diff options
Diffstat (limited to 'drivers/spi/spi-omap2-mcspi.c')
| -rw-r--r-- | drivers/spi/spi-omap2-mcspi.c | 111 | 
1 files changed, 56 insertions, 55 deletions
diff --git a/drivers/spi/spi-omap2-mcspi.c b/drivers/spi/spi-omap2-mcspi.c index 9bf64e6eca9b..6c628a54e946 100644 --- a/drivers/spi/spi-omap2-mcspi.c +++ b/drivers/spi/spi-omap2-mcspi.c @@ -255,6 +255,7 @@ static void omap2_mcspi_set_cs(struct spi_device *spi, bool enable)  	if (spi->controller_state) {  		int err = pm_runtime_get_sync(mcspi->dev);  		if (err < 0) { +			pm_runtime_put_noidle(mcspi->dev);  			dev_err(mcspi->dev, "failed to get sync: %d\n", err);  			return;  		} @@ -350,20 +351,6 @@ disable_fifo:  	mcspi->fifo_depth = 0;  } -static void omap2_mcspi_restore_ctx(struct omap2_mcspi *mcspi) -{ -	struct spi_master	*spi_cntrl = mcspi->master; -	struct omap2_mcspi_regs	*ctx = &mcspi->ctx; -	struct omap2_mcspi_cs	*cs; - -	/* McSPI: context restore */ -	mcspi_write_reg(spi_cntrl, OMAP2_MCSPI_MODULCTRL, ctx->modulctrl); -	mcspi_write_reg(spi_cntrl, OMAP2_MCSPI_WAKEUPENABLE, ctx->wakeupenable); - -	list_for_each_entry(cs, &ctx->cs, node) -		writel_relaxed(cs->chconf0, cs->base + OMAP2_MCSPI_CHCONF0); -} -  static int mcspi_wait_for_reg_bit(void __iomem *reg, unsigned long bit)  {  	unsigned long timeout; @@ -1065,8 +1052,11 @@ static int omap2_mcspi_setup(struct spi_device *spi)  	}  	ret = pm_runtime_get_sync(mcspi->dev); -	if (ret < 0) +	if (ret < 0) { +		pm_runtime_put_noidle(mcspi->dev); +  		return ret; +	}  	ret = omap2_mcspi_setup_transfer(spi, NULL);  	pm_runtime_mark_last_busy(mcspi->dev); @@ -1284,8 +1274,11 @@ static int omap2_mcspi_master_setup(struct omap2_mcspi *mcspi)  	int			ret = 0;  	ret = pm_runtime_get_sync(mcspi->dev); -	if (ret < 0) +	if (ret < 0) { +		pm_runtime_put_noidle(mcspi->dev); +  		return ret; +	}  	mcspi_write_reg(master, OMAP2_MCSPI_WAKEUPENABLE,  			OMAP2_MCSPI_WAKEUPENABLE_WKEN); @@ -1297,14 +1290,39 @@ static int omap2_mcspi_master_setup(struct omap2_mcspi *mcspi)  	return 0;  } +/* + * When SPI wake up from off-mode, CS is in activate state. If it was in + * inactive state when driver was suspend, then force it to inactive state at + * wake up. + */  static int omap_mcspi_runtime_resume(struct device *dev)  { -	struct omap2_mcspi	*mcspi; -	struct spi_master	*master; +	struct spi_master *master = dev_get_drvdata(dev); +	struct omap2_mcspi *mcspi = spi_master_get_devdata(master); +	struct omap2_mcspi_regs *ctx = &mcspi->ctx; +	struct omap2_mcspi_cs *cs; -	master = dev_get_drvdata(dev); -	mcspi = spi_master_get_devdata(master); -	omap2_mcspi_restore_ctx(mcspi); +	/* McSPI: context restore */ +	mcspi_write_reg(master, OMAP2_MCSPI_MODULCTRL, ctx->modulctrl); +	mcspi_write_reg(master, OMAP2_MCSPI_WAKEUPENABLE, ctx->wakeupenable); + +	list_for_each_entry(cs, &ctx->cs, node) { +		/* +		 * We need to toggle CS state for OMAP take this +		 * change in account. +		 */ +		if ((cs->chconf0 & OMAP2_MCSPI_CHCONF_FORCE) == 0) { +			cs->chconf0 |= OMAP2_MCSPI_CHCONF_FORCE; +			writel_relaxed(cs->chconf0, +				       cs->base + OMAP2_MCSPI_CHCONF0); +			cs->chconf0 &= ~OMAP2_MCSPI_CHCONF_FORCE; +			writel_relaxed(cs->chconf0, +				       cs->base + OMAP2_MCSPI_CHCONF0); +		} else { +			writel_relaxed(cs->chconf0, +				       cs->base + OMAP2_MCSPI_CHCONF0); +		} +	}  	return 0;  } @@ -1447,50 +1465,33 @@ static int omap2_mcspi_remove(struct platform_device *pdev)  MODULE_ALIAS("platform:omap2_mcspi");  #ifdef	CONFIG_SUSPEND -/* - * When SPI wake up from off-mode, CS is in activate state. If it was in - * unactive state when driver was suspend, then force it to unactive state at - * wake up. - */ -static int omap2_mcspi_resume(struct device *dev) +static int omap2_mcspi_suspend_noirq(struct device *dev)  { -	struct spi_master	*master = dev_get_drvdata(dev); -	struct omap2_mcspi	*mcspi = spi_master_get_devdata(master); -	struct omap2_mcspi_regs	*ctx = &mcspi->ctx; -	struct omap2_mcspi_cs	*cs; - -	pm_runtime_get_sync(mcspi->dev); -	list_for_each_entry(cs, &ctx->cs, node) { -		if ((cs->chconf0 & OMAP2_MCSPI_CHCONF_FORCE) == 0) { -			/* -			 * We need to toggle CS state for OMAP take this -			 * change in account. -			 */ -			cs->chconf0 |= OMAP2_MCSPI_CHCONF_FORCE; -			writel_relaxed(cs->chconf0, cs->base + OMAP2_MCSPI_CHCONF0); -			cs->chconf0 &= ~OMAP2_MCSPI_CHCONF_FORCE; -			writel_relaxed(cs->chconf0, cs->base + OMAP2_MCSPI_CHCONF0); -		} -	} -	pm_runtime_mark_last_busy(mcspi->dev); -	pm_runtime_put_autosuspend(mcspi->dev); - -	return pinctrl_pm_select_default_state(dev); +	return pinctrl_pm_select_sleep_state(dev);  } -static int omap2_mcspi_suspend(struct device *dev) +static int omap2_mcspi_resume_noirq(struct device *dev)  { -	return pinctrl_pm_select_sleep_state(dev); +	struct spi_master *master = dev_get_drvdata(dev); +	struct omap2_mcspi *mcspi = spi_master_get_devdata(master); +	int error; + +	error = pinctrl_pm_select_default_state(dev); +	if (error) +		dev_warn(mcspi->dev, "%s: failed to set pins: %i\n", +			 __func__, error); + +	return 0;  }  #else -#define omap2_mcspi_suspend	NULL -#define	omap2_mcspi_resume	NULL +#define omap2_mcspi_suspend_noirq	NULL +#define omap2_mcspi_resume_noirq	NULL  #endif  static const struct dev_pm_ops omap2_mcspi_pm_ops = { -	.resume = omap2_mcspi_resume, -	.suspend = omap2_mcspi_suspend, +	.suspend_noirq = omap2_mcspi_suspend_noirq, +	.resume_noirq = omap2_mcspi_resume_noirq,  	.runtime_resume	= omap_mcspi_runtime_resume,  };  | 
