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