diff options
Diffstat (limited to 'drivers/spi/spi-pl022.c')
-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 a1db91a99b89..1361868fced7 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)) |
@@ -2246,10 +2252,9 @@ pl022_probe(struct amba_device *adev, const struct amba_id *id) | |||
2246 | pm_runtime_set_autosuspend_delay(dev, | 2252 | pm_runtime_set_autosuspend_delay(dev, |
2247 | platform_info->autosuspend_delay); | 2253 | platform_info->autosuspend_delay); |
2248 | pm_runtime_use_autosuspend(dev); | 2254 | pm_runtime_use_autosuspend(dev); |
2249 | pm_runtime_put_autosuspend(dev); | ||
2250 | } else { | ||
2251 | pm_runtime_put(dev); | ||
2252 | } | 2255 | } |
2256 | pm_runtime_put(dev); | ||
2257 | |||
2253 | return 0; | 2258 | return 0; |
2254 | 2259 | ||
2255 | err_spi_register: | 2260 | err_spi_register: |
@@ -2303,35 +2308,47 @@ pl022_remove(struct amba_device *adev) | |||
2303 | * the runtime counterparts to handle external resources like | 2308 | * the runtime counterparts to handle external resources like |
2304 | * clocks, pins and regulators when going to sleep. | 2309 | * clocks, pins and regulators when going to sleep. |
2305 | */ | 2310 | */ |
2306 | static void pl022_suspend_resources(struct pl022 *pl022) | 2311 | static void pl022_suspend_resources(struct pl022 *pl022, bool runtime) |
2307 | { | 2312 | { |
2308 | int ret; | 2313 | int ret; |
2314 | struct pinctrl_state *pins_state; | ||
2309 | 2315 | ||
2310 | clk_disable(pl022->clk); | 2316 | clk_disable(pl022->clk); |
2311 | 2317 | ||
2318 | pins_state = runtime ? pl022->pins_idle : pl022->pins_sleep; | ||
2312 | /* Optionally let pins go into sleep states */ | 2319 | /* Optionally let pins go into sleep states */ |
2313 | if (!IS_ERR(pl022->pins_sleep)) { | 2320 | if (!IS_ERR(pins_state)) { |
2314 | ret = pinctrl_select_state(pl022->pinctrl, | 2321 | ret = pinctrl_select_state(pl022->pinctrl, pins_state); |
2315 | pl022->pins_sleep); | ||
2316 | if (ret) | 2322 | if (ret) |
2317 | dev_err(&pl022->adev->dev, | 2323 | dev_err(&pl022->adev->dev, "could not set %s pins\n", |
2318 | "could not set pins to sleep state\n"); | 2324 | runtime ? "idle" : "sleep"); |
2319 | } | 2325 | } |
2320 | } | 2326 | } |
2321 | 2327 | ||
2322 | static void pl022_resume_resources(struct pl022 *pl022) | 2328 | static void pl022_resume_resources(struct pl022 *pl022, bool runtime) |
2323 | { | 2329 | { |
2324 | int ret; | 2330 | int ret; |
2325 | 2331 | ||
2326 | /* Optionaly enable pins to be muxed in and configured */ | 2332 | /* Optionaly enable pins to be muxed in and configured */ |
2333 | /* First go to the default state */ | ||
2327 | if (!IS_ERR(pl022->pins_default)) { | 2334 | if (!IS_ERR(pl022->pins_default)) { |
2328 | ret = pinctrl_select_state(pl022->pinctrl, | 2335 | ret = pinctrl_select_state(pl022->pinctrl, pl022->pins_default); |
2329 | pl022->pins_default); | ||
2330 | if (ret) | 2336 | if (ret) |
2331 | dev_err(&pl022->adev->dev, | 2337 | dev_err(&pl022->adev->dev, |
2332 | "could not set default pins\n"); | 2338 | "could not set default pins\n"); |
2333 | } | 2339 | } |
2334 | 2340 | ||
2341 | if (!runtime) { | ||
2342 | /* Then let's idle the pins until the next transfer happens */ | ||
2343 | if (!IS_ERR(pl022->pins_idle)) { | ||
2344 | ret = pinctrl_select_state(pl022->pinctrl, | ||
2345 | pl022->pins_idle); | ||
2346 | if (ret) | ||
2347 | dev_err(&pl022->adev->dev, | ||
2348 | "could not set idle pins\n"); | ||
2349 | } | ||
2350 | } | ||
2351 | |||
2335 | clk_enable(pl022->clk); | 2352 | clk_enable(pl022->clk); |
2336 | } | 2353 | } |
2337 | #endif | 2354 | #endif |
@@ -2347,7 +2364,9 @@ static int pl022_suspend(struct device *dev) | |||
2347 | dev_warn(dev, "cannot suspend master\n"); | 2364 | dev_warn(dev, "cannot suspend master\n"); |
2348 | return ret; | 2365 | return ret; |
2349 | } | 2366 | } |
2350 | pl022_suspend_resources(pl022); | 2367 | |
2368 | pm_runtime_get_sync(dev); | ||
2369 | pl022_suspend_resources(pl022, false); | ||
2351 | 2370 | ||
2352 | dev_dbg(dev, "suspended\n"); | 2371 | dev_dbg(dev, "suspended\n"); |
2353 | return 0; | 2372 | return 0; |
@@ -2358,7 +2377,8 @@ static int pl022_resume(struct device *dev) | |||
2358 | struct pl022 *pl022 = dev_get_drvdata(dev); | 2377 | struct pl022 *pl022 = dev_get_drvdata(dev); |
2359 | int ret; | 2378 | int ret; |
2360 | 2379 | ||
2361 | pl022_resume_resources(pl022); | 2380 | pl022_resume_resources(pl022, false); |
2381 | pm_runtime_put(dev); | ||
2362 | 2382 | ||
2363 | /* Start the queue running */ | 2383 | /* Start the queue running */ |
2364 | ret = spi_master_resume(pl022->master); | 2384 | ret = spi_master_resume(pl022->master); |
@@ -2376,7 +2396,7 @@ static int pl022_runtime_suspend(struct device *dev) | |||
2376 | { | 2396 | { |
2377 | struct pl022 *pl022 = dev_get_drvdata(dev); | 2397 | struct pl022 *pl022 = dev_get_drvdata(dev); |
2378 | 2398 | ||
2379 | pl022_suspend_resources(pl022); | 2399 | pl022_suspend_resources(pl022, true); |
2380 | return 0; | 2400 | return 0; |
2381 | } | 2401 | } |
2382 | 2402 | ||
@@ -2384,7 +2404,7 @@ static int pl022_runtime_resume(struct device *dev) | |||
2384 | { | 2404 | { |
2385 | struct pl022 *pl022 = dev_get_drvdata(dev); | 2405 | struct pl022 *pl022 = dev_get_drvdata(dev); |
2386 | 2406 | ||
2387 | pl022_resume_resources(pl022); | 2407 | pl022_resume_resources(pl022, true); |
2388 | return 0; | 2408 | return 0; |
2389 | } | 2409 | } |
2390 | #endif | 2410 | #endif |