1
2
3
4
5
6
7
8
9
10
11
12
13
14
15#include <common.h>
16#include <clk.h>
17#include <div64.h>
18#include <dm.h>
19#include <pwm.h>
20#include <regmap.h>
21#include <asm/global_data.h>
22#include <linux/io.h>
23#include <linux/log2.h>
24#include <linux/bitfield.h>
25
26
27#define PWM_SIFIVE_PWMCFG_SCALE GENMASK(3, 0)
28#define PWM_SIFIVE_PWMCFG_STICKY BIT(8)
29#define PWM_SIFIVE_PWMCFG_ZERO_CMP BIT(9)
30#define PWM_SIFIVE_PWMCFG_DEGLITCH BIT(10)
31#define PWM_SIFIVE_PWMCFG_EN_ALWAYS BIT(12)
32#define PWM_SIFIVE_PWMCFG_EN_ONCE BIT(13)
33#define PWM_SIFIVE_PWMCFG_CENTER BIT(16)
34#define PWM_SIFIVE_PWMCFG_GANG BIT(24)
35#define PWM_SIFIVE_PWMCFG_IP BIT(28)
36
37
38#define PWM_SIFIVE_SIZE_PWMCMP 4
39#define PWM_SIFIVE_CMPWIDTH 16
40
41DECLARE_GLOBAL_DATA_PTR;
42
43struct pwm_sifive_regs {
44 unsigned long cfg;
45 unsigned long cnt;
46 unsigned long pwms;
47 unsigned long cmp0;
48};
49
50struct pwm_sifive_data {
51 struct pwm_sifive_regs regs;
52};
53
54struct pwm_sifive_priv {
55 void __iomem *base;
56 ulong freq;
57 const struct pwm_sifive_data *data;
58};
59
60static int pwm_sifive_set_config(struct udevice *dev, uint channel,
61 uint period_ns, uint duty_ns)
62{
63 struct pwm_sifive_priv *priv = dev_get_priv(dev);
64 const struct pwm_sifive_regs *regs = &priv->data->regs;
65 unsigned long scale_pow;
66 unsigned long long num;
67 u32 scale, val = 0, frac;
68
69 debug("%s: period_ns=%u, duty_ns=%u\n", __func__, period_ns, duty_ns);
70
71
72
73
74
75
76
77
78 scale_pow = lldiv((uint64_t)priv->freq * period_ns, 1000000000);
79 scale = clamp(ilog2(scale_pow) - PWM_SIFIVE_CMPWIDTH, 0, 0xf);
80 val |= FIELD_PREP(PWM_SIFIVE_PWMCFG_SCALE, scale);
81
82
83
84
85
86
87
88 num = (u64)duty_ns * (1U << PWM_SIFIVE_CMPWIDTH);
89 frac = DIV_ROUND_CLOSEST_ULL(num, period_ns);
90 frac = min(frac, (1U << PWM_SIFIVE_CMPWIDTH) - 1);
91
92 writel(val, priv->base + regs->cfg);
93 writel(frac, priv->base + regs->cmp0 + channel *
94 PWM_SIFIVE_SIZE_PWMCMP);
95
96 return 0;
97}
98
99static int pwm_sifive_set_enable(struct udevice *dev, uint channel, bool enable)
100{
101 struct pwm_sifive_priv *priv = dev_get_priv(dev);
102 const struct pwm_sifive_regs *regs = &priv->data->regs;
103 u32 val;
104
105 debug("%s: Enable '%s'\n", __func__, dev->name);
106
107 if (enable) {
108 val = readl(priv->base + regs->cfg);
109 val |= PWM_SIFIVE_PWMCFG_EN_ALWAYS;
110 writel(val, priv->base + regs->cfg);
111 } else {
112 writel(0, priv->base + regs->cmp0 + channel *
113 PWM_SIFIVE_SIZE_PWMCMP);
114 }
115
116 return 0;
117}
118
119static int pwm_sifive_of_to_plat(struct udevice *dev)
120{
121 struct pwm_sifive_priv *priv = dev_get_priv(dev);
122
123 priv->base = dev_read_addr_ptr(dev);
124
125 return 0;
126}
127
128static int pwm_sifive_probe(struct udevice *dev)
129{
130 struct pwm_sifive_priv *priv = dev_get_priv(dev);
131 struct clk clk;
132 int ret = 0;
133
134 ret = clk_get_by_index(dev, 0, &clk);
135 if (ret < 0) {
136 debug("%s get clock fail!\n", __func__);
137 return -EINVAL;
138 }
139
140 priv->freq = clk_get_rate(&clk);
141 priv->data = (struct pwm_sifive_data *)dev_get_driver_data(dev);
142
143 return 0;
144}
145
146static const struct pwm_ops pwm_sifive_ops = {
147 .set_config = pwm_sifive_set_config,
148 .set_enable = pwm_sifive_set_enable,
149};
150
151static const struct pwm_sifive_data pwm_data = {
152 .regs = {
153 .cfg = 0x00,
154 .cnt = 0x08,
155 .pwms = 0x10,
156 .cmp0 = 0x20,
157 },
158};
159
160static const struct udevice_id pwm_sifive_ids[] = {
161 { .compatible = "sifive,pwm0", .data = (ulong)&pwm_data},
162 { }
163};
164
165U_BOOT_DRIVER(pwm_sifive) = {
166 .name = "pwm_sifive",
167 .id = UCLASS_PWM,
168 .of_match = pwm_sifive_ids,
169 .ops = &pwm_sifive_ops,
170 .of_to_plat = pwm_sifive_of_to_plat,
171 .probe = pwm_sifive_probe,
172 .priv_auto = sizeof(struct pwm_sifive_priv),
173};
174