ARM: EXYNOS4: Implement Clock gating for System MMU

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>
This commit is contained in:
KyongHo Cho 2011-03-07 09:10:24 +09:00 committed by Kukjin Kim
parent b34f003f27
commit b0b6ff0b21
5 changed files with 117 additions and 11 deletions

View 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[] = {

View 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]);
}

View File

@ -19,11 +19,11 @@
#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)
@ -113,20 +113,16 @@
#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)
@ -142,7 +138,6 @@
#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)
@ -160,7 +155,6 @@
#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)
@ -172,7 +166,6 @@
#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)

View 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 */

View 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",