Samsung mach updates for v4.1
- for s3c64xx : use fixed IRQ bases to avoid conflicts on Cragganmore - for exynos3250 : add cpuidle and AFTR mode support : fix CPU1 hotplug - for exynos SoCs : add code for setting/clearing boot flag for cpuidle AFTR : remove left over 'extra_save' and constify 'exynos_pm_data' array : use static in suspend.c as per compiler suggestions : use platform device name as power domain name : add support for async-bridge clocks for pm_domains (exynos5420) -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.11 (GNU/Linux) iQIcBAABAgAGBQJVHDOIAAoJEA0Cl+kVi2xqIc0P/0x7bX76DHU01ATRWi4u+wRe tPCjxeBpN/VfLb/x0JtFv6HHCGeGpgzEaYRHG7LHvX6F/oVldTuDr43aJximKG1k NLG1NqczL4G6GrLABM3dQqWC88Jgrhfflqoq1y7M/fUhayOBjKcy0jrNIK1Qb+dp 3msyDeODyTSMIMIvufJLYW/kq0EVM7RMN9QUVGg+6YXZOuYs1nEa104PMElz8oEk ntS14DYTZV/U5Nof+SK+6AYi+JN9ywnIv/NG0zjTF4kHEgqy+MRW7nRIKt4B7iSV WT1i/AktTByEhhZlz3KTMyhrP/L0LxVqsc6COyrUHPj9yugWXcEmcoC7pOxni4sR YWwDSCWkJyZ5PmzBG6tGLrEiUDlPng9qHCPXg5tI+ZRgli3IzKjPmUSB5onv3nT5 fHEH7uuhQ4D6MpNeCxb0KSDT6bvR3ghKZyIvn0X3sfRzGM1z4tDaG59FMlTc0DaX jt56LHXfmqIomLNYRe3MihFHPtK0AB5z8SU//ebPFBIB+i3z3OLeQKNQkG6Zccuq mhtlumGAe6xqPDNmN0KvnW2IJ9K+E35IH5M6goEddDK6xi6jCtyKGfL/CK6N+87C rOIs08fg5tQ0i0KVzx0StbTMAOVfKMqGJrKeUuDb11fX8PUFEPYDl26QdSAcjkwQ 4Z6q42dLlxfWQOs5bF9N =05kO -----END PGP SIGNATURE----- Merge tag 'samsung-updates' of git://git.kernel.org/pub/scm/linux/kernel/git/kgene/linux-samsung into next/soc Merge "Samsung mach updates for v4.1" from Kukjin Kim: - for s3c64xx : use fixed IRQ bases to avoid conflicts on Cragganmore - for exynos3250 : add cpuidle and AFTR mode support : fix CPU1 hotplug - for exynos SoCs : add code for setting/clearing boot flag for cpuidle AFTR : remove left over 'extra_save' and constify 'exynos_pm_data' array : use static in suspend.c as per compiler suggestions : use platform device name as power domain name : add support for async-bridge clocks for pm_domains (exynos5420) * tag 'samsung-updates' of git://git.kernel.org/pub/scm/linux/kernel/git/kgene/linux-samsung: ARM: EXYNOS: allow cpuidle driver usage on Exynos3250 SoC ARM: EXYNOS: add AFTR mode support for Exynos3250 ARM: EXYNOS: add code for setting/clearing boot flag ARM: EXYNOS: fix CPU1 hotplug on Exynos3250 ARM: S3C64XX: Use fixed IRQ bases to avoid conflicts on Cragganmore ARM: EXYNOS: Remove left over 'extra_save' ARM: EXYNOS: Constify exynos_pm_data array ARM: EXYNOS: use static in suspend.c ARM: EXYNOS: Use platform device name as power domain name ARM: EXYNOS: add support for async-bridge clocks for pm_domains Signed-off-by: Olof Johansson <olof@lixom.net>
This commit is contained in:
Коммит
7cef9875f3
|
@ -126,6 +126,12 @@ enum {
|
|||
|
||||
void exynos_firmware_init(void);
|
||||
|
||||
/* CPU BOOT mode flag for Exynos3250 SoC bootloader */
|
||||
#define C2_STATE (1 << 3)
|
||||
|
||||
void exynos_set_boot_flag(unsigned int cpu, unsigned int mode);
|
||||
void exynos_clear_boot_flag(unsigned int cpu, unsigned int mode);
|
||||
|
||||
extern u32 exynos_get_eint_wake_mask(void);
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
|
|
|
@ -219,6 +219,7 @@ static void __init exynos_dt_machine_init(void)
|
|||
of_machine_is_compatible("samsung,exynos4212") ||
|
||||
(of_machine_is_compatible("samsung,exynos4412") &&
|
||||
of_machine_is_compatible("samsung,trats2")) ||
|
||||
of_machine_is_compatible("samsung,exynos3250") ||
|
||||
of_machine_is_compatible("samsung,exynos5250"))
|
||||
platform_device_register(&exynos_cpuidle);
|
||||
|
||||
|
|
|
@ -48,7 +48,13 @@ static int exynos_do_idle(unsigned long mode)
|
|||
__raw_writel(virt_to_phys(exynos_cpu_resume_ns),
|
||||
sysram_ns_base_addr + 0x24);
|
||||
__raw_writel(EXYNOS_AFTR_MAGIC, sysram_ns_base_addr + 0x20);
|
||||
exynos_smc(SMC_CMD_CPU0AFTR, 0, 0, 0);
|
||||
if (soc_is_exynos3250()) {
|
||||
exynos_smc(SMC_CMD_SAVE, OP_TYPE_CORE,
|
||||
SMC_POWERSTATE_IDLE, 0);
|
||||
exynos_smc(SMC_CMD_SHUTDOWN, OP_TYPE_CLUSTER,
|
||||
SMC_POWERSTATE_IDLE, 0);
|
||||
} else
|
||||
exynos_smc(SMC_CMD_CPU0AFTR, 0, 0, 0);
|
||||
break;
|
||||
case FW_DO_IDLE_SLEEP:
|
||||
exynos_smc(SMC_CMD_SLEEP, 0, 0, 0);
|
||||
|
@ -206,3 +212,28 @@ void __init exynos_firmware_init(void)
|
|||
outer_cache.configure = exynos_l2_configure;
|
||||
}
|
||||
}
|
||||
|
||||
#define REG_CPU_STATE_ADDR (sysram_ns_base_addr + 0x28)
|
||||
#define BOOT_MODE_MASK 0x1f
|
||||
|
||||
void exynos_set_boot_flag(unsigned int cpu, unsigned int mode)
|
||||
{
|
||||
unsigned int tmp;
|
||||
|
||||
tmp = __raw_readl(REG_CPU_STATE_ADDR + cpu * 4);
|
||||
|
||||
if (mode & BOOT_MODE_MASK)
|
||||
tmp &= ~BOOT_MODE_MASK;
|
||||
|
||||
tmp |= mode;
|
||||
__raw_writel(tmp, REG_CPU_STATE_ADDR + cpu * 4);
|
||||
}
|
||||
|
||||
void exynos_clear_boot_flag(unsigned int cpu, unsigned int mode)
|
||||
{
|
||||
unsigned int tmp;
|
||||
|
||||
tmp = __raw_readl(REG_CPU_STATE_ADDR + cpu * 4);
|
||||
tmp &= ~mode;
|
||||
__raw_writel(tmp, REG_CPU_STATE_ADDR + cpu * 4);
|
||||
}
|
||||
|
|
|
@ -126,6 +126,8 @@ static inline void platform_do_lowpower(unsigned int cpu, int *spurious)
|
|||
*/
|
||||
void exynos_cpu_power_down(int cpu)
|
||||
{
|
||||
u32 core_conf;
|
||||
|
||||
if (cpu == 0 && (of_machine_is_compatible("samsung,exynos5420") ||
|
||||
of_machine_is_compatible("samsung,exynos5800"))) {
|
||||
/*
|
||||
|
@ -138,7 +140,10 @@ void exynos_cpu_power_down(int cpu)
|
|||
if (!(val & S5P_CORE_LOCAL_PWR_EN))
|
||||
return;
|
||||
}
|
||||
pmu_raw_writel(0, EXYNOS_ARM_CORE_CONFIGURATION(cpu));
|
||||
|
||||
core_conf = pmu_raw_readl(EXYNOS_ARM_CORE_CONFIGURATION(cpu));
|
||||
core_conf &= ~S5P_CORE_LOCAL_PWR_EN;
|
||||
pmu_raw_writel(core_conf, EXYNOS_ARM_CORE_CONFIGURATION(cpu));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -149,7 +154,12 @@ void exynos_cpu_power_down(int cpu)
|
|||
*/
|
||||
void exynos_cpu_power_up(int cpu)
|
||||
{
|
||||
pmu_raw_writel(S5P_CORE_LOCAL_PWR_EN,
|
||||
u32 core_conf = S5P_CORE_LOCAL_PWR_EN;
|
||||
|
||||
if (soc_is_exynos3250())
|
||||
core_conf |= S5P_CORE_AUTOWAKEUP_EN;
|
||||
|
||||
pmu_raw_writel(core_conf,
|
||||
EXYNOS_ARM_CORE_CONFIGURATION(cpu));
|
||||
}
|
||||
|
||||
|
@ -227,6 +237,10 @@ static void exynos_core_restart(u32 core_id)
|
|||
if (!of_machine_is_compatible("samsung,exynos3250"))
|
||||
return;
|
||||
|
||||
while (!pmu_raw_readl(S5P_PMU_SPARE2))
|
||||
udelay(10);
|
||||
udelay(10);
|
||||
|
||||
val = pmu_raw_readl(EXYNOS_ARM_CORE_STATUS(core_id));
|
||||
val |= S5P_CORE_WAKEUP_FROM_LOCAL_CFG;
|
||||
pmu_raw_writel(val, EXYNOS_ARM_CORE_STATUS(core_id));
|
||||
|
@ -347,7 +361,10 @@ static int exynos_boot_secondary(unsigned int cpu, struct task_struct *idle)
|
|||
|
||||
call_firmware_op(cpu_boot, core_id);
|
||||
|
||||
arch_send_wakeup_ipi_mask(cpumask_of(cpu));
|
||||
if (soc_is_exynos3250())
|
||||
dsb_sev();
|
||||
else
|
||||
arch_send_wakeup_ipi_mask(cpumask_of(cpu));
|
||||
|
||||
if (pen_release == -1)
|
||||
break;
|
||||
|
|
|
@ -127,6 +127,8 @@ int exynos_pm_central_resume(void)
|
|||
static void exynos_set_wakeupmask(long mask)
|
||||
{
|
||||
pmu_raw_writel(mask, S5P_WAKEUP_MASK);
|
||||
if (soc_is_exynos3250())
|
||||
pmu_raw_writel(0x0, S5P_WAKEUP_MASK2);
|
||||
}
|
||||
|
||||
static void exynos_cpu_set_boot_vector(long flags)
|
||||
|
@ -140,7 +142,7 @@ static int exynos_aftr_finisher(unsigned long flags)
|
|||
{
|
||||
int ret;
|
||||
|
||||
exynos_set_wakeupmask(0x0000ff3e);
|
||||
exynos_set_wakeupmask(soc_is_exynos3250() ? 0x40003ffe : 0x0000ff3e);
|
||||
/* Set value of power down register for aftr mode */
|
||||
exynos_sys_powerdown_conf(SYS_AFTR);
|
||||
|
||||
|
@ -157,8 +159,13 @@ static int exynos_aftr_finisher(unsigned long flags)
|
|||
|
||||
void exynos_enter_aftr(void)
|
||||
{
|
||||
unsigned int cpuid = smp_processor_id();
|
||||
|
||||
cpu_pm_enter();
|
||||
|
||||
if (soc_is_exynos3250())
|
||||
exynos_set_boot_flag(cpuid, C2_STATE);
|
||||
|
||||
exynos_pm_central_suspend();
|
||||
|
||||
if (of_machine_is_compatible("samsung,exynos4212") ||
|
||||
|
@ -178,6 +185,9 @@ void exynos_enter_aftr(void)
|
|||
|
||||
exynos_pm_central_resume();
|
||||
|
||||
if (soc_is_exynos3250())
|
||||
exynos_clear_boot_flag(cpuid, C2_STATE);
|
||||
|
||||
cpu_pm_exit();
|
||||
}
|
||||
|
||||
|
|
|
@ -37,6 +37,7 @@ struct exynos_pm_domain {
|
|||
struct clk *oscclk;
|
||||
struct clk *clk[MAX_CLK_PER_DOMAIN];
|
||||
struct clk *pclk[MAX_CLK_PER_DOMAIN];
|
||||
struct clk *asb_clk[MAX_CLK_PER_DOMAIN];
|
||||
};
|
||||
|
||||
static int exynos_pd_power(struct generic_pm_domain *domain, bool power_on)
|
||||
|
@ -45,14 +46,19 @@ static int exynos_pd_power(struct generic_pm_domain *domain, bool power_on)
|
|||
void __iomem *base;
|
||||
u32 timeout, pwr;
|
||||
char *op;
|
||||
int i;
|
||||
|
||||
pd = container_of(domain, struct exynos_pm_domain, pd);
|
||||
base = pd->base;
|
||||
|
||||
for (i = 0; i < MAX_CLK_PER_DOMAIN; i++) {
|
||||
if (IS_ERR(pd->asb_clk[i]))
|
||||
break;
|
||||
clk_prepare_enable(pd->asb_clk[i]);
|
||||
}
|
||||
|
||||
/* Set oscclk before powering off a domain*/
|
||||
if (!power_on) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < MAX_CLK_PER_DOMAIN; i++) {
|
||||
if (IS_ERR(pd->clk[i]))
|
||||
break;
|
||||
|
@ -81,8 +87,6 @@ static int exynos_pd_power(struct generic_pm_domain *domain, bool power_on)
|
|||
|
||||
/* Restore clocks after powering on a domain*/
|
||||
if (power_on) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < MAX_CLK_PER_DOMAIN; i++) {
|
||||
if (IS_ERR(pd->clk[i]))
|
||||
break;
|
||||
|
@ -92,6 +96,12 @@ static int exynos_pd_power(struct generic_pm_domain *domain, bool power_on)
|
|||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < MAX_CLK_PER_DOMAIN; i++) {
|
||||
if (IS_ERR(pd->asb_clk[i]))
|
||||
break;
|
||||
clk_disable_unprepare(pd->asb_clk[i]);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -125,12 +135,21 @@ static __init int exynos4_pm_init_power_domain(void)
|
|||
return -ENOMEM;
|
||||
}
|
||||
|
||||
pd->pd.name = kstrdup(np->name, GFP_KERNEL);
|
||||
pd->pd.name = kstrdup(dev_name(dev), GFP_KERNEL);
|
||||
pd->name = pd->pd.name;
|
||||
pd->base = of_iomap(np, 0);
|
||||
pd->pd.power_off = exynos_pd_power_off;
|
||||
pd->pd.power_on = exynos_pd_power_on;
|
||||
|
||||
for (i = 0; i < MAX_CLK_PER_DOMAIN; i++) {
|
||||
char clk_name[8];
|
||||
|
||||
snprintf(clk_name, sizeof(clk_name), "asb%d", i);
|
||||
pd->asb_clk[i] = clk_get(dev, clk_name);
|
||||
if (IS_ERR(pd->asb_clk[i]))
|
||||
break;
|
||||
}
|
||||
|
||||
pd->oscclk = clk_get(dev, "oscclk");
|
||||
if (IS_ERR(pd->oscclk))
|
||||
goto no_clk;
|
||||
|
|
|
@ -43,12 +43,14 @@
|
|||
#define S5P_WAKEUP_STAT 0x0600
|
||||
#define S5P_EINT_WAKEUP_MASK 0x0604
|
||||
#define S5P_WAKEUP_MASK 0x0608
|
||||
#define S5P_WAKEUP_MASK2 0x0614
|
||||
|
||||
#define S5P_INFORM0 0x0800
|
||||
#define S5P_INFORM1 0x0804
|
||||
#define S5P_INFORM5 0x0814
|
||||
#define S5P_INFORM6 0x0818
|
||||
#define S5P_INFORM7 0x081C
|
||||
#define S5P_PMU_SPARE2 0x0908
|
||||
#define S5P_PMU_SPARE3 0x090C
|
||||
|
||||
#define EXYNOS_IROM_DATA2 0x0988
|
||||
|
@ -182,6 +184,7 @@
|
|||
|
||||
#define S5P_CORE_LOCAL_PWR_EN 0x3
|
||||
#define S5P_CORE_WAKEUP_FROM_LOCAL_CFG (0x3 << 8)
|
||||
#define S5P_CORE_AUTOWAKEUP_EN (1 << 31)
|
||||
|
||||
/* Only for EXYNOS4210 */
|
||||
#define S5P_CMU_CLKSTOP_LCD1_LOWPWR 0x1154
|
||||
|
|
|
@ -17,6 +17,8 @@
|
|||
#define SMC_CMD_SLEEP (-3)
|
||||
#define SMC_CMD_CPU1BOOT (-4)
|
||||
#define SMC_CMD_CPU0AFTR (-5)
|
||||
#define SMC_CMD_SAVE (-6)
|
||||
#define SMC_CMD_SHUTDOWN (-7)
|
||||
/* For CP15 Access */
|
||||
#define SMC_CMD_C15RESUME (-11)
|
||||
/* For L2 Cache Access */
|
||||
|
@ -32,4 +34,11 @@ extern void exynos_smc(u32 cmd, u32 arg1, u32 arg2, u32 arg3);
|
|||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
|
||||
/* op type for SMC_CMD_SAVE and SMC_CMD_SHUTDOWN */
|
||||
#define OP_TYPE_CORE 0x0
|
||||
#define OP_TYPE_CLUSTER 0x1
|
||||
|
||||
/* Power State required for SMC_CMD_SAVE and SMC_CMD_SHUTDOWN */
|
||||
#define SMC_POWERSTATE_IDLE 0x1
|
||||
|
||||
#endif
|
||||
|
|
|
@ -63,8 +63,6 @@ static struct sleep_save exynos_core_save[] = {
|
|||
|
||||
struct exynos_pm_data {
|
||||
const struct exynos_wkup_irq *wkup_irq;
|
||||
struct sleep_save *extra_save;
|
||||
int num_extra_save;
|
||||
unsigned int wake_disable_mask;
|
||||
unsigned int *release_ret_regs;
|
||||
|
||||
|
@ -75,7 +73,7 @@ struct exynos_pm_data {
|
|||
int (*cpu_suspend)(unsigned long);
|
||||
};
|
||||
|
||||
struct exynos_pm_data *pm_data;
|
||||
static const struct exynos_pm_data *pm_data;
|
||||
|
||||
static int exynos5420_cpu_state;
|
||||
static unsigned int exynos_pmu_spare3;
|
||||
|
@ -104,7 +102,7 @@ static const struct exynos_wkup_irq exynos5250_wkup_irq[] = {
|
|||
{ /* sentinel */ },
|
||||
};
|
||||
|
||||
unsigned int exynos_release_ret_regs[] = {
|
||||
static unsigned int exynos_release_ret_regs[] = {
|
||||
S5P_PAD_RET_MAUDIO_OPTION,
|
||||
S5P_PAD_RET_GPIO_OPTION,
|
||||
S5P_PAD_RET_UART_OPTION,
|
||||
|
@ -115,7 +113,7 @@ unsigned int exynos_release_ret_regs[] = {
|
|||
REG_TABLE_END,
|
||||
};
|
||||
|
||||
unsigned int exynos3250_release_ret_regs[] = {
|
||||
static unsigned int exynos3250_release_ret_regs[] = {
|
||||
S5P_PAD_RET_MAUDIO_OPTION,
|
||||
S5P_PAD_RET_GPIO_OPTION,
|
||||
S5P_PAD_RET_UART_OPTION,
|
||||
|
@ -128,7 +126,7 @@ unsigned int exynos3250_release_ret_regs[] = {
|
|||
REG_TABLE_END,
|
||||
};
|
||||
|
||||
unsigned int exynos5420_release_ret_regs[] = {
|
||||
static unsigned int exynos5420_release_ret_regs[] = {
|
||||
EXYNOS_PAD_RET_DRAM_OPTION,
|
||||
EXYNOS_PAD_RET_MAUDIO_OPTION,
|
||||
EXYNOS_PAD_RET_JTAG_OPTION,
|
||||
|
@ -240,10 +238,6 @@ static void exynos_pm_prepare(void)
|
|||
|
||||
s3c_pm_do_save(exynos_core_save, ARRAY_SIZE(exynos_core_save));
|
||||
|
||||
if (pm_data->extra_save)
|
||||
s3c_pm_do_save(pm_data->extra_save,
|
||||
pm_data->num_extra_save);
|
||||
|
||||
exynos_pm_enter_sleep_mode();
|
||||
|
||||
/* ensure at least INFORM0 has the resume address */
|
||||
|
@ -366,10 +360,6 @@ static void exynos_pm_resume(void)
|
|||
/* For release retention */
|
||||
exynos_pm_release_retention();
|
||||
|
||||
if (pm_data->extra_save)
|
||||
s3c_pm_do_restore_core(pm_data->extra_save,
|
||||
pm_data->num_extra_save);
|
||||
|
||||
s3c_pm_do_restore_core(exynos_core_save, ARRAY_SIZE(exynos_core_save));
|
||||
|
||||
if (cpuid == ARM_CPU_PART_CORTEX_A9)
|
||||
|
@ -576,7 +566,7 @@ static const struct exynos_pm_data exynos5250_pm_data = {
|
|||
.cpu_suspend = exynos_cpu_suspend,
|
||||
};
|
||||
|
||||
static struct exynos_pm_data exynos5420_pm_data = {
|
||||
static const struct exynos_pm_data exynos5420_pm_data = {
|
||||
.wkup_irq = exynos5250_wkup_irq,
|
||||
.wake_disable_mask = (0x7F << 7) | (0x1F << 1),
|
||||
.release_ret_regs = exynos5420_release_ret_regs,
|
||||
|
@ -622,7 +612,7 @@ void __init exynos_pm_init(void)
|
|||
pr_err("Failed to find PMU node\n");
|
||||
return;
|
||||
}
|
||||
pm_data = (struct exynos_pm_data *) match->data;
|
||||
pm_data = (const struct exynos_pm_data *) match->data;
|
||||
|
||||
/* Platform-specific GIC callback */
|
||||
gic_arch_extn.irq_set_wake = exynos_irq_set_wake;
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include <mach/gpio-samsung.h>
|
||||
|
||||
#define GLENFARCLAS_PMIC_IRQ_BASE IRQ_BOARD_START
|
||||
#define BANFF_PMIC_IRQ_BASE (IRQ_BOARD_START + 64)
|
||||
|
||||
#define PCA935X_GPIO_BASE GPIO_BOARD_START
|
||||
#define CODEC_GPIO_BASE (GPIO_BOARD_START + 8)
|
||||
|
|
|
@ -554,6 +554,7 @@ static struct wm831x_touch_pdata touch_pdata = {
|
|||
|
||||
static struct wm831x_pdata crag_pmic_pdata = {
|
||||
.wm831x_num = 1,
|
||||
.irq_base = BANFF_PMIC_IRQ_BASE,
|
||||
.gpio_base = BANFF_PMIC_GPIO_BASE,
|
||||
.soft_shutdown = true,
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче