Add qemu 2.4.0
[kvmfornfv.git] / qemu / roms / u-boot / board / scb9328 / flash.c
diff --git a/qemu/roms/u-boot/board/scb9328/flash.c b/qemu/roms/u-boot/board/scb9328/flash.c
new file mode 100644 (file)
index 0000000..e3a582f
--- /dev/null
@@ -0,0 +1,308 @@
+/*
+ * Copyright (C) 2003 ETC s.r.o.
+ *
+ * This code was inspired by Marius Groeger and Kyle Harris code
+ * available in other board ports for U-Boot
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ *
+ * Written by Peter Figuli <peposh@etc.sk>, 2003.
+ */
+
+#include <common.h>
+#include "intel.h"
+
+
+/*
+ * This code should handle CFI FLASH memory device. This code is very
+ * minimalistic approach without many essential error handling code as well.
+ * Because U-Boot actually is missing smart handling of FLASH device,
+ * we just set flash_id to anything else to FLASH_UNKNOW, so common code
+ * can call us without any restrictions.
+ * TODO: Add CFI Query, to be able to determine FLASH device.
+ * TODO: Add error handling code
+ * NOTE: This code was tested with BUS_WIDTH 4 and ITERLEAVE 2 only, but
+ *       hopefully may work with other configurations.
+ */
+
+#if ( SCB9328_FLASH_BUS_WIDTH == 1 )
+#  define FLASH_BUS vu_char
+#  define FLASH_BUS_RET u_char
+#  if ( SCB9328_FLASH_INTERLEAVE == 1 )
+#    define FLASH_CMD( x ) x
+#  else
+#    error "With 8bit bus only one chip is allowed"
+#  endif
+
+
+#elif ( SCB9328_FLASH_BUS_WIDTH == 2 )
+#  define FLASH_BUS vu_short
+#  define FLASH_BUS_RET u_short
+#  if ( SCB9328_FLASH_INTERLEAVE == 1 )
+#    define FLASH_CMD( x ) x
+#  elif ( SCB9328_FLASH_INTERLEAVE == 2 )
+#    define FLASH_CMD( x ) (( x << 8 )| x )
+#  else
+#    error "With 16bit bus only 1 or 2 chip(s) are allowed"
+#  endif
+
+
+#elif ( SCB9328_FLASH_BUS_WIDTH == 4 )
+#  define FLASH_BUS vu_long
+#  define FLASH_BUS_RET u_long
+#  if ( SCB9328_FLASH_INTERLEAVE == 1 )
+#    define FLASH_CMD( x ) x
+#  elif ( SCB9328_FLASH_INTERLEAVE == 2 )
+#    define FLASH_CMD( x ) (( x << 16 )| x )
+#  elif ( SCB9328_FLASH_INTERLEAVE == 4 )
+#    define FLASH_CMD( x ) (( x << 24 )|( x << 16 ) ( x << 8 )| x )
+#  else
+#    error "With 32bit bus only 1,2 or 4 chip(s) are allowed"
+#  endif
+
+#else
+#  error "Flash bus width might be 1,2,4 for 8,16,32 bit configuration"
+#endif
+
+
+flash_info_t flash_info[CONFIG_SYS_MAX_FLASH_BANKS];
+
+static FLASH_BUS_RET flash_status_reg (void)
+{
+
+       FLASH_BUS *addr = (FLASH_BUS *) 0;
+
+       *addr = FLASH_CMD (CFI_INTEL_CMD_READ_STATUS_REGISTER);
+
+       return *addr;
+}
+
+static int flash_ready (ulong timeout)
+{
+       int ok = 1;
+       ulong start;
+
+       start = get_timer(0);
+       while ((flash_status_reg () & FLASH_CMD (CFI_INTEL_SR_READY)) !=
+                  FLASH_CMD (CFI_INTEL_SR_READY)) {
+               if (get_timer(start) > timeout && timeout != 0) {
+                       ok = 0;
+                       break;
+               }
+       }
+       return ok;
+}
+
+#if ( CONFIG_SYS_MAX_FLASH_BANKS != 1 )
+#  error "SCB9328 platform has only one flash bank!"
+#endif
+
+
+ulong flash_init (void)
+{
+       int i;
+       unsigned long address = SCB9328_FLASH_BASE;
+
+       flash_info[0].size = SCB9328_FLASH_BANK_SIZE;
+       flash_info[0].sector_count = CONFIG_SYS_MAX_FLASH_SECT;
+       flash_info[0].flash_id = INTEL_MANUFACT;
+       memset (flash_info[0].protect, 0, CONFIG_SYS_MAX_FLASH_SECT);
+
+       for (i = 0; i < CONFIG_SYS_MAX_FLASH_SECT; i++) {
+               flash_info[0].start[i] = address;
+#ifdef SCB9328_FLASH_UNLOCK
+               /* Some devices are hw locked after start. */
+               *((FLASH_BUS *) address) = FLASH_CMD (CFI_INTEL_CMD_LOCK_SETUP);
+               *((FLASH_BUS *) address) = FLASH_CMD (CFI_INTEL_CMD_UNLOCK_BLOCK);
+               flash_ready (0);
+               *((FLASH_BUS *) address) = FLASH_CMD (CFI_INTEL_CMD_READ_ARRAY);
+#endif
+               address += SCB9328_FLASH_SECT_SIZE;
+       }
+
+       flash_protect (FLAG_PROTECT_SET,
+                                  CONFIG_SYS_FLASH_BASE,
+                                  CONFIG_SYS_FLASH_BASE + monitor_flash_len - 1,
+                                  &flash_info[0]);
+
+       flash_protect (FLAG_PROTECT_SET,
+                                  CONFIG_ENV_ADDR,
+                                  CONFIG_ENV_ADDR + CONFIG_ENV_SIZE - 1, &flash_info[0]);
+
+       return SCB9328_FLASH_BANK_SIZE;
+}
+
+void flash_print_info (flash_info_t * info)
+{
+       int i;
+
+       printf (" Intel vendor\n");
+       printf ("  Size: %ld MB in %d Sectors\n",
+                       info->size >> 20, info->sector_count);
+
+       printf ("  Sector Start Addresses:");
+       for (i = 0; i < info->sector_count; i++) {
+               if (!(i % 5)) {
+                       printf ("\n");
+               }
+
+               printf (" %08lX%s", info->start[i],
+                               info->protect[i] ? " (RO)" : "     ");
+       }
+       printf ("\n");
+}
+
+
+int flash_erase (flash_info_t * info, int s_first, int s_last)
+{
+       int flag, non_protected = 0, sector;
+       int rc = ERR_OK;
+
+       FLASH_BUS *address;
+
+       for (sector = s_first; sector <= s_last; sector++) {
+               if (!info->protect[sector]) {
+                       non_protected++;
+               }
+       }
+
+       if (!non_protected) {
+               return ERR_PROTECTED;
+       }
+
+       /*
+        * Disable interrupts which might cause a timeout
+        * here. Remember that our exception vectors are
+        * at address 0 in the flash, and we don't want a
+        * (ticker) exception to happen while the flash
+        * chip is in programming mode.
+        */
+       flag = disable_interrupts ();
+
+
+       /* Start erase on unprotected sectors */
+       for (sector = s_first; sector <= s_last && !ctrlc (); sector++) {
+               if (info->protect[sector]) {
+                       printf ("Protected sector %2d skipping...\n", sector);
+                       continue;
+               } else {
+                       printf ("Erasing sector %2d ... ", sector);
+               }
+
+               address = (FLASH_BUS *) (info->start[sector]);
+
+               *address = FLASH_CMD (CFI_INTEL_CMD_BLOCK_ERASE);
+               *address = FLASH_CMD (CFI_INTEL_CMD_CONFIRM);
+               if (flash_ready (CONFIG_SYS_FLASH_ERASE_TOUT)) {
+                       *address = FLASH_CMD (CFI_INTEL_CMD_CLEAR_STATUS_REGISTER);
+                       printf ("ok.\n");
+               } else {
+                       *address = FLASH_CMD (CFI_INTEL_CMD_SUSPEND);
+                       rc = ERR_TIMOUT;
+                       printf ("timeout! Aborting...\n");
+                       break;
+               }
+               *address = FLASH_CMD (CFI_INTEL_CMD_READ_ARRAY);
+       }
+       if (ctrlc ())
+               printf ("User Interrupt!\n");
+
+       /* allow flash to settle - wait 10 ms */
+       udelay_masked (10000);
+       if (flag) {
+               enable_interrupts ();
+       }
+
+       return rc;
+}
+
+static int write_data (flash_info_t * info, ulong dest, FLASH_BUS data)
+{
+       FLASH_BUS *address = (FLASH_BUS *) dest;
+       int rc = ERR_OK;
+       int flag;
+
+       /* Check if Flash is (sufficiently) erased */
+       if ((*address & data) != data) {
+               return ERR_NOT_ERASED;
+       }
+
+       /*
+        * Disable interrupts which might cause a timeout
+        * here. Remember that our exception vectors are
+        * at address 0 in the flash, and we don't want a
+        * (ticker) exception to happen while the flash
+        * chip is in programming mode.
+        */
+
+       flag = disable_interrupts ();
+
+       *address = FLASH_CMD (CFI_INTEL_CMD_CLEAR_STATUS_REGISTER);
+       *address = FLASH_CMD (CFI_INTEL_CMD_PROGRAM1);
+       *address = data;
+
+       if (!flash_ready (CONFIG_SYS_FLASH_WRITE_TOUT)) {
+               *address = FLASH_CMD (CFI_INTEL_CMD_SUSPEND);
+               rc = ERR_TIMOUT;
+               printf ("timeout! Aborting...\n");
+       }
+
+       *address = FLASH_CMD (CFI_INTEL_CMD_READ_ARRAY);
+       if (flag) {
+               enable_interrupts ();
+       }
+
+       return rc;
+}
+
+int write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt)
+{
+       ulong read_addr, write_addr;
+       FLASH_BUS data;
+       int i, result = ERR_OK;
+
+
+       read_addr = addr & ~(sizeof (FLASH_BUS) - 1);
+       write_addr = read_addr;
+       if (read_addr != addr) {
+               data = 0;
+               for (i = 0; i < sizeof (FLASH_BUS); i++) {
+                       if (read_addr < addr || cnt == 0) {
+                               data |= *((uchar *) read_addr) << i * 8;
+                       } else {
+                               data |= (*src++) << i * 8;
+                               cnt--;
+                       }
+                       read_addr++;
+               }
+               if ((result = write_data (info, write_addr, data)) != ERR_OK) {
+                       return result;
+               }
+               write_addr += sizeof (FLASH_BUS);
+       }
+       for (; cnt >= sizeof (FLASH_BUS); cnt -= sizeof (FLASH_BUS)) {
+               if ((result = write_data (info, write_addr,
+                                                                 *((FLASH_BUS *) src))) != ERR_OK) {
+                       return result;
+               }
+               write_addr += sizeof (FLASH_BUS);
+               src += sizeof (FLASH_BUS);
+       }
+       if (cnt > 0) {
+               read_addr = write_addr;
+               data = 0;
+               for (i = 0; i < sizeof (FLASH_BUS); i++) {
+                       if (cnt > 0) {
+                               data |= (*src++) << i * 8;
+                               cnt--;
+                       } else {
+                               data |= *((uchar *) read_addr) << i * 8;
+                       }
+                       read_addr++;
+               }
+               if ((result = write_data (info, write_addr, data)) != 0) {
+                       return result;
+               }
+       }
+       return ERR_OK;
+}