root/drivers/pwm/pwm-omap-dmtimer.c

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

DEFINITIONS

This source file includes following definitions.
  1. to_pwm_omap_dmtimer_chip
  2. pwm_omap_dmtimer_get_clock_cycles
  3. pwm_omap_dmtimer_start
  4. pwm_omap_dmtimer_enable
  5. pwm_omap_dmtimer_disable
  6. pwm_omap_dmtimer_config
  7. pwm_omap_dmtimer_set_polarity
  8. pwm_omap_dmtimer_probe
  9. pwm_omap_dmtimer_remove

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * Copyright (c) 2015 Neil Armstrong <narmstrong@baylibre.com>
   4  * Copyright (c) 2014 Joachim Eastwood <manabian@gmail.com>
   5  * Copyright (c) 2012 NeilBrown <neilb@suse.de>
   6  * Heavily based on earlier code which is:
   7  * Copyright (c) 2010 Grant Erickson <marathon96@gmail.com>
   8  *
   9  * Also based on pwm-samsung.c
  10  *
  11  * Description:
  12  *   This file is the core OMAP support for the generic, Linux
  13  *   PWM driver / controller, using the OMAP's dual-mode timers.
  14  */
  15 
  16 #include <linux/clk.h>
  17 #include <linux/err.h>
  18 #include <linux/kernel.h>
  19 #include <linux/module.h>
  20 #include <linux/mutex.h>
  21 #include <linux/of.h>
  22 #include <linux/of_platform.h>
  23 #include <linux/platform_data/dmtimer-omap.h>
  24 #include <linux/platform_data/pwm_omap_dmtimer.h>
  25 #include <linux/platform_device.h>
  26 #include <linux/pm_runtime.h>
  27 #include <linux/pwm.h>
  28 #include <linux/slab.h>
  29 #include <linux/time.h>
  30 
  31 #define DM_TIMER_LOAD_MIN 0xfffffffe
  32 #define DM_TIMER_MAX      0xffffffff
  33 
  34 struct pwm_omap_dmtimer_chip {
  35         struct pwm_chip chip;
  36         struct mutex mutex;
  37         pwm_omap_dmtimer *dm_timer;
  38         const struct omap_dm_timer_ops *pdata;
  39         struct platform_device *dm_timer_pdev;
  40 };
  41 
  42 static inline struct pwm_omap_dmtimer_chip *
  43 to_pwm_omap_dmtimer_chip(struct pwm_chip *chip)
  44 {
  45         return container_of(chip, struct pwm_omap_dmtimer_chip, chip);
  46 }
  47 
  48 static u32 pwm_omap_dmtimer_get_clock_cycles(unsigned long clk_rate, int ns)
  49 {
  50         return DIV_ROUND_CLOSEST_ULL((u64)clk_rate * ns, NSEC_PER_SEC);
  51 }
  52 
  53 static void pwm_omap_dmtimer_start(struct pwm_omap_dmtimer_chip *omap)
  54 {
  55         /*
  56          * According to OMAP 4 TRM section 22.2.4.10 the counter should be
  57          * started at 0xFFFFFFFE when overflow and match is used to ensure
  58          * that the PWM line is toggled on the first event.
  59          *
  60          * Note that omap_dm_timer_enable/disable is for register access and
  61          * not the timer counter itself.
  62          */
  63         omap->pdata->enable(omap->dm_timer);
  64         omap->pdata->write_counter(omap->dm_timer, DM_TIMER_LOAD_MIN);
  65         omap->pdata->disable(omap->dm_timer);
  66 
  67         omap->pdata->start(omap->dm_timer);
  68 }
  69 
  70 static int pwm_omap_dmtimer_enable(struct pwm_chip *chip,
  71                                    struct pwm_device *pwm)
  72 {
  73         struct pwm_omap_dmtimer_chip *omap = to_pwm_omap_dmtimer_chip(chip);
  74 
  75         mutex_lock(&omap->mutex);
  76         pwm_omap_dmtimer_start(omap);
  77         mutex_unlock(&omap->mutex);
  78 
  79         return 0;
  80 }
  81 
  82 static void pwm_omap_dmtimer_disable(struct pwm_chip *chip,
  83                                      struct pwm_device *pwm)
  84 {
  85         struct pwm_omap_dmtimer_chip *omap = to_pwm_omap_dmtimer_chip(chip);
  86 
  87         mutex_lock(&omap->mutex);
  88         omap->pdata->stop(omap->dm_timer);
  89         mutex_unlock(&omap->mutex);
  90 }
  91 
  92 static int pwm_omap_dmtimer_config(struct pwm_chip *chip,
  93                                    struct pwm_device *pwm,
  94                                    int duty_ns, int period_ns)
  95 {
  96         struct pwm_omap_dmtimer_chip *omap = to_pwm_omap_dmtimer_chip(chip);
  97         u32 period_cycles, duty_cycles;
  98         u32 load_value, match_value;
  99         struct clk *fclk;
 100         unsigned long clk_rate;
 101         bool timer_active;
 102 
 103         dev_dbg(chip->dev, "requested duty cycle: %d ns, period: %d ns\n",
 104                 duty_ns, period_ns);
 105 
 106         mutex_lock(&omap->mutex);
 107         if (duty_ns == pwm_get_duty_cycle(pwm) &&
 108             period_ns == pwm_get_period(pwm)) {
 109                 /* No change - don't cause any transients. */
 110                 mutex_unlock(&omap->mutex);
 111                 return 0;
 112         }
 113 
 114         fclk = omap->pdata->get_fclk(omap->dm_timer);
 115         if (!fclk) {
 116                 dev_err(chip->dev, "invalid pmtimer fclk\n");
 117                 goto err_einval;
 118         }
 119 
 120         clk_rate = clk_get_rate(fclk);
 121         if (!clk_rate) {
 122                 dev_err(chip->dev, "invalid pmtimer fclk rate\n");
 123                 goto err_einval;
 124         }
 125 
 126         dev_dbg(chip->dev, "clk rate: %luHz\n", clk_rate);
 127 
 128         /*
 129          * Calculate the appropriate load and match values based on the
 130          * specified period and duty cycle. The load value determines the
 131          * period time and the match value determines the duty time.
 132          *
 133          * The period lasts for (DM_TIMER_MAX-load_value+1) clock cycles.
 134          * Similarly, the active time lasts (match_value-load_value+1) cycles.
 135          * The non-active time is the remainder: (DM_TIMER_MAX-match_value)
 136          * clock cycles.
 137          *
 138          * NOTE: It is required that: load_value <= match_value < DM_TIMER_MAX
 139          *
 140          * References:
 141          *   OMAP4430/60/70 TRM sections 22.2.4.10 and 22.2.4.11
 142          *   AM335x Sitara TRM sections 20.1.3.5 and 20.1.3.6
 143          */
 144         period_cycles = pwm_omap_dmtimer_get_clock_cycles(clk_rate, period_ns);
 145         duty_cycles = pwm_omap_dmtimer_get_clock_cycles(clk_rate, duty_ns);
 146 
 147         if (period_cycles < 2) {
 148                 dev_info(chip->dev,
 149                          "period %d ns too short for clock rate %lu Hz\n",
 150                          period_ns, clk_rate);
 151                 goto err_einval;
 152         }
 153 
 154         if (duty_cycles < 1) {
 155                 dev_dbg(chip->dev,
 156                         "duty cycle %d ns is too short for clock rate %lu Hz\n",
 157                         duty_ns, clk_rate);
 158                 dev_dbg(chip->dev, "using minimum of 1 clock cycle\n");
 159                 duty_cycles = 1;
 160         } else if (duty_cycles >= period_cycles) {
 161                 dev_dbg(chip->dev,
 162                         "duty cycle %d ns is too long for period %d ns at clock rate %lu Hz\n",
 163                         duty_ns, period_ns, clk_rate);
 164                 dev_dbg(chip->dev, "using maximum of 1 clock cycle less than period\n");
 165                 duty_cycles = period_cycles - 1;
 166         }
 167 
 168         dev_dbg(chip->dev, "effective duty cycle: %lld ns, period: %lld ns\n",
 169                 DIV_ROUND_CLOSEST_ULL((u64)NSEC_PER_SEC * duty_cycles,
 170                                       clk_rate),
 171                 DIV_ROUND_CLOSEST_ULL((u64)NSEC_PER_SEC * period_cycles,
 172                                       clk_rate));
 173 
 174         load_value = (DM_TIMER_MAX - period_cycles) + 1;
 175         match_value = load_value + duty_cycles - 1;
 176 
 177         /*
 178          * We MUST stop the associated dual-mode timer before attempting to
 179          * write its registers, but calls to omap_dm_timer_start/stop must
 180          * be balanced so check if timer is active before calling timer_stop.
 181          */
 182         timer_active = pm_runtime_active(&omap->dm_timer_pdev->dev);
 183         if (timer_active)
 184                 omap->pdata->stop(omap->dm_timer);
 185 
 186         omap->pdata->set_load(omap->dm_timer, true, load_value);
 187         omap->pdata->set_match(omap->dm_timer, true, match_value);
 188 
 189         dev_dbg(chip->dev, "load value: %#08x (%d), match value: %#08x (%d)\n",
 190                 load_value, load_value, match_value, match_value);
 191 
 192         omap->pdata->set_pwm(omap->dm_timer,
 193                               pwm_get_polarity(pwm) == PWM_POLARITY_INVERSED,
 194                               true,
 195                               PWM_OMAP_DMTIMER_TRIGGER_OVERFLOW_AND_COMPARE);
 196 
 197         /* If config was called while timer was running it must be reenabled. */
 198         if (timer_active)
 199                 pwm_omap_dmtimer_start(omap);
 200 
 201         mutex_unlock(&omap->mutex);
 202 
 203         return 0;
 204 
 205 err_einval:
 206         mutex_unlock(&omap->mutex);
 207 
 208         return -EINVAL;
 209 }
 210 
 211 static int pwm_omap_dmtimer_set_polarity(struct pwm_chip *chip,
 212                                          struct pwm_device *pwm,
 213                                          enum pwm_polarity polarity)
 214 {
 215         struct pwm_omap_dmtimer_chip *omap = to_pwm_omap_dmtimer_chip(chip);
 216 
 217         /*
 218          * PWM core will not call set_polarity while PWM is enabled so it's
 219          * safe to reconfigure the timer here without stopping it first.
 220          */
 221         mutex_lock(&omap->mutex);
 222         omap->pdata->set_pwm(omap->dm_timer,
 223                               polarity == PWM_POLARITY_INVERSED,
 224                               true,
 225                               PWM_OMAP_DMTIMER_TRIGGER_OVERFLOW_AND_COMPARE);
 226         mutex_unlock(&omap->mutex);
 227 
 228         return 0;
 229 }
 230 
 231 static const struct pwm_ops pwm_omap_dmtimer_ops = {
 232         .enable = pwm_omap_dmtimer_enable,
 233         .disable = pwm_omap_dmtimer_disable,
 234         .config = pwm_omap_dmtimer_config,
 235         .set_polarity = pwm_omap_dmtimer_set_polarity,
 236         .owner = THIS_MODULE,
 237 };
 238 
 239 static int pwm_omap_dmtimer_probe(struct platform_device *pdev)
 240 {
 241         struct device_node *np = pdev->dev.of_node;
 242         struct device_node *timer;
 243         struct platform_device *timer_pdev;
 244         struct pwm_omap_dmtimer_chip *omap;
 245         struct dmtimer_platform_data *timer_pdata;
 246         const struct omap_dm_timer_ops *pdata;
 247         pwm_omap_dmtimer *dm_timer;
 248         u32 v;
 249         int ret = 0;
 250 
 251         timer = of_parse_phandle(np, "ti,timers", 0);
 252         if (!timer)
 253                 return -ENODEV;
 254 
 255         timer_pdev = of_find_device_by_node(timer);
 256         if (!timer_pdev) {
 257                 dev_err(&pdev->dev, "Unable to find Timer pdev\n");
 258                 ret = -ENODEV;
 259                 goto err_find_timer_pdev;
 260         }
 261 
 262         timer_pdata = dev_get_platdata(&timer_pdev->dev);
 263         if (!timer_pdata) {
 264                 dev_dbg(&pdev->dev,
 265                          "dmtimer pdata structure NULL, deferring probe\n");
 266                 ret = -EPROBE_DEFER;
 267                 goto err_platdata;
 268         }
 269 
 270         pdata = timer_pdata->timer_ops;
 271 
 272         if (!pdata || !pdata->request_by_node ||
 273             !pdata->free ||
 274             !pdata->enable ||
 275             !pdata->disable ||
 276             !pdata->get_fclk ||
 277             !pdata->start ||
 278             !pdata->stop ||
 279             !pdata->set_load ||
 280             !pdata->set_match ||
 281             !pdata->set_pwm ||
 282             !pdata->set_prescaler ||
 283             !pdata->write_counter) {
 284                 dev_err(&pdev->dev, "Incomplete dmtimer pdata structure\n");
 285                 ret = -EINVAL;
 286                 goto err_platdata;
 287         }
 288 
 289         if (!of_get_property(timer, "ti,timer-pwm", NULL)) {
 290                 dev_err(&pdev->dev, "Missing ti,timer-pwm capability\n");
 291                 ret = -ENODEV;
 292                 goto err_timer_property;
 293         }
 294 
 295         dm_timer = pdata->request_by_node(timer);
 296         if (!dm_timer) {
 297                 ret = -EPROBE_DEFER;
 298                 goto err_request_timer;
 299         }
 300 
 301         omap = devm_kzalloc(&pdev->dev, sizeof(*omap), GFP_KERNEL);
 302         if (!omap) {
 303                 ret = -ENOMEM;
 304                 goto err_alloc_omap;
 305         }
 306 
 307         omap->pdata = pdata;
 308         omap->dm_timer = dm_timer;
 309         omap->dm_timer_pdev = timer_pdev;
 310 
 311         /*
 312          * Ensure that the timer is stopped before we allow PWM core to call
 313          * pwm_enable.
 314          */
 315         if (pm_runtime_active(&omap->dm_timer_pdev->dev))
 316                 omap->pdata->stop(omap->dm_timer);
 317 
 318         if (!of_property_read_u32(pdev->dev.of_node, "ti,prescaler", &v))
 319                 omap->pdata->set_prescaler(omap->dm_timer, v);
 320 
 321         /* setup dmtimer clock source */
 322         if (!of_property_read_u32(pdev->dev.of_node, "ti,clock-source", &v))
 323                 omap->pdata->set_source(omap->dm_timer, v);
 324 
 325         omap->chip.dev = &pdev->dev;
 326         omap->chip.ops = &pwm_omap_dmtimer_ops;
 327         omap->chip.base = -1;
 328         omap->chip.npwm = 1;
 329         omap->chip.of_xlate = of_pwm_xlate_with_flags;
 330         omap->chip.of_pwm_n_cells = 3;
 331 
 332         mutex_init(&omap->mutex);
 333 
 334         ret = pwmchip_add(&omap->chip);
 335         if (ret < 0) {
 336                 dev_err(&pdev->dev, "failed to register PWM\n");
 337                 goto err_pwmchip_add;
 338         }
 339 
 340         of_node_put(timer);
 341 
 342         platform_set_drvdata(pdev, omap);
 343 
 344         return 0;
 345 
 346 err_pwmchip_add:
 347 
 348         /*
 349          * *omap is allocated using devm_kzalloc,
 350          * so no free necessary here
 351          */
 352 err_alloc_omap:
 353 
 354         pdata->free(dm_timer);
 355 err_request_timer:
 356 
 357 err_timer_property:
 358 err_platdata:
 359 
 360         put_device(&timer_pdev->dev);
 361 err_find_timer_pdev:
 362 
 363         of_node_put(timer);
 364 
 365         return ret;
 366 }
 367 
 368 static int pwm_omap_dmtimer_remove(struct platform_device *pdev)
 369 {
 370         struct pwm_omap_dmtimer_chip *omap = platform_get_drvdata(pdev);
 371         int ret;
 372 
 373         ret = pwmchip_remove(&omap->chip);
 374         if (ret)
 375                 return ret;
 376 
 377         if (pm_runtime_active(&omap->dm_timer_pdev->dev))
 378                 omap->pdata->stop(omap->dm_timer);
 379 
 380         omap->pdata->free(omap->dm_timer);
 381 
 382         put_device(&omap->dm_timer_pdev->dev);
 383 
 384         mutex_destroy(&omap->mutex);
 385 
 386         return 0;
 387 }
 388 
 389 static const struct of_device_id pwm_omap_dmtimer_of_match[] = {
 390         {.compatible = "ti,omap-dmtimer-pwm"},
 391         {}
 392 };
 393 MODULE_DEVICE_TABLE(of, pwm_omap_dmtimer_of_match);
 394 
 395 static struct platform_driver pwm_omap_dmtimer_driver = {
 396         .driver = {
 397                 .name = "omap-dmtimer-pwm",
 398                 .of_match_table = of_match_ptr(pwm_omap_dmtimer_of_match),
 399         },
 400         .probe = pwm_omap_dmtimer_probe,
 401         .remove = pwm_omap_dmtimer_remove,
 402 };
 403 module_platform_driver(pwm_omap_dmtimer_driver);
 404 
 405 MODULE_AUTHOR("Grant Erickson <marathon96@gmail.com>");
 406 MODULE_AUTHOR("NeilBrown <neilb@suse.de>");
 407 MODULE_AUTHOR("Neil Armstrong <narmstrong@baylibre.com>");
 408 MODULE_LICENSE("GPL v2");
 409 MODULE_DESCRIPTION("OMAP PWM Driver using Dual-mode Timers");

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