nor: add get_flash_bank_by_name autoprobe
[fw/openocd] / src / flash / nor / core.c
index 232d503714fb8ffb38c5dbe28279a9132584c684..1bd09b444d9c392d08f6f097937039c9660e8d43 100644 (file)
@@ -3,6 +3,7 @@
  *   Copyright (C) 2007-2010 Ã˜yvind Harboe <oyvind.harboe@zylin.com>       *
  *   Copyright (C) 2008 by Spencer Oliver <spen@spen-soft.co.uk>           *
  *   Copyright (C) 2009 Zachary T Welch <zw@superlucidity.net>             *
+ *   Copyright (C) 2010 by Antonio Borneo <borneo.antonio@gmail.com>       *
  *                                                                         *
  *   This program is free software; you can redistribute it and/or modify  *
  *   it under the terms of the GNU General Public License as published by  *
@@ -54,74 +55,27 @@ int flash_driver_erase(struct flash_bank *bank, int first, int last)
 int flash_driver_protect(struct flash_bank *bank, int set, int first, int last)
 {
        int retval;
-       bool updated = false;
-
-       /* NOTE: "first == last" means (un?)protect just that sector.
-        code including Lower level ddrivers may rely on this "first <= last"
-        * invariant.
-       */
 
        /* callers may not supply illegal parameters ... */
        if (first < 0 || first > last || last >= bank->num_sectors)
+       {
+               LOG_ERROR("illegal sector range");
                return ERROR_FAIL;
+       }
 
        /* force "set" to 0/1 */
        set = !!set;
 
-       /*
-        * Filter out what trivial nonsense we can, so drivers don't have to.
+       /* DANGER!
         *
-        * Don't tell drivers to change to the current state...  it's needless,
-        * and reducing the amount of work to be done (potentially to nothing)
-        * speeds at least some things up.
-        */
-scan:
-       for (int i = first; i <= last; i++) {
-               struct flash_sector *sector = bank->sectors + i;
-
-               /* Only filter requests to protect the already-protected, or
-                * to unprotect the already-unprotected.  Changing from the
-                * unknown state (-1) to a known one is unwise but allowed;
-                * protection status is best checked first.
-                */
-               if (sector->is_protected != set)
-                       continue;
-
-               /* Shrink this range of sectors from the start; don't overrun
-                * the end.  Also shrink from the end; don't overun the start.
-                *
-                * REVISIT we could handle discontiguous regions by issuing
-                * more than one driver request.  How much would that matter?
-                */
-               if (i == first && i != last) {
-                       updated = true;
-                       first++;
-               } else if (i == last && i != first) {
-                       updated = true;
-                       last--;
-               }
-       }
-
-       /* updating the range affects the tests in the scan loop above; so
-        * re-scan, to make sure we didn't miss anything.
-        */
-       if (updated) {
-               updated = false;
-               goto scan;
-       }
-
-       /* Single sector, already protected?  Nothing to do!
-        * We may have trimmed our parameters into this degenerate case.
+        * We must not use any cached information about protection state!!!!
         *
-        * FIXME repeating the "is_protected==set" test is a giveaway that
-        * this fast-exit belongs earlier, in the trim-it-down loop; mve.
-        * */
-       if (first == last && bank->sectors[first].is_protected == set)
-               return ERROR_OK;
-
-
-       /* Note that we don't pass illegal parameters to drivers; any
-        * trimming just turns one valid range into another one.
+        * There are a million things that could change the protect state:
+        *
+        * the target could have reset, power cycled, been hot plugged,
+        * the application could have run, etc.
+        *
+        * Drivers only receive valid sector range.
         */
        retval = bank->driver->protect(bank, set, first, last);
        if (retval != ERROR_OK)
@@ -147,6 +101,29 @@ int flash_driver_write(struct flash_bank *bank,
        return retval;
 }
 
+int flash_driver_read(struct flash_bank *bank,
+               uint8_t *buffer, uint32_t offset, uint32_t count)
+{
+       int retval;
+
+       LOG_DEBUG("call flash_driver_read()");
+
+       retval = bank->driver->read(bank, buffer, offset, count);
+       if (retval != ERROR_OK)
+       {
+               LOG_ERROR("error reading to flash at address 0x%08" PRIx32 " at offset 0x%8.8" PRIx32 " (%d)",
+                         bank->base, offset, retval);
+       }
+
+       return retval;
+}
+
+int default_flash_read(struct flash_bank *bank,
+               uint8_t *buffer, uint32_t offset, uint32_t count)
+{
+       return target_read_buffer(bank->target, offset + bank->base, count, buffer);
+}
+
 void flash_bank_add(struct flash_bank *bank)
 {
        /* put flash bank in linked list */
@@ -201,7 +178,7 @@ int flash_get_bank_count(void)
        return i;
 }
 
-struct flash_bank *get_flash_bank_by_name(const char *name)
+struct flash_bank *get_flash_bank_by_name_noprobe(const char *name)
 {
        unsigned requested = get_flash_name_index(name);
        unsigned found = 0;
@@ -220,6 +197,26 @@ struct flash_bank *get_flash_bank_by_name(const char *name)
        return NULL;
 }
 
+struct flash_bank *get_flash_bank_by_name(const char *name)
+{
+       struct flash_bank *bank;
+       int retval;
+
+       bank = get_flash_bank_by_name_noprobe(name);
+       if (bank != NULL)
+       {
+               retval = bank->driver->auto_probe(bank);
+
+               if (retval != ERROR_OK)
+               {
+                       LOG_ERROR("auto_probe failed %d\n", retval);
+                       return NULL;
+               }
+       }
+
+       return bank;
+}
+
 int get_flash_bank_by_num(int num, struct flash_bank **bank)
 {
        struct flash_bank *p = get_flash_bank_by_num_noprobe(num);
@@ -502,7 +499,7 @@ static int flash_driver_unprotect(struct flash_bank *bank, int first, int last)
        return flash_driver_protect(bank, 0, first, last);
 }
 
-static int flash_unlock_address_range(struct target *target, uint32_t addr, uint32_t length)
+int flash_unlock_address_range(struct target *target, uint32_t addr, uint32_t length)
 {
        /* By default, pad to sector boundaries ... the real issue here
         * is that our (only) caller *permanently* removes protection,
@@ -683,7 +680,7 @@ int flash_write_unlock(struct target *target, struct image *image,
                        intptr_t diff = (intptr_t)sections[section] - (intptr_t)image->sections;
                        int t_section_num = diff / sizeof(struct imageection);
 
-                       LOG_DEBUG("image_read_section: section = %d, t_section_num = %d, section_offset = %d, buffer_size = %d, size_read = %d", 
+                       LOG_DEBUG("image_read_section: section = %d, t_section_num = %d, section_offset = %d, buffer_size = %d, size_read = %d",
                                 (int)section,
 (int)t_section_num, (int)section_offset, (int)buffer_size, (int)size_read);
                        if ((retval = image_read_section(image, t_section_num, section_offset,
@@ -754,34 +751,3 @@ int flash_write(struct target *target, struct image *image,
 {
        return flash_write_unlock(target, image, written, erase, false);
 }
-
-/**
- * Invalidates cached flash state which a target can change as it runs.
- *
- * @param target The target being resumed
- *
- * OpenOCD caches some flash state for brief periods.  For example, a sector
- * that is protected must be unprotected before OpenOCD tries to write it,
- * Also, a sector that's not erased must be erased before it's written.
- *
- * As a rule, OpenOCD and target firmware can both modify the flash, so when
- * a target starts running, OpenOCD needs to invalidate its cached state.
- */
-void nor_resume(struct target *target)
-{
-       struct flash_bank *bank;
-
-       for (bank = flash_banks; bank; bank = bank->next) {
-               int i;
-
-               if (bank->target != target)
-                       continue;
-
-               for (i = 0; i < bank->num_sectors; i++) {
-                       struct flash_sector *sector = bank->sectors + i;
-
-                       sector->is_erased = -1;
-                       sector->is_protected = -1;
-               }
-       }
-}