diff options
-rw-r--r-- | cmd/mtd.c | 9 | ||||
-rw-r--r-- | drivers/core/ofnode.c | 44 | ||||
-rw-r--r-- | drivers/mtd/mtd-uclass.c | 15 | ||||
-rw-r--r-- | drivers/mtd/mtd_uboot.c | 129 | ||||
-rw-r--r-- | drivers/mtd/mtdcore.c | 35 | ||||
-rw-r--r-- | drivers/mtd/mtdpart.c | 63 | ||||
-rw-r--r-- | drivers/mtd/nand/spi/macronix.c | 46 | ||||
-rw-r--r-- | drivers/mtd/spi/sf_internal.h | 4 | ||||
-rw-r--r-- | drivers/mtd/spi/sf_mtd.c | 19 | ||||
-rw-r--r-- | drivers/mtd/spi/sf_probe.c | 6 | ||||
-rw-r--r-- | drivers/mtd/spi/spi-nor-core.c | 1 | ||||
-rw-r--r-- | drivers/mtd/spi/spi-nor-ids.c | 1 | ||||
-rw-r--r-- | drivers/mtd/spi/spi-nor-tiny.c | 1 | ||||
-rw-r--r-- | include/dm/ofnode.h | 27 | ||||
-rw-r--r-- | include/linux/mtd/mtd.h | 10 | ||||
-rw-r--r-- | include/mtd.h | 1 | ||||
-rw-r--r-- | test/dm/ofnode.c | 26 |
17 files changed, 362 insertions, 75 deletions
@@ -126,6 +126,13 @@ static void mtd_show_device(struct mtd_info *mtd) printf(" - driver: %s\n", mtd->dev->driver->name); } #endif + if (IS_ENABLED(CONFIG_OF_CONTROL) && mtd->dev) { + char buf[256]; + int res; + + res = ofnode_get_path(mtd_get_ofnode(mtd), buf, 256); + printf(" - path: %s\n", res == 0 ? buf : "unavailable"); + } /* MTD device information */ printf(" - type: "); @@ -535,7 +542,7 @@ static char mtd_help_text[] = "mtd bad <name>\n" "\n" "With:\n" - "\t<name>: NAND partition/chip name\n" + "\t<name>: NAND partition/chip name (or corresponding DM device name or OF path)\n" "\t<addr>: user address from/to which data will be retrieved/stored\n" "\t<off>: offset in <name> in bytes (default: start of the part)\n" "\t\t* must be block-aligned for erase\n" diff --git a/drivers/core/ofnode.c b/drivers/core/ofnode.c index 6c771e364f..eeeccfb446 100644 --- a/drivers/core/ofnode.c +++ b/drivers/core/ofnode.c @@ -286,6 +286,31 @@ const char *ofnode_get_name(ofnode node) return fdt_get_name(gd->fdt_blob, ofnode_to_offset(node), NULL); } +int ofnode_get_path(ofnode node, char *buf, int buflen) +{ + assert(ofnode_valid(node)); + + if (ofnode_is_np(node)) { + if (strlen(node.np->full_name) >= buflen) + return -ENOSPC; + + strcpy(buf, node.np->full_name); + + return 0; + } else { + int res; + + res = fdt_get_path(gd->fdt_blob, ofnode_to_offset(node), buf, + buflen); + if (!res) + return res; + else if (res == -FDT_ERR_NOSPACE) + return -ENOSPC; + else + return -EINVAL; + } +} + ofnode ofnode_get_by_phandle(uint phandle) { ofnode node; @@ -299,7 +324,8 @@ ofnode ofnode_get_by_phandle(uint phandle) return node; } -fdt_addr_t ofnode_get_addr_size_index(ofnode node, int index, fdt_size_t *size) +static fdt_addr_t __ofnode_get_addr_size_index(ofnode node, int index, + fdt_size_t *size, bool translate) { int na, ns; @@ -319,7 +345,7 @@ fdt_addr_t ofnode_get_addr_size_index(ofnode node, int index, fdt_size_t *size) ns = of_n_size_cells(ofnode_to_np(node)); - if (IS_ENABLED(CONFIG_OF_TRANSLATE) && ns > 0) { + if (translate && IS_ENABLED(CONFIG_OF_TRANSLATE) && ns > 0) { return of_translate_address(ofnode_to_np(node), prop_val); } else { na = of_n_addr_cells(ofnode_to_np(node)); @@ -330,12 +356,24 @@ fdt_addr_t ofnode_get_addr_size_index(ofnode node, int index, fdt_size_t *size) ns = ofnode_read_simple_size_cells(ofnode_get_parent(node)); return fdtdec_get_addr_size_fixed(gd->fdt_blob, ofnode_to_offset(node), "reg", - index, na, ns, size, true); + index, na, ns, size, + translate); } return FDT_ADDR_T_NONE; } +fdt_addr_t ofnode_get_addr_size_index(ofnode node, int index, fdt_size_t *size) +{ + return __ofnode_get_addr_size_index(node, index, size, true); +} + +fdt_addr_t ofnode_get_addr_size_index_notrans(ofnode node, int index, + fdt_size_t *size) +{ + return __ofnode_get_addr_size_index(node, index, size, false); +} + fdt_addr_t ofnode_get_addr_index(ofnode node, int index) { fdt_size_t size; diff --git a/drivers/mtd/mtd-uclass.c b/drivers/mtd/mtd-uclass.c index 9f5f672ba3..4ab84de553 100644 --- a/drivers/mtd/mtd-uclass.c +++ b/drivers/mtd/mtd-uclass.c @@ -9,21 +9,6 @@ #include <errno.h> #include <mtd.h> -/** - * mtd_probe - Probe the device @dev if not already done - * - * @dev: U-Boot device to probe - * - * @return 0 on success, an error otherwise. - */ -int mtd_probe(struct udevice *dev) -{ - if (device_active(dev)) - return 0; - - return device_probe(dev); -} - /* * Implement a MTD uclass which should include most flash drivers. * The uclass private is pointed to mtd_info. diff --git a/drivers/mtd/mtd_uboot.c b/drivers/mtd/mtd_uboot.c index c53ec657a3..90767ec417 100644 --- a/drivers/mtd/mtd_uboot.c +++ b/drivers/mtd/mtd_uboot.c @@ -9,6 +9,7 @@ #include <malloc.h> #include <dm/device.h> #include <dm/uclass-internal.h> +#include <dm/uclass.h> #include <linux/err.h> #include <linux/mtd/mtd.h> #include <linux/mtd/partitions.h> @@ -106,18 +107,26 @@ int mtd_search_alternate_name(const char *mtdname, char *altname, static void mtd_probe_uclass_mtd_devs(void) { struct udevice *dev; - int idx = 0; - /* Probe devices with DM compliant drivers */ - while (!uclass_find_device(UCLASS_MTD, idx, &dev) && dev) { - mtd_probe(dev); - idx++; - } + uclass_foreach_dev_probe(UCLASS_MTD, dev) + ; } #else static void mtd_probe_uclass_mtd_devs(void) { } #endif +#if IS_ENABLED(CONFIG_DM_SPI_FLASH) && IS_ENABLED(CONFIG_SPI_FLASH_MTD) +static void mtd_probe_uclass_spi_nor_devs(void) +{ + struct udevice *dev; + + uclass_foreach_dev_probe(UCLASS_SPI_FLASH, dev) + ; +} +#else +static void mtd_probe_uclass_spi_nor_devs(void) { } +#endif + #if defined(CONFIG_MTD_PARTITIONS) #define MTDPARTS_MAXLEN 512 @@ -198,53 +207,11 @@ static void mtd_del_all_parts(void) } while (ret > 0); } -int mtd_probe_devices(void) +static int parse_mtdparts(const char *mtdparts, const char *mtdids) { - static char *old_mtdparts; - static char *old_mtdids; - const char *mtdparts = get_mtdparts(); - const char *mtdids = get_mtdids(); - const char *mtdparts_next = mtdparts; + const char *mtdparts_next; struct mtd_info *mtd; - mtd_probe_uclass_mtd_devs(); - - /* - * Check if mtdparts/mtdids changed, if the MTD dev list was updated - * or if our previous attempt to delete existing partititions failed. - * In any of these cases we want to update the partitions, otherwise, - * everything is up-to-date and we can return 0 directly. - */ - if ((!mtdparts && !old_mtdparts && !mtdids && !old_mtdids) || - (mtdparts && old_mtdparts && mtdids && old_mtdids && - !mtd_dev_list_updated() && !mtd_del_all_parts_failed && - !strcmp(mtdparts, old_mtdparts) && - !strcmp(mtdids, old_mtdids))) - return 0; - - /* Update the local copy of mtdparts */ - free(old_mtdparts); - free(old_mtdids); - old_mtdparts = strdup(mtdparts); - old_mtdids = strdup(mtdids); - - /* - * Remove all old parts. Note that partition removal can fail in case - * one of the partition is still being used by an MTD user, so this - * does not guarantee that all old partitions are gone. - */ - mtd_del_all_parts(); - - /* - * Call mtd_dev_list_updated() to clear updates generated by our own - * parts removal loop. - */ - mtd_dev_list_updated(); - - /* If either mtdparts or mtdids is empty, then exit */ - if (!mtdparts || !mtdids) - return 0; - /* Start the parsing by ignoring the extra 'mtdparts=' prefix, if any */ if (!strncmp(mtdparts, "mtdparts=", sizeof("mtdparts=") - 1)) mtdparts += 9; @@ -343,6 +310,67 @@ int mtd_probe_devices(void) put_mtd_device(mtd); } + return 0; +} + +int mtd_probe_devices(void) +{ + static char *old_mtdparts; + static char *old_mtdids; + const char *mtdparts = get_mtdparts(); + const char *mtdids = get_mtdids(); + struct mtd_info *mtd; + + mtd_probe_uclass_mtd_devs(); + mtd_probe_uclass_spi_nor_devs(); + + /* + * Check if mtdparts/mtdids changed, if the MTD dev list was updated + * or if our previous attempt to delete existing partititions failed. + * In any of these cases we want to update the partitions, otherwise, + * everything is up-to-date and we can return 0 directly. + */ + if ((!mtdparts && !old_mtdparts && !mtdids && !old_mtdids) || + (mtdparts && old_mtdparts && mtdids && old_mtdids && + !mtd_dev_list_updated() && !mtd_del_all_parts_failed && + !strcmp(mtdparts, old_mtdparts) && + !strcmp(mtdids, old_mtdids))) + return 0; + + /* Update the local copy of mtdparts */ + free(old_mtdparts); + free(old_mtdids); + old_mtdparts = strdup(mtdparts); + old_mtdids = strdup(mtdids); + + /* + * Remove all old parts. Note that partition removal can fail in case + * one of the partition is still being used by an MTD user, so this + * does not guarantee that all old partitions are gone. + */ + mtd_del_all_parts(); + + /* + * Call mtd_dev_list_updated() to clear updates generated by our own + * parts removal loop. + */ + mtd_dev_list_updated(); + + /* If both mtdparts and mtdids are non-empty, parse */ + if (mtdparts && mtdids) { + if (parse_mtdparts(mtdparts, mtdids) < 0) + printf("Failed parsing MTD partitions from mtdparts!\n"); + } + + /* Fallback to OF partitions */ + mtd_for_each_device(mtd) { + if (list_empty(&mtd->partitions)) { + if (add_mtd_partitions_of(mtd) < 0) + printf("Failed parsing MTD %s OF partitions!\n", + mtd->name); + } + } + /* * Call mtd_dev_list_updated() to clear updates generated by our own * parts registration loop. @@ -355,6 +383,7 @@ int mtd_probe_devices(void) int mtd_probe_devices(void) { mtd_probe_uclass_mtd_devs(); + mtd_probe_uclass_spi_nor_devs(); return 0; } diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c index 0d1f94c6cb..582129d0df 100644 --- a/drivers/mtd/mtdcore.c +++ b/drivers/mtd/mtdcore.c @@ -768,6 +768,32 @@ int __get_mtd_device(struct mtd_info *mtd) } EXPORT_SYMBOL_GPL(__get_mtd_device); +#if CONFIG_IS_ENABLED(DM) && CONFIG_IS_ENABLED(OF_CONTROL) +static bool mtd_device_matches_name(struct mtd_info *mtd, const char *name) +{ + struct udevice *dev = NULL; + bool is_part; + + /* + * If the first character of mtd name is '/', try interpreting as OF + * path. Otherwise try comparing by mtd->name and mtd->dev->name. + */ + if (*name == '/') + device_get_global_by_ofnode(ofnode_path(name), &dev); + + is_part = mtd_is_partition(mtd); + + return (!is_part && dev && mtd->dev == dev) || + !strcmp(name, mtd->name) || + (is_part && mtd->dev && !strcmp(name, mtd->dev->name)); +} +#else +static bool mtd_device_matches_name(struct mtd_info *mtd, const char *name) +{ + return !strcmp(name, mtd->name); +} +#endif + /** * get_mtd_device_nm - obtain a validated handle for an MTD device by * device name @@ -784,10 +810,19 @@ struct mtd_info *get_mtd_device_nm(const char *name) mutex_lock(&mtd_table_mutex); mtd_for_each_device(other) { +#ifdef __UBOOT__ + if (mtd_device_matches_name(other, name)) { + if (mtd) + printf("\nWarning: MTD name \"%s\" is not unique!\n\n", + name); + mtd = other; + } +#else /* !__UBOOT__ */ if (!strcmp(name, other->name)) { mtd = other; break; } +#endif /* !__UBOOT__ */ } if (!mtd) diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c index d064ac3048..aa58f722da 100644 --- a/drivers/mtd/mtdpart.c +++ b/drivers/mtd/mtdpart.c @@ -892,6 +892,69 @@ int add_mtd_partitions(struct mtd_info *master, return 0; } +#if CONFIG_IS_ENABLED(DM) && CONFIG_IS_ENABLED(OF_CONTROL) +int add_mtd_partitions_of(struct mtd_info *master) +{ + ofnode parts, child; + int i = 0; + + if (!master->dev) + return 0; + + parts = ofnode_find_subnode(mtd_get_ofnode(master), "partitions"); + if (!ofnode_valid(parts) || !ofnode_is_available(parts) || + !ofnode_device_is_compatible(parts, "fixed-partitions")) + return 0; + + ofnode_for_each_subnode(child, parts) { + struct mtd_partition part = { 0 }; + struct mtd_info *slave; + fdt_addr_t offset, size; + + if (!ofnode_is_available(child)) + continue; + + offset = ofnode_get_addr_size_index_notrans(child, 0, &size); + if (offset == FDT_ADDR_T_NONE || !size) { + debug("Missing partition offset/size on \"%s\" partition\n", + master->name); + continue; + } + + part.name = ofnode_read_string(child, "label"); + if (!part.name) + part.name = ofnode_read_string(child, "name"); + + /* + * .mask_flags is used to remove flags in allocate_partition(), + * so when "read-only" is present, we add MTD_WRITABLE to the + * mask, and so MTD_WRITABLE will be removed on partition + * allocation + */ + if (ofnode_read_bool(child, "read-only")) + part.mask_flags |= MTD_WRITEABLE; + if (ofnode_read_bool(child, "lock")) + part.mask_flags |= MTD_POWERUP_LOCK; + + part.offset = offset; + part.size = size; + part.ecclayout = master->ecclayout; + + slave = allocate_partition(master, &part, i++, 0); + if (IS_ERR(slave)) + return PTR_ERR(slave); + + mutex_lock(&mtd_partitions_mutex); + list_add_tail(&slave->node, &master->partitions); + mutex_unlock(&mtd_partitions_mutex); + + add_mtd_device(slave); + } + + return 0; +} +#endif /* CONFIG_IS_ENABLED(DM) && CONFIG_IS_ENABLED(OF_CONTROL) */ + #ifndef __UBOOT__ static DEFINE_SPINLOCK(part_parser_lock); static LIST_HEAD(part_parsers); diff --git a/drivers/mtd/nand/spi/macronix.c b/drivers/mtd/nand/spi/macronix.c index 215f09acc3..f4a8e81639 100644 --- a/drivers/mtd/nand/spi/macronix.c +++ b/drivers/mtd/nand/spi/macronix.c @@ -114,6 +114,52 @@ static const struct spinand_info macronix_spinand_table[] = { &update_cache_variants), SPINAND_HAS_QE_BIT, SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout, NULL)), + SPINAND_INFO("MX35UF4GE4AD", 0xb7, + NAND_MEMORG(1, 4096, 256, 64, 2048, 1, 1, 1), + NAND_ECCREQ(8, 512), + SPINAND_INFO_OP_VARIANTS(&read_cache_variants, + &write_cache_variants, + &update_cache_variants), + SPINAND_HAS_QE_BIT, + SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout, + mx35lf1ge4ab_ecc_get_status)), + SPINAND_INFO("MX35UF2GE4AD", 0xa6, + NAND_MEMORG(1, 2048, 128, 64, 2048, 1, 1, 1), + NAND_ECCREQ(8, 512), + SPINAND_INFO_OP_VARIANTS(&read_cache_variants, + &write_cache_variants, + &update_cache_variants), + SPINAND_HAS_QE_BIT, + SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout, + mx35lf1ge4ab_ecc_get_status)), + SPINAND_INFO("MX35UF2GE4AC", 0xa2, + NAND_MEMORG(1, 2048, 64, 64, 2048, 1, 1, 1), + NAND_ECCREQ(4, 512), + SPINAND_INFO_OP_VARIANTS(&read_cache_variants, + &write_cache_variants, + &update_cache_variants), + SPINAND_HAS_QE_BIT, + SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout, + mx35lf1ge4ab_ecc_get_status)), + SPINAND_INFO("MX35UF1GE4AD", 0x96, + NAND_MEMORG(1, 2048, 128, 64, 1024, 1, 1, 1), + NAND_ECCREQ(8, 512), + SPINAND_INFO_OP_VARIANTS(&read_cache_variants, + &write_cache_variants, + &update_cache_variants), + SPINAND_HAS_QE_BIT, + SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout, + mx35lf1ge4ab_ecc_get_status)), + SPINAND_INFO("MX35UF1GE4AC", 0x92, + NAND_MEMORG(1, 2048, 64, 64, 1024, 1, 1, 1), + NAND_ECCREQ(4, 512), + SPINAND_INFO_OP_VARIANTS(&read_cache_variants, + &write_cache_variants, + &update_cache_variants), + SPINAND_HAS_QE_BIT, + SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout, + mx35lf1ge4ab_ecc_get_status)), + }; static int macronix_spinand_detect(struct spinand_device *spinand) diff --git a/drivers/mtd/spi/sf_internal.h b/drivers/mtd/spi/sf_internal.h index 786301ba4a..0b63e1bfc2 100644 --- a/drivers/mtd/spi/sf_internal.h +++ b/drivers/mtd/spi/sf_internal.h @@ -81,14 +81,14 @@ int spi_flash_cmd_get_sw_write_prot(struct spi_flash *flash); #if CONFIG_IS_ENABLED(SPI_FLASH_MTD) int spi_flash_mtd_register(struct spi_flash *flash); -void spi_flash_mtd_unregister(void); +void spi_flash_mtd_unregister(struct spi_flash *flash); #else static inline int spi_flash_mtd_register(struct spi_flash *flash) { return 0; } -static inline void spi_flash_mtd_unregister(void) +static inline void spi_flash_mtd_unregister(struct spi_flash *flash) { } #endif diff --git a/drivers/mtd/spi/sf_mtd.c b/drivers/mtd/spi/sf_mtd.c index 987fac2501..04de868080 100644 --- a/drivers/mtd/spi/sf_mtd.c +++ b/drivers/mtd/spi/sf_mtd.c @@ -10,6 +10,20 @@ #include <linux/mtd/mtd.h> #include <spi_flash.h> +#if CONFIG_IS_ENABLED(DM_SPI_FLASH) + +int spi_flash_mtd_register(struct spi_flash *flash) +{ + return add_mtd_device(&flash->mtd); +} + +void spi_flash_mtd_unregister(struct spi_flash *flash) +{ + del_mtd_device(&flash->mtd); +} + +#else /* !CONFIG_IS_ENABLED(DM_SPI_FLASH) */ + static struct mtd_info sf_mtd_info; static bool sf_mtd_registered; static char sf_mtd_name[8]; @@ -111,6 +125,7 @@ int spi_flash_mtd_register(struct spi_flash *flash) sf_mtd_info.size = flash->size; sf_mtd_info.priv = flash; + sf_mtd_info.dev = flash->dev; /* Only uniform flash devices for now */ sf_mtd_info.numeraseregions = 0; @@ -123,7 +138,7 @@ int spi_flash_mtd_register(struct spi_flash *flash) return ret; } -void spi_flash_mtd_unregister(void) +void spi_flash_mtd_unregister(struct spi_flash *flash) { int ret; @@ -146,3 +161,5 @@ void spi_flash_mtd_unregister(void) printf("Failed to unregister MTD %s and the spi_flash object is going away: you're in deep trouble!", sf_mtd_info.name); } + +#endif /* !CONFIG_IS_ENABLED(DM_SPI_FLASH) */ diff --git a/drivers/mtd/spi/sf_probe.c b/drivers/mtd/spi/sf_probe.c index 3befbe91ca..7edb8759fd 100644 --- a/drivers/mtd/spi/sf_probe.c +++ b/drivers/mtd/spi/sf_probe.c @@ -84,7 +84,7 @@ struct spi_flash *spi_flash_probe(unsigned int busnum, unsigned int cs, void spi_flash_free(struct spi_flash *flash) { if (CONFIG_IS_ENABLED(SPI_FLASH_MTD)) - spi_flash_mtd_unregister(); + spi_flash_mtd_unregister(flash); spi_free_slave(flash->spi); free(flash); @@ -150,8 +150,10 @@ int spi_flash_std_probe(struct udevice *dev) static int spi_flash_std_remove(struct udevice *dev) { + struct spi_flash *flash = dev_get_uclass_priv(dev); + if (CONFIG_IS_ENABLED(SPI_FLASH_MTD)) - spi_flash_mtd_unregister(); + spi_flash_mtd_unregister(flash); return 0; } diff --git a/drivers/mtd/spi/spi-nor-core.c b/drivers/mtd/spi/spi-nor-core.c index a6625535a7..6af9c675a4 100644 --- a/drivers/mtd/spi/spi-nor-core.c +++ b/drivers/mtd/spi/spi-nor-core.c @@ -2535,6 +2535,7 @@ int spi_nor_scan(struct spi_nor *nor) if (!mtd->name) mtd->name = info->name; + mtd->dev = nor->dev; mtd->priv = nor; mtd->type = MTD_NORFLASH; mtd->writesize = 1; diff --git a/drivers/mtd/spi/spi-nor-ids.c b/drivers/mtd/spi/spi-nor-ids.c index 2b57797954..8d2b73b676 100644 --- a/drivers/mtd/spi/spi-nor-ids.c +++ b/drivers/mtd/spi/spi-nor-ids.c @@ -167,6 +167,7 @@ const struct flash_info spi_nor_ids[] = { { INFO("mx66l1g45g", 0xc2201b, 0, 64 * 1024, 2048, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, { INFO("mx25l1633e", 0xc22415, 0, 64 * 1024, 32, SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES | SECT_4K) }, { INFO("mx25r6435f", 0xc22817, 0, 64 * 1024, 128, SECT_4K) }, + { INFO("mx66uw2g345g", 0xc2943c, 0, 64 * 1024, 4096, SECT_4K | SPI_NOR_OCTAL_READ | SPI_NOR_4B_OPCODES) }, #endif #ifdef CONFIG_SPI_FLASH_STMICRO /* STMICRO */ diff --git a/drivers/mtd/spi/spi-nor-tiny.c b/drivers/mtd/spi/spi-nor-tiny.c index 1d5861d55c..b0aa97d324 100644 --- a/drivers/mtd/spi/spi-nor-tiny.c +++ b/drivers/mtd/spi/spi-nor-tiny.c @@ -751,6 +751,7 @@ int spi_nor_scan(struct spi_nor *nor) return ret; mtd->name = "spi-flash"; + mtd->dev = nor->dev; mtd->priv = nor; mtd->type = MTD_NORFLASH; mtd->writesize = 1; diff --git a/include/dm/ofnode.h b/include/dm/ofnode.h index 8a69fd87da..3da05d8b21 100644 --- a/include/dm/ofnode.h +++ b/include/dm/ofnode.h @@ -459,6 +459,16 @@ ofnode ofnode_get_parent(ofnode node); const char *ofnode_get_name(ofnode node); /** + * ofnode_get_path() - get the full path of a node + * + * @node: valid node to look up + * @buf: buffer to write the node path into + * @buflen: buffer size + * @return 0 if OK, -ve on error + */ +int ofnode_get_path(ofnode node, char *buf, int buflen); + +/** * ofnode_get_by_phandle() - get ofnode from phandle * * @phandle: phandle to look up @@ -490,6 +500,23 @@ phys_addr_t ofnode_get_addr_size_index(ofnode node, int index, fdt_size_t *size); /** + * ofnode_get_addr_size_index_notrans() - get an address/size from a node + * based on index, without address + * translation + * + * This reads the register address/size from a node based on index. + * The resulting address is not translated. Useful for example for on-disk + * addresses. + * + * @node: node to read from + * @index: Index of address to read (0 for first) + * @size: Pointer to size of the address + * @return address, or FDT_ADDR_T_NONE if not present or invalid + */ +phys_addr_t ofnode_get_addr_size_index_notrans(ofnode node, int index, + fdt_size_t *size); + +/** * ofnode_get_addr_index() - get an address from a node * * This reads the register address from a node diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h index 927854950a..3b302fb8c3 100644 --- a/include/linux/mtd/mtd.h +++ b/include/linux/mtd/mtd.h @@ -581,6 +581,16 @@ static inline int del_mtd_partitions(struct mtd_info *mtd) } #endif +#if defined(CONFIG_MTD_PARTITIONS) && CONFIG_IS_ENABLED(DM) && \ + CONFIG_IS_ENABLED(OF_CONTROL) +int add_mtd_partitions_of(struct mtd_info *master); +#else +static inline int add_mtd_partitions_of(struct mtd_info *master) +{ + return 0; +} +#endif + struct mtd_info *__mtd_next_device(int i); #define mtd_for_each_device(mtd) \ for ((mtd) = __mtd_next_device(0); \ diff --git a/include/mtd.h b/include/mtd.h index b0f8693386..b569331edb 100644 --- a/include/mtd.h +++ b/include/mtd.h @@ -8,7 +8,6 @@ #include <linux/mtd/mtd.h> -int mtd_probe(struct udevice *dev); int mtd_probe_devices(void); void board_mtdparts_default(const char **mtdids, const char **mtdparts); diff --git a/test/dm/ofnode.c b/test/dm/ofnode.c index e0b525eeb1..94a4d2189e 100644 --- a/test/dm/ofnode.c +++ b/test/dm/ofnode.c @@ -289,6 +289,32 @@ static int dm_test_ofnode_get_reg(struct unit_test_state *uts) ut_asserteq(FDT_ADDR_T_NONE, addr); ut_asserteq(FDT_SIZE_T_NONE, size); + node = ofnode_path("/translation-test@8000/noxlatebus@3,300/dev@42"); + ut_assert(ofnode_valid(node)); + addr = ofnode_get_addr_size_index_notrans(node, 0, &size); + ut_asserteq_64(0x42, addr); + return 0; } DM_TEST(dm_test_ofnode_get_reg, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +static int dm_test_ofnode_get_path(struct unit_test_state *uts) +{ + const char *path = "/translation-test@8000/noxlatebus@3,300/dev@42"; + char buf[64]; + ofnode node; + int res; + + node = ofnode_path(path); + ut_assert(ofnode_valid(node)); + + res = ofnode_get_path(node, buf, 64); + ut_asserteq(0, res); + ut_asserteq_str(path, buf); + + res = ofnode_get_path(node, buf, 32); + ut_asserteq(-ENOSPC, res); + + return 0; +} +DM_TEST(dm_test_ofnode_get_path, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); |