diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-12-13 19:15:11 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-12-13 19:15:11 -0800 |
commit | d3b43e12b2c8c69f79ab76dcdc5956f47c376378 (patch) | |
tree | 4fba9e425d7407e5abd5ab50d5ac09398ec5bff6 /drivers/spi/spi-pl022.c | |
parent | 15de0599277f3477ddd11766282587f12d214252 (diff) | |
parent | 7cb943615aabbd72624f77f0a84b8c5d627cf846 (diff) |
Merge tag 'spi-for-linus' of git://git.secretlab.ca/git/linux-2.6
Pull SPI updates from Grant Likely:
"Primarily SPI device driver bug fixes, one removal of an old driver,
and some new tegra support. There is some core code change too, but
all in all pretty small stuff.
The new features to note are:
- Common code for describing GPIO CS lines in the device tree
- Remove the SPI_BUFSIZ limitation on spi_write_the_read()
- core spi ensures bits_per_word is set correctly
- SPARC can now use SPI"
* tag 'spi-for-linus' of git://git.secretlab.ca/git/linux-2.6: (36 commits)
spi/sparc: Allow of_register_spi_devices for sparc
spi: Remove HOTPLUG section attributes
spi: Add support for specifying 3-wire mode via device tree
spi: Fix comparison of different integer types
spi/orion: Add SPI_CHPA and SPI_CPOL support to kirkwood driver.
spi/sh: Add SH Mobile series as dependency to MSIOF controller
spi/sh-msiof: Remove unneeded clock name
spi: Remove SPI_BUFSIZ restriction on spi_write_then_read()
spi/stmp: remove obsolete driver
spi/clps711x: New SPI master driver
spi: omap2-mcspi: remove duplicate inclusion of linux/err.h
spi: omap2-mcspi: Fix the redifine warning
spi/sh-hspi: add CS manual control support
of_spi: add generic binding support to specify cs gpio
spi: omap2-mcspi: remove duplicated include from spi-omap2-mcspi.c
spi/bitbang: (cosmetic) simplify list manipulation
spi/bitbang: avoid needless loop flow manipulations
spi/omap: fix D0/D1 direction confusion
spi: tegra: add spi driver for sflash controller
spi: Dont call master->setup if not populated
...
Diffstat (limited to 'drivers/spi/spi-pl022.c')
-rw-r--r-- | drivers/spi/spi-pl022.c | 61 |
1 files changed, 40 insertions, 21 deletions
diff --git a/drivers/spi/spi-pl022.c b/drivers/spi/spi-pl022.c index a1db91a99b89..b0fe393c882c 100644 --- a/drivers/spi/spi-pl022.c +++ b/drivers/spi/spi-pl022.c @@ -371,6 +371,7 @@ struct pl022 { /* Two optional pin states - default & sleep */ struct pinctrl *pinctrl; struct pinctrl_state *pins_default; + struct pinctrl_state *pins_idle; struct pinctrl_state *pins_sleep; struct spi_master *master; struct pl022_ssp_controller *master_info; @@ -1088,7 +1089,7 @@ err_alloc_rx_sg: return -ENOMEM; } -static int __devinit pl022_dma_probe(struct pl022 *pl022) +static int pl022_dma_probe(struct pl022 *pl022) { dma_cap_mask_t mask; @@ -2057,8 +2058,7 @@ pl022_platform_data_dt_get(struct device *dev) return pd; } -static int __devinit -pl022_probe(struct amba_device *adev, const struct amba_id *id) +static int pl022_probe(struct amba_device *adev, const struct amba_id *id) { struct device *dev = &adev->dev; struct pl022_ssp_controller *platform_info = adev->dev.platform_data; @@ -2116,6 +2116,11 @@ pl022_probe(struct amba_device *adev, const struct amba_id *id) } else dev_err(dev, "could not get default pinstate\n"); + pl022->pins_idle = pinctrl_lookup_state(pl022->pinctrl, + PINCTRL_STATE_IDLE); + if (IS_ERR(pl022->pins_idle)) + dev_dbg(dev, "could not get idle pinstate\n"); + pl022->pins_sleep = pinctrl_lookup_state(pl022->pinctrl, PINCTRL_STATE_SLEEP); if (IS_ERR(pl022->pins_sleep)) @@ -2246,10 +2251,9 @@ pl022_probe(struct amba_device *adev, const struct amba_id *id) pm_runtime_set_autosuspend_delay(dev, platform_info->autosuspend_delay); pm_runtime_use_autosuspend(dev); - pm_runtime_put_autosuspend(dev); - } else { - pm_runtime_put(dev); } + pm_runtime_put(dev); + return 0; err_spi_register: @@ -2270,7 +2274,7 @@ pl022_probe(struct amba_device *adev, const struct amba_id *id) return status; } -static int __devexit +static int pl022_remove(struct amba_device *adev) { struct pl022 *pl022 = amba_get_drvdata(adev); @@ -2303,35 +2307,47 @@ pl022_remove(struct amba_device *adev) * the runtime counterparts to handle external resources like * clocks, pins and regulators when going to sleep. */ -static void pl022_suspend_resources(struct pl022 *pl022) +static void pl022_suspend_resources(struct pl022 *pl022, bool runtime) { int ret; + struct pinctrl_state *pins_state; clk_disable(pl022->clk); + pins_state = runtime ? pl022->pins_idle : pl022->pins_sleep; /* Optionally let pins go into sleep states */ - if (!IS_ERR(pl022->pins_sleep)) { - ret = pinctrl_select_state(pl022->pinctrl, - pl022->pins_sleep); + if (!IS_ERR(pins_state)) { + ret = pinctrl_select_state(pl022->pinctrl, pins_state); if (ret) - dev_err(&pl022->adev->dev, - "could not set pins to sleep state\n"); + dev_err(&pl022->adev->dev, "could not set %s pins\n", + runtime ? "idle" : "sleep"); } } -static void pl022_resume_resources(struct pl022 *pl022) +static void pl022_resume_resources(struct pl022 *pl022, bool runtime) { int ret; /* Optionaly enable pins to be muxed in and configured */ + /* First go to the default state */ if (!IS_ERR(pl022->pins_default)) { - ret = pinctrl_select_state(pl022->pinctrl, - pl022->pins_default); + ret = pinctrl_select_state(pl022->pinctrl, pl022->pins_default); if (ret) dev_err(&pl022->adev->dev, "could not set default pins\n"); } + if (!runtime) { + /* Then let's idle the pins until the next transfer happens */ + if (!IS_ERR(pl022->pins_idle)) { + ret = pinctrl_select_state(pl022->pinctrl, + pl022->pins_idle); + if (ret) + dev_err(&pl022->adev->dev, + "could not set idle pins\n"); + } + } + clk_enable(pl022->clk); } #endif @@ -2347,7 +2363,9 @@ static int pl022_suspend(struct device *dev) dev_warn(dev, "cannot suspend master\n"); return ret; } - pl022_suspend_resources(pl022); + + pm_runtime_get_sync(dev); + pl022_suspend_resources(pl022, false); dev_dbg(dev, "suspended\n"); return 0; @@ -2358,7 +2376,8 @@ static int pl022_resume(struct device *dev) struct pl022 *pl022 = dev_get_drvdata(dev); int ret; - pl022_resume_resources(pl022); + pl022_resume_resources(pl022, false); + pm_runtime_put(dev); /* Start the queue running */ ret = spi_master_resume(pl022->master); @@ -2376,7 +2395,7 @@ static int pl022_runtime_suspend(struct device *dev) { struct pl022 *pl022 = dev_get_drvdata(dev); - pl022_suspend_resources(pl022); + pl022_suspend_resources(pl022, true); return 0; } @@ -2384,7 +2403,7 @@ static int pl022_runtime_resume(struct device *dev) { struct pl022 *pl022 = dev_get_drvdata(dev); - pl022_resume_resources(pl022); + pl022_resume_resources(pl022, true); return 0; } #endif @@ -2464,7 +2483,7 @@ static struct amba_driver pl022_driver = { }, .id_table = pl022_ids, .probe = pl022_probe, - .remove = __devexit_p(pl022_remove), + .remove = pl022_remove, }; static int __init pl022_init(void) |