ARM: rockchip: fix rk3288 smp and timer support
author黄涛 <huangtao@rock-chips.com>
Fri, 21 Mar 2014 10:07:09 +0000 (18:07 +0800)
committer黄涛 <huangtao@rock-chips.com>
Fri, 21 Mar 2014 10:07:37 +0000 (18:07 +0800)
arch/arm/boot/dts/rk3288.dtsi
arch/arm/mach-rockchip/platsmp.c
arch/arm/mach-rockchip/rk3288.c

index 44a64d75ab1520dc194c9b1c0c1eedf60e11d1dc..c7cd9feea8c28d0fdce54d35333e602f4c3bc025 100755 (executable)
@@ -41,7 +41,6 @@
                        compatible = "arm,cortex-a15";
                        reg = <0x500>;
                };
-/*
                cpu@1 {
                        device_type = "cpu";
                        compatible = "arm,cortex-a15";
@@ -57,7 +56,6 @@
                        compatible = "arm,cortex-a15";
                        reg = <0x503>;
                };
-*/
        };
 
        gic: interrupt-controller@ffc01000 {
        };
 */
 
+       timer@ff6b0000 {
+               compatible = "rockchip,timer";
+               reg = <0xff6b0000 0x20>;
+               interrupts = <GIC_SPI 66 IRQ_TYPE_LEVEL_HIGH>;
+               rockchip,percpu = <0>;
+       };
+
+       timer@ff6b0020 {
+               compatible = "rockchip,timer";
+               reg = <0xff6b0020 0x20>;
+               interrupts = <GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>;
+               rockchip,percpu = <1>;
+       };
+
+       timer@ff6b0040 {
+               compatible = "rockchip,timer";
+               reg = <0xff6b0040 0x20>;
+               interrupts = <GIC_SPI 68 IRQ_TYPE_LEVEL_HIGH>;
+               rockchip,percpu = <2>;
+       };
+
+       timer@ff6b0060 {
+               compatible = "rockchip,timer";
+               reg = <0xff6b0060 0x20>;
+               interrupts = <GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH>;
+               rockchip,percpu = <3>;
+       };
+
        timer@ff810000 {
                compatible = "rockchip,timer";
                reg = <0xff810000 0x20>;
index d0358a372ae6600e84d9176466c4507915c9a256..9444a1c5e54111d0af0c8d791928f97ab10771d6 100644 (file)
@@ -147,8 +147,21 @@ static void __init rockchip_a9_smp_prepare_cpus(unsigned int max_cpus)
 
 static void __init rockchip_smp_prepare_cpus(unsigned int max_cpus)
 {
+       unsigned int i, cpu;
+       unsigned long scuctlr;
+
        if (scu_a9_has_base())
                return rockchip_a9_smp_prepare_cpus(max_cpus);
+
+       asm("mrc p15, 1, %0, c9, c0, 4" : "=r" (scuctlr));
+       ncores = (scuctlr & 3) + 1;
+       cpu = MPIDR_AFFINITY_LEVEL(read_cpuid_mpidr(), 0);
+       /* Make sure that all cores except myself are really off */
+       for (i = 0; i < ncores; i++) {
+               if (i == cpu)
+                       continue;
+               rockchip_pmu_ops.set_power_domain(PD_CPU_0 + i, false);
+       }
 }
 
 struct smp_operations rockchip_smp_ops __initdata = {
index 1ee73bb90e51c894e5c0b82e8571277af6f065d9..f493c5718cb82f97eb4b18e575098741a7dc9f30 100755 (executable)
@@ -16,6 +16,7 @@
 
 #include <linux/clk-provider.h>
 #include <linux/clocksource.h>
+#include <linux/delay.h>
 #include <linux/init.h>
 #include <linux/irqchip.h>
 #include <linux/kernel.h>
@@ -45,6 +46,8 @@
 #define RK3288_SERVICE_DEVICE(name) \
        RK_DEVICE(RK3288_SERVICE_##name##_VIRT, RK3288_SERVICE_##name##_PHYS, RK3288_SERVICE_##name##_SIZE)
 
+#define RK3288_IMEM_VIRT (RK_BOOTRAM_VIRT + SZ_32K)
+
 static struct map_desc rk3288_io_desc[] __initdata = {
        RK3288_DEVICE(CRU),
        RK3288_DEVICE(GRF),
@@ -73,10 +76,10 @@ static struct map_desc rk3288_io_desc[] __initdata = {
        RK_DEVICE(RK_GPIO_VIRT(7), RK3288_GPIO7_PHYS, RK3288_GPIO_SIZE),
        RK_DEVICE(RK_GPIO_VIRT(8), RK3288_GPIO8_PHYS, RK3288_GPIO_SIZE),
        RK_DEVICE(RK_DEBUG_UART_VIRT, RK3288_UART_DBG_PHYS, RK3288_UART_SIZE),
-        RK_DEVICE(RK_GIC_VIRT, RK3288_GIC_DIST_PHYS, RK3288_GIC_DIST_SIZE),      
-        RK_DEVICE(RK_GIC_VIRT+RK3288_GIC_DIST_SIZE, RK3288_GIC_DIST_PHYS+RK3288_GIC_DIST_SIZE, RK3288_GIC_CPU_SIZE),
-        RK_DEVICE(RK_BOOTRAM_VIRT, RK3288_BOOTRAM_PHYS, RK3288_BOOTRAM_SIZE),      
-
+       RK_DEVICE(RK_GIC_VIRT, RK3288_GIC_DIST_PHYS, RK3288_GIC_DIST_SIZE),
+       RK_DEVICE(RK_GIC_VIRT + RK3288_GIC_DIST_SIZE, RK3288_GIC_DIST_PHYS + RK3288_GIC_DIST_SIZE, RK3288_GIC_CPU_SIZE),
+       RK_DEVICE(RK_BOOTRAM_VIRT, RK3288_BOOTRAM_PHYS, RK3288_BOOTRAM_SIZE),
+       RK_DEVICE(RK3288_IMEM_VIRT, RK3288_IMEM_PHYS, SZ_4K),
 };
 
 static void __init rk3288_boot_mode_init(void)
@@ -96,16 +99,16 @@ static void __init rk3288_boot_mode_init(void)
 
 static void usb_uart_init(void)
 {
-    u32 soc_status2;
+       u32 soc_status2;
        writel_relaxed(0x00c00000, RK_GRF_VIRT + RK3288_GRF_UOC0_CON3);
 #ifdef CONFIG_RK_USB_UART
-    soc_status2 = (readl_relaxed(RK_GRF_VIRT + RK3288_GRF_SOC_STATUS2));
-    if(!(soc_status2 & (1<<14)) && (soc_status2 & (1<<17)))
-    {
-        writel_relaxed(0x00040004, RK_GRF_VIRT + RK3288_GRF_UOC0_CON2); //software control usb phy enable 
+       soc_status2 = (readl_relaxed(RK_GRF_VIRT + RK3288_GRF_SOC_STATUS2));
+       if(!(soc_status2 & (1<<14)) && (soc_status2 & (1<<17)))
+       {
+               writel_relaxed(0x00040004, RK_GRF_VIRT + RK3288_GRF_UOC0_CON2); //software control usb phy enable 
                writel_relaxed(0x003f002a, RK_GRF_VIRT + RK3288_GRF_UOC0_CON3); //usb phy enter suspend
                writel_relaxed(0x00c000c0, RK_GRF_VIRT + RK3288_GRF_UOC0_CON3);
-    }    
+       }
 #endif // end of CONFIG_RK_USB_UART
 }
 
@@ -121,12 +124,6 @@ static void __init rk3288_dt_map_io(void)
        /* rkpwm is used instead of old pwm */
        writel_relaxed(0x00010001, RK_GRF_VIRT + RK3288_GRF_SOC_CON2);
 
-#ifdef CONFIG_SMP
-       /* enable fast boot */
-       writel_relaxed(0x01000100, RK_SGRF_VIRT + RK3288_SGRF_SOC_CON0);
-       writel_relaxed(virt_to_phys(secondary_startup), RK_SGRF_VIRT + RK3288_SGRF_FAST_BOOT_ADDR);
-#endif
-
        rk3288_boot_mode_init();
 }
 
@@ -302,6 +299,11 @@ static int rk3288_pmu_set_power_domain(enum pmu_power_domain pd, bool on)
                        rk3288_pmu_set_idle_request(IDLE_REQ_HEVC, false);
                        RESTORE_QOS(hevc_r_qos, HEVC_R);
                        RESTORE_QOS(hevc_w_qos, HEVC_W);
+               } else if (pd >= PD_CPU_1 && pd <= PD_CPU_3) {
+                       udelay(10);
+                       writel_relaxed(virt_to_phys(secondary_startup), RK3288_IMEM_VIRT + 8);
+                       writel_relaxed(0xDEADBEAF, RK3288_IMEM_VIRT + 4);
+                       dsb_sev();
                }
        }
 
@@ -391,8 +393,8 @@ arch_initcall(rk3288_pie_init);
 static void __init rk3288_init_suspend(void)
 {
        return;
-        rockchip_suspend_init();       
-        rkpm_pie_init();
-        rk3288_suspend_init();
+       rockchip_suspend_init();
+       rkpm_pie_init();
+       rk3288_suspend_init();
 }
 #endif