]> git.sur5r.net Git - u-boot/blobdiff - drivers/mtd/cfi_flash.c
Merge git://git.denx.de/u-boot-usb
[u-boot] / drivers / mtd / cfi_flash.c
index fc7a878d595c564d01b8214ea3236675aadf7655..39932f46478eff7253720538443cc1279884a3af 100644 (file)
 /* #define DEBUG       */
 
 #include <common.h>
+#include <console.h>
+#include <dm.h>
+#include <errno.h>
+#include <fdt_support.h>
 #include <asm/processor.h>
 #include <asm/io.h>
 #include <asm/byteorder.h>
@@ -47,6 +51,8 @@
  * reading and writing ... (yes there is such a Hardware).
  */
 
+DECLARE_GLOBAL_DATA_PTR;
+
 static uint flash_offset_cfi[2] = { FLASH_OFFSET_CFI, FLASH_OFFSET_CFI_ALT };
 #ifdef CONFIG_FLASH_CFI_MTD
 static uint flash_verbose = 1;
@@ -87,10 +93,36 @@ static u16 cfi_flash_config_reg(int i)
 int cfi_flash_num_flash_banks = CONFIG_SYS_MAX_FLASH_BANKS_DETECT;
 #endif
 
+#ifdef CONFIG_CFI_FLASH /* for driver model */
+static void cfi_flash_init_dm(void)
+{
+       struct udevice *dev;
+
+       cfi_flash_num_flash_banks = 0;
+       /*
+        * The uclass_first_device() will probe the first device and
+        * uclass_next_device() will probe the rest if they exist. So
+        * that cfi_flash_probe() will get called assigning the base
+        * addresses that are available.
+        */
+       for (uclass_first_device(UCLASS_MTD, &dev);
+            dev;
+            uclass_next_device(&dev)) {
+       }
+}
+
+static phys_addr_t cfi_flash_base[CFI_MAX_FLASH_BANKS];
+
+phys_addr_t cfi_flash_bank_addr(int i)
+{
+       return cfi_flash_base[i];
+}
+#else
 __weak phys_addr_t cfi_flash_bank_addr(int i)
 {
        return ((phys_addr_t [])CONFIG_SYS_FLASH_BANKS_LIST)[i];
 }
+#endif
 
 __weak unsigned long cfi_flash_bank_size(int i)
 {
@@ -2322,6 +2354,10 @@ unsigned long flash_init (void)
        getenv_f("unlock", s, sizeof(s));
 #endif
 
+#ifdef CONFIG_CFI_FLASH /* for driver model */
+       cfi_flash_init_dm();
+#endif
+
        /* Init: no FLASHes known */
        for (i = 0; i < CONFIG_SYS_MAX_FLASH_BANKS; ++i) {
                flash_info[i].flash_id = FLASH_UNKNOWN;
@@ -2398,3 +2434,46 @@ unsigned long flash_init (void)
 
        return (size);
 }
+
+#ifdef CONFIG_CFI_FLASH /* for driver model */
+static int cfi_flash_probe(struct udevice *dev)
+{
+       void *blob = (void *)gd->fdt_blob;
+       int node = dev->of_offset;
+       const fdt32_t *cell;
+       phys_addr_t addr;
+       int parent, addrc, sizec;
+       int len, idx;
+
+       parent = fdt_parent_offset(blob, node);
+       of_bus_default_count_cells(blob, parent, &addrc, &sizec);
+       /* decode regs, there may be multiple reg tuples. */
+       cell = fdt_getprop(blob, node, "reg", &len);
+       if (!cell)
+               return -ENOENT;
+       idx = 0;
+       len /= sizeof(fdt32_t);
+       while (idx < len) {
+               addr = fdt_translate_address((void *)blob,
+                                            node, cell + idx);
+               cfi_flash_base[cfi_flash_num_flash_banks++] = addr;
+               idx += addrc + sizec;
+       }
+       gd->bd->bi_flashstart = cfi_flash_base[0];
+
+       return 0;
+}
+
+static const struct udevice_id cfi_flash_ids[] = {
+       { .compatible = "cfi-flash" },
+       { .compatible = "jedec-flash" },
+       {}
+};
+
+U_BOOT_DRIVER(cfi_flash) = {
+       .name   = "cfi_flash",
+       .id     = UCLASS_MTD,
+       .of_match = cfi_flash_ids,
+       .probe = cfi_flash_probe,
+};
+#endif /* CONFIG_CFI_FLASH */