diff options
Diffstat (limited to 'arch/arm/mach-omap2')
-rw-r--r-- | arch/arm/mach-omap2/Kconfig | 1 | ||||
-rw-r--r-- | arch/arm/mach-omap2/board-generic.c | 17 | ||||
-rw-r--r-- | arch/arm/mach-omap2/board-omap3beagle.c | 22 | ||||
-rw-r--r-- | arch/arm/mach-omap2/clock33xx_data.c | 2 | ||||
-rw-r--r-- | arch/arm/mach-omap2/mux34xx.c | 8 | ||||
-rw-r--r-- | arch/arm/mach-omap2/pm.h | 1 | ||||
-rw-r--r-- | arch/arm/mach-omap2/pm34xx.c | 30 | ||||
-rw-r--r-- | arch/arm/mach-omap2/serial.c | 5 | ||||
-rw-r--r-- | arch/arm/mach-omap2/timer.c | 203 |
9 files changed, 240 insertions, 49 deletions
diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig index 2a1a898..d669e22 100644 --- a/arch/arm/mach-omap2/Kconfig +++ b/arch/arm/mach-omap2/Kconfig @@ -11,7 +11,6 @@ config ARCH_OMAP2PLUS_TYPICAL select I2C_OMAP select MENELAUS if ARCH_OMAP2 select NEON if ARCH_OMAP3 || ARCH_OMAP4 || SOC_OMAP5 - select PINCTRL select PM_RUNTIME select REGULATOR select SERIAL_OMAP diff --git a/arch/arm/mach-omap2/board-generic.c b/arch/arm/mach-omap2/board-generic.c index 601ecdf..d690180 100644 --- a/arch/arm/mach-omap2/board-generic.c +++ b/arch/arm/mach-omap2/board-generic.c @@ -97,6 +97,23 @@ DT_MACHINE_START(OMAP3_DT, "Generic OMAP3 (Flattened Device Tree)") .dt_compat = omap3_boards_compat, .restart = omap_prcm_restart, MACHINE_END + +static const char *omap3_gp_boards_compat[] __initdata = { + "ti,omap3-beagle", + NULL, +}; + +DT_MACHINE_START(OMAP3_GP_DT, "Generic OMAP3-GP (Flattened Device Tree)") + .reserve = omap_reserve, + .map_io = omap3_map_io, + .init_early = omap3430_init_early, + .init_irq = omap_intc_of_init, + .handle_irq = omap3_intc_handle_irq, + .init_machine = omap_generic_init, + .timer = &omap3_secure_timer, + .dt_compat = omap3_gp_boards_compat, + .restart = omap_prcm_restart, +MACHINE_END #endif #ifdef CONFIG_SOC_AM33XX diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c index 85c09a0..5a3800d 100644 --- a/arch/arm/mach-omap2/board-omap3beagle.c +++ b/arch/arm/mach-omap2/board-omap3beagle.c @@ -24,6 +24,7 @@ #include <linux/input.h> #include <linux/gpio_keys.h> #include <linux/opp.h> +#include <linux/cpu.h> #include <linux/mtd/mtd.h> #include <linux/mtd/partitions.h> @@ -447,27 +448,31 @@ static struct omap_board_mux board_mux[] __initdata = { }; #endif -static void __init beagle_opp_init(void) +static int __init beagle_opp_init(void) { int r = 0; - /* Initialize the omap3 opp table */ - if (omap3_opp_init()) { + if (!machine_is_omap3_beagle()) + return 0; + + /* Initialize the omap3 opp table if not already created. */ + r = omap3_opp_init(); + if (IS_ERR_VALUE(r) && (r != -EEXIST)) { pr_err("%s: opp default init failed\n", __func__); - return; + return r; } /* Custom OPP enabled for all xM versions */ if (cpu_is_omap3630()) { struct device *mpu_dev, *iva_dev; - mpu_dev = omap_device_get_by_hwmod_name("mpu"); + mpu_dev = get_cpu_device(0); iva_dev = omap_device_get_by_hwmod_name("iva"); if (IS_ERR(mpu_dev) || IS_ERR(iva_dev)) { pr_err("%s: Aiee.. no mpu/dsp devices? %p %p\n", __func__, mpu_dev, iva_dev); - return; + return -ENODEV; } /* Enable MPU 1GHz and lower opps */ r = opp_enable(mpu_dev, 800000000); @@ -487,8 +492,9 @@ static void __init beagle_opp_init(void) opp_disable(iva_dev, 660000000); } } - return; + return 0; } +device_initcall(beagle_opp_init); static void __init omap3_beagle_init(void) { @@ -526,8 +532,6 @@ static void __init omap3_beagle_init(void) /* Ensure SDRC pins are mux'd for self-refresh */ omap_mux_init_signal("sdrc_cke0", OMAP_PIN_OUTPUT); omap_mux_init_signal("sdrc_cke1", OMAP_PIN_OUTPUT); - - beagle_opp_init(); } MACHINE_START(OMAP3_BEAGLE, "OMAP3 Beagle Board") diff --git a/arch/arm/mach-omap2/clock33xx_data.c b/arch/arm/mach-omap2/clock33xx_data.c index 1cb79cc..17e3de5 100644 --- a/arch/arm/mach-omap2/clock33xx_data.c +++ b/arch/arm/mach-omap2/clock33xx_data.c @@ -1072,6 +1072,8 @@ static struct omap_clk am33xx_clks[] = { CLK(NULL, "gfx_fck_div_ck", &gfx_fck_div_ck, CK_AM33XX), CLK(NULL, "sysclkout_pre_ck", &sysclkout_pre_ck, CK_AM33XX), CLK(NULL, "clkout2_ck", &clkout2_ck, CK_AM33XX), + CLK(NULL, "timer_32k_ck", &clkdiv32k_ick, CK_AM33XX), + CLK(NULL, "timer_sys_ck", &sys_clkin_ck, CK_AM33XX), }; int __init am33xx_clk_init(void) diff --git a/arch/arm/mach-omap2/mux34xx.c b/arch/arm/mach-omap2/mux34xx.c index 17f80e4..c47140b 100644 --- a/arch/arm/mach-omap2/mux34xx.c +++ b/arch/arm/mach-omap2/mux34xx.c @@ -614,16 +614,16 @@ static struct omap_mux __initdata omap3_muxmodes[] = { "sys_off_mode", NULL, NULL, NULL, "gpio_9", NULL, NULL, "safe_mode"), _OMAP3_MUXENTRY(UART1_CTS, 150, - "uart1_cts", NULL, NULL, NULL, + "uart1_cts", "ssi1_rdy_tx", NULL, NULL, "gpio_150", "hsusb3_tll_clk", NULL, "safe_mode"), _OMAP3_MUXENTRY(UART1_RTS, 149, - "uart1_rts", NULL, NULL, NULL, + "uart1_rts", "ssi1_flag_tx", NULL, NULL, "gpio_149", NULL, NULL, "safe_mode"), _OMAP3_MUXENTRY(UART1_RX, 151, - "uart1_rx", NULL, "mcbsp1_clkr", "mcspi4_clk", + "uart1_rx", "ss1_wake_tx", "mcbsp1_clkr", "mcspi4_clk", "gpio_151", NULL, NULL, "safe_mode"), _OMAP3_MUXENTRY(UART1_TX, 148, - "uart1_tx", NULL, NULL, NULL, + "uart1_tx", "ssi1_dat_tx", NULL, NULL, "gpio_148", NULL, NULL, "safe_mode"), _OMAP3_MUXENTRY(UART2_CTS, 144, "uart2_cts", "mcbsp3_dx", "gpt9_pwm_evt", NULL, diff --git a/arch/arm/mach-omap2/pm.h b/arch/arm/mach-omap2/pm.h index 686137d..67d6613 100644 --- a/arch/arm/mach-omap2/pm.h +++ b/arch/arm/mach-omap2/pm.h @@ -91,6 +91,7 @@ extern void omap3_save_scratchpad_contents(void); #define PM_RTA_ERRATUM_i608 (1 << 0) #define PM_SDRC_WAKEUP_ERRATUM_i583 (1 << 1) +#define PM_PER_MEMORIES_ERRATUM_i582 (1 << 2) #if defined(CONFIG_PM) && defined(CONFIG_ARCH_OMAP3) extern u16 pm34xx_errata; diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c index 4c85762..11f9669 100644 --- a/arch/arm/mach-omap2/pm34xx.c +++ b/arch/arm/mach-omap2/pm34xx.c @@ -653,14 +653,17 @@ static void __init pm_errata_configure(void) /* Enable the l2 cache toggling in sleep logic */ enable_omap3630_toggle_l2_on_restore(); if (omap_rev() < OMAP3630_REV_ES1_2) - pm34xx_errata |= PM_SDRC_WAKEUP_ERRATUM_i583; + pm34xx_errata |= (PM_SDRC_WAKEUP_ERRATUM_i583 | + PM_PER_MEMORIES_ERRATUM_i582); + } else if (cpu_is_omap34xx()) { + pm34xx_errata |= PM_PER_MEMORIES_ERRATUM_i582; } } int __init omap3_pm_init(void) { struct power_state *pwrst, *tmp; - struct clockdomain *neon_clkdm, *mpu_clkdm; + struct clockdomain *neon_clkdm, *mpu_clkdm, *per_clkdm, *wkup_clkdm; int ret; if (!omap3_has_io_chain_ctrl()) @@ -712,6 +715,8 @@ int __init omap3_pm_init(void) neon_clkdm = clkdm_lookup("neon_clkdm"); mpu_clkdm = clkdm_lookup("mpu_clkdm"); + per_clkdm = clkdm_lookup("per_clkdm"); + wkup_clkdm = clkdm_lookup("wkup_clkdm"); #ifdef CONFIG_SUSPEND omap_pm_suspend = omap3_pm_suspend; @@ -728,6 +733,27 @@ int __init omap3_pm_init(void) if (IS_PM34XX_ERRATUM(PM_RTA_ERRATUM_i608)) omap3630_ctrl_disable_rta(); + /* + * The UART3/4 FIFO and the sidetone memory in McBSP2/3 are + * not correctly reset when the PER powerdomain comes back + * from OFF or OSWR when the CORE powerdomain is kept active. + * See OMAP36xx Erratum i582 "PER Domain reset issue after + * Domain-OFF/OSWR Wakeup". This wakeup dependency is not a + * complete workaround. The kernel must also prevent the PER + * powerdomain from going to OSWR/OFF while the CORE + * powerdomain is not going to OSWR/OFF. And if PER last + * power state was off while CORE last power state was ON, the + * UART3/4 and McBSP2/3 SIDETONE devices need to run a + * self-test using their loopback tests; if that fails, those + * devices are unusable until the PER/CORE can complete a transition + * from ON to OSWR/OFF and then back to ON. + * + * XXX Technically this workaround is only needed if off-mode + * or OSWR is enabled. + */ + if (IS_PM34XX_ERRATUM(PM_PER_MEMORIES_ERRATUM_i582)) + clkdm_add_wkdep(per_clkdm, wkup_clkdm); + clkdm_add_wkdep(neon_clkdm, mpu_clkdm); if (omap_type() != OMAP2_DEVICE_TYPE_GP) { omap3_secure_ram_storage = diff --git a/arch/arm/mach-omap2/serial.c b/arch/arm/mach-omap2/serial.c index 812976e..aa30a3c 100644 --- a/arch/arm/mach-omap2/serial.c +++ b/arch/arm/mach-omap2/serial.c @@ -330,6 +330,11 @@ void __init omap_serial_init_port(struct omap_board_data *bdata, oh->mux = omap_hwmod_mux_init(bdata->pads, bdata->pads_cnt); + if (console_uart_id == bdata->id) { + omap_device_enable(pdev); + pm_runtime_set_active(&pdev->dev); + } + oh->dev_attr = uart; if (((cpu_is_omap34xx() || cpu_is_omap44xx()) && bdata->pads) diff --git a/arch/arm/mach-omap2/timer.c b/arch/arm/mach-omap2/timer.c index c5bc2cb..684d2fc 100644 --- a/arch/arm/mach-omap2/timer.c +++ b/arch/arm/mach-omap2/timer.c @@ -37,6 +37,8 @@ #include <linux/clockchips.h> #include <linux/slab.h> #include <linux/of.h> +#include <linux/of_address.h> +#include <linux/of_irq.h> #include <asm/mach/time.h> #include <asm/smp_twd.h> @@ -67,11 +69,13 @@ #define OMAP3_CLKEV_SOURCE OMAP3_32K_SOURCE #define OMAP4_CLKEV_SOURCE OMAP4_32K_SOURCE #define OMAP3_SECURE_TIMER 12 +#define TIMER_PROP_SECURE "ti,timer-secure" #else #define OMAP2_CLKEV_SOURCE OMAP2_MPU_SOURCE #define OMAP3_CLKEV_SOURCE OMAP3_MPU_SOURCE #define OMAP4_CLKEV_SOURCE OMAP4_MPU_SOURCE #define OMAP3_SECURE_TIMER 1 +#define TIMER_PROP_SECURE "ti,timer-alwon" #endif #define REALTIME_COUNTER_BASE 0x48243200 @@ -145,36 +149,141 @@ static struct clock_event_device clockevent_gpt = { .set_mode = omap2_gp_timer_set_mode, }; +static struct property device_disabled = { + .name = "status", + .length = sizeof("disabled"), + .value = "disabled", +}; + +static struct of_device_id omap_timer_match[] __initdata = { + { .compatible = "ti,omap2-timer", }, + { } +}; + +static struct of_device_id omap_counter_match[] __initdata = { + { .compatible = "ti,omap-counter32k", }, + { } +}; + +/** + * omap_get_timer_dt - get a timer using device-tree + * @match - device-tree match structure for matching a device type + * @property - optional timer property to match + * + * Helper function to get a timer during early boot using device-tree for use + * as kernel system timer. Optionally, the property argument can be used to + * select a timer with a specific property. Once a timer is found then mark + * the timer node in device-tree as disabled, to prevent the kernel from + * 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)) { + of_node_put(np); + continue; + } + + if (property && !of_get_property(np, property, NULL)) { + of_node_put(np); + continue; + } + + prom_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. + */ +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); + } +} + static int __init omap_dm_timer_init_one(struct omap_dm_timer *timer, int gptimer_id, - const char *fck_source) + const char *fck_source, + const char *property) { char name[10]; /* 10 = sizeof("gptXX_Xck0") */ + const char *oh_name; + struct device_node *np; struct omap_hwmod *oh; struct resource irq_rsrc, mem_rsrc; size_t size; int res = 0; int r; - sprintf(name, "timer%d", gptimer_id); - omap_hwmod_setup_one(name); - oh = omap_hwmod_lookup(name); + 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; + } + + omap_hwmod_setup_one(oh_name); + oh = omap_hwmod_lookup(oh_name); + if (!oh) return -ENODEV; - r = omap_hwmod_get_resource_byname(oh, IORESOURCE_IRQ, NULL, &irq_rsrc); - if (r) - return -ENXIO; - timer->irq = irq_rsrc.start; - - r = omap_hwmod_get_resource_byname(oh, IORESOURCE_MEM, NULL, &mem_rsrc); - if (r) - return -ENXIO; - timer->phys_base = mem_rsrc.start; - size = mem_rsrc.end - mem_rsrc.start; + if (!of_have_populated_dt()) { + r = omap_hwmod_get_resource_byname(oh, IORESOURCE_IRQ, NULL, + &irq_rsrc); + if (r) + return -ENXIO; + timer->irq = irq_rsrc.start; + + r = omap_hwmod_get_resource_byname(oh, IORESOURCE_MEM, NULL, + &mem_rsrc); + if (r) + return -ENXIO; + timer->phys_base = mem_rsrc.start; + size = mem_rsrc.end - mem_rsrc.start; + + /* Static mapping, never released */ + timer->io_base = ioremap(timer->phys_base, size); + } - /* Static mapping, never released */ - timer->io_base = ioremap(timer->phys_base, size); if (!timer->io_base) return -ENXIO; @@ -185,9 +294,7 @@ static int __init omap_dm_timer_init_one(struct omap_dm_timer *timer, omap_hwmod_enable(oh); - if (omap_dm_timer_reserve_systimer(gptimer_id)) - return -ENODEV; - + /* FIXME: Need to remove hard-coded test on timer ID */ if (gptimer_id != 12) { struct clk *src; @@ -197,8 +304,8 @@ static int __init omap_dm_timer_init_one(struct omap_dm_timer *timer, } else { res = __omap_dm_timer_set_source(timer->fclk, src); if (IS_ERR_VALUE(res)) - pr_warning("%s: timer%i cannot set source\n", - __func__, gptimer_id); + pr_warn("%s: %s cannot set source\n", + __func__, oh->name); clk_put(src); } } @@ -214,11 +321,12 @@ static int __init omap_dm_timer_init_one(struct omap_dm_timer *timer, } static void __init omap2_gp_clockevent_init(int gptimer_id, - const char *fck_source) + const char *fck_source, + const char *property) { int res; - res = omap_dm_timer_init_one(&clkev, gptimer_id, fck_source); + res = omap_dm_timer_init_one(&clkev, gptimer_id, fck_source, property); BUG_ON(res); omap2_gp_timer_irq.dev_id = &clkev; @@ -275,11 +383,26 @@ static u32 notrace dmtimer_read_sched_clock(void) static int __init omap2_sync32k_clocksource_init(void) { int ret; + struct device_node *np = NULL; struct omap_hwmod *oh; void __iomem *vbase; const char *oh_name = "counter_32k"; /* + * If device-tree is present, then search the DT blob + * to see if the 32kHz counter is supported. + */ + if (of_have_populated_dt()) { + np = omap_get_timer_dt(omap_counter_match, NULL); + if (!np) + return -ENODEV; + + of_property_read_string_index(np, "ti,hwmods", 0, &oh_name); + if (!oh_name) + return -ENODEV; + } + + /* * First check hwmod data is available for sync32k counter */ oh = omap_hwmod_lookup(oh_name); @@ -288,7 +411,13 @@ static int __init omap2_sync32k_clocksource_init(void) omap_hwmod_setup_one(oh_name); - vbase = omap_hwmod_get_mpu_rt_va(oh); + if (np) { + vbase = of_iomap(np, 0); + of_node_put(np); + } else { + vbase = omap_hwmod_get_mpu_rt_va(oh); + } + if (!vbase) { pr_warn("%s: failed to get counter_32k resource\n", __func__); return -ENXIO; @@ -322,7 +451,7 @@ static void __init omap2_gptimer_clocksource_init(int gptimer_id, { int res; - res = omap_dm_timer_init_one(&clksrc, gptimer_id, fck_source); + res = omap_dm_timer_init_one(&clksrc, gptimer_id, fck_source, NULL); BUG_ON(res); __omap_dm_timer_load_start(&clksrc, @@ -434,11 +563,12 @@ static inline void __init realtime_counter_init(void) {} #endif -#define OMAP_SYS_TIMER_INIT(name, clkev_nr, clkev_src, \ +#define OMAP_SYS_TIMER_INIT(name, clkev_nr, clkev_src, clkev_prop, \ clksrc_nr, clksrc_src) \ static void __init omap##name##_timer_init(void) \ { \ - omap2_gp_clockevent_init((clkev_nr), clkev_src); \ + omap_dmtimer_init(); \ + omap2_gp_clockevent_init((clkev_nr), clkev_src, clkev_prop); \ omap2_clocksource_init((clksrc_nr), clksrc_src); \ } @@ -448,20 +578,23 @@ struct sys_timer omap##name##_timer = { \ }; #ifdef CONFIG_ARCH_OMAP2 -OMAP_SYS_TIMER_INIT(2, 1, OMAP2_CLKEV_SOURCE, 2, OMAP2_MPU_SOURCE) +OMAP_SYS_TIMER_INIT(2, 1, OMAP2_CLKEV_SOURCE, "ti,timer-alwon", + 2, OMAP2_MPU_SOURCE) OMAP_SYS_TIMER(2) #endif #ifdef CONFIG_ARCH_OMAP3 -OMAP_SYS_TIMER_INIT(3, 1, OMAP3_CLKEV_SOURCE, 2, OMAP3_MPU_SOURCE) +OMAP_SYS_TIMER_INIT(3, 1, OMAP3_CLKEV_SOURCE, "ti,timer-alwon", + 2, OMAP3_MPU_SOURCE) OMAP_SYS_TIMER(3) OMAP_SYS_TIMER_INIT(3_secure, OMAP3_SECURE_TIMER, OMAP3_CLKEV_SOURCE, - 2, OMAP3_MPU_SOURCE) + TIMER_PROP_SECURE, 2, OMAP3_MPU_SOURCE) OMAP_SYS_TIMER(3_secure) #endif #ifdef CONFIG_SOC_AM33XX -OMAP_SYS_TIMER_INIT(3_am33xx, 1, OMAP4_MPU_SOURCE, 2, OMAP4_MPU_SOURCE) +OMAP_SYS_TIMER_INIT(3_am33xx, 1, OMAP4_MPU_SOURCE, "ti,timer-alwon", + 2, OMAP4_MPU_SOURCE) OMAP_SYS_TIMER(3_am33xx) #endif @@ -473,7 +606,7 @@ static DEFINE_TWD_LOCAL_TIMER(twd_local_timer, static void __init omap4_timer_init(void) { - omap2_gp_clockevent_init(1, OMAP4_CLKEV_SOURCE); + omap2_gp_clockevent_init(1, OMAP4_CLKEV_SOURCE, "ti,timer-alwon"); omap2_clocksource_init(2, OMAP4_MPU_SOURCE); #ifdef CONFIG_LOCAL_TIMERS /* Local timers are not supprted on OMAP4430 ES1.0 */ @@ -499,7 +632,7 @@ static void __init omap5_timer_init(void) { int err; - omap2_gp_clockevent_init(1, OMAP4_CLKEV_SOURCE); + omap2_gp_clockevent_init(1, OMAP4_CLKEV_SOURCE, "ti,timer-alwon"); omap2_clocksource_init(2, OMAP4_MPU_SOURCE); realtime_counter_init(); @@ -586,6 +719,10 @@ static int __init omap2_dm_timer_init(void) { int ret; + /* If dtb is there, the devices will be created dynamically */ + if (of_have_populated_dt()) + return -ENODEV; + ret = omap_hwmod_for_each_by_class("timer", omap_timer_init, NULL); if (unlikely(ret)) { pr_err("%s: device registration failed.\n", __func__); |