1
0
mirror of https://xff.cz/git/u-boot/ synced 2025-09-04 10:12:14 +02:00
- Use IS_ENABLED to prevent ifdef in board_key_check for STM32MP
  - Add STM32 FMC2 EBI controller driver
  - Fix dwc3-sti-glue which allows STiH410-B2260 to boot again
  - Add fitImage its entry for 587-200 DHCOR SoM
  - Add both PDK2 and DRC02 DT into DHCOM fitImage its
  - Fix DHCOM KS8851 ethernet MAC address
  - Remove stm32mp1 board.c file
  - Use const for struct node_info in board stm32mp1.c file
This commit is contained in:
Tom Rini
2020-08-13 08:11:27 -04:00
20 changed files with 1628 additions and 520 deletions

View File

@@ -1328,23 +1328,38 @@
dma-requests = <48>; dma-requests = <48>;
}; };
fmc: nand-controller@58002000 { fmc: memory-controller@58002000 {
compatible = "st,stm32mp15-fmc2"; #address-cells = <2>;
reg = <0x58002000 0x1000>, #size-cells = <1>;
<0x80000000 0x1000>, compatible = "st,stm32mp1-fmc2-ebi";
<0x88010000 0x1000>, reg = <0x58002000 0x1000>;
<0x88020000 0x1000>,
<0x81000000 0x1000>,
<0x89010000 0x1000>,
<0x89020000 0x1000>;
interrupts = <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>;
dmas = <&mdma1 20 0x10 0x12000a02 0x0 0x0>,
<&mdma1 20 0x10 0x12000a08 0x0 0x0>,
<&mdma1 21 0x10 0x12000a0a 0x0 0x0>;
dma-names = "tx", "rx", "ecc";
clocks = <&rcc FMC_K>; clocks = <&rcc FMC_K>;
resets = <&rcc FMC_R>; resets = <&rcc FMC_R>;
status = "disabled"; status = "disabled";
ranges = <0 0 0x60000000 0x04000000>, /* EBI CS 1 */
<1 0 0x64000000 0x04000000>, /* EBI CS 2 */
<2 0 0x68000000 0x04000000>, /* EBI CS 3 */
<3 0 0x6c000000 0x04000000>, /* EBI CS 4 */
<4 0 0x80000000 0x10000000>; /* NAND */
nand-controller@4,0 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "st,stm32mp1-fmc2-nfc";
reg = <4 0x00000000 0x1000>,
<4 0x08010000 0x1000>,
<4 0x08020000 0x1000>,
<4 0x01000000 0x1000>,
<4 0x09010000 0x1000>,
<4 0x09020000 0x1000>;
interrupts = <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>;
dmas = <&mdma1 20 0x2 0x12000a02 0x0 0x0>,
<&mdma1 20 0x2 0x12000a08 0x0 0x0>,
<&mdma1 21 0x2 0x12000a0a 0x0 0x0>;
dma-names = "tx", "rx", "ecc";
status = "disabled";
};
}; };
qspi: spi@58003000 { qspi: spi@58003000 {

View File

@@ -157,14 +157,16 @@
pinctrl-0 = <&fmc_pins_a>; pinctrl-0 = <&fmc_pins_a>;
pinctrl-1 = <&fmc_sleep_pins_a>; pinctrl-1 = <&fmc_sleep_pins_a>;
status = "okay"; status = "okay";
#address-cells = <1>;
#size-cells = <0>;
nand@0 { nand-controller@4,0 {
reg = <0>; status = "okay";
nand-on-flash-bbt;
#address-cells = <1>; nand@0 {
#size-cells = <1>; reg = <0>;
nand-on-flash-bbt;
#address-cells = <1>;
#size-cells = <1>;
};
}; };
}; };

View File

