linux/drivers/pwm/pwm-lpc18xx-sct.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * NXP LPC18xx State Configurable Timer - Pulse Width Modulator driver
   4 *
   5 * Copyright (c) 2015 Ariel D'Alessandro <ariel@vanguardiasur.com>
   6 *
   7 * Notes
   8 * =====
   9 * NXP LPC18xx provides a State Configurable Timer (SCT) which can be configured
  10 * as a Pulse Width Modulator.
  11 *
  12 * SCT supports 16 outputs, 16 events and 16 registers. Each event will be
  13 * triggered when its related register matches the SCT counter value, and it
  14 * will set or clear a selected output.
  15 *
  16 * One of the events is preselected to generate the period, thus the maximum
  17 * number of simultaneous channels is limited to 15. Notice that period is
  18 * global to all the channels, thus PWM driver will refuse setting different
  19 * values to it, unless there's only one channel requested.
  20 */
  21
  22#include <linux/clk.h>
  23#include <linux/err.h>
  24#include <linux/io.h>
  25#include <linux/module.h>
  26#include <linux/platform_device.h>
  27#include <linux/pwm.h>
  28
  29/* LPC18xx SCT registers */
  30#define LPC18XX_PWM_CONFIG              0x000
  31#define LPC18XX_PWM_CONFIG_UNIFY        BIT(0)
  32#define LPC18XX_PWM_CONFIG_NORELOAD     BIT(7)
  33
  34#define LPC18XX_PWM_CTRL                0x004
  35#define LPC18XX_PWM_CTRL_HALT           BIT(2)
  36#define LPC18XX_PWM_BIDIR               BIT(4)
  37#define LPC18XX_PWM_PRE_SHIFT           5
  38#define LPC18XX_PWM_PRE_MASK            (0xff << LPC18XX_PWM_PRE_SHIFT)
  39#define LPC18XX_PWM_PRE(x)              (x << LPC18XX_PWM_PRE_SHIFT)
  40
  41#define LPC18XX_PWM_LIMIT               0x008
  42
  43#define LPC18XX_PWM_RES_BASE            0x058
  44#define LPC18XX_PWM_RES_SHIFT(_ch)      (_ch * 2)
  45#define LPC18XX_PWM_RES(_ch, _action)   (_action << LPC18XX_PWM_RES_SHIFT(_ch))
  46#define LPC18XX_PWM_RES_MASK(_ch)       (0x3 << LPC18XX_PWM_RES_SHIFT(_ch))
  47
  48#define LPC18XX_PWM_MATCH_BASE          0x100
  49#define LPC18XX_PWM_MATCH(_ch)          (LPC18XX_PWM_MATCH_BASE + _ch * 4)
  50
  51#define LPC18XX_PWM_MATCHREL_BASE       0x200
  52#define LPC18XX_PWM_MATCHREL(_ch)       (LPC18XX_PWM_MATCHREL_BASE + _ch * 4)
  53
  54#define LPC18XX_PWM_EVSTATEMSK_BASE     0x300
  55#define LPC18XX_PWM_EVSTATEMSK(_ch)     (LPC18XX_PWM_EVSTATEMSK_BASE + _ch * 8)
  56#define LPC18XX_PWM_EVSTATEMSK_ALL      0xffffffff
  57
  58#define LPC18XX_PWM_EVCTRL_BASE         0x304
  59#define LPC18XX_PWM_EVCTRL(_ev)         (LPC18XX_PWM_EVCTRL_BASE + _ev * 8)
  60
  61#define LPC18XX_PWM_EVCTRL_MATCH(_ch)   _ch
  62
  63#define LPC18XX_PWM_EVCTRL_COMB_SHIFT   12
  64#define LPC18XX_PWM_EVCTRL_COMB_MATCH   (0x1 << LPC18XX_PWM_EVCTRL_COMB_SHIFT)
  65
  66#define LPC18XX_PWM_OUTPUTSET_BASE      0x500
  67#define LPC18XX_PWM_OUTPUTSET(_ch)      (LPC18XX_PWM_OUTPUTSET_BASE + _ch * 8)
  68
  69#define LPC18XX_PWM_OUTPUTCL_BASE       0x504
  70#define LPC18XX_PWM_OUTPUTCL(_ch)       (LPC18XX_PWM_OUTPUTCL_BASE + _ch * 8)
  71
  72/* LPC18xx SCT unified counter */
  73#define LPC18XX_PWM_TIMER_MAX           0xffffffff
  74
  75/* LPC18xx SCT events */
  76#define LPC18XX_PWM_EVENT_PERIOD        0
  77#define LPC18XX_PWM_EVENT_MAX           16
  78
  79/* SCT conflict resolution */
  80enum lpc18xx_pwm_res_action {
  81        LPC18XX_PWM_RES_NONE,
  82        LPC18XX_PWM_RES_SET,
  83        LPC18XX_PWM_RES_CLEAR,
  84        LPC18XX_PWM_RES_TOGGLE,
  85};
  86
  87struct lpc18xx_pwm_data {
  88        unsigned int duty_event;
  89};
  90
  91struct lpc18xx_pwm_chip {
  92        struct device *dev;
  93        struct pwm_chip chip;
  94        void __iomem *base;
  95        struct clk *pwm_clk;
  96        unsigned long clk_rate;
  97        unsigned int period_ns;
  98        unsigned int min_period_ns;
  99        unsigned int max_period_ns;
 100        unsigned int period_event;
 101        unsigned long event_map;
 102        struct mutex res_lock;
 103        struct mutex period_lock;
 104};
 105
 106static inline struct lpc18xx_pwm_chip *
 107to_lpc18xx_pwm_chip(struct pwm_chip *chip)
 108{
 109        return container_of(chip, struct lpc18xx_pwm_chip, chip);
 110}
 111
 112static inline void lpc18xx_pwm_writel(struct lpc18xx_pwm_chip *lpc18xx_pwm,
 113                                      u32 reg, u32 val)
 114{
 115        writel(val, lpc18xx_pwm->base + reg);
 116}
 117
 118static inline u32 lpc18xx_pwm_readl(struct lpc18xx_pwm_chip *lpc18xx_pwm,
 119                                    u32 reg)
 120{
 121        return readl(lpc18xx_pwm->base + reg);
 122}
 123
 124static void lpc18xx_pwm_set_conflict_res(struct lpc18xx_pwm_chip *lpc18xx_pwm,
 125                                         struct pwm_device *pwm,
 126                                         enum lpc18xx_pwm_res_action action)
 127{
 128        u32 val;
 129
 130        mutex_lock(&lpc18xx_pwm->res_lock);
 131
 132        /*
 133         * Simultaneous set and clear may happen on an output, that is the case
 134         * when duty_ns == period_ns. LPC18xx SCT allows to set a conflict
 135         * resolution action to be taken in such a case.
 136         */
 137        val = lpc18xx_pwm_readl(lpc18xx_pwm, LPC18XX_PWM_RES_BASE);
 138        val &= ~LPC18XX_PWM_RES_MASK(pwm->hwpwm);
 139        val |= LPC18XX_PWM_RES(pwm->hwpwm, action);
 140        lpc18xx_pwm_writel(lpc18xx_pwm, LPC18XX_PWM_RES_BASE, val);
 141
 142        mutex_unlock(&lpc18xx_pwm->res_lock);
 143}
 144
 145static void lpc18xx_pwm_config_period(struct pwm_chip *chip, int period_ns)
 146{
 147        struct lpc18xx_pwm_chip *lpc18xx_pwm = to_lpc18xx_pwm_chip(chip);
 148        u64 val;
 149
 150        val = (u64)period_ns * lpc18xx_pwm->clk_rate;
 151        do_div(val, NSEC_PER_SEC);
 152
 153        lpc18xx_pwm_writel(lpc18xx_pwm,
 154                           LPC18XX_PWM_MATCH(lpc18xx_pwm->period_event),
 155                           (u32)val - 1);
 156
 157        lpc18xx_pwm_writel(lpc18xx_pwm,
 158                           LPC18XX_PWM_MATCHREL(lpc18xx_pwm->period_event),
 159                           (u32)val - 1);
 160}
 161
 162static void lpc18xx_pwm_config_duty(struct pwm_chip *chip,
 163                                    struct pwm_device *pwm, int duty_ns)
 164{
 165        struct lpc18xx_pwm_chip *lpc18xx_pwm = to_lpc18xx_pwm_chip(chip);
 166        struct lpc18xx_pwm_data *lpc18xx_data = pwm_get_chip_data(pwm);
 167        u64 val;
 168
 169        val = (u64)duty_ns * lpc18xx_pwm->clk_rate;
 170        do_div(val, NSEC_PER_SEC);
 171
 172        lpc18xx_pwm_writel(lpc18xx_pwm,
 173                           LPC18XX_PWM_MATCH(lpc18xx_data->duty_event),
 174                           (u32)val);
 175
 176        lpc18xx_pwm_writel(lpc18xx_pwm,
 177                           LPC18XX_PWM_MATCHREL(lpc18xx_data->duty_event),
 178                           (u32)val);
 179}
 180
 181static int lpc18xx_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
 182                              int duty_ns, int period_ns)
 183{
 184        struct lpc18xx_pwm_chip *lpc18xx_pwm = to_lpc18xx_pwm_chip(chip);
 185        int requested_events, i;
 186
 187        if (period_ns < lpc18xx_pwm->min_period_ns ||
 188            period_ns > lpc18xx_pwm->max_period_ns) {
 189                dev_err(chip->dev, "period %d not in range\n", period_ns);
 190                return -ERANGE;
 191        }
 192
 193        mutex_lock(&lpc18xx_pwm->period_lock);
 194
 195        requested_events = bitmap_weight(&lpc18xx_pwm->event_map,
 196                                         LPC18XX_PWM_EVENT_MAX);
 197
 198        /*
 199         * The PWM supports only a single period for all PWM channels.
 200         * Once the period is set, it can only be changed if no more than one
 201         * channel is requested at that moment.
 202         */
 203        if (requested_events > 2 && lpc18xx_pwm->period_ns != period_ns &&
 204            lpc18xx_pwm->period_ns) {
 205                dev_err(chip->dev, "conflicting period requested for PWM %u\n",
 206                        pwm->hwpwm);
 207                mutex_unlock(&lpc18xx_pwm->period_lock);
 208                return -EBUSY;
 209        }
 210
 211        if ((requested_events <= 2 && lpc18xx_pwm->period_ns != period_ns) ||
 212            !lpc18xx_pwm->period_ns) {
 213                lpc18xx_pwm->period_ns = period_ns;
 214                for (i = 0; i < chip->npwm; i++)
 215                        pwm_set_period(&chip->pwms[i], period_ns);
 216                lpc18xx_pwm_config_period(chip, period_ns);
 217        }
 218
 219        mutex_unlock(&lpc18xx_pwm->period_lock);
 220
 221        lpc18xx_pwm_config_duty(chip, pwm, duty_ns);
 222
 223        return 0;
 224}
 225
 226static int lpc18xx_pwm_set_polarity(struct pwm_chip *chip,
 227                                    struct pwm_device *pwm,
 228                                    enum pwm_polarity polarity)
 229{
 230        return 0;
 231}
 232
 233static int lpc18xx_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
 234{
 235        struct lpc18xx_pwm_chip *lpc18xx_pwm = to_lpc18xx_pwm_chip(chip);
 236        struct lpc18xx_pwm_data *lpc18xx_data = pwm_get_chip_data(pwm);
 237        enum lpc18xx_pwm_res_action res_action;
 238        unsigned int set_event, clear_event;
 239
 240        lpc18xx_pwm_writel(lpc18xx_pwm,
 241                           LPC18XX_PWM_EVCTRL(lpc18xx_data->duty_event),
 242                           LPC18XX_PWM_EVCTRL_MATCH(lpc18xx_data->duty_event) |
 243                           LPC18XX_PWM_EVCTRL_COMB_MATCH);
 244
 245        lpc18xx_pwm_writel(lpc18xx_pwm,
 246                           LPC18XX_PWM_EVSTATEMSK(lpc18xx_data->duty_event),
 247                           LPC18XX_PWM_EVSTATEMSK_ALL);
 248
 249        if (pwm_get_polarity(pwm) == PWM_POLARITY_NORMAL) {
 250                set_event = lpc18xx_pwm->period_event;
 251                clear_event = lpc18xx_data->duty_event;
 252                res_action = LPC18XX_PWM_RES_SET;
 253        } else {
 254                set_event = lpc18xx_data->duty_event;
 255                clear_event = lpc18xx_pwm->period_event;
 256                res_action = LPC18XX_PWM_RES_CLEAR;
 257        }
 258
 259        lpc18xx_pwm_writel(lpc18xx_pwm, LPC18XX_PWM_OUTPUTSET(pwm->hwpwm),
 260                           BIT(set_event));
 261        lpc18xx_pwm_writel(lpc18xx_pwm, LPC18XX_PWM_OUTPUTCL(pwm->hwpwm),
 262                           BIT(clear_event));
 263        lpc18xx_pwm_set_conflict_res(lpc18xx_pwm, pwm, res_action);
 264
 265        return 0;
 266}
 267
 268static void lpc18xx_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
 269{
 270        struct lpc18xx_pwm_chip *lpc18xx_pwm = to_lpc18xx_pwm_chip(chip);
 271        struct lpc18xx_pwm_data *lpc18xx_data = pwm_get_chip_data(pwm);
 272
 273        lpc18xx_pwm_writel(lpc18xx_pwm,
 274                           LPC18XX_PWM_EVCTRL(lpc18xx_data->duty_event), 0);
 275        lpc18xx_pwm_writel(lpc18xx_pwm, LPC18XX_PWM_OUTPUTSET(pwm->hwpwm), 0);
 276        lpc18xx_pwm_writel(lpc18xx_pwm, LPC18XX_PWM_OUTPUTCL(pwm->hwpwm), 0);
 277}
 278
 279static int lpc18xx_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm)
 280{
 281        struct lpc18xx_pwm_chip *lpc18xx_pwm = to_lpc18xx_pwm_chip(chip);
 282        struct lpc18xx_pwm_data *lpc18xx_data = pwm_get_chip_data(pwm);
 283        unsigned long event;
 284
 285        event = find_first_zero_bit(&lpc18xx_pwm->event_map,
 286                                    LPC18XX_PWM_EVENT_MAX);
 287
 288        if (event >= LPC18XX_PWM_EVENT_MAX) {
 289                dev_err(lpc18xx_pwm->dev,
 290                        "maximum number of simultaneous channels reached\n");
 291                return -EBUSY;
 292        };
 293
 294        set_bit(event, &lpc18xx_pwm->event_map);
 295        lpc18xx_data->duty_event = event;
 296
 297        return 0;
 298}
 299
 300static void lpc18xx_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm)
 301{
 302        struct lpc18xx_pwm_chip *lpc18xx_pwm = to_lpc18xx_pwm_chip(chip);
 303        struct lpc18xx_pwm_data *lpc18xx_data = pwm_get_chip_data(pwm);
 304
 305        clear_bit(lpc18xx_data->duty_event, &lpc18xx_pwm->event_map);
 306}
 307
 308static const struct pwm_ops lpc18xx_pwm_ops = {
 309        .config = lpc18xx_pwm_config,
 310        .set_polarity = lpc18xx_pwm_set_polarity,
 311        .enable = lpc18xx_pwm_enable,
 312        .disable = lpc18xx_pwm_disable,
 313        .request = lpc18xx_pwm_request,
 314        .free = lpc18xx_pwm_free,
 315        .owner = THIS_MODULE,
 316};
 317
 318static const struct of_device_id lpc18xx_pwm_of_match[] = {
 319        { .compatible = "nxp,lpc1850-sct-pwm" },
 320        {}
 321};
 322MODULE_DEVICE_TABLE(of, lpc18xx_pwm_of_match);
 323
 324static int lpc18xx_pwm_probe(struct platform_device *pdev)
 325{
 326        struct lpc18xx_pwm_chip *lpc18xx_pwm;
 327        struct pwm_device *pwm;
 328        struct resource *res;
 329        int ret, i;
 330        u64 val;
 331
 332        lpc18xx_pwm = devm_kzalloc(&pdev->dev, sizeof(*lpc18xx_pwm),
 333                                   GFP_KERNEL);
 334        if (!lpc18xx_pwm)
 335                return -ENOMEM;
 336
 337        lpc18xx_pwm->dev = &pdev->dev;
 338
 339        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 340        lpc18xx_pwm->base = devm_ioremap_resource(&pdev->dev, res);
 341        if (IS_ERR(lpc18xx_pwm->base))
 342                return PTR_ERR(lpc18xx_pwm->base);
 343
 344        lpc18xx_pwm->pwm_clk = devm_clk_get(&pdev->dev, "pwm");
 345        if (IS_ERR(lpc18xx_pwm->pwm_clk)) {
 346                dev_err(&pdev->dev, "failed to get pwm clock\n");
 347                return PTR_ERR(lpc18xx_pwm->pwm_clk);
 348        }
 349
 350        ret = clk_prepare_enable(lpc18xx_pwm->pwm_clk);
 351        if (ret < 0) {
 352                dev_err(&pdev->dev, "could not prepare or enable pwm clock\n");
 353                return ret;
 354        }
 355
 356        lpc18xx_pwm->clk_rate = clk_get_rate(lpc18xx_pwm->pwm_clk);
 357        if (!lpc18xx_pwm->clk_rate) {
 358                dev_err(&pdev->dev, "pwm clock has no frequency\n");
 359                ret = -EINVAL;
 360                goto disable_pwmclk;
 361        }
 362
 363        mutex_init(&lpc18xx_pwm->res_lock);
 364        mutex_init(&lpc18xx_pwm->period_lock);
 365
 366        val = (u64)NSEC_PER_SEC * LPC18XX_PWM_TIMER_MAX;
 367        do_div(val, lpc18xx_pwm->clk_rate);
 368        lpc18xx_pwm->max_period_ns = val;
 369
 370        lpc18xx_pwm->min_period_ns = DIV_ROUND_UP(NSEC_PER_SEC,
 371                                                  lpc18xx_pwm->clk_rate);
 372
 373        lpc18xx_pwm->chip.dev = &pdev->dev;
 374        lpc18xx_pwm->chip.ops = &lpc18xx_pwm_ops;
 375        lpc18xx_pwm->chip.base = -1;
 376        lpc18xx_pwm->chip.npwm = 16;
 377        lpc18xx_pwm->chip.of_xlate = of_pwm_xlate_with_flags;
 378        lpc18xx_pwm->chip.of_pwm_n_cells = 3;
 379
 380        /* SCT counter must be in unify (32 bit) mode */
 381        lpc18xx_pwm_writel(lpc18xx_pwm, LPC18XX_PWM_CONFIG,
 382                           LPC18XX_PWM_CONFIG_UNIFY);
 383
 384        /*
 385         * Everytime the timer counter reaches the period value, the related
 386         * event will be triggered and the counter reset to 0.
 387         */
 388        set_bit(LPC18XX_PWM_EVENT_PERIOD, &lpc18xx_pwm->event_map);
 389        lpc18xx_pwm->period_event = LPC18XX_PWM_EVENT_PERIOD;
 390
 391        lpc18xx_pwm_writel(lpc18xx_pwm,
 392                           LPC18XX_PWM_EVSTATEMSK(lpc18xx_pwm->period_event),
 393                           LPC18XX_PWM_EVSTATEMSK_ALL);
 394
 395        val = LPC18XX_PWM_EVCTRL_MATCH(lpc18xx_pwm->period_event) |
 396              LPC18XX_PWM_EVCTRL_COMB_MATCH;
 397        lpc18xx_pwm_writel(lpc18xx_pwm,
 398                           LPC18XX_PWM_EVCTRL(lpc18xx_pwm->period_event), val);
 399
 400        lpc18xx_pwm_writel(lpc18xx_pwm, LPC18XX_PWM_LIMIT,
 401                           BIT(lpc18xx_pwm->period_event));
 402
 403        ret = pwmchip_add(&lpc18xx_pwm->chip);
 404        if (ret < 0) {
 405                dev_err(&pdev->dev, "pwmchip_add failed: %d\n", ret);
 406                goto disable_pwmclk;
 407        }
 408
 409        for (i = 0; i < lpc18xx_pwm->chip.npwm; i++) {
 410                struct lpc18xx_pwm_data *data;
 411
 412                pwm = &lpc18xx_pwm->chip.pwms[i];
 413
 414                data = devm_kzalloc(lpc18xx_pwm->dev, sizeof(*data),
 415                                    GFP_KERNEL);
 416                if (!data) {
 417                        ret = -ENOMEM;
 418                        goto remove_pwmchip;
 419                }
 420
 421                pwm_set_chip_data(pwm, data);
 422        }
 423
 424        platform_set_drvdata(pdev, lpc18xx_pwm);
 425
 426        val = lpc18xx_pwm_readl(lpc18xx_pwm, LPC18XX_PWM_CTRL);
 427        val &= ~LPC18XX_PWM_BIDIR;
 428        val &= ~LPC18XX_PWM_CTRL_HALT;
 429        val &= ~LPC18XX_PWM_PRE_MASK;
 430        val |= LPC18XX_PWM_PRE(0);
 431        lpc18xx_pwm_writel(lpc18xx_pwm, LPC18XX_PWM_CTRL, val);
 432
 433        return 0;
 434
 435remove_pwmchip:
 436        pwmchip_remove(&lpc18xx_pwm->chip);
 437disable_pwmclk:
 438        clk_disable_unprepare(lpc18xx_pwm->pwm_clk);
 439        return ret;
 440}
 441
 442static int lpc18xx_pwm_remove(struct platform_device *pdev)
 443{
 444        struct lpc18xx_pwm_chip *lpc18xx_pwm = platform_get_drvdata(pdev);
 445        u32 val;
 446
 447        val = lpc18xx_pwm_readl(lpc18xx_pwm, LPC18XX_PWM_CTRL);
 448        lpc18xx_pwm_writel(lpc18xx_pwm, LPC18XX_PWM_CTRL,
 449                           val | LPC18XX_PWM_CTRL_HALT);
 450
 451        clk_disable_unprepare(lpc18xx_pwm->pwm_clk);
 452
 453        return pwmchip_remove(&lpc18xx_pwm->chip);
 454}
 455
 456static struct platform_driver lpc18xx_pwm_driver = {
 457        .driver = {
 458                .name = "lpc18xx-sct-pwm",
 459                .of_match_table = lpc18xx_pwm_of_match,
 460        },
 461        .probe = lpc18xx_pwm_probe,
 462        .remove = lpc18xx_pwm_remove,
 463};
 464module_platform_driver(lpc18xx_pwm_driver);
 465
 466MODULE_AUTHOR("Ariel D'Alessandro <ariel@vanguardiasur.com.ar>");
 467MODULE_DESCRIPTION("NXP LPC18xx PWM driver");
 468MODULE_LICENSE("GPL v2");
 469