/* SYSC Status Register */ #define SYSCSR_PONENB 1 /* Ready for power resume requests */ #define SYSCSR_POFFENB 0 /* Ready for power shutoff requests */
/* * Power Control Register Offsets inside the register block for each domain * Note: The "CR" registers for ARM cores exist on H1 only * Use WFI to power off, CPG/APMU to resume ARM cores on R-Car Gen2 * Use PSCI on R-Car Gen3
*/ #define PWRSR_OFFS 0x00 /* Power Status Register */ #define PWROFFCR_OFFS 0x04 /* Power Shutoff Control Register */ #define PWROFFSR_OFFS 0x08 /* Power Shutoff Status Register */ #define PWRONCR_OFFS 0x0c /* Power Resume Control Register */ #define PWRONSR_OFFS 0x10 /* Power Resume Status Register */ #define PWRER_OFFS 0x14 /* Power Shutoff/Resume Error */
/* Wait until SYSC is ready to accept a power request */
ret = readl_poll_timeout_atomic(rcar_sysc_base + SYSCSR, val,
val & BIT(sr_bit), SYSCSR_DELAY_US,
SYSCSR_TIMEOUT); if (ret) return -EAGAIN;
/* * Mask external power requests for CPU or 3DG domains
*/ if (rcar_sysc_extmask_val) {
iowrite32(rcar_sysc_extmask_val,
rcar_sysc_base + rcar_sysc_extmask_offs);
}
/* * The interrupt source needs to be enabled, but masked, to prevent the * CPU from receiving it.
*/
iowrite32(ioread32(rcar_sysc_base + SYSCIMR) | isr_mask,
rcar_sysc_base + SYSCIMR);
iowrite32(ioread32(rcar_sysc_base + SYSCIER) | isr_mask,
rcar_sysc_base + SYSCIER);
iowrite32(isr_mask, rcar_sysc_base + SYSCISCR);
/* Submit power shutoff or resume request until it was accepted */ for (k = 0; k < PWRER_RETRIES; k++) {
ret = rcar_sysc_pwr_on_off(pd, on); if (ret) goto out;
status = ioread32(rcar_sysc_base + pd->chan_offs + PWRER_OFFS); if (!(status & chan_mask)) break;
udelay(PWRER_DELAY_US);
}
if (k == PWRER_RETRIES) {
ret = -EIO; goto out;
}
/* Wait until the power shutoff or resume request has completed * */
ret = readl_poll_timeout_atomic(rcar_sysc_base + SYSCISR, status,
status & isr_mask, SYSCISR_DELAY_US,
SYSCISR_TIMEOUT); if (ret)
ret = -EIO;
iowrite32(isr_mask, rcar_sysc_base + SYSCISCR);
out: if (rcar_sysc_extmask_val)
iowrite32(0, rcar_sysc_base + rcar_sysc_extmask_offs);
if (pd->flags & PD_CPU) { /* * This domain contains a CPU core and therefore it should * only be turned off if the CPU is not in use.
*/
pr_debug("PM domain %s contains %s\n", name, "CPU");
genpd->flags |= GENPD_FLAG_ALWAYS_ON;
} elseif (pd->flags & PD_SCU) { /* * This domain contains an SCU and cache-controller, and * therefore it should only be turned off if the CPU cores are * not in use.
*/
pr_debug("PM domain %s contains %s\n", name, "SCU");
genpd->flags |= GENPD_FLAG_ALWAYS_ON;
} elseif (pd->flags & PD_NO_CR) { /* * This domain cannot be turned off.
*/
genpd->flags |= GENPD_FLAG_ALWAYS_ON;
}
if (pd->flags & (PD_CPU | PD_NO_CR)) { /* Skip CPUs (handled by SMP code) and areas without control */
pr_debug("%s: Not touching %s\n", __func__, genpd->name); goto finalize;
}
if (!rcar_sysc_power_is_off(pd)) {
pr_debug("%s: %s is already powered\n", __func__, genpd->name); goto finalize;
}
rcar_sysc_power(pd, true);
finalize:
error = pm_genpd_init(genpd, &simple_qos_governor, false); if (error)
pr_err("Failed to init PM domain %s: %d\n", name, error);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.