xref: /minix/minix/drivers/bus/i2c/arch/earm/omap_i2c.c (revision 7f5f010b)
1 /*
2  * This file implements support for i2c on the BeagleBone and BeagleBoard-xM
3  */
4 
5 /* kernel headers */
6 #include <minix/chardriver.h>
7 #include <minix/clkconf.h>
8 #include <minix/drivers.h>
9 #include <minix/ds.h>
10 #include <minix/log.h>
11 #include <minix/mmio.h>
12 #include <minix/padconf.h>
13 #include <minix/sysutil.h>
14 #include <minix/type.h>
15 #include <minix/board.h>
16 #include <minix/spin.h>
17 
18 /* device headers */
19 #include <minix/i2c.h>
20 
21 /* system headers */
22 #include <sys/ioctl.h>
23 #include <sys/mman.h>
24 #include <sys/types.h>
25 
26 /* usr headers */
27 #include <string.h>
28 #include <stdio.h>
29 #include <stdlib.h>
30 
31 /* local headers */
32 #include "omap_i2c.h"
33 
34 /*
35  * defines the set of register
36  *
37  * Warning: always use the 16-bit variants of read/write/set from mmio.h
38  * to access these registers. The DM37XX TRM Section 17.6 warns that 32-bit
39  * accesses can corrupt the register contents.
40  */
41 typedef struct omap_i2c_registers
42 {
43 	vir_bytes I2C_REVNB_LO;	/* AM335X Only */
44 	vir_bytes I2C_REVNB_HI;	/* AM335X Only */
45 	vir_bytes I2C_REV;	/* DM37XX Only */
46 	vir_bytes I2C_IE;	/* DM37XX Only */
47 	vir_bytes I2C_STAT;	/* DM37XX Only */
48 	vir_bytes I2C_SYSC;
49 	vir_bytes I2C_IRQSTATUS_RAW;	/* AM335X Only */
50 	vir_bytes I2C_IRQSTATUS;	/* AM335X Only */
51 	vir_bytes I2C_IRQENABLE_SET;	/* AM335X Only */
52 	vir_bytes I2C_IRQENABLE_CLR;	/* AM335X Only */
53 	vir_bytes I2C_WE;
54 	vir_bytes I2C_DMARXENABLE_SET;	/* AM335X Only */
55 	vir_bytes I2C_DMATXENABLE_SET;	/* AM335X Only */
56 	vir_bytes I2C_DMARXENABLE_CLR;	/* AM335X Only */
57 	vir_bytes I2C_DMATXENABLE_CLR;	/* AM335X Only */
58 	vir_bytes I2C_DMARXWAKE_EN;	/* AM335X Only */
59 	vir_bytes I2C_DMATXWAKE_EN;	/* AM335X Only */
60 	vir_bytes I2C_SYSS;
61 	vir_bytes I2C_BUF;
62 	vir_bytes I2C_CNT;
63 	vir_bytes I2C_DATA;
64 	vir_bytes I2C_CON;
65 	vir_bytes I2C_OA;	/* AM335X Only */
66 	vir_bytes I2C_OA0;	/* DM37XX Only */
67 	vir_bytes I2C_SA;
68 	vir_bytes I2C_PSC;
69 	vir_bytes I2C_SCLL;
70 	vir_bytes I2C_SCLH;
71 	vir_bytes I2C_SYSTEST;
72 	vir_bytes I2C_BUFSTAT;
73 	vir_bytes I2C_OA1;
74 	vir_bytes I2C_OA2;
75 	vir_bytes I2C_OA3;
76 	vir_bytes I2C_ACTOA;
77 	vir_bytes I2C_SBLOCK;
78 } omap_i2c_regs_t;
79 
80 /* generic definition an i2c bus */
81 
82 typedef struct omap_i2c_bus
83 {
84 	enum bus_types
85 	{ AM335X_I2C_BUS, DM37XX_I2C_BUS} bus_type;
86 	phys_bytes mr_base;
87 	phys_bytes mr_size;
88 	vir_bytes mapped_addr;
89 	omap_i2c_regs_t *regs;
90 	uint32_t functional_clock;
91 	uint32_t module_clock;
92 	uint32_t bus_speed;
93 	uint16_t major;
94 	uint16_t minor;
95 	int irq;
96 	int irq_hook_id;
97 	int irq_hook_kernel_id;
98 } omap_i2c_bus_t;
99 
100 /* Define the registers for each chip */
101 
102 static omap_i2c_regs_t am335x_i2c_regs = {
103 	.I2C_REVNB_LO = AM335X_I2C_REVNB_LO,
104 	.I2C_REVNB_HI = AM335X_I2C_REVNB_HI,
105 	.I2C_SYSC = AM335X_I2C_SYSC,
106 	.I2C_IRQSTATUS_RAW = AM335X_I2C_IRQSTATUS_RAW,
107 	.I2C_IRQSTATUS = AM335X_I2C_IRQSTATUS,
108 	.I2C_IRQENABLE_SET = AM335X_I2C_IRQENABLE_SET,
109 	.I2C_IRQENABLE_CLR = AM335X_I2C_IRQENABLE_CLR,
110 	.I2C_WE = AM335X_I2C_WE,
111 	.I2C_DMARXENABLE_SET = AM335X_I2C_DMARXENABLE_SET,
112 	.I2C_DMATXENABLE_SET = AM335X_I2C_DMATXENABLE_SET,
113 	.I2C_DMARXENABLE_CLR = AM335X_I2C_DMARXENABLE_CLR,
114 	.I2C_DMATXENABLE_CLR = AM335X_I2C_DMATXENABLE_CLR,
115 	.I2C_DMARXWAKE_EN = AM335X_I2C_DMARXWAKE_EN,
116 	.I2C_DMATXWAKE_EN = AM335X_I2C_DMATXWAKE_EN,
117 	.I2C_SYSS = AM335X_I2C_SYSS,
118 	.I2C_BUF = AM335X_I2C_BUF,
119 	.I2C_CNT = AM335X_I2C_CNT,
120 	.I2C_DATA = AM335X_I2C_DATA,
121 	.I2C_CON = AM335X_I2C_CON,
122 	.I2C_OA = AM335X_I2C_OA,
123 	.I2C_SA = AM335X_I2C_SA,
124 	.I2C_PSC = AM335X_I2C_PSC,
125 	.I2C_SCLL = AM335X_I2C_SCLL,
126 	.I2C_SCLH = AM335X_I2C_SCLH,
127 	.I2C_SYSTEST = AM335X_I2C_SYSTEST,
128 	.I2C_BUFSTAT = AM335X_I2C_BUFSTAT,
129 	.I2C_OA1 = AM335X_I2C_OA1,
130 	.I2C_OA2 = AM335X_I2C_OA2,
131 	.I2C_OA3 = AM335X_I2C_OA3,
132 	.I2C_ACTOA = AM335X_I2C_ACTOA,
133 	.I2C_SBLOCK = AM335X_I2C_SBLOCK
134 };
135 
136 static omap_i2c_regs_t dm37xx_i2c_regs = {
137 	.I2C_REV = DM37XX_I2C_REV,
138 	.I2C_IE = DM37XX_I2C_IE,
139 	.I2C_STAT = DM37XX_I2C_STAT,
140 	.I2C_WE = DM37XX_I2C_WE,
141 	.I2C_SYSS = DM37XX_I2C_SYSS,
142 	.I2C_BUF = DM37XX_I2C_BUF,
143 	.I2C_CNT = DM37XX_I2C_CNT,
144 	.I2C_DATA = DM37XX_I2C_DATA,
145 	.I2C_SYSC = DM37XX_I2C_SYSC,
146 	.I2C_CON = DM37XX_I2C_CON,
147 	.I2C_OA0 = DM37XX_I2C_OA0,
148 	.I2C_SA = DM37XX_I2C_SA,
149 	.I2C_PSC = DM37XX_I2C_PSC,
150 	.I2C_SCLL = DM37XX_I2C_SCLL,
151 	.I2C_SCLH = DM37XX_I2C_SCLH,
152 	.I2C_SYSTEST = DM37XX_I2C_SYSTEST,
153 	.I2C_BUFSTAT = DM37XX_I2C_BUFSTAT,
154 	.I2C_OA1 = DM37XX_I2C_OA1,
155 	.I2C_OA2 = DM37XX_I2C_OA2,
156 	.I2C_OA3 = DM37XX_I2C_OA3,
157 	.I2C_ACTOA = DM37XX_I2C_ACTOA,
158 	.I2C_SBLOCK = DM37XX_I2C_SBLOCK
159 };
160 
161 /* Define the buses available on each chip */
162 
163 static omap_i2c_bus_t am335x_i2c_buses[] = {
164 	{AM335X_I2C_BUS, AM335X_I2C0_BASE, AM335X_I2C0_SIZE, 0, &am335x_i2c_regs,
165 		    AM335X_FUNCTIONAL_CLOCK, AM335X_MODULE_CLOCK,
166 		    BUS_SPEED_400KHz, AM335X_REV_MAJOR, AM335X_REV_MINOR,
167 	    AM335X_I2C0_IRQ, 1, 1},
168 	{AM335X_I2C_BUS, AM335X_I2C1_BASE, AM335X_I2C1_SIZE, 0, &am335x_i2c_regs,
169 		    AM335X_FUNCTIONAL_CLOCK, AM335X_MODULE_CLOCK,
170 		    BUS_SPEED_100KHz, AM335X_REV_MAJOR, AM335X_REV_MINOR,
171 	    AM335X_I2C1_IRQ, 2, 3},
172 	{AM335X_I2C_BUS, AM335X_I2C2_BASE, AM335X_I2C2_SIZE, 0, &am335x_i2c_regs,
173 		    AM335X_FUNCTIONAL_CLOCK, AM335X_MODULE_CLOCK,
174 		    BUS_SPEED_100KHz, AM335X_REV_MAJOR, AM335X_REV_MINOR,
175 	    AM335X_I2C2_IRQ, 3, 3}
176 };
177 
178 #define AM335X_OMAP_NBUSES (sizeof(am335x_i2c_buses) / sizeof(omap_i2c_bus_t))
179 
180 static omap_i2c_bus_t dm37xx_i2c_buses[] = {
181 	{DM37XX_I2C_BUS, DM37XX_I2C0_BASE, DM37XX_I2C0_SIZE, 0, &dm37xx_i2c_regs,
182 		    DM37XX_FUNCTIONAL_CLOCK, DM37XX_MODULE_CLOCK,
183 		    BUS_SPEED_100KHz, DM37XX_REV_MAJOR, DM37XX_REV_MINOR,
184 	    DM37XX_I2C0_IRQ, 1, 1},
185 	{DM37XX_I2C_BUS, DM37XX_I2C1_BASE, DM37XX_I2C1_SIZE, 0, &dm37xx_i2c_regs,
186 		    DM37XX_FUNCTIONAL_CLOCK, DM37XX_MODULE_CLOCK,
187 		    BUS_SPEED_100KHz, DM37XX_REV_MAJOR, DM37XX_REV_MINOR,
188 	    DM37XX_I2C1_IRQ, 2, 2},
189 	{DM37XX_I2C_BUS, DM37XX_I2C2_BASE, DM37XX_I2C2_SIZE, 0, &dm37xx_i2c_regs,
190 		    DM37XX_FUNCTIONAL_CLOCK, DM37XX_MODULE_CLOCK,
191 		    BUS_SPEED_100KHz, DM37XX_REV_MAJOR, DM37XX_REV_MINOR,
192 	    DM37XX_I2C2_IRQ, 3, 3}
193 };
194 
195 #define DM37XX_OMAP_NBUSES (sizeof(dm37xx_i2c_buses) / sizeof(omap_i2c_bus_t))
196 
197 /* Globals */
198 
199 static omap_i2c_bus_t *omap_i2c_buses;	/* all available buses for this SoC */
200 static omap_i2c_bus_t *omap_i2c_bus;	/* the bus selected at start-up */
201 static int omap_i2c_nbuses;	/* number of buses supported by SoC */
202 
203 /* logging - use with log_warn(), log_info(), log_debug(), log_trace() */
204 static struct log log = {
205 	.name = "i2c",
206 	.log_level = LEVEL_INFO,
207 	.log_func = default_log
208 };
209 
210 /* Local Function Prototypes */
211 
212 /* Implementation of Generic I2C Interface using Bus Specific Code */
213 static int omap_i2c_process(minix_i2c_ioctl_exec_t * m);
214 
215 /* Bus Specific Code */
216 static void omap_i2c_flush(void);
217 static uint16_t omap_i2c_poll(uint16_t mask);
218 static int omap_i2c_bus_is_free(void);
219 static int omap_i2c_soft_reset(void);
220 static void omap_i2c_bus_init(void);
221 static void omap_i2c_padconf(int i2c_bus_id);
222 static void omap_i2c_clkconf(int i2c_bus_id);
223 static void omap_i2c_intr_enable(void);
224 static uint16_t omap_i2c_read_status(void);
225 static void omap_i2c_write_status(uint16_t mask);
226 static int omap_i2c_read(i2c_addr_t addr, uint8_t * buf, size_t buflen,
227     int dostop);
228 static int omap_i2c_write(i2c_addr_t addr, const uint8_t * buf, size_t buflen,
229     int dostop);
230 
231 /*
232  * Performs the action in minix_i2c_ioctl_exec_t.
233  */
234 static int
235 omap_i2c_process(minix_i2c_ioctl_exec_t * ioctl_exec)
236 {
237 	int r;
238 
239 	/*
240 	 * Zero data bytes transfers are not allowed. The controller treats
241 	 * I2C_CNT register value of 0x0 as 65536. This is true for both the
242 	 * am335x and dm37xx. Full details in the TRM on the I2C_CNT page.
243 	 */
244 	if (ioctl_exec->iie_buflen == 0) {
245 		return EINVAL;
246 	}
247 
248 	omap_i2c_flush();	/* clear any garbage in the fifo */
249 
250 	/* Check bus busy flag before using the bus */
251 	r = omap_i2c_bus_is_free();
252 	if (r == 0) {
253 		log_warn(&log, "Bus is busy\n");
254 		return EBUSY;
255 	}
256 
257 	if (ioctl_exec->iie_cmdlen > 0) {
258 		r = omap_i2c_write(ioctl_exec->iie_addr, ioctl_exec->iie_cmd,
259 		    ioctl_exec->iie_cmdlen,
260 		    !(I2C_OP_READ_P(ioctl_exec->iie_op)));
261 		if (r != OK) {
262 			omap_i2c_soft_reset();
263 			omap_i2c_bus_init();
264 			return r;
265 		}
266 	}
267 
268 	if (I2C_OP_READ_P(ioctl_exec->iie_op)) {
269 		r = omap_i2c_read(ioctl_exec->iie_addr, ioctl_exec->iie_buf,
270 		    ioctl_exec->iie_buflen, I2C_OP_STOP_P(ioctl_exec->iie_op));
271 	} else {
272 		r = omap_i2c_write(ioctl_exec->iie_addr, ioctl_exec->iie_buf,
273 		    ioctl_exec->iie_buflen, I2C_OP_STOP_P(ioctl_exec->iie_op));
274 	}
275 
276 	if (r != OK) {
277 		omap_i2c_soft_reset();
278 		omap_i2c_bus_init();
279 		return r;
280 	}
281 
282 	return OK;
283 }
284 
285 /*
286  * Drain the incoming FIFO.
287  *
288  * Usually called to clear any garbage that may be in the buffer before
289  * doing a read.
290  */
291 static void
292 omap_i2c_flush(void)
293 {
294 	int tries;
295 	int status;
296 
297 	for (tries = 0; tries < 1000; tries++) {
298 		status = omap_i2c_poll(1 << RRDY);
299 		if ((status & (1 << RRDY)) != 0) {	/* bytes available for reading */
300 
301 			/* consume the byte and throw it away */
302 			(void) read16(omap_i2c_bus->mapped_addr + omap_i2c_bus->regs->I2C_DATA);
303 
304 			/* clear the read ready flag */
305 			omap_i2c_write_status(1 << RRDY);
306 
307 		} else {
308 			break;	/* buffer drained */
309 		}
310 	}
311 }
312 
313 /*
314  * Poll the status register checking the bits set in 'mask'.
315  * Returns the status if any bits set or 0x0000 when the timeout is reached.
316  */
317 static uint16_t
318 omap_i2c_poll(uint16_t mask)
319 {
320 	spin_t spin;
321 	uint16_t status;
322 
323 	/* poll for up to 1 s */
324 	spin_init(&spin, 1000000);
325 	do {
326 		status = omap_i2c_read_status();
327 		if ((status & mask) != 0) {	/* any bits in mask set */
328 			return status;
329 		}
330 
331 	} while (spin_check(&spin));
332 
333 	return status;		/* timeout reached, abort */
334 }
335 
336 /*
337  * Poll Bus Busy Flag until the bus becomes free (return 1) or the timeout
338  * expires (return 0).
339  */
340 static int
341 omap_i2c_bus_is_free(void)
342 {
343 	spin_t spin;
344 	uint16_t status;
345 
346 	/* wait for up to 1 second for the bus to become free */
347 	spin_init(&spin, 1000000);
348 	do {
349 
350 		status = omap_i2c_read_status();
351 		if ((status & (1 << BB)) == 0) {
352 			return 1;	/* bus is free */
353 		}
354 
355 	} while (spin_check(&spin));
356 
357 	return 0;		/* timeout expired */
358 }
359 
360 static void
361 omap_i2c_clkconf(int i2c_bus_id)
362 {
363 	clkconf_init();
364 
365 	if (omap_i2c_bus->bus_type == DM37XX_I2C_BUS) {
366 
367 		clkconf_set(CM_ICLKEN1_CORE, BIT((15 + i2c_bus_id)),
368 		    0xffffffff);
369 		clkconf_set(CM_FCLKEN1_CORE, BIT((15 + i2c_bus_id)),
370 		    0xffffffff);
371 
372 	} else if (omap_i2c_bus->bus_type == AM335X_I2C_BUS) {
373 
374 		switch (i2c_bus_id) {
375 		case 0:
376 			clkconf_set(CM_WKUP_I2C0_CLKCTRL, BIT(1), 0xffffffff);
377 			break;
378 		case 1:
379 			clkconf_set(CM_PER_I2C1_CLKCTRL, BIT(1), 0xffffffff);
380 			break;
381 		case 2:
382 			clkconf_set(CM_PER_I2C2_CLKCTRL, BIT(1), 0xffffffff);
383 			break;
384 		default:
385 			log_warn(&log, "Invalid i2c_bus_id\n");
386 			break;
387 		}
388 	}
389 
390 	clkconf_release();
391 }
392 
393 static void
394 omap_i2c_padconf(int i2c_bus_id)
395 {
396 	int r;
397 	u32_t pinopts;
398 
399 	if (omap_i2c_bus->bus_type == AM335X_I2C_BUS) {
400 
401 		/* use the options suggested in starterware driver */
402 		pinopts =
403 		    CONTROL_CONF_SLEWCTRL | CONTROL_CONF_RXACTIVE |
404 		    CONTROL_CONF_PUTYPESEL;
405 
406 		switch (i2c_bus_id) {
407 		case 0:
408 			pinopts |= CONTROL_CONF_MUXMODE(0);
409 
410 			r = sys_padconf(CONTROL_CONF_I2C0_SDA, 0xffffffff,
411 			    pinopts);
412 			if (r != OK) {
413 				log_warn(&log, "padconf failed (r=%d)\n", r);
414 			}
415 
416 			r = sys_padconf(CONTROL_CONF_I2C0_SCL, 0xffffffff,
417 			    pinopts);
418 			if (r != OK) {
419 				log_warn(&log, "padconf failed (r=%d)\n", r);
420 			}
421 
422 			log_debug(&log, "pinopts=0x%x\n", pinopts);
423 			break;
424 
425 		case 1:
426 			pinopts |= CONTROL_CONF_MUXMODE(2);
427 
428 			r = sys_padconf(CONTROL_CONF_SPI0_CS0, 0xffffffff,
429 			    pinopts);
430 			if (r != OK) {
431 				log_warn(&log, "padconf failed (r=%d)\n", r);
432 			}
433 
434 			r = sys_padconf(CONTROL_CONF_SPI0_D1, 0xffffffff,
435 			    pinopts);
436 			if (r != OK) {
437 				log_warn(&log, "padconf failed (r=%d)\n", r);
438 			}
439 			log_debug(&log, "pinopts=0x%x\n", pinopts);
440 			break;
441 
442 		case 2:
443 			pinopts |= CONTROL_CONF_MUXMODE(3);
444 
445 			r = sys_padconf(CONTROL_CONF_UART1_CTSN, 0xffffffff,
446 			    pinopts);
447 			if (r != OK) {
448 				log_warn(&log, "padconf failed (r=%d)\n", r);
449 			}
450 
451 			r = sys_padconf(CONTROL_CONF_UART1_RTSN,
452 			    0xffffffff, pinopts);
453 			if (r != OK) {
454 				log_warn(&log, "padconf failed (r=%d)\n", r);
455 			}
456 
457 			log_debug(&log, "pinopts=0x%x\n", pinopts);
458 			break;
459 
460 		default:
461 			log_warn(&log, "Invalid i2c_bus_id\n");
462 			break;
463 		}
464 	}
465 
466 	/* nothing to do for the DM37XX */
467 }
468 
469 static int
470 omap_i2c_soft_reset(void)
471 {
472 	spin_t spin;
473 
474 	/* Disable to do soft reset */
475 	write16(omap_i2c_bus->mapped_addr + omap_i2c_bus->regs->I2C_CON, 0);
476 	micro_delay(50000);
477 
478 	/* Do a soft reset */
479 	write16(omap_i2c_bus->mapped_addr + omap_i2c_bus->regs->I2C_SYSC, (1 << SRST));
480 
481 	/* Have to temporarily enable I2C to read RDONE */
482 	set16(omap_i2c_bus->mapped_addr + omap_i2c_bus->regs->I2C_CON, (1<<I2C_EN), (1<<I2C_EN));
483 	micro_delay(50000);
484 
485 	/* wait up to 3 seconds for reset to complete */
486 	spin_init(&spin, 3000000);
487 	do {
488 		if (read16(omap_i2c_bus->mapped_addr + omap_i2c_bus->regs->I2C_SYSS) & (1 << RDONE)) {
489 			return OK;
490 		}
491 
492 	} while (spin_check(&spin));
493 
494 	log_warn(&log, "Tried soft reset, but bus never came back.\n");
495 	return EIO;
496 }
497 
498 static void
499 omap_i2c_intr_enable(void)
500 {
501 	int r;
502 	uint16_t intmask;
503 	static int policy_set = 0;
504 	static int enabled = 0;
505 
506 	if (!policy_set) {
507 		r = sys_irqsetpolicy(omap_i2c_bus->irq, 0,
508 		    &omap_i2c_bus->irq_hook_kernel_id);
509 		if (r == OK) {
510 			policy_set = 1;
511 		} else {
512 			log_warn(&log, "Couldn't set irq policy\n");
513 		}
514 	}
515 
516 	if (policy_set && !enabled) {
517 		r = sys_irqenable(&omap_i2c_bus->irq_hook_kernel_id);
518 		if (r == OK) {
519 			enabled = 1;
520 		} else {
521 			log_warn(&log, "Couldn't enable irq %d (hooked)\n",
522 			    omap_i2c_bus->irq);
523 		}
524 	}
525 
526 	/* According to NetBSD driver and u-boot, these are needed even
527 	 * if just using polling (i.e. non-interrupt driver programming).
528 	 */
529 	intmask = 0;
530 	intmask |= (1 << ROVR);
531 	intmask |= (1 << AERR);
532 	intmask |= (1 << XRDY);
533 	intmask |= (1 << RRDY);
534 	intmask |= (1 << ARDY);
535 	intmask |= (1 << NACK);
536 	intmask |= (1 << AL);
537 
538 	if (omap_i2c_bus->bus_type == AM335X_I2C_BUS) {
539 		write16(omap_i2c_bus->mapped_addr + omap_i2c_bus->regs->I2C_IRQENABLE_SET, intmask);
540 	} else if (omap_i2c_bus->bus_type == DM37XX_I2C_BUS) {
541 		write16(omap_i2c_bus->mapped_addr + omap_i2c_bus->regs->I2C_IE, intmask);
542 	} else {
543 		log_warn(&log, "Don't know how to enable interrupts.\n");
544 	}
545 }
546 
547 static void
548 omap_i2c_bus_init(void)
549 {
550 
551 	/* Ensure i2c module is disabled before setting prescalar & bus speed */
552 	write16(omap_i2c_bus->mapped_addr + omap_i2c_bus->regs->I2C_CON, 0);
553 	micro_delay(50000);
554 
555 	/* Disable autoidle */
556 	set16(omap_i2c_bus->mapped_addr + omap_i2c_bus->regs->I2C_SYSC, (1<<AUTOIDLE), (0<<AUTOIDLE));
557 
558 	/* Set prescalar to obtain 12 MHz i2c module clock */
559 	write16(omap_i2c_bus->mapped_addr + omap_i2c_bus->regs->I2C_PSC,
560 	    ((omap_i2c_bus->functional_clock / omap_i2c_bus->module_clock) -
561 		1));
562 
563 	/* Set the bus speed */
564 	write16(omap_i2c_bus->mapped_addr + omap_i2c_bus->regs->I2C_SCLL,
565 	    ((omap_i2c_bus->module_clock / (2 * omap_i2c_bus->bus_speed)) -
566 		7));
567 	write16(omap_i2c_bus->mapped_addr + omap_i2c_bus->regs->I2C_SCLH,
568 	    ((omap_i2c_bus->module_clock / (2 * omap_i2c_bus->bus_speed)) -
569 		5));
570 
571 	/* Set own I2C address */
572 	if (omap_i2c_bus->bus_type == AM335X_I2C_BUS) {
573 		write16(omap_i2c_bus->mapped_addr + omap_i2c_bus->regs->I2C_OA, I2C_OWN_ADDRESS);
574 	} else if (omap_i2c_bus->bus_type == DM37XX_I2C_BUS) {
575 		write16(omap_i2c_bus->mapped_addr + omap_i2c_bus->regs->I2C_OA0, I2C_OWN_ADDRESS);
576 	} else {
577 		log_warn(&log, "Don't know how to set own address.\n");
578 	}
579 
580 	/* Set TX/RX Threshold to 1 and disable I2C DMA */
581 	write16(omap_i2c_bus->mapped_addr + omap_i2c_bus->regs->I2C_BUF, 0x0000);
582 
583 	/* Bring the i2c module out of reset */
584 	set16(omap_i2c_bus->mapped_addr + omap_i2c_bus->regs->I2C_CON, (1<<I2C_EN), (1<<I2C_EN));
585 	micro_delay(50000);
586 
587 	/*
588 	 * Enable interrupts
589 	 */
590 	omap_i2c_intr_enable();
591 }
592 
593 static uint16_t
594 omap_i2c_read_status(void)
595 {
596 	uint16_t status = 0x0000;
597 
598 	if (omap_i2c_bus->bus_type == AM335X_I2C_BUS) {
599 		/* TRM says to use RAW for polling for events */
600 		status = read16(omap_i2c_bus->mapped_addr + omap_i2c_bus->regs->I2C_IRQSTATUS_RAW);
601 	} else if (omap_i2c_bus->bus_type == DM37XX_I2C_BUS) {
602 		status = read16(omap_i2c_bus->mapped_addr + omap_i2c_bus->regs->I2C_STAT);
603 	} else {
604 		log_warn(&log, "Don't know how to read i2c bus status.\n");
605 	}
606 
607 	return status;
608 }
609 
610 static void
611 omap_i2c_write_status(uint16_t mask)
612 {
613 	if (omap_i2c_bus->bus_type == AM335X_I2C_BUS) {
614 		/* write 1's to IRQSTATUS (not RAW) to clear the bits */
615 		write16(omap_i2c_bus->mapped_addr + omap_i2c_bus->regs->I2C_IRQSTATUS, mask);
616 	} else if (omap_i2c_bus->bus_type == DM37XX_I2C_BUS) {
617 		write16(omap_i2c_bus->mapped_addr + omap_i2c_bus->regs->I2C_STAT, mask);
618 	} else {
619 		log_warn(&log, "Don't know how to clear i2c bus status.\n");
620 	}
621 }
622 
623 static int
624 omap_i2c_read(i2c_addr_t addr, uint8_t * buf, size_t buflen, int dostop)
625 {
626 	int r, i;
627 	uint16_t conopts;
628 	uint16_t pollmask;
629 	uint16_t errmask;
630 
631 	/* Set address of slave device */
632 	conopts = 0;
633 	addr &= MAX_I2C_SA_MASK;	/* sanitize address (10-bit max) */
634 	if (addr > 0x7f) {
635 		/* 10-bit extended address in use, need to set XSA */
636 		conopts |= (1 << XSA);
637 	}
638 
639 	errmask = 0;
640 	errmask |= (1 << ROVR);
641 	errmask |= (1 << AERR);
642 	errmask |= (1 << NACK);
643 	errmask |= (1 << AL);
644 
645 	pollmask = 0;
646 	pollmask |= (1 << RRDY);
647 
648 	/* Set bytes to read and slave address */
649 	write16(omap_i2c_bus->mapped_addr + omap_i2c_bus->regs->I2C_CNT, buflen);
650 	write16(omap_i2c_bus->mapped_addr + omap_i2c_bus->regs->I2C_SA, addr);
651 
652 	/* Set control register */
653 	conopts |= (1 << I2C_EN);	/* enabled */
654 	conopts |= (1 << MST);	/* master mode */
655 	conopts |= (1 << STT);	/* start condition */
656 
657 	if (dostop != 0) {
658 		conopts |= (1 << STP);	/* stop condition */
659 	}
660 
661 	write16(omap_i2c_bus->mapped_addr + omap_i2c_bus->regs->I2C_CON, conopts);
662 
663 	for (i = 0; i < buflen; i++) {
664 		/* Data to read? */
665 		r = omap_i2c_poll(pollmask | errmask);
666 		if ((r & errmask) != 0) {
667 			/* only debug log level because i2cscan trigers this */
668 			log_debug(&log, "Read Error! Status=%x\n", r);
669 			return EIO;
670 		} else if ((r & pollmask) == 0) {
671 			log_warn(&log, "No RRDY Interrupt. Status=%x\n", r);
672 			log_warn(&log,
673 			    "Likely cause: bad pinmux or no devices on bus\n");
674 			return EBUSY;
675 		}
676 
677 		/* read a byte */
678 		buf[i] = read16(omap_i2c_bus->mapped_addr + omap_i2c_bus->regs->I2C_DATA) & 0xff;
679 
680 		/* clear the read ready flag */
681 		omap_i2c_write_status(pollmask);
682 	}
683 
684 	r = omap_i2c_read_status();
685 	if ((r & (1 << NACK)) != 0) {
686 		log_warn(&log, "NACK\n");
687 		return EIO;
688 	}
689 
690 	/* Wait for operation to complete */
691 	pollmask = (1<<ARDY); /* poll access ready bit */
692 	r = omap_i2c_poll(pollmask);
693 	if ((r & pollmask) == 0) {
694 		log_warn(&log, "Read operation never finished.\n");
695 		return EBUSY;
696 	}
697 	omap_i2c_write_status(0x7fff);
698 
699 	return 0;
700 }
701 
702 static int
703 omap_i2c_write(i2c_addr_t addr, const uint8_t * buf, size_t buflen, int dostop)
704 {
705 	int r, i;
706 	uint16_t conopts;
707 	uint16_t pollmask;
708 	uint16_t errmask;
709 
710 	/* Set address of slave device */
711 	conopts = 0;
712 	addr &= MAX_I2C_SA_MASK;	/* sanitize address (10-bit max) */
713 	if (addr > 0x7f) {
714 		/* 10-bit extended address in use, need to set XSA */
715 		conopts |= (1 << XSA);
716 	}
717 
718 	pollmask = 0;
719 	pollmask |= (1 << XRDY);
720 
721 	errmask = 0;
722 	errmask |= (1 << ROVR);
723 	errmask |= (1 << AERR);
724 	errmask |= (1 << NACK);
725 	errmask |= (1 << AL);
726 
727 	write16(omap_i2c_bus->mapped_addr + omap_i2c_bus->regs->I2C_CNT, buflen);
728 	write16(omap_i2c_bus->mapped_addr + omap_i2c_bus->regs->I2C_SA, addr);
729 
730 	/* Set control register */
731 	conopts |= (1 << I2C_EN);	/* enabled */
732 	conopts |= (1 << MST);	/* master mode */
733 	conopts |= (1 << TRX);	/* TRX mode */
734 	conopts |= (1 << STT);	/* start condition */
735 
736 	if (dostop != 0) {
737 		conopts |= (1 << STP);	/* stop condition */
738 	}
739 
740 	omap_i2c_write_status(0x7fff);
741 	write16(omap_i2c_bus->mapped_addr + omap_i2c_bus->regs->I2C_CON, conopts);
742 
743 	for (i = 0; i < buflen; i++) {
744 
745 		/* Ready to write? */
746 		r = omap_i2c_poll(pollmask | errmask);
747 		if ((r & errmask) != 0) {
748 			log_warn(&log, "Write Error! Status=%x\n", r);
749 			return EIO;
750 		} else if ((r & pollmask) == 0) {
751 			log_warn(&log, "Not ready for write? Status=%x\n", r);
752 			return EBUSY;
753 		}
754 
755 		write16(omap_i2c_bus->mapped_addr + omap_i2c_bus->regs->I2C_DATA, buf[i]);
756 
757 		/* clear the write ready flag */
758 		omap_i2c_write_status(pollmask);
759 	}
760 
761 	r = omap_i2c_read_status();
762 	if ((r & (1 << NACK)) != 0) {
763 		log_warn(&log, "NACK\n");
764 		return EIO;
765 	}
766 
767 	/* Wait for operation to complete */
768 	pollmask = (1<<ARDY); /* poll access ready bit */
769 	r = omap_i2c_poll(pollmask);
770 	if ((r & pollmask) == 0) {
771 		log_warn(&log, "Write operation never finished.\n");
772 		return EBUSY;
773 	}
774 	omap_i2c_write_status(0x7fff);
775 
776 	return 0;
777 }
778 
779 int
780 omap_interface_setup(int (**process) (minix_i2c_ioctl_exec_t * ioctl_exec),
781     int i2c_bus_id)
782 {
783 	int r;
784 	int i2c_rev, major, minor;
785 	struct minix_mem_range mr;
786 	struct machine machine;
787 	sys_getmachine(&machine);
788 
789 	/* Fill in the function pointer */
790 
791 	*process = omap_i2c_process;
792 
793 	/* Select the correct i2c definition for this SoC */
794 
795 	if (BOARD_IS_BBXM(machine.board_id)){
796 		omap_i2c_buses = dm37xx_i2c_buses;
797 		omap_i2c_nbuses = DM37XX_OMAP_NBUSES;
798 	} else if (BOARD_IS_BB(machine.board_id)){
799 		omap_i2c_buses = am335x_i2c_buses;
800 		omap_i2c_nbuses = AM335X_OMAP_NBUSES;
801 	} else {
802 		return EINVAL;
803 	}
804 
805 	if (i2c_bus_id < 0 || i2c_bus_id >= omap_i2c_nbuses) {
806 		return EINVAL;
807 	}
808 
809 	/* select the bus to operate on */
810 	omap_i2c_bus = &omap_i2c_buses[i2c_bus_id];
811 
812 	/* Configure Pins */
813 	omap_i2c_padconf(i2c_bus_id);
814 
815 	/*
816 	 * Map I2C Registers
817 	 */
818 
819 	/* Configure memory access */
820 	mr.mr_base = omap_i2c_bus->mr_base;	/* start addr */
821 	mr.mr_limit = mr.mr_base + omap_i2c_bus->mr_size;	/* end addr */
822 
823 	/* ask for privileges to access the I2C memory range */
824 	if (sys_privctl(SELF, SYS_PRIV_ADD_MEM, &mr) != OK) {
825 		panic("Unable to obtain i2c memory range privileges");
826 	}
827 
828 	/* map the memory into this process */
829 	omap_i2c_bus->mapped_addr = (vir_bytes) vm_map_phys(SELF,
830 	    (void *) omap_i2c_bus->mr_base, omap_i2c_bus->mr_size);
831 
832 	if (omap_i2c_bus->mapped_addr == (vir_bytes) MAP_FAILED) {
833 		panic("Unable to map i2c registers");
834 	}
835 
836 	/* Enable Clocks */
837 	omap_i2c_clkconf(i2c_bus_id);
838 
839 	/* Perform a soft reset of the I2C module to ensure a fresh start */
840 	r = omap_i2c_soft_reset();
841 	if (r != OK) {
842 		/* module didn't come back up :( */
843 		return r;
844 	}
845 
846 	/* Bring up I2C module */
847 	omap_i2c_bus_init();
848 
849 	/* Get I2C Revision */
850 	if (omap_i2c_bus->bus_type == AM335X_I2C_BUS) {
851 		/* I2C_REVLO revision: major (bits 10-8), minor (bits 5-0) */
852 		i2c_rev = read16(omap_i2c_bus->mapped_addr + omap_i2c_bus->regs->I2C_REVNB_LO);
853 		major = (i2c_rev >> 8) & 0x07;
854 		minor = i2c_rev & 0x3f;
855 
856 	} else if (omap_i2c_bus->bus_type == DM37XX_I2C_BUS) {
857 		/* I2C_REV revision: major (bits 7-4), minor (bits 3-0) */
858 		i2c_rev = read16(omap_i2c_bus->mapped_addr + omap_i2c_bus->regs->I2C_REV);
859 		major = (i2c_rev >> 4) & 0x0f;
860 		minor = i2c_rev & 0x0f;
861 	} else {
862 		panic("Don't know how to read i2c revision.");
863 	}
864 
865 	if (major != omap_i2c_bus->major || minor != omap_i2c_bus->minor) {
866 		log_warn(&log, "Unrecognized value in I2C_REV register.\n");
867 		log_warn(&log, "Read: 0x%x.0x%x | Expected: 0x%x.0x%x\n",
868 		    major, minor, omap_i2c_bus->major, omap_i2c_bus->minor);
869 	}
870 
871 	/* display i2c revision information for debugging purposes */
872 	log_debug(&log, "i2c_%d: I2C rev 0x%x.0x%x\n", (i2c_bus_id + 1),
873 	    major, minor);
874 
875 	return OK;
876 }
877