diff options
Diffstat (limited to 'firmware/target/arm/imx31/spi-imx31.c')
-rw-r--r-- | firmware/target/arm/imx31/spi-imx31.c | 88 |
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); | |||
37 | static __attribute__((interrupt("IRQ"))) void CSPI3_HANDLER(void); | 37 | static __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 */ |
41 | static struct spi_module_desc | 50 | static 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 | |||
83 | static void spi_reset(struct spi_module_desc * const desc) | 92 | static 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. */ |
121 | static int tx_fill_fifo(struct spi_module_desc * const desc, | 129 | static 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, | |||
158 | static bool start_transfer(struct spi_module_desc * const desc, | 166 | static 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, | |||
189 | static void spi_interrupt(enum spi_module_number spi) | 197 | static 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); |