linux/drivers/pwm/pwm-sti.c
<<
>>
Prefs
   1/*
   2 * PWM device driver for ST SoCs.
   3 * Author: Ajit Pal Singh <ajitpal.singh@st.com>
   4 *
   5 * Copyright (C) 2013-2014 STMicroelectronics (R&D) Limited
   6 *
   7 * This program is free software; you can redistribute it and/or modify
   8 * it under the terms of the GNU General Public License as published by
   9 * the Free Software Foundation; either version 2 of the License, or
  10 * (at your option) any later version.
  11 */
  12
  13#include <linux/clk.h>
  14#include <linux/math64.h>
  15#include <linux/mfd/syscon.h>
  16#include <linux/module.h>
  17#include <linux/of.h>
  18#include <linux/platform_device.h>
  19#include <linux/pwm.h>
  20#include <linux/regmap.h>
  21#include <linux/slab.h>
  22#include <linux/time.h>
  23
  24#define STI_DS_REG(ch)  (4 * (ch))      /* Channel's Duty Cycle register */
  25#define STI_PWMCR       0x50            /* Control/Config register */
  26#define STI_INTEN       0x54            /* Interrupt Enable/Disable register */
  27#define PWM_PRESCALE_LOW_MASK           0x0f
  28#define PWM_PRESCALE_HIGH_MASK          0xf0
  29
  30/* Regfield IDs */
  31enum {
  32        PWMCLK_PRESCALE_LOW,
  33        PWMCLK_PRESCALE_HIGH,
  34        PWM_EN,
  35        PWM_INT_EN,
  36
  37        /* Keep last */
  38        MAX_REGFIELDS
  39};
  40
  41struct sti_pwm_compat_data {
  42        const struct reg_field *reg_fields;
  43        unsigned int num_chan;
  44        unsigned int max_pwm_cnt;
  45        unsigned int max_prescale;
  46};
  47
  48struct sti_pwm_chip {
  49        struct device *dev;
  50        struct clk *clk;
  51        unsigned long clk_rate;
  52        struct regmap *regmap;
  53        struct sti_pwm_compat_data *cdata;
  54        struct regmap_field *prescale_low;
  55        struct regmap_field *prescale_high;
  56        struct regmap_field *pwm_en;
  57        struct regmap_field *pwm_int_en;
  58        struct pwm_chip chip;
  59        struct pwm_device *cur;
  60        unsigned int en_count;
  61        struct mutex sti_pwm_lock; /* To sync between enable/disable calls */
  62        void __iomem *mmio;
  63};
  64
  65static const struct reg_field sti_pwm_regfields[MAX_REGFIELDS] = {
  66        [PWMCLK_PRESCALE_LOW]   = REG_FIELD(STI_PWMCR, 0, 3),
  67        [PWMCLK_PRESCALE_HIGH]  = REG_FIELD(STI_PWMCR, 11, 14),
  68        [PWM_EN]                = REG_FIELD(STI_PWMCR, 9, 9),
  69        [PWM_INT_EN]            = REG_FIELD(STI_INTEN, 0, 0),
  70};
  71
  72static inline struct sti_pwm_chip *to_sti_pwmchip(struct pwm_chip *chip)
  73{
  74        return container_of(chip, struct sti_pwm_chip, chip);
  75}
  76
  77/*
  78 * Calculate the prescaler value corresponding to the period.
  79 */
  80static int sti_pwm_get_prescale(struct sti_pwm_chip *pc, unsigned long period,
  81                                unsigned int *prescale)
  82{
  83        struct sti_pwm_compat_data *cdata = pc->cdata;
  84        unsigned long val;
  85        unsigned int ps;
  86
  87        /*
  88         * prescale = ((period_ns * clk_rate) / (10^9 * (max_pwm_count + 1)) - 1
  89         */
  90        val = NSEC_PER_SEC / pc->clk_rate;
  91        val *= cdata->max_pwm_cnt + 1;
  92
  93        if (period % val) {
  94                return -EINVAL;
  95        } else {
  96                ps  = period / val - 1;
  97                if (ps > cdata->max_prescale)
  98                        return -EINVAL;
  99        }
 100        *prescale = ps;
 101
 102        return 0;
 103}
 104
 105/* Calculate the number of PWM devices configured with a period. */
 106static unsigned int sti_pwm_count_configured(struct pwm_chip *chip)
 107{
 108        struct pwm_device *pwm;
 109        unsigned int ncfg = 0;
 110        unsigned int i;
 111
 112        for (i = 0; i < chip->npwm; i++) {
 113                pwm = &chip->pwms[i];
 114                if (test_bit(PWMF_REQUESTED, &pwm->flags)) {
 115                        if (pwm_get_period(pwm))
 116                                ncfg++;
 117                }
 118        }
 119
 120        return ncfg;
 121}
 122
 123/*
 124 * For STiH4xx PWM IP, the PWM period is fixed to 256 local clock cycles.
 125 * The only way to change the period (apart from changing the PWM input clock)
 126 * is to change the PWM clock prescaler.
 127 * The prescaler is of 8 bits, so 256 prescaler values and hence
 128 * 256 possible period values are supported (for a particular clock rate).
 129 * The requested period will be applied only if it matches one of these
 130 * 256 values.
 131 */
 132static int sti_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
 133                         int duty_ns, int period_ns)
 134{
 135        struct sti_pwm_chip *pc = to_sti_pwmchip(chip);
 136        struct sti_pwm_compat_data *cdata = pc->cdata;
 137        struct pwm_device *cur = pc->cur;
 138        struct device *dev = pc->dev;
 139        unsigned int prescale = 0, pwmvalx;
 140        int ret;
 141        unsigned int ncfg;
 142        bool period_same = false;
 143
 144        ncfg = sti_pwm_count_configured(chip);
 145        if (ncfg)
 146                period_same = (period_ns == pwm_get_period(cur));
 147
 148        /* Allow configuration changes if one of the
 149         * following conditions satisfy.
 150         * 1. No channels have been configured.
 151         * 2. Only one channel has been configured and the new request
 152         *    is for the same channel.
 153         * 3. Only one channel has been configured and the new request is
 154         *    for a new channel and period of the new channel is same as
 155         *    the current configured period.
 156         * 4. More than one channels are configured and period of the new
 157         *    requestis the same as the current period.
 158         */
 159        if (!ncfg ||
 160            ((ncfg == 1) && (pwm->hwpwm == cur->hwpwm)) ||
 161            ((ncfg == 1) && (pwm->hwpwm != cur->hwpwm) && period_same) ||
 162            ((ncfg > 1) && period_same)) {
 163                /* Enable clock before writing to PWM registers. */
 164                ret = clk_enable(pc->clk);
 165                if (ret)
 166                        return ret;
 167
 168                if (!period_same) {
 169                        ret = sti_pwm_get_prescale(pc, period_ns, &prescale);
 170                        if (ret)
 171                                goto clk_dis;
 172
 173                        ret =
 174                        regmap_field_write(pc->prescale_low,
 175                                           prescale & PWM_PRESCALE_LOW_MASK);
 176                        if (ret)
 177                                goto clk_dis;
 178
 179                        ret =
 180                        regmap_field_write(pc->prescale_high,
 181                                (prescale & PWM_PRESCALE_HIGH_MASK) >> 4);
 182                        if (ret)
 183                                goto clk_dis;
 184                }
 185
 186                /*
 187                 * When PWMVal == 0, PWM pulse = 1 local clock cycle.
 188                 * When PWMVal == max_pwm_count,
 189                 * PWM pulse = (max_pwm_count + 1) local cycles,
 190                 * that is continuous pulse: signal never goes low.
 191                 */
 192                pwmvalx = cdata->max_pwm_cnt * duty_ns / period_ns;
 193
 194                ret = regmap_write(pc->regmap, STI_DS_REG(pwm->hwpwm), pwmvalx);
 195                if (ret)
 196                        goto clk_dis;
 197
 198                ret = regmap_field_write(pc->pwm_int_en, 0);
 199
 200                pc->cur = pwm;
 201
 202                dev_dbg(dev, "prescale:%u, period:%i, duty:%i, pwmvalx:%u\n",
 203                        prescale, period_ns, duty_ns, pwmvalx);
 204        } else {
 205                return -EINVAL;
 206        }
 207
 208clk_dis:
 209        clk_disable(pc->clk);
 210        return ret;
 211}
 212
 213static int sti_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
 214{
 215        struct sti_pwm_chip *pc = to_sti_pwmchip(chip);
 216        struct device *dev = pc->dev;
 217        int ret = 0;
 218
 219        /*
 220         * Since we have a common enable for all PWM channels,
 221         * do not enable if already enabled.
 222         */
 223        mutex_lock(&pc->sti_pwm_lock);
 224        if (!pc->en_count) {
 225                ret = clk_enable(pc->clk);
 226                if (ret)
 227                        goto out;
 228
 229                ret = regmap_field_write(pc->pwm_en, 1);
 230                if (ret) {
 231                        dev_err(dev, "failed to enable PWM device:%d\n",
 232                                pwm->hwpwm);
 233                        goto out;
 234                }
 235        }
 236        pc->en_count++;
 237out:
 238        mutex_unlock(&pc->sti_pwm_lock);
 239        return ret;
 240}
 241
 242static void sti_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
 243{
 244        struct sti_pwm_chip *pc = to_sti_pwmchip(chip);
 245
 246        mutex_lock(&pc->sti_pwm_lock);
 247        if (--pc->en_count) {
 248                mutex_unlock(&pc->sti_pwm_lock);
 249                return;
 250        }
 251        regmap_field_write(pc->pwm_en, 0);
 252
 253        clk_disable(pc->clk);
 254        mutex_unlock(&pc->sti_pwm_lock);
 255}
 256
 257static const struct pwm_ops sti_pwm_ops = {
 258        .config = sti_pwm_config,
 259        .enable = sti_pwm_enable,
 260        .disable = sti_pwm_disable,
 261        .owner = THIS_MODULE,
 262};
 263
 264static int sti_pwm_probe_dt(struct sti_pwm_chip *pc)
 265{
 266        struct device *dev = pc->dev;
 267        const struct reg_field *reg_fields;
 268        struct device_node *np = dev->of_node;
 269        struct sti_pwm_compat_data *cdata = pc->cdata;
 270        u32 num_chan;
 271
 272        of_property_read_u32(np, "st,pwm-num-chan", &num_chan);
 273        if (num_chan)
 274                cdata->num_chan = num_chan;
 275
 276        reg_fields = cdata->reg_fields;
 277
 278        pc->prescale_low = devm_regmap_field_alloc(dev, pc->regmap,
 279                                        reg_fields[PWMCLK_PRESCALE_LOW]);
 280        if (IS_ERR(pc->prescale_low))
 281                return PTR_ERR(pc->prescale_low);
 282
 283        pc->prescale_high = devm_regmap_field_alloc(dev, pc->regmap,
 284                                        reg_fields[PWMCLK_PRESCALE_HIGH]);
 285        if (IS_ERR(pc->prescale_high))
 286                return PTR_ERR(pc->prescale_high);
 287
 288        pc->pwm_en = devm_regmap_field_alloc(dev, pc->regmap,
 289                                             reg_fields[PWM_EN]);
 290        if (IS_ERR(pc->pwm_en))
 291                return PTR_ERR(pc->pwm_en);
 292
 293        pc->pwm_int_en = devm_regmap_field_alloc(dev, pc->regmap,
 294                                                 reg_fields[PWM_INT_EN]);
 295        if (IS_ERR(pc->pwm_int_en))
 296                return PTR_ERR(pc->pwm_int_en);
 297
 298        return 0;
 299}
 300
 301static const struct regmap_config sti_pwm_regmap_config = {
 302        .reg_bits = 32,
 303        .val_bits = 32,
 304        .reg_stride = 4,
 305};
 306
 307static int sti_pwm_probe(struct platform_device *pdev)
 308{
 309        struct device *dev = &pdev->dev;
 310        struct sti_pwm_compat_data *cdata;
 311        struct sti_pwm_chip *pc;
 312        struct resource *res;
 313        int ret;
 314
 315        pc = devm_kzalloc(dev, sizeof(*pc), GFP_KERNEL);
 316        if (!pc)
 317                return -ENOMEM;
 318
 319        cdata = devm_kzalloc(dev, sizeof(*cdata), GFP_KERNEL);
 320        if (!cdata)
 321                return -ENOMEM;
 322
 323        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 324
 325        pc->mmio = devm_ioremap_resource(dev, res);
 326        if (IS_ERR(pc->mmio))
 327                return PTR_ERR(pc->mmio);
 328
 329        pc->regmap = devm_regmap_init_mmio(dev, pc->mmio,
 330                                           &sti_pwm_regmap_config);
 331        if (IS_ERR(pc->regmap))
 332                return PTR_ERR(pc->regmap);
 333
 334        /*
 335         * Setup PWM data with default values: some values could be replaced
 336         * with specific ones provided from Device Tree.
 337         */
 338        cdata->reg_fields   = &sti_pwm_regfields[0];
 339        cdata->max_prescale = 0xff;
 340        cdata->max_pwm_cnt  = 255;
 341        cdata->num_chan     = 1;
 342
 343        pc->cdata = cdata;
 344        pc->dev = dev;
 345        pc->en_count = 0;
 346        mutex_init(&pc->sti_pwm_lock);
 347
 348        ret = sti_pwm_probe_dt(pc);
 349        if (ret)
 350                return ret;
 351
 352        pc->clk = of_clk_get_by_name(dev->of_node, "pwm");
 353        if (IS_ERR(pc->clk)) {
 354                dev_err(dev, "failed to get PWM clock\n");
 355                return PTR_ERR(pc->clk);
 356        }
 357
 358        pc->clk_rate = clk_get_rate(pc->clk);
 359        if (!pc->clk_rate) {
 360                dev_err(dev, "failed to get clock rate\n");
 361                return -EINVAL;
 362        }
 363
 364        ret = clk_prepare(pc->clk);
 365        if (ret) {
 366                dev_err(dev, "failed to prepare clock\n");
 367                return ret;
 368        }
 369
 370        pc->chip.dev = dev;
 371        pc->chip.ops = &sti_pwm_ops;
 372        pc->chip.base = -1;
 373        pc->chip.npwm = pc->cdata->num_chan;
 374        pc->chip.can_sleep = true;
 375
 376        ret = pwmchip_add(&pc->chip);
 377        if (ret < 0) {
 378                clk_unprepare(pc->clk);
 379                return ret;
 380        }
 381
 382        platform_set_drvdata(pdev, pc);
 383
 384        return 0;
 385}
 386
 387static int sti_pwm_remove(struct platform_device *pdev)
 388{
 389        struct sti_pwm_chip *pc = platform_get_drvdata(pdev);
 390        unsigned int i;
 391
 392        for (i = 0; i < pc->cdata->num_chan; i++)
 393                pwm_disable(&pc->chip.pwms[i]);
 394
 395        clk_unprepare(pc->clk);
 396
 397        return pwmchip_remove(&pc->chip);
 398}
 399
 400static const struct of_device_id sti_pwm_of_match[] = {
 401        { .compatible = "st,sti-pwm", },
 402        { /* sentinel */ }
 403};
 404MODULE_DEVICE_TABLE(of, sti_pwm_of_match);
 405
 406static struct platform_driver sti_pwm_driver = {
 407        .driver = {
 408                .name = "sti-pwm",
 409                .of_match_table = sti_pwm_of_match,
 410        },
 411        .probe = sti_pwm_probe,
 412        .remove = sti_pwm_remove,
 413};
 414module_platform_driver(sti_pwm_driver);
 415
 416MODULE_AUTHOR("Ajit Pal Singh <ajitpal.singh@st.com>");
 417MODULE_DESCRIPTION("STMicroelectronics ST PWM driver");
 418MODULE_LICENSE("GPL");
 419