summaryrefslogtreecommitdiff
path: root/cmd/pwm.c
blob: e1f97c759d2cfc2c1bab5667a95ef4a136ca3a1e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
// 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");