diff options
Diffstat (limited to 'drivers/spi/spi-imx.c')
-rw-r--r-- | drivers/spi/spi-imx.c | 75 |
1 files changed, 41 insertions, 34 deletions
diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c index e4ccd0c329d0..34e5f81ec431 100644 --- a/drivers/spi/spi-imx.c +++ b/drivers/spi/spi-imx.c @@ -252,6 +252,18 @@ static bool spi_imx_can_dma(struct spi_controller *controller, struct spi_device return true; } +/* + * Note the number of natively supported chip selects for MX51 is 4. Some + * devices may have less actual SS pins but the register map supports 4. When + * using gpio chip selects the cs values passed into the macros below can go + * outside the range 0 - 3. We therefore need to limit the cs value to avoid + * corrupting bits outside the allocated locations. + * + * The simplest way to do this is to just mask the cs bits to 2 bits. This + * still allows all 4 native chip selects to work as well as gpio chip selects + * (which can use any of the 4 chip select configurations). + */ + #define MX51_ECSPI_CTRL 0x08 #define MX51_ECSPI_CTRL_ENABLE (1 << 0) #define MX51_ECSPI_CTRL_XCH (1 << 2) @@ -260,16 +272,16 @@ static bool spi_imx_can_dma(struct spi_controller *controller, struct spi_device #define MX51_ECSPI_CTRL_DRCTL(drctl) ((drctl) << 16) #define MX51_ECSPI_CTRL_POSTDIV_OFFSET 8 #define MX51_ECSPI_CTRL_PREDIV_OFFSET 12 -#define MX51_ECSPI_CTRL_CS(cs) ((cs) << 18) +#define MX51_ECSPI_CTRL_CS(cs) ((cs & 3) << 18) #define MX51_ECSPI_CTRL_BL_OFFSET 20 #define MX51_ECSPI_CTRL_BL_MASK (0xfff << 20) #define MX51_ECSPI_CONFIG 0x0c -#define MX51_ECSPI_CONFIG_SCLKPHA(cs) (1 << ((cs) + 0)) -#define MX51_ECSPI_CONFIG_SCLKPOL(cs) (1 << ((cs) + 4)) -#define MX51_ECSPI_CONFIG_SBBCTRL(cs) (1 << ((cs) + 8)) -#define MX51_ECSPI_CONFIG_SSBPOL(cs) (1 << ((cs) + 12)) -#define MX51_ECSPI_CONFIG_SCLKCTL(cs) (1 << ((cs) + 20)) +#define MX51_ECSPI_CONFIG_SCLKPHA(cs) (1 << ((cs & 3) + 0)) +#define MX51_ECSPI_CONFIG_SCLKPOL(cs) (1 << ((cs & 3) + 4)) +#define MX51_ECSPI_CONFIG_SBBCTRL(cs) (1 << ((cs & 3) + 8)) +#define MX51_ECSPI_CONFIG_SSBPOL(cs) (1 << ((cs & 3) + 12)) +#define MX51_ECSPI_CONFIG_SCLKCTL(cs) (1 << ((cs & 3) + 20)) #define MX51_ECSPI_INT 0x10 #define MX51_ECSPI_INT_TEEN (1 << 0) @@ -528,7 +540,7 @@ static int mx51_ecspi_prepare_message(struct spi_imx_data *spi_imx, ctrl |= MX51_ECSPI_CTRL_DRCTL(spi_imx->spi_drctl); /* set chip select to use */ - ctrl |= MX51_ECSPI_CTRL_CS(spi->chip_select); + ctrl |= MX51_ECSPI_CTRL_CS(spi_get_chipselect(spi, 0)); /* * The ctrl register must be written first, with the EN bit set other @@ -549,22 +561,22 @@ static int mx51_ecspi_prepare_message(struct spi_imx_data *spi_imx, * BURST_LENGTH + 1 bits are received */ if (spi_imx->slave_mode && is_imx53_ecspi(spi_imx)) - cfg &= ~MX51_ECSPI_CONFIG_SBBCTRL(spi->chip_select); + cfg &= ~MX51_ECSPI_CONFIG_SBBCTRL(spi_get_chipselect(spi, 0)); else - cfg |= MX51_ECSPI_CONFIG_SBBCTRL(spi->chip_select); + cfg |= MX51_ECSPI_CONFIG_SBBCTRL(spi_get_chipselect(spi, 0)); if (spi->mode & SPI_CPOL) { - cfg |= MX51_ECSPI_CONFIG_SCLKPOL(spi->chip_select); - cfg |= MX51_ECSPI_CONFIG_SCLKCTL(spi->chip_select); + cfg |= MX51_ECSPI_CONFIG_SCLKPOL(spi_get_chipselect(spi, 0)); + cfg |= MX51_ECSPI_CONFIG_SCLKCTL(spi_get_chipselect(spi, 0)); } else { - cfg &= ~MX51_ECSPI_CONFIG_SCLKPOL(spi->chip_select); - cfg &= ~MX51_ECSPI_CONFIG_SCLKCTL(spi->chip_select); + cfg &= ~MX51_ECSPI_CONFIG_SCLKPOL(spi_get_chipselect(spi, 0)); + cfg &= ~MX51_ECSPI_CONFIG_SCLKCTL(spi_get_chipselect(spi, 0)); } if (spi->mode & SPI_CS_HIGH) - cfg |= MX51_ECSPI_CONFIG_SSBPOL(spi->chip_select); + cfg |= MX51_ECSPI_CONFIG_SSBPOL(spi_get_chipselect(spi, 0)); else - cfg &= ~MX51_ECSPI_CONFIG_SSBPOL(spi->chip_select); + cfg &= ~MX51_ECSPI_CONFIG_SSBPOL(spi_get_chipselect(spi, 0)); if (cfg == current_cfg) return 0; @@ -614,9 +626,9 @@ static void mx51_configure_cpha(struct spi_imx_data *spi_imx, cpha ^= flip_cpha; if (cpha) - cfg |= MX51_ECSPI_CONFIG_SCLKPHA(spi->chip_select); + cfg |= MX51_ECSPI_CONFIG_SCLKPHA(spi_get_chipselect(spi, 0)); else - cfg &= ~MX51_ECSPI_CONFIG_SCLKPHA(spi->chip_select); + cfg &= ~MX51_ECSPI_CONFIG_SCLKPHA(spi_get_chipselect(spi, 0)); writel(cfg, spi_imx->base + MX51_ECSPI_CONFIG); } @@ -768,8 +780,8 @@ static int mx31_prepare_transfer(struct spi_imx_data *spi_imx, reg |= MX31_CSPICTRL_POL; if (spi->mode & SPI_CS_HIGH) reg |= MX31_CSPICTRL_SSPOL; - if (!spi->cs_gpiod) - reg |= (spi->chip_select) << + if (!spi_get_csgpiod(spi, 0)) + reg |= (spi_get_chipselect(spi, 0)) << (is_imx35_cspi(spi_imx) ? MX35_CSPICTRL_CS_SHIFT : MX31_CSPICTRL_CS_SHIFT); @@ -868,8 +880,8 @@ static int mx21_prepare_transfer(struct spi_imx_data *spi_imx, reg |= MX21_CSPICTRL_POL; if (spi->mode & SPI_CS_HIGH) reg |= MX21_CSPICTRL_SSPOL; - if (!spi->cs_gpiod) - reg |= spi->chip_select << MX21_CSPICTRL_CS_SHIFT; + if (!spi_get_csgpiod(spi, 0)) + reg |= spi_get_chipselect(spi, 0) << MX21_CSPICTRL_CS_SHIFT; writel(reg, spi_imx->base + MXC_CSPICTRL); @@ -1753,8 +1765,7 @@ static int spi_imx_probe(struct platform_device *pdev) init_completion(&spi_imx->xfer_done); - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - spi_imx->base = devm_ioremap_resource(&pdev->dev, res); + spi_imx->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); if (IS_ERR(spi_imx->base)) { ret = PTR_ERR(spi_imx->base); goto out_controller_put; @@ -1848,7 +1859,7 @@ out_controller_put: return ret; } -static int spi_imx_remove(struct platform_device *pdev) +static void spi_imx_remove(struct platform_device *pdev) { struct spi_controller *controller = platform_get_drvdata(pdev); struct spi_imx_data *spi_imx = spi_controller_get_devdata(controller); @@ -1856,21 +1867,17 @@ static int spi_imx_remove(struct platform_device *pdev) spi_unregister_controller(controller); - ret = pm_runtime_resume_and_get(spi_imx->dev); - if (ret < 0) { - dev_err(spi_imx->dev, "failed to enable clock\n"); - return ret; - } - - writel(0, spi_imx->base + MXC_CSPICTRL); + ret = pm_runtime_get_sync(spi_imx->dev); + if (ret >= 0) + writel(0, spi_imx->base + MXC_CSPICTRL); + else + dev_warn(spi_imx->dev, "failed to enable clock, skip hw disable\n"); pm_runtime_dont_use_autosuspend(spi_imx->dev); pm_runtime_put_sync(spi_imx->dev); pm_runtime_disable(spi_imx->dev); spi_imx_sdma_exit(spi_imx); - - return 0; } static int __maybe_unused spi_imx_runtime_resume(struct device *dev) @@ -1932,7 +1939,7 @@ static struct platform_driver spi_imx_driver = { .pm = &imx_spi_pm, }, .probe = spi_imx_probe, - .remove = spi_imx_remove, + .remove_new = spi_imx_remove, }; module_platform_driver(spi_imx_driver); |