linux/drivers/pwm/pwm-lp3943.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * TI/National Semiconductor LP3943 PWM driver
   4 *
   5 * Copyright 2013 Texas Instruments
   6 *
   7 * Author: Milo Kim <milo.kim@ti.com>
   8 */
   9
  10#include <linux/err.h>
  11#include <linux/i2c.h>
  12#include <linux/mfd/lp3943.h>
  13#include <linux/module.h>
  14#include <linux/platform_device.h>
  15#include <linux/pwm.h>
  16#include <linux/slab.h>
  17
  18#define LP3943_MAX_DUTY                 255
  19#define LP3943_MIN_PERIOD               6250
  20#define LP3943_MAX_PERIOD               1600000
  21
  22struct lp3943_pwm {
  23        struct pwm_chip chip;
  24        struct lp3943 *lp3943;
  25        struct lp3943_platform_data *pdata;
  26};
  27
  28static inline struct lp3943_pwm *to_lp3943_pwm(struct pwm_chip *_chip)
  29{
  30        return container_of(_chip, struct lp3943_pwm, chip);
  31}
  32
  33static struct lp3943_pwm_map *
  34lp3943_pwm_request_map(struct lp3943_pwm *lp3943_pwm, int hwpwm)
  35{
  36        struct lp3943_platform_data *pdata = lp3943_pwm->pdata;
  37        struct lp3943 *lp3943 = lp3943_pwm->lp3943;
  38        struct lp3943_pwm_map *pwm_map;
  39        int i, offset;
  40
  41        pwm_map = kzalloc(sizeof(*pwm_map), GFP_KERNEL);
  42        if (!pwm_map)
  43                return ERR_PTR(-ENOMEM);
  44
  45        pwm_map->output = pdata->pwms[hwpwm]->output;
  46        pwm_map->num_outputs = pdata->pwms[hwpwm]->num_outputs;
  47
  48        for (i = 0; i < pwm_map->num_outputs; i++) {
  49                offset = pwm_map->output[i];
  50
  51                /* Return an error if the pin is already assigned */
  52                if (test_and_set_bit(offset, &lp3943->pin_used)) {
  53                        kfree(pwm_map);
  54                        return ERR_PTR(-EBUSY);
  55                }
  56        }
  57
  58        return pwm_map;
  59}
  60
  61static int lp3943_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm)
  62{
  63        struct lp3943_pwm *lp3943_pwm = to_lp3943_pwm(chip);
  64        struct lp3943_pwm_map *pwm_map;
  65
  66        pwm_map = lp3943_pwm_request_map(lp3943_pwm, pwm->hwpwm);
  67        if (IS_ERR(pwm_map))
  68                return PTR_ERR(pwm_map);
  69
  70        return pwm_set_chip_data(pwm, pwm_map);
  71}
  72
  73static void lp3943_pwm_free_map(struct lp3943_pwm *lp3943_pwm,
  74                                struct lp3943_pwm_map *pwm_map)
  75{
  76        struct lp3943 *lp3943 = lp3943_pwm->lp3943;
  77        int i, offset;
  78
  79        for (i = 0; i < pwm_map->num_outputs; i++) {
  80                offset = pwm_map->output[i];
  81                clear_bit(offset, &lp3943->pin_used);
  82        }
  83
  84        kfree(pwm_map);
  85}
  86
  87static void lp3943_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm)
  88{
  89        struct lp3943_pwm *lp3943_pwm = to_lp3943_pwm(chip);
  90        struct lp3943_pwm_map *pwm_map = pwm_get_chip_data(pwm);
  91
  92        lp3943_pwm_free_map(lp3943_pwm, pwm_map);
  93}
  94
  95static int lp3943_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
  96                             int duty_ns, int period_ns)
  97{
  98        struct lp3943_pwm *lp3943_pwm = to_lp3943_pwm(chip);
  99        struct lp3943 *lp3943 = lp3943_pwm->lp3943;
 100        u8 val, reg_duty, reg_prescale;
 101        int err;
 102
 103        /*
 104         * How to configure the LP3943 PWMs
 105         *
 106         * 1) Period = 6250 ~ 1600000
 107         * 2) Prescale = period / 6250 -1
 108         * 3) Duty = input duty
 109         *
 110         * Prescale and duty are register values
 111         */
 112
 113        if (pwm->hwpwm == 0) {
 114                reg_prescale = LP3943_REG_PRESCALE0;
 115                reg_duty     = LP3943_REG_PWM0;
 116        } else {
 117                reg_prescale = LP3943_REG_PRESCALE1;
 118                reg_duty     = LP3943_REG_PWM1;
 119        }
 120
 121        period_ns = clamp(period_ns, LP3943_MIN_PERIOD, LP3943_MAX_PERIOD);
 122        val       = (u8)(period_ns / LP3943_MIN_PERIOD - 1);
 123
 124        err = lp3943_write_byte(lp3943, reg_prescale, val);
 125        if (err)
 126                return err;
 127
 128        val = (u8)(duty_ns * LP3943_MAX_DUTY / period_ns);
 129
 130        return lp3943_write_byte(lp3943, reg_duty, val);
 131}
 132
 133static int lp3943_pwm_set_mode(struct lp3943_pwm *lp3943_pwm,
 134                               struct lp3943_pwm_map *pwm_map,
 135                               u8 val)
 136{
 137        struct lp3943 *lp3943 = lp3943_pwm->lp3943;
 138        const struct lp3943_reg_cfg *mux = lp3943->mux_cfg;
 139        int i, index, err;
 140
 141        for (i = 0; i < pwm_map->num_outputs; i++) {
 142                index = pwm_map->output[i];
 143                err = lp3943_update_bits(lp3943, mux[index].reg,
 144                                         mux[index].mask,
 145                                         val << mux[index].shift);
 146                if (err)
 147                        return err;
 148        }
 149
 150        return 0;
 151}
 152
 153static int lp3943_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
 154{
 155        struct lp3943_pwm *lp3943_pwm = to_lp3943_pwm(chip);
 156        struct lp3943_pwm_map *pwm_map = pwm_get_chip_data(pwm);
 157        u8 val;
 158
 159        if (pwm->hwpwm == 0)
 160                val = LP3943_DIM_PWM0;
 161        else
 162                val = LP3943_DIM_PWM1;
 163
 164        /*
 165         * Each PWM generator is set to control any of outputs of LP3943.
 166         * To enable/disable the PWM, these output pins should be configured.
 167         */
 168
 169        return lp3943_pwm_set_mode(lp3943_pwm, pwm_map, val);
 170}
 171
 172static void lp3943_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
 173{
 174        struct lp3943_pwm *lp3943_pwm = to_lp3943_pwm(chip);
 175        struct lp3943_pwm_map *pwm_map = pwm_get_chip_data(pwm);
 176
 177        /*
 178         * LP3943 outputs are open-drain, so the pin should be configured
 179         * when the PWM is disabled.
 180         */
 181
 182        lp3943_pwm_set_mode(lp3943_pwm, pwm_map, LP3943_GPIO_OUT_HIGH);
 183}
 184
 185static const struct pwm_ops lp3943_pwm_ops = {
 186        .request        = lp3943_pwm_request,
 187        .free           = lp3943_pwm_free,
 188        .config         = lp3943_pwm_config,
 189        .enable         = lp3943_pwm_enable,
 190        .disable        = lp3943_pwm_disable,
 191        .owner          = THIS_MODULE,
 192};
 193
 194static int lp3943_pwm_parse_dt(struct device *dev,
 195                               struct lp3943_pwm *lp3943_pwm)
 196{
 197        static const char * const name[] = { "ti,pwm0", "ti,pwm1", };
 198        struct device_node *node = dev->of_node;
 199        struct lp3943_platform_data *pdata;
 200        struct lp3943_pwm_map *pwm_map;
 201        enum lp3943_pwm_output *output;
 202        int i, err, proplen, count = 0;
 203        u32 num_outputs;
 204
 205        if (!node)
 206                return -EINVAL;
 207
 208        pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
 209        if (!pdata)
 210                return -ENOMEM;
 211
 212        /*
 213         * Read the output map configuration from the device tree.
 214         * Each of the two PWM generators can drive zero or more outputs.
 215         */
 216
 217        for (i = 0; i < LP3943_NUM_PWMS; i++) {
 218                if (!of_get_property(node, name[i], &proplen))
 219                        continue;
 220
 221                num_outputs = proplen / sizeof(u32);
 222                if (num_outputs == 0)
 223                        continue;
 224
 225                output = devm_kcalloc(dev, num_outputs, sizeof(*output),
 226                                      GFP_KERNEL);
 227                if (!output)
 228                        return -ENOMEM;
 229
 230                err = of_property_read_u32_array(node, name[i], output,
 231                                                 num_outputs);
 232                if (err)
 233                        return err;
 234
 235                pwm_map = devm_kzalloc(dev, sizeof(*pwm_map), GFP_KERNEL);
 236                if (!pwm_map)
 237                        return -ENOMEM;
 238
 239                pwm_map->output = output;
 240                pwm_map->num_outputs = num_outputs;
 241                pdata->pwms[i] = pwm_map;
 242
 243                count++;
 244        }
 245
 246        if (count == 0)
 247                return -ENODATA;
 248
 249        lp3943_pwm->pdata = pdata;
 250        return 0;
 251}
 252
 253static int lp3943_pwm_probe(struct platform_device *pdev)
 254{
 255        struct lp3943 *lp3943 = dev_get_drvdata(pdev->dev.parent);
 256        struct lp3943_pwm *lp3943_pwm;
 257        int ret;
 258
 259        lp3943_pwm = devm_kzalloc(&pdev->dev, sizeof(*lp3943_pwm), GFP_KERNEL);
 260        if (!lp3943_pwm)
 261                return -ENOMEM;
 262
 263        lp3943_pwm->pdata = lp3943->pdata;
 264        if (!lp3943_pwm->pdata) {
 265                if (IS_ENABLED(CONFIG_OF))
 266                        ret = lp3943_pwm_parse_dt(&pdev->dev, lp3943_pwm);
 267                else
 268                        ret = -ENODEV;
 269
 270                if (ret)
 271                        return ret;
 272        }
 273
 274        lp3943_pwm->lp3943 = lp3943;
 275        lp3943_pwm->chip.dev = &pdev->dev;
 276        lp3943_pwm->chip.ops = &lp3943_pwm_ops;
 277        lp3943_pwm->chip.npwm = LP3943_NUM_PWMS;
 278
 279        return devm_pwmchip_add(&pdev->dev, &lp3943_pwm->chip);
 280}
 281
 282#ifdef CONFIG_OF
 283static const struct of_device_id lp3943_pwm_of_match[] = {
 284        { .compatible = "ti,lp3943-pwm", },
 285        { }
 286};
 287MODULE_DEVICE_TABLE(of, lp3943_pwm_of_match);
 288#endif
 289
 290static struct platform_driver lp3943_pwm_driver = {
 291        .probe = lp3943_pwm_probe,
 292        .driver = {
 293                .name = "lp3943-pwm",
 294                .of_match_table = of_match_ptr(lp3943_pwm_of_match),
 295        },
 296};
 297module_platform_driver(lp3943_pwm_driver);
 298
 299MODULE_DESCRIPTION("LP3943 PWM driver");
 300MODULE_ALIAS("platform:lp3943-pwm");
 301MODULE_AUTHOR("Milo Kim");
 302MODULE_LICENSE("GPL");
 303