aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pwm
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pwm')
-rw-r--r--drivers/pwm/pwm-fsl-ftm.c83
1 files changed, 44 insertions, 39 deletions
diff --git a/drivers/pwm/pwm-fsl-ftm.c b/drivers/pwm/pwm-fsl-ftm.c
index 96982da52d86..0f2cc7ef7784 100644
--- a/drivers/pwm/pwm-fsl-ftm.c
+++ b/drivers/pwm/pwm-fsl-ftm.c
@@ -18,6 +18,7 @@
18#include <linux/of_address.h> 18#include <linux/of_address.h>
19#include <linux/platform_device.h> 19#include <linux/platform_device.h>
20#include <linux/pwm.h> 20#include <linux/pwm.h>
21#include <linux/regmap.h>
21#include <linux/slab.h> 22#include <linux/slab.h>
22 23
23#define FTM_SC 0x00 24#define FTM_SC 0x00
@@ -82,7 +83,7 @@ struct fsl_pwm_chip {
82 unsigned int cnt_select; 83 unsigned int cnt_select;
83 unsigned int clk_ps; 84 unsigned int clk_ps;
84 85
85 void __iomem *base; 86 struct regmap *regmap;
86 87
87 int period_ns; 88 int period_ns;
88 89
@@ -218,10 +219,11 @@ static unsigned long fsl_pwm_calculate_duty(struct fsl_pwm_chip *fpc,
218 unsigned long period_ns, 219 unsigned long period_ns,
219 unsigned long duty_ns) 220 unsigned long duty_ns)
220{ 221{
221 unsigned long long val, duty; 222 unsigned long long duty;
223 u32 val;
222 224
223 val = readl(fpc->base + FTM_MOD); 225 regmap_read(fpc->regmap, FTM_MOD, &val);
224 duty = duty_ns * (val + 1); 226 duty = (unsigned long long)duty_ns * (val + 1);
225 do_div(duty, period_ns); 227 do_div(duty, period_ns);
226 228
227 return (unsigned long)duty; 229 return (unsigned long)duty;
@@ -231,7 +233,7 @@ static int fsl_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
231 int duty_ns, int period_ns) 233 int duty_ns, int period_ns)
232{ 234{
233 struct fsl_pwm_chip *fpc = to_fsl_chip(chip); 235 struct fsl_pwm_chip *fpc = to_fsl_chip(chip);
234 u32 val, period, duty; 236 u32 period, duty;
235 237
236 mutex_lock(&fpc->lock); 238 mutex_lock(&fpc->lock);
237 239
@@ -256,11 +258,9 @@ static int fsl_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
256 return -EINVAL; 258 return -EINVAL;
257 } 259 }
258 260
259 val = readl(fpc->base + FTM_SC); 261 regmap_update_bits(fpc->regmap, FTM_SC, FTM_SC_PS_MASK,
260 val &= ~FTM_SC_PS_MASK; 262 fpc->clk_ps);
261 val |= fpc->clk_ps; 263 regmap_write(fpc->regmap, FTM_MOD, period - 1);
262 writel(val, fpc->base + FTM_SC);
263 writel(period - 1, fpc->base + FTM_MOD);
264 264
265 fpc->period_ns = period_ns; 265 fpc->period_ns = period_ns;
266 } 266 }
@@ -269,8 +269,9 @@ static int fsl_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
269 269
270 duty = fsl_pwm_calculate_duty(fpc, period_ns, duty_ns); 270 duty = fsl_pwm_calculate_duty(fpc, period_ns, duty_ns);
271 271
272 writel(FTM_CSC_MSB | FTM_CSC_ELSB, fpc->base + FTM_CSC(pwm->hwpwm)); 272 regmap_write(fpc->regmap, FTM_CSC(pwm->hwpwm),
273 writel(duty, fpc->base + FTM_CV(pwm->hwpwm)); 273 FTM_CSC_MSB | FTM_CSC_ELSB);
274 regmap_write(fpc->regmap, FTM_CV(pwm->hwpwm), duty);
274 275
275 return 0; 276 return 0;
276} 277}
@@ -282,31 +283,28 @@ static int fsl_pwm_set_polarity(struct pwm_chip *chip,
282 struct fsl_pwm_chip *fpc = to_fsl_chip(chip); 283 struct fsl_pwm_chip *fpc = to_fsl_chip(chip);
283 u32 val; 284 u32 val;
284 285
285 val = readl(fpc->base + FTM_POL); 286 regmap_read(fpc->regmap, FTM_POL, &val);
286 287
287 if (polarity == PWM_POLARITY_INVERSED) 288 if (polarity == PWM_POLARITY_INVERSED)
288 val |= BIT(pwm->hwpwm); 289 val |= BIT(pwm->hwpwm);
289 else 290 else
290 val &= ~BIT(pwm->hwpwm); 291 val &= ~BIT(pwm->hwpwm);
291 292
292 writel(val, fpc->base + FTM_POL); 293 regmap_write(fpc->regmap, FTM_POL, val);
293 294
294 return 0; 295 return 0;
295} 296}
296 297
297static int fsl_counter_clock_enable(struct fsl_pwm_chip *fpc) 298static int fsl_counter_clock_enable(struct fsl_pwm_chip *fpc)
298{ 299{
299 u32 val;
300 int ret; 300 int ret;
301 301
302 if (fpc->use_count != 0) 302 if (fpc->use_count != 0)
303 return 0; 303 return 0;
304 304
305 /* select counter clock source */ 305 /* select counter clock source */
306 val = readl(fpc->base + FTM_SC); 306 regmap_update_bits(fpc->regmap, FTM_SC, FTM_SC_CLK_MASK,
307 val &= ~FTM_SC_CLK_MASK; 307 FTM_SC_CLK(fpc->cnt_select));
308 val |= FTM_SC_CLK(fpc->cnt_select);
309 writel(val, fpc->base + FTM_SC);
310 308
311 ret = clk_prepare_enable(fpc->clk[fpc->cnt_select]); 309 ret = clk_prepare_enable(fpc->clk[fpc->cnt_select]);
312 if (ret) 310 if (ret)
@@ -326,13 +324,10 @@ static int fsl_counter_clock_enable(struct fsl_pwm_chip *fpc)
326static int fsl_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm) 324static int fsl_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
327{ 325{
328 struct fsl_pwm_chip *fpc = to_fsl_chip(chip); 326 struct fsl_pwm_chip *fpc = to_fsl_chip(chip);
329 u32 val;
330 int ret; 327 int ret;
331 328
332 mutex_lock(&fpc->lock); 329 mutex_lock(&fpc->lock);
333 val = readl(fpc->base + FTM_OUTMASK); 330 regmap_update_bits(fpc->regmap, FTM_OUTMASK, BIT(pwm->hwpwm), 0);
334 val &= ~BIT(pwm->hwpwm);
335 writel(val, fpc->base + FTM_OUTMASK);
336 331
337 ret = fsl_counter_clock_enable(fpc); 332 ret = fsl_counter_clock_enable(fpc);
338 mutex_unlock(&fpc->lock); 333 mutex_unlock(&fpc->lock);
@@ -342,8 +337,6 @@ static int fsl_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
342 337
343static void fsl_counter_clock_disable(struct fsl_pwm_chip *fpc) 338static void fsl_counter_clock_disable(struct fsl_pwm_chip *fpc)
344{ 339{
345 u32 val;
346
347 /* 340 /*
348 * already disabled, do nothing 341 * already disabled, do nothing
349 */ 342 */
@@ -355,9 +348,7 @@ static void fsl_counter_clock_disable(struct fsl_pwm_chip *fpc)
355 return; 348 return;
356 349
357 /* no users left, disable PWM counter clock */ 350 /* no users left, disable PWM counter clock */
358 val = readl(fpc->base + FTM_SC); 351 regmap_update_bits(fpc->regmap, FTM_SC, FTM_SC_CLK_MASK, 0);
359 val &= ~FTM_SC_CLK_MASK;
360 writel(val, fpc->base + FTM_SC);
361 352
362 clk_disable_unprepare(fpc->clk[FSL_PWM_CLK_CNTEN]); 353 clk_disable_unprepare(fpc->clk[FSL_PWM_CLK_CNTEN]);
363 clk_disable_unprepare(fpc->clk[fpc->cnt_select]); 354 clk_disable_unprepare(fpc->clk[fpc->cnt_select]);
@@ -369,14 +360,12 @@ static void fsl_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
369 u32 val; 360 u32 val;
370 361
371 mutex_lock(&fpc->lock); 362 mutex_lock(&fpc->lock);
372 val = readl(fpc->base + FTM_OUTMASK); 363 regmap_update_bits(fpc->regmap, FTM_OUTMASK, BIT(pwm->hwpwm),
373 val |= BIT(pwm->hwpwm); 364 BIT(pwm->hwpwm));
374 writel(val, fpc->base + FTM_OUTMASK);
375 365
376 fsl_counter_clock_disable(fpc); 366 fsl_counter_clock_disable(fpc);
377 367
378 val = readl(fpc->base + FTM_OUTMASK); 368 regmap_read(fpc->regmap, FTM_OUTMASK, &val);
379
380 if ((val & 0xFF) == 0xFF) 369 if ((val & 0xFF) == 0xFF)
381 fpc->period_ns = 0; 370 fpc->period_ns = 0;
382 371
@@ -401,19 +390,28 @@ static int fsl_pwm_init(struct fsl_pwm_chip *fpc)
401 if (ret) 390 if (ret)
402 return ret; 391 return ret;
403 392
404 writel(0x00, fpc->base + FTM_CNTIN); 393 regmap_write(fpc->regmap, FTM_CNTIN, 0x00);
405 writel(0x00, fpc->base + FTM_OUTINIT); 394 regmap_write(fpc->regmap, FTM_OUTINIT, 0x00);
406 writel(0xFF, fpc->base + FTM_OUTMASK); 395 regmap_write(fpc->regmap, FTM_OUTMASK, 0xFF);
407 396
408 clk_disable_unprepare(fpc->clk[FSL_PWM_CLK_SYS]); 397 clk_disable_unprepare(fpc->clk[FSL_PWM_CLK_SYS]);
409 398
410 return 0; 399 return 0;
411} 400}
412 401
402static const struct regmap_config fsl_pwm_regmap_config = {
403 .reg_bits = 32,
404 .reg_stride = 4,
405 .val_bits = 32,
406
407 .max_register = FTM_PWMLOAD,
408};
409
413static int fsl_pwm_probe(struct platform_device *pdev) 410static int fsl_pwm_probe(struct platform_device *pdev)
414{ 411{
415 struct fsl_pwm_chip *fpc; 412 struct fsl_pwm_chip *fpc;
416 struct resource *res; 413 struct resource *res;
414 void __iomem *base;
417 int ret; 415 int ret;
418 416
419 fpc = devm_kzalloc(&pdev->dev, sizeof(*fpc), GFP_KERNEL); 417 fpc = devm_kzalloc(&pdev->dev, sizeof(*fpc), GFP_KERNEL);
@@ -425,9 +423,16 @@ static int fsl_pwm_probe(struct platform_device *pdev)
425 fpc->chip.dev = &pdev->dev; 423 fpc->chip.dev = &pdev->dev;
426 424
427 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 425 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
428 fpc->base = devm_ioremap_resource(&pdev->dev, res); 426 base = devm_ioremap_resource(&pdev->dev, res);
429 if (IS_ERR(fpc->base)) 427 if (IS_ERR(base))
430 return PTR_ERR(fpc->base); 428 return PTR_ERR(base);
429
430 fpc->regmap = devm_regmap_init_mmio_clk(&pdev->dev, NULL, base,
431 &fsl_pwm_regmap_config);
432 if (IS_ERR(fpc->regmap)) {
433 dev_err(&pdev->dev, "regmap init failed\n");
434 return PTR_ERR(fpc->regmap);
435 }
431 436
432 fpc->clk[FSL_PWM_CLK_SYS] = devm_clk_get(&pdev->dev, "ftm_sys"); 437 fpc->clk[FSL_PWM_CLK_SYS] = devm_clk_get(&pdev->dev, "ftm_sys");
433 if (IS_ERR(fpc->clk[FSL_PWM_CLK_SYS])) { 438 if (IS_ERR(fpc->clk[FSL_PWM_CLK_SYS])) {