Skip to content

Commit

Permalink
Merge tag 'samsung-updates' of git://git.kernel.org/pub/scm/linux/ker…
Browse files Browse the repository at this point in the history
…nel/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 <[email protected]>
  • Loading branch information
olofj committed Apr 3, 2015
2 parents f83255c + bd0d888 commit 7cef987
Show file tree
Hide file tree
Showing 11 changed files with 114 additions and 26 deletions.
6 changes: 6 additions & 0 deletions arch/arm/mach-exynos/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions arch/arm/mach-exynos/exynos.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
33 changes: 32 additions & 1 deletion arch/arm/mach-exynos/firmware.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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);
}
23 changes: 20 additions & 3 deletions arch/arm/mach-exynos/platsmp.c
Original file line number Diff line number Diff line change
Expand Up @@ -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"))) {
/*
Expand All @@ -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));
}

/**
Expand All @@ -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));
}

Expand Down Expand Up @@ -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));
Expand Down Expand Up @@ -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;
Expand Down
12 changes: 11 additions & 1 deletion arch/arm/mach-exynos/pm.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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);

Expand All @@ -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") ||
Expand All @@ -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();
}

Expand Down
29 changes: 24 additions & 5 deletions arch/arm/mach-exynos/pm_domains.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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;
Expand Down Expand Up @@ -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;
Expand All @@ -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;
}

Expand Down Expand Up @@ -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;
Expand Down
3 changes: 3 additions & 0 deletions arch/arm/mach-exynos/regs-pmu.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
9 changes: 9 additions & 0 deletions arch/arm/mach-exynos/smc.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand All @@ -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
22 changes: 6 additions & 16 deletions arch/arm/mach-exynos/suspend.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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;
Expand Down Expand Up @@ -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,
Expand All @@ -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,
Expand All @@ -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,
Expand Down Expand Up @@ -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 */
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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;
Expand Down
1 change: 1 addition & 0 deletions arch/arm/mach-s3c64xx/crag6410.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
1 change: 1 addition & 0 deletions arch/arm/mach-s3c64xx/mach-crag6410.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,

Expand Down

0 comments on commit 7cef987

Please sign in to comment.