cmd: Add a pwm command
[pandora-u-boot.git] / cmd / pwm.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Control PWM channels
4  *
5  * Copyright (c) 2020 SiFive, Inc
6  * author: Pragnesh Patel <pragnesh.patel@sifive.com>
7  */
8
9 #include <command.h>
10 #include <dm.h>
11 #include <pwm.h>
12
13 enum pwm_cmd {
14         PWM_SET_INVERT,
15         PWM_SET_CONFIG,
16         PWM_SET_ENABLE,
17         PWM_SET_DISABLE,
18 };
19
20 static int do_pwm(struct cmd_tbl *cmdtp, int flag, int argc,
21                   char *const argv[])
22 {
23         const char *str_cmd, *str_channel = NULL, *str_enable = NULL;
24         const char *str_pwm = NULL, *str_period = NULL, *str_duty = NULL;
25         enum pwm_cmd sub_cmd;
26         struct udevice *dev;
27         u32 channel, pwm_enable, pwm_dev, period_ns = 0, duty_ns = 0;
28         int ret;
29
30         if (argc < 4)
31                 return CMD_RET_USAGE;
32
33         str_cmd = argv[1];
34         argc -= 2;
35         argv += 2;
36
37         if (argc > 0) {
38                 str_pwm = *argv;
39                 argc--;
40                 argv++;
41         }
42
43         if (!str_pwm)
44                 return CMD_RET_USAGE;
45
46         switch (*str_cmd) {
47         case 'i':
48                 sub_cmd = PWM_SET_INVERT;
49                 break;
50         case 'c':
51                 sub_cmd = PWM_SET_CONFIG;
52                 break;
53         case 'e':
54                 sub_cmd = PWM_SET_ENABLE;
55                 break;
56         case 'd':
57                 sub_cmd = PWM_SET_DISABLE;
58                 break;
59         default:
60                 return CMD_RET_USAGE;
61         }
62
63         pwm_dev = simple_strtoul(str_pwm, NULL, 10);
64         ret = uclass_get_device(UCLASS_PWM, pwm_dev, &dev);
65         if (ret) {
66                 printf("pwm: '%s' not found\n", str_pwm);
67                 return cmd_process_error(cmdtp, ret);
68         }
69
70         if (argc > 0) {
71                 str_channel = *argv;
72                 channel = simple_strtoul(str_channel, NULL, 10);
73                 argc--;
74                 argv++;
75         } else {
76                 return CMD_RET_USAGE;
77         }
78
79         if (sub_cmd == PWM_SET_INVERT && argc > 0) {
80                 str_enable = *argv;
81                 pwm_enable = simple_strtoul(str_enable, NULL, 10);
82                 ret = pwm_set_invert(dev, channel, pwm_enable);
83         } else if (sub_cmd == PWM_SET_CONFIG && argc == 2) {
84                 str_period = *argv;
85                 argc--;
86                 argv++;
87                 period_ns = simple_strtoul(str_period, NULL, 10);
88
89                 if (argc > 0) {
90                         str_duty = *argv;
91                         duty_ns = simple_strtoul(str_duty, NULL, 10);
92                 }
93
94                 ret = pwm_set_config(dev, channel, period_ns, duty_ns);
95         } else if (sub_cmd == PWM_SET_ENABLE) {
96                 ret = pwm_set_enable(dev, channel, 1);
97         } else if (sub_cmd == PWM_SET_DISABLE) {
98                 ret = pwm_set_enable(dev, channel, 0);
99         } else {
100                 printf("PWM arguments missing\n");
101                 return CMD_RET_FAILURE;
102         }
103
104         if (ret) {
105                 printf("error(%d)\n", ret);
106                 return CMD_RET_FAILURE;
107         }
108
109         return CMD_RET_SUCCESS;
110 }
111
112 U_BOOT_CMD(pwm, 6, 0, do_pwm,
113            "control pwm channels",
114            "pwm <invert> <pwm_dev_num> <channel> <polarity>\n"
115            "pwm <config> <pwm_dev_num> <channel> <period_ns> <duty_ns>\n"
116            "pwm <enable/disable> <pwm_dev_num> <channel>\n"
117            "Note: All input values are in decimal");