linux/drivers/pwm/pwm-lpss.c
<<
>>
Prefs
   1/*
   2 * Intel Low Power Subsystem PWM controller driver
   3 *
   4 * Copyright (C) 2014, Intel Corporation
   5 * Author: Mika Westerberg <mika.westerberg@linux.intel.com>
   6 * Author: Chew Kean Ho <kean.ho.chew@intel.com>
   7 * Author: Chang Rebecca Swee Fun <rebecca.swee.fun.chang@intel.com>
   8 * Author: Chew Chiau Ee <chiau.ee.chew@intel.com>
   9 * Author: Alan Cox <alan@linux.intel.com>
  10 *
  11 * This program is free software; you can redistribute it and/or modify
  12 * it under the terms of the GNU General Public License version 2 as
  13 * published by the Free Software Foundation.
  14 */
  15
  16#include <linux/delay.h>
  17#include <linux/io.h>
  18#include <linux/iopoll.h>
  19#include <linux/kernel.h>
  20#include <linux/module.h>
  21#include <linux/pm_runtime.h>
  22#include <linux/time.h>
  23
  24#include "pwm-lpss.h"
  25
  26#define PWM                             0x00000000
  27#define PWM_ENABLE                      BIT(31)
  28#define PWM_SW_UPDATE                   BIT(30)
  29#define PWM_BASE_UNIT_SHIFT             8
  30#define PWM_ON_TIME_DIV_MASK            0x000000ff
  31
  32/* Size of each PWM register space if multiple */
  33#define PWM_SIZE                        0x400
  34
  35static inline struct pwm_lpss_chip *to_lpwm(struct pwm_chip *chip)
  36{
  37        return container_of(chip, struct pwm_lpss_chip, chip);
  38}
  39
  40static inline u32 pwm_lpss_read(const struct pwm_device *pwm)
  41{
  42        struct pwm_lpss_chip *lpwm = to_lpwm(pwm->chip);
  43
  44        return readl(lpwm->regs + pwm->hwpwm * PWM_SIZE + PWM);
  45}
  46
  47static inline void pwm_lpss_write(const struct pwm_device *pwm, u32 value)
  48{
  49        struct pwm_lpss_chip *lpwm = to_lpwm(pwm->chip);
  50
  51        writel(value, lpwm->regs + pwm->hwpwm * PWM_SIZE + PWM);
  52}
  53
  54static int pwm_lpss_wait_for_update(struct pwm_device *pwm)
  55{
  56        struct pwm_lpss_chip *lpwm = to_lpwm(pwm->chip);
  57        const void __iomem *addr = lpwm->regs + pwm->hwpwm * PWM_SIZE + PWM;
  58        const unsigned int ms = 500 * USEC_PER_MSEC;
  59        u32 val;
  60        int err;
  61
  62        /*
  63         * PWM Configuration register has SW_UPDATE bit that is set when a new
  64         * configuration is written to the register. The bit is automatically
  65         * cleared at the start of the next output cycle by the IP block.
  66         *
  67         * If one writes a new configuration to the register while it still has
  68         * the bit enabled, PWM may freeze. That is, while one can still write
  69         * to the register, it won't have an effect. Thus, we try to sleep long
  70         * enough that the bit gets cleared and make sure the bit is not
  71         * enabled while we update the configuration.
  72         */
  73        err = readl_poll_timeout(addr, val, !(val & PWM_SW_UPDATE), 40, ms);
  74        if (err)
  75                dev_err(pwm->chip->dev, "PWM_SW_UPDATE was not cleared\n");
  76
  77        return err;
  78}
  79
  80static inline int pwm_lpss_is_updating(struct pwm_device *pwm)
  81{
  82        return (pwm_lpss_read(pwm) & PWM_SW_UPDATE) ? -EBUSY : 0;
  83}
  84
  85static void pwm_lpss_prepare(struct pwm_lpss_chip *lpwm, struct pwm_device *pwm,
  86                             int duty_ns, int period_ns)
  87{
  88        unsigned long long on_time_div;
  89        unsigned long c = lpwm->info->clk_rate, base_unit_range;
  90        unsigned long long base_unit, freq = NSEC_PER_SEC;
  91        u32 orig_ctrl, ctrl;
  92
  93        do_div(freq, period_ns);
  94
  95        /*
  96         * The equation is:
  97         * base_unit = round(base_unit_range * freq / c)
  98         */
  99        base_unit_range = BIT(lpwm->info->base_unit_bits) - 1;
 100        freq *= base_unit_range;
 101
 102        base_unit = DIV_ROUND_CLOSEST_ULL(freq, c);
 103
 104        on_time_div = 255ULL * duty_ns;
 105        do_div(on_time_div, period_ns);
 106        on_time_div = 255ULL - on_time_div;
 107
 108        orig_ctrl = ctrl = pwm_lpss_read(pwm);
 109        ctrl &= ~PWM_ON_TIME_DIV_MASK;
 110        ctrl &= ~(base_unit_range << PWM_BASE_UNIT_SHIFT);
 111        base_unit &= base_unit_range;
 112        ctrl |= (u32) base_unit << PWM_BASE_UNIT_SHIFT;
 113        ctrl |= on_time_div;
 114
 115        if (orig_ctrl != ctrl) {
 116                pwm_lpss_write(pwm, ctrl);
 117                pwm_lpss_write(pwm, ctrl | PWM_SW_UPDATE);
 118        }
 119}
 120
 121static inline void pwm_lpss_cond_enable(struct pwm_device *pwm, bool cond)
 122{
 123        if (cond)
 124                pwm_lpss_write(pwm, pwm_lpss_read(pwm) | PWM_ENABLE);
 125}
 126
 127static int pwm_lpss_apply(struct pwm_chip *chip, struct pwm_device *pwm,
 128                          struct pwm_state *state)
 129{
 130        struct pwm_lpss_chip *lpwm = to_lpwm(chip);
 131        int ret;
 132
 133        if (state->enabled) {
 134                if (!pwm_is_enabled(pwm)) {
 135                        pm_runtime_get_sync(chip->dev);
 136                        ret = pwm_lpss_is_updating(pwm);
 137                        if (ret) {
 138                                pm_runtime_put(chip->dev);
 139                                return ret;
 140                        }
 141                        pwm_lpss_prepare(lpwm, pwm, state->duty_cycle, state->period);
 142                        pwm_lpss_cond_enable(pwm, lpwm->info->bypass == false);
 143                        ret = pwm_lpss_wait_for_update(pwm);
 144                        if (ret) {
 145                                pm_runtime_put(chip->dev);
 146                                return ret;
 147                        }
 148                        pwm_lpss_cond_enable(pwm, lpwm->info->bypass == true);
 149                } else {
 150                        ret = pwm_lpss_is_updating(pwm);
 151                        if (ret)
 152                                return ret;
 153                        pwm_lpss_prepare(lpwm, pwm, state->duty_cycle, state->period);
 154                        return pwm_lpss_wait_for_update(pwm);
 155                }
 156        } else if (pwm_is_enabled(pwm)) {
 157                pwm_lpss_write(pwm, pwm_lpss_read(pwm) & ~PWM_ENABLE);
 158                pm_runtime_put(chip->dev);
 159        }
 160
 161        return 0;
 162}
 163
 164/* This function gets called once from pwmchip_add to get the initial state */
 165static void pwm_lpss_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
 166                               struct pwm_state *state)
 167{
 168        struct pwm_lpss_chip *lpwm = to_lpwm(chip);
 169        unsigned long base_unit_range;
 170        unsigned long long base_unit, freq, on_time_div;
 171        u32 ctrl;
 172
 173        base_unit_range = BIT(lpwm->info->base_unit_bits);
 174
 175        ctrl = pwm_lpss_read(pwm);
 176        on_time_div = 255 - (ctrl & PWM_ON_TIME_DIV_MASK);
 177        base_unit = (ctrl >> PWM_BASE_UNIT_SHIFT) & (base_unit_range - 1);
 178
 179        freq = base_unit * lpwm->info->clk_rate;
 180        do_div(freq, base_unit_range);
 181        if (freq == 0)
 182                state->period = NSEC_PER_SEC;
 183        else
 184                state->period = NSEC_PER_SEC / (unsigned long)freq;
 185
 186        on_time_div *= state->period;
 187        do_div(on_time_div, 255);
 188        state->duty_cycle = on_time_div;
 189
 190        state->polarity = PWM_POLARITY_NORMAL;
 191        state->enabled = !!(ctrl & PWM_ENABLE);
 192
 193        if (state->enabled)
 194                pm_runtime_get(chip->dev);
 195}
 196
 197static const struct pwm_ops pwm_lpss_ops = {
 198        .apply = pwm_lpss_apply,
 199        .get_state = pwm_lpss_get_state,
 200        .owner = THIS_MODULE,
 201};
 202
 203struct pwm_lpss_chip *pwm_lpss_probe(struct device *dev, struct resource *r,
 204                                     const struct pwm_lpss_boardinfo *info)
 205{
 206        struct pwm_lpss_chip *lpwm;
 207        unsigned long c;
 208        int ret;
 209
 210        if (WARN_ON(info->npwm > MAX_PWMS))
 211                return ERR_PTR(-ENODEV);
 212
 213        lpwm = devm_kzalloc(dev, sizeof(*lpwm), GFP_KERNEL);
 214        if (!lpwm)
 215                return ERR_PTR(-ENOMEM);
 216
 217        lpwm->regs = devm_ioremap_resource(dev, r);
 218        if (IS_ERR(lpwm->regs))
 219                return ERR_CAST(lpwm->regs);
 220
 221        lpwm->info = info;
 222
 223        c = lpwm->info->clk_rate;
 224        if (!c)
 225                return ERR_PTR(-EINVAL);
 226
 227        lpwm->chip.dev = dev;
 228        lpwm->chip.ops = &pwm_lpss_ops;
 229        lpwm->chip.base = -1;
 230        lpwm->chip.npwm = info->npwm;
 231
 232        ret = pwmchip_add(&lpwm->chip);
 233        if (ret) {
 234                dev_err(dev, "failed to add PWM chip: %d\n", ret);
 235                return ERR_PTR(ret);
 236        }
 237
 238        return lpwm;
 239}
 240EXPORT_SYMBOL_GPL(pwm_lpss_probe);
 241
 242int pwm_lpss_remove(struct pwm_lpss_chip *lpwm)
 243{
 244        int i;
 245
 246        for (i = 0; i < lpwm->info->npwm; i++) {
 247                if (pwm_is_enabled(&lpwm->chip.pwms[i]))
 248                        pm_runtime_put(lpwm->chip.dev);
 249        }
 250        return pwmchip_remove(&lpwm->chip);
 251}
 252EXPORT_SYMBOL_GPL(pwm_lpss_remove);
 253
 254int pwm_lpss_suspend(struct device *dev)
 255{
 256        struct pwm_lpss_chip *lpwm = dev_get_drvdata(dev);
 257        int i;
 258
 259        for (i = 0; i < lpwm->info->npwm; i++)
 260                lpwm->saved_ctrl[i] = readl(lpwm->regs + i * PWM_SIZE + PWM);
 261
 262        return 0;
 263}
 264EXPORT_SYMBOL_GPL(pwm_lpss_suspend);
 265
 266int pwm_lpss_resume(struct device *dev)
 267{
 268        struct pwm_lpss_chip *lpwm = dev_get_drvdata(dev);
 269        int i;
 270
 271        for (i = 0; i < lpwm->info->npwm; i++)
 272                writel(lpwm->saved_ctrl[i], lpwm->regs + i * PWM_SIZE + PWM);
 273
 274        return 0;
 275}
 276EXPORT_SYMBOL_GPL(pwm_lpss_resume);
 277
 278MODULE_DESCRIPTION("PWM driver for Intel LPSS");
 279MODULE_AUTHOR("Mika Westerberg <mika.westerberg@linux.intel.com>");
 280MODULE_LICENSE("GPL v2");
 281