diff options
author | Sascha Hauer <s.hauer@pengutronix.de> | 2013-08-05 12:50:06 +0200 |
---|---|---|
committer | Sascha Hauer <s.hauer@pengutronix.de> | 2013-08-05 12:50:06 +0200 |
commit | fbf082b56540b4f3853015f3686c8f106a91707a (patch) | |
tree | e5901744625d45ca075a55eff3c9fc1e2c05a134 /drivers | |
parent | 8c5a1c0c81aade3546a18b12e2eeff0b38e79e99 (diff) | |
parent | 6a37488917b22fcf24d99c695ed1755198a9393b (diff) | |
download | barebox-fbf082b56540b4f3853015f3686c8f106a91707a.tar.gz barebox-fbf082b56540b4f3853015f3686c8f106a91707a.tar.xz |
Merge branch 'for-next/of'
Conflicts:
arch/arm/boards/freescale-mx53-loco/board.c
drivers/of/Makefile
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/Kconfig | 1 | ||||
-rw-r--r-- | drivers/Makefile | 1 | ||||
-rw-r--r-- | drivers/bus/Kconfig | 7 | ||||
-rw-r--r-- | drivers/bus/Makefile | 1 | ||||
-rw-r--r-- | drivers/bus/imx-weim.c | 171 | ||||
-rw-r--r-- | drivers/led/Kconfig | 4 | ||||
-rw-r--r-- | drivers/led/led-gpio.c | 78 | ||||
-rw-r--r-- | drivers/mci/mci-core.c | 13 | ||||
-rw-r--r-- | drivers/mtd/core.c | 1 | ||||
-rw-r--r-- | drivers/of/Kconfig | 9 | ||||
-rw-r--r-- | drivers/of/Makefile | 1 | ||||
-rw-r--r-- | drivers/of/barebox.c | 99 | ||||
-rw-r--r-- | drivers/of/base.c | 65 | ||||
-rw-r--r-- | drivers/of/of_path.c | 155 | ||||
-rw-r--r-- | drivers/of/partition.c | 64 |
15 files changed, 640 insertions, 30 deletions
diff --git a/drivers/Kconfig b/drivers/Kconfig index 3a95e5140d..d34d2c7443 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig @@ -24,5 +24,6 @@ source "drivers/dma/Kconfig" source "drivers/gpio/Kconfig" source "drivers/w1/Kconfig" source "drivers/pinctrl/Kconfig" +source "drivers/bus/Kconfig" endmenu diff --git a/drivers/Makefile b/drivers/Makefile index daf821c83c..ba1dc6df76 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -23,3 +23,4 @@ obj-y += gpio/ obj-$(CONFIG_OFTREE) += of/ obj-$(CONFIG_W1) += w1/ obj-y += pinctrl/ +obj-y += bus/ diff --git a/drivers/bus/Kconfig b/drivers/bus/Kconfig new file mode 100644 index 0000000000..5938d3f2dc --- /dev/null +++ b/drivers/bus/Kconfig @@ -0,0 +1,7 @@ +menu "Bus devices" + +config IMX_WEIM + depends on ARCH_IMX + bool "i.MX WEIM driver" + +endmenu diff --git a/drivers/bus/Makefile b/drivers/bus/Makefile new file mode 100644 index 0000000000..42a8d49479 --- /dev/null +++ b/drivers/bus/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_IMX_WEIM) += imx-weim.o diff --git a/drivers/bus/imx-weim.c b/drivers/bus/imx-weim.c new file mode 100644 index 0000000000..78bccda15a --- /dev/null +++ b/drivers/bus/imx-weim.c @@ -0,0 +1,171 @@ +/* + * EIM driver for Freescale's i.MX chips + * + * Copyright (C) 2013 Freescale Semiconductor, Inc. + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ +#include <common.h> +#include <driver.h> +#include <init.h> +#include <io.h> +#include <of.h> + +struct imx_weim_devtype { + unsigned int cs_count; + unsigned int cs_regs_count; + unsigned int cs_stride; +}; + +static const struct imx_weim_devtype imx1_weim_devtype = { + .cs_count = 6, + .cs_regs_count = 2, + .cs_stride = 0x08, +}; + +static const struct imx_weim_devtype imx27_weim_devtype = { + .cs_count = 6, + .cs_regs_count = 3, + .cs_stride = 0x10, +}; + +static const struct imx_weim_devtype imx50_weim_devtype = { + .cs_count = 4, + .cs_regs_count = 6, + .cs_stride = 0x18, +}; + +static const struct imx_weim_devtype imx51_weim_devtype = { + .cs_count = 6, + .cs_regs_count = 6, + .cs_stride = 0x18, +}; + +static struct of_device_id weim_id_table[] = { + { + /* i.MX1/21 */ + .compatible = "fsl,imx1-weim", + .data = (unsigned long)&imx1_weim_devtype, + }, { + /* i.MX25/27/31/35 */ + .compatible = "fsl,imx27-weim", + .data = (unsigned long)&imx27_weim_devtype, + }, { + /* i.MX50/53/6Q */ + .compatible = "fsl,imx50-weim", + .data = (unsigned long)&imx50_weim_devtype, + }, { + /* i.MX51 */ + .compatible = "fsl,imx51-weim", + .data = (unsigned long)&imx51_weim_devtype, + }, { + .compatible = "fsl,imx6q-weim", + .data = (unsigned long)&imx50_weim_devtype, + }, { + } +}; + +struct imx_weim { + struct device_d *dev; + void __iomem *base; + struct imx_weim_devtype *devtype; +}; + +/* Parse and set the timing for this device. */ +static int +weim_timing_setup(struct imx_weim *weim, struct device_node *np) +{ + struct imx_weim_devtype *devtype = weim->devtype; + u32 cs_idx, value[devtype->cs_regs_count]; + int i, ret; + + /* get the CS index from this child node's "reg" property. */ + ret = of_property_read_u32(np, "reg", &cs_idx); + if (ret) + return ret; + + if (cs_idx >= devtype->cs_count) + return -EINVAL; + + ret = of_property_read_u32_array(np, "fsl,weim-cs-timing", + value, devtype->cs_regs_count); + if (ret) + return ret; + + dev_dbg(weim->dev, "setting up cs for %s\n", np->name); + + /* set the timing for WEIM */ + for (i = 0; i < devtype->cs_regs_count; i++) + writel(value[i], weim->base + cs_idx * devtype->cs_stride + i * 4); + + return 0; +} + +static int weim_parse_dt(struct imx_weim *weim) +{ + struct device_node *child; + int ret; + + for_each_child_of_node(weim->dev->device_node, child) { + if (!child->name) + continue; + + ret = weim_timing_setup(weim, child); + if (ret) { + dev_err(weim->dev, "%s set timing failed.\n", + child->full_name); + return ret; + } + } + + ret = of_platform_populate(weim->dev->device_node, NULL, weim->dev); + if (ret) + dev_err(weim->dev, "%s fail to create devices.\n", + weim->dev->device_node->full_name); + return ret; +} + +static int weim_probe(struct device_d *dev) +{ + struct imx_weim_devtype *devtype; + struct imx_weim *weim; + int ret; + + ret = dev_get_drvdata(dev, (unsigned long *)&devtype); + if (ret) + return ret; + + weim = xzalloc(sizeof(*weim)); + + weim->dev = dev; + weim->devtype = devtype; + + /* get the resource */ + weim->base = dev_request_mem_region(dev, 0); + if (!weim->base) { + ret = -EBUSY; + goto weim_err; + } + + /* parse the device node */ + ret = weim_parse_dt(weim); + if (ret) { + goto weim_err; + } + + dev_info(dev, "WEIM driver registered.\n"); + + return 0; + +weim_err: + return ret; +} + +static struct driver_d weim_driver = { + .name = "imx-weim", + .of_compatible = DRV_OF_COMPAT(weim_id_table), + .probe = weim_probe, +}; +device_platform_driver(weim_driver); diff --git a/drivers/led/Kconfig b/drivers/led/Kconfig index 8ca6ab8e44..3ead82e031 100644 --- a/drivers/led/Kconfig +++ b/drivers/led/Kconfig @@ -7,6 +7,10 @@ config LED_GPIO bool "gpio LED support" depends on GENERIC_GPIO +config LED_GPIO_OF + bool "support parsing gpio LEDs from device tree" + depends on LED_GPIO && OFTREE + config LED_GPIO_RGB bool "gpio rgb LED support" depends on LED_GPIO diff --git a/drivers/led/led-gpio.c b/drivers/led/led-gpio.c index 08dc9bad0d..69db70fab8 100644 --- a/drivers/led/led-gpio.c +++ b/drivers/led/led-gpio.c @@ -18,8 +18,10 @@ * */ #include <common.h> +#include <init.h> #include <led.h> #include <gpio.h> +#include <of_gpio.h> static void led_gpio_set(struct led *led, unsigned int value) { @@ -194,3 +196,79 @@ void led_gpio_rgb_unregister(struct gpio_led *led) led_unregister(&led->led); } #endif /* CONFIG_LED_GPIO_RGB */ + +#ifdef CONFIG_LED_GPIO_OF + +struct led_trg { + const char *str; + enum led_trigger trg; +}; + +static struct led_trg triggers[] = { + { .str = "heartbeat", LED_TRIGGER_HEARTBEAT, }, + { .str = "panic", LED_TRIGGER_PANIC, }, + { .str = "net", LED_TRIGGER_NET_TXRX, }, +}; + +static void led_of_parse_trigger(struct led *led, struct device_node *np) +{ + const char *trigger; + int i; + + trigger = of_get_property(np, "linux,default-trigger", NULL); + if (!trigger) + trigger = of_get_property(np, "barebox,default-trigger", NULL); + + if (!trigger) + return; + + for (i = 0; i < ARRAY_SIZE(triggers); i++) { + struct led_trg *trg = &triggers[i]; + if (!strcmp(trg->str, trigger)) { + led_set_trigger(trg->trg, led); + return; + } + } +} + +static int led_gpio_of_probe(struct device_d *dev) +{ + struct device_node *child; + + for_each_child_of_node(dev->device_node, child) { + struct gpio_led *gled; + enum of_gpio_flags flags; + int gpio; + + gpio = of_get_named_gpio_flags(child, "gpios", 0, &flags); + if (gpio < 0) + continue; + + gled = xzalloc(sizeof(*gled)); + gled->led.name = xstrdup(child->name); + gled->gpio = gpio; + gled->active_low = (flags & OF_GPIO_ACTIVE_LOW) ? 1 : 0; + + dev_dbg(dev, "register led %s on gpio%d, active_low = %d\n", + gled->led.name, gled->gpio, gled->active_low); + + led_of_parse_trigger(&gled->led, child); + led_gpio_register(gled); + } + + return 0; +} + +static struct of_device_id led_gpio_of_ids[] = { + { .compatible = "gpio-leds", }, + { } +}; + +static struct driver_d led_gpio_of_driver = { + .name = "gpio-leds", + .probe = led_gpio_of_probe, + .of_compatible = DRV_OF_COMPAT(led_gpio_of_ids), +}; +device_platform_driver(led_gpio_of_driver); + +#endif /* CONFIG LED_GPIO_OF */ diff --git a/drivers/mci/mci-core.c b/drivers/mci/mci-core.c index 67668d53f0..66ddb5b4ff 100644 --- a/drivers/mci/mci-core.c +++ b/drivers/mci/mci-core.c @@ -406,7 +406,7 @@ static int mci_calc_blk_cnt(uint64_t cap, unsigned shift) } static void mci_part_add(struct mci *mci, uint64_t size, - unsigned int part_cfg, char *name, int idx, bool ro, + unsigned int part_cfg, char *name, char *partname, int idx, bool ro, int area_type) { struct mci_part *part = &mci->part[mci->nr_parts]; @@ -414,6 +414,7 @@ static void mci_part_add(struct mci *mci, uint64_t size, part->mci = mci; part->size = size; part->blk.cdev.name = name; + part->blk.cdev.partname = partname; part->blk.blockbits = SECTOR_SHIFT; part->blk.num_blocks = mci_calc_blk_cnt(size, part->blk.blockbits); part->area_type = area_type; @@ -482,13 +483,14 @@ static int mmc_change_freq(struct mci *mci) unsigned int part_size; for (idx = 0; idx < MMC_NUM_BOOT_PARTITION; idx++) { - char *name; + char *name, *partname; part_size = mci->ext_csd[EXT_CSD_BOOT_MULT] << 17; - name = asprintf("%s.boot%d", mci->cdevname, idx); + partname = asprintf("boot%d", idx); + name = asprintf("%s.%s", mci->cdevname, partname); mci_part_add(mci, part_size, EXT_CSD_PART_CONFIG_ACC_BOOT0 + idx, - name, idx, true, + name, partname, idx, true, MMC_BLK_DATA_AREA_BOOT); } @@ -1104,7 +1106,7 @@ static int mci_startup(struct mci *mci) err = mci_set_blocklen(mci, mci->read_bl_len); mci_part_add(mci, mci->capacity, 0, - mci->cdevname, 0, true, + mci->cdevname, NULL, 0, true, MMC_BLK_DATA_AREA_MAIN); return err; @@ -1556,6 +1558,7 @@ static int mci_card_probe(struct mci *mci) dev_warn(&mci->dev, "No partition table found\n"); rc = 0; /* it's not a failure */ } + of_parse_partitions(&part->blk.cdev, host->hw_dev->device_node); } if (IS_ENABLED(CONFIG_MCI_MMC_BOOT_PARTITIONS) && diff --git a/drivers/mtd/core.c b/drivers/mtd/core.c index fc345470f2..70036aaa5b 100644 --- a/drivers/mtd/core.c +++ b/drivers/mtd/core.c @@ -386,6 +386,7 @@ int add_mtd_device(struct mtd_info *mtd, char *devname) } devfs_create(&mtd->cdev); + of_parse_partitions(&mtd->cdev, mtd->parent->device_node); list_for_each_entry(hook, &mtd_register_hooks, hook) if (hook->add_mtd_device) diff --git a/drivers/of/Kconfig b/drivers/of/Kconfig index 03ae599279..ab5eac8442 100644 --- a/drivers/of/Kconfig +++ b/drivers/of/Kconfig @@ -18,3 +18,12 @@ config OFDEVICE config OF_NET depends on NET def_bool y + +config OF_BAREBOX_DRIVERS + depends on OFDEVICE + bool "Enable barebox specific devicetree configuration drivers" + help + barebox supports being configured from devicetree. This enables + support for this feature. This currently allows to configure the + environment path from devicetree and to partition devices. See + Documentation/devicetree/bindings/barebox/ for more information. diff --git a/drivers/of/Makefile b/drivers/of/Makefile index 058afc2788..a19a8af635 100644 --- a/drivers/of/Makefile +++ b/drivers/of/Makefile @@ -4,3 +4,4 @@ obj-$(CONFIG_GPIOLIB) += of_gpio.o obj-y += partition.o obj-y += of_net.o obj-$(CONFIG_MTD) += of_mtd.o +obj-$(CONFIG_OF_BAREBOX_DRIVERS) += barebox.o of_path.o diff --git a/drivers/of/barebox.c b/drivers/of/barebox.c new file mode 100644 index 0000000000..8977158992 --- /dev/null +++ b/drivers/of/barebox.c @@ -0,0 +1,99 @@ +/* + * barebox.c + * + * Copyright (c) 2013 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include <common.h> +#include <init.h> +#include <io.h> +#include <of.h> +#include <malloc.h> +#include <partition.h> +#include <envfs.h> + +struct of_partition { + struct list_head list; + char *nodepath; + struct device_d *dev; + struct device_node *of_partitions; +}; + +static LIST_HEAD(of_partition_list); + +struct device_d *of_find_device_by_node_path(const char *path) +{ + struct device_d *dev; + + for_each_device(dev) { + if (!dev->device_node) + continue; + if (!strcmp(path, dev->device_node->full_name)) + return dev; + } + + return NULL; +} + +static int environment_probe(struct device_d *dev) +{ + char *path; + int ret; + + ret = of_find_path(dev->device_node, "device-path", &path); + if (ret) + return ret; + + dev_info(dev, "setting default environment path to %s\n", path); + + default_environment_path = path; + + return 0; +} + +static struct of_device_id environment_dt_ids[] = { + { + .compatible = "barebox,environment", + }, { + /* sentinel */ + } +}; + +static struct driver_d environment_driver = { + .name = "barebox-environment", + .probe = environment_probe, + .of_compatible = environment_dt_ids, +}; + +static int barebox_of_driver_init(void) +{ + struct device_node *node; + + node = of_get_root_node(); + if (!node) + return 0; + + node = of_find_node_by_path("/chosen"); + if (!node) + return 0; + + of_platform_populate(node, of_default_bus_match_table, NULL); + + platform_driver_register(&environment_driver); + + return 0; +} +late_initcall(barebox_of_driver_init); diff --git a/drivers/of/base.c b/drivers/of/base.c index 3b8dd0c3dd..34a06c298e 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -1755,3 +1755,68 @@ int of_add_initrd(struct device_node *root, resource_size_t start, return 0; } + +/** + * of_device_enable - enable a devicenode device + * @node - the node to enable + * + * This deletes the status property of a devicenode effectively + * enabling the device. + */ +int of_device_enable(struct device_node *node) +{ + struct property *pp; + + pp = of_find_property(node, "status", NULL); + if (!pp) + return 0; + + of_delete_property(pp); + + return 0; +} + +/** + * of_device_enable_path - enable a devicenode + * @path - the nodepath to enable + * + * wrapper around of_device_enable taking the nodepath as argument + */ +int of_device_enable_path(const char *path) +{ + struct device_node *node; + + node = of_find_node_by_path(path); + if (!node) + return -ENODEV; + + return of_device_enable(node); +} + +/** + * of_device_enable - disable a devicenode device + * @node - the node to disable + * + * This sets the status of a devicenode to "disabled" + */ +int of_device_disable(struct device_node *node) +{ + return of_set_property(node, "status", "disabled", sizeof("disabled"), 1); +} + +/** + * of_device_disable_path - disable a devicenode + * @path - the nodepath to disable + * + * wrapper around of_device_disable taking the nodepath as argument + */ +int of_device_disable_path(const char *path) +{ + struct device_node *node; + + node = of_find_node_by_path(path); + if (!node) + return -ENODEV; + + return of_device_disable(node); +} diff --git a/drivers/of/of_path.c b/drivers/of/of_path.c new file mode 100644 index 0000000000..ab8618e23d --- /dev/null +++ b/drivers/of/of_path.c @@ -0,0 +1,155 @@ +/* + * of_path.c + * + * Copyright (c) 2013 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include <common.h> +#include <malloc.h> +#include <of.h> + +struct of_path { + struct cdev *cdev; + struct device_d *dev; +}; + +struct of_path_type { + const char *name; + int (*parse)(struct of_path *op, const char *str); +}; + +/** + * of_path_type_partname - find a partition based on physical device and + * partition name + * @op: of_path context + * @name: the partition name to find + */ +static int of_path_type_partname(struct of_path *op, const char *name) +{ + if (!op->dev) + return -EINVAL; + + op->cdev = device_find_partition(op->dev, name); + if (op->cdev) { + pr_debug("%s: found part '%s'\n", __func__, name); + return 0; + } else { + pr_debug("%s: cannot find part '%s'\n", __func__, name); + return -ENODEV; + } +} + +static struct of_path_type of_path_types[] = { + { + .name = "partname", + .parse = of_path_type_partname, + }, +}; + +static int of_path_parse_one(struct of_path *op, const char *str) +{ + int i, ret; + char *name, *desc; + + pr_debug("parsing: %s\n", str); + + name = xstrdup(str); + desc = strchr(name, ':'); + if (!desc) { + free(name); + return -EINVAL; + } + + *desc = 0; + desc++; + + for (i = 0; i < ARRAY_SIZE(of_path_types); i++) { + if (!strcmp(of_path_types[i].name, name)) { + ret = of_path_types[i].parse(op, desc); + goto out; + } + } + + ret = -EINVAL; +out: + free(name); + + return ret; +} + +/** + * of_find_path - translate a path description in the devicetree to a barebox + * path + * + * @node: the node containing the property with the path description + * @propname: the property name of the path description + * @outpath: if this function returns 0 outpath will contain the path belonging + * to the input path description. Must be freed with free(). + * + * pathes in the devicetree have the form of a multistring property. The first + * string contains the full path to the physical device containing the path. + * The remaining strings have the form "<type>:<options>". Currently supported + * for <type> are: + * + * partname:<partname> - find a partition by its partition name. For mtd + * partitions this is the label. For DOS partitions + * this is the number beginning with 0. + * + * examples: + * + * device-path = &mmc0, "partname:0"; + * device-path = &norflash, "partname:barebox-environment"; + */ +int of_find_path(struct device_node *node, const char *propname, char **outpath) +{ + struct of_path op = {}; + struct device_node *rnode; + const char *path, *str; + int i, len, ret; + + path = of_get_property(node, propname, &len); + if (!path) + return -EINVAL; + + rnode = of_find_node_by_path(path); + if (!rnode) + return -ENODEV; + + op.dev = of_find_device_by_node_path(rnode->full_name); + if (!op.dev) + return -ENODEV; + + device_detect(op.dev); + + i = 1; + + while (1) { + ret = of_property_read_string_index(node, propname, i++, &str); + if (ret) + break; + + ret = of_path_parse_one(&op, str); + if (ret) + return ret; + } + + if (!op.cdev) + return -ENOENT; + + *outpath = asprintf("/dev/%s", op.cdev->name); + + return 0; +} diff --git a/drivers/of/partition.c b/drivers/of/partition.c index e4b7d1e66b..7199eff875 100644 --- a/drivers/of/partition.c +++ b/drivers/of/partition.c @@ -23,44 +23,58 @@ #include <linux/mtd/mtd.h> #include <nand.h> -int of_parse_partitions(struct cdev *cdev, struct device_node *node) +struct cdev *of_parse_partition(struct cdev *cdev, struct device_node *node) { - struct device_node *n; const char *partname; char *filename; + struct cdev *new; + const __be32 *reg; + unsigned long offset, size; + const char *name; + int len; + unsigned long flags = 0; - for_each_child_of_node(node, n) { - const __be32 *reg; - unsigned long offset, size; - const char *name; - int len; - unsigned long flags = 0; + if (!node) + return NULL; + + reg = of_get_property(node, "reg", &len); + if (!reg) + return NULL; + + offset = be32_to_cpu(reg[0]); + size = be32_to_cpu(reg[1]); + + partname = of_get_property(node, "label", &len); + if (!partname) + partname = of_get_property(node, "name", &len); + name = (char *)partname; - reg = of_get_property(n, "reg", &len); - if (!reg) - continue; + debug("add partition: %s.%s 0x%08lx 0x%08lx\n", cdev->name, partname, offset, size); - offset = be32_to_cpu(reg[0]); - size = be32_to_cpu(reg[1]); + if (of_get_property(node, "read-only", &len)) + flags = DEVFS_PARTITION_READONLY; - partname = of_get_property(n, "label", &len); - if (!partname) - partname = of_get_property(n, "name", &len); - name = (char *)partname; + filename = asprintf("%s.%s", cdev->name, partname); - debug("add partition: %s.%s 0x%08lx 0x%08lx\n", cdev->name, partname, offset, size); + new = devfs_add_partition(cdev->name, offset, size, flags, filename); - if (of_get_property(n, "read-only", &len)) - flags = DEVFS_PARTITION_READONLY; + if (cdev->mtd && cdev->mtd->type == MTD_NANDFLASH) + dev_add_bb_dev(filename, NULL); - filename = asprintf("%s.%s", cdev->name, partname); + free(filename); - devfs_add_partition(cdev->name, offset, size, flags, filename); + return new; +} + +int of_parse_partitions(struct cdev *cdev, struct device_node *node) +{ + struct device_node *n; - if (cdev->mtd && cdev->mtd->type == MTD_NANDFLASH) - dev_add_bb_dev(filename, NULL); + if (!node) + return -EINVAL; - free(filename); + for_each_child_of_node(node, n) { + of_parse_partition(cdev, n); } return 0; |