diff options
Diffstat (limited to 'firmware/target/arm/imx31/gigabeat-s/i2c-imx31.c')
-rw-r--r-- | firmware/target/arm/imx31/gigabeat-s/i2c-imx31.c | 338 |
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) | ||
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 | ||
39 | |||
40 | static 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 | |||
82 | static 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 | { | ||
122 | i2c_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 | |||
156 | i2c_stop: | ||
157 | /* Generate STOP signal */ | ||
158 | base->i2cr &= ~(I2C_I2CR_MSTA | I2C_I2CR_IIEN); | ||
159 | i2c_done: | ||
160 | /* Signal thread we're done */ | ||
161 | wakeup_signal(&desc->w); | ||
162 | } | ||
163 | |||
164 | #if (I2C_MODULE_MASK & USE_I2C1_MODULE) | ||
165 | static __attribute__((interrupt("IRQ"))) void I2C1_HANDLER(void) | ||
166 | { | ||
167 | i2c_interrupt(I2C1_NUM); | ||
168 | } | ||
169 | #endif | ||
170 | #if (I2C_MODULE_MASK & USE_I2C2_MODULE) | ||
171 | static __attribute__((interrupt("IRQ"))) void I2C2_HANDLER(void) | ||
172 | { | ||
173 | i2c_interrupt(I2C2_NUM); | ||
174 | } | ||
175 | #endif | ||
176 | #if (I2C_MODULE_MASK & USE_I2C3_MODULE) | ||
177 | static __attribute__((interrupt("IRQ"))) void I2C3_HANDLER(void) | ||
178 | { | ||
179 | i2c_interrupt(I2C3_NUM); | ||
180 | } | ||
181 | #endif | ||
182 | |||
183 | static 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 | |||
234 | int 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 | |||
263 | int 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 | |||
280 | void 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 | |||
297 | void 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 | |||
328 | void 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 | |||
334 | void 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 | } | ||