1 /* $NetBSD: isp1763hc_rr.c,v 1.1 2026/10/11 17:31:04 rkujawa Exp $ */ 2 3 /*- 4 * Copyright (c) 2026 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Radoslaw Kujawa. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 /* 33 * Individual Computers RapidRoad USB, on clockport. 34 */ 35 36 #include <sys/cdefs.h> 37 __KERNEL_RCSID(0, "$NetBSD: isp1763hc_rr.c,v 1.1 2026/10/11 17:31:04 rkujawa Exp $"); 38 39 #include <sys/param.h> 40 #include <sys/bus.h> 41 #include <sys/device.h> 42 #include <sys/systm.h> 43 44 #include <dev/ic/isp1763reg.h> 45 #include <dev/ic/isp1763var.h> 46 47 #include <amiga/clockport/clockportvar.h> 48 #include <amiga/clockport/isp1763hc_rrreg.h> 49 50 struct isp1763hc_rr_softc { 51 struct isp1763hc_softc sc_isp; 52 bus_space_tag_t sc_iot; 53 bus_space_handle_t sc_ioh; 54 void *sc_ih; 55 void (*sc_intr_disestablish)(void *); 56 int sc_bank; 57 bool sc_attached; 58 }; 59 60 #define RR_SOFTC(sc) ((struct isp1763hc_rr_softc *)(sc)) 61 62 static int isp1763hc_rr_match(device_t, cfdata_t, void *); 63 static void isp1763hc_rr_attach(device_t, device_t, void *); 64 static int isp1763hc_rr_detach(device_t, int); 65 static bool isp1763hc_rr_identify(bus_space_tag_t, bus_space_handle_t); 66 static bool isp1763hc_rr_shutdown(device_t, int); 67 static int isp1763hc_rr_intr(void *); 68 69 static void isp1763hc_rr_bank(struct isp1763hc_rr_softc *, bus_size_t); 70 static uint8_t isp1763hc_rr_rd1(struct isp1763hc_softc *, bus_size_t); 71 static void isp1763hc_rr_wr1(struct isp1763hc_softc *, bus_size_t, 72 uint8_t); 73 static uint16_t isp1763hc_rr_rd2(struct isp1763hc_softc *, bus_size_t); 74 static void isp1763hc_rr_wr2(struct isp1763hc_softc *, bus_size_t, 75 uint16_t); 76 static void isp1763hc_rr_memrd(struct isp1763hc_softc *, uint16_t, void *, 77 size_t); 78 static void isp1763hc_rr_memwr(struct isp1763hc_softc *, uint16_t, 79 const void *, size_t); 80 static void isp1763hc_rr_intr_enable(struct isp1763hc_softc *, bool); 81 82 CFATTACH_DECL3_NEW(isp1763hc_rr, sizeof(struct isp1763hc_rr_softc), 83 isp1763hc_rr_match, isp1763hc_rr_attach, isp1763hc_rr_detach, 84 isp1763hc_activate, NULL, isp1763hc_childdet, DVF_DETACH_SHUTDOWN); 85 86 static bool 87 isp1763hc_rr_identify(bus_space_tag_t iot, bus_space_handle_t ioh) 88 { 89 uint32_t id; 90 int i; 91 92 (void)bus_space_read_1(iot, ioh, RR_WINDOW); 93 delay(10000); 94 95 if ((bus_space_read_1(iot, ioh, RR_BANKA) & RR_BANKA_ID_MASK) != 96 RR_BANKA_ID) 97 return false; 98 99 /* Select bank 0x0e, which holds the id. */ 100 (void)bus_space_read_1(iot, ioh, RR_BANKB); 101 102 id = 0; 103 for (i = 0; i < 4; i++) 104 id |= (uint32_t)bus_space_read_1(iot, ioh, RR_WINDOW + i) << 105 (8 * i); 106 107 return id == ISP1763_CHIPID_VALUE; 108 } 109 110 static int 111 isp1763hc_rr_match(device_t parent, cfdata_t cf, void *aux) 112 { 113 struct clockport_attach_args *cpa = aux; 114 bus_space_handle_t ioh; 115 bool found; 116 117 if (bus_space_map(cpa->cp_iot, 0, RR_NREGS, 0, &ioh) != 0) 118 return 0; 119 120 if ((cf->cf_flags & RR_FLAGS_FORCE) != 0 && 121 (bus_space_read_1(cpa->cp_iot, ioh, RR_STATUS) & 122 RR_STATUS_GATE) != 0) 123 bus_space_write_1(cpa->cp_iot, ioh, RR_CTRL, 0); 124 125 found = isp1763hc_rr_identify(cpa->cp_iot, ioh); 126 bus_space_unmap(cpa->cp_iot, ioh, RR_NREGS); 127 128 return found ? 1 : 0; 129 } 130 131 static void 132 isp1763hc_rr_attach(device_t parent, device_t self, void *aux) 133 { 134 struct isp1763hc_rr_softc *rsc = device_private(self); 135 struct isp1763hc_softc *sc = &rsc->sc_isp; 136 struct clockport_attach_args *cpa = aux; 137 138 aprint_naive("\n"); 139 aprint_normal(": RapidRoad USB\n"); 140 141 rsc->sc_iot = cpa->cp_iot; 142 if (bus_space_map(rsc->sc_iot, 0, RR_NREGS, 0, &rsc->sc_ioh) != 0) { 143 aprint_error_dev(self, "can't map registers\n"); 144 return; 145 } 146 bus_space_write_1(rsc->sc_iot, rsc->sc_ioh, RR_CTRL, 0); 147 rsc->sc_bank = -1; 148 149 sc->sc_dev = self; 150 sc->sc_hwmode = ISP1763_HWMODE_BUS8; 151 sc->sc_rd1 = isp1763hc_rr_rd1; 152 sc->sc_wr1 = isp1763hc_rr_wr1; 153 sc->sc_rd2 = isp1763hc_rr_rd2; 154 sc->sc_wr2 = isp1763hc_rr_wr2; 155 sc->sc_memrd = isp1763hc_rr_memrd; 156 sc->sc_memwr = isp1763hc_rr_memwr; 157 sc->sc_intr_enable = isp1763hc_rr_intr_enable; 158 159 rsc->sc_intr_disestablish = cpa->cp_intr_disestablish; 160 rsc->sc_ih = cpa->cp_intr_establish(isp1763hc_rr_intr, rsc); 161 162 if (isp1763hc_attach(sc) != 0) { 163 rsc->sc_intr_disestablish(rsc->sc_ih); 164 bus_space_unmap(rsc->sc_iot, rsc->sc_ioh, RR_NREGS); 165 return; 166 } 167 rsc->sc_attached = true; 168 169 if (!pmf_device_register1(self, NULL, NULL, isp1763hc_rr_shutdown)) 170 aprint_error_dev(self, "couldn't establish power handler\n"); 171 } 172 173 static int 174 isp1763hc_rr_detach(device_t self, int flags) 175 { 176 struct isp1763hc_rr_softc *rsc = device_private(self); 177 int error; 178 179 if (!rsc->sc_attached) 180 return 0; 181 182 error = isp1763hc_detach(&rsc->sc_isp, flags); 183 if (error != 0) 184 return error; 185 186 pmf_device_deregister(self); 187 rsc->sc_intr_disestablish(rsc->sc_ih); 188 bus_space_unmap(rsc->sc_iot, rsc->sc_ioh, RR_NREGS); 189 rsc->sc_attached = false; 190 191 return 0; 192 } 193 194 static bool 195 isp1763hc_rr_shutdown(device_t self, int howto) 196 { 197 struct isp1763hc_rr_softc *rsc = device_private(self); 198 199 isp1763hc_shutdown(&rsc->sc_isp); 200 201 return true; 202 } 203 204 static int 205 isp1763hc_rr_intr(void *arg) 206 { 207 struct isp1763hc_rr_softc *rsc = arg; 208 uint8_t status; 209 210 status = bus_space_read_1(rsc->sc_iot, rsc->sc_ioh, RR_STATUS); 211 if ((status & (RR_STATUS_GATE | RR_STATUS_INT)) != 212 (RR_STATUS_GATE | RR_STATUS_INT)) 213 return 0; 214 215 bus_space_write_1(rsc->sc_iot, rsc->sc_ioh, RR_CTRL, 0); 216 isp1763hc_intr(&rsc->sc_isp); 217 218 return 1; 219 } 220 221 static void 222 isp1763hc_rr_bank(struct isp1763hc_rr_softc *rsc, bus_size_t reg) 223 { 224 225 if (rsc->sc_bank == RR_BANK(reg)) 226 return; 227 228 rsc->sc_bank = RR_BANK(reg); 229 bus_space_write_1(rsc->sc_iot, rsc->sc_ioh, RR_BANKA, rsc->sc_bank); 230 } 231 232 static uint8_t 233 isp1763hc_rr_rd1(struct isp1763hc_softc *sc, bus_size_t reg) 234 { 235 struct isp1763hc_rr_softc *rsc = RR_SOFTC(sc); 236 237 isp1763hc_rr_bank(rsc, reg); 238 239 return bus_space_read_1(rsc->sc_iot, rsc->sc_ioh, RR_SLOT(reg)); 240 } 241 242 static void 243 isp1763hc_rr_wr1(struct isp1763hc_softc *sc, bus_size_t reg, uint8_t val) 244 { 245 struct isp1763hc_rr_softc *rsc = RR_SOFTC(sc); 246 247 isp1763hc_rr_bank(rsc, reg); 248 bus_space_write_1(rsc->sc_iot, rsc->sc_ioh, RR_SLOT(reg), val); 249 } 250 251 static uint16_t 252 isp1763hc_rr_rd2(struct isp1763hc_softc *sc, bus_size_t reg) 253 { 254 struct isp1763hc_rr_softc *rsc = RR_SOFTC(sc); 255 uint16_t hi; 256 257 isp1763hc_rr_bank(rsc, reg); 258 hi = bus_space_read_1(rsc->sc_iot, rsc->sc_ioh, RR_SLOT(reg) + 1); 259 260 return (hi << 8) | 261 bus_space_read_1(rsc->sc_iot, rsc->sc_ioh, RR_SLOT(reg)); 262 } 263 264 static void 265 isp1763hc_rr_wr2(struct isp1763hc_softc *sc, bus_size_t reg, uint16_t val) 266 { 267 struct isp1763hc_rr_softc *rsc = RR_SOFTC(sc); 268 269 isp1763hc_rr_bank(rsc, reg); 270 bus_space_write_1(rsc->sc_iot, rsc->sc_ioh, RR_SLOT(reg), val & 0xff); 271 bus_space_write_1(rsc->sc_iot, rsc->sc_ioh, RR_SLOT(reg) + 1, 272 val >> 8); 273 } 274 275 static void 276 isp1763hc_rr_memrd(struct isp1763hc_softc *sc, uint16_t addr, void *buf, 277 size_t len) 278 { 279 struct isp1763hc_rr_softc *rsc = RR_SOFTC(sc); 280 281 bus_space_write_1(rsc->sc_iot, rsc->sc_ioh, RR_MEMLO, addr & 0xff); 282 bus_space_write_1(rsc->sc_iot, rsc->sc_ioh, RR_MEMHI, addr >> 8); 283 bus_space_read_multi_1(rsc->sc_iot, rsc->sc_ioh, RR_DATA, buf, len); 284 } 285 286 static void 287 isp1763hc_rr_memwr(struct isp1763hc_softc *sc, uint16_t addr, 288 const void *buf, size_t len) 289 { 290 struct isp1763hc_rr_softc *rsc = RR_SOFTC(sc); 291 292 bus_space_write_1(rsc->sc_iot, rsc->sc_ioh, RR_MEMLO, addr & 0xff); 293 bus_space_write_1(rsc->sc_iot, rsc->sc_ioh, RR_MEMHI, addr >> 8); 294 bus_space_write_multi_1(rsc->sc_iot, rsc->sc_ioh, RR_DATA, buf, len); 295 } 296 297 static void 298 isp1763hc_rr_intr_enable(struct isp1763hc_softc *sc, bool on) 299 { 300 struct isp1763hc_rr_softc *rsc = RR_SOFTC(sc); 301 302 bus_space_write_1(rsc->sc_iot, rsc->sc_ioh, RR_CTRL, 303 on ? RR_CTRL_GATE : 0); 304 } 305