root/drivers/pwm/pwm-imx27.c

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

DEFINITIONS

This source file includes following definitions.
  1. pwm_imx27_clk_prepare_enable
  2. pwm_imx27_clk_disable_unprepare
  3. pwm_imx27_get_state
  4. pwm_imx27_sw_reset
  5. pwm_imx27_wait_fifo_slot
  6. pwm_imx27_apply
  7. pwm_imx27_probe
  8. pwm_imx27_remove

   1 // SPDX-License-Identifier: GPL-2.0
   2 /*
   3  * simple driver for PWM (Pulse Width Modulator) controller
   4  *
   5  * Derived from pxa PWM driver by eric miao <eric.miao@marvell.com>
   6  *
   7  * Limitations:
   8  * - When disabled the output is driven to 0 independent of the configured
   9  *   polarity.
  10  */
  11 
  12 #include <linux/bitfield.h>
  13 #include <linux/bitops.h>
  14 #include <linux/clk.h>
  15 #include <linux/delay.h>
  16 #include <linux/err.h>
  17 #include <linux/io.h>
  18 #include <linux/kernel.h>
  19 #include <linux/module.h>
  20 #include <linux/of.h>
  21 #include <linux/of_device.h>
  22 #include <linux/platform_device.h>
  23 #include <linux/pwm.h>
  24 #include <linux/slab.h>
  25 
  26 #define MX3_PWMCR                       0x00    /* PWM Control Register */
  27 #define MX3_PWMSR                       0x04    /* PWM Status Register */
  28 #define MX3_PWMSAR                      0x0C    /* PWM Sample Register */
  29 #define MX3_PWMPR                       0x10    /* PWM Period Register */
  30 
  31 #define MX3_PWMCR_FWM                   GENMASK(27, 26)
  32 #define MX3_PWMCR_STOPEN                BIT(25)
  33 #define MX3_PWMCR_DOZEN                 BIT(24)
  34 #define MX3_PWMCR_WAITEN                BIT(23)
  35 #define MX3_PWMCR_DBGEN                 BIT(22)
  36 #define MX3_PWMCR_BCTR                  BIT(21)
  37 #define MX3_PWMCR_HCTR                  BIT(20)
  38 
  39 #define MX3_PWMCR_POUTC                 GENMASK(19, 18)
  40 #define MX3_PWMCR_POUTC_NORMAL          0
  41 #define MX3_PWMCR_POUTC_INVERTED        1
  42 #define MX3_PWMCR_POUTC_OFF             2
  43 
  44 #define MX3_PWMCR_CLKSRC                GENMASK(17, 16)
  45 #define MX3_PWMCR_CLKSRC_OFF            0
  46 #define MX3_PWMCR_CLKSRC_IPG            1
  47 #define MX3_PWMCR_CLKSRC_IPG_HIGH       2
  48 #define MX3_PWMCR_CLKSRC_IPG_32K        3
  49 
  50 #define MX3_PWMCR_PRESCALER             GENMASK(15, 4)
  51 
  52 #define MX3_PWMCR_SWR                   BIT(3)
  53 
  54 #define MX3_PWMCR_REPEAT                GENMASK(2, 1)
  55 #define MX3_PWMCR_REPEAT_1X             0
  56 #define MX3_PWMCR_REPEAT_2X             1
  57 #define MX3_PWMCR_REPEAT_4X             2
  58 #define MX3_PWMCR_REPEAT_8X             3
  59 
  60 #define MX3_PWMCR_EN                    BIT(0)
  61 
  62 #define MX3_PWMSR_FWE                   BIT(6)
  63 #define MX3_PWMSR_CMP                   BIT(5)
  64 #define MX3_PWMSR_ROV                   BIT(4)
  65 #define MX3_PWMSR_FE                    BIT(3)
  66 
  67 #define MX3_PWMSR_FIFOAV                GENMASK(2, 0)
  68 #define MX3_PWMSR_FIFOAV_EMPTY          0
  69 #define MX3_PWMSR_FIFOAV_1WORD          1
  70 #define MX3_PWMSR_FIFOAV_2WORDS         2
  71 #define MX3_PWMSR_FIFOAV_3WORDS         3
  72 #define MX3_PWMSR_FIFOAV_4WORDS         4
  73 
  74 #define MX3_PWMCR_PRESCALER_SET(x)      FIELD_PREP(MX3_PWMCR_PRESCALER, (x) - 1)
  75 #define MX3_PWMCR_PRESCALER_GET(x)      (FIELD_GET(MX3_PWMCR_PRESCALER, \
  76                                                    (x)) + 1)
  77 
  78 #define MX3_PWM_SWR_LOOP                5
  79 
  80 /* PWMPR register value of 0xffff has the same effect as 0xfffe */
  81 #define MX3_PWMPR_MAX                   0xfffe
  82 
  83 struct pwm_imx27_chip {
  84         struct clk      *clk_ipg;
  85         struct clk      *clk_per;
  86         void __iomem    *mmio_base;
  87         struct pwm_chip chip;
  88 };
  89 
  90 #define to_pwm_imx27_chip(chip) container_of(chip, struct pwm_imx27_chip, chip)
  91 
  92 static int pwm_imx27_clk_prepare_enable(struct pwm_chip *chip)
  93 {
  94         struct pwm_imx27_chip *imx = to_pwm_imx27_chip(chip);
  95         int ret;
  96 
  97         ret = clk_prepare_enable(imx->clk_ipg);
  98         if (ret)
  99                 return ret;
 100 
 101         ret = clk_prepare_enable(imx->clk_per);
 102         if (ret) {
 103                 clk_disable_unprepare(imx->clk_ipg);
 104                 return ret;
 105         }
 106 
 107         return 0;
 108 }
 109 
 110 static void pwm_imx27_clk_disable_unprepare(struct pwm_chip *chip)
 111 {
 112         struct pwm_imx27_chip *imx = to_pwm_imx27_chip(chip);
 113 
 114         clk_disable_unprepare(imx->clk_per);
 115         clk_disable_unprepare(imx->clk_ipg);
 116 }
 117 
 118 static void pwm_imx27_get_state(struct pwm_chip *chip,
 119                                 struct pwm_device *pwm, struct pwm_state *state)
 120 {
 121         struct pwm_imx27_chip *imx = to_pwm_imx27_chip(chip);
 122         u32 period, prescaler, pwm_clk, val;
 123         u64 tmp;
 124         int ret;
 125 
 126         ret = pwm_imx27_clk_prepare_enable(chip);
 127         if (ret < 0)
 128                 return;
 129 
 130         val = readl(imx->mmio_base + MX3_PWMCR);
 131 
 132         if (val & MX3_PWMCR_EN)
 133                 state->enabled = true;
 134         else
 135                 state->enabled = false;
 136 
 137         switch (FIELD_GET(MX3_PWMCR_POUTC, val)) {
 138         case MX3_PWMCR_POUTC_NORMAL:
 139                 state->polarity = PWM_POLARITY_NORMAL;
 140                 break;
 141         case MX3_PWMCR_POUTC_INVERTED:
 142                 state->polarity = PWM_POLARITY_INVERSED;
 143                 break;
 144         default:
 145                 dev_warn(chip->dev, "can't set polarity, output disconnected");
 146         }
 147 
 148         prescaler = MX3_PWMCR_PRESCALER_GET(val);
 149         pwm_clk = clk_get_rate(imx->clk_per);
 150         pwm_clk = DIV_ROUND_CLOSEST_ULL(pwm_clk, prescaler);
 151         val = readl(imx->mmio_base + MX3_PWMPR);
 152         period = val >= MX3_PWMPR_MAX ? MX3_PWMPR_MAX : val;
 153 
 154         /* PWMOUT (Hz) = PWMCLK / (PWMPR + 2) */
 155         tmp = NSEC_PER_SEC * (u64)(period + 2);
 156         state->period = DIV_ROUND_CLOSEST_ULL(tmp, pwm_clk);
 157 
 158         /* PWMSAR can be read only if PWM is enabled */
 159         if (state->enabled) {
 160                 val = readl(imx->mmio_base + MX3_PWMSAR);
 161                 tmp = NSEC_PER_SEC * (u64)(val);
 162                 state->duty_cycle = DIV_ROUND_CLOSEST_ULL(tmp, pwm_clk);
 163         } else {
 164                 state->duty_cycle = 0;
 165         }
 166 
 167         if (!state->enabled)
 168                 pwm_imx27_clk_disable_unprepare(chip);
 169 }
 170 
 171 static void pwm_imx27_sw_reset(struct pwm_chip *chip)
 172 {
 173         struct pwm_imx27_chip *imx = to_pwm_imx27_chip(chip);
 174         struct device *dev = chip->dev;
 175         int wait_count = 0;
 176         u32 cr;
 177 
 178         writel(MX3_PWMCR_SWR, imx->mmio_base + MX3_PWMCR);
 179         do {
 180                 usleep_range(200, 1000);
 181                 cr = readl(imx->mmio_base + MX3_PWMCR);
 182         } while ((cr & MX3_PWMCR_SWR) &&
 183                  (wait_count++ < MX3_PWM_SWR_LOOP));
 184 
 185         if (cr & MX3_PWMCR_SWR)
 186                 dev_warn(dev, "software reset timeout\n");
 187 }
 188 
 189 static void pwm_imx27_wait_fifo_slot(struct pwm_chip *chip,
 190                                      struct pwm_device *pwm)
 191 {
 192         struct pwm_imx27_chip *imx = to_pwm_imx27_chip(chip);
 193         struct device *dev = chip->dev;
 194         unsigned int period_ms;
 195         int fifoav;
 196         u32 sr;
 197 
 198         sr = readl(imx->mmio_base + MX3_PWMSR);
 199         fifoav = FIELD_GET(MX3_PWMSR_FIFOAV, sr);
 200         if (fifoav == MX3_PWMSR_FIFOAV_4WORDS) {
 201                 period_ms = DIV_ROUND_UP(pwm_get_period(pwm),
 202                                          NSEC_PER_MSEC);
 203                 msleep(period_ms);
 204 
 205                 sr = readl(imx->mmio_base + MX3_PWMSR);
 206                 if (fifoav == FIELD_GET(MX3_PWMSR_FIFOAV, sr))
 207                         dev_warn(dev, "there is no free FIFO slot\n");
 208         }
 209 }
 210 
 211 static int pwm_imx27_apply(struct pwm_chip *chip, struct pwm_device *pwm,
 212                            const struct pwm_state *state)
 213 {
 214         unsigned long period_cycles, duty_cycles, prescale;
 215         struct pwm_imx27_chip *imx = to_pwm_imx27_chip(chip);
 216         struct pwm_state cstate;
 217         unsigned long long c;
 218         int ret;
 219         u32 cr;
 220 
 221         pwm_get_state(pwm, &cstate);
 222 
 223         if (state->enabled) {
 224                 c = clk_get_rate(imx->clk_per);
 225                 c *= state->period;
 226 
 227                 do_div(c, 1000000000);
 228                 period_cycles = c;
 229 
 230                 prescale = period_cycles / 0x10000 + 1;
 231 
 232                 period_cycles /= prescale;
 233                 c = (unsigned long long)period_cycles * state->duty_cycle;
 234                 do_div(c, state->period);
 235                 duty_cycles = c;
 236 
 237                 /*
 238                  * according to imx pwm RM, the real period value should be
 239                  * PERIOD value in PWMPR plus 2.
 240                  */
 241                 if (period_cycles > 2)
 242                         period_cycles -= 2;
 243                 else
 244                         period_cycles = 0;
 245 
 246                 /*
 247                  * Wait for a free FIFO slot if the PWM is already enabled, and
 248                  * flush the FIFO if the PWM was disabled and is about to be
 249                  * enabled.
 250                  */
 251                 if (cstate.enabled) {
 252                         pwm_imx27_wait_fifo_slot(chip, pwm);
 253                 } else {
 254                         ret = pwm_imx27_clk_prepare_enable(chip);
 255                         if (ret)
 256                                 return ret;
 257 
 258                         pwm_imx27_sw_reset(chip);
 259                 }
 260 
 261                 writel(duty_cycles, imx->mmio_base + MX3_PWMSAR);
 262                 writel(period_cycles, imx->mmio_base + MX3_PWMPR);
 263 
 264                 cr = MX3_PWMCR_PRESCALER_SET(prescale) |
 265                      MX3_PWMCR_STOPEN | MX3_PWMCR_DOZEN | MX3_PWMCR_WAITEN |
 266                      FIELD_PREP(MX3_PWMCR_CLKSRC, MX3_PWMCR_CLKSRC_IPG_HIGH) |
 267                      MX3_PWMCR_DBGEN | MX3_PWMCR_EN;
 268 
 269                 if (state->polarity == PWM_POLARITY_INVERSED)
 270                         cr |= FIELD_PREP(MX3_PWMCR_POUTC,
 271                                         MX3_PWMCR_POUTC_INVERTED);
 272 
 273                 writel(cr, imx->mmio_base + MX3_PWMCR);
 274         } else if (cstate.enabled) {
 275                 writel(0, imx->mmio_base + MX3_PWMCR);
 276 
 277                 pwm_imx27_clk_disable_unprepare(chip);
 278         }
 279 
 280         return 0;
 281 }
 282 
 283 static const struct pwm_ops pwm_imx27_ops = {
 284         .apply = pwm_imx27_apply,
 285         .get_state = pwm_imx27_get_state,
 286         .owner = THIS_MODULE,
 287 };
 288 
 289 static const struct of_device_id pwm_imx27_dt_ids[] = {
 290         { .compatible = "fsl,imx27-pwm", },
 291         { /* sentinel */ }
 292 };
 293 MODULE_DEVICE_TABLE(of, pwm_imx27_dt_ids);
 294 
 295 static int pwm_imx27_probe(struct platform_device *pdev)
 296 {
 297         struct pwm_imx27_chip *imx;
 298 
 299         imx = devm_kzalloc(&pdev->dev, sizeof(*imx), GFP_KERNEL);
 300         if (imx == NULL)
 301                 return -ENOMEM;
 302 
 303         platform_set_drvdata(pdev, imx);
 304 
 305         imx->clk_ipg = devm_clk_get(&pdev->dev, "ipg");
 306         if (IS_ERR(imx->clk_ipg)) {
 307                 dev_err(&pdev->dev, "getting ipg clock failed with %ld\n",
 308                                 PTR_ERR(imx->clk_ipg));
 309                 return PTR_ERR(imx->clk_ipg);
 310         }
 311 
 312         imx->clk_per = devm_clk_get(&pdev->dev, "per");
 313         if (IS_ERR(imx->clk_per)) {
 314                 int ret = PTR_ERR(imx->clk_per);
 315 
 316                 if (ret != -EPROBE_DEFER)
 317                         dev_err(&pdev->dev,
 318                                 "failed to get peripheral clock: %d\n",
 319                                 ret);
 320 
 321                 return ret;
 322         }
 323 
 324         imx->chip.ops = &pwm_imx27_ops;
 325         imx->chip.dev = &pdev->dev;
 326         imx->chip.base = -1;
 327         imx->chip.npwm = 1;
 328 
 329         imx->chip.of_xlate = of_pwm_xlate_with_flags;
 330         imx->chip.of_pwm_n_cells = 3;
 331 
 332         imx->mmio_base = devm_platform_ioremap_resource(pdev, 0);
 333         if (IS_ERR(imx->mmio_base))
 334                 return PTR_ERR(imx->mmio_base);
 335 
 336         return pwmchip_add(&imx->chip);
 337 }
 338 
 339 static int pwm_imx27_remove(struct platform_device *pdev)
 340 {
 341         struct pwm_imx27_chip *imx;
 342 
 343         imx = platform_get_drvdata(pdev);
 344 
 345         pwm_imx27_clk_disable_unprepare(&imx->chip);
 346 
 347         return pwmchip_remove(&imx->chip);
 348 }
 349 
 350 static struct platform_driver imx_pwm_driver = {
 351         .driver = {
 352                 .name = "pwm-imx27",
 353                 .of_match_table = pwm_imx27_dt_ids,
 354         },
 355         .probe = pwm_imx27_probe,
 356         .remove = pwm_imx27_remove,
 357 };
 358 module_platform_driver(imx_pwm_driver);
 359 
 360 MODULE_LICENSE("GPL v2");
 361 MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>");

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