Merge tag 'soc-for-3.17' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
Pull ARM SoC platform changes from Olof Johansson: "This is the bulk of new SoC enablement and other platform changes for 3.17: - Samsung S5PV210 has been converted to DT and multiplatform - Clock drivers and bindings for some of the lower-end i.MX 1/2 platforms - Kirkwood, one of the popular Marvell platforms, is folded into the mvebu platform code, removing mach-kirkwood - Hwmod data for TI AM43xx and DRA7 platforms - More additions of Renesas shmobile platform support - Removal of plat-samsung contents that can be removed with S5PV210 being multiplatform/DT-enabled and the other two old platforms being removed New platforms (most with only basic support right now): - Hisilicon X5HD2 settop box chipset is introduced - Mediatek MT6589 (mobile chipset) is introduced - Broadcom BCM7xxx settop box chipset is introduced + as usual a lot other pieces all over the platform code" * tag 'soc-for-3.17' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc: (240 commits) ARM: hisi: remove smp from machine descriptor power: reset: move hisilicon reboot code ARM: dts: Add hix5hd2-dkb dts file. ARM: debug: Rename Hi3716 to HIX5HD2 ARM: hisi: enable hix5hd2 SoC ARM: hisi: add ARCH_HISI MAINTAINERS: add entry for Broadcom ARM STB architecture ARM: brcmstb: select GISB arbiter and interrupt drivers ARM: brcmstb: add infrastructure for ARM-based Broadcom STB SoCs ARM: configs: enable SMP in bcm_defconfig ARM: add SMP support for Broadcom mobile SoCs Documentation: arm: misc updates to Marvell EBU SoC status Documentation: arm: add URLs to public datasheets for the Marvell Armada XP SoC ARM: mvebu: fix build without platforms selected ARM: mvebu: add cpuidle support for Armada 38x ARM: mvebu: add cpuidle support for Armada 370 cpuidle: mvebu: add Armada 38x support cpuidle: mvebu: add Armada 370 support cpuidle: mvebu: rename the driver from armada-370-xp to mvebu-v7 ARM: mvebu: export the SCU address ...
This commit is contained in:
@@ -26,6 +26,10 @@
|
||||
#define EXYNOS5420_CPUS_PER_CLUSTER 4
|
||||
#define EXYNOS5420_NR_CLUSTERS 2
|
||||
|
||||
#define EXYNOS5420_ENABLE_AUTOMATIC_CORE_DOWN BIT(9)
|
||||
#define EXYNOS5420_USE_ARM_CORE_DOWN_STATE BIT(29)
|
||||
#define EXYNOS5420_USE_L2_COMMON_UP_STATE BIT(30)
|
||||
|
||||
/*
|
||||
* The common v7_exit_coherency_flush API could not be used because of the
|
||||
* Erratum 799270 workaround. This macro is the same as the common one (in
|
||||
@@ -51,7 +55,7 @@
|
||||
"dsb\n\t" \
|
||||
"ldmfd sp!, {fp, ip}" \
|
||||
: \
|
||||
: "Ir" (S5P_INFORM0) \
|
||||
: "Ir" (pmu_base_addr + S5P_INFORM0) \
|
||||
: "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", \
|
||||
"r9", "r10", "lr", "memory")
|
||||
|
||||
@@ -73,36 +77,9 @@ cpu_use_count[EXYNOS5420_CPUS_PER_CLUSTER][EXYNOS5420_NR_CLUSTERS];
|
||||
|
||||
#define exynos_cluster_unused(cluster) !exynos_cluster_usecnt(cluster)
|
||||
|
||||
static int exynos_cluster_power_control(unsigned int cluster, int enable)
|
||||
{
|
||||
unsigned int tries = 100;
|
||||
unsigned int val;
|
||||
|
||||
if (enable) {
|
||||
exynos_cluster_power_up(cluster);
|
||||
val = S5P_CORE_LOCAL_PWR_EN;
|
||||
} else {
|
||||
exynos_cluster_power_down(cluster);
|
||||
val = 0;
|
||||
}
|
||||
|
||||
/* Wait until cluster power control is applied */
|
||||
while (tries--) {
|
||||
if (exynos_cluster_power_state(cluster) == val)
|
||||
return 0;
|
||||
|
||||
cpu_relax();
|
||||
}
|
||||
pr_debug("timed out waiting for cluster %u to power %s\n", cluster,
|
||||
enable ? "on" : "off");
|
||||
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
static int exynos_power_up(unsigned int cpu, unsigned int cluster)
|
||||
{
|
||||
unsigned int cpunr = cpu + (cluster * EXYNOS5420_CPUS_PER_CLUSTER);
|
||||
int err = 0;
|
||||
|
||||
pr_debug("%s: cpu %u cluster %u\n", __func__, cpu, cluster);
|
||||
if (cpu >= EXYNOS5420_CPUS_PER_CLUSTER ||
|
||||
@@ -126,12 +103,9 @@ static int exynos_power_up(unsigned int cpu, unsigned int cluster)
|
||||
* cores.
|
||||
*/
|
||||
if (was_cluster_down)
|
||||
err = exynos_cluster_power_control(cluster, 1);
|
||||
exynos_cluster_power_up(cluster);
|
||||
|
||||
if (!err)
|
||||
exynos_cpu_power_up(cpunr);
|
||||
else
|
||||
exynos_cluster_power_control(cluster, 0);
|
||||
exynos_cpu_power_up(cpunr);
|
||||
} else if (cpu_use_count[cpu][cluster] != 2) {
|
||||
/*
|
||||
* The only possible values are:
|
||||
@@ -147,7 +121,7 @@ static int exynos_power_up(unsigned int cpu, unsigned int cluster)
|
||||
arch_spin_unlock(&exynos_mcpm_lock);
|
||||
local_irq_enable();
|
||||
|
||||
return err;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -178,9 +152,10 @@ static void exynos_power_down(void)
|
||||
if (cpu_use_count[cpu][cluster] == 0) {
|
||||
exynos_cpu_power_down(cpunr);
|
||||
|
||||
if (exynos_cluster_unused(cluster))
|
||||
/* TODO: Turn off the cluster here to save power. */
|
||||
if (exynos_cluster_unused(cluster)) {
|
||||
exynos_cluster_power_down(cluster);
|
||||
last_man = true;
|
||||
}
|
||||
} else if (cpu_use_count[cpu][cluster] == 1) {
|
||||
/*
|
||||
* A power_up request went ahead of us.
|
||||
@@ -257,10 +232,46 @@ static int exynos_wait_for_powerdown(unsigned int cpu, unsigned int cluster)
|
||||
return -ETIMEDOUT; /* timeout */
|
||||
}
|
||||
|
||||
static void exynos_powered_up(void)
|
||||
{
|
||||
unsigned int mpidr, cpu, cluster;
|
||||
|
||||
mpidr = read_cpuid_mpidr();
|
||||
cpu = MPIDR_AFFINITY_LEVEL(mpidr, 0);
|
||||
cluster = MPIDR_AFFINITY_LEVEL(mpidr, 1);
|
||||
|
||||
arch_spin_lock(&exynos_mcpm_lock);
|
||||
if (cpu_use_count[cpu][cluster] == 0)
|
||||
cpu_use_count[cpu][cluster] = 1;
|
||||
arch_spin_unlock(&exynos_mcpm_lock);
|
||||
}
|
||||
|
||||
static void exynos_suspend(u64 residency)
|
||||
{
|
||||
unsigned int mpidr, cpunr;
|
||||
|
||||
exynos_power_down();
|
||||
|
||||
/*
|
||||
* Execution reaches here only if cpu did not power down.
|
||||
* Hence roll back the changes done in exynos_power_down function.
|
||||
*
|
||||
* CAUTION: "This function requires the stack data to be visible through
|
||||
* power down and can only be executed on processors like A15 and A7
|
||||
* that hit the cache with the C bit clear in the SCTLR register."
|
||||
*/
|
||||
mpidr = read_cpuid_mpidr();
|
||||
cpunr = exynos_pmu_cpunr(mpidr);
|
||||
|
||||
exynos_cpu_power_up(cpunr);
|
||||
}
|
||||
|
||||
static const struct mcpm_platform_ops exynos_power_ops = {
|
||||
.power_up = exynos_power_up,
|
||||
.power_down = exynos_power_down,
|
||||
.wait_for_powerdown = exynos_wait_for_powerdown,
|
||||
.suspend = exynos_suspend,
|
||||
.powered_up = exynos_powered_up,
|
||||
};
|
||||
|
||||
static void __init exynos_mcpm_usage_count_init(void)
|
||||
@@ -312,6 +323,7 @@ static int __init exynos_mcpm_init(void)
|
||||
{
|
||||
struct device_node *node;
|
||||
void __iomem *ns_sram_base_addr;
|
||||
unsigned int value, i;
|
||||
int ret;
|
||||
|
||||
node = of_find_matching_node(NULL, exynos_dt_mcpm_match);
|
||||
@@ -338,7 +350,7 @@ static int __init exynos_mcpm_init(void)
|
||||
* To increase the stability of KFC reset we need to program
|
||||
* the PMU SPARE3 register
|
||||
*/
|
||||
__raw_writel(EXYNOS5420_SWRESET_KFC_SEL, S5P_PMU_SPARE3);
|
||||
pmu_raw_writel(EXYNOS5420_SWRESET_KFC_SEL, S5P_PMU_SPARE3);
|
||||
|
||||
exynos_mcpm_usage_count_init();
|
||||
|
||||
@@ -356,6 +368,26 @@ static int __init exynos_mcpm_init(void)
|
||||
|
||||
pr_info("Exynos MCPM support installed\n");
|
||||
|
||||
/*
|
||||
* On Exynos5420/5800 for the A15 and A7 clusters:
|
||||
*
|
||||
* EXYNOS5420_ENABLE_AUTOMATIC_CORE_DOWN ensures that all the cores
|
||||
* in a cluster are turned off before turning off the cluster L2.
|
||||
*
|
||||
* EXYNOS5420_USE_ARM_CORE_DOWN_STATE ensures that a cores is powered
|
||||
* off before waking it up.
|
||||
*
|
||||
* EXYNOS5420_USE_L2_COMMON_UP_STATE ensures that cluster L2 will be
|
||||
* turned on before the first man is powered up.
|
||||
*/
|
||||
for (i = 0; i < EXYNOS5420_NR_CLUSTERS; i++) {
|
||||
value = pmu_raw_readl(EXYNOS_COMMON_OPTION(i));
|
||||
value |= EXYNOS5420_ENABLE_AUTOMATIC_CORE_DOWN |
|
||||
EXYNOS5420_USE_ARM_CORE_DOWN_STATE |
|
||||
EXYNOS5420_USE_L2_COMMON_UP_STATE;
|
||||
pmu_raw_writel(value, EXYNOS_COMMON_OPTION(i));
|
||||
}
|
||||
|
||||
/*
|
||||
* U-Boot SPL is hardcoded to jump to the start of ns_sram_base_addr
|
||||
* as part of secondary_cpu_start(). Let's redirect it to the
|
||||
|
Reference in New Issue
Block a user