imx31: Rename clkctl-imx31.* to ccm-imx31.* and move up from ...imx31/gigabeat-s...
[kugel-rb.git] / firmware / target / arm / imx31 / gigabeat-s / spi-imx31.c
blobac063f9b105a382cd1176c8052b4ce024c7f69ca
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (c) 2007 Will Robertson
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 "config.h"
22 #include "system.h"
23 #include "spi-imx31.h"
24 #include "avic-imx31.h"
25 #include "ccm-imx31.h"
26 #include "debug.h"
27 #include "kernel.h"
29 /* Forward interrupt handler declarations */
30 #if (SPI_MODULE_MASK & USE_CSPI1_MODULE)
31 static __attribute__((interrupt("IRQ"))) void CSPI1_HANDLER(void);
32 #endif
33 #if (SPI_MODULE_MASK & USE_CSPI2_MODULE)
34 static __attribute__((interrupt("IRQ"))) void CSPI2_HANDLER(void);
35 #endif
36 #if (SPI_MODULE_MASK & USE_CSPI3_MODULE)
37 static __attribute__((interrupt("IRQ"))) void CSPI3_HANDLER(void);
38 #endif
40 /* State data associatated with each CSPI module */
41 static struct spi_module_descriptor
43 struct cspi_map * const base;
44 int enab;
45 struct spi_node *last;
46 enum IMX31_CG_LIST cg;
47 enum IMX31_INT_LIST ints;
48 int byte_size;
49 void (*handler)(void);
50 struct mutex m;
51 struct wakeup w;
52 struct spi_transfer *trans;
53 int rxcount;
54 } spi_descs[SPI_NUM_CSPI] =
55 /* Init non-zero members */
57 #if (SPI_MODULE_MASK & USE_CSPI1_MODULE)
59 .base = (struct cspi_map *)CSPI1_BASE_ADDR,
60 .cg = CG_CSPI1,
61 .ints = INT_CSPI1,
62 .handler = CSPI1_HANDLER,
64 #endif
65 #if (SPI_MODULE_MASK & USE_CSPI2_MODULE)
67 .base = (struct cspi_map *)CSPI2_BASE_ADDR,
68 .cg = CG_CSPI2,
69 .ints = INT_CSPI2,
70 .handler = CSPI2_HANDLER,
72 #endif
73 #if (SPI_MODULE_MASK & USE_CSPI3_MODULE)
75 .base = (struct cspi_map *)CSPI3_BASE_ADDR,
76 .cg = CG_CSPI3,
77 .ints = INT_CSPI3,
78 .handler = CSPI3_HANDLER,
80 #endif
83 /* Common code for interrupt handlers */
84 static void spi_interrupt(enum spi_module_number spi)
86 struct spi_module_descriptor *desc = &spi_descs[spi];
87 struct cspi_map * const base = desc->base;
88 struct spi_transfer *trans = desc->trans;
89 int inc = desc->byte_size + 1;
91 if (desc->rxcount > 0)
93 /* Data received - empty out RXFIFO */
94 while ((base->statreg & CSPI_STATREG_RR) != 0)
96 uint32_t word = base->rxdata;
98 switch (desc->byte_size & 3)
100 case 3:
101 *(unsigned char *)(trans->rxbuf + 3) = word >> 24;
102 case 2:
103 *(unsigned char *)(trans->rxbuf + 2) = word >> 16;
104 case 1:
105 *(unsigned char *)(trans->rxbuf + 1) = word >> 8;
106 case 0:
107 *(unsigned char *)(trans->rxbuf + 0) = word;
110 trans->rxbuf += inc;
112 if (--desc->rxcount < 4)
114 unsigned long intreg = base->intreg;
116 if (desc->rxcount <= 0)
118 /* No more to receive - stop RX interrupts */
119 intreg &= ~(CSPI_INTREG_RHEN | CSPI_INTREG_RREN);
120 base->intreg = intreg;
121 break;
123 else if (!(intreg & CSPI_INTREG_RREN))
125 /* < 4 words expected - switch to RX ready */
126 intreg &= ~CSPI_INTREG_RHEN;
127 base->intreg = intreg | CSPI_INTREG_RREN;
133 if (trans->count > 0)
135 /* Data to transmit - fill TXFIFO or write until exhausted */
136 while ((base->statreg & CSPI_STATREG_TF) == 0)
138 uint32_t word = 0;
140 switch (desc->byte_size & 3)
142 case 3:
143 word = *(unsigned char *)(trans->txbuf + 3) << 24;
144 case 2:
145 word |= *(unsigned char *)(trans->txbuf + 2) << 16;
146 case 1:
147 word |= *(unsigned char *)(trans->txbuf + 1) << 8;
148 case 0:
149 word |= *(unsigned char *)(trans->txbuf + 0);
152 trans->txbuf += inc;
154 base->txdata = word;
156 if (--trans->count <= 0)
158 /* Out of data - stop TX interrupts */
159 base->intreg &= ~CSPI_INTREG_THEN;
160 break;
165 /* If all interrupts have been remasked - we're done */
166 if (base->intreg == 0)
168 base->statreg = CSPI_STATREG_TC | CSPI_STATREG_BO;
169 wakeup_signal(&desc->w);
173 /* Interrupt handlers for each CSPI module */
174 #if (SPI_MODULE_MASK & USE_CSPI1_MODULE)
175 static __attribute__((interrupt("IRQ"))) void CSPI1_HANDLER(void)
177 spi_interrupt(CSPI1_NUM);
179 #endif
181 #if (SPI_MODULE_MASK & USE_CSPI2_MODULE)
182 static __attribute__((interrupt("IRQ"))) void CSPI2_HANDLER(void)
184 spi_interrupt(CSPI2_NUM);
186 #endif
188 #if (SPI_MODULE_MASK & USE_CSPI3_MODULE)
189 static __attribute__((interrupt("IRQ"))) void CSPI3_HANDLER(void)
191 spi_interrupt(CSPI3_NUM);
193 #endif
195 /* Write the context for the node and remember it to avoid unneeded reconfigure */
196 static bool spi_set_context(struct spi_node *node,
197 struct spi_module_descriptor *desc)
199 struct cspi_map * const base = desc->base;
201 if ((base->conreg & CSPI_CONREG_EN) == 0)
202 return false;
204 if (node != desc->last)
206 /* Switch the module's node */
207 desc->last = node;
208 desc->byte_size = (((node->conreg >> 8) & 0x1f) + 1 + 7) / 8 - 1;
210 /* Keep reserved and start bits cleared. Keep enabled bit. */
211 base->conreg =
212 (node->conreg & ~(0xfcc8e000 | CSPI_CONREG_XCH | CSPI_CONREG_SMC))
213 | CSPI_CONREG_EN;
214 /* Set the wait-states */
215 base->periodreg = node->periodreg & 0xffff;
216 /* Clear out any spuriously-pending interrupts */
217 base->statreg = CSPI_STATREG_TC | CSPI_STATREG_BO;
220 return true;
223 static void spi_reset(struct cspi_map * const base)
225 /* Reset */
226 base->conreg &= ~CSPI_CONREG_EN;
227 base->conreg |= CSPI_CONREG_EN;
228 base->intreg = 0;
229 base->statreg = CSPI_STATREG_TC | CSPI_STATREG_BO;
232 /* Initialize each of the used SPI descriptors */
233 void spi_init(void)
235 int i;
237 for (i = 0; i < SPI_NUM_CSPI; i++)
239 struct spi_module_descriptor * const desc = &spi_descs[i];
240 mutex_init(&desc->m);
241 wakeup_init(&desc->w);
245 /* Get mutually-exclusive access to the node */
246 void spi_lock(struct spi_node *node)
248 mutex_lock(&spi_descs[node->num].m);
251 /* Release mutual exclusion */
252 void spi_unlock(struct spi_node *node)
254 mutex_unlock(&spi_descs[node->num].m);
257 /* Enable the specified module for the node */
258 void spi_enable_module(struct spi_node *node)
260 struct spi_module_descriptor * const desc = &spi_descs[node->num];
262 mutex_lock(&desc->m);
264 if (++desc->enab == 1)
266 /* First enable for this module */
267 struct cspi_map * const base = desc->base;
269 /* Enable clock-gating register */
270 ccm_module_clock_gating(desc->cg, CGM_ON_RUN_WAIT);
271 /* Reset */
272 spi_reset(base);
273 desc->last = NULL;
274 /* Enable interrupt at controller level */
275 avic_enable_int(desc->ints, INT_TYPE_IRQ, INT_PRIO_DEFAULT,
276 desc->handler);
279 mutex_unlock(&desc->m);
282 /* Disabled the specified module for the node */
283 void spi_disable_module(struct spi_node *node)
285 struct spi_module_descriptor * const desc = &spi_descs[node->num];
287 mutex_lock(&desc->m);
289 if (desc->enab > 0 && --desc->enab == 0)
291 /* Last enable for this module */
292 struct cspi_map * const base = desc->base;
294 /* Disable interrupt at controller level */
295 avic_disable_int(desc->ints);
297 /* Disable interface */
298 base->conreg &= ~CSPI_CONREG_EN;
300 /* Disable interface clock */
301 ccm_module_clock_gating(desc->cg, CGM_OFF);
304 mutex_unlock(&desc->m);
307 /* Send and/or receive data on the specified node */
308 int spi_transfer(struct spi_node *node, struct spi_transfer *trans)
310 struct spi_module_descriptor * const desc = &spi_descs[node->num];
311 int retval;
313 if (trans->count <= 0)
314 return true;
316 mutex_lock(&desc->m);
318 retval = spi_set_context(node, desc);
320 if (retval)
322 struct cspi_map * const base = desc->base;
323 unsigned long intreg;
325 desc->trans = trans;
326 desc->rxcount = trans->count;
328 /* Enable needed interrupts - FIFOs will start filling */
329 intreg = CSPI_INTREG_THEN;
331 intreg |= (trans->count < 4) ?
332 CSPI_INTREG_RREN : /* Must grab data on every word */
333 CSPI_INTREG_RHEN; /* Enough data to wait for half-full */
335 base->intreg = intreg;
337 /* Start transfer */
338 base->conreg |= CSPI_CONREG_XCH;
340 if (wakeup_wait(&desc->w, HZ) != OBJ_WAIT_SUCCEEDED)
342 base->intreg = 0; /* Stop SPI ints */
343 spi_reset(base); /* Reset module (esp. to empty FIFOs) */
344 desc->last = NULL; /* Force reconfigure */
345 retval = false;
349 mutex_unlock(&desc->m);
351 return retval;