1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62#include <common.h>
63#include <asm/io.h>
64#include <asm/arch/hardware.h>
65#include <asm/arch/at91_common.h>
66#include <asm/arch/at91_eefc.h>
67#include <asm/arch/at91_dbu.h>
68
69
70#if CONFIG_SYS_MAX_FLASH_BANKS!=1
71#error eflash: this driver can only handle 1 bank
72#endif
73
74
75flash_info_t flash_info[CONFIG_SYS_MAX_FLASH_BANKS];
76static u32 pagesize;
77
78unsigned long flash_init (void)
79{
80 at91_eefc_t *eefc = (at91_eefc_t *) ATMEL_BASE_EEFC;
81 at91_dbu_t *dbu = (at91_dbu_t *) ATMEL_BASE_DBGU;
82 u32 id, size, nplanes, planesize, nlocks;
83 u32 addr, i, tmp=0;
84
85 debug("eflash: init\n");
86
87 flash_info[0].flash_id = FLASH_UNKNOWN;
88
89
90 if ((readl(&dbu->cidr) & AT91_DBU_CID_ARCH_MASK) != AT91_DBU_CID_ARCH_9XExx) {
91 puts("eflash: not an AT91SAM9XE\n");
92 return 0;
93 }
94
95
96 writel(AT91_EEFC_FCR_KEY | AT91_EEFC_FCR_FCMD_GETD, &eefc->fcr);
97 while ((readl(&eefc->fsr) & AT91_EEFC_FSR_FRDY) == 0)
98 ;
99 id = readl(&eefc->frr);
100 size = readl(&eefc->frr);
101 pagesize = readl(&eefc->frr);
102 nplanes = readl(&eefc->frr);
103 planesize = readl(&eefc->frr);
104 debug("id=%08x size=%u pagesize=%u planes=%u planesize=%u\n",
105 id, size, pagesize, nplanes, planesize);
106 for (i=1; i<nplanes; i++) {
107 tmp = readl(&eefc->frr);
108 };
109 nlocks = readl(&eefc->frr);
110 debug("nlocks=%u\n", nlocks);
111
112 if (nlocks > CONFIG_SYS_MAX_FLASH_SECT) {
113 printf("eflash: number of lock regions(%u) "\
114 "> CONFIG_SYS_MAX_FLASH_SECT. reducing...\n",
115 nlocks);
116 nlocks = CONFIG_SYS_MAX_FLASH_SECT;
117 }
118 flash_info[0].size = size;
119 flash_info[0].sector_count = nlocks;
120 flash_info[0].flash_id = id;
121
122 addr = ATMEL_BASE_FLASH;
123 for (i=0; i<nlocks; i++) {
124 tmp = readl(&eefc->frr);
125 flash_info[0].start[i] = addr;
126 flash_info[0].protect[i] = 0;
127 addr += tmp;
128 };
129
130
131 writel(AT91_EEFC_FCR_KEY | AT91_EEFC_FCR_FCMD_GLB, &eefc->fcr);
132 while ((readl(&eefc->fsr) & AT91_EEFC_FSR_FRDY) == 0)
133 ;
134 for (i=0; i<flash_info[0].sector_count; i++) {
135 if (i%32 == 0)
136 tmp = readl(&eefc->frr);
137 flash_info[0].protect[i] = (tmp >> (i%32)) & 1;
138#if defined(CONFIG_EFLASH_PROTSECTORS)
139 if (i < CONFIG_EFLASH_PROTSECTORS)
140 flash_info[0].protect[i] = 1;
141#endif
142 }
143
144 return size;
145}
146
147void flash_print_info (flash_info_t *info)
148{
149 int i;
150
151 puts("AT91SAM9XE embedded flash\n Size: ");
152 print_size(info->size, " in ");
153 printf("%d Sectors\n", info->sector_count);
154
155 printf(" Sector Start Addresses:");
156 for (i=0; i<info->sector_count; ++i) {
157 if ((i % 5) == 0)
158 printf("\n ");
159 printf(" %08lX%s",
160 info->start[i],
161 info->protect[i] ? " (RO)" : " "
162 );
163 }
164 printf ("\n");
165 return;
166}
167
168int flash_real_protect (flash_info_t *info, long sector, int prot)
169{
170 at91_eefc_t *eefc = (at91_eefc_t *) ATMEL_BASE_EEFC;
171 u32 pagenum = (info->start[sector]-ATMEL_BASE_FLASH)/pagesize;
172 u32 i, tmp=0;
173
174 debug("protect sector=%ld prot=%d\n", sector, prot);
175
176#if defined(CONFIG_EFLASH_PROTSECTORS)
177 if (sector < CONFIG_EFLASH_PROTSECTORS) {
178 if (!prot) {
179 printf("eflash: sector %lu cannot be unprotected\n",
180 sector);
181 }
182 return 1;
183 }
184#endif
185 if (prot) {
186 writel(AT91_EEFC_FCR_KEY | AT91_EEFC_FCR_FCMD_SLB |
187 (pagenum << AT91_EEFC_FCR_FARG_SHIFT), &eefc->fcr);
188 } else {
189 writel(AT91_EEFC_FCR_KEY | AT91_EEFC_FCR_FCMD_CLB |
190 (pagenum << AT91_EEFC_FCR_FARG_SHIFT), &eefc->fcr);
191 }
192 while ((readl(&eefc->fsr) & AT91_EEFC_FSR_FRDY) == 0)
193 ;
194
195 writel(AT91_EEFC_FCR_KEY | AT91_EEFC_FCR_FCMD_GLB, &eefc->fcr);
196 while ((readl(&eefc->fsr) & AT91_EEFC_FSR_FRDY) == 0)
197 ;
198 for (i=0; i<info->sector_count; i++) {
199 if (i%32 == 0)
200 tmp = readl(&eefc->frr);
201 info->protect[i] = (tmp >> (i%32)) & 1;
202 }
203 return 0;
204}
205
206static u32 erase_write_page (u32 pagenum)
207{
208 at91_eefc_t *eefc = (at91_eefc_t *) ATMEL_BASE_EEFC;
209
210 debug("erase+write page=%u\n", pagenum);
211
212
213 writel(AT91_EEFC_FCR_KEY | AT91_EEFC_FCR_FCMD_EWP |
214 (pagenum << AT91_EEFC_FCR_FARG_SHIFT), &eefc->fcr);
215 while ((readl(&eefc->fsr) & AT91_EEFC_FSR_FRDY) == 0)
216 ;
217
218 return readl(&eefc->fsr)
219 & (AT91_EEFC_FSR_FCMDE | AT91_EEFC_FSR_FLOCKE);
220}
221
222int flash_erase (flash_info_t *info, int s_first, int s_last)
223{
224 debug("erase first=%d last=%d\n", s_first, s_last);
225 puts("this flash does not need and support erasing!\n");
226 return 0;
227}
228
229
230
231
232
233
234
235int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
236{
237 u32 pagenum;
238 u32 *src32, *dst32;
239 u32 i;
240
241 debug("write src=%08lx addr=%08lx cnt=%lx\n",
242 (ulong)src, addr, cnt);
243
244
245 if (addr % pagesize) {
246 printf ("eflash: start %08lx is not on page start\n"\
247 " write aborted\n", addr);
248 return 1;
249 }
250
251
252 pagenum = (addr-ATMEL_BASE_FLASH)/pagesize;
253 src32 = (u32 *) src;
254 dst32 = (u32 *) addr;
255 while (cnt > 0) {
256 i = pagesize / 4;
257
258 while (i--)
259 *dst32++ = *src32++;
260
261 if (erase_write_page(pagenum))
262 return 1;
263 pagenum++;
264 if (cnt > pagesize)
265 cnt -= pagesize;
266 else
267 cnt = 0;
268 }
269 return 0;
270}
271