diff options
-rw-r--r-- | drivers/pwm/Kconfig | 2 | ||||
-rw-r--r-- | drivers/pwm/pwm-brcmstb.c | 4 | ||||
-rw-r--r-- | drivers/pwm/pwm-img.c | 5 | ||||
-rw-r--r-- | drivers/pwm/pwm-lpc18xx-sct.c | 5 | ||||
-rw-r--r-- | drivers/pwm/pwm-omap-dmtimer.c | 74 |
5 files changed, 71 insertions, 19 deletions
diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig index 8cf0dae78555..c182efc62c7b 100644 --- a/drivers/pwm/Kconfig +++ b/drivers/pwm/Kconfig | |||
@@ -316,7 +316,7 @@ config PWM_RCAR | |||
316 | 316 | ||
317 | config PWM_RENESAS_TPU | 317 | config PWM_RENESAS_TPU |
318 | tristate "Renesas TPU PWM support" | 318 | tristate "Renesas TPU PWM support" |
319 | depends on ARCH_SHMOBILE || COMPILE_TEST | 319 | depends on ARCH_RENESAS || COMPILE_TEST |
320 | depends on HAS_IOMEM | 320 | depends on HAS_IOMEM |
321 | help | 321 | help |
322 | This driver exposes the Timer Pulse Unit (TPU) PWM controller found | 322 | This driver exposes the Timer Pulse Unit (TPU) PWM controller found |
diff --git a/drivers/pwm/pwm-brcmstb.c b/drivers/pwm/pwm-brcmstb.c index 423ce087cd9c..5d5adee16886 100644 --- a/drivers/pwm/pwm-brcmstb.c +++ b/drivers/pwm/pwm-brcmstb.c | |||
@@ -274,8 +274,8 @@ static int brcmstb_pwm_probe(struct platform_device *pdev) | |||
274 | 274 | ||
275 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 275 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
276 | p->base = devm_ioremap_resource(&pdev->dev, res); | 276 | p->base = devm_ioremap_resource(&pdev->dev, res); |
277 | if (!p->base) { | 277 | if (IS_ERR(p->base)) { |
278 | ret = -ENOMEM; | 278 | ret = PTR_ERR(p->base); |
279 | goto out_clk; | 279 | goto out_clk; |
280 | } | 280 | } |
281 | 281 | ||
diff --git a/drivers/pwm/pwm-img.c b/drivers/pwm/pwm-img.c index 8a029f9bc18c..2fb30deee345 100644 --- a/drivers/pwm/pwm-img.c +++ b/drivers/pwm/pwm-img.c | |||
@@ -237,6 +237,11 @@ static int img_pwm_probe(struct platform_device *pdev) | |||
237 | } | 237 | } |
238 | 238 | ||
239 | clk_rate = clk_get_rate(pwm->pwm_clk); | 239 | clk_rate = clk_get_rate(pwm->pwm_clk); |
240 | if (!clk_rate) { | ||
241 | dev_err(&pdev->dev, "pwm clock has no frequency\n"); | ||
242 | ret = -EINVAL; | ||
243 | goto disable_pwmclk; | ||
244 | } | ||
240 | 245 | ||
241 | /* The maximum input clock divider is 512 */ | 246 | /* The maximum input clock divider is 512 */ |
242 | val = (u64)NSEC_PER_SEC * 512 * pwm->data->max_timebase; | 247 | val = (u64)NSEC_PER_SEC * 512 * pwm->data->max_timebase; |
diff --git a/drivers/pwm/pwm-lpc18xx-sct.c b/drivers/pwm/pwm-lpc18xx-sct.c index 9163085101bc..9861fed4e67d 100644 --- a/drivers/pwm/pwm-lpc18xx-sct.c +++ b/drivers/pwm/pwm-lpc18xx-sct.c | |||
@@ -360,6 +360,11 @@ static int lpc18xx_pwm_probe(struct platform_device *pdev) | |||
360 | } | 360 | } |
361 | 361 | ||
362 | lpc18xx_pwm->clk_rate = clk_get_rate(lpc18xx_pwm->pwm_clk); | 362 | lpc18xx_pwm->clk_rate = clk_get_rate(lpc18xx_pwm->pwm_clk); |
363 | if (!lpc18xx_pwm->clk_rate) { | ||
364 | dev_err(&pdev->dev, "pwm clock has no frequency\n"); | ||
365 | ret = -EINVAL; | ||
366 | goto disable_pwmclk; | ||
367 | } | ||
363 | 368 | ||
364 | mutex_init(&lpc18xx_pwm->res_lock); | 369 | mutex_init(&lpc18xx_pwm->res_lock); |
365 | mutex_init(&lpc18xx_pwm->period_lock); | 370 | mutex_init(&lpc18xx_pwm->period_lock); |
diff --git a/drivers/pwm/pwm-omap-dmtimer.c b/drivers/pwm/pwm-omap-dmtimer.c index 826634ec0d5c..b7e6ecba7d5c 100644 --- a/drivers/pwm/pwm-omap-dmtimer.c +++ b/drivers/pwm/pwm-omap-dmtimer.c | |||
@@ -31,6 +31,7 @@ | |||
31 | #include <linux/time.h> | 31 | #include <linux/time.h> |
32 | 32 | ||
33 | #define DM_TIMER_LOAD_MIN 0xfffffffe | 33 | #define DM_TIMER_LOAD_MIN 0xfffffffe |
34 | #define DM_TIMER_MAX 0xffffffff | ||
34 | 35 | ||
35 | struct pwm_omap_dmtimer_chip { | 36 | struct pwm_omap_dmtimer_chip { |
36 | struct pwm_chip chip; | 37 | struct pwm_chip chip; |
@@ -46,13 +47,9 @@ to_pwm_omap_dmtimer_chip(struct pwm_chip *chip) | |||
46 | return container_of(chip, struct pwm_omap_dmtimer_chip, chip); | 47 | return container_of(chip, struct pwm_omap_dmtimer_chip, chip); |
47 | } | 48 | } |
48 | 49 | ||
49 | static int pwm_omap_dmtimer_calc_value(unsigned long clk_rate, int ns) | 50 | static u32 pwm_omap_dmtimer_get_clock_cycles(unsigned long clk_rate, int ns) |
50 | { | 51 | { |
51 | u64 c = (u64)clk_rate * ns; | 52 | return DIV_ROUND_CLOSEST_ULL((u64)clk_rate * ns, NSEC_PER_SEC); |
52 | |||
53 | do_div(c, NSEC_PER_SEC); | ||
54 | |||
55 | return DM_TIMER_LOAD_MIN - c; | ||
56 | } | 53 | } |
57 | 54 | ||
58 | static void pwm_omap_dmtimer_start(struct pwm_omap_dmtimer_chip *omap) | 55 | static void pwm_omap_dmtimer_start(struct pwm_omap_dmtimer_chip *omap) |
@@ -99,12 +96,14 @@ static int pwm_omap_dmtimer_config(struct pwm_chip *chip, | |||
99 | int duty_ns, int period_ns) | 96 | int duty_ns, int period_ns) |
100 | { | 97 | { |
101 | struct pwm_omap_dmtimer_chip *omap = to_pwm_omap_dmtimer_chip(chip); | 98 | struct pwm_omap_dmtimer_chip *omap = to_pwm_omap_dmtimer_chip(chip); |
102 | int load_value, match_value; | 99 | u32 period_cycles, duty_cycles; |
100 | u32 load_value, match_value; | ||
103 | struct clk *fclk; | 101 | struct clk *fclk; |
104 | unsigned long clk_rate; | 102 | unsigned long clk_rate; |
105 | bool timer_active; | 103 | bool timer_active; |
106 | 104 | ||
107 | dev_dbg(chip->dev, "duty cycle: %d, period %d\n", duty_ns, period_ns); | 105 | dev_dbg(chip->dev, "requested duty cycle: %d ns, period: %d ns\n", |
106 | duty_ns, period_ns); | ||
108 | 107 | ||
109 | mutex_lock(&omap->mutex); | 108 | mutex_lock(&omap->mutex); |
110 | if (duty_ns == pwm_get_duty_cycle(pwm) && | 109 | if (duty_ns == pwm_get_duty_cycle(pwm) && |
@@ -117,15 +116,13 @@ static int pwm_omap_dmtimer_config(struct pwm_chip *chip, | |||
117 | fclk = omap->pdata->get_fclk(omap->dm_timer); | 116 | fclk = omap->pdata->get_fclk(omap->dm_timer); |
118 | if (!fclk) { | 117 | if (!fclk) { |
119 | dev_err(chip->dev, "invalid pmtimer fclk\n"); | 118 | dev_err(chip->dev, "invalid pmtimer fclk\n"); |
120 | mutex_unlock(&omap->mutex); | 119 | goto err_einval; |
121 | return -EINVAL; | ||
122 | } | 120 | } |
123 | 121 | ||
124 | clk_rate = clk_get_rate(fclk); | 122 | clk_rate = clk_get_rate(fclk); |
125 | if (!clk_rate) { | 123 | if (!clk_rate) { |
126 | dev_err(chip->dev, "invalid pmtimer fclk rate\n"); | 124 | dev_err(chip->dev, "invalid pmtimer fclk rate\n"); |
127 | mutex_unlock(&omap->mutex); | 125 | goto err_einval; |
128 | return -EINVAL; | ||
129 | } | 126 | } |
130 | 127 | ||
131 | dev_dbg(chip->dev, "clk rate: %luHz\n", clk_rate); | 128 | dev_dbg(chip->dev, "clk rate: %luHz\n", clk_rate); |
@@ -133,11 +130,51 @@ static int pwm_omap_dmtimer_config(struct pwm_chip *chip, | |||
133 | /* | 130 | /* |
134 | * Calculate the appropriate load and match values based on the | 131 | * Calculate the appropriate load and match values based on the |
135 | * specified period and duty cycle. The load value determines the | 132 | * specified period and duty cycle. The load value determines the |
136 | * cycle time and the match value determines the duty cycle. | 133 | * period time and the match value determines the duty time. |
134 | * | ||
135 | * The period lasts for (DM_TIMER_MAX-load_value+1) clock cycles. | ||
136 | * Similarly, the active time lasts (match_value-load_value+1) cycles. | ||
137 | * The non-active time is the remainder: (DM_TIMER_MAX-match_value) | ||
138 | * clock cycles. | ||
139 | * | ||
140 | * NOTE: It is required that: load_value <= match_value < DM_TIMER_MAX | ||
141 | * | ||
142 | * References: | ||
143 | * OMAP4430/60/70 TRM sections 22.2.4.10 and 22.2.4.11 | ||
144 | * AM335x Sitara TRM sections 20.1.3.5 and 20.1.3.6 | ||
137 | */ | 145 | */ |
138 | load_value = pwm_omap_dmtimer_calc_value(clk_rate, period_ns); | 146 | period_cycles = pwm_omap_dmtimer_get_clock_cycles(clk_rate, period_ns); |
139 | match_value = pwm_omap_dmtimer_calc_value(clk_rate, | 147 | duty_cycles = pwm_omap_dmtimer_get_clock_cycles(clk_rate, duty_ns); |
140 | period_ns - duty_ns); | 148 | |
149 | if (period_cycles < 2) { | ||
150 | dev_info(chip->dev, | ||
151 | "period %d ns too short for clock rate %lu Hz\n", | ||
152 | period_ns, clk_rate); | ||
153 | goto err_einval; | ||
154 | } | ||
155 | |||
156 | if (duty_cycles < 1) { | ||
157 | dev_dbg(chip->dev, | ||
158 | "duty cycle %d ns is too short for clock rate %lu Hz\n", | ||
159 | duty_ns, clk_rate); | ||
160 | dev_dbg(chip->dev, "using minimum of 1 clock cycle\n"); | ||
161 | duty_cycles = 1; | ||
162 | } else if (duty_cycles >= period_cycles) { | ||
163 | dev_dbg(chip->dev, | ||
164 | "duty cycle %d ns is too long for period %d ns at clock rate %lu Hz\n", | ||
165 | duty_ns, period_ns, clk_rate); | ||
166 | dev_dbg(chip->dev, "using maximum of 1 clock cycle less than period\n"); | ||
167 | duty_cycles = period_cycles - 1; | ||
168 | } | ||
169 | |||
170 | dev_dbg(chip->dev, "effective duty cycle: %lld ns, period: %lld ns\n", | ||
171 | DIV_ROUND_CLOSEST_ULL((u64)NSEC_PER_SEC * duty_cycles, | ||
172 | clk_rate), | ||
173 | DIV_ROUND_CLOSEST_ULL((u64)NSEC_PER_SEC * period_cycles, | ||
174 | clk_rate)); | ||
175 | |||
176 | load_value = (DM_TIMER_MAX - period_cycles) + 1; | ||
177 | match_value = load_value + duty_cycles - 1; | ||
141 | 178 | ||
142 | /* | 179 | /* |
143 | * We MUST stop the associated dual-mode timer before attempting to | 180 | * We MUST stop the associated dual-mode timer before attempting to |
@@ -166,6 +203,11 @@ static int pwm_omap_dmtimer_config(struct pwm_chip *chip, | |||
166 | mutex_unlock(&omap->mutex); | 203 | mutex_unlock(&omap->mutex); |
167 | 204 | ||
168 | return 0; | 205 | return 0; |
206 | |||
207 | err_einval: | ||
208 | mutex_unlock(&omap->mutex); | ||
209 | |||
210 | return -EINVAL; | ||
169 | } | 211 | } |
170 | 212 | ||
171 | static int pwm_omap_dmtimer_set_polarity(struct pwm_chip *chip, | 213 | static int pwm_omap_dmtimer_set_polarity(struct pwm_chip *chip, |