2013-10-14 15:11:37

by Vyacheslav Tyrtov

[permalink] [raw]
Subject: [PATCH v2 0/4] Exynos 5410 Dual cluster support

The series of patches represent support of Exynos 5410 SoC

The Exynos 5410 is the first Samsung SoC based on bigLITTLE architecture.
Patches allow all 8 CPU cores (4 x A7 and 4 x A15) to run at the same time

Patches add new platform description, support of clock controller,
dual cluster support and device tree for Exynos 5410

Has been build on v3.12-rc5.
Has been tested on Exynos 5410 reference board (exynos_defconfig).

Thanks,
Vyacheslav.


Changelog:

v2:
In drivers/clk/samsung/clk-exynos5410.c
1. Clock driver converted to use preprocessor macros instead of enums.
Clock IDs now defined in include/dt-bindings/clock/exynos5410.h.
2. Unused spinlock removed.
3. Function exynos5410_clk_init defined as static.
Struct exynos5410_fixed_rate_ext_clks defined as static.
Struct exynos5410_mux_clks defined as static.
Struct exynos5410_div_clks defined as static.
Struct exynos5410_gate_clks defined as static.
4. Removed aliases.
5. Pll's magic register offsets defined as preprocessor macros.
6. Redundant check of device_node pointer removed.

In arch/arm/boot/dts/exynos5410.dtsi
1. dwmmcX nodes renamed to mmc.
dwmmc_X renamed to mmc_X.
dwmmc status="disabled" field added.
fifo-depth field moved from arch/arm/boot/dts/exynos5410-smdk5410.dts
2. Blank lines added where necessary.
3. cpu@ suffixes corrected.
4. edcs node removed.
5. Hexadecimal characters case corrected.
6. Clock IDs replaced with preprocessor macros.

In arch/arm/boot/dts/exynos5410-smdk5410.dts
1. status = "okay" field added to mmc nodes.

In arch/arm/mach-exynos/edcs.c
1. "kfs_" prefix replaced with "edcs_"
2. EDCS_CPUS_PER_CLUSTER and EDCS_CLUSTERS defined instead of MCPM's values.
3. Cache handling sequence borrowed from arch/arm/mach-vexpress/tc2_pm.c
4. mcpm_sync_init() call added.
5. power management functions reworked.

Other
1. Documentation/devicetree/bindings/clock/exynos5410-clock.txt corrected.
2. Removed smdk5410_defconfig. Instead SOC_EXYNOS5410 now selects MCPM and
ARM_CCI in arch/arm/mach-exynos/Kconfig.
3. edcs_status driver removed.

Tarek Dakhran (4):
ARM: EXYNOS: Add support for EXYNOS5410 SoC
clk: exynos5410: register clocks using common clock framework
ARM: EXYNOS: add Exynos Dual Cluster Support
ARM: dts: Add initial device tree support for EXYNOS5410

.../devicetree/bindings/clock/exynos5410-clock.txt | 37 +++
arch/arm/boot/dts/Makefile | 1 +
arch/arm/boot/dts/exynos5410-smdk5410.dts | 65 +++++
arch/arm/boot/dts/exynos5410.dtsi | 209 ++++++++++++++++
arch/arm/mach-exynos/Kconfig | 12 +
arch/arm/mach-exynos/Makefile | 2 +
arch/arm/mach-exynos/common.c | 18 ++
arch/arm/mach-exynos/edcs.c | 270 +++++++++++++++++++++
arch/arm/mach-exynos/include/mach/map.h | 1 +
arch/arm/mach-exynos/mach-exynos5-dt.c | 1 +
arch/arm/plat-samsung/include/plat/cpu.h | 8 +
drivers/clk/samsung/Makefile | 1 +
drivers/clk/samsung/clk-exynos5410.c | 251 +++++++++++++++++++
include/dt-bindings/clock/exynos5410.h | 175 +++++++++++++
14 files changed, 1051 insertions(+)
create mode 100644 Documentation/devicetree/bindings/clock/exynos5410-clock.txt
create mode 100644 arch/arm/boot/dts/exynos5410-smdk5410.dts
create mode 100644 arch/arm/boot/dts/exynos5410.dtsi
create mode 100644 arch/arm/mach-exynos/edcs.c
create mode 100644 drivers/clk/samsung/clk-exynos5410.c
create mode 100644 include/dt-bindings/clock/exynos5410.h

--
1.8.1.5


2013-10-14 15:11:48

by Vyacheslav Tyrtov

[permalink] [raw]
Subject: [PATCH v2 2/4] clk: exynos5410: register clocks using common clock framework

From: Tarek Dakhran <[email protected]>

The EXYNOS5410 clocks are statically listed and registered
using the Samsung specific common clock helper functions.

Signed-off-by: Tarek Dakhran <[email protected]>
Signed-off-by: Vyacheslav Tyrtov <[email protected]>
---
.../devicetree/bindings/clock/exynos5410-clock.txt | 37 +++
drivers/clk/samsung/Makefile | 1 +
drivers/clk/samsung/clk-exynos5410.c | 251 +++++++++++++++++++++
include/dt-bindings/clock/exynos5410.h | 175 ++++++++++++++
4 files changed, 464 insertions(+)
create mode 100644 Documentation/devicetree/bindings/clock/exynos5410-clock.txt
create mode 100644 drivers/clk/samsung/clk-exynos5410.c
create mode 100644 include/dt-bindings/clock/exynos5410.h

diff --git a/Documentation/devicetree/bindings/clock/exynos5410-clock.txt b/Documentation/devicetree/bindings/clock/exynos5410-clock.txt
new file mode 100644
index 0000000..a462da231
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/exynos5410-clock.txt
@@ -0,0 +1,37 @@
+* Samsung Exynos5410 Clock Controller
+
+The Exynos5410 clock controller generates and supplies clock to various
+controllers within the Exynos5410 SoC.
+
+Required Properties:
+
+- compatible: should be "samsung,exynos5410-clock"
+
+- reg: physical base address of the controller and length of memory mapped
+ region.
+
+- #clock-cells: should be 1.
+
+All available clocks are defined as preprocessor macros in
+dt-bindings/clock/exynos5410.h header and can be used in device
+tree sources.
+
+Example 1: An example of a clock controller node is listed below.
+
+ clock: clock-controller@0x10010000 {
+ compatible = "samsung,exynos5410-clock";
+ reg = <0x10010000 0x30000>;
+ #clock-cells = <1>;
+ };
+
+Example 2: UART controller node that consumes the clock generated by the clock
+ controller. Refer to the standard clock bindings for information
+ about 'clocks' and 'clock-names' property.
+
+ serial@12C20000 {
+ compatible = "samsung,exynos4210-uart";
+ reg = <0x12C00000 0x100>;
+ interrupts = <0 51 0>;
+ clocks = <&clock CLK_UART0>, <&clock CLK_SCLK_UART0>;
+ clock-names = "uart", "clk_uart_baud0";
+ };
diff --git a/drivers/clk/samsung/Makefile b/drivers/clk/samsung/Makefile
index 3413380..5a446ca 100644
--- a/drivers/clk/samsung/Makefile
+++ b/drivers/clk/samsung/Makefile
@@ -5,6 +5,7 @@
obj-$(CONFIG_COMMON_CLK) += clk.o clk-pll.o
obj-$(CONFIG_ARCH_EXYNOS4) += clk-exynos4.o
obj-$(CONFIG_SOC_EXYNOS5250) += clk-exynos5250.o
+obj-$(CONFIG_SOC_EXYNOS5410) += clk-exynos5410.o
obj-$(CONFIG_SOC_EXYNOS5420) += clk-exynos5420.o
obj-$(CONFIG_SOC_EXYNOS5440) += clk-exynos5440.o
obj-$(CONFIG_ARCH_EXYNOS) += clk-exynos-audss.o
diff --git a/drivers/clk/samsung/clk-exynos5410.c b/drivers/clk/samsung/clk-exynos5410.c
new file mode 100644
index 0000000..c5eba08
--- /dev/null
+++ b/drivers/clk/samsung/clk-exynos5410.c
@@ -0,0 +1,251 @@
+/*
+ * Copyright (c) 2013 Samsung Electronics Co., Ltd.
+ * Author: Tarek Dakhran <[email protected]>
+ *
+ * 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.
+ *
+ * Common Clock Framework support for Exynos5410 SoC.
+*/
+
+#include <dt-bindings/clock/exynos5410.h>
+
+#include <linux/clk.h>
+#include <linux/clkdev.h>
+#include <linux/clk-provider.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+
+#include "clk.h"
+
+#define APLL_LOCK 0x0
+#define APLL_CON0 0x100
+#define CPLL_LOCK 0x10020
+#define CPLL_CON0 0x10120
+#define MPLL_LOCK 0x4000
+#define MPLL_CON0 0x4100
+#define BPLL_LOCK 0x20010
+#define BPLL_CON0 0x20110
+#define KPLL_LOCK 0x28000
+#define KPLL_CON0 0x28100
+
+#define SRC_CPU 0x200
+#define DIV_CPU0 0x500
+#define SRC_CPERI1 0x4204
+#define DIV_TOP0 0x10510
+#define DIV_TOP1 0x10514
+#define DIV_FSYS1 0x1054c
+#define DIV_FSYS2 0x10550
+#define DIV_PERIC0 0x10558
+#define SRC_TOP0 0x10210
+#define SRC_TOP1 0x10214
+#define SRC_TOP2 0x10218
+#define SRC_FSYS 0x10244
+#define SRC_PERIC0 0x10250
+#define SRC_MASK_FSYS 0x10340
+#define SRC_MASK_PERIC0 0x10350
+#define GATE_BUS_FSYS0 0x10740
+#define GATE_IP_FSYS 0x10944
+#define GATE_IP_PERIC 0x10950
+#define GATE_IP_PERIS 0x10960
+#define SRC_CDREX 0x20200
+#define SRC_KFC 0x28200
+#define DIV_KFC0 0x28500
+
+/* list of PLLs */
+enum exynos5410_plls {
+ apll, cpll, mpll,
+ bpll, kpll,
+ nr_plls /* number of PLLs */
+};
+
+/*
+ * list of controller registers to be saved and restored during a
+ * suspend/resume cycle.
+ */
+static unsigned long exynos5410_clk_regs[] __initdata = {
+ SRC_CPU,
+ DIV_CPU0,
+ SRC_CPERI1,
+ DIV_TOP0,
+ DIV_TOP1,
+ DIV_FSYS1,
+ DIV_FSYS2,
+ DIV_PERIC0,
+ SRC_TOP0,
+ SRC_TOP1,
+ SRC_TOP2,
+ SRC_FSYS,
+ SRC_PERIC0,
+ SRC_MASK_FSYS,
+ SRC_MASK_PERIC0,
+ GATE_BUS_FSYS0,
+ GATE_IP_FSYS,
+ GATE_IP_PERIC,
+ GATE_IP_PERIS,
+ SRC_CDREX,
+ SRC_KFC,
+ DIV_KFC0,
+};
+
+/* list of all parent clocks */
+PNAME(apll_p) = { "fin_pll", "fout_apll", };
+PNAME(bpll_p) = { "fin_pll", "fout_bpll", };
+PNAME(cpll_p) = { "fin_pll", "fout_cpll" };
+PNAME(mpll_p) = { "fin_pll", "fout_mpll", };
+PNAME(kpll_p) = { "fin_pll", "fout_kpll", };
+
+PNAME(mout_cpu_p) = { "mout_apll", "sclk_mpll", };
+PNAME(mout_kfc_p) = { "mout_kpll", "sclk_mpll", };
+
+PNAME(mpll_user_p) = { "fin_pll", "sclk_mpll", };
+PNAME(bpll_user_p) = { "fin_pll", "sclk_bpll", };
+PNAME(mpll_bpll_p) = { "sclk_mpll_muxed", "sclk_bpll_muxed", };
+
+PNAME(group2_p) = { "fin_pll", "fin_pll", "none", "none",
+ "none", "none", "sclk_mpll_bpll",
+ "none", "none", "sclk_cpll" };
+
+/* fixed rate clocks generated outside the soc */
+static struct samsung_fixed_rate_clock exynos5410_frt_ext_clks[] __initdata = {
+ FRATE(CLK_FIN_PLL, "fin_pll", NULL, CLK_IS_ROOT, 0),
+};
+
+static struct samsung_mux_clock exynos5410_mux_clks[] __initdata = {
+ MUX(0, "mout_apll", apll_p, SRC_CPU, 0, 1),
+ MUX(0, "mout_cpu", mout_cpu_p, SRC_CPU, 16, 1),
+
+ MUX(0, "mout_kpll", kpll_p, SRC_KFC, 0, 1),
+ MUX(0, "mout_kfc", mout_kfc_p, SRC_KFC, 16, 1),
+
+ MUX(0, "sclk_mpll", mpll_p, SRC_CPERI1, 8, 1),
+ MUX(0, "sclk_mpll_muxed", mpll_user_p, SRC_TOP2, 20, 1),
+
+ MUX(0, "sclk_bpll", bpll_p, SRC_CDREX, 0, 1),
+ MUX(0, "sclk_bpll_muxed", bpll_user_p, SRC_TOP2, 24, 1),
+
+ MUX(0, "sclk_cpll", cpll_p, SRC_TOP2, 8, 1),
+
+ MUX(0, "sclk_mpll_bpll", mpll_bpll_p, SRC_TOP1, 20, 1),
+
+ MUX(0, "mout_mmc0", group2_p, SRC_FSYS, 0, 4),
+ MUX(0, "mout_mmc1", group2_p, SRC_FSYS, 4, 4),
+ MUX(0, "mout_mmc2", group2_p, SRC_FSYS, 8, 4),
+
+ MUX(0, "mout_uart0", group2_p, SRC_PERIC0, 0, 4),
+ MUX(0, "mout_uart1", group2_p, SRC_PERIC0, 4, 4),
+ MUX(0, "mout_uart2", group2_p, SRC_PERIC0, 8, 4),
+
+ MUX(0, "mout_aclk200", mpll_bpll_p, SRC_TOP0, 12, 1),
+ MUX(0, "mout_aclk400", mpll_bpll_p, SRC_TOP0, 20, 1),
+};
+
+static struct samsung_div_clock exynos5410_div_clks[] __initdata = {
+ DIV(0, "div_arm", "mout_cpu", DIV_CPU0, 0, 3),
+ DIV(0, "div_arm2", "div_arm", DIV_CPU0, 28, 3),
+
+ DIV(0, "div_acp", "div_arm2", DIV_CPU0, 8, 3),
+ DIV(0, "div_cpud", "div_arm2", DIV_CPU0, 4, 3),
+ DIV(0, "div_atb", "div_arm2", DIV_CPU0, 16, 3),
+ DIV(0, "pclk_dbg", "div_arm2", DIV_CPU0, 20, 3),
+
+ DIV(0, "div_kfc", "mout_kfc", DIV_KFC0, 0, 3),
+ DIV(0, "div_aclk", "div_kfc", DIV_KFC0, 4, 3),
+ DIV(0, "div_pclk", "div_kfc", DIV_KFC0, 20, 3),
+
+ DIV(0, "aclk66_pre", "sclk_mpll_muxed", DIV_TOP1, 24, 3),
+ DIV(0, "aclk66", "aclk66_pre", DIV_TOP0, 0, 3),
+
+ DIV(0, "div_mmc0", "mout_mmc0", DIV_FSYS1, 0, 4),
+ DIV(0, "div_mmc1", "mout_mmc1", DIV_FSYS1, 16, 4),
+ DIV(0, "div_mmc2", "mout_mmc2", DIV_FSYS2, 0, 4),
+
+ DIV_F(0, "div_mmc_pre0", "div_mmc0",
+ DIV_FSYS1, 8, 8, CLK_SET_RATE_PARENT, 0),
+ DIV_F(0, "div_mmc_pre1", "div_mmc1",
+ DIV_FSYS1, 24, 8, CLK_SET_RATE_PARENT, 0),
+ DIV_F(0, "div_mmc_pre2", "div_mmc2",
+ DIV_FSYS2, 8, 8, CLK_SET_RATE_PARENT, 0),
+
+ DIV(0, "div_uart0", "mout_uart0", DIV_PERIC0, 0, 4),
+ DIV(0, "div_uart1", "mout_uart1", DIV_PERIC0, 4, 4),
+ DIV(0, "div_uart2", "mout_uart2", DIV_PERIC0, 8, 4),
+ DIV(0, "div_uart3", "mout_uart3", DIV_PERIC0, 12, 4),
+
+ DIV(0, "aclk200", "mout_aclk200", DIV_TOP0, 12, 3),
+ DIV(0, "aclk400", "mout_aclk400", DIV_TOP0, 24, 3),
+};
+
+static struct samsung_gate_clock exynos5410_gate_clks[] __initdata = {
+ GATE(CLK_MCT, "mct", "aclk66", GATE_IP_PERIS, 18, 0, 0),
+
+ GATE(CLK_SCLK_MMC0, "sclk_mmc0", "div_mmc_pre0",
+ SRC_MASK_FSYS, 0, CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_SCLK_MMC1, "sclk_mmc1", "div_mmc_pre1",
+ SRC_MASK_FSYS, 4, CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_SCLK_MMC2, "sclk_mmc2", "div_mmc_pre2",
+ SRC_MASK_FSYS, 8, CLK_SET_RATE_PARENT, 0),
+
+ GATE(CLK_MMC0, "sdmmc0", "aclk200", GATE_BUS_FSYS0, 12, 0, 0),
+ GATE(CLK_MMC1, "sdmmc1", "aclk200", GATE_BUS_FSYS0, 13, 0, 0),
+ GATE(CLK_MMC2, "sdmmc2", "aclk200", GATE_BUS_FSYS0, 14, 0, 0),
+
+ GATE(CLK_UART0, "uart0", "aclk66", GATE_IP_PERIC, 0, 0, 0),
+ GATE(CLK_UART1, "uart1", "aclk66", GATE_IP_PERIC, 1, 0, 0),
+ GATE(CLK_UART2, "uart2", "aclk66", GATE_IP_PERIC, 2, 0, 0),
+
+ GATE(CLK_SCLK_UART0, "sclk_uart0", "div_uart0",
+ SRC_MASK_PERIC0, 0, CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_SCLK_UART1, "sclk_uart1", "div_uart1",
+ SRC_MASK_PERIC0, 4, CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_SCLK_UART2, "sclk_uart2", "div_uart2",
+ SRC_MASK_PERIC0, 8, CLK_SET_RATE_PARENT, 0),
+};
+
+static struct samsung_pll_clock exynos5410_plls[nr_plls] __initdata = {
+ [apll] = PLL(pll_35xx, CLK_FOUT_APLL, "fout_apll", "fin_pll", APLL_LOCK,
+ APLL_CON0, NULL),
+ [cpll] = PLL(pll_35xx, CLK_FOUT_CPLL, "fout_cpll", "fin_pll", CPLL_LOCK,
+ CPLL_CON0, NULL),
+ [mpll] = PLL(pll_35xx, CLK_FOUT_MPLL, "fout_mpll", "fin_pll", MPLL_LOCK,
+ MPLL_CON0, NULL),
+ [bpll] = PLL(pll_35xx, CLK_FOUT_BPLL, "fout_bpll", "fin_pll", BPLL_LOCK,
+ BPLL_CON0, NULL),
+ [kpll] = PLL(pll_35xx, CLK_FOUT_KPLL, "fout_kpll", "fin_pll", KPLL_LOCK,
+ KPLL_CON0, NULL),
+};
+
+static struct of_device_id ext_clk_match[] __initdata = {
+ { .compatible = "samsung,clock-oscclk", .data = (void *)0, },
+ { },
+};
+
+/* register exynos5410 clocks */
+static void __init exynos5410_clk_init(struct device_node *np)
+{
+ void __iomem *reg_base;
+
+ reg_base = of_iomap(np, 0);
+ if (!reg_base)
+ panic("%s: failed to map registers\n", __func__);
+
+ samsung_clk_init(np, reg_base, CLK_NR_CLKS,
+ exynos5410_clk_regs, ARRAY_SIZE(exynos5410_clk_regs),
+ NULL, 0);
+ samsung_clk_of_register_fixed_ext(exynos5410_frt_ext_clks,
+ ARRAY_SIZE(exynos5410_frt_ext_clks),
+ ext_clk_match);
+ samsung_clk_register_pll(exynos5410_plls, ARRAY_SIZE(exynos5410_plls),
+ reg_base);
+
+ samsung_clk_register_mux(exynos5410_mux_clks,
+ ARRAY_SIZE(exynos5410_mux_clks));
+ samsung_clk_register_div(exynos5410_div_clks,
+ ARRAY_SIZE(exynos5410_div_clks));
+ samsung_clk_register_gate(exynos5410_gate_clks,
+ ARRAY_SIZE(exynos5410_gate_clks));
+
+ pr_debug("Exynos5410: clock setup completed.\n");
+}
+CLK_OF_DECLARE(exynos5410_clk, "samsung,exynos5410-clock", exynos5410_clk_init);
diff --git a/include/dt-bindings/clock/exynos5410.h b/include/dt-bindings/clock/exynos5410.h
new file mode 100644
index 0000000..9b4a58b
--- /dev/null
+++ b/include/dt-bindings/clock/exynos5410.h
@@ -0,0 +1,175 @@
+#ifndef _DT_BINDINGS_CLOCK_EXYNOS_5410_H
+#define _DT_BINDINGS_CLOCK_EXYNOS_5410_H
+
+/* core clocks */
+#define CLK_FIN_PLL 1
+#define CLK_FOUT_APLL 2
+#define CLK_FOUT_CPLL 3
+#define CLK_FOUT_DPLL 4
+#define CLK_FOUT_EPLL 5
+#define CLK_FOUT_RPLL 6
+#define CLK_FOUT_IPLL 7
+#define CLK_FOUT_SPLL 8
+#define CLK_FOUT_VPLL 9
+#define CLK_FOUT_MPLL 10
+#define CLK_FOUT_BPLL 11
+#define CLK_FOUT_KPLL 12
+
+/* gate for special clocks (sclk) */
+#define CLK_SCLK_UART0 128
+#define CLK_SCLK_UART1 129
+#define CLK_SCLK_UART2 130
+#define CLK_SCLK_UART3 131
+#define CLK_SCLK_MMC0 132
+#define CLK_SCLK_MMC1 133
+#define CLK_SCLK_MMC2 134
+#define CLK_SCLK_SPI0 135
+#define CLK_SCLK_SPI1 136
+#define CLK_SCLK_SPI2 137
+#define CLK_SCLK_I2S1 138
+#define CLK_SCLK_I2S2 139
+#define CLK_SCLK_PCM1 140
+#define CLK_SCLK_PCM2 141
+#define CLK_SCLK_SPDIF 142
+#define CLK_SCLK_HDMI 143
+#define CLK_SCLK_PIXEL 144
+#define CLK_SCLK_DP1 145
+#define CLK_SCLK_MIPI1 146
+#define CLK_SCLK_FIMD1 147
+#define CLK_SCLK_MAUDIO0 148
+#define CLK_SCLK_MAUPCM0 149
+#define CLK_SCLK_USBD300 150
+#define CLK_SCLK_USBD301 151
+#define CLK_SCLK_USBPHY300 152
+#define CLK_SCLK_USBPHY301 153
+#define CLK_SCLK_UNIPRO 154
+#define CLK_SCLK_PWM 155
+#define CLK_SCLK_GSCL_WA 156
+#define CLK_SCLK_GSCL_WB 157
+#define CLK_SCLK_HDMIPHY 158
+
+/* gate clocks */
+#define CLK_ACLK66_PERIC 256
+#define CLK_UART0 257
+#define CLK_UART1 258
+#define CLK_UART2 259
+#define CLK_UART3 260
+#define CLK_I2C0 261
+#define CLK_I2C1 262
+#define CLK_I2C2 263
+#define CLK_I2C3 264
+#define CLK_I2C4 265
+#define CLK_I2C5 266
+#define CLK_I2C6 267
+#define CLK_I2C7 268
+#define CLK_I2C_HDMI 269
+#define CLK_TSADC 270
+#define CLK_SPI0 271
+#define CLK_SPI1 272
+#define CLK_SPI2 273
+#define CLK_KEYIF 274
+#define CLK_I2S1 275
+#define CLK_I2S2 276
+#define CLK_PCM1 277
+#define CLK_PCM2 278
+#define CLK_PWM 279
+#define CLK_SPDIF 280
+#define CLK_I2C8 281
+#define CLK_I2C9 282
+#define CLK_I2C10 283
+#define CLK_ACLK66_PSGEN 300
+#define CLK_CHIPID 301
+#define CLK_SYSREG 302
+#define CLK_TZPC0 303
+#define CLK_TZPC1 304
+#define CLK_TZPC2 305
+#define CLK_TZPC3 306
+#define CLK_TZPC4 307
+#define CLK_TZPC5 308
+#define CLK_TZPC6 309
+#define CLK_TZPC7 310
+#define CLK_TZPC8 311
+#define CLK_TZPC9 312
+#define CLK_HDMI_CEC 313
+#define CLK_SECKEY 314
+#define CLK_MCT 315
+#define CLK_WDT 316
+#define CLK_RTC 317
+#define CLK_TMU 318
+#define CLK_TMU_GPU 319
+#define CLK_PCLK66_GPIO 330
+#define CLK_ACLK200_FSYS2 350
+#define CLK_MMC0 351
+#define CLK_MMC1 352
+#define CLK_MMC2 353
+#define CLK_SROMC 354
+#define CLK_UFS 355
+#define CLK_ACLK200_FSYS 360
+#define CLK_TSI 361
+#define CLK_PDMA0 362
+#define CLK_PDMA1 363
+#define CLK_RTIC 364
+#define CLK_USBH20 365
+#define CLK_USBD300 366
+#define CLK_USBD301 367
+#define CLK_ACLK400_MSCL 380
+#define CLK_MSCL0 381
+#define CLK_MSCL1 382
+#define CLK_MSCL2 383
+#define CLK_SMMU_MSCL0 384
+#define CLK_SMMU_MSCL1 385
+#define CLK_SMMU_MSCL2 386
+#define CLK_ACLK333 400
+#define CLK_MFC 401
+#define CLK_SMMU_MFCL 402
+#define CLK_SMMU_MFCR 403
+#define CLK_ACLK200_DISP1 410
+#define CLK_DSIM1 411
+#define CLK_DP1 412
+#define CLK_HDMI 413
+#define CLK_ACLK300_DISP1 420
+#define CLK_FIMD1 421
+#define CLK_SMMU_FIMD1 422
+#define CLK_ACLK166 430
+#define CLK_MIXER 431
+#define CLK_ACLK266 440
+#define CLK_ROTATOR 441
+#define CLK_MDMA1 442
+#define CLK_SMMU_ROTATOR 443
+#define CLK_SMMU_MDMA1 444
+#define CLK_ACLK300_JPEG 450
+#define CLK_JPEG 451
+#define CLK_JPEG2 452
+#define CLK_SMMU_JPEG 453
+#define CLK_ACLK300_GSCL 460
+#define CLK_SMMU_GSCL0 461
+#define CLK_SMMU_GSCL1 462
+#define CLK_GSCL_WA 463
+#define CLK_GSCL_WB 464
+#define CLK_GSCL0 465
+#define CLK_GSCL1 466
+#define CLK_CLK_3AA 467
+#define CLK_ACLK266_G2D 470
+#define CLK_SSS 471
+#define CLK_SLIM_SSS 472
+#define CLK_MDMA0 473
+#define CLK_ACLK333_G2D 480
+#define CLK_G2D 481
+#define CLK_ACLK333_432_GSCL 490
+#define CLK_SMMU_3AA 491
+#define CLK_SMMU_FIMCL0 492
+#define CLK_SMMU_FIMCL1 493
+#define CLK_SMMU_FIMCL3 494
+#define CLK_FIMC_LITE3 495
+#define CLK_ACLK_G3D 500
+#define CLK_G3D 501
+#define CLK_SMMU_MIXER 502
+
+/* mux clocks */
+#define CLK_MOUT_HDMI 640
+
+/* divider clocks */
+#define CLK_DOUT_PIXEL 768
+#define CLK_NR_CLKS 769
+
+#endif /* _DT_BINDINGS_CLOCK_EXYNOS_5410_H */
--
1.8.1.5

