/** * Initialize power management for application processors */ void psci_board_init(void) { struct flow_ctlr *flow = (struct flow_ctlr *)NV_PA_FLOW_BASE; writel((u32)park_cpu, EXCEP_VECTOR_CPU_RESET_VECTOR); /* * The naturally expected order of putting these CPUs under Flow * Controller regime would be * - configure the Flow Controller * - power up the CPUs * - wait for the CPUs to hit wfi and be powered down again * * However, this doesn't work in practice. We rather need to power them * up first and park them in wfi. While they are waiting there, we can * indeed program the Flow Controller to powergate them on wfi, which * will then happen immediately as they are already in that state. */ tegra_powergate_power_on(TEGRA_POWERGATE_CPU1); tegra_powergate_power_on(TEGRA_POWERGATE_CPU2); tegra_powergate_power_on(TEGRA_POWERGATE_CPU3); writel((2 << CSR_WAIT_WFI_SHIFT) | CSR_ENABLE, &flow->cpu1_csr); writel((4 << CSR_WAIT_WFI_SHIFT) | CSR_ENABLE, &flow->cpu2_csr); writel((8 << CSR_WAIT_WFI_SHIFT) | CSR_ENABLE, &flow->cpu3_csr); writel(EVENT_MODE_STOP, &flow->halt_cpu1_events); writel(EVENT_MODE_STOP, &flow->halt_cpu2_events); writel(EVENT_MODE_STOP, &flow->halt_cpu3_events); while (!(readl(&flow->cpu1_csr) & CSR_PWR_OFF_STS) || !(readl(&flow->cpu2_csr) & CSR_PWR_OFF_STS) || !(readl(&flow->cpu3_csr) & CSR_PWR_OFF_STS)) /* wait */; }
/* Must be called with clk disabled, and returns with clk enabled */ int tegra_powergate_sequence_power_up(int id, struct clk *clk, struct reset_control *rst) { int ret; reset_control_assert(rst); ret = tegra_powergate_power_on(id); if (ret) goto err_power; ret = clk_prepare_enable(clk); if (ret) goto err_clk; udelay(10); ret = tegra_powergate_remove_clamping(id); if (ret) goto err_clamp; udelay(10); reset_control_deassert(rst); return 0; err_clamp: clk_disable_unprepare(clk); err_clk: tegra_powergate_power_off(id); err_power: return ret; }
/* Must be called with clk disabled, and returns with clk enabled */ int tegra_powergate_sequence_power_up(int id, struct clk *clk) { int ret; tegra_periph_reset_assert(clk); ret = tegra_powergate_power_on(id); if (ret) goto err_power; ret = clk_enable(clk); if (ret) goto err_clk; udelay(10); ret = tegra_powergate_remove_clamping(id); if (ret) goto err_clamp; udelay(10); tegra_periph_reset_deassert(clk); return 0; err_clamp: clk_disable(clk); err_clk: tegra_powergate_power_off(id); err_power: return ret; }
int tegra_powergate_sequence_power_up(enum tegra_powergate_id id, clk_t clk, hwreset_t rst) { struct tegra124_pmc_softc *sc; int rv; sc = tegra124_pmc_get_sc(); rv = hwreset_assert(rst); if (rv != 0) { device_printf(sc->dev, "Cannot assert reset\n"); return (rv); } rv = clk_stop(clk); if (rv != 0) { device_printf(sc->dev, "Cannot stop clock\n"); goto clk_fail; } rv = tegra_powergate_power_on(id); if (rv != 0) { device_printf(sc->dev, "Cannot power on powergate\n"); goto clk_fail; } rv = clk_enable(clk); if (rv != 0) { device_printf(sc->dev, "Cannot enable clock\n"); goto clk_fail; } DELAY(20); rv = tegra_powergate_remove_clamping(id); if (rv != 0) { device_printf(sc->dev, "Cannot remove clamping\n"); goto fail; } rv = hwreset_deassert(rst); if (rv != 0) { device_printf(sc->dev, "Cannot unreset reset\n"); goto fail; } return 0; fail: clk_disable(clk); clk_fail: hwreset_assert(rst); tegra_powergate_power_off(id); return (rv); }
static int tegra30_power_up_cpu(unsigned int cpu) { u32 reg; int ret, pwrgateid; unsigned long timeout; pwrgateid = tegra_cpu_powergate_id(cpu); if (pwrgateid < 0) return pwrgateid; /* If this is the first boot, toggle powergates directly. */ if (!tegra_powergate_is_powered(pwrgateid)) { ret = tegra_powergate_power_on(pwrgateid); if (ret) return ret; /* Wait for the power to come up. */ timeout = jiffies + 10*HZ; while (tegra_powergate_is_powered(pwrgateid)) { if (time_after(jiffies, timeout)) return -ETIMEDOUT; udelay(10); } } /* CPU partition is powered. Enable the CPU clock. */ writel(CPU_CLOCK(cpu), CLK_RST_CONTROLLER_CLK_CPU_CMPLX_CLR); reg = readl(CLK_RST_CONTROLLER_CLK_CPU_CMPLX_CLR); udelay(10); /* Remove I/O clamps. */ ret = tegra_powergate_remove_clamping(pwrgateid); udelay(10); /* Clear flow controller CSR. */ flowctrl_write_cpu_csr(cpu, 0); return 0; }