/* #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>
* 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;
#define CONFIG_SYS_FLASH_CFI_WIDTH FLASH_CFI_8BIT
#endif
+#ifdef CONFIG_CFI_FLASH_USE_WEAK_ACCESSORS
+#define __maybe_weak __weak
+#else
+#define __maybe_weak static
+#endif
+
/*
* 0xffff is an undefined value for the configuration register. When
* this value is returned, the configuration register shall not be
int cfi_flash_num_flash_banks = CONFIG_SYS_MAX_FLASH_BANKS_DETECT;
#endif
-static phys_addr_t __cfi_flash_bank_addr(int i)
+#ifdef CONFIG_CFI_FLASH /* for driver model */
+static void cfi_flash_init_dm(void)
{
- return ((phys_addr_t [])CONFIG_SYS_FLASH_BANKS_LIST)[i];
+ 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)
- __attribute__((weak, alias("__cfi_flash_bank_addr")));
+{
+ 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
-static unsigned long __cfi_flash_bank_size(int i)
+__weak unsigned long cfi_flash_bank_size(int i)
{
#ifdef CONFIG_SYS_FLASH_BANKS_SIZES
return ((unsigned long [])CONFIG_SYS_FLASH_BANKS_SIZES)[i];
return 0;
#endif
}
-unsigned long cfi_flash_bank_size(int i)
- __attribute__((weak, alias("__cfi_flash_bank_size")));
-static void __flash_write8(u8 value, void *addr)
+__maybe_weak void flash_write8(u8 value, void *addr)
{
__raw_writeb(value, addr);
}
-static void __flash_write16(u16 value, void *addr)
+__maybe_weak void flash_write16(u16 value, void *addr)
{
__raw_writew(value, addr);
}
-static void __flash_write32(u32 value, void *addr)
+__maybe_weak void flash_write32(u32 value, void *addr)
{
__raw_writel(value, addr);
}
-static void __flash_write64(u64 value, void *addr)
+__maybe_weak void flash_write64(u64 value, void *addr)
{
/* No architectures currently implement __raw_writeq() */
*(volatile u64 *)addr = value;
}
-static u8 __flash_read8(void *addr)
+__maybe_weak u8 flash_read8(void *addr)
{
return __raw_readb(addr);
}
-static u16 __flash_read16(void *addr)
+__maybe_weak u16 flash_read16(void *addr)
{
return __raw_readw(addr);
}
-static u32 __flash_read32(void *addr)
+__maybe_weak u32 flash_read32(void *addr)
{
return __raw_readl(addr);
}
-static u64 __flash_read64(void *addr)
+__maybe_weak u64 flash_read64(void *addr)
{
/* No architectures currently implement __raw_readq() */
return *(volatile u64 *)addr;
}
-#ifdef CONFIG_CFI_FLASH_USE_WEAK_ACCESSORS
-void flash_write8(u8 value, void *addr)__attribute__((weak, alias("__flash_write8")));
-void flash_write16(u16 value, void *addr)__attribute__((weak, alias("__flash_write16")));
-void flash_write32(u32 value, void *addr)__attribute__((weak, alias("__flash_write32")));
-void flash_write64(u64 value, void *addr)__attribute__((weak, alias("__flash_write64")));
-u8 flash_read8(void *addr)__attribute__((weak, alias("__flash_read8")));
-u16 flash_read16(void *addr)__attribute__((weak, alias("__flash_read16")));
-u32 flash_read32(void *addr)__attribute__((weak, alias("__flash_read32")));
-u64 flash_read64(void *addr)__attribute__((weak, alias("__flash_read64")));
-#else
-#define flash_write8 __flash_write8
-#define flash_write16 __flash_write16
-#define flash_write32 __flash_write32
-#define flash_write64 __flash_write64
-#define flash_read8 __flash_read8
-#define flash_read16 __flash_read16
-#define flash_read32 __flash_read32
-#define flash_read64 __flash_read64
-#endif
-
/*-----------------------------------------------------------------------
*/
#if defined(CONFIG_ENV_IS_IN_FLASH) || defined(CONFIG_ENV_ADDR_REDUND) || (CONFIG_SYS_MONITOR_BASE >= CONFIG_SYS_FLASH_BASE)
switch (info->portwidth) {
case FLASH_CFI_8BIT:
debug ("fwc addr %p cmd %x %x 8bit x %d bit\n", addr, cmd,
- cword.c, info->chipwidth << CFI_FLASH_SHIFT_WIDTH);
- flash_write8(cword.c, addr);
+ cword.w8, info->chipwidth << CFI_FLASH_SHIFT_WIDTH);
+ flash_write8(cword.w8, addr);
break;
case FLASH_CFI_16BIT:
debug ("fwc addr %p cmd %x %4.4x 16bit x %d bit\n", addr,
- cmd, cword.w,
+ cmd, cword.w16,
info->chipwidth << CFI_FLASH_SHIFT_WIDTH);
- flash_write16(cword.w, addr);
+ flash_write16(cword.w16, addr);
break;
case FLASH_CFI_32BIT:
- debug ("fwc addr %p cmd %x %8.8lx 32bit x %d bit\n", addr,
- cmd, cword.l,
+ debug ("fwc addr %p cmd %x %8.8x 32bit x %d bit\n", addr,
+ cmd, cword.w32,
info->chipwidth << CFI_FLASH_SHIFT_WIDTH);
- flash_write32(cword.l, addr);
+ flash_write32(cword.w32, addr);
break;
case FLASH_CFI_64BIT:
#ifdef DEBUG
{
char str[20];
- print_longlong (str, cword.ll);
+ print_longlong (str, cword.w64);
debug ("fwrite addr %p cmd %x %s 64 bit x %d bit\n",
addr, cmd, str,
info->chipwidth << CFI_FLASH_SHIFT_WIDTH);
}
#endif
- flash_write64(cword.ll, addr);
+ flash_write64(cword.w64, addr);
break;
}
debug ("is= cmd %x(%c) addr %p ", cmd, cmd, addr);
switch (info->portwidth) {
case FLASH_CFI_8BIT:
- debug ("is= %x %x\n", flash_read8(addr), cword.c);
- retval = (flash_read8(addr) == cword.c);
+ debug ("is= %x %x\n", flash_read8(addr), cword.w8);
+ retval = (flash_read8(addr) == cword.w8);
break;
case FLASH_CFI_16BIT:
- debug ("is= %4.4x %4.4x\n", flash_read16(addr), cword.w);
- retval = (flash_read16(addr) == cword.w);
+ debug ("is= %4.4x %4.4x\n", flash_read16(addr), cword.w16);
+ retval = (flash_read16(addr) == cword.w16);
break;
case FLASH_CFI_32BIT:
- debug ("is= %8.8x %8.8lx\n", flash_read32(addr), cword.l);
- retval = (flash_read32(addr) == cword.l);
+ debug ("is= %8.8x %8.8x\n", flash_read32(addr), cword.w32);
+ retval = (flash_read32(addr) == cword.w32);
break;
case FLASH_CFI_64BIT:
#ifdef DEBUG
char str2[20];
print_longlong (str1, flash_read64(addr));
- print_longlong (str2, cword.ll);
+ print_longlong (str2, cword.w64);
debug ("is= %s %s\n", str1, str2);
}
#endif
- retval = (flash_read64(addr) == cword.ll);
+ retval = (flash_read64(addr) == cword.w64);
break;
default:
retval = 0;
flash_make_cmd (info, cmd, &cword);
switch (info->portwidth) {
case FLASH_CFI_8BIT:
- retval = ((flash_read8(addr) & cword.c) == cword.c);
+ retval = ((flash_read8(addr) & cword.w8) == cword.w8);
break;
case FLASH_CFI_16BIT:
- retval = ((flash_read16(addr) & cword.w) == cword.w);
+ retval = ((flash_read16(addr) & cword.w16) == cword.w16);
break;
case FLASH_CFI_32BIT:
- retval = ((flash_read32(addr) & cword.l) == cword.l);
+ retval = ((flash_read32(addr) & cword.w32) == cword.w32);
break;
case FLASH_CFI_64BIT:
- retval = ((flash_read64(addr) & cword.ll) == cword.ll);
+ retval = ((flash_read64(addr) & cword.w64) == cword.w64);
break;
default:
retval = 0;
case CFI_CMDSET_INTEL_PROG_REGIONS:
case CFI_CMDSET_INTEL_EXTENDED:
case CFI_CMDSET_INTEL_STANDARD:
- if ((retcode != ERR_OK)
+ if ((retcode == ERR_OK)
&& !flash_isequal (info, sector, 0, FLASH_STATUS_DONE)) {
retcode = ERR_INVAL;
printf ("Flash %s error at address %lx\n", prompt,
switch (info->portwidth) {
case FLASH_CFI_8BIT:
- cword->c = c;
+ cword->w8 = c;
break;
case FLASH_CFI_16BIT:
#if defined(__LITTLE_ENDIAN) && !defined(CONFIG_SYS_WRITE_SWAPPED_DATA)
w = c;
w <<= 8;
- cword->w = (cword->w >> 8) | w;
+ cword->w16 = (cword->w16 >> 8) | w;
#else
- cword->w = (cword->w << 8) | c;
+ cword->w16 = (cword->w16 << 8) | c;
#endif
break;
case FLASH_CFI_32BIT:
#if defined(__LITTLE_ENDIAN) && !defined(CONFIG_SYS_WRITE_SWAPPED_DATA)
l = c;
l <<= 24;
- cword->l = (cword->l >> 8) | l;
+ cword->w32 = (cword->w32 >> 8) | l;
#else
- cword->l = (cword->l << 8) | c;
+ cword->w32 = (cword->w32 << 8) | c;
#endif
break;
case FLASH_CFI_64BIT:
#if defined(__LITTLE_ENDIAN) && !defined(CONFIG_SYS_WRITE_SWAPPED_DATA)
ll = c;
ll <<= 56;
- cword->ll = (cword->ll >> 8) | ll;
+ cword->w64 = (cword->w64 >> 8) | ll;
#else
- cword->ll = (cword->ll << 8) | c;
+ cword->w64 = (cword->w64 << 8) | c;
#endif
break;
}
/* Check if Flash is (sufficiently) erased */
switch (info->portwidth) {
case FLASH_CFI_8BIT:
- flag = ((flash_read8(dstaddr) & cword.c) == cword.c);
+ flag = ((flash_read8(dstaddr) & cword.w8) == cword.w8);
break;
case FLASH_CFI_16BIT:
- flag = ((flash_read16(dstaddr) & cword.w) == cword.w);
+ flag = ((flash_read16(dstaddr) & cword.w16) == cword.w16);
break;
case FLASH_CFI_32BIT:
- flag = ((flash_read32(dstaddr) & cword.l) == cword.l);
+ flag = ((flash_read32(dstaddr) & cword.w32) == cword.w32);
break;
case FLASH_CFI_64BIT:
- flag = ((flash_read64(dstaddr) & cword.ll) == cword.ll);
+ flag = ((flash_read64(dstaddr) & cword.w64) == cword.w64);
break;
default:
flag = 0;
switch (info->portwidth) {
case FLASH_CFI_8BIT:
- flash_write8(cword.c, dstaddr);
+ flash_write8(cword.w8, dstaddr);
break;
case FLASH_CFI_16BIT:
- flash_write16(cword.w, dstaddr);
+ flash_write16(cword.w16, dstaddr);
break;
case FLASH_CFI_32BIT:
- flash_write32(cword.l, dstaddr);
+ flash_write32(cword.w32, dstaddr);
break;
case FLASH_CFI_64BIT:
- flash_write64(cword.ll, dstaddr);
+ flash_write64(cword.w64, dstaddr);
break;
}
if (use_flash_status_poll(info)) {
cfiword_t cword;
void *dest;
- cword.ll = 0xffffffffffffffffULL;
+ cword.w64 = 0xffffffffffffffffULL;
dest = flash_map(info, sect, 0);
st = flash_status_poll(info, &cword, dest,
info->erase_blk_tout, "erase");
/* handle unaligned start */
if ((aln = addr - wp) != 0) {
- cword.l = 0;
+ cword.w32 = 0;
p = (uchar *)wp;
for (i = 0; i < aln; ++i)
flash_add_byte (info, &cword, flash_read8(p + i));
while (cnt >= info->portwidth) {
/* prohibit buffer write when buffer_size is 1 */
if (info->buffer_size == 1) {
- cword.l = 0;
+ cword.w32 = 0;
for (i = 0; i < info->portwidth; i++)
flash_add_byte (info, &cword, *src++);
if ((rc = flash_write_cfiword (info, wp, cword)) != 0)
}
#else
while (cnt >= info->portwidth) {
- cword.l = 0;
+ cword.w32 = 0;
for (i = 0; i < info->portwidth; i++) {
flash_add_byte (info, &cword, *src++);
}
/*
* handle unaligned tail bytes
*/
- cword.l = 0;
+ cword.w32 = 0;
p = (uchar *)wp;
for (i = 0; (i < info->portwidth) && (cnt > 0); ++i) {
flash_add_byte (info, &cword, *src++);
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;
#endif /* CONFIG_SYS_FLASH_QUIET_TEST */
}
#ifdef CONFIG_SYS_FLASH_PROTECTION
- else if ((s != NULL) && (strcmp(s, "yes") == 0)) {
+ else if (strcmp(s, "yes") == 0) {
/*
* Only the U-Boot image and it's environment
* is protected, all other sectors are
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 */