xref: /openbsd/sys/arch/riscv64/dev/mpfiic.c (revision 5dea098c)
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
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
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
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
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
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
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
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
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
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
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", &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(&reg[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
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