diff options
-rw-r--r-- | arch/arm/mach-tegra/include/mach/dc.h | 1 | ||||
-rw-r--r-- | arch/arm/mach-tegra/timer.c | 64 | ||||
-rw-r--r-- | drivers/usb/host/ehci-tegra.c | 15 | ||||
-rw-r--r-- | drivers/video/tegra/dc/dc.c | 15 |
4 files changed, 47 insertions, 48 deletions
diff --git a/arch/arm/mach-tegra/include/mach/dc.h b/arch/arm/mach-tegra/include/mach/dc.h index 77a9f15bc0bf..254b732097ef 100644 --- a/arch/arm/mach-tegra/include/mach/dc.h +++ b/arch/arm/mach-tegra/include/mach/dc.h @@ -154,6 +154,7 @@ struct tegra_fb_data { struct tegra_dc_platform_data { unsigned long flags; + unsigned long emc_clk_rate; struct tegra_dc_out *default_out; struct tegra_fb_data *fb; }; diff --git a/arch/arm/mach-tegra/timer.c b/arch/arm/mach-tegra/timer.c index dff49f201c7a..632c58e3e399 100644 --- a/arch/arm/mach-tegra/timer.c +++ b/arch/arm/mach-tegra/timer.c @@ -55,13 +55,17 @@ #define TIMER_PTV 0x0 #define TIMER_PCR 0x4 -static void __iomem *timer_base = IO_ADDRESS(TEGRA_TMR1_BASE); +static void __iomem *timer_reg_base = IO_ADDRESS(TEGRA_TMR1_BASE); static void __iomem *rtc_base = IO_ADDRESS(TEGRA_RTC_BASE); #define timer_writel(value, reg) \ - __raw_writel(value, (u32)timer_base + (reg)) + __raw_writel(value, (u32)timer_reg_base + (reg)) #define timer_readl(reg) \ - __raw_readl((u32)timer_base + (reg)) + __raw_readl((u32)timer_reg_base + (reg)) + +static u64 tegra_sched_clock_offset; +static u64 tegra_sched_clock_suspend_val; +static u64 tegra_sched_clock_suspend_rtc; static int tegra_timer_set_next_event(unsigned long cycles, struct clock_event_device *evt) @@ -95,25 +99,9 @@ static void tegra_timer_set_mode(enum clock_event_mode mode, } } -static u64 tegra_us_clocksource_offset; -static u64 tegra_us_resume_offset; -static cycle_t tegra_clocksource_us_read(struct clocksource *cs) -{ - return tegra_us_clocksource_offset + - cnt32_to_63(timer_readl(TIMERUS_CNTR_1US)); -} - -void tegra_clocksource_us_suspend(struct clocksource *cs) -{ - tegra_us_resume_offset = tegra_clocksource_us_read(cs) - - tegra_rtc_read_ms() * 1000; -} - -void tegra_clocksource_us_resume(struct clocksource *cs) +static cycle_t tegra_clocksource_read(struct clocksource *cs) { - tegra_us_clocksource_offset += tegra_us_resume_offset + - tegra_rtc_read_ms() * 1000 - - tegra_clocksource_us_read(cs); + return timer_readl(TIMERUS_CNTR_1US); } static struct clock_event_device tegra_clockevent = { @@ -124,21 +112,33 @@ static struct clock_event_device tegra_clockevent = { .set_mode = tegra_timer_set_mode, }; -static struct clocksource tegra_clocksource_us = { +static struct clocksource tegra_clocksource = { .name = "timer_us", .rating = 300, - .read = tegra_clocksource_us_read, - .suspend= tegra_clocksource_us_suspend, - .resume = tegra_clocksource_us_resume, - .mask = 0x7FFFFFFFFFFFFFFFULL, + .read = tegra_clocksource_read, + .mask = CLOCKSOURCE_MASK(32), .flags = CLOCK_SOURCE_IS_CONTINUOUS, }; unsigned long long sched_clock(void) { - return tegra_clocksource_us.read(&tegra_clocksource_us) * 1000; + return tegra_sched_clock_offset + + cnt32_to_63(timer_readl(TIMERUS_CNTR_1US)) * NSEC_PER_USEC; +} + +static void tegra_sched_clock_suspend(void) +{ + tegra_sched_clock_suspend_val = sched_clock(); + tegra_sched_clock_suspend_rtc = tegra_rtc_read_ms(); } +static void tegra_sched_clock_resume(void) +{ + u64 rtc_offset_ms = tegra_rtc_read_ms() - tegra_sched_clock_suspend_rtc; + tegra_sched_clock_offset = tegra_sched_clock_suspend_val + + rtc_offset_ms * NSEC_PER_MSEC - + (sched_clock() - tegra_sched_clock_offset); +} /* * tegra_rtc_read - Reads the Tegra RTC registers @@ -150,7 +150,7 @@ u64 tegra_rtc_read_ms(void) { u32 ms = readl(rtc_base + RTC_MILLISECONDS); u32 s = readl(rtc_base + RTC_SHADOW_SECONDS); - return (u64)s * 1000 + ms; + return (u64)s * MSEC_PER_SEC + ms; } /* @@ -174,7 +174,7 @@ void read_persistent_clock(struct timespec *ts) persistent_ms = tegra_rtc_read_ms(); delta = persistent_ms - last_persistent_ms; - timespec_add_ns(tsp, delta * 1000000); + timespec_add_ns(tsp, delta * NSEC_PER_MSEC); *ts = *tsp; } @@ -234,8 +234,8 @@ static void __init tegra_init_timer(void) WARN(1, "Unknown clock rate"); } - if (clocksource_register_hz(&tegra_clocksource_us, 1000000)) { - printk(KERN_ERR "Failed to register us clocksource\n"); + if (clocksource_register_hz(&tegra_clocksource, 1000000)) { + printk(KERN_ERR "Failed to register clocksource\n"); BUG(); } @@ -285,10 +285,12 @@ unsigned long tegra_lp2_timer_remain(void) static u32 usec_config; void tegra_timer_suspend(void) { + tegra_sched_clock_suspend(); usec_config = timer_readl(TIMERUS_USEC_CFG); } void tegra_timer_resume(void) { timer_writel(usec_config, TIMERUS_USEC_CFG); + tegra_sched_clock_resume(); } diff --git a/drivers/usb/host/ehci-tegra.c b/drivers/usb/host/ehci-tegra.c index 21c58dfb9035..262bbb01228b 100644 --- a/drivers/usb/host/ehci-tegra.c +++ b/drivers/usb/host/ehci-tegra.c @@ -35,7 +35,6 @@ struct tegra_ehci_context { bool valid; u32 command; - u32 intr_enable; u32 frame_list; u32 async_next; u32 txfilltunning; @@ -215,9 +214,6 @@ static void tegra_ehci_restart(struct usb_hcd *hcd) /* flush posted writes */ ehci_readl(ehci, &ehci->regs->command); up_write(&ehci_cf_port_reset_rwsem); - - /* Turn On Interrupts */ - ehci_writel(ehci, INTR_MASK, &ehci->regs->intr_enable); } static int tegra_usb_suspend(struct usb_hcd *hcd) @@ -237,7 +233,6 @@ static int tegra_usb_suspend(struct usb_hcd *hcd) context->valid = false; } else { context->command = readl(&hw->command); - context->intr_enable = readl(&hw->intr_enable); context->frame_list = readl(&hw->frame_list); context->async_next = readl(&hw->async_next); context->txfilltunning = readl(&hw->reserved[2]); @@ -264,8 +259,12 @@ static int tegra_usb_resume(struct usb_hcd *hcd) set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); tegra_ehci_power_up(ehci_to_hcd(tegra->ehci)); - if (!context->valid) + if (!context->valid) { + /* Wait for the phy to detect new devices + * before we restart the controller */ + msleep(10); goto restart; + } /* Restore register context */ writel(TEGRA_USB_USBMODE_HOST, &hw->reserved[19]); @@ -333,10 +332,6 @@ static int tegra_usb_resume(struct usb_hcd *hcd) } } - /* Restore interrupt register */ - writel(context->intr_enable, &hw->intr_enable); - udelay(10); - return 0; restart: diff --git a/drivers/video/tegra/dc/dc.c b/drivers/video/tegra/dc/dc.c index 946d3da7dc2c..2819a93d8442 100644 --- a/drivers/video/tegra/dc/dc.c +++ b/drivers/video/tegra/dc/dc.c @@ -1041,6 +1041,7 @@ static int tegra_dc_probe(struct nvhost_device *ndev) void __iomem *base; int irq; int i; + unsigned long emc_clk_rate; if (!ndev->dev.platform_data) { dev_err(&ndev->dev, "no platform data\n"); @@ -1097,13 +1098,6 @@ static int tegra_dc_probe(struct nvhost_device *ndev) goto err_put_clk; } - /* - * The emc is a shared clock, it will be set to the highest - * requested rate from any user. Set the rate to ULONG_MAX to - * always request the max rate whenever this request is enabled - */ - clk_set_rate(emc_clk, ULONG_MAX); - dc->clk = clk; dc->emc_clk = emc_clk; dc->base_res = base_res; @@ -1112,6 +1106,13 @@ static int tegra_dc_probe(struct nvhost_device *ndev) dc->ndev = ndev; dc->pdata = ndev->dev.platform_data; + /* + * The emc is a shared clock, it will be set based on + * the requirements for each user on the bus. + */ + emc_clk_rate = dc->pdata->emc_clk_rate; + clk_set_rate(emc_clk, emc_clk_rate ? emc_clk_rate : ULONG_MAX); + if (dc->pdata->flags & TEGRA_DC_FLAG_ENABLED) dc->enabled = true; |