Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7e0a6fd5 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
* 'amba' of http://ftp.arm.linux.org.uk/pub/linux/arm/kernel/git-cur/linux-2.6-arm:
  ARM: 7079/1: spi: Fix builderror in spi-pl022.c
  PM: add runtime PM support to MMCI
  PM: add runtime PM support to core Primecell driver
parents ca906662 6cfa6279
Loading
Loading
Loading
Loading
+54 −3
Original line number Diff line number Diff line
@@ -365,6 +365,40 @@ static int amba_pm_restore_noirq(struct device *dev)

#endif /* !CONFIG_HIBERNATE_CALLBACKS */

#ifdef CONFIG_PM_RUNTIME
/*
 * Hooks to provide runtime PM of the pclk (bus clock).  It is safe to
 * enable/disable the bus clock at runtime PM suspend/resume as this
 * does not result in loss of context.  However, disabling vcore power
 * would do, so we leave that to the driver.
 */
static int amba_pm_runtime_suspend(struct device *dev)
{
	struct amba_device *pcdev = to_amba_device(dev);
	int ret = pm_generic_runtime_suspend(dev);

	if (ret == 0 && dev->driver)
		clk_disable(pcdev->pclk);

	return ret;
}

static int amba_pm_runtime_resume(struct device *dev)
{
	struct amba_device *pcdev = to_amba_device(dev);
	int ret;

	if (dev->driver) {
		ret = clk_enable(pcdev->pclk);
		/* Failure is probably fatal to the system, but... */
		if (ret)
			return ret;
	}

	return pm_generic_runtime_resume(dev);
}
#endif

#ifdef CONFIG_PM

static const struct dev_pm_ops amba_pm = {
@@ -383,8 +417,8 @@ static const struct dev_pm_ops amba_pm = {
	.poweroff_noirq	= amba_pm_poweroff_noirq,
	.restore_noirq	= amba_pm_restore_noirq,
	SET_RUNTIME_PM_OPS(
		pm_generic_runtime_suspend,
		pm_generic_runtime_resume,
		amba_pm_runtime_suspend,
		amba_pm_runtime_resume,
		pm_generic_runtime_idle
	)
};
@@ -494,10 +528,18 @@ static int amba_probe(struct device *dev)
		if (ret)
			break;

		pm_runtime_get_noresume(dev);
		pm_runtime_set_active(dev);
		pm_runtime_enable(dev);

		ret = pcdrv->probe(pcdev, id);
		if (ret == 0)
			break;

		pm_runtime_disable(dev);
		pm_runtime_set_suspended(dev);
		pm_runtime_put_noidle(dev);

		amba_put_disable_pclk(pcdev);
		amba_put_disable_vcore(pcdev);
	} while (0);
@@ -509,7 +551,16 @@ static int amba_remove(struct device *dev)
{
	struct amba_device *pcdev = to_amba_device(dev);
	struct amba_driver *drv = to_amba_driver(dev->driver);
	int ret = drv->remove(pcdev);
	int ret;

	pm_runtime_get_sync(dev);
	ret = drv->remove(pcdev);
	pm_runtime_put_noidle(dev);

	/* Undo the runtime PM settings in amba_probe() */
	pm_runtime_disable(dev);
	pm_runtime_set_suspended(dev);
	pm_runtime_put_noidle(dev);

	amba_put_disable_pclk(pcdev);
	amba_put_disable_vcore(pcdev);
+12 −0
Original line number Diff line number Diff line
@@ -29,6 +29,7 @@
#include <linux/dmaengine.h>
#include <linux/dma-mapping.h>
#include <linux/amba/mmci.h>
#include <linux/pm_runtime.h>

#include <asm/div64.h>
#include <asm/io.h>
@@ -170,6 +171,7 @@ mmci_request_end(struct mmci_host *host, struct mmc_request *mrq)
	 * back into the driver...
	 */
	spin_unlock(&host->lock);
	pm_runtime_put(mmc_dev(host->mmc));
	mmc_request_done(host->mmc, mrq);
	spin_lock(&host->lock);
}
@@ -984,6 +986,8 @@ static void mmci_request(struct mmc_host *mmc, struct mmc_request *mrq)
		return;
	}

	pm_runtime_get_sync(mmc_dev(mmc));

	spin_lock_irqsave(&host->lock, flags);

	host->mrq = mrq;
@@ -1327,6 +1331,8 @@ static int __devinit mmci_probe(struct amba_device *dev,

	mmci_dma_setup(host);

	pm_runtime_put(&dev->dev);

	mmc_add_host(mmc);

	return 0;
@@ -1364,6 +1370,12 @@ static int __devexit mmci_remove(struct amba_device *dev)
	if (mmc) {
		struct mmci_host *host = mmc_priv(mmc);

		/*
		 * Undo pm_runtime_put() in probe.  We use the _sync
		 * version here so that we can access the primecell.
		 */
		pm_runtime_get_sync(&dev->dev);

		mmc_remove_host(mmc);

		writel(0, host->base + MMCIMASK0);
+50 −34
Original line number Diff line number Diff line
@@ -515,9 +515,6 @@ static void giveback(struct pl022 *pl022)
	if (msg->complete)
		msg->complete(msg->context);
	/* This message is completed, so let's turn off the clocks & power */
	clk_disable(pl022->clk);
	amba_pclk_disable(pl022->adev);
	amba_vcore_disable(pl022->adev);
	pm_runtime_put(&pl022->adev->dev);
}

@@ -1545,9 +1542,6 @@ static void pump_messages(struct work_struct *work)
	 * (poll/interrupt/DMA)
	 */
	pm_runtime_get_sync(&pl022->adev->dev);
	amba_vcore_enable(pl022->adev);
	amba_pclk_enable(pl022->adev);
	clk_enable(pl022->clk);
	restore_state(pl022);
	flush(pl022);

@@ -2186,8 +2180,6 @@ pl022_probe(struct amba_device *adev, const struct amba_id *id)
	}
	printk(KERN_INFO "pl022: mapped registers from 0x%08x to %p\n",
	       adev->res.start, pl022->virtbase);
	pm_runtime_enable(dev);
	pm_runtime_resume(dev);

	pl022->clk = clk_get(&adev->dev, NULL);
	if (IS_ERR(pl022->clk)) {
@@ -2195,7 +2187,6 @@ pl022_probe(struct amba_device *adev, const struct amba_id *id)
		dev_err(&adev->dev, "could not retrieve SSP/SPI bus clock\n");
		goto err_no_clk;
	}

	/* Disable SSP */
	writew((readw(SSP_CR1(pl022->virtbase)) & (~SSP_CR1_MASK_SSE)),
	       SSP_CR1(pl022->virtbase));
