1 /* $OpenBSD: mviic.c,v 1.4 2021/10/24 17:52:26 mpi 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 const 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
mviic_match(struct device * parent,void * match,void * aux)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
mviic_attach(struct device * parent,struct device * self,void * aux)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
mviic_wait_state(struct mviic_softc * sc,uint32_t mask,uint32_t value)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
mviic_i2c_acquire_bus(void * cookie,int flags)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
mviic_i2c_release_bus(void * cookie,int flags)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
mviic_send_start(void * v,int flags)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
mviic_send_stop(void * v,int flags)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
mviic_initiate_xfer(void * v,i2c_addr_t addr,int flags)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
mviic_read_byte(void * v,uint8_t * valp,int flags)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
mviic_write_byte(void * v,uint8_t val,int flags)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
mviic_detach(struct device * self,int flags)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
mviic_bus_scan(struct device * self,struct i2cbus_attach_args * iba,void * aux)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", ®, 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(®[0]);
341 ia.ia_name = name;
342 ia.ia_cookie = &node;
343
344 config_found(self, &ia, iic_print);
345 }
346 }
347