mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-11-08 06:04:34 +00:00
65e25bea59
In the spirit of using the same base name for all of these related macros, rename this to have the operation at the end. This is not widely used so the impact is fairly small. Signed-off-by: Simon Glass <sjg@chromium.org>
248 lines
5.3 KiB
C
248 lines
5.3 KiB
C
// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
|
|
/*
|
|
* Copyright (C) 2020, STMicroelectronics - All Rights Reserved
|
|
*/
|
|
|
|
#include <common.h>
|
|
#include <blk.h>
|
|
#include <dm.h>
|
|
#include <dfu.h>
|
|
#include <env.h>
|
|
#include <memalign.h>
|
|
#include <misc.h>
|
|
#include <mtd.h>
|
|
#include <mtd_node.h>
|
|
#include <asm/arch/stm32prog.h>
|
|
|
|
#define DFU_ALT_BUF_LEN SZ_1K
|
|
|
|
static void board_get_alt_info_mmc(struct udevice *dev, char *buf)
|
|
{
|
|
struct disk_partition info;
|
|
int p, len, devnum;
|
|
bool first = true;
|
|
const char *name;
|
|
struct mmc *mmc;
|
|
struct blk_desc *desc;
|
|
|
|
mmc = mmc_get_mmc_dev(dev);
|
|
if (!mmc)
|
|
return;
|
|
|
|
if (mmc_init(mmc))
|
|
return;
|
|
|
|
desc = mmc_get_blk_desc(mmc);
|
|
if (!desc)
|
|
return;
|
|
|
|
name = blk_get_if_type_name(desc->if_type);
|
|
devnum = desc->devnum;
|
|
len = strlen(buf);
|
|
|
|
if (buf[0] != '\0')
|
|
len += snprintf(buf + len,
|
|
DFU_ALT_BUF_LEN - len, "&");
|
|
len += snprintf(buf + len, DFU_ALT_BUF_LEN - len,
|
|
"%s %d=", name, devnum);
|
|
|
|
if (IS_MMC(mmc) && mmc->capacity_boot) {
|
|
len += snprintf(buf + len, DFU_ALT_BUF_LEN - len,
|
|
"%s%d_boot1 raw 0x0 0x%llx mmcpart 1;",
|
|
name, devnum, mmc->capacity_boot);
|
|
len += snprintf(buf + len, DFU_ALT_BUF_LEN - len,
|
|
"%s%d_boot2 raw 0x0 0x%llx mmcpart 2",
|
|
name, devnum, mmc->capacity_boot);
|
|
first = false;
|
|
}
|
|
|
|
for (p = 1; p < MAX_SEARCH_PARTITIONS; p++) {
|
|
if (part_get_info(desc, p, &info))
|
|
continue;
|
|
if (!first)
|
|
len += snprintf(buf + len, DFU_ALT_BUF_LEN - len, ";");
|
|
first = false;
|
|
len += snprintf(buf + len, DFU_ALT_BUF_LEN - len,
|
|
"%s%d_%s part %d %d",
|
|
name, devnum, info.name, devnum, p);
|
|
}
|
|
}
|
|
|
|
static void board_get_alt_info_mtd(struct mtd_info *mtd, char *buf)
|
|
{
|
|
struct mtd_info *part;
|
|
bool first = true;
|
|
const char *name;
|
|
int len, partnum = 0;
|
|
|
|
name = mtd->name;
|
|
len = strlen(buf);
|
|
|
|
if (buf[0] != '\0')
|
|
len += snprintf(buf + len, DFU_ALT_BUF_LEN - len, "&");
|
|
len += snprintf(buf + len, DFU_ALT_BUF_LEN - len,
|
|
"mtd %s=", name);
|
|
|
|
len += snprintf(buf + len, DFU_ALT_BUF_LEN - len,
|
|
"%s raw 0x0 0x%llx ",
|
|
name, mtd->size);
|
|
|
|
list_for_each_entry(part, &mtd->partitions, node) {
|
|
partnum++;
|
|
if (!first)
|
|
len += snprintf(buf + len, DFU_ALT_BUF_LEN - len, ";");
|
|
first = false;
|
|
|
|
len += snprintf(buf + len, DFU_ALT_BUF_LEN - len,
|
|
"%s_%s part %d",
|
|
name, part->name, partnum);
|
|
}
|
|
}
|
|
|
|
void set_dfu_alt_info(char *interface, char *devstr)
|
|
{
|
|
struct udevice *dev;
|
|
struct mtd_info *mtd;
|
|
|
|
ALLOC_CACHE_ALIGN_BUFFER(char, buf, DFU_ALT_BUF_LEN);
|
|
|
|
if (env_get("dfu_alt_info"))
|
|
return;
|
|
|
|
memset(buf, 0, sizeof(buf));
|
|
|
|
snprintf(buf, DFU_ALT_BUF_LEN,
|
|
"ram 0=%s", CONFIG_DFU_ALT_RAM0);
|
|
|
|
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 (CONFIG_IS_ENABLED(MTD)) {
|
|
/* probe all MTD devices */
|
|
mtd_probe_devices();
|
|
|
|
/* probe SPI flash device on a bus */
|
|
if (!uclass_get_device(UCLASS_SPI_FLASH, 0, &dev)) {
|
|
mtd = get_mtd_device_nm("nor0");
|
|
if (!IS_ERR_OR_NULL(mtd))
|
|
board_get_alt_info_mtd(mtd, buf);
|
|
}
|
|
|
|
mtd = get_mtd_device_nm("nand0");
|
|
if (!IS_ERR_OR_NULL(mtd))
|
|
board_get_alt_info_mtd(mtd, buf);
|
|
|
|
mtd = get_mtd_device_nm("spi-nand0");
|
|
if (!IS_ERR_OR_NULL(mtd))
|
|
board_get_alt_info_mtd(mtd, buf);
|
|
}
|
|
|
|
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);
|
|
}
|
|
|
|
env_set("dfu_alt_info", buf);
|
|
puts("DFU alt info setting: done\n");
|
|
}
|
|
|
|
#if CONFIG_IS_ENABLED(DFU_VIRT)
|
|
#include <dfu.h>
|
|
#include <power/stpmic1.h>
|
|
|
|
static int dfu_otp_read(u64 offset, u8 *buffer, long *size)
|
|
{
|
|
struct udevice *dev;
|
|
int ret;
|
|
|
|
ret = uclass_get_device_by_driver(UCLASS_MISC,
|
|
DM_DRIVER_GET(stm32mp_bsec),
|
|
&dev);
|
|
if (ret)
|
|
return ret;
|
|
|
|
ret = misc_read(dev, offset + STM32_BSEC_OTP_OFFSET, buffer, *size);
|
|
if (ret >= 0) {
|
|
*size = ret;
|
|
ret = 0;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int dfu_pmic_read(u64 offset, u8 *buffer, long *size)
|
|
{
|
|
int ret;
|
|
#ifdef CONFIG_PMIC_STPMIC1
|
|
struct udevice *dev;
|
|
|
|
ret = uclass_get_device_by_driver(UCLASS_MISC,
|
|
DM_DRIVER_GET(stpmic1_nvm),
|
|
&dev);
|
|
if (ret)
|
|
return ret;
|
|
|
|
ret = misc_read(dev, 0xF8 + offset, buffer, *size);
|
|
if (ret >= 0) {
|
|
*size = ret;
|
|
ret = 0;
|
|
}
|
|
if (ret == -EACCES) {
|
|
*size = 0;
|
|
ret = 0;
|
|
}
|
|
#else
|
|
pr_err("PMIC update not supported");
|
|
ret = -EOPNOTSUPP;
|
|
#endif
|
|
|
|
return ret;
|
|
}
|
|
|
|
int dfu_read_medium_virt(struct dfu_entity *dfu, u64 offset,
|
|
void *buf, long *len)
|
|
{
|
|
switch (dfu->data.virt.dev_num) {
|
|
case 0x0:
|
|
return dfu_otp_read(offset, buf, len);
|
|
case 0x1:
|
|
return dfu_pmic_read(offset, buf, len);
|
|
}
|
|
|
|
if (CONFIG_IS_ENABLED(CMD_STM32PROG) &&
|
|
dfu->data.virt.dev_num >= STM32PROG_VIRT_FIRST_DEV_NUM)
|
|
return stm32prog_read_medium_virt(dfu, offset, buf, len);
|
|
|
|
*len = 0;
|
|
return 0;
|
|
}
|
|
|
|
int dfu_write_medium_virt(struct dfu_entity *dfu, u64 offset,
|
|
void *buf, long *len)
|
|
{
|
|
if (CONFIG_IS_ENABLED(CMD_STM32PROG) &&
|
|
dfu->data.virt.dev_num >= STM32PROG_VIRT_FIRST_DEV_NUM)
|
|
return stm32prog_write_medium_virt(dfu, offset, buf, len);
|
|
|
|
return -EOPNOTSUPP;
|
|
}
|
|
|
|
int __weak dfu_get_medium_size_virt(struct dfu_entity *dfu, u64 *size)
|
|
{
|
|
if (CONFIG_IS_ENABLED(CMD_STM32PROG) &&
|
|
dfu->data.virt.dev_num >= STM32PROG_VIRT_FIRST_DEV_NUM)
|
|
return stm32prog_get_medium_size_virt(dfu, size);
|
|
|
|
*size = SZ_1K;
|
|
|
|
return 0;
|
|
}
|
|
|
|
#endif
|