arm: tegra: Add Tegra3 wakeup sources
Scott Williams [Wed, 5 Jan 2011 16:44:01 +0000 (08:44 -0800)]
Original-Change-Id: I77cb790db20cc8c8b67069130c0bc8724ba8934e
Reviewed-on: http://git-master/r/15027
Tested-by: Jin Qian <jqian@nvidia.com>
Reviewed-by: Krishna Reddy <vdumpa@nvidia.com>
Reviewed-by: Aleksandr Frid <afrid@nvidia.com>
Reviewed-by: Scott Williams <scwilliams@nvidia.com>
Original-Change-Id: I45764ed134dc0be2a21d7641692efb9c847a9b7a

Rebase-Id: R0a34fc6fc83145c3720471d359216befb5d0bf5b

arch/arm/mach-tegra/pm-irq.c
arch/arm/mach-tegra/wakeups-t2.h
arch/arm/mach-tegra/wakeups-t3.h [new file with mode: 0644]

index 1be1db8..98657e9 100644 (file)
 #define PMC_WAKE_LEVEL         0x10
 #define PMC_WAKE_STATUS                0x14
 #define PMC_SW_WAKE_STATUS     0x18
+#ifndef CONFIG_ARCH_TEGRA_2x_SOC
+#define PMC_WAKE2_MASK         0x160
+#define PMC_WAKE2_LEVEL                0x164
+#define PMC_WAKE2_STATUS       0x168
+#define PMC_SW_WAKE2_STATUS    0x16C
+#endif
 
 static void __iomem *pmc = IO_ADDRESS(TEGRA_PMC_BASE);
 
-static u32 tegra_lp0_wake_enb;
-static u32 tegra_lp0_wake_level;
-static u32 tegra_lp0_wake_level_any;
+static u64 tegra_lp0_wake_enb;
+static u64 tegra_lp0_wake_level;
+static u64 tegra_lp0_wake_level_any;
 static int tegra_prevent_lp0;
 
-static unsigned int tegra_wake_irq_count[32];
+static unsigned int tegra_wake_irq_count[64];
 
 static bool debug_lp0;
 module_param(debug_lp0, bool, S_IRUGO | S_IWUSR);
@@ -64,6 +70,56 @@ static void pmc_32kwritel(u32 val, unsigned long offs)
        udelay(130);
 }
 
+static inline void write_pmc_wake_mask(u64 value)
+{
+       writel((u32)value, pmc + PMC_WAKE_MASK);
+#ifndef CONFIG_ARCH_TEGRA_2x_SOC
+       __raw_writel((u32)(value >> 32), pmc + PMC_WAKE2_MASK);
+#endif
+}
+
+static inline u64 read_pmc_wake_level(void)
+{
+       u64 reg;
+
+#ifdef CONFIG_ARCH_TEGRA_2x_SOC
+       reg = readl(pmc + PMC_WAKE_LEVEL);
+#else
+       reg = __raw_readl(pmc + PMC_WAKE_LEVEL);
+       reg |= ((u64)readl(pmc + PMC_WAKE2_LEVEL)) << 32;
+#endif
+       return reg;
+}
+
+static inline void write_pmc_wake_level(u64 value)
+{
+       writel((u32)value, pmc + PMC_WAKE_LEVEL);
+#ifndef CONFIG_ARCH_TEGRA_2x_SOC
+       __raw_writel((u32)(value >> 32), pmc + PMC_WAKE2_LEVEL);
+#endif
+}
+
+static inline u64 read_pmc_wake_status(void)
+{
+       u64 reg;
+
+#ifdef CONFIG_ARCH_TEGRA_2x_SOC
+       reg = readl(pmc + PMC_WAKE_STATUS);
+#else
+       reg = __raw_readl(pmc + PMC_WAKE_STATUS);
+       reg |= ((u64)readl(pmc + PMC_WAKE2_STATUS)) << 32;
+#endif
+       return reg;
+}
+
+static inline void clear_pmc_sw_wake_status(void)
+{
+       pmc_32kwritel(0, PMC_SW_WAKE_STATUS);
+#ifndef CONFIG_ARCH_TEGRA_2x_SOC
+       pmc_32kwritel(0, PMC_SW_WAKE2_STATUS);
+#endif
+}
+
 int tegra_pm_irq_set_wake(int irq, int enable)
 {
        int wake = tegra_irq_to_wake(irq);
@@ -84,9 +140,9 @@ int tegra_pm_irq_set_wake(int irq, int enable)
        }
 
        if (enable)
