diff options
author | David Wu <david.wu@rock-chips.com> | 2017-08-08 11:41:28 -0400 |
---|---|---|
committer | Thierry Reding <thierry.reding@gmail.com> | 2017-08-18 11:42:30 -0400 |
commit | 831b2790507b3aac3213e9f39c714d85b0220098 (patch) | |
tree | 39793c3b3cf2f7ac26cc7067508a21f3f421ad56 | |
parent | bc834d7b07b4e57c89607c929dcb5eabb17b47a7 (diff) |
pwm: rockchip: Use same PWM ops for each IP
Just use the same PWM ops for each IP, and get rid of the ops in struct
rockchip_pwm_data, but still define the three different instances of the
struct to use common interface for each IP.
Signed-off-by: David Wu <david.wu@rock-chips.com>
Signed-off-by: Thierry Reding <thierry.reding@gmail.com>
-rw-r--r-- | drivers/pwm/pwm-rockchip.c | 149 |
1 files changed, 38 insertions, 111 deletions
diff --git a/drivers/pwm/pwm-rockchip.c b/drivers/pwm/pwm-rockchip.c index 911329a15da0..a3fcb404036d 100644 --- a/drivers/pwm/pwm-rockchip.c +++ b/drivers/pwm/pwm-rockchip.c | |||
@@ -50,12 +50,7 @@ struct rockchip_pwm_data { | |||
50 | struct rockchip_pwm_regs regs; | 50 | struct rockchip_pwm_regs regs; |
51 | unsigned int prescaler; | 51 | unsigned int prescaler; |
52 | bool supports_polarity; | 52 | bool supports_polarity; |
53 | const struct pwm_ops *ops; | 53 | u32 enable_conf; |
54 | |||
55 | void (*get_state)(struct pwm_chip *chip, struct pwm_device *pwm, | ||
56 | struct pwm_state *state); | ||
57 | int (*pwm_apply)(struct pwm_chip *chip, struct pwm_device *pwm, | ||
58 | struct pwm_state *state); | ||
59 | }; | 54 | }; |
60 | 55 | ||
61 | static inline struct rockchip_pwm_chip *to_rockchip_pwm_chip(struct pwm_chip *c) | 56 | static inline struct rockchip_pwm_chip *to_rockchip_pwm_chip(struct pwm_chip *c) |
@@ -63,45 +58,15 @@ static inline struct rockchip_pwm_chip *to_rockchip_pwm_chip(struct pwm_chip *c) | |||
63 | return container_of(c, struct rockchip_pwm_chip, chip); | 58 | return container_of(c, struct rockchip_pwm_chip, chip); |
64 | } | 59 | } |
65 | 60 | ||
66 | static void rockchip_pwm_get_state_v1(struct pwm_chip *chip, | ||
67 | struct pwm_device *pwm, | ||
68 | struct pwm_state *state) | ||
69 | { | ||
70 | struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip); | ||
71 | u32 enable_conf = PWM_CTRL_OUTPUT_EN | PWM_CTRL_TIMER_EN; | ||
72 | u32 val; | ||
73 | |||
74 | val = readl_relaxed(pc->base + pc->data->regs.ctrl); | ||
75 | if ((val & enable_conf) == enable_conf) | ||
76 | state->enabled = true; | ||
77 | } | ||
78 | |||
79 | static void rockchip_pwm_get_state_v2(struct pwm_chip *chip, | ||
80 | struct pwm_device *pwm, | ||
81 | struct pwm_state *state) | ||
82 | { | ||
83 | struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip); | ||
84 | u32 enable_conf = PWM_OUTPUT_LEFT | PWM_LP_DISABLE | PWM_ENABLE | | ||
85 | PWM_CONTINUOUS; | ||
86 | u32 val; | ||
87 | |||
88 | val = readl_relaxed(pc->base + pc->data->regs.ctrl); | ||
89 | if ((val & enable_conf) != enable_conf) | ||
90 | return; | ||
91 | |||
92 | state->enabled = true; | ||
93 | |||
94 | if (!(val & PWM_DUTY_POSITIVE)) | ||
95 | state->polarity = PWM_POLARITY_INVERSED; | ||
96 | } | ||
97 | |||
98 | static void rockchip_pwm_get_state(struct pwm_chip *chip, | 61 | static void rockchip_pwm_get_state(struct pwm_chip *chip, |
99 | struct pwm_device *pwm, | 62 | struct pwm_device *pwm, |
100 | struct pwm_state *state) | 63 | struct pwm_state *state) |
101 | { | 64 | { |
102 | struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip); | 65 | struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip); |
66 | u32 enable_conf = pc->data->enable_conf; | ||
103 | unsigned long clk_rate; | 67 | unsigned long clk_rate; |
104 | u64 tmp; | 68 | u64 tmp; |
69 | u32 val; | ||
105 | int ret; | 70 | int ret; |
106 | 71 | ||
107 | ret = clk_enable(pc->pclk); | 72 | ret = clk_enable(pc->pclk); |
@@ -116,9 +81,20 @@ static void rockchip_pwm_get_state(struct pwm_chip *chip, | |||
116 | 81 | ||
117 | tmp = readl_relaxed(pc->base + pc->data->regs.duty); | 82 | tmp = readl_relaxed(pc->base + pc->data->regs.duty); |
118 | tmp *= pc->data->prescaler * NSEC_PER_SEC; | 83 | tmp *= pc->data->prescaler * NSEC_PER_SEC; |
119 | state->duty_cycle = DIV_ROUND_CLOSEST_ULL(tmp, clk_rate); | 84 | state->duty_cycle = DIV_ROUND_CLOSEST_ULL(tmp, clk_rate); |
120 | 85 | ||
121 | pc->data->get_state(chip, pwm, state); | 86 | val = readl_relaxed(pc->base + pc->data->regs.ctrl); |
87 | if (pc->data->supports_polarity) | ||
88 | state->enabled = ((val & enable_conf) != enable_conf) ? | ||
89 | false : true; | ||
90 | else | ||
91 | state->enabled = ((val & enable_conf) == enable_conf) ? | ||
92 | true : false; | ||
93 | |||
94 | if (pc->data->supports_polarity) { | ||
95 | if (!(val & PWM_DUTY_POSITIVE)) | ||
96 | state->polarity = PWM_POLARITY_INVERSED; | ||
97 | } | ||
122 | 98 | ||
123 | clk_disable(pc->pclk); | 99 | clk_disable(pc->pclk); |
124 | } | 100 | } |
@@ -161,10 +137,10 @@ static void rockchip_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, | |||
161 | 137 | ||
162 | static int rockchip_pwm_enable(struct pwm_chip *chip, | 138 | static int rockchip_pwm_enable(struct pwm_chip *chip, |
163 | struct pwm_device *pwm, | 139 | struct pwm_device *pwm, |
164 | bool enable, | 140 | bool enable) |
165 | u32 enable_conf) | ||
166 | { | 141 | { |
167 | struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip); | 142 | struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip); |
143 | u32 enable_conf = pc->data->enable_conf; | ||
168 | int ret; | 144 | int ret; |
169 | u32 val; | 145 | u32 val; |
170 | 146 | ||
@@ -189,75 +165,35 @@ static int rockchip_pwm_enable(struct pwm_chip *chip, | |||
189 | return 0; | 165 | return 0; |
190 | } | 166 | } |
191 | 167 | ||
192 | static int rockchip_pwm_apply_v1(struct pwm_chip *chip, struct pwm_device *pwm, | 168 | static int rockchip_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, |
193 | struct pwm_state *state) | 169 | struct pwm_state *state) |
194 | { | 170 | { |
195 | u32 enable_conf = PWM_CTRL_OUTPUT_EN | PWM_CTRL_TIMER_EN; | 171 | struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip); |
196 | struct pwm_state curstate; | 172 | struct pwm_state curstate; |
197 | bool enabled; | 173 | bool enabled; |
198 | int ret = 0; | 174 | int ret = 0; |
199 | 175 | ||
176 | ret = clk_enable(pc->pclk); | ||
177 | if (ret) | ||
178 | return ret; | ||
179 | |||
200 | pwm_get_state(pwm, &curstate); | 180 | pwm_get_state(pwm, &curstate); |
201 | enabled = curstate.enabled; | 181 | enabled = curstate.enabled; |
202 | 182 | ||
203 | if (state->polarity != curstate.polarity && enabled) { | 183 | if (state->polarity != curstate.polarity && enabled) { |
204 | ret = rockchip_pwm_enable(chip, pwm, false, enable_conf); | 184 | ret = rockchip_pwm_enable(chip, pwm, false); |
205 | if (ret) | 185 | if (ret) |
206 | return ret; | 186 | goto out; |
207 | enabled = false; | 187 | enabled = false; |
208 | } | 188 | } |
209 | 189 | ||
210 | rockchip_pwm_config(chip, pwm, state); | 190 | rockchip_pwm_config(chip, pwm, state); |
211 | 191 | if (state->enabled != enabled) { | |
212 | if (state->enabled != enabled) | 192 | ret = rockchip_pwm_enable(chip, pwm, state->enabled); |
213 | ret = rockchip_pwm_enable(chip, pwm, state->enabled, | ||
214 | enable_conf); | ||
215 | |||
216 | return ret; | ||
217 | } | ||
218 | |||
219 | static int rockchip_pwm_apply_v2(struct pwm_chip *chip, struct pwm_device *pwm, | ||
220 | struct pwm_state *state) | ||
221 | { | ||
222 | u32 enable_conf = PWM_OUTPUT_LEFT | PWM_LP_DISABLE | PWM_ENABLE | | ||
223 | PWM_CONTINUOUS; | ||
224 | struct pwm_state curstate; | ||
225 | bool enabled; | ||
226 | int ret = 0; | ||
227 | |||
228 | pwm_get_state(pwm, &curstate); | ||
229 | enabled = curstate.enabled; | ||
230 | |||
231 | if (state->polarity != curstate.polarity && enabled) { | ||
232 | ret = rockchip_pwm_enable(chip, pwm, false, enable_conf); | ||
233 | if (ret) | 193 | if (ret) |
234 | return ret; | 194 | goto out; |
235 | enabled = false; | ||
236 | } | 195 | } |
237 | 196 | ||
238 | rockchip_pwm_config(chip, pwm, state); | ||
239 | |||
240 | if (state->enabled != enabled) | ||
241 | ret = rockchip_pwm_enable(chip, pwm, state->enabled, | ||
242 | enable_conf); | ||
243 | |||
244 | return ret; | ||
245 | } | ||
246 | |||
247 | static int rockchip_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, | ||
248 | struct pwm_state *state) | ||
249 | { | ||
250 | struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip); | ||
251 | int ret; | ||
252 | |||
253 | ret = clk_enable(pc->pclk); | ||
254 | if (ret) | ||
255 | return ret; | ||
256 | |||
257 | ret = pc->data->pwm_apply(chip, pwm, state); | ||
258 | if (ret) | ||
259 | goto out; | ||
260 | |||
261 | /* | 197 | /* |
262 | * Update the state with the real hardware, which can differ a bit | 198 | * Update the state with the real hardware, which can differ a bit |
263 | * because of period/duty_cycle approximation. | 199 | * because of period/duty_cycle approximation. |
@@ -270,13 +206,7 @@ out: | |||
270 | return ret; | 206 | return ret; |
271 | } | 207 | } |
272 | 208 | ||
273 | static const struct pwm_ops rockchip_pwm_ops_v1 = { | 209 | static const struct pwm_ops rockchip_pwm_ops = { |
274 | .get_state = rockchip_pwm_get_state, | ||
275 | .apply = rockchip_pwm_apply, | ||
276 | .owner = THIS_MODULE, | ||
277 | }; | ||
278 | |||
279 | static const struct pwm_ops rockchip_pwm_ops_v2 = { | ||
280 | .get_state = rockchip_pwm_get_state, | 210 | .get_state = rockchip_pwm_get_state, |
281 | .apply = rockchip_pwm_apply, | 211 | .apply = rockchip_pwm_apply, |
282 | .owner = THIS_MODULE, | 212 | .owner = THIS_MODULE, |
@@ -290,9 +220,8 @@ static const struct rockchip_pwm_data pwm_data_v1 = { | |||
290 | .ctrl = 0x0c, | 220 | .ctrl = 0x0c, |
291 | }, | 221 | }, |
292 | .prescaler = 2, | 222 | .prescaler = 2, |
293 | .ops = &rockchip_pwm_ops_v1, | 223 | .supports_polarity = false, |
294 | .get_state = rockchip_pwm_get_state_v1, | 224 | .enable_conf = PWM_CTRL_OUTPUT_EN | PWM_CTRL_TIMER_EN, |
295 | .pwm_apply = rockchip_pwm_apply_v1, | ||
296 | }; | 225 | }; |
297 | 226 | ||
298 | static const struct rockchip_pwm_data pwm_data_v2 = { | 227 | static const struct rockchip_pwm_data pwm_data_v2 = { |
@@ -304,9 +233,8 @@ static const struct rockchip_pwm_data pwm_data_v2 = { | |||
304 | }, | 233 | }, |
305 | .prescaler = 1, | 234 | .prescaler = 1, |
306 | .supports_polarity = true, | 235 | .supports_polarity = true, |
307 | .ops = &rockchip_pwm_ops_v2, | 236 | .enable_conf = PWM_OUTPUT_LEFT | PWM_LP_DISABLE | PWM_ENABLE | |
308 | .get_state = rockchip_pwm_get_state_v2, | 237 | PWM_CONTINUOUS, |
309 | .pwm_apply = rockchip_pwm_apply_v2, | ||
310 | }; | 238 | }; |
311 | 239 | ||
312 | static const struct rockchip_pwm_data pwm_data_vop = { | 240 | static const struct rockchip_pwm_data pwm_data_vop = { |
@@ -318,9 +246,8 @@ static const struct rockchip_pwm_data pwm_data_vop = { | |||
318 | }, | 246 | }, |
319 | .prescaler = 1, | 247 | .prescaler = 1, |
320 | .supports_polarity = true, | 248 | .supports_polarity = true, |
321 | .ops = &rockchip_pwm_ops_v2, | 249 | .enable_conf = PWM_OUTPUT_LEFT | PWM_LP_DISABLE | PWM_ENABLE | |
322 | .get_state = rockchip_pwm_get_state_v2, | 250 | PWM_CONTINUOUS, |
323 | .pwm_apply = rockchip_pwm_apply_v2, | ||
324 | }; | 251 | }; |
325 | 252 | ||
326 | static const struct of_device_id rockchip_pwm_dt_ids[] = { | 253 | static const struct of_device_id rockchip_pwm_dt_ids[] = { |
@@ -393,7 +320,7 @@ static int rockchip_pwm_probe(struct platform_device *pdev) | |||
393 | 320 | ||
394 | pc->data = id->data; | 321 | pc->data = id->data; |
395 | pc->chip.dev = &pdev->dev; | 322 | pc->chip.dev = &pdev->dev; |
396 | pc->chip.ops = pc->data->ops; | 323 | pc->chip.ops = &rockchip_pwm_ops; |
397 | pc->chip.base = -1; | 324 | pc->chip.base = -1; |
398 | pc->chip.npwm = 1; | 325 | pc->chip.npwm = 1; |
399 | 326 | ||