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