linux/drivers/pwm/pwm-atmel.c
<<
>>
Prefs
   1/*
   2 * Driver for Atmel Pulse Width Modulation Controller
   3 *
   4 * Copyright (C) 2013 Atmel Corporation
   5 *               Bo Shen <voice.shen@atmel.com>
   6 *
   7 * Licensed under GPLv2.
   8 */
   9
  10#include <linux/clk.h>
  11#include <linux/err.h>
  12#include <linux/io.h>
  13#include <linux/module.h>
  14#include <linux/of.h>
  15#include <linux/of_device.h>
  16#include <linux/platform_device.h>
  17#include <linux/pwm.h>
  18#include <linux/slab.h>
  19
  20/* The following is global registers for PWM controller */
  21#define PWM_ENA                 0x04
  22#define PWM_DIS                 0x08
  23#define PWM_SR                  0x0C
  24/* Bit field in SR */
  25#define PWM_SR_ALL_CH_ON        0x0F
  26
  27/* The following register is PWM channel related registers */
  28#define PWM_CH_REG_OFFSET       0x200
  29#define PWM_CH_REG_SIZE         0x20
  30
  31#define PWM_CMR                 0x0
  32/* Bit field in CMR */
  33#define PWM_CMR_CPOL            (1 << 9)
  34#define PWM_CMR_UPD_CDTY        (1 << 10)
  35#define PWM_CMR_CPRE_MSK        0xF
  36
  37/* The following registers for PWM v1 */
  38#define PWMV1_CDTY              0x04
  39#define PWMV1_CPRD              0x08
  40#define PWMV1_CUPD              0x10
  41
  42/* The following registers for PWM v2 */
  43#define PWMV2_CDTY              0x04
  44#define PWMV2_CDTYUPD           0x08
  45#define PWMV2_CPRD              0x0C
  46#define PWMV2_CPRDUPD           0x10
  47
  48/*
  49 * Max value for duty and period
  50 *
  51 * Although the duty and period register is 32 bit,
  52 * however only the LSB 16 bits are significant.
  53 */
  54#define PWM_MAX_DTY             0xFFFF
  55#define PWM_MAX_PRD             0xFFFF
  56#define PRD_MAX_PRES            10
  57
  58struct atmel_pwm_chip {
  59        struct pwm_chip chip;
  60        struct clk *clk;
  61        void __iomem *base;
  62
  63        void (*config)(struct pwm_chip *chip, struct pwm_device *pwm,
  64                       unsigned long dty, unsigned long prd);
  65};
  66
  67static inline struct atmel_pwm_chip *to_atmel_pwm_chip(struct pwm_chip *chip)
  68{
  69        return container_of(chip, struct atmel_pwm_chip, chip);
  70}
  71
  72static inline u32 atmel_pwm_readl(struct atmel_pwm_chip *chip,
  73                                  unsigned long offset)
  74{
  75        return readl_relaxed(chip->base + offset);
  76}
  77
  78static inline void atmel_pwm_writel(struct atmel_pwm_chip *chip,
  79                                    unsigned long offset, unsigned long val)
  80{
  81        writel_relaxed(val, chip->base + offset);
  82}
  83
  84static inline u32 atmel_pwm_ch_readl(struct atmel_pwm_chip *chip,
  85                                     unsigned int ch, unsigned long offset)
  86{
  87        unsigned long base = PWM_CH_REG_OFFSET + ch * PWM_CH_REG_SIZE;
  88
  89        return readl_relaxed(chip->base + base + offset);
  90}
  91
  92static inline void atmel_pwm_ch_writel(struct atmel_pwm_chip *chip,
  93                                       unsigned int ch, unsigned long offset,
  94                                       unsigned long val)
  95{
  96        unsigned long base = PWM_CH_REG_OFFSET + ch * PWM_CH_REG_SIZE;
  97
  98        writel_relaxed(val, chip->base + base + offset);
  99}
 100
 101static int atmel_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
 102                            int duty_ns, int period_ns)
 103{
 104        struct atmel_pwm_chip *atmel_pwm = to_atmel_pwm_chip(chip);
 105        unsigned long prd, dty;
 106        unsigned long long div;
 107        unsigned int pres = 0;
 108        u32 val;
 109        int ret;
 110
 111        if (test_bit(PWMF_ENABLED, &pwm->flags) && (period_ns != pwm->period)) {
 112                dev_err(chip->dev, "cannot change PWM period while enabled\n");
 113                return -EBUSY;
 114        }
 115
 116        /* Calculate the period cycles and prescale value */
 117        div = (unsigned long long)clk_get_rate(atmel_pwm->clk) * period_ns;
 118        do_div(div, NSEC_PER_SEC);
 119
 120        while (div > PWM_MAX_PRD) {
 121                div >>= 1;
 122                pres++;
 123        }
 124
 125        if (pres > PRD_MAX_PRES) {
 126                dev_err(chip->dev, "pres exceeds the maximum value\n");
 127                return -EINVAL;
 128        }
 129
 130        /* Calculate the duty cycles */
 131        prd = div;
 132        div *= duty_ns;
 133        do_div(div, period_ns);
 134        dty = prd - div;
 135
 136        ret = clk_enable(atmel_pwm->clk);
 137        if (ret) {
 138                dev_err(chip->dev, "failed to enable PWM clock\n");
 139                return ret;
 140        }
 141
 142        /* It is necessary to preserve CPOL, inside CMR */
 143        val = atmel_pwm_ch_readl(atmel_pwm, pwm->hwpwm, PWM_CMR);
 144        val = (val & ~PWM_CMR_CPRE_MSK) | (pres & PWM_CMR_CPRE_MSK);
 145        atmel_pwm_ch_writel(atmel_pwm, pwm->hwpwm, PWM_CMR, val);
 146        atmel_pwm->config(chip, pwm, dty, prd);
 147
 148        clk_disable(atmel_pwm->clk);
 149        return ret;
 150}
 151
 152static void atmel_pwm_config_v1(struct pwm_chip *chip, struct pwm_device *pwm,
 153                                unsigned long dty, unsigned long prd)
 154{
 155        struct atmel_pwm_chip *atmel_pwm = to_atmel_pwm_chip(chip);
 156        unsigned int val;
 157
 158        if (test_bit(PWMF_ENABLED, &pwm->flags)) {
 159                /*
 160                 * If the PWM channel is enabled, using the update register,
 161                 * it needs to set bit 10 of CMR to 0
 162                 */
 163                atmel_pwm_ch_writel(atmel_pwm, pwm->hwpwm, PWMV1_CUPD, dty);
 164
 165                val = atmel_pwm_ch_readl(atmel_pwm, pwm->hwpwm, PWM_CMR);
 166                val &= ~PWM_CMR_UPD_CDTY;
 167                atmel_pwm_ch_writel(atmel_pwm, pwm->hwpwm, PWM_CMR, val);
 168        } else {
 169                /*
 170                 * If the PWM channel is disabled, write value to duty and
 171                 * period registers directly.
 172                 */
 173                atmel_pwm_ch_writel(atmel_pwm, pwm->hwpwm, PWMV1_CDTY, dty);
 174                atmel_pwm_ch_writel(atmel_pwm, pwm->hwpwm, PWMV1_CPRD, prd);
 175        }
 176}
 177
 178static void atmel_pwm_config_v2(struct pwm_chip *chip, struct pwm_device *pwm,
 179                                unsigned long dty, unsigned long prd)
 180{
 181        struct atmel_pwm_chip *atmel_pwm = to_atmel_pwm_chip(chip);
 182
 183        if (test_bit(PWMF_ENABLED, &pwm->flags)) {
 184                /*
 185                 * If the PWM channel is enabled, using the duty update register
 186                 * to update the value.
 187                 */
 188                atmel_pwm_ch_writel(atmel_pwm, pwm->hwpwm, PWMV2_CDTYUPD, dty);
 189        } else {
 190                /*
 191                 * If the PWM channel is disabled, write value to duty and
 192                 * period registers directly.
 193                 */
 194                atmel_pwm_ch_writel(atmel_pwm, pwm->hwpwm, PWMV2_CDTY, dty);
 195                atmel_pwm_ch_writel(atmel_pwm, pwm->hwpwm, PWMV2_CPRD, prd);
 196        }
 197}
 198
 199static int atmel_pwm_set_polarity(struct pwm_chip *chip, struct pwm_device *pwm,
 200                                  enum pwm_polarity polarity)
 201{
 202        struct atmel_pwm_chip *atmel_pwm = to_atmel_pwm_chip(chip);
 203        u32 val;
 204        int ret;
 205
 206        val = atmel_pwm_ch_readl(atmel_pwm, pwm->hwpwm, PWM_CMR);
 207
 208        if (polarity == PWM_POLARITY_NORMAL)
 209                val &= ~PWM_CMR_CPOL;
 210        else
 211                val |= PWM_CMR_CPOL;
 212
 213        ret = clk_enable(atmel_pwm->clk);
 214        if (ret) {
 215                dev_err(chip->dev, "failed to enable PWM clock\n");
 216                return ret;
 217        }
 218
 219        atmel_pwm_ch_writel(atmel_pwm, pwm->hwpwm, PWM_CMR, val);
 220
 221        clk_disable(atmel_pwm->clk);
 222
 223        return 0;
 224}
 225
 226static int atmel_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
 227{
 228        struct atmel_pwm_chip *atmel_pwm = to_atmel_pwm_chip(chip);
 229        int ret;
 230
 231        ret = clk_enable(atmel_pwm->clk);
 232        if (ret) {
 233                dev_err(chip->dev, "failed to enable PWM clock\n");
 234                return ret;
 235        }
 236
 237        atmel_pwm_writel(atmel_pwm, PWM_ENA, 1 << pwm->hwpwm);
 238
 239        return 0;
 240}
 241
 242static void atmel_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
 243{
 244        struct atmel_pwm_chip *atmel_pwm = to_atmel_pwm_chip(chip);
 245
 246        atmel_pwm_writel(atmel_pwm, PWM_DIS, 1 << pwm->hwpwm);
 247
 248        clk_disable(atmel_pwm->clk);
 249}
 250
 251static const struct pwm_ops atmel_pwm_ops = {
 252        .config = atmel_pwm_config,
 253        .set_polarity = atmel_pwm_set_polarity,
 254        .enable = atmel_pwm_enable,
 255        .disable = atmel_pwm_disable,
 256        .owner = THIS_MODULE,
 257};
 258
 259struct atmel_pwm_data {
 260        void (*config)(struct pwm_chip *chip, struct pwm_device *pwm,
 261                       unsigned long dty, unsigned long prd);
 262};
 263
 264static const struct atmel_pwm_data atmel_pwm_data_v1 = {
 265        .config = atmel_pwm_config_v1,
 266};
 267
 268static const struct atmel_pwm_data atmel_pwm_data_v2 = {
 269        .config = atmel_pwm_config_v2,
 270};
 271
 272static const struct platform_device_id atmel_pwm_devtypes[] = {
 273        {
 274                .name = "at91sam9rl-pwm",
 275                .driver_data = (kernel_ulong_t)&atmel_pwm_data_v1,
 276        }, {
 277                .name = "sama5d3-pwm",
 278                .driver_data = (kernel_ulong_t)&atmel_pwm_data_v2,
 279        }, {
 280                /* sentinel */
 281        },
 282};
 283MODULE_DEVICE_TABLE(platform, atmel_pwm_devtypes);
 284
 285static const struct of_device_id atmel_pwm_dt_ids[] = {
 286        {
 287                .compatible = "atmel,at91sam9rl-pwm",
 288                .data = &atmel_pwm_data_v1,
 289        }, {
 290                .compatible = "atmel,sama5d3-pwm",
 291                .data = &atmel_pwm_data_v2,
 292        }, {
 293                /* sentinel */
 294        },
 295};
 296MODULE_DEVICE_TABLE(of, atmel_pwm_dt_ids);
 297
 298static inline const struct atmel_pwm_data *
 299atmel_pwm_get_driver_data(struct platform_device *pdev)
 300{
 301        if (pdev->dev.of_node) {
 302                const struct of_device_id *match;
 303
 304                match = of_match_device(atmel_pwm_dt_ids, &pdev->dev);
 305                if (!match)
 306                        return NULL;
 307
 308                return match->data;
 309        } else {
 310                const struct platform_device_id *id;
 311
 312                id = platform_get_device_id(pdev);
 313
 314                return (struct atmel_pwm_data *)id->driver_data;
 315        }
 316}
 317
 318static int atmel_pwm_probe(struct platform_device *pdev)
 319{
 320        const struct atmel_pwm_data *data;
 321        struct atmel_pwm_chip *atmel_pwm;
 322        struct resource *res;
 323        int ret;
 324
 325        data = atmel_pwm_get_driver_data(pdev);
 326        if (!data)
 327                return -ENODEV;
 328
 329        atmel_pwm = devm_kzalloc(&pdev->dev, sizeof(*atmel_pwm), GFP_KERNEL);
 330        if (!atmel_pwm)
 331                return -ENOMEM;
 332
 333        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 334        atmel_pwm->base = devm_ioremap_resource(&pdev->dev, res);
 335        if (IS_ERR(atmel_pwm->base))
 336                return PTR_ERR(atmel_pwm->base);
 337
 338        atmel_pwm->clk = devm_clk_get(&pdev->dev, NULL);
 339        if (IS_ERR(atmel_pwm->clk))
 340                return PTR_ERR(atmel_pwm->clk);
 341
 342        ret = clk_prepare(atmel_pwm->clk);
 343        if (ret) {
 344                dev_err(&pdev->dev, "failed to prepare PWM clock\n");
 345                return ret;
 346        }
 347
 348        atmel_pwm->chip.dev = &pdev->dev;
 349        atmel_pwm->chip.ops = &atmel_pwm_ops;
 350
 351        if (pdev->dev.of_node) {
 352                atmel_pwm->chip.of_xlate = of_pwm_xlate_with_flags;
 353                atmel_pwm->chip.of_pwm_n_cells = 3;
 354        }
 355
 356        atmel_pwm->chip.base = -1;
 357        atmel_pwm->chip.npwm = 4;
 358        atmel_pwm->chip.can_sleep = true;
 359        atmel_pwm->config = data->config;
 360
 361        ret = pwmchip_add(&atmel_pwm->chip);
 362        if (ret < 0) {
 363                dev_err(&pdev->dev, "failed to add PWM chip %d\n", ret);
 364                goto unprepare_clk;
 365        }
 366
 367        platform_set_drvdata(pdev, atmel_pwm);
 368
 369        return ret;
 370
 371unprepare_clk:
 372        clk_unprepare(atmel_pwm->clk);
 373        return ret;
 374}
 375
 376static int atmel_pwm_remove(struct platform_device *pdev)
 377{
 378        struct atmel_pwm_chip *atmel_pwm = platform_get_drvdata(pdev);
 379
 380        clk_unprepare(atmel_pwm->clk);
 381
 382        return pwmchip_remove(&atmel_pwm->chip);
 383}
 384
 385static struct platform_driver atmel_pwm_driver = {
 386        .driver = {
 387                .name = "atmel-pwm",
 388                .of_match_table = of_match_ptr(atmel_pwm_dt_ids),
 389        },
 390        .id_table = atmel_pwm_devtypes,
 391        .probe = atmel_pwm_probe,
 392        .remove = atmel_pwm_remove,
 393};
 394module_platform_driver(atmel_pwm_driver);
 395
 396MODULE_ALIAS("platform:atmel-pwm");
 397MODULE_AUTHOR("Bo Shen <voice.shen@atmel.com>");
 398MODULE_DESCRIPTION("Atmel PWM driver");
 399MODULE_LICENSE("GPL v2");
 400