-               tegra_lp0_wake_enb |= 1 << wake;
+               tegra_lp0_wake_enb |= 1ull << wake;
        else
-               tegra_lp0_wake_enb &= ~(1 << wake);
+               tegra_lp0_wake_enb &= ~(1ull << wake);
 
        return 0;
 }
@@ -121,12 +177,11 @@ int tegra_pm_irq_set_wake_type(int irq, int flow_type)
 }
 
 /* translate lp0 wake sources back into irqs to catch edge triggered wakeups */
-static void tegra_pm_irq_syscore_resume(void)
+static void tegra_pm_irq_syscore_resume_helper(unsigned long wake_status)
 {
        int wake;
        int irq;
        struct irq_desc *desc;
-       unsigned long wake_status = readl(pmc + PMC_WAKE_STATUS);
 
        for_each_set_bit(wake, &wake_status, sizeof(wake_status) * 8) {
                irq = tegra_wake_to_irq(wake);
@@ -150,16 +205,26 @@ static void tegra_pm_irq_syscore_resume(void)
        }
 }
 
+static void tegra_pm_irq_syscore_resume(void)
+{
+       unsigned long long wake_status = read_pmc_wake_status();
+
+       tegra_pm_irq_syscore_resume_helper((unsigned long)wake_status);
+#ifndef CONFIG_ARCH_TEGRA_2x_SOC
+       tegra_pm_irq_syscore_resume_helper((unsigned long)(wake_status >> 32));
+#endif
+}
+
 /* set up lp0 wake sources */
 static int tegra_pm_irq_syscore_suspend(void)
 {
        u32 temp;
-       u32 status;
-       u32 lvl;
-       u32 wake_level;
-       u32 wake_enb;
+       u64 status;
+       u64 lvl;
+       u64 wake_level;
+       u64 wake_enb;
 
-       pmc_32kwritel(0, PMC_SW_WAKE_STATUS);
+       clear_pmc_sw_wake_status();
 
        temp = readl(pmc + PMC_CTRL);
        temp |= PMC_CTRL_LATCH_WAKEUPS;
@@ -168,9 +233,9 @@ static int tegra_pm_irq_syscore_suspend(void)
        temp &= ~PMC_CTRL_LATCH_WAKEUPS;
        pmc_32kwritel(temp, PMC_CTRL);
 
-       status = readl(pmc + PMC_SW_WAKE_STATUS);
+       status = read_pmc_wake_status();
 
-       lvl = readl(pmc + PMC_WAKE_LEVEL);
+       lvl = read_pmc_wake_level();
 
        /* flip the wakeup trigger for any-edge triggered pads
         * which are currently asserting as wakeups */
@@ -185,9 +250,9 @@ static int tegra_pm_irq_syscore_suspend(void)
                wake_enb = 0xffffffff;
        }
 
-       writel(wake_level, pmc + PMC_WAKE_LEVEL);
+       write_pmc_wake_level(wake_level);
 
-       writel(wake_enb, pmc + PMC_WAKE_MASK);
+       write_pmc_wake_mask(wake_enb);
 
        return 0;
 }
index 0cd6e0f..eb193c0 100644 (file)
 #ifndef __MACH_TEGRA_WAKEUPS_T2_H
 #define __MACH_TEGRA_WAKEUPS_T2_H
 
+#ifndef CONFIG_ARCH_TEGRA_2x_SOC
+#error "Tegra 2 wakeup sources valid only for CONFIG_ARCH_TEGRA_2x_SOC"
+#endif
+
 int tegra_irq_to_wake(int irq);
 int tegra_wake_to_irq(int wake);
 
