]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - arch/arm/cpu/arm926ejs/at91/eflash.c
Add GPL-2.0+ SPDX-License-Identifier to source files
[karo-tx-uboot.git] / arch / arm / cpu / arm926ejs / at91 / eflash.c
1 /*
2  * (C) Copyright 2010
3  * Reinhard Meyer, EMK Elektronik, reinhard.meyer@emk-elektronik.de
4  *
5  * SPDX-License-Identifier:     GPL-2.0+
6  */
7
8 /*
9  * this driver supports the enhanced embedded flash in the Atmel
10  * AT91SAM9XE devices with the following geometry:
11  *
12  * AT91SAM9XE128: 1 plane of  8 regions of 32 pages (total  256 pages)
13  * AT91SAM9XE256: 1 plane of 16 regions of 32 pages (total  512 pages)
14  * AT91SAM9XE512: 1 plane of 32 regions of 32 pages (total 1024 pages)
15  * (the exact geometry is read from the flash at runtime, so any
16  *  future devices should already be covered)
17  *
18  * Regions can be write/erase protected.
19  * Whole (!) pages can be individually written with erase on the fly.
20  * Writing partial pages will corrupt the rest of the page.
21  *
22  * The flash is presented to u-boot with each region being a sector,
23  * having the following effects:
24  * Each sector can be hardware protected (protect on/off).
25  * Each page in a sector can be rewritten anytime.
26  * Since pages are erased when written, the "erase" does nothing.
27  * The first "CONFIG_EFLASH_PROTSECTORS" cannot be unprotected
28  * by u-Boot commands.
29  *
30  * Note: Redundant environment will not work in this flash since
31  * it does use partial page writes. Make sure the environent spans
32  * whole pages!
33  */
34
35 /*
36  * optional TODOs (nice to have features):
37  *
38  * make the driver coexist with other NOR flash drivers
39  *      (use an index into flash_info[], requires work
40  *      in those other drivers, too)
41  * Make the erase command fill the sectors with 0xff
42  *      (if the flashes grow larger in the future and
43  *      someone puts a jffs2 into them)
44  * do a read-modify-write for partially programmed pages
45  */
46 #include <common.h>
47 #include <asm/io.h>
48 #include <asm/arch/hardware.h>
49 #include <asm/arch/at91_common.h>
50 #include <asm/arch/at91_eefc.h>
51 #include <asm/arch/at91_dbu.h>
52
53 /* checks to detect configuration errors */
54 #if CONFIG_SYS_MAX_FLASH_BANKS!=1
55 #error eflash: this driver can only handle 1 bank
56 #endif
57
58 /* global structure */
59 flash_info_t flash_info[CONFIG_SYS_MAX_FLASH_BANKS];
60 static u32 pagesize;
61
62 unsigned long flash_init (void)
63 {
64         at91_eefc_t *eefc = (at91_eefc_t *) ATMEL_BASE_EEFC;
65         at91_dbu_t *dbu = (at91_dbu_t *) ATMEL_BASE_DBGU;
66         u32 id, size, nplanes, planesize, nlocks;
67         u32 addr, i, tmp=0;
68
69         debug("eflash: init\n");
70
71         flash_info[0].flash_id = FLASH_UNKNOWN;
72
73         /* check if its an AT91ARM9XE SoC */
74         if ((readl(&dbu->cidr) & AT91_DBU_CID_ARCH_MASK) != AT91_DBU_CID_ARCH_9XExx) {
75                 puts("eflash: not an AT91SAM9XE\n");
76                 return 0;
77         }
78
79         /* now query the eflash for its structure */
80         writel(AT91_EEFC_FCR_KEY | AT91_EEFC_FCR_FCMD_GETD, &eefc->fcr);
81         while ((readl(&eefc->fsr) & AT91_EEFC_FSR_FRDY) == 0)
82                 ;
83         id = readl(&eefc->frr);         /* word 0 */
84         size = readl(&eefc->frr);       /* word 1 */
85         pagesize = readl(&eefc->frr);   /* word 2 */
86         nplanes = readl(&eefc->frr);    /* word 3 */
87         planesize = readl(&eefc->frr);  /* word 4 */
88         debug("id=%08x size=%u pagesize=%u planes=%u planesize=%u\n",
89                 id, size, pagesize, nplanes, planesize);
90         for (i=1; i<nplanes; i++) {
91                 tmp = readl(&eefc->frr);        /* words 5..4+nplanes-1 */
92         };
93         nlocks = readl(&eefc->frr);     /* word 4+nplanes */
94         debug("nlocks=%u\n", nlocks);
95         /* since we are going to use the lock regions as sectors, check count */
96         if (nlocks > CONFIG_SYS_MAX_FLASH_SECT) {
97                 printf("eflash: number of lock regions(%u) "\
98                         "> CONFIG_SYS_MAX_FLASH_SECT. reducing...\n",
99                         nlocks);
100                 nlocks = CONFIG_SYS_MAX_FLASH_SECT;
101         }
102         flash_info[0].size = size;
103         flash_info[0].sector_count = nlocks;
104         flash_info[0].flash_id = id;
105
106         addr = ATMEL_BASE_FLASH;
107         for (i=0; i<nlocks; i++) {
108                 tmp = readl(&eefc->frr);        /* words 4+nplanes+1.. */
109                 flash_info[0].start[i] = addr;
110                 flash_info[0].protect[i] = 0;
111                 addr += tmp;
112         };
113
114         /* now read the protection information for all regions */
115         writel(AT91_EEFC_FCR_KEY | AT91_EEFC_FCR_FCMD_GLB, &eefc->fcr);
116         while ((readl(&eefc->fsr) & AT91_EEFC_FSR_FRDY) == 0)
117                 ;
118         for (i=0; i<flash_info[0].sector_count; i++) {
119                 if (i%32 == 0)
120                         tmp = readl(&eefc->frr);
121                 flash_info[0].protect[i] = (tmp >> (i%32)) & 1;
122 #if defined(CONFIG_EFLASH_PROTSECTORS)
123                 if (i < CONFIG_EFLASH_PROTSECTORS)
124                         flash_info[0].protect[i] = 1;
125 #endif
126         }
127
128         return size;
129 }
130
131 void flash_print_info (flash_info_t *info)
132 {
133         int i;
134
135         puts("AT91SAM9XE embedded flash\n  Size: ");
136         print_size(info->size, " in ");
137         printf("%d Sectors\n", info->sector_count);
138
139         printf("  Sector Start Addresses:");
140         for (i=0; i<info->sector_count; ++i) {
141                 if ((i % 5) == 0)
142                         printf("\n   ");
143                 printf(" %08lX%s",
144                         info->start[i],
145                         info->protect[i] ? " (RO)" : "     "
146                 );
147         }
148         printf ("\n");
149         return;
150 }
151
152 int flash_real_protect (flash_info_t *info, long sector, int prot)
153 {
154         at91_eefc_t *eefc = (at91_eefc_t *) ATMEL_BASE_EEFC;
155         u32 pagenum = (info->start[sector]-ATMEL_BASE_FLASH)/pagesize;
156         u32 i, tmp=0;
157
158         debug("protect sector=%ld prot=%d\n", sector, prot);
159
160 #if defined(CONFIG_EFLASH_PROTSECTORS)
161         if (sector < CONFIG_EFLASH_PROTSECTORS) {
162                 if (!prot) {
163                         printf("eflash: sector %lu cannot be unprotected\n",
164                                 sector);
165                 }
166                 return 1; /* return anyway, caller does not care for result */
167         }
168 #endif
169         if (prot) {
170                 writel(AT91_EEFC_FCR_KEY | AT91_EEFC_FCR_FCMD_SLB |
171                         (pagenum << AT91_EEFC_FCR_FARG_SHIFT), &eefc->fcr);
172         } else {
173                 writel(AT91_EEFC_FCR_KEY | AT91_EEFC_FCR_FCMD_CLB |
174                         (pagenum << AT91_EEFC_FCR_FARG_SHIFT), &eefc->fcr);
175         }
176         while ((readl(&eefc->fsr) & AT91_EEFC_FSR_FRDY) == 0)
177                 ;
178         /* now re-read the protection information for all regions */
179         writel(AT91_EEFC_FCR_KEY | AT91_EEFC_FCR_FCMD_GLB, &eefc->fcr);
180         while ((readl(&eefc->fsr) & AT91_EEFC_FSR_FRDY) == 0)
181                 ;
182         for (i=0; i<info->sector_count; i++) {
183                 if (i%32 == 0)
184                         tmp = readl(&eefc->frr);
185                 info->protect[i] = (tmp >> (i%32)) & 1;
186         }
187         return 0;
188 }
189
190 static u32 erase_write_page (u32 pagenum)
191 {
192         at91_eefc_t *eefc = (at91_eefc_t *) ATMEL_BASE_EEFC;
193
194         debug("erase+write page=%u\n", pagenum);
195
196         /* give erase and write page command */
197         writel(AT91_EEFC_FCR_KEY | AT91_EEFC_FCR_FCMD_EWP |
198                 (pagenum << AT91_EEFC_FCR_FARG_SHIFT), &eefc->fcr);
199         while ((readl(&eefc->fsr) & AT91_EEFC_FSR_FRDY) == 0)
200                 ;
201         /* return status */
202         return readl(&eefc->fsr)
203                 & (AT91_EEFC_FSR_FCMDE | AT91_EEFC_FSR_FLOCKE);
204 }
205
206 int flash_erase (flash_info_t *info, int s_first, int s_last)
207 {
208         debug("erase first=%d last=%d\n", s_first, s_last);
209         puts("this flash does not need and support erasing!\n");
210         return 0;
211 }
212
213 /*
214  * Copy memory to flash, returns:
215  * 0 - OK
216  * 1 - write timeout
217  */
218
219 int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
220 {
221         u32 pagenum;
222         u32 *src32, *dst32;
223         u32 i;
224
225         debug("write src=%08lx addr=%08lx cnt=%lx\n",
226                 (ulong)src, addr, cnt);
227
228         /* REQUIRE addr to be on a page start, abort if not */
229         if (addr % pagesize) {
230                 printf ("eflash: start %08lx is not on page start\n"\
231                         "        write aborted\n", addr);
232                 return 1;
233         }
234
235         /* now start copying data */
236         pagenum = (addr-ATMEL_BASE_FLASH)/pagesize;
237         src32 = (u32 *) src;
238         dst32 = (u32 *) addr;
239         while (cnt > 0) {
240                 i = pagesize / 4;
241                 /* fill page buffer */
242                 while (i--)
243                         *dst32++ = *src32++;
244                 /* write page */
245                 if (erase_write_page(pagenum))
246                         return 1;
247                 pagenum++;
248                 if (cnt > pagesize)
249                         cnt -= pagesize;
250                 else
251                         cnt = 0;
252         }
253         return 0;
254 }