rk30: support cpu axi qos setup properly, and add setup lcdc qos
author黄涛 <huangtao@rock-chips.com>
Sat, 26 Jan 2013 04:19:41 +0000 (12:19 +0800)
committer黄涛 <huangtao@rock-chips.com>
Sat, 26 Jan 2013 04:20:34 +0000 (12:20 +0800)
arch/arm/mach-rk30/common.c
arch/arm/mach-rk30/include/mach/cpu_axi.h [new file with mode: 0644]
arch/arm/mach-rk30/pm.c
arch/arm/mach-rk30/pmu.c

index 8c3f436d279e758466fc93d49ccfbb30f8d9d763..f5148b95487acb462100922bed723f30b9d143c5 100755 (executable)
 #include <mach/loader.h>
 #include <mach/ddr.h>
 #include <mach/dvfs.h>
+#include <mach/cpu_axi.h>
 
 static void __init rk30_cpu_axi_init(void)
 {
-#ifdef CONFIG_ARCH_RK3188
-       writel_relaxed(0x0, RK30_CPU_AXI_BUS_BASE + 0x1008);    // dmac1
-       writel_relaxed(0x0, RK30_CPU_AXI_BUS_BASE + 0x2008);    // cpu0
-       writel_relaxed(0x0, RK30_CPU_AXI_BUS_BASE + 0x2088);    // cpu1r
-       writel_relaxed(0x0, RK30_CPU_AXI_BUS_BASE + 0x2108);    // cpu1w
-#else
-       writel_relaxed(0x0, RK30_CPU_AXI_BUS_BASE + 0x0088);    // cpu0
-       writel_relaxed(0x0, RK30_CPU_AXI_BUS_BASE + 0x0108);    // dmac1
-       writel_relaxed(0x0, RK30_CPU_AXI_BUS_BASE + 0x0188);    // cpu1r
-       writel_relaxed(0x0, RK30_CPU_AXI_BUS_BASE + 0x0388);    // cpu1w
-#endif
+       CPU_AXI_SET_QOS_PRIORITY(0, 0, DMAC);
+       CPU_AXI_SET_QOS_PRIORITY(0, 0, CPU0);
+       CPU_AXI_SET_QOS_PRIORITY(0, 0, CPU1R);
+       CPU_AXI_SET_QOS_PRIORITY(0, 0, CPU1W);
 #ifdef CONFIG_RK29_VMAC
-       writel_relaxed(0xa, RK30_CPU_AXI_BUS_BASE + 0x4008);    // peri
+       CPU_AXI_SET_QOS_PRIORITY(2, 2, PERI);
 #else
-       writel_relaxed(0x0, RK30_CPU_AXI_BUS_BASE + 0x4008);    // peri
-#endif
-#if 0
-       writel_relaxed(0x0, RK30_CPU_AXI_BUS_BASE + 0x5008);    // gpu
-       writel_relaxed(0x0, RK30_CPU_AXI_BUS_BASE + 0x6008);    // vpu
-       writel_relaxed(0xa, RK30_CPU_AXI_BUS_BASE + 0x7008);    // lcdc0
-       writel_relaxed(0x0, RK30_CPU_AXI_BUS_BASE + 0x7088);    // cif0
-       writel_relaxed(0x0, RK30_CPU_AXI_BUS_BASE + 0x7108);    // ipp
-       writel_relaxed(0xa, RK30_CPU_AXI_BUS_BASE + 0x7188);    // lcdc1
-       writel_relaxed(0x0, RK30_CPU_AXI_BUS_BASE + 0x7208);    // cif1
-       writel_relaxed(0x0, RK30_CPU_AXI_BUS_BASE + 0x7288);    // rga
+       CPU_AXI_SET_QOS_PRIORITY(0, 0, PERI);
 #endif
+       CPU_AXI_SET_QOS_PRIORITY(3, 3, LCDC0);
+       CPU_AXI_SET_QOS_PRIORITY(3, 3, LCDC1);
+
        writel_relaxed(0x3f, RK30_CPU_AXI_BUS_BASE + 0x0014);   // memory scheduler read latency
        dsb();
 }
