summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Rini <trini@konsulko.com>2020-08-13 08:11:27 -0400
committerTom Rini <trini@konsulko.com>2020-08-13 08:11:27 -0400
commit6808dc62d75de706c5aabc24e36caf52ead30fc7 (patch)
treea4bc8b1852fc82f0b2703085f9c9199c07bef9cd
parentdbfca734d0e2b36a966be066cb2dc15e0fc71c85 (diff)
parentd0a3c4f9dbf0d661d3b91f46f0fa4db2dc33bb78 (diff)
downloadu-boot-WIP/13Aug2020.tar.gz
Merge tag 'u-boot-stm32-20200813' of https://gitlab.denx.de/u-boot/custodians/u-boot-stmWIP/13Aug2020
- 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
-rw-r--r--arch/arm/dts/stm32mp151.dtsi43
-rw-r--r--arch/arm/dts/stm32mp157c-ev1.dts16
-rw-r--r--arch/arm/dts/stm32mp15xx-dhcom-u-boot.dtsi1
-rw-r--r--arch/arm/mach-stm32mp/bsec.c86
-rw-r--r--arch/arm/mach-stm32mp/cmd_stm32prog/cmd_stm32prog.c5
-rw-r--r--arch/arm/mach-stm32mp/cmd_stm32prog/stm32prog.c100
-rw-r--r--board/dhelectronics/dh_stm32mp1/board.c33
-rw-r--r--board/dhelectronics/dh_stm32mp1/u-boot-dhcom.its32
-rw-r--r--board/dhelectronics/dh_stm32mp1/u-boot-dhcor.its3
-rw-r--r--board/st/common/stm32mp_dfu.c20
-rw-r--r--board/st/stm32mp1/board.c36
-rw-r--r--board/st/stm32mp1/stm32mp1.c201
-rw-r--r--configs/stm32mp15_basic_defconfig1
-rw-r--r--configs/stm32mp15_dhcom_basic_defconfig1
-rw-r--r--configs/stm32mp15_trusted_defconfig1
-rw-r--r--drivers/memory/Kconfig9
-rw-r--r--drivers/memory/Makefile1
-rw-r--r--drivers/memory/stm32-fmc2-ebi.c1056
-rw-r--r--drivers/mtd/nand/raw/stm32_fmc2_nand.c499
-rw-r--r--drivers/usb/host/dwc3-sti-glue.c2
20 files changed, 1627 insertions, 519 deletions
diff --git a/arch/arm/dts/stm32mp151.dtsi b/arch/arm/dts/stm32mp151.dtsi
index 0d97f56fca..39d9e545ed 100644
--- a/arch/arm/dts/stm32mp151.dtsi
+++ b/arch/arm/dts/stm32mp151.dtsi
@@ -1328,23 +1328,38 @@
dma-requests = <48>;
};
- fmc: nand-controller@58002000 {
- compatible = "st,stm32mp15-fmc2";
- reg = <0x58002000 0x1000>,
- <0x80000000 0x1000>,
- <0x88010000 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";
+ fmc: memory-controller@58002000 {
+ #address-cells = <2>;
+ #size-cells = <1>;
+ compatible = "st,stm32mp1-fmc2-ebi";
+ reg = <0x58002000 0x1000>;
clocks = <&rcc FMC_K>;
resets = <&rcc FMC_R>;
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 {
diff --git a/arch/arm/dts/stm32mp157c-ev1.dts b/arch/arm/dts/stm32mp157c-ev1.dts
index b19056557e..46f81ce92e 100644
--- a/arch/arm/dts/stm32mp157c-ev1.dts
+++ b/arch/arm/dts/stm32mp157c-ev1.dts
@@ -157,14 +157,16 @@
pinctrl-0 = <&fmc_pins_a>;
pinctrl-1 = <&fmc_sleep_pins_a>;
status = "okay";
- #address-cells = <1>;
- #size-cells = <0>;
- nand@0 {
- reg = <0>;
- nand-on-flash-bbt;
- #address-cells = <1>;
- #size-cells = <1>;
+ nand-controller@4,0 {
+ status = "okay";
+
+ nand@0 {
+ reg = <0>;
+ nand-on-flash-bbt;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ };
};
};
diff --git a/arch/arm/dts/stm32mp15xx-dhcom-u-boot.dtsi b/arch/arm/dts/stm32mp15xx-dhcom-u-boot.dtsi
index f96de9e7a3..92345b7ba3 100644
--- a/arch/arm/dts/stm32mp15xx-dhcom-u-boot.dtsi
+++ b/arch/arm/dts/stm32mp15xx-dhcom-u-boot.dtsi
@@ -18,6 +18,7 @@
mmc1 = &sdmmc2;
spi0 = &qspi;
usb0 = &usbotg_hs;
+ ethernet1 = &ksz8851;
};
config {
diff --git a/arch/arm/mach-stm32mp/bsec.c b/arch/arm/mach-stm32mp/bsec.c
index 0c56b440f5..a9b9bd0902 100644
--- a/arch/arm/mach-stm32mp/bsec.c
+++ b/arch/arm/mach-stm32mp/bsec.c
@@ -74,7 +74,6 @@ static bool bsec_read_lock(u32 address, u32 otp)
return !!(readl(address + bank) & bit);
}
-#ifndef CONFIG_TFABOOT
/**
* bsec_check_error() - Check status of one otp
* @base: base address of bsec IP
@@ -279,7 +278,6 @@ static int bsec_program_otp(long base, u32 val, u32 otp)
return ret;
}
-#endif /* CONFIG_TFABOOT */
/* BSEC MISC driver *******************************************************/
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)
{
-#ifdef CONFIG_TFABOOT
- return stm32_smc(STM32_SMC_BSEC,
- STM32_SMC_READ_OTP,
- otp, 0, val);
-#else
- struct stm32mp_bsec_platdata *plat = dev_get_platdata(dev);
+ struct stm32mp_bsec_platdata *plat;
u32 tmp_data = 0;
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 */
ret = bsec_read_shadow(plat->base, &tmp_data, otp);
if (ret)
@@ -313,21 +313,22 @@ static int stm32mp_bsec_read_otp(struct udevice *dev, u32 *val, u32 otp)
/* restore shadow value */
ret = bsec_write_shadow(plat->base, tmp_data, otp);
+
return ret;
-#endif
}
static int stm32mp_bsec_read_shadow(struct udevice *dev, u32 *val, u32 otp)
{
-#ifdef CONFIG_TFABOOT
- return stm32_smc(STM32_SMC_BSEC,
- STM32_SMC_READ_SHADOW,
- otp, 0, val);
-#else
- struct stm32mp_bsec_platdata *plat = dev_get_platdata(dev);
+ struct stm32mp_bsec_platdata *plat;
+
+ if (IS_ENABLED(CONFIG_TFABOOT))
+ return stm32_smc(STM32_SMC_BSEC,
+ STM32_SMC_READ_SHADOW,
+ otp, 0, val);
+
+ plat = dev_get_platdata(dev);
return bsec_read_shadow(plat->base, val, otp);
-#endif
}
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)
{
-#ifdef CONFIG_TFABOOT
- return stm32_smc_exec(STM32_SMC_BSEC,
- STM32_SMC_PROG_OTP,
- otp, val);
-#else
- struct stm32mp_bsec_platdata *plat = dev_get_platdata(dev);
+ struct stm32mp_bsec_platdata *plat;
+
+ if (IS_ENABLED(CONFIG_TFABOOT))
+ return stm32_smc_exec(STM32_SMC_BSEC,
+ STM32_SMC_PROG_OTP,
+ otp, val);
+
+ plat = dev_get_platdata(dev);
return bsec_program_otp(plat->base, val, otp);
-#endif
+
}
static int stm32mp_bsec_write_shadow(struct udevice *dev, u32 val, u32 otp)
{
-#ifdef CONFIG_TFABOOT
- return stm32_smc_exec(STM32_SMC_BSEC,
- STM32_SMC_WRITE_SHADOW,
- otp, val);
-#else
- struct stm32mp_bsec_platdata *plat = dev_get_platdata(dev);
+ struct stm32mp_bsec_platdata *plat;
+
+ if (IS_ENABLED(CONFIG_TFABOOT))
+ return stm32_smc_exec(STM32_SMC_BSEC,
+ STM32_SMC_WRITE_SHADOW,
+ otp, val);
+
+ plat = dev_get_platdata(dev);
return bsec_write_shadow(plat->base, val, otp);
-#endif
}
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)
return stm32_smc_exec(STM32_SMC_BSEC,
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 -EINVAL;
-#else
- return -ENOTSUPP;
-#endif
}
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)
{
-#if !defined(CONFIG_TFABOOT) && !defined(CONFIG_SPL_BUILD)
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
* 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))
- bsec_shadow_register(plat->base, otp);
-#endif
+
+ if (!IS_ENABLED(CONFIG_TFABOOT) && !IS_ENABLED(CONFIG_SPL_BUILD)) {
+ plat = dev_get_platdata(dev);
+
+ 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;
}
diff --git a/arch/arm/mach-stm32mp/cmd_stm32prog/cmd_stm32prog.c b/arch/arm/mach-stm32mp/cmd_stm32prog/cmd_stm32prog.c
index cbf0120adc..49dd25b28f 100644
--- a/arch/arm/mach-stm32mp/cmd_stm32prog/cmd_stm32prog.c
+++ b/arch/arm/mach-stm32mp/cmd_stm32prog/cmd_stm32prog.c
@@ -14,7 +14,6 @@ struct stm32prog_data *stm32prog_data;
static void enable_vidconsole(void)
{
-#ifdef CONFIG_DM_VIDEO
char *stdname;
char buf[64];
@@ -35,7 +34,6 @@ static void enable_vidconsole(void)
snprintf(buf, sizeof(buf), "%s,vidconsole", stdname);
env_set("stderr", buf);
}
-#endif
}
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");
}
- enable_vidconsole();
+ if (IS_ENABLED(CONFIG_DM_VIDEO))
+ enable_vidconsole();
data = (struct stm32prog_data *)malloc(sizeof(*data));
diff --git a/arch/arm/mach-stm32mp/cmd_stm32prog/stm32prog.c b/arch/arm/mach-stm32mp/cmd_stm32prog/stm32prog.c
index e4199dbaa5..ec3355d816 100644
--- a/arch/arm/mach-stm32mp/cmd_stm32prog/stm32prog.c
+++ b/arch/arm/mach-stm32mp/cmd_stm32prog/stm32prog.c
@@ -544,10 +544,8 @@ static int init_device(struct stm32prog_data *data,
{
struct mmc *mmc = NULL;
struct blk_desc *block_dev = NULL;
-#ifdef CONFIG_MTD
struct mtd_info *mtd = NULL;
char mtd_id[16];
-#endif
int part_id;
int ret;
u64 first_addr = 0, last_addr = 0;
@@ -557,8 +555,11 @@ static int init_device(struct stm32prog_data *data,
const char *part_name;
switch (dev->target) {
-#ifdef CONFIG_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);
if (!mmc || mmc_init(mmc)) {
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);
pr_debug(" full_update = %d\n", dev->full_update);
break;
-#endif
-#ifdef CONFIG_MTD
case STM32PROG_NOR:
case STM32PROG_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);
pr_debug("%s\n", mtd_id);
@@ -612,7 +615,6 @@ static int init_device(struct stm32prog_data *data,
first_addr, last_addr);
dev->mtd = mtd;
break;
-#endif
case STM32PROG_RAM:
first_addr = gd->bd->bi_dram[0].start;
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;
}
-#ifdef CONFIG_MTD
- if (mtd) {
+ if (IS_ENABLED(CONFIG_MTD) && mtd) {
char mtd_part_id[32];
struct part_info *mtd_part;
struct mtd_device *mtd_dev;
@@ -766,7 +767,7 @@ static int init_device(struct stm32prog_data *data,
part_name = mtd_part->name;
part_found = true;
}
-#endif
+
if (!part_found) {
stm32prog_err("%s (0x%x): Invalid partition",
part->name, part->id);
@@ -873,9 +874,8 @@ static int treat_partition_list(struct stm32prog_data *data)
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;
const int buflen = SZ_8K;
char *buf;
@@ -991,7 +991,6 @@ static int create_partitions(struct stm32prog_data *data)
run_command("mtd list", 0);
#endif
free(buf);
-#endif
return 0;
}
@@ -1070,28 +1069,35 @@ static int stm32prog_alt_add(struct stm32prog_data *data,
offset += snprintf(buf + offset, ALT_BUF_LEN - offset,
" %d;", part->part_id);
}
+ ret = -ENODEV;
switch (part->target) {
-#ifdef CONFIG_MMC
case STM32PROG_MMC:
- sprintf(dfustr, "mmc");
- sprintf(devstr, "%d", part->dev_id);
+ if (IS_ENABLED(CONFIG_MMC)) {
+ ret = 0;
+ sprintf(dfustr, "mmc");
+ sprintf(devstr, "%d", part->dev_id);
+ }
break;
-#endif
-#ifdef CONFIG_MTD
case STM32PROG_NAND:
case STM32PROG_NOR:
case STM32PROG_SPI_NAND:
- sprintf(dfustr, "mtd");
- get_mtd_by_target(devstr, part->target, part->dev_id);
+ if (IS_ENABLED(CONFIG_MTD)) {
+ ret = 0;
+ sprintf(dfustr, "mtd");
+ get_mtd_by_target(devstr, part->target, part->dev_id);
+ }
break;
-#endif
case STM32PROG_RAM:
+ ret = 0;
sprintf(dfustr, "ram");
sprintf(devstr, "0");
break;
default:
+ break;
+ }
+ if (ret) {
stm32prog_err("invalid target: %d", part->target);
- return -ENODEV;
+ return ret;
}
pr_debug("dfu_alt_add(%s,%s,%s)\n", 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,
long *size)
{
-#ifndef CONFIG_ARM_SMCCC
- stm32prog_err("OTP update not supported");
-
- return -1;
-#else
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);
/* alway read for first packet */
if (!offset) {
@@ -1255,19 +1262,19 @@ end_otp_read:
pr_debug("%s: result %i\n", __func__, result);
return result;
-#endif
}
int stm32prog_otp_start(struct stm32prog_data *data)
{
-#ifndef CONFIG_ARM_SMCCC
- stm32prog_err("OTP update not supported");
-
- return -1;
-#else
int result = 0;
struct arm_smccc_res res;
+ if (!IS_ENABLED(CONFIG_ARM_SMCCC)) {
+ stm32prog_err("OTP update not supported");
+
+ return -1;
+ }
+
if (!data->otp_part) {
stm32prog_err("start OTP without data");
return -1;
@@ -1302,7 +1309,6 @@ int stm32prog_otp_start(struct stm32prog_data *data)
pr_debug("%s: result %i\n", __func__, result);
return result;
-#endif
}
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)
{
int ret = 0;
-#ifdef CONFIG_MMC
unsigned long blks, blks_offset, blks_size;
struct blk_desc *block_dev = NULL;
- #endif
-#ifdef CONFIG_MTD
char cmdbuf[40];
char devstr[10];
-#endif
printf("Erasing %s ", part->name);
switch (part->target) {
-#ifdef CONFIG_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);
block_dev = mmc_get_blk_desc(part->dev->mmc);
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);
}
break;
-#endif
-#ifdef CONFIG_MTD
case STM32PROG_NOR:
case STM32PROG_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);
printf("on %s: ", devstr);
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);
}
break;
-#endif
case STM32PROG_RAM:
printf("on ram: ");
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;
}
- ret = create_partitions(data);
- if (ret)
- goto error;
+ if (IS_ENABLED(CONFIG_MMC)) {
+ ret = create_gpt_partitions(data);
+ if (ret)
+ goto error;
+ }
/* delete partition GPT or MTD */
for (i = 0; i < data->part_nb; i++) {
diff --git a/board/dhelectronics/dh_stm32mp1/board.c b/board/dhelectronics/dh_stm32mp1/board.c
index 17dbf20d76..c9abe3cc6d 100644
--- a/board/dhelectronics/dh_stm32mp1/board.c
+++ b/board/dhelectronics/dh_stm32mp1/board.c
@@ -84,11 +84,26 @@ DECLARE_GLOBAL_DATA_PTR;
int setup_mac_address(void)
{
unsigned char enetaddr[6];
+ bool skip_eth0 = false;
+ bool skip_eth1 = false;
struct udevice *dev;
int off, ret;
ret = eth_env_get_enetaddr("ethaddr", enetaddr);
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;
off = fdt_path_offset(gd->fdt_blob, "eeprom0");
@@ -109,8 +124,14 @@ int setup_mac_address(void)
return ret;
}
- if (is_valid_ethaddr(enetaddr))
- eth_env_set_enetaddr("ethaddr", enetaddr);
+ if (is_valid_ethaddr(enetaddr)) {
+ if (!skip_eth0)
+ eth_env_set_enetaddr("ethaddr", enetaddr);
+
+ enetaddr[5]++;
+ if (!skip_eth1)
+ eth_env_set_enetaddr("eth1addr", enetaddr);
+ }
return 0;
}
@@ -216,9 +237,13 @@ int board_early_init_f(void)
#ifdef CONFIG_SPL_LOAD_FIT
int board_fit_config_name_match(const char *name)
{
- char test[20];
+ const char *compat;
+ char test[128];
+
+ compat = fdt_getprop(gd->fdt_blob, 0, "compatible", NULL);
- snprintf(test, sizeof(test), "somrev%d_boardrev%d", somcode, brdcode);
+ snprintf(test, sizeof(test), "%s_somrev%d_boardrev%d",
+ compat, somcode, brdcode);
if (!strcmp(name, test))
return 0;
diff --git a/board/dhelectronics/dh_stm32mp1/u-boot-dhcom.its b/board/dhelectronics/dh_stm32mp1/u-boot-dhcom.its
index 2776c41af1..905be57dff 100644
--- a/board/dhelectronics/dh_stm32mp1/u-boot-dhcom.its
+++ b/board/dhelectronics/dh_stm32mp1/u-boot-dhcom.its
@@ -23,17 +23,47 @@
arch = "arm";
compression = "none";
};
+
+ fdt-2 {
+ description = ".dtb";
+ data = /incbin/("arch/arm/dts/stm32mp15xx-dhcom-drc02.dtb");
+ type = "flat_dt";
+ arch = "arm";
+ compression = "none";
+ };
};
configurations {
default = "config-1";
config-1 {
- description = "somrev0_boardrev0"; /* SoM+board model */
+ /* DT+SoM+board model */
+ description = "dh,stm32mp15xx-dhcom-pdk2_somrev0_boardrev0";
+ loadables = "uboot";
+ 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 */
};
};
diff --git a/board/dhelectronics/dh_stm32mp1/u-boot-dhcor.its b/board/dhelectronics/dh_stm32mp1/u-boot-dhcor.its
index 8844508f1a..7419684f55 100644
--- a/board/dhelectronics/dh_stm32mp1/u-boot-dhcor.its
+++ b/board/dhelectronics/dh_stm32mp1/u-boot-dhcor.its
@@ -29,7 +29,8 @@
default = "config-1";
config-1 {
- description = "somrev0_boardrev1"; /* SoM+board model */
+ /* DT+SoM+board model */
+ description = "arrow,stm32mp15xx-avenger96_somrev0_boardrev1";
loadables = "uboot";
fdt = "fdt-1";
};
diff --git a/board/st/common/stm32mp_dfu.c b/board/st/common/stm32mp_dfu.c
index 38eb0f27c9..aab7d741ac 100644
--- a/board/st/common/stm32mp_dfu.c
+++ b/board/st/common/stm32mp_dfu.c
@@ -114,11 +114,13 @@ void set_dfu_alt_info(char *interface, char *devstr)
snprintf(buf, DFU_ALT_BUF_LEN,
"ram 0=%s", CONFIG_DFU_ALT_RAM0);
- if (!uclass_get_device(UCLASS_MMC, 0, &dev))
- board_get_alt_info_mmc(dev, buf);
+ if (CONFIG_IS_ENABLED(MMC)) {
+ if (!uclass_get_device(UCLASS_MMC, 0, &dev))
+ board_get_alt_info_mmc(dev, buf);
- if (!uclass_get_device(UCLASS_MMC, 1, &dev))
- board_get_alt_info_mmc(dev, buf);
+ if (!uclass_get_device(UCLASS_MMC, 1, &dev))
+ board_get_alt_info_mmc(dev, buf);
+ }
if (CONFIG_IS_ENABLED(MTD)) {
/* probe all MTD devices */
@@ -140,12 +142,12 @@ void set_dfu_alt_info(char *interface, char *devstr)
board_get_alt_info_mtd(mtd, buf);
}
-#ifdef CONFIG_DFU_VIRT
- strncat(buf, "&virt 0=OTP", DFU_ALT_BUF_LEN);
+ if (IS_ENABLED(CONFIG_DFU_VIRT)) {
+ strncat(buf, "&virt 0=OTP", DFU_ALT_BUF_LEN);
- if (IS_ENABLED(CONFIG_PMIC_STPMIC1))
- strncat(buf, "&virt 1=PMIC", DFU_ALT_BUF_LEN);
-#endif
+ if (IS_ENABLED(CONFIG_PMIC_STPMIC1))
+ strncat(buf, "&virt 1=PMIC", DFU_ALT_BUF_LEN);
+ }
env_set("dfu_alt_info", buf);
puts("DFU alt info setting: done\n");
diff --git a/board/st/stm32mp1/board.c b/board/st/stm32mp1/board.c
deleted file mode 100644
index 00c61c2886..0000000000
--- a/board/st/stm32mp1/board.c
+++ /dev/null
@@ -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
diff --git a/board/st/stm32mp1/stm32mp1.c b/board/st/stm32mp1/stm32mp1.c
index 1d274c3157..3b677d339b 100644
--- a/board/st/stm32mp1/stm32mp1.c
+++ b/board/st/stm32mp1/stm32mp1.c
@@ -135,60 +135,61 @@ int checkboard(void)
static void board_key_check(void)
{
-#if defined(CONFIG_FASTBOOT) || defined(CONFIG_CMD_STM32PROG)
ofnode node;
struct gpio_desc gpio;
enum forced_boot_mode boot_mode = BOOT_NORMAL;
+ if (!IS_ENABLED(CONFIG_FASTBOOT) && !IS_ENABLED(CONFIG_CMD_STM32PROG))
+ return;
+
node = ofnode_path("/config");
if (!ofnode_valid(node)) {
debug("%s: no /config node?\n", __func__);
return;
}
-#ifdef CONFIG_FASTBOOT
- if (gpio_request_by_name_nodev(node, "st,fastboot-gpios", 0,
- &gpio, GPIOD_IS_IN)) {
- debug("%s: could not find a /config/st,fastboot-gpios\n",
- __func__);
- } else {
- if (dm_gpio_get_value(&gpio)) {
- puts("Fastboot key pressed, ");
- boot_mode = BOOT_FASTBOOT;
- }
+ if (IS_ENABLED(CONFIG_FASTBOOT)) {
+ if (gpio_request_by_name_nodev(node, "st,fastboot-gpios", 0,
+ &gpio, GPIOD_IS_IN)) {
+ debug("%s: could not find a /config/st,fastboot-gpios\n",
+ __func__);
+ } else {
+ if (dm_gpio_get_value(&gpio)) {
+ puts("Fastboot key pressed, ");
+ boot_mode = BOOT_FASTBOOT;
+ }
- dm_gpio_free(NULL, &gpio);
+ dm_gpio_free(NULL, &gpio);
+ }
}
-#endif
-#ifdef CONFIG_CMD_STM32PROG
- if (gpio_request_by_name_nodev(node, "st,stm32prog-gpios", 0,
- &gpio, GPIOD_IS_IN)) {
- debug("%s: could not find a /config/st,stm32prog-gpios\n",
- __func__);
- } else {
- if (dm_gpio_get_value(&gpio)) {
- puts("STM32Programmer key pressed, ");
- boot_mode = BOOT_STM32PROG;
+ if (IS_ENABLED(CONFIG_CMD_STM32PROG)) {
+ if (gpio_request_by_name_nodev(node, "st,stm32prog-gpios", 0,
+ &gpio, GPIOD_IS_IN)) {
+ debug("%s: could not find a /config/st,stm32prog-gpios\n",
+ __func__);
+ } else {
+ if (dm_gpio_get_value(&gpio)) {
+ puts("STM32Programmer key pressed, ");
+ boot_mode = BOOT_STM32PROG;
+ }
+ dm_gpio_free(NULL, &gpio);
}
- dm_gpio_free(NULL, &gpio);
}
-#endif
-
if (boot_mode != BOOT_NORMAL) {
puts("entering download mode...\n");
clrsetbits_le32(TAMP_BOOT_CONTEXT,
TAMP_BOOT_FORCED_MASK,
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)
{
struct udevice *dwc2_udc_otg;
int ret;
+ if (!IS_ENABLED(CONFIG_USB_GADGET_DWC2_OTG))
+ return -ENODEV;
+
/* if typec stusb160x is present, means DK1 or DK2 board */
ret = stusb160x_cable_connected();
if (ret >= 0)
@@ -203,14 +204,17 @@ int g_dnl_board_usb_cable_connected(void)
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_FASTBOOT_PRODUCT_NUM 0x0afb
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);
- 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,
&dev->idProduct);
else
@@ -218,8 +222,7 @@ int g_dnl_bind_fixup(struct usb_device_descriptor *dev, const char *name)
return 0;
}
-
-#endif /* CONFIG_USB_GADGET */
+#endif /* CONFIG_USB_GADGET_DOWNLOAD */
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();
}
-#ifdef CONFIG_ADC
static int board_check_usb_power(void)
{
struct ofnode_phandle_args adc_args;
@@ -297,6 +299,10 @@ static int board_check_usb_power(void)
int ret, uV, adc_count;
u32 nb_blink;
u8 i;
+
+ if (!IS_ENABLED(CONFIG_ADC))
+ return -ENODEV;
+
node = ofnode_path("/config");
if (!ofnode_valid(node)) {
debug("%s: no /config node?\n", __func__);
@@ -419,18 +425,14 @@ static int board_check_usb_power(void)
return 0;
}
-#endif /* CONFIG_ADC */
static void sysconf_init(void)
{
-#ifndef CONFIG_TFABOOT
u8 *syscfg;
-#ifdef CONFIG_DM_REGULATOR
struct udevice *pwr_dev;
struct udevice *pwr_reg;
struct udevice *dev;
u32 otp = 0;
-#endif
int ret;
u32 bootr, val;
@@ -448,7 +450,6 @@ static void sysconf_init(void)
bootr |= (bootr & SYSCFG_BOOTR_BOOT_MASK) << SYSCFG_BOOTR_BOOTPD_SHIFT;
writel(bootr, syscfg + SYSCFG_BOOTR);
-#ifdef CONFIG_DM_REGULATOR
/* High Speed Low Voltage Pad mode Enable for SPI, SDMMC, ETH, QSPI
* and TRACE. Needed above ~50MHz and conditioned by AFMUX selection.
* 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,
DM_GET_DRIVER(stm32mp_pwr_pmic),
&pwr_dev);
- if (!ret) {
+ if (!ret && IS_ENABLED(CONFIG_DM_REGULATOR)) {
ret = uclass_get_device_by_driver(UCLASS_MISC,
DM_GET_DRIVER(stm32mp_bsec),
&dev);
@@ -502,7 +503,6 @@ static void sysconf_init(void)
debug("VDD unknown");
}
}
-#endif
/* activate automatic I/O compensation
* 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);
-#endif
}
-#ifdef CONFIG_DM_REGULATOR
/* Fix to make I2C1 usable on DK2 for touchscreen usage in kernel */
static int dk2_i2c1_fix(void)
{
@@ -530,6 +528,9 @@ static int dk2_i2c1_fix(void)
struct gpio_desc hdmi, audio;
int ret = 0;
+ if (!IS_ENABLED(CONFIG_DM_REGULATOR))
+ return -ENODEV;
+
node = ofnode_path("/soc/i2c@40012000/hdmi-transmitter@39");
if (!ofnode_valid(node)) {
pr_debug("%s: no hdmi-transmitter@39 ?\n", __func__);
@@ -587,7 +588,6 @@ static bool board_is_dk2(void)
return false;
}
-#endif
static bool board_is_ev1(void)
{
@@ -635,14 +635,14 @@ int board_init(void)
if (board_is_ev1())
board_ev1_init();
-#ifdef CONFIG_DM_REGULATOR
if (board_is_dk2())
dk2_i2c1_fix();
- regulators_enable_boot_on(_DEBUG);
-#endif
+ if (IS_ENABLED(CONFIG_DM_REGULATOR))
+ regulators_enable_boot_on(_DEBUG);
- sysconf_init();
+ if (!IS_ENABLED(CONFIG_TFABOOT))
+ sysconf_init();
if (CONFIG_IS_ENABLED(LED))
led_default_state();
@@ -654,52 +654,50 @@ int board_init(void)
int board_late_init(void)
{
-#ifdef CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG
const void *fdt_compat;
int fdt_compat_len;
int ret;
u32 otp;
struct udevice *dev;
char buf[10];
+ char dtb_name[256];
+ int buf_len;
+
+ if (IS_ENABLED(CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG)) {
+ fdt_compat = fdt_getprop(gd->fdt_blob, 0, "compatible",
+ &fdt_compat_len);
+ if (fdt_compat && fdt_compat_len) {
+ if (strncmp(fdt_compat, "st,", 3) != 0) {
+ env_set("board_name", fdt_compat);
+ } else {
+ env_set("board_name", fdt_compat + 3);
- fdt_compat = fdt_getprop(gd->fdt_blob, 0, "compatible",
- &fdt_compat_len);
- if (fdt_compat && fdt_compat_len) {
- if (strncmp(fdt_compat, "st,", 3) != 0) {
- env_set("board_name", fdt_compat);
- } else {
- char dtb_name[256];
- int buf_len = sizeof(dtb_name);
+ 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);
- env_set("board_name", fdt_compat + 3);
+ 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);
- 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);
+ 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 */
board_check_usb_power();
-#endif /* CONFIG_ADC */
return 0;
}
@@ -787,31 +785,33 @@ enum env_location env_get_location(enum env_operation op, int prio)
return ENVL_UNKNOWN;
switch (bootmode & TAMP_BOOT_DEVICE_MASK) {
-#if CONFIG_IS_ENABLED(ENV_IS_IN_MMC)
- case BOOT_FLASH_SD:
- case BOOT_FLASH_EMMC:
- return ENVL_MMC;
-#endif
-#if CONFIG_IS_ENABLED(ENV_IS_IN_EXT4)
case BOOT_FLASH_SD:
case BOOT_FLASH_EMMC:
- return ENVL_EXT4;
-#endif
-#if CONFIG_IS_ENABLED(ENV_IS_IN_UBI)
+ if (CONFIG_IS_ENABLED(ENV_IS_IN_MMC))
+ return ENVL_MMC;
+ else if (CONFIG_IS_ENABLED(ENV_IS_IN_EXT4))
+ return ENVL_EXT4;
+ else
+ return ENVL_NOWHERE;
+
case BOOT_FLASH_NAND:
case BOOT_FLASH_SPINAND:
- return ENVL_UBI;
-#endif
-#if CONFIG_IS_ENABLED(ENV_IS_IN_SPI_FLASH)
+ if (CONFIG_IS_ENABLED(ENV_IS_IN_UBI))
+ return ENVL_UBI;
+ else
+ return ENVL_NOWHERE;
+
case BOOT_FLASH_NOR:
- return ENVL_SPI_FLASH;
-#endif
+ if (CONFIG_IS_ENABLED(ENV_IS_IN_SPI_FLASH))
+ return ENVL_SPI_FLASH;
+ else
+ return ENVL_NOWHERE;
+
default:
return ENVL_NOWHERE;
}
}
-#if defined(CONFIG_ENV_IS_IN_EXT4)
const char *env_ext4_get_intf(void)
{
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];
}
-#endif
-
-#if defined(CONFIG_ENV_IS_IN_MMC)
int mmc_get_env_dev(void)
{
u32 bootmode = get_bootmode();
return (bootmode & TAMP_BOOT_INSTANCE_MASK) - 1;
}
-#endif
#if defined(CONFIG_OF_BOARD_SETUP)
int ft_board_setup(void *blob, struct bd_info *bd)
{
-#ifdef CONFIG_FDT_FIXUP_PARTITIONS
- struct node_info nodes[] = {
+ static const struct node_info nodes[] = {
{ "st,stm32f469-qspi", MTD_DEV_TYPE_NOR, },
{ "st,stm32f469-qspi", MTD_DEV_TYPE_SPINAND},
{ "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;
}
diff --git a/configs/stm32mp15_basic_defconfig b/configs/stm32mp15_basic_defconfig
index 5c500a131e..2094183295 100644
--- a/configs/stm32mp15_basic_defconfig
+++ b/configs/stm32mp15_basic_defconfig
@@ -88,6 +88,7 @@ CONFIG_LED=y
CONFIG_LED_GPIO=y
CONFIG_DM_MAILBOX=y
CONFIG_STM32_IPCC=y
+CONFIG_STM32_FMC2_EBI=y
CONFIG_DM_MMC=y
CONFIG_SUPPORT_EMMC_BOOT=y
CONFIG_STM32_SDMMC2=y
diff --git a/configs/stm32mp15_dhcom_basic_defconfig b/configs/stm32mp15_dhcom_basic_defconfig
index dc85625a8b..c70414e23b 100644
--- a/configs/stm32mp15_dhcom_basic_defconfig
+++ b/configs/stm32mp15_dhcom_basic_defconfig
@@ -57,6 +57,7 @@ CONFIG_CMD_REGULATOR=y
CONFIG_CMD_EXT4_WRITE=y
CONFIG_CMD_MTDPARTS=y
# 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_ENV_IS_IN_SPI_FLASH=y
CONFIG_USE_ENV_SPI_BUS=y
diff --git a/configs/stm32mp15_trusted_defconfig b/configs/stm32mp15_trusted_defconfig
index 98680cb2dc..8d59d84184 100644
--- a/configs/stm32mp15_trusted_defconfig
+++ b/configs/stm32mp15_trusted_defconfig
@@ -68,6 +68,7 @@ CONFIG_LED=y
CONFIG_LED_GPIO=y
CONFIG_DM_MAILBOX=y
CONFIG_STM32_IPCC=y
+CONFIG_STM32_FMC2_EBI=y
CONFIG_DM_MMC=y
CONFIG_SUPPORT_EMMC_BOOT=y
CONFIG_STM32_SDMMC2=y
diff --git a/drivers/memory/Kconfig b/drivers/memory/Kconfig
index 4fbb5aa217..7271892763 100644
--- a/drivers/memory/Kconfig
+++ b/drivers/memory/Kconfig
@@ -4,6 +4,15 @@
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
tristate "Texas Instruments AEMIF driver"
depends on ARCH_KEYSTONE
diff --git a/drivers/memory/Makefile b/drivers/memory/Makefile
index 238add0879..fec52efb60 100644
--- a/drivers/memory/Makefile
+++ b/drivers/memory/Makefile
@@ -1,2 +1,3 @@
+obj-$(CONFIG_STM32_FMC2_EBI) += stm32-fmc2-ebi.o
obj-$(CONFIG_TI_AEMIF) += ti-aemif.o
diff --git a/drivers/memory/stm32-fmc2-ebi.c b/drivers/memory/stm32-fmc2-ebi.c
new file mode 100644
index 0000000000..d887a1e09d
--- /dev/null
+++ b/drivers/memory/stm32-fmc2-ebi.c
@@ -0,0 +1,1056 @@
+// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
+/*
+ * Copyright (C) STMicroelectronics 2020
+ */
+
+#include <common.h>
+#include <clk.h>
+#include <dm.h>
+#include <reset.h>
+#include <linux/bitfield.h>
+#include <linux/err.h>
+#include <linux/iopoll.h>
+#include <linux/ioport.h>
+
+/* FMC2 Controller Registers */
+#define FMC2_BCR1 0x0
+#define FMC2_BTR1 0x4
+#define FMC2_BCR(x) ((x) * 0x8 + FMC2_BCR1)
+#define FMC2_BTR(x) ((x) * 0x8 + FMC2_BTR1)
+#define FMC2_PCSCNTR 0x20
+#define FMC2_BWTR1 0x104
+#define FMC2_BWTR(x) ((x) * 0x8 + FMC2_BWTR1)
+
+/* Register: FMC2_BCR1 */
+#define FMC2_BCR1_CCLKEN BIT(20)
+#define FMC2_BCR1_FMC2EN BIT(31)
+
+/* Register: FMC2_BCRx */
+#define FMC2_BCR_MBKEN BIT(0)
+#define FMC2_BCR_MUXEN BIT(1)
+#define FMC2_BCR_MTYP GENMASK(3, 2)
+#define FMC2_BCR_MWID GENMASK(5, 4)
+#define FMC2_BCR_FACCEN BIT(6)
+#define FMC2_BCR_BURSTEN BIT(8)
+#define FMC2_BCR_WAITPOL BIT(9)
+#define FMC2_BCR_WAITCFG BIT(11)
+#define FMC2_BCR_WREN BIT(12)
+#define FMC2_BCR_WAITEN BIT(13)
+#define FMC2_BCR_EXTMOD BIT(14)
+#define FMC2_BCR_ASYNCWAIT BIT(15)
+#define FMC2_BCR_CPSIZE GENMASK(18, 16)
+#define FMC2_BCR_CBURSTRW BIT(19)
+#define FMC2_BCR_NBLSET GENMASK(23, 22)
+
+/* Register: FMC2_BTRx/FMC2_BWTRx */
+#define FMC2_BXTR_ADDSET GENMASK(3, 0)
+#define FMC2_BXTR_ADDHLD GENMASK(7, 4)
+#define FMC2_BXTR_DATAST GENMASK(15, 8)
+#define FMC2_BXTR_BUSTURN GENMASK(19, 16)
+#define FMC2_BTR_CLKDIV GENMASK(23, 20)
+#define FMC2_BTR_DATLAT GENMASK(27, 24)
+#define FMC2_BXTR_ACCMOD GENMASK(29, 28)
+#define FMC2_BXTR_DATAHLD GENMASK(31, 30)
+
+/* Register: FMC2_PCSCNTR */
+#define FMC2_PCSCNTR_CSCOUNT GENMASK(15, 0)
+#define FMC2_PCSCNTR_CNTBEN(x) BIT((x) + 16)
+
+#define FMC2_MAX_EBI_CE 4
+#define FMC2_MAX_BANKS 5
+
+#define FMC2_BCR_CPSIZE_0 0x0
+#define FMC2_BCR_CPSIZE_128 0x1
+#define FMC2_BCR_CPSIZE_256 0x2
+#define FMC2_BCR_CPSIZE_512 0x3
+#define FMC2_BCR_CPSIZE_1024 0x4
+
+#define FMC2_BCR_MWID_8 0x0
+#define FMC2_BCR_MWID_16 0x1
+
+#define FMC2_BCR_MTYP_SRAM 0x0
+#define FMC2_BCR_MTYP_PSRAM 0x1
+#define FMC2_BCR_MTYP_NOR 0x2
+
+#define FMC2_BXTR_EXTMOD_A 0x0
+#define FMC2_BXTR_EXTMOD_B 0x1
+#define FMC2_BXTR_EXTMOD_C 0x2
+#define FMC2_BXTR_EXTMOD_D 0x3
+
+#define FMC2_BCR_NBLSET_MAX 0x3
+#define FMC2_BXTR_ADDSET_MAX 0xf
+#define FMC2_BXTR_ADDHLD_MAX 0xf
+#define FMC2_BXTR_DATAST_MAX 0xff
+#define FMC2_BXTR_BUSTURN_MAX 0xf
+#define FMC2_BXTR_DATAHLD_MAX 0x3
+#define FMC2_BTR_CLKDIV_MAX 0xf
+#define FMC2_BTR_DATLAT_MAX 0xf
+#define FMC2_PCSCNTR_CSCOUNT_MAX 0xff
+
+#define FMC2_NSEC_PER_SEC 1000000000L
+
+enum stm32_fmc2_ebi_bank {
+ FMC2_EBI1 = 0,
+ FMC2_EBI2,
+ FMC2_EBI3,
+ FMC2_EBI4,
+ FMC2_NAND
+};
+
+enum stm32_fmc2_ebi_register_type {
+ FMC2_REG_BCR = 1,
+ FMC2_REG_BTR,
+ FMC2_REG_BWTR,
+ FMC2_REG_PCSCNTR
+};
+
+enum stm32_fmc2_ebi_transaction_type {
+ FMC2_ASYNC_MODE_1_SRAM = 0,
+ FMC2_ASYNC_MODE_1_PSRAM,
+ FMC2_ASYNC_MODE_A_SRAM,
+ FMC2_ASYNC_MODE_A_PSRAM,
+ FMC2_ASYNC_MODE_2_NOR,
+ FMC2_ASYNC_MODE_B_NOR,
+ FMC2_ASYNC_MODE_C_NOR,
+ FMC2_ASYNC_MODE_D_NOR,
+ FMC2_SYNC_READ_SYNC_WRITE_PSRAM,
+ FMC2_SYNC_READ_ASYNC_WRITE_PSRAM,
+ FMC2_SYNC_READ_SYNC_WRITE_NOR,
+ FMC2_SYNC_READ_ASYNC_WRITE_NOR
+};
+
+enum stm32_fmc2_ebi_buswidth {
+ FMC2_BUSWIDTH_8 = 8,
+ FMC2_BUSWIDTH_16 = 16
+};
+
+enum stm32_fmc2_ebi_cpsize {
+ FMC2_CPSIZE_0 = 0,
+ FMC2_CPSIZE_128 = 128,
+ FMC2_CPSIZE_256 = 256,
+ FMC2_CPSIZE_512 = 512,
+ FMC2_CPSIZE_1024 = 1024
+};
+
+struct stm32_fmc2_ebi {
+ struct clk clk;
+ fdt_addr_t io_base;
+ u8 bank_assigned;
+};
+
+/*
+ * struct stm32_fmc2_prop - STM32 FMC2 EBI property
+ * @name: the device tree binding name of the property
+ * @bprop: indicate that it is a boolean property
+ * @mprop: indicate that it is a mandatory property
+ * @reg_type: the register that have to be modified
+ * @reg_mask: the bit that have to be modified in the selected register
+ * in case of it is a boolean property
+ * @reset_val: the default value that have to be set in case the property
+ * has not been defined in the device tree
+ * @check: this callback ckecks that the property is compliant with the
+ * transaction type selected
+ * @calculate: this callback is called to calculate for exemple a timing
+ * set in nanoseconds in the device tree in clock cycles or in
+ * clock period
+ * @set: this callback applies the values in the registers
+ */
+struct stm32_fmc2_prop {
+ const char *name;
+ bool bprop;
+ bool mprop;
+ int reg_type;
+ u32 reg_mask;
+ u32 reset_val;
+ int (*check)(struct stm32_fmc2_ebi *ebi,
+ const struct stm32_fmc2_prop *prop, int cs);
+ u32 (*calculate)(struct stm32_fmc2_ebi *ebi, int cs, u32 setup);
+ int (*set)(struct stm32_fmc2_ebi *ebi,
+ const struct stm32_fmc2_prop *prop,
+ int cs, u32 setup);
+};
+
+static int stm32_fmc2_ebi_check_mux(struct stm32_fmc2_ebi *ebi,
+ const struct stm32_fmc2_prop *prop,
+ int cs)
+{
+ u32 bcr = readl(ebi->io_base + FMC2_BCR(cs));
+
+ if (bcr & FMC2_BCR_MTYP)
+ return 0;
+
+ return -EINVAL;
+}
+
+static int stm32_fmc2_ebi_check_waitcfg(struct stm32_fmc2_ebi *ebi,
+ const struct stm32_fmc2_prop *prop,
+ int cs)
+{
+ u32 bcr = readl(ebi->io_base + FMC2_BCR(cs));
+ u32 val = FIELD_PREP(FMC2_BCR_MTYP, FMC2_BCR_MTYP_NOR);
+
+ if ((bcr & FMC2_BCR_MTYP) == val && bcr & FMC2_BCR_BURSTEN)
+ return 0;
+
+ return -EINVAL;
+}
+
+static int stm32_fmc2_ebi_check_sync_trans(struct stm32_fmc2_ebi *ebi,
+ const struct stm32_fmc2_prop *prop,
+ int cs)
+{
+ u32 bcr = readl(ebi->io_base + FMC2_BCR(cs));
+
+ if (bcr & FMC2_BCR_BURSTEN)
+ return 0;
+
+ return -EINVAL;
+}
+
+static int stm32_fmc2_ebi_check_async_trans(struct stm32_fmc2_ebi *ebi,
+ const struct stm32_fmc2_prop *prop,
+ int cs)
+{
+ u32 bcr = readl(ebi->io_base + FMC2_BCR(cs));
+
+ if (!(bcr & FMC2_BCR_BURSTEN) || !(bcr & FMC2_BCR_CBURSTRW))
+ return 0;
+
+ return -EINVAL;
+}
+
+static int stm32_fmc2_ebi_check_cpsize(struct stm32_fmc2_ebi *ebi,
+ const struct stm32_fmc2_prop *prop,
+ int cs)
+{
+ u32 bcr = readl(ebi->io_base + FMC2_BCR(cs));
+ u32 val = FIELD_PREP(FMC2_BCR_MTYP, FMC2_BCR_MTYP_PSRAM);
+
+ if ((bcr & FMC2_BCR_MTYP) == val && bcr & FMC2_BCR_BURSTEN)
+ return 0;
+
+ return -EINVAL;
+}
+
+static int stm32_fmc2_ebi_check_address_hold(struct stm32_fmc2_ebi *ebi,
+ const struct stm32_fmc2_prop *prop,
+ int cs)
+{
+ u32 bcr = readl(ebi->io_base + FMC2_BCR(cs));
+ u32 bxtr = prop->reg_type == FMC2_REG_BWTR ?
+ readl(ebi->io_base + FMC2_BWTR(cs)) :
+ readl(ebi->io_base + FMC2_BTR(cs));
+ u32 val = FIELD_PREP(FMC2_BXTR_ACCMOD, FMC2_BXTR_EXTMOD_D);
+
+ if ((!(bcr & FMC2_BCR_BURSTEN) || !(bcr & FMC2_BCR_CBURSTRW)) &&
+ ((bxtr & FMC2_BXTR_ACCMOD) == val || bcr & FMC2_BCR_MUXEN))
+ return 0;
+
+ return -EINVAL;
+}
+
+static int stm32_fmc2_ebi_check_clk_period(struct stm32_fmc2_ebi *ebi,
+ const struct stm32_fmc2_prop *prop,
+ int cs)
+{
+ u32 bcr = readl(ebi->io_base + FMC2_BCR(cs));
+ u32 bcr1 = cs ? readl(ebi->io_base + FMC2_BCR1) : bcr;
+
+ if (bcr & FMC2_BCR_BURSTEN && (!cs || !(bcr1 & FMC2_BCR1_CCLKEN)))
+ return 0;
+
+ return -EINVAL;
+}
+
+static int stm32_fmc2_ebi_check_cclk(struct stm32_fmc2_ebi *ebi,
+ const struct stm32_fmc2_prop *prop,
+ int cs)
+{
+ if (cs)
+ return -EINVAL;
+
+ return stm32_fmc2_ebi_check_sync_trans(ebi, prop, cs);
+}
+
+static u32 stm32_fmc2_ebi_ns_to_clock_cycles(struct stm32_fmc2_ebi *ebi,
+ int cs, u32 setup)
+{
+ unsigned long hclk = clk_get_rate(&ebi->clk);
+ unsigned long hclkp = FMC2_NSEC_PER_SEC / (hclk / 1000);
+
+ return DIV_ROUND_UP(setup * 1000, hclkp);
+}
+
+static u32 stm32_fmc2_ebi_ns_to_clk_period(struct stm32_fmc2_ebi *ebi,
+ int cs, u32 setup)
+{
+ u32 nb_clk_cycles = stm32_fmc2_ebi_ns_to_clock_cycles(ebi, cs, setup);
+ u32 bcr = readl(ebi->io_base + FMC2_BCR1);
+ u32 btr = bcr & FMC2_BCR1_CCLKEN || !cs ?
+ readl(ebi->io_base + FMC2_BTR1) :
+ readl(ebi->io_base + FMC2_BTR(cs));
+ u32 clk_period = FIELD_GET(FMC2_BTR_CLKDIV, btr) + 1;
+
+ return DIV_ROUND_UP(nb_clk_cycles, clk_period);
+}
+
+static int stm32_fmc2_ebi_get_reg(int reg_type, int cs, u32 *reg)
+{
+ switch (reg_type) {
+ case FMC2_REG_BCR:
+ *reg = FMC2_BCR(cs);
+ break;
+ case FMC2_REG_BTR:
+ *reg = FMC2_BTR(cs);
+ break;
+ case FMC2_REG_BWTR:
+ *reg = FMC2_BWTR(cs);
+ break;
+ case FMC2_REG_PCSCNTR:
+ *reg = FMC2_PCSCNTR;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int stm32_fmc2_ebi_set_bit_field(struct stm32_fmc2_ebi *ebi,
+ const struct stm32_fmc2_prop *prop,
+ int cs, u32 setup)
+{
+ u32 reg;
+ int ret;
+
+ ret = stm32_fmc2_ebi_get_reg(prop->reg_type, cs, &reg);
+ if (ret)
+ return ret;
+
+ clrsetbits_le32(ebi->io_base + reg, prop->reg_mask,
+ setup ? prop->reg_mask : 0);
+
+ return 0;
+}
+
+static int stm32_fmc2_ebi_set_trans_type(struct stm32_fmc2_ebi *ebi,
+ const struct stm32_fmc2_prop *prop,
+ int cs, u32 setup)
+{
+ u32 bcr_mask, bcr = FMC2_BCR_WREN;
+ u32 btr_mask, btr = 0;
+ u32 bwtr_mask, bwtr = 0;
+
+ bwtr_mask = FMC2_BXTR_ACCMOD;
+ btr_mask = FMC2_BXTR_ACCMOD;
+ bcr_mask = FMC2_BCR_MUXEN | FMC2_BCR_MTYP | FMC2_BCR_FACCEN |
+ FMC2_BCR_WREN | FMC2_BCR_WAITEN | FMC2_BCR_BURSTEN |
+ FMC2_BCR_EXTMOD | FMC2_BCR_CBURSTRW;
+
+ switch (setup) {
+ case FMC2_ASYNC_MODE_1_SRAM:
+ bcr |= FIELD_PREP(FMC2_BCR_MTYP, FMC2_BCR_MTYP_SRAM);
+ /*
+ * MUXEN = 0, MTYP = 0, FACCEN = 0, BURSTEN = 0, WAITEN = 0,
+ * WREN = 1, EXTMOD = 0, CBURSTRW = 0, ACCMOD = 0
+ */
+ break;
+ case FMC2_ASYNC_MODE_1_PSRAM:
+ /*
+ * MUXEN = 0, MTYP = 1, FACCEN = 0, BURSTEN = 0, WAITEN = 0,
+ * WREN = 1, EXTMOD = 0, CBURSTRW = 0, ACCMOD = 0
+ */
+ bcr |= FIELD_PREP(FMC2_BCR_MTYP, FMC2_BCR_MTYP_PSRAM);
+ break;
+ case FMC2_ASYNC_MODE_A_SRAM:
+ /*
+ * MUXEN = 0, MTYP = 0, FACCEN = 0, BURSTEN = 0, WAITEN = 0,
+ * WREN = 1, EXTMOD = 1, CBURSTRW = 0, ACCMOD = 0
+ */
+ bcr |= FIELD_PREP(FMC2_BCR_MTYP, FMC2_BCR_MTYP_SRAM);
+ bcr |= FMC2_BCR_EXTMOD;
+ btr |= FIELD_PREP(FMC2_BXTR_ACCMOD, FMC2_BXTR_EXTMOD_A);
+ bwtr |= FIELD_PREP(FMC2_BXTR_ACCMOD, FMC2_BXTR_EXTMOD_A);
+ break;
+ case FMC2_ASYNC_MODE_A_PSRAM:
+ /*
+ * MUXEN = 0, MTYP = 1, FACCEN = 0, BURSTEN = 0, WAITEN = 0,
+ * WREN = 1, EXTMOD = 1, CBURSTRW = 0, ACCMOD = 0
+ */
+ bcr |= FIELD_PREP(FMC2_BCR_MTYP, FMC2_BCR_MTYP_PSRAM);
+ bcr |= FMC2_BCR_EXTMOD;
+ btr |= FIELD_PREP(FMC2_BXTR_ACCMOD, FMC2_BXTR_EXTMOD_A);
+ bwtr |= FIELD_PREP(FMC2_BXTR_ACCMOD, FMC2_BXTR_EXTMOD_A);
+ break;
+ case FMC2_ASYNC_MODE_2_NOR:
+ /*
+ * MUXEN = 0, MTYP = 2, FACCEN = 1, BURSTEN = 0, WAITEN = 0,
+ * WREN = 1, EXTMOD = 0, CBURSTRW = 0, ACCMOD = 0
+ */
+ bcr |= FIELD_PREP(FMC2_BCR_MTYP, FMC2_BCR_MTYP_NOR);
+ bcr |= FMC2_BCR_FACCEN;
+ break;
+ case FMC2_ASYNC_MODE_B_NOR:
+ /*
+ * MUXEN = 0, MTYP = 2, FACCEN = 1, BURSTEN = 0, WAITEN = 0,
+ * WREN = 1, EXTMOD = 1, CBURSTRW = 0, ACCMOD = 1
+ */
+ bcr |= FIELD_PREP(FMC2_BCR_MTYP, FMC2_BCR_MTYP_NOR);
+ bcr |= FMC2_BCR_FACCEN | FMC2_BCR_EXTMOD;
+ btr |= FIELD_PREP(FMC2_BXTR_ACCMOD, FMC2_BXTR_EXTMOD_B);
+ bwtr |= FIELD_PREP(FMC2_BXTR_ACCMOD, FMC2_BXTR_EXTMOD_B);
+ break;
+ case FMC2_ASYNC_MODE_C_NOR:
+ /*
+ * MUXEN = 0, MTYP = 2, FACCEN = 1, BURSTEN = 0, WAITEN = 0,
+ * WREN = 1, EXTMOD = 1, CBURSTRW = 0, ACCMOD = 2
+ */
+ bcr |= FIELD_PREP(FMC2_BCR_MTYP, FMC2_BCR_MTYP_NOR);
+ bcr |= FMC2_BCR_FACCEN | FMC2_BCR_EXTMOD;
+ btr |= FIELD_PREP(FMC2_BXTR_ACCMOD, FMC2_BXTR_EXTMOD_C);
+ bwtr |= FIELD_PREP(FMC2_BXTR_ACCMOD, FMC2_BXTR_EXTMOD_C);
+ break;
+ case FMC2_ASYNC_MODE_D_NOR:
+ /*
+ * MUXEN = 0, MTYP = 2, FACCEN = 1, BURSTEN = 0, WAITEN = 0,
+ * WREN = 1, EXTMOD = 1, CBURSTRW = 0, ACCMOD = 3
+ */
+ bcr |= FIELD_PREP(FMC2_BCR_MTYP, FMC2_BCR_MTYP_NOR);
+ bcr |= FMC2_BCR_FACCEN | FMC2_BCR_EXTMOD;
+ btr |= FIELD_PREP(FMC2_BXTR_ACCMOD, FMC2_BXTR_EXTMOD_D);
+ bwtr |= FIELD_PREP(FMC2_BXTR_ACCMOD, FMC2_BXTR_EXTMOD_D);
+ break;
+ case FMC2_SYNC_READ_SYNC_WRITE_PSRAM:
+ /*
+ * MUXEN = 0, MTYP = 1, FACCEN = 0, BURSTEN = 1, WAITEN = 0,
+ * WREN = 1, EXTMOD = 0, CBURSTRW = 1, ACCMOD = 0
+ */
+ bcr |= FIELD_PREP(FMC2_BCR_MTYP, FMC2_BCR_MTYP_PSRAM);
+ bcr |= FMC2_BCR_BURSTEN | FMC2_BCR_CBURSTRW;
+ break;
+ case FMC2_SYNC_READ_ASYNC_WRITE_PSRAM:
+ /*
+ * MUXEN = 0, MTYP = 1, FACCEN = 0, BURSTEN = 1, WAITEN = 0,
+ * WREN = 1, EXTMOD = 0, CBURSTRW = 0, ACCMOD = 0
+ */
+ bcr |= FIELD_PREP(FMC2_BCR_MTYP, FMC2_BCR_MTYP_PSRAM);
+ bcr |= FMC2_BCR_BURSTEN;
+ break;
+ case FMC2_SYNC_READ_SYNC_WRITE_NOR:
+ /*
+ * MUXEN = 0, MTYP = 2, FACCEN = 1, BURSTEN = 1, WAITEN = 0,
+ * WREN = 1, EXTMOD = 0, CBURSTRW = 1, ACCMOD = 0
+ */
+ bcr |= FIELD_PREP(FMC2_BCR_MTYP, FMC2_BCR_MTYP_NOR);
+ bcr |= FMC2_BCR_FACCEN | FMC2_BCR_BURSTEN | FMC2_BCR_CBURSTRW;
+ break;
+ case FMC2_SYNC_READ_ASYNC_WRITE_NOR:
+ /*
+ * MUXEN = 0, MTYP = 2, FACCEN = 1, BURSTEN = 1, WAITEN = 0,
+ * WREN = 1, EXTMOD = 0, CBURSTRW = 0, ACCMOD = 0
+ */
+ bcr |= FIELD_PREP(FMC2_BCR_MTYP, FMC2_BCR_MTYP_NOR);
+ bcr |= FMC2_BCR_FACCEN | FMC2_BCR_BURSTEN;
+ break;
+ default:
+ /* Type of transaction not supported */
+ return -EINVAL;
+ }
+
+ if (bcr & FMC2_BCR_EXTMOD)
+ clrsetbits_le32(ebi->io_base + FMC2_BWTR(cs),
+ bwtr_mask, bwtr);
+ clrsetbits_le32(ebi->io_base + FMC2_BTR(cs), btr_mask, btr);
+ clrsetbits_le32(ebi->io_base + FMC2_BCR(cs), bcr_mask, bcr);
+
+ return 0;
+}
+
+static int stm32_fmc2_ebi_set_buswidth(struct stm32_fmc2_ebi *ebi,
+ const struct stm32_fmc2_prop *prop,
+ int cs, u32 setup)
+{
+ u32 val;
+
+ switch (setup) {
+ case FMC2_BUSWIDTH_8:
+ val = FIELD_PREP(FMC2_BCR_MWID, FMC2_BCR_MWID_8);
+ break;
+ case FMC2_BUSWIDTH_16:
+ val = FIELD_PREP(FMC2_BCR_MWID, FMC2_BCR_MWID_16);
+ break;
+ default:
+ /* Buswidth not supported */
+ return -EINVAL;
+ }
+
+ clrsetbits_le32(ebi->io_base + FMC2_BCR(cs), FMC2_BCR_MWID, val);
+
+ return 0;
+}
+
+static int stm32_fmc2_ebi_set_cpsize(struct stm32_fmc2_ebi *ebi,
+ const struct stm32_fmc2_prop *prop,
+ int cs, u32 setup)
+{
+ u32 val;
+
+ switch (setup) {
+ case FMC2_CPSIZE_0:
+ val = FIELD_PREP(FMC2_BCR_CPSIZE, FMC2_BCR_CPSIZE_0);
+ break;
+ case FMC2_CPSIZE_128:
+ val = FIELD_PREP(FMC2_BCR_CPSIZE, FMC2_BCR_CPSIZE_128);
+ break;
+ case FMC2_CPSIZE_256:
+ val = FIELD_PREP(FMC2_BCR_CPSIZE, FMC2_BCR_CPSIZE_256);
+ break;
+ case FMC2_CPSIZE_512:
+ val = FIELD_PREP(FMC2_BCR_CPSIZE, FMC2_BCR_CPSIZE_512);
+ break;
+ case FMC2_CPSIZE_1024:
+ val = FIELD_PREP(FMC2_BCR_CPSIZE, FMC2_BCR_CPSIZE_1024);
+ break;
+ default:
+ /* Cpsize not supported */
+ return -EINVAL;
+ }
+
+ clrsetbits_le32(ebi->io_base + FMC2_BCR(cs), FMC2_BCR_CPSIZE, val);
+
+ return 0;
+}
+
+static int stm32_fmc2_ebi_set_bl_setup(struct stm32_fmc2_ebi *ebi,
+ const struct stm32_fmc2_prop *prop,
+ int cs, u32 setup)
+{
+ u32 val;
+
+ val = min_t(u32, setup, FMC2_BCR_NBLSET_MAX);
+ val = FIELD_PREP(FMC2_BCR_NBLSET, val);
+ clrsetbits_le32(ebi->io_base + FMC2_BCR(cs), FMC2_BCR_NBLSET, val);
+
+ return 0;
+}
+
+static int stm32_fmc2_ebi_set_address_setup(struct stm32_fmc2_ebi *ebi,
+ const struct stm32_fmc2_prop *prop,
+ int cs, u32 setup)
+{
+ u32 bcr = readl(ebi->io_base + FMC2_BCR(cs));
+ u32 bxtr = prop->reg_type == FMC2_REG_BWTR ?
+ readl(ebi->io_base + FMC2_BWTR(cs)) :
+ readl(ebi->io_base + FMC2_BTR(cs));
+ u32 reg, val = FIELD_PREP(FMC2_BXTR_ACCMOD, FMC2_BXTR_EXTMOD_D);
+ int ret;
+
+ ret = stm32_fmc2_ebi_get_reg(prop->reg_type, cs, &reg);
+ if (ret)
+ return ret;
+
+ if ((bxtr & FMC2_BXTR_ACCMOD) == val || bcr & FMC2_BCR_MUXEN)
+ val = clamp_val(setup, 1, FMC2_BXTR_ADDSET_MAX);
+ else
+ val = min_t(u32, setup, FMC2_BXTR_ADDSET_MAX);
+ val = FIELD_PREP(FMC2_BXTR_ADDSET, val);
+ clrsetbits_le32(ebi->io_base + reg, FMC2_BXTR_ADDSET, val);
+
+ return 0;
+}
+
+static int stm32_fmc2_ebi_set_address_hold(struct stm32_fmc2_ebi *ebi,
+ const struct stm32_fmc2_prop *prop,
+ int cs, u32 setup)
+{
+ u32 val, reg;
+ int ret;
+
+ ret = stm32_fmc2_ebi_get_reg(prop->reg_type, cs, &reg);
+ if (ret)
+ return ret;
+
+ val = clamp_val(setup, 1, FMC2_BXTR_ADDHLD_MAX);
+ val = FIELD_PREP(FMC2_BXTR_ADDHLD, val);
+ clrsetbits_le32(ebi->io_base + reg, FMC2_BXTR_ADDHLD, val);
+
+ return 0;
+}
+
+static int stm32_fmc2_ebi_set_data_setup(struct stm32_fmc2_ebi *ebi,
+ const struct stm32_fmc2_prop *prop,
+ int cs, u32 setup)
+{
+ u32 val, reg;
+ int ret;
+
+ ret = stm32_fmc2_ebi_get_reg(prop->reg_type, cs, &reg);
+ if (ret)
+ return ret;
+
+ val = clamp_val(setup, 1, FMC2_BXTR_DATAST_MAX);
+ val = FIELD_PREP(FMC2_BXTR_DATAST, val);
+ clrsetbits_le32(ebi->io_base + reg, FMC2_BXTR_DATAST, val);
+
+ return 0;
+}
+
+static int stm32_fmc2_ebi_set_bus_turnaround(struct stm32_fmc2_ebi *ebi,
+ const struct stm32_fmc2_prop *prop,
+ int cs, u32 setup)
+{
+ u32 val, reg;
+ int ret;
+
+ ret = stm32_fmc2_ebi_get_reg(prop->reg_type, cs, &reg);
+ if (ret)
+ return ret;
+
+ val = setup ? min_t(u32, setup - 1, FMC2_BXTR_BUSTURN_MAX) : 0;
+ val = FIELD_PREP(FMC2_BXTR_BUSTURN, val);
+ clrsetbits_le32(ebi->io_base + reg, FMC2_BXTR_BUSTURN, val);
+
+ return 0;
+}
+
+static int stm32_fmc2_ebi_set_data_hold(struct stm32_fmc2_ebi *ebi,
+ const struct stm32_fmc2_prop *prop,
+ int cs, u32 setup)
+{
+ u32 val, reg;
+ int ret;
+
+ ret = stm32_fmc2_ebi_get_reg(prop->reg_type, cs, &reg);
+ if (ret)
+ return ret;
+
+ if (prop->reg_type == FMC2_REG_BWTR)
+ val = setup ? min_t(u32, setup - 1, FMC2_BXTR_DATAHLD_MAX) : 0;
+ else
+ val = min_t(u32, setup, FMC2_BXTR_DATAHLD_MAX);
+ val = FIELD_PREP(FMC2_BXTR_DATAHLD, val);
+ clrsetbits_le32(ebi->io_base + reg, FMC2_BXTR_DATAHLD, val);
+
+ return 0;
+}
+
+static int stm32_fmc2_ebi_set_clk_period(struct stm32_fmc2_ebi *ebi,
+ const struct stm32_fmc2_prop *prop,
+ int cs, u32 setup)
+{
+ u32 val;
+
+ val = setup ? clamp_val(setup - 1, 1, FMC2_BTR_CLKDIV_MAX) : 1;
+ val = FIELD_PREP(FMC2_BTR_CLKDIV, val);
+ clrsetbits_le32(ebi->io_base + FMC2_BTR(cs), FMC2_BTR_CLKDIV, val);
+
+ return 0;
+}
+
+static int stm32_fmc2_ebi_set_data_latency(struct stm32_fmc2_ebi *ebi,
+ const struct stm32_fmc2_prop *prop,
+ int cs, u32 setup)
+{
+ u32 val;
+
+ val = setup > 1 ? min_t(u32, setup - 2, FMC2_BTR_DATLAT_MAX) : 0;
+ val = FIELD_PREP(FMC2_BTR_DATLAT, val);
+ clrsetbits_le32(ebi->io_base + FMC2_BTR(cs), FMC2_BTR_DATLAT, val);
+
+ return 0;
+}
+
+static int stm32_fmc2_ebi_set_max_low_pulse(struct stm32_fmc2_ebi *ebi,
+ const struct stm32_fmc2_prop *prop,
+ int cs, u32 setup)
+{
+ u32 old_val, new_val, pcscntr;
+
+ if (setup < 1)
+ return 0;
+
+ pcscntr = readl(ebi->io_base + FMC2_PCSCNTR);
+
+ /* Enable counter for the bank */
+ setbits_le32(ebi->io_base + FMC2_PCSCNTR, FMC2_PCSCNTR_CNTBEN(cs));
+
+ new_val = min_t(u32, setup - 1, FMC2_PCSCNTR_CSCOUNT_MAX);
+ old_val = FIELD_GET(FMC2_PCSCNTR_CSCOUNT, pcscntr);
+ if (old_val && new_val > old_val)
+ /* Keep current counter value */
+ return 0;
+
+ new_val = FIELD_PREP(FMC2_PCSCNTR_CSCOUNT, new_val);
+ clrsetbits_le32(ebi->io_base + FMC2_PCSCNTR,
+ FMC2_PCSCNTR_CSCOUNT, new_val);
+
+ return 0;
+}
+
+static const struct stm32_fmc2_prop stm32_fmc2_child_props[] = {
+ /* st,fmc2-ebi-cs-trans-type must be the first property */
+ {
+ .name = "st,fmc2-ebi-cs-transaction-type",
+ .mprop = true,
+ .set = stm32_fmc2_ebi_set_trans_type,
+ },
+ {
+ .name = "st,fmc2-ebi-cs-cclk-enable",
+ .bprop = true,
+ .reg_type = FMC2_REG_BCR,
+ .reg_mask = FMC2_BCR1_CCLKEN,
+ .check = stm32_fmc2_ebi_check_cclk,
+ .set = stm32_fmc2_ebi_set_bit_field,
+ },
+ {
+ .name = "st,fmc2-ebi-cs-mux-enable",
+ .bprop = true,
+ .reg_type = FMC2_REG_BCR,
+ .reg_mask = FMC2_BCR_MUXEN,
+ .check = stm32_fmc2_ebi_check_mux,
+ .set = stm32_fmc2_ebi_set_bit_field,
+ },
+ {
+ .name = "st,fmc2-ebi-cs-buswidth",
+ .reset_val = FMC2_BUSWIDTH_16,
+ .set = stm32_fmc2_ebi_set_buswidth,
+ },
+ {
+ .name = "st,fmc2-ebi-cs-waitpol-high",
+ .bprop = true,
+ .reg_type = FMC2_REG_BCR,
+ .reg_mask = FMC2_BCR_WAITPOL,
+ .set = stm32_fmc2_ebi_set_bit_field,
+ },
+ {
+ .name = "st,fmc2-ebi-cs-waitcfg-enable",
+ .bprop = true,
+ .reg_type = FMC2_REG_BCR,
+ .reg_mask = FMC2_BCR_WAITCFG,
+ .check = stm32_fmc2_ebi_check_waitcfg,
+ .set = stm32_fmc2_ebi_set_bit_field,
+ },
+ {
+ .name = "st,fmc2-ebi-cs-wait-enable",
+ .bprop = true,
+ .reg_type = FMC2_REG_BCR,
+ .reg_mask = FMC2_BCR_WAITEN,
+ .check = stm32_fmc2_ebi_check_sync_trans,
+ .set = stm32_fmc2_ebi_set_bit_field,
+ },
+ {
+ .name = "st,fmc2-ebi-cs-asyncwait-enable",
+ .bprop = true,
+ .reg_type = FMC2_REG_BCR,
+ .reg_mask = FMC2_BCR_ASYNCWAIT,
+ .check = stm32_fmc2_ebi_check_async_trans,
+ .set = stm32_fmc2_ebi_set_bit_field,
+ },
+ {
+ .name = "st,fmc2-ebi-cs-cpsize",
+ .check = stm32_fmc2_ebi_check_cpsize,
+ .set = stm32_fmc2_ebi_set_cpsize,
+ },
+ {
+ .name = "st,fmc2-ebi-cs-byte-lane-setup-ns",
+ .calculate = stm32_fmc2_ebi_ns_to_clock_cycles,
+ .set = stm32_fmc2_ebi_set_bl_setup,
+ },
+ {
+ .name = "st,fmc2-ebi-cs-address-setup-ns",
+ .reg_type = FMC2_REG_BTR,
+ .reset_val = FMC2_BXTR_ADDSET_MAX,
+ .check = stm32_fmc2_ebi_check_async_trans,
+ .calculate = stm32_fmc2_ebi_ns_to_clock_cycles,
+ .set = stm32_fmc2_ebi_set_address_setup,
+ },
+ {
+ .name = "st,fmc2-ebi-cs-address-hold-ns",
+ .reg_type = FMC2_REG_BTR,
+ .reset_val = FMC2_BXTR_ADDHLD_MAX,
+ .check = stm32_fmc2_ebi_check_address_hold,
+ .calculate = stm32_fmc2_ebi_ns_to_clock_cycles,
+ .set = stm32_fmc2_ebi_set_address_hold,
+ },
+ {
+ .name = "st,fmc2-ebi-cs-data-setup-ns",
+ .reg_type = FMC2_REG_BTR,
+ .reset_val = FMC2_BXTR_DATAST_MAX,
+ .check = stm32_fmc2_ebi_check_async_trans,
+ .calculate = stm32_fmc2_ebi_ns_to_clock_cycles,
+ .set = stm32_fmc2_ebi_set_data_setup,
+ },
+ {
+ .name = "st,fmc2-ebi-cs-bus-turnaround-ns",
+ .reg_type = FMC2_REG_BTR,
+ .reset_val = FMC2_BXTR_BUSTURN_MAX + 1,
+ .calculate = stm32_fmc2_ebi_ns_to_clock_cycles,
+ .set = stm32_fmc2_ebi_set_bus_turnaround,
+ },
+ {
+ .name = "st,fmc2-ebi-cs-data-hold-ns",
+ .reg_type = FMC2_REG_BTR,
+ .check = stm32_fmc2_ebi_check_async_trans,
+ .calculate = stm32_fmc2_ebi_ns_to_clock_cycles,
+ .set = stm32_fmc2_ebi_set_data_hold,
+ },
+ {
+ .name = "st,fmc2-ebi-cs-clk-period-ns",
+ .reset_val = FMC2_BTR_CLKDIV_MAX + 1,
+ .check = stm32_fmc2_ebi_check_clk_period,
+ .calculate = stm32_fmc2_ebi_ns_to_clock_cycles,
+ .set = stm32_fmc2_ebi_set_clk_period,
+ },
+ {
+ .name = "st,fmc2-ebi-cs-data-latency-ns",
+ .check = stm32_fmc2_ebi_check_sync_trans,
+ .calculate = stm32_fmc2_ebi_ns_to_clk_period,
+ .set = stm32_fmc2_ebi_set_data_latency,
+ },
+ {
+ .name = "st,fmc2-ebi-cs-write-address-setup-ns",
+ .reg_type = FMC2_REG_BWTR,
+ .reset_val = FMC2_BXTR_ADDSET_MAX,
+ .check = stm32_fmc2_ebi_check_async_trans,
+ .calculate = stm32_fmc2_ebi_ns_to_clock_cycles,
+ .set = stm32_fmc2_ebi_set_address_setup,
+ },
+ {
+ .name = "st,fmc2-ebi-cs-write-address-hold-ns",
+ .reg_type = FMC2_REG_BWTR,
+ .reset_val = FMC2_BXTR_ADDHLD_MAX,
+ .check = stm32_fmc2_ebi_check_address_hold,
+ .calculate = stm32_fmc2_ebi_ns_to_clock_cycles,
+ .set = stm32_fmc2_ebi_set_address_hold,
+ },
+ {
+ .name = "st,fmc2-ebi-cs-write-data-setup-ns",
+ .reg_type = FMC2_REG_BWTR,
+ .reset_val = FMC2_BXTR_DATAST_MAX,
+ .check = stm32_fmc2_ebi_check_async_trans,
+ .calculate = stm32_fmc2_ebi_ns_to_clock_cycles,
+ .set = stm32_fmc2_ebi_set_data_setup,
+ },
+ {
+ .name = "st,fmc2-ebi-cs-write-bus-turnaround-ns",
+ .reg_type = FMC2_REG_BWTR,
+ .reset_val = FMC2_BXTR_BUSTURN_MAX + 1,
+ .calculate = stm32_fmc2_ebi_ns_to_clock_cycles,
+ .set = stm32_fmc2_ebi_set_bus_turnaround,
+ },
+ {
+ .name = "st,fmc2-ebi-cs-write-data-hold-ns",
+ .reg_type = FMC2_REG_BWTR,
+ .check = stm32_fmc2_ebi_check_async_trans,
+ .calculate = stm32_fmc2_ebi_ns_to_clock_cycles,
+ .set = stm32_fmc2_ebi_set_data_hold,
+ },
+ {
+ .name = "st,fmc2-ebi-cs-max-low-pulse-ns",
+ .calculate = stm32_fmc2_ebi_ns_to_clock_cycles,
+ .set = stm32_fmc2_ebi_set_max_low_pulse,
+ },
+};
+
+static int stm32_fmc2_ebi_parse_prop(struct stm32_fmc2_ebi *ebi,
+ ofnode node,
+ const struct stm32_fmc2_prop *prop,
+ int cs)
+{
+ u32 setup = 0;
+
+ if (!prop->set) {
+ pr_err("property %s is not well defined\n", prop->name);
+ return -EINVAL;
+ }
+
+ if (prop->check && prop->check(ebi, prop, cs))
+ /* Skip this property */
+ return 0;
+
+ if (prop->bprop) {
+ bool bprop;
+
+ bprop = ofnode_read_bool(node, prop->name);
+ if (prop->mprop && !bprop) {
+ pr_err("mandatory property %s not defined in the device tree\n",
+ prop->name);
+ return -EINVAL;
+ }
+
+ if (bprop)
+ setup = 1;
+ } else {
+ u32 val;
+ int ret;
+
+ ret = ofnode_read_u32(node, prop->name, &val);
+ if (prop->mprop && ret) {
+ pr_err("mandatory property %s not defined in the device tree\n",
+ prop->name);
+ return ret;
+ }
+
+ if (ret)
+ setup = prop->reset_val;
+ else if (prop->calculate)
+ setup = prop->calculate(ebi, cs, val);
+ else
+ setup = val;
+ }
+
+ return prop->set(ebi, prop, cs, setup);
+}
+
+static void stm32_fmc2_ebi_enable_bank(struct stm32_fmc2_ebi *ebi, int cs)
+{
+ setbits_le32(ebi->io_base + FMC2_BCR(cs), FMC2_BCR_MBKEN);
+}
+
+static void stm32_fmc2_ebi_disable_bank(struct stm32_fmc2_ebi *ebi, int cs)
+{
+ clrbits_le32(ebi->io_base + FMC2_BCR(cs), FMC2_BCR_MBKEN);
+}
+
+/* NWAIT signal can not be connected to EBI controller and NAND controller */
+static bool stm32_fmc2_ebi_nwait_used_by_ctrls(struct stm32_fmc2_ebi *ebi)
+{
+ unsigned int cs;
+ u32 bcr;
+
+ for (cs = 0; cs < FMC2_MAX_EBI_CE; cs++) {
+ if (!(ebi->bank_assigned & BIT(cs)))
+ continue;
+
+ bcr = readl(ebi->io_base + FMC2_BCR(cs));
+ if ((bcr & FMC2_BCR_WAITEN || bcr & FMC2_BCR_ASYNCWAIT) &&
+ ebi->bank_assigned & BIT(FMC2_NAND))
+ return true;
+ }
+
+ return false;
+}
+
+static void stm32_fmc2_ebi_enable(struct stm32_fmc2_ebi *ebi)
+{
+ setbits_le32(ebi->io_base + FMC2_BCR1, FMC2_BCR1_FMC2EN);
+}
+
+static int stm32_fmc2_ebi_setup_cs(struct stm32_fmc2_ebi *ebi,
+ ofnode node, u32 cs)
+{
+ unsigned int i;
+ int ret;
+
+ stm32_fmc2_ebi_disable_bank(ebi, cs);
+
+ for (i = 0; i < ARRAY_SIZE(stm32_fmc2_child_props); i++) {
+ const struct stm32_fmc2_prop *p = &stm32_fmc2_child_props[i];
+
+ ret = stm32_fmc2_ebi_parse_prop(ebi, node, p, cs);
+ if (ret) {
+ pr_err("property %s could not be set: %d\n",
+ p->name, ret);
+ return ret;
+ }
+ }
+
+ stm32_fmc2_ebi_enable_bank(ebi, cs);
+
+ return 0;
+}
+
+static int stm32_fmc2_ebi_parse_dt(struct udevice *dev,
+ struct stm32_fmc2_ebi *ebi)
+{
+ ofnode child;
+ bool child_found = false;
+ u32 bank;
+ int ret;
+
+ dev_for_each_subnode(child, dev) {
+ ret = ofnode_read_u32(child, "reg", &bank);
+ if (ret) {
+ pr_err("could not retrieve reg property: %d\n", ret);
+ return ret;
+ }
+
+ if (bank >= FMC2_MAX_BANKS) {
+ pr_err("invalid reg value: %d\n", bank);
+ return -EINVAL;
+ }
+
+ if (ebi->bank_assigned & BIT(bank)) {
+ pr_err("bank already assigned: %d\n", bank);
+ return -EINVAL;
+ }
+
+ if (bank < FMC2_MAX_EBI_CE) {
+ ret = stm32_fmc2_ebi_setup_cs(ebi, child, bank);
+ if (ret) {
+ pr_err("setup chip select %d failed: %d\n",
+ bank, ret);
+ return ret;
+ }
+ }
+
+ ebi->bank_assigned |= BIT(bank);
+ child_found = true;
+ }
+
+ if (!child_found) {
+ pr_warn("no subnodes found, disable the driver.\n");
+ return -ENODEV;
+ }
+
+ if (stm32_fmc2_ebi_nwait_used_by_ctrls(ebi)) {
+ pr_err("NWAIT signal connected to EBI and NAND controllers\n");
+ return -EINVAL;
+ }
+
+ stm32_fmc2_ebi_enable(ebi);
+
+ return 0;
+}
+
+static int stm32_fmc2_ebi_probe(struct udevice *dev)
+{
+ struct stm32_fmc2_ebi *ebi = dev_get_priv(dev);
+ struct reset_ctl reset;
+ int ret;
+
+ ebi->io_base = dev_read_addr(dev);
+ if (ebi->io_base == FDT_ADDR_T_NONE)
+ return -EINVAL;
+
+ ret = clk_get_by_index(dev, 0, &ebi->clk);
+ if (ret)
+ return ret;
+
+ ret = clk_enable(&ebi->clk);
+ if (ret)
+ return ret;
+
+ ret = reset_get_by_index(dev, 0, &reset);
+ if (!ret) {
+ reset_assert(&reset);
+ udelay(2);
+ reset_deassert(&reset);
+ }
+
+ return stm32_fmc2_ebi_parse_dt(dev, ebi);
+}
+
+static const struct udevice_id stm32_fmc2_ebi_match[] = {
+ {.compatible = "st,stm32mp1-fmc2-ebi"},
+ { /* Sentinel */ }
+};
+
+U_BOOT_DRIVER(stm32_fmc2_ebi) = {
+ .name = "stm32_fmc2_ebi",
+ .id = UCLASS_NOP,
+ .of_match = stm32_fmc2_ebi_match,
+ .probe = stm32_fmc2_ebi_probe,
+ .priv_auto_alloc_size = sizeof(struct stm32_fmc2_ebi),
+ .bind = dm_scan_fdt_dev,
+};
diff --git a/drivers/mtd/nand/raw/stm32_fmc2_nand.c b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
index 3306bd8ac9..47fe61090d 100644
--- a/drivers/mtd/nand/raw/stm32_fmc2_nand.c
+++ b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
@@ -10,6 +10,7 @@
#include <log.h>
#include <nand.h>
#include <reset.h>
+#include <linux/bitfield.h>
#include <linux/bitops.h>
#include <linux/delay.h>
#include <linux/err.h>
@@ -60,20 +61,16 @@
/* Register: FMC2_PCR */
#define FMC2_PCR_PWAITEN BIT(1)
#define FMC2_PCR_PBKEN BIT(2)
-#define FMC2_PCR_PWID_MASK GENMASK(5, 4)
-#define FMC2_PCR_PWID(x) (((x) & 0x3) << 4)
+#define FMC2_PCR_PWID GENMASK(5, 4)
#define FMC2_PCR_PWID_BUSWIDTH_8 0
#define FMC2_PCR_PWID_BUSWIDTH_16 1
#define FMC2_PCR_ECCEN BIT(6)
#define FMC2_PCR_ECCALG BIT(8)
-#define FMC2_PCR_TCLR_MASK GENMASK(12, 9)
-#define FMC2_PCR_TCLR(x) (((x) & 0xf) << 9)
+#define FMC2_PCR_TCLR GENMASK(12, 9)
#define FMC2_PCR_TCLR_DEFAULT 0xf
-#define FMC2_PCR_TAR_MASK GENMASK(16, 13)
-#define FMC2_PCR_TAR(x) (((x) & 0xf) << 13)
+#define FMC2_PCR_TAR GENMASK(16, 13)
#define FMC2_PCR_TAR_DEFAULT 0xf
-#define FMC2_PCR_ECCSS_MASK GENMASK(19, 17)
-#define FMC2_PCR_ECCSS(x) (((x) & 0x7) << 17)
+#define FMC2_PCR_ECCSS GENMASK(19, 17)
#define FMC2_PCR_ECCSS_512 1
#define FMC2_PCR_ECCSS_2048 3
#define FMC2_PCR_BCHECC BIT(24)
@@ -83,17 +80,17 @@
#define FMC2_SR_NWRF BIT(6)
/* Register: FMC2_PMEM */
-#define FMC2_PMEM_MEMSET(x) (((x) & 0xff) << 0)
-#define FMC2_PMEM_MEMWAIT(x) (((x) & 0xff) << 8)
-#define FMC2_PMEM_MEMHOLD(x) (((x) & 0xff) << 16)
-#define FMC2_PMEM_MEMHIZ(x) (((x) & 0xff) << 24)
+#define FMC2_PMEM_MEMSET GENMASK(7, 0)
+#define FMC2_PMEM_MEMWAIT GENMASK(15, 8)
+#define FMC2_PMEM_MEMHOLD GENMASK(23, 16)
+#define FMC2_PMEM_MEMHIZ GENMASK(31, 24)
#define FMC2_PMEM_DEFAULT 0x0a0a0a0a
/* Register: FMC2_PATT */
-#define FMC2_PATT_ATTSET(x) (((x) & 0xff) << 0)
-#define FMC2_PATT_ATTWAIT(x) (((x) & 0xff) << 8)
-#define FMC2_PATT_ATTHOLD(x) (((x) & 0xff) << 16)
-#define FMC2_PATT_ATTHIZ(x) (((x) & 0xff) << 24)
+#define FMC2_PATT_ATTSET GENMASK(7, 0)
+#define FMC2_PATT_ATTWAIT GENMASK(15, 8)
+#define FMC2_PATT_ATTHOLD GENMASK(23, 16)
+#define FMC2_PATT_ATTHIZ GENMASK(31, 24)
#define FMC2_PATT_DEFAULT 0x0a0a0a0a
/* Register: FMC2_BCHISR */
@@ -106,31 +103,28 @@
/* Register: FMC2_BCHDSR0 */
#define FMC2_BCHDSR0_DUE BIT(0)
#define FMC2_BCHDSR0_DEF BIT(1)
-#define FMC2_BCHDSR0_DEN_MASK GENMASK(7, 4)
-#define FMC2_BCHDSR0_DEN_SHIFT 4
+#define FMC2_BCHDSR0_DEN GENMASK(7, 4)
/* Register: FMC2_BCHDSR1 */
-#define FMC2_BCHDSR1_EBP1_MASK GENMASK(12, 0)
-#define FMC2_BCHDSR1_EBP2_MASK GENMASK(28, 16)
-#define FMC2_BCHDSR1_EBP2_SHIFT 16
+#define FMC2_BCHDSR1_EBP1 GENMASK(12, 0)
+#define FMC2_BCHDSR1_EBP2 GENMASK(28, 16)
/* Register: FMC2_BCHDSR2 */
-#define FMC2_BCHDSR2_EBP3_MASK GENMASK(12, 0)
-#define FMC2_BCHDSR2_EBP4_MASK GENMASK(28, 16)
-#define FMC2_BCHDSR2_EBP4_SHIFT 16
+#define FMC2_BCHDSR2_EBP3 GENMASK(12, 0)
+#define FMC2_BCHDSR2_EBP4 GENMASK(28, 16)
/* Register: FMC2_BCHDSR3 */
-#define FMC2_BCHDSR3_EBP5_MASK GENMASK(12, 0)
-#define FMC2_BCHDSR3_EBP6_MASK GENMASK(28, 16)
-#define FMC2_BCHDSR3_EBP6_SHIFT 16
+#define FMC2_BCHDSR3_EBP5 GENMASK(12, 0)
+#define FMC2_BCHDSR3_EBP6 GENMASK(28, 16)
/* Register: FMC2_BCHDSR4 */
-#define FMC2_BCHDSR4_EBP7_MASK GENMASK(12, 0)
-#define FMC2_BCHDSR4_EBP8_MASK GENMASK(28, 16)
-#define FMC2_BCHDSR4_EBP8_SHIFT 16
+#define FMC2_BCHDSR4_EBP7 GENMASK(12, 0)
+#define FMC2_BCHDSR4_EBP8 GENMASK(28, 16)
#define FMC2_NSEC_PER_SEC 1000000000L
+#define FMC2_TIMEOUT_5S 5000000
+
enum stm32_fmc2_ecc {
FMC2_ECC_HAM = 1,
FMC2_ECC_BCH4 = 4,
@@ -164,10 +158,10 @@ struct stm32_fmc2_nfc {
struct nand_hw_control base;
struct stm32_fmc2_nand nand;
struct nand_ecclayout ecclayout;
- void __iomem *io_base;
- void __iomem *data_base[FMC2_MAX_CE];
- void __iomem *cmd_base[FMC2_MAX_CE];
- void __iomem *addr_base[FMC2_MAX_CE];
+ fdt_addr_t io_base;
+ fdt_addr_t data_base[FMC2_MAX_CE];
+ fdt_addr_t cmd_base[FMC2_MAX_CE];
+ fdt_addr_t addr_base[FMC2_MAX_CE];
struct clk clk;
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);
}
-/* Timings configuration */
-static void stm32_fmc2_timings_init(struct nand_chip *chip)
+static void stm32_fmc2_nfc_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_timings *timings = &nand->timings;
- u32 pcr = readl(fmc2->io_base + FMC2_PCR);
u32 pmem, patt;
/* Set tclr/tar timings */
- pcr &= ~FMC2_PCR_TCLR_MASK;
- pcr |= FMC2_PCR_TCLR(timings->tclr);
- pcr &= ~FMC2_PCR_TAR_MASK;
- pcr |= FMC2_PCR_TAR(timings->tar);
+ clrsetbits_le32(nfc->io_base + FMC2_PCR,
+ FMC2_PCR_TCLR | FMC2_PCR_TAR,
+ FIELD_PREP(FMC2_PCR_TCLR, timings->tclr) |
+ FIELD_PREP(FMC2_PCR_TAR, timings->tar));
/* Set tset/twait/thold/thiz timings in common bank */
- pmem = FMC2_PMEM_MEMSET(timings->tset_mem);
- pmem |= FMC2_PMEM_MEMWAIT(timings->twait);
- pmem |= FMC2_PMEM_MEMHOLD(timings->thold_mem);
- pmem |= FMC2_PMEM_MEMHIZ(timings->thiz);
+ pmem = FIELD_PREP(FMC2_PMEM_MEMSET, timings->tset_mem);
+ pmem |= FIELD_PREP(FMC2_PMEM_MEMWAIT, timings->twait);
+ pmem |= FIELD_PREP(FMC2_PMEM_MEMHOLD, timings->thold_mem);
+ pmem |= FIELD_PREP(FMC2_PMEM_MEMHIZ, timings->thiz);
+ writel(pmem, nfc->io_base + FMC2_PMEM);
/* Set tset/twait/thold/thiz timings in attribut bank */
- patt = FMC2_PATT_ATTSET(timings->tset_att);
- patt |= FMC2_PATT_ATTWAIT(timings->twait);
- patt |= FMC2_PATT_ATTHOLD(timings->thold_att);
- patt |= FMC2_PATT_ATTHIZ(timings->thiz);
-
- writel(pcr, fmc2->io_base + FMC2_PCR);
- writel(pmem, fmc2->io_base + FMC2_PMEM);
- writel(patt, fmc2->io_base + FMC2_PATT);
+ patt = FIELD_PREP(FMC2_PATT_ATTSET, timings->tset_att);
+ patt |= FIELD_PREP(FMC2_PATT_ATTWAIT, timings->twait);
+ patt |= FIELD_PREP(FMC2_PATT_ATTHOLD, timings->thold_att);
+ patt |= FIELD_PREP(FMC2_PATT_ATTHIZ, timings->thiz);
+ writel(patt, nfc->io_base + FMC2_PATT);
}
-/* Controller configuration */
-static void stm32_fmc2_setup(struct nand_chip *chip)
+static void stm32_fmc2_nfc_setup(struct nand_chip *chip)
{
- struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
- u32 pcr = readl(fmc2->io_base + FMC2_PCR);
+ struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller);
+ u32 pcr = 0, pcr_mask;
/* Configure ECC algorithm (default configuration is Hamming) */
- pcr &= ~FMC2_PCR_ECCALG;
- pcr &= ~FMC2_PCR_BCHECC;
+ pcr_mask = FMC2_PCR_ECCALG;
+ pcr_mask |= FMC2_PCR_BCHECC;
if (chip->ecc.strength == FMC2_ECC_BCH8) {
pcr |= FMC2_PCR_ECCALG;
pcr |= FMC2_PCR_BCHECC;
@@ -228,111 +217,95 @@ static void stm32_fmc2_setup(struct nand_chip *chip)
}
/* Set buswidth */
- pcr &= ~FMC2_PCR_PWID_MASK;
+ pcr_mask |= FMC2_PCR_PWID;
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 */
- pcr &= ~FMC2_PCR_ECCSS_MASK;
- pcr |= FMC2_PCR_ECCSS(FMC2_PCR_ECCSS_512);
+ pcr_mask |= FMC2_PCR_ECCSS;
+ 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_select_chip(struct mtd_info *mtd, int chipnr)
+static void stm32_fmc2_nfc_select_chip(struct mtd_info *mtd, int chipnr)
{
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);
if (chipnr < 0 || chipnr >= nand->ncs)
return;
- if (nand->cs_used[chipnr] == fmc2->cs_sel)
+ if (nand->cs_used[chipnr] == nfc->cs_sel)
return;
- fmc2->cs_sel = nand->cs_used[chipnr];
- chip->IO_ADDR_R = fmc2->data_base[fmc2->cs_sel];
- chip->IO_ADDR_W = fmc2->data_base[fmc2->cs_sel];
-
- /* FMC2 setup routine */
- stm32_fmc2_setup(chip);
+ nfc->cs_sel = nand->cs_used[chipnr];
+ chip->IO_ADDR_R = (void __iomem *)nfc->data_base[nfc->cs_sel];
+ chip->IO_ADDR_W = (void __iomem *)nfc->data_base[nfc->cs_sel];
- /* Apply timings */
- stm32_fmc2_timings_init(chip);
+ stm32_fmc2_nfc_setup(chip);
+ stm32_fmc2_nfc_timings_init(chip);
}
-/* Set bus width to 16-bit or 8-bit */
-static void stm32_fmc2_set_buswidth_16(struct stm32_fmc2_nfc *fmc2, bool set)
+static void stm32_fmc2_nfc_set_buswidth_16(struct stm32_fmc2_nfc *nfc,
+ bool set)
{
- u32 pcr = readl(fmc2->io_base + FMC2_PCR);
+ u32 pcr;
- pcr &= ~FMC2_PCR_PWID_MASK;
- if (set)
- pcr |= FMC2_PCR_PWID(FMC2_PCR_PWID_BUSWIDTH_16);
- writel(pcr, fmc2->io_base + FMC2_PCR);
+ pcr = set ? FIELD_PREP(FMC2_PCR_PWID, FMC2_PCR_PWID_BUSWIDTH_16) :
+ FIELD_PREP(FMC2_PCR_PWID, FMC2_PCR_PWID_BUSWIDTH_8);
+
+ clrsetbits_le32(nfc->io_base + FMC2_PCR, FMC2_PCR_PWID, pcr);
}
-/* Enable/disable ECC */
-static void stm32_fmc2_set_ecc(struct stm32_fmc2_nfc *fmc2, bool enable)
+static void stm32_fmc2_nfc_set_ecc(struct stm32_fmc2_nfc *nfc, bool enable)
{
- u32 pcr = readl(fmc2->io_base + FMC2_PCR);
-
- pcr &= ~FMC2_PCR_ECCEN;
- if (enable)
- pcr |= FMC2_PCR_ECCEN;
- writel(pcr, fmc2->io_base + FMC2_PCR);
+ clrsetbits_le32(nfc->io_base + FMC2_PCR, FMC2_PCR_ECCEN,
+ enable ? FMC2_PCR_ECCEN : 0);
}
-/* Clear irq sources in case of bch is used */
-static inline void stm32_fmc2_clear_bch_irq(struct stm32_fmc2_nfc *fmc2)
+static void stm32_fmc2_nfc_clear_bch_irq(struct stm32_fmc2_nfc *nfc)
{
- 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_cmd_ctrl(struct mtd_info *mtd, int cmd,
- unsigned int ctrl)
+static void stm32_fmc2_nfc_cmd_ctrl(struct mtd_info *mtd, int cmd,
+ unsigned int ctrl)
{
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)
return;
if (ctrl & NAND_CLE) {
- writeb(cmd, fmc2->cmd_base[fmc2->cs_sel]);
+ writeb(cmd, nfc->cmd_base[nfc->cs_sel]);
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
* 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 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) {
- 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)
- pcr |= FMC2_PCR_WEN;
- else
- pcr &= ~FMC2_PCR_WEN;
- writel(pcr, fmc2->io_base + FMC2_PCR);
-
- stm32_fmc2_clear_bch_irq(fmc2);
+ stm32_fmc2_nfc_clear_bch_irq(nfc);
}
- 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
* max of 1-bit)
*/
-static int stm32_fmc2_ham_calculate(struct mtd_info *mtd, const u8 *data,
- u8 *ecc)
+static int stm32_fmc2_nfc_ham_calculate(struct mtd_info *mtd, const u8 *data,
+ u8 *ecc)
{
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;
int ret;
- ret = readl_poll_timeout(fmc2->io_base + FMC2_SR, sr,
- sr & FMC2_SR_NWRF, 10000);
+ ret = readl_poll_timeout(nfc->io_base + FMC2_SR, sr,
+ sr & FMC2_SR_NWRF, FMC2_TIMEOUT_5S);
if (ret < 0) {
pr_err("Ham timeout\n");
return ret;
}
- heccr = readl(fmc2->io_base + FMC2_HECCR);
+ heccr = readl(nfc->io_base + FMC2_HECCR);
ecc[0] = heccr;
ecc[1] = heccr >> 8;
ecc[2] = heccr >> 16;
- /* Disable ecc */
- stm32_fmc2_set_ecc(fmc2, false);
+ stm32_fmc2_nfc_set_ecc(nfc, false);
return 0;
}
-static int stm32_fmc2_ham_correct(struct mtd_info *mtd, u8 *dat,
- u8 *read_ecc, u8 *calc_ecc)
+static int stm32_fmc2_nfc_ham_correct(struct mtd_info *mtd, u8 *dat,
+ u8 *read_ecc, u8 *calc_ecc)
{
u8 bit_position = 0, b0, b1, b2;
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)
*/
-static int stm32_fmc2_bch_calculate(struct mtd_info *mtd, const u8 *data,
- u8 *ecc)
+static int stm32_fmc2_nfc_bch_calculate(struct mtd_info *mtd, const u8 *data,
+ u8 *ecc)
{
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;
int ret;
/* Wait until the BCH code is ready */
- ret = readl_poll_timeout(fmc2->io_base + FMC2_BCHISR, bchisr,
- bchisr & FMC2_BCHISR_EPBRF, 10000);
+ ret = readl_poll_timeout(nfc->io_base + FMC2_BCHISR, bchisr,
+ bchisr & FMC2_BCHISR_EPBRF, FMC2_TIMEOUT_5S);
if (ret < 0) {
pr_err("Bch timeout\n");
return ret;
}
/* Read parity bits */
- bchpbr = readl(fmc2->io_base + FMC2_BCHPBR1);
+ bchpbr = readl(nfc->io_base + FMC2_BCHPBR1);
ecc[0] = bchpbr;
ecc[1] = bchpbr >> 8;
ecc[2] = bchpbr >> 16;
ecc[3] = bchpbr >> 24;
- bchpbr = readl(fmc2->io_base + FMC2_BCHPBR2);
+ bchpbr = readl(nfc->io_base + FMC2_BCHPBR2);
ecc[4] = bchpbr;
ecc[5] = bchpbr >> 8;
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) {
ecc[7] = bchpbr >> 24;
- bchpbr = readl(fmc2->io_base + FMC2_BCHPBR3);
+ bchpbr = readl(nfc->io_base + FMC2_BCHPBR3);
ecc[8] = bchpbr;
ecc[9] = bchpbr >> 8;
ecc[10] = bchpbr >> 16;
ecc[11] = bchpbr >> 24;
- bchpbr = readl(fmc2->io_base + FMC2_BCHPBR4);
+ bchpbr = readl(nfc->io_base + FMC2_BCHPBR4);
ecc[12] = bchpbr;
}
- /* Disable ecc */
- stm32_fmc2_set_ecc(fmc2, false);
+ stm32_fmc2_nfc_set_ecc(nfc, false);
return 0;
}
-/* BCH algorithm correction */
-static int stm32_fmc2_bch_correct(struct mtd_info *mtd, u8 *dat,
- u8 *read_ecc, u8 *calc_ecc)
+static int stm32_fmc2_nfc_bch_correct(struct mtd_info *mtd, u8 *dat,
+ u8 *read_ecc, u8 *calc_ecc)
{
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;
u16 pos[8];
int i, ret, den, eccsize = chip->ecc.size;
unsigned int nb_errs = 0;
/* Wait until the decoding error is ready */
- ret = readl_poll_timeout(fmc2->io_base + FMC2_BCHISR, bchisr,
- bchisr & FMC2_BCHISR_DERF, 10000);
+ ret = readl_poll_timeout(nfc->io_base + FMC2_BCHISR, bchisr,
+ bchisr & FMC2_BCHISR_DERF, FMC2_TIMEOUT_5S);
if (ret < 0) {
pr_err("Bch timeout\n");
return ret;
}
- bchdsr0 = readl(fmc2->io_base + FMC2_BCHDSR0);
- bchdsr1 = readl(fmc2->io_base + FMC2_BCHDSR1);
- bchdsr2 = readl(fmc2->io_base + FMC2_BCHDSR2);
- bchdsr3 = readl(fmc2->io_base + FMC2_BCHDSR3);
- bchdsr4 = readl(fmc2->io_base + FMC2_BCHDSR4);
+ bchdsr0 = readl(nfc->io_base + FMC2_BCHDSR0);
+ bchdsr1 = readl(nfc->io_base + FMC2_BCHDSR1);
+ bchdsr2 = readl(nfc->io_base + FMC2_BCHDSR2);
+ bchdsr3 = readl(nfc->io_base + FMC2_BCHDSR3);
+ bchdsr4 = readl(nfc->io_base + FMC2_BCHDSR4);
- /* Disable ECC */
- stm32_fmc2_set_ecc(fmc2, false);
+ stm32_fmc2_nfc_set_ecc(nfc, false);
/* No errors found */
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))
return -EBADMSG;
- pos[0] = bchdsr1 & FMC2_BCHDSR1_EBP1_MASK;
- pos[1] = (bchdsr1 & FMC2_BCHDSR1_EBP2_MASK) >> FMC2_BCHDSR1_EBP2_SHIFT;
- pos[2] = bchdsr2 & FMC2_BCHDSR2_EBP3_MASK;
- pos[3] = (bchdsr2 & FMC2_BCHDSR2_EBP4_MASK) >> FMC2_BCHDSR2_EBP4_SHIFT;
- pos[4] = bchdsr3 & FMC2_BCHDSR3_EBP5_MASK;
- pos[5] = (bchdsr3 & FMC2_BCHDSR3_EBP6_MASK) >> FMC2_BCHDSR3_EBP6_SHIFT;
- pos[6] = bchdsr4 & FMC2_BCHDSR4_EBP7_MASK;
- pos[7] = (bchdsr4 & FMC2_BCHDSR4_EBP8_MASK) >> FMC2_BCHDSR4_EBP8_SHIFT;
+ pos[0] = FIELD_GET(FMC2_BCHDSR1_EBP1, bchdsr1);
+ pos[1] = FIELD_GET(FMC2_BCHDSR1_EBP2, bchdsr1);
+ pos[2] = FIELD_GET(FMC2_BCHDSR2_EBP3, bchdsr2);
+ pos[3] = FIELD_GET(FMC2_BCHDSR2_EBP4, bchdsr2);
+ pos[4] = FIELD_GET(FMC2_BCHDSR3_EBP5, bchdsr3);
+ pos[5] = FIELD_GET(FMC2_BCHDSR3_EBP6, bchdsr3);
+ pos[6] = FIELD_GET(FMC2_BCHDSR4_EBP7, bchdsr4);
+ 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++) {
if (pos[i] < eccsize * 8) {
__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;
}
-static int stm32_fmc2_read_page(struct mtd_info *mtd,
- struct nand_chip *chip, u8 *buf,
- int oob_required, int page)
+static int stm32_fmc2_nfc_read_page(struct mtd_info *mtd,
+ struct nand_chip *chip, u8 *buf,
+ int oob_required, int page)
{
int i, s, stat, eccsize = chip->ecc.size;
int eccbytes = chip->ecc.bytes;
@@ -579,21 +548,19 @@ static int stm32_fmc2_read_page(struct mtd_info *mtd,
return max_bitflips;
}
-/* Controller initialization */
-static void stm32_fmc2_init(struct stm32_fmc2_nfc *fmc2)
+static void stm32_fmc2_nfc_init(struct stm32_fmc2_nfc *nfc, bool has_parent)
{
- u32 pcr = readl(fmc2->io_base + FMC2_PCR);
- u32 bcr1 = readl(fmc2->io_base + FMC2_BCR1);
+ u32 pcr = readl(nfc->io_base + FMC2_PCR);
/* Set CS used to undefined */
- fmc2->cs_sel = -1;
+ nfc->cs_sel = -1;
/* Enable wait feature and nand flash memory bank */
pcr |= FMC2_PCR_PWAITEN;
pcr |= FMC2_PCR_PBKEN;
/* Set buswidth to 8 bits mode for identification */
- pcr &= ~FMC2_PCR_PWID_MASK;
+ pcr &= ~FMC2_PCR_PWID;
/* ECC logic is disabled */
pcr &= ~FMC2_PCR_ECCEN;
@@ -604,32 +571,31 @@ static void stm32_fmc2_init(struct stm32_fmc2_nfc *fmc2)
pcr &= ~FMC2_PCR_WEN;
/* Set default ECC sector size */
- pcr &= ~FMC2_PCR_ECCSS_MASK;
- pcr |= FMC2_PCR_ECCSS(FMC2_PCR_ECCSS_2048);
+ pcr &= ~FMC2_PCR_ECCSS;
+ pcr |= FIELD_PREP(FMC2_PCR_ECCSS, FMC2_PCR_ECCSS_2048);
/* Set default tclr/tar timings */
- pcr &= ~FMC2_PCR_TCLR_MASK;
- pcr |= FMC2_PCR_TCLR(FMC2_PCR_TCLR_DEFAULT);
- pcr &= ~FMC2_PCR_TAR_MASK;
- pcr |= FMC2_PCR_TAR(FMC2_PCR_TAR_DEFAULT);
+ pcr &= ~FMC2_PCR_TCLR;
+ pcr |= FIELD_PREP(FMC2_PCR_TCLR, FMC2_PCR_TCLR_DEFAULT);
+ pcr &= ~FMC2_PCR_TAR;
+ pcr |= FIELD_PREP(FMC2_PCR_TAR, FMC2_PCR_TAR_DEFAULT);
/* 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, fmc2->io_base + FMC2_PCR);
- writel(FMC2_PMEM_DEFAULT, fmc2->io_base + FMC2_PMEM);
- writel(FMC2_PATT_DEFAULT, fmc2->io_base + FMC2_PATT);
+ writel(pcr, nfc->io_base + FMC2_PCR);
+ writel(FMC2_PMEM_DEFAULT, nfc->io_base + FMC2_PMEM);
+ writel(FMC2_PATT_DEFAULT, nfc->io_base + FMC2_PATT);
}
-/* Controller timings */
-static void stm32_fmc2_calc_timings(struct nand_chip *chip,
- const struct nand_sdr_timings *sdrt)
+static void stm32_fmc2_nfc_calc_timings(struct nand_chip *chip,
+ 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_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 timing, tar, tclr, thiz, twait;
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);
}
-static int stm32_fmc2_setup_interface(struct mtd_info *mtd, int chipnr,
- const struct nand_data_interface *conf)
+static int stm32_fmc2_nfc_setup_interface(struct mtd_info *mtd, int chipnr,
+ const struct nand_data_interface *cf)
{
struct nand_chip *chip = mtd_to_nand(mtd);
const struct nand_sdr_timings *sdrt;
- sdrt = nand_get_sdr_timings(conf);
+ sdrt = nand_get_sdr_timings(cf);
if (IS_ERR(sdrt))
return PTR_ERR(sdrt);
if (chipnr == NAND_DATA_IFACE_CHECK_ONLY)
return 0;
- stm32_fmc2_calc_timings(chip, sdrt);
-
- /* Apply timings */
- stm32_fmc2_timings_init(chip);
+ stm32_fmc2_nfc_calc_timings(chip, sdrt);
+ stm32_fmc2_nfc_timings_init(chip);
return 0;
}
-/* NAND callbacks setup */
-static void stm32_fmc2_nand_callbacks_setup(struct nand_chip *chip)
+static void stm32_fmc2_nfc_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
@@ -785,17 +748,17 @@ static void stm32_fmc2_nand_callbacks_setup(struct nand_chip *chip)
*/
if (chip->ecc.strength == FMC2_ECC_HAM) {
/* Hamming is used */
- chip->ecc.calculate = stm32_fmc2_ham_calculate;
- chip->ecc.correct = stm32_fmc2_ham_correct;
+ chip->ecc.calculate = stm32_fmc2_nfc_ham_calculate;
+ chip->ecc.correct = stm32_fmc2_nfc_ham_correct;
chip->ecc.bytes = chip->options & NAND_BUSWIDTH_16 ? 4 : 3;
chip->ecc.options |= NAND_ECC_GENERIC_ERASED_CHECK;
return;
}
/* BCH is used */
- chip->ecc.read_page = stm32_fmc2_read_page;
- chip->ecc.calculate = stm32_fmc2_bch_calculate;
- chip->ecc.correct = stm32_fmc2_bch_correct;
+ chip->ecc.read_page = stm32_fmc2_nfc_read_page;
+ chip->ecc.calculate = stm32_fmc2_nfc_bch_calculate;
+ chip->ecc.correct = stm32_fmc2_nfc_bch_correct;
if (chip->ecc.strength == FMC2_ECC_BCH8)
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;
}
-/* FMC2 caps */
-static int stm32_fmc2_calc_ecc_bytes(int step_size, int strength)
+static int stm32_fmc2_nfc_calc_ecc_bytes(int step_size, int strength)
{
/* Hamming */
if (strength == FMC2_ECC_HAM)
@@ -818,15 +780,13 @@ static int stm32_fmc2_calc_ecc_bytes(int step_size, int strength)
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_HAM, FMC2_ECC_BCH4, FMC2_ECC_BCH8);
-/* FMC2 probe */
-static int stm32_fmc2_parse_child(struct stm32_fmc2_nfc *fmc2,
- ofnode node)
+static int stm32_fmc2_nfc_parse_child(struct stm32_fmc2_nfc *nfc, ofnode node)
{
- struct stm32_fmc2_nand *nand = &fmc2->nand;
+ struct stm32_fmc2_nand *nand = &nfc->nand;
u32 cs[FMC2_MAX_CE];
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++) {
- if (cs[i] > FMC2_MAX_CE) {
+ if (cs[i] >= FMC2_MAX_CE) {
pr_err("Invalid reg value: %d\n",
nand->cs_used[i]);
return -EINVAL;
}
- if (fmc2->cs_assigned & BIT(cs[i])) {
+ if (nfc->cs_assigned & BIT(cs[i])) {
pr_err("Cs already assigned: %d\n",
nand->cs_used[i]);
return -EINVAL;
}
- fmc2->cs_assigned |= BIT(cs[i]);
+ nfc->cs_assigned |= BIT(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;
}
-static int stm32_fmc2_parse_dt(struct udevice *dev,
- struct stm32_fmc2_nfc *fmc2)
+static int stm32_fmc2_nfc_parse_dt(struct udevice *dev,
+ struct stm32_fmc2_nfc *nfc)
{
ofnode child;
int ret, nchips = 0;
@@ -887,7 +847,7 @@ static int stm32_fmc2_parse_dt(struct udevice *dev,
}
dev_for_each_subnode(child, dev) {
- ret = stm32_fmc2_parse_child(fmc2, child);
+ ret = stm32_fmc2_nfc_parse_child(nfc, child);
if (ret)
return ret;
}
@@ -895,69 +855,98 @@ static int stm32_fmc2_parse_dt(struct udevice *dev,
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 stm32_fmc2_nand *nand = &fmc2->nand;
+ struct udevice *pdev = dev_get_parent(dev);
+ 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 mtd_info *mtd = &chip->mtd;
struct nand_ecclayout *ecclayout;
- struct resource resource;
+ struct udevice *cdev;
struct reset_ctl reset;
int oob_index, chip_cs, mem_region, ret;
unsigned int i;
+ int start_region = 0;
+ fdt_addr_t addr;
+
+ spin_lock_init(&nfc->controller.lock);
+ init_waitqueue_head(&nfc->controller.wq);
- spin_lock_init(&fmc2->controller.lock);
- init_waitqueue_head(&fmc2->controller.wq);
+ cdev = stm32_fmc2_nfc_get_cdev(dev);
+ if (!cdev)
+ return -EINVAL;
- ret = stm32_fmc2_parse_dt(dev, fmc2);
+ ret = stm32_fmc2_nfc_parse_dt(dev, nfc);
if (ret)
return ret;
- /* Get resources */
- ret = dev_read_resource(dev, 0, &resource);
- if (ret) {
- pr_err("Resource io_base not found");
- return ret;
- }
- fmc2->io_base = (void __iomem *)resource.start;
+ nfc->io_base = dev_read_addr(cdev);
+ if (nfc->io_base == FDT_ADDR_T_NONE)
+ return -EINVAL;
+
+ if (dev == cdev)
+ start_region = 1;
- for (chip_cs = 0, mem_region = 1; chip_cs < FMC2_MAX_CE;
+ for (chip_cs = 0, mem_region = start_region; chip_cs < FMC2_MAX_CE;
chip_cs++, mem_region += 3) {
- if (!(fmc2->cs_assigned & BIT(chip_cs)))
+ if (!(nfc->cs_assigned & BIT(chip_cs)))
continue;
- ret = dev_read_resource(dev, mem_region, &resource);
- if (ret) {
+ addr = dev_read_addr_index(dev, mem_region);
+ if (addr == FDT_ADDR_T_NONE) {
pr_err("Resource data_base not found for cs%d",
chip_cs);
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);
- if (ret) {
+ addr = dev_read_addr_index(dev, mem_region + 1);
+ if (addr == FDT_ADDR_T_NONE) {
pr_err("Resource cmd_base not found for cs%d",
chip_cs);
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);
- if (ret) {
+ addr = dev_read_addr_index(dev, mem_region + 2);
+ if (addr == FDT_ADDR_T_NONE) {
pr_err("Resource addr_base not found for cs%d",
chip_cs);
return ret;
}
- fmc2->addr_base[chip_cs] = (void __iomem *)resource.start;
+ nfc->addr_base[chip_cs] = addr;
}
/* Enable the clock */
- ret = clk_get_by_index(dev, 0, &fmc2->clk);
+ ret = clk_get_by_index(cdev, 0, &nfc->clk);
if (ret)
return ret;
- ret = clk_enable(&fmc2->clk);
+ ret = clk_enable(&nfc->clk);
if (ret)
return ret;
@@ -969,13 +958,12 @@ static int stm32_fmc2_probe(struct udevice *dev)
reset_deassert(&reset);
}
- /* FMC2 init routine */
- stm32_fmc2_init(fmc2);
+ stm32_fmc2_nfc_init(nfc, dev != cdev);
- chip->controller = &fmc2->base;
- chip->select_chip = stm32_fmc2_select_chip;
- chip->setup_data_interface = stm32_fmc2_setup_interface;
- chip->cmd_ctrl = stm32_fmc2_cmd_ctrl;
+ chip->controller = &nfc->base;
+ chip->select_chip = stm32_fmc2_nfc_select_chip;
+ chip->setup_data_interface = stm32_fmc2_nfc_setup_interface;
+ chip->cmd_ctrl = stm32_fmc2_nfc_cmd_ctrl;
chip->chip_delay = FMC2_RB_DELAY_US;
chip->options |= NAND_BUSWIDTH_AUTO | NAND_NO_SUBPAGE_WRITE |
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.strength = FMC2_ECC_BCH8;
- /* Scan to find existence of the device */
ret = nand_scan_ident(mtd, nand->ncs, NULL);
if (ret)
return ret;
@@ -1002,7 +989,7 @@ static int stm32_fmc2_probe(struct udevice *dev)
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);
if (ret) {
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)
chip->bbt_options |= NAND_BBT_NO_OOB;
- /* NAND callbacks setup */
- stm32_fmc2_nand_callbacks_setup(chip);
+ stm32_fmc2_nfc_nand_callbacks_setup(chip);
/* Define ECC layout */
- ecclayout = &fmc2->ecclayout;
+ ecclayout = &nfc->ecclayout;
ecclayout->eccbytes = chip->ecc.bytes *
(mtd->writesize / chip->ecc.size);
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;
chip->ecc.layout = ecclayout;
- /* Configure bus width to 16-bit */
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);
if (ret)
return ret;
@@ -1038,16 +1022,17 @@ static int stm32_fmc2_probe(struct udevice *dev)
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,stm32mp1-fmc2-nfc" },
{ /* Sentinel */ }
};
-U_BOOT_DRIVER(stm32_fmc2_nand) = {
- .name = "stm32_fmc2_nand",
+U_BOOT_DRIVER(stm32_fmc2_nfc) = {
+ .name = "stm32_fmc2_nfc",
.id = UCLASS_MTD,
- .of_match = stm32_fmc2_match,
- .probe = stm32_fmc2_probe,
+ .of_match = stm32_fmc2_nfc_match,
+ .probe = stm32_fmc2_nfc_probe,
.priv_auto_alloc_size = sizeof(struct stm32_fmc2_nfc),
};
@@ -1057,9 +1042,9 @@ void board_nand_init(void)
int ret;
ret = uclass_get_device_by_driver(UCLASS_MTD,
- DM_GET_DRIVER(stm32_fmc2_nand),
+ DM_GET_DRIVER(stm32_fmc2_nfc),
&dev);
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);
}
diff --git a/drivers/usb/host/dwc3-sti-glue.c b/drivers/usb/host/dwc3-sti-glue.c
index a72ab20168..3e6c1429d6 100644
--- a/drivers/usb/host/dwc3-sti-glue.c
+++ b/drivers/usb/host/dwc3-sti-glue.c
@@ -159,7 +159,7 @@ static int sti_dwc3_glue_bind(struct udevice *dev)
dwc3_node = node;
}
- if (!ofnode_valid(node)) {
+ if (!ofnode_valid(dwc3_node)) {
pr_err("Can't find dwc3 subnode for %s\n", dev->name);
return -ENODEV;
}