From 5cc7b04740effa5cc0af53f434134b5859d58b73 Mon Sep 17 00:00:00 2001 From: Alexander Stein Date: Tue, 4 Nov 2014 09:20:18 +0100 Subject: [PATCH 1/2] spi: fsl-dspi: Fix CTAR selection There are only 4 CTAR registers (CTAR0 - CTAR3) so we can only use the lower 2 bits of the chip select to select a CTAR register. SPI_PUSHR_CTAS used the lower 3 bits which would result in wrong bit values if the chip selects 4/5 are used. For those chip selects SPI_CTAR even calculated offsets of non-existing registers. Signed-off-by: Alexander Stein Signed-off-by: Mark Brown Cc: stable@vger.kernel.org --- drivers/spi/spi-fsl-dspi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/spi/spi-fsl-dspi.c b/drivers/spi/spi-fsl-dspi.c index 448216025ce8..831ceb4a91f6 100644 --- a/drivers/spi/spi-fsl-dspi.c +++ b/drivers/spi/spi-fsl-dspi.c @@ -46,7 +46,7 @@ #define SPI_TCR 0x08 -#define SPI_CTAR(x) (0x0c + (x * 4)) +#define SPI_CTAR(x) (0x0c + (((x) & 0x3) * 4)) #define SPI_CTAR_FMSZ(x) (((x) & 0x0000000f) << 27) #define SPI_CTAR_CPOL(x) ((x) << 26) #define SPI_CTAR_CPHA(x) ((x) << 25) @@ -70,7 +70,7 @@ #define SPI_PUSHR 0x34 #define SPI_PUSHR_CONT (1 << 31) -#define SPI_PUSHR_CTAS(x) (((x) & 0x00000007) << 28) +#define SPI_PUSHR_CTAS(x) (((x) & 0x00000003) << 28) #define SPI_PUSHR_EOQ (1 << 27) #define SPI_PUSHR_CTCNT (1 << 26) #define SPI_PUSHR_PCS(x) (((1 << x) & 0x0000003f) << 16) From 2b9375b91bef65b837bed61a05fb387159b38ddf Mon Sep 17 00:00:00 2001 From: Dmitry Eremin-Solenikov Date: Thu, 6 Nov 2014 14:08:29 +0300 Subject: [PATCH 2/2] spi: pxa2xx: toggle clocks on suspend if not disabled by runtime PM If PM_RUNTIME is enabled, it is easy to trigger the following backtrace on pxa2xx hosts: ------------[ cut here ]------------ WARNING: CPU: 0 PID: 1 at /home/lumag/linux/arch/arm/mach-pxa/clock.c:35 clk_disable+0xa0/0xa8() Modules linked in: CPU: 0 PID: 1 Comm: swapper Not tainted 3.17.0-00007-g1b3d2ee-dirty #104 [] (unwind_backtrace) from [] (show_stack+0x10/0x14) [] (show_stack) from [] (warn_slowpath_common+0x6c/0x8c) [] (warn_slowpath_common) from [] (warn_slowpath_null+0x1c/0x24) [] (warn_slowpath_null) from [] (clk_disable+0xa0/0xa8) [] (clk_disable) from [] (pxa2xx_spi_suspend+0x2c/0x34) [] (pxa2xx_spi_suspend) from [] (platform_pm_suspend+0x2c/0x54) [] (platform_pm_suspend) from [] (dpm_run_callback.isra.14+0x2c/0x74) [] (dpm_run_callback.isra.14) from [] (__device_suspend+0x120/0x2f8) [] (__device_suspend) from [] (dpm_suspend+0x50/0x208) [] (dpm_suspend) from [] (suspend_devices_and_enter+0x8c/0x3a0) [] (suspend_devices_and_enter) from [] (pm_suspend+0x214/0x2a8) [] (pm_suspend) from [] (test_suspend+0x14c/0x1dc) [] (test_suspend) from [] (do_one_initcall+0x8c/0x1fc) [] (do_one_initcall) from [] (kernel_init_freeable+0xf4/0x1b4) [] (kernel_init_freeable) from [] (kernel_init+0x8/0xec) [] (kernel_init) from [] (ret_from_fork+0x14/0x24) ---[ end trace 46524156d8faa4f6 ]--- This happens because suspend function tries to disable a clock that is already disabled by runtime_suspend callback. Add if (!pm_runtime_suspended()) checks to suspend/resume path. Fixes: 7d94a505858 (spi/pxa2xx: add support for runtime PM) Signed-off-by: Dmitry Eremin-Solenikov Reported-by: Andrea Adami Signed-off-by: Mark Brown Cc: stable@vger.kernel.org --- drivers/spi/spi-pxa2xx.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/spi/spi-pxa2xx.c b/drivers/spi/spi-pxa2xx.c index d8a105f76837..9e9e0f971e6c 100644 --- a/drivers/spi/spi-pxa2xx.c +++ b/drivers/spi/spi-pxa2xx.c @@ -1274,7 +1274,9 @@ static int pxa2xx_spi_suspend(struct device *dev) if (status != 0) return status; write_SSCR0(0, drv_data->ioaddr); - clk_disable_unprepare(ssp->clk); + + if (!pm_runtime_suspended(dev)) + clk_disable_unprepare(ssp->clk); return 0; } @@ -1288,7 +1290,8 @@ static int pxa2xx_spi_resume(struct device *dev) pxa2xx_spi_dma_resume(drv_data); /* Enable the SSP clock */ - clk_prepare_enable(ssp->clk); + if (!pm_runtime_suspended(dev)) + clk_prepare_enable(ssp->clk); /* Restore LPSS private register bits */ lpss_ssp_setup(drv_data);