root/drivers/pwm/pwm-imx-tpm.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. to_imx_tpm_pwm_chip
  2. pwm_imx_tpm_round_state
  3. pwm_imx_tpm_get_state
  4. pwm_imx_tpm_apply_hw
  5. pwm_imx_tpm_apply
  6. pwm_imx_tpm_request
  7. pwm_imx_tpm_free
  8. pwm_imx_tpm_probe
  9. pwm_imx_tpm_remove
  10. pwm_imx_tpm_suspend
  11. pwm_imx_tpm_resume

   1 // SPDX-License-Identifier: GPL-2.0
   2 /*
   3  * Copyright 2018-2019 NXP.
   4  *
   5  * Limitations:
   6  * - The TPM counter and period counter are shared between
   7  *   multiple channels, so all channels should use same period
   8  *   settings.
   9  * - Changes to polarity cannot be latched at the time of the
  10  *   next period start.
  11  * - Changing period and duty cycle together isn't atomic,
  12  *   with the wrong timing it might happen that a period is
  13  *   produced with old duty cycle but new period settings.
  14  */
  15 
  16 #include <linux/bitfield.h>
  17 #include <linux/bitops.h>
  18 #include <linux/clk.h>
  19 #include <linux/err.h>
  20 #include <linux/io.h>
  21 #include <linux/log2.h>
  22 #include <linux/module.h>
  23 #include <linux/of.h>
  24 #include <linux/of_address.h>
  25 #include <linux/platform_device.h>
  26 #include <linux/pwm.h>
  27 #include <linux/slab.h>
  28 
  29 #define PWM_IMX_TPM_PARAM       0x4
  30 #define PWM_IMX_TPM_GLOBAL      0x8
  31 #define PWM_IMX_TPM_SC          0x10
  32 #define PWM_IMX_TPM_CNT         0x14
  33 #define PWM_IMX_TPM_MOD         0x18
  34 #define PWM_IMX_TPM_CnSC(n)     (0x20 + (n) * 0x8)
  35 #define PWM_IMX_TPM_CnV(n)      (0x24 + (n) * 0x8)
  36 
  37 #define PWM_IMX_TPM_PARAM_CHAN                  GENMASK(7, 0)
  38 
  39 #define PWM_IMX_TPM_SC_PS                       GENMASK(2, 0)
  40 #define PWM_IMX_TPM_SC_CMOD                     GENMASK(4, 3)
  41 #define PWM_IMX_TPM_SC_CMOD_INC_EVERY_CLK       FIELD_PREP(PWM_IMX_TPM_SC_CMOD, 1)
  42 #define PWM_IMX_TPM_SC_CPWMS                    BIT(5)
  43 
  44 #define PWM_IMX_TPM_CnSC_CHF    BIT(7)
  45 #define PWM_IMX_TPM_CnSC_MSB    BIT(5)
  46 #define PWM_IMX_TPM_CnSC_MSA    BIT(4)
  47 
  48 /*
  49  * The reference manual describes this field as two separate bits. The
  50  * semantic of the two bits isn't orthogonal though, so they are treated
  51  * together as a 2-bit field here.
  52  */
  53 #define PWM_IMX_TPM_CnSC_ELS    GENMASK(3, 2)
  54 #define PWM_IMX_TPM_CnSC_ELS_INVERSED   FIELD_PREP(PWM_IMX_TPM_CnSC_ELS, 1)
  55 #define PWM_IMX_TPM_CnSC_ELS_NORMAL     FIELD_PREP(PWM_IMX_TPM_CnSC_ELS, 2)
  56 
  57 
  58 #define PWM_IMX_TPM_MOD_WIDTH   16
  59 #define PWM_IMX_TPM_MOD_MOD     GENMASK(PWM_IMX_TPM_MOD_WIDTH - 1, 0)
  60 
  61 struct imx_tpm_pwm_chip {
  62         struct pwm_chip chip;
  63         struct clk *clk;
  64         void __iomem *base;
  65         struct mutex lock;
  66         u32 user_count;
  67         u32 enable_count;
  68         u32 real_period;
  69 };
  70 
  71 struct imx_tpm_pwm_param {
  72         u8 prescale;
  73         u32 mod;
  74         u32 val;
  75 };
  76 
  77 static inline struct imx_tpm_pwm_chip *
  78 to_imx_tpm_pwm_chip(struct pwm_chip *chip)
  79 {
  80         return container_of(chip, struct imx_tpm_pwm_chip, chip);
  81 }
  82 
  83 /*
  84  * This function determines for a given pwm_state *state that a consumer
  85  * might request the pwm_state *real_state that eventually is implemented
  86  * by the hardware and the necessary register values (in *p) to achieve
  87  * this.
  88  */
  89 static int pwm_imx_tpm_round_state(struct pwm_chip *chip,
  90                                    struct imx_tpm_pwm_param *p,
  91                                    struct pwm_state *real_state,
  92                                    const struct pwm_state *state)
  93 {
  94         struct imx_tpm_pwm_chip *tpm = to_imx_tpm_pwm_chip(chip);
  95         u32 rate, prescale, period_count, clock_unit;
  96         u64 tmp;
  97 
  98         rate = clk_get_rate(tpm->clk);
  99         tmp = (u64)state->period * rate;
 100         clock_unit = DIV_ROUND_CLOSEST_ULL(tmp, NSEC_PER_SEC);
 101         if (clock_unit <= PWM_IMX_TPM_MOD_MOD)
 102                 prescale = 0;
 103         else
 104                 prescale = ilog2(clock_unit) + 1 - PWM_IMX_TPM_MOD_WIDTH;
 105 
 106         if ((!FIELD_FIT(PWM_IMX_TPM_SC_PS, prescale)))
 107                 return -ERANGE;
 108         p->prescale = prescale;
 109 
 110         period_count = (clock_unit + ((1 << prescale) >> 1)) >> prescale;
 111         p->mod = period_count;
 112 
 113         /* calculate real period HW can support */
 114         tmp = (u64)period_count << prescale;
 115         tmp *= NSEC_PER_SEC;
 116         real_state->period = DIV_ROUND_CLOSEST_ULL(tmp, rate);
 117 
 118         /*
 119          * if eventually the PWM output is inactive, either
 120          * duty cycle is 0 or status is disabled, need to
 121          * make sure the output pin is inactive.
 122          */
 123         if (!state->enabled)
 124                 real_state->duty_cycle = 0;
 125         else
 126                 real_state->duty_cycle = state->duty_cycle;
 127 
 128         tmp = (u64)p->mod * real_state->duty_cycle;
 129         p->val = DIV_ROUND_CLOSEST_ULL(tmp, real_state->period);
 130 
 131         real_state->polarity = state->polarity;
 132         real_state->enabled = state->enabled;
 133 
 134         return 0;
 135 }
 136 
 137 static void pwm_imx_tpm_get_state(struct pwm_chip *chip,
 138                                   struct pwm_device *pwm,
 139                                   struct pwm_state *state)
 140 {
 141         struct imx_tpm_pwm_chip *tpm = to_imx_tpm_pwm_chip(chip);
 142         u32 rate, val, prescale;
 143         u64 tmp;
 144 
 145         /* get period */
 146         state->period = tpm->real_period;
 147 
 148         /* get duty cycle */
 149         rate = clk_get_rate(tpm->clk);
 150         val = readl(tpm->base + PWM_IMX_TPM_SC);
 151         prescale = FIELD_GET(PWM_IMX_TPM_SC_PS, val);
 152         tmp = readl(tpm->base + PWM_IMX_TPM_CnV(pwm->hwpwm));
 153         tmp = (tmp << prescale) * NSEC_PER_SEC;
 154         state->duty_cycle = DIV_ROUND_CLOSEST_ULL(tmp, rate);
 155 
 156         /* get polarity */
 157         val = readl(tpm->base + PWM_IMX_TPM_CnSC(pwm->hwpwm));
 158         if ((val & PWM_IMX_TPM_CnSC_ELS) == PWM_IMX_TPM_CnSC_ELS_INVERSED)
 159                 state->polarity = PWM_POLARITY_INVERSED;
 160         else
 161                 /*
 162                  * Assume reserved values (2b00 and 2b11) to yield
 163                  * normal polarity.
 164                  */
 165                 state->polarity = PWM_POLARITY_NORMAL;
 166 
 167         /* get channel status */
 168         state->enabled = FIELD_GET(PWM_IMX_TPM_CnSC_ELS, val) ? true : false;
 169 }
 170 
 171 /* this function is supposed to be called with mutex hold */
 172 static int pwm_imx_tpm_apply_hw(struct pwm_chip *chip,
 173                                 struct imx_tpm_pwm_param *p,
 174                                 struct pwm_state *state,
 175                                 struct pwm_device *pwm)
 176 {
 177         struct imx_tpm_pwm_chip *tpm = to_imx_tpm_pwm_chip(chip);
 178         bool period_update = false;
 179         bool duty_update = false;
 180         u32 val, cmod, cur_prescale;
 181         unsigned long timeout;
 182         struct pwm_state c;
 183 
 184         if (state->period != tpm->real_period) {
 185                 /*
 186                  * TPM counter is shared by multiple channels, so
 187                  * prescale and period can NOT be modified when
 188                  * there are multiple channels in use with different
 189                  * period settings.
 190                  */
 191                 if (tpm->user_count > 1)
 192                         return -EBUSY;
 193 
 194                 val = readl(tpm->base + PWM_IMX_TPM_SC);
 195                 cmod = FIELD_GET(PWM_IMX_TPM_SC_CMOD, val);
 196                 cur_prescale = FIELD_GET(PWM_IMX_TPM_SC_PS, val);
 197                 if (cmod && cur_prescale != p->prescale)
 198                         return -EBUSY;
 199 
 200                 /* set TPM counter prescale */
 201                 val &= ~PWM_IMX_TPM_SC_PS;
 202                 val |= FIELD_PREP(PWM_IMX_TPM_SC_PS, p->prescale);
 203                 writel(val, tpm->base + PWM_IMX_TPM_SC);
 204 
 205                 /*
 206                  * set period count:
 207                  * if the PWM is disabled (CMOD[1:0] = 2b00), then MOD register
 208                  * is updated when MOD register is written.
 209                  *
 210                  * if the PWM is enabled (CMOD[1:0] ≠ 2b00), the period length
 211                  * is latched into hardware when the next period starts.
 212                  */
 213                 writel(p->mod, tpm->base + PWM_IMX_TPM_MOD);
 214                 tpm->real_period = state->period;
 215                 period_update = true;
 216         }
 217 
 218         pwm_imx_tpm_get_state(chip, pwm, &c);
 219 
 220         /* polarity is NOT allowed to be changed if PWM is active */
 221         if (c.enabled && c.polarity != state->polarity)
 222                 return -EBUSY;
 223 
 224         if (state->duty_cycle != c.duty_cycle) {
 225                 /*
 226                  * set channel value:
 227                  * if the PWM is disabled (CMOD[1:0] = 2b00), then CnV register
 228                  * is updated when CnV register is written.
 229                  *
 230                  * if the PWM is enabled (CMOD[1:0] ≠ 2b00), the duty length
 231                  * is latched into hardware when the next period starts.
 232                  */
 233                 writel(p->val, tpm->base + PWM_IMX_TPM_CnV(pwm->hwpwm));
 234                 duty_update = true;
 235         }
 236 
 237         /* make sure MOD & CnV registers are updated */
 238         if (period_update || duty_update) {
 239                 timeout = jiffies + msecs_to_jiffies(tpm->real_period /
 240                                                      NSEC_PER_MSEC + 1);
 241                 while (readl(tpm->base + PWM_IMX_TPM_MOD) != p->mod
 242                        || readl(tpm->base + PWM_IMX_TPM_CnV(pwm->hwpwm))
 243                        != p->val) {
 244                         if (time_after(jiffies, timeout))
 245                                 return -ETIME;
 246                         cpu_relax();
 247                 }
 248         }
 249 
 250         /*
 251          * polarity settings will enabled/disable output status
 252          * immediately, so if the channel is disabled, need to
 253          * make sure MSA/MSB/ELS are set to 0 which means channel
 254          * disabled.
 255          */
 256         val = readl(tpm->base + PWM_IMX_TPM_CnSC(pwm->hwpwm));
 257         val &= ~(PWM_IMX_TPM_CnSC_ELS | PWM_IMX_TPM_CnSC_MSA |
 258                  PWM_IMX_TPM_CnSC_MSB);
 259         if (state->enabled) {
 260                 /*
 261                  * set polarity (for edge-aligned PWM modes)
 262                  *
 263                  * ELS[1:0] = 2b10 yields normal polarity behaviour,
 264                  * ELS[1:0] = 2b01 yields inversed polarity.
 265                  * The other values are reserved.
 266                  */
 267                 val |= PWM_IMX_TPM_CnSC_MSB;
 268                 val |= (state->polarity == PWM_POLARITY_NORMAL) ?
 269                         PWM_IMX_TPM_CnSC_ELS_NORMAL :
 270                         PWM_IMX_TPM_CnSC_ELS_INVERSED;
 271         }
 272         writel(val, tpm->base + PWM_IMX_TPM_CnSC(pwm->hwpwm));
 273 
 274         /* control the counter status */
 275         if (state->enabled != c.enabled) {
 276                 val = readl(tpm->base + PWM_IMX_TPM_SC);
 277                 if (state->enabled) {
 278                         if (++tpm->enable_count == 1)
 279                                 val |= PWM_IMX_TPM_SC_CMOD_INC_EVERY_CLK;
 280                 } else {
 281                         if (--tpm->enable_count == 0)
 282                                 val &= ~PWM_IMX_TPM_SC_CMOD;
 283                 }
 284                 writel(val, tpm->base + PWM_IMX_TPM_SC);
 285         }
 286 
 287         return 0;
 288 }
 289 
 290 static int pwm_imx_tpm_apply(struct pwm_chip *chip,
 291                              struct pwm_device *pwm,
 292                              const struct pwm_state *state)
 293 {
 294         struct imx_tpm_pwm_chip *tpm = to_imx_tpm_pwm_chip(chip);
 295         struct imx_tpm_pwm_param param;
 296         struct pwm_state real_state;
 297         int ret;
 298 
 299         ret = pwm_imx_tpm_round_state(chip, &param, &real_state, state);
 300         if (ret)
 301                 return ret;
 302 
 303         mutex_lock(&tpm->lock);
 304         ret = pwm_imx_tpm_apply_hw(chip, &param, &real_state, pwm);
 305         mutex_unlock(&tpm->lock);
 306 
 307         return ret;
 308 }
 309 
 310 static int pwm_imx_tpm_request(struct pwm_chip *chip, struct pwm_device *pwm)
 311 {
 312         struct imx_tpm_pwm_chip *tpm = to_imx_tpm_pwm_chip(chip);
 313 
 314         mutex_lock(&tpm->lock);
 315         tpm->user_count++;
 316         mutex_unlock(&tpm->lock);
 317 
 318         return 0;
 319 }
 320 
 321 static void pwm_imx_tpm_free(struct pwm_chip *chip, struct pwm_device *pwm)
 322 {
 323         struct imx_tpm_pwm_chip *tpm = to_imx_tpm_pwm_chip(chip);
 324 
 325         mutex_lock(&tpm->lock);
 326         tpm->user_count--;
 327         mutex_unlock(&tpm->lock);
 328 }
 329 
 330 static const struct pwm_ops imx_tpm_pwm_ops = {
 331         .request = pwm_imx_tpm_request,
 332         .free = pwm_imx_tpm_free,
 333         .get_state = pwm_imx_tpm_get_state,
 334         .apply = pwm_imx_tpm_apply,
 335         .owner = THIS_MODULE,
 336 };
 337 
 338 static int pwm_imx_tpm_probe(struct platform_device *pdev)
 339 {
 340         struct imx_tpm_pwm_chip *tpm;
 341         int ret;
 342         u32 val;
 343 
 344         tpm = devm_kzalloc(&pdev->dev, sizeof(*tpm), GFP_KERNEL);
 345         if (!tpm)
 346                 return -ENOMEM;
 347 
 348         platform_set_drvdata(pdev, tpm);
 349 
 350         tpm->base = devm_platform_ioremap_resource(pdev, 0);
 351         if (IS_ERR(tpm->base))
 352                 return PTR_ERR(tpm->base);
 353 
 354         tpm->clk = devm_clk_get(&pdev->dev, NULL);
 355         if (IS_ERR(tpm->clk)) {
 356                 ret = PTR_ERR(tpm->clk);
 357                 if (ret != -EPROBE_DEFER)
 358                         dev_err(&pdev->dev,
 359                                 "failed to get PWM clock: %d\n", ret);
 360                 return ret;
 361         }
 362 
 363         ret = clk_prepare_enable(tpm->clk);
 364         if (ret) {
 365                 dev_err(&pdev->dev,
 366                         "failed to prepare or enable clock: %d\n", ret);
 367                 return ret;
 368         }
 369 
 370         tpm->chip.dev = &pdev->dev;
 371         tpm->chip.ops = &imx_tpm_pwm_ops;
 372         tpm->chip.base = -1;
 373         tpm->chip.of_xlate = of_pwm_xlate_with_flags;
 374         tpm->chip.of_pwm_n_cells = 3;
 375 
 376         /* get number of channels */
 377         val = readl(tpm->base + PWM_IMX_TPM_PARAM);
 378         tpm->chip.npwm = FIELD_GET(PWM_IMX_TPM_PARAM_CHAN, val);
 379 
 380         mutex_init(&tpm->lock);
 381 
 382         ret = pwmchip_add(&tpm->chip);
 383         if (ret) {
 384                 dev_err(&pdev->dev, "failed to add PWM chip: %d\n", ret);
 385                 clk_disable_unprepare(tpm->clk);
 386         }
 387 
 388         return ret;
 389 }
 390 
 391 static int pwm_imx_tpm_remove(struct platform_device *pdev)
 392 {
 393         struct imx_tpm_pwm_chip *tpm = platform_get_drvdata(pdev);
 394         int ret = pwmchip_remove(&tpm->chip);
 395 
 396         clk_disable_unprepare(tpm->clk);
 397 
 398         return ret;
 399 }
 400 
 401 static int __maybe_unused pwm_imx_tpm_suspend(struct device *dev)
 402 {
 403         struct imx_tpm_pwm_chip *tpm = dev_get_drvdata(dev);
 404 
 405         if (tpm->enable_count > 0)
 406                 return -EBUSY;
 407 
 408         clk_disable_unprepare(tpm->clk);
 409 
 410         return 0;
 411 }
 412 
 413 static int __maybe_unused pwm_imx_tpm_resume(struct device *dev)
 414 {
 415         struct imx_tpm_pwm_chip *tpm = dev_get_drvdata(dev);
 416         int ret = 0;
 417 
 418         ret = clk_prepare_enable(tpm->clk);
 419         if (ret)
 420                 dev_err(dev,
 421                         "failed to prepare or enable clock: %d\n",
 422                         ret);
 423 
 424         return ret;
 425 }
 426 
 427 static SIMPLE_DEV_PM_OPS(imx_tpm_pwm_pm,
 428                          pwm_imx_tpm_suspend, pwm_imx_tpm_resume);
 429 
 430 static const struct of_device_id imx_tpm_pwm_dt_ids[] = {
 431         { .compatible = "fsl,imx7ulp-pwm", },
 432         { /* sentinel */ }
 433 };
 434 MODULE_DEVICE_TABLE(of, imx_tpm_pwm_dt_ids);
 435 
 436 static struct platform_driver imx_tpm_pwm_driver = {
 437         .driver = {
 438                 .name = "imx7ulp-tpm-pwm",
 439                 .of_match_table = imx_tpm_pwm_dt_ids,
 440                 .pm = &imx_tpm_pwm_pm,
 441         },
 442         .probe  = pwm_imx_tpm_probe,
 443         .remove = pwm_imx_tpm_remove,
 444 };
 445 module_platform_driver(imx_tpm_pwm_driver);
 446 
 447 MODULE_AUTHOR("Anson Huang <Anson.Huang@nxp.com>");
 448 MODULE_DESCRIPTION("i.MX TPM PWM Driver");
 449 MODULE_LICENSE("GPL v2");

/* [<][>][^][v][top][bottom][index][help] */