]> git.sur5r.net Git - u-boot/blob - drivers/mtd/pic32_flash.c
Merge tag 'signed-efi-2018.05' of git://github.com/agraf/u-boot
[u-boot] / drivers / mtd / pic32_flash.c
1 /*
2  * Copyright (C) 2015
3  * Cristian Birsan <cristian.birsan@microchip.com>
4  * Purna Chandra Mandal <purna.mandal@microchip.com>
5  *
6  * SPDX-License-Identifier:     GPL-2.0+
7  */
8
9 #include <common.h>
10 #include <dm.h>
11 #include <fdt_support.h>
12 #include <flash.h>
13 #include <mach/pic32.h>
14 #include <wait_bit.h>
15
16 DECLARE_GLOBAL_DATA_PTR;
17
18 /* NVM Controller registers */
19 struct pic32_reg_nvm {
20         struct pic32_reg_atomic ctrl;
21         struct pic32_reg_atomic key;
22         struct pic32_reg_atomic addr;
23         struct pic32_reg_atomic data;
24 };
25
26 /* NVM operations */
27 #define NVMOP_NOP               0
28 #define NVMOP_WORD_WRITE        1
29 #define NVMOP_PAGE_ERASE        4
30
31 /* NVM control bits */
32 #define NVM_WR                  BIT(15)
33 #define NVM_WREN                BIT(14)
34 #define NVM_WRERR               BIT(13)
35 #define NVM_LVDERR              BIT(12)
36
37 /* NVM programming unlock register */
38 #define LOCK_KEY                0x0
39 #define UNLOCK_KEY1             0xaa996655
40 #define UNLOCK_KEY2             0x556699aa
41
42 /*
43  * PIC32 flash banks consist of number of pages, each page
44  * into number of rows and rows into number of words.
45  * Here we will maintain page information instead of sector.
46  */
47 flash_info_t flash_info[CONFIG_SYS_MAX_FLASH_BANKS];
48 static struct pic32_reg_nvm *nvm_regs_p;
49
50 static inline void flash_initiate_operation(u32 nvmop)
51 {
52         /* set operation */
53         writel(nvmop, &nvm_regs_p->ctrl.raw);
54
55         /* enable flash write */
56         writel(NVM_WREN, &nvm_regs_p->ctrl.set);
57
58         /* unlock sequence */
59         writel(LOCK_KEY, &nvm_regs_p->key.raw);
60         writel(UNLOCK_KEY1, &nvm_regs_p->key.raw);
61         writel(UNLOCK_KEY2, &nvm_regs_p->key.raw);
62
63         /* initiate operation */
64         writel(NVM_WR, &nvm_regs_p->ctrl.set);
65 }
66
67 static int flash_wait_till_busy(const char *func, ulong timeout)
68 {
69         int ret = wait_for_bit_le32(&nvm_regs_p->ctrl.raw,
70                                     NVM_WR, false, timeout, false);
71
72         return ret ? ERR_TIMEOUT : ERR_OK;
73 }
74
75 static inline int flash_complete_operation(void)
76 {
77         u32 tmp;
78
79         tmp = readl(&nvm_regs_p->ctrl.raw);
80         if (tmp & NVM_WRERR) {
81                 printf("Error in Block Erase - Lock Bit may be set!\n");
82                 flash_initiate_operation(NVMOP_NOP);
83                 return ERR_PROTECTED;
84         }
85
86         if (tmp & NVM_LVDERR) {
87                 printf("Error in Block Erase - low-vol detected!\n");
88                 flash_initiate_operation(NVMOP_NOP);
89                 return ERR_NOT_ERASED;
90         }
91
92         /* disable flash write or erase operation */
93         writel(NVM_WREN, &nvm_regs_p->ctrl.clr);
94
95         return ERR_OK;
96 }
97
98 /*
99  * Erase flash sectors, returns:
100  * ERR_OK - OK
101  * ERR_INVAL - invalid sector arguments
102  * ERR_TIMEOUT - write timeout
103  * ERR_NOT_ERASED - Flash not erased
104  * ERR_UNKNOWN_FLASH_VENDOR - incorrect flash
105  */
106 int flash_erase(flash_info_t *info, int s_first, int s_last)
107 {
108         ulong sect_start, sect_end, flags;
109         int prot, sect;
110         int rc;
111
112         if ((info->flash_id & FLASH_VENDMASK) != FLASH_MAN_MCHP) {
113                 printf("Can't erase unknown flash type %08lx - aborted\n",
114                        info->flash_id);
115                 return ERR_UNKNOWN_FLASH_VENDOR;
116         }
117
118         if ((s_first < 0) || (s_first > s_last)) {
119                 printf("- no sectors to erase\n");
120                 return ERR_INVAL;
121         }
122
123         prot = 0;
124         for (sect = s_first; sect <= s_last; ++sect) {
125                 if (info->protect[sect])
126                         prot++;
127         }
128
129         if (prot)
130                 printf("- Warning: %d protected sectors will not be erased!\n",
131                        prot);
132         else
133                 printf("\n");
134
135         /* erase on unprotected sectors */
136         for (sect = s_first; sect <= s_last; sect++) {
137                 if (info->protect[sect])
138                         continue;
139
140                 /* disable interrupts */
141                 flags = disable_interrupts();
142
143                 /* write destination page address (physical) */
144                 sect_start = CPHYSADDR(info->start[sect]);
145                 writel(sect_start, &nvm_regs_p->addr.raw);
146
147                 /* page erase */
148                 flash_initiate_operation(NVMOP_PAGE_ERASE);
149
150                 /* wait */
151                 rc = flash_wait_till_busy(__func__,
152                                           CONFIG_SYS_FLASH_ERASE_TOUT);
153
154                 /* re-enable interrupts if necessary */
155                 if (flags)
156                         enable_interrupts();
157
158                 if (rc != ERR_OK)
159                         return rc;
160
161                 rc = flash_complete_operation();
162                 if (rc != ERR_OK)
163                         return rc;
164
165                 /*
166                  * flash content is updated but cache might contain stale
167                  * data, so invalidate dcache.
168                  */
169                 sect_end = info->start[sect] + info->size / info->sector_count;
170                 invalidate_dcache_range(info->start[sect], sect_end);
171         }
172
173         printf(" done\n");
174         return ERR_OK;
175 }
176
177 int page_erase(flash_info_t *info, int sect)
178 {
179         return 0;
180 }
181
182 /* Write a word to flash */
183 static int write_word(flash_info_t *info, ulong dest, ulong word)
184 {
185         ulong flags;
186         int rc;
187
188         /* read flash to check if it is sufficiently erased */
189         if ((readl((void __iomem *)dest) & word) != word) {
190                 printf("Error, Flash not erased!\n");
191                 return ERR_NOT_ERASED;
192         }
193
194         /* disable interrupts */
195         flags = disable_interrupts();
196
197         /* update destination page address (physical) */
198         writel(CPHYSADDR(dest), &nvm_regs_p->addr.raw);
199         writel(word, &nvm_regs_p->data.raw);
200
201         /* word write */
202         flash_initiate_operation(NVMOP_WORD_WRITE);
203
204         /* wait for operation to complete */
205         rc = flash_wait_till_busy(__func__, CONFIG_SYS_FLASH_WRITE_TOUT);
206
207         /* re-enable interrupts if necessary */
208         if (flags)
209                 enable_interrupts();
210
211         if (rc != ERR_OK)
212                 return rc;
213
214         return flash_complete_operation();
215 }
216
217 /*
218  * Copy memory to flash, returns:
219  * ERR_OK - OK
220  * ERR_TIMEOUT - write timeout
221  * ERR_NOT_ERASED - Flash not erased
222  */
223 int write_buff(flash_info_t *info, uchar *src, ulong addr, ulong cnt)
224 {
225         ulong dst, tmp_le, len = cnt;
226         int i, l, rc;
227         uchar *cp;
228
229         /* get lower word aligned address */
230         dst = (addr & ~3);
231
232         /* handle unaligned start bytes */
233         l = addr - dst;
234         if (l != 0) {
235                 tmp_le = 0;
236                 for (i = 0, cp = (uchar *)dst; i < l; ++i, ++cp)
237                         tmp_le |= *cp << (i * 8);
238
239                 for (; (i < 4) && (cnt > 0); ++i, ++src, --cnt, ++cp)
240                         tmp_le |= *src << (i * 8);
241
242                 for (; (cnt == 0) && (i < 4); ++i, ++cp)
243                         tmp_le |= *cp << (i * 8);
244
245                 rc = write_word(info, dst, tmp_le);
246                 if (rc)
247                         goto out;
248
249                 dst += 4;
250         }
251
252         /* handle word aligned part */
253         while (cnt >= 4) {
254                 tmp_le = src[0] | src[1] << 8 | src[2] << 16 | src[3] << 24;
255                 rc = write_word(info, dst, tmp_le);
256                 if (rc)
257                         goto out;
258                 src += 4;
259                 dst += 4;
260                 cnt -= 4;
261         }
262
263         if (cnt == 0) {
264                 rc = ERR_OK;
265                 goto out;
266         }
267
268         /* handle unaligned tail bytes */
269         tmp_le = 0;
270         for (i = 0, cp = (uchar *)dst; (i < 4) && (cnt > 0); ++i, ++cp) {
271                 tmp_le |= *src++ << (i * 8);
272                 --cnt;
273         }
274
275         for (; i < 4; ++i, ++cp)
276                 tmp_le |= *cp << (i * 8);
277
278         rc = write_word(info, dst, tmp_le);
279 out:
280         /*
281          * flash content updated by nvm controller but CPU cache might
282          * have stale data, so invalidate dcache.
283          */
284         invalidate_dcache_range(addr, addr + len);
285
286         printf(" done\n");
287         return rc;
288 }
289
290 void flash_print_info(flash_info_t *info)
291 {
292         int i;
293
294         if (info->flash_id == FLASH_UNKNOWN) {
295                 printf("missing or unknown FLASH type\n");
296                 return;
297         }
298
299         switch (info->flash_id & FLASH_VENDMASK) {
300         case FLASH_MAN_MCHP:
301                 printf("Microchip Technology ");
302                 break;
303         default:
304                 printf("Unknown Vendor ");
305                 break;
306         }
307
308         switch (info->flash_id & FLASH_TYPEMASK) {
309         case FLASH_MCHP100T:
310                 printf("Internal (8 Mbit, 64 x 16k)\n");
311                 break;
312         default:
313                 printf("Unknown Chip Type\n");
314                 break;
315         }
316
317         printf("  Size: %ld MB in %d Sectors\n",
318                info->size >> 20, info->sector_count);
319
320         printf("  Sector Start Addresses:");
321         for (i = 0; i < info->sector_count; ++i) {
322                 if ((i % 5) == 0)
323                         printf("\n   ");
324
325                 printf(" %08lX%s", info->start[i],
326                        info->protect[i] ? " (RO)" : "     ");
327         }
328         printf("\n");
329 }
330
331 unsigned long flash_init(void)
332 {
333         unsigned long size = 0;
334         struct udevice *dev;
335         int bank;
336
337         /* probe every MTD device */
338         for (uclass_first_device(UCLASS_MTD, &dev); dev;
339              uclass_next_device(&dev)) {
340                 /* nop */
341         }
342
343         /* calc total flash size */
344         for (bank = 0; bank < CONFIG_SYS_MAX_FLASH_BANKS; ++bank)
345                 size += flash_info[bank].size;
346
347         return size;
348 }
349
350 static void pic32_flash_bank_init(flash_info_t *info,
351                                   ulong base, ulong size)
352 {
353         ulong sect_size;
354         int sect;
355
356         /* device & manufacturer code */
357         info->flash_id = FLASH_MAN_MCHP | FLASH_MCHP100T;
358         info->sector_count = CONFIG_SYS_MAX_FLASH_SECT;
359         info->size = size;
360
361         /* update sector (i.e page) info */
362         sect_size = info->size / info->sector_count;
363         for (sect = 0; sect < info->sector_count; sect++) {
364                 info->start[sect] = base;
365                 /* protect each sector by default */
366                 info->protect[sect] = 1;
367                 base += sect_size;
368         }
369 }
370
371 static int pic32_flash_probe(struct udevice *dev)
372 {
373         void *blob = (void *)gd->fdt_blob;
374         int node = dev_of_offset(dev);
375         const char *list, *end;
376         const fdt32_t *cell;
377         unsigned long addr, size;
378         int parent, addrc, sizec;
379         flash_info_t *info;
380         int len, idx;
381
382         /*
383          * decode regs. there are multiple reg tuples, and they need to
384          * match with reg-names.
385          */
386         parent = fdt_parent_offset(blob, node);
387         fdt_support_default_count_cells(blob, parent, &addrc, &sizec);
388         list = fdt_getprop(blob, node, "reg-names", &len);
389         if (!list)
390                 return -ENOENT;
391
392         end = list + len;
393         cell = fdt_getprop(blob, node, "reg", &len);
394         if (!cell)
395                 return -ENOENT;
396
397         for (idx = 0, info = &flash_info[0]; list < end;) {
398                 addr = fdt_translate_address((void *)blob, node, cell + idx);
399                 size = fdt_addr_to_cpu(cell[idx + addrc]);
400                 len = strlen(list);
401                 if (!strncmp(list, "nvm", len)) {
402                         /* NVM controller */
403                         nvm_regs_p = ioremap(addr, size);
404                 } else if (!strncmp(list, "bank", 4)) {
405                         /* Flash bank: use kseg0 cached address */
406                         pic32_flash_bank_init(info, CKSEG0ADDR(addr), size);
407                         info++;
408                 }
409                 idx += addrc + sizec;
410                 list += len + 1;
411         }
412
413         /* disable flash write/erase operations */
414         writel(NVM_WREN, &nvm_regs_p->ctrl.clr);
415
416 #if (CONFIG_SYS_MONITOR_BASE >= CONFIG_SYS_FLASH_BASE)
417         /* monitor protection ON by default */
418         flash_protect(FLAG_PROTECT_SET,
419                       CONFIG_SYS_MONITOR_BASE,
420                       CONFIG_SYS_MONITOR_BASE + monitor_flash_len - 1,
421                       &flash_info[0]);
422 #endif
423
424 #ifdef CONFIG_ENV_IS_IN_FLASH
425         /* ENV protection ON by default */
426         flash_protect(FLAG_PROTECT_SET,
427                       CONFIG_ENV_ADDR,
428                       CONFIG_ENV_ADDR + CONFIG_ENV_SECT_SIZE - 1,
429                       &flash_info[0]);
430 #endif
431         return 0;
432 }
433
434 static const struct udevice_id pic32_flash_ids[] = {
435         { .compatible = "microchip,pic32mzda-flash" },
436         {}
437 };
438
439 U_BOOT_DRIVER(pic32_flash) = {
440         .name   = "pic32_flash",
441         .id     = UCLASS_MTD,
442         .of_match = pic32_flash_ids,
443         .probe  = pic32_flash_probe,
444 };