xref: /openbsd/sys/dev/fdt/mviic.c (revision 097a140d)
1 /* $OpenBSD: mviic.c,v 1.3 2021/03/11 09:15:25 patrick Exp $ */
2 /*
3  * Copyright (c) 2019 Patrick Wildt <patrick@blueri.se>
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/device.h>
20 #include <sys/kernel.h>
21 #include <sys/systm.h>
22 
23 #include <dev/i2c/i2cvar.h>
24 
25 #include <machine/bus.h>
26 #include <machine/fdt.h>
27 
28 #include <dev/ofw/openfirm.h>
29 #include <dev/ofw/ofw_clock.h>
30 #include <dev/ofw/ofw_pinctrl.h>
31 #include <dev/ofw/ofw_misc.h>
32 #include <dev/ofw/fdt.h>
33 
34 /* registers */
35 #define IDBR		0x04
36 #define ICR		0x08
37 #define  ICR_START		(1 << 0)
38 #define  ICR_STOP		(1 << 1)
39 #define  ICR_NAK		(1 << 2)
40 #define  ICR_TX_BYTE		(1 << 3)
41 #define  ICR_MSTA		(1 << 5)
42 #define  ICR_ENABLE		(1 << 6)
43 #define  ICR_GCD		(1 << 7)
44 #define  ICR_RESET		(1 << 14)
45 #define  ICR_MODE_MASK		(3 << 16)
46 #define  ICR_MODE_FAST		(1 << 16)
47 #define ISR		0x0c
48 #define  ISR_INIT		0x7ff
49 #define  ISR_NAK		(1 << 1)
50 #define  ISR_UB			(1 << 2)
51 #define  ISR_IBB		(1 << 3)
52 #define  ISR_TXE		(1 << 6)
53 #define  ISR_RXF		(1 << 7)
54 
55 struct mviic_softc {
56 	struct device		sc_dev;
57 	bus_space_tag_t		sc_iot;
58 	bus_space_handle_t	sc_ioh;
59 	bus_size_t		sc_ios;
60 	void			*sc_ih;
61 	int			sc_node;
62 	int			sc_fastmode;
63 
64 	struct rwlock		sc_buslock;
65 	struct i2c_controller	sc_ic;
66 	struct i2c_bus		sc_ib;
67 };
68 
69 int mviic_match(struct device *, void *, void *);
70 void mviic_attach(struct device *, struct device *, void *);
71 int mviic_detach(struct device *, int);
72 int mviic_wait_state(struct mviic_softc *, uint32_t, uint32_t);
73 
74 int mviic_i2c_acquire_bus(void *, int);
75 void mviic_i2c_release_bus(void *, int);
76 int mviic_send_start(void *, int);
77 int mviic_send_stop(void *, int);
78 int mviic_initiate_xfer(void *, i2c_addr_t, int);
79 int mviic_read_byte(void *, uint8_t *, int);
80 int mviic_write_byte(void *, uint8_t, int);
81 
82 void mviic_bus_scan(struct device *, struct i2cbus_attach_args *, void *);
83 
84 #define HREAD4(sc, reg)							\
85 	(bus_space_read_4((sc)->sc_iot, (sc)->sc_ioh, (reg)))
86 #define HWRITE4(sc, reg, val)						\
87 	bus_space_write_4((sc)->sc_iot, (sc)->sc_ioh, (reg), (val))
88 #define HSET4(sc, reg, bits)						\
89 	HWRITE4((sc), (reg), HREAD4((sc), (reg)) | (bits))
90 #define HCLR4(sc, reg, bits)						\
91 	HWRITE4((sc), (reg), HREAD4((sc), (reg)) & ~(bits))
92 
93 struct cfattach mviic_ca = {
94 	sizeof(struct mviic_softc), mviic_match, mviic_attach, mviic_detach
95 };
96 
97 struct cfdriver mviic_cd = {
98 	NULL, "mviic", DV_DULL
99 };
100 
101 int
102 mviic_match(struct device *parent, void *match, void *aux)
103 {
104 	struct fdt_attach_args *faa = aux;
105 
106 	return OF_is_compatible(faa->fa_node, "marvell,armada-3700-i2c");
107 }
108 
109 void
110 mviic_attach(struct device *parent, struct device *self, void *aux)
111 {
112 	struct mviic_softc *sc = (struct mviic_softc *)self;
113 	struct fdt_attach_args *faa = aux;
114 	struct i2cbus_attach_args iba;
115 
116 	if (faa->fa_nreg < 1) {
117 		printf(": no registers\n");
118 		return;
119 	}
120 
121 	sc->sc_iot = faa->fa_iot;
122 	sc->sc_ios = faa->fa_reg[0].size;
123 	sc->sc_node = faa->fa_node;
124 	if (bus_space_map(sc->sc_iot, faa->fa_reg[0].addr,
125 	    faa->fa_reg[0].size, 0, &sc->sc_ioh)) {
126 		printf(": can't map registers\n");
127 		return;
128 	}
129 
130 	printf("\n");
131 
132 	clock_enable(faa->fa_node, NULL);
133 	pinctrl_byname(faa->fa_node, "default");
134 
135 	sc->sc_fastmode = (OF_getproplen(sc->sc_node,
136 	    "mrvl,i2c-fast-mode") == 0);
137 
138 	/* reset */
139 	HWRITE4(sc, ICR, ICR_RESET);
140 	HWRITE4(sc, ISR, ISR_INIT);
141 	HCLR4(sc, ICR, ICR_RESET);
142 
143 	/* set defaults */
144 	HWRITE4(sc, ICR, ICR_MSTA | ICR_GCD);
145 	if (sc->sc_fastmode)
146 		HSET4(sc, ICR, ICR_MODE_FAST);
147 
148 	/* enable */
149 	HSET4(sc, ICR, ICR_ENABLE);
150 	delay(100);
151 
152 	rw_init(&sc->sc_buslock, sc->sc_dev.dv_xname);
153 
154 	sc->sc_ic.ic_cookie = sc;
155 	sc->sc_ic.ic_acquire_bus = mviic_i2c_acquire_bus;
156 	sc->sc_ic.ic_release_bus = mviic_i2c_release_bus;
157 	sc->sc_ic.ic_exec = NULL;
158 	sc->sc_ic.ic_send_start = mviic_send_start;
159 	sc->sc_ic.ic_send_stop = mviic_send_stop;
160 	sc->sc_ic.ic_initiate_xfer = mviic_initiate_xfer;
161 	sc->sc_ic.ic_read_byte = mviic_read_byte;
162 	sc->sc_ic.ic_write_byte = mviic_write_byte;
163 
164 	bzero(&iba, sizeof iba);
165 	iba.iba_name = "iic";
166 	iba.iba_tag = &sc->sc_ic;
167 	iba.iba_bus_scan = mviic_bus_scan;
168 	iba.iba_bus_scan_arg = &sc->sc_node;
169 	config_found(&sc->sc_dev, &iba, iicbus_print);
170 
171 	sc->sc_ib.ib_node = sc->sc_node;
172 	sc->sc_ib.ib_ic = &sc->sc_ic;
173 	i2c_register(&sc->sc_ib);
174 }
175 
176 int
177 mviic_wait_state(struct mviic_softc *sc, uint32_t mask, uint32_t value)
178 {
179 	uint32_t state;
180 	int timeout;
181 
182 	for (timeout = 1000; timeout > 0; timeout--) {
183 		if (((state = HREAD4(sc, ISR)) & mask) == value)
184 			return 0;
185 		delay(10);
186 	}
187 	return ETIMEDOUT;
188 }
189 
190 int
191 mviic_i2c_acquire_bus(void *cookie, int flags)
192 {
193 	struct mviic_softc *sc = cookie;
194 
195 	rw_enter(&sc->sc_buslock, RW_WRITE);
196 
197 	clock_enable(sc->sc_node, NULL);
198 	delay(50);
199 
200 	return 0;
201 }
202 
203 void
204 mviic_i2c_release_bus(void *cookie, int flags)
205 {
206 	struct mviic_softc *sc = cookie;
207 
208 	rw_exit(&sc->sc_buslock);
209 }
210 
211 int
212 mviic_send_start(void *v, int flags)
213 {
214 	struct mviic_softc *sc = v;
215 
216 	HSET4(sc, ICR, ICR_START);
217 	return 0;
218 }
219 
220 int
221 mviic_send_stop(void *v, int flags)
222 {
223 	struct mviic_softc *sc = v;
224 
225 	HSET4(sc, ICR, ICR_STOP);
226 	return 0;
227 }
228 
229 int
230 mviic_initiate_xfer(void *v, i2c_addr_t addr, int flags)
231 {
232 	struct mviic_softc *sc = v;
233 
234 	if (mviic_wait_state(sc, ISR_IBB, 0))
235 		return EIO;
236 
237 	HCLR4(sc, ICR, ICR_START);
238 	HCLR4(sc, ICR, ICR_STOP);
239 	if (flags & I2C_F_READ)
240 		HWRITE4(sc, IDBR, addr << 1 | 1);
241 	else
242 		HWRITE4(sc, IDBR, addr << 1);
243 	HSET4(sc, ICR, ICR_START);
244 
245 	HSET4(sc, ICR, ICR_TX_BYTE);
246 	if (mviic_wait_state(sc, ISR_TXE, ISR_TXE))
247 		return EIO;
248 	HWRITE4(sc, ISR, ISR_TXE);
249 	if (HREAD4(sc, ISR) & ISR_NAK)
250 		return EIO;
251 
252 	return 0;
253 }
254 
255 int
256 mviic_read_byte(void *v, uint8_t *valp, int flags)
257 {
258 	struct mviic_softc *sc = v;
259 
260 	if (mviic_wait_state(sc, ISR_IBB, 0))
261 		return EIO;
262 
263 	HCLR4(sc, ICR, ICR_START);
264 	HCLR4(sc, ICR, ICR_STOP);
265 	HCLR4(sc, ICR, ICR_NAK);
266 	if ((flags & (I2C_F_LAST | I2C_F_STOP)) == (I2C_F_LAST | I2C_F_STOP))
267 		HSET4(sc, ICR, ICR_STOP);
268 	if (flags & I2C_F_LAST)
269 		HSET4(sc, ICR, ICR_NAK);
270 
271 	HSET4(sc, ICR, ICR_TX_BYTE);
272 	if (mviic_wait_state(sc, ISR_RXF, ISR_RXF))
273 		return EIO;
274 	HWRITE4(sc, ISR, ISR_RXF);
275 	*valp = HREAD4(sc, IDBR);
276 
277 	return 0;
278 }
279 
280 int
281 mviic_write_byte(void *v, uint8_t val, int flags)
282 {
283 	struct mviic_softc *sc = v;
284 
285 	HCLR4(sc, ICR, ICR_START);
286 	HCLR4(sc, ICR, ICR_STOP);
287 	HWRITE4(sc, IDBR, val);
288 	if (flags & I2C_F_STOP)
289 		HSET4(sc, ICR, ICR_STOP);
290 
291 	HSET4(sc, ICR, ICR_TX_BYTE);
292 	if (mviic_wait_state(sc, ISR_TXE, ISR_TXE))
293 		return EIO;
294 	HWRITE4(sc, ISR, ISR_TXE);
295 	if (HREAD4(sc, ISR) & ISR_NAK)
296 		return EIO;
297 
298 	return 0;
299 }
300 
301 int
302 mviic_detach(struct device *self, int flags)
303 {
304 	struct mviic_softc *sc = (struct mviic_softc *)self;
305 
306 	HCLR4(sc, ICR, ICR_ENABLE);
307 	bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_ios);
308 	return 0;
309 }
310 
311 void
312 mviic_bus_scan(struct device *self, struct i2cbus_attach_args *iba, void *aux)
313 {
314 	int iba_node = *(int *)aux;
315 	extern int iic_print(void *, const char *);
316 	struct i2c_attach_args ia;
317 	char name[32], status[32];
318 	uint32_t reg[1];
319 	int node;
320 
321 	for (node = OF_child(iba_node); node; node = OF_peer(node)) {
322 		memset(name, 0, sizeof(name));
323 		memset(status, 0, sizeof(status));
324 		memset(reg, 0, sizeof(reg));
325 
326 		if (OF_getprop(node, "compatible", name, sizeof(name)) == -1)
327 			continue;
328 		if (name[0] == '\0')
329 			continue;
330 
331 		if (OF_getprop(node, "status", status, sizeof(status)) > 0 &&
332 		    strcmp(status, "disabled") == 0)
333 			continue;
334 
335 		if (OF_getprop(node, "reg", &reg, sizeof(reg)) != sizeof(reg))
336 			continue;
337 
338 		memset(&ia, 0, sizeof(ia));
339 		ia.ia_tag = iba->iba_tag;
340 		ia.ia_addr = bemtoh32(&reg[0]);
341 		ia.ia_name = name;
342 		ia.ia_cookie = &node;
343 
344 		config_found(self, &ia, iic_print);
345 	}
346 }
347