]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - board/earthlcd/favr-32-ezkit/flash.c
atngw100: convert to generic board
[karo-tx-uboot.git] / board / earthlcd / favr-32-ezkit / flash.c
1 /*
2  * Copyright (C) 2008 Atmel Corporation
3  *
4  * SPDX-License-Identifier:     GPL-2.0+
5  */
6 #include <common.h>
7
8 #ifdef CONFIG_FAVR32_EZKIT_EXT_FLASH
9 #include <asm/arch/cacheflush.h>
10 #include <asm/io.h>
11 #include <asm/sections.h>
12
13 DECLARE_GLOBAL_DATA_PTR;
14
15 flash_info_t flash_info[1];
16
17 static void flash_identify(uint16_t *flash, flash_info_t *info)
18 {
19         unsigned long flags;
20
21         flags = disable_interrupts();
22
23         dcache_flush_unlocked();
24
25         writew(0xaa, flash + 0x555);
26         writew(0x55, flash + 0xaaa);
27         writew(0x90, flash + 0x555);
28         info->flash_id = readl(flash);
29         writew(0xff, flash);
30
31         readw(flash);
32
33         if (flags)
34                 enable_interrupts();
35 }
36
37 unsigned long flash_init(void)
38 {
39         unsigned long addr;
40         unsigned int i;
41
42         flash_info[0].size = CONFIG_SYS_FLASH_SIZE;
43         flash_info[0].sector_count = 135;
44
45         flash_identify(uncached((void *)CONFIG_SYS_FLASH_BASE), &flash_info[0]);
46
47         for (i = 0, addr = 0; i < 8; i++, addr += 0x2000)
48                 flash_info[0].start[i] = addr;
49         for (; i < flash_info[0].sector_count; i++, addr += 0x10000)
50                 flash_info[0].start[i] = addr;
51
52         return CONFIG_SYS_FLASH_SIZE;
53 }
54
55 void flash_print_info(flash_info_t *info)
56 {
57         printf("Flash: Vendor ID: 0x%02lx, Product ID: 0x%02lx\n",
58                info->flash_id >> 16, info->flash_id & 0xffff);
59         printf("Size: %ld MB in %d sectors\n",
60                info->size >> 10, info->sector_count);
61 }
62
63 int flash_erase(flash_info_t *info, int s_first, int s_last)
64 {
65         unsigned long flags;
66         unsigned long start_time;
67         uint16_t *fb, *sb;
68         unsigned int i;
69         int ret;
70         uint16_t status;
71
72         if ((s_first < 0) || (s_first > s_last)
73             || (s_last >= info->sector_count)) {
74                 puts("Error: first and/or last sector out of range\n");
75                 return ERR_INVAL;
76         }
77
78         for (i = s_first; i < s_last; i++)
79                 if (info->protect[i]) {
80                         printf("Error: sector %d is protected\n", i);
81                         return ERR_PROTECTED;
82                 }
83
84         fb = (uint16_t *)uncached(info->start[0]);
85
86         dcache_flush_unlocked();
87
88         for (i = s_first; (i <= s_last) && !ctrlc(); i++) {
89                 printf("Erasing sector %3d...", i);
90
91                 sb = (uint16_t *)uncached(info->start[i]);
92
93                 flags = disable_interrupts();
94
95                 start_time = get_timer(0);
96
97                 /* Unlock sector */
98                 writew(0xaa, fb + 0x555);
99                 writew(0x70, sb);
100
101                 /* Erase sector */
102                 writew(0xaa, fb + 0x555);
103                 writew(0x55, fb + 0xaaa);
104                 writew(0x80, fb + 0x555);
105                 writew(0xaa, fb + 0x555);
106                 writew(0x55, fb + 0xaaa);
107                 writew(0x30, sb);
108
109                 /* Wait for completion */
110                 ret = ERR_OK;
111                 do {
112                         /* TODO: Timeout */
113                         status = readw(sb);
114                 } while ((status != 0xffff) && !(status & 0x28));
115
116                 writew(0xf0, fb);
117
118                 /*
119                  * Make sure the command actually makes it to the bus
120                  * before we re-enable interrupts.
121                  */
122                 readw(fb);
123
124                 if (flags)
125                         enable_interrupts();
126
127                 if (status != 0xffff) {
128                         printf("Flash erase error at address 0x%p: 0x%02x\n",
129                                sb, status);
130                         ret = ERR_PROG_ERROR;
131                         break;
132                 }
133         }
134
135         if (ctrlc())
136                 printf("User interrupt!\n");
137
138         return ERR_OK;
139 }
140
141 int write_buff(flash_info_t *info, uchar *src,
142                            ulong addr, ulong count)
143 {
144         unsigned long flags;
145         uint16_t *base, *p, *s, *end;
146         uint16_t word, status, status1;
147         int ret = ERR_OK;
148
149         if (addr < info->start[0]
150             || (addr + count) > (info->start[0] + info->size)
151             || (addr + count) < addr) {
152                 puts("Error: invalid address range\n");
153                 return ERR_INVAL;
154         }
155
156         if (addr & 1 || count & 1 || (unsigned int)src & 1) {
157                 puts("Error: misaligned source, destination or count\n");
158                 return ERR_ALIGN;
159         }
160
161         base = (uint16_t *)uncached(info->start[0]);
162         end = (uint16_t *)uncached(addr + count);
163
164         flags = disable_interrupts();
165
166         dcache_flush_unlocked();
167         sync_write_buffer();
168
169         for (p = (uint16_t *)uncached(addr), s = (uint16_t *)src;
170              p < end && !ctrlc(); p++, s++) {
171                 word = *s;
172
173                 writew(0xaa, base + 0x555);
174                 writew(0x55, base + 0xaaa);
175                 writew(0xa0, base + 0x555);
176                 writew(word, p);
177
178                 sync_write_buffer();
179
180                 /* Wait for completion */
181                 status1 = readw(p);
182                 do {
183                         /* TODO: Timeout */
184                         status = status1;
185                         status1 = readw(p);
186                 } while (((status ^ status1) & 0x40)    /* toggled */
187                          && !(status1 & 0x28));         /* error bits */
188
189                 /*
190                  * We'll need to check once again for toggle bit
191                  * because the toggle bit may stop toggling as I/O5
192                  * changes to "1" (ref at49bv642.pdf p9)
193                  */
194                 status1 = readw(p);
195                 status = readw(p);
196                 if ((status ^ status1) & 0x40) {
197                         printf("Flash write error at address 0x%p: "
198                                "0x%02x != 0x%02x\n",
199                                p, status,word);
200                         ret = ERR_PROG_ERROR;
201                         writew(0xf0, base);
202                         readw(base);
203                         break;
204                 }
205
206                 writew(0xf0, base);
207                 readw(base);
208         }
209
210         if (flags)
211                 enable_interrupts();
212
213         return ret;
214 }
215
216 #endif /* CONFIG_FAVR32_EZKIT_EXT_FLASH */