diff --git a/arch/arm/mach-tegra/wakeups-t3.h b/arch/arm/mach-tegra/wakeups-t3.h
new file mode 100644 (file)
index 0000000..f811d89
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * arch/arm/mach-tegra/wakeups-t3.h
+ *
+ * Declarations of Tegra 3 LP0 wakeup sources
+ *
+ * Copyright (c) 2010, NVIDIA Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+#ifndef __MACH_TEGRA_WAKEUPS_T3_H
+#define __MACH_TEGRA_WAKEUPS_T3_H
+
+#ifndef CONFIG_ARCH_TEGRA_3x_SOC
+#error "Tegra 3 wakeup sources valid only for CONFIG_ARCH_TEGRA_3x_SOC"
+#endif
+
+#define TEGRA_WAKE_GPIO_PO5    (1ull << 0)
+#define TEGRA_WAKE_GPIO_PV1    (1ull << 1)
+#define TEGRA_WAKE_GPIO_PL1    (1ull << 2)
+#define TEGRA_WAKE_GPIO_PB6    (1ull << 3)
+#define TEGRA_WAKE_GPIO_PN7    (1ull << 4)
+#define TEGRA_WAKE_GPIO_PBB6   (1ull << 5)
+#define TEGRA_WAKE_GPIO_PU5    (1ull << 6)
+#define TEGRA_WAKE_GPIO_PU6    (1ull << 7)
+#define TEGRA_WAKE_GPIO_PC7    (1ull << 8)
+#define TEGRA_WAKE_GPIO_PS2    (1ull << 9)
+#define TEGRA_WAKE_GPIO_PAA1   (1ull << 10)
+#define TEGRA_WAKE_GPIO_PW3    (1ull << 11)
+#define TEGRA_WAKE_GPIO_PW2    (1ull << 12)
+#define TEGRA_WAKE_GPIO_PY6    (1ull << 13)
+#define TEGRA_WAKE_GPIO_PDD3   (1ull << 14)
+#define TEGRA_WAKE_GPIO_PJ2    (1ull << 15)
+#define TEGRA_WAKE_RTC_ALARM   (1ull << 16)
+#define TEGRA_WAKE_KBC_EVENT   (1ull << 17)
+#define TEGRA_WAKE_PWR_INT     (1ull << 18)
+#define TEGRA_WAKE_USB1_VBUS   (1ull << 19)
+#define TEGRA_WAKE_USB2_VBUS   (1ull << 20)
+#define TEGRA_WAKE_USB1_ID     (1ull << 21)
+#define TEGRA_WAKE_USB2_ID     (1ull << 22)
+#define TEGRA_WAKE_GPIO_PI5    (1ull << 23)
+#define TEGRA_WAKE_GPIO_PV0    (1ull << 24)
+#define TEGRA_WAKE_GPIO_PS4    (1ull << 25)
+#define TEGRA_WAKE_GPIO_PS5    (1ull << 26)
+#define TEGRA_WAKE_GPIO_PS0    (1ull << 27)
+#define TEGRA_WAKE_GPIO_PS6    (1ull << 28)
+#define TEGRA_WAKE_GPIO_PS7    (1ull << 29)
+#define TEGRA_WAKE_GPIO_PN2    (1ull << 30)
+/* bit 31 is unused */
+
+#define TEGRA_WAKE_GPIO_PO4    (1ull << 32)
+#define TEGRA_WAKE_GPIO_PJ0    (1ull << 33)
+#define TEGRA_WAKE_GPIO_PK2    (1ull << 34)
+#define TEGRA_WAKE_GPIO_PI6    (1ull << 35)
+#define TEGRA_WAKE_GPIO_PBB1   (1ull << 36)
+#define TEGRA_WAKE_USB3_ID     (1ull << 37)
+#define TEGRA_WAKE_USB3_VBUS   (1ull << 38)
+
+#endif