root/drivers/pwm/pwm-atmel-tcb.c

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

DEFINITIONS

This source file includes following definitions.
  1. to_tcb_chip
  2. atmel_tcb_pwm_set_polarity
  3. atmel_tcb_pwm_request
  4. atmel_tcb_pwm_free
  5. atmel_tcb_pwm_disable
  6. atmel_tcb_pwm_enable
  7. atmel_tcb_pwm_config
  8. atmel_tcb_pwm_probe
  9. atmel_tcb_pwm_remove
  10. atmel_tcb_pwm_suspend
  11. atmel_tcb_pwm_resume

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * Copyright (C) Overkiz SAS 2012
   4  *
   5  * Author: Boris BREZILLON <b.brezillon@overkiz.com>
   6  */
   7 
   8 #include <linux/module.h>
   9 #include <linux/init.h>
  10 #include <linux/clocksource.h>
  11 #include <linux/clockchips.h>
  12 #include <linux/interrupt.h>
  13 #include <linux/irq.h>
  14 
  15 #include <linux/clk.h>
  16 #include <linux/err.h>
  17 #include <linux/ioport.h>
  18 #include <linux/io.h>
  19 #include <linux/platform_device.h>
  20 #include <linux/pwm.h>
  21 #include <linux/of_device.h>
  22 #include <linux/slab.h>
  23 #include <soc/at91/atmel_tcb.h>
  24 
  25 #define NPWM    6
  26 
  27 #define ATMEL_TC_ACMR_MASK      (ATMEL_TC_ACPA | ATMEL_TC_ACPC |        \
  28                                  ATMEL_TC_AEEVT | ATMEL_TC_ASWTRG)
  29 
  30 #define ATMEL_TC_BCMR_MASK      (ATMEL_TC_BCPB | ATMEL_TC_BCPC |        \
  31                                  ATMEL_TC_BEEVT | ATMEL_TC_BSWTRG)
  32 
  33 struct atmel_tcb_pwm_device {
  34         enum pwm_polarity polarity;     /* PWM polarity */
  35         unsigned div;                   /* PWM clock divider */
  36         unsigned duty;                  /* PWM duty expressed in clk cycles */
  37         unsigned period;                /* PWM period expressed in clk cycles */
  38 };
  39 
  40 struct atmel_tcb_channel {
  41         u32 enabled;
  42         u32 cmr;
  43         u32 ra;
  44         u32 rb;
  45         u32 rc;
  46 };
  47 
  48 struct atmel_tcb_pwm_chip {
  49         struct pwm_chip chip;
  50         spinlock_t lock;
  51         struct atmel_tc *tc;
  52         struct atmel_tcb_pwm_device *pwms[NPWM];
  53         struct atmel_tcb_channel bkup[NPWM / 2];
  54 };
  55 
  56 static inline struct atmel_tcb_pwm_chip *to_tcb_chip(struct pwm_chip *chip)
  57 {
  58         return container_of(chip, struct atmel_tcb_pwm_chip, chip);
  59 }
  60 
  61 static int atmel_tcb_pwm_set_polarity(struct pwm_chip *chip,
  62                                       struct pwm_device *pwm,
  63                                       enum pwm_polarity polarity)
  64 {
  65         struct atmel_tcb_pwm_device *tcbpwm = pwm_get_chip_data(pwm);
  66 
  67         tcbpwm->polarity = polarity;
  68 
  69         return 0;
  70 }
  71 
  72 static int atmel_tcb_pwm_request(struct pwm_chip *chip,
  73                                  struct pwm_device *pwm)
  74 {
  75         struct atmel_tcb_pwm_chip *tcbpwmc = to_tcb_chip(chip);
  76         struct atmel_tcb_pwm_device *tcbpwm;
  77         struct atmel_tc *tc = tcbpwmc->tc;
  78         void __iomem *regs = tc->regs;
  79         unsigned group = pwm->hwpwm / 2;
  80         unsigned index = pwm->hwpwm % 2;
  81         unsigned cmr;
  82         int ret;
  83 
  84         tcbpwm = devm_kzalloc(chip->dev, sizeof(*tcbpwm), GFP_KERNEL);
  85         if (!tcbpwm)
  86                 return -ENOMEM;
  87 
  88         ret = clk_prepare_enable(tc->clk[group]);
  89         if (ret) {
  90                 devm_kfree(chip->dev, tcbpwm);
  91                 return ret;
  92         }
  93 
  94         pwm_set_chip_data(pwm, tcbpwm);
  95         tcbpwm->polarity = PWM_POLARITY_NORMAL;
  96         tcbpwm->duty = 0;
  97         tcbpwm->period = 0;
  98         tcbpwm->div = 0;
  99 
 100         spin_lock(&tcbpwmc->lock);
 101         cmr = __raw_readl(regs + ATMEL_TC_REG(group, CMR));
 102         /*
 103          * Get init config from Timer Counter registers if
 104          * Timer Counter is already configured as a PWM generator.
 105          */
 106         if (cmr & ATMEL_TC_WAVE) {
 107                 if (index == 0)
 108                         tcbpwm->duty =
 109                                 __raw_readl(regs + ATMEL_TC_REG(group, RA));
 110                 else
 111                         tcbpwm->duty =
 112                                 __raw_readl(regs + ATMEL_TC_REG(group, RB));
 113 
 114                 tcbpwm->div = cmr & ATMEL_TC_TCCLKS;
 115                 tcbpwm->period = __raw_readl(regs + ATMEL_TC_REG(group, RC));
 116                 cmr &= (ATMEL_TC_TCCLKS | ATMEL_TC_ACMR_MASK |
 117                         ATMEL_TC_BCMR_MASK);
 118         } else
 119                 cmr = 0;
 120 
 121         cmr |= ATMEL_TC_WAVE | ATMEL_TC_WAVESEL_UP_AUTO | ATMEL_TC_EEVT_XC0;
 122         __raw_writel(cmr, regs + ATMEL_TC_REG(group, CMR));
 123         spin_unlock(&tcbpwmc->lock);
 124 
 125         tcbpwmc->pwms[pwm->hwpwm] = tcbpwm;
 126 
 127         return 0;
 128 }
 129 
 130 static void atmel_tcb_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm)
 131 {
 132         struct atmel_tcb_pwm_chip *tcbpwmc = to_tcb_chip(chip);
 133         struct atmel_tcb_pwm_device *tcbpwm = pwm_get_chip_data(pwm);
 134         struct atmel_tc *tc = tcbpwmc->tc;
 135 
 136         clk_disable_unprepare(tc->clk[pwm->hwpwm / 2]);
 137         tcbpwmc->pwms[pwm->hwpwm] = NULL;
 138         devm_kfree(chip->dev, tcbpwm);
 139 }
 140 
 141 static void atmel_tcb_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
 142 {
 143         struct atmel_tcb_pwm_chip *tcbpwmc = to_tcb_chip(chip);
 144         struct atmel_tcb_pwm_device *tcbpwm = pwm_get_chip_data(pwm);
 145         struct atmel_tc *tc = tcbpwmc->tc;
 146         void __iomem *regs = tc->regs;
 147         unsigned group = pwm->hwpwm / 2;
 148         unsigned index = pwm->hwpwm % 2;
 149         unsigned cmr;
 150         enum pwm_polarity polarity = tcbpwm->polarity;
 151 
 152         /*
 153          * If duty is 0 the timer will be stopped and we have to
 154          * configure the output correctly on software trigger:
 155          *  - set output to high if PWM_POLARITY_INVERSED
 156          *  - set output to low if PWM_POLARITY_NORMAL
 157          *
 158          * This is why we're reverting polarity in this case.
 159          */
 160         if (tcbpwm->duty == 0)
 161                 polarity = !polarity;
 162 
 163         spin_lock(&tcbpwmc->lock);
 164         cmr = __raw_readl(regs + ATMEL_TC_REG(group, CMR));
 165 
 166         /* flush old setting and set the new one */
 167         if (index == 0) {
 168                 cmr &= ~ATMEL_TC_ACMR_MASK;
 169                 if (polarity == PWM_POLARITY_INVERSED)
 170                         cmr |= ATMEL_TC_ASWTRG_CLEAR;
 171                 else
 172                         cmr |= ATMEL_TC_ASWTRG_SET;
 173         } else {
 174                 cmr &= ~ATMEL_TC_BCMR_MASK;
 175                 if (polarity == PWM_POLARITY_INVERSED)
 176                         cmr |= ATMEL_TC_BSWTRG_CLEAR;
 177                 else
 178                         cmr |= ATMEL_TC_BSWTRG_SET;
 179         }
 180 
 181         __raw_writel(cmr, regs + ATMEL_TC_REG(group, CMR));
 182 
 183         /*
 184          * Use software trigger to apply the new setting.
 185          * If both PWM devices in this group are disabled we stop the clock.
 186          */
 187         if (!(cmr & (ATMEL_TC_ACPC | ATMEL_TC_BCPC))) {
 188                 __raw_writel(ATMEL_TC_SWTRG | ATMEL_TC_CLKDIS,
 189                              regs + ATMEL_TC_REG(group, CCR));
 190                 tcbpwmc->bkup[group].enabled = 1;
 191         } else {
 192                 __raw_writel(ATMEL_TC_SWTRG, regs +
 193                              ATMEL_TC_REG(group, CCR));
 194                 tcbpwmc->bkup[group].enabled = 0;
 195         }
 196 
 197         spin_unlock(&tcbpwmc->lock);
 198 }
 199 
 200 static int atmel_tcb_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
 201 {
 202         struct atmel_tcb_pwm_chip *tcbpwmc = to_tcb_chip(chip);
 203         struct atmel_tcb_pwm_device *tcbpwm = pwm_get_chip_data(pwm);
 204         struct atmel_tc *tc = tcbpwmc->tc;
 205         void __iomem *regs = tc->regs;
 206         unsigned group = pwm->hwpwm / 2;
 207         unsigned index = pwm->hwpwm % 2;
 208         u32 cmr;
 209         enum pwm_polarity polarity = tcbpwm->polarity;
 210 
 211         /*
 212          * If duty is 0 the timer will be stopped and we have to
 213          * configure the output correctly on software trigger:
 214          *  - set output to high if PWM_POLARITY_INVERSED
 215          *  - set output to low if PWM_POLARITY_NORMAL
 216          *
 217          * This is why we're reverting polarity in this case.
 218          */
 219         if (tcbpwm->duty == 0)
 220                 polarity = !polarity;
 221 
 222         spin_lock(&tcbpwmc->lock);
 223         cmr = __raw_readl(regs + ATMEL_TC_REG(group, CMR));
 224 
 225         /* flush old setting and set the new one */
 226         cmr &= ~ATMEL_TC_TCCLKS;
 227 
 228         if (index == 0) {
 229                 cmr &= ~ATMEL_TC_ACMR_MASK;
 230 
 231                 /* Set CMR flags according to given polarity */
 232                 if (polarity == PWM_POLARITY_INVERSED)
 233                         cmr |= ATMEL_TC_ASWTRG_CLEAR;
 234                 else
 235                         cmr |= ATMEL_TC_ASWTRG_SET;
 236         } else {
 237                 cmr &= ~ATMEL_TC_BCMR_MASK;
 238                 if (polarity == PWM_POLARITY_INVERSED)
 239                         cmr |= ATMEL_TC_BSWTRG_CLEAR;
 240                 else
 241                         cmr |= ATMEL_TC_BSWTRG_SET;
 242         }
 243 
 244         /*
 245          * If duty is 0 or equal to period there's no need to register
 246          * a specific action on RA/RB and RC compare.
 247          * The output will be configured on software trigger and keep
 248          * this config till next config call.
 249          */
 250         if (tcbpwm->duty != tcbpwm->period && tcbpwm->duty > 0) {
 251                 if (index == 0) {
 252                         if (polarity == PWM_POLARITY_INVERSED)
 253                                 cmr |= ATMEL_TC_ACPA_SET | ATMEL_TC_ACPC_CLEAR;
 254                         else
 255                                 cmr |= ATMEL_TC_ACPA_CLEAR | ATMEL_TC_ACPC_SET;
 256                 } else {
 257                         if (polarity == PWM_POLARITY_INVERSED)
 258                                 cmr |= ATMEL_TC_BCPB_SET | ATMEL_TC_BCPC_CLEAR;
 259                         else
 260                                 cmr |= ATMEL_TC_BCPB_CLEAR | ATMEL_TC_BCPC_SET;
 261                 }
 262         }
 263 
 264         cmr |= (tcbpwm->div & ATMEL_TC_TCCLKS);
 265 
 266         __raw_writel(cmr, regs + ATMEL_TC_REG(group, CMR));
 267 
 268         if (index == 0)
 269                 __raw_writel(tcbpwm->duty, regs + ATMEL_TC_REG(group, RA));
 270         else
 271                 __raw_writel(tcbpwm->duty, regs + ATMEL_TC_REG(group, RB));
 272 
 273         __raw_writel(tcbpwm->period, regs + ATMEL_TC_REG(group, RC));
 274 
 275         /* Use software trigger to apply the new setting */
 276         __raw_writel(ATMEL_TC_CLKEN | ATMEL_TC_SWTRG,
 277                      regs + ATMEL_TC_REG(group, CCR));
 278         tcbpwmc->bkup[group].enabled = 1;
 279         spin_unlock(&tcbpwmc->lock);
 280         return 0;
 281 }
 282 
 283 static int atmel_tcb_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
 284                                 int duty_ns, int period_ns)
 285 {
 286         struct atmel_tcb_pwm_chip *tcbpwmc = to_tcb_chip(chip);
 287         struct atmel_tcb_pwm_device *tcbpwm = pwm_get_chip_data(pwm);
 288         unsigned group = pwm->hwpwm / 2;
 289         unsigned index = pwm->hwpwm % 2;
 290         struct atmel_tcb_pwm_device *atcbpwm = NULL;
 291         struct atmel_tc *tc = tcbpwmc->tc;
 292         int i;
 293         int slowclk = 0;
 294         unsigned period;
 295         unsigned duty;
 296         unsigned rate = clk_get_rate(tc->clk[group]);
 297         unsigned long long min;
 298         unsigned long long max;
 299 
 300         /*
 301          * Find best clk divisor:
 302          * the smallest divisor which can fulfill the period_ns requirements.
 303          */
 304         for (i = 0; i < 5; ++i) {
 305                 if (atmel_tc_divisors[i] == 0) {
 306                         slowclk = i;
 307                         continue;
 308                 }
 309                 min = div_u64((u64)NSEC_PER_SEC * atmel_tc_divisors[i], rate);
 310                 max = min << tc->tcb_config->counter_width;
 311                 if (max >= period_ns)
 312                         break;
 313         }
 314 
 315         /*
 316          * If none of the divisor are small enough to represent period_ns
 317          * take slow clock (32KHz).
 318          */
 319         if (i == 5) {
 320                 i = slowclk;
 321                 rate = clk_get_rate(tc->slow_clk);
 322                 min = div_u64(NSEC_PER_SEC, rate);
 323                 max = min << tc->tcb_config->counter_width;
 324 
 325                 /* If period is too big return ERANGE error */
 326                 if (max < period_ns)
 327                         return -ERANGE;
 328         }
 329 
 330         duty = div_u64(duty_ns, min);
 331         period = div_u64(period_ns, min);
 332 
 333         if (index == 0)
 334                 atcbpwm = tcbpwmc->pwms[pwm->hwpwm + 1];
 335         else
 336                 atcbpwm = tcbpwmc->pwms[pwm->hwpwm - 1];
 337 
 338         /*
 339          * PWM devices provided by TCB driver are grouped by 2:
 340          * - group 0: PWM 0 & 1
 341          * - group 1: PWM 2 & 3
 342          * - group 2: PWM 4 & 5
 343          *
 344          * PWM devices in a given group must be configured with the
 345          * same period_ns.
 346          *
 347          * We're checking the period value of the second PWM device
 348          * in this group before applying the new config.
 349          */
 350         if ((atcbpwm && atcbpwm->duty > 0 &&
 351                         atcbpwm->duty != atcbpwm->period) &&
 352                 (atcbpwm->div != i || atcbpwm->period != period)) {
 353                 dev_err(chip->dev,
 354                         "failed to configure period_ns: PWM group already configured with a different value\n");
 355                 return -EINVAL;
 356         }
 357 
 358         tcbpwm->period = period;
 359         tcbpwm->div = i;
 360         tcbpwm->duty = duty;
 361 
 362         /* If the PWM is enabled, call enable to apply the new conf */
 363         if (pwm_is_enabled(pwm))
 364                 atmel_tcb_pwm_enable(chip, pwm);
 365 
 366         return 0;
 367 }
 368 
 369 static const struct pwm_ops atmel_tcb_pwm_ops = {
 370         .request = atmel_tcb_pwm_request,
 371         .free = atmel_tcb_pwm_free,
 372         .config = atmel_tcb_pwm_config,
 373         .set_polarity = atmel_tcb_pwm_set_polarity,
 374         .enable = atmel_tcb_pwm_enable,
 375         .disable = atmel_tcb_pwm_disable,
 376         .owner = THIS_MODULE,
 377 };
 378 
 379 static int atmel_tcb_pwm_probe(struct platform_device *pdev)
 380 {
 381         struct atmel_tcb_pwm_chip *tcbpwm;
 382         struct device_node *np = pdev->dev.of_node;
 383         struct atmel_tc *tc;
 384         int err;
 385         int tcblock;
 386 
 387         err = of_property_read_u32(np, "tc-block", &tcblock);
 388         if (err < 0) {
 389                 dev_err(&pdev->dev,
 390                         "failed to get Timer Counter Block number from device tree (error: %d)\n",
 391                         err);
 392                 return err;
 393         }
 394 
 395         tc = atmel_tc_alloc(tcblock);
 396         if (tc == NULL) {
 397                 dev_err(&pdev->dev, "failed to allocate Timer Counter Block\n");
 398                 return -ENOMEM;
 399         }
 400 
 401         tcbpwm = devm_kzalloc(&pdev->dev, sizeof(*tcbpwm), GFP_KERNEL);
 402         if (tcbpwm == NULL) {
 403                 err = -ENOMEM;
 404                 goto err_free_tc;
 405         }
 406 
 407         tcbpwm->chip.dev = &pdev->dev;
 408         tcbpwm->chip.ops = &atmel_tcb_pwm_ops;
 409         tcbpwm->chip.of_xlate = of_pwm_xlate_with_flags;
 410         tcbpwm->chip.of_pwm_n_cells = 3;
 411         tcbpwm->chip.base = -1;
 412         tcbpwm->chip.npwm = NPWM;
 413         tcbpwm->tc = tc;
 414 
 415         err = clk_prepare_enable(tc->slow_clk);
 416         if (err)
 417                 goto err_free_tc;
 418 
 419         spin_lock_init(&tcbpwm->lock);
 420 
 421         err = pwmchip_add(&tcbpwm->chip);
 422         if (err < 0)
 423                 goto err_disable_clk;
 424 
 425         platform_set_drvdata(pdev, tcbpwm);
 426 
 427         return 0;
 428 
 429 err_disable_clk:
 430         clk_disable_unprepare(tcbpwm->tc->slow_clk);
 431 
 432 err_free_tc:
 433         atmel_tc_free(tc);
 434 
 435         return err;
 436 }
 437 
 438 static int atmel_tcb_pwm_remove(struct platform_device *pdev)
 439 {
 440         struct atmel_tcb_pwm_chip *tcbpwm = platform_get_drvdata(pdev);
 441         int err;
 442 
 443         clk_disable_unprepare(tcbpwm->tc->slow_clk);
 444 
 445         err = pwmchip_remove(&tcbpwm->chip);
 446         if (err < 0)
 447                 return err;
 448 
 449         atmel_tc_free(tcbpwm->tc);
 450 
 451         return 0;
 452 }
 453 
 454 static const struct of_device_id atmel_tcb_pwm_dt_ids[] = {
 455         { .compatible = "atmel,tcb-pwm", },
 456         { /* sentinel */ }
 457 };
 458 MODULE_DEVICE_TABLE(of, atmel_tcb_pwm_dt_ids);
 459 
 460 #ifdef CONFIG_PM_SLEEP
 461 static int atmel_tcb_pwm_suspend(struct device *dev)
 462 {
 463         struct atmel_tcb_pwm_chip *tcbpwm = dev_get_drvdata(dev);
 464         void __iomem *base = tcbpwm->tc->regs;
 465         int i;
 466 
 467         for (i = 0; i < (NPWM / 2); i++) {
 468                 struct atmel_tcb_channel *chan = &tcbpwm->bkup[i];
 469 
 470                 chan->cmr = readl(base + ATMEL_TC_REG(i, CMR));
 471                 chan->ra = readl(base + ATMEL_TC_REG(i, RA));
 472                 chan->rb = readl(base + ATMEL_TC_REG(i, RB));
 473                 chan->rc = readl(base + ATMEL_TC_REG(i, RC));
 474         }
 475         return 0;
 476 }
 477 
 478 static int atmel_tcb_pwm_resume(struct device *dev)
 479 {
 480         struct atmel_tcb_pwm_chip *tcbpwm = dev_get_drvdata(dev);
 481         void __iomem *base = tcbpwm->tc->regs;
 482         int i;
 483 
 484         for (i = 0; i < (NPWM / 2); i++) {
 485                 struct atmel_tcb_channel *chan = &tcbpwm->bkup[i];
 486 
 487                 writel(chan->cmr, base + ATMEL_TC_REG(i, CMR));
 488                 writel(chan->ra, base + ATMEL_TC_REG(i, RA));
 489                 writel(chan->rb, base + ATMEL_TC_REG(i, RB));
 490                 writel(chan->rc, base + ATMEL_TC_REG(i, RC));
 491                 if (chan->enabled) {
 492                         writel(ATMEL_TC_CLKEN | ATMEL_TC_SWTRG,
 493                                 base + ATMEL_TC_REG(i, CCR));
 494                 }
 495         }
 496         return 0;
 497 }
 498 #endif
 499 
 500 static SIMPLE_DEV_PM_OPS(atmel_tcb_pwm_pm_ops, atmel_tcb_pwm_suspend,
 501                          atmel_tcb_pwm_resume);
 502 
 503 static struct platform_driver atmel_tcb_pwm_driver = {
 504         .driver = {
 505                 .name = "atmel-tcb-pwm",
 506                 .of_match_table = atmel_tcb_pwm_dt_ids,
 507                 .pm = &atmel_tcb_pwm_pm_ops,
 508         },
 509         .probe = atmel_tcb_pwm_probe,
 510         .remove = atmel_tcb_pwm_remove,
 511 };
 512 module_platform_driver(atmel_tcb_pwm_driver);
 513 
 514 MODULE_AUTHOR("Boris BREZILLON <b.brezillon@overkiz.com>");
 515 MODULE_DESCRIPTION("Atmel Timer Counter Pulse Width Modulation Driver");
 516 MODULE_LICENSE("GPL v2");

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