// SPDX-License-Identifier: GPL-2.0-only /* * OMAP2/3 System Control Module register access * * Copyright (C) 2007, 2012 Texas Instruments, Inc. * Copyright (C) 2007 Nokia Corporation * * Written by Paul Walmsley
*/ #undef DEBUG
/* * This is used to store ARM registers in SDRAM before attempting * an MPU OFF. The save and restore happens from the SRAM sleep code. * The address is stored in scratchpad, so that it can be used * during the restore path.
*/
u32 omap3_arm_context[128];
/** * omap3_ctrl_write_boot_mode - set scratchpad boot mode for the next boot * @bootmode: 8-bit value to pass to some boot code * * Set the bootmode in the scratchpad RAM. This is used after the * system restarts. Not sure what actually uses this - it may be the * bootloader, rather than the boot ROM - contrary to the preserved * comment below. No return value.
*/ void omap3_ctrl_write_boot_mode(u8 bootmode)
{
u32 l;
l = ('B' << 24) | ('M' << 16) | bootmode;
/* * Reserve the first word in scratchpad for communicating * with the boot ROM. A pointer to a data structure * describing the boot process can be stored there, * cf. OMAP34xx TRM, Initialization / Software Booting * Configuration. * * XXX This should use some omap_ctrl_writel()-type function
*/
writel_relaxed(l, OMAP2_L4_IO_ADDRESS(OMAP343X_SCRATCHPAD + 4));
}
/* * Populate the Scratchpad contents * * The "get_*restore_pointer" functions are used to provide a * physical restore address where the ROM code jumps while waking * up from MPU OFF/OSWR state. * The restore pointer is stored into the scratchpad.
*/
scratchpad_contents.boot_config_ptr = 0x0; if (cpu_is_omap3630())
scratchpad_contents.public_restore_ptr =
__pa_symbol(omap3_restore_3630); elseif (omap_rev() != OMAP3430_REV_ES3_0 &&
omap_rev() != OMAP3430_REV_ES3_1 &&
omap_rev() != OMAP3430_REV_ES3_1_2)
scratchpad_contents.public_restore_ptr =
__pa_symbol(omap3_restore); else
scratchpad_contents.public_restore_ptr =
__pa_symbol(omap3_restore_es3);
/* Copy all the contents to the scratchpad location */
scratchpad_address = OMAP2_L4_IO_ADDRESS(OMAP343X_SCRATCHPAD);
memcpy_toio(scratchpad_address, &scratchpad_contents, sizeof(scratchpad_contents)); /* Scratchpad contents being 32 bits, a divide by 4 done here */
memcpy_toio(scratchpad_address +
scratchpad_contents.prcm_block_offset,
&prcm_block_contents, sizeof(prcm_block_contents));
memcpy_toio(scratchpad_address +
scratchpad_contents.sdrc_block_offset,
&sdrc_block_contents, sizeof(sdrc_block_contents)); /* * Copies the address of the location in SDRAM where ARM * registers get saved during a MPU OFF transition.
*/
memcpy_toio(scratchpad_address +
scratchpad_contents.sdrc_block_offset + sizeof(sdrc_block_contents), &arm_context_addr, 4);
}
void omap3630_ctrl_disable_rta(void)
{ if (!cpu_is_omap3630()) return;
omap_ctrl_writel(OMAP36XX_RTA_DISABLE, OMAP36XX_CONTROL_MEM_RTA_CTRL);
}
/** * omap3_ctrl_save_padconf - save padconf registers to scratchpad RAM * * Tell the SCM to start saving the padconf registers, then wait for * the process to complete. Returns 0 unconditionally, although it * should also eventually be able to return -ETIMEDOUT, if the save * does not complete. * * XXX This function is missing a timeout. What should it be?
*/ int omap3_ctrl_save_padconf(void)
{
u32 cpo;
/* Save the padconf registers */
cpo = omap_ctrl_readl(OMAP343X_CONTROL_PADCONF_OFF);
cpo |= START_PADCONF_SAVE;
omap_ctrl_writel(cpo, OMAP343X_CONTROL_PADCONF_OFF);
/* wait for the save to complete */ while (!(omap_ctrl_readl(OMAP343X_CONTROL_GENERAL_PURPOSE_STATUS)
& PADCONF_SAVE_DONE))
udelay(1);
return 0;
}
/** * omap3_ctrl_set_iva_bootmode_idle - sets the IVA2 bootmode to idle * * Sets the bootmode for IVA2 to idle. This is needed by the PM code to * force disable IVA2 so that it does not prevent any low-power states.
*/ staticvoid __init omap3_ctrl_set_iva_bootmode_idle(void)
{
omap_ctrl_writel(OMAP3_IVA2_BOOTMOD_IDLE,
OMAP343X_CONTROL_IVA2_BOOTMOD);
}
/** * omap3_ctrl_setup_d2d_padconf - setup stacked modem pads for idle * * Sets up the pads controlling the stacked modem in such way that the * device can enter idle.
*/ staticvoid __init omap3_ctrl_setup_d2d_padconf(void)
{
u16 mask, padconf;
/* * In a stand alone OMAP3430 where there is not a stacked * modem for the D2D Idle Ack and D2D MStandby must be pulled * high. S CONTROL_PADCONF_SAD2D_IDLEACK and * CONTROL_PADCONF_SAD2D_MSTDBY to have a pull up.
*/
mask = (1 << 4) | (1 << 3); /* pull-up, enabled */
padconf = omap_ctrl_readw(OMAP3_PADCONF_SAD2D_MSTANDBY);
padconf |= mask;
omap_ctrl_writew(padconf, OMAP3_PADCONF_SAD2D_MSTANDBY);
/** * omap3_ctrl_init - does static initializations for control module * * Initializes system control module. This sets up the sysconfig autoidle, * and sets up modem and iva2 so that they can be idled properly.
*/ void __init omap3_ctrl_init(void)
{
omap_ctrl_writel(OMAP3430_AUTOIDLE_MASK, OMAP2_CONTROL_SYSCONFIG);
/** * am43xx_control_save_context - Save the wakeup domain registers * * Save the wkup domain registers
*/ staticvoid am43xx_control_save_context(void)
{ int i;
for (i = 0; i < ARRAY_SIZE(am43xx_control_reg_offsets); i++)
am33xx_control_vals[i] =
omap_ctrl_readl(am43xx_control_reg_offsets[i]);
}
/** * am43xx_control_restore_context - Restore the wakeup domain registers * * Restore the wkup domain registers
*/ staticvoid am43xx_control_restore_context(void)
{ int i;
for (i = 0; i < ARRAY_SIZE(am43xx_control_reg_offsets); i++)
omap_ctrl_writel(am33xx_control_vals[i],
am43xx_control_reg_offsets[i]);
}
staticint cpu_notifier(struct notifier_block *nb, unsignedlong cmd, void *v)
{ switch (cmd) { case CPU_CLUSTER_PM_ENTER: if (enable_off_mode)
am43xx_control_save_context(); break; case CPU_CLUSTER_PM_EXIT: if (enable_off_mode)
am43xx_control_restore_context(); break;
}
/** * omap2_control_base_init - initialize iomappings for the control driver * * Detects and initializes the iomappings for the control driver, based * on the DT data. Returns 0 in success, negative error value * otherwise.
*/ int __init omap2_control_base_init(void)
{ struct device_node *np; conststruct of_device_id *match; struct control_init_data *data; void __iomem *mem;
for_each_matching_node_and_match(np, omap_scrm_dt_match_table, &match) {
data = (struct control_init_data *)match->data;
mem = of_iomap(np, 0); if (!mem) {
of_node_put(np); return -ENOMEM;
}
/** * omap_control_init - low level init for the control driver * * Initializes the low level clock infrastructure for control driver. * Returns 0 in success, negative error value in failure.
*/ int __init omap_control_init(void)
{ struct device_node *np, *scm_conf; conststruct of_device_id *match; conststruct omap_prcm_init_data *data; int ret; struct regmap *syscon; staticstruct notifier_block nb;
for_each_matching_node_and_match(np, omap_scrm_dt_match_table, &match) {
data = match->data;
/* * Check if we have scm_conf node, if yes, use this to * access clock registers.
*/
scm_conf = of_get_child_by_name(np, "scm_conf");
if (scm_conf) {
syscon = syscon_node_to_regmap(scm_conf);
if (IS_ERR(syscon)) {
ret = PTR_ERR(syscon); goto of_node_put;
}
if (of_get_child_by_name(scm_conf, "clocks")) {
ret = omap2_clk_provider_init(scm_conf,
data->index,
syscon, NULL); if (ret) goto of_node_put;
}
} else { /* No scm_conf found, direct access */
ret = omap2_clk_provider_init(np, data->index, NULL,
data->mem); if (ret) goto of_node_put;
}
}
/* Only AM43XX can lose ctrl registers context during rtc-ddr suspend */ if (soc_is_am43xx()) {
nb.notifier_call = cpu_notifier;
cpu_pm_register_notifier(&nb);
}
return 0;
of_node_put:
of_node_put(np); return ret;
}
Messung V0.5
¤ Dauer der Verarbeitung: 0.11 Sekunden
(vorverarbeitet)
¤
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.