Qualcomm ARM Based SoC Updates for v3.15
* Add support for determining smp ops based on device tree. * Add DT binding specs for Krait/Scorpion enable method * Add DT binding specs for various Krait Processor controller complexes * Add SoC SMP support for Krait Processor Subsystem v1 & v2 -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.10 (GNU/Linux) Comment: GPGTools - https://gpgtools.org iQIbBAABCgAGBQJS+pFkAAoJEF9hYXeAcXzBnzsP+LCQcfVV35/b0RnZpbTVjQhj 2Zr6Z2sbAV2nKN7ifUSZPTd19X9NBoa7ZACOoX0WYQzj9xLBkH+70ke/zECc6Kli uIYfeKeKcPVyrTFA9kb4qXNrfdqTa/urjzQy/zb65yo1omkNdYoTDphylnMslMXj 6+cCc1eMJmV/aOrjLLFVW88OjlDCdJD3x4CyS8ttj3j+uuUPJ/NJsy4E2NzURm8p AS8fzTHWU+Yus8NRX1DpMCbJWWdS6K6m8Gv9lpeweCQsK1GtwKzZLg5jFka3w5G2 YnV6bHQHtwMsR9SikHFv79gVj+pJLw0Cv0xcgPc0bmLBioCs8a120TSonKkw5PE/ 3ezCUtS3o3Cs6AWBx8keokEphj/gogHIH4MVtILsxB9XEAoZ+oGYz5dvqIQXZtG7 GdPehP7g3c0kxtjfCUQG9czF2AUWA6BRO3eUOq1d8Vdzj++D0KbGF/3hFyg0ppcj LbbxAvVQYCQ/ag0W3jgf3KzjfzPSvmHlaIV/IhTcBLg4O1/WedBGiu4EWp2231aw uXg2Y9UP5m42p/qlZyIoFIk1A5KupDBuAskKd7uqjw7Pu7ukccBfOy9tJ9Eej4WP 6tgTfc7oeRjmqzCXx5vdHwljgwFB4XgFqqnJG1L4452yDgMGR+it9M5i40RzJe8e Ndx4cuELlGrrpdXDQX4= =R5RP -----END PGP SIGNATURE----- Merge tag 'qcom-soc-for-3.15' of git://git.kernel.org/pub/scm/linux/kernel/git/galak/linux-qcom into next/soc Merge "Qualcomm ARM Based SoC Updates for v3.15" from Kumar Gala: * Add support for determining smp ops based on device tree. * Add DT binding specs for Krait/Scorpion enable method * Add DT binding specs for various Krait Processor controller complexes * Add SoC SMP support for Krait Processor Subsystem v1 & v2 * tag 'qcom-soc-for-3.15' of git://git.kernel.org/pub/scm/linux/kernel/git/galak/linux-qcom: ARM: qcom: Add SMP support for KPSSv2 ARM: qcom: Add SMP support for KPSSv1 devicetree: bindings: Document qcom,saw2 node devicetree: bindings: Document qcom,kpss-acc devicetree: bindings: Document Krait/Scorpion cpus and enable-method ARM: qcom: Re-organize platsmp to make it extensible ARM: Introduce CPU_METHOD_OF_DECLARE() for cpu hotplug/smp ARM: qcom: Rename various msm prefixed functions to qcom clocksource: qcom: split building of legacy vs multiplatform support ARM: qcom: Split Qualcomm support into legacy and multiplatform clocksource: qcom: Move clocksource code out of mach-msm ARM: msm: kill off hotplug.c ARM: msm: Remove pen_release usage ARM: dts: msm: split out msm8660 and msm8960 soc into dts include Signed-off-by: Olof Johansson <olof@lixom.net>
This commit is contained in:
Коммит
567acf8e17
|
@ -180,7 +180,11 @@ nodes to be present and contain the properties described below.
|
|||
be one of:
|
||||
"spin-table"
|
||||
"psci"
|
||||
# On ARM 32-bit systems this property is optional.
|
||||
# On ARM 32-bit systems this property is optional and
|
||||
can be one of:
|
||||
"qcom,gcc-msm8660"
|
||||
"qcom,kpss-acc-v1"
|
||||
"qcom,kpss-acc-v2"
|
||||
|
||||
- cpu-release-addr
|
||||
Usage: required for systems that have an "enable-method"
|
||||
|
@ -191,6 +195,21 @@ nodes to be present and contain the properties described below.
|
|||
property identifying a 64-bit zero-initialised
|
||||
memory location.
|
||||
|
||||
- qcom,saw
|
||||
Usage: required for systems that have an "enable-method"
|
||||
property value of "qcom,kpss-acc-v1" or
|
||||
"qcom,kpss-acc-v2"
|
||||
Value type: <phandle>
|
||||
Definition: Specifies the SAW[1] node associated with this CPU.
|
||||
|
||||
- qcom,acc
|
||||
Usage: required for systems that have an "enable-method"
|
||||
property value of "qcom,kpss-acc-v1" or
|
||||
"qcom,kpss-acc-v2"
|
||||
Value type: <phandle>
|
||||
Definition: Specifies the ACC[2] node associated with this CPU.
|
||||
|
||||
|
||||
Example 1 (dual-cluster big.LITTLE system 32-bit):
|
||||
|
||||
cpus {
|
||||
|
@ -382,3 +401,7 @@ cpus {
|
|||
cpu-release-addr = <0 0x20000000>;
|
||||
};
|
||||
};
|
||||
|
||||
--
|
||||
[1] arm/msm/qcom,saw2.txt
|
||||
[2] arm/msm/qcom,kpss-acc.txt
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
Krait Processor Sub-system (KPSS) Application Clock Controller (ACC)
|
||||
|
||||
The KPSS ACC provides clock, power domain, and reset control to a Krait CPU.
|
||||
There is one ACC register region per CPU within the KPSS remapped region as
|
||||
well as an alias register region that remaps accesses to the ACC associated
|
||||
with the CPU accessing the region.
|
||||
|
||||
PROPERTIES
|
||||
|
||||
- compatible:
|
||||
Usage: required
|
||||
Value type: <string>
|
||||
Definition: should be one of:
|
||||
"qcom,kpss-acc-v1"
|
||||
"qcom,kpss-acc-v2"
|
||||
|
||||
- reg:
|
||||
Usage: required
|
||||
Value type: <prop-encoded-array>
|
||||
Definition: the first element specifies the base address and size of
|
||||
the register region. An optional second element specifies
|
||||
the base address and size of the alias register region.
|
||||
|
||||
Example:
|
||||
|
||||
clock-controller@2088000 {
|
||||
compatible = "qcom,kpss-acc-v2";
|
||||
reg = <0x02088000 0x1000>,
|
||||
<0x02008000 0x1000>;
|
||||
};
|
|
@ -0,0 +1,35 @@
|
|||
SPM AVS Wrapper 2 (SAW2)
|
||||
|
||||
The SAW2 is a wrapper around the Subsystem Power Manager (SPM) and the
|
||||
Adaptive Voltage Scaling (AVS) hardware. The SPM is a programmable
|
||||
micro-controller that transitions a piece of hardware (like a processor or
|
||||
subsystem) into and out of low power modes via a direct connection to
|
||||
the PMIC. It can also be wired up to interact with other processors in the
|
||||
system, notifying them when a low power state is entered or exited.
|
||||
|
||||
PROPERTIES
|
||||
|
||||
- compatible:
|
||||
Usage: required
|
||||
Value type: <string>
|
||||
Definition: shall contain "qcom,saw2". A more specific value should be
|
||||
one of:
|
||||
"qcom,saw2-v1"
|
||||
"qcom,saw2-v1.1"
|
||||
"qcom,saw2-v2"
|
||||
"qcom,saw2-v2.1"
|
||||
|
||||
- reg:
|
||||
Usage: required
|
||||
Value type: <prop-encoded-array>
|
||||
Definition: the first element specifies the base address and size of
|
||||
the register region. An optional second element specifies
|
||||
the base address and size of the alias register region.
|
||||
|
||||
|
||||
Example:
|
||||
|
||||
regulator@2099000 {
|
||||
compatible = "qcom,saw2";
|
||||
reg = <0x02099000 0x1000>, <0x02009000 0x1000>;
|
||||
};
|
|
@ -1167,6 +1167,14 @@ L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
|
|||
W: http://www.arm.linux.org.uk/
|
||||
S: Maintained
|
||||
|
||||
ARM/QUALCOMM SUPPORT
|
||||
M: Kumar Gala <galak@codeaurora.org>
|
||||
M: David Brown <davidb@codeaurora.org>
|
||||
L: linux-arm-msm@vger.kernel.org
|
||||
S: Maintained
|
||||
F: arch/arm/mach-qcom/
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/galak/linux-qcom.git
|
||||
|
||||
ARM/RADISYS ENP2611 MACHINE SUPPORT
|
||||
M: Lennert Buytenhek <kernel@wantstofly.org>
|
||||
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
|
||||
|
|
|
@ -657,9 +657,8 @@ config ARCH_PXA
|
|||
help
|
||||
Support for Intel/Marvell's PXA2xx/PXA3xx processor line.
|
||||
|
||||
config ARCH_MSM_NODT
|
||||
bool "Qualcomm MSM"
|
||||
select ARCH_MSM
|
||||
config ARCH_MSM
|
||||
bool "Qualcomm MSM (non-multiplatform)"
|
||||
select ARCH_REQUIRE_GPIOLIB
|
||||
select COMMON_CLK
|
||||
select GENERIC_CLOCKEVENTS
|
||||
|
@ -1005,6 +1004,8 @@ source "arch/arm/plat-pxa/Kconfig"
|
|||
|
||||
source "arch/arm/mach-mmp/Kconfig"
|
||||
|
||||
source "arch/arm/mach-qcom/Kconfig"
|
||||
|
||||
source "arch/arm/mach-realview/Kconfig"
|
||||
|
||||
source "arch/arm/mach-rockchip/Kconfig"
|
||||
|
|
|
@ -956,7 +956,7 @@ config DEBUG_STI_UART
|
|||
|
||||
config DEBUG_MSM_UART
|
||||
bool
|
||||
depends on ARCH_MSM
|
||||
depends on ARCH_MSM || ARCH_QCOM
|
||||
|
||||
config DEBUG_LL_INCLUDE
|
||||
string
|
||||
|
|
|
@ -180,6 +180,7 @@ machine-$(CONFIG_ARCH_OMAP2PLUS) += omap2
|
|||
machine-$(CONFIG_ARCH_ORION5X) += orion5x
|
||||
machine-$(CONFIG_ARCH_PICOXCELL) += picoxcell
|
||||
machine-$(CONFIG_ARCH_PXA) += pxa
|
||||
machine-$(CONFIG_ARCH_QCOM) += qcom
|
||||
machine-$(CONFIG_ARCH_REALVIEW) += realview
|
||||
machine-$(CONFIG_ARCH_ROCKCHIP) += rockchip
|
||||
machine-$(CONFIG_ARCH_RPC) += rpc
|
||||
|
|
|
@ -119,9 +119,6 @@ dtb-$(CONFIG_ARCH_KIRKWOOD) += kirkwood-cloudbox.dtb \
|
|||
kirkwood-ts219-6282.dtb
|
||||
dtb-$(CONFIG_ARCH_MARCO) += marco-evb.dtb
|
||||
dtb-$(CONFIG_ARCH_MOXART) += moxart-uc7112lx.dtb
|
||||
dtb-$(CONFIG_ARCH_MSM) += qcom-msm8660-surf.dtb \
|
||||
qcom-msm8960-cdp.dtb \
|
||||
qcom-apq8074-dragonboard.dtb
|
||||
dtb-$(CONFIG_ARCH_MVEBU) += armada-370-db.dtb \
|
||||
armada-370-mirabox.dtb \
|
||||
armada-370-netgear-rn102.dtb \
|
||||
|
@ -233,6 +230,9 @@ dtb-$(CONFIG_ARCH_OMAP2PLUS) += omap2420-h4.dtb \
|
|||
dra7-evm.dtb
|
||||
dtb-$(CONFIG_ARCH_ORION5X) += orion5x-lacie-ethernet-disk-mini-v2.dtb
|
||||
dtb-$(CONFIG_ARCH_PRIMA2) += prima2-evb.dtb
|
||||
dtb-$(CONFIG_ARCH_QCOM) += qcom-msm8660-surf.dtb \
|
||||
qcom-msm8960-cdp.dtb \
|
||||
qcom-apq8074-dragonboard.dtb
|
||||
dtb-$(CONFIG_ARCH_U8500) += ste-snowball.dtb \
|
||||
ste-hrefprev60-stuib.dtb \
|
||||
ste-hrefprev60-tvk.dtb \
|
||||
|
|
|
@ -1,63 +1,6 @@
|
|||
/dts-v1/;
|
||||
|
||||
/include/ "skeleton.dtsi"
|
||||
|
||||
#include <dt-bindings/clock/qcom,gcc-msm8660.h>
|
||||
#include "qcom-msm8660.dtsi"
|
||||
|
||||
/ {
|
||||
model = "Qualcomm MSM8660 SURF";
|
||||
compatible = "qcom,msm8660-surf", "qcom,msm8660";
|
||||
interrupt-parent = <&intc>;
|
||||
|
||||
intc: interrupt-controller@2080000 {
|
||||
compatible = "qcom,msm-8660-qgic";
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <3>;
|
||||
reg = < 0x02080000 0x1000 >,
|
||||
< 0x02081000 0x1000 >;
|
||||
};
|
||||
|
||||
timer@2000000 {
|
||||
compatible = "qcom,scss-timer", "qcom,msm-timer";
|
||||
interrupts = <1 0 0x301>,
|
||||
<1 1 0x301>,
|
||||
<1 2 0x301>;
|
||||
reg = <0x02000000 0x100>;
|
||||
clock-frequency = <27000000>,
|
||||
<32768>;
|
||||
cpu-offset = <0x40000>;
|
||||
};
|
||||
|
||||
msmgpio: gpio@800000 {
|
||||
compatible = "qcom,msm-gpio";
|
||||
reg = <0x00800000 0x4000>;
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
ngpio = <173>;
|
||||
interrupts = <0 16 0x4>;
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
|
||||
gcc: clock-controller@900000 {
|
||||
compatible = "qcom,gcc-msm8660";
|
||||
#clock-cells = <1>;
|
||||
#reset-cells = <1>;
|
||||
reg = <0x900000 0x4000>;
|
||||
};
|
||||
|
||||
serial@19c40000 {
|
||||
compatible = "qcom,msm-uartdm-v1.3", "qcom,msm-uartdm";
|
||||
reg = <0x19c40000 0x1000>,
|
||||
<0x19c00000 0x1000>;
|
||||
interrupts = <0 195 0x0>;
|
||||
clocks = <&gcc GSBI12_UART_CLK>, <&gcc GSBI12_H_CLK>;
|
||||
clock-names = "core", "iface";
|
||||
};
|
||||
|
||||
qcom,ssbi@500000 {
|
||||
compatible = "qcom,ssbi";
|
||||
reg = <0x500000 0x1000>;
|
||||
qcom,controller-type = "pmic-arbiter";
|
||||
};
|
||||
};
|
||||
|
|
|
@ -0,0 +1,63 @@
|
|||
/dts-v1/;
|
||||
|
||||
/include/ "skeleton.dtsi"
|
||||
|
||||
#include <dt-bindings/clock/qcom,gcc-msm8660.h>
|
||||
|
||||
/ {
|
||||
model = "Qualcomm MSM8660";
|
||||
compatible = "qcom,msm8660";
|
||||
interrupt-parent = <&intc>;
|
||||
|
||||
intc: interrupt-controller@2080000 {
|
||||
compatible = "qcom,msm-8660-qgic";
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <3>;
|
||||
reg = < 0x02080000 0x1000 >,
|
||||
< 0x02081000 0x1000 >;
|
||||
};
|
||||
|
||||
timer@2000000 {
|
||||
compatible = "qcom,scss-timer", "qcom,msm-timer";
|
||||
interrupts = <1 0 0x301>,
|
||||
<1 1 0x301>,
|
||||
<1 2 0x301>;
|
||||
reg = <0x02000000 0x100>;
|
||||
clock-frequency = <27000000>,
|
||||
<32768>;
|
||||
cpu-offset = <0x40000>;
|
||||
};
|
||||
|
||||
msmgpio: gpio@800000 {
|
||||
compatible = "qcom,msm-gpio";
|
||||
reg = <0x00800000 0x4000>;
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
ngpio = <173>;
|
||||
interrupts = <0 16 0x4>;
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
|
||||
gcc: clock-controller@900000 {
|
||||
compatible = "qcom,gcc-msm8660";
|
||||
#clock-cells = <1>;
|
||||
#reset-cells = <1>;
|
||||
reg = <0x900000 0x4000>;
|
||||
};
|
||||
|
||||
serial@19c40000 {
|
||||
compatible = "qcom,msm-uartdm-v1.3", "qcom,msm-uartdm";
|
||||
reg = <0x19c40000 0x1000>,
|
||||
<0x19c00000 0x1000>;
|
||||
interrupts = <0 195 0x0>;
|
||||
clocks = <&gcc GSBI12_UART_CLK>, <&gcc GSBI12_H_CLK>;
|
||||
clock-names = "core", "iface";
|
||||
};
|
||||
|
||||
qcom,ssbi@500000 {
|
||||
compatible = "qcom,ssbi";
|
||||
reg = <0x500000 0x1000>;
|
||||
qcom,controller-type = "pmic-arbiter";
|
||||
};
|
||||
};
|
|
@ -1,70 +1,6 @@
|
|||
/dts-v1/;
|
||||
|
||||
/include/ "skeleton.dtsi"
|
||||
|
||||
#include <dt-bindings/clock/qcom,gcc-msm8960.h>
|
||||
#include "qcom-msm8960.dtsi"
|
||||
|
||||
/ {
|
||||
model = "Qualcomm MSM8960 CDP";
|
||||
compatible = "qcom,msm8960-cdp", "qcom,msm8960";
|
||||
interrupt-parent = <&intc>;
|
||||
|
||||
intc: interrupt-controller@2000000 {
|
||||
compatible = "qcom,msm-qgic2";
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <3>;
|
||||
reg = < 0x02000000 0x1000 >,
|
||||
< 0x02002000 0x1000 >;
|
||||
};
|
||||
|
||||
timer@200a000 {
|
||||
compatible = "qcom,kpss-timer", "qcom,msm-timer";
|
||||
interrupts = <1 1 0x301>,
|
||||
<1 2 0x301>,
|
||||
<1 3 0x301>;
|
||||
reg = <0x0200a000 0x100>;
|
||||
clock-frequency = <27000000>,
|
||||
<32768>;
|
||||
cpu-offset = <0x80000>;
|
||||
};
|
||||
|
||||
msmgpio: gpio@800000 {
|
||||
compatible = "qcom,msm-gpio";
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
ngpio = <150>;
|
||||
interrupts = <0 16 0x4>;
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
reg = <0x800000 0x4000>;
|
||||
};
|
||||
|
||||
gcc: clock-controller@900000 {
|
||||
compatible = "qcom,gcc-msm8960";
|
||||
#clock-cells = <1>;
|
||||
#reset-cells = <1>;
|
||||
reg = <0x900000 0x4000>;
|
||||
};
|
||||
|
||||
clock-controller@4000000 {
|
||||
compatible = "qcom,mmcc-msm8960";
|
||||
reg = <0x4000000 0x1000>;
|
||||
#clock-cells = <1>;
|
||||
#reset-cells = <1>;
|
||||
};
|
||||
|
||||
serial@16440000 {
|
||||
compatible = "qcom,msm-uartdm-v1.3", "qcom,msm-uartdm";
|
||||
reg = <0x16440000 0x1000>,
|
||||
<0x16400000 0x1000>;
|
||||
interrupts = <0 154 0x0>;
|
||||
clocks = <&gcc GSBI5_UART_CLK>, <&gcc GSBI5_H_CLK>;
|
||||
clock-names = "core", "iface";
|
||||
};
|
||||
|
||||
qcom,ssbi@500000 {
|
||||
compatible = "qcom,ssbi";
|
||||
reg = <0x500000 0x1000>;
|
||||
qcom,controller-type = "pmic-arbiter";
|
||||
};
|
||||
};
|
||||
|
|
|
@ -0,0 +1,70 @@
|
|||
/dts-v1/;
|
||||
|
||||
/include/ "skeleton.dtsi"
|
||||
|
||||
#include <dt-bindings/clock/qcom,gcc-msm8960.h>
|
||||
|
||||
/ {
|
||||
model = "Qualcomm MSM8960";
|
||||
compatible = "qcom,msm8960";
|
||||
interrupt-parent = <&intc>;
|
||||
|
||||
intc: interrupt-controller@2000000 {
|
||||
compatible = "qcom,msm-qgic2";
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <3>;
|
||||
reg = < 0x02000000 0x1000 >,
|
||||
< 0x02002000 0x1000 >;
|
||||
};
|
||||
|
||||
timer@200a000 {
|
||||
compatible = "qcom,kpss-timer", "qcom,msm-timer";
|
||||
interrupts = <1 1 0x301>,
|
||||
<1 2 0x301>,
|
||||
<1 3 0x301>;
|
||||
reg = <0x0200a000 0x100>;
|
||||
clock-frequency = <27000000>,
|
||||
<32768>;
|
||||
cpu-offset = <0x80000>;
|
||||
};
|
||||
|
||||
msmgpio: gpio@800000 {
|
||||
compatible = "qcom,msm-gpio";
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
ngpio = <150>;
|
||||
interrupts = <0 16 0x4>;
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
reg = <0x800000 0x4000>;
|
||||
};
|
||||
|
||||
gcc: clock-controller@900000 {
|
||||
compatible = "qcom,gcc-msm8960";
|
||||
#clock-cells = <1>;
|
||||
#reset-cells = <1>;
|
||||
reg = <0x900000 0x4000>;
|
||||
};
|
||||
|
||||
clock-controller@4000000 {
|
||||
compatible = "qcom,mmcc-msm8960";
|
||||
reg = <0x4000000 0x1000>;
|
||||
#clock-cells = <1>;
|
||||
#reset-cells = <1>;
|
||||
};
|
||||
|
||||
serial@16440000 {
|
||||
compatible = "qcom,msm-uartdm-v1.3", "qcom,msm-uartdm";
|
||||
reg = <0x16440000 0x1000>,
|
||||
<0x16400000 0x1000>;
|
||||
interrupts = <0 154 0x0>;
|
||||
clocks = <&gcc GSBI5_UART_CLK>, <&gcc GSBI5_H_CLK>;
|
||||
clock-names = "core", "iface";
|
||||
};
|
||||
|
||||
qcom,ssbi@500000 {
|
||||
compatible = "qcom,ssbi";
|
||||
reg = <0x500000 0x1000>;
|
||||
qcom,controller-type = "pmic-arbiter";
|
||||
};
|
||||
};
|
|
@ -114,6 +114,15 @@ struct smp_operations {
|
|||
#endif
|
||||
};
|
||||
|
||||
struct of_cpu_method {
|
||||
const char *method;
|
||||
struct smp_operations *ops;
|
||||
};
|
||||
|
||||
#define CPU_METHOD_OF_DECLARE(name, _method, _ops) \
|
||||
static const struct of_cpu_method __cpu_method_of_table_##name \
|
||||
__used __section(__cpu_method_of_table) \
|
||||
= { .method = _method, .ops = _ops }
|
||||
/*
|
||||
* set platform specific SMP operations
|
||||
*/
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include <linux/of_fdt.h>
|
||||
#include <linux/of_irq.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/smp.h>
|
||||
|
||||
#include <asm/cputype.h>
|
||||
#include <asm/setup.h>
|
||||
|
@ -63,6 +64,34 @@ void __init arm_dt_memblock_reserve(void)
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
extern struct of_cpu_method __cpu_method_of_table_begin[];
|
||||
extern struct of_cpu_method __cpu_method_of_table_end[];
|
||||
|
||||
static int __init set_smp_ops_by_method(struct device_node *node)
|
||||
{
|
||||
const char *method;
|
||||
struct of_cpu_method *m = __cpu_method_of_table_begin;
|
||||
|
||||
if (of_property_read_string(node, "enable-method", &method))
|
||||
return 0;
|
||||
|
||||
for (; m < __cpu_method_of_table_end; m++)
|
||||
if (!strcmp(m->method, method)) {
|
||||
smp_set_ops(m->ops);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
static inline int set_smp_ops_by_method(struct device_node *node)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* arm_dt_init_cpu_maps - Function retrieves cpu nodes from the device tree
|
||||
* and builds the cpu logical map array containing MPIDR values related to
|
||||
|
@ -79,6 +108,7 @@ void __init arm_dt_init_cpu_maps(void)
|
|||
* read as 0.
|
||||
*/
|
||||
struct device_node *cpu, *cpus;
|
||||
int found_method = 0;
|
||||
u32 i, j, cpuidx = 1;
|
||||
u32 mpidr = is_smp() ? read_cpuid_mpidr() & MPIDR_HWID_BITMASK : 0;
|
||||
|
||||
|
@ -150,8 +180,18 @@ void __init arm_dt_init_cpu_maps(void)
|
|||
}
|
||||
|
||||
tmp_map[i] = hwid;
|
||||
|
||||
if (!found_method)
|
||||
found_method = set_smp_ops_by_method(cpu);
|
||||
}
|
||||
|
||||
/*
|
||||
* Fallback to an enable-method in the cpus node if nothing found in
|
||||
* a cpu node.
|
||||
*/
|
||||
if (!found_method)
|
||||
set_smp_ops_by_method(cpus);
|
||||
|
||||
if (!bootcpu_valid) {
|
||||
pr_warn("DT missing boot CPU MPIDR[23:0], fall back to default cpu_logical_map\n");
|
||||
return;
|
||||
|
|
|
@ -1,50 +1,9 @@
|
|||
config ARCH_MSM
|
||||
bool
|
||||
|
||||
config ARCH_MSM_DT
|
||||
bool "Qualcomm MSM DT Support" if ARCH_MULTI_V7
|
||||
select ARCH_MSM
|
||||
select ARCH_REQUIRE_GPIOLIB
|
||||
select CLKSRC_OF
|
||||
select GENERIC_CLOCKEVENTS
|
||||
help
|
||||
Support for Qualcomm's devicetree based MSM systems.
|
||||
|
||||
if ARCH_MSM
|
||||
|
||||
menu "Qualcomm MSM SoC Selection"
|
||||
depends on ARCH_MSM_DT
|
||||
|
||||
config ARCH_MSM8X60
|
||||
bool "Enable support for MSM8X60"
|
||||
select ARM_GIC
|
||||
select CPU_V7
|
||||
select HAVE_SMP
|
||||
select MSM_SCM if SMP
|
||||
select MSM_TIMER
|
||||
|
||||
config ARCH_MSM8960
|
||||
bool "Enable support for MSM8960"
|
||||
select ARM_GIC
|
||||
select CPU_V7
|
||||
select HAVE_SMP
|
||||
select MSM_SCM if SMP
|
||||
select MSM_TIMER
|
||||
|
||||
config ARCH_MSM8974
|
||||
bool "Enable support for MSM8974"
|
||||
select ARM_GIC
|
||||
select CPU_V7
|
||||
select HAVE_ARM_ARCH_TIMER
|
||||
select HAVE_SMP
|
||||
select MSM_SCM if SMP
|
||||
|
||||
endmenu
|
||||
|
||||
choice
|
||||
prompt "Qualcomm MSM SoC Type"
|
||||
default ARCH_MSM7X00A
|
||||
depends on ARCH_MSM_NODT
|
||||
depends on ARCH_MSM
|
||||
|
||||
config ARCH_MSM7X00A
|
||||
bool "MSM7x00A / MSM7x01A"
|
||||
|
@ -54,7 +13,7 @@ config ARCH_MSM7X00A
|
|||
select MACH_TROUT if !MACH_HALIBUT
|
||||
select MSM_PROC_COMM
|
||||
select MSM_SMD
|
||||
select MSM_TIMER
|
||||
select CLKSRC_QCOM
|
||||
select MSM_SMD_PKG3
|
||||
|
||||
config ARCH_MSM7X30
|
||||
|
@ -66,7 +25,7 @@ config ARCH_MSM7X30
|
|||
select MSM_GPIOMUX
|
||||
select MSM_PROC_COMM
|
||||
select MSM_SMD
|
||||
select MSM_TIMER
|
||||
select CLKSRC_QCOM
|
||||
select MSM_VIC
|
||||
|
||||
config ARCH_QSD8X50
|
||||
|
@ -78,7 +37,7 @@ config ARCH_QSD8X50
|
|||
select MSM_GPIOMUX
|
||||
select MSM_PROC_COMM
|
||||
select MSM_SMD
|
||||
select MSM_TIMER
|
||||
select CLKSRC_QCOM
|
||||
select MSM_VIC
|
||||
|
||||
endchoice
|
||||
|
@ -99,7 +58,7 @@ config MSM_VIC
|
|||
bool
|
||||
|
||||
menu "Qualcomm MSM Board Type"
|
||||
depends on ARCH_MSM_NODT
|
||||
depends on ARCH_MSM
|
||||
|
||||
config MACH_HALIBUT
|
||||
depends on ARCH_MSM
|
||||
|
@ -153,7 +112,4 @@ config MSM_GPIOMUX
|
|||
config MSM_SCM
|
||||
bool
|
||||
|
||||
config MSM_TIMER
|
||||
bool
|
||||
|
||||
endif
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
obj-$(CONFIG_MSM_TIMER) += timer.o
|
||||
obj-$(CONFIG_MSM_PROC_COMM) += clock.o
|
||||
|
||||
obj-$(CONFIG_MSM_VIC) += irq-vic.o
|
||||
|
@ -14,18 +13,11 @@ obj-$(CONFIG_ARCH_QSD8X50) += dma.o io.o
|
|||
|
||||
obj-$(CONFIG_MSM_SMD) += smd.o smd_debug.o
|
||||
obj-$(CONFIG_MSM_SMD) += last_radio_log.o
|
||||
obj-$(CONFIG_MSM_SCM) += scm.o scm-boot.o
|
||||
|
||||
CFLAGS_scm.o :=$(call as-instr,.arch_extension sec,-DREQUIRES_SEC=1)
|
||||
|
||||
obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
|
||||
obj-$(CONFIG_SMP) += headsmp.o platsmp.o
|
||||
|
||||
obj-$(CONFIG_MACH_TROUT) += board-trout.o board-trout-gpio.o board-trout-mmc.o devices-msm7x00.o
|
||||
obj-$(CONFIG_MACH_TROUT) += board-trout.o board-trout-gpio.o board-trout-mmc.o board-trout-panel.o devices-msm7x00.o
|
||||
obj-$(CONFIG_MACH_HALIBUT) += board-halibut.o devices-msm7x00.o
|
||||
obj-$(CONFIG_ARCH_MSM7X30) += board-msm7x30.o devices-msm7x30.o
|
||||
obj-$(CONFIG_ARCH_QSD8X50) += board-qsd8x50.o devices-qsd8x50.o
|
||||
obj-$(CONFIG_ARCH_MSM_DT) += board-dt.o
|
||||
obj-$(CONFIG_MSM_GPIOMUX) += gpiomux.o
|
||||
obj-$(CONFIG_ARCH_QSD8X50) += gpiomux-8x50.o
|
||||
|
|
|
@ -23,9 +23,6 @@ extern void msm_map_qsd8x50_io(void);
|
|||
extern void __iomem *__msm_ioremap_caller(phys_addr_t phys_addr, size_t size,
|
||||
unsigned int mtype, void *caller);
|
||||
|
||||
extern struct smp_operations msm_smp_ops;
|
||||
extern void msm_cpu_die(unsigned int cpu);
|
||||
|
||||
struct msm_mmc_platform_data;
|
||||
|
||||
extern void msm_add_devices(void);
|
||||
|
|
|
@ -1,39 +0,0 @@
|
|||
/*
|
||||
* linux/arch/arm/mach-realview/headsmp.S
|
||||
*
|
||||
* Copyright (c) 2003 ARM Limited
|
||||
* All Rights Reserved
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
#include <linux/linkage.h>
|
||||
#include <linux/init.h>
|
||||
|
||||
/*
|
||||
* MSM specific entry point for secondary CPUs. This provides
|
||||
* a "holding pen" into which all secondary cores are held until we're
|
||||
* ready for them to initialise.
|
||||
*/
|
||||
ENTRY(msm_secondary_startup)
|
||||
mrc p15, 0, r0, c0, c0, 5
|
||||
and r0, r0, #15
|
||||
adr r4, 1f
|
||||
ldmia r4, {r5, r6}
|
||||
sub r4, r4, r5
|
||||
add r6, r6, r4
|
||||
pen: ldr r7, [r6]
|
||||
cmp r7, r0
|
||||
bne pen
|
||||
|
||||
/*
|
||||
* we've been released from the holding pen: secondary_stack
|
||||
* should now contain the SVC stack for this core
|
||||
*/
|
||||
b secondary_startup
|
||||
ENDPROC(msm_secondary_startup)
|
||||
|
||||
.align
|
||||
1: .long .
|
||||
.long pen_release
|
|
@ -1,74 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2002 ARM Ltd.
|
||||
* All Rights Reserved
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/smp.h>
|
||||
|
||||
#include <asm/smp_plat.h>
|
||||
|
||||
#include "common.h"
|
||||
|
||||
static inline void cpu_enter_lowpower(void)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void cpu_leave_lowpower(void)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void platform_do_lowpower(unsigned int cpu)
|
||||
{
|
||||
/* Just enter wfi for now. TODO: Properly shut off the cpu. */
|
||||
for (;;) {
|
||||
/*
|
||||
* here's the WFI
|
||||
*/
|
||||
asm("wfi"
|
||||
:
|
||||
:
|
||||
: "memory", "cc");
|
||||
|
||||
if (pen_release == cpu_logical_map(cpu)) {
|
||||
/*
|
||||
* OK, proper wakeup, we're done
|
||||
*/
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* getting here, means that we have come out of WFI without
|
||||
* having been woken up - this shouldn't happen
|
||||
*
|
||||
* The trouble is, letting people know about this is not really
|
||||
* possible, since we are currently running incoherently, and
|
||||
* therefore cannot safely call printk() or anything else
|
||||
*/
|
||||
pr_debug("CPU%u: spurious wakeup call\n", cpu);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* platform-specific code to shutdown a CPU
|
||||
*
|
||||
* Called with IRQs disabled
|
||||
*/
|
||||
void __ref msm_cpu_die(unsigned int cpu)
|
||||
{
|
||||
/*
|
||||
* we're ready for shutdown now, so do it
|
||||
*/
|
||||
cpu_enter_lowpower();
|
||||
platform_do_lowpower(cpu);
|
||||
|
||||
/*
|
||||
* bring this CPU back into the world of cache
|
||||
* coherency, and then restore interrupts
|
||||
*/
|
||||
cpu_leave_lowpower();
|
||||
}
|
|
@ -1,161 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2002 ARM Ltd.
|
||||
* All Rights Reserved
|
||||
* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/smp.h>
|
||||
#include <linux/io.h>
|
||||
|
||||
#include <asm/cacheflush.h>
|
||||
#include <asm/cputype.h>
|
||||
#include <asm/mach-types.h>
|
||||
#include <asm/smp_plat.h>
|
||||
|
||||
#include "scm-boot.h"
|
||||
#include "common.h"
|
||||
|
||||
#define VDD_SC1_ARRAY_CLAMP_GFS_CTL 0x15A0
|
||||
#define SCSS_CPU1CORE_RESET 0xD80
|
||||
#define SCSS_DBG_STATUS_CORE_PWRDUP 0xE64
|
||||
|
||||
extern void msm_secondary_startup(void);
|
||||
|
||||
static DEFINE_SPINLOCK(boot_lock);
|
||||
|
||||
static inline int get_core_count(void)
|
||||
{
|
||||
/* 1 + the PART[1:0] field of MIDR */
|
||||
return ((read_cpuid_id() >> 4) & 3) + 1;
|
||||
}
|
||||
|
||||
static void msm_secondary_init(unsigned int cpu)
|
||||
{
|
||||
/*
|
||||
* let the primary processor know we're out of the
|
||||
* pen, then head off into the C entry point
|
||||
*/
|
||||
pen_release = -1;
|
||||
smp_wmb();
|
||||
|
||||
/*
|
||||
* Synchronise with the boot thread.
|
||||
*/
|
||||
spin_lock(&boot_lock);
|
||||
spin_unlock(&boot_lock);
|
||||
}
|
||||
|
||||
static void prepare_cold_cpu(unsigned int cpu)
|
||||
{
|
||||
int ret;
|
||||
ret = scm_set_boot_addr(virt_to_phys(msm_secondary_startup),
|
||||
SCM_FLAG_COLDBOOT_CPU1);
|
||||
if (ret == 0) {
|
||||
void __iomem *sc1_base_ptr;
|
||||
sc1_base_ptr = ioremap_nocache(0x00902000, SZ_4K*2);
|
||||
if (sc1_base_ptr) {
|
||||
writel(0, sc1_base_ptr + VDD_SC1_ARRAY_CLAMP_GFS_CTL);
|
||||
writel(0, sc1_base_ptr + SCSS_CPU1CORE_RESET);
|
||||
writel(3, sc1_base_ptr + SCSS_DBG_STATUS_CORE_PWRDUP);
|
||||
iounmap(sc1_base_ptr);
|
||||
}
|
||||
} else
|
||||
printk(KERN_DEBUG "Failed to set secondary core boot "
|
||||
"address\n");
|
||||
}
|
||||
|
||||
static int msm_boot_secondary(unsigned int cpu, struct task_struct *idle)
|
||||
{
|
||||
unsigned long timeout;
|
||||
static int cold_boot_done;
|
||||
|
||||
/* Only need to bring cpu out of reset this way once */
|
||||
if (cold_boot_done == false) {
|
||||
prepare_cold_cpu(cpu);
|
||||
cold_boot_done = true;
|
||||
}
|
||||
|
||||
/*
|
||||
* set synchronisation state between this boot processor
|
||||
* and the secondary one
|
||||
*/
|
||||
spin_lock(&boot_lock);
|
||||
|
||||
/*
|
||||
* The secondary processor is waiting to be released from
|
||||
* the holding pen - release it, then wait for it to flag
|
||||
* that it has been released by resetting pen_release.
|
||||
*
|
||||
* Note that "pen_release" is the hardware CPU ID, whereas
|
||||
* "cpu" is Linux's internal ID.
|
||||
*/
|
||||
pen_release = cpu_logical_map(cpu);
|
||||
sync_cache_w(&pen_release);
|
||||
|
||||
/*
|
||||
* Send the secondary CPU a soft interrupt, thereby causing
|
||||
* the boot monitor to read the system wide flags register,
|
||||
* and branch to the address found there.
|
||||
*/
|
||||
arch_send_wakeup_ipi_mask(cpumask_of(cpu));
|
||||
|
||||
timeout = jiffies + (1 * HZ);
|
||||
while (time_before(jiffies, timeout)) {
|
||||
smp_rmb();
|
||||
if (pen_release == -1)
|
||||
break;
|
||||
|
||||
udelay(10);
|
||||
}
|
||||
|
||||
/*
|
||||
* now the secondary core is starting up let it run its
|
||||
* calibrations, then wait for it to finish
|
||||
*/
|
||||
spin_unlock(&boot_lock);
|
||||
|
||||
return pen_release != -1 ? -ENOSYS : 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialise the CPU possible map early - this describes the CPUs
|
||||
* which may be present or become present in the system. The msm8x60
|
||||
* does not support the ARM SCU, so just set the possible cpu mask to
|
||||
* NR_CPUS.
|
||||
*/
|
||||
static void __init msm_smp_init_cpus(void)
|
||||
{
|
||||
unsigned int i, ncores = get_core_count();
|
||||
|
||||
if (ncores > nr_cpu_ids) {
|
||||
pr_warn("SMP: %u cores greater than maximum (%u), clipping\n",
|
||||
ncores, nr_cpu_ids);
|
||||
ncores = nr_cpu_ids;
|
||||
}
|
||||
|
||||
for (i = 0; i < ncores; i++)
|
||||
set_cpu_possible(i, true);
|
||||
}
|
||||
|
||||
static void __init msm_smp_prepare_cpus(unsigned int max_cpus)
|
||||
{
|
||||
}
|
||||
|
||||
struct smp_operations msm_smp_ops __initdata = {
|
||||
.smp_init_cpus = msm_smp_init_cpus,
|
||||
.smp_prepare_cpus = msm_smp_prepare_cpus,
|
||||
.smp_secondary_init = msm_secondary_init,
|
||||
.smp_boot_secondary = msm_boot_secondary,
|
||||
#ifdef CONFIG_HOTPLUG_CPU
|
||||
.cpu_die = msm_cpu_die,
|
||||
#endif
|
||||
};
|
|
@ -0,0 +1,33 @@
|
|||
config ARCH_QCOM
|
||||
bool "Qualcomm Support" if ARCH_MULTI_V7
|
||||
select ARCH_REQUIRE_GPIOLIB
|
||||
select ARM_GIC
|
||||
select CLKSRC_OF
|
||||
select GENERIC_CLOCKEVENTS
|
||||
select HAVE_SMP
|
||||
select QCOM_SCM if SMP
|
||||
help
|
||||
Support for Qualcomm's devicetree based systems.
|
||||
|
||||
if ARCH_QCOM
|
||||
|
||||
menu "Qualcomm SoC Selection"
|
||||
|
||||
config ARCH_MSM8X60
|
||||
bool "Enable support for MSM8X60"
|
||||
select CLKSRC_QCOM
|
||||
|
||||
config ARCH_MSM8960
|
||||
bool "Enable support for MSM8960"
|
||||
select CLKSRC_QCOM
|
||||
|
||||
config ARCH_MSM8974
|
||||
bool "Enable support for MSM8974"
|
||||
select HAVE_ARM_ARCH_TIMER
|
||||
|
||||
endmenu
|
||||
|
||||
config QCOM_SCM
|
||||
bool
|
||||
|
||||
endif
|
|
@ -0,0 +1,5 @@
|
|||
obj-y := board.o
|
||||
obj-$(CONFIG_SMP) += platsmp.o
|
||||
obj-$(CONFIG_QCOM_SCM) += scm.o scm-boot.o
|
||||
|
||||
CFLAGS_scm.o :=$(call as-instr,.arch_extension sec,-DREQUIRES_SEC=1)
|
|
@ -1,4 +1,4 @@
|
|||
/* Copyright (c) 2010-2012,2013 The Linux Foundation. All rights reserved.
|
||||
/* Copyright (c) 2010-2014 The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
|
@ -11,31 +11,16 @@
|
|||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_platform.h>
|
||||
|
||||
#include <asm/mach/arch.h>
|
||||
#include <asm/mach/map.h>
|
||||
|
||||
#include "common.h"
|
||||
|
||||
static const char * const msm_dt_match[] __initconst = {
|
||||
"qcom,msm8660-fluid",
|
||||
static const char * const qcom_dt_match[] __initconst = {
|
||||
"qcom,msm8660-surf",
|
||||
"qcom,msm8960-cdp",
|
||||
NULL
|
||||
};
|
||||
|
||||
static const char * const apq8074_dt_match[] __initconst = {
|
||||
"qcom,apq8074-dragonboard",
|
||||
NULL
|
||||
};
|
||||
|
||||
DT_MACHINE_START(MSM_DT, "Qualcomm MSM (Flattened Device Tree)")
|
||||
.smp = smp_ops(msm_smp_ops),
|
||||
.dt_compat = msm_dt_match,
|
||||
MACHINE_END
|
||||
|
||||
DT_MACHINE_START(APQ_DT, "Qualcomm MSM (Flattened Device Tree)")
|
||||
.dt_compat = apq8074_dt_match,
|
||||
DT_MACHINE_START(QCOM_DT, "Qualcomm (Flattened Device Tree)")
|
||||
.dt_compat = qcom_dt_match,
|
||||
MACHINE_END
|
|
@ -0,0 +1,378 @@
|
|||
/*
|
||||
* Copyright (C) 2002 ARM Ltd.
|
||||
* All Rights Reserved
|
||||
* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
|
||||
* Copyright (c) 2014 The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/smp.h>
|
||||
#include <linux/io.h>
|
||||
|
||||
#include <asm/smp_plat.h>
|
||||
|
||||
#include "scm-boot.h"
|
||||
|
||||
#define VDD_SC1_ARRAY_CLAMP_GFS_CTL 0x35a0
|
||||
#define SCSS_CPU1CORE_RESET 0x2d80
|
||||
#define SCSS_DBG_STATUS_CORE_PWRDUP 0x2e64
|
||||
|
||||
#define APCS_CPU_PWR_CTL 0x04
|
||||
#define PLL_CLAMP BIT(8)
|
||||
#define CORE_PWRD_UP BIT(7)
|
||||
#define COREPOR_RST BIT(5)
|
||||
#define CORE_RST BIT(4)
|
||||
#define L2DT_SLP BIT(3)
|
||||
#define CLAMP BIT(0)
|
||||
|
||||
#define APC_PWR_GATE_CTL 0x14
|
||||
#define BHS_CNT_SHIFT 24
|
||||
#define LDO_PWR_DWN_SHIFT 16
|
||||
#define LDO_BYP_SHIFT 8
|
||||
#define BHS_SEG_SHIFT 1
|
||||
#define BHS_EN BIT(0)
|
||||
|
||||
#define APCS_SAW2_VCTL 0x14
|
||||
#define APCS_SAW2_2_VCTL 0x1c
|
||||
|
||||
extern void secondary_startup(void);
|
||||
|
||||
static DEFINE_SPINLOCK(boot_lock);
|
||||
|
||||
#ifdef CONFIG_HOTPLUG_CPU
|
||||
static void __ref qcom_cpu_die(unsigned int cpu)
|
||||
{
|
||||
wfi();
|
||||
}
|
||||
#endif
|
||||
|
||||
static void qcom_secondary_init(unsigned int cpu)
|
||||
{
|
||||
/*
|
||||
* Synchronise with the boot thread.
|
||||
*/
|
||||
spin_lock(&boot_lock);
|
||||
spin_unlock(&boot_lock);
|
||||
}
|
||||
|
||||
static int scss_release_secondary(unsigned int cpu)
|
||||
{
|
||||
struct device_node *node;
|
||||
void __iomem *base;
|
||||
|
||||
node = of_find_compatible_node(NULL, NULL, "qcom,gcc-msm8660");
|
||||
if (!node) {
|
||||
pr_err("%s: can't find node\n", __func__);
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
base = of_iomap(node, 0);
|
||||
of_node_put(node);
|
||||
if (!base)
|
||||
return -ENOMEM;
|
||||
|
||||
writel_relaxed(0, base + VDD_SC1_ARRAY_CLAMP_GFS_CTL);
|
||||
writel_relaxed(0, base + SCSS_CPU1CORE_RESET);
|
||||
writel_relaxed(3, base + SCSS_DBG_STATUS_CORE_PWRDUP);
|
||||
mb();
|
||||
iounmap(base);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int kpssv1_release_secondary(unsigned int cpu)
|
||||
{
|
||||
int ret = 0;
|
||||
void __iomem *reg, *saw_reg;
|
||||
struct device_node *cpu_node, *acc_node, *saw_node;
|
||||
u32 val;
|
||||
|
||||
cpu_node = of_get_cpu_node(cpu, NULL);
|
||||
if (!cpu_node)
|
||||
return -ENODEV;
|
||||
|
||||
acc_node = of_parse_phandle(cpu_node, "qcom,acc", 0);
|
||||
if (!acc_node) {
|
||||
ret = -ENODEV;
|
||||
goto out_acc;
|
||||
}
|
||||
|
||||
saw_node = of_parse_phandle(cpu_node, "qcom,saw", 0);
|
||||
if (!saw_node) {
|
||||
ret = -ENODEV;
|
||||
goto out_saw;
|
||||
}
|
||||
|
||||
reg = of_iomap(acc_node, 0);
|
||||
if (!reg) {
|
||||
ret = -ENOMEM;
|
||||
goto out_acc_map;
|
||||
}
|
||||
|
||||
saw_reg = of_iomap(saw_node, 0);
|
||||
if (!saw_reg) {
|
||||
ret = -ENOMEM;
|
||||
goto out_saw_map;
|
||||
}
|
||||
|
||||
/* Turn on CPU rail */
|
||||
writel_relaxed(0xA4, saw_reg + APCS_SAW2_VCTL);
|
||||
mb();
|
||||
udelay(512);
|
||||
|
||||
/* Krait bring-up sequence */
|
||||
val = PLL_CLAMP | L2DT_SLP | CLAMP;
|
||||
writel_relaxed(val, reg + APCS_CPU_PWR_CTL);
|
||||
val &= ~L2DT_SLP;
|
||||
writel_relaxed(val, reg + APCS_CPU_PWR_CTL);
|
||||
mb();
|
||||
ndelay(300);
|
||||
|
||||
val |= COREPOR_RST;
|
||||
writel_relaxed(val, reg + APCS_CPU_PWR_CTL);
|
||||
mb();
|
||||
udelay(2);
|
||||
|
||||
val &= ~CLAMP;
|
||||
writel_relaxed(val, reg + APCS_CPU_PWR_CTL);
|
||||
mb();
|
||||
udelay(2);
|
||||
|
||||
val &= ~COREPOR_RST;
|
||||
writel_relaxed(val, reg + APCS_CPU_PWR_CTL);
|
||||
mb();
|
||||
udelay(100);
|
||||
|
||||
val |= CORE_PWRD_UP;
|
||||
writel_relaxed(val, reg + APCS_CPU_PWR_CTL);
|
||||
mb();
|
||||
|
||||
iounmap(saw_reg);
|
||||
out_saw_map:
|
||||
iounmap(reg);
|
||||
out_acc_map:
|
||||
of_node_put(saw_node);
|
||||
out_saw:
|
||||
of_node_put(acc_node);
|
||||
out_acc:
|
||||
of_node_put(cpu_node);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int kpssv2_release_secondary(unsigned int cpu)
|
||||
{
|
||||
void __iomem *reg;
|
||||
struct device_node *cpu_node, *l2_node, *acc_node, *saw_node;
|
||||
void __iomem *l2_saw_base;
|
||||
unsigned reg_val;
|
||||
int ret;
|
||||
|
||||
cpu_node = of_get_cpu_node(cpu, NULL);
|
||||
if (!cpu_node)
|
||||
return -ENODEV;
|
||||
|
||||
acc_node = of_parse_phandle(cpu_node, "qcom,acc", 0);
|
||||
if (!acc_node) {
|
||||
ret = -ENODEV;
|
||||
goto out_acc;
|
||||
}
|
||||
|
||||
l2_node = of_parse_phandle(cpu_node, "next-level-cache", 0);
|
||||
if (!l2_node) {
|
||||
ret = -ENODEV;
|
||||
goto out_l2;
|
||||
}
|
||||
|
||||
saw_node = of_parse_phandle(l2_node, "qcom,saw", 0);
|
||||
if (!saw_node) {
|
||||
ret = -ENODEV;
|
||||
goto out_saw;
|
||||
}
|
||||
|
||||
reg = of_iomap(acc_node, 0);
|
||||
if (!reg) {
|
||||
ret = -ENOMEM;
|
||||
goto out_map;
|
||||
}
|
||||
|
||||
l2_saw_base = of_iomap(saw_node, 0);
|
||||
if (!l2_saw_base) {
|
||||
ret = -ENOMEM;
|
||||
goto out_saw_map;
|
||||
}
|
||||
|
||||
/* Turn on the BHS, turn off LDO Bypass and power down LDO */
|
||||
reg_val = (64 << BHS_CNT_SHIFT) | (0x3f << LDO_PWR_DWN_SHIFT) | BHS_EN;
|
||||
writel_relaxed(reg_val, reg + APC_PWR_GATE_CTL);
|
||||
mb();
|
||||
/* wait for the BHS to settle */
|
||||
udelay(1);
|
||||
|
||||
/* Turn on BHS segments */
|
||||
reg_val |= 0x3f << BHS_SEG_SHIFT;
|
||||
writel_relaxed(reg_val, reg + APC_PWR_GATE_CTL);
|
||||
mb();
|
||||
/* wait for the BHS to settle */
|
||||
udelay(1);
|
||||
|
||||
/* Finally turn on the bypass so that BHS supplies power */
|
||||
reg_val |= 0x3f << LDO_BYP_SHIFT;
|
||||
writel_relaxed(reg_val, reg + APC_PWR_GATE_CTL);
|
||||
|
||||
/* enable max phases */
|
||||
writel_relaxed(0x10003, l2_saw_base + APCS_SAW2_2_VCTL);
|
||||
mb();
|
||||
udelay(50);
|
||||
|
||||
reg_val = COREPOR_RST | CLAMP;
|
||||
writel_relaxed(reg_val, reg + APCS_CPU_PWR_CTL);
|
||||
mb();
|
||||
udelay(2);
|
||||
|
||||
reg_val &= ~CLAMP;
|
||||
writel_relaxed(reg_val, reg + APCS_CPU_PWR_CTL);
|
||||
mb();
|
||||
udelay(2);
|
||||
|
||||
reg_val &= ~COREPOR_RST;
|
||||
writel_relaxed(reg_val, reg + APCS_CPU_PWR_CTL);
|
||||
mb();
|
||||
|
||||
reg_val |= CORE_PWRD_UP;
|
||||
writel_relaxed(reg_val, reg + APCS_CPU_PWR_CTL);
|
||||
mb();
|
||||
|
||||
ret = 0;
|
||||
|
||||
iounmap(l2_saw_base);
|
||||
out_saw_map:
|
||||
iounmap(reg);
|
||||
out_map:
|
||||
of_node_put(saw_node);
|
||||
out_saw:
|
||||
of_node_put(l2_node);
|
||||
out_l2:
|
||||
of_node_put(acc_node);
|
||||
out_acc:
|
||||
of_node_put(cpu_node);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static DEFINE_PER_CPU(int, cold_boot_done);
|
||||
|
||||
static int qcom_boot_secondary(unsigned int cpu, int (*func)(unsigned int))
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (!per_cpu(cold_boot_done, cpu)) {
|
||||
ret = func(cpu);
|
||||
if (!ret)
|
||||
per_cpu(cold_boot_done, cpu) = true;
|
||||
}
|
||||
|
||||
/*
|
||||
* set synchronisation state between this boot processor
|
||||
* and the secondary one
|
||||
*/
|
||||
spin_lock(&boot_lock);
|
||||
|
||||
/*
|
||||
* Send the secondary CPU a soft interrupt, thereby causing
|
||||
* the boot monitor to read the system wide flags register,
|
||||
* and branch to the address found there.
|
||||
*/
|
||||
arch_send_wakeup_ipi_mask(cpumask_of(cpu));
|
||||
|
||||
/*
|
||||
* now the secondary core is starting up let it run its
|
||||
* calibrations, then wait for it to finish
|
||||
*/
|
||||
spin_unlock(&boot_lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int msm8660_boot_secondary(unsigned int cpu, struct task_struct *idle)
|
||||
{
|
||||
return qcom_boot_secondary(cpu, scss_release_secondary);
|
||||
}
|
||||
|
||||
static int kpssv1_boot_secondary(unsigned int cpu, struct task_struct *idle)
|
||||
{
|
||||
return qcom_boot_secondary(cpu, kpssv1_release_secondary);
|
||||
}
|
||||
|
||||
static int kpssv2_boot_secondary(unsigned int cpu, struct task_struct *idle)
|
||||
{
|
||||
return qcom_boot_secondary(cpu, kpssv2_release_secondary);
|
||||
}
|
||||
|
||||
static void __init qcom_smp_prepare_cpus(unsigned int max_cpus)
|
||||
{
|
||||
int cpu, map;
|
||||
unsigned int flags = 0;
|
||||
static const int cold_boot_flags[] = {
|
||||
0,
|
||||
SCM_FLAG_COLDBOOT_CPU1,
|
||||
SCM_FLAG_COLDBOOT_CPU2,
|
||||
SCM_FLAG_COLDBOOT_CPU3,
|
||||
};
|
||||
|
||||
for_each_present_cpu(cpu) {
|
||||
map = cpu_logical_map(cpu);
|
||||
if (WARN_ON(map >= ARRAY_SIZE(cold_boot_flags))) {
|
||||
set_cpu_present(cpu, false);
|
||||
continue;
|
||||
}
|
||||
flags |= cold_boot_flags[map];
|
||||
}
|
||||
|
||||
if (scm_set_boot_addr(virt_to_phys(secondary_startup), flags)) {
|
||||
for_each_present_cpu(cpu) {
|
||||
if (cpu == smp_processor_id())
|
||||
continue;
|
||||
set_cpu_present(cpu, false);
|
||||
}
|
||||
pr_warn("Failed to set CPU boot address, disabling SMP\n");
|
||||
}
|
||||
}
|
||||
|
||||
static struct smp_operations smp_msm8660_ops __initdata = {
|
||||
.smp_prepare_cpus = qcom_smp_prepare_cpus,
|
||||
.smp_secondary_init = qcom_secondary_init,
|
||||
.smp_boot_secondary = msm8660_boot_secondary,
|
||||
#ifdef CONFIG_HOTPLUG_CPU
|
||||
.cpu_die = qcom_cpu_die,
|
||||
#endif
|
||||
};
|
||||
CPU_METHOD_OF_DECLARE(qcom_smp, "qcom,gcc-msm8660", &smp_msm8660_ops);
|
||||
|
||||
static struct smp_operations qcom_smp_kpssv1_ops __initdata = {
|
||||
.smp_prepare_cpus = qcom_smp_prepare_cpus,
|
||||
.smp_secondary_init = qcom_secondary_init,
|
||||
.smp_boot_secondary = kpssv1_boot_secondary,
|
||||
#ifdef CONFIG_HOTPLUG_CPU
|
||||
.cpu_die = qcom_cpu_die,
|
||||
#endif
|
||||
};
|
||||
CPU_METHOD_OF_DECLARE(qcom_smp_kpssv1, "qcom,kpss-acc-v1", &qcom_smp_kpssv1_ops);
|
||||
|
||||
static struct smp_operations qcom_smp_kpssv2_ops __initdata = {
|
||||
.smp_prepare_cpus = qcom_smp_prepare_cpus,
|
||||
.smp_secondary_init = qcom_secondary_init,
|
||||
.smp_boot_secondary = kpssv2_boot_secondary,
|
||||
#ifdef CONFIG_HOTPLUG_CPU
|
||||
.cpu_die = qcom_cpu_die,
|
||||
#endif
|
||||
};
|
||||
CPU_METHOD_OF_DECLARE(qcom_smp_kpssv2, "qcom,kpss-acc-v2", &qcom_smp_kpssv2_ops);
|
|
@ -13,9 +13,11 @@
|
|||
#define __MACH_SCM_BOOT_H
|
||||
|
||||
#define SCM_BOOT_ADDR 0x1
|
||||
#define SCM_FLAG_COLDBOOT_CPU1 0x1
|
||||
#define SCM_FLAG_WARMBOOT_CPU1 0x2
|
||||
#define SCM_FLAG_WARMBOOT_CPU0 0x4
|
||||
#define SCM_FLAG_COLDBOOT_CPU1 0x01
|
||||
#define SCM_FLAG_COLDBOOT_CPU2 0x08
|
||||
#define SCM_FLAG_COLDBOOT_CPU3 0x20
|
||||
#define SCM_FLAG_WARMBOOT_CPU0 0x04
|
||||
#define SCM_FLAG_WARMBOOT_CPU1 0x02
|
||||
|
||||
int scm_set_boot_addr(phys_addr_t addr, int flags);
|
||||
|
|
@ -140,3 +140,6 @@ config VF_PIT_TIMER
|
|||
bool
|
||||
help
|
||||
Support for Period Interrupt Timer on Freescale Vybrid Family SoCs.
|
||||
|
||||
config CLKSRC_QCOM
|
||||
bool
|
||||
|
|
|
@ -32,6 +32,7 @@ obj-$(CONFIG_CLKSRC_EFM32) += time-efm32.o
|
|||
obj-$(CONFIG_CLKSRC_EXYNOS_MCT) += exynos_mct.o
|
||||
obj-$(CONFIG_CLKSRC_SAMSUNG_PWM) += samsung_pwm_timer.o
|
||||
obj-$(CONFIG_VF_PIT_TIMER) += vf_pit_timer.o
|
||||
obj-$(CONFIG_CLKSRC_QCOM) += qcom-timer.o
|
||||
|
||||
obj-$(CONFIG_ARM_ARCH_TIMER) += arm_arch_timer.o
|
||||
obj-$(CONFIG_ARM_GLOBAL_TIMER) += arm_global_timer.o
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
*
|
||||
* Copyright (C) 2007 Google, Inc.
|
||||
* Copyright (c) 2009-2012, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2009-2012,2014, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License version 2, as published by the Free Software Foundation, and
|
||||
|
@ -26,10 +26,6 @@
|
|||
#include <linux/of_irq.h>
|
||||
#include <linux/sched_clock.h>
|
||||
|
||||
#include <asm/mach/time.h>
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#define TIMER_MATCH_VAL 0x0000
|
||||
#define TIMER_COUNT_VAL 0x0004
|
||||
#define TIMER_ENABLE 0x0008
|
||||
|
@ -110,15 +106,6 @@ static notrace cycle_t msm_read_timer_count(struct clocksource *cs)
|
|||
return readl_relaxed(source_base + TIMER_COUNT_VAL);
|
||||
}
|
||||
|
||||
static notrace cycle_t msm_read_timer_count_shift(struct clocksource *cs)
|
||||
{
|
||||
/*
|
||||
* Shift timer count down by a constant due to unreliable lower bits
|
||||
* on some targets.
|
||||
*/
|
||||
return msm_read_timer_count(cs) >> MSM_DGT_SHIFT;
|
||||
}
|
||||
|
||||
static struct clocksource msm_clocksource = {
|
||||
.name = "dg_timer",
|
||||
.rating = 300,
|
||||
|
@ -232,7 +219,7 @@ err:
|
|||
sched_clock_register(msm_sched_clock_read, sched_bits, dgt_hz);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
#ifdef CONFIG_ARCH_QCOM
|
||||
static void __init msm_dt_timer_init(struct device_node *np)
|
||||
{
|
||||
u32 freq;
|
||||
|
@ -285,7 +272,7 @@ static void __init msm_dt_timer_init(struct device_node *np)
|
|||
}
|
||||
CLOCKSOURCE_OF_DECLARE(kpss_timer, "qcom,kpss-timer", msm_dt_timer_init);
|
||||
CLOCKSOURCE_OF_DECLARE(scss_timer, "qcom,scss-timer", msm_dt_timer_init);
|
||||
#endif
|
||||
#else
|
||||
|
||||
static int __init msm_timer_map(phys_addr_t addr, u32 event, u32 source,
|
||||
u32 sts)
|
||||
|
@ -305,6 +292,15 @@ static int __init msm_timer_map(phys_addr_t addr, u32 event, u32 source,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static notrace cycle_t msm_read_timer_count_shift(struct clocksource *cs)
|
||||
{
|
||||
/*
|
||||
* Shift timer count down by a constant due to unreliable lower bits
|
||||
* on some targets.
|
||||
*/
|
||||
return msm_read_timer_count(cs) >> MSM_DGT_SHIFT;
|
||||
}
|
||||
|
||||
void __init msm7x01_timer_init(void)
|
||||
{
|
||||
struct clocksource *cs = &msm_clocksource;
|
||||
|
@ -331,3 +327,4 @@ void __init qsd8x50_timer_init(void)
|
|||
return;
|
||||
msm_timer_init(19200000 / 4, 32, 7, false);
|
||||
}
|
||||
#endif
|
|
@ -167,6 +167,15 @@
|
|||
#define CLK_OF_TABLES()
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
#define CPU_METHOD_OF_TABLES() . = ALIGN(8); \
|
||||
VMLINUX_SYMBOL(__cpu_method_of_table_begin) = .; \
|
||||
*(__cpu_method_of_table) \
|
||||
VMLINUX_SYMBOL(__cpu_method_of_table_end) = .;
|
||||
#else
|
||||
#define CPU_METHOD_OF_TABLES()
|
||||
#endif
|
||||
|
||||
#define KERNEL_DTB() \
|
||||
STRUCT_ALIGN(); \
|
||||
VMLINUX_SYMBOL(__dtb_start) = .; \
|
||||
|
@ -491,6 +500,7 @@
|
|||
MEM_DISCARD(init.rodata) \
|
||||
CLK_OF_TABLES() \
|
||||
CLKSRC_OF_TABLES() \
|
||||
CPU_METHOD_OF_TABLES() \
|
||||
KERNEL_DTB() \
|
||||
IRQCHIP_OF_MATCH_TABLE()
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче