treewide: drop executable file attrib for non-executable files
[oweals/u-boot_mod.git] / u-boot / board / ar7240 / common / ar7240_flash.c
1 #include <common.h>
2 #include <jffs2/jffs2.h>
3 #include <asm/addrspace.h>
4 #include <asm/types.h>
5 #include "ar7240_soc.h"
6 #include "ar7240_flash.h"
7
8 #define SIZE_INBYTES_4MBYTES    (4 * 1024 * 1024)
9 #define SIZE_INBYTES_8MBYTES    (2 * SIZE_INBYTES_4MBYTES)
10 #define SIZE_INBYTES_16MBYTES   (2 * SIZE_INBYTES_8MBYTES)
11
12 #define SIZE_INBYTES_4KBYTES    (4 * 1024)
13 #define SIZE_INBYTES_64KBYTES   (16 * SIZE_INBYTES_4KBYTES)
14
15 #ifndef DEFAULT_FLASH_SIZE_IN_MB
16 #error "DEFAULT_FLASH_SIZE_IN_MB not defined!"
17 #endif
18
19 extern void led_toggle(void);
20 extern void all_led_off(void);
21 extern int reset_button_status(void);
22
23 /*
24  * globals
25  */
26 flash_info_t flash_info[CFG_MAX_FLASH_BANKS];
27
28 /*
29  * statics
30  */
31 static void ar7240_spi_write_enable(void);
32 static void ar7240_spi_poll(void);
33 static void ar7240_spi_write_page(uint32_t addr, uint8_t * data, int len);
34 static void ar7240_spi_sector_erase(uint32_t addr);
35
36 /*
37  * Returns JEDEC ID from SPI flash
38  */
39 static ulong read_id(void){
40         unsigned int flashid = 0;
41
42         ar7240_reg_wr_nf(AR7240_SPI_FS, 1);
43         ar7240_reg_wr_nf(AR7240_SPI_WRITE, AR7240_SPI_CS_DIS);
44
45         ar7240_spi_bit_banger(0x9F);
46
47         ar7240_spi_delay_8();
48         ar7240_spi_delay_8();
49         ar7240_spi_delay_8();
50         ar7240_spi_delay_8();
51
52         flashid = ar7240_reg_rd(AR7240_SPI_RD_STATUS);
53
54         /*
55          * We have 3 bytes:
56          * - manufacture ID (1b)
57          * - product ID (2b)
58          */
59         flashid = flashid >> 8;
60
61         ar7240_spi_done();
62
63         return((ulong)flashid);
64 }
65
66 static void flash_set_geom(int size, int sector_count, int sector_size){
67         int i;
68         flash_info_t *info = &flash_info[0];
69
70         info->size = size;
71         info->sector_count = sector_count;
72         info->sector_size = sector_size;
73
74         for(i = 0; i < info->sector_count; i++){
75                 info->start[i] = CFG_FLASH_BASE + (i * info->sector_size);
76                 info->protect[i] = 0;
77         }
78 }
79
80 unsigned long flash_init(void){
81         flash_info_t *info;
82 #if defined(PLL_IN_FLASH_MAGIC_OFFSET)
83         u32 pll_magic, spi_control;
84
85         pll_magic = ar7240_reg_rd(CFG_FLASH_BASE + PLL_IN_FLASH_DATA_BLOCK_OFFSET + PLL_IN_FLASH_MAGIC_OFFSET);
86
87         // read SPI CONTROL Configuration register (SPI_CONTROL) value stored in FLASH (PLL_IN_FLASH_MAGIC_OFFSET + 12)
88         spi_control = ar7240_reg_rd(CFG_FLASH_BASE + PLL_IN_FLASH_DATA_BLOCK_OFFSET + PLL_IN_FLASH_MAGIC_OFFSET + 12);
89 #endif
90
91         info = &flash_info[0];
92
93         // spi flash clock
94         ar7240_reg_wr(AR7240_SPI_FS,    0x01);
95
96         // if reset button is pressed -> write default CLOCK_DIVIDER for SPI CLOCK
97         if(reset_button_status()){
98                 ar7240_reg_wr(AR7240_SPI_CLOCK, AR7240_SPI_CONTROL_DEFAULT);
99         } else {
100 #if defined(PLL_IN_FLASH_MAGIC_OFFSET)
101                 // do we have PLL_MAGIC in FLASH?
102                 if(pll_magic == PLL_IN_FLASH_MAGIC){
103                         ar7240_reg_wr(AR7240_SPI_CLOCK, spi_control);
104                 } else {
105 #endif
106                         ar7240_reg_wr(AR7240_SPI_CLOCK, AR7240_SPI_CONTROL);
107 #if defined(PLL_IN_FLASH_MAGIC_OFFSET)
108                 }
109 #endif
110         }
111
112         ar7240_reg_wr(AR7240_SPI_FS,    0x0);
113
114         // get flash id
115         info->flash_id = read_id();
116
117         puts("FLASH:  ");
118
119         // fill flash info based on JEDEC ID
120         switch(info->flash_id){
121                 /*
122                  * 4M flash chips
123                  */
124                 case 0x010215:  // tested
125                         flash_set_geom(SIZE_INBYTES_4MBYTES, 64, SIZE_INBYTES_64KBYTES);
126                         puts("Spansion S25FL032P (4 MB)");
127                         break;
128
129                 case 0x1F4700:
130                         flash_set_geom(SIZE_INBYTES_4MBYTES, 64, SIZE_INBYTES_64KBYTES);
131                         puts("Atmel AT25DF321 (4 MB)");
132                         break;
133
134                 case 0x1C3016:  // tested
135                         flash_set_geom(SIZE_INBYTES_4MBYTES, 64, SIZE_INBYTES_64KBYTES);
136                         puts("EON EN25Q32 (4 MB)");
137                         break;
138
139                 case 0x1C3116:  // tested
140                         flash_set_geom(SIZE_INBYTES_4MBYTES, 64, SIZE_INBYTES_64KBYTES);
141                         puts("EON EN25F32 (4 MB)");
142                         break;
143
144                 case 0x202016:
145                         flash_set_geom(SIZE_INBYTES_4MBYTES, 64, SIZE_INBYTES_64KBYTES);
146                         puts("Micron M25P32 (4 MB)");
147                         break;
148
149                 case 0xEF4016:
150                         flash_set_geom(SIZE_INBYTES_4MBYTES, 64, SIZE_INBYTES_64KBYTES);
151                         puts("Winbond W25Q32 (4 MB)");
152                         break;
153
154                 case 0xC22016:
155                         flash_set_geom(SIZE_INBYTES_4MBYTES, 64, SIZE_INBYTES_64KBYTES);
156                         puts("Macronix MX25L320 (4 MB)");
157                         break;
158
159                         /*
160                          * 8M flash chips
161                          */
162                 case 0x010216:
163                         flash_set_geom(SIZE_INBYTES_8MBYTES, 128, SIZE_INBYTES_64KBYTES);
164                         puts("Spansion S25FL064P (8 MB)");
165                         break;
166
167                 case 0x1F4800:
168                         flash_set_geom(SIZE_INBYTES_8MBYTES, 128, SIZE_INBYTES_64KBYTES);
169                         puts("Atmel AT25DF641 (8 MB)");
170                         break;
171
172                 case 0x1C3017:  // tested
173                         flash_set_geom(SIZE_INBYTES_8MBYTES, 128, SIZE_INBYTES_64KBYTES);
174                         puts("EON EN25Q64 (8 MB)");
175                         break;
176
177                 case 0x202017:
178                         flash_set_geom(SIZE_INBYTES_8MBYTES, 128, SIZE_INBYTES_64KBYTES);
179                         puts("Micron M25P64 (8 MB)");
180                         break;
181
182                 case 0xEF4017:  // tested
183                         flash_set_geom(SIZE_INBYTES_8MBYTES, 128, SIZE_INBYTES_64KBYTES);
184                         puts("Winbond W25Q64 (8 MB)");
185                         break;
186
187                 case 0xC22017:  // tested
188                 case 0xC22617:
189                         flash_set_geom(SIZE_INBYTES_8MBYTES, 128, SIZE_INBYTES_64KBYTES);
190                         puts("Macronix MX25L64 (8 MB)");
191                         break;
192
193                         /*
194                          * 16M flash chips
195                          */
196                 case 0xEF4018:  // tested
197                         flash_set_geom(SIZE_INBYTES_16MBYTES, 256, SIZE_INBYTES_64KBYTES);
198                         puts("Winbond W25Q128 (16 MB)");
199                         break;
200
201                 case 0xC22018:
202                 case 0xC22618:
203                         flash_set_geom(SIZE_INBYTES_16MBYTES, 256, SIZE_INBYTES_64KBYTES);
204                         puts("Macronix MX25L128 (16 MB)");
205                         break;
206
207                 case 0x012018:
208                         flash_set_geom(SIZE_INBYTES_16MBYTES, 256, SIZE_INBYTES_64KBYTES);
209                         puts("Spansion S25FL127S (16 MB)");
210                         break;
211
212                 case 0x20BA18:
213                         flash_set_geom(SIZE_INBYTES_16MBYTES, 256, SIZE_INBYTES_64KBYTES);
214                         puts("Micron N25Q128 (16 MB)");
215                         break;
216
217                         /*
218                          * Unknown flash
219                          */
220                 default:
221 #if (DEFAULT_FLASH_SIZE_IN_MB == 4)
222                         flash_set_geom(SIZE_INBYTES_4MBYTES, 64, SIZE_INBYTES_64KBYTES);
223                         puts("Unknown type (using only 4 MB)\n");
224 #elif (DEFAULT_FLASH_SIZE_IN_MB == 8)
225                         flash_set_geom(SIZE_INBYTES_8MBYTES, 128, SIZE_INBYTES_64KBYTES);
226                         puts("Unknown type (using only 8 MB)\n");
227 #elif (DEFAULT_FLASH_SIZE_IN_MB == 16)
228                         flash_set_geom(SIZE_INBYTES_16MBYTES, 256, SIZE_INBYTES_64KBYTES);
229                         puts("Unknown type (using only 16 MB)\n");
230 #endif
231                         printf("\nPlease, send request to add support\nfor your FLASH - JEDEC ID: 0x%06lX\n", info->flash_id);
232                         info->flash_id = FLASH_CUSTOM;
233                         break;
234         }
235
236         puts("\n");
237
238         return(info->size);
239 }
240
241 int flash_erase(flash_info_t *info, int s_first, int s_last){
242         int i, j, sector_size = info->size / info->sector_count;
243
244         printf("Erasing: ");
245
246         j = 0;
247
248         for(i = s_first; i <= s_last; i++){
249                 ar7240_spi_sector_erase(i * sector_size);
250
251                 if(j == 39){
252                         puts("\n         ");
253                         j = 0;
254                 }
255                 puts("#");
256                 led_toggle();
257                 j++;
258         }
259
260         ar7240_spi_done();
261         all_led_off();
262         printf("\n\n");
263
264         return(0);
265 }
266
267 /*
268  * Write a buffer from memory to flash:
269  * 0. Assumption: Caller has already erased the appropriate sectors.
270  * 1. call page programming for every 256 bytes
271  */
272 int write_buff(flash_info_t *info, uchar *source, ulong addr, ulong len){
273         int total = 0, len_this_lp, bytes_this_page;
274         ulong dst;
275         uchar *src;
276
277         printf("Writting at address: 0x%08lX\n", addr);
278         addr = addr - CFG_FLASH_BASE;
279
280         while(total < len){
281                 src = source + total;
282                 dst = addr + total;
283                 bytes_this_page = AR7240_SPI_PAGE_SIZE - (addr % AR7240_SPI_PAGE_SIZE);
284                 len_this_lp = ((len - total) > bytes_this_page) ? bytes_this_page : (len - total);
285                 ar7240_spi_write_page(dst, src, len_this_lp);
286                 total += len_this_lp;
287         }
288
289         ar7240_spi_done();
290         printf("\n");
291
292         return(0);
293 }
294
295 static void ar7240_spi_write_enable(){
296         ar7240_reg_wr_nf(AR7240_SPI_FS, 1);
297         ar7240_reg_wr_nf(AR7240_SPI_WRITE, AR7240_SPI_CS_DIS);
298         ar7240_spi_bit_banger(AR7240_SPI_CMD_WREN);
299         ar7240_spi_go();
300 }
301
302 static void ar7240_spi_poll(){
303         int rd;
304
305         do {
306                 ar7240_reg_wr_nf(AR7240_SPI_WRITE, AR7240_SPI_CS_DIS);
307                 ar7240_spi_bit_banger(AR7240_SPI_CMD_RD_STATUS);
308                 ar7240_spi_delay_8();
309                 rd = (ar7240_reg_rd(AR7240_SPI_RD_STATUS) & 1);
310         } while(rd);
311 }
312
313 static void ar7240_spi_write_page(uint32_t addr, uint8_t *data, int len){
314         int i;
315         uint8_t ch;
316
317         ar7240_spi_write_enable();
318         ar7240_spi_bit_banger(AR7240_SPI_CMD_PAGE_PROG);
319         ar7240_spi_send_addr(addr);
320
321         for(i = 0; i < len; i++){
322                 ch = *(data + i);
323                 ar7240_spi_bit_banger(ch);
324         }
325
326         ar7240_spi_go();
327         ar7240_spi_poll();
328 }
329
330 static void ar7240_spi_sector_erase(uint32_t addr){
331         ar7240_spi_write_enable();
332         ar7240_spi_bit_banger(AR7240_SPI_CMD_SECTOR_ERASE);
333         ar7240_spi_send_addr(addr);
334         ar7240_spi_go();
335         ar7240_spi_poll();
336 }