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);  |