aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pwm
diff options
context:
space:
mode:
authorXiubo Li <Li.Xiubo@freescale.com>2014-08-19 00:38:02 -0400
committerThierry Reding <thierry.reding@gmail.com>2014-08-20 04:10:12 -0400
commit42fa98a9c3609c1aff466cb847e421c611cc9157 (patch)
tree0b736f637bcc49b9ccc86106be61d4e396495c8f /drivers/pwm
parentcd6d92d2aa1556b22cd05acbc5f2cc8e5caafcc4 (diff)
pwm: fsl-ftm: Convert to direct regmap API usage
The regmap core supports different endian modes for devices. This patch convert to direct regmap API usage, preparing to support big endianness for LS1 SoC. Using the regmap framework it will be easy to support devices that only differ in endianness with the same device driver. Signed-off-by: Xiubo Li <Li.Xiubo@freescale.com> Signed-off-by: Thierry Reding <thierry.reding@gmail.com>
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])) {