xref: /openbsd/sys/arch/armv7/exynos/exiic.c (revision 5af055cd)
1 /*
2  * Copyright (c) 2013 Patrick Wildt <patrick@blueri.se>
3  *
4  * Permission to use, copy, modify, and distribute this software for any
5  * purpose with or without fee is hereby granted, provided that the above
6  * copyright notice and this permission notice appear in all copies.
7  *
8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15  */
16 
17 #include "fdt.h"
18 
19 #include <sys/param.h>
20 #include <sys/device.h>
21 #include <sys/kernel.h>
22 #include <sys/kthread.h>
23 #include <sys/malloc.h>
24 #include <sys/systm.h>
25 #include <machine/bus.h>
26 #if NFDT > 0
27 #include <machine/fdt.h>
28 #endif
29 
30 #include <armv7/armv7/armv7var.h>
31 #include <armv7/exynos/exgpiovar.h>
32 #include <armv7/exynos/exiicvar.h>
33 #include <armv7/exynos/exclockvar.h>
34 
35 /* registers */
36 #define I2C_CON				0x00	/* control register */
37 #define I2C_STAT			0x04	/* control/status register */
38 #define I2C_ADD				0x08	/* address register */
39 #define I2C_DS				0x0C	/* transmit/receive data shift register */
40 #define I2C_LC				0x10	/* multi-master line control register */
41 
42 /* bits and bytes */
43 #define I2C_CON_TXCLKVAL_MASK		(0xf << 0) /* tx clock = i2cclk / (i2ccon[3:0] + 1) */
44 #define I2C_CON_INTPENDING		(0x1 << 4) /* 0 = no interrupt pending/clear, 1 = pending */
45 #define I2C_CON_TXRX_INT		(0x1 << 5) /* enable/disable */
46 #define I2C_CON_TXCLKSRC_16		(0x0 << 6) /* i2clk = fpclk/16 */
47 #define I2C_CON_TXCLKSRC_512		(0x1 << 6) /* i2clk = fpclk/512 */
48 #define I2C_CON_ACK			(0x1 << 7)
49 #define I2C_STAT_LAST_RVCD_BIT		(0x1 << 0) /* last received bit 0 => ack, 1 => no ack */
50 #define I2C_STAT_ADDR_ZERO_FLAG		(0x1 << 1) /* 0 => start/stop cond. detected, 1 => received slave addr 0xb */
51 #define I2C_STAT_ADDR_SLAVE_ZERO_FLAG	(0x1 << 2) /* 0 => start/stop cond. detected, 1 => received slave addr matches i2cadd */
52 #define I2C_STAT_ARBITRATION		(0x1 << 3) /* 0 => successul, 1 => failed */
53 #define I2C_STAT_SERIAL_OUTPUT		(0x1 << 4) /* 0 => disable tx/rx, 1 => enable tx/rx */
54 #define I2C_STAT_BUSY_SIGNAL		(0x1 << 5) /* 0 => not busy / stop signal generation, 1 => busy / start signal generation */
55 #define I2C_STAT_MODE_SEL_SLAVE_RX	(0x0 << 6) /* slave receive mode */
56 #define I2C_STAT_MODE_SEL_SLAVE_TX	(0x1 << 6) /* slave transmit mode */
57 #define I2C_STAT_MODE_SEL_MASTER_RX	(0x2 << 6) /* master receive mode */
58 #define I2C_STAT_MODE_SEL_MASTER_TX	(0x3 << 6) /* master transmit */
59 #define I2C_ADD_SLAVE_ADDR(x)		(((x) & 0x7f) << 1)
60 #define I2C_DS_DATA_SHIFT(x)		(((x) & 0xff) << 0)
61 
62 #define I2C_ACK				0
63 #define I2C_NACK			1
64 #define I2C_TIMEOUT			2
65 
66 struct exiic_softc {
67 	struct device		sc_dev;
68 	bus_space_tag_t		sc_iot;
69 	bus_space_handle_t	sc_ioh;
70 	bus_size_t		sc_ios;
71 	void			*sc_ih;
72 	int			unit;
73 
74 	struct rwlock		sc_buslock;
75 	struct i2c_controller	i2c_tag;
76 
77 	uint16_t		frequency;
78 	uint16_t		intr_status;
79 };
80 
81 int exiic_match(struct device *parent, void *v, void *aux);
82 void exiic_attach(struct device *, struct device *, void *);
83 int exiic_detach(struct device *, int);
84 void exiic_bus_scan(struct device *, struct i2cbus_attach_args *, void *);
85 void exiic_setspeed(struct exiic_softc *, int);
86 int exiic_intr(void *);
87 int exiic_wait_intr(struct exiic_softc *, int, int);
88 int exiic_wait_state(struct exiic_softc *, uint32_t, uint32_t, uint32_t);
89 int exiic_start(struct exiic_softc *, int, int, void *, int);
90 
91 void exiic_xfer_start(struct exiic_softc *);
92 int exiic_xfer_wait(struct exiic_softc *);
93 int exiic_i2c_acquire_bus(void *, int);
94 void exiic_i2c_release_bus(void *, int);
95 int exiic_i2c_exec(void *, i2c_op_t, i2c_addr_t, const void *, size_t,
96     void *, size_t, int);
97 
98 #define HREAD4(sc, reg)							\
99 	(bus_space_read_4((sc)->sc_iot, (sc)->sc_ioh, (reg)))
100 #define HWRITE4(sc, reg, val)						\
101 	bus_space_write_4((sc)->sc_iot, (sc)->sc_ioh, (reg), (val))
102 #define HSET4(sc, reg, bits)						\
103 	HWRITE4((sc), (reg), HREAD4((sc), (reg)) | (bits))
104 #define HCLR4(sc, reg, bits)						\
105 	HWRITE4((sc), (reg), HREAD4((sc), (reg)) & ~(bits))
106 
107 
108 struct cfattach exiic_ca = {
109 	sizeof(struct exiic_softc), NULL, exiic_attach, exiic_detach
110 };
111 struct cfattach exiic_fdt_ca = {
112 	sizeof(struct exiic_softc), exiic_match, exiic_attach, exiic_detach
113 };
114 
115 struct cfdriver exiic_cd = {
116 	NULL, "exiic", DV_DULL
117 };
118 
119 int
120 exiic_match(struct device *parent, void *v, void *aux)
121 {
122 #if NFDT > 0
123 	struct armv7_attach_args *aa = aux;
124 
125 	if (fdt_node_compatible("samsung,s3c2440-i2c", aa->aa_node))
126 		return 1;
127 #endif
128 
129 	return 0;
130 }
131 
132 void
133 exiic_attach(struct device *parent, struct device *self, void *args)
134 {
135 	struct exiic_softc *sc = (struct exiic_softc *)self;
136 	struct armv7_attach_args *aa = args;
137 	struct armv7mem mem;
138 
139 	sc->sc_iot = aa->aa_iot;
140 #if NFDT > 0
141 	if (aa->aa_node) {
142 		struct fdt_memory fdtmem;
143 		static int unit = 0;
144 
145 		sc->unit = unit++;
146 		if (fdt_get_memory_address(aa->aa_node, 0, &fdtmem))
147 			panic("%s: could not extract memory data from FDT",
148 			    __func__);
149 		mem.addr = fdtmem.addr;
150 		mem.size = fdtmem.size;
151 	} else
152 #endif
153 	{
154 		mem.addr = aa->aa_dev->mem[0].addr;
155 		mem.size = aa->aa_dev->mem[0].size;
156 		sc->unit = aa->aa_dev->unit;
157 	}
158 	if (bus_space_map(sc->sc_iot, mem.addr, mem.size, 0, &sc->sc_ioh))
159 		panic("%s: bus_space_map failed!", __func__);
160 	sc->sc_ios = mem.size;
161 
162 #if 0
163 	sc->sc_ih = arm_intr_establish(aa->aa_dev->irq[0], IPL_BIO,
164 	    exiic_intr, sc, sc->sc_dev.dv_xname);
165 #endif
166 
167 	printf("\n");
168 
169 	rw_init(&sc->sc_buslock, sc->sc_dev.dv_xname);
170 
171 	struct i2cbus_attach_args iba;
172 
173 	sc->i2c_tag.ic_cookie = sc;
174 	sc->i2c_tag.ic_acquire_bus = exiic_i2c_acquire_bus;
175 	sc->i2c_tag.ic_release_bus = exiic_i2c_release_bus;
176 	sc->i2c_tag.ic_exec = exiic_i2c_exec;
177 
178 	bzero(&iba, sizeof iba);
179 	iba.iba_name = "iic";
180 	iba.iba_tag = &sc->i2c_tag;
181 	iba.iba_bus_scan = exiic_bus_scan;
182 	iba.iba_bus_scan_arg = sc;
183 	config_found(&sc->sc_dev, &iba, NULL);
184 }
185 
186 void
187 exiic_bus_scan(struct device *self, struct i2cbus_attach_args *iba, void *arg)
188 {
189 	struct exiic_softc *sc = (struct exiic_softc *)arg;
190 	struct i2c_attach_args ia;
191 
192 	/* XXX: We currently only attach cros-ec on I2C4.  We'll use FDT later. */
193 	if (sc->unit != 4)
194 		return;
195 
196 	char *name = "crosec";
197 	int addr = 0x1e;
198 
199 	memset(&ia, 0, sizeof(ia));
200 	ia.ia_tag = iba->iba_tag;
201 	ia.ia_addr = addr;
202 	ia.ia_size = 1;
203 	ia.ia_name = name;
204 	config_found(self, &ia, iicbus_print);
205 
206 	name = "tps65090";
207 	addr = 0x48;
208 
209 	memset(&ia, 0, sizeof(ia));
210 	ia.ia_tag = iba->iba_tag;
211 	ia.ia_addr = addr;
212 	ia.ia_size = 1;
213 	ia.ia_name = name;
214 	config_found(self, &ia, iicbus_print);
215 }
216 
217 void
218 exiic_setspeed(struct exiic_softc *sc, int speed)
219 {
220 	if (!sc->frequency) {
221 		uint32_t freq, div = 0, pres = 16;
222 		freq = exclock_get_i2cclk();
223 
224 		/* calculate prescaler and divisor values */
225 		if ((freq / pres / (16 + 1)) > speed)
226 			/* set prescaler to 512 */
227 			pres = 512;
228 
229 		while ((freq / pres / (div + 1)) > speed)
230 			div++;
231 
232 		/* set prescaler, divisor according to freq, also set ACKGEN, IRQ */
233 		sc->frequency = (div & 0x0F) | 0xA0 | ((pres == 512) ? 0x40 : 0);
234 	}
235 
236 	HWRITE4(sc, I2C_CON, sc->frequency);
237 }
238 
239 #if 0
240 int
241 exiic_intr(void *arg)
242 {
243 	struct exiic_softc *sc = arg;
244 	u_int16_t status;
245 	int rc = 0;
246 
247 	status = HREAD4(sc, I2C_CON);
248 
249 	if (ISSET(status, I2C_CON_INTPENDING)) {
250 		/* we do not acknowledge the interrupt here */
251 		rc = 1;
252 
253 		sc->intr_status |= status;
254 		wakeup(&sc->intr_status);
255 	}
256 
257 	return (rc);
258 }
259 
260 int
261 exiic_wait_intr(struct exiic_softc *sc, int mask, int timo)
262 {
263 	int status;
264 	int s;
265 
266 	s = splbio();
267 
268 	status = sc->intr_status & mask;
269 	while (status == 0) {
270 		if (tsleep(&sc->intr_status, PWAIT, "hcintr", timo)
271 		    == EWOULDBLOCK) {
272 			break;
273 		}
274 		status = sc->intr_status & mask;
275 	}
276 	status = sc->intr_status & mask;
277 	sc->intr_status &= ~status;
278 
279 	splx(s);
280 	return status;
281 }
282 #endif
283 
284 int
285 exiic_wait_state(struct exiic_softc *sc, uint32_t reg, uint32_t mask, uint32_t value)
286 {
287 	uint32_t state;
288 	int timeout;
289 	state = HREAD4(sc, reg);
290 	for (timeout = 1000; timeout > 0; timeout--) {
291 		if (((state = HREAD4(sc, reg)) & mask) == value)
292 			return 0;
293 		delay(1000);
294 	}
295 	return ETIMEDOUT;
296 }
297 
298 int
299 exiic_i2c_acquire_bus(void *cookie, int flags)
300 {
301 	struct exiic_softc *sc = cookie;
302 	int ret = rw_enter(&sc->sc_buslock, RW_WRITE);
303 
304 	if (!ret) {
305 		/* set speed to 100 Kbps */
306 		exiic_setspeed(sc, 100);
307 
308 		/* STOP */
309 		HWRITE4(sc, I2C_STAT, 0);
310 		HWRITE4(sc, I2C_ADD, 0);
311 		HWRITE4(sc, I2C_STAT, I2C_STAT_MODE_SEL_MASTER_TX
312 				    | I2C_STAT_SERIAL_OUTPUT);
313 	}
314 
315 	return ret;
316 }
317 
318 void
319 exiic_i2c_release_bus(void *cookie, int flags)
320 {
321 	struct exiic_softc *sc = cookie;
322 
323 	(void) rw_exit(&sc->sc_buslock);
324 }
325 
326 int
327 exiic_i2c_exec(void *cookie, i2c_op_t op, i2c_addr_t _addr,
328     const void *cmdbuf, size_t cmdlen, void *databuf, size_t datalen, int flags)
329 {
330 	struct exiic_softc *sc = cookie;
331 	uint32_t ret = 0;
332 	u_int8_t addr = 0;
333 	int i = 0;
334 
335 	addr = (_addr & 0x7f) << 1;
336 
337 	/* clock gating */
338 	//exccm_enable_i2c(sc->unit);
339 
340 	if (exiic_wait_state(sc, I2C_STAT, I2C_STAT_BUSY_SIGNAL, 0)) {
341 		printf("%s: busy\n", __func__);
342 		return (EIO);
343 	}
344 
345 	/* acknowledge generation */
346 	HSET4(sc, I2C_CON, I2C_CON_ACK);
347 
348 	/* Send the slave-address */
349 	HWRITE4(sc, I2C_DS, addr);
350 	if (!I2C_OP_READ_P(op) || (cmdbuf && cmdlen))
351 		HWRITE4(sc, I2C_STAT, I2C_STAT_MODE_SEL_MASTER_TX
352 				    | I2C_STAT_SERIAL_OUTPUT
353 				    | I2C_STAT_BUSY_SIGNAL);
354 	else
355 		HWRITE4(sc, I2C_STAT, I2C_STAT_MODE_SEL_MASTER_RX
356 				    | I2C_STAT_SERIAL_OUTPUT
357 				    | I2C_STAT_BUSY_SIGNAL);
358 
359 	ret = exiic_xfer_wait(sc);
360 	if (ret != I2C_ACK)
361 		goto fail;
362 
363 	/* transmit commands */
364 	if (cmdbuf && cmdlen) {
365 		for (i = 0; i < cmdlen; i++) {
366 			HWRITE4(sc, I2C_DS, ((uint8_t *)cmdbuf)[i]);
367 			exiic_xfer_start(sc);
368 			ret = exiic_xfer_wait(sc);
369 			if (ret != I2C_ACK)
370 				goto fail;
371 		}
372 	}
373 
374 	if (I2C_OP_READ_P(op)) {
375 		if (cmdbuf && cmdlen) {
376 			/* write slave chip address again for actual read */
377 			HWRITE4(sc, I2C_DS, addr);
378 
379 			/* restart */
380 			HWRITE4(sc, I2C_STAT, I2C_STAT_MODE_SEL_MASTER_RX
381 					    | I2C_STAT_SERIAL_OUTPUT
382 					    | I2C_STAT_BUSY_SIGNAL);
383 			exiic_xfer_start(sc);
384 			ret = exiic_xfer_wait(sc);
385 			if (ret != I2C_ACK)
386 				goto fail;
387 		}
388 
389 		for (i = 0; i < datalen && ret == I2C_ACK; i++) {
390 			/* disable ACK for final read */
391 			if (i == datalen - 1)
392 				HCLR4(sc, I2C_CON, I2C_CON_ACK);
393 			exiic_xfer_start(sc);
394 			ret = exiic_xfer_wait(sc);
395 			((uint8_t *)databuf)[i] = HREAD4(sc, I2C_DS);
396 		}
397 		if (ret == I2C_NACK)
398 			ret = I2C_ACK; /* Normal terminated read. */
399 	} else {
400 		for (i = 0; i < datalen && ret == I2C_ACK; i++) {
401 			HWRITE4(sc, I2C_DS, ((uint8_t *)databuf)[i]);
402 			exiic_xfer_start(sc);
403 			ret = exiic_xfer_wait(sc);
404 		}
405 	}
406 
407 fail:
408 	/* send STOP */
409 	if (op & I2C_OP_READ_WITH_STOP) {
410 		HWRITE4(sc, I2C_STAT, I2C_STAT_MODE_SEL_MASTER_RX
411 				    | I2C_STAT_SERIAL_OUTPUT);
412 		exiic_xfer_start(sc);
413 	}
414 
415 	return ret;
416 }
417 
418 void
419 exiic_xfer_start(struct exiic_softc *sc)
420 {
421 	HCLR4(sc, I2C_CON, I2C_CON_INTPENDING);
422 }
423 
424 int
425 exiic_xfer_wait(struct exiic_softc *sc)
426 {
427 	if (!exiic_wait_state(sc, I2C_CON, I2C_CON_INTPENDING,
428 					   I2C_CON_INTPENDING))
429 		return (HREAD4(sc, I2C_STAT) & I2C_STAT_LAST_RVCD_BIT) ?
430 			I2C_NACK : I2C_ACK;
431 	else
432 		return I2C_TIMEOUT;
433 }
434 
435 int
436 exiic_detach(struct device *self, int flags)
437 {
438 	struct exiic_softc *sc = (struct exiic_softc *)self;
439 
440 	bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_ios);
441 	return 0;
442 }
443