ARM: EXYNOS4: Implement Clock gating for System MMU
authorKyongHo Cho <pullip.cho@samsung.com>
Mon, 7 Mar 2011 00:10:24 +0000 (09:10 +0900)
committerKukjin Kim <kgene.kim@samsung.com>
Tue, 15 Mar 2011 12:37:38 +0000 (21:37 +0900)
This patch includes the implementation of the clock gating
for System MMU. Initially, all System MMUs are not asserted
the system clock. Asserting the system clock to a System MMU
is enabled only when s5p_sysmmu_enable() is called. Likewise,
it is disabled only when s5p_sysmmu_disable() is called.
Therefore, clock gating on System MMUs are still invisible to
the outside of the System MMU driver.

Signed-off-by: KyongHo Cho <pullip.cho@samsung.com>
Signed-off-by: Kukjin Kim <kgene.kim@samsung.com>
arch/arm/mach-exynos4/clock.c
arch/arm/mach-exynos4/dev-sysmmu.c
arch/arm/mach-exynos4/include/mach/regs-clock.h
arch/arm/mach-exynos4/include/mach/sysmmu.h
arch/arm/plat-s5p/sysmmu.c

index 15f1333..871f9d5 100644 (file)
@@ -23,6 +23,7 @@
 
 #include <mach/map.h>
 #include <mach/regs-clock.h>
+#include <mach/sysmmu.h>
 
 static struct clk clk_sclk_hdmi27m = {
        .name           = "sclk_hdmi27m",
@@ -81,11 +82,21 @@ static int exynos4_clksrc_mask_peril1_ctrl(struct clk *clk, int enable)
        return s5p_gatectrl(S5P_CLKSRC_MASK_PERIL1, clk, enable);
 }
 
+static int exynos4_clk_ip_mfc_ctrl(struct clk *clk, int enable)
+{
+       return s5p_gatectrl(S5P_CLKGATE_IP_MFC, clk, enable);
+}
+
 static int exynos4_clk_ip_cam_ctrl(struct clk *clk, int enable)
 {
        return s5p_gatectrl(S5P_CLKGATE_IP_CAM, clk, enable);
 }
 
