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                        mtd = get_mtd_device_nm("nor1");
 137                        if (!IS_ERR_OR_NULL(mtd))
 138                                board_get_alt_info_mtd(mtd, buf);
 139                }
 140
 141                mtd = get_mtd_device_nm("nand0");
 142                if (!IS_ERR_OR_NULL(mtd))
 143                        board_get_alt_info_mtd(mtd, buf);
 144
 145                mtd = get_mtd_device_nm("spi-nand0");
 146                if (!IS_ERR_OR_NULL(mtd))
 147                        board_get_alt_info_mtd(mtd, buf);
 148        }
 149
 150        if (IS_ENABLED(CONFIG_DFU_VIRT) &&
 151            IS_ENABLED(CMD_STM32PROG_USB)) {
 152                strncat(buf, "&virt 0=OTP", DFU_ALT_BUF_LEN);
 153
 154                if (IS_ENABLED(CONFIG_PMIC_STPMIC1))
 155                        strncat(buf, "&virt 1=PMIC", DFU_ALT_BUF_LEN);
 156        }
 157
 158        env_set("dfu_alt_info", buf);
 159        puts("DFU alt info setting: done\n");
 160}
 161
 162#if CONFIG_IS_ENABLED(DFU_VIRT)
 163#include <dfu.h>
 164#include <power/stpmic1.h>
 165
 166static int dfu_otp_read(u64 offset, u8 *buffer, long *size)
 167{
 168        struct udevice *dev;
 169        int ret;
 170
 171        ret = uclass_get_device_by_driver(UCLASS_MISC,
 172                                          DM_DRIVER_GET(stm32mp_bsec),
 173                                          &dev);
 174        if (ret)
 175                return ret;
 176
 177        ret = misc_read(dev, offset + STM32_BSEC_OTP_OFFSET, buffer, *size);
 178        if (ret >= 0) {
 179                *size = ret;
 180                ret = 0;
 181        }
 182
 183        return 0;
 184}
 185
 186static int dfu_pmic_read(u64 offset, u8 *buffer, long *size)
 187{
 188        int ret;
 189#ifdef CONFIG_PMIC_STPMIC1
 190        struct udevice *dev;
 191
 192        ret = uclass_get_device_by_driver(UCLASS_MISC,
 193                                          DM_DRIVER_GET(stpmic1_nvm),
 194                                          &dev);
 195        if (ret)
 196                return ret;
 197
 198        ret = misc_read(dev, 0xF8 + offset, buffer, *size);
 199        if (ret >= 0) {
 200                *size = ret;
 201                ret = 0;
 202        }
 203        if (ret == -EACCES) {
 204                *size = 0;
 205                ret = 0;
 206        }
 207#else
 208        log_err("PMIC update not supported");
 209        ret = -EOPNOTSUPP;
 210#endif
 211
 212        return ret;
 213}
 214
 215int dfu_read_medium_virt(struct dfu_entity *dfu, u64 offset,
 216                         void *buf, long *len)
 217{
 218        switch (dfu->data.virt.dev_num) {
 219        case 0x0:
 220                return dfu_otp_read(offset, buf, len);
 221        case 0x1:
 222                return dfu_pmic_read(offset, buf, len);
 223        }
 224
 225        if (IS_ENABLED(CONFIG_CMD_STM32PROG_USB) &&
 226            dfu->data.virt.dev_num >= STM32PROG_VIRT_FIRST_DEV_NUM)
 227                return stm32prog_read_medium_virt(dfu, offset, buf, len);
 228
 229        *len = 0;
 230        return 0;
 231}
 232
 233int dfu_write_medium_virt(struct dfu_entity *dfu, u64 offset,
 234                          void *buf, long *len)
 235{
 236        if (IS_ENABLED(CONFIG_CMD_STM32PROG_USB) &&
 237            dfu->data.virt.dev_num >= STM32PROG_VIRT_FIRST_DEV_NUM)
 238                return stm32prog_write_medium_virt(dfu, offset, buf, len);
 239
 240        return -EOPNOTSUPP;
 241}
 242
 243int __weak dfu_get_medium_size_virt(struct dfu_entity *dfu, u64 *size)
 244{
 245        if (IS_ENABLED(CONFIG_CMD_STM32PROG_USB) &&
 246            dfu->data.virt.dev_num >= STM32PROG_VIRT_FIRST_DEV_NUM)
 247                return stm32prog_get_medium_size_virt(dfu, size);
 248
 249        *size = SZ_1K;
 250
 251        return 0;
 252}
 253
 254#endif
 255