diff options
author | Mark Brown <broonie@linaro.org> | 2013-09-01 08:49:12 -0400 |
---|---|---|
committer | Mark Brown <broonie@linaro.org> | 2013-09-01 08:49:12 -0400 |
commit | a3e412dcf568cc389a584cd37ccb0057a89dcb0a (patch) | |
tree | 279b97d2e178721c2d0b0d6663631e9f9ccc69b8 /drivers/spi | |
parent | 368ce0bca434347b7cd5550ee71b046d7727830f (diff) | |
parent | 692fb0fe5aacea861e4006342029cf505a7dbe18 (diff) |
Merge remote-tracking branch 'spi/topic/sirf' into spi-next
Diffstat (limited to 'drivers/spi')
-rw-r--r-- | drivers/spi/Kconfig | 2 | ||||
-rw-r--r-- | drivers/spi/spi-sirf.c | 227 |
2 files changed, 182 insertions, 47 deletions
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index f552c89abdd4..0170d4c4a8a3 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig | |||
@@ -433,7 +433,7 @@ config SPI_SH_HSPI | |||
433 | 433 | ||
434 | config SPI_SIRF | 434 | config SPI_SIRF |
435 | tristate "CSR SiRFprimaII SPI controller" | 435 | tristate "CSR SiRFprimaII SPI controller" |
436 | depends on ARCH_SIRF | 436 | depends on SIRF_DMA |
437 | select SPI_BITBANG | 437 | select SPI_BITBANG |
438 | help | 438 | help |
439 | SPI driver for CSR SiRFprimaII SoCs | 439 | SPI driver for CSR SiRFprimaII SoCs |
diff --git a/drivers/spi/spi-sirf.c b/drivers/spi/spi-sirf.c index fc5081ab3677..a1f21b747733 100644 --- a/drivers/spi/spi-sirf.c +++ b/drivers/spi/spi-sirf.c | |||
@@ -19,6 +19,10 @@ | |||
19 | #include <linux/of_gpio.h> | 19 | #include <linux/of_gpio.h> |
20 | #include <linux/spi/spi.h> | 20 | #include <linux/spi/spi.h> |
21 | #include <linux/spi/spi_bitbang.h> | 21 | #include <linux/spi/spi_bitbang.h> |
22 | #include <linux/dmaengine.h> | ||
23 | #include <linux/dma-direction.h> | ||
24 | #include <linux/dma-mapping.h> | ||
25 | #include <linux/sirfsoc_dma.h> | ||
22 | 26 | ||
23 | #define DRIVER_NAME "sirfsoc_spi" | 27 | #define DRIVER_NAME "sirfsoc_spi" |
24 | 28 | ||
@@ -119,9 +123,19 @@ | |||
119 | #define SIRFSOC_SPI_FIFO_HC(x) (((x) & 0x3F) << 20) | 123 | #define SIRFSOC_SPI_FIFO_HC(x) (((x) & 0x3F) << 20) |
120 | #define SIRFSOC_SPI_FIFO_THD(x) (((x) & 0xFF) << 2) | 124 | #define SIRFSOC_SPI_FIFO_THD(x) (((x) & 0xFF) << 2) |
121 | 125 | ||
126 | /* | ||
127 | * only if the rx/tx buffer and transfer size are 4-bytes aligned, we use dma | ||
128 | * due to the limitation of dma controller | ||
129 | */ | ||
130 | |||
131 | #define ALIGNED(x) (!((u32)x & 0x3)) | ||
132 | #define IS_DMA_VALID(x) (x && ALIGNED(x->tx_buf) && ALIGNED(x->rx_buf) && \ | ||
133 | ALIGNED(x->len) && (x->len < 2 * PAGE_SIZE)) | ||
134 | |||
122 | struct sirfsoc_spi { | 135 | struct sirfsoc_spi { |
123 | struct spi_bitbang bitbang; | 136 | struct spi_bitbang bitbang; |
124 | struct completion done; | 137 | struct completion rx_done; |
138 | struct completion tx_done; | ||
125 | 139 | ||
126 | void __iomem *base; | 140 | void __iomem *base; |
127 | u32 ctrl_freq; /* SPI controller clock speed */ | 141 | u32 ctrl_freq; /* SPI controller clock speed */ |
@@ -137,8 +151,16 @@ struct sirfsoc_spi { | |||
137 | void (*tx_word) (struct sirfsoc_spi *); | 151 | void (*tx_word) (struct sirfsoc_spi *); |
138 | 152 | ||
139 | /* number of words left to be tranmitted/received */ | 153 | /* number of words left to be tranmitted/received */ |
140 | unsigned int left_tx_cnt; | 154 | unsigned int left_tx_word; |
141 | unsigned int left_rx_cnt; | 155 | unsigned int left_rx_word; |
156 | |||
157 | /* rx & tx DMA channels */ | ||
158 | struct dma_chan *rx_chan; | ||
159 | struct dma_chan *tx_chan; | ||
160 | dma_addr_t src_start; | ||
161 | dma_addr_t dst_start; | ||
162 | void *dummypage; | ||
163 | int word_width; /* in bytes */ | ||
142 | 164 | ||
143 | int chipselect[0]; | 165 | int chipselect[0]; |
144 | }; | 166 | }; |
@@ -155,7 +177,7 @@ static void spi_sirfsoc_rx_word_u8(struct sirfsoc_spi *sspi) | |||
155 | sspi->rx = rx; | 177 | sspi->rx = rx; |
156 | } | 178 | } |
157 | 179 | ||
158 | sspi->left_rx_cnt--; | 180 | sspi->left_rx_word--; |
159 | } | 181 | } |
160 | 182 | ||
161 | static void spi_sirfsoc_tx_word_u8(struct sirfsoc_spi *sspi) | 183 | static void spi_sirfsoc_tx_word_u8(struct sirfsoc_spi *sspi) |
@@ -169,7 +191,7 @@ static void spi_sirfsoc_tx_word_u8(struct sirfsoc_spi *sspi) | |||
169 | } | 191 | } |
170 | 192 | ||
171 | writel(data, sspi->base + SIRFSOC_SPI_TXFIFO_DATA); | 193 | writel(data, sspi->base + SIRFSOC_SPI_TXFIFO_DATA); |
172 | sspi->left_tx_cnt--; | 194 | sspi->left_tx_word--; |
173 | } | 195 | } |
174 | 196 | ||
175 | static void spi_sirfsoc_rx_word_u16(struct sirfsoc_spi *sspi) | 197 | static void spi_sirfsoc_rx_word_u16(struct sirfsoc_spi *sspi) |
@@ -184,7 +206,7 @@ static void spi_sirfsoc_rx_word_u16(struct sirfsoc_spi *sspi) | |||
184 | sspi->rx = rx; | 206 | sspi->rx = rx; |
185 | } | 207 | } |
186 | 208 | ||
187 | sspi->left_rx_cnt--; | 209 | sspi->left_rx_word--; |
188 | } | 210 | } |
189 | 211 | ||
190 | static void spi_sirfsoc_tx_word_u16(struct sirfsoc_spi *sspi) | 212 | static void spi_sirfsoc_tx_word_u16(struct sirfsoc_spi *sspi) |
@@ -198,7 +220,7 @@ static void spi_sirfsoc_tx_word_u16(struct sirfsoc_spi *sspi) | |||
198 | } | 220 | } |
199 | 221 | ||
200 | writel(data, sspi->base + SIRFSOC_SPI_TXFIFO_DATA); | 222 | writel(data, sspi->base + SIRFSOC_SPI_TXFIFO_DATA); |
201 | sspi->left_tx_cnt--; | 223 | sspi->left_tx_word--; |
202 | } | 224 | } |
203 | 225 | ||
204 | static void spi_sirfsoc_rx_word_u32(struct sirfsoc_spi *sspi) | 226 | static void spi_sirfsoc_rx_word_u32(struct sirfsoc_spi *sspi) |
@@ -213,7 +235,7 @@ static void spi_sirfsoc_rx_word_u32(struct sirfsoc_spi *sspi) | |||
213 | sspi->rx = rx; | 235 | sspi->rx = rx; |
214 | } | 236 | } |
215 | 237 | ||
216 | sspi->left_rx_cnt--; | 238 | sspi->left_rx_word--; |
217 | 239 | ||
218 | } | 240 | } |
219 | 241 | ||
@@ -228,7 +250,7 @@ static void spi_sirfsoc_tx_word_u32(struct sirfsoc_spi *sspi) | |||
228 | } | 250 | } |
229 | 251 | ||
230 | writel(data, sspi->base + SIRFSOC_SPI_TXFIFO_DATA); | 252 | writel(data, sspi->base + SIRFSOC_SPI_TXFIFO_DATA); |
231 | sspi->left_tx_cnt--; | 253 | sspi->left_tx_word--; |
232 | } | 254 | } |
233 | 255 | ||
234 | static irqreturn_t spi_sirfsoc_irq(int irq, void *dev_id) | 256 | static irqreturn_t spi_sirfsoc_irq(int irq, void *dev_id) |
@@ -241,7 +263,7 @@ static irqreturn_t spi_sirfsoc_irq(int irq, void *dev_id) | |||
241 | /* Error Conditions */ | 263 | /* Error Conditions */ |
242 | if (spi_stat & SIRFSOC_SPI_RX_OFLOW || | 264 | if (spi_stat & SIRFSOC_SPI_RX_OFLOW || |
243 | spi_stat & SIRFSOC_SPI_TX_UFLOW) { | 265 | spi_stat & SIRFSOC_SPI_TX_UFLOW) { |
244 | complete(&sspi->done); | 266 | complete(&sspi->rx_done); |
245 | writel(0x0, sspi->base + SIRFSOC_SPI_INT_EN); | 267 | writel(0x0, sspi->base + SIRFSOC_SPI_INT_EN); |
246 | } | 268 | } |
247 | 269 | ||
@@ -249,50 +271,61 @@ static irqreturn_t spi_sirfsoc_irq(int irq, void *dev_id) | |||
249 | | SIRFSOC_SPI_RXFIFO_THD_REACH)) | 271 | | SIRFSOC_SPI_RXFIFO_THD_REACH)) |
250 | while (!((readl(sspi->base + SIRFSOC_SPI_RXFIFO_STATUS) | 272 | while (!((readl(sspi->base + SIRFSOC_SPI_RXFIFO_STATUS) |
251 | & SIRFSOC_SPI_FIFO_EMPTY)) && | 273 | & SIRFSOC_SPI_FIFO_EMPTY)) && |
252 | sspi->left_rx_cnt) | 274 | sspi->left_rx_word) |
253 | sspi->rx_word(sspi); | 275 | sspi->rx_word(sspi); |
254 | 276 | ||
255 | if (spi_stat & (SIRFSOC_SPI_FIFO_EMPTY | 277 | if (spi_stat & (SIRFSOC_SPI_FIFO_EMPTY |
256 | | SIRFSOC_SPI_TXFIFO_THD_REACH)) | 278 | | SIRFSOC_SPI_TXFIFO_THD_REACH)) |
257 | while (!((readl(sspi->base + SIRFSOC_SPI_TXFIFO_STATUS) | 279 | while (!((readl(sspi->base + SIRFSOC_SPI_TXFIFO_STATUS) |
258 | & SIRFSOC_SPI_FIFO_FULL)) && | 280 | & SIRFSOC_SPI_FIFO_FULL)) && |
259 | sspi->left_tx_cnt) | 281 | sspi->left_tx_word) |
260 | sspi->tx_word(sspi); | 282 | sspi->tx_word(sspi); |
261 | 283 | ||
262 | /* Received all words */ | 284 | /* Received all words */ |
263 | if ((sspi->left_rx_cnt == 0) && (sspi->left_tx_cnt == 0)) { | 285 | if ((sspi->left_rx_word == 0) && (sspi->left_tx_word == 0)) { |
264 | complete(&sspi->done); | 286 | complete(&sspi->rx_done); |
265 | writel(0x0, sspi->base + SIRFSOC_SPI_INT_EN); | 287 | writel(0x0, sspi->base + SIRFSOC_SPI_INT_EN); |
266 | } | 288 | } |
267 | return IRQ_HANDLED; | 289 | return IRQ_HANDLED; |
268 | } | 290 | } |
269 | 291 | ||
292 | static void spi_sirfsoc_dma_fini_callback(void *data) | ||
293 | { | ||
294 | struct completion *dma_complete = data; | ||
295 | |||
296 | complete(dma_complete); | ||
297 | } | ||
298 | |||
270 | static int spi_sirfsoc_transfer(struct spi_device *spi, struct spi_transfer *t) | 299 | static int spi_sirfsoc_transfer(struct spi_device *spi, struct spi_transfer *t) |
271 | { | 300 | { |
272 | struct sirfsoc_spi *sspi; | 301 | struct sirfsoc_spi *sspi; |
273 | int timeout = t->len * 10; | 302 | int timeout = t->len * 10; |
274 | sspi = spi_master_get_devdata(spi->master); | 303 | sspi = spi_master_get_devdata(spi->master); |
275 | 304 | ||
276 | sspi->tx = t->tx_buf; | 305 | sspi->tx = t->tx_buf ? t->tx_buf : sspi->dummypage; |
277 | sspi->rx = t->rx_buf; | 306 | sspi->rx = t->rx_buf ? t->rx_buf : sspi->dummypage; |
278 | sspi->left_tx_cnt = sspi->left_rx_cnt = t->len; | 307 | sspi->left_tx_word = sspi->left_rx_word = t->len / sspi->word_width; |
279 | INIT_COMPLETION(sspi->done); | 308 | INIT_COMPLETION(sspi->rx_done); |
309 | INIT_COMPLETION(sspi->tx_done); | ||
280 | 310 | ||
281 | writel(SIRFSOC_SPI_INT_MASK_ALL, sspi->base + SIRFSOC_SPI_INT_STATUS); | 311 | writel(SIRFSOC_SPI_INT_MASK_ALL, sspi->base + SIRFSOC_SPI_INT_STATUS); |
282 | 312 | ||
283 | if (t->len == 1) { | 313 | if (sspi->left_tx_word == 1) { |
284 | writel(readl(sspi->base + SIRFSOC_SPI_CTRL) | | 314 | writel(readl(sspi->base + SIRFSOC_SPI_CTRL) | |
285 | SIRFSOC_SPI_ENA_AUTO_CLR, | 315 | SIRFSOC_SPI_ENA_AUTO_CLR, |
286 | sspi->base + SIRFSOC_SPI_CTRL); | 316 | sspi->base + SIRFSOC_SPI_CTRL); |
287 | writel(0, sspi->base + SIRFSOC_SPI_TX_DMA_IO_LEN); | 317 | writel(0, sspi->base + SIRFSOC_SPI_TX_DMA_IO_LEN); |
288 | writel(0, sspi->base + SIRFSOC_SPI_RX_DMA_IO_LEN); | 318 | writel(0, sspi->base + SIRFSOC_SPI_RX_DMA_IO_LEN); |
289 | } else if ((t->len > 1) && (t->len < SIRFSOC_SPI_DAT_FRM_LEN_MAX)) { | 319 | } else if ((sspi->left_tx_word > 1) && (sspi->left_tx_word < |
320 | SIRFSOC_SPI_DAT_FRM_LEN_MAX)) { | ||
290 | writel(readl(sspi->base + SIRFSOC_SPI_CTRL) | | 321 | writel(readl(sspi->base + SIRFSOC_SPI_CTRL) | |
291 | SIRFSOC_SPI_MUL_DAT_MODE | | 322 | SIRFSOC_SPI_MUL_DAT_MODE | |
292 | SIRFSOC_SPI_ENA_AUTO_CLR, | 323 | SIRFSOC_SPI_ENA_AUTO_CLR, |
293 | sspi->base + SIRFSOC_SPI_CTRL); | 324 | sspi->base + SIRFSOC_SPI_CTRL); |
294 | writel(t->len - 1, sspi->base + SIRFSOC_SPI_TX_DMA_IO_LEN); | 325 | writel(sspi->left_tx_word - 1, |
295 | writel(t->len - 1, sspi->base + SIRFSOC_SPI_RX_DMA_IO_LEN); | 326 | sspi->base + SIRFSOC_SPI_TX_DMA_IO_LEN); |
327 | writel(sspi->left_tx_word - 1, | ||
328 | sspi->base + SIRFSOC_SPI_RX_DMA_IO_LEN); | ||
296 | } else { | 329 | } else { |
297 | writel(readl(sspi->base + SIRFSOC_SPI_CTRL), | 330 | writel(readl(sspi->base + SIRFSOC_SPI_CTRL), |
298 | sspi->base + SIRFSOC_SPI_CTRL); | 331 | sspi->base + SIRFSOC_SPI_CTRL); |
@@ -305,17 +338,64 @@ static int spi_sirfsoc_transfer(struct spi_device *spi, struct spi_transfer *t) | |||
305 | writel(SIRFSOC_SPI_FIFO_START, sspi->base + SIRFSOC_SPI_RXFIFO_OP); | 338 | writel(SIRFSOC_SPI_FIFO_START, sspi->base + SIRFSOC_SPI_RXFIFO_OP); |
306 | writel(SIRFSOC_SPI_FIFO_START, sspi->base + SIRFSOC_SPI_TXFIFO_OP); | 339 | writel(SIRFSOC_SPI_FIFO_START, sspi->base + SIRFSOC_SPI_TXFIFO_OP); |
307 | 340 | ||
308 | /* Send the first word to trigger the whole tx/rx process */ | 341 | if (IS_DMA_VALID(t)) { |
309 | sspi->tx_word(sspi); | 342 | struct dma_async_tx_descriptor *rx_desc, *tx_desc; |
343 | |||
344 | sspi->dst_start = dma_map_single(&spi->dev, sspi->rx, t->len, DMA_FROM_DEVICE); | ||
345 | rx_desc = dmaengine_prep_slave_single(sspi->rx_chan, | ||
346 | sspi->dst_start, t->len, DMA_DEV_TO_MEM, | ||
347 | DMA_PREP_INTERRUPT | DMA_CTRL_ACK); | ||
348 | rx_desc->callback = spi_sirfsoc_dma_fini_callback; | ||
349 | rx_desc->callback_param = &sspi->rx_done; | ||
350 | |||
351 | sspi->src_start = dma_map_single(&spi->dev, (void *)sspi->tx, t->len, DMA_TO_DEVICE); | ||
352 | tx_desc = dmaengine_prep_slave_single(sspi->tx_chan, | ||
353 | sspi->src_start, t->len, DMA_MEM_TO_DEV, | ||
354 | DMA_PREP_INTERRUPT | DMA_CTRL_ACK); | ||
355 | tx_desc->callback = spi_sirfsoc_dma_fini_callback; | ||
356 | tx_desc->callback_param = &sspi->tx_done; | ||
357 | |||
358 | dmaengine_submit(tx_desc); | ||
359 | dmaengine_submit(rx_desc); | ||
360 | dma_async_issue_pending(sspi->tx_chan); | ||
361 | dma_async_issue_pending(sspi->rx_chan); | ||
362 | } else { | ||
363 | /* Send the first word to trigger the whole tx/rx process */ | ||
364 | sspi->tx_word(sspi); | ||
365 | |||
366 | writel(SIRFSOC_SPI_RX_OFLOW_INT_EN | SIRFSOC_SPI_TX_UFLOW_INT_EN | | ||
367 | SIRFSOC_SPI_RXFIFO_THD_INT_EN | SIRFSOC_SPI_TXFIFO_THD_INT_EN | | ||
368 | SIRFSOC_SPI_FRM_END_INT_EN | SIRFSOC_SPI_RXFIFO_FULL_INT_EN | | ||
369 | SIRFSOC_SPI_TXFIFO_EMPTY_INT_EN, sspi->base + SIRFSOC_SPI_INT_EN); | ||
370 | } | ||
310 | 371 | ||
311 | writel(SIRFSOC_SPI_RX_OFLOW_INT_EN | SIRFSOC_SPI_TX_UFLOW_INT_EN | | ||
312 | SIRFSOC_SPI_RXFIFO_THD_INT_EN | SIRFSOC_SPI_TXFIFO_THD_INT_EN | | ||
313 | SIRFSOC_SPI_FRM_END_INT_EN | SIRFSOC_SPI_RXFIFO_FULL_INT_EN | | ||
314 | SIRFSOC_SPI_TXFIFO_EMPTY_INT_EN, sspi->base + SIRFSOC_SPI_INT_EN); | ||
315 | writel(SIRFSOC_SPI_RX_EN | SIRFSOC_SPI_TX_EN, sspi->base + SIRFSOC_SPI_TX_RX_EN); | 372 | writel(SIRFSOC_SPI_RX_EN | SIRFSOC_SPI_TX_EN, sspi->base + SIRFSOC_SPI_TX_RX_EN); |
316 | 373 | ||
317 | if (wait_for_completion_timeout(&sspi->done, timeout) == 0) | 374 | if (!IS_DMA_VALID(t)) { /* for PIO */ |
375 | if (wait_for_completion_timeout(&sspi->rx_done, timeout) == 0) | ||
376 | dev_err(&spi->dev, "transfer timeout\n"); | ||
377 | } else if (wait_for_completion_timeout(&sspi->rx_done, timeout) == 0) { | ||
318 | dev_err(&spi->dev, "transfer timeout\n"); | 378 | dev_err(&spi->dev, "transfer timeout\n"); |
379 | dmaengine_terminate_all(sspi->rx_chan); | ||
380 | } else | ||
381 | sspi->left_rx_word = 0; | ||
382 | |||
383 | /* | ||
384 | * we only wait tx-done event if transferring by DMA. for PIO, | ||
385 | * we get rx data by writing tx data, so if rx is done, tx has | ||
386 | * done earlier | ||
387 | */ | ||
388 | if (IS_DMA_VALID(t)) { | ||
389 | if (wait_for_completion_timeout(&sspi->tx_done, timeout) == 0) { | ||
390 | dev_err(&spi->dev, "transfer timeout\n"); | ||
391 | dmaengine_terminate_all(sspi->tx_chan); | ||
392 | } | ||
393 | } | ||
394 | |||
395 | if (IS_DMA_VALID(t)) { | ||
396 | dma_unmap_single(&spi->dev, sspi->src_start, t->len, DMA_TO_DEVICE); | ||
397 | dma_unmap_single(&spi->dev, sspi->dst_start, t->len, DMA_FROM_DEVICE); | ||
398 | } | ||
319 | 399 | ||
320 | /* TX, RX FIFO stop */ | 400 | /* TX, RX FIFO stop */ |
321 | writel(0, sspi->base + SIRFSOC_SPI_RXFIFO_OP); | 401 | writel(0, sspi->base + SIRFSOC_SPI_RXFIFO_OP); |
@@ -323,7 +403,7 @@ static int spi_sirfsoc_transfer(struct spi_device *spi, struct spi_transfer *t) | |||
323 | writel(0, sspi->base + SIRFSOC_SPI_TX_RX_EN); | 403 | writel(0, sspi->base + SIRFSOC_SPI_TX_RX_EN); |
324 | writel(0, sspi->base + SIRFSOC_SPI_INT_EN); | 404 | writel(0, sspi->base + SIRFSOC_SPI_INT_EN); |
325 | 405 | ||
326 | return t->len - sspi->left_rx_cnt; | 406 | return t->len - sspi->left_rx_word * sspi->word_width; |
327 | } | 407 | } |
328 | 408 | ||
329 | static void spi_sirfsoc_chipselect(struct spi_device *spi, int value) | 409 | static void spi_sirfsoc_chipselect(struct spi_device *spi, int value) |
@@ -332,7 +412,6 @@ static void spi_sirfsoc_chipselect(struct spi_device *spi, int value) | |||
332 | 412 | ||
333 | if (sspi->chipselect[spi->chip_select] == 0) { | 413 | if (sspi->chipselect[spi->chip_select] == 0) { |
334 | u32 regval = readl(sspi->base + SIRFSOC_SPI_CTRL); | 414 | u32 regval = readl(sspi->base + SIRFSOC_SPI_CTRL); |
335 | regval |= SIRFSOC_SPI_CS_IO_OUT; | ||
336 | switch (value) { | 415 | switch (value) { |
337 | case BITBANG_CS_ACTIVE: | 416 | case BITBANG_CS_ACTIVE: |
338 | if (spi->mode & SPI_CS_HIGH) | 417 | if (spi->mode & SPI_CS_HIGH) |
@@ -369,11 +448,7 @@ spi_sirfsoc_setup_transfer(struct spi_device *spi, struct spi_transfer *t) | |||
369 | bits_per_word = (t) ? t->bits_per_word : spi->bits_per_word; | 448 | bits_per_word = (t) ? t->bits_per_word : spi->bits_per_word; |
370 | hz = t && t->speed_hz ? t->speed_hz : spi->max_speed_hz; | 449 | hz = t && t->speed_hz ? t->speed_hz : spi->max_speed_hz; |
371 | 450 | ||
372 | /* Enable IO mode for RX, TX */ | ||
373 | writel(SIRFSOC_SPI_IO_MODE_SEL, sspi->base + SIRFSOC_SPI_TX_DMA_IO_CTRL); | ||
374 | writel(SIRFSOC_SPI_IO_MODE_SEL, sspi->base + SIRFSOC_SPI_RX_DMA_IO_CTRL); | ||
375 | regval = (sspi->ctrl_freq / (2 * hz)) - 1; | 451 | regval = (sspi->ctrl_freq / (2 * hz)) - 1; |
376 | |||
377 | if (regval > 0xFFFF || regval < 0) { | 452 | if (regval > 0xFFFF || regval < 0) { |
378 | dev_err(&spi->dev, "Speed %d not supported\n", hz); | 453 | dev_err(&spi->dev, "Speed %d not supported\n", hz); |
379 | return -EINVAL; | 454 | return -EINVAL; |
@@ -388,6 +463,7 @@ spi_sirfsoc_setup_transfer(struct spi_device *spi, struct spi_transfer *t) | |||
388 | SIRFSOC_SPI_FIFO_WIDTH_BYTE; | 463 | SIRFSOC_SPI_FIFO_WIDTH_BYTE; |
389 | rxfifo_ctrl = SIRFSOC_SPI_FIFO_THD(SIRFSOC_SPI_FIFO_SIZE / 2) | | 464 | rxfifo_ctrl = SIRFSOC_SPI_FIFO_THD(SIRFSOC_SPI_FIFO_SIZE / 2) | |
390 | SIRFSOC_SPI_FIFO_WIDTH_BYTE; | 465 | SIRFSOC_SPI_FIFO_WIDTH_BYTE; |
466 | sspi->word_width = 1; | ||
391 | break; | 467 | break; |
392 | case 12: | 468 | case 12: |
393 | case 16: | 469 | case 16: |
@@ -399,6 +475,7 @@ spi_sirfsoc_setup_transfer(struct spi_device *spi, struct spi_transfer *t) | |||
399 | SIRFSOC_SPI_FIFO_WIDTH_WORD; | 475 | SIRFSOC_SPI_FIFO_WIDTH_WORD; |
400 | rxfifo_ctrl = SIRFSOC_SPI_FIFO_THD(SIRFSOC_SPI_FIFO_SIZE / 2) | | 476 | rxfifo_ctrl = SIRFSOC_SPI_FIFO_THD(SIRFSOC_SPI_FIFO_SIZE / 2) | |
401 | SIRFSOC_SPI_FIFO_WIDTH_WORD; | 477 | SIRFSOC_SPI_FIFO_WIDTH_WORD; |
478 | sspi->word_width = 2; | ||
402 | break; | 479 | break; |
403 | case 32: | 480 | case 32: |
404 | regval |= SIRFSOC_SPI_TRAN_DAT_FORMAT_32; | 481 | regval |= SIRFSOC_SPI_TRAN_DAT_FORMAT_32; |
@@ -408,6 +485,7 @@ spi_sirfsoc_setup_transfer(struct spi_device *spi, struct spi_transfer *t) | |||
408 | SIRFSOC_SPI_FIFO_WIDTH_DWORD; | 485 | SIRFSOC_SPI_FIFO_WIDTH_DWORD; |
409 | rxfifo_ctrl = SIRFSOC_SPI_FIFO_THD(SIRFSOC_SPI_FIFO_SIZE / 2) | | 486 | rxfifo_ctrl = SIRFSOC_SPI_FIFO_THD(SIRFSOC_SPI_FIFO_SIZE / 2) | |
410 | SIRFSOC_SPI_FIFO_WIDTH_DWORD; | 487 | SIRFSOC_SPI_FIFO_WIDTH_DWORD; |
488 | sspi->word_width = 4; | ||
411 | break; | 489 | break; |
412 | default: | 490 | default: |
413 | BUG(); | 491 | BUG(); |
@@ -442,6 +520,17 @@ spi_sirfsoc_setup_transfer(struct spi_device *spi, struct spi_transfer *t) | |||
442 | writel(rxfifo_ctrl, sspi->base + SIRFSOC_SPI_RXFIFO_CTRL); | 520 | writel(rxfifo_ctrl, sspi->base + SIRFSOC_SPI_RXFIFO_CTRL); |
443 | 521 | ||
444 | writel(regval, sspi->base + SIRFSOC_SPI_CTRL); | 522 | writel(regval, sspi->base + SIRFSOC_SPI_CTRL); |
523 | |||
524 | if (IS_DMA_VALID(t)) { | ||
525 | /* Enable DMA mode for RX, TX */ | ||
526 | writel(0, sspi->base + SIRFSOC_SPI_TX_DMA_IO_CTRL); | ||
527 | writel(SIRFSOC_SPI_RX_DMA_FLUSH, sspi->base + SIRFSOC_SPI_RX_DMA_IO_CTRL); | ||
528 | } else { | ||
529 | /* Enable IO mode for RX, TX */ | ||
530 | writel(SIRFSOC_SPI_IO_MODE_SEL, sspi->base + SIRFSOC_SPI_TX_DMA_IO_CTRL); | ||
531 | writel(SIRFSOC_SPI_IO_MODE_SEL, sspi->base + SIRFSOC_SPI_RX_DMA_IO_CTRL); | ||
532 | } | ||
533 | |||
445 | return 0; | 534 | return 0; |
446 | } | 535 | } |
447 | 536 | ||
@@ -466,6 +555,8 @@ static int spi_sirfsoc_probe(struct platform_device *pdev) | |||
466 | struct spi_master *master; | 555 | struct spi_master *master; |
467 | struct resource *mem_res; | 556 | struct resource *mem_res; |
468 | int num_cs, cs_gpio, irq; | 557 | int num_cs, cs_gpio, irq; |
558 | u32 rx_dma_ch, tx_dma_ch; | ||
559 | dma_cap_mask_t dma_cap_mask; | ||
469 | int i; | 560 | int i; |
470 | int ret; | 561 | int ret; |
471 | 562 | ||
@@ -476,6 +567,20 @@ static int spi_sirfsoc_probe(struct platform_device *pdev) | |||
476 | goto err_cs; | 567 | goto err_cs; |
477 | } | 568 | } |
478 | 569 | ||
570 | ret = of_property_read_u32(pdev->dev.of_node, | ||
571 | "sirf,spi-dma-rx-channel", &rx_dma_ch); | ||
572 | if (ret < 0) { | ||
573 | dev_err(&pdev->dev, "Unable to get rx dma channel\n"); | ||
574 | goto err_cs; | ||
575 | } | ||
576 | |||
577 | ret = of_property_read_u32(pdev->dev.of_node, | ||
578 | "sirf,spi-dma-tx-channel", &tx_dma_ch); | ||
579 | if (ret < 0) { | ||
580 | dev_err(&pdev->dev, "Unable to get tx dma channel\n"); | ||
581 | goto err_cs; | ||
582 | } | ||
583 | |||
479 | master = spi_alloc_master(&pdev->dev, sizeof(*sspi) + sizeof(int) * num_cs); | 584 | master = spi_alloc_master(&pdev->dev, sizeof(*sspi) + sizeof(int) * num_cs); |
480 | if (!master) { | 585 | if (!master) { |
481 | dev_err(&pdev->dev, "Unable to allocate SPI master\n"); | 586 | dev_err(&pdev->dev, "Unable to allocate SPI master\n"); |
@@ -484,12 +589,6 @@ static int spi_sirfsoc_probe(struct platform_device *pdev) | |||
484 | platform_set_drvdata(pdev, master); | 589 | platform_set_drvdata(pdev, master); |
485 | sspi = spi_master_get_devdata(master); | 590 | sspi = spi_master_get_devdata(master); |
486 | 591 | ||
487 | mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
488 | if (!mem_res) { | ||
489 | dev_err(&pdev->dev, "Unable to get IO resource\n"); | ||
490 | ret = -ENODEV; | ||
491 | goto free_master; | ||
492 | } | ||
493 | master->num_chipselect = num_cs; | 592 | master->num_chipselect = num_cs; |
494 | 593 | ||
495 | for (i = 0; i < master->num_chipselect; i++) { | 594 | for (i = 0; i < master->num_chipselect; i++) { |
@@ -516,6 +615,7 @@ static int spi_sirfsoc_probe(struct platform_device *pdev) | |||
516 | } | 615 | } |
517 | } | 616 | } |
518 | 617 | ||
618 | mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
519 | sspi->base = devm_ioremap_resource(&pdev->dev, mem_res); | 619 | sspi->base = devm_ioremap_resource(&pdev->dev, mem_res); |
520 | if (IS_ERR(sspi->base)) { | 620 | if (IS_ERR(sspi->base)) { |
521 | ret = PTR_ERR(sspi->base); | 621 | ret = PTR_ERR(sspi->base); |
@@ -538,19 +638,40 @@ static int spi_sirfsoc_probe(struct platform_device *pdev) | |||
538 | sspi->bitbang.txrx_bufs = spi_sirfsoc_transfer; | 638 | sspi->bitbang.txrx_bufs = spi_sirfsoc_transfer; |
539 | sspi->bitbang.master->setup = spi_sirfsoc_setup; | 639 | sspi->bitbang.master->setup = spi_sirfsoc_setup; |
540 | master->bus_num = pdev->id; | 640 | master->bus_num = pdev->id; |
641 | master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_LSB_FIRST | SPI_CS_HIGH; | ||
541 | master->bits_per_word_mask = SPI_BPW_MASK(8) | SPI_BPW_MASK(12) | | 642 | master->bits_per_word_mask = SPI_BPW_MASK(8) | SPI_BPW_MASK(12) | |
542 | SPI_BPW_MASK(16) | SPI_BPW_MASK(32); | 643 | SPI_BPW_MASK(16) | SPI_BPW_MASK(32); |
543 | sspi->bitbang.master->dev.of_node = pdev->dev.of_node; | 644 | sspi->bitbang.master->dev.of_node = pdev->dev.of_node; |
544 | 645 | ||
646 | /* request DMA channels */ | ||
647 | dma_cap_zero(dma_cap_mask); | ||
648 | dma_cap_set(DMA_INTERLEAVE, dma_cap_mask); | ||
649 | |||
650 | sspi->rx_chan = dma_request_channel(dma_cap_mask, (dma_filter_fn)sirfsoc_dma_filter_id, | ||
651 | (void *)rx_dma_ch); | ||
652 | if (!sspi->rx_chan) { | ||
653 | dev_err(&pdev->dev, "can not allocate rx dma channel\n"); | ||
654 | ret = -ENODEV; | ||
655 | goto free_master; | ||
656 | } | ||
657 | sspi->tx_chan = dma_request_channel(dma_cap_mask, (dma_filter_fn)sirfsoc_dma_filter_id, | ||
658 | (void *)tx_dma_ch); | ||
659 | if (!sspi->tx_chan) { | ||
660 | dev_err(&pdev->dev, "can not allocate tx dma channel\n"); | ||
661 | ret = -ENODEV; | ||
662 | goto free_rx_dma; | ||
663 | } | ||
664 | |||
545 | sspi->clk = clk_get(&pdev->dev, NULL); | 665 | sspi->clk = clk_get(&pdev->dev, NULL); |
546 | if (IS_ERR(sspi->clk)) { | 666 | if (IS_ERR(sspi->clk)) { |
547 | ret = -EINVAL; | 667 | ret = PTR_ERR(sspi->clk); |
548 | goto free_master; | 668 | goto free_tx_dma; |
549 | } | 669 | } |
550 | clk_prepare_enable(sspi->clk); | 670 | clk_prepare_enable(sspi->clk); |
551 | sspi->ctrl_freq = clk_get_rate(sspi->clk); | 671 | sspi->ctrl_freq = clk_get_rate(sspi->clk); |
552 | 672 | ||
553 | init_completion(&sspi->done); | 673 | init_completion(&sspi->rx_done); |
674 | init_completion(&sspi->tx_done); | ||
554 | 675 | ||
555 | writel(SIRFSOC_SPI_FIFO_RESET, sspi->base + SIRFSOC_SPI_RXFIFO_OP); | 676 | writel(SIRFSOC_SPI_FIFO_RESET, sspi->base + SIRFSOC_SPI_RXFIFO_OP); |
556 | writel(SIRFSOC_SPI_FIFO_RESET, sspi->base + SIRFSOC_SPI_TXFIFO_OP); | 677 | writel(SIRFSOC_SPI_FIFO_RESET, sspi->base + SIRFSOC_SPI_TXFIFO_OP); |
@@ -559,17 +680,28 @@ static int spi_sirfsoc_probe(struct platform_device *pdev) | |||
559 | /* We are not using dummy delay between command and data */ | 680 | /* We are not using dummy delay between command and data */ |
560 | writel(0, sspi->base + SIRFSOC_SPI_DUMMY_DELAY_CTL); | 681 | writel(0, sspi->base + SIRFSOC_SPI_DUMMY_DELAY_CTL); |
561 | 682 | ||
683 | sspi->dummypage = kmalloc(2 * PAGE_SIZE, GFP_KERNEL); | ||
684 | if (!sspi->dummypage) { | ||
685 | ret = -ENOMEM; | ||
686 | goto free_clk; | ||
687 | } | ||
688 | |||
562 | ret = spi_bitbang_start(&sspi->bitbang); | 689 | ret = spi_bitbang_start(&sspi->bitbang); |
563 | if (ret) | 690 | if (ret) |
564 | goto free_clk; | 691 | goto free_dummypage; |
565 | 692 | ||
566 | dev_info(&pdev->dev, "registerred, bus number = %d\n", master->bus_num); | 693 | dev_info(&pdev->dev, "registerred, bus number = %d\n", master->bus_num); |
567 | 694 | ||
568 | return 0; | 695 | return 0; |
569 | 696 | free_dummypage: | |
697 | kfree(sspi->dummypage); | ||
570 | free_clk: | 698 | free_clk: |
571 | clk_disable_unprepare(sspi->clk); | 699 | clk_disable_unprepare(sspi->clk); |
572 | clk_put(sspi->clk); | 700 | clk_put(sspi->clk); |
701 | free_tx_dma: | ||
702 | dma_release_channel(sspi->tx_chan); | ||
703 | free_rx_dma: | ||
704 | dma_release_channel(sspi->rx_chan); | ||
573 | free_master: | 705 | free_master: |
574 | spi_master_put(master); | 706 | spi_master_put(master); |
575 | err_cs: | 707 | err_cs: |
@@ -590,8 +722,11 @@ static int spi_sirfsoc_remove(struct platform_device *pdev) | |||
590 | if (sspi->chipselect[i] > 0) | 722 | if (sspi->chipselect[i] > 0) |
591 | gpio_free(sspi->chipselect[i]); | 723 | gpio_free(sspi->chipselect[i]); |
592 | } | 724 | } |
725 | kfree(sspi->dummypage); | ||
593 | clk_disable_unprepare(sspi->clk); | 726 | clk_disable_unprepare(sspi->clk); |
594 | clk_put(sspi->clk); | 727 | clk_put(sspi->clk); |
728 | dma_release_channel(sspi->rx_chan); | ||
729 | dma_release_channel(sspi->tx_chan); | ||
595 | spi_master_put(master); | 730 | spi_master_put(master); |
596 | return 0; | 731 | return 0; |
597 | } | 732 | } |