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
13enum pwm_cmd {
14	PWM_SET_INVERT,
15	PWM_SET_CONFIG,
16	PWM_SET_ENABLE,
17	PWM_SET_DISABLE,
18};
19
20static 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 = dectoul(str_pwm, NULL);
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 = dectoul(str_channel, NULL);
78	argc--;
79	argv++;
80
81	if (sub_cmd == PWM_SET_INVERT) {
82		str_enable = *argv;
83		pwm_enable = dectoul(str_enable, NULL);
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 = dectoul(str_period, NULL);
90
91		str_duty = *argv;
92		duty_ns = dectoul(str_duty, NULL);
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
109U_BOOT_CMD(pwm, 6, 0, do_pwm,
110	   "control pwm channels",
111	   "invert <pwm_dev_num> <channel> <polarity> - invert polarity\n"
112	   "pwm config <pwm_dev_num> <channel> <period_ns> <duty_ns> - config PWM\n"
113	   "pwm enable <pwm_dev_num> <channel> - enable PWM output\n"
114	   "pwm disable <pwm_dev_num> <channel> - disable PWM output\n"
115	   "Note: All input values are in decimal");
116