Exynos MCPM support for v3.16
- adding MCPM backend support for SMP secondary boot and core switching on Samsung's Exynos5420. Tested on exynos5420-smdk5420 and exynos5420 based chromebook (peach-pit) using the "/dev/b.L_switcher" user interface. Secondary core boot-up has also been tested on both the boards. -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.11 (GNU/Linux) iQIcBAABAgAGBQJTeo2RAAoJEA0Cl+kVi2xqynAQAInNHE2zWbOj/h9VcOV4+Upt VTobcgMiwEKZ530vkW3dq0acs24M6BU/OEBDP9qCPKG5q9qdjQcmiIlwjmzWiPJM VBi05exFXAxcaOmj4SBl0rkFCHrpKu64B0YJrjKZz/zK9A1QN03kkYe8EYRnuwsH w3FN61JX/S+4MBvdgDL1KAvciHoZvNjhrsOFfY24+0vAMaQzWVhps49Tkg675MHO rZw9VV8nv0uJmOgFc8XnmlUe1DVTUHjBbCPC6Sy0H3H5DXzuMQOW1Y+qL0DLR9NJ bZDPYVaqpYK2cWvXqjqSNJz3sNpZhrWZi4BrVdnmWSlzuLSF8/DZom4gv+SNnd8+ DrvP/4wqGTzuhWq/gr+9T+/Lz2qzlyr8dGy86ohtBLwMocYwpufaEqU7iKIOxCrb IlpkM5EcstHKnSr8QinehVPGp8N1PqJDympYOgFb3hPDIDbKktNU2Wwgr4CDBN30 Qypd3+fHwU2SJtK34L5/+hDmxwQwB5gnpPbc//7Ir1Ld3ZTEXv9sn5Rtv0EXFK1E Xx/C4B+2COi3IGbELqyS1ax4twJr/t1EwxjZgQZO1LT2B9CtQeKKdrG/IpI+J6wL 9qjIRv4i0tICkGXyu/wwwhLAHqpDQ+FebWAqM3llpIcoTjBy3BOdjZ+C2R0mkS94 X2dRzKw0dswv8GpBTAYm =d5ZP -----END PGP SIGNATURE----- Merge tag 'exynos-mcpm' of http://git.kernel.org/pub/scm/linux/kernel/git/kgene/linux-samsung into next/soc Merge "Exynos MCPM support for v3.16" from Kukjin Kim: - adding MCPM backend support for SMP secondary boot and core switching on Samsung's Exynos5420. Tested on exynos5420-smdk5420 and exynos5420 based chromebook (peach-pit) using the "/dev/b.L_switcher" user interface. Secondary core boot-up has also been tested on both the boards. * tag 'exynos-mcpm' of http://git.kernel.org/pub/scm/linux/kernel/git/kgene/linux-samsung: ARM: EXYNOS: Add MCPM call-back functions ARM: dts: add CCI node for exynos5420 ARM: EXYNOS: Add generic cluster power control functions ARM: EXYNOS: use generic exynos cpu power control functions ARM: EXYNOS: Add generic cpu power control functions for exynos SoCs Signed-off-by: Olof Johansson <olof@lixom.net>
This commit is contained in:
commit
dca092f6d4
38
Documentation/devicetree/bindings/arm/exynos/smp-sysram.txt
Normal file
38
Documentation/devicetree/bindings/arm/exynos/smp-sysram.txt
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
Samsung Exynos SYSRAM for SMP bringup:
|
||||||
|
------------------------------------
|
||||||
|
|
||||||
|
Samsung SMP-capable Exynos SoCs use part of the SYSRAM for the bringup
|
||||||
|
of the secondary cores. Once the core gets powered up it executes the
|
||||||
|
code that is residing at some specific location of the SYSRAM.
|
||||||
|
|
||||||
|
Therefore reserved section sub-nodes have to be added to the mmio-sram
|
||||||
|
declaration. These nodes are of two types depending upon secure or
|
||||||
|
non-secure execution environment.
|
||||||
|
|
||||||
|
Required sub-node properties:
|
||||||
|
- compatible : depending upon boot mode, should be
|
||||||
|
"samsung,exynos4210-sysram" : for Secure SYSRAM
|
||||||
|
"samsung,exynos4210-sysram-ns" : for Non-secure SYSRAM
|
||||||
|
|
||||||
|
The rest of the properties should follow the generic mmio-sram discription
|
||||||
|
found in ../../misc/sysram.txt
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
sysram@02020000 {
|
||||||
|
compatible = "mmio-sram";
|
||||||
|
reg = <0x02020000 0x54000>;
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <1>;
|
||||||
|
ranges = <0 0x02020000 0x54000>;
|
||||||
|
|
||||||
|
smp-sysram@0 {
|
||||||
|
compatible = "samsung,exynos4210-sysram";
|
||||||
|
reg = <0x0 0x1000>;
|
||||||
|
};
|
||||||
|
|
||||||
|
smp-sysram@53000 {
|
||||||
|
compatible = "samsung,exynos4210-sysram-ns";
|
||||||
|
reg = <0x53000 0x1000>;
|
||||||
|
};
|
||||||
|
};
|
@ -843,6 +843,7 @@ config ARCH_EXYNOS
|
|||||||
select HAVE_S3C_RTC if RTC_CLASS
|
select HAVE_S3C_RTC if RTC_CLASS
|
||||||
select NEED_MACH_MEMORY_H
|
select NEED_MACH_MEMORY_H
|
||||||
select SPARSE_IRQ
|
select SPARSE_IRQ
|
||||||
|
select SRAM
|
||||||
select USE_OF
|
select USE_OF
|
||||||
help
|
help
|
||||||
Support for SAMSUNG's EXYNOS SoCs (EXYNOS4/5)
|
Support for SAMSUNG's EXYNOS SoCs (EXYNOS4/5)
|
||||||
|
@ -74,6 +74,7 @@ dtb-$(CONFIG_ARCH_EXYNOS) += exynos4210-origen.dtb \
|
|||||||
exynos5250-smdk5250.dtb \
|
exynos5250-smdk5250.dtb \
|
||||||
exynos5250-snow.dtb \
|
exynos5250-snow.dtb \
|
||||||
exynos5420-arndale-octa.dtb \
|
exynos5420-arndale-octa.dtb \
|
||||||
|
exynos5420-peach-pit.dtb \
|
||||||
exynos5420-smdk5420.dtb \
|
exynos5420-smdk5420.dtb \
|
||||||
exynos5440-sd5v1.dtb \
|
exynos5440-sd5v1.dtb \
|
||||||
exynos5440-ssdk5440.dtb
|
exynos5440-ssdk5440.dtb
|
||||||
|
@ -129,12 +129,10 @@
|
|||||||
status = "disabled";
|
status = "disabled";
|
||||||
#address-cells = <1>;
|
#address-cells = <1>;
|
||||||
#size-cells = <1>;
|
#size-cells = <1>;
|
||||||
|
#clock-cells = <1>;
|
||||||
|
clock-output-names = "cam_a_clkout", "cam_b_clkout";
|
||||||
ranges;
|
ranges;
|
||||||
|
|
||||||
clock_cam: clock-controller {
|
|
||||||
#clock-cells = <1>;
|
|
||||||
};
|
|
||||||
|
|
||||||
fimc_0: fimc@11800000 {
|
fimc_0: fimc@11800000 {
|
||||||
compatible = "samsung,exynos4210-fimc";
|
compatible = "samsung,exynos4210-fimc";
|
||||||
reg = <0x11800000 0x1000>;
|
reg = <0x11800000 0x1000>;
|
||||||
@ -371,6 +369,8 @@
|
|||||||
interrupts = <0 60 0>;
|
interrupts = <0 60 0>;
|
||||||
clocks = <&clock CLK_I2C2>;
|
clocks = <&clock CLK_I2C2>;
|
||||||
clock-names = "i2c";
|
clock-names = "i2c";
|
||||||
|
pinctrl-names = "default";
|
||||||
|
pinctrl-0 = <&i2c2_bus>;
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -382,6 +382,8 @@
|
|||||||
interrupts = <0 61 0>;
|
interrupts = <0 61 0>;
|
||||||
clocks = <&clock CLK_I2C3>;
|
clocks = <&clock CLK_I2C3>;
|
||||||
clock-names = "i2c";
|
clock-names = "i2c";
|
||||||
|
pinctrl-names = "default";
|
||||||
|
pinctrl-0 = <&i2c3_bus>;
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -393,6 +395,8 @@
|
|||||||
interrupts = <0 62 0>;
|
interrupts = <0 62 0>;
|
||||||
clocks = <&clock CLK_I2C4>;
|
clocks = <&clock CLK_I2C4>;
|
||||||
clock-names = "i2c";
|
clock-names = "i2c";
|
||||||
|
pinctrl-names = "default";
|
||||||
|
pinctrl-0 = <&i2c4_bus>;
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -404,6 +408,8 @@
|
|||||||
interrupts = <0 63 0>;
|
interrupts = <0 63 0>;
|
||||||
clocks = <&clock CLK_I2C5>;
|
clocks = <&clock CLK_I2C5>;
|
||||||
clock-names = "i2c";
|
clock-names = "i2c";
|
||||||
|
pinctrl-names = "default";
|
||||||
|
pinctrl-0 = <&i2c5_bus>;
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -415,6 +421,8 @@
|
|||||||
interrupts = <0 64 0>;
|
interrupts = <0 64 0>;
|
||||||
clocks = <&clock CLK_I2C6>;
|
clocks = <&clock CLK_I2C6>;
|
||||||
clock-names = "i2c";
|
clock-names = "i2c";
|
||||||
|
pinctrl-names = "default";
|
||||||
|
pinctrl-0 = <&i2c6_bus>;
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -426,6 +434,8 @@
|
|||||||
interrupts = <0 65 0>;
|
interrupts = <0 65 0>;
|
||||||
clocks = <&clock CLK_I2C7>;
|
clocks = <&clock CLK_I2C7>;
|
||||||
clock-names = "i2c";
|
clock-names = "i2c";
|
||||||
|
pinctrl-names = "default";
|
||||||
|
pinctrl-0 = <&i2c7_bus>;
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -28,6 +28,21 @@
|
|||||||
bootargs = "console=ttySAC2,115200N8 root=/dev/mmcblk0p5 rw rootwait earlyprintk panic=5 maxcpus=1";
|
bootargs = "console=ttySAC2,115200N8 root=/dev/mmcblk0p5 rw rootwait earlyprintk panic=5 maxcpus=1";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
sysram@02020000 {
|
||||||
|
smp-sysram@0 {
|
||||||
|
status = "disabled";
|
||||||
|
};
|
||||||
|
|
||||||
|
smp-sysram@5000 {
|
||||||
|
compatible = "samsung,exynos4210-sysram";
|
||||||
|
reg = <0x5000 0x1000>;
|
||||||
|
};
|
||||||
|
|
||||||
|
smp-sysram@1f000 {
|
||||||
|
status = "disabled";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
mct@10050000 {
|
mct@10050000 {
|
||||||
compatible = "none";
|
compatible = "none";
|
||||||
};
|
};
|
||||||
|
@ -31,6 +31,24 @@
|
|||||||
pinctrl2 = &pinctrl_2;
|
pinctrl2 = &pinctrl_2;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
sysram@02020000 {
|
||||||
|
compatible = "mmio-sram";
|
||||||
|
reg = <0x02020000 0x20000>;
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <1>;
|
||||||
|
ranges = <0 0x02020000 0x20000>;
|
||||||
|
|
||||||
|
smp-sysram@0 {
|
||||||
|
compatible = "samsung,exynos4210-sysram";
|
||||||
|
reg = <0x0 0x1000>;
|
||||||
|
};
|
||||||
|
|
||||||
|
smp-sysram@1f000 {
|
||||||
|
compatible = "samsung,exynos4210-sysram-ns";
|
||||||
|
reg = <0x1f000 0x1000>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
pd_lcd1: lcd1-power-domain@10023CA0 {
|
pd_lcd1: lcd1-power-domain@10023CA0 {
|
||||||
compatible = "samsung,exynos4210-pd";
|
compatible = "samsung,exynos4210-pd";
|
||||||
reg = <0x10023CA0 0x20>;
|
reg = <0x10023CA0 0x20>;
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
compatible = "samsung,trats2", "samsung,exynos4412", "samsung,exynos4";
|
compatible = "samsung,trats2", "samsung,exynos4412", "samsung,exynos4";
|
||||||
|
|
||||||
aliases {
|
aliases {
|
||||||
i2c8 = &i2c_ak8975;
|
i2c9 = &i2c_ak8975;
|
||||||
};
|
};
|
||||||
|
|
||||||
memory {
|
memory {
|
||||||
@ -80,7 +80,24 @@
|
|||||||
enable-active-high;
|
enable-active-high;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* More to come */
|
cam_af_reg: voltage-regulator-3 {
|
||||||
|
compatible = "regulator-fixed";
|
||||||
|
regulator-name = "CAM_AF";
|
||||||
|
regulator-min-microvolt = <2800000>;
|
||||||
|
regulator-max-microvolt = <2800000>;
|
||||||
|
gpio = <&gpm0 4 0>;
|
||||||
|
enable-active-high;
|
||||||
|
};
|
||||||
|
|
||||||
|
cam_isp_core_reg: voltage-regulator-4 {
|
||||||
|
compatible = "regulator-fixed";
|
||||||
|
regulator-name = "CAM_ISP_CORE_1.2V_EN";
|
||||||
|
regulator-min-microvolt = <1200000>;
|
||||||
|
regulator-max-microvolt = <1200000>;
|
||||||
|
gpio = <&gpm0 3 0>;
|
||||||
|
enable-active-high;
|
||||||
|
regulator-always-on;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
gpio-keys {
|
gpio-keys {
|
||||||
@ -140,6 +157,38 @@
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
i2c_0: i2c@13860000 {
|
||||||
|
samsung,i2c-sda-delay = <100>;
|
||||||
|
samsung,i2c-slave-addr = <0x10>;
|
||||||
|
samsung,i2c-max-bus-freq = <400000>;
|
||||||
|
pinctrl-0 = <&i2c0_bus>;
|
||||||
|
pinctrl-names = "default";
|
||||||
|
status = "okay";
|
||||||
|
|
||||||
|
s5c73m3@3c {
|
||||||
|
compatible = "samsung,s5c73m3";
|
||||||
|
reg = <0x3c>;
|
||||||
|
standby-gpios = <&gpm0 1 1>; /* ISP_STANDBY */
|
||||||
|
xshutdown-gpios = <&gpf1 3 1>; /* ISP_RESET */
|
||||||
|
vdd-int-supply = <&buck9_reg>;
|
||||||
|
vddio-cis-supply = <&ldo9_reg>;
|
||||||
|
vdda-supply = <&ldo17_reg>;
|
||||||
|
vddio-host-supply = <&ldo18_reg>;
|
||||||
|
vdd-af-supply = <&cam_af_reg>;
|
||||||
|
vdd-reg-supply = <&cam_io_reg>;
|
||||||
|
clock-frequency = <24000000>;
|
||||||
|
/* CAM_A_CLKOUT */
|
||||||
|
clocks = <&camera 0>;
|
||||||
|
clock-names = "cis_extclk";
|
||||||
|
port {
|
||||||
|
s5c73m3_ep: endpoint {
|
||||||
|
remote-endpoint = <&csis0_ep>;
|
||||||
|
data-lanes = <1 2 3 4>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
i2c@138D0000 {
|
i2c@138D0000 {
|
||||||
samsung,i2c-sda-delay = <100>;
|
samsung,i2c-sda-delay = <100>;
|
||||||
samsung,i2c-slave-addr = <0x10>;
|
samsung,i2c-slave-addr = <0x10>;
|
||||||
@ -586,8 +635,8 @@
|
|||||||
status = "okay";
|
status = "okay";
|
||||||
};
|
};
|
||||||
|
|
||||||
camera {
|
camera: camera {
|
||||||
pinctrl-0 = <&cam_port_b_clk_active>;
|
pinctrl-0 = <&cam_port_a_clk_active &cam_port_b_clk_active>;
|
||||||
pinctrl-names = "default";
|
pinctrl-names = "default";
|
||||||
status = "okay";
|
status = "okay";
|
||||||
|
|
||||||
@ -607,6 +656,23 @@
|
|||||||
status = "okay";
|
status = "okay";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
csis_0: csis@11880000 {
|
||||||
|
status = "okay";
|
||||||
|
vddcore-supply = <&ldo8_reg>;
|
||||||
|
vddio-supply = <&ldo10_reg>;
|
||||||
|
clock-frequency = <176000000>;
|
||||||
|
|
||||||
|
/* Camera C (3) MIPI CSI-2 (CSIS0) */
|
||||||
|
port@3 {
|
||||||
|
reg = <3>;
|
||||||
|
csis0_ep: endpoint {
|
||||||
|
remote-endpoint = <&s5c73m3_ep>;
|
||||||
|
data-lanes = <1 2 3 4>;
|
||||||
|
samsung,csis-hs-settle = <12>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
csis_1: csis@11890000 {
|
csis_1: csis@11890000 {
|
||||||
vddcore-supply = <&ldo8_reg>;
|
vddcore-supply = <&ldo8_reg>;
|
||||||
vddio-supply = <&ldo10_reg>;
|
vddio-supply = <&ldo10_reg>;
|
||||||
@ -647,10 +713,11 @@
|
|||||||
reg = <0x10>;
|
reg = <0x10>;
|
||||||
svdda-supply = <&cam_io_reg>;
|
svdda-supply = <&cam_io_reg>;
|
||||||
svddio-supply = <&ldo19_reg>;
|
svddio-supply = <&ldo19_reg>;
|
||||||
|
afvdd-supply = <&ldo19_reg>;
|
||||||
clock-frequency = <24000000>;
|
clock-frequency = <24000000>;
|
||||||
/* CAM_B_CLKOUT */
|
/* CAM_B_CLKOUT */
|
||||||
clocks = <&clock_cam 1>;
|
clocks = <&camera 1>;
|
||||||
clock-names = "mclk";
|
clock-names = "extclk";
|
||||||
samsung,camclk-out = <1>;
|
samsung,camclk-out = <1>;
|
||||||
gpios = <&gpm1 6 0>;
|
gpios = <&gpm1 6 0>;
|
||||||
|
|
||||||
|
@ -37,6 +37,24 @@
|
|||||||
interrupts = <2 2>, <3 2>, <18 2>, <19 2>;
|
interrupts = <2 2>, <3 2>, <18 2>, <19 2>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
sysram@02020000 {
|
||||||
|
compatible = "mmio-sram";
|
||||||
|
reg = <0x02020000 0x40000>;
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <1>;
|
||||||
|
ranges = <0 0x02020000 0x40000>;
|
||||||
|
|
||||||
|
smp-sysram@0 {
|
||||||
|
compatible = "samsung,exynos4210-sysram";
|
||||||
|
reg = <0x0 0x1000>;
|
||||||
|
};
|
||||||
|
|
||||||
|
smp-sysram@2f000 {
|
||||||
|
compatible = "samsung,exynos4210-sysram-ns";
|
||||||
|
reg = <0x2f000 0x1000>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
pd_isp: isp-power-domain@10023CA0 {
|
pd_isp: isp-power-domain@10023CA0 {
|
||||||
compatible = "samsung,exynos4210-pd";
|
compatible = "samsung,exynos4210-pd";
|
||||||
reg = <0x10023CA0 0x20>;
|
reg = <0x10023CA0 0x20>;
|
||||||
|
@ -72,6 +72,24 @@
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
sysram@02020000 {
|
||||||
|
compatible = "mmio-sram";
|
||||||
|
reg = <0x02020000 0x30000>;
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <1>;
|
||||||
|
ranges = <0 0x02020000 0x30000>;
|
||||||
|
|
||||||
|
smp-sysram@0 {
|
||||||
|
compatible = "samsung,exynos4210-sysram";
|
||||||
|
reg = <0x0 0x1000>;
|
||||||
|
};
|
||||||
|
|
||||||
|
smp-sysram@2f000 {
|
||||||
|
compatible = "samsung,exynos4210-sysram-ns";
|
||||||
|
reg = <0x2f000 0x1000>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
pd_gsc: gsc-power-domain@10044000 {
|
pd_gsc: gsc-power-domain@10044000 {
|
||||||
compatible = "samsung,exynos4210-pd";
|
compatible = "samsung,exynos4210-pd";
|
||||||
reg = <0x10044000 0x20>;
|
reg = <0x10044000 0x20>;
|
||||||
|
147
arch/arm/boot/dts/exynos5420-peach-pit.dts
Normal file
147
arch/arm/boot/dts/exynos5420-peach-pit.dts
Normal file
@ -0,0 +1,147 @@
|
|||||||
|
/*
|
||||||
|
* Google Peach Pit Rev 6+ board device tree source
|
||||||
|
*
|
||||||
|
* Copyright (c) 2014 Google, Inc
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/dts-v1/;
|
||||||
|
#include <dt-bindings/input/input.h>
|
||||||
|
#include <dt-bindings/gpio/gpio.h>
|
||||||
|
#include "exynos5420.dtsi"
|
||||||
|
|
||||||
|
/ {
|
||||||
|
model = "Google Peach Pit Rev 6+";
|
||||||
|
|
||||||
|
compatible = "google,pit-rev16",
|
||||||
|
"google,pit-rev15", "google,pit-rev14",
|
||||||
|
"google,pit-rev13", "google,pit-rev12",
|
||||||
|
"google,pit-rev11", "google,pit-rev10",
|
||||||
|
"google,pit-rev9", "google,pit-rev8",
|
||||||
|
"google,pit-rev7", "google,pit-rev6",
|
||||||
|
"google,pit", "google,peach","samsung,exynos5420",
|
||||||
|
"samsung,exynos5";
|
||||||
|
|
||||||
|
memory {
|
||||||
|
reg = <0x20000000 0x80000000>;
|
||||||
|
};
|
||||||
|
|
||||||
|
fixed-rate-clocks {
|
||||||
|
oscclk {
|
||||||
|
compatible = "samsung,exynos5420-oscclk";
|
||||||
|
clock-frequency = <24000000>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
gpio-keys {
|
||||||
|
compatible = "gpio-keys";
|
||||||
|
|
||||||
|
pinctrl-names = "default";
|
||||||
|
pinctrl-0 = <&power_key_irq>;
|
||||||
|
|
||||||
|
power {
|
||||||
|
label = "Power";
|
||||||
|
gpios = <&gpx1 2 GPIO_ACTIVE_LOW>;
|
||||||
|
linux,code = <KEY_POWER>;
|
||||||
|
gpio-key,wakeup;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
backlight {
|
||||||
|
compatible = "pwm-backlight";
|
||||||
|
pwms = <&pwm 0 1000000 0>;
|
||||||
|
brightness-levels = <0 100 500 1000 1500 2000 2500 2800>;
|
||||||
|
default-brightness-level = <7>;
|
||||||
|
pinctrl-0 = <&pwm0_out>;
|
||||||
|
pinctrl-names = "default";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
&pinctrl_0 {
|
||||||
|
tpm_irq: tpm-irq {
|
||||||
|
samsung,pins = "gpx1-0";
|
||||||
|
samsung,pin-function = <0>;
|
||||||
|
samsung,pin-pud = <0>;
|
||||||
|
samsung,pin-drv = <0>;
|
||||||
|
};
|
||||||
|
|
||||||
|
power_key_irq: power-key-irq {
|
||||||
|
samsung,pins = "gpx1-2";
|
||||||
|
samsung,pin-function = <0>;
|
||||||
|
samsung,pin-pud = <0>;
|
||||||
|
samsung,pin-drv = <0>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
&rtc {
|
||||||
|
status = "okay";
|
||||||
|
};
|
||||||
|
|
||||||
|
&uart_3 {
|
||||||
|
status = "okay";
|
||||||
|
};
|
||||||
|
|
||||||
|
&mmc_0 {
|
||||||
|
status = "okay";
|
||||||
|
num-slots = <1>;
|
||||||
|
broken-cd;
|
||||||
|
caps2-mmc-hs200-1_8v;
|
||||||
|
supports-highspeed;
|
||||||
|
non-removable;
|
||||||
|
card-detect-delay = <200>;
|
||||||
|
clock-frequency = <400000000>;
|
||||||
|
samsung,dw-mshc-ciu-div = <3>;
|
||||||
|
samsung,dw-mshc-sdr-timing = <0 4>;
|
||||||
|
samsung,dw-mshc-ddr-timing = <0 2>;
|
||||||
|
pinctrl-names = "default";
|
||||||
|
pinctrl-0 = <&sd0_clk &sd0_cmd &sd0_bus4 &sd0_bus8>;
|
||||||
|
|
||||||
|
slot@0 {
|
||||||
|
reg = <0>;
|
||||||
|
bus-width = <8>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
&mmc_2 {
|
||||||
|
status = "okay";
|
||||||
|
num-slots = <1>;
|
||||||
|
supports-highspeed;
|
||||||
|
card-detect-delay = <200>;
|
||||||
|
clock-frequency = <400000000>;
|
||||||
|
samsung,dw-mshc-ciu-div = <3>;
|
||||||
|
samsung,dw-mshc-sdr-timing = <2 3>;
|
||||||
|
samsung,dw-mshc-ddr-timing = <1 2>;
|
||||||
|
pinctrl-names = "default";
|
||||||
|
pinctrl-0 = <&sd2_clk &sd2_cmd &sd2_cd &sd2_bus4>;
|
||||||
|
|
||||||
|
slot@0 {
|
||||||
|
reg = <0>;
|
||||||
|
bus-width = <4>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
&hsi2c_9 {
|
||||||
|
status = "okay";
|
||||||
|
clock-frequency = <400000>;
|
||||||
|
|
||||||
|
tpm@20 {
|
||||||
|
compatible = "infineon,slb9645tt";
|
||||||
|
reg = <0x20>;
|
||||||
|
|
||||||
|
/* Unused irq; but still need to configure the pins */
|
||||||
|
pinctrl-names = "default";
|
||||||
|
pinctrl-0 = <&tpm_irq>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Use longest HW watchdog in SoC (32 seconds) since the hardware
|
||||||
|
* watchdog provides no debugging information (compared to soft/hard
|
||||||
|
* lockup detectors) and so should be last resort.
|
||||||
|
*/
|
||||||
|
&watchdog {
|
||||||
|
timeout-sec = <32>;
|
||||||
|
};
|
@ -624,6 +624,34 @@
|
|||||||
samsung,pin-drv = <0>;
|
samsung,pin-drv = <0>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pwm0_out: pwm0-out {
|
||||||
|
samsung,pins = "gpb2-0";
|
||||||
|
samsung,pin-function = <2>;
|
||||||
|
samsung,pin-pud = <0>;
|
||||||
|
samsung,pin-drv = <0>;
|
||||||
|
};
|
||||||
|
|
||||||
|
pwm1_out: pwm1-out {
|
||||||
|
samsung,pins = "gpb2-1";
|
||||||
|
samsung,pin-function = <2>;
|
||||||
|
samsung,pin-pud = <0>;
|
||||||
|
samsung,pin-drv = <0>;
|
||||||
|
};
|
||||||
|
|
||||||
|
pwm2_out: pwm2-out {
|
||||||
|
samsung,pins = "gpb2-2";
|
||||||
|
samsung,pin-function = <2>;
|
||||||
|
samsung,pin-pud = <0>;
|
||||||
|
samsung,pin-drv = <0>;
|
||||||
|
};
|
||||||
|
|
||||||
|
pwm3_out: pwm3-out {
|
||||||
|
samsung,pins = "gpb2-3";
|
||||||
|
samsung,pin-function = <2>;
|
||||||
|
samsung,pin-pud = <0>;
|
||||||
|
samsung,pin-drv = <0>;
|
||||||
|
};
|
||||||
|
|
||||||
i2c7_hs_bus: i2c7-hs-bus {
|
i2c7_hs_bus: i2c7-hs-bus {
|
||||||
samsung,pins = "gpb2-2", "gpb2-3";
|
samsung,pins = "gpb2-2", "gpb2-3";
|
||||||
samsung,pin-function = <3>;
|
samsung,pin-function = <3>;
|
||||||
|
@ -58,6 +58,7 @@
|
|||||||
compatible = "arm,cortex-a15";
|
compatible = "arm,cortex-a15";
|
||||||
reg = <0x0>;
|
reg = <0x0>;
|
||||||
clock-frequency = <1800000000>;
|
clock-frequency = <1800000000>;
|
||||||
|
cci-control-port = <&cci_control1>;
|
||||||
};
|
};
|
||||||
|
|
||||||
cpu1: cpu@1 {
|
cpu1: cpu@1 {
|
||||||
@ -65,6 +66,7 @@
|
|||||||
compatible = "arm,cortex-a15";
|
compatible = "arm,cortex-a15";
|
||||||
reg = <0x1>;
|
reg = <0x1>;
|
||||||
clock-frequency = <1800000000>;
|
clock-frequency = <1800000000>;
|
||||||
|
cci-control-port = <&cci_control1>;
|
||||||
};
|
};
|
||||||
|
|
||||||
cpu2: cpu@2 {
|
cpu2: cpu@2 {
|
||||||
@ -72,6 +74,7 @@
|
|||||||
compatible = "arm,cortex-a15";
|
compatible = "arm,cortex-a15";
|
||||||
reg = <0x2>;
|
reg = <0x2>;
|
||||||
clock-frequency = <1800000000>;
|
clock-frequency = <1800000000>;
|
||||||
|
cci-control-port = <&cci_control1>;
|
||||||
};
|
};
|
||||||
|
|
||||||
cpu3: cpu@3 {
|
cpu3: cpu@3 {
|
||||||
@ -79,6 +82,7 @@
|
|||||||
compatible = "arm,cortex-a15";
|
compatible = "arm,cortex-a15";
|
||||||
reg = <0x3>;
|
reg = <0x3>;
|
||||||
clock-frequency = <1800000000>;
|
clock-frequency = <1800000000>;
|
||||||
|
cci-control-port = <&cci_control1>;
|
||||||
};
|
};
|
||||||
|
|
||||||
cpu4: cpu@100 {
|
cpu4: cpu@100 {
|
||||||
@ -86,6 +90,7 @@
|
|||||||
compatible = "arm,cortex-a7";
|
compatible = "arm,cortex-a7";
|
||||||
reg = <0x100>;
|
reg = <0x100>;
|
||||||
clock-frequency = <1000000000>;
|
clock-frequency = <1000000000>;
|
||||||
|
cci-control-port = <&cci_control0>;
|
||||||
};
|
};
|
||||||
|
|
||||||
cpu5: cpu@101 {
|
cpu5: cpu@101 {
|
||||||
@ -93,6 +98,7 @@
|
|||||||
compatible = "arm,cortex-a7";
|
compatible = "arm,cortex-a7";
|
||||||
reg = <0x101>;
|
reg = <0x101>;
|
||||||
clock-frequency = <1000000000>;
|
clock-frequency = <1000000000>;
|
||||||
|
cci-control-port = <&cci_control0>;
|
||||||
};
|
};
|
||||||
|
|
||||||
cpu6: cpu@102 {
|
cpu6: cpu@102 {
|
||||||
@ -100,6 +106,7 @@
|
|||||||
compatible = "arm,cortex-a7";
|
compatible = "arm,cortex-a7";
|
||||||
reg = <0x102>;
|
reg = <0x102>;
|
||||||
clock-frequency = <1000000000>;
|
clock-frequency = <1000000000>;
|
||||||
|
cci-control-port = <&cci_control0>;
|
||||||
};
|
};
|
||||||
|
|
||||||
cpu7: cpu@103 {
|
cpu7: cpu@103 {
|
||||||
@ -107,6 +114,44 @@
|
|||||||
compatible = "arm,cortex-a7";
|
compatible = "arm,cortex-a7";
|
||||||
reg = <0x103>;
|
reg = <0x103>;
|
||||||
clock-frequency = <1000000000>;
|
clock-frequency = <1000000000>;
|
||||||
|
cci-control-port = <&cci_control0>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
cci@10d20000 {
|
||||||
|
compatible = "arm,cci-400";
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <1>;
|
||||||
|
reg = <0x10d20000 0x1000>;
|
||||||
|
ranges = <0x0 0x10d20000 0x6000>;
|
||||||
|
|
||||||
|
cci_control0: slave-if@4000 {
|
||||||
|
compatible = "arm,cci-400-ctrl-if";
|
||||||
|
interface-type = "ace";
|
||||||
|
reg = <0x4000 0x1000>;
|
||||||
|
};
|
||||||
|
cci_control1: slave-if@5000 {
|
||||||
|
compatible = "arm,cci-400-ctrl-if";
|
||||||
|
interface-type = "ace";
|
||||||
|
reg = <0x5000 0x1000>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
sysram@02020000 {
|
||||||
|
compatible = "mmio-sram";
|
||||||
|
reg = <0x02020000 0x54000>;
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <1>;
|
||||||
|
ranges = <0 0x02020000 0x54000>;
|
||||||
|
|
||||||
|
smp-sysram@0 {
|
||||||
|
compatible = "samsung,exynos4210-sysram";
|
||||||
|
reg = <0x0 0x1000>;
|
||||||
|
};
|
||||||
|
|
||||||
|
smp-sysram@53000 {
|
||||||
|
compatible = "samsung,exynos4210-sysram-ns";
|
||||||
|
reg = <0x53000 0x1000>;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -125,7 +170,7 @@
|
|||||||
clock-names = "pll_ref", "pll_in", "sclk_audio", "sclk_pcm_in";
|
clock-names = "pll_ref", "pll_in", "sclk_audio", "sclk_pcm_in";
|
||||||
};
|
};
|
||||||
|
|
||||||
codec@11000000 {
|
mfc: codec@11000000 {
|
||||||
compatible = "samsung,mfc-v7";
|
compatible = "samsung,mfc-v7";
|
||||||
reg = <0x11000000 0x10000>;
|
reg = <0x11000000 0x10000>;
|
||||||
interrupts = <0 96 0>;
|
interrupts = <0 96 0>;
|
||||||
@ -169,7 +214,7 @@
|
|||||||
status = "disabled";
|
status = "disabled";
|
||||||
};
|
};
|
||||||
|
|
||||||
mct@101C0000 {
|
mct: mct@101C0000 {
|
||||||
compatible = "samsung,exynos4210-mct";
|
compatible = "samsung,exynos4210-mct";
|
||||||
reg = <0x101C0000 0x800>;
|
reg = <0x101C0000 0x800>;
|
||||||
interrupt-controller;
|
interrupt-controller;
|
||||||
@ -270,7 +315,7 @@
|
|||||||
interrupts = <0 47 0>;
|
interrupts = <0 47 0>;
|
||||||
};
|
};
|
||||||
|
|
||||||
rtc@101E0000 {
|
rtc: rtc@101E0000 {
|
||||||
clocks = <&clock CLK_RTC>;
|
clocks = <&clock CLK_RTC>;
|
||||||
clock-names = "rtc";
|
clock-names = "rtc";
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
@ -430,22 +475,22 @@
|
|||||||
status = "disabled";
|
status = "disabled";
|
||||||
};
|
};
|
||||||
|
|
||||||
serial@12C00000 {
|
uart_0: serial@12C00000 {
|
||||||
clocks = <&clock CLK_UART0>, <&clock CLK_SCLK_UART0>;
|
clocks = <&clock CLK_UART0>, <&clock CLK_SCLK_UART0>;
|
||||||
clock-names = "uart", "clk_uart_baud0";
|
clock-names = "uart", "clk_uart_baud0";
|
||||||
};
|
};
|
||||||
|
|
||||||
serial@12C10000 {
|
uart_1: serial@12C10000 {
|
||||||
clocks = <&clock CLK_UART1>, <&clock CLK_SCLK_UART1>;
|
clocks = <&clock CLK_UART1>, <&clock CLK_SCLK_UART1>;
|
||||||
clock-names = "uart", "clk_uart_baud0";
|
clock-names = "uart", "clk_uart_baud0";
|
||||||
};
|
};
|
||||||
|
|
||||||
serial@12C20000 {
|
uart_2: serial@12C20000 {
|
||||||
clocks = <&clock CLK_UART2>, <&clock CLK_SCLK_UART2>;
|
clocks = <&clock CLK_UART2>, <&clock CLK_SCLK_UART2>;
|
||||||
clock-names = "uart", "clk_uart_baud0";
|
clock-names = "uart", "clk_uart_baud0";
|
||||||
};
|
};
|
||||||
|
|
||||||
serial@12C30000 {
|
uart_3: serial@12C30000 {
|
||||||
clocks = <&clock CLK_UART3>, <&clock CLK_SCLK_UART3>;
|
clocks = <&clock CLK_UART3>, <&clock CLK_SCLK_UART3>;
|
||||||
clock-names = "uart", "clk_uart_baud0";
|
clock-names = "uart", "clk_uart_baud0";
|
||||||
};
|
};
|
||||||
@ -465,14 +510,14 @@
|
|||||||
#phy-cells = <0>;
|
#phy-cells = <0>;
|
||||||
};
|
};
|
||||||
|
|
||||||
dp-controller@145B0000 {
|
dp: dp-controller@145B0000 {
|
||||||
clocks = <&clock CLK_DP1>;
|
clocks = <&clock CLK_DP1>;
|
||||||
clock-names = "dp";
|
clock-names = "dp";
|
||||||
phys = <&dp_phy>;
|
phys = <&dp_phy>;
|
||||||
phy-names = "dp";
|
phy-names = "dp";
|
||||||
};
|
};
|
||||||
|
|
||||||
fimd@14400000 {
|
fimd: fimd@14400000 {
|
||||||
samsung,power-domain = <&disp_pd>;
|
samsung,power-domain = <&disp_pd>;
|
||||||
clocks = <&clock CLK_SCLK_FIMD1>, <&clock CLK_FIMD1>;
|
clocks = <&clock CLK_SCLK_FIMD1>, <&clock CLK_FIMD1>;
|
||||||
clock-names = "sclk_fimd", "fimd";
|
clock-names = "sclk_fimd", "fimd";
|
||||||
@ -632,7 +677,7 @@
|
|||||||
status = "disabled";
|
status = "disabled";
|
||||||
};
|
};
|
||||||
|
|
||||||
hdmi@14530000 {
|
hdmi: hdmi@14530000 {
|
||||||
compatible = "samsung,exynos4212-hdmi";
|
compatible = "samsung,exynos4212-hdmi";
|
||||||
reg = <0x14530000 0x70000>;
|
reg = <0x14530000 0x70000>;
|
||||||
interrupts = <0 95 0>;
|
interrupts = <0 95 0>;
|
||||||
@ -644,7 +689,7 @@
|
|||||||
status = "disabled";
|
status = "disabled";
|
||||||
};
|
};
|
||||||
|
|
||||||
mixer@14450000 {
|
mixer: mixer@14450000 {
|
||||||
compatible = "samsung,exynos5420-mixer";
|
compatible = "samsung,exynos5420-mixer";
|
||||||
reg = <0x14450000 0x10000>;
|
reg = <0x14450000 0x10000>;
|
||||||
interrupts = <0 94 0>;
|
interrupts = <0 94 0>;
|
||||||
@ -715,7 +760,7 @@
|
|||||||
clock-names = "tmu_apbif", "tmu_triminfo_apbif";
|
clock-names = "tmu_apbif", "tmu_triminfo_apbif";
|
||||||
};
|
};
|
||||||
|
|
||||||
watchdog@101D0000 {
|
watchdog: watchdog@101D0000 {
|
||||||
compatible = "samsung,exynos5420-wdt";
|
compatible = "samsung,exynos5420-wdt";
|
||||||
reg = <0x101D0000 0x100>;
|
reg = <0x101D0000 0x100>;
|
||||||
interrupts = <0 42 0>;
|
interrupts = <0 42 0>;
|
||||||
@ -724,7 +769,7 @@
|
|||||||
samsung,syscon-phandle = <&pmu_system_controller>;
|
samsung,syscon-phandle = <&pmu_system_controller>;
|
||||||
};
|
};
|
||||||
|
|
||||||
sss@10830000 {
|
sss: sss@10830000 {
|
||||||
compatible = "samsung,exynos4210-secss";
|
compatible = "samsung,exynos4210-secss";
|
||||||
reg = <0x10830000 0x10000>;
|
reg = <0x10830000 0x10000>;
|
||||||
interrupts = <0 112 0>;
|
interrupts = <0 112 0>;
|
||||||
|
@ -110,4 +110,12 @@ config SOC_EXYNOS5440
|
|||||||
|
|
||||||
endmenu
|
endmenu
|
||||||
|
|
||||||
|
config EXYNOS5420_MCPM
|
||||||
|
bool "Exynos5420 Multi-Cluster PM support"
|
||||||
|
depends on MCPM && SOC_EXYNOS5420
|
||||||
|
select ARM_CCI
|
||||||
|
help
|
||||||
|
This is needed to provide CPU and cluster power management
|
||||||
|
on Exynos5420 implementing big.LITTLE.
|
||||||
|
|
||||||
endif
|
endif
|
||||||
|
@ -29,3 +29,5 @@ obj-$(CONFIG_ARCH_EXYNOS) += firmware.o
|
|||||||
|
|
||||||
plus_sec := $(call as-instr,.arch_extension sec,+sec)
|
plus_sec := $(call as-instr,.arch_extension sec,+sec)
|
||||||
AFLAGS_exynos-smc.o :=-Wa,-march=armv7-a$(plus_sec)
|
AFLAGS_exynos-smc.o :=-Wa,-march=armv7-a$(plus_sec)
|
||||||
|
|
||||||
|
obj-$(CONFIG_EXYNOS5420_MCPM) += mcpm-exynos.o
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
void mct_init(void __iomem *base, int irq_g0, int irq_l0, int irq_l1);
|
void mct_init(void __iomem *base, int irq_g0, int irq_l0, int irq_l1);
|
||||||
|
|
||||||
struct map_desc;
|
struct map_desc;
|
||||||
|
extern void __iomem *sysram_ns_base_addr;
|
||||||
void exynos_init_io(void);
|
void exynos_init_io(void);
|
||||||
void exynos_restart(enum reboot_mode mode, const char *cmd);
|
void exynos_restart(enum reboot_mode mode, const char *cmd);
|
||||||
void exynos_cpuidle_init(void);
|
void exynos_cpuidle_init(void);
|
||||||
@ -62,5 +63,11 @@ struct exynos_pmu_conf {
|
|||||||
};
|
};
|
||||||
|
|
||||||
extern void exynos_sys_powerdown_conf(enum sys_powerdown mode);
|
extern void exynos_sys_powerdown_conf(enum sys_powerdown mode);
|
||||||
|
extern void exynos_cpu_power_down(int cpu);
|
||||||
|
extern void exynos_cpu_power_up(int cpu);
|
||||||
|
extern int exynos_cpu_power_state(int cpu);
|
||||||
|
extern void exynos_cluster_power_down(int cluster);
|
||||||
|
extern void exynos_cluster_power_up(int cluster);
|
||||||
|
extern int exynos_cluster_power_state(int cluster);
|
||||||
|
|
||||||
#endif /* __ARCH_ARM_MACH_EXYNOS_COMMON_H */
|
#endif /* __ARCH_ARM_MACH_EXYNOS_COMMON_H */
|
||||||
|
@ -114,51 +114,6 @@ static struct map_desc exynos4_iodesc[] __initdata = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct map_desc exynos4_iodesc0[] __initdata = {
|
|
||||||
{
|
|
||||||
.virtual = (unsigned long)S5P_VA_SYSRAM,
|
|
||||||
.pfn = __phys_to_pfn(EXYNOS4_PA_SYSRAM0),
|
|
||||||
.length = SZ_4K,
|
|
||||||
.type = MT_DEVICE,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
static struct map_desc exynos4_iodesc1[] __initdata = {
|
|
||||||
{
|
|
||||||
.virtual = (unsigned long)S5P_VA_SYSRAM,
|
|
||||||
.pfn = __phys_to_pfn(EXYNOS4_PA_SYSRAM1),
|
|
||||||
.length = SZ_4K,
|
|
||||||
.type = MT_DEVICE,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
static struct map_desc exynos4210_iodesc[] __initdata = {
|
|
||||||
{
|
|
||||||
.virtual = (unsigned long)S5P_VA_SYSRAM_NS,
|
|
||||||
.pfn = __phys_to_pfn(EXYNOS4210_PA_SYSRAM_NS),
|
|
||||||
.length = SZ_4K,
|
|
||||||
.type = MT_DEVICE,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
static struct map_desc exynos4x12_iodesc[] __initdata = {
|
|
||||||
{
|
|
||||||
.virtual = (unsigned long)S5P_VA_SYSRAM_NS,
|
|
||||||
.pfn = __phys_to_pfn(EXYNOS4x12_PA_SYSRAM_NS),
|
|
||||||
.length = SZ_4K,
|
|
||||||
.type = MT_DEVICE,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
static struct map_desc exynos5250_iodesc[] __initdata = {
|
|
||||||
{
|
|
||||||
.virtual = (unsigned long)S5P_VA_SYSRAM_NS,
|
|
||||||
.pfn = __phys_to_pfn(EXYNOS5250_PA_SYSRAM_NS),
|
|
||||||
.length = SZ_4K,
|
|
||||||
.type = MT_DEVICE,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
static struct map_desc exynos5_iodesc[] __initdata = {
|
static struct map_desc exynos5_iodesc[] __initdata = {
|
||||||
{
|
{
|
||||||
.virtual = (unsigned long)S3C_VA_SYS,
|
.virtual = (unsigned long)S3C_VA_SYS,
|
||||||
@ -180,11 +135,6 @@ static struct map_desc exynos5_iodesc[] __initdata = {
|
|||||||
.pfn = __phys_to_pfn(EXYNOS5_PA_SROMC),
|
.pfn = __phys_to_pfn(EXYNOS5_PA_SROMC),
|
||||||
.length = SZ_4K,
|
.length = SZ_4K,
|
||||||
.type = MT_DEVICE,
|
.type = MT_DEVICE,
|
||||||
}, {
|
|
||||||
.virtual = (unsigned long)S5P_VA_SYSRAM,
|
|
||||||
.pfn = __phys_to_pfn(EXYNOS5_PA_SYSRAM),
|
|
||||||
.length = SZ_4K,
|
|
||||||
.type = MT_DEVICE,
|
|
||||||
}, {
|
}, {
|
||||||
.virtual = (unsigned long)S5P_VA_CMU,
|
.virtual = (unsigned long)S5P_VA_CMU,
|
||||||
.pfn = __phys_to_pfn(EXYNOS5_PA_CMU),
|
.pfn = __phys_to_pfn(EXYNOS5_PA_CMU),
|
||||||
@ -280,20 +230,6 @@ static void __init exynos_map_io(void)
|
|||||||
|
|
||||||
if (soc_is_exynos5())
|
if (soc_is_exynos5())
|
||||||
iotable_init(exynos5_iodesc, ARRAY_SIZE(exynos5_iodesc));
|
iotable_init(exynos5_iodesc, ARRAY_SIZE(exynos5_iodesc));
|
||||||
|
|
||||||
if (soc_is_exynos4210()) {
|
|
||||||
if (samsung_rev() == EXYNOS4210_REV_0)
|
|
||||||
iotable_init(exynos4_iodesc0,
|
|
||||||
ARRAY_SIZE(exynos4_iodesc0));
|
|
||||||
else
|
|
||||||
iotable_init(exynos4_iodesc1,
|
|
||||||
ARRAY_SIZE(exynos4_iodesc1));
|
|
||||||
iotable_init(exynos4210_iodesc, ARRAY_SIZE(exynos4210_iodesc));
|
|
||||||
}
|
|
||||||
if (soc_is_exynos4212() || soc_is_exynos4412())
|
|
||||||
iotable_init(exynos4x12_iodesc, ARRAY_SIZE(exynos4x12_iodesc));
|
|
||||||
if (soc_is_exynos5250())
|
|
||||||
iotable_init(exynos5250_iodesc, ARRAY_SIZE(exynos5250_iodesc));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void __init exynos_init_io(void)
|
void __init exynos_init_io(void)
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
|
|
||||||
#include <mach/map.h>
|
#include <mach/map.h>
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
#include "smc.h"
|
#include "smc.h"
|
||||||
|
|
||||||
static int exynos_do_idle(void)
|
static int exynos_do_idle(void)
|
||||||
@ -34,7 +35,12 @@ static int exynos_cpu_boot(int cpu)
|
|||||||
|
|
||||||
static int exynos_set_cpu_boot_addr(int cpu, unsigned long boot_addr)
|
static int exynos_set_cpu_boot_addr(int cpu, unsigned long boot_addr)
|
||||||
{
|
{
|
||||||
void __iomem *boot_reg = S5P_VA_SYSRAM_NS + 0x1c + 4*cpu;
|
void __iomem *boot_reg;
|
||||||
|
|
||||||
|
if (!sysram_ns_base_addr)
|
||||||
|
return -ENODEV;
|
||||||
|
|
||||||
|
boot_reg = sysram_ns_base_addr + 0x1c + 4*cpu;
|
||||||
|
|
||||||
__raw_writel(boot_addr, boot_reg);
|
__raw_writel(boot_addr, boot_reg);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -96,7 +96,7 @@ static inline void platform_do_lowpower(unsigned int cpu, int *spurious)
|
|||||||
|
|
||||||
/* make cpu1 to be turned off at next WFI command */
|
/* make cpu1 to be turned off at next WFI command */
|
||||||
if (cpu == 1)
|
if (cpu == 1)
|
||||||
__raw_writel(0, S5P_ARM_CORE1_CONFIGURATION);
|
exynos_cpu_power_down(cpu);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* here's the WFI
|
* here's the WFI
|
||||||
|
@ -23,13 +23,6 @@
|
|||||||
|
|
||||||
#include <plat/map-s5p.h>
|
#include <plat/map-s5p.h>
|
||||||
|
|
||||||
#define EXYNOS4_PA_SYSRAM0 0x02025000
|
|
||||||
#define EXYNOS4_PA_SYSRAM1 0x02020000
|
|
||||||
#define EXYNOS5_PA_SYSRAM 0x02020000
|
|
||||||
#define EXYNOS4210_PA_SYSRAM_NS 0x0203F000
|
|
||||||
#define EXYNOS4x12_PA_SYSRAM_NS 0x0204F000
|
|
||||||
#define EXYNOS5250_PA_SYSRAM_NS 0x0204F000
|
|
||||||
|
|
||||||
#define EXYNOS_PA_CHIPID 0x10000000
|
#define EXYNOS_PA_CHIPID 0x10000000
|
||||||
|
|
||||||
#define EXYNOS4_PA_SYSCON 0x10010000
|
#define EXYNOS4_PA_SYSCON 0x10010000
|
||||||
|
351
arch/arm/mach-exynos/mcpm-exynos.c
Normal file
351
arch/arm/mach-exynos/mcpm-exynos.c
Normal file
@ -0,0 +1,351 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2014 Samsung Electronics Co., Ltd.
|
||||||
|
* http://www.samsung.com
|
||||||
|
*
|
||||||
|
* arch/arm/mach-exynos/mcpm-exynos.c
|
||||||
|
*
|
||||||
|
* Based on arch/arm/mach-vexpress/dcscb.c
|
||||||
|
*
|
||||||
|
* 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/arm-cci.h>
|
||||||
|
#include <linux/delay.h>
|
||||||
|
#include <linux/io.h>
|
||||||
|
#include <linux/of_address.h>
|
||||||
|
|
||||||
|
#include <asm/cputype.h>
|
||||||
|
#include <asm/cp15.h>
|
||||||
|
#include <asm/mcpm.h>
|
||||||
|
|
||||||
|
#include "regs-pmu.h"
|
||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
#define EXYNOS5420_CPUS_PER_CLUSTER 4
|
||||||
|
#define EXYNOS5420_NR_CLUSTERS 2
|
||||||
|
#define MCPM_BOOT_ADDR_OFFSET 0x1c
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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
|
||||||
|
* arch/arm/include/asm/cacheflush.h) except for the erratum handling.
|
||||||
|
*/
|
||||||
|
#define exynos_v7_exit_coherency_flush(level) \
|
||||||
|
asm volatile( \
|
||||||
|
"stmfd sp!, {fp, ip}\n\t"\
|
||||||
|
"mrc p15, 0, r0, c1, c0, 0 @ get SCTLR\n\t" \
|
||||||
|
"bic r0, r0, #"__stringify(CR_C)"\n\t" \
|
||||||
|
"mcr p15, 0, r0, c1, c0, 0 @ set SCTLR\n\t" \
|
||||||
|
"isb\n\t"\
|
||||||
|
"bl v7_flush_dcache_"__stringify(level)"\n\t" \
|
||||||
|
"clrex\n\t"\
|
||||||
|
"mrc p15, 0, r0, c1, c0, 1 @ get ACTLR\n\t" \
|
||||||
|
"bic r0, r0, #(1 << 6) @ disable local coherency\n\t" \
|
||||||
|
/* Dummy Load of a device register to avoid Erratum 799270 */ \
|
||||||
|
"ldr r4, [%0]\n\t" \
|
||||||
|
"and r4, r4, #0\n\t" \
|
||||||
|
"orr r0, r0, r4\n\t" \
|
||||||
|
"mcr p15, 0, r0, c1, c0, 1 @ set ACTLR\n\t" \
|
||||||
|
"isb\n\t" \
|
||||||
|
"dsb\n\t" \
|
||||||
|
"ldmfd sp!, {fp, ip}" \
|
||||||
|
: \
|
||||||
|
: "Ir" (S5P_INFORM0) \
|
||||||
|
: "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", \
|
||||||
|
"r9", "r10", "lr", "memory")
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We can't use regular spinlocks. In the switcher case, it is possible
|
||||||
|
* for an outbound CPU to call power_down() after its inbound counterpart
|
||||||
|
* is already live using the same logical CPU number which trips lockdep
|
||||||
|
* debugging.
|
||||||
|
*/
|
||||||
|
static arch_spinlock_t exynos_mcpm_lock = __ARCH_SPIN_LOCK_UNLOCKED;
|
||||||
|
static int
|
||||||
|
cpu_use_count[EXYNOS5420_CPUS_PER_CLUSTER][EXYNOS5420_NR_CLUSTERS];
|
||||||
|
|
||||||
|
#define exynos_cluster_usecnt(cluster) \
|
||||||
|
(cpu_use_count[0][cluster] + \
|
||||||
|
cpu_use_count[1][cluster] + \
|
||||||
|
cpu_use_count[2][cluster] + \
|
||||||
|
cpu_use_count[3][cluster])
|
||||||
|
|
||||||
|
#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 ||
|
||||||
|
cluster >= EXYNOS5420_NR_CLUSTERS)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Since this is called with IRQs enabled, and no arch_spin_lock_irq
|
||||||
|
* variant exists, we need to disable IRQs manually here.
|
||||||
|
*/
|
||||||
|
local_irq_disable();
|
||||||
|
arch_spin_lock(&exynos_mcpm_lock);
|
||||||
|
|
||||||
|
cpu_use_count[cpu][cluster]++;
|
||||||
|
if (cpu_use_count[cpu][cluster] == 1) {
|
||||||
|
bool was_cluster_down =
|
||||||
|
(exynos_cluster_usecnt(cluster) == 1);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Turn on the cluster (L2/COMMON) and then power on the
|
||||||
|
* cores.
|
||||||
|
*/
|
||||||
|
if (was_cluster_down)
|
||||||
|
err = exynos_cluster_power_control(cluster, 1);
|
||||||
|
|
||||||
|
if (!err)
|
||||||
|
exynos_cpu_power_up(cpunr);
|
||||||
|
else
|
||||||
|
exynos_cluster_power_control(cluster, 0);
|
||||||
|
} else if (cpu_use_count[cpu][cluster] != 2) {
|
||||||
|
/*
|
||||||
|
* The only possible values are:
|
||||||
|
* 0 = CPU down
|
||||||
|
* 1 = CPU (still) up
|
||||||
|
* 2 = CPU requested to be up before it had a chance
|
||||||
|
* to actually make itself down.
|
||||||
|
* Any other value is a bug.
|
||||||
|
*/
|
||||||
|
BUG();
|
||||||
|
}
|
||||||
|
|
||||||
|
arch_spin_unlock(&exynos_mcpm_lock);
|
||||||
|
local_irq_enable();
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* NOTE: 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.
|
||||||
|
*/
|
||||||
|
static void exynos_power_down(void)
|
||||||
|
{
|
||||||
|
unsigned int mpidr, cpu, cluster;
|
||||||
|
bool last_man = false, skip_wfi = false;
|
||||||
|
unsigned int cpunr;
|
||||||
|
|
||||||
|
mpidr = read_cpuid_mpidr();
|
||||||
|
cpu = MPIDR_AFFINITY_LEVEL(mpidr, 0);
|
||||||
|
cluster = MPIDR_AFFINITY_LEVEL(mpidr, 1);
|
||||||
|
cpunr = cpu + (cluster * EXYNOS5420_CPUS_PER_CLUSTER);
|
||||||
|
|
||||||
|
pr_debug("%s: cpu %u cluster %u\n", __func__, cpu, cluster);
|
||||||
|
BUG_ON(cpu >= EXYNOS5420_CPUS_PER_CLUSTER ||
|
||||||
|
cluster >= EXYNOS5420_NR_CLUSTERS);
|
||||||
|
|
||||||
|
__mcpm_cpu_going_down(cpu, cluster);
|
||||||
|
|
||||||
|
arch_spin_lock(&exynos_mcpm_lock);
|
||||||
|
BUG_ON(__mcpm_cluster_state(cluster) != CLUSTER_UP);
|
||||||
|
cpu_use_count[cpu][cluster]--;
|
||||||
|
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. */
|
||||||
|
last_man = true;
|
||||||
|
} else if (cpu_use_count[cpu][cluster] == 1) {
|
||||||
|
/*
|
||||||
|
* A power_up request went ahead of us.
|
||||||
|
* Even if we do not want to shut this CPU down,
|
||||||
|
* the caller expects a certain state as if the WFI
|
||||||
|
* was aborted. So let's continue with cache cleaning.
|
||||||
|
*/
|
||||||
|
skip_wfi = true;
|
||||||
|
} else {
|
||||||
|
BUG();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (last_man && __mcpm_outbound_enter_critical(cpu, cluster)) {
|
||||||
|
arch_spin_unlock(&exynos_mcpm_lock);
|
||||||
|
|
||||||
|
if (read_cpuid_part_number() == ARM_CPU_PART_CORTEX_A15) {
|
||||||
|
/*
|
||||||
|
* On the Cortex-A15 we need to disable
|
||||||
|
* L2 prefetching before flushing the cache.
|
||||||
|
*/
|
||||||
|
asm volatile(
|
||||||
|
"mcr p15, 1, %0, c15, c0, 3\n\t"
|
||||||
|
"isb\n\t"
|
||||||
|
"dsb"
|
||||||
|
: : "r" (0x400));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Flush all cache levels for this cluster. */
|
||||||
|
exynos_v7_exit_coherency_flush(all);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Disable cluster-level coherency by masking
|
||||||
|
* incoming snoops and DVM messages:
|
||||||
|
*/
|
||||||
|
cci_disable_port_by_cpu(mpidr);
|
||||||
|
|
||||||
|
__mcpm_outbound_leave_critical(cluster, CLUSTER_DOWN);
|
||||||
|
} else {
|
||||||
|
arch_spin_unlock(&exynos_mcpm_lock);
|
||||||
|
|
||||||
|
/* Disable and flush the local CPU cache. */
|
||||||
|
exynos_v7_exit_coherency_flush(louis);
|
||||||
|
}
|
||||||
|
|
||||||
|
__mcpm_cpu_down(cpu, cluster);
|
||||||
|
|
||||||
|
/* Now we are prepared for power-down, do it: */
|
||||||
|
if (!skip_wfi)
|
||||||
|
wfi();
|
||||||
|
|
||||||
|
/* Not dead at this point? Let our caller cope. */
|
||||||
|
}
|
||||||
|
|
||||||
|
static int exynos_power_down_finish(unsigned int cpu, unsigned int cluster)
|
||||||
|
{
|
||||||
|
unsigned int tries = 100;
|
||||||
|
unsigned int cpunr = cpu + (cluster * EXYNOS5420_CPUS_PER_CLUSTER);
|
||||||
|
|
||||||
|
pr_debug("%s: cpu %u cluster %u\n", __func__, cpu, cluster);
|
||||||
|
BUG_ON(cpu >= EXYNOS5420_CPUS_PER_CLUSTER ||
|
||||||
|
cluster >= EXYNOS5420_NR_CLUSTERS);
|
||||||
|
|
||||||
|
/* Wait for the core state to be OFF */
|
||||||
|
while (tries--) {
|
||||||
|
if (ACCESS_ONCE(cpu_use_count[cpu][cluster]) == 0) {
|
||||||
|
if ((exynos_cpu_power_state(cpunr) == 0))
|
||||||
|
return 0; /* success: the CPU is halted */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Otherwise, wait and retry: */
|
||||||
|
msleep(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return -ETIMEDOUT; /* timeout */
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct mcpm_platform_ops exynos_power_ops = {
|
||||||
|
.power_up = exynos_power_up,
|
||||||
|
.power_down = exynos_power_down,
|
||||||
|
.power_down_finish = exynos_power_down_finish,
|
||||||
|
};
|
||||||
|
|
||||||
|
static void __init exynos_mcpm_usage_count_init(void)
|
||||||
|
{
|
||||||
|
unsigned int mpidr, cpu, cluster;
|
||||||
|
|
||||||
|
mpidr = read_cpuid_mpidr();
|
||||||
|
cpu = MPIDR_AFFINITY_LEVEL(mpidr, 0);
|
||||||
|
cluster = MPIDR_AFFINITY_LEVEL(mpidr, 1);
|
||||||
|
|
||||||
|
pr_debug("%s: cpu %u cluster %u\n", __func__, cpu, cluster);
|
||||||
|
BUG_ON(cpu >= EXYNOS5420_CPUS_PER_CLUSTER ||
|
||||||
|
cluster >= EXYNOS5420_NR_CLUSTERS);
|
||||||
|
|
||||||
|
cpu_use_count[cpu][cluster] = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Enable cluster-level coherency, in preparation for turning on the MMU.
|
||||||
|
*/
|
||||||
|
static void __naked exynos_pm_power_up_setup(unsigned int affinity_level)
|
||||||
|
{
|
||||||
|
asm volatile ("\n"
|
||||||
|
"cmp r0, #1\n"
|
||||||
|
"bxne lr\n"
|
||||||
|
"b cci_enable_port_for_self");
|
||||||
|
}
|
||||||
|
|
||||||
|
static int __init exynos_mcpm_init(void)
|
||||||
|
{
|
||||||
|
struct device_node *node;
|
||||||
|
void __iomem *ns_sram_base_addr;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
node = of_find_compatible_node(NULL, NULL, "samsung,exynos5420");
|
||||||
|
if (!node)
|
||||||
|
return -ENODEV;
|
||||||
|
of_node_put(node);
|
||||||
|
|
||||||
|
if (!cci_probed())
|
||||||
|
return -ENODEV;
|
||||||
|
|
||||||
|
node = of_find_compatible_node(NULL, NULL,
|
||||||
|
"samsung,exynos4210-sysram-ns");
|
||||||
|
if (!node)
|
||||||
|
return -ENODEV;
|
||||||
|
|
||||||
|
ns_sram_base_addr = of_iomap(node, 0);
|
||||||
|
of_node_put(node);
|
||||||
|
if (!ns_sram_base_addr) {
|
||||||
|
pr_err("failed to map non-secure iRAM base address\n");
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* To increase the stability of KFC reset we need to program
|
||||||
|
* the PMU SPARE3 register
|
||||||
|
*/
|
||||||
|
__raw_writel(EXYNOS5420_SWRESET_KFC_SEL, S5P_PMU_SPARE3);
|
||||||
|
|
||||||
|
exynos_mcpm_usage_count_init();
|
||||||
|
|
||||||
|
ret = mcpm_platform_register(&exynos_power_ops);
|
||||||
|
if (!ret)
|
||||||
|
ret = mcpm_sync_init(exynos_pm_power_up_setup);
|
||||||
|
if (ret) {
|
||||||
|
iounmap(ns_sram_base_addr);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
mcpm_smp_set_ops();
|
||||||
|
|
||||||
|
pr_info("Exynos MCPM support installed\n");
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Future entries into the kernel can now go
|
||||||
|
* through the cluster entry vectors.
|
||||||
|
*/
|
||||||
|
__raw_writel(virt_to_phys(mcpm_entry_point),
|
||||||
|
ns_sram_base_addr + MCPM_BOOT_ADDR_OFFSET);
|
||||||
|
|
||||||
|
iounmap(ns_sram_base_addr);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
early_initcall(exynos_mcpm_init);
|
@ -20,6 +20,7 @@
|
|||||||
#include <linux/jiffies.h>
|
#include <linux/jiffies.h>
|
||||||
#include <linux/smp.h>
|
#include <linux/smp.h>
|
||||||
#include <linux/io.h>
|
#include <linux/io.h>
|
||||||
|
#include <linux/of_address.h>
|
||||||
|
|
||||||
#include <asm/cacheflush.h>
|
#include <asm/cacheflush.h>
|
||||||
#include <asm/smp_plat.h>
|
#include <asm/smp_plat.h>
|
||||||
@ -33,11 +34,33 @@
|
|||||||
|
|
||||||
extern void exynos4_secondary_startup(void);
|
extern void exynos4_secondary_startup(void);
|
||||||
|
|
||||||
|
static void __iomem *sysram_base_addr;
|
||||||
|
void __iomem *sysram_ns_base_addr;
|
||||||
|
|
||||||
|
static void __init exynos_smp_prepare_sysram(void)
|
||||||
|
{
|
||||||
|
struct device_node *node;
|
||||||
|
|
||||||
|
for_each_compatible_node(node, NULL, "samsung,exynos4210-sysram") {
|
||||||
|
if (!of_device_is_available(node))
|
||||||
|
continue;
|
||||||
|
sysram_base_addr = of_iomap(node, 0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
for_each_compatible_node(node, NULL, "samsung,exynos4210-sysram-ns") {
|
||||||
|
if (!of_device_is_available(node))
|
||||||
|
continue;
|
||||||
|
sysram_ns_base_addr = of_iomap(node, 0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static inline void __iomem *cpu_boot_reg_base(void)
|
static inline void __iomem *cpu_boot_reg_base(void)
|
||||||
{
|
{
|
||||||
if (soc_is_exynos4210() && samsung_rev() == EXYNOS4210_REV_1_1)
|
if (soc_is_exynos4210() && samsung_rev() == EXYNOS4210_REV_1_1)
|
||||||
return S5P_INFORM5;
|
return S5P_INFORM5;
|
||||||
return S5P_VA_SYSRAM;
|
return sysram_base_addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void __iomem *cpu_boot_reg(int cpu)
|
static inline void __iomem *cpu_boot_reg(int cpu)
|
||||||
@ -45,6 +68,8 @@ static inline void __iomem *cpu_boot_reg(int cpu)
|
|||||||
void __iomem *boot_reg;
|
void __iomem *boot_reg;
|
||||||
|
|
||||||
boot_reg = cpu_boot_reg_base();
|
boot_reg = cpu_boot_reg_base();
|
||||||
|
if (!boot_reg)
|
||||||
|
return ERR_PTR(-ENODEV);
|
||||||
if (soc_is_exynos4412())
|
if (soc_is_exynos4412())
|
||||||
boot_reg += 4*cpu;
|
boot_reg += 4*cpu;
|
||||||
else if (soc_is_exynos5420())
|
else if (soc_is_exynos5420())
|
||||||
@ -90,6 +115,7 @@ static int exynos_boot_secondary(unsigned int cpu, struct task_struct *idle)
|
|||||||
{
|
{
|
||||||
unsigned long timeout;
|
unsigned long timeout;
|
||||||
unsigned long phys_cpu = cpu_logical_map(cpu);
|
unsigned long phys_cpu = cpu_logical_map(cpu);
|
||||||
|
int ret = -ENOSYS;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Set synchronisation state between this boot processor
|
* Set synchronisation state between this boot processor
|
||||||
@ -107,15 +133,12 @@ static int exynos_boot_secondary(unsigned int cpu, struct task_struct *idle)
|
|||||||
*/
|
*/
|
||||||
write_pen_release(phys_cpu);
|
write_pen_release(phys_cpu);
|
||||||
|
|
||||||
if (!(__raw_readl(S5P_ARM_CORE1_STATUS) & S5P_CORE_LOCAL_PWR_EN)) {
|
if (!exynos_cpu_power_state(cpu)) {
|
||||||
__raw_writel(S5P_CORE_LOCAL_PWR_EN,
|
exynos_cpu_power_up(cpu);
|
||||||
S5P_ARM_CORE1_CONFIGURATION);
|
|
||||||
|
|
||||||
timeout = 10;
|
timeout = 10;
|
||||||
|
|
||||||
/* wait max 10 ms until cpu1 is on */
|
/* wait max 10 ms until cpu1 is on */
|
||||||
while ((__raw_readl(S5P_ARM_CORE1_STATUS)
|
while (exynos_cpu_power_state(cpu) != S5P_CORE_LOCAL_PWR_EN) {
|
||||||
& S5P_CORE_LOCAL_PWR_EN) != S5P_CORE_LOCAL_PWR_EN) {
|
|
||||||
if (timeout-- == 0)
|
if (timeout-- == 0)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -146,8 +169,18 @@ static int exynos_boot_secondary(unsigned int cpu, struct task_struct *idle)
|
|||||||
* Try to set boot address using firmware first
|
* Try to set boot address using firmware first
|
||||||
* and fall back to boot register if it fails.
|
* and fall back to boot register if it fails.
|
||||||
*/
|
*/
|
||||||
if (call_firmware_op(set_cpu_boot_addr, phys_cpu, boot_addr))
|
ret = call_firmware_op(set_cpu_boot_addr, phys_cpu, boot_addr);
|
||||||
|
if (ret && ret != -ENOSYS)
|
||||||
|
goto fail;
|
||||||
|
if (ret == -ENOSYS) {
|
||||||
|
void __iomem *boot_reg = cpu_boot_reg(phys_cpu);
|
||||||
|
|
||||||
|
if (IS_ERR(boot_reg)) {
|
||||||
|
ret = PTR_ERR(boot_reg);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
__raw_writel(boot_addr, cpu_boot_reg(phys_cpu));
|
__raw_writel(boot_addr, cpu_boot_reg(phys_cpu));
|
||||||
|
}
|
||||||
|
|
||||||
call_firmware_op(cpu_boot, phys_cpu);
|
call_firmware_op(cpu_boot, phys_cpu);
|
||||||
|
|
||||||
@ -163,9 +196,10 @@ static int exynos_boot_secondary(unsigned int cpu, struct task_struct *idle)
|
|||||||
* now the secondary core is starting up let it run its
|
* now the secondary core is starting up let it run its
|
||||||
* calibrations, then wait for it to finish
|
* calibrations, then wait for it to finish
|
||||||
*/
|
*/
|
||||||
|
fail:
|
||||||
spin_unlock(&boot_lock);
|
spin_unlock(&boot_lock);
|
||||||
|
|
||||||
return pen_release != -1 ? -ENOSYS : 0;
|
return pen_release != -1 ? ret : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -205,6 +239,8 @@ static void __init exynos_smp_prepare_cpus(unsigned int max_cpus)
|
|||||||
if (read_cpuid_part_number() == ARM_CPU_PART_CORTEX_A9)
|
if (read_cpuid_part_number() == ARM_CPU_PART_CORTEX_A9)
|
||||||
scu_enable(scu_base_addr());
|
scu_enable(scu_base_addr());
|
||||||
|
|
||||||
|
exynos_smp_prepare_sysram();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Write the address of secondary startup into the
|
* Write the address of secondary startup into the
|
||||||
* system-wide flags register. The boot monitor waits
|
* system-wide flags register. The boot monitor waits
|
||||||
@ -217,12 +253,21 @@ static void __init exynos_smp_prepare_cpus(unsigned int max_cpus)
|
|||||||
for (i = 1; i < max_cpus; ++i) {
|
for (i = 1; i < max_cpus; ++i) {
|
||||||
unsigned long phys_cpu;
|
unsigned long phys_cpu;
|
||||||
unsigned long boot_addr;
|
unsigned long boot_addr;
|
||||||
|
int ret;
|
||||||
|
|
||||||
phys_cpu = cpu_logical_map(i);
|
phys_cpu = cpu_logical_map(i);
|
||||||
boot_addr = virt_to_phys(exynos4_secondary_startup);
|
boot_addr = virt_to_phys(exynos4_secondary_startup);
|
||||||
|
|
||||||
if (call_firmware_op(set_cpu_boot_addr, phys_cpu, boot_addr))
|
ret = call_firmware_op(set_cpu_boot_addr, phys_cpu, boot_addr);
|
||||||
|
if (ret && ret != -ENOSYS)
|
||||||
|
break;
|
||||||
|
if (ret == -ENOSYS) {
|
||||||
|
void __iomem *boot_reg = cpu_boot_reg(phys_cpu);
|
||||||
|
|
||||||
|
if (IS_ERR(boot_reg))
|
||||||
|
break;
|
||||||
__raw_writel(boot_addr, cpu_boot_reg(phys_cpu));
|
__raw_writel(boot_addr, cpu_boot_reg(phys_cpu));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -100,6 +100,72 @@ static int exynos_irq_set_wake(struct irq_data *data, unsigned int state)
|
|||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* exynos_core_power_down : power down the specified cpu
|
||||||
|
* @cpu : the cpu to power down
|
||||||
|
*
|
||||||
|
* Power down the specified cpu. The sequence must be finished by a
|
||||||
|
* call to cpu_do_idle()
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void exynos_cpu_power_down(int cpu)
|
||||||
|
{
|
||||||
|
__raw_writel(0, EXYNOS_ARM_CORE_CONFIGURATION(cpu));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* exynos_cpu_power_up : power up the specified cpu
|
||||||
|
* @cpu : the cpu to power up
|
||||||
|
*
|
||||||
|
* Power up the specified cpu
|
||||||
|
*/
|
||||||
|
void exynos_cpu_power_up(int cpu)
|
||||||
|
{
|
||||||
|
__raw_writel(S5P_CORE_LOCAL_PWR_EN,
|
||||||
|
EXYNOS_ARM_CORE_CONFIGURATION(cpu));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* exynos_cpu_power_state : returns the power state of the cpu
|
||||||
|
* @cpu : the cpu to retrieve the power state from
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
int exynos_cpu_power_state(int cpu)
|
||||||
|
{
|
||||||
|
return (__raw_readl(EXYNOS_ARM_CORE_STATUS(cpu)) &
|
||||||
|
S5P_CORE_LOCAL_PWR_EN);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* exynos_cluster_power_down : power down the specified cluster
|
||||||
|
* @cluster : the cluster to power down
|
||||||
|
*/
|
||||||
|
void exynos_cluster_power_down(int cluster)
|
||||||
|
{
|
||||||
|
__raw_writel(0, EXYNOS_COMMON_CONFIGURATION(cluster));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* exynos_cluster_power_up : power up the specified cluster
|
||||||
|
* @cluster : the cluster to power up
|
||||||
|
*/
|
||||||
|
void exynos_cluster_power_up(int cluster)
|
||||||
|
{
|
||||||
|
__raw_writel(S5P_CORE_LOCAL_PWR_EN,
|
||||||
|
EXYNOS_COMMON_CONFIGURATION(cluster));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* exynos_cluster_power_state : returns the power state of the cluster
|
||||||
|
* @cluster : the cluster to retrieve the power state from
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
int exynos_cluster_power_state(int cluster)
|
||||||
|
{
|
||||||
|
return (__raw_readl(EXYNOS_COMMON_STATUS(cluster)) &
|
||||||
|
S5P_CORE_LOCAL_PWR_EN);
|
||||||
|
}
|
||||||
|
|
||||||
/* For Cortex-A9 Diagnostic and Power control register */
|
/* For Cortex-A9 Diagnostic and Power control register */
|
||||||
static unsigned int save_arm_register[2];
|
static unsigned int save_arm_register[2];
|
||||||
|
|
||||||
|
@ -38,6 +38,7 @@
|
|||||||
#define S5P_INFORM5 S5P_PMUREG(0x0814)
|
#define S5P_INFORM5 S5P_PMUREG(0x0814)
|
||||||
#define S5P_INFORM6 S5P_PMUREG(0x0818)
|
#define S5P_INFORM6 S5P_PMUREG(0x0818)
|
||||||
#define S5P_INFORM7 S5P_PMUREG(0x081C)
|
#define S5P_INFORM7 S5P_PMUREG(0x081C)
|
||||||
|
#define S5P_PMU_SPARE3 S5P_PMUREG(0x090C)
|
||||||
|
|
||||||
#define S5P_ARM_CORE0_LOWPWR S5P_PMUREG(0x1000)
|
#define S5P_ARM_CORE0_LOWPWR S5P_PMUREG(0x1000)
|
||||||
#define S5P_DIS_IRQ_CORE0 S5P_PMUREG(0x1004)
|
#define S5P_DIS_IRQ_CORE0 S5P_PMUREG(0x1004)
|
||||||
@ -105,8 +106,17 @@
|
|||||||
#define S5P_GPS_LOWPWR S5P_PMUREG(0x139C)
|
#define S5P_GPS_LOWPWR S5P_PMUREG(0x139C)
|
||||||
#define S5P_GPS_ALIVE_LOWPWR S5P_PMUREG(0x13A0)
|
#define S5P_GPS_ALIVE_LOWPWR S5P_PMUREG(0x13A0)
|
||||||
|
|
||||||
#define S5P_ARM_CORE1_CONFIGURATION S5P_PMUREG(0x2080)
|
#define EXYNOS_ARM_CORE0_CONFIGURATION S5P_PMUREG(0x2000)
|
||||||
#define S5P_ARM_CORE1_STATUS S5P_PMUREG(0x2084)
|
#define EXYNOS_ARM_CORE_CONFIGURATION(_nr) \
|
||||||
|
(EXYNOS_ARM_CORE0_CONFIGURATION + (0x80 * (_nr)))
|
||||||
|
#define EXYNOS_ARM_CORE_STATUS(_nr) \
|
||||||
|
(EXYNOS_ARM_CORE_CONFIGURATION(_nr) + 0x4)
|
||||||
|
|
||||||
|
#define EXYNOS_ARM_COMMON_CONFIGURATION S5P_PMUREG(0x2500)
|
||||||
|
#define EXYNOS_COMMON_CONFIGURATION(_nr) \
|
||||||
|
(EXYNOS_ARM_COMMON_CONFIGURATION + (0x80 * (_nr)))
|
||||||
|
#define EXYNOS_COMMON_STATUS(_nr) \
|
||||||
|
(EXYNOS_COMMON_CONFIGURATION(_nr) + 0x4)
|
||||||
|
|
||||||
#define S5P_PAD_RET_MAUDIO_OPTION S5P_PMUREG(0x3028)
|
#define S5P_PAD_RET_MAUDIO_OPTION S5P_PMUREG(0x3028)
|
||||||
#define S5P_PAD_RET_GPIO_OPTION S5P_PMUREG(0x3108)
|
#define S5P_PAD_RET_GPIO_OPTION S5P_PMUREG(0x3108)
|
||||||
@ -313,4 +323,6 @@
|
|||||||
|
|
||||||
#define EXYNOS5_OPTION_USE_RETENTION (1 << 4)
|
#define EXYNOS5_OPTION_USE_RETENTION (1 << 4)
|
||||||
|
|
||||||
|
#define EXYNOS5420_SWRESET_KFC_SEL 0x3
|
||||||
|
|
||||||
#endif /* __ASM_ARCH_REGS_PMU_H */
|
#endif /* __ASM_ARCH_REGS_PMU_H */
|
||||||
|
Loading…
Reference in New Issue
Block a user