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