uboot/board/st/common/stm32mp_dfu.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
   2/*
   3 * Copyright (C) 2020, STMicroelectronics - All Rights Reserved
   4 */
   5
   6#include <common.h>
   7#include <blk.h>
   8#include <dm.h>
   9#include <dfu.h>
  10#include <env.h>
  11#include <memalign.h>
  12#include <misc.h>
  13#include <mtd.h>
  14#include <mtd_node.h>
  15#include <asm/arch/stm32prog.h>
  16
  17#define DFU_ALT_BUF_LEN SZ_1K
  18
  19static void board_get_alt_info_mmc(struct udevice *dev, char *buf)
  20{
  21        struct disk_partition info;
  22        int p, len, devnum;
  23        bool first = true;
  24        const char *name;
  25        struct mmc *mmc;
  26        struct blk_desc *desc;
  27
  28        mmc = mmc_get_mmc_dev(dev);
  29        if (!mmc)
  30                return;
  31
  32        if (mmc_init(mmc))
  33                return;
  34
  35        desc = mmc_get_blk_desc(mmc);
  36        if (!desc)
  37                return;
  38
  39        name = blk_get_if_type_name(desc->if_type);
  40        devnum = desc->devnum;
  41        len = strlen(buf);
  42
  43        if (buf[0] != '\0')
  44                len += snprintf(buf + len,
  45                                DFU_ALT_BUF_LEN - len, "&");
  46        len += snprintf(buf + len, DFU_ALT_BUF_LEN - len,
  47                         "%s %d=", name, devnum);
  48
  49        if (IS_MMC(mmc) && mmc->capacity_boot) {
  50                len += snprintf(buf + len, DFU_ALT_BUF_LEN - len,
  51                                "%s%d_boot1 raw 0x0 0x%llx mmcpart 1;",
  52                                name, devnum, mmc->capacity_boot);
  53                len += snprintf(buf + len, DFU_ALT_BUF_LEN - len,
  54                                "%s%d_boot2 raw 0x0 0x%llx mmcpart 2",
  55                                name, devnum, mmc->capacity_boot);
  56                first = false;
  57        }
  58
  59        for (p = 1; p < MAX_SEARCH_PARTITIONS; p++) {
  60                if (part_get_info(desc, p, &info))
  61                        continue;
  62                if (!first)
  63                        len += snprintf(buf + len, DFU_ALT_BUF_LEN - len, ";");
  64                first = false;
  65                len += snprintf(buf + len, DFU_ALT_BUF_LEN - len,
  66                                "%s%d_%s part %d %d",
  67                                name, devnum, info.name, devnum, p);
  68        }
  69}
  70
  71static void board_get_alt_info_mtd(struct mtd_info *mtd, char *buf)
  72{
  73        struct mtd_info *part;
  74        bool first = true;
  75        const char *name;
  76        int len, partnum = 0;
  77
  78        name = mtd->name;
  79        len = strlen(buf);
  80
  81        if (buf[0] != '\0')
  82                len += snprintf(buf + len, DFU_ALT_BUF_LEN - len, "&");
  83        len += snprintf(buf + len, DFU_ALT_BUF_LEN - len,
  84                        "mtd %s=", name);
  85
  86        len += snprintf(buf + len, DFU_ALT_BUF_LEN - len,
  87                        "%s raw 0x0 0x%llx ",
  88                        name, mtd->size);
  89
  90        list_for_each_entry(part, &mtd->partitions, node) {
  91                partnum++;
  92                if (!first)
  93                        len += snprintf(buf + len, DFU_ALT_BUF_LEN - len, ";");
  94                first = false;
  95
  96                len += snprintf(buf + len, DFU_ALT_BUF_LEN - len,
  97                                "%s_%s part %d",
  98                                name, part->name, partnum);
  99        }
 100}
 101
 102void set_dfu_alt_info(char *interface, char *devstr)
 103{
 104        struct udevice *dev;
 105        struct mtd_info *mtd;
 106
 107        ALLOC_CACHE_ALIGN_BUFFER(char, buf, DFU_ALT_BUF_LEN);
 108
 109        if (env_get("dfu_alt_info"))
 110                return;
 111
 112        memset(buf, 0, sizeof(buf));
 113
 114        snprintf(buf, DFU_ALT_BUF_LEN,
 115                 "ram 0=%s", CONFIG_DFU_ALT_RAM0);
 116
 117        if (CONFIG_IS_ENABLED(MMC)) {
 118                if (!uclass_get_device(UCLASS_MMC, 0, &dev))
 119                        board_get_alt_info_mmc(dev, buf);
 120
 121                if (!uclass_get_device(UCLASS_MMC, 1, &dev))
 122                        board_get_alt_info_mmc(dev, buf);
 123        }
 124
 125        if (CONFIG_IS_ENABLED(MTD)) {
 126                /* probe all MTD devices */
 127                mtd_probe_devices();
 128
 129                /* probe SPI flash device on a bus */
 130                if (!uclass_get_device(UCLASS_SPI_FLASH, 0, &dev)) {
 131                        mtd = get_mtd_device_nm("nor0");
 132                        if (!IS_ERR_OR_NULL(mtd))
 133                                board_get_alt_info_mtd(mtd, buf);
 134                }
 135
 136                mtd = get_mtd_device_nm("nand0");
 137                if (!IS_ERR_OR_NULL(mtd))
 138                        board_get_alt_info_mtd(mtd, buf);
 139
 140                mtd = get_mtd_device_nm("spi-nand0");
 141                if (!IS_ERR_OR_NULL(mtd))
 142                        board_get_alt_info_mtd(mtd, buf);
 143        }
 144
 145        if (IS_ENABLED(CONFIG_DFU_VIRT)) {
 146                strncat(buf, "&virt 0=OTP", DFU_ALT_BUF_LEN);
 147
 148                if (IS_ENABLED(CONFIG_PMIC_STPMIC1))
 149                        strncat(buf, "&virt 1=PMIC", DFU_ALT_BUF_LEN);
 150        }
 151
 152        env_set("dfu_alt_info", buf);
 153        puts("DFU alt info setting: done\n");
 154}
 155
 156#if CONFIG_IS_ENABLED(DFU_VIRT)
 157#include <dfu.h>
 158#include <power/stpmic1.h>
 159
 160static int dfu_otp_read(u64 offset, u8 *buffer, long *size)
 161{
 162        struct udevice *dev;
 163        int ret;
 164
 165        ret = uclass_get_device_by_driver(UCLASS_MISC,
 166                                          DM_GET_DRIVER(stm32mp_bsec),
 167                                          &dev);
 168        if (ret)
 169                return ret;
 170
 171        ret = misc_read(dev, offset + STM32_BSEC_OTP_OFFSET, buffer, *size);
 172        if (ret >= 0) {
 173                *size = ret;
 174                ret = 0;
 175        }
 176
 177        return 0;
 178}
 179
 180static int dfu_pmic_read(u64 offset, u8 *buffer, long *size)
 181{
 182        int ret;
 183#ifdef CONFIG_PMIC_STPMIC1
 184        struct udevice *dev;
 185
 186        ret = uclass_get_device_by_driver(UCLASS_MISC,
 187                                          DM_GET_DRIVER(stpmic1_nvm),
 188                                          &dev);
 189        if (ret)
 190                return ret;
 191
 192        ret = misc_read(dev, 0xF8 + offset, buffer, *size);
 193        if (ret >= 0) {
 194                *size = ret;
 195                ret = 0;
 196        }
 197        if (ret == -EACCES) {
 198                *size = 0;
 199                ret = 0;
 200        }
 201#else
 202        pr_err("PMIC update not supported");
 203        ret = -EOPNOTSUPP;
 204#endif
 205
 206        return ret;
 207}
 208
 209int dfu_read_medium_virt(struct dfu_entity *dfu, u64 offset,
 210                         void *buf, long *len)
 211{
 212        switch (dfu->data.virt.dev_num) {
 213        case 0x0:
 214                return dfu_otp_read(offset, buf, len);
 215        case 0x1:
 216                return dfu_pmic_read(offset, buf, len);
 217        }
 218
 219        if (CONFIG_IS_ENABLED(CMD_STM32PROG) &&
 220            dfu->data.virt.dev_num >= STM32PROG_VIRT_FIRST_DEV_NUM)
 221                return stm32prog_read_medium_virt(dfu, offset, buf, len);
 222
 223        *len = 0;
 224        return 0;
 225}
 226
 227int dfu_write_medium_virt(struct dfu_entity *dfu, u64 offset,
 228                          void *buf, long *len)
 229{
 230        if (CONFIG_IS_ENABLED(CMD_STM32PROG) &&
 231            dfu->data.virt.dev_num >= STM32PROG_VIRT_FIRST_DEV_NUM)
 232                return stm32prog_write_medium_virt(dfu, offset, buf, len);
 233
 234        return -EOPNOTSUPP;
 235}
 236
 237int __weak dfu_get_medium_size_virt(struct dfu_entity *dfu, u64 *size)
 238{
 239        if (CONFIG_IS_ENABLED(CMD_STM32PROG) &&
 240            dfu->data.virt.dev_num >= STM32PROG_VIRT_FIRST_DEV_NUM)
 241                return stm32prog_get_medium_size_virt(dfu, size);
 242
 243        *size = SZ_1K;
 244
 245        return 0;
 246}
 247
 248#endif
 249