1 /* $OpenBSD: mpfiic.c,v 1.1 2022/02/16 13:07:36 visa Exp $ */
2
3 /*
4 * Copyright (c) 2022 Visa Hankala
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19 /*
20 * Driver for PolarFire SoC MSS I2C controller.
21 */
22
23 #include <sys/param.h>
24 #include <sys/systm.h>
25 #include <sys/device.h>
26 #include <sys/malloc.h>
27
28 #include <machine/bus.h>
29 #include <machine/fdt.h>
30
31 #define _I2C_PRIVATE
32 #include <dev/i2c/i2cvar.h>
33
34 #include <dev/ofw/fdt.h>
35 #include <dev/ofw/openfirm.h>
36 #include <dev/ofw/ofw_clock.h>
37 #include <dev/ofw/ofw_misc.h>
38
39 #define I2C_CTRL 0x0000
40 #define I2C_CTRL_CR2 (1 << 7)
41 #define I2C_CTRL_ENS1 (1 << 6)
42 #define I2C_CTRL_STA (1 << 5)
43 #define I2C_CTRL_STO (1 << 4)
44 #define I2C_CTRL_SI (1 << 3)
45 #define I2C_CTRL_AA (1 << 2)
46 #define I2C_CTRL_CR1 (1 << 1)
47 #define I2C_CTRL_CR0 (1 << 0)
48 #define I2C_STATUS 0x0004
49 #define I2C_DATA 0x0008
50 #define I2C_SLAVE0ADR 0x000c
51 #define I2C_SMBUS 0x0010
52 #define I2C_FREQ 0x0014
53 #define I2C_GLITCHREG 0x0018
54 #define I2C_SLAVE1ADR 0x001c
55
56 #define I2C_STATUS_START 0x08
57 #define I2C_STATUS_RESTART 0x10
58 #define I2C_STATUS_SLAW_ACK 0x18
59 #define I2C_STATUS_DATAW_ACK 0x28
60 #define I2C_STATUS_LOSTARB 0x38
61 #define I2C_STATUS_SLAR_ACK 0x40
62 #define I2C_STATUS_DATAR_ACK 0x50
63 #define I2C_STATUS_DATAR_NACK 0x58
64 #define I2C_STATUS_IDLE 0xf8
65
66 struct mpfiic_softc {
67 struct device sc_dev;
68 bus_space_tag_t sc_iot;
69 bus_space_handle_t sc_ioh;
70 int sc_node;
71
72 struct i2c_bus sc_i2c_bus;
73 struct i2c_controller sc_i2c_tag;
74 struct rwlock sc_i2c_lock;
75
76 uint32_t sc_bus_freq; /* in Hz */
77 uint8_t sc_ctrl;
78 uint8_t sc_start_sent;
79 };
80
81 #define HREAD4(sc, reg) \
82 (bus_space_read_4((sc)->sc_iot, (sc)->sc_ioh, (reg)))
83 #define HWRITE4(sc, reg, val) \
84 bus_space_write_4((sc)->sc_iot, (sc)->sc_ioh, (reg), (val))
85
86 int mpfiic_match(struct device *, void *, void*);
87 void mpfiic_attach(struct device *, struct device *, void *);
88
89 int mpfiic_i2c_acquire_bus(void *, int);
90 void mpfiic_i2c_release_bus(void *, int);
91 int mpfiic_i2c_send_start(void *, int);
92 int mpfiic_i2c_send_stop(void *, int);
93 int mpfiic_i2c_initiate_xfer(void *, i2c_addr_t, int);
94 int mpfiic_i2c_read_byte(void *, uint8_t *, int);
95 int mpfiic_i2c_write_byte(void *, uint8_t, int);
96 void mpfiic_i2c_scan(struct device *, struct i2cbus_attach_args *, void *);
97
98 int mpfiic_wait(struct mpfiic_softc *, uint8_t);
99
100 const struct cfattach mpfiic_ca = {
101 sizeof(struct mpfiic_softc), mpfiic_match, mpfiic_attach
102 };
103
104 struct cfdriver mpfiic_cd = {
105 NULL, "mpfiic", DV_DULL
106 };
107
108 static struct {
109 uint32_t div;
110 uint32_t cr;
111 } mpfiic_clk_divs[] = {
112 #ifdef notused
113 /* BCLK */
114 { 8, I2C_CTRL_CR2 | I2C_CTRL_CR1 | I2C_CTRL_CR0 },
115 #endif
116 /* PCLK */
117 { 60, I2C_CTRL_CR2 | I2C_CTRL_CR1 },
118 { 120, I2C_CTRL_CR2 | I2C_CTRL_CR0 },
119 { 160, I2C_CTRL_CR1 | I2C_CTRL_CR0 },
120 { 192, I2C_CTRL_CR1 },
121 { 224, I2C_CTRL_CR0 },
122 { 256, 0 },
123 { 960, I2C_CTRL_CR2 },
124 };
125
126 int
mpfiic_match(struct device * parent,void * match,void * aux)127 mpfiic_match(struct device *parent, void *match, void *aux)
128 {
129 struct fdt_attach_args *faa = aux;
130
131 if (faa->fa_nreg < 1)
132 return 0;
133 return OF_is_compatible(faa->fa_node, "microchip,mpfs-i2c");
134 }
135
136 void
mpfiic_attach(struct device * parent,struct device * self,void * aux)137 mpfiic_attach(struct device *parent, struct device *self, void *aux)
138 {
139 struct i2cbus_attach_args iba;
140 struct fdt_attach_args *faa = aux;
141 struct mpfiic_softc *sc = (struct mpfiic_softc *)self;
142 uint32_t i, bus_freq, clock_freq;
143
144 sc->sc_node = faa->fa_node;
145 sc->sc_iot = faa->fa_iot;
146
147 clock_freq = clock_get_frequency(sc->sc_node, NULL);
148 bus_freq = OF_getpropint(sc->sc_node, "clock-frequency", 100000);
149
150 /* Determine clock divider, assumes PCLK. */
151 for (i = 0; i < nitems(mpfiic_clk_divs) - 1; i++) {
152 if (clock_freq / mpfiic_clk_divs[i].div <= bus_freq)
153 break;
154 }
155 sc->sc_bus_freq = clock_freq / mpfiic_clk_divs[i].div;
156 sc->sc_ctrl = mpfiic_clk_divs[i].cr | I2C_CTRL_ENS1;
157
158 if (sc->sc_bus_freq == 0) {
159 printf(": invalid bus frequency\n");
160 return;
161 }
162
163 if (bus_space_map(sc->sc_iot, faa->fa_reg[0].addr, faa->fa_reg[0].size,
164 0, &sc->sc_ioh) != 0) {
165 printf(": can't map registers\n");
166 return;
167 }
168
169 clock_enable_all(sc->sc_node);
170
171 /* Initialize the device. */
172 HWRITE4(sc, I2C_CTRL, sc->sc_ctrl);
173 HWRITE4(sc, I2C_CTRL, 0);
174
175 /* Disable slave address comparison. */
176 HWRITE4(sc, I2C_SLAVE0ADR, 0);
177 HWRITE4(sc, I2C_SLAVE1ADR, 0);
178
179 /* Disable SMBus logic, operate in standard I2C mode. */
180 HWRITE4(sc, I2C_SMBUS, 0);
181
182 printf("\n");
183
184 rw_init(&sc->sc_i2c_lock, "iiclk");
185 sc->sc_i2c_tag.ic_cookie = sc;
186 sc->sc_i2c_tag.ic_acquire_bus = mpfiic_i2c_acquire_bus;
187 sc->sc_i2c_tag.ic_release_bus = mpfiic_i2c_release_bus;
188 sc->sc_i2c_tag.ic_send_start = mpfiic_i2c_send_start;
189 sc->sc_i2c_tag.ic_send_stop = mpfiic_i2c_send_stop;
190 sc->sc_i2c_tag.ic_initiate_xfer = mpfiic_i2c_initiate_xfer;
191 sc->sc_i2c_tag.ic_read_byte = mpfiic_i2c_read_byte;
192 sc->sc_i2c_tag.ic_write_byte = mpfiic_i2c_write_byte;
193
194 memset(&iba, 0, sizeof(iba));
195 iba.iba_name = "iic";
196 iba.iba_tag = &sc->sc_i2c_tag;
197 iba.iba_bus_scan = mpfiic_i2c_scan;
198 iba.iba_bus_scan_arg = &sc->sc_node;
199 config_found(self, &iba, iicbus_print);
200
201 sc->sc_i2c_bus.ib_node = faa->fa_node;
202 sc->sc_i2c_bus.ib_ic = &sc->sc_i2c_tag;
203 i2c_register(&sc->sc_i2c_bus);
204 }
205
206 int
mpfiic_i2c_acquire_bus(void * arg,int flags)207 mpfiic_i2c_acquire_bus(void *arg, int flags)
208 {
209 struct mpfiic_softc *sc = arg;
210
211 if (cold || (flags & I2C_F_POLL))
212 return 0;
213
214 return rw_enter(&sc->sc_i2c_lock, RW_WRITE | RW_INTR);
215 }
216
217 void
mpfiic_i2c_release_bus(void * arg,int flags)218 mpfiic_i2c_release_bus(void *arg, int flags)
219 {
220 struct mpfiic_softc *sc = arg;
221
222 if (cold || (flags & I2C_F_POLL))
223 return;
224
225 rw_exit(&sc->sc_i2c_lock);
226 }
227
228 int
mpfiic_i2c_send_start(void * cookie,int flags)229 mpfiic_i2c_send_start(void *cookie, int flags)
230 {
231 struct mpfiic_softc *sc = cookie;
232 int error;
233 uint8_t nstatus;
234
235 HWRITE4(sc, I2C_CTRL, sc->sc_ctrl | I2C_CTRL_STA);
236
237 if (sc->sc_start_sent)
238 nstatus = I2C_STATUS_RESTART;
239 else
240 nstatus = I2C_STATUS_START;
241 error = mpfiic_wait(sc, nstatus);
242 if (error != 0)
243 return error;
244
245 sc->sc_start_sent = 1;
246
247 return 0;
248 }
249
250 int
mpfiic_i2c_send_stop(void * cookie,int flags)251 mpfiic_i2c_send_stop(void *cookie, int flags)
252 {
253 struct mpfiic_softc *sc = cookie;
254
255 sc->sc_start_sent = 0;
256
257 HWRITE4(sc, I2C_CTRL, sc->sc_ctrl | I2C_CTRL_STO);
258
259 /* Let a few bus clock cycles pass. */
260 delay(4 * 1000000 / sc->sc_bus_freq);
261
262 /* Disable the device. This resets the state machine. */
263 HWRITE4(sc, I2C_CTRL, 0);
264
265 return 0;
266 }
267
268 int
mpfiic_i2c_initiate_xfer(void * cookie,i2c_addr_t addr,int flags)269 mpfiic_i2c_initiate_xfer(void *cookie, i2c_addr_t addr, int flags)
270 {
271 struct mpfiic_softc *sc = cookie;
272 int error;
273 uint8_t mode, nstatus;
274
275 if (addr >= 0x80)
276 return EINVAL;
277
278 error = mpfiic_i2c_send_start(sc, flags);
279 if (error != 0)
280 return error;
281
282 if (flags & I2C_F_READ) {
283 mode = 0x01;
284 nstatus = I2C_STATUS_SLAR_ACK;
285 } else {
286 mode = 0x00;
287 nstatus = I2C_STATUS_SLAW_ACK;
288 }
289
290 HWRITE4(sc, I2C_DATA, (addr << 1) | mode);
291 HWRITE4(sc, I2C_CTRL, sc->sc_ctrl);
292
293 return mpfiic_wait(sc, nstatus);
294 }
295
296 int
mpfiic_i2c_read_byte(void * cookie,uint8_t * datap,int flags)297 mpfiic_i2c_read_byte(void *cookie, uint8_t *datap, int flags)
298 {
299 struct mpfiic_softc *sc = cookie;
300 int error;
301 uint8_t ack = 0, nstatus;
302
303 if ((flags & I2C_F_LAST) == 0)
304 ack = I2C_CTRL_AA;
305 HWRITE4(sc, I2C_CTRL, sc->sc_ctrl | ack);
306
307 if (flags & I2C_F_LAST)
308 nstatus = I2C_STATUS_DATAR_NACK;
309 else
310 nstatus = I2C_STATUS_DATAR_ACK;
311 error = mpfiic_wait(sc, nstatus);
312 if (error != 0)
313 return error;
314
315 *datap = HREAD4(sc, I2C_DATA);
316
317 if (flags & I2C_F_STOP)
318 error = mpfiic_i2c_send_stop(sc, flags);
319
320 return error;
321 }
322
323 int
mpfiic_i2c_write_byte(void * cookie,uint8_t data,int flags)324 mpfiic_i2c_write_byte(void *cookie, uint8_t data, int flags)
325 {
326 struct mpfiic_softc *sc = cookie;
327 int error;
328
329 HWRITE4(sc, I2C_DATA, data);
330 HWRITE4(sc, I2C_CTRL, sc->sc_ctrl);
331
332 error = mpfiic_wait(sc, I2C_STATUS_DATAW_ACK);
333 if (error != 0)
334 return error;
335
336 if (flags & I2C_F_STOP)
337 error = mpfiic_i2c_send_stop(sc, flags);
338
339 return error;
340 }
341
342 void
mpfiic_i2c_scan(struct device * self,struct i2cbus_attach_args * iba,void * arg)343 mpfiic_i2c_scan(struct device *self, struct i2cbus_attach_args *iba, void *arg)
344 {
345 struct i2c_attach_args ia;
346 char status[32];
347 char *compat;
348 uint32_t reg[1];
349 int iba_node = *(int *)arg;
350 int len, node;
351
352 for (node = OF_child(iba_node); node != 0; node = OF_peer(node)) {
353 memset(status, 0, sizeof(status));
354 if (OF_getprop(node, "status", status, sizeof(status)) > 0 &&
355 strcmp(status, "disabled") == 0)
356 continue;
357
358 memset(reg, 0, sizeof(reg));
359 if (OF_getprop(node, "reg", ®, sizeof(reg)) != sizeof(reg))
360 continue;
361
362 len = OF_getproplen(node, "compatible");
363 if (len <= 0)
364 continue;
365
366 compat = malloc(len, M_TEMP, M_WAITOK);
367 OF_getprop(node, "compatible", compat, len);
368
369 memset(&ia, 0, sizeof(ia));
370 ia.ia_tag = iba->iba_tag;
371 ia.ia_addr = bemtoh32(®[0]);
372 ia.ia_name = compat;
373 ia.ia_namelen = len;
374 ia.ia_cookie = &node;
375 config_found(self, &ia, iic_print);
376
377 free(compat, M_TEMP, len);
378 }
379 }
380
381 int
mpfiic_wait(struct mpfiic_softc * sc,uint8_t nstatus)382 mpfiic_wait(struct mpfiic_softc *sc, uint8_t nstatus)
383 {
384 int timeout;
385 uint8_t ctrl, status;
386
387 for (timeout = 100000; timeout > 0; timeout--) {
388 ctrl = HREAD4(sc, I2C_CTRL);
389 if (ctrl & I2C_CTRL_SI)
390 break;
391 delay(1);
392 }
393 if (timeout == 0)
394 return ETIMEDOUT;
395
396 status = HREAD4(sc, I2C_STATUS);
397 if (status != nstatus)
398 return EIO;
399
400 return 0;
401 }
402