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 
do_pwm(struct cmd_tbl * cmdtp,int flag,int argc,char * const argv[])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 	str_pwm = *argv;
38 	argc--;
39 	argv++;
40 
41 	if (!str_pwm)
42 		return CMD_RET_USAGE;
43 
44 	switch (*str_cmd) {
45 	case 'i':
46 		sub_cmd = PWM_SET_INVERT;
47 		if (argc != 2)
48 			return CMD_RET_USAGE;
49 		break;
50 	case 'c':
51 		sub_cmd = PWM_SET_CONFIG;
52 		if (argc != 3)
53 			return CMD_RET_USAGE;
54 		break;
55 	case 'e':
56 		sub_cmd = PWM_SET_ENABLE;
57 		if (argc != 1)
58 			return CMD_RET_USAGE;
59 		break;
60 	case 'd':
61 		sub_cmd = PWM_SET_DISABLE;
62 		if (argc != 1)
63 			return CMD_RET_USAGE;
64 		break;
65 	default:
66 		return CMD_RET_USAGE;
67 	}
68 
69 	pwm_dev = simple_strtoul(str_pwm, NULL, 10);
70 	ret = uclass_get_device(UCLASS_PWM, pwm_dev, &dev);
71 	if (ret) {
72 		printf("pwm: '%s' not found\n", str_pwm);
73 		return cmd_process_error(cmdtp, ret);
74 	}
75 
76 	str_channel = *argv;
77 	channel = simple_strtoul(str_channel, NULL, 10);
78 	argc--;
79 	argv++;
80 
81 	if (sub_cmd == PWM_SET_INVERT) {
82 		str_enable = *argv;
83 		pwm_enable = simple_strtoul(str_enable, NULL, 10);
84 		ret = pwm_set_invert(dev, channel, pwm_enable);
85 	} else if (sub_cmd == PWM_SET_CONFIG) {
86 		str_period = *argv;
87 		argc--;
88 		argv++;
89 		period_ns = simple_strtoul(str_period, NULL, 10);
90 
91 		str_duty = *argv;
92 		duty_ns = simple_strtoul(str_duty, NULL, 10);
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 	}
100 
101 	if (ret) {
102 		printf("error(%d)\n", ret);
103 		return CMD_RET_FAILURE;
104 	}
105 
106 	return CMD_RET_SUCCESS;
107 }
108 
109 U_BOOT_CMD(pwm, 6, 0, do_pwm,
110 	   "control pwm channels",
111 	   "pwm <invert> <pwm_dev_num> <channel> <polarity>\n"
112 	   "pwm <config> <pwm_dev_num> <channel> <period_ns> <duty_ns>\n"
113 	   "pwm <enable/disable> <pwm_dev_num> <channel>\n"
114 	   "Note: All input values are in decimal");
115