2013-10-14 15:11:46

by Vyacheslav Tyrtov

[permalink] [raw]
Subject: [PATCH v2 1/4] ARM: EXYNOS: Add support for EXYNOS5410 SoC

From: Tarek Dakhran <[email protected]>

EXYNOS5410 is SoC in Samsung's Exynos5 SoC series.
Add initial support for this SoC.

Signed-off-by: Tarek Dakhran <[email protected]>
Signed-off-by: Vyacheslav Tyrtov <[email protected]>
---
arch/arm/mach-exynos/Kconfig | 12 ++++++++++++
arch/arm/mach-exynos/common.c | 18 ++++++++++++++++++
arch/arm/mach-exynos/include/mach/map.h | 1 +
arch/arm/mach-exynos/mach-exynos5-dt.c | 1 +
arch/arm/plat-samsung/include/plat/cpu.h | 8 ++++++++
5 files changed, 40 insertions(+)

diff --git a/arch/arm/mach-exynos/Kconfig b/arch/arm/mach-exynos/Kconfig
index 56fe819..9ea1799 100644
--- a/arch/arm/mach-exynos/Kconfig
+++ b/arch/arm/mach-exynos/Kconfig
@@ -84,6 +84,18 @@ config SOC_EXYNOS5250
help
Enable EXYNOS5250 SoC support

+config SOC_EXYNOS5410
+ bool "SAMSUNG EXYNOS5410"
+ default y
+ depends on ARCH_EXYNOS5
+ select MCPM
+ select ARM_CCI
+ select PM_GENERIC_DOMAINS if PM
+ select S5P_PM if PM
+ select S5P_SLEEP if PM
+ help
+ Enable EXYNOS5410 SoC support
+
config SOC_EXYNOS5420
bool "SAMSUNG EXYNOS5420"
default y
diff --git a/arch/arm/mach-exynos/common.c b/arch/arm/mach-exynos/common.c
index ba95e5d..187c0a4 100644
--- a/arch/arm/mach-exynos/common.c
+++ b/arch/arm/mach-exynos/common.c
@@ -53,6 +53,7 @@ static const char name_exynos4210[] = "EXYNOS4210";
static const char name_exynos4212[] = "EXYNOS4212";
static const char name_exynos4412[] = "EXYNOS4412";
static const char name_exynos5250[] = "EXYNOS5250";
+static const char name_exynos5410[] = "EXYNOS5410";
static const char name_exynos5420[] = "EXYNOS5420";
static const char name_exynos5440[] = "EXYNOS5440";

@@ -86,6 +87,12 @@ static struct cpu_table cpu_ids[] __initdata = {
.init = exynos_init,
.name = name_exynos5250,
}, {
+ .idcode = EXYNOS5410_SOC_ID,
+ .idmask = EXYNOS5_SOC_MASK,
+ .map_io = exynos5_map_io,
+ .init = exynos_init,
+ .name = name_exynos5410,
+ }, {
.idcode = EXYNOS5420_SOC_ID,
.idmask = EXYNOS5_SOC_MASK,
.map_io = exynos5_map_io,
@@ -216,6 +223,15 @@ static struct map_desc exynos4x12_iodesc[] __initdata = {
},
};

+static struct map_desc exynos5410_iodesc[] __initdata = {
+ {
+ .virtual = (unsigned long)S5P_VA_SYSRAM_NS,
+ .pfn = __phys_to_pfn(EXYNOS5410_PA_SYSRAM_NS),
+ .length = SZ_4K,
+ .type = MT_DEVICE,
+ },
+};
+
static struct map_desc exynos5250_iodesc[] __initdata = {
{
.virtual = (unsigned long)S5P_VA_SYSRAM_NS,
@@ -365,6 +381,8 @@ static void __init exynos5_map_io(void)

if (soc_is_exynos5250())
iotable_init(exynos5250_iodesc, ARRAY_SIZE(exynos5250_iodesc));
+ if (soc_is_exynos5410())
+ iotable_init(exynos5410_iodesc, ARRAY_SIZE(exynos5410_iodesc));
}

void __init exynos_init_time(void)
diff --git a/arch/arm/mach-exynos/include/mach/map.h b/arch/arm/mach-exynos/include/mach/map.h
index 7b046b5..894f431 100644
--- a/arch/arm/mach-exynos/include/mach/map.h
+++ b/arch/arm/mach-exynos/include/mach/map.h
@@ -29,6 +29,7 @@
#define EXYNOS4210_PA_SYSRAM_NS 0x0203F000
#define EXYNOS4x12_PA_SYSRAM_NS 0x0204F000
#define EXYNOS5250_PA_SYSRAM_NS 0x0204F000
+#define EXYNOS5410_PA_SYSRAM_NS 0x02073000

#define EXYNOS_PA_CHIPID 0x10000000

diff --git a/arch/arm/mach-exynos/mach-exynos5-dt.c b/arch/arm/mach-exynos/mach-exynos5-dt.c
index f874b77..9515186 100644
--- a/arch/arm/mach-exynos/mach-exynos5-dt.c
+++ b/arch/arm/mach-exynos/mach-exynos5-dt.c
@@ -52,6 +52,7 @@ static void __init exynos5_dt_machine_init(void)

static char const *exynos5_dt_compat[] __initdata = {
"samsung,exynos5250",
+ "samsung,exynos5410",
"samsung,exynos5420",
"samsung,exynos5440",
NULL
diff --git a/arch/arm/plat-samsung/include/plat/cpu.h b/arch/arm/plat-samsung/include/plat/cpu.h
index 4fb1f03..aad7c40 100644
--- a/arch/arm/plat-samsung/include/plat/cpu.h
+++ b/arch/arm/plat-samsung/include/plat/cpu.h
@@ -46,6 +46,7 @@ extern unsigned long samsung_cpu_id;
#define EXYNOS4_CPU_MASK 0xFFFE0000

#define EXYNOS5250_SOC_ID 0x43520000
+#define EXYNOS5410_SOC_ID 0xE5410023
#define EXYNOS5420_SOC_ID 0xE5420000
#define EXYNOS5440_SOC_ID 0xE5440000
#define EXYNOS5_SOC_MASK 0xFFFFF000
@@ -68,6 +69,7 @@ IS_SAMSUNG_CPU(exynos4210, EXYNOS4210_CPU_ID, EXYNOS4_CPU_MASK)
IS_SAMSUNG_CPU(exynos4212, EXYNOS4212_CPU_ID, EXYNOS4_CPU_MASK)
IS_SAMSUNG_CPU(exynos4412, EXYNOS4412_CPU_ID, EXYNOS4_CPU_MASK)
IS_SAMSUNG_CPU(exynos5250, EXYNOS5250_SOC_ID, EXYNOS5_SOC_MASK)
+IS_SAMSUNG_CPU(exynos5410, EXYNOS5410_SOC_ID, EXYNOS5_SOC_MASK)
IS_SAMSUNG_CPU(exynos5420, EXYNOS5420_SOC_ID, EXYNOS5_SOC_MASK)
IS_SAMSUNG_CPU(exynos5440, EXYNOS5440_SOC_ID, EXYNOS5_SOC_MASK)

@@ -144,6 +146,12 @@ IS_SAMSUNG_CPU(exynos5440, EXYNOS5440_SOC_ID, EXYNOS5_SOC_MASK)
# define soc_is_exynos5250() 0
#endif

+#if defined(CONFIG_SOC_EXYNOS5410)
+# define soc_is_exynos5410() is_samsung_exynos5410()
+#else
+# define soc_is_exynos5410() 0
+#endif
+
#if defined(CONFIG_SOC_EXYNOS5420)
# define soc_is_exynos5420() is_samsung_exynos5420()
#else
--
1.8.1.5

2013-10-14 15:12:12

by Vyacheslav Tyrtov

[permalink] [raw]
Subject: [PATCH v2 4/4] ARM: dts: Add initial device tree support for EXYNOS5410

From: Tarek Dakhran <[email protected]>

Add initial device tree nodes for EXYNOS5410 SoC and SMDK5410 board.

Signed-off-by: Tarek Dakhran <[email protected]>
Signed-off-by: Vyacheslav Tyrtov <[email protected]>
---
arch/arm/boot/dts/Makefile | 1 +
arch/arm/boot/dts/exynos5410-smdk5410.dts | 65 ++++++++++
arch/arm/boot/dts/exynos5410.dtsi | 209 ++++++++++++++++++++++++++++++
3 files changed, 275 insertions(+)
create mode 100644 arch/arm/boot/dts/exynos5410-smdk5410.dts
create mode 100644 arch/arm/boot/dts/exynos5410.dtsi

diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index 802720e..e991739 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -63,6 +63,7 @@ dtb-$(CONFIG_ARCH_EXYNOS) += exynos4210-origen.dtb \
exynos5250-arndale.dtb \
exynos5250-smdk5250.dtb \
exynos5250-snow.dtb \
+ exynos5410-smdk5410.dtb \
exynos5420-smdk5420.dtb \
exynos5440-sd5v1.dtb \
exynos5440-ssdk5440.dtb
diff --git a/arch/arm/boot/dts/exynos5410-smdk5410.dts b/arch/arm/boot/dts/exynos5410-smdk5410.dts
new file mode 100644
index 0000000..c3d0b32
--- /dev/null
+++ b/arch/arm/boot/dts/exynos5410-smdk5410.dts
@@ -0,0 +1,65 @@
+/*
+ * SAMSUNG SMDK5410 board device tree source
+ *
+ * Copyright (c) 2013 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com
+ *
+ * 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 "exynos5410.dtsi"
+/ {
+ model = "Samsung SMDK5410 board based on EXYNOS5410";
+ compatible = "samsung,smdk5410", "samsung,exynos5410";
+
+ memory {
+ reg = <0x40000000 0x80000000>;
+ };
+
+ chosen {
+ bootargs = "console=ttySAC2,115200";
+ };
+
+ fixed-rate-clocks {
+ oscclk {
+ compatible = "samsung,clock-oscclk";
+ clock-frequency = <24000000>;
+ };
+ };
+
+ mmc@12200000 {
+ status = "okay";
+ num-slots = <1>;
+ supports-highspeed;
+ broken-cd;
+ card-detect-delay = <200>;
+ samsung,dw-mshc-ciu-div = <3>;
+ samsung,dw-mshc-sdr-timing = <2 3>;
+ samsung,dw-mshc-ddr-timing = <1 2>;
+
+ slot@0 {
+ reg = <0>;
+ bus-width = <8>;
+ };
+ };
+
+ mmc@12220000 {
+ status = "okay";
+ num-slots = <1>;
+ supports-highspeed;
+ card-detect-delay = <200>;
+ samsung,dw-mshc-ciu-div = <3>;
+ samsung,dw-mshc-sdr-timing = <2 3>;
+ samsung,dw-mshc-ddr-timing = <1 2>;
+
+ slot@0 {
+ reg = <0>;
+ bus-width = <4>;
+ disable-wp;
+ };
+ };
+
+};
diff --git a/arch/arm/boot/dts/exynos5410.dtsi b/arch/arm/boot/dts/exynos5410.dtsi
new file mode 100644
index 0000000..92a5a73
--- /dev/null
+++ b/arch/arm/boot/dts/exynos5410.dtsi
@@ -0,0 +1,209 @@
+/*
+ * SAMSUNG EXYNOS5410 SoC device tree source
+ *
+ * Copyright (c) 2013 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com
+ *
+ * SAMSUNG EXYNOS5410 SoC device nodes are listed in this file.
+ * EXYNOS5410 based board files can include this file and provide
+ * values for board specfic bindings.
+ *
+ * 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 <dt-bindings/clock/exynos5410.h>
+#include "exynos5.dtsi"
+/ {
+ compatible = "samsung,exynos5410";
+
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ CPU0: cpu@0 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a15";
+ reg = <0>;
+ cci-control-port = <&cci_control2>;
+ clock-frequency = <1600000000>;
+ };
+
+ CPU1: cpu@1 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a15";
+ reg = <1>;
+ cci-control-port = <&cci_control2>;
+ clock-frequency = <1600000000>;
+ };
+
+ CPU2: cpu@2 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a15";
+ reg = <2>;
+ cci-control-port = <&cci_control2>;
+ clock-frequency = <1600000000>;
+ };
+
+ CPU3: cpu@3 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a15";
+ reg = <3>;
+ cci-control-port = <&cci_control2>;
+ clock-frequency = <1600000000>;
+ };
+
+ CPU4: cpu@100 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a7";
+ reg = <0x100>;
+ cci-control-port = <&cci_control1>;
+ clock-frequency = <1200000000>;
+ };
+
+ CPU5: cpu@101 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a7";
+ reg = <0x101>;
+ cci-control-port = <&cci_control1>;
+ clock-frequency = <1200000000>;
+ };
+
+ CPU6: cpu@102 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a7";
+ reg = <0x102>;
+ cci-control-port = <&cci_control1>;
+ clock-frequency = <1200000000>;
+ };
+
+ CPU7: cpu@103 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a7";
+ reg = <0x103>;
+ cci-control-port = <&cci_control1>;
+ clock-frequency = <1200000000>;
+ };
+ };
+
+ cci@10D20000 {
+ compatible = "arm,cci-400";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0x10D20000 0x1000>;
+ ranges = <0 0x10D20000 0x6000>;
+
+ cci_control0: slave-if@1000 {
+ compatible = "arm,cci-400-ctrl-if";
+ interface-type = "ace-lite";
+ reg = <0x1000 0x1000>;
+ };
+
+ cci_control1: slave-if@4000 {
+ compatible = "arm,cci-400-ctrl-if";
+ interface-type = "ace";
+ reg = <0x4000 0x1000>;
+ };
+
+ cci_control2: slave-if@5000 {
+ compatible = "arm,cci-400-ctrl-if";
+ interface-type = "ace";
+ reg = <0x5000 0x1000>;
+ };
+ };
+
+ clock: clock-controller@10010000 {
+ compatible = "samsung,exynos5410-clock";
+ reg = <0x10010000 0x30000>;
+ #clock-cells = <1>;
+ };
+
+ mct@101C0000 {
+ compatible = "samsung,exynos4210-mct";
+ reg = <0x101C0000 0xB00>;
+ interrupt-controller;
+ #interrups-cells = <1>;
+ interrupt-parent = <&mct_map>;
+ interrupts = <0>, <1>, <2>, <3>,
+ <4>, <5>, <6>, <7>,
+ <8>, <9>, <10>, <11>;
+ clocks = <&clock CLK_FIN_PLL>, <&clock CLK_MCT>;
+ clock-names = "fin_pll", "mct";
+
+ mct_map: mct-map {
+ #interrupt-cells = <1>;
+ #address-cells = <0>;
+ #size-cells = <0>;
+ interrupt-map = <0 &combiner 23 3>,
+ <1 &combiner 23 4>,
+ <2 &combiner 25 2>,
+ <3 &combiner 25 3>,
+ <4 &gic 0 120 0>,
+ <5 &gic 0 121 0>,
+ <6 &gic 0 122 0>,
+ <7 &gic 0 123 0>,
+ <8 &gic 0 128 0>,
+ <9 &gic 0 129 0>,
+ <10 &gic 0 130 0>,
+ <11 &gic 0 131 0>;
+ };
+ };
+
+ mmc_0: mmc@12200000 {
+ compatible = "samsung,exynos5250-dw-mshc";
+ interrupts = <0 75 0>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x12200000 0x1000>;
+ clocks = <&clock CLK_MMC0>, <&clock CLK_SCLK_MMC0>;
+ clock-names = "biu", "ciu";
+ fifo-depth = <0x80>;
+ status = "disabled";
+ };
+
+ mmc_1: mmc@12210000 {
+ compatible = "samsung,exynos5250-dw-mshc";
+ interrupts = <0 76 0>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x12210000 0x1000>;
+ clocks = <&clock CLK_MMC1>, <&clock CLK_SCLK_MMC1>;
+ clock-names = "biu", "ciu";
+ fifo-depth = <0x80>;
+ status = "disabled";
+ };
+
+ mmc_2: mmc@12220000 {
+ compatible = "samsung,exynos5250-dw-mshc";
+ interrupts = <0 77 0>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x12220000 0x1000>;
+ clocks = <&clock CLK_MMC2>, <&clock CLK_SCLK_MMC2>;
+ clock-names = "biu", "ciu";
+ fifo-depth = <0x80>;
+ status = "disabled";
+ };
+
+ serial@12C00000 {
+ clocks = <&clock CLK_UART0>, <&clock CLK_SCLK_UART0>;
+ clock-names = "uart", "clk_uart_baud0";
+ };
+
+ serial@12C10000 {
+ clocks = <&clock CLK_UART1>, <&clock CLK_SCLK_UART1>;
+ clock-names = "uart", "clk_uart_baud0";
+ };
+
+ serial@12C20000 {
+ clocks = <&clock CLK_UART2>, <&clock CLK_SCLK_UART2>;
+ clock-names = "uart", "clk_uart_baud0";
+ };
+
+ serial@12C30000 {
+ clocks = <&clock CLK_UART3>, <&clock CLK_SCLK_UART3>;
+ clock-names = "uart", "clk_uart_baud0";
+ };
+
+};
--
1.8.1.5

2013-10-14 15:12:42

by Vyacheslav Tyrtov

[permalink] [raw]
Subject: [PATCH v2 3/4] ARM: EXYNOS: add Exynos Dual Cluster Support

From: Tarek Dakhran <[email protected]>

Add EDCS(Exynos Dual Cluster Support) for Samsung Exynos5410 SoC.
This enables all 8 cores, 4 x A7 and 4 x A15 run at the same time.

Signed-off-by: Tarek Dakhran <[email protected]>
Signed-off-by: Vyacheslav Tyrtov <[email protected]>
---
arch/arm/mach-exynos/Makefile | 2 +
arch/arm/mach-exynos/edcs.c | 270 ++++++++++++++++++++++++++++++++++++++++++
2 files changed, 272 insertions(+)
create mode 100644 arch/arm/mach-exynos/edcs.c

diff --git a/arch/arm/mach-exynos/Makefile b/arch/arm/mach-exynos/Makefile
index 5369615..ba6efdb 100644
--- a/arch/arm/mach-exynos/Makefile
+++ b/arch/arm/mach-exynos/Makefile
@@ -34,3 +34,5 @@ AFLAGS_exynos-smc.o :=-Wa,-march=armv7-a$(plus_sec)

obj-$(CONFIG_MACH_EXYNOS4_DT) += mach-exynos4-dt.o
obj-$(CONFIG_MACH_EXYNOS5_DT) += mach-exynos5-dt.o
+
+obj-$(CONFIG_SOC_EXYNOS5410) += edcs.o
diff --git a/arch/arm/mach-exynos/edcs.c b/arch/arm/mach-exynos/edcs.c
new file mode 100644
index 0000000..e304bd9
--- /dev/null
+++ b/arch/arm/mach-exynos/edcs.c
@@ -0,0 +1,270 @@
+/*
+ * arch/arm/mach-exynos/edcs.c - exynos dual cluster power management support
+ *
+ * Copyright (c) 2013 Samsung Electronics Co., Ltd.
+ * Author: Tarek Dakhran <[email protected]>
+ *
+ * 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.
+ *
+ * EDCS(exynos dual cluster support) for Exynos5410 SoC.
+ */
+
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/of_address.h>
+#include <linux/spinlock.h>
+#include <linux/errno.h>
+
+#include <asm/mcpm.h>
+#include <asm/proc-fns.h>
+#include <asm/cacheflush.h>
+#include <asm/cputype.h>
+#include <asm/cp15.h>
+
+#include <linux/arm-cci.h>
+#include <mach/regs-pmu.h>
+
+#define EDCS_CPUS_PER_CLUSTER 4
+#define EDCS_CLUSTERS 2
+
+/* Exynos5410 power management registers */
+#define EDCS_CORE_CONFIGURATION(_nr) (S5P_ARM_CORE0_CONFIGURATION \
+ + ((_nr) * 0x80))
+#define EDCS_CORE_STATUS(_nr) (EDCS_CORE_CONFIGURATION(_nr) + 0x4)
+#define EDCS_CORE_OPTION(_nr) (EDCS_CORE_CONFIGURATION(_nr) + 0x8)
+
+#define REG_CPU_STATE_ADDR0 (S5P_VA_SYSRAM_NS + 0x28)
+#define REG_CPU_STATE_ADDR(_nr) (REG_CPU_STATE_ADDR0 + \
+ _nr * EDCS_CPUS_PER_CLUSTER)
+
+static arch_spinlock_t edcs_lock = __ARCH_SPIN_LOCK_UNLOCKED;
+
+static int edcs_use_count[EDCS_CPUS_PER_CLUSTER][EDCS_CLUSTERS];
+static int core_count[EDCS_CLUSTERS];
+
+static void exynos_core_power_control(unsigned int cpu, unsigned int cluster,
+ bool enable)
+{
+ unsigned int offset = cluster * EDCS_CPUS_PER_CLUSTER + cpu;
+ int value = enable ? S5P_CORE_LOCAL_PWR_EN : 0;
+
+ if ((__raw_readl(EDCS_CORE_STATUS(offset)) & 0x3) != value)
+ __raw_writel(value, EDCS_CORE_CONFIGURATION(offset));
+}
+
+static void exynos_core_power_up(unsigned int cpu, unsigned int cluster)
+{
+ exynos_core_power_control(cpu, cluster, true);
+}
+
+static void exynos_core_power_down(unsigned int cpu, unsigned int cluster)
+{
+ exynos_core_power_control(cpu, cluster, false);
+}
+
+void set_boot_flag(unsigned int cpu, unsigned int mode)
+{
+ __raw_writel(mode, REG_CPU_STATE_ADDR(cpu));
+}
+
+static int exynos_power_up(unsigned int cpu, unsigned int cluster)
+{
+ pr_debug("%s: cpu %u cluster %u\n", __func__, cpu, cluster);
+ BUG_ON(cpu >= EDCS_CPUS_PER_CLUSTER || cluster >= EDCS_CLUSTERS);
+
+ local_irq_disable();
+ arch_spin_lock(&edcs_lock);
+
+ edcs_use_count[cpu][cluster]++;
+ if (edcs_use_count[cpu][cluster] == 1) {
+ ++core_count[cluster];
+ set_boot_flag(cpu, 0x2);
+ exynos_core_power_up(cpu, cluster);
+ } else if (edcs_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(&edcs_lock);
+ local_irq_enable();
+
+ return 0;
+}
+static void exynos_power_down(void)
+{
+ unsigned int mpidr, cpu, cluster;
+ bool last_man = false, skip_wfi = false;
+
+ 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 >= EDCS_CPUS_PER_CLUSTER || cluster >= EDCS_CLUSTERS);
+
+ __mcpm_cpu_going_down(cpu, cluster);
+
+ arch_spin_lock(&edcs_lock);
+ BUG_ON(__mcpm_cluster_state(cluster) != CLUSTER_UP);
+ edcs_use_count[cpu][cluster]--;
+ if (edcs_use_count[cpu][cluster] == 0) {
+ --core_count[cluster];
+ if (core_count[cluster] == 0)
+ last_man = true;
+ } else if (edcs_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(&edcs_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));
+ }
+
+ /*
+ * We need to disable and flush the whole (L1 and L2) cache.
+ * Let's do it in the safest possible way i.e. with
+ * no memory access within the following sequence
+ * including the stack.
+ *
+ * Note: fp is preserved to the stack explicitly prior doing
+ * this since adding it to the clobber list is incompatible
+ * with having CONFIG_FRAME_POINTER=y.
+ */
+ asm volatile(
+ "str fp, [sp, #-4]!\n\t"
+ "mrc p15, 0, r0, c1, c0, 0 @ get CR\n\t"
+ "bic r0, r0, #"__stringify(CR_C)"\n\t"
+ "mcr p15, 0, r0, c1, c0, 0 @ set CR\n\t"
+ "isb\n\t"
+ "bl v7_flush_dcache_all\n\t"
+ "clrex\n\t"
+ "mrc p15, 0, r0, c1, c0, 1 @ get AUXCR\n\t"
+ "bic r0, r0, #(1 << 6) @ disable local coherency\n\t"
+ "mcr p15, 0, r0, c1, c0, 1 @ set AUXCR\n\t"
+ "isb\n\t"
+ "dsb\n\t"
+ "ldr fp, [sp], #4"
+ : : : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
+ "r9", "r10", "lr", "memory");
+
+ cci_disable_port_by_cpu(mpidr);
+
+ __mcpm_outbound_leave_critical(cluster, CLUSTER_DOWN);
+
+ } else {
+ arch_spin_unlock(&edcs_lock);
+ /*
+ * We need to disable and flush only the L1 cache.
+ * Let's do it in the safest possible way as above.
+ */
+ asm volatile(
+ "str fp, [sp, #-4]!\n\t"
+ "mrc p15, 0, r0, c1, c0, 0 @ get CR\n\t"
+ "bic r0, r0, #"__stringify(CR_C)"\n\t"
+ "mcr p15, 0, r0, c1, c0, 0 @ set CR\n\t"
+ "isb\n\t"
+ "bl v7_flush_dcache_louis\n\t"
+ "clrex\n\t"
+ "mrc p15, 0, r0, c1, c0, 1 @ get AUXCR\n\t"
+ "bic r0, r0, #(1 << 6) @ disable local coherency\n\t"
+ "mcr p15, 0, r0, c1, c0, 1 @ set AUXCR\n\t"
+ "isb\n\t"
+ "dsb\n\t"
+ "ldr fp, [sp], #4"
+ : : : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
+ "r9", "r10", "lr", "memory");
+
+ }
+ __mcpm_cpu_down(cpu, cluster);
+
+ if (!skip_wfi) {
+ exynos_core_power_down(cpu, cluster);
+ wfi();
+ }
+}
+
+static const struct mcpm_platform_ops exynos_power_ops = {
+ .power_up = exynos_power_up,
+ .power_down = exynos_power_down,
+};
+
+static void __init edcs_data_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 >= EDCS_CPUS_PER_CLUSTER || cluster >= EDCS_CLUSTERS);
+ edcs_use_count[cpu][cluster] = 1;
+ ++core_count[cluster];
+}
+
+/*
+ * Enable cluster-level coherency, in preparation for turning on the MMU.
+ */
+static void __naked edcs_power_up_setup(unsigned int affinity_level)
+{
+ asm volatile ("\n"
+ "b cci_enable_port_for_self");
+}
+
+static int __init edcs_init(void)
+{
+ int ret;
+ struct device_node *node;
+
+ node = of_find_compatible_node(NULL, NULL, "samsung,exynos5410");
+ if (!node)
+ return -ENODEV;
+
+ if (!cci_probed())
+ return -ENODEV;
+
+ /*
+ * Future entries into the kernel can now go
+ * through the cluster entry vectors.
+ */
+ __raw_writel(virt_to_phys(mcpm_entry_point),
+ S5P_VA_SYSRAM_NS + 0x1c);
+
+ edcs_data_init();
+ mcpm_smp_set_ops();
+
+ ret = mcpm_platform_register(&exynos_power_ops);
+ if (!ret) {
+ mcpm_sync_init(edcs_power_up_setup);
+ pr_info("EDCS power management initialized\n");
+ }
+ return ret;
+}
+
+early_initcall(edcs_init);
--
1.8.1.5

