i.MX31: Make some style changes to some driver code so that hardware vs. variable...
[kugel-rb.git] / firmware / target / arm / imx31 / i2c-imx31.c
blob4e810c588f6e95af4e22f4661e5fbf280a3fd376
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2008 by Michael Sevakis
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
21 #include <stdlib.h>
22 #include "config.h"
23 #include "system.h"
24 #include "kernel.h"
25 #include "avic-imx31.h"
26 #include "ccm-imx31.h"
27 #include "i2c-imx31.h"
29 /* Forward interrupt handler declarations */
30 #if (I2C_MODULE_MASK & USE_I2C1_MODULE)
31 static __attribute__((interrupt("IRQ"))) void I2C1_HANDLER(void);
32 #endif
33 #if (I2C_MODULE_MASK & USE_I2C2_MODULE)
34 static __attribute__((interrupt("IRQ"))) void I2C2_HANDLER(void);
35 #endif
36 #if (I2C_MODULE_MASK & USE_I2C3_MODULE)
37 static __attribute__((interrupt("IRQ"))) void I2C3_HANDLER(void);
38 #endif
40 #define IADR (0x00 / sizeof (unsigned short)) /* 00h */
41 #define IFDR (0x04 / sizeof (unsigned short)) /* 04h */
42 #define I2CR (0x08 / sizeof (unsigned short)) /* 08h */
43 #define I2SR (0x0c / sizeof (unsigned short)) /* 0ch */
44 #define I2DR (0x10 / sizeof (unsigned short)) /* 10h */
46 static struct i2c_module_descriptor
48 volatile unsigned short * const base; /* Module base address */
49 void (* const handler)(void); /* Module interrupt handler */
50 struct mutex m; /* Node mutual-exclusion */
51 struct wakeup w; /* I2C done signal */
52 unsigned char *addr_data; /* Additional addressing data */
53 int addr_count; /* Addressing byte count */
54 unsigned char *data; /* TX/RX buffer (actual data) */
55 int data_count; /* TX/RX byte count */
56 unsigned char addr; /* Address + r/w bit */
57 uint8_t enable; /* Enable count */
58 const uint8_t cg; /* Clock gating index */
59 const uint8_t ints; /* Module interrupt number */
60 } i2c_descs[I2C_NUM_I2C] =
62 #if (I2C_MODULE_MASK & USE_I2C1_MODULE)
64 .base = (unsigned short *)I2C1_BASE_ADDR,
65 .cg = CG_I2C1,
66 .ints = INT_I2C1,
67 .handler = I2C1_HANDLER,
69 #endif
70 #if (I2C_MODULE_MASK & USE_I2C2_MODULE)
72 .base = (unsigned short *)I2C2_BASE_ADDR,
73 .cg = CG_I2C2,
74 .ints = INT_I2C2,
75 .handler = I2C2_HANDLER,
77 #endif
78 #if (I2C_MODULE_MASK & USE_I2C3_MODULE)
80 .base = (unsigned short *)I2C3_BASE_ADDR,
81 .cg = CG_I2C3,
82 .ints = INT_I2C3,
83 .handler = I2C3_HANDLER,
85 #endif
88 static void i2c_interrupt(enum i2c_module_number i2c)
90 struct i2c_module_descriptor * const desc = &i2c_descs[i2c];
91 volatile unsigned short * const base = desc->base;
92 unsigned short i2sr = base[I2SR];
94 base[I2SR] = 0; /* Clear IIF */
96 if (desc->addr_count >= 0)
98 /* ADDR cycle - either done or more to send */
99 if ((i2sr & I2C_I2SR_RXAK) != 0)
101 goto i2c_stop; /* problem */
104 if (--desc->addr_count < 0)
106 /* Switching to data cycle */
107 if (desc->addr & 0x1)
109 base[I2CR] &= ~I2C_I2CR_MTX; /* Switch to RX mode */
110 base[I2DR]; /* Dummy read */
111 return;
113 /* else remaining data is TX - handle below */
114 goto i2c_transmit;
116 else
118 base[I2DR] = *desc->addr_data++; /* Send next addressing byte */
119 return;
123 if (base[I2CR] & I2C_I2CR_MTX)
125 /* Transmitting data */
126 if ((i2sr & I2C_I2SR_RXAK) == 0)
128 i2c_transmit:
129 if (desc->data_count > 0)
131 /* More bytes to send, got ACK from previous byte */
132 base[I2DR] = *desc->data++;
133 desc->data_count--;
134 return;
137 /* else done or no ACK received */
139 else
141 /* Receiving data */
142 if (--desc->data_count > 0)
144 if (desc->data_count == 1)
146 /* 2nd to Last byte - NACK */
147 base[I2CR] |= I2C_I2CR_TXAK;
150 *desc->data++ = base[I2DR]; /* Read data from I2DR and store */
151 return;
153 else
155 /* Generate STOP signal before reading data */
156 base[I2CR] &= ~(I2C_I2CR_MSTA | I2C_I2CR_IIEN);
157 *desc->data++ = base[I2DR]; /* Read data from I2DR and store */
158 goto i2c_done;
162 i2c_stop:
163 /* Generate STOP signal */
164 base[I2CR] &= ~(I2C_I2CR_MSTA | I2C_I2CR_IIEN);
165 i2c_done:
166 /* Signal thread we're done */
167 wakeup_signal(&desc->w);
170 #if (I2C_MODULE_MASK & USE_I2C1_MODULE)
171 static __attribute__((interrupt("IRQ"))) void I2C1_HANDLER(void)
173 i2c_interrupt(I2C1_NUM);
175 #endif
176 #if (I2C_MODULE_MASK & USE_I2C2_MODULE)
177 static __attribute__((interrupt("IRQ"))) void I2C2_HANDLER(void)
179 i2c_interrupt(I2C2_NUM);
181 #endif
182 #if (I2C_MODULE_MASK & USE_I2C3_MODULE)
183 static __attribute__((interrupt("IRQ"))) void I2C3_HANDLER(void)
185 i2c_interrupt(I2C3_NUM);
187 #endif
189 static int i2c_transfer(struct i2c_node * const node,
190 struct i2c_module_descriptor *const desc)
192 volatile unsigned short * const base = desc->base;
193 int count = desc->data_count;
194 uint16_t i2cr;
196 /* Make sure bus is idle. */
197 while (base[I2SR] & I2C_I2SR_IBB);
199 /* Set speed */
200 base[IFDR] = node->ifdr;
202 /* Enable module */
203 base[I2CR] = I2C_I2CR_IEN;
205 /* Enable Interrupt, Master */
206 i2cr = I2C_I2CR_IEN | I2C_I2CR_IIEN | I2C_I2CR_MTX;
208 if ((desc->addr & 0x1) && desc->data_count < 2)
210 /* Receiving less than two bytes - disable ACK generation */
211 i2cr |= I2C_I2CR_TXAK;
214 /* Set config */
215 base[I2CR] = i2cr;
217 /* Generate START */
218 base[I2CR] = i2cr | I2C_I2CR_MSTA;
220 /* Address slave (first byte sent) and begin session. */
221 base[I2DR] = desc->addr;
223 /* Wait for transfer to complete */
224 if (wakeup_wait(&desc->w, HZ) == OBJ_WAIT_SUCCEEDED)
226 count -= desc->data_count;
228 else
230 /* Generate STOP if timeout */
231 base[I2CR] &= ~(I2C_I2CR_MSTA | I2C_I2CR_IIEN);
232 count = -1;
235 desc->addr_count = 0;
237 return count;
240 int i2c_read(struct i2c_node *node, int reg,
241 unsigned char *data, int data_count)
243 struct i2c_module_descriptor *const desc = &i2c_descs[node->num];
244 unsigned char ad[1];
246 mutex_lock(&desc->m);
248 desc->addr = (node->addr & 0xfe) | 0x1; /* Slave address/rd */
250 if (reg >= 0)
252 /* Sub-address */
253 desc->addr_count = 1;
254 desc->addr_data = ad;
255 ad[0] = reg;
257 /* else raw read from slave */
259 desc->data = data;
260 desc->data_count = data_count;
262 data_count = i2c_transfer(node, desc);
264 mutex_unlock(&desc->m);
266 return data_count;
269 int i2c_write(struct i2c_node *node, const unsigned char *data, int data_count)
271 struct i2c_module_descriptor *const desc = &i2c_descs[node->num];
273 mutex_lock(&desc->m);
275 desc->addr = node->addr & 0xfe; /* Slave address/wr */
276 desc->data = (unsigned char *)data;
277 desc->data_count = data_count;
279 data_count = i2c_transfer(node, desc);
281 mutex_unlock(&desc->m);
283 return data_count;
286 void i2c_init(void)
288 int i;
290 /* Do one-time inits for each module that will be used - leave
291 * module disabled and unclocked until something wants it */
292 for (i = 0; i < I2C_NUM_I2C; i++)
294 struct i2c_module_descriptor *const desc = &i2c_descs[i];
295 ccm_module_clock_gating(desc->cg, CGM_ON_RUN_WAIT);
296 mutex_init(&desc->m);
297 wakeup_init(&desc->w);
298 desc->base[I2CR] = 0;
299 ccm_module_clock_gating(desc->cg, CGM_OFF);
303 void i2c_enable_node(struct i2c_node *node, bool enable)
305 struct i2c_module_descriptor *const desc = &i2c_descs[node->num];
307 mutex_lock(&desc->m);
309 if (enable)
311 if (++desc->enable == 1)
313 /* First enable */
314 ccm_module_clock_gating(desc->cg, CGM_ON_RUN_WAIT);
315 avic_enable_int(desc->ints, INT_TYPE_IRQ, INT_PRIO_DEFAULT,
316 desc->handler);
319 else
321 if (desc->enable > 0 && --desc->enable == 0)
323 /* Last enable */
324 while (desc->base[I2SR] & I2C_I2SR_IBB); /* Wait for STOP */
325 desc->base[I2CR] &= ~I2C_I2CR_IEN;
326 avic_disable_int(desc->ints);
327 ccm_module_clock_gating(desc->cg, CGM_OFF);
331 mutex_unlock(&desc->m);
334 void i2c_lock_node(struct i2c_node *node)
336 struct i2c_module_descriptor *const desc = &i2c_descs[node->num];
337 mutex_lock(&desc->m);
340 void i2c_unlock_node(struct i2c_node *node)
342 struct i2c_module_descriptor *const desc = &i2c_descs[node->num];
343 mutex_unlock(&desc->m);