diff options
Diffstat (limited to 'drivers/spi')
-rw-r--r-- | drivers/spi/spi-dw.c | 1 | ||||
-rw-r--r-- | drivers/spi/spi-orion.c | 2 | ||||
-rw-r--r-- | drivers/spi/spi-pl022.c | 2 | ||||
-rw-r--r-- | drivers/spi/spi-rockchip.c | 50 | ||||
-rw-r--r-- | drivers/spi/spidev.c | 79 |
5 files changed, 93 insertions, 41 deletions
diff --git a/drivers/spi/spi-dw.c b/drivers/spi/spi-dw.c index 729215885250..72e12bad14b9 100644 --- a/drivers/spi/spi-dw.c +++ b/drivers/spi/spi-dw.c | |||
@@ -669,6 +669,7 @@ int dw_spi_add_host(struct device *dev, struct dw_spi *dws) | |||
669 | master->cleanup = dw_spi_cleanup; | 669 | master->cleanup = dw_spi_cleanup; |
670 | master->transfer_one_message = dw_spi_transfer_one_message; | 670 | master->transfer_one_message = dw_spi_transfer_one_message; |
671 | master->max_speed_hz = dws->max_freq; | 671 | master->max_speed_hz = dws->max_freq; |
672 | master->dev.of_node = dev->of_node; | ||
672 | 673 | ||
673 | /* Basic HW init */ | 674 | /* Basic HW init */ |
674 | spi_hw_init(dws); | 675 | spi_hw_init(dws); |
diff --git a/drivers/spi/spi-orion.c b/drivers/spi/spi-orion.c index 835cdda6f4f5..c76b7d7879df 100644 --- a/drivers/spi/spi-orion.c +++ b/drivers/spi/spi-orion.c | |||
@@ -454,7 +454,7 @@ static int orion_spi_probe(struct platform_device *pdev) | |||
454 | spi->master = master; | 454 | spi->master = master; |
455 | 455 | ||
456 | of_id = of_match_device(orion_spi_of_match_table, &pdev->dev); | 456 | of_id = of_match_device(orion_spi_of_match_table, &pdev->dev); |
457 | devdata = of_id->data; | 457 | devdata = (of_id) ? of_id->data : &orion_spi_dev_data; |
458 | spi->devdata = devdata; | 458 | spi->devdata = devdata; |
459 | 459 | ||
460 | spi->clk = devm_clk_get(&pdev->dev, NULL); | 460 | spi->clk = devm_clk_get(&pdev->dev, NULL); |
diff --git a/drivers/spi/spi-pl022.c b/drivers/spi/spi-pl022.c index f35f723816ea..fc2dd8441608 100644 --- a/drivers/spi/spi-pl022.c +++ b/drivers/spi/spi-pl022.c | |||
@@ -1106,7 +1106,7 @@ err_rxdesc: | |||
1106 | pl022->sgt_tx.nents, DMA_TO_DEVICE); | 1106 | pl022->sgt_tx.nents, DMA_TO_DEVICE); |
1107 | err_tx_sgmap: | 1107 | err_tx_sgmap: |
1108 | dma_unmap_sg(rxchan->device->dev, pl022->sgt_rx.sgl, | 1108 | dma_unmap_sg(rxchan->device->dev, pl022->sgt_rx.sgl, |
1109 | pl022->sgt_tx.nents, DMA_FROM_DEVICE); | 1109 | pl022->sgt_rx.nents, DMA_FROM_DEVICE); |
1110 | err_rx_sgmap: | 1110 | err_rx_sgmap: |
1111 | sg_free_table(&pl022->sgt_tx); | 1111 | sg_free_table(&pl022->sgt_tx); |
1112 | err_alloc_tx_sg: | 1112 | err_alloc_tx_sg: |
diff --git a/drivers/spi/spi-rockchip.c b/drivers/spi/spi-rockchip.c index f96ea8a38d64..87bc16f491f0 100644 --- a/drivers/spi/spi-rockchip.c +++ b/drivers/spi/spi-rockchip.c | |||
@@ -145,6 +145,9 @@ | |||
145 | #define RXBUSY (1 << 0) | 145 | #define RXBUSY (1 << 0) |
146 | #define TXBUSY (1 << 1) | 146 | #define TXBUSY (1 << 1) |
147 | 147 | ||
148 | /* sclk_out: spi master internal logic in rk3x can support 50Mhz */ | ||
149 | #define MAX_SCLK_OUT 50000000 | ||
150 | |||
148 | enum rockchip_ssi_type { | 151 | enum rockchip_ssi_type { |
149 | SSI_MOTO_SPI = 0, | 152 | SSI_MOTO_SPI = 0, |
150 | SSI_TI_SSP, | 153 | SSI_TI_SSP, |
@@ -325,6 +328,8 @@ static int rockchip_spi_unprepare_message(struct spi_master *master, | |||
325 | 328 | ||
326 | spin_unlock_irqrestore(&rs->lock, flags); | 329 | spin_unlock_irqrestore(&rs->lock, flags); |
327 | 330 | ||
331 | spi_enable_chip(rs, 0); | ||
332 | |||
328 | return 0; | 333 | return 0; |
329 | } | 334 | } |
330 | 335 | ||
@@ -381,6 +386,8 @@ static int rockchip_spi_pio_transfer(struct rockchip_spi *rs) | |||
381 | if (rs->tx) | 386 | if (rs->tx) |
382 | wait_for_idle(rs); | 387 | wait_for_idle(rs); |
383 | 388 | ||
389 | spi_enable_chip(rs, 0); | ||
390 | |||
384 | return 0; | 391 | return 0; |
385 | } | 392 | } |
386 | 393 | ||
@@ -392,8 +399,10 @@ static void rockchip_spi_dma_rxcb(void *data) | |||
392 | spin_lock_irqsave(&rs->lock, flags); | 399 | spin_lock_irqsave(&rs->lock, flags); |
393 | 400 | ||
394 | rs->state &= ~RXBUSY; | 401 | rs->state &= ~RXBUSY; |
395 | if (!(rs->state & TXBUSY)) | 402 | if (!(rs->state & TXBUSY)) { |
403 | spi_enable_chip(rs, 0); | ||
396 | spi_finalize_current_transfer(rs->master); | 404 | spi_finalize_current_transfer(rs->master); |
405 | } | ||
397 | 406 | ||
398 | spin_unlock_irqrestore(&rs->lock, flags); | 407 | spin_unlock_irqrestore(&rs->lock, flags); |
399 | } | 408 | } |
@@ -409,8 +418,10 @@ static void rockchip_spi_dma_txcb(void *data) | |||
409 | spin_lock_irqsave(&rs->lock, flags); | 418 | spin_lock_irqsave(&rs->lock, flags); |
410 | 419 | ||
411 | rs->state &= ~TXBUSY; | 420 | rs->state &= ~TXBUSY; |
412 | if (!(rs->state & RXBUSY)) | 421 | if (!(rs->state & RXBUSY)) { |
422 | spi_enable_chip(rs, 0); | ||
413 | spi_finalize_current_transfer(rs->master); | 423 | spi_finalize_current_transfer(rs->master); |
424 | } | ||
414 | 425 | ||
415 | spin_unlock_irqrestore(&rs->lock, flags); | 426 | spin_unlock_irqrestore(&rs->lock, flags); |
416 | } | 427 | } |
@@ -496,12 +507,19 @@ static void rockchip_spi_config(struct rockchip_spi *rs) | |||
496 | dmacr |= RF_DMA_EN; | 507 | dmacr |= RF_DMA_EN; |
497 | } | 508 | } |
498 | 509 | ||
510 | if (WARN_ON(rs->speed > MAX_SCLK_OUT)) | ||
511 | rs->speed = MAX_SCLK_OUT; | ||
512 | |||
513 | /* the minimum divsor is 2 */ | ||
514 | if (rs->max_freq < 2 * rs->speed) { | ||
515 | clk_set_rate(rs->spiclk, 2 * rs->speed); | ||
516 | rs->max_freq = clk_get_rate(rs->spiclk); | ||
517 | } | ||
518 | |||
499 | /* div doesn't support odd number */ | 519 | /* div doesn't support odd number */ |
500 | div = max_t(u32, rs->max_freq / rs->speed, 1); | 520 | div = max_t(u32, rs->max_freq / rs->speed, 1); |
501 | div = (div + 1) & 0xfffe; | 521 | div = (div + 1) & 0xfffe; |
502 | 522 | ||
503 | spi_enable_chip(rs, 0); | ||
504 | |||
505 | writel_relaxed(cr0, rs->regs + ROCKCHIP_SPI_CTRLR0); | 523 | writel_relaxed(cr0, rs->regs + ROCKCHIP_SPI_CTRLR0); |
506 | 524 | ||
507 | writel_relaxed(rs->len - 1, rs->regs + ROCKCHIP_SPI_CTRLR1); | 525 | writel_relaxed(rs->len - 1, rs->regs + ROCKCHIP_SPI_CTRLR1); |
@@ -515,8 +533,6 @@ static void rockchip_spi_config(struct rockchip_spi *rs) | |||
515 | spi_set_clk(rs, div); | 533 | spi_set_clk(rs, div); |
516 | 534 | ||
517 | dev_dbg(rs->dev, "cr0 0x%x, div %d\n", cr0, div); | 535 | dev_dbg(rs->dev, "cr0 0x%x, div %d\n", cr0, div); |
518 | |||
519 | spi_enable_chip(rs, 1); | ||
520 | } | 536 | } |
521 | 537 | ||
522 | static int rockchip_spi_transfer_one( | 538 | static int rockchip_spi_transfer_one( |
@@ -524,7 +540,7 @@ static int rockchip_spi_transfer_one( | |||
524 | struct spi_device *spi, | 540 | struct spi_device *spi, |
525 | struct spi_transfer *xfer) | 541 | struct spi_transfer *xfer) |
526 | { | 542 | { |
527 | int ret = 0; | 543 | int ret = 1; |
528 | struct rockchip_spi *rs = spi_master_get_devdata(master); | 544 | struct rockchip_spi *rs = spi_master_get_devdata(master); |
529 | 545 | ||
530 | WARN_ON(readl_relaxed(rs->regs + ROCKCHIP_SPI_SSIENR) && | 546 | WARN_ON(readl_relaxed(rs->regs + ROCKCHIP_SPI_SSIENR) && |
@@ -556,17 +572,27 @@ static int rockchip_spi_transfer_one( | |||
556 | rs->tmode = CR0_XFM_RO; | 572 | rs->tmode = CR0_XFM_RO; |
557 | 573 | ||
558 | /* we need prepare dma before spi was enabled */ | 574 | /* we need prepare dma before spi was enabled */ |
559 | if (master->can_dma && master->can_dma(master, spi, xfer)) { | 575 | if (master->can_dma && master->can_dma(master, spi, xfer)) |
560 | rs->use_dma = 1; | 576 | rs->use_dma = 1; |
561 | rockchip_spi_prepare_dma(rs); | 577 | else |
562 | } else { | ||
563 | rs->use_dma = 0; | 578 | rs->use_dma = 0; |
564 | } | ||
565 | 579 | ||
566 | rockchip_spi_config(rs); | 580 | rockchip_spi_config(rs); |
567 | 581 | ||
568 | if (!rs->use_dma) | 582 | if (rs->use_dma) { |
583 | if (rs->tmode == CR0_XFM_RO) { | ||
584 | /* rx: dma must be prepared first */ | ||
585 | rockchip_spi_prepare_dma(rs); | ||
586 | spi_enable_chip(rs, 1); | ||
587 | } else { | ||
588 | /* tx or tr: spi must be enabled first */ | ||
589 | spi_enable_chip(rs, 1); | ||
590 | rockchip_spi_prepare_dma(rs); | ||
591 | } | ||
592 | } else { | ||
593 | spi_enable_chip(rs, 1); | ||
569 | ret = rockchip_spi_pio_transfer(rs); | 594 | ret = rockchip_spi_pio_transfer(rs); |
595 | } | ||
570 | 596 | ||
571 | return ret; | 597 | return ret; |
572 | } | 598 | } |
diff --git a/drivers/spi/spidev.c b/drivers/spi/spidev.c index e3bc23bb5883..e50039fb1474 100644 --- a/drivers/spi/spidev.c +++ b/drivers/spi/spidev.c | |||
@@ -82,10 +82,11 @@ struct spidev_data { | |||
82 | struct spi_device *spi; | 82 | struct spi_device *spi; |
83 | struct list_head device_entry; | 83 | struct list_head device_entry; |
84 | 84 | ||
85 | /* buffer is NULL unless this device is open (users > 0) */ | 85 | /* TX/RX buffers are NULL unless this device is open (users > 0) */ |
86 | struct mutex buf_lock; | 86 | struct mutex buf_lock; |
87 | unsigned users; | 87 | unsigned users; |
88 | u8 *buffer; | 88 | u8 *tx_buffer; |
89 | u8 *rx_buffer; | ||
89 | }; | 90 | }; |
90 | 91 | ||
91 | static LIST_HEAD(device_list); | 92 | static LIST_HEAD(device_list); |
@@ -135,7 +136,7 @@ static inline ssize_t | |||
135 | spidev_sync_write(struct spidev_data *spidev, size_t len) | 136 | spidev_sync_write(struct spidev_data *spidev, size_t len) |
136 | { | 137 | { |
137 | struct spi_transfer t = { | 138 | struct spi_transfer t = { |
138 | .tx_buf = spidev->buffer, | 139 | .tx_buf = spidev->tx_buffer, |
139 | .len = len, | 140 | .len = len, |
140 | }; | 141 | }; |
141 | struct spi_message m; | 142 | struct spi_message m; |
@@ -149,7 +150,7 @@ static inline ssize_t | |||
149 | spidev_sync_read(struct spidev_data *spidev, size_t len) | 150 | spidev_sync_read(struct spidev_data *spidev, size_t len) |
150 | { | 151 | { |
151 | struct spi_transfer t = { | 152 | struct spi_transfer t = { |
152 | .rx_buf = spidev->buffer, | 153 | .rx_buf = spidev->rx_buffer, |
153 | .len = len, | 154 | .len = len, |
154 | }; | 155 | }; |
155 | struct spi_message m; | 156 | struct spi_message m; |
@@ -179,7 +180,7 @@ spidev_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos) | |||
179 | if (status > 0) { | 180 | if (status > 0) { |
180 | unsigned long missing; | 181 | unsigned long missing; |
181 | 182 | ||
182 | missing = copy_to_user(buf, spidev->buffer, status); | 183 | missing = copy_to_user(buf, spidev->rx_buffer, status); |
183 | if (missing == status) | 184 | if (missing == status) |
184 | status = -EFAULT; | 185 | status = -EFAULT; |
185 | else | 186 | else |
@@ -206,7 +207,7 @@ spidev_write(struct file *filp, const char __user *buf, | |||
206 | spidev = filp->private_data; | 207 | spidev = filp->private_data; |
207 | 208 | ||
208 | mutex_lock(&spidev->buf_lock); | 209 | mutex_lock(&spidev->buf_lock); |
209 | missing = copy_from_user(spidev->buffer, buf, count); | 210 | missing = copy_from_user(spidev->tx_buffer, buf, count); |
210 | if (missing == 0) | 211 | if (missing == 0) |
211 | status = spidev_sync_write(spidev, count); | 212 | status = spidev_sync_write(spidev, count); |
212 | else | 213 | else |
@@ -224,7 +225,7 @@ static int spidev_message(struct spidev_data *spidev, | |||
224 | struct spi_transfer *k_tmp; | 225 | struct spi_transfer *k_tmp; |
225 | struct spi_ioc_transfer *u_tmp; | 226 | struct spi_ioc_transfer *u_tmp; |
226 | unsigned n, total; | 227 | unsigned n, total; |
227 | u8 *buf; | 228 | u8 *tx_buf, *rx_buf; |
228 | int status = -EFAULT; | 229 | int status = -EFAULT; |
229 | 230 | ||
230 | spi_message_init(&msg); | 231 | spi_message_init(&msg); |
@@ -236,7 +237,8 @@ static int spidev_message(struct spidev_data *spidev, | |||
236 | * We walk the array of user-provided transfers, using each one | 237 | * We walk the array of user-provided transfers, using each one |
237 | * to initialize a kernel version of the same transfer. | 238 | * to initialize a kernel version of the same transfer. |
238 | */ | 239 | */ |
239 | buf = spidev->buffer; | 240 | tx_buf = spidev->tx_buffer; |
241 | rx_buf = spidev->rx_buffer; | ||
240 | total = 0; | 242 | total = 0; |
241 | for (n = n_xfers, k_tmp = k_xfers, u_tmp = u_xfers; | 243 | for (n = n_xfers, k_tmp = k_xfers, u_tmp = u_xfers; |
242 | n; | 244 | n; |
@@ -250,20 +252,21 @@ static int spidev_message(struct spidev_data *spidev, | |||
250 | } | 252 | } |
251 | 253 | ||
252 | if (u_tmp->rx_buf) { | 254 | if (u_tmp->rx_buf) { |
253 | k_tmp->rx_buf = buf; | 255 | k_tmp->rx_buf = rx_buf; |
254 | if (!access_ok(VERIFY_WRITE, (u8 __user *) | 256 | if (!access_ok(VERIFY_WRITE, (u8 __user *) |
255 | (uintptr_t) u_tmp->rx_buf, | 257 | (uintptr_t) u_tmp->rx_buf, |
256 | u_tmp->len)) | 258 | u_tmp->len)) |
257 | goto done; | 259 | goto done; |
258 | } | 260 | } |
259 | if (u_tmp->tx_buf) { | 261 | if (u_tmp->tx_buf) { |
260 | k_tmp->tx_buf = buf; | 262 | k_tmp->tx_buf = tx_buf; |
261 | if (copy_from_user(buf, (const u8 __user *) | 263 | if (copy_from_user(tx_buf, (const u8 __user *) |
262 | (uintptr_t) u_tmp->tx_buf, | 264 | (uintptr_t) u_tmp->tx_buf, |
263 | u_tmp->len)) | 265 | u_tmp->len)) |
264 | goto done; | 266 | goto done; |
265 | } | 267 | } |
266 | buf += k_tmp->len; | 268 | tx_buf += k_tmp->len; |
269 | rx_buf += k_tmp->len; | ||
267 | 270 | ||
268 | k_tmp->cs_change = !!u_tmp->cs_change; | 271 | k_tmp->cs_change = !!u_tmp->cs_change; |
269 | k_tmp->tx_nbits = u_tmp->tx_nbits; | 272 | k_tmp->tx_nbits = u_tmp->tx_nbits; |
@@ -290,17 +293,17 @@ static int spidev_message(struct spidev_data *spidev, | |||
290 | goto done; | 293 | goto done; |
291 | 294 | ||
292 | /* copy any rx data out of bounce buffer */ | 295 | /* copy any rx data out of bounce buffer */ |
293 | buf = spidev->buffer; | 296 | rx_buf = spidev->rx_buffer; |
294 | for (n = n_xfers, u_tmp = u_xfers; n; n--, u_tmp++) { | 297 | for (n = n_xfers, u_tmp = u_xfers; n; n--, u_tmp++) { |
295 | if (u_tmp->rx_buf) { | 298 | if (u_tmp->rx_buf) { |
296 | if (__copy_to_user((u8 __user *) | 299 | if (__copy_to_user((u8 __user *) |
297 | (uintptr_t) u_tmp->rx_buf, buf, | 300 | (uintptr_t) u_tmp->rx_buf, rx_buf, |
298 | u_tmp->len)) { | 301 | u_tmp->len)) { |
299 | status = -EFAULT; | 302 | status = -EFAULT; |
300 | goto done; | 303 | goto done; |
301 | } | 304 | } |
302 | } | 305 | } |
303 | buf += u_tmp->len; | 306 | rx_buf += u_tmp->len; |
304 | } | 307 | } |
305 | status = total; | 308 | status = total; |
306 | 309 | ||
@@ -508,22 +511,41 @@ static int spidev_open(struct inode *inode, struct file *filp) | |||
508 | break; | 511 | break; |
509 | } | 512 | } |
510 | } | 513 | } |
511 | if (status == 0) { | 514 | |
512 | if (!spidev->buffer) { | 515 | if (status) { |
513 | spidev->buffer = kmalloc(bufsiz, GFP_KERNEL); | 516 | pr_debug("spidev: nothing for minor %d\n", iminor(inode)); |
514 | if (!spidev->buffer) { | 517 | goto err_find_dev; |
518 | } | ||
519 | |||
520 | if (!spidev->tx_buffer) { | ||
521 | spidev->tx_buffer = kmalloc(bufsiz, GFP_KERNEL); | ||
522 | if (!spidev->tx_buffer) { | ||
515 | dev_dbg(&spidev->spi->dev, "open/ENOMEM\n"); | 523 | dev_dbg(&spidev->spi->dev, "open/ENOMEM\n"); |
516 | status = -ENOMEM; | 524 | status = -ENOMEM; |
525 | goto err_find_dev; | ||
517 | } | 526 | } |
518 | } | 527 | } |
519 | if (status == 0) { | 528 | |
520 | spidev->users++; | 529 | if (!spidev->rx_buffer) { |
521 | filp->private_data = spidev; | 530 | spidev->rx_buffer = kmalloc(bufsiz, GFP_KERNEL); |
522 | nonseekable_open(inode, filp); | 531 | if (!spidev->rx_buffer) { |
532 | dev_dbg(&spidev->spi->dev, "open/ENOMEM\n"); | ||
533 | status = -ENOMEM; | ||
534 | goto err_alloc_rx_buf; | ||
523 | } | 535 | } |
524 | } else | 536 | } |
525 | pr_debug("spidev: nothing for minor %d\n", iminor(inode)); | 537 | |
538 | spidev->users++; | ||
539 | filp->private_data = spidev; | ||
540 | nonseekable_open(inode, filp); | ||
541 | |||
542 | mutex_unlock(&device_list_lock); | ||
543 | return 0; | ||
526 | 544 | ||
545 | err_alloc_rx_buf: | ||
546 | kfree(spidev->tx_buffer); | ||
547 | spidev->tx_buffer = NULL; | ||
548 | err_find_dev: | ||
527 | mutex_unlock(&device_list_lock); | 549 | mutex_unlock(&device_list_lock); |
528 | return status; | 550 | return status; |
529 | } | 551 | } |
@@ -542,8 +564,11 @@ static int spidev_release(struct inode *inode, struct file *filp) | |||
542 | if (!spidev->users) { | 564 | if (!spidev->users) { |
543 | int dofree; | 565 | int dofree; |
544 | 566 | ||
545 | kfree(spidev->buffer); | 567 | kfree(spidev->tx_buffer); |
546 | spidev->buffer = NULL; | 568 | spidev->tx_buffer = NULL; |
569 | |||
570 | kfree(spidev->rx_buffer); | ||
571 | spidev->rx_buffer = NULL; | ||
547 | 572 | ||
548 | /* ... after we unbound from the underlying device? */ | 573 | /* ... after we unbound from the underlying device? */ |
549 | spin_lock_irq(&spidev->spi_lock); | 574 | spin_lock_irq(&spidev->spi_lock); |