linux/drivers/pwm/pwm-bcm-kona.c
<<
>>
Prefs
   1/*
   2 * Copyright (C) 2014 Broadcom Corporation
   3 *
   4 * This program is free software; you can redistribute it and/or
   5 * modify it under the terms of the GNU General Public License as
   6 * published by the Free Software Foundation version 2.
   7 *
   8 * This program is distributed "as is" WITHOUT ANY WARRANTY of any
   9 * kind, whether express or implied; without even the implied warranty
  10 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  11 * GNU General Public License for more details.
  12 */
  13
  14#include <linux/clk.h>
  15#include <linux/delay.h>
  16#include <linux/err.h>
  17#include <linux/io.h>
  18#include <linux/ioport.h>
  19#include <linux/math64.h>
  20#include <linux/module.h>
  21#include <linux/of.h>
  22#include <linux/platform_device.h>
  23#include <linux/pwm.h>
  24#include <linux/slab.h>
  25#include <linux/types.h>
  26
  27/*
  28 * The Kona PWM has some unusual characteristics.  Here are the main points.
  29 *
  30 * 1) There is no disable bit and the hardware docs advise programming a zero
  31 *    duty to achieve output equivalent to that of a normal disable operation.
  32 *
  33 * 2) Changes to prescale, duty, period, and polarity do not take effect until
  34 *    a subsequent rising edge of the trigger bit.
  35 *
  36 * 3) If the smooth bit and trigger bit are both low, the output is a constant
  37 *    high signal.  Otherwise, the earlier waveform continues to be output.
  38 *
  39 * 4) If the smooth bit is set on the rising edge of the trigger bit, output
  40 *    will transition to the new settings on a period boundary (which could be
  41 *    seconds away).  If the smooth bit is clear, new settings will be applied
  42 *    as soon as possible (the hardware always has a 400ns delay).
  43 *
  44 * 5) When the external clock that feeds the PWM is disabled, output is pegged
  45 *    high or low depending on its state at that exact instant.
  46 */
  47
  48#define PWM_CONTROL_OFFSET                      0x00000000
  49#define PWM_CONTROL_SMOOTH_SHIFT(chan)          (24 + (chan))
  50#define PWM_CONTROL_TYPE_SHIFT(chan)            (16 + (chan))
  51#define PWM_CONTROL_POLARITY_SHIFT(chan)        (8 + (chan))
  52#define PWM_CONTROL_TRIGGER_SHIFT(chan)         (chan)
  53
  54#define PRESCALE_OFFSET                         0x00000004
  55#define PRESCALE_SHIFT(chan)                    ((chan) << 2)
  56#define PRESCALE_MASK(chan)                     (0x7 << PRESCALE_SHIFT(chan))
  57#define PRESCALE_MIN                            0x00000000
  58#define PRESCALE_MAX                            0x00000007
  59
  60#define PERIOD_COUNT_OFFSET(chan)               (0x00000008 + ((chan) << 3))
  61#define PERIOD_COUNT_MIN                        0x00000002
  62#define PERIOD_COUNT_MAX                        0x00ffffff
  63
  64#define DUTY_CYCLE_HIGH_OFFSET(chan)            (0x0000000c + ((chan) << 3))
  65#define DUTY_CYCLE_HIGH_MIN                     0x00000000
  66#define DUTY_CYCLE_HIGH_MAX                     0x00ffffff
  67
  68struct kona_pwmc {
  69        struct pwm_chip chip;
  70        void __iomem *base;
  71        struct clk *clk;
  72};
  73
  74static inline struct kona_pwmc *to_kona_pwmc(struct pwm_chip *_chip)
  75{
  76        return container_of(_chip, struct kona_pwmc, chip);
  77}
  78
  79/*
  80 * Clear trigger bit but set smooth bit to maintain old output.
  81 */
  82static void kona_pwmc_prepare_for_settings(struct kona_pwmc *kp,
  83        unsigned int chan)
  84{
  85        unsigned int value = readl(kp->base + PWM_CONTROL_OFFSET);
  86
  87        value |= 1 << PWM_CONTROL_SMOOTH_SHIFT(chan);
  88        value &= ~(1 << PWM_CONTROL_TRIGGER_SHIFT(chan));
  89        writel(value, kp->base + PWM_CONTROL_OFFSET);
  90
  91        /*
  92         * There must be a min 400ns delay between clearing trigger and setting
  93         * it. Failing to do this may result in no PWM signal.
  94         */
  95        ndelay(400);
  96}
  97
  98static void kona_pwmc_apply_settings(struct kona_pwmc *kp, unsigned int chan)
  99{
 100        unsigned int value = readl(kp->base + PWM_CONTROL_OFFSET);
 101
 102        /* Set trigger bit and clear smooth bit to apply new settings */
 103        value &= ~(1 << PWM_CONTROL_SMOOTH_SHIFT(chan));
 104        value |= 1 << PWM_CONTROL_TRIGGER_SHIFT(chan);
 105        writel(value, kp->base + PWM_CONTROL_OFFSET);
 106
 107        /* Trigger bit must be held high for at least 400 ns. */
 108        ndelay(400);
 109}
 110
 111static int kona_pwmc_config(struct pwm_chip *chip, struct pwm_device *pwm,
 112                            int duty_ns, int period_ns)
 113{
 114        struct kona_pwmc *kp = to_kona_pwmc(chip);
 115        u64 val, div, rate;
 116        unsigned long prescale = PRESCALE_MIN, pc, dc;
 117        unsigned int value, chan = pwm->hwpwm;
 118
 119        /*
 120         * Find period count, duty count and prescale to suit duty_ns and
 121         * period_ns. This is done according to formulas described below:
 122         *
 123         * period_ns = 10^9 * (PRESCALE + 1) * PC / PWM_CLK_RATE
 124         * duty_ns = 10^9 * (PRESCALE + 1) * DC / PWM_CLK_RATE
 125         *
 126         * PC = (PWM_CLK_RATE * period_ns) / (10^9 * (PRESCALE + 1))
 127         * DC = (PWM_CLK_RATE * duty_ns) / (10^9 * (PRESCALE + 1))
 128         */
 129
 130        rate = clk_get_rate(kp->clk);
 131
 132        while (1) {
 133                div = 1000000000;
 134                div *= 1 + prescale;
 135                val = rate * period_ns;
 136                pc = div64_u64(val, div);
 137                val = rate * duty_ns;
 138                dc = div64_u64(val, div);
 139
 140                /* If duty_ns or period_ns are not achievable then return */
 141                if (pc < PERIOD_COUNT_MIN || dc < DUTY_CYCLE_HIGH_MIN)
 142                        return -EINVAL;
 143
 144                /* If pc and dc are in bounds, the calculation is done */
 145                if (pc <= PERIOD_COUNT_MAX && dc <= DUTY_CYCLE_HIGH_MAX)
 146                        break;
 147
 148                /* Otherwise, increase prescale and recalculate pc and dc */
 149                if (++prescale > PRESCALE_MAX)
 150                        return -EINVAL;
 151        }
 152
 153        /*
 154         * Don't apply settings if disabled. The period and duty cycle are
 155         * always calculated above to ensure the new values are
 156         * validated immediately instead of on enable.
 157         */
 158        if (pwm_is_enabled(pwm)) {
 159                kona_pwmc_prepare_for_settings(kp, chan);
 160
 161                value = readl(kp->base + PRESCALE_OFFSET);
 162                value &= ~PRESCALE_MASK(chan);
 163                value |= prescale << PRESCALE_SHIFT(chan);
 164                writel(value, kp->base + PRESCALE_OFFSET);
 165
 166                writel(pc, kp->base + PERIOD_COUNT_OFFSET(chan));
 167
 168                writel(dc, kp->base + DUTY_CYCLE_HIGH_OFFSET(chan));
 169
 170                kona_pwmc_apply_settings(kp, chan);
 171        }
 172
 173        return 0;
 174}
 175
 176static int kona_pwmc_set_polarity(struct pwm_chip *chip, struct pwm_device *pwm,
 177                                  enum pwm_polarity polarity)
 178{
 179        struct kona_pwmc *kp = to_kona_pwmc(chip);
 180        unsigned int chan = pwm->hwpwm;
 181        unsigned int value;
 182        int ret;
 183
 184        ret = clk_prepare_enable(kp->clk);
 185        if (ret < 0) {
 186                dev_err(chip->dev, "failed to enable clock: %d\n", ret);
 187                return ret;
 188        }
 189
 190        kona_pwmc_prepare_for_settings(kp, chan);
 191
 192        value = readl(kp->base + PWM_CONTROL_OFFSET);
 193
 194        if (polarity == PWM_POLARITY_NORMAL)
 195                value |= 1 << PWM_CONTROL_POLARITY_SHIFT(chan);
 196        else
 197                value &= ~(1 << PWM_CONTROL_POLARITY_SHIFT(chan));
 198
 199        writel(value, kp->base + PWM_CONTROL_OFFSET);
 200
 201        kona_pwmc_apply_settings(kp, chan);
 202
 203        clk_disable_unprepare(kp->clk);
 204
 205        return 0;
 206}
 207
 208static int kona_pwmc_enable(struct pwm_chip *chip, struct pwm_device *pwm)
 209{
 210        struct kona_pwmc *kp = to_kona_pwmc(chip);
 211        int ret;
 212
 213        ret = clk_prepare_enable(kp->clk);
 214        if (ret < 0) {
 215                dev_err(chip->dev, "failed to enable clock: %d\n", ret);
 216                return ret;
 217        }
 218
 219        ret = kona_pwmc_config(chip, pwm, pwm_get_duty_cycle(pwm),
 220                               pwm_get_period(pwm));
 221        if (ret < 0) {
 222                clk_disable_unprepare(kp->clk);
 223                return ret;
 224        }
 225
 226        return 0;
 227}
 228
 229static void kona_pwmc_disable(struct pwm_chip *chip, struct pwm_device *pwm)
 230{
 231        struct kona_pwmc *kp = to_kona_pwmc(chip);
 232        unsigned int chan = pwm->hwpwm;
 233        unsigned int value;
 234
 235        kona_pwmc_prepare_for_settings(kp, chan);
 236
 237        /* Simulate a disable by configuring for zero duty */
 238        writel(0, kp->base + DUTY_CYCLE_HIGH_OFFSET(chan));
 239        writel(0, kp->base + PERIOD_COUNT_OFFSET(chan));
 240
 241        /* Set prescale to 0 for this channel */
 242        value = readl(kp->base + PRESCALE_OFFSET);
 243        value &= ~PRESCALE_MASK(chan);
 244        writel(value, kp->base + PRESCALE_OFFSET);
 245
 246        kona_pwmc_apply_settings(kp, chan);
 247
 248        clk_disable_unprepare(kp->clk);
 249}
 250
 251static const struct pwm_ops kona_pwm_ops = {
 252        .config = kona_pwmc_config,
 253        .set_polarity = kona_pwmc_set_polarity,
 254        .enable = kona_pwmc_enable,
 255        .disable = kona_pwmc_disable,
 256        .owner = THIS_MODULE,
 257};
 258
 259static int kona_pwmc_probe(struct platform_device *pdev)
 260{
 261        struct kona_pwmc *kp;
 262        struct resource *res;
 263        unsigned int chan;
 264        unsigned int value = 0;
 265        int ret = 0;
 266
 267        kp = devm_kzalloc(&pdev->dev, sizeof(*kp), GFP_KERNEL);
 268        if (kp == NULL)
 269                return -ENOMEM;
 270
 271        platform_set_drvdata(pdev, kp);
 272
 273        kp->chip.dev = &pdev->dev;
 274        kp->chip.ops = &kona_pwm_ops;
 275        kp->chip.base = -1;
 276        kp->chip.npwm = 6;
 277        kp->chip.of_xlate = of_pwm_xlate_with_flags;
 278        kp->chip.of_pwm_n_cells = 3;
 279
 280        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 281        kp->base = devm_ioremap_resource(&pdev->dev, res);
 282        if (IS_ERR(kp->base))
 283                return PTR_ERR(kp->base);
 284
 285        kp->clk = devm_clk_get(&pdev->dev, NULL);
 286        if (IS_ERR(kp->clk)) {
 287                dev_err(&pdev->dev, "failed to get clock: %ld\n",
 288                        PTR_ERR(kp->clk));
 289                return PTR_ERR(kp->clk);
 290        }
 291
 292        ret = clk_prepare_enable(kp->clk);
 293        if (ret < 0) {
 294                dev_err(&pdev->dev, "failed to enable clock: %d\n", ret);
 295                return ret;
 296        }
 297
 298        /* Set push/pull for all channels */
 299        for (chan = 0; chan < kp->chip.npwm; chan++)
 300                value |= (1 << PWM_CONTROL_TYPE_SHIFT(chan));
 301
 302        writel(value, kp->base + PWM_CONTROL_OFFSET);
 303
 304        clk_disable_unprepare(kp->clk);
 305
 306        ret = pwmchip_add_with_polarity(&kp->chip, PWM_POLARITY_INVERSED);
 307        if (ret < 0)
 308                dev_err(&pdev->dev, "failed to add PWM chip: %d\n", ret);
 309
 310        return ret;
 311}
 312
 313static int kona_pwmc_remove(struct platform_device *pdev)
 314{
 315        struct kona_pwmc *kp = platform_get_drvdata(pdev);
 316        unsigned int chan;
 317
 318        for (chan = 0; chan < kp->chip.npwm; chan++)
 319                if (pwm_is_enabled(&kp->chip.pwms[chan]))
 320                        clk_disable_unprepare(kp->clk);
 321
 322        return pwmchip_remove(&kp->chip);
 323}
 324
 325static const struct of_device_id bcm_kona_pwmc_dt[] = {
 326        { .compatible = "brcm,kona-pwm" },
 327        { },
 328};
 329MODULE_DEVICE_TABLE(of, bcm_kona_pwmc_dt);
 330
 331static struct platform_driver kona_pwmc_driver = {
 332        .driver = {
 333                .name = "bcm-kona-pwm",
 334                .of_match_table = bcm_kona_pwmc_dt,
 335        },
 336        .probe = kona_pwmc_probe,
 337        .remove = kona_pwmc_remove,
 338};
 339module_platform_driver(kona_pwmc_driver);
 340
 341MODULE_AUTHOR("Broadcom Corporation <bcm-kernel-feedback-list@broadcom.com>");
 342MODULE_AUTHOR("Tim Kryger <tkryger@broadcom.com>");
 343MODULE_DESCRIPTION("Broadcom Kona PWM driver");
 344MODULE_LICENSE("GPL v2");
 345