]>
Commit | Line | Data |
---|---|---|
83d290c5 | 1 | // SPDX-License-Identifier: GPL-2.0+ |
43b41566 SG |
2 | /* |
3 | * Copyright (c) 2015 Google, Inc | |
4 | * Written by Simon Glass <[email protected]> | |
43b41566 SG |
5 | */ |
6 | ||
43b41566 SG |
7 | #include <dm.h> |
8 | #include <errno.h> | |
9 | #include <pwm.h> | |
10 | #include <asm/test.h> | |
11 | ||
43b41566 SG |
12 | enum { |
13 | NUM_CHANNELS = 3, | |
14 | }; | |
15 | ||
5d9a88f4 SG |
16 | /** |
17 | * struct sandbox_pwm_chan - a sandbox PWM channel | |
18 | * | |
19 | * @period_ns: Period of the PWM in nanoseconds | |
20 | * @duty_ns: Current duty cycle of the PWM in nanoseconds | |
21 | * @enable: true if the PWM is enabled | |
22 | * @polarity: true if the PWM polarity is active high | |
23 | */ | |
43b41566 SG |
24 | struct sandbox_pwm_chan { |
25 | uint period_ns; | |
26 | uint duty_ns; | |
27 | bool enable; | |
5540e25a | 28 | bool polarity; |
43b41566 SG |
29 | }; |
30 | ||
31 | struct sandbox_pwm_priv { | |
32 | struct sandbox_pwm_chan chan[NUM_CHANNELS]; | |
33 | }; | |
34 | ||
5d9a88f4 SG |
35 | int sandbox_pwm_get_config(struct udevice *dev, uint channel, uint *period_nsp, |
36 | uint *duty_nsp, bool *enablep, bool *polarityp) | |
37 | { | |
38 | struct sandbox_pwm_priv *priv = dev_get_priv(dev); | |
39 | struct sandbox_pwm_chan *chan; | |
40 | ||
41 | if (channel >= NUM_CHANNELS) | |
42 | return -ENOSPC; | |
43 | chan = &priv->chan[channel]; | |
44 | *period_nsp = chan->period_ns; | |
45 | *duty_nsp = chan->duty_ns; | |
46 | *enablep = chan->enable; | |
47 | *polarityp = chan->polarity; | |
48 | ||
49 | return 0; | |
50 | } | |
51 | ||
43b41566 SG |
52 | static int sandbox_pwm_set_config(struct udevice *dev, uint channel, |
53 | uint period_ns, uint duty_ns) | |
54 | { | |
55 | struct sandbox_pwm_priv *priv = dev_get_priv(dev); | |
56 | struct sandbox_pwm_chan *chan; | |
57 | ||
58 | if (channel >= NUM_CHANNELS) | |
59 | return -ENOSPC; | |
60 | chan = &priv->chan[channel]; | |
fefa713b ANY |
61 | |
62 | if (channel == 2) { | |
63 | /* Pretend to have some fixed period */ | |
64 | chan->period_ns = 4096; | |
65 | chan->duty_ns = duty_ns * 4096 / period_ns; | |
66 | } else { | |
67 | chan->period_ns = period_ns; | |
68 | chan->duty_ns = duty_ns; | |
69 | } | |
43b41566 SG |
70 | |
71 | return 0; | |
72 | } | |
73 | ||
74 | static int sandbox_pwm_set_enable(struct udevice *dev, uint channel, | |
75 | bool enable) | |
76 | { | |
77 | struct sandbox_pwm_priv *priv = dev_get_priv(dev); | |
78 | struct sandbox_pwm_chan *chan; | |
79 | ||
80 | if (channel >= NUM_CHANNELS) | |
81 | return -ENOSPC; | |
82 | chan = &priv->chan[channel]; | |
83 | chan->enable = enable; | |
84 | ||
85 | return 0; | |
86 | } | |
87 | ||
5540e25a KY |
88 | static int sandbox_pwm_set_invert(struct udevice *dev, uint channel, |
89 | bool polarity) | |
90 | { | |
91 | struct sandbox_pwm_priv *priv = dev_get_priv(dev); | |
92 | struct sandbox_pwm_chan *chan; | |
93 | ||
94 | if (channel >= NUM_CHANNELS) | |
95 | return -ENOSPC; | |
96 | chan = &priv->chan[channel]; | |
97 | chan->polarity = polarity; | |
98 | ||
99 | return 0; | |
100 | } | |
101 | ||
43b41566 SG |
102 | static const struct pwm_ops sandbox_pwm_ops = { |
103 | .set_config = sandbox_pwm_set_config, | |
104 | .set_enable = sandbox_pwm_set_enable, | |
5540e25a | 105 | .set_invert = sandbox_pwm_set_invert, |
43b41566 SG |
106 | }; |
107 | ||
108 | static const struct udevice_id sandbox_pwm_ids[] = { | |
109 | { .compatible = "sandbox,pwm" }, | |
110 | { } | |
111 | }; | |
112 | ||
113 | U_BOOT_DRIVER(warm_pwm_sandbox) = { | |
114 | .name = "pwm_sandbox", | |
115 | .id = UCLASS_PWM, | |
116 | .of_match = sandbox_pwm_ids, | |
117 | .ops = &sandbox_pwm_ops, | |
41575d8e | 118 | .priv_auto = sizeof(struct sandbox_pwm_priv), |
43b41566 | 119 | }; |