162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * OMAP2/3 System Control Module register access 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (C) 2007, 2012 Texas Instruments, Inc. 662306a36Sopenharmony_ci * Copyright (C) 2007 Nokia Corporation 762306a36Sopenharmony_ci * 862306a36Sopenharmony_ci * Written by Paul Walmsley 962306a36Sopenharmony_ci */ 1062306a36Sopenharmony_ci#undef DEBUG 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_ci#include <linux/kernel.h> 1362306a36Sopenharmony_ci#include <linux/io.h> 1462306a36Sopenharmony_ci#include <linux/of_address.h> 1562306a36Sopenharmony_ci#include <linux/regmap.h> 1662306a36Sopenharmony_ci#include <linux/mfd/syscon.h> 1762306a36Sopenharmony_ci#include <linux/cpu_pm.h> 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_ci#include "soc.h" 2062306a36Sopenharmony_ci#include "iomap.h" 2162306a36Sopenharmony_ci#include "common.h" 2262306a36Sopenharmony_ci#include "cm-regbits-34xx.h" 2362306a36Sopenharmony_ci#include "prm-regbits-34xx.h" 2462306a36Sopenharmony_ci#include "prm3xxx.h" 2562306a36Sopenharmony_ci#include "cm3xxx.h" 2662306a36Sopenharmony_ci#include "sdrc.h" 2762306a36Sopenharmony_ci#include "pm.h" 2862306a36Sopenharmony_ci#include "control.h" 2962306a36Sopenharmony_ci#include "clock.h" 3062306a36Sopenharmony_ci 3162306a36Sopenharmony_ci/* Used by omap3_ctrl_save_padconf() */ 3262306a36Sopenharmony_ci#define START_PADCONF_SAVE 0x2 3362306a36Sopenharmony_ci#define PADCONF_SAVE_DONE 0x1 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_cistatic void __iomem *omap2_ctrl_base; 3662306a36Sopenharmony_cistatic s16 omap2_ctrl_offset; 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_ci#if defined(CONFIG_ARCH_OMAP3) && defined(CONFIG_PM) 3962306a36Sopenharmony_cistruct omap3_scratchpad { 4062306a36Sopenharmony_ci u32 boot_config_ptr; 4162306a36Sopenharmony_ci u32 public_restore_ptr; 4262306a36Sopenharmony_ci u32 secure_ram_restore_ptr; 4362306a36Sopenharmony_ci u32 sdrc_module_semaphore; 4462306a36Sopenharmony_ci u32 prcm_block_offset; 4562306a36Sopenharmony_ci u32 sdrc_block_offset; 4662306a36Sopenharmony_ci}; 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_cistruct omap3_scratchpad_prcm_block { 4962306a36Sopenharmony_ci u32 prm_contents[2]; 5062306a36Sopenharmony_ci u32 cm_contents[11]; 5162306a36Sopenharmony_ci u32 prcm_block_size; 5262306a36Sopenharmony_ci}; 5362306a36Sopenharmony_ci 5462306a36Sopenharmony_cistruct omap3_scratchpad_sdrc_block { 5562306a36Sopenharmony_ci u16 sysconfig; 5662306a36Sopenharmony_ci u16 cs_cfg; 5762306a36Sopenharmony_ci u16 sharing; 5862306a36Sopenharmony_ci u16 err_type; 5962306a36Sopenharmony_ci u32 dll_a_ctrl; 6062306a36Sopenharmony_ci u32 dll_b_ctrl; 6162306a36Sopenharmony_ci u32 power; 6262306a36Sopenharmony_ci u32 cs_0; 6362306a36Sopenharmony_ci u32 mcfg_0; 6462306a36Sopenharmony_ci u16 mr_0; 6562306a36Sopenharmony_ci u16 emr_1_0; 6662306a36Sopenharmony_ci u16 emr_2_0; 6762306a36Sopenharmony_ci u16 emr_3_0; 6862306a36Sopenharmony_ci u32 actim_ctrla_0; 6962306a36Sopenharmony_ci u32 actim_ctrlb_0; 7062306a36Sopenharmony_ci u32 rfr_ctrl_0; 7162306a36Sopenharmony_ci u32 cs_1; 7262306a36Sopenharmony_ci u32 mcfg_1; 7362306a36Sopenharmony_ci u16 mr_1; 7462306a36Sopenharmony_ci u16 emr_1_1; 7562306a36Sopenharmony_ci u16 emr_2_1; 7662306a36Sopenharmony_ci u16 emr_3_1; 7762306a36Sopenharmony_ci u32 actim_ctrla_1; 7862306a36Sopenharmony_ci u32 actim_ctrlb_1; 7962306a36Sopenharmony_ci u32 rfr_ctrl_1; 8062306a36Sopenharmony_ci u16 dcdl_1_ctrl; 8162306a36Sopenharmony_ci u16 dcdl_2_ctrl; 8262306a36Sopenharmony_ci u32 flags; 8362306a36Sopenharmony_ci u32 block_size; 8462306a36Sopenharmony_ci}; 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_civoid *omap3_secure_ram_storage; 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_ci/* 8962306a36Sopenharmony_ci * This is used to store ARM registers in SDRAM before attempting 9062306a36Sopenharmony_ci * an MPU OFF. The save and restore happens from the SRAM sleep code. 9162306a36Sopenharmony_ci * The address is stored in scratchpad, so that it can be used 9262306a36Sopenharmony_ci * during the restore path. 9362306a36Sopenharmony_ci */ 9462306a36Sopenharmony_ciu32 omap3_arm_context[128]; 9562306a36Sopenharmony_ci 9662306a36Sopenharmony_cistruct omap3_control_regs { 9762306a36Sopenharmony_ci u32 sysconfig; 9862306a36Sopenharmony_ci u32 devconf0; 9962306a36Sopenharmony_ci u32 mem_dftrw0; 10062306a36Sopenharmony_ci u32 mem_dftrw1; 10162306a36Sopenharmony_ci u32 msuspendmux_0; 10262306a36Sopenharmony_ci u32 msuspendmux_1; 10362306a36Sopenharmony_ci u32 msuspendmux_2; 10462306a36Sopenharmony_ci u32 msuspendmux_3; 10562306a36Sopenharmony_ci u32 msuspendmux_4; 10662306a36Sopenharmony_ci u32 msuspendmux_5; 10762306a36Sopenharmony_ci u32 sec_ctrl; 10862306a36Sopenharmony_ci u32 devconf1; 10962306a36Sopenharmony_ci u32 csirxfe; 11062306a36Sopenharmony_ci u32 iva2_bootaddr; 11162306a36Sopenharmony_ci u32 iva2_bootmod; 11262306a36Sopenharmony_ci u32 wkup_ctrl; 11362306a36Sopenharmony_ci u32 debobs_0; 11462306a36Sopenharmony_ci u32 debobs_1; 11562306a36Sopenharmony_ci u32 debobs_2; 11662306a36Sopenharmony_ci u32 debobs_3; 11762306a36Sopenharmony_ci u32 debobs_4; 11862306a36Sopenharmony_ci u32 debobs_5; 11962306a36Sopenharmony_ci u32 debobs_6; 12062306a36Sopenharmony_ci u32 debobs_7; 12162306a36Sopenharmony_ci u32 debobs_8; 12262306a36Sopenharmony_ci u32 prog_io0; 12362306a36Sopenharmony_ci u32 prog_io1; 12462306a36Sopenharmony_ci u32 dss_dpll_spreading; 12562306a36Sopenharmony_ci u32 core_dpll_spreading; 12662306a36Sopenharmony_ci u32 per_dpll_spreading; 12762306a36Sopenharmony_ci u32 usbhost_dpll_spreading; 12862306a36Sopenharmony_ci u32 pbias_lite; 12962306a36Sopenharmony_ci u32 temp_sensor; 13062306a36Sopenharmony_ci u32 sramldo4; 13162306a36Sopenharmony_ci u32 sramldo5; 13262306a36Sopenharmony_ci u32 csi; 13362306a36Sopenharmony_ci u32 padconf_sys_nirq; 13462306a36Sopenharmony_ci}; 13562306a36Sopenharmony_ci 13662306a36Sopenharmony_cistatic struct omap3_control_regs control_context; 13762306a36Sopenharmony_ci#endif /* CONFIG_ARCH_OMAP3 && CONFIG_PM */ 13862306a36Sopenharmony_ci 13962306a36Sopenharmony_ciu8 omap_ctrl_readb(u16 offset) 14062306a36Sopenharmony_ci{ 14162306a36Sopenharmony_ci u32 val; 14262306a36Sopenharmony_ci u8 byte_offset = offset & 0x3; 14362306a36Sopenharmony_ci 14462306a36Sopenharmony_ci val = omap_ctrl_readl(offset); 14562306a36Sopenharmony_ci 14662306a36Sopenharmony_ci return (val >> (byte_offset * 8)) & 0xff; 14762306a36Sopenharmony_ci} 14862306a36Sopenharmony_ci 14962306a36Sopenharmony_ciu16 omap_ctrl_readw(u16 offset) 15062306a36Sopenharmony_ci{ 15162306a36Sopenharmony_ci u32 val; 15262306a36Sopenharmony_ci u16 byte_offset = offset & 0x2; 15362306a36Sopenharmony_ci 15462306a36Sopenharmony_ci val = omap_ctrl_readl(offset); 15562306a36Sopenharmony_ci 15662306a36Sopenharmony_ci return (val >> (byte_offset * 8)) & 0xffff; 15762306a36Sopenharmony_ci} 15862306a36Sopenharmony_ci 15962306a36Sopenharmony_ciu32 omap_ctrl_readl(u16 offset) 16062306a36Sopenharmony_ci{ 16162306a36Sopenharmony_ci offset &= 0xfffc; 16262306a36Sopenharmony_ci 16362306a36Sopenharmony_ci return readl_relaxed(omap2_ctrl_base + offset); 16462306a36Sopenharmony_ci} 16562306a36Sopenharmony_ci 16662306a36Sopenharmony_civoid omap_ctrl_writeb(u8 val, u16 offset) 16762306a36Sopenharmony_ci{ 16862306a36Sopenharmony_ci u32 tmp; 16962306a36Sopenharmony_ci u8 byte_offset = offset & 0x3; 17062306a36Sopenharmony_ci 17162306a36Sopenharmony_ci tmp = omap_ctrl_readl(offset); 17262306a36Sopenharmony_ci 17362306a36Sopenharmony_ci tmp &= 0xffffffff ^ (0xff << (byte_offset * 8)); 17462306a36Sopenharmony_ci tmp |= val << (byte_offset * 8); 17562306a36Sopenharmony_ci 17662306a36Sopenharmony_ci omap_ctrl_writel(tmp, offset); 17762306a36Sopenharmony_ci} 17862306a36Sopenharmony_ci 17962306a36Sopenharmony_civoid omap_ctrl_writew(u16 val, u16 offset) 18062306a36Sopenharmony_ci{ 18162306a36Sopenharmony_ci u32 tmp; 18262306a36Sopenharmony_ci u8 byte_offset = offset & 0x2; 18362306a36Sopenharmony_ci 18462306a36Sopenharmony_ci tmp = omap_ctrl_readl(offset); 18562306a36Sopenharmony_ci 18662306a36Sopenharmony_ci tmp &= 0xffffffff ^ (0xffff << (byte_offset * 8)); 18762306a36Sopenharmony_ci tmp |= val << (byte_offset * 8); 18862306a36Sopenharmony_ci 18962306a36Sopenharmony_ci omap_ctrl_writel(tmp, offset); 19062306a36Sopenharmony_ci} 19162306a36Sopenharmony_ci 19262306a36Sopenharmony_civoid omap_ctrl_writel(u32 val, u16 offset) 19362306a36Sopenharmony_ci{ 19462306a36Sopenharmony_ci offset &= 0xfffc; 19562306a36Sopenharmony_ci writel_relaxed(val, omap2_ctrl_base + offset); 19662306a36Sopenharmony_ci} 19762306a36Sopenharmony_ci 19862306a36Sopenharmony_ci#ifdef CONFIG_ARCH_OMAP3 19962306a36Sopenharmony_ci 20062306a36Sopenharmony_ci/** 20162306a36Sopenharmony_ci * omap3_ctrl_write_boot_mode - set scratchpad boot mode for the next boot 20262306a36Sopenharmony_ci * @bootmode: 8-bit value to pass to some boot code 20362306a36Sopenharmony_ci * 20462306a36Sopenharmony_ci * Set the bootmode in the scratchpad RAM. This is used after the 20562306a36Sopenharmony_ci * system restarts. Not sure what actually uses this - it may be the 20662306a36Sopenharmony_ci * bootloader, rather than the boot ROM - contrary to the preserved 20762306a36Sopenharmony_ci * comment below. No return value. 20862306a36Sopenharmony_ci */ 20962306a36Sopenharmony_civoid omap3_ctrl_write_boot_mode(u8 bootmode) 21062306a36Sopenharmony_ci{ 21162306a36Sopenharmony_ci u32 l; 21262306a36Sopenharmony_ci 21362306a36Sopenharmony_ci l = ('B' << 24) | ('M' << 16) | bootmode; 21462306a36Sopenharmony_ci 21562306a36Sopenharmony_ci /* 21662306a36Sopenharmony_ci * Reserve the first word in scratchpad for communicating 21762306a36Sopenharmony_ci * with the boot ROM. A pointer to a data structure 21862306a36Sopenharmony_ci * describing the boot process can be stored there, 21962306a36Sopenharmony_ci * cf. OMAP34xx TRM, Initialization / Software Booting 22062306a36Sopenharmony_ci * Configuration. 22162306a36Sopenharmony_ci * 22262306a36Sopenharmony_ci * XXX This should use some omap_ctrl_writel()-type function 22362306a36Sopenharmony_ci */ 22462306a36Sopenharmony_ci writel_relaxed(l, OMAP2_L4_IO_ADDRESS(OMAP343X_SCRATCHPAD + 4)); 22562306a36Sopenharmony_ci} 22662306a36Sopenharmony_ci 22762306a36Sopenharmony_ci#endif 22862306a36Sopenharmony_ci 22962306a36Sopenharmony_ci#if defined(CONFIG_ARCH_OMAP3) && defined(CONFIG_PM) 23062306a36Sopenharmony_ci/* Populate the scratchpad structure with restore structure */ 23162306a36Sopenharmony_civoid omap3_save_scratchpad_contents(void) 23262306a36Sopenharmony_ci{ 23362306a36Sopenharmony_ci void __iomem *scratchpad_address; 23462306a36Sopenharmony_ci u32 arm_context_addr; 23562306a36Sopenharmony_ci struct omap3_scratchpad scratchpad_contents; 23662306a36Sopenharmony_ci struct omap3_scratchpad_prcm_block prcm_block_contents; 23762306a36Sopenharmony_ci struct omap3_scratchpad_sdrc_block sdrc_block_contents; 23862306a36Sopenharmony_ci 23962306a36Sopenharmony_ci /* 24062306a36Sopenharmony_ci * Populate the Scratchpad contents 24162306a36Sopenharmony_ci * 24262306a36Sopenharmony_ci * The "get_*restore_pointer" functions are used to provide a 24362306a36Sopenharmony_ci * physical restore address where the ROM code jumps while waking 24462306a36Sopenharmony_ci * up from MPU OFF/OSWR state. 24562306a36Sopenharmony_ci * The restore pointer is stored into the scratchpad. 24662306a36Sopenharmony_ci */ 24762306a36Sopenharmony_ci scratchpad_contents.boot_config_ptr = 0x0; 24862306a36Sopenharmony_ci if (cpu_is_omap3630()) 24962306a36Sopenharmony_ci scratchpad_contents.public_restore_ptr = 25062306a36Sopenharmony_ci __pa_symbol(omap3_restore_3630); 25162306a36Sopenharmony_ci else if (omap_rev() != OMAP3430_REV_ES3_0 && 25262306a36Sopenharmony_ci omap_rev() != OMAP3430_REV_ES3_1 && 25362306a36Sopenharmony_ci omap_rev() != OMAP3430_REV_ES3_1_2) 25462306a36Sopenharmony_ci scratchpad_contents.public_restore_ptr = 25562306a36Sopenharmony_ci __pa_symbol(omap3_restore); 25662306a36Sopenharmony_ci else 25762306a36Sopenharmony_ci scratchpad_contents.public_restore_ptr = 25862306a36Sopenharmony_ci __pa_symbol(omap3_restore_es3); 25962306a36Sopenharmony_ci 26062306a36Sopenharmony_ci if (omap_type() == OMAP2_DEVICE_TYPE_GP) 26162306a36Sopenharmony_ci scratchpad_contents.secure_ram_restore_ptr = 0x0; 26262306a36Sopenharmony_ci else 26362306a36Sopenharmony_ci scratchpad_contents.secure_ram_restore_ptr = 26462306a36Sopenharmony_ci (u32) __pa(omap3_secure_ram_storage); 26562306a36Sopenharmony_ci scratchpad_contents.sdrc_module_semaphore = 0x0; 26662306a36Sopenharmony_ci scratchpad_contents.prcm_block_offset = 0x2C; 26762306a36Sopenharmony_ci scratchpad_contents.sdrc_block_offset = 0x64; 26862306a36Sopenharmony_ci 26962306a36Sopenharmony_ci /* Populate the PRCM block contents */ 27062306a36Sopenharmony_ci omap3_prm_save_scratchpad_contents(prcm_block_contents.prm_contents); 27162306a36Sopenharmony_ci omap3_cm_save_scratchpad_contents(prcm_block_contents.cm_contents); 27262306a36Sopenharmony_ci 27362306a36Sopenharmony_ci prcm_block_contents.prcm_block_size = 0x0; 27462306a36Sopenharmony_ci 27562306a36Sopenharmony_ci /* Populate the SDRC block contents */ 27662306a36Sopenharmony_ci sdrc_block_contents.sysconfig = 27762306a36Sopenharmony_ci (sdrc_read_reg(SDRC_SYSCONFIG) & 0xFFFF); 27862306a36Sopenharmony_ci sdrc_block_contents.cs_cfg = 27962306a36Sopenharmony_ci (sdrc_read_reg(SDRC_CS_CFG) & 0xFFFF); 28062306a36Sopenharmony_ci sdrc_block_contents.sharing = 28162306a36Sopenharmony_ci (sdrc_read_reg(SDRC_SHARING) & 0xFFFF); 28262306a36Sopenharmony_ci sdrc_block_contents.err_type = 28362306a36Sopenharmony_ci (sdrc_read_reg(SDRC_ERR_TYPE) & 0xFFFF); 28462306a36Sopenharmony_ci sdrc_block_contents.dll_a_ctrl = sdrc_read_reg(SDRC_DLLA_CTRL); 28562306a36Sopenharmony_ci sdrc_block_contents.dll_b_ctrl = 0x0; 28662306a36Sopenharmony_ci /* 28762306a36Sopenharmony_ci * Due to a OMAP3 errata (1.142), on EMU/HS devices SRDC should 28862306a36Sopenharmony_ci * be programed to issue automatic self refresh on timeout 28962306a36Sopenharmony_ci * of AUTO_CNT = 1 prior to any transition to OFF mode. 29062306a36Sopenharmony_ci */ 29162306a36Sopenharmony_ci if ((omap_type() != OMAP2_DEVICE_TYPE_GP) 29262306a36Sopenharmony_ci && (omap_rev() >= OMAP3430_REV_ES3_0)) 29362306a36Sopenharmony_ci sdrc_block_contents.power = (sdrc_read_reg(SDRC_POWER) & 29462306a36Sopenharmony_ci ~(SDRC_POWER_AUTOCOUNT_MASK| 29562306a36Sopenharmony_ci SDRC_POWER_CLKCTRL_MASK)) | 29662306a36Sopenharmony_ci (1 << SDRC_POWER_AUTOCOUNT_SHIFT) | 29762306a36Sopenharmony_ci SDRC_SELF_REFRESH_ON_AUTOCOUNT; 29862306a36Sopenharmony_ci else 29962306a36Sopenharmony_ci sdrc_block_contents.power = sdrc_read_reg(SDRC_POWER); 30062306a36Sopenharmony_ci 30162306a36Sopenharmony_ci sdrc_block_contents.cs_0 = 0x0; 30262306a36Sopenharmony_ci sdrc_block_contents.mcfg_0 = sdrc_read_reg(SDRC_MCFG_0); 30362306a36Sopenharmony_ci sdrc_block_contents.mr_0 = (sdrc_read_reg(SDRC_MR_0) & 0xFFFF); 30462306a36Sopenharmony_ci sdrc_block_contents.emr_1_0 = 0x0; 30562306a36Sopenharmony_ci sdrc_block_contents.emr_2_0 = 0x0; 30662306a36Sopenharmony_ci sdrc_block_contents.emr_3_0 = 0x0; 30762306a36Sopenharmony_ci sdrc_block_contents.actim_ctrla_0 = 30862306a36Sopenharmony_ci sdrc_read_reg(SDRC_ACTIM_CTRL_A_0); 30962306a36Sopenharmony_ci sdrc_block_contents.actim_ctrlb_0 = 31062306a36Sopenharmony_ci sdrc_read_reg(SDRC_ACTIM_CTRL_B_0); 31162306a36Sopenharmony_ci sdrc_block_contents.rfr_ctrl_0 = 31262306a36Sopenharmony_ci sdrc_read_reg(SDRC_RFR_CTRL_0); 31362306a36Sopenharmony_ci sdrc_block_contents.cs_1 = 0x0; 31462306a36Sopenharmony_ci sdrc_block_contents.mcfg_1 = sdrc_read_reg(SDRC_MCFG_1); 31562306a36Sopenharmony_ci sdrc_block_contents.mr_1 = sdrc_read_reg(SDRC_MR_1) & 0xFFFF; 31662306a36Sopenharmony_ci sdrc_block_contents.emr_1_1 = 0x0; 31762306a36Sopenharmony_ci sdrc_block_contents.emr_2_1 = 0x0; 31862306a36Sopenharmony_ci sdrc_block_contents.emr_3_1 = 0x0; 31962306a36Sopenharmony_ci sdrc_block_contents.actim_ctrla_1 = 32062306a36Sopenharmony_ci sdrc_read_reg(SDRC_ACTIM_CTRL_A_1); 32162306a36Sopenharmony_ci sdrc_block_contents.actim_ctrlb_1 = 32262306a36Sopenharmony_ci sdrc_read_reg(SDRC_ACTIM_CTRL_B_1); 32362306a36Sopenharmony_ci sdrc_block_contents.rfr_ctrl_1 = 32462306a36Sopenharmony_ci sdrc_read_reg(SDRC_RFR_CTRL_1); 32562306a36Sopenharmony_ci sdrc_block_contents.dcdl_1_ctrl = 0x0; 32662306a36Sopenharmony_ci sdrc_block_contents.dcdl_2_ctrl = 0x0; 32762306a36Sopenharmony_ci sdrc_block_contents.flags = 0x0; 32862306a36Sopenharmony_ci sdrc_block_contents.block_size = 0x0; 32962306a36Sopenharmony_ci 33062306a36Sopenharmony_ci arm_context_addr = __pa_symbol(omap3_arm_context); 33162306a36Sopenharmony_ci 33262306a36Sopenharmony_ci /* Copy all the contents to the scratchpad location */ 33362306a36Sopenharmony_ci scratchpad_address = OMAP2_L4_IO_ADDRESS(OMAP343X_SCRATCHPAD); 33462306a36Sopenharmony_ci memcpy_toio(scratchpad_address, &scratchpad_contents, 33562306a36Sopenharmony_ci sizeof(scratchpad_contents)); 33662306a36Sopenharmony_ci /* Scratchpad contents being 32 bits, a divide by 4 done here */ 33762306a36Sopenharmony_ci memcpy_toio(scratchpad_address + 33862306a36Sopenharmony_ci scratchpad_contents.prcm_block_offset, 33962306a36Sopenharmony_ci &prcm_block_contents, sizeof(prcm_block_contents)); 34062306a36Sopenharmony_ci memcpy_toio(scratchpad_address + 34162306a36Sopenharmony_ci scratchpad_contents.sdrc_block_offset, 34262306a36Sopenharmony_ci &sdrc_block_contents, sizeof(sdrc_block_contents)); 34362306a36Sopenharmony_ci /* 34462306a36Sopenharmony_ci * Copies the address of the location in SDRAM where ARM 34562306a36Sopenharmony_ci * registers get saved during a MPU OFF transition. 34662306a36Sopenharmony_ci */ 34762306a36Sopenharmony_ci memcpy_toio(scratchpad_address + 34862306a36Sopenharmony_ci scratchpad_contents.sdrc_block_offset + 34962306a36Sopenharmony_ci sizeof(sdrc_block_contents), &arm_context_addr, 4); 35062306a36Sopenharmony_ci} 35162306a36Sopenharmony_ci 35262306a36Sopenharmony_civoid omap3_control_save_context(void) 35362306a36Sopenharmony_ci{ 35462306a36Sopenharmony_ci control_context.sysconfig = omap_ctrl_readl(OMAP2_CONTROL_SYSCONFIG); 35562306a36Sopenharmony_ci control_context.devconf0 = omap_ctrl_readl(OMAP2_CONTROL_DEVCONF0); 35662306a36Sopenharmony_ci control_context.mem_dftrw0 = 35762306a36Sopenharmony_ci omap_ctrl_readl(OMAP343X_CONTROL_MEM_DFTRW0); 35862306a36Sopenharmony_ci control_context.mem_dftrw1 = 35962306a36Sopenharmony_ci omap_ctrl_readl(OMAP343X_CONTROL_MEM_DFTRW1); 36062306a36Sopenharmony_ci control_context.msuspendmux_0 = 36162306a36Sopenharmony_ci omap_ctrl_readl(OMAP2_CONTROL_MSUSPENDMUX_0); 36262306a36Sopenharmony_ci control_context.msuspendmux_1 = 36362306a36Sopenharmony_ci omap_ctrl_readl(OMAP2_CONTROL_MSUSPENDMUX_1); 36462306a36Sopenharmony_ci control_context.msuspendmux_2 = 36562306a36Sopenharmony_ci omap_ctrl_readl(OMAP2_CONTROL_MSUSPENDMUX_2); 36662306a36Sopenharmony_ci control_context.msuspendmux_3 = 36762306a36Sopenharmony_ci omap_ctrl_readl(OMAP2_CONTROL_MSUSPENDMUX_3); 36862306a36Sopenharmony_ci control_context.msuspendmux_4 = 36962306a36Sopenharmony_ci omap_ctrl_readl(OMAP2_CONTROL_MSUSPENDMUX_4); 37062306a36Sopenharmony_ci control_context.msuspendmux_5 = 37162306a36Sopenharmony_ci omap_ctrl_readl(OMAP2_CONTROL_MSUSPENDMUX_5); 37262306a36Sopenharmony_ci control_context.sec_ctrl = omap_ctrl_readl(OMAP2_CONTROL_SEC_CTRL); 37362306a36Sopenharmony_ci control_context.devconf1 = omap_ctrl_readl(OMAP343X_CONTROL_DEVCONF1); 37462306a36Sopenharmony_ci control_context.csirxfe = omap_ctrl_readl(OMAP343X_CONTROL_CSIRXFE); 37562306a36Sopenharmony_ci control_context.iva2_bootaddr = 37662306a36Sopenharmony_ci omap_ctrl_readl(OMAP343X_CONTROL_IVA2_BOOTADDR); 37762306a36Sopenharmony_ci control_context.iva2_bootmod = 37862306a36Sopenharmony_ci omap_ctrl_readl(OMAP343X_CONTROL_IVA2_BOOTMOD); 37962306a36Sopenharmony_ci control_context.wkup_ctrl = omap_ctrl_readl(OMAP34XX_CONTROL_WKUP_CTRL); 38062306a36Sopenharmony_ci control_context.debobs_0 = omap_ctrl_readl(OMAP343X_CONTROL_DEBOBS(0)); 38162306a36Sopenharmony_ci control_context.debobs_1 = omap_ctrl_readl(OMAP343X_CONTROL_DEBOBS(1)); 38262306a36Sopenharmony_ci control_context.debobs_2 = omap_ctrl_readl(OMAP343X_CONTROL_DEBOBS(2)); 38362306a36Sopenharmony_ci control_context.debobs_3 = omap_ctrl_readl(OMAP343X_CONTROL_DEBOBS(3)); 38462306a36Sopenharmony_ci control_context.debobs_4 = omap_ctrl_readl(OMAP343X_CONTROL_DEBOBS(4)); 38562306a36Sopenharmony_ci control_context.debobs_5 = omap_ctrl_readl(OMAP343X_CONTROL_DEBOBS(5)); 38662306a36Sopenharmony_ci control_context.debobs_6 = omap_ctrl_readl(OMAP343X_CONTROL_DEBOBS(6)); 38762306a36Sopenharmony_ci control_context.debobs_7 = omap_ctrl_readl(OMAP343X_CONTROL_DEBOBS(7)); 38862306a36Sopenharmony_ci control_context.debobs_8 = omap_ctrl_readl(OMAP343X_CONTROL_DEBOBS(8)); 38962306a36Sopenharmony_ci control_context.prog_io0 = omap_ctrl_readl(OMAP343X_CONTROL_PROG_IO0); 39062306a36Sopenharmony_ci control_context.prog_io1 = omap_ctrl_readl(OMAP343X_CONTROL_PROG_IO1); 39162306a36Sopenharmony_ci control_context.dss_dpll_spreading = 39262306a36Sopenharmony_ci omap_ctrl_readl(OMAP343X_CONTROL_DSS_DPLL_SPREADING); 39362306a36Sopenharmony_ci control_context.core_dpll_spreading = 39462306a36Sopenharmony_ci omap_ctrl_readl(OMAP343X_CONTROL_CORE_DPLL_SPREADING); 39562306a36Sopenharmony_ci control_context.per_dpll_spreading = 39662306a36Sopenharmony_ci omap_ctrl_readl(OMAP343X_CONTROL_PER_DPLL_SPREADING); 39762306a36Sopenharmony_ci control_context.usbhost_dpll_spreading = 39862306a36Sopenharmony_ci omap_ctrl_readl(OMAP343X_CONTROL_USBHOST_DPLL_SPREADING); 39962306a36Sopenharmony_ci control_context.pbias_lite = 40062306a36Sopenharmony_ci omap_ctrl_readl(OMAP343X_CONTROL_PBIAS_LITE); 40162306a36Sopenharmony_ci control_context.temp_sensor = 40262306a36Sopenharmony_ci omap_ctrl_readl(OMAP343X_CONTROL_TEMP_SENSOR); 40362306a36Sopenharmony_ci control_context.sramldo4 = omap_ctrl_readl(OMAP343X_CONTROL_SRAMLDO4); 40462306a36Sopenharmony_ci control_context.sramldo5 = omap_ctrl_readl(OMAP343X_CONTROL_SRAMLDO5); 40562306a36Sopenharmony_ci control_context.csi = omap_ctrl_readl(OMAP343X_CONTROL_CSI); 40662306a36Sopenharmony_ci control_context.padconf_sys_nirq = 40762306a36Sopenharmony_ci omap_ctrl_readl(OMAP343X_CONTROL_PADCONF_SYSNIRQ); 40862306a36Sopenharmony_ci} 40962306a36Sopenharmony_ci 41062306a36Sopenharmony_civoid omap3_control_restore_context(void) 41162306a36Sopenharmony_ci{ 41262306a36Sopenharmony_ci omap_ctrl_writel(control_context.sysconfig, OMAP2_CONTROL_SYSCONFIG); 41362306a36Sopenharmony_ci omap_ctrl_writel(control_context.devconf0, OMAP2_CONTROL_DEVCONF0); 41462306a36Sopenharmony_ci omap_ctrl_writel(control_context.mem_dftrw0, 41562306a36Sopenharmony_ci OMAP343X_CONTROL_MEM_DFTRW0); 41662306a36Sopenharmony_ci omap_ctrl_writel(control_context.mem_dftrw1, 41762306a36Sopenharmony_ci OMAP343X_CONTROL_MEM_DFTRW1); 41862306a36Sopenharmony_ci omap_ctrl_writel(control_context.msuspendmux_0, 41962306a36Sopenharmony_ci OMAP2_CONTROL_MSUSPENDMUX_0); 42062306a36Sopenharmony_ci omap_ctrl_writel(control_context.msuspendmux_1, 42162306a36Sopenharmony_ci OMAP2_CONTROL_MSUSPENDMUX_1); 42262306a36Sopenharmony_ci omap_ctrl_writel(control_context.msuspendmux_2, 42362306a36Sopenharmony_ci OMAP2_CONTROL_MSUSPENDMUX_2); 42462306a36Sopenharmony_ci omap_ctrl_writel(control_context.msuspendmux_3, 42562306a36Sopenharmony_ci OMAP2_CONTROL_MSUSPENDMUX_3); 42662306a36Sopenharmony_ci omap_ctrl_writel(control_context.msuspendmux_4, 42762306a36Sopenharmony_ci OMAP2_CONTROL_MSUSPENDMUX_4); 42862306a36Sopenharmony_ci omap_ctrl_writel(control_context.msuspendmux_5, 42962306a36Sopenharmony_ci OMAP2_CONTROL_MSUSPENDMUX_5); 43062306a36Sopenharmony_ci omap_ctrl_writel(control_context.sec_ctrl, OMAP2_CONTROL_SEC_CTRL); 43162306a36Sopenharmony_ci omap_ctrl_writel(control_context.devconf1, OMAP343X_CONTROL_DEVCONF1); 43262306a36Sopenharmony_ci omap_ctrl_writel(control_context.csirxfe, OMAP343X_CONTROL_CSIRXFE); 43362306a36Sopenharmony_ci omap_ctrl_writel(control_context.iva2_bootaddr, 43462306a36Sopenharmony_ci OMAP343X_CONTROL_IVA2_BOOTADDR); 43562306a36Sopenharmony_ci omap_ctrl_writel(control_context.iva2_bootmod, 43662306a36Sopenharmony_ci OMAP343X_CONTROL_IVA2_BOOTMOD); 43762306a36Sopenharmony_ci omap_ctrl_writel(control_context.wkup_ctrl, OMAP34XX_CONTROL_WKUP_CTRL); 43862306a36Sopenharmony_ci omap_ctrl_writel(control_context.debobs_0, OMAP343X_CONTROL_DEBOBS(0)); 43962306a36Sopenharmony_ci omap_ctrl_writel(control_context.debobs_1, OMAP343X_CONTROL_DEBOBS(1)); 44062306a36Sopenharmony_ci omap_ctrl_writel(control_context.debobs_2, OMAP343X_CONTROL_DEBOBS(2)); 44162306a36Sopenharmony_ci omap_ctrl_writel(control_context.debobs_3, OMAP343X_CONTROL_DEBOBS(3)); 44262306a36Sopenharmony_ci omap_ctrl_writel(control_context.debobs_4, OMAP343X_CONTROL_DEBOBS(4)); 44362306a36Sopenharmony_ci omap_ctrl_writel(control_context.debobs_5, OMAP343X_CONTROL_DEBOBS(5)); 44462306a36Sopenharmony_ci omap_ctrl_writel(control_context.debobs_6, OMAP343X_CONTROL_DEBOBS(6)); 44562306a36Sopenharmony_ci omap_ctrl_writel(control_context.debobs_7, OMAP343X_CONTROL_DEBOBS(7)); 44662306a36Sopenharmony_ci omap_ctrl_writel(control_context.debobs_8, OMAP343X_CONTROL_DEBOBS(8)); 44762306a36Sopenharmony_ci omap_ctrl_writel(control_context.prog_io0, OMAP343X_CONTROL_PROG_IO0); 44862306a36Sopenharmony_ci omap_ctrl_writel(control_context.prog_io1, OMAP343X_CONTROL_PROG_IO1); 44962306a36Sopenharmony_ci omap_ctrl_writel(control_context.dss_dpll_spreading, 45062306a36Sopenharmony_ci OMAP343X_CONTROL_DSS_DPLL_SPREADING); 45162306a36Sopenharmony_ci omap_ctrl_writel(control_context.core_dpll_spreading, 45262306a36Sopenharmony_ci OMAP343X_CONTROL_CORE_DPLL_SPREADING); 45362306a36Sopenharmony_ci omap_ctrl_writel(control_context.per_dpll_spreading, 45462306a36Sopenharmony_ci OMAP343X_CONTROL_PER_DPLL_SPREADING); 45562306a36Sopenharmony_ci omap_ctrl_writel(control_context.usbhost_dpll_spreading, 45662306a36Sopenharmony_ci OMAP343X_CONTROL_USBHOST_DPLL_SPREADING); 45762306a36Sopenharmony_ci omap_ctrl_writel(control_context.pbias_lite, 45862306a36Sopenharmony_ci OMAP343X_CONTROL_PBIAS_LITE); 45962306a36Sopenharmony_ci omap_ctrl_writel(control_context.temp_sensor, 46062306a36Sopenharmony_ci OMAP343X_CONTROL_TEMP_SENSOR); 46162306a36Sopenharmony_ci omap_ctrl_writel(control_context.sramldo4, OMAP343X_CONTROL_SRAMLDO4); 46262306a36Sopenharmony_ci omap_ctrl_writel(control_context.sramldo5, OMAP343X_CONTROL_SRAMLDO5); 46362306a36Sopenharmony_ci omap_ctrl_writel(control_context.csi, OMAP343X_CONTROL_CSI); 46462306a36Sopenharmony_ci omap_ctrl_writel(control_context.padconf_sys_nirq, 46562306a36Sopenharmony_ci OMAP343X_CONTROL_PADCONF_SYSNIRQ); 46662306a36Sopenharmony_ci} 46762306a36Sopenharmony_ci 46862306a36Sopenharmony_civoid omap3630_ctrl_disable_rta(void) 46962306a36Sopenharmony_ci{ 47062306a36Sopenharmony_ci if (!cpu_is_omap3630()) 47162306a36Sopenharmony_ci return; 47262306a36Sopenharmony_ci omap_ctrl_writel(OMAP36XX_RTA_DISABLE, OMAP36XX_CONTROL_MEM_RTA_CTRL); 47362306a36Sopenharmony_ci} 47462306a36Sopenharmony_ci 47562306a36Sopenharmony_ci/** 47662306a36Sopenharmony_ci * omap3_ctrl_save_padconf - save padconf registers to scratchpad RAM 47762306a36Sopenharmony_ci * 47862306a36Sopenharmony_ci * Tell the SCM to start saving the padconf registers, then wait for 47962306a36Sopenharmony_ci * the process to complete. Returns 0 unconditionally, although it 48062306a36Sopenharmony_ci * should also eventually be able to return -ETIMEDOUT, if the save 48162306a36Sopenharmony_ci * does not complete. 48262306a36Sopenharmony_ci * 48362306a36Sopenharmony_ci * XXX This function is missing a timeout. What should it be? 48462306a36Sopenharmony_ci */ 48562306a36Sopenharmony_ciint omap3_ctrl_save_padconf(void) 48662306a36Sopenharmony_ci{ 48762306a36Sopenharmony_ci u32 cpo; 48862306a36Sopenharmony_ci 48962306a36Sopenharmony_ci /* Save the padconf registers */ 49062306a36Sopenharmony_ci cpo = omap_ctrl_readl(OMAP343X_CONTROL_PADCONF_OFF); 49162306a36Sopenharmony_ci cpo |= START_PADCONF_SAVE; 49262306a36Sopenharmony_ci omap_ctrl_writel(cpo, OMAP343X_CONTROL_PADCONF_OFF); 49362306a36Sopenharmony_ci 49462306a36Sopenharmony_ci /* wait for the save to complete */ 49562306a36Sopenharmony_ci while (!(omap_ctrl_readl(OMAP343X_CONTROL_GENERAL_PURPOSE_STATUS) 49662306a36Sopenharmony_ci & PADCONF_SAVE_DONE)) 49762306a36Sopenharmony_ci udelay(1); 49862306a36Sopenharmony_ci 49962306a36Sopenharmony_ci return 0; 50062306a36Sopenharmony_ci} 50162306a36Sopenharmony_ci 50262306a36Sopenharmony_ci/** 50362306a36Sopenharmony_ci * omap3_ctrl_set_iva_bootmode_idle - sets the IVA2 bootmode to idle 50462306a36Sopenharmony_ci * 50562306a36Sopenharmony_ci * Sets the bootmode for IVA2 to idle. This is needed by the PM code to 50662306a36Sopenharmony_ci * force disable IVA2 so that it does not prevent any low-power states. 50762306a36Sopenharmony_ci */ 50862306a36Sopenharmony_cistatic void __init omap3_ctrl_set_iva_bootmode_idle(void) 50962306a36Sopenharmony_ci{ 51062306a36Sopenharmony_ci omap_ctrl_writel(OMAP3_IVA2_BOOTMOD_IDLE, 51162306a36Sopenharmony_ci OMAP343X_CONTROL_IVA2_BOOTMOD); 51262306a36Sopenharmony_ci} 51362306a36Sopenharmony_ci 51462306a36Sopenharmony_ci/** 51562306a36Sopenharmony_ci * omap3_ctrl_setup_d2d_padconf - setup stacked modem pads for idle 51662306a36Sopenharmony_ci * 51762306a36Sopenharmony_ci * Sets up the pads controlling the stacked modem in such way that the 51862306a36Sopenharmony_ci * device can enter idle. 51962306a36Sopenharmony_ci */ 52062306a36Sopenharmony_cistatic void __init omap3_ctrl_setup_d2d_padconf(void) 52162306a36Sopenharmony_ci{ 52262306a36Sopenharmony_ci u16 mask, padconf; 52362306a36Sopenharmony_ci 52462306a36Sopenharmony_ci /* 52562306a36Sopenharmony_ci * In a stand alone OMAP3430 where there is not a stacked 52662306a36Sopenharmony_ci * modem for the D2D Idle Ack and D2D MStandby must be pulled 52762306a36Sopenharmony_ci * high. S CONTROL_PADCONF_SAD2D_IDLEACK and 52862306a36Sopenharmony_ci * CONTROL_PADCONF_SAD2D_MSTDBY to have a pull up. 52962306a36Sopenharmony_ci */ 53062306a36Sopenharmony_ci mask = (1 << 4) | (1 << 3); /* pull-up, enabled */ 53162306a36Sopenharmony_ci padconf = omap_ctrl_readw(OMAP3_PADCONF_SAD2D_MSTANDBY); 53262306a36Sopenharmony_ci padconf |= mask; 53362306a36Sopenharmony_ci omap_ctrl_writew(padconf, OMAP3_PADCONF_SAD2D_MSTANDBY); 53462306a36Sopenharmony_ci 53562306a36Sopenharmony_ci padconf = omap_ctrl_readw(OMAP3_PADCONF_SAD2D_IDLEACK); 53662306a36Sopenharmony_ci padconf |= mask; 53762306a36Sopenharmony_ci omap_ctrl_writew(padconf, OMAP3_PADCONF_SAD2D_IDLEACK); 53862306a36Sopenharmony_ci} 53962306a36Sopenharmony_ci 54062306a36Sopenharmony_ci/** 54162306a36Sopenharmony_ci * omap3_ctrl_init - does static initializations for control module 54262306a36Sopenharmony_ci * 54362306a36Sopenharmony_ci * Initializes system control module. This sets up the sysconfig autoidle, 54462306a36Sopenharmony_ci * and sets up modem and iva2 so that they can be idled properly. 54562306a36Sopenharmony_ci */ 54662306a36Sopenharmony_civoid __init omap3_ctrl_init(void) 54762306a36Sopenharmony_ci{ 54862306a36Sopenharmony_ci omap_ctrl_writel(OMAP3430_AUTOIDLE_MASK, OMAP2_CONTROL_SYSCONFIG); 54962306a36Sopenharmony_ci 55062306a36Sopenharmony_ci omap3_ctrl_set_iva_bootmode_idle(); 55162306a36Sopenharmony_ci 55262306a36Sopenharmony_ci omap3_ctrl_setup_d2d_padconf(); 55362306a36Sopenharmony_ci} 55462306a36Sopenharmony_ci#endif /* CONFIG_ARCH_OMAP3 && CONFIG_PM */ 55562306a36Sopenharmony_ci 55662306a36Sopenharmony_cistatic unsigned long am43xx_control_reg_offsets[] = { 55762306a36Sopenharmony_ci AM33XX_CONTROL_SYSCONFIG_OFFSET, 55862306a36Sopenharmony_ci AM33XX_CONTROL_STATUS_OFFSET, 55962306a36Sopenharmony_ci AM43XX_CONTROL_MPU_L2_CTRL_OFFSET, 56062306a36Sopenharmony_ci AM33XX_CONTROL_CORE_SLDO_CTRL_OFFSET, 56162306a36Sopenharmony_ci AM33XX_CONTROL_MPU_SLDO_CTRL_OFFSET, 56262306a36Sopenharmony_ci AM33XX_CONTROL_CLK32KDIVRATIO_CTRL_OFFSET, 56362306a36Sopenharmony_ci AM33XX_CONTROL_BANDGAP_CTRL_OFFSET, 56462306a36Sopenharmony_ci AM33XX_CONTROL_BANDGAP_TRIM_OFFSET, 56562306a36Sopenharmony_ci AM33XX_CONTROL_PLL_CLKINPULOW_CTRL_OFFSET, 56662306a36Sopenharmony_ci AM33XX_CONTROL_MOSC_CTRL_OFFSET, 56762306a36Sopenharmony_ci AM33XX_CONTROL_DEEPSLEEP_CTRL_OFFSET, 56862306a36Sopenharmony_ci AM43XX_CONTROL_DISPLAY_PLL_SEL_OFFSET, 56962306a36Sopenharmony_ci AM33XX_CONTROL_INIT_PRIORITY_0_OFFSET, 57062306a36Sopenharmony_ci AM33XX_CONTROL_INIT_PRIORITY_1_OFFSET, 57162306a36Sopenharmony_ci AM33XX_CONTROL_TPTC_CFG_OFFSET, 57262306a36Sopenharmony_ci AM33XX_CONTROL_USB_CTRL0_OFFSET, 57362306a36Sopenharmony_ci AM33XX_CONTROL_USB_CTRL1_OFFSET, 57462306a36Sopenharmony_ci AM43XX_CONTROL_USB_CTRL2_OFFSET, 57562306a36Sopenharmony_ci AM43XX_CONTROL_GMII_SEL_OFFSET, 57662306a36Sopenharmony_ci AM43XX_CONTROL_MPUSS_CTRL_OFFSET, 57762306a36Sopenharmony_ci AM43XX_CONTROL_TIMER_CASCADE_CTRL_OFFSET, 57862306a36Sopenharmony_ci AM43XX_CONTROL_PWMSS_CTRL_OFFSET, 57962306a36Sopenharmony_ci AM33XX_CONTROL_MREQPRIO_0_OFFSET, 58062306a36Sopenharmony_ci AM33XX_CONTROL_MREQPRIO_1_OFFSET, 58162306a36Sopenharmony_ci AM33XX_CONTROL_HW_EVENT_SEL_GRP1_OFFSET, 58262306a36Sopenharmony_ci AM33XX_CONTROL_HW_EVENT_SEL_GRP2_OFFSET, 58362306a36Sopenharmony_ci AM33XX_CONTROL_HW_EVENT_SEL_GRP3_OFFSET, 58462306a36Sopenharmony_ci AM33XX_CONTROL_HW_EVENT_SEL_GRP4_OFFSET, 58562306a36Sopenharmony_ci AM33XX_CONTROL_SMRT_CTRL_OFFSET, 58662306a36Sopenharmony_ci AM33XX_CONTROL_MPUSS_HW_DEBUG_SEL_OFFSET, 58762306a36Sopenharmony_ci AM43XX_CONTROL_CQDETECT_STS_OFFSET, 58862306a36Sopenharmony_ci AM43XX_CONTROL_CQDETECT_STS2_OFFSET, 58962306a36Sopenharmony_ci AM43XX_CONTROL_VTP_CTRL_OFFSET, 59062306a36Sopenharmony_ci AM33XX_CONTROL_VREF_CTRL_OFFSET, 59162306a36Sopenharmony_ci AM33XX_CONTROL_TPCC_EVT_MUX_0_3_OFFSET, 59262306a36Sopenharmony_ci AM33XX_CONTROL_TPCC_EVT_MUX_4_7_OFFSET, 59362306a36Sopenharmony_ci AM33XX_CONTROL_TPCC_EVT_MUX_8_11_OFFSET, 59462306a36Sopenharmony_ci AM33XX_CONTROL_TPCC_EVT_MUX_12_15_OFFSET, 59562306a36Sopenharmony_ci AM33XX_CONTROL_TPCC_EVT_MUX_16_19_OFFSET, 59662306a36Sopenharmony_ci AM33XX_CONTROL_TPCC_EVT_MUX_20_23_OFFSET, 59762306a36Sopenharmony_ci AM33XX_CONTROL_TPCC_EVT_MUX_24_27_OFFSET, 59862306a36Sopenharmony_ci AM33XX_CONTROL_TPCC_EVT_MUX_28_31_OFFSET, 59962306a36Sopenharmony_ci AM33XX_CONTROL_TPCC_EVT_MUX_32_35_OFFSET, 60062306a36Sopenharmony_ci AM33XX_CONTROL_TPCC_EVT_MUX_36_39_OFFSET, 60162306a36Sopenharmony_ci AM33XX_CONTROL_TPCC_EVT_MUX_40_43_OFFSET, 60262306a36Sopenharmony_ci AM33XX_CONTROL_TPCC_EVT_MUX_44_47_OFFSET, 60362306a36Sopenharmony_ci AM33XX_CONTROL_TPCC_EVT_MUX_48_51_OFFSET, 60462306a36Sopenharmony_ci AM33XX_CONTROL_TPCC_EVT_MUX_52_55_OFFSET, 60562306a36Sopenharmony_ci AM33XX_CONTROL_TPCC_EVT_MUX_56_59_OFFSET, 60662306a36Sopenharmony_ci AM33XX_CONTROL_TPCC_EVT_MUX_60_63_OFFSET, 60762306a36Sopenharmony_ci AM33XX_CONTROL_TIMER_EVT_CAPT_OFFSET, 60862306a36Sopenharmony_ci AM33XX_CONTROL_ECAP_EVT_CAPT_OFFSET, 60962306a36Sopenharmony_ci AM33XX_CONTROL_ADC_EVT_CAPT_OFFSET, 61062306a36Sopenharmony_ci AM43XX_CONTROL_ADC1_EVT_CAPT_OFFSET, 61162306a36Sopenharmony_ci AM33XX_CONTROL_RESET_ISO_OFFSET, 61262306a36Sopenharmony_ci}; 61362306a36Sopenharmony_ci 61462306a36Sopenharmony_cistatic u32 am33xx_control_vals[ARRAY_SIZE(am43xx_control_reg_offsets)]; 61562306a36Sopenharmony_ci 61662306a36Sopenharmony_ci/** 61762306a36Sopenharmony_ci * am43xx_control_save_context - Save the wakeup domain registers 61862306a36Sopenharmony_ci * 61962306a36Sopenharmony_ci * Save the wkup domain registers 62062306a36Sopenharmony_ci */ 62162306a36Sopenharmony_cistatic void am43xx_control_save_context(void) 62262306a36Sopenharmony_ci{ 62362306a36Sopenharmony_ci int i; 62462306a36Sopenharmony_ci 62562306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(am43xx_control_reg_offsets); i++) 62662306a36Sopenharmony_ci am33xx_control_vals[i] = 62762306a36Sopenharmony_ci omap_ctrl_readl(am43xx_control_reg_offsets[i]); 62862306a36Sopenharmony_ci} 62962306a36Sopenharmony_ci 63062306a36Sopenharmony_ci/** 63162306a36Sopenharmony_ci * am43xx_control_restore_context - Restore the wakeup domain registers 63262306a36Sopenharmony_ci * 63362306a36Sopenharmony_ci * Restore the wkup domain registers 63462306a36Sopenharmony_ci */ 63562306a36Sopenharmony_cistatic void am43xx_control_restore_context(void) 63662306a36Sopenharmony_ci{ 63762306a36Sopenharmony_ci int i; 63862306a36Sopenharmony_ci 63962306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(am43xx_control_reg_offsets); i++) 64062306a36Sopenharmony_ci omap_ctrl_writel(am33xx_control_vals[i], 64162306a36Sopenharmony_ci am43xx_control_reg_offsets[i]); 64262306a36Sopenharmony_ci} 64362306a36Sopenharmony_ci 64462306a36Sopenharmony_cistatic int cpu_notifier(struct notifier_block *nb, unsigned long cmd, void *v) 64562306a36Sopenharmony_ci{ 64662306a36Sopenharmony_ci switch (cmd) { 64762306a36Sopenharmony_ci case CPU_CLUSTER_PM_ENTER: 64862306a36Sopenharmony_ci if (enable_off_mode) 64962306a36Sopenharmony_ci am43xx_control_save_context(); 65062306a36Sopenharmony_ci break; 65162306a36Sopenharmony_ci case CPU_CLUSTER_PM_EXIT: 65262306a36Sopenharmony_ci if (enable_off_mode) 65362306a36Sopenharmony_ci am43xx_control_restore_context(); 65462306a36Sopenharmony_ci break; 65562306a36Sopenharmony_ci } 65662306a36Sopenharmony_ci 65762306a36Sopenharmony_ci return NOTIFY_OK; 65862306a36Sopenharmony_ci} 65962306a36Sopenharmony_ci 66062306a36Sopenharmony_cistruct control_init_data { 66162306a36Sopenharmony_ci int index; 66262306a36Sopenharmony_ci void __iomem *mem; 66362306a36Sopenharmony_ci s16 offset; 66462306a36Sopenharmony_ci}; 66562306a36Sopenharmony_ci 66662306a36Sopenharmony_cistatic struct control_init_data ctrl_data = { 66762306a36Sopenharmony_ci .index = TI_CLKM_CTRL, 66862306a36Sopenharmony_ci}; 66962306a36Sopenharmony_ci 67062306a36Sopenharmony_cistatic const struct control_init_data omap2_ctrl_data = { 67162306a36Sopenharmony_ci .index = TI_CLKM_CTRL, 67262306a36Sopenharmony_ci .offset = -OMAP2_CONTROL_GENERAL, 67362306a36Sopenharmony_ci}; 67462306a36Sopenharmony_ci 67562306a36Sopenharmony_cistatic const struct control_init_data ctrl_aux_data = { 67662306a36Sopenharmony_ci .index = TI_CLKM_CTRL_AUX, 67762306a36Sopenharmony_ci}; 67862306a36Sopenharmony_ci 67962306a36Sopenharmony_cistatic const struct of_device_id omap_scrm_dt_match_table[] = { 68062306a36Sopenharmony_ci { .compatible = "ti,am3-scm", .data = &ctrl_data }, 68162306a36Sopenharmony_ci { .compatible = "ti,am4-scm", .data = &ctrl_data }, 68262306a36Sopenharmony_ci { .compatible = "ti,omap2-scm", .data = &omap2_ctrl_data }, 68362306a36Sopenharmony_ci { .compatible = "ti,omap3-scm", .data = &omap2_ctrl_data }, 68462306a36Sopenharmony_ci { .compatible = "ti,dm814-scm", .data = &ctrl_data }, 68562306a36Sopenharmony_ci { .compatible = "ti,dm816-scrm", .data = &ctrl_data }, 68662306a36Sopenharmony_ci { .compatible = "ti,omap4-scm-core", .data = &ctrl_data }, 68762306a36Sopenharmony_ci { .compatible = "ti,omap5-scm-core", .data = &ctrl_data }, 68862306a36Sopenharmony_ci { .compatible = "ti,omap5-scm-wkup-pad-conf", .data = &ctrl_aux_data }, 68962306a36Sopenharmony_ci { .compatible = "ti,dra7-scm-core", .data = &ctrl_data }, 69062306a36Sopenharmony_ci { } 69162306a36Sopenharmony_ci}; 69262306a36Sopenharmony_ci 69362306a36Sopenharmony_ci/** 69462306a36Sopenharmony_ci * omap2_control_base_init - initialize iomappings for the control driver 69562306a36Sopenharmony_ci * 69662306a36Sopenharmony_ci * Detects and initializes the iomappings for the control driver, based 69762306a36Sopenharmony_ci * on the DT data. Returns 0 in success, negative error value 69862306a36Sopenharmony_ci * otherwise. 69962306a36Sopenharmony_ci */ 70062306a36Sopenharmony_ciint __init omap2_control_base_init(void) 70162306a36Sopenharmony_ci{ 70262306a36Sopenharmony_ci struct device_node *np; 70362306a36Sopenharmony_ci const struct of_device_id *match; 70462306a36Sopenharmony_ci struct control_init_data *data; 70562306a36Sopenharmony_ci void __iomem *mem; 70662306a36Sopenharmony_ci 70762306a36Sopenharmony_ci for_each_matching_node_and_match(np, omap_scrm_dt_match_table, &match) { 70862306a36Sopenharmony_ci data = (struct control_init_data *)match->data; 70962306a36Sopenharmony_ci 71062306a36Sopenharmony_ci mem = of_iomap(np, 0); 71162306a36Sopenharmony_ci if (!mem) { 71262306a36Sopenharmony_ci of_node_put(np); 71362306a36Sopenharmony_ci return -ENOMEM; 71462306a36Sopenharmony_ci } 71562306a36Sopenharmony_ci 71662306a36Sopenharmony_ci if (data->index == TI_CLKM_CTRL) { 71762306a36Sopenharmony_ci omap2_ctrl_base = mem; 71862306a36Sopenharmony_ci omap2_ctrl_offset = data->offset; 71962306a36Sopenharmony_ci } 72062306a36Sopenharmony_ci 72162306a36Sopenharmony_ci data->mem = mem; 72262306a36Sopenharmony_ci } 72362306a36Sopenharmony_ci 72462306a36Sopenharmony_ci return 0; 72562306a36Sopenharmony_ci} 72662306a36Sopenharmony_ci 72762306a36Sopenharmony_ci/** 72862306a36Sopenharmony_ci * omap_control_init - low level init for the control driver 72962306a36Sopenharmony_ci * 73062306a36Sopenharmony_ci * Initializes the low level clock infrastructure for control driver. 73162306a36Sopenharmony_ci * Returns 0 in success, negative error value in failure. 73262306a36Sopenharmony_ci */ 73362306a36Sopenharmony_ciint __init omap_control_init(void) 73462306a36Sopenharmony_ci{ 73562306a36Sopenharmony_ci struct device_node *np, *scm_conf; 73662306a36Sopenharmony_ci const struct of_device_id *match; 73762306a36Sopenharmony_ci const struct omap_prcm_init_data *data; 73862306a36Sopenharmony_ci int ret; 73962306a36Sopenharmony_ci struct regmap *syscon; 74062306a36Sopenharmony_ci static struct notifier_block nb; 74162306a36Sopenharmony_ci 74262306a36Sopenharmony_ci for_each_matching_node_and_match(np, omap_scrm_dt_match_table, &match) { 74362306a36Sopenharmony_ci data = match->data; 74462306a36Sopenharmony_ci 74562306a36Sopenharmony_ci /* 74662306a36Sopenharmony_ci * Check if we have scm_conf node, if yes, use this to 74762306a36Sopenharmony_ci * access clock registers. 74862306a36Sopenharmony_ci */ 74962306a36Sopenharmony_ci scm_conf = of_get_child_by_name(np, "scm_conf"); 75062306a36Sopenharmony_ci 75162306a36Sopenharmony_ci if (scm_conf) { 75262306a36Sopenharmony_ci syscon = syscon_node_to_regmap(scm_conf); 75362306a36Sopenharmony_ci 75462306a36Sopenharmony_ci if (IS_ERR(syscon)) { 75562306a36Sopenharmony_ci ret = PTR_ERR(syscon); 75662306a36Sopenharmony_ci goto of_node_put; 75762306a36Sopenharmony_ci } 75862306a36Sopenharmony_ci 75962306a36Sopenharmony_ci if (of_get_child_by_name(scm_conf, "clocks")) { 76062306a36Sopenharmony_ci ret = omap2_clk_provider_init(scm_conf, 76162306a36Sopenharmony_ci data->index, 76262306a36Sopenharmony_ci syscon, NULL); 76362306a36Sopenharmony_ci if (ret) 76462306a36Sopenharmony_ci goto of_node_put; 76562306a36Sopenharmony_ci } 76662306a36Sopenharmony_ci } else { 76762306a36Sopenharmony_ci /* No scm_conf found, direct access */ 76862306a36Sopenharmony_ci ret = omap2_clk_provider_init(np, data->index, NULL, 76962306a36Sopenharmony_ci data->mem); 77062306a36Sopenharmony_ci if (ret) 77162306a36Sopenharmony_ci goto of_node_put; 77262306a36Sopenharmony_ci } 77362306a36Sopenharmony_ci } 77462306a36Sopenharmony_ci 77562306a36Sopenharmony_ci /* Only AM43XX can lose ctrl registers context during rtc-ddr suspend */ 77662306a36Sopenharmony_ci if (soc_is_am43xx()) { 77762306a36Sopenharmony_ci nb.notifier_call = cpu_notifier; 77862306a36Sopenharmony_ci cpu_pm_register_notifier(&nb); 77962306a36Sopenharmony_ci } 78062306a36Sopenharmony_ci 78162306a36Sopenharmony_ci return 0; 78262306a36Sopenharmony_ci 78362306a36Sopenharmony_ciof_node_put: 78462306a36Sopenharmony_ci of_node_put(np); 78562306a36Sopenharmony_ci return ret; 78662306a36Sopenharmony_ci 78762306a36Sopenharmony_ci} 788