From 9c869d1f07852b47ae8578c14161ec2821682464 Mon Sep 17 00:00:00 2001 From: Tomasz Stanislawski Date: Fri, 9 May 2014 05:55:42 +0900 Subject: ARM: dts: add missing pinctrls for I2C of exynos4 This patch adds missing pinctrls for I2C controllers 2-7. Signed-off-by: Tomasz Stanislawski Reviewed-by: Tomasz Figa Signed-off-by: Kukjin Kim --- arch/arm/boot/dts/exynos4.dtsi | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/arch/arm/boot/dts/exynos4.dtsi b/arch/arm/boot/dts/exynos4.dtsi index 2f8bcd068d17..a2302b55e9e5 100644 --- a/arch/arm/boot/dts/exynos4.dtsi +++ b/arch/arm/boot/dts/exynos4.dtsi @@ -371,6 +371,8 @@ interrupts = <0 60 0>; clocks = <&clock CLK_I2C2>; clock-names = "i2c"; + pinctrl-names = "default"; + pinctrl-0 = <&i2c2_bus>; status = "disabled"; }; @@ -382,6 +384,8 @@ interrupts = <0 61 0>; clocks = <&clock CLK_I2C3>; clock-names = "i2c"; + pinctrl-names = "default"; + pinctrl-0 = <&i2c3_bus>; status = "disabled"; }; @@ -393,6 +397,8 @@ interrupts = <0 62 0>; clocks = <&clock CLK_I2C4>; clock-names = "i2c"; + pinctrl-names = "default"; + pinctrl-0 = <&i2c4_bus>; status = "disabled"; }; @@ -404,6 +410,8 @@ interrupts = <0 63 0>; clocks = <&clock CLK_I2C5>; clock-names = "i2c"; + pinctrl-names = "default"; + pinctrl-0 = <&i2c5_bus>; status = "disabled"; }; @@ -415,6 +423,8 @@ interrupts = <0 64 0>; clocks = <&clock CLK_I2C6>; clock-names = "i2c"; + pinctrl-names = "default"; + pinctrl-0 = <&i2c6_bus>; status = "disabled"; }; @@ -426,6 +436,8 @@ interrupts = <0 65 0>; clocks = <&clock CLK_I2C7>; clock-names = "i2c"; + pinctrl-names = "default"; + pinctrl-0 = <&i2c7_bus>; status = "disabled"; }; -- cgit v1.2.3 From 6af2ba90818f9e9c4b8711e1f896e797c5da151c Mon Sep 17 00:00:00 2001 From: Tomasz Stanislawski Date: Fri, 9 May 2014 05:58:59 +0900 Subject: ARM: dts: rename alias for i2c_ak8975 label for exynos4412-trats2 The i2c_ak8975 controller uses label i2c8. This alias is already used for I2C controller 8 defined in file arch/arm/boot/dts/exynos4.dtsi. This patch renames a label for i2c_ak8975 to i2c9. Signed-off-by: Tomasz Stanislawski Reviewed-by: Tomasz Figa Signed-off-by: Kukjin Kim --- arch/arm/boot/dts/exynos4412-trats2.dts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/exynos4412-trats2.dts b/arch/arm/boot/dts/exynos4412-trats2.dts index 9583563dd0ef..a61fa7e3168b 100644 --- a/arch/arm/boot/dts/exynos4412-trats2.dts +++ b/arch/arm/boot/dts/exynos4412-trats2.dts @@ -20,7 +20,7 @@ compatible = "samsung,trats2", "samsung,exynos4412", "samsung,exynos4"; aliases { - i2c8 = &i2c_ak8975; + i2c9 = &i2c_ak8975; }; memory { -- cgit v1.2.3 From ee5eda64af051097c00534db7c5432c4a061d355 Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Fri, 9 May 2014 06:00:35 +0900 Subject: ARM: dts: Update camera nodes for exynos4 and exynos4412-trats2 Remove unused /camera/clock-controller node and add required clock properties to the camera node. This is required for a clock provider that will be referenced by image sensor devices. Also add required clock related changes to s5k6a3 device node and afvdd regulator supply. Signed-off-by: Sylwester Nawrocki Acked-by: Kyungmin Park Signed-off-by: Kukjin Kim --- arch/arm/boot/dts/exynos4.dtsi | 6 ++---- arch/arm/boot/dts/exynos4412-trats2.dts | 5 +++-- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/arch/arm/boot/dts/exynos4.dtsi b/arch/arm/boot/dts/exynos4.dtsi index a2302b55e9e5..58ff8e28c74f 100644 --- a/arch/arm/boot/dts/exynos4.dtsi +++ b/arch/arm/boot/dts/exynos4.dtsi @@ -129,12 +129,10 @@ status = "disabled"; #address-cells = <1>; #size-cells = <1>; + #clock-cells = <1>; + clock-output-names = "cam_a_clkout", "cam_b_clkout"; ranges; - clock_cam: clock-controller { - #clock-cells = <1>; - }; - fimc_0: fimc@11800000 { compatible = "samsung,exynos4210-fimc"; reg = <0x11800000 0x1000>; diff --git a/arch/arm/boot/dts/exynos4412-trats2.dts b/arch/arm/boot/dts/exynos4412-trats2.dts index a61fa7e3168b..cf0e11037729 100644 --- a/arch/arm/boot/dts/exynos4412-trats2.dts +++ b/arch/arm/boot/dts/exynos4412-trats2.dts @@ -647,10 +647,11 @@ reg = <0x10>; svdda-supply = <&cam_io_reg>; svddio-supply = <&ldo19_reg>; + afvdd-supply = <&ldo19_reg>; clock-frequency = <24000000>; /* CAM_B_CLKOUT */ - clocks = <&clock_cam 1>; - clock-names = "mclk"; + clocks = <&camera 1>; + clock-names = "extclk"; samsung,camclk-out = <1>; gpios = <&gpm1 6 0>; -- cgit v1.2.3 From 4cb378646ef85e76745225912025871f3dc93ca3 Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Fri, 9 May 2014 06:01:40 +0900 Subject: ARM: dts: Add rear camera nodes for exynos4412-trats2 This patch enables the rear facing camera (s5c73m3) on TRATS2 board by adding the I2C0 bus controller, s5c73m3 sensor, MIPI CSI-2 receiver and the sensor's voltage regulator supply nodes. Signed-off-by: Andrzej Hajda Acked-by: Kyungmin Park Signed-off-by: Sylwester Nawrocki Signed-off-by: Kukjin Kim --- arch/arm/boot/dts/exynos4412-trats2.dts | 72 +++++++++++++++++++++++++++++++-- 1 file changed, 69 insertions(+), 3 deletions(-) diff --git a/arch/arm/boot/dts/exynos4412-trats2.dts b/arch/arm/boot/dts/exynos4412-trats2.dts index cf0e11037729..f621fd976815 100644 --- a/arch/arm/boot/dts/exynos4412-trats2.dts +++ b/arch/arm/boot/dts/exynos4412-trats2.dts @@ -80,7 +80,24 @@ 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 { @@ -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 { samsung,i2c-sda-delay = <100>; samsung,i2c-slave-addr = <0x10>; @@ -586,8 +635,8 @@ status = "okay"; }; - camera { - pinctrl-0 = <&cam_port_b_clk_active>; + camera: camera { + pinctrl-0 = <&cam_port_a_clk_active &cam_port_b_clk_active>; pinctrl-names = "default"; status = "okay"; @@ -607,6 +656,23 @@ 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 { vddcore-supply = <&ldo8_reg>; vddio-supply = <&ldo10_reg>; -- cgit v1.2.3 From c4539e88e758901c298ee1f6c0e19471be693f54 Mon Sep 17 00:00:00 2001 From: Arun Kumar K Date: Fri, 9 May 2014 06:06:10 +0900 Subject: ARM: dts: Add pwmX_out pinctrl nodes to exynos5420 Adds the PWM nodes to 5420 pinctrl dtsi file. Signed-off-by: Arun Kumar K Reviewed-by: Doug Anderson Reviewed-by: Tomasz Figa Signed-off-by: Kukjin Kim --- arch/arm/boot/dts/exynos5420-pinctrl.dtsi | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/arch/arm/boot/dts/exynos5420-pinctrl.dtsi b/arch/arm/boot/dts/exynos5420-pinctrl.dtsi index e62c8eb57438..ba686e40eac7 100644 --- a/arch/arm/boot/dts/exynos5420-pinctrl.dtsi +++ b/arch/arm/boot/dts/exynos5420-pinctrl.dtsi @@ -624,6 +624,34 @@ 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 { samsung,pins = "gpb2-2", "gpb2-3"; samsung,pin-function = <3>; -- cgit v1.2.3 From 8e371a91d98e8d8d032c6032eb0ac6e2bbcb231f Mon Sep 17 00:00:00 2001 From: Arun Kumar K Date: Fri, 9 May 2014 06:06:24 +0900 Subject: ARM: dts: Add node labels to exynos5420 Adding labels to nodes which do not have it yet in exynos5420. This is done so as to use reference based node updation in board files. Signed-off-by: Arun Kumar K Reviewed-by: Tomasz Figa Reviewed-by: Doug Anderson Signed-off-by: Kukjin Kim --- arch/arm/boot/dts/exynos5420.dtsi | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/arch/arm/boot/dts/exynos5420.dtsi b/arch/arm/boot/dts/exynos5420.dtsi index c3a9a66c5767..0d1dea81af0c 100644 --- a/arch/arm/boot/dts/exynos5420.dtsi +++ b/arch/arm/boot/dts/exynos5420.dtsi @@ -125,7 +125,7 @@ clock-names = "pll_ref", "pll_in", "sclk_audio", "sclk_pcm_in"; }; - codec@11000000 { + mfc: codec@11000000 { compatible = "samsung,mfc-v7"; reg = <0x11000000 0x10000>; interrupts = <0 96 0>; @@ -169,7 +169,7 @@ status = "disabled"; }; - mct@101C0000 { + mct: mct@101C0000 { compatible = "samsung,exynos4210-mct"; reg = <0x101C0000 0x800>; interrupt-controller; @@ -270,7 +270,7 @@ interrupts = <0 47 0>; }; - rtc@101E0000 { + rtc: rtc@101E0000 { clocks = <&clock CLK_RTC>; clock-names = "rtc"; status = "disabled"; @@ -430,22 +430,22 @@ status = "disabled"; }; - serial@12C00000 { + uart_0: serial@12C00000 { clocks = <&clock CLK_UART0>, <&clock CLK_SCLK_UART0>; clock-names = "uart", "clk_uart_baud0"; }; - serial@12C10000 { + uart_1: serial@12C10000 { clocks = <&clock CLK_UART1>, <&clock CLK_SCLK_UART1>; clock-names = "uart", "clk_uart_baud0"; }; - serial@12C20000 { + uart_2: serial@12C20000 { clocks = <&clock CLK_UART2>, <&clock CLK_SCLK_UART2>; clock-names = "uart", "clk_uart_baud0"; }; - serial@12C30000 { + uart_3: serial@12C30000 { clocks = <&clock CLK_UART3>, <&clock CLK_SCLK_UART3>; clock-names = "uart", "clk_uart_baud0"; }; @@ -465,14 +465,14 @@ #phy-cells = <0>; }; - dp-controller@145B0000 { + dp: dp-controller@145B0000 { clocks = <&clock CLK_DP1>; clock-names = "dp"; phys = <&dp_phy>; phy-names = "dp"; }; - fimd@14400000 { + fimd: fimd@14400000 { samsung,power-domain = <&disp_pd>; clocks = <&clock CLK_SCLK_FIMD1>, <&clock CLK_FIMD1>; clock-names = "sclk_fimd", "fimd"; @@ -632,7 +632,7 @@ status = "disabled"; }; - hdmi@14530000 { + hdmi: hdmi@14530000 { compatible = "samsung,exynos4212-hdmi"; reg = <0x14530000 0x70000>; interrupts = <0 95 0>; @@ -644,7 +644,7 @@ status = "disabled"; }; - mixer@14450000 { + mixer: mixer@14450000 { compatible = "samsung,exynos5420-mixer"; reg = <0x14450000 0x10000>; interrupts = <0 94 0>; @@ -715,7 +715,7 @@ clock-names = "tmu_apbif", "tmu_triminfo_apbif"; }; - watchdog@101D0000 { + watchdog: watchdog@101D0000 { compatible = "samsung,exynos5420-wdt"; reg = <0x101D0000 0x100>; interrupts = <0 42 0>; @@ -724,7 +724,7 @@ samsung,syscon-phandle = <&pmu_system_controller>; }; - sss@10830000 { + sss: sss@10830000 { compatible = "samsung,exynos4210-secss"; reg = <0x10830000 0x10000>; interrupts = <0 112 0>; -- cgit v1.2.3 From 3528dd34b2d3dc642669fd12399e18a16e3aacc8 Mon Sep 17 00:00:00 2001 From: Arun Kumar K Date: Fri, 9 May 2014 06:06:25 +0900 Subject: ARM: dts: Add exynos5420 peach-pit board support Adds the google peach-pit board dts file which uses exynos5420 SoC. Signed-off-by: Arun Kumar K Signed-off-by: Doug Anderson Reviewed-by: Doug Anderson Signed-off-by: Kukjin Kim --- arch/arm/boot/dts/Makefile | 1 + arch/arm/boot/dts/exynos5420-peach-pit.dts | 147 +++++++++++++++++++++++++++++ 2 files changed, 148 insertions(+) create mode 100644 arch/arm/boot/dts/exynos5420-peach-pit.dts diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index 35c146f31e46..3220e2968352 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -74,6 +74,7 @@ dtb-$(CONFIG_ARCH_EXYNOS) += exynos4210-origen.dtb \ exynos5250-smdk5250.dtb \ exynos5250-snow.dtb \ exynos5420-arndale-octa.dtb \ + exynos5420-peach-pit.dtb \ exynos5420-smdk5420.dtb \ exynos5440-sd5v1.dtb \ exynos5440-ssdk5440.dtb diff --git a/arch/arm/boot/dts/exynos5420-peach-pit.dts b/arch/arm/boot/dts/exynos5420-peach-pit.dts new file mode 100644 index 000000000000..fae33dddac39 --- /dev/null +++ b/arch/arm/boot/dts/exynos5420-peach-pit.dts @@ -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 +#include +#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 = ; + 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>; +}; -- cgit v1.2.3 From b3205dea8fbf6db9b1e46a0dad19a0712fdff44f Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Tue, 13 May 2014 07:13:44 +0900 Subject: ARM: EXYNOS: Map SYSRAM through generic DT bindings Instead of hardcoding the SYSRAM details for each SoC, pass this information through device tree (DT) and make the code SoC agnostic. Generic DT SRAM bindings are used for achieving this. Signed-off-by: Sachin Kamat Acked-by: Arnd Bergmann Acked-by: Heiko Stuebner Reviewed-by: Tomasz Figa Signed-off-by: Kukjin Kim --- arch/arm/Kconfig | 1 + arch/arm/boot/dts/exynos4210-universal_c210.dts | 15 ++++++ arch/arm/boot/dts/exynos4210.dtsi | 18 +++++++ arch/arm/boot/dts/exynos4x12.dtsi | 18 +++++++ arch/arm/boot/dts/exynos5250.dtsi | 18 +++++++ arch/arm/boot/dts/exynos5420.dtsi | 18 +++++++ arch/arm/mach-exynos/common.h | 1 + arch/arm/mach-exynos/exynos.c | 64 ------------------------- arch/arm/mach-exynos/firmware.c | 8 +++- arch/arm/mach-exynos/include/mach/map.h | 7 --- arch/arm/mach-exynos/platsmp.c | 56 ++++++++++++++++++++-- 11 files changed, 148 insertions(+), 76 deletions(-) diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index ab438cb5af55..19ffaaed971e 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -843,6 +843,7 @@ config ARCH_EXYNOS select HAVE_S3C_RTC if RTC_CLASS select NEED_MACH_MEMORY_H select SPARSE_IRQ + select SRAM select USE_OF help Support for SAMSUNG's EXYNOS SoCs (EXYNOS4/5) diff --git a/arch/arm/boot/dts/exynos4210-universal_c210.dts b/arch/arm/boot/dts/exynos4210-universal_c210.dts index 63e34b24b04f..9296dee10e26 100644 --- a/arch/arm/boot/dts/exynos4210-universal_c210.dts +++ b/arch/arm/boot/dts/exynos4210-universal_c210.dts @@ -28,6 +28,21 @@ 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 { compatible = "none"; }; diff --git a/arch/arm/boot/dts/exynos4210.dtsi b/arch/arm/boot/dts/exynos4210.dtsi index cacf6140dd2f..ee3001f38821 100644 --- a/arch/arm/boot/dts/exynos4210.dtsi +++ b/arch/arm/boot/dts/exynos4210.dtsi @@ -31,6 +31,24 @@ 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 { compatible = "samsung,exynos4210-pd"; reg = <0x10023CA0 0x20>; diff --git a/arch/arm/boot/dts/exynos4x12.dtsi b/arch/arm/boot/dts/exynos4x12.dtsi index c4a9306f8529..70e3765b51ee 100644 --- a/arch/arm/boot/dts/exynos4x12.dtsi +++ b/arch/arm/boot/dts/exynos4x12.dtsi @@ -37,6 +37,24 @@ 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 { compatible = "samsung,exynos4210-pd"; reg = <0x10023CA0 0x20>; diff --git a/arch/arm/boot/dts/exynos5250.dtsi b/arch/arm/boot/dts/exynos5250.dtsi index 37423314a028..e44693e2cfda 100644 --- a/arch/arm/boot/dts/exynos5250.dtsi +++ b/arch/arm/boot/dts/exynos5250.dtsi @@ -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 { compatible = "samsung,exynos4210-pd"; reg = <0x10044000 0x20>; diff --git a/arch/arm/boot/dts/exynos5420.dtsi b/arch/arm/boot/dts/exynos5420.dtsi index 0d1dea81af0c..3f34196d394e 100644 --- a/arch/arm/boot/dts/exynos5420.dtsi +++ b/arch/arm/boot/dts/exynos5420.dtsi @@ -110,6 +110,24 @@ }; }; + 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>; + }; + }; + clock: clock-controller@10010000 { compatible = "samsung,exynos5420-clock"; reg = <0x10010000 0x30000>; diff --git a/arch/arm/mach-exynos/common.h b/arch/arm/mach-exynos/common.h index 9ef3f83efaff..963c51fb606c 100644 --- a/arch/arm/mach-exynos/common.h +++ b/arch/arm/mach-exynos/common.h @@ -18,6 +18,7 @@ void mct_init(void __iomem *base, int irq_g0, int irq_l0, int irq_l1); struct map_desc; +extern void __iomem *sysram_ns_base_addr; void exynos_init_io(void); void exynos_restart(enum reboot_mode mode, const char *cmd); void exynos_cpuidle_init(void); diff --git a/arch/arm/mach-exynos/exynos.c b/arch/arm/mach-exynos/exynos.c index b32a907d021d..e973ff5de7b3 100644 --- a/arch/arm/mach-exynos/exynos.c +++ b/arch/arm/mach-exynos/exynos.c @@ -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 = { { .virtual = (unsigned long)S3C_VA_SYS, @@ -180,11 +135,6 @@ static struct map_desc exynos5_iodesc[] __initdata = { .pfn = __phys_to_pfn(EXYNOS5_PA_SROMC), .length = SZ_4K, .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, .pfn = __phys_to_pfn(EXYNOS5_PA_CMU), @@ -280,20 +230,6 @@ static void __init exynos_map_io(void) if (soc_is_exynos5()) 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) diff --git a/arch/arm/mach-exynos/firmware.c b/arch/arm/mach-exynos/firmware.c index 932129ef26c6..483dfcd69065 100644 --- a/arch/arm/mach-exynos/firmware.c +++ b/arch/arm/mach-exynos/firmware.c @@ -18,6 +18,7 @@ #include +#include "common.h" #include "smc.h" 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) { - 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); return 0; diff --git a/arch/arm/mach-exynos/include/mach/map.h b/arch/arm/mach-exynos/include/mach/map.h index 7b046b59d9ec..548269a60634 100644 --- a/arch/arm/mach-exynos/include/mach/map.h +++ b/arch/arm/mach-exynos/include/mach/map.h @@ -23,13 +23,6 @@ #include -#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 EXYNOS4_PA_SYSCON 0x10010000 diff --git a/arch/arm/mach-exynos/platsmp.c b/arch/arm/mach-exynos/platsmp.c index 03e5e9f94705..c11c5418e0fc 100644 --- a/arch/arm/mach-exynos/platsmp.c +++ b/arch/arm/mach-exynos/platsmp.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -33,11 +34,33 @@ 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) { if (soc_is_exynos4210() && samsung_rev() == EXYNOS4210_REV_1_1) return S5P_INFORM5; - return S5P_VA_SYSRAM; + return sysram_base_addr; } 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; boot_reg = cpu_boot_reg_base(); + if (!boot_reg) + return ERR_PTR(-ENODEV); if (soc_is_exynos4412()) boot_reg += 4*cpu; 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 phys_cpu = cpu_logical_map(cpu); + int ret = -ENOSYS; /* * Set synchronisation state between this boot processor @@ -146,8 +172,18 @@ static int exynos_boot_secondary(unsigned int cpu, struct task_struct *idle) * Try to set boot address using firmware first * 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)); + } call_firmware_op(cpu_boot, phys_cpu); @@ -163,9 +199,10 @@ static int exynos_boot_secondary(unsigned int cpu, struct task_struct *idle) * now the secondary core is starting up let it run its * calibrations, then wait for it to finish */ +fail: spin_unlock(&boot_lock); - return pen_release != -1 ? -ENOSYS : 0; + return pen_release != -1 ? ret : 0; } /* @@ -205,6 +242,8 @@ static void __init exynos_smp_prepare_cpus(unsigned int max_cpus) if (read_cpuid_part_number() == ARM_CPU_PART_CORTEX_A9) scu_enable(scu_base_addr()); + exynos_smp_prepare_sysram(); + /* * Write the address of secondary startup into the * system-wide flags register. The boot monitor waits @@ -217,12 +256,21 @@ static void __init exynos_smp_prepare_cpus(unsigned int max_cpus) for (i = 1; i < max_cpus; ++i) { unsigned long phys_cpu; unsigned long boot_addr; + int ret; phys_cpu = cpu_logical_map(i); 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)); + } } } -- cgit v1.2.3 From d7067f1c5fa0232001502569c6878d22308da268 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Tue, 13 May 2014 07:13:47 +0900 Subject: devicetree: bindings: document SYSRAM binding Add SRAM binding documentation. Signed-off-by: Sachin Kamat Acked-by: Arnd Bergmann Reviewed-by: Tomasz Figa [kgene.kim@samsung.com: changed name SRAM to SYSRAM] Signed-off-by: Kukjin Kim --- .../devicetree/bindings/arm/exynos/smp-sysram.txt | 38 ++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 Documentation/devicetree/bindings/arm/exynos/smp-sysram.txt diff --git a/Documentation/devicetree/bindings/arm/exynos/smp-sysram.txt b/Documentation/devicetree/bindings/arm/exynos/smp-sysram.txt new file mode 100644 index 000000000000..4a0a4f70a0ce --- /dev/null +++ b/Documentation/devicetree/bindings/arm/exynos/smp-sysram.txt @@ -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>; + }; + }; -- cgit v1.2.3 From d3af6976a24f8cebef23e72ade6d91ddd781c12b Mon Sep 17 00:00:00 2001 From: Leela Krishna Amudala Date: Fri, 16 May 2014 04:23:24 +0900 Subject: ARM: EXYNOS: Add generic cpu power control functions for exynos SoCs Add generic cpu power control functions for exynos based SoCS for cpu power up/down and to know the cpu status. Signed-off-by: Leela Krishna Amudala Signed-off-by: Abhilash Kesavan Signed-off-by: Kukjin Kim --- arch/arm/mach-exynos/common.h | 3 +++ arch/arm/mach-exynos/pm.c | 36 ++++++++++++++++++++++++++++++++++++ arch/arm/mach-exynos/regs-pmu.h | 6 ++++++ 3 files changed, 45 insertions(+) diff --git a/arch/arm/mach-exynos/common.h b/arch/arm/mach-exynos/common.h index 963c51fb606c..4d815a511bc1 100644 --- a/arch/arm/mach-exynos/common.h +++ b/arch/arm/mach-exynos/common.h @@ -63,5 +63,8 @@ struct exynos_pmu_conf { }; 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); #endif /* __ARCH_ARM_MACH_EXYNOS_COMMON_H */ diff --git a/arch/arm/mach-exynos/pm.c b/arch/arm/mach-exynos/pm.c index 15af0ceb0a66..cbfe23598236 100644 --- a/arch/arm/mach-exynos/pm.c +++ b/arch/arm/mach-exynos/pm.c @@ -100,6 +100,42 @@ static int exynos_irq_set_wake(struct irq_data *data, unsigned int state) 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); +} + /* For Cortex-A9 Diagnostic and Power control register */ static unsigned int save_arm_register[2]; diff --git a/arch/arm/mach-exynos/regs-pmu.h b/arch/arm/mach-exynos/regs-pmu.h index 4f6a2560d022..84634ac5b127 100644 --- a/arch/arm/mach-exynos/regs-pmu.h +++ b/arch/arm/mach-exynos/regs-pmu.h @@ -105,6 +105,12 @@ #define S5P_GPS_LOWPWR S5P_PMUREG(0x139C) #define S5P_GPS_ALIVE_LOWPWR S5P_PMUREG(0x13A0) +#define EXYNOS_ARM_CORE0_CONFIGURATION S5P_PMUREG(0x2000) +#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 S5P_ARM_CORE1_CONFIGURATION S5P_PMUREG(0x2080) #define S5P_ARM_CORE1_STATUS S5P_PMUREG(0x2084) -- cgit v1.2.3 From 664ba4430156c224b184692ab1a038a467c7826c Mon Sep 17 00:00:00 2001 From: Leela Krishna Amudala Date: Fri, 16 May 2014 04:23:25 +0900 Subject: ARM: EXYNOS: use generic exynos cpu power control functions Use generic exynos cpu power control functions to power up/down and to know the status of the cpu in platsmp and hotplug code. Signed-off-by: Leela Krishna Amudala Signed-off-by: Abhilash Kesavan Signed-off-by: Kukjin Kim --- arch/arm/mach-exynos/hotplug.c | 2 +- arch/arm/mach-exynos/platsmp.c | 9 +++------ arch/arm/mach-exynos/regs-pmu.h | 3 --- 3 files changed, 4 insertions(+), 10 deletions(-) diff --git a/arch/arm/mach-exynos/hotplug.c b/arch/arm/mach-exynos/hotplug.c index 5eead530c6f8..609c99ca59c4 100644 --- a/arch/arm/mach-exynos/hotplug.c +++ b/arch/arm/mach-exynos/hotplug.c @@ -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 */ if (cpu == 1) - __raw_writel(0, S5P_ARM_CORE1_CONFIGURATION); + exynos_cpu_power_down(cpu); /* * here's the WFI diff --git a/arch/arm/mach-exynos/platsmp.c b/arch/arm/mach-exynos/platsmp.c index c11c5418e0fc..78002c7344b3 100644 --- a/arch/arm/mach-exynos/platsmp.c +++ b/arch/arm/mach-exynos/platsmp.c @@ -133,15 +133,12 @@ static int exynos_boot_secondary(unsigned int cpu, struct task_struct *idle) */ write_pen_release(phys_cpu); - if (!(__raw_readl(S5P_ARM_CORE1_STATUS) & S5P_CORE_LOCAL_PWR_EN)) { - __raw_writel(S5P_CORE_LOCAL_PWR_EN, - S5P_ARM_CORE1_CONFIGURATION); - + if (!exynos_cpu_power_state(cpu)) { + exynos_cpu_power_up(cpu); timeout = 10; /* wait max 10 ms until cpu1 is on */ - while ((__raw_readl(S5P_ARM_CORE1_STATUS) - & S5P_CORE_LOCAL_PWR_EN) != S5P_CORE_LOCAL_PWR_EN) { + while (exynos_cpu_power_state(cpu) != S5P_CORE_LOCAL_PWR_EN) { if (timeout-- == 0) break; diff --git a/arch/arm/mach-exynos/regs-pmu.h b/arch/arm/mach-exynos/regs-pmu.h index 84634ac5b127..98fb8d8715e6 100644 --- a/arch/arm/mach-exynos/regs-pmu.h +++ b/arch/arm/mach-exynos/regs-pmu.h @@ -111,9 +111,6 @@ #define EXYNOS_ARM_CORE_STATUS(_nr) \ (EXYNOS_ARM_CORE_CONFIGURATION(_nr) + 0x4) -#define S5P_ARM_CORE1_CONFIGURATION S5P_PMUREG(0x2080) -#define S5P_ARM_CORE1_STATUS S5P_PMUREG(0x2084) - #define S5P_PAD_RET_MAUDIO_OPTION S5P_PMUREG(0x3028) #define S5P_PAD_RET_GPIO_OPTION S5P_PMUREG(0x3108) #define S5P_PAD_RET_UART_OPTION S5P_PMUREG(0x3128) -- cgit v1.2.3 From 096d21c6ebd01b3440d1e6063e646d9db8e31ac9 Mon Sep 17 00:00:00 2001 From: Abhilash Kesavan Date: Fri, 16 May 2014 04:23:26 +0900 Subject: ARM: EXYNOS: Add generic cluster power control functions Add generic cluster power control functions for exynos based SoCS for cluster power up/down and to know the cluster status. Signed-off-by: Abhilash Kesavan Signed-off-by: Kukjin Kim --- arch/arm/mach-exynos/common.h | 3 +++ arch/arm/mach-exynos/pm.c | 30 ++++++++++++++++++++++++++++++ arch/arm/mach-exynos/regs-pmu.h | 6 ++++++ 3 files changed, 39 insertions(+) diff --git a/arch/arm/mach-exynos/common.h b/arch/arm/mach-exynos/common.h index 4d815a511bc1..7876ed04b7a5 100644 --- a/arch/arm/mach-exynos/common.h +++ b/arch/arm/mach-exynos/common.h @@ -66,5 +66,8 @@ 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 */ diff --git a/arch/arm/mach-exynos/pm.c b/arch/arm/mach-exynos/pm.c index cbfe23598236..3f2ae864582e 100644 --- a/arch/arm/mach-exynos/pm.c +++ b/arch/arm/mach-exynos/pm.c @@ -136,6 +136,36 @@ int exynos_cpu_power_state(int 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 */ static unsigned int save_arm_register[2]; diff --git a/arch/arm/mach-exynos/regs-pmu.h b/arch/arm/mach-exynos/regs-pmu.h index 98fb8d8715e6..f6b68a327586 100644 --- a/arch/arm/mach-exynos/regs-pmu.h +++ b/arch/arm/mach-exynos/regs-pmu.h @@ -111,6 +111,12 @@ #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_GPIO_OPTION S5P_PMUREG(0x3108) #define S5P_PAD_RET_UART_OPTION S5P_PMUREG(0x3128) -- cgit v1.2.3 From 5b56642bd8d8d8e5015603704568902c0f18bca1 Mon Sep 17 00:00:00 2001 From: Andrew Bresticker Date: Fri, 16 May 2014 04:23:26 +0900 Subject: ARM: dts: add CCI node for exynos5420 Add device-tree bindings for the ARM CCI-400 on Exynos5420. There are two slave interfaces: one for the A15 cluster and one for the A7 cluster. Signed-off-by: Andrew Bresticker Signed-off-by: Abhilash Kesavan Signed-off-by: Kukjin Kim --- arch/arm/boot/dts/exynos5420.dtsi | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/arch/arm/boot/dts/exynos5420.dtsi b/arch/arm/boot/dts/exynos5420.dtsi index 3f34196d394e..00d541a1a3d4 100644 --- a/arch/arm/boot/dts/exynos5420.dtsi +++ b/arch/arm/boot/dts/exynos5420.dtsi @@ -58,6 +58,7 @@ compatible = "arm,cortex-a15"; reg = <0x0>; clock-frequency = <1800000000>; + cci-control-port = <&cci_control1>; }; cpu1: cpu@1 { @@ -65,6 +66,7 @@ compatible = "arm,cortex-a15"; reg = <0x1>; clock-frequency = <1800000000>; + cci-control-port = <&cci_control1>; }; cpu2: cpu@2 { @@ -72,6 +74,7 @@ compatible = "arm,cortex-a15"; reg = <0x2>; clock-frequency = <1800000000>; + cci-control-port = <&cci_control1>; }; cpu3: cpu@3 { @@ -79,6 +82,7 @@ compatible = "arm,cortex-a15"; reg = <0x3>; clock-frequency = <1800000000>; + cci-control-port = <&cci_control1>; }; cpu4: cpu@100 { @@ -86,6 +90,7 @@ compatible = "arm,cortex-a7"; reg = <0x100>; clock-frequency = <1000000000>; + cci-control-port = <&cci_control0>; }; cpu5: cpu@101 { @@ -93,6 +98,7 @@ compatible = "arm,cortex-a7"; reg = <0x101>; clock-frequency = <1000000000>; + cci-control-port = <&cci_control0>; }; cpu6: cpu@102 { @@ -100,6 +106,7 @@ compatible = "arm,cortex-a7"; reg = <0x102>; clock-frequency = <1000000000>; + cci-control-port = <&cci_control0>; }; cpu7: cpu@103 { @@ -107,6 +114,26 @@ compatible = "arm,cortex-a7"; reg = <0x103>; 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>; }; }; -- cgit v1.2.3 From ccf5511797cd4b48d20a85fa1778f5608eac9fd7 Mon Sep 17 00:00:00 2001 From: Abhilash Kesavan Date: Fri, 16 May 2014 04:26:30 +0900 Subject: ARM: EXYNOS: Add MCPM call-back functions Add machine-dependent MCPM call-backs for Exynos5420. These are used to power up/down the secondary CPUs during boot, shutdown, s2r and switching. Signed-off-by: Thomas Abraham Signed-off-by: Inderpal Singh Signed-off-by: Andrew Bresticker Signed-off-by: Abhilash Kesavan Reviewed-by: Nicolas Pitre Signed-off-by: Kukjin Kim --- arch/arm/mach-exynos/Kconfig | 8 + arch/arm/mach-exynos/Makefile | 2 + arch/arm/mach-exynos/mcpm-exynos.c | 351 +++++++++++++++++++++++++++++++++++++ arch/arm/mach-exynos/regs-pmu.h | 3 + 4 files changed, 364 insertions(+) create mode 100644 arch/arm/mach-exynos/mcpm-exynos.c diff --git a/arch/arm/mach-exynos/Kconfig b/arch/arm/mach-exynos/Kconfig index fc8bf18e222d..1602abce6ec0 100644 --- a/arch/arm/mach-exynos/Kconfig +++ b/arch/arm/mach-exynos/Kconfig @@ -110,4 +110,12 @@ config SOC_EXYNOS5440 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 diff --git a/arch/arm/mach-exynos/Makefile b/arch/arm/mach-exynos/Makefile index a656dbe3b78c..01bc9b94a032 100644 --- a/arch/arm/mach-exynos/Makefile +++ b/arch/arm/mach-exynos/Makefile @@ -29,3 +29,5 @@ obj-$(CONFIG_ARCH_EXYNOS) += firmware.o plus_sec := $(call as-instr,.arch_extension sec,+sec) AFLAGS_exynos-smc.o :=-Wa,-march=armv7-a$(plus_sec) + +obj-$(CONFIG_EXYNOS5420_MCPM) += mcpm-exynos.o diff --git a/arch/arm/mach-exynos/mcpm-exynos.c b/arch/arm/mach-exynos/mcpm-exynos.c new file mode 100644 index 000000000000..1ac618ce440b --- /dev/null +++ b/arch/arm/mach-exynos/mcpm-exynos.c @@ -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 +#include +#include +#include + +#include +#include +#include + +#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); diff --git a/arch/arm/mach-exynos/regs-pmu.h b/arch/arm/mach-exynos/regs-pmu.h index f6b68a327586..4179f6a6d595 100644 --- a/arch/arm/mach-exynos/regs-pmu.h +++ b/arch/arm/mach-exynos/regs-pmu.h @@ -38,6 +38,7 @@ #define S5P_INFORM5 S5P_PMUREG(0x0814) #define S5P_INFORM6 S5P_PMUREG(0x0818) #define S5P_INFORM7 S5P_PMUREG(0x081C) +#define S5P_PMU_SPARE3 S5P_PMUREG(0x090C) #define S5P_ARM_CORE0_LOWPWR S5P_PMUREG(0x1000) #define S5P_DIS_IRQ_CORE0 S5P_PMUREG(0x1004) @@ -322,4 +323,6 @@ #define EXYNOS5_OPTION_USE_RETENTION (1 << 4) +#define EXYNOS5420_SWRESET_KFC_SEL 0x3 + #endif /* __ASM_ARCH_REGS_PMU_H */ -- cgit v1.2.3