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
  29/* EHRPWM registers and bits definitions */
  30
  31/* Time base module registers */
  32#define TBCTL                   0x00
  33#define TBPRD                   0x0A
  34
  35#define TBCTL_RUN_MASK          (BIT(15) | BIT(14))
  36#define TBCTL_STOP_NEXT         0
  37#define TBCTL_STOP_ON_CYCLE     BIT(14)
  38#define TBCTL_FREE_RUN          (BIT(15) | BIT(14))
  39#define TBCTL_PRDLD_MASK        BIT(3)
  40#define TBCTL_PRDLD_SHDW        0
  41#define TBCTL_PRDLD_IMDT        BIT(3)
  42#define TBCTL_CLKDIV_MASK       (BIT(12) | BIT(11) | BIT(10) | BIT(9) | \
  43                                BIT(8) | BIT(7))
  44#define TBCTL_CTRMODE_MASK      (BIT(1) | BIT(0))
  45#define TBCTL_CTRMODE_UP        0
  46#define TBCTL_CTRMODE_DOWN      BIT(0)
  47#define TBCTL_CTRMODE_UPDOWN    BIT(1)
  48#define TBCTL_CTRMODE_FREEZE    (BIT(1) | BIT(0))
  49
  50#define TBCTL_HSPCLKDIV_SHIFT   7
  51#define TBCTL_CLKDIV_SHIFT      10
  52
  53#define CLKDIV_MAX              7
  54#define HSPCLKDIV_MAX           7
  55#define PERIOD_MAX              0xFFFF
  56
  57/* compare module registers */
  58#define CMPA                    0x12
  59#define CMPB                    0x14
  60
  61/* Action qualifier module registers */
  62#define AQCTLA                  0x16
  63#define AQCTLB                  0x18
  64#define AQSFRC                  0x1A
  65#define AQCSFRC                 0x1C
  66
  67#define AQCTL_CBU_MASK          (BIT(9) | BIT(8))
  68#define AQCTL_CBU_FRCLOW        BIT(8)
  69#define AQCTL_CBU_FRCHIGH       BIT(9)
  70#define AQCTL_CBU_FRCTOGGLE     (BIT(9) | BIT(8))
  71#define AQCTL_CAU_MASK          (BIT(5) | BIT(4))
  72#define AQCTL_CAU_FRCLOW        BIT(4)
  73#define AQCTL_CAU_FRCHIGH       BIT(5)
  74#define AQCTL_CAU_FRCTOGGLE     (BIT(5) | BIT(4))
  75#define AQCTL_PRD_MASK          (BIT(3) | BIT(2))
  76#define AQCTL_PRD_FRCLOW        BIT(2)
  77#define AQCTL_PRD_FRCHIGH       BIT(3)
  78#define AQCTL_PRD_FRCTOGGLE     (BIT(3) | BIT(2))
  79#define AQCTL_ZRO_MASK          (BIT(1) | BIT(0))
  80#define AQCTL_ZRO_FRCLOW        BIT(0)
  81#define AQCTL_ZRO_FRCHIGH       BIT(1)
  82#define AQCTL_ZRO_FRCTOGGLE     (BIT(1) | BIT(0))
  83
  84#define AQCTL_CHANA_POLNORMAL   (AQCTL_CAU_FRCLOW | AQCTL_PRD_FRCHIGH | \
  85                                AQCTL_ZRO_FRCHIGH)
  86#define AQCTL_CHANA_POLINVERSED (AQCTL_CAU_FRCHIGH | AQCTL_PRD_FRCLOW | \
  87                                AQCTL_ZRO_FRCLOW)
  88#define AQCTL_CHANB_POLNORMAL   (AQCTL_CBU_FRCLOW | AQCTL_PRD_FRCHIGH | \
  89                                AQCTL_ZRO_FRCHIGH)
  90#define AQCTL_CHANB_POLINVERSED (AQCTL_CBU_FRCHIGH | AQCTL_PRD_FRCLOW | \
  91                                AQCTL_ZRO_FRCLOW)
  92
  93#define AQSFRC_RLDCSF_MASK      (BIT(7) | BIT(6))
  94#define AQSFRC_RLDCSF_ZRO       0
  95#define AQSFRC_RLDCSF_PRD       BIT(6)
  96#define AQSFRC_RLDCSF_ZROPRD    BIT(7)
  97#define AQSFRC_RLDCSF_IMDT      (BIT(7) | BIT(6))
  98
  99#define AQCSFRC_CSFB_MASK       (BIT(3) | BIT(2))
 100#define AQCSFRC_CSFB_FRCDIS     0
 101#define AQCSFRC_CSFB_FRCLOW     BIT(2)
 102#define AQCSFRC_CSFB_FRCHIGH    BIT(3)
 103#define AQCSFRC_CSFB_DISSWFRC   (BIT(3) | BIT(2))
 104#define AQCSFRC_CSFA_MASK       (BIT(1) | BIT(0))
 105#define AQCSFRC_CSFA_FRCDIS     0
 106#define AQCSFRC_CSFA_FRCLOW     BIT(0)
 107#define AQCSFRC_CSFA_FRCHIGH    BIT(1)
 108#define AQCSFRC_CSFA_DISSWFRC   (BIT(1) | BIT(0))
 109
 110#define NUM_PWM_CHANNEL         2       /* EHRPWM channels */
 111
 112struct ehrpwm_pwm_chip {
 113        struct pwm_chip chip;
 114        unsigned int    clk_rate;
 115        void __iomem    *mmio_base;
 116        unsigned long period_cycles[NUM_PWM_CHANNEL];
 117        enum pwm_polarity polarity[NUM_PWM_CHANNEL];
 118};
 119
 120static inline struct ehrpwm_pwm_chip *to_ehrpwm_pwm_chip(struct pwm_chip *chip)
 121{
 122        return container_of(chip, struct ehrpwm_pwm_chip, chip);
 123}
 124
 125static void ehrpwm_write(void *base, int offset, unsigned int val)
 126{
 127        writew(val & 0xFFFF, base + offset);
 128}
 129
 130static void ehrpwm_modify(void *base, int offset,
 131                unsigned short mask, unsigned short val)
 132{
 133        unsigned short regval;
 134
 135        regval = readw(base + offset);
 136        regval &= ~mask;
 137        regval |= val & mask;
 138        writew(regval, base + offset);
 139}
 140
 141/**
 142 * set_prescale_div -   Set up the prescaler divider function
 143 * @rqst_prescaler:     prescaler value min
 144 * @prescale_div:       prescaler value set
 145 * @tb_clk_div:         Time Base Control prescaler bits
 146 */
 147static int set_prescale_div(unsigned long rqst_prescaler,
 148                unsigned short *prescale_div, unsigned short *tb_clk_div)
 149{
 150        unsigned int clkdiv, hspclkdiv;
 151
 152        for (clkdiv = 0; clkdiv <= CLKDIV_MAX; clkdiv++) {
 153                for (hspclkdiv = 0; hspclkdiv <= HSPCLKDIV_MAX; hspclkdiv++) {
 154
 155                        /*
 156                         * calculations for prescaler value :
 157                         * prescale_div = HSPCLKDIVIDER * CLKDIVIDER.
 158                         * HSPCLKDIVIDER =  2 ** hspclkdiv
 159                         * CLKDIVIDER = (1),            if clkdiv == 0 *OR*
 160                         *              (2 * clkdiv),   if clkdiv != 0
 161                         *
 162                         * Configure prescale_div value such that period
 163                         * register value is less than 65535.
 164                         */
 165
 166                        *prescale_div = (1 << clkdiv) *
 167                                        (hspclkdiv ? (hspclkdiv * 2) : 1);
 168                        if (*prescale_div > rqst_prescaler) {
 169                                *tb_clk_div = (clkdiv << TBCTL_CLKDIV_SHIFT) |
 170                                        (hspclkdiv << TBCTL_HSPCLKDIV_SHIFT);
 171                                return 0;
 172                        }
 173                }
 174        }
 175        return 1;
 176}
 177
 178static void configure_polarity(struct ehrpwm_pwm_chip *pc, int chan)
 179{
 180        int aqctl_reg;
 181        unsigned short aqctl_val, aqctl_mask;
 182
 183        /*
 184         * Configure PWM output to HIGH/LOW level on counter
 185         * reaches compare register value and LOW/HIGH level
 186         * on counter value reaches period register value and
 187         * zero value on counter
 188         */
 189        if (chan == 1) {
 190                aqctl_reg = AQCTLB;
 191                aqctl_mask = AQCTL_CBU_MASK;
 192
 193                if (pc->polarity[chan] == PWM_POLARITY_INVERSED)
 194                        aqctl_val = AQCTL_CHANB_POLINVERSED;
 195                else
 196                        aqctl_val = AQCTL_CHANB_POLNORMAL;
 197        } else {
 198                aqctl_reg = AQCTLA;
 199                aqctl_mask = AQCTL_CAU_MASK;
 200
 201                if (pc->polarity[chan] == PWM_POLARITY_INVERSED)
 202                        aqctl_val = AQCTL_CHANA_POLINVERSED;
 203                else
 204                        aqctl_val = AQCTL_CHANA_POLNORMAL;
 205        }
 206
 207        aqctl_mask |= AQCTL_PRD_MASK | AQCTL_ZRO_MASK;
 208        ehrpwm_modify(pc->mmio_base, aqctl_reg, aqctl_mask, aqctl_val);
 209}
 210
 211/*
 212 * period_ns = 10^9 * (ps_divval * period_cycles) / PWM_CLK_RATE
 213 * duty_ns   = 10^9 * (ps_divval * duty_cycles) / PWM_CLK_RATE
 214 */
 215static int ehrpwm_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
 216                int duty_ns, int period_ns)
 217{
 218        struct ehrpwm_pwm_chip *pc = to_ehrpwm_pwm_chip(chip);
 219        unsigned long long c;
 220        unsigned long period_cycles, duty_cycles;
 221        unsigned short ps_divval, tb_divval;
 222        int i, cmp_reg;
 223
 224        if (period_ns > NSEC_PER_SEC)
 225                return -ERANGE;
 226
 227        c = pc->clk_rate;
 228        c = c * period_ns;
 229        do_div(c, NSEC_PER_SEC);
 230        period_cycles = (unsigned long)c;
 231
 232        if (period_cycles < 1) {
 233                period_cycles = 1;
 234                duty_cycles = 1;
 235        } else {
 236                c = pc->clk_rate;
 237                c = c * duty_ns;
 238                do_div(c, NSEC_PER_SEC);
 239                duty_cycles = (unsigned long)c;
 240        }
 241
 242        /*
 243         * Period values should be same for multiple PWM channels as IP uses
 244         * same period register for multiple channels.
 245         */
 246        for (i = 0; i < NUM_PWM_CHANNEL; i++) {
 247                if (pc->period_cycles[i] &&
 248                                (pc->period_cycles[i] != period_cycles)) {
 249                        /*
 250                         * Allow channel to reconfigure period if no other
 251                         * channels being configured.
 252                         */
 253                        if (i == pwm->hwpwm)
 254                                continue;
 255
 256                        dev_err(chip->dev, "Period value conflicts with channel %d\n",
 257                                        i);
 258                        return -EINVAL;
 259                }
 260        }
 261
 262        pc->period_cycles[pwm->hwpwm] = period_cycles;
 263
 264        /* Configure clock prescaler to support Low frequency PWM wave */
 265        if (set_prescale_div(period_cycles/PERIOD_MAX, &ps_divval,
 266                                &tb_divval)) {
 267                dev_err(chip->dev, "Unsupported values\n");
 268                return -EINVAL;
 269        }
 270
 271        pm_runtime_get_sync(chip->dev);
 272
 273        /* Update clock prescaler values */
 274        ehrpwm_modify(pc->mmio_base, TBCTL, TBCTL_CLKDIV_MASK, tb_divval);
 275
 276        /* Update period & duty cycle with presacler division */
 277        period_cycles = period_cycles / ps_divval;
 278        duty_cycles = duty_cycles / ps_divval;
 279
 280        /* Configure shadow loading on Period register */
 281        ehrpwm_modify(pc->mmio_base, TBCTL, TBCTL_PRDLD_MASK, TBCTL_PRDLD_SHDW);
 282
 283        ehrpwm_write(pc->mmio_base, TBPRD, period_cycles);
 284
 285        /* Configure ehrpwm counter for up-count mode */
 286        ehrpwm_modify(pc->mmio_base, TBCTL, TBCTL_CTRMODE_MASK,
 287                        TBCTL_CTRMODE_UP);
 288
 289        if (pwm->hwpwm == 1)
 290                /* Channel 1 configured with compare B register */
 291                cmp_reg = CMPB;
 292        else
 293                /* Channel 0 configured with compare A register */
 294                cmp_reg = CMPA;
 295
 296        ehrpwm_write(pc->mmio_base, cmp_reg, duty_cycles);
 297
 298        pm_runtime_put_sync(chip->dev);
 299        return 0;
 300}
 301
 302static int ehrpwm_pwm_set_polarity(struct pwm_chip *chip,
 303                struct pwm_device *pwm, enum pwm_polarity polarity)
 304{
 305        struct ehrpwm_pwm_chip *pc = to_ehrpwm_pwm_chip(chip);
 306
 307        /* Configuration of polarity in hardware delayed, do at enable */
 308        pc->polarity[pwm->hwpwm] = polarity;
 309        return 0;
 310}
 311
 312static int ehrpwm_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
 313{
 314        struct ehrpwm_pwm_chip *pc = to_ehrpwm_pwm_chip(chip);
 315        unsigned short aqcsfrc_val, aqcsfrc_mask;
 316
 317        /* Leave clock enabled on enabling PWM */
 318        pm_runtime_get_sync(chip->dev);
 319
 320        /* Disabling Action Qualifier on PWM output */
 321        if (pwm->hwpwm) {
 322                aqcsfrc_val = AQCSFRC_CSFB_FRCDIS;
 323                aqcsfrc_mask = AQCSFRC_CSFB_MASK;
 324        } else {
 325                aqcsfrc_val = AQCSFRC_CSFA_FRCDIS;
 326                aqcsfrc_mask = AQCSFRC_CSFA_MASK;
 327        }
 328
 329        /* Changes to shadow mode */
 330        ehrpwm_modify(pc->mmio_base, AQSFRC, AQSFRC_RLDCSF_MASK,
 331                        AQSFRC_RLDCSF_ZRO);
 332
 333        ehrpwm_modify(pc->mmio_base, AQCSFRC, aqcsfrc_mask, aqcsfrc_val);
 334
 335        /* Channels polarity can be configured from action qualifier module */
 336        configure_polarity(pc, pwm->hwpwm);
 337
 338        /* Enable time counter for free_run */
 339        ehrpwm_modify(pc->mmio_base, TBCTL, TBCTL_RUN_MASK, TBCTL_FREE_RUN);
 340        return 0;
 341}
 342
 343static void ehrpwm_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
 344{
 345        struct ehrpwm_pwm_chip *pc = to_ehrpwm_pwm_chip(chip);
 346        unsigned short aqcsfrc_val, aqcsfrc_mask;
 347
 348        /* Action Qualifier puts PWM output low forcefully */
 349        if (pwm->hwpwm) {
 350                aqcsfrc_val = AQCSFRC_CSFB_FRCLOW;
 351                aqcsfrc_mask = AQCSFRC_CSFB_MASK;
 352        } else {
 353                aqcsfrc_val = AQCSFRC_CSFA_FRCLOW;
 354                aqcsfrc_mask = AQCSFRC_CSFA_MASK;
 355        }
 356
 357        /*
 358         * Changes to immediate action on Action Qualifier. This puts
 359         * Action Qualifier control on PWM output from next TBCLK
 360         */
 361        ehrpwm_modify(pc->mmio_base, AQSFRC, AQSFRC_RLDCSF_MASK,
 362                        AQSFRC_RLDCSF_IMDT);
 363
 364        ehrpwm_modify(pc->mmio_base, AQCSFRC, aqcsfrc_mask, aqcsfrc_val);
 365
 366        /* Stop Time base counter */
 367        ehrpwm_modify(pc->mmio_base, TBCTL, TBCTL_RUN_MASK, TBCTL_STOP_NEXT);
 368
 369        /* Disable clock on PWM disable */
 370        pm_runtime_put_sync(chip->dev);
 371}
 372
 373static void ehrpwm_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm)
 374{
 375        struct ehrpwm_pwm_chip *pc = to_ehrpwm_pwm_chip(chip);
 376
 377        if (test_bit(PWMF_ENABLED, &pwm->flags)) {
 378                dev_warn(chip->dev, "Removing PWM device without disabling\n");
 379                pm_runtime_put_sync(chip->dev);
 380        }
 381
 382        /* set period value to zero on free */
 383        pc->period_cycles[pwm->hwpwm] = 0;
 384}
 385
 386static const struct pwm_ops ehrpwm_pwm_ops = {
 387        .free           = ehrpwm_pwm_free,
 388        .config         = ehrpwm_pwm_config,
 389        .set_polarity   = ehrpwm_pwm_set_polarity,
 390        .enable         = ehrpwm_pwm_enable,
 391        .disable        = ehrpwm_pwm_disable,
 392        .owner          = THIS_MODULE,
 393};
 394
 395static int __devinit ehrpwm_pwm_probe(struct platform_device *pdev)
 396{
 397        int ret;
 398        struct resource *r;
 399        struct clk *clk;
 400        struct ehrpwm_pwm_chip *pc;
 401
 402        pc = devm_kzalloc(&pdev->dev, sizeof(*pc), GFP_KERNEL);
 403        if (!pc) {
 404                dev_err(&pdev->dev, "failed to allocate memory\n");
 405                return -ENOMEM;
 406        }
 407
 408        clk = devm_clk_get(&pdev->dev, "fck");
 409        if (IS_ERR(clk)) {
 410                dev_err(&pdev->dev, "failed to get clock\n");
 411                return PTR_ERR(clk);
 412        }
 413
 414        pc->clk_rate = clk_get_rate(clk);
 415        if (!pc->clk_rate) {
 416                dev_err(&pdev->dev, "failed to get clock rate\n");
 417                return -EINVAL;
 418        }
 419
 420        pc->chip.dev = &pdev->dev;
 421        pc->chip.ops = &ehrpwm_pwm_ops;
 422        pc->chip.base = -1;
 423        pc->chip.npwm = NUM_PWM_CHANNEL;
 424
 425        r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 426        if (!r) {
 427                dev_err(&pdev->dev, "no memory resource defined\n");
 428                return -ENODEV;
 429        }
 430
 431        pc->mmio_base = devm_request_and_ioremap(&pdev->dev, r);
 432        if (!pc->mmio_base)
 433                return  -EADDRNOTAVAIL;
 434
 435        ret = pwmchip_add(&pc->chip);
 436        if (ret < 0) {
 437                dev_err(&pdev->dev, "pwmchip_add() failed: %d\n", ret);
 438                return ret;
 439        }
 440
 441        pm_runtime_enable(&pdev->dev);
 442        platform_set_drvdata(pdev, pc);
 443        return 0;
 444}
 445
 446static int __devexit ehrpwm_pwm_remove(struct platform_device *pdev)
 447{
 448        struct ehrpwm_pwm_chip *pc = platform_get_drvdata(pdev);
 449
 450        pm_runtime_put_sync(&pdev->dev);
 451        pm_runtime_disable(&pdev->dev);
 452        return pwmchip_remove(&pc->chip);
 453}
 454
 455static struct platform_driver ehrpwm_pwm_driver = {
 456        .driver = {
 457                .name = "ehrpwm",
 458        },
 459        .probe = ehrpwm_pwm_probe,
 460        .remove = __devexit_p(ehrpwm_pwm_remove),
 461};
 462
 463module_platform_driver(ehrpwm_pwm_driver);
 464
 465MODULE_DESCRIPTION("EHRPWM PWM driver");
 466MODULE_AUTHOR("Texas Instruments");
 467MODULE_LICENSE("GPL");
 468
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.