Loading Documentation/devicetree/bindings/spi/spi-fsl-lpspi.yaml +1 −0 Original line number Diff line number Diff line Loading @@ -39,6 +39,7 @@ properties: spi common code does not support use of CS signals discontinuously. i.MX8DXL-EVK board only uses CS1 without using CS0. Therefore, add this property to re-config the chipselect value in the LPSPI driver. type: boolean required: - compatible Loading drivers/spi/Kconfig +3 −0 Original line number Diff line number Diff line Loading @@ -1017,4 +1017,7 @@ config SPI_SLAVE_SYSTEM_CONTROL endif # SPI_SLAVE config SPI_DYNAMIC def_bool ACPI || OF_DYNAMIC || SPI_SLAVE endif # SPI drivers/spi/spi-stm32.c +62 −38 Original line number Diff line number Diff line Loading @@ -13,6 +13,7 @@ #include <linux/iopoll.h> #include <linux/module.h> #include <linux/of_platform.h> #include <linux/pinctrl/consumer.h> #include <linux/pm_runtime.h> #include <linux/reset.h> #include <linux/spi/spi.h> Loading Loading @@ -441,7 +442,8 @@ static int stm32_spi_prepare_mbr(struct stm32_spi *spi, u32 speed_hz, { u32 div, mbrdiv; div = DIV_ROUND_UP(spi->clk_rate, speed_hz); /* Ensure spi->clk_rate is even */ div = DIV_ROUND_UP(spi->clk_rate & ~0x1, speed_hz); /* * SPI framework set xfer->speed_hz to master->max_speed_hz if Loading @@ -467,20 +469,27 @@ static int stm32_spi_prepare_mbr(struct stm32_spi *spi, u32 speed_hz, /** * stm32h7_spi_prepare_fthlv - Determine FIFO threshold level * @spi: pointer to the spi controller data structure * @xfer_len: length of the message to be transferred */ static u32 stm32h7_spi_prepare_fthlv(struct stm32_spi *spi) static u32 stm32h7_spi_prepare_fthlv(struct stm32_spi *spi, u32 xfer_len) { u32 fthlv, half_fifo; u32 fthlv, half_fifo, packet; /* data packet should not exceed 1/2 of fifo space */ half_fifo = (spi->fifo_size / 2); /* data_packet should not exceed transfer length */ if (half_fifo > xfer_len) packet = xfer_len; else packet = half_fifo; if (spi->cur_bpw <= 8) fthlv = half_fifo; fthlv = packet; else if (spi->cur_bpw <= 16) fthlv = half_fifo / 2; fthlv = packet / 2; else fthlv = half_fifo / 4; fthlv = packet / 4; /* align packet size with data registers access */ if (spi->cur_bpw > 8) Loading @@ -488,6 +497,9 @@ static u32 stm32h7_spi_prepare_fthlv(struct stm32_spi *spi) else fthlv -= (fthlv % 4); /* multiple of 4 */ if (!fthlv) fthlv = 1; return fthlv; } Loading Loading @@ -966,13 +978,13 @@ static irqreturn_t stm32h7_spi_irq_thread(int irq, void *dev_id) if (!spi->cur_usedma && (spi->rx_buf && (spi->rx_len > 0))) stm32h7_spi_read_rxfifo(spi, false); writel_relaxed(mask, spi->base + STM32H7_SPI_IFCR); writel_relaxed(sr & mask, spi->base + STM32H7_SPI_IFCR); spin_unlock_irqrestore(&spi->lock, flags); if (end) { spi_finalize_current_transfer(master); stm32h7_spi_disable(spi); spi_finalize_current_transfer(master); } return IRQ_HANDLED; Loading Loading @@ -1393,7 +1405,7 @@ static void stm32h7_spi_set_bpw(struct stm32_spi *spi) cfg1_setb |= (bpw << STM32H7_SPI_CFG1_DSIZE_SHIFT) & STM32H7_SPI_CFG1_DSIZE; spi->cur_fthlv = stm32h7_spi_prepare_fthlv(spi); spi->cur_fthlv = stm32h7_spi_prepare_fthlv(spi, spi->cur_xferlen); fthlv = spi->cur_fthlv - 1; cfg1_clrb |= STM32H7_SPI_CFG1_FTHLV; Loading Loading @@ -1585,16 +1597,14 @@ static int stm32_spi_transfer_one_setup(struct stm32_spi *spi, unsigned long flags; unsigned int comm_type; int nb_words, ret = 0; int mbr; spin_lock_irqsave(&spi->lock, flags); if (spi->cur_bpw != transfer->bits_per_word) { spi->cur_xferlen = transfer->len; spi->cur_bpw = transfer->bits_per_word; spi->cfg->set_bpw(spi); } if (spi->cur_speed != transfer->speed_hz) { int mbr; /* Update spi->cur_speed with real clock speed */ mbr = stm32_spi_prepare_mbr(spi, transfer->speed_hz, Loading @@ -1607,17 +1617,13 @@ static int stm32_spi_transfer_one_setup(struct stm32_spi *spi, transfer->speed_hz = spi->cur_speed; stm32_spi_set_mbr(spi, mbr); } comm_type = stm32_spi_communication_type(spi_dev, transfer); if (spi->cur_comm != comm_type) { ret = spi->cfg->set_mode(spi, comm_type); if (ret < 0) goto out; spi->cur_comm = comm_type; } if (spi->cfg->set_data_idleness) spi->cfg->set_data_idleness(spi, transfer->len); Loading @@ -1635,8 +1641,6 @@ static int stm32_spi_transfer_one_setup(struct stm32_spi *spi, goto out; } spi->cur_xferlen = transfer->len; dev_dbg(spi->dev, "transfer communication mode set to %d\n", spi->cur_comm); dev_dbg(spi->dev, Loading Loading @@ -1996,6 +2000,8 @@ static int stm32_spi_remove(struct platform_device *pdev) pm_runtime_disable(&pdev->dev); pinctrl_pm_select_sleep_state(&pdev->dev); return 0; } Loading @@ -2007,13 +2013,18 @@ static int stm32_spi_runtime_suspend(struct device *dev) clk_disable_unprepare(spi->clk); return 0; return pinctrl_pm_select_sleep_state(dev); } static int stm32_spi_runtime_resume(struct device *dev) { struct spi_master *master = dev_get_drvdata(dev); struct stm32_spi *spi = spi_master_get_devdata(master); int ret; ret = pinctrl_pm_select_default_state(dev); if (ret) return ret; return clk_prepare_enable(spi->clk); } Loading Loading @@ -2043,11 +2054,24 @@ static int stm32_spi_resume(struct device *dev) return ret; ret = spi_master_resume(master); if (ret) if (ret) { clk_disable_unprepare(spi->clk); return ret; } ret = pm_runtime_get_sync(dev); if (ret) { dev_err(dev, "Unable to power device:%d\n", ret); return ret; } spi->cfg->config(spi); pm_runtime_mark_last_busy(dev); pm_runtime_put_autosuspend(dev); return 0; } #endif static const struct dev_pm_ops stm32_spi_pm_ops = { Loading drivers/spi/spi.c +20 −1 Original line number Diff line number Diff line Loading @@ -475,6 +475,12 @@ static LIST_HEAD(spi_controller_list); */ static DEFINE_MUTEX(board_lock); /* * Prevents addition of devices with same chip select and * addition of devices below an unregistering controller. */ static DEFINE_MUTEX(spi_add_lock); /** * spi_alloc_device - Allocate a new SPI device * @ctlr: Controller to which device is connected Loading Loading @@ -554,7 +560,6 @@ static int spi_dev_check(struct device *dev, void *data) */ int spi_add_device(struct spi_device *spi) { static DEFINE_MUTEX(spi_add_lock); struct spi_controller *ctlr = spi->controller; struct device *dev = ctlr->dev.parent; int status; Loading Loading @@ -582,6 +587,13 @@ int spi_add_device(struct spi_device *spi) goto done; } /* Controller may unregister concurrently */ if (IS_ENABLED(CONFIG_SPI_DYNAMIC) && !device_is_registered(&ctlr->dev)) { status = -ENODEV; goto done; } /* Descriptors take precedence */ if (ctlr->cs_gpiods) spi->cs_gpiod = ctlr->cs_gpiods[spi->chip_select]; Loading Loading @@ -2795,6 +2807,10 @@ void spi_unregister_controller(struct spi_controller *ctlr) struct spi_controller *found; int id = ctlr->bus_num; /* Prevent addition of new devices, unregister existing ones */ if (IS_ENABLED(CONFIG_SPI_DYNAMIC)) mutex_lock(&spi_add_lock); device_for_each_child(&ctlr->dev, NULL, __unregister); /* First make sure that this controller was ever added */ Loading @@ -2815,6 +2831,9 @@ void spi_unregister_controller(struct spi_controller *ctlr) if (found == ctlr) idr_remove(&spi_master_idr, id); mutex_unlock(&board_lock); if (IS_ENABLED(CONFIG_SPI_DYNAMIC)) mutex_unlock(&spi_add_lock); } EXPORT_SYMBOL_GPL(spi_unregister_controller); Loading Loading
Documentation/devicetree/bindings/spi/spi-fsl-lpspi.yaml +1 −0 Original line number Diff line number Diff line Loading @@ -39,6 +39,7 @@ properties: spi common code does not support use of CS signals discontinuously. i.MX8DXL-EVK board only uses CS1 without using CS0. Therefore, add this property to re-config the chipselect value in the LPSPI driver. type: boolean required: - compatible Loading
drivers/spi/Kconfig +3 −0 Original line number Diff line number Diff line Loading @@ -1017,4 +1017,7 @@ config SPI_SLAVE_SYSTEM_CONTROL endif # SPI_SLAVE config SPI_DYNAMIC def_bool ACPI || OF_DYNAMIC || SPI_SLAVE endif # SPI
drivers/spi/spi-stm32.c +62 −38 Original line number Diff line number Diff line Loading @@ -13,6 +13,7 @@ #include <linux/iopoll.h> #include <linux/module.h> #include <linux/of_platform.h> #include <linux/pinctrl/consumer.h> #include <linux/pm_runtime.h> #include <linux/reset.h> #include <linux/spi/spi.h> Loading Loading @@ -441,7 +442,8 @@ static int stm32_spi_prepare_mbr(struct stm32_spi *spi, u32 speed_hz, { u32 div, mbrdiv; div = DIV_ROUND_UP(spi->clk_rate, speed_hz); /* Ensure spi->clk_rate is even */ div = DIV_ROUND_UP(spi->clk_rate & ~0x1, speed_hz); /* * SPI framework set xfer->speed_hz to master->max_speed_hz if Loading @@ -467,20 +469,27 @@ static int stm32_spi_prepare_mbr(struct stm32_spi *spi, u32 speed_hz, /** * stm32h7_spi_prepare_fthlv - Determine FIFO threshold level * @spi: pointer to the spi controller data structure * @xfer_len: length of the message to be transferred */ static u32 stm32h7_spi_prepare_fthlv(struct stm32_spi *spi) static u32 stm32h7_spi_prepare_fthlv(struct stm32_spi *spi, u32 xfer_len) { u32 fthlv, half_fifo; u32 fthlv, half_fifo, packet; /* data packet should not exceed 1/2 of fifo space */ half_fifo = (spi->fifo_size / 2); /* data_packet should not exceed transfer length */ if (half_fifo > xfer_len) packet = xfer_len; else packet = half_fifo; if (spi->cur_bpw <= 8) fthlv = half_fifo; fthlv = packet; else if (spi->cur_bpw <= 16) fthlv = half_fifo / 2; fthlv = packet / 2; else fthlv = half_fifo / 4; fthlv = packet / 4; /* align packet size with data registers access */ if (spi->cur_bpw > 8) Loading @@ -488,6 +497,9 @@ static u32 stm32h7_spi_prepare_fthlv(struct stm32_spi *spi) else fthlv -= (fthlv % 4); /* multiple of 4 */ if (!fthlv) fthlv = 1; return fthlv; } Loading Loading @@ -966,13 +978,13 @@ static irqreturn_t stm32h7_spi_irq_thread(int irq, void *dev_id) if (!spi->cur_usedma && (spi->rx_buf && (spi->rx_len > 0))) stm32h7_spi_read_rxfifo(spi, false); writel_relaxed(mask, spi->base + STM32H7_SPI_IFCR); writel_relaxed(sr & mask, spi->base + STM32H7_SPI_IFCR); spin_unlock_irqrestore(&spi->lock, flags); if (end) { spi_finalize_current_transfer(master); stm32h7_spi_disable(spi); spi_finalize_current_transfer(master); } return IRQ_HANDLED; Loading Loading @@ -1393,7 +1405,7 @@ static void stm32h7_spi_set_bpw(struct stm32_spi *spi) cfg1_setb |= (bpw << STM32H7_SPI_CFG1_DSIZE_SHIFT) & STM32H7_SPI_CFG1_DSIZE; spi->cur_fthlv = stm32h7_spi_prepare_fthlv(spi); spi->cur_fthlv = stm32h7_spi_prepare_fthlv(spi, spi->cur_xferlen); fthlv = spi->cur_fthlv - 1; cfg1_clrb |= STM32H7_SPI_CFG1_FTHLV; Loading Loading @@ -1585,16 +1597,14 @@ static int stm32_spi_transfer_one_setup(struct stm32_spi *spi, unsigned long flags; unsigned int comm_type; int nb_words, ret = 0; int mbr; spin_lock_irqsave(&spi->lock, flags); if (spi->cur_bpw != transfer->bits_per_word) { spi->cur_xferlen = transfer->len; spi->cur_bpw = transfer->bits_per_word; spi->cfg->set_bpw(spi); } if (spi->cur_speed != transfer->speed_hz) { int mbr; /* Update spi->cur_speed with real clock speed */ mbr = stm32_spi_prepare_mbr(spi, transfer->speed_hz, Loading @@ -1607,17 +1617,13 @@ static int stm32_spi_transfer_one_setup(struct stm32_spi *spi, transfer->speed_hz = spi->cur_speed; stm32_spi_set_mbr(spi, mbr); } comm_type = stm32_spi_communication_type(spi_dev, transfer); if (spi->cur_comm != comm_type) { ret = spi->cfg->set_mode(spi, comm_type); if (ret < 0) goto out; spi->cur_comm = comm_type; } if (spi->cfg->set_data_idleness) spi->cfg->set_data_idleness(spi, transfer->len); Loading @@ -1635,8 +1641,6 @@ static int stm32_spi_transfer_one_setup(struct stm32_spi *spi, goto out; } spi->cur_xferlen = transfer->len; dev_dbg(spi->dev, "transfer communication mode set to %d\n", spi->cur_comm); dev_dbg(spi->dev, Loading Loading @@ -1996,6 +2000,8 @@ static int stm32_spi_remove(struct platform_device *pdev) pm_runtime_disable(&pdev->dev); pinctrl_pm_select_sleep_state(&pdev->dev); return 0; } Loading @@ -2007,13 +2013,18 @@ static int stm32_spi_runtime_suspend(struct device *dev) clk_disable_unprepare(spi->clk); return 0; return pinctrl_pm_select_sleep_state(dev); } static int stm32_spi_runtime_resume(struct device *dev) { struct spi_master *master = dev_get_drvdata(dev); struct stm32_spi *spi = spi_master_get_devdata(master); int ret; ret = pinctrl_pm_select_default_state(dev); if (ret) return ret; return clk_prepare_enable(spi->clk); } Loading Loading @@ -2043,11 +2054,24 @@ static int stm32_spi_resume(struct device *dev) return ret; ret = spi_master_resume(master); if (ret) if (ret) { clk_disable_unprepare(spi->clk); return ret; } ret = pm_runtime_get_sync(dev); if (ret) { dev_err(dev, "Unable to power device:%d\n", ret); return ret; } spi->cfg->config(spi); pm_runtime_mark_last_busy(dev); pm_runtime_put_autosuspend(dev); return 0; } #endif static const struct dev_pm_ops stm32_spi_pm_ops = { Loading
drivers/spi/spi.c +20 −1 Original line number Diff line number Diff line Loading @@ -475,6 +475,12 @@ static LIST_HEAD(spi_controller_list); */ static DEFINE_MUTEX(board_lock); /* * Prevents addition of devices with same chip select and * addition of devices below an unregistering controller. */ static DEFINE_MUTEX(spi_add_lock); /** * spi_alloc_device - Allocate a new SPI device * @ctlr: Controller to which device is connected Loading Loading @@ -554,7 +560,6 @@ static int spi_dev_check(struct device *dev, void *data) */ int spi_add_device(struct spi_device *spi) { static DEFINE_MUTEX(spi_add_lock); struct spi_controller *ctlr = spi->controller; struct device *dev = ctlr->dev.parent; int status; Loading Loading @@ -582,6 +587,13 @@ int spi_add_device(struct spi_device *spi) goto done; } /* Controller may unregister concurrently */ if (IS_ENABLED(CONFIG_SPI_DYNAMIC) && !device_is_registered(&ctlr->dev)) { status = -ENODEV; goto done; } /* Descriptors take precedence */ if (ctlr->cs_gpiods) spi->cs_gpiod = ctlr->cs_gpiods[spi->chip_select]; Loading Loading @@ -2795,6 +2807,10 @@ void spi_unregister_controller(struct spi_controller *ctlr) struct spi_controller *found; int id = ctlr->bus_num; /* Prevent addition of new devices, unregister existing ones */ if (IS_ENABLED(CONFIG_SPI_DYNAMIC)) mutex_lock(&spi_add_lock); device_for_each_child(&ctlr->dev, NULL, __unregister); /* First make sure that this controller was ever added */ Loading @@ -2815,6 +2831,9 @@ void spi_unregister_controller(struct spi_controller *ctlr) if (found == ctlr) idr_remove(&spi_master_idr, id); mutex_unlock(&board_lock); if (IS_ENABLED(CONFIG_SPI_DYNAMIC)) mutex_unlock(&spi_add_lock); } EXPORT_SYMBOL_GPL(spi_unregister_controller); Loading