Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Copyright (c) 2015 Neil Armstrong <narmstrong@baylibre.com>
0004  * Copyright (c) 2014 Joachim Eastwood <manabian@gmail.com>
0005  * Copyright (c) 2012 NeilBrown <neilb@suse.de>
0006  * Heavily based on earlier code which is:
0007  * Copyright (c) 2010 Grant Erickson <marathon96@gmail.com>
0008  *
0009  * Also based on pwm-samsung.c
0010  *
0011  * Description:
0012  *   This file is the core OMAP support for the generic, Linux
0013  *   PWM driver / controller, using the OMAP's dual-mode timers
0014  *   with a timer counter that goes up. When it overflows it gets
0015  *   reloaded with the load value and the pwm output goes up.
0016  *   When counter matches with match register, the output goes down.
0017  *   Reference Manual: https://www.ti.com/lit/ug/spruh73q/spruh73q.pdf
0018  *
0019  * Limitations:
0020  * - When PWM is stopped, timer counter gets stopped immediately. This
0021  *   doesn't allow the current PWM period to complete and stops abruptly.
0022  * - When PWM is running and changing both duty cycle and period,
0023  *   we cannot prevent in software that the output might produce
0024  *   a period with mixed settings. Especially when period/duty_cyle
0025  *   is updated while the pwm pin is high, current pwm period/duty_cycle
0026  *   can get updated as below based on the current timer counter:
0027  *      - period for current cycle =  current_period + new period
0028  *      - duty_cycle for current period = current period + new duty_cycle.
0029  * - PWM OMAP DM timer cannot change the polarity when pwm is active. When
0030  *   user requests a change in polarity when in active state:
0031  *  - PWM is stopped abruptly(without completing the current cycle)
0032  *  - Polarity is changed
0033  *  - A fresh cycle is started.
0034  */
0035 
0036 #include <linux/clk.h>
0037 #include <linux/err.h>
0038 #include <linux/kernel.h>
0039 #include <linux/module.h>
0040 #include <linux/mutex.h>
0041 #include <linux/of.h>
0042 #include <linux/of_platform.h>
0043 #include <clocksource/timer-ti-dm.h>
0044 #include <linux/platform_data/dmtimer-omap.h>
0045 #include <linux/platform_device.h>
0046 #include <linux/pm_runtime.h>
0047 #include <linux/pwm.h>
0048 #include <linux/slab.h>
0049 #include <linux/time.h>
0050 
0051 #define DM_TIMER_LOAD_MIN 0xfffffffe
0052 #define DM_TIMER_MAX      0xffffffff
0053 
0054 /**
0055  * struct pwm_omap_dmtimer_chip - Structure representing a pwm chip
0056  *                corresponding to omap dmtimer.
0057  * @chip:       PWM chip structure representing PWM controller
0058  * @mutex:      Mutex to protect pwm apply state
0059  * @dm_timer:       Pointer to omap dm timer.
0060  * @pdata:      Pointer to omap dm timer ops.
0061  * @dm_timer_pdev:  Pointer to omap dm timer platform device
0062  */
0063 struct pwm_omap_dmtimer_chip {
0064     struct pwm_chip chip;
0065     /* Mutex to protect pwm apply state */
0066     struct mutex mutex;
0067     struct omap_dm_timer *dm_timer;
0068     const struct omap_dm_timer_ops *pdata;
0069     struct platform_device *dm_timer_pdev;
0070 };
0071 
0072 static inline struct pwm_omap_dmtimer_chip *
0073 to_pwm_omap_dmtimer_chip(struct pwm_chip *chip)
0074 {
0075     return container_of(chip, struct pwm_omap_dmtimer_chip, chip);
0076 }
0077 
0078 /**
0079  * pwm_omap_dmtimer_get_clock_cycles() - Get clock cycles in a time frame
0080  * @clk_rate:   pwm timer clock rate
0081  * @ns:     time frame in nano seconds.
0082  *
0083  * Return number of clock cycles in a given period(ins ns).
0084  */
0085 static u32 pwm_omap_dmtimer_get_clock_cycles(unsigned long clk_rate, int ns)
0086 {
0087     return DIV_ROUND_CLOSEST_ULL((u64)clk_rate * ns, NSEC_PER_SEC);
0088 }
0089 
0090 /**
0091  * pwm_omap_dmtimer_start() - Start the pwm omap dm timer in pwm mode
0092  * @omap:   Pointer to pwm omap dm timer chip
0093  */
0094 static void pwm_omap_dmtimer_start(struct pwm_omap_dmtimer_chip *omap)
0095 {
0096     /*
0097      * According to OMAP 4 TRM section 22.2.4.10 the counter should be
0098      * started at 0xFFFFFFFE when overflow and match is used to ensure
0099      * that the PWM line is toggled on the first event.
0100      *
0101      * Note that omap_dm_timer_enable/disable is for register access and
0102      * not the timer counter itself.
0103      */
0104     omap->pdata->enable(omap->dm_timer);
0105     omap->pdata->write_counter(omap->dm_timer, DM_TIMER_LOAD_MIN);
0106     omap->pdata->disable(omap->dm_timer);
0107 
0108     omap->pdata->start(omap->dm_timer);
0109 }
0110 
0111 /**
0112  * pwm_omap_dmtimer_is_enabled() -  Detect if the pwm is enabled.
0113  * @omap:   Pointer to pwm omap dm timer chip
0114  *
0115  * Return true if pwm is enabled else false.
0116  */
0117 static bool pwm_omap_dmtimer_is_enabled(struct pwm_omap_dmtimer_chip *omap)
0118 {
0119     u32 status;
0120 
0121     status = omap->pdata->get_pwm_status(omap->dm_timer);
0122 
0123     return !!(status & OMAP_TIMER_CTRL_ST);
0124 }
0125 
0126 /**
0127  * pwm_omap_dmtimer_polarity() -  Detect the polarity of pwm.
0128  * @omap:   Pointer to pwm omap dm timer chip
0129  *
0130  * Return the polarity of pwm.
0131  */
0132 static int pwm_omap_dmtimer_polarity(struct pwm_omap_dmtimer_chip *omap)
0133 {
0134     u32 status;
0135 
0136     status = omap->pdata->get_pwm_status(omap->dm_timer);
0137 
0138     return !!(status & OMAP_TIMER_CTRL_SCPWM);
0139 }
0140 
0141 /**
0142  * pwm_omap_dmtimer_config() - Update the configuration of pwm omap dm timer
0143  * @chip:   Pointer to PWM controller
0144  * @pwm:    Pointer to PWM channel
0145  * @duty_ns:    New duty cycle in nano seconds
0146  * @period_ns:  New period in nano seconds
0147  *
0148  * Return 0 if successfully changed the period/duty_cycle else appropriate
0149  * error.
0150  */
0151 static int pwm_omap_dmtimer_config(struct pwm_chip *chip,
0152                    struct pwm_device *pwm,
0153                    int duty_ns, int period_ns)
0154 {
0155     struct pwm_omap_dmtimer_chip *omap = to_pwm_omap_dmtimer_chip(chip);
0156     u32 period_cycles, duty_cycles;
0157     u32 load_value, match_value;
0158     unsigned long clk_rate;
0159     struct clk *fclk;
0160 
0161     dev_dbg(chip->dev, "requested duty cycle: %d ns, period: %d ns\n",
0162         duty_ns, period_ns);
0163 
0164     if (duty_ns == pwm_get_duty_cycle(pwm) &&
0165         period_ns == pwm_get_period(pwm))
0166         return 0;
0167 
0168     fclk = omap->pdata->get_fclk(omap->dm_timer);
0169     if (!fclk) {
0170         dev_err(chip->dev, "invalid pmtimer fclk\n");
0171         return -EINVAL;
0172     }
0173 
0174     clk_rate = clk_get_rate(fclk);
0175     if (!clk_rate) {
0176         dev_err(chip->dev, "invalid pmtimer fclk rate\n");
0177         return -EINVAL;
0178     }
0179 
0180     dev_dbg(chip->dev, "clk rate: %luHz\n", clk_rate);
0181 
0182     /*
0183      * Calculate the appropriate load and match values based on the
0184      * specified period and duty cycle. The load value determines the
0185      * period time and the match value determines the duty time.
0186      *
0187      * The period lasts for (DM_TIMER_MAX-load_value+1) clock cycles.
0188      * Similarly, the active time lasts (match_value-load_value+1) cycles.
0189      * The non-active time is the remainder: (DM_TIMER_MAX-match_value)
0190      * clock cycles.
0191      *
0192      * NOTE: It is required that: load_value <= match_value < DM_TIMER_MAX
0193      *
0194      * References:
0195      *   OMAP4430/60/70 TRM sections 22.2.4.10 and 22.2.4.11
0196      *   AM335x Sitara TRM sections 20.1.3.5 and 20.1.3.6
0197      */
0198     period_cycles = pwm_omap_dmtimer_get_clock_cycles(clk_rate, period_ns);
0199     duty_cycles = pwm_omap_dmtimer_get_clock_cycles(clk_rate, duty_ns);
0200 
0201     if (period_cycles < 2) {
0202         dev_info(chip->dev,
0203              "period %d ns too short for clock rate %lu Hz\n",
0204              period_ns, clk_rate);
0205         return -EINVAL;
0206     }
0207 
0208     if (duty_cycles < 1) {
0209         dev_dbg(chip->dev,
0210             "duty cycle %d ns is too short for clock rate %lu Hz\n",
0211             duty_ns, clk_rate);
0212         dev_dbg(chip->dev, "using minimum of 1 clock cycle\n");
0213         duty_cycles = 1;
0214     } else if (duty_cycles >= period_cycles) {
0215         dev_dbg(chip->dev,
0216             "duty cycle %d ns is too long for period %d ns at clock rate %lu Hz\n",
0217             duty_ns, period_ns, clk_rate);
0218         dev_dbg(chip->dev, "using maximum of 1 clock cycle less than period\n");
0219         duty_cycles = period_cycles - 1;
0220     }
0221 
0222     dev_dbg(chip->dev, "effective duty cycle: %lld ns, period: %lld ns\n",
0223         DIV_ROUND_CLOSEST_ULL((u64)NSEC_PER_SEC * duty_cycles,
0224                       clk_rate),
0225         DIV_ROUND_CLOSEST_ULL((u64)NSEC_PER_SEC * period_cycles,
0226                       clk_rate));
0227 
0228     load_value = (DM_TIMER_MAX - period_cycles) + 1;
0229     match_value = load_value + duty_cycles - 1;
0230 
0231     omap->pdata->set_load(omap->dm_timer, load_value);
0232     omap->pdata->set_match(omap->dm_timer, true, match_value);
0233 
0234     dev_dbg(chip->dev, "load value: %#08x (%d), match value: %#08x (%d)\n",
0235         load_value, load_value, match_value, match_value);
0236 
0237     return 0;
0238 }
0239 
0240 /**
0241  * pwm_omap_dmtimer_set_polarity() - Changes the polarity of the pwm dm timer.
0242  * @chip:   Pointer to PWM controller
0243  * @pwm:    Pointer to PWM channel
0244  * @polarity:   New pwm polarity to be set
0245  */
0246 static void pwm_omap_dmtimer_set_polarity(struct pwm_chip *chip,
0247                       struct pwm_device *pwm,
0248                       enum pwm_polarity polarity)
0249 {
0250     struct pwm_omap_dmtimer_chip *omap = to_pwm_omap_dmtimer_chip(chip);
0251     bool enabled;
0252 
0253     /* Disable the PWM before changing the polarity. */
0254     enabled = pwm_omap_dmtimer_is_enabled(omap);
0255     if (enabled)
0256         omap->pdata->stop(omap->dm_timer);
0257 
0258     omap->pdata->set_pwm(omap->dm_timer,
0259                  polarity == PWM_POLARITY_INVERSED,
0260                  true, OMAP_TIMER_TRIGGER_OVERFLOW_AND_COMPARE,
0261                  true);
0262 
0263     if (enabled)
0264         pwm_omap_dmtimer_start(omap);
0265 }
0266 
0267 /**
0268  * pwm_omap_dmtimer_apply() - Changes the state of the pwm omap dm timer.
0269  * @chip:   Pointer to PWM controller
0270  * @pwm:    Pointer to PWM channel
0271  * @state:  New state to apply
0272  *
0273  * Return 0 if successfully changed the state else appropriate error.
0274  */
0275 static int pwm_omap_dmtimer_apply(struct pwm_chip *chip,
0276                   struct pwm_device *pwm,
0277                   const struct pwm_state *state)
0278 {
0279     struct pwm_omap_dmtimer_chip *omap = to_pwm_omap_dmtimer_chip(chip);
0280     int ret = 0;
0281 
0282     mutex_lock(&omap->mutex);
0283 
0284     if (pwm_omap_dmtimer_is_enabled(omap) && !state->enabled) {
0285         omap->pdata->stop(omap->dm_timer);
0286         goto unlock_mutex;
0287     }
0288 
0289     if (pwm_omap_dmtimer_polarity(omap) != state->polarity)
0290         pwm_omap_dmtimer_set_polarity(chip, pwm, state->polarity);
0291 
0292     ret = pwm_omap_dmtimer_config(chip, pwm, state->duty_cycle,
0293                       state->period);
0294     if (ret)
0295         goto unlock_mutex;
0296 
0297     if (!pwm_omap_dmtimer_is_enabled(omap) && state->enabled) {
0298         omap->pdata->set_pwm(omap->dm_timer,
0299                      state->polarity == PWM_POLARITY_INVERSED,
0300                      true,
0301                      OMAP_TIMER_TRIGGER_OVERFLOW_AND_COMPARE,
0302                      true);
0303         pwm_omap_dmtimer_start(omap);
0304     }
0305 
0306 unlock_mutex:
0307     mutex_unlock(&omap->mutex);
0308 
0309     return ret;
0310 }
0311 
0312 static const struct pwm_ops pwm_omap_dmtimer_ops = {
0313     .apply = pwm_omap_dmtimer_apply,
0314     .owner = THIS_MODULE,
0315 };
0316 
0317 static int pwm_omap_dmtimer_probe(struct platform_device *pdev)
0318 {
0319     struct device_node *np = pdev->dev.of_node;
0320     struct dmtimer_platform_data *timer_pdata;
0321     const struct omap_dm_timer_ops *pdata;
0322     struct platform_device *timer_pdev;
0323     struct pwm_omap_dmtimer_chip *omap;
0324     struct omap_dm_timer *dm_timer;
0325     struct device_node *timer;
0326     int ret = 0;
0327     u32 v;
0328 
0329     timer = of_parse_phandle(np, "ti,timers", 0);
0330     if (!timer)
0331         return -ENODEV;
0332 
0333     timer_pdev = of_find_device_by_node(timer);
0334     if (!timer_pdev) {
0335         dev_err(&pdev->dev, "Unable to find Timer pdev\n");
0336         ret = -ENODEV;
0337         goto err_find_timer_pdev;
0338     }
0339 
0340     timer_pdata = dev_get_platdata(&timer_pdev->dev);
0341     if (!timer_pdata) {
0342         dev_dbg(&pdev->dev,
0343              "dmtimer pdata structure NULL, deferring probe\n");
0344         ret = -EPROBE_DEFER;
0345         goto err_platdata;
0346     }
0347 
0348     pdata = timer_pdata->timer_ops;
0349 
0350     if (!pdata || !pdata->request_by_node ||
0351         !pdata->free ||
0352         !pdata->enable ||
0353         !pdata->disable ||
0354         !pdata->get_fclk ||
0355         !pdata->start ||
0356         !pdata->stop ||
0357         !pdata->set_load ||
0358         !pdata->set_match ||
0359         !pdata->set_pwm ||
0360         !pdata->get_pwm_status ||
0361         !pdata->set_prescaler ||
0362         !pdata->write_counter) {
0363         dev_err(&pdev->dev, "Incomplete dmtimer pdata structure\n");
0364         ret = -EINVAL;
0365         goto err_platdata;
0366     }
0367 
0368     if (!of_get_property(timer, "ti,timer-pwm", NULL)) {
0369         dev_err(&pdev->dev, "Missing ti,timer-pwm capability\n");
0370         ret = -ENODEV;
0371         goto err_timer_property;
0372     }
0373 
0374     dm_timer = pdata->request_by_node(timer);
0375     if (!dm_timer) {
0376         ret = -EPROBE_DEFER;
0377         goto err_request_timer;
0378     }
0379 
0380     omap = devm_kzalloc(&pdev->dev, sizeof(*omap), GFP_KERNEL);
0381     if (!omap) {
0382         ret = -ENOMEM;
0383         goto err_alloc_omap;
0384     }
0385 
0386     omap->pdata = pdata;
0387     omap->dm_timer = dm_timer;
0388     omap->dm_timer_pdev = timer_pdev;
0389 
0390     /*
0391      * Ensure that the timer is stopped before we allow PWM core to call
0392      * pwm_enable.
0393      */
0394     if (pm_runtime_active(&omap->dm_timer_pdev->dev))
0395         omap->pdata->stop(omap->dm_timer);
0396 
0397     if (!of_property_read_u32(pdev->dev.of_node, "ti,prescaler", &v))
0398         omap->pdata->set_prescaler(omap->dm_timer, v);
0399 
0400     /* setup dmtimer clock source */
0401     if (!of_property_read_u32(pdev->dev.of_node, "ti,clock-source", &v))
0402         omap->pdata->set_source(omap->dm_timer, v);
0403 
0404     omap->chip.dev = &pdev->dev;
0405     omap->chip.ops = &pwm_omap_dmtimer_ops;
0406     omap->chip.npwm = 1;
0407 
0408     mutex_init(&omap->mutex);
0409 
0410     ret = pwmchip_add(&omap->chip);
0411     if (ret < 0) {
0412         dev_err(&pdev->dev, "failed to register PWM\n");
0413         goto err_pwmchip_add;
0414     }
0415 
0416     of_node_put(timer);
0417 
0418     platform_set_drvdata(pdev, omap);
0419 
0420     return 0;
0421 
0422 err_pwmchip_add:
0423 
0424     /*
0425      * *omap is allocated using devm_kzalloc,
0426      * so no free necessary here
0427      */
0428 err_alloc_omap:
0429 
0430     pdata->free(dm_timer);
0431 err_request_timer:
0432 
0433 err_timer_property:
0434 err_platdata:
0435 
0436     put_device(&timer_pdev->dev);
0437 err_find_timer_pdev:
0438 
0439     of_node_put(timer);
0440 
0441     return ret;
0442 }
0443 
0444 static int pwm_omap_dmtimer_remove(struct platform_device *pdev)
0445 {
0446     struct pwm_omap_dmtimer_chip *omap = platform_get_drvdata(pdev);
0447 
0448     pwmchip_remove(&omap->chip);
0449 
0450     if (pm_runtime_active(&omap->dm_timer_pdev->dev))
0451         omap->pdata->stop(omap->dm_timer);
0452 
0453     omap->pdata->free(omap->dm_timer);
0454 
0455     put_device(&omap->dm_timer_pdev->dev);
0456 
0457     mutex_destroy(&omap->mutex);
0458 
0459     return 0;
0460 }
0461 
0462 static const struct of_device_id pwm_omap_dmtimer_of_match[] = {
0463     {.compatible = "ti,omap-dmtimer-pwm"},
0464     {}
0465 };
0466 MODULE_DEVICE_TABLE(of, pwm_omap_dmtimer_of_match);
0467 
0468 static struct platform_driver pwm_omap_dmtimer_driver = {
0469     .driver = {
0470         .name = "omap-dmtimer-pwm",
0471         .of_match_table = of_match_ptr(pwm_omap_dmtimer_of_match),
0472     },
0473     .probe = pwm_omap_dmtimer_probe,
0474     .remove = pwm_omap_dmtimer_remove,
0475 };
0476 module_platform_driver(pwm_omap_dmtimer_driver);
0477 
0478 MODULE_AUTHOR("Grant Erickson <marathon96@gmail.com>");
0479 MODULE_AUTHOR("NeilBrown <neilb@suse.de>");
0480 MODULE_AUTHOR("Neil Armstrong <narmstrong@baylibre.com>");
0481 MODULE_LICENSE("GPL v2");
0482 MODULE_DESCRIPTION("OMAP PWM Driver using Dual-mode Timers");