|
@@ -160,3 +160,113 @@ static struct of_device_id omap_timer_match[] __initdata = {
|
|
|
* registering this timer as a platform device and so no one else can use it.
|
|
|
*/
|
|
|
static struct device_node * __init omap_get_timer_dt(struct of_device_id *match,
|
|
|
+ const char *property)
|
|
|
+{
|
|
|
+ struct device_node *np;
|
|
|
+
|
|
|
+ for_each_matching_node(np, match) {
|
|
|
+ if (!of_device_is_available(np))
|
|
|
+ continue;
|
|
|
+
|
|
|
+ if (property && !of_get_property(np, property, NULL))
|
|
|
+ continue;
|
|
|
+
|
|
|
+ of_add_property(np, &device_disabled);
|
|
|
+ return np;
|
|
|
+ }
|
|
|
+
|
|
|
+ return NULL;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * omap_dmtimer_init - initialisation function when device tree is used
|
|
|
+ *
|
|
|
+ * For secure OMAP3 devices, timers with device type "timer-secure" cannot
|
|
|
+ * be used by the kernel as they are reserved. Therefore, to prevent the
|
|
|
+ * kernel registering these devices remove them dynamically from the device
|
|
|
+ * tree on boot.
|
|
|
+ */
|
|
|
+static void __init omap_dmtimer_init(void)
|
|
|
+{
|
|
|
+ struct device_node *np;
|
|
|
+
|
|
|
+ if (!cpu_is_omap34xx())
|
|
|
+ return;
|
|
|
+
|
|
|
+ /* If we are a secure device, remove any secure timer nodes */
|
|
|
+ if ((omap_type() != OMAP2_DEVICE_TYPE_GP)) {
|
|
|
+ np = omap_get_timer_dt(omap_timer_match, "ti,timer-secure");
|
|
|
+ if (np)
|
|
|
+ of_node_put(np);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * omap_dm_timer_get_errata - get errata flags for a timer
|
|
|
+ *
|
|
|
+ * Get the timer errata flags that are specific to the OMAP device being used.
|
|
|
+ */
|
|
|
+static u32 __init omap_dm_timer_get_errata(void)
|
|
|
+{
|
|
|
+ if (cpu_is_omap24xx())
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ return OMAP_TIMER_ERRATA_I103_I767;
|
|
|
+}
|
|
|
+
|
|
|
+static int __init omap_dm_timer_init_one(struct omap_dm_timer *timer,
|
|
|
+ int gptimer_id,
|
|
|
+ const char *fck_source,
|
|
|
+ const char *property,
|
|
|
+ int posted)
|
|
|
+{
|
|
|
+ char name[10]; /* 10 = sizeof("gptXX_Xck0") */
|
|
|
+ const char *oh_name;
|
|
|
+ struct device_node *np;
|
|
|
+ struct omap_hwmod *oh;
|
|
|
+ struct resource irq, mem;
|
|
|
+ int r = 0;
|
|
|
+
|
|
|
+ if (of_have_populated_dt()) {
|
|
|
+ np = omap_get_timer_dt(omap_timer_match, NULL);
|
|
|
+ if (!np)
|
|
|
+ return -ENODEV;
|
|
|
+
|
|
|
+ of_property_read_string_index(np, "ti,hwmods", 0, &oh_name);
|
|
|
+ if (!oh_name)
|
|
|
+ return -ENODEV;
|
|
|
+
|
|
|
+ timer->irq = irq_of_parse_and_map(np, 0);
|
|
|
+ if (!timer->irq)
|
|
|
+ return -ENXIO;
|
|
|
+
|
|
|
+ timer->io_base = of_iomap(np, 0);
|
|
|
+
|
|
|
+ of_node_put(np);
|
|
|
+ } else {
|
|
|
+ if (omap_dm_timer_reserve_systimer(gptimer_id))
|
|
|
+ return -ENODEV;
|
|
|
+
|
|
|
+ sprintf(name, "timer%d", gptimer_id);
|
|
|
+ oh_name = name;
|
|
|
+ }
|
|
|
+
|
|
|
+ oh = omap_hwmod_lookup(oh_name);
|
|
|
+ if (!oh)
|
|
|
+ return -ENODEV;
|
|
|
+
|
|
|
+ if (!of_have_populated_dt()) {
|
|
|
+ r = omap_hwmod_get_resource_byname(oh, IORESOURCE_IRQ, NULL,
|
|
|
+ &irq);
|
|
|
+ if (r)
|
|
|
+ return -ENXIO;
|
|
|
+ timer->irq = irq.start;
|
|
|
+
|
|
|
+ r = omap_hwmod_get_resource_byname(oh, IORESOURCE_MEM, NULL,
|
|
|
+ &mem);
|
|
|
+ if (r)
|
|
|
+ return -ENXIO;
|
|
|
+
|
|
|
+ /* Static mapping, never released */
|
|
|
+ timer->io_base = ioremap(mem.start, mem.end - mem.start);
|
|
|
+ }
|