diff options
author | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2012-10-17 09:14:35 -0400 |
---|---|---|
committer | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2012-10-17 09:14:35 -0400 |
commit | b4482afeb7e91dabd8a2d6570a1b216eb34408a6 (patch) | |
tree | 42515b3241227581e4475ab550c75f7d3ab19376 /drivers/spi | |
parent | ef5347c63f9d19c4185fe06d73ffb8f4d55606bf (diff) | |
parent | d8f18420c552de6d38e5464074133e0e9730abcd (diff) |
Merge branch 'spi-pl022' into spi-next
Diffstat (limited to 'drivers/spi')
-rw-r--r-- | drivers/spi/spi-pl022.c | 52 |
1 files changed, 36 insertions, 16 deletions
diff --git a/drivers/spi/spi-pl022.c b/drivers/spi/spi-pl022.c index 5cf0643ae74c..0205d470fde6 100644 --- a/drivers/spi/spi-pl022.c +++ b/drivers/spi/spi-pl022.c | |||
@@ -371,6 +371,7 @@ struct pl022 { | |||
371 | /* Two optional pin states - default & sleep */ | 371 | /* Two optional pin states - default & sleep */ |
372 | struct pinctrl *pinctrl; | 372 | struct pinctrl *pinctrl; |
373 | struct pinctrl_state *pins_default; | 373 | struct pinctrl_state *pins_default; |
374 | struct pinctrl_state *pins_idle; | ||
374 | struct pinctrl_state *pins_sleep; | 375 | struct pinctrl_state *pins_sleep; |
375 | struct spi_master *master; | 376 | struct spi_master *master; |
376 | struct pl022_ssp_controller *master_info; | 377 | struct pl022_ssp_controller *master_info; |
@@ -2116,6 +2117,11 @@ pl022_probe(struct amba_device *adev, const struct amba_id *id) | |||
2116 | } else | 2117 | } else |
2117 | dev_err(dev, "could not get default pinstate\n"); | 2118 | dev_err(dev, "could not get default pinstate\n"); |
2118 | 2119 | ||
2120 | pl022->pins_idle = pinctrl_lookup_state(pl022->pinctrl, | ||
2121 | PINCTRL_STATE_IDLE); | ||
2122 | if (IS_ERR(pl022->pins_idle)) | ||
2123 | dev_dbg(dev, "could not get idle pinstate\n"); | ||
2124 | |||
2119 | pl022->pins_sleep = pinctrl_lookup_state(pl022->pinctrl, | 2125 | pl022->pins_sleep = pinctrl_lookup_state(pl022->pinctrl, |
2120 | PINCTRL_STATE_SLEEP); | 2126 | PINCTRL_STATE_SLEEP); |
2121 | if (IS_ERR(pl022->pins_sleep)) | 2127 | if (IS_ERR(pl022->pins_sleep)) |
@@ -2249,10 +2255,9 @@ pl022_probe(struct amba_device *adev, const struct amba_id *id) | |||
2249 | pm_runtime_set_autosuspend_delay(dev, | 2255 | pm_runtime_set_autosuspend_delay(dev, |
2250 | platform_info->autosuspend_delay); | 2256 | platform_info->autosuspend_delay); |
2251 | pm_runtime_use_autosuspend(dev); | 2257 | pm_runtime_use_autosuspend(dev); |
2252 | pm_runtime_put_autosuspend(dev); | ||
2253 | } else { | ||
2254 | pm_runtime_put(dev); | ||
2255 | } | 2258 | } |
2259 | pm_runtime_put(dev); | ||
2260 | |||
2256 | return 0; | 2261 | return 0; |
2257 | 2262 | ||
2258 | err_spi_register: | 2263 | err_spi_register: |
@@ -2307,35 +2312,47 @@ pl022_remove(struct amba_device *adev) | |||
2307 | * the runtime counterparts to handle external resources like | 2312 | * the runtime counterparts to handle external resources like |
2308 | * clocks, pins and regulators when going to sleep. | 2313 | * clocks, pins and regulators when going to sleep. |
2309 | */ | 2314 | */ |
2310 | static void pl022_suspend_resources(struct pl022 *pl022) | 2315 | static void pl022_suspend_resources(struct pl022 *pl022, bool runtime) |
2311 | { | 2316 | { |
2312 | int ret; | 2317 | int ret; |
2318 | struct pinctrl_state *pins_state; | ||
2313 | 2319 | ||
2314 | clk_disable(pl022->clk); | 2320 | clk_disable(pl022->clk); |
2315 | 2321 | ||
2322 | pins_state = runtime ? pl022->pins_idle : pl022->pins_sleep; | ||
2316 | /* Optionally let pins go into sleep states */ | 2323 | /* Optionally let pins go into sleep states */ |
2317 | if (!IS_ERR(pl022->pins_sleep)) { | 2324 | if (!IS_ERR(pins_state)) { |
2318 | ret = pinctrl_select_state(pl022->pinctrl, | 2325 | ret = pinctrl_select_state(pl022->pinctrl, pins_state); |
2319 | pl022->pins_sleep); | ||
2320 | if (ret) | 2326 | if (ret) |
2321 | dev_err(&pl022->adev->dev, | 2327 | dev_err(&pl022->adev->dev, "could not set %s pins\n", |
2322 | "could not set pins to sleep state\n"); | 2328 | runtime ? "idle" : "sleep"); |
2323 | } | 2329 | } |
2324 | } | 2330 | } |
2325 | 2331 | ||
2326 | static void pl022_resume_resources(struct pl022 *pl022) | 2332 | static void pl022_resume_resources(struct pl022 *pl022, bool runtime) |
2327 | { | 2333 | { |
2328 | int ret; | 2334 | int ret; |
2329 | 2335 | ||
2330 | /* Optionaly enable pins to be muxed in and configured */ | 2336 | /* Optionaly enable pins to be muxed in and configured */ |
2337 | /* First go to the default state */ | ||
2331 | if (!IS_ERR(pl022->pins_default)) { | 2338 | if (!IS_ERR(pl022->pins_default)) { |
2332 | ret = pinctrl_select_state(pl022->pinctrl, | 2339 | ret = pinctrl_select_state(pl022->pinctrl, pl022->pins_default); |
2333 | pl022->pins_default); | ||
2334 | if (ret) | 2340 | if (ret) |
2335 | dev_err(&pl022->adev->dev, | 2341 | dev_err(&pl022->adev->dev, |
2336 | "could not set default pins\n"); | 2342 | "could not set default pins\n"); |
2337 | } | 2343 | } |
2338 | 2344 | ||
2345 | if (!runtime) { | ||
2346 | /* Then let's idle the pins until the next transfer happens */ | ||
2347 | if (!IS_ERR(pl022->pins_idle)) { | ||
2348 | ret = pinctrl_select_state(pl022->pinctrl, | ||
2349 | pl022->pins_idle); | ||
2350 | if (ret) | ||
2351 | dev_err(&pl022->adev->dev, | ||
2352 | "could not set idle pins\n"); | ||
2353 | } | ||
2354 | } | ||
2355 | |||
2339 | clk_enable(pl022->clk); | 2356 | clk_enable(pl022->clk); |
2340 | } | 2357 | } |
2341 | #endif | 2358 | #endif |
@@ -2351,7 +2368,9 @@ static int pl022_suspend(struct device *dev) | |||
2351 | dev_warn(dev, "cannot suspend master\n"); | 2368 | dev_warn(dev, "cannot suspend master\n"); |
2352 | return ret; | 2369 | return ret; |
2353 | } | 2370 | } |
2354 | pl022_suspend_resources(pl022); | 2371 | |
2372 | pm_runtime_get_sync(dev); | ||
2373 | pl022_suspend_resources(pl022, false); | ||
2355 | 2374 | ||
2356 | dev_dbg(dev, "suspended\n"); | 2375 | dev_dbg(dev, "suspended\n"); |
2357 | return 0; | 2376 | return 0; |
@@ -2362,7 +2381,8 @@ static int pl022_resume(struct device *dev) | |||
2362 | struct pl022 *pl022 = dev_get_drvdata(dev); | 2381 | struct pl022 *pl022 = dev_get_drvdata(dev); |
2363 | int ret; | 2382 | int ret; |
2364 | 2383 | ||
2365 | pl022_resume_resources(pl022); | 2384 | pl022_resume_resources(pl022, false); |
2385 | pm_runtime_put(dev); | ||
2366 | 2386 | ||
2367 | /* Start the queue running */ | 2387 | /* Start the queue running */ |
2368 | ret = spi_master_resume(pl022->master); | 2388 | ret = spi_master_resume(pl022->master); |
@@ -2380,7 +2400,7 @@ static int pl022_runtime_suspend(struct device *dev) | |||
2380 | { | 2400 | { |
2381 | struct pl022 *pl022 = dev_get_drvdata(dev); | 2401 | struct pl022 *pl022 = dev_get_drvdata(dev); |
2382 | 2402 | ||
2383 | pl022_suspend_resources(pl022); | 2403 | pl022_suspend_resources(pl022, true); |
2384 | return 0; | 2404 | return 0; |
2385 | } | 2405 | } |
2386 | 2406 | ||
@@ -2388,7 +2408,7 @@ static int pl022_runtime_resume(struct device *dev) | |||
2388 | { | 2408 | { |
2389 | struct pl022 *pl022 = dev_get_drvdata(dev); | 2409 | struct pl022 *pl022 = dev_get_drvdata(dev); |
2390 | 2410 | ||
2391 | pl022_resume_resources(pl022); | 2411 | pl022_resume_resources(pl022, true); |
2392 | return 0; | 2412 | return 0; |
2393 | } | 2413 | } |
2394 | #endif | 2414 | #endif |