blob: 5860cd0ac03bf1e683ef264e926f1771b08acad0 [file] [log] [blame]
Tom Rini83d290c2018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
wdenka562e1b2005-01-09 18:21:42 +00002/*
3 * (C) Copyright 2000-2003
4 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
wdenka562e1b2005-01-09 18:21:42 +00005 */
6
7#include <common.h>
Simon Glass24b852a2015-11-08 23:47:45 -07008#include <console.h>
Simon Glass9edefc22019-11-14 12:57:37 -07009#include <cpu_func.h>
Simon Glassb79fdc72020-05-10 11:39:54 -060010#include <flash.h>
Simon Glass36bf4462019-11-14 12:57:42 -070011#include <irq_func.h>
Simon Glassb79fdc72020-05-10 11:39:54 -060012#include <uuid.h>
wdenka562e1b2005-01-09 18:21:42 +000013
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +020014#define PHYS_FLASH_1 CONFIG_SYS_FLASH_BASE
wdenka562e1b2005-01-09 18:21:42 +000015#define FLASH_BANK_SIZE 0x200000
16
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +020017flash_info_t flash_info[CONFIG_SYS_MAX_FLASH_BANKS];
wdenka562e1b2005-01-09 18:21:42 +000018
Simon Glassa595a0e2020-05-10 11:39:53 -060019void flash_print_info(flash_info_t *info)
wdenka562e1b2005-01-09 18:21:42 +000020{
21 int i;
22
23 switch (info->flash_id & FLASH_VENDMASK) {
24 case (AMD_MANUFACT & FLASH_VENDMASK):
25 printf ("AMD: ");
26 break;
27 default:
28 printf ("Unknown Vendor ");
29 break;
30 }
31
32 switch (info->flash_id & FLASH_TYPEMASK) {
33 case (AMD_ID_PL160CB & FLASH_TYPEMASK):
34 printf ("AM29PL160CB (16Mbit)\n");
35 break;
36 default:
37 printf ("Unknown Chip Type\n");
38 goto Done;
39 break;
40 }
41
42 printf (" Size: %ld MB in %d Sectors\n",
43 info->size >> 20, info->sector_count);
44
45 printf (" Sector Start Addresses:");
46 for (i = 0; i < info->sector_count; i++) {
47 if ((i % 5) == 0) {
48 printf ("\n ");
49 }
50 printf (" %08lX%s", info->start[i],
51 info->protect[i] ? " (RO)" : " ");
52 }
53 printf ("\n");
54
55Done:
Marian Balakowicz483a0cf2006-05-09 11:28:36 +020056 return;
wdenka562e1b2005-01-09 18:21:42 +000057}
58
59
Simon Glassa595a0e2020-05-10 11:39:53 -060060unsigned long flash_init(void)
wdenka562e1b2005-01-09 18:21:42 +000061{
62 int i, j;
63 ulong size = 0;
64
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +020065 for (i = 0; i < CONFIG_SYS_MAX_FLASH_BANKS; i++) {
wdenka562e1b2005-01-09 18:21:42 +000066 ulong flashbase = 0;
67
68 flash_info[i].flash_id =
69 (AMD_MANUFACT & FLASH_VENDMASK) |
70 (AMD_ID_PL160CB & FLASH_TYPEMASK);
71 flash_info[i].size = FLASH_BANK_SIZE;
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +020072 flash_info[i].sector_count = CONFIG_SYS_MAX_FLASH_SECT;
73 memset (flash_info[i].protect, 0, CONFIG_SYS_MAX_FLASH_SECT);
wdenka562e1b2005-01-09 18:21:42 +000074 if (i == 0)
75 flashbase = PHYS_FLASH_1;
76 else
77 panic ("configured to many flash banks!\n");
78
79 for (j = 0; j < flash_info[i].sector_count; j++) {
80 if (j == 0) {
81 /* 1st is 16 KiB */
82 flash_info[i].start[j] = flashbase;
83 }
84 if ((j >= 1) && (j <= 2)) {
85 /* 2nd and 3rd are 8 KiB */
86 flash_info[i].start[j] =
87 flashbase + 0x4000 + 0x2000 * (j - 1);
88 }
89 if (j == 3) {
90 /* 4th is 224 KiB */
91 flash_info[i].start[j] = flashbase + 0x8000;
92 }
93 if ((j >= 4) && (j <= 10)) {
94 /* rest is 256 KiB */
95 flash_info[i].start[j] =
96 flashbase + 0x40000 + 0x40000 * (j -
97 4);
98 }
99 }
100 size += flash_info[i].size;
101 }
102
Simon Glassa595a0e2020-05-10 11:39:53 -0600103 flash_protect(FLAG_PROTECT_SET,
104 CONFIG_SYS_FLASH_BASE,
105 CONFIG_SYS_FLASH_BASE + 0x3ffff, &flash_info[0]);
wdenka562e1b2005-01-09 18:21:42 +0000106
107 return size;
108}
109
110
111#define CMD_READ_ARRAY 0x00F0
112#define CMD_UNLOCK1 0x00AA
113#define CMD_UNLOCK2 0x0055
114#define CMD_ERASE_SETUP 0x0080
115#define CMD_ERASE_CONFIRM 0x0030
116#define CMD_PROGRAM 0x00A0
117#define CMD_UNLOCK_BYPASS 0x0020
118
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200119#define MEM_FLASH_ADDR1 (*(volatile u16 *)(CONFIG_SYS_FLASH_BASE + (0x00000555<<1)))
120#define MEM_FLASH_ADDR2 (*(volatile u16 *)(CONFIG_SYS_FLASH_BASE + (0x000002AA<<1)))
wdenka562e1b2005-01-09 18:21:42 +0000121
122#define BIT_ERASE_DONE 0x0080
123#define BIT_RDY_MASK 0x0080
124#define BIT_PROGRAM_ERROR 0x0020
125#define BIT_TIMEOUT 0x80000000 /* our flag */
126
127#define READY 1
128#define ERR 2
129#define TMO 4
130
131
Simon Glassa595a0e2020-05-10 11:39:53 -0600132int flash_erase(flash_info_t *info, int s_first, int s_last)
wdenka562e1b2005-01-09 18:21:42 +0000133{
134 ulong result;
135 int iflag, cflag, prot, sect;
136 int rc = ERR_OK;
137 int chip1;
Graeme Russdcac25a2011-06-28 01:40:55 +0000138 ulong start;
wdenka562e1b2005-01-09 18:21:42 +0000139
140 /* first look for protection bits */
141
142 if (info->flash_id == FLASH_UNKNOWN)
143 return ERR_UNKNOWN_FLASH_TYPE;
144
145 if ((s_first < 0) || (s_first > s_last)) {
146 return ERR_INVAL;
147 }
148
149 if ((info->flash_id & FLASH_VENDMASK) !=
150 (AMD_MANUFACT & FLASH_VENDMASK)) {
151 return ERR_UNKNOWN_FLASH_VENDOR;
152 }
153
154 prot = 0;
155 for (sect = s_first; sect <= s_last; ++sect) {
156 if (info->protect[sect]) {
157 prot++;
158 }
159 }
160 if (prot)
161 return ERR_PROTECTED;
162
163 /*
164 * Disable interrupts which might cause a timeout
165 * here. Remember that our exception vectors are
166 * at address 0 in the flash, and we don't want a
167 * (ticker) exception to happen while the flash
168 * chip is in programming mode.
169 */
170
Simon Glass6cc915b2019-11-14 12:57:36 -0700171 cflag = icache_status();
172 icache_disable();
Simon Glass9d3915b2019-11-14 12:57:40 -0700173 iflag = disable_interrupts();
wdenka562e1b2005-01-09 18:21:42 +0000174
175 printf ("\n");
176
177 /* Start erase on unprotected sectors */
178 for (sect = s_first; sect <= s_last && !ctrlc (); sect++) {
179 printf ("Erasing sector %2d ... ", sect);
180
181 /* arm simple, non interrupt dependent timer */
Graeme Russdcac25a2011-06-28 01:40:55 +0000182 start = get_timer(0);
wdenka562e1b2005-01-09 18:21:42 +0000183
184 if (info->protect[sect] == 0) { /* not protected */
185 volatile u16 *addr =
186 (volatile u16 *) (info->start[sect]);
187
188 MEM_FLASH_ADDR1 = CMD_UNLOCK1;
189 MEM_FLASH_ADDR2 = CMD_UNLOCK2;
190 MEM_FLASH_ADDR1 = CMD_ERASE_SETUP;
191
192 MEM_FLASH_ADDR1 = CMD_UNLOCK1;
193 MEM_FLASH_ADDR2 = CMD_UNLOCK2;
194 *addr = CMD_ERASE_CONFIRM;
195
196 /* wait until flash is ready */
197 chip1 = 0;
198
199 do {
200 result = *addr;
201
202 /* check timeout */
Graeme Russdcac25a2011-06-28 01:40:55 +0000203 if (get_timer(start) > CONFIG_SYS_FLASH_ERASE_TOUT) {
wdenka562e1b2005-01-09 18:21:42 +0000204 MEM_FLASH_ADDR1 = CMD_READ_ARRAY;
205 chip1 = TMO;
206 break;
207 }
208
209 if (!chip1
210 && (result & 0xFFFF) & BIT_ERASE_DONE)
211 chip1 = READY;
212
213 } while (!chip1);
214
215 MEM_FLASH_ADDR1 = CMD_READ_ARRAY;
216
217 if (chip1 == ERR) {
218 rc = ERR_PROG_ERROR;
219 goto outahere;
220 }
221 if (chip1 == TMO) {
Mario Six9dbaebc2018-01-26 14:43:52 +0100222 rc = ERR_TIMEOUT;
wdenka562e1b2005-01-09 18:21:42 +0000223 goto outahere;
224 }
225
226 printf ("ok.\n");
227 } else { /* it was protected */
228
229 printf ("protected!\n");
230 }
231 }
232
233 if (ctrlc ())
234 printf ("User Interrupt!\n");
235
236 outahere:
237 /* allow flash to settle - wait 10 ms */
238 udelay (10000);
239
240 if (iflag)
Simon Glass9d3915b2019-11-14 12:57:40 -0700241 enable_interrupts();
wdenka562e1b2005-01-09 18:21:42 +0000242
243 if (cflag)
Simon Glass6cc915b2019-11-14 12:57:36 -0700244 icache_enable();
wdenka562e1b2005-01-09 18:21:42 +0000245
246 return rc;
247}
248
Simon Glassa595a0e2020-05-10 11:39:53 -0600249static int write_word(flash_info_t *info, ulong dest, ulong data)
wdenka562e1b2005-01-09 18:21:42 +0000250{
251 volatile u16 *addr = (volatile u16 *) dest;
252 ulong result;
253 int rc = ERR_OK;
254 int cflag, iflag;
255 int chip1;
Graeme Russdcac25a2011-06-28 01:40:55 +0000256 ulong start;
wdenka562e1b2005-01-09 18:21:42 +0000257
258 /*
259 * Check if Flash is (sufficiently) erased
260 */
261 result = *addr;
262 if ((result & data) != data)
263 return ERR_NOT_ERASED;
264
265
266 /*
267 * Disable interrupts which might cause a timeout
268 * here. Remember that our exception vectors are
269 * at address 0 in the flash, and we don't want a
270 * (ticker) exception to happen while the flash
271 * chip is in programming mode.
272 */
273
Simon Glass6cc915b2019-11-14 12:57:36 -0700274 cflag = icache_status();
275 icache_disable();
Simon Glass9d3915b2019-11-14 12:57:40 -0700276 iflag = disable_interrupts();
wdenka562e1b2005-01-09 18:21:42 +0000277
278 MEM_FLASH_ADDR1 = CMD_UNLOCK1;
279 MEM_FLASH_ADDR2 = CMD_UNLOCK2;
280 MEM_FLASH_ADDR1 = CMD_PROGRAM;
281 *addr = data;
282
283 /* arm simple, non interrupt dependent timer */
Graeme Russdcac25a2011-06-28 01:40:55 +0000284 start = get_timer(0);
wdenka562e1b2005-01-09 18:21:42 +0000285
286 /* wait until flash is ready */
287 chip1 = 0;
288 do {
289 result = *addr;
290
291 /* check timeout */
Graeme Russdcac25a2011-06-28 01:40:55 +0000292 if (get_timer(start) > CONFIG_SYS_FLASH_ERASE_TOUT) {
wdenka562e1b2005-01-09 18:21:42 +0000293 chip1 = ERR | TMO;
294 break;
295 }
296 if (!chip1 && ((result & 0x80) == (data & 0x80)))
297 chip1 = READY;
298
299 } while (!chip1);
300
301 *addr = CMD_READ_ARRAY;
302
303 if (chip1 == ERR || *addr != data)
304 rc = ERR_PROG_ERROR;
305
306 if (iflag)
Simon Glass9d3915b2019-11-14 12:57:40 -0700307 enable_interrupts();
wdenka562e1b2005-01-09 18:21:42 +0000308
309 if (cflag)
Simon Glass6cc915b2019-11-14 12:57:36 -0700310 icache_enable();
wdenka562e1b2005-01-09 18:21:42 +0000311
312 return rc;
313}
314
315
Simon Glassa595a0e2020-05-10 11:39:53 -0600316int write_buff(flash_info_t *info, uchar *src, ulong addr, ulong cnt)
wdenka562e1b2005-01-09 18:21:42 +0000317{
318 ulong wp, data;
319 int rc;
320
321 if (addr & 1) {
322 printf ("unaligned destination not supported\n");
323 return ERR_ALIGN;
324 }
325
326#if 0
327 if (cnt & 1) {
328 printf ("odd transfer sizes not supported\n");
329 return ERR_ALIGN;
330 }
331#endif
332
333 wp = addr;
334
335 if (addr & 1) {
336 data = (*((volatile u8 *) addr) << 8) | *((volatile u8 *)
337 src);
338 if ((rc = write_word (info, wp - 1, data)) != 0) {
339 return (rc);
340 }
341 src += 1;
342 wp += 1;
343 cnt -= 1;
344 }
345
346 while (cnt >= 2) {
347 data = *((volatile u16 *) src);
348 if ((rc = write_word (info, wp, data)) != 0) {
349 return (rc);
350 }
351 src += 2;
352 wp += 2;
353 cnt -= 2;
354 }
355
356 if (cnt == 1) {
357 data = (*((volatile u8 *) src) << 8) |
358 *((volatile u8 *) (wp + 1));
359 if ((rc = write_word (info, wp, data)) != 0) {
360 return (rc);
361 }
362 src += 1;
363 wp += 1;
364 cnt -= 1;
365 }
366
367 return ERR_OK;
368}