linux/drivers/pwm/pwm-zx.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * Copyright (C) 2017 Sanechips Technology Co., Ltd.
   4 * Copyright 2017 Linaro Ltd.
   5 */
   6
   7#include <linux/clk.h>
   8#include <linux/err.h>
   9#include <linux/io.h>
  10#include <linux/kernel.h>
  11#include <linux/module.h>
  12#include <linux/platform_device.h>
  13#include <linux/pwm.h>
  14#include <linux/slab.h>
  15
  16#define ZX_PWM_MODE             0x0
  17#define ZX_PWM_CLKDIV_SHIFT     2
  18#define ZX_PWM_CLKDIV_MASK      GENMASK(11, 2)
  19#define ZX_PWM_CLKDIV(x)        (((x) << ZX_PWM_CLKDIV_SHIFT) & \
  20                                         ZX_PWM_CLKDIV_MASK)
  21#define ZX_PWM_POLAR            BIT(1)
  22#define ZX_PWM_EN               BIT(0)
  23#define ZX_PWM_PERIOD           0x4
  24#define ZX_PWM_DUTY             0x8
  25
  26#define ZX_PWM_CLKDIV_MAX       1023
  27#define ZX_PWM_PERIOD_MAX       65535
  28
  29struct zx_pwm_chip {
  30        struct pwm_chip chip;
  31        struct clk *pclk;
  32        struct clk *wclk;
  33        void __iomem *base;
  34};
  35
  36static inline struct zx_pwm_chip *to_zx_pwm_chip(struct pwm_chip *chip)
  37{
  38        return container_of(chip, struct zx_pwm_chip, chip);
  39}
  40
  41static inline u32 zx_pwm_readl(struct zx_pwm_chip *zpc, unsigned int hwpwm,
  42                               unsigned int offset)
  43{
  44        return readl(zpc->base + (hwpwm + 1) * 0x10 + offset);
  45}
  46
  47static inline void zx_pwm_writel(struct zx_pwm_chip *zpc, unsigned int hwpwm,
  48                                 unsigned int offset, u32 value)
  49{
  50        writel(value, zpc->base + (hwpwm + 1) * 0x10 + offset);
  51}
  52
  53static void zx_pwm_set_mask(struct zx_pwm_chip *zpc, unsigned int hwpwm,
  54                            unsigned int offset, u32 mask, u32 value)
  55{
  56        u32 data;
  57
  58        data = zx_pwm_readl(zpc, hwpwm, offset);
  59        data &= ~mask;
  60        data |= value & mask;
  61        zx_pwm_writel(zpc, hwpwm, offset, data);
  62}
  63
  64static void zx_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
  65                             struct pwm_state *state)
  66{
  67        struct zx_pwm_chip *zpc = to_zx_pwm_chip(chip);
  68        unsigned long rate;
  69        unsigned int div;
  70        u32 value;
  71        u64 tmp;
  72
  73        value = zx_pwm_readl(zpc, pwm->hwpwm, ZX_PWM_MODE);
  74
  75        if (value & ZX_PWM_POLAR)
  76                state->polarity = PWM_POLARITY_NORMAL;
  77        else
  78                state->polarity = PWM_POLARITY_INVERSED;
  79
  80        if (value & ZX_PWM_EN)
  81                state->enabled = true;
  82        else
  83                state->enabled = false;
  84
  85        div = (value & ZX_PWM_CLKDIV_MASK) >> ZX_PWM_CLKDIV_SHIFT;
  86        rate = clk_get_rate(zpc->wclk);
  87
  88        tmp = zx_pwm_readl(zpc, pwm->hwpwm, ZX_PWM_PERIOD);
  89        tmp *= div * NSEC_PER_SEC;
  90        state->period = DIV_ROUND_CLOSEST_ULL(tmp, rate);
  91
  92        tmp = zx_pwm_readl(zpc, pwm->hwpwm, ZX_PWM_DUTY);
  93        tmp *= div * NSEC_PER_SEC;
  94        state->duty_cycle = DIV_ROUND_CLOSEST_ULL(tmp, rate);
  95}
  96
  97static int zx_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
  98                         unsigned int duty_ns, unsigned int period_ns)
  99{
 100        struct zx_pwm_chip *zpc = to_zx_pwm_chip(chip);
 101        unsigned int period_cycles, duty_cycles;
 102        unsigned long long c;
 103        unsigned int div = 1;
 104        unsigned long rate;
 105
 106        /* Find out the best divider */
 107        rate = clk_get_rate(zpc->wclk);
 108
 109        while (1) {
 110                c = rate / div;
 111                c = c * period_ns;
 112                do_div(c, NSEC_PER_SEC);
 113
 114                if (c < ZX_PWM_PERIOD_MAX)
 115                        break;
 116
 117                div++;
 118
 119                if (div > ZX_PWM_CLKDIV_MAX)
 120                        return -ERANGE;
 121        }
 122
 123        /* Calculate duty cycles */
 124        period_cycles = c;
 125        c *= duty_ns;
 126        do_div(c, period_ns);
 127        duty_cycles = c;
 128
 129        /*
 130         * If the PWM is being enabled, we have to temporarily disable it
 131         * before configuring the registers.
 132         */
 133        if (pwm_is_enabled(pwm))
 134                zx_pwm_set_mask(zpc, pwm->hwpwm, ZX_PWM_MODE, ZX_PWM_EN, 0);
 135
 136        /* Set up registers */
 137        zx_pwm_set_mask(zpc, pwm->hwpwm, ZX_PWM_MODE, ZX_PWM_CLKDIV_MASK,
 138                        ZX_PWM_CLKDIV(div));
 139        zx_pwm_writel(zpc, pwm->hwpwm, ZX_PWM_PERIOD, period_cycles);
 140        zx_pwm_writel(zpc, pwm->hwpwm, ZX_PWM_DUTY, duty_cycles);
 141
 142        /* Re-enable the PWM if needed */
 143        if (pwm_is_enabled(pwm))
 144                zx_pwm_set_mask(zpc, pwm->hwpwm, ZX_PWM_MODE,
 145                                ZX_PWM_EN, ZX_PWM_EN);
 146
 147        return 0;
 148}
 149
 150static int zx_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
 151                        const struct pwm_state *state)
 152{
 153        struct zx_pwm_chip *zpc = to_zx_pwm_chip(chip);
 154        struct pwm_state cstate;
 155        int ret;
 156
 157        pwm_get_state(pwm, &cstate);
 158
 159        if (state->polarity != cstate.polarity)
 160                zx_pwm_set_mask(zpc, pwm->hwpwm, ZX_PWM_MODE, ZX_PWM_POLAR,
 161                                (state->polarity == PWM_POLARITY_INVERSED) ?
 162                                 0 : ZX_PWM_POLAR);
 163
 164        if (state->period != cstate.period ||
 165            state->duty_cycle != cstate.duty_cycle) {
 166                ret = zx_pwm_config(chip, pwm, state->duty_cycle,
 167                                    state->period);
 168                if (ret)
 169                        return ret;
 170        }
 171
 172        if (state->enabled != cstate.enabled) {
 173                if (state->enabled) {
 174                        ret = clk_prepare_enable(zpc->wclk);
 175                        if (ret)
 176                                return ret;
 177
 178                        zx_pwm_set_mask(zpc, pwm->hwpwm, ZX_PWM_MODE,
 179                                        ZX_PWM_EN, ZX_PWM_EN);
 180                } else {
 181                        zx_pwm_set_mask(zpc, pwm->hwpwm, ZX_PWM_MODE,
 182                                        ZX_PWM_EN, 0);
 183                        clk_disable_unprepare(zpc->wclk);
 184                }
 185        }
 186
 187        return 0;
 188}
 189
 190static const struct pwm_ops zx_pwm_ops = {
 191        .apply = zx_pwm_apply,
 192        .get_state = zx_pwm_get_state,
 193        .owner = THIS_MODULE,
 194};
 195
 196static int zx_pwm_probe(struct platform_device *pdev)
 197{
 198        struct zx_pwm_chip *zpc;
 199        struct resource *res;
 200        unsigned int i;
 201        int ret;
 202
 203        zpc = devm_kzalloc(&pdev->dev, sizeof(*zpc), GFP_KERNEL);
 204        if (!zpc)
 205                return -ENOMEM;
 206
 207        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 208        zpc->base = devm_ioremap_resource(&pdev->dev, res);
 209        if (IS_ERR(zpc->base))
 210                return PTR_ERR(zpc->base);
 211
 212        zpc->pclk = devm_clk_get(&pdev->dev, "pclk");
 213        if (IS_ERR(zpc->pclk))
 214                return PTR_ERR(zpc->pclk);
 215
 216        zpc->wclk = devm_clk_get(&pdev->dev, "wclk");
 217        if (IS_ERR(zpc->wclk))
 218                return PTR_ERR(zpc->wclk);
 219
 220        ret = clk_prepare_enable(zpc->pclk);
 221        if (ret)
 222                return ret;
 223
 224        zpc->chip.dev = &pdev->dev;
 225        zpc->chip.ops = &zx_pwm_ops;
 226        zpc->chip.base = -1;
 227        zpc->chip.npwm = 4;
 228        zpc->chip.of_xlate = of_pwm_xlate_with_flags;
 229        zpc->chip.of_pwm_n_cells = 3;
 230
 231        /*
 232         * PWM devices may be enabled by firmware, and let's disable all of
 233         * them initially to save power.
 234         */
 235        for (i = 0; i < zpc->chip.npwm; i++)
 236                zx_pwm_set_mask(zpc, i, ZX_PWM_MODE, ZX_PWM_EN, 0);
 237
 238        ret = pwmchip_add(&zpc->chip);
 239        if (ret < 0) {
 240                dev_err(&pdev->dev, "failed to add PWM chip: %d\n", ret);
 241                return ret;
 242        }
 243
 244        platform_set_drvdata(pdev, zpc);
 245
 246        return 0;
 247}
 248
 249static int zx_pwm_remove(struct platform_device *pdev)
 250{
 251        struct zx_pwm_chip *zpc = platform_get_drvdata(pdev);
 252        int ret;
 253
 254        ret = pwmchip_remove(&zpc->chip);
 255        clk_disable_unprepare(zpc->pclk);
 256
 257        return ret;
 258}
 259
 260static const struct of_device_id zx_pwm_dt_ids[] = {
 261        { .compatible = "zte,zx296718-pwm", },
 262        { /* sentinel */ }
 263};
 264MODULE_DEVICE_TABLE(of, zx_pwm_dt_ids);
 265
 266static struct platform_driver zx_pwm_driver = {
 267        .driver = {
 268                .name = "zx-pwm",
 269                .of_match_table = zx_pwm_dt_ids,
 270        },
 271        .probe = zx_pwm_probe,
 272        .remove = zx_pwm_remove,
 273};
 274module_platform_driver(zx_pwm_driver);
 275
 276MODULE_ALIAS("platform:zx-pwm");
 277MODULE_AUTHOR("Shawn Guo <shawn.guo@linaro.org>");
 278MODULE_DESCRIPTION("ZTE ZX PWM Driver");
 279MODULE_LICENSE("GPL v2");
 280