Commit eedd52e3 authored by Arnd Bergmann's avatar Arnd Bergmann

Merge branch 'exynos/sysmmu' into next/cleanup2

Required as a depdency for the next/cleanup-plat-s3c24xx-s5p branch
Signed-off-by: default avatarArnd Bergmann <arnd@arndb.de>
parents 030caf3f bca10b90
...@@ -85,10 +85,10 @@ config EXYNOS4_SETUP_FIMD0 ...@@ -85,10 +85,10 @@ config EXYNOS4_SETUP_FIMD0
help help
Common setup code for FIMD0. Common setup code for FIMD0.
config EXYNOS4_DEV_SYSMMU config EXYNOS_DEV_SYSMMU
bool bool
help help
Common setup code for SYSTEM MMU in EXYNOS4 Common setup code for SYSTEM MMU in EXYNOS platforms
config EXYNOS4_DEV_DWMCI config EXYNOS4_DEV_DWMCI
bool bool
...@@ -200,12 +200,12 @@ config MACH_SMDKV310 ...@@ -200,12 +200,12 @@ config MACH_SMDKV310
select S3C_DEV_HSMMC2 select S3C_DEV_HSMMC2
select S3C_DEV_HSMMC3 select S3C_DEV_HSMMC3
select SAMSUNG_DEV_BACKLIGHT select SAMSUNG_DEV_BACKLIGHT
select EXYNOS_DEV_SYSMMU
select EXYNOS4_DEV_AHCI select EXYNOS4_DEV_AHCI
select SAMSUNG_DEV_KEYPAD select SAMSUNG_DEV_KEYPAD
select EXYNOS4_DEV_DMA select EXYNOS4_DEV_DMA
select SAMSUNG_DEV_PWM select SAMSUNG_DEV_PWM
select EXYNOS4_DEV_USB_OHCI select EXYNOS4_DEV_USB_OHCI
select EXYNOS4_DEV_SYSMMU
select EXYNOS4_SETUP_FIMD0 select EXYNOS4_SETUP_FIMD0
select EXYNOS4_SETUP_I2C1 select EXYNOS4_SETUP_I2C1
select EXYNOS4_SETUP_KEYPAD select EXYNOS4_SETUP_KEYPAD
...@@ -224,7 +224,6 @@ config MACH_ARMLEX4210 ...@@ -224,7 +224,6 @@ config MACH_ARMLEX4210
select S3C_DEV_HSMMC3 select S3C_DEV_HSMMC3
select EXYNOS4_DEV_AHCI select EXYNOS4_DEV_AHCI
select EXYNOS4_DEV_DMA select EXYNOS4_DEV_DMA
select EXYNOS4_DEV_SYSMMU
select EXYNOS4_SETUP_SDHCI select EXYNOS4_SETUP_SDHCI
help help
Machine support for Samsung ARMLEX4210 based on EXYNOS4210 Machine support for Samsung ARMLEX4210 based on EXYNOS4210
...@@ -251,6 +250,7 @@ config MACH_UNIVERSAL_C210 ...@@ -251,6 +250,7 @@ config MACH_UNIVERSAL_C210
select S5P_DEV_MFC select S5P_DEV_MFC
select S5P_DEV_ONENAND select S5P_DEV_ONENAND
select S5P_DEV_TV select S5P_DEV_TV
select EXYNOS_DEV_SYSMMU
select EXYNOS4_DEV_DMA select EXYNOS4_DEV_DMA
select EXYNOS4_SETUP_FIMD0 select EXYNOS4_SETUP_FIMD0
select EXYNOS4_SETUP_I2C1 select EXYNOS4_SETUP_I2C1
...@@ -322,6 +322,7 @@ config MACH_ORIGEN ...@@ -322,6 +322,7 @@ config MACH_ORIGEN
select S5P_DEV_USB_EHCI select S5P_DEV_USB_EHCI
select SAMSUNG_DEV_BACKLIGHT select SAMSUNG_DEV_BACKLIGHT
select SAMSUNG_DEV_PWM select SAMSUNG_DEV_PWM
select EXYNOS_DEV_SYSMMU
select EXYNOS4_DEV_DMA select EXYNOS4_DEV_DMA
select EXYNOS4_DEV_USB_OHCI select EXYNOS4_DEV_USB_OHCI
select EXYNOS4_SETUP_FIMD0 select EXYNOS4_SETUP_FIMD0
...@@ -345,6 +346,7 @@ config MACH_SMDK4212 ...@@ -345,6 +346,7 @@ config MACH_SMDK4212
select SAMSUNG_DEV_BACKLIGHT select SAMSUNG_DEV_BACKLIGHT
select SAMSUNG_DEV_KEYPAD select SAMSUNG_DEV_KEYPAD
select SAMSUNG_DEV_PWM select SAMSUNG_DEV_PWM
select EXYNOS_DEV_SYSMMU
select EXYNOS4_DEV_DMA select EXYNOS4_DEV_DMA
select EXYNOS4_SETUP_I2C1 select EXYNOS4_SETUP_I2C1
select EXYNOS4_SETUP_I2C3 select EXYNOS4_SETUP_I2C3
......
...@@ -50,7 +50,7 @@ obj-$(CONFIG_MACH_EXYNOS5_DT) += mach-exynos5-dt.o ...@@ -50,7 +50,7 @@ obj-$(CONFIG_MACH_EXYNOS5_DT) += mach-exynos5-dt.o
obj-y += dev-uart.o obj-y += dev-uart.o
obj-$(CONFIG_ARCH_EXYNOS4) += dev-audio.o obj-$(CONFIG_ARCH_EXYNOS4) += dev-audio.o
obj-$(CONFIG_EXYNOS4_DEV_AHCI) += dev-ahci.o obj-$(CONFIG_EXYNOS4_DEV_AHCI) += dev-ahci.o
obj-$(CONFIG_EXYNOS4_DEV_SYSMMU) += dev-sysmmu.o obj-$(CONFIG_EXYNOS_DEV_SYSMMU) += dev-sysmmu.o
obj-$(CONFIG_EXYNOS4_DEV_DWMCI) += dev-dwmci.o obj-$(CONFIG_EXYNOS4_DEV_DWMCI) += dev-dwmci.o
obj-$(CONFIG_EXYNOS4_DEV_DMA) += dma.o obj-$(CONFIG_EXYNOS4_DEV_DMA) += dma.o
obj-$(CONFIG_EXYNOS4_DEV_USB_OHCI) += dev-ohci.o obj-$(CONFIG_EXYNOS4_DEV_USB_OHCI) += dev-ohci.o
......
...@@ -168,7 +168,7 @@ static int exynos4_clk_ip_tv_ctrl(struct clk *clk, int enable) ...@@ -168,7 +168,7 @@ static int exynos4_clk_ip_tv_ctrl(struct clk *clk, int enable)
return s5p_gatectrl(EXYNOS4_CLKGATE_IP_TV, clk, enable); return s5p_gatectrl(EXYNOS4_CLKGATE_IP_TV, clk, enable);
} }
static int exynos4_clk_ip_image_ctrl(struct clk *clk, int enable) int exynos4_clk_ip_image_ctrl(struct clk *clk, int enable)
{ {
return s5p_gatectrl(EXYNOS4_CLKGATE_IP_IMAGE, clk, enable); return s5p_gatectrl(EXYNOS4_CLKGATE_IP_IMAGE, clk, enable);
} }
...@@ -198,6 +198,11 @@ static int exynos4_clk_ip_perir_ctrl(struct clk *clk, int enable) ...@@ -198,6 +198,11 @@ static int exynos4_clk_ip_perir_ctrl(struct clk *clk, int enable)
return s5p_gatectrl(EXYNOS4_CLKGATE_IP_PERIR, clk, enable); return s5p_gatectrl(EXYNOS4_CLKGATE_IP_PERIR, clk, enable);
} }
int exynos4_clk_ip_dmc_ctrl(struct clk *clk, int enable)
{
return s5p_gatectrl(EXYNOS4_CLKGATE_IP_DMC, clk, enable);
}
static int exynos4_clk_hdmiphy_ctrl(struct clk *clk, int enable) static int exynos4_clk_hdmiphy_ctrl(struct clk *clk, int enable)
{ {
return s5p_gatectrl(S5P_HDMI_PHY_CONTROL, clk, enable); return s5p_gatectrl(S5P_HDMI_PHY_CONTROL, clk, enable);
...@@ -678,61 +683,55 @@ static struct clk exynos4_init_clocks_off[] = { ...@@ -678,61 +683,55 @@ static struct clk exynos4_init_clocks_off[] = {
.enable = exynos4_clk_ip_peril_ctrl, .enable = exynos4_clk_ip_peril_ctrl,
.ctrlbit = (1 << 14), .ctrlbit = (1 << 14),
}, { }, {
.name = "SYSMMU_MDMA", .name = SYSMMU_CLOCK_NAME,
.devname = SYSMMU_CLOCK_DEVNAME(mfc_l, 0),
.enable = exynos4_clk_ip_mfc_ctrl,
.ctrlbit = (1 << 1),
}, {
.name = SYSMMU_CLOCK_NAME,
.devname = SYSMMU_CLOCK_DEVNAME(mfc_r, 1),
.enable = exynos4_clk_ip_mfc_ctrl,
.ctrlbit = (1 << 2),
}, {
.name = SYSMMU_CLOCK_NAME,
.devname = SYSMMU_CLOCK_DEVNAME(tv, 2),
.enable = exynos4_clk_ip_tv_ctrl,
.ctrlbit = (1 << 4),
}, {
.name = SYSMMU_CLOCK_NAME,
.devname = SYSMMU_CLOCK_DEVNAME(jpeg, 3),
.enable = exynos4_clk_ip_cam_ctrl,
.ctrlbit = (1 << 11),
}, {
.name = SYSMMU_CLOCK_NAME,
.devname = SYSMMU_CLOCK_DEVNAME(rot, 4),
.enable = exynos4_clk_ip_image_ctrl, .enable = exynos4_clk_ip_image_ctrl,
.ctrlbit = (1 << 5), .ctrlbit = (1 << 4),
}, { }, {
.name = "SYSMMU_FIMC0", .name = SYSMMU_CLOCK_NAME,
.devname = SYSMMU_CLOCK_DEVNAME(fimc0, 5),
.enable = exynos4_clk_ip_cam_ctrl, .enable = exynos4_clk_ip_cam_ctrl,
.ctrlbit = (1 << 7), .ctrlbit = (1 << 7),
}, { }, {
.name = "SYSMMU_FIMC1", .name = SYSMMU_CLOCK_NAME,
.devname = SYSMMU_CLOCK_DEVNAME(fimc1, 6),
.enable = exynos4_clk_ip_cam_ctrl, .enable = exynos4_clk_ip_cam_ctrl,
.ctrlbit = (1 << 8), .ctrlbit = (1 << 8),
}, { }, {
.name = "SYSMMU_FIMC2", .name = SYSMMU_CLOCK_NAME,
.devname = SYSMMU_CLOCK_DEVNAME(fimc2, 7),
.enable = exynos4_clk_ip_cam_ctrl, .enable = exynos4_clk_ip_cam_ctrl,
.ctrlbit = (1 << 9), .ctrlbit = (1 << 9),
}, { }, {
.name = "SYSMMU_FIMC3", .name = SYSMMU_CLOCK_NAME,
.devname = SYSMMU_CLOCK_DEVNAME(fimc3, 8),
.enable = exynos4_clk_ip_cam_ctrl, .enable = exynos4_clk_ip_cam_ctrl,
.ctrlbit = (1 << 10), .ctrlbit = (1 << 10),
}, { }, {
.name = "SYSMMU_JPEG", .name = SYSMMU_CLOCK_NAME,
.enable = exynos4_clk_ip_cam_ctrl, .devname = SYSMMU_CLOCK_DEVNAME(fimd0, 10),
.ctrlbit = (1 << 11),
}, {
.name = "SYSMMU_FIMD0",
.enable = exynos4_clk_ip_lcd0_ctrl, .enable = exynos4_clk_ip_lcd0_ctrl,
.ctrlbit = (1 << 4), .ctrlbit = (1 << 4),
}, {
.name = "SYSMMU_FIMD1",
.enable = exynos4_clk_ip_lcd1_ctrl,
.ctrlbit = (1 << 4),
}, {
.name = "SYSMMU_PCIe",
.enable = exynos4_clk_ip_fsys_ctrl,
.ctrlbit = (1 << 18),
}, {
.name = "SYSMMU_G2D",
.enable = exynos4_clk_ip_image_ctrl,
.ctrlbit = (1 << 3),
}, {
.name = "SYSMMU_ROTATOR",
.enable = exynos4_clk_ip_image_ctrl,
.ctrlbit = (1 << 4),
}, {
.name = "SYSMMU_TV",
.enable = exynos4_clk_ip_tv_ctrl,
.ctrlbit = (1 << 4),
}, {
.name = "SYSMMU_MFC_L",
.enable = exynos4_clk_ip_mfc_ctrl,
.ctrlbit = (1 << 1),
}, {
.name = "SYSMMU_MFC_R",
.enable = exynos4_clk_ip_mfc_ctrl,
.ctrlbit = (1 << 2),
} }
}; };
......
...@@ -26,5 +26,7 @@ extern struct clk *exynos4_clkset_group_list[]; ...@@ -26,5 +26,7 @@ extern struct clk *exynos4_clkset_group_list[];
extern int exynos4_clksrc_mask_fsys_ctrl(struct clk *clk, int enable); extern int exynos4_clksrc_mask_fsys_ctrl(struct clk *clk, int enable);
extern int exynos4_clk_ip_fsys_ctrl(struct clk *clk, int enable); extern int exynos4_clk_ip_fsys_ctrl(struct clk *clk, int enable);
extern int exynos4_clk_ip_lcd1_ctrl(struct clk *clk, int enable); extern int exynos4_clk_ip_lcd1_ctrl(struct clk *clk, int enable);
extern int exynos4_clk_ip_image_ctrl(struct clk *clk, int enable);
extern int exynos4_clk_ip_dmc_ctrl(struct clk *clk, int enable);
#endif /* __ASM_ARCH_CLOCK_H */ #endif /* __ASM_ARCH_CLOCK_H */
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#include <mach/hardware.h> #include <mach/hardware.h>
#include <mach/map.h> #include <mach/map.h>
#include <mach/regs-clock.h> #include <mach/regs-clock.h>
#include <mach/sysmmu.h>
#include "common.h" #include "common.h"
#include "clock-exynos4.h" #include "clock-exynos4.h"
...@@ -94,6 +95,16 @@ static struct clk init_clocks_off[] = { ...@@ -94,6 +95,16 @@ static struct clk init_clocks_off[] = {
.devname = "exynos4-fb.1", .devname = "exynos4-fb.1",
.enable = exynos4_clk_ip_lcd1_ctrl, .enable = exynos4_clk_ip_lcd1_ctrl,
.ctrlbit = (1 << 0), .ctrlbit = (1 << 0),
}, {
.name = SYSMMU_CLOCK_NAME,
.devname = SYSMMU_CLOCK_DEVNAME(2d, 14),
.enable = exynos4_clk_ip_image_ctrl,
.ctrlbit = (1 << 3),
}, {
.name = SYSMMU_CLOCK_NAME,
.devname = SYSMMU_CLOCK_DEVNAME(fimd1, 11),
.enable = exynos4_clk_ip_lcd1_ctrl,
.ctrlbit = (1 << 4),
}, },
}; };
......
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#include <mach/hardware.h> #include <mach/hardware.h>
#include <mach/map.h> #include <mach/map.h>
#include <mach/regs-clock.h> #include <mach/regs-clock.h>
#include <mach/sysmmu.h>
#include "common.h" #include "common.h"
#include "clock-exynos4.h" #include "clock-exynos4.h"
...@@ -39,6 +40,16 @@ static struct sleep_save exynos4212_clock_save[] = { ...@@ -39,6 +40,16 @@ static struct sleep_save exynos4212_clock_save[] = {
}; };
#endif #endif
static int exynos4212_clk_ip_isp0_ctrl(struct clk *clk, int enable)
{
return s5p_gatectrl(EXYNOS4_CLKGATE_IP_ISP0, clk, enable);
}
static int exynos4212_clk_ip_isp1_ctrl(struct clk *clk, int enable)
{
return s5p_gatectrl(EXYNOS4_CLKGATE_IP_ISP1, clk, enable);
}
static struct clk *clk_src_mpll_user_list[] = { static struct clk *clk_src_mpll_user_list[] = {
[0] = &clk_fin_mpll, [0] = &clk_fin_mpll,
[1] = &exynos4_clk_mout_mpll.clk, [1] = &exynos4_clk_mout_mpll.clk,
...@@ -66,7 +77,22 @@ static struct clksrc_clk clksrcs[] = { ...@@ -66,7 +77,22 @@ static struct clksrc_clk clksrcs[] = {
}; };
static struct clk init_clocks_off[] = { static struct clk init_clocks_off[] = {
/* nothing here yet */ {
.name = SYSMMU_CLOCK_NAME,
.devname = SYSMMU_CLOCK_DEVNAME(2d, 14),
.enable = exynos4_clk_ip_dmc_ctrl,
.ctrlbit = (1 << 24),
}, {
.name = SYSMMU_CLOCK_NAME,
.devname = SYSMMU_CLOCK_DEVNAME(isp, 9),
.enable = exynos4212_clk_ip_isp0_ctrl,
.ctrlbit = (7 << 8),
}, {
.name = SYSMMU_CLOCK_NAME2,
.devname = SYSMMU_CLOCK_DEVNAME(isp, 9),
.enable = exynos4212_clk_ip_isp1_ctrl,
.ctrlbit = (1 << 4),
}
}; };
#ifdef CONFIG_PM_SLEEP #ifdef CONFIG_PM_SLEEP
......
...@@ -82,6 +82,11 @@ static int exynos5_clksrc_mask_peric0_ctrl(struct clk *clk, int enable) ...@@ -82,6 +82,11 @@ static int exynos5_clksrc_mask_peric0_ctrl(struct clk *clk, int enable)
return s5p_gatectrl(EXYNOS5_CLKSRC_MASK_PERIC0, clk, enable); return s5p_gatectrl(EXYNOS5_CLKSRC_MASK_PERIC0, clk, enable);
} }
static int exynos5_clk_ip_acp_ctrl(struct clk *clk, int enable)
{
return s5p_gatectrl(EXYNOS5_CLKGATE_IP_ACP, clk, enable);
}
static int exynos5_clk_ip_core_ctrl(struct clk *clk, int enable) static int exynos5_clk_ip_core_ctrl(struct clk *clk, int enable)
{ {
return s5p_gatectrl(EXYNOS5_CLKGATE_IP_CORE, clk, enable); return s5p_gatectrl(EXYNOS5_CLKGATE_IP_CORE, clk, enable);
...@@ -127,6 +132,21 @@ static int exynos5_clk_ip_peris_ctrl(struct clk *clk, int enable) ...@@ -127,6 +132,21 @@ static int exynos5_clk_ip_peris_ctrl(struct clk *clk, int enable)
return s5p_gatectrl(EXYNOS5_CLKGATE_IP_PERIS, clk, enable); return s5p_gatectrl(EXYNOS5_CLKGATE_IP_PERIS, clk, enable);
} }
static int exynos5_clk_ip_gscl_ctrl(struct clk *clk, int enable)
{
return s5p_gatectrl(EXYNOS5_CLKGATE_IP_GSCL, clk, enable);
}
static int exynos5_clk_ip_isp0_ctrl(struct clk *clk, int enable)
{
return s5p_gatectrl(EXYNOS5_CLKGATE_IP_ISP0, clk, enable);
}
static int exynos5_clk_ip_isp1_ctrl(struct clk *clk, int enable)
{
return s5p_gatectrl(EXYNOS5_CLKGATE_IP_ISP1, clk, enable);
}
/* Core list of CMU_CPU side */ /* Core list of CMU_CPU side */
static struct clksrc_clk exynos5_clk_mout_apll = { static struct clksrc_clk exynos5_clk_mout_apll = {
...@@ -630,6 +650,76 @@ static struct clk exynos5_init_clocks_off[] = { ...@@ -630,6 +650,76 @@ static struct clk exynos5_init_clocks_off[] = {
.parent = &exynos5_clk_aclk_66.clk, .parent = &exynos5_clk_aclk_66.clk,
.enable = exynos5_clk_ip_peric_ctrl, .enable = exynos5_clk_ip_peric_ctrl,
.ctrlbit = (1 << 14), .ctrlbit = (1 << 14),
}, {
.name = SYSMMU_CLOCK_NAME,
.devname = SYSMMU_CLOCK_DEVNAME(mfc_l, 0),
.enable = &exynos5_clk_ip_mfc_ctrl,
.ctrlbit = (1 << 1),
}, {
.name = SYSMMU_CLOCK_NAME,
.devname = SYSMMU_CLOCK_DEVNAME(mfc_r, 1),
.enable = &exynos5_clk_ip_mfc_ctrl,
.ctrlbit = (1 << 2),
}, {
.name = SYSMMU_CLOCK_NAME,
.devname = SYSMMU_CLOCK_DEVNAME(tv, 2),
.enable = &exynos5_clk_ip_disp1_ctrl,
.ctrlbit = (1 << 9)
}, {
.name = SYSMMU_CLOCK_NAME,
.devname = SYSMMU_CLOCK_DEVNAME(jpeg, 3),
.enable = &exynos5_clk_ip_gen_ctrl,
.ctrlbit = (1 << 7),
}, {
.name = SYSMMU_CLOCK_NAME,
.devname = SYSMMU_CLOCK_DEVNAME(rot, 4),
.enable = &exynos5_clk_ip_gen_ctrl,
.ctrlbit = (1 << 6)
}, {
.name = SYSMMU_CLOCK_NAME,
.devname = SYSMMU_CLOCK_DEVNAME(gsc0, 5),
.enable = &exynos5_clk_ip_gscl_ctrl,
.ctrlbit = (1 << 7),
}, {
.name = SYSMMU_CLOCK_NAME,
.devname = SYSMMU_CLOCK_DEVNAME(gsc1, 6),
.enable = &exynos5_clk_ip_gscl_ctrl,
.ctrlbit = (1 << 8),
}, {
.name = SYSMMU_CLOCK_NAME,
.devname = SYSMMU_CLOCK_DEVNAME(gsc2, 7),
.enable = &exynos5_clk_ip_gscl_ctrl,
.ctrlbit = (1 << 9),
}, {
.name = SYSMMU_CLOCK_NAME,
.devname = SYSMMU_CLOCK_DEVNAME(gsc3, 8),
.enable = &exynos5_clk_ip_gscl_ctrl,
.ctrlbit = (1 << 10),
}, {
.name = SYSMMU_CLOCK_NAME,
.devname = SYSMMU_CLOCK_DEVNAME(isp, 9),
.enable = &exynos5_clk_ip_isp0_ctrl,
.ctrlbit = (0x3F << 8),
}, {
.name = SYSMMU_CLOCK_NAME2,
.devname = SYSMMU_CLOCK_DEVNAME(isp, 9),
.enable = &exynos5_clk_ip_isp1_ctrl,
.ctrlbit = (0xF << 4),
}, {
.name = SYSMMU_CLOCK_NAME,
.devname = SYSMMU_CLOCK_DEVNAME(camif0, 12),
.enable = &exynos5_clk_ip_gscl_ctrl,
.ctrlbit = (1 << 11),
}, {
.name = SYSMMU_CLOCK_NAME,
.devname = SYSMMU_CLOCK_DEVNAME(camif1, 13),
.enable = &exynos5_clk_ip_gscl_ctrl,
.ctrlbit = (1 << 12),
}, {
.name = SYSMMU_CLOCK_NAME,
.devname = SYSMMU_CLOCK_DEVNAME(2d, 14),
.enable = &exynos5_clk_ip_acp_ctrl,
.ctrlbit = (1 << 7)
} }
}; };
......
/* linux/arch/arm/mach-exynos4/dev-sysmmu.c /* linux/arch/arm/mach-exynos/dev-sysmmu.c
* *
* Copyright (c) 2010 Samsung Electronics Co., Ltd. * Copyright (c) 2010-2012 Samsung Electronics Co., Ltd.
* http://www.samsung.com * http://www.samsung.com
* *
* EXYNOS4 - System MMU support * EXYNOS - System MMU support
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License version 2 as
...@@ -12,222 +12,263 @@ ...@@ -12,222 +12,263 @@
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/dma-mapping.h> #include <linux/dma-mapping.h>
#include <linux/export.h>
#include <plat/cpu.h>
#include <mach/map.h> #include <mach/map.h>
#include <mach/irqs.h> #include <mach/irqs.h>
#include <mach/sysmmu.h> #include <mach/sysmmu.h>
#include <plat/s5p-clock.h>
/* These names must be equal to the clock names in mach-exynos4/clock.c */
const char *sysmmu_ips_name[EXYNOS4_SYSMMU_TOTAL_IPNUM] = {
"SYSMMU_MDMA" ,
"SYSMMU_SSS" ,
"SYSMMU_FIMC0" ,
"SYSMMU_FIMC1" ,
"SYSMMU_FIMC2" ,
"SYSMMU_FIMC3" ,
"SYSMMU_JPEG" ,
"SYSMMU_FIMD0" ,
"SYSMMU_FIMD1" ,
"SYSMMU_PCIe" ,
"SYSMMU_G2D" ,
"SYSMMU_ROTATOR",
"SYSMMU_MDMA2" ,
"SYSMMU_TV" ,
"SYSMMU_MFC_L" ,
"SYSMMU_MFC_R" ,
};
static struct resource exynos4_sysmmu_resource[] = { static u64 exynos_sysmmu_dma_mask = DMA_BIT_MASK(32);
[0] = {
.start = EXYNOS4_PA_SYSMMU_MDMA, #define SYSMMU_PLATFORM_DEVICE(ipname, devid) \
.end = EXYNOS4_PA_SYSMMU_MDMA + SZ_64K - 1, static struct sysmmu_platform_data platdata_##ipname = { \
.flags = IORESOURCE_MEM, .dbgname = #ipname, \
}, }; \
[1] = { struct platform_device SYSMMU_PLATDEV(ipname) = \
.start = IRQ_SYSMMU_MDMA0_0, { \
.end = IRQ_SYSMMU_MDMA0_0, .name = SYSMMU_DEVNAME_BASE, \
.flags = IORESOURCE_IRQ, .id = devid, \
}, .dev = { \
[2] = { .dma_mask = &exynos_sysmmu_dma_mask, \
.start = EXYNOS4_PA_SYSMMU_SSS, .coherent_dma_mask = DMA_BIT_MASK(32), \
.end = EXYNOS4_PA_SYSMMU_SSS + SZ_64K - 1, .platform_data = &platdata_##ipname, \
.flags = IORESOURCE_MEM, }, \
}, }
[3] = {
.start = IRQ_SYSMMU_SSS_0, SYSMMU_PLATFORM_DEVICE(mfc_l, 0);
.end = IRQ_SYSMMU_SSS_0, SYSMMU_PLATFORM_DEVICE(mfc_r, 1);
.flags = IORESOURCE_IRQ, SYSMMU_PLATFORM_DEVICE(tv, 2);
}, SYSMMU_PLATFORM_DEVICE(jpeg, 3);
[4] = { SYSMMU_PLATFORM_DEVICE(rot, 4);
.start = EXYNOS4_PA_SYSMMU_FIMC0, SYSMMU_PLATFORM_DEVICE(fimc0, 5); /* fimc* and gsc* exist exclusively */
.end = EXYNOS4_PA_SYSMMU_FIMC0 + SZ_64K - 1, SYSMMU_PLATFORM_DEVICE(fimc1, 6);
.flags = IORESOURCE_MEM, SYSMMU_PLATFORM_DEVICE(fimc2, 7);
}, SYSMMU_PLATFORM_DEVICE(fimc3, 8);
[5] = { SYSMMU_PLATFORM_DEVICE(gsc0, 5);
.start = IRQ_SYSMMU_FIMC0_0, SYSMMU_PLATFORM_DEVICE(gsc1, 6);
.end = IRQ_SYSMMU_FIMC0_0, SYSMMU_PLATFORM_DEVICE(gsc2, 7);
.flags = IORESOURCE_IRQ, SYSMMU_PLATFORM_DEVICE(gsc3, 8);
}, SYSMMU_PLATFORM_DEVICE(isp, 9);
[6] = { SYSMMU_PLATFORM_DEVICE(fimd0, 10);
.start = EXYNOS4_PA_SYSMMU_FIMC1, SYSMMU_PLATFORM_DEVICE(fimd1, 11);
.end = EXYNOS4_PA_SYSMMU_FIMC1 + SZ_64K - 1, SYSMMU_PLATFORM_DEVICE(camif0, 12);
.flags = IORESOURCE_MEM, SYSMMU_PLATFORM_DEVICE(camif1, 13);
}, SYSMMU_PLATFORM_DEVICE(2d, 14);
[7] = {
.start = IRQ_SYSMMU_FIMC1_0, #define SYSMMU_RESOURCE_NAME(core, ipname) sysmmures_##core##_##ipname
.end = IRQ_SYSMMU_FIMC1_0,
.flags = IORESOURCE_IRQ, #define SYSMMU_RESOURCE(core, ipname) \
}, static struct resource SYSMMU_RESOURCE_NAME(core, ipname)[] __initdata =
[8] = {
.start = EXYNOS4_PA_SYSMMU_FIMC2, #define DEFINE_SYSMMU_RESOURCE(core, mem, irq) \
.end = EXYNOS4_PA_SYSMMU_FIMC2 + SZ_64K - 1, DEFINE_RES_MEM_NAMED(core##_PA_SYSMMU_##mem, SZ_4K, #mem), \
.flags = IORESOURCE_MEM, DEFINE_RES_IRQ_NAMED(core##_IRQ_SYSMMU_##irq##_0, #mem)
},
[9] = { #define SYSMMU_RESOURCE_DEFINE(core, ipname, mem, irq) \
.start = IRQ_SYSMMU_FIMC2_0, SYSMMU_RESOURCE(core, ipname) { \
.end = IRQ_SYSMMU_FIMC2_0, DEFINE_SYSMMU_RESOURCE(core, mem, irq) \
.flags = IORESOURCE_IRQ, }
},
[10] = {
.start = EXYNOS4_PA_SYSMMU_FIMC3,
.end = EXYNOS4_PA_SYSMMU_FIMC3 + SZ_64K - 1,
.flags = IORESOURCE_MEM,
},
[11] = {
.start = IRQ_SYSMMU_FIMC3_0,
.end = IRQ_SYSMMU_FIMC3_0,
.flags = IORESOURCE_IRQ,
},
[12] = {
.start = EXYNOS4_PA_SYSMMU_JPEG,
.end = EXYNOS4_PA_SYSMMU_JPEG + SZ_64K - 1,
.flags = IORESOURCE_MEM,
},
[13] = {
.start = IRQ_SYSMMU_JPEG_0,
.end = IRQ_SYSMMU_JPEG_0,
.flags = IORESOURCE_IRQ,
},
[14] = {
.start = EXYNOS4_PA_SYSMMU_FIMD0,
.end = EXYNOS4_PA_SYSMMU_FIMD0 + SZ_64K - 1,
.flags = IORESOURCE_MEM,
},
[15] = {
.start = IRQ_SYSMMU_LCD0_M0_0,
.end = IRQ_SYSMMU_LCD0_M0_0,
.flags = IORESOURCE_IRQ,
},
[16] = {
.start = EXYNOS4_PA_SYSMMU_FIMD1,
.end = EXYNOS4_PA_SYSMMU_FIMD1 + SZ_64K - 1,
.flags = IORESOURCE_MEM,
},
[17] = {
.start = IRQ_SYSMMU_LCD1_M1_0,
.end = IRQ_SYSMMU_LCD1_M1_0,
.flags = IORESOURCE_IRQ,
},
[18] = {
.start = EXYNOS4_PA_SYSMMU_PCIe,
.end = EXYNOS4_PA_SYSMMU_PCIe + SZ_64K - 1,
.flags = IORESOURCE_MEM,
},
[19] = {
.start = IRQ_SYSMMU_PCIE_0,
.end = IRQ_SYSMMU_PCIE_0,
.flags = IORESOURCE_IRQ,
},
[20] = {
.start = EXYNOS4_PA_SYSMMU_G2D,
.end = EXYNOS4_PA_SYSMMU_G2D + SZ_64K - 1,
.flags = IORESOURCE_MEM,
},
[21] = {
.start = IRQ_SYSMMU_2D_0,
.end = IRQ_SYSMMU_2D_0,
.flags = IORESOURCE_IRQ,
},
[22] = {
.start = EXYNOS4_PA_SYSMMU_ROTATOR,
.end = EXYNOS4_PA_SYSMMU_ROTATOR + SZ_64K - 1,
.flags = IORESOURCE_MEM,
},
[23] = {
.start = IRQ_SYSMMU_ROTATOR_0,
.end = IRQ_SYSMMU_ROTATOR_0,
.flags = IORESOURCE_IRQ,
},
[24] = {
.start = EXYNOS4_PA_SYSMMU_MDMA2,
.end = EXYNOS4_PA_SYSMMU_MDMA2 + SZ_64K - 1,
.flags = IORESOURCE_MEM,
},
[25] = {
.start = IRQ_SYSMMU_MDMA1_0,
.end = IRQ_SYSMMU_MDMA1_0,
.flags = IORESOURCE_IRQ,
},
[26] = {
.start = EXYNOS4_PA_SYSMMU_TV,
.end = EXYNOS4_PA_SYSMMU_TV + SZ_64K - 1,
.flags = IORESOURCE_MEM,
},
[27] = {
.start = IRQ_SYSMMU_TV_M0_0,
.end = IRQ_SYSMMU_TV_M0_0,
.flags = IORESOURCE_IRQ,
},
[28] = {
.start = EXYNOS4_PA_SYSMMU_MFC_L,
.end = EXYNOS4_PA_SYSMMU_MFC_L + SZ_64K - 1,
.flags = IORESOURCE_MEM,
},
[29] = {
.start = IRQ_SYSMMU_MFC_M0_0,
.end = IRQ_SYSMMU_MFC_M0_0,
.flags = IORESOURCE_IRQ,
},
[30] = {
.start = EXYNOS4_PA_SYSMMU_MFC_R,
.end = EXYNOS4_PA_SYSMMU_MFC_R + SZ_64K - 1,
.flags = IORESOURCE_MEM,
},
[31] = {
.start = IRQ_SYSMMU_MFC_M1_0,
.end = IRQ_SYSMMU_MFC_M1_0,
.flags = IORESOURCE_IRQ,
},
};
struct platform_device exynos4_device_sysmmu = { struct sysmmu_resource_map {
.name = "s5p-sysmmu", struct platform_device *pdev;
.id = 32, struct resource *res;
.num_resources = ARRAY_SIZE(exynos4_sysmmu_resource), u32 rnum;
.resource = exynos4_sysmmu_resource, struct device *pdd;
char *clocknames;
}; };
EXPORT_SYMBOL(exynos4_device_sysmmu);
static struct clk *sysmmu_clk[S5P_SYSMMU_TOTAL_IPNUM]; #define SYSMMU_RESOURCE_MAPPING(core, ipname, resname) { \
void sysmmu_clk_init(struct device *dev, sysmmu_ips ips) .pdev = &SYSMMU_PLATDEV(ipname), \
{ .res = SYSMMU_RESOURCE_NAME(EXYNOS##core, resname), \
sysmmu_clk[ips] = clk_get(dev, sysmmu_ips_name[ips]); .rnum = ARRAY_SIZE(SYSMMU_RESOURCE_NAME(EXYNOS##core, resname)),\
if (IS_ERR(sysmmu_clk[ips])) .clocknames = SYSMMU_CLOCK_NAME, \
sysmmu_clk[ips] = NULL;
else
clk_put(sysmmu_clk[ips]);
} }
void sysmmu_clk_enable(sysmmu_ips ips) #define SYSMMU_RESOURCE_MAPPING_MC(core, ipname, resname, pdata) { \
{ .pdev = &SYSMMU_PLATDEV(ipname), \
if (sysmmu_clk[ips]) .res = SYSMMU_RESOURCE_NAME(EXYNOS##core, resname), \
clk_enable(sysmmu_clk[ips]); .rnum = ARRAY_SIZE(SYSMMU_RESOURCE_NAME(EXYNOS##core, resname)),\
.clocknames = SYSMMU_CLOCK_NAME "," SYSMMU_CLOCK_NAME2, \
}
#ifdef CONFIG_EXYNOS_DEV_PD
#define SYSMMU_RESOURCE_MAPPING_PD(core, ipname, resname, pd) { \
.pdev = &SYSMMU_PLATDEV(ipname), \
.res = &SYSMMU_RESOURCE_NAME(EXYNOS##core, resname), \
.rnum = ARRAY_SIZE(SYSMMU_RESOURCE_NAME(EXYNOS##core, resname)),\
.clocknames = SYSMMU_CLOCK_NAME, \
.pdd = &exynos##core##_device_pd[pd].dev, \
}
#define SYSMMU_RESOURCE_MAPPING_MCPD(core, ipname, resname, pd, pdata) {\
.pdev = &SYSMMU_PLATDEV(ipname), \
.res = &SYSMMU_RESOURCE_NAME(EXYNOS##core, resname), \
.rnum = ARRAY_SIZE(SYSMMU_RESOURCE_NAME(EXYNOS##core, resname)),\
.clocknames = SYSMMU_CLOCK_NAME "," SYSMMU_CLOCK_NAME2, \
.pdd = &exynos##core##_device_pd[pd].dev, \
} }
#else
#define SYSMMU_RESOURCE_MAPPING_PD(core, ipname, resname, pd) \
SYSMMU_RESOURCE_MAPPING(core, ipname, resname)
#define SYSMMU_RESOURCE_MAPPING_MCPD(core, ipname, resname, pd, pdata) \
SYSMMU_RESOURCE_MAPPING_MC(core, ipname, resname, pdata)
#endif /* CONFIG_EXYNOS_DEV_PD */
#ifdef CONFIG_ARCH_EXYNOS4
SYSMMU_RESOURCE_DEFINE(EXYNOS4, fimc0, FIMC0, FIMC0);
SYSMMU_RESOURCE_DEFINE(EXYNOS4, fimc1, FIMC1, FIMC1);
SYSMMU_RESOURCE_DEFINE(EXYNOS4, fimc2, FIMC2, FIMC2);
SYSMMU_RESOURCE_DEFINE(EXYNOS4, fimc3, FIMC3, FIMC3);
SYSMMU_RESOURCE_DEFINE(EXYNOS4, jpeg, JPEG, JPEG);
SYSMMU_RESOURCE_DEFINE(EXYNOS4, 2d, G2D, 2D);
SYSMMU_RESOURCE_DEFINE(EXYNOS4, tv, TV, TV_M0);
SYSMMU_RESOURCE_DEFINE(EXYNOS4, 2d_acp, 2D_ACP, 2D);
SYSMMU_RESOURCE_DEFINE(EXYNOS4, rot, ROTATOR, ROTATOR);
SYSMMU_RESOURCE_DEFINE(EXYNOS4, fimd0, FIMD0, LCD0_M0);
SYSMMU_RESOURCE_DEFINE(EXYNOS4, fimd1, FIMD1, LCD1_M1);
SYSMMU_RESOURCE_DEFINE(EXYNOS4, flite0, FIMC_LITE0, FIMC_LITE0);
SYSMMU_RESOURCE_DEFINE(EXYNOS4, flite1, FIMC_LITE1, FIMC_LITE1);
SYSMMU_RESOURCE_DEFINE(EXYNOS4, mfc_r, MFC_R, MFC_M0);
SYSMMU_RESOURCE_DEFINE(EXYNOS4, mfc_l, MFC_L, MFC_M1);
SYSMMU_RESOURCE(EXYNOS4, isp) {
DEFINE_SYSMMU_RESOURCE(EXYNOS4, FIMC_ISP, FIMC_ISP),
DEFINE_SYSMMU_RESOURCE(EXYNOS4, FIMC_DRC, FIMC_DRC),
DEFINE_SYSMMU_RESOURCE(EXYNOS4, FIMC_FD, FIMC_FD),
DEFINE_SYSMMU_RESOURCE(EXYNOS4, ISPCPU, FIMC_CX),
};
static struct sysmmu_resource_map sysmmu_resmap4[] __initdata = {
SYSMMU_RESOURCE_MAPPING_PD(4, fimc0, fimc0, PD_CAM),
SYSMMU_RESOURCE_MAPPING_PD(4, fimc1, fimc1, PD_CAM),
SYSMMU_RESOURCE_MAPPING_PD(4, fimc2, fimc2, PD_CAM),
SYSMMU_RESOURCE_MAPPING_PD(4, fimc3, fimc3, PD_CAM),
SYSMMU_RESOURCE_MAPPING_PD(4, tv, tv, PD_TV),
SYSMMU_RESOURCE_MAPPING_PD(4, mfc_r, mfc_r, PD_MFC),
SYSMMU_RESOURCE_MAPPING_PD(4, mfc_l, mfc_l, PD_MFC),
SYSMMU_RESOURCE_MAPPING_PD(4, rot, rot, PD_LCD0),
SYSMMU_RESOURCE_MAPPING_PD(4, jpeg, jpeg, PD_CAM),
SYSMMU_RESOURCE_MAPPING_PD(4, fimd0, fimd0, PD_LCD0),
};
static struct sysmmu_resource_map sysmmu_resmap4210[] __initdata = {
SYSMMU_RESOURCE_MAPPING_PD(4, 2d, 2d, PD_LCD0),
SYSMMU_RESOURCE_MAPPING_PD(4, fimd1, fimd1, PD_LCD1),
};
static struct sysmmu_resource_map sysmmu_resmap4212[] __initdata = {
SYSMMU_RESOURCE_MAPPING(4, 2d, 2d_acp),
SYSMMU_RESOURCE_MAPPING_PD(4, camif0, flite0, PD_ISP),
SYSMMU_RESOURCE_MAPPING_PD(4, camif1, flite1, PD_ISP),
SYSMMU_RESOURCE_MAPPING_PD(4, isp, isp, PD_ISP),
};
#endif /* CONFIG_ARCH_EXYNOS4 */
void sysmmu_clk_disable(sysmmu_ips ips) #ifdef CONFIG_ARCH_EXYNOS5
SYSMMU_RESOURCE_DEFINE(EXYNOS5, jpeg, JPEG, JPEG);
SYSMMU_RESOURCE_DEFINE(EXYNOS5, fimd1, FIMD1, FIMD1);
SYSMMU_RESOURCE_DEFINE(EXYNOS5, 2d, 2D, 2D);
SYSMMU_RESOURCE_DEFINE(EXYNOS5, rot, ROTATOR, ROTATOR);
SYSMMU_RESOURCE_DEFINE(EXYNOS5, tv, TV, TV);
SYSMMU_RESOURCE_DEFINE(EXYNOS5, flite0, LITE0, LITE0);
SYSMMU_RESOURCE_DEFINE(EXYNOS5, flite1, LITE1, LITE1);
SYSMMU_RESOURCE_DEFINE(EXYNOS5, gsc0, GSC0, GSC0);
SYSMMU_RESOURCE_DEFINE(EXYNOS5, gsc1, GSC1, GSC1);
SYSMMU_RESOURCE_DEFINE(EXYNOS5, gsc2, GSC2, GSC2);
SYSMMU_RESOURCE_DEFINE(EXYNOS5, gsc3, GSC3, GSC3);
SYSMMU_RESOURCE_DEFINE(EXYNOS5, mfc_r, MFC_R, MFC_R);
SYSMMU_RESOURCE_DEFINE(EXYNOS5, mfc_l, MFC_L, MFC_L);
SYSMMU_RESOURCE(EXYNOS5, isp) {
DEFINE_SYSMMU_RESOURCE(EXYNOS5, ISP, ISP),
DEFINE_SYSMMU_RESOURCE(EXYNOS5, DRC, DRC),
DEFINE_SYSMMU_RESOURCE(EXYNOS5, FD, FD),
DEFINE_SYSMMU_RESOURCE(EXYNOS5, ISPCPU, MCUISP),
DEFINE_SYSMMU_RESOURCE(EXYNOS5, SCALERC, SCALERCISP),
DEFINE_SYSMMU_RESOURCE(EXYNOS5, SCALERP, SCALERPISP),
DEFINE_SYSMMU_RESOURCE(EXYNOS5, ODC, ODC),
DEFINE_SYSMMU_RESOURCE(EXYNOS5, DIS0, DIS0),
DEFINE_SYSMMU_RESOURCE(EXYNOS5, DIS1, DIS1),
DEFINE_SYSMMU_RESOURCE(EXYNOS5, 3DNR, 3DNR),
};
static struct sysmmu_resource_map sysmmu_resmap5[] __initdata = {
SYSMMU_RESOURCE_MAPPING(5, jpeg, jpeg),
SYSMMU_RESOURCE_MAPPING(5, fimd1, fimd1),
SYSMMU_RESOURCE_MAPPING(5, 2d, 2d),
SYSMMU_RESOURCE_MAPPING(5, rot, rot),
SYSMMU_RESOURCE_MAPPING_PD(5, tv, tv, PD_DISP1),
SYSMMU_RESOURCE_MAPPING_PD(5, camif0, flite0, PD_GSCL),
SYSMMU_RESOURCE_MAPPING_PD(5, camif1, flite1, PD_GSCL),
SYSMMU_RESOURCE_MAPPING_PD(5, gsc0, gsc0, PD_GSCL),
SYSMMU_RESOURCE_MAPPING_PD(5, gsc1, gsc1, PD_GSCL),
SYSMMU_RESOURCE_MAPPING_PD(5, gsc2, gsc2, PD_GSCL),
SYSMMU_RESOURCE_MAPPING_PD(5, gsc3, gsc3, PD_GSCL),
SYSMMU_RESOURCE_MAPPING_PD(5, mfc_r, mfc_r, PD_MFC),
SYSMMU_RESOURCE_MAPPING_PD(5, mfc_l, mfc_l, PD_MFC),
SYSMMU_RESOURCE_MAPPING_MCPD(5, isp, isp, PD_ISP, mc_platdata),
};
#endif /* CONFIG_ARCH_EXYNOS5 */
static int __init init_sysmmu_platform_device(void)
{ {
if (sysmmu_clk[ips]) int i, j;
clk_disable(sysmmu_clk[ips]); struct sysmmu_resource_map *resmap[2] = {NULL, NULL};
int nmap[2] = {0, 0};
#ifdef CONFIG_ARCH_EXYNOS5
if (soc_is_exynos5250()) {
resmap[0] = sysmmu_resmap5;
nmap[0] = ARRAY_SIZE(sysmmu_resmap5);
nmap[1] = 0;
}
#endif
#ifdef CONFIG_ARCH_EXYNOS4
if (resmap[0] == NULL) {
resmap[0] = sysmmu_resmap4;
nmap[0] = ARRAY_SIZE(sysmmu_resmap4);
}
if (soc_is_exynos4210()) {
resmap[1] = sysmmu_resmap4210;
nmap[1] = ARRAY_SIZE(sysmmu_resmap4210);
}
if (soc_is_exynos4412() || soc_is_exynos4212()) {
resmap[1] = sysmmu_resmap4212;
nmap[1] = ARRAY_SIZE(sysmmu_resmap4212);
}
#endif
for (j = 0; j < 2; j++) {
for (i = 0; i < nmap[j]; i++) {
struct sysmmu_resource_map *map;
struct sysmmu_platform_data *platdata;
map = &resmap[j][i];
map->pdev->dev.parent = map->pdd;
platdata = map->pdev->dev.platform_data;
platdata->clockname = map->clocknames;
if (platform_device_add_resources(map->pdev, map->res,
map->rnum)) {
pr_err("%s: Failed to add device resources for "
"%s.%d\n", __func__,
map->pdev->name, map->pdev->id);
continue;
}
if (platform_device_register(map->pdev)) {
pr_err("%s: Failed to register %s.%d\n",
__func__, map->pdev->name,
map->pdev->id);
}
}
}
return 0;
} }
arch_initcall(init_sysmmu_platform_device);
...@@ -154,6 +154,13 @@ ...@@ -154,6 +154,13 @@
#define EXYNOS4_IRQ_SYSMMU_MFC_M1_0 COMBINER_IRQ(5, 6) #define EXYNOS4_IRQ_SYSMMU_MFC_M1_0 COMBINER_IRQ(5, 6)
#define EXYNOS4_IRQ_SYSMMU_PCIE_0 COMBINER_IRQ(5, 7) #define EXYNOS4_IRQ_SYSMMU_PCIE_0 COMBINER_IRQ(5, 7)
#define EXYNOS4_IRQ_SYSMMU_FIMC_LITE0_0 COMBINER_IRQ(16, 0)
#define EXYNOS4_IRQ_SYSMMU_FIMC_LITE1_0 COMBINER_IRQ(16, 1)
#define EXYNOS4_IRQ_SYSMMU_FIMC_ISP_0 COMBINER_IRQ(16, 2)
#define EXYNOS4_IRQ_SYSMMU_FIMC_DRC_0 COMBINER_IRQ(16, 3)
#define EXYNOS4_IRQ_SYSMMU_FIMC_FD_0 COMBINER_IRQ(16, 4)
#define EXYNOS4_IRQ_SYSMMU_FIMC_CX_0 COMBINER_IRQ(16, 5)
#define EXYNOS4_IRQ_FIMD0_FIFO COMBINER_IRQ(11, 0) #define EXYNOS4_IRQ_FIMD0_FIFO COMBINER_IRQ(11, 0)
#define EXYNOS4_IRQ_FIMD0_VSYNC COMBINER_IRQ(11, 1) #define EXYNOS4_IRQ_FIMD0_VSYNC COMBINER_IRQ(11, 1)
#define EXYNOS4_IRQ_FIMD0_SYSTEM COMBINER_IRQ(11, 2) #define EXYNOS4_IRQ_FIMD0_SYSTEM COMBINER_IRQ(11, 2)
...@@ -220,24 +227,6 @@ ...@@ -220,24 +227,6 @@
#define IRQ_KEYPAD EXYNOS4_IRQ_KEYPAD #define IRQ_KEYPAD EXYNOS4_IRQ_KEYPAD
#define IRQ_PMU EXYNOS4_IRQ_PMU #define IRQ_PMU EXYNOS4_IRQ_PMU
#define IRQ_SYSMMU_MDMA0_0 EXYNOS4_IRQ_SYSMMU_MDMA0_0
#define IRQ_SYSMMU_SSS_0 EXYNOS4_IRQ_SYSMMU_SSS_0
#define IRQ_SYSMMU_FIMC0_0 EXYNOS4_IRQ_SYSMMU_FIMC0_0
#define IRQ_SYSMMU_FIMC1_0 EXYNOS4_IRQ_SYSMMU_FIMC1_0
#define IRQ_SYSMMU_FIMC2_0 EXYNOS4_IRQ_SYSMMU_FIMC2_0
#define IRQ_SYSMMU_FIMC3_0 EXYNOS4_IRQ_SYSMMU_FIMC3_0
#define IRQ_SYSMMU_JPEG_0 EXYNOS4_IRQ_SYSMMU_JPEG_0
#define IRQ_SYSMMU_2D_0 EXYNOS4_IRQ_SYSMMU_2D_0
#define IRQ_SYSMMU_ROTATOR_0 EXYNOS4_IRQ_SYSMMU_ROTATOR_0
#define IRQ_SYSMMU_MDMA1_0 EXYNOS4_IRQ_SYSMMU_MDMA1_0
#define IRQ_SYSMMU_LCD0_M0_0 EXYNOS4_IRQ_SYSMMU_LCD0_M0_0
#define IRQ_SYSMMU_LCD1_M1_0 EXYNOS4_IRQ_SYSMMU_LCD1_M1_0
#define IRQ_SYSMMU_TV_M0_0 EXYNOS4_IRQ_SYSMMU_TV_M0_0
#define IRQ_SYSMMU_MFC_M0_0 EXYNOS4_IRQ_SYSMMU_MFC_M0_0
#define IRQ_SYSMMU_MFC_M1_0 EXYNOS4_IRQ_SYSMMU_MFC_M1_0
#define IRQ_SYSMMU_PCIE_0 EXYNOS4_IRQ_SYSMMU_PCIE_0
#define IRQ_FIMD0_FIFO EXYNOS4_IRQ_FIMD0_FIFO #define IRQ_FIMD0_FIFO EXYNOS4_IRQ_FIMD0_FIFO
#define IRQ_FIMD0_VSYNC EXYNOS4_IRQ_FIMD0_VSYNC #define IRQ_FIMD0_VSYNC EXYNOS4_IRQ_FIMD0_VSYNC
#define IRQ_FIMD0_SYSTEM EXYNOS4_IRQ_FIMD0_SYSTEM #define IRQ_FIMD0_SYSTEM EXYNOS4_IRQ_FIMD0_SYSTEM
......
...@@ -95,6 +95,7 @@ ...@@ -95,6 +95,7 @@
#define EXYNOS5_PA_PDMA1 0x121B0000 #define EXYNOS5_PA_PDMA1 0x121B0000
#define EXYNOS4_PA_SYSMMU_MDMA 0x10A40000 #define EXYNOS4_PA_SYSMMU_MDMA 0x10A40000
#define EXYNOS4_PA_SYSMMU_2D_ACP 0x10A40000
#define EXYNOS4_PA_SYSMMU_SSS 0x10A50000 #define EXYNOS4_PA_SYSMMU_SSS 0x10A50000
#define EXYNOS4_PA_SYSMMU_FIMC0 0x11A20000 #define EXYNOS4_PA_SYSMMU_FIMC0 0x11A20000
#define EXYNOS4_PA_SYSMMU_FIMC1 0x11A30000 #define EXYNOS4_PA_SYSMMU_FIMC1 0x11A30000
...@@ -103,6 +104,12 @@ ...@@ -103,6 +104,12 @@
#define EXYNOS4_PA_SYSMMU_JPEG 0x11A60000 #define EXYNOS4_PA_SYSMMU_JPEG 0x11A60000
#define EXYNOS4_PA_SYSMMU_FIMD0 0x11E20000 #define EXYNOS4_PA_SYSMMU_FIMD0 0x11E20000
#define EXYNOS4_PA_SYSMMU_FIMD1 0x12220000 #define EXYNOS4_PA_SYSMMU_FIMD1 0x12220000
#define EXYNOS4_PA_SYSMMU_FIMC_ISP 0x12260000
#define EXYNOS4_PA_SYSMMU_FIMC_DRC 0x12270000
#define EXYNOS4_PA_SYSMMU_FIMC_FD 0x122A0000
#define EXYNOS4_PA_SYSMMU_ISPCPU 0x122B0000
#define EXYNOS4_PA_SYSMMU_FIMC_LITE0 0x123B0000
#define EXYNOS4_PA_SYSMMU_FIMC_LITE1 0x123C0000
#define EXYNOS4_PA_SYSMMU_PCIe 0x12620000 #define EXYNOS4_PA_SYSMMU_PCIe 0x12620000
#define EXYNOS4_PA_SYSMMU_G2D 0x12A20000 #define EXYNOS4_PA_SYSMMU_G2D 0x12A20000
#define EXYNOS4_PA_SYSMMU_ROTATOR 0x12A30000 #define EXYNOS4_PA_SYSMMU_ROTATOR 0x12A30000
...@@ -110,6 +117,37 @@ ...@@ -110,6 +117,37 @@
#define EXYNOS4_PA_SYSMMU_TV 0x12E20000 #define EXYNOS4_PA_SYSMMU_TV 0x12E20000
#define EXYNOS4_PA_SYSMMU_MFC_L 0x13620000 #define EXYNOS4_PA_SYSMMU_MFC_L 0x13620000
#define EXYNOS4_PA_SYSMMU_MFC_R 0x13630000 #define EXYNOS4_PA_SYSMMU_MFC_R 0x13630000
#define EXYNOS5_PA_SYSMMU_MDMA1 0x10A40000
#define EXYNOS5_PA_SYSMMU_SSS 0x10A50000
#define EXYNOS5_PA_SYSMMU_2D 0x10A60000
#define EXYNOS5_PA_SYSMMU_MFC_L 0x11200000
#define EXYNOS5_PA_SYSMMU_MFC_R 0x11210000
#define EXYNOS5_PA_SYSMMU_ROTATOR 0x11D40000
#define EXYNOS5_PA_SYSMMU_MDMA2 0x11D50000
#define EXYNOS5_PA_SYSMMU_JPEG 0x11F20000
#define EXYNOS5_PA_SYSMMU_IOP 0x12360000
#define EXYNOS5_PA_SYSMMU_RTIC 0x12370000
#define EXYNOS5_PA_SYSMMU_GPS 0x12630000
#define EXYNOS5_PA_SYSMMU_ISP 0x13260000
#define EXYNOS5_PA_SYSMMU_DRC 0x12370000
#define EXYNOS5_PA_SYSMMU_SCALERC 0x13280000
#define EXYNOS5_PA_SYSMMU_SCALERP 0x13290000
#define EXYNOS5_PA_SYSMMU_FD 0x132A0000
#define EXYNOS5_PA_SYSMMU_ISPCPU 0x132B0000
#define EXYNOS5_PA_SYSMMU_ODC 0x132C0000
#define EXYNOS5_PA_SYSMMU_DIS0 0x132D0000
#define EXYNOS5_PA_SYSMMU_DIS1 0x132E0000
#define EXYNOS5_PA_SYSMMU_3DNR 0x132F0000
#define EXYNOS5_PA_SYSMMU_LITE0 0x13C40000
#define EXYNOS5_PA_SYSMMU_LITE1 0x13C50000
#define EXYNOS5_PA_SYSMMU_GSC0 0x13E80000
#define EXYNOS5_PA_SYSMMU_GSC1 0x13E90000
#define EXYNOS5_PA_SYSMMU_GSC2 0x13EA0000
#define EXYNOS5_PA_SYSMMU_GSC3 0x13EB0000
#define EXYNOS5_PA_SYSMMU_FIMD1 0x14640000
#define EXYNOS5_PA_SYSMMU_TV 0x14650000
#define EXYNOS4_PA_SPI0 0x13920000 #define EXYNOS4_PA_SPI0 0x13920000
#define EXYNOS4_PA_SPI1 0x13930000 #define EXYNOS4_PA_SPI1 0x13930000
#define EXYNOS4_PA_SPI2 0x13940000 #define EXYNOS4_PA_SPI2 0x13940000
......
...@@ -135,6 +135,9 @@ ...@@ -135,6 +135,9 @@
#define EXYNOS4_CLKGATE_SCLKCPU EXYNOS_CLKREG(0x14800) #define EXYNOS4_CLKGATE_SCLKCPU EXYNOS_CLKREG(0x14800)
#define EXYNOS4_CLKGATE_IP_CPU EXYNOS_CLKREG(0x14900) #define EXYNOS4_CLKGATE_IP_CPU EXYNOS_CLKREG(0x14900)
#define EXYNOS4_CLKGATE_IP_ISP0 EXYNOS_CLKREG(0x18800)
#define EXYNOS4_CLKGATE_IP_ISP1 EXYNOS_CLKREG(0x18804)
#define EXYNOS4_APLL_LOCKTIME (0x1C20) /* 300us */ #define EXYNOS4_APLL_LOCKTIME (0x1C20) /* 300us */
#define EXYNOS4_APLLCON0_ENABLE_SHIFT (31) #define EXYNOS4_APLLCON0_ENABLE_SHIFT (31)
...@@ -303,6 +306,8 @@ ...@@ -303,6 +306,8 @@
#define EXYNOS5_CLKDIV_PERIC0 EXYNOS_CLKREG(0x10558) #define EXYNOS5_CLKDIV_PERIC0 EXYNOS_CLKREG(0x10558)
#define EXYNOS5_CLKGATE_IP_ACP EXYNOS_CLKREG(0x08800) #define EXYNOS5_CLKGATE_IP_ACP EXYNOS_CLKREG(0x08800)
#define EXYNOS5_CLKGATE_IP_ISP0 EXYNOS_CLKREG(0x0C800)
#define EXYNOS5_CLKGATE_IP_ISP1 EXYNOS_CLKREG(0x0C804)
#define EXYNOS5_CLKGATE_IP_GSCL EXYNOS_CLKREG(0x10920) #define EXYNOS5_CLKGATE_IP_GSCL EXYNOS_CLKREG(0x10920)
#define EXYNOS5_CLKGATE_IP_DISP1 EXYNOS_CLKREG(0x10928) #define EXYNOS5_CLKGATE_IP_DISP1 EXYNOS_CLKREG(0x10928)
#define EXYNOS5_CLKGATE_IP_MFC EXYNOS_CLKREG(0x1092C) #define EXYNOS5_CLKGATE_IP_MFC EXYNOS_CLKREG(0x1092C)
......
/* linux/arch/arm/mach-exynos4/include/mach/regs-sysmmu.h
*
* Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
* http://www.samsung.com
*
* EXYNOS4 - System MMU register
*
* 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.
*/
#ifndef __ASM_ARCH_REGS_SYSMMU_H
#define __ASM_ARCH_REGS_SYSMMU_H __FILE__
#define S5P_MMU_CTRL 0x000
#define S5P_MMU_CFG 0x004
#define S5P_MMU_STATUS 0x008
#define S5P_MMU_FLUSH 0x00C
#define S5P_PT_BASE_ADDR 0x014
#define S5P_INT_STATUS 0x018
#define S5P_INT_CLEAR 0x01C
#define S5P_PAGE_FAULT_ADDR 0x024
#define S5P_AW_FAULT_ADDR 0x028
#define S5P_AR_FAULT_ADDR 0x02C
#define S5P_DEFAULT_SLAVE_ADDR 0x030
#endif /* __ASM_ARCH_REGS_SYSMMU_H */
/* linux/arch/arm/mach-exynos4/include/mach/sysmmu.h /*
* * Copyright (c) 2011-2012 Samsung Electronics Co., Ltd.
* Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
* http://www.samsung.com * http://www.samsung.com
* *
* Samsung sysmmu driver for EXYNOS4 * EXYNOS - System MMU support
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation. * published by the Free Software Foundation.
*/ */
#ifndef __ASM_ARM_ARCH_SYSMMU_H #ifndef _ARM_MACH_EXYNOS_SYSMMU_H_
#define __ASM_ARM_ARCH_SYSMMU_H __FILE__ #define _ARM_MACH_EXYNOS_SYSMMU_H_
enum exynos4_sysmmu_ips { struct sysmmu_platform_data {
SYSMMU_MDMA, char *dbgname;
SYSMMU_SSS, /* comma(,) separated list of clock names for clock gating */
SYSMMU_FIMC0, char *clockname;
SYSMMU_FIMC1,
SYSMMU_FIMC2,
SYSMMU_FIMC3,
SYSMMU_JPEG,
SYSMMU_FIMD0,
SYSMMU_FIMD1,
SYSMMU_PCIe,
SYSMMU_G2D,
SYSMMU_ROTATOR,
SYSMMU_MDMA2,
SYSMMU_TV,
SYSMMU_MFC_L,
SYSMMU_MFC_R,
EXYNOS4_SYSMMU_TOTAL_IPNUM,
}; };
#define S5P_SYSMMU_TOTAL_IPNUM EXYNOS4_SYSMMU_TOTAL_IPNUM #define SYSMMU_DEVNAME_BASE "exynos-sysmmu"
#define SYSMMU_CLOCK_NAME "sysmmu"
#define SYSMMU_CLOCK_NAME2 "sysmmu_mc"
#ifdef CONFIG_EXYNOS_DEV_SYSMMU
#include <linux/device.h>
struct platform_device;
#define SYSMMU_PLATDEV(ipname) exynos_device_sysmmu_##ipname
extern struct platform_device SYSMMU_PLATDEV(mfc_l);
extern struct platform_device SYSMMU_PLATDEV(mfc_r);
extern struct platform_device SYSMMU_PLATDEV(tv);
extern struct platform_device SYSMMU_PLATDEV(jpeg);
extern struct platform_device SYSMMU_PLATDEV(rot);
extern struct platform_device SYSMMU_PLATDEV(fimc0);
extern struct platform_device SYSMMU_PLATDEV(fimc1);
extern struct platform_device SYSMMU_PLATDEV(fimc2);
extern struct platform_device SYSMMU_PLATDEV(fimc3);
extern struct platform_device SYSMMU_PLATDEV(gsc0);
extern struct platform_device SYSMMU_PLATDEV(gsc1);
extern struct platform_device SYSMMU_PLATDEV(gsc2);
extern struct platform_device SYSMMU_PLATDEV(gsc3);
extern struct platform_device SYSMMU_PLATDEV(isp);
extern struct platform_device SYSMMU_PLATDEV(fimd0);
extern struct platform_device SYSMMU_PLATDEV(fimd1);
extern struct platform_device SYSMMU_PLATDEV(camif0);
extern struct platform_device SYSMMU_PLATDEV(camif1);
extern struct platform_device SYSMMU_PLATDEV(2d);
extern const char *sysmmu_ips_name[EXYNOS4_SYSMMU_TOTAL_IPNUM]; #ifdef CONFIG_IOMMU_API
static inline void platform_set_sysmmu(
struct device *sysmmu, struct device *dev)
{
dev->archdata.iommu = sysmmu;
}
#endif
typedef enum exynos4_sysmmu_ips sysmmu_ips; #else /* !CONFIG_EXYNOS_DEV_SYSMMU */
#define platform_set_sysmmu(dev, sysmmu) do { } while (0)
#endif
void sysmmu_clk_init(struct device *dev, sysmmu_ips ips); #define SYSMMU_CLOCK_DEVNAME(ipname, id) (SYSMMU_DEVNAME_BASE "." #id)
void sysmmu_clk_enable(sysmmu_ips ips);
void sysmmu_clk_disable(sysmmu_ips ips);
#endif /* __ASM_ARM_ARCH_SYSMMU_H */ #endif /* _ARM_MACH_EXYNOS_SYSMMU_H_ */
...@@ -157,7 +157,6 @@ static struct platform_device *armlex4210_devices[] __initdata = { ...@@ -157,7 +157,6 @@ static struct platform_device *armlex4210_devices[] __initdata = {
&s3c_device_hsmmc3, &s3c_device_hsmmc3,
&s3c_device_rtc, &s3c_device_rtc,
&s3c_device_wdt, &s3c_device_wdt,
&exynos4_device_sysmmu,
&samsung_asoc_dma, &samsung_asoc_dma,
&armlex4210_smsc911x, &armlex4210_smsc911x,
&exynos4_device_ahci, &exynos4_device_ahci,
......
...@@ -281,7 +281,6 @@ static struct platform_device *smdkv310_devices[] __initdata = { ...@@ -281,7 +281,6 @@ static struct platform_device *smdkv310_devices[] __initdata = {
&s5p_device_mfc_l, &s5p_device_mfc_l,
&s5p_device_mfc_r, &s5p_device_mfc_r,
&exynos4_device_spdif, &exynos4_device_spdif,
&exynos4_device_sysmmu,
&samsung_asoc_dma, &samsung_asoc_dma,
&samsung_asoc_idma, &samsung_asoc_idma,
&s5p_device_fimd0, &s5p_device_fimd0,
......
...@@ -50,14 +50,6 @@ config S5P_PM ...@@ -50,14 +50,6 @@ config S5P_PM
Common code for power management support on S5P and newer SoCs Common code for power management support on S5P and newer SoCs
Note: Do not select this for S5P6440 and S5P6450. Note: Do not select this for S5P6440 and S5P6450.
comment "System MMU"
config S5P_SYSTEM_MMU
bool "S5P SYSTEM MMU"
depends on ARCH_EXYNOS4
help
Say Y here if you want to enable System MMU
config S5P_SLEEP config S5P_SLEEP
bool bool
help help
......
...@@ -16,7 +16,6 @@ obj-y += clock.o ...@@ -16,7 +16,6 @@ obj-y += clock.o
obj-y += irq.o obj-y += irq.o
obj-$(CONFIG_S5P_EXT_INT) += irq-eint.o obj-$(CONFIG_S5P_EXT_INT) += irq-eint.o
obj-$(CONFIG_S5P_GPIO_INT) += irq-gpioint.o obj-$(CONFIG_S5P_GPIO_INT) += irq-gpioint.o
obj-$(CONFIG_S5P_SYSTEM_MMU) += sysmmu.o
obj-$(CONFIG_S5P_PM) += pm.o irq-pm.o obj-$(CONFIG_S5P_PM) += pm.o irq-pm.o
obj-$(CONFIG_S5P_SLEEP) += sleep.o obj-$(CONFIG_S5P_SLEEP) += sleep.o
obj-$(CONFIG_S5P_HRT) += s5p-time.o obj-$(CONFIG_S5P_HRT) += s5p-time.o
......
/* linux/arch/arm/plat-s5p/sysmmu.c
*
* Copyright (c) 2010 Samsung Electronics Co., Ltd.
* http://www.samsung.com
*
* 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/io.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include <linux/export.h>
#include <asm/pgtable.h>
#include <mach/map.h>
#include <mach/regs-sysmmu.h>
#include <plat/sysmmu.h>
#define CTRL_ENABLE 0x5
#define CTRL_BLOCK 0x7
#define CTRL_DISABLE 0x0
static struct device *dev;
static unsigned short fault_reg_offset[SYSMMU_FAULTS_NUM] = {
S5P_PAGE_FAULT_ADDR,
S5P_AR_FAULT_ADDR,
S5P_AW_FAULT_ADDR,
S5P_DEFAULT_SLAVE_ADDR,
S5P_AR_FAULT_ADDR,
S5P_AR_FAULT_ADDR,
S5P_AW_FAULT_ADDR,
S5P_AW_FAULT_ADDR
};
static char *sysmmu_fault_name[SYSMMU_FAULTS_NUM] = {
"PAGE FAULT",
"AR MULTI-HIT FAULT",
"AW MULTI-HIT FAULT",
"BUS ERROR",
"AR SECURITY PROTECTION FAULT",
"AR ACCESS PROTECTION FAULT",
"AW SECURITY PROTECTION FAULT",
"AW ACCESS PROTECTION FAULT"
};
static int (*fault_handlers[S5P_SYSMMU_TOTAL_IPNUM])(
enum S5P_SYSMMU_INTERRUPT_TYPE itype,
unsigned long pgtable_base,
unsigned long fault_addr);
/*
* If adjacent 2 bits are true, the system MMU is enabled.
* The system MMU is disabled, otherwise.
*/
static unsigned long sysmmu_states;
static inline void set_sysmmu_active(sysmmu_ips ips)
{
sysmmu_states |= 3 << (ips * 2);
}
static inline void set_sysmmu_inactive(sysmmu_ips ips)
{
sysmmu_states &= ~(3 << (ips * 2));
}
static inline int is_sysmmu_active(sysmmu_ips ips)
{
return sysmmu_states & (3 << (ips * 2));
}
static void __iomem *sysmmusfrs[S5P_SYSMMU_TOTAL_IPNUM];
static inline void sysmmu_block(sysmmu_ips ips)
{
__raw_writel(CTRL_BLOCK, sysmmusfrs[ips] + S5P_MMU_CTRL);
dev_dbg(dev, "%s is blocked.\n", sysmmu_ips_name[ips]);
}
static inline void sysmmu_unblock(sysmmu_ips ips)
{
__raw_writel(CTRL_ENABLE, sysmmusfrs[ips] + S5P_MMU_CTRL);
dev_dbg(dev, "%s is unblocked.\n", sysmmu_ips_name[ips]);
}
static inline void __sysmmu_tlb_invalidate(sysmmu_ips ips)
{
__raw_writel(0x1, sysmmusfrs[ips] + S5P_MMU_FLUSH);
dev_dbg(dev, "TLB of %s is invalidated.\n", sysmmu_ips_name[ips]);
}
static inline void __sysmmu_set_ptbase(sysmmu_ips ips, unsigned long pgd)
{
if (unlikely(pgd == 0)) {
pgd = (unsigned long)ZERO_PAGE(0);
__raw_writel(0x20, sysmmusfrs[ips] + S5P_MMU_CFG); /* 4KB LV1 */
} else {
__raw_writel(0x0, sysmmusfrs[ips] + S5P_MMU_CFG); /* 16KB LV1 */
}
__raw_writel(pgd, sysmmusfrs[ips] + S5P_PT_BASE_ADDR);
dev_dbg(dev, "Page table base of %s is initialized with 0x%08lX.\n",
sysmmu_ips_name[ips], pgd);
__sysmmu_tlb_invalidate(ips);
}
void sysmmu_set_fault_handler(sysmmu_ips ips,
int (*handler)(enum S5P_SYSMMU_INTERRUPT_TYPE itype,
unsigned long pgtable_base,
unsigned long fault_addr))
{
BUG_ON(!((ips >= SYSMMU_MDMA) && (ips < S5P_SYSMMU_TOTAL_IPNUM)));
fault_handlers[ips] = handler;
}
static irqreturn_t s5p_sysmmu_irq(int irq, void *dev_id)
{
/* SYSMMU is in blocked when interrupt occurred. */
unsigned long base = 0;
sysmmu_ips ips = (sysmmu_ips)dev_id;
enum S5P_SYSMMU_INTERRUPT_TYPE itype;
itype = (enum S5P_SYSMMU_INTERRUPT_TYPE)
__ffs(__raw_readl(sysmmusfrs[ips] + S5P_INT_STATUS));
BUG_ON(!((itype >= 0) && (itype < 8)));
dev_alert(dev, "%s occurred by %s.\n", sysmmu_fault_name[itype],
sysmmu_ips_name[ips]);
if (fault_handlers[ips]) {
unsigned long addr;
base = __raw_readl(sysmmusfrs[ips] + S5P_PT_BASE_ADDR);
addr = __raw_readl(sysmmusfrs[ips] + fault_reg_offset[itype]);
if (fault_handlers[ips](itype, base, addr)) {
__raw_writel(1 << itype,
sysmmusfrs[ips] + S5P_INT_CLEAR);
dev_notice(dev, "%s from %s is resolved."
" Retrying translation.\n",
sysmmu_fault_name[itype], sysmmu_ips_name[ips]);
} else {
base = 0;
}
}
sysmmu_unblock(ips);
if (!base)
dev_notice(dev, "%s from %s is not handled.\n",
sysmmu_fault_name[itype], sysmmu_ips_name[ips]);
return IRQ_HANDLED;
}
void s5p_sysmmu_set_tablebase_pgd(sysmmu_ips ips, unsigned long pgd)
{
if (is_sysmmu_active(ips)) {
sysmmu_block(ips);
__sysmmu_set_ptbase(ips, pgd);
sysmmu_unblock(ips);
} else {
dev_dbg(dev, "%s is disabled. "
"Skipping initializing page table base.\n",
sysmmu_ips_name[ips]);
}
}
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);
set_sysmmu_active(ips);
dev_dbg(dev, "%s is enabled.\n", sysmmu_ips_name[ips]);
} else {
dev_dbg(dev, "%s is already enabled.\n", sysmmu_ips_name[ips]);
}
}
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]);
}
}
void s5p_sysmmu_tlb_invalidate(sysmmu_ips ips)
{
if (is_sysmmu_active(ips)) {
sysmmu_block(ips);
__sysmmu_tlb_invalidate(ips);
sysmmu_unblock(ips);
} else {
dev_dbg(dev, "%s is disabled. "
"Skipping invalidating TLB.\n", sysmmu_ips_name[ips]);
}
}
static int s5p_sysmmu_probe(struct platform_device *pdev)
{
int i, ret;
struct resource *res, *mem;
dev = &pdev->dev;
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",
sysmmu_ips_name[i]);
ret = -ENODEV;
goto err_res;
}
mem = request_mem_region(res->start, resource_size(res),
pdev->name);
if (!mem) {
dev_err(dev, "Failed to request the memory region of %s.\n",
sysmmu_ips_name[i]);
ret = -EBUSY;
goto err_res;
}
sysmmusfrs[i] = ioremap(res->start, resource_size(res));
if (!sysmmusfrs[i]) {
dev_err(dev, "Failed to ioremap() for %s.\n",
sysmmu_ips_name[i]);
ret = -ENXIO;
goto err_reg;
}
irq = platform_get_irq(pdev, i);
if (irq <= 0) {
dev_err(dev, "Failed to get the IRQ resource of %s.\n",
sysmmu_ips_name[i]);
ret = -ENOENT;
goto err_map;
}
if (request_irq(irq, s5p_sysmmu_irq, IRQF_DISABLED,
pdev->name, (void *)i)) {
dev_err(dev, "Failed to request IRQ for %s.\n",
sysmmu_ips_name[i]);
ret = -ENOENT;
goto err_map;
}
}
return 0;
err_map:
iounmap(sysmmusfrs[i]);
err_reg:
release_mem_region(mem->start, resource_size(mem));
err_res:
return ret;
}
static int s5p_sysmmu_remove(struct platform_device *pdev)
{
return 0;
}
int s5p_sysmmu_runtime_suspend(struct device *dev)
{
return 0;
}
int s5p_sysmmu_runtime_resume(struct device *dev)
{
return 0;
}
const struct dev_pm_ops s5p_sysmmu_pm_ops = {
.runtime_suspend = s5p_sysmmu_runtime_suspend,
.runtime_resume = s5p_sysmmu_runtime_resume,
};
static struct platform_driver s5p_sysmmu_driver = {
.probe = s5p_sysmmu_probe,
.remove = s5p_sysmmu_remove,
.driver = {
.owner = THIS_MODULE,
.name = "s5p-sysmmu",
.pm = &s5p_sysmmu_pm_ops,
}
};
static int __init s5p_sysmmu_init(void)
{
return platform_driver_register(&s5p_sysmmu_driver);
}
arch_initcall(s5p_sysmmu_init);
...@@ -133,7 +133,6 @@ extern struct platform_device exynos4_device_pcm1; ...@@ -133,7 +133,6 @@ extern struct platform_device exynos4_device_pcm1;
extern struct platform_device exynos4_device_pcm2; extern struct platform_device exynos4_device_pcm2;
extern struct platform_device exynos4_device_pd[]; extern struct platform_device exynos4_device_pd[];
extern struct platform_device exynos4_device_spdif; extern struct platform_device exynos4_device_spdif;
extern struct platform_device exynos4_device_sysmmu;
extern struct platform_device samsung_asoc_dma; extern struct platform_device samsung_asoc_dma;
extern struct platform_device samsung_asoc_idma; extern struct platform_device samsung_asoc_idma;
......
/* linux/arch/arm/plat-samsung/include/plat/sysmmu.h
*
* Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
* http://www.samsung.com
*
* Samsung System MMU driver for S5P platform
*
* 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.
*/
#ifndef __PLAT_SAMSUNG_SYSMMU_H
#define __PLAT_SAMSUNG_SYSMMU_H __FILE__
enum S5P_SYSMMU_INTERRUPT_TYPE {
SYSMMU_PAGEFAULT,
SYSMMU_AR_MULTIHIT,
SYSMMU_AW_MULTIHIT,
SYSMMU_BUSERROR,
SYSMMU_AR_SECURITY,
SYSMMU_AR_ACCESS,
SYSMMU_AW_SECURITY,
SYSMMU_AW_PROTECTION, /* 7 */
SYSMMU_FAULTS_NUM
};
#ifdef CONFIG_S5P_SYSTEM_MMU
#include <mach/sysmmu.h>
/**
* s5p_sysmmu_enable() - enable system mmu of ip
* @ips: The ip connected system mmu.
* #pgd: Base physical address of the 1st level page table
*
* This function enable system mmu to transfer address
* from virtual address to physical address
*/
void s5p_sysmmu_enable(sysmmu_ips ips, unsigned long pgd);
/**
* s5p_sysmmu_disable() - disable sysmmu mmu of ip
* @ips: The ip connected system mmu.
*
* This function disable system mmu to transfer address
* from virtual address to physical address
*/
void s5p_sysmmu_disable(sysmmu_ips ips);
/**
* s5p_sysmmu_set_tablebase_pgd() - set page table base address to refer page table
* @ips: The ip connected system mmu.
* @pgd: The page table base address.
*
* This function set page table base address
* When system mmu transfer address from virtaul address to physical address,
* system mmu refer address information from page table
*/
void s5p_sysmmu_set_tablebase_pgd(sysmmu_ips ips, unsigned long pgd);
/**
* s5p_sysmmu_tlb_invalidate() - flush all TLB entry in system mmu
* @ips: The ip connected system mmu.
*
* This function flush all TLB entry in system mmu
*/
void s5p_sysmmu_tlb_invalidate(sysmmu_ips ips);
/** s5p_sysmmu_set_fault_handler() - Fault handler for System MMUs
* @itype: type of fault.
* @pgtable_base: the physical address of page table base. This is 0 if @ips is
* SYSMMU_BUSERROR.
* @fault_addr: the device (virtual) address that the System MMU tried to
* translated. This is 0 if @ips is SYSMMU_BUSERROR.
* Called when interrupt occurred by the System MMUs
* The device drivers of peripheral devices that has a System MMU can implement
* a fault handler to resolve address translation fault by System MMU.
* The meanings of return value and parameters are described below.
* return value: non-zero if the fault is correctly resolved.
* zero if the fault is not handled.
*/
void s5p_sysmmu_set_fault_handler(sysmmu_ips ips,
int (*handler)(enum S5P_SYSMMU_INTERRUPT_TYPE itype,
unsigned long pgtable_base,
unsigned long fault_addr));
#else
#define s5p_sysmmu_enable(ips, pgd) do { } while (0)
#define s5p_sysmmu_disable(ips) do { } while (0)
#define s5p_sysmmu_set_tablebase_pgd(ips, pgd) do { } while (0)
#define s5p_sysmmu_tlb_invalidate(ips) do { } while (0)
#define s5p_sysmmu_set_fault_handler(ips, handler) do { } while (0)
#endif
#endif /* __ASM_PLAT_SYSMMU_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment