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