void __init tegra_pmc_init(void) { bool invert_interrupt = true; u32 val; #ifdef CONFIG_OF if (of_have_populated_dt()) { struct device_node *np; invert_interrupt = false; np = of_find_matching_node(NULL, matches); if (np) { if (of_find_property(np, "nvidia,invert-interrupt", NULL)) invert_interrupt = true; } } #endif val = tegra_pmc_readl(PMC_CTRL); if (invert_interrupt) val |= PMC_CTRL_INTR_LOW; else val &= ~PMC_CTRL_INTR_LOW; tegra_pmc_writel(val, PMC_CTRL); }
void tegra_pmc_restart(enum reboot_mode mode, const char *cmd) { u32 val; val = tegra_pmc_readl(0); val |= 0x10; tegra_pmc_writel(val, 0); }
void tegra_pmc_suspend_init(void) { u32 reg; /* Always enable CPU power request */ reg = tegra_pmc_readl(PMC_CTRL); reg |= TEGRA_POWER_CPU_PWRREQ_OE; tegra_pmc_writel(reg, PMC_CTRL); }
static int do_enterrcm(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { puts("Entering RCM...\n"); udelay(50000); tegra_pmc_writel(2, PMC_SCRATCH0); disable_interrupts(); reset_cpu(0); return 0; }
void __init tegra_pmc_init(void) { u32 val; tegra_pmc_parse_dt(); val = tegra_pmc_readl(PMC_CTRL); if (tegra_pmc_invert_interrupt) val |= PMC_CTRL_INTR_LOW; else val &= ~PMC_CTRL_INTR_LOW; tegra_pmc_writel(val, PMC_CTRL); }
static void set_power_timers(u32 us_on, u32 us_off, unsigned long rate) { unsigned long long ticks; unsigned long long pclk; static unsigned long tegra_last_pclk; if (WARN_ON_ONCE(rate <= 0)) pclk = 100000000; else pclk = rate; if ((rate != tegra_last_pclk)) { ticks = (us_on * pclk) + 999999ull; do_div(ticks, 1000000); tegra_pmc_writel((unsigned long)ticks, PMC_CPUPWRGOOD_TIMER); ticks = (us_off * pclk) + 999999ull; do_div(ticks, 1000000); tegra_pmc_writel((unsigned long)ticks, PMC_CPUPWROFF_TIMER); wmb(); } tegra_last_pclk = pclk; }
void tegra_pmc_suspend_init(void) { u32 reg; /* Always enable CPU power request */ reg = tegra_pmc_readl(PMC_CTRL); reg |= TEGRA_POWER_CPU_PWRREQ_OE; tegra_pmc_writel(reg, PMC_CTRL); reg = tegra_pmc_readl(PMC_CTRL); if (!pmc_pm_data.sysclkreq_high) reg |= TEGRA_POWER_SYSCLK_POLARITY; else reg &= ~TEGRA_POWER_SYSCLK_POLARITY; /* configure the output polarity while the request is tristated */ tegra_pmc_writel(reg, PMC_CTRL); /* now enable the request */ reg |= TEGRA_POWER_SYSCLK_OE; tegra_pmc_writel(reg, PMC_CTRL); }
void tegra_pmc_restart(enum reboot_mode mode, const char *cmd) { u32 val; val = tegra_pmc_readl(PMC_SCRATCH0); val &= ~PMC_SCRATCH0_MODE_MASK; if (cmd) { if (strcmp(cmd, "recovery") == 0) val |= PMC_SCRATCH0_MODE_RECOVERY; if (strcmp(cmd, "bootloader") == 0) val |= PMC_SCRATCH0_MODE_BOOTLOADER; if (strcmp(cmd, "forced-recovery") == 0) val |= PMC_SCRATCH0_MODE_RCM; } tegra_pmc_writel(val, PMC_SCRATCH0); val = tegra_pmc_readl(0); val |= 0x10; tegra_pmc_writel(val, 0); }
static int tegra_pmc_powergate_set(int id, bool new_state) { bool old_state; unsigned long flags; spin_lock_irqsave(&tegra_powergate_lock, flags); old_state = tegra_pmc_powergate_is_powered(id); WARN_ON(old_state == new_state); tegra_pmc_writel(PMC_PWRGATE_TOGGLE_START | id, PMC_PWRGATE_TOGGLE); spin_unlock_irqrestore(&tegra_powergate_lock, flags); return 0; }
static int tegra_pmc_powergate_remove_clamping(int id) { u32 mask; /* * Tegra has a bug where PCIE and VDE clamping masks are * swapped relatively to the partition ids. */ if (id == TEGRA_POWERGATE_VDEC) mask = (1 << TEGRA_POWERGATE_PCIE); else if (id == TEGRA_POWERGATE_PCIE) mask = (1 << TEGRA_POWERGATE_VDEC); else mask = (1 << id); tegra_pmc_writel(mask, PMC_REMOVE_CLAMPING); return 0; }
void __init tegra_pmc_init_irq(void) { struct device_node *np; u32 val; np = of_find_matching_node(NULL, matches); BUG_ON(!np); tegra_pmc_base = of_iomap(np, 0); tegra_pmc_invert_interrupt = of_property_read_bool(np, "nvidia,invert-interrupt"); val = tegra_pmc_readl(PMC_CTRL); if (tegra_pmc_invert_interrupt) val |= PMC_CTRL_INTR_LOW; else val &= ~PMC_CTRL_INTR_LOW; tegra_pmc_writel(val, PMC_CTRL); }
void tegra_pmc_pm_set(enum tegra_suspend_mode mode) { u32 reg; unsigned long rate = 0; reg = tegra_pmc_readl(PMC_CTRL); reg |= TEGRA_POWER_CPU_PWRREQ_OE; reg &= ~TEGRA_POWER_EFFECT_LP0; switch (mode) { case TEGRA_SUSPEND_LP2: rate = clk_get_rate(tegra_pclk); break; default: break; } set_power_timers(pmc_pm_data.cpu_good_time, pmc_pm_data.cpu_off_time, rate); tegra_pmc_writel(reg, PMC_CTRL); }
void tegra_pmc_pm_set(enum tegra_suspend_mode mode) { u32 reg, csr_reg; unsigned long rate = 0; reg = tegra_pmc_readl(PMC_CTRL); reg |= TEGRA_POWER_CPU_PWRREQ_OE; reg &= ~TEGRA_POWER_EFFECT_LP0; switch (tegra_chip_id) { case TEGRA20: case TEGRA30: break; default: /* Turn off CRAIL */ csr_reg = flowctrl_read_cpu_csr(0); csr_reg &= ~FLOW_CTRL_CSR_ENABLE_EXT_MASK; csr_reg |= FLOW_CTRL_CSR_ENABLE_EXT_CRAIL; flowctrl_write_cpu_csr(0, csr_reg); break; } switch (mode) { case TEGRA_SUSPEND_LP1: rate = 32768; break; case TEGRA_SUSPEND_LP2: rate = clk_get_rate(tegra_pclk); break; default: break; } set_power_timers(pmc_pm_data.cpu_good_time, pmc_pm_data.cpu_off_time, rate); tegra_pmc_writel(reg, PMC_CTRL); }
void tegra_pmc_resume(void) { tegra_pmc_writel(0x0, PMC_SCRATCH41); }
void tegra_pmc_suspend(void) { tegra_pmc_writel(virt_to_phys(tegra_resume), PMC_SCRATCH41); }