2013-10-16 22:15:11

by Kevin Hilman

[permalink] [raw]
Subject: Re: [PATCH v2 0/4] Exynos 5410 Dual cluster support

Vyacheslav Tyrtov <[email protected]> writes:

> The series of patches represent support of Exynos 5410 SoC
>
> The Exynos 5410 is the first Samsung SoC based on bigLITTLE architecture.
> Patches allow all 8 CPU cores (4 x A7 and 4 x A15) to run at the same time
>
> Patches add new platform description, support of clock controller,
> dual cluster support and device tree for Exynos 5410
>
> Has been build on v3.12-rc5.
> Has been tested on Exynos 5410 reference board (exynos_defconfig).

Has anyone tried this on the exynos5410 based odroid-xu yet?

I tried booting this on my recently arrived odroid-xu, but am not
getting it to boot.

I'm not yet terribly familiar with this SoC, what are the settings
needed for DEBUG_LL on this board?

Thanks,

Kevin

2013-10-17 10:45:37

by Daniel Lezcano

[permalink] [raw]
Subject: Re: [PATCH v2 3/4] ARM: EXYNOS: add Exynos Dual Cluster Support

On 10/14/2013 05:08 PM, Vyacheslav Tyrtov wrote:
> From: Tarek Dakhran <[email protected]>
>
> Add EDCS(Exynos Dual Cluster Support) for Samsung Exynos5410 SoC.
> This enables all 8 cores, 4 x A7 and 4 x A15 run at the same time.

IIUC, the 5410 has a CCI-400 bug preventing to use the two clusters at
the same time. Right ? Could you explain how you fixed it ?

> Signed-off-by: Tarek Dakhran <[email protected]>
> Signed-off-by: Vyacheslav Tyrtov <[email protected]>
> ---
> arch/arm/mach-exynos/Makefile | 2 +
> arch/arm/mach-exynos/edcs.c | 270 ++++++++++++++++++++++++++++++++++++++++++
> 2 files changed, 272 insertions(+)
> create mode 100644 arch/arm/mach-exynos/edcs.c
>
> diff --git a/arch/arm/mach-exynos/Makefile b/arch/arm/mach-exynos/Makefile
> index 5369615..ba6efdb 100644
> --- a/arch/arm/mach-exynos/Makefile
> +++ b/arch/arm/mach-exynos/Makefile
> @@ -34,3 +34,5 @@ AFLAGS_exynos-smc.o :=-Wa,-march=armv7-a$(plus_sec)
>
> obj-$(CONFIG_MACH_EXYNOS4_DT) += mach-exynos4-dt.o
> obj-$(CONFIG_MACH_EXYNOS5_DT) += mach-exynos5-dt.o
> +
> +obj-$(CONFIG_SOC_EXYNOS5410) += edcs.o
> diff --git a/arch/arm/mach-exynos/edcs.c b/arch/arm/mach-exynos/edcs.c
> new file mode 100644
> index 0000000..e304bd9
> --- /dev/null
> +++ b/arch/arm/mach-exynos/edcs.c
> @@ -0,0 +1,270 @@
> +/*
> + * arch/arm/mach-exynos/edcs.c - exynos dual cluster power management support
> + *
> + * Copyright (c) 2013 Samsung Electronics Co., Ltd.
> + * Author: Tarek Dakhran <[email protected]>
> + *
> + * 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.
> + *
> + * EDCS(exynos dual cluster support) for Exynos5410 SoC.
> + */
> +
> +#include <linux/init.h>
> +#include <linux/io.h>
> +#include <linux/of_address.h>
> +#include <linux/spinlock.h>
> +#include <linux/errno.h>
> +
> +#include <asm/mcpm.h>
> +#include <asm/proc-fns.h>
> +#include <asm/cacheflush.h>
> +#include <asm/cputype.h>
> +#include <asm/cp15.h>
> +
> +#include <linux/arm-cci.h>
> +#include <mach/regs-pmu.h>
> +
> +#define EDCS_CPUS_PER_CLUSTER 4
> +#define EDCS_CLUSTERS 2
> +
> +/* Exynos5410 power management registers */
> +#define EDCS_CORE_CONFIGURATION(_nr) (S5P_ARM_CORE0_CONFIGURATION \
> + + ((_nr) * 0x80))
> +#define EDCS_CORE_STATUS(_nr) (EDCS_CORE_CONFIGURATION(_nr) + 0x4)
> +#define EDCS_CORE_OPTION(_nr) (EDCS_CORE_CONFIGURATION(_nr) + 0x8)
> +
> +#define REG_CPU_STATE_ADDR0 (S5P_VA_SYSRAM_NS + 0x28)
> +#define REG_CPU_STATE_ADDR(_nr) (REG_CPU_STATE_ADDR0 + \
> + _nr * EDCS_CPUS_PER_CLUSTER)
> +
> +static arch_spinlock_t edcs_lock = __ARCH_SPIN_LOCK_UNLOCKED;
> +
> +static int edcs_use_count[EDCS_CPUS_PER_CLUSTER][EDCS_CLUSTERS];
> +static int core_count[EDCS_CLUSTERS];
> +
> +static void exynos_core_power_control(unsigned int cpu, unsigned int cluster,
> + bool enable)
> +{
> + unsigned int offset = cluster * EDCS_CPUS_PER_CLUSTER + cpu;
> + int value = enable ? S5P_CORE_LOCAL_PWR_EN : 0;
> +
> + if ((__raw_readl(EDCS_CORE_STATUS(offset)) & 0x3) != value)
> + __raw_writel(value, EDCS_CORE_CONFIGURATION(offset));
> +}
> +
> +static void exynos_core_power_up(unsigned int cpu, unsigned int cluster)
> +{
> + exynos_core_power_control(cpu, cluster, true);
> +}
> +
> +static void exynos_core_power_down(unsigned int cpu, unsigned int cluster)
> +{
> + exynos_core_power_control(cpu, cluster, false);
> +}
> +
> +void set_boot_flag(unsigned int cpu, unsigned int mode)
> +{
> + __raw_writel(mode, REG_CPU_STATE_ADDR(cpu));
> +}
> +
> +static int exynos_power_up(unsigned int cpu, unsigned int cluster)
> +{
> + pr_debug("%s: cpu %u cluster %u\n", __func__, cpu, cluster);
> + BUG_ON(cpu >= EDCS_CPUS_PER_CLUSTER || cluster >= EDCS_CLUSTERS);
> +
> + local_irq_disable();
> + arch_spin_lock(&edcs_lock);
> +
> + edcs_use_count[cpu][cluster]++;
> + if (edcs_use_count[cpu][cluster] == 1) {
> + ++core_count[cluster];
> + set_boot_flag(cpu, 0x2);
> + exynos_core_power_up(cpu, cluster);
> + } else if (edcs_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(&edcs_lock);
> + local_irq_enable();
> +
> + return 0;
> +}
> +static void exynos_power_down(void)
> +{
> + unsigned int mpidr, cpu, cluster;
> + bool last_man = false, skip_wfi = false;
> +
> + 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 >= EDCS_CPUS_PER_CLUSTER || cluster >= EDCS_CLUSTERS);
> +
> + __mcpm_cpu_going_down(cpu, cluster);
> +
> + arch_spin_lock(&edcs_lock);
> + BUG_ON(__mcpm_cluster_state(cluster) != CLUSTER_UP);
> + edcs_use_count[cpu][cluster]--;
> + if (edcs_use_count[cpu][cluster] == 0) {
> + --core_count[cluster];
> + if (core_count[cluster] == 0)
> + last_man = true;
> + } else if (edcs_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(&edcs_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));
> + }
> +
> + /*
> + * We need to disable and flush the whole (L1 and L2) cache.
> + * Let's do it in the safest possible way i.e. with
> + * no memory access within the following sequence
> + * including the stack.
> + *
> + * Note: fp is preserved to the stack explicitly prior doing
> + * this since adding it to the clobber list is incompatible
> + * with having CONFIG_FRAME_POINTER=y.
> + */
> + asm volatile(
> + "str fp, [sp, #-4]!\n\t"
> + "mrc p15, 0, r0, c1, c0, 0 @ get CR\n\t"
> + "bic r0, r0, #"__stringify(CR_C)"\n\t"
> + "mcr p15, 0, r0, c1, c0, 0 @ set CR\n\t"
> + "isb\n\t"
> + "bl v7_flush_dcache_all\n\t"
> + "clrex\n\t"
> + "mrc p15, 0, r0, c1, c0, 1 @ get AUXCR\n\t"
> + "bic r0, r0, #(1 << 6) @ disable local coherency\n\t"
> + "mcr p15, 0, r0, c1, c0, 1 @ set AUXCR\n\t"
> + "isb\n\t"
> + "dsb\n\t"
> + "ldr fp, [sp], #4"
> + : : : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
> + "r9", "r10", "lr", "memory");
> +
> + cci_disable_port_by_cpu(mpidr);
> +
> + __mcpm_outbound_leave_critical(cluster, CLUSTER_DOWN);
> +
> + } else {
> + arch_spin_unlock(&edcs_lock);
> + /*
> + * We need to disable and flush only the L1 cache.
> + * Let's do it in the safest possible way as above.
> + */
> + asm volatile(
> + "str fp, [sp, #-4]!\n\t"
> + "mrc p15, 0, r0, c1, c0, 0 @ get CR\n\t"
> + "bic r0, r0, #"__stringify(CR_C)"\n\t"
> + "mcr p15, 0, r0, c1, c0, 0 @ set CR\n\t"
> + "isb\n\t"
> + "bl v7_flush_dcache_louis\n\t"
> + "clrex\n\t"
> + "mrc p15, 0, r0, c1, c0, 1 @ get AUXCR\n\t"
> + "bic r0, r0, #(1 << 6) @ disable local coherency\n\t"
> + "mcr p15, 0, r0, c1, c0, 1 @ set AUXCR\n\t"
> + "isb\n\t"
> + "dsb\n\t"
> + "ldr fp, [sp], #4"
> + : : : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
> + "r9", "r10", "lr", "memory");
> +
> + }
> + __mcpm_cpu_down(cpu, cluster);
> +
> + if (!skip_wfi) {
> + exynos_core_power_down(cpu, cluster);
> + wfi();
> + }
> +}

I did not looked line by line but these functions looks very similar
than the tc2_pm.c's function. no ?

May be some code consolidation could be considered here.

Added Nico and Lorenzo in Cc.

Thanks
-- Daniel

> +static const struct mcpm_platform_ops exynos_power_ops = {
> + .power_up = exynos_power_up,
> + .power_down = exynos_power_down,
> +};
> +
> +static void __init edcs_data_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 >= EDCS_CPUS_PER_CLUSTER || cluster >= EDCS_CLUSTERS);
> + edcs_use_count[cpu][cluster] = 1;
> + ++core_count[cluster];
> +}
> +
> +/*
> + * Enable cluster-level coherency, in preparation for turning on the MMU.
> + */
> +static void __naked edcs_power_up_setup(unsigned int affinity_level)
> +{
> + asm volatile ("\n"
> + "b cci_enable_port_for_self");
> +}
> +
> +static int __init edcs_init(void)
> +{
> + int ret;
> + struct device_node *node;
> +
> + node = of_find_compatible_node(NULL, NULL, "samsung,exynos5410");
> + if (!node)
> + return -ENODEV;
> +
> + if (!cci_probed())
> + return -ENODEV;
> +
> + /*
> + * Future entries into the kernel can now go
> + * through the cluster entry vectors.
> + */
> + __raw_writel(virt_to_phys(mcpm_entry_point),
> + S5P_VA_SYSRAM_NS + 0x1c);
> +
> + edcs_data_init();
> + mcpm_smp_set_ops();
> +
> + ret = mcpm_platform_register(&exynos_power_ops);
> + if (!ret) {
> + mcpm_sync_init(edcs_power_up_setup);
> + pr_info("EDCS power management initialized\n");
> + }
> + return ret;
> +}
> +
> +early_initcall(edcs_init);
>


--
<http://www.linaro.org/> Linaro.org │ Open source software for ARM SoCs

Follow Linaro: <http://www.facebook.com/pages/Linaro> Facebook |
<http://twitter.com/#!/linaroorg> Twitter |
<http://www.linaro.org/linaro-blog/> Blog

2013-10-17 12:24:23

by Aliaksei Katovich

[permalink] [raw]
Subject: Re: [PATCH v2 0/4] Exynos 5410 Dual cluster support

hi Kevin;

> Vyacheslav Tyrtov <[email protected]> writes:
>
> > The series of patches represent support of Exynos 5410 SoC
> >
> > The Exynos 5410 is the first Samsung SoC based on bigLITTLE architecture.
> > Patches allow all 8 CPU cores (4 x A7 and 4 x A15) to run at the same time
> >
> > Patches add new platform description, support of clock controller,
> > dual cluster support and device tree for Exynos 5410
> >
> > Has been build on v3.12-rc5.
> > Has been tested on Exynos 5410 reference board (exynos_defconfig).
>
> Has anyone tried this on the exynos5410 based odroid-xu yet?
>
> I tried booting this on my recently arrived odroid-xu, but am not
> getting it to boot.

I am able to boot my odroid-xu+e to busybox with these patches applied
against 3.12-rc5: exynos_defconfig and exynos5410-smdk5410.dtb were
used.

However there seem to be some issues with virq allocations, check log
in attachment.

--
Aliaksei

>
> I'm not yet terribly familiar with this SoC, what are the settings
> needed for DEBUG_LL on this board?
>
> Thanks,
>
> Kevin
>
> _______________________________________________
> linux-arm-kernel mailing list
> [email protected]
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>


Attachments:
(No filename) (1.25 kB)
odroid-xu.log (127.36 kB)
Download all attachments

2013-10-17 13:04:44

by Aliaksei Katovich

[permalink] [raw]
Subject: Re: [PATCH v2 0/4] Exynos 5410 Dual cluster support

hi Kevin;

> Vyacheslav Tyrtov <[email protected]> writes:
>
> > The series of patches represent support of Exynos 5410 SoC
> >
> > The Exynos 5410 is the first Samsung SoC based on bigLITTLE architecture.
> > Patches allow all 8 CPU cores (4 x A7 and 4 x A15) to run at the same time
> >
> > Patches add new platform description, support of clock controller,
> > dual cluster support and device tree for Exynos 5410
> >
> > Has been build on v3.12-rc5.
> > Has been tested on Exynos 5410 reference board (exynos_defconfig).
>
> Has anyone tried this on the exynos5410 based odroid-xu yet?
>
> I tried booting this on my recently arrived odroid-xu, but am not
> getting it to boot.

I am able to boot my odroid-xu+e to busybox with these patches applied
against 3.12-rc5: exynos_defconfig and exynos5410-smdk5410.dtb were
used.

However there seem to be some issues with virq allocations, like this:

<snippet>
Starting kernel ...

[ 0.000000] [<c0014d48>] (unwind_backtrace+0x0/0xf8) from [<c00117d0>] (show_stack+0x10/0x14)
[ 0.000000] [<c00117d0>] (show_stack+0x10/0x14) from [<c0363488>] (dump_stack+0x6c/0xac)
[ 0.000000] [<c0363488>] (dump_stack+0x6c/0xac) from [<c001e330>] (warn_slowpath_common+0x64/0x88)
[ 0.000000] [<c001e330>] (warn_slowpath_common+0x64/0x88) from [<c001e3e8>] (warn_slowpath_fmt+0x30/0x40)
[ 0.000000] [<c001e3e8>] (warn_slowpath_fmt+0x30/0x40) from [<c005a1b4>] (irq_domain_associate+0x128/0x1a8)
[ 0.000000] [<c005a1b4>] (irq_domain_associate+0x128/0x1a8) from [<c005a508>] (irq_domain_associate_many+0x30/0x3c
)
[ 0.000000] [<c005a508>] (irq_domain_associate_many+0x30/0x3c) from [<c005a768>] (irq_domain_add_simple+0x78/0x90)
[ 0.000000] [<c005a768>] (irq_domain_add_simple+0x78/0x90) from [<c04b044c>] (combiner_of_init+0xb4/0x198)
[ 0.000000] [<c04b044c>] (combiner_of_init+0xb4/0x198) from [<c04b6938>] (of_irq_init+0x278/0x2a0)
[ 0.000000] [<c04b6938>] (of_irq_init+0x278/0x2a0) from [<c049b8fc>] (start_kernel+0x18c/0x384)
[ 0.000000] [<c049b8fc>] (start_kernel+0x18c/0x384) from [<40008074>] (0x40008074)
[ 0.000000] ---[ end trace 1b75b31a2719edcd ]---
[ 0.000000] ------------[ cut here ]------------
[ 0.000000] WARNING: CPU: 0 PID: 0 at kernel/irq/irqdomain.c:278 irq_domain_associate+0x128/0x1a8()
[ 0.000000] error: virq337 is not allocated
[ 0.000000] Modules linked in:
[ 0.000000] CPU: 0 PID: 0 Comm: swapper/0 Tainted: G W 3.12.0-rc5-00004-g1cb405f #1
[ 0.000000] [<c0014d48>] (unwind_backtrace+0x0/0xf8) from [<c00117d0>] (show_stack+0x10/0x14)
[ 0.000000] [<c00117d0>] (show_stack+0x10/0x14) from [<c0363488>] (dump_stack+0x6c/0xac)
[ 0.000000] [<c0363488>] (dump_stack+0x6c/0xac) from [<c001e330>] (warn_slowpath_common+0x64/0x88)
[ 0.000000] [<c001e330>] (warn_slowpath_common+0x64/0x88) from [<c001e3e8>] (warn_slowpath_fmt+0x30/0x40)
[ 0.000000] [<c001e3e8>] (warn_slowpath_fmt+0x30/0x40) from [<c005a1b4>] (irq_domain_associate+0x128/0x1a8)
[ 0.000000] [<c005a1b4>] (irq_domain_associate+0x128/0x1a8) from [<c005a508>] (irq_domain_associate_many+0x30/0x3c
)
[ 0.000000] [<c005a508>] (irq_domain_associate_many+0x30/0x3c) from [<c005a768>] (irq_domain_add_simple+0x78/0x90)
[ 0.000000] [<c005a768>] (irq_domain_add_simple+0x78/0x90) from [<c04b044c>] (combiner_of_init+0xb4/0x198)
[ 0.000000] [<c04b044c>] (combiner_of_init+0xb4/0x198) from [<c04b6938>] (of_irq_init+0x278/0x2a0)
[ 0.000000] [<c04b6938>] (of_irq_init+0x278/0x2a0) from [<c049b8fc>] (start_kernel+0x18c/0x384)
[ 0.000000] [<c049b8fc>] (start_kernel+0x18c/0x384) from [<40008074>] (0x40008074)
[ 0.000000] ---[ end trace 1b75b31a2719edce ]---
[ 0.000000] ------------[ cut here ]------------
</snippet>

You can check full boot log here http://sprunge.us/NKcU

--
Aliaksei

>
> I'm not yet terribly familiar with this SoC, what are the settings
> needed for DEBUG_LL on this board?
>
> Thanks,
>
> Kevin
>
> _______________________________________________
> linux-arm-kernel mailing list
> [email protected]
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>

2013-10-17 13:53:22

by Tarek Dakhran

[permalink] [raw]
Subject: Re: [PATCH v2 0/4] Exynos 5410 Dual cluster support

On 17.10.2013 17:04, Aliaksei Katovich wrote:
> hi Kevin;
>
>> Vyacheslav Tyrtov <[email protected]> writes:
>>
>>> The series of patches represent support of Exynos 5410 SoC
>>>
>>> The Exynos 5410 is the first Samsung SoC based on bigLITTLE architecture.
>>> Patches allow all 8 CPU cores (4 x A7 and 4 x A15) to run at the same time
>>>
>>> Patches add new platform description, support of clock controller,
>>> dual cluster support and device tree for Exynos 5410
>>>
>>> Has been build on v3.12-rc5.
>>> Has been tested on Exynos 5410 reference board (exynos_defconfig).
>> Has anyone tried this on the exynos5410 based odroid-xu yet?
>>
>> I tried booting this on my recently arrived odroid-xu, but am not
>> getting it to boot.
> I am able to boot my odroid-xu+e to busybox with these patches applied
> against 3.12-rc5: exynos_defconfig and exynos5410-smdk5410.dtb were
> used.
>
> However there seem to be some issues with virq allocations, like this:
>
> <snippet>
> Starting kernel ...
>
> [ 0.000000] [<c0014d48>] (unwind_backtrace+0x0/0xf8) from [<c00117d0>] (show_stack+0x10/0x14)
> [ 0.000000] [<c00117d0>] (show_stack+0x10/0x14) from [<c0363488>] (dump_stack+0x6c/0xac)
> [ 0.000000] [<c0363488>] (dump_stack+0x6c/0xac) from [<c001e330>] (warn_slowpath_common+0x64/0x88)
> [ 0.000000] [<c001e330>] (warn_slowpath_common+0x64/0x88) from [<c001e3e8>] (warn_slowpath_fmt+0x30/0x40)
> [ 0.000000] [<c001e3e8>] (warn_slowpath_fmt+0x30/0x40) from [<c005a1b4>] (irq_domain_associate+0x128/0x1a8)
> [ 0.000000] [<c005a1b4>] (irq_domain_associate+0x128/0x1a8) from [<c005a508>] (irq_domain_associate_many+0x30/0x3c
> )
> [ 0.000000] [<c005a508>] (irq_domain_associate_many+0x30/0x3c) from [<c005a768>] (irq_domain_add_simple+0x78/0x90)
> [ 0.000000] [<c005a768>] (irq_domain_add_simple+0x78/0x90) from [<c04b044c>] (combiner_of_init+0xb4/0x198)
> [ 0.000000] [<c04b044c>] (combiner_of_init+0xb4/0x198) from [<c04b6938>] (of_irq_init+0x278/0x2a0)
> [ 0.000000] [<c04b6938>] (of_irq_init+0x278/0x2a0) from [<c049b8fc>] (start_kernel+0x18c/0x384)
> [ 0.000000] [<c049b8fc>] (start_kernel+0x18c/0x384) from [<40008074>] (0x40008074)
> [ 0.000000] ---[ end trace 1b75b31a2719edcd ]---
> [ 0.000000] ------------[ cut here ]------------
> [ 0.000000] WARNING: CPU: 0 PID: 0 at kernel/irq/irqdomain.c:278 irq_domain_associate+0x128/0x1a8()
> [ 0.000000] error: virq337 is not allocated
> [ 0.000000] Modules linked in:
> [ 0.000000] CPU: 0 PID: 0 Comm: swapper/0 Tainted: G W 3.12.0-rc5-00004-g1cb405f #1
> [ 0.000000] [<c0014d48>] (unwind_backtrace+0x0/0xf8) from [<c00117d0>] (show_stack+0x10/0x14)
> [ 0.000000] [<c00117d0>] (show_stack+0x10/0x14) from [<c0363488>] (dump_stack+0x6c/0xac)
> [ 0.000000] [<c0363488>] (dump_stack+0x6c/0xac) from [<c001e330>] (warn_slowpath_common+0x64/0x88)
> [ 0.000000] [<c001e330>] (warn_slowpath_common+0x64/0x88) from [<c001e3e8>] (warn_slowpath_fmt+0x30/0x40)
> [ 0.000000] [<c001e3e8>] (warn_slowpath_fmt+0x30/0x40) from [<c005a1b4>] (irq_domain_associate+0x128/0x1a8)
> [ 0.000000] [<c005a1b4>] (irq_domain_associate+0x128/0x1a8) from [<c005a508>] (irq_domain_associate_many+0x30/0x3c
> )
> [ 0.000000] [<c005a508>] (irq_domain_associate_many+0x30/0x3c) from [<c005a768>] (irq_domain_add_simple+0x78/0x90)
> [ 0.000000] [<c005a768>] (irq_domain_add_simple+0x78/0x90) from [<c04b044c>] (combiner_of_init+0xb4/0x198)
> [ 0.000000] [<c04b044c>] (combiner_of_init+0xb4/0x198) from [<c04b6938>] (of_irq_init+0x278/0x2a0)
> [ 0.000000] [<c04b6938>] (of_irq_init+0x278/0x2a0) from [<c049b8fc>] (start_kernel+0x18c/0x384)
> [ 0.000000] [<c049b8fc>] (start_kernel+0x18c/0x384) from [<40008074>] (0x40008074)
> [ 0.000000] ---[ end trace 1b75b31a2719edce ]---
> [ 0.000000] ------------[ cut here ]------------
> </snippet>
>
> You can check full boot log here http://sprunge.us/NKcU
>
> --
> Aliaksei
>
>> I'm not yet terribly familiar with this SoC, what are the settings
>> needed for DEBUG_LL on this board?
>>
>> Thanks,
>>
>> Kevin
>>
>> _______________________________________________
>> linux-arm-kernel mailing list
>> [email protected]
>> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>>
This will be fixed in 3.13.

Now you can just change "irq_base = 160" to "irq_base = 256"
in "static int __init combiner_of_init(struct device_node *np, struct
device_node *parent)" function
in "drivers/irqchip/exynos-combiner.c"

Best regards,
Tarek Dakhran

2013-10-17 14:02:22

by Tarek Dakhran

[permalink] [raw]
Subject: Re: [PATCH v2 0/4] Exynos 5410 Dual cluster support

On 17.10.2013 17:04, Aliaksei Katovich wrote:
> hi Kevin;
>
>> Vyacheslav Tyrtov <[email protected]> writes:
>>
>>> The series of patches represent support of Exynos 5410 SoC
>>>
>>> The Exynos 5410 is the first Samsung SoC based on bigLITTLE architecture.
>>> Patches allow all 8 CPU cores (4 x A7 and 4 x A15) to run at the same time
>>>
>>> Patches add new platform description, support of clock controller,
>>> dual cluster support and device tree for Exynos 5410
>>>
>>> Has been build on v3.12-rc5.
>>> Has been tested on Exynos 5410 reference board (exynos_defconfig).
>> Has anyone tried this on the exynos5410 based odroid-xu yet?
>>
>> I tried booting this on my recently arrived odroid-xu, but am not
>> getting it to boot.
> I am able to boot my odroid-xu+e to busybox with these patches applied
> against 3.12-rc5: exynos_defconfig and exynos5410-smdk5410.dtb were
> used.
>
> However there seem to be some issues with virq allocations, like this:
>
> <snippet>
> Starting kernel ...
>
> [ 0.000000] [<c0014d48>] (unwind_backtrace+0x0/0xf8) from [<c00117d0>] (show_stack+0x10/0x14)
> [ 0.000000] [<c00117d0>] (show_stack+0x10/0x14) from [<c0363488>] (dump_stack+0x6c/0xac)
> [ 0.000000] [<c0363488>] (dump_stack+0x6c/0xac) from [<c001e330>] (warn_slowpath_common+0x64/0x88)
> [ 0.000000] [<c001e330>] (warn_slowpath_common+0x64/0x88) from [<c001e3e8>] (warn_slowpath_fmt+0x30/0x40)
> [ 0.000000] [<c001e3e8>] (warn_slowpath_fmt+0x30/0x40) from [<c005a1b4>] (irq_domain_associate+0x128/0x1a8)
> [ 0.000000] [<c005a1b4>] (irq_domain_associate+0x128/0x1a8) from [<c005a508>] (irq_domain_associate_many+0x30/0x3c
> )
> [ 0.000000] [<c005a508>] (irq_domain_associate_many+0x30/0x3c) from [<c005a768>] (irq_domain_add_simple+0x78/0x90)
> [ 0.000000] [<c005a768>] (irq_domain_add_simple+0x78/0x90) from [<c04b044c>] (combiner_of_init+0xb4/0x198)
> [ 0.000000] [<c04b044c>] (combiner_of_init+0xb4/0x198) from [<c04b6938>] (of_irq_init+0x278/0x2a0)
> [ 0.000000] [<c04b6938>] (of_irq_init+0x278/0x2a0) from [<c049b8fc>] (start_kernel+0x18c/0x384)
> [ 0.000000] [<c049b8fc>] (start_kernel+0x18c/0x384) from [<40008074>] (0x40008074)
> [ 0.000000] ---[ end trace 1b75b31a2719edcd ]---
> [ 0.000000] ------------[ cut here ]------------
> [ 0.000000] WARNING: CPU: 0 PID: 0 at kernel/irq/irqdomain.c:278 irq_domain_associate+0x128/0x1a8()
> [ 0.000000] error: virq337 is not allocated
> [ 0.000000] Modules linked in:
> [ 0.000000] CPU: 0 PID: 0 Comm: swapper/0 Tainted: G W 3.12.0-rc5-00004-g1cb405f #1
> [ 0.000000] [<c0014d48>] (unwind_backtrace+0x0/0xf8) from [<c00117d0>] (show_stack+0x10/0x14)
> [ 0.000000] [<c00117d0>] (show_stack+0x10/0x14) from [<c0363488>] (dump_stack+0x6c/0xac)
> [ 0.000000] [<c0363488>] (dump_stack+0x6c/0xac) from [<c001e330>] (warn_slowpath_common+0x64/0x88)
> [ 0.000000] [<c001e330>] (warn_slowpath_common+0x64/0x88) from [<c001e3e8>] (warn_slowpath_fmt+0x30/0x40)
> [ 0.000000] [<c001e3e8>] (warn_slowpath_fmt+0x30/0x40) from [<c005a1b4>] (irq_domain_associate+0x128/0x1a8)
> [ 0.000000] [<c005a1b4>] (irq_domain_associate+0x128/0x1a8) from [<c005a508>] (irq_domain_associate_many+0x30/0x3c
> )
> [ 0.000000] [<c005a508>] (irq_domain_associate_many+0x30/0x3c) from [<c005a768>] (irq_domain_add_simple+0x78/0x90)
> [ 0.000000] [<c005a768>] (irq_domain_add_simple+0x78/0x90) from [<c04b044c>] (combiner_of_init+0xb4/0x198)
> [ 0.000000] [<c04b044c>] (combiner_of_init+0xb4/0x198) from [<c04b6938>] (of_irq_init+0x278/0x2a0)
> [ 0.000000] [<c04b6938>] (of_irq_init+0x278/0x2a0) from [<c049b8fc>] (start_kernel+0x18c/0x384)
> [ 0.000000] [<c049b8fc>] (start_kernel+0x18c/0x384) from [<40008074>] (0x40008074)
> [ 0.000000] ---[ end trace 1b75b31a2719edce ]---
> [ 0.000000] ------------[ cut here ]------------
> </snippet>
>
> You can check full boot log here http://sprunge.us/NKcU
>
> --
> Aliaksei
>
>> I'm not yet terribly familiar with this SoC, what are the settings
>> needed for DEBUG_LL on this board?
>>
>> Thanks,
>>
>> Kevin
>>
>> _______________________________________________
>> linux-arm-kernel mailing list
>> [email protected]
>> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>>
Also change NR_CPUS to 8 in kernel config, so you will get 8 cores
booted instead of 2.

Best regards,
Tarek Dakhran

2013-10-17 14:25:05

by Aliaksei Katovich

[permalink] [raw]
Subject: Re: [PATCH v2 0/4] Exynos 5410 Dual cluster support

hi Tarek;

<skip>

> > However there seem to be some issues with virq allocations, like this:
> >
> > <snippet>
> > Starting kernel ...
> >
> > [ 0.000000] [<c0014d48>] (unwind_backtrace+0x0/0xf8) from [<c00117d0>] (show_stack+0x10/0x14)
> > [ 0.000000] [<c00117d0>] (show_stack+0x10/0x14) from [<c0363488>] (dump_stack+0x6c/0xac)
> > [ 0.000000] [<c0363488>] (dump_stack+0x6c/0xac) from [<c001e330>] (warn_slowpath_common+0x64/0x88)
> > [ 0.000000] [<c001e330>] (warn_slowpath_common+0x64/0x88) from [<c001e3e8>] (warn_slowpath_fmt+0x30/0x40)
> > [ 0.000000] [<c001e3e8>] (warn_slowpath_fmt+0x30/0x40) from [<c005a1b4>] (irq_domain_associate+0x128/0x1a8)
> > [ 0.000000] [<c005a1b4>] (irq_domain_associate+0x128/0x1a8) from [<c005a508>] (irq_domain_associate_many+0x30/0x3c
> > )
> > [ 0.000000] [<c005a508>] (irq_domain_associate_many+0x30/0x3c) from [<c005a768>] (irq_domain_add_simple+0x78/0x90)
> > [ 0.000000] [<c005a768>] (irq_domain_add_simple+0x78/0x90) from [<c04b044c>] (combiner_of_init+0xb4/0x198)
> > [ 0.000000] [<c04b044c>] (combiner_of_init+0xb4/0x198) from [<c04b6938>] (of_irq_init+0x278/0x2a0)
> > [ 0.000000] [<c04b6938>] (of_irq_init+0x278/0x2a0) from [<c049b8fc>] (start_kernel+0x18c/0x384)
> > [ 0.000000] [<c049b8fc>] (start_kernel+0x18c/0x384) from [<40008074>] (0x40008074)
> > [ 0.000000] ---[ end trace 1b75b31a2719edcd ]---
> > [ 0.000000] ------------[ cut here ]------------
> > [ 0.000000] WARNING: CPU: 0 PID: 0 at kernel/irq/irqdomain.c:278 irq_domain_associate+0x128/0x1a8()
> > [ 0.000000] error: virq337 is not allocated
> > [ 0.000000] Modules linked in:
> > [ 0.000000] CPU: 0 PID: 0 Comm: swapper/0 Tainted: G W 3.12.0-rc5-00004-g1cb405f #1
> > [ 0.000000] [<c0014d48>] (unwind_backtrace+0x0/0xf8) from [<c00117d0>] (show_stack+0x10/0x14)
> > [ 0.000000] [<c00117d0>] (show_stack+0x10/0x14) from [<c0363488>] (dump_stack+0x6c/0xac)
> > [ 0.000000] [<c0363488>] (dump_stack+0x6c/0xac) from [<c001e330>] (warn_slowpath_common+0x64/0x88)
> > [ 0.000000] [<c001e330>] (warn_slowpath_common+0x64/0x88) from [<c001e3e8>] (warn_slowpath_fmt+0x30/0x40)
> > [ 0.000000] [<c001e3e8>] (warn_slowpath_fmt+0x30/0x40) from [<c005a1b4>] (irq_domain_associate+0x128/0x1a8)
> > [ 0.000000] [<c005a1b4>] (irq_domain_associate+0x128/0x1a8) from [<c005a508>] (irq_domain_associate_many+0x30/0x3c
> > )
> > [ 0.000000] [<c005a508>] (irq_domain_associate_many+0x30/0x3c) from [<c005a768>] (irq_domain_add_simple+0x78/0x90)
> > [ 0.000000] [<c005a768>] (irq_domain_add_simple+0x78/0x90) from [<c04b044c>] (combiner_of_init+0xb4/0x198)
> > [ 0.000000] [<c04b044c>] (combiner_of_init+0xb4/0x198) from [<c04b6938>] (of_irq_init+0x278/0x2a0)
> > [ 0.000000] [<c04b6938>] (of_irq_init+0x278/0x2a0) from [<c049b8fc>] (start_kernel+0x18c/0x384)
> > [ 0.000000] [<c049b8fc>] (start_kernel+0x18c/0x384) from [<40008074>] (0x40008074)
> > [ 0.000000] ---[ end trace 1b75b31a2719edce ]---
> > [ 0.000000] ------------[ cut here ]------------
> > </snippet>
> This will be fixed in 3.13.
>
> Now you can just change "irq_base = 160" to "irq_base = 256"
> in "static int __init combiner_of_init(struct device_node *np, struct
> device_node *parent)" function
> in "drivers/irqchip/exynos-combiner.c"

Thanks, this works for me!

--
Aliaksei

>
> Best regards,
> Tarek Dakhran
>

2013-10-17 14:33:06

by Dave Martin

[permalink] [raw]
Subject: Re: [PATCH v2 3/4] ARM: EXYNOS: add Exynos Dual Cluster Support

On Thu, Oct 17, 2013 at 12:45:29PM +0200, Daniel Lezcano wrote:
> On 10/14/2013 05:08 PM, Vyacheslav Tyrtov wrote:
> > From: Tarek Dakhran <[email protected]>
> >
> > Add EDCS(Exynos Dual Cluster Support) for Samsung Exynos5410 SoC.
> > This enables all 8 cores, 4 x A7 and 4 x A15 run at the same time.

[...]

> > + __mcpm_cpu_down(cpu, cluster);
> > +
> > + if (!skip_wfi) {
> > + exynos_core_power_down(cpu, cluster);
> > + wfi();
> > + }
> > +}
>
> I did not looked line by line but these functions looks very similar
> than the tc2_pm.c's function. no ?

This is true.

> May be some code consolidation could be considered here.
>
> Added Nico and Lorenzo in Cc.
>
> Thanks
> -- Daniel

Nico can commnent further, but I think the main concern here was that
this code shouldn't be factored prematurely.

There are many low-level platform specifics involved here, so it's
hard to be certain that all platforms could fit into a more abstracted
framework until we have some evidence to look at.

This could be revisited when we have a few diverse MCPM ports to
compare.


The low-level A15/A7 cacheflush sequence is already being factored
by Nico [1].

Cheers
---Dave

[1] http://lists.infradead.org/pipermail/linux-arm-kernel/2013-October/205085.html
[PATCH] ARM: cacheflush: consolidate single-CPU ARMv7 cache disabling code

[...]

2013-10-17 15:47:56

by Dave Martin

[permalink] [raw]
Subject: Re: [PATCH v2 3/4] ARM: EXYNOS: add Exynos Dual Cluster Support

On Mon, Oct 14, 2013 at 07:08:24PM +0400, Vyacheslav Tyrtov wrote:
> From: Tarek Dakhran <[email protected]>
>
> Add EDCS(Exynos Dual Cluster Support) for Samsung Exynos5410 SoC.
> This enables all 8 cores, 4 x A7 and 4 x A15 run at the same time.
>
> Signed-off-by: Tarek Dakhran <[email protected]>
> Signed-off-by: Vyacheslav Tyrtov <[email protected]>
> ---
> arch/arm/mach-exynos/Makefile | 2 +
> arch/arm/mach-exynos/edcs.c | 270 ++++++++++++++++++++++++++++++++++++++++++
> 2 files changed, 272 insertions(+)
> create mode 100644 arch/arm/mach-exynos/edcs.c
>
> diff --git a/arch/arm/mach-exynos/Makefile b/arch/arm/mach-exynos/Makefile
> index 5369615..ba6efdb 100644
> --- a/arch/arm/mach-exynos/Makefile
> +++ b/arch/arm/mach-exynos/Makefile
> @@ -34,3 +34,5 @@ AFLAGS_exynos-smc.o :=-Wa,-march=armv7-a$(plus_sec)
>
> obj-$(CONFIG_MACH_EXYNOS4_DT) += mach-exynos4-dt.o
> obj-$(CONFIG_MACH_EXYNOS5_DT) += mach-exynos5-dt.o
> +
> +obj-$(CONFIG_SOC_EXYNOS5410) += edcs.o
> diff --git a/arch/arm/mach-exynos/edcs.c b/arch/arm/mach-exynos/edcs.c
> new file mode 100644
> index 0000000..e304bd9
> --- /dev/null
> +++ b/arch/arm/mach-exynos/edcs.c
> @@ -0,0 +1,270 @@
> +/*
> + * arch/arm/mach-exynos/edcs.c - exynos dual cluster power management support
> + *
> + * Copyright (c) 2013 Samsung Electronics Co., Ltd.
> + * Author: Tarek Dakhran <[email protected]>
> + *
> + * 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.
> + *
> + * EDCS(exynos dual cluster support) for Exynos5410 SoC.
> + */
> +
> +#include <linux/init.h>
> +#include <linux/io.h>
> +#include <linux/of_address.h>
> +#include <linux/spinlock.h>
> +#include <linux/errno.h>
> +
> +#include <asm/mcpm.h>
> +#include <asm/proc-fns.h>
> +#include <asm/cacheflush.h>
> +#include <asm/cputype.h>
> +#include <asm/cp15.h>
> +
> +#include <linux/arm-cci.h>
> +#include <mach/regs-pmu.h>
> +
> +#define EDCS_CPUS_PER_CLUSTER 4
> +#define EDCS_CLUSTERS 2
> +
> +/* Exynos5410 power management registers */
> +#define EDCS_CORE_CONFIGURATION(_nr) (S5P_ARM_CORE0_CONFIGURATION \
> + + ((_nr) * 0x80))
> +#define EDCS_CORE_STATUS(_nr) (EDCS_CORE_CONFIGURATION(_nr) + 0x4)
> +#define EDCS_CORE_OPTION(_nr) (EDCS_CORE_CONFIGURATION(_nr) + 0x8)
> +
> +#define REG_CPU_STATE_ADDR0 (S5P_VA_SYSRAM_NS + 0x28)

