Loading drivers/spi/spi-dw.c +1 −0 Original line number Diff line number Diff line Loading @@ -669,6 +669,7 @@ int dw_spi_add_host(struct device *dev, struct dw_spi *dws) master->cleanup = dw_spi_cleanup; master->transfer_one_message = dw_spi_transfer_one_message; master->max_speed_hz = dws->max_freq; master->dev.of_node = dev->of_node; /* Basic HW init */ spi_hw_init(dws); Loading drivers/spi/spi-orion.c +1 −1 Original line number Diff line number Diff line Loading @@ -454,7 +454,7 @@ static int orion_spi_probe(struct platform_device *pdev) spi->master = master; of_id = of_match_device(orion_spi_of_match_table, &pdev->dev); devdata = of_id->data; devdata = (of_id) ? of_id->data : &orion_spi_dev_data; spi->devdata = devdata; spi->clk = devm_clk_get(&pdev->dev, NULL); Loading drivers/spi/spi-pl022.c +1 −1 Original line number Diff line number Diff line Loading @@ -1106,7 +1106,7 @@ static int configure_dma(struct pl022 *pl022) pl022->sgt_tx.nents, DMA_TO_DEVICE); err_tx_sgmap: dma_unmap_sg(rxchan->device->dev, pl022->sgt_rx.sgl, pl022->sgt_tx.nents, DMA_FROM_DEVICE); pl022->sgt_rx.nents, DMA_FROM_DEVICE); err_rx_sgmap: sg_free_table(&pl022->sgt_tx); err_alloc_tx_sg: Loading drivers/spi/spi-rockchip.c +38 −12 Original line number Diff line number Diff line Loading @@ -145,6 +145,9 @@ #define RXBUSY (1 << 0) #define TXBUSY (1 << 1) /* sclk_out: spi master internal logic in rk3x can support 50Mhz */ #define MAX_SCLK_OUT 50000000 enum rockchip_ssi_type { SSI_MOTO_SPI = 0, SSI_TI_SSP, Loading Loading @@ -325,6 +328,8 @@ static int rockchip_spi_unprepare_message(struct spi_master *master, spin_unlock_irqrestore(&rs->lock, flags); spi_enable_chip(rs, 0); return 0; } Loading Loading @@ -381,6 +386,8 @@ static int rockchip_spi_pio_transfer(struct rockchip_spi *rs) if (rs->tx) wait_for_idle(rs); spi_enable_chip(rs, 0); return 0; } Loading @@ -392,8 +399,10 @@ static void rockchip_spi_dma_rxcb(void *data) spin_lock_irqsave(&rs->lock, flags); rs->state &= ~RXBUSY; if (!(rs->state & TXBUSY)) if (!(rs->state & TXBUSY)) { spi_enable_chip(rs, 0); spi_finalize_current_transfer(rs->master); } spin_unlock_irqrestore(&rs->lock, flags); } Loading @@ -409,8 +418,10 @@ static void rockchip_spi_dma_txcb(void *data) spin_lock_irqsave(&rs->lock, flags); rs->state &= ~TXBUSY; if (!(rs->state & RXBUSY)) if (!(rs->state & RXBUSY)) { spi_enable_chip(rs, 0); spi_finalize_current_transfer(rs->master); } spin_unlock_irqrestore(&rs->lock, flags); } Loading Loading @@ -496,12 +507,19 @@ static void rockchip_spi_config(struct rockchip_spi *rs) dmacr |= RF_DMA_EN; } if (WARN_ON(rs->speed > MAX_SCLK_OUT)) rs->speed = MAX_SCLK_OUT; /* the minimum divsor is 2 */ if (rs->max_freq < 2 * rs->speed) { clk_set_rate(rs->spiclk, 2 * rs->speed); rs->max_freq = clk_get_rate(rs->spiclk); } /* div doesn't support odd number */ div = max_t(u32, rs->max_freq / rs->speed, 1); div = (div + 1) & 0xfffe; spi_enable_chip(rs, 0); writel_relaxed(cr0, rs->regs + ROCKCHIP_SPI_CTRLR0); writel_relaxed(rs->len - 1, rs->regs + ROCKCHIP_SPI_CTRLR1); Loading @@ -515,8 +533,6 @@ static void rockchip_spi_config(struct rockchip_spi *rs) spi_set_clk(rs, div); dev_dbg(rs->dev, "cr0 0x%x, div %d\n", cr0, div); spi_enable_chip(rs, 1); } static int rockchip_spi_transfer_one( Loading @@ -524,7 +540,7 @@ static int rockchip_spi_transfer_one( struct spi_device *spi, struct spi_transfer *xfer) { int ret = 0; int ret = 1; struct rockchip_spi *rs = spi_master_get_devdata(master); WARN_ON(readl_relaxed(rs->regs + ROCKCHIP_SPI_SSIENR) && Loading Loading @@ -556,17 +572,27 @@ static int rockchip_spi_transfer_one( rs->tmode = CR0_XFM_RO; /* we need prepare dma before spi was enabled */ if (master->can_dma && master->can_dma(master, spi, xfer)) { if (master->can_dma && master->can_dma(master, spi, xfer)) rs->use_dma = 1; rockchip_spi_prepare_dma(rs); } else { else rs->use_dma = 0; } rockchip_spi_config(rs); if (!rs->use_dma) if (rs->use_dma) { if (rs->tmode == CR0_XFM_RO) { /* rx: dma must be prepared first */ rockchip_spi_prepare_dma(rs); spi_enable_chip(rs, 1); } else { /* tx or tr: spi must be enabled first */ spi_enable_chip(rs, 1); rockchip_spi_prepare_dma(rs); } } else { spi_enable_chip(rs, 1); ret = rockchip_spi_pio_transfer(rs); } return ret; } Loading drivers/spi/spidev.c +52 −27 Original line number Diff line number Diff line Loading @@ -82,10 +82,11 @@ struct spidev_data { struct spi_device *spi; struct list_head device_entry; /* buffer is NULL unless this device is open (users > 0) */ /* TX/RX buffers are NULL unless this device is open (users > 0) */ struct mutex buf_lock; unsigned users; u8 *buffer; u8 *tx_buffer; u8 *rx_buffer; }; static LIST_HEAD(device_list); Loading Loading @@ -135,7 +136,7 @@ static inline ssize_t spidev_sync_write(struct spidev_data *spidev, size_t len) { struct spi_transfer t = { .tx_buf = spidev->buffer, .tx_buf = spidev->tx_buffer, .len = len, }; struct spi_message m; Loading @@ -149,7 +150,7 @@ static inline ssize_t spidev_sync_read(struct spidev_data *spidev, size_t len) { struct spi_transfer t = { .rx_buf = spidev->buffer, .rx_buf = spidev->rx_buffer, .len = len, }; struct spi_message m; Loading Loading @@ -179,7 +180,7 @@ spidev_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos) if (status > 0) { unsigned long missing; missing = copy_to_user(buf, spidev->buffer, status); missing = copy_to_user(buf, spidev->rx_buffer, status); if (missing == status) status = -EFAULT; else Loading @@ -206,7 +207,7 @@ spidev_write(struct file *filp, const char __user *buf, spidev = filp->private_data; mutex_lock(&spidev->buf_lock); missing = copy_from_user(spidev->buffer, buf, count); missing = copy_from_user(spidev->tx_buffer, buf, count); if (missing == 0) status = spidev_sync_write(spidev, count); else Loading @@ -224,7 +225,7 @@ static int spidev_message(struct spidev_data *spidev, struct spi_transfer *k_tmp; struct spi_ioc_transfer *u_tmp; unsigned n, total; u8 *buf; u8 *tx_buf, *rx_buf; int status = -EFAULT; spi_message_init(&msg); Loading @@ -236,7 +237,8 @@ static int spidev_message(struct spidev_data *spidev, * We walk the array of user-provided transfers, using each one * to initialize a kernel version of the same transfer. */ buf = spidev->buffer; tx_buf = spidev->tx_buffer; rx_buf = spidev->rx_buffer; total = 0; for (n = n_xfers, k_tmp = k_xfers, u_tmp = u_xfers; n; Loading @@ -250,20 +252,21 @@ static int spidev_message(struct spidev_data *spidev, } if (u_tmp->rx_buf) { k_tmp->rx_buf = buf; k_tmp->rx_buf = rx_buf; if (!access_ok(VERIFY_WRITE, (u8 __user *) (uintptr_t) u_tmp->rx_buf, u_tmp->len)) goto done; } if (u_tmp->tx_buf) { k_tmp->tx_buf = buf; if (copy_from_user(buf, (const u8 __user *) k_tmp->tx_buf = tx_buf; if (copy_from_user(tx_buf, (const u8 __user *) (uintptr_t) u_tmp->tx_buf, u_tmp->len)) goto done; } buf += k_tmp->len; tx_buf += k_tmp->len; rx_buf += k_tmp->len; k_tmp->cs_change = !!u_tmp->cs_change; k_tmp->tx_nbits = u_tmp->tx_nbits; Loading @@ -290,17 +293,17 @@ static int spidev_message(struct spidev_data *spidev, goto done; /* copy any rx data out of bounce buffer */ buf = spidev->buffer; rx_buf = spidev->rx_buffer; for (n = n_xfers, u_tmp = u_xfers; n; n--, u_tmp++) { if (u_tmp->rx_buf) { if (__copy_to_user((u8 __user *) (uintptr_t) u_tmp->rx_buf, buf, (uintptr_t) u_tmp->rx_buf, rx_buf, u_tmp->len)) { status = -EFAULT; goto done; } } buf += u_tmp->len; rx_buf += u_tmp->len; } status = total; Loading Loading @@ -508,22 +511,41 @@ static int spidev_open(struct inode *inode, struct file *filp) break; } } if (status == 0) { if (!spidev->buffer) { spidev->buffer = kmalloc(bufsiz, GFP_KERNEL); if (!spidev->buffer) { if (status) { pr_debug("spidev: nothing for minor %d\n", iminor(inode)); goto err_find_dev; } if (!spidev->tx_buffer) { spidev->tx_buffer = kmalloc(bufsiz, GFP_KERNEL); if (!spidev->tx_buffer) { dev_dbg(&spidev->spi->dev, "open/ENOMEM\n"); status = -ENOMEM; goto err_find_dev; } } if (status == 0) { if (!spidev->rx_buffer) { spidev->rx_buffer = kmalloc(bufsiz, GFP_KERNEL); if (!spidev->rx_buffer) { dev_dbg(&spidev->spi->dev, "open/ENOMEM\n"); status = -ENOMEM; goto err_alloc_rx_buf; } } spidev->users++; filp->private_data = spidev; nonseekable_open(inode, filp); } } else pr_debug("spidev: nothing for minor %d\n", iminor(inode)); mutex_unlock(&device_list_lock); return 0; err_alloc_rx_buf: kfree(spidev->tx_buffer); spidev->tx_buffer = NULL; err_find_dev: mutex_unlock(&device_list_lock); return status; } Loading @@ -542,8 +564,11 @@ static int spidev_release(struct inode *inode, struct file *filp) if (!spidev->users) { int dofree; kfree(spidev->buffer); spidev->buffer = NULL; kfree(spidev->tx_buffer); spidev->tx_buffer = NULL; kfree(spidev->rx_buffer); spidev->rx_buffer = NULL; /* ... after we unbound from the underlying device? */ spin_lock_irq(&spidev->spi_lock); Loading Loading
drivers/spi/spi-dw.c +1 −0 Original line number Diff line number Diff line Loading @@ -669,6 +669,7 @@ int dw_spi_add_host(struct device *dev, struct dw_spi *dws) master->cleanup = dw_spi_cleanup; master->transfer_one_message = dw_spi_transfer_one_message; master->max_speed_hz = dws->max_freq; master->dev.of_node = dev->of_node; /* Basic HW init */ spi_hw_init(dws); Loading
drivers/spi/spi-orion.c +1 −1 Original line number Diff line number Diff line Loading @@ -454,7 +454,7 @@ static int orion_spi_probe(struct platform_device *pdev) spi->master = master; of_id = of_match_device(orion_spi_of_match_table, &pdev->dev); devdata = of_id->data; devdata = (of_id) ? of_id->data : &orion_spi_dev_data; spi->devdata = devdata; spi->clk = devm_clk_get(&pdev->dev, NULL); Loading
drivers/spi/spi-pl022.c +1 −1 Original line number Diff line number Diff line Loading @@ -1106,7 +1106,7 @@ static int configure_dma(struct pl022 *pl022) pl022->sgt_tx.nents, DMA_TO_DEVICE); err_tx_sgmap: dma_unmap_sg(rxchan->device->dev, pl022->sgt_rx.sgl, pl022->sgt_tx.nents, DMA_FROM_DEVICE); pl022->sgt_rx.nents, DMA_FROM_DEVICE); err_rx_sgmap: sg_free_table(&pl022->sgt_tx); err_alloc_tx_sg: Loading
drivers/spi/spi-rockchip.c +38 −12 Original line number Diff line number Diff line Loading @@ -145,6 +145,9 @@ #define RXBUSY (1 << 0) #define TXBUSY (1 << 1) /* sclk_out: spi master internal logic in rk3x can support 50Mhz */ #define MAX_SCLK_OUT 50000000 enum rockchip_ssi_type { SSI_MOTO_SPI = 0, SSI_TI_SSP, Loading Loading @@ -325,6 +328,8 @@ static int rockchip_spi_unprepare_message(struct spi_master *master, spin_unlock_irqrestore(&rs->lock, flags); spi_enable_chip(rs, 0); return 0; } Loading Loading @@ -381,6 +386,8 @@ static int rockchip_spi_pio_transfer(struct rockchip_spi *rs) if (rs->tx) wait_for_idle(rs); spi_enable_chip(rs, 0); return 0; } Loading @@ -392,8 +399,10 @@ static void rockchip_spi_dma_rxcb(void *data) spin_lock_irqsave(&rs->lock, flags); rs->state &= ~RXBUSY; if (!(rs->state & TXBUSY)) if (!(rs->state & TXBUSY)) { spi_enable_chip(rs, 0); spi_finalize_current_transfer(rs->master); } spin_unlock_irqrestore(&rs->lock, flags); } Loading @@ -409,8 +418,10 @@ static void rockchip_spi_dma_txcb(void *data) spin_lock_irqsave(&rs->lock, flags); rs->state &= ~TXBUSY; if (!(rs->state & RXBUSY)) if (!(rs->state & RXBUSY)) { spi_enable_chip(rs, 0); spi_finalize_current_transfer(rs->master); } spin_unlock_irqrestore(&rs->lock, flags); } Loading Loading @@ -496,12 +507,19 @@ static void rockchip_spi_config(struct rockchip_spi *rs) dmacr |= RF_DMA_EN; } if (WARN_ON(rs->speed > MAX_SCLK_OUT)) rs->speed = MAX_SCLK_OUT; /* the minimum divsor is 2 */ if (rs->max_freq < 2 * rs->speed) { clk_set_rate(rs->spiclk, 2 * rs->speed); rs->max_freq = clk_get_rate(rs->spiclk); } /* div doesn't support odd number */ div = max_t(u32, rs->max_freq / rs->speed, 1); div = (div + 1) & 0xfffe; spi_enable_chip(rs, 0); writel_relaxed(cr0, rs->regs + ROCKCHIP_SPI_CTRLR0); writel_relaxed(rs->len - 1, rs->regs + ROCKCHIP_SPI_CTRLR1); Loading @@ -515,8 +533,6 @@ static void rockchip_spi_config(struct rockchip_spi *rs) spi_set_clk(rs, div); dev_dbg(rs->dev, "cr0 0x%x, div %d\n", cr0, div); spi_enable_chip(rs, 1); } static int rockchip_spi_transfer_one( Loading @@ -524,7 +540,7 @@ static int rockchip_spi_transfer_one( struct spi_device *spi, struct spi_transfer *xfer) { int ret = 0; int ret = 1; struct rockchip_spi *rs = spi_master_get_devdata(master); WARN_ON(readl_relaxed(rs->regs + ROCKCHIP_SPI_SSIENR) && Loading Loading @@ -556,17 +572,27 @@ static int rockchip_spi_transfer_one( rs->tmode = CR0_XFM_RO; /* we need prepare dma before spi was enabled */ if (master->can_dma && master->can_dma(master, spi, xfer)) { if (master->can_dma && master->can_dma(master, spi, xfer)) rs->use_dma = 1; rockchip_spi_prepare_dma(rs); } else { else rs->use_dma = 0; } rockchip_spi_config(rs); if (!rs->use_dma) if (rs->use_dma) { if (rs->tmode == CR0_XFM_RO) { /* rx: dma must be prepared first */ rockchip_spi_prepare_dma(rs); spi_enable_chip(rs, 1); } else { /* tx or tr: spi must be enabled first */ spi_enable_chip(rs, 1); rockchip_spi_prepare_dma(rs); } } else { spi_enable_chip(rs, 1); ret = rockchip_spi_pio_transfer(rs); } return ret; } Loading
drivers/spi/spidev.c +52 −27 Original line number Diff line number Diff line Loading @@ -82,10 +82,11 @@ struct spidev_data { struct spi_device *spi; struct list_head device_entry; /* buffer is NULL unless this device is open (users > 0) */ /* TX/RX buffers are NULL unless this device is open (users > 0) */ struct mutex buf_lock; unsigned users; u8 *buffer; u8 *tx_buffer; u8 *rx_buffer; }; static LIST_HEAD(device_list); Loading Loading @@ -135,7 +136,7 @@ static inline ssize_t spidev_sync_write(struct spidev_data *spidev, size_t len) { struct spi_transfer t = { .tx_buf = spidev->buffer, .tx_buf = spidev->tx_buffer, .len = len, }; struct spi_message m; Loading @@ -149,7 +150,7 @@ static inline ssize_t spidev_sync_read(struct spidev_data *spidev, size_t len) { struct spi_transfer t = { .rx_buf = spidev->buffer, .rx_buf = spidev->rx_buffer, .len = len, }; struct spi_message m; Loading Loading @@ -179,7 +180,7 @@ spidev_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos) if (status > 0) { unsigned long missing; missing = copy_to_user(buf, spidev->buffer, status); missing = copy_to_user(buf, spidev->rx_buffer, status); if (missing == status) status = -EFAULT; else Loading @@ -206,7 +207,7 @@ spidev_write(struct file *filp, const char __user *buf, spidev = filp->private_data; mutex_lock(&spidev->buf_lock); missing = copy_from_user(spidev->buffer, buf, count); missing = copy_from_user(spidev->tx_buffer, buf, count); if (missing == 0) status = spidev_sync_write(spidev, count); else Loading @@ -224,7 +225,7 @@ static int spidev_message(struct spidev_data *spidev, struct spi_transfer *k_tmp; struct spi_ioc_transfer *u_tmp; unsigned n, total; u8 *buf; u8 *tx_buf, *rx_buf; int status = -EFAULT; spi_message_init(&msg); Loading @@ -236,7 +237,8 @@ static int spidev_message(struct spidev_data *spidev, * We walk the array of user-provided transfers, using each one * to initialize a kernel version of the same transfer. */ buf = spidev->buffer; tx_buf = spidev->tx_buffer; rx_buf = spidev->rx_buffer; total = 0; for (n = n_xfers, k_tmp = k_xfers, u_tmp = u_xfers; n; Loading @@ -250,20 +252,21 @@ static int spidev_message(struct spidev_data *spidev, } if (u_tmp->rx_buf) { k_tmp->rx_buf = buf; k_tmp->rx_buf = rx_buf; if (!access_ok(VERIFY_WRITE, (u8 __user *) (uintptr_t) u_tmp->rx_buf, u_tmp->len)) goto done; } if (u_tmp->tx_buf) { k_tmp->tx_buf = buf; if (copy_from_user(buf, (const u8 __user *) k_tmp->tx_buf = tx_buf; if (copy_from_user(tx_buf, (const u8 __user *) (uintptr_t) u_tmp->tx_buf, u_tmp->len)) goto done; } buf += k_tmp->len; tx_buf += k_tmp->len; rx_buf += k_tmp->len; k_tmp->cs_change = !!u_tmp->cs_change; k_tmp->tx_nbits = u_tmp->tx_nbits; Loading @@ -290,17 +293,17 @@ static int spidev_message(struct spidev_data *spidev, goto done; /* copy any rx data out of bounce buffer */ buf = spidev->buffer; rx_buf = spidev->rx_buffer; for (n = n_xfers, u_tmp = u_xfers; n; n--, u_tmp++) { if (u_tmp->rx_buf) { if (__copy_to_user((u8 __user *) (uintptr_t) u_tmp->rx_buf, buf, (uintptr_t) u_tmp->rx_buf, rx_buf, u_tmp->len)) { status = -EFAULT; goto done; } } buf += u_tmp->len; rx_buf += u_tmp->len; } status = total; Loading Loading @@ -508,22 +511,41 @@ static int spidev_open(struct inode *inode, struct file *filp) break; } } if (status == 0) { if (!spidev->buffer) { spidev->buffer = kmalloc(bufsiz, GFP_KERNEL); if (!spidev->buffer) { if (status) { pr_debug("spidev: nothing for minor %d\n", iminor(inode)); goto err_find_dev; } if (!spidev->tx_buffer) { spidev->tx_buffer = kmalloc(bufsiz, GFP_KERNEL); if (!spidev->tx_buffer) { dev_dbg(&spidev->spi->dev, "open/ENOMEM\n"); status = -ENOMEM; goto err_find_dev; } } if (status == 0) { if (!spidev->rx_buffer) { spidev->rx_buffer = kmalloc(bufsiz, GFP_KERNEL); if (!spidev->rx_buffer) { dev_dbg(&spidev->spi->dev, "open/ENOMEM\n"); status = -ENOMEM; goto err_alloc_rx_buf; } } spidev->users++; filp->private_data = spidev; nonseekable_open(inode, filp); } } else pr_debug("spidev: nothing for minor %d\n", iminor(inode)); mutex_unlock(&device_list_lock); return 0; err_alloc_rx_buf: kfree(spidev->tx_buffer); spidev->tx_buffer = NULL; err_find_dev: mutex_unlock(&device_list_lock); return status; } Loading @@ -542,8 +564,11 @@ static int spidev_release(struct inode *inode, struct file *filp) if (!spidev->users) { int dofree; kfree(spidev->buffer); spidev->buffer = NULL; kfree(spidev->tx_buffer); spidev->tx_buffer = NULL; kfree(spidev->rx_buffer); spidev->rx_buffer = NULL; /* ... after we unbound from the underlying device? */ spin_lock_irq(&spidev->spi_lock); Loading