xref: /openbsd/sys/dev/fdt/sxirsb.c (revision 2b3827ce)
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