diff options
author | Patrick Delaunay <patrick.delaunay@st.com> | 2020-03-18 09:24:59 +0100 |
---|---|---|
committer | Patrick Delaunay <patrick.delaunay@st.com> | 2020-05-14 09:02:12 +0200 |
commit | 6ce1f4ad8d300272e7584a514d9be0c334754ff7 (patch) | |
tree | 571dbcb64fdff2b9a6d81afdfd8c7d6db35e738a /arch/arm/mach-stm32mp/cmd_stm32prog/stm32prog.c | |
parent | 936f1aea8006ba5fda13a6d9d2f08baf0a4e7b97 (diff) |
stm32mp: stm32prog: add pmic NVM update support
Add a virtual partition to update the pmic non volatile memory.
(on ST board, STPMIC1).
Signed-off-by: Patrick Delaunay <patrick.delaunay@st.com>
Reviewed-by: Patrice Chotard <patrice.chotard@st.com>
Diffstat (limited to 'arch/arm/mach-stm32mp/cmd_stm32prog/stm32prog.c')
-rw-r--r-- | arch/arm/mach-stm32mp/cmd_stm32prog/stm32prog.c | 95 |
1 files changed, 94 insertions, 1 deletions
diff --git a/arch/arm/mach-stm32mp/cmd_stm32prog/stm32prog.c b/arch/arm/mach-stm32mp/cmd_stm32prog/stm32prog.c index cd826dbb9c..d127afefaa 100644 --- a/arch/arm/mach-stm32mp/cmd_stm32prog/stm32prog.c +++ b/arch/arm/mach-stm32mp/cmd_stm32prog/stm32prog.c @@ -7,6 +7,7 @@ #include <console.h> #include <dfu.h> #include <malloc.h> +#include <misc.h> #include <mmc.h> #include <part.h> #include <asm/arch/stm32mp1_smc.h> @@ -1107,7 +1108,7 @@ static int dfu_init_entities(struct stm32prog_data *data) struct dfu_entity *dfu; int alt_nb; - alt_nb = 2; /* number of virtual = CMD, OTP*/ + alt_nb = 3; /* number of virtual = CMD, OTP, PMIC*/ if (data->part_nb == 0) alt_nb++; /* +1 for FlashLayout */ else @@ -1158,6 +1159,9 @@ static int dfu_init_entities(struct stm32prog_data *data) if (!ret) ret = stm32prog_alt_add_virt(dfu, "OTP", PHASE_OTP, 512); + if (!ret && CONFIG_IS_ENABLED(DM_PMIC)) + ret = stm32prog_alt_add_virt(dfu, "PMIC", PHASE_PMIC, 8); + if (ret) stm32prog_err("dfu init failed: %d", ret); puts("done\n"); @@ -1285,6 +1289,93 @@ int stm32prog_otp_start(struct stm32prog_data *data) #endif } +int stm32prog_pmic_write(struct stm32prog_data *data, u32 offset, u8 *buffer, + long *size) +{ + pr_debug("%s: %x %lx\n", __func__, offset, *size); + + if (!offset) + memset(data->pmic_part, 0, PMIC_SIZE); + + if (offset + *size > PMIC_SIZE) + *size = PMIC_SIZE - offset; + + memcpy(&data->pmic_part[offset], buffer, *size); + + return 0; +} + +int stm32prog_pmic_read(struct stm32prog_data *data, u32 offset, u8 *buffer, + long *size) +{ + int result = 0, ret; + struct udevice *dev; + + if (!CONFIG_IS_ENABLED(PMIC_STPMIC1)) { + stm32prog_err("PMIC update not supported"); + + return -EOPNOTSUPP; + } + + pr_debug("%s: %x %lx\n", __func__, offset, *size); + ret = uclass_get_device_by_driver(UCLASS_MISC, + DM_GET_DRIVER(stpmic1_nvm), + &dev); + if (ret) + return ret; + + /* alway request PMIC for first packet */ + if (!offset) { + /* init struct with 0 */ + memset(data->pmic_part, 0, PMIC_SIZE); + + ret = uclass_get_device_by_driver(UCLASS_MISC, + DM_GET_DRIVER(stpmic1_nvm), + &dev); + if (ret) + return ret; + + ret = misc_read(dev, 0xF8, data->pmic_part, PMIC_SIZE); + if (ret < 0) { + result = ret; + goto end_pmic_read; + } + if (ret != PMIC_SIZE) { + result = -EACCES; + goto end_pmic_read; + } + } + + if (offset + *size > PMIC_SIZE) + *size = PMIC_SIZE - offset; + + memcpy(buffer, &data->pmic_part[offset], *size); + +end_pmic_read: + pr_debug("%s: result %i\n", __func__, result); + return result; +} + +int stm32prog_pmic_start(struct stm32prog_data *data) +{ + int ret; + struct udevice *dev; + + if (!CONFIG_IS_ENABLED(PMIC_STPMIC1)) { + stm32prog_err("PMIC update not supported"); + + return -EOPNOTSUPP; + } + + ret = uclass_get_device_by_driver(UCLASS_MISC, + DM_GET_DRIVER(stpmic1_nvm), + &dev); + if (ret) + return ret; + + return misc_write(dev, 0xF8, data->pmic_part, PMIC_SIZE); +} + /* copy FSBL on NAND to improve reliability on NAND */ static int stm32prog_copy_fsbl(struct stm32prog_part_t *part) { @@ -1585,6 +1676,8 @@ void dfu_flush_callback(struct dfu_entity *dfu) if (dfu->dev_type == DFU_DEV_VIRT) { if (dfu->data.virt.dev_num == PHASE_OTP) stm32prog_otp_start(stm32prog_data); + else if (dfu->data.virt.dev_num == PHASE_PMIC) + stm32prog_pmic_start(stm32prog_data); return; } |