linux/drivers/pwm/pwm-fsl-ftm.c
<<
>>
Prefs
   1/*
   2 *  Freescale FlexTimer Module (FTM) PWM Driver
   3 *
   4 *  Copyright 2012-2013 Freescale Semiconductor, Inc.
   5 *
   6 * This program is free software; you can redistribute it and/or modify
   7 * it under the terms of the GNU General Public License as published by
   8 * the Free Software Foundation; either version 2 of the License, or
   9 * (at your option) any later version.
  10 */
  11
  12#include <linux/clk.h>
  13#include <linux/err.h>
  14#include <linux/io.h>
  15#include <linux/kernel.h>
  16#include <linux/module.h>
  17#include <linux/mutex.h>
  18#include <linux/of_address.h>
  19#include <linux/platform_device.h>
  20#include <linux/pm.h>
  21#include <linux/pwm.h>
  22#include <linux/regmap.h>
  23#include <linux/slab.h>
  24
  25#define FTM_SC          0x00
  26#define FTM_SC_CLK_MASK_SHIFT   3
  27#define FTM_SC_CLK_MASK (3 << FTM_SC_CLK_MASK_SHIFT)
  28#define FTM_SC_CLK(c)   (((c) + 1) << FTM_SC_CLK_MASK_SHIFT)
  29#define FTM_SC_PS_MASK  0x7
  30
  31#define FTM_CNT         0x04
  32#define FTM_MOD         0x08
  33
  34#define FTM_CSC_BASE    0x0C
  35#define FTM_CSC_MSB     BIT(5)
  36#define FTM_CSC_MSA     BIT(4)
  37#define FTM_CSC_ELSB    BIT(3)
  38#define FTM_CSC_ELSA    BIT(2)
  39#define FTM_CSC(_channel)       (FTM_CSC_BASE + ((_channel) * 8))
  40
  41#define FTM_CV_BASE     0x10
  42#define FTM_CV(_channel)        (FTM_CV_BASE + ((_channel) * 8))
  43
  44#define FTM_CNTIN       0x4C
  45#define FTM_STATUS      0x50
  46
  47#define FTM_MODE        0x54
  48#define FTM_MODE_FTMEN  BIT(0)
  49#define FTM_MODE_INIT   BIT(2)
  50#define FTM_MODE_PWMSYNC        BIT(3)
  51
  52#define FTM_SYNC        0x58
  53#define FTM_OUTINIT     0x5C
  54#define FTM_OUTMASK     0x60
  55#define FTM_COMBINE     0x64
  56#define FTM_DEADTIME    0x68
  57#define FTM_EXTTRIG     0x6C
  58#define FTM_POL         0x70
  59#define FTM_FMS         0x74
  60#define FTM_FILTER      0x78
  61#define FTM_FLTCTRL     0x7C
  62#define FTM_QDCTRL      0x80
  63#define FTM_CONF        0x84
  64#define FTM_FLTPOL      0x88
  65#define FTM_SYNCONF     0x8C
  66#define FTM_INVCTRL     0x90
  67#define FTM_SWOCTRL     0x94
  68#define FTM_PWMLOAD     0x98
  69
  70enum fsl_pwm_clk {
  71        FSL_PWM_CLK_SYS,
  72        FSL_PWM_CLK_FIX,
  73        FSL_PWM_CLK_EXT,
  74        FSL_PWM_CLK_CNTEN,
  75        FSL_PWM_CLK_MAX
  76};
  77
  78struct fsl_pwm_chip {
  79        struct pwm_chip chip;
  80
  81        struct mutex lock;
  82
  83        unsigned int cnt_select;
  84        unsigned int clk_ps;
  85
  86        struct regmap *regmap;
  87
  88        int period_ns;
  89
  90        struct clk *clk[FSL_PWM_CLK_MAX];
  91};
  92
  93static inline struct fsl_pwm_chip *to_fsl_chip(struct pwm_chip *chip)
  94{
  95        return container_of(chip, struct fsl_pwm_chip, chip);
  96}
  97
  98static int fsl_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm)
  99{
 100        struct fsl_pwm_chip *fpc = to_fsl_chip(chip);
 101
 102        return clk_prepare_enable(fpc->clk[FSL_PWM_CLK_SYS]);
 103}
 104
 105static void fsl_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm)
 106{
 107        struct fsl_pwm_chip *fpc = to_fsl_chip(chip);
 108
 109        clk_disable_unprepare(fpc->clk[FSL_PWM_CLK_SYS]);
 110}
 111
 112static int fsl_pwm_calculate_default_ps(struct fsl_pwm_chip *fpc,
 113                                        enum fsl_pwm_clk index)
 114{
 115        unsigned long sys_rate, cnt_rate;
 116        unsigned long long ratio;
 117
 118        sys_rate = clk_get_rate(fpc->clk[FSL_PWM_CLK_SYS]);
 119        if (!sys_rate)
 120                return -EINVAL;
 121
 122        cnt_rate = clk_get_rate(fpc->clk[fpc->cnt_select]);
 123        if (!cnt_rate)
 124                return -EINVAL;
 125
 126        switch (index) {
 127        case FSL_PWM_CLK_SYS:
 128                fpc->clk_ps = 1;
 129                break;
 130        case FSL_PWM_CLK_FIX:
 131                ratio = 2 * cnt_rate - 1;
 132                do_div(ratio, sys_rate);
 133                fpc->clk_ps = ratio;
 134                break;
 135        case FSL_PWM_CLK_EXT:
 136                ratio = 4 * cnt_rate - 1;
 137                do_div(ratio, sys_rate);
 138                fpc->clk_ps = ratio;
 139                break;
 140        default:
 141                return -EINVAL;
 142        }
 143
 144        return 0;
 145}
 146
 147static unsigned long fsl_pwm_calculate_cycles(struct fsl_pwm_chip *fpc,
 148                                              unsigned long period_ns)
 149{
 150        unsigned long long c, c0;
 151
 152        c = clk_get_rate(fpc->clk[fpc->cnt_select]);
 153        c = c * period_ns;
 154        do_div(c, 1000000000UL);
 155
 156        do {
 157                c0 = c;
 158                do_div(c0, (1 << fpc->clk_ps));
 159                if (c0 <= 0xFFFF)
 160                        return (unsigned long)c0;
 161        } while (++fpc->clk_ps < 8);
 162
 163        return 0;
 164}
 165
 166static unsigned long fsl_pwm_calculate_period_cycles(struct fsl_pwm_chip *fpc,
 167                                                     unsigned long period_ns,
 168                                                     enum fsl_pwm_clk index)
 169{
 170        int ret;
 171
 172        ret = fsl_pwm_calculate_default_ps(fpc, index);
 173        if (ret) {
 174                dev_err(fpc->chip.dev,
 175                        "failed to calculate default prescaler: %d\n",
 176                        ret);
 177                return 0;
 178        }
 179
 180        return fsl_pwm_calculate_cycles(fpc, period_ns);
 181}
 182
 183static unsigned long fsl_pwm_calculate_period(struct fsl_pwm_chip *fpc,
 184                                              unsigned long period_ns)
 185{
 186        enum fsl_pwm_clk m0, m1;
 187        unsigned long fix_rate, ext_rate, cycles;
 188
 189        cycles = fsl_pwm_calculate_period_cycles(fpc, period_ns,
 190                        FSL_PWM_CLK_SYS);
 191        if (cycles) {
 192                fpc->cnt_select = FSL_PWM_CLK_SYS;
 193                return cycles;
 194        }
 195
 196        fix_rate = clk_get_rate(fpc->clk[FSL_PWM_CLK_FIX]);
 197        ext_rate = clk_get_rate(fpc->clk[FSL_PWM_CLK_EXT]);
 198
 199        if (fix_rate > ext_rate) {
 200                m0 = FSL_PWM_CLK_FIX;
 201                m1 = FSL_PWM_CLK_EXT;
 202        } else {
 203                m0 = FSL_PWM_CLK_EXT;
 204                m1 = FSL_PWM_CLK_FIX;
 205        }
 206
 207        cycles = fsl_pwm_calculate_period_cycles(fpc, period_ns, m0);
 208        if (cycles) {
 209                fpc->cnt_select = m0;
 210                return cycles;
 211        }
 212
 213        fpc->cnt_select = m1;
 214
 215        return fsl_pwm_calculate_period_cycles(fpc, period_ns, m1);
 216}
 217
 218static unsigned long fsl_pwm_calculate_duty(struct fsl_pwm_chip *fpc,
 219                                            unsigned long period_ns,
 220                                            unsigned long duty_ns)
 221{
 222        unsigned long long duty;
 223        u32 val;
 224
 225        regmap_read(fpc->regmap, FTM_MOD, &val);
 226        duty = (unsigned long long)duty_ns * (val + 1);
 227        do_div(duty, period_ns);
 228
 229        return (unsigned long)duty;
 230}
 231
 232static int fsl_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
 233                          int duty_ns, int period_ns)
 234{
 235        struct fsl_pwm_chip *fpc = to_fsl_chip(chip);
 236        u32 period, duty;
 237
 238        mutex_lock(&fpc->lock);
 239
 240        /*
 241         * The Freescale FTM controller supports only a single period for
 242         * all PWM channels, therefore incompatible changes need to be
 243         * refused.
 244         */
 245        if (fpc->period_ns && fpc->period_ns != period_ns) {
 246                dev_err(fpc->chip.dev,
 247                        "conflicting period requested for PWM %u\n",
 248                        pwm->hwpwm);
 249                mutex_unlock(&fpc->lock);
 250                return -EBUSY;
 251        }
 252
 253        if (!fpc->period_ns && duty_ns) {
 254                period = fsl_pwm_calculate_period(fpc, period_ns);
 255                if (!period) {
 256                        dev_err(fpc->chip.dev, "failed to calculate period\n");
 257                        mutex_unlock(&fpc->lock);
 258                        return -EINVAL;
 259                }
 260
 261                regmap_update_bits(fpc->regmap, FTM_SC, FTM_SC_PS_MASK,
 262                                   fpc->clk_ps);
 263                regmap_write(fpc->regmap, FTM_MOD, period - 1);
 264
 265                fpc->period_ns = period_ns;
 266        }
 267
 268        mutex_unlock(&fpc->lock);
 269
 270        duty = fsl_pwm_calculate_duty(fpc, period_ns, duty_ns);
 271
 272        regmap_write(fpc->regmap, FTM_CSC(pwm->hwpwm),
 273                     FTM_CSC_MSB | FTM_CSC_ELSB);
 274        regmap_write(fpc->regmap, FTM_CV(pwm->hwpwm), duty);
 275
 276        return 0;
 277}
 278
 279static int fsl_pwm_set_polarity(struct pwm_chip *chip,
 280                                struct pwm_device *pwm,
 281                                enum pwm_polarity polarity)
 282{
 283        struct fsl_pwm_chip *fpc = to_fsl_chip(chip);
 284        u32 val;
 285
 286        regmap_read(fpc->regmap, FTM_POL, &val);
 287
 288        if (polarity == PWM_POLARITY_INVERSED)
 289                val |= BIT(pwm->hwpwm);
 290        else
 291                val &= ~BIT(pwm->hwpwm);
 292
 293        regmap_write(fpc->regmap, FTM_POL, val);
 294
 295        return 0;
 296}
 297
 298static int fsl_counter_clock_enable(struct fsl_pwm_chip *fpc)
 299{
 300        int ret;
 301
 302        /* select counter clock source */
 303        regmap_update_bits(fpc->regmap, FTM_SC, FTM_SC_CLK_MASK,
 304                           FTM_SC_CLK(fpc->cnt_select));
 305
 306        ret = clk_prepare_enable(fpc->clk[fpc->cnt_select]);
 307        if (ret)
 308                return ret;
 309
 310        ret = clk_prepare_enable(fpc->clk[FSL_PWM_CLK_CNTEN]);
 311        if (ret) {
 312                clk_disable_unprepare(fpc->clk[fpc->cnt_select]);
 313                return ret;
 314        }
 315
 316        return 0;
 317}
 318
 319static int fsl_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
 320{
 321        struct fsl_pwm_chip *fpc = to_fsl_chip(chip);
 322        int ret;
 323
 324        mutex_lock(&fpc->lock);
 325        regmap_update_bits(fpc->regmap, FTM_OUTMASK, BIT(pwm->hwpwm), 0);
 326
 327        ret = fsl_counter_clock_enable(fpc);
 328        mutex_unlock(&fpc->lock);
 329
 330        return ret;
 331}
 332
 333static void fsl_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
 334{
 335        struct fsl_pwm_chip *fpc = to_fsl_chip(chip);
 336        u32 val;
 337
 338        mutex_lock(&fpc->lock);
 339        regmap_update_bits(fpc->regmap, FTM_OUTMASK, BIT(pwm->hwpwm),
 340                           BIT(pwm->hwpwm));
 341
 342        clk_disable_unprepare(fpc->clk[FSL_PWM_CLK_CNTEN]);
 343        clk_disable_unprepare(fpc->clk[fpc->cnt_select]);
 344
 345        regmap_read(fpc->regmap, FTM_OUTMASK, &val);
 346        if ((val & 0xFF) == 0xFF)
 347                fpc->period_ns = 0;
 348
 349        mutex_unlock(&fpc->lock);
 350}
 351
 352static const struct pwm_ops fsl_pwm_ops = {
 353        .request = fsl_pwm_request,
 354        .free = fsl_pwm_free,
 355        .config = fsl_pwm_config,
 356        .set_polarity = fsl_pwm_set_polarity,
 357        .enable = fsl_pwm_enable,
 358        .disable = fsl_pwm_disable,
 359        .owner = THIS_MODULE,
 360};
 361
 362static int fsl_pwm_init(struct fsl_pwm_chip *fpc)
 363{
 364        int ret;
 365
 366        ret = clk_prepare_enable(fpc->clk[FSL_PWM_CLK_SYS]);
 367        if (ret)
 368                return ret;
 369
 370        regmap_write(fpc->regmap, FTM_CNTIN, 0x00);
 371        regmap_write(fpc->regmap, FTM_OUTINIT, 0x00);
 372        regmap_write(fpc->regmap, FTM_OUTMASK, 0xFF);
 373
 374        clk_disable_unprepare(fpc->clk[FSL_PWM_CLK_SYS]);
 375
 376        return 0;
 377}
 378
 379static bool fsl_pwm_volatile_reg(struct device *dev, unsigned int reg)
 380{
 381        switch (reg) {
 382        case FTM_CNT:
 383                return true;
 384        }
 385        return false;
 386}
 387
 388static const struct regmap_config fsl_pwm_regmap_config = {
 389        .reg_bits = 32,
 390        .reg_stride = 4,
 391        .val_bits = 32,
 392
 393        .max_register = FTM_PWMLOAD,
 394        .volatile_reg = fsl_pwm_volatile_reg,
 395        .cache_type = REGCACHE_FLAT,
 396};
 397
 398static int fsl_pwm_probe(struct platform_device *pdev)
 399{
 400        struct fsl_pwm_chip *fpc;
 401        struct resource *res;
 402        void __iomem *base;
 403        int ret;
 404
 405        fpc = devm_kzalloc(&pdev->dev, sizeof(*fpc), GFP_KERNEL);
 406        if (!fpc)
 407                return -ENOMEM;
 408
 409        mutex_init(&fpc->lock);
 410
 411        fpc->chip.dev = &pdev->dev;
 412
 413        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 414        base = devm_ioremap_resource(&pdev->dev, res);
 415        if (IS_ERR(base))
 416                return PTR_ERR(base);
 417
 418        fpc->regmap = devm_regmap_init_mmio_clk(&pdev->dev, "ftm_sys", base,
 419                                                &fsl_pwm_regmap_config);
 420        if (IS_ERR(fpc->regmap)) {
 421                dev_err(&pdev->dev, "regmap init failed\n");
 422                return PTR_ERR(fpc->regmap);
 423        }
 424
 425        fpc->clk[FSL_PWM_CLK_SYS] = devm_clk_get(&pdev->dev, "ftm_sys");
 426        if (IS_ERR(fpc->clk[FSL_PWM_CLK_SYS])) {
 427                dev_err(&pdev->dev, "failed to get \"ftm_sys\" clock\n");
 428                return PTR_ERR(fpc->clk[FSL_PWM_CLK_SYS]);
 429        }
 430
 431        fpc->clk[FSL_PWM_CLK_FIX] = devm_clk_get(fpc->chip.dev, "ftm_fix");
 432        if (IS_ERR(fpc->clk[FSL_PWM_CLK_FIX]))
 433                return PTR_ERR(fpc->clk[FSL_PWM_CLK_FIX]);
 434
 435        fpc->clk[FSL_PWM_CLK_EXT] = devm_clk_get(fpc->chip.dev, "ftm_ext");
 436        if (IS_ERR(fpc->clk[FSL_PWM_CLK_EXT]))
 437                return PTR_ERR(fpc->clk[FSL_PWM_CLK_EXT]);
 438
 439        fpc->clk[FSL_PWM_CLK_CNTEN] =
 440                                devm_clk_get(fpc->chip.dev, "ftm_cnt_clk_en");
 441        if (IS_ERR(fpc->clk[FSL_PWM_CLK_CNTEN]))
 442                return PTR_ERR(fpc->clk[FSL_PWM_CLK_CNTEN]);
 443
 444        fpc->chip.ops = &fsl_pwm_ops;
 445        fpc->chip.of_xlate = of_pwm_xlate_with_flags;
 446        fpc->chip.of_pwm_n_cells = 3;
 447        fpc->chip.base = -1;
 448        fpc->chip.npwm = 8;
 449        fpc->chip.can_sleep = true;
 450
 451        ret = pwmchip_add(&fpc->chip);
 452        if (ret < 0) {
 453                dev_err(&pdev->dev, "failed to add PWM chip: %d\n", ret);
 454                return ret;
 455        }
 456
 457        platform_set_drvdata(pdev, fpc);
 458
 459        return fsl_pwm_init(fpc);
 460}
 461
 462static int fsl_pwm_remove(struct platform_device *pdev)
 463{
 464        struct fsl_pwm_chip *fpc = platform_get_drvdata(pdev);
 465
 466        return pwmchip_remove(&fpc->chip);
 467}
 468
 469#ifdef CONFIG_PM_SLEEP
 470static int fsl_pwm_suspend(struct device *dev)
 471{
 472        struct fsl_pwm_chip *fpc = dev_get_drvdata(dev);
 473        int i;
 474
 475        regcache_cache_only(fpc->regmap, true);
 476        regcache_mark_dirty(fpc->regmap);
 477
 478        for (i = 0; i < fpc->chip.npwm; i++) {
 479                struct pwm_device *pwm = &fpc->chip.pwms[i];
 480
 481                if (!test_bit(PWMF_REQUESTED, &pwm->flags))
 482                        continue;
 483
 484                clk_disable_unprepare(fpc->clk[FSL_PWM_CLK_SYS]);
 485
 486                if (!pwm_is_enabled(pwm))
 487                        continue;
 488
 489                clk_disable_unprepare(fpc->clk[FSL_PWM_CLK_CNTEN]);
 490                clk_disable_unprepare(fpc->clk[fpc->cnt_select]);
 491        }
 492
 493        return 0;
 494}
 495
 496static int fsl_pwm_resume(struct device *dev)
 497{
 498        struct fsl_pwm_chip *fpc = dev_get_drvdata(dev);
 499        int i;
 500
 501        for (i = 0; i < fpc->chip.npwm; i++) {
 502                struct pwm_device *pwm = &fpc->chip.pwms[i];
 503
 504                if (!test_bit(PWMF_REQUESTED, &pwm->flags))
 505                        continue;
 506
 507                clk_prepare_enable(fpc->clk[FSL_PWM_CLK_SYS]);
 508
 509                if (!pwm_is_enabled(pwm))
 510                        continue;
 511
 512                clk_prepare_enable(fpc->clk[fpc->cnt_select]);
 513                clk_prepare_enable(fpc->clk[FSL_PWM_CLK_CNTEN]);
 514        }
 515
 516        /* restore all registers from cache */
 517        regcache_cache_only(fpc->regmap, false);
 518        regcache_sync(fpc->regmap);
 519
 520        return 0;
 521}
 522#endif
 523
 524static const struct dev_pm_ops fsl_pwm_pm_ops = {
 525        SET_SYSTEM_SLEEP_PM_OPS(fsl_pwm_suspend, fsl_pwm_resume)
 526};
 527
 528static const struct of_device_id fsl_pwm_dt_ids[] = {
 529        { .compatible = "fsl,vf610-ftm-pwm", },
 530        { /* sentinel */ }
 531};
 532MODULE_DEVICE_TABLE(of, fsl_pwm_dt_ids);
 533
 534static struct platform_driver fsl_pwm_driver = {
 535        .driver = {
 536                .name = "fsl-ftm-pwm",
 537                .of_match_table = fsl_pwm_dt_ids,
 538                .pm = &fsl_pwm_pm_ops,
 539        },
 540        .probe = fsl_pwm_probe,
 541        .remove = fsl_pwm_remove,
 542};
 543module_platform_driver(fsl_pwm_driver);
 544
 545MODULE_DESCRIPTION("Freescale FlexTimer Module PWM Driver");
 546MODULE_AUTHOR("Xiubo Li <Li.Xiubo@freescale.com>");
 547MODULE_ALIAS("platform:fsl-ftm-pwm");
 548MODULE_LICENSE("GPL");
 549