@@ -18,6 +18,7 @@
mmc1 = &sdmmc2; mmc1 = &sdmmc2;
spi0 = &qspi; spi0 = &qspi;
usb0 = &usbotg_hs; usb0 = &usbotg_hs;
ethernet1 = &ksz8851;
}; };
config { config {

View File

@@ -74,7 +74,6 @@ static bool bsec_read_lock(u32 address, u32 otp)
return !!(readl(address + bank) & bit); return !!(readl(address + bank) & bit);
} }
#ifndef CONFIG_TFABOOT
/** /**
* bsec_check_error() - Check status of one otp * bsec_check_error() - Check status of one otp
* @base: base address of bsec IP * @base: base address of bsec IP
@@ -279,7 +278,6 @@ static int bsec_program_otp(long base, u32 val, u32 otp)
return ret; return ret;
} }
#endif /* CONFIG_TFABOOT */
/* BSEC MISC driver *******************************************************/ /* BSEC MISC driver *******************************************************/
struct stm32mp_bsec_platdata { struct stm32mp_bsec_platdata {
@@ -288,15 +286,17 @@ struct stm32mp_bsec_platdata {
static int stm32mp_bsec_read_otp(struct udevice *dev, u32 *val, u32 otp) static int stm32mp_bsec_read_otp(struct udevice *dev, u32 *val, u32 otp)
{ {
#ifdef CONFIG_TFABOOT struct stm32mp_bsec_platdata *plat;
return stm32_smc(STM32_SMC_BSEC,
STM32_SMC_READ_OTP,
otp, 0, val);
#else
struct stm32mp_bsec_platdata *plat = dev_get_platdata(dev);
u32 tmp_data = 0; u32 tmp_data = 0;
int ret; int ret;
if (IS_ENABLED(CONFIG_TFABOOT))
return stm32_smc(STM32_SMC_BSEC,
STM32_SMC_READ_OTP,
otp, 0, val);
plat = dev_get_platdata(dev);
/* read current shadow value */ /* read current shadow value */
ret = bsec_read_shadow(plat->base, &tmp_data, otp); ret = bsec_read_shadow(plat->base, &tmp_data, otp);
if (ret) if (ret)
@@ -313,21 +313,22 @@ static int stm32mp_bsec_read_otp(struct udevice *dev, u32 *val, u32 otp)
/* restore shadow value */ /* restore shadow value */
ret = bsec_write_shadow(plat->base, tmp_data, otp); ret = bsec_write_shadow(plat->base, tmp_data, otp);
return ret; return ret;
#endif
} }
static int stm32mp_bsec_read_shadow(struct udevice *dev, u32 *val, u32 otp) static int stm32mp_bsec_read_shadow(struct udevice *dev, u32 *val, u32 otp)
{ {
#ifdef CONFIG_TFABOOT struct stm32mp_bsec_platdata *plat;
return stm32_smc(STM32_SMC_BSEC,
STM32_SMC_READ_SHADOW, if (IS_ENABLED(CONFIG_TFABOOT))
otp, 0, val); return stm32_smc(STM32_SMC_BSEC,
#else STM32_SMC_READ_SHADOW,
struct stm32mp_bsec_platdata *plat = dev_get_platdata(dev); otp, 0, val);
plat = dev_get_platdata(dev);
return bsec_read_shadow(plat->base, val, otp); return bsec_read_shadow(plat->base, val, otp);
#endif
} }
static int stm32mp_bsec_read_lock(struct udevice *dev, u32 *val, u32 otp) static int stm32mp_bsec_read_lock(struct udevice *dev, u32 *val, u32 otp)
@@ -342,33 +343,38 @@ static int stm32mp_bsec_read_lock(struct udevice *dev, u32 *val, u32 otp)
static int stm32mp_bsec_write_otp(struct udevice *dev, u32 val, u32 otp) static int stm32mp_bsec_write_otp(struct udevice *dev, u32 val, u32 otp)
{ {
#ifdef CONFIG_TFABOOT struct stm32mp_bsec_platdata *plat;
return stm32_smc_exec(STM32_SMC_BSEC,
STM32_SMC_PROG_OTP, if (IS_ENABLED(CONFIG_TFABOOT))
otp, val); return stm32_smc_exec(STM32_SMC_BSEC,
#else STM32_SMC_PROG_OTP,
struct stm32mp_bsec_platdata *plat = dev_get_platdata(dev); otp, val);
plat = dev_get_platdata(dev);
return bsec_program_otp(plat->base, val, otp); return bsec_program_otp(plat->base, val, otp);
#endif
} }
static int stm32mp_bsec_write_shadow(struct udevice *dev, u32 val, u32 otp) static int stm32mp_bsec_write_shadow(struct udevice *dev, u32 val, u32 otp)
{ {
#ifdef CONFIG_TFABOOT struct stm32mp_bsec_platdata *plat;
return stm32_smc_exec(STM32_SMC_BSEC,
STM32_SMC_WRITE_SHADOW, if (IS_ENABLED(CONFIG_TFABOOT))
otp, val); return stm32_smc_exec(STM32_SMC_BSEC,
#else STM32_SMC_WRITE_SHADOW,
struct stm32mp_bsec_platdata *plat = dev_get_platdata(dev); otp, val);
plat = dev_get_platdata(dev);
return bsec_write_shadow(plat->base, val, otp); return bsec_write_shadow(plat->base, val, otp);
#endif
} }
static int stm32mp_bsec_write_lock(struct udevice *dev, u32 val, u32 otp) static int stm32mp_bsec_write_lock(struct udevice *dev, u32 val, u32 otp)
{ {
#ifdef CONFIG_TFABOOT if (!IS_ENABLED(CONFIG_TFABOOT))
return -ENOTSUPP;
if (val == 1) if (val == 1)
return stm32_smc_exec(STM32_SMC_BSEC, return stm32_smc_exec(STM32_SMC_BSEC,
STM32_SMC_WRLOCK_OTP, STM32_SMC_WRLOCK_OTP,
@@ -377,9 +383,6 @@ static int stm32mp_bsec_write_lock(struct udevice *dev, u32 val, u32 otp)
return 0; /* nothing to do */ return 0; /* nothing to do */
return -EINVAL; return -EINVAL;
#else
return -ENOTSUPP;
#endif
} }
static int stm32mp_bsec_read(struct udevice *dev, int offset, static int stm32mp_bsec_read(struct udevice *dev, int offset,
@@ -481,18 +484,21 @@ static int stm32mp_bsec_ofdata_to_platdata(struct udevice *dev)
static int stm32mp_bsec_probe(struct udevice *dev) static int stm32mp_bsec_probe(struct udevice *dev)
{ {
#if !defined(CONFIG_TFABOOT) && !defined(CONFIG_SPL_BUILD)
int otp; int otp;
struct stm32mp_bsec_platdata *plat = dev_get_platdata(dev); struct stm32mp_bsec_platdata *plat;
/* /*
* update unlocked shadow for OTP cleared by the rom code * update unlocked shadow for OTP cleared by the rom code
* only executed in U-Boot proper when TF-A is not used * only executed in U-Boot proper when TF-A is not used
*/ */
for (otp = 57; otp <= BSEC_OTP_MAX_VALUE; otp++)
if (!bsec_read_SR_lock(plat->base, otp)) if (!IS_ENABLED(CONFIG_TFABOOT) && !IS_ENABLED(CONFIG_SPL_BUILD)) {
bsec_shadow_register(plat->base, otp); plat = dev_get_platdata(dev);
#endif
for (otp = 57; otp <= BSEC_OTP_MAX_VALUE; otp++)
if (!bsec_read_SR_lock(plat->base, otp))
bsec_shadow_register(plat->base, otp);
}
return 0; return 0;
} }

View File

@@ -14,7 +14,6 @@ struct stm32prog_data *stm32prog_data;
static void enable_vidconsole(void) static void enable_vidconsole(void)
{ {
#ifdef CONFIG_DM_VIDEO
char *stdname; char *stdname;
char buf[64]; char buf[64];
@@ -35,7 +34,6 @@ static void enable_vidconsole(void)
snprintf(buf, sizeof(buf), "%s,vidconsole", stdname); snprintf(buf, sizeof(buf), "%s,vidconsole", stdname);
env_set("stderr", buf); env_set("stderr", buf);
} }
#endif
} }
static int do_stm32prog(struct cmd_tbl *cmdtp, int flag, int argc, static int do_stm32prog(struct cmd_tbl *cmdtp, int flag, int argc,
@@ -86,7 +84,8 @@ static int do_stm32prog(struct cmd_tbl *cmdtp, int flag, int argc,
"script@1"); "script@1");
} }
enable_vidconsole(); if (IS_ENABLED(CONFIG_DM_VIDEO))
enable_vidconsole();
data = (struct stm32prog_data *)malloc(sizeof(*data)); data = (struct stm32prog_data *)malloc(sizeof(*data));

View File

@@ -544,10 +544,8 @@ static int init_device(struct stm32prog_data *data,
{ {
struct mmc *mmc = NULL; struct mmc *mmc = NULL;
struct blk_desc *block_dev = NULL; struct blk_desc *block_dev = NULL;
#ifdef CONFIG_MTD
struct mtd_info *mtd = NULL; struct mtd_info *mtd = NULL;
char mtd_id[16]; char mtd_id[16];
#endif
int part_id; int part_id;
int ret; int ret;
u64 first_addr = 0, last_addr = 0; u64 first_addr = 0, last_addr = 0;
@@ -557,8 +555,11 @@ static int init_device(struct stm32prog_data *data,
const char *part_name; const char *part_name;
switch (dev->target) { switch (dev->target) {
#ifdef CONFIG_MMC
case STM32PROG_MMC: case STM32PROG_MMC:
if (!IS_ENABLED(CONFIG_MMC)) {
stm32prog_err("unknown device type = %d", dev->target);
return -ENODEV;
}
mmc = find_mmc_device(dev->dev_id); mmc = find_mmc_device(dev->dev_id);
if (!mmc || mmc_init(mmc)) { if (!mmc || mmc_init(mmc)) {
stm32prog_err("mmc device %d not found", dev->dev_id); stm32prog_err("mmc device %d not found", dev->dev_id);
@@ -589,11 +590,13 @@ static int init_device(struct stm32prog_data *data,
first_addr, last_addr); first_addr, last_addr);
pr_debug(" full_update = %d\n", dev->full_update); pr_debug(" full_update = %d\n", dev->full_update);
break; break;
#endif
#ifdef CONFIG_MTD
case STM32PROG_NOR: case STM32PROG_NOR:
case STM32PROG_NAND: case STM32PROG_NAND:
case STM32PROG_SPI_NAND: case STM32PROG_SPI_NAND:
if (!IS_ENABLED(CONFIG_MTD)) {
stm32prog_err("unknown device type = %d", dev->target);
return -ENODEV;
}
get_mtd_by_target(mtd_id, dev->target, dev->dev_id); get_mtd_by_target(mtd_id, dev->target, dev->dev_id);
pr_debug("%s\n", mtd_id); pr_debug("%s\n", mtd_id);
@@ -612,7 +615,6 @@ static int init_device(struct stm32prog_data *data,
first_addr, last_addr); first_addr, last_addr);
dev->mtd = mtd; dev->mtd = mtd;
break; break;
#endif
case STM32PROG_RAM: case STM32PROG_RAM:
first_addr = gd->bd->bi_dram[0].start; first_addr = gd->bd->bi_dram[0].start;
last_addr = first_addr + gd->bd->bi_dram[0].size; last_addr = first_addr + gd->bd->bi_dram[0].size;
@@ -744,8 +746,7 @@ static int init_device(struct stm32prog_data *data,
part_found = true; part_found = true;
} }
#ifdef CONFIG_MTD if (IS_ENABLED(CONFIG_MTD) && mtd) {
if (mtd) {
char mtd_part_id[32]; char mtd_part_id[32];
struct part_info *mtd_part; struct part_info *mtd_part;
struct mtd_device *mtd_dev; struct mtd_device *mtd_dev;
@@ -766,7 +767,7 @@ static int init_device(struct stm32prog_data *data,
part_name = mtd_part->name; part_name = mtd_part->name;
part_found = true; part_found = true;
} }
#endif
if (!part_found) { if (!part_found) {
stm32prog_err("%s (0x%x): Invalid partition", stm32prog_err("%s (0x%x): Invalid partition",
part->name, part->id); part->name, part->id);
@@ -873,9 +874,8 @@ static int treat_partition_list(struct stm32prog_data *data)
return 0; return 0;
} }
static int create_partitions(struct stm32prog_data *data) static int create_gpt_partitions(struct stm32prog_data *data)
{ {
#ifdef CONFIG_MMC
int offset = 0; int offset = 0;
const int buflen = SZ_8K; const int buflen = SZ_8K;
char *buf; char *buf;
@@ -991,7 +991,6 @@ static int create_partitions(struct stm32prog_data *data)
run_command("mtd list", 0); run_command("mtd list", 0);
#endif #endif
free(buf); free(buf);
#endif
return 0; return 0;
} }
@@ -1070,28 +1069,35 @@ static int stm32prog_alt_add(struct stm32prog_data *data,
offset += snprintf(buf + offset, ALT_BUF_LEN - offset, offset += snprintf(buf + offset, ALT_BUF_LEN - offset,
" %d;", part->part_id); " %d;", part->part_id);
} }
ret = -ENODEV;
switch (part->target) { switch (part->target) {
#ifdef CONFIG_MMC
case STM32PROG_MMC: case STM32PROG_MMC:
sprintf(dfustr, "mmc"); if (IS_ENABLED(CONFIG_MMC)) {
sprintf(devstr, "%d", part->dev_id); ret = 0;
sprintf(dfustr, "mmc");
sprintf(devstr, "%d", part->dev_id);
}
break; break;
#endif
#ifdef CONFIG_MTD
case STM32PROG_NAND: case STM32PROG_NAND:
case STM32PROG_NOR: case STM32PROG_NOR:
case STM32PROG_SPI_NAND: case STM32PROG_SPI_NAND:
sprintf(dfustr, "mtd"); if (IS_ENABLED(CONFIG_MTD)) {
get_mtd_by_target(devstr, part->target, part->dev_id); ret = 0;
sprintf(dfustr, "mtd");
get_mtd_by_target(devstr, part->target, part->dev_id);
}
break; break;
#endif
case STM32PROG_RAM: case STM32PROG_RAM:
ret = 0;
sprintf(dfustr, "ram"); sprintf(dfustr, "ram");
sprintf(devstr, "0"); sprintf(devstr, "0");
break; break;
default: default:
break;
}
if (ret) {
stm32prog_err("invalid target: %d", part->target); stm32prog_err("invalid target: %d", part->target);
return -ENODEV; return ret;
} }
pr_debug("dfu_alt_add(%s,%s,%s)\n", dfustr, devstr, buf); pr_debug("dfu_alt_add(%s,%s,%s)\n", dfustr, devstr, buf);
ret = dfu_alt_add(dfu, dfustr, devstr, buf); ret = dfu_alt_add(dfu, dfustr, devstr, buf);
@@ -1213,13 +1219,14 @@ int stm32prog_otp_write(struct stm32prog_data *data, u32 offset, u8 *buffer,
int stm32prog_otp_read(struct stm32prog_data *data, u32 offset, u8 *buffer, int stm32prog_otp_read(struct stm32prog_data *data, u32 offset, u8 *buffer,
long *size) long *size)
{ {
#ifndef CONFIG_ARM_SMCCC
stm32prog_err("OTP update not supported");
return -1;
#else
int result = 0; int result = 0;
if (!IS_ENABLED(CONFIG_ARM_SMCCC)) {
stm32prog_err("OTP update not supported");
return -1;
}
pr_debug("%s: %x %lx\n", __func__, offset, *size); pr_debug("%s: %x %lx\n", __func__, offset, *size);
/* alway read for first packet */ /* alway read for first packet */
if (!offset) { if (!offset) {
@@ -1255,19 +1262,19 @@ end_otp_read:
pr_debug("%s: result %i\n", __func__, result); pr_debug("%s: result %i\n", __func__, result);
return result; return result;
#endif
} }
int stm32prog_otp_start(struct stm32prog_data *data) int stm32prog_otp_start(struct stm32prog_data *data)
{ {
#ifndef CONFIG_ARM_SMCCC
stm32prog_err("OTP update not supported");
return -1;
#else
int result = 0; int result = 0;
struct arm_smccc_res res; struct arm_smccc_res res;
if (!IS_ENABLED(CONFIG_ARM_SMCCC)) {
stm32prog_err("OTP update not supported");
return -1;
}
if (!data->otp_part) { if (!data->otp_part) {
stm32prog_err("start OTP without data"); stm32prog_err("start OTP without data");
return -1; return -1;
@@ -1302,7 +1309,6 @@ int stm32prog_otp_start(struct stm32prog_data *data)
pr_debug("%s: result %i\n", __func__, result); pr_debug("%s: result %i\n", __func__, result);
return result; return result;
#endif
} }
int stm32prog_pmic_write(struct stm32prog_data *data, u32 offset, u8 *buffer, int stm32prog_pmic_write(struct stm32prog_data *data, u32 offset, u8 *buffer,
@@ -1538,19 +1544,20 @@ static int part_delete(struct stm32prog_data *data,
struct stm32prog_part_t *part) struct stm32prog_part_t *part)
{ {
int ret = 0; int ret = 0;
#ifdef CONFIG_MMC
unsigned long blks, blks_offset, blks_size; unsigned long blks, blks_offset, blks_size;
struct blk_desc *block_dev = NULL; struct blk_desc *block_dev = NULL;
#endif
#ifdef CONFIG_MTD
char cmdbuf[40]; char cmdbuf[40];
char devstr[10]; char devstr[10];
#endif
printf("Erasing %s ", part->name); printf("Erasing %s ", part->name);
switch (part->target) { switch (part->target) {
#ifdef CONFIG_MMC
case STM32PROG_MMC: case STM32PROG_MMC:
if (!IS_ENABLED(CONFIG_MMC)) {
ret = -1;
stm32prog_err("%s (0x%x): erase invalid",
part->name, part->id);
break;
}
printf("on mmc %d: ", part->dev->dev_id); printf("on mmc %d: ", part->dev->dev_id);
block_dev = mmc_get_blk_desc(part->dev->mmc); block_dev = mmc_get_blk_desc(part->dev->mmc);
blks_offset = lldiv(part->addr, part->dev->mmc->read_bl_len); blks_offset = lldiv(part->addr, part->dev->mmc->read_bl_len);
@@ -1576,11 +1583,15 @@ static int part_delete(struct stm32prog_data *data,
part->name, part->id); part->name, part->id);
} }
break; break;
#endif
#ifdef CONFIG_MTD
case STM32PROG_NOR: case STM32PROG_NOR:
case STM32PROG_NAND: case STM32PROG_NAND:
case STM32PROG_SPI_NAND: case STM32PROG_SPI_NAND:
if (!IS_ENABLED(CONFIG_MTD)) {
ret = -1;
stm32prog_err("%s (0x%x): erase invalid",
part->name, part->id);
break;
}
get_mtd_by_target(devstr, part->target, part->dev->dev_id); get_mtd_by_target(devstr, part->target, part->dev->dev_id);
printf("on %s: ", devstr); printf("on %s: ", devstr);
sprintf(cmdbuf, "mtd erase %s 0x%llx 0x%llx", sprintf(cmdbuf, "mtd erase %s 0x%llx 0x%llx",
@@ -1591,7 +1602,6 @@ static int part_delete(struct stm32prog_data *data,
part->name, part->id, cmdbuf); part->name, part->id, cmdbuf);
} }
break; break;
#endif
case STM32PROG_RAM: case STM32PROG_RAM:
printf("on ram: "); printf("on ram: ");
memset((void *)(uintptr_t)part->addr, 0, (size_t)part->size); memset((void *)(uintptr_t)part->addr, 0, (size_t)part->size);
@@ -1639,9 +1649,11 @@ static void stm32prog_devices_init(struct stm32prog_data *data)
goto error; goto error;
} }
ret = create_partitions(data); if (IS_ENABLED(CONFIG_MMC)) {
if (ret) ret = create_gpt_partitions(data);
goto error; if (ret)
goto error;
}
/* delete partition GPT or MTD */ /* delete partition GPT or MTD */
for (i = 0; i < data->part_nb; i++) { for (i = 0; i < data->part_nb; i++) {

View File

@@ -84,11 +84,26 @@ DECLARE_GLOBAL_DATA_PTR;
int setup_mac_address(void) int setup_mac_address(void)
{ {
unsigned char enetaddr[6]; unsigned char enetaddr[6];
bool skip_eth0 = false;
bool skip_eth1 = false;
struct udevice *dev; struct udevice *dev;
int off, ret; int off, ret;
ret = eth_env_get_enetaddr("ethaddr", enetaddr); ret = eth_env_get_enetaddr("ethaddr", enetaddr);
if (ret) /* ethaddr is already set */ if (ret) /* ethaddr is already set */
skip_eth0 = true;
off = fdt_path_offset(gd->fdt_blob, "ethernet1");
if (off < 0) {
/* ethernet1 is not present in the system */
skip_eth1 = true;
} else {
ret = eth_env_get_enetaddr("eth1addr", enetaddr);
if (ret) /* eth1addr is already set */
skip_eth1 = true;
}
if (skip_eth0 && skip_eth1)
return 0; return 0;
off = fdt_path_offset(gd->fdt_blob, "eeprom0"); off = fdt_path_offset(gd->fdt_blob, "eeprom0");
@@ -109,8 +124,14 @@ int setup_mac_address(void)
return ret; return ret;
} }
if (is_valid_ethaddr(enetaddr)) if (is_valid_ethaddr(enetaddr)) {
eth_env_set_enetaddr("ethaddr", enetaddr); if (!skip_eth0)
eth_env_set_enetaddr("ethaddr", enetaddr);
enetaddr[5]++;
if (!skip_eth1)
eth_env_set_enetaddr("eth1addr", enetaddr);
}
return 0; return 0;
} }
@@ -216,9 +237,13 @@ int board_early_init_f(void)
#ifdef CONFIG_SPL_LOAD_FIT #ifdef CONFIG_SPL_LOAD_FIT
int board_fit_config_name_match(const char *name) int board_fit_config_name_match(const char *name)
{ {
char test[20]; const char *compat;
char test[128];
snprintf(test, sizeof(test), "somrev%d_boardrev%d", somcode, brdcode); compat = fdt_getprop(gd->fdt_blob, 0, "compatible", NULL);
snprintf(test, sizeof(test), "%s_somrev%d_boardrev%d",
compat, somcode, brdcode);
if (!strcmp(name, test)) if (!strcmp(name, test))
return 0; return 0;

View File

@@ -23,17 +23,47 @@
arch = "arm"; arch = "arm";
compression = "none"; compression = "none";
}; };
fdt-2 {
description = ".dtb";
data = /incbin/("arch/arm/dts/stm32mp15xx-dhcom-drc02.dtb");
type = "flat_dt";
arch = "arm";
compression = "none";
};
}; };
configurations { configurations {
default = "config-1"; default = "config-1";
config-1 { config-1 {
description = "somrev0_boardrev0"; /* SoM+board model */ /* DT+SoM+board model */
description = "dh,stm32mp15xx-dhcom-pdk2_somrev0_boardrev0";
loadables = "uboot"; loadables = "uboot";
fdt = "fdt-1"; fdt = "fdt-1";
}; };
config-2 {
/* DT+SoM+board model */
description = "dh,stm32mp15xx-dhcom-pdk2_somrev1_boardrev0";
loadables = "uboot";
fdt = "fdt-1";
};
config-3 {
/* DT+SoM+board model */
description = "dh,stm32mp15xx-dhcom-drc02_somrev0_boardrev0";
loadables = "uboot";
fdt = "fdt-2";
};
config-4 {
/* DT+SoM+board model */
description = "dh,stm32mp15xx-dhcom-drc02_somrev1_boardrev0";
loadables = "uboot";
fdt = "fdt-2";
};
/* Add 587-100..587-400 with fdt-2..fdt-4 here */ /* Add 587-100..587-400 with fdt-2..fdt-4 here */
}; };
}; };

View File

@@ -29,7 +29,8 @@
default = "config-1"; default = "config-1";
config-1 { config-1 {
description = "somrev0_boardrev1"; /* SoM+board model */ /* DT+SoM+board model */
description = "arrow,stm32mp15xx-avenger96_somrev0_boardrev1";
loadables = "uboot"; loadables = "uboot";
fdt = "fdt-1"; fdt = "fdt-1";
}; };

View File

@@ -114,11 +114,13 @@ void set_dfu_alt_info(char *interface, char *devstr)
snprintf(buf, DFU_ALT_BUF_LEN, snprintf(buf, DFU_ALT_BUF_LEN,
"ram 0=%s", CONFIG_DFU_ALT_RAM0); "ram 0=%s", CONFIG_DFU_ALT_RAM0);
if (!uclass_get_device(UCLASS_MMC, 0, &dev)) if (CONFIG_IS_ENABLED(MMC)) {
board_get_alt_info_mmc(dev, buf); if (!uclass_get_device(UCLASS_MMC, 0, &dev))
board_get_alt_info_mmc(dev, buf);
if (!uclass_get_device(UCLASS_MMC, 1, &dev)) if (!uclass_get_device(UCLASS_MMC, 1, &dev))
board_get_alt_info_mmc(dev, buf); board_get_alt_info_mmc(dev, buf);
}
if (CONFIG_IS_ENABLED(MTD)) { if (CONFIG_IS_ENABLED(MTD)) {
/* probe all MTD devices */ /* probe all MTD devices */
@@ -140,12 +142,12 @@ void set_dfu_alt_info(char *interface, char *devstr)
board_get_alt_info_mtd(mtd, buf); board_get_alt_info_mtd(mtd, buf);
} }
#ifdef CONFIG_DFU_VIRT if (IS_ENABLED(CONFIG_DFU_VIRT)) {
strncat(buf, "&virt 0=OTP", DFU_ALT_BUF_LEN); strncat(buf, "&virt 0=OTP", DFU_ALT_BUF_LEN);
if (IS_ENABLED(CONFIG_PMIC_STPMIC1)) if (IS_ENABLED(CONFIG_PMIC_STPMIC1))
strncat(buf, "&virt 1=PMIC", DFU_ALT_BUF_LEN); strncat(buf, "&virt 1=PMIC", DFU_ALT_BUF_LEN);
#endif }
env_set("dfu_alt_info", buf); env_set("dfu_alt_info", buf);
puts("DFU alt info setting: done\n"); puts("DFU alt info setting: done\n");

View File

@@ -1,36 +0,0 @@
// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
/*
* Copyright (C) 2018, STMicroelectronics - All Rights Reserved
*/
#include <common.h>
#include <asm/io.h>
#include <linux/bitops.h>
#include <linux/delay.h>
#ifdef CONFIG_DEBUG_UART_BOARD_INIT
void board_debug_uart_init(void)
{
#if (CONFIG_DEBUG_UART_BASE == STM32_UART4_BASE)
#define RCC_MP_APB1ENSETR (STM32_RCC_BASE + 0x0A00)
#define RCC_MP_AHB4ENSETR (STM32_RCC_BASE + 0x0A28)
/* UART4 clock enable */
setbits_le32(RCC_MP_APB1ENSETR, BIT(16));
#define GPIOG_BASE 0x50008000
/* GPIOG clock enable */
writel(BIT(6), RCC_MP_AHB4ENSETR);
/* GPIO configuration for EVAL board
* => Uart4 TX = G11
*/
writel(0xffbfffff, GPIOG_BASE + 0x00);
writel(0x00006000, GPIOG_BASE + 0x24);
#else
#error("CONFIG_DEBUG_UART_BASE: not supported value")
#endif
}
#endif

View File

@@ -135,60 +135,61 @@ int checkboard(void)
static void board_key_check(void) static void board_key_check(void)
{ {
#if defined(CONFIG_FASTBOOT) || defined(CONFIG_CMD_STM32PROG)
ofnode node; ofnode node;
struct gpio_desc gpio; struct gpio_desc gpio;
enum forced_boot_mode boot_mode = BOOT_NORMAL; enum forced_boot_mode boot_mode = BOOT_NORMAL;
if (!IS_ENABLED(CONFIG_FASTBOOT) && !IS_ENABLED(CONFIG_CMD_STM32PROG))
return;
node = ofnode_path("/config"); node = ofnode_path("/config");
if (!ofnode_valid(node)) { if (!ofnode_valid(node)) {
debug("%s: no /config node?\n", __func__); debug("%s: no /config node?\n", __func__);
return; return;
} }
#ifdef CONFIG_FASTBOOT if (IS_ENABLED(CONFIG_FASTBOOT)) {
if (gpio_request_by_name_nodev(node, "st,fastboot-gpios", 0, if (gpio_request_by_name_nodev(node, "st,fastboot-gpios", 0,
&gpio, GPIOD_IS_IN)) { &gpio, GPIOD_IS_IN)) {
debug("%s: could not find a /config/st,fastboot-gpios\n", debug("%s: could not find a /config/st,fastboot-gpios\n",
__func__); __func__);
} else { } else {
if (dm_gpio_get_value(&gpio)) { if (dm_gpio_get_value(&gpio)) {
puts("Fastboot key pressed, "); puts("Fastboot key pressed, ");
boot_mode = BOOT_FASTBOOT; boot_mode = BOOT_FASTBOOT;
} }
dm_gpio_free(NULL, &gpio); dm_gpio_free(NULL, &gpio);
} }
#endif }
#ifdef CONFIG_CMD_STM32PROG if (IS_ENABLED(CONFIG_CMD_STM32PROG)) {
if (gpio_request_by_name_nodev(node, "st,stm32prog-gpios", 0, if (gpio_request_by_name_nodev(node, "st,stm32prog-gpios", 0,
&gpio, GPIOD_IS_IN)) { &gpio, GPIOD_IS_IN)) {
debug("%s: could not find a /config/st,stm32prog-gpios\n", debug("%s: could not find a /config/st,stm32prog-gpios\n",
__func__); __func__);
} else { } else {
if (dm_gpio_get_value(&gpio)) { if (dm_gpio_get_value(&gpio)) {
puts("STM32Programmer key pressed, "); puts("STM32Programmer key pressed, ");
boot_mode = BOOT_STM32PROG; boot_mode = BOOT_STM32PROG;
}
dm_gpio_free(NULL, &gpio);
} }
dm_gpio_free(NULL, &gpio);
} }
#endif
if (boot_mode != BOOT_NORMAL) { if (boot_mode != BOOT_NORMAL) {
puts("entering download mode...\n"); puts("entering download mode...\n");
clrsetbits_le32(TAMP_BOOT_CONTEXT, clrsetbits_le32(TAMP_BOOT_CONTEXT,
TAMP_BOOT_FORCED_MASK, TAMP_BOOT_FORCED_MASK,
boot_mode); boot_mode);
} }
#endif
} }
#if defined(CONFIG_USB_GADGET) && defined(CONFIG_USB_GADGET_DWC2_OTG)
#include <usb/dwc2_udc.h>
int g_dnl_board_usb_cable_connected(void) int g_dnl_board_usb_cable_connected(void)
{ {
struct udevice *dwc2_udc_otg; struct udevice *dwc2_udc_otg;
int ret; int ret;
if (!IS_ENABLED(CONFIG_USB_GADGET_DWC2_OTG))
return -ENODEV;
/* if typec stusb160x is present, means DK1 or DK2 board */ /* if typec stusb160x is present, means DK1 or DK2 board */
ret = stusb160x_cable_connected(); ret = stusb160x_cable_connected();
if (ret >= 0) if (ret >= 0)
@@ -203,14 +204,17 @@ int g_dnl_board_usb_cable_connected(void)
return dwc2_udc_B_session_valid(dwc2_udc_otg); return dwc2_udc_B_session_valid(dwc2_udc_otg);
} }
#ifdef CONFIG_USB_GADGET_DOWNLOAD
#define STM32MP1_G_DNL_DFU_PRODUCT_NUM 0xdf11 #define STM32MP1_G_DNL_DFU_PRODUCT_NUM 0xdf11
#define STM32MP1_G_DNL_FASTBOOT_PRODUCT_NUM 0x0afb #define STM32MP1_G_DNL_FASTBOOT_PRODUCT_NUM 0x0afb
int g_dnl_bind_fixup(struct usb_device_descriptor *dev, const char *name) int g_dnl_bind_fixup(struct usb_device_descriptor *dev, const char *name)
{ {
if (!strcmp(name, "usb_dnl_dfu")) if (IS_ENABLED(CONFIG_DFU_OVER_USB) &&
!strcmp(name, "usb_dnl_dfu"))
put_unaligned(STM32MP1_G_DNL_DFU_PRODUCT_NUM, &dev->idProduct); put_unaligned(STM32MP1_G_DNL_DFU_PRODUCT_NUM, &dev->idProduct);
else if (!strcmp(name, "usb_dnl_fastboot")) else if (IS_ENABLED(CONFIG_FASTBOOT) &&
!strcmp(name, "usb_dnl_fastboot"))
put_unaligned(STM32MP1_G_DNL_FASTBOOT_PRODUCT_NUM, put_unaligned(STM32MP1_G_DNL_FASTBOOT_PRODUCT_NUM,
&dev->idProduct); &dev->idProduct);
else else
@@ -218,8 +222,7 @@ int g_dnl_bind_fixup(struct usb_device_descriptor *dev, const char *name)
return 0; return 0;
} }
#endif /* CONFIG_USB_GADGET_DOWNLOAD */
#endif /* CONFIG_USB_GADGET */
static int get_led(struct udevice **dev, char *led_string) static int get_led(struct udevice **dev, char *led_string)
{ {
@@ -285,7 +288,6 @@ static void __maybe_unused led_error_blink(u32 nb_blink)
hang(); hang();
} }
#ifdef CONFIG_ADC
static int board_check_usb_power(void) static int board_check_usb_power(void)
{ {
struct ofnode_phandle_args adc_args; struct ofnode_phandle_args adc_args;
@@ -297,6 +299,10 @@ static int board_check_usb_power(void)
int ret, uV, adc_count; int ret, uV, adc_count;
u32 nb_blink; u32 nb_blink;
u8 i; u8 i;
if (!IS_ENABLED(CONFIG_ADC))
return -ENODEV;
node = ofnode_path("/config"); node = ofnode_path("/config");
if (!ofnode_valid(node)) { if (!ofnode_valid(node)) {
debug("%s: no /config node?\n", __func__); debug("%s: no /config node?\n", __func__);
@@ -419,18 +425,14 @@ static int board_check_usb_power(void)
return 0; return 0;
} }
#endif /* CONFIG_ADC */
static void sysconf_init(void) static void sysconf_init(void)
{ {
#ifndef CONFIG_TFABOOT
u8 *syscfg; u8 *syscfg;
#ifdef CONFIG_DM_REGULATOR
struct udevice *pwr_dev; struct udevice *pwr_dev;
struct udevice *pwr_reg; struct udevice *pwr_reg;
struct udevice *dev; struct udevice *dev;
u32 otp = 0; u32 otp = 0;
#endif
int ret; int ret;
u32 bootr, val; u32 bootr, val;
@@ -448,7 +450,6 @@ static void sysconf_init(void)
bootr |= (bootr & SYSCFG_BOOTR_BOOT_MASK) << SYSCFG_BOOTR_BOOTPD_SHIFT; bootr |= (bootr & SYSCFG_BOOTR_BOOT_MASK) << SYSCFG_BOOTR_BOOTPD_SHIFT;
writel(bootr, syscfg + SYSCFG_BOOTR); writel(bootr, syscfg + SYSCFG_BOOTR);
#ifdef CONFIG_DM_REGULATOR
/* High Speed Low Voltage Pad mode Enable for SPI, SDMMC, ETH, QSPI /* High Speed Low Voltage Pad mode Enable for SPI, SDMMC, ETH, QSPI
* and TRACE. Needed above ~50MHz and conditioned by AFMUX selection. * and TRACE. Needed above ~50MHz and conditioned by AFMUX selection.
* The customer will have to disable this for low frequencies * The customer will have to disable this for low frequencies
@@ -465,7 +466,7 @@ static void sysconf_init(void)
ret = uclass_get_device_by_driver(UCLASS_PMIC, ret = uclass_get_device_by_driver(UCLASS_PMIC,
DM_GET_DRIVER(stm32mp_pwr_pmic), DM_GET_DRIVER(stm32mp_pwr_pmic),
&pwr_dev); &pwr_dev);
if (!ret) { if (!ret && IS_ENABLED(CONFIG_DM_REGULATOR)) {
ret = uclass_get_device_by_driver(UCLASS_MISC, ret = uclass_get_device_by_driver(UCLASS_MISC,
DM_GET_DRIVER(stm32mp_bsec), DM_GET_DRIVER(stm32mp_bsec),
&dev); &dev);
@@ -502,7 +503,6 @@ static void sysconf_init(void)
debug("VDD unknown"); debug("VDD unknown");
} }
} }
#endif
/* activate automatic I/O compensation /* activate automatic I/O compensation
* warning: need to ensure CSI enabled and ready in clock driver * warning: need to ensure CSI enabled and ready in clock driver
@@ -519,10 +519,8 @@ static void sysconf_init(void)
} }
clrbits_le32(syscfg + SYSCFG_CMPCR, SYSCFG_CMPCR_SW_CTRL); clrbits_le32(syscfg + SYSCFG_CMPCR, SYSCFG_CMPCR_SW_CTRL);
#endif
} }
#ifdef CONFIG_DM_REGULATOR
/* Fix to make I2C1 usable on DK2 for touchscreen usage in kernel */ /* Fix to make I2C1 usable on DK2 for touchscreen usage in kernel */
static int dk2_i2c1_fix(void) static int dk2_i2c1_fix(void)
{ {
@@ -530,6 +528,9 @@ static int dk2_i2c1_fix(void)
struct gpio_desc hdmi, audio; struct gpio_desc hdmi, audio;
int ret = 0; int ret = 0;
if (!IS_ENABLED(CONFIG_DM_REGULATOR))
return -ENODEV;
node = ofnode_path("/soc/i2c@40012000/hdmi-transmitter@39"); node = ofnode_path("/soc/i2c@40012000/hdmi-transmitter@39");
if (!ofnode_valid(node)) { if (!ofnode_valid(node)) {
pr_debug("%s: no hdmi-transmitter@39 ?\n", __func__); pr_debug("%s: no hdmi-transmitter@39 ?\n", __func__);
@@ -587,7 +588,6 @@ static bool board_is_dk2(void)
return false; return false;
} }
#endif
static bool board_is_ev1(void) static bool board_is_ev1(void)
{ {
@@ -635,14 +635,14 @@ int board_init(void)
if (board_is_ev1()) if (board_is_ev1())
board_ev1_init(); board_ev1_init();
#ifdef CONFIG_DM_REGULATOR
if (board_is_dk2()) if (board_is_dk2())
dk2_i2c1_fix(); dk2_i2c1_fix();
regulators_enable_boot_on(_DEBUG); if (IS_ENABLED(CONFIG_DM_REGULATOR))
#endif regulators_enable_boot_on(_DEBUG);
sysconf_init(); if (!IS_ENABLED(CONFIG_TFABOOT))
sysconf_init();
if (CONFIG_IS_ENABLED(LED)) if (CONFIG_IS_ENABLED(LED))
led_default_state(); led_default_state();
@@ -654,52 +654,50 @@ int board_init(void)
int board_late_init(void) int board_late_init(void)
{ {
#ifdef CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG
const void *fdt_compat; const void *fdt_compat;
int fdt_compat_len; int fdt_compat_len;
int ret; int ret;
u32 otp; u32 otp;
struct udevice *dev; struct udevice *dev;
char buf[10]; char buf[10];
char dtb_name[256];
int buf_len;
fdt_compat = fdt_getprop(gd->fdt_blob, 0, "compatible", if (IS_ENABLED(CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG)) {
&fdt_compat_len); fdt_compat = fdt_getprop(gd->fdt_blob, 0, "compatible",
if (fdt_compat && fdt_compat_len) { &fdt_compat_len);
if (strncmp(fdt_compat, "st,", 3) != 0) { if (fdt_compat && fdt_compat_len) {
env_set("board_name", fdt_compat); if (strncmp(fdt_compat, "st,", 3) != 0) {
} else { env_set("board_name", fdt_compat);
char dtb_name[256]; } else {
int buf_len = sizeof(dtb_name); env_set("board_name", fdt_compat + 3);
env_set("board_name", fdt_compat + 3); buf_len = sizeof(dtb_name);
strncpy(dtb_name, fdt_compat + 3, buf_len);
buf_len -= strlen(fdt_compat + 3);
strncat(dtb_name, ".dtb", buf_len);
env_set("fdtfile", dtb_name);
}
}
ret = uclass_get_device_by_driver(UCLASS_MISC,
DM_GET_DRIVER(stm32mp_bsec),
&dev);
strncpy(dtb_name, fdt_compat + 3, buf_len); if (!ret)
buf_len -= strlen(fdt_compat + 3); ret = misc_read(dev, STM32_BSEC_SHADOW(BSEC_OTP_BOARD),
strncat(dtb_name, ".dtb", buf_len); &otp, sizeof(otp));
env_set("fdtfile", dtb_name); if (ret > 0 && otp) {
snprintf(buf, sizeof(buf), "0x%04x", otp >> 16);
env_set("board_id", buf);
snprintf(buf, sizeof(buf), "0x%04x",
((otp >> 8) & 0xF) - 1 + 0xA);
env_set("board_rev", buf);
} }
} }
ret = uclass_get_device_by_driver(UCLASS_MISC,
DM_GET_DRIVER(stm32mp_bsec),
&dev);
if (!ret)
ret = misc_read(dev, STM32_BSEC_SHADOW(BSEC_OTP_BOARD),
&otp, sizeof(otp));
if (ret > 0 && otp) {
snprintf(buf, sizeof(buf), "0x%04x", otp >> 16);
env_set("board_id", buf);
snprintf(buf, sizeof(buf), "0x%04x",
((otp >> 8) & 0xF) - 1 + 0xA);
env_set("board_rev", buf);
}
#endif
#ifdef CONFIG_ADC
/* for DK1/DK2 boards */ /* for DK1/DK2 boards */
board_check_usb_power(); board_check_usb_power();
#endif /* CONFIG_ADC */
return 0; return 0;
} }
@@ -787,31 +785,33 @@ enum env_location env_get_location(enum env_operation op, int prio)
return ENVL_UNKNOWN; return ENVL_UNKNOWN;
switch (bootmode & TAMP_BOOT_DEVICE_MASK) { switch (bootmode & TAMP_BOOT_DEVICE_MASK) {
#if CONFIG_IS_ENABLED(ENV_IS_IN_MMC)
case BOOT_FLASH_SD: case BOOT_FLASH_SD:
case BOOT_FLASH_EMMC: case BOOT_FLASH_EMMC:
return ENVL_MMC; if (CONFIG_IS_ENABLED(ENV_IS_IN_MMC))
#endif return ENVL_MMC;
#if CONFIG_IS_ENABLED(ENV_IS_IN_EXT4) else if (CONFIG_IS_ENABLED(ENV_IS_IN_EXT4))
case BOOT_FLASH_SD: return ENVL_EXT4;
case BOOT_FLASH_EMMC: else
return ENVL_EXT4; return ENVL_NOWHERE;
#endif
#if CONFIG_IS_ENABLED(ENV_IS_IN_UBI)
case BOOT_FLASH_NAND: case BOOT_FLASH_NAND:
case BOOT_FLASH_SPINAND: case BOOT_FLASH_SPINAND:
return ENVL_UBI; if (CONFIG_IS_ENABLED(ENV_IS_IN_UBI))
#endif return ENVL_UBI;
#if CONFIG_IS_ENABLED(ENV_IS_IN_SPI_FLASH) else
return ENVL_NOWHERE;
case BOOT_FLASH_NOR: case BOOT_FLASH_NOR:
return ENVL_SPI_FLASH; if (CONFIG_IS_ENABLED(ENV_IS_IN_SPI_FLASH))
#endif return ENVL_SPI_FLASH;
else
return ENVL_NOWHERE;
default: default:
return ENVL_NOWHERE; return ENVL_NOWHERE;
} }
} }
#if defined(CONFIG_ENV_IS_IN_EXT4)
const char *env_ext4_get_intf(void) const char *env_ext4_get_intf(void)
{ {
u32 bootmode = get_bootmode(); u32 bootmode = get_bootmode();
@@ -832,28 +832,25 @@ const char *env_ext4_get_dev_part(void)
return dev_part[(bootmode & TAMP_BOOT_INSTANCE_MASK) - 1]; return dev_part[(bootmode & TAMP_BOOT_INSTANCE_MASK) - 1];
} }
#endif
#if defined(CONFIG_ENV_IS_IN_MMC)
int mmc_get_env_dev(void) int mmc_get_env_dev(void)
{ {
u32 bootmode = get_bootmode(); u32 bootmode = get_bootmode();
return (bootmode & TAMP_BOOT_INSTANCE_MASK) - 1; return (bootmode & TAMP_BOOT_INSTANCE_MASK) - 1;
} }
#endif
#if defined(CONFIG_OF_BOARD_SETUP) #if defined(CONFIG_OF_BOARD_SETUP)
int ft_board_setup(void *blob, struct bd_info *bd) int ft_board_setup(void *blob, struct bd_info *bd)
{ {
#ifdef CONFIG_FDT_FIXUP_PARTITIONS static const struct node_info nodes[] = {
struct node_info nodes[] = {
{ "st,stm32f469-qspi", MTD_DEV_TYPE_NOR, }, { "st,stm32f469-qspi", MTD_DEV_TYPE_NOR, },
{ "st,stm32f469-qspi", MTD_DEV_TYPE_SPINAND}, { "st,stm32f469-qspi", MTD_DEV_TYPE_SPINAND},
{ "st,stm32mp15-fmc2", MTD_DEV_TYPE_NAND, }, { "st,stm32mp15-fmc2", MTD_DEV_TYPE_NAND, },
{ "st,stm32mp1-fmc2-nfc", MTD_DEV_TYPE_NAND, },
}; };
fdt_fixup_mtdparts(blob, nodes, ARRAY_SIZE(nodes));
#endif if (IS_ENABLED(CONFIG_FDT_FIXUP_PARTITIONS))
fdt_fixup_mtdparts(blob, nodes, ARRAY_SIZE(nodes));
return 0; return 0;
} }

View File

@@ -88,6 +88,7 @@ CONFIG_LED=y
CONFIG_LED_GPIO=y CONFIG_LED_GPIO=y
CONFIG_DM_MAILBOX=y CONFIG_DM_MAILBOX=y
CONFIG_STM32_IPCC=y CONFIG_STM32_IPCC=y
CONFIG_STM32_FMC2_EBI=y
CONFIG_DM_MMC=y CONFIG_DM_MMC=y
CONFIG_SUPPORT_EMMC_BOOT=y CONFIG_SUPPORT_EMMC_BOOT=y
CONFIG_STM32_SDMMC2=y CONFIG_STM32_SDMMC2=y

View File

@@ -57,6 +57,7 @@ CONFIG_CMD_REGULATOR=y
CONFIG_CMD_EXT4_WRITE=y CONFIG_CMD_EXT4_WRITE=y
CONFIG_CMD_MTDPARTS=y CONFIG_CMD_MTDPARTS=y
# CONFIG_SPL_DOS_PARTITION is not set # CONFIG_SPL_DOS_PARTITION is not set
CONFIG_OF_LIST="stm32mp15xx-dhcom-pdk2 stm32mp15xx-dhcom-drc02"
CONFIG_OF_SPL_REMOVE_PROPS="interrupts interrupt-names interrupts-extended interrupt-controller \\\#interrupt-cells interrupt-parent dmas dma-names assigned-clocks assigned-clock-rates assigned-clock-parents hwlocks" CONFIG_OF_SPL_REMOVE_PROPS="interrupts interrupt-names interrupts-extended interrupt-controller \\\#interrupt-cells interrupt-parent dmas dma-names assigned-clocks assigned-clock-rates assigned-clock-parents hwlocks"
CONFIG_ENV_IS_IN_SPI_FLASH=y CONFIG_ENV_IS_IN_SPI_FLASH=y
CONFIG_USE_ENV_SPI_BUS=y CONFIG_USE_ENV_SPI_BUS=y

View File

@@ -68,6 +68,7 @@ CONFIG_LED=y
CONFIG_LED_GPIO=y CONFIG_LED_GPIO=y
CONFIG_DM_MAILBOX=y CONFIG_DM_MAILBOX=y
CONFIG_STM32_IPCC=y CONFIG_STM32_IPCC=y
CONFIG_STM32_FMC2_EBI=y
CONFIG_DM_MMC=y CONFIG_DM_MMC=y
CONFIG_SUPPORT_EMMC_BOOT=y CONFIG_SUPPORT_EMMC_BOOT=y
CONFIG_STM32_SDMMC2=y CONFIG_STM32_SDMMC2=y

View File

@@ -4,6 +4,15 @@
menu "Memory Controller drivers" menu "Memory Controller drivers"
config STM32_FMC2_EBI
bool "Support for FMC2 External Bus Interface on STM32MP SoCs"
depends on ARCH_STM32MP
help
Select this option to enable the STM32 FMC2 External Bus Interface
controller. This driver configures the transactions with external
devices (like SRAM, ethernet adapters, FPGAs, LCD displays, ...) on
SOCs containing the FMC2 External Bus Interface.
config TI_AEMIF config TI_AEMIF
tristate "Texas Instruments AEMIF driver" tristate "Texas Instruments AEMIF driver"
depends on ARCH_KEYSTONE depends on ARCH_KEYSTONE

View File

@@ -1,2 +1,3 @@
obj-$(CONFIG_STM32_FMC2_EBI) += stm32-fmc2-ebi.o
obj-$(CONFIG_TI_AEMIF) += ti-aemif.o obj-$(CONFIG_TI_AEMIF) += ti-aemif.o

File diff suppressed because it is too large Load Diff

View File

@@ -10,6 +10,7 @@
#include <log.h> #include <log.h>
#include <nand.h> #include <nand.h>
#include <reset.h> #include <reset.h>
#include <linux/bitfield.h>
#include <linux/bitops.h> #include <linux/bitops.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/err.h> #include <linux/err.h>
@@ -60,20 +61,16 @@
/* Register: FMC2_PCR */ /* Register: FMC2_PCR */
#define FMC2_PCR_PWAITEN BIT(1) #define FMC2_PCR_PWAITEN BIT(1)
#define FMC2_PCR_PBKEN BIT(2) #define FMC2_PCR_PBKEN BIT(2)
#define FMC2_PCR_PWID_MASK GENMASK(5, 4) #define FMC2_PCR_PWID GENMASK(5, 4)
#define FMC2_PCR_PWID(x) (((x) & 0x3) << 4)
#define FMC2_PCR_PWID_BUSWIDTH_8 0 #define FMC2_PCR_PWID_BUSWIDTH_8 0
#define FMC2_PCR_PWID_BUSWIDTH_16 1 #define FMC2_PCR_PWID_BUSWIDTH_16 1
#define FMC2_PCR_ECCEN BIT(6) #define FMC2_PCR_ECCEN BIT(6)
#define FMC2_PCR_ECCALG BIT(8) #define FMC2_PCR_ECCALG BIT(8)
#define FMC2_PCR_TCLR_MASK GENMASK(12, 9) #define FMC2_PCR_TCLR GENMASK(12, 9)
#define FMC2_PCR_TCLR(x) (((x) & 0xf) << 9)
#define FMC2_PCR_TCLR_DEFAULT 0xf #define FMC2_PCR_TCLR_DEFAULT 0xf
#define FMC2_PCR_TAR_MASK GENMASK(16, 13) #define FMC2_PCR_TAR GENMASK(16, 13)
#define FMC2_PCR_TAR(x) (((x) & 0xf) << 13)
#define FMC2_PCR_TAR_DEFAULT 0xf #define FMC2_PCR_TAR_DEFAULT 0xf
#define FMC2_PCR_ECCSS_MASK GENMASK(19, 17) #define FMC2_PCR_ECCSS GENMASK(19, 17)
#define FMC2_PCR_ECCSS(x) (((x) & 0x7) << 17)
#define FMC2_PCR_ECCSS_512 1 #define FMC2_PCR_ECCSS_512 1
#define FMC2_PCR_ECCSS_2048 3 #define FMC2_PCR_ECCSS_2048 3
#define FMC2_PCR_BCHECC BIT(24) #define FMC2_PCR_BCHECC BIT(24)
@@ -83,17 +80,17 @@
#define FMC2_SR_NWRF BIT(6) #define FMC2_SR_NWRF BIT(6)
/* Register: FMC2_PMEM */ /* Register: FMC2_PMEM */
#define FMC2_PMEM_MEMSET(x) (((x) & 0xff) << 0) #define FMC2_PMEM_MEMSET GENMASK(7, 0)
#define FMC2_PMEM_MEMWAIT(x) (((x) & 0xff) << 8) #define FMC2_PMEM_MEMWAIT GENMASK(15, 8)
#define FMC2_PMEM_MEMHOLD(x) (((x) & 0xff) << 16) #define FMC2_PMEM_MEMHOLD GENMASK(23, 16)
#define FMC2_PMEM_MEMHIZ(x) (((x) & 0xff) << 24) #define FMC2_PMEM_MEMHIZ GENMASK(31, 24)
#define FMC2_PMEM_DEFAULT 0x0a0a0a0a #define FMC2_PMEM_DEFAULT 0x0a0a0a0a
/* Register: FMC2_PATT */ /* Register: FMC2_PATT */
#define FMC2_PATT_ATTSET(x) (((x) & 0xff) << 0) #define FMC2_PATT_ATTSET GENMASK(7, 0)
#define FMC2_PATT_ATTWAIT(x) (((x) & 0xff) << 8) #define FMC2_PATT_ATTWAIT GENMASK(15, 8)
#define FMC2_PATT_ATTHOLD(x) (((x) & 0xff) << 16) #define FMC2_PATT_ATTHOLD GENMASK(23, 16)
#define FMC2_PATT_ATTHIZ(x) (((x) & 0xff) << 24) #define FMC2_PATT_ATTHIZ GENMASK(31, 24)
#define FMC2_PATT_DEFAULT 0x0a0a0a0a #define FMC2_PATT_DEFAULT 0x0a0a0a0a
/* Register: FMC2_BCHISR */ /* Register: FMC2_BCHISR */
@@ -106,31 +103,28 @@
/* Register: FMC2_BCHDSR0 */ /* Register: FMC2_BCHDSR0 */
#define FMC2_BCHDSR0_DUE BIT(0) #define FMC2_BCHDSR0_DUE BIT(0)
#define FMC2_BCHDSR0_DEF BIT(1) #define FMC2_BCHDSR0_DEF BIT(1)
#define FMC2_BCHDSR0_DEN_MASK GENMASK(7, 4) #define FMC2_BCHDSR0_DEN GENMASK(7, 4)
#define FMC2_BCHDSR0_DEN_SHIFT 4
/* Register: FMC2_BCHDSR1 */ /* Register: FMC2_BCHDSR1 */
#define FMC2_BCHDSR1_EBP1_MASK GENMASK(12, 0) #define FMC2_BCHDSR1_EBP1 GENMASK(12, 0)
#define FMC2_BCHDSR1_EBP2_MASK GENMASK(28, 16) #define FMC2_BCHDSR1_EBP2 GENMASK(28, 16)
#define FMC2_BCHDSR1_EBP2_SHIFT 16
/* Register: FMC2_BCHDSR2 */ /* Register: FMC2_BCHDSR2 */
#define FMC2_BCHDSR2_EBP3_MASK GENMASK(12, 0) #define FMC2_BCHDSR2_EBP3 GENMASK(12, 0)
#define FMC2_BCHDSR2_EBP4_MASK GENMASK(28, 16) #define FMC2_BCHDSR2_EBP4 GENMASK(28, 16)
#define FMC2_BCHDSR2_EBP4_SHIFT 16
/* Register: FMC2_BCHDSR3 */ /* Register: FMC2_BCHDSR3 */
#define FMC2_BCHDSR3_EBP5_MASK GENMASK(12, 0) #define FMC2_BCHDSR3_EBP5 GENMASK(12, 0)
#define FMC2_BCHDSR3_EBP6_MASK GENMASK(28, 16) #define FMC2_BCHDSR3_EBP6 GENMASK(28, 16)
#define FMC2_BCHDSR3_EBP6_SHIFT 16
/* Register: FMC2_BCHDSR4 */ /* Register: FMC2_BCHDSR4 */
#define FMC2_BCHDSR4_EBP7_MASK GENMASK(12, 0) #define FMC2_BCHDSR4_EBP7 GENMASK(12, 0)
#define FMC2_BCHDSR4_EBP8_MASK GENMASK(28, 16) #define FMC2_BCHDSR4_EBP8 GENMASK(28, 16)
#define FMC2_BCHDSR4_EBP8_SHIFT 16
#define FMC2_NSEC_PER_SEC 1000000000L #define FMC2_NSEC_PER_SEC 1000000000L
#define FMC2_TIMEOUT_5S 5000000
enum stm32_fmc2_ecc { enum stm32_fmc2_ecc {
FMC2_ECC_HAM = 1, FMC2_ECC_HAM = 1,
FMC2_ECC_BCH4 = 4, FMC2_ECC_BCH4 = 4,
@@ -164,10 +158,10 @@ struct stm32_fmc2_nfc {
struct nand_hw_control base; struct nand_hw_control base;
struct stm32_fmc2_nand nand; struct stm32_fmc2_nand nand;
struct nand_ecclayout ecclayout; struct nand_ecclayout ecclayout;
void __iomem *io_base; fdt_addr_t io_base;
void __iomem *data_base[FMC2_MAX_CE]; fdt_addr_t data_base[FMC2_MAX_CE];
void __iomem *cmd_base[FMC2_MAX_CE]; fdt_addr_t cmd_base[FMC2_MAX_CE];
void __iomem *addr_base[FMC2_MAX_CE]; fdt_addr_t addr_base[FMC2_MAX_CE];
struct clk clk; struct clk clk;
u8 cs_assigned; u8 cs_assigned;
@@ -179,47 +173,42 @@ static inline struct stm32_fmc2_nfc *to_stm32_nfc(struct nand_hw_control *base)
return container_of(base, struct stm32_fmc2_nfc, base); return container_of(base, struct stm32_fmc2_nfc, base);
} }
/* Timings configuration */ static void stm32_fmc2_nfc_timings_init(struct nand_chip *chip)
static void stm32_fmc2_timings_init(struct nand_chip *chip)
{ {
struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller); struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller);
struct stm32_fmc2_nand *nand = to_fmc2_nand(chip); struct stm32_fmc2_nand *nand = to_fmc2_nand(chip);
struct stm32_fmc2_timings *timings = &nand->timings; struct stm32_fmc2_timings *timings = &nand->timings;
u32 pcr = readl(fmc2->io_base + FMC2_PCR);
u32 pmem, patt; u32 pmem, patt;
/* Set tclr/tar timings */ /* Set tclr/tar timings */
pcr &= ~FMC2_PCR_TCLR_MASK; clrsetbits_le32(nfc->io_base + FMC2_PCR,
pcr |= FMC2_PCR_TCLR(timings->tclr); FMC2_PCR_TCLR | FMC2_PCR_TAR,
pcr &= ~FMC2_PCR_TAR_MASK; FIELD_PREP(FMC2_PCR_TCLR, timings->tclr) |
pcr |= FMC2_PCR_TAR(timings->tar); FIELD_PREP(FMC2_PCR_TAR, timings->tar));
/* Set tset/twait/thold/thiz timings in common bank */ /* Set tset/twait/thold/thiz timings in common bank */
pmem = FMC2_PMEM_MEMSET(timings->tset_mem); pmem = FIELD_PREP(FMC2_PMEM_MEMSET, timings->tset_mem);
pmem |= FMC2_PMEM_MEMWAIT(timings->twait); pmem |= FIELD_PREP(FMC2_PMEM_MEMWAIT, timings->twait);
pmem |= FMC2_PMEM_MEMHOLD(timings->thold_mem); pmem |= FIELD_PREP(FMC2_PMEM_MEMHOLD, timings->thold_mem);
pmem |= FMC2_PMEM_MEMHIZ(timings->thiz); pmem |= FIELD_PREP(FMC2_PMEM_MEMHIZ, timings->thiz);
writel(pmem, nfc->io_base + FMC2_PMEM);
/* Set tset/twait/thold/thiz timings in attribut bank */ /* Set tset/twait/thold/thiz timings in attribut bank */
patt = FMC2_PATT_ATTSET(timings->tset_att); patt = FIELD_PREP(FMC2_PATT_ATTSET, timings->tset_att);
patt |= FMC2_PATT_ATTWAIT(timings->twait); patt |= FIELD_PREP(FMC2_PATT_ATTWAIT, timings->twait);
patt |= FMC2_PATT_ATTHOLD(timings->thold_att); patt |= FIELD_PREP(FMC2_PATT_ATTHOLD, timings->thold_att);
patt |= FMC2_PATT_ATTHIZ(timings->thiz); patt |= FIELD_PREP(FMC2_PATT_ATTHIZ, timings->thiz);
writel(patt, nfc->io_base + FMC2_PATT);
writel(pcr, fmc2->io_base + FMC2_PCR);
writel(pmem, fmc2->io_base + FMC2_PMEM);
writel(patt, fmc2->io_base + FMC2_PATT);
} }
/* Controller configuration */ static void stm32_fmc2_nfc_setup(struct nand_chip *chip)
static void stm32_fmc2_setup(struct nand_chip *chip)
{ {
struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller); struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller);
u32 pcr = readl(fmc2->io_base + FMC2_PCR); u32 pcr = 0, pcr_mask;
/* Configure ECC algorithm (default configuration is Hamming) */ /* Configure ECC algorithm (default configuration is Hamming) */
pcr &= ~FMC2_PCR_ECCALG; pcr_mask = FMC2_PCR_ECCALG;
pcr &= ~FMC2_PCR_BCHECC; pcr_mask |= FMC2_PCR_BCHECC;
if (chip->ecc.strength == FMC2_ECC_BCH8) { if (chip->ecc.strength == FMC2_ECC_BCH8) {
pcr |= FMC2_PCR_ECCALG; pcr |= FMC2_PCR_ECCALG;
pcr |= FMC2_PCR_BCHECC; pcr |= FMC2_PCR_BCHECC;
@@ -228,111 +217,95 @@ static void stm32_fmc2_setup(struct nand_chip *chip)
} }
/* Set buswidth */ /* Set buswidth */
pcr &= ~FMC2_PCR_PWID_MASK; pcr_mask |= FMC2_PCR_PWID;
if (chip->options & NAND_BUSWIDTH_16) if (chip->options & NAND_BUSWIDTH_16)
pcr |= FMC2_PCR_PWID(FMC2_PCR_PWID_BUSWIDTH_16); pcr |= FIELD_PREP(FMC2_PCR_PWID, FMC2_PCR_PWID_BUSWIDTH_16);
/* Set ECC sector size */ /* Set ECC sector size */
pcr &= ~FMC2_PCR_ECCSS_MASK; pcr_mask |= FMC2_PCR_ECCSS;
pcr |= FMC2_PCR_ECCSS(FMC2_PCR_ECCSS_512); pcr |= FIELD_PREP(FMC2_PCR_ECCSS, FMC2_PCR_ECCSS_512);
writel(pcr, fmc2->io_base + FMC2_PCR); clrsetbits_le32(nfc->io_base + FMC2_PCR, pcr_mask, pcr);
} }
/* Select target */ static void stm32_fmc2_nfc_select_chip(struct mtd_info *mtd, int chipnr)
static void stm32_fmc2_select_chip(struct mtd_info *mtd, int chipnr)
{ {
struct nand_chip *chip = mtd_to_nand(mtd); struct nand_chip *chip = mtd_to_nand(mtd);
struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller); struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller);
struct stm32_fmc2_nand *nand = to_fmc2_nand(chip); struct stm32_fmc2_nand *nand = to_fmc2_nand(chip);
if (chipnr < 0 || chipnr >= nand->ncs) if (chipnr < 0 || chipnr >= nand->ncs)
return; return;
if (nand->cs_used[chipnr] == fmc2->cs_sel) if (nand->cs_used[chipnr] == nfc->cs_sel)
return; return;
fmc2->cs_sel = nand->cs_used[chipnr]; nfc->cs_sel = nand->cs_used[chipnr];
chip->IO_ADDR_R = fmc2->data_base[fmc2->cs_sel]; chip->IO_ADDR_R = (void __iomem *)nfc->data_base[nfc->cs_sel];
chip->IO_ADDR_W = fmc2->data_base[fmc2->cs_sel]; chip->IO_ADDR_W = (void __iomem *)nfc->data_base[nfc->cs_sel];
/* FMC2 setup routine */ stm32_fmc2_nfc_setup(chip);
stm32_fmc2_setup(chip); stm32_fmc2_nfc_timings_init(chip);
/* Apply timings */
stm32_fmc2_timings_init(chip);
} }
/* Set bus width to 16-bit or 8-bit */ static void stm32_fmc2_nfc_set_buswidth_16(struct stm32_fmc2_nfc *nfc,
static void stm32_fmc2_set_buswidth_16(struct stm32_fmc2_nfc *fmc2, bool set) bool set)
{ {
u32 pcr = readl(fmc2->io_base + FMC2_PCR); u32 pcr;
pcr &= ~FMC2_PCR_PWID_MASK; pcr = set ? FIELD_PREP(FMC2_PCR_PWID, FMC2_PCR_PWID_BUSWIDTH_16) :
if (set) FIELD_PREP(FMC2_PCR_PWID, FMC2_PCR_PWID_BUSWIDTH_8);
pcr |= FMC2_PCR_PWID(FMC2_PCR_PWID_BUSWIDTH_16);
writel(pcr, fmc2->io_base + FMC2_PCR); clrsetbits_le32(nfc->io_base + FMC2_PCR, FMC2_PCR_PWID, pcr);
} }
/* Enable/disable ECC */ static void stm32_fmc2_nfc_set_ecc(struct stm32_fmc2_nfc *nfc, bool enable)
static void stm32_fmc2_set_ecc(struct stm32_fmc2_nfc *fmc2, bool enable)
{ {
u32 pcr = readl(fmc2->io_base + FMC2_PCR); clrsetbits_le32(nfc->io_base + FMC2_PCR, FMC2_PCR_ECCEN,
enable ? FMC2_PCR_ECCEN : 0);
pcr &= ~FMC2_PCR_ECCEN;
if (enable)
pcr |= FMC2_PCR_ECCEN;
writel(pcr, fmc2->io_base + FMC2_PCR);
} }
/* Clear irq sources in case of bch is used */ static void stm32_fmc2_nfc_clear_bch_irq(struct stm32_fmc2_nfc *nfc)
static inline void stm32_fmc2_clear_bch_irq(struct stm32_fmc2_nfc *fmc2)
{ {
writel(FMC2_BCHICR_CLEAR_IRQ, fmc2->io_base + FMC2_BCHICR); writel(FMC2_BCHICR_CLEAR_IRQ, nfc->io_base + FMC2_BCHICR);
} }
/* Send command and address cycles */ static void stm32_fmc2_nfc_cmd_ctrl(struct mtd_info *mtd, int cmd,
static void stm32_fmc2_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
unsigned int ctrl)
{ {
struct nand_chip *chip = mtd_to_nand(mtd); struct nand_chip *chip = mtd_to_nand(mtd);
struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller); struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller);
if (cmd == NAND_CMD_NONE) if (cmd == NAND_CMD_NONE)
return; return;
if (ctrl & NAND_CLE) { if (ctrl & NAND_CLE) {
writeb(cmd, fmc2->cmd_base[fmc2->cs_sel]); writeb(cmd, nfc->cmd_base[nfc->cs_sel]);
return; return;
} }
writeb(cmd, fmc2->addr_base[fmc2->cs_sel]); writeb(cmd, nfc->addr_base[nfc->cs_sel]);
} }
/* /*
* Enable ECC logic and reset syndrome/parity bits previously calculated * Enable ECC logic and reset syndrome/parity bits previously calculated
* Syndrome/parity bits is cleared by setting the ECCEN bit to 0 * Syndrome/parity bits is cleared by setting the ECCEN bit to 0
*/ */
static void stm32_fmc2_hwctl(struct mtd_info *mtd, int mode) static void stm32_fmc2_nfc_hwctl(struct mtd_info *mtd, int mode)
{ {
struct nand_chip *chip = mtd_to_nand(mtd); struct nand_chip *chip = mtd_to_nand(mtd);
struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller); struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller);
stm32_fmc2_set_ecc(fmc2, false); stm32_fmc2_nfc_set_ecc(nfc, false);
if (chip->ecc.strength != FMC2_ECC_HAM) { if (chip->ecc.strength != FMC2_ECC_HAM) {
u32 pcr = readl(fmc2->io_base + FMC2_PCR); clrsetbits_le32(nfc->io_base + FMC2_PCR, FMC2_PCR_WEN,
mode == NAND_ECC_WRITE ? FMC2_PCR_WEN : 0);
if (mode == NAND_ECC_WRITE) stm32_fmc2_nfc_clear_bch_irq(nfc);
pcr |= FMC2_PCR_WEN;
else
pcr &= ~FMC2_PCR_WEN;
writel(pcr, fmc2->io_base + FMC2_PCR);
stm32_fmc2_clear_bch_irq(fmc2);
} }
stm32_fmc2_set_ecc(fmc2, true); stm32_fmc2_nfc_set_ecc(nfc, true);
} }
/* /*
@@ -340,35 +313,34 @@ static void stm32_fmc2_hwctl(struct mtd_info *mtd, int mode)
* ECC is 3 bytes for 512 bytes of data (supports error correction up to * ECC is 3 bytes for 512 bytes of data (supports error correction up to
* max of 1-bit) * max of 1-bit)
*/ */
static int stm32_fmc2_ham_calculate(struct mtd_info *mtd, const u8 *data, static int stm32_fmc2_nfc_ham_calculate(struct mtd_info *mtd, const u8 *data,
u8 *ecc) u8 *ecc)
{ {
struct nand_chip *chip = mtd_to_nand(mtd); struct nand_chip *chip = mtd_to_nand(mtd);
struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller); struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller);
u32 heccr, sr; u32 heccr, sr;
int ret; int ret;
ret = readl_poll_timeout(fmc2->io_base + FMC2_SR, sr, ret = readl_poll_timeout(nfc->io_base + FMC2_SR, sr,
sr & FMC2_SR_NWRF, 10000); sr & FMC2_SR_NWRF, FMC2_TIMEOUT_5S);
if (ret < 0) { if (ret < 0) {
pr_err("Ham timeout\n"); pr_err("Ham timeout\n");
return ret; return ret;
} }
heccr = readl(fmc2->io_base + FMC2_HECCR); heccr = readl(nfc->io_base + FMC2_HECCR);
ecc[0] = heccr; ecc[0] = heccr;
ecc[1] = heccr >> 8; ecc[1] = heccr >> 8;
ecc[2] = heccr >> 16; ecc[2] = heccr >> 16;
/* Disable ecc */ stm32_fmc2_nfc_set_ecc(nfc, false);
stm32_fmc2_set_ecc(fmc2, false);
return 0; return 0;
} }
static int stm32_fmc2_ham_correct(struct mtd_info *mtd, u8 *dat, static int stm32_fmc2_nfc_ham_correct(struct mtd_info *mtd, u8 *dat,
u8 *read_ecc, u8 *calc_ecc) u8 *read_ecc, u8 *calc_ecc)
{ {
u8 bit_position = 0, b0, b1, b2; u8 bit_position = 0, b0, b1, b2;
u32 byte_addr = 0, b; u32 byte_addr = 0, b;
@@ -425,30 +397,30 @@ static int stm32_fmc2_ham_correct(struct mtd_info *mtd, u8 *dat,
* max of 4-bit/8-bit) * max of 4-bit/8-bit)
*/ */
static int stm32_fmc2_bch_calculate(struct mtd_info *mtd, const u8 *data, static int stm32_fmc2_nfc_bch_calculate(struct mtd_info *mtd, const u8 *data,
u8 *ecc) u8 *ecc)
{ {
struct nand_chip *chip = mtd_to_nand(mtd); struct nand_chip *chip = mtd_to_nand(mtd);
struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller); struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller);
u32 bchpbr, bchisr; u32 bchpbr, bchisr;
int ret; int ret;
/* Wait until the BCH code is ready */ /* Wait until the BCH code is ready */
ret = readl_poll_timeout(fmc2->io_base + FMC2_BCHISR, bchisr, ret = readl_poll_timeout(nfc->io_base + FMC2_BCHISR, bchisr,
bchisr & FMC2_BCHISR_EPBRF, 10000); bchisr & FMC2_BCHISR_EPBRF, FMC2_TIMEOUT_5S);
if (ret < 0) { if (ret < 0) {
pr_err("Bch timeout\n"); pr_err("Bch timeout\n");
return ret; return ret;
} }
/* Read parity bits */ /* Read parity bits */
bchpbr = readl(fmc2->io_base + FMC2_BCHPBR1); bchpbr = readl(nfc->io_base + FMC2_BCHPBR1);
ecc[0] = bchpbr; ecc[0] = bchpbr;
ecc[1] = bchpbr >> 8; ecc[1] = bchpbr >> 8;
ecc[2] = bchpbr >> 16; ecc[2] = bchpbr >> 16;
ecc[3] = bchpbr >> 24; ecc[3] = bchpbr >> 24;
bchpbr = readl(fmc2->io_base + FMC2_BCHPBR2); bchpbr = readl(nfc->io_base + FMC2_BCHPBR2);
ecc[4] = bchpbr; ecc[4] = bchpbr;
ecc[5] = bchpbr >> 8; ecc[5] = bchpbr >> 8;
ecc[6] = bchpbr >> 16; ecc[6] = bchpbr >> 16;
@@ -456,49 +428,46 @@ static int stm32_fmc2_bch_calculate(struct mtd_info *mtd, const u8 *data,
if (chip->ecc.strength == FMC2_ECC_BCH8) { if (chip->ecc.strength == FMC2_ECC_BCH8) {
ecc[7] = bchpbr >> 24; ecc[7] = bchpbr >> 24;
bchpbr = readl(fmc2->io_base + FMC2_BCHPBR3); bchpbr = readl(nfc->io_base + FMC2_BCHPBR3);
ecc[8] = bchpbr; ecc[8] = bchpbr;
ecc[9] = bchpbr >> 8; ecc[9] = bchpbr >> 8;
ecc[10] = bchpbr >> 16; ecc[10] = bchpbr >> 16;
ecc[11] = bchpbr >> 24; ecc[11] = bchpbr >> 24;
bchpbr = readl(fmc2->io_base + FMC2_BCHPBR4); bchpbr = readl(nfc->io_base + FMC2_BCHPBR4);
ecc[12] = bchpbr; ecc[12] = bchpbr;
} }
/* Disable ecc */ stm32_fmc2_nfc_set_ecc(nfc, false);
stm32_fmc2_set_ecc(fmc2, false);
return 0; return 0;
} }
/* BCH algorithm correction */ static int stm32_fmc2_nfc_bch_correct(struct mtd_info *mtd, u8 *dat,
static int stm32_fmc2_bch_correct(struct mtd_info *mtd, u8 *dat, u8 *read_ecc, u8 *calc_ecc)
u8 *read_ecc, u8 *calc_ecc)
{ {
struct nand_chip *chip = mtd_to_nand(mtd); struct nand_chip *chip = mtd_to_nand(mtd);
struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller); struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller);
u32 bchdsr0, bchdsr1, bchdsr2, bchdsr3, bchdsr4, bchisr; u32 bchdsr0, bchdsr1, bchdsr2, bchdsr3, bchdsr4, bchisr;
u16 pos[8]; u16 pos[8];
int i, ret, den, eccsize = chip->ecc.size; int i, ret, den, eccsize = chip->ecc.size;
unsigned int nb_errs = 0; unsigned int nb_errs = 0;
/* Wait until the decoding error is ready */ /* Wait until the decoding error is ready */
ret = readl_poll_timeout(fmc2->io_base + FMC2_BCHISR, bchisr, ret = readl_poll_timeout(nfc->io_base + FMC2_BCHISR, bchisr,
bchisr & FMC2_BCHISR_DERF, 10000); bchisr & FMC2_BCHISR_DERF, FMC2_TIMEOUT_5S);
if (ret < 0) { if (ret < 0) {
pr_err("Bch timeout\n"); pr_err("Bch timeout\n");
return ret; return ret;
} }
bchdsr0 = readl(fmc2->io_base + FMC2_BCHDSR0); bchdsr0 = readl(nfc->io_base + FMC2_BCHDSR0);
bchdsr1 = readl(fmc2->io_base + FMC2_BCHDSR1); bchdsr1 = readl(nfc->io_base + FMC2_BCHDSR1);
bchdsr2 = readl(fmc2->io_base + FMC2_BCHDSR2); bchdsr2 = readl(nfc->io_base + FMC2_BCHDSR2);
bchdsr3 = readl(fmc2->io_base + FMC2_BCHDSR3); bchdsr3 = readl(nfc->io_base + FMC2_BCHDSR3);
bchdsr4 = readl(fmc2->io_base + FMC2_BCHDSR4); bchdsr4 = readl(nfc->io_base + FMC2_BCHDSR4);
/* Disable ECC */ stm32_fmc2_nfc_set_ecc(nfc, false);
stm32_fmc2_set_ecc(fmc2, false);
/* No errors found */ /* No errors found */
if (likely(!(bchdsr0 & FMC2_BCHDSR0_DEF))) if (likely(!(bchdsr0 & FMC2_BCHDSR0_DEF)))
@@ -508,16 +477,16 @@ static int stm32_fmc2_bch_correct(struct mtd_info *mtd, u8 *dat,
if (unlikely(bchdsr0 & FMC2_BCHDSR0_DUE)) if (unlikely(bchdsr0 & FMC2_BCHDSR0_DUE))
return -EBADMSG; return -EBADMSG;
pos[0] = bchdsr1 & FMC2_BCHDSR1_EBP1_MASK; pos[0] = FIELD_GET(FMC2_BCHDSR1_EBP1, bchdsr1);
pos[1] = (bchdsr1 & FMC2_BCHDSR1_EBP2_MASK) >> FMC2_BCHDSR1_EBP2_SHIFT; pos[1] = FIELD_GET(FMC2_BCHDSR1_EBP2, bchdsr1);
pos[2] = bchdsr2 & FMC2_BCHDSR2_EBP3_MASK; pos[2] = FIELD_GET(FMC2_BCHDSR2_EBP3, bchdsr2);
pos[3] = (bchdsr2 & FMC2_BCHDSR2_EBP4_MASK) >> FMC2_BCHDSR2_EBP4_SHIFT; pos[3] = FIELD_GET(FMC2_BCHDSR2_EBP4, bchdsr2);
pos[4] = bchdsr3 & FMC2_BCHDSR3_EBP5_MASK; pos[4] = FIELD_GET(FMC2_BCHDSR3_EBP5, bchdsr3);
pos[5] = (bchdsr3 & FMC2_BCHDSR3_EBP6_MASK) >> FMC2_BCHDSR3_EBP6_SHIFT; pos[5] = FIELD_GET(FMC2_BCHDSR3_EBP6, bchdsr3);
pos[6] = bchdsr4 & FMC2_BCHDSR4_EBP7_MASK; pos[6] = FIELD_GET(FMC2_BCHDSR4_EBP7, bchdsr4);
pos[7] = (bchdsr4 & FMC2_BCHDSR4_EBP8_MASK) >> FMC2_BCHDSR4_EBP8_SHIFT; pos[7] = FIELD_GET(FMC2_BCHDSR4_EBP8, bchdsr4);
den = (bchdsr0 & FMC2_BCHDSR0_DEN_MASK) >> FMC2_BCHDSR0_DEN_SHIFT; den = FIELD_GET(FMC2_BCHDSR0_DEN, bchdsr0);
for (i = 0; i < den; i++) { for (i = 0; i < den; i++) {
if (pos[i] < eccsize * 8) { if (pos[i] < eccsize * 8) {
__change_bit(pos[i], (unsigned long *)dat); __change_bit(pos[i], (unsigned long *)dat);
@@ -528,9 +497,9 @@ static int stm32_fmc2_bch_correct(struct mtd_info *mtd, u8 *dat,
return nb_errs; return nb_errs;
} }
static int stm32_fmc2_read_page(struct mtd_info *mtd, static int stm32_fmc2_nfc_read_page(struct mtd_info *mtd,
struct nand_chip *chip, u8 *buf, struct nand_chip *chip, u8 *buf,
int oob_required, int page) int oob_required, int page)
{ {
int i, s, stat, eccsize = chip->ecc.size; int i, s, stat, eccsize = chip->ecc.size;
int eccbytes = chip->ecc.bytes; int eccbytes = chip->ecc.bytes;
@@ -579,21 +548,19 @@ static int stm32_fmc2_read_page(struct mtd_info *mtd,
return max_bitflips; return max_bitflips;
} }
/* Controller initialization */ static void stm32_fmc2_nfc_init(struct stm32_fmc2_nfc *nfc, bool has_parent)
static void stm32_fmc2_init(struct stm32_fmc2_nfc *fmc2)
{ {
u32 pcr = readl(fmc2->io_base + FMC2_PCR); u32 pcr = readl(nfc->io_base + FMC2_PCR);
u32 bcr1 = readl(fmc2->io_base + FMC2_BCR1);
/* Set CS used to undefined */ /* Set CS used to undefined */
fmc2->cs_sel = -1; nfc->cs_sel = -1;
/* Enable wait feature and nand flash memory bank */ /* Enable wait feature and nand flash memory bank */
pcr |= FMC2_PCR_PWAITEN; pcr |= FMC2_PCR_PWAITEN;
pcr |= FMC2_PCR_PBKEN; pcr |= FMC2_PCR_PBKEN;
/* Set buswidth to 8 bits mode for identification */ /* Set buswidth to 8 bits mode for identification */
pcr &= ~FMC2_PCR_PWID_MASK; pcr &= ~FMC2_PCR_PWID;
/* ECC logic is disabled */ /* ECC logic is disabled */
pcr &= ~FMC2_PCR_ECCEN; pcr &= ~FMC2_PCR_ECCEN;
@@ -604,32 +571,31 @@ static void stm32_fmc2_init(struct stm32_fmc2_nfc *fmc2)
pcr &= ~FMC2_PCR_WEN; pcr &= ~FMC2_PCR_WEN;
/* Set default ECC sector size */ /* Set default ECC sector size */
pcr &= ~FMC2_PCR_ECCSS_MASK; pcr &= ~FMC2_PCR_ECCSS;
pcr |= FMC2_PCR_ECCSS(FMC2_PCR_ECCSS_2048); pcr |= FIELD_PREP(FMC2_PCR_ECCSS, FMC2_PCR_ECCSS_2048);
/* Set default tclr/tar timings */ /* Set default tclr/tar timings */
pcr &= ~FMC2_PCR_TCLR_MASK; pcr &= ~FMC2_PCR_TCLR;
pcr |= FMC2_PCR_TCLR(FMC2_PCR_TCLR_DEFAULT); pcr |= FIELD_PREP(FMC2_PCR_TCLR, FMC2_PCR_TCLR_DEFAULT);
pcr &= ~FMC2_PCR_TAR_MASK; pcr &= ~FMC2_PCR_TAR;
pcr |= FMC2_PCR_TAR(FMC2_PCR_TAR_DEFAULT); pcr |= FIELD_PREP(FMC2_PCR_TAR, FMC2_PCR_TAR_DEFAULT);
/* Enable FMC2 controller */ /* Enable FMC2 controller */
bcr1 |= FMC2_BCR1_FMC2EN; if (!has_parent)
setbits_le32(nfc->io_base + FMC2_BCR1, FMC2_BCR1_FMC2EN);
writel(bcr1, fmc2->io_base + FMC2_BCR1); writel(pcr, nfc->io_base + FMC2_PCR);
writel(pcr, fmc2->io_base + FMC2_PCR); writel(FMC2_PMEM_DEFAULT, nfc->io_base + FMC2_PMEM);
writel(FMC2_PMEM_DEFAULT, fmc2->io_base + FMC2_PMEM); writel(FMC2_PATT_DEFAULT, nfc->io_base + FMC2_PATT);
writel(FMC2_PATT_DEFAULT, fmc2->io_base + FMC2_PATT);
} }
/* Controller timings */ static void stm32_fmc2_nfc_calc_timings(struct nand_chip *chip,
static void stm32_fmc2_calc_timings(struct nand_chip *chip, const struct nand_sdr_timings *sdrt)
const struct nand_sdr_timings *sdrt)
{ {
struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller); struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller);
struct stm32_fmc2_nand *nand = to_fmc2_nand(chip); struct stm32_fmc2_nand *nand = to_fmc2_nand(chip);
struct stm32_fmc2_timings *tims = &nand->timings; struct stm32_fmc2_timings *tims = &nand->timings;
unsigned long hclk = clk_get_rate(&fmc2->clk); unsigned long hclk = clk_get_rate(&nfc->clk);
unsigned long hclkp = FMC2_NSEC_PER_SEC / (hclk / 1000); unsigned long hclkp = FMC2_NSEC_PER_SEC / (hclk / 1000);
unsigned long timing, tar, tclr, thiz, twait; unsigned long timing, tar, tclr, thiz, twait;
unsigned long tset_mem, tset_att, thold_mem, thold_att; unsigned long tset_mem, tset_att, thold_mem, thold_att;
@@ -753,31 +719,28 @@ static void stm32_fmc2_calc_timings(struct nand_chip *chip,
tims->thold_att = clamp_val(timing, 1, FMC2_PMEM_PATT_TIMING_MASK); tims->thold_att = clamp_val(timing, 1, FMC2_PMEM_PATT_TIMING_MASK);
} }
static int stm32_fmc2_setup_interface(struct mtd_info *mtd, int chipnr, static int stm32_fmc2_nfc_setup_interface(struct mtd_info *mtd, int chipnr,
const struct nand_data_interface *conf) const struct nand_data_interface *cf)
{ {
struct nand_chip *chip = mtd_to_nand(mtd); struct nand_chip *chip = mtd_to_nand(mtd);
const struct nand_sdr_timings *sdrt; const struct nand_sdr_timings *sdrt;
sdrt = nand_get_sdr_timings(conf); sdrt = nand_get_sdr_timings(cf);
if (IS_ERR(sdrt)) if (IS_ERR(sdrt))
return PTR_ERR(sdrt); return PTR_ERR(sdrt);
if (chipnr == NAND_DATA_IFACE_CHECK_ONLY) if (chipnr == NAND_DATA_IFACE_CHECK_ONLY)
return 0; return 0;
stm32_fmc2_calc_timings(chip, sdrt); stm32_fmc2_nfc_calc_timings(chip, sdrt);
stm32_fmc2_nfc_timings_init(chip);
/* Apply timings */
stm32_fmc2_timings_init(chip);
return 0; return 0;
} }
/* NAND callbacks setup */ static void stm32_fmc2_nfc_nand_callbacks_setup(struct nand_chip *chip)
static void stm32_fmc2_nand_callbacks_setup(struct nand_chip *chip)
{ {
chip->ecc.hwctl = stm32_fmc2_hwctl; chip->ecc.hwctl = stm32_fmc2_nfc_hwctl;
/* /*
* Specific callbacks to read/write a page depending on * Specific callbacks to read/write a page depending on
@@ -785,17 +748,17 @@ static void stm32_fmc2_nand_callbacks_setup(struct nand_chip *chip)
*/ */
if (chip->ecc.strength == FMC2_ECC_HAM) { if (chip->ecc.strength == FMC2_ECC_HAM) {
/* Hamming is used */ /* Hamming is used */
chip->ecc.calculate = stm32_fmc2_ham_calculate; chip->ecc.calculate = stm32_fmc2_nfc_ham_calculate;
chip->ecc.correct = stm32_fmc2_ham_correct; chip->ecc.correct = stm32_fmc2_nfc_ham_correct;
chip->ecc.bytes = chip->options & NAND_BUSWIDTH_16 ? 4 : 3; chip->ecc.bytes = chip->options & NAND_BUSWIDTH_16 ? 4 : 3;
chip->ecc.options |= NAND_ECC_GENERIC_ERASED_CHECK; chip->ecc.options |= NAND_ECC_GENERIC_ERASED_CHECK;
return; return;
} }
/* BCH is used */ /* BCH is used */
chip->ecc.read_page = stm32_fmc2_read_page; chip->ecc.read_page = stm32_fmc2_nfc_read_page;
chip->ecc.calculate = stm32_fmc2_bch_calculate; chip->ecc.calculate = stm32_fmc2_nfc_bch_calculate;
chip->ecc.correct = stm32_fmc2_bch_correct; chip->ecc.correct = stm32_fmc2_nfc_bch_correct;
if (chip->ecc.strength == FMC2_ECC_BCH8) if (chip->ecc.strength == FMC2_ECC_BCH8)
chip->ecc.bytes = chip->options & NAND_BUSWIDTH_16 ? 14 : 13; chip->ecc.bytes = chip->options & NAND_BUSWIDTH_16 ? 14 : 13;
@@ -803,8 +766,7 @@ static void stm32_fmc2_nand_callbacks_setup(struct nand_chip *chip)
chip->ecc.bytes = chip->options & NAND_BUSWIDTH_16 ? 8 : 7; chip->ecc.bytes = chip->options & NAND_BUSWIDTH_16 ? 8 : 7;
} }
/* FMC2 caps */ static int stm32_fmc2_nfc_calc_ecc_bytes(int step_size, int strength)
static int stm32_fmc2_calc_ecc_bytes(int step_size, int strength)
{ {
/* Hamming */ /* Hamming */
if (strength == FMC2_ECC_HAM) if (strength == FMC2_ECC_HAM)
@@ -818,15 +780,13 @@ static int stm32_fmc2_calc_ecc_bytes(int step_size, int strength)
return 8; return 8;
} }
NAND_ECC_CAPS_SINGLE(stm32_fmc2_ecc_caps, stm32_fmc2_calc_ecc_bytes, NAND_ECC_CAPS_SINGLE(stm32_fmc2_nfc_ecc_caps, stm32_fmc2_nfc_calc_ecc_bytes,
FMC2_ECC_STEP_SIZE, FMC2_ECC_STEP_SIZE,
FMC2_ECC_HAM, FMC2_ECC_BCH4, FMC2_ECC_BCH8); FMC2_ECC_HAM, FMC2_ECC_BCH4, FMC2_ECC_BCH8);
/* FMC2 probe */ static int stm32_fmc2_nfc_parse_child(struct stm32_fmc2_nfc *nfc, ofnode node)
static int stm32_fmc2_parse_child(struct stm32_fmc2_nfc *fmc2,
ofnode node)
{ {
struct stm32_fmc2_nand *nand = &fmc2->nand; struct stm32_fmc2_nand *nand = &nfc->nand;
u32 cs[FMC2_MAX_CE]; u32 cs[FMC2_MAX_CE];
int ret, i; int ret, i;
@@ -846,19 +806,19 @@ static int stm32_fmc2_parse_child(struct stm32_fmc2_nfc *fmc2,
} }
for (i = 0; i < nand->ncs; i++) { for (i = 0; i < nand->ncs; i++) {
if (cs[i] > FMC2_MAX_CE) { if (cs[i] >= FMC2_MAX_CE) {
pr_err("Invalid reg value: %d\n", pr_err("Invalid reg value: %d\n",
nand->cs_used[i]); nand->cs_used[i]);
return -EINVAL; return -EINVAL;
} }
if (fmc2->cs_assigned & BIT(cs[i])) { if (nfc->cs_assigned & BIT(cs[i])) {
pr_err("Cs already assigned: %d\n", pr_err("Cs already assigned: %d\n",
nand->cs_used[i]); nand->cs_used[i]);
return -EINVAL; return -EINVAL;
} }
fmc2->cs_assigned |= BIT(cs[i]); nfc->cs_assigned |= BIT(cs[i]);
nand->cs_used[i] = cs[i]; nand->cs_used[i] = cs[i];
} }
@@ -867,8 +827,8 @@ static int stm32_fmc2_parse_child(struct stm32_fmc2_nfc *fmc2,
return 0; return 0;
} }
static int stm32_fmc2_parse_dt(struct udevice *dev, static int stm32_fmc2_nfc_parse_dt(struct udevice *dev,
struct stm32_fmc2_nfc *fmc2) struct stm32_fmc2_nfc *nfc)
{ {
ofnode child; ofnode child;
int ret, nchips = 0; int ret, nchips = 0;
@@ -887,7 +847,7 @@ static int stm32_fmc2_parse_dt(struct udevice *dev,
} }
dev_for_each_subnode(child, dev) { dev_for_each_subnode(child, dev) {
ret = stm32_fmc2_parse_child(fmc2, child); ret = stm32_fmc2_nfc_parse_child(nfc, child);
if (ret) if (ret)
return ret; return ret;
} }
@@ -895,69 +855,98 @@ static int stm32_fmc2_parse_dt(struct udevice *dev,
return 0; return 0;
} }
static int stm32_fmc2_probe(struct udevice *dev) static struct udevice *stm32_fmc2_nfc_get_cdev(struct udevice *dev)
{ {
struct stm32_fmc2_nfc *fmc2 = dev_get_priv(dev); struct udevice *pdev = dev_get_parent(dev);
struct stm32_fmc2_nand *nand = &fmc2->nand; struct udevice *cdev = NULL;
bool ebi_found = false;
if (pdev && ofnode_device_is_compatible(dev_ofnode(pdev),
"st,stm32mp1-fmc2-ebi"))
ebi_found = true;
if (ofnode_device_is_compatible(dev_ofnode(dev),
"st,stm32mp1-fmc2-nfc")) {
if (ebi_found)
cdev = pdev;
return cdev;
}
if (!ebi_found)
cdev = dev;
return cdev;
}
static int stm32_fmc2_nfc_probe(struct udevice *dev)
{
struct stm32_fmc2_nfc *nfc = dev_get_priv(dev);
struct stm32_fmc2_nand *nand = &nfc->nand;
struct nand_chip *chip = &nand->chip; struct nand_chip *chip = &nand->chip;
struct mtd_info *mtd = &chip->mtd; struct mtd_info *mtd = &chip->mtd;
struct nand_ecclayout *ecclayout; struct nand_ecclayout *ecclayout;
struct resource resource; struct udevice *cdev;
struct reset_ctl reset; struct reset_ctl reset;
int oob_index, chip_cs, mem_region, ret; int oob_index, chip_cs, mem_region, ret;
unsigned int i; unsigned int i;
int start_region = 0;
fdt_addr_t addr;
spin_lock_init(&fmc2->controller.lock); spin_lock_init(&nfc->controller.lock);
init_waitqueue_head(&fmc2->controller.wq); init_waitqueue_head(&nfc->controller.wq);
ret = stm32_fmc2_parse_dt(dev, fmc2); cdev = stm32_fmc2_nfc_get_cdev(dev);
if (!cdev)
return -EINVAL;
ret = stm32_fmc2_nfc_parse_dt(dev, nfc);
if (ret) if (ret)
return ret; return ret;
/* Get resources */ nfc->io_base = dev_read_addr(cdev);
ret = dev_read_resource(dev, 0, &resource); if (nfc->io_base == FDT_ADDR_T_NONE)
if (ret) { return -EINVAL;
pr_err("Resource io_base not found");
return ret;
}
fmc2->io_base = (void __iomem *)resource.start;
for (chip_cs = 0, mem_region = 1; chip_cs < FMC2_MAX_CE; if (dev == cdev)
start_region = 1;
for (chip_cs = 0, mem_region = start_region; chip_cs < FMC2_MAX_CE;
chip_cs++, mem_region += 3) { chip_cs++, mem_region += 3) {
if (!(fmc2->cs_assigned & BIT(chip_cs))) if (!(nfc->cs_assigned & BIT(chip_cs)))
continue; continue;
ret = dev_read_resource(dev, mem_region, &resource); addr = dev_read_addr_index(dev, mem_region);
if (ret) { if (addr == FDT_ADDR_T_NONE) {
pr_err("Resource data_base not found for cs%d", pr_err("Resource data_base not found for cs%d",
chip_cs); chip_cs);
return ret; return ret;
} }
fmc2->data_base[chip_cs] = (void __iomem *)resource.start; nfc->data_base[chip_cs] = addr;
ret = dev_read_resource(dev, mem_region + 1, &resource); addr = dev_read_addr_index(dev, mem_region + 1);
if (ret) { if (addr == FDT_ADDR_T_NONE) {
pr_err("Resource cmd_base not found for cs%d", pr_err("Resource cmd_base not found for cs%d",
chip_cs); chip_cs);
return ret; return ret;
} }
fmc2->cmd_base[chip_cs] = (void __iomem *)resource.start; nfc->cmd_base[chip_cs] = addr;
ret = dev_read_resource(dev, mem_region + 2, &resource); addr = dev_read_addr_index(dev, mem_region + 2);
if (ret) { if (addr == FDT_ADDR_T_NONE) {
pr_err("Resource addr_base not found for cs%d", pr_err("Resource addr_base not found for cs%d",
chip_cs); chip_cs);
return ret; return ret;
} }
fmc2->addr_base[chip_cs] = (void __iomem *)resource.start; nfc->addr_base[chip_cs] = addr;
} }
/* Enable the clock */ /* Enable the clock */
ret = clk_get_by_index(dev, 0, &fmc2->clk); ret = clk_get_by_index(cdev, 0, &nfc->clk);
if (ret) if (ret)
return ret; return ret;
ret = clk_enable(&fmc2->clk); ret = clk_enable(&nfc->clk);
if (ret) if (ret)
return ret; return ret;
@@ -969,13 +958,12 @@ static int stm32_fmc2_probe(struct udevice *dev)
reset_deassert(&reset); reset_deassert(&reset);
} }
/* FMC2 init routine */ stm32_fmc2_nfc_init(nfc, dev != cdev);
stm32_fmc2_init(fmc2);
chip->controller = &fmc2->base; chip->controller = &nfc->base;
chip->select_chip = stm32_fmc2_select_chip; chip->select_chip = stm32_fmc2_nfc_select_chip;
chip->setup_data_interface = stm32_fmc2_setup_interface; chip->setup_data_interface = stm32_fmc2_nfc_setup_interface;
chip->cmd_ctrl = stm32_fmc2_cmd_ctrl; chip->cmd_ctrl = stm32_fmc2_nfc_cmd_ctrl;
chip->chip_delay = FMC2_RB_DELAY_US; chip->chip_delay = FMC2_RB_DELAY_US;
chip->options |= NAND_BUSWIDTH_AUTO | NAND_NO_SUBPAGE_WRITE | chip->options |= NAND_BUSWIDTH_AUTO | NAND_NO_SUBPAGE_WRITE |
NAND_USE_BOUNCE_BUFFER; NAND_USE_BOUNCE_BUFFER;
@@ -985,7 +973,6 @@ static int stm32_fmc2_probe(struct udevice *dev)
chip->ecc.size = FMC2_ECC_STEP_SIZE; chip->ecc.size = FMC2_ECC_STEP_SIZE;
chip->ecc.strength = FMC2_ECC_BCH8; chip->ecc.strength = FMC2_ECC_BCH8;
/* Scan to find existence of the device */
ret = nand_scan_ident(mtd, nand->ncs, NULL); ret = nand_scan_ident(mtd, nand->ncs, NULL);
if (ret) if (ret)
return ret; return ret;
@@ -1002,7 +989,7 @@ static int stm32_fmc2_probe(struct udevice *dev)
return -EINVAL; return -EINVAL;
} }
ret = nand_check_ecc_caps(chip, &stm32_fmc2_ecc_caps, ret = nand_check_ecc_caps(chip, &stm32_fmc2_nfc_ecc_caps,
mtd->oobsize - FMC2_BBM_LEN); mtd->oobsize - FMC2_BBM_LEN);
if (ret) { if (ret) {
pr_err("No valid ECC settings set\n"); pr_err("No valid ECC settings set\n");
@@ -1012,11 +999,10 @@ static int stm32_fmc2_probe(struct udevice *dev)
if (chip->bbt_options & NAND_BBT_USE_FLASH) if (chip->bbt_options & NAND_BBT_USE_FLASH)
chip->bbt_options |= NAND_BBT_NO_OOB; chip->bbt_options |= NAND_BBT_NO_OOB;
/* NAND callbacks setup */ stm32_fmc2_nfc_nand_callbacks_setup(chip);
stm32_fmc2_nand_callbacks_setup(chip);
/* Define ECC layout */ /* Define ECC layout */
ecclayout = &fmc2->ecclayout; ecclayout = &nfc->ecclayout;
ecclayout->eccbytes = chip->ecc.bytes * ecclayout->eccbytes = chip->ecc.bytes *
(mtd->writesize / chip->ecc.size); (mtd->writesize / chip->ecc.size);
oob_index = FMC2_BBM_LEN; oob_index = FMC2_BBM_LEN;
@@ -1026,11 +1012,9 @@ static int stm32_fmc2_probe(struct udevice *dev)
ecclayout->oobfree->length = mtd->oobsize - ecclayout->oobfree->offset; ecclayout->oobfree->length = mtd->oobsize - ecclayout->oobfree->offset;
chip->ecc.layout = ecclayout; chip->ecc.layout = ecclayout;
/* Configure bus width to 16-bit */
if (chip->options & NAND_BUSWIDTH_16) if (chip->options & NAND_BUSWIDTH_16)
stm32_fmc2_set_buswidth_16(fmc2, true); stm32_fmc2_nfc_set_buswidth_16(nfc, true);
/* Scan the device to fill MTD data-structures */
ret = nand_scan_tail(mtd); ret = nand_scan_tail(mtd);
if (ret) if (ret)
return ret; return ret;
@@ -1038,16 +1022,17 @@ static int stm32_fmc2_probe(struct udevice *dev)
return nand_register(0, mtd); return nand_register(0, mtd);
} }
static const struct udevice_id stm32_fmc2_match[] = { static const struct udevice_id stm32_fmc2_nfc_match[] = {
{ .compatible = "st,stm32mp15-fmc2" }, { .compatible = "st,stm32mp15-fmc2" },
{ .compatible = "st,stm32mp1-fmc2-nfc" },
{ /* Sentinel */ } { /* Sentinel */ }
}; };
U_BOOT_DRIVER(stm32_fmc2_nand) = { U_BOOT_DRIVER(stm32_fmc2_nfc) = {
.name = "stm32_fmc2_nand", .name = "stm32_fmc2_nfc",
.id = UCLASS_MTD, .id = UCLASS_MTD,
.of_match = stm32_fmc2_match, .of_match = stm32_fmc2_nfc_match,
.probe = stm32_fmc2_probe, .probe = stm32_fmc2_nfc_probe,
.priv_auto_alloc_size = sizeof(struct stm32_fmc2_nfc), .priv_auto_alloc_size = sizeof(struct stm32_fmc2_nfc),
}; };
@@ -1057,9 +1042,9 @@ void board_nand_init(void)
int ret; int ret;
ret = uclass_get_device_by_driver(UCLASS_MTD, ret = uclass_get_device_by_driver(UCLASS_MTD,
DM_GET_DRIVER(stm32_fmc2_nand), DM_GET_DRIVER(stm32_fmc2_nfc),
&dev); &dev);
if (ret && ret != -ENODEV) if (ret && ret != -ENODEV)
pr_err("Failed to initialize STM32 FMC2 NAND controller. (error %d)\n", pr_err("Failed to initialize STM32 FMC2 NFC controller. (error %d)\n",
ret); ret);
} }

View File

@@ -159,7 +159,7 @@ static int sti_dwc3_glue_bind(struct udevice *dev)
dwc3_node = node; dwc3_node = node;
} }
if (!ofnode_valid(node)) { if (!ofnode_valid(dwc3_node)) {
pr_err("Can't find dwc3 subnode for %s\n", dev->name); pr_err("Can't find dwc3 subnode for %s\n", dev->name);
return -ENODEV; return -ENODEV;
} }