Add a configurable clock base rate for the pwm as when being built for non-PCI the block may be sourced from an internal clock. Signed-off-by: Ben Dooks <ben.dooks@xxxxxxxxxx> -- v2: - removed the ifdef and merged the other clock patch in here --- drivers/pwm/pwm-dwc.c | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/drivers/pwm/pwm-dwc.c b/drivers/pwm/pwm-dwc.c index 235cb730c888..9067f32869f8 100644 --- a/drivers/pwm/pwm-dwc.c +++ b/drivers/pwm/pwm-dwc.c @@ -18,6 +18,7 @@ #include <linux/kernel.h> #include <linux/module.h> #include <linux/pci.h> +#include <linux/clk.h> #include <linux/platform_device.h> #include <linux/pm_runtime.h> #include <linux/pwm.h> @@ -35,7 +36,6 @@ #define DWC_TIMERS_COMP_VERSION 0xac #define DWC_TIMERS_TOTAL 8 -#define DWC_CLK_PERIOD_NS 10 /* Timer Control Register */ #define DWC_TIM_CTRL_EN BIT(0) @@ -54,6 +54,8 @@ struct dwc_pwm_ctx { struct dwc_pwm { struct pwm_chip chip; void __iomem *base; + struct clk *clk; + unsigned int clk_ns; struct dwc_pwm_ctx ctx[DWC_TIMERS_TOTAL]; }; #define to_dwc_pwm(p) (container_of((p), struct dwc_pwm, chip)) @@ -96,13 +98,13 @@ static int __dwc_pwm_configure_timer(struct dwc_pwm *dwc, * periods and check are the result within HW limits between 1 and * 2^32 periods. */ - tmp = DIV_ROUND_CLOSEST_ULL(state->duty_cycle, DWC_CLK_PERIOD_NS); + tmp = DIV_ROUND_CLOSEST_ULL(state->duty_cycle, dwc->clk_ns); if (tmp < 1 || tmp > (1ULL << 32)) return -ERANGE; low = tmp - 1; tmp = DIV_ROUND_CLOSEST_ULL(state->period - state->duty_cycle, - DWC_CLK_PERIOD_NS); + dwc->clk_ns); if (tmp < 1 || tmp > (1ULL << 32)) return -ERANGE; high = tmp - 1; @@ -177,12 +179,12 @@ static void dwc_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm, duty = dwc_pwm_readl(dwc, DWC_TIM_LD_CNT(pwm->hwpwm)); duty += 1; - duty *= DWC_CLK_PERIOD_NS; + duty *= dwc->clk_ns; state->duty_cycle = duty; period = dwc_pwm_readl(dwc, DWC_TIM_LD_CNT2(pwm->hwpwm)); period += 1; - period *= DWC_CLK_PERIOD_NS; + period *= dwc->clk_ns; period += duty; state->period = period; @@ -205,6 +207,7 @@ static struct dwc_pwm *dwc_pwm_alloc(struct device *dev) if (!dwc) return NULL; + dwc->clk_ns = 10; dwc->chip.dev = dev; dwc->chip.ops = &dwc_pwm_ops; dwc->chip.npwm = DWC_TIMERS_TOTAL; @@ -336,6 +339,14 @@ static int dwc_pwm_plat_probe(struct platform_device *pdev) return dev_err_probe(dev, PTR_ERR(dwc->base), "failed to map IO\n"); + dwc->clk = devm_clk_get(dev, "timer"); + if (IS_ERR(dwc->clk)) + return dev_err_probe(dev, PTR_ERR(dwc->clk), + "failed to get timer clock\n"); + + clk_prepare_enable(dwc->clk); + dwc->clk_ns = 1000000000 / clk_get_rate(dwc->clk); + ret = pwmchip_add(&dwc->chip); if (ret) return ret; @@ -347,6 +358,7 @@ static int dwc_pwm_plat_remove(struct platform_device *pdev) { struct dwc_pwm *dwc = platform_get_drvdata(pdev); + clk_disable_unprepare(dwc->clk); pwmchip_remove(&dwc->chip); return 0; } -- 2.35.1