summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorThomas Chou <thomas@wytron.com.tw>2015-11-07 14:31:08 +0800
committerThomas Chou <thomas@wytron.com.tw>2015-11-12 08:26:58 +0800
commitf1056910434d87051ff8af80a84e248dd1670abb (patch)
treebf6a6407ffb49e7bc01aa9f1d75cea3961991526 /drivers
parentd85879938d3fc3557f6ff74a60f95e0975a314ce (diff)
downloadu-boot-f1056910434d87051ff8af80a84e248dd1670abb.tar.gz
u-boot-f1056910434d87051ff8af80a84e248dd1670abb.tar.bz2
u-boot-f1056910434d87051ff8af80a84e248dd1670abb.zip
cfi_flash: convert to driver model
Convert cfi flash to driver model. Signed-off-by: Thomas Chou <thomas@wytron.com.tw> Reviewed-by: Simon Glass <sjg@chromium.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/mtd/Kconfig11
-rw-r--r--drivers/mtd/cfi_flash.c78
2 files changed, 89 insertions, 0 deletions
diff --git a/drivers/mtd/Kconfig b/drivers/mtd/Kconfig
index 23dff48f08..57e4b867bc 100644
--- a/drivers/mtd/Kconfig
+++ b/drivers/mtd/Kconfig
@@ -8,6 +8,17 @@ config MTD
flash, RAM and similar chips, often used for solid state file
systems on embedded devices.
+config CFI_FLASH
+ bool "Enable Driver Model for CFI Flash driver"
+ depends on MTD
+ help
+ The Common Flash Interface specification was developed by Intel,
+ AMD and other flash manufactures. It provides a universal method
+ for probing the capabilities of flash devices. If you wish to
+ support any device that is CFI-compliant, you need to enable this
+ option. Visit <http://www.amd.com/products/nvd/overview/cfi.html>
+ for more information on CFI.
+
endmenu
source "drivers/mtd/nand/Kconfig"
diff --git a/drivers/mtd/cfi_flash.c b/drivers/mtd/cfi_flash.c
index fc7a878d59..e3cb59887c 100644
--- a/drivers/mtd/cfi_flash.c
+++ b/drivers/mtd/cfi_flash.c
@@ -18,6 +18,9 @@
/* #define DEBUG */
#include <common.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 +50,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 +92,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 +2353,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 +2433,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 */