Is there any reason why S5P_VA_SYSRAM_NS needs to be a static mapping?

> +#define REG_CPU_STATE_ADDR(_nr) (REG_CPU_STATE_ADDR0 + \
> + _nr * EDCS_CPUS_PER_CLUSTER)
> +
> +static arch_spinlock_t edcs_lock = __ARCH_SPIN_LOCK_UNLOCKED;
> +
> +static int edcs_use_count[EDCS_CPUS_PER_CLUSTER][EDCS_CLUSTERS];
> +static int core_count[EDCS_CLUSTERS];
> +
> +static void exynos_core_power_control(unsigned int cpu, unsigned int cluster,
> + bool enable)
> +{
> + unsigned int offset = cluster * EDCS_CPUS_PER_CLUSTER + cpu;
> + int value = enable ? S5P_CORE_LOCAL_PWR_EN : 0;
> +
> + if ((__raw_readl(EDCS_CORE_STATUS(offset)) & 0x3) != value)
> + __raw_writel(value, EDCS_CORE_CONFIGURATION(offset));

I think you need to replace all the __raw_readl() / __raw_writel() calls
in this file with readl_relaxed() / writel_relaxed().

This ensures little-endian byte order, so that BE8 kernels will work.

> +}
> +
> +static void exynos_core_power_up(unsigned int cpu, unsigned int cluster)
> +{
> + exynos_core_power_control(cpu, cluster, true);
> +}
> +
> +static void exynos_core_power_down(unsigned int cpu, unsigned int cluster)
> +{
> + exynos_core_power_control(cpu, cluster, false);
> +}
> +
> +void set_boot_flag(unsigned int cpu, unsigned int mode)
> +{
> + __raw_writel(mode, REG_CPU_STATE_ADDR(cpu));
> +}
> +
> +static int exynos_power_up(unsigned int cpu, unsigned int cluster)
> +{
> + pr_debug("%s: cpu %u cluster %u\n", __func__, cpu, cluster);
> + BUG_ON(cpu >= EDCS_CPUS_PER_CLUSTER || cluster >= EDCS_CLUSTERS);
> +
> + local_irq_disable();
> + arch_spin_lock(&edcs_lock);
> +
> + edcs_use_count[cpu][cluster]++;
> + if (edcs_use_count[cpu][cluster] == 1) {
> + ++core_count[cluster];
> + set_boot_flag(cpu, 0x2);

0x2 looks like a magic number. Can we have a #define for that?


If the boot flag is read by the inbound CPU or by a peripheral then
there are memory ordering issues to take into account. Otherwise, can't
the inbound CPU come online and race with the write to the boot flag?

What is the memory type of REG_STATE_ADDR()?

> + exynos_core_power_up(cpu, cluster);
> + } else if (edcs_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(&edcs_lock);
> + local_irq_enable();
> +
> + return 0;
> +}
> +static void exynos_power_down(void)
> +{
> + unsigned int mpidr, cpu, cluster;
> + bool last_man = false, skip_wfi = false;
> +
> + 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 >= EDCS_CPUS_PER_CLUSTER || cluster >= EDCS_CLUSTERS);
> +
> + __mcpm_cpu_going_down(cpu, cluster);
> +
> + arch_spin_lock(&edcs_lock);
> + BUG_ON(__mcpm_cluster_state(cluster) != CLUSTER_UP);
> + edcs_use_count[cpu][cluster]--;
> + if (edcs_use_count[cpu][cluster] == 0) {
> + --core_count[cluster];
> + if (core_count[cluster] == 0)
> + last_man = true;
> + } else if (edcs_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();

For TC2, Lorenzo discovered need to disable the GIC CPU interface, so
that no suprious wakeups can happen once the power controller is
configured to power the CPU down.

The problem is that a spurious wakeup can trigger a race in the power
controller when the last man powers down, where the power controller
continues to wait for the cluster to power down, but it never happens.

http://lists.infradead.org/pipermail/linux-arm-kernel/2013-September/200917.html
([PATCH v2] arm: vexpress: tc2: fix hotplug/idle/kexec race on cluster power down)


This might not be a problem for Exynos5410 -- it depends on the way the
power control logic works.

On the other hand, disabling the GIC CPU interface here is cheap to do,
even if it's not really needed.

> +
> + if (last_man && __mcpm_outbound_enter_critical(cpu, cluster)) {
> + arch_spin_unlock(&edcs_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));
> + }
> +
> + /*
> + * We need to disable and flush the whole (L1 and L2) cache.
> + * Let's do it in the safest possible way i.e. with
> + * no memory access within the following sequence
> + * including the stack.
> + *
> + * Note: fp is preserved to the stack explicitly prior doing
> + * this since adding it to the clobber list is incompatible
> + * with having CONFIG_FRAME_POINTER=y.
> + */
> + asm volatile(
> + "str fp, [sp, #-4]!\n\t"
> + "mrc p15, 0, r0, c1, c0, 0 @ get CR\n\t"
> + "bic r0, r0, #"__stringify(CR_C)"\n\t"
> + "mcr p15, 0, r0, c1, c0, 0 @ set CR\n\t"
> + "isb\n\t"
> + "bl v7_flush_dcache_all\n\t"
> + "clrex\n\t"
> + "mrc p15, 0, r0, c1, c0, 1 @ get AUXCR\n\t"
> + "bic r0, r0, #(1 << 6) @ disable local coherency\n\t"
> + "mcr p15, 0, r0, c1, c0, 1 @ set AUXCR\n\t"
> + "isb\n\t"
> + "dsb\n\t"
> + "ldr fp, [sp], #4"
> + : : : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
> + "r9", "r10", "lr", "memory");

For these code sequences, please take a look at

http://lists.infradead.org/pipermail/linux-arm-kernel/2013-October/205085.html
[PATCH] ARM: cacheflush: consolidate single-CPU ARMv7 cache disabling code

The aim is to consolidate on a macro that can be shared between
backends.

> +
> + cci_disable_port_by_cpu(mpidr);
> +
> + __mcpm_outbound_leave_critical(cluster, CLUSTER_DOWN);
> +
> + } else {
> + arch_spin_unlock(&edcs_lock);
> + /*
> + * We need to disable and flush only the L1 cache.
> + * Let's do it in the safest possible way as above.
> + */
> + asm volatile(
> + "str fp, [sp, #-4]!\n\t"
> + "mrc p15, 0, r0, c1, c0, 0 @ get CR\n\t"
> + "bic r0, r0, #"__stringify(CR_C)"\n\t"
> + "mcr p15, 0, r0, c1, c0, 0 @ set CR\n\t"
> + "isb\n\t"
> + "bl v7_flush_dcache_louis\n\t"
> + "clrex\n\t"
> + "mrc p15, 0, r0, c1, c0, 1 @ get AUXCR\n\t"
> + "bic r0, r0, #(1 << 6) @ disable local coherency\n\t"
> + "mcr p15, 0, r0, c1, c0, 1 @ set AUXCR\n\t"
> + "isb\n\t"
> + "dsb\n\t"
> + "ldr fp, [sp], #4"
> + : : : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
> + "r9", "r10", "lr", "memory");
> +
> + }
> + __mcpm_cpu_down(cpu, cluster);
> +
> + if (!skip_wfi) {
> + exynos_core_power_down(cpu, cluster);
> + wfi();
> + }
> +}
> +
> +static const struct mcpm_platform_ops exynos_power_ops = {
> + .power_up = exynos_power_up,
> + .power_down = exynos_power_down,
> +};
> +
> +static void __init edcs_data_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 >= EDCS_CPUS_PER_CLUSTER || cluster >= EDCS_CLUSTERS);
> + edcs_use_count[cpu][cluster] = 1;
> + ++core_count[cluster];
> +}
> +
> +/*
> + * Enable cluster-level coherency, in preparation for turning on the MMU.
> + */
> +static void __naked edcs_power_up_setup(unsigned int affinity_level)
> +{
> + asm volatile ("\n"
> + "b cci_enable_port_for_self");
> +}
> +
> +static int __init edcs_init(void)
> +{
> + int ret;
> + struct device_node *node;
> +
> + node = of_find_compatible_node(NULL, NULL, "samsung,exynos5410");
> + if (!node)
> + return -ENODEV;
> +
> + if (!cci_probed())
> + return -ENODEV;
> +
> + /*
> + * Future entries into the kernel can now go
> + * through the cluster entry vectors.
> + */
> + __raw_writel(virt_to_phys(mcpm_entry_point),
> + S5P_VA_SYSRAM_NS + 0x1c);

It would me more readable to have a #define to describe what
S5P_VA_SYSRAM_NS + 0x1c is.


Also, what is the memory type of S5P_VA_SYSRAM_NS? How is the entry
point address value read? Does the inbound CPU's boot ROM or firmware
read it?

If it is read via some non-coherent side-channel, or if S5P_VA_SYSRAM_NS
is mapped as normal memory then we would need some explicit
synchronisation, but I suspect this is not the case (?)

Cheers
---Dave

> +
> + edcs_data_init();
> + mcpm_smp_set_ops();
> +
> + ret = mcpm_platform_register(&exynos_power_ops);
> + if (!ret) {
> + mcpm_sync_init(edcs_power_up_setup);
> + pr_info("EDCS power management initialized\n");
> + }
> + return ret;
> +}
> +
> +early_initcall(edcs_init);
> --
> 1.8.1.5
>
>
> _______________________________________________
> linux-arm-kernel mailing list
> [email protected]
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

2013-10-17 16:04:20

by Daniel Lezcano

[permalink] [raw]
Subject: Re: [PATCH v2 3/4] ARM: EXYNOS: add Exynos Dual Cluster Support

On 10/17/2013 04:32 PM, Dave Martin wrote:
> On Thu, Oct 17, 2013 at 12:45:29PM +0200, Daniel Lezcano wrote:
>> On 10/14/2013 05:08 PM, Vyacheslav Tyrtov wrote:
>>> From: Tarek Dakhran <[email protected]>
>>>
>>> Add EDCS(Exynos Dual Cluster Support) for Samsung Exynos5410 SoC.
>>> This enables all 8 cores, 4 x A7 and 4 x A15 run at the same time.
>
> [...]
>
>>> + __mcpm_cpu_down(cpu, cluster);
>>> +
>>> + if (!skip_wfi) {
>>> + exynos_core_power_down(cpu, cluster);
>>> + wfi();
>>> + }
>>> +}
>>
>> I did not looked line by line but these functions looks very similar
>> than the tc2_pm.c's function. no ?
>
> This is true.
>
>> May be some code consolidation could be considered here.
>>
>> Added Nico and Lorenzo in Cc.
>>
>> Thanks
>> -- Daniel
>
> Nico can commnent further, but I think the main concern here was that
> this code shouldn't be factored prematurely.

I do not share this opinion.

> There are many low-level platform specifics involved here, so it's
> hard to be certain that all platforms could fit into a more abstracted
> framework until we have some evidence to look at.
>
> This could be revisited when we have a few diverse MCPM ports to
> compare.

I am worried about seeing more and more duplicated code around the ARM
arch (eg. arm[64]/kernel/smp.c arm64/kernel/smp.c).

The cpuidle drivers have been duplicated and it took a while before
refactoring them, and it is not finished. The hotplug code have been
duplicated and now it is very difficult to factor it out.

A lot of work have been done to consolidate the code across the
different SoC since the last 2 years.

If we let duplicate code populate the different files, they will belong
to different maintainers, thus different trees. Each SoC contributors
will tend to add their small changes making the code to diverge more and
more and making difficult to re-factor it later.

I am in favor of preventing duplicate code entering in the kernel and
force the contributors to improve the kernel in general, not just the
small part they are supposed to work on. Otherwise, we are letting the
kernel to fork itself, internally...

> The low-level A15/A7 cacheflush sequence is already being factored
> by Nico [1].

Hopefully he did it :)

Thanks
-- Daniel

> [1] http://lists.infradead.org/pipermail/linux-arm-kernel/2013-October/205085.html
> [PATCH] ARM: cacheflush: consolidate single-CPU ARMv7 cache disabling code
>
> [...]
>


--
<http://www.linaro.org/> Linaro.org │ Open source software for ARM SoCs

Follow Linaro: <http://www.facebook.com/pages/Linaro> Facebook |
<http://twitter.com/#!/linaroorg> Twitter |
<http://www.linaro.org/linaro-blog/> Blog

2013-10-17 16:50:44

by Dave Martin

[permalink] [raw]
Subject: Re: [PATCH v2 3/4] ARM: EXYNOS: add Exynos Dual Cluster Support

On Thu, Oct 17, 2013 at 06:04:13PM +0200, Daniel Lezcano wrote:
> On 10/17/2013 04:32 PM, Dave Martin wrote:
> > On Thu, Oct 17, 2013 at 12:45:29PM +0200, Daniel Lezcano wrote:
> >> On 10/14/2013 05:08 PM, Vyacheslav Tyrtov wrote:
> >>> From: Tarek Dakhran <[email protected]>
> >>>
> >>> Add EDCS(Exynos Dual Cluster Support) for Samsung Exynos5410 SoC.
> >>> This enables all 8 cores, 4 x A7 and 4 x A15 run at the same time.
> >
> > [...]
> >
> >>> + __mcpm_cpu_down(cpu, cluster);
> >>> +
> >>> + if (!skip_wfi) {
> >>> + exynos_core_power_down(cpu, cluster);
> >>> + wfi();
> >>> + }
> >>> +}
> >>
> >> I did not looked line by line but these functions looks very similar
> >> than the tc2_pm.c's function. no ?
> >
> > This is true.
> >
> >> May be some code consolidation could be considered here.
> >>
> >> Added Nico and Lorenzo in Cc.
> >>
> >> Thanks
> >> -- Daniel
> >
> > Nico can commnent further, but I think the main concern here was that
> > this code shouldn't be factored prematurely.
>
> I do not share this opinion.
>
> > There are many low-level platform specifics involved here, so it's
> > hard to be certain that all platforms could fit into a more abstracted
> > framework until we have some evidence to look at.
> >
> > This could be revisited when we have a few diverse MCPM ports to
> > compare.
>
> I am worried about seeing more and more duplicated code around the ARM
> arch (eg. arm[64]/kernel/smp.c arm64/kernel/smp.c).
>
> The cpuidle drivers have been duplicated and it took a while before
> refactoring them, and it is not finished. The hotplug code have been
> duplicated and now it is very difficult to factor it out.
>
> A lot of work have been done to consolidate the code across the
> different SoC since the last 2 years.
>
> If we let duplicate code populate the different files, they will
> belong to different maintainers, thus different trees. Each SoC
> contributors will tend to add their small changes making the code to
> diverge more and more and making difficult to re-factor it later.

I think this is Nico's call, since he has more experience than I do
of how these things tend to play out in practice.

Cheers
---Dave

> I am in favor of preventing duplicate code entering in the kernel and
> force the contributors to improve the kernel in general, not just the
> small part they are supposed to work on. Otherwise, we are letting the
> kernel to fork itself, internally...
>
> > The low-level A15/A7 cacheflush sequence is already being factored
> > by Nico [1].
>
> Hopefully he did it :)
>
> Thanks
> -- Daniel
>
> > [1] http://lists.infradead.org/pipermail/linux-arm-kernel/2013-October/205085.html
> > [PATCH] ARM: cacheflush: consolidate single-CPU ARMv7 cache disabling code
> >
> > [...]
> >
>
>
> --
> <http://www.linaro.org/> Linaro.org │ Open source software for ARM SoCs
>
> Follow Linaro: <http://www.facebook.com/pages/Linaro> Facebook |
> <http://twitter.com/#!/linaroorg> Twitter |
> <http://www.linaro.org/linaro-blog/> Blog
>
>
> _______________________________________________
> linux-arm-kernel mailing list
> [email protected]
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

2013-10-17 18:16:51

by Nicolas Pitre

[permalink] [raw]
Subject: Re: [PATCH v2 3/4] ARM: EXYNOS: add Exynos Dual Cluster Support

On Thu, 17 Oct 2013, Daniel Lezcano wrote:

> On 10/17/2013 04:32 PM, Dave Martin wrote:
> > On Thu, Oct 17, 2013 at 12:45:29PM +0200, Daniel Lezcano wrote:
> > > On 10/14/2013 05:08 PM, Vyacheslav Tyrtov wrote:
> > > > From: Tarek Dakhran <[email protected]>
> > > >
> > > > Add EDCS(Exynos Dual Cluster Support) for Samsung Exynos5410 SoC.
> > > > This enables all 8 cores, 4 x A7 and 4 x A15 run at the same time.
> >
> > [...]
> >
> > > > + __mcpm_cpu_down(cpu, cluster);
> > > > +
> > > > + if (!skip_wfi) {
> > > > + exynos_core_power_down(cpu, cluster);
> > > > + wfi();
> > > > + }
> > > > +}
> > >
> > > I did not looked line by line but these functions looks very similar
> > > than the tc2_pm.c's function. no ?
> >
> > This is true.
> >
> > > May be some code consolidation could be considered here.
> > >
> > > Added Nico and Lorenzo in Cc.
> > >
> > > Thanks
> > > -- Daniel
> >
> > Nico can commnent further, but I think the main concern here was that
> > this code shouldn't be factored prematurely.
>
> I do not share this opinion.
>
> > There are many low-level platform specifics involved here, so it's
> > hard to be certain that all platforms could fit into a more abstracted
> > framework until we have some evidence to look at.
> >
> > This could be revisited when we have a few diverse MCPM ports to
> > compare.
>
> I am worried about seeing more and more duplicated code around the ARM arch
> (eg. arm[64]/kernel/smp.c arm64/kernel/smp.c).

I didn't look too closely at those files so can't comment much on them.

> The cpuidle drivers have been duplicated and it took a while before
> refactoring them, and it is not finished. The hotplug code have been
> duplicated and now it is very difficult to factor it out.
>
> A lot of work have been done to consolidate the code across the different SoC
> since the last 2 years.
>
> If we let duplicate code populate the different files, they will belong to
> different maintainers, thus different trees. Each SoC contributors will tend
> to add their small changes making the code to diverge more and more and making
> difficult to re-factor it later.
>
> I am in favor of preventing duplicate code entering in the kernel and force
> the contributors to improve the kernel in general, not just the small part
> they are supposed to work on. Otherwise, we are letting the kernel to fork
> itself, internally...

Now I'm going to comment.

What you say above is perfectly right. As a general principle, we want
good consolidation. That's the theory.

However you need to know what needs to be consolidated in the first
place. In practice you cannot consolidate duplicated code if that code
doesn't exist. In the cpuidle and hotplug cases it is very easy now to
see what kind of consolidation should have been done after the facts.
I'm sure that 10 years ago that wasn't as obvious.

In the MCPM case we didn't know up front what exactly would end up being
duplicated in each machine specific backend. And to some extent we
still don't know as there is very few backends merged into mainline at
this point (I know more of them exist out of tree but I didn't see the
code yet). Right now we have only 2 such backends and some duplication
was already identified, hence the patch to abstract the v7 cache
flushing I posted recently.

Another possibility for consolidation in the MCPM backends is the last
man determination. However we've seen that the PSCI compatibility
backend doesn't need that and abstracting that just yet might be
premature, possibly making interaction with PSCI very awkward.

So it is very important to get the right balance between code
duplication and over-engineering. Premature abstractions do fall into
the over-engineering category and it is just as bad. Above all it is
most important to be vigilant and take care of duplicated code before it
gets too big.

In the past we've seen bad code duplication in some subsystems because
no one was looking at the big picture. In the MCPM case I'm watching.
And in this case we're far from being in a critical situation.


Nicolas

2013-10-17 20:00:44

by Kevin Hilman

[permalink] [raw]
Subject: Re: [PATCH v2 0/4] Exynos 5410 Dual cluster support

Aliaksei Katovich <[email protected]> writes:

> hi Kevin;
>
>> Vyacheslav Tyrtov <[email protected]> writes:
>>
>> > The series of patches represent support of Exynos 5410 SoC
>> >
>> > The Exynos 5410 is the first Samsung SoC based on bigLITTLE architecture.
>> > Patches allow all 8 CPU cores (4 x A7 and 4 x A15) to run at the same time
>> >
>> > Patches add new platform description, support of clock controller,
>> > dual cluster support and device tree for Exynos 5410
>> >
>> > Has been build on v3.12-rc5.
>> > Has been tested on Exynos 5410 reference board (exynos_defconfig).
>>
>> Has anyone tried this on the exynos5410 based odroid-xu yet?
>>
>> I tried booting this on my recently arrived odroid-xu, but am not
>> getting it to boot.
>
> I am able to boot my odroid-xu+e to busybox with these patches applied
> against 3.12-rc5: exynos_defconfig and exynos5410-smdk5410.dtb were
> used.
>
> However there seem to be some issues with virq allocations, like this:

Ah, I've seen the same thing, but for me it doesn't boot reliably.
Sometimes there's an immediate fault like this[1], and once in a rare
while, it starts to boot and I see the same virq errors.

Curious what you guys are using for boot loaders. I found some
pre-build u-boot binaries along with the necessary BL1/2 binary blobs in
the hardkernel kernel repo: https://github.com/hardkernel/linux.git
branch: origin/odroidxu-3.4.y
path: tools/hardkernel/u-boot-pre-built

Unfortunatly, that u-boot doesn't have usb networking support built in
so I couln't use u-boot to tftp the kernel, so I was able to use fasboot
to load the kernel/ramdisk, but it's very flaky.

Do you have an pointers of where to get a known working bootloader.
Ideally, a u-boot with networking/tftp support would be ideal.

Thanks,

Kevin

[1]
USB cable Connected![0x4]
Starting download of 10008576 bytes
.........
downloading of 10008576 bytes finished
Kernel size: 00296bc5
Ramdisk size: 006f3c00
Booting kernel..
## Booting kernel from Legacy Image at 40008000 ...
Image Name: Linux
Image Type: ARM Linux Kernel Image (uncompressed)
Data Size: 2714501 Bytes = 2.6 MiB
Load Address: 40008000
Entry Point: 40008000
Verifying Checksum ... OK
XIP Kernel Image ... OK
OK

Starting kernel ...

undefined instruction
pc : [<4000800c>] lr : [<bfc65df4>]
sp : bfb5bbc8 ip : 00000000 fp : 00001251
r10: 00000000 r9 : 00000000 r8 : bfb5bf30
r7 : 00000000 r6 : 00000000 r5 : 40008000 r4 : bfcabac0
r3 : bfb5bfa8 r2 : 40000100 r1 : 00001251 r0 : 00000000
Flags: nZCv IRQs off FIQs off Mode SVC_32
Resetting CPU ...

emmc resetting ...
resetting ...

2013-10-18 08:29:14

by Tarek Dakhran

[permalink] [raw]
Subject: Re: [PATCH v2 3/4] ARM: EXYNOS: add Exynos Dual Cluster Support

