From patchwork Thu Jul 12 16:38:41 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: [2/2] mtd: maps: physmap_of: Add GPIO VPP control Date: Thu, 12 Jul 2012 06:38:41 -0000 From: Pawel Moll X-Patchwork-Id: 170726 Message-Id: <1342111121-23161-3-git-send-email-pawel.moll@arm.com> To: linux-mtd@lists.infradead.org Cc: Artem Bityutskiy , David Woodhouse , Pawel Moll Add a GPIO control of the VPP signal and "vpp-gpios" tree property, specifying the GPIO line in a standard DT way, including polarity flags. Signed-off-by: Pawel Moll --- .../devicetree/bindings/mtd/mtd-physmap.txt | 7 +++- drivers/mtd/maps/physmap_of.c | 42 ++++++++++++++++++++ 2 files changed, 48 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/mtd/mtd-physmap.txt b/Documentation/devicetree/bindings/mtd/mtd-physmap.txt index a63c2bd7..28084cf 100644 --- a/Documentation/devicetree/bindings/mtd/mtd-physmap.txt +++ b/Documentation/devicetree/bindings/mtd/mtd-physmap.txt @@ -13,10 +13,13 @@ file systems on embedded devices. device width times the number of interleaved chips. - device-width : (optional) Width of a single mtd chip. If omitted, assumed to be equal to 'bank-width'. + - vpp-gpios : (optional) specifies the GPIO line to control + VPP signal of the flash chip, the polarity is defined as a + standard flag (see Documentation/devicetree/bindings/gpio/gpio.txt + for more details and examples below) - #address-cells, #size-cells : Must be present if the device has sub-nodes representing partitions (see below). In this case both #address-cells and #size-cells must be equal to 1. - For JEDEC compatible devices, the following additional properties are defined: @@ -33,6 +36,7 @@ Example: reg = ; bank-width = <4>; device-width = <1>; + vpp-gpios = <&pio2 1 0>; /* PIO2.1 active high */ #address-cells = <1>; #size-cells = <1>; fs@0 { @@ -55,6 +59,7 @@ Here an example with multiple "reg" tuples: reg = <0 0x00000000 0x02000000 0 0x02000000 0x02000000>; bank-width = <2>; + vpp-gpios = <&pio3 2 1>; /* PIO3.2 active low */ partition@0 { label = "test-part1"; reg = <0 0x04000000>; diff --git a/drivers/mtd/maps/physmap_of.c b/drivers/mtd/maps/physmap_of.c index 2e6fb68..81caa77 100644 --- a/drivers/mtd/maps/physmap_of.c +++ b/drivers/mtd/maps/physmap_of.c @@ -17,12 +17,14 @@ #include #include #include +#include #include #include #include #include #include #include +#include #include #include @@ -74,6 +76,24 @@ static int of_flash_remove(struct platform_device *dev) return 0; } +static void of_flash_set_vpp_high(struct map_info *map, int state) +{ + /* map_priv_1 = gpio, map_priv_2 = "reference counter" */ + if (state && !map->map_priv_2++) + gpio_set_value(map->map_priv_1, 1); + else if (!state && !--map->map_priv_2) + gpio_set_value(map->map_priv_1, 0); +} + +static void of_flash_set_vpp_low(struct map_info *map, int state) +{ + /* map_priv_1 = gpio, map_priv_2 = "reference counter" */ + if (state && !map->map_priv_2++) + gpio_set_value(map->map_priv_1, 0); + else if (!state && !--map->map_priv_2) + gpio_set_value(map->map_priv_1, 1); +} + /* Helper function to handle probing of the obsolete "direct-mapped" * compatible binding, which has an extra "probe-type" property * describing the type of flash probe necessary. */ @@ -169,6 +189,9 @@ static int __devinit of_flash_probe(struct platform_device *dev) struct mtd_info **mtd_list = NULL; resource_size_t res_size; struct mtd_part_parser_data ppdata; + void (*set_vpp)(struct map_info *, int) = NULL; + int gpio_vpp; + enum of_gpio_flags gpio_flags; match = of_match_device(of_flash_match, &dev->dev); if (!match) @@ -200,6 +223,23 @@ static int __devinit of_flash_probe(struct platform_device *dev) dev_set_drvdata(&dev->dev, info); + gpio_vpp = of_get_named_gpio_flags(dp, "vpp-gpios", 0, &gpio_flags); + if (gpio_is_valid(gpio_vpp)) { + unsigned long dir = GPIOF_DIR_OUT; + + if (gpio_flags & OF_GPIO_ACTIVE_LOW) { + set_vpp = of_flash_set_vpp_low; + dir |= GPIOF_INIT_HIGH; + } else { + set_vpp = of_flash_set_vpp_high; + dir |= GPIOF_INIT_LOW; + } + err = devm_gpio_request_one(&dev->dev, gpio_vpp, dir, + dev_name(&dev->dev)); + if (err) + goto err_flash_remove; + } + mtd_list = kzalloc(sizeof(*mtd_list) * count, GFP_KERNEL); if (!mtd_list) goto err_flash_remove; @@ -235,6 +275,8 @@ static int __devinit of_flash_probe(struct platform_device *dev) info->list[i].map.phys = res.start; info->list[i].map.size = res_size; info->list[i].map.bankwidth = be32_to_cpup(width); + info->list[i].map.set_vpp = set_vpp; + info->list[i].map.map_priv_1 = gpio_vpp; err = -ENOMEM; info->list[i].map.virt = ioremap(info->list[i].map.phys,