u-boot/cmd/pwm.c
Tom Rini da7991b38e cmd: pwm: Rework argc sanity checking
Currently, we check argc in a number of places to make sure that we have
all of the required arguments for each of the pwm sub-commands.
However, there's at least one place where we've got dead code as we'll
never have argc == 0, due to checking that argc was at least 4 earlier
and having only subtracted 3.  Rework things so that when we have
determined our subcommand make sure we have the right number of
arguments for it, or error out.  This means we can stop checking against
argc again later.

Reported-by: Coverity (CID: 316601)
Cc: Pragnesh Patel <pragnesh.patel@sifive.com>
Signed-off-by: Tom Rini <trini@konsulko.com>
2021-02-24 16:51:48 -05:00

115 lines
2.4 KiB
C

// SPDX-License-Identifier: GPL-2.0+
/*
* Control PWM channels
*
* Copyright (c) 2020 SiFive, Inc
* author: Pragnesh Patel <pragnesh.patel@sifive.com>
*/
#include <command.h>
#include <dm.h>
#include <pwm.h>
enum pwm_cmd {
PWM_SET_INVERT,
PWM_SET_CONFIG,
PWM_SET_ENABLE,
PWM_SET_DISABLE,
};
static int do_pwm(struct cmd_tbl *cmdtp, int flag, int argc,
char *const argv[])
{
const char *str_cmd, *str_channel = NULL, *str_enable = NULL;
const char *str_pwm = NULL, *str_period = NULL, *str_duty = NULL;
enum pwm_cmd sub_cmd;
struct udevice *dev;
u32 channel, pwm_enable, pwm_dev, period_ns = 0, duty_ns = 0;
int ret;
if (argc < 4)
return CMD_RET_USAGE;
str_cmd = argv[1];
argc -= 2;
argv += 2;
str_pwm = *argv;
argc--;
argv++;
if (!str_pwm)
return CMD_RET_USAGE;
switch (*str_cmd) {
case 'i':
sub_cmd = PWM_SET_INVERT;
if (argc != 2)
return CMD_RET_USAGE;
break;
case 'c':
sub_cmd = PWM_SET_CONFIG;
if (argc != 3)
return CMD_RET_USAGE;
break;
case 'e':
sub_cmd = PWM_SET_ENABLE;
if (argc != 1)
return CMD_RET_USAGE;
break;
case 'd':
sub_cmd = PWM_SET_DISABLE;
if (argc != 1)
return CMD_RET_USAGE;
break;
default:
return CMD_RET_USAGE;
}
pwm_dev = simple_strtoul(str_pwm, NULL, 10);
ret = uclass_get_device(UCLASS_PWM, pwm_dev, &dev);
if (ret) {
printf("pwm: '%s' not found\n", str_pwm);
return cmd_process_error(cmdtp, ret);
}
str_channel = *argv;
channel = simple_strtoul(str_channel, NULL, 10);
argc--;
argv++;
if (sub_cmd == PWM_SET_INVERT) {
str_enable = *argv;
pwm_enable = simple_strtoul(str_enable, NULL, 10);
ret = pwm_set_invert(dev, channel, pwm_enable);
} else if (sub_cmd == PWM_SET_CONFIG) {
str_period = *argv;
argc--;
argv++;
period_ns = simple_strtoul(str_period, NULL, 10);
str_duty = *argv;
duty_ns = simple_strtoul(str_duty, NULL, 10);
ret = pwm_set_config(dev, channel, period_ns, duty_ns);
} else if (sub_cmd == PWM_SET_ENABLE) {
ret = pwm_set_enable(dev, channel, 1);
} else if (sub_cmd == PWM_SET_DISABLE) {
ret = pwm_set_enable(dev, channel, 0);
}
if (ret) {
printf("error(%d)\n", ret);
return CMD_RET_FAILURE;
}
return CMD_RET_SUCCESS;
}
U_BOOT_CMD(pwm, 6, 0, do_pwm,
"control pwm channels",
"pwm <invert> <pwm_dev_num> <channel> <polarity>\n"
"pwm <config> <pwm_dev_num> <channel> <period_ns> <duty_ns>\n"
"pwm <enable/disable> <pwm_dev_num> <channel>\n"
"Note: All input values are in decimal");