X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;ds=sidebyside;f=drivers%2Fmtd%2Fcfi_flash.c;h=a389cd101c2f55e62ca8ab90efaf395234d98713;hb=968294bd7b9b540f53c1fb3c809da464623a4362;hp=cf10b0d4ca4af366ab2576aae41c77bf4a258225;hpb=0c669fd17a9d8452f70369474925a91139e3005d;p=u-boot diff --git a/drivers/mtd/cfi_flash.c b/drivers/mtd/cfi_flash.c index cf10b0d4ca..a389cd101c 100644 --- a/drivers/mtd/cfi_flash.c +++ b/drivers/mtd/cfi_flash.c @@ -11,24 +11,7 @@ * Copyright (C) 2006 * Tolunay Orkun * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - * + * SPDX-License-Identifier: GPL-2.0+ */ /* The DEBUG define must be before common to enable debugging */ @@ -38,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -183,16 +167,16 @@ u64 flash_read64(void *addr)__attribute__((weak, alias("__flash_read64"))); flash_info_t *flash_get_info(ulong base) { int i; - flash_info_t *info = NULL; + flash_info_t *info; for (i = 0; i < CONFIG_SYS_MAX_FLASH_BANKS; i++) { - info = & flash_info[i]; + info = &flash_info[i]; if (info->size && info->start[0] <= base && base <= info->start[0] + info->size - 1) - break; + return info; } - return info; + return NULL; } #endif @@ -210,11 +194,9 @@ unsigned long flash_sector_size(flash_info_t *info, flash_sect_t sect) static inline void * flash_map (flash_info_t * info, flash_sect_t sect, uint offset) { - unsigned int byte_offset = offset * info->portwidth / info->chipwidth; - unsigned int addr = (info->start[sect] + byte_offset); - unsigned int mask = 0xffffffff << (info->portwidth - 1); + unsigned int byte_offset = offset * info->portwidth; - return (void *)(uintptr_t)(addr & mask); + return (void *)(info->start[sect] + byte_offset); } static inline void flash_unmap(flash_info_t *info, flash_sect_t sect, @@ -400,8 +382,6 @@ void flash_write_cmd (flash_info_t * info, flash_sect_t sect, #endif flash_write64(cword.ll, addr); break; - default: - printf("fwc: Unknown port width %d\n", info->portwidth); } /* Ensure all the instructions are fully finished */ @@ -589,6 +569,7 @@ static int flash_status_check (flash_info_t * info, flash_sect_t sector, prompt, info->start[sector], flash_read_long (info, sector, 0)); flash_write_cmd (info, sector, 0, info->cmd_reset); + udelay(1); return ERR_TIMOUT; } udelay (1); /* also triggers watchdog */ @@ -756,8 +737,12 @@ static void flash_add_byte (flash_info_t * info, cfiword_t * cword, uchar c) static flash_sect_t find_sector (flash_info_t * info, ulong addr) { static flash_sect_t saved_sector; /* previously found sector */ + static flash_info_t *saved_info; /* previously used flash bank */ flash_sect_t sector = saved_sector; + if ((info != saved_info) || (sector >= info->sector_count)) + sector = 0; + while ((info->start[sector] < addr) && (sector < info->sector_count - 1)) sector++; @@ -769,6 +754,7 @@ static flash_sect_t find_sector (flash_info_t * info, ulong addr) sector--; saved_sector = sector; + saved_info = info; return sector; } @@ -785,15 +771,12 @@ static int flash_write_cfiword (flash_info_t * info, ulong dest, /* Check if Flash is (sufficiently) erased */ switch (info->portwidth) { case FLASH_CFI_8BIT: - debug("%s: 8-bit 0x%02x\n", __func__, cword.c); flag = ((flash_read8(dstaddr) & cword.c) == cword.c); break; case FLASH_CFI_16BIT: - debug("%s: 16-bit 0x%04x\n", __func__, cword.w); flag = ((flash_read16(dstaddr) & cword.w) == cword.w); break; case FLASH_CFI_32BIT: - debug("%s: 32-bit 0x%08lx\n", __func__, cword.l); flag = ((flash_read32(dstaddr) & cword.l) == cword.l); break; case FLASH_CFI_64BIT: @@ -1054,8 +1037,6 @@ int flash_erase (flash_info_t * info, int s_first, int s_last) flash_sect_t sect; int st; - debug("%s: erasing sectors %d to %d\n", __func__, s_first, s_last); - if (info->flash_id != FLASH_MAN_CFI) { puts ("Can't erase unknown flash type - aborted\n"); return 1; @@ -1165,9 +1146,6 @@ int flash_erase (flash_info_t * info, int s_first, int s_last) rcode = 1; else if (flash_verbose) putc ('.'); - } else { - debug("\nSector %d is protected.\n", - info->protect[sect]); } } @@ -1646,9 +1624,10 @@ static void cfi_reverse_geometry(struct cfi_qry *qry) u32 tmp; for (i = 0, j = qry->num_erase_regions - 1; i < j; i++, j--) { - tmp = qry->erase_region_info[i]; - qry->erase_region_info[i] = qry->erase_region_info[j]; - qry->erase_region_info[j] = tmp; + tmp = get_unaligned(&(qry->erase_region_info[i])); + put_unaligned(get_unaligned(&(qry->erase_region_info[j])), + &(qry->erase_region_info[i])); + put_unaligned(tmp, &(qry->erase_region_info[j])); } } @@ -1801,7 +1780,7 @@ static int flash_detect_legacy(phys_addr_t base, int banknum) }; int i; - for (i = 0; i < sizeof(modes) / sizeof(modes[0]); i++) { + for (i = 0; i < ARRAY_SIZE(modes); i++) { info->vendor = modes[i]; info->start[0] = (ulong)map_physmem(base, @@ -1824,7 +1803,7 @@ static int flash_detect_legacy(phys_addr_t base, int banknum) break; else unmap_physmem((void *)info->start[0], - MAP_NOCACHE); + info->portwidth); } } @@ -1863,7 +1842,7 @@ static void flash_read_cfi (flash_info_t *info, void *buf, unsigned int i; for (i = 0; i < len; i++) - p[i] = flash_read_uchar(info, start + (i * 2)); + p[i] = flash_read_uchar(info, start + i); } static void __flash_cmd_reset(flash_info_t *info) @@ -1884,40 +1863,20 @@ static int __flash_detect_cfi (flash_info_t * info, struct cfi_qry *qry) { int cfi_offset; - for (cfi_offset=0; - cfi_offset < sizeof(flash_offset_cfi) / sizeof(uint); + /* Issue FLASH reset command */ + flash_cmd_reset(info); + + for (cfi_offset = 0; cfi_offset < ARRAY_SIZE(flash_offset_cfi); cfi_offset++) { - /* Issue FLASH reset command */ - flash_cmd_reset(info); flash_write_cmd (info, 0, flash_offset_cfi[cfi_offset], FLASH_CMD_CFI); - if (flash_isequal(info, 0, FLASH_OFFSET_CFI_RESP, 'Q') && - flash_isequal(info, 0, - FLASH_OFFSET_CFI_RESP + 2, 'R') && - flash_isequal(info, 0, - FLASH_OFFSET_CFI_RESP + 4, 'Y')) { + if (flash_isequal (info, 0, FLASH_OFFSET_CFI_RESP, 'Q') + && flash_isequal (info, 0, FLASH_OFFSET_CFI_RESP + 1, 'R') + && flash_isequal (info, 0, FLASH_OFFSET_CFI_RESP + 2, 'Y')) { flash_read_cfi(info, qry, FLASH_OFFSET_CFI_RESP, sizeof(struct cfi_qry)); -#ifdef CONFIG_SYS_FLASH_INTERFACE_WIDTH - info->interface = CONFIG_SYS_FLASH_INTERFACE_WIDTH; -#else info->interface = le16_to_cpu(qry->interface_desc); - /* Some flash chips can support multiple bus widths. - * In this case, override the interface width and - * limit it to the port width. - */ - if ((info->interface == FLASH_CFI_X8X16) && - (info->portwidth == FLASH_CFI_8BIT)) { - debug("Overriding 16-bit interface" - " width to 8-bit port width.\n"); - info->interface = FLASH_CFI_X8; - } else if ((info->interface == FLASH_CFI_X16X32) && - (info->portwidth == FLASH_CFI_16BIT)) { - debug("Overriding 16-bit interface" - " width to 16-bit port width.\n"); - info->interface = FLASH_CFI_X16; - } -#endif + info->cfi_offset = flash_offset_cfi[cfi_offset]; debug ("device interface is %d\n", info->interface); @@ -1928,8 +1887,8 @@ static int __flash_detect_cfi (flash_info_t * info, struct cfi_qry *qry) info->chipwidth << CFI_FLASH_SHIFT_WIDTH); /* calculate command offsets as in the Linux driver */ - info->addr_unlock1 = 0xaaa; - info->addr_unlock2 = 0x555; + info->addr_unlock1 = 0x555; + info->addr_unlock2 = 0x2aa; /* * modify the unlock address if we are @@ -1963,12 +1922,8 @@ static int flash_detect_cfi (flash_info_t * info, struct cfi_qry *qry) for (info->chipwidth = FLASH_CFI_BY8; info->chipwidth <= info->portwidth; info->chipwidth <<= 1) - if (__flash_detect_cfi(info, qry)) { - debug("Found CFI flash, portwidth %d," - " chipwidth %d\n", - info->portwidth, info->chipwidth); + if (__flash_detect_cfi(info, qry)) return 1; - } } debug ("not found\n"); return 0; @@ -1987,7 +1942,7 @@ static void flash_fixup_amd(flash_info_t *info, struct cfi_qry *qry) /* CFI < 1.1, try to guess from device id */ if ((info->device_id & 0x80) != 0) cfi_reverse_geometry(qry); - } else if (flash_read_uchar(info, info->ext_addr + 0x1e) == 3) { + } else if (flash_read_uchar(info, info->ext_addr + 0xf) == 3) { /* CFI >= 1.1, deduct from top/bottom flag */ /* note: ext_addr is valid since cfi_version > 0 */ cfi_reverse_geometry(qry); @@ -2102,16 +2057,15 @@ ulong flash_get_size (phys_addr_t base, int banknum) info->start[0] = (ulong)map_physmem(base, info->portwidth, MAP_NOCACHE); if (flash_detect_cfi (info, &qry)) { - info->vendor = le16_to_cpu(qry.p_id); - info->ext_addr = le16_to_cpu(qry.p_adr) * 2; - debug("extended address is 0x%x\n", info->ext_addr); + info->vendor = le16_to_cpu(get_unaligned(&(qry.p_id))); + info->ext_addr = le16_to_cpu(get_unaligned(&(qry.p_adr))); num_erase_regions = qry.num_erase_regions; if (info->ext_addr) { info->cfi_version = (ushort) flash_read_uchar (info, - info->ext_addr + 6) << 8; + info->ext_addr + 3) << 8; info->cfi_version |= (ushort) flash_read_uchar (info, - info->ext_addr + 8); + info->ext_addr + 4); } #ifdef DEBUG @@ -2165,8 +2119,6 @@ ulong flash_get_size (phys_addr_t base, int banknum) debug ("device id is 0x%x\n", info->device_id); debug ("device id2 is 0x%x\n", info->device_id2); debug ("cfi version is 0x%04x\n", info->cfi_version); - debug("port width: %d, chipwidth: %d, interface: %d\n", - info->portwidth, info->chipwidth, info->interface); size_ratio = info->portwidth / info->chipwidth; /* if the chip is x8/x16 reduce the ratio by half */ @@ -2195,7 +2147,8 @@ ulong flash_get_size (phys_addr_t base, int banknum) break; } - tmp = le32_to_cpu(qry.erase_region_info[i]); + tmp = le32_to_cpu(get_unaligned( + &(qry.erase_region_info[i]))); debug("erase region %u: 0x%08lx\n", i, tmp); erase_region_count = (tmp & 0xffff) + 1; @@ -2365,7 +2318,7 @@ void flash_protect_default(void) #endif #if defined(CONFIG_SYS_FLASH_AUTOPROTECT_LIST) - for (i = 0; i < (sizeof(apl) / sizeof(struct apl_s)); i++) { + for (i = 0; i < ARRAY_SIZE(apl); i++) { debug("autoprotecting from %08lx to %08lx\n", apl[i].start, apl[i].start + apl[i].size - 1); flash_protect(FLAG_PROTECT_SET,