From 80d4c02b9324e7e0049582142474c9cc8630e27c Mon Sep 17 00:00:00 2001 From: Peter Cai Date: Wed, 2 Feb 2022 13:04:04 -0500 Subject: button: adc: set state to pressed when the voltage is closest to nominal In the Linux implementation of adc-keys (drivers/input/keyboard/adc-keys.c), `press-threshold-microvolt` is not really interpreted as a threshold, but rather as the "nominal voltage" of the button. When the voltage read from the ADC is closest to a button's `press-threshold-microvolt`, the button is considered pressed. This patch reconciles the behavior of button-adc with Linux's adc-keys such that device trees can be synchronized with minimal modifications. Signed-off-by: Peter Cai --- drivers/button/button-adc.c | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/button/button-adc.c b/drivers/button/button-adc.c index fd896c76f9d..9c24c960e6f 100644 --- a/drivers/button/button-adc.c +++ b/drivers/button/button-adc.c @@ -55,7 +55,7 @@ static int button_adc_of_to_plat(struct udevice *dev) struct button_uc_plat *uc_plat = dev_get_uclass_plat(dev); struct button_adc_priv *priv = dev_get_priv(dev); struct ofnode_phandle_args args; - u32 threshold, up_threshold, t; + u32 down_threshold = 0, up_threshold, voltage, t; ofnode node; int ret; @@ -78,7 +78,7 @@ static int button_adc_of_to_plat(struct udevice *dev) return ret; ret = ofnode_read_u32(dev_ofnode(dev), "press-threshold-microvolt", - &threshold); + &voltage); if (ret) return ret; @@ -87,13 +87,24 @@ static int button_adc_of_to_plat(struct udevice *dev) if (ret) return ret; - if (t > threshold) + if (t > voltage && t < up_threshold) up_threshold = t; + else if (t < voltage && t > down_threshold) + down_threshold = t; } priv->channel = args.args[0]; - priv->min = threshold; - priv->max = up_threshold; + + /* + * Define the voltage range such that the button is only pressed + * when the voltage is closest to its own press-threshold-microvolt + */ + if (down_threshold == 0) + priv->min = 0; + else + priv->min = down_threshold + (voltage - down_threshold) / 2; + + priv->max = voltage + (up_threshold - voltage) / 2; return ret; } -- cgit v1.3.1 From d8ae90a8d47da2f22041bf9f6fd6d42a598f44ee Mon Sep 17 00:00:00 2001 From: Masami Hiramatsu Date: Mon, 31 Jan 2022 11:52:20 +0900 Subject: DFU: Do not copy the entity name over the buffer size Use strlcpy() instead of strcpy() to prevent copying the entity name over the name buffer size. Signed-off-by: Masami Hiramatsu --- drivers/dfu/dfu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/dfu/dfu.c b/drivers/dfu/dfu.c index af3975925a9..66c41b5e762 100644 --- a/drivers/dfu/dfu.c +++ b/drivers/dfu/dfu.c @@ -503,7 +503,7 @@ static int dfu_fill_entity(struct dfu_entity *dfu, char *s, int alt, debug("%s: %s interface: %s dev: %s\n", __func__, s, interface, devstr); st = strsep(&s, " "); - strcpy(dfu->name, st); + strlcpy(dfu->name, st, DFU_NAME_SIZE); dfu->alt = alt; dfu->max_buf_size = 0; -- cgit v1.3.1 From 8db74c153b4e30edc5290da6c7330c63558678d0 Mon Sep 17 00:00:00 2001 From: Masami Hiramatsu Date: Mon, 31 Jan 2022 11:52:29 +0900 Subject: DFU: Accept redundant spaces and tabs in dfu_alt_info If dfu_alt_info has repeated spaces or tab (for indentation or readability), the dfu fails to parse it. For example, if dfu_alt_info="mtd nor1=image raw 100000 200000" (double spaces after "raw"), the image entity start address is '0' and the size '0x100000'. This is because the repeated space is not skipped. Use space and tab as a separater and apply skip_spaces() to skip redundant spaces and tabs. Signed-off-by: Masami Hiramatsu --- drivers/dfu/dfu.c | 6 ++++-- drivers/dfu/dfu_mmc.c | 11 ++++++++--- drivers/dfu/dfu_mtd.c | 8 ++++++-- drivers/dfu/dfu_nand.c | 11 ++++++++--- drivers/dfu/dfu_ram.c | 3 ++- drivers/dfu/dfu_sf.c | 12 +++++++++--- 6 files changed, 37 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/dfu/dfu.c b/drivers/dfu/dfu.c index 66c41b5e762..18154774f9a 100644 --- a/drivers/dfu/dfu.c +++ b/drivers/dfu/dfu.c @@ -123,9 +123,10 @@ int dfu_config_interfaces(char *env) s = env; while (s) { ret = -EINVAL; - i = strsep(&s, " "); + i = strsep(&s, " \t"); if (!i) break; + s = skip_spaces(s); d = strsep(&s, "="); if (!d) break; @@ -502,8 +503,9 @@ static int dfu_fill_entity(struct dfu_entity *dfu, char *s, int alt, char *st; debug("%s: %s interface: %s dev: %s\n", __func__, s, interface, devstr); - st = strsep(&s, " "); + st = strsep(&s, " \t"); strlcpy(dfu->name, st, DFU_NAME_SIZE); + s = skip_spaces(s); dfu->alt = alt; dfu->max_buf_size = 0; diff --git a/drivers/dfu/dfu_mmc.c b/drivers/dfu/dfu_mmc.c index 3dab5a5f633..d747ede66c4 100644 --- a/drivers/dfu/dfu_mmc.c +++ b/drivers/dfu/dfu_mmc.c @@ -351,11 +351,12 @@ int dfu_fill_entity_mmc(struct dfu_entity *dfu, char *devstr, char *s) dfu->data.mmc.dev_num = dectoul(devstr, NULL); for (; parg < argv + sizeof(argv) / sizeof(*argv); ++parg) { - *parg = strsep(&s, " "); + *parg = strsep(&s, " \t"); if (*parg == NULL) { pr_err("Invalid number of arguments.\n"); return -ENODEV; } + s = skip_spaces(s); } entity_type = argv[0]; @@ -390,9 +391,11 @@ int dfu_fill_entity_mmc(struct dfu_entity *dfu, char *devstr, char *s) * specifying the mmc HW defined partition number */ if (s) - if (!strcmp(strsep(&s, " "), "mmcpart")) + if (!strcmp(strsep(&s, " \t"), "mmcpart")) { + s = skip_spaces(s); dfu->data.mmc.hw_partition = simple_strtoul(s, NULL, 0); + } } else if (!strcmp(entity_type, "part")) { struct disk_partition partinfo; @@ -412,8 +415,10 @@ int dfu_fill_entity_mmc(struct dfu_entity *dfu, char *devstr, char *s) * specifying the mmc HW defined partition number */ if (s) - if (!strcmp(strsep(&s, " "), "offset")) + if (!strcmp(strsep(&s, " \t"), "offset")) { + s = skip_spaces(s); offset = simple_strtoul(s, NULL, 0); + } dfu->layout = DFU_RAW_ADDR; dfu->data.mmc.lba_start = partinfo.start + offset; diff --git a/drivers/dfu/dfu_mtd.c b/drivers/dfu/dfu_mtd.c index cce9ce0845e..27c011f5379 100644 --- a/drivers/dfu/dfu_mtd.c +++ b/drivers/dfu/dfu_mtd.c @@ -12,6 +12,7 @@ #include #include #include +#include static bool mtd_is_aligned_with_block_size(struct mtd_info *mtd, u64 size) { @@ -285,11 +286,14 @@ int dfu_fill_entity_mtd(struct dfu_entity *dfu, char *devstr, char *s) dfu->data.mtd.info = mtd; dfu->max_buf_size = mtd->erasesize; - st = strsep(&s, " "); + st = strsep(&s, " \t"); + s = skip_spaces(s); if (!strcmp(st, "raw")) { dfu->layout = DFU_RAW_ADDR; dfu->data.mtd.start = hextoul(s, &s); - s++; + if (!isspace(*s)) + return -1; + s = skip_spaces(s); dfu->data.mtd.size = hextoul(s, &s); } else if ((!strcmp(st, "part")) || (!strcmp(st, "partubi"))) { char mtd_id[32]; diff --git a/drivers/dfu/dfu_nand.c b/drivers/dfu/dfu_nand.c index e53b35e42b8..76761939ab5 100644 --- a/drivers/dfu/dfu_nand.c +++ b/drivers/dfu/dfu_nand.c @@ -201,11 +201,14 @@ int dfu_fill_entity_nand(struct dfu_entity *dfu, char *devstr, char *s) dfu->data.nand.ubi = 0; dfu->dev_type = DFU_DEV_NAND; - st = strsep(&s, " "); + st = strsep(&s, " \t"); + s = skip_spaces(s); if (!strcmp(st, "raw")) { dfu->layout = DFU_RAW_ADDR; dfu->data.nand.start = hextoul(s, &s); - s++; + if (!isspace(*s)) + return -1; + s = skip_spaces(s); dfu->data.nand.size = hextoul(s, &s); } else if ((!strcmp(st, "part")) || (!strcmp(st, "partubi"))) { char mtd_id[32]; @@ -216,7 +219,9 @@ int dfu_fill_entity_nand(struct dfu_entity *dfu, char *devstr, char *s) dfu->layout = DFU_RAW_ADDR; dev = dectoul(s, &s); - s++; + if (!isspace(*s)) + return -1; + s = skip_spaces(s); part = dectoul(s, &s); sprintf(mtd_id, "%s%d,%d", "nand", dev, part - 1); diff --git a/drivers/dfu/dfu_ram.c b/drivers/dfu/dfu_ram.c index cc7e45ba335..361a3ff8af8 100644 --- a/drivers/dfu/dfu_ram.c +++ b/drivers/dfu/dfu_ram.c @@ -60,11 +60,12 @@ int dfu_fill_entity_ram(struct dfu_entity *dfu, char *devstr, char *s) const char **parg = argv; for (; parg < argv + sizeof(argv) / sizeof(*argv); ++parg) { - *parg = strsep(&s, " "); + *parg = strsep(&s, " \t"); if (*parg == NULL) { pr_err("Invalid number of arguments.\n"); return -ENODEV; } + s = skip_spaces(s); } dfu->dev_type = DFU_DEV_RAM; diff --git a/drivers/dfu/dfu_sf.c b/drivers/dfu/dfu_sf.c index b72493ced86..993e951bc3b 100644 --- a/drivers/dfu/dfu_sf.c +++ b/drivers/dfu/dfu_sf.c @@ -13,6 +13,7 @@ #include #include #include +#include static int dfu_get_medium_size_sf(struct dfu_entity *dfu, u64 *size) { @@ -178,11 +179,14 @@ int dfu_fill_entity_sf(struct dfu_entity *dfu, char *devstr, char *s) dfu->dev_type = DFU_DEV_SF; dfu->max_buf_size = dfu->data.sf.dev->sector_size; - st = strsep(&s, " "); + st = strsep(&s, " \t"); + s = skip_spaces(s); if (!strcmp(st, "raw")) { dfu->layout = DFU_RAW_ADDR; dfu->data.sf.start = hextoul(s, &s); - s++; + if (!isspace(*s)) + return -1; + s = skip_spaces(s); dfu->data.sf.size = hextoul(s, &s); } else if (CONFIG_IS_ENABLED(DFU_SF_PART) && (!strcmp(st, "part") || !strcmp(st, "partubi"))) { @@ -195,7 +199,9 @@ int dfu_fill_entity_sf(struct dfu_entity *dfu, char *devstr, char *s) dfu->layout = DFU_RAW_ADDR; dev = dectoul(s, &s); - s++; + if (!isspace(*s)) + return -1; + s = skip_spaces(s); part = dectoul(s, &s); sprintf(mtd_id, "%s%d,%d", "nor", dev, part - 1); -- cgit v1.3.1 From 53b406369e9d0ba2da1df9b2488976c41acc6332 Mon Sep 17 00:00:00 2001 From: Masami Hiramatsu Date: Mon, 31 Jan 2022 11:52:37 +0900 Subject: DFU: Check the number of arguments and argument string strictly When parsing the dfu_alt_info, check the number of arguments and argument string strictly. If there is any garbage data (which is not able to be parsed correctly) in dfu_alt_info, that means something wrong and user may make a typo or mis- understanding about the syntax. Since the dfu_alt_info is used for updating the firmware, this mistake may lead to brick the hardware. Thus it should be checked strictly for making sure there is no mistake. Signed-off-by: Masami Hiramatsu --- drivers/dfu/dfu.c | 31 +++++++++++++++++++++------- drivers/dfu/dfu_mmc.c | 56 +++++++++++++++++++++++++++----------------------- drivers/dfu/dfu_mtd.c | 36 +++++++++++++++++++------------- drivers/dfu/dfu_nand.c | 39 +++++++++++++++++++---------------- drivers/dfu/dfu_ram.c | 25 +++++++++++----------- drivers/dfu/dfu_sf.c | 38 ++++++++++++++++++---------------- drivers/dfu/dfu_virt.c | 5 ++++- include/dfu.h | 33 ++++++++++++++++++----------- 8 files changed, 154 insertions(+), 109 deletions(-) (limited to 'drivers') diff --git a/drivers/dfu/dfu.c b/drivers/dfu/dfu.c index 18154774f9a..516dda61796 100644 --- a/drivers/dfu/dfu.c +++ b/drivers/dfu/dfu.c @@ -500,12 +500,29 @@ int dfu_read(struct dfu_entity *dfu, void *buf, int size, int blk_seq_num) static int dfu_fill_entity(struct dfu_entity *dfu, char *s, int alt, char *interface, char *devstr) { + char *argv[DFU_MAX_ENTITY_ARGS]; + int argc; char *st; debug("%s: %s interface: %s dev: %s\n", __func__, s, interface, devstr); st = strsep(&s, " \t"); strlcpy(dfu->name, st, DFU_NAME_SIZE); - s = skip_spaces(s); + + /* Parse arguments */ + for (argc = 0; s && argc < DFU_MAX_ENTITY_ARGS; argc++) { + s = skip_spaces(s); + if (!*s) + break; + argv[argc] = strsep(&s, " \t"); + } + + if (argc == DFU_MAX_ENTITY_ARGS && s) { + s = skip_spaces(s); + if (*s) { + log_err("Too many arguments for %s\n", dfu->name); + return -EINVAL; + } + } dfu->alt = alt; dfu->max_buf_size = 0; @@ -513,22 +530,22 @@ static int dfu_fill_entity(struct dfu_entity *dfu, char *s, int alt, /* Specific for mmc device */ if (strcmp(interface, "mmc") == 0) { - if (dfu_fill_entity_mmc(dfu, devstr, s)) + if (dfu_fill_entity_mmc(dfu, devstr, argv, argc)) return -1; } else if (strcmp(interface, "mtd") == 0) { - if (dfu_fill_entity_mtd(dfu, devstr, s)) + if (dfu_fill_entity_mtd(dfu, devstr, argv, argc)) return -1; } else if (strcmp(interface, "nand") == 0) { - if (dfu_fill_entity_nand(dfu, devstr, s)) + if (dfu_fill_entity_nand(dfu, devstr, argv, argc)) return -1; } else if (strcmp(interface, "ram") == 0) { - if (dfu_fill_entity_ram(dfu, devstr, s)) + if (dfu_fill_entity_ram(dfu, devstr, argv, argc)) return -1; } else if (strcmp(interface, "sf") == 0) { - if (dfu_fill_entity_sf(dfu, devstr, s)) + if (dfu_fill_entity_sf(dfu, devstr, argv, argc)) return -1; } else if (strcmp(interface, "virt") == 0) { - if (dfu_fill_entity_virt(dfu, devstr, s)) + if (dfu_fill_entity_virt(dfu, devstr, argv, argc)) return -1; } else { printf("%s: Device %s not (yet) supported!\n", diff --git a/drivers/dfu/dfu_mmc.c b/drivers/dfu/dfu_mmc.c index d747ede66c4..a91da972d46 100644 --- a/drivers/dfu/dfu_mmc.c +++ b/drivers/dfu/dfu_mmc.c @@ -337,35 +337,34 @@ void dfu_free_entity_mmc(struct dfu_entity *dfu) * 4th (optional): * mmcpart (access to HW eMMC partitions) */ -int dfu_fill_entity_mmc(struct dfu_entity *dfu, char *devstr, char *s) +int dfu_fill_entity_mmc(struct dfu_entity *dfu, char *devstr, char **argv, int argc) { const char *entity_type; ssize_t second_arg; size_t third_arg; - struct mmc *mmc; + char *s; - const char *argv[3]; - const char **parg = argv; - - dfu->data.mmc.dev_num = dectoul(devstr, NULL); - - for (; parg < argv + sizeof(argv) / sizeof(*argv); ++parg) { - *parg = strsep(&s, " \t"); - if (*parg == NULL) { - pr_err("Invalid number of arguments.\n"); - return -ENODEV; - } - s = skip_spaces(s); + if (argc < 3) { + pr_err("The number of parameters are not enough.\n"); + return -EINVAL; } + dfu->data.mmc.dev_num = dectoul(devstr, &s); + if (*s) + return -EINVAL; + entity_type = argv[0]; /* * Base 0 means we'll accept (prefixed with 0x or 0) base 16, 8, * with default 10. */ - second_arg = simple_strtol(argv[1], NULL, 0); - third_arg = simple_strtoul(argv[2], NULL, 0); + second_arg = simple_strtol(argv[1], &s, 0); + if (*s) + return -EINVAL; + third_arg = simple_strtoul(argv[2], &s, 0); + if (*s) + return -EINVAL; mmc = find_mmc_device(dfu->data.mmc.dev_num); if (mmc == NULL) { @@ -390,12 +389,14 @@ int dfu_fill_entity_mmc(struct dfu_entity *dfu, char *devstr, char *s) * Check for an extra entry at dfu_alt_info env variable * specifying the mmc HW defined partition number */ - if (s) - if (!strcmp(strsep(&s, " \t"), "mmcpart")) { - s = skip_spaces(s); - dfu->data.mmc.hw_partition = - simple_strtoul(s, NULL, 0); + if (argc > 3) { + if (argc != 5 || strcmp(argv[3], "mmcpart")) { + pr_err("DFU mmc raw accept 'mmcpart ' option.\n"); + return -EINVAL; } + dfu->data.mmc.hw_partition = + simple_strtoul(argv[4], NULL, 0); + } } else if (!strcmp(entity_type, "part")) { struct disk_partition partinfo; @@ -414,15 +415,18 @@ int dfu_fill_entity_mmc(struct dfu_entity *dfu, char *devstr, char *s) * Check for an extra entry at dfu_alt_info env variable * specifying the mmc HW defined partition number */ - if (s) - if (!strcmp(strsep(&s, " \t"), "offset")) { - s = skip_spaces(s); - offset = simple_strtoul(s, NULL, 0); + if (argc > 3) { + if (argc != 5 || strcmp(argv[3], "offset")) { + pr_err("DFU mmc raw accept 'mmcpart ' option.\n"); + return -EINVAL; } + dfu->data.mmc.hw_partition = + simple_strtoul(argv[4], NULL, 0); + } dfu->layout = DFU_RAW_ADDR; dfu->data.mmc.lba_start = partinfo.start + offset; - dfu->data.mmc.lba_size = partinfo.size-offset; + dfu->data.mmc.lba_size = partinfo.size - offset; dfu->data.mmc.lba_blk_size = partinfo.blksz; } else if (!strcmp(entity_type, "fat")) { dfu->layout = DFU_FS_FAT; diff --git a/drivers/dfu/dfu_mtd.c b/drivers/dfu/dfu_mtd.c index 27c011f5379..c7075f12eca 100644 --- a/drivers/dfu/dfu_mtd.c +++ b/drivers/dfu/dfu_mtd.c @@ -271,9 +271,9 @@ static unsigned int dfu_polltimeout_mtd(struct dfu_entity *dfu) return DFU_DEFAULT_POLL_TIMEOUT; } -int dfu_fill_entity_mtd(struct dfu_entity *dfu, char *devstr, char *s) +int dfu_fill_entity_mtd(struct dfu_entity *dfu, char *devstr, char **argv, int argc) { - char *st; + char *s; struct mtd_info *mtd; int ret, part; @@ -285,25 +285,33 @@ int dfu_fill_entity_mtd(struct dfu_entity *dfu, char *devstr, char *s) dfu->dev_type = DFU_DEV_MTD; dfu->data.mtd.info = mtd; dfu->max_buf_size = mtd->erasesize; + if (argc < 1) + return -EINVAL; - st = strsep(&s, " \t"); - s = skip_spaces(s); - if (!strcmp(st, "raw")) { + if (!strcmp(argv[0], "raw")) { + if (argc != 3) + return -EINVAL; dfu->layout = DFU_RAW_ADDR; - dfu->data.mtd.start = hextoul(s, &s); - if (!isspace(*s)) - return -1; - s = skip_spaces(s); - dfu->data.mtd.size = hextoul(s, &s); - } else if ((!strcmp(st, "part")) || (!strcmp(st, "partubi"))) { + dfu->data.mtd.start = hextoul(argv[1], &s); + if (*s) + return -EINVAL; + dfu->data.mtd.size = hextoul(argv[2], &s); + if (*s) + return -EINVAL; + } else if ((!strcmp(argv[0], "part")) || (!strcmp(argv[0], "partubi"))) { char mtd_id[32]; struct mtd_device *mtd_dev; u8 part_num; struct part_info *pi; + if (argc != 2) + return -EINVAL; + dfu->layout = DFU_RAW_ADDR; - part = dectoul(s, &s); + part = dectoul(argv[1], &s); + if (*s) + return -EINVAL; sprintf(mtd_id, "%s,%d", devstr, part - 1); printf("using id '%s'\n", mtd_id); @@ -318,10 +326,10 @@ int dfu_fill_entity_mtd(struct dfu_entity *dfu, char *devstr, char *s) dfu->data.mtd.start = pi->offset; dfu->data.mtd.size = pi->size; - if (!strcmp(st, "partubi")) + if (!strcmp(argv[0], "partubi")) dfu->data.mtd.ubi = 1; } else { - printf("%s: Memory layout (%s) not supported!\n", __func__, st); + printf("%s: Memory layout (%s) not supported!\n", __func__, argv[0]); return -1; } diff --git a/drivers/dfu/dfu_nand.c b/drivers/dfu/dfu_nand.c index 76761939ab5..08e8cf5cdb3 100644 --- a/drivers/dfu/dfu_nand.c +++ b/drivers/dfu/dfu_nand.c @@ -194,23 +194,25 @@ unsigned int dfu_polltimeout_nand(struct dfu_entity *dfu) return DFU_DEFAULT_POLL_TIMEOUT; } -int dfu_fill_entity_nand(struct dfu_entity *dfu, char *devstr, char *s) +int dfu_fill_entity_nand(struct dfu_entity *dfu, char *devstr, char **argv, int argc) { - char *st; + char *s; int ret, dev, part; dfu->data.nand.ubi = 0; dfu->dev_type = DFU_DEV_NAND; - st = strsep(&s, " \t"); - s = skip_spaces(s); - if (!strcmp(st, "raw")) { + if (argc != 3) + return -EINVAL; + + if (!strcmp(argv[0], "raw")) { dfu->layout = DFU_RAW_ADDR; - dfu->data.nand.start = hextoul(s, &s); - if (!isspace(*s)) - return -1; - s = skip_spaces(s); - dfu->data.nand.size = hextoul(s, &s); - } else if ((!strcmp(st, "part")) || (!strcmp(st, "partubi"))) { + dfu->data.nand.start = hextoul(argv[1], &s); + if (*s) + return -EINVAL; + dfu->data.nand.size = hextoul(argv[2], &s); + if (*s) + return -EINVAL; + } else if ((!strcmp(argv[0], "part")) || (!strcmp(argv[0], "partubi"))) { char mtd_id[32]; struct mtd_device *mtd_dev; u8 part_num; @@ -218,11 +220,12 @@ int dfu_fill_entity_nand(struct dfu_entity *dfu, char *devstr, char *s) dfu->layout = DFU_RAW_ADDR; - dev = dectoul(s, &s); - if (!isspace(*s)) - return -1; - s = skip_spaces(s); - part = dectoul(s, &s); + dev = dectoul(argv[1], &s); + if (*s) + return -EINVAL; + part = dectoul(argv[2], &s); + if (*s) + return -EINVAL; sprintf(mtd_id, "%s%d,%d", "nand", dev, part - 1); debug("using id '%s'\n", mtd_id); @@ -237,10 +240,10 @@ int dfu_fill_entity_nand(struct dfu_entity *dfu, char *devstr, char *s) dfu->data.nand.start = pi->offset; dfu->data.nand.size = pi->size; - if (!strcmp(st, "partubi")) + if (!strcmp(argv[0], "partubi")) dfu->data.nand.ubi = 1; } else { - printf("%s: Memory layout (%s) not supported!\n", __func__, st); + printf("%s: Memory layout (%s) not supported!\n", __func__, argv[0]); return -1; } diff --git a/drivers/dfu/dfu_ram.c b/drivers/dfu/dfu_ram.c index 361a3ff8af8..9d10303164e 100644 --- a/drivers/dfu/dfu_ram.c +++ b/drivers/dfu/dfu_ram.c @@ -54,18 +54,13 @@ static int dfu_read_medium_ram(struct dfu_entity *dfu, u64 offset, return dfu_transfer_medium_ram(DFU_OP_READ, dfu, offset, buf, len); } -int dfu_fill_entity_ram(struct dfu_entity *dfu, char *devstr, char *s) +int dfu_fill_entity_ram(struct dfu_entity *dfu, char *devstr, char **argv, int argc) { - const char *argv[3]; - const char **parg = argv; - - for (; parg < argv + sizeof(argv) / sizeof(*argv); ++parg) { - *parg = strsep(&s, " \t"); - if (*parg == NULL) { - pr_err("Invalid number of arguments.\n"); - return -ENODEV; - } - s = skip_spaces(s); + char *s; + + if (argc != 3) { + pr_err("Invalid number of arguments.\n"); + return -EINVAL; } dfu->dev_type = DFU_DEV_RAM; @@ -75,8 +70,12 @@ int dfu_fill_entity_ram(struct dfu_entity *dfu, char *devstr, char *s) } dfu->layout = DFU_RAM_ADDR; - dfu->data.ram.start = hextoul(argv[1], NULL); - dfu->data.ram.size = hextoul(argv[2], NULL); + dfu->data.ram.start = hextoul(argv[1], &s); + if (*s) + return -EINVAL; + dfu->data.ram.size = hextoul(argv[2], &s); + if (*s) + return -EINVAL; dfu->write_medium = dfu_write_medium_ram; dfu->get_medium_size = dfu_get_medium_size_ram; diff --git a/drivers/dfu/dfu_sf.c b/drivers/dfu/dfu_sf.c index 993e951bc3b..25a9c818503 100644 --- a/drivers/dfu/dfu_sf.c +++ b/drivers/dfu/dfu_sf.c @@ -166,9 +166,9 @@ static struct spi_flash *parse_dev(char *devstr) return dev; } -int dfu_fill_entity_sf(struct dfu_entity *dfu, char *devstr, char *s) +int dfu_fill_entity_sf(struct dfu_entity *dfu, char *devstr, char **argv, int argc) { - char *st; + char *s; char *devstr_bkup = strdup(devstr); dfu->data.sf.dev = parse_dev(devstr_bkup); @@ -179,17 +179,18 @@ int dfu_fill_entity_sf(struct dfu_entity *dfu, char *devstr, char *s) dfu->dev_type = DFU_DEV_SF; dfu->max_buf_size = dfu->data.sf.dev->sector_size; - st = strsep(&s, " \t"); - s = skip_spaces(s); - if (!strcmp(st, "raw")) { + if (argc != 3) + return -EINVAL; + if (!strcmp(argv[0], "raw")) { dfu->layout = DFU_RAW_ADDR; - dfu->data.sf.start = hextoul(s, &s); - if (!isspace(*s)) - return -1; - s = skip_spaces(s); - dfu->data.sf.size = hextoul(s, &s); + dfu->data.sf.start = hextoul(argv[1], &s); + if (*s) + return -EINVAL; + dfu->data.sf.size = hextoul(argv[2], &s); + if (*s) + return -EINVAL; } else if (CONFIG_IS_ENABLED(DFU_SF_PART) && - (!strcmp(st, "part") || !strcmp(st, "partubi"))) { + (!strcmp(argv[0], "part") || !strcmp(argv[0], "partubi"))) { char mtd_id[32]; struct mtd_device *mtd_dev; u8 part_num; @@ -198,11 +199,12 @@ int dfu_fill_entity_sf(struct dfu_entity *dfu, char *devstr, char *s) dfu->layout = DFU_RAW_ADDR; - dev = dectoul(s, &s); - if (!isspace(*s)) - return -1; - s = skip_spaces(s); - part = dectoul(s, &s); + dev = dectoul(argv[1], &s); + if (*s) + return -EINVAL; + part = dectoul(argv[2], &s); + if (*s) + return -EINVAL; sprintf(mtd_id, "%s%d,%d", "nor", dev, part - 1); printf("using id '%s'\n", mtd_id); @@ -216,10 +218,10 @@ int dfu_fill_entity_sf(struct dfu_entity *dfu, char *devstr, char *s) } dfu->data.sf.start = pi->offset; dfu->data.sf.size = pi->size; - if (!strcmp(st, "partubi")) + if (!strcmp(argv[0], "partubi")) dfu->data.sf.ubi = 1; } else { - printf("%s: Memory layout (%s) not supported!\n", __func__, st); + printf("%s: Memory layout (%s) not supported!\n", __func__, argv[0]); spi_flash_free(dfu->data.sf.dev); return -1; } diff --git a/drivers/dfu/dfu_virt.c b/drivers/dfu/dfu_virt.c index 80c99cb06e3..29f7a08f672 100644 --- a/drivers/dfu/dfu_virt.c +++ b/drivers/dfu/dfu_virt.c @@ -32,10 +32,13 @@ int __weak dfu_read_medium_virt(struct dfu_entity *dfu, u64 offset, return 0; } -int dfu_fill_entity_virt(struct dfu_entity *dfu, char *devstr, char *s) +int dfu_fill_entity_virt(struct dfu_entity *dfu, char *devstr, char **argv, int argc) { debug("%s: devstr = %s\n", __func__, devstr); + if (argc != 0) + return -EINVAL; + dfu->dev_type = DFU_DEV_VIRT; dfu->layout = DFU_RAW_ADDR; dfu->data.virt.dev_num = dectoul(devstr, NULL); diff --git a/include/dfu.h b/include/dfu.h index f6868982df7..dcb9cd9d799 100644 --- a/include/dfu.h +++ b/include/dfu.h @@ -432,11 +432,15 @@ static inline void dfu_set_defer_flush(struct dfu_entity *dfu) int dfu_write_from_mem_addr(struct dfu_entity *dfu, void *buf, int size); /* Device specific */ +/* Each entity has 5 arguments in maximum. */ +#define DFU_MAX_ENTITY_ARGS 5 + #if CONFIG_IS_ENABLED(DFU_MMC) -extern int dfu_fill_entity_mmc(struct dfu_entity *dfu, char *devstr, char *s); +extern int dfu_fill_entity_mmc(struct dfu_entity *dfu, char *devstr, + char **argv, int argc); #else static inline int dfu_fill_entity_mmc(struct dfu_entity *dfu, char *devstr, - char *s) + char **argv, int argc) { puts("MMC support not available!\n"); return -1; @@ -444,10 +448,11 @@ static inline int dfu_fill_entity_mmc(struct dfu_entity *dfu, char *devstr, #endif #if CONFIG_IS_ENABLED(DFU_NAND) -extern int dfu_fill_entity_nand(struct dfu_entity *dfu, char *devstr, char *s); +extern int dfu_fill_entity_nand(struct dfu_entity *dfu, char *devstr, + char **argv, int argc); #else static inline int dfu_fill_entity_nand(struct dfu_entity *dfu, char *devstr, - char *s) + char **argv, int argc) { puts("NAND support not available!\n"); return -1; @@ -455,10 +460,11 @@ static inline int dfu_fill_entity_nand(struct dfu_entity *dfu, char *devstr, #endif #if CONFIG_IS_ENABLED(DFU_RAM) -extern int dfu_fill_entity_ram(struct dfu_entity *dfu, char *devstr, char *s); +extern int dfu_fill_entity_ram(struct dfu_entity *dfu, char *devstr, + char **argv, int argc); #else static inline int dfu_fill_entity_ram(struct dfu_entity *dfu, char *devstr, - char *s) + char **argv, int argc) { puts("RAM support not available!\n"); return -1; @@ -466,10 +472,11 @@ static inline int dfu_fill_entity_ram(struct dfu_entity *dfu, char *devstr, #endif #if CONFIG_IS_ENABLED(DFU_SF) -extern int dfu_fill_entity_sf(struct dfu_entity *dfu, char *devstr, char *s); +extern int dfu_fill_entity_sf(struct dfu_entity *dfu, char *devstr, + char **argv, int argc); #else static inline int dfu_fill_entity_sf(struct dfu_entity *dfu, char *devstr, - char *s) + char **argv, int argc) { puts("SF support not available!\n"); return -1; @@ -477,10 +484,11 @@ static inline int dfu_fill_entity_sf(struct dfu_entity *dfu, char *devstr, #endif #if CONFIG_IS_ENABLED(DFU_MTD) -int dfu_fill_entity_mtd(struct dfu_entity *dfu, char *devstr, char *s); +extern int dfu_fill_entity_mtd(struct dfu_entity *dfu, char *devstr, + char **argv, int argc); #else static inline int dfu_fill_entity_mtd(struct dfu_entity *dfu, char *devstr, - char *s) + char **argv, int argc) { puts("MTD support not available!\n"); return -1; @@ -488,7 +496,8 @@ static inline int dfu_fill_entity_mtd(struct dfu_entity *dfu, char *devstr, #endif #ifdef CONFIG_DFU_VIRT -int dfu_fill_entity_virt(struct dfu_entity *dfu, char *devstr, char *s); +int dfu_fill_entity_virt(struct dfu_entity *dfu, char *devstr, + char **argv, int argc); int dfu_write_medium_virt(struct dfu_entity *dfu, u64 offset, void *buf, long *len); int dfu_get_medium_size_virt(struct dfu_entity *dfu, u64 *size); @@ -496,7 +505,7 @@ int dfu_read_medium_virt(struct dfu_entity *dfu, u64 offset, void *buf, long *len); #else static inline int dfu_fill_entity_virt(struct dfu_entity *dfu, char *devstr, - char *s) + char **argv, int argc) { puts("VIRT support not available!\n"); return -1; -- cgit v1.3.1 From 3970c82a60857b72afcb676697caf9c979dab946 Mon Sep 17 00:00:00 2001 From: Adam Ford Date: Sat, 29 Jan 2022 07:27:47 -0600 Subject: phy: nop-phy: Enable reset-gpios support Some usb-nop-xceiv devices use a gpio take them out of reset. Add a reset function to put them into that state. This is similar to how Linux handles the usb-nop-xceiv driver. Signed-off-by: Adam Ford --- drivers/phy/nop-phy.c | 45 ++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 42 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/phy/nop-phy.c b/drivers/phy/nop-phy.c index 9f12ebc0624..b08eedd4d42 100644 --- a/drivers/phy/nop-phy.c +++ b/drivers/phy/nop-phy.c @@ -10,25 +10,54 @@ #include #include #include +#include struct nop_phy_priv { struct clk_bulk bulk; +#if CONFIG_IS_ENABLED(DM_GPIO) + struct gpio_desc reset_gpio; +#endif }; +#if CONFIG_IS_ENABLED(DM_GPIO) +static int nop_phy_reset(struct phy *phy) +{ + struct nop_phy_priv *priv = dev_get_priv(phy->dev); + + /* Return if there is no gpio since it's optional */ + if (!dm_gpio_is_valid(&priv->reset_gpio)) + return 0; + + return dm_gpio_set_value(&priv->reset_gpio, false); +} +#endif + static int nop_phy_init(struct phy *phy) { struct nop_phy_priv *priv = dev_get_priv(phy->dev); + int ret = 0; - if (CONFIG_IS_ENABLED(CLK)) - return clk_enable_bulk(&priv->bulk); + if (CONFIG_IS_ENABLED(CLK)) { + ret = clk_enable_bulk(&priv->bulk); + if (ret) + return ret; + } +#if CONFIG_IS_ENABLED(DM_GPIO) + ret = nop_phy_reset(phy); + if (ret) { + if (CONFIG_IS_ENABLED(CLK)) + clk_disable_bulk(&priv->bulk); + return ret; + } +#endif return 0; } static int nop_phy_probe(struct udevice *dev) { struct nop_phy_priv *priv = dev_get_priv(dev); - int ret; + int ret = 0; if (CONFIG_IS_ENABLED(CLK)) { ret = clk_get_bulk(dev, &priv->bulk); @@ -37,6 +66,13 @@ static int nop_phy_probe(struct udevice *dev) return ret; } } +#if CONFIG_IS_ENABLED(DM_GPIO) + ret = gpio_request_by_name(dev, "reset-gpios", 0, + &priv->reset_gpio, + GPIOD_IS_OUT); +#endif + if (ret != -ENOENT) + return ret; return 0; } @@ -49,6 +85,9 @@ static const struct udevice_id nop_phy_ids[] = { static struct phy_ops nop_phy_ops = { .init = nop_phy_init, +#if CONFIG_IS_ENABLED(DM_GPIO) + .reset = nop_phy_reset, +#endif }; U_BOOT_DRIVER(nop_phy) = { -- cgit v1.3.1