summaryrefslogtreecommitdiff
path: root/drivers/spi/spi-fsl-dspi.c
AgeCommit message (Collapse)AuthorFilesLines
2024-07-01spi: fsl-dspi: use common proptery 'spi-cs-setup(hold)-delay-ns'Frank Li1-5/+14
Use SPI common DT binding properties 'spi-cs-setup-delay-ns' and 'spi-cs-hold-delay-ns'. If these properties do not exist, fall back to legacy 'fsl,spi-cs-sck-delay' and 'fsl,spi-sck-cs-delay'. Signed-off-by: Frank Li <Frank.Li@nxp.com> Reviewed-by: Vladimir Oltean <olteanv@gmail.com> Link: https://patch.msgid.link/20240624-ls_qspi-v4-1-3d1c6f5005bf@nxp.com Signed-off-by: Mark Brown <broonie@kernel.org>
2024-03-28spi: fsl-dspi: drop driver owner assignmentKrzysztof Kozlowski1-1/+0
Core in platform_driver_register() already sets the .owner, so driver does not need to. Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org> Link: https://msgid.link/r/20240327174737.519637-3-krzysztof.kozlowski@linaro.org Signed-off-by: Mark Brown <broonie@kernel.org>
2024-02-05spi: fsl-dspi: Unify error messaging in dspi_request_dma()andy.shevchenko@gmail.com1-8/+5
Use dev_err_probe() for all messages in dspi_request_dma() for the sake of making them uniform. While at it, fix indentation issue reported by Vladimir Oltean. Signed-off-by: Andy Shevchenko <andy.shevchenko@gmail.com> Reviewed-by: Vladimir Oltean <olteanv@gmail.com> Link: https://lore.kernel.org/r/20240204203127.1186621-3-andy.shevchenko@gmail.com Signed-off-by: Mark Brown <broonie@kernel.org>
2024-02-05spi: fsl-dspi: Preserve error code returned by dmaengine_slave_config()andy.shevchenko@gmail.com1-2/+0
dmaengine_slave_config() may return different error codes based on the circumstances. Preserve it instead of shadowing to -EINVAL. Suggested-by: Vladimir Oltean <olteanv@gmail.com> Signed-off-by: Andy Shevchenko <andy.shevchenko@gmail.com> Reviewed-by: Vladimir Oltean <olteanv@gmail.com> Link: https://lore.kernel.org/r/20240204203127.1186621-2-andy.shevchenko@gmail.com Signed-off-by: Mark Brown <broonie@kernel.org>
2023-09-11spi: spi-fsl-dspi: Use helper function devm_clk_get_enabled()Li Zetao1-9/+3
Since commit 7ef9651e9792 ("clk: Provide new devm_clk helpers for prepared and enabled clocks"), devm_clk_get() and clk_prepare_enable() can now be replaced by devm_clk_get_enabled() when driver enables (and possibly prepares) the clocks for the whole lifetime of the device. Moreover, it is no longer necessary to unprepare and disable the clocks explicitly. Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com> Signed-off-by: Li Zetao <lizetao1@huawei.com> Link: https://lore.kernel.org/r/20230823133938.1359106-14-lizetao1@huawei.com Signed-off-by: Mark Brown <broonie@kernel.org>
2023-08-14spi: fsl-dspi: switch to use modern nameYang Yingliang1-12/+12
Change legacy name master/target to modern name host/target or controller. No functional changed. Signed-off-by: Yang Yingliang <yangyingliang@huawei.com> Link: https://lore.kernel.org/r/20230807124105.3429709-7-yangyingliang@huawei.com Signed-off-by: Mark Brown <broonie@kernel.org>
2023-07-25spi: fsl-dspi: Use dev_err_probe() in dspi_request_dma()Minjie Du1-4/+3
It is possible for dma_request_chan() to return EPROBE_DEFER, which means dev is not ready yet. At this point dev_err() will have no output. Signed-off-by: Minjie Du <duminjie@vivo.com> Link: https://lore.kernel.org/r/20230725035038.1702-1-duminjie@vivo.com Signed-off-by: Mark Brown <broonie@kernel.org>
2023-07-14spi: Explicitly include correct DT includesRob Herring1-1/+2
The DT of_device.h and of_platform.h date back to the separate of_platform_bus_type before it as merged into the regular platform bus. As part of that merge prepping Arm DT support 13 years ago, they "temporarily" include each other. They also include platform_device.h and of.h. As a result, there's a pretty much random mix of those include files used throughout the tree. In order to detangle these headers and replace the implicit includes with struct declarations, users need to explicitly include the correct includes. Signed-off-by: Rob Herring <robh@kernel.org> Link: https://lore.kernel.org/r/20230714174955.4064174-1-robh@kernel.org Signed-off-by: Mark Brown <broonie@kernel.org>
2023-06-06spi: fsl-dspi: avoid SCK glitches with continuous transfersVladimir Oltean1-0/+15
The DSPI controller has configurable timing for (a) tCSC: the interval between the assertion of the chip select and the first clock edge (b) tASC: the interval between the last clock edge and the deassertion of the chip select What is a bit surprising, but is documented in the figure "Example of continuous transfer (CPHA=1, CONT=1)" in the datasheet, is that when the chip select stays asserted between multiple TX FIFO writes, the tCSC and tASC times still apply. With CONT=1, chip select remains asserted, but SCK takes a break and goes to the idle state for tASC + tCSC ns. In other words, the default values (of 0 and 0 ns) result in SCK glitches where the SCK transition to the idle state, as well as the SCK transition from the idle state, will have no delay in between, and it may appear that a SCK cycle has simply gone missing. The resulting timing violation might cause data corruption in many peripherals, as their chip select is asserted. The driver has device tree bindings for tCSC ("fsl,spi-cs-sck-delay") and tASC ("fsl,spi-sck-cs-delay"), but these are only specified to apply when the chip select toggles in the first place, and this timing characteristic depends on each peripheral. Many peripherals do not have explicit timing requirements, so many device trees do not have these properties present at all. Nonetheless, the lack of SCK glitches is a common sense requirement, and since the SCK stays in the idle state during transfers for tCSC+tASC ns, and that in itself should look like half a cycle, then let's ensure that tCSC and tASC are at least a quarter of a SCK period, such that their sum is at least half of one. Fixes: 95bf15f38641 ("spi: fsl-dspi: Add ~50ns delay between cs and sck") Reported-by: Lisa Chen (陈敏捷) <minjie.chen@geekplus.com> Debugged-by: Lisa Chen (陈敏捷) <minjie.chen@geekplus.com> Tested-by: Lisa Chen (陈敏捷) <minjie.chen@geekplus.com> Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com> Link: https://lore.kernel.org/r/20230529223402.1199503-1-vladimir.oltean@nxp.com Signed-off-by: Mark Brown <broonie@kernel.org>
2023-03-13spi: fsl-dspi: Remove unneeded cast to same typeGeert Uytterhoeven1-1/+1
There is never a need to cast a pointer to the same pointer type. Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be> Link: https://lore.kernel.org/r/a417735ca3ff629ee897327b163b23414673f0a3.1678704562.git.geert+renesas@glider.be Signed-off-by: Mark Brown <broonie@kernel.org>
2023-03-11spi: Replace all spi->chip_select and spi->cs_gpiod references with function ↵Amit Kumar Mahapatra via Alsa-devel1-8/+8
call Supporting multi-cs in spi drivers would require the chip_select & cs_gpiod members of struct spi_device to be an array. But changing the type of these members to array would break the spi driver functionality. To make the transition smoother introduced four new APIs to get/set the spi->chip_select & spi->cs_gpiod and replaced all spi->chip_select and spi->cs_gpiod references with get or set API calls. While adding multi-cs support in further patches the chip_select & cs_gpiod members of the spi_device structure would be converted to arrays & the "idx" parameter of the APIs would be used as array index i.e., spi->chip_select[idx] & spi->cs_gpiod[idx] respectively. Signed-off-by: Amit Kumar Mahapatra <amit.kumar-mahapatra@amd.com> Acked-by: Heiko Stuebner <heiko@sntech.de> # Rockchip drivers Reviewed-by: Michal Simek <michal.simek@amd.com> Reviewed-by: Cédric Le Goater <clg@kaod.org> # Aspeed driver Reviewed-by: Dhruva Gole <d-gole@ti.com> # SPI Cadence QSPI Reviewed-by: Patrice Chotard <patrice.chotard@foss.st.com> # spi-stm32-qspi Acked-by: William Zhang <william.zhang@broadcom.com> # bcm63xx-hsspi driver Reviewed-by: Serge Semin <fancer.lancer@gmail.com> # DW SSI part Link: https://lore.kernel.org/r/167847070432.26.15076794204368669839@mailman-core.alsa-project.org Signed-off-by: Mark Brown <broonie@kernel.org>
2023-03-06spi: fsl-dspi: Convert to platform remove callback returning voidUwe Kleine-König1-4/+2
The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de> Link: https://lore.kernel.org/r/20230303172041.2103336-25-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown <broonie@kernel.org>
2022-11-16spi: fsl-dspi: add cs-gpios supportRadu Pirea (NXP OSS)1-2/+34
Make the driver be able to bit-bang a GPIO for the Chip Select pin of select peripherals. The GPIO value is driven by the driver in that case, and none of the hardware Chip Select bits will be populated in the PUSHR register for the TX commands constructed for this peripheral. Signed-off-by: Radu Pirea (NXP OSS) <radu-nicolae.pirea@oss.nxp.com> Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com> Link: https://lore.kernel.org/r/20221111211356.545026-1-vladimir.oltean@nxp.com Signed-off-by: Mark Brown <broonie@kernel.org>
2022-09-26spi: spi-fsl-dspi: Use devm_platform_get_and_ioremap_resource()Yang Yingliang1-2/+1
Use the devm_platform_get_and_ioremap_resource() helper instead of calling platform_get_resource() and devm_ioremap_resource() separately. Signed-off-by: Yang Yingliang <yangyingliang@huawei.com> Link: https://lore.kernel.org/r/20220924131854.964923-1-yangyingliang@huawei.com Signed-off-by: Mark Brown <broonie@kernel.org>
2021-08-10spi: spi-fsl-dspi: Fix issue with uninitialized dma_slave_configTony Lindgren1-0/+1
Depending on the DMA driver being used, the struct dma_slave_config may need to be initialized to zero for the unused data. For example, we have three DMA drivers using src_port_window_size and dst_port_window_size. If these are left uninitialized, it can cause DMA failures. For spi-fsl-dspi, this is probably not currently an issue but is still good to fix though. Fixes: 90ba37033cb9 ("spi: spi-fsl-dspi: Add DMA support for Vybrid") Cc: Sanchayan Maity <maitysanchayan@gmail.com> Cc: Vladimir Oltean <vladimir.oltean@nxp.com> Cc: Peter Ujfalusi <peter.ujfalusi@gmail.com> Cc: Vinod Koul <vkoul@kernel.org> Signed-off-by: Tony Lindgren <tony@atomide.com> Acked-by: Vladimir Oltean <vladimir.oltean@nxp.com> Link: https://lore.kernel.org/r/20210810081727.19491-1-tony@atomide.com Signed-off-by: Mark Brown <broonie@kernel.org>
2021-05-10spi: spi-fsl-dspi: Fix a resource leak in an error handling pathChristophe JAILLET1-1/+3
'dspi_request_dma()' should be undone by a 'dspi_release_dma()' call in the error handling path of the probe function, as already done in the remove function Fixes: 90ba37033cb9 ("spi: spi-fsl-dspi: Add DMA support for Vybrid") Signed-off-by: Christophe JAILLET <christophe.jaillet@wanadoo.fr> Reviewed-by: Vladimir Oltean <olteanv@gmail.com> Link: https://lore.kernel.org/r/d51caaac747277a1099ba8dea07acd85435b857e.1620587472.git.christophe.jaillet@wanadoo.fr Signed-off-by: Mark Brown <broonie@kernel.org>
2020-12-01spi: spi-fsl-dspi: Use max_native_cs instead of num_chipselect to set SPI_MCRMaxim Kochetkov1-3/+3
If cs-gpios property is used in devicetree then ctlr->num_chipselect value may be changed by spi_get_gpio_descs(). So use ctlr->max_native_cs instead of ctlr->num_chipselect to set SPI_MCR Fixes: 4fcc7c2292de (spi: spi-fsl-dspi: Don't access reserved fields in SPI_MCR) Signed-off-by: Maxim Kochetkov <fido_max@inbox.ru> Link: https://lore.kernel.org/r/20201201085916.63543-1-fido_max@inbox.ru Signed-off-by: Mark Brown <broonie@kernel.org>
2020-11-04spi: fsl-dspi: fix wrong pointer in suspend/resumeZhao Qiang1-6/+4
Since commit 530b5affc675 ("spi: fsl-dspi: fix use-after-free in remove path"), this driver causes a "NULL pointer dereference" in dspi_suspend/resume. This is because since this commit, the drivers private data point to "dspi" instead of "ctlr", the codes in suspend and resume func were not modified correspondly. Fixes: 530b5affc675 ("spi: fsl-dspi: fix use-after-free in remove path") Signed-off-by: Zhao Qiang <qiang.zhao@nxp.com> Reviewed-by: Vladimir Oltean <olteanv@gmail.com> Link: https://lore.kernel.org/r/20201103020546.1822-1-qiang.zhao@nxp.com Signed-off-by: Mark Brown <broonie@kernel.org>
2020-10-09Merge remote-tracking branch 'spi/for-5.10' into spi-nextMark Brown1-52/+6
2020-09-28spi: fsl-dspi: fix NULL pointer dereferenceMichael Walle1-2/+3
Since commit 530b5affc675 ("spi: fsl-dspi: fix use-after-free in remove path") this driver causes a kernel oops: [ 1.891065] Unable to handle kernel NULL pointer dereference at virtual address 0000000000000080 [..] [ 2.056973] Call trace: [ 2.059425] dspi_setup+0xc8/0x2e0 [ 2.062837] spi_setup+0xcc/0x248 [ 2.066160] spi_add_device+0xb4/0x198 [ 2.069918] of_register_spi_device+0x250/0x370 [ 2.074462] spi_register_controller+0x4f4/0x770 [ 2.079094] dspi_probe+0x5bc/0x7b0 [ 2.082594] platform_drv_probe+0x5c/0xb0 [ 2.086615] really_probe+0xec/0x3c0 [ 2.090200] driver_probe_device+0x60/0xc0 [ 2.094308] device_driver_attach+0x7c/0x88 [ 2.098503] __driver_attach+0x60/0xe8 [ 2.102263] bus_for_each_dev+0x7c/0xd0 [ 2.106109] driver_attach+0x2c/0x38 [ 2.109692] bus_add_driver+0x194/0x1f8 [ 2.113538] driver_register+0x6c/0x128 [ 2.117385] __platform_driver_register+0x50/0x60 [ 2.122105] fsl_dspi_driver_init+0x24/0x30 [ 2.126302] do_one_initcall+0x54/0x2d0 [ 2.130149] kernel_init_freeable+0x1ec/0x258 [ 2.134520] kernel_init+0x1c/0x120 [ 2.138018] ret_from_fork+0x10/0x34 [ 2.141606] Code: 97e0b11d aa0003f3 b4000680 f94006e0 (f9404000) [ 2.147723] ---[ end trace 26cf63e6cbba33a8 ]--- This is because since this commit, the allocation of the drivers private data is done explicitly and in this case spi_alloc_master() won't set the correct pointer. Also move the platform_set_drvdata() to have both next to each other. Fixes: 530b5affc675 ("spi: fsl-dspi: fix use-after-free in remove path") Signed-off-by: Michael Walle <michael@walle.cc> Tested-by: Sascha Hauer <s.hauer@pengutronix.de> Reviewed-by: Krzysztof Kozlowski <krzk@kernel.org> Link: https://lore.kernel.org/r/20200928085500.28254-1-michael@walle.cc Signed-off-by: Mark Brown <broonie@kernel.org>
2020-09-23spi: fsl-dspi: fix use-after-free in remove pathSascha Hauer1-5/+7
spi_unregister_controller() not only unregisters the controller, but also frees the controller. This will free the driver data with it, so we must not access it later dspi_remove(). Solve this by allocating the driver data separately from the SPI controller. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> Link: https://lore.kernel.org/r/20200923131026.20707-1-s.hauer@pengutronix.de Signed-off-by: Mark Brown <broonie@kernel.org>
2020-09-14spi: spi-fsl-dspi: use XSPI mode instead of DMA for DPAA2 SoCsVladimir Oltean1-3/+3
The arch/arm64/boot/dts/freescale/fsl-ls208xa.dtsi device tree lacks DMA channels for DSPI, so naturally, the driver fails to probe: [ 2.945302] fsl-dspi 2100000.spi: rx dma channel not available [ 2.951134] fsl-dspi 2100000.spi: can't get dma channels In retrospect, this should have been obvious, because LS2080A, LS2085A LS2088A and LX2160A don't appear to have an eDMA module at all. Looking again at their datasheets, the CTARE register (which is specific to XSPI functionality) seems to be documented, so switch them to XSPI mode instead. Fixes: 0feaf8f5afe0 ("spi: spi-fsl-dspi: Convert the instantiations that support it to DMA") Reported-by: Qiang Zhao <qiang.zhao@nxp.com> Tested-by: Qiang Zhao <qiang.zhao@nxp.com> Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com> Link: https://lore.kernel.org/r/20200910121532.1138596-1-olteanv@gmail.com Signed-off-by: Mark Brown <broonie@kernel.org>
2020-09-11spi: spi-fsl-dspi: use XSPI mode instead of DMA for DPAA2 SoCsVladimir Oltean1-3/+3
The arch/arm64/boot/dts/freescale/fsl-ls208xa.dtsi device tree lacks DMA channels for DSPI, so naturally, the driver fails to probe: [ 2.945302] fsl-dspi 2100000.spi: rx dma channel not available [ 2.951134] fsl-dspi 2100000.spi: can't get dma channels In retrospect, this should have been obvious, because LS2080A, LS2085A LS2088A and LX2160A don't appear to have an eDMA module at all. Looking again at their datasheets, the CTARE register (which is specific to XSPI functionality) seems to be documented, so switch them to XSPI mode instead. Fixes: 0feaf8f5afe0 ("spi: spi-fsl-dspi: Convert the instantiations that support it to DMA") Reported-by: Qiang Zhao <qiang.zhao@nxp.com> Tested-by: Qiang Zhao <qiang.zhao@nxp.com> Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com> Link: https://lore.kernel.org/r/20200910121532.1138596-1-olteanv@gmail.com Signed-off-by: Mark Brown <broonie@kernel.org>
2020-08-24spi: spi-fsl-dspi: delete EOQ transfer modeVladimir Oltean1-51/+5
After the only user of the limited EOQ mode has now been converted to DMA as of commit b09058bbf5f0 ("spi: spi-fsl-dspi: set ColdFire to DMA mode"), we can finally delete this code. Signed-off-by: Vladimir Oltean <olteanv@gmail.com> Link: https://lore.kernel.org/r/20200823212657.2400075-1-olteanv@gmail.com Signed-off-by: Mark Brown <broonie@kernel.org>
2020-08-18spi: spi-fsl-dspi: set ColdFire to DMA modeAngelo Dureghello1-1/+1
Set DMA transfer mode for ColdFire. After recent fixes to fsl edma engine, this mode can be used also for ColdFire, and from some raw mtd r/w tests it definitely improves the transfer rate, so keeping it selected. Signed-off-by: Angelo Dureghello <angelo.dureghello@timesys.com> Link: https://lore.kernel.org/r/20200816094635.1830006-1-angelo.dureghello@timesys.com Signed-off-by: Mark Brown <broonie@kernel.org>
2020-06-22spi: spi-fsl-dspi: Initialize completion before possible interruptKrzysztof Kozlowski1-2/+2
The interrupt handler calls completion and is IRQ requested before the completion is initialized. Logically it should be the other way. Signed-off-by: Krzysztof Kozlowski <krzk@kernel.org> Link: https://lore.kernel.org/r/20200622110543.5035-4-krzk@kernel.org Signed-off-by: Mark Brown <broonie@kernel.org>
2020-06-22spi: spi-fsl-dspi: Fix external abort on interrupt in resume or exit pathsKrzysztof Kozlowski1-4/+13
If shared interrupt comes late, during probe error path or device remove (could be triggered with CONFIG_DEBUG_SHIRQ), the interrupt handler dspi_interrupt() will access registers with the clock being disabled. This leads to external abort on non-linefetch on Toradex Colibri VF50 module (with Vybrid VF5xx): $ echo 4002d000.spi > /sys/devices/platform/soc/40000000.bus/4002d000.spi/driver/unbind Unhandled fault: external abort on non-linefetch (0x1008) at 0x8887f02c Internal error: : 1008 [#1] ARM Hardware name: Freescale Vybrid VF5xx/VF6xx (Device Tree) Backtrace: (regmap_mmio_read32le) (regmap_mmio_read) (_regmap_bus_reg_read) (_regmap_read) (regmap_read) (dspi_interrupt) (free_irq) (devm_irq_release) (release_nodes) (devres_release_all) (device_release_driver_internal) The resource-managed framework should not be used for shared interrupt handling, because the interrupt handler might be called after releasing other resources and disabling clocks. Similar bug could happen during suspend - the shared interrupt handler could be invoked after suspending the device. Each device sharing this interrupt line should disable the IRQ during suspend so handler will be invoked only in following cases: 1. None suspended, 2. All devices resumed. Fixes: 349ad66c0ab0 ("spi:Add Freescale DSPI driver for Vybrid VF610 platform") Signed-off-by: Krzysztof Kozlowski <krzk@kernel.org> Tested-by: Vladimir Oltean <vladimir.oltean@nxp.com> Reviewed-by: Vladimir Oltean <vladimir.oltean@nxp.com> Cc: <stable@vger.kernel.org> Link: https://lore.kernel.org/r/20200622110543.5035-3-krzk@kernel.org Signed-off-by: Mark Brown <broonie@kernel.org>
2020-06-22spi: spi-fsl-dspi: Fix lockup if device is shutdown during SPI transferKrzysztof Kozlowski1-14/+1
During shutdown, the driver should unregister the SPI controller and stop the hardware. Otherwise the dspi_transfer_one_message() could wait on completion infinitely. Additionally, calling spi_unregister_controller() first in device shutdown reverse-matches the probe function, where SPI controller is registered at the end. Fixes: dc234825997e ("spi: spi-fsl-dspi: Adding shutdown hook") Reported-by: Vladimir Oltean <olteanv@gmail.com> Signed-off-by: Krzysztof Kozlowski <krzk@kernel.org> Tested-by: Vladimir Oltean <vladimir.oltean@nxp.com> Reviewed-by: Vladimir Oltean <vladimir.oltean@nxp.com> Cc: <stable@vger.kernel.org> Link: https://lore.kernel.org/r/20200622110543.5035-2-krzk@kernel.org Signed-off-by: Mark Brown <broonie@kernel.org>
2020-06-22spi: spi-fsl-dspi: Fix lockup if device is removed during SPI transferKrzysztof Kozlowski1-1/+10
During device removal, the driver should unregister the SPI controller and stop the hardware. Otherwise the dspi_transfer_one_message() could wait on completion infinitely. Additionally, calling spi_unregister_controller() first in device removal reverse-matches the probe function, where SPI controller is registered at the end. Fixes: 05209f457069 ("spi: fsl-dspi: add missing clk_disable_unprepare() in dspi_remove()") Reported-by: Vladimir Oltean <olteanv@gmail.com> Signed-off-by: Krzysztof Kozlowski <krzk@kernel.org> Cc: <stable@vger.kernel.org> Link: https://lore.kernel.org/r/20200622110543.5035-1-krzk@kernel.org Signed-off-by: Mark Brown <broonie@kernel.org>
2020-06-11spi: spi-fsl-dspi: Free DMA memory with matching functionKrzysztof Kozlowski1-4/+4
Driver allocates DMA memory with dma_alloc_coherent() but frees it with dma_unmap_single(). This causes DMA warning during system shutdown (with DMA debugging) on Toradex Colibri VF50 module: WARNING: CPU: 0 PID: 1 at ../kernel/dma/debug.c:1036 check_unmap+0x3fc/0xb04 DMA-API: fsl-edma 40098000.dma-controller: device driver frees DMA memory with wrong function [device address=0x0000000087040000] [size=8 bytes] [mapped as coherent] [unmapped as single] Hardware name: Freescale Vybrid VF5xx/VF6xx (Device Tree) (unwind_backtrace) from [<8010bb34>] (show_stack+0x10/0x14) (show_stack) from [<8011ced8>] (__warn+0xf0/0x108) (__warn) from [<8011cf64>] (warn_slowpath_fmt+0x74/0xb8) (warn_slowpath_fmt) from [<8017d170>] (check_unmap+0x3fc/0xb04) (check_unmap) from [<8017d900>] (debug_dma_unmap_page+0x88/0x90) (debug_dma_unmap_page) from [<80601d68>] (dspi_release_dma+0x88/0x110) (dspi_release_dma) from [<80601e4c>] (dspi_shutdown+0x5c/0x80) (dspi_shutdown) from [<805845f8>] (device_shutdown+0x17c/0x220) (device_shutdown) from [<80143ef8>] (kernel_restart+0xc/0x50) (kernel_restart) from [<801441cc>] (__do_sys_reboot+0x18c/0x210) (__do_sys_reboot) from [<80100060>] (ret_fast_syscall+0x0/0x28) DMA-API: Mapped at: dma_alloc_attrs+0xa4/0x130 dspi_probe+0x568/0x7b4 platform_drv_probe+0x6c/0xa4 really_probe+0x208/0x348 driver_probe_device+0x5c/0xb4 Fixes: 90ba37033cb9 ("spi: spi-fsl-dspi: Add DMA support for Vybrid") Signed-off-by: Krzysztof Kozlowski <krzk@kernel.org> Acked-by: Vladimir Oltean <vladimir.oltean@nxp.com> Cc: <stable@vger.kernel.org> Link: https://lore.kernel.org/r/1591803717-11218-1-git-send-email-krzk@kernel.org Signed-off-by: Mark Brown <broonie@kernel.org>
2020-05-30spi: spi-fsl-dspi: fix native data copyAngelo Dureghello1-2/+22
ColdFire is a big-endian cpu with a big-endian dspi hw module, so, it uses native access, but memcpy breaks the endianness. So, if i understand properly, by native copy we would mean be(cpu)->be(dspi) or le(cpu)->le(dspi) accesses, so my fix shouldn't break anything, but i couldn't test it on LS family, so every test is really appreciated. Fixes: 53fadb4d90c7 ("spi: spi-fsl-dspi: Simplify bytes_per_word gymnastics") Signed-off-by: Angelo Dureghello <angelo.dureghello@timesys.com> Tested-by: Vladimir Oltean <vladimir.oltean@nxp.com> Reviewed-by: Vladimir Oltean <vladimir.oltean@nxp.com> Link: https://lore.kernel.org/r/20200529195756.184677-1-angelo.dureghello@timesys.com Signed-off-by: Mark Brown <broonie@kernel.org>
2020-04-24spi: spi-fsl-dspi: Adding shutdown hookPeng Ma1-0/+23
We need to ensure dspi controller could be stopped in order for kexec to start the next kernel. So add the shutdown operation support. Signed-off-by: Peng Ma <peng.ma@nxp.com> Link: https://lore.kernel.org/r/20200424061216.27445-1-peng.ma@nxp.com Signed-off-by: Mark Brown <broonie@kernel.org>
2020-03-19spi: spi-fsl-dspi: Add support for LS1028AVladimir Oltean1-0/+9
This is similar to the DSPI instantiation on LS1028A, except that: - The A-011218 erratum has been fixed, so DMA works - The endianness is different, which has implications on XSPI mode Some benchmarking with the following command: spidev_test --device /dev/spidev2.0 --bpw 8 --size 256 --cpha --iter 10000000 --speed 20000000 shows that in DMA mode, it can achieve around 2400 kbps, and in XSPI mode, the same command goes up to 4700 kbps. This is somewhat to be expected, since the DMA buffer size is extremely small at 8 bytes, the winner becomes whomever can prepare the buffers for transmission quicker, and DMA mode has higher overhead there. So XSPI FIFO mode has been chosen as the operating mode for this chip. Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com> Tested-by: Michael Walle <michael@walle.cc> Link: https://lore.kernel.org/r/20200318001603.9650-11-olteanv@gmail.com Signed-off-by: Mark Brown <broonie@kernel.org>
2020-03-19spi: spi-fsl-dspi: Move invariant configs out of dspi_transfer_one_messageVladimir Oltean1-26/+29
The operating mode (DMA, XSPI, EOQ) is not going to change across the lifetime of the device. So it makes no sense to keep writing to SPI_RSER on each message. Move this configuration to dspi_init instead. Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com> Tested-by: Michael Walle <michael@walle.cc> Link: https://lore.kernel.org/r/20200318001603.9650-10-olteanv@gmail.com Signed-off-by: Mark Brown <broonie@kernel.org>
2020-03-19spi: spi-fsl-dspi: Fix interrupt-less DMA mode taking an XSPI code pathVladimir Oltean1-7/+9
Interrupts are not necessary for DMA functionality, since the completion event is provided by the DMA driver. But if the driver fails to request the IRQ defined in the device tree, it will call dspi_poll which would make the driver hang waiting for data to become available in the RX FIFO. Fixes: c55be3059159 ("spi: spi-fsl-dspi: Use poll mode in case the platform IRQ is missing") Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com> Tested-by: Michael Walle <michael@walle.cc> Link: https://lore.kernel.org/r/20200318001603.9650-9-olteanv@gmail.com Signed-off-by: Mark Brown <broonie@kernel.org>
2020-03-19spi: spi-fsl-dspi: Avoid NULL pointer in dspi_slave_abort for non-DMA modeVladimir Oltean1-2/+4
The driver does not create the dspi->dma structure unless operating in DSPI_DMA_MODE, so it makes sense to check for that. Fixes: f4b323905d8b ("spi: Introduce dspi_slave_abort() function for NXP's dspi SPI driver") Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com> Tested-by: Michael Walle <michael@walle.cc> Link: https://lore.kernel.org/r/20200318001603.9650-8-olteanv@gmail.com Signed-off-by: Mark Brown <broonie@kernel.org>
2020-03-19spi: spi-fsl-dspi: Replace interruptible wait queue with a simple completionVladimir Oltean1-13/+6
Currently the driver puts the process in interruptible sleep waiting for the interrupt train to finish transfer to/from the tx_buf and rx_buf. But exiting the process with ctrl-c may make the kernel panic: the wait_event_interruptible call will return -ERESTARTSYS, which a proper driver implementation is perhaps supposed to handle, but nonetheless this one doesn't, and aborts the transfer altogether. Actually when the task is interrupted, there is still a high chance that the dspi_interrupt is still triggering. And if dspi_transfer_one_message returns execution all the way to the spi_device driver, that can free the spi_message and spi_transfer structures, leaving the interrupts to access a freed tx_buf and rx_buf. hexdump -C /dev/mtd0 00000000 00 75 68 75 0a ff ff ff ff ff ff ff ff ff ff ff |.uhu............| 00000010 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| * ^C[ 38.495955] fsl-dspi 2120000.spi: Waiting for transfer to complete failed! [ 38.503097] spi_master spi2: failed to transfer one message from queue [ 38.509729] Unable to handle kernel paging request at virtual address ffff800095ab3377 [ 38.517676] Mem abort info: [ 38.520474] ESR = 0x96000045 [ 38.523533] EC = 0x25: DABT (current EL), IL = 32 bits [ 38.528861] SET = 0, FnV = 0 [ 38.531921] EA = 0, S1PTW = 0 [ 38.535067] Data abort info: [ 38.537952] ISV = 0, ISS = 0x00000045 [ 38.541797] CM = 0, WnR = 1 [ 38.544771] swapper pgtable: 4k pages, 48-bit VAs, pgdp=0000000082621000 [ 38.551494] [ffff800095ab3377] pgd=00000020fffff003, p4d=00000020fffff003, pud=0000000000000000 [ 38.560229] Internal error: Oops: 96000045 [#1] PREEMPT SMP [ 38.565819] Modules linked in: [ 38.568882] CPU: 0 PID: 2729 Comm: hexdump Not tainted 5.6.0-rc4-next-20200306-00052-gd8730cdc8a0b-dirty #193 [ 38.578834] Hardware name: Kontron SMARC-sAL28 (Single PHY) on SMARC Eval 2.0 carrier (DT) [ 38.587129] pstate: 20000085 (nzCv daIf -PAN -UAO) [ 38.591941] pc : ktime_get_real_ts64+0x3c/0x110 [ 38.596487] lr : spi_take_timestamp_pre+0x40/0x90 [ 38.601203] sp : ffff800010003d90 [ 38.604525] x29: ffff800010003d90 x28: ffff80001200e000 [ 38.609854] x27: ffff800011da9000 x26: ffff002079c40400 [ 38.615184] x25: ffff8000117fe018 x24: ffff800011daa1a0 [ 38.620513] x23: ffff800015ab3860 x22: ffff800095ab3377 [ 38.625841] x21: 000000000000146e x20: ffff8000120c3000 [ 38.631170] x19: ffff0020795f6e80 x18: ffff800011da9948 [ 38.636498] x17: 0000000000000000 x16: 0000000000000000 [ 38.641826] x15: ffff800095ab3377 x14: 0720072007200720 [ 38.647155] x13: 0720072007200765 x12: 0775076507750771 [ 38.652483] x11: 0720076d076f0772 x10: 0000000000000040 [ 38.657812] x9 : ffff8000108e2100 x8 : ffff800011dcabe8 [ 38.663139] x7 : 0000000000000000 x6 : ffff800015ab3a60 [ 38.668468] x5 : 0000000007200720 x4 : ffff800095ab3377 [ 38.673796] x3 : 0000000000000000 x2 : 0000000000000ab0 [ 38.679125] x1 : ffff800011daa000 x0 : 0000000000000026 [ 38.684454] Call trace: [ 38.686905] ktime_get_real_ts64+0x3c/0x110 [ 38.691100] spi_take_timestamp_pre+0x40/0x90 [ 38.695470] dspi_fifo_write+0x58/0x2c0 [ 38.699315] dspi_interrupt+0xbc/0xd0 [ 38.702987] __handle_irq_event_percpu+0x78/0x2c0 [ 38.707706] handle_irq_event_percpu+0x3c/0x90 [ 38.712161] handle_irq_event+0x4c/0xd0 [ 38.716008] handle_fasteoi_irq+0xbc/0x170 [ 38.720115] generic_handle_irq+0x2c/0x40 [ 38.724135] __handle_domain_irq+0x68/0xc0 [ 38.728243] gic_handle_irq+0xc8/0x160 [ 38.732000] el1_irq+0xb8/0x180 [ 38.735149] spi_nor_spimem_read_data+0xe0/0x140 [ 38.739779] spi_nor_read+0xc4/0x120 [ 38.743364] mtd_read_oob+0xa8/0xc0 [ 38.746860] mtd_read+0x4c/0x80 [ 38.750007] mtdchar_read+0x108/0x2a0 [ 38.753679] __vfs_read+0x20/0x50 [ 38.757002] vfs_read+0xa4/0x190 [ 38.760237] ksys_read+0x6c/0xf0 [ 38.763471] __arm64_sys_read+0x20/0x30 [ 38.767319] el0_svc_common.constprop.3+0x90/0x160 [ 38.772125] do_el0_svc+0x28/0x90 [ 38.775449] el0_sync_handler+0x118/0x190 [ 38.779468] el0_sync+0x140/0x180 [ 38.782793] Code: 91000294 1400000f d50339bf f9405e80 (f90002c0) [ 38.788910] ---[ end trace 55da560db4d6bef7 ]--- [ 38.793540] Kernel panic - not syncing: Fatal exception in interrupt [ 38.799914] SMP: stopping secondary CPUs [ 38.803849] Kernel Offset: disabled [ 38.807344] CPU features: 0x10002,20006008 [ 38.811451] Memory Limit: none [ 38.814513] ---[ end Kernel panic - not syncing: Fatal exception in interrupt ]--- So it is clear that the "interruptible" part isn't handled correctly. When the process receives a signal, one could either attempt a clean abort (which appears to be difficult with this hardware) or just keep restarting the sleep until the wait queue really completes. But checking in a loop for -ERESTARTSYS is a bit too complicated for this driver, so just make the sleep uninterruptible, to avoid all that nonsense. The wait queue was actually restructured as a completion, after polling other drivers for the most "popular" approach. Fixes: 349ad66c0ab0 ("spi:Add Freescale DSPI driver for Vybrid VF610 platform") Reported-by: Michael Walle <michael@walle.cc> Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com> Tested-by: Michael Walle <michael@walle.cc> Link: https://lore.kernel.org/r/20200318001603.9650-7-olteanv@gmail.com Signed-off-by: Mark Brown <broonie@kernel.org>
2020-03-19spi: spi-fsl-dspi: Protect against races on dspi->words_in_flightVladimir Oltean1-59/+52
dspi->words_in_flight is a variable populated in the *_write functions and used in the dspi_fifo_read function. It is also used in dspi_fifo_write, immediately after transmission, to update the message->actual_length variable used by higher layers such as spi-mem for integrity checking. But it may happen that the IRQ which calls dspi_fifo_read to be triggered before the updating of message->actual_length takes place. In that case, dspi_fifo_read will decrement dspi->words_in_flight to -1, and that will cause an invalid modification of message->actual_length. For that, we make the simplest fix possible: to not decrement the actual shared variable in dspi->words_in_flight from dspi_fifo_read, but actually a copy of it which is on stack. But even if dspi_fifo_read from the next IRQ does not interfere with the dspi_fifo_write of the current chunk, the *next* dspi_fifo_write still can. So we must assume that everything after the last write to the TX FIFO can be preempted by the "TX complete" IRQ, and the dspi_fifo_write function must be safe against that. This means refactoring the 2 flavours of FIFO writes (for EOQ and XSPI) such that the calculation of the number of words to be written is common and happens a priori. This way, the code for updating the message->actual_length variable works with a copy and not with the volatile dspi->words_in_flight. After some interior debate, the dspi->progress variable used for software timestamping was *not* backed up against preemption in a copy on stack. Because if preemption does occur between spi_take_timestamp_pre and spi_take_timestamp_post, there's really no point in trying to save anything. The first-in-time spi_take_timestamp_post call with a dspi->progress higher than the requested xfer->ptp_sts_word_post will trigger xfer->timestamped = true anyway and will close the deal. To understand the above a bit better, consider a transfer with xfer->ptp_sts_word_pre = xfer->ptp_sts_word_post = 3, and xfer->bits_per_words = 8 (so byte 3 needs to be timestamped). The DSPI controller timestamps in chunks of 4 bytes at a time, and preemption occurs in the middle of timestamping the first chunk: spi_take_timestamp_pre(0) . . (preemption) . . spi_take_timestamp_pre(4) . . spi_take_timestamp_post(7) . spi_take_timestamp_post(3) So the reason I'm not bothering to back up dspi->progress for that spi_take_timestamp_post(3) is that spi_take_timestamp_post(7) is going to (a) be more honest, (b) provide better accuracy and (c) already render the spi_take_timestamp_post(3) into a noop by setting xfer->timestamped = true anyway. Fixes: d59c90a2400f ("spi: spi-fsl-dspi: Convert TCFQ users to XSPI FIFO mode") Reported-by: Michael Walle <michael@walle.cc> Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com> Tested-by: Michael Walle <michael@walle.cc> Link: https://lore.kernel.org/r/20200318001603.9650-6-olteanv@gmail.com Signed-off-by: Mark Brown <broonie@kernel.org>
2020-03-19spi: spi-fsl-dspi: Avoid reading more data than written in EOQ modeVladimir Oltean1-2/+5
If dspi->words_in_flight is populated with the hardware FIFO size, then in dspi_fifo_read it will attempt to read more data at the end of a buffer that is not a multiple of 16 bytes in length. It will probably time out attempting to do so. So limit the num_fifo_entries variable to the actual number of FIFO entries that is going to be used. Fixes: d59c90a2400f ("spi: spi-fsl-dspi: Convert TCFQ users to XSPI FIFO mode") Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com> Tested-by: Michael Walle <michael@walle.cc> Link: https://lore.kernel.org/r/20200318001603.9650-5-olteanv@gmail.com Signed-off-by: Mark Brown <broonie@kernel.org>
2020-03-19spi: spi-fsl-dspi: Fix bits-per-word acceleration in DMA modeVladimir Oltean1-54/+32
In DMA mode, dspi_setup_accel does not get called, which results in the dspi->oper_word_size variable (which is used by dspi_dma_xfer) to not be initialized properly. Because oper_word_size is zero, a few calculations end up being incorrect, and the DMA transfer eventually times out instead of sending anything on the wire. Set up native transfers (or 8-on-16 acceleration) using dspi_setup_accel for DMA mode too. Also take the opportunity and simplify the DMA buffer handling a little bit. Fixes: 6c1c26ecd9a3 ("spi: spi-fsl-dspi: Accelerate transfers using larger word size if possible") Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com> Tested-by: Michael Walle <michael@walle.cc> Link: https://lore.kernel.org/r/20200318001603.9650-4-olteanv@gmail.com Signed-off-by: Mark Brown <broonie@kernel.org>
2020-03-19spi: spi-fsl-dspi: Fix little endian access to PUSHR CMD and TXDATAVladimir Oltean1-6/+20
In XSPI mode, the 32-bit PUSHR register can be written to separately: the higher 16 bits are for commands and the lower 16 bits are for data. This has nicely been hacked around, by defining a second regmap with a width of 16 bits, and effectively splitting a 32-bit register into 2 16-bit ones, from the perspective of this regmap_pushr. The problem is the assumption about the controller's endianness. If the controller is little endian (such as anything post-LS1046A), then the first 2 bytes, in the order imposed by memory layout, will actually hold the TXDATA, and the last 2 bytes will hold the CMD. So take the controller's endianness into account when performing split writes to PUSHR. The obvious and simple solution would have been to call regmap_get_val_endian(), but that is an internal regmap function and we don't want to change regmap just for this. Therefore, we just re-read the "big-endian" device tree property. Fixes: 58ba07ec79e6 ("spi: spi-fsl-dspi: Add support for XSPI mode registers") Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com> Tested-by: Michael Walle <michael@walle.cc> Link: https://lore.kernel.org/r/20200318001603.9650-3-olteanv@gmail.com Signed-off-by: Mark Brown <broonie@kernel.org>
2020-03-19spi: spi-fsl-dspi: Don't access reserved fields in SPI_MCRVladimir Oltean1-2/+5
The SPI_MCR_PCSIS macro assumes that the controller has a number of chip select signals equal to 6. That is not always the case, but actually is described through the driver-specific "spi-num-chipselects" device tree binding. LS1028A for example only has 4 chip selects. Don't write to the upper bits of the PCSIS field, which are reserved in the reference manual. Fixes: 349ad66c0ab0 ("spi:Add Freescale DSPI driver for Vybrid VF610 platform") Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com> Tested-by: Michael Walle <michael@walle.cc> Link: https://lore.kernel.org/r/20200318001603.9650-2-olteanv@gmail.com Signed-off-by: Mark Brown <broonie@kernel.org>
2020-03-10spi: spi-fsl-dspi: fix DMA mappingMichael Walle1-7/+10
Use the correct device to request the DMA mapping. Otherwise the IOMMU doesn't get the mapping and it will generate a page fault. The error messages look like: [ 3.008452] arm-smmu 5000000.iommu: Unhandled context fault: fsr=0x402, iova=0xf9800000, fsynr=0x3f0022, cbfrsynra=0x828, cb=8 [ 3.020123] arm-smmu 5000000.iommu: Unhandled context fault: fsr=0x402, iova=0xf9800000, fsynr=0x3f0022, cbfrsynra=0x828, cb=8 This was tested on a custom board with a LS1028A SoC. Signed-off-by: Michael Walle <michael@walle.cc> Link: https://lore.kernel.org/r/20200310073313.21277-1-michael@walle.cc Signed-off-by: Mark Brown <broonie@kernel.org>
2020-03-05Merge series "TCFQ to XSPI migration for NXP DSPI driver" from Vladimir ↵Mark Brown1-141/+280
Oltean <olteanv@gmail.com> Vladimir Oltean <vladimir.oltean@nxp.com>: From: Vladimir Oltean <vladimir.oltean@nxp.com> This series aims to remove the most inefficient transfer method from the NXP DSPI driver. TCFQ (Transfer Complete Flag) mode works by transferring one word, waiting for its TX confirmation interrupt (or polling on the equivalent status bit), sending the next word, etc, until the buffer is complete. The issue with this mode is that it's fundamentally incompatible with any sort of batching such as writing to a FIFO. But actually, due to previous patchset ("Compatible string consolidation for NXP DSPI driver"): https://patchwork.kernel.org/cover/11414593/ all existing users of TCFQ mode today already support a more advanced feature set, in the form of XSPI (extended SPI). XSPI brings 2 extra features: - Word sizes up to 32 bits. This is sub-utilized today, and acceleration of smaller-than-32 bpw values is provided. - "Command cycling", basically the ability to write multiple words in a row and receiving an interrupt only after the completion of the last one. This is what enables us to make use of the full FIFO depth of this controller. Series was tested on the NXP LS1021A-TSN and LS1043A-RDB boards, both functionally as well as from a performance standpoint. The command used to benchmark the increased throughput was: spidev_test --device /dev/spidev1.0 --bpw 8 --size 256 --cpha --iter 10000000 --speed 20000000 where spidev1.0 is a dummy spidev node, using a chip select that no peripheral responds to. On LS1021A, which has a 4-entry-deep FIFO and a less powerful CPU, the performance increase brought by this patchset is from 2700 kbps to 5800 kbps. On LS1043A, which has a 16-entry-deep FIFO and a more powerful CPU, the performance increases from 4100 kbps to 13700 kbps. On average, SPI software timestamping is not adversely affected by the extra batching, due to the extra patches. There is one extra patch which clarifies why the TCFQ users were not converted to the "other" mode in this driver that makes use of the FIFO, which would be EOQ mode. My request to the many people on CC (known users and/or contributors) is to give this series a test to ensure there are no regressions, and for the Coldfire maintainers to clarify whether the EOQ limitation is acceptable for them in the long run. Vladimir Oltean (12): spi: spi-fsl-dspi: Simplify bytes_per_word gymnastics spi: spi-fsl-dspi: Remove unused chip->void_write_data spi: spi-fsl-dspi: Don't mask off undefined bits spi: spi-fsl-dspi: Add comments around dspi_pop_tx and dspi_push_rx functions spi: spi-fsl-dspi: Rename fifo_{read,write} and {tx,cmd}_fifo_write spi: spi-fsl-dspi: Implement .max_message_size method for EOQ mode spi: Do spi_take_timestamp_pre for as many times as necessary spi: spi-fsl-dspi: Convert TCFQ users to XSPI FIFO mode spi: spi-fsl-dspi: Accelerate transfers using larger word size if possible spi: spi-fsl-dspi: Optimize dspi_setup_accel for lowest interrupt count spi: spi-fsl-dspi: Use EOQ for last word in buffer even for XSPI mode spi: spi-fsl-dspi: Take software timestamp in dspi_fifo_write drivers/spi/spi-fsl-dspi.c | 421 ++++++++++++++++++++++++------------- drivers/spi/spi.c | 19 +- include/linux/spi/spi.h | 3 +- 3 files changed, 288 insertions(+), 155 deletions(-) -- 2.17.1
2020-03-05spi: spi-fsl-dspi: Make bus-num property optionalSascha Hauer1-6/+2
The SPI bus number is completely optional to Linux, so make the corresponding device tree property optional as well. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> Link: https://lore.kernel.org/r/20200305115546.31814-1-s.hauer@pengutronix.de Signed-off-by: Mark Brown <broonie@kernel.org>
2020-03-05spi: spi-fsl-dspi: Take software timestamp in dspi_fifo_writeVladimir Oltean1-10/+9
Although the SPI system timestamps are supposed to reflect the moment that the peripheral has received a word rather than the moment when the CPU has enqueued that word to the FIFO, in practice it is easier to just record the latter time than the former (with a smaller error). With the recent migration of TCFQ users from poll back to interrupt mode (this time for XSPI FIFO), it's wiser to keep the interrupt latency outside of the measurement of the PTP system timestamp itself. If there proves to be any constant offset that requires static compensation, that can always be added later. So far that does not appear to be the case at least on the LS1021A-TSN board, where testing shows that the phc2sys offset is able to remain within +/- 200 ns even after 68 hours of testing. Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com> Link: https://lore.kernel.org/r/20200304220044.11193-13-olteanv@gmail.com Signed-off-by: Mark Brown <broonie@kernel.org>
2020-03-05spi: spi-fsl-dspi: Use EOQ for last word in buffer even for XSPI modeVladimir Oltean1-9/+13
The EOQ mode has a hardware limitation in that it stops the transmission (including the deassertion of the chip select signal) once the host CPU requests end-of-queue for a particular word in the TX FIFO. And XSPI mode has a limitation in that we need a separate CMD FIFO entry for the last byte in the buffer, where the chip select signal needs to be deasserted. It's not a functional limitation, but it's rather clunky and the fact that we need to halt the pipeline and write a single entry to the TX FIFO whenever a buffer ends brings the throughput down when transmitting small buffers. So the idea here is to use EOQ's limitation in our favor when using XSPI mode. Stop special-casing that final word in the buffer, and just kill the chip select signal by issuing an EOQ for that last word. Now it can be mixed in with all the other words in the current TX FIFO train. A small trick here is that we still keep using the XSPI-specific signaling via the CMDTCFQ interrupt in RSER, and not enabling the EOQ interrupt, in order to avoid hardware weirdness (potential races with separate interrupts being raised for CMDTCFQ and EOQ for what is in fact the end of the same transmission). That is just theoretical, but it's good to be cautious, and the EOQ interrupt isn't needed. Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com> Link: https://lore.kernel.org/r/20200304220044.11193-12-olteanv@gmail.com Signed-off-by: Mark Brown <broonie@kernel.org>
2020-03-05spi: spi-fsl-dspi: Optimize dspi_setup_accel for lowest interrupt countVladimir Oltean1-11/+25
Currently, a SPI transfer that is not multiple of the highest supported word width (e.g. 4 bytes) will be transmitted as follows (assume a 30-byte buffer transmitted through a 32-bit wide FIFO that is 32 bytes deep): - First 28 bytes are sent as 7 words of 32 bits each - Last 2 bytes are sent as 1 word of 16 bits size But if the dspi_setup_accel function had decided to use a lower oper_bits_per_word value (16 instead of 32), there would have been enough space in the TX FIFO to fit the entire buffer in one go (15 words of 16 bits each). What we're actually trying to avoid is mixing word sizes within the same run with the TX FIFO, since there is an erratum surrounding this, and invalid data might get transmitted. So this patch adds special cases for when the remaining length of the buffer can be sent in one go as 8-bit or 16-bit words, otherwise it falls back to the standard logic of sending as many bytes as possible at the highest oper_bits_per_word value possible. The benefit is that there will be one less CMDFQ/EOQ interrupt to service when the entire buffer is transmitted during a single go, and that will improve the overall latency of the transfer. Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com> Link: https://lore.kernel.org/r/20200304220044.11193-11-olteanv@gmail.com Signed-off-by: Mark Brown <broonie@kernel.org>
2020-03-05spi: spi-fsl-dspi: Accelerate transfers using larger word size if possibleVladimir Oltean1-25/+135
This patch adds logic in the driver to transmit SPI buffers that use bits_per_word=8 with a higher bits_per_word count (multiple of 8). Currently the following (most common) modes are implemented: - 8 bits_per_word on 32-bit capable controllers - 8 bits_per_word on 16-bit capable controllers - 16 bits_per_word on 32-bit capable controllers Transfers which are not accelerated are transferred with a hardware bits_per_word value equal to the one of the SPI transfer. The difference from just extending bits_per_word=32 at the spi_device driver level is that endianness is different - the SPI core wants to treat bits_per_word=32 buffers as arrays of u32 (i.e. words in host CPU endianness). So to preserve endianness when clumping 8x4 bits into 32-bit words, one must perform conversion between CPU and standard (big) endianness. All appearances (both on the wire as well as in the buffers presented to the peripheral driver) are preserved, just that accesses to the PUSHR and POPR registers are now more efficient, since the same number of reads/writes can now carry more data (2x more data on TX, 4x more data on RX). Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com> Link: https://lore.kernel.org/r/20200304220044.11193-10-olteanv@gmail.com Signed-off-by: Mark Brown <broonie@kernel.org>
2020-03-05spi: spi-fsl-dspi: Convert TCFQ users to XSPI FIFO modeVladimir Oltean1-88/+101
The Transfer Complete Flag (TCF) interrupt gets raised after each write to the TX FIFO (PUSHR) which means that it is not possible to devise a transfer procedure that makes full utilization of the FIFO depth (4 entries on most controllers, 16 entries on some). On the other hand, XSPI mode has a feature called "command cycling", which allows a single TX command to be run for a pre-specified number of TX words. When the command cycle ends, the Command Transfer Complete Flag bit asserts and raises an interrupt. The advantage in this mode is that the TX FIFO can be better utilized (more words can be batched at once). Other changes brought by this patch: - The dspi->rx_end variable has been removed, since now the dspi_fifo_write function sets up dspi->words_in_flight, so dspi_fifo_read knows how much to read without overrunning the RX buffer. - Stop using poll mode unconditionally for TCFQ mode, since XSPI mode is a little less efficient than that, and so, poll mode doesn't bring as many improvements for XSPI. - Stop relying on the hardware transfer counter (SPI_TCR_GET_TCNT) and instead increment the message->actual_length based on the newly introduced dspi->words_in_flight variable. - The CTARE register is now written in the hotpath instead of just at transfer init time, since it contains the DTCP field (transfer preload - the counter indicating how many txdata words will follow), which is a dynamic value. Due to the fact that the Chip Select toggling setting is part of the command written to the TX FIFO, the ending word of each buffer needs to be sent via its own TX command, so that we have a chance to emit a 1-word command with deasserted PCS. Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com> Link: https://lore.kernel.org/r/20200304220044.11193-9-olteanv@gmail.com Signed-off-by: Mark Brown <broonie@kernel.org>