1 /* $OpenBSD: sxirsb.c,v 1.3 2019/08/29 11:51:48 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 0x7e3e00 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_addr; 75 }; 76 77 int sxirsb_match(struct device *, void *, void *); 78 void sxirsb_attach(struct device *, struct device *, void *); 79 80 struct cfattach sxirsb_ca = { 81 sizeof(struct sxirsb_softc), sxirsb_match, sxirsb_attach 82 }; 83 84 struct cfdriver sxirsb_cd = { 85 NULL, "sxirsb", DV_DULL 86 }; 87 88 uint8_t sxirsb_rta(uint16_t); 89 90 int 91 sxirsb_match(struct device *parent, void *match, void *aux) 92 { 93 struct fdt_attach_args *faa = aux; 94 95 return OF_is_compatible(faa->fa_node, "allwinner,sun8i-a23-rsb"); 96 } 97 98 void 99 sxirsb_attach(struct device *parent, struct device *self, void *aux) 100 { 101 struct sxirsb_softc *sc = (struct sxirsb_softc *)self; 102 struct fdt_attach_args *faa = aux; 103 uint32_t freq, parent_freq, div, odly; 104 struct rsb_attach_args ra; 105 char name[32]; 106 uint32_t reg; 107 uint8_t rta; 108 int node; 109 int timo; 110 111 if (faa->fa_nreg < 1) { 112 printf(": no registers\n"); 113 return; 114 } 115 116 sc->sc_iot = faa->fa_iot; 117 if (bus_space_map(sc->sc_iot, faa->fa_reg[0].addr, 118 faa->fa_reg[0].size, 0, &sc->sc_ioh)) { 119 printf(": can't map registers\n"); 120 return; 121 } 122 123 pinctrl_byname(faa->fa_node, "default"); 124 125 clock_enable_all(faa->fa_node); 126 reset_deassert_all(faa->fa_node); 127 128 HWRITE4(sc, RSB_CTRL, RSB_CTRL_SOFT_RESET); 129 for (timo = 1000; timo > 0; timo--) { 130 if ((HREAD4(sc, RSB_CTRL) & RSB_CTRL_SOFT_RESET) == 0) 131 break; 132 delay(100); 133 } 134 if (timo == 0) { 135 printf(": reset failed\n"); 136 return; 137 } 138 139 freq = OF_getpropint(faa->fa_node, "clock-frequency", 3000000); 140 parent_freq = clock_get_frequency_idx(faa->fa_node, 0); 141 div = parent_freq / freq / 2; 142 if (div == 0) 143 div = 1; 144 if (div > (RSB_CCR_CK_DIV_MAX + 1)) 145 div = (RSB_CCR_CK_DIV_MAX + 1); 146 odly = div >> 1; 147 if (odly == 0) 148 odly = 1; 149 if (odly > RSB_CCR_CD_ODLY_MAX) 150 odly = RSB_CCR_CD_ODLY_MAX; 151 HWRITE4(sc, RSB_CCR, (odly << RSB_CCR_CD_ODLY_SHIFT) | 152 ((div - 1) << RSB_CCR_CK_DIV_SHIFT)); 153 154 HWRITE4(sc, RSB_DMCR, RSB_DMCR_DEVICE_MODE_START | 155 RSB_DMCR_DEVICE_MODE_DATA); 156 for (timo = 1000; timo > 0; timo--) { 157 if ((HREAD4(sc, RSB_DMCR) & RSB_DMCR_DEVICE_MODE_START) == 0) 158 break; 159 delay(100); 160 } 161 if (timo == 0) { 162 printf(": mode switch failed\n"); 163 return; 164 } 165 166 for (node = OF_child(faa->fa_node); node; node = OF_peer(node)) { 167 reg = OF_getpropint(node, "reg", 0); 168 if (reg == 0) 169 continue; 170 171 rta = sxirsb_rta(reg); 172 HWRITE4(sc, RSB_CMD, SRTA); 173 HWRITE4(sc, RSB_DAR, (rta << 16 | reg)); 174 175 HSET4(sc, RSB_CTRL, RSB_CTRL_START_TRANS); 176 for (timo = 1000; timo > 0; timo--) { 177 if ((HREAD4(sc, RSB_CTRL) & RSB_CTRL_START_TRANS) == 0) 178 break; 179 delay(10); 180 } 181 if (timo == 0) { 182 printf(": SRTA failed for device 0x%03x\n", reg); 183 return; 184 } 185 } 186 187 printf("\n"); 188 189 for (node = OF_child(faa->fa_node); node; node = OF_peer(node)) { 190 reg = OF_getpropint(node, "reg", 0); 191 if (reg == 0) 192 continue; 193 194 memset(name, 0, sizeof(name)); 195 if (OF_getprop(node, "compatible", name, sizeof(name)) == -1) 196 continue; 197 if (name[0] == '\0') 198 continue; 199 200 memset(&ra, 0, sizeof(ra)); 201 ra.ra_cookie = sc; 202 ra.ra_da = reg; 203 ra.ra_rta = sxirsb_rta(reg); 204 ra.ra_name = name; 205 ra.ra_node = node; 206 config_found(self, &ra, rsb_print); 207 } 208 } 209 210 /* 211 * Use a fixed device address to run-time address mapping. This keeps 212 * things simple and matches what Linux does. 213 */ 214 215 struct rsb_addr_map { 216 uint16_t da; 217 uint8_t rta; 218 }; 219 220 struct rsb_addr_map rsb_addr_map[] = { 221 { 0x3a3, 0x2d }, 222 { 0x745, 0x3a }, 223 { 0xe89, 0x4e } 224 }; 225 226 uint8_t 227 sxirsb_rta(uint16_t da) 228 { 229 int i; 230 231 for (i = 0; i < nitems(rsb_addr_map); i++) { 232 if (rsb_addr_map[i].da == da) 233 return rsb_addr_map[i].rta; 234 } 235 236 return 0; 237 } 238 239 int 240 sxirsb_do_trans(struct sxirsb_softc *sc) 241 { 242 uint16_t stat; 243 int timo; 244 245 HSET4(sc, RSB_CTRL, RSB_CTRL_START_TRANS); 246 for (timo = 1000; timo > 0; timo--) { 247 if ((HREAD4(sc, RSB_CTRL) & RSB_CTRL_START_TRANS) == 0) 248 break; 249 delay(10); 250 } 251 stat = HREAD4(sc, RSB_STAT); 252 HWRITE4(sc, RSB_STAT, stat); 253 if (stat != RSB_STAT_TRANS_OVER) 254 return EIO; 255 if (timo == 0) 256 return ETIMEDOUT; 257 return 0; 258 } 259 260 uint8_t 261 rsb_read_1(void *cookie, uint8_t rta, uint8_t addr) 262 { 263 struct sxirsb_softc *sc = cookie; 264 265 HWRITE4(sc, RSB_CMD, RD8); 266 HWRITE4(sc, RSB_DAR, rta << 16); 267 HWRITE4(sc, RSB_AR, addr); 268 269 if (sxirsb_do_trans(sc)) { 270 printf("%s: RD8 failed for run-time address 0x%02x\n", 271 sc->sc_dev.dv_xname, rta); 272 return 0xff; 273 } 274 275 return HREAD4(sc, RSB_DATA); 276 } 277 278 uint16_t 279 rsb_read_2(void *cookie, uint8_t rta, uint8_t addr) 280 { 281 struct sxirsb_softc *sc = cookie; 282 283 HWRITE4(sc, RSB_CMD, RD16); 284 HWRITE4(sc, RSB_DAR, rta << 16); 285 HWRITE4(sc, RSB_AR, addr); 286 287 if (sxirsb_do_trans(sc)) { 288 printf("%s: RD16 failed for run-time address 0x%02x\n", 289 sc->sc_dev.dv_xname, rta); 290 return 0xff; 291 } 292 293 return HREAD4(sc, RSB_DATA); 294 } 295 296 void 297 rsb_write_1(void *cookie, uint8_t rta, uint8_t addr, uint8_t data) 298 { 299 struct sxirsb_softc *sc = cookie; 300 301 HWRITE4(sc, RSB_CMD, WR8); 302 HWRITE4(sc, RSB_DAR, rta << 16); 303 HWRITE4(sc, RSB_AR, addr); 304 HWRITE4(sc, RSB_DATA, data); 305 306 if (sxirsb_do_trans(sc)) { 307 printf("%s: WR8 failed for run-time address 0x%02x\n", 308 sc->sc_dev.dv_xname, rta); 309 return; 310 } 311 } 312 313 void 314 rsb_write_2(void *cookie, uint8_t rta, uint8_t addr, uint16_t data) 315 { 316 struct sxirsb_softc *sc = cookie; 317 318 HWRITE4(sc, RSB_CMD, WR16); 319 HWRITE4(sc, RSB_DAR, rta << 16); 320 HWRITE4(sc, RSB_AR, addr); 321 HWRITE4(sc, RSB_DATA, data); 322 323 if (sxirsb_do_trans(sc)) { 324 printf("%s: WR16 failed for run-time address 0x%02x\n", 325 sc->sc_dev.dv_xname, rta); 326 return; 327 } 328 } 329 330 int 331 rsb_print(void *aux, const char *pnp) 332 { 333 struct rsb_attach_args *ra = aux; 334 335 if (pnp != NULL) 336 printf("\"%s\" at %s", ra->ra_name, pnp); 337 printf(" addr 0x%x", ra->ra_da); 338 339 return (UNCONF); 340 } 341