@@ -2235,12 +2226,9 @@ pl022_probe(struct amba_device *adev, const struct amba_id *id)
		goto err_spi_register;
	}
	dev_dbg(dev, "probe succeeded\n");
	/*
	 * Disable the silicon block pclk and any voltage domain and just
	 * power it up and clock it when it's needed
	 */
	amba_pclk_disable(adev);
	amba_vcore_disable(adev);

	/* let runtime pm put suspend */
	pm_runtime_put(dev);
	return 0;

 err_spi_register:
@@ -2249,7 +2237,6 @@ pl022_probe(struct amba_device *adev, const struct amba_id *id)
	destroy_queue(pl022);
	pl022_dma_remove(pl022);
	free_irq(adev->irq[0], pl022);
	pm_runtime_disable(&adev->dev);
 err_no_irq:
	clk_put(pl022->clk);
 err_no_clk:
@@ -2271,6 +2258,12 @@ pl022_remove(struct amba_device *adev)
	if (!pl022)
		return 0;

	/*
	 * undo pm_runtime_put() in probe.  I assume that we're not
	 * accessing the primecell here.
	 */
	pm_runtime_get_noresume(&adev->dev);

	/* Remove the queue */
	if (destroy_queue(pl022) != 0)
		dev_err(&adev->dev, "queue remove failed\n");
@@ -2288,46 +2281,70 @@ pl022_remove(struct amba_device *adev)
	return 0;
}

#ifdef CONFIG_PM
static int pl022_suspend(struct amba_device *adev, pm_message_t state)
#ifdef CONFIG_SUSPEND
static int pl022_suspend(struct device *dev)
{
	struct pl022 *pl022 = amba_get_drvdata(adev);
	struct pl022 *pl022 = dev_get_drvdata(dev);
	int status = 0;

	status = stop_queue(pl022);
	if (status) {
		dev_warn(&adev->dev, "suspend cannot stop queue\n");
		dev_warn(dev, "suspend cannot stop queue\n");
		return status;
	}

	amba_vcore_enable(adev);
	amba_pclk_enable(adev);
	amba_vcore_enable(pl022->adev);
	amba_pclk_enable(pl022->adev);
	load_ssp_default_config(pl022);
	amba_pclk_disable(adev);
	amba_vcore_disable(adev);
	dev_dbg(&adev->dev, "suspended\n");
	amba_pclk_disable(pl022->adev);
	amba_vcore_disable(pl022->adev);
	dev_dbg(dev, "suspended\n");
	return 0;
}

static int pl022_resume(struct amba_device *adev)
static int pl022_resume(struct device *dev)
{
	struct pl022 *pl022 = amba_get_drvdata(adev);
	struct pl022 *pl022 = dev_get_drvdata(dev);
	int status = 0;

	/* Start the queue running */
	status = start_queue(pl022);
	if (status)
		dev_err(&adev->dev, "problem starting queue (%d)\n", status);
		dev_err(dev, "problem starting queue (%d)\n", status);
	else
		dev_dbg(&adev->dev, "resumed\n");
		dev_dbg(dev, "resumed\n");

	return status;
}
#else
#define pl022_suspend NULL
#define pl022_resume NULL
#endif	/* CONFIG_PM */

#ifdef CONFIG_PM_RUNTIME
static int pl022_runtime_suspend(struct device *dev)
{
	struct pl022 *pl022 = dev_get_drvdata(dev);

	clk_disable(pl022->clk);
	amba_vcore_disable(pl022->adev);

	return 0;
}

static int pl022_runtime_resume(struct device *dev)
{
	struct pl022 *pl022 = dev_get_drvdata(dev);

	amba_vcore_enable(pl022->adev);
	clk_enable(pl022->clk);

	return 0;
}
#endif

static const struct dev_pm_ops pl022_dev_pm_ops = {
	SET_SYSTEM_SLEEP_PM_OPS(pl022_suspend, pl022_resume)
	SET_RUNTIME_PM_OPS(pl022_runtime_suspend, pl022_runtime_resume, NULL)
};

static struct vendor_data vendor_arm = {
	.fifodepth = 8,
	.max_bpw = 16,
@@ -2407,12 +2424,11 @@ static struct amba_id pl022_ids[] = {
static struct amba_driver pl022_driver = {
	.drv = {
		.name	= "ssp-pl022",
		.pm	= &pl022_dev_pm_ops,
	},
	.id_table	= pl022_ids,
	.probe		= pl022_probe,
	.remove		= __devexit_p(pl022_remove),
	.suspend        = pl022_suspend,
	.resume         = pl022_resume,
};