linux/drivers/pwm/pwm-meson.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
   2/*
   3 * PWM controller driver for Amlogic Meson SoCs.
   4 *
   5 * This PWM is only a set of Gates, Dividers and Counters:
   6 * PWM output is achieved by calculating a clock that permits calculating
   7 * two periods (low and high). The counter then has to be set to switch after
   8 * N cycles for the first half period.
   9 * The hardware has no "polarity" setting. This driver reverses the period
  10 * cycles (the low length is inverted with the high length) for
  11 * PWM_POLARITY_INVERSED. This means that .get_state cannot read the polarity
  12 * from the hardware.
  13 * Setting the duty cycle will disable and re-enable the PWM output.
  14 * Disabling the PWM stops the output immediately (without waiting for the
  15 * current period to complete first).
  16 *
  17 * The public S912 (GXM) datasheet contains some documentation for this PWM
  18 * controller starting on page 543:
  19 * https://dl.khadas.com/Hardware/VIM2/Datasheet/S912_Datasheet_V0.220170314publicversion-Wesion.pdf
  20 * An updated version of this IP block is found in S922X (G12B) SoCs. The
  21 * datasheet contains the description for this IP block revision starting at
  22 * page 1084:
  23 * https://dn.odroid.com/S922X/ODROID-N2/Datasheet/S922X_Public_Datasheet_V0.2.pdf
  24 *
  25 * Copyright (c) 2016 BayLibre, SAS.
  26 * Author: Neil Armstrong <narmstrong@baylibre.com>
  27 * Copyright (C) 2014 Amlogic, Inc.
  28 */
  29
  30#include <linux/bitfield.h>
  31#include <linux/bits.h>
  32#include <linux/clk.h>
  33#include <linux/clk-provider.h>
  34#include <linux/err.h>
  35#include <linux/io.h>
  36#include <linux/kernel.h>
  37#include <linux/math64.h>
  38#include <linux/module.h>
  39#include <linux/of.h>
  40#include <linux/of_device.h>
  41#include <linux/platform_device.h>
  42#include <linux/pwm.h>
  43#include <linux/slab.h>
  44#include <linux/spinlock.h>
  45
  46#define REG_PWM_A               0x0
  47#define REG_PWM_B               0x4
  48#define PWM_LOW_MASK            GENMASK(15, 0)
  49#define PWM_HIGH_MASK           GENMASK(31, 16)
  50
  51#define REG_MISC_AB             0x8
  52#define MISC_B_CLK_EN           BIT(23)
  53#define MISC_A_CLK_EN           BIT(15)
  54#define MISC_CLK_DIV_MASK       0x7f
  55#define MISC_B_CLK_DIV_SHIFT    16
  56#define MISC_A_CLK_DIV_SHIFT    8
  57#define MISC_B_CLK_SEL_SHIFT    6
  58#define MISC_A_CLK_SEL_SHIFT    4
  59#define MISC_CLK_SEL_MASK       0x3
  60#define MISC_B_EN               BIT(1)
  61#define MISC_A_EN               BIT(0)
  62
  63#define MESON_NUM_PWMS          2
  64
  65static struct meson_pwm_channel_data {
  66        u8              reg_offset;
  67        u8              clk_sel_shift;
  68        u8              clk_div_shift;
  69        u32             clk_en_mask;
  70        u32             pwm_en_mask;
  71} meson_pwm_per_channel_data[MESON_NUM_PWMS] = {
  72        {
  73                .reg_offset     = REG_PWM_A,
  74                .clk_sel_shift  = MISC_A_CLK_SEL_SHIFT,
  75                .clk_div_shift  = MISC_A_CLK_DIV_SHIFT,
  76                .clk_en_mask    = MISC_A_CLK_EN,
  77                .pwm_en_mask    = MISC_A_EN,
  78        },
  79        {
  80                .reg_offset     = REG_PWM_B,
  81                .clk_sel_shift  = MISC_B_CLK_SEL_SHIFT,
  82                .clk_div_shift  = MISC_B_CLK_DIV_SHIFT,
  83                .clk_en_mask    = MISC_B_CLK_EN,
  84                .pwm_en_mask    = MISC_B_EN,
  85        }
  86};
  87
  88struct meson_pwm_channel {
  89        unsigned int hi;
  90        unsigned int lo;
  91        u8 pre_div;
  92
  93        struct clk *clk_parent;
  94        struct clk_mux mux;
  95        struct clk *clk;
  96};
  97
  98struct meson_pwm_data {
  99        const char * const *parent_names;
 100        unsigned int num_parents;
 101};
 102
 103struct meson_pwm {
 104        struct pwm_chip chip;
 105        const struct meson_pwm_data *data;
 106        struct meson_pwm_channel channels[MESON_NUM_PWMS];
 107        void __iomem *base;
 108        /*
 109         * Protects register (write) access to the REG_MISC_AB register
 110         * that is shared between the two PWMs.
 111         */
 112        spinlock_t lock;
 113};
 114
 115static inline struct meson_pwm *to_meson_pwm(struct pwm_chip *chip)
 116{
 117        return container_of(chip, struct meson_pwm, chip);
 118}
 119
 120static int meson_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm)
 121{
 122        struct meson_pwm *meson = to_meson_pwm(chip);
 123        struct meson_pwm_channel *channel;
 124        struct device *dev = chip->dev;
 125        int err;
 126
 127        channel = pwm_get_chip_data(pwm);
 128        if (channel)
 129                return 0;
 130
 131        channel = &meson->channels[pwm->hwpwm];
 132
 133        if (channel->clk_parent) {
 134                err = clk_set_parent(channel->clk, channel->clk_parent);
 135                if (err < 0) {
 136                        dev_err(dev, "failed to set parent %s for %s: %d\n",
 137                                __clk_get_name(channel->clk_parent),
 138                                __clk_get_name(channel->clk), err);
 139                        return err;
 140                }
 141        }
 142
 143        err = clk_prepare_enable(channel->clk);
 144        if (err < 0) {
 145                dev_err(dev, "failed to enable clock %s: %d\n",
 146                        __clk_get_name(channel->clk), err);
 147                return err;
 148        }
 149
 150        return pwm_set_chip_data(pwm, channel);
 151}
 152
 153static void meson_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm)
 154{
 155        struct meson_pwm_channel *channel = pwm_get_chip_data(pwm);
 156
 157        if (channel)
 158                clk_disable_unprepare(channel->clk);
 159}
 160
 161static int meson_pwm_calc(struct meson_pwm *meson, struct pwm_device *pwm,
 162                          const struct pwm_state *state)
 163{
 164        struct meson_pwm_channel *channel = pwm_get_chip_data(pwm);
 165        unsigned int duty, period, pre_div, cnt, duty_cnt;
 166        unsigned long fin_freq;
 167
 168        duty = state->duty_cycle;
 169        period = state->period;
 170
 171        if (state->polarity == PWM_POLARITY_INVERSED)
 172                duty = period - duty;
 173
 174        fin_freq = clk_get_rate(channel->clk);
 175        if (fin_freq == 0) {
 176                dev_err(meson->chip.dev, "invalid source clock frequency\n");
 177                return -EINVAL;
 178        }
 179
 180        dev_dbg(meson->chip.dev, "fin_freq: %lu Hz\n", fin_freq);
 181
 182        pre_div = div64_u64(fin_freq * (u64)period, NSEC_PER_SEC * 0xffffLL);
 183        if (pre_div > MISC_CLK_DIV_MASK) {
 184                dev_err(meson->chip.dev, "unable to get period pre_div\n");
 185                return -EINVAL;
 186        }
 187
 188        cnt = div64_u64(fin_freq * (u64)period, NSEC_PER_SEC * (pre_div + 1));
 189        if (cnt > 0xffff) {
 190                dev_err(meson->chip.dev, "unable to get period cnt\n");
 191                return -EINVAL;
 192        }
 193
 194        dev_dbg(meson->chip.dev, "period=%u pre_div=%u cnt=%u\n", period,
 195                pre_div, cnt);
 196
 197        if (duty == period) {
 198                channel->pre_div = pre_div;
 199                channel->hi = cnt;
 200                channel->lo = 0;
 201        } else if (duty == 0) {
 202                channel->pre_div = pre_div;
 203                channel->hi = 0;
 204                channel->lo = cnt;
 205        } else {
 206                /* Then check is we can have the duty with the same pre_div */
 207                duty_cnt = div64_u64(fin_freq * (u64)duty,
 208                                     NSEC_PER_SEC * (pre_div + 1));
 209                if (duty_cnt > 0xffff) {
 210                        dev_err(meson->chip.dev, "unable to get duty cycle\n");
 211                        return -EINVAL;
 212                }
 213
 214                dev_dbg(meson->chip.dev, "duty=%u pre_div=%u duty_cnt=%u\n",
 215                        duty, pre_div, duty_cnt);
 216
 217                channel->pre_div = pre_div;
 218                channel->hi = duty_cnt;
 219                channel->lo = cnt - duty_cnt;
 220        }
 221
 222        return 0;
 223}
 224
 225static void meson_pwm_enable(struct meson_pwm *meson, struct pwm_device *pwm)
 226{
 227        struct meson_pwm_channel *channel = pwm_get_chip_data(pwm);
 228        struct meson_pwm_channel_data *channel_data;
 229        unsigned long flags;
 230        u32 value;
 231
 232        channel_data = &meson_pwm_per_channel_data[pwm->hwpwm];
 233
 234        spin_lock_irqsave(&meson->lock, flags);
 235
 236        value = readl(meson->base + REG_MISC_AB);
 237        value &= ~(MISC_CLK_DIV_MASK << channel_data->clk_div_shift);
 238        value |= channel->pre_div << channel_data->clk_div_shift;
 239        value |= channel_data->clk_en_mask;
 240        writel(value, meson->base + REG_MISC_AB);
 241
 242        value = FIELD_PREP(PWM_HIGH_MASK, channel->hi) |
 243                FIELD_PREP(PWM_LOW_MASK, channel->lo);
 244        writel(value, meson->base + channel_data->reg_offset);
 245
 246        value = readl(meson->base + REG_MISC_AB);
 247        value |= channel_data->pwm_en_mask;
 248        writel(value, meson->base + REG_MISC_AB);
 249
 250        spin_unlock_irqrestore(&meson->lock, flags);
 251}
 252
 253static void meson_pwm_disable(struct meson_pwm *meson, struct pwm_device *pwm)
 254{
 255        unsigned long flags;
 256        u32 value;
 257
 258        spin_lock_irqsave(&meson->lock, flags);
 259
 260        value = readl(meson->base + REG_MISC_AB);
 261        value &= ~meson_pwm_per_channel_data[pwm->hwpwm].pwm_en_mask;
 262        writel(value, meson->base + REG_MISC_AB);
 263
 264        spin_unlock_irqrestore(&meson->lock, flags);
 265}
 266
 267static int meson_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
 268                           const struct pwm_state *state)
 269{
 270        struct meson_pwm_channel *channel = pwm_get_chip_data(pwm);
 271        struct meson_pwm *meson = to_meson_pwm(chip);
 272        int err = 0;
 273
 274        if (!state)
 275                return -EINVAL;
 276
 277        if (!state->enabled) {
 278                if (state->polarity == PWM_POLARITY_INVERSED) {
 279                        /*
 280                         * This IP block revision doesn't have an "always high"
 281                         * setting which we can use for "inverted disabled".
 282                         * Instead we achieve this using the same settings
 283                         * that we use a pre_div of 0 (to get the shortest
 284                         * possible duration for one "count") and
 285                         * "period == duty_cycle". This results in a signal
 286                         * which is LOW for one "count", while being HIGH for
 287                         * the rest of the (so the signal is HIGH for slightly
 288                         * less than 100% of the period, but this is the best
 289                         * we can achieve).
 290                         */
 291                        channel->pre_div = 0;
 292                        channel->hi = ~0;
 293                        channel->lo = 0;
 294
 295                        meson_pwm_enable(meson, pwm);
 296                } else {
 297                        meson_pwm_disable(meson, pwm);
 298                }
 299        } else {
 300                err = meson_pwm_calc(meson, pwm, state);
 301                if (err < 0)
 302                        return err;
 303
 304                meson_pwm_enable(meson, pwm);
 305        }
 306
 307        return 0;
 308}
 309
 310static unsigned int meson_pwm_cnt_to_ns(struct pwm_chip *chip,
 311                                        struct pwm_device *pwm, u32 cnt)
 312{
 313        struct meson_pwm *meson = to_meson_pwm(chip);
 314        struct meson_pwm_channel *channel;
 315        unsigned long fin_freq;
 316        u32 fin_ns;
 317
 318        /* to_meson_pwm() can only be used after .get_state() is called */
 319        channel = &meson->channels[pwm->hwpwm];
 320
 321        fin_freq = clk_get_rate(channel->clk);
 322        if (fin_freq == 0)
 323                return 0;
 324
 325        fin_ns = div_u64(NSEC_PER_SEC, fin_freq);
 326
 327        return cnt * fin_ns * (channel->pre_div + 1);
 328}
 329
 330static void meson_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
 331                                struct pwm_state *state)
 332{
 333        struct meson_pwm *meson = to_meson_pwm(chip);
 334        struct meson_pwm_channel_data *channel_data;
 335        struct meson_pwm_channel *channel;
 336        u32 value, tmp;
 337
 338        if (!state)
 339                return;
 340
 341        channel = &meson->channels[pwm->hwpwm];
 342        channel_data = &meson_pwm_per_channel_data[pwm->hwpwm];
 343
 344        value = readl(meson->base + REG_MISC_AB);
 345
 346        tmp = channel_data->pwm_en_mask | channel_data->clk_en_mask;
 347        state->enabled = (value & tmp) == tmp;
 348
 349        tmp = value >> channel_data->clk_div_shift;
 350        channel->pre_div = FIELD_GET(MISC_CLK_DIV_MASK, tmp);
 351
 352        value = readl(meson->base + channel_data->reg_offset);
 353
 354        channel->lo = FIELD_GET(PWM_LOW_MASK, value);
 355        channel->hi = FIELD_GET(PWM_HIGH_MASK, value);
 356
 357        if (channel->lo == 0) {
 358                state->period = meson_pwm_cnt_to_ns(chip, pwm, channel->hi);
 359                state->duty_cycle = state->period;
 360        } else if (channel->lo >= channel->hi) {
 361                state->period = meson_pwm_cnt_to_ns(chip, pwm,
 362                                                    channel->lo + channel->hi);
 363                state->duty_cycle = meson_pwm_cnt_to_ns(chip, pwm,
 364                                                        channel->hi);
 365        } else {
 366                state->period = 0;
 367                state->duty_cycle = 0;
 368        }
 369}
 370
 371static const struct pwm_ops meson_pwm_ops = {
 372        .request = meson_pwm_request,
 373        .free = meson_pwm_free,
 374        .apply = meson_pwm_apply,
 375        .get_state = meson_pwm_get_state,
 376        .owner = THIS_MODULE,
 377};
 378
 379static const char * const pwm_meson8b_parent_names[] = {
 380        "xtal", "vid_pll", "fclk_div4", "fclk_div3"
 381};
 382
 383static const struct meson_pwm_data pwm_meson8b_data = {
 384        .parent_names = pwm_meson8b_parent_names,
 385        .num_parents = ARRAY_SIZE(pwm_meson8b_parent_names),
 386};
 387
 388static const char * const pwm_gxbb_parent_names[] = {
 389        "xtal", "hdmi_pll", "fclk_div4", "fclk_div3"
 390};
 391
 392static const struct meson_pwm_data pwm_gxbb_data = {
 393        .parent_names = pwm_gxbb_parent_names,
 394        .num_parents = ARRAY_SIZE(pwm_gxbb_parent_names),
 395};
 396
 397/*
 398 * Only the 2 first inputs of the GXBB AO PWMs are valid
 399 * The last 2 are grounded
 400 */
 401static const char * const pwm_gxbb_ao_parent_names[] = {
 402        "xtal", "clk81"
 403};
 404
 405static const struct meson_pwm_data pwm_gxbb_ao_data = {
 406        .parent_names = pwm_gxbb_ao_parent_names,
 407        .num_parents = ARRAY_SIZE(pwm_gxbb_ao_parent_names),
 408};
 409
 410static const char * const pwm_axg_ee_parent_names[] = {
 411        "xtal", "fclk_div5", "fclk_div4", "fclk_div3"
 412};
 413
 414static const struct meson_pwm_data pwm_axg_ee_data = {
 415        .parent_names = pwm_axg_ee_parent_names,
 416        .num_parents = ARRAY_SIZE(pwm_axg_ee_parent_names),
 417};
 418
 419static const char * const pwm_axg_ao_parent_names[] = {
 420        "aoclk81", "xtal", "fclk_div4", "fclk_div5"
 421};
 422
 423static const struct meson_pwm_data pwm_axg_ao_data = {
 424        .parent_names = pwm_axg_ao_parent_names,
 425        .num_parents = ARRAY_SIZE(pwm_axg_ao_parent_names),
 426};
 427
 428static const char * const pwm_g12a_ao_ab_parent_names[] = {
 429        "xtal", "aoclk81", "fclk_div4", "fclk_div5"
 430};
 431
 432static const struct meson_pwm_data pwm_g12a_ao_ab_data = {
 433        .parent_names = pwm_g12a_ao_ab_parent_names,
 434        .num_parents = ARRAY_SIZE(pwm_g12a_ao_ab_parent_names),
 435};
 436
 437static const char * const pwm_g12a_ao_cd_parent_names[] = {
 438        "xtal", "aoclk81",
 439};
 440
 441static const struct meson_pwm_data pwm_g12a_ao_cd_data = {
 442        .parent_names = pwm_g12a_ao_cd_parent_names,
 443        .num_parents = ARRAY_SIZE(pwm_g12a_ao_cd_parent_names),
 444};
 445
 446static const char * const pwm_g12a_ee_parent_names[] = {
 447        "xtal", "hdmi_pll", "fclk_div4", "fclk_div3"
 448};
 449
 450static const struct meson_pwm_data pwm_g12a_ee_data = {
 451        .parent_names = pwm_g12a_ee_parent_names,
 452        .num_parents = ARRAY_SIZE(pwm_g12a_ee_parent_names),
 453};
 454
 455static const struct of_device_id meson_pwm_matches[] = {
 456        {
 457                .compatible = "amlogic,meson8b-pwm",
 458                .data = &pwm_meson8b_data
 459        },
 460        {
 461                .compatible = "amlogic,meson-gxbb-pwm",
 462                .data = &pwm_gxbb_data
 463        },
 464        {
 465                .compatible = "amlogic,meson-gxbb-ao-pwm",
 466                .data = &pwm_gxbb_ao_data
 467        },
 468        {
 469                .compatible = "amlogic,meson-axg-ee-pwm",
 470                .data = &pwm_axg_ee_data
 471        },
 472        {
 473                .compatible = "amlogic,meson-axg-ao-pwm",
 474                .data = &pwm_axg_ao_data
 475        },
 476        {
 477                .compatible = "amlogic,meson-g12a-ee-pwm",
 478                .data = &pwm_g12a_ee_data
 479        },
 480        {
 481                .compatible = "amlogic,meson-g12a-ao-pwm-ab",
 482                .data = &pwm_g12a_ao_ab_data
 483        },
 484        {
 485                .compatible = "amlogic,meson-g12a-ao-pwm-cd",
 486                .data = &pwm_g12a_ao_cd_data
 487        },
 488        {},
 489};
 490MODULE_DEVICE_TABLE(of, meson_pwm_matches);
 491
 492static int meson_pwm_init_channels(struct meson_pwm *meson)
 493{
 494        struct device *dev = meson->chip.dev;
 495        struct clk_init_data init;
 496        unsigned int i;
 497        char name[255];
 498        int err;
 499
 500        for (i = 0; i < meson->chip.npwm; i++) {
 501                struct meson_pwm_channel *channel = &meson->channels[i];
 502
 503                snprintf(name, sizeof(name), "%s#mux%u", dev_name(dev), i);
 504
 505                init.name = name;
 506                init.ops = &clk_mux_ops;
 507                init.flags = 0;
 508                init.parent_names = meson->data->parent_names;
 509                init.num_parents = meson->data->num_parents;
 510
 511                channel->mux.reg = meson->base + REG_MISC_AB;
 512                channel->mux.shift =
 513                                meson_pwm_per_channel_data[i].clk_sel_shift;
 514                channel->mux.mask = MISC_CLK_SEL_MASK;
 515                channel->mux.flags = 0;
 516                channel->mux.lock = &meson->lock;
 517                channel->mux.table = NULL;
 518                channel->mux.hw.init = &init;
 519
 520                channel->clk = devm_clk_register(dev, &channel->mux.hw);
 521                if (IS_ERR(channel->clk)) {
 522                        err = PTR_ERR(channel->clk);
 523                        dev_err(dev, "failed to register %s: %d\n", name, err);
 524                        return err;
 525                }
 526
 527                snprintf(name, sizeof(name), "clkin%u", i);
 528
 529                channel->clk_parent = devm_clk_get_optional(dev, name);
 530                if (IS_ERR(channel->clk_parent))
 531                        return PTR_ERR(channel->clk_parent);
 532        }
 533
 534        return 0;
 535}
 536
 537static int meson_pwm_probe(struct platform_device *pdev)
 538{
 539        struct meson_pwm *meson;
 540        int err;
 541
 542        meson = devm_kzalloc(&pdev->dev, sizeof(*meson), GFP_KERNEL);
 543        if (!meson)
 544                return -ENOMEM;
 545
 546        meson->base = devm_platform_ioremap_resource(pdev, 0);
 547        if (IS_ERR(meson->base))
 548                return PTR_ERR(meson->base);
 549
 550        spin_lock_init(&meson->lock);
 551        meson->chip.dev = &pdev->dev;
 552        meson->chip.ops = &meson_pwm_ops;
 553        meson->chip.base = -1;
 554        meson->chip.npwm = MESON_NUM_PWMS;
 555        meson->chip.of_xlate = of_pwm_xlate_with_flags;
 556        meson->chip.of_pwm_n_cells = 3;
 557
 558        meson->data = of_device_get_match_data(&pdev->dev);
 559
 560        err = meson_pwm_init_channels(meson);
 561        if (err < 0)
 562                return err;
 563
 564        err = pwmchip_add(&meson->chip);
 565        if (err < 0) {
 566                dev_err(&pdev->dev, "failed to register PWM chip: %d\n", err);
 567                return err;
 568        }
 569
 570        platform_set_drvdata(pdev, meson);
 571
 572        return 0;
 573}
 574
 575static int meson_pwm_remove(struct platform_device *pdev)
 576{
 577        struct meson_pwm *meson = platform_get_drvdata(pdev);
 578
 579        return pwmchip_remove(&meson->chip);
 580}
 581
 582static struct platform_driver meson_pwm_driver = {
 583        .driver = {
 584                .name = "meson-pwm",
 585                .of_match_table = meson_pwm_matches,
 586        },
 587        .probe = meson_pwm_probe,
 588        .remove = meson_pwm_remove,
 589};
 590module_platform_driver(meson_pwm_driver);
 591
 592MODULE_DESCRIPTION("Amlogic Meson PWM Generator driver");
 593MODULE_AUTHOR("Neil Armstrong <narmstrong@baylibre.com>");
 594MODULE_LICENSE("Dual BSD/GPL");
 595