tools/llvm: Do not build with symbols
[minix3.git] / minix / drivers / bus / i2c / arch / earm / omap_i2c.c
blobcc571c5095c423bf132fe339ee9c666689044efa
1 /*
2 * This file implements support for i2c on the BeagleBone and BeagleBoard-xM
3 */
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>
18 /* device headers */
19 #include <minix/i2c.h>
21 /* system headers */
22 #include <sys/ioctl.h>
23 #include <sys/mman.h>
24 #include <sys/types.h>
26 /* usr headers */
27 #include <string.h>
28 #include <stdio.h>
29 #include <stdlib.h>
31 /* local headers */
32 #include "omap_i2c.h"
35 * defines the set of register
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.
41 typedef struct omap_i2c_registers
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;
80 /* generic definition an i2c bus */
82 typedef struct omap_i2c_bus
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;
100 /* Define the registers for each chip */
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
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
161 /* Define the buses available on each chip */
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}
178 #define AM335X_OMAP_NBUSES (sizeof(am335x_i2c_buses) / sizeof(omap_i2c_bus_t))
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}
195 #define DM37XX_OMAP_NBUSES (sizeof(dm37xx_i2c_buses) / sizeof(omap_i2c_bus_t))
197 /* Globals */
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 */
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
210 /* Local Function Prototypes */
212 /* Implementation of Generic I2C Interface using Bus Specific Code */
213 static int omap_i2c_process(minix_i2c_ioctl_exec_t * m);
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);
232 * Performs the action in minix_i2c_ioctl_exec_t.
234 static int
235 omap_i2c_process(minix_i2c_ioctl_exec_t * ioctl_exec)
237 int r;
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.
244 if (ioctl_exec->iie_buflen == 0) {
245 return EINVAL;
248 omap_i2c_flush(); /* clear any garbage in the fifo */
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;
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;
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));
276 if (r != OK) {
277 omap_i2c_soft_reset();
278 omap_i2c_bus_init();
279 return r;
282 return OK;
286 * Drain the incoming FIFO.
288 * Usually called to clear any garbage that may be in the buffer before
289 * doing a read.
291 static void
292 omap_i2c_flush(void)
294 int tries;
295 int status;
297 for (tries = 0; tries < 1000; tries++) {
298 status = omap_i2c_poll(1 << RRDY);
299 if ((status & (1 << RRDY)) != 0) { /* bytes available for reading */
301 /* consume the byte and throw it away */
302 (void) read16(omap_i2c_bus->mapped_addr + omap_i2c_bus->regs->I2C_DATA);
304 /* clear the read ready flag */
305 omap_i2c_write_status(1 << RRDY);
307 } else {
308 break; /* buffer drained */
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.
317 static uint16_t
318 omap_i2c_poll(uint16_t mask)
320 spin_t spin;
321 uint16_t status;
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;
331 } while (spin_check(&spin));
333 return status; /* timeout reached, abort */
337 * Poll Bus Busy Flag until the bus becomes free (return 1) or the timeout
338 * expires (return 0).
340 static int
341 omap_i2c_bus_is_free(void)
343 spin_t spin;
344 uint16_t status;
346 /* wait for up to 1 second for the bus to become free */
347 spin_init(&spin, 1000000);
348 do {
350 status = omap_i2c_read_status();
351 if ((status & (1 << BB)) == 0) {
352 return 1; /* bus is free */
355 } while (spin_check(&spin));
357 return 0; /* timeout expired */
360 static void
361 omap_i2c_clkconf(int i2c_bus_id)
363 clkconf_init();
365 if (omap_i2c_bus->bus_type == DM37XX_I2C_BUS) {
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);
372 } else if (omap_i2c_bus->bus_type == AM335X_I2C_BUS) {
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;
390 clkconf_release();
393 static void
394 omap_i2c_padconf(int i2c_bus_id)
396 int r;
397 u32_t pinopts;
399 if (omap_i2c_bus->bus_type == AM335X_I2C_BUS) {
401 /* use the options suggested in starterware driver */
402 pinopts =
403 CONTROL_CONF_SLEWCTRL | CONTROL_CONF_RXACTIVE |
404 CONTROL_CONF_PUTYPESEL;
406 switch (i2c_bus_id) {
407 case 0:
408 pinopts |= CONTROL_CONF_MUXMODE(0);
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);
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);
422 log_debug(&log, "pinopts=0x%x\n", pinopts);
423 break;
425 case 1:
426 pinopts |= CONTROL_CONF_MUXMODE(2);
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);
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);
439 log_debug(&log, "pinopts=0x%x\n", pinopts);
440 break;
442 case 2:
443 pinopts |= CONTROL_CONF_MUXMODE(3);
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);
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);
457 log_debug(&log, "pinopts=0x%x\n", pinopts);
458 break;
460 default:
461 log_warn(&log, "Invalid i2c_bus_id\n");
462 break;
466 /* nothing to do for the DM37XX */
469 static int
470 omap_i2c_soft_reset(void)
472 spin_t spin;
474 /* Disable to do soft reset */
475 write16(omap_i2c_bus->mapped_addr + omap_i2c_bus->regs->I2C_CON, 0);
476 micro_delay(50000);
478 /* Do a soft reset */
479 write16(omap_i2c_bus->mapped_addr + omap_i2c_bus->regs->I2C_SYSC, (1 << SRST));
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);
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;
492 } while (spin_check(&spin));
494 log_warn(&log, "Tried soft reset, but bus never came back.\n");
495 return EIO;
498 static void
499 omap_i2c_intr_enable(void)
501 int r;
502 uint16_t intmask;
503 static int policy_set = 0;
504 static int enabled = 0;
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");
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);
526 /* According to NetBSD driver and u-boot, these are needed even
527 * if just using polling (i.e. non-interrupt driver programming).
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);
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");
547 static void
548 omap_i2c_bus_init(void)
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);
555 /* Disable autoidle */
556 set16(omap_i2c_bus->mapped_addr + omap_i2c_bus->regs->I2C_SYSC, (1<<AUTOIDLE), (0<<AUTOIDLE));
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));
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));
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");
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);
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);
588 * Enable interrupts
590 omap_i2c_intr_enable();
593 static uint16_t
594 omap_i2c_read_status(void)
596 uint16_t status = 0x0000;
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");
607 return status;
610 static void
611 omap_i2c_write_status(uint16_t mask)
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");
623 static int
624 omap_i2c_read(i2c_addr_t addr, uint8_t * buf, size_t buflen, int dostop)
626 int r, i;
627 uint16_t conopts;
628 uint16_t pollmask;
629 uint16_t errmask;
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);
639 errmask = 0;
640 errmask |= (1 << ROVR);
641 errmask |= (1 << AERR);
642 errmask |= (1 << NACK);
643 errmask |= (1 << AL);
645 pollmask = 0;
646 pollmask |= (1 << RRDY);
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);
652 /* Set control register */
653 conopts |= (1 << I2C_EN); /* enabled */
654 conopts |= (1 << MST); /* master mode */
655 conopts |= (1 << STT); /* start condition */
657 if (dostop != 0) {
658 conopts |= (1 << STP); /* stop condition */
661 write16(omap_i2c_bus->mapped_addr + omap_i2c_bus->regs->I2C_CON, conopts);
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;
677 /* read a byte */
678 buf[i] = read16(omap_i2c_bus->mapped_addr + omap_i2c_bus->regs->I2C_DATA) & 0xff;
680 /* clear the read ready flag */
681 omap_i2c_write_status(pollmask);
684 r = omap_i2c_read_status();
685 if ((r & (1 << NACK)) != 0) {
686 log_warn(&log, "NACK\n");
687 return EIO;
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;
697 omap_i2c_write_status(0x7fff);
699 return 0;
702 static int
703 omap_i2c_write(i2c_addr_t addr, const uint8_t * buf, size_t buflen, int dostop)
705 int r, i;
706 uint16_t conopts;
707 uint16_t pollmask;
708 uint16_t errmask;
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);
718 pollmask = 0;
719 pollmask |= (1 << XRDY);
721 errmask = 0;
722 errmask |= (1 << ROVR);
723 errmask |= (1 << AERR);
724 errmask |= (1 << NACK);
725 errmask |= (1 << AL);
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);
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 */
736 if (dostop != 0) {
737 conopts |= (1 << STP); /* stop condition */
740 omap_i2c_write_status(0x7fff);
741 write16(omap_i2c_bus->mapped_addr + omap_i2c_bus->regs->I2C_CON, conopts);
743 for (i = 0; i < buflen; i++) {
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;
755 write16(omap_i2c_bus->mapped_addr + omap_i2c_bus->regs->I2C_DATA, buf[i]);
757 /* clear the write ready flag */
758 omap_i2c_write_status(pollmask);
761 r = omap_i2c_read_status();
762 if ((r & (1 << NACK)) != 0) {
763 log_warn(&log, "NACK\n");
764 return EIO;
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;
774 omap_i2c_write_status(0x7fff);
776 return 0;
780 omap_interface_setup(int (**process) (minix_i2c_ioctl_exec_t * ioctl_exec),
781 int i2c_bus_id)
783 int r;
784 int i2c_rev, major, minor;
785 struct minix_mem_range mr;
786 struct machine machine;
787 sys_getmachine(&machine);
789 /* Fill in the function pointer */
791 *process = omap_i2c_process;
793 /* Select the correct i2c definition for this SoC */
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;
805 if (i2c_bus_id < 0 || i2c_bus_id >= omap_i2c_nbuses) {
806 return EINVAL;
809 /* select the bus to operate on */
810 omap_i2c_bus = &omap_i2c_buses[i2c_bus_id];
812 /* Configure Pins */
813 omap_i2c_padconf(i2c_bus_id);
816 * Map I2C Registers
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 */
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");
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);
832 if (omap_i2c_bus->mapped_addr == (vir_bytes) MAP_FAILED) {
833 panic("Unable to map i2c registers");
836 /* Enable Clocks */
837 omap_i2c_clkconf(i2c_bus_id);
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;
846 /* Bring up I2C module */
847 omap_i2c_bus_init();
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;
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.");
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);
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);
875 return OK;