summaryrefslogtreecommitdiff
path: root/firmware/target/arm/imx31/spi-imx31.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/target/arm/imx31/spi-imx31.c')
-rw-r--r--firmware/target/arm/imx31/spi-imx31.c88
1 files changed, 47 insertions, 41 deletions
diff --git a/firmware/target/arm/imx31/spi-imx31.c b/firmware/target/arm/imx31/spi-imx31.c
index 3f66257c95..e6dddd65c1 100644
--- a/firmware/target/arm/imx31/spi-imx31.c
+++ b/firmware/target/arm/imx31/spi-imx31.c
@@ -37,25 +37,34 @@ static __attribute__((interrupt("IRQ"))) void CSPI2_HANDLER(void);
37static __attribute__((interrupt("IRQ"))) void CSPI3_HANDLER(void); 37static __attribute__((interrupt("IRQ"))) void CSPI3_HANDLER(void);
38#endif 38#endif
39 39
40#define RXDATA (0x000 / sizeof (unsigned long)) /* 000h */
41#define TXDATA (0x004 / sizeof (unsigned long)) /* 004h */
42#define CONREG (0x008 / sizeof (unsigned long)) /* 008h */
43#define INTREG (0x00c / sizeof (unsigned long)) /* 00Ch */
44#define DMAREG (0x010 / sizeof (unsigned long)) /* 010h */
45#define STATREG (0x014 / sizeof (unsigned long)) /* 014h */
46#define PERIODREG (0x01c / sizeof (unsigned long)) /* 018h */
47#define TESTREG (0x1c0 / sizeof (unsigned long)) /* 1C0h */
48
40/* State data associatated with each CSPI module */ 49/* State data associatated with each CSPI module */
41static struct spi_module_desc 50static struct spi_module_desc
42{ 51{
43 struct cspi_map * const base; /* CSPI module address */ 52 volatile unsigned long * const base; /* CSPI module address */
44 struct spi_transfer_desc *head; /* Running job */ 53 struct spi_transfer_desc *head; /* Running job */
45 struct spi_transfer_desc *tail; /* Most recent job added */ 54 struct spi_transfer_desc *tail; /* Most recent job added */
46 const struct spi_node *last_node; /* Last node used for module */ 55 const struct spi_node *last_node; /* Last node used for module */
47 void (*handler)(void); /* Interrupt handler */ 56 void (* const handler)(void); /* Interrupt handler */
48 int rxcount; /* Independent copy of txcount */ 57 int rxcount; /* Independent copy of txcount */
49 int8_t enab; /* Enable count */ 58 int8_t enab; /* Enable count */
50 int8_t byte_size; /* Size of transfers in bytes */ 59 int8_t byte_size; /* Size of transfers in bytes */
51 int8_t cg; /* Clock-gating value */ 60 const int8_t cg; /* Clock-gating value */
52 int8_t ints; /* AVIC vector number */ 61 const int8_t ints; /* AVIC vector number */
53} spi_descs[SPI_NUM_CSPI] = 62} spi_descs[SPI_NUM_CSPI] =
54/* Init non-zero members */ 63/* Init non-zero members */
55{ 64{
56#if (SPI_MODULE_MASK & USE_CSPI1_MODULE) 65#if (SPI_MODULE_MASK & USE_CSPI1_MODULE)
57 { 66 {
58 .base = (struct cspi_map *)CSPI1_BASE_ADDR, 67 .base = (unsigned long *)CSPI1_BASE_ADDR,
59 .cg = CG_CSPI1, 68 .cg = CG_CSPI1,
60 .ints = INT_CSPI1, 69 .ints = INT_CSPI1,
61 .handler = CSPI1_HANDLER, 70 .handler = CSPI1_HANDLER,
@@ -63,7 +72,7 @@ static struct spi_module_desc
63#endif 72#endif
64#if (SPI_MODULE_MASK & USE_CSPI2_MODULE) 73#if (SPI_MODULE_MASK & USE_CSPI2_MODULE)
65 { 74 {
66 .base = (struct cspi_map *)CSPI2_BASE_ADDR, 75 .base = (unsigned long *)CSPI2_BASE_ADDR,
67 .cg = CG_CSPI2, 76 .cg = CG_CSPI2,
68 .ints = INT_CSPI2, 77 .ints = INT_CSPI2,
69 .handler = CSPI2_HANDLER, 78 .handler = CSPI2_HANDLER,
@@ -71,7 +80,7 @@ static struct spi_module_desc
71#endif 80#endif
72#if (SPI_MODULE_MASK & USE_CSPI3_MODULE) 81#if (SPI_MODULE_MASK & USE_CSPI3_MODULE)
73 { 82 {
74 .base = (struct cspi_map *)CSPI3_BASE_ADDR, 83 .base = (unsigned long *)CSPI3_BASE_ADDR,
75 .cg = CG_CSPI3, 84 .cg = CG_CSPI3,
76 .ints = INT_CSPI3, 85 .ints = INT_CSPI3,
77 .handler = CSPI3_HANDLER, 86 .handler = CSPI3_HANDLER,
@@ -83,8 +92,7 @@ static struct spi_module_desc
83static void spi_reset(struct spi_module_desc * const desc) 92static void spi_reset(struct spi_module_desc * const desc)
84{ 93{
85 /* Reset by leaving it disabled */ 94 /* Reset by leaving it disabled */
86 struct cspi_map * const base = desc->base; 95 desc->base[CONREG] &= ~CSPI_CONREG_EN;
87 base->conreg &= ~CSPI_CONREG_EN;
88} 96}
89 97
90/* Write the context for the node and remember it to avoid unneeded reconfigure */ 98/* Write the context for the node and remember it to avoid unneeded reconfigure */
@@ -92,7 +100,7 @@ static bool spi_set_context(struct spi_module_desc *desc,
92 struct spi_transfer_desc *xfer) 100 struct spi_transfer_desc *xfer)
93{ 101{
94 const struct spi_node * const node = xfer->node; 102 const struct spi_node * const node = xfer->node;
95 struct cspi_map * const base = desc->base; 103 volatile unsigned long * const base = desc->base;
96 104
97 if (desc->enab == 0) 105 if (desc->enab == 0)
98 return false; 106 return false;
@@ -101,17 +109,17 @@ static bool spi_set_context(struct spi_module_desc *desc,
101 return true; 109 return true;
102 110
103 /* Errata says CSPI should be disabled when writing PERIODREG. */ 111 /* Errata says CSPI should be disabled when writing PERIODREG. */
104 base->conreg &= ~CSPI_CONREG_EN; 112 base[CONREG] &= ~CSPI_CONREG_EN;
105 113
106 /* Switch the module's node */ 114 /* Switch the module's node */
107 desc->last_node = node; 115 desc->last_node = node;
108 desc->byte_size = (((node->conreg >> 8) & 0x1f) + 1 + 7) / 8 - 1; 116 desc->byte_size = (((node->conreg >> 8) & 0x1f) + 1 + 7) / 8 - 1;
109 117
110 /* Set the wait-states */ 118 /* Set the wait-states */
111 base->periodreg = node->periodreg & 0xffff; 119 base[PERIODREG] = node->periodreg & 0xffff;
112 120
113 /* Keep reserved and start bits cleared. Keep enabled bit. */ 121 /* Keep reserved and start bits cleared. Keep enabled bit. */
114 base->conreg = 122 base[CONREG] =
115 (node->conreg & ~(0xfcc8e000 | CSPI_CONREG_XCH | CSPI_CONREG_SMC)); 123 (node->conreg & ~(0xfcc8e000 | CSPI_CONREG_XCH | CSPI_CONREG_SMC));
116 return true; 124 return true;
117} 125}
@@ -119,13 +127,13 @@ static bool spi_set_context(struct spi_module_desc *desc,
119 127
120/* Fill the TX fifo. Returns the number of remaining words. */ 128/* Fill the TX fifo. Returns the number of remaining words. */
121static int tx_fill_fifo(struct spi_module_desc * const desc, 129static int tx_fill_fifo(struct spi_module_desc * const desc,
122 struct cspi_map * const base, 130 volatile unsigned long * const base,
123 struct spi_transfer_desc * const xfer) 131 struct spi_transfer_desc * const xfer)
124{ 132{
125 int count = xfer->count; 133 int count = xfer->count;
126 int size = desc->byte_size; 134 int size = desc->byte_size;
127 135
128 while ((base->statreg & CSPI_STATREG_TF) == 0) 136 while ((base[STATREG] & CSPI_STATREG_TF) == 0)
129 { 137 {
130 uint32_t word = 0; 138 uint32_t word = 0;
131 139
@@ -143,7 +151,7 @@ static int tx_fill_fifo(struct spi_module_desc * const desc,
143 151
144 xfer->txbuf += size + 1; /* Increment buffer */ 152 xfer->txbuf += size + 1; /* Increment buffer */
145 153
146 base->txdata = word; /* Write to FIFO */ 154 base[TXDATA] = word; /* Write to FIFO */
147 155
148 if (--count == 0) 156 if (--count == 0)
149 break; 157 break;
@@ -158,13 +166,13 @@ static int tx_fill_fifo(struct spi_module_desc * const desc,
158static bool start_transfer(struct spi_module_desc * const desc, 166static bool start_transfer(struct spi_module_desc * const desc,
159 struct spi_transfer_desc * const xfer) 167 struct spi_transfer_desc * const xfer)
160{ 168{
161 struct cspi_map * const base = desc->base; 169 volatile unsigned long * const base = desc->base;
162 unsigned long intreg; 170 unsigned long intreg;
163 171
164 if (!spi_set_context(desc, xfer)) 172 if (!spi_set_context(desc, xfer))
165 return false; 173 return false;
166 174
167 base->conreg |= CSPI_CONREG_EN; /* Enable module */ 175 base[CONREG] |= CSPI_CONREG_EN; /* Enable module */
168 176
169 desc->rxcount = xfer->count; 177 desc->rxcount = xfer->count;
170 178
@@ -178,9 +186,9 @@ static bool start_transfer(struct spi_module_desc * const desc,
178 186
179 tx_fill_fifo(desc, base, xfer); 187 tx_fill_fifo(desc, base, xfer);
180 188
181 base->statreg = CSPI_STATREG_TC; /* Ack 'complete' */ 189 base[STATREG] = CSPI_STATREG_TC; /* Ack 'complete' */
182 base->intreg = intreg; /* Enable interrupts */ 190 base[INTREG] = intreg; /* Enable interrupts */
183 base->conreg |= CSPI_CONREG_XCH; /* Begin transfer */ 191 base[CONREG] |= CSPI_CONREG_XCH; /* Begin transfer */
184 192
185 return true; 193 return true;
186} 194}
@@ -189,15 +197,15 @@ static bool start_transfer(struct spi_module_desc * const desc,
189static void spi_interrupt(enum spi_module_number spi) 197static void spi_interrupt(enum spi_module_number spi)
190{ 198{
191 struct spi_module_desc *desc = &spi_descs[spi]; 199 struct spi_module_desc *desc = &spi_descs[spi];
192 struct cspi_map * const base = desc->base; 200 volatile unsigned long * const base = desc->base;
193 unsigned long intreg = base->intreg; 201 unsigned long intreg = base[INTREG];
194 struct spi_transfer_desc *xfer = desc->head; 202 struct spi_transfer_desc *xfer = desc->head;
195 int inc = desc->byte_size + 1; 203 int inc = desc->byte_size + 1;
196 204
197 /* Data received - empty out RXFIFO */ 205 /* Data received - empty out RXFIFO */
198 while ((base->statreg & CSPI_STATREG_RR) != 0) 206 while ((base[STATREG] & CSPI_STATREG_RR) != 0)
199 { 207 {
200 uint32_t word = base->rxdata; 208 uint32_t word = base[RXDATA];
201 209
202 if (desc->rxcount <= 0) 210 if (desc->rxcount <= 0)
203 continue; 211 continue;
@@ -226,14 +234,14 @@ static void spi_interrupt(enum spi_module_number spi)
226 { 234 {
227 /* No more to receive - stop RX interrupts */ 235 /* No more to receive - stop RX interrupts */
228 intreg &= ~(CSPI_INTREG_RHEN | CSPI_INTREG_RREN); 236 intreg &= ~(CSPI_INTREG_RHEN | CSPI_INTREG_RREN);
229 base->intreg = intreg; 237 base[INTREG] = intreg;
230 } 238 }
231 else if (intreg & CSPI_INTREG_RHEN) 239 else if (intreg & CSPI_INTREG_RHEN)
232 { 240 {
233 /* < 4 words expected - switch to RX ready */ 241 /* < 4 words expected - switch to RX ready */
234 intreg &= ~CSPI_INTREG_RHEN; 242 intreg &= ~CSPI_INTREG_RHEN;
235 intreg |= CSPI_INTREG_RREN; 243 intreg |= CSPI_INTREG_RREN;
236 base->intreg = intreg; 244 base[INTREG] = intreg;
237 } 245 }
238 } 246 }
239 } 247 }
@@ -247,15 +255,15 @@ static void spi_interrupt(enum spi_module_number spi)
247 /* Out of data - stop TX interrupts, enable TC interrupt. */ 255 /* Out of data - stop TX interrupts, enable TC interrupt. */
248 intreg &= ~CSPI_INTREG_THEN; 256 intreg &= ~CSPI_INTREG_THEN;
249 intreg |= CSPI_INTREG_TCEN; 257 intreg |= CSPI_INTREG_TCEN;
250 base->intreg = intreg; 258 base[INTREG] = intreg;
251 } 259 }
252 260
253 if ((intreg & CSPI_INTREG_TCEN) && (base->statreg & CSPI_STATREG_TC)) 261 if ((intreg & CSPI_INTREG_TCEN) && (base[STATREG] & CSPI_STATREG_TC))
254 { 262 {
255 /* Outbound transfer is complete. */ 263 /* Outbound transfer is complete. */
256 intreg &= ~CSPI_INTREG_TCEN; 264 intreg &= ~CSPI_INTREG_TCEN;
257 base->intreg = intreg; 265 base[INTREG] = intreg;
258 base->statreg = CSPI_STATREG_TC; /* Ack 'complete' */ 266 base[STATREG] = CSPI_STATREG_TC; /* Ack 'complete' */
259 } 267 }
260 268
261 if (intreg != 0) 269 if (intreg != 0)
@@ -268,7 +276,7 @@ static void spi_interrupt(enum spi_module_number spi)
268 spi_transfer_cb_fn_type callback = xfer->callback; 276 spi_transfer_cb_fn_type callback = xfer->callback;
269 xfer->next = NULL; 277 xfer->next = NULL;
270 278
271 base->conreg &= ~CSPI_CONREG_EN; /* Disable module */ 279 base[CONREG] &= ~CSPI_CONREG_EN; /* Disable module */
272 280
273 if (next == xfer) 281 if (next == xfer)
274 { 282 {
@@ -361,8 +369,6 @@ void spi_disable_module(const struct spi_node *node)
361 if (desc->enab > 0 && --desc->enab == 0) 369 if (desc->enab > 0 && --desc->enab == 0)
362 { 370 {
363 /* Last enable for this module */ 371 /* Last enable for this module */
364 struct cspi_map * const base = desc->base;
365
366 /* Wait for outstanding transactions */ 372 /* Wait for outstanding transactions */
367 while (*(void ** volatile)&desc->head != NULL); 373 while (*(void ** volatile)&desc->head != NULL);
368 374
@@ -370,7 +376,7 @@ void spi_disable_module(const struct spi_node *node)
370 avic_disable_int(desc->ints); 376 avic_disable_int(desc->ints);
371 377
372 /* Disable interface */ 378 /* Disable interface */
373 base->conreg &= ~CSPI_CONREG_EN; 379 desc->base[CONREG] &= ~CSPI_CONREG_EN;
374 380
375 /* Disable interface clock */ 381 /* Disable interface clock */
376 ccm_module_clock_gating(desc->cg, CGM_OFF); 382 ccm_module_clock_gating(desc->cg, CGM_OFF);