Commit 682e3efa authored by Arnd Bergmann's avatar Arnd Bergmann

Merge tag 'amlogic-soc' of...

Merge tag 'amlogic-soc' of git://git.kernel.org/pub/scm/linux/kernel/git/khilman/linux-amlogic into next/soc

Pull "Amlogic SoC updates for v4.15" from Kevin Hilman:

- add SMP support to Meson8/8b

* tag 'amlogic-soc' of git://git.kernel.org/pub/scm/linux/kernel/git/khilman/linux-amlogic:
  ARM: meson: enable MESON_IRQ_GPIO in Kconfig for meson8b
  ARM: meson: Add SMP bringup code for Meson8 and Meson8b
  ARM: smp_scu: allow the platform code to read the SCU CPU status
  ARM: smp_scu: add a helper for powering on a specific CPU
  dt-bindings: Amlogic: Add Meson8 and Meson8b SMP related documentation
parents 16511ee2 dea54268
Amlogic Meson8 and Meson8b power-management-unit:
-------------------------------------------------
The pmu is used to turn off and on different power domains of the SoCs
This includes the power to the CPU cores.
Required node properties:
- compatible value : depending on the SoC this should be one of:
"amlogic,meson8-pmu"
"amlogic,meson8b-pmu"
- reg : physical base address and the size of the registers window
Example:
pmu@c81000e4 {
compatible = "amlogic,meson8b-pmu", "syscon";
reg = <0xc81000e0 0x18>;
};
Amlogic Meson8 and Meson8b SRAM for smp bringup:
------------------------------------------------
Amlogic's SMP-capable SoCs use part of the sram for the bringup of the cores.
Once the core gets powered up it executes the code that is residing at a
specific location.
Therefore a reserved section sub-node has to be added to the mmio-sram
declaration.
Required sub-node properties:
- compatible : depending on the SoC this should be one of:
"amlogic,meson8-smp-sram"
"amlogic,meson8b-smp-sram"
The rest of the properties should follow the generic mmio-sram discription
found in ../../misc/sram.txt
Example:
sram: sram@d9000000 {
compatible = "mmio-sram";
reg = <0xd9000000 0x20000>;
#address-cells = <1>;
#size-cells = <1>;
ranges = <0 0xd9000000 0x20000>;
smp-sram@1ff80 {
compatible = "amlogic,meson8b-smp-sram";
reg = <0x1ff80 0x8>;
};
};
...@@ -197,6 +197,8 @@ described below. ...@@ -197,6 +197,8 @@ described below.
"actions,s500-smp" "actions,s500-smp"
"allwinner,sun6i-a31" "allwinner,sun6i-a31"
"allwinner,sun8i-a23" "allwinner,sun8i-a23"
"amlogic,meson8-smp"
"amlogic,meson8b-smp"
"arm,realview-smp" "arm,realview-smp"
"brcm,bcm11351-cpu-method" "brcm,bcm11351-cpu-method"
"brcm,bcm23550" "brcm,bcm23550"
......
...@@ -147,6 +147,7 @@ textofs-$(CONFIG_SA1111) := 0x00208000 ...@@ -147,6 +147,7 @@ textofs-$(CONFIG_SA1111) := 0x00208000
endif endif
textofs-$(CONFIG_ARCH_MSM8X60) := 0x00208000 textofs-$(CONFIG_ARCH_MSM8X60) := 0x00208000
textofs-$(CONFIG_ARCH_MSM8960) := 0x00208000 textofs-$(CONFIG_ARCH_MSM8960) := 0x00208000
textofs-$(CONFIG_ARCH_MESON) := 0x00208000
textofs-$(CONFIG_ARCH_AXXIA) := 0x00308000 textofs-$(CONFIG_ARCH_AXXIA) := 0x00308000
# Machine directory name. This list is sorted alphanumerically # Machine directory name. This list is sorted alphanumerically
......
...@@ -27,6 +27,8 @@ static inline unsigned long scu_a9_get_base(void) ...@@ -27,6 +27,8 @@ static inline unsigned long scu_a9_get_base(void)
#ifdef CONFIG_HAVE_ARM_SCU #ifdef CONFIG_HAVE_ARM_SCU
unsigned int scu_get_core_count(void __iomem *); unsigned int scu_get_core_count(void __iomem *);
int scu_power_mode(void __iomem *, unsigned int); int scu_power_mode(void __iomem *, unsigned int);
int scu_cpu_power_enable(void __iomem *, unsigned int);
int scu_get_cpu_power_mode(void __iomem *scu_base, unsigned int logical_cpu);
#else #else
static inline unsigned int scu_get_core_count(void __iomem *scu_base) static inline unsigned int scu_get_core_count(void __iomem *scu_base)
{ {
...@@ -36,6 +38,16 @@ static inline int scu_power_mode(void __iomem *scu_base, unsigned int mode) ...@@ -36,6 +38,16 @@ static inline int scu_power_mode(void __iomem *scu_base, unsigned int mode)
{ {
return -EINVAL; return -EINVAL;
} }
static inline int scu_cpu_power_enable(void __iomem *scu_base,
unsigned int mode)
{
return -EINVAL;
}
static inline int scu_get_cpu_power_mode(void __iomem *scu_base,
unsigned int logical_cpu)
{
return -EINVAL;
}
#endif #endif
#if defined(CONFIG_SMP) && defined(CONFIG_HAVE_ARM_SCU) #if defined(CONFIG_SMP) && defined(CONFIG_HAVE_ARM_SCU)
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#define SCU_STANDBY_ENABLE (1 << 5) #define SCU_STANDBY_ENABLE (1 << 5)
#define SCU_CONFIG 0x04 #define SCU_CONFIG 0x04
#define SCU_CPU_STATUS 0x08 #define SCU_CPU_STATUS 0x08
#define SCU_CPU_STATUS_MASK GENMASK(1, 0)
#define SCU_INVALIDATE 0x0c #define SCU_INVALIDATE 0x0c
#define SCU_FPGA_REVISION 0x10 #define SCU_FPGA_REVISION 0x10
...@@ -72,6 +73,24 @@ void scu_enable(void __iomem *scu_base) ...@@ -72,6 +73,24 @@ void scu_enable(void __iomem *scu_base)
} }
#endif #endif
static int scu_set_power_mode_internal(void __iomem *scu_base,
unsigned int logical_cpu,
unsigned int mode)
{
unsigned int val;
int cpu = MPIDR_AFFINITY_LEVEL(cpu_logical_map(logical_cpu), 0);
if (mode > 3 || mode == 1 || cpu > 3)
return -EINVAL;
val = readb_relaxed(scu_base + SCU_CPU_STATUS + cpu);
val &= ~SCU_CPU_STATUS_MASK;
val |= mode;
writeb_relaxed(val, scu_base + SCU_CPU_STATUS + cpu);
return 0;
}
/* /*
* Set the executing CPUs power mode as defined. This will be in * Set the executing CPUs power mode as defined. This will be in
* preparation for it executing a WFI instruction. * preparation for it executing a WFI instruction.
...@@ -81,16 +100,28 @@ void scu_enable(void __iomem *scu_base) ...@@ -81,16 +100,28 @@ void scu_enable(void __iomem *scu_base)
* flushed. Interrupts must also have been disabled. * flushed. Interrupts must also have been disabled.
*/ */
int scu_power_mode(void __iomem *scu_base, unsigned int mode) int scu_power_mode(void __iomem *scu_base, unsigned int mode)
{
return scu_set_power_mode_internal(scu_base, smp_processor_id(), mode);
}
/*
* Set the given (logical) CPU's power mode to SCU_PM_NORMAL.
*/
int scu_cpu_power_enable(void __iomem *scu_base, unsigned int cpu)
{
return scu_set_power_mode_internal(scu_base, cpu, SCU_PM_NORMAL);
}
int scu_get_cpu_power_mode(void __iomem *scu_base, unsigned int logical_cpu)
{ {
unsigned int val; unsigned int val;
int cpu = MPIDR_AFFINITY_LEVEL(cpu_logical_map(smp_processor_id()), 0); int cpu = MPIDR_AFFINITY_LEVEL(cpu_logical_map(logical_cpu), 0);
if (mode > 3 || mode == 1 || cpu > 3) if (cpu > 3)
return -EINVAL; return -EINVAL;
val = readb_relaxed(scu_base + SCU_CPU_STATUS + cpu) & ~0x03; val = readb_relaxed(scu_base + SCU_CPU_STATUS + cpu);
val |= mode; val &= SCU_CPU_STATUS_MASK;
writeb_relaxed(val, scu_base + SCU_CPU_STATUS + cpu);
return 0; return val;
} }
...@@ -9,6 +9,7 @@ menuconfig ARCH_MESON ...@@ -9,6 +9,7 @@ menuconfig ARCH_MESON
select PINCTRL_MESON select PINCTRL_MESON
select COMMON_CLK select COMMON_CLK
select COMMON_CLK_AMLOGIC select COMMON_CLK_AMLOGIC
select HAVE_ARM_SCU if SMP
if ARCH_MESON if ARCH_MESON
...@@ -28,5 +29,6 @@ config MACH_MESON8B ...@@ -28,5 +29,6 @@ config MACH_MESON8B
default ARCH_MESON default ARCH_MESON
select MESON6_TIMER select MESON6_TIMER
select COMMON_CLK_MESON8B select COMMON_CLK_MESON8B
select MESON_IRQ_GPIO
endif endif
obj-$(CONFIG_ARCH_MESON) += meson.o obj-$(CONFIG_ARCH_MESON) += meson.o
obj-$(CONFIG_SMP) += platsmp.o
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment