linux/drivers/pwm/pwm-tiehrpwm.c
<<
>>
Prefs
   1/*
   2 * EHRPWM PWM driver
   3 *
   4 * Copyright (C) 2012 Texas Instruments, Inc. - http://www.ti.com/
   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 * This program is distributed in the hope that it will be useful,
  12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14 * GNU General Public License for more details.
  15 *
  16 * You should have received a copy of the GNU General Public License
  17 * along with this program; if not, write to the Free Software
  18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19 */
  20
  21#include <linux/module.h>
  22#include <linux/platform_device.h>
  23#include <linux/pwm.h>
  24#include <linux/io.h>
  25#include <linux/err.h>
  26#include <linux/clk.h>
  27#include <linux/pm_runtime.h>
  28#include <linux/of_device.h>
  29
  30/* EHRPWM registers and bits definitions */
  31
  32/* Time base module registers */
  33#define TBCTL                   0x00
  34#define TBPRD                   0x0A
  35
  36#define TBCTL_PRDLD_MASK        BIT(3)
  37#define TBCTL_PRDLD_SHDW        0
  38#define TBCTL_PRDLD_IMDT        BIT(3)
  39#define TBCTL_CLKDIV_MASK       (BIT(12) | BIT(11) | BIT(10) | BIT(9) | \
  40                                BIT(8) | BIT(7))
  41#define TBCTL_CTRMODE_MASK      (BIT(1) | BIT(0))
  42#define TBCTL_CTRMODE_UP        0
  43#define TBCTL_CTRMODE_DOWN      BIT(0)
  44#define TBCTL_CTRMODE_UPDOWN    BIT(1)
  45#define TBCTL_CTRMODE_FREEZE    (BIT(1) | BIT(0))
  46
  47#define TBCTL_HSPCLKDIV_SHIFT   7
  48#define TBCTL_CLKDIV_SHIFT      10
  49
  50#define CLKDIV_MAX              7
  51#define HSPCLKDIV_MAX           7
  52#define PERIOD_MAX              0xFFFF
  53
  54/* compare module registers */
  55#define CMPA                    0x12
  56#define CMPB                    0x14
  57
  58/* Action qualifier module registers */
  59#define AQCTLA                  0x16
  60#define AQCTLB                  0x18
  61#define AQSFRC                  0x1A
  62#define AQCSFRC                 0x1C
  63
  64#define AQCTL_CBU_MASK          (BIT(9) | BIT(8))
  65#define AQCTL_CBU_FRCLOW        BIT(8)
  66#define AQCTL_CBU_FRCHIGH       BIT(9)
  67#define AQCTL_CBU_FRCTOGGLE     (BIT(9) | BIT(8))
  68#define AQCTL_CAU_MASK          (BIT(5) | BIT(4))
  69#define AQCTL_CAU_FRCLOW        BIT(4)
  70#define AQCTL_CAU_FRCHIGH       BIT(5)
  71#define AQCTL_CAU_FRCTOGGLE     (BIT(5) | BIT(4))
  72#define AQCTL_PRD_MASK          (BIT(3) | BIT(2))
  73#define AQCTL_PRD_FRCLOW        BIT(2)
  74#define AQCTL_PRD_FRCHIGH       BIT(3)
  75#define AQCTL_PRD_FRCTOGGLE     (BIT(3) | BIT(2))
  76#define AQCTL_ZRO_MASK          (BIT(1) | BIT(0))
  77#define AQCTL_ZRO_FRCLOW        BIT(0)
  78#define AQCTL_ZRO_FRCHIGH       BIT(1)
  79#define AQCTL_ZRO_FRCTOGGLE     (BIT(1) | BIT(0))
  80
  81#define AQCTL_CHANA_POLNORMAL   (AQCTL_CAU_FRCLOW | AQCTL_PRD_FRCHIGH | \
  82                                AQCTL_ZRO_FRCHIGH)
  83#define AQCTL_CHANA_POLINVERSED (AQCTL_CAU_FRCHIGH | AQCTL_PRD_FRCLOW | \
  84                                AQCTL_ZRO_FRCLOW)
  85#define AQCTL_CHANB_POLNORMAL   (AQCTL_CBU_FRCLOW | AQCTL_PRD_FRCHIGH | \
  86                                AQCTL_ZRO_FRCHIGH)
  87#define AQCTL_CHANB_POLINVERSED (AQCTL_CBU_FRCHIGH | AQCTL_PRD_FRCLOW | \
  88                                AQCTL_ZRO_FRCLOW)
  89
  90#define AQSFRC_RLDCSF_MASK      (BIT(7) | BIT(6))
  91#define AQSFRC_RLDCSF_ZRO       0
  92#define AQSFRC_RLDCSF_PRD       BIT(6)
  93#define AQSFRC_RLDCSF_ZROPRD    BIT(7)
  94#define AQSFRC_RLDCSF_IMDT      (BIT(7) | BIT(6))
  95
  96#define AQCSFRC_CSFB_MASK       (BIT(3) | BIT(2))
  97#define AQCSFRC_CSFB_FRCDIS     0
  98#define AQCSFRC_CSFB_FRCLOW     BIT(2)
  99#define AQCSFRC_CSFB_FRCHIGH    BIT(3)
 100#define AQCSFRC_CSFB_DISSWFRC   (BIT(3) | BIT(2))
 101#define AQCSFRC_CSFA_MASK       (BIT(1) | BIT(0))
 102#define AQCSFRC_CSFA_FRCDIS     0
 103#define AQCSFRC_CSFA_FRCLOW     BIT(0)
 104#define AQCSFRC_CSFA_FRCHIGH    BIT(1)
 105#define AQCSFRC_CSFA_DISSWFRC   (BIT(1) | BIT(0))
 106
 107#define NUM_PWM_CHANNEL         2       /* EHRPWM channels */
 108
 109struct ehrpwm_context {
 110        u16 tbctl;
 111        u16 tbprd;
 112        u16 cmpa;
 113        u16 cmpb;
 114        u16 aqctla;
 115        u16 aqctlb;
 116        u16 aqsfrc;
 117        u16 aqcsfrc;
 118};
 119
 120struct ehrpwm_pwm_chip {
 121        struct pwm_chip chip;
 122        unsigned long clk_rate;
 123        void __iomem *mmio_base;
 124        unsigned long period_cycles[NUM_PWM_CHANNEL];
 125        enum pwm_polarity polarity[NUM_PWM_CHANNEL];
 126        struct clk *tbclk;
 127        struct ehrpwm_context ctx;
 128};
 129
 130static inline struct ehrpwm_pwm_chip *to_ehrpwm_pwm_chip(struct pwm_chip *chip)
 131{
 132        return container_of(chip, struct ehrpwm_pwm_chip, chip);
 133}
 134
 135static inline u16 ehrpwm_read(void __iomem *base, unsigned int offset)
 136{
 137        return readw(base + offset);
 138}
 139
 140static inline void ehrpwm_write(void __iomem *base, unsigned int offset,
 141                                u16 value)
 142{
 143        writew(value, base + offset);
 144}
 145
 146static void ehrpwm_modify(void __iomem *base, unsigned int offset, u16 mask,
 147                          u16 value)
 148{
 149        unsigned short val;
 150
 151        val = readw(base + offset);
 152        val &= ~mask;
 153        val |= value & mask;
 154        writew(val, base + offset);
 155}
 156
 157/**
 158 * set_prescale_div -   Set up the prescaler divider function
 159 * @rqst_prescaler:     prescaler value min
 160 * @prescale_div:       prescaler value set
 161 * @tb_clk_div:         Time Base Control prescaler bits
 162 */
 163static int set_prescale_div(unsigned long rqst_prescaler, u16 *prescale_div,
 164                            u16 *tb_clk_div)
 165{
 166        unsigned int clkdiv, hspclkdiv;
 167
 168        for (clkdiv = 0; clkdiv <= CLKDIV_MAX; clkdiv++) {
 169                for (hspclkdiv = 0; hspclkdiv <= HSPCLKDIV_MAX; hspclkdiv++) {
 170                        /*
 171                         * calculations for prescaler value :
 172                         * prescale_div = HSPCLKDIVIDER * CLKDIVIDER.
 173                         * HSPCLKDIVIDER =  2 ** hspclkdiv
 174                         * CLKDIVIDER = (1),            if clkdiv == 0 *OR*
 175                         *              (2 * clkdiv),   if clkdiv != 0
 176                         *
 177                         * Configure prescale_div value such that period
 178                         * register value is less than 65535.
 179                         */
 180
 181                        *prescale_div = (1 << clkdiv) *
 182                                        (hspclkdiv ? (hspclkdiv * 2) : 1);
 183                        if (*prescale_div > rqst_prescaler) {
 184                                *tb_clk_div = (clkdiv << TBCTL_CLKDIV_SHIFT) |
 185                                        (hspclkdiv << TBCTL_HSPCLKDIV_SHIFT);
 186                                return 0;
 187                        }
 188                }
 189        }
 190
 191        return 1;
 192}
 193
 194static void configure_polarity(struct ehrpwm_pwm_chip *pc, int chan)
 195{
 196        u16 aqctl_val, aqctl_mask;
 197        unsigned int aqctl_reg;
 198
 199        /*
 200         * Configure PWM output to HIGH/LOW level on counter
 201         * reaches compare register value and LOW/HIGH level
 202         * on counter value reaches period register value and
 203         * zero value on counter
 204         */
 205        if (chan == 1) {
 206                aqctl_reg = AQCTLB;
 207                aqctl_mask = AQCTL_CBU_MASK;
 208
 209                if (pc->polarity[chan] == PWM_POLARITY_INVERSED)
 210                        aqctl_val = AQCTL_CHANB_POLINVERSED;
 211                else
 212                        aqctl_val = AQCTL_CHANB_POLNORMAL;
 213        } else {
 214                aqctl_reg = AQCTLA;
 215                aqctl_mask = AQCTL_CAU_MASK;
 216
 217                if (pc->polarity[chan] == PWM_POLARITY_INVERSED)
 218                        aqctl_val = AQCTL_CHANA_POLINVERSED;
 219                else
 220                        aqctl_val = AQCTL_CHANA_POLNORMAL;
 221        }
 222
 223        aqctl_mask |= AQCTL_PRD_MASK | AQCTL_ZRO_MASK;
 224        ehrpwm_modify(pc->mmio_base, aqctl_reg, aqctl_mask, aqctl_val);
 225}
 226
 227/*
 228 * period_ns = 10^9 * (ps_divval * period_cycles) / PWM_CLK_RATE
 229 * duty_ns   = 10^9 * (ps_divval * duty_cycles) / PWM_CLK_RATE
 230 */
 231static int ehrpwm_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
 232                             int duty_ns, int period_ns)
 233{
 234        struct ehrpwm_pwm_chip *pc = to_ehrpwm_pwm_chip(chip);
 235        u32 period_cycles, duty_cycles;
 236        u16 ps_divval, tb_divval;
 237        unsigned int i, cmp_reg;
 238        unsigned long long c;
 239
 240        if (period_ns > NSEC_PER_SEC)
 241                return -ERANGE;
 242
 243        c = pc->clk_rate;
 244        c = c * period_ns;
 245        do_div(c, NSEC_PER_SEC);
 246        period_cycles = (unsigned long)c;
 247
 248        if (period_cycles < 1) {
 249                period_cycles = 1;
 250                duty_cycles = 1;
 251        } else {
 252                c = pc->clk_rate;
 253                c = c * duty_ns;
 254                do_div(c, NSEC_PER_SEC);
 255                duty_cycles = (unsigned long)c;
 256        }
 257
 258        /*
 259         * Period values should be same for multiple PWM channels as IP uses
 260         * same period register for multiple channels.
 261         */
 262        for (i = 0; i < NUM_PWM_CHANNEL; i++) {
 263                if (pc->period_cycles[i] &&
 264                                (pc->period_cycles[i] != period_cycles)) {
 265                        /*
 266                         * Allow channel to reconfigure period if no other
 267                         * channels being configured.
 268                         */
 269                        if (i == pwm->hwpwm)
 270                                continue;
 271
 272                        dev_err(chip->dev,
 273                                "period value conflicts with channel %u\n",
 274                                i);
 275                        return -EINVAL;
 276                }
 277        }
 278
 279        pc->period_cycles[pwm->hwpwm] = period_cycles;
 280
 281        /* Configure clock prescaler to support Low frequency PWM wave */
 282        if (set_prescale_div(period_cycles/PERIOD_MAX, &ps_divval,
 283                             &tb_divval)) {
 284                dev_err(chip->dev, "Unsupported values\n");
 285                return -EINVAL;
 286        }
 287
 288        pm_runtime_get_sync(chip->dev);
 289
 290        /* Update clock prescaler values */
 291        ehrpwm_modify(pc->mmio_base, TBCTL, TBCTL_CLKDIV_MASK, tb_divval);
 292
 293        /* Update period & duty cycle with presacler division */
 294        period_cycles = period_cycles / ps_divval;
 295        duty_cycles = duty_cycles / ps_divval;
 296
 297        /* Configure shadow loading on Period register */
 298        ehrpwm_modify(pc->mmio_base, TBCTL, TBCTL_PRDLD_MASK, TBCTL_PRDLD_SHDW);
 299
 300        ehrpwm_write(pc->mmio_base, TBPRD, period_cycles);
 301
 302        /* Configure ehrpwm counter for up-count mode */
 303        ehrpwm_modify(pc->mmio_base, TBCTL, TBCTL_CTRMODE_MASK,
 304                      TBCTL_CTRMODE_UP);
 305
 306        if (pwm->hwpwm == 1)
 307                /* Channel 1 configured with compare B register */
 308                cmp_reg = CMPB;
 309        else
 310                /* Channel 0 configured with compare A register */
 311                cmp_reg = CMPA;
 312
 313        ehrpwm_write(pc->mmio_base, cmp_reg, duty_cycles);
 314
 315        pm_runtime_put_sync(chip->dev);
 316
 317        return 0;
 318}
 319
 320static int ehrpwm_pwm_set_polarity(struct pwm_chip *chip,
 321                                   struct pwm_device *pwm,
 322                                   enum pwm_polarity polarity)
 323{
 324        struct ehrpwm_pwm_chip *pc = to_ehrpwm_pwm_chip(chip);
 325
 326        /* Configuration of polarity in hardware delayed, do at enable */
 327        pc->polarity[pwm->hwpwm] = polarity;
 328
 329        return 0;
 330}
 331
 332static int ehrpwm_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
 333{
 334        struct ehrpwm_pwm_chip *pc = to_ehrpwm_pwm_chip(chip);
 335        u16 aqcsfrc_val, aqcsfrc_mask;
 336        int ret;
 337
 338        /* Leave clock enabled on enabling PWM */
 339        pm_runtime_get_sync(chip->dev);
 340
 341        /* Disabling Action Qualifier on PWM output */
 342        if (pwm->hwpwm) {
 343                aqcsfrc_val = AQCSFRC_CSFB_FRCDIS;
 344                aqcsfrc_mask = AQCSFRC_CSFB_MASK;
 345        } else {
 346                aqcsfrc_val = AQCSFRC_CSFA_FRCDIS;
 347                aqcsfrc_mask = AQCSFRC_CSFA_MASK;
 348        }
 349
 350        /* Changes to shadow mode */
 351        ehrpwm_modify(pc->mmio_base, AQSFRC, AQSFRC_RLDCSF_MASK,
 352                      AQSFRC_RLDCSF_ZRO);
 353
 354        ehrpwm_modify(pc->mmio_base, AQCSFRC, aqcsfrc_mask, aqcsfrc_val);
 355
 356        /* Channels polarity can be configured from action qualifier module */
 357        configure_polarity(pc, pwm->hwpwm);
 358
 359        /* Enable TBCLK */
 360        ret = clk_enable(pc->tbclk);
 361        if (ret) {
 362                dev_err(chip->dev, "Failed to enable TBCLK for %s: %d\n",
 363                        dev_name(pc->chip.dev), ret);
 364                return ret;
 365        }
 366
 367        return 0;
 368}
 369
 370static void ehrpwm_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
 371{
 372        struct ehrpwm_pwm_chip *pc = to_ehrpwm_pwm_chip(chip);
 373        u16 aqcsfrc_val, aqcsfrc_mask;
 374
 375        /* Action Qualifier puts PWM output low forcefully */
 376        if (pwm->hwpwm) {
 377                aqcsfrc_val = AQCSFRC_CSFB_FRCLOW;
 378                aqcsfrc_mask = AQCSFRC_CSFB_MASK;
 379        } else {
 380                aqcsfrc_val = AQCSFRC_CSFA_FRCLOW;
 381                aqcsfrc_mask = AQCSFRC_CSFA_MASK;
 382        }
 383
 384        /* Update shadow register first before modifying active register */
 385        ehrpwm_modify(pc->mmio_base, AQCSFRC, aqcsfrc_mask, aqcsfrc_val);
 386        /*
 387         * Changes to immediate action on Action Qualifier. This puts
 388         * Action Qualifier control on PWM output from next TBCLK
 389         */
 390        ehrpwm_modify(pc->mmio_base, AQSFRC, AQSFRC_RLDCSF_MASK,
 391                      AQSFRC_RLDCSF_IMDT);
 392
 393        ehrpwm_modify(pc->mmio_base, AQCSFRC, aqcsfrc_mask, aqcsfrc_val);
 394
 395        /* Disabling TBCLK on PWM disable */
 396        clk_disable(pc->tbclk);
 397
 398        /* Disable clock on PWM disable */
 399        pm_runtime_put_sync(chip->dev);
 400}
 401
 402static void ehrpwm_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm)
 403{
 404        struct ehrpwm_pwm_chip *pc = to_ehrpwm_pwm_chip(chip);
 405
 406        if (pwm_is_enabled(pwm)) {
 407                dev_warn(chip->dev, "Removing PWM device without disabling\n");
 408                pm_runtime_put_sync(chip->dev);
 409        }
 410
 411        /* set period value to zero on free */
 412        pc->period_cycles[pwm->hwpwm] = 0;
 413}
 414
 415static const struct pwm_ops ehrpwm_pwm_ops = {
 416        .free = ehrpwm_pwm_free,
 417        .config = ehrpwm_pwm_config,
 418        .set_polarity = ehrpwm_pwm_set_polarity,
 419        .enable = ehrpwm_pwm_enable,
 420        .disable = ehrpwm_pwm_disable,
 421        .owner = THIS_MODULE,
 422};
 423
 424static const struct of_device_id ehrpwm_of_match[] = {
 425        { .compatible = "ti,am3352-ehrpwm" },
 426        { .compatible = "ti,am33xx-ehrpwm" },
 427        {},
 428};
 429MODULE_DEVICE_TABLE(of, ehrpwm_of_match);
 430
 431static int ehrpwm_pwm_probe(struct platform_device *pdev)
 432{
 433        struct device_node *np = pdev->dev.of_node;
 434        struct ehrpwm_pwm_chip *pc;
 435        struct resource *r;
 436        struct clk *clk;
 437        int ret;
 438
 439        pc = devm_kzalloc(&pdev->dev, sizeof(*pc), GFP_KERNEL);
 440        if (!pc)
 441                return -ENOMEM;
 442
 443        clk = devm_clk_get(&pdev->dev, "fck");
 444        if (IS_ERR(clk)) {
 445                if (of_device_is_compatible(np, "ti,am33xx-ecap")) {
 446                        dev_warn(&pdev->dev, "Binding is obsolete.\n");
 447                        clk = devm_clk_get(pdev->dev.parent, "fck");
 448                }
 449        }
 450
 451        if (IS_ERR(clk)) {
 452                dev_err(&pdev->dev, "failed to get clock\n");
 453                return PTR_ERR(clk);
 454        }
 455
 456        pc->clk_rate = clk_get_rate(clk);
 457        if (!pc->clk_rate) {
 458                dev_err(&pdev->dev, "failed to get clock rate\n");
 459                return -EINVAL;
 460        }
 461
 462        pc->chip.dev = &pdev->dev;
 463        pc->chip.ops = &ehrpwm_pwm_ops;
 464        pc->chip.of_xlate = of_pwm_xlate_with_flags;
 465        pc->chip.of_pwm_n_cells = 3;
 466        pc->chip.base = -1;
 467        pc->chip.npwm = NUM_PWM_CHANNEL;
 468
 469        r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 470        pc->mmio_base = devm_ioremap_resource(&pdev->dev, r);
 471        if (IS_ERR(pc->mmio_base))
 472                return PTR_ERR(pc->mmio_base);
 473
 474        /* Acquire tbclk for Time Base EHRPWM submodule */
 475        pc->tbclk = devm_clk_get(&pdev->dev, "tbclk");
 476        if (IS_ERR(pc->tbclk)) {
 477                dev_err(&pdev->dev, "Failed to get tbclk\n");
 478                return PTR_ERR(pc->tbclk);
 479        }
 480
 481        ret = clk_prepare(pc->tbclk);
 482        if (ret < 0) {
 483                dev_err(&pdev->dev, "clk_prepare() failed: %d\n", ret);
 484                return ret;
 485        }
 486
 487        ret = pwmchip_add(&pc->chip);
 488        if (ret < 0) {
 489                dev_err(&pdev->dev, "pwmchip_add() failed: %d\n", ret);
 490                goto err_clk_unprepare;
 491        }
 492
 493        platform_set_drvdata(pdev, pc);
 494        pm_runtime_enable(&pdev->dev);
 495
 496        return 0;
 497
 498err_clk_unprepare:
 499        clk_unprepare(pc->tbclk);
 500
 501        return ret;
 502}
 503
 504static int ehrpwm_pwm_remove(struct platform_device *pdev)
 505{
 506        struct ehrpwm_pwm_chip *pc = platform_get_drvdata(pdev);
 507
 508        clk_unprepare(pc->tbclk);
 509
 510        pm_runtime_disable(&pdev->dev);
 511
 512        return pwmchip_remove(&pc->chip);
 513}
 514
 515#ifdef CONFIG_PM_SLEEP
 516static void ehrpwm_pwm_save_context(struct ehrpwm_pwm_chip *pc)
 517{
 518        pm_runtime_get_sync(pc->chip.dev);
 519
 520        pc->ctx.tbctl = ehrpwm_read(pc->mmio_base, TBCTL);
 521        pc->ctx.tbprd = ehrpwm_read(pc->mmio_base, TBPRD);
 522        pc->ctx.cmpa = ehrpwm_read(pc->mmio_base, CMPA);
 523        pc->ctx.cmpb = ehrpwm_read(pc->mmio_base, CMPB);
 524        pc->ctx.aqctla = ehrpwm_read(pc->mmio_base, AQCTLA);
 525        pc->ctx.aqctlb = ehrpwm_read(pc->mmio_base, AQCTLB);
 526        pc->ctx.aqsfrc = ehrpwm_read(pc->mmio_base, AQSFRC);
 527        pc->ctx.aqcsfrc = ehrpwm_read(pc->mmio_base, AQCSFRC);
 528
 529        pm_runtime_put_sync(pc->chip.dev);
 530}
 531
 532static void ehrpwm_pwm_restore_context(struct ehrpwm_pwm_chip *pc)
 533{
 534        ehrpwm_write(pc->mmio_base, TBPRD, pc->ctx.tbprd);
 535        ehrpwm_write(pc->mmio_base, CMPA, pc->ctx.cmpa);
 536        ehrpwm_write(pc->mmio_base, CMPB, pc->ctx.cmpb);
 537        ehrpwm_write(pc->mmio_base, AQCTLA, pc->ctx.aqctla);
 538        ehrpwm_write(pc->mmio_base, AQCTLB, pc->ctx.aqctlb);
 539        ehrpwm_write(pc->mmio_base, AQSFRC, pc->ctx.aqsfrc);
 540        ehrpwm_write(pc->mmio_base, AQCSFRC, pc->ctx.aqcsfrc);
 541        ehrpwm_write(pc->mmio_base, TBCTL, pc->ctx.tbctl);
 542}
 543
 544static int ehrpwm_pwm_suspend(struct device *dev)
 545{
 546        struct ehrpwm_pwm_chip *pc = dev_get_drvdata(dev);
 547        unsigned int i;
 548
 549        ehrpwm_pwm_save_context(pc);
 550
 551        for (i = 0; i < pc->chip.npwm; i++) {
 552                struct pwm_device *pwm = &pc->chip.pwms[i];
 553
 554                if (!pwm_is_enabled(pwm))
 555                        continue;
 556
 557                /* Disable explicitly if PWM is running */
 558                pm_runtime_put_sync(dev);
 559        }
 560
 561        return 0;
 562}
 563
 564static int ehrpwm_pwm_resume(struct device *dev)
 565{
 566        struct ehrpwm_pwm_chip *pc = dev_get_drvdata(dev);
 567        unsigned int i;
 568
 569        for (i = 0; i < pc->chip.npwm; i++) {
 570                struct pwm_device *pwm = &pc->chip.pwms[i];
 571
 572                if (!pwm_is_enabled(pwm))
 573                        continue;
 574
 575                /* Enable explicitly if PWM was running */
 576                pm_runtime_get_sync(dev);
 577        }
 578
 579        ehrpwm_pwm_restore_context(pc);
 580
 581        return 0;
 582}
 583#endif
 584
 585static SIMPLE_DEV_PM_OPS(ehrpwm_pwm_pm_ops, ehrpwm_pwm_suspend,
 586                         ehrpwm_pwm_resume);
 587
 588static struct platform_driver ehrpwm_pwm_driver = {
 589        .driver = {
 590                .name = "ehrpwm",
 591                .of_match_table = ehrpwm_of_match,
 592                .pm = &ehrpwm_pwm_pm_ops,
 593        },
 594        .probe = ehrpwm_pwm_probe,
 595        .remove = ehrpwm_pwm_remove,
 596};
 597module_platform_driver(ehrpwm_pwm_driver);
 598
 599MODULE_DESCRIPTION("EHRPWM PWM driver");
 600MODULE_AUTHOR("Texas Instruments");
 601MODULE_LICENSE("GPL");
 602