+// SPDX-License-Identifier: GPL-2.0+
/*
* (C) Copyright 2002-2004
* Brad Kemp, Seranoa Networks, Brad.Kemp@seranoa.com
*
* Copyright (C) 2006
* Tolunay Orkun <listmember@orkun.us>
- *
- * SPDX-License-Identifier: GPL-2.0+
*/
/* The DEBUG define must be before common to enable debugging */
#include <common.h>
#include <console.h>
#include <dm.h>
+#include <env.h>
#include <errno.h>
#include <fdt_support.h>
+#include <flash.h>
+#include <init.h>
+#include <irq_func.h>
+#include <log.h>
+#include <asm/global_data.h>
#include <asm/processor.h>
#include <asm/io.h>
#include <asm/byteorder.h>
#include <asm/unaligned.h>
-#include <environment.h>
+#include <env_internal.h>
+#include <linux/delay.h>
#include <mtd/cfi_flash.h>
#include <watchdog.h>
flash_info_t flash_info[CFI_MAX_FLASH_BANKS]; /* FLASH chips info */
-/*
- * Check if chip width is defined. If not, start detecting with 8bit.
- */
-#ifndef CONFIG_SYS_FLASH_CFI_WIDTH
-#define CONFIG_SYS_FLASH_CFI_WIDTH FLASH_CFI_8BIT
-#endif
-
#ifdef CONFIG_CFI_FLASH_USE_WEAK_ACCESSORS
#define __maybe_weak __weak
#else
}
#if defined(CONFIG_SYS_MAX_FLASH_BANKS_DETECT)
-int cfi_flash_num_flash_banks = CONFIG_SYS_MAX_FLASH_BANKS_DETECT;
+int cfi_flash_num_flash_banks = CFI_MAX_FLASH_BANKS;
#else
int cfi_flash_num_flash_banks;
#endif
/*-----------------------------------------------------------------------
*/
#if defined(CONFIG_ENV_IS_IN_FLASH) || defined(CONFIG_ENV_ADDR_REDUND) || \
- (CONFIG_SYS_MONITOR_BASE >= CONFIG_SYS_FLASH_BASE)
+ (defined(CONFIG_SYS_MONITOR_BASE) && \
+ (CONFIG_SYS_MONITOR_BASE >= CONFIG_SYS_FLASH_BASE))
static flash_info_t *flash_get_info(ulong base)
{
int i;
flash_info_t *info;
- for (i = 0; i < CONFIG_SYS_MAX_FLASH_BANKS; i++) {
+ for (i = 0; i < CFI_FLASH_BANKS; i++) {
info = &flash_info[i];
if (info->size && info->start[0] <= base &&
base <= info->start[0] + info->size - 1)
{
unsigned int byte_offset = offset * info->portwidth;
- return (void *)(info->start[sect] + byte_offset);
+ return (void *)(info->start[sect] + (byte_offset << info->chip_lsb));
}
static inline void flash_unmap(flash_info_t *info, flash_sect_t sect,
flash_read_cfi(info, qry, FLASH_OFFSET_CFI_RESP,
sizeof(struct cfi_qry));
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;
+ }
info->cfi_offset = flash_offset_cfi[cfi_offset];
debug("device interface is %d\n",
info->interface);
- debug("found port %d chip %d ",
- info->portwidth, info->chipwidth);
+ debug("found port %d chip %d chip_lsb %d ",
+ info->portwidth, info->chipwidth, info->chip_lsb);
debug("port %d bits chip %d bits\n",
info->portwidth << CFI_FLASH_SHIFT_WIDTH,
info->chipwidth << CFI_FLASH_SHIFT_WIDTH);
info->portwidth <= FLASH_CFI_64BIT; info->portwidth <<= 1) {
for (info->chipwidth = FLASH_CFI_BY8;
info->chipwidth <= info->portwidth;
- info->chipwidth <<= 1)
+ info->chipwidth <<= 1) {
+ /*
+ * First, try detection without shifting the addresses
+ * for 8bit devices (16bit wide connection)
+ */
+ info->chip_lsb = 0;
if (__flash_detect_cfi(info, qry))
return 1;
+
+ /*
+ * Not detected, so let's try with shifting
+ * for 8bit devices
+ */
+ info->chip_lsb = 1;
+ if (__flash_detect_cfi(info, qry))
+ return 1;
+ }
}
debug("not found\n");
return 0;
flash_unlock_seq(info, 0);
flash_write_cmd(info, 0,
info->addr_unlock1,
- FLASH_CMD_READ_ID);
+ AMD_CMD_SET_PPB_ENTRY);
info->protect[sect_cnt] =
- flash_isset(
- info, sect_cnt,
- FLASH_OFFSET_PROTECT,
- FLASH_STATUS_PROTECT);
+ !flash_isset(info, sect_cnt,
+ 0, 0x01);
+ flash_write_cmd(info, 0, 0,
+ info->cmd_reset);
break;
default:
/* default: not protected */
#endif
/* Monitor protection ON by default */
-#if (CONFIG_SYS_MONITOR_BASE >= CONFIG_SYS_FLASH_BASE) && \
+#if defined(CONFIG_SYS_MONITOR_BASE) && \
+ (CONFIG_SYS_MONITOR_BASE >= CONFIG_SYS_FLASH_BASE) && \
(!defined(CONFIG_MONITOR_IS_IN_RAM))
flash_protect(FLAG_PROTECT_SET,
CONFIG_SYS_MONITOR_BASE,
#endif
/* Init: no FLASHes known */
- for (i = 0; i < CONFIG_SYS_MAX_FLASH_BANKS; ++i) {
+ for (i = 0; i < CFI_FLASH_BANKS; ++i) {
flash_info[i].flash_id = FLASH_UNKNOWN;
/* Optionally write flash configuration register */
#ifdef CONFIG_CFI_FLASH /* for driver model */
static int cfi_flash_probe(struct udevice *dev)
{
- void *blob = (void *)gd->fdt_blob;
- int node = dev_of_offset(dev);
- const fdt32_t *cell;
- phys_addr_t addr;
- int parent, addrc, sizec;
- int len, idx;
-
- parent = fdt_parent_offset(blob, node);
- fdt_support_default_count_cells(blob, parent, &addrc, &sizec);
- /* decode regs, there may be multiple reg tuples. */
- cell = fdt_getprop(blob, node, "reg", &len);
- if (!cell)
- return -ENOENT;
- idx = 0;
- len /= sizeof(fdt32_t);
- while (idx < len) {
- addr = fdt_translate_address((void *)blob,
- node, cell + idx);
+ fdt_addr_t addr;
+ int idx;
+
+ for (idx = 0; idx < CFI_MAX_FLASH_BANKS; idx++) {
+ addr = dev_read_addr_index(dev, idx);
+ if (addr == FDT_ADDR_T_NONE)
+ break;
+
flash_info[cfi_flash_num_flash_banks].dev = dev;
flash_info[cfi_flash_num_flash_banks].base = addr;
cfi_flash_num_flash_banks++;
- idx += addrc + sizec;
}
gd->bd->bi_flashstart = flash_info[0].base;