]> git.proxmox.com Git - mirror_ubuntu-zesty-kernel.git/commitdiff
Merge tag 'soc2' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
authorLinus Torvalds <torvalds@linux-foundation.org>
Fri, 14 Dec 2012 22:38:28 +0000 (14:38 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 14 Dec 2012 22:38:28 +0000 (14:38 -0800)
Pull ARM Soc updates, take 2, from Olof Johansson:
 "This is the second batch of SoC updates for the 3.8 merge window,
  containing parts that had dependencies on earlier branches such that
  we couldn't include them with the first branch.

  These are general updates for Samsung Exynos, Renesas/shmobile and a
  topic branch that adds SMP support to Altera's socfpga platform."

Fix up conflicts mostly as per Olof.

* tag 'soc2' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc:
  ARM: EXYNOS: Clock settings for SATA and SATA PHY
  ARM: EXYNOS: Add ARM down clock support
  ARM: EXYNOS: Fix i2c suspend/resume for legacy controller
  ARM: EXYNOS: Add aliases for i2c controller
  ARM: EXYNOS: Setup legacy i2c controller interrupts
  sh: clkfwk: fixup unsed variable warning
  Revert "ARM: shmobile: r8a7779: Replace modify_scu_cpu_psr with scu_power_mode"
  Revert "ARM: shmobile: sh73a0: Replace modify_scu_cpu_psr with scu_power_mode"
  Revert "ARM: shmobile: emev2: Replace modify_scu_cpu_psr with scu_power_mode"
  ARM: highbank: use common debug_ll_io_init
  ARM: shmobile: sh7372: sh7372_fsiXck_clk become non-global
  ARM: shmobile: sh7372: remove fsidivx clock
  ARM: socfpga: mark secondary_trampoline as cpuinit
  socfpga: map uart into virtual address space so that early_printk() works
  ARM: socfpga: fix build break for allyesconfig
  ARM: socfpga: Enable SMP for socfpga
  ARM: EXYNOS: Add dp clock support for EXYNOS5
  ARM: SAMSUNG: call clk_get_rate for debugfs rate files
  ARM: SAMSUNG: add clock_tree debugfs file in clock

24 files changed:
Documentation/devicetree/bindings/arm/altera/socfpga-reset.txt [new file with mode: 0644]
Documentation/devicetree/bindings/arm/altera/socfpga-system.txt [new file with mode: 0644]
arch/arm/boot/dts/exynos5250.dtsi
arch/arm/boot/dts/socfpga.dtsi
arch/arm/configs/socfpga_defconfig
arch/arm/mach-exynos/clock-exynos5.c
arch/arm/mach-exynos/cpuidle.c
arch/arm/mach-exynos/include/mach/regs-clock.h
arch/arm/mach-exynos/include/mach/regs-pmu.h
arch/arm/mach-exynos/mach-exynos5-dt.c
arch/arm/mach-exynos/pm.c
arch/arm/mach-shmobile/clock-sh7372.c
arch/arm/mach-shmobile/include/mach/sh7372.h
arch/arm/mach-shmobile/smp-emev2.c
arch/arm/mach-shmobile/smp-r8a7779.c
arch/arm/mach-shmobile/smp-sh73a0.c
arch/arm/mach-socfpga/Kconfig
arch/arm/mach-socfpga/Makefile
arch/arm/mach-socfpga/core.h [new file with mode: 0644]
arch/arm/mach-socfpga/headsmp.S [new file with mode: 0644]
arch/arm/mach-socfpga/platsmp.c [new file with mode: 0644]
arch/arm/mach-socfpga/socfpga.c
arch/arm/plat-samsung/clock.c
drivers/sh/clk/cpg.c

diff --git a/Documentation/devicetree/bindings/arm/altera/socfpga-reset.txt b/Documentation/devicetree/bindings/arm/altera/socfpga-reset.txt
new file mode 100644 (file)
index 0000000..ecdb57d
--- /dev/null
@@ -0,0 +1,11 @@
+Altera SOCFPGA Reset Manager
+
+Required properties:
+- compatible : "altr,rst-mgr"
+- reg : Should contain 1 register ranges(address and length)
+
+Example:
+        rstmgr@ffd05000 {
+               compatible = "altr,rst-mgr";
+               reg = <0xffd05000 0x1000>;
+       };
diff --git a/Documentation/devicetree/bindings/arm/altera/socfpga-system.txt b/Documentation/devicetree/bindings/arm/altera/socfpga-system.txt
new file mode 100644 (file)
index 0000000..07c65e3
--- /dev/null
@@ -0,0 +1,11 @@
+Altera SOCFPGA System Manager
+
+Required properties:
+- compatible : "altr,sys-mgr"
+- reg : Should contain 1 register ranges(address and length)
+
+Example:
+        sysmgr@ffd08000 {
+               compatible = "altr,sys-mgr";
+               reg = <0xffd08000 0x1000>;
+       };
index 36d8246ea50eaef5e5cae9c719b8ade854a17bd1..2e3b6efaf1a2632062fd93a8ca7d0eec792a9c0c 100644 (file)
                mshc1 = &dwmmc_1;
                mshc2 = &dwmmc_2;
                mshc3 = &dwmmc_3;
+               i2c0 = &i2c_0;
+               i2c1 = &i2c_1;
+               i2c2 = &i2c_2;
+               i2c3 = &i2c_3;
+               i2c4 = &i2c_4;
+               i2c5 = &i2c_5;
+               i2c6 = &i2c_6;
+               i2c7 = &i2c_7;
+               i2c8 = &i2c_8;
        };
 
        gic:interrupt-controller@10481000 {
                reg = <0x12170000 0x1ff>;
        };
 
