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