root/drivers/pwm/pwm-tiehrpwm.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. to_ehrpwm_pwm_chip
  2. ehrpwm_read
  3. ehrpwm_write
  4. ehrpwm_modify
  5. set_prescale_div
  6. configure_polarity
  7. ehrpwm_pwm_config
  8. ehrpwm_pwm_set_polarity
  9. ehrpwm_pwm_enable
  10. ehrpwm_pwm_disable
  11. ehrpwm_pwm_free
  12. ehrpwm_pwm_probe
  13. ehrpwm_pwm_remove
  14. ehrpwm_pwm_save_context
  15. ehrpwm_pwm_restore_context
  16. ehrpwm_pwm_suspend
  17. ehrpwm_pwm_resume

   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 
  96 struct 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 
 107 struct 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 
 117 static 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 
 122 static inline u16 ehrpwm_read(void __iomem *base, unsigned int offset)
 123 {
 124         return readw(base + offset);
 125 }
 126 
 127 static inline void ehrpwm_write(void __iomem *base, unsigned int offset,
 128                                 u16 value)
 129 {
 130         writew(value, base + offset);
 131 }
 132 
 133 static 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  */
 150 static 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 
 181 static 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  */
 218 static 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 
 307 static 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 
 319 static 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 
 357 static 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 
 391 static 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 
 404 static 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 
 413 static const struct of_device_id ehrpwm_of_match[] = {
 414         { .compatible = "ti,am3352-ehrpwm" },
 415         { .compatible = "ti,am33xx-ehrpwm" },
 416         {},
 417 };
 418 MODULE_DEVICE_TABLE(of, ehrpwm_of_match);
 419 
 420 static 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 
 487 err_clk_unprepare:
 488         clk_unprepare(pc->tbclk);
 489 
 490         return ret;
 491 }
 492 
 493 static 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
 505 static 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 
 521 static 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 
 533 static 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 
 553 static 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 
 574 static SIMPLE_DEV_PM_OPS(ehrpwm_pwm_pm_ops, ehrpwm_pwm_suspend,
 575                          ehrpwm_pwm_resume);
 576 
 577 static 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 };
 586 module_platform_driver(ehrpwm_pwm_driver);
 587 
 588 MODULE_DESCRIPTION("EHRPWM PWM driver");
 589 MODULE_AUTHOR("Texas Instruments");
 590 MODULE_LICENSE("GPL");

/* [<][>][^][v][top][bottom][index][help] */