15c990456SPurna Chandra Mandal /* 25c990456SPurna Chandra Mandal * Copyright (C) 2015 35c990456SPurna Chandra Mandal * Cristian Birsan <cristian.birsan@microchip.com> 45c990456SPurna Chandra Mandal * Purna Chandra Mandal <purna.mandal@microchip.com> 55c990456SPurna Chandra Mandal * 65c990456SPurna Chandra Mandal * SPDX-License-Identifier: GPL-2.0+ 75c990456SPurna Chandra Mandal */ 85c990456SPurna Chandra Mandal 95c990456SPurna Chandra Mandal #include <common.h> 105c990456SPurna Chandra Mandal #include <dm.h> 115c990456SPurna Chandra Mandal #include <fdt_support.h> 125c990456SPurna Chandra Mandal #include <flash.h> 135c990456SPurna Chandra Mandal #include <mach/pic32.h> 145c990456SPurna Chandra Mandal #include <wait_bit.h> 155c990456SPurna Chandra Mandal 165c990456SPurna Chandra Mandal DECLARE_GLOBAL_DATA_PTR; 175c990456SPurna Chandra Mandal 185c990456SPurna Chandra Mandal /* NVM Controller registers */ 195c990456SPurna Chandra Mandal struct pic32_reg_nvm { 205c990456SPurna Chandra Mandal struct pic32_reg_atomic ctrl; 215c990456SPurna Chandra Mandal struct pic32_reg_atomic key; 225c990456SPurna Chandra Mandal struct pic32_reg_atomic addr; 235c990456SPurna Chandra Mandal struct pic32_reg_atomic data; 245c990456SPurna Chandra Mandal }; 255c990456SPurna Chandra Mandal 265c990456SPurna Chandra Mandal /* NVM operations */ 275c990456SPurna Chandra Mandal #define NVMOP_NOP 0 285c990456SPurna Chandra Mandal #define NVMOP_WORD_WRITE 1 295c990456SPurna Chandra Mandal #define NVMOP_PAGE_ERASE 4 305c990456SPurna Chandra Mandal 315c990456SPurna Chandra Mandal /* NVM control bits */ 325c990456SPurna Chandra Mandal #define NVM_WR BIT(15) 335c990456SPurna Chandra Mandal #define NVM_WREN BIT(14) 345c990456SPurna Chandra Mandal #define NVM_WRERR BIT(13) 355c990456SPurna Chandra Mandal #define NVM_LVDERR BIT(12) 365c990456SPurna Chandra Mandal 375c990456SPurna Chandra Mandal /* NVM programming unlock register */ 385c990456SPurna Chandra Mandal #define LOCK_KEY 0x0 395c990456SPurna Chandra Mandal #define UNLOCK_KEY1 0xaa996655 405c990456SPurna Chandra Mandal #define UNLOCK_KEY2 0x556699aa 415c990456SPurna Chandra Mandal 425c990456SPurna Chandra Mandal /* 435c990456SPurna Chandra Mandal * PIC32 flash banks consist of number of pages, each page 445c990456SPurna Chandra Mandal * into number of rows and rows into number of words. 455c990456SPurna Chandra Mandal * Here we will maintain page information instead of sector. 465c990456SPurna Chandra Mandal */ 475c990456SPurna Chandra Mandal flash_info_t flash_info[CONFIG_SYS_MAX_FLASH_BANKS]; 485c990456SPurna Chandra Mandal static struct pic32_reg_nvm *nvm_regs_p; 495c990456SPurna Chandra Mandal 505c990456SPurna Chandra Mandal static inline void flash_initiate_operation(u32 nvmop) 515c990456SPurna Chandra Mandal { 525c990456SPurna Chandra Mandal /* set operation */ 535c990456SPurna Chandra Mandal writel(nvmop, &nvm_regs_p->ctrl.raw); 545c990456SPurna Chandra Mandal 555c990456SPurna Chandra Mandal /* enable flash write */ 565c990456SPurna Chandra Mandal writel(NVM_WREN, &nvm_regs_p->ctrl.set); 575c990456SPurna Chandra Mandal 585c990456SPurna Chandra Mandal /* unlock sequence */ 595c990456SPurna Chandra Mandal writel(LOCK_KEY, &nvm_regs_p->key.raw); 605c990456SPurna Chandra Mandal writel(UNLOCK_KEY1, &nvm_regs_p->key.raw); 615c990456SPurna Chandra Mandal writel(UNLOCK_KEY2, &nvm_regs_p->key.raw); 625c990456SPurna Chandra Mandal 635c990456SPurna Chandra Mandal /* initiate operation */ 645c990456SPurna Chandra Mandal writel(NVM_WR, &nvm_regs_p->ctrl.set); 655c990456SPurna Chandra Mandal } 665c990456SPurna Chandra Mandal 675c990456SPurna Chandra Mandal static int flash_wait_till_busy(const char *func, ulong timeout) 685c990456SPurna Chandra Mandal { 695c990456SPurna Chandra Mandal int ret = wait_for_bit(__func__, &nvm_regs_p->ctrl.raw, 705c990456SPurna Chandra Mandal NVM_WR, false, timeout, false); 715c990456SPurna Chandra Mandal 725c990456SPurna Chandra Mandal return ret ? ERR_TIMOUT : ERR_OK; 735c990456SPurna Chandra Mandal } 745c990456SPurna Chandra Mandal 755c990456SPurna Chandra Mandal static inline int flash_complete_operation(void) 765c990456SPurna Chandra Mandal { 775c990456SPurna Chandra Mandal u32 tmp; 785c990456SPurna Chandra Mandal 795c990456SPurna Chandra Mandal tmp = readl(&nvm_regs_p->ctrl.raw); 805c990456SPurna Chandra Mandal if (tmp & NVM_WRERR) { 815c990456SPurna Chandra Mandal printf("Error in Block Erase - Lock Bit may be set!\n"); 825c990456SPurna Chandra Mandal flash_initiate_operation(NVMOP_NOP); 835c990456SPurna Chandra Mandal return ERR_PROTECTED; 845c990456SPurna Chandra Mandal } 855c990456SPurna Chandra Mandal 865c990456SPurna Chandra Mandal if (tmp & NVM_LVDERR) { 875c990456SPurna Chandra Mandal printf("Error in Block Erase - low-vol detected!\n"); 885c990456SPurna Chandra Mandal flash_initiate_operation(NVMOP_NOP); 895c990456SPurna Chandra Mandal return ERR_NOT_ERASED; 905c990456SPurna Chandra Mandal } 915c990456SPurna Chandra Mandal 925c990456SPurna Chandra Mandal /* disable flash write or erase operation */ 935c990456SPurna Chandra Mandal writel(NVM_WREN, &nvm_regs_p->ctrl.clr); 945c990456SPurna Chandra Mandal 955c990456SPurna Chandra Mandal return ERR_OK; 965c990456SPurna Chandra Mandal } 975c990456SPurna Chandra Mandal 985c990456SPurna Chandra Mandal /* 995c990456SPurna Chandra Mandal * Erase flash sectors, returns: 1005c990456SPurna Chandra Mandal * ERR_OK - OK 1015c990456SPurna Chandra Mandal * ERR_INVAL - invalid sector arguments 1025c990456SPurna Chandra Mandal * ERR_TIMOUT - write timeout 1035c990456SPurna Chandra Mandal * ERR_NOT_ERASED - Flash not erased 1045c990456SPurna Chandra Mandal * ERR_UNKNOWN_FLASH_VENDOR - incorrect flash 1055c990456SPurna Chandra Mandal */ 1065c990456SPurna Chandra Mandal int flash_erase(flash_info_t *info, int s_first, int s_last) 1075c990456SPurna Chandra Mandal { 1085c990456SPurna Chandra Mandal ulong sect_start, sect_end, flags; 1095c990456SPurna Chandra Mandal int prot, sect; 1105c990456SPurna Chandra Mandal int rc; 1115c990456SPurna Chandra Mandal 1125c990456SPurna Chandra Mandal if ((info->flash_id & FLASH_VENDMASK) != FLASH_MAN_MCHP) { 1135c990456SPurna Chandra Mandal printf("Can't erase unknown flash type %08lx - aborted\n", 1145c990456SPurna Chandra Mandal info->flash_id); 1155c990456SPurna Chandra Mandal return ERR_UNKNOWN_FLASH_VENDOR; 1165c990456SPurna Chandra Mandal } 1175c990456SPurna Chandra Mandal 1185c990456SPurna Chandra Mandal if ((s_first < 0) || (s_first > s_last)) { 1195c990456SPurna Chandra Mandal printf("- no sectors to erase\n"); 1205c990456SPurna Chandra Mandal return ERR_INVAL; 1215c990456SPurna Chandra Mandal } 1225c990456SPurna Chandra Mandal 1235c990456SPurna Chandra Mandal prot = 0; 1245c990456SPurna Chandra Mandal for (sect = s_first; sect <= s_last; ++sect) { 1255c990456SPurna Chandra Mandal if (info->protect[sect]) 1265c990456SPurna Chandra Mandal prot++; 1275c990456SPurna Chandra Mandal } 1285c990456SPurna Chandra Mandal 1295c990456SPurna Chandra Mandal if (prot) 1305c990456SPurna Chandra Mandal printf("- Warning: %d protected sectors will not be erased!\n", 1315c990456SPurna Chandra Mandal prot); 1325c990456SPurna Chandra Mandal else 1335c990456SPurna Chandra Mandal printf("\n"); 1345c990456SPurna Chandra Mandal 1355c990456SPurna Chandra Mandal /* erase on unprotected sectors */ 1365c990456SPurna Chandra Mandal for (sect = s_first; sect <= s_last; sect++) { 1375c990456SPurna Chandra Mandal if (info->protect[sect]) 1385c990456SPurna Chandra Mandal continue; 1395c990456SPurna Chandra Mandal 1405c990456SPurna Chandra Mandal /* disable interrupts */ 1415c990456SPurna Chandra Mandal flags = disable_interrupts(); 1425c990456SPurna Chandra Mandal 1435c990456SPurna Chandra Mandal /* write destination page address (physical) */ 1445c990456SPurna Chandra Mandal sect_start = CPHYSADDR(info->start[sect]); 1455c990456SPurna Chandra Mandal writel(sect_start, &nvm_regs_p->addr.raw); 1465c990456SPurna Chandra Mandal 1475c990456SPurna Chandra Mandal /* page erase */ 1485c990456SPurna Chandra Mandal flash_initiate_operation(NVMOP_PAGE_ERASE); 1495c990456SPurna Chandra Mandal 1505c990456SPurna Chandra Mandal /* wait */ 1515c990456SPurna Chandra Mandal rc = flash_wait_till_busy(__func__, 1525c990456SPurna Chandra Mandal CONFIG_SYS_FLASH_ERASE_TOUT); 1535c990456SPurna Chandra Mandal 1545c990456SPurna Chandra Mandal /* re-enable interrupts if necessary */ 1555c990456SPurna Chandra Mandal if (flags) 1565c990456SPurna Chandra Mandal enable_interrupts(); 1575c990456SPurna Chandra Mandal 1585c990456SPurna Chandra Mandal if (rc != ERR_OK) 1595c990456SPurna Chandra Mandal return rc; 1605c990456SPurna Chandra Mandal 1615c990456SPurna Chandra Mandal rc = flash_complete_operation(); 1625c990456SPurna Chandra Mandal if (rc != ERR_OK) 1635c990456SPurna Chandra Mandal return rc; 1645c990456SPurna Chandra Mandal 1655c990456SPurna Chandra Mandal /* 1665c990456SPurna Chandra Mandal * flash content is updated but cache might contain stale 1675c990456SPurna Chandra Mandal * data, so invalidate dcache. 1685c990456SPurna Chandra Mandal */ 1695c990456SPurna Chandra Mandal sect_end = info->start[sect] + info->size / info->sector_count; 1705c990456SPurna Chandra Mandal invalidate_dcache_range(info->start[sect], sect_end); 1715c990456SPurna Chandra Mandal } 1725c990456SPurna Chandra Mandal 1735c990456SPurna Chandra Mandal printf(" done\n"); 1745c990456SPurna Chandra Mandal return ERR_OK; 1755c990456SPurna Chandra Mandal } 1765c990456SPurna Chandra Mandal 1775c990456SPurna Chandra Mandal int page_erase(flash_info_t *info, int sect) 1785c990456SPurna Chandra Mandal { 1795c990456SPurna Chandra Mandal return 0; 1805c990456SPurna Chandra Mandal } 1815c990456SPurna Chandra Mandal 1825c990456SPurna Chandra Mandal /* Write a word to flash */ 1835c990456SPurna Chandra Mandal static int write_word(flash_info_t *info, ulong dest, ulong word) 1845c990456SPurna Chandra Mandal { 1855c990456SPurna Chandra Mandal ulong flags; 1865c990456SPurna Chandra Mandal int rc; 1875c990456SPurna Chandra Mandal 1885c990456SPurna Chandra Mandal /* read flash to check if it is sufficiently erased */ 1895c990456SPurna Chandra Mandal if ((readl((void __iomem *)dest) & word) != word) { 1905c990456SPurna Chandra Mandal printf("Error, Flash not erased!\n"); 1915c990456SPurna Chandra Mandal return ERR_NOT_ERASED; 1925c990456SPurna Chandra Mandal } 1935c990456SPurna Chandra Mandal 1945c990456SPurna Chandra Mandal /* disable interrupts */ 1955c990456SPurna Chandra Mandal flags = disable_interrupts(); 1965c990456SPurna Chandra Mandal 1975c990456SPurna Chandra Mandal /* update destination page address (physical) */ 1985c990456SPurna Chandra Mandal writel(CPHYSADDR(dest), &nvm_regs_p->addr.raw); 1995c990456SPurna Chandra Mandal writel(word, &nvm_regs_p->data.raw); 2005c990456SPurna Chandra Mandal 2015c990456SPurna Chandra Mandal /* word write */ 2025c990456SPurna Chandra Mandal flash_initiate_operation(NVMOP_WORD_WRITE); 2035c990456SPurna Chandra Mandal 2045c990456SPurna Chandra Mandal /* wait for operation to complete */ 2055c990456SPurna Chandra Mandal rc = flash_wait_till_busy(__func__, CONFIG_SYS_FLASH_WRITE_TOUT); 2065c990456SPurna Chandra Mandal 2075c990456SPurna Chandra Mandal /* re-enable interrupts if necessary */ 2085c990456SPurna Chandra Mandal if (flags) 2095c990456SPurna Chandra Mandal enable_interrupts(); 2105c990456SPurna Chandra Mandal 2115c990456SPurna Chandra Mandal if (rc != ERR_OK) 2125c990456SPurna Chandra Mandal return rc; 2135c990456SPurna Chandra Mandal 2145c990456SPurna Chandra Mandal return flash_complete_operation(); 2155c990456SPurna Chandra Mandal } 2165c990456SPurna Chandra Mandal 2175c990456SPurna Chandra Mandal /* 2185c990456SPurna Chandra Mandal * Copy memory to flash, returns: 2195c990456SPurna Chandra Mandal * ERR_OK - OK 2205c990456SPurna Chandra Mandal * ERR_TIMOUT - write timeout 2215c990456SPurna Chandra Mandal * ERR_NOT_ERASED - Flash not erased 2225c990456SPurna Chandra Mandal */ 2235c990456SPurna Chandra Mandal int write_buff(flash_info_t *info, uchar *src, ulong addr, ulong cnt) 2245c990456SPurna Chandra Mandal { 2255c990456SPurna Chandra Mandal ulong dst, tmp_le, len = cnt; 2265c990456SPurna Chandra Mandal int i, l, rc; 2275c990456SPurna Chandra Mandal uchar *cp; 2285c990456SPurna Chandra Mandal 2295c990456SPurna Chandra Mandal /* get lower word aligned address */ 2305c990456SPurna Chandra Mandal dst = (addr & ~3); 2315c990456SPurna Chandra Mandal 2325c990456SPurna Chandra Mandal /* handle unaligned start bytes */ 2335c990456SPurna Chandra Mandal l = addr - dst; 2345c990456SPurna Chandra Mandal if (l != 0) { 2355c990456SPurna Chandra Mandal tmp_le = 0; 2365c990456SPurna Chandra Mandal for (i = 0, cp = (uchar *)dst; i < l; ++i, ++cp) 2375c990456SPurna Chandra Mandal tmp_le |= *cp << (i * 8); 2385c990456SPurna Chandra Mandal 2395c990456SPurna Chandra Mandal for (; (i < 4) && (cnt > 0); ++i, ++src, --cnt, ++cp) 2405c990456SPurna Chandra Mandal tmp_le |= *src << (i * 8); 2415c990456SPurna Chandra Mandal 2425c990456SPurna Chandra Mandal for (; (cnt == 0) && (i < 4); ++i, ++cp) 2435c990456SPurna Chandra Mandal tmp_le |= *cp << (i * 8); 2445c990456SPurna Chandra Mandal 2455c990456SPurna Chandra Mandal rc = write_word(info, dst, tmp_le); 2465c990456SPurna Chandra Mandal if (rc) 2475c990456SPurna Chandra Mandal goto out; 2485c990456SPurna Chandra Mandal 2495c990456SPurna Chandra Mandal dst += 4; 2505c990456SPurna Chandra Mandal } 2515c990456SPurna Chandra Mandal 2525c990456SPurna Chandra Mandal /* handle word aligned part */ 2535c990456SPurna Chandra Mandal while (cnt >= 4) { 2545c990456SPurna Chandra Mandal tmp_le = src[0] | src[1] << 8 | src[2] << 16 | src[3] << 24; 2555c990456SPurna Chandra Mandal rc = write_word(info, dst, tmp_le); 2565c990456SPurna Chandra Mandal if (rc) 2575c990456SPurna Chandra Mandal goto out; 2585c990456SPurna Chandra Mandal src += 4; 2595c990456SPurna Chandra Mandal dst += 4; 2605c990456SPurna Chandra Mandal cnt -= 4; 2615c990456SPurna Chandra Mandal } 2625c990456SPurna Chandra Mandal 2635c990456SPurna Chandra Mandal if (cnt == 0) { 2645c990456SPurna Chandra Mandal rc = ERR_OK; 2655c990456SPurna Chandra Mandal goto out; 2665c990456SPurna Chandra Mandal } 2675c990456SPurna Chandra Mandal 2685c990456SPurna Chandra Mandal /* handle unaligned tail bytes */ 2695c990456SPurna Chandra Mandal tmp_le = 0; 2705c990456SPurna Chandra Mandal for (i = 0, cp = (uchar *)dst; (i < 4) && (cnt > 0); ++i, ++cp) { 2715c990456SPurna Chandra Mandal tmp_le |= *src++ << (i * 8); 2725c990456SPurna Chandra Mandal --cnt; 2735c990456SPurna Chandra Mandal } 2745c990456SPurna Chandra Mandal 2755c990456SPurna Chandra Mandal for (; i < 4; ++i, ++cp) 2765c990456SPurna Chandra Mandal tmp_le |= *cp << (i * 8); 2775c990456SPurna Chandra Mandal 2785c990456SPurna Chandra Mandal rc = write_word(info, dst, tmp_le); 2795c990456SPurna Chandra Mandal out: 2805c990456SPurna Chandra Mandal /* 2815c990456SPurna Chandra Mandal * flash content updated by nvm controller but CPU cache might 2825c990456SPurna Chandra Mandal * have stale data, so invalidate dcache. 2835c990456SPurna Chandra Mandal */ 2845c990456SPurna Chandra Mandal invalidate_dcache_range(addr, addr + len); 2855c990456SPurna Chandra Mandal 2865c990456SPurna Chandra Mandal printf(" done\n"); 2875c990456SPurna Chandra Mandal return rc; 2885c990456SPurna Chandra Mandal } 2895c990456SPurna Chandra Mandal 2905c990456SPurna Chandra Mandal void flash_print_info(flash_info_t *info) 2915c990456SPurna Chandra Mandal { 2925c990456SPurna Chandra Mandal int i; 2935c990456SPurna Chandra Mandal 2945c990456SPurna Chandra Mandal if (info->flash_id == FLASH_UNKNOWN) { 2955c990456SPurna Chandra Mandal printf("missing or unknown FLASH type\n"); 2965c990456SPurna Chandra Mandal return; 2975c990456SPurna Chandra Mandal } 2985c990456SPurna Chandra Mandal 2995c990456SPurna Chandra Mandal switch (info->flash_id & FLASH_VENDMASK) { 3005c990456SPurna Chandra Mandal case FLASH_MAN_MCHP: 3015c990456SPurna Chandra Mandal printf("Microchip Technology "); 3025c990456SPurna Chandra Mandal break; 3035c990456SPurna Chandra Mandal default: 3045c990456SPurna Chandra Mandal printf("Unknown Vendor "); 3055c990456SPurna Chandra Mandal break; 3065c990456SPurna Chandra Mandal } 3075c990456SPurna Chandra Mandal 3085c990456SPurna Chandra Mandal switch (info->flash_id & FLASH_TYPEMASK) { 3095c990456SPurna Chandra Mandal case FLASH_MCHP100T: 3105c990456SPurna Chandra Mandal printf("Internal (8 Mbit, 64 x 16k)\n"); 3115c990456SPurna Chandra Mandal break; 3125c990456SPurna Chandra Mandal default: 3135c990456SPurna Chandra Mandal printf("Unknown Chip Type\n"); 3145c990456SPurna Chandra Mandal break; 3155c990456SPurna Chandra Mandal } 3165c990456SPurna Chandra Mandal 3175c990456SPurna Chandra Mandal printf(" Size: %ld MB in %d Sectors\n", 3185c990456SPurna Chandra Mandal info->size >> 20, info->sector_count); 3195c990456SPurna Chandra Mandal 3205c990456SPurna Chandra Mandal printf(" Sector Start Addresses:"); 3215c990456SPurna Chandra Mandal for (i = 0; i < info->sector_count; ++i) { 3225c990456SPurna Chandra Mandal if ((i % 5) == 0) 3235c990456SPurna Chandra Mandal printf("\n "); 3245c990456SPurna Chandra Mandal 3255c990456SPurna Chandra Mandal printf(" %08lX%s", info->start[i], 3265c990456SPurna Chandra Mandal info->protect[i] ? " (RO)" : " "); 3275c990456SPurna Chandra Mandal } 3285c990456SPurna Chandra Mandal printf("\n"); 3295c990456SPurna Chandra Mandal } 3305c990456SPurna Chandra Mandal 3315c990456SPurna Chandra Mandal unsigned long flash_init(void) 3325c990456SPurna Chandra Mandal { 3335c990456SPurna Chandra Mandal unsigned long size = 0; 3345c990456SPurna Chandra Mandal struct udevice *dev; 3355c990456SPurna Chandra Mandal int bank; 3365c990456SPurna Chandra Mandal 3375c990456SPurna Chandra Mandal /* probe every MTD device */ 3385c990456SPurna Chandra Mandal for (uclass_first_device(UCLASS_MTD, &dev); dev; 3395c990456SPurna Chandra Mandal uclass_next_device(&dev)) { 3405c990456SPurna Chandra Mandal /* nop */ 3415c990456SPurna Chandra Mandal } 3425c990456SPurna Chandra Mandal 3435c990456SPurna Chandra Mandal /* calc total flash size */ 3445c990456SPurna Chandra Mandal for (bank = 0; bank < CONFIG_SYS_MAX_FLASH_BANKS; ++bank) 3455c990456SPurna Chandra Mandal size += flash_info[bank].size; 3465c990456SPurna Chandra Mandal 3475c990456SPurna Chandra Mandal return size; 3485c990456SPurna Chandra Mandal } 3495c990456SPurna Chandra Mandal 3505c990456SPurna Chandra Mandal static void pic32_flash_bank_init(flash_info_t *info, 3515c990456SPurna Chandra Mandal ulong base, ulong size) 3525c990456SPurna Chandra Mandal { 3535c990456SPurna Chandra Mandal ulong sect_size; 3545c990456SPurna Chandra Mandal int sect; 3555c990456SPurna Chandra Mandal 3565c990456SPurna Chandra Mandal /* device & manufacturer code */ 3575c990456SPurna Chandra Mandal info->flash_id = FLASH_MAN_MCHP | FLASH_MCHP100T; 3585c990456SPurna Chandra Mandal info->sector_count = CONFIG_SYS_MAX_FLASH_SECT; 3595c990456SPurna Chandra Mandal info->size = size; 3605c990456SPurna Chandra Mandal 3615c990456SPurna Chandra Mandal /* update sector (i.e page) info */ 3625c990456SPurna Chandra Mandal sect_size = info->size / info->sector_count; 3635c990456SPurna Chandra Mandal for (sect = 0; sect < info->sector_count; sect++) { 3645c990456SPurna Chandra Mandal info->start[sect] = base; 3655c990456SPurna Chandra Mandal /* protect each sector by default */ 3665c990456SPurna Chandra Mandal info->protect[sect] = 1; 3675c990456SPurna Chandra Mandal base += sect_size; 3685c990456SPurna Chandra Mandal } 3695c990456SPurna Chandra Mandal } 3705c990456SPurna Chandra Mandal 3715c990456SPurna Chandra Mandal static int pic32_flash_probe(struct udevice *dev) 3725c990456SPurna Chandra Mandal { 3735c990456SPurna Chandra Mandal void *blob = (void *)gd->fdt_blob; 374e160f7d4SSimon Glass int node = dev_of_offset(dev); 3755c990456SPurna Chandra Mandal const char *list, *end; 3765c990456SPurna Chandra Mandal const fdt32_t *cell; 3775c990456SPurna Chandra Mandal unsigned long addr, size; 3785c990456SPurna Chandra Mandal int parent, addrc, sizec; 3795c990456SPurna Chandra Mandal flash_info_t *info; 3805c990456SPurna Chandra Mandal int len, idx; 3815c990456SPurna Chandra Mandal 3825c990456SPurna Chandra Mandal /* 3835c990456SPurna Chandra Mandal * decode regs. there are multiple reg tuples, and they need to 3845c990456SPurna Chandra Mandal * match with reg-names. 3855c990456SPurna Chandra Mandal */ 3865c990456SPurna Chandra Mandal parent = fdt_parent_offset(blob, node); 387*eed36609SSimon Glass fdt_support_default_count_cells(blob, parent, &addrc, &sizec); 3885c990456SPurna Chandra Mandal list = fdt_getprop(blob, node, "reg-names", &len); 3895c990456SPurna Chandra Mandal if (!list) 3905c990456SPurna Chandra Mandal return -ENOENT; 3915c990456SPurna Chandra Mandal 3925c990456SPurna Chandra Mandal end = list + len; 3935c990456SPurna Chandra Mandal cell = fdt_getprop(blob, node, "reg", &len); 3945c990456SPurna Chandra Mandal if (!cell) 3955c990456SPurna Chandra Mandal return -ENOENT; 3965c990456SPurna Chandra Mandal 3975c990456SPurna Chandra Mandal for (idx = 0, info = &flash_info[0]; list < end;) { 3985c990456SPurna Chandra Mandal addr = fdt_translate_address((void *)blob, node, cell + idx); 3995c990456SPurna Chandra Mandal size = fdt_addr_to_cpu(cell[idx + addrc]); 4005c990456SPurna Chandra Mandal len = strlen(list); 4015c990456SPurna Chandra Mandal if (!strncmp(list, "nvm", len)) { 4025c990456SPurna Chandra Mandal /* NVM controller */ 4035c990456SPurna Chandra Mandal nvm_regs_p = ioremap(addr, size); 4045c990456SPurna Chandra Mandal } else if (!strncmp(list, "bank", 4)) { 4055c990456SPurna Chandra Mandal /* Flash bank: use kseg0 cached address */ 4065c990456SPurna Chandra Mandal pic32_flash_bank_init(info, CKSEG0ADDR(addr), size); 4075c990456SPurna Chandra Mandal info++; 4085c990456SPurna Chandra Mandal } 4095c990456SPurna Chandra Mandal idx += addrc + sizec; 4105c990456SPurna Chandra Mandal list += len + 1; 4115c990456SPurna Chandra Mandal } 4125c990456SPurna Chandra Mandal 4135c990456SPurna Chandra Mandal /* disable flash write/erase operations */ 4145c990456SPurna Chandra Mandal writel(NVM_WREN, &nvm_regs_p->ctrl.clr); 4155c990456SPurna Chandra Mandal 4165c990456SPurna Chandra Mandal #if (CONFIG_SYS_MONITOR_BASE >= CONFIG_SYS_FLASH_BASE) 4175c990456SPurna Chandra Mandal /* monitor protection ON by default */ 4185c990456SPurna Chandra Mandal flash_protect(FLAG_PROTECT_SET, 4195c990456SPurna Chandra Mandal CONFIG_SYS_MONITOR_BASE, 4205c990456SPurna Chandra Mandal CONFIG_SYS_MONITOR_BASE + monitor_flash_len - 1, 4215c990456SPurna Chandra Mandal &flash_info[0]); 4225c990456SPurna Chandra Mandal #endif 4235c990456SPurna Chandra Mandal 4245c990456SPurna Chandra Mandal #ifdef CONFIG_ENV_IS_IN_FLASH 4255c990456SPurna Chandra Mandal /* ENV protection ON by default */ 4265c990456SPurna Chandra Mandal flash_protect(FLAG_PROTECT_SET, 4275c990456SPurna Chandra Mandal CONFIG_ENV_ADDR, 4285c990456SPurna Chandra Mandal CONFIG_ENV_ADDR + CONFIG_ENV_SECT_SIZE - 1, 4295c990456SPurna Chandra Mandal &flash_info[0]); 4305c990456SPurna Chandra Mandal #endif 4315c990456SPurna Chandra Mandal return 0; 4325c990456SPurna Chandra Mandal } 4335c990456SPurna Chandra Mandal 4345c990456SPurna Chandra Mandal static const struct udevice_id pic32_flash_ids[] = { 4355c990456SPurna Chandra Mandal { .compatible = "microchip,pic32mzda-flash" }, 4365c990456SPurna Chandra Mandal {} 4375c990456SPurna Chandra Mandal }; 4385c990456SPurna Chandra Mandal 4395c990456SPurna Chandra Mandal U_BOOT_DRIVER(pic32_flash) = { 4405c990456SPurna Chandra Mandal .name = "pic32_flash", 4415c990456SPurna Chandra Mandal .id = UCLASS_MTD, 4425c990456SPurna Chandra Mandal .of_match = pic32_flash_ids, 4435c990456SPurna Chandra Mandal .probe = pic32_flash_probe, 4445c990456SPurna Chandra Mandal }; 445