diff --git a/arch/arm/mach-rk30/include/mach/cpu_axi.h b/arch/arm/mach-rk30/include/mach/cpu_axi.h
new file mode 100644 (file)
index 0000000..7fe8556
--- /dev/null
@@ -0,0 +1,56 @@
+#ifndef __MACH_CPU_AXI_H
+#define __MACH_CPU_AXI_H
+
+#define CPU_AXI_QOS_PRIORITY    0x08
+#define CPU_AXI_QOS_MODE        0x0c
+#define CPU_AXI_QOS_BANDWIDTH   0x10
+#define CPU_AXI_QOS_SATURATION  0x14
+
+#define CPU_AXI_QOS_MODE_NONE           0
+#define CPU_AXI_QOS_MODE_FIXED          1
+#define CPU_AXI_QOS_MODE_LIMITER        2
+#define CPU_AXI_QOS_MODE_REGULATOR      3
+
+#define CPU_AXI_QOS_PRIORITY_LEVEL(h, l)        (((h & 3) << 2) | (l & 3))
+#define CPU_AXI_SET_QOS_PRIORITY(h, l, NAME) \
+       writel_relaxed(CPU_AXI_QOS_PRIORITY_LEVEL(h, l), CPU_AXI_##NAME##_QOS_BASE + CPU_AXI_QOS_PRIORITY)
+#define CPU_AXI_QOS_NUM_REGS 4
+#define CPU_AXI_SAVE_QOS(array, NAME) do { \
+       array[0] = readl_relaxed(CPU_AXI_##NAME##_QOS_BASE + CPU_AXI_QOS_PRIORITY); \
+       array[1] = readl_relaxed(CPU_AXI_##NAME##_QOS_BASE + CPU_AXI_QOS_MODE); \
+       array[2] = readl_relaxed(CPU_AXI_##NAME##_QOS_BASE + CPU_AXI_QOS_BANDWIDTH); \
+       array[3] = readl_relaxed(CPU_AXI_##NAME##_QOS_BASE + CPU_AXI_QOS_SATURATION); \
+} while (0)
+#define CPU_AXI_RESTORE_QOS(array, NAME) do { \
+       writel_relaxed(array[0], CPU_AXI_##NAME##_QOS_BASE + CPU_AXI_QOS_PRIORITY); \
+       writel_relaxed(array[1], CPU_AXI_##NAME##_QOS_BASE + CPU_AXI_QOS_MODE); \
+       writel_relaxed(array[2], CPU_AXI_##NAME##_QOS_BASE + CPU_AXI_QOS_BANDWIDTH); \
+       writel_relaxed(array[3], CPU_AXI_##NAME##_QOS_BASE + CPU_AXI_QOS_SATURATION); \
+} while (0)
+
+#define CPU_AXI_LCDC0_QOS_BASE          (RK30_CPU_AXI_BUS_BASE + 0x7000)
+#define CPU_AXI_CIF0_QOS_BASE           (RK30_CPU_AXI_BUS_BASE + 0x7080)
+#define CPU_AXI_IPP_QOS_BASE            (RK30_CPU_AXI_BUS_BASE + 0x7100)
+#define CPU_AXI_LCDC1_QOS_BASE          (RK30_CPU_AXI_BUS_BASE + 0x7180)
+#define CPU_AXI_CIF1_QOS_BASE           (RK30_CPU_AXI_BUS_BASE + 0x7200)
+#define CPU_AXI_RGA_QOS_BASE            (RK30_CPU_AXI_BUS_BASE + 0x7280)
+
+#define CPU_AXI_PERI_QOS_BASE           (RK30_CPU_AXI_BUS_BASE + 0x4000)
+
+#define CPU_AXI_GPU_QOS_BASE            (RK30_CPU_AXI_BUS_BASE + 0x5000)
+
+#define CPU_AXI_VPU_QOS_BASE            (RK30_CPU_AXI_BUS_BASE + 0x6000)
+
+#ifdef CONFIG_ARCH_RK3188
+#define CPU_AXI_DMAC_QOS_BASE           (RK30_CPU_AXI_BUS_BASE + 0x1000)
+#define CPU_AXI_CPU0_QOS_BASE           (RK30_CPU_AXI_BUS_BASE + 0x2000)
+#define CPU_AXI_CPU1R_QOS_BASE          (RK30_CPU_AXI_BUS_BASE + 0x2080)
+#define CPU_AXI_CPU1W_QOS_BASE          (RK30_CPU_AXI_BUS_BASE + 0x2100)
+#else
+#define CPU_AXI_CPU0_QOS_BASE           (RK30_CPU_AXI_BUS_BASE + 0x0080)
+#define CPU_AXI_DMAC_QOS_BASE           (RK30_CPU_AXI_BUS_BASE + 0x0100)
+#define CPU_AXI_CPU1R_QOS_BASE          (RK30_CPU_AXI_BUS_BASE + 0x0180)
+#define CPU_AXI_CPU1W_QOS_BASE          (RK30_CPU_AXI_BUS_BASE + 0x0380)
+#endif
+
+#endif
index bdc04fec75930b770e7ab52180da23d592eb6be3..c73a3930b08152bbb43c7e9d47e6a1c77a397a34 100755 (executable)
@@ -23,6 +23,7 @@
 #include <mach/cru.h>
 #include <mach/ddr.h>
 #include <mach/debug_uart.h>
+#include <mach/cpu_axi.h>
 
 #define cru_readl(offset)      readl_relaxed(RK30_CRU_BASE + offset)
 #define cru_writel(v, offset)  do { writel_relaxed(v, RK30_CRU_BASE + offset); dsb(); } while (0)
@@ -402,6 +403,8 @@ static void rk30_pm_set_power_domain(u32 pmu_pwrdn_st, bool state)
 
        if (pm_pmu_power_domain_is_on(PD_VIO, pmu_pwrdn_st)) {
                u32 gate[10];
+               static u32 lcdc0_qos[CPU_AXI_QOS_NUM_REGS];
+               static u32 lcdc1_qos[CPU_AXI_QOS_NUM_REGS];
                gate[0] = cru_readl(CLK_GATE_CLKID_CONS(CLK_GATE_ACLK_LCDC0_SRC));
                gate[1] = cru_readl(CLK_GATE_CLKID_CONS(CLK_GATE_ACLK_LCDC1_SRC));
                gate[2] = cru_readl(CLK_GATE_CLKID_CONS(CLK_GATE_ACLK_LCDC0));
@@ -422,7 +425,15 @@ static void rk30_pm_set_power_domain(u32 pmu_pwrdn_st, bool state)
                cru_writel(CLK_GATE_W_MSK(CLK_GATE_ACLK_VIO1), CLK_GATE_CLKID_CONS(CLK_GATE_ACLK_VIO1));
                cru_writel(CLK_GATE_W_MSK(CLK_GATE_ACLK_IPP), CLK_GATE_CLKID_CONS(CLK_GATE_ACLK_IPP));
                cru_writel(CLK_GATE_W_MSK(CLK_GATE_ACLK_RGA), CLK_GATE_CLKID_CONS(CLK_GATE_ACLK_RGA));
+               if (!state) {
+                       CPU_AXI_SAVE_QOS(lcdc0_qos, LCDC0);
+                       CPU_AXI_SAVE_QOS(lcdc1_qos, LCDC0);
+               }
                pmu_set_power_domain(PD_VIO, state);
+               if (state) {
+                       CPU_AXI_RESTORE_QOS(lcdc0_qos, LCDC0);
+                       CPU_AXI_RESTORE_QOS(lcdc1_qos, LCDC0);
+               }
                cru_writel(CLK_GATE_W_MSK(CLK_GATE_ACLK_LCDC0_SRC) | gate[0], CLK_GATE_CLKID_CONS(CLK_GATE_ACLK_LCDC0_SRC));
                cru_writel(CLK_GATE_W_MSK(CLK_GATE_ACLK_LCDC1_SRC) | gate[1], CLK_GATE_CLKID_CONS(CLK_GATE_ACLK_LCDC1_SRC));
                cru_writel(CLK_GATE_W_MSK(CLK_GATE_ACLK_LCDC0) | gate[2], CLK_GATE_CLKID_CONS(CLK_GATE_ACLK_LCDC0));
index 11f6b20ba3327a7c904904b10cf05cc2b76df295..d8c3b197a20009ce5a7ba51153c92f32c3706814 100644 (file)
@@ -2,6 +2,7 @@
 #include <linux/spinlock.h>
 #include <mach/pmu.h>
 #include <mach/sram.h>
+#include <mach/cpu_axi.h>
 
 static void __sramfunc pmu_set_power_domain_sram(enum pmu_power_domain pd, bool on)
 {
@@ -34,6 +35,8 @@ static noinline void do_pmu_set_power_domain(enum pmu_power_domain pd, bool on)
  *  change dramatically which will affect the chip function.
  */
 static DEFINE_SPINLOCK(pmu_pd_lock);
+static u32 lcdc0_qos[CPU_AXI_QOS_NUM_REGS];
+static u32 lcdc1_qos[CPU_AXI_QOS_NUM_REGS];
 
 void pmu_set_power_domain(enum pmu_power_domain pd, bool on)
 {
@@ -46,9 +49,11 @@ void pmu_set_power_domain(enum pmu_power_domain pd, bool on)
        }
        if (!on) {
                /* if power down, idle request to NIU first */
-               if (pd == PD_VIO)
+               if (pd == PD_VIO) {
+                       CPU_AXI_SAVE_QOS(lcdc0_qos, LCDC0);
+                       CPU_AXI_SAVE_QOS(lcdc1_qos, LCDC1);
                        pmu_set_idle_request(IDLE_REQ_VIO, true);
-               else if (pd == PD_VIDEO)
+               else if (pd == PD_VIDEO)
                        pmu_set_idle_request(IDLE_REQ_VIDEO, true);
                else if (pd == PD_GPU)
                        pmu_set_idle_request(IDLE_REQ_GPU, true);
@@ -56,9 +61,11 @@ void pmu_set_power_domain(enum pmu_power_domain pd, bool on)
        do_pmu_set_power_domain(pd, on);
        if (on) {
                /* if power up, idle request release to NIU */
-               if (pd == PD_VIO)
+               if (pd == PD_VIO) {
                        pmu_set_idle_request(IDLE_REQ_VIO, false);
-               else if (pd == PD_VIDEO)
+                       CPU_AXI_RESTORE_QOS(lcdc0_qos, LCDC0);
+                       CPU_AXI_RESTORE_QOS(lcdc1_qos, LCDC1);
+               } else if (pd == PD_VIDEO)
                        pmu_set_idle_request(IDLE_REQ_VIDEO, false);
                else if (pd == PD_GPU)
                        pmu_set_idle_request(IDLE_REQ_GPU, false);