mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-11-10 15:14:43 +00:00
- Use IS_ENABLED to prevent ifdef in board_key_check for STM32MP
- Add STM32 FMC2 EBI controller driver - Fix dwc3-sti-glue which allows STiH410-B2260 to boot again - Add fitImage its entry for 587-200 DHCOR SoM - Add both PDK2 and DRC02 DT into DHCOM fitImage its - Fix DHCOM KS8851 ethernet MAC address - Remove stm32mp1 board.c file - Use const for struct node_info in board stm32mp1.c file -----BEGIN PGP SIGNATURE----- iQJLBAABCgA1FiEEXyrViUccKBz9c35Jysd4L3sz/6YFAl81JrkXHHBhdHJpY2Uu Y2hvdGFyZEBzdC5jb20ACgkQysd4L3sz/6ZZBw//TiEtosS/6NRuC3kzK9KrpVUY hIvrZldrh5lr+RZn7GqmNHD9CUZeXFBweG6ah5oHImsyaUdUnWZSftXykEzdIyoL +r2j27npjqviATH1dZNliZnb/QiMsPmmf7XmF2MO0U7NTkbc7GMvsPWHAllk7jue cPfa+uiRWsfM2oiHki6zC+QvfYQ5x+yxsWjoaOXgyAqjC8oIFBTqXFCHEYPhhZPr 9yu7uIXkahpEZe0x2J/5B0rCfgwpaX/fkF9OU35ThhpSEJOLWneiNwMtODGS96CQ VjJhpdP3T/8TL8cQF+DJVP3tBQn60zepb12LvYY4Lhm08EolBRS8E/reukthkhWP 9C8KBHNFZG/PTccuHhF2t75AsFOQm37xR5S6qf2vjTYddTojqKQ404/BB89+jkJP 2bYfi5VZc9kz5gD4faGObHqqhhaMeC64ihrtJouFR8APS8IMEzsb282LX6mpa+IM Id9zKHEyLZ9vig/ybQ2G1lpucFYtDrEcl7HBLFGrPkzWXhhvh8Onm6BGda378lBM JTTstUlDPrmc8OSUR8RSE15LXnoYP4QfJwUUy2/DOYt3GoHWCIHAY2V5Eo+ATl7q 2p2/5pi/mOblSk5LW3cnjAqlnFmH7IVp4rLNLPvunRSDC34lhjvOzTgEiBvwqA/Z 2YbPPXFM7nwU/OXbG7w= =J4aq -----END PGP SIGNATURE----- Merge tag 'u-boot-stm32-20200813' of https://gitlab.denx.de/u-boot/custodians/u-boot-stm - Use IS_ENABLED to prevent ifdef in board_key_check for STM32MP - Add STM32 FMC2 EBI controller driver - Fix dwc3-sti-glue which allows STiH410-B2260 to boot again - Add fitImage its entry for 587-200 DHCOR SoM - Add both PDK2 and DRC02 DT into DHCOM fitImage its - Fix DHCOM KS8851 ethernet MAC address - Remove stm32mp1 board.c file - Use const for struct node_info in board stm32mp1.c file
This commit is contained in:
commit
6808dc62d7
20 changed files with 1628 additions and 520 deletions
|
@ -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 {
|
||||
|
|
|
@ -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>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
mmc1 = &sdmmc2;
|
||||
spi0 = &qspi;
|
||||
usb0 = &usbotg_hs;
|
||||
ethernet1 = &ksz8851;
|
||||
};
|
||||
|
||||
config {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
|
||||
|
|
|
@ -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++) {
|
||||
|
|
|
@ -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];
|
||||
|
||||
snprintf(test, sizeof(test), "somrev%d_boardrev%d", somcode, brdcode);
|
||||
compat = fdt_getprop(gd->fdt_blob, 0, "compatible", NULL);
|
||||
|
||||
snprintf(test, sizeof(test), "%s_somrev%d_boardrev%d",
|
||||
compat, somcode, brdcode);
|
||||
|
||||
if (!strcmp(name, test))
|
||||
return 0;
|
||||
|
|
|
@ -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 */
|
||||
};
|
||||
};
|
||||
|
|
|
@ -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";
|
||||
};
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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
|
|
@ -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);
|
||||
}
|
||||
#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;
|
||||
dm_gpio_free(NULL, &gpio);
|
||||
}
|
||||
}
|
||||
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;
|
||||
|
||||
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);
|
||||
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);
|
||||
|
||||
env_set("board_name", fdt_compat + 3);
|
||||
buf_len = sizeof(dtb_name);
|
||||
strncpy(dtb_name, fdt_compat + 3, buf_len);
|
||||
buf_len -= strlen(fdt_compat + 3);
|
||||
strncat(dtb_name, ".dtb", buf_len);
|
||||
env_set("fdtfile", dtb_name);
|
||||
}
|
||||
}
|
||||
ret = uclass_get_device_by_driver(UCLASS_MISC,
|
||||
DM_GET_DRIVER(stm32mp_bsec),
|
||||
&dev);
|
||||
|
||||
strncpy(dtb_name, fdt_compat + 3, buf_len);
|
||||
buf_len -= strlen(fdt_compat + 3);
|
||||
strncat(dtb_name, ".dtb", buf_len);
|
||||
env_set("fdtfile", dtb_name);
|
||||
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);
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -1,2 +1,3 @@
|
|||
|
||||
obj-$(CONFIG_STM32_FMC2_EBI) += stm32-fmc2-ebi.o
|
||||
obj-$(CONFIG_TI_AEMIF) += ti-aemif.o
|
||||
|
|
1056
drivers/memory/stm32-fmc2-ebi.c
Normal file
1056
drivers/memory/stm32-fmc2-ebi.c
Normal file
File diff suppressed because it is too large
Load diff
|
@ -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];
|
||||
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];
|
||||
|
||||
/* FMC2 setup routine */
|
||||
stm32_fmc2_setup(chip);
|
||||
|
||||
/* 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(&fmc2->controller.lock);
|
||||
init_waitqueue_head(&fmc2->controller.wq);
|
||||
spin_lock_init(&nfc->controller.lock);
|
||||
init_waitqueue_head(&nfc->controller.wq);
|
||||
|
||||
ret = stm32_fmc2_parse_dt(dev, fmc2);
|
||||
cdev = stm32_fmc2_nfc_get_cdev(dev);
|
||||
if (!cdev)
|
||||
return -EINVAL;
|
||||
|
||||
ret = stm32_fmc2_nfc_parse_dt(dev, nfc);
|
||||
if (ret)
|
||||
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;
|
||||
|
||||
for (chip_cs = 0, mem_region = 1; chip_cs < FMC2_MAX_CE;
|
||||
if (dev == cdev)
|
||||
start_region = 1;
|
||||
|
||||
for (chip_cs = 0, mem_region = start_region; chip_cs < FMC2_MAX_CE;
|
||||
chip_cs++, mem_region += 3) {
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue