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
sxirsb_match(struct device * parent,void * match,void * aux)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
sxirsb_attach(struct device * parent,struct device * self,void * aux)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
sxirsb_activate(struct device * self,int act)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
sxirsb_init(struct sxirsb_softc * sc)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
sxirsb_rta(uint16_t da)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
sxirsb_do_trans(struct sxirsb_softc * sc)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
rsb_read_1(void * cookie,uint8_t rta,uint8_t addr)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
rsb_read_2(void * cookie,uint8_t rta,uint8_t addr)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
rsb_write_1(void * cookie,uint8_t rta,uint8_t addr,uint8_t data)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
rsb_write_2(void * cookie,uint8_t rta,uint8_t addr,uint16_t data)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
rsb_print(void * aux,const char * pnp)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