1 /* $OpenBSD: sxirsb.c,v 1.6 2022/07/09 20:52:46 kettenis Exp $ */ 2 /* 3 * Copyright (c) 2017 Mark Kettenis <kettenis@openbsd.org> 4 * 5 * Permission to use, copy, modify, and distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18 #include <sys/param.h> 19 #include <sys/systm.h> 20 #include <sys/device.h> 21 22 #include <machine/bus.h> 23 #include <machine/fdt.h> 24 25 #include <dev/fdt/rsbvar.h> 26 27 #include <dev/ofw/openfirm.h> 28 #include <dev/ofw/ofw_clock.h> 29 #include <dev/ofw/ofw_pinctrl.h> 30 #include <dev/ofw/fdt.h> 31 32 #define RSB_CTRL 0x0000 33 #define RSB_CTRL_START_TRANS (1 << 7) 34 #define RSB_CTRL_ABORT_TRANS (1 << 6) 35 #define RSB_CTRL_GLOBAL_INT_ENB (1 << 1) 36 #define RSB_CTRL_SOFT_RESET (1 << 0) 37 #define RSB_CCR 0x0004 38 #define RSB_CCR_CD_ODLY_SHIFT 8 39 #define RSB_CCR_CD_ODLY_MAX 0x7 40 #define RSB_CCR_CK_DIV_SHIFT 0 41 #define RSB_CCR_CK_DIV_MAX 0xff 42 #define RSB_STAT 0x000c 43 #define RSB_STAT_TRANS_OVER (1 << 0) 44 #define RSB_AR 0x0010 45 #define RSB_DATA 0x001c 46 #define RSB_DMCR 0x0028 47 #define RSB_DMCR_DEVICE_MODE_START (1U << 31) 48 #define RSB_DMCR_DEVICE_MODE_DATA 0x7c3e00 49 #define RSB_CMD 0x002c 50 #define RSB_DAR 0x0030 51 52 #define SRTA 0xe8 53 #define RD8 0x8b 54 #define RD16 0x9c 55 #define RD32 0xa6 56 #define WR8 0x4e 57 #define WR16 0x59 58 #define WR32 0x63 59 60 #define HREAD4(sc, reg) \ 61 (bus_space_read_4((sc)->sc_iot, (sc)->sc_ioh, (reg))) 62 #define HWRITE4(sc, reg, val) \ 63 bus_space_write_4((sc)->sc_iot, (sc)->sc_ioh, (reg), (val)) 64 #define HSET4(sc, reg, bits) \ 65 HWRITE4((sc), (reg), HREAD4((sc), (reg)) | (bits)) 66 #define HCLR4(sc, reg, bits) \ 67 HWRITE4((sc), (reg), HREAD4((sc), (reg)) & ~(bits)) 68 69 struct sxirsb_softc { 70 struct device sc_dev; 71 bus_space_tag_t sc_iot; 72 bus_space_handle_t sc_ioh; 73 74 int sc_node; 75 int sc_addr; 76 }; 77 78 int sxirsb_match(struct device *, void *, void *); 79 void sxirsb_attach(struct device *, struct device *, void *); 80 int sxirsb_activate(struct device *, int); 81 82 const struct cfattach sxirsb_ca = { 83 sizeof(struct sxirsb_softc), sxirsb_match, sxirsb_attach, 84 NULL, sxirsb_activate 85 }; 86 87 struct cfdriver sxirsb_cd = { 88 NULL, "sxirsb", DV_DULL 89 }; 90 91 int sxirsb_init(struct sxirsb_softc *); 92 uint8_t sxirsb_rta(uint16_t); 93 94 int 95 sxirsb_match(struct device *parent, void *match, void *aux) 96 { 97 struct fdt_attach_args *faa = aux; 98 99 return OF_is_compatible(faa->fa_node, "allwinner,sun8i-a23-rsb"); 100 } 101 102 void 103 sxirsb_attach(struct device *parent, struct device *self, void *aux) 104 { 105 struct sxirsb_softc *sc = (struct sxirsb_softc *)self; 106 struct fdt_attach_args *faa = aux; 107 struct rsb_attach_args ra; 108 char name[32]; 109 uint32_t reg; 110 int node; 111 112 if (faa->fa_nreg < 1) { 113 printf(": no registers\n"); 114 return; 115 } 116 117 sc->sc_node = faa->fa_node; 118 sc->sc_iot = faa->fa_iot; 119 if (bus_space_map(sc->sc_iot, faa->fa_reg[0].addr, 120 faa->fa_reg[0].size, 0, &sc->sc_ioh)) { 121 printf(": can't map registers\n"); 122 return; 123 } 124 125 printf("\n"); 126 127 if (sxirsb_init(sc)) 128 return; 129 130 for (node = OF_child(faa->fa_node); node; node = OF_peer(node)) { 131 reg = OF_getpropint(node, "reg", 0); 132 if (reg == 0) 133 continue; 134 135 memset(name, 0, sizeof(name)); 136 if (OF_getprop(node, "compatible", name, sizeof(name)) == -1) 137 continue; 138 if (name[0] == '\0') 139 continue; 140 141 memset(&ra, 0, sizeof(ra)); 142 ra.ra_cookie = sc; 143 ra.ra_da = reg; 144 ra.ra_rta = sxirsb_rta(reg); 145 ra.ra_name = name; 146 ra.ra_node = node; 147 config_found(self, &ra, rsb_print); 148 } 149 } 150 151 int 152 sxirsb_activate(struct device *self, int act) 153 { 154 struct sxirsb_softc *sc = (struct sxirsb_softc *)self; 155 int error = 0; 156 157 switch (act) { 158 case DVACT_RESUME: 159 error = sxirsb_init(sc); 160 if (error) 161 return error; 162 error = config_activate_children(self, act); 163 break; 164 default: 165 error = config_activate_children(self, act); 166 break; 167 } 168 169 return error; 170 } 171 172 int 173 sxirsb_init(struct sxirsb_softc *sc) 174 { 175 uint32_t freq, parent_freq, div, odly; 176 uint32_t reg; 177 uint8_t rta; 178 int node; 179 int timo; 180 181 pinctrl_byname(sc->sc_node, "default"); 182 183 clock_enable_all(sc->sc_node); 184 reset_deassert_all(sc->sc_node); 185 186 HWRITE4(sc, RSB_CTRL, RSB_CTRL_SOFT_RESET); 187 for (timo = 1000; timo > 0; timo--) { 188 if ((HREAD4(sc, RSB_CTRL) & RSB_CTRL_SOFT_RESET) == 0) 189 break; 190 delay(100); 191 } 192 if (timo == 0) { 193 printf("%s: reset failed\n", sc->sc_dev.dv_xname); 194 return EIO; 195 } 196 197 freq = OF_getpropint(sc->sc_node, "clock-frequency", 3000000); 198 parent_freq = clock_get_frequency_idx(sc->sc_node, 0); 199 div = parent_freq / freq / 2; 200 if (div == 0) 201 div = 1; 202 if (div > (RSB_CCR_CK_DIV_MAX + 1)) 203 div = (RSB_CCR_CK_DIV_MAX + 1); 204 odly = div >> 1; 205 if (odly == 0) 206 odly = 1; 207 if (odly > RSB_CCR_CD_ODLY_MAX) 208 odly = RSB_CCR_CD_ODLY_MAX; 209 HWRITE4(sc, RSB_CCR, (odly << RSB_CCR_CD_ODLY_SHIFT) | 210 ((div - 1) << RSB_CCR_CK_DIV_SHIFT)); 211 212 HWRITE4(sc, RSB_DMCR, RSB_DMCR_DEVICE_MODE_START | 213 RSB_DMCR_DEVICE_MODE_DATA); 214 for (timo = 1000; timo > 0; timo--) { 215 if ((HREAD4(sc, RSB_DMCR) & RSB_DMCR_DEVICE_MODE_START) == 0) 216 break; 217 delay(100); 218 } 219 if (timo == 0) { 220 printf("%s: mode switch failed\n", sc->sc_dev.dv_xname); 221 return EIO; 222 } 223 224 for (node = OF_child(sc->sc_node); node; node = OF_peer(node)) { 225 reg = OF_getpropint(node, "reg", 0); 226 if (reg == 0) 227 continue; 228 229 rta = sxirsb_rta(reg); 230 HWRITE4(sc, RSB_CMD, SRTA); 231 HWRITE4(sc, RSB_DAR, (rta << 16 | reg)); 232 233 HSET4(sc, RSB_CTRL, RSB_CTRL_START_TRANS); 234 for (timo = 1000; timo > 0; timo--) { 235 if ((HREAD4(sc, RSB_CTRL) & RSB_CTRL_START_TRANS) == 0) 236 break; 237 delay(10); 238 } 239 if (timo == 0) { 240 printf("%s: SRTA failed for device 0x%03x\n", 241 sc->sc_dev.dv_xname, reg); 242 return EIO; 243 } 244 } 245 246 return 0; 247 } 248 249 /* 250 * Use a fixed device address to run-time address mapping. This keeps 251 * things simple and matches what Linux does. 252 */ 253 254 struct rsb_addr_map { 255 uint16_t da; 256 uint8_t rta; 257 }; 258 259 struct rsb_addr_map rsb_addr_map[] = { 260 { 0x3a3, 0x2d }, 261 { 0x745, 0x3a }, 262 { 0xe89, 0x4e } 263 }; 264 265 uint8_t 266 sxirsb_rta(uint16_t da) 267 { 268 int i; 269 270 for (i = 0; i < nitems(rsb_addr_map); i++) { 271 if (rsb_addr_map[i].da == da) 272 return rsb_addr_map[i].rta; 273 } 274 275 return 0; 276 } 277 278 int 279 sxirsb_do_trans(struct sxirsb_softc *sc) 280 { 281 uint16_t stat; 282 int timo; 283 284 HSET4(sc, RSB_CTRL, RSB_CTRL_START_TRANS); 285 for (timo = 1000; timo > 0; timo--) { 286 if ((HREAD4(sc, RSB_CTRL) & RSB_CTRL_START_TRANS) == 0) 287 break; 288 delay(10); 289 } 290 stat = HREAD4(sc, RSB_STAT); 291 HWRITE4(sc, RSB_STAT, stat); 292 if (stat != RSB_STAT_TRANS_OVER) 293 return EIO; 294 if (timo == 0) 295 return ETIMEDOUT; 296 return 0; 297 } 298 299 uint8_t 300 rsb_read_1(void *cookie, uint8_t rta, uint8_t addr) 301 { 302 struct sxirsb_softc *sc = cookie; 303 304 HWRITE4(sc, RSB_CMD, RD8); 305 HWRITE4(sc, RSB_DAR, rta << 16); 306 HWRITE4(sc, RSB_AR, addr); 307 308 if (sxirsb_do_trans(sc)) { 309 printf("%s: RD8 failed for run-time address 0x%02x\n", 310 sc->sc_dev.dv_xname, rta); 311 return 0xff; 312 } 313 314 return HREAD4(sc, RSB_DATA); 315 } 316 317 uint16_t 318 rsb_read_2(void *cookie, uint8_t rta, uint8_t addr) 319 { 320 struct sxirsb_softc *sc = cookie; 321 322 HWRITE4(sc, RSB_CMD, RD16); 323 HWRITE4(sc, RSB_DAR, rta << 16); 324 HWRITE4(sc, RSB_AR, addr); 325 326 if (sxirsb_do_trans(sc)) { 327 printf("%s: RD16 failed for run-time address 0x%02x\n", 328 sc->sc_dev.dv_xname, rta); 329 return 0xff; 330 } 331 332 return HREAD4(sc, RSB_DATA); 333 } 334 335 void 336 rsb_write_1(void *cookie, uint8_t rta, uint8_t addr, uint8_t data) 337 { 338 struct sxirsb_softc *sc = cookie; 339 340 HWRITE4(sc, RSB_CMD, WR8); 341 HWRITE4(sc, RSB_DAR, rta << 16); 342 HWRITE4(sc, RSB_AR, addr); 343 HWRITE4(sc, RSB_DATA, data); 344 345 if (sxirsb_do_trans(sc)) { 346 printf("%s: WR8 failed for run-time address 0x%02x\n", 347 sc->sc_dev.dv_xname, rta); 348 return; 349 } 350 } 351 352 void 353 rsb_write_2(void *cookie, uint8_t rta, uint8_t addr, uint16_t data) 354 { 355 struct sxirsb_softc *sc = cookie; 356 357 HWRITE4(sc, RSB_CMD, WR16); 358 HWRITE4(sc, RSB_DAR, rta << 16); 359 HWRITE4(sc, RSB_AR, addr); 360 HWRITE4(sc, RSB_DATA, data); 361 362 if (sxirsb_do_trans(sc)) { 363 printf("%s: WR16 failed for run-time address 0x%02x\n", 364 sc->sc_dev.dv_xname, rta); 365 return; 366 } 367 } 368 369 int 370 rsb_print(void *aux, const char *pnp) 371 { 372 struct rsb_attach_args *ra = aux; 373 374 if (pnp != NULL) 375 printf("\"%s\" at %s", ra->ra_name, pnp); 376 printf(" addr 0x%x", ra->ra_da); 377 378 return (UNCONF); 379 } 380