On 17.10.2013 19:46, Dave Martin wrote:
> On Mon, Oct 14, 2013 at 07:08:24PM +0400, Vyacheslav Tyrtov wrote:
>> From: Tarek Dakhran <[email protected]>
>>
>> Add EDCS(Exynos Dual Cluster Support) for Samsung Exynos5410 SoC.
>> This enables all 8 cores, 4 x A7 and 4 x A15 run at the same time.
>>
>> Signed-off-by: Tarek Dakhran <[email protected]>
>> Signed-off-by: Vyacheslav Tyrtov <[email protected]>
>> ---
>> arch/arm/mach-exynos/Makefile | 2 +
>> arch/arm/mach-exynos/edcs.c | 270 ++++++++++++++++++++++++++++++++++++++++++
>> 2 files changed, 272 insertions(+)
>> create mode 100644 arch/arm/mach-exynos/edcs.c
>>
>> diff --git a/arch/arm/mach-exynos/Makefile b/arch/arm/mach-exynos/Makefile
>> index 5369615..ba6efdb 100644
>> --- a/arch/arm/mach-exynos/Makefile
>> +++ b/arch/arm/mach-exynos/Makefile
>> @@ -34,3 +34,5 @@ AFLAGS_exynos-smc.o :=-Wa,-march=armv7-a$(plus_sec)
>>
>> obj-$(CONFIG_MACH_EXYNOS4_DT) += mach-exynos4-dt.o
>> obj-$(CONFIG_MACH_EXYNOS5_DT) += mach-exynos5-dt.o
>> +
>> +obj-$(CONFIG_SOC_EXYNOS5410) += edcs.o
>> diff --git a/arch/arm/mach-exynos/edcs.c b/arch/arm/mach-exynos/edcs.c
>> new file mode 100644
>> index 0000000..e304bd9
>> --- /dev/null
>> +++ b/arch/arm/mach-exynos/edcs.c
>> @@ -0,0 +1,270 @@
>> +/*
>> + * arch/arm/mach-exynos/edcs.c - exynos dual cluster power management support
>> + *
>> + * Copyright (c) 2013 Samsung Electronics Co., Ltd.
>> + * Author: Tarek Dakhran <[email protected]>
>> + *
>> + * 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.
>> + *
>> + * EDCS(exynos dual cluster support) for Exynos5410 SoC.
>> + */
>> +
[snip]
>> +#define EDCS_CORE_STATUS(_nr) (EDCS_CORE_CONFIGURATION(_nr) + 0x4)
>> +#define EDCS_CORE_OPTION(_nr) (EDCS_CORE_CONFIGURATION(_nr) + 0x8)
>> +
>> +#define REG_CPU_STATE_ADDR0 (S5P_VA_SYSRAM_NS + 0x28)
> Is there any reason why S5P_VA_SYSRAM_NS needs to be a static mapping?
What do you mean by "static mapping"?
>
>> +#define REG_CPU_STATE_ADDR(_nr) (REG_CPU_STATE_ADDR0 + \
>> + _nr * EDCS_CPUS_PER_CLUSTER)
>> +
>> +static arch_spinlock_t edcs_lock = __ARCH_SPIN_LOCK_UNLOCKED;
>> +
>> +static int edcs_use_count[EDCS_CPUS_PER_CLUSTER][EDCS_CLUSTERS];
>> +static int core_count[EDCS_CLUSTERS];
>> +
>> +static void exynos_core_power_control(unsigned int cpu, unsigned int cluster,
>> + bool enable)
>> +{
>> + unsigned int offset = cluster * EDCS_CPUS_PER_CLUSTER + cpu;
>> + int value = enable ? S5P_CORE_LOCAL_PWR_EN : 0;
>> +
>> + if ((__raw_readl(EDCS_CORE_STATUS(offset)) & 0x3) != value)
>> + __raw_writel(value, EDCS_CORE_CONFIGURATION(offset));
> I think you need to replace all the __raw_readl() / __raw_writel() calls
> in this file with readl_relaxed() / writel_relaxed().
>
> This ensures little-endian byte order, so that BE8 kernels will work.
>
Will be done.
>> +}
>> +
>> +static void exynos_core_power_up(unsigned int cpu, unsigned int cluster)
>> +{
>> + exynos_core_power_control(cpu, cluster, true);
>> +}
[snip]
>> +
>> + edcs_use_count[cpu][cluster]++;
>> + if (edcs_use_count[cpu][cluster] == 1) {
>> + ++core_count[cluster];
>> + set_boot_flag(cpu, 0x2);
> 0x2 looks like a magic number. Can we have a #define for that?
Will be done.
> If the boot flag is read by the inbound CPU or by a peripheral then
> there are memory ordering issues to take into account. Otherwise, can't
> the inbound CPU come online and race with the write to the boot flag?
Inbound CPU doesn't write the boot flag.
> What is the memory type of REG_STATE_ADDR()?
Same type as S5P_VA_SYSRAM_NS.
This 4K region is mapped as follows:

static struct map_desc exynos5410_iodesc[] __initdata = {
{
.virtual = (unsigned long)S5P_VA_SYSRAM_NS,
.pfn = __phys_to_pfn(EXYNOS5410_PA_SYSRAM_NS),
.length = SZ_4K,
.type = MT_DEVICE,
},
};


>> + exynos_core_power_up(cpu, cluster);
>> + } else if (edcs_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(&edcs_lock);
>> + local_irq_enable();
>> +
>> + return 0;
>> +}
>> +static void exynos_power_down(void)
>> +{
>> + unsigned int mpidr, cpu, cluster;
>> + bool last_man = false, skip_wfi = false;
>> +
>> + 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 >= EDCS_CPUS_PER_CLUSTER || cluster >= EDCS_CLUSTERS);
>> +
>> + __mcpm_cpu_going_down(cpu, cluster);
>> +
>> + arch_spin_lock(&edcs_lock);
>> + BUG_ON(__mcpm_cluster_state(cluster) != CLUSTER_UP);
>> + edcs_use_count[cpu][cluster]--;
>> + if (edcs_use_count[cpu][cluster] == 0) {
>> + --core_count[cluster];
>> + if (core_count[cluster] == 0)
>> + last_man = true;
>> + } else if (edcs_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();
> For TC2, Lorenzo discovered need to disable the GIC CPU interface, so
> that no suprious wakeups can happen once the power controller is
> configured to power the CPU down.
>
> The problem is that a spurious wakeup can trigger a race in the power
> controller when the last man powers down, where the power controller
> continues to wait for the cluster to power down, but it never happens.
>
> http://lists.infradead.org/pipermail/linux-arm-kernel/2013-September/200917.html
> ([PATCH v2] arm: vexpress: tc2: fix hotplug/idle/kexec race on cluster power down)
>
>
> This might not be a problem for Exynos5410 -- it depends on the way the
> power control logic works.
>
> On the other hand, disabling the GIC CPU interface here is cheap to do,
> even if it's not really needed.
>
>> +
>> + if (last_man && __mcpm_outbound_enter_critical(cpu, cluster)) {
>> + arch_spin_unlock(&edcs_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));
>> + }
>> +
>> + /*
>> + * We need to disable and flush the whole (L1 and L2) cache.
>> + * Let's do it in the safest possible way i.e. with
>> + * no memory access within the following sequence
>> + * including the stack.
>> + *
>> + * Note: fp is preserved to the stack explicitly prior doing
>> + * this since adding it to the clobber list is incompatible
>> + * with having CONFIG_FRAME_POINTER=y.
>> + */
>> + asm volatile(
>> + "str fp, [sp, #-4]!\n\t"
>> + "mrc p15, 0, r0, c1, c0, 0 @ get CR\n\t"
>> + "bic r0, r0, #"__stringify(CR_C)"\n\t"
>> + "mcr p15, 0, r0, c1, c0, 0 @ set CR\n\t"
>> + "isb\n\t"
>> + "bl v7_flush_dcache_all\n\t"
>> + "clrex\n\t"
>> + "mrc p15, 0, r0, c1, c0, 1 @ get AUXCR\n\t"
>> + "bic r0, r0, #(1 << 6) @ disable local coherency\n\t"
>> + "mcr p15, 0, r0, c1, c0, 1 @ set AUXCR\n\t"
>> + "isb\n\t"
>> + "dsb\n\t"
>> + "ldr fp, [sp], #4"
>> + : : : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
>> + "r9", "r10", "lr", "memory");
> For these code sequences, please take a look at
>
> http://lists.infradead.org/pipermail/linux-arm-kernel/2013-October/205085.html
> [PATCH] ARM: cacheflush: consolidate single-CPU ARMv7 cache disabling code
>
> The aim is to consolidate on a macro that can be shared between
> backends.
Will be done right after Nicolases patch will be applied to the mainline.
>
>> +
>> + cci_disable_port_by_cpu(mpidr);
>> +
>> + __mcpm_outbound_leave_critical(cluster, CLUSTER_DOWN);
>> +
>> + } else {
>> + arch_spin_unlock(&edcs_lock);
>> + /*
>> + * We need to disable and flush only the L1 cache.
>> + * Let's do it in the safest possible way as above.
>> + */
>> + asm volatile(
>> + "str fp, [sp, #-4]!\n\t"
>> + "mrc p15, 0, r0, c1, c0, 0 @ get CR\n\t"
>> + "bic r0, r0, #"__stringify(CR_C)"\n\t"
>> + "mcr p15, 0, r0, c1, c0, 0 @ set CR\n\t"
>> + "isb\n\t"
>> + "bl v7_flush_dcache_louis\n\t"
>> + "clrex\n\t"
>> + "mrc p15, 0, r0, c1, c0, 1 @ get AUXCR\n\t"
>> + "bic r0, r0, #(1 << 6) @ disable local coherency\n\t"
>> + "mcr p15, 0, r0, c1, c0, 1 @ set AUXCR\n\t"
>> + "isb\n\t"
>> + "dsb\n\t"
>> + "ldr fp, [sp], #4"
>> + : : : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
>> + "r9", "r10", "lr", "memory");
>> +
>> + }
>> + __mcpm_cpu_down(cpu, cluster);
>> +
>> + if (!skip_wfi) {
>> + exynos_core_power_down(cpu, cluster);
>> + wfi();
>> + }
>> +}
>> +
>> +static const struct mcpm_platform_ops exynos_power_ops = {
>> + .power_up = exynos_power_up,
>> + .power_down = exynos_power_down,
>> +};
>> +
>> +static void __init edcs_data_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 >= EDCS_CPUS_PER_CLUSTER || cluster >= EDCS_CLUSTERS);
>> + edcs_use_count[cpu][cluster] = 1;
>> + ++core_count[cluster];
>> +}
>> +
>> +/*
>> + * Enable cluster-level coherency, in preparation for turning on the MMU.
>> + */
>> +static void __naked edcs_power_up_setup(unsigned int affinity_level)
>> +{
>> + asm volatile ("\n"
>> + "b cci_enable_port_for_self");
>> +}
>> +
>> +static int __init edcs_init(void)
>> +{
>> + int ret;
>> + struct device_node *node;
>> +
>> + node = of_find_compatible_node(NULL, NULL, "samsung,exynos5410");
>> + if (!node)
>> + return -ENODEV;
>> +
>> + if (!cci_probed())
>> + return -ENODEV;
>> +
>> + /*
>> + * Future entries into the kernel can now go
>> + * through the cluster entry vectors.
>> + */
>> + __raw_writel(virt_to_phys(mcpm_entry_point),
>> + S5P_VA_SYSRAM_NS + 0x1c);
> It would me more readable to have a #define to describe what
> S5P_VA_SYSRAM_NS + 0x1c is.
Will be done.
> Also, what is the memory type of S5P_VA_SYSRAM_NS? How is the entry
> point address value read? Does the inbound CPU's boot ROM or firmware
> read it?
The former (i.e. boot ROM reads it).
> If it is read via some non-coherent side-channel, or if S5P_VA_SYSRAM_NS
> is mapped as normal memory then we would need some explicit
> synchronisation, but I suspect this is not the case (?)
>
> Cheers
> ---Dave
>
>> +
>> + edcs_data_init();
>> + mcpm_smp_set_ops();
>> +
>> + ret = mcpm_platform_register(&exynos_power_ops);
>> + if (!ret) {
>> + mcpm_sync_init(edcs_power_up_setup);
>> + pr_info("EDCS power management initialized\n");
>> + }
>> + return ret;
>> +}
>> +
>> +early_initcall(edcs_init);
>> --
>> 1.8.1.5
>>
>>
>> _______________________________________________
>> linux-arm-kernel mailing list
>> [email protected]
>> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

Thanks for your comments.

Sincerely yours,
Tarek Dakhran

2013-10-18 12:54:37

by Dave Martin

[permalink] [raw]
Subject: Re: [PATCH v2 3/4] ARM: EXYNOS: add Exynos Dual Cluster Support

On Fri, Oct 18, 2013 at 12:29:03PM +0400, Tarek Dakhran wrote:
> On 17.10.2013 19:46, Dave Martin wrote:
> > On Mon, Oct 14, 2013 at 07:08:24PM +0400, Vyacheslav Tyrtov wrote:
> >> From: Tarek Dakhran <[email protected]>
> >>
> >> Add EDCS(Exynos Dual Cluster Support) for Samsung Exynos5410 SoC.
> >> This enables all 8 cores, 4 x A7 and 4 x A15 run at the same time.
> >>
> >> Signed-off-by: Tarek Dakhran <[email protected]>
> >> Signed-off-by: Vyacheslav Tyrtov <[email protected]>
> >> ---
> >> arch/arm/mach-exynos/Makefile | 2 +
> >> arch/arm/mach-exynos/edcs.c | 270 ++++++++++++++++++++++++++++++++++++++++++
> >> 2 files changed, 272 insertions(+)
> >> create mode 100644 arch/arm/mach-exynos/edcs.c
> >>
> >> diff --git a/arch/arm/mach-exynos/Makefile b/arch/arm/mach-exynos/Makefile
> >> index 5369615..ba6efdb 100644
> >> --- a/arch/arm/mach-exynos/Makefile
> >> +++ b/arch/arm/mach-exynos/Makefile
> >> @@ -34,3 +34,5 @@ AFLAGS_exynos-smc.o :=-Wa,-march=armv7-a$(plus_sec)
> >> obj-$(CONFIG_MACH_EXYNOS4_DT) += mach-exynos4-dt.o
> >> obj-$(CONFIG_MACH_EXYNOS5_DT) += mach-exynos5-dt.o
> >> +
> >> +obj-$(CONFIG_SOC_EXYNOS5410) += edcs.o
> >> diff --git a/arch/arm/mach-exynos/edcs.c b/arch/arm/mach-exynos/edcs.c
> >> new file mode 100644
> >> index 0000000..e304bd9
> >> --- /dev/null
> >> +++ b/arch/arm/mach-exynos/edcs.c
> >> @@ -0,0 +1,270 @@
> >> +/*
> >> + * arch/arm/mach-exynos/edcs.c - exynos dual cluster power management support
> >> + *
> >> + * Copyright (c) 2013 Samsung Electronics Co., Ltd.
> >> + * Author: Tarek Dakhran <[email protected]>
> >> + *
> >> + * 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.
> >> + *
> >> + * EDCS(exynos dual cluster support) for Exynos5410 SoC.
> >> + */
> >> +

> [snip]

> >> +#define EDCS_CORE_STATUS(_nr) (EDCS_CORE_CONFIGURATION(_nr) + 0x4)
> >> +#define EDCS_CORE_OPTION(_nr) (EDCS_CORE_CONFIGURATION(_nr) + 0x8)
> >> +
> >> +#define REG_CPU_STATE_ADDR0 (S5P_VA_SYSRAM_NS + 0x28)
> > Is there any reason why S5P_VA_SYSRAM_NS needs to be a static mapping?

> What do you mean by "static mapping"?

See below

> >
> >> +#define REG_CPU_STATE_ADDR(_nr) (REG_CPU_STATE_ADDR0 + \
> >> + _nr * EDCS_CPUS_PER_CLUSTER)
> >> +
> >> +static arch_spinlock_t edcs_lock = __ARCH_SPIN_LOCK_UNLOCKED;
> >> +
> >> +static int edcs_use_count[EDCS_CPUS_PER_CLUSTER][EDCS_CLUSTERS];
> >> +static int core_count[EDCS_CLUSTERS];
> >> +
> >> +static void exynos_core_power_control(unsigned int cpu, unsigned int cluster,
> >> + bool enable)
> >> +{
> >> + unsigned int offset = cluster * EDCS_CPUS_PER_CLUSTER + cpu;
> >> + int value = enable ? S5P_CORE_LOCAL_PWR_EN : 0;
> >> +
> >> + if ((__raw_readl(EDCS_CORE_STATUS(offset)) & 0x3) != value)
> >> + __raw_writel(value, EDCS_CORE_CONFIGURATION(offset));
> > I think you need to replace all the __raw_readl() / __raw_writel() calls
> > in this file with readl_relaxed() / writel_relaxed().
> >
> > This ensures little-endian byte order, so that BE8 kernels will work.
> >
> Will be done.
> >> +}
> >> +
> >> +static void exynos_core_power_up(unsigned int cpu, unsigned int cluster)
> >> +{
> >> + exynos_core_power_control(cpu, cluster, true);
> >> +}

> [snip]

> >> +
> >> + edcs_use_count[cpu][cluster]++;
> >> + if (edcs_use_count[cpu][cluster] == 1) {
> >> + ++core_count[cluster];
> >> + set_boot_flag(cpu, 0x2);
> > 0x2 looks like a magic number. Can we have a #define for that?

> Will be done.

Thanks

> > If the boot flag is read by the inbound CPU or by a peripheral then
> > there are memory ordering issues to take into account. Otherwise, can't
> > the inbound CPU come online and race with the write to the boot flag?

> Inbound CPU doesn't write the boot flag.

Sorry, I didn't explain this clearly. The scenario I'm thinking about is:

CPU0 writes 2 to the boot flag

The write is temporarily held in a write buffer somewhere in the
memory system.

CPU0 pokes the power controller to bring CPU1 online

CPU1 powers up and starts running its boot ROM

CPU1 reads the boot flag, but misses the value written by CPU0
because that is still held in a write buffer somewhere, and isn't
globally visible.

... and finally ...

The write to the boot flag drains and becomes globally visible.
But it's too late now.

There's also the problem that set_boot_flag() and the read by the
boot ROM probably don't use the same memory type (Device versus
Strongly-Ordered for example). The ARM Architecture doesn't guarantee
full coherency in situations like this.


I believe that a correct solution to this problem is to put a wmb()
between setting the boot flag and poking the power controller.

Putting the wmb() before the writel in exynos_core_power_control()
should do the job.

> > What is the memory type of REG_STATE_ADDR()?
> Same type as S5P_VA_SYSRAM_NS.
> This 4K region is mapped as follows:
>
> static struct map_desc exynos5410_iodesc[] __initdata = {
> {
> .virtual = (unsigned long)S5P_VA_SYSRAM_NS,
> .pfn = __phys_to_pfn(EXYNOS5410_PA_SYSRAM_NS),
> .length = SZ_4K,
> .type = MT_DEVICE,
> },
> };

This is what I mean by a static mapping.

If this mapping isn't needed early (i.e., before ioremap works) then
ioremap can be used instead of reserving a specific virtual address.

This isn't a problem for this patch, just nice to have in general.

[...]

> >> + arch_spin_lock(&edcs_lock);
> >> + BUG_ON(__mcpm_cluster_state(cluster) != CLUSTER_UP);
> >> + edcs_use_count[cpu][cluster]--;
> >> + if (edcs_use_count[cpu][cluster] == 0) {
> >> + --core_count[cluster];
> >> + if (core_count[cluster] == 0)
> >> + last_man = true;
> >> + } else if (edcs_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();
> > For TC2, Lorenzo discovered need to disable the GIC CPU interface, so
> > that no suprious wakeups can happen once the power controller is
> > configured to power the CPU down.
> >
> > The problem is that a spurious wakeup can trigger a race in the power
> > controller when the last man powers down, where the power controller
> > continues to wait for the cluster to power down, but it never happens.
> >
> > http://lists.infradead.org/pipermail/linux-arm-kernel/2013-September/200917.html
> > ([PATCH v2] arm: vexpress: tc2: fix hotplug/idle/kexec race on cluster power down)
> >
> >
> > This might not be a problem for Exynos5410 -- it depends on the way the
> > power control logic works.
> >
> > On the other hand, disabling the GIC CPU interface here is cheap to do,
> > even if it's not really needed.

Did you have any further thoughts on this issue?

> >> +
> >> + if (last_man && __mcpm_outbound_enter_critical(cpu, cluster)) {
> >> + arch_spin_unlock(&edcs_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));
> >> + }
> >> +
> >> + /*
> >> + * We need to disable and flush the whole (L1 and L2) cache.
> >> + * Let's do it in the safest possible way i.e. with
> >> + * no memory access within the following sequence
> >> + * including the stack.
> >> + *
> >> + * Note: fp is preserved to the stack explicitly prior doing
> >> + * this since adding it to the clobber list is incompatible
> >> + * with having CONFIG_FRAME_POINTER=y.
> >> + */
> >> + asm volatile(
> >> + "str fp, [sp, #-4]!\n\t"
> >> + "mrc p15, 0, r0, c1, c0, 0 @ get CR\n\t"
> >> + "bic r0, r0, #"__stringify(CR_C)"\n\t"
> >> + "mcr p15, 0, r0, c1, c0, 0 @ set CR\n\t"
> >> + "isb\n\t"
> >> + "bl v7_flush_dcache_all\n\t"
> >> + "clrex\n\t"
> >> + "mrc p15, 0, r0, c1, c0, 1 @ get AUXCR\n\t"
> >> + "bic r0, r0, #(1 << 6) @ disable local coherency\n\t"
> >> + "mcr p15, 0, r0, c1, c0, 1 @ set AUXCR\n\t"
> >> + "isb\n\t"
> >> + "dsb\n\t"
> >> + "ldr fp, [sp], #4"
> >> + : : : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
> >> + "r9", "r10", "lr", "memory");
> > For these code sequences, please take a look at
> >
> > http://lists.infradead.org/pipermail/linux-arm-kernel/2013-October/205085.html
> > [PATCH] ARM: cacheflush: consolidate single-CPU ARMv7 cache disabling code
> >
> > The aim is to consolidate on a macro that can be shared between
> > backends.
> Will be done right after Nicolases patch will be applied to the mainline.

OK, keep an eye on it.

