diff options
Diffstat (limited to 'drivers/pwm/pwm-tiecap.c')
-rw-r--r-- | drivers/pwm/pwm-tiecap.c | 48 |
1 files changed, 47 insertions, 1 deletions
diff --git a/drivers/pwm/pwm-tiecap.c b/drivers/pwm/pwm-tiecap.c index 87c091b245cc..5cf016dd9822 100644 --- a/drivers/pwm/pwm-tiecap.c +++ b/drivers/pwm/pwm-tiecap.c | |||
@@ -25,6 +25,10 @@ | |||
25 | #include <linux/clk.h> | 25 | #include <linux/clk.h> |
26 | #include <linux/pm_runtime.h> | 26 | #include <linux/pm_runtime.h> |
27 | #include <linux/pwm.h> | 27 | #include <linux/pwm.h> |
28 | #include <linux/of_device.h> | ||
29 | #include <linux/pinctrl/consumer.h> | ||
30 | |||
31 | #include "pwm-tipwmss.h" | ||
28 | 32 | ||
29 | /* ECAP registers and bits definitions */ | 33 | /* ECAP registers and bits definitions */ |
30 | #define CAP1 0x08 | 34 | #define CAP1 0x08 |
@@ -184,12 +188,24 @@ static const struct pwm_ops ecap_pwm_ops = { | |||
184 | .owner = THIS_MODULE, | 188 | .owner = THIS_MODULE, |
185 | }; | 189 | }; |
186 | 190 | ||
191 | static const struct of_device_id ecap_of_match[] = { | ||
192 | { .compatible = "ti,am33xx-ecap" }, | ||
193 | {}, | ||
194 | }; | ||
195 | MODULE_DEVICE_TABLE(of, ecap_of_match); | ||
196 | |||
187 | static int ecap_pwm_probe(struct platform_device *pdev) | 197 | static int ecap_pwm_probe(struct platform_device *pdev) |
188 | { | 198 | { |
189 | int ret; | 199 | int ret; |
190 | struct resource *r; | 200 | struct resource *r; |
191 | struct clk *clk; | 201 | struct clk *clk; |
192 | struct ecap_pwm_chip *pc; | 202 | struct ecap_pwm_chip *pc; |
203 | u16 status; | ||
204 | struct pinctrl *pinctrl; | ||
205 | |||
206 | pinctrl = devm_pinctrl_get_select_default(&pdev->dev); | ||
207 | if (IS_ERR(pinctrl)) | ||
208 | dev_warn(&pdev->dev, "unable to select pin group\n"); | ||
193 | 209 | ||
194 | pc = devm_kzalloc(&pdev->dev, sizeof(*pc), GFP_KERNEL); | 210 | pc = devm_kzalloc(&pdev->dev, sizeof(*pc), GFP_KERNEL); |
195 | if (!pc) { | 211 | if (!pc) { |
@@ -211,6 +227,8 @@ static int ecap_pwm_probe(struct platform_device *pdev) | |||
211 | 227 | ||
212 | pc->chip.dev = &pdev->dev; | 228 | pc->chip.dev = &pdev->dev; |
213 | pc->chip.ops = &ecap_pwm_ops; | 229 | pc->chip.ops = &ecap_pwm_ops; |
230 | pc->chip.of_xlate = of_pwm_xlate_with_flags; | ||
231 | pc->chip.of_pwm_n_cells = 3; | ||
214 | pc->chip.base = -1; | 232 | pc->chip.base = -1; |
215 | pc->chip.npwm = 1; | 233 | pc->chip.npwm = 1; |
216 | 234 | ||
@@ -231,14 +249,40 @@ static int ecap_pwm_probe(struct platform_device *pdev) | |||
231 | } | 249 | } |
232 | 250 | ||
233 | pm_runtime_enable(&pdev->dev); | 251 | pm_runtime_enable(&pdev->dev); |
252 | pm_runtime_get_sync(&pdev->dev); | ||
253 | |||
254 | status = pwmss_submodule_state_change(pdev->dev.parent, | ||
255 | PWMSS_ECAPCLK_EN); | ||
256 | if (!(status & PWMSS_ECAPCLK_EN_ACK)) { | ||
257 | dev_err(&pdev->dev, "PWMSS config space clock enable failed\n"); | ||
258 | ret = -EINVAL; | ||
259 | goto pwmss_clk_failure; | ||
260 | } | ||
261 | |||
262 | pm_runtime_put_sync(&pdev->dev); | ||
263 | |||
234 | platform_set_drvdata(pdev, pc); | 264 | platform_set_drvdata(pdev, pc); |
235 | return 0; | 265 | return 0; |
266 | |||
267 | pwmss_clk_failure: | ||
268 | pm_runtime_put_sync(&pdev->dev); | ||
269 | pm_runtime_disable(&pdev->dev); | ||
270 | pwmchip_remove(&pc->chip); | ||
271 | return ret; | ||
236 | } | 272 | } |
237 | 273 | ||
238 | static int ecap_pwm_remove(struct platform_device *pdev) | 274 | static int ecap_pwm_remove(struct platform_device *pdev) |
239 | { | 275 | { |
240 | struct ecap_pwm_chip *pc = platform_get_drvdata(pdev); | 276 | struct ecap_pwm_chip *pc = platform_get_drvdata(pdev); |
241 | 277 | ||
278 | pm_runtime_get_sync(&pdev->dev); | ||
279 | /* | ||
280 | * Due to hardware misbehaviour, acknowledge of the stop_req | ||
281 | * is missing. Hence checking of the status bit skipped. | ||
282 | */ | ||
283 | pwmss_submodule_state_change(pdev->dev.parent, PWMSS_ECAPCLK_STOP_REQ); | ||
284 | pm_runtime_put_sync(&pdev->dev); | ||
285 | |||
242 | pm_runtime_put_sync(&pdev->dev); | 286 | pm_runtime_put_sync(&pdev->dev); |
243 | pm_runtime_disable(&pdev->dev); | 287 | pm_runtime_disable(&pdev->dev); |
244 | return pwmchip_remove(&pc->chip); | 288 | return pwmchip_remove(&pc->chip); |
@@ -246,7 +290,9 @@ static int ecap_pwm_remove(struct platform_device *pdev) | |||
246 | 290 | ||
247 | static struct platform_driver ecap_pwm_driver = { | 291 | static struct platform_driver ecap_pwm_driver = { |
248 | .driver = { | 292 | .driver = { |
249 | .name = "ecap", | 293 | .name = "ecap", |
294 | .owner = THIS_MODULE, | ||
295 | .of_match_table = ecap_of_match, | ||
250 | }, | 296 | }, |
251 | .probe = ecap_pwm_probe, | 297 | .probe = ecap_pwm_probe, |
252 | .remove = ecap_pwm_remove, | 298 | .remove = ecap_pwm_remove, |