add flash/nor/drivers.c
[fw/openocd] / src / flash / flash.c
1 /***************************************************************************
2  *   Copyright (C) 2005 by Dominic Rath                                    *
3  *   Dominic.Rath@gmx.de                                                   *
4  *                                                                         *
5  *   Copyright (C) 2007,2008 Ã˜yvind Harboe                                 *
6  *   oyvind.harboe@zylin.com                                               *
7  *                                                                         *
8  *   Copyright (C) 2008 by Spencer Oliver                                  *
9  *   spen@spen-soft.co.uk                                                  *
10  *                                                                         *
11  *   This program is free software; you can redistribute it and/or modify  *
12  *   it under the terms of the GNU General Public License as published by  *
13  *   the Free Software Foundation; either version 2 of the License, or     *
14  *   (at your option) any later version.                                   *
15  *                                                                         *
16  *   This program is distributed in the hope that it will be useful,       *
17  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
18  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
19  *   GNU General Public License for more details.                          *
20  *                                                                         *
21  *   You should have received a copy of the GNU General Public License     *
22  *   along with this program; if not, write to the                         *
23  *   Free Software Foundation, Inc.,                                       *
24  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
25  ***************************************************************************/
26 #ifdef HAVE_CONFIG_H
27 #include "config.h"
28 #endif
29
30 #include "flash.h"
31 #include "common.h"
32 #include <target/image.h>
33 #include <helper/time_support.h>
34
35 struct flash_bank *flash_banks;
36
37 struct flash_bank *get_flash_bank_by_num_noprobe(int num)
38 {
39         struct flash_bank *p;
40         int i = 0;
41
42         for (p = flash_banks; p; p = p->next)
43         {
44                 if (i++ == num)
45                 {
46                         return p;
47                 }
48         }
49         LOG_ERROR("flash bank %d does not exist", num);
50         return NULL;
51 }
52
53 int flash_get_bank_count(void)
54 {
55         struct flash_bank *p;
56         int i = 0;
57         for (p = flash_banks; p; p = p->next)
58         {
59                 i++;
60         }
61         return i;
62 }
63
64 struct flash_bank *get_flash_bank_by_name(const char *name)
65 {
66         unsigned requested = get_flash_name_index(name);
67         unsigned found = 0;
68
69         struct flash_bank *bank;
70         for (bank = flash_banks; NULL != bank; bank = bank->next)
71         {
72                 if (strcmp(bank->name, name) == 0)
73                         return bank;
74                 if (!flash_driver_name_matches(bank->driver->name, name))
75                         continue;
76                 if (++found < requested)
77                         continue;
78                 return bank;
79         }
80         return NULL;
81 }
82
83 struct flash_bank *get_flash_bank_by_num(int num)
84 {
85         struct flash_bank *p = get_flash_bank_by_num_noprobe(num);
86         int retval;
87
88         if (p == NULL)
89                 return NULL;
90
91         retval = p->driver->auto_probe(p);
92
93         if (retval != ERROR_OK)
94         {
95                 LOG_ERROR("auto_probe failed %d\n", retval);
96                 return NULL;
97         }
98         return p;
99 }
100
101 /* lookup flash bank by address */
102 struct flash_bank *get_flash_bank_by_addr(struct target *target, uint32_t addr)
103 {
104         struct flash_bank *c;
105
106         /* cycle through bank list */
107         for (c = flash_banks; c; c = c->next)
108         {
109                 int retval;
110                 retval = c->driver->auto_probe(c);
111
112                 if (retval != ERROR_OK)
113                 {
114                         LOG_ERROR("auto_probe failed %d\n", retval);
115                         return NULL;
116                 }
117                 /* check whether address belongs to this flash bank */
118                 if ((addr >= c->base) && (addr <= c->base + (c->size - 1)) && target == c->target)
119                         return c;
120         }
121         LOG_ERROR("No flash at address 0x%08" PRIx32 "\n", addr);
122         return NULL;
123 }
124
125 int default_flash_mem_blank_check(struct flash_bank *bank)
126 {
127         struct target *target = bank->target;
128         const int buffer_size = 1024;
129         int i;
130         uint32_t nBytes;
131         int retval = ERROR_OK;
132
133         if (bank->target->state != TARGET_HALTED)
134         {
135                 LOG_ERROR("Target not halted");
136                 return ERROR_TARGET_NOT_HALTED;
137         }
138
139         uint8_t *buffer = malloc(buffer_size);
140
141         for (i = 0; i < bank->num_sectors; i++)
142         {
143                 uint32_t j;
144                 bank->sectors[i].is_erased = 1;
145
146                 for (j = 0; j < bank->sectors[i].size; j += buffer_size)
147                 {
148                         uint32_t chunk;
149                         chunk = buffer_size;
150                         if (chunk > (j - bank->sectors[i].size))
151                         {
152                                 chunk = (j - bank->sectors[i].size);
153                         }
154
155                         retval = target_read_memory(target, bank->base + bank->sectors[i].offset + j, 4, chunk/4, buffer);
156                         if (retval != ERROR_OK)
157                         {
158                                 goto done;
159                         }
160
161                         for (nBytes = 0; nBytes < chunk; nBytes++)
162                         {
163                                 if (buffer[nBytes] != 0xFF)
164                                 {
165                                         bank->sectors[i].is_erased = 0;
166                                         break;
167                                 }
168                         }
169                 }
170         }
171
172         done:
173         free(buffer);
174
175         return retval;
176 }
177
178 int default_flash_blank_check(struct flash_bank *bank)
179 {
180         struct target *target = bank->target;
181         int i;
182         int retval;
183         int fast_check = 0;
184         uint32_t blank;
185
186         if (bank->target->state != TARGET_HALTED)
187         {
188                 LOG_ERROR("Target not halted");
189                 return ERROR_TARGET_NOT_HALTED;
190         }
191
192         for (i = 0; i < bank->num_sectors; i++)
193         {
194                 uint32_t address = bank->base + bank->sectors[i].offset;
195                 uint32_t size = bank->sectors[i].size;
196
197                 if ((retval = target_blank_check_memory(target, address, size, &blank)) != ERROR_OK)
198                 {
199                         fast_check = 0;
200                         break;
201                 }
202                 if (blank == 0xFF)
203                         bank->sectors[i].is_erased = 1;
204                 else
205                         bank->sectors[i].is_erased = 0;
206                 fast_check = 1;
207         }
208
209         if (!fast_check)
210         {
211                 LOG_USER("Running slow fallback erase check - add working memory");
212                 return default_flash_mem_blank_check(bank);
213         }
214
215         return ERROR_OK;
216 }