-       i2c@12C60000 {
+       i2c_0: i2c@12C60000 {
                compatible = "samsung,s3c2440-i2c";
                reg = <0x12C60000 0x100>;
                interrupts = <0 56 0>;
                #size-cells = <0>;
        };
 
-       i2c@12C70000 {
+       i2c_1: i2c@12C70000 {
                compatible = "samsung,s3c2440-i2c";
                reg = <0x12C70000 0x100>;
                interrupts = <0 57 0>;
                #size-cells = <0>;
        };
 
-       i2c@12C80000 {
+       i2c_2: i2c@12C80000 {
                compatible = "samsung,s3c2440-i2c";
                reg = <0x12C80000 0x100>;
                interrupts = <0 58 0>;
                #size-cells = <0>;
        };
 
-       i2c@12C90000 {
+       i2c_3: i2c@12C90000 {
                compatible = "samsung,s3c2440-i2c";
                reg = <0x12C90000 0x100>;
                interrupts = <0 59 0>;
                #size-cells = <0>;
        };
 
-       i2c@12CA0000 {
+       i2c_4: i2c@12CA0000 {
                compatible = "samsung,s3c2440-i2c";
                reg = <0x12CA0000 0x100>;
                interrupts = <0 60 0>;
                #size-cells = <0>;
        };
 
-       i2c@12CB0000 {
+       i2c_5: i2c@12CB0000 {
                compatible = "samsung,s3c2440-i2c";
                reg = <0x12CB0000 0x100>;
                interrupts = <0 61 0>;
                #size-cells = <0>;
        };
 
-       i2c@12CC0000 {
+       i2c_6: i2c@12CC0000 {
                compatible = "samsung,s3c2440-i2c";
                reg = <0x12CC0000 0x100>;
                interrupts = <0 62 0>;
                #size-cells = <0>;
        };
 
-       i2c@12CD0000 {
+       i2c_7: i2c@12CD0000 {
                compatible = "samsung,s3c2440-i2c";
                reg = <0x12CD0000 0x100>;
                interrupts = <0 63 0>;
                #size-cells = <0>;
        };
 
-       i2c@12CE0000 {
+       i2c_8: i2c@12CE0000 {
                compatible = "samsung,s3c2440-hdmiphy-i2c";
                reg = <0x12CE0000 0x1000>;
                interrupts = <0 64 0>;
index 0772f5739f59573aa1403b6cc0e6efd8a873892a..19aec421bb26bab363a059e2395ebfe8fc0489a9 100644 (file)
                        reg-shift = <2>;
                        reg-io-width = <4>;
                };
+
+               rstmgr@ffd05000 {
+                               compatible = "altr,rst-mgr";
+                               reg = <0xffd05000 0x1000>;
+                       };
+
+               sysmgr@ffd08000 {
+                               compatible = "altr,sys-mgr";
+                               reg = <0xffd08000 0x4000>;
+                       };
        };
 };
index 0ac1293dba102dce226b510d2aca075558e16cfe..4e1ce211d43f101153f676cc2114a791b4a6ea52 100644 (file)
@@ -18,9 +18,10 @@ CONFIG_MODULE_UNLOAD=y
 CONFIG_ARCH_SOCFPGA=y
 CONFIG_MACH_SOCFPGA_CYCLONE5=y
 CONFIG_ARM_THUMBEE=y
+# CONFIG_ARCH_VEXPRESS_CORTEX_A5_A9_ERRATA is not set
 # CONFIG_CACHE_L2X0 is not set
 CONFIG_HIGH_RES_TIMERS=y
-CONFIG_VMSPLIT_2G=y
+CONFIG_SMP=y
 CONFIG_NR_CPUS=2
 CONFIG_AEABI=y
 CONFIG_ZBOOT_ROM_TEXT=0x0
index 7652f5d78a56664dba722ec0dea19e51d0dd3937..e9d7b80bae492cf241818d989e3f926d9577761e 100644 (file)
@@ -80,6 +80,8 @@ static struct sleep_save exynos5_clock_save[] = {
        SAVE_ITEM(EXYNOS5_VPLL_CON0),
        SAVE_ITEM(EXYNOS5_VPLL_CON1),
        SAVE_ITEM(EXYNOS5_VPLL_CON2),
+       SAVE_ITEM(EXYNOS5_PWR_CTRL1),
+       SAVE_ITEM(EXYNOS5_PWR_CTRL2),
 };
 #endif
 
@@ -661,15 +663,20 @@ static struct clk exynos5_init_clocks_off[] = {
                .ctrlbit        = (1 << 15),
        }, {
                .name           = "sata",
-               .devname        = "ahci",
+               .devname        = "exynos5-sata",
+               .parent         = &exynos5_clk_aclk_200.clk,
                .enable         = exynos5_clk_ip_fsys_ctrl,
                .ctrlbit        = (1 << 6),
        }, {
-               .name           = "sata_phy",
+               .name           = "sata-phy",
+               .devname        = "exynos5-sata-phy",
+               .parent         = &exynos5_clk_aclk_200.clk,
                .enable         = exynos5_clk_ip_fsys_ctrl,
                .ctrlbit        = (1 << 24),
        }, {
-               .name           = "sata_phy_i2c",
+               .name           = "i2c",
+               .devname        = "exynos5-sata-phy-i2c",
+               .parent         = &exynos5_clk_aclk_200.clk,
                .enable         = exynos5_clk_ip_fsys_ctrl,
                .ctrlbit        = (1 << 25),
        }, {
@@ -692,6 +699,11 @@ static struct clk exynos5_init_clocks_off[] = {
                .devname        = "exynos5-mixer",
                .enable         = exynos5_clk_ip_disp1_ctrl,
                .ctrlbit        = (1 << 5),
+       }, {
+               .name           = "dp",
+               .devname        = "exynos-dp",
+               .enable         = exynos5_clk_ip_disp1_ctrl,
+               .ctrlbit        = (1 << 4),
        }, {
                .name           = "jpeg",
                .enable         = exynos5_clk_ip_gen_ctrl,
@@ -1239,6 +1251,16 @@ static struct clksrc_clk exynos5_clksrcs[] = {
                .sources = &exynos5_clkset_aclk,
                .reg_src = { .reg = EXYNOS5_CLKSRC_TOP0, .shift = 20, .size = 1 },
                .reg_div = { .reg = EXYNOS5_CLKDIV_TOP0, .shift = 24, .size = 3 },
+       }, {
+               .clk    = {
+                       .name           = "sclk_sata",
+                       .devname        = "exynos5-sata",
+                       .enable         = exynos5_clksrc_mask_fsys_ctrl,
+                       .ctrlbit        = (1 << 24),
+               },
+               .sources = &exynos5_clkset_aclk,
+               .reg_src = { .reg = EXYNOS5_CLKSRC_FSYS, .shift = 24, .size = 1 },
+               .reg_div = { .reg = EXYNOS5_CLKDIV_FSYS0, .shift = 20, .size = 4 },
        }, {
                .clk    = {
                        .name           = "sclk_gscl_wrap",
index 8e4ec21ef2cf6ba3790b222e3e1ced6684ee2387..05092415277688605e4c2dc5ede85ba60c94e678 100644 (file)
@@ -21,6 +21,7 @@
 #include <asm/suspend.h>
 #include <asm/unified.h>
 #include <asm/cpuidle.h>
+#include <mach/regs-clock.h>
 #include <mach/regs-pmu.h>
 #include <mach/pmu.h>
 
@@ -157,12 +158,47 @@ static int exynos4_enter_lowpower(struct cpuidle_device *dev,
                return exynos4_enter_core0_aftr(dev, drv, new_index);
 }
 
+static void __init exynos5_core_down_clk(void)
+{
+       unsigned int tmp;
+
+       /*
+        * Enable arm clock down (in idle) and set arm divider
+        * ratios in WFI/WFE state.
+        */
+       tmp = PWR_CTRL1_CORE2_DOWN_RATIO | \
+             PWR_CTRL1_CORE1_DOWN_RATIO | \
+             PWR_CTRL1_DIV2_DOWN_EN     | \
+             PWR_CTRL1_DIV1_DOWN_EN     | \
+             PWR_CTRL1_USE_CORE1_WFE    | \
+             PWR_CTRL1_USE_CORE0_WFE    | \
+             PWR_CTRL1_USE_CORE1_WFI    | \
+             PWR_CTRL1_USE_CORE0_WFI;
+       __raw_writel(tmp, EXYNOS5_PWR_CTRL1);
+
+       /*
+        * Enable arm clock up (on exiting idle). Set arm divider
+        * ratios when not in idle along with the standby duration
+        * ratios.
+        */
+       tmp = PWR_CTRL2_DIV2_UP_EN       | \
+             PWR_CTRL2_DIV1_UP_EN       | \
+             PWR_CTRL2_DUR_STANDBY2_VAL | \
+             PWR_CTRL2_DUR_STANDBY1_VAL | \
+             PWR_CTRL2_CORE2_UP_RATIO   | \
+             PWR_CTRL2_CORE1_UP_RATIO;
+       __raw_writel(tmp, EXYNOS5_PWR_CTRL2);
+}
+
 static int __init exynos4_init_cpuidle(void)
 {
        int i, max_cpuidle_state, cpu_id;
        struct cpuidle_device *device;
        struct cpuidle_driver *drv = &exynos4_idle_driver;
 
+       if (soc_is_exynos5250())
+               exynos5_core_down_clk();
+
        /* Setup cpuidle driver */
        drv->state_count = (sizeof(exynos4_cpuidle_set) /
                                       sizeof(struct cpuidle_state));
index 8c9b38c9c5042d931ede0f3ab6f569cc3406dd86..d36ad76ad6a46cbab1f07e1c3d9e2a4cde230cd7 100644 (file)
 #define EXYNOS5_CLKDIV_STATCPU0                        EXYNOS_CLKREG(0x00600)
 #define EXYNOS5_CLKDIV_STATCPU1                        EXYNOS_CLKREG(0x00604)
 
+#define EXYNOS5_PWR_CTRL1                      EXYNOS_CLKREG(0x01020)
+#define EXYNOS5_PWR_CTRL2                      EXYNOS_CLKREG(0x01024)
+
 #define EXYNOS5_MPLL_CON0                      EXYNOS_CLKREG(0x04100)
 #define EXYNOS5_CLKSRC_CORE1                   EXYNOS_CLKREG(0x04204)
 
 
 #define EXYNOS5_EPLLCON0_LOCKED_SHIFT          (29)
 
+#define PWR_CTRL1_CORE2_DOWN_RATIO             (7 << 28)
+#define PWR_CTRL1_CORE1_DOWN_RATIO             (7 << 16)
+#define PWR_CTRL1_DIV2_DOWN_EN                 (1 << 9)
+#define PWR_CTRL1_DIV1_DOWN_EN                 (1 << 8)
+#define PWR_CTRL1_USE_CORE1_WFE                        (1 << 5)
+#define PWR_CTRL1_USE_CORE0_WFE                        (1 << 4)
+#define PWR_CTRL1_USE_CORE1_WFI                        (1 << 1)
+#define PWR_CTRL1_USE_CORE0_WFI                        (1 << 0)
+
+#define PWR_CTRL2_DIV2_UP_EN                   (1 << 25)
+#define PWR_CTRL2_DIV1_UP_EN                   (1 << 24)
+#define PWR_CTRL2_DUR_STANDBY2_VAL             (1 << 16)
+#define PWR_CTRL2_DUR_STANDBY1_VAL             (1 << 8)
+#define PWR_CTRL2_CORE2_UP_RATIO               (1 << 4)
+#define PWR_CTRL2_CORE1_UP_RATIO               (1 << 0)
+
 /* Compatibility defines and inclusion */
 
 #include <mach/regs-pmu.h>
index 84428e72cf5e771fd6e42fd066879bfb36395272..3f30aa1ae3547897410d64471cdd20eca2372b95 100644 (file)
@@ -15,6 +15,7 @@
 #include <mach/map.h>
 
 #define S5P_PMUREG(x)                          (S5P_VA_PMU + (x))
+#define S5P_SYSREG(x)                          (S3C_VA_SYS + (x))
 
 #define S5P_CENTRAL_SEQ_CONFIGURATION          S5P_PMUREG(0x0200)
 
 
 /* For EXYNOS5 */
 
+#define EXYNOS5_SYS_I2C_CFG                                    S5P_SYSREG(0x0234)
+
 #define EXYNOS5_AUTO_WDTRESET_DISABLE                          S5P_PMUREG(0x0408)
 #define EXYNOS5_MASK_WDTRESET_REQUEST                          S5P_PMUREG(0x040C)
 
index 929de766d4906cdb8856da45baf47301528fb3ae..f038c8cadca484e1831cd3277394bd8565ab88c1 100644 (file)
 #include <linux/of_fdt.h>
 #include <linux/serial_core.h>
 #include <linux/memblock.h>
-#include <linux/of_fdt.h>
+#include <linux/io.h>
 
 #include <asm/mach/arch.h>
 #include <asm/hardware/gic.h>
 #include <mach/map.h>
+#include <mach/regs-pmu.h>
 
 #include <plat/cpu.h>
 #include <plat/regs-serial.h>
@@ -124,6 +125,28 @@ static void __init exynos5_dt_map_io(void)
 
 static void __init exynos5_dt_machine_init(void)
 {
+       struct device_node *i2c_np;
+       const char *i2c_compat = "samsung,s3c2440-i2c";
+       unsigned int tmp;
+
+       /*
+        * Exynos5's legacy i2c controller and new high speed i2c
+        * controller have muxed interrupt sources. By default the
+        * interrupts for 4-channel HS-I2C controller are enabled.
+        * If node for first four channels of legacy i2c controller
+        * are available then re-configure the interrupts via the
+        * system register.
+        */
+       for_each_compatible_node(i2c_np, NULL, i2c_compat) {
+               if (of_device_is_available(i2c_np)) {
+                       if (of_alias_get_id(i2c_np, "i2c") < 4) {
+                               tmp = readl(EXYNOS5_SYS_I2C_CFG);
+                               writel(tmp & ~(0x1 << of_alias_get_id(i2c_np, "i2c")),
+                                               EXYNOS5_SYS_I2C_CFG);
+                       }
+               }
+       }
+
        if (of_machine_is_compatible("samsung,exynos5250"))
                of_platform_populate(NULL, of_default_bus_match_table,
                                     exynos5250_auxdata_lookup, NULL);
index 8df6ec547f78fcaa4234c8a08c0fe4a32187414f..b9b539cac81e12869523ceb6c8e5e0817f6092a0 100644 (file)
@@ -62,6 +62,10 @@ static struct sleep_save exynos4_vpll_save[] = {
        SAVE_ITEM(EXYNOS4_VPLL_CON1),
 };
 
+static struct sleep_save exynos5_sys_save[] = {
+       SAVE_ITEM(EXYNOS5_SYS_I2C_CFG),
+};
+
 static struct sleep_save exynos_core_save[] = {
        /* SROM side */
        SAVE_ITEM(S5P_SROM_BW),
@@ -101,6 +105,7 @@ static void exynos_pm_prepare(void)
                s3c_pm_do_save(exynos4_epll_save, ARRAY_SIZE(exynos4_epll_save));
                s3c_pm_do_save(exynos4_vpll_save, ARRAY_SIZE(exynos4_vpll_save));
        } else {
+               s3c_pm_do_save(exynos5_sys_save, ARRAY_SIZE(exynos5_sys_save));
                /* Disable USE_RETENTION of JPEG_MEM_OPTION */
                tmp = __raw_readl(EXYNOS5_JPEG_MEM_OPTION);
                tmp &= ~EXYNOS5_OPTION_USE_RETENTION;
@@ -304,6 +309,10 @@ static void exynos_pm_resume(void)
        __raw_writel((1 << 28), S5P_PAD_RET_EBIA_OPTION);
        __raw_writel((1 << 28), S5P_PAD_RET_EBIB_OPTION);
 
+       if (soc_is_exynos5250())
+               s3c_pm_do_restore(exynos5_sys_save,
+                       ARRAY_SIZE(exynos5_sys_save));
+
        s3c_pm_do_restore_core(exynos_core_save, ARRAY_SIZE(exynos_core_save));
 
        if (!soc_is_exynos5250()) {
index 4d57e342537b6b24bde3dd17d189887636dcbaa4..3ca6757b129ad7da9be7b8654e61402b8647f012 100644 (file)
@@ -295,10 +295,10 @@ struct clk sh7372_pllc2_clk = {
 };
 
 /* External input clock (pin name: FSIACK/FSIBCK ) */
-struct clk sh7372_fsiack_clk = {
+static struct clk fsiack_clk = {
 };
 
-struct clk sh7372_fsibck_clk = {
+static struct clk fsibck_clk = {
 };
 
 static struct clk *main_clks[] = {
@@ -314,8 +314,8 @@ static struct clk *main_clks[] = {
        &pllc1_clk,
        &pllc1_div2_clk,
        &sh7372_pllc2_clk,
-       &sh7372_fsiack_clk,
-       &sh7372_fsibck_clk,
+       &fsiack_clk,
+       &fsibck_clk,
 };
 
 static void div4_kick(struct clk *clk)
@@ -399,14 +399,14 @@ static struct clk *hdmi_parent[] = {
 static struct clk *fsiackcr_parent[] = {
        [0] = &pllc1_div2_clk,
        [1] = &sh7372_pllc2_clk,
-       [2] = &sh7372_fsiack_clk, /* external input for FSI A */
+       [2] = &fsiack_clk, /* external input for FSI A */
        [3] = NULL,     /* setting prohibited */
 };
 
 static struct clk *fsibckcr_parent[] = {
        [0] = &pllc1_div2_clk,
        [1] = &sh7372_pllc2_clk,
-       [2] = &sh7372_fsibck_clk, /* external input for FSI B */
+       [2] = &fsibck_clk, /* external input for FSI B */
        [3] = NULL,     /* setting prohibited */
 };
 
@@ -507,8 +507,8 @@ static struct clk_lookup lookups[] = {
        CLKDEV_CON_ID("pllc1_clk", &pllc1_clk),
        CLKDEV_CON_ID("pllc1_div2_clk", &pllc1_div2_clk),
        CLKDEV_CON_ID("pllc2_clk", &sh7372_pllc2_clk),
-       CLKDEV_CON_ID("fsidiva", &fsidivs[FSIDIV_A]),
-       CLKDEV_CON_ID("fsidivb", &fsidivs[FSIDIV_B]),
+       CLKDEV_CON_ID("fsiack", &fsiack_clk),
+       CLKDEV_CON_ID("fsibck", &fsibck_clk),
 
        /* DIV4 clocks */
        CLKDEV_CON_ID("i_clk", &div4_clks[DIV4_I]),
@@ -606,8 +606,8 @@ static struct clk_lookup lookups[] = {
        CLKDEV_ICK_ID("spu2", "sh_fsi2", &mstp_clks[MSTP223]),
        CLKDEV_ICK_ID("diva", "sh_fsi2", &fsidivs[FSIDIV_A]),
        CLKDEV_ICK_ID("divb", "sh_fsi2", &fsidivs[FSIDIV_B]),
-       CLKDEV_ICK_ID("xcka", "sh_fsi2", &sh7372_fsiack_clk),
-       CLKDEV_ICK_ID("xckb", "sh_fsi2", &sh7372_fsibck_clk),
+       CLKDEV_ICK_ID("xcka", "sh_fsi2", &fsiack_clk),
+       CLKDEV_ICK_ID("xckb", "sh_fsi2", &fsibck_clk),
 };
 
 void __init sh7372_clock_init(void)
index 26cd1016fad85dde44d9e0d9b21f6ebab0678d66..b582facc1cf6b174d3bcbfe56ef2bb0ac0a6634f 100644 (file)
@@ -477,8 +477,6 @@ extern struct clk sh7372_extal2_clk;
 extern struct clk sh7372_dv_clki_clk;
 extern struct clk sh7372_dv_clki_div2_clk;
 extern struct clk sh7372_pllc2_clk;
-extern struct clk sh7372_fsiack_clk;
-extern struct clk sh7372_fsibck_clk;
 
 extern void sh7372_intcs_suspend(void);
 extern void sh7372_intcs_resume(void);
index 535426c306bd70e7cae25c24ac550d516005999f..f6745628628003f6f23e5e16c3ea175177f256a6 100644 (file)
 
 #define EMEV2_SCU_BASE 0x1e000000
 
+static DEFINE_SPINLOCK(scu_lock);
 static void __iomem *scu_base;
 
+static void modify_scu_cpu_psr(unsigned long set, unsigned long clr)
+{
+       unsigned long tmp;
+
+       /* we assume this code is running on a different cpu
+        * than the one that is changing coherency setting */
+       spin_lock(&scu_lock);
+       tmp = readl(scu_base + 8);
+       tmp &= ~clr;
+       tmp |= set;
+       writel(tmp, scu_base + 8);
+       spin_unlock(&scu_lock);
+
+}
+
 static unsigned int __init emev2_get_core_count(void)
 {
        if (!scu_base) {
@@ -79,7 +95,7 @@ static int __cpuinit emev2_boot_secondary(unsigned int cpu, struct task_struct *
        cpu = cpu_logical_map(cpu);
 
        /* enable cache coherency */
-       scu_power_mode(scu_base, 0);
+       modify_scu_cpu_psr(0, 3 << (cpu * 8));
 
        /* Tell ROM loader about our vector (in headsmp.S) */
        emev2_set_boot_vector(__pa(shmobile_secondary_vector));
@@ -90,10 +106,12 @@ static int __cpuinit emev2_boot_secondary(unsigned int cpu, struct task_struct *
 
 static void __init emev2_smp_prepare_cpus(unsigned int max_cpus)
 {
+       int cpu = cpu_logical_map(0);
+
        scu_enable(scu_base);
 
        /* enable cache coherency on CPU0 */
-       scu_power_mode(scu_base, 0);
+       modify_scu_cpu_psr(0, 3 << (cpu * 8));
 }
 
 static void __init emev2_smp_init_cpus(void)
index 9def0f22bf22cacfb1891e69b947e72874964132..2ce6af9a6a3763954c79b757450adc20007cfd40 100644 (file)
@@ -61,6 +61,9 @@ static void __iomem *scu_base_addr(void)
        return (void __iomem *)0xf0000000;
 }
 
+static DEFINE_SPINLOCK(scu_lock);
+static unsigned long tmp;
+
 #ifdef CONFIG_HAVE_ARM_TWD
 static DEFINE_TWD_LOCAL_TIMER(twd_local_timer, 0xf0000600, 29);
 
@@ -70,6 +73,20 @@ void __init r8a7779_register_twd(void)
 }
 #endif
 
+static void modify_scu_cpu_psr(unsigned long set, unsigned long clr)
+{
+       void __iomem *scu_base = scu_base_addr();
+
+       spin_lock(&scu_lock);
+       tmp = __raw_readl(scu_base + 8);
+       tmp &= ~clr;
+       tmp |= set;
+       spin_unlock(&scu_lock);
+
+       /* disable cache coherency after releasing the lock */
+       __raw_writel(tmp, scu_base + 8);
+}
+
 static unsigned int __init r8a7779_get_core_count(void)
 {
        void __iomem *scu_base = scu_base_addr();
@@ -85,7 +102,7 @@ static int r8a7779_platform_cpu_kill(unsigned int cpu)
        cpu = cpu_logical_map(cpu);
 
        /* disable cache coherency */
-       scu_power_mode(scu_base_addr(), 3);
+       modify_scu_cpu_psr(3 << (cpu * 8), 0);
 
        if (cpu < ARRAY_SIZE(r8a7779_ch_cpu))
                ch = r8a7779_ch_cpu[cpu];
@@ -128,7 +145,7 @@ static int __cpuinit r8a7779_boot_secondary(unsigned int cpu, struct task_struct
        cpu = cpu_logical_map(cpu);
 
        /* enable cache coherency */
-       scu_power_mode(scu_base_addr(), 0);
+       modify_scu_cpu_psr(0, 3 << (cpu * 8));
 
        if (cpu < ARRAY_SIZE(r8a7779_ch_cpu))
                ch = r8a7779_ch_cpu[cpu];
@@ -141,13 +158,15 @@ static int __cpuinit r8a7779_boot_secondary(unsigned int cpu, struct task_struct
 
 static void __init r8a7779_smp_prepare_cpus(unsigned int max_cpus)
 {
+       int cpu = cpu_logical_map(0);
+
        scu_enable(scu_base_addr());
 
        /* Map the reset vector (in headsmp.S) */
        __raw_writel(__pa(shmobile_secondary_vector), AVECR);
 
        /* enable cache coherency on CPU0 */
-       scu_power_mode(scu_base_addr(), 0);
+       modify_scu_cpu_psr(0, 3 << (cpu * 8));
 
        r8a7779_pm_init();
 
index 96ddb97babbee92ca4080d45a463817234d2fbfc..624f00f70abf79e266504073ce99e8a170f43e77 100644 (file)
@@ -41,6 +41,9 @@ static void __iomem *scu_base_addr(void)
        return (void __iomem *)0xf0000000;
 }
 
+static DEFINE_SPINLOCK(scu_lock);
+static unsigned long tmp;
+
 #ifdef CONFIG_HAVE_ARM_TWD
 static DEFINE_TWD_LOCAL_TIMER(twd_local_timer, 0xf0000600, 29);
 void __init sh73a0_register_twd(void)
@@ -49,6 +52,20 @@ void __init sh73a0_register_twd(void)
 }
 #endif
 
+static void modify_scu_cpu_psr(unsigned long set, unsigned long clr)
+{
+       void __iomem *scu_base = scu_base_addr();
+
+       spin_lock(&scu_lock);
+       tmp = __raw_readl(scu_base + 8);
+       tmp &= ~clr;
+       tmp |= set;
+       spin_unlock(&scu_lock);
+
+       /* disable cache coherency after releasing the lock */
+       __raw_writel(tmp, scu_base + 8);
+}
+
 static unsigned int __init sh73a0_get_core_count(void)
 {
        void __iomem *scu_base = scu_base_addr();
@@ -66,7 +83,7 @@ static int __cpuinit sh73a0_boot_secondary(unsigned int cpu, struct task_struct
        cpu = cpu_logical_map(cpu);
 
        /* enable cache coherency */
-       scu_power_mode(scu_base_addr(), 0);
+       modify_scu_cpu_psr(0, 3 << (cpu * 8));
 
        if (((__raw_readl(PSTR) >> (4 * cpu)) & 3) == 3)
                __raw_writel(1 << cpu, WUPCR);  /* wake up */
@@ -78,6 +95,8 @@ static int __cpuinit sh73a0_boot_secondary(unsigned int cpu, struct task_struct
 
 static void __init sh73a0_smp_prepare_cpus(unsigned int max_cpus)
 {
+       int cpu = cpu_logical_map(0);
+
        scu_enable(scu_base_addr());
 
        /* Map the reset vector (in headsmp.S) */
@@ -85,7 +104,7 @@ static void __init sh73a0_smp_prepare_cpus(unsigned int max_cpus)
        __raw_writel(__pa(shmobile_secondary_vector), SBAR);
 
        /* enable cache coherency on CPU0 */
-       scu_power_mode(scu_base_addr(), 0);
+       modify_scu_cpu_psr(0, 3 << (cpu * 8));
 }
 
 static void __init sh73a0_smp_init_cpus(void)
index 803a3281feb581a6123fb5fc7232951c765e8cbe..566e804d40367c8a13bf83164b4c3af7b7320750 100644 (file)
@@ -12,5 +12,6 @@ config ARCH_SOCFPGA
        select GENERIC_CLOCKEVENTS
        select GPIO_PL061 if GPIOLIB
        select HAVE_ARM_SCU
+       select HAVE_SMP
        select SPARSE_IRQ
        select USE_OF
index 4fb93240971d369a51de869d0198c021f1e28274..6dd7a93a90fea07c472c8cbcbd6f0a0ec5a4d779 100644 (file)
@@ -3,3 +3,4 @@
 #
 
 obj-y                                  := socfpga.o
+obj-$(CONFIG_SMP)      += headsmp.o platsmp.o
diff --git a/arch/arm/mach-socfpga/core.h b/arch/arm/mach-socfpga/core.h
new file mode 100644 (file)
index 0000000..9941caa
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2012 Pavel Machek <pavel@denx.de>
+ * Copyright (C) 2012 Altera Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef __MACH_CORE_H
+#define __MACH_CORE_H
+
+extern void secondary_startup(void);
+extern void __iomem *socfpga_scu_base_addr;
+
+extern void socfpga_init_clocks(void);
+extern void socfpga_sysmgr_init(void);
+
+extern struct smp_operations socfpga_smp_ops;
+extern char secondary_trampoline, secondary_trampoline_end;
+
+#define SOCFPGA_SCU_VIRT_BASE   0xfffec000
+
+#endif
diff --git a/arch/arm/mach-socfpga/headsmp.S b/arch/arm/mach-socfpga/headsmp.S
new file mode 100644 (file)
index 0000000..f09b128
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ *  Copyright (c) 2003 ARM Limited
+ *  Copyright (c) u-boot contributors
+ *  Copyright (c) 2012 Pavel Machek <pavel@denx.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/linkage.h>
+#include <linux/init.h>
+
+       __CPUINIT
+       .arch   armv7-a
+
+#define CPU1_START_ADDR                0xffd08010
+
+ENTRY(secondary_trampoline)
+       movw    r0, #:lower16:CPU1_START_ADDR
+       movt  r0, #:upper16:CPU1_START_ADDR
+
+       ldr     r1, [r0]
+       bx      r1
+
+ENTRY(secondary_trampoline_end)
diff --git a/arch/arm/mach-socfpga/platsmp.c b/arch/arm/mach-socfpga/platsmp.c
new file mode 100644 (file)
index 0000000..68dd1b6
--- /dev/null
@@ -0,0 +1,116 @@
+/*
+ * Copyright 2010-2011 Calxeda, Inc.
+ * Copyright 2012 Pavel Machek <pavel@denx.de>
+ * Based on platsmp.c, Copyright (C) 2002 ARM Ltd.
+ * Copyright (C) 2012 Altera Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/smp.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+
+#include <asm/cacheflush.h>
+#include <asm/hardware/gic.h>
+#include <asm/smp_scu.h>
+#include <asm/smp_plat.h>
+
+#include "core.h"
+
+extern void __iomem *sys_manager_base_addr;
+extern void __iomem *rst_manager_base_addr;
+
+static void __cpuinit socfpga_secondary_init(unsigned int cpu)
+{
+       /*
+        * if any interrupts are already enabled for the primary
+        * core (e.g. timer irq), then they will not have been enabled
+        * for us: do so
+        */
+       gic_secondary_init(0);
+}
+
+static int __cpuinit socfpga_boot_secondary(unsigned int cpu, struct task_struct *idle)
+{
+       int trampoline_size = &secondary_trampoline_end - &secondary_trampoline;
+
+       memcpy(phys_to_virt(0), &secondary_trampoline, trampoline_size);
+
+       __raw_writel(virt_to_phys(secondary_startup), (sys_manager_base_addr+0x10));
+
+       flush_cache_all();
+       smp_wmb();
+       outer_clean_range(0, trampoline_size);
+
+       /* This will release CPU #1 out of reset.*/
+       __raw_writel(0, rst_manager_base_addr + 0x10);
+
+       return 0;
+}
+
+/*
+ * Initialise the CPU possible map early - this describes the CPUs
+ * which may be present or become present in the system.
+ */
+static void __init socfpga_smp_init_cpus(void)
+{
+       unsigned int i, ncores;
+
+       ncores = scu_get_core_count(socfpga_scu_base_addr);
+
+       for (i = 0; i < ncores; i++)
+               set_cpu_possible(i, true);
+
+       /* sanity check */
+       if (ncores > num_possible_cpus()) {
+               pr_warn("socfpga: no. of cores (%d) greater than configured"
+                       "maximum of %d - clipping\n", ncores, num_possible_cpus());
+               ncores = num_possible_cpus();
+       }
+
+       for (i = 0; i < ncores; i++)
+               set_cpu_possible(i, true);
+
+       set_smp_cross_call(gic_raise_softirq);
+}
+
+static void __init socfpga_smp_prepare_cpus(unsigned int max_cpus)
+{
+       scu_enable(socfpga_scu_base_addr);
+}
+
+/*
+ * platform-specific code to shutdown a CPU
+ *
+ * Called with IRQs disabled
+ */
+static void socfpga_cpu_die(unsigned int cpu)
+{
+       cpu_do_idle();
+
+       /* We should have never returned from idle */
+       panic("cpu %d unexpectedly exit from shutdown\n", cpu);
+}
+
+struct smp_operations socfpga_smp_ops __initdata = {
+       .smp_init_cpus          = socfpga_smp_init_cpus,
+       .smp_prepare_cpus       = socfpga_smp_prepare_cpus,
+       .smp_secondary_init     = socfpga_secondary_init,
+       .smp_boot_secondary     = socfpga_boot_secondary,
+#ifdef CONFIG_HOTPLUG_CPU
+       .cpu_die                = socfpga_cpu_die,
+#endif
+};
index f01e1ebf539601dd772eb9237eea5252800fb806..6732924a5fee2900fb8b9bc97c39921cd966b136 100644 (file)
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 #include <linux/dw_apb_timer.h>
+#include <linux/of_address.h>
 #include <linux/of_irq.h>
 #include <linux/of_platform.h>
 
 #include <asm/hardware/cache-l2x0.h>
 #include <asm/hardware/gic.h>
 #include <asm/mach/arch.h>
+#include <asm/mach/map.h>
 
-extern void socfpga_init_clocks(void);
+#include "core.h"
+
+void __iomem *socfpga_scu_base_addr = ((void __iomem *)(SOCFPGA_SCU_VIRT_BASE));
+void __iomem *sys_manager_base_addr;
+void __iomem *rst_manager_base_addr;
+
+static struct map_desc scu_io_desc __initdata = {
+       .virtual        = SOCFPGA_SCU_VIRT_BASE,
+       .pfn            = 0, /* run-time */
+       .length         = SZ_8K,
+       .type           = MT_DEVICE,
+};
+
+static struct map_desc uart_io_desc __initdata = {
+       .virtual        = 0xfec02000,
+       .pfn            = __phys_to_pfn(0xffc02000),
+       .length         = SZ_8K,
+       .type           = MT_DEVICE,
+};
+
+static void __init socfpga_scu_map_io(void)
+{
+       unsigned long base;
+
+       /* Get SCU base */
+       asm("mrc p15, 4, %0, c15, c0, 0" : "=r" (base));
+
+       scu_io_desc.pfn = __phys_to_pfn(base);
+       iotable_init(&scu_io_desc, 1);
+}
+
+static void __init socfpga_map_io(void)
+{
+       socfpga_scu_map_io();
+       iotable_init(&uart_io_desc, 1);
+       early_printk("Early printk initialized\n");
+}
 
 const static struct of_device_id irq_match[] = {
        { .compatible = "arm,cortex-a9-gic", .data = gic_of_init, },
        {}
 };
 
+void __init socfpga_sysmgr_init(void)
+{
+       struct device_node *np;
+
+       np = of_find_compatible_node(NULL, NULL, "altr,sys-mgr");
+       sys_manager_base_addr = of_iomap(np, 0);
+
+       np = of_find_compatible_node(NULL, NULL, "altr,rst-mgr");
+       rst_manager_base_addr = of_iomap(np, 0);
+}
+
 static void __init gic_init_irq(void)
 {
        of_irq_init(irq_match);
+       socfpga_sysmgr_init();
 }
 
 static void socfpga_cyclone5_restart(char mode, const char *cmd)
@@ -53,6 +103,8 @@ static const char *altera_dt_match[] = {
 };
 
 DT_MACHINE_START(SOCFPGA, "Altera SOCFPGA")
+       .smp            = smp_ops(socfpga_smp_ops),
+       .map_io         = socfpga_map_io,
        .init_irq       = gic_init_irq,
        .handle_irq     = gic_handle_irq,
        .timer          = &dw_apb_timer,
index 012bbd0b8d81063fa7db1547f440b7ca97adca74..47c9fad43f00124ce8e78e3f04b141f716034cd6 100644 (file)
@@ -389,6 +389,72 @@ int __init s3c24xx_register_baseclocks(unsigned long xtal)
 
 static struct dentry *clk_debugfs_root;
 
+static void clock_tree_show_one(struct seq_file *s, struct clk *c, int level)
+{
+       struct clk *child;
+       const char *state;
+       char buf[255] = { 0 };
+       int n = 0;
+
+       if (c->name)
+               n = snprintf(buf, sizeof(buf) - 1, "%s", c->name);
+
+       if (c->devname)
+               n += snprintf(buf + n, sizeof(buf) - 1 - n, ":%s", c->devname);
+
+       state = (c->usage > 0) ? "on" : "off";
+
+       seq_printf(s, "%*s%-*s %-6s %-3d %-10lu\n",
+                  level * 3 + 1, "",
+                  50 - level * 3, buf,
+                  state, c->usage, clk_get_rate(c));
+
+       list_for_each_entry(child, &clocks, list) {
+               if (child->parent != c)
+                       continue;
+
+               clock_tree_show_one(s, child, level + 1);
+       }
+}
+
+static int clock_tree_show(struct seq_file *s, void *data)
+{
+       struct clk *c;
+       unsigned long flags;
+
+       seq_printf(s, " clock state ref rate\n");
+       seq_printf(s, "----------------------------------------------------\n");
+
+       spin_lock_irqsave(&clocks_lock, flags);
+
+       list_for_each_entry(c, &clocks, list)
+               if (c->parent == NULL)
+                       clock_tree_show_one(s, c, 0);
+
+       spin_unlock_irqrestore(&clocks_lock, flags);
+       return 0;
+}
+
+static int clock_tree_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, clock_tree_show, inode->i_private);
+}
+
+static const struct file_operations clock_tree_fops = {
+       .open           = clock_tree_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+};
+
+static int clock_rate_show(void *data, u64 *val)
+{
+       struct clk *c = data;
+       *val = clk_get_rate(c);
+       return 0;
+}
+DEFINE_SIMPLE_ATTRIBUTE(clock_rate_fops, clock_rate_show, NULL, "%llu\n");
+
 static int clk_debugfs_register_one(struct clk *c)
 {
        int err;
@@ -411,7 +477,7 @@ static int clk_debugfs_register_one(struct clk *c)
                goto err_out;
        }
 
-       d = debugfs_create_u32("rate", S_IRUGO, c->dent, (u32 *)&c->rate);
+       d = debugfs_create_file("rate", S_IRUGO, c->dent, c, &clock_rate_fops);
        if (!d) {
                err = -ENOMEM;
                goto err_out;
@@ -446,13 +512,18 @@ static int __init clk_debugfs_init(void)
 {
        struct clk *c;
        struct dentry *d;
-       int err;
+       int err = -ENOMEM;
 
        d = debugfs_create_dir("clock", NULL);
        if (!d)
                return -ENOMEM;
        clk_debugfs_root = d;
 
+       d = debugfs_create_file("clock_tree", S_IRUGO, clk_debugfs_root, NULL,
+                                &clock_tree_fops);
+       if (!d)
+               goto err_out;
+
        list_for_each_entry(c, &clocks, list) {
                err = clk_debugfs_register(c);
                if (err)
index b3dc44146ca072bdacc97ab0ba3f872a664a341a..5aedcdf4ac5cd185a2ffac8ebcca2e3dcffd6c27 100644 (file)
@@ -401,7 +401,6 @@ static int fsidiv_enable(struct clk *clk)
 
 static int fsidiv_set_rate(struct clk *clk, unsigned long rate)
 {
-       u32 val;
        int idx;
 
        idx = (clk->parent->rate / rate) & 0xffff;