Skip to content

Commit

Permalink
mtd: maps: physmap: Add minimal Runtime PM support
Browse files Browse the repository at this point in the history
Add minimal runtime PM support (enable on probe, disable on remove), to
ensure proper operation with a parent device that uses runtime PM.

This is needed on systems where the FLASH is connected to a bus
controller that is contained in a PM domain and/or has a gateable
functional clock.  In such cases, before accessing any device connected
to the external bus, the PM domain must be powered up, and/or the
functional clock must be enabled, which is typically handled through
runtime PM by the bus controller driver.

An example of this is the Renesas APE6-EVM development board, which has
an Ethernet controller and a CFI FLASH connected to the Bus State
Controller (BSC) of an R-Mobile APE6 SoC.
As long as the Ethernet driver, which had Runtime PM support since
commit 3a611e2 ("net/smsc911x: Add minimal runtime PM
support"), keeps the BSC powered, accessing the FLASH works.
When the ethernet node in r8a73a4-ape6evm.dts is disabled, the BSC is
never powered up, and the kernel crashes when trying to access the
FLASH:

    Unhandled fault: imprecise external abort (0x1406) at 0x00000000
    pgd = (ptrval)
    [00000000] *pgd=7fef2835
    Internal error: : 1406 [#1] SMP ARM
    CPU: 0 PID: 122 Comm: hd Tainted: G        W         5.5.0-rc1-ape6evm-00814-g38ca966db25b9dbd-dirty torvalds#136
    Hardware name: Generic R8A73A4 (Flattened Device Tree)
    PC is at chip_ready+0x12c/0x380
    LR is at chip_ready+0x10c/0x380

Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
  • Loading branch information
geertu authored and miquelraynal committed Jan 27, 2020
1 parent 2a0b390 commit 0bc448b
Showing 1 changed file with 15 additions and 5 deletions.
20 changes: 15 additions & 5 deletions drivers/mtd/maps/physmap-core.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
#include <linux/mtd/cfi_endian.h>
#include <linux/io.h>
#include <linux/of_device.h>
#include <linux/pm_runtime.h>
#include <linux/gpio/consumer.h>

#include "physmap-gemini.h"
Expand All @@ -64,16 +65,16 @@ static int physmap_flash_remove(struct platform_device *dev)
{
struct physmap_flash_info *info;
struct physmap_flash_data *physmap_data;
int i, err;
int i, err = 0;

info = platform_get_drvdata(dev);
if (!info)
return 0;
goto out;

if (info->cmtd) {
err = mtd_device_unregister(info->cmtd);
if (err)
return err;
goto out;

if (info->cmtd != info->mtds[0])
mtd_concat_destroy(info->cmtd);
Expand All @@ -88,7 +89,10 @@ static int physmap_flash_remove(struct platform_device *dev)
if (physmap_data && physmap_data->exit)
physmap_data->exit(dev);

return 0;
out:
pm_runtime_put(&dev->dev);
pm_runtime_disable(&dev->dev);
return err;
}

static void physmap_set_vpp(struct map_info *map, int state)
Expand Down Expand Up @@ -484,13 +488,19 @@ static int physmap_flash_probe(struct platform_device *dev)
return -EINVAL;
}

pm_runtime_enable(&dev->dev);
pm_runtime_get_sync(&dev->dev);

if (dev->dev.of_node)
err = physmap_flash_of_init(dev);
else
err = physmap_flash_pdata_init(dev);

if (err)
if (err) {
pm_runtime_put(&dev->dev);
pm_runtime_disable(&dev->dev);
return err;
}

for (i = 0; i < info->nmaps; i++) {
struct resource *res;
Expand Down

0 comments on commit 0bc448b

Please sign in to comment.