if (on)
reg_offs = PDRONCR(pdr); else
reg_offs = PDROFFCR(pdr);
/* Wait until SYSC is ready to accept a power request */
ret = readl_poll_timeout_atomic(rcar_gen4_sysc_base + SYSCSR, val,
(val & SYSCSR_BUSY) == SYSCSR_BUSY,
SYSCSR_DELAY_US, SYSCSR_TIMEOUT); if (ret < 0) return -EAGAIN;
/* Submit power shutoff or power resume request */
iowrite32(PWRON_PWROFF, rcar_gen4_sysc_base + reg_offs);
return 0;
}
staticint clear_irq_flags(unsignedint reg_idx, unsignedint isr_mask)
{
u32 val; int ret;
/* * The interrupt source needs to be enabled, but masked, to prevent the * CPU from receiving it.
*/
iowrite32(ioread32(rcar_gen4_sysc_base + SYSCIER(reg_idx)) | isr_mask,
rcar_gen4_sysc_base + SYSCIER(reg_idx));
iowrite32(ioread32(rcar_gen4_sysc_base + SYSCIMR(reg_idx)) | isr_mask,
rcar_gen4_sysc_base + SYSCIMR(reg_idx));
ret = clear_irq_flags(reg_idx, isr_mask); if (ret) goto out;
/* Submit power shutoff or resume request until it was accepted */ for (k = 0; k < PDRESR_RETRIES; k++) {
ret = rcar_gen4_sysc_pwr_on_off(pdr, on); if (ret) goto out;
status = ioread32(rcar_gen4_sysc_base + PDRESR(pdr)); if (!(status & PDRESR_ERR)) break;
udelay(PDRESR_DELAY_US);
}
if (k == PDRESR_RETRIES) {
ret = -EIO; goto out;
}
/* Wait until the power shutoff or resume request has completed * */
ret = readl_poll_timeout_atomic(rcar_gen4_sysc_base + SYSCISCR(reg_idx),
val, (val & isr_mask),
SYSCISCR_DELAY_US, SYSCISCR_TIMEOUT); if (ret < 0) {
ret = -EIO; goto out;
}
/* Clear interrupt flags */
ret = clear_irq_flags(reg_idx, isr_mask); if (ret) goto out;
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_gen4_sysc_power_is_off(pd->pdr)) {
pr_debug("%s: %s is already powered\n", __func__, genpd->name); goto finalize;
}
rcar_gen4_sysc_power(pd->pdr, 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.