summaryrefslogtreecommitdiff
path: root/firmware/target/arm/imx31/gigabeat-s/i2c-imx31.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/target/arm/imx31/gigabeat-s/i2c-imx31.c')
-rw-r--r--firmware/target/arm/imx31/gigabeat-s/i2c-imx31.c338
1 files changed, 0 insertions, 338 deletions
diff --git a/firmware/target/arm/imx31/gigabeat-s/i2c-imx31.c b/firmware/target/arm/imx31/gigabeat-s/i2c-imx31.c
deleted file mode 100644
index 1ffdce38ea..0000000000
--- a/firmware/target/arm/imx31/gigabeat-s/i2c-imx31.c
+++ /dev/null
@@ -1,338 +0,0 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2008 by Michael Sevakis
11 *
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.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
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"
28
29/* Forward interrupt handler declarations */
30#if (I2C_MODULE_MASK & USE_I2C1_MODULE)
31static __attribute__((interrupt("IRQ"))) void I2C1_HANDLER(void);
32#endif
33#if (I2C_MODULE_MASK & USE_I2C2_MODULE)
34static __attribute__((interrupt("IRQ"))) void I2C2_HANDLER(void);
35#endif
36#if (I2C_MODULE_MASK & USE_I2C3_MODULE)
37static __attribute__((interrupt("IRQ"))) void I2C3_HANDLER(void);
38#endif
39
40static struct i2c_module_descriptor
41{
42 struct i2c_map *base; /* Module base address */
43 enum IMX31_CG_LIST cg; /* Clock gating index */
44 enum IMX31_INT_LIST ints; /* Module interrupt number */
45 int enable; /* Enable count */
46 void (*handler)(void); /* Module interrupt handler */
47 struct mutex m; /* Node mutual-exclusion */
48 struct wakeup w; /* I2C done signal */
49 unsigned char *addr_data; /* Additional addressing data */
50 int addr_count; /* Addressing byte count */
51 unsigned char *data; /* TX/RX buffer (actual data) */
52 int data_count; /* TX/RX byte count */
53 unsigned char addr; /* Address + r/w bit */
54} i2c_descs[I2C_NUM_I2C] =
55{
56#if (I2C_MODULE_MASK & USE_I2C1_MODULE)
57 {
58 .base = (struct i2c_map *)I2C1_BASE_ADDR,
59 .cg = CG_I2C1,
60 .ints = INT_I2C1,
61 .handler = I2C1_HANDLER,
62 },
63#endif
64#if (I2C_MODULE_MASK & USE_I2C2_MODULE)
65 {
66 .base = (struct i2c_map *)I2C2_BASE_ADDR,
67 .cg = CG_I2C2,
68 .ints = INT_I2C2,
69 .handler = I2C2_HANDLER,
70 },
71#endif
72#if (I2C_MODULE_MASK & USE_I2C3_MODULE)
73 {
74 .base = (struct i2c_map *)I2C3_BASE_ADDR,
75 .cg = CG_I2C3,
76 .ints = INT_I2C3,
77 .handler = I2C3_HANDLER,
78 },
79#endif
80};
81
82static void i2c_interrupt(enum i2c_module_number i2c)
83{
84 struct i2c_module_descriptor *const desc = &i2c_descs[i2c];
85 struct i2c_map * const base = desc->base;
86 uint16_t i2sr = base->i2sr;
87
88 base->i2sr = 0; /* Clear IIF */
89
90 if (desc->addr_count >= 0)
91 {
92 /* ADDR cycle - either done or more to send */
93 if ((i2sr & I2C_I2SR_RXAK) != 0)
94 {
95 goto i2c_stop; /* problem */
96 }
97
98 if (--desc->addr_count < 0)
99 {
100 /* Switching to data cycle */
101 if (desc->addr & 0x1)
102 {
103 base->i2cr &= ~I2C_I2CR_MTX; /* Switch to RX mode */
104 base->i2dr; /* Dummy read */
105 return;
106 }
107 /* else remaining data is TX - handle below */
108 goto i2c_transmit;
109 }
110 else
111 {
112 base->i2dr = *desc->addr_data++; /* Send next addressing byte */
113 return;
114 }
115 }
116
117 if (base->i2cr & I2C_I2CR_MTX)
118 {
119 /* Transmitting data */
120 if ((i2sr & I2C_I2SR_RXAK) == 0)
121 {
122i2c_transmit:
123 if (desc->data_count > 0)
124 {
125 /* More bytes to send, got ACK from previous byte */
126 base->i2dr = *desc->data++;
127 desc->data_count--;
128 return;
129 }
130 }
131 /* else done or no ACK received */
132 }
133 else
134 {
135 /* Receiving data */
136 if (--desc->data_count > 0)
137 {
138 if (desc->data_count == 1)
139 {
140 /* 2nd to Last byte - NACK */
141 base->i2cr |= I2C_I2CR_TXAK;
142 }
143
144 *desc->data++ = base->i2dr; /* Read data from I2DR and store */
145 return;
146 }
147 else
148 {
149 /* Generate STOP signal before reading data */
150 base->i2cr &= ~(I2C_I2CR_MSTA | I2C_I2CR_IIEN);
151 *desc->data++ = base->i2dr; /* Read data from I2DR and store */
152 goto i2c_done;
153 }
154 }
155
156i2c_stop:
157 /* Generate STOP signal */
158 base->i2cr &= ~(I2C_I2CR_MSTA | I2C_I2CR_IIEN);
159i2c_done:
160 /* Signal thread we're done */
161 wakeup_signal(&desc->w);
162}
163
164#if (I2C_MODULE_MASK & USE_I2C1_MODULE)
165static __attribute__((interrupt("IRQ"))) void I2C1_HANDLER(void)
166{
167 i2c_interrupt(I2C1_NUM);
168}
169#endif
170#if (I2C_MODULE_MASK & USE_I2C2_MODULE)
171static __attribute__((interrupt("IRQ"))) void I2C2_HANDLER(void)
172{
173 i2c_interrupt(I2C2_NUM);
174}
175#endif
176#if (I2C_MODULE_MASK & USE_I2C3_MODULE)
177static __attribute__((interrupt("IRQ"))) void I2C3_HANDLER(void)
178{
179 i2c_interrupt(I2C3_NUM);
180}
181#endif
182
183static int i2c_transfer(struct i2c_node * const node,
184 struct i2c_module_descriptor *const desc)
185{
186 struct i2c_map * const base = desc->base;
187 int count = desc->data_count;
188 uint16_t i2cr;
189
190 /* Make sure bus is idle. */
191 while (base->i2sr & I2C_I2SR_IBB);
192
193 /* Set speed */
194 base->ifdr = node->ifdr;
195
196 /* Enable module */
197 base->i2cr = I2C_I2CR_IEN;
198
199 /* Enable Interrupt, Master */
200 i2cr = I2C_I2CR_IEN | I2C_I2CR_IIEN | I2C_I2CR_MTX;
201
202 if ((desc->addr & 0x1) && desc->data_count < 2)
203 {
204 /* Receiving less than two bytes - disable ACK generation */
205 i2cr |= I2C_I2CR_TXAK;
206 }
207
208 /* Set config */
209 base->i2cr = i2cr;
210
211 /* Generate START */
212 base->i2cr = i2cr | I2C_I2CR_MSTA;
213
214 /* Address slave (first byte sent) and begin session. */
215 base->i2dr = desc->addr;
216
217 /* Wait for transfer to complete */
218 if (wakeup_wait(&desc->w, HZ) == OBJ_WAIT_SUCCEEDED)
219 {
220 count -= desc->data_count;
221 }
222 else
223 {
224 /* Generate STOP if timeout */
225 base->i2cr &= ~(I2C_I2CR_MSTA | I2C_I2CR_IIEN);
226 count = -1;
227 }
228
229 desc->addr_count = 0;
230
231 return count;
232}
233
234int i2c_read(struct i2c_node *node, int reg,
235 unsigned char *data, int data_count)
236{
237 struct i2c_module_descriptor *const desc = &i2c_descs[node->num];
238 unsigned char ad[1];
239
240 mutex_lock(&desc->m);
241
242 desc->addr = (node->addr & 0xfe) | 0x1; /* Slave address/rd */
243
244 if (reg >= 0)
245 {
246 /* Sub-address */
247 desc->addr_count = 1;
248 desc->addr_data = ad;
249 ad[0] = reg;
250 }
251 /* else raw read from slave */
252
253 desc->data = data;
254 desc->data_count = data_count;
255
256 data_count = i2c_transfer(node, desc);
257
258 mutex_unlock(&desc->m);
259
260 return data_count;
261}
262
263int i2c_write(struct i2c_node *node, const unsigned char *data, int data_count)
264{
265 struct i2c_module_descriptor *const desc = &i2c_descs[node->num];
266
267 mutex_lock(&desc->m);
268
269 desc->addr = node->addr & 0xfe; /* Slave address/wr */
270 desc->data = (unsigned char *)data;
271 desc->data_count = data_count;
272
273 data_count = i2c_transfer(node, desc);
274
275 mutex_unlock(&desc->m);
276
277 return data_count;
278}
279
280void i2c_init(void)
281{
282 int i;
283
284 /* Do one-time inits for each module that will be used - leave
285 * module disabled and unclocked until something wants it */
286 for (i = 0; i < I2C_NUM_I2C; i++)
287 {
288 struct i2c_module_descriptor *const desc = &i2c_descs[i];
289 ccm_module_clock_gating(desc->cg, CGM_ON_RUN_WAIT);
290 mutex_init(&desc->m);
291 wakeup_init(&desc->w);
292 desc->base->i2cr = 0;
293 ccm_module_clock_gating(desc->cg, CGM_OFF);
294 }
295}
296
297void i2c_enable_node(struct i2c_node *node, bool enable)
298{
299 struct i2c_module_descriptor *const desc = &i2c_descs[node->num];
300
301 mutex_lock(&desc->m);
302
303 if (enable)
304 {
305 if (++desc->enable == 1)
306 {
307 /* First enable */
308 ccm_module_clock_gating(desc->cg, CGM_ON_RUN_WAIT);
309 avic_enable_int(desc->ints, INT_TYPE_IRQ, INT_PRIO_DEFAULT,
310 desc->handler);
311 }
312 }
313 else
314 {
315 if (desc->enable > 0 && --desc->enable == 0)
316 {
317 /* Last enable */
318 while (desc->base->i2sr & I2C_I2SR_IBB); /* Wait for STOP */
319 desc->base->i2cr &= ~I2C_I2CR_IEN;
320 avic_disable_int(desc->ints);
321 ccm_module_clock_gating(desc->cg, CGM_OFF);
322 }
323 }
324
325 mutex_unlock(&desc->m);
326}
327
328void i2c_lock_node(struct i2c_node *node)
329{
330 struct i2c_module_descriptor *const desc = &i2c_descs[node->num];
331 mutex_lock(&desc->m);
332}
333
334void i2c_unlock_node(struct i2c_node *node)
335{
336 struct i2c_module_descriptor *const desc = &i2c_descs[node->num];
337 mutex_unlock(&desc->m);
338}