1 /*
2  * Copyright (C) 2017 Sanechips Technology Co., Ltd.
3  * Copyright 2017 Linaro Ltd.
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation.
8  */
9 
10 #include <linux/clk.h>
11 #include <linux/err.h>
12 #include <linux/io.h>
13 #include <linux/kernel.h>
14 #include <linux/module.h>
15 #include <linux/platform_device.h>
16 #include <linux/pwm.h>
17 #include <linux/slab.h>
18 
19 #define ZX_PWM_MODE		0x0
20 #define ZX_PWM_CLKDIV_SHIFT	2
21 #define ZX_PWM_CLKDIV_MASK	GENMASK(11, 2)
22 #define ZX_PWM_CLKDIV(x)	(((x) << ZX_PWM_CLKDIV_SHIFT) & \
23 					 ZX_PWM_CLKDIV_MASK)
24 #define ZX_PWM_POLAR		BIT(1)
25 #define ZX_PWM_EN		BIT(0)
26 #define ZX_PWM_PERIOD		0x4
27 #define ZX_PWM_DUTY		0x8
28 
29 #define ZX_PWM_CLKDIV_MAX	1023
30 #define ZX_PWM_PERIOD_MAX	65535
31 
32 struct zx_pwm_chip {
33 	struct pwm_chip chip;
34 	struct clk *pclk;
35 	struct clk *wclk;
36 	void __iomem *base;
37 };
38 
to_zx_pwm_chip(struct pwm_chip * chip)39 static inline struct zx_pwm_chip *to_zx_pwm_chip(struct pwm_chip *chip)
40 {
41 	return container_of(chip, struct zx_pwm_chip, chip);
42 }
43 
zx_pwm_readl(struct zx_pwm_chip * zpc,unsigned int hwpwm,unsigned int offset)44 static inline u32 zx_pwm_readl(struct zx_pwm_chip *zpc, unsigned int hwpwm,
45 			       unsigned int offset)
46 {
47 	return readl(zpc->base + (hwpwm + 1) * 0x10 + offset);
48 }
49 
zx_pwm_writel(struct zx_pwm_chip * zpc,unsigned int hwpwm,unsigned int offset,u32 value)50 static inline void zx_pwm_writel(struct zx_pwm_chip *zpc, unsigned int hwpwm,
51 				 unsigned int offset, u32 value)
52 {
53 	writel(value, zpc->base + (hwpwm + 1) * 0x10 + offset);
54 }
55 
zx_pwm_set_mask(struct zx_pwm_chip * zpc,unsigned int hwpwm,unsigned int offset,u32 mask,u32 value)56 static void zx_pwm_set_mask(struct zx_pwm_chip *zpc, unsigned int hwpwm,
57 			    unsigned int offset, u32 mask, u32 value)
58 {
59 	u32 data;
60 
61 	data = zx_pwm_readl(zpc, hwpwm, offset);
62 	data &= ~mask;
63 	data |= value & mask;
64 	zx_pwm_writel(zpc, hwpwm, offset, data);
65 }
66 
zx_pwm_get_state(struct pwm_chip * chip,struct pwm_device * pwm,struct pwm_state * state)67 static void zx_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
68 			     struct pwm_state *state)
69 {
70 	struct zx_pwm_chip *zpc = to_zx_pwm_chip(chip);
71 	unsigned long rate;
72 	unsigned int div;
73 	u32 value;
74 	u64 tmp;
75 
76 	value = zx_pwm_readl(zpc, pwm->hwpwm, ZX_PWM_MODE);
77 
78 	if (value & ZX_PWM_POLAR)
79 		state->polarity = PWM_POLARITY_NORMAL;
80 	else
81 		state->polarity = PWM_POLARITY_INVERSED;
82 
83 	if (value & ZX_PWM_EN)
84 		state->enabled = true;
85 	else
86 		state->enabled = false;
87 
88 	div = (value & ZX_PWM_CLKDIV_MASK) >> ZX_PWM_CLKDIV_SHIFT;
89 	rate = clk_get_rate(zpc->wclk);
90 
91 	tmp = zx_pwm_readl(zpc, pwm->hwpwm, ZX_PWM_PERIOD);
92 	tmp *= div * NSEC_PER_SEC;
93 	state->period = DIV_ROUND_CLOSEST_ULL(tmp, rate);
94 
95 	tmp = zx_pwm_readl(zpc, pwm->hwpwm, ZX_PWM_DUTY);
96 	tmp *= div * NSEC_PER_SEC;
97 	state->duty_cycle = DIV_ROUND_CLOSEST_ULL(tmp, rate);
98 }
99 
zx_pwm_config(struct pwm_chip * chip,struct pwm_device * pwm,unsigned int duty_ns,unsigned int period_ns)100 static int zx_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
101 			 unsigned int duty_ns, unsigned int period_ns)
102 {
103 	struct zx_pwm_chip *zpc = to_zx_pwm_chip(chip);
104 	unsigned int period_cycles, duty_cycles;
105 	unsigned long long c;
106 	unsigned int div = 1;
107 	unsigned long rate;
108 
109 	/* Find out the best divider */
110 	rate = clk_get_rate(zpc->wclk);
111 
112 	while (1) {
113 		c = rate / div;
114 		c = c * period_ns;
115 		do_div(c, NSEC_PER_SEC);
116 
117 		if (c < ZX_PWM_PERIOD_MAX)
118 			break;
119 
120 		div++;
121 
122 		if (div > ZX_PWM_CLKDIV_MAX)
123 			return -ERANGE;
124 	}
125 
126 	/* Calculate duty cycles */
127 	period_cycles = c;
128 	c *= duty_ns;
129 	do_div(c, period_ns);
130 	duty_cycles = c;
131 
132 	/*
133 	 * If the PWM is being enabled, we have to temporarily disable it
134 	 * before configuring the registers.
135 	 */
136 	if (pwm_is_enabled(pwm))
137 		zx_pwm_set_mask(zpc, pwm->hwpwm, ZX_PWM_MODE, ZX_PWM_EN, 0);
138 
139 	/* Set up registers */
140 	zx_pwm_set_mask(zpc, pwm->hwpwm, ZX_PWM_MODE, ZX_PWM_CLKDIV_MASK,
141 			ZX_PWM_CLKDIV(div));
142 	zx_pwm_writel(zpc, pwm->hwpwm, ZX_PWM_PERIOD, period_cycles);
143 	zx_pwm_writel(zpc, pwm->hwpwm, ZX_PWM_DUTY, duty_cycles);
144 
145 	/* Re-enable the PWM if needed */
146 	if (pwm_is_enabled(pwm))
147 		zx_pwm_set_mask(zpc, pwm->hwpwm, ZX_PWM_MODE,
148 				ZX_PWM_EN, ZX_PWM_EN);
149 
150 	return 0;
151 }
152 
zx_pwm_apply(struct pwm_chip * chip,struct pwm_device * pwm,struct pwm_state * state)153 static int zx_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
154 			struct pwm_state *state)
155 {
156 	struct zx_pwm_chip *zpc = to_zx_pwm_chip(chip);
157 	struct pwm_state cstate;
158 	int ret;
159 
160 	pwm_get_state(pwm, &cstate);
161 
162 	if (state->polarity != cstate.polarity)
163 		zx_pwm_set_mask(zpc, pwm->hwpwm, ZX_PWM_MODE, ZX_PWM_POLAR,
164 				(state->polarity == PWM_POLARITY_INVERSED) ?
165 				 0 : ZX_PWM_POLAR);
166 
167 	if (state->period != cstate.period ||
168 	    state->duty_cycle != cstate.duty_cycle) {
169 		ret = zx_pwm_config(chip, pwm, state->duty_cycle,
170 				    state->period);
171 		if (ret)
172 			return ret;
173 	}
174 
175 	if (state->enabled != cstate.enabled) {
176 		if (state->enabled) {
177 			ret = clk_prepare_enable(zpc->wclk);
178 			if (ret)
179 				return ret;
180 
181 			zx_pwm_set_mask(zpc, pwm->hwpwm, ZX_PWM_MODE,
182 					ZX_PWM_EN, ZX_PWM_EN);
183 		} else {
184 			zx_pwm_set_mask(zpc, pwm->hwpwm, ZX_PWM_MODE,
185 					ZX_PWM_EN, 0);
186 			clk_disable_unprepare(zpc->wclk);
187 		}
188 	}
189 
190 	return 0;
191 }
192 
193 static const struct pwm_ops zx_pwm_ops = {
194 	.apply = zx_pwm_apply,
195 	.get_state = zx_pwm_get_state,
196 	.owner = THIS_MODULE,
197 };
198 
zx_pwm_probe(struct platform_device * pdev)199 static int zx_pwm_probe(struct platform_device *pdev)
200 {
201 	struct zx_pwm_chip *zpc;
202 	struct resource *res;
203 	unsigned int i;
204 	int ret;
205 
206 	zpc = devm_kzalloc(&pdev->dev, sizeof(*zpc), GFP_KERNEL);
207 	if (!zpc)
208 		return -ENOMEM;
209 
210 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
211 	zpc->base = devm_ioremap_resource(&pdev->dev, res);
212 	if (IS_ERR(zpc->base))
213 		return PTR_ERR(zpc->base);
214 
215 	zpc->pclk = devm_clk_get(&pdev->dev, "pclk");
216 	if (IS_ERR(zpc->pclk))
217 		return PTR_ERR(zpc->pclk);
218 
219 	zpc->wclk = devm_clk_get(&pdev->dev, "wclk");
220 	if (IS_ERR(zpc->wclk))
221 		return PTR_ERR(zpc->wclk);
222 
223 	ret = clk_prepare_enable(zpc->pclk);
224 	if (ret)
225 		return ret;
226 
227 	zpc->chip.dev = &pdev->dev;
228 	zpc->chip.ops = &zx_pwm_ops;
229 	zpc->chip.base = -1;
230 	zpc->chip.npwm = 4;
231 	zpc->chip.of_xlate = of_pwm_xlate_with_flags;
232 	zpc->chip.of_pwm_n_cells = 3;
233 
234 	/*
235 	 * PWM devices may be enabled by firmware, and let's disable all of
236 	 * them initially to save power.
237 	 */
238 	for (i = 0; i < zpc->chip.npwm; i++)
239 		zx_pwm_set_mask(zpc, i, ZX_PWM_MODE, ZX_PWM_EN, 0);
240 
241 	ret = pwmchip_add(&zpc->chip);
242 	if (ret < 0) {
243 		dev_err(&pdev->dev, "failed to add PWM chip: %d\n", ret);
244 		clk_disable_unprepare(zpc->pclk);
245 		return ret;
246 	}
247 
248 	platform_set_drvdata(pdev, zpc);
249 
250 	return 0;
251 }
252 
zx_pwm_remove(struct platform_device * pdev)253 static int zx_pwm_remove(struct platform_device *pdev)
254 {
255 	struct zx_pwm_chip *zpc = platform_get_drvdata(pdev);
256 	int ret;
257 
258 	ret = pwmchip_remove(&zpc->chip);
259 	clk_disable_unprepare(zpc->pclk);
260 
261 	return ret;
262 }
263 
264 static const struct of_device_id zx_pwm_dt_ids[] = {
265 	{ .compatible = "zte,zx296718-pwm", },
266 	{ /* sentinel */ }
267 };
268 MODULE_DEVICE_TABLE(of, zx_pwm_dt_ids);
269 
270 static struct platform_driver zx_pwm_driver = {
271 	.driver = {
272 		.name = "zx-pwm",
273 		.of_match_table = zx_pwm_dt_ids,
274 	},
275 	.probe = zx_pwm_probe,
276 	.remove = zx_pwm_remove,
277 };
278 module_platform_driver(zx_pwm_driver);
279 
280 MODULE_ALIAS("platform:zx-pwm");
281 MODULE_AUTHOR("Shawn Guo <shawn.guo@linaro.org>");
282 MODULE_DESCRIPTION("ZTE ZX PWM Driver");
283 MODULE_LICENSE("GPL v2");
284