diff options
31 files changed, 576 insertions, 236 deletions
diff --git a/Documentation/devicetree/bindings/pwm/pwm-mediatek.txt b/Documentation/devicetree/bindings/pwm/pwm-mediatek.txt index 991728cb46cb..c8501530173c 100644 --- a/Documentation/devicetree/bindings/pwm/pwm-mediatek.txt +++ b/Documentation/devicetree/bindings/pwm/pwm-mediatek.txt | |||
@@ -6,6 +6,8 @@ Required properties: | |||
6 | - "mediatek,mt7622-pwm": found on mt7622 SoC. | 6 | - "mediatek,mt7622-pwm": found on mt7622 SoC. |
7 | - "mediatek,mt7623-pwm": found on mt7623 SoC. | 7 | - "mediatek,mt7623-pwm": found on mt7623 SoC. |
8 | - "mediatek,mt7628-pwm": found on mt7628 SoC. | 8 | - "mediatek,mt7628-pwm": found on mt7628 SoC. |
9 | - "mediatek,mt7629-pwm", "mediatek,mt7622-pwm": found on mt7629 SoC. | ||
10 | - "mediatek,mt8516-pwm": found on mt8516 SoC. | ||
9 | - reg: physical base address and length of the controller's registers. | 11 | - reg: physical base address and length of the controller's registers. |
10 | - #pwm-cells: must be 2. See pwm.txt in this directory for a description of | 12 | - #pwm-cells: must be 2. See pwm.txt in this directory for a description of |
11 | the cell format. | 13 | the cell format. |
diff --git a/Documentation/devicetree/bindings/pwm/pwm-sprd.txt b/Documentation/devicetree/bindings/pwm/pwm-sprd.txt new file mode 100644 index 000000000000..16fa5a096206 --- /dev/null +++ b/Documentation/devicetree/bindings/pwm/pwm-sprd.txt | |||
@@ -0,0 +1,40 @@ | |||
1 | Spreadtrum PWM controller | ||
2 | |||
3 | Spreadtrum SoCs PWM controller provides 4 PWM channels. | ||
4 | |||
5 | Required properties: | ||
6 | - compatible : Should be "sprd,ums512-pwm". | ||
7 | - reg: Physical base address and length of the controller's registers. | ||
8 | - clocks: The phandle and specifier referencing the controller's clocks. | ||
9 | - clock-names: Should contain following entries: | ||
10 | "pwmn": used to derive the functional clock for PWM channel n (n range: 0 ~ 3). | ||
11 | "enablen": for PWM channel n enable clock (n range: 0 ~ 3). | ||
12 | - #pwm-cells: Should be 2. See pwm.txt in this directory for a description of | ||
13 | the cells format. | ||
14 | |||
15 | Optional properties: | ||
16 | - assigned-clocks: Reference to the PWM clock entries. | ||
17 | - assigned-clock-parents: The phandle of the parent clock of PWM clock. | ||
18 | |||
19 | Example: | ||
20 | pwms: pwm@32260000 { | ||
21 | compatible = "sprd,ums512-pwm"; | ||
22 | reg = <0 0x32260000 0 0x10000>; | ||
23 | clock-names = "pwm0", "enable0", | ||
24 | "pwm1", "enable1", | ||
25 | "pwm2", "enable2", | ||
26 | "pwm3", "enable3"; | ||
27 | clocks = <&aon_clk CLK_PWM0>, <&aonapb_gate CLK_PWM0_EB>, | ||
28 | <&aon_clk CLK_PWM1>, <&aonapb_gate CLK_PWM1_EB>, | ||
29 | <&aon_clk CLK_PWM2>, <&aonapb_gate CLK_PWM2_EB>, | ||
30 | <&aon_clk CLK_PWM3>, <&aonapb_gate CLK_PWM3_EB>; | ||
31 | assigned-clocks = <&aon_clk CLK_PWM0>, | ||
32 | <&aon_clk CLK_PWM1>, | ||
33 | <&aon_clk CLK_PWM2>, | ||
34 | <&aon_clk CLK_PWM3>; | ||
35 | assigned-clock-parents = <&ext_26m>, | ||
36 | <&ext_26m>, | ||
37 | <&ext_26m>, | ||
38 | <&ext_26m>; | ||
39 | #pwm-cells = <2>; | ||
40 | }; | ||
diff --git a/MAINTAINERS b/MAINTAINERS index ee3971d8d335..f6ff76864649 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -13246,9 +13246,11 @@ F: drivers/media/rc/pwm-ir-tx.c | |||
13246 | 13246 | ||
13247 | PWM SUBSYSTEM | 13247 | PWM SUBSYSTEM |
13248 | M: Thierry Reding <thierry.reding@gmail.com> | 13248 | M: Thierry Reding <thierry.reding@gmail.com> |
13249 | R: Uwe Kleine-König <u.kleine-koenig@pengutronix.de> | ||
13249 | L: linux-pwm@vger.kernel.org | 13250 | L: linux-pwm@vger.kernel.org |
13250 | S: Maintained | 13251 | S: Maintained |
13251 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/thierry.reding/linux-pwm.git | 13252 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/thierry.reding/linux-pwm.git |
13253 | Q: https://patchwork.ozlabs.org/project/linux-pwm/list/ | ||
13252 | F: Documentation/driver-api/pwm.rst | 13254 | F: Documentation/driver-api/pwm.rst |
13253 | F: Documentation/devicetree/bindings/pwm/ | 13255 | F: Documentation/devicetree/bindings/pwm/ |
13254 | F: include/linux/pwm.h | 13256 | F: include/linux/pwm.h |
@@ -13257,6 +13259,7 @@ F: drivers/video/backlight/pwm_bl.c | |||
13257 | F: include/linux/pwm_backlight.h | 13259 | F: include/linux/pwm_backlight.h |
13258 | F: drivers/gpio/gpio-mvebu.c | 13260 | F: drivers/gpio/gpio-mvebu.c |
13259 | F: Documentation/devicetree/bindings/gpio/gpio-mvebu.txt | 13261 | F: Documentation/devicetree/bindings/gpio/gpio-mvebu.txt |
13262 | K: pwm_(config|apply_state|ops) | ||
13260 | 13263 | ||
13261 | PXA GPIO DRIVER | 13264 | PXA GPIO DRIVER |
13262 | M: Robert Jarzmik <robert.jarzmik@free.fr> | 13265 | M: Robert Jarzmik <robert.jarzmik@free.fr> |
diff --git a/drivers/gpio/gpio-mvebu.c b/drivers/gpio/gpio-mvebu.c index 869d47f89599..6c0687694341 100644 --- a/drivers/gpio/gpio-mvebu.c +++ b/drivers/gpio/gpio-mvebu.c | |||
@@ -694,7 +694,7 @@ static void mvebu_pwm_get_state(struct pwm_chip *chip, | |||
694 | } | 694 | } |
695 | 695 | ||
696 | static int mvebu_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, | 696 | static int mvebu_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, |
697 | struct pwm_state *state) | 697 | const struct pwm_state *state) |
698 | { | 698 | { |
699 | struct mvebu_pwm *mvpwm = to_mvebu_pwm(chip); | 699 | struct mvebu_pwm *mvpwm = to_mvebu_pwm(chip); |
700 | struct mvebu_gpio_chip *mvchip = mvpwm->mvchip; | 700 | struct mvebu_gpio_chip *mvchip = mvpwm->mvchip; |
diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig index b0e632ba8590..e3a2518503ed 100644 --- a/drivers/pwm/Kconfig +++ b/drivers/pwm/Kconfig | |||
@@ -44,7 +44,7 @@ config PWM_AB8500 | |||
44 | 44 | ||
45 | config PWM_ATMEL | 45 | config PWM_ATMEL |
46 | tristate "Atmel PWM support" | 46 | tristate "Atmel PWM support" |
47 | depends on ARCH_AT91 | 47 | depends on ARCH_AT91 && OF |
48 | help | 48 | help |
49 | Generic PWM framework driver for Atmel SoC. | 49 | Generic PWM framework driver for Atmel SoC. |
50 | 50 | ||
@@ -423,6 +423,17 @@ config PWM_SPEAR | |||
423 | To compile this driver as a module, choose M here: the module | 423 | To compile this driver as a module, choose M here: the module |
424 | will be called pwm-spear. | 424 | will be called pwm-spear. |
425 | 425 | ||
426 | config PWM_SPRD | ||
427 | tristate "Spreadtrum PWM support" | ||
428 | depends on ARCH_SPRD || COMPILE_TEST | ||
429 | depends on HAS_IOMEM | ||
430 | help | ||
431 | Generic PWM framework driver for the PWM controller on | ||
432 | Spreadtrum SoCs. | ||
433 | |||
434 | To compile this driver as a module, choose M here: the module | ||
435 | will be called pwm-sprd. | ||
436 | |||
426 | config PWM_STI | 437 | config PWM_STI |
427 | tristate "STiH4xx PWM support" | 438 | tristate "STiH4xx PWM support" |
428 | depends on ARCH_STI | 439 | depends on ARCH_STI |
diff --git a/drivers/pwm/Makefile b/drivers/pwm/Makefile index 76b555b51887..26326adf71d7 100644 --- a/drivers/pwm/Makefile +++ b/drivers/pwm/Makefile | |||
@@ -41,6 +41,7 @@ obj-$(CONFIG_PWM_ROCKCHIP) += pwm-rockchip.o | |||
41 | obj-$(CONFIG_PWM_SAMSUNG) += pwm-samsung.o | 41 | obj-$(CONFIG_PWM_SAMSUNG) += pwm-samsung.o |
42 | obj-$(CONFIG_PWM_SIFIVE) += pwm-sifive.o | 42 | obj-$(CONFIG_PWM_SIFIVE) += pwm-sifive.o |
43 | obj-$(CONFIG_PWM_SPEAR) += pwm-spear.o | 43 | obj-$(CONFIG_PWM_SPEAR) += pwm-spear.o |
44 | obj-$(CONFIG_PWM_SPRD) += pwm-sprd.o | ||
44 | obj-$(CONFIG_PWM_STI) += pwm-sti.o | 45 | obj-$(CONFIG_PWM_STI) += pwm-sti.o |
45 | obj-$(CONFIG_PWM_STM32) += pwm-stm32.o | 46 | obj-$(CONFIG_PWM_STM32) += pwm-stm32.o |
46 | obj-$(CONFIG_PWM_STM32_LP) += pwm-stm32-lp.o | 47 | obj-$(CONFIG_PWM_STM32_LP) += pwm-stm32-lp.o |
diff --git a/drivers/pwm/core.c b/drivers/pwm/core.c index 8edfac17364e..6ad51aa60c03 100644 --- a/drivers/pwm/core.c +++ b/drivers/pwm/core.c | |||
@@ -448,36 +448,44 @@ EXPORT_SYMBOL_GPL(pwm_free); | |||
448 | /** | 448 | /** |
449 | * pwm_apply_state() - atomically apply a new state to a PWM device | 449 | * pwm_apply_state() - atomically apply a new state to a PWM device |
450 | * @pwm: PWM device | 450 | * @pwm: PWM device |
451 | * @state: new state to apply. This can be adjusted by the PWM driver | 451 | * @state: new state to apply |
452 | * if the requested config is not achievable, for example, | ||
453 | * ->duty_cycle and ->period might be approximated. | ||
454 | */ | 452 | */ |
455 | int pwm_apply_state(struct pwm_device *pwm, struct pwm_state *state) | 453 | int pwm_apply_state(struct pwm_device *pwm, const struct pwm_state *state) |
456 | { | 454 | { |
455 | struct pwm_chip *chip; | ||
457 | int err; | 456 | int err; |
458 | 457 | ||
459 | if (!pwm || !state || !state->period || | 458 | if (!pwm || !state || !state->period || |
460 | state->duty_cycle > state->period) | 459 | state->duty_cycle > state->period) |
461 | return -EINVAL; | 460 | return -EINVAL; |
462 | 461 | ||
462 | chip = pwm->chip; | ||
463 | |||
463 | if (state->period == pwm->state.period && | 464 | if (state->period == pwm->state.period && |
464 | state->duty_cycle == pwm->state.duty_cycle && | 465 | state->duty_cycle == pwm->state.duty_cycle && |
465 | state->polarity == pwm->state.polarity && | 466 | state->polarity == pwm->state.polarity && |
466 | state->enabled == pwm->state.enabled) | 467 | state->enabled == pwm->state.enabled) |
467 | return 0; | 468 | return 0; |
468 | 469 | ||
469 | if (pwm->chip->ops->apply) { | 470 | if (chip->ops->apply) { |
470 | err = pwm->chip->ops->apply(pwm->chip, pwm, state); | 471 | err = chip->ops->apply(chip, pwm, state); |
471 | if (err) | 472 | if (err) |
472 | return err; | 473 | return err; |
473 | 474 | ||
474 | pwm->state = *state; | 475 | /* |
476 | * .apply might have to round some values in *state, if possible | ||
477 | * read the actually implemented value back. | ||
478 | */ | ||
479 | if (chip->ops->get_state) | ||
480 | chip->ops->get_state(chip, pwm, &pwm->state); | ||
481 | else | ||
482 | pwm->state = *state; | ||
475 | } else { | 483 | } else { |
476 | /* | 484 | /* |
477 | * FIXME: restore the initial state in case of error. | 485 | * FIXME: restore the initial state in case of error. |
478 | */ | 486 | */ |
479 | if (state->polarity != pwm->state.polarity) { | 487 | if (state->polarity != pwm->state.polarity) { |
480 | if (!pwm->chip->ops->set_polarity) | 488 | if (!chip->ops->set_polarity) |
481 | return -ENOTSUPP; | 489 | return -ENOTSUPP; |
482 | 490 | ||
483 | /* | 491 | /* |
@@ -486,12 +494,12 @@ int pwm_apply_state(struct pwm_device *pwm, struct pwm_state *state) | |||
486 | * ->apply(). | 494 | * ->apply(). |
487 | */ | 495 | */ |
488 | if (pwm->state.enabled) { | 496 | if (pwm->state.enabled) { |
489 | pwm->chip->ops->disable(pwm->chip, pwm); | 497 | chip->ops->disable(chip, pwm); |
490 | pwm->state.enabled = false; | 498 | pwm->state.enabled = false; |
491 | } | 499 | } |
492 | 500 | ||
493 | err = pwm->chip->ops->set_polarity(pwm->chip, pwm, | 501 | err = chip->ops->set_polarity(chip, pwm, |
494 | state->polarity); | 502 | state->polarity); |
495 | if (err) | 503 | if (err) |
496 | return err; | 504 | return err; |
497 | 505 | ||
@@ -500,9 +508,9 @@ int pwm_apply_state(struct pwm_device *pwm, struct pwm_state *state) | |||
500 | 508 | ||
501 | if (state->period != pwm->state.period || | 509 | if (state->period != pwm->state.period || |
502 | state->duty_cycle != pwm->state.duty_cycle) { | 510 | state->duty_cycle != pwm->state.duty_cycle) { |
503 | err = pwm->chip->ops->config(pwm->chip, pwm, | 511 | err = chip->ops->config(pwm->chip, pwm, |
504 | state->duty_cycle, | 512 | state->duty_cycle, |
505 | state->period); | 513 | state->period); |
506 | if (err) | 514 | if (err) |
507 | return err; | 515 | return err; |
508 | 516 | ||
@@ -512,11 +520,11 @@ int pwm_apply_state(struct pwm_device *pwm, struct pwm_state *state) | |||
512 | 520 | ||
513 | if (state->enabled != pwm->state.enabled) { | 521 | if (state->enabled != pwm->state.enabled) { |
514 | if (state->enabled) { | 522 | if (state->enabled) { |
515 | err = pwm->chip->ops->enable(pwm->chip, pwm); | 523 | err = chip->ops->enable(chip, pwm); |
516 | if (err) | 524 | if (err) |
517 | return err; | 525 | return err; |
518 | } else { | 526 | } else { |
519 | pwm->chip->ops->disable(pwm->chip, pwm); | 527 | chip->ops->disable(chip, pwm); |
520 | } | 528 | } |
521 | 529 | ||
522 | pwm->state.enabled = state->enabled; | 530 | pwm->state.enabled = state->enabled; |
diff --git a/drivers/pwm/pwm-atmel-hlcdc.c b/drivers/pwm/pwm-atmel-hlcdc.c index d13a83f430ac..dcbc0489dfd4 100644 --- a/drivers/pwm/pwm-atmel-hlcdc.c +++ b/drivers/pwm/pwm-atmel-hlcdc.c | |||
@@ -39,7 +39,7 @@ static inline struct atmel_hlcdc_pwm *to_atmel_hlcdc_pwm(struct pwm_chip *chip) | |||
39 | } | 39 | } |
40 | 40 | ||
41 | static int atmel_hlcdc_pwm_apply(struct pwm_chip *c, struct pwm_device *pwm, | 41 | static int atmel_hlcdc_pwm_apply(struct pwm_chip *c, struct pwm_device *pwm, |
42 | struct pwm_state *state) | 42 | const struct pwm_state *state) |
43 | { | 43 | { |
44 | struct atmel_hlcdc_pwm *chip = to_atmel_hlcdc_pwm(c); | 44 | struct atmel_hlcdc_pwm *chip = to_atmel_hlcdc_pwm(c); |
45 | struct atmel_hlcdc *hlcdc = chip->hlcdc; | 45 | struct atmel_hlcdc *hlcdc = chip->hlcdc; |
diff --git a/drivers/pwm/pwm-atmel.c b/drivers/pwm/pwm-atmel.c index e5e1eaf372fa..9ba733467e26 100644 --- a/drivers/pwm/pwm-atmel.c +++ b/drivers/pwm/pwm-atmel.c | |||
@@ -209,7 +209,7 @@ static void atmel_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm, | |||
209 | } | 209 | } |
210 | 210 | ||
211 | static int atmel_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, | 211 | static int atmel_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, |
212 | struct pwm_state *state) | 212 | const struct pwm_state *state) |
213 | { | 213 | { |
214 | struct atmel_pwm_chip *atmel_pwm = to_atmel_pwm_chip(chip); | 214 | struct atmel_pwm_chip *atmel_pwm = to_atmel_pwm_chip(chip); |
215 | struct pwm_state cstate; | 215 | struct pwm_state cstate; |
@@ -318,19 +318,6 @@ static const struct atmel_pwm_data mchp_sam9x60_pwm_data = { | |||
318 | }, | 318 | }, |
319 | }; | 319 | }; |
320 | 320 | ||
321 | static const struct platform_device_id atmel_pwm_devtypes[] = { | ||
322 | { | ||
323 | .name = "at91sam9rl-pwm", | ||
324 | .driver_data = (kernel_ulong_t)&atmel_sam9rl_pwm_data, | ||
325 | }, { | ||
326 | .name = "sama5d3-pwm", | ||
327 | .driver_data = (kernel_ulong_t)&atmel_sama5_pwm_data, | ||
328 | }, { | ||
329 | /* sentinel */ | ||
330 | }, | ||
331 | }; | ||
332 | MODULE_DEVICE_TABLE(platform, atmel_pwm_devtypes); | ||
333 | |||
334 | static const struct of_device_id atmel_pwm_dt_ids[] = { | 321 | static const struct of_device_id atmel_pwm_dt_ids[] = { |
335 | { | 322 | { |
336 | .compatible = "atmel,at91sam9rl-pwm", | 323 | .compatible = "atmel,at91sam9rl-pwm", |
@@ -350,34 +337,20 @@ static const struct of_device_id atmel_pwm_dt_ids[] = { | |||
350 | }; | 337 | }; |
351 | MODULE_DEVICE_TABLE(of, atmel_pwm_dt_ids); | 338 | MODULE_DEVICE_TABLE(of, atmel_pwm_dt_ids); |
352 | 339 | ||
353 | static inline const struct atmel_pwm_data * | ||
354 | atmel_pwm_get_driver_data(struct platform_device *pdev) | ||
355 | { | ||
356 | const struct platform_device_id *id; | ||
357 | |||
358 | if (pdev->dev.of_node) | ||
359 | return of_device_get_match_data(&pdev->dev); | ||
360 | |||
361 | id = platform_get_device_id(pdev); | ||
362 | |||
363 | return (struct atmel_pwm_data *)id->driver_data; | ||
364 | } | ||
365 | |||
366 | static int atmel_pwm_probe(struct platform_device *pdev) | 340 | static int atmel_pwm_probe(struct platform_device *pdev) |
367 | { | 341 | { |
368 | const struct atmel_pwm_data *data; | ||
369 | struct atmel_pwm_chip *atmel_pwm; | 342 | struct atmel_pwm_chip *atmel_pwm; |
370 | struct resource *res; | 343 | struct resource *res; |
371 | int ret; | 344 | int ret; |
372 | 345 | ||
373 | data = atmel_pwm_get_driver_data(pdev); | ||
374 | if (!data) | ||
375 | return -ENODEV; | ||
376 | |||
377 | atmel_pwm = devm_kzalloc(&pdev->dev, sizeof(*atmel_pwm), GFP_KERNEL); | 346 | atmel_pwm = devm_kzalloc(&pdev->dev, sizeof(*atmel_pwm), GFP_KERNEL); |
378 | if (!atmel_pwm) | 347 | if (!atmel_pwm) |
379 | return -ENOMEM; | 348 | return -ENOMEM; |
380 | 349 | ||
350 | mutex_init(&atmel_pwm->isr_lock); | ||
351 | atmel_pwm->data = of_device_get_match_data(&pdev->dev); | ||
352 | atmel_pwm->updated_pwms = 0; | ||
353 | |||
381 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 354 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
382 | atmel_pwm->base = devm_ioremap_resource(&pdev->dev, res); | 355 | atmel_pwm->base = devm_ioremap_resource(&pdev->dev, res); |
383 | if (IS_ERR(atmel_pwm->base)) | 356 | if (IS_ERR(atmel_pwm->base)) |
@@ -395,17 +368,10 @@ static int atmel_pwm_probe(struct platform_device *pdev) | |||
395 | 368 | ||
396 | atmel_pwm->chip.dev = &pdev->dev; | 369 | atmel_pwm->chip.dev = &pdev->dev; |
397 | atmel_pwm->chip.ops = &atmel_pwm_ops; | 370 | atmel_pwm->chip.ops = &atmel_pwm_ops; |
398 | 371 | atmel_pwm->chip.of_xlate = of_pwm_xlate_with_flags; | |
399 | if (pdev->dev.of_node) { | 372 | atmel_pwm->chip.of_pwm_n_cells = 3; |
400 | atmel_pwm->chip.of_xlate = of_pwm_xlate_with_flags; | ||
401 | atmel_pwm->chip.of_pwm_n_cells = 3; | ||
402 | } | ||
403 | |||
404 | atmel_pwm->chip.base = -1; | 373 | atmel_pwm->chip.base = -1; |
405 | atmel_pwm->chip.npwm = 4; | 374 | atmel_pwm->chip.npwm = 4; |
406 | atmel_pwm->data = data; | ||
407 | atmel_pwm->updated_pwms = 0; | ||
408 | mutex_init(&atmel_pwm->isr_lock); | ||
409 | 375 | ||
410 | ret = pwmchip_add(&atmel_pwm->chip); | 376 | ret = pwmchip_add(&atmel_pwm->chip); |
411 | if (ret < 0) { | 377 | if (ret < 0) { |
@@ -437,7 +403,6 @@ static struct platform_driver atmel_pwm_driver = { | |||
437 | .name = "atmel-pwm", | 403 | .name = "atmel-pwm", |
438 | .of_match_table = of_match_ptr(atmel_pwm_dt_ids), | 404 | .of_match_table = of_match_ptr(atmel_pwm_dt_ids), |
439 | }, | 405 | }, |
440 | .id_table = atmel_pwm_devtypes, | ||
441 | .probe = atmel_pwm_probe, | 406 | .probe = atmel_pwm_probe, |
442 | .remove = atmel_pwm_remove, | 407 | .remove = atmel_pwm_remove, |
443 | }; | 408 | }; |
diff --git a/drivers/pwm/pwm-bcm-iproc.c b/drivers/pwm/pwm-bcm-iproc.c index d961a8207b1c..56c38cfae92c 100644 --- a/drivers/pwm/pwm-bcm-iproc.c +++ b/drivers/pwm/pwm-bcm-iproc.c | |||
@@ -115,7 +115,7 @@ static void iproc_pwmc_get_state(struct pwm_chip *chip, struct pwm_device *pwm, | |||
115 | } | 115 | } |
116 | 116 | ||
117 | static int iproc_pwmc_apply(struct pwm_chip *chip, struct pwm_device *pwm, | 117 | static int iproc_pwmc_apply(struct pwm_chip *chip, struct pwm_device *pwm, |
118 | struct pwm_state *state) | 118 | const struct pwm_state *state) |
119 | { | 119 | { |
120 | unsigned long prescale = IPROC_PWM_PRESCALE_MIN; | 120 | unsigned long prescale = IPROC_PWM_PRESCALE_MIN; |
121 | struct iproc_pwmc *ip = to_iproc_pwmc(chip); | 121 | struct iproc_pwmc *ip = to_iproc_pwmc(chip); |
diff --git a/drivers/pwm/pwm-bcm2835.c b/drivers/pwm/pwm-bcm2835.c index f6fe0b922e1e..91e24f01b54e 100644 --- a/drivers/pwm/pwm-bcm2835.c +++ b/drivers/pwm/pwm-bcm2835.c | |||
@@ -21,7 +21,7 @@ | |||
21 | #define PERIOD(x) (((x) * 0x10) + 0x10) | 21 | #define PERIOD(x) (((x) * 0x10) + 0x10) |
22 | #define DUTY(x) (((x) * 0x10) + 0x14) | 22 | #define DUTY(x) (((x) * 0x10) + 0x14) |
23 | 23 | ||
24 | #define MIN_PERIOD 108 /* 9.2 MHz max. PWM clock */ | 24 | #define PERIOD_MIN 0x2 |
25 | 25 | ||
26 | struct bcm2835_pwm { | 26 | struct bcm2835_pwm { |
27 | struct pwm_chip chip; | 27 | struct pwm_chip chip; |
@@ -64,6 +64,7 @@ static int bcm2835_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, | |||
64 | struct bcm2835_pwm *pc = to_bcm2835_pwm(chip); | 64 | struct bcm2835_pwm *pc = to_bcm2835_pwm(chip); |
65 | unsigned long rate = clk_get_rate(pc->clk); | 65 | unsigned long rate = clk_get_rate(pc->clk); |
66 | unsigned long scaler; | 66 | unsigned long scaler; |
67 | u32 period; | ||
67 | 68 | ||
68 | if (!rate) { | 69 | if (!rate) { |
69 | dev_err(pc->dev, "failed to get clock rate\n"); | 70 | dev_err(pc->dev, "failed to get clock rate\n"); |
@@ -71,17 +72,14 @@ static int bcm2835_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, | |||
71 | } | 72 | } |
72 | 73 | ||
73 | scaler = DIV_ROUND_CLOSEST(NSEC_PER_SEC, rate); | 74 | scaler = DIV_ROUND_CLOSEST(NSEC_PER_SEC, rate); |
75 | period = DIV_ROUND_CLOSEST(period_ns, scaler); | ||
74 | 76 | ||
75 | if (period_ns <= MIN_PERIOD) { | 77 | if (period < PERIOD_MIN) |
76 | dev_err(pc->dev, "period %d not supported, minimum %d\n", | ||
77 | period_ns, MIN_PERIOD); | ||
78 | return -EINVAL; | 78 | return -EINVAL; |
79 | } | ||
80 | 79 | ||
81 | writel(DIV_ROUND_CLOSEST(duty_ns, scaler), | 80 | writel(DIV_ROUND_CLOSEST(duty_ns, scaler), |
82 | pc->base + DUTY(pwm->hwpwm)); | 81 | pc->base + DUTY(pwm->hwpwm)); |
83 | writel(DIV_ROUND_CLOSEST(period_ns, scaler), | 82 | writel(period, pc->base + PERIOD(pwm->hwpwm)); |
84 | pc->base + PERIOD(pwm->hwpwm)); | ||
85 | 83 | ||
86 | return 0; | 84 | return 0; |
87 | } | 85 | } |
@@ -155,8 +153,11 @@ static int bcm2835_pwm_probe(struct platform_device *pdev) | |||
155 | 153 | ||
156 | pc->clk = devm_clk_get(&pdev->dev, NULL); | 154 | pc->clk = devm_clk_get(&pdev->dev, NULL); |
157 | if (IS_ERR(pc->clk)) { | 155 | if (IS_ERR(pc->clk)) { |
158 | dev_err(&pdev->dev, "clock not found: %ld\n", PTR_ERR(pc->clk)); | 156 | ret = PTR_ERR(pc->clk); |
159 | return PTR_ERR(pc->clk); | 157 | if (ret != -EPROBE_DEFER) |
158 | dev_err(&pdev->dev, "clock not found: %d\n", ret); | ||
159 | |||
160 | return ret; | ||
160 | } | 161 | } |
161 | 162 | ||
162 | ret = clk_prepare_enable(pc->clk); | 163 | ret = clk_prepare_enable(pc->clk); |
diff --git a/drivers/pwm/pwm-cros-ec.c b/drivers/pwm/pwm-cros-ec.c index 85bea2d40b7d..89497448d217 100644 --- a/drivers/pwm/pwm-cros-ec.c +++ b/drivers/pwm/pwm-cros-ec.c | |||
@@ -93,7 +93,7 @@ static int cros_ec_pwm_get_duty(struct cros_ec_device *ec, u8 index) | |||
93 | } | 93 | } |
94 | 94 | ||
95 | static int cros_ec_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, | 95 | static int cros_ec_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, |
96 | struct pwm_state *state) | 96 | const struct pwm_state *state) |
97 | { | 97 | { |
98 | struct cros_ec_pwm_device *ec_pwm = pwm_to_cros_ec_pwm(chip); | 98 | struct cros_ec_pwm_device *ec_pwm = pwm_to_cros_ec_pwm(chip); |
99 | int duty_cycle; | 99 | int duty_cycle; |
diff --git a/drivers/pwm/pwm-fsl-ftm.c b/drivers/pwm/pwm-fsl-ftm.c index 9d31a217111d..59272a920479 100644 --- a/drivers/pwm/pwm-fsl-ftm.c +++ b/drivers/pwm/pwm-fsl-ftm.c | |||
@@ -227,7 +227,7 @@ static bool fsl_pwm_is_other_pwm_enabled(struct fsl_pwm_chip *fpc, | |||
227 | 227 | ||
228 | static int fsl_pwm_apply_config(struct fsl_pwm_chip *fpc, | 228 | static int fsl_pwm_apply_config(struct fsl_pwm_chip *fpc, |
229 | struct pwm_device *pwm, | 229 | struct pwm_device *pwm, |
230 | struct pwm_state *newstate) | 230 | const struct pwm_state *newstate) |
231 | { | 231 | { |
232 | unsigned int duty; | 232 | unsigned int duty; |
233 | u32 reg_polarity; | 233 | u32 reg_polarity; |
@@ -292,17 +292,13 @@ static int fsl_pwm_apply_config(struct fsl_pwm_chip *fpc, | |||
292 | 292 | ||
293 | regmap_update_bits(fpc->regmap, FTM_POL, BIT(pwm->hwpwm), reg_polarity); | 293 | regmap_update_bits(fpc->regmap, FTM_POL, BIT(pwm->hwpwm), reg_polarity); |
294 | 294 | ||
295 | newstate->period = fsl_pwm_ticks_to_ns(fpc, | ||
296 | fpc->period.mod_period + 1); | ||
297 | newstate->duty_cycle = fsl_pwm_ticks_to_ns(fpc, duty); | ||
298 | |||
299 | ftm_set_write_protection(fpc); | 295 | ftm_set_write_protection(fpc); |
300 | 296 | ||
301 | return 0; | 297 | return 0; |
302 | } | 298 | } |
303 | 299 | ||
304 | static int fsl_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, | 300 | static int fsl_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, |
305 | struct pwm_state *newstate) | 301 | const struct pwm_state *newstate) |
306 | { | 302 | { |
307 | struct fsl_pwm_chip *fpc = to_fsl_chip(chip); | 303 | struct fsl_pwm_chip *fpc = to_fsl_chip(chip); |
308 | struct pwm_state *oldstate = &pwm->state; | 304 | struct pwm_state *oldstate = &pwm->state; |
diff --git a/drivers/pwm/pwm-hibvt.c b/drivers/pwm/pwm-hibvt.c index 753bd58111e4..ad205fdad372 100644 --- a/drivers/pwm/pwm-hibvt.c +++ b/drivers/pwm/pwm-hibvt.c | |||
@@ -149,7 +149,7 @@ static void hibvt_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm, | |||
149 | } | 149 | } |
150 | 150 | ||
151 | static int hibvt_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, | 151 | static int hibvt_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, |
152 | struct pwm_state *state) | 152 | const struct pwm_state *state) |
153 | { | 153 | { |
154 | struct hibvt_pwm_chip *hi_pwm_chip = to_hibvt_pwm_chip(chip); | 154 | struct hibvt_pwm_chip *hi_pwm_chip = to_hibvt_pwm_chip(chip); |
155 | 155 | ||
diff --git a/drivers/pwm/pwm-imx-tpm.c b/drivers/pwm/pwm-imx-tpm.c index e8385c1cf342..9145f6160649 100644 --- a/drivers/pwm/pwm-imx-tpm.c +++ b/drivers/pwm/pwm-imx-tpm.c | |||
@@ -89,7 +89,7 @@ to_imx_tpm_pwm_chip(struct pwm_chip *chip) | |||
89 | static int pwm_imx_tpm_round_state(struct pwm_chip *chip, | 89 | static int pwm_imx_tpm_round_state(struct pwm_chip *chip, |
90 | struct imx_tpm_pwm_param *p, | 90 | struct imx_tpm_pwm_param *p, |
91 | struct pwm_state *real_state, | 91 | struct pwm_state *real_state, |
92 | struct pwm_state *state) | 92 | const struct pwm_state *state) |
93 | { | 93 | { |
94 | struct imx_tpm_pwm_chip *tpm = to_imx_tpm_pwm_chip(chip); | 94 | struct imx_tpm_pwm_chip *tpm = to_imx_tpm_pwm_chip(chip); |
95 | u32 rate, prescale, period_count, clock_unit; | 95 | u32 rate, prescale, period_count, clock_unit; |
@@ -289,7 +289,7 @@ static int pwm_imx_tpm_apply_hw(struct pwm_chip *chip, | |||
289 | 289 | ||
290 | static int pwm_imx_tpm_apply(struct pwm_chip *chip, | 290 | static int pwm_imx_tpm_apply(struct pwm_chip *chip, |
291 | struct pwm_device *pwm, | 291 | struct pwm_device *pwm, |
292 | struct pwm_state *state) | 292 | const struct pwm_state *state) |
293 | { | 293 | { |
294 | struct imx_tpm_pwm_chip *tpm = to_imx_tpm_pwm_chip(chip); | 294 | struct imx_tpm_pwm_chip *tpm = to_imx_tpm_pwm_chip(chip); |
295 | struct imx_tpm_pwm_param param; | 295 | struct imx_tpm_pwm_param param; |
diff --git a/drivers/pwm/pwm-imx27.c b/drivers/pwm/pwm-imx27.c index 434a351fb626..ae11d8577f18 100644 --- a/drivers/pwm/pwm-imx27.c +++ b/drivers/pwm/pwm-imx27.c | |||
@@ -3,6 +3,10 @@ | |||
3 | * simple driver for PWM (Pulse Width Modulator) controller | 3 | * simple driver for PWM (Pulse Width Modulator) controller |
4 | * | 4 | * |
5 | * Derived from pxa PWM driver by eric miao <eric.miao@marvell.com> | 5 | * Derived from pxa PWM driver by eric miao <eric.miao@marvell.com> |
6 | * | ||
7 | * Limitations: | ||
8 | * - When disabled the output is driven to 0 independent of the configured | ||
9 | * polarity. | ||
6 | */ | 10 | */ |
7 | 11 | ||
8 | #include <linux/bitfield.h> | 12 | #include <linux/bitfield.h> |
@@ -205,7 +209,7 @@ static void pwm_imx27_wait_fifo_slot(struct pwm_chip *chip, | |||
205 | } | 209 | } |
206 | 210 | ||
207 | static int pwm_imx27_apply(struct pwm_chip *chip, struct pwm_device *pwm, | 211 | static int pwm_imx27_apply(struct pwm_chip *chip, struct pwm_device *pwm, |
208 | struct pwm_state *state) | 212 | const struct pwm_state *state) |
209 | { | 213 | { |
210 | unsigned long period_cycles, duty_cycles, prescale; | 214 | unsigned long period_cycles, duty_cycles, prescale; |
211 | struct pwm_imx27_chip *imx = to_pwm_imx27_chip(chip); | 215 | struct pwm_imx27_chip *imx = to_pwm_imx27_chip(chip); |
diff --git a/drivers/pwm/pwm-jz4740.c b/drivers/pwm/pwm-jz4740.c index f901e8a0d33d..9d78cc21cb12 100644 --- a/drivers/pwm/pwm-jz4740.c +++ b/drivers/pwm/pwm-jz4740.c | |||
@@ -2,6 +2,11 @@ | |||
2 | /* | 2 | /* |
3 | * Copyright (C) 2010, Lars-Peter Clausen <lars@metafoo.de> | 3 | * Copyright (C) 2010, Lars-Peter Clausen <lars@metafoo.de> |
4 | * JZ4740 platform PWM support | 4 | * JZ4740 platform PWM support |
5 | * | ||
6 | * Limitations: | ||
7 | * - The .apply callback doesn't complete the currently running period before | ||
8 | * reconfiguring the hardware. | ||
9 | * - Each period starts with the inactive part. | ||
5 | */ | 10 | */ |
6 | 11 | ||
7 | #include <linux/clk.h> | 12 | #include <linux/clk.h> |
@@ -83,7 +88,7 @@ static void jz4740_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm) | |||
83 | } | 88 | } |
84 | 89 | ||
85 | static int jz4740_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, | 90 | static int jz4740_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, |
86 | struct pwm_state *state) | 91 | const struct pwm_state *state) |
87 | { | 92 | { |
88 | struct jz4740_pwm_chip *jz4740 = to_jz4740(pwm->chip); | 93 | struct jz4740_pwm_chip *jz4740 = to_jz4740(pwm->chip); |
89 | unsigned long long tmp; | 94 | unsigned long long tmp; |
diff --git a/drivers/pwm/pwm-lpss.c b/drivers/pwm/pwm-lpss.c index 4098a4601691..75bbfe5f3bc2 100644 --- a/drivers/pwm/pwm-lpss.c +++ b/drivers/pwm/pwm-lpss.c | |||
@@ -122,7 +122,7 @@ static inline void pwm_lpss_cond_enable(struct pwm_device *pwm, bool cond) | |||
122 | } | 122 | } |
123 | 123 | ||
124 | static int pwm_lpss_apply(struct pwm_chip *chip, struct pwm_device *pwm, | 124 | static int pwm_lpss_apply(struct pwm_chip *chip, struct pwm_device *pwm, |
125 | struct pwm_state *state) | 125 | const struct pwm_state *state) |
126 | { | 126 | { |
127 | struct pwm_lpss_chip *lpwm = to_lpwm(chip); | 127 | struct pwm_lpss_chip *lpwm = to_lpwm(chip); |
128 | int ret; | 128 | int ret; |
diff --git a/drivers/pwm/pwm-mediatek.c b/drivers/pwm/pwm-mediatek.c index eb6674ce995f..b94e0d09c300 100644 --- a/drivers/pwm/pwm-mediatek.c +++ b/drivers/pwm/pwm-mediatek.c | |||
@@ -1,12 +1,10 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
1 | /* | 2 | /* |
2 | * Mediatek Pulse Width Modulator driver | 3 | * MediaTek Pulse Width Modulator driver |
3 | * | 4 | * |
4 | * Copyright (C) 2015 John Crispin <blogic@openwrt.org> | 5 | * Copyright (C) 2015 John Crispin <blogic@openwrt.org> |
5 | * Copyright (C) 2017 Zhi Mao <zhi.mao@mediatek.com> | 6 | * Copyright (C) 2017 Zhi Mao <zhi.mao@mediatek.com> |
6 | * | 7 | * |
7 | * This file is licensed under the terms of the GNU General Public | ||
8 | * License version 2. This program is licensed "as is" without any | ||
9 | * warranty of any kind, whether express or implied. | ||
10 | */ | 8 | */ |
11 | 9 | ||
12 | #include <linux/err.h> | 10 | #include <linux/err.h> |
@@ -35,125 +33,107 @@ | |||
35 | 33 | ||
36 | #define PWM_CLK_DIV_MAX 7 | 34 | #define PWM_CLK_DIV_MAX 7 |
37 | 35 | ||
38 | enum { | 36 | struct pwm_mediatek_of_data { |
39 | MTK_CLK_MAIN = 0, | ||
40 | MTK_CLK_TOP, | ||
41 | MTK_CLK_PWM1, | ||
42 | MTK_CLK_PWM2, | ||
43 | MTK_CLK_PWM3, | ||
44 | MTK_CLK_PWM4, | ||
45 | MTK_CLK_PWM5, | ||
46 | MTK_CLK_PWM6, | ||
47 | MTK_CLK_PWM7, | ||
48 | MTK_CLK_PWM8, | ||
49 | MTK_CLK_MAX, | ||
50 | }; | ||
51 | |||
52 | static const char * const mtk_pwm_clk_name[MTK_CLK_MAX] = { | ||
53 | "main", "top", "pwm1", "pwm2", "pwm3", "pwm4", "pwm5", "pwm6", "pwm7", | ||
54 | "pwm8" | ||
55 | }; | ||
56 | |||
57 | struct mtk_pwm_platform_data { | ||
58 | unsigned int num_pwms; | 37 | unsigned int num_pwms; |
59 | bool pwm45_fixup; | 38 | bool pwm45_fixup; |
60 | bool has_clks; | ||
61 | }; | 39 | }; |
62 | 40 | ||
63 | /** | 41 | /** |
64 | * struct mtk_pwm_chip - struct representing PWM chip | 42 | * struct pwm_mediatek_chip - struct representing PWM chip |
65 | * @chip: linux PWM chip representation | 43 | * @chip: linux PWM chip representation |
66 | * @regs: base address of PWM chip | 44 | * @regs: base address of PWM chip |
67 | * @clks: list of clocks | 45 | * @clk_top: the top clock generator |
46 | * @clk_main: the clock used by PWM core | ||
47 | * @clk_pwms: the clock used by each PWM channel | ||
48 | * @clk_freq: the fix clock frequency of legacy MIPS SoC | ||
68 | */ | 49 | */ |
69 | struct mtk_pwm_chip { | 50 | struct pwm_mediatek_chip { |
70 | struct pwm_chip chip; | 51 | struct pwm_chip chip; |
71 | void __iomem *regs; | 52 | void __iomem *regs; |
72 | struct clk *clks[MTK_CLK_MAX]; | 53 | struct clk *clk_top; |
73 | const struct mtk_pwm_platform_data *soc; | 54 | struct clk *clk_main; |
55 | struct clk **clk_pwms; | ||
56 | const struct pwm_mediatek_of_data *soc; | ||
74 | }; | 57 | }; |
75 | 58 | ||
76 | static const unsigned int mtk_pwm_reg_offset[] = { | 59 | static const unsigned int pwm_mediatek_reg_offset[] = { |
77 | 0x0010, 0x0050, 0x0090, 0x00d0, 0x0110, 0x0150, 0x0190, 0x0220 | 60 | 0x0010, 0x0050, 0x0090, 0x00d0, 0x0110, 0x0150, 0x0190, 0x0220 |
78 | }; | 61 | }; |
79 | 62 | ||
80 | static inline struct mtk_pwm_chip *to_mtk_pwm_chip(struct pwm_chip *chip) | 63 | static inline struct pwm_mediatek_chip * |
64 | to_pwm_mediatek_chip(struct pwm_chip *chip) | ||
81 | { | 65 | { |
82 | return container_of(chip, struct mtk_pwm_chip, chip); | 66 | return container_of(chip, struct pwm_mediatek_chip, chip); |
83 | } | 67 | } |
84 | 68 | ||
85 | static int mtk_pwm_clk_enable(struct pwm_chip *chip, struct pwm_device *pwm) | 69 | static int pwm_mediatek_clk_enable(struct pwm_chip *chip, |
70 | struct pwm_device *pwm) | ||
86 | { | 71 | { |
87 | struct mtk_pwm_chip *pc = to_mtk_pwm_chip(chip); | 72 | struct pwm_mediatek_chip *pc = to_pwm_mediatek_chip(chip); |
88 | int ret; | 73 | int ret; |
89 | 74 | ||
90 | if (!pc->soc->has_clks) | 75 | ret = clk_prepare_enable(pc->clk_top); |
91 | return 0; | ||
92 | |||
93 | ret = clk_prepare_enable(pc->clks[MTK_CLK_TOP]); | ||
94 | if (ret < 0) | 76 | if (ret < 0) |
95 | return ret; | 77 | return ret; |
96 | 78 | ||
97 | ret = clk_prepare_enable(pc->clks[MTK_CLK_MAIN]); | 79 | ret = clk_prepare_enable(pc->clk_main); |
98 | if (ret < 0) | 80 | if (ret < 0) |
99 | goto disable_clk_top; | 81 | goto disable_clk_top; |
100 | 82 | ||
101 | ret = clk_prepare_enable(pc->clks[MTK_CLK_PWM1 + pwm->hwpwm]); | 83 | ret = clk_prepare_enable(pc->clk_pwms[pwm->hwpwm]); |
102 | if (ret < 0) | 84 | if (ret < 0) |
103 | goto disable_clk_main; | 85 | goto disable_clk_main; |
104 | 86 | ||
105 | return 0; | 87 | return 0; |
106 | 88 | ||
107 | disable_clk_main: | 89 | disable_clk_main: |
108 | clk_disable_unprepare(pc->clks[MTK_CLK_MAIN]); | 90 | clk_disable_unprepare(pc->clk_main); |
109 | disable_clk_top: | 91 | disable_clk_top: |
110 | clk_disable_unprepare(pc->clks[MTK_CLK_TOP]); | 92 | clk_disable_unprepare(pc->clk_top); |
111 | 93 | ||
112 | return ret; | 94 | return ret; |
113 | } | 95 | } |
114 | 96 | ||
115 | static void mtk_pwm_clk_disable(struct pwm_chip *chip, struct pwm_device *pwm) | 97 | static void pwm_mediatek_clk_disable(struct pwm_chip *chip, |
98 | struct pwm_device *pwm) | ||
116 | { | 99 | { |
117 | struct mtk_pwm_chip *pc = to_mtk_pwm_chip(chip); | 100 | struct pwm_mediatek_chip *pc = to_pwm_mediatek_chip(chip); |
118 | |||
119 | if (!pc->soc->has_clks) | ||
120 | return; | ||
121 | 101 | ||
122 | clk_disable_unprepare(pc->clks[MTK_CLK_PWM1 + pwm->hwpwm]); | 102 | clk_disable_unprepare(pc->clk_pwms[pwm->hwpwm]); |
123 | clk_disable_unprepare(pc->clks[MTK_CLK_MAIN]); | 103 | clk_disable_unprepare(pc->clk_main); |
124 | clk_disable_unprepare(pc->clks[MTK_CLK_TOP]); | 104 | clk_disable_unprepare(pc->clk_top); |
125 | } | 105 | } |
126 | 106 | ||
127 | static inline u32 mtk_pwm_readl(struct mtk_pwm_chip *chip, unsigned int num, | 107 | static inline u32 pwm_mediatek_readl(struct pwm_mediatek_chip *chip, |
128 | unsigned int offset) | 108 | unsigned int num, unsigned int offset) |
129 | { | 109 | { |
130 | return readl(chip->regs + mtk_pwm_reg_offset[num] + offset); | 110 | return readl(chip->regs + pwm_mediatek_reg_offset[num] + offset); |
131 | } | 111 | } |
132 | 112 | ||
133 | static inline void mtk_pwm_writel(struct mtk_pwm_chip *chip, | 113 | static inline void pwm_mediatek_writel(struct pwm_mediatek_chip *chip, |
134 | unsigned int num, unsigned int offset, | 114 | unsigned int num, unsigned int offset, |
135 | u32 value) | 115 | u32 value) |
136 | { | 116 | { |
137 | writel(value, chip->regs + mtk_pwm_reg_offset[num] + offset); | 117 | writel(value, chip->regs + pwm_mediatek_reg_offset[num] + offset); |
138 | } | 118 | } |
139 | 119 | ||
140 | static int mtk_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, | 120 | static int pwm_mediatek_config(struct pwm_chip *chip, struct pwm_device *pwm, |
141 | int duty_ns, int period_ns) | 121 | int duty_ns, int period_ns) |
142 | { | 122 | { |
143 | struct mtk_pwm_chip *pc = to_mtk_pwm_chip(chip); | 123 | struct pwm_mediatek_chip *pc = to_pwm_mediatek_chip(chip); |
144 | struct clk *clk = pc->clks[MTK_CLK_PWM1 + pwm->hwpwm]; | ||
145 | u32 clkdiv = 0, cnt_period, cnt_duty, reg_width = PWMDWIDTH, | 124 | u32 clkdiv = 0, cnt_period, cnt_duty, reg_width = PWMDWIDTH, |
146 | reg_thres = PWMTHRES; | 125 | reg_thres = PWMTHRES; |
147 | u64 resolution; | 126 | u64 resolution; |
148 | int ret; | 127 | int ret; |
149 | 128 | ||
150 | ret = mtk_pwm_clk_enable(chip, pwm); | 129 | ret = pwm_mediatek_clk_enable(chip, pwm); |
130 | |||
151 | if (ret < 0) | 131 | if (ret < 0) |
152 | return ret; | 132 | return ret; |
153 | 133 | ||
154 | /* Using resolution in picosecond gets accuracy higher */ | 134 | /* Using resolution in picosecond gets accuracy higher */ |
155 | resolution = (u64)NSEC_PER_SEC * 1000; | 135 | resolution = (u64)NSEC_PER_SEC * 1000; |
156 | do_div(resolution, clk_get_rate(clk)); | 136 | do_div(resolution, clk_get_rate(pc->clk_pwms[pwm->hwpwm])); |
157 | 137 | ||
158 | cnt_period = DIV_ROUND_CLOSEST_ULL((u64)period_ns * 1000, resolution); | 138 | cnt_period = DIV_ROUND_CLOSEST_ULL((u64)period_ns * 1000, resolution); |
159 | while (cnt_period > 8191) { | 139 | while (cnt_period > 8191) { |
@@ -164,7 +144,7 @@ static int mtk_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, | |||
164 | } | 144 | } |
165 | 145 | ||
166 | if (clkdiv > PWM_CLK_DIV_MAX) { | 146 | if (clkdiv > PWM_CLK_DIV_MAX) { |
167 | mtk_pwm_clk_disable(chip, pwm); | 147 | pwm_mediatek_clk_disable(chip, pwm); |
168 | dev_err(chip->dev, "period %d not supported\n", period_ns); | 148 | dev_err(chip->dev, "period %d not supported\n", period_ns); |
169 | return -EINVAL; | 149 | return -EINVAL; |
170 | } | 150 | } |
@@ -179,22 +159,22 @@ static int mtk_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, | |||
179 | } | 159 | } |
180 | 160 | ||
181 | cnt_duty = DIV_ROUND_CLOSEST_ULL((u64)duty_ns * 1000, resolution); | 161 | cnt_duty = DIV_ROUND_CLOSEST_ULL((u64)duty_ns * 1000, resolution); |
182 | mtk_pwm_writel(pc, pwm->hwpwm, PWMCON, BIT(15) | clkdiv); | 162 | pwm_mediatek_writel(pc, pwm->hwpwm, PWMCON, BIT(15) | clkdiv); |
183 | mtk_pwm_writel(pc, pwm->hwpwm, reg_width, cnt_period); | 163 | pwm_mediatek_writel(pc, pwm->hwpwm, reg_width, cnt_period); |
184 | mtk_pwm_writel(pc, pwm->hwpwm, reg_thres, cnt_duty); | 164 | pwm_mediatek_writel(pc, pwm->hwpwm, reg_thres, cnt_duty); |
185 | 165 | ||
186 | mtk_pwm_clk_disable(chip, pwm); | 166 | pwm_mediatek_clk_disable(chip, pwm); |
187 | 167 | ||
188 | return 0; | 168 | return 0; |
189 | } | 169 | } |
190 | 170 | ||
191 | static int mtk_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm) | 171 | static int pwm_mediatek_enable(struct pwm_chip *chip, struct pwm_device *pwm) |
192 | { | 172 | { |
193 | struct mtk_pwm_chip *pc = to_mtk_pwm_chip(chip); | 173 | struct pwm_mediatek_chip *pc = to_pwm_mediatek_chip(chip); |
194 | u32 value; | 174 | u32 value; |
195 | int ret; | 175 | int ret; |
196 | 176 | ||
197 | ret = mtk_pwm_clk_enable(chip, pwm); | 177 | ret = pwm_mediatek_clk_enable(chip, pwm); |
198 | if (ret < 0) | 178 | if (ret < 0) |
199 | return ret; | 179 | return ret; |
200 | 180 | ||
@@ -205,29 +185,28 @@ static int mtk_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm) | |||
205 | return 0; | 185 | return 0; |
206 | } | 186 | } |
207 | 187 | ||
208 | static void mtk_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm) | 188 | static void pwm_mediatek_disable(struct pwm_chip *chip, struct pwm_device *pwm) |
209 | { | 189 | { |
210 | struct mtk_pwm_chip *pc = to_mtk_pwm_chip(chip); | 190 | struct pwm_mediatek_chip *pc = to_pwm_mediatek_chip(chip); |
211 | u32 value; | 191 | u32 value; |
212 | 192 | ||
213 | value = readl(pc->regs); | 193 | value = readl(pc->regs); |
214 | value &= ~BIT(pwm->hwpwm); | 194 | value &= ~BIT(pwm->hwpwm); |
215 | writel(value, pc->regs); | 195 | writel(value, pc->regs); |
216 | 196 | ||
217 | mtk_pwm_clk_disable(chip, pwm); | 197 | pwm_mediatek_clk_disable(chip, pwm); |
218 | } | 198 | } |
219 | 199 | ||
220 | static const struct pwm_ops mtk_pwm_ops = { | 200 | static const struct pwm_ops pwm_mediatek_ops = { |
221 | .config = mtk_pwm_config, | 201 | .config = pwm_mediatek_config, |
222 | .enable = mtk_pwm_enable, | 202 | .enable = pwm_mediatek_enable, |
223 | .disable = mtk_pwm_disable, | 203 | .disable = pwm_mediatek_disable, |
224 | .owner = THIS_MODULE, | 204 | .owner = THIS_MODULE, |
225 | }; | 205 | }; |
226 | 206 | ||
227 | static int mtk_pwm_probe(struct platform_device *pdev) | 207 | static int pwm_mediatek_probe(struct platform_device *pdev) |
228 | { | 208 | { |
229 | const struct mtk_pwm_platform_data *data; | 209 | struct pwm_mediatek_chip *pc; |
230 | struct mtk_pwm_chip *pc; | ||
231 | struct resource *res; | 210 | struct resource *res; |
232 | unsigned int i; | 211 | unsigned int i; |
233 | int ret; | 212 | int ret; |
@@ -236,31 +215,51 @@ static int mtk_pwm_probe(struct platform_device *pdev) | |||
236 | if (!pc) | 215 | if (!pc) |
237 | return -ENOMEM; | 216 | return -ENOMEM; |
238 | 217 | ||
239 | data = of_device_get_match_data(&pdev->dev); | 218 | pc->soc = of_device_get_match_data(&pdev->dev); |
240 | if (data == NULL) | ||
241 | return -EINVAL; | ||
242 | pc->soc = data; | ||
243 | 219 | ||
244 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 220 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
245 | pc->regs = devm_ioremap_resource(&pdev->dev, res); | 221 | pc->regs = devm_ioremap_resource(&pdev->dev, res); |
246 | if (IS_ERR(pc->regs)) | 222 | if (IS_ERR(pc->regs)) |
247 | return PTR_ERR(pc->regs); | 223 | return PTR_ERR(pc->regs); |
248 | 224 | ||
249 | for (i = 0; i < data->num_pwms + 2 && pc->soc->has_clks; i++) { | 225 | pc->clk_pwms = devm_kcalloc(&pdev->dev, pc->soc->num_pwms, |
250 | pc->clks[i] = devm_clk_get(&pdev->dev, mtk_pwm_clk_name[i]); | 226 | sizeof(*pc->clk_pwms), GFP_KERNEL); |
251 | if (IS_ERR(pc->clks[i])) { | 227 | if (!pc->clk_pwms) |
228 | return -ENOMEM; | ||
229 | |||
230 | pc->clk_top = devm_clk_get(&pdev->dev, "top"); | ||
231 | if (IS_ERR(pc->clk_top)) { | ||
232 | dev_err(&pdev->dev, "clock: top fail: %ld\n", | ||
233 | PTR_ERR(pc->clk_top)); | ||
234 | return PTR_ERR(pc->clk_top); | ||
235 | } | ||
236 | |||
237 | pc->clk_main = devm_clk_get(&pdev->dev, "main"); | ||
238 | if (IS_ERR(pc->clk_main)) { | ||
239 | dev_err(&pdev->dev, "clock: main fail: %ld\n", | ||
240 | PTR_ERR(pc->clk_main)); | ||
241 | return PTR_ERR(pc->clk_main); | ||
242 | } | ||
243 | |||
244 | for (i = 0; i < pc->soc->num_pwms; i++) { | ||
245 | char name[8]; | ||
246 | |||
247 | snprintf(name, sizeof(name), "pwm%d", i + 1); | ||
248 | |||
249 | pc->clk_pwms[i] = devm_clk_get(&pdev->dev, name); | ||
250 | if (IS_ERR(pc->clk_pwms[i])) { | ||
252 | dev_err(&pdev->dev, "clock: %s fail: %ld\n", | 251 | dev_err(&pdev->dev, "clock: %s fail: %ld\n", |
253 | mtk_pwm_clk_name[i], PTR_ERR(pc->clks[i])); | 252 | name, PTR_ERR(pc->clk_pwms[i])); |
254 | return PTR_ERR(pc->clks[i]); | 253 | return PTR_ERR(pc->clk_pwms[i]); |
255 | } | 254 | } |
256 | } | 255 | } |
257 | 256 | ||
258 | platform_set_drvdata(pdev, pc); | 257 | platform_set_drvdata(pdev, pc); |
259 | 258 | ||
260 | pc->chip.dev = &pdev->dev; | 259 | pc->chip.dev = &pdev->dev; |
261 | pc->chip.ops = &mtk_pwm_ops; | 260 | pc->chip.ops = &pwm_mediatek_ops; |
262 | pc->chip.base = -1; | 261 | pc->chip.base = -1; |
263 | pc->chip.npwm = data->num_pwms; | 262 | pc->chip.npwm = pc->soc->num_pwms; |
264 | 263 | ||
265 | ret = pwmchip_add(&pc->chip); | 264 | ret = pwmchip_add(&pc->chip); |
266 | if (ret < 0) { | 265 | if (ret < 0) { |
@@ -271,55 +270,63 @@ static int mtk_pwm_probe(struct platform_device *pdev) | |||
271 | return 0; | 270 | return 0; |
272 | } | 271 | } |
273 | 272 | ||
274 | static int mtk_pwm_remove(struct platform_device *pdev) | 273 | static int pwm_mediatek_remove(struct platform_device *pdev) |
275 | { | 274 | { |
276 | struct mtk_pwm_chip *pc = platform_get_drvdata(pdev); | 275 | struct pwm_mediatek_chip *pc = platform_get_drvdata(pdev); |
277 | 276 | ||
278 | return pwmchip_remove(&pc->chip); | 277 | return pwmchip_remove(&pc->chip); |
279 | } | 278 | } |
280 | 279 | ||
281 | static const struct mtk_pwm_platform_data mt2712_pwm_data = { | 280 | static const struct pwm_mediatek_of_data mt2712_pwm_data = { |
282 | .num_pwms = 8, | 281 | .num_pwms = 8, |
283 | .pwm45_fixup = false, | 282 | .pwm45_fixup = false, |
284 | .has_clks = true, | ||
285 | }; | 283 | }; |
286 | 284 | ||
287 | static const struct mtk_pwm_platform_data mt7622_pwm_data = { | 285 | static const struct pwm_mediatek_of_data mt7622_pwm_data = { |
288 | .num_pwms = 6, | 286 | .num_pwms = 6, |
289 | .pwm45_fixup = false, | 287 | .pwm45_fixup = false, |
290 | .has_clks = true, | ||
291 | }; | 288 | }; |
292 | 289 | ||
293 | static const struct mtk_pwm_platform_data mt7623_pwm_data = { | 290 | static const struct pwm_mediatek_of_data mt7623_pwm_data = { |
294 | .num_pwms = 5, | 291 | .num_pwms = 5, |
295 | .pwm45_fixup = true, | 292 | .pwm45_fixup = true, |
296 | .has_clks = true, | ||
297 | }; | 293 | }; |
298 | 294 | ||
299 | static const struct mtk_pwm_platform_data mt7628_pwm_data = { | 295 | static const struct pwm_mediatek_of_data mt7628_pwm_data = { |
300 | .num_pwms = 4, | 296 | .num_pwms = 4, |
301 | .pwm45_fixup = true, | 297 | .pwm45_fixup = true, |
302 | .has_clks = false, | ||
303 | }; | 298 | }; |
304 | 299 | ||
305 | static const struct of_device_id mtk_pwm_of_match[] = { | 300 | static const struct pwm_mediatek_of_data mt7629_pwm_data = { |
301 | .num_pwms = 1, | ||
302 | .pwm45_fixup = false, | ||
303 | }; | ||
304 | |||
305 | static const struct pwm_mediatek_of_data mt8516_pwm_data = { | ||
306 | .num_pwms = 5, | ||
307 | .pwm45_fixup = false, | ||
308 | }; | ||
309 | |||
310 | static const struct of_device_id pwm_mediatek_of_match[] = { | ||
306 | { .compatible = "mediatek,mt2712-pwm", .data = &mt2712_pwm_data }, | 311 | { .compatible = "mediatek,mt2712-pwm", .data = &mt2712_pwm_data }, |
307 | { .compatible = "mediatek,mt7622-pwm", .data = &mt7622_pwm_data }, | 312 | { .compatible = "mediatek,mt7622-pwm", .data = &mt7622_pwm_data }, |
308 | { .compatible = "mediatek,mt7623-pwm", .data = &mt7623_pwm_data }, | 313 | { .compatible = "mediatek,mt7623-pwm", .data = &mt7623_pwm_data }, |
309 | { .compatible = "mediatek,mt7628-pwm", .data = &mt7628_pwm_data }, | 314 | { .compatible = "mediatek,mt7628-pwm", .data = &mt7628_pwm_data }, |
315 | { .compatible = "mediatek,mt7629-pwm", .data = &mt7629_pwm_data }, | ||
316 | { .compatible = "mediatek,mt8516-pwm", .data = &mt8516_pwm_data }, | ||
310 | { }, | 317 | { }, |
311 | }; | 318 | }; |
312 | MODULE_DEVICE_TABLE(of, mtk_pwm_of_match); | 319 | MODULE_DEVICE_TABLE(of, pwm_mediatek_of_match); |
313 | 320 | ||
314 | static struct platform_driver mtk_pwm_driver = { | 321 | static struct platform_driver pwm_mediatek_driver = { |
315 | .driver = { | 322 | .driver = { |
316 | .name = "mtk-pwm", | 323 | .name = "pwm-mediatek", |
317 | .of_match_table = mtk_pwm_of_match, | 324 | .of_match_table = pwm_mediatek_of_match, |
318 | }, | 325 | }, |
319 | .probe = mtk_pwm_probe, | 326 | .probe = pwm_mediatek_probe, |
320 | .remove = mtk_pwm_remove, | 327 | .remove = pwm_mediatek_remove, |
321 | }; | 328 | }; |
322 | module_platform_driver(mtk_pwm_driver); | 329 | module_platform_driver(pwm_mediatek_driver); |
323 | 330 | ||
324 | MODULE_AUTHOR("John Crispin <blogic@openwrt.org>"); | 331 | MODULE_AUTHOR("John Crispin <blogic@openwrt.org>"); |
325 | MODULE_LICENSE("GPL"); | 332 | MODULE_LICENSE("GPL v2"); |
diff --git a/drivers/pwm/pwm-meson.c b/drivers/pwm/pwm-meson.c index 3cbff5cbb789..6245bbdb6e6c 100644 --- a/drivers/pwm/pwm-meson.c +++ b/drivers/pwm/pwm-meson.c | |||
@@ -159,7 +159,7 @@ static void meson_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm) | |||
159 | } | 159 | } |
160 | 160 | ||
161 | static int meson_pwm_calc(struct meson_pwm *meson, struct pwm_device *pwm, | 161 | static int meson_pwm_calc(struct meson_pwm *meson, struct pwm_device *pwm, |
162 | struct pwm_state *state) | 162 | const struct pwm_state *state) |
163 | { | 163 | { |
164 | struct meson_pwm_channel *channel = pwm_get_chip_data(pwm); | 164 | struct meson_pwm_channel *channel = pwm_get_chip_data(pwm); |
165 | unsigned int duty, period, pre_div, cnt, duty_cnt; | 165 | unsigned int duty, period, pre_div, cnt, duty_cnt; |
@@ -265,7 +265,7 @@ static void meson_pwm_disable(struct meson_pwm *meson, struct pwm_device *pwm) | |||
265 | } | 265 | } |
266 | 266 | ||
267 | static int meson_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, | 267 | static int meson_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, |
268 | struct pwm_state *state) | 268 | const struct pwm_state *state) |
269 | { | 269 | { |
270 | struct meson_pwm_channel *channel = pwm_get_chip_data(pwm); | 270 | struct meson_pwm_channel *channel = pwm_get_chip_data(pwm); |
271 | struct meson_pwm *meson = to_meson_pwm(chip); | 271 | struct meson_pwm *meson = to_meson_pwm(chip); |
diff --git a/drivers/pwm/pwm-mxs.c b/drivers/pwm/pwm-mxs.c index 04c0f6b95c1a..b14376b47ac8 100644 --- a/drivers/pwm/pwm-mxs.c +++ b/drivers/pwm/pwm-mxs.c | |||
@@ -126,15 +126,13 @@ static int mxs_pwm_probe(struct platform_device *pdev) | |||
126 | { | 126 | { |
127 | struct device_node *np = pdev->dev.of_node; | 127 | struct device_node *np = pdev->dev.of_node; |
128 | struct mxs_pwm_chip *mxs; | 128 | struct mxs_pwm_chip *mxs; |
129 | struct resource *res; | ||
130 | int ret; | 129 | int ret; |
131 | 130 | ||
132 | mxs = devm_kzalloc(&pdev->dev, sizeof(*mxs), GFP_KERNEL); | 131 | mxs = devm_kzalloc(&pdev->dev, sizeof(*mxs), GFP_KERNEL); |
133 | if (!mxs) | 132 | if (!mxs) |
134 | return -ENOMEM; | 133 | return -ENOMEM; |
135 | 134 | ||
136 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 135 | mxs->base = devm_platform_ioremap_resource(pdev, 0); |
137 | mxs->base = devm_ioremap_resource(&pdev->dev, res); | ||
138 | if (IS_ERR(mxs->base)) | 136 | if (IS_ERR(mxs->base)) |
139 | return PTR_ERR(mxs->base); | 137 | return PTR_ERR(mxs->base); |
140 | 138 | ||
diff --git a/drivers/pwm/pwm-rcar.c b/drivers/pwm/pwm-rcar.c index 5b2b8ecc354c..852eb2347954 100644 --- a/drivers/pwm/pwm-rcar.c +++ b/drivers/pwm/pwm-rcar.c | |||
@@ -158,7 +158,7 @@ static void rcar_pwm_disable(struct rcar_pwm_chip *rp) | |||
158 | } | 158 | } |
159 | 159 | ||
160 | static int rcar_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, | 160 | static int rcar_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, |
161 | struct pwm_state *state) | 161 | const struct pwm_state *state) |
162 | { | 162 | { |
163 | struct rcar_pwm_chip *rp = to_rcar_pwm_chip(chip); | 163 | struct rcar_pwm_chip *rp = to_rcar_pwm_chip(chip); |
164 | struct pwm_state cur_state; | 164 | struct pwm_state cur_state; |
@@ -187,7 +187,7 @@ static int rcar_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, | |||
187 | /* The SYNC should be set to 0 even if rcar_pwm_set_counter failed */ | 187 | /* The SYNC should be set to 0 even if rcar_pwm_set_counter failed */ |
188 | rcar_pwm_update(rp, RCAR_PWMCR_SYNC, 0, RCAR_PWMCR); | 188 | rcar_pwm_update(rp, RCAR_PWMCR_SYNC, 0, RCAR_PWMCR); |
189 | 189 | ||
190 | if (!ret && state->enabled) | 190 | if (!ret) |
191 | ret = rcar_pwm_enable(rp); | 191 | ret = rcar_pwm_enable(rp); |
192 | 192 | ||
193 | return ret; | 193 | return ret; |
diff --git a/drivers/pwm/pwm-rockchip.c b/drivers/pwm/pwm-rockchip.c index 51b96cb7dd25..73352e6fbccb 100644 --- a/drivers/pwm/pwm-rockchip.c +++ b/drivers/pwm/pwm-rockchip.c | |||
@@ -90,16 +90,16 @@ static void rockchip_pwm_get_state(struct pwm_chip *chip, | |||
90 | state->enabled = ((val & enable_conf) == enable_conf) ? | 90 | state->enabled = ((val & enable_conf) == enable_conf) ? |
91 | true : false; | 91 | true : false; |
92 | 92 | ||
93 | if (pc->data->supports_polarity) { | 93 | if (pc->data->supports_polarity && !(val & PWM_DUTY_POSITIVE)) |
94 | if (!(val & PWM_DUTY_POSITIVE)) | 94 | state->polarity = PWM_POLARITY_INVERSED; |
95 | state->polarity = PWM_POLARITY_INVERSED; | 95 | else |
96 | } | 96 | state->polarity = PWM_POLARITY_NORMAL; |
97 | 97 | ||
98 | clk_disable(pc->pclk); | 98 | clk_disable(pc->pclk); |
99 | } | 99 | } |
100 | 100 | ||
101 | static void rockchip_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, | 101 | static void rockchip_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, |
102 | struct pwm_state *state) | 102 | const struct pwm_state *state) |
103 | { | 103 | { |
104 | struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip); | 104 | struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip); |
105 | unsigned long period, duty; | 105 | unsigned long period, duty; |
@@ -183,7 +183,7 @@ static int rockchip_pwm_enable(struct pwm_chip *chip, | |||
183 | } | 183 | } |
184 | 184 | ||
185 | static int rockchip_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, | 185 | static int rockchip_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, |
186 | struct pwm_state *state) | 186 | const struct pwm_state *state) |
187 | { | 187 | { |
188 | struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip); | 188 | struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip); |
189 | struct pwm_state curstate; | 189 | struct pwm_state curstate; |
@@ -212,12 +212,6 @@ static int rockchip_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, | |||
212 | goto out; | 212 | goto out; |
213 | } | 213 | } |
214 | 214 | ||
215 | /* | ||
216 | * Update the state with the real hardware, which can differ a bit | ||
217 | * because of period/duty_cycle approximation. | ||
218 | */ | ||
219 | rockchip_pwm_get_state(chip, pwm, state); | ||
220 | |||
221 | out: | 215 | out: |
222 | clk_disable(pc->pclk); | 216 | clk_disable(pc->pclk); |
223 | 217 | ||
diff --git a/drivers/pwm/pwm-sifive.c b/drivers/pwm/pwm-sifive.c index a7c107f19e66..cc63f9baa481 100644 --- a/drivers/pwm/pwm-sifive.c +++ b/drivers/pwm/pwm-sifive.c | |||
@@ -147,7 +147,7 @@ static int pwm_sifive_enable(struct pwm_chip *chip, bool enable) | |||
147 | } | 147 | } |
148 | 148 | ||
149 | static int pwm_sifive_apply(struct pwm_chip *chip, struct pwm_device *pwm, | 149 | static int pwm_sifive_apply(struct pwm_chip *chip, struct pwm_device *pwm, |
150 | struct pwm_state *state) | 150 | const struct pwm_state *state) |
151 | { | 151 | { |
152 | struct pwm_sifive_ddata *ddata = pwm_sifive_chip_to_ddata(chip); | 152 | struct pwm_sifive_ddata *ddata = pwm_sifive_chip_to_ddata(chip); |
153 | struct pwm_state cur_state; | 153 | struct pwm_state cur_state; |
@@ -250,10 +250,8 @@ static int pwm_sifive_probe(struct platform_device *pdev) | |||
250 | 250 | ||
251 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 251 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
252 | ddata->regs = devm_ioremap_resource(dev, res); | 252 | ddata->regs = devm_ioremap_resource(dev, res); |
253 | if (IS_ERR(ddata->regs)) { | 253 | if (IS_ERR(ddata->regs)) |
254 | dev_err(dev, "Unable to map IO resources\n"); | ||
255 | return PTR_ERR(ddata->regs); | 254 | return PTR_ERR(ddata->regs); |
256 | } | ||
257 | 255 | ||
258 | ddata->clk = devm_clk_get(dev, NULL); | 256 | ddata->clk = devm_clk_get(dev, NULL); |
259 | if (IS_ERR(ddata->clk)) { | 257 | if (IS_ERR(ddata->clk)) { |
diff --git a/drivers/pwm/pwm-sprd.c b/drivers/pwm/pwm-sprd.c new file mode 100644 index 000000000000..be2394227423 --- /dev/null +++ b/drivers/pwm/pwm-sprd.c | |||
@@ -0,0 +1,309 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
2 | /* | ||
3 | * Copyright (C) 2019 Spreadtrum Communications Inc. | ||
4 | */ | ||
5 | |||
6 | #include <linux/clk.h> | ||
7 | #include <linux/err.h> | ||
8 | #include <linux/io.h> | ||
9 | #include <linux/math64.h> | ||
10 | #include <linux/module.h> | ||
11 | #include <linux/platform_device.h> | ||
12 | #include <linux/pwm.h> | ||
13 | |||
14 | #define SPRD_PWM_PRESCALE 0x0 | ||
15 | #define SPRD_PWM_MOD 0x4 | ||
16 | #define SPRD_PWM_DUTY 0x8 | ||
17 | #define SPRD_PWM_ENABLE 0x18 | ||
18 | |||
19 | #define SPRD_PWM_MOD_MAX GENMASK(7, 0) | ||
20 | #define SPRD_PWM_DUTY_MSK GENMASK(15, 0) | ||
21 | #define SPRD_PWM_PRESCALE_MSK GENMASK(7, 0) | ||
22 | #define SPRD_PWM_ENABLE_BIT BIT(0) | ||
23 | |||
24 | #define SPRD_PWM_CHN_NUM 4 | ||
25 | #define SPRD_PWM_REGS_SHIFT 5 | ||
26 | #define SPRD_PWM_CHN_CLKS_NUM 2 | ||
27 | #define SPRD_PWM_CHN_OUTPUT_CLK 1 | ||
28 | |||
29 | struct sprd_pwm_chn { | ||
30 | struct clk_bulk_data clks[SPRD_PWM_CHN_CLKS_NUM]; | ||
31 | u32 clk_rate; | ||
32 | }; | ||
33 | |||
34 | struct sprd_pwm_chip { | ||
35 | void __iomem *base; | ||
36 | struct device *dev; | ||
37 | struct pwm_chip chip; | ||
38 | int num_pwms; | ||
39 | struct sprd_pwm_chn chn[SPRD_PWM_CHN_NUM]; | ||
40 | }; | ||
41 | |||
42 | /* | ||
43 | * The list of clocks required by PWM channels, and each channel has 2 clocks: | ||
44 | * enable clock and pwm clock. | ||
45 | */ | ||
46 | static const char * const sprd_pwm_clks[] = { | ||
47 | "enable0", "pwm0", | ||
48 | "enable1", "pwm1", | ||
49 | "enable2", "pwm2", | ||
50 | "enable3", "pwm3", | ||
51 | }; | ||
52 | |||
53 | static u32 sprd_pwm_read(struct sprd_pwm_chip *spc, u32 hwid, u32 reg) | ||
54 | { | ||
55 | u32 offset = reg + (hwid << SPRD_PWM_REGS_SHIFT); | ||
56 | |||
57 | return readl_relaxed(spc->base + offset); | ||
58 | } | ||
59 | |||
60 | static void sprd_pwm_write(struct sprd_pwm_chip *spc, u32 hwid, | ||
61 | u32 reg, u32 val) | ||
62 | { | ||
63 | u32 offset = reg + (hwid << SPRD_PWM_REGS_SHIFT); | ||
64 | |||
65 | writel_relaxed(val, spc->base + offset); | ||
66 | } | ||
67 | |||
68 | static void sprd_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm, | ||
69 | struct pwm_state *state) | ||
70 | { | ||
71 | struct sprd_pwm_chip *spc = | ||
72 | container_of(chip, struct sprd_pwm_chip, chip); | ||
73 | struct sprd_pwm_chn *chn = &spc->chn[pwm->hwpwm]; | ||
74 | u32 val, duty, prescale; | ||
75 | u64 tmp; | ||
76 | int ret; | ||
77 | |||
78 | /* | ||
79 | * The clocks to PWM channel has to be enabled first before | ||
80 | * reading to the registers. | ||
81 | */ | ||
82 | ret = clk_bulk_prepare_enable(SPRD_PWM_CHN_CLKS_NUM, chn->clks); | ||
83 | if (ret) { | ||
84 | dev_err(spc->dev, "failed to enable pwm%u clocks\n", | ||
85 | pwm->hwpwm); | ||
86 | return; | ||
87 | } | ||
88 | |||
89 | val = sprd_pwm_read(spc, pwm->hwpwm, SPRD_PWM_ENABLE); | ||
90 | if (val & SPRD_PWM_ENABLE_BIT) | ||
91 | state->enabled = true; | ||
92 | else | ||
93 | state->enabled = false; | ||
94 | |||
95 | /* | ||
96 | * The hardware provides a counter that is feed by the source clock. | ||
97 | * The period length is (PRESCALE + 1) * MOD counter steps. | ||
98 | * The duty cycle length is (PRESCALE + 1) * DUTY counter steps. | ||
99 | * Thus the period_ns and duty_ns calculation formula should be: | ||
100 | * period_ns = NSEC_PER_SEC * (prescale + 1) * mod / clk_rate | ||
101 | * duty_ns = NSEC_PER_SEC * (prescale + 1) * duty / clk_rate | ||
102 | */ | ||
103 | val = sprd_pwm_read(spc, pwm->hwpwm, SPRD_PWM_PRESCALE); | ||
104 | prescale = val & SPRD_PWM_PRESCALE_MSK; | ||
105 | tmp = (prescale + 1) * NSEC_PER_SEC * SPRD_PWM_MOD_MAX; | ||
106 | state->period = DIV_ROUND_CLOSEST_ULL(tmp, chn->clk_rate); | ||
107 | |||
108 | val = sprd_pwm_read(spc, pwm->hwpwm, SPRD_PWM_DUTY); | ||
109 | duty = val & SPRD_PWM_DUTY_MSK; | ||
110 | tmp = (prescale + 1) * NSEC_PER_SEC * duty; | ||
111 | state->duty_cycle = DIV_ROUND_CLOSEST_ULL(tmp, chn->clk_rate); | ||
112 | |||
113 | /* Disable PWM clocks if the PWM channel is not in enable state. */ | ||
114 | if (!state->enabled) | ||
115 | clk_bulk_disable_unprepare(SPRD_PWM_CHN_CLKS_NUM, chn->clks); | ||
116 | } | ||
117 | |||
118 | static int sprd_pwm_config(struct sprd_pwm_chip *spc, struct pwm_device *pwm, | ||
119 | int duty_ns, int period_ns) | ||
120 | { | ||
121 | struct sprd_pwm_chn *chn = &spc->chn[pwm->hwpwm]; | ||
122 | u32 prescale, duty; | ||
123 | u64 tmp; | ||
124 | |||
125 | /* | ||
126 | * The hardware provides a counter that is feed by the source clock. | ||
127 | * The period length is (PRESCALE + 1) * MOD counter steps. | ||
128 | * The duty cycle length is (PRESCALE + 1) * DUTY counter steps. | ||
129 | * | ||
130 | * To keep the maths simple we're always using MOD = SPRD_PWM_MOD_MAX. | ||
131 | * The value for PRESCALE is selected such that the resulting period | ||
132 | * gets the maximal length not bigger than the requested one with the | ||
133 | * given settings (MOD = SPRD_PWM_MOD_MAX and input clock). | ||
134 | */ | ||
135 | duty = duty_ns * SPRD_PWM_MOD_MAX / period_ns; | ||
136 | |||
137 | tmp = (u64)chn->clk_rate * period_ns; | ||
138 | do_div(tmp, NSEC_PER_SEC); | ||
139 | prescale = DIV_ROUND_CLOSEST_ULL(tmp, SPRD_PWM_MOD_MAX) - 1; | ||
140 | if (prescale > SPRD_PWM_PRESCALE_MSK) | ||
141 | prescale = SPRD_PWM_PRESCALE_MSK; | ||
142 | |||
143 | /* | ||
144 | * Note: Writing DUTY triggers the hardware to actually apply the | ||
145 | * values written to MOD and DUTY to the output, so must keep writing | ||
146 | * DUTY last. | ||
147 | * | ||
148 | * The hardware can ensures that current running period is completed | ||
149 | * before changing a new configuration to avoid mixed settings. | ||
150 | */ | ||
151 | sprd_pwm_write(spc, pwm->hwpwm, SPRD_PWM_PRESCALE, prescale); | ||
152 | sprd_pwm_write(spc, pwm->hwpwm, SPRD_PWM_MOD, SPRD_PWM_MOD_MAX); | ||
153 | sprd_pwm_write(spc, pwm->hwpwm, SPRD_PWM_DUTY, duty); | ||
154 | |||
155 | return 0; | ||
156 | } | ||
157 | |||
158 | static int sprd_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, | ||
159 | const struct pwm_state *state) | ||
160 | { | ||
161 | struct sprd_pwm_chip *spc = | ||
162 | container_of(chip, struct sprd_pwm_chip, chip); | ||
163 | struct sprd_pwm_chn *chn = &spc->chn[pwm->hwpwm]; | ||
164 | struct pwm_state *cstate = &pwm->state; | ||
165 | int ret; | ||
166 | |||
167 | if (state->enabled) { | ||
168 | if (!cstate->enabled) { | ||
169 | /* | ||
170 | * The clocks to PWM channel has to be enabled first | ||
171 | * before writing to the registers. | ||
172 | */ | ||
173 | ret = clk_bulk_prepare_enable(SPRD_PWM_CHN_CLKS_NUM, | ||
174 | chn->clks); | ||
175 | if (ret) { | ||
176 | dev_err(spc->dev, | ||
177 | "failed to enable pwm%u clocks\n", | ||
178 | pwm->hwpwm); | ||
179 | return ret; | ||
180 | } | ||
181 | } | ||
182 | |||
183 | if (state->period != cstate->period || | ||
184 | state->duty_cycle != cstate->duty_cycle) { | ||
185 | ret = sprd_pwm_config(spc, pwm, state->duty_cycle, | ||
186 | state->period); | ||
187 | if (ret) | ||
188 | return ret; | ||
189 | } | ||
190 | |||
191 | sprd_pwm_write(spc, pwm->hwpwm, SPRD_PWM_ENABLE, 1); | ||
192 | } else if (cstate->enabled) { | ||
193 | /* | ||
194 | * Note: After setting SPRD_PWM_ENABLE to zero, the controller | ||
195 | * will not wait for current period to be completed, instead it | ||
196 | * will stop the PWM channel immediately. | ||
197 | */ | ||
198 | sprd_pwm_write(spc, pwm->hwpwm, SPRD_PWM_ENABLE, 0); | ||
199 | |||
200 | clk_bulk_disable_unprepare(SPRD_PWM_CHN_CLKS_NUM, chn->clks); | ||
201 | } | ||
202 | |||
203 | return 0; | ||
204 | } | ||
205 | |||
206 | static const struct pwm_ops sprd_pwm_ops = { | ||
207 | .apply = sprd_pwm_apply, | ||
208 | .get_state = sprd_pwm_get_state, | ||
209 | .owner = THIS_MODULE, | ||
210 | }; | ||
211 | |||
212 | static int sprd_pwm_clk_init(struct sprd_pwm_chip *spc) | ||
213 | { | ||
214 | struct clk *clk_pwm; | ||
215 | int ret, i; | ||
216 | |||
217 | for (i = 0; i < SPRD_PWM_CHN_NUM; i++) { | ||
218 | struct sprd_pwm_chn *chn = &spc->chn[i]; | ||
219 | int j; | ||
220 | |||
221 | for (j = 0; j < SPRD_PWM_CHN_CLKS_NUM; ++j) | ||
222 | chn->clks[j].id = | ||
223 | sprd_pwm_clks[i * SPRD_PWM_CHN_CLKS_NUM + j]; | ||
224 | |||
225 | ret = devm_clk_bulk_get(spc->dev, SPRD_PWM_CHN_CLKS_NUM, | ||
226 | chn->clks); | ||
227 | if (ret) { | ||
228 | if (ret == -ENOENT) | ||
229 | break; | ||
230 | |||
231 | if (ret != -EPROBE_DEFER) | ||
232 | dev_err(spc->dev, | ||
233 | "failed to get channel clocks\n"); | ||
234 | |||
235 | return ret; | ||
236 | } | ||
237 | |||
238 | clk_pwm = chn->clks[SPRD_PWM_CHN_OUTPUT_CLK].clk; | ||
239 | chn->clk_rate = clk_get_rate(clk_pwm); | ||
240 | } | ||
241 | |||
242 | if (!i) { | ||
243 | dev_err(spc->dev, "no available PWM channels\n"); | ||
244 | return -ENODEV; | ||
245 | } | ||
246 | |||
247 | spc->num_pwms = i; | ||
248 | |||
249 | return 0; | ||
250 | } | ||
251 | |||
252 | static int sprd_pwm_probe(struct platform_device *pdev) | ||
253 | { | ||
254 | struct sprd_pwm_chip *spc; | ||
255 | int ret; | ||
256 | |||
257 | spc = devm_kzalloc(&pdev->dev, sizeof(*spc), GFP_KERNEL); | ||
258 | if (!spc) | ||
259 | return -ENOMEM; | ||
260 | |||
261 | spc->base = devm_platform_ioremap_resource(pdev, 0); | ||
262 | if (IS_ERR(spc->base)) | ||
263 | return PTR_ERR(spc->base); | ||
264 | |||
265 | spc->dev = &pdev->dev; | ||
266 | platform_set_drvdata(pdev, spc); | ||
267 | |||
268 | ret = sprd_pwm_clk_init(spc); | ||
269 | if (ret) | ||
270 | return ret; | ||
271 | |||
272 | spc->chip.dev = &pdev->dev; | ||
273 | spc->chip.ops = &sprd_pwm_ops; | ||
274 | spc->chip.base = -1; | ||
275 | spc->chip.npwm = spc->num_pwms; | ||
276 | |||
277 | ret = pwmchip_add(&spc->chip); | ||
278 | if (ret) | ||
279 | dev_err(&pdev->dev, "failed to add PWM chip\n"); | ||
280 | |||
281 | return ret; | ||
282 | } | ||
283 | |||
284 | static int sprd_pwm_remove(struct platform_device *pdev) | ||
285 | { | ||
286 | struct sprd_pwm_chip *spc = platform_get_drvdata(pdev); | ||
287 | |||
288 | return pwmchip_remove(&spc->chip); | ||
289 | } | ||
290 | |||
291 | static const struct of_device_id sprd_pwm_of_match[] = { | ||
292 | { .compatible = "sprd,ums512-pwm", }, | ||
293 | { }, | ||
294 | }; | ||
295 | MODULE_DEVICE_TABLE(of, sprd_pwm_of_match); | ||
296 | |||
297 | static struct platform_driver sprd_pwm_driver = { | ||
298 | .driver = { | ||
299 | .name = "sprd-pwm", | ||
300 | .of_match_table = sprd_pwm_of_match, | ||
301 | }, | ||
302 | .probe = sprd_pwm_probe, | ||
303 | .remove = sprd_pwm_remove, | ||
304 | }; | ||
305 | |||
306 | module_platform_driver(sprd_pwm_driver); | ||
307 | |||
308 | MODULE_DESCRIPTION("Spreadtrum PWM Driver"); | ||
309 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/pwm/pwm-sti.c b/drivers/pwm/pwm-sti.c index 20450e34ad57..1508616d794c 100644 --- a/drivers/pwm/pwm-sti.c +++ b/drivers/pwm/pwm-sti.c | |||
@@ -564,10 +564,8 @@ static int sti_pwm_probe(struct platform_device *pdev) | |||
564 | return PTR_ERR(pc->regmap); | 564 | return PTR_ERR(pc->regmap); |
565 | 565 | ||
566 | irq = platform_get_irq(pdev, 0); | 566 | irq = platform_get_irq(pdev, 0); |
567 | if (irq < 0) { | 567 | if (irq < 0) |
568 | dev_err(&pdev->dev, "Failed to obtain IRQ\n"); | ||
569 | return irq; | 568 | return irq; |
570 | } | ||
571 | 569 | ||
572 | ret = devm_request_irq(&pdev->dev, irq, sti_pwm_interrupt, 0, | 570 | ret = devm_request_irq(&pdev->dev, irq, sti_pwm_interrupt, 0, |
573 | pdev->name, pc); | 571 | pdev->name, pc); |
diff --git a/drivers/pwm/pwm-stm32-lp.c b/drivers/pwm/pwm-stm32-lp.c index 2211a642066d..67fca62524dc 100644 --- a/drivers/pwm/pwm-stm32-lp.c +++ b/drivers/pwm/pwm-stm32-lp.c | |||
@@ -32,7 +32,7 @@ static inline struct stm32_pwm_lp *to_stm32_pwm_lp(struct pwm_chip *chip) | |||
32 | #define STM32_LPTIM_MAX_PRESCALER 128 | 32 | #define STM32_LPTIM_MAX_PRESCALER 128 |
33 | 33 | ||
34 | static int stm32_pwm_lp_apply(struct pwm_chip *chip, struct pwm_device *pwm, | 34 | static int stm32_pwm_lp_apply(struct pwm_chip *chip, struct pwm_device *pwm, |
35 | struct pwm_state *state) | 35 | const struct pwm_state *state) |
36 | { | 36 | { |
37 | struct stm32_pwm_lp *priv = to_stm32_pwm_lp(chip); | 37 | struct stm32_pwm_lp *priv = to_stm32_pwm_lp(chip); |
38 | unsigned long long prd, div, dty; | 38 | unsigned long long prd, div, dty; |
@@ -59,6 +59,12 @@ static int stm32_pwm_lp_apply(struct pwm_chip *chip, struct pwm_device *pwm, | |||
59 | /* Calculate the period and prescaler value */ | 59 | /* Calculate the period and prescaler value */ |
60 | div = (unsigned long long)clk_get_rate(priv->clk) * state->period; | 60 | div = (unsigned long long)clk_get_rate(priv->clk) * state->period; |
61 | do_div(div, NSEC_PER_SEC); | 61 | do_div(div, NSEC_PER_SEC); |
62 | if (!div) { | ||
63 | /* Clock is too slow to achieve requested period. */ | ||
64 | dev_dbg(priv->chip.dev, "Can't reach %u ns\n", state->period); | ||
65 | return -EINVAL; | ||
66 | } | ||
67 | |||
62 | prd = div; | 68 | prd = div; |
63 | while (div > STM32_LPTIM_MAX_ARR) { | 69 | while (div > STM32_LPTIM_MAX_ARR) { |
64 | presc++; | 70 | presc++; |
diff --git a/drivers/pwm/pwm-stm32.c b/drivers/pwm/pwm-stm32.c index 740e2dec8313..359b08596d9e 100644 --- a/drivers/pwm/pwm-stm32.c +++ b/drivers/pwm/pwm-stm32.c | |||
@@ -440,7 +440,7 @@ static void stm32_pwm_disable(struct stm32_pwm *priv, int ch) | |||
440 | } | 440 | } |
441 | 441 | ||
442 | static int stm32_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, | 442 | static int stm32_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, |
443 | struct pwm_state *state) | 443 | const struct pwm_state *state) |
444 | { | 444 | { |
445 | bool enabled; | 445 | bool enabled; |
446 | struct stm32_pwm *priv = to_stm32_pwm_dev(chip); | 446 | struct stm32_pwm *priv = to_stm32_pwm_dev(chip); |
@@ -468,7 +468,7 @@ static int stm32_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, | |||
468 | } | 468 | } |
469 | 469 | ||
470 | static int stm32_pwm_apply_locked(struct pwm_chip *chip, struct pwm_device *pwm, | 470 | static int stm32_pwm_apply_locked(struct pwm_chip *chip, struct pwm_device *pwm, |
471 | struct pwm_state *state) | 471 | const struct pwm_state *state) |
472 | { | 472 | { |
473 | struct stm32_pwm *priv = to_stm32_pwm_dev(chip); | 473 | struct stm32_pwm *priv = to_stm32_pwm_dev(chip); |
474 | int ret; | 474 | int ret; |
diff --git a/drivers/pwm/pwm-sun4i.c b/drivers/pwm/pwm-sun4i.c index de78c824bbfd..6f5840a1a82d 100644 --- a/drivers/pwm/pwm-sun4i.c +++ b/drivers/pwm/pwm-sun4i.c | |||
@@ -145,7 +145,7 @@ static void sun4i_pwm_get_state(struct pwm_chip *chip, | |||
145 | } | 145 | } |
146 | 146 | ||
147 | static int sun4i_pwm_calculate(struct sun4i_pwm_chip *sun4i_pwm, | 147 | static int sun4i_pwm_calculate(struct sun4i_pwm_chip *sun4i_pwm, |
148 | struct pwm_state *state, | 148 | const struct pwm_state *state, |
149 | u32 *dty, u32 *prd, unsigned int *prsclr) | 149 | u32 *dty, u32 *prd, unsigned int *prsclr) |
150 | { | 150 | { |
151 | u64 clk_rate, div = 0; | 151 | u64 clk_rate, div = 0; |
@@ -192,17 +192,11 @@ static int sun4i_pwm_calculate(struct sun4i_pwm_chip *sun4i_pwm, | |||
192 | *dty = div; | 192 | *dty = div; |
193 | *prsclr = prescaler; | 193 | *prsclr = prescaler; |
194 | 194 | ||
195 | div = (u64)pval * NSEC_PER_SEC * *prd; | ||
196 | state->period = DIV_ROUND_CLOSEST_ULL(div, clk_rate); | ||
197 | |||
198 | div = (u64)pval * NSEC_PER_SEC * *dty; | ||
199 | state->duty_cycle = DIV_ROUND_CLOSEST_ULL(div, clk_rate); | ||
200 | |||
201 | return 0; | 195 | return 0; |
202 | } | 196 | } |
203 | 197 | ||
204 | static int sun4i_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, | 198 | static int sun4i_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, |
205 | struct pwm_state *state) | 199 | const struct pwm_state *state) |
206 | { | 200 | { |
207 | struct sun4i_pwm_chip *sun4i_pwm = to_sun4i_pwm_chip(chip); | 201 | struct sun4i_pwm_chip *sun4i_pwm = to_sun4i_pwm_chip(chip); |
208 | struct pwm_state cstate; | 202 | struct pwm_state cstate; |
diff --git a/drivers/pwm/pwm-zx.c b/drivers/pwm/pwm-zx.c index e24f4be35316..e2c21cc34a96 100644 --- a/drivers/pwm/pwm-zx.c +++ b/drivers/pwm/pwm-zx.c | |||
@@ -148,7 +148,7 @@ static int zx_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, | |||
148 | } | 148 | } |
149 | 149 | ||
150 | static int zx_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, | 150 | static int zx_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, |
151 | struct pwm_state *state) | 151 | const struct pwm_state *state) |
152 | { | 152 | { |
153 | struct zx_pwm_chip *zpc = to_zx_pwm_chip(chip); | 153 | struct zx_pwm_chip *zpc = to_zx_pwm_chip(chip); |
154 | struct pwm_state cstate; | 154 | struct pwm_state cstate; |
diff --git a/include/linux/pwm.h b/include/linux/pwm.h index 24632a7a7d11..b2c9c460947d 100644 --- a/include/linux/pwm.h +++ b/include/linux/pwm.h | |||
@@ -262,7 +262,7 @@ struct pwm_ops { | |||
262 | int (*capture)(struct pwm_chip *chip, struct pwm_device *pwm, | 262 | int (*capture)(struct pwm_chip *chip, struct pwm_device *pwm, |
263 | struct pwm_capture *result, unsigned long timeout); | 263 | struct pwm_capture *result, unsigned long timeout); |
264 | int (*apply)(struct pwm_chip *chip, struct pwm_device *pwm, | 264 | int (*apply)(struct pwm_chip *chip, struct pwm_device *pwm, |
265 | struct pwm_state *state); | 265 | const struct pwm_state *state); |
266 | void (*get_state)(struct pwm_chip *chip, struct pwm_device *pwm, | 266 | void (*get_state)(struct pwm_chip *chip, struct pwm_device *pwm, |
267 | struct pwm_state *state); | 267 | struct pwm_state *state); |
268 | struct module *owner; | 268 | struct module *owner; |
@@ -316,7 +316,7 @@ struct pwm_capture { | |||
316 | /* PWM user APIs */ | 316 | /* PWM user APIs */ |
317 | struct pwm_device *pwm_request(int pwm_id, const char *label); | 317 | struct pwm_device *pwm_request(int pwm_id, const char *label); |
318 | void pwm_free(struct pwm_device *pwm); | 318 | void pwm_free(struct pwm_device *pwm); |
319 | int pwm_apply_state(struct pwm_device *pwm, struct pwm_state *state); | 319 | int pwm_apply_state(struct pwm_device *pwm, const struct pwm_state *state); |
320 | int pwm_adjust_config(struct pwm_device *pwm); | 320 | int pwm_adjust_config(struct pwm_device *pwm); |
321 | 321 | ||
322 | /** | 322 | /** |