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