Pull pwm updates from Thierry Reding: "The ZTE ZX platform is being removed, so the PWM driver is no longer needed and removed as well. Other than that this contains a small set of fixes and cleanups across a couple of drivers" * tag 'pwm/for-5.12-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/thierry.reding/linux-pwm: pwm: lpc18xx-sct: remove unneeded semicolon pwm: iqs620a: Correct a stale state variable pwm: iqs620a: Fix overflow and optimize calculations pwm: rockchip: Enable clock before calling clk_get_rate() pwm: rockchip: Eliminate potential race condition when probing pwm: rockchip: Replace "bus clk" with "PWM clk" pwm: rockchip: rockchip_pwm_probe(): Remove superfluous clk_unprepare() pwm: rockchip: Enable APB clock during register access while probing pwm: Remove ZTE ZX driver
Unified · Split
| @@ -1,22 +0,0 @@ | |||
| 1 | ZTE ZX PWM controller | ||
| 2 | |||
| 3 | Required properties: | ||
| 4 | - compatible: Should be "zte,zx296718-pwm". | ||
| 5 | - reg: Physical base address and length of the controller's registers. | ||
| 6 | - clocks : The phandle and specifier referencing the controller's clocks. | ||
| 7 | - clock-names: "pclk" for PCLK, "wclk" for WCLK to the PWM controller. The | ||
| 8 | PCLK is for register access, while WCLK is the reference clock for | ||
| 9 | calculating period and duty cycles. | ||
| 10 | - #pwm-cells: Should be 3. See pwm.yaml in this directory for a description of | ||
| 11 | the cells format. | ||
| 12 | |||
| 13 | Example: | ||
| 14 | |||
| 15 | pwm: pwm@1439000 { | ||
| 16 | compatible = "zte,zx296718-pwm"; | ||
| 17 | reg = <0x1439000 0x1000>; | ||
| 18 | clocks = <&lsp1crm LSP1_PWM_PCLK>, | ||
| 19 | <&lsp1crm LSP1_PWM_WCLK>; | ||
| 20 | clock-names = "pclk", "wclk"; | ||
| 21 | #pwm-cells = <3>; | ||
| 22 | }; | ||
| @@ -611,14 +611,4 @@ config PWM_VT8500 · 610 unmodified lines | |||
| 611 | To compile this driver as a module, choose M here: the module | 611 | To compile this driver as a module, choose M here: the module |
| 612 | will be called pwm-vt8500. | 612 | will be called pwm-vt8500. |
| 613 | 613 | ||
| 614 | config PWM_ZX | ||
| 615 | tristate "ZTE ZX PWM support" | ||
| 616 | depends on ARCH_ZX || COMPILE_TEST | ||
| 617 | depends on HAS_IOMEM | ||
| 618 | help | ||
| 619 | Generic PWM framework driver for ZTE ZX family SoCs. | ||
| 620 | |||
| 621 | To compile this driver as a module, choose M here: the module | ||
| 622 | will be called pwm-zx. | ||
| 623 | |||
| 624 | endif | 614 | endif |
| @@ -57,4 +57,3 @@ obj-$(CONFIG_PWM_TIEHRPWM) += pwm-tiehrpwm.o · 56 unmodified lines | |||
| 57 | obj-$(CONFIG_PWM_TWL) += pwm-twl.o | 57 | obj-$(CONFIG_PWM_TWL) += pwm-twl.o |
| 58 | obj-$(CONFIG_PWM_TWL_LED) += pwm-twl-led.o | 58 | obj-$(CONFIG_PWM_TWL_LED) += pwm-twl-led.o |
| 59 | obj-$(CONFIG_PWM_VT8500) += pwm-vt8500.o | 59 | obj-$(CONFIG_PWM_VT8500) += pwm-vt8500.o |
| 60 | obj-$(CONFIG_PWM_ZX) += pwm-zx.o | ||
| @@ -37,16 +37,34 @@ struct iqs620_pwm_private { · 36 unmodified lines | |||
| 37 | struct pwm_chip chip; | 37 | struct pwm_chip chip; |
| 38 | struct notifier_block notifier; | 38 | struct notifier_block notifier; |
| 39 | struct mutex lock; | 39 | struct mutex lock; |
| 40 | bool out_en; | 40 | unsigned int duty_scale; |
| 41 | u8 duty_val; | ||
| 42 | }; | 41 | }; |
| 43 | 42 | ||
| 43 | static int iqs620_pwm_init(struct iqs620_pwm_private *iqs620_pwm, | ||
| 44 | unsigned int duty_scale) | ||
| 45 | { | ||
| 46 | struct iqs62x_core *iqs62x = iqs620_pwm->iqs62x; | ||
| 47 | int ret; | ||
| 48 | |||
| 49 | if (!duty_scale) | ||
| 50 | return regmap_update_bits(iqs62x->regmap, IQS620_PWR_SETTINGS, | ||
| 51 | IQS620_PWR_SETTINGS_PWM_OUT, 0); | ||
| 52 | |||
| 53 | ret = regmap_write(iqs62x->regmap, IQS620_PWM_DUTY_CYCLE, | ||
| 54 | duty_scale - 1); | ||
| 55 | if (ret) | ||
| 56 | return ret; | ||
| 57 | |||
| 58 | return regmap_update_bits(iqs62x->regmap, IQS620_PWR_SETTINGS, | ||
| 59 | IQS620_PWR_SETTINGS_PWM_OUT, 0xff); | ||
| 60 | } | ||
| 61 | |||
| 44 | static int iqs620_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, | 62 | static int iqs620_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, |
| 45 | const struct pwm_state *state) | 63 | const struct pwm_state *state) |
| 46 | { | 64 | { |
| 47 | struct iqs620_pwm_private *iqs620_pwm; | 65 | struct iqs620_pwm_private *iqs620_pwm; |
| 48 | struct iqs62x_core *iqs62x; | 66 | unsigned int duty_cycle; |
| 49 | u64 duty_scale; | 67 | unsigned int duty_scale; |
| 50 | int ret; | 68 | int ret; |
| 51 | 69 | ||
| 52 | if (state->polarity != PWM_POLARITY_NORMAL) | 70 | if (state->polarity != PWM_POLARITY_NORMAL) |
| @@ -56,7 +74,6 @@ static int iqs620_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, · 3 unmodified lines | |||
| 56 | return -EINVAL; | 74 | return -EINVAL; |
| 57 | 75 | ||
| 58 | iqs620_pwm = container_of(chip, struct iqs620_pwm_private, chip); | 76 | iqs620_pwm = container_of(chip, struct iqs620_pwm_private, chip); |
| 59 | iqs62x = iqs620_pwm->iqs62x; | ||
| 60 | 77 | ||
| 61 | /* | 78 | /* |
| 62 | * The duty cycle generated by the device is calculated as follows: | 79 | * The duty cycle generated by the device is calculated as follows: |
| @@ -70,38 +87,18 @@ static int iqs620_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, · 7 unmodified lines | |||
| 70 | * For lower duty cycles (e.g. 0), the PWM output is simply disabled to | 87 | * For lower duty cycles (e.g. 0), the PWM output is simply disabled to |
| 71 | * allow an external pull-down resistor to hold the GPIO3/LTX pin low. | 88 | * allow an external pull-down resistor to hold the GPIO3/LTX pin low. |
| 72 | */ | 89 | */ |
| 73 | duty_scale = div_u64(state->duty_cycle * 256, IQS620_PWM_PERIOD_NS); | 90 | duty_cycle = min_t(u64, state->duty_cycle, IQS620_PWM_PERIOD_NS); |
| 74 | 91 | duty_scale = duty_cycle * 256 / IQS620_PWM_PERIOD_NS; | |
| 75 | mutex_lock(&iqs620_pwm->lock); | ||
| 76 | |||
| 77 | if (!state->enabled || !duty_scale) { | ||
| 78 | ret = regmap_update_bits(iqs62x->regmap, IQS620_PWR_SETTINGS, | ||
| 79 | IQS620_PWR_SETTINGS_PWM_OUT, 0); | ||
| 80 | if (ret) | ||
| 81 | goto err_mutex; | ||
| 82 | } | ||
| 83 | 92 | ||
| 84 | if (duty_scale) { | 93 | if (!state->enabled) |
| 85 | u8 duty_val = min_t(u64, duty_scale - 1, 0xff); | 94 | duty_scale = 0; |
| 86 | 95 | ||
| 87 | ret = regmap_write(iqs62x->regmap, IQS620_PWM_DUTY_CYCLE, | 96 | mutex_lock(&iqs620_pwm->lock); |
| 88 | duty_val); | ||
| 89 | if (ret) | ||
| 90 | goto err_mutex; | ||
| 91 | |||
| 92 | iqs620_pwm->duty_val = duty_val; | ||
| 93 | } | ||
| 94 | |||
| 95 | if (state->enabled && duty_scale) { | ||
| 96 | ret = regmap_update_bits(iqs62x->regmap, IQS620_PWR_SETTINGS, | ||
| 97 | IQS620_PWR_SETTINGS_PWM_OUT, 0xff); | ||
| 98 | if (ret) | ||
| 99 | goto err_mutex; | ||
| 100 | } | ||
| 101 | 97 | ||
| 102 | iqs620_pwm->out_en = state->enabled; | 98 | ret = iqs620_pwm_init(iqs620_pwm, duty_scale); |
| 99 | if (!ret) | ||
| 100 | iqs620_pwm->duty_scale = duty_scale; | ||
| 103 | 101 | ||
| 104 | err_mutex: | ||
| 105 | mutex_unlock(&iqs620_pwm->lock); | 102 | mutex_unlock(&iqs620_pwm->lock); |
| 106 | 103 | ||
| 107 | return ret; | 104 | return ret; |
| @@ -119,12 +116,11 @@ static void iqs620_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm, · 11 unmodified lines | |||
| 119 | /* | 116 | /* |
| 120 | * Since the device cannot generate a 0% duty cycle, requests to do so | 117 | * Since the device cannot generate a 0% duty cycle, requests to do so |
| 121 | * cause subsequent calls to iqs620_pwm_get_state to report the output | 118 | * cause subsequent calls to iqs620_pwm_get_state to report the output |
| 122 | * as disabled with duty cycle equal to that which was in use prior to | 119 | * as disabled. This is not ideal, but is the best compromise based on |
| 123 | * the request. This is not ideal, but is the best compromise based on | ||
| 124 | * the capabilities of the device. | 120 | * the capabilities of the device. |
| 125 | */ | 121 | */ |
| 126 | state->enabled = iqs620_pwm->out_en; | 122 | state->enabled = iqs620_pwm->duty_scale > 0; |
| 127 | state->duty_cycle = DIV_ROUND_UP((iqs620_pwm->duty_val + 1) * | 123 | state->duty_cycle = DIV_ROUND_UP(iqs620_pwm->duty_scale * |
| 128 | IQS620_PWM_PERIOD_NS, 256); | 124 | IQS620_PWM_PERIOD_NS, 256); |
| 129 | 125 | ||
| 130 | mutex_unlock(&iqs620_pwm->lock); | 126 | mutex_unlock(&iqs620_pwm->lock); |
| @@ -136,7 +132,6 @@ static int iqs620_pwm_notifier(struct notifier_block *notifier, · 5 unmodified lines | |||
| 136 | unsigned long event_flags, void *context) | 132 | unsigned long event_flags, void *context) |
| 137 | { | 133 | { |
| 138 | struct iqs620_pwm_private *iqs620_pwm; | 134 | struct iqs620_pwm_private *iqs620_pwm; |
| 139 | struct iqs62x_core *iqs62x; | ||
| 140 | int ret; | 135 | int ret; |
| 141 | 136 | ||
| 142 | if (!(event_flags & BIT(IQS62X_EVENT_SYS_RESET))) | 137 | if (!(event_flags & BIT(IQS62X_EVENT_SYS_RESET))) |
| @@ -144,7 +139,6 @@ static int iqs620_pwm_notifier(struct notifier_block *notifier, · 1 unmodified line | |||
| 144 | 139 | ||
| 145 | iqs620_pwm = container_of(notifier, struct iqs620_pwm_private, | 140 | iqs620_pwm = container_of(notifier, struct iqs620_pwm_private, |
| 146 | notifier); | 141 | notifier); |
| 147 | iqs62x = iqs620_pwm->iqs62x; | ||
| 148 | 142 | ||
| 149 | mutex_lock(&iqs620_pwm->lock); | 143 | mutex_lock(&iqs620_pwm->lock); |
| 150 | 144 | ||
| @@ -153,16 +147,8 @@ static int iqs620_pwm_notifier(struct notifier_block *notifier, · 2 unmodified lines | |||
| 153 | * of a device reset, so nothing else is printed here unless there is | 147 | * of a device reset, so nothing else is printed here unless there is |
| 154 | * an additional failure. | 148 | * an additional failure. |
| 155 | */ | 149 | */ |
| 156 | ret = regmap_write(iqs62x->regmap, IQS620_PWM_DUTY_CYCLE, | 150 | ret = iqs620_pwm_init(iqs620_pwm, iqs620_pwm->duty_scale); |
| 157 | iqs620_pwm->duty_val); | ||
| 158 | if (ret) | ||
| 159 | goto err_mutex; | ||
| 160 | 151 | ||
| 161 | ret = regmap_update_bits(iqs62x->regmap, IQS620_PWR_SETTINGS, | ||
| 162 | IQS620_PWR_SETTINGS_PWM_OUT, | ||
| 163 | iqs620_pwm->out_en ? 0xff : 0); | ||
| 164 | |||
| 165 | err_mutex: | ||
| 166 | mutex_unlock(&iqs620_pwm->lock); | 152 | mutex_unlock(&iqs620_pwm->lock); |
| 167 | 153 | ||
| 168 | if (ret) { | 154 | if (ret) { |
| @@ -209,12 +195,14 @@ static int iqs620_pwm_probe(struct platform_device *pdev) · 40 unmodified lines | |||
| 209 | ret = regmap_read(iqs62x->regmap, IQS620_PWR_SETTINGS, &val); | 195 | ret = regmap_read(iqs62x->regmap, IQS620_PWR_SETTINGS, &val); |
| 210 | if (ret) | 196 | if (ret) |
| 211 | return ret; | 197 | return ret; |
| 212 | iqs620_pwm->out_en = val & IQS620_PWR_SETTINGS_PWM_OUT; | ||
| 213 | 198 | ||
| 214 | ret = regmap_read(iqs62x->regmap, IQS620_PWM_DUTY_CYCLE, &val); | 199 | if (val & IQS620_PWR_SETTINGS_PWM_OUT) { |
| 215 | if (ret) | 200 | ret = regmap_read(iqs62x->regmap, IQS620_PWM_DUTY_CYCLE, &val); |
| 216 | return ret; | 201 | if (ret) |
| 217 | iqs620_pwm->duty_val = val; | 202 | return ret; |
| 203 | |||
| 204 | iqs620_pwm->duty_scale = val + 1; | ||
| 205 | } | ||
| 218 | 206 | ||
| 219 | iqs620_pwm->chip.dev = &pdev->dev; | 207 | iqs620_pwm->chip.dev = &pdev->dev; |
| 220 | iqs620_pwm->chip.ops = &iqs620_pwm_ops; | 208 | iqs620_pwm->chip.ops = &iqs620_pwm_ops; |
| @@ -289,7 +289,7 @@ static int lpc18xx_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm) · 288 unmodified lines | |||
| 289 | dev_err(lpc18xx_pwm->dev, | 289 | dev_err(lpc18xx_pwm->dev, |
| 290 | "maximum number of simultaneous channels reached\n"); | 290 | "maximum number of simultaneous channels reached\n"); |
| 291 | return -EBUSY; | 291 | return -EBUSY; |
| 292 | }; | 292 | } |
| 293 | 293 | ||
| 294 | set_bit(event, &lpc18xx_pwm->event_map); | 294 | set_bit(event, &lpc18xx_pwm->event_map); |
| 295 | lpc18xx_data->duty_event = event; | 295 | lpc18xx_data->duty_event = event; |
| @@ -72,6 +72,10 @@ static void rockchip_pwm_get_state(struct pwm_chip *chip, · 71 unmodified lines | |||
| 72 | if (ret) | 72 | if (ret) |
| 73 | return; | 73 | return; |
| 74 | 74 | ||
| 75 | ret = clk_enable(pc->clk); | ||
| 76 | if (ret) | ||
| 77 | return; | ||
| 78 | |||
| 75 | clk_rate = clk_get_rate(pc->clk); | 79 | clk_rate = clk_get_rate(pc->clk); |
| 76 | 80 | ||
| 77 | tmp = readl_relaxed(pc->base + pc->data->regs.period); | 81 | tmp = readl_relaxed(pc->base + pc->data->regs.period); |
| @@ -90,6 +94,7 @@ static void rockchip_pwm_get_state(struct pwm_chip *chip, · 12 unmodified lines | |||
| 90 | else | 94 | else |
| 91 | state->polarity = PWM_POLARITY_NORMAL; | 95 | state->polarity = PWM_POLARITY_NORMAL; |
| 92 | 96 | ||
| 97 | clk_disable(pc->clk); | ||
| 93 | clk_disable(pc->pclk); | 98 | clk_disable(pc->pclk); |
| 94 | } | 99 | } |
| 95 | 100 | ||
| @@ -189,6 +194,10 @@ static int rockchip_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, · 93 unmodified lines | |||
| 189 | if (ret) | 194 | if (ret) |
| 190 | return ret; | 195 | return ret; |
| 191 | 196 | ||
| 197 | ret = clk_enable(pc->clk); | ||
| 198 | if (ret) | ||
| 199 | return ret; | ||
| 200 | |||
| 192 | pwm_get_state(pwm, &curstate); | 201 | pwm_get_state(pwm, &curstate); |
| 193 | enabled = curstate.enabled; | 202 | enabled = curstate.enabled; |
| 194 | 203 | ||
| @@ -208,6 +217,7 @@ static int rockchip_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, · 13 unmodified lines | |||
| 208 | } | 217 | } |
| 209 | 218 | ||
| 210 | out: | 219 | out: |
| 220 | clk_disable(pc->clk); | ||
| 211 | clk_disable(pc->pclk); | 221 | clk_disable(pc->pclk); |
| 212 | 222 | ||
| 213 | return ret; | 223 | return ret; |
| @@ -288,6 +298,7 @@ static int rockchip_pwm_probe(struct platform_device *pdev) · 74 unmodified lines | |||
| 288 | const struct of_device_id *id; | 298 | const struct of_device_id *id; |
| 289 | struct rockchip_pwm_chip *pc; | 299 | struct rockchip_pwm_chip *pc; |
| 290 | u32 enable_conf, ctrl; | 300 | u32 enable_conf, ctrl; |
| 301 | bool enabled; | ||
| 291 | int ret, count; | 302 | int ret, count; |
| 292 | 303 | ||
| 293 | id = of_match_device(rockchip_pwm_dt_ids, &pdev->dev); | 304 | id = of_match_device(rockchip_pwm_dt_ids, &pdev->dev); |
| @@ -307,7 +318,7 @@ static int rockchip_pwm_probe(struct platform_device *pdev) · 13 unmodified lines | |||
| 307 | pc->clk = devm_clk_get(&pdev->dev, NULL); | 318 | pc->clk = devm_clk_get(&pdev->dev, NULL); |
| 308 | if (IS_ERR(pc->clk)) | 319 | if (IS_ERR(pc->clk)) |
| 309 | return dev_err_probe(&pdev->dev, PTR_ERR(pc->clk), | 320 | return dev_err_probe(&pdev->dev, PTR_ERR(pc->clk), |
| 310 | "Can't get bus clk\n"); | 321 | "Can't get PWM clk\n"); |
| 311 | } | 322 | } |
| 312 | 323 | ||
| 313 | count = of_count_phandle_with_args(pdev->dev.of_node, | 324 | count = of_count_phandle_with_args(pdev->dev.of_node, |
| @@ -326,13 +337,13 @@ static int rockchip_pwm_probe(struct platform_device *pdev) · 12 unmodified lines | |||
| 326 | 337 | ||
| 327 | ret = clk_prepare_enable(pc->clk); | 338 | ret = clk_prepare_enable(pc->clk); |
| 328 | if (ret) { | 339 | if (ret) { |
| 329 | dev_err(&pdev->dev, "Can't prepare enable bus clk: %d\n", ret); | 340 | dev_err(&pdev->dev, "Can't prepare enable PWM clk: %d\n", ret); |
| 330 | return ret; | 341 | return ret; |
| 331 | } | 342 | } |
| 332 | 343 | ||
| 333 | ret = clk_prepare(pc->pclk); | 344 | ret = clk_prepare_enable(pc->pclk); |
| 334 | if (ret) { | 345 | if (ret) { |
| 335 | dev_err(&pdev->dev, "Can't prepare APB clk: %d\n", ret); | 346 | dev_err(&pdev->dev, "Can't prepare enable APB clk: %d\n", ret); |
| 336 | goto err_clk; | 347 | goto err_clk; |
| 337 | } | 348 | } |
| 338 | 349 | ||
| @@ -349,23 +360,26 @@ static int rockchip_pwm_probe(struct platform_device *pdev) · 10 unmodified lines | |||
| 349 | pc->chip.of_pwm_n_cells = 3; | 360 | pc->chip.of_pwm_n_cells = 3; |
| 350 | } | 361 | } |
| 351 | 362 | ||
| 363 | enable_conf = pc->data->enable_conf; | ||
| 364 | ctrl = readl_relaxed(pc->base + pc->data->regs.ctrl); | ||
| 365 | enabled = (ctrl & enable_conf) == enable_conf; | ||
| 366 | |||
| 352 | ret = pwmchip_add(&pc->chip); | 367 | ret = pwmchip_add(&pc->chip); |
| 353 | if (ret < 0) { | 368 | if (ret < 0) { |
| 354 | clk_unprepare(pc->clk); | ||
| 355 | dev_err(&pdev->dev, "pwmchip_add() failed: %d\n", ret); | 369 | dev_err(&pdev->dev, "pwmchip_add() failed: %d\n", ret); |
| 356 | goto err_pclk; | 370 | goto err_pclk; |
| 357 | } | 371 | } |
| 358 | 372 | ||
| 359 | /* Keep the PWM clk enabled if the PWM appears to be up and running. */ | 373 | /* Keep the PWM clk enabled if the PWM appears to be up and running. */ |
| 360 | enable_conf = pc->data->enable_conf; | 374 | if (!enabled) |
| 361 | ctrl = readl_relaxed(pc->base + pc->data->regs.ctrl); | ||
| 362 | if ((ctrl & enable_conf) != enable_conf) | ||
| 363 | clk_disable(pc->clk); | 375 | clk_disable(pc->clk); |
| 364 | 376 | ||
| 377 | clk_disable(pc->pclk); | ||
| 378 | |||
| 365 | return 0; | 379 | return 0; |
| 366 | 380 | ||
| 367 | err_pclk: | 381 | err_pclk: |
| 368 | clk_unprepare(pc->pclk); | 382 | clk_disable_unprepare(pc->pclk); |
| 369 | err_clk: | 383 | err_clk: |
| 370 | clk_disable_unprepare(pc->clk); | 384 | clk_disable_unprepare(pc->clk); |
| 371 | 385 | ||
| @@ -1,278 +0,0 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0-only | ||
| 2 | /* | ||
| 3 | * Copyright (C) 2017 Sanechips Technology Co., Ltd. | ||
| 4 | * Copyright 2017 Linaro Ltd. | ||
| 5 | */ | ||
| 6 | |||
| 7 | #include <linux/clk.h> | ||
| 8 | #include <linux/err.h> | ||
| 9 | #include <linux/io.h> | ||
| 10 | #include <linux/kernel.h> | ||
| 11 | #include <linux/module.h> | ||
| 12 | #include <linux/platform_device.h> | ||
| 13 | #include <linux/pwm.h> | ||
| 14 | #include <linux/slab.h> | ||
| 15 | |||
| 16 | #define ZX_PWM_MODE 0x0 | ||
| 17 | #define ZX_PWM_CLKDIV_SHIFT 2 | ||
| 18 | #define ZX_PWM_CLKDIV_MASK GENMASK(11, 2) | ||
| 19 | #define ZX_PWM_CLKDIV(x) (((x) << ZX_PWM_CLKDIV_SHIFT) & \ | ||
| 20 | ZX_PWM_CLKDIV_MASK) | ||
| 21 | #define ZX_PWM_POLAR BIT(1) | ||
| 22 | #define ZX_PWM_EN BIT(0) | ||
| 23 | #define ZX_PWM_PERIOD 0x4 | ||
| 24 | #define ZX_PWM_DUTY 0x8 | ||
| 25 | |||
| 26 | #define ZX_PWM_CLKDIV_MAX 1023 | ||
| 27 | #define ZX_PWM_PERIOD_MAX 65535 | ||
| 28 | |||
| 29 | struct zx_pwm_chip { | ||
| 30 | struct pwm_chip chip; | ||
| 31 | struct clk *pclk; | ||
| 32 | struct clk *wclk; | ||
| 33 | void __iomem *base; | ||
| 34 | }; | ||
| 35 | |||
| 36 | static inline struct zx_pwm_chip *to_zx_pwm_chip(struct pwm_chip *chip) | ||
| 37 | { | ||
| 38 | return container_of(chip, struct zx_pwm_chip, chip); | ||
| 39 | } | ||
| 40 | |||
| 41 | static inline u32 zx_pwm_readl(struct zx_pwm_chip *zpc, unsigned int hwpwm, | ||
| 42 | unsigned int offset) | ||
| 43 | { | ||
| 44 | return readl(zpc->base + (hwpwm + 1) * 0x10 + offset); | ||
| 45 | } | ||
| 46 | |||
| 47 | static inline void zx_pwm_writel(struct zx_pwm_chip *zpc, unsigned int hwpwm, | ||
| 48 | unsigned int offset, u32 value) | ||
| 49 | { | ||
| 50 | writel(value, zpc->base + (hwpwm + 1) * 0x10 + offset); | ||
| 51 | } | ||
| 52 | |||
| 53 | static void zx_pwm_set_mask(struct zx_pwm_chip *zpc, unsigned int hwpwm, | ||
| 54 | unsigned int offset, u32 mask, u32 value) | ||
| 55 | { | ||
| 56 | u32 data; | ||
| 57 | |||
| 58 | data = zx_pwm_readl(zpc, hwpwm, offset); | ||
| 59 | data &= ~mask; | ||
| 60 | data |= value & mask; | ||
| 61 | zx_pwm_writel(zpc, hwpwm, offset, data); | ||
| 62 | } | ||
| 63 | |||
| 64 | static void zx_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm, | ||
| 65 | struct pwm_state *state) | ||
| 66 | { | ||
| 67 | struct zx_pwm_chip *zpc = to_zx_pwm_chip(chip); | ||
| 68 | unsigned long rate; | ||
| 69 | unsigned int div; | ||
| 70 | u32 value; | ||
| 71 | u64 tmp; | ||
| 72 | |||
| 73 | value = zx_pwm_readl(zpc, pwm->hwpwm, ZX_PWM_MODE); | ||
| 74 | |||
| 75 | if (value & ZX_PWM_POLAR) | ||
| 76 | state->polarity = PWM_POLARITY_NORMAL; | ||
| 77 | else | ||
| 78 | state->polarity = PWM_POLARITY_INVERSED; | ||
| 79 | |||
| 80 | if (value & ZX_PWM_EN) | ||
| 81 | state->enabled = true; | ||
| 82 | else | ||
| 83 | state->enabled = false; | ||
| 84 | |||
| 85 | div = (value & ZX_PWM_CLKDIV_MASK) >> ZX_PWM_CLKDIV_SHIFT; | ||
| 86 | rate = clk_get_rate(zpc->wclk); | ||
| 87 | |||
| 88 | tmp = zx_pwm_readl(zpc, pwm->hwpwm, ZX_PWM_PERIOD); | ||
| 89 | tmp *= div * NSEC_PER_SEC; | ||
| 90 | state->period = DIV_ROUND_CLOSEST_ULL(tmp, rate); | ||
| 91 | |||
| 92 | tmp = zx_pwm_readl(zpc, pwm->hwpwm, ZX_PWM_DUTY); | ||
| 93 | tmp *= div * NSEC_PER_SEC; | ||
| 94 | state->duty_cycle = DIV_ROUND_CLOSEST_ULL(tmp, rate); | ||
| 95 | } | ||
| 96 | |||
| 97 | static int zx_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, | ||
| 98 | unsigned int duty_ns, unsigned int period_ns) | ||
| 99 | { | ||
| 100 | struct zx_pwm_chip *zpc = to_zx_pwm_chip(chip); | ||
| 101 | unsigned int period_cycles, duty_cycles; | ||
| 102 | unsigned long long c; | ||
| 103 | unsigned int div = 1; | ||
| 104 | unsigned long rate; | ||
| 105 | |||
| 106 | /* Find out the best divider */ | ||
| 107 | rate = clk_get_rate(zpc->wclk); | ||
| 108 | |||
| 109 | while (1) { | ||
| 110 | c = rate / div; | ||
| 111 | c = c * period_ns; | ||
| 112 | do_div(c, NSEC_PER_SEC); | ||
| 113 | |||
| 114 | if (c < ZX_PWM_PERIOD_MAX) | ||
| 115 | break; | ||
| 116 | |||
| 117 | div++; | ||
| 118 | |||
| 119 | if (div > ZX_PWM_CLKDIV_MAX) | ||
| 120 | return -ERANGE; | ||
| 121 | } | ||
| 122 | |||
| 123 | /* Calculate duty cycles */ | ||
| 124 | period_cycles = c; | ||
| 125 | c *= duty_ns; | ||
| 126 | do_div(c, period_ns); | ||
| 127 | duty_cycles = c; | ||
| 128 | |||
| 129 | /* | ||
| 130 | * If the PWM is being enabled, we have to temporarily disable it | ||
| 131 | * before configuring the registers. | ||
| 132 | */ | ||
| 133 | if (pwm_is_enabled(pwm)) | ||
| 134 | zx_pwm_set_mask(zpc, pwm->hwpwm, ZX_PWM_MODE, ZX_PWM_EN, 0); | ||
| 135 | |||
| 136 | /* Set up registers */ | ||
| 137 | zx_pwm_set_mask(zpc, pwm->hwpwm, ZX_PWM_MODE, ZX_PWM_CLKDIV_MASK, | ||
| 138 | ZX_PWM_CLKDIV(div)); | ||
| 139 | zx_pwm_writel(zpc, pwm->hwpwm, ZX_PWM_PERIOD, period_cycles); | ||
| 140 | zx_pwm_writel(zpc, pwm->hwpwm, ZX_PWM_DUTY, duty_cycles); | ||
| 141 | |||
| 142 | /* Re-enable the PWM if needed */ | ||
| 143 | if (pwm_is_enabled(pwm)) | ||
| 144 | zx_pwm_set_mask(zpc, pwm->hwpwm, ZX_PWM_MODE, | ||
| 145 | ZX_PWM_EN, ZX_PWM_EN); | ||
| 146 | |||
| 147 | return 0; | ||
| 148 | } | ||
| 149 | |||
| 150 | static int zx_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, | ||
| 151 | const struct pwm_state *state) | ||
| 152 | { | ||
| 153 | struct zx_pwm_chip *zpc = to_zx_pwm_chip(chip); | ||
| 154 | struct pwm_state cstate; | ||
| 155 | int ret; | ||
| 156 | |||
| 157 | pwm_get_state(pwm, &cstate); | ||
| 158 | |||
| 159 | if (state->polarity != cstate.polarity) | ||
| 160 | zx_pwm_set_mask(zpc, pwm->hwpwm, ZX_PWM_MODE, ZX_PWM_POLAR, | ||
| 161 | (state->polarity == PWM_POLARITY_INVERSED) ? | ||
| 162 | 0 : ZX_PWM_POLAR); | ||
| 163 | |||
| 164 | if (state->period != cstate.period || | ||
| 165 | state->duty_cycle != cstate.duty_cycle) { | ||
| 166 | ret = zx_pwm_config(chip, pwm, state->duty_cycle, | ||
| 167 | state->period); | ||
| 168 | if (ret) | ||
| 169 | return ret; | ||
| 170 | } | ||
| 171 | |||
| 172 | if (state->enabled != cstate.enabled) { | ||
| 173 | if (state->enabled) { | ||
| 174 | ret = clk_prepare_enable(zpc->wclk); | ||
| 175 | if (ret) | ||
| 176 | return ret; | ||
| 177 | |||
| 178 | zx_pwm_set_mask(zpc, pwm->hwpwm, ZX_PWM_MODE, | ||
| 179 | ZX_PWM_EN, ZX_PWM_EN); | ||
| 180 | } else { | ||
| 181 | zx_pwm_set_mask(zpc, pwm->hwpwm, ZX_PWM_MODE, | ||
| 182 | ZX_PWM_EN, 0); | ||
| 183 | clk_disable_unprepare(zpc->wclk); | ||
| 184 | } | ||
| 185 | } | ||
| 186 | |||
| 187 | return 0; | ||
| 188 | } | ||
| 189 | |||
| 190 | static const struct pwm_ops zx_pwm_ops = { | ||
| 191 | .apply = zx_pwm_apply, | ||
| 192 | .get_state = zx_pwm_get_state, | ||
| 193 | .owner = THIS_MODULE, | ||
| 194 | }; | ||
| 195 | |||
| 196 | static int zx_pwm_probe(struct platform_device *pdev) | ||
| 197 | { | ||
| 198 | struct zx_pwm_chip *zpc; | ||
| 199 | unsigned int i; | ||
| 200 | int ret; | ||
| 201 | |||
| 202 | zpc = devm_kzalloc(&pdev->dev, sizeof(*zpc), GFP_KERNEL); | ||
| 203 | if (!zpc) | ||
| 204 | return -ENOMEM; | ||
| 205 | |||
| 206 | zpc->base = devm_platform_ioremap_resource(pdev, 0); | ||
| 207 | if (IS_ERR(zpc->base)) | ||
| 208 | return PTR_ERR(zpc->base); | ||
| 209 | |||
| 210 | zpc->pclk = devm_clk_get(&pdev->dev, "pclk"); | ||
| 211 | if (IS_ERR(zpc->pclk)) | ||
| 212 | return PTR_ERR(zpc->pclk); | ||
| 213 | |||
| 214 | zpc->wclk = devm_clk_get(&pdev->dev, "wclk"); | ||
| 215 | if (IS_ERR(zpc->wclk)) | ||
| 216 | return PTR_ERR(zpc->wclk); | ||
| 217 | |||
| 218 | ret = clk_prepare_enable(zpc->pclk); | ||
| 219 | if (ret) | ||
| 220 | return ret; | ||
| 221 | |||
| 222 | zpc->chip.dev = &pdev->dev; | ||
| 223 | zpc->chip.ops = &zx_pwm_ops; | ||
| 224 | zpc->chip.base = -1; | ||
| 225 | zpc->chip.npwm = 4; | ||
| 226 | zpc->chip.of_xlate = of_pwm_xlate_with_flags; | ||
| 227 | zpc->chip.of_pwm_n_cells = 3; | ||
| 228 | |||
| 229 | /* | ||
| 230 | * PWM devices may be enabled by firmware, and let's disable all of | ||
| 231 | * them initially to save power. | ||
| 232 | */ | ||
| 233 | for (i = 0; i < zpc->chip.npwm; i++) | ||
| 234 | zx_pwm_set_mask(zpc, i, ZX_PWM_MODE, ZX_PWM_EN, 0); | ||
| 235 | |||
| 236 | ret = pwmchip_add(&zpc->chip); | ||
| 237 | if (ret < 0) { | ||
| 238 | dev_err(&pdev->dev, "failed to add PWM chip: %d\n", ret); | ||
| 239 | clk_disable_unprepare(zpc->pclk); | ||
| 240 | return ret; | ||
| 241 | } | ||
| 242 | |||
| 243 | platform_set_drvdata(pdev, zpc); | ||
| 244 | |||
| 245 | return 0; | ||
| 246 | } | ||
| 247 | |||
| 248 | static int zx_pwm_remove(struct platform_device *pdev) | ||
| 249 | { | ||
| 250 | struct zx_pwm_chip *zpc = platform_get_drvdata(pdev); | ||
| 251 | int ret; | ||
| 252 | |||
| 253 | ret = pwmchip_remove(&zpc->chip); | ||
| 254 | clk_disable_unprepare(zpc->pclk); | ||
| 255 | |||
| 256 | return ret; | ||
| 257 | } | ||
| 258 | |||
| 259 | static const struct of_device_id zx_pwm_dt_ids[] = { | ||
| 260 | { .compatible = "zte,zx296718-pwm", }, | ||
| 261 | { /* sentinel */ } | ||
| 262 | }; | ||
| 263 | MODULE_DEVICE_TABLE(of, zx_pwm_dt_ids); | ||
| 264 | |||
| 265 | static struct platform_driver zx_pwm_driver = { | ||
| 266 | .driver = { | ||
| 267 | .name = "zx-pwm", | ||
| 268 | .of_match_table = zx_pwm_dt_ids, | ||
| 269 | }, | ||
| 270 | .probe = zx_pwm_probe, | ||
| 271 | .remove = zx_pwm_remove, | ||
| 272 | }; | ||
| 273 | module_platform_driver(zx_pwm_driver); | ||
| 274 | |||
| 275 | MODULE_ALIAS("platform:zx-pwm"); | ||
| 276 | MODULE_AUTHOR("Shawn Guo <shawn.guo@linaro.org>"); | ||
| 277 | MODULE_DESCRIPTION("ZTE ZX PWM Driver"); | ||
| 278 | MODULE_LICENSE("GPL v2"); | ||