summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorTom Rini <[email protected]>2021-06-24 11:11:13 -0400
committerTom Rini <[email protected]>2021-06-24 11:11:13 -0400
commit67edf2553f15e5148efca213af3f41cef3410680 (patch)
treec362fd9dc9446add0e24fd4d843dee32af2f299a /drivers
parent95eca8612b7ba790dfe5d72ce3269ef3a7cdae84 (diff)
parente41a2bc6b87397ef0aeda4132a8227d164cd592b (diff)
Merge branch 'master' of https://source.denx.de/u-boot/custodians/u-boot-spi into next
- SPI NOT OF partitions (Marek BehĂșn) - Macronic SPI NAND (Jaime Liao) - Macronix MX66UW2G345G SPI NOR (zhengxun)
Diffstat (limited to 'drivers')
-rw-r--r--drivers/core/ofnode.c44
-rw-r--r--drivers/mtd/mtd-uclass.c15
-rw-r--r--drivers/mtd/mtd_uboot.c129
-rw-r--r--drivers/mtd/mtdcore.c35
-rw-r--r--drivers/mtd/mtdpart.c63
-rw-r--r--drivers/mtd/nand/spi/macronix.c46
-rw-r--r--drivers/mtd/spi/sf_internal.h4
-rw-r--r--drivers/mtd/spi/sf_mtd.c19
-rw-r--r--drivers/mtd/spi/sf_probe.c6
-rw-r--r--drivers/mtd/spi/spi-nor-core.c1
-rw-r--r--drivers/mtd/spi/spi-nor-ids.c1
-rw-r--r--drivers/mtd/spi/spi-nor-tiny.c1
12 files changed, 291 insertions, 73 deletions
diff --git a/drivers/core/ofnode.c b/drivers/core/ofnode.c
index 6c771e364fb..eeeccfb4467 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 9f5f672ba3f..4ab84de5531 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 c53ec657a34..90767ec417a 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 0d1f94c6cba..582129d0df1 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 d064ac30480..aa58f722dad 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 215f09acc37..f4a8e816398 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 786301ba4a9..0b63e1bfc27 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 987fac2501f..04de8680809 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 3befbe91cac..7edb8759fdc 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 a6625535a70..6af9c675a4f 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 2b57797954c..8d2b73b6764 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 1d5861d55cd..b0aa97d3244 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;