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_pwm_chip {
 117        struct pwm_chip chip;
 118        unsigned int    clk_rate;
 119        void __iomem    *mmio_base;
 120        unsigned long period_cycles[NUM_PWM_CHANNEL];
 121        enum pwm_polarity polarity[NUM_PWM_CHANNEL];
 122        struct  clk     *tbclk;
 123};
 124
 125static inline struct ehrpwm_pwm_chip *to_ehrpwm_pwm_chip(struct pwm_chip *chip)
 126{
 127        return container_of(chip, struct ehrpwm_pwm_chip, chip);
 128}
 129
 130static void ehrpwm_write(void *base, int offset, unsigned int val)
 131{
 132        writew(val & 0xFFFF, base + offset);
 133}
 134
 135static void ehrpwm_modify(void *base, int offset,
 136                unsigned short mask, unsigned short val)
 137{
 138        unsigned short regval;
 139
 140        regval = readw(base + offset);
 141        regval &= ~mask;
 142        regval |= val & mask;
 143        writew(regval, base + offset);
 144}
 145
 146/**
 147 * set_prescale_div -   Set up the prescaler divider function
 148 * @rqst_prescaler:     prescaler value min
 149 * @prescale_div:       prescaler value set
 150 * @tb_clk_div:         Time Base Control prescaler bits
 151 */
 152static int set_prescale_div(unsigned long rqst_prescaler,
 153                unsigned short *prescale_div, unsigned short *tb_clk_div)
 154{
 155        unsigned int clkdiv, hspclkdiv;
 156
 157        for (clkdiv = 0; clkdiv <= CLKDIV_MAX; clkdiv++) {
 158                for (hspclkdiv = 0; hspclkdiv <= HSPCLKDIV_MAX; hspclkdiv++) {
 159
 160                        /*
 161                         * calculations for prescaler value :
 162                         * prescale_div = HSPCLKDIVIDER * CLKDIVIDER.
 163                         * HSPCLKDIVIDER =  2 ** hspclkdiv
 164                         * CLKDIVIDER = (1),            if clkdiv == 0 *OR*
 165                         *              (2 * clkdiv),   if clkdiv != 0
 166                         *
 167                         * Configure prescale_div value such that period
 168                         * register value is less than 65535.
 169                         */
 170
 171                        *prescale_div = (1 << clkdiv) *
 172                                        (hspclkdiv ? (hspclkdiv * 2) : 1);
 173                        if (*prescale_div > rqst_prescaler) {
 174                                *tb_clk_div = (clkdiv << TBCTL_CLKDIV_SHIFT) |
 175                                        (hspclkdiv << TBCTL_HSPCLKDIV_SHIFT);
 176                                return 0;
 177                        }
 178                }
 179        }
 180        return 1;
 181}
 182
 183static void configure_polarity(struct ehrpwm_pwm_chip *pc, int chan)
 184{
 185        int aqctl_reg;
 186        unsigned short aqctl_val, aqctl_mask;
 187
 188        /*
 189         * Configure PWM output to HIGH/LOW level on counter
 190         * reaches compare register value and LOW/HIGH level
 191         * on counter value reaches period register value and
 192         * zero value on counter
 193         */
 194        if (chan == 1) {
 195                aqctl_reg = AQCTLB;
 196                aqctl_mask = AQCTL_CBU_MASK;
 197
 198                if (pc->polarity[chan] == PWM_POLARITY_INVERSED)
 199                        aqctl_val = AQCTL_CHANB_POLINVERSED;
 200                else
 201                        aqctl_val = AQCTL_CHANB_POLNORMAL;
 202        } else {
 203                aqctl_reg = AQCTLA;
 204                aqctl_mask = AQCTL_CAU_MASK;
 205
 206                if (pc->polarity[chan] == PWM_POLARITY_INVERSED)
 207                        aqctl_val = AQCTL_CHANA_POLINVERSED;
 208                else
 209                        aqctl_val = AQCTL_CHANA_POLNORMAL;
 210        }
 211
 212        aqctl_mask |= AQCTL_PRD_MASK | AQCTL_ZRO_MASK;
 213        ehrpwm_modify(pc->mmio_base, aqctl_reg, aqctl_mask, aqctl_val);
 214}
 215
 216/*
 217 * period_ns = 10^9 * (ps_divval * period_cycles) / PWM_CLK_RATE
 218 * duty_ns   = 10^9 * (ps_divval * duty_cycles) / PWM_CLK_RATE
 219 */
 220static int ehrpwm_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
 221                int duty_ns, int period_ns)
 222{
 223        struct ehrpwm_pwm_chip *pc = to_ehrpwm_pwm_chip(chip);
 224        unsigned long long c;
 225        unsigned long period_cycles, duty_cycles;
 226        unsigned short ps_divval, tb_divval;
 227        int i, cmp_reg;
 228
 229        if (period_ns > NSEC_PER_SEC)
 230                return -ERANGE;
 231
 232        c = pc->clk_rate;
 233        c = c * period_ns;
 234        do_div(c, NSEC_PER_SEC);
 235        period_cycles = (unsigned long)c;
 236
 237        if (period_cycles < 1) {
 238                period_cycles = 1;
 239                duty_cycles = 1;
 240        } else {
 241                c = pc->clk_rate;
 242                c = c * duty_ns;
 243                do_div(c, NSEC_PER_SEC);
 244                duty_cycles = (unsigned long)c;
 245        }
 246
 247        /*
 248         * Period values should be same for multiple PWM channels as IP uses
 249         * same period register for multiple channels.
 250         */
 251        for (i = 0; i < NUM_PWM_CHANNEL; i++) {
 252                if (pc->period_cycles[i] &&
 253                                (pc->period_cycles[i] != period_cycles)) {
 254                        /*
 255                         * Allow channel to reconfigure period if no other
 256                         * channels being configured.
 257                         */
 258                        if (i == pwm->hwpwm)
 259                                continue;
 260
 261                        dev_err(chip->dev, "Period value conflicts with channel %d\n",
 262                                        i);
 263                        return -EINVAL;
 264                }
 265        }
 266
 267        pc->period_cycles[pwm->hwpwm] = period_cycles;
 268
 269        /* Configure clock prescaler to support Low frequency PWM wave */
 270        if (set_prescale_div(period_cycles/PERIOD_MAX, &ps_divval,
 271                                &tb_divval)) {
 272                dev_err(chip->dev, "Unsupported values\n");
 273                return -EINVAL;
 274        }
 275
 276        pm_runtime_get_sync(chip->dev);
 277
 278        /* Update clock prescaler values */
 279        ehrpwm_modify(pc->mmio_base, TBCTL, TBCTL_CLKDIV_MASK, tb_divval);
 280
 281        /* Update period & duty cycle with presacler division */
 282        period_cycles = period_cycles / ps_divval;
 283        duty_cycles = duty_cycles / ps_divval;
 284
 285        /* Configure shadow loading on Period register */
 286        ehrpwm_modify(pc->mmio_base, TBCTL, TBCTL_PRDLD_MASK, TBCTL_PRDLD_SHDW);
 287
 288        ehrpwm_write(pc->mmio_base, TBPRD, period_cycles);
 289
 290        /* Configure ehrpwm counter for up-count mode */
 291        ehrpwm_modify(pc->mmio_base, TBCTL, TBCTL_CTRMODE_MASK,
 292                        TBCTL_CTRMODE_UP);
 293
 294        if (pwm->hwpwm == 1)
 295                /* Channel 1 configured with compare B register */
 296                cmp_reg = CMPB;
 297        else
 298                /* Channel 0 configured with compare A register */
 299                cmp_reg = CMPA;
 300
 301        ehrpwm_write(pc->mmio_base, cmp_reg, duty_cycles);
 302
 303        pm_runtime_put_sync(chip->dev);
 304        return 0;
 305}
 306
 307static int ehrpwm_pwm_set_polarity(struct pwm_chip *chip,
 308                struct pwm_device *pwm, enum pwm_polarity polarity)
 309{
 310        struct ehrpwm_pwm_chip *pc = to_ehrpwm_pwm_chip(chip);
 311
 312        /* Configuration of polarity in hardware delayed, do at enable */
 313        pc->polarity[pwm->hwpwm] = polarity;
 314        return 0;
 315}
 316
 317static int ehrpwm_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
 318{
 319        struct ehrpwm_pwm_chip *pc = to_ehrpwm_pwm_chip(chip);
 320        unsigned short aqcsfrc_val, aqcsfrc_mask;
 321
 322        /* Leave clock enabled on enabling PWM */
 323        pm_runtime_get_sync(chip->dev);
 324
 325        /* Disabling Action Qualifier on PWM output */
 326        if (pwm->hwpwm) {
 327                aqcsfrc_val = AQCSFRC_CSFB_FRCDIS;
 328                aqcsfrc_mask = AQCSFRC_CSFB_MASK;
 329        } else {
 330                aqcsfrc_val = AQCSFRC_CSFA_FRCDIS;
 331                aqcsfrc_mask = AQCSFRC_CSFA_MASK;
 332        }
 333
 334        /* Changes to shadow mode */
 335        ehrpwm_modify(pc->mmio_base, AQSFRC, AQSFRC_RLDCSF_MASK,
 336                        AQSFRC_RLDCSF_ZRO);
 337
 338        ehrpwm_modify(pc->mmio_base, AQCSFRC, aqcsfrc_mask, aqcsfrc_val);
 339
 340        /* Channels polarity can be configured from action qualifier module */
 341        configure_polarity(pc, pwm->hwpwm);
 342
 343        /* Enable TBCLK before enabling PWM device */
 344        clk_enable(pc->tbclk);
 345
 346        /* Enable time counter for free_run */
 347        ehrpwm_modify(pc->mmio_base, TBCTL, TBCTL_RUN_MASK, TBCTL_FREE_RUN);
 348        return 0;
 349}
 350
 351static void ehrpwm_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
 352{
 353        struct ehrpwm_pwm_chip *pc = to_ehrpwm_pwm_chip(chip);
 354        unsigned short aqcsfrc_val, aqcsfrc_mask;
 355
 356        /* Action Qualifier puts PWM output low forcefully */
 357        if (pwm->hwpwm) {
 358                aqcsfrc_val = AQCSFRC_CSFB_FRCLOW;
 359                aqcsfrc_mask = AQCSFRC_CSFB_MASK;
 360        } else {
 361                aqcsfrc_val = AQCSFRC_CSFA_FRCLOW;
 362                aqcsfrc_mask = AQCSFRC_CSFA_MASK;
 363        }
 364
 365        /*
 366         * Changes to immediate action on Action Qualifier. This puts
 367         * Action Qualifier control on PWM output from next TBCLK
 368         */
 369        ehrpwm_modify(pc->mmio_base, AQSFRC, AQSFRC_RLDCSF_MASK,
 370                        AQSFRC_RLDCSF_IMDT);
 371
 372        ehrpwm_modify(pc->mmio_base, AQCSFRC, aqcsfrc_mask, aqcsfrc_val);
 373
 374        /* Disabling TBCLK on PWM disable */
 375        clk_disable(pc->tbclk);
 376
 377        /* Stop Time base counter */
 378        ehrpwm_modify(pc->mmio_base, TBCTL, TBCTL_RUN_MASK, TBCTL_STOP_NEXT);
 379
 380        /* Disable clock on PWM disable */
 381        pm_runtime_put_sync(chip->dev);
 382}
 383
 384static void ehrpwm_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm)
 385{
 386        struct ehrpwm_pwm_chip *pc = to_ehrpwm_pwm_chip(chip);
 387
 388        if (test_bit(PWMF_ENABLED, &pwm->flags)) {
 389                dev_warn(chip->dev, "Removing PWM device without disabling\n");
 390                pm_runtime_put_sync(chip->dev);
 391        }
 392
 393        /* set period value to zero on free */
 394        pc->period_cycles[pwm->hwpwm] = 0;
 395}
 396
 397static const struct pwm_ops ehrpwm_pwm_ops = {
 398        .free           = ehrpwm_pwm_free,
 399        .config         = ehrpwm_pwm_config,
 400        .set_polarity   = ehrpwm_pwm_set_polarity,
 401        .enable         = ehrpwm_pwm_enable,
 402        .disable        = ehrpwm_pwm_disable,
 403        .owner          = THIS_MODULE,
 404};
 405
 406static const struct of_device_id ehrpwm_of_match[] = {
 407        { .compatible   = "ti,am33xx-ehrpwm" },
 408        {},
 409};
 410MODULE_DEVICE_TABLE(of, ehrpwm_of_match);
 411
 412static int ehrpwm_pwm_probe(struct platform_device *pdev)
 413{
 414        int ret;
 415        struct resource *r;
 416        struct clk *clk;
 417        struct ehrpwm_pwm_chip *pc;
 418        u16 status;
 419        struct pinctrl *pinctrl;
 420
 421        pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
 422        if (IS_ERR(pinctrl))
 423                dev_warn(&pdev->dev, "unable to select pin group\n");
 424
 425        pc = devm_kzalloc(&pdev->dev, sizeof(*pc), GFP_KERNEL);
 426        if (!pc) {
 427                dev_err(&pdev->dev, "failed to allocate memory\n");
 428                return -ENOMEM;
 429        }
 430
 431        clk = devm_clk_get(&pdev->dev, "fck");
 432        if (IS_ERR(clk)) {
 433                dev_err(&pdev->dev, "failed to get clock\n");
 434                return PTR_ERR(clk);
 435        }
 436
 437        pc->clk_rate = clk_get_rate(clk);
 438        if (!pc->clk_rate) {
 439                dev_err(&pdev->dev, "failed to get clock rate\n");
 440                return -EINVAL;
 441        }
 442
 443        pc->chip.dev = &pdev->dev;
 444        pc->chip.ops = &ehrpwm_pwm_ops;
 445        pc->chip.of_xlate = of_pwm_xlate_with_flags;
 446        pc->chip.of_pwm_n_cells = 3;
 447        pc->chip.base = -1;
 448        pc->chip.npwm = NUM_PWM_CHANNEL;
 449
 450        r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 451        if (!r) {
 452                dev_err(&pdev->dev, "no memory resource defined\n");
 453                return -ENODEV;
 454        }
 455
 456        pc->mmio_base = devm_request_and_ioremap(&pdev->dev, r);
 457        if (!pc->mmio_base)
 458                return  -EADDRNOTAVAIL;
 459
 460        /* Acquire tbclk for Time Base EHRPWM submodule */
 461        pc->tbclk = devm_clk_get(&pdev->dev, "tbclk");
 462        if (IS_ERR(pc->tbclk)) {
 463                dev_err(&pdev->dev, "Failed to get tbclk\n");
 464                return PTR_ERR(pc->tbclk);
 465        }
 466
 467        ret = pwmchip_add(&pc->chip);
 468        if (ret < 0) {
 469                dev_err(&pdev->dev, "pwmchip_add() failed: %d\n", ret);
 470                return ret;
 471        }
 472
 473        pm_runtime_enable(&pdev->dev);
 474        pm_runtime_get_sync(&pdev->dev);
 475
 476        status = pwmss_submodule_state_change(pdev->dev.parent,
 477                        PWMSS_EPWMCLK_EN);
 478        if (!(status & PWMSS_EPWMCLK_EN_ACK)) {
 479                dev_err(&pdev->dev, "PWMSS config space clock enable failed\n");
 480                ret = -EINVAL;
 481                goto pwmss_clk_failure;
 482        }
 483
 484        pm_runtime_put_sync(&pdev->dev);
 485
 486        platform_set_drvdata(pdev, pc);
 487        return 0;
 488
 489pwmss_clk_failure:
 490        pm_runtime_put_sync(&pdev->dev);
 491        pm_runtime_disable(&pdev->dev);
 492        pwmchip_remove(&pc->chip);
 493        return ret;
 494}
 495
 496static int ehrpwm_pwm_remove(struct platform_device *pdev)
 497{
 498        struct ehrpwm_pwm_chip *pc = platform_get_drvdata(pdev);
 499
 500        pm_runtime_get_sync(&pdev->dev);
 501        /*
 502         * Due to hardware misbehaviour, acknowledge of the stop_req
 503         * is missing. Hence checking of the status bit skipped.
 504         */
 505        pwmss_submodule_state_change(pdev->dev.parent, PWMSS_EPWMCLK_STOP_REQ);
 506        pm_runtime_put_sync(&pdev->dev);
 507
 508        pm_runtime_put_sync(&pdev->dev);
 509        pm_runtime_disable(&pdev->dev);
 510        return pwmchip_remove(&pc->chip);
 511}
 512
 513static struct platform_driver ehrpwm_pwm_driver = {
 514        .driver = {
 515                .name   = "ehrpwm",
 516                .owner  = THIS_MODULE,
 517                .of_match_table = ehrpwm_of_match,
 518        },
 519        .probe = ehrpwm_pwm_probe,
 520        .remove = ehrpwm_pwm_remove,
 521};
 522
 523module_platform_driver(ehrpwm_pwm_driver);
 524
 525MODULE_DESCRIPTION("EHRPWM PWM driver");
 526MODULE_AUTHOR("Texas Instruments");
 527MODULE_LICENSE("GPL");
 528
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.