···11NVIDIA Tegra Power Management Controller (PMC)2233-Properties:33+The PMC block interacts with an external Power Management Unit. The PMC44+mostly controls the entry and exit of the system from different sleep55+modes. It provides power-gating controllers for SoC and CPU power-islands.66+77+Required properties:48- name : Should be pmc59- compatible : Should contain "nvidia,tegra<chip>-pmc".610- reg : Offset and length of the register set for the device1111+- clocks : Must contain an entry for each entry in clock-names.1212+- clock-names : Must include the following entries:1313+ "pclk" (The Tegra clock of that name),1414+ "clk32k_in" (The 32KHz clock input to Tegra).1515+1616+Optional properties:717- nvidia,invert-interrupt : If present, inverts the PMU interrupt signal.818 The PMU is an external Power Management Unit, whose interrupt output919 signal is fed into the PMC. This signal is optionally inverted, and then1020 fed into the ARM GIC. The PMC is not involved in the detection or1121 handling of this interrupt signal, merely its inversion.2222+- nvidia,suspend-mode : The suspend mode that the platform should use.2323+ Valid values are 0, 1 and 2:2424+ 0 (LP0): CPU + Core voltage off and DRAM in self-refresh2525+ 1 (LP1): CPU voltage off and DRAM in self-refresh2626+ 2 (LP2): CPU voltage off2727+- nvidia,core-power-req-active-high : Boolean, core power request active-high2828+- nvidia,sys-clock-req-active-high : Boolean, system clock request active-high2929+- nvidia,combined-power-req : Boolean, combined power request for CPU & Core3030+- nvidia,cpu-pwr-good-en : Boolean, CPU power good signal (from PMIC to PMC)3131+ is enabled.3232+3333+Required properties when nvidia,suspend-mode is specified:3434+- nvidia,cpu-pwr-good-time : CPU power good time in uS.3535+- nvidia,cpu-pwr-off-time : CPU power off time in uS.3636+- nvidia,core-pwr-good-time : <Oscillator-stable-time Power-stable-time>3737+ Core power good time in uS.3838+- nvidia,core-pwr-off-time : Core power off time in uS.3939+4040+Required properties when nvidia,suspend-mode=<0>:4141+- nvidia,lp0-vec : <start length> Starting address and length of LP0 vector4242+ The LP0 vector contains the warm boot code that is executed by AVP when4343+ resuming from the LP0 state. The AVP (Audio-Video Processor) is an ARM74444+ processor and always being the first boot processor when chip is power on4545+ or resume from deep sleep mode. When the system is resumed from the deep4646+ sleep mode, the warm boot code will restore some PLLs, clocks and then4747+ bring up CPU0 for resuming the system.12481349Example:14505151+/ SoC dts including file1552pmc@7000f400 {1653 compatible = "nvidia,tegra20-pmc";1754 reg = <0x7000e400 0x400>;5555+ clocks = <&tegra_car 110>, <&clk32k_in>;5656+ clock-names = "pclk", "clk32k_in";1857 nvidia,invert-interrupt;5858+ nvidia,suspend-mode = <1>;5959+ nvidia,cpu-pwr-good-time = <2000>;6060+ nvidia,cpu-pwr-off-time = <100>;6161+ nvidia,core-pwr-good-time = <3845 3845>;6262+ nvidia,core-pwr-off-time = <458>;6363+ nvidia,core-power-req-active-high;6464+ nvidia,sys-clock-req-active-high;6565+ nvidia,lp0-vec = <0xbdffd000 0x2000>;6666+};6767+6868+/ Tegra board dts file6969+{7070+ ...7171+ clocks {7272+ compatible = "simple-bus";7373+ #address-cells = <1>;7474+ #size-cells = <0>;7575+7676+ clk32k_in: clock {7777+ compatible = "fixed-clock";7878+ reg=<0>;7979+ #clock-cells = <0>;8080+ clock-frequency = <32768>;8181+ };8282+ };8383+ ...1984};
···11-/*22- * NVIDIA Tegra114 device tree board support33- *44- * Copyright (C) 2013 NVIDIA Corporation55- *66- * This software is licensed under the terms of the GNU General Public77- * License version 2, as published by the Free Software Foundation, and88- * may be copied, distributed, and modified under those terms.99- *1010- * This program is distributed in the hope that it will be useful,1111- * but WITHOUT ANY WARRANTY; without even the implied warranty of1212- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the1313- * GNU General Public License for more details.1414- *1515- */1616-1717-#include <linux/of.h>1818-#include <linux/of_platform.h>1919-#include <linux/clocksource.h>2020-2121-#include <asm/mach/arch.h>2222-2323-#include "board.h"2424-#include "common.h"2525-2626-static void __init tegra114_dt_init(void)2727-{2828- of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);2929-}3030-3131-static const char * const tegra114_dt_board_compat[] = {3232- "nvidia,tegra114",3333- NULL,3434-};3535-3636-DT_MACHINE_START(TEGRA114_DT, "NVIDIA Tegra114 (Flattened Device Tree)")3737- .smp = smp_ops(tegra_smp_ops),3838- .map_io = tegra_map_common_io,3939- .init_early = tegra114_init_early,4040- .init_irq = tegra_dt_init_irq,4141- .init_time = clocksource_of_init,4242- .init_machine = tegra114_dt_init,4343- .init_late = tegra_init_late,4444- .restart = tegra_assert_system_reset,4545- .dt_compat = tegra114_dt_board_compat,4646-MACHINE_END
···11-/*22- * arch/arm/mach-tegra/board-dt-tegra30.c33- *44- * NVIDIA Tegra30 device tree board support55- *66- * Copyright (C) 2011 NVIDIA Corporation77- *88- * Derived from:99- *1010- * arch/arm/mach-tegra/board-dt-tegra20.c1111- *1212- * Copyright (C) 2010 Secret Lab Technologies, Ltd.1313- * Copyright (C) 2010 Google, Inc.1414- *1515- * This software is licensed under the terms of the GNU General Public1616- * License version 2, as published by the Free Software Foundation, and1717- * may be copied, distributed, and modified under those terms.1818- *1919- * This program is distributed in the hope that it will be useful,2020- * but WITHOUT ANY WARRANTY; without even the implied warranty of2121- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the2222- * GNU General Public License for more details.2323- *2424- */2525-2626-#include <linux/clocksource.h>2727-#include <linux/kernel.h>2828-#include <linux/of.h>2929-#include <linux/of_address.h>3030-#include <linux/of_fdt.h>3131-#include <linux/of_irq.h>3232-#include <linux/of_platform.h>3333-3434-#include <asm/mach/arch.h>3535-3636-#include "board.h"3737-#include "common.h"3838-#include "iomap.h"3939-4040-static void __init tegra30_dt_init(void)4141-{4242- of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);4343-}4444-4545-static const char *tegra30_dt_board_compat[] = {4646- "nvidia,tegra30",4747- NULL4848-};4949-5050-DT_MACHINE_START(TEGRA30_DT, "NVIDIA Tegra30 (Flattened Device Tree)")5151- .smp = smp_ops(tegra_smp_ops),5252- .map_io = tegra_map_common_io,5353- .init_early = tegra30_init_early,5454- .init_irq = tegra_dt_init_irq,5555- .init_time = clocksource_of_init,5656- .init_machine = tegra30_dt_init,5757- .init_late = tegra_init_late,5858- .restart = tegra_assert_system_reset,5959- .dt_compat = tegra30_dt_board_compat,6060-MACHINE_END
···11/*22- *32 * Copyright (C) 2002 ARM Ltd.43 * All Rights Reserved55- * Copyright (c) 2010, 2012 NVIDIA Corporation. All rights reserved.44+ * Copyright (c) 2010, 2012-2013, NVIDIA Corporation. All rights reserved.65 *76 * This program is free software; you can redistribute it and/or modify87 * it under the terms of the GNU General Public License version 2 as···1415#include <asm/cacheflush.h>1516#include <asm/smp_plat.h>16171818+#include "fuse.h"1719#include "sleep.h"18201921static void (*tegra_hotplug_shutdown)(void);···5656 return cpu == 0 ? -EPERM : 0;5757}58585959-#ifdef CONFIG_ARCH_TEGRA_2x_SOC6060-extern void tegra20_hotplug_shutdown(void);6161-void __init tegra20_hotplug_init(void)5959+void __init tegra_hotplug_init(void)6260{6363- tegra_hotplug_shutdown = tegra20_hotplug_shutdown;6464-}6565-#endif6161+ if (!IS_ENABLED(CONFIG_HOTPLUG_CPU))6262+ return;66636767-#ifdef CONFIG_ARCH_TEGRA_3x_SOC6868-extern void tegra30_hotplug_shutdown(void);6969-void __init tegra30_hotplug_init(void)7070-{7171- tegra_hotplug_shutdown = tegra30_hotplug_shutdown;6464+ if (IS_ENABLED(CONFIG_ARCH_TEGRA_2x_SOC) && tegra_chip_id == TEGRA20)6565+ tegra_hotplug_shutdown = tegra20_hotplug_shutdown;6666+ if (IS_ENABLED(CONFIG_ARCH_TEGRA_3x_SOC) && tegra_chip_id == TEGRA30)6767+ tegra_hotplug_shutdown = tegra30_hotplug_shutdown;7268}7373-#endif
+95-1
arch/arm/mach-tegra/irq.c
···44 * Author:55 * Colin Cross <ccross@android.com>66 *77- * Copyright (C) 2010, NVIDIA Corporation77+ * Copyright (C) 2010,2013, NVIDIA Corporation88 *99 * This software is licensed under the terms of the GNU General Public1010 * License version 2, as published by the Free Software Foundation, and···2323#include <linux/io.h>2424#include <linux/of.h>2525#include <linux/irqchip/arm-gic.h>2626+#include <linux/syscore_ops.h>26272728#include "board.h"2829#include "iomap.h"···4443#define ICTLR_COP_IEP_CLASS 0x3c45444645#define FIRST_LEGACY_IRQ 324646+#define TEGRA_MAX_NUM_ICTLRS 547474848#define SGI_MASK 0xFFFF4949···5755 IO_ADDRESS(TEGRA_QUATERNARY_ICTLR_BASE),5856 IO_ADDRESS(TEGRA_QUINARY_ICTLR_BASE),5957};5858+5959+#ifdef CONFIG_PM_SLEEP6060+static u32 cop_ier[TEGRA_MAX_NUM_ICTLRS];6161+static u32 cop_iep[TEGRA_MAX_NUM_ICTLRS];6262+static u32 cpu_ier[TEGRA_MAX_NUM_ICTLRS];6363+static u32 cpu_iep[TEGRA_MAX_NUM_ICTLRS];6464+6565+static u32 ictlr_wake_mask[TEGRA_MAX_NUM_ICTLRS];6666+#endif60676168bool tegra_pending_sgi(void)6269{···136125 return 1;137126}138127128128+#ifdef CONFIG_PM_SLEEP129129+static int tegra_set_wake(struct irq_data *d, unsigned int enable)130130+{131131+ u32 irq = d->irq;132132+ u32 index, mask;133133+134134+ if (irq < FIRST_LEGACY_IRQ ||135135+ irq >= FIRST_LEGACY_IRQ + num_ictlrs * 32)136136+ return -EINVAL;137137+138138+ index = ((irq - FIRST_LEGACY_IRQ) / 32);139139+ mask = BIT((irq - FIRST_LEGACY_IRQ) % 32);140140+ if (enable)141141+ ictlr_wake_mask[index] |= mask;142142+ else143143+ ictlr_wake_mask[index] &= ~mask;144144+145145+ return 0;146146+}147147+148148+static int tegra_legacy_irq_suspend(void)149149+{150150+ unsigned long flags;151151+ int i;152152+153153+ local_irq_save(flags);154154+ for (i = 0; i < num_ictlrs; i++) {155155+ void __iomem *ictlr = ictlr_reg_base[i];156156+ /* Save interrupt state */157157+ cpu_ier[i] = readl_relaxed(ictlr + ICTLR_CPU_IER);158158+ cpu_iep[i] = readl_relaxed(ictlr + ICTLR_CPU_IEP_CLASS);159159+ cop_ier[i] = readl_relaxed(ictlr + ICTLR_COP_IER);160160+ cop_iep[i] = readl_relaxed(ictlr + ICTLR_COP_IEP_CLASS);161161+162162+ /* Disable COP interrupts */163163+ writel_relaxed(~0ul, ictlr + ICTLR_COP_IER_CLR);164164+165165+ /* Disable CPU interrupts */166166+ writel_relaxed(~0ul, ictlr + ICTLR_CPU_IER_CLR);167167+168168+ /* Enable the wakeup sources of ictlr */169169+ writel_relaxed(ictlr_wake_mask[i], ictlr + ICTLR_CPU_IER_SET);170170+ }171171+ local_irq_restore(flags);172172+173173+ return 0;174174+}175175+176176+static void tegra_legacy_irq_resume(void)177177+{178178+ unsigned long flags;179179+ int i;180180+181181+ local_irq_save(flags);182182+ for (i = 0; i < num_ictlrs; i++) {183183+ void __iomem *ictlr = ictlr_reg_base[i];184184+ writel_relaxed(cpu_iep[i], ictlr + ICTLR_CPU_IEP_CLASS);185185+ writel_relaxed(~0ul, ictlr + ICTLR_CPU_IER_CLR);186186+ writel_relaxed(cpu_ier[i], ictlr + ICTLR_CPU_IER_SET);187187+ writel_relaxed(cop_iep[i], ictlr + ICTLR_COP_IEP_CLASS);188188+ writel_relaxed(~0ul, ictlr + ICTLR_COP_IER_CLR);189189+ writel_relaxed(cop_ier[i], ictlr + ICTLR_COP_IER_SET);190190+ }191191+ local_irq_restore(flags);192192+}193193+194194+static struct syscore_ops tegra_legacy_irq_syscore_ops = {195195+ .suspend = tegra_legacy_irq_suspend,196196+ .resume = tegra_legacy_irq_resume,197197+};198198+199199+int tegra_legacy_irq_syscore_init(void)200200+{201201+ register_syscore_ops(&tegra_legacy_irq_syscore_ops);202202+203203+ return 0;204204+}205205+#else206206+#define tegra_set_wake NULL207207+#endif208208+139209void __init tegra_init_irq(void)140210{141211 int i;···242150 gic_arch_extn.irq_mask = tegra_mask;243151 gic_arch_extn.irq_unmask = tegra_unmask;244152 gic_arch_extn.irq_retrigger = tegra_retrigger;153153+ gic_arch_extn.irq_set_wake = tegra_set_wake;154154+ gic_arch_extn.flags = IRQCHIP_MASK_ON_SUSPEND;245155246156 /*247157 * Check if there is a devicetree present, since the GIC will be
···2626#include <asm/smp_scu.h>2727#include <asm/smp_plat.h>28282929-#include <mach/powergate.h>3030-3129#include "fuse.h"3230#include "flowctrl.h"3331#include "reset.h"3232+#include "pmc.h"34333534#include "common.h"3635#include "iomap.h"37363838-extern void tegra_secondary_startup(void);3939-4037static cpumask_t tegra_cpu_init_mask;4141-4242-#define EVP_CPU_RESET_VECTOR \4343- (IO_ADDRESS(TEGRA_EXCEPTION_VECTORS_BASE) + 0x100)44384539static void __cpuinit tegra_secondary_init(unsigned int cpu)4640{···4854 cpumask_set_cpu(cpu, &tegra_cpu_init_mask);4955}50565151-static int tegra20_power_up_cpu(unsigned int cpu)5757+5858+static int tegra20_boot_secondary(unsigned int cpu, struct task_struct *idle)5259{5353- /* Enable the CPU clock. */6060+ cpu = cpu_logical_map(cpu);6161+6262+ /*6363+ * Force the CPU into reset. The CPU must remain in reset when6464+ * the flow controller state is cleared (which will cause the6565+ * flow controller to stop driving reset if the CPU has been6666+ * power-gated via the flow controller). This will have no6767+ * effect on first boot of the CPU since it should already be6868+ * in reset.6969+ */7070+ tegra_put_cpu_in_reset(cpu);7171+7272+ /*7373+ * Unhalt the CPU. If the flow controller was used to7474+ * power-gate the CPU this will cause the flow controller to7575+ * stop driving reset. The CPU will remain in reset because the7676+ * clock and reset block is now driving reset.7777+ */7878+ flowctrl_write_cpu_halt(cpu, 0);7979+5480 tegra_enable_cpu_clock(cpu);5555-5656- /* Clear flow controller CSR. */5757- flowctrl_write_cpu_csr(cpu, 0);5858-8181+ flowctrl_write_cpu_csr(cpu, 0); /* Clear flow controller CSR. */8282+ tegra_cpu_out_of_reset(cpu);5983 return 0;6084}61856262-static int tegra30_power_up_cpu(unsigned int cpu)8686+static int tegra30_boot_secondary(unsigned int cpu, struct task_struct *idle)6387{6464- int ret, pwrgateid;8888+ int ret;6589 unsigned long timeout;66906767- pwrgateid = tegra_cpu_powergate_id(cpu);6868- if (pwrgateid < 0)6969- return pwrgateid;9191+ cpu = cpu_logical_map(cpu);9292+ tegra_put_cpu_in_reset(cpu);9393+ flowctrl_write_cpu_halt(cpu, 0);70947195 /*7296 * The power up sequence of cold boot CPU and warm boot CPU···9785 * the IO clamps.9886 * For cold boot CPU, do not wait. After the cold boot CPU be9987 * booted, it will run to tegra_secondary_init() and set100100- * tegra_cpu_init_mask which influences what tegra30_power_up_cpu()8888+ * tegra_cpu_init_mask which influences what tegra30_boot_secondary()10189 * next time around.10290 */10391 if (cpumask_test_cpu(cpu, &tegra_cpu_init_mask)) {10492 timeout = jiffies + msecs_to_jiffies(50);10593 do {106106- if (!tegra_powergate_is_powered(pwrgateid))9494+ if (tegra_pmc_cpu_is_powered(cpu))10795 goto remove_clamps;10896 udelay(10);10997 } while (time_before(jiffies, timeout));···115103 * be un-gated by un-toggling the power gate register116104 * manually.117105 */118118- if (!tegra_powergate_is_powered(pwrgateid)) {119119- ret = tegra_powergate_power_on(pwrgateid);106106+ if (!tegra_pmc_cpu_is_powered(cpu)) {107107+ ret = tegra_pmc_cpu_power_on(cpu);120108 if (ret)121109 return ret;122110123111 /* Wait for the power to come up. */124112 timeout = jiffies + msecs_to_jiffies(100);125125- while (tegra_powergate_is_powered(pwrgateid)) {113113+ while (tegra_pmc_cpu_is_powered(cpu)) {126114 if (time_after(jiffies, timeout))127115 return -ETIMEDOUT;128116 udelay(10);···135123 udelay(10);136124137125 /* Remove I/O clamps. */138138- ret = tegra_powergate_remove_clamping(pwrgateid);126126+ ret = tegra_pmc_cpu_remove_clamping(cpu);127127+ if (ret)128128+ return ret;129129+139130 udelay(10);140131141141- /* Clear flow controller CSR. */142142- flowctrl_write_cpu_csr(cpu, 0);143143-132132+ flowctrl_write_cpu_csr(cpu, 0); /* Clear flow controller CSR. */133133+ tegra_cpu_out_of_reset(cpu);144134 return 0;145135}146136147147-static int __cpuinit tegra_boot_secondary(unsigned int cpu, struct task_struct *idle)137137+static int tegra114_boot_secondary(unsigned int cpu, struct task_struct *idle)148138{149149- int status;150150-151139 cpu = cpu_logical_map(cpu);140140+ return tegra_pmc_cpu_power_on(cpu);141141+}152142153153- /*154154- * Force the CPU into reset. The CPU must remain in reset when the155155- * flow controller state is cleared (which will cause the flow156156- * controller to stop driving reset if the CPU has been power-gated157157- * via the flow controller). This will have no effect on first boot158158- * of the CPU since it should already be in reset.159159- */160160- tegra_put_cpu_in_reset(cpu);143143+static int __cpuinit tegra_boot_secondary(unsigned int cpu,144144+ struct task_struct *idle)145145+{146146+ if (IS_ENABLED(CONFIG_ARCH_TEGRA_2x_SOC) && tegra_chip_id == TEGRA20)147147+ return tegra20_boot_secondary(cpu, idle);148148+ if (IS_ENABLED(CONFIG_ARCH_TEGRA_3x_SOC) && tegra_chip_id == TEGRA30)149149+ return tegra30_boot_secondary(cpu, idle);150150+ if (IS_ENABLED(CONFIG_ARCH_TEGRA_114_SOC) && tegra_chip_id == TEGRA114)151151+ return tegra114_boot_secondary(cpu, idle);161152162162- /*163163- * Unhalt the CPU. If the flow controller was used to power-gate the164164- * CPU this will cause the flow controller to stop driving reset.165165- * The CPU will remain in reset because the clock and reset block166166- * is now driving reset.167167- */168168- flowctrl_write_cpu_halt(cpu, 0);169169-170170- switch (tegra_chip_id) {171171- case TEGRA20:172172- status = tegra20_power_up_cpu(cpu);173173- break;174174- case TEGRA30:175175- status = tegra30_power_up_cpu(cpu);176176- break;177177- default:178178- status = -EINVAL;179179- break;180180- }181181-182182- if (status)183183- goto done;184184-185185- /* Take the CPU out of reset. */186186- tegra_cpu_out_of_reset(cpu);187187-done:188188- return status;153153+ return -EINVAL;189154}190155191156static void __init tegra_smp_prepare_cpus(unsigned int max_cpus)
+81-69
arch/arm/mach-tegra/pm.c
···2222#include <linux/cpumask.h>2323#include <linux/delay.h>2424#include <linux/cpu_pm.h>2525-#include <linux/clk.h>2525+#include <linux/suspend.h>2626#include <linux/err.h>2727#include <linux/clk/tegra.h>2828···3737#include "reset.h"3838#include "flowctrl.h"3939#include "fuse.h"4040+#include "pmc.h"4041#include "sleep.h"41424242-#define TEGRA_POWER_CPU_PWRREQ_OE (1 << 16) /* CPU pwr req enable */4343-4444-#define PMC_CTRL 0x04545-#define PMC_CPUPWRGOOD_TIMER 0xc84646-#define PMC_CPUPWROFF_TIMER 0xcc4747-4843#ifdef CONFIG_PM_SLEEP4949-static unsigned int g_diag_reg;5044static DEFINE_SPINLOCK(tegra_lp2_lock);5151-static void __iomem *pmc = IO_ADDRESS(TEGRA_PMC_BASE);5252-static struct clk *tegra_pclk;5345void (*tegra_tear_down_cpu)(void);5454-5555-void save_cpu_arch_register(void)5656-{5757- /* read diagnostic register */5858- asm("mrc p15, 0, %0, c15, c0, 1" : "=r"(g_diag_reg) : : "cc");5959- return;6060-}6161-6262-void restore_cpu_arch_register(void)6363-{6464- /* write diagnostic register */6565- asm("mcr p15, 0, %0, c15, c0, 1" : : "r"(g_diag_reg) : "cc");6666- return;6767-}6868-6969-static void set_power_timers(unsigned long us_on, unsigned long us_off)7070-{7171- unsigned long long ticks;7272- unsigned long long pclk;7373- unsigned long rate;7474- static unsigned long tegra_last_pclk;7575-7676- if (tegra_pclk == NULL) {7777- tegra_pclk = clk_get_sys(NULL, "pclk");7878- WARN_ON(IS_ERR(tegra_pclk));7979- }8080-8181- rate = clk_get_rate(tegra_pclk);8282-8383- if (WARN_ON_ONCE(rate <= 0))8484- pclk = 100000000;8585- else8686- pclk = rate;8787-8888- if ((rate != tegra_last_pclk)) {8989- ticks = (us_on * pclk) + 999999ull;9090- do_div(ticks, 1000000);9191- writel((unsigned long)ticks, pmc + PMC_CPUPWRGOOD_TIMER);9292-9393- ticks = (us_off * pclk) + 999999ull;9494- do_div(ticks, 1000000);9595- writel((unsigned long)ticks, pmc + PMC_CPUPWROFF_TIMER);9696- wmb();9797- }9898- tegra_last_pclk = pclk;9999-}1004610147/*10248 * restore_cpu_complex···65119 tegra_cpu_clock_resume();6612067121 flowctrl_cpu_suspend_exit(cpu);6868-6969- restore_cpu_arch_register();70122}7112372124/*···89145 tegra_cpu_clock_suspend();9014691147 flowctrl_cpu_suspend_enter(cpu);9292-9393- save_cpu_arch_register();94148}9514996150void tegra_clear_cpu_in_lp2(int phy_cpu_id)···139197 return 0;140198}141199142142-void tegra_idle_lp2_last(u32 cpu_on_time, u32 cpu_off_time)200200+void tegra_idle_lp2_last(void)143201{144144- u32 mode;145145-146146- /* Only the last cpu down does the final suspend steps */147147- mode = readl(pmc + PMC_CTRL);148148- mode |= TEGRA_POWER_CPU_PWRREQ_OE;149149- writel(mode, pmc + PMC_CTRL);150150-151151- set_power_timers(cpu_on_time, cpu_off_time);202202+ tegra_pmc_pm_set(TEGRA_SUSPEND_LP2);152203153204 cpu_cluster_pm_enter();154205 suspend_cpu_complex();···150215151216 restore_cpu_complex();152217 cpu_cluster_pm_exit();218218+}219219+220220+enum tegra_suspend_mode tegra_pm_validate_suspend_mode(221221+ enum tegra_suspend_mode mode)222222+{223223+ /* Tegra114 didn't support any suspending mode yet. */224224+ if (tegra_chip_id == TEGRA114)225225+ return TEGRA_SUSPEND_NONE;226226+227227+ /*228228+ * The Tegra devices only support suspending to LP2 currently.229229+ */230230+ if (mode > TEGRA_SUSPEND_LP2)231231+ return TEGRA_SUSPEND_LP2;232232+233233+ return mode;234234+}235235+236236+static const char *lp_state[TEGRA_MAX_SUSPEND_MODE] = {237237+ [TEGRA_SUSPEND_NONE] = "none",238238+ [TEGRA_SUSPEND_LP2] = "LP2",239239+ [TEGRA_SUSPEND_LP1] = "LP1",240240+ [TEGRA_SUSPEND_LP0] = "LP0",241241+};242242+243243+static int __cpuinit tegra_suspend_enter(suspend_state_t state)244244+{245245+ enum tegra_suspend_mode mode = tegra_pmc_get_suspend_mode();246246+247247+ if (WARN_ON(mode < TEGRA_SUSPEND_NONE ||248248+ mode >= TEGRA_MAX_SUSPEND_MODE))249249+ return -EINVAL;250250+251251+ pr_info("Entering suspend state %s\n", lp_state[mode]);252252+253253+ tegra_pmc_pm_set(mode);254254+255255+ local_fiq_disable();256256+257257+ suspend_cpu_complex();258258+ switch (mode) {259259+ case TEGRA_SUSPEND_LP2:260260+ tegra_set_cpu_in_lp2(0);261261+ break;262262+ default:263263+ break;264264+ }265265+266266+ cpu_suspend(PHYS_OFFSET - PAGE_OFFSET, &tegra_sleep_cpu);267267+268268+ switch (mode) {269269+ case TEGRA_SUSPEND_LP2:270270+ tegra_clear_cpu_in_lp2(0);271271+ break;272272+ default:273273+ break;274274+ }275275+ restore_cpu_complex();276276+277277+ local_fiq_enable();278278+279279+ return 0;280280+}281281+282282+static const struct platform_suspend_ops tegra_suspend_ops = {283283+ .valid = suspend_valid_only_mem,284284+ .enter = tegra_suspend_enter,285285+};286286+287287+void __init tegra_init_suspend(void)288288+{289289+ if (tegra_pmc_get_suspend_mode() == TEGRA_SUSPEND_NONE)290290+ return;291291+292292+ tegra_pmc_suspend_init();293293+294294+ suspend_set_ops(&tegra_suspend_ops);153295}154296#endif
···11/*22- * Copyright (C) 2012 NVIDIA CORPORATION. All rights reserved.22+ * Copyright (C) 2012,2013 NVIDIA CORPORATION. All rights reserved.33 *44 * This program is free software; you can redistribute it and/or modify it55 * under the terms and conditions of the GNU General Public License,···1616 */17171818#include <linux/kernel.h>1919+#include <linux/clk.h>1920#include <linux/io.h>2021#include <linux/of.h>2222+#include <linux/of_address.h>21232222-#include "iomap.h"2424+#include "fuse.h"2525+#include "pm.h"2626+#include "pmc.h"2727+#include "sleep.h"23282424-#define PMC_CTRL 0x02525-#define PMC_CTRL_INTR_LOW (1 << 17)2929+#define TEGRA_POWER_EFFECT_LP0 (1 << 14) /* LP0 when CPU pwr gated */3030+#define TEGRA_POWER_CPU_PWRREQ_POLARITY (1 << 15) /* CPU pwr req polarity */3131+#define TEGRA_POWER_CPU_PWRREQ_OE (1 << 16) /* CPU pwr req enable */3232+3333+#define PMC_CTRL 0x03434+#define PMC_CTRL_INTR_LOW (1 << 17)3535+#define PMC_PWRGATE_TOGGLE 0x303636+#define PMC_PWRGATE_TOGGLE_START (1 << 8)3737+#define PMC_REMOVE_CLAMPING 0x343838+#define PMC_PWRGATE_STATUS 0x383939+4040+#define PMC_CPUPWRGOOD_TIMER 0xc84141+#define PMC_CPUPWROFF_TIMER 0xcc4242+4343+#define TEGRA_POWERGATE_PCIE 34444+#define TEGRA_POWERGATE_VDEC 44545+#define TEGRA_POWERGATE_CPU1 94646+#define TEGRA_POWERGATE_CPU2 104747+#define TEGRA_POWERGATE_CPU3 114848+4949+static u8 tegra_cpu_domains[] = {5050+ 0xFF, /* not available for CPU0 */5151+ TEGRA_POWERGATE_CPU1,5252+ TEGRA_POWERGATE_CPU2,5353+ TEGRA_POWERGATE_CPU3,5454+};5555+static DEFINE_SPINLOCK(tegra_powergate_lock);5656+5757+static void __iomem *tegra_pmc_base;5858+static bool tegra_pmc_invert_interrupt;5959+static struct clk *tegra_pclk;6060+6161+struct pmc_pm_data {6262+ u32 cpu_good_time; /* CPU power good time in uS */6363+ u32 cpu_off_time; /* CPU power off time in uS */6464+ u32 core_osc_time; /* Core power good osc time in uS */6565+ u32 core_pmu_time; /* Core power good pmu time in uS */6666+ u32 core_off_time; /* Core power off time in uS */6767+ bool corereq_high; /* Core power request active-high */6868+ bool sysclkreq_high; /* System clock request active-high */6969+ bool combined_req; /* Combined pwr req for CPU & Core */7070+ bool cpu_pwr_good_en; /* CPU power good signal is enabled */7171+ u32 lp0_vec_phy_addr; /* The phy addr of LP0 warm boot code */7272+ u32 lp0_vec_size; /* The size of LP0 warm boot code */7373+ enum tegra_suspend_mode suspend_mode;7474+};7575+static struct pmc_pm_data pmc_pm_data;26762777static inline u32 tegra_pmc_readl(u32 reg)2878{2929- return readl(IO_ADDRESS(TEGRA_PMC_BASE + reg));7979+ return readl(tegra_pmc_base + reg);3080}31813282static inline void tegra_pmc_writel(u32 val, u32 reg)3383{3434- writel(val, IO_ADDRESS(TEGRA_PMC_BASE + reg));8484+ writel(val, tegra_pmc_base + reg);3585}36863737-#ifdef CONFIG_OF8787+static int tegra_pmc_get_cpu_powerdomain_id(int cpuid)8888+{8989+ if (cpuid <= 0 || cpuid >= num_possible_cpus())9090+ return -EINVAL;9191+ return tegra_cpu_domains[cpuid];9292+}9393+9494+static bool tegra_pmc_powergate_is_powered(int id)9595+{9696+ return (tegra_pmc_readl(PMC_PWRGATE_STATUS) >> id) & 1;9797+}9898+9999+static int tegra_pmc_powergate_set(int id, bool new_state)100100+{101101+ bool old_state;102102+ unsigned long flags;103103+104104+ spin_lock_irqsave(&tegra_powergate_lock, flags);105105+106106+ old_state = tegra_pmc_powergate_is_powered(id);107107+ WARN_ON(old_state == new_state);108108+109109+ tegra_pmc_writel(PMC_PWRGATE_TOGGLE_START | id, PMC_PWRGATE_TOGGLE);110110+111111+ spin_unlock_irqrestore(&tegra_powergate_lock, flags);112112+113113+ return 0;114114+}115115+116116+static int tegra_pmc_powergate_remove_clamping(int id)117117+{118118+ u32 mask;119119+120120+ /*121121+ * Tegra has a bug where PCIE and VDE clamping masks are122122+ * swapped relatively to the partition ids.123123+ */124124+ if (id == TEGRA_POWERGATE_VDEC)125125+ mask = (1 << TEGRA_POWERGATE_PCIE);126126+ else if (id == TEGRA_POWERGATE_PCIE)127127+ mask = (1 << TEGRA_POWERGATE_VDEC);128128+ else129129+ mask = (1 << id);130130+131131+ tegra_pmc_writel(mask, PMC_REMOVE_CLAMPING);132132+133133+ return 0;134134+}135135+136136+bool tegra_pmc_cpu_is_powered(int cpuid)137137+{138138+ int id;139139+140140+ id = tegra_pmc_get_cpu_powerdomain_id(cpuid);141141+ if (id < 0)142142+ return false;143143+ return tegra_pmc_powergate_is_powered(id);144144+}145145+146146+int tegra_pmc_cpu_power_on(int cpuid)147147+{148148+ int id;149149+150150+ id = tegra_pmc_get_cpu_powerdomain_id(cpuid);151151+ if (id < 0)152152+ return id;153153+ return tegra_pmc_powergate_set(id, true);154154+}155155+156156+int tegra_pmc_cpu_remove_clamping(int cpuid)157157+{158158+ int id;159159+160160+ id = tegra_pmc_get_cpu_powerdomain_id(cpuid);161161+ if (id < 0)162162+ return id;163163+ return tegra_pmc_powergate_remove_clamping(id);164164+}165165+166166+#ifdef CONFIG_PM_SLEEP167167+static void set_power_timers(u32 us_on, u32 us_off, unsigned long rate)168168+{169169+ unsigned long long ticks;170170+ unsigned long long pclk;171171+ static unsigned long tegra_last_pclk;172172+173173+ if (WARN_ON_ONCE(rate <= 0))174174+ pclk = 100000000;175175+ else176176+ pclk = rate;177177+178178+ if ((rate != tegra_last_pclk)) {179179+ ticks = (us_on * pclk) + 999999ull;180180+ do_div(ticks, 1000000);181181+ tegra_pmc_writel((unsigned long)ticks, PMC_CPUPWRGOOD_TIMER);182182+183183+ ticks = (us_off * pclk) + 999999ull;184184+ do_div(ticks, 1000000);185185+ tegra_pmc_writel((unsigned long)ticks, PMC_CPUPWROFF_TIMER);186186+ wmb();187187+ }188188+ tegra_last_pclk = pclk;189189+}190190+191191+enum tegra_suspend_mode tegra_pmc_get_suspend_mode(void)192192+{193193+ return pmc_pm_data.suspend_mode;194194+}195195+196196+void tegra_pmc_pm_set(enum tegra_suspend_mode mode)197197+{198198+ u32 reg;199199+ unsigned long rate = 0;200200+201201+ reg = tegra_pmc_readl(PMC_CTRL);202202+ reg |= TEGRA_POWER_CPU_PWRREQ_OE;203203+ reg &= ~TEGRA_POWER_EFFECT_LP0;204204+205205+ switch (mode) {206206+ case TEGRA_SUSPEND_LP2:207207+ rate = clk_get_rate(tegra_pclk);208208+ break;209209+ default:210210+ break;211211+ }212212+213213+ set_power_timers(pmc_pm_data.cpu_good_time, pmc_pm_data.cpu_off_time,214214+ rate);215215+216216+ tegra_pmc_writel(reg, PMC_CTRL);217217+}218218+219219+void tegra_pmc_suspend_init(void)220220+{221221+ u32 reg;222222+223223+ /* Always enable CPU power request */224224+ reg = tegra_pmc_readl(PMC_CTRL);225225+ reg |= TEGRA_POWER_CPU_PWRREQ_OE;226226+ tegra_pmc_writel(reg, PMC_CTRL);227227+}228228+#endif229229+38230static const struct of_device_id matches[] __initconst = {231231+ { .compatible = "nvidia,tegra114-pmc" },232232+ { .compatible = "nvidia,tegra30-pmc" },39233 { .compatible = "nvidia,tegra20-pmc" },40234 { }41235};4242-#endif236236+237237+static void tegra_pmc_parse_dt(void)238238+{239239+ struct device_node *np;240240+ u32 prop;241241+ enum tegra_suspend_mode suspend_mode;242242+ u32 core_good_time[2] = {0, 0};243243+ u32 lp0_vec[2] = {0, 0};244244+245245+ np = of_find_matching_node(NULL, matches);246246+ BUG_ON(!np);247247+248248+ tegra_pmc_base = of_iomap(np, 0);249249+250250+ tegra_pmc_invert_interrupt = of_property_read_bool(np,251251+ "nvidia,invert-interrupt");252252+ tegra_pclk = of_clk_get_by_name(np, "pclk");253253+ WARN_ON(IS_ERR(tegra_pclk));254254+255255+ /* Grabbing the power management configurations */256256+ if (of_property_read_u32(np, "nvidia,suspend-mode", &prop)) {257257+ suspend_mode = TEGRA_SUSPEND_NONE;258258+ } else {259259+ switch (prop) {260260+ case 0:261261+ suspend_mode = TEGRA_SUSPEND_LP0;262262+ break;263263+ case 1:264264+ suspend_mode = TEGRA_SUSPEND_LP1;265265+ break;266266+ case 2:267267+ suspend_mode = TEGRA_SUSPEND_LP2;268268+ break;269269+ default:270270+ suspend_mode = TEGRA_SUSPEND_NONE;271271+ break;272272+ }273273+ }274274+ suspend_mode = tegra_pm_validate_suspend_mode(suspend_mode);275275+276276+ if (of_property_read_u32(np, "nvidia,cpu-pwr-good-time", &prop))277277+ suspend_mode = TEGRA_SUSPEND_NONE;278278+ pmc_pm_data.cpu_good_time = prop;279279+280280+ if (of_property_read_u32(np, "nvidia,cpu-pwr-off-time", &prop))281281+ suspend_mode = TEGRA_SUSPEND_NONE;282282+ pmc_pm_data.cpu_off_time = prop;283283+284284+ if (of_property_read_u32_array(np, "nvidia,core-pwr-good-time",285285+ core_good_time, ARRAY_SIZE(core_good_time)))286286+ suspend_mode = TEGRA_SUSPEND_NONE;287287+ pmc_pm_data.core_osc_time = core_good_time[0];288288+ pmc_pm_data.core_pmu_time = core_good_time[1];289289+290290+ if (of_property_read_u32(np, "nvidia,core-pwr-off-time",291291+ &prop))292292+ suspend_mode = TEGRA_SUSPEND_NONE;293293+ pmc_pm_data.core_off_time = prop;294294+295295+ pmc_pm_data.corereq_high = of_property_read_bool(np,296296+ "nvidia,core-power-req-active-high");297297+298298+ pmc_pm_data.sysclkreq_high = of_property_read_bool(np,299299+ "nvidia,sys-clock-req-active-high");300300+301301+ pmc_pm_data.combined_req = of_property_read_bool(np,302302+ "nvidia,combined-power-req");303303+304304+ pmc_pm_data.cpu_pwr_good_en = of_property_read_bool(np,305305+ "nvidia,cpu-pwr-good-en");306306+307307+ if (of_property_read_u32_array(np, "nvidia,lp0-vec", lp0_vec,308308+ ARRAY_SIZE(lp0_vec)))309309+ if (suspend_mode == TEGRA_SUSPEND_LP0)310310+ suspend_mode = TEGRA_SUSPEND_LP1;311311+312312+ pmc_pm_data.lp0_vec_phy_addr = lp0_vec[0];313313+ pmc_pm_data.lp0_vec_size = lp0_vec[1];314314+315315+ pmc_pm_data.suspend_mode = suspend_mode;316316+}4331744318void __init tegra_pmc_init(void)45319{4646- /*4747- * For now, Harmony is the only board that uses the PMC, and it wants4848- * the signal inverted. Seaboard would too if it used the PMC.4949- * Hopefully by the time other boards want to use the PMC, everything5050- * will be device-tree, or they also want it inverted.5151- */5252- bool invert_interrupt = true;53320 u32 val;543215555-#ifdef CONFIG_OF5656- if (of_have_populated_dt()) {5757- struct device_node *np;5858-5959- invert_interrupt = false;6060-6161- np = of_find_matching_node(NULL, matches);6262- if (np) {6363- if (of_find_property(np, "nvidia,invert-interrupt",6464- NULL))6565- invert_interrupt = true;6666- }6767- }6868-#endif322322+ tegra_pmc_parse_dt();6932370324 val = tegra_pmc_readl(PMC_CTRL);7171- if (invert_interrupt)325325+ if (tegra_pmc_invert_interrupt)72326 val |= PMC_CTRL_INTR_LOW;73327 else74328 val &= ~PMC_CTRL_INTR_LOW;
+18
arch/arm/mach-tegra/pmc.h
···1818#ifndef __MACH_TEGRA_PMC_H1919#define __MACH_TEGRA_PMC_H20202121+enum tegra_suspend_mode {2222+ TEGRA_SUSPEND_NONE = 0,2323+ TEGRA_SUSPEND_LP2, /* CPU voltage off */2424+ TEGRA_SUSPEND_LP1, /* CPU voltage off, DRAM self-refresh */2525+ TEGRA_SUSPEND_LP0, /* CPU + core voltage off, DRAM self-refresh */2626+ TEGRA_MAX_SUSPEND_MODE,2727+};2828+2929+#ifdef CONFIG_PM_SLEEP3030+enum tegra_suspend_mode tegra_pmc_get_suspend_mode(void);3131+void tegra_pmc_pm_set(enum tegra_suspend_mode mode);3232+void tegra_pmc_suspend_init(void);3333+#endif3434+3535+bool tegra_pmc_cpu_is_powered(int cpuid);3636+int tegra_pmc_cpu_power_on(int cpuid);3737+int tegra_pmc_cpu_remove_clamping(int cpuid);3838+2139void tegra_pmc_init(void);22402341#endif
+39-9
arch/arm/mach-tegra/reset-handler.S
···4141 */4242ENTRY(tegra_resume)4343 bl v7_invalidate_l14444- /* Enable coresight */4545- mov32 r0, 0xC5ACCE554646- mcr p14, 0, r0, c7, c12, 647444845 cpu_id r04946 cmp r0, #0 @ CPU0?···9699 *97100 * Register usage within the reset handler:98101 *102102+ * Others: scratch103103+ * R6 = SoC ID << 899104 * R7 = CPU present (to the OS) mask100105 * R8 = CPU in LP1 state mask101106 * R9 = CPU in LP2 state mask···113114ENTRY(__tegra_cpu_reset_handler)114115115116 cpsid aif, 0x13 @ SVC mode, interrupts disabled117117+118118+ mov32 r6, TEGRA_APB_MISC_BASE119119+ ldr r6, [r6, #APB_MISC_GP_HIDREV]120120+ and r6, r6, #0xff00121121+#ifdef CONFIG_ARCH_TEGRA_2x_SOC122122+t20_check:123123+ cmp r6, #(0x20 << 8)124124+ bne after_t20_check125125+t20_errata:126126+ # Tegra20 is a Cortex-A9 r1p1127127+ mrc p15, 0, r0, c1, c0, 0 @ read system control register128128+ orr r0, r0, #1 << 14 @ erratum 716044129129+ mcr p15, 0, r0, c1, c0, 0 @ write system control register130130+ mrc p15, 0, r0, c15, c0, 1 @ read diagnostic register131131+ orr r0, r0, #1 << 4 @ erratum 742230132132+ orr r0, r0, #1 << 11 @ erratum 751472133133+ mcr p15, 0, r0, c15, c0, 1 @ write diagnostic register134134+ b after_errata135135+after_t20_check:136136+#endif137137+#ifdef CONFIG_ARCH_TEGRA_3x_SOC138138+t30_check:139139+ cmp r6, #(0x30 << 8)140140+ bne after_t30_check141141+t30_errata:142142+ # Tegra30 is a Cortex-A9 r2p9143143+ mrc p15, 0, r0, c15, c0, 1 @ read diagnostic register144144+ orr r0, r0, #1 << 6 @ erratum 743622145145+ orr r0, r0, #1 << 11 @ erratum 751472146146+ mcr p15, 0, r0, c15, c0, 1 @ write diagnostic register147147+ b after_errata148148+after_t30_check:149149+#endif150150+after_errata:116151 mrc p15, 0, r10, c0, c0, 5 @ MPIDR117152 and r10, r10, #0x3 @ R10 = CPU number118153 mov r11, #1···162129163130#ifdef CONFIG_ARCH_TEGRA_2x_SOC164131 /* Are we on Tegra20? */165165- mov32 r6, TEGRA_APB_MISC_BASE166166- ldr r0, [r6, #APB_MISC_GP_HIDREV]167167- and r0, r0, #0xff00168168- cmp r0, #(0x20 << 8)132132+ cmp r6, #(0x20 << 8)169133 bne 1f170134 /* If not CPU0, don't let CPU0 reset CPU1 now that CPU1 is coming up. */171171- mov32 r6, TEGRA_PMC_BASE135135+ mov32 r5, TEGRA_PMC_BASE172136 mov r0, #0173137 cmp r10, #0174174- strne r0, [r6, #PMC_SCRATCH41]138138+ strne r0, [r5, #PMC_SCRATCH41]1751391:176140#endif177141
+5-5
arch/arm/mach-tegra/sleep.h
···11/*22- * Copyright (c) 2010-2012, NVIDIA Corporation. All rights reserved.22+ * Copyright (c) 2010-2013, NVIDIA Corporation. All rights reserved.33 *44 * This program is free software; you can redistribute it and/or modify it55 * under the terms and conditions of the GNU General Public License,···124124void tegra_disable_clean_inv_dcache(void);125125126126#ifdef CONFIG_HOTPLUG_CPU127127-void tegra20_hotplug_init(void);128128-void tegra30_hotplug_init(void);127127+void tegra20_hotplug_shutdown(void);128128+void tegra30_hotplug_shutdown(void);129129+void tegra_hotplug_init(void);129130#else130130-static inline void tegra20_hotplug_init(void) {}131131-static inline void tegra30_hotplug_init(void) {}131131+static inline void tegra_hotplug_init(void) {}132132#endif133133134134void tegra20_cpu_shutdown(int cpu);
+104
arch/arm/mach-tegra/tegra114_speedo.c
···11+/*22+ * Copyright (c) 2013, NVIDIA CORPORATION. All rights reserved.33+ *44+ * This program is free software; you can redistribute it and/or modify it55+ * under the terms and conditions of the GNU General Public License,66+ * version 2, as published by the Free Software Foundation.77+ *88+ * This program is distributed in the hope it will be useful, but WITHOUT99+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or1010+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for1111+ * more details.1212+ *1313+ * You should have received a copy of the GNU General Public License1414+ * along with this program. If not, see <http://www.gnu.org/licenses/>.1515+ */1616+1717+#include <linux/kernel.h>1818+#include <linux/bug.h>1919+2020+#include "fuse.h"2121+2222+#define CORE_PROCESS_CORNERS_NUM 22323+#define CPU_PROCESS_CORNERS_NUM 22424+2525+enum {2626+ THRESHOLD_INDEX_0,2727+ THRESHOLD_INDEX_1,2828+ THRESHOLD_INDEX_COUNT,2929+};3030+3131+static const u32 core_process_speedos[][CORE_PROCESS_CORNERS_NUM] = {3232+ {1123, UINT_MAX},3333+ {0, UINT_MAX},3434+};3535+3636+static const u32 cpu_process_speedos[][CPU_PROCESS_CORNERS_NUM] = {3737+ {1695, UINT_MAX},3838+ {0, UINT_MAX},3939+};4040+4141+static void rev_sku_to_speedo_ids(int rev, int sku, int *threshold)4242+{4343+ u32 tmp;4444+4545+ switch (sku) {4646+ case 0x00:4747+ case 0x10:4848+ case 0x05:4949+ case 0x06:5050+ tegra_cpu_speedo_id = 1;5151+ tegra_soc_speedo_id = 0;5252+ *threshold = THRESHOLD_INDEX_0;5353+ break;5454+5555+ case 0x03:5656+ case 0x04:5757+ tegra_cpu_speedo_id = 2;5858+ tegra_soc_speedo_id = 1;5959+ *threshold = THRESHOLD_INDEX_1;6060+ break;6161+6262+ default:6363+ pr_err("Tegra114 Unknown SKU %d\n", sku);6464+ tegra_cpu_speedo_id = 0;6565+ tegra_soc_speedo_id = 0;6666+ *threshold = THRESHOLD_INDEX_0;6767+ break;6868+ }6969+7070+ if (rev == TEGRA_REVISION_A01) {7171+ tmp = tegra_fuse_readl(0x270) << 1;7272+ tmp |= tegra_fuse_readl(0x26c);7373+ if (!tmp)7474+ tegra_cpu_speedo_id = 0;7575+ }7676+}7777+7878+void tegra114_init_speedo_data(void)7979+{8080+ u32 cpu_speedo_val;8181+ u32 core_speedo_val;8282+ int threshold;8383+ int i;8484+8585+ BUILD_BUG_ON(ARRAY_SIZE(cpu_process_speedos) !=8686+ THRESHOLD_INDEX_COUNT);8787+ BUILD_BUG_ON(ARRAY_SIZE(core_process_speedos) !=8888+ THRESHOLD_INDEX_COUNT);8989+9090+ rev_sku_to_speedo_ids(tegra_revision, tegra_sku_id, &threshold);9191+9292+ cpu_speedo_val = tegra_fuse_readl(0x12c) + 1024;9393+ core_speedo_val = tegra_fuse_readl(0x134);9494+9595+ for (i = 0; i < CPU_PROCESS_CORNERS_NUM; i++)9696+ if (cpu_speedo_val < cpu_process_speedos[threshold][i])9797+ break;9898+ tegra_cpu_process_id = i;9999+100100+ for (i = 0; i < CORE_PROCESS_CORNERS_NUM; i++)101101+ if (core_speedo_val < core_process_speedos[threshold][i])102102+ break;103103+ tegra_core_process_id = i;104104+}