> >> +static int __init edcs_init(void)
> >> +{

[...]

> >> + /*
> >> + * Future entries into the kernel can now go
> >> + * through the cluster entry vectors.
> >> + */
> >> + __raw_writel(virt_to_phys(mcpm_entry_point),
> >> + S5P_VA_SYSRAM_NS + 0x1c);
> > It would me more readable to have a #define to describe what
> > S5P_VA_SYSRAM_NS + 0x1c is.
> Will be done.

> > Also, what is the memory type of S5P_VA_SYSRAM_NS? How is the entry
> > point address value read? Does the inbound CPU's boot ROM or firmware
> > read it?

> The former (i.e. boot ROM reads it).

OK -- since that write is to device memory, I think we can assume in
practice that it will drain before the first secondary comes online.

If you follow the above advice about adding a wmb() in
exynos_core_power_control(), that should ensure correct ordering for
this too, if I've understood correctly.

Cheers
---Dave

2013-10-22 09:44:22

by Mike Turquette

[permalink] [raw]
Subject: Re: [PATCH v2 2/4] clk: exynos5410: register clocks using common clock framework

Quoting Vyacheslav Tyrtov (2013-10-14 08:08:23)
> From: Tarek Dakhran <[email protected]>
>
> The EXYNOS5410 clocks are statically listed and registered
> using the Samsung specific common clock helper functions.
>
> Signed-off-by: Tarek Dakhran <[email protected]>
> Signed-off-by: Vyacheslav Tyrtov <[email protected]>

Looks good to me. Any objections for me to take this through the clk
tree?

Regards,
Mike

> ---
> .../devicetree/bindings/clock/exynos5410-clock.txt | 37 +++
> drivers/clk/samsung/Makefile | 1 +
> drivers/clk/samsung/clk-exynos5410.c | 251 +++++++++++++++++++++
> include/dt-bindings/clock/exynos5410.h | 175 ++++++++++++++
> 4 files changed, 464 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/clock/exynos5410-clock.txt
> create mode 100644 drivers/clk/samsung/clk-exynos5410.c
> create mode 100644 include/dt-bindings/clock/exynos5410.h
>
> diff --git a/Documentation/devicetree/bindings/clock/exynos5410-clock.txt b/Documentation/devicetree/bindings/clock/exynos5410-clock.txt
> new file mode 100644
> index 0000000..a462da231
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/clock/exynos5410-clock.txt
> @@ -0,0 +1,37 @@
> +* Samsung Exynos5410 Clock Controller
> +
> +The Exynos5410 clock controller generates and supplies clock to various
> +controllers within the Exynos5410 SoC.
> +
> +Required Properties:
> +
> +- compatible: should be "samsung,exynos5410-clock"
> +
> +- reg: physical base address of the controller and length of memory mapped
> + region.
> +
> +- #clock-cells: should be 1.
> +
> +All available clocks are defined as preprocessor macros in
> +dt-bindings/clock/exynos5410.h header and can be used in device
> +tree sources.
> +
> +Example 1: An example of a clock controller node is listed below.
> +
> + clock: clock-controller@0x10010000 {
> + compatible = "samsung,exynos5410-clock";
> + reg = <0x10010000 0x30000>;
> + #clock-cells = <1>;
> + };
> +
> +Example 2: UART controller node that consumes the clock generated by the clock
> + controller. Refer to the standard clock bindings for information
> + about 'clocks' and 'clock-names' property.
> +
> + serial@12C20000 {
> + compatible = "samsung,exynos4210-uart";
> + reg = <0x12C00000 0x100>;
> + interrupts = <0 51 0>;
> + clocks = <&clock CLK_UART0>, <&clock CLK_SCLK_UART0>;
> + clock-names = "uart", "clk_uart_baud0";
> + };
> diff --git a/drivers/clk/samsung/Makefile b/drivers/clk/samsung/Makefile
> index 3413380..5a446ca 100644
> --- a/drivers/clk/samsung/Makefile
> +++ b/drivers/clk/samsung/Makefile
> @@ -5,6 +5,7 @@
> obj-$(CONFIG_COMMON_CLK) += clk.o clk-pll.o
> obj-$(CONFIG_ARCH_EXYNOS4) += clk-exynos4.o
> obj-$(CONFIG_SOC_EXYNOS5250) += clk-exynos5250.o
> +obj-$(CONFIG_SOC_EXYNOS5410) += clk-exynos5410.o
> obj-$(CONFIG_SOC_EXYNOS5420) += clk-exynos5420.o
> obj-$(CONFIG_SOC_EXYNOS5440) += clk-exynos5440.o
> obj-$(CONFIG_ARCH_EXYNOS) += clk-exynos-audss.o
> diff --git a/drivers/clk/samsung/clk-exynos5410.c b/drivers/clk/samsung/clk-exynos5410.c
> new file mode 100644
> index 0000000..c5eba08
> --- /dev/null
> +++ b/drivers/clk/samsung/clk-exynos5410.c
> @@ -0,0 +1,251 @@
> +/*
> + * Copyright (c) 2013 Samsung Electronics Co., Ltd.
> + * Author: Tarek Dakhran <[email protected]>
> + *
> + * 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.
> + *
> + * Common Clock Framework support for Exynos5410 SoC.
> +*/
> +
> +#include <dt-bindings/clock/exynos5410.h>
> +
> +#include <linux/clk.h>
> +#include <linux/clkdev.h>
> +#include <linux/clk-provider.h>
> +#include <linux/of.h>
> +#include <linux/of_address.h>
> +
> +#include "clk.h"
> +
> +#define APLL_LOCK 0x0
> +#define APLL_CON0 0x100
> +#define CPLL_LOCK 0x10020
> +#define CPLL_CON0 0x10120
> +#define MPLL_LOCK 0x4000
> +#define MPLL_CON0 0x4100
> +#define BPLL_LOCK 0x20010
> +#define BPLL_CON0 0x20110
> +#define KPLL_LOCK 0x28000
> +#define KPLL_CON0 0x28100
> +
> +#define SRC_CPU 0x200
> +#define DIV_CPU0 0x500
> +#define SRC_CPERI1 0x4204
> +#define DIV_TOP0 0x10510
> +#define DIV_TOP1 0x10514
> +#define DIV_FSYS1 0x1054c
> +#define DIV_FSYS2 0x10550
> +#define DIV_PERIC0 0x10558
> +#define SRC_TOP0 0x10210
> +#define SRC_TOP1 0x10214
> +#define SRC_TOP2 0x10218
> +#define SRC_FSYS 0x10244
> +#define SRC_PERIC0 0x10250
> +#define SRC_MASK_FSYS 0x10340
> +#define SRC_MASK_PERIC0 0x10350
> +#define GATE_BUS_FSYS0 0x10740
> +#define GATE_IP_FSYS 0x10944
> +#define GATE_IP_PERIC 0x10950
> +#define GATE_IP_PERIS 0x10960
> +#define SRC_CDREX 0x20200
> +#define SRC_KFC 0x28200
> +#define DIV_KFC0 0x28500
> +
> +/* list of PLLs */
> +enum exynos5410_plls {
> + apll, cpll, mpll,
> + bpll, kpll,
> + nr_plls /* number of PLLs */
> +};
> +
> +/*
> + * list of controller registers to be saved and restored during a
> + * suspend/resume cycle.
> + */
> +static unsigned long exynos5410_clk_regs[] __initdata = {
> + SRC_CPU,
> + DIV_CPU0,
> + SRC_CPERI1,
> + DIV_TOP0,
> + DIV_TOP1,
> + DIV_FSYS1,
> + DIV_FSYS2,
> + DIV_PERIC0,
> + SRC_TOP0,
> + SRC_TOP1,
> + SRC_TOP2,
> + SRC_FSYS,
> + SRC_PERIC0,
> + SRC_MASK_FSYS,
> + SRC_MASK_PERIC0,
> + GATE_BUS_FSYS0,
> + GATE_IP_FSYS,
> + GATE_IP_PERIC,
> + GATE_IP_PERIS,
> + SRC_CDREX,
> + SRC_KFC,
> + DIV_KFC0,
> +};
> +
> +/* list of all parent clocks */
> +PNAME(apll_p) = { "fin_pll", "fout_apll", };
> +PNAME(bpll_p) = { "fin_pll", "fout_bpll", };
> +PNAME(cpll_p) = { "fin_pll", "fout_cpll" };
> +PNAME(mpll_p) = { "fin_pll", "fout_mpll", };
> +PNAME(kpll_p) = { "fin_pll", "fout_kpll", };
> +
> +PNAME(mout_cpu_p) = { "mout_apll", "sclk_mpll", };
> +PNAME(mout_kfc_p) = { "mout_kpll", "sclk_mpll", };
> +
> +PNAME(mpll_user_p) = { "fin_pll", "sclk_mpll", };
> +PNAME(bpll_user_p) = { "fin_pll", "sclk_bpll", };
> +PNAME(mpll_bpll_p) = { "sclk_mpll_muxed", "sclk_bpll_muxed", };
> +
> +PNAME(group2_p) = { "fin_pll", "fin_pll", "none", "none",
> + "none", "none", "sclk_mpll_bpll",
> + "none", "none", "sclk_cpll" };
> +
> +/* fixed rate clocks generated outside the soc */
> +static struct samsung_fixed_rate_clock exynos5410_frt_ext_clks[] __initdata = {
> + FRATE(CLK_FIN_PLL, "fin_pll", NULL, CLK_IS_ROOT, 0),
> +};
> +
> +static struct samsung_mux_clock exynos5410_mux_clks[] __initdata = {
> + MUX(0, "mout_apll", apll_p, SRC_CPU, 0, 1),
> + MUX(0, "mout_cpu", mout_cpu_p, SRC_CPU, 16, 1),
> +
> + MUX(0, "mout_kpll", kpll_p, SRC_KFC, 0, 1),
> + MUX(0, "mout_kfc", mout_kfc_p, SRC_KFC, 16, 1),
> +
> + MUX(0, "sclk_mpll", mpll_p, SRC_CPERI1, 8, 1),
> + MUX(0, "sclk_mpll_muxed", mpll_user_p, SRC_TOP2, 20, 1),
> +
> + MUX(0, "sclk_bpll", bpll_p, SRC_CDREX, 0, 1),
> + MUX(0, "sclk_bpll_muxed", bpll_user_p, SRC_TOP2, 24, 1),
> +
> + MUX(0, "sclk_cpll", cpll_p, SRC_TOP2, 8, 1),
> +
> + MUX(0, "sclk_mpll_bpll", mpll_bpll_p, SRC_TOP1, 20, 1),
> +
> + MUX(0, "mout_mmc0", group2_p, SRC_FSYS, 0, 4),
> + MUX(0, "mout_mmc1", group2_p, SRC_FSYS, 4, 4),
> + MUX(0, "mout_mmc2", group2_p, SRC_FSYS, 8, 4),
> +
> + MUX(0, "mout_uart0", group2_p, SRC_PERIC0, 0, 4),
> + MUX(0, "mout_uart1", group2_p, SRC_PERIC0, 4, 4),
> + MUX(0, "mout_uart2", group2_p, SRC_PERIC0, 8, 4),
> +
> + MUX(0, "mout_aclk200", mpll_bpll_p, SRC_TOP0, 12, 1),
> + MUX(0, "mout_aclk400", mpll_bpll_p, SRC_TOP0, 20, 1),
> +};
> +
> +static struct samsung_div_clock exynos5410_div_clks[] __initdata = {
> + DIV(0, "div_arm", "mout_cpu", DIV_CPU0, 0, 3),
> + DIV(0, "div_arm2", "div_arm", DIV_CPU0, 28, 3),
> +
> + DIV(0, "div_acp", "div_arm2", DIV_CPU0, 8, 3),
> + DIV(0, "div_cpud", "div_arm2", DIV_CPU0, 4, 3),
> + DIV(0, "div_atb", "div_arm2", DIV_CPU0, 16, 3),
> + DIV(0, "pclk_dbg", "div_arm2", DIV_CPU0, 20, 3),
> +
> + DIV(0, "div_kfc", "mout_kfc", DIV_KFC0, 0, 3),
> + DIV(0, "div_aclk", "div_kfc", DIV_KFC0, 4, 3),
> + DIV(0, "div_pclk", "div_kfc", DIV_KFC0, 20, 3),
> +
> + DIV(0, "aclk66_pre", "sclk_mpll_muxed", DIV_TOP1, 24, 3),
> + DIV(0, "aclk66", "aclk66_pre", DIV_TOP0, 0, 3),
> +
> + DIV(0, "div_mmc0", "mout_mmc0", DIV_FSYS1, 0, 4),
> + DIV(0, "div_mmc1", "mout_mmc1", DIV_FSYS1, 16, 4),
> + DIV(0, "div_mmc2", "mout_mmc2", DIV_FSYS2, 0, 4),
> +
> + DIV_F(0, "div_mmc_pre0", "div_mmc0",
> + DIV_FSYS1, 8, 8, CLK_SET_RATE_PARENT, 0),
> + DIV_F(0, "div_mmc_pre1", "div_mmc1",
> + DIV_FSYS1, 24, 8, CLK_SET_RATE_PARENT, 0),
> + DIV_F(0, "div_mmc_pre2", "div_mmc2",
> + DIV_FSYS2, 8, 8, CLK_SET_RATE_PARENT, 0),
> +
> + DIV(0, "div_uart0", "mout_uart0", DIV_PERIC0, 0, 4),
> + DIV(0, "div_uart1", "mout_uart1", DIV_PERIC0, 4, 4),
> + DIV(0, "div_uart2", "mout_uart2", DIV_PERIC0, 8, 4),
> + DIV(0, "div_uart3", "mout_uart3", DIV_PERIC0, 12, 4),
> +
> + DIV(0, "aclk200", "mout_aclk200", DIV_TOP0, 12, 3),
> + DIV(0, "aclk400", "mout_aclk400", DIV_TOP0, 24, 3),
> +};
> +
> +static struct samsung_gate_clock exynos5410_gate_clks[] __initdata = {
> + GATE(CLK_MCT, "mct", "aclk66", GATE_IP_PERIS, 18, 0, 0),
> +
> + GATE(CLK_SCLK_MMC0, "sclk_mmc0", "div_mmc_pre0",
> + SRC_MASK_FSYS, 0, CLK_SET_RATE_PARENT, 0),
> + GATE(CLK_SCLK_MMC1, "sclk_mmc1", "div_mmc_pre1",
> + SRC_MASK_FSYS, 4, CLK_SET_RATE_PARENT, 0),
> + GATE(CLK_SCLK_MMC2, "sclk_mmc2", "div_mmc_pre2",
> + SRC_MASK_FSYS, 8, CLK_SET_RATE_PARENT, 0),
> +
> + GATE(CLK_MMC0, "sdmmc0", "aclk200", GATE_BUS_FSYS0, 12, 0, 0),
> + GATE(CLK_MMC1, "sdmmc1", "aclk200", GATE_BUS_FSYS0, 13, 0, 0),
> + GATE(CLK_MMC2, "sdmmc2", "aclk200", GATE_BUS_FSYS0, 14, 0, 0),
> +
> + GATE(CLK_UART0, "uart0", "aclk66", GATE_IP_PERIC, 0, 0, 0),
> + GATE(CLK_UART1, "uart1", "aclk66", GATE_IP_PERIC, 1, 0, 0),
> + GATE(CLK_UART2, "uart2", "aclk66", GATE_IP_PERIC, 2, 0, 0),
> +
> + GATE(CLK_SCLK_UART0, "sclk_uart0", "div_uart0",
> + SRC_MASK_PERIC0, 0, CLK_SET_RATE_PARENT, 0),
> + GATE(CLK_SCLK_UART1, "sclk_uart1", "div_uart1",
> + SRC_MASK_PERIC0, 4, CLK_SET_RATE_PARENT, 0),
> + GATE(CLK_SCLK_UART2, "sclk_uart2", "div_uart2",
> + SRC_MASK_PERIC0, 8, CLK_SET_RATE_PARENT, 0),
> +};
> +
> +static struct samsung_pll_clock exynos5410_plls[nr_plls] __initdata = {
> + [apll] = PLL(pll_35xx, CLK_FOUT_APLL, "fout_apll", "fin_pll", APLL_LOCK,
> + APLL_CON0, NULL),
> + [cpll] = PLL(pll_35xx, CLK_FOUT_CPLL, "fout_cpll", "fin_pll", CPLL_LOCK,
> + CPLL_CON0, NULL),
> + [mpll] = PLL(pll_35xx, CLK_FOUT_MPLL, "fout_mpll", "fin_pll", MPLL_LOCK,
> + MPLL_CON0, NULL),
> + [bpll] = PLL(pll_35xx, CLK_FOUT_BPLL, "fout_bpll", "fin_pll", BPLL_LOCK,
> + BPLL_CON0, NULL),
> + [kpll] = PLL(pll_35xx, CLK_FOUT_KPLL, "fout_kpll", "fin_pll", KPLL_LOCK,
> + KPLL_CON0, NULL),
> +};
> +
> +static struct of_device_id ext_clk_match[] __initdata = {
> + { .compatible = "samsung,clock-oscclk", .data = (void *)0, },
> + { },
> +};
> +
> +/* register exynos5410 clocks */
> +static void __init exynos5410_clk_init(struct device_node *np)
> +{
> + void __iomem *reg_base;
> +
> + reg_base = of_iomap(np, 0);
> + if (!reg_base)
> + panic("%s: failed to map registers\n", __func__);
> +
> + samsung_clk_init(np, reg_base, CLK_NR_CLKS,
> + exynos5410_clk_regs, ARRAY_SIZE(exynos5410_clk_regs),
> + NULL, 0);
> + samsung_clk_of_register_fixed_ext(exynos5410_frt_ext_clks,
> + ARRAY_SIZE(exynos5410_frt_ext_clks),
> + ext_clk_match);
> + samsung_clk_register_pll(exynos5410_plls, ARRAY_SIZE(exynos5410_plls),
> + reg_base);
> +
> + samsung_clk_register_mux(exynos5410_mux_clks,
> + ARRAY_SIZE(exynos5410_mux_clks));
> + samsung_clk_register_div(exynos5410_div_clks,
> + ARRAY_SIZE(exynos5410_div_clks));
> + samsung_clk_register_gate(exynos5410_gate_clks,
> + ARRAY_SIZE(exynos5410_gate_clks));
> +
> + pr_debug("Exynos5410: clock setup completed.\n");
> +}
> +CLK_OF_DECLARE(exynos5410_clk, "samsung,exynos5410-clock", exynos5410_clk_init);
> diff --git a/include/dt-bindings/clock/exynos5410.h b/include/dt-bindings/clock/exynos5410.h
> new file mode 100644
> index 0000000..9b4a58b
> --- /dev/null
> +++ b/include/dt-bindings/clock/exynos5410.h
> @@ -0,0 +1,175 @@
> +#ifndef _DT_BINDINGS_CLOCK_EXYNOS_5410_H
> +#define _DT_BINDINGS_CLOCK_EXYNOS_5410_H
> +
> +/* core clocks */
> +#define CLK_FIN_PLL 1
> +#define CLK_FOUT_APLL 2
> +#define CLK_FOUT_CPLL 3
> +#define CLK_FOUT_DPLL 4
> +#define CLK_FOUT_EPLL 5
> +#define CLK_FOUT_RPLL 6
> +#define CLK_FOUT_IPLL 7
> +#define CLK_FOUT_SPLL 8
> +#define CLK_FOUT_VPLL 9
> +#define CLK_FOUT_MPLL 10
> +#define CLK_FOUT_BPLL 11
> +#define CLK_FOUT_KPLL 12
> +
> +/* gate for special clocks (sclk) */
> +#define CLK_SCLK_UART0 128
> +#define CLK_SCLK_UART1 129
> +#define CLK_SCLK_UART2 130
> +#define CLK_SCLK_UART3 131
> +#define CLK_SCLK_MMC0 132
> +#define CLK_SCLK_MMC1 133
> +#define CLK_SCLK_MMC2 134
> +#define CLK_SCLK_SPI0 135
> +#define CLK_SCLK_SPI1 136
> +#define CLK_SCLK_SPI2 137
> +#define CLK_SCLK_I2S1 138
> +#define CLK_SCLK_I2S2 139
> +#define CLK_SCLK_PCM1 140
> +#define CLK_SCLK_PCM2 141
> +#define CLK_SCLK_SPDIF 142
> +#define CLK_SCLK_HDMI 143
> +#define CLK_SCLK_PIXEL 144
> +#define CLK_SCLK_DP1 145
> +#define CLK_SCLK_MIPI1 146
> +#define CLK_SCLK_FIMD1 147
> +#define CLK_SCLK_MAUDIO0 148
> +#define CLK_SCLK_MAUPCM0 149
> +#define CLK_SCLK_USBD300 150
> +#define CLK_SCLK_USBD301 151
> +#define CLK_SCLK_USBPHY300 152
> +#define CLK_SCLK_USBPHY301 153
> +#define CLK_SCLK_UNIPRO 154
> +#define CLK_SCLK_PWM 155
> +#define CLK_SCLK_GSCL_WA 156
> +#define CLK_SCLK_GSCL_WB 157
> +#define CLK_SCLK_HDMIPHY 158
> +
> +/* gate clocks */
> +#define CLK_ACLK66_PERIC 256
> +#define CLK_UART0 257
> +#define CLK_UART1 258
> +#define CLK_UART2 259
> +#define CLK_UART3 260
> +#define CLK_I2C0 261
> +#define CLK_I2C1 262
> +#define CLK_I2C2 263
> +#define CLK_I2C3 264
> +#define CLK_I2C4 265
> +#define CLK_I2C5 266
> +#define CLK_I2C6 267
> +#define CLK_I2C7 268
> +#define CLK_I2C_HDMI 269
> +#define CLK_TSADC 270
> +#define CLK_SPI0 271
> +#define CLK_SPI1 272
> +#define CLK_SPI2 273
> +#define CLK_KEYIF 274
> +#define CLK_I2S1 275
> +#define CLK_I2S2 276
> +#define CLK_PCM1 277
> +#define CLK_PCM2 278
> +#define CLK_PWM 279
> +#define CLK_SPDIF 280
> +#define CLK_I2C8 281
> +#define CLK_I2C9 282
> +#define CLK_I2C10 283
> +#define CLK_ACLK66_PSGEN 300
> +#define CLK_CHIPID 301
> +#define CLK_SYSREG 302
> +#define CLK_TZPC0 303
> +#define CLK_TZPC1 304
> +#define CLK_TZPC2 305
> +#define CLK_TZPC3 306
> +#define CLK_TZPC4 307
> +#define CLK_TZPC5 308
> +#define CLK_TZPC6 309
> +#define CLK_TZPC7 310
> +#define CLK_TZPC8 311
> +#define CLK_TZPC9 312
> +#define CLK_HDMI_CEC 313
> +#define CLK_SECKEY 314
> +#define CLK_MCT 315
> +#define CLK_WDT 316
> +#define CLK_RTC 317
> +#define CLK_TMU 318
> +#define CLK_TMU_GPU 319
> +#define CLK_PCLK66_GPIO 330
> +#define CLK_ACLK200_FSYS2 350
> +#define CLK_MMC0 351
> +#define CLK_MMC1 352
> +#define CLK_MMC2 353
> +#define CLK_SROMC 354
> +#define CLK_UFS 355
> +#define CLK_ACLK200_FSYS 360
> +#define CLK_TSI 361
> +#define CLK_PDMA0 362
> +#define CLK_PDMA1 363
> +#define CLK_RTIC 364
> +#define CLK_USBH20 365
> +#define CLK_USBD300 366
> +#define CLK_USBD301 367
> +#define CLK_ACLK400_MSCL 380
> +#define CLK_MSCL0 381
> +#define CLK_MSCL1 382
> +#define CLK_MSCL2 383
> +#define CLK_SMMU_MSCL0 384
> +#define CLK_SMMU_MSCL1 385
> +#define CLK_SMMU_MSCL2 386
> +#define CLK_ACLK333 400
> +#define CLK_MFC 401
> +#define CLK_SMMU_MFCL 402
> +#define CLK_SMMU_MFCR 403
> +#define CLK_ACLK200_DISP1 410
> +#define CLK_DSIM1 411
> +#define CLK_DP1 412
> +#define CLK_HDMI 413
> +#define CLK_ACLK300_DISP1 420
> +#define CLK_FIMD1 421
> +#define CLK_SMMU_FIMD1 422
> +#define CLK_ACLK166 430
> +#define CLK_MIXER 431
> +#define CLK_ACLK266 440
> +#define CLK_ROTATOR 441
> +#define CLK_MDMA1 442
> +#define CLK_SMMU_ROTATOR 443
> +#define CLK_SMMU_MDMA1 444
> +#define CLK_ACLK300_JPEG 450
> +#define CLK_JPEG 451
> +#define CLK_JPEG2 452
> +#define CLK_SMMU_JPEG 453
> +#define CLK_ACLK300_GSCL 460
> +#define CLK_SMMU_GSCL0 461
> +#define CLK_SMMU_GSCL1 462
> +#define CLK_GSCL_WA 463
> +#define CLK_GSCL_WB 464
> +#define CLK_GSCL0 465
> +#define CLK_GSCL1 466
> +#define CLK_CLK_3AA 467
> +#define CLK_ACLK266_G2D 470
> +#define CLK_SSS 471
> +#define CLK_SLIM_SSS 472
> +#define CLK_MDMA0 473
> +#define CLK_ACLK333_G2D 480
> +#define CLK_G2D 481
> +#define CLK_ACLK333_432_GSCL 490
> +#define CLK_SMMU_3AA 491
> +#define CLK_SMMU_FIMCL0 492
> +#define CLK_SMMU_FIMCL1 493
> +#define CLK_SMMU_FIMCL3 494
> +#define CLK_FIMC_LITE3 495
> +#define CLK_ACLK_G3D 500
> +#define CLK_G3D 501
> +#define CLK_SMMU_MIXER 502
> +
> +/* mux clocks */
> +#define CLK_MOUT_HDMI 640
> +
> +/* divider clocks */
> +#define CLK_DOUT_PIXEL 768
> +#define CLK_NR_CLKS 769
> +
> +#endif /* _DT_BINDINGS_CLOCK_EXYNOS_5410_H */
> --
> 1.8.1.5

2013-10-25 10:06:43

by Aliaksei Katovich

[permalink] [raw]
Subject: Re: [PATCH v2 3/4] ARM: EXYNOS: add Exynos Dual Cluster Support

hi Vyacheslav;

> From: Tarek Dakhran <[email protected]>
>
> Add EDCS(Exynos Dual Cluster Support) for Samsung Exynos5410 SoC.
> This enables all 8 cores, 4 x A7 and 4 x A15 run at the same time.
>
> Signed-off-by: Tarek Dakhran <[email protected]>
> Signed-off-by: Vyacheslav Tyrtov <[email protected]>
> ---
> arch/arm/mach-exynos/Makefile | 2 +
> arch/arm/mach-exynos/edcs.c | 270 ++++++++++++++++++++++++++++++++++++++++++
> 2 files changed, 272 insertions(+)
> create mode 100644 arch/arm/mach-exynos/edcs.c
>
> diff --git a/arch/arm/mach-exynos/Makefile b/arch/arm/mach-exynos/Makefile
> index 5369615..ba6efdb 100644
> --- a/arch/arm/mach-exynos/Makefile
> +++ b/arch/arm/mach-exynos/Makefile
> @@ -34,3 +34,5 @@ AFLAGS_exynos-smc.o :=-Wa,-march=armv7-a$(plus_sec)
>
> obj-$(CONFIG_MACH_EXYNOS4_DT) += mach-exynos4-dt.o
> obj-$(CONFIG_MACH_EXYNOS5_DT) += mach-exynos5-dt.o
> +
> +obj-$(CONFIG_SOC_EXYNOS5410) += edcs.o
> diff --git a/arch/arm/mach-exynos/edcs.c b/arch/arm/mach-exynos/edcs.c
> new file mode 100644
> index 0000000..e304bd9
> --- /dev/null
> +++ b/arch/arm/mach-exynos/edcs.c
> @@ -0,0 +1,270 @@
> +/*
> + * arch/arm/mach-exynos/edcs.c - exynos dual cluster power management support
> + *
> + * Copyright (c) 2013 Samsung Electronics Co., Ltd.
> + * Author: Tarek Dakhran <[email protected]>
> + *
> + * 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.
> + *
> + * EDCS(exynos dual cluster support) for Exynos5410 SoC.
> + */
> +
> +#include <linux/init.h>
> +#include <linux/io.h>
> +#include <linux/of_address.h>
> +#include <linux/spinlock.h>
> +#include <linux/errno.h>
> +
> +#include <asm/mcpm.h>
> +#include <asm/proc-fns.h>
> +#include <asm/cacheflush.h>
> +#include <asm/cputype.h>
> +#include <asm/cp15.h>
> +
> +#include <linux/arm-cci.h>
> +#include <mach/regs-pmu.h>
> +
> +#define EDCS_CPUS_PER_CLUSTER 4
> +#define EDCS_CLUSTERS 2
> +
> +/* Exynos5410 power management registers */
> +#define EDCS_CORE_CONFIGURATION(_nr) (S5P_ARM_CORE0_CONFIGURATION \
> + + ((_nr) * 0x80))
> +#define EDCS_CORE_STATUS(_nr) (EDCS_CORE_CONFIGURATION(_nr) + 0x4)
> +#define EDCS_CORE_OPTION(_nr) (EDCS_CORE_CONFIGURATION(_nr) + 0x8)
> +
> +#define REG_CPU_STATE_ADDR0 (S5P_VA_SYSRAM_NS + 0x28)
> +#define REG_CPU_STATE_ADDR(_nr) (REG_CPU_STATE_ADDR0 + \
> + _nr * EDCS_CPUS_PER_CLUSTER)
> +
> +static arch_spinlock_t edcs_lock = __ARCH_SPIN_LOCK_UNLOCKED;
> +
> +static int edcs_use_count[EDCS_CPUS_PER_CLUSTER][EDCS_CLUSTERS];
> +static int core_count[EDCS_CLUSTERS];
> +
> +static void exynos_core_power_control(unsigned int cpu, unsigned int cluster,
> + bool enable)
> +{
> + unsigned int offset = cluster * EDCS_CPUS_PER_CLUSTER + cpu;
> + int value = enable ? S5P_CORE_LOCAL_PWR_EN : 0;
> +
> + if ((__raw_readl(EDCS_CORE_STATUS(offset)) & 0x3) != value)
> + __raw_writel(value, EDCS_CORE_CONFIGURATION(offset));
> +}
> +
> +static void exynos_core_power_up(unsigned int cpu, unsigned int cluster)
> +{
> + exynos_core_power_control(cpu, cluster, true);
> +}
> +
> +static void exynos_core_power_down(unsigned int cpu, unsigned int cluster)
> +{
> + exynos_core_power_control(cpu, cluster, false);
> +}
> +
> +void set_boot_flag(unsigned int cpu, unsigned int mode)
> +{
> + __raw_writel(mode, REG_CPU_STATE_ADDR(cpu));
> +}
> +
> +static int exynos_power_up(unsigned int cpu, unsigned int cluster)
> +{
> + pr_debug("%s: cpu %u cluster %u\n", __func__, cpu, cluster);
> + BUG_ON(cpu >= EDCS_CPUS_PER_CLUSTER || cluster >= EDCS_CLUSTERS);
> +
> + local_irq_disable();
> + arch_spin_lock(&edcs_lock);
> +
> + edcs_use_count[cpu][cluster]++;
> + if (edcs_use_count[cpu][cluster] == 1) {
> + ++core_count[cluster];
> + set_boot_flag(cpu, 0x2);
> + exynos_core_power_up(cpu, cluster);
> + } else if (edcs_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(&edcs_lock);
> + local_irq_enable();
> +
> + return 0;
> +}
> +static void exynos_power_down(void)
> +{
> + unsigned int mpidr, cpu, cluster;
> + bool last_man = false, skip_wfi = false;
> +
> + 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 >= EDCS_CPUS_PER_CLUSTER || cluster >= EDCS_CLUSTERS);
> +
> + __mcpm_cpu_going_down(cpu, cluster);
> +
> + arch_spin_lock(&edcs_lock);
> + BUG_ON(__mcpm_cluster_state(cluster) != CLUSTER_UP);
> + edcs_use_count[cpu][cluster]--;
> + if (edcs_use_count[cpu][cluster] == 0) {
> + --core_count[cluster];
> + if (core_count[cluster] == 0)
> + last_man = true;
> + } else if (edcs_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(&edcs_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));
> + }
> +
> + /*
> + * We need to disable and flush the whole (L1 and L2) cache.
> + * Let's do it in the safest possible way i.e. with
> + * no memory access within the following sequence
> + * including the stack.
> + *
> + * Note: fp is preserved to the stack explicitly prior doing
> + * this since adding it to the clobber list is incompatible
> + * with having CONFIG_FRAME_POINTER=y.
> + */
> + asm volatile(
> + "str fp, [sp, #-4]!\n\t"
> + "mrc p15, 0, r0, c1, c0, 0 @ get CR\n\t"
> + "bic r0, r0, #"__stringify(CR_C)"\n\t"
> + "mcr p15, 0, r0, c1, c0, 0 @ set CR\n\t"
> + "isb\n\t"
> + "bl v7_flush_dcache_all\n\t"
> + "clrex\n\t"
> + "mrc p15, 0, r0, c1, c0, 1 @ get AUXCR\n\t"
> + "bic r0, r0, #(1 << 6) @ disable local coherency\n\t"
> + "mcr p15, 0, r0, c1, c0, 1 @ set AUXCR\n\t"
> + "isb\n\t"
> + "dsb\n\t"
> + "ldr fp, [sp], #4"
> + : : : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
> + "r9", "r10", "lr", "memory");
> +
> + cci_disable_port_by_cpu(mpidr);
> +
> + __mcpm_outbound_leave_critical(cluster, CLUSTER_DOWN);
> +
> + } else {
> + arch_spin_unlock(&edcs_lock);
> + /*
> + * We need to disable and flush only the L1 cache.
> + * Let's do it in the safest possible way as above.
> + */
> + asm volatile(
> + "str fp, [sp, #-4]!\n\t"
> + "mrc p15, 0, r0, c1, c0, 0 @ get CR\n\t"
> + "bic r0, r0, #"__stringify(CR_C)"\n\t"
> + "mcr p15, 0, r0, c1, c0, 0 @ set CR\n\t"
> + "isb\n\t"
> + "bl v7_flush_dcache_louis\n\t"
> + "clrex\n\t"
> + "mrc p15, 0, r0, c1, c0, 1 @ get AUXCR\n\t"
> + "bic r0, r0, #(1 << 6) @ disable local coherency\n\t"
> + "mcr p15, 0, r0, c1, c0, 1 @ set AUXCR\n\t"
> + "isb\n\t"
> + "dsb\n\t"
> + "ldr fp, [sp], #4"
> + : : : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
> + "r9", "r10", "lr", "memory");
> +
> + }
> + __mcpm_cpu_down(cpu, cluster);
> +
> + if (!skip_wfi) {
> + exynos_core_power_down(cpu, cluster);
> + wfi();
> + }
> +}
> +
> +static const struct mcpm_platform_ops exynos_power_ops = {
> + .power_up = exynos_power_up,
> + .power_down = exynos_power_down,
> +};
> +
> +static void __init edcs_data_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 >= EDCS_CPUS_PER_CLUSTER || cluster >= EDCS_CLUSTERS);
> + edcs_use_count[cpu][cluster] = 1;
> + ++core_count[cluster];
> +}
> +
> +/*
> + * Enable cluster-level coherency, in preparation for turning on the MMU.
> + */
> +static void __naked edcs_power_up_setup(unsigned int affinity_level)
> +{
> + asm volatile ("\n"
> + "b cci_enable_port_for_self");
> +}

This code breaks odroid-xu boot with NR_CPUS set to 8. Kernel panics
like this:

%< -----------------------------------------------------------------------
[ 5.315000] drivers/rtc/hctosys.c: unable to open rtc device (rtc0)
[ 5.320000] Freeing unused kernel memory: 216K (c049b000 - c04d1000)
[ 5.325000] Unhandled fault: imprecise external abort (0x1406) at 0x00000000
[ 5.340000] Kernel panic - not syncing: Attempted to kill init! exitcode=0x00000007
[ 5.340000]
[ 5.345000] mmc_host mmc0: Bus speed (slot 0) = 100000000Hz (slot req 200000Hz, actual 200000HZ div = 250)
[ 5.355000] CPU: 3 PID: 1 Comm: init Not tainted 3.12.0-rc5-00006-g847e427-dirty #1
[ 5.365000] [<c0014d40>] (unwind_backtrace+0x0/0xf8) from [<c00117cc>] (show_stack+0x10/0x14)
[ 5.370000] [<c00117cc>] (show_stack+0x10/0x14) from [<c03633ac>] (dump_stack+0x6c/0xac)
[ 5.380000] mmc_host mmc0: Bus speed (slot 0) = 100000000Hz (slot req 196079Hz, actual 196078HZ div = 255)
[ 5.390000] [<c03633ac>] (dump_stack+0x6c/0xac) from [<c03609fc>] (panic+0x90/0x1e8)
[ 5.395000] [<c03609fc>] (panic+0x90/0x1e8) from [<c002048c>] (do_exit+0x780/0x834)
[ 5.405000] [<c002048c>] (do_exit+0x780/0x834) from [<c002062c>] (do_group_exit+0x3c/0xb0)
[ 5.410000] [<c002062c>] (do_group_exit+0x3c/0xb0) from [<c002ae80>] (get_signal_to_deliver+0x1d4/0x534)
[ 5.420000] [<c002ae80>] (get_signal_to_deliver+0x1d4/0x534) from [<c0010d08>] (do_signal+0x100/0x40c)
[ 5.430000] [<c0010d08>] (do_signal+0x100/0x40c) from [<c0011348>] (do_work_pending+0x68/0xa8)
[ 5.430000] mmc_host mmc1: Bus speed (slot 0) = 100000000Hz (slot req 50000000Hz, actual 50000000HZ div = 1)
[ 5.430000] mmc1: new high speed SDHC card at address b368
[ 5.435000] mmcblk0: mmc1:b368 USD 14.9 GiB
[ 5.440000] mmcblk0: p1 p2 p3 < p5 p6 p7 >
[ 5.455000] mmc_host mmc0: Bus speed (slot 0) = 100000000Hz (slot req 400000Hz, actual 400000HZ div = 125)
[ 5.475000] [<c0011348>] (do_work_pending+0x68/0xa8) from [<c000e420>] (work_pending+0xc/0x20)
[ 5.480000] CPU1: stopping
[ 5.480000] CPU: 1 PID: 0 Comm: swapper/1 Not tainted 3.12.0-rc5-00006-g847e427-dirty #1
[ 5.480000] [<c0014d40>] (unwind_backtrace+0x0/0xf8) from [<c00117cc>] (show_stack+0x10/0x14)
[ 5.480000] [<c00117cc>] (show_stack+0x10/0x14) from [<c03633ac>] (dump_stack+0x6c/0xac)
[ 5.480000] [<c03633ac>] (dump_stack+0x6c/0xac) from [<c0013604>] (handle_IPI+0xf8/0x11c)
[ 5.480000] [<c0013604>] (handle_IPI+0xf8/0x11c) from [<c000851c>] (gic_handle_irq+0x60/0x68)
[ 5.480000] [<c000851c>] (gic_handle_irq+0x60/0x68) from [<c00122c0>] (__irq_svc+0x40/0x70)
[ 5.480000] Exception stack(0xef0a7f88 to 0xef0a7fd0)
[ 5.480000] 7f80: 00000001 00000000 008d20ff 00000001 00000000 00000000
[ 5.480000] 7fa0: c04d07a0 60000113 010da000 412fc0f3 c15aa7a0 00000000 00000001 ef0a7fd0
[ 5.480000] 7fc0: c0072d74 c0072d78 20000113 ffffffff
[ 5.480000] [<c00122c0>] (__irq_svc+0x40/0x70) from [<c0072d78>] (rcu_idle_exit+0x68/0xb8)
[ 5.480000] [<c0072d78>] (rcu_idle_exit+0x68/0xb8) from [<c00550a4>] (cpu_startup_entry+0x6c/0x148)
[ 5.480000] [<c00550a4>] (cpu_startup_entry+0x6c/0x148) from [<400085c4>] (0x400085c4)
[ 5.480000] CPU0: stopping
[ 5.480000] CPU: 0 PID: 0 Comm: swapper/0 Not tainted 3.12.0-rc5-00006-g847e427-dirty #1
[ 5.480000] [<c0014d40>] (unwind_backtrace+0x0/0xf8) from [<c00117cc>] (show_stack+0x10/0x14)
[ 5.480000] [<c00117cc>] (show_stack+0x10/0x14) from [<c03633ac>] (dump_stack+0x6c/0xac)
[ 5.480000] [<c03633ac>] (dump_stack+0x6c/0xac) from [<c0013604>] (handle_IPI+0xf8/0x11c)
[ 5.480000] [<c0013604>] (handle_IPI+0xf8/0x11c) from [<c000851c>] (gic_handle_irq+0x60/0x68)
[ 5.480000] [<c000851c>] (gic_handle_irq+0x60/0x68) from [<c00122c0>] (__irq_svc+0x40/0x70)
[ 5.480000] Exception stack(0xc04d3f70 to 0xc04d3fb8)
[ 5.480000] SMP: failed to stop secondary CPUs
[ 5.480000] 3f60: 00000000 00000000 00002190 00000000
[ 5.480000] 3f80: c04d2000 c050a88f 00000001 c050a88f c04da44c 412fc0f3 c036a960 00000000
[ 5.480000] 3fa0: 00000020 c04d3fb8 c000f5d4 c000f5d8 60000113 ffffffff
[ 5.480000] [<c00122c0>] (__irq_svc+0x40/0x70) from [<c000f5d8>] (arch_cpu_idle+0x28/0x30)
[ 5.480000] [<c000f5d8>] (arch_cpu_idle+0x28/0x30) from [<c0055094>] (cpu_startup_entry+0x5c/0x148)
[ 5.480000] [<c0055094>] (cpu_startup_entry+0x5c/0x148) from [<c049ba9c>] (start_kernel+0x32c/0x384)
[ 5.480000] CPU2: stopping
[ 5.480000] CPU: 2 PID: 0 Comm: swapper/2 Not tainted 3.12.0-rc5-00006-g847e427-dirty #1
[ 5.480000] [<c0014d40>] (unwind_backtrace+0x0/0xf8) from [<c00117cc>] (show_stack+0x10/0x14)
[ 5.480000] [<c00117cc>] (show_stack+0x10/0x14) from [<c03633ac>] (dump_stack+0x6c/0xac)
[ 5.480000] [<c03633ac>] (dump_stack+0x6c/0xac) from [<c0013604>] (handle_IPI+0xf8/0x11c)
[ 5.480000] [<c0013604>] (handle_IPI+0xf8/0x11c) from [<c000851c>] (gic_handle_irq+0x60/0x68)
[ 5.480000] [<c000851c>] (gic_handle_irq+0x60/0x68) from [<c00122c0>] (__irq_svc+0x40/0x70)
[ 5.480000] Exception stack(0xef0a9fa0 to 0xef0a9fe8)
[ 5.480000] 9fa0: 00000002 00000000 008e4858 00000000 ef0a8000 c050a88f 00000001 c050a88f
[ 5.480000] 9fc0: c04da44c 412fc0f3 c036a960 00000000 00000001 ef0a9fe8 c000f5d4 c000f5d8
[ 5.480000] 9fe0: 60000113 ffffffff
[ 5.480000] [<c00122c0>] (__irq_svc+0x40/0x70) from [<c000f5d8>] (arch_cpu_idle+0x28/0x30)
[ 5.480000] [<c000f5d8>] (arch_cpu_idle+0x28/0x30) from [<c0055094>] (cpu_startup_entry+0x5c/0x148)
[ 5.480000] [<c0055094>] (cpu_startup_entry+0x5c/0x148) from [<400085c4>] (0x400085c4)
%< -----------------------------------------------------------------------

I checked arch/arm/mach-vexpress/tc2_pm.c to see how CCI is enabled
there an realized that you should follow same pattern, i.e.:

asm volatile (" \n"
" cmp r0, #1 \n"
" bxne lr \n"
" b cci_enable_port_for_self ");

In this case only one cluster (4 LITTLE cores for Exynos5410) will be
initialized at boot time. And no panic.

--
Aliaksei

> +
> +static int __init edcs_init(void)
> +{
> + int ret;
> + struct device_node *node;
> +
> + node = of_find_compatible_node(NULL, NULL, "samsung,exynos5410");
> + if (!node)
> + return -ENODEV;
> +
> + if (!cci_probed())
> + return -ENODEV;
> +
> + /*
> + * Future entries into the kernel can now go
> + * through the cluster entry vectors.
> + */
> + __raw_writel(virt_to_phys(mcpm_entry_point),
> + S5P_VA_SYSRAM_NS + 0x1c);
> +
> + edcs_data_init();
> + mcpm_smp_set_ops();
> +
> + ret = mcpm_platform_register(&exynos_power_ops);
> + if (!ret) {
> + mcpm_sync_init(edcs_power_up_setup);
> + pr_info("EDCS power management initialized\n");
> + }
> + return ret;
> +}
> +
> +early_initcall(edcs_init);
> --
> 1.8.1.5
>
>
> _______________________________________________
> linux-arm-kernel mailing list
> [email protected]
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>

2013-10-30 23:57:39

by Kevin Hilman

[permalink] [raw]
Subject: Re: [PATCH v2 0/4] Exynos 5410 Dual cluster support

Hi Mauro,

Mauro Ribeiro <[email protected]> writes:

> Kevin,
>
> https://github.com/hardkernel/u-boot/tree/odroid-v2012.07

Yes, this is the one I'm using, but USB networking doesn't seem to work
with that. Do you have USB networking working with that u-boot? If so,
what changes to the config did you make?

Kevin

>
> On Thu, Oct 17, 2013 at 5:00 PM, Kevin Hilman <[email protected]> wrote:
>
>> Aliaksei Katovich <[email protected]> writes:
>>
>> > hi Kevin;
>> >
>> >> Vyacheslav Tyrtov <[email protected]> writes:
>> >>
>> >> > The series of patches represent support of Exynos 5410 SoC
>> >> >
>> >> > The Exynos 5410 is the first Samsung SoC based on bigLITTLE
>> architecture.
>> >> > Patches allow all 8 CPU cores (4 x A7 and 4 x A15) to run at the same
>> time
>> >> >
>> >> > Patches add new platform description, support of clock controller,
>> >> > dual cluster support and device tree for Exynos 5410
>> >> >
>> >> > Has been build on v3.12-rc5.
>> >> > Has been tested on Exynos 5410 reference board (exynos_defconfig).
>> >>
>> >> Has anyone tried this on the exynos5410 based odroid-xu yet?
>> >>
>> >> I tried booting this on my recently arrived odroid-xu, but am not
>> >> getting it to boot.
>> >
>> > I am able to boot my odroid-xu+e to busybox with these patches
>> applied
>> > against 3.12-rc5: exynos_defconfig and exynos5410-smdk5410.dtb were
>> > used.
>> >
>> > However there seem to be some issues with virq allocations, like
>> this:
>>
>> Ah, I've seen the same thing, but for me it doesn't boot reliably.
>> Sometimes there's an immediate fault like this[1], and once in a rare
>> while, it starts to boot and I see the same virq errors.
>>
>> Curious what you guys are using for boot loaders. I found some
>> pre-build u-boot binaries along with the necessary BL1/2 binary blobs in
>> the hardkernel kernel repo: https://github.com/hardkernel/linux.git
>> branch: origin/odroidxu-3.4.y
>> path: tools/hardkernel/u-boot-pre-built
>>
>> Unfortunatly, that u-boot doesn't have usb networking support built in
>> so I couln't use u-boot to tftp the kernel, so I was able to use fasboot
>> to load the kernel/ramdisk, but it's very flaky.
>>
>> Do you have an pointers of where to get a known working bootloader.
>> Ideally, a u-boot with networking/tftp support would be ideal.
>>
>> Thanks,
>>
>> Kevin
>>
>> [1]
>> USB cable Connected![0x4]
>> Starting download of 10008576 bytes
>> .........
>> downloading of 10008576 bytes finished
>> Kernel size: 00296bc5
>> Ramdisk size: 006f3c00
>> Booting kernel..
>> ## Booting kernel from Legacy Image at 40008000 ...
>> Image Name: Linux
>> Image Type: ARM Linux Kernel Image (uncompressed)
>> Data Size: 2714501 Bytes = 2.6 MiB
>> Load Address: 40008000
>> Entry Point: 40008000
>> Verifying Checksum ... OK
>> XIP Kernel Image ... OK
>> OK
>>
>> Starting kernel ...
>>
>> undefined instruction
>> pc : [<4000800c>] lr : [<bfc65df4>]
>> sp : bfb5bbc8 ip : 00000000 fp : 00001251
>> r10: 00000000 r9 : 00000000 r8 : bfb5bf30
>> r7 : 00000000 r6 : 00000000 r5 : 40008000 r4 : bfcabac0
>> r3 : bfb5bfa8 r2 : 40000100 r1 : 00001251 r0 : 00000000
>> Flags: nZCv IRQs off FIQs off Mode SVC_32
>> Resetting CPU ...
>>
>> emmc resetting ...
>> resetting ...
>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe
>> linux-samsung-soc" in
>> the body of a message to [email protected]
>> More majordomo info at http://vger.kernel.org/majordomo-info.html
>>