diff options
author | Jon Hunter <jon-hunter@ti.com> | 2012-05-14 10:41:37 -0500 |
---|---|---|
committer | Jon Hunter <jon-hunter@ti.com> | 2012-11-02 13:16:30 -0500 |
commit | 9725f4451a9ccd159b1d13f63e05896cd9bce07d (patch) | |
tree | f158dc234b62a4d0cebc989e9e532f290f5d8784 /arch/arm/plat-omap/dmtimer.c | |
parent | 7dd9d502b6cb9f82c9726ea601276b666a93e95d (diff) | |
download | blackbird-op-linux-9725f4451a9ccd159b1d13f63e05896cd9bce07d.tar.gz blackbird-op-linux-9725f4451a9ccd159b1d13f63e05896cd9bce07d.zip |
ARM: OMAP: Add DT support for timer driver
In order to add device-tree support to the timer driver the following changes
were made ...
1. Allocate system timers (used for clock-events and clock-source) based upon
timer properties rather than using an hard-coded timer instance ID. To allow
this a new helper function called omap_dmtimer_find_by_property() has been
added for finding a timer with the particular properties in the device-tree
blob. Please note that this is an internal helper function for system timers
only to find a timer in the device-tree blob. This cannot be used by device
drivers, another API has been added for that (see below). Timers that are
allocated for system timers are dynamically disabled at boot time by adding
a status property with the value "disabled" to the timer's device-tree node.
Please note that when allocating system timers we now pass a timer ID and
timer property. The timer ID is only be used for allocating a timer when
booting without device-tree. Once device-tree migration is complete, all
the timer ID references will be removed.
2. System timer resources (memory and interrupts) are directly obtained from
the device-tree timer node when booting with device-tree, so that system
timers are no longer reliant upon the OMAP HWMOD framework to provide these
resources.
3. If DT blob is present, then let device-tree create the timer devices
dynamically.
4. When device-tree is present the "id" field in the platform_device structure
(pdev->id) is initialised to -1 and hence cannot be used to identify a timer
instance. Due to this the following changes were made ...
a). The API omap_dm_timer_request_specific() is not supported when using
device-tree, because it uses the device ID to request a specific timer.
This function will return an error if called when device-tree is present.
Users of this API should use omap_dm_timer_request_by_cap() instead.
b). When removing the DMTIMER driver, the timer "id" was used to identify the
timer instance. The remove function has been modified to use the device
name instead of the "id".
5. When device-tree is present the platform_data structure will be NULL and so
check for this.
6. The OMAP timer device tree binding has the following optional parameters ...
a). ti,timer-alwon --> Timer is in an always-on power domain
b). ti,timer-dsp --> Timer can generate an interrupt to the on-chip DSP
c). ti,timer-pwm --> Timer can generate a PWM output
d). ti,timer-secure --> Timer is reserved on a secure OMAP device
Search for the above parameters and set the appropriate timer attribute
flags.
Signed-off-by: Jon Hunter <jon-hunter@ti.com>
Diffstat (limited to 'arch/arm/plat-omap/dmtimer.c')
-rw-r--r-- | arch/arm/plat-omap/dmtimer.c | 41 |
1 files changed, 35 insertions, 6 deletions
diff --git a/arch/arm/plat-omap/dmtimer.c b/arch/arm/plat-omap/dmtimer.c index 2574b86ad2dc..b09e55632f4b 100644 --- a/arch/arm/plat-omap/dmtimer.c +++ b/arch/arm/plat-omap/dmtimer.c @@ -40,6 +40,8 @@ #include <linux/device.h> #include <linux/err.h> #include <linux/pm_runtime.h> +#include <linux/of.h> +#include <linux/of_device.h> #include <plat/dmtimer.h> #include <plat/omap-pm.h> @@ -212,6 +214,13 @@ struct omap_dm_timer *omap_dm_timer_request_specific(int id) unsigned long flags; int ret = 0; + /* Requesting timer by ID is not supported when device tree is used */ + if (of_have_populated_dt()) { + pr_warn("%s: Please use omap_dm_timer_request_by_cap()\n", + __func__); + return NULL; + } + spin_lock_irqsave(&dm_timer_lock, flags); list_for_each_entry(t, &omap_timer_list, node) { if (t->pdev->id == id && !t->reserved) { @@ -466,7 +475,7 @@ int omap_dm_timer_set_source(struct omap_dm_timer *timer, int source) * use the clock framework to set the parent clock. To be removed * once OMAP1 migrated to using clock framework for dmtimers */ - if (pdata->set_timer_src) + if (pdata && pdata->set_timer_src) return pdata->set_timer_src(timer->pdev, source); fclk = clk_get(&timer->pdev->dev, "fck"); @@ -747,7 +756,7 @@ static int __devinit omap_dm_timer_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct dmtimer_platform_data *pdata = pdev->dev.platform_data; - if (!pdata) { + if (!pdata && !dev->of_node) { dev_err(dev, "%s: no platform data.\n", __func__); return -ENODEV; } @@ -776,11 +785,23 @@ static int __devinit omap_dm_timer_probe(struct platform_device *pdev) return -ENOMEM; } - timer->id = pdev->id; + if (dev->of_node) { + if (of_find_property(dev->of_node, "ti,timer-alwon", NULL)) + timer->capability |= OMAP_TIMER_ALWON; + if (of_find_property(dev->of_node, "ti,timer-dsp", NULL)) + timer->capability |= OMAP_TIMER_HAS_DSP_IRQ; + if (of_find_property(dev->of_node, "ti,timer-pwm", NULL)) + timer->capability |= OMAP_TIMER_HAS_PWM; + if (of_find_property(dev->of_node, "ti,timer-secure", NULL)) + timer->capability |= OMAP_TIMER_SECURE; + } else { + timer->id = pdev->id; + timer->capability = pdata->timer_capability; + timer->reserved = omap_dm_timer_reserved_systimer(timer->id); + } + timer->irq = irq->start; - timer->reserved = omap_dm_timer_reserved_systimer(timer->id); timer->pdev = pdev; - timer->capability = pdata->timer_capability; /* Skip pm_runtime_enable for OMAP1 */ if (!(timer->capability & OMAP_TIMER_NEEDS_RESET)) { @@ -820,7 +841,8 @@ static int __devexit omap_dm_timer_remove(struct platform_device *pdev) spin_lock_irqsave(&dm_timer_lock, flags); list_for_each_entry(timer, &omap_timer_list, node) - if (timer->pdev->id == pdev->id) { + if (!strcmp(dev_name(&timer->pdev->dev), + dev_name(&pdev->dev))) { list_del(&timer->node); ret = 0; break; @@ -830,11 +852,18 @@ static int __devexit omap_dm_timer_remove(struct platform_device *pdev) return ret; } +static const struct of_device_id omap_timer_match[] = { + { .compatible = "ti,omap2-timer", }, + {}, +}; +MODULE_DEVICE_TABLE(of, omap_timer_match); + static struct platform_driver omap_dm_timer_driver = { .probe = omap_dm_timer_probe, .remove = __devexit_p(omap_dm_timer_remove), .driver = { .name = "omap_timer", + .of_match_table = of_match_ptr(omap_timer_match), }, }; |