summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/arm/mach-tegra/include/mach/dc.h1
-rw-r--r--arch/arm/mach-tegra/timer.c64
-rw-r--r--drivers/usb/host/ehci-tegra.c15
-rw-r--r--drivers/video/tegra/dc/dc.c15
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;