+static int exynos4_clk_ip_tv_ctrl(struct clk *clk, int enable)
+{
+       return s5p_gatectrl(S5P_CLKGATE_IP_TV, clk, enable);
+}
+
 static int exynos4_clk_ip_image_ctrl(struct clk *clk, int enable)
 {
        return s5p_gatectrl(S5P_CLKGATE_IP_IMAGE, clk, enable);
@@ -602,7 +613,77 @@ static struct clk init_clocks_off[] = {
                .parent         = &clk_aclk_100.clk,
                .enable         = exynos4_clk_ip_peril_ctrl,
                .ctrlbit        = (1 << 13),
-       },
+       }, {
+               .name           = "SYSMMU_MDMA",
+               .id             = -1,
+               .enable         = exynos4_clk_ip_image_ctrl,
+               .ctrlbit        = (1 << 5),
+       }, {
+               .name           = "SYSMMU_FIMC0",
+               .id             = -1,
+               .enable         = exynos4_clk_ip_cam_ctrl,
+               .ctrlbit        = (1 << 7),
+       }, {
+               .name           = "SYSMMU_FIMC1",
+               .id             = -1,
+               .enable         = exynos4_clk_ip_cam_ctrl,
+               .ctrlbit        = (1 << 8),
+       }, {
+               .name           = "SYSMMU_FIMC2",
+               .id             = -1,
+               .enable         = exynos4_clk_ip_cam_ctrl,
+               .ctrlbit        = (1 << 9),
+       }, {
+               .name           = "SYSMMU_FIMC3",
+               .id             = -1,
+               .enable         = exynos4_clk_ip_cam_ctrl,
+               .ctrlbit        = (1 << 10),
+       }, {
+               .name           = "SYSMMU_JPEG",
+               .id             = -1,
+               .enable         = exynos4_clk_ip_cam_ctrl,
+               .ctrlbit        = (1 << 11),
+       }, {
+               .name           = "SYSMMU_FIMD0",
+               .id             = -1,
+               .enable         = exynos4_clk_ip_lcd0_ctrl,
+               .ctrlbit        = (1 << 4),
+       }, {
+               .name           = "SYSMMU_FIMD1",
+               .id             = -1,
+               .enable         = exynos4_clk_ip_lcd1_ctrl,
+               .ctrlbit        = (1 << 4),
+       }, {
+               .name           = "SYSMMU_PCIe",
+               .id             = -1,
+               .enable         = exynos4_clk_ip_fsys_ctrl,
+               .ctrlbit        = (1 << 18),
+       }, {
+               .name           = "SYSMMU_G2D",
+               .id             = -1,
+               .enable         = exynos4_clk_ip_image_ctrl,
+               .ctrlbit        = (1 << 3),
+       }, {
+               .name           = "SYSMMU_ROTATOR",
+               .id             = -1,
+               .enable         = exynos4_clk_ip_image_ctrl,
+               .ctrlbit        = (1 << 4),
+       }, {
+               .name           = "SYSMMU_TV",
+               .id             = -1,
+               .enable         = exynos4_clk_ip_tv_ctrl,
+               .ctrlbit        = (1 << 4),
+       }, {
+               .name           = "SYSMMU_MFC_L",
+               .id             = -1,
+               .enable         = exynos4_clk_ip_mfc_ctrl,
+               .ctrlbit        = (1 << 1),
+       }, {
+               .name           = "SYSMMU_MFC_R",
+               .id             = -1,
+               .enable         = exynos4_clk_ip_mfc_ctrl,
+               .ctrlbit        = (1 << 2),
+       }
 };
 
 static struct clk init_clocks[] = {
index 6889c9a..3b7cae0 100644 (file)
@@ -208,3 +208,25 @@ struct platform_device exynos4_device_sysmmu = {
        .resource       = exynos4_sysmmu_resource,
 };
 EXPORT_SYMBOL(exynos4_device_sysmmu);
+
+static struct clk *sysmmu_clk[S5P_SYSMMU_TOTAL_IPNUM];
+void sysmmu_clk_init(struct device *dev, sysmmu_ips ips)
+{
+       sysmmu_clk[ips] = clk_get(dev, sysmmu_ips_name[ips]);
+       if (IS_ERR(sysmmu_clk[ips]))
+               sysmmu_clk[ips] = NULL;
+       else
+               clk_put(sysmmu_clk[ips]);
+}
+
+void sysmmu_clk_enable(sysmmu_ips ips)
+{
+       if (sysmmu_clk[ips])
+               clk_enable(sysmmu_clk[ips]);
+}
+
+void sysmmu_clk_disable(sysmmu_ips ips)
+{
+       if (sysmmu_clk[ips])
+               clk_disable(sysmmu_clk[ips]);
+}
index c91f930..6e311c1 100644 (file)
 
 #define S5P_CLKDIV_LEFTBUS             S5P_CLKREG(0x04500)
 #define S5P_CLKDIV_STAT_LEFTBUS                S5P_CLKREG(0x04600)
-#define S5P_CLKGATE_IP_LEFTBUS          S5P_CLKREG(0x04800)
+#define S5P_CLKGATE_IP_LEFTBUS         S5P_CLKREG(0x04800)
 
 #define S5P_CLKDIV_RIGHTBUS            S5P_CLKREG(0x08500)
 #define S5P_CLKDIV_STAT_RIGHTBUS       S5P_CLKREG(0x08600)
-#define S5P_CLKGATE_IP_RIGHTBUS         S5P_CLKREG(0x08800)
+#define S5P_CLKGATE_IP_RIGHTBUS                S5P_CLKREG(0x08800)
 
 #define S5P_EPLL_CON0                  S5P_CLKREG(0x0C110)
 #define S5P_EPLL_CON1                  S5P_CLKREG(0x0C114)
@@ -76,7 +76,7 @@
 
 #define S5P_CLKGATE_SCLKCAM            S5P_CLKREG(0x0C820)
 #define S5P_CLKGATE_IP_CAM             S5P_CLKREG(0x0C920)
-#define S5P_CLKGATE_IP_TV              S5P_CLKREG(0x0C924)
+#define S5P_CLKGATE_IP_TV              S5P_CLKREG(0x0C924)
 #define S5P_CLKGATE_IP_MFC             S5P_CLKREG(0x0C928)
 #define S5P_CLKGATE_IP_G3D             S5P_CLKREG(0x0C92C)
 #define S5P_CLKGATE_IP_IMAGE           S5P_CLKREG(0x0C930)
 #define S5P_CLKGATE_SCLKCPU            S5P_CLKREG(0x14800)
 #define S5P_CLKGATE_IP_CPU             S5P_CLKREG(0x14900)
 
-/* APLL_LOCK */
 #define S5P_APLL_LOCKTIME              (0x1C20)        /* 300us */
 
-/* APLL_CON0 */
 #define S5P_APLLCON0_ENABLE_SHIFT      (31)
 #define S5P_APLLCON0_LOCKED_SHIFT      (29)
 #define S5P_APLL_VAL_1000              ((250 << 16) | (6 << 8) | 1)
 #define S5P_APLL_VAL_800               ((200 << 16) | (6 << 8) | 1)
 
-/* CLK_SRC_CPU */
 #define S5P_CLKSRC_CPU_MUXCORE_SHIFT   (16)
 #define S5P_CLKMUX_STATCPU_MUXCORE_MASK        (0x7 << S5P_CLKSRC_CPU_MUXCORE_SHIFT)
 
-/* CLKDIV_CPU0 */
 #define S5P_CLKDIV_CPU0_CORE_SHIFT     (0)
 #define S5P_CLKDIV_CPU0_CORE_MASK      (0x7 << S5P_CLKDIV_CPU0_CORE_SHIFT)
 #define S5P_CLKDIV_CPU0_COREM0_SHIFT   (4)
 #define S5P_CLKDIV_CPU0_APLL_SHIFT     (24)
 #define S5P_CLKDIV_CPU0_APLL_MASK      (0x7 << S5P_CLKDIV_CPU0_APLL_SHIFT)
 
-/* CLKDIV_DMC0 */
 #define S5P_CLKDIV_DMC0_ACP_SHIFT      (0)
 #define S5P_CLKDIV_DMC0_ACP_MASK       (0x7 << S5P_CLKDIV_DMC0_ACP_SHIFT)
 #define S5P_CLKDIV_DMC0_ACPPCLK_SHIFT  (4)
 #define S5P_CLKDIV_DMC0_CORETI_SHIFT   (28)
 #define S5P_CLKDIV_DMC0_CORETI_MASK    (0x7 << S5P_CLKDIV_DMC0_CORETI_SHIFT)
 
-/* CLKDIV_TOP */
 #define S5P_CLKDIV_TOP_ACLK200_SHIFT   (0)
 #define S5P_CLKDIV_TOP_ACLK200_MASK    (0x7 << S5P_CLKDIV_TOP_ACLK200_SHIFT)
 #define S5P_CLKDIV_TOP_ACLK100_SHIFT   (4)
 #define S5P_CLKDIV_TOP_ONENAND_SHIFT   (16)
 #define S5P_CLKDIV_TOP_ONENAND_MASK    (0x7 << S5P_CLKDIV_TOP_ONENAND_SHIFT)
 
-/* CLKDIV_LEFTBUS / CLKDIV_RIGHTBUS*/
 #define S5P_CLKDIV_BUS_GDLR_SHIFT      (0)
 #define S5P_CLKDIV_BUS_GDLR_MASK       (0x7 << S5P_CLKDIV_BUS_GDLR_SHIFT)
 #define S5P_CLKDIV_BUS_GPLR_SHIFT      (4)
index eff3dc3..6a5fbb5 100644 (file)
@@ -39,4 +39,8 @@ extern const char *sysmmu_ips_name[EXYNOS4_SYSMMU_TOTAL_IPNUM];
 
 typedef enum exynos4_sysmmu_ips sysmmu_ips;
 
+void sysmmu_clk_init(struct device *dev, sysmmu_ips ips);
+void sysmmu_clk_enable(sysmmu_ips ips);
+void sysmmu_clk_disable(sysmmu_ips ips);
+
 #endif /* __ASM_ARM_ARCH_SYSMMU_H */
index 89e024f..54f5edd 100644 (file)
@@ -174,6 +174,8 @@ void s5p_sysmmu_set_tablebase_pgd(sysmmu_ips ips, unsigned long pgd)
 void s5p_sysmmu_enable(sysmmu_ips ips, unsigned long pgd)
 {
        if (!is_sysmmu_active(ips)) {
+               sysmmu_clk_enable(ips);
+
                __sysmmu_set_ptbase(ips, pgd);
 
                __raw_writel(CTRL_ENABLE, sysmmusfrs[ips] + S5P_MMU_CTRL);
@@ -190,6 +192,7 @@ void s5p_sysmmu_disable(sysmmu_ips ips)
        if (is_sysmmu_active(ips)) {
                __raw_writel(CTRL_DISABLE, sysmmusfrs[ips] + S5P_MMU_CTRL);
                set_sysmmu_inactive(ips);
+               sysmmu_clk_disable(ips);
                dev_dbg(dev, "%s is disabled.\n", sysmmu_ips_name[ips]);
        } else {
                dev_dbg(dev, "%s is already disabled.\n", sysmmu_ips_name[ips]);
@@ -218,6 +221,9 @@ static int s5p_sysmmu_probe(struct platform_device *pdev)
        for (i = 0; i < S5P_SYSMMU_TOTAL_IPNUM; i++) {
                int irq;
 
+               sysmmu_clk_init(dev, i);
+               sysmmu_clk_disable(i);
+
                res = platform_get_resource(pdev, IORESOURCE_MEM, i);
                if (!res) {
                        dev_err(dev, "Failed to get the resource of %s.\n",