aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKukjin Kim <kgene.kim@samsung.com>2011-10-04 07:18:36 -0400
committerKukjin Kim <kgene.kim@samsung.com>2011-10-04 07:18:36 -0400
commitdb3c94a7edc6b29f8d52ba5884dec6a15feeadad (patch)
treeac9207a44cecafb9104ca4e1f46aecb9fe01383d
parentc9477f38cba225870862fd9e08868ae3d4abdfe0 (diff)
parent568f0e278c6dd33dc11bd19c4ad781d1f8d86800 (diff)
Merge branch 'next-samsung-devel' into next-samsung-devel-2
Conflicts: arch/arm/mach-exynos4/clock.c arch/arm/mach-s3c2412/gpio.c arch/arm/mach-s5p64x0/dma.c arch/arm/mach-s5p64x0/gpiolib.c
-rw-r--r--arch/arm/Kconfig3
-rw-r--r--arch/arm/include/asm/hardware/pl080.h4
-rw-r--r--arch/arm/mach-exynos4/Kconfig35
-rw-r--r--arch/arm/mach-exynos4/clock.c220
-rw-r--r--arch/arm/mach-exynos4/cpu.c2
-rw-r--r--arch/arm/mach-exynos4/dma.c300
-rw-r--r--arch/arm/mach-exynos4/include/mach/dma.h4
-rw-r--r--arch/arm/mach-exynos4/include/mach/i2c-hdmiphy.h16
-rw-r--r--arch/arm/mach-exynos4/include/mach/irqs.h4
-rw-r--r--arch/arm/mach-exynos4/include/mach/map.h12
-rw-r--r--arch/arm/mach-exynos4/include/mach/pm-core.h8
-rw-r--r--arch/arm/mach-exynos4/include/mach/pmu.h7
-rw-r--r--arch/arm/mach-exynos4/include/mach/regs-pmu.h74
-rw-r--r--arch/arm/mach-exynos4/mach-nuri.c34
-rw-r--r--arch/arm/mach-exynos4/mach-origen.c577
-rw-r--r--arch/arm/mach-exynos4/mach-smdkv310.c49
-rw-r--r--arch/arm/mach-exynos4/mach-universal_c210.c312
-rw-r--r--arch/arm/mach-exynos4/pm.c7
-rw-r--r--arch/arm/mach-exynos4/pmu.c353
-rw-r--r--arch/arm/mach-s3c2410/Kconfig1
-rw-r--r--arch/arm/mach-s3c2410/include/mach/dma.h20
-rw-r--r--arch/arm/mach-s3c2410/include/mach/gpio-fns.h99
-rw-r--r--arch/arm/mach-s3c2410/include/mach/gpio-track.h6
-rw-r--r--arch/arm/mach-s3c2410/include/mach/pm-core.h2
-rw-r--r--arch/arm/mach-s3c2410/include/mach/regs-s3c2443-clock.h1
-rw-r--r--arch/arm/mach-s3c2410/s3c2410.c4
-rw-r--r--arch/arm/mach-s3c2412/dma.c4
-rw-r--r--arch/arm/mach-s3c2412/gpio.c62
-rw-r--r--arch/arm/mach-s3c2416/Kconfig1
-rw-r--r--arch/arm/mach-s3c2416/clock.c28
-rw-r--r--arch/arm/mach-s3c2416/s3c2416.c4
-rw-r--r--arch/arm/mach-s3c2440/Kconfig2
-rw-r--r--arch/arm/mach-s3c2440/s3c2440.c4
-rw-r--r--arch/arm/mach-s3c2440/s3c2442.c4
-rw-r--r--arch/arm/mach-s3c2443/Kconfig1
-rw-r--r--arch/arm/mach-s3c2443/clock.c55
-rw-r--r--arch/arm/mach-s3c2443/s3c2443.c4
-rw-r--r--arch/arm/mach-s3c64xx/Kconfig1
-rw-r--r--arch/arm/mach-s3c64xx/Makefile3
-rw-r--r--arch/arm/mach-s3c64xx/clock.c8
-rw-r--r--arch/arm/mach-s3c64xx/dma.c12
-rw-r--r--arch/arm/mach-s3c64xx/gpiolib.c290
-rw-r--r--arch/arm/mach-s3c64xx/include/mach/crag6410.h23
-rw-r--r--arch/arm/mach-s3c64xx/include/mach/dma.h8
-rw-r--r--arch/arm/mach-s3c64xx/include/mach/pm-core.h2
-rw-r--r--arch/arm/mach-s3c64xx/include/mach/regs-sys.h3
-rw-r--r--arch/arm/mach-s3c64xx/mach-crag6410-module.c182
-rw-r--r--arch/arm/mach-s3c64xx/mach-crag6410.c106
-rw-r--r--arch/arm/mach-s3c64xx/pm.c4
-rw-r--r--arch/arm/mach-s5p64x0/Kconfig14
-rw-r--r--arch/arm/mach-s5p64x0/Makefile3
-rw-r--r--arch/arm/mach-s5p64x0/clock-s5p6440.c10
-rw-r--r--arch/arm/mach-s5p64x0/clock-s5p6450.c10
-rw-r--r--arch/arm/mach-s5p64x0/cpu.c3
-rw-r--r--arch/arm/mach-s5p64x0/dma.c269
-rw-r--r--arch/arm/mach-s5p64x0/include/mach/dma.h4
-rw-r--r--arch/arm/mach-s5p64x0/include/mach/irqs.h4
-rw-r--r--arch/arm/mach-s5p64x0/include/mach/map.h3
-rw-r--r--arch/arm/mach-s5p64x0/include/mach/regs-gpio.h4
-rw-r--r--arch/arm/mach-s5p64x0/mach-smdk6440.c74
-rw-r--r--arch/arm/mach-s5p64x0/mach-smdk6450.c75
-rw-r--r--arch/arm/mach-s5p64x0/setup-fb-24bpp.c29
-rw-r--r--arch/arm/mach-s5pc100/Kconfig2
-rw-r--r--arch/arm/mach-s5pc100/clock.c15
-rw-r--r--arch/arm/mach-s5pc100/dma.c324
-rw-r--r--arch/arm/mach-s5pc100/include/mach/dma.h4
-rw-r--r--arch/arm/mach-s5pv210/Kconfig4
-rw-r--r--arch/arm/mach-s5pv210/clock.c151
-rw-r--r--arch/arm/mach-s5pv210/cpu.c4
-rw-r--r--arch/arm/mach-s5pv210/dma.c317
-rw-r--r--arch/arm/mach-s5pv210/include/mach/dma.h4
-rw-r--r--arch/arm/mach-s5pv210/include/mach/i2c-hdmiphy.h16
-rw-r--r--arch/arm/mach-s5pv210/include/mach/irqs.h4
-rw-r--r--arch/arm/mach-s5pv210/include/mach/map.h13
-rw-r--r--arch/arm/mach-s5pv210/include/mach/pm-core.h2
-rw-r--r--arch/arm/mach-s5pv210/include/mach/regs-clock.h3
-rw-r--r--arch/arm/mach-s5pv210/mach-goni.c62
-rw-r--r--arch/arm/plat-s3c24xx/Kconfig1
-rw-r--r--arch/arm/plat-s3c24xx/Makefile2
-rw-r--r--arch/arm/plat-s3c24xx/dma.c10
-rw-r--r--arch/arm/plat-s3c24xx/gpio.c96
-rw-r--r--arch/arm/plat-s3c24xx/gpiolib.c229
-rw-r--r--arch/arm/plat-s3c24xx/s3c2443-clock.c57
-rw-r--r--arch/arm/plat-s5p/Kconfig13
-rw-r--r--arch/arm/plat-s5p/Makefile2
-rw-r--r--arch/arm/plat-s5p/dev-i2c-hdmiphy.c59
-rw-r--r--arch/arm/plat-s5p/dev-tv.c98
-rw-r--r--arch/arm/plat-s5p/include/plat/pll.h14
-rw-r--r--arch/arm/plat-s5p/irq-gpioint.c10
-rw-r--r--arch/arm/plat-samsung/Kconfig36
-rw-r--r--arch/arm/plat-samsung/Makefile6
-rw-r--r--arch/arm/plat-samsung/dma-ops.c131
-rw-r--r--arch/arm/plat-samsung/gpio-config.c431
-rw-r--r--arch/arm/plat-samsung/gpio.c167
-rw-r--r--arch/arm/plat-samsung/include/plat/devs.h6
-rw-r--r--arch/arm/plat-samsung/include/plat/dma-ops.h63
-rw-r--r--arch/arm/plat-samsung/include/plat/dma-pl330.h (renamed from arch/arm/plat-samsung/include/plat/s3c-dma-pl330.h)24
-rw-r--r--arch/arm/plat-samsung/include/plat/dma-s3c24xx.h2
-rw-r--r--arch/arm/plat-samsung/include/plat/dma.h10
-rw-r--r--arch/arm/plat-samsung/include/plat/fb.h7
-rw-r--r--arch/arm/plat-samsung/include/plat/gpio-cfg-helpers.h172
-rw-r--r--arch/arm/plat-samsung/include/plat/gpio-cfg.h34
-rw-r--r--arch/arm/plat-samsung/include/plat/gpio-core.h97
-rw-r--r--arch/arm/plat-samsung/include/plat/gpio-fns.h98
-rw-r--r--arch/arm/plat-samsung/include/plat/iic.h1
-rw-r--r--arch/arm/plat-samsung/include/plat/pm.h10
-rw-r--r--arch/arm/plat-samsung/include/plat/s3c-pl330-pdata.h32
-rw-r--r--arch/arm/plat-samsung/include/plat/tv-core.h44
-rw-r--r--arch/arm/plat-samsung/pm-gpio.c72
-rw-r--r--arch/arm/plat-samsung/pm.c6
-rw-r--r--arch/arm/plat-samsung/s3c-dma-ops.c130
-rw-r--r--arch/arm/plat-samsung/s3c-pl330.c1244
-rw-r--r--drivers/dma/Kconfig3
-rw-r--r--drivers/dma/amba-pl08x.c455
-rw-r--r--drivers/dma/at_hdmac.c159
-rw-r--r--drivers/dma/at_hdmac_regs.h24
-rw-r--r--drivers/dma/dmatest.c23
-rw-r--r--drivers/dma/imx-sdma.c47
-rw-r--r--drivers/dma/mxs-dma.c45
-rw-r--r--drivers/dma/pl330.c229
-rw-r--r--drivers/gpio/Kconfig16
-rw-r--r--drivers/gpio/Makefile7
-rw-r--r--drivers/gpio/gpio-exynos4.c385
-rw-r--r--drivers/gpio/gpio-plat-samsung.c205
-rw-r--r--drivers/gpio/gpio-s5pc100.c354
-rw-r--r--drivers/gpio/gpio-s5pv210.c287
-rw-r--r--drivers/gpio/gpio-samsung.c2688
-rw-r--r--drivers/mmc/host/s3cmci.c6
-rw-r--r--drivers/spi/spi-s3c64xx.c175
-rw-r--r--include/linux/amba/pl08x.h14
-rw-r--r--include/linux/amba/pl330.h6
-rw-r--r--include/linux/dmaengine.h13
-rw-r--r--sound/soc/samsung/ac97.c10
-rw-r--r--sound/soc/samsung/dma.c148
-rw-r--r--sound/soc/samsung/dma.h4
135 files changed, 7591 insertions, 5518 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 3146ed3f6eca..bea81d018312 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -724,9 +724,6 @@ config ARCH_S3C64XX
724 select SAMSUNG_IRQ_VIC_TIMER 724 select SAMSUNG_IRQ_VIC_TIMER
725 select SAMSUNG_IRQ_UART 725 select SAMSUNG_IRQ_UART
726 select S3C_GPIO_TRACK 726 select S3C_GPIO_TRACK
727 select S3C_GPIO_PULL_UPDOWN
728 select S3C_GPIO_CFG_S3C24XX
729 select S3C_GPIO_CFG_S3C64XX
730 select S3C_DEV_NAND 727 select S3C_DEV_NAND
731 select USB_ARCH_HAS_OHCI 728 select USB_ARCH_HAS_OHCI
732 select SAMSUNG_GPIOLIB_4BIT 729 select SAMSUNG_GPIOLIB_4BIT
diff --git a/arch/arm/include/asm/hardware/pl080.h b/arch/arm/include/asm/hardware/pl080.h
index e4a04e4e5627..33c78d7af2e1 100644
--- a/arch/arm/include/asm/hardware/pl080.h
+++ b/arch/arm/include/asm/hardware/pl080.h
@@ -21,6 +21,9 @@
21 * OneNAND features. 21 * OneNAND features.
22*/ 22*/
23 23
24#ifndef ASM_PL080_H
25#define ASM_PL080_H
26
24#define PL080_INT_STATUS (0x00) 27#define PL080_INT_STATUS (0x00)
25#define PL080_TC_STATUS (0x04) 28#define PL080_TC_STATUS (0x04)
26#define PL080_TC_CLEAR (0x08) 29#define PL080_TC_CLEAR (0x08)
@@ -138,3 +141,4 @@ struct pl080s_lli {
138 u32 control1; 141 u32 control1;
139}; 142};
140 143
144#endif /* ASM_PL080_H */
diff --git a/arch/arm/mach-exynos4/Kconfig b/arch/arm/mach-exynos4/Kconfig
index c595bb03f417..b6722decff9d 100644
--- a/arch/arm/mach-exynos4/Kconfig
+++ b/arch/arm/mach-exynos4/Kconfig
@@ -11,7 +11,7 @@ if ARCH_EXYNOS4
11 11
12config CPU_EXYNOS4210 12config CPU_EXYNOS4210
13 bool 13 bool
14 select S3C_PL330_DMA 14 select SAMSUNG_DMADEV
15 help 15 help
16 Enable EXYNOS4210 CPU support 16 Enable EXYNOS4210 CPU support
17 17
@@ -131,6 +131,14 @@ config MACH_SMDKV310
131 select S3C_DEV_RTC 131 select S3C_DEV_RTC
132 select S3C_DEV_WDT 132 select S3C_DEV_WDT
133 select S3C_DEV_I2C1 133 select S3C_DEV_I2C1
134 select S5P_DEV_FIMC0
135 select S5P_DEV_FIMC1
136 select S5P_DEV_FIMC2
137 select S5P_DEV_FIMC3
138 select S5P_DEV_I2C_HDMIPHY
139 select S5P_DEV_MFC
140 select S5P_DEV_TV
141 select S5P_DEV_USB_EHCI
134 select S3C_DEV_HSMMC 142 select S3C_DEV_HSMMC
135 select S3C_DEV_HSMMC1 143 select S3C_DEV_HSMMC1
136 select S3C_DEV_HSMMC2 144 select S3C_DEV_HSMMC2
@@ -145,6 +153,7 @@ config MACH_SMDKV310
145 select EXYNOS4_SETUP_I2C1 153 select EXYNOS4_SETUP_I2C1
146 select EXYNOS4_SETUP_KEYPAD 154 select EXYNOS4_SETUP_KEYPAD
147 select EXYNOS4_SETUP_SDHCI 155 select EXYNOS4_SETUP_SDHCI
156 select EXYNOS4_SETUP_USB_PHY
148 help 157 help
149 Machine support for Samsung SMDKV310 158 Machine support for Samsung SMDKV310
150 159
@@ -170,19 +179,26 @@ config MACH_UNIVERSAL_C210
170 select S5P_DEV_FIMC1 179 select S5P_DEV_FIMC1
171 select S5P_DEV_FIMC2 180 select S5P_DEV_FIMC2
172 select S5P_DEV_FIMC3 181 select S5P_DEV_FIMC3
182 select S5P_DEV_CSIS0
183 select S5P_DEV_FIMD0
173 select S3C_DEV_HSMMC 184 select S3C_DEV_HSMMC
174 select S3C_DEV_HSMMC2 185 select S3C_DEV_HSMMC2
175 select S3C_DEV_HSMMC3 186 select S3C_DEV_HSMMC3
176 select S3C_DEV_I2C1 187 select S3C_DEV_I2C1
177 select S3C_DEV_I2C3 188 select S3C_DEV_I2C3
178 select S3C_DEV_I2C5 189 select S3C_DEV_I2C5
190 select S5P_DEV_I2C_HDMIPHY
179 select S5P_DEV_MFC 191 select S5P_DEV_MFC
180 select S5P_DEV_ONENAND 192 select S5P_DEV_ONENAND
193 select S5P_DEV_TV
181 select EXYNOS4_DEV_PD 194 select EXYNOS4_DEV_PD
195 select EXYNOS4_SETUP_FIMD0
182 select EXYNOS4_SETUP_I2C1 196 select EXYNOS4_SETUP_I2C1
183 select EXYNOS4_SETUP_I2C3 197 select EXYNOS4_SETUP_I2C3
184 select EXYNOS4_SETUP_I2C5 198 select EXYNOS4_SETUP_I2C5
185 select EXYNOS4_SETUP_SDHCI 199 select EXYNOS4_SETUP_SDHCI
200 select EXYNOS4_SETUP_FIMC
201 select S5P_SETUP_MIPIPHY
186 help 202 help
187 Machine support for Samsung Mobile Universal S5PC210 Reference 203 Machine support for Samsung Mobile Universal S5PC210 Reference
188 Board. 204 Board.
@@ -191,6 +207,8 @@ config MACH_NURI
191 bool "Mobile NURI Board" 207 bool "Mobile NURI Board"
192 select CPU_EXYNOS4210 208 select CPU_EXYNOS4210
193 select S3C_DEV_WDT 209 select S3C_DEV_WDT
210 select S3C_DEV_RTC
211 select S5P_DEV_FIMD0
194 select S3C_DEV_HSMMC 212 select S3C_DEV_HSMMC
195 select S3C_DEV_HSMMC2 213 select S3C_DEV_HSMMC2
196 select S3C_DEV_HSMMC3 214 select S3C_DEV_HSMMC3
@@ -200,6 +218,7 @@ config MACH_NURI
200 select S5P_DEV_MFC 218 select S5P_DEV_MFC
201 select S5P_DEV_USB_EHCI 219 select S5P_DEV_USB_EHCI
202 select EXYNOS4_DEV_PD 220 select EXYNOS4_DEV_PD
221 select EXYNOS4_SETUP_FIMD0
203 select EXYNOS4_SETUP_I2C1 222 select EXYNOS4_SETUP_I2C1
204 select EXYNOS4_SETUP_I2C3 223 select EXYNOS4_SETUP_I2C3
205 select EXYNOS4_SETUP_I2C5 224 select EXYNOS4_SETUP_I2C5
@@ -215,8 +234,22 @@ config MACH_ORIGEN
215 select CPU_EXYNOS4210 234 select CPU_EXYNOS4210
216 select S3C_DEV_RTC 235 select S3C_DEV_RTC
217 select S3C_DEV_WDT 236 select S3C_DEV_WDT
237 select S3C_DEV_HSMMC
218 select S3C_DEV_HSMMC2 238 select S3C_DEV_HSMMC2
239 select S5P_DEV_FIMC0
240 select S5P_DEV_FIMC1
241 select S5P_DEV_FIMC2
242 select S5P_DEV_FIMC3
243 select S5P_DEV_FIMD0
244 select S5P_DEV_I2C_HDMIPHY
245 select S5P_DEV_TV
246 select S5P_DEV_USB_EHCI
247 select EXYNOS4_DEV_PD
248 select SAMSUNG_DEV_BACKLIGHT
249 select SAMSUNG_DEV_PWM
250 select EXYNOS4_SETUP_FIMD0
219 select EXYNOS4_SETUP_SDHCI 251 select EXYNOS4_SETUP_SDHCI
252 select EXYNOS4_SETUP_USB_PHY
220 help 253 help
221 Machine support for ORIGEN based on Samsung EXYNOS4210 254 Machine support for ORIGEN based on Samsung EXYNOS4210
222 255
diff --git a/arch/arm/mach-exynos4/clock.c b/arch/arm/mach-exynos4/clock.c
index 413c7cc81979..a25c81836759 100644
--- a/arch/arm/mach-exynos4/clock.c
+++ b/arch/arm/mach-exynos4/clock.c
@@ -111,6 +111,11 @@ struct clk clk_sclk_usbphy1 = {
111 .name = "sclk_usbphy1", 111 .name = "sclk_usbphy1",
112}; 112};
113 113
114static struct clk dummy_apb_pclk = {
115 .name = "apb_pclk",
116 .id = -1,
117};
118
114static int exynos4_clksrc_mask_top_ctrl(struct clk *clk, int enable) 119static int exynos4_clksrc_mask_top_ctrl(struct clk *clk, int enable)
115{ 120{
116 return s5p_gatectrl(S5P_CLKSRC_MASK_TOP, clk, enable); 121 return s5p_gatectrl(S5P_CLKSRC_MASK_TOP, clk, enable);
@@ -146,6 +151,11 @@ static int exynos4_clk_ip_mfc_ctrl(struct clk *clk, int enable)
146 return s5p_gatectrl(S5P_CLKGATE_IP_MFC, clk, enable); 151 return s5p_gatectrl(S5P_CLKGATE_IP_MFC, clk, enable);
147} 152}
148 153
154static int exynos4_clksrc_mask_tv_ctrl(struct clk *clk, int enable)
155{
156 return s5p_gatectrl(S5P_CLKSRC_MASK_TV, clk, enable);
157}
158
149static int exynos4_clk_ip_cam_ctrl(struct clk *clk, int enable) 159static int exynos4_clk_ip_cam_ctrl(struct clk *clk, int enable)
150{ 160{
151 return s5p_gatectrl(S5P_CLKGATE_IP_CAM, clk, enable); 161 return s5p_gatectrl(S5P_CLKGATE_IP_CAM, clk, enable);
@@ -186,6 +196,16 @@ static int exynos4_clk_ip_perir_ctrl(struct clk *clk, int enable)
186 return s5p_gatectrl(S5P_CLKGATE_IP_PERIR, clk, enable); 196 return s5p_gatectrl(S5P_CLKGATE_IP_PERIR, clk, enable);
187} 197}
188 198
199static int exynos4_clk_hdmiphy_ctrl(struct clk *clk, int enable)
200{
201 return s5p_gatectrl(S5P_HDMI_PHY_CONTROL, clk, enable);
202}
203
204static int exynos4_clk_dac_ctrl(struct clk *clk, int enable)
205{
206 return s5p_gatectrl(S5P_DAC_PHY_CONTROL, clk, enable);
207}
208
189/* Core list of CMU_CPU side */ 209/* Core list of CMU_CPU side */
190 210
191static struct clksrc_clk clk_mout_apll = { 211static struct clksrc_clk clk_mout_apll = {
@@ -503,13 +523,48 @@ static struct clk init_clocks_off[] = {
503 .enable = exynos4_clk_ip_fsys_ctrl, 523 .enable = exynos4_clk_ip_fsys_ctrl,
504 .ctrlbit = (1 << 9), 524 .ctrlbit = (1 << 9),
505 }, { 525 }, {
506 .name = "pdma", 526 .name = "dac",
507 .devname = "s3c-pl330.0", 527 .devname = "s5p-sdo",
528 .enable = exynos4_clk_ip_tv_ctrl,
529 .ctrlbit = (1 << 2),
530 }, {
531 .name = "mixer",
532 .devname = "s5p-mixer",
533 .enable = exynos4_clk_ip_tv_ctrl,
534 .ctrlbit = (1 << 1),
535 }, {
536 .name = "vp",
537 .devname = "s5p-mixer",
538 .enable = exynos4_clk_ip_tv_ctrl,
539 .ctrlbit = (1 << 0),
540 }, {
541 .name = "hdmi",
542 .devname = "exynos4-hdmi",
543 .enable = exynos4_clk_ip_tv_ctrl,
544 .ctrlbit = (1 << 3),
545 }, {
546 .name = "hdmiphy",
547 .devname = "exynos4-hdmi",
548 .enable = exynos4_clk_hdmiphy_ctrl,
549 .ctrlbit = (1 << 0),
550 }, {
551 .name = "dacphy",
552 .devname = "s5p-sdo",
553 .enable = exynos4_clk_dac_ctrl,
554 .ctrlbit = (1 << 0),
555 }, {
556 .name = "sata",
557 .parent = &clk_aclk_133.clk,
558 .enable = exynos4_clk_ip_fsys_ctrl,
559 .ctrlbit = (1 << 10),
560 }, {
561 .name = "dma",
562 .devname = "dma-pl330.0",
508 .enable = exynos4_clk_ip_fsys_ctrl, 563 .enable = exynos4_clk_ip_fsys_ctrl,
509 .ctrlbit = (1 << 0), 564 .ctrlbit = (1 << 0),
510 }, { 565 }, {
511 .name = "pdma", 566 .name = "dma",
512 .devname = "s3c-pl330.1", 567 .devname = "dma-pl330.1",
513 .enable = exynos4_clk_ip_fsys_ctrl, 568 .enable = exynos4_clk_ip_fsys_ctrl,
514 .ctrlbit = (1 << 1), 569 .ctrlbit = (1 << 1),
515 }, { 570 }, {
@@ -630,6 +685,12 @@ static struct clk init_clocks_off[] = {
630 .enable = exynos4_clk_ip_peril_ctrl, 685 .enable = exynos4_clk_ip_peril_ctrl,
631 .ctrlbit = (1 << 13), 686 .ctrlbit = (1 << 13),
632 }, { 687 }, {
688 .name = "i2c",
689 .devname = "s3c2440-hdmiphy-i2c",
690 .parent = &clk_aclk_100.clk,
691 .enable = exynos4_clk_ip_peril_ctrl,
692 .ctrlbit = (1 << 14),
693 }, {
633 .name = "SYSMMU_MDMA", 694 .name = "SYSMMU_MDMA",
634 .enable = exynos4_clk_ip_image_ctrl, 695 .enable = exynos4_clk_ip_image_ctrl,
635 .ctrlbit = (1 << 5), 696 .ctrlbit = (1 << 5),
@@ -831,6 +892,81 @@ static struct clksrc_sources clkset_mout_mfc = {
831 .nr_sources = ARRAY_SIZE(clkset_mout_mfc_list), 892 .nr_sources = ARRAY_SIZE(clkset_mout_mfc_list),
832}; 893};
833 894
895static struct clk *clkset_sclk_dac_list[] = {
896 [0] = &clk_sclk_vpll.clk,
897 [1] = &clk_sclk_hdmiphy,
898};
899
900static struct clksrc_sources clkset_sclk_dac = {
901 .sources = clkset_sclk_dac_list,
902 .nr_sources = ARRAY_SIZE(clkset_sclk_dac_list),
903};
904
905static struct clksrc_clk clk_sclk_dac = {
906 .clk = {
907 .name = "sclk_dac",
908 .enable = exynos4_clksrc_mask_tv_ctrl,
909 .ctrlbit = (1 << 8),
910 },
911 .sources = &clkset_sclk_dac,
912 .reg_src = { .reg = S5P_CLKSRC_TV, .shift = 8, .size = 1 },
913};
914
915static struct clksrc_clk clk_sclk_pixel = {
916 .clk = {
917 .name = "sclk_pixel",
918 .parent = &clk_sclk_vpll.clk,
919 },
920 .reg_div = { .reg = S5P_CLKDIV_TV, .shift = 0, .size = 4 },
921};
922
923static struct clk *clkset_sclk_hdmi_list[] = {
924 [0] = &clk_sclk_pixel.clk,
925 [1] = &clk_sclk_hdmiphy,
926};
927
928static struct clksrc_sources clkset_sclk_hdmi = {
929 .sources = clkset_sclk_hdmi_list,
930 .nr_sources = ARRAY_SIZE(clkset_sclk_hdmi_list),
931};
932
933static struct clksrc_clk clk_sclk_hdmi = {
934 .clk = {
935 .name = "sclk_hdmi",
936 .enable = exynos4_clksrc_mask_tv_ctrl,
937 .ctrlbit = (1 << 0),
938 },
939 .sources = &clkset_sclk_hdmi,
940 .reg_src = { .reg = S5P_CLKSRC_TV, .shift = 0, .size = 1 },
941};
942
943static struct clk *clkset_sclk_mixer_list[] = {
944 [0] = &clk_sclk_dac.clk,
945 [1] = &clk_sclk_hdmi.clk,
946};
947
948static struct clksrc_sources clkset_sclk_mixer = {
949 .sources = clkset_sclk_mixer_list,
950 .nr_sources = ARRAY_SIZE(clkset_sclk_mixer_list),
951};
952
953static struct clksrc_clk clk_sclk_mixer = {
954 .clk = {
955 .name = "sclk_mixer",
956 .enable = exynos4_clksrc_mask_tv_ctrl,
957 .ctrlbit = (1 << 4),
958 },
959 .sources = &clkset_sclk_mixer,
960 .reg_src = { .reg = S5P_CLKSRC_TV, .shift = 4, .size = 1 },
961};
962
963static struct clksrc_clk *sclk_tv[] = {
964 &clk_sclk_dac,
965 &clk_sclk_pixel,
966 &clk_sclk_hdmi,
967 &clk_sclk_mixer,
968};
969
834static struct clksrc_clk clk_dout_mmc0 = { 970static struct clksrc_clk clk_dout_mmc0 = {
835 .clk = { 971 .clk = {
836 .name = "dout_mmc0", 972 .name = "dout_mmc0",
@@ -1157,6 +1293,71 @@ static struct clk_ops exynos4_fout_apll_ops = {
1157 .get_rate = exynos4_fout_apll_get_rate, 1293 .get_rate = exynos4_fout_apll_get_rate,
1158}; 1294};
1159 1295
1296static u32 vpll_div[][8] = {
1297 { 54000000, 3, 53, 3, 1024, 0, 17, 0 },
1298 { 108000000, 3, 53, 2, 1024, 0, 17, 0 },
1299};
1300
1301static unsigned long exynos4_vpll_get_rate(struct clk *clk)
1302{
1303 return clk->rate;
1304}
1305
1306static int exynos4_vpll_set_rate(struct clk *clk, unsigned long rate)
1307{
1308 unsigned int vpll_con0, vpll_con1 = 0;
1309 unsigned int i;
1310
1311 /* Return if nothing changed */
1312 if (clk->rate == rate)
1313 return 0;
1314
1315 vpll_con0 = __raw_readl(S5P_VPLL_CON0);
1316 vpll_con0 &= ~(0x1 << 27 | \
1317 PLL90XX_MDIV_MASK << PLL46XX_MDIV_SHIFT | \
1318 PLL90XX_PDIV_MASK << PLL46XX_PDIV_SHIFT | \
1319 PLL90XX_SDIV_MASK << PLL46XX_SDIV_SHIFT);
1320
1321 vpll_con1 = __raw_readl(S5P_VPLL_CON1);
1322 vpll_con1 &= ~(PLL46XX_MRR_MASK << PLL46XX_MRR_SHIFT | \
1323 PLL46XX_MFR_MASK << PLL46XX_MFR_SHIFT | \
1324 PLL4650C_KDIV_MASK << PLL46XX_KDIV_SHIFT);
1325
1326 for (i = 0; i < ARRAY_SIZE(vpll_div); i++) {
1327 if (vpll_div[i][0] == rate) {
1328 vpll_con0 |= vpll_div[i][1] << PLL46XX_PDIV_SHIFT;
1329 vpll_con0 |= vpll_div[i][2] << PLL46XX_MDIV_SHIFT;
1330 vpll_con0 |= vpll_div[i][3] << PLL46XX_SDIV_SHIFT;
1331 vpll_con1 |= vpll_div[i][4] << PLL46XX_KDIV_SHIFT;
1332 vpll_con1 |= vpll_div[i][5] << PLL46XX_MFR_SHIFT;
1333 vpll_con1 |= vpll_div[i][6] << PLL46XX_MRR_SHIFT;
1334 vpll_con0 |= vpll_div[i][7] << 27;
1335 break;
1336 }
1337 }
1338
1339 if (i == ARRAY_SIZE(vpll_div)) {
1340 printk(KERN_ERR "%s: Invalid Clock VPLL Frequency\n",
1341 __func__);
1342 return -EINVAL;
1343 }
1344
1345 __raw_writel(vpll_con0, S5P_VPLL_CON0);
1346 __raw_writel(vpll_con1, S5P_VPLL_CON1);
1347
1348 /* Wait for VPLL lock */
1349 while (!(__raw_readl(S5P_VPLL_CON0) & (1 << PLL46XX_LOCKED_SHIFT)))
1350 continue;
1351
1352 clk->rate = rate;
1353 return 0;
1354}
1355
1356static struct clk_ops exynos4_vpll_ops = {
1357 .get_rate = exynos4_vpll_get_rate,
1358 .set_rate = exynos4_vpll_set_rate,
1359};
1360
1160void __init_or_cpufreq exynos4_setup_clocks(void) 1361void __init_or_cpufreq exynos4_setup_clocks(void)
1161{ 1362{
1162 struct clk *xtal_clk; 1363 struct clk *xtal_clk;
@@ -1214,6 +1415,7 @@ void __init_or_cpufreq exynos4_setup_clocks(void)
1214 clk_fout_apll.ops = &exynos4_fout_apll_ops; 1415 clk_fout_apll.ops = &exynos4_fout_apll_ops;
1215 clk_fout_mpll.rate = mpll; 1416 clk_fout_mpll.rate = mpll;
1216 clk_fout_epll.rate = epll; 1417 clk_fout_epll.rate = epll;
1418 clk_fout_vpll.ops = &exynos4_vpll_ops;
1217 clk_fout_vpll.rate = vpll; 1419 clk_fout_vpll.rate = vpll;
1218 1420
1219 printk(KERN_INFO "EXYNOS4: PLL settings, A=%ld, M=%ld, E=%ld V=%ld", 1421 printk(KERN_INFO "EXYNOS4: PLL settings, A=%ld, M=%ld, E=%ld V=%ld",
@@ -1241,7 +1443,10 @@ void __init_or_cpufreq exynos4_setup_clocks(void)
1241} 1443}
1242 1444
1243static struct clk *clks[] __initdata = { 1445static struct clk *clks[] __initdata = {
1244 /* Nothing here yet */ 1446 &clk_sclk_hdmi27m,
1447 &clk_sclk_hdmiphy,
1448 &clk_sclk_usbphy0,
1449 &clk_sclk_usbphy1,
1245}; 1450};
1246 1451
1247#ifdef CONFIG_PM_SLEEP 1452#ifdef CONFIG_PM_SLEEP
@@ -1275,6 +1480,9 @@ void __init exynos4_register_clocks(void)
1275 for (ptr = 0; ptr < ARRAY_SIZE(sysclks); ptr++) 1480 for (ptr = 0; ptr < ARRAY_SIZE(sysclks); ptr++)
1276 s3c_register_clksrc(sysclks[ptr], 1); 1481 s3c_register_clksrc(sysclks[ptr], 1);
1277 1482
1483 for (ptr = 0; ptr < ARRAY_SIZE(sclk_tv); ptr++)
1484 s3c_register_clksrc(sclk_tv[ptr], 1);
1485
1278 s3c_register_clksrc(clksrcs, ARRAY_SIZE(clksrcs)); 1486 s3c_register_clksrc(clksrcs, ARRAY_SIZE(clksrcs));
1279 s3c_register_clocks(init_clocks, ARRAY_SIZE(init_clocks)); 1487 s3c_register_clocks(init_clocks, ARRAY_SIZE(init_clocks));
1280 1488
@@ -1282,5 +1490,7 @@ void __init exynos4_register_clocks(void)
1282 s3c_disable_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off)); 1490 s3c_disable_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
1283 1491
1284 register_syscore_ops(&exynos4_clock_syscore_ops); 1492 register_syscore_ops(&exynos4_clock_syscore_ops);
1493 s3c24xx_register_clock(&dummy_apb_pclk);
1494
1285 s3c_pwmclk_init(); 1495 s3c_pwmclk_init();
1286} 1496}
diff --git a/arch/arm/mach-exynos4/cpu.c b/arch/arm/mach-exynos4/cpu.c
index 02ec52a99274..2aa3df003683 100644
--- a/arch/arm/mach-exynos4/cpu.c
+++ b/arch/arm/mach-exynos4/cpu.c
@@ -28,6 +28,7 @@
28#include <plat/fimc-core.h> 28#include <plat/fimc-core.h>
29#include <plat/iic-core.h> 29#include <plat/iic-core.h>
30#include <plat/reset.h> 30#include <plat/reset.h>
31#include <plat/tv-core.h>
31 32
32#include <mach/regs-irq.h> 33#include <mach/regs-irq.h>
33#include <mach/regs-pmu.h> 34#include <mach/regs-pmu.h>
@@ -180,6 +181,7 @@ void __init exynos4_map_io(void)
180 s3c_i2c2_setname("s3c2440-i2c"); 181 s3c_i2c2_setname("s3c2440-i2c");
181 182
182 s5p_fb_setname(0, "exynos4-fb"); 183 s5p_fb_setname(0, "exynos4-fb");
184 s5p_hdmi_setname("exynos4-hdmi");
183} 185}
184 186
185void __init exynos4_init_clocks(int xtal) 187void __init exynos4_init_clocks(int xtal)
diff --git a/arch/arm/mach-exynos4/dma.c b/arch/arm/mach-exynos4/dma.c
index 564bb530f332..9667c61e64fb 100644
--- a/arch/arm/mach-exynos4/dma.c
+++ b/arch/arm/mach-exynos4/dma.c
@@ -21,151 +21,229 @@
21 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 21 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 */ 22 */
23 23
24#include <linux/platform_device.h>
25#include <linux/dma-mapping.h> 24#include <linux/dma-mapping.h>
25#include <linux/amba/bus.h>
26#include <linux/amba/pl330.h>
26 27
28#include <asm/irq.h>
27#include <plat/devs.h> 29#include <plat/devs.h>
28#include <plat/irqs.h> 30#include <plat/irqs.h>
29 31
30#include <mach/map.h> 32#include <mach/map.h>
31#include <mach/irqs.h> 33#include <mach/irqs.h>
32 34#include <mach/dma.h>
33#include <plat/s3c-pl330-pdata.h>
34 35
35static u64 dma_dmamask = DMA_BIT_MASK(32); 36static u64 dma_dmamask = DMA_BIT_MASK(32);
36 37
37static struct resource exynos4_pdma0_resource[] = { 38struct dma_pl330_peri pdma0_peri[28] = {
38 [0] = { 39 {
39 .start = EXYNOS4_PA_PDMA0, 40 .peri_id = (u8)DMACH_PCM0_RX,
40 .end = EXYNOS4_PA_PDMA0 + SZ_4K, 41 .rqtype = DEVTOMEM,
41 .flags = IORESOURCE_MEM, 42 }, {
42 }, 43 .peri_id = (u8)DMACH_PCM0_TX,
43 [1] = { 44 .rqtype = MEMTODEV,
44 .start = IRQ_PDMA0, 45 }, {
45 .end = IRQ_PDMA0, 46 .peri_id = (u8)DMACH_PCM2_RX,
46 .flags = IORESOURCE_IRQ, 47 .rqtype = DEVTOMEM,
48 }, {
49 .peri_id = (u8)DMACH_PCM2_TX,
50 .rqtype = MEMTODEV,
51 }, {
52 .peri_id = (u8)DMACH_MSM_REQ0,
53 }, {
54 .peri_id = (u8)DMACH_MSM_REQ2,
55 }, {
56 .peri_id = (u8)DMACH_SPI0_RX,
57 .rqtype = DEVTOMEM,
58 }, {
59 .peri_id = (u8)DMACH_SPI0_TX,
60 .rqtype = MEMTODEV,
61 }, {
62 .peri_id = (u8)DMACH_SPI2_RX,
63 .rqtype = DEVTOMEM,
64 }, {
65 .peri_id = (u8)DMACH_SPI2_TX,
66 .rqtype = MEMTODEV,
67 }, {
68 .peri_id = (u8)DMACH_I2S0S_TX,
69 .rqtype = MEMTODEV,
70 }, {
71 .peri_id = (u8)DMACH_I2S0_RX,
72 .rqtype = DEVTOMEM,
73 }, {
74 .peri_id = (u8)DMACH_I2S0_TX,
75 .rqtype = MEMTODEV,
76 }, {
77 .peri_id = (u8)DMACH_UART0_RX,
78 .rqtype = DEVTOMEM,
79 }, {
80 .peri_id = (u8)DMACH_UART0_TX,
81 .rqtype = MEMTODEV,
82 }, {
83 .peri_id = (u8)DMACH_UART2_RX,
84 .rqtype = DEVTOMEM,
85 }, {
86 .peri_id = (u8)DMACH_UART2_TX,
87 .rqtype = MEMTODEV,
88 }, {
89 .peri_id = (u8)DMACH_UART4_RX,
90 .rqtype = DEVTOMEM,
91 }, {
92 .peri_id = (u8)DMACH_UART4_TX,
93 .rqtype = MEMTODEV,
94 }, {
95 .peri_id = (u8)DMACH_SLIMBUS0_RX,
96 .rqtype = DEVTOMEM,
97 }, {
98 .peri_id = (u8)DMACH_SLIMBUS0_TX,
99 .rqtype = MEMTODEV,
100 }, {
101 .peri_id = (u8)DMACH_SLIMBUS2_RX,
102 .rqtype = DEVTOMEM,
103 }, {
104 .peri_id = (u8)DMACH_SLIMBUS2_TX,
105 .rqtype = MEMTODEV,
106 }, {
107 .peri_id = (u8)DMACH_SLIMBUS4_RX,
108 .rqtype = DEVTOMEM,
109 }, {
110 .peri_id = (u8)DMACH_SLIMBUS4_TX,
111 .rqtype = MEMTODEV,
112 }, {
113 .peri_id = (u8)DMACH_AC97_MICIN,
114 .rqtype = DEVTOMEM,
115 }, {
116 .peri_id = (u8)DMACH_AC97_PCMIN,
117 .rqtype = DEVTOMEM,
118 }, {
119 .peri_id = (u8)DMACH_AC97_PCMOUT,
120 .rqtype = MEMTODEV,
47 }, 121 },
48}; 122};
49 123
50static struct s3c_pl330_platdata exynos4_pdma0_pdata = { 124struct dma_pl330_platdata exynos4_pdma0_pdata = {
51 .peri = { 125 .nr_valid_peri = ARRAY_SIZE(pdma0_peri),
52 [0] = DMACH_PCM0_RX, 126 .peri = pdma0_peri,
53 [1] = DMACH_PCM0_TX,
54 [2] = DMACH_PCM2_RX,
55 [3] = DMACH_PCM2_TX,
56 [4] = DMACH_MSM_REQ0,
57 [5] = DMACH_MSM_REQ2,
58 [6] = DMACH_SPI0_RX,
59 [7] = DMACH_SPI0_TX,
60 [8] = DMACH_SPI2_RX,
61 [9] = DMACH_SPI2_TX,
62 [10] = DMACH_I2S0S_TX,
63 [11] = DMACH_I2S0_RX,
64 [12] = DMACH_I2S0_TX,
65 [13] = DMACH_I2S2_RX,
66 [14] = DMACH_I2S2_TX,
67 [15] = DMACH_UART0_RX,
68 [16] = DMACH_UART0_TX,
69 [17] = DMACH_UART2_RX,
70 [18] = DMACH_UART2_TX,
71 [19] = DMACH_UART4_RX,
72 [20] = DMACH_UART4_TX,
73 [21] = DMACH_SLIMBUS0_RX,
74 [22] = DMACH_SLIMBUS0_TX,
75 [23] = DMACH_SLIMBUS2_RX,
76 [24] = DMACH_SLIMBUS2_TX,
77 [25] = DMACH_SLIMBUS4_RX,
78 [26] = DMACH_SLIMBUS4_TX,
79 [27] = DMACH_AC97_MICIN,
80 [28] = DMACH_AC97_PCMIN,
81 [29] = DMACH_AC97_PCMOUT,
82 [30] = DMACH_MAX,
83 [31] = DMACH_MAX,
84 },
85}; 127};
86 128
87static struct platform_device exynos4_device_pdma0 = { 129struct amba_device exynos4_device_pdma0 = {
88 .name = "s3c-pl330", 130 .dev = {
89 .id = 0, 131 .init_name = "dma-pl330.0",
90 .num_resources = ARRAY_SIZE(exynos4_pdma0_resource),
91 .resource = exynos4_pdma0_resource,
92 .dev = {
93 .dma_mask = &dma_dmamask, 132 .dma_mask = &dma_dmamask,
94 .coherent_dma_mask = DMA_BIT_MASK(32), 133 .coherent_dma_mask = DMA_BIT_MASK(32),
95 .platform_data = &exynos4_pdma0_pdata, 134 .platform_data = &exynos4_pdma0_pdata,
96 }, 135 },
136 .res = {
137 .start = EXYNOS4_PA_PDMA0,
138 .end = EXYNOS4_PA_PDMA0 + SZ_4K,
139 .flags = IORESOURCE_MEM,
140 },
141 .irq = {IRQ_PDMA0, NO_IRQ},
142 .periphid = 0x00041330,
97}; 143};
98 144
99static struct resource exynos4_pdma1_resource[] = { 145struct dma_pl330_peri pdma1_peri[25] = {
100 [0] = { 146 {
101 .start = EXYNOS4_PA_PDMA1, 147 .peri_id = (u8)DMACH_PCM0_RX,
102 .end = EXYNOS4_PA_PDMA1 + SZ_4K, 148 .rqtype = DEVTOMEM,
103 .flags = IORESOURCE_MEM, 149 }, {
104 }, 150 .peri_id = (u8)DMACH_PCM0_TX,
105 [1] = { 151 .rqtype = MEMTODEV,
106 .start = IRQ_PDMA1, 152 }, {
107 .end = IRQ_PDMA1, 153 .peri_id = (u8)DMACH_PCM1_RX,
108 .flags = IORESOURCE_IRQ, 154 .rqtype = DEVTOMEM,
155 }, {
156 .peri_id = (u8)DMACH_PCM1_TX,
157 .rqtype = MEMTODEV,
158 }, {
159 .peri_id = (u8)DMACH_MSM_REQ1,
160 }, {
161 .peri_id = (u8)DMACH_MSM_REQ3,
162 }, {
163 .peri_id = (u8)DMACH_SPI1_RX,
164 .rqtype = DEVTOMEM,
165 }, {
166 .peri_id = (u8)DMACH_SPI1_TX,
167 .rqtype = MEMTODEV,
168 }, {
169 .peri_id = (u8)DMACH_I2S0S_TX,
170 .rqtype = MEMTODEV,
171 }, {
172 .peri_id = (u8)DMACH_I2S0_RX,
173 .rqtype = DEVTOMEM,
174 }, {
175 .peri_id = (u8)DMACH_I2S0_TX,
176 .rqtype = MEMTODEV,
177 }, {
178 .peri_id = (u8)DMACH_I2S1_RX,
179 .rqtype = DEVTOMEM,
180 }, {
181 .peri_id = (u8)DMACH_I2S1_TX,
182 .rqtype = MEMTODEV,
183 }, {
184 .peri_id = (u8)DMACH_UART0_RX,
185 .rqtype = DEVTOMEM,
186 }, {
187 .peri_id = (u8)DMACH_UART0_TX,
188 .rqtype = MEMTODEV,
189 }, {
190 .peri_id = (u8)DMACH_UART1_RX,
191 .rqtype = DEVTOMEM,
192 }, {
193 .peri_id = (u8)DMACH_UART1_TX,
194 .rqtype = MEMTODEV,
195 }, {
196 .peri_id = (u8)DMACH_UART3_RX,
197 .rqtype = DEVTOMEM,
198 }, {
199 .peri_id = (u8)DMACH_UART3_TX,
200 .rqtype = MEMTODEV,
201 }, {
202 .peri_id = (u8)DMACH_SLIMBUS1_RX,
203 .rqtype = DEVTOMEM,
204 }, {
205 .peri_id = (u8)DMACH_SLIMBUS1_TX,
206 .rqtype = MEMTODEV,
207 }, {
208 .peri_id = (u8)DMACH_SLIMBUS3_RX,
209 .rqtype = DEVTOMEM,
210 }, {
211 .peri_id = (u8)DMACH_SLIMBUS3_TX,
212 .rqtype = MEMTODEV,
213 }, {
214 .peri_id = (u8)DMACH_SLIMBUS5_RX,
215 .rqtype = DEVTOMEM,
216 }, {
217 .peri_id = (u8)DMACH_SLIMBUS5_TX,
218 .rqtype = MEMTODEV,
109 }, 219 },
110}; 220};
111 221
112static struct s3c_pl330_platdata exynos4_pdma1_pdata = { 222struct dma_pl330_platdata exynos4_pdma1_pdata = {
113 .peri = { 223 .nr_valid_peri = ARRAY_SIZE(pdma1_peri),
114 [0] = DMACH_PCM0_RX, 224 .peri = pdma1_peri,
115 [1] = DMACH_PCM0_TX,
116 [2] = DMACH_PCM1_RX,
117 [3] = DMACH_PCM1_TX,
118 [4] = DMACH_MSM_REQ1,
119 [5] = DMACH_MSM_REQ3,
120 [6] = DMACH_SPI1_RX,
121 [7] = DMACH_SPI1_TX,
122 [8] = DMACH_I2S0S_TX,
123 [9] = DMACH_I2S0_RX,
124 [10] = DMACH_I2S0_TX,
125 [11] = DMACH_I2S1_RX,
126 [12] = DMACH_I2S1_TX,
127 [13] = DMACH_UART0_RX,
128 [14] = DMACH_UART0_TX,
129 [15] = DMACH_UART1_RX,
130 [16] = DMACH_UART1_TX,
131 [17] = DMACH_UART3_RX,
132 [18] = DMACH_UART3_TX,
133 [19] = DMACH_SLIMBUS1_RX,
134 [20] = DMACH_SLIMBUS1_TX,
135 [21] = DMACH_SLIMBUS3_RX,
136 [22] = DMACH_SLIMBUS3_TX,
137 [23] = DMACH_SLIMBUS5_RX,
138 [24] = DMACH_SLIMBUS5_TX,
139 [25] = DMACH_SLIMBUS0AUX_RX,
140 [26] = DMACH_SLIMBUS0AUX_TX,
141 [27] = DMACH_SPDIF,
142 [28] = DMACH_MAX,
143 [29] = DMACH_MAX,
144 [30] = DMACH_MAX,
145 [31] = DMACH_MAX,
146 },
147}; 225};
148 226
149static struct platform_device exynos4_device_pdma1 = { 227struct amba_device exynos4_device_pdma1 = {
150 .name = "s3c-pl330", 228 .dev = {
151 .id = 1, 229 .init_name = "dma-pl330.1",
152 .num_resources = ARRAY_SIZE(exynos4_pdma1_resource),
153 .resource = exynos4_pdma1_resource,
154 .dev = {
155 .dma_mask = &dma_dmamask, 230 .dma_mask = &dma_dmamask,
156 .coherent_dma_mask = DMA_BIT_MASK(32), 231 .coherent_dma_mask = DMA_BIT_MASK(32),
157 .platform_data = &exynos4_pdma1_pdata, 232 .platform_data = &exynos4_pdma1_pdata,
158 }, 233 },
159}; 234 .res = {
160 235 .start = EXYNOS4_PA_PDMA1,
161static struct platform_device *exynos4_dmacs[] __initdata = { 236 .end = EXYNOS4_PA_PDMA1 + SZ_4K,
162 &exynos4_device_pdma0, 237 .flags = IORESOURCE_MEM,
163 &exynos4_device_pdma1, 238 },
239 .irq = {IRQ_PDMA1, NO_IRQ},
240 .periphid = 0x00041330,
164}; 241};
165 242
166static int __init exynos4_dma_init(void) 243static int __init exynos4_dma_init(void)
167{ 244{
168 platform_add_devices(exynos4_dmacs, ARRAY_SIZE(exynos4_dmacs)); 245 amba_device_register(&exynos4_device_pdma0, &iomem_resource);
246 amba_device_register(&exynos4_device_pdma1, &iomem_resource);
169 247
170 return 0; 248 return 0;
171} 249}
diff --git a/arch/arm/mach-exynos4/include/mach/dma.h b/arch/arm/mach-exynos4/include/mach/dma.h
index 81209eb1409b..201842a3769e 100644
--- a/arch/arm/mach-exynos4/include/mach/dma.h
+++ b/arch/arm/mach-exynos4/include/mach/dma.h
@@ -20,7 +20,7 @@
20#ifndef __MACH_DMA_H 20#ifndef __MACH_DMA_H
21#define __MACH_DMA_H 21#define __MACH_DMA_H
22 22
23/* This platform uses the common S3C DMA API driver for PL330 */ 23/* This platform uses the common DMA API driver for PL330 */
24#include <plat/s3c-dma-pl330.h> 24#include <plat/dma-pl330.h>
25 25
26#endif /* __MACH_DMA_H */ 26#endif /* __MACH_DMA_H */
diff --git a/arch/arm/mach-exynos4/include/mach/i2c-hdmiphy.h b/arch/arm/mach-exynos4/include/mach/i2c-hdmiphy.h
new file mode 100644
index 000000000000..9dbe3179ad59
--- /dev/null
+++ b/arch/arm/mach-exynos4/include/mach/i2c-hdmiphy.h
@@ -0,0 +1,16 @@
1/*
2 * Copyright (C) 2011 Samsung Electronics Co., Ltd.
3 *
4 * S5P series i2c hdmiphy helper definitions
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 */
10
11#ifndef PLAT_S5P_I2C_HDMIPHY_H_
12#define PLAT_S5P_I2C_HDMIPHY_H_
13
14#define S5P_I2C_HDMIPHY_BUS_NUM (8)
15
16#endif
diff --git a/arch/arm/mach-exynos4/include/mach/irqs.h b/arch/arm/mach-exynos4/include/mach/irqs.h
index f8952f8f3757..62093b9339db 100644
--- a/arch/arm/mach-exynos4/include/mach/irqs.h
+++ b/arch/arm/mach-exynos4/include/mach/irqs.h
@@ -93,7 +93,11 @@
93#define IRQ_2D IRQ_SPI(89) 93#define IRQ_2D IRQ_SPI(89)
94#define IRQ_PCIE IRQ_SPI(90) 94#define IRQ_PCIE IRQ_SPI(90)
95 95
96#define IRQ_MIXER IRQ_SPI(91)
97#define IRQ_HDMI IRQ_SPI(92)
98#define IRQ_IIC_HDMIPHY IRQ_SPI(93)
96#define IRQ_MFC IRQ_SPI(94) 99#define IRQ_MFC IRQ_SPI(94)
100#define IRQ_SDO IRQ_SPI(95)
97 101
98#define IRQ_AUDIO_SS IRQ_SPI(96) 102#define IRQ_AUDIO_SS IRQ_SPI(96)
99#define IRQ_I2S0 IRQ_SPI(97) 103#define IRQ_I2S0 IRQ_SPI(97)
diff --git a/arch/arm/mach-exynos4/include/mach/map.h b/arch/arm/mach-exynos4/include/mach/map.h
index 7073ac730855..1bea7d139bb0 100644
--- a/arch/arm/mach-exynos4/include/mach/map.h
+++ b/arch/arm/mach-exynos4/include/mach/map.h
@@ -113,6 +113,12 @@
113 113
114#define EXYNOS4_PA_UART 0x13800000 114#define EXYNOS4_PA_UART 0x13800000
115 115
116#define EXYNOS4_PA_VP 0x12C00000
117#define EXYNOS4_PA_MIXER 0x12C10000
118#define EXYNOS4_PA_SDO 0x12C20000
119#define EXYNOS4_PA_HDMI 0x12D00000
120#define EXYNOS4_PA_IIC_HDMIPHY 0x138E0000
121
116#define EXYNOS4_PA_IIC(x) (0x13860000 + ((x) * 0x10000)) 122#define EXYNOS4_PA_IIC(x) (0x13860000 + ((x) * 0x10000))
117 123
118#define EXYNOS4_PA_ADC 0x13910000 124#define EXYNOS4_PA_ADC 0x13910000
@@ -162,6 +168,12 @@
162#define S5P_PA_TIMER EXYNOS4_PA_TIMER 168#define S5P_PA_TIMER EXYNOS4_PA_TIMER
163#define S5P_PA_EHCI EXYNOS4_PA_EHCI 169#define S5P_PA_EHCI EXYNOS4_PA_EHCI
164 170
171#define S5P_PA_SDO EXYNOS4_PA_SDO
172#define S5P_PA_VP EXYNOS4_PA_VP
173#define S5P_PA_MIXER EXYNOS4_PA_MIXER
174#define S5P_PA_HDMI EXYNOS4_PA_HDMI
175#define S5P_PA_IIC_HDMIPHY EXYNOS4_PA_IIC_HDMIPHY
176
165#define SAMSUNG_PA_KEYPAD EXYNOS4_PA_KEYPAD 177#define SAMSUNG_PA_KEYPAD EXYNOS4_PA_KEYPAD
166 178
167/* UART */ 179/* UART */
diff --git a/arch/arm/mach-exynos4/include/mach/pm-core.h b/arch/arm/mach-exynos4/include/mach/pm-core.h
index 1df3b81f96e8..9d8da51e35ca 100644
--- a/arch/arm/mach-exynos4/include/mach/pm-core.h
+++ b/arch/arm/mach-exynos4/include/mach/pm-core.h
@@ -14,6 +14,10 @@
14 * it under the terms of the GNU General Public License version 2 as 14 * it under the terms of the GNU General Public License version 2 as
15 * published by the Free Software Foundation. 15 * published by the Free Software Foundation.
16*/ 16*/
17
18#ifndef __ASM_ARCH_PM_CORE_H
19#define __ASM_ARCH_PM_CORE_H __FILE__
20
17#include <mach/regs-pmu.h> 21#include <mach/regs-pmu.h>
18 22
19static inline void s3c_pm_debug_init_uart(void) 23static inline void s3c_pm_debug_init_uart(void)
@@ -53,7 +57,9 @@ static inline void s3c_pm_restored_gpios(void)
53 /* nothing here yet */ 57 /* nothing here yet */
54} 58}
55 59
56static inline void s3c_pm_saved_gpios(void) 60static inline void samsung_pm_saved_gpios(void)
57{ 61{
58 /* nothing here yet */ 62 /* nothing here yet */
59} 63}
64
65#endif /* __ASM_ARCH_PM_CORE_H */
diff --git a/arch/arm/mach-exynos4/include/mach/pmu.h b/arch/arm/mach-exynos4/include/mach/pmu.h
index a952904b010e..632dd5630138 100644
--- a/arch/arm/mach-exynos4/include/mach/pmu.h
+++ b/arch/arm/mach-exynos4/include/mach/pmu.h
@@ -13,6 +13,8 @@
13#ifndef __ASM_ARCH_PMU_H 13#ifndef __ASM_ARCH_PMU_H
14#define __ASM_ARCH_PMU_H __FILE__ 14#define __ASM_ARCH_PMU_H __FILE__
15 15
16#define PMU_TABLE_END NULL
17
16enum sys_powerdown { 18enum sys_powerdown {
17 SYS_AFTR, 19 SYS_AFTR,
18 SYS_LPA, 20 SYS_LPA,
@@ -20,6 +22,11 @@ enum sys_powerdown {
20 NUM_SYS_POWERDOWN, 22 NUM_SYS_POWERDOWN,
21}; 23};
22 24
25struct exynos4_pmu_conf {
26 void __iomem *reg;
27 unsigned int val[NUM_SYS_POWERDOWN];
28};
29
23extern void exynos4_sys_powerdown_conf(enum sys_powerdown mode); 30extern void exynos4_sys_powerdown_conf(enum sys_powerdown mode);
24 31
25#endif /* __ASM_ARCH_PMU_H */ 32#endif /* __ASM_ARCH_PMU_H */
diff --git a/arch/arm/mach-exynos4/include/mach/regs-pmu.h b/arch/arm/mach-exynos4/include/mach/regs-pmu.h
index cdf9b47c303c..4fff8e938fec 100644
--- a/arch/arm/mach-exynos4/include/mach/regs-pmu.h
+++ b/arch/arm/mach-exynos4/include/mach/regs-pmu.h
@@ -25,9 +25,10 @@
25 25
26#define S5P_USE_STANDBY_WFI0 (1 << 16) 26#define S5P_USE_STANDBY_WFI0 (1 << 16)
27#define S5P_USE_STANDBY_WFI1 (1 << 17) 27#define S5P_USE_STANDBY_WFI1 (1 << 17)
28#define S5P_USE_STANDBYWFI_ISP_ARM (1 << 18)
28#define S5P_USE_STANDBY_WFE0 (1 << 24) 29#define S5P_USE_STANDBY_WFE0 (1 << 24)
29#define S5P_USE_STANDBY_WFE1 (1 << 25) 30#define S5P_USE_STANDBY_WFE1 (1 << 25)
30#define S5P_USE_MASK ((0x3 << 16) | (0x3 << 24)) 31#define S5P_USE_STANDBYWFE_ISP_ARM (1 << 26)
31 32
32#define S5P_SWRESET S5P_PMUREG(0x0400) 33#define S5P_SWRESET S5P_PMUREG(0x0400)
33 34
@@ -35,15 +36,17 @@
35#define S5P_EINT_WAKEUP_MASK S5P_PMUREG(0x0604) 36#define S5P_EINT_WAKEUP_MASK S5P_PMUREG(0x0604)
36#define S5P_WAKEUP_MASK S5P_PMUREG(0x0608) 37#define S5P_WAKEUP_MASK S5P_PMUREG(0x0608)
37 38
38#define S5P_USBHOST_PHY_CONTROL S5P_PMUREG(0x0708) 39#define S5P_HDMI_PHY_CONTROL S5P_PMUREG(0x0700)
39#define S5P_USBHOST_PHY_ENABLE (1 << 0) 40#define S5P_HDMI_PHY_ENABLE (1 << 0)
41
42#define S5P_DAC_PHY_CONTROL S5P_PMUREG(0x070C)
43#define S5P_DAC_PHY_ENABLE (1 << 0)
40 44
41#define S5P_MIPI_DPHY_CONTROL(n) S5P_PMUREG(0x0710 + (n) * 4) 45#define S5P_MIPI_DPHY_CONTROL(n) S5P_PMUREG(0x0710 + (n) * 4)
42#define S5P_MIPI_DPHY_ENABLE (1 << 0) 46#define S5P_MIPI_DPHY_ENABLE (1 << 0)
43#define S5P_MIPI_DPHY_SRESETN (1 << 1) 47#define S5P_MIPI_DPHY_SRESETN (1 << 1)
44#define S5P_MIPI_DPHY_MRESETN (1 << 2) 48#define S5P_MIPI_DPHY_MRESETN (1 << 2)
45 49
46#define S5P_PMU_SATA_PHY_CONTROL S5P_PMUREG(0x0720)
47#define S5P_INFORM0 S5P_PMUREG(0x0800) 50#define S5P_INFORM0 S5P_PMUREG(0x0800)
48#define S5P_INFORM1 S5P_PMUREG(0x0804) 51#define S5P_INFORM1 S5P_PMUREG(0x0804)
49#define S5P_INFORM2 S5P_PMUREG(0x0808) 52#define S5P_INFORM2 S5P_PMUREG(0x0808)
@@ -76,7 +79,6 @@
76#define S5P_CMU_CLKSTOP_MFC_LOWPWR S5P_PMUREG(0x1148) 79#define S5P_CMU_CLKSTOP_MFC_LOWPWR S5P_PMUREG(0x1148)
77#define S5P_CMU_CLKSTOP_G3D_LOWPWR S5P_PMUREG(0x114C) 80#define S5P_CMU_CLKSTOP_G3D_LOWPWR S5P_PMUREG(0x114C)
78#define S5P_CMU_CLKSTOP_LCD0_LOWPWR S5P_PMUREG(0x1150) 81#define S5P_CMU_CLKSTOP_LCD0_LOWPWR S5P_PMUREG(0x1150)
79#define S5P_CMU_CLKSTOP_LCD1_LOWPWR S5P_PMUREG(0x1154)
80#define S5P_CMU_CLKSTOP_MAUDIO_LOWPWR S5P_PMUREG(0x1158) 82#define S5P_CMU_CLKSTOP_MAUDIO_LOWPWR S5P_PMUREG(0x1158)
81#define S5P_CMU_CLKSTOP_GPS_LOWPWR S5P_PMUREG(0x115C) 83#define S5P_CMU_CLKSTOP_GPS_LOWPWR S5P_PMUREG(0x115C)
82#define S5P_CMU_RESET_CAM_LOWPWR S5P_PMUREG(0x1160) 84#define S5P_CMU_RESET_CAM_LOWPWR S5P_PMUREG(0x1160)
@@ -84,7 +86,6 @@
84#define S5P_CMU_RESET_MFC_LOWPWR S5P_PMUREG(0x1168) 86#define S5P_CMU_RESET_MFC_LOWPWR S5P_PMUREG(0x1168)
85#define S5P_CMU_RESET_G3D_LOWPWR S5P_PMUREG(0x116C) 87#define S5P_CMU_RESET_G3D_LOWPWR S5P_PMUREG(0x116C)
86#define S5P_CMU_RESET_LCD0_LOWPWR S5P_PMUREG(0x1170) 88#define S5P_CMU_RESET_LCD0_LOWPWR S5P_PMUREG(0x1170)
87#define S5P_CMU_RESET_LCD1_LOWPWR S5P_PMUREG(0x1174)
88#define S5P_CMU_RESET_MAUDIO_LOWPWR S5P_PMUREG(0x1178) 89#define S5P_CMU_RESET_MAUDIO_LOWPWR S5P_PMUREG(0x1178)
89#define S5P_CMU_RESET_GPS_LOWPWR S5P_PMUREG(0x117C) 90#define S5P_CMU_RESET_GPS_LOWPWR S5P_PMUREG(0x117C)
90#define S5P_TOP_BUS_LOWPWR S5P_PMUREG(0x1180) 91#define S5P_TOP_BUS_LOWPWR S5P_PMUREG(0x1180)
@@ -92,14 +93,11 @@
92#define S5P_TOP_PWR_LOWPWR S5P_PMUREG(0x1188) 93#define S5P_TOP_PWR_LOWPWR S5P_PMUREG(0x1188)
93#define S5P_LOGIC_RESET_LOWPWR S5P_PMUREG(0x11A0) 94#define S5P_LOGIC_RESET_LOWPWR S5P_PMUREG(0x11A0)
94#define S5P_ONENAND_MEM_LOWPWR S5P_PMUREG(0x11C0) 95#define S5P_ONENAND_MEM_LOWPWR S5P_PMUREG(0x11C0)
95#define S5P_MODIMIF_MEM_LOWPWR S5P_PMUREG(0x11C4)
96#define S5P_G2D_ACP_MEM_LOWPWR S5P_PMUREG(0x11C8) 96#define S5P_G2D_ACP_MEM_LOWPWR S5P_PMUREG(0x11C8)
97#define S5P_USBOTG_MEM_LOWPWR S5P_PMUREG(0x11CC) 97#define S5P_USBOTG_MEM_LOWPWR S5P_PMUREG(0x11CC)
98#define S5P_HSMMC_MEM_LOWPWR S5P_PMUREG(0x11D0) 98#define S5P_HSMMC_MEM_LOWPWR S5P_PMUREG(0x11D0)
99#define S5P_CSSYS_MEM_LOWPWR S5P_PMUREG(0x11D4) 99#define S5P_CSSYS_MEM_LOWPWR S5P_PMUREG(0x11D4)
100#define S5P_SECSS_MEM_LOWPWR S5P_PMUREG(0x11D8) 100#define S5P_SECSS_MEM_LOWPWR S5P_PMUREG(0x11D8)
101#define S5P_PCIE_MEM_LOWPWR S5P_PMUREG(0x11E0)
102#define S5P_SATA_MEM_LOWPWR S5P_PMUREG(0x11E4)
103#define S5P_PAD_RETENTION_DRAM_LOWPWR S5P_PMUREG(0x1200) 101#define S5P_PAD_RETENTION_DRAM_LOWPWR S5P_PMUREG(0x1200)
104#define S5P_PAD_RETENTION_MAUDIO_LOWPWR S5P_PMUREG(0x1204) 102#define S5P_PAD_RETENTION_MAUDIO_LOWPWR S5P_PMUREG(0x1204)
105#define S5P_PAD_RETENTION_GPIO_LOWPWR S5P_PMUREG(0x1220) 103#define S5P_PAD_RETENTION_GPIO_LOWPWR S5P_PMUREG(0x1220)
@@ -120,7 +118,6 @@
120#define S5P_MFC_LOWPWR S5P_PMUREG(0x1388) 118#define S5P_MFC_LOWPWR S5P_PMUREG(0x1388)
121#define S5P_G3D_LOWPWR S5P_PMUREG(0x138C) 119#define S5P_G3D_LOWPWR S5P_PMUREG(0x138C)
122#define S5P_LCD0_LOWPWR S5P_PMUREG(0x1390) 120#define S5P_LCD0_LOWPWR S5P_PMUREG(0x1390)
123#define S5P_LCD1_LOWPWR S5P_PMUREG(0x1394)
124#define S5P_MAUDIO_LOWPWR S5P_PMUREG(0x1398) 121#define S5P_MAUDIO_LOWPWR S5P_PMUREG(0x1398)
125#define S5P_GPS_LOWPWR S5P_PMUREG(0x139C) 122#define S5P_GPS_LOWPWR S5P_PMUREG(0x139C)
126#define S5P_GPS_ALIVE_LOWPWR S5P_PMUREG(0x13A0) 123#define S5P_GPS_ALIVE_LOWPWR S5P_PMUREG(0x13A0)
@@ -156,7 +153,6 @@
156#define S5P_PMU_MFC_CONF S5P_PMUREG(0x3C40) 153#define S5P_PMU_MFC_CONF S5P_PMUREG(0x3C40)
157#define S5P_PMU_G3D_CONF S5P_PMUREG(0x3C60) 154#define S5P_PMU_G3D_CONF S5P_PMUREG(0x3C60)
158#define S5P_PMU_LCD0_CONF S5P_PMUREG(0x3C80) 155#define S5P_PMU_LCD0_CONF S5P_PMUREG(0x3C80)
159#define S5P_PMU_LCD1_CONF S5P_PMUREG(0x3CA0)
160#define S5P_PMU_GPS_CONF S5P_PMUREG(0x3CE0) 156#define S5P_PMU_GPS_CONF S5P_PMUREG(0x3CE0)
161 157
162#define S5P_PMU_SATA_PHY_CONTROL_EN 0x1 158#define S5P_PMU_SATA_PHY_CONTROL_EN 0x1
@@ -165,4 +161,60 @@
165 161
166#define S5P_CHECK_SLEEP 0x00000BAD 162#define S5P_CHECK_SLEEP 0x00000BAD
167 163
164/* Only for EXYNOS4210 */
165#define S5P_USBHOST_PHY_CONTROL S5P_PMUREG(0x0708)
166#define S5P_USBHOST_PHY_ENABLE (1 << 0)
167
168#define S5P_PMU_SATA_PHY_CONTROL S5P_PMUREG(0x0720)
169
170#define S5P_CMU_CLKSTOP_LCD1_LOWPWR S5P_PMUREG(0x1154)
171#define S5P_CMU_RESET_LCD1_LOWPWR S5P_PMUREG(0x1174)
172#define S5P_MODIMIF_MEM_LOWPWR S5P_PMUREG(0x11C4)
173#define S5P_PCIE_MEM_LOWPWR S5P_PMUREG(0x11E0)
174#define S5P_SATA_MEM_LOWPWR S5P_PMUREG(0x11E4)
175#define S5P_LCD1_LOWPWR S5P_PMUREG(0x1394)
176
177#define S5P_PMU_LCD1_CONF S5P_PMUREG(0x3CA0)
178
179/* Only for EXYNOS4212 */
180#define S5P_ISP_ARM_LOWPWR S5P_PMUREG(0x1050)
181#define S5P_DIS_IRQ_ISP_ARM_LOCAL_LOWPWR S5P_PMUREG(0x1054)
182#define S5P_DIS_IRQ_ISP_ARM_CENTRAL_LOWPWR S5P_PMUREG(0x1058)
183#define S5P_CMU_ACLKSTOP_COREBLK_LOWPWR S5P_PMUREG(0x1110)
184#define S5P_CMU_SCLKSTOP_COREBLK_LOWPWR S5P_PMUREG(0x1114)
185#define S5P_CMU_RESET_COREBLK_LOWPWR S5P_PMUREG(0x111C)
186#define S5P_MPLLUSER_SYSCLK_LOWPWR S5P_PMUREG(0x1130)
187#define S5P_CMU_CLKSTOP_ISP_LOWPWR S5P_PMUREG(0x1154)
188#define S5P_CMU_RESET_ISP_LOWPWR S5P_PMUREG(0x1174)
189#define S5P_TOP_BUS_COREBLK_LOWPWR S5P_PMUREG(0x1190)
190#define S5P_TOP_RETENTION_COREBLK_LOWPWR S5P_PMUREG(0x1194)
191#define S5P_TOP_PWR_COREBLK_LOWPWR S5P_PMUREG(0x1198)
192#define S5P_OSCCLK_GATE_LOWPWR S5P_PMUREG(0x11A4)
193#define S5P_LOGIC_RESET_COREBLK_LOWPWR S5P_PMUREG(0x11B0)
194#define S5P_OSCCLK_GATE_COREBLK_LOWPWR S5P_PMUREG(0x11B4)
195#define S5P_HSI_MEM_LOWPWR S5P_PMUREG(0x11C4)
196#define S5P_ROTATOR_MEM_LOWPWR S5P_PMUREG(0x11DC)
197#define S5P_PAD_RETENTION_GPIO_COREBLK_LOWPWR S5P_PMUREG(0x123C)
198#define S5P_PAD_ISOLATION_COREBLK_LOWPWR S5P_PMUREG(0x1250)
199#define S5P_GPIO_MODE_COREBLK_LOWPWR S5P_PMUREG(0x1320)
200#define S5P_TOP_ASB_RESET_LOWPWR S5P_PMUREG(0x1344)
201#define S5P_TOP_ASB_ISOLATION_LOWPWR S5P_PMUREG(0x1348)
202#define S5P_ISP_LOWPWR S5P_PMUREG(0x1394)
203#define S5P_DRAM_FREQ_DOWN_LOWPWR S5P_PMUREG(0x13B0)
204#define S5P_DDRPHY_DLLOFF_LOWPWR S5P_PMUREG(0x13B4)
205#define S5P_CMU_SYSCLK_ISP_LOWPWR S5P_PMUREG(0x13B8)
206#define S5P_CMU_SYSCLK_GPS_LOWPWR S5P_PMUREG(0x13BC)
207#define S5P_LPDDR_PHY_DLL_LOCK_LOWPWR S5P_PMUREG(0x13C0)
208
209#define S5P_ARM_L2_0_OPTION S5P_PMUREG(0x2608)
210#define S5P_ARM_L2_1_OPTION S5P_PMUREG(0x2628)
211#define S5P_ONENAND_MEM_OPTION S5P_PMUREG(0x2E08)
212#define S5P_HSI_MEM_OPTION S5P_PMUREG(0x2E28)
213#define S5P_G2D_ACP_MEM_OPTION S5P_PMUREG(0x2E48)
214#define S5P_USBOTG_MEM_OPTION S5P_PMUREG(0x2E68)
215#define S5P_HSMMC_MEM_OPTION S5P_PMUREG(0x2E88)
216#define S5P_CSSYS_MEM_OPTION S5P_PMUREG(0x2EA8)
217#define S5P_SECSS_MEM_OPTION S5P_PMUREG(0x2EC8)
218#define S5P_ROTATOR_MEM_OPTION S5P_PMUREG(0x2F48)
219
168#endif /* __ASM_ARCH_REGS_PMU_H */ 220#endif /* __ASM_ARCH_REGS_PMU_H */
diff --git a/arch/arm/mach-exynos4/mach-nuri.c b/arch/arm/mach-exynos4/mach-nuri.c
index 43be71b799cb..bbd13f454151 100644
--- a/arch/arm/mach-exynos4/mach-nuri.c
+++ b/arch/arm/mach-exynos4/mach-nuri.c
@@ -32,10 +32,12 @@
32#include <asm/mach-types.h> 32#include <asm/mach-types.h>
33 33
34#include <plat/adc.h> 34#include <plat/adc.h>
35#include <plat/regs-fb-v4.h>
35#include <plat/regs-serial.h> 36#include <plat/regs-serial.h>
36#include <plat/exynos4.h> 37#include <plat/exynos4.h>
37#include <plat/cpu.h> 38#include <plat/cpu.h>
38#include <plat/devs.h> 39#include <plat/devs.h>
40#include <plat/fb.h>
39#include <plat/sdhci.h> 41#include <plat/sdhci.h>
40#include <plat/ehci.h> 42#include <plat/ehci.h>
41#include <plat/clock.h> 43#include <plat/clock.h>
@@ -199,6 +201,33 @@ static struct platform_device nuri_gpio_keys = {
199 }, 201 },
200}; 202};
201 203
204/* Frame Buffer */
205static struct s3c_fb_pd_win nuri_fb_win0 = {
206 .win_mode = {
207 .left_margin = 64,
208 .right_margin = 16,
209 .upper_margin = 64,
210 .lower_margin = 1,
211 .hsync_len = 48,
212 .vsync_len = 3,
213 .xres = 1280,
214 .yres = 800,
215 .refresh = 60,
216 },
217 .max_bpp = 24,
218 .default_bpp = 16,
219 .virtual_x = 1280,
220 .virtual_y = 800,
221};
222
223static struct s3c_fb_platdata nuri_fb_pdata __initdata = {
224 .win[0] = &nuri_fb_win0,
225 .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB |
226 VIDCON0_CLKSEL_LCD,
227 .vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC,
228 .setup_gpio = exynos4_fimd0_gpio_setup_24bpp,
229};
230
202static void nuri_lcd_power_on(struct plat_lcd_data *pd, unsigned int power) 231static void nuri_lcd_power_on(struct plat_lcd_data *pd, unsigned int power)
203{ 232{
204 int gpio = EXYNOS4_GPE1(5); 233 int gpio = EXYNOS4_GPE1(5);
@@ -1092,6 +1121,7 @@ static struct platform_device *nuri_devices[] __initdata = {
1092 /* Samsung Platform Devices */ 1121 /* Samsung Platform Devices */
1093 &s3c_device_i2c5, /* PMIC should initialize first */ 1122 &s3c_device_i2c5, /* PMIC should initialize first */
1094 &emmc_fixed_voltage, 1123 &emmc_fixed_voltage,
1124 &s5p_device_fimd0,
1095 &s3c_device_hsmmc0, 1125 &s3c_device_hsmmc0,
1096 &s3c_device_hsmmc2, 1126 &s3c_device_hsmmc2,
1097 &s3c_device_hsmmc3, 1127 &s3c_device_hsmmc3,
@@ -1106,6 +1136,7 @@ static struct platform_device *nuri_devices[] __initdata = {
1106 &s5p_device_mfc_l, 1136 &s5p_device_mfc_l,
1107 &s5p_device_mfc_r, 1137 &s5p_device_mfc_r,
1108 &exynos4_device_pd[PD_MFC], 1138 &exynos4_device_pd[PD_MFC],
1139 &exynos4_device_pd[PD_LCD0],
1109 1140
1110 /* NURI Devices */ 1141 /* NURI Devices */
1111 &nuri_gpio_keys, 1142 &nuri_gpio_keys,
@@ -1142,12 +1173,15 @@ static void __init nuri_machine_init(void)
1142 i2c9_devs[I2C9_MAX17042].irq = gpio_to_irq(EXYNOS4_GPX2(3)); 1173 i2c9_devs[I2C9_MAX17042].irq = gpio_to_irq(EXYNOS4_GPX2(3));
1143 i2c_register_board_info(9, i2c9_devs, ARRAY_SIZE(i2c9_devs)); 1174 i2c_register_board_info(9, i2c9_devs, ARRAY_SIZE(i2c9_devs));
1144 1175
1176 s5p_fimd0_set_platdata(&nuri_fb_pdata);
1177
1145 nuri_ehci_init(); 1178 nuri_ehci_init();
1146 clk_xusbxti.rate = 24000000; 1179 clk_xusbxti.rate = 24000000;
1147 1180
1148 /* Last */ 1181 /* Last */
1149 platform_add_devices(nuri_devices, ARRAY_SIZE(nuri_devices)); 1182 platform_add_devices(nuri_devices, ARRAY_SIZE(nuri_devices));
1150 s5p_device_mfc.dev.parent = &exynos4_device_pd[PD_MFC].dev; 1183 s5p_device_mfc.dev.parent = &exynos4_device_pd[PD_MFC].dev;
1184 s5p_device_fimd0.dev.parent = &exynos4_device_pd[PD_LCD0].dev;
1151} 1185}
1152 1186
1153MACHINE_START(NURI, "NURI") 1187MACHINE_START(NURI, "NURI")
diff --git a/arch/arm/mach-exynos4/mach-origen.c b/arch/arm/mach-exynos4/mach-origen.c
index ed59f86001ac..18909cf6c07d 100644
--- a/arch/arm/mach-exynos4/mach-origen.c
+++ b/arch/arm/mach-exynos4/mach-origen.c
@@ -14,16 +14,31 @@
14#include <linux/platform_device.h> 14#include <linux/platform_device.h>
15#include <linux/io.h> 15#include <linux/io.h>
16#include <linux/input.h> 16#include <linux/input.h>
17#include <linux/pwm_backlight.h>
18#include <linux/gpio_keys.h>
19#include <linux/i2c.h>
20#include <linux/regulator/machine.h>
21#include <linux/mfd/max8997.h>
22#include <linux/lcd.h>
17 23
18#include <asm/mach/arch.h> 24#include <asm/mach/arch.h>
19#include <asm/mach-types.h> 25#include <asm/mach-types.h>
20 26
27#include <video/platform_lcd.h>
28
21#include <plat/regs-serial.h> 29#include <plat/regs-serial.h>
30#include <plat/regs-fb-v4.h>
22#include <plat/exynos4.h> 31#include <plat/exynos4.h>
23#include <plat/cpu.h> 32#include <plat/cpu.h>
24#include <plat/devs.h> 33#include <plat/devs.h>
25#include <plat/sdhci.h> 34#include <plat/sdhci.h>
26#include <plat/iic.h> 35#include <plat/iic.h>
36#include <plat/ehci.h>
37#include <plat/clock.h>
38#include <plat/gpio-cfg.h>
39#include <plat/backlight.h>
40#include <plat/pd.h>
41#include <plat/fb.h>
27 42
28#include <mach/map.h> 43#include <mach/map.h>
29 44
@@ -72,19 +87,543 @@ static struct s3c2410_uartcfg origen_uartcfgs[] __initdata = {
72 }, 87 },
73}; 88};
74 89
90static struct regulator_consumer_supply __initdata ldo3_consumer[] = {
91 REGULATOR_SUPPLY("vdd11", "s5p-mipi-csis.0"), /* MIPI */
92};
93static struct regulator_consumer_supply __initdata ldo6_consumer[] = {
94 REGULATOR_SUPPLY("vdd18", "s5p-mipi-csis.0"), /* MIPI */
95};
96static struct regulator_consumer_supply __initdata ldo7_consumer[] = {
97 REGULATOR_SUPPLY("avdd", "alc5625"), /* Realtek ALC5625 */
98};
99static struct regulator_consumer_supply __initdata ldo8_consumer[] = {
100 REGULATOR_SUPPLY("vdd", "s5p-adc"), /* ADC */
101};
102static struct regulator_consumer_supply __initdata ldo9_consumer[] = {
103 REGULATOR_SUPPLY("dvdd", "swb-a31"), /* AR6003 WLAN & CSR 8810 BT */
104};
105static struct regulator_consumer_supply __initdata ldo11_consumer[] = {
106 REGULATOR_SUPPLY("dvdd", "alc5625"), /* Realtek ALC5625 */
107};
108static struct regulator_consumer_supply __initdata ldo14_consumer[] = {
109 REGULATOR_SUPPLY("avdd18", "swb-a31"), /* AR6003 WLAN & CSR 8810 BT */
110};
111static struct regulator_consumer_supply __initdata ldo17_consumer[] = {
112 REGULATOR_SUPPLY("vdd33", "swb-a31"), /* AR6003 WLAN & CSR 8810 BT */
113};
114static struct regulator_consumer_supply __initdata buck1_consumer[] = {
115 REGULATOR_SUPPLY("vdd_arm", NULL), /* CPUFREQ */
116};
117static struct regulator_consumer_supply __initdata buck2_consumer[] = {
118 REGULATOR_SUPPLY("vdd_int", NULL), /* CPUFREQ */
119};
120static struct regulator_consumer_supply __initdata buck3_consumer[] = {
121 REGULATOR_SUPPLY("vdd_g3d", "mali_drm"), /* G3D */
122};
123static struct regulator_consumer_supply __initdata buck7_consumer[] = {
124 REGULATOR_SUPPLY("vcc", "platform-lcd"), /* LCD */
125};
126
127static struct regulator_init_data __initdata max8997_ldo1_data = {
128 .constraints = {
129 .name = "VDD_ABB_3.3V",
130 .min_uV = 3300000,
131 .max_uV = 3300000,
132 .apply_uV = 1,
133 .state_mem = {
134 .disabled = 1,
135 },
136 },
137};
138
139static struct regulator_init_data __initdata max8997_ldo2_data = {
140 .constraints = {
141 .name = "VDD_ALIVE_1.1V",
142 .min_uV = 1100000,
143 .max_uV = 1100000,
144 .apply_uV = 1,
145 .always_on = 1,
146 .state_mem = {
147 .enabled = 1,
148 },
149 },
150};
151
152static struct regulator_init_data __initdata max8997_ldo3_data = {
153 .constraints = {
154 .name = "VMIPI_1.1V",
155 .min_uV = 1100000,
156 .max_uV = 1100000,
157 .apply_uV = 1,
158 .valid_ops_mask = REGULATOR_CHANGE_STATUS,
159 .state_mem = {
160 .disabled = 1,
161 },
162 },
163 .num_consumer_supplies = ARRAY_SIZE(ldo3_consumer),
164 .consumer_supplies = ldo3_consumer,
165};
166
167static struct regulator_init_data __initdata max8997_ldo4_data = {
168 .constraints = {
169 .name = "VDD_RTC_1.8V",
170 .min_uV = 1800000,
171 .max_uV = 1800000,
172 .apply_uV = 1,
173 .always_on = 1,
174 .state_mem = {
175 .disabled = 1,
176 },
177 },
178};
179
180static struct regulator_init_data __initdata max8997_ldo6_data = {
181 .constraints = {
182 .name = "VMIPI_1.8V",
183 .min_uV = 1800000,
184 .max_uV = 1800000,
185 .apply_uV = 1,
186 .valid_ops_mask = REGULATOR_CHANGE_STATUS,
187 .state_mem = {
188 .disabled = 1,
189 },
190 },
191 .num_consumer_supplies = ARRAY_SIZE(ldo6_consumer),
192 .consumer_supplies = ldo6_consumer,
193};
194
195static struct regulator_init_data __initdata max8997_ldo7_data = {
196 .constraints = {
197 .name = "VDD_AUD_1.8V",
198 .min_uV = 1800000,
199 .max_uV = 1800000,
200 .apply_uV = 1,
201 .valid_ops_mask = REGULATOR_CHANGE_STATUS,
202 .state_mem = {
203 .disabled = 1,
204 },
205 },
206 .num_consumer_supplies = ARRAY_SIZE(ldo7_consumer),
207 .consumer_supplies = ldo7_consumer,
208};
209
210static struct regulator_init_data __initdata max8997_ldo8_data = {
211 .constraints = {
212 .name = "VADC_3.3V",
213 .min_uV = 3300000,
214 .max_uV = 3300000,
215 .apply_uV = 1,
216 .valid_ops_mask = REGULATOR_CHANGE_STATUS,
217 .state_mem = {
218 .disabled = 1,
219 },
220 },
221 .num_consumer_supplies = ARRAY_SIZE(ldo8_consumer),
222 .consumer_supplies = ldo8_consumer,
223};
224
225static struct regulator_init_data __initdata max8997_ldo9_data = {
226 .constraints = {
227 .name = "DVDD_SWB_2.8V",
228 .min_uV = 2800000,
229 .max_uV = 2800000,
230 .apply_uV = 1,
231 .valid_ops_mask = REGULATOR_CHANGE_STATUS,
232 .state_mem = {
233 .disabled = 1,
234 },
235 },
236 .num_consumer_supplies = ARRAY_SIZE(ldo9_consumer),
237 .consumer_supplies = ldo9_consumer,
238};
239
240static struct regulator_init_data __initdata max8997_ldo10_data = {
241 .constraints = {
242 .name = "VDD_PLL_1.1V",
243 .min_uV = 1100000,
244 .max_uV = 1100000,
245 .apply_uV = 1,
246 .always_on = 1,
247 .state_mem = {
248 .disabled = 1,
249 },
250 },
251};
252
253static struct regulator_init_data __initdata max8997_ldo11_data = {
254 .constraints = {
255 .name = "VDD_AUD_3V",
256 .min_uV = 3000000,
257 .max_uV = 3000000,
258 .apply_uV = 1,
259 .valid_ops_mask = REGULATOR_CHANGE_STATUS,
260 .state_mem = {
261 .disabled = 1,
262 },
263 },
264 .num_consumer_supplies = ARRAY_SIZE(ldo11_consumer),
265 .consumer_supplies = ldo11_consumer,
266};
267
268static struct regulator_init_data __initdata max8997_ldo14_data = {
269 .constraints = {
270 .name = "AVDD18_SWB_1.8V",
271 .min_uV = 1800000,
272 .max_uV = 1800000,
273 .apply_uV = 1,
274 .valid_ops_mask = REGULATOR_CHANGE_STATUS,
275 .state_mem = {
276 .disabled = 1,
277 },
278 },
279 .num_consumer_supplies = ARRAY_SIZE(ldo14_consumer),
280 .consumer_supplies = ldo14_consumer,
281};
282
283static struct regulator_init_data __initdata max8997_ldo17_data = {
284 .constraints = {
285 .name = "VDD_SWB_3.3V",
286 .min_uV = 3300000,
287 .max_uV = 3300000,
288 .apply_uV = 1,
289 .valid_ops_mask = REGULATOR_CHANGE_STATUS,
290 .state_mem = {
291 .disabled = 1,
292 },
293 },
294 .num_consumer_supplies = ARRAY_SIZE(ldo17_consumer),
295 .consumer_supplies = ldo17_consumer,
296};
297
298static struct regulator_init_data __initdata max8997_ldo21_data = {
299 .constraints = {
300 .name = "VDD_MIF_1.2V",
301 .min_uV = 1200000,
302 .max_uV = 1200000,
303 .apply_uV = 1,
304 .always_on = 1,
305 .state_mem = {
306 .disabled = 1,
307 },
308 },
309};
310
311static struct regulator_init_data __initdata max8997_buck1_data = {
312 .constraints = {
313 .name = "VDD_ARM_1.2V",
314 .min_uV = 950000,
315 .max_uV = 1350000,
316 .always_on = 1,
317 .boot_on = 1,
318 .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
319 .state_mem = {
320 .disabled = 1,
321 },
322 },
323 .num_consumer_supplies = ARRAY_SIZE(buck1_consumer),
324 .consumer_supplies = buck1_consumer,
325};
326
327static struct regulator_init_data __initdata max8997_buck2_data = {
328 .constraints = {
329 .name = "VDD_INT_1.1V",
330 .min_uV = 900000,
331 .max_uV = 1100000,
332 .always_on = 1,
333 .boot_on = 1,
334 .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
335 .state_mem = {
336 .disabled = 1,
337 },
338 },
339 .num_consumer_supplies = ARRAY_SIZE(buck2_consumer),
340 .consumer_supplies = buck2_consumer,
341};
342
343static struct regulator_init_data __initdata max8997_buck3_data = {
344 .constraints = {
345 .name = "VDD_G3D_1.1V",
346 .min_uV = 900000,
347 .max_uV = 1100000,
348 .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
349 REGULATOR_CHANGE_STATUS,
350 .state_mem = {
351 .disabled = 1,
352 },
353 },
354 .num_consumer_supplies = ARRAY_SIZE(buck3_consumer),
355 .consumer_supplies = buck3_consumer,
356};
357
358static struct regulator_init_data __initdata max8997_buck5_data = {
359 .constraints = {
360 .name = "VDDQ_M1M2_1.2V",
361 .min_uV = 1200000,
362 .max_uV = 1200000,
363 .apply_uV = 1,
364 .always_on = 1,
365 .state_mem = {
366 .disabled = 1,
367 },
368 },
369};
370
371static struct regulator_init_data __initdata max8997_buck7_data = {
372 .constraints = {
373 .name = "VDD_LCD_3.3V",
374 .min_uV = 3300000,
375 .max_uV = 3300000,
376 .boot_on = 1,
377 .apply_uV = 1,
378 .valid_ops_mask = REGULATOR_CHANGE_STATUS,
379 .state_mem = {
380 .disabled = 1
381 },
382 },
383 .num_consumer_supplies = ARRAY_SIZE(buck7_consumer),
384 .consumer_supplies = buck7_consumer,
385};
386
387static struct max8997_regulator_data __initdata origen_max8997_regulators[] = {
388 { MAX8997_LDO1, &max8997_ldo1_data },
389 { MAX8997_LDO2, &max8997_ldo2_data },
390 { MAX8997_LDO3, &max8997_ldo3_data },
391 { MAX8997_LDO4, &max8997_ldo4_data },
392 { MAX8997_LDO6, &max8997_ldo6_data },
393 { MAX8997_LDO7, &max8997_ldo7_data },
394 { MAX8997_LDO8, &max8997_ldo8_data },
395 { MAX8997_LDO9, &max8997_ldo9_data },
396 { MAX8997_LDO10, &max8997_ldo10_data },
397 { MAX8997_LDO11, &max8997_ldo11_data },
398 { MAX8997_LDO14, &max8997_ldo14_data },
399 { MAX8997_LDO17, &max8997_ldo17_data },
400 { MAX8997_LDO21, &max8997_ldo21_data },
401 { MAX8997_BUCK1, &max8997_buck1_data },
402 { MAX8997_BUCK2, &max8997_buck2_data },
403 { MAX8997_BUCK3, &max8997_buck3_data },
404 { MAX8997_BUCK5, &max8997_buck5_data },
405 { MAX8997_BUCK7, &max8997_buck7_data },
406};
407
408struct max8997_platform_data __initdata origen_max8997_pdata = {
409 .num_regulators = ARRAY_SIZE(origen_max8997_regulators),
410 .regulators = origen_max8997_regulators,
411
412 .wakeup = true,
413 .buck1_gpiodvs = false,
414 .buck2_gpiodvs = false,
415 .buck5_gpiodvs = false,
416 .irq_base = IRQ_GPIO_END + 1,
417
418 .ignore_gpiodvs_side_effect = true,
419 .buck125_default_idx = 0x0,
420
421 .buck125_gpios[0] = EXYNOS4_GPX0(0),
422 .buck125_gpios[1] = EXYNOS4_GPX0(1),
423 .buck125_gpios[2] = EXYNOS4_GPX0(2),
424
425 .buck1_voltage[0] = 1350000,
426 .buck1_voltage[1] = 1300000,
427 .buck1_voltage[2] = 1250000,
428 .buck1_voltage[3] = 1200000,
429 .buck1_voltage[4] = 1150000,
430 .buck1_voltage[5] = 1100000,
431 .buck1_voltage[6] = 1000000,
432 .buck1_voltage[7] = 950000,
433
434 .buck2_voltage[0] = 1100000,
435 .buck2_voltage[1] = 1100000,
436 .buck2_voltage[2] = 1100000,
437 .buck2_voltage[3] = 1100000,
438 .buck2_voltage[4] = 1000000,
439 .buck2_voltage[5] = 1000000,
440 .buck2_voltage[6] = 1000000,
441 .buck2_voltage[7] = 1000000,
442
443 .buck5_voltage[0] = 1200000,
444 .buck5_voltage[1] = 1200000,
445 .buck5_voltage[2] = 1200000,
446 .buck5_voltage[3] = 1200000,
447 .buck5_voltage[4] = 1200000,
448 .buck5_voltage[5] = 1200000,
449 .buck5_voltage[6] = 1200000,
450 .buck5_voltage[7] = 1200000,
451};
452
453/* I2C0 */
454static struct i2c_board_info i2c0_devs[] __initdata = {
455 {
456 I2C_BOARD_INFO("max8997", (0xCC >> 1)),
457 .platform_data = &origen_max8997_pdata,
458 .irq = IRQ_EINT(4),
459 },
460};
461
462static struct s3c_sdhci_platdata origen_hsmmc0_pdata __initdata = {
463 .cd_type = S3C_SDHCI_CD_INTERNAL,
464 .clk_type = S3C_SDHCI_CLK_DIV_EXTERNAL,
465};
466
75static struct s3c_sdhci_platdata origen_hsmmc2_pdata __initdata = { 467static struct s3c_sdhci_platdata origen_hsmmc2_pdata __initdata = {
76 .cd_type = S3C_SDHCI_CD_GPIO, 468 .cd_type = S3C_SDHCI_CD_INTERNAL,
77 .ext_cd_gpio = EXYNOS4_GPK2(2),
78 .ext_cd_gpio_invert = 1,
79 .clk_type = S3C_SDHCI_CLK_DIV_EXTERNAL, 469 .clk_type = S3C_SDHCI_CLK_DIV_EXTERNAL,
80}; 470};
81 471
472/* USB EHCI */
473static struct s5p_ehci_platdata origen_ehci_pdata;
474
475static void __init origen_ehci_init(void)
476{
477 struct s5p_ehci_platdata *pdata = &origen_ehci_pdata;
478
479 s5p_ehci_set_platdata(pdata);
480}
481
482static struct gpio_keys_button origen_gpio_keys_table[] = {
483 {
484 .code = KEY_MENU,
485 .gpio = EXYNOS4_GPX1(5),
486 .desc = "gpio-keys: KEY_MENU",
487 .type = EV_KEY,
488 .active_low = 1,
489 .wakeup = 1,
490 .debounce_interval = 1,
491 }, {
492 .code = KEY_HOME,
493 .gpio = EXYNOS4_GPX1(6),
494 .desc = "gpio-keys: KEY_HOME",
495 .type = EV_KEY,
496 .active_low = 1,
497 .wakeup = 1,
498 .debounce_interval = 1,
499 }, {
500 .code = KEY_BACK,
501 .gpio = EXYNOS4_GPX1(7),
502 .desc = "gpio-keys: KEY_BACK",
503 .type = EV_KEY,
504 .active_low = 1,
505 .wakeup = 1,
506 .debounce_interval = 1,
507 }, {
508 .code = KEY_UP,
509 .gpio = EXYNOS4_GPX2(0),
510 .desc = "gpio-keys: KEY_UP",
511 .type = EV_KEY,
512 .active_low = 1,
513 .wakeup = 1,
514 .debounce_interval = 1,
515 }, {
516 .code = KEY_DOWN,
517 .gpio = EXYNOS4_GPX2(1),
518 .desc = "gpio-keys: KEY_DOWN",
519 .type = EV_KEY,
520 .active_low = 1,
521 .wakeup = 1,
522 .debounce_interval = 1,
523 },
524};
525
526static struct gpio_keys_platform_data origen_gpio_keys_data = {
527 .buttons = origen_gpio_keys_table,
528 .nbuttons = ARRAY_SIZE(origen_gpio_keys_table),
529};
530
531static struct platform_device origen_device_gpiokeys = {
532 .name = "gpio-keys",
533 .dev = {
534 .platform_data = &origen_gpio_keys_data,
535 },
536};
537
538static void lcd_hv070wsa_set_power(struct plat_lcd_data *pd, unsigned int power)
539{
540 int ret;
541
542 if (power)
543 ret = gpio_request_one(EXYNOS4_GPE3(4),
544 GPIOF_OUT_INIT_HIGH, "GPE3_4");
545 else
546 ret = gpio_request_one(EXYNOS4_GPE3(4),
547 GPIOF_OUT_INIT_LOW, "GPE3_4");
548
549 gpio_free(EXYNOS4_GPE3(4));
550
551 if (ret)
552 pr_err("failed to request gpio for LCD power: %d\n", ret);
553}
554
555static struct plat_lcd_data origen_lcd_hv070wsa_data = {
556 .set_power = lcd_hv070wsa_set_power,
557};
558
559static struct platform_device origen_lcd_hv070wsa = {
560 .name = "platform-lcd",
561 .dev.parent = &s5p_device_fimd0.dev,
562 .dev.platform_data = &origen_lcd_hv070wsa_data,
563};
564
565static struct s3c_fb_pd_win origen_fb_win0 = {
566 .win_mode = {
567 .left_margin = 64,
568 .right_margin = 16,
569 .upper_margin = 64,
570 .lower_margin = 16,
571 .hsync_len = 48,
572 .vsync_len = 3,
573 .xres = 1024,
574 .yres = 600,
575 },
576 .max_bpp = 32,
577 .default_bpp = 24,
578};
579
580static struct s3c_fb_platdata origen_lcd_pdata __initdata = {
581 .win[0] = &origen_fb_win0,
582 .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB,
583 .vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC,
584 .setup_gpio = exynos4_fimd0_gpio_setup_24bpp,
585};
586
82static struct platform_device *origen_devices[] __initdata = { 587static struct platform_device *origen_devices[] __initdata = {
83 &s3c_device_hsmmc2, 588 &s3c_device_hsmmc2,
589 &s3c_device_hsmmc0,
590 &s3c_device_i2c0,
84 &s3c_device_rtc, 591 &s3c_device_rtc,
85 &s3c_device_wdt, 592 &s3c_device_wdt,
593 &s5p_device_ehci,
594 &s5p_device_fimc0,
595 &s5p_device_fimc1,
596 &s5p_device_fimc2,
597 &s5p_device_fimc3,
598 &s5p_device_fimd0,
599 &s5p_device_hdmi,
600 &s5p_device_i2c_hdmiphy,
601 &s5p_device_mixer,
602 &exynos4_device_pd[PD_LCD0],
603 &exynos4_device_pd[PD_TV],
604 &origen_device_gpiokeys,
605 &origen_lcd_hv070wsa,
606};
607
608/* LCD Backlight data */
609static struct samsung_bl_gpio_info origen_bl_gpio_info = {
610 .no = EXYNOS4_GPD0(0),
611 .func = S3C_GPIO_SFN(2),
86}; 612};
87 613
614static struct platform_pwm_backlight_data origen_bl_data = {
615 .pwm_id = 0,
616 .pwm_period_ns = 1000,
617};
618
619static void s5p_tv_setup(void)
620{
621 /* Direct HPD to HDMI chip */
622 gpio_request_one(EXYNOS4_GPX3(7), GPIOF_IN, "hpd-plug");
623 s3c_gpio_cfgpin(EXYNOS4_GPX3(7), S3C_GPIO_SFN(0x3));
624 s3c_gpio_setpull(EXYNOS4_GPX3(7), S3C_GPIO_PULL_NONE);
625}
626
88static void __init origen_map_io(void) 627static void __init origen_map_io(void)
89{ 628{
90 s5p_init_io(NULL, 0, S5P_VA_CHIPID); 629 s5p_init_io(NULL, 0, S5P_VA_CHIPID);
@@ -92,10 +631,42 @@ static void __init origen_map_io(void)
92 s3c24xx_init_uarts(origen_uartcfgs, ARRAY_SIZE(origen_uartcfgs)); 631 s3c24xx_init_uarts(origen_uartcfgs, ARRAY_SIZE(origen_uartcfgs));
93} 632}
94 633
634static void __init origen_power_init(void)
635{
636 gpio_request(EXYNOS4_GPX0(4), "PMIC_IRQ");
637 s3c_gpio_cfgpin(EXYNOS4_GPX0(4), S3C_GPIO_SFN(0xf));
638 s3c_gpio_setpull(EXYNOS4_GPX0(4), S3C_GPIO_PULL_NONE);
639}
640
95static void __init origen_machine_init(void) 641static void __init origen_machine_init(void)
96{ 642{
643 origen_power_init();
644
645 s3c_i2c0_set_platdata(NULL);
646 i2c_register_board_info(0, i2c0_devs, ARRAY_SIZE(i2c0_devs));
647
648 /*
649 * Since sdhci instance 2 can contain a bootable media,
650 * sdhci instance 0 is registered after instance 2.
651 */
97 s3c_sdhci2_set_platdata(&origen_hsmmc2_pdata); 652 s3c_sdhci2_set_platdata(&origen_hsmmc2_pdata);
653 s3c_sdhci0_set_platdata(&origen_hsmmc0_pdata);
654
655 origen_ehci_init();
656 clk_xusbxti.rate = 24000000;
657
658 s5p_tv_setup();
659 s5p_i2c_hdmiphy_set_platdata(NULL);
660
661 s5p_fimd0_set_platdata(&origen_lcd_pdata);
662
98 platform_add_devices(origen_devices, ARRAY_SIZE(origen_devices)); 663 platform_add_devices(origen_devices, ARRAY_SIZE(origen_devices));
664 s5p_device_fimd0.dev.parent = &exynos4_device_pd[PD_LCD0].dev;
665
666 s5p_device_hdmi.dev.parent = &exynos4_device_pd[PD_TV].dev;
667 s5p_device_mixer.dev.parent = &exynos4_device_pd[PD_TV].dev;
668
669 samsung_bl_set(&origen_bl_gpio_info, &origen_bl_data);
99} 670}
100 671
101MACHINE_START(ORIGEN, "ORIGEN") 672MACHINE_START(ORIGEN, "ORIGEN")
diff --git a/arch/arm/mach-exynos4/mach-smdkv310.c b/arch/arm/mach-exynos4/mach-smdkv310.c
index a16eb569a3e6..35a763e9a659 100644
--- a/arch/arm/mach-exynos4/mach-smdkv310.c
+++ b/arch/arm/mach-exynos4/mach-smdkv310.c
@@ -37,6 +37,9 @@
37#include <plat/pd.h> 37#include <plat/pd.h>
38#include <plat/gpio-cfg.h> 38#include <plat/gpio-cfg.h>
39#include <plat/backlight.h> 39#include <plat/backlight.h>
40#include <plat/mfc.h>
41#include <plat/ehci.h>
42#include <plat/clock.h>
40 43
41#include <mach/map.h> 44#include <mach/map.h>
42 45
@@ -232,17 +235,36 @@ static struct i2c_board_info i2c_devs1[] __initdata = {
232 {I2C_BOARD_INFO("wm8994", 0x1a),}, 235 {I2C_BOARD_INFO("wm8994", 0x1a),},
233}; 236};
234 237
238/* USB EHCI */
239static struct s5p_ehci_platdata smdkv310_ehci_pdata;
240
241static void __init smdkv310_ehci_init(void)
242{
243 struct s5p_ehci_platdata *pdata = &smdkv310_ehci_pdata;
244
245 s5p_ehci_set_platdata(pdata);
246}
247
235static struct platform_device *smdkv310_devices[] __initdata = { 248static struct platform_device *smdkv310_devices[] __initdata = {
236 &s3c_device_hsmmc0, 249 &s3c_device_hsmmc0,
237 &s3c_device_hsmmc1, 250 &s3c_device_hsmmc1,
238 &s3c_device_hsmmc2, 251 &s3c_device_hsmmc2,
239 &s3c_device_hsmmc3, 252 &s3c_device_hsmmc3,
240 &s3c_device_i2c1, 253 &s3c_device_i2c1,
254 &s5p_device_i2c_hdmiphy,
241 &s3c_device_rtc, 255 &s3c_device_rtc,
242 &s3c_device_wdt, 256 &s3c_device_wdt,
257 &s5p_device_ehci,
258 &s5p_device_fimc0,
259 &s5p_device_fimc1,
260 &s5p_device_fimc2,
261 &s5p_device_fimc3,
243 &exynos4_device_ac97, 262 &exynos4_device_ac97,
244 &exynos4_device_i2s0, 263 &exynos4_device_i2s0,
245 &samsung_device_keypad, 264 &samsung_device_keypad,
265 &s5p_device_mfc,
266 &s5p_device_mfc_l,
267 &s5p_device_mfc_r,
246 &exynos4_device_pd[PD_MFC], 268 &exynos4_device_pd[PD_MFC],
247 &exynos4_device_pd[PD_G3D], 269 &exynos4_device_pd[PD_G3D],
248 &exynos4_device_pd[PD_LCD0], 270 &exynos4_device_pd[PD_LCD0],
@@ -258,6 +280,8 @@ static struct platform_device *smdkv310_devices[] __initdata = {
258 &smdkv310_lcd_lte480wv, 280 &smdkv310_lcd_lte480wv,
259 &smdkv310_smsc911x, 281 &smdkv310_smsc911x,
260 &exynos4_device_ahci, 282 &exynos4_device_ahci,
283 &s5p_device_hdmi,
284 &s5p_device_mixer,
261}; 285};
262 286
263static void __init smdkv310_smsc911x_init(void) 287static void __init smdkv310_smsc911x_init(void)
@@ -294,6 +318,18 @@ static struct platform_pwm_backlight_data smdkv310_bl_data = {
294 .pwm_period_ns = 1000, 318 .pwm_period_ns = 1000,
295}; 319};
296 320
321static void s5p_tv_setup(void)
322{
323 /* direct HPD to HDMI chip */
324 WARN_ON(gpio_request_one(EXYNOS4_GPX3(7), GPIOF_IN, "hpd-plug"));
325 s3c_gpio_cfgpin(EXYNOS4_GPX3(7), S3C_GPIO_SFN(0x3));
326 s3c_gpio_setpull(EXYNOS4_GPX3(7), S3C_GPIO_PULL_NONE);
327
328 /* setup dependencies between TV devices */
329 s5p_device_hdmi.dev.parent = &exynos4_device_pd[PD_TV].dev;
330 s5p_device_mixer.dev.parent = &exynos4_device_pd[PD_TV].dev;
331}
332
297static void __init smdkv310_map_io(void) 333static void __init smdkv310_map_io(void)
298{ 334{
299 s5p_init_io(NULL, 0, S5P_VA_CHIPID); 335 s5p_init_io(NULL, 0, S5P_VA_CHIPID);
@@ -301,6 +337,11 @@ static void __init smdkv310_map_io(void)
301 s3c24xx_init_uarts(smdkv310_uartcfgs, ARRAY_SIZE(smdkv310_uartcfgs)); 337 s3c24xx_init_uarts(smdkv310_uartcfgs, ARRAY_SIZE(smdkv310_uartcfgs));
302} 338}
303 339
340static void __init smdkv310_reserve(void)
341{
342 s5p_mfc_reserve_mem(0x43000000, 8 << 20, 0x51000000, 8 << 20);
343}
344
304static void __init smdkv310_machine_init(void) 345static void __init smdkv310_machine_init(void)
305{ 346{
306 s3c_i2c1_set_platdata(NULL); 347 s3c_i2c1_set_platdata(NULL);
@@ -313,12 +354,19 @@ static void __init smdkv310_machine_init(void)
313 s3c_sdhci2_set_platdata(&smdkv310_hsmmc2_pdata); 354 s3c_sdhci2_set_platdata(&smdkv310_hsmmc2_pdata);
314 s3c_sdhci3_set_platdata(&smdkv310_hsmmc3_pdata); 355 s3c_sdhci3_set_platdata(&smdkv310_hsmmc3_pdata);
315 356
357 s5p_tv_setup();
358 s5p_i2c_hdmiphy_set_platdata(NULL);
359
316 samsung_keypad_set_platdata(&smdkv310_keypad_data); 360 samsung_keypad_set_platdata(&smdkv310_keypad_data);
317 361
318 samsung_bl_set(&smdkv310_bl_gpio_info, &smdkv310_bl_data); 362 samsung_bl_set(&smdkv310_bl_gpio_info, &smdkv310_bl_data);
319 s5p_fimd0_set_platdata(&smdkv310_lcd0_pdata); 363 s5p_fimd0_set_platdata(&smdkv310_lcd0_pdata);
320 364
365 smdkv310_ehci_init();
366 clk_xusbxti.rate = 24000000;
367
321 platform_add_devices(smdkv310_devices, ARRAY_SIZE(smdkv310_devices)); 368 platform_add_devices(smdkv310_devices, ARRAY_SIZE(smdkv310_devices));
369 s5p_device_mfc.dev.parent = &exynos4_device_pd[PD_MFC].dev;
322} 370}
323 371
324MACHINE_START(SMDKV310, "SMDKV310") 372MACHINE_START(SMDKV310, "SMDKV310")
@@ -329,6 +377,7 @@ MACHINE_START(SMDKV310, "SMDKV310")
329 .map_io = smdkv310_map_io, 377 .map_io = smdkv310_map_io,
330 .init_machine = smdkv310_machine_init, 378 .init_machine = smdkv310_machine_init,
331 .timer = &exynos4_timer, 379 .timer = &exynos4_timer,
380 .reserve = &smdkv310_reserve,
332MACHINE_END 381MACHINE_END
333 382
334MACHINE_START(SMDKC210, "SMDKC210") 383MACHINE_START(SMDKC210, "SMDKC210")
diff --git a/arch/arm/mach-exynos4/mach-universal_c210.c b/arch/arm/mach-exynos4/mach-universal_c210.c
index b3b5d8911004..18cf5c7cf56d 100644
--- a/arch/arm/mach-exynos4/mach-universal_c210.c
+++ b/arch/arm/mach-exynos4/mach-universal_c210.c
@@ -13,6 +13,7 @@
13#include <linux/i2c.h> 13#include <linux/i2c.h>
14#include <linux/gpio_keys.h> 14#include <linux/gpio_keys.h>
15#include <linux/gpio.h> 15#include <linux/gpio.h>
16#include <linux/fb.h>
16#include <linux/mfd/max8998.h> 17#include <linux/mfd/max8998.h>
17#include <linux/regulator/machine.h> 18#include <linux/regulator/machine.h>
18#include <linux/regulator/fixed.h> 19#include <linux/regulator/fixed.h>
@@ -31,12 +32,21 @@
31#include <plat/devs.h> 32#include <plat/devs.h>
32#include <plat/iic.h> 33#include <plat/iic.h>
33#include <plat/gpio-cfg.h> 34#include <plat/gpio-cfg.h>
35#include <plat/fb.h>
34#include <plat/mfc.h> 36#include <plat/mfc.h>
35#include <plat/sdhci.h> 37#include <plat/sdhci.h>
36#include <plat/pd.h> 38#include <plat/pd.h>
39#include <plat/regs-fb-v4.h>
40#include <plat/fimc-core.h>
41#include <plat/camport.h>
42#include <plat/mipi_csis.h>
37 43
38#include <mach/map.h> 44#include <mach/map.h>
39 45
46#include <media/v4l2-mediabus.h>
47#include <media/s5p_fimc.h>
48#include <media/m5mols.h>
49
40/* Following are default values for UCON, ULCON and UFCON UART registers */ 50/* Following are default values for UCON, ULCON and UFCON UART registers */
41#define UNIVERSAL_UCON_DEFAULT (S3C2410_UCON_TXILEVEL | \ 51#define UNIVERSAL_UCON_DEFAULT (S3C2410_UCON_TXILEVEL | \
42 S3C2410_UCON_RXILEVEL | \ 52 S3C2410_UCON_RXILEVEL | \
@@ -110,6 +120,9 @@ static struct regulator_consumer_supply lp3974_buck1_consumer =
110static struct regulator_consumer_supply lp3974_buck2_consumer = 120static struct regulator_consumer_supply lp3974_buck2_consumer =
111 REGULATOR_SUPPLY("vddg3d", NULL); 121 REGULATOR_SUPPLY("vddg3d", NULL);
112 122
123static struct regulator_consumer_supply lp3974_buck3_consumer =
124 REGULATOR_SUPPLY("vdet", "s5p-sdo");
125
113static struct regulator_init_data lp3974_buck1_data = { 126static struct regulator_init_data lp3974_buck1_data = {
114 .constraints = { 127 .constraints = {
115 .name = "VINT_1.1V", 128 .name = "VINT_1.1V",
@@ -153,6 +166,8 @@ static struct regulator_init_data lp3974_buck3_data = {
153 .enabled = 1, 166 .enabled = 1,
154 }, 167 },
155 }, 168 },
169 .num_consumer_supplies = 1,
170 .consumer_supplies = &lp3974_buck3_consumer,
156}; 171};
157 172
158static struct regulator_init_data lp3974_buck4_data = { 173static struct regulator_init_data lp3974_buck4_data = {
@@ -181,6 +196,12 @@ static struct regulator_init_data lp3974_ldo2_data = {
181 }, 196 },
182}; 197};
183 198
199static struct regulator_consumer_supply lp3974_ldo3_consumer[] = {
200 REGULATOR_SUPPLY("vdd", "exynos4-hdmi"),
201 REGULATOR_SUPPLY("vdd_pll", "exynos4-hdmi"),
202 REGULATOR_SUPPLY("vdd11", "s5p-mipi-csis.0"),
203};
204
184static struct regulator_init_data lp3974_ldo3_data = { 205static struct regulator_init_data lp3974_ldo3_data = {
185 .constraints = { 206 .constraints = {
186 .name = "VUSB+MIPI_1.1V", 207 .name = "VUSB+MIPI_1.1V",
@@ -192,6 +213,12 @@ static struct regulator_init_data lp3974_ldo3_data = {
192 .disabled = 1, 213 .disabled = 1,
193 }, 214 },
194 }, 215 },
216 .num_consumer_supplies = ARRAY_SIZE(lp3974_ldo3_consumer),
217 .consumer_supplies = lp3974_ldo3_consumer,
218};
219
220static struct regulator_consumer_supply lp3974_ldo4_consumer[] = {
221 REGULATOR_SUPPLY("vdd_osc", "exynos4-hdmi"),
195}; 222};
196 223
197static struct regulator_init_data lp3974_ldo4_data = { 224static struct regulator_init_data lp3974_ldo4_data = {
@@ -205,6 +232,8 @@ static struct regulator_init_data lp3974_ldo4_data = {
205 .disabled = 1, 232 .disabled = 1,
206 }, 233 },
207 }, 234 },
235 .num_consumer_supplies = ARRAY_SIZE(lp3974_ldo4_consumer),
236 .consumer_supplies = lp3974_ldo4_consumer,
208}; 237};
209 238
210static struct regulator_init_data lp3974_ldo5_data = { 239static struct regulator_init_data lp3974_ldo5_data = {
@@ -233,6 +262,10 @@ static struct regulator_init_data lp3974_ldo6_data = {
233 }, 262 },
234}; 263};
235 264
265static struct regulator_consumer_supply lp3974_ldo7_consumer[] = {
266 REGULATOR_SUPPLY("vdd18", "s5p-mipi-csis.0"),
267};
268
236static struct regulator_init_data lp3974_ldo7_data = { 269static struct regulator_init_data lp3974_ldo7_data = {
237 .constraints = { 270 .constraints = {
238 .name = "VLCD+VMIPI_1.8V", 271 .name = "VLCD+VMIPI_1.8V",
@@ -244,6 +277,12 @@ static struct regulator_init_data lp3974_ldo7_data = {
244 .disabled = 1, 277 .disabled = 1,
245 }, 278 },
246 }, 279 },
280 .num_consumer_supplies = ARRAY_SIZE(lp3974_ldo7_consumer),
281 .consumer_supplies = lp3974_ldo7_consumer,
282};
283
284static struct regulator_consumer_supply lp3974_ldo8_consumer[] = {
285 REGULATOR_SUPPLY("vdd33a_dac", "s5p-sdo"),
247}; 286};
248 287
249static struct regulator_init_data lp3974_ldo8_data = { 288static struct regulator_init_data lp3974_ldo8_data = {
@@ -257,6 +296,8 @@ static struct regulator_init_data lp3974_ldo8_data = {
257 .disabled = 1, 296 .disabled = 1,
258 }, 297 },
259 }, 298 },
299 .num_consumer_supplies = ARRAY_SIZE(lp3974_ldo8_consumer),
300 .consumer_supplies = lp3974_ldo8_consumer,
260}; 301};
261 302
262static struct regulator_init_data lp3974_ldo9_data = { 303static struct regulator_init_data lp3974_ldo9_data = {
@@ -286,6 +327,9 @@ static struct regulator_init_data lp3974_ldo10_data = {
286 }, 327 },
287}; 328};
288 329
330static struct regulator_consumer_supply lp3974_ldo11_consumer =
331 REGULATOR_SUPPLY("dig_28", "0-001f");
332
289static struct regulator_init_data lp3974_ldo11_data = { 333static struct regulator_init_data lp3974_ldo11_data = {
290 .constraints = { 334 .constraints = {
291 .name = "CAM_AF_3.3V", 335 .name = "CAM_AF_3.3V",
@@ -297,6 +341,8 @@ static struct regulator_init_data lp3974_ldo11_data = {
297 .disabled = 1, 341 .disabled = 1,
298 }, 342 },
299 }, 343 },
344 .num_consumer_supplies = 1,
345 .consumer_supplies = &lp3974_ldo11_consumer,
300}; 346};
301 347
302static struct regulator_init_data lp3974_ldo12_data = { 348static struct regulator_init_data lp3974_ldo12_data = {
@@ -325,6 +371,9 @@ static struct regulator_init_data lp3974_ldo13_data = {
325 }, 371 },
326}; 372};
327 373
374static struct regulator_consumer_supply lp3974_ldo14_consumer =
375 REGULATOR_SUPPLY("dig_18", "0-001f");
376
328static struct regulator_init_data lp3974_ldo14_data = { 377static struct regulator_init_data lp3974_ldo14_data = {
329 .constraints = { 378 .constraints = {
330 .name = "CAM_I_HOST_1.8V", 379 .name = "CAM_I_HOST_1.8V",
@@ -336,8 +385,14 @@ static struct regulator_init_data lp3974_ldo14_data = {
336 .disabled = 1, 385 .disabled = 1,
337 }, 386 },
338 }, 387 },
388 .num_consumer_supplies = 1,
389 .consumer_supplies = &lp3974_ldo14_consumer,
339}; 390};
340 391
392
393static struct regulator_consumer_supply lp3974_ldo15_consumer =
394 REGULATOR_SUPPLY("dig_12", "0-001f");
395
341static struct regulator_init_data lp3974_ldo15_data = { 396static struct regulator_init_data lp3974_ldo15_data = {
342 .constraints = { 397 .constraints = {
343 .name = "CAM_S_DIG+FM33_CORE_1.2V", 398 .name = "CAM_S_DIG+FM33_CORE_1.2V",
@@ -349,6 +404,12 @@ static struct regulator_init_data lp3974_ldo15_data = {
349 .disabled = 1, 404 .disabled = 1,
350 }, 405 },
351 }, 406 },
407 .num_consumer_supplies = 1,
408 .consumer_supplies = &lp3974_ldo15_consumer,
409};
410
411static struct regulator_consumer_supply lp3974_ldo16_consumer[] = {
412 REGULATOR_SUPPLY("a_sensor", "0-001f"),
352}; 413};
353 414
354static struct regulator_init_data lp3974_ldo16_data = { 415static struct regulator_init_data lp3974_ldo16_data = {
@@ -362,6 +423,8 @@ static struct regulator_init_data lp3974_ldo16_data = {
362 .disabled = 1, 423 .disabled = 1,
363 }, 424 },
364 }, 425 },
426 .num_consumer_supplies = ARRAY_SIZE(lp3974_ldo16_consumer),
427 .consumer_supplies = lp3974_ldo16_consumer,
365}; 428};
366 429
367static struct regulator_init_data lp3974_ldo17_data = { 430static struct regulator_init_data lp3974_ldo17_data = {
@@ -472,6 +535,43 @@ static struct max8998_platform_data universal_lp3974_pdata = {
472 .wakeup = true, 535 .wakeup = true,
473}; 536};
474 537
538
539enum fixed_regulator_id {
540 FIXED_REG_ID_MMC0,
541 FIXED_REG_ID_HDMI_5V,
542 FIXED_REG_ID_CAM_S_IF,
543 FIXED_REG_ID_CAM_I_CORE,
544 FIXED_REG_ID_CAM_VT_DIO,
545};
546
547static struct regulator_consumer_supply hdmi_fixed_consumer =
548 REGULATOR_SUPPLY("hdmi-en", "exynos4-hdmi");
549
550static struct regulator_init_data hdmi_fixed_voltage_init_data = {
551 .constraints = {
552 .name = "HDMI_5V",
553 .valid_ops_mask = REGULATOR_CHANGE_STATUS,
554 },
555 .num_consumer_supplies = 1,
556 .consumer_supplies = &hdmi_fixed_consumer,
557};
558
559static struct fixed_voltage_config hdmi_fixed_voltage_config = {
560 .supply_name = "HDMI_EN1",
561 .microvolts = 5000000,
562 .gpio = EXYNOS4_GPE0(1),
563 .enable_high = true,
564 .init_data = &hdmi_fixed_voltage_init_data,
565};
566
567static struct platform_device hdmi_fixed_voltage = {
568 .name = "reg-fixed-voltage",
569 .id = FIXED_REG_ID_HDMI_5V,
570 .dev = {
571 .platform_data = &hdmi_fixed_voltage_config,
572 },
573};
574
475/* GPIO I2C 5 (PMIC) */ 575/* GPIO I2C 5 (PMIC) */
476static struct i2c_board_info i2c5_devs[] __initdata = { 576static struct i2c_board_info i2c5_devs[] __initdata = {
477 { 577 {
@@ -573,6 +673,11 @@ static void __init universal_touchkey_init(void)
573 gpio_direction_output(gpio, 1); 673 gpio_direction_output(gpio, 1);
574} 674}
575 675
676static struct s3c2410_platform_i2c universal_i2c0_platdata __initdata = {
677 .frequency = 300 * 1000,
678 .sda_delay = 200,
679};
680
576/* GPIO KEYS */ 681/* GPIO KEYS */
577static struct gpio_keys_button universal_gpio_keys_tables[] = { 682static struct gpio_keys_button universal_gpio_keys_tables[] = {
578 { 683 {
@@ -658,7 +763,7 @@ static struct fixed_voltage_config mmc0_fixed_voltage_config = {
658 763
659static struct platform_device mmc0_fixed_voltage = { 764static struct platform_device mmc0_fixed_voltage = {
660 .name = "reg-fixed-voltage", 765 .name = "reg-fixed-voltage",
661 .id = 0, 766 .id = FIXED_REG_ID_MMC0,
662 .dev = { 767 .dev = {
663 .platform_data = &mmc0_fixed_voltage_config, 768 .platform_data = &mmc0_fixed_voltage_config,
664 }, 769 },
@@ -692,18 +797,170 @@ static void __init universal_sdhci_init(void)
692 s3c_sdhci3_set_platdata(&universal_hsmmc3_data); 797 s3c_sdhci3_set_platdata(&universal_hsmmc3_data);
693} 798}
694 799
695/* I2C0 */
696static struct i2c_board_info i2c0_devs[] __initdata = {
697 /* Camera, To be updated */
698};
699
700/* I2C1 */ 800/* I2C1 */
701static struct i2c_board_info i2c1_devs[] __initdata = { 801static struct i2c_board_info i2c1_devs[] __initdata = {
702 /* Gyro, To be updated */ 802 /* Gyro, To be updated */
703}; 803};
704 804
805/* Frame Buffer */
806static struct s3c_fb_pd_win universal_fb_win0 = {
807 .win_mode = {
808 .left_margin = 16,
809 .right_margin = 16,
810 .upper_margin = 2,
811 .lower_margin = 28,
812 .hsync_len = 2,
813 .vsync_len = 1,
814 .xres = 480,
815 .yres = 800,
816 .refresh = 55,
817 },
818 .max_bpp = 32,
819 .default_bpp = 16,
820};
821
822static struct s3c_fb_platdata universal_lcd_pdata __initdata = {
823 .win[0] = &universal_fb_win0,
824 .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB |
825 VIDCON0_CLKSEL_LCD,
826 .vidcon1 = VIDCON1_INV_VCLK | VIDCON1_INV_VDEN
827 | VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC,
828 .setup_gpio = exynos4_fimd0_gpio_setup_24bpp,
829};
830
831static struct regulator_consumer_supply cam_i_core_supply =
832 REGULATOR_SUPPLY("core", "0-001f");
833
834static struct regulator_init_data cam_i_core_reg_init_data = {
835 .constraints = { .valid_ops_mask = REGULATOR_CHANGE_STATUS },
836 .num_consumer_supplies = 1,
837 .consumer_supplies = &cam_i_core_supply,
838};
839
840static struct fixed_voltage_config cam_i_core_fixed_voltage_cfg = {
841 .supply_name = "CAM_I_CORE_1.2V",
842 .microvolts = 1200000,
843 .gpio = EXYNOS4_GPE2(2), /* CAM_8M_CORE_EN */
844 .enable_high = 1,
845 .init_data = &cam_i_core_reg_init_data,
846};
847
848static struct platform_device cam_i_core_fixed_reg_dev = {
849 .name = "reg-fixed-voltage", .id = FIXED_REG_ID_CAM_I_CORE,
850 .dev = { .platform_data = &cam_i_core_fixed_voltage_cfg },
851};
852
853static struct regulator_consumer_supply cam_s_if_supply =
854 REGULATOR_SUPPLY("d_sensor", "0-001f");
855
856static struct regulator_init_data cam_s_if_reg_init_data = {
857 .constraints = { .valid_ops_mask = REGULATOR_CHANGE_STATUS },
858 .num_consumer_supplies = 1,
859 .consumer_supplies = &cam_s_if_supply,
860};
861
862static struct fixed_voltage_config cam_s_if_fixed_voltage_cfg = {
863 .supply_name = "CAM_S_IF_1.8V",
864 .microvolts = 1800000,
865 .gpio = EXYNOS4_GPE3(0), /* CAM_PWR_EN1 */
866 .enable_high = 1,
867 .init_data = &cam_s_if_reg_init_data,
868};
869
870static struct platform_device cam_s_if_fixed_reg_dev = {
871 .name = "reg-fixed-voltage", .id = FIXED_REG_ID_CAM_S_IF,
872 .dev = { .platform_data = &cam_s_if_fixed_voltage_cfg },
873};
874
875static struct s5p_platform_mipi_csis mipi_csis_platdata = {
876 .clk_rate = 166000000UL,
877 .lanes = 2,
878 .alignment = 32,
879 .hs_settle = 12,
880 .phy_enable = s5p_csis_phy_enable,
881};
882
883#define GPIO_CAM_LEVEL_EN(n) EXYNOS4_GPE4(n + 3)
884#define GPIO_CAM_8M_ISP_INT EXYNOS4_GPX1(5) /* XEINT_13 */
885#define GPIO_CAM_MEGA_nRST EXYNOS4_GPE2(5)
886
887static int m5mols_set_power(struct device *dev, int on)
888{
889 gpio_set_value(GPIO_CAM_LEVEL_EN(1), !on);
890 gpio_set_value(GPIO_CAM_LEVEL_EN(2), !!on);
891 return 0;
892}
893
894static struct m5mols_platform_data m5mols_platdata = {
895 .gpio_reset = GPIO_CAM_MEGA_nRST,
896 .reset_polarity = 0,
897 .set_power = m5mols_set_power,
898};
899
900static struct i2c_board_info m5mols_board_info = {
901 I2C_BOARD_INFO("M5MOLS", 0x1F),
902 .platform_data = &m5mols_platdata,
903};
904
905static struct s5p_fimc_isp_info universal_camera_sensors[] = {
906 {
907 .mux_id = 0,
908 .flags = V4L2_MBUS_PCLK_SAMPLE_FALLING |
909 V4L2_MBUS_VSYNC_ACTIVE_LOW,
910 .bus_type = FIMC_MIPI_CSI2,
911 .board_info = &m5mols_board_info,
912 .i2c_bus_num = 0,
913 .clk_frequency = 21600000UL,
914 .csi_data_align = 32,
915 },
916};
917
918static struct s5p_platform_fimc fimc_md_platdata = {
919 .isp_info = universal_camera_sensors,
920 .num_clients = ARRAY_SIZE(universal_camera_sensors),
921};
922
923struct platform_device s5p_device_fimc_md = {
924 .name = "s5p-fimc-md",
925 .id = -1,
926};
927
928static struct gpio universal_camera_gpios[] = {
929 { GPIO_CAM_LEVEL_EN(1), GPIOF_OUT_INIT_HIGH, "CAM_LVL_EN1" },
930 { GPIO_CAM_LEVEL_EN(2), GPIOF_OUT_INIT_LOW, "CAM_LVL_EN2" },
931 { GPIO_CAM_8M_ISP_INT, GPIOF_IN, "8M_ISP_INT" },
932 { GPIO_CAM_MEGA_nRST, GPIOF_OUT_INIT_LOW, "CAM_8M_NRST" },
933};
934
935static void universal_camera_init(void)
936{
937 s3c_set_platdata(&mipi_csis_platdata, sizeof(mipi_csis_platdata),
938 &s5p_device_mipi_csis0);
939 s3c_set_platdata(&fimc_md_platdata, sizeof(fimc_md_platdata),
940 &s5p_device_fimc_md);
941
942 if (gpio_request_array(universal_camera_gpios,
943 ARRAY_SIZE(universal_camera_gpios))) {
944 pr_err("%s: GPIO request failed\n", __func__);
945 return;
946 }
947
948 if (!s3c_gpio_cfgpin(GPIO_CAM_8M_ISP_INT, S3C_GPIO_SFN(0xf)))
949 m5mols_board_info.irq = gpio_to_irq(GPIO_CAM_8M_ISP_INT);
950 else
951 pr_err("Failed to configure 8M_ISP_INT GPIO\n");
952
953 /* Free GPIOs controlled directly by the sensor drivers. */
954 gpio_free(GPIO_CAM_MEGA_nRST);
955 gpio_free(GPIO_CAM_8M_ISP_INT);
956
957 if (exynos4_fimc_setup_gpio(S5P_CAMPORT_A))
958 pr_err("Camera port A setup failed\n");
959}
960
705static struct platform_device *universal_devices[] __initdata = { 961static struct platform_device *universal_devices[] __initdata = {
706 /* Samsung Platform Devices */ 962 /* Samsung Platform Devices */
963 &s5p_device_mipi_csis0,
707 &s5p_device_fimc0, 964 &s5p_device_fimc0,
708 &s5p_device_fimc1, 965 &s5p_device_fimc1,
709 &s5p_device_fimc2, 966 &s5p_device_fimc2,
@@ -712,17 +969,30 @@ static struct platform_device *universal_devices[] __initdata = {
712 &s3c_device_hsmmc0, 969 &s3c_device_hsmmc0,
713 &s3c_device_hsmmc2, 970 &s3c_device_hsmmc2,
714 &s3c_device_hsmmc3, 971 &s3c_device_hsmmc3,
972 &s3c_device_i2c0,
715 &s3c_device_i2c3, 973 &s3c_device_i2c3,
716 &s3c_device_i2c5, 974 &s3c_device_i2c5,
975 &s5p_device_i2c_hdmiphy,
976 &hdmi_fixed_voltage,
977 &exynos4_device_pd[PD_TV],
978 &s5p_device_hdmi,
979 &s5p_device_sdo,
980 &s5p_device_mixer,
717 981
718 /* Universal Devices */ 982 /* Universal Devices */
719 &i2c_gpio12, 983 &i2c_gpio12,
720 &universal_gpio_keys, 984 &universal_gpio_keys,
721 &s5p_device_onenand, 985 &s5p_device_onenand,
986 &s5p_device_fimd0,
722 &s5p_device_mfc, 987 &s5p_device_mfc,
723 &s5p_device_mfc_l, 988 &s5p_device_mfc_l,
724 &s5p_device_mfc_r, 989 &s5p_device_mfc_r,
725 &exynos4_device_pd[PD_MFC], 990 &exynos4_device_pd[PD_MFC],
991 &exynos4_device_pd[PD_LCD0],
992 &exynos4_device_pd[PD_CAM],
993 &cam_i_core_fixed_reg_dev,
994 &cam_s_if_fixed_reg_dev,
995 &s5p_device_fimc_md,
726}; 996};
727 997
728static void __init universal_map_io(void) 998static void __init universal_map_io(void)
@@ -732,6 +1002,20 @@ static void __init universal_map_io(void)
732 s3c24xx_init_uarts(universal_uartcfgs, ARRAY_SIZE(universal_uartcfgs)); 1002 s3c24xx_init_uarts(universal_uartcfgs, ARRAY_SIZE(universal_uartcfgs));
733} 1003}
734 1004
1005void s5p_tv_setup(void)
1006{
1007 /* direct HPD to HDMI chip */
1008 gpio_request(EXYNOS4_GPX3(7), "hpd-plug");
1009
1010 gpio_direction_input(EXYNOS4_GPX3(7));
1011 s3c_gpio_cfgpin(EXYNOS4_GPX3(7), S3C_GPIO_SFN(0x3));
1012 s3c_gpio_setpull(EXYNOS4_GPX3(7), S3C_GPIO_PULL_NONE);
1013
1014 /* setup dependencies between TV devices */
1015 s5p_device_hdmi.dev.parent = &exynos4_device_pd[PD_TV].dev;
1016 s5p_device_mixer.dev.parent = &exynos4_device_pd[PD_TV].dev;
1017}
1018
735static void __init universal_reserve(void) 1019static void __init universal_reserve(void)
736{ 1020{
737 s5p_mfc_reserve_mem(0x43000000, 8 << 20, 0x51000000, 8 << 20); 1021 s5p_mfc_reserve_mem(0x43000000, 8 << 20, 0x51000000, 8 << 20);
@@ -740,8 +1024,9 @@ static void __init universal_reserve(void)
740static void __init universal_machine_init(void) 1024static void __init universal_machine_init(void)
741{ 1025{
742 universal_sdhci_init(); 1026 universal_sdhci_init();
1027 s5p_tv_setup();
743 1028
744 i2c_register_board_info(0, i2c0_devs, ARRAY_SIZE(i2c0_devs)); 1029 s3c_i2c0_set_platdata(&universal_i2c0_platdata);
745 i2c_register_board_info(1, i2c1_devs, ARRAY_SIZE(i2c1_devs)); 1030 i2c_register_board_info(1, i2c1_devs, ARRAY_SIZE(i2c1_devs));
746 1031
747 universal_tsp_init(); 1032 universal_tsp_init();
@@ -749,15 +1034,28 @@ static void __init universal_machine_init(void)
749 i2c_register_board_info(3, i2c3_devs, ARRAY_SIZE(i2c3_devs)); 1034 i2c_register_board_info(3, i2c3_devs, ARRAY_SIZE(i2c3_devs));
750 1035
751 s3c_i2c5_set_platdata(NULL); 1036 s3c_i2c5_set_platdata(NULL);
1037 s5p_i2c_hdmiphy_set_platdata(NULL);
752 i2c_register_board_info(5, i2c5_devs, ARRAY_SIZE(i2c5_devs)); 1038 i2c_register_board_info(5, i2c5_devs, ARRAY_SIZE(i2c5_devs));
753 1039
1040 s5p_fimd0_set_platdata(&universal_lcd_pdata);
1041
754 universal_touchkey_init(); 1042 universal_touchkey_init();
755 i2c_register_board_info(I2C_GPIO_BUS_12, i2c_gpio12_devs, 1043 i2c_register_board_info(I2C_GPIO_BUS_12, i2c_gpio12_devs,
756 ARRAY_SIZE(i2c_gpio12_devs)); 1044 ARRAY_SIZE(i2c_gpio12_devs));
757 1045
1046 universal_camera_init();
1047
758 /* Last */ 1048 /* Last */
759 platform_add_devices(universal_devices, ARRAY_SIZE(universal_devices)); 1049 platform_add_devices(universal_devices, ARRAY_SIZE(universal_devices));
1050
760 s5p_device_mfc.dev.parent = &exynos4_device_pd[PD_MFC].dev; 1051 s5p_device_mfc.dev.parent = &exynos4_device_pd[PD_MFC].dev;
1052 s5p_device_fimd0.dev.parent = &exynos4_device_pd[PD_LCD0].dev;
1053
1054 s5p_device_fimc0.dev.parent = &exynos4_device_pd[PD_CAM].dev;
1055 s5p_device_fimc1.dev.parent = &exynos4_device_pd[PD_CAM].dev;
1056 s5p_device_fimc2.dev.parent = &exynos4_device_pd[PD_CAM].dev;
1057 s5p_device_fimc3.dev.parent = &exynos4_device_pd[PD_CAM].dev;
1058 s5p_device_mipi_csis0.dev.parent = &exynos4_device_pd[PD_CAM].dev;
761} 1059}
762 1060
763MACHINE_START(UNIVERSAL_C210, "UNIVERSAL_C210") 1061MACHINE_START(UNIVERSAL_C210, "UNIVERSAL_C210")
diff --git a/arch/arm/mach-exynos4/pm.c b/arch/arm/mach-exynos4/pm.c
index 62e4f4363006..509a435afd4b 100644
--- a/arch/arm/mach-exynos4/pm.c
+++ b/arch/arm/mach-exynos4/pm.c
@@ -339,6 +339,13 @@ static int exynos4_pm_suspend(void)
339 tmp &= ~S5P_CENTRAL_LOWPWR_CFG; 339 tmp &= ~S5P_CENTRAL_LOWPWR_CFG;
340 __raw_writel(tmp, S5P_CENTRAL_SEQ_CONFIGURATION); 340 __raw_writel(tmp, S5P_CENTRAL_SEQ_CONFIGURATION);
341 341
342 if (soc_is_exynos4212()) {
343 tmp = __raw_readl(S5P_CENTRAL_SEQ_OPTION);
344 tmp &= ~(S5P_USE_STANDBYWFI_ISP_ARM |
345 S5P_USE_STANDBYWFE_ISP_ARM);
346 __raw_writel(tmp, S5P_CENTRAL_SEQ_OPTION);
347 }
348
342 /* Save Power control register */ 349 /* Save Power control register */
343 asm ("mrc p15, 0, %0, c15, c0, 0" 350 asm ("mrc p15, 0, %0, c15, c0, 0"
344 : "=r" (tmp) : : "cc"); 351 : "=r" (tmp) : : "cc");
diff --git a/arch/arm/mach-exynos4/pmu.c b/arch/arm/mach-exynos4/pmu.c
index 7ea9eb2a20d2..bba48f5c3e8f 100644
--- a/arch/arm/mach-exynos4/pmu.c
+++ b/arch/arm/mach-exynos4/pmu.c
@@ -16,160 +16,215 @@
16#include <mach/regs-clock.h> 16#include <mach/regs-clock.h>
17#include <mach/pmu.h> 17#include <mach/pmu.h>
18 18
19static void __iomem *sys_powerdown_reg[] = { 19static struct exynos4_pmu_conf *exynos4_pmu_config;
20 S5P_ARM_CORE0_LOWPWR, 20
21 S5P_DIS_IRQ_CORE0, 21static struct exynos4_pmu_conf exynos4210_pmu_config[] = {
22 S5P_DIS_IRQ_CENTRAL0, 22 /* { .reg = address, .val = { AFTR, LPA, SLEEP } */
23 S5P_ARM_CORE1_LOWPWR, 23 { S5P_ARM_CORE0_LOWPWR, { 0x0, 0x0, 0x2 } },
24 S5P_DIS_IRQ_CORE1, 24 { S5P_DIS_IRQ_CORE0, { 0x0, 0x0, 0x0 } },
25 S5P_DIS_IRQ_CENTRAL1, 25 { S5P_DIS_IRQ_CENTRAL0, { 0x0, 0x0, 0x0 } },
26 S5P_ARM_COMMON_LOWPWR, 26 { S5P_ARM_CORE1_LOWPWR, { 0x0, 0x0, 0x2 } },
27 S5P_L2_0_LOWPWR, 27 { S5P_DIS_IRQ_CORE1, { 0x0, 0x0, 0x0 } },
28 S5P_L2_1_LOWPWR, 28 { S5P_DIS_IRQ_CENTRAL1, { 0x0, 0x0, 0x0 } },
29 S5P_CMU_ACLKSTOP_LOWPWR, 29 { S5P_ARM_COMMON_LOWPWR, { 0x0, 0x0, 0x2 } },
30 S5P_CMU_SCLKSTOP_LOWPWR, 30 { S5P_L2_0_LOWPWR, { 0x2, 0x2, 0x3 } },
31 S5P_CMU_RESET_LOWPWR, 31 { S5P_L2_1_LOWPWR, { 0x2, 0x2, 0x3 } },
32 S5P_APLL_SYSCLK_LOWPWR, 32 { S5P_CMU_ACLKSTOP_LOWPWR, { 0x1, 0x0, 0x0 } },
33 S5P_MPLL_SYSCLK_LOWPWR, 33 { S5P_CMU_SCLKSTOP_LOWPWR, { 0x1, 0x0, 0x0 } },
34 S5P_VPLL_SYSCLK_LOWPWR, 34 { S5P_CMU_RESET_LOWPWR, { 0x1, 0x1, 0x0 } },
35 S5P_EPLL_SYSCLK_LOWPWR, 35 { S5P_APLL_SYSCLK_LOWPWR, { 0x1, 0x0, 0x0 } },
36 S5P_CMU_CLKSTOP_GPS_ALIVE_LOWPWR, 36 { S5P_MPLL_SYSCLK_LOWPWR, { 0x1, 0x0, 0x0 } },
37 S5P_CMU_RESET_GPSALIVE_LOWPWR, 37 { S5P_VPLL_SYSCLK_LOWPWR, { 0x1, 0x0, 0x0 } },
38 S5P_CMU_CLKSTOP_CAM_LOWPWR, 38 { S5P_EPLL_SYSCLK_LOWPWR, { 0x1, 0x1, 0x0 } },
39 S5P_CMU_CLKSTOP_TV_LOWPWR, 39 { S5P_CMU_CLKSTOP_GPS_ALIVE_LOWPWR, { 0x1, 0x1, 0x0 } },
40 S5P_CMU_CLKSTOP_MFC_LOWPWR, 40 { S5P_CMU_RESET_GPSALIVE_LOWPWR, { 0x1, 0x1, 0x0 } },
41 S5P_CMU_CLKSTOP_G3D_LOWPWR, 41 { S5P_CMU_CLKSTOP_CAM_LOWPWR, { 0x1, 0x1, 0x0 } },
42 S5P_CMU_CLKSTOP_LCD0_LOWPWR, 42 { S5P_CMU_CLKSTOP_TV_LOWPWR, { 0x1, 0x1, 0x0 } },
43 S5P_CMU_CLKSTOP_LCD1_LOWPWR, 43 { S5P_CMU_CLKSTOP_MFC_LOWPWR, { 0x1, 0x1, 0x0 } },
44 S5P_CMU_CLKSTOP_MAUDIO_LOWPWR, 44 { S5P_CMU_CLKSTOP_G3D_LOWPWR, { 0x1, 0x1, 0x0 } },
45 S5P_CMU_CLKSTOP_GPS_LOWPWR, 45 { S5P_CMU_CLKSTOP_LCD0_LOWPWR, { 0x1, 0x1, 0x0 } },
46 S5P_CMU_RESET_CAM_LOWPWR, 46 { S5P_CMU_CLKSTOP_LCD1_LOWPWR, { 0x1, 0x1, 0x0 } },
47 S5P_CMU_RESET_TV_LOWPWR, 47 { S5P_CMU_CLKSTOP_MAUDIO_LOWPWR, { 0x1, 0x1, 0x0 } },
48 S5P_CMU_RESET_MFC_LOWPWR, 48 { S5P_CMU_CLKSTOP_GPS_LOWPWR, { 0x1, 0x1, 0x0 } },
49 S5P_CMU_RESET_G3D_LOWPWR, 49 { S5P_CMU_RESET_CAM_LOWPWR, { 0x1, 0x1, 0x0 } },
50 S5P_CMU_RESET_LCD0_LOWPWR, 50 { S5P_CMU_RESET_TV_LOWPWR, { 0x1, 0x1, 0x0 } },
51 S5P_CMU_RESET_LCD1_LOWPWR, 51 { S5P_CMU_RESET_MFC_LOWPWR, { 0x1, 0x1, 0x0 } },
52 S5P_CMU_RESET_MAUDIO_LOWPWR, 52 { S5P_CMU_RESET_G3D_LOWPWR, { 0x1, 0x1, 0x0 } },
53 S5P_CMU_RESET_GPS_LOWPWR, 53 { S5P_CMU_RESET_LCD0_LOWPWR, { 0x1, 0x1, 0x0 } },
54 S5P_TOP_BUS_LOWPWR, 54 { S5P_CMU_RESET_LCD1_LOWPWR, { 0x1, 0x1, 0x0 } },
55 S5P_TOP_RETENTION_LOWPWR, 55 { S5P_CMU_RESET_MAUDIO_LOWPWR, { 0x1, 0x1, 0x0 } },
56 S5P_TOP_PWR_LOWPWR, 56 { S5P_CMU_RESET_GPS_LOWPWR, { 0x1, 0x1, 0x0 } },
57 S5P_LOGIC_RESET_LOWPWR, 57 { S5P_TOP_BUS_LOWPWR, { 0x3, 0x0, 0x0 } },
58 S5P_ONENAND_MEM_LOWPWR, 58 { S5P_TOP_RETENTION_LOWPWR, { 0x1, 0x0, 0x1 } },
59 S5P_MODIMIF_MEM_LOWPWR, 59 { S5P_TOP_PWR_LOWPWR, { 0x3, 0x0, 0x3 } },
60 S5P_G2D_ACP_MEM_LOWPWR, 60 { S5P_LOGIC_RESET_LOWPWR, { 0x1, 0x1, 0x0 } },
61 S5P_USBOTG_MEM_LOWPWR, 61 { S5P_ONENAND_MEM_LOWPWR, { 0x3, 0x0, 0x0 } },
62 S5P_HSMMC_MEM_LOWPWR, 62 { S5P_MODIMIF_MEM_LOWPWR, { 0x3, 0x0, 0x0 } },
63 S5P_CSSYS_MEM_LOWPWR, 63 { S5P_G2D_ACP_MEM_LOWPWR, { 0x3, 0x0, 0x0 } },
64 S5P_SECSS_MEM_LOWPWR, 64 { S5P_USBOTG_MEM_LOWPWR, { 0x3, 0x0, 0x0 } },
65 S5P_PCIE_MEM_LOWPWR, 65 { S5P_HSMMC_MEM_LOWPWR, { 0x3, 0x0, 0x0 } },
66 S5P_SATA_MEM_LOWPWR, 66 { S5P_CSSYS_MEM_LOWPWR, { 0x3, 0x0, 0x0 } },
67 S5P_PAD_RETENTION_DRAM_LOWPWR, 67 { S5P_SECSS_MEM_LOWPWR, { 0x3, 0x0, 0x0 } },
68 S5P_PAD_RETENTION_MAUDIO_LOWPWR, 68 { S5P_PCIE_MEM_LOWPWR, { 0x3, 0x0, 0x0 } },
69 S5P_PAD_RETENTION_GPIO_LOWPWR, 69 { S5P_SATA_MEM_LOWPWR, { 0x3, 0x0, 0x0 } },
70 S5P_PAD_RETENTION_UART_LOWPWR, 70 { S5P_PAD_RETENTION_DRAM_LOWPWR, { 0x1, 0x0, 0x0 } },
71 S5P_PAD_RETENTION_MMCA_LOWPWR, 71 { S5P_PAD_RETENTION_MAUDIO_LOWPWR, { 0x1, 0x1, 0x0 } },
72 S5P_PAD_RETENTION_MMCB_LOWPWR, 72 { S5P_PAD_RETENTION_GPIO_LOWPWR, { 0x1, 0x0, 0x0 } },
73 S5P_PAD_RETENTION_EBIA_LOWPWR, 73 { S5P_PAD_RETENTION_UART_LOWPWR, { 0x1, 0x0, 0x0 } },
74 S5P_PAD_RETENTION_EBIB_LOWPWR, 74 { S5P_PAD_RETENTION_MMCA_LOWPWR, { 0x1, 0x0, 0x0 } },
75 S5P_PAD_RETENTION_ISOLATION_LOWPWR, 75 { S5P_PAD_RETENTION_MMCB_LOWPWR, { 0x1, 0x0, 0x0 } },
76 S5P_PAD_RETENTION_ALV_SEL_LOWPWR, 76 { S5P_PAD_RETENTION_EBIA_LOWPWR, { 0x1, 0x0, 0x0 } },
77 S5P_XUSBXTI_LOWPWR, 77 { S5P_PAD_RETENTION_EBIB_LOWPWR, { 0x1, 0x0, 0x0 } },
78 S5P_XXTI_LOWPWR, 78 { S5P_PAD_RETENTION_ISOLATION_LOWPWR, { 0x1, 0x0, 0x0 } },
79 S5P_EXT_REGULATOR_LOWPWR, 79 { S5P_PAD_RETENTION_ALV_SEL_LOWPWR, { 0x1, 0x0, 0x0 } },
80 S5P_GPIO_MODE_LOWPWR, 80 { S5P_XUSBXTI_LOWPWR, { 0x1, 0x1, 0x0 } },
81 S5P_GPIO_MODE_MAUDIO_LOWPWR, 81 { S5P_XXTI_LOWPWR, { 0x1, 0x1, 0x0 } },
82 S5P_CAM_LOWPWR, 82 { S5P_EXT_REGULATOR_LOWPWR, { 0x1, 0x1, 0x0 } },
83 S5P_TV_LOWPWR, 83 { S5P_GPIO_MODE_LOWPWR, { 0x1, 0x0, 0x0 } },
84 S5P_MFC_LOWPWR, 84 { S5P_GPIO_MODE_MAUDIO_LOWPWR, { 0x1, 0x1, 0x0 } },
85 S5P_G3D_LOWPWR, 85 { S5P_CAM_LOWPWR, { 0x7, 0x0, 0x0 } },
86 S5P_LCD0_LOWPWR, 86 { S5P_TV_LOWPWR, { 0x7, 0x0, 0x0 } },
87 S5P_LCD1_LOWPWR, 87 { S5P_MFC_LOWPWR, { 0x7, 0x0, 0x0 } },
88 S5P_MAUDIO_LOWPWR, 88 { S5P_G3D_LOWPWR, { 0x7, 0x0, 0x0 } },
89 S5P_GPS_LOWPWR, 89 { S5P_LCD0_LOWPWR, { 0x7, 0x0, 0x0 } },
90 S5P_GPS_ALIVE_LOWPWR, 90 { S5P_LCD1_LOWPWR, { 0x7, 0x0, 0x0 } },
91 { S5P_MAUDIO_LOWPWR, { 0x7, 0x7, 0x0 } },
92 { S5P_GPS_LOWPWR, { 0x7, 0x0, 0x0 } },
93 { S5P_GPS_ALIVE_LOWPWR, { 0x7, 0x0, 0x0 } },
94 { PMU_TABLE_END,},
91}; 95};
92 96
93static const unsigned int sys_powerdown_val[][NUM_SYS_POWERDOWN] = { 97static struct exynos4_pmu_conf exynos4212_pmu_config[] = {
94 /* { AFTR, LPA, SLEEP }*/ 98 { S5P_ARM_CORE0_LOWPWR, { 0x0, 0x0, 0x2 } },
95 { 0, 0, 2 }, /* ARM_CORE0 */ 99 { S5P_DIS_IRQ_CORE0, { 0x0, 0x0, 0x0 } },
96 { 0, 0, 0 }, /* ARM_DIS_IRQ_CORE0 */ 100 { S5P_DIS_IRQ_CENTRAL0, { 0x0, 0x0, 0x0 } },
97 { 0, 0, 0 }, /* ARM_DIS_IRQ_CENTRAL0 */ 101 { S5P_ARM_CORE1_LOWPWR, { 0x0, 0x0, 0x2 } },
98 { 0, 0, 2 }, /* ARM_CORE1 */ 102 { S5P_DIS_IRQ_CORE1, { 0x0, 0x0, 0x0 } },
99 { 0, 0, 0 }, /* ARM_DIS_IRQ_CORE1 */ 103 { S5P_DIS_IRQ_CENTRAL1, { 0x0, 0x0, 0x0 } },
100 { 0, 0, 0 }, /* ARM_DIS_IRQ_CENTRAL1 */ 104 { S5P_ISP_ARM_LOWPWR, { 0x1, 0x0, 0x0 } },
101 { 0, 0, 2 }, /* ARM_COMMON */ 105 { S5P_DIS_IRQ_ISP_ARM_LOCAL_LOWPWR, { 0x0, 0x0, 0x0 } },
102 { 2, 2, 3 }, /* ARM_CPU_L2_0 */ 106 { S5P_DIS_IRQ_ISP_ARM_CENTRAL_LOWPWR, { 0x0, 0x0, 0x0 } },
103 { 2, 2, 3 }, /* ARM_CPU_L2_1 */ 107 { S5P_ARM_COMMON_LOWPWR, { 0x0, 0x0, 0x2 } },
104 { 1, 0, 0 }, /* CMU_ACLKSTOP */ 108 { S5P_L2_0_LOWPWR, { 0x0, 0x0, 0x3 } },
105 { 1, 0, 0 }, /* CMU_SCLKSTOP */ 109 /* XXX_OPTION register should be set other field */
106 { 1, 1, 0 }, /* CMU_RESET */ 110 { S5P_ARM_L2_0_OPTION, { 0x10, 0x10, 0x0 } },
107 { 1, 0, 0 }, /* APLL_SYSCLK */ 111 { S5P_L2_1_LOWPWR, { 0x0, 0x0, 0x3 } },
108 { 1, 0, 0 }, /* MPLL_SYSCLK */ 112 { S5P_ARM_L2_1_OPTION, { 0x10, 0x10, 0x0 } },
109 { 1, 0, 0 }, /* VPLL_SYSCLK */ 113 { S5P_CMU_ACLKSTOP_LOWPWR, { 0x1, 0x0, 0x0 } },
110 { 1, 1, 0 }, /* EPLL_SYSCLK */ 114 { S5P_CMU_SCLKSTOP_LOWPWR, { 0x1, 0x0, 0x0 } },
111 { 1, 1, 0 }, /* CMU_CLKSTOP_GPS_ALIVE */ 115 { S5P_CMU_RESET_LOWPWR, { 0x1, 0x1, 0x0 } },
112 { 1, 1, 0 }, /* CMU_RESET_GPS_ALIVE */ 116 { S5P_DRAM_FREQ_DOWN_LOWPWR, { 0x1, 0x1, 0x1 } },
113 { 1, 1, 0 }, /* CMU_CLKSTOP_CAM */ 117 { S5P_DDRPHY_DLLOFF_LOWPWR, { 0x1, 0x1, 0x1 } },
114 { 1, 1, 0 }, /* CMU_CLKSTOP_TV */ 118 { S5P_LPDDR_PHY_DLL_LOCK_LOWPWR, { 0x1, 0x1, 0x1 } },
115 { 1, 1, 0 }, /* CMU_CLKSTOP_MFC */ 119 { S5P_CMU_ACLKSTOP_COREBLK_LOWPWR, { 0x1, 0x0, 0x0 } },
116 { 1, 1, 0 }, /* CMU_CLKSTOP_G3D */ 120 { S5P_CMU_SCLKSTOP_COREBLK_LOWPWR, { 0x1, 0x0, 0x0 } },
117 { 1, 1, 0 }, /* CMU_CLKSTOP_LCD0 */ 121 { S5P_CMU_RESET_COREBLK_LOWPWR, { 0x1, 0x1, 0x0 } },
118 { 1, 1, 0 }, /* CMU_CLKSTOP_LCD1 */ 122 { S5P_APLL_SYSCLK_LOWPWR, { 0x1, 0x0, 0x0 } },
119 { 1, 1, 0 }, /* CMU_CLKSTOP_MAUDIO */ 123 { S5P_MPLL_SYSCLK_LOWPWR, { 0x1, 0x0, 0x0 } },
120 { 1, 1, 0 }, /* CMU_CLKSTOP_GPS */ 124 { S5P_VPLL_SYSCLK_LOWPWR, { 0x1, 0x0, 0x0 } },
121 { 1, 1, 0 }, /* CMU_RESET_CAM */ 125 { S5P_EPLL_SYSCLK_LOWPWR, { 0x1, 0x1, 0x0 } },
122 { 1, 1, 0 }, /* CMU_RESET_TV */ 126 { S5P_MPLLUSER_SYSCLK_LOWPWR, { 0x1, 0x0, 0x0 } },
123 { 1, 1, 0 }, /* CMU_RESET_MFC */ 127 { S5P_CMU_CLKSTOP_GPS_ALIVE_LOWPWR, { 0x1, 0x0, 0x0 } },
124 { 1, 1, 0 }, /* CMU_RESET_G3D */ 128 { S5P_CMU_RESET_GPSALIVE_LOWPWR, { 0x1, 0x0, 0x0 } },
125 { 1, 1, 0 }, /* CMU_RESET_LCD0 */ 129 { S5P_CMU_CLKSTOP_CAM_LOWPWR, { 0x1, 0x0, 0x0 } },
126 { 1, 1, 0 }, /* CMU_RESET_LCD1 */ 130 { S5P_CMU_CLKSTOP_TV_LOWPWR, { 0x1, 0x0, 0x0 } },
127 { 1, 1, 0 }, /* CMU_RESET_MAUDIO */ 131 { S5P_CMU_CLKSTOP_MFC_LOWPWR, { 0x1, 0x0, 0x0 } },
128 { 1, 1, 0 }, /* CMU_RESET_GPS */ 132 { S5P_CMU_CLKSTOP_G3D_LOWPWR, { 0x1, 0x0, 0x0 } },
129 { 3, 0, 0 }, /* TOP_BUS */ 133 { S5P_CMU_CLKSTOP_LCD0_LOWPWR, { 0x1, 0x0, 0x0 } },
130 { 1, 0, 1 }, /* TOP_RETENTION */ 134 { S5P_CMU_CLKSTOP_ISP_LOWPWR, { 0x1, 0x0, 0x0 } },
131 { 3, 0, 3 }, /* TOP_PWR */ 135 { S5P_CMU_CLKSTOP_MAUDIO_LOWPWR, { 0x1, 0x0, 0x0 } },
132 { 1, 1, 0 }, /* LOGIC_RESET */ 136 { S5P_CMU_CLKSTOP_GPS_LOWPWR, { 0x1, 0x0, 0x0 } },
133 { 3, 0, 0 }, /* ONENAND_MEM */ 137 { S5P_CMU_RESET_CAM_LOWPWR, { 0x1, 0x0, 0x0 } },
134 { 3, 0, 0 }, /* MODIMIF_MEM */ 138 { S5P_CMU_RESET_TV_LOWPWR, { 0x1, 0x0, 0x0 } },
135 { 3, 0, 0 }, /* G2D_ACP_MEM */ 139 { S5P_CMU_RESET_MFC_LOWPWR, { 0x1, 0x0, 0x0 } },
136 { 3, 0, 0 }, /* USBOTG_MEM */ 140 { S5P_CMU_RESET_G3D_LOWPWR, { 0x1, 0x0, 0x0 } },
137 { 3, 0, 0 }, /* HSMMC_MEM */ 141 { S5P_CMU_RESET_LCD0_LOWPWR, { 0x1, 0x0, 0x0 } },
138 { 3, 0, 0 }, /* CSSYS_MEM */ 142 { S5P_CMU_RESET_ISP_LOWPWR, { 0x1, 0x0, 0x0 } },
139 { 3, 0, 0 }, /* SECSS_MEM */ 143 { S5P_CMU_RESET_MAUDIO_LOWPWR, { 0x1, 0x1, 0x0 } },
140 { 3, 0, 0 }, /* PCIE_MEM */ 144 { S5P_CMU_RESET_GPS_LOWPWR, { 0x1, 0x0, 0x0 } },
141 { 3, 0, 0 }, /* SATA_MEM */ 145 { S5P_TOP_BUS_LOWPWR, { 0x3, 0x0, 0x0 } },
142 { 1, 0, 0 }, /* PAD_RETENTION_DRAM */ 146 { S5P_TOP_RETENTION_LOWPWR, { 0x1, 0x0, 0x1 } },
143 { 1, 1, 0 }, /* PAD_RETENTION_MAUDIO */ 147 { S5P_TOP_PWR_LOWPWR, { 0x3, 0x0, 0x3 } },
144 { 1, 0, 0 }, /* PAD_RETENTION_GPIO */ 148 { S5P_TOP_BUS_COREBLK_LOWPWR, { 0x3, 0x0, 0x0 } },
145 { 1, 0, 0 }, /* PAD_RETENTION_UART */ 149 { S5P_TOP_RETENTION_COREBLK_LOWPWR, { 0x1, 0x0, 0x1 } },
146 { 1, 0, 0 }, /* PAD_RETENTION_MMCA */ 150 { S5P_TOP_PWR_COREBLK_LOWPWR, { 0x3, 0x0, 0x3 } },
147 { 1, 0, 0 }, /* PAD_RETENTION_MMCB */ 151 { S5P_LOGIC_RESET_LOWPWR, { 0x1, 0x1, 0x0 } },
148 { 1, 0, 0 }, /* PAD_RETENTION_EBIA */ 152 { S5P_OSCCLK_GATE_LOWPWR, { 0x1, 0x0, 0x1 } },
149 { 1, 0, 0 }, /* PAD_RETENTION_EBIB */ 153 { S5P_LOGIC_RESET_COREBLK_LOWPWR, { 0x1, 0x1, 0x0 } },
150 { 1, 0, 0 }, /* PAD_RETENTION_ISOLATION */ 154 { S5P_OSCCLK_GATE_COREBLK_LOWPWR, { 0x1, 0x0, 0x1 } },
151 { 1, 0, 0 }, /* PAD_RETENTION_ALV_SEL */ 155 { S5P_ONENAND_MEM_LOWPWR, { 0x3, 0x0, 0x0 } },
152 { 1, 1, 0 }, /* XUSBXTI */ 156 { S5P_ONENAND_MEM_OPTION, { 0x10, 0x10, 0x0 } },
153 { 1, 1, 0 }, /* XXTI */ 157 { S5P_HSI_MEM_LOWPWR, { 0x3, 0x0, 0x0 } },
154 { 1, 1, 0 }, /* EXT_REGULATOR */ 158 { S5P_HSI_MEM_OPTION, { 0x10, 0x10, 0x0 } },
155 { 1, 0, 0 }, /* GPIO_MODE */ 159 { S5P_G2D_ACP_MEM_LOWPWR, { 0x3, 0x0, 0x0 } },
156 { 1, 1, 0 }, /* GPIO_MODE_MAUDIO */ 160 { S5P_G2D_ACP_MEM_OPTION, { 0x10, 0x10, 0x0 } },
157 { 7, 0, 0 }, /* CAM */ 161 { S5P_USBOTG_MEM_LOWPWR, { 0x3, 0x0, 0x0 } },
158 { 7, 0, 0 }, /* TV */ 162 { S5P_USBOTG_MEM_OPTION, { 0x10, 0x10, 0x0 } },
159 { 7, 0, 0 }, /* MFC */ 163 { S5P_HSMMC_MEM_LOWPWR, { 0x3, 0x0, 0x0 } },
160 { 7, 0, 0 }, /* G3D */ 164 { S5P_HSMMC_MEM_OPTION, { 0x10, 0x10, 0x0 } },
161 { 7, 0, 0 }, /* LCD0 */ 165 { S5P_CSSYS_MEM_LOWPWR, { 0x3, 0x0, 0x0 } },
162 { 7, 0, 0 }, /* LCD1 */ 166 { S5P_CSSYS_MEM_OPTION, { 0x10, 0x10, 0x0 } },
163 { 7, 7, 0 }, /* MAUDIO */ 167 { S5P_SECSS_MEM_LOWPWR, { 0x3, 0x0, 0x0 } },
164 { 7, 0, 0 }, /* GPS */ 168 { S5P_SECSS_MEM_OPTION, { 0x10, 0x10, 0x0 } },
165 { 7, 0, 0 }, /* GPS_ALIVE */ 169 { S5P_ROTATOR_MEM_LOWPWR, { 0x3, 0x0, 0x0 } },
170 { S5P_ROTATOR_MEM_OPTION, { 0x10, 0x10, 0x0 } },
171 { S5P_PAD_RETENTION_DRAM_LOWPWR, { 0x1, 0x0, 0x0 } },
172 { S5P_PAD_RETENTION_MAUDIO_LOWPWR, { 0x1, 0x1, 0x0 } },
173 { S5P_PAD_RETENTION_GPIO_LOWPWR, { 0x1, 0x0, 0x0 } },
174 { S5P_PAD_RETENTION_UART_LOWPWR, { 0x1, 0x0, 0x0 } },
175 { S5P_PAD_RETENTION_MMCA_LOWPWR, { 0x1, 0x0, 0x0 } },
176 { S5P_PAD_RETENTION_MMCB_LOWPWR, { 0x1, 0x0, 0x0 } },
177 { S5P_PAD_RETENTION_EBIA_LOWPWR, { 0x1, 0x0, 0x0 } },
178 { S5P_PAD_RETENTION_EBIB_LOWPWR, { 0x1, 0x0, 0x0 } },
179 { S5P_PAD_RETENTION_GPIO_COREBLK_LOWPWR,{ 0x1, 0x0, 0x0 } },
180 { S5P_PAD_RETENTION_ISOLATION_LOWPWR, { 0x1, 0x0, 0x0 } },
181 { S5P_PAD_ISOLATION_COREBLK_LOWPWR, { 0x1, 0x0, 0x0 } },
182 { S5P_PAD_RETENTION_ALV_SEL_LOWPWR, { 0x1, 0x0, 0x0 } },
183 { S5P_XUSBXTI_LOWPWR, { 0x1, 0x1, 0x0 } },
184 { S5P_XXTI_LOWPWR, { 0x1, 0x1, 0x0 } },
185 { S5P_EXT_REGULATOR_LOWPWR, { 0x1, 0x1, 0x0 } },
186 { S5P_GPIO_MODE_LOWPWR, { 0x1, 0x0, 0x0 } },
187 { S5P_GPIO_MODE_COREBLK_LOWPWR, { 0x1, 0x0, 0x0 } },
188 { S5P_GPIO_MODE_MAUDIO_LOWPWR, { 0x1, 0x1, 0x0 } },
189 { S5P_TOP_ASB_RESET_LOWPWR, { 0x1, 0x1, 0x1 } },
190 { S5P_TOP_ASB_ISOLATION_LOWPWR, { 0x1, 0x0, 0x1 } },
191 { S5P_CAM_LOWPWR, { 0x7, 0x0, 0x0 } },
192 { S5P_TV_LOWPWR, { 0x7, 0x0, 0x0 } },
193 { S5P_MFC_LOWPWR, { 0x7, 0x0, 0x0 } },
194 { S5P_G3D_LOWPWR, { 0x7, 0x0, 0x0 } },
195 { S5P_LCD0_LOWPWR, { 0x7, 0x0, 0x0 } },
196 { S5P_ISP_LOWPWR, { 0x7, 0x0, 0x0 } },
197 { S5P_MAUDIO_LOWPWR, { 0x7, 0x7, 0x0 } },
198 { S5P_GPS_LOWPWR, { 0x7, 0x0, 0x0 } },
199 { S5P_GPS_ALIVE_LOWPWR, { 0x7, 0x0, 0x0 } },
200 { S5P_CMU_SYSCLK_ISP_LOWPWR, { 0x1, 0x0, 0x0 } },
201 { S5P_CMU_SYSCLK_GPS_LOWPWR, { 0x1, 0x0, 0x0 } },
202 { PMU_TABLE_END,},
166}; 203};
167 204
168void exynos4_sys_powerdown_conf(enum sys_powerdown mode) 205void exynos4_sys_powerdown_conf(enum sys_powerdown mode)
169{ 206{
170 unsigned int count = ARRAY_SIZE(sys_powerdown_reg); 207 unsigned int i;
208
209 for (i = 0; (exynos4_pmu_config[i].reg != PMU_TABLE_END) ; i++)
210 __raw_writel(exynos4_pmu_config[i].val[mode],
211 exynos4_pmu_config[i].reg);
212}
213
214static int __init exynos4_pmu_init(void)
215{
216 exynos4_pmu_config = exynos4210_pmu_config;
217
218 if (soc_is_exynos4210()) {
219 exynos4_pmu_config = exynos4210_pmu_config;
220 pr_info("EXYNOS4210 PMU Initialize\n");
221 } else if (soc_is_exynos4212()) {
222 exynos4_pmu_config = exynos4212_pmu_config;
223 pr_info("EXYNOS4212 PMU Initialize\n");
224 } else {
225 pr_info("EXYNOS4: PMU not supported\n");
226 }
171 227
172 for (; count > 0; count--) 228 return 0;
173 __raw_writel(sys_powerdown_val[count - 1][mode],
174 sys_powerdown_reg[count - 1]);
175} 229}
230arch_initcall(exynos4_pmu_init);
diff --git a/arch/arm/mach-s3c2410/Kconfig b/arch/arm/mach-s3c2410/Kconfig
index 3700cf32af0f..5261a7ed0999 100644
--- a/arch/arm/mach-s3c2410/Kconfig
+++ b/arch/arm/mach-s3c2410/Kconfig
@@ -6,7 +6,6 @@ config CPU_S3C2410
6 bool 6 bool
7 depends on ARCH_S3C2410 7 depends on ARCH_S3C2410
8 select CPU_ARM920T 8 select CPU_ARM920T
9 select S3C_GPIO_PULL_UP
10 select S3C2410_CLOCK 9 select S3C2410_CLOCK
11 select CPU_LLSERIAL_S3C2410 10 select CPU_LLSERIAL_S3C2410
12 select S3C2410_PM if PM 11 select S3C2410_PM if PM
diff --git a/arch/arm/mach-s3c2410/include/mach/dma.h b/arch/arm/mach-s3c2410/include/mach/dma.h
index b2b2a5bb275e..ae8e482b6427 100644
--- a/arch/arm/mach-s3c2410/include/mach/dma.h
+++ b/arch/arm/mach-s3c2410/include/mach/dma.h
@@ -13,7 +13,6 @@
13#ifndef __ASM_ARCH_DMA_H 13#ifndef __ASM_ARCH_DMA_H
14#define __ASM_ARCH_DMA_H __FILE__ 14#define __ASM_ARCH_DMA_H __FILE__
15 15
16#include <plat/dma.h>
17#include <linux/sysdev.h> 16#include <linux/sysdev.h>
18 17
19#define MAX_DMA_TRANSFER_SIZE 0x100000 /* Data Unit is half word */ 18#define MAX_DMA_TRANSFER_SIZE 0x100000 /* Data Unit is half word */
@@ -51,6 +50,18 @@ enum dma_ch {
51 DMACH_MAX, /* the end entry */ 50 DMACH_MAX, /* the end entry */
52}; 51};
53 52
53static inline bool samsung_dma_has_circular(void)
54{
55 return false;
56}
57
58static inline bool samsung_dma_is_dmadev(void)
59{
60 return false;
61}
62
63#include <plat/dma.h>
64
54#define DMACH_LOW_LEVEL (1<<28) /* use this to specifiy hardware ch no */ 65#define DMACH_LOW_LEVEL (1<<28) /* use this to specifiy hardware ch no */
55 66
56/* we have 4 dma channels */ 67/* we have 4 dma channels */
@@ -163,7 +174,7 @@ struct s3c2410_dma_chan {
163 struct s3c2410_dma_client *client; 174 struct s3c2410_dma_client *client;
164 175
165 /* channel configuration */ 176 /* channel configuration */
166 enum s3c2410_dmasrc source; 177 enum dma_data_direction source;
167 enum dma_ch req_ch; 178 enum dma_ch req_ch;
168 unsigned long dev_addr; 179 unsigned long dev_addr;
169 unsigned long load_timeout; 180 unsigned long load_timeout;
@@ -196,9 +207,4 @@ struct s3c2410_dma_chan {
196 207
197typedef unsigned long dma_device_t; 208typedef unsigned long dma_device_t;
198 209
199static inline bool s3c_dma_has_circular(void)
200{
201 return false;
202}
203
204#endif /* __ASM_ARCH_DMA_H */ 210#endif /* __ASM_ARCH_DMA_H */
diff --git a/arch/arm/mach-s3c2410/include/mach/gpio-fns.h b/arch/arm/mach-s3c2410/include/mach/gpio-fns.h
index bab139201761..c53ad34c6579 100644
--- a/arch/arm/mach-s3c2410/include/mach/gpio-fns.h
+++ b/arch/arm/mach-s3c2410/include/mach/gpio-fns.h
@@ -1,98 +1 @@
1/* arch/arm/mach-s3c2410/include/mach/gpio-fns.h #include <plat/gpio-fns.h>
2 *
3 * Copyright (c) 2003-2009 Simtec Electronics
4 * Ben Dooks <ben@simtec.co.uk>
5 *
6 * S3C2410 - hardware
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11*/
12
13#ifndef __MACH_GPIO_FNS_H
14#define __MACH_GPIO_FNS_H __FILE__
15
16/* These functions are in the to-be-removed category and it is strongly
17 * encouraged not to use these in new code. They will be marked deprecated
18 * very soon.
19 *
20 * Most of the functionality can be either replaced by the gpiocfg calls
21 * for the s3c platform or by the generic GPIOlib API.
22 *
23 * As of 2.6.35-rc, these will be removed, with the few drivers using them
24 * either replaced or given a wrapper until the calls can be removed.
25*/
26
27#include <plat/gpio-cfg.h>
28
29static inline void s3c2410_gpio_cfgpin(unsigned int pin, unsigned int cfg)
30{
31 /* 1:1 mapping between cfgpin and setcfg calls at the moment */
32 s3c_gpio_cfgpin(pin, cfg);
33}
34
35/* external functions for GPIO support
36 *
37 * These allow various different clients to access the same GPIO
38 * registers without conflicting. If your driver only owns the entire
39 * GPIO register, then it is safe to ioremap/__raw_{read|write} to it.
40*/
41
42extern unsigned int s3c2410_gpio_getcfg(unsigned int pin);
43
44/* s3c2410_gpio_getirq
45 *
46 * turn the given pin number into the corresponding IRQ number
47 *
48 * returns:
49 * < 0 = no interrupt for this pin
50 * >=0 = interrupt number for the pin
51*/
52
53extern int s3c2410_gpio_getirq(unsigned int pin);
54
55/* s3c2410_gpio_irqfilter
56 *
57 * set the irq filtering on the given pin
58 *
59 * on = 0 => disable filtering
60 * 1 => enable filtering
61 *
62 * config = S3C2410_EINTFLT_PCLK or S3C2410_EINTFLT_EXTCLK orred with
63 * width of filter (0 through 63)
64 *
65 *
66*/
67
68extern int s3c2410_gpio_irqfilter(unsigned int pin, unsigned int on,
69 unsigned int config);
70
71/* s3c2410_gpio_pullup
72 *
73 * This call should be replaced with s3c_gpio_setpull().
74 *
75 * As a note, there is currently no distinction between pull-up and pull-down
76 * in the s3c24xx series devices with only an on/off configuration.
77 */
78
79/* s3c2410_gpio_pullup
80 *
81 * configure the pull-up control on the given pin
82 *
83 * to = 1 => disable the pull-up
84 * 0 => enable the pull-up
85 *
86 * eg;
87 *
88 * s3c2410_gpio_pullup(S3C2410_GPB(0), 0);
89 * s3c2410_gpio_pullup(S3C2410_GPE(8), 0);
90*/
91
92extern void s3c2410_gpio_pullup(unsigned int pin, unsigned int to);
93
94extern void s3c2410_gpio_setpin(unsigned int pin, unsigned int to);
95
96extern unsigned int s3c2410_gpio_getpin(unsigned int pin);
97
98#endif /* __MACH_GPIO_FNS_H */
diff --git a/arch/arm/mach-s3c2410/include/mach/gpio-track.h b/arch/arm/mach-s3c2410/include/mach/gpio-track.h
index d67819dde42a..c410a078622c 100644
--- a/arch/arm/mach-s3c2410/include/mach/gpio-track.h
+++ b/arch/arm/mach-s3c2410/include/mach/gpio-track.h
@@ -17,11 +17,11 @@
17 17
18#include <mach/regs-gpio.h> 18#include <mach/regs-gpio.h>
19 19
20extern struct s3c_gpio_chip s3c24xx_gpios[]; 20extern struct samsung_gpio_chip s3c24xx_gpios[];
21 21
22static inline struct s3c_gpio_chip *s3c_gpiolib_getchip(unsigned int pin) 22static inline struct samsung_gpio_chip *samsung_gpiolib_getchip(unsigned int pin)
23{ 23{
24 struct s3c_gpio_chip *chip; 24 struct samsung_gpio_chip *chip;
25 25
26 if (pin > S3C_GPIO_END) 26 if (pin > S3C_GPIO_END)
27 return NULL; 27 return NULL;
diff --git a/arch/arm/mach-s3c2410/include/mach/pm-core.h b/arch/arm/mach-s3c2410/include/mach/pm-core.h
index 45eea5210c87..2eef7e6f7675 100644
--- a/arch/arm/mach-s3c2410/include/mach/pm-core.h
+++ b/arch/arm/mach-s3c2410/include/mach/pm-core.h
@@ -64,4 +64,4 @@ static inline void s3c_pm_arch_update_uart(void __iomem *regs,
64} 64}
65 65
66static inline void s3c_pm_restored_gpios(void) { } 66static inline void s3c_pm_restored_gpios(void) { }
67static inline void s3c_pm_saved_gpios(void) { } 67static inline void samsung_pm_saved_gpios(void) { }
diff --git a/arch/arm/mach-s3c2410/include/mach/regs-s3c2443-clock.h b/arch/arm/mach-s3c2410/include/mach/regs-s3c2443-clock.h
index 5e06c7265835..df6434f326f0 100644
--- a/arch/arm/mach-s3c2410/include/mach/regs-s3c2443-clock.h
+++ b/arch/arm/mach-s3c2410/include/mach/regs-s3c2443-clock.h
@@ -102,6 +102,7 @@
102#define S3C2443_PCLKCON_UART3 (1<<3) 102#define S3C2443_PCLKCON_UART3 (1<<3)
103#define S3C2443_PCLKCON_IIC (1<<4) 103#define S3C2443_PCLKCON_IIC (1<<4)
104#define S3C2443_PCLKCON_SDI (1<<5) 104#define S3C2443_PCLKCON_SDI (1<<5)
105#define S3C2443_PCLKCON_HSSPI (1<<6)
105#define S3C2443_PCLKCON_ADC (1<<7) 106#define S3C2443_PCLKCON_ADC (1<<7)
106#define S3C2443_PCLKCON_AC97 (1<<8) 107#define S3C2443_PCLKCON_AC97 (1<<8)
107#define S3C2443_PCLKCON_IIS (1<<9) 108#define S3C2443_PCLKCON_IIS (1<<9)
diff --git a/arch/arm/mach-s3c2410/s3c2410.c b/arch/arm/mach-s3c2410/s3c2410.c
index f1d3bd8f6f17..a99c2f4a523f 100644
--- a/arch/arm/mach-s3c2410/s3c2410.c
+++ b/arch/arm/mach-s3c2410/s3c2410.c
@@ -72,8 +72,8 @@ void __init s3c2410_init_uarts(struct s3c2410_uartcfg *cfg, int no)
72 72
73void __init s3c2410_map_io(void) 73void __init s3c2410_map_io(void)
74{ 74{
75 s3c24xx_gpiocfg_default.set_pull = s3c_gpio_setpull_1up; 75 s3c24xx_gpiocfg_default.set_pull = s3c24xx_gpio_setpull_1up;
76 s3c24xx_gpiocfg_default.get_pull = s3c_gpio_getpull_1up; 76 s3c24xx_gpiocfg_default.get_pull = s3c24xx_gpio_getpull_1up;
77 77
78 iotable_init(s3c2410_iodesc, ARRAY_SIZE(s3c2410_iodesc)); 78 iotable_init(s3c2410_iodesc, ARRAY_SIZE(s3c2410_iodesc));
79} 79}
diff --git a/arch/arm/mach-s3c2412/dma.c b/arch/arm/mach-s3c2412/dma.c
index c61e3261615d..d2a7d5ef3e67 100644
--- a/arch/arm/mach-s3c2412/dma.c
+++ b/arch/arm/mach-s3c2412/dma.c
@@ -130,11 +130,11 @@ static struct s3c24xx_dma_map __initdata s3c2412_dma_mappings[] = {
130 130
131static void s3c2412_dma_direction(struct s3c2410_dma_chan *chan, 131static void s3c2412_dma_direction(struct s3c2410_dma_chan *chan,
132 struct s3c24xx_dma_map *map, 132 struct s3c24xx_dma_map *map,
133 enum s3c2410_dmasrc dir) 133 enum dma_data_direction dir)
134{ 134{
135 unsigned long chsel; 135 unsigned long chsel;
136 136
137 if (dir == S3C2410_DMASRC_HW) 137 if (dir == DMA_FROM_DEVICE)
138 chsel = map->channels_rx[0]; 138 chsel = map->channels_rx[0];
139 else 139 else
140 chsel = map->channels[0]; 140 chsel = map->channels[0];
diff --git a/arch/arm/mach-s3c2412/gpio.c b/arch/arm/mach-s3c2412/gpio.c
new file mode 100644
index 000000000000..4526f6ba31a8
--- /dev/null
+++ b/arch/arm/mach-s3c2412/gpio.c
@@ -0,0 +1,62 @@
1/* linux/arch/arm/mach-s3c2412/gpio.c
2 *
3 * Copyright (c) 2007 Simtec Electronics
4 * Ben Dooks <ben@simtec.co.uk>
5 *
6 * http://armlinux.simtec.co.uk/.
7 *
8 * S3C2412/S3C2413 specific GPIO support
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
13*/
14
15#include <linux/kernel.h>
16#include <linux/types.h>
17#include <linux/module.h>
18#include <linux/interrupt.h>
19#include <linux/gpio.h>
20
21#include <asm/mach/arch.h>
22#include <asm/mach/map.h>
23
24#include <mach/regs-gpio.h>
25#include <mach/hardware.h>
26
27#include <plat/gpio-core.h>
28
29int s3c2412_gpio_set_sleepcfg(unsigned int pin, unsigned int state)
30{
31 struct samsung_gpio_chip *chip = samsung_gpiolib_getchip(pin);
32 unsigned long offs = pin - chip->chip.base;
33 unsigned long flags;
34 unsigned long slpcon;
35
36 offs *= 2;
37
38 if (pin < S3C2410_GPB(0))
39 return -EINVAL;
40
41 if (pin >= S3C2410_GPF(0) &&
42 pin <= S3C2410_GPG(16))
43 return -EINVAL;
44
45 if (pin > S3C2410_GPH(16))
46 return -EINVAL;
47
48 local_irq_save(flags);
49
50 slpcon = __raw_readl(chip->base + 0x0C);
51
52 slpcon &= ~(3 << offs);
53 slpcon |= state << offs;
54
55 __raw_writel(slpcon, chip->base + 0x0C);
56
57 local_irq_restore(flags);
58
59 return 0;
60}
61
62EXPORT_SYMBOL(s3c2412_gpio_set_sleepcfg);
diff --git a/arch/arm/mach-s3c2416/Kconfig b/arch/arm/mach-s3c2416/Kconfig
index 69b48a7d1dbd..84c7b03e5a30 100644
--- a/arch/arm/mach-s3c2416/Kconfig
+++ b/arch/arm/mach-s3c2416/Kconfig
@@ -13,7 +13,6 @@ config CPU_S3C2416
13 select CPU_ARM926T 13 select CPU_ARM926T
14 select S3C2416_DMA if S3C2410_DMA 14 select S3C2416_DMA if S3C2410_DMA
15 select CPU_LLSERIAL_S3C2440 15 select CPU_LLSERIAL_S3C2440
16 select S3C_GPIO_PULL_UPDOWN
17 select SAMSUNG_CLKSRC 16 select SAMSUNG_CLKSRC
18 select S3C2443_CLOCK 17 select S3C2443_CLOCK
19 help 18 help
diff --git a/arch/arm/mach-s3c2416/clock.c b/arch/arm/mach-s3c2416/clock.c
index 21a5e81f0ab5..196fb37f4b19 100644
--- a/arch/arm/mach-s3c2416/clock.c
+++ b/arch/arm/mach-s3c2416/clock.c
@@ -38,6 +38,32 @@ static unsigned int armdiv[8] = {
38 [7] = 8, 38 [7] = 8,
39}; 39};
40 40
41static struct clksrc_clk hsspi_eplldiv = {
42 .clk = {
43 .name = "hsspi-eplldiv",
44 .parent = &clk_esysclk.clk,
45 .ctrlbit = (1 << 14),
46 .enable = s3c2443_clkcon_enable_s,
47 },
48 .reg_div = { .reg = S3C2443_CLKDIV1, .size = 2, .shift = 24 },
49};
50
51static struct clk *hsspi_sources[] = {
52 [0] = &hsspi_eplldiv.clk,
53 [1] = NULL, /* to fix */
54};
55
56static struct clksrc_clk hsspi_mux = {
57 .clk = {
58 .name = "hsspi-if",
59 },
60 .sources = &(struct clksrc_sources) {
61 .sources = hsspi_sources,
62 .nr_sources = ARRAY_SIZE(hsspi_sources),
63 },
64 .reg_src = { .reg = S3C2443_CLKSRC, .size = 1, .shift = 18 },
65};
66
41static struct clksrc_clk hsmmc_div[] = { 67static struct clksrc_clk hsmmc_div[] = {
42 [0] = { 68 [0] = {
43 .clk = { 69 .clk = {
@@ -114,6 +140,8 @@ void __init_or_cpufreq s3c2416_setup_clocks(void)
114 140
115 141
116static struct clksrc_clk *clksrcs[] __initdata = { 142static struct clksrc_clk *clksrcs[] __initdata = {
143 &hsspi_eplldiv,
144 &hsspi_mux,
117 &hsmmc_div[0], 145 &hsmmc_div[0],
118 &hsmmc_div[1], 146 &hsmmc_div[1],
119 &hsmmc_mux[0], 147 &hsmmc_mux[0],
diff --git a/arch/arm/mach-s3c2416/s3c2416.c b/arch/arm/mach-s3c2416/s3c2416.c
index 494ce913dc95..3156b7a71371 100644
--- a/arch/arm/mach-s3c2416/s3c2416.c
+++ b/arch/arm/mach-s3c2416/s3c2416.c
@@ -118,8 +118,8 @@ void __init s3c2416_init_uarts(struct s3c2410_uartcfg *cfg, int no)
118 118
119void __init s3c2416_map_io(void) 119void __init s3c2416_map_io(void)
120{ 120{
121 s3c24xx_gpiocfg_default.set_pull = s3c_gpio_setpull_updown; 121 s3c24xx_gpiocfg_default.set_pull = samsung_gpio_setpull_updown;
122 s3c24xx_gpiocfg_default.get_pull = s3c_gpio_getpull_updown; 122 s3c24xx_gpiocfg_default.get_pull = samsung_gpio_getpull_updown;
123 123
124 /* initialize device information early */ 124 /* initialize device information early */
125 s3c2416_default_sdhci0(); 125 s3c2416_default_sdhci0();
diff --git a/arch/arm/mach-s3c2440/Kconfig b/arch/arm/mach-s3c2440/Kconfig
index c461fb8e15c0..914e620f1257 100644
--- a/arch/arm/mach-s3c2440/Kconfig
+++ b/arch/arm/mach-s3c2440/Kconfig
@@ -5,7 +5,6 @@
5config CPU_S3C2440 5config CPU_S3C2440
6 bool 6 bool
7 select CPU_ARM920T 7 select CPU_ARM920T
8 select S3C_GPIO_PULL_UP
9 select S3C2410_CLOCK 8 select S3C2410_CLOCK
10 select S3C2410_PM if PM 9 select S3C2410_PM if PM
11 select S3C2440_DMA if S3C2410_DMA 10 select S3C2440_DMA if S3C2410_DMA
@@ -17,7 +16,6 @@ config CPU_S3C2440
17config CPU_S3C2442 16config CPU_S3C2442
18 bool 17 bool
19 select CPU_ARM920T 18 select CPU_ARM920T
20 select S3C_GPIO_PULL_DOWN
21 select S3C2410_CLOCK 19 select S3C2410_CLOCK
22 select S3C2410_PM if PM 20 select S3C2410_PM if PM
23 select CPU_S3C244X 21 select CPU_S3C244X
diff --git a/arch/arm/mach-s3c2440/s3c2440.c b/arch/arm/mach-s3c2440/s3c2440.c
index ce99ff72838d..fc84e481efcf 100644
--- a/arch/arm/mach-s3c2440/s3c2440.c
+++ b/arch/arm/mach-s3c2440/s3c2440.c
@@ -68,6 +68,6 @@ void __init s3c2440_map_io(void)
68{ 68{
69 s3c244x_map_io(); 69 s3c244x_map_io();
70 70
71 s3c24xx_gpiocfg_default.set_pull = s3c_gpio_setpull_1up; 71 s3c24xx_gpiocfg_default.set_pull = s3c24xx_gpio_setpull_1up;
72 s3c24xx_gpiocfg_default.get_pull = s3c_gpio_getpull_1up; 72 s3c24xx_gpiocfg_default.get_pull = s3c24xx_gpio_getpull_1up;
73} 73}
diff --git a/arch/arm/mach-s3c2440/s3c2442.c b/arch/arm/mach-s3c2440/s3c2442.c
index 9ad99f8016a1..48e273ce9f9a 100644
--- a/arch/arm/mach-s3c2440/s3c2442.c
+++ b/arch/arm/mach-s3c2440/s3c2442.c
@@ -180,6 +180,6 @@ void __init s3c2442_map_io(void)
180{ 180{
181 s3c244x_map_io(); 181 s3c244x_map_io();
182 182
183 s3c24xx_gpiocfg_default.set_pull = s3c_gpio_setpull_1down; 183 s3c24xx_gpiocfg_default.set_pull = s3c24xx_gpio_setpull_1down;
184 s3c24xx_gpiocfg_default.get_pull = s3c_gpio_getpull_1down; 184 s3c24xx_gpiocfg_default.get_pull = s3c24xx_gpio_getpull_1down;
185} 185}
diff --git a/arch/arm/mach-s3c2443/Kconfig b/arch/arm/mach-s3c2443/Kconfig
index d8eb86823df7..8814031516ce 100644
--- a/arch/arm/mach-s3c2443/Kconfig
+++ b/arch/arm/mach-s3c2443/Kconfig
@@ -10,7 +10,6 @@ config CPU_S3C2443
10 select CPU_LLSERIAL_S3C2440 10 select CPU_LLSERIAL_S3C2440
11 select SAMSUNG_CLKSRC 11 select SAMSUNG_CLKSRC
12 select S3C2443_CLOCK 12 select S3C2443_CLOCK
13 select S3C_GPIO_PULL_S3C2443
14 help 13 help
15 Support for the S3C2443 SoC from the S3C24XX line 14 Support for the S3C2443 SoC from the S3C24XX line
16 15
diff --git a/arch/arm/mach-s3c2443/clock.c b/arch/arm/mach-s3c2443/clock.c
index 38058af48972..cd51d04e1de7 100644
--- a/arch/arm/mach-s3c2443/clock.c
+++ b/arch/arm/mach-s3c2443/clock.c
@@ -57,10 +57,6 @@
57 57
58/* clock selections */ 58/* clock selections */
59 59
60static struct clk clk_i2s_ext = {
61 .name = "i2s-ext",
62};
63
64/* armdiv 60/* armdiv
65 * 61 *
66 * this clock is sourced from msysclk and can have a number of 62 * this clock is sourced from msysclk and can have a number of
@@ -173,7 +169,7 @@ static struct clksrc_clk clk_arm = {
173 169
174static struct clksrc_clk clk_hsspi = { 170static struct clksrc_clk clk_hsspi = {
175 .clk = { 171 .clk = {
176 .name = "hsspi", 172 .name = "hsspi-if",
177 .parent = &clk_esysclk.clk, 173 .parent = &clk_esysclk.clk,
178 .ctrlbit = S3C2443_SCLKCON_HSSPICLK, 174 .ctrlbit = S3C2443_SCLKCON_HSSPICLK,
179 .enable = s3c2443_clkcon_enable_s, 175 .enable = s3c2443_clkcon_enable_s,
@@ -235,48 +231,6 @@ static struct clk clk_hsmmc = {
235 }, 231 },
236}; 232};
237 233
238/* i2s_eplldiv
239 *
240 * This clock is the output from the I2S divisor of ESYSCLK, and is separate
241 * from the mux that comes after it (cannot merge into one single clock)
242*/
243
244static struct clksrc_clk clk_i2s_eplldiv = {
245 .clk = {
246 .name = "i2s-eplldiv",
247 .parent = &clk_esysclk.clk,
248 },
249 .reg_div = { .reg = S3C2443_CLKDIV1, .size = 4, .shift = 12, },
250};
251
252/* i2s-ref
253 *
254 * i2s bus reference clock, selectable from external, esysclk or epllref
255 *
256 * Note, this used to be two clocks, but was compressed into one.
257*/
258
259struct clk *clk_i2s_srclist[] = {
260 [0] = &clk_i2s_eplldiv.clk,
261 [1] = &clk_i2s_ext,
262 [2] = &clk_epllref.clk,
263 [3] = &clk_epllref.clk,
264};
265
266static struct clksrc_clk clk_i2s = {
267 .clk = {
268 .name = "i2s-if",
269 .ctrlbit = S3C2443_SCLKCON_I2SCLK,
270 .enable = s3c2443_clkcon_enable_s,
271
272 },
273 .sources = &(struct clksrc_sources) {
274 .sources = clk_i2s_srclist,
275 .nr_sources = ARRAY_SIZE(clk_i2s_srclist),
276 },
277 .reg_src = { .reg = S3C2443_CLKSRC, .size = 2, .shift = 14 },
278};
279
280/* standard clock definitions */ 234/* standard clock definitions */
281 235
282static struct clk init_clocks_off[] = { 236static struct clk init_clocks_off[] = {
@@ -286,11 +240,6 @@ static struct clk init_clocks_off[] = {
286 .enable = s3c2443_clkcon_enable_p, 240 .enable = s3c2443_clkcon_enable_p,
287 .ctrlbit = S3C2443_PCLKCON_SDI, 241 .ctrlbit = S3C2443_PCLKCON_SDI,
288 }, { 242 }, {
289 .name = "iis",
290 .parent = &clk_p,
291 .enable = s3c2443_clkcon_enable_p,
292 .ctrlbit = S3C2443_PCLKCON_IIS,
293 }, {
294 .name = "spi", 243 .name = "spi",
295 .devname = "s3c2410-spi.0", 244 .devname = "s3c2410-spi.0",
296 .parent = &clk_p, 245 .parent = &clk_p,
@@ -312,8 +261,6 @@ static struct clk init_clocks[] = {
312 261
313static struct clksrc_clk *clksrcs[] __initdata = { 262static struct clksrc_clk *clksrcs[] __initdata = {
314 &clk_arm, 263 &clk_arm,
315 &clk_i2s_eplldiv,
316 &clk_i2s,
317 &clk_hsspi, 264 &clk_hsspi,
318 &clk_hsmmc_div, 265 &clk_hsmmc_div,
319}; 266};
diff --git a/arch/arm/mach-s3c2443/s3c2443.c b/arch/arm/mach-s3c2443/s3c2443.c
index e6a28ba52c7d..5df6458ddd42 100644
--- a/arch/arm/mach-s3c2443/s3c2443.c
+++ b/arch/arm/mach-s3c2443/s3c2443.c
@@ -90,8 +90,8 @@ void __init s3c2443_init_uarts(struct s3c2410_uartcfg *cfg, int no)
90 90
91void __init s3c2443_map_io(void) 91void __init s3c2443_map_io(void)
92{ 92{
93 s3c24xx_gpiocfg_default.set_pull = s3c_gpio_setpull_s3c2443; 93 s3c24xx_gpiocfg_default.set_pull = s3c2443_gpio_setpull;
94 s3c24xx_gpiocfg_default.get_pull = s3c_gpio_getpull_s3c2443; 94 s3c24xx_gpiocfg_default.get_pull = s3c2443_gpio_getpull;
95 95
96 iotable_init(s3c2443_iodesc, ARRAY_SIZE(s3c2443_iodesc)); 96 iotable_init(s3c2443_iodesc, ARRAY_SIZE(s3c2443_iodesc));
97} 97}
diff --git a/arch/arm/mach-s3c64xx/Kconfig b/arch/arm/mach-s3c64xx/Kconfig
index f057b6ae4f90..5552e048c2be 100644
--- a/arch/arm/mach-s3c64xx/Kconfig
+++ b/arch/arm/mach-s3c64xx/Kconfig
@@ -288,5 +288,6 @@ config MACH_WLF_CRAGG_6410
288 select S3C_DEV_RTC 288 select S3C_DEV_RTC
289 select S3C64XX_DEV_SPI 289 select S3C64XX_DEV_SPI
290 select S3C24XX_GPIO_EXTRA128 290 select S3C24XX_GPIO_EXTRA128
291 select I2C
291 help 292 help
292 Machine support for the Wolfson Cragganmore S3C6410 variant. 293 Machine support for the Wolfson Cragganmore S3C6410 variant.
diff --git a/arch/arm/mach-s3c64xx/Makefile b/arch/arm/mach-s3c64xx/Makefile
index 61b4034a0c22..902ab9ace93b 100644
--- a/arch/arm/mach-s3c64xx/Makefile
+++ b/arch/arm/mach-s3c64xx/Makefile
@@ -13,7 +13,6 @@ obj- :=
13# Core files 13# Core files
14obj-y += cpu.o 14obj-y += cpu.o
15obj-y += clock.o 15obj-y += clock.o
16obj-y += gpiolib.o
17 16
18# Core support for S3C6400 system 17# Core support for S3C6400 system
19 18
@@ -55,7 +54,7 @@ obj-$(CONFIG_MACH_HMT) += mach-hmt.o
55obj-$(CONFIG_MACH_SMARTQ) += mach-smartq.o 54obj-$(CONFIG_MACH_SMARTQ) += mach-smartq.o
56obj-$(CONFIG_MACH_SMARTQ5) += mach-smartq5.o 55obj-$(CONFIG_MACH_SMARTQ5) += mach-smartq5.o
57obj-$(CONFIG_MACH_SMARTQ7) += mach-smartq7.o 56obj-$(CONFIG_MACH_SMARTQ7) += mach-smartq7.o
58obj-$(CONFIG_MACH_WLF_CRAGG_6410) += mach-crag6410.o 57obj-$(CONFIG_MACH_WLF_CRAGG_6410) += mach-crag6410.o mach-crag6410-module.o
59 58
60# device support 59# device support
61 60
diff --git a/arch/arm/mach-s3c64xx/clock.c b/arch/arm/mach-s3c64xx/clock.c
index 8cf39e33579e..872e68361eb4 100644
--- a/arch/arm/mach-s3c64xx/clock.c
+++ b/arch/arm/mach-s3c64xx/clock.c
@@ -744,7 +744,13 @@ void __init_or_cpufreq s3c6400_setup_clocks(void)
744 printk(KERN_INFO "S3C64XX: PLL settings, A=%ld, M=%ld, E=%ld\n", 744 printk(KERN_INFO "S3C64XX: PLL settings, A=%ld, M=%ld, E=%ld\n",
745 apll, mpll, epll); 745 apll, mpll, epll);
746 746
747 hclk2 = mpll / GET_DIV(clkdiv0, S3C6400_CLKDIV0_HCLK2); 747 if(__raw_readl(S3C64XX_OTHERS) & S3C64XX_OTHERS_SYNCMUXSEL)
748 /* Synchronous mode */
749 hclk2 = apll / GET_DIV(clkdiv0, S3C6400_CLKDIV0_HCLK2);
750 else
751 /* Asynchronous mode */
752 hclk2 = mpll / GET_DIV(clkdiv0, S3C6400_CLKDIV0_HCLK2);
753
748 hclk = hclk2 / GET_DIV(clkdiv0, S3C6400_CLKDIV0_HCLK); 754 hclk = hclk2 / GET_DIV(clkdiv0, S3C6400_CLKDIV0_HCLK);
749 pclk = hclk2 / GET_DIV(clkdiv0, S3C6400_CLKDIV0_PCLK); 755 pclk = hclk2 / GET_DIV(clkdiv0, S3C6400_CLKDIV0_PCLK);
750 756
diff --git a/arch/arm/mach-s3c64xx/dma.c b/arch/arm/mach-s3c64xx/dma.c
index 204bfafe4bfc..17d62f4f8204 100644
--- a/arch/arm/mach-s3c64xx/dma.c
+++ b/arch/arm/mach-s3c64xx/dma.c
@@ -147,14 +147,14 @@ static void s3c64xx_dma_fill_lli(struct s3c2410_dma_chan *chan,
147 u32 control0, control1; 147 u32 control0, control1;
148 148
149 switch (chan->source) { 149 switch (chan->source) {
150 case S3C2410_DMASRC_HW: 150 case DMA_FROM_DEVICE:
151 src = chan->dev_addr; 151 src = chan->dev_addr;
152 dst = data; 152 dst = data;
153 control0 = PL080_CONTROL_SRC_AHB2; 153 control0 = PL080_CONTROL_SRC_AHB2;
154 control0 |= PL080_CONTROL_DST_INCR; 154 control0 |= PL080_CONTROL_DST_INCR;
155 break; 155 break;
156 156
157 case S3C2410_DMASRC_MEM: 157 case DMA_TO_DEVICE:
158 src = data; 158 src = data;
159 dst = chan->dev_addr; 159 dst = chan->dev_addr;
160 control0 = PL080_CONTROL_DST_AHB2; 160 control0 = PL080_CONTROL_DST_AHB2;
@@ -416,7 +416,7 @@ EXPORT_SYMBOL(s3c2410_dma_enqueue);
416 416
417 417
418int s3c2410_dma_devconfig(enum dma_ch channel, 418int s3c2410_dma_devconfig(enum dma_ch channel,
419 enum s3c2410_dmasrc source, 419 enum dma_data_direction source,
420 unsigned long devaddr) 420 unsigned long devaddr)
421{ 421{
422 struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel); 422 struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel);
@@ -437,11 +437,11 @@ int s3c2410_dma_devconfig(enum dma_ch channel,
437 pr_debug("%s: peripheral %d\n", __func__, peripheral); 437 pr_debug("%s: peripheral %d\n", __func__, peripheral);
438 438
439 switch (source) { 439 switch (source) {
440 case S3C2410_DMASRC_HW: 440 case DMA_FROM_DEVICE:
441 config = 2 << PL080_CONFIG_FLOW_CONTROL_SHIFT; 441 config = 2 << PL080_CONFIG_FLOW_CONTROL_SHIFT;
442 config |= peripheral << PL080_CONFIG_SRC_SEL_SHIFT; 442 config |= peripheral << PL080_CONFIG_SRC_SEL_SHIFT;
443 break; 443 break;
444 case S3C2410_DMASRC_MEM: 444 case DMA_TO_DEVICE:
445 config = 1 << PL080_CONFIG_FLOW_CONTROL_SHIFT; 445 config = 1 << PL080_CONFIG_FLOW_CONTROL_SHIFT;
446 config |= peripheral << PL080_CONFIG_DST_SEL_SHIFT; 446 config |= peripheral << PL080_CONFIG_DST_SEL_SHIFT;
447 break; 447 break;
@@ -740,7 +740,7 @@ static int __init s3c64xx_dma_init(void)
740 } 740 }
741 741
742 /* Set all DMA configuration to be DMA, not SDMA */ 742 /* Set all DMA configuration to be DMA, not SDMA */
743 writel(0xffffff, S3C_SYSREG(0x110)); 743 writel(0xffffff, S3C64XX_SDMA_SEL);
744 744
745 /* Register standard DMA controllers */ 745 /* Register standard DMA controllers */
746 s3c64xx_dma_init1(0, DMACH_UART0, IRQ_DMA0, 0x75000000); 746 s3c64xx_dma_init1(0, DMACH_UART0, IRQ_DMA0, 0x75000000);
diff --git a/arch/arm/mach-s3c64xx/gpiolib.c b/arch/arm/mach-s3c64xx/gpiolib.c
deleted file mode 100644
index 92b09085caaa..000000000000
--- a/arch/arm/mach-s3c64xx/gpiolib.c
+++ /dev/null
@@ -1,290 +0,0 @@
1/* arch/arm/plat-s3c64xx/gpiolib.c
2 *
3 * Copyright 2008 Openmoko, Inc.
4 * Copyright 2008 Simtec Electronics
5 * Ben Dooks <ben@simtec.co.uk>
6 * http://armlinux.simtec.co.uk/
7 *
8 * S3C64XX - GPIOlib support
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
13 */
14
15#include <linux/kernel.h>
16#include <linux/irq.h>
17#include <linux/io.h>
18#include <linux/gpio.h>
19
20#include <mach/map.h>
21
22#include <plat/gpio-core.h>
23#include <plat/gpio-cfg.h>
24#include <plat/gpio-cfg-helpers.h>
25#include <mach/regs-gpio.h>
26
27/* GPIO bank summary:
28 *
29 * Bank GPIOs Style SlpCon ExtInt Group
30 * A 8 4Bit Yes 1
31 * B 7 4Bit Yes 1
32 * C 8 4Bit Yes 2
33 * D 5 4Bit Yes 3
34 * E 5 4Bit Yes None
35 * F 16 2Bit Yes 4 [1]
36 * G 7 4Bit Yes 5
37 * H 10 4Bit[2] Yes 6
38 * I 16 2Bit Yes None
39 * J 12 2Bit Yes None
40 * K 16 4Bit[2] No None
41 * L 15 4Bit[2] No None
42 * M 6 4Bit No IRQ_EINT
43 * N 16 2Bit No IRQ_EINT
44 * O 16 2Bit Yes 7
45 * P 15 2Bit Yes 8
46 * Q 9 2Bit Yes 9
47 *
48 * [1] BANKF pins 14,15 do not form part of the external interrupt sources
49 * [2] BANK has two control registers, GPxCON0 and GPxCON1
50 */
51
52static struct s3c_gpio_cfg gpio_4bit_cfg_noint = {
53 .set_config = s3c_gpio_setcfg_s3c64xx_4bit,
54 .get_config = s3c_gpio_getcfg_s3c64xx_4bit,
55 .set_pull = s3c_gpio_setpull_updown,
56 .get_pull = s3c_gpio_getpull_updown,
57};
58
59static struct s3c_gpio_cfg gpio_4bit_cfg_eint0111 = {
60 .cfg_eint = 7,
61 .set_config = s3c_gpio_setcfg_s3c64xx_4bit,
62 .get_config = s3c_gpio_getcfg_s3c64xx_4bit,
63 .set_pull = s3c_gpio_setpull_updown,
64 .get_pull = s3c_gpio_getpull_updown,
65};
66
67static struct s3c_gpio_cfg gpio_4bit_cfg_eint0011 = {
68 .cfg_eint = 3,
69 .get_config = s3c_gpio_getcfg_s3c64xx_4bit,
70 .set_config = s3c_gpio_setcfg_s3c64xx_4bit,
71 .set_pull = s3c_gpio_setpull_updown,
72 .get_pull = s3c_gpio_getpull_updown,
73};
74
75static int s3c64xx_gpio2int_gpm(struct gpio_chip *chip, unsigned pin)
76{
77 return pin < 5 ? IRQ_EINT(23) + pin : -ENXIO;
78}
79
80static struct s3c_gpio_chip gpio_4bit[] = {
81 {
82 .base = S3C64XX_GPA_BASE,
83 .config = &gpio_4bit_cfg_eint0111,
84 .chip = {
85 .base = S3C64XX_GPA(0),
86 .ngpio = S3C64XX_GPIO_A_NR,
87 .label = "GPA",
88 },
89 }, {
90 .base = S3C64XX_GPB_BASE,
91 .config = &gpio_4bit_cfg_eint0111,
92 .chip = {
93 .base = S3C64XX_GPB(0),
94 .ngpio = S3C64XX_GPIO_B_NR,
95 .label = "GPB",
96 },
97 }, {
98 .base = S3C64XX_GPC_BASE,
99 .config = &gpio_4bit_cfg_eint0111,
100 .chip = {
101 .base = S3C64XX_GPC(0),
102 .ngpio = S3C64XX_GPIO_C_NR,
103 .label = "GPC",
104 },
105 }, {
106 .base = S3C64XX_GPD_BASE,
107 .config = &gpio_4bit_cfg_eint0111,
108 .chip = {
109 .base = S3C64XX_GPD(0),
110 .ngpio = S3C64XX_GPIO_D_NR,
111 .label = "GPD",
112 },
113 }, {
114 .base = S3C64XX_GPE_BASE,
115 .config = &gpio_4bit_cfg_noint,
116 .chip = {
117 .base = S3C64XX_GPE(0),
118 .ngpio = S3C64XX_GPIO_E_NR,
119 .label = "GPE",
120 },
121 }, {
122 .base = S3C64XX_GPG_BASE,
123 .config = &gpio_4bit_cfg_eint0111,
124 .chip = {
125 .base = S3C64XX_GPG(0),
126 .ngpio = S3C64XX_GPIO_G_NR,
127 .label = "GPG",
128 },
129 }, {
130 .base = S3C64XX_GPM_BASE,
131 .config = &gpio_4bit_cfg_eint0011,
132 .chip = {
133 .base = S3C64XX_GPM(0),
134 .ngpio = S3C64XX_GPIO_M_NR,
135 .label = "GPM",
136 .to_irq = s3c64xx_gpio2int_gpm,
137 },
138 },
139};
140
141static int s3c64xx_gpio2int_gpl(struct gpio_chip *chip, unsigned pin)
142{
143 return pin >= 8 ? IRQ_EINT(16) + pin - 8 : -ENXIO;
144}
145
146static struct s3c_gpio_chip gpio_4bit2[] = {
147 {
148 .base = S3C64XX_GPH_BASE + 0x4,
149 .config = &gpio_4bit_cfg_eint0111,
150 .chip = {
151 .base = S3C64XX_GPH(0),
152 .ngpio = S3C64XX_GPIO_H_NR,
153 .label = "GPH",
154 },
155 }, {
156 .base = S3C64XX_GPK_BASE + 0x4,
157 .config = &gpio_4bit_cfg_noint,
158 .chip = {
159 .base = S3C64XX_GPK(0),
160 .ngpio = S3C64XX_GPIO_K_NR,
161 .label = "GPK",
162 },
163 }, {
164 .base = S3C64XX_GPL_BASE + 0x4,
165 .config = &gpio_4bit_cfg_eint0011,
166 .chip = {
167 .base = S3C64XX_GPL(0),
168 .ngpio = S3C64XX_GPIO_L_NR,
169 .label = "GPL",
170 .to_irq = s3c64xx_gpio2int_gpl,
171 },
172 },
173};
174
175static struct s3c_gpio_cfg gpio_2bit_cfg_noint = {
176 .set_config = s3c_gpio_setcfg_s3c24xx,
177 .get_config = s3c_gpio_getcfg_s3c24xx,
178 .set_pull = s3c_gpio_setpull_updown,
179 .get_pull = s3c_gpio_getpull_updown,
180};
181
182static struct s3c_gpio_cfg gpio_2bit_cfg_eint10 = {
183 .cfg_eint = 2,
184 .set_config = s3c_gpio_setcfg_s3c24xx,
185 .get_config = s3c_gpio_getcfg_s3c24xx,
186 .set_pull = s3c_gpio_setpull_updown,
187 .get_pull = s3c_gpio_getpull_updown,
188};
189
190static struct s3c_gpio_cfg gpio_2bit_cfg_eint11 = {
191 .cfg_eint = 3,
192 .set_config = s3c_gpio_setcfg_s3c24xx,
193 .get_config = s3c_gpio_getcfg_s3c24xx,
194 .set_pull = s3c_gpio_setpull_updown,
195 .get_pull = s3c_gpio_getpull_updown,
196};
197
198static struct s3c_gpio_chip gpio_2bit[] = {
199 {
200 .base = S3C64XX_GPF_BASE,
201 .config = &gpio_2bit_cfg_eint11,
202 .chip = {
203 .base = S3C64XX_GPF(0),
204 .ngpio = S3C64XX_GPIO_F_NR,
205 .label = "GPF",
206 },
207 }, {
208 .base = S3C64XX_GPI_BASE,
209 .config = &gpio_2bit_cfg_noint,
210 .chip = {
211 .base = S3C64XX_GPI(0),
212 .ngpio = S3C64XX_GPIO_I_NR,
213 .label = "GPI",
214 },
215 }, {
216 .base = S3C64XX_GPJ_BASE,
217 .config = &gpio_2bit_cfg_noint,
218 .chip = {
219 .base = S3C64XX_GPJ(0),
220 .ngpio = S3C64XX_GPIO_J_NR,
221 .label = "GPJ",
222 },
223 }, {
224 .base = S3C64XX_GPN_BASE,
225 .irq_base = IRQ_EINT(0),
226 .config = &gpio_2bit_cfg_eint10,
227 .chip = {
228 .base = S3C64XX_GPN(0),
229 .ngpio = S3C64XX_GPIO_N_NR,
230 .label = "GPN",
231 .to_irq = samsung_gpiolib_to_irq,
232 },
233 }, {
234 .base = S3C64XX_GPO_BASE,
235 .config = &gpio_2bit_cfg_eint11,
236 .chip = {
237 .base = S3C64XX_GPO(0),
238 .ngpio = S3C64XX_GPIO_O_NR,
239 .label = "GPO",
240 },
241 }, {
242 .base = S3C64XX_GPP_BASE,
243 .config = &gpio_2bit_cfg_eint11,
244 .chip = {
245 .base = S3C64XX_GPP(0),
246 .ngpio = S3C64XX_GPIO_P_NR,
247 .label = "GPP",
248 },
249 }, {
250 .base = S3C64XX_GPQ_BASE,
251 .config = &gpio_2bit_cfg_eint11,
252 .chip = {
253 .base = S3C64XX_GPQ(0),
254 .ngpio = S3C64XX_GPIO_Q_NR,
255 .label = "GPQ",
256 },
257 },
258};
259
260static __init void s3c64xx_gpiolib_add_2bit(struct s3c_gpio_chip *chip)
261{
262 chip->pm = __gpio_pm(&s3c_gpio_pm_2bit);
263}
264
265static __init void s3c64xx_gpiolib_add(struct s3c_gpio_chip *chips,
266 int nr_chips,
267 void (*fn)(struct s3c_gpio_chip *))
268{
269 for (; nr_chips > 0; nr_chips--, chips++) {
270 if (fn)
271 (fn)(chips);
272 s3c_gpiolib_add(chips);
273 }
274}
275
276static __init int s3c64xx_gpiolib_init(void)
277{
278 s3c64xx_gpiolib_add(gpio_4bit, ARRAY_SIZE(gpio_4bit),
279 samsung_gpiolib_add_4bit);
280
281 s3c64xx_gpiolib_add(gpio_4bit2, ARRAY_SIZE(gpio_4bit2),
282 samsung_gpiolib_add_4bit2);
283
284 s3c64xx_gpiolib_add(gpio_2bit, ARRAY_SIZE(gpio_2bit),
285 s3c64xx_gpiolib_add_2bit);
286
287 return 0;
288}
289
290core_initcall(s3c64xx_gpiolib_init);
diff --git a/arch/arm/mach-s3c64xx/include/mach/crag6410.h b/arch/arm/mach-s3c64xx/include/mach/crag6410.h
new file mode 100644
index 000000000000..be9074e17dfd
--- /dev/null
+++ b/arch/arm/mach-s3c64xx/include/mach/crag6410.h
@@ -0,0 +1,23 @@
1/* Cragganmore 6410 shared definitions
2 *
3 * Copyright 2011 Wolfson Microelectronics plc
4 * Mark Brown <broonie@opensource.wolfsonmicro.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 */
10
11#ifndef MACH_CRAG6410_H
12#define MACH_CRAG6410_H
13
14#include <linux/gpio.h>
15
16#define BANFF_PMIC_IRQ_BASE IRQ_BOARD_START
17#define GLENFARCLAS_PMIC_IRQ_BASE (IRQ_BOARD_START + 64)
18
19#define PCA935X_GPIO_BASE GPIO_BOARD_START
20#define CODEC_GPIO_BASE (GPIO_BOARD_START + 8)
21#define GLENFARCLAS_PMIC_GPIO_BASE (GPIO_BOARD_START + 16)
22
23#endif
diff --git a/arch/arm/mach-s3c64xx/include/mach/dma.h b/arch/arm/mach-s3c64xx/include/mach/dma.h
index 0a5d9268a23e..fe1a98cf0e4c 100644
--- a/arch/arm/mach-s3c64xx/include/mach/dma.h
+++ b/arch/arm/mach-s3c64xx/include/mach/dma.h
@@ -58,11 +58,15 @@ enum dma_ch {
58 DMACH_MAX /* the end */ 58 DMACH_MAX /* the end */
59}; 59};
60 60
61static __inline__ bool s3c_dma_has_circular(void) 61static inline bool samsung_dma_has_circular(void)
62{ 62{
63 return true; 63 return true;
64} 64}
65 65
66static inline bool samsung_dma_is_dmadev(void)
67{
68 return false;
69}
66#define S3C2410_DMAF_CIRCULAR (1 << 0) 70#define S3C2410_DMAF_CIRCULAR (1 << 0)
67 71
68#include <plat/dma.h> 72#include <plat/dma.h>
@@ -95,7 +99,7 @@ struct s3c2410_dma_chan {
95 unsigned char peripheral; 99 unsigned char peripheral;
96 100
97 unsigned int flags; 101 unsigned int flags;
98 enum s3c2410_dmasrc source; 102 enum dma_data_direction source;
99 103
100 104
101 dma_addr_t dev_addr; 105 dma_addr_t dev_addr;
diff --git a/arch/arm/mach-s3c64xx/include/mach/pm-core.h b/arch/arm/mach-s3c64xx/include/mach/pm-core.h
index 38659bebe4b1..fcf3dcabb694 100644
--- a/arch/arm/mach-s3c64xx/include/mach/pm-core.h
+++ b/arch/arm/mach-s3c64xx/include/mach/pm-core.h
@@ -104,7 +104,7 @@ static inline void s3c_pm_restored_gpios(void)
104 __raw_writel(0, S3C64XX_SLPEN); 104 __raw_writel(0, S3C64XX_SLPEN);
105} 105}
106 106
107static inline void s3c_pm_saved_gpios(void) 107static inline void samsung_pm_saved_gpios(void)
108{ 108{
109 /* turn on the sleep mode and keep it there, as it seems that during 109 /* turn on the sleep mode and keep it there, as it seems that during
110 * suspend the xCON registers get re-set and thus you can end up with 110 * suspend the xCON registers get re-set and thus you can end up with
diff --git a/arch/arm/mach-s3c64xx/include/mach/regs-sys.h b/arch/arm/mach-s3c64xx/include/mach/regs-sys.h
index 69b78d9f83b8..b91e02093289 100644
--- a/arch/arm/mach-s3c64xx/include/mach/regs-sys.h
+++ b/arch/arm/mach-s3c64xx/include/mach/regs-sys.h
@@ -21,8 +21,11 @@
21#define S3C64XX_AHB_CON1 S3C_SYSREG(0x104) 21#define S3C64XX_AHB_CON1 S3C_SYSREG(0x104)
22#define S3C64XX_AHB_CON2 S3C_SYSREG(0x108) 22#define S3C64XX_AHB_CON2 S3C_SYSREG(0x108)
23 23
24#define S3C64XX_SDMA_SEL S3C_SYSREG(0x110)
25
24#define S3C64XX_OTHERS S3C_SYSREG(0x900) 26#define S3C64XX_OTHERS S3C_SYSREG(0x900)
25 27
26#define S3C64XX_OTHERS_USBMASK (1 << 16) 28#define S3C64XX_OTHERS_USBMASK (1 << 16)
29#define S3C64XX_OTHERS_SYNCMUXSEL (1 << 6)
27 30
28#endif /* _PLAT_REGS_SYS_H */ 31#endif /* _PLAT_REGS_SYS_H */
diff --git a/arch/arm/mach-s3c64xx/mach-crag6410-module.c b/arch/arm/mach-s3c64xx/mach-crag6410-module.c
new file mode 100644
index 000000000000..66668565ee75
--- /dev/null
+++ b/arch/arm/mach-s3c64xx/mach-crag6410-module.c
@@ -0,0 +1,182 @@
1/* Speyside modules for Cragganmore - board data probing
2 *
3 * Copyright 2011 Wolfson Microelectronics plc
4 * Mark Brown <broonie@opensource.wolfsonmicro.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 */
10
11#include <linux/module.h>
12#include <linux/interrupt.h>
13#include <linux/i2c.h>
14
15#include <linux/mfd/wm831x/irq.h>
16#include <linux/mfd/wm831x/gpio.h>
17
18#include <sound/wm8996.h>
19#include <sound/wm8962.h>
20#include <sound/wm9081.h>
21
22#include <mach/crag6410.h>
23
24static struct wm8996_retune_mobile_config wm8996_retune[] = {
25 {
26 .name = "Sub LPF",
27 .rate = 48000,
28 .regs = {
29 0x6318, 0x6300, 0x1000, 0x0000, 0x0004, 0x2000, 0xF000,
30 0x0000, 0x0004, 0x2000, 0xF000, 0x0000, 0x0004, 0x2000,
31 0xF000, 0x0000, 0x0004, 0x1000, 0x0800, 0x4000
32 },
33 },
34 {
35 .name = "Sub HPF",
36 .rate = 48000,
37 .regs = {
38 0x000A, 0x6300, 0x1000, 0x0000, 0x0004, 0x2000, 0xF000,
39 0x0000, 0x0004, 0x2000, 0xF000, 0x0000, 0x0004, 0x2000,
40 0xF000, 0x0000, 0x0004, 0x1000, 0x0800, 0x4000
41 },
42 },
43};
44
45static struct wm8996_pdata wm8996_pdata __initdata = {
46 .ldo_ena = S3C64XX_GPN(7),
47 .gpio_base = CODEC_GPIO_BASE,
48 .micdet_def = 1,
49 .inl_mode = WM8996_DIFFERRENTIAL_1,
50 .inr_mode = WM8996_DIFFERRENTIAL_1,
51
52 .irq_flags = IRQF_TRIGGER_RISING,
53
54 .gpio_default = {
55 0x8001, /* GPIO1 == ADCLRCLK1 */
56 0x8001, /* GPIO2 == ADCLRCLK2, input due to CPU */
57 0x0141, /* GPIO3 == HP_SEL */
58 0x0002, /* GPIO4 == IRQ */
59 0x020e, /* GPIO5 == CLKOUT */
60 },
61
62 .retune_mobile_cfgs = wm8996_retune,
63 .num_retune_mobile_cfgs = ARRAY_SIZE(wm8996_retune),
64};
65
66static struct wm8962_pdata wm8962_pdata __initdata = {
67 .gpio_init = {
68 0,
69 WM8962_GPIO_FN_OPCLK,
70 WM8962_GPIO_FN_DMICCLK,
71 0,
72 0x8000 | WM8962_GPIO_FN_DMICDAT,
73 WM8962_GPIO_FN_IRQ, /* Open drain mode */
74 },
75 .irq_active_low = true,
76};
77
78static struct wm9081_pdata wm9081_pdata __initdata = {
79 .irq_high = false,
80 .irq_cmos = false,
81};
82
83static const struct i2c_board_info wm1254_devs[] = {
84 { I2C_BOARD_INFO("wm8996", 0x1a),
85 .platform_data = &wm8996_pdata,
86 .irq = GLENFARCLAS_PMIC_IRQ_BASE + WM831X_IRQ_GPIO_2,
87 },
88 { I2C_BOARD_INFO("wm9081", 0x6c),
89 .platform_data = &wm9081_pdata, },
90};
91
92static const struct i2c_board_info wm1255_devs[] = {
93 { I2C_BOARD_INFO("wm5100", 0x1a),
94 .irq = GLENFARCLAS_PMIC_IRQ_BASE + WM831X_IRQ_GPIO_2,
95 },
96 { I2C_BOARD_INFO("wm9081", 0x6c),
97 .platform_data = &wm9081_pdata, },
98};
99
100static const struct i2c_board_info wm1259_devs[] = {
101 { I2C_BOARD_INFO("wm8962", 0x1a),
102 .platform_data = &wm8962_pdata,
103 .irq = GLENFARCLAS_PMIC_IRQ_BASE + WM831X_IRQ_GPIO_2,
104 },
105};
106
107
108static __devinitdata const struct {
109 u8 id;
110 const char *name;
111 const struct i2c_board_info *i2c_devs;
112 int num_i2c_devs;
113} gf_mods[] = {
114 { .id = 0x01, .name = "1250-EV1 Springbank" },
115 { .id = 0x02, .name = "1251-EV1 Jura" },
116 { .id = 0x03, .name = "1252-EV1 Glenlivet" },
117 { .id = 0x11, .name = "6249-EV2 Glenfarclas", },
118 { .id = 0x21, .name = "1275-EV1 Mortlach" },
119 { .id = 0x25, .name = "1274-EV1 Glencadam" },
120 { .id = 0x31, .name = "1253-EV1 Tomatin", },
121 { .id = 0x39, .name = "1254-EV1 Dallas Dhu",
122 .i2c_devs = wm1254_devs, .num_i2c_devs = ARRAY_SIZE(wm1254_devs) },
123 { .id = 0x3a, .name = "1259-EV1 Tobermory",
124 .i2c_devs = wm1259_devs, .num_i2c_devs = ARRAY_SIZE(wm1259_devs) },
125 { .id = 0x3b, .name = "1255-EV1 Kilchoman",
126 .i2c_devs = wm1255_devs, .num_i2c_devs = ARRAY_SIZE(wm1255_devs) },
127 { .id = 0x3c, .name = "1273-EV1 Longmorn" },
128};
129
130static __devinit int wlf_gf_module_probe(struct i2c_client *i2c,
131 const struct i2c_device_id *i2c_id)
132{
133 int ret, i, j, id, rev;
134
135 ret = i2c_smbus_read_byte_data(i2c, 0);
136 if (ret < 0) {
137 dev_err(&i2c->dev, "Failed to read ID: %d\n", ret);
138 return ret;
139 }
140
141 id = (ret & 0xfe) >> 2;
142 rev = ret & 0x3;
143 for (i = 0; i < ARRAY_SIZE(gf_mods); i++)
144 if (id == gf_mods[i].id)
145 break;
146
147 if (i < ARRAY_SIZE(gf_mods)) {
148 dev_info(&i2c->dev, "%s revision %d\n",
149 gf_mods[i].name, rev + 1);
150 for (j = 0; j < gf_mods[i].num_i2c_devs; j++) {
151 if (!i2c_new_device(i2c->adapter,
152 &(gf_mods[i].i2c_devs[j])))
153 dev_err(&i2c->dev,
154 "Failed to register dev: %d\n", ret);
155 }
156 } else {
157 dev_warn(&i2c->dev, "Unknown module ID %d revision %d\n",
158 id, rev);
159 }
160
161 return 0;
162}
163
164static const struct i2c_device_id wlf_gf_module_id[] = {
165 { "wlf-gf-module", 0 },
166 { }
167};
168
169static struct i2c_driver wlf_gf_module_driver = {
170 .driver = {
171 .name = "wlf-gf-module",
172 .owner = THIS_MODULE,
173 },
174 .probe = wlf_gf_module_probe,
175 .id_table = wlf_gf_module_id,
176};
177
178static int __init wlf_gf_module_register(void)
179{
180 return i2c_add_driver(&wlf_gf_module_driver);
181}
182module_init(wlf_gf_module_register);
diff --git a/arch/arm/mach-s3c64xx/mach-crag6410.c b/arch/arm/mach-s3c64xx/mach-crag6410.c
index f32ec68002ef..30afaa537fcf 100644
--- a/arch/arm/mach-s3c64xx/mach-crag6410.c
+++ b/arch/arm/mach-s3c64xx/mach-crag6410.c
@@ -47,6 +47,7 @@
47#include <mach/regs-sys.h> 47#include <mach/regs-sys.h>
48#include <mach/regs-gpio.h> 48#include <mach/regs-gpio.h>
49#include <mach/regs-modem.h> 49#include <mach/regs-modem.h>
50#include <mach/crag6410.h>
50 51
51#include <mach/regs-gpio-memport.h> 52#include <mach/regs-gpio-memport.h>
52 53
@@ -65,17 +66,6 @@
65#include <plat/iic.h> 66#include <plat/iic.h>
66#include <plat/pm.h> 67#include <plat/pm.h>
67 68
68#include <sound/wm8996.h>
69#include <sound/wm8962.h>
70#include <sound/wm9081.h>
71
72#define BANFF_PMIC_IRQ_BASE IRQ_BOARD_START
73#define GLENFARCLAS_PMIC_IRQ_BASE (IRQ_BOARD_START + 64)
74
75#define PCA935X_GPIO_BASE GPIO_BOARD_START
76#define CODEC_GPIO_BASE (GPIO_BOARD_START + 8)
77#define GLENFARCLAS_PMIC_GPIO_BASE (GPIO_BOARD_START + 16)
78
79/* serial port setup */ 69/* serial port setup */
80 70
81#define UCON (S3C2410_UCON_DEFAULT | S3C2410_UCON_UCLK) 71#define UCON (S3C2410_UCON_DEFAULT | S3C2410_UCON_UCLK)
@@ -287,6 +277,11 @@ static struct platform_device speyside_device = {
287 .id = -1, 277 .id = -1,
288}; 278};
289 279
280static struct platform_device lowland_device = {
281 .name = "lowland",
282 .id = -1,
283};
284
290static struct platform_device speyside_wm8962_device = { 285static struct platform_device speyside_wm8962_device = {
291 .name = "speyside-wm8962", 286 .name = "speyside-wm8962",
292 .id = -1, 287 .id = -1,
@@ -295,6 +290,8 @@ static struct platform_device speyside_wm8962_device = {
295static struct regulator_consumer_supply wallvdd_consumers[] = { 290static struct regulator_consumer_supply wallvdd_consumers[] = {
296 REGULATOR_SUPPLY("SPKVDD1", "1-001a"), 291 REGULATOR_SUPPLY("SPKVDD1", "1-001a"),
297 REGULATOR_SUPPLY("SPKVDD2", "1-001a"), 292 REGULATOR_SUPPLY("SPKVDD2", "1-001a"),
293 REGULATOR_SUPPLY("SPKVDDL", "1-001a"),
294 REGULATOR_SUPPLY("SPKVDDR", "1-001a"),
298}; 295};
299 296
300static struct regulator_init_data wallvdd_data = { 297static struct regulator_init_data wallvdd_data = {
@@ -342,6 +339,7 @@ static struct platform_device *crag6410_devices[] __initdata = {
342 &crag6410_backlight_device, 339 &crag6410_backlight_device,
343 &speyside_device, 340 &speyside_device,
344 &speyside_wm8962_device, 341 &speyside_wm8962_device,
342 &lowland_device,
345 &wallvdd_device, 343 &wallvdd_device,
346}; 344};
347 345
@@ -350,6 +348,12 @@ static struct pca953x_platform_data crag6410_pca_data = {
350 .irq_base = 0, 348 .irq_base = 0,
351}; 349};
352 350
351/* VDDARM is controlled by DVS1 connected to GPK(0) */
352static struct wm831x_buckv_pdata vddarm_pdata = {
353 .dvs_control_src = 1,
354 .dvs_gpio = S3C64XX_GPK(0),
355};
356
353static struct regulator_consumer_supply vddarm_consumers[] __initdata = { 357static struct regulator_consumer_supply vddarm_consumers[] __initdata = {
354 REGULATOR_SUPPLY("vddarm", NULL), 358 REGULATOR_SUPPLY("vddarm", NULL),
355}; 359};
@@ -365,6 +369,7 @@ static struct regulator_init_data vddarm __initdata = {
365 .num_consumer_supplies = ARRAY_SIZE(vddarm_consumers), 369 .num_consumer_supplies = ARRAY_SIZE(vddarm_consumers),
366 .consumer_supplies = vddarm_consumers, 370 .consumer_supplies = vddarm_consumers,
367 .supply_regulator = "WALLVDD", 371 .supply_regulator = "WALLVDD",
372 .driver_data = &vddarm_pdata,
368}; 373};
369 374
370static struct regulator_init_data vddint __initdata = { 375static struct regulator_init_data vddint __initdata = {
@@ -500,6 +505,8 @@ static struct wm831x_pdata crag_pmic_pdata __initdata = {
500 .backup = &banff_backup_pdata, 505 .backup = &banff_backup_pdata,
501 506
502 .gpio_defaults = { 507 .gpio_defaults = {
508 /* GPIO5: DVS1_REQ - CMOS, DBVDD, active high */
509 [4] = WM831X_GPN_DIR | WM831X_GPN_POL | WM831X_GPN_ENA | 0x8,
503 /* GPIO11: Touchscreen data - CMOS, DBVDD, active high*/ 510 /* GPIO11: Touchscreen data - CMOS, DBVDD, active high*/
504 [10] = WM831X_GPN_POL | WM831X_GPN_ENA | 0x6, 511 [10] = WM831X_GPN_POL | WM831X_GPN_ENA | 0x6,
505 /* GPIO12: Touchscreen pen down - CMOS, DBVDD, active high*/ 512 /* GPIO12: Touchscreen pen down - CMOS, DBVDD, active high*/
@@ -557,8 +564,12 @@ static struct regulator_init_data pvdd_1v2 __initdata = {
557}; 564};
558 565
559static struct regulator_consumer_supply pvdd_1v8_consumers[] __initdata = { 566static struct regulator_consumer_supply pvdd_1v8_consumers[] __initdata = {
567 REGULATOR_SUPPLY("LDOVDD", "1-001a"),
560 REGULATOR_SUPPLY("PLLVDD", "1-001a"), 568 REGULATOR_SUPPLY("PLLVDD", "1-001a"),
561 REGULATOR_SUPPLY("DBVDD", "1-001a"), 569 REGULATOR_SUPPLY("DBVDD", "1-001a"),
570 REGULATOR_SUPPLY("DBVDD1", "1-001a"),
571 REGULATOR_SUPPLY("DBVDD2", "1-001a"),
572 REGULATOR_SUPPLY("DBVDD3", "1-001a"),
562 REGULATOR_SUPPLY("CPVDD", "1-001a"), 573 REGULATOR_SUPPLY("CPVDD", "1-001a"),
563 REGULATOR_SUPPLY("AVDD2", "1-001a"), 574 REGULATOR_SUPPLY("AVDD2", "1-001a"),
564 REGULATOR_SUPPLY("DCVDD", "1-001a"), 575 REGULATOR_SUPPLY("DCVDD", "1-001a"),
@@ -611,81 +622,16 @@ static struct wm831x_pdata glenfarclas_pmic_pdata __initdata = {
611 .disable_touch = true, 622 .disable_touch = true,
612}; 623};
613 624
614static struct wm8996_retune_mobile_config wm8996_retune[] = {
615 {
616 .name = "Sub LPF",
617 .rate = 48000,
618 .regs = {
619 0x6318, 0x6300, 0x1000, 0x0000, 0x0004, 0x2000, 0xF000,
620 0x0000, 0x0004, 0x2000, 0xF000, 0x0000, 0x0004, 0x2000,
621 0xF000, 0x0000, 0x0004, 0x1000, 0x0800, 0x4000
622 },
623 },
624 {
625 .name = "Sub HPF",
626 .rate = 48000,
627 .regs = {
628 0x000A, 0x6300, 0x1000, 0x0000, 0x0004, 0x2000, 0xF000,
629 0x0000, 0x0004, 0x2000, 0xF000, 0x0000, 0x0004, 0x2000,
630 0xF000, 0x0000, 0x0004, 0x1000, 0x0800, 0x4000
631 },
632 },
633};
634
635static struct wm8996_pdata wm8996_pdata __initdata = {
636 .ldo_ena = S3C64XX_GPN(7),
637 .gpio_base = CODEC_GPIO_BASE,
638 .micdet_def = 1,
639 .inl_mode = WM8996_DIFFERRENTIAL_1,
640 .inr_mode = WM8996_DIFFERRENTIAL_1,
641
642 .irq_flags = IRQF_TRIGGER_RISING,
643
644 .gpio_default = {
645 0x8001, /* GPIO1 == ADCLRCLK1 */
646 0x8001, /* GPIO2 == ADCLRCLK2, input due to CPU */
647 0x0141, /* GPIO3 == HP_SEL */
648 0x0002, /* GPIO4 == IRQ */
649 0x020e, /* GPIO5 == CLKOUT */
650 },
651
652 .retune_mobile_cfgs = wm8996_retune,
653 .num_retune_mobile_cfgs = ARRAY_SIZE(wm8996_retune),
654};
655
656static struct wm8962_pdata wm8962_pdata __initdata = {
657 .gpio_init = {
658 0,
659 WM8962_GPIO_FN_OPCLK,
660 WM8962_GPIO_FN_DMICCLK,
661 0,
662 0x8000 | WM8962_GPIO_FN_DMICDAT,
663 WM8962_GPIO_FN_IRQ, /* Open drain mode */
664 },
665 .irq_active_low = true,
666};
667
668static struct wm9081_pdata wm9081_pdata __initdata = {
669 .irq_high = false,
670 .irq_cmos = false,
671};
672
673static struct i2c_board_info i2c_devs1[] __initdata = { 625static struct i2c_board_info i2c_devs1[] __initdata = {
674 { I2C_BOARD_INFO("wm8311", 0x34), 626 { I2C_BOARD_INFO("wm8311", 0x34),
675 .irq = S3C_EINT(0), 627 .irq = S3C_EINT(0),
676 .platform_data = &glenfarclas_pmic_pdata }, 628 .platform_data = &glenfarclas_pmic_pdata },
677 629
630 { I2C_BOARD_INFO("wlf-gf-module", 0x24) },
631 { I2C_BOARD_INFO("wlf-gf-module", 0x25) },
632 { I2C_BOARD_INFO("wlf-gf-module", 0x26) },
633
678 { I2C_BOARD_INFO("wm1250-ev1", 0x27) }, 634 { I2C_BOARD_INFO("wm1250-ev1", 0x27) },
679 { I2C_BOARD_INFO("wm8996", 0x1a),
680 .platform_data = &wm8996_pdata,
681 .irq = GLENFARCLAS_PMIC_IRQ_BASE + WM831X_IRQ_GPIO_2,
682 },
683 { I2C_BOARD_INFO("wm9081", 0x6c),
684 .platform_data = &wm9081_pdata, },
685 { I2C_BOARD_INFO("wm8962", 0x1a),
686 .platform_data = &wm8962_pdata,
687 .irq = GLENFARCLAS_PMIC_IRQ_BASE + WM831X_IRQ_GPIO_2,
688 },
689}; 635};
690 636
691static void __init crag6410_map_io(void) 637static void __init crag6410_map_io(void)
diff --git a/arch/arm/mach-s3c64xx/pm.c b/arch/arm/mach-s3c64xx/pm.c
index 055e2858b0dd..b375cd5c47cb 100644
--- a/arch/arm/mach-s3c64xx/pm.c
+++ b/arch/arm/mach-s3c64xx/pm.c
@@ -29,6 +29,7 @@
29#include <mach/regs-clock.h> 29#include <mach/regs-clock.h>
30#include <mach/regs-syscon-power.h> 30#include <mach/regs-syscon-power.h>
31#include <mach/regs-gpio-memport.h> 31#include <mach/regs-gpio-memport.h>
32#include <mach/regs-modem.h>
32 33
33#ifdef CONFIG_S3C_PM_DEBUG_LED_SMDK 34#ifdef CONFIG_S3C_PM_DEBUG_LED_SMDK
34void s3c_pm_debug_smdkled(u32 set, u32 clear) 35void s3c_pm_debug_smdkled(u32 set, u32 clear)
@@ -85,6 +86,9 @@ static struct sleep_save misc_save[] = {
85 SAVE_ITEM(S3C64XX_MEM0CONSLP0), 86 SAVE_ITEM(S3C64XX_MEM0CONSLP0),
86 SAVE_ITEM(S3C64XX_MEM0CONSLP1), 87 SAVE_ITEM(S3C64XX_MEM0CONSLP1),
87 SAVE_ITEM(S3C64XX_MEM1CONSLP), 88 SAVE_ITEM(S3C64XX_MEM1CONSLP),
89
90 SAVE_ITEM(S3C64XX_SDMA_SEL),
91 SAVE_ITEM(S3C64XX_MODEM_MIFPCON),
88}; 92};
89 93
90void s3c_pm_configure_extint(void) 94void s3c_pm_configure_extint(void)
diff --git a/arch/arm/mach-s5p64x0/Kconfig b/arch/arm/mach-s5p64x0/Kconfig
index 65c7518dad7f..e361c41314e9 100644
--- a/arch/arm/mach-s5p64x0/Kconfig
+++ b/arch/arm/mach-s5p64x0/Kconfig
@@ -9,18 +9,24 @@ if ARCH_S5P64X0
9 9
10config CPU_S5P6440 10config CPU_S5P6440
11 bool 11 bool
12 select S3C_PL330_DMA 12 select SAMSUNG_DMADEV
13 select S5P_HRT 13 select S5P_HRT
14 help 14 help
15 Enable S5P6440 CPU support 15 Enable S5P6440 CPU support
16 16
17config CPU_S5P6450 17config CPU_S5P6450
18 bool 18 bool
19 select S3C_PL330_DMA 19 select SAMSUNG_DMADEV
20 select S5P_HRT 20 select S5P_HRT
21 help 21 help
22 Enable S5P6450 CPU support 22 Enable S5P6450 CPU support
23 23
24config S5P64X0_SETUP_FB_24BPP
25 bool
26 help
27 Common setup code for S5P64X0 based boards with a LCD display
28 through RGB interface.
29
24config S5P64X0_SETUP_I2C1 30config S5P64X0_SETUP_I2C1
25 bool 31 bool
26 help 32 help
@@ -31,6 +37,7 @@ config S5P64X0_SETUP_I2C1
31config MACH_SMDK6440 37config MACH_SMDK6440
32 bool "SMDK6440" 38 bool "SMDK6440"
33 select CPU_S5P6440 39 select CPU_S5P6440
40 select S3C_DEV_FB
34 select S3C_DEV_I2C1 41 select S3C_DEV_I2C1
35 select S3C_DEV_RTC 42 select S3C_DEV_RTC
36 select S3C_DEV_WDT 43 select S3C_DEV_WDT
@@ -39,6 +46,7 @@ config MACH_SMDK6440
39 select SAMSUNG_DEV_BACKLIGHT 46 select SAMSUNG_DEV_BACKLIGHT
40 select SAMSUNG_DEV_PWM 47 select SAMSUNG_DEV_PWM
41 select SAMSUNG_DEV_TS 48 select SAMSUNG_DEV_TS
49 select S5P64X0_SETUP_FB_24BPP
42 select S5P64X0_SETUP_I2C1 50 select S5P64X0_SETUP_I2C1
43 help 51 help
44 Machine support for the Samsung SMDK6440 52 Machine support for the Samsung SMDK6440
@@ -46,6 +54,7 @@ config MACH_SMDK6440
46config MACH_SMDK6450 54config MACH_SMDK6450
47 bool "SMDK6450" 55 bool "SMDK6450"
48 select CPU_S5P6450 56 select CPU_S5P6450
57 select S3C_DEV_FB
49 select S3C_DEV_I2C1 58 select S3C_DEV_I2C1
50 select S3C_DEV_RTC 59 select S3C_DEV_RTC
51 select S3C_DEV_WDT 60 select S3C_DEV_WDT
@@ -54,6 +63,7 @@ config MACH_SMDK6450
54 select SAMSUNG_DEV_BACKLIGHT 63 select SAMSUNG_DEV_BACKLIGHT
55 select SAMSUNG_DEV_PWM 64 select SAMSUNG_DEV_PWM
56 select SAMSUNG_DEV_TS 65 select SAMSUNG_DEV_TS
66 select S5P64X0_SETUP_FB_24BPP
57 select S5P64X0_SETUP_I2C1 67 select S5P64X0_SETUP_I2C1
58 help 68 help
59 Machine support for the Samsung SMDK6450 69 Machine support for the Samsung SMDK6450
diff --git a/arch/arm/mach-s5p64x0/Makefile b/arch/arm/mach-s5p64x0/Makefile
index 5f6afdf067ed..eb7468012a37 100644
--- a/arch/arm/mach-s5p64x0/Makefile
+++ b/arch/arm/mach-s5p64x0/Makefile
@@ -12,7 +12,7 @@ obj- :=
12 12
13# Core support for S5P64X0 system 13# Core support for S5P64X0 system
14 14
15obj-$(CONFIG_ARCH_S5P64X0) += cpu.o init.o clock.o dma.o gpiolib.o 15obj-$(CONFIG_ARCH_S5P64X0) += cpu.o init.o clock.o dma.o
16obj-$(CONFIG_ARCH_S5P64X0) += setup-i2c0.o irq-eint.o 16obj-$(CONFIG_ARCH_S5P64X0) += setup-i2c0.o irq-eint.o
17obj-$(CONFIG_CPU_S5P6440) += clock-s5p6440.o 17obj-$(CONFIG_CPU_S5P6440) += clock-s5p6440.o
18obj-$(CONFIG_CPU_S5P6450) += clock-s5p6450.o 18obj-$(CONFIG_CPU_S5P6450) += clock-s5p6450.o
@@ -28,3 +28,4 @@ obj-y += dev-audio.o
28obj-$(CONFIG_S3C64XX_DEV_SPI) += dev-spi.o 28obj-$(CONFIG_S3C64XX_DEV_SPI) += dev-spi.o
29 29
30obj-$(CONFIG_S5P64X0_SETUP_I2C1) += setup-i2c1.o 30obj-$(CONFIG_S5P64X0_SETUP_I2C1) += setup-i2c1.o
31obj-$(CONFIG_S5P64X0_SETUP_FB_24BPP) += setup-fb-24bpp.o
diff --git a/arch/arm/mach-s5p64x0/clock-s5p6440.c b/arch/arm/mach-s5p64x0/clock-s5p6440.c
index 0e9cd3092dd2..c54c65d511f0 100644
--- a/arch/arm/mach-s5p64x0/clock-s5p6440.c
+++ b/arch/arm/mach-s5p64x0/clock-s5p6440.c
@@ -146,7 +146,8 @@ static struct clk init_clocks_off[] = {
146 .enable = s5p64x0_hclk0_ctrl, 146 .enable = s5p64x0_hclk0_ctrl,
147 .ctrlbit = (1 << 8), 147 .ctrlbit = (1 << 8),
148 }, { 148 }, {
149 .name = "pdma", 149 .name = "dma",
150 .devname = "dma-pl330",
150 .parent = &clk_hclk_low.clk, 151 .parent = &clk_hclk_low.clk,
151 .enable = s5p64x0_hclk0_ctrl, 152 .enable = s5p64x0_hclk0_ctrl,
152 .ctrlbit = (1 << 12), 153 .ctrlbit = (1 << 12),
@@ -499,6 +500,11 @@ static struct clksrc_clk *sysclks[] = {
499 &clk_pclk_low, 500 &clk_pclk_low,
500}; 501};
501 502
503static struct clk dummy_apb_pclk = {
504 .name = "apb_pclk",
505 .id = -1,
506};
507
502void __init_or_cpufreq s5p6440_setup_clocks(void) 508void __init_or_cpufreq s5p6440_setup_clocks(void)
503{ 509{
504 struct clk *xtal_clk; 510 struct clk *xtal_clk;
@@ -581,5 +587,7 @@ void __init s5p6440_register_clocks(void)
581 s3c_register_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off)); 587 s3c_register_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
582 s3c_disable_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off)); 588 s3c_disable_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
583 589
590 s3c24xx_register_clock(&dummy_apb_pclk);
591
584 s3c_pwmclk_init(); 592 s3c_pwmclk_init();
585} 593}
diff --git a/arch/arm/mach-s5p64x0/clock-s5p6450.c b/arch/arm/mach-s5p64x0/clock-s5p6450.c
index d9dc16cde109..2d04abfba12e 100644
--- a/arch/arm/mach-s5p64x0/clock-s5p6450.c
+++ b/arch/arm/mach-s5p64x0/clock-s5p6450.c
@@ -179,7 +179,8 @@ static struct clk init_clocks_off[] = {
179 .enable = s5p64x0_hclk0_ctrl, 179 .enable = s5p64x0_hclk0_ctrl,
180 .ctrlbit = (1 << 3), 180 .ctrlbit = (1 << 3),
181 }, { 181 }, {
182 .name = "pdma", 182 .name = "dma",
183 .devname = "dma-pl330",
183 .parent = &clk_hclk_low.clk, 184 .parent = &clk_hclk_low.clk,
184 .enable = s5p64x0_hclk0_ctrl, 185 .enable = s5p64x0_hclk0_ctrl,
185 .ctrlbit = (1 << 12), 186 .ctrlbit = (1 << 12),
@@ -553,6 +554,11 @@ static struct clksrc_clk *sysclks[] = {
553 &clk_sclk_audio0, 554 &clk_sclk_audio0,
554}; 555};
555 556
557static struct clk dummy_apb_pclk = {
558 .name = "apb_pclk",
559 .id = -1,
560};
561
556void __init_or_cpufreq s5p6450_setup_clocks(void) 562void __init_or_cpufreq s5p6450_setup_clocks(void)
557{ 563{
558 struct clk *xtal_clk; 564 struct clk *xtal_clk;
@@ -632,5 +638,7 @@ void __init s5p6450_register_clocks(void)
632 s3c_register_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off)); 638 s3c_register_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
633 s3c_disable_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off)); 639 s3c_disable_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
634 640
641 s3c24xx_register_clock(&dummy_apb_pclk);
642
635 s3c_pwmclk_init(); 643 s3c_pwmclk_init();
636} 644}
diff --git a/arch/arm/mach-s5p64x0/cpu.c b/arch/arm/mach-s5p64x0/cpu.c
index a5c00952ea35..617da3b3bfb7 100644
--- a/arch/arm/mach-s5p64x0/cpu.c
+++ b/arch/arm/mach-s5p64x0/cpu.c
@@ -38,6 +38,7 @@
38#include <plat/s5p6440.h> 38#include <plat/s5p6440.h>
39#include <plat/s5p6450.h> 39#include <plat/s5p6450.h>
40#include <plat/adc-core.h> 40#include <plat/adc-core.h>
41#include <plat/fb-core.h>
41 42
42/* Initial IO mappings */ 43/* Initial IO mappings */
43 44
@@ -108,6 +109,7 @@ void __init s5p6440_map_io(void)
108{ 109{
109 /* initialize any device information early */ 110 /* initialize any device information early */
110 s3c_adc_setname("s3c64xx-adc"); 111 s3c_adc_setname("s3c64xx-adc");
112 s3c_fb_setname("s5p64x0-fb");
111 113
112 iotable_init(s5p64x0_iodesc, ARRAY_SIZE(s5p64x0_iodesc)); 114 iotable_init(s5p64x0_iodesc, ARRAY_SIZE(s5p64x0_iodesc));
113 iotable_init(s5p6440_iodesc, ARRAY_SIZE(s5p6440_iodesc)); 115 iotable_init(s5p6440_iodesc, ARRAY_SIZE(s5p6440_iodesc));
@@ -117,6 +119,7 @@ void __init s5p6450_map_io(void)
117{ 119{
118 /* initialize any device information early */ 120 /* initialize any device information early */
119 s3c_adc_setname("s3c64xx-adc"); 121 s3c_adc_setname("s3c64xx-adc");
122 s3c_fb_setname("s5p64x0-fb");
120 123
121 iotable_init(s5p64x0_iodesc, ARRAY_SIZE(s5p64x0_iodesc)); 124 iotable_init(s5p64x0_iodesc, ARRAY_SIZE(s5p64x0_iodesc));
122 iotable_init(s5p6450_iodesc, ARRAY_SIZE(s5p6450_iodesc)); 125 iotable_init(s5p6450_iodesc, ARRAY_SIZE(s5p6450_iodesc));
diff --git a/arch/arm/mach-s5p64x0/dma.c b/arch/arm/mach-s5p64x0/dma.c
index 0e5b3e63e5b3..442dd4ad12da 100644
--- a/arch/arm/mach-s5p64x0/dma.c
+++ b/arch/arm/mach-s5p64x0/dma.c
@@ -21,115 +21,208 @@
21 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 21 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22*/ 22*/
23 23
24#include <linux/platform_device.h>
25#include <linux/dma-mapping.h> 24#include <linux/dma-mapping.h>
25#include <linux/amba/bus.h>
26#include <linux/amba/pl330.h>
27
28#include <asm/irq.h>
26 29
27#include <mach/map.h> 30#include <mach/map.h>
28#include <mach/irqs.h> 31#include <mach/irqs.h>
29#include <mach/regs-clock.h> 32#include <mach/regs-clock.h>
33#include <mach/dma.h>
30 34
31#include <plat/cpu.h> 35#include <plat/cpu.h>
32#include <plat/devs.h> 36#include <plat/devs.h>
33#include <plat/s3c-pl330-pdata.h> 37#include <plat/irqs.h>
34 38
35static u64 dma_dmamask = DMA_BIT_MASK(32); 39static u64 dma_dmamask = DMA_BIT_MASK(32);
36 40
37static struct resource s5p64x0_pdma_resource[] = { 41struct dma_pl330_peri s5p6440_pdma_peri[22] = {
38 [0] = { 42 {
39 .start = S5P64X0_PA_PDMA, 43 .peri_id = (u8)DMACH_UART0_RX,
40 .end = S5P64X0_PA_PDMA + SZ_4K, 44 .rqtype = DEVTOMEM,
41 .flags = IORESOURCE_MEM, 45 }, {
42 }, 46 .peri_id = (u8)DMACH_UART0_TX,
43 [1] = { 47 .rqtype = MEMTODEV,
44 .start = IRQ_DMA0, 48 }, {
45 .end = IRQ_DMA0, 49 .peri_id = (u8)DMACH_UART1_RX,
46 .flags = IORESOURCE_IRQ, 50 .rqtype = DEVTOMEM,
51 }, {
52 .peri_id = (u8)DMACH_UART1_TX,
53 .rqtype = MEMTODEV,
54 }, {
55 .peri_id = (u8)DMACH_UART2_RX,
56 .rqtype = DEVTOMEM,
57 }, {
58 .peri_id = (u8)DMACH_UART2_TX,
59 .rqtype = MEMTODEV,
60 }, {
61 .peri_id = (u8)DMACH_UART3_RX,
62 .rqtype = DEVTOMEM,
63 }, {
64 .peri_id = (u8)DMACH_UART3_TX,
65 .rqtype = MEMTODEV,
66 }, {
67 .peri_id = DMACH_MAX,
68 }, {
69 .peri_id = DMACH_MAX,
70 }, {
71 .peri_id = (u8)DMACH_PCM0_TX,
72 .rqtype = MEMTODEV,
73 }, {
74 .peri_id = (u8)DMACH_PCM0_RX,
75 .rqtype = DEVTOMEM,
76 }, {
77 .peri_id = (u8)DMACH_I2S0_TX,
78 .rqtype = MEMTODEV,
79 }, {
80 .peri_id = (u8)DMACH_I2S0_RX,
81 .rqtype = DEVTOMEM,
82 }, {
83 .peri_id = (u8)DMACH_SPI0_TX,
84 .rqtype = MEMTODEV,
85 }, {
86 .peri_id = (u8)DMACH_SPI0_RX,
87 .rqtype = DEVTOMEM,
88 }, {
89 .peri_id = (u8)DMACH_MAX,
90 }, {
91 .peri_id = (u8)DMACH_MAX,
92 }, {
93 .peri_id = (u8)DMACH_MAX,
94 }, {
95 .peri_id = (u8)DMACH_MAX,
96 }, {
97 .peri_id = (u8)DMACH_SPI1_TX,
98 .rqtype = MEMTODEV,
99 }, {
100 .peri_id = (u8)DMACH_SPI1_RX,
101 .rqtype = DEVTOMEM,
47 }, 102 },
48}; 103};
49 104
50static struct s3c_pl330_platdata s5p6440_pdma_pdata = { 105struct dma_pl330_platdata s5p6440_pdma_pdata = {
51 .peri = { 106 .nr_valid_peri = ARRAY_SIZE(s5p6440_pdma_peri),
52 [0] = DMACH_UART0_RX, 107 .peri = s5p6440_pdma_peri,
53 [1] = DMACH_UART0_TX,
54 [2] = DMACH_UART1_RX,
55 [3] = DMACH_UART1_TX,
56 [4] = DMACH_UART2_RX,
57 [5] = DMACH_UART2_TX,
58 [6] = DMACH_UART3_RX,
59 [7] = DMACH_UART3_TX,
60 [8] = DMACH_MAX,
61 [9] = DMACH_MAX,
62 [10] = DMACH_PCM0_TX,
63 [11] = DMACH_PCM0_RX,
64 [12] = DMACH_I2S0_TX,
65 [13] = DMACH_I2S0_RX,
66 [14] = DMACH_SPI0_TX,
67 [15] = DMACH_SPI0_RX,
68 [16] = DMACH_MAX,
69 [17] = DMACH_MAX,
70 [18] = DMACH_MAX,
71 [19] = DMACH_MAX,
72 [20] = DMACH_SPI1_TX,
73 [21] = DMACH_SPI1_RX,
74 [22] = DMACH_MAX,
75 [23] = DMACH_MAX,
76 [24] = DMACH_MAX,
77 [25] = DMACH_MAX,
78 [26] = DMACH_MAX,
79 [27] = DMACH_MAX,
80 [28] = DMACH_MAX,
81 [29] = DMACH_PWM,
82 [30] = DMACH_MAX,
83 [31] = DMACH_MAX,
84 },
85}; 108};
86 109
87static struct s3c_pl330_platdata s5p6450_pdma_pdata = { 110struct dma_pl330_peri s5p6450_pdma_peri[32] = {
88 .peri = { 111 {
89 [0] = DMACH_UART0_RX, 112 .peri_id = (u8)DMACH_UART0_RX,
90 [1] = DMACH_UART0_TX, 113 .rqtype = DEVTOMEM,
91 [2] = DMACH_UART1_RX, 114 }, {
92 [3] = DMACH_UART1_TX, 115 .peri_id = (u8)DMACH_UART0_TX,
93 [4] = DMACH_UART2_RX, 116 .rqtype = MEMTODEV,
94 [5] = DMACH_UART2_TX, 117 }, {
95 [6] = DMACH_UART3_RX, 118 .peri_id = (u8)DMACH_UART1_RX,
96 [7] = DMACH_UART3_TX, 119 .rqtype = DEVTOMEM,
97 [8] = DMACH_UART4_RX, 120 }, {
98 [9] = DMACH_UART4_TX, 121 .peri_id = (u8)DMACH_UART1_TX,
99 [10] = DMACH_PCM0_TX, 122 .rqtype = MEMTODEV,
100 [11] = DMACH_PCM0_RX, 123 }, {
101 [12] = DMACH_I2S0_TX, 124 .peri_id = (u8)DMACH_UART2_RX,
102 [13] = DMACH_I2S0_RX, 125 .rqtype = DEVTOMEM,
103 [14] = DMACH_SPI0_TX, 126 }, {
104 [15] = DMACH_SPI0_RX, 127 .peri_id = (u8)DMACH_UART2_TX,
105 [16] = DMACH_PCM1_TX, 128 .rqtype = MEMTODEV,
106 [17] = DMACH_PCM1_RX, 129 }, {
107 [18] = DMACH_PCM2_TX, 130 .peri_id = (u8)DMACH_UART3_RX,
108 [19] = DMACH_PCM2_RX, 131 .rqtype = DEVTOMEM,
109 [20] = DMACH_SPI1_TX, 132 }, {
110 [21] = DMACH_SPI1_RX, 133 .peri_id = (u8)DMACH_UART3_TX,
111 [22] = DMACH_USI_TX, 134 .rqtype = MEMTODEV,
112 [23] = DMACH_USI_RX, 135 }, {
113 [24] = DMACH_MAX, 136 .peri_id = (u8)DMACH_UART4_RX,
114 [25] = DMACH_I2S1_TX, 137 .rqtype = DEVTOMEM,
115 [26] = DMACH_I2S1_RX, 138 }, {
116 [27] = DMACH_I2S2_TX, 139 .peri_id = (u8)DMACH_UART4_TX,
117 [28] = DMACH_I2S2_RX, 140 .rqtype = MEMTODEV,
118 [29] = DMACH_PWM, 141 }, {
119 [30] = DMACH_UART5_RX, 142 .peri_id = (u8)DMACH_PCM0_TX,
120 [31] = DMACH_UART5_TX, 143 .rqtype = MEMTODEV,
144 }, {
145 .peri_id = (u8)DMACH_PCM0_RX,
146 .rqtype = DEVTOMEM,
147 }, {
148 .peri_id = (u8)DMACH_I2S0_TX,
149 .rqtype = MEMTODEV,
150 }, {
151 .peri_id = (u8)DMACH_I2S0_RX,
152 .rqtype = DEVTOMEM,
153 }, {
154 .peri_id = (u8)DMACH_SPI0_TX,
155 .rqtype = MEMTODEV,
156 }, {
157 .peri_id = (u8)DMACH_SPI0_RX,
158 .rqtype = DEVTOMEM,
159 }, {
160 .peri_id = (u8)DMACH_PCM1_TX,
161 .rqtype = MEMTODEV,
162 }, {
163 .peri_id = (u8)DMACH_PCM1_RX,
164 .rqtype = DEVTOMEM,
165 }, {
166 .peri_id = (u8)DMACH_PCM2_TX,
167 .rqtype = MEMTODEV,
168 }, {
169 .peri_id = (u8)DMACH_PCM2_RX,
170 .rqtype = DEVTOMEM,
171 }, {
172 .peri_id = (u8)DMACH_SPI1_TX,
173 .rqtype = MEMTODEV,
174 }, {
175 .peri_id = (u8)DMACH_SPI1_RX,
176 .rqtype = DEVTOMEM,
177 }, {
178 .peri_id = (u8)DMACH_USI_TX,
179 .rqtype = MEMTODEV,
180 }, {
181 .peri_id = (u8)DMACH_USI_RX,
182 .rqtype = DEVTOMEM,
183 }, {
184 .peri_id = (u8)DMACH_MAX,
185 }, {
186 .peri_id = (u8)DMACH_I2S1_TX,
187 .rqtype = MEMTODEV,
188 }, {
189 .peri_id = (u8)DMACH_I2S1_RX,
190 .rqtype = DEVTOMEM,
191 }, {
192 .peri_id = (u8)DMACH_I2S2_TX,
193 .rqtype = MEMTODEV,
194 }, {
195 .peri_id = (u8)DMACH_I2S2_RX,
196 .rqtype = DEVTOMEM,
197 }, {
198 .peri_id = (u8)DMACH_PWM,
199 }, {
200 .peri_id = (u8)DMACH_UART5_RX,
201 .rqtype = DEVTOMEM,
202 }, {
203 .peri_id = (u8)DMACH_UART5_TX,
204 .rqtype = MEMTODEV,
121 }, 205 },
122}; 206};
123 207
124static struct platform_device s5p64x0_device_pdma = { 208struct dma_pl330_platdata s5p6450_pdma_pdata = {
125 .name = "s3c-pl330", 209 .nr_valid_peri = ARRAY_SIZE(s5p6450_pdma_peri),
126 .id = -1, 210 .peri = s5p6450_pdma_peri,
127 .num_resources = ARRAY_SIZE(s5p64x0_pdma_resource), 211};
128 .resource = s5p64x0_pdma_resource, 212
129 .dev = { 213struct amba_device s5p64x0_device_pdma = {
214 .dev = {
215 .init_name = "dma-pl330",
130 .dma_mask = &dma_dmamask, 216 .dma_mask = &dma_dmamask,
131 .coherent_dma_mask = DMA_BIT_MASK(32), 217 .coherent_dma_mask = DMA_BIT_MASK(32),
132 }, 218 },
219 .res = {
220 .start = S5P64X0_PA_PDMA,
221 .end = S5P64X0_PA_PDMA + SZ_4K,
222 .flags = IORESOURCE_MEM,
223 },
224 .irq = {IRQ_DMA0, NO_IRQ},
225 .periphid = 0x00041330,
133}; 226};
134 227
135static int __init s5p64x0_dma_init(void) 228static int __init s5p64x0_dma_init(void)
@@ -139,7 +232,7 @@ static int __init s5p64x0_dma_init(void)
139 else 232 else
140 s5p64x0_device_pdma.dev.platform_data = &s5p6440_pdma_pdata; 233 s5p64x0_device_pdma.dev.platform_data = &s5p6440_pdma_pdata;
141 234
142 platform_device_register(&s5p64x0_device_pdma); 235 amba_device_register(&s5p64x0_device_pdma, &iomem_resource);
143 236
144 return 0; 237 return 0;
145} 238}
diff --git a/arch/arm/mach-s5p64x0/include/mach/dma.h b/arch/arm/mach-s5p64x0/include/mach/dma.h
index 81209eb1409b..5a622af461d7 100644
--- a/arch/arm/mach-s5p64x0/include/mach/dma.h
+++ b/arch/arm/mach-s5p64x0/include/mach/dma.h
@@ -20,7 +20,7 @@
20#ifndef __MACH_DMA_H 20#ifndef __MACH_DMA_H
21#define __MACH_DMA_H 21#define __MACH_DMA_H
22 22
23/* This platform uses the common S3C DMA API driver for PL330 */ 23/* This platform uses the common common DMA API driver for PL330 */
24#include <plat/s3c-dma-pl330.h> 24#include <plat/dma-pl330.h>
25 25
26#endif /* __MACH_DMA_H */ 26#endif /* __MACH_DMA_H */
diff --git a/arch/arm/mach-s5p64x0/include/mach/irqs.h b/arch/arm/mach-s5p64x0/include/mach/irqs.h
index 5837a36ece8d..53982db9d259 100644
--- a/arch/arm/mach-s5p64x0/include/mach/irqs.h
+++ b/arch/arm/mach-s5p64x0/include/mach/irqs.h
@@ -87,6 +87,10 @@
87 87
88#define IRQ_I2S0 IRQ_I2SV40 88#define IRQ_I2S0 IRQ_I2SV40
89 89
90#define IRQ_LCD_FIFO IRQ_DISPCON0
91#define IRQ_LCD_VSYNC IRQ_DISPCON1
92#define IRQ_LCD_SYSTEM IRQ_DISPCON2
93
90/* S5P6450 EINT feature will be added */ 94/* S5P6450 EINT feature will be added */
91 95
92/* 96/*
diff --git a/arch/arm/mach-s5p64x0/include/mach/map.h b/arch/arm/mach-s5p64x0/include/mach/map.h
index 95c91257c7ca..c5ef50c26291 100644
--- a/arch/arm/mach-s5p64x0/include/mach/map.h
+++ b/arch/arm/mach-s5p64x0/include/mach/map.h
@@ -47,6 +47,8 @@
47 47
48#define S5P64X0_PA_HSMMC(x) (0xED800000 + ((x) * 0x100000)) 48#define S5P64X0_PA_HSMMC(x) (0xED800000 + ((x) * 0x100000))
49 49
50#define S5P64X0_PA_FB 0xEE000000
51
50#define S5P64X0_PA_I2S 0xF2000000 52#define S5P64X0_PA_I2S 0xF2000000
51#define S5P6450_PA_I2S1 0xF2800000 53#define S5P6450_PA_I2S1 0xF2800000
52#define S5P6450_PA_I2S2 0xF2900000 54#define S5P6450_PA_I2S2 0xF2900000
@@ -64,6 +66,7 @@
64#define S3C_PA_IIC1 S5P6440_PA_IIC1 66#define S3C_PA_IIC1 S5P6440_PA_IIC1
65#define S3C_PA_RTC S5P64X0_PA_RTC 67#define S3C_PA_RTC S5P64X0_PA_RTC
66#define S3C_PA_WDT S5P64X0_PA_WDT 68#define S3C_PA_WDT S5P64X0_PA_WDT
69#define S3C_PA_FB S5P64X0_PA_FB
67 70
68#define S5P_PA_CHIPID S5P64X0_PA_CHIPID 71#define S5P_PA_CHIPID S5P64X0_PA_CHIPID
69#define S5P_PA_SROMC S5P64X0_PA_SROMC 72#define S5P_PA_SROMC S5P64X0_PA_SROMC
diff --git a/arch/arm/mach-s5p64x0/include/mach/regs-gpio.h b/arch/arm/mach-s5p64x0/include/mach/regs-gpio.h
index 6ce254729f3b..88269ec70a38 100644
--- a/arch/arm/mach-s5p64x0/include/mach/regs-gpio.h
+++ b/arch/arm/mach-s5p64x0/include/mach/regs-gpio.h
@@ -34,6 +34,10 @@
34#define S5P6450_GPQ_BASE (S5P_VA_GPIO + 0x0180) 34#define S5P6450_GPQ_BASE (S5P_VA_GPIO + 0x0180)
35#define S5P6450_GPS_BASE (S5P_VA_GPIO + 0x0300) 35#define S5P6450_GPS_BASE (S5P_VA_GPIO + 0x0300)
36 36
37#define S5P64X0_SPCON0 (S5P_VA_GPIO + 0x1A0)
38#define S5P64X0_SPCON0_LCD_SEL_MASK (0x3 << 0)
39#define S5P64X0_SPCON0_LCD_SEL_RGB (0x1 << 0)
40
37/* External interrupt control registers for group0 */ 41/* External interrupt control registers for group0 */
38 42
39#define EINT0CON0_OFFSET (0x900) 43#define EINT0CON0_OFFSET (0x900)
diff --git a/arch/arm/mach-s5p64x0/mach-smdk6440.c b/arch/arm/mach-s5p64x0/mach-smdk6440.c
index 340f30f4a3da..b0465d4e84e7 100644
--- a/arch/arm/mach-s5p64x0/mach-smdk6440.c
+++ b/arch/arm/mach-s5p64x0/mach-smdk6440.c
@@ -23,6 +23,9 @@
23#include <linux/clk.h> 23#include <linux/clk.h>
24#include <linux/gpio.h> 24#include <linux/gpio.h>
25#include <linux/pwm_backlight.h> 25#include <linux/pwm_backlight.h>
26#include <linux/fb.h>
27
28#include <video/platform_lcd.h>
26 29
27#include <asm/mach/arch.h> 30#include <asm/mach/arch.h>
28#include <asm/mach/map.h> 31#include <asm/mach/map.h>
@@ -47,6 +50,8 @@
47#include <plat/ts.h> 50#include <plat/ts.h>
48#include <plat/s5p-time.h> 51#include <plat/s5p-time.h>
49#include <plat/backlight.h> 52#include <plat/backlight.h>
53#include <plat/fb.h>
54#include <plat/regs-fb.h>
50 55
51#define SMDK6440_UCON_DEFAULT (S3C2410_UCON_TXILEVEL | \ 56#define SMDK6440_UCON_DEFAULT (S3C2410_UCON_TXILEVEL | \
52 S3C2410_UCON_RXILEVEL | \ 57 S3C2410_UCON_RXILEVEL | \
@@ -92,6 +97,59 @@ static struct s3c2410_uartcfg smdk6440_uartcfgs[] __initdata = {
92 }, 97 },
93}; 98};
94 99
100/* Frame Buffer */
101static struct s3c_fb_pd_win smdk6440_fb_win0 = {
102 .win_mode = {
103 .left_margin = 8,
104 .right_margin = 13,
105 .upper_margin = 7,
106 .lower_margin = 5,
107 .hsync_len = 3,
108 .vsync_len = 1,
109 .xres = 800,
110 .yres = 480,
111 },
112 .max_bpp = 32,
113 .default_bpp = 24,
114};
115
116static struct s3c_fb_platdata smdk6440_lcd_pdata __initdata = {
117 .win[0] = &smdk6440_fb_win0,
118 .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB,
119 .vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC,
120 .setup_gpio = s5p64x0_fb_gpio_setup_24bpp,
121};
122
123/* LCD power controller */
124static void smdk6440_lte480_reset_power(struct plat_lcd_data *pd,
125 unsigned int power)
126{
127 int err;
128
129 if (power) {
130 err = gpio_request(S5P6440_GPN(5), "GPN");
131 if (err) {
132 printk(KERN_ERR "failed to request GPN for lcd reset\n");
133 return;
134 }
135
136 gpio_direction_output(S5P6440_GPN(5), 1);
137 gpio_set_value(S5P6440_GPN(5), 0);
138 gpio_set_value(S5P6440_GPN(5), 1);
139 gpio_free(S5P6440_GPN(5));
140 }
141}
142
143static struct plat_lcd_data smdk6440_lcd_power_data = {
144 .set_power = smdk6440_lte480_reset_power,
145};
146
147static struct platform_device smdk6440_lcd_lte480wv = {
148 .name = "platform-lcd",
149 .dev.parent = &s3c_device_fb.dev,
150 .dev.platform_data = &smdk6440_lcd_power_data,
151};
152
95static struct platform_device *smdk6440_devices[] __initdata = { 153static struct platform_device *smdk6440_devices[] __initdata = {
96 &s3c_device_adc, 154 &s3c_device_adc,
97 &s3c_device_rtc, 155 &s3c_device_rtc,
@@ -101,6 +159,8 @@ static struct platform_device *smdk6440_devices[] __initdata = {
101 &s3c_device_wdt, 159 &s3c_device_wdt,
102 &samsung_asoc_dma, 160 &samsung_asoc_dma,
103 &s5p6440_device_iis, 161 &s5p6440_device_iis,
162 &s3c_device_fb,
163 &smdk6440_lcd_lte480wv,
104}; 164};
105 165
106static struct s3c2410_platform_i2c s5p6440_i2c0_data __initdata = { 166static struct s3c2410_platform_i2c s5p6440_i2c0_data __initdata = {
@@ -147,6 +207,17 @@ static void __init smdk6440_map_io(void)
147 s5p_set_timer_source(S5P_PWM3, S5P_PWM4); 207 s5p_set_timer_source(S5P_PWM3, S5P_PWM4);
148} 208}
149 209
210static void s5p6440_set_lcd_interface(void)
211{
212 unsigned int cfg;
213
214 /* select TFT LCD type (RGB I/F) */
215 cfg = __raw_readl(S5P64X0_SPCON0);
216 cfg &= ~S5P64X0_SPCON0_LCD_SEL_MASK;
217 cfg |= S5P64X0_SPCON0_LCD_SEL_RGB;
218 __raw_writel(cfg, S5P64X0_SPCON0);
219}
220
150static void __init smdk6440_machine_init(void) 221static void __init smdk6440_machine_init(void)
151{ 222{
152 s3c24xx_ts_set_platdata(NULL); 223 s3c24xx_ts_set_platdata(NULL);
@@ -160,6 +231,9 @@ static void __init smdk6440_machine_init(void)
160 231
161 samsung_bl_set(&smdk6440_bl_gpio_info, &smdk6440_bl_data); 232 samsung_bl_set(&smdk6440_bl_gpio_info, &smdk6440_bl_data);
162 233
234 s5p6440_set_lcd_interface();
235 s3c_fb_set_platdata(&smdk6440_lcd_pdata);
236
163 platform_add_devices(smdk6440_devices, ARRAY_SIZE(smdk6440_devices)); 237 platform_add_devices(smdk6440_devices, ARRAY_SIZE(smdk6440_devices));
164} 238}
165 239
diff --git a/arch/arm/mach-s5p64x0/mach-smdk6450.c b/arch/arm/mach-s5p64x0/mach-smdk6450.c
index ee0da14665b6..2a69caa70afd 100644
--- a/arch/arm/mach-s5p64x0/mach-smdk6450.c
+++ b/arch/arm/mach-s5p64x0/mach-smdk6450.c
@@ -23,6 +23,9 @@
23#include <linux/clk.h> 23#include <linux/clk.h>
24#include <linux/gpio.h> 24#include <linux/gpio.h>
25#include <linux/pwm_backlight.h> 25#include <linux/pwm_backlight.h>
26#include <linux/fb.h>
27
28#include <video/platform_lcd.h>
26 29
27#include <asm/mach/arch.h> 30#include <asm/mach/arch.h>
28#include <asm/mach/map.h> 31#include <asm/mach/map.h>
@@ -47,6 +50,8 @@
47#include <plat/ts.h> 50#include <plat/ts.h>
48#include <plat/s5p-time.h> 51#include <plat/s5p-time.h>
49#include <plat/backlight.h> 52#include <plat/backlight.h>
53#include <plat/fb.h>
54#include <plat/regs-fb.h>
50 55
51#define SMDK6450_UCON_DEFAULT (S3C2410_UCON_TXILEVEL | \ 56#define SMDK6450_UCON_DEFAULT (S3C2410_UCON_TXILEVEL | \
52 S3C2410_UCON_RXILEVEL | \ 57 S3C2410_UCON_RXILEVEL | \
@@ -110,6 +115,59 @@ static struct s3c2410_uartcfg smdk6450_uartcfgs[] __initdata = {
110#endif 115#endif
111}; 116};
112 117
118/* Frame Buffer */
119static struct s3c_fb_pd_win smdk6450_fb_win0 = {
120 .win_mode = {
121 .left_margin = 8,
122 .right_margin = 13,
123 .upper_margin = 7,
124 .lower_margin = 5,
125 .hsync_len = 3,
126 .vsync_len = 1,
127 .xres = 800,
128 .yres = 480,
129 },
130 .max_bpp = 32,
131 .default_bpp = 24,
132};
133
134static struct s3c_fb_platdata smdk6450_lcd_pdata __initdata = {
135 .win[0] = &smdk6450_fb_win0,
136 .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB,
137 .vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC,
138 .setup_gpio = s5p64x0_fb_gpio_setup_24bpp,
139};
140
141/* LCD power controller */
142static void smdk6450_lte480_reset_power(struct plat_lcd_data *pd,
143 unsigned int power)
144{
145 int err;
146
147 if (power) {
148 err = gpio_request(S5P6450_GPN(5), "GPN");
149 if (err) {
150 printk(KERN_ERR "failed to request GPN for lcd reset\n");
151 return;
152 }
153
154 gpio_direction_output(S5P6450_GPN(5), 1);
155 gpio_set_value(S5P6450_GPN(5), 0);
156 gpio_set_value(S5P6450_GPN(5), 1);
157 gpio_free(S5P6450_GPN(5));
158 }
159}
160
161static struct plat_lcd_data smdk6450_lcd_power_data = {
162 .set_power = smdk6450_lte480_reset_power,
163};
164
165static struct platform_device smdk6450_lcd_lte480wv = {
166 .name = "platform-lcd",
167 .dev.parent = &s3c_device_fb.dev,
168 .dev.platform_data = &smdk6450_lcd_power_data,
169};
170
113static struct platform_device *smdk6450_devices[] __initdata = { 171static struct platform_device *smdk6450_devices[] __initdata = {
114 &s3c_device_adc, 172 &s3c_device_adc,
115 &s3c_device_rtc, 173 &s3c_device_rtc,
@@ -119,6 +177,9 @@ static struct platform_device *smdk6450_devices[] __initdata = {
119 &s3c_device_wdt, 177 &s3c_device_wdt,
120 &samsung_asoc_dma, 178 &samsung_asoc_dma,
121 &s5p6450_device_iis0, 179 &s5p6450_device_iis0,
180 &s3c_device_fb,
181 &smdk6450_lcd_lte480wv,
182
122 /* s5p6450_device_spi0 will be added */ 183 /* s5p6450_device_spi0 will be added */
123}; 184};
124 185
@@ -166,6 +227,17 @@ static void __init smdk6450_map_io(void)
166 s5p_set_timer_source(S5P_PWM3, S5P_PWM4); 227 s5p_set_timer_source(S5P_PWM3, S5P_PWM4);
167} 228}
168 229
230static void s5p6450_set_lcd_interface(void)
231{
232 unsigned int cfg;
233
234 /* select TFT LCD type (RGB I/F) */
235 cfg = __raw_readl(S5P64X0_SPCON0);
236 cfg &= ~S5P64X0_SPCON0_LCD_SEL_MASK;
237 cfg |= S5P64X0_SPCON0_LCD_SEL_RGB;
238 __raw_writel(cfg, S5P64X0_SPCON0);
239}
240
169static void __init smdk6450_machine_init(void) 241static void __init smdk6450_machine_init(void)
170{ 242{
171 s3c24xx_ts_set_platdata(NULL); 243 s3c24xx_ts_set_platdata(NULL);
@@ -179,6 +251,9 @@ static void __init smdk6450_machine_init(void)
179 251
180 samsung_bl_set(&smdk6450_bl_gpio_info, &smdk6450_bl_data); 252 samsung_bl_set(&smdk6450_bl_gpio_info, &smdk6450_bl_data);
181 253
254 s5p6450_set_lcd_interface();
255 s3c_fb_set_platdata(&smdk6450_lcd_pdata);
256
182 platform_add_devices(smdk6450_devices, ARRAY_SIZE(smdk6450_devices)); 257 platform_add_devices(smdk6450_devices, ARRAY_SIZE(smdk6450_devices));
183} 258}
184 259
diff --git a/arch/arm/mach-s5p64x0/setup-fb-24bpp.c b/arch/arm/mach-s5p64x0/setup-fb-24bpp.c
new file mode 100644
index 000000000000..f346ee4af54d
--- /dev/null
+++ b/arch/arm/mach-s5p64x0/setup-fb-24bpp.c
@@ -0,0 +1,29 @@
1/* linux/arch/arm/mach-s5p64x0/setup-fb-24bpp.c
2 *
3 * Copyright (c) 2011 Samsung Electronics Co., Ltd.
4 * http://www.samsung.com/
5 *
6 * Base S5P64X0 GPIO setup information for LCD framebuffer
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11*/
12
13#include <linux/fb.h>
14#include <linux/gpio.h>
15
16#include <plat/cpu.h>
17#include <plat/fb.h>
18#include <plat/gpio-cfg.h>
19
20void s5p64x0_fb_gpio_setup_24bpp(void)
21{
22 if (soc_is_s5p6440()) {
23 s3c_gpio_cfgrange_nopull(S5P6440_GPI(0), 16, S3C_GPIO_SFN(2));
24 s3c_gpio_cfgrange_nopull(S5P6440_GPJ(0), 12, S3C_GPIO_SFN(2));
25 } else if (soc_is_s5p6450()) {
26 s3c_gpio_cfgrange_nopull(S5P6450_GPI(0), 16, S3C_GPIO_SFN(2));
27 s3c_gpio_cfgrange_nopull(S5P6450_GPJ(0), 12, S3C_GPIO_SFN(2));
28 }
29}
diff --git a/arch/arm/mach-s5pc100/Kconfig b/arch/arm/mach-s5pc100/Kconfig
index e8a33c4b054c..e538a4c67e9c 100644
--- a/arch/arm/mach-s5pc100/Kconfig
+++ b/arch/arm/mach-s5pc100/Kconfig
@@ -10,7 +10,7 @@ if ARCH_S5PC100
10config CPU_S5PC100 10config CPU_S5PC100
11 bool 11 bool
12 select S5P_EXT_INT 12 select S5P_EXT_INT
13 select S3C_PL330_DMA 13 select SAMSUNG_DMADEV
14 help 14 help
15 Enable S5PC100 CPU support 15 Enable S5PC100 CPU support
16 16
diff --git a/arch/arm/mach-s5pc100/clock.c b/arch/arm/mach-s5pc100/clock.c
index ff5cbb30de5b..8d47709da713 100644
--- a/arch/arm/mach-s5pc100/clock.c
+++ b/arch/arm/mach-s5pc100/clock.c
@@ -33,6 +33,11 @@ static struct clk s5p_clk_otgphy = {
33 .name = "otg_phy", 33 .name = "otg_phy",
34}; 34};
35 35
36static struct clk dummy_apb_pclk = {
37 .name = "apb_pclk",
38 .id = -1,
39};
40
36static struct clk *clk_src_mout_href_list[] = { 41static struct clk *clk_src_mout_href_list[] = {
37 [0] = &s5p_clk_27m, 42 [0] = &s5p_clk_27m,
38 [1] = &clk_fin_hpll, 43 [1] = &clk_fin_hpll,
@@ -454,14 +459,14 @@ static struct clk init_clocks_off[] = {
454 .enable = s5pc100_d1_0_ctrl, 459 .enable = s5pc100_d1_0_ctrl,
455 .ctrlbit = (1 << 2), 460 .ctrlbit = (1 << 2),
456 }, { 461 }, {
457 .name = "pdma", 462 .name = "dma",
458 .devname = "s3c-pl330.1", 463 .devname = "dma-pl330.1",
459 .parent = &clk_div_d1_bus.clk, 464 .parent = &clk_div_d1_bus.clk,
460 .enable = s5pc100_d1_0_ctrl, 465 .enable = s5pc100_d1_0_ctrl,
461 .ctrlbit = (1 << 1), 466 .ctrlbit = (1 << 1),
462 }, { 467 }, {
463 .name = "pdma", 468 .name = "dma",
464 .devname = "s3c-pl330.0", 469 .devname = "dma-pl330.0",
465 .parent = &clk_div_d1_bus.clk, 470 .parent = &clk_div_d1_bus.clk,
466 .enable = s5pc100_d1_0_ctrl, 471 .enable = s5pc100_d1_0_ctrl,
467 .ctrlbit = (1 << 0), 472 .ctrlbit = (1 << 0),
@@ -1276,5 +1281,7 @@ void __init s5pc100_register_clocks(void)
1276 s3c_register_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off)); 1281 s3c_register_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
1277 s3c_disable_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off)); 1282 s3c_disable_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
1278 1283
1284 s3c24xx_register_clock(&dummy_apb_pclk);
1285
1279 s3c_pwmclk_init(); 1286 s3c_pwmclk_init();
1280} 1287}
diff --git a/arch/arm/mach-s5pc100/dma.c b/arch/arm/mach-s5pc100/dma.c
index bf4cd0fb97c6..065a087f5a8b 100644
--- a/arch/arm/mach-s5pc100/dma.c
+++ b/arch/arm/mach-s5pc100/dma.c
@@ -1,4 +1,8 @@
1/* 1/* linux/arch/arm/mach-s5pc100/dma.c
2 *
3 * Copyright (c) 2011 Samsung Electronics Co., Ltd.
4 * http://www.samsung.com
5 *
2 * Copyright (C) 2010 Samsung Electronics Co. Ltd. 6 * Copyright (C) 2010 Samsung Electronics Co. Ltd.
3 * Jaswinder Singh <jassi.brar@samsung.com> 7 * Jaswinder Singh <jassi.brar@samsung.com>
4 * 8 *
@@ -17,150 +21,246 @@
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 21 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */ 22 */
19 23
20#include <linux/platform_device.h>
21#include <linux/dma-mapping.h> 24#include <linux/dma-mapping.h>
25#include <linux/amba/bus.h>
26#include <linux/amba/pl330.h>
22 27
28#include <asm/irq.h>
23#include <plat/devs.h> 29#include <plat/devs.h>
30#include <plat/irqs.h>
24 31
25#include <mach/map.h> 32#include <mach/map.h>
26#include <mach/irqs.h> 33#include <mach/irqs.h>
27 34#include <mach/dma.h>
28#include <plat/s3c-pl330-pdata.h>
29 35
30static u64 dma_dmamask = DMA_BIT_MASK(32); 36static u64 dma_dmamask = DMA_BIT_MASK(32);
31 37
32static struct resource s5pc100_pdma0_resource[] = { 38struct dma_pl330_peri pdma0_peri[30] = {
33 [0] = { 39 {
34 .start = S5PC100_PA_PDMA0, 40 .peri_id = (u8)DMACH_UART0_RX,
35 .end = S5PC100_PA_PDMA0 + SZ_4K, 41 .rqtype = DEVTOMEM,
36 .flags = IORESOURCE_MEM, 42 }, {
37 }, 43 .peri_id = (u8)DMACH_UART0_TX,
38 [1] = { 44 .rqtype = MEMTODEV,
39 .start = IRQ_PDMA0, 45 }, {
40 .end = IRQ_PDMA0, 46 .peri_id = (u8)DMACH_UART1_RX,
41 .flags = IORESOURCE_IRQ, 47 .rqtype = DEVTOMEM,
48 }, {
49 .peri_id = (u8)DMACH_UART1_TX,
50 .rqtype = MEMTODEV,
51 }, {
52 .peri_id = (u8)DMACH_UART2_RX,
53 .rqtype = DEVTOMEM,
54 }, {
55 .peri_id = (u8)DMACH_UART2_TX,
56 .rqtype = MEMTODEV,
57 }, {
58 .peri_id = (u8)DMACH_UART3_RX,
59 .rqtype = DEVTOMEM,
60 }, {
61 .peri_id = (u8)DMACH_UART3_TX,
62 .rqtype = MEMTODEV,
63 }, {
64 .peri_id = DMACH_IRDA,
65 }, {
66 .peri_id = (u8)DMACH_I2S0_RX,
67 .rqtype = DEVTOMEM,
68 }, {
69 .peri_id = (u8)DMACH_I2S0_TX,
70 .rqtype = MEMTODEV,
71 }, {
72 .peri_id = (u8)DMACH_I2S0S_TX,
73 .rqtype = MEMTODEV,
74 }, {
75 .peri_id = (u8)DMACH_I2S1_RX,
76 .rqtype = DEVTOMEM,
77 }, {
78 .peri_id = (u8)DMACH_I2S1_TX,
79 .rqtype = MEMTODEV,
80 }, {
81 .peri_id = (u8)DMACH_I2S2_RX,
82 .rqtype = DEVTOMEM,
83 }, {
84 .peri_id = (u8)DMACH_I2S2_TX,
85 .rqtype = MEMTODEV,
86 }, {
87 .peri_id = (u8)DMACH_SPI0_RX,
88 .rqtype = DEVTOMEM,
89 }, {
90 .peri_id = (u8)DMACH_SPI0_TX,
91 .rqtype = MEMTODEV,
92 }, {
93 .peri_id = (u8)DMACH_SPI1_RX,
94 .rqtype = DEVTOMEM,
95 }, {
96 .peri_id = (u8)DMACH_SPI1_TX,
97 .rqtype = MEMTODEV,
98 }, {
99 .peri_id = (u8)DMACH_SPI2_RX,
100 .rqtype = DEVTOMEM,
101 }, {
102 .peri_id = (u8)DMACH_SPI2_TX,
103 .rqtype = MEMTODEV,
104 }, {
105 .peri_id = (u8)DMACH_AC97_MICIN,
106 .rqtype = DEVTOMEM,
107 }, {
108 .peri_id = (u8)DMACH_AC97_PCMIN,
109 .rqtype = DEVTOMEM,
110 }, {
111 .peri_id = (u8)DMACH_AC97_PCMOUT,
112 .rqtype = MEMTODEV,
113 }, {
114 .peri_id = (u8)DMACH_EXTERNAL,
115 }, {
116 .peri_id = (u8)DMACH_PWM,
117 }, {
118 .peri_id = (u8)DMACH_SPDIF,
119 .rqtype = MEMTODEV,
120 }, {
121 .peri_id = (u8)DMACH_HSI_RX,
122 .rqtype = DEVTOMEM,
123 }, {
124 .peri_id = (u8)DMACH_HSI_TX,
125 .rqtype = MEMTODEV,
42 }, 126 },
43}; 127};
44 128
45static struct s3c_pl330_platdata s5pc100_pdma0_pdata = { 129struct dma_pl330_platdata s5pc100_pdma0_pdata = {
46 .peri = { 130 .nr_valid_peri = ARRAY_SIZE(pdma0_peri),
47 [0] = DMACH_UART0_RX, 131 .peri = pdma0_peri,
48 [1] = DMACH_UART0_TX,
49 [2] = DMACH_UART1_RX,
50 [3] = DMACH_UART1_TX,
51 [4] = DMACH_UART2_RX,
52 [5] = DMACH_UART2_TX,
53 [6] = DMACH_UART3_RX,
54 [7] = DMACH_UART3_TX,
55 [8] = DMACH_IRDA,
56 [9] = DMACH_I2S0_RX,
57 [10] = DMACH_I2S0_TX,
58 [11] = DMACH_I2S0S_TX,
59 [12] = DMACH_I2S1_RX,
60 [13] = DMACH_I2S1_TX,
61 [14] = DMACH_I2S2_RX,
62 [15] = DMACH_I2S2_TX,
63 [16] = DMACH_SPI0_RX,
64 [17] = DMACH_SPI0_TX,
65 [18] = DMACH_SPI1_RX,
66 [19] = DMACH_SPI1_TX,
67 [20] = DMACH_SPI2_RX,
68 [21] = DMACH_SPI2_TX,
69 [22] = DMACH_AC97_MICIN,
70 [23] = DMACH_AC97_PCMIN,
71 [24] = DMACH_AC97_PCMOUT,
72 [25] = DMACH_EXTERNAL,
73 [26] = DMACH_PWM,
74 [27] = DMACH_SPDIF,
75 [28] = DMACH_HSI_RX,
76 [29] = DMACH_HSI_TX,
77 [30] = DMACH_MAX,
78 [31] = DMACH_MAX,
79 },
80}; 132};
81 133
82static struct platform_device s5pc100_device_pdma0 = { 134struct amba_device s5pc100_device_pdma0 = {
83 .name = "s3c-pl330", 135 .dev = {
84 .id = 0, 136 .init_name = "dma-pl330.0",
85 .num_resources = ARRAY_SIZE(s5pc100_pdma0_resource),
86 .resource = s5pc100_pdma0_resource,
87 .dev = {
88 .dma_mask = &dma_dmamask, 137 .dma_mask = &dma_dmamask,
89 .coherent_dma_mask = DMA_BIT_MASK(32), 138 .coherent_dma_mask = DMA_BIT_MASK(32),
90 .platform_data = &s5pc100_pdma0_pdata, 139 .platform_data = &s5pc100_pdma0_pdata,
91 }, 140 },
92}; 141 .res = {
93 142 .start = S5PC100_PA_PDMA0,
94static struct resource s5pc100_pdma1_resource[] = { 143 .end = S5PC100_PA_PDMA0 + SZ_4K,
95 [0] = {
96 .start = S5PC100_PA_PDMA1,
97 .end = S5PC100_PA_PDMA1 + SZ_4K,
98 .flags = IORESOURCE_MEM, 144 .flags = IORESOURCE_MEM,
99 }, 145 },
100 [1] = { 146 .irq = {IRQ_PDMA0, NO_IRQ},
101 .start = IRQ_PDMA1, 147 .periphid = 0x00041330,
102 .end = IRQ_PDMA1,
103 .flags = IORESOURCE_IRQ,
104 },
105}; 148};
106 149
107static struct s3c_pl330_platdata s5pc100_pdma1_pdata = { 150struct dma_pl330_peri pdma1_peri[30] = {
108 .peri = { 151 {
109 [0] = DMACH_UART0_RX, 152 .peri_id = (u8)DMACH_UART0_RX,
110 [1] = DMACH_UART0_TX, 153 .rqtype = DEVTOMEM,
111 [2] = DMACH_UART1_RX, 154 }, {
112 [3] = DMACH_UART1_TX, 155 .peri_id = (u8)DMACH_UART0_TX,
113 [4] = DMACH_UART2_RX, 156 .rqtype = MEMTODEV,
114 [5] = DMACH_UART2_TX, 157 }, {
115 [6] = DMACH_UART3_RX, 158 .peri_id = (u8)DMACH_UART1_RX,
116 [7] = DMACH_UART3_TX, 159 .rqtype = DEVTOMEM,
117 [8] = DMACH_IRDA, 160 }, {
118 [9] = DMACH_I2S0_RX, 161 .peri_id = (u8)DMACH_UART1_TX,
119 [10] = DMACH_I2S0_TX, 162 .rqtype = MEMTODEV,
120 [11] = DMACH_I2S0S_TX, 163 }, {
121 [12] = DMACH_I2S1_RX, 164 .peri_id = (u8)DMACH_UART2_RX,
122 [13] = DMACH_I2S1_TX, 165 .rqtype = DEVTOMEM,
123 [14] = DMACH_I2S2_RX, 166 }, {
124 [15] = DMACH_I2S2_TX, 167 .peri_id = (u8)DMACH_UART2_TX,
125 [16] = DMACH_SPI0_RX, 168 .rqtype = MEMTODEV,
126 [17] = DMACH_SPI0_TX, 169 }, {
127 [18] = DMACH_SPI1_RX, 170 .peri_id = (u8)DMACH_UART3_RX,
128 [19] = DMACH_SPI1_TX, 171 .rqtype = DEVTOMEM,
129 [20] = DMACH_SPI2_RX, 172 }, {
130 [21] = DMACH_SPI2_TX, 173 .peri_id = (u8)DMACH_UART3_TX,
131 [22] = DMACH_PCM0_RX, 174 .rqtype = MEMTODEV,
132 [23] = DMACH_PCM0_TX, 175 }, {
133 [24] = DMACH_PCM1_RX, 176 .peri_id = DMACH_IRDA,
134 [25] = DMACH_PCM1_TX, 177 }, {
135 [26] = DMACH_MSM_REQ0, 178 .peri_id = (u8)DMACH_I2S0_RX,
136 [27] = DMACH_MSM_REQ1, 179 .rqtype = DEVTOMEM,
137 [28] = DMACH_MSM_REQ2, 180 }, {
138 [29] = DMACH_MSM_REQ3, 181 .peri_id = (u8)DMACH_I2S0_TX,
139 [30] = DMACH_MAX, 182 .rqtype = MEMTODEV,
140 [31] = DMACH_MAX, 183 }, {
184 .peri_id = (u8)DMACH_I2S0S_TX,
185 .rqtype = MEMTODEV,
186 }, {
187 .peri_id = (u8)DMACH_I2S1_RX,
188 .rqtype = DEVTOMEM,
189 }, {
190 .peri_id = (u8)DMACH_I2S1_TX,
191 .rqtype = MEMTODEV,
192 }, {
193 .peri_id = (u8)DMACH_I2S2_RX,
194 .rqtype = DEVTOMEM,
195 }, {
196 .peri_id = (u8)DMACH_I2S2_TX,
197 .rqtype = MEMTODEV,
198 }, {
199 .peri_id = (u8)DMACH_SPI0_RX,
200 .rqtype = DEVTOMEM,
201 }, {
202 .peri_id = (u8)DMACH_SPI0_TX,
203 .rqtype = MEMTODEV,
204 }, {
205 .peri_id = (u8)DMACH_SPI1_RX,
206 .rqtype = DEVTOMEM,
207 }, {
208 .peri_id = (u8)DMACH_SPI1_TX,
209 .rqtype = MEMTODEV,
210 }, {
211 .peri_id = (u8)DMACH_SPI2_RX,
212 .rqtype = DEVTOMEM,
213 }, {
214 .peri_id = (u8)DMACH_SPI2_TX,
215 .rqtype = MEMTODEV,
216 }, {
217 .peri_id = (u8)DMACH_PCM0_RX,
218 .rqtype = DEVTOMEM,
219 }, {
220 .peri_id = (u8)DMACH_PCM1_TX,
221 .rqtype = MEMTODEV,
222 }, {
223 .peri_id = (u8)DMACH_PCM1_RX,
224 .rqtype = DEVTOMEM,
225 }, {
226 .peri_id = (u8)DMACH_PCM1_TX,
227 .rqtype = MEMTODEV,
228 }, {
229 .peri_id = (u8)DMACH_MSM_REQ0,
230 }, {
231 .peri_id = (u8)DMACH_MSM_REQ1,
232 }, {
233 .peri_id = (u8)DMACH_MSM_REQ2,
234 }, {
235 .peri_id = (u8)DMACH_MSM_REQ3,
141 }, 236 },
142}; 237};
143 238
144static struct platform_device s5pc100_device_pdma1 = { 239struct dma_pl330_platdata s5pc100_pdma1_pdata = {
145 .name = "s3c-pl330", 240 .nr_valid_peri = ARRAY_SIZE(pdma1_peri),
146 .id = 1, 241 .peri = pdma1_peri,
147 .num_resources = ARRAY_SIZE(s5pc100_pdma1_resource), 242};
148 .resource = s5pc100_pdma1_resource, 243
149 .dev = { 244struct amba_device s5pc100_device_pdma1 = {
245 .dev = {
246 .init_name = "dma-pl330.1",
150 .dma_mask = &dma_dmamask, 247 .dma_mask = &dma_dmamask,
151 .coherent_dma_mask = DMA_BIT_MASK(32), 248 .coherent_dma_mask = DMA_BIT_MASK(32),
152 .platform_data = &s5pc100_pdma1_pdata, 249 .platform_data = &s5pc100_pdma1_pdata,
153 }, 250 },
154}; 251 .res = {
155 252 .start = S5PC100_PA_PDMA1,
156static struct platform_device *s5pc100_dmacs[] __initdata = { 253 .end = S5PC100_PA_PDMA1 + SZ_4K,
157 &s5pc100_device_pdma0, 254 .flags = IORESOURCE_MEM,
158 &s5pc100_device_pdma1, 255 },
256 .irq = {IRQ_PDMA1, NO_IRQ},
257 .periphid = 0x00041330,
159}; 258};
160 259
161static int __init s5pc100_dma_init(void) 260static int __init s5pc100_dma_init(void)
162{ 261{
163 platform_add_devices(s5pc100_dmacs, ARRAY_SIZE(s5pc100_dmacs)); 262 amba_device_register(&s5pc100_device_pdma0, &iomem_resource);
263 amba_device_register(&s5pc100_device_pdma1, &iomem_resource);
164 264
165 return 0; 265 return 0;
166} 266}
diff --git a/arch/arm/mach-s5pc100/include/mach/dma.h b/arch/arm/mach-s5pc100/include/mach/dma.h
index 81209eb1409b..201842a3769e 100644
--- a/arch/arm/mach-s5pc100/include/mach/dma.h
+++ b/arch/arm/mach-s5pc100/include/mach/dma.h
@@ -20,7 +20,7 @@
20#ifndef __MACH_DMA_H 20#ifndef __MACH_DMA_H
21#define __MACH_DMA_H 21#define __MACH_DMA_H
22 22
23/* This platform uses the common S3C DMA API driver for PL330 */ 23/* This platform uses the common DMA API driver for PL330 */
24#include <plat/s3c-dma-pl330.h> 24#include <plat/dma-pl330.h>
25 25
26#endif /* __MACH_DMA_H */ 26#endif /* __MACH_DMA_H */
diff --git a/arch/arm/mach-s5pv210/Kconfig b/arch/arm/mach-s5pv210/Kconfig
index aaeb44a73716..f22c683272d3 100644
--- a/arch/arm/mach-s5pv210/Kconfig
+++ b/arch/arm/mach-s5pv210/Kconfig
@@ -11,7 +11,7 @@ if ARCH_S5PV210
11 11
12config CPU_S5PV210 12config CPU_S5PV210
13 bool 13 bool
14 select S3C_PL330_DMA 14 select SAMSUNG_DMADEV
15 select S5P_EXT_INT 15 select S5P_EXT_INT
16 select S5P_HRT 16 select S5P_HRT
17 help 17 help
@@ -93,11 +93,13 @@ config MACH_GONI
93 select S3C_DEV_USB_HSOTG 93 select S3C_DEV_USB_HSOTG
94 select S5P_DEV_ONENAND 94 select S5P_DEV_ONENAND
95 select SAMSUNG_DEV_KEYPAD 95 select SAMSUNG_DEV_KEYPAD
96 select S5P_DEV_TV
96 select S5PV210_SETUP_FB_24BPP 97 select S5PV210_SETUP_FB_24BPP
97 select S5PV210_SETUP_I2C1 98 select S5PV210_SETUP_I2C1
98 select S5PV210_SETUP_I2C2 99 select S5PV210_SETUP_I2C2
99 select S5PV210_SETUP_KEYPAD 100 select S5PV210_SETUP_KEYPAD
100 select S5PV210_SETUP_SDHCI 101 select S5PV210_SETUP_SDHCI
102 select S5PV210_SETUP_FIMC
101 help 103 help
102 Machine support for Samsung GONI board 104 Machine support for Samsung GONI board
103 S5PC110(MCP) is one of package option of S5PV210 105 S5PC110(MCP) is one of package option of S5PV210
diff --git a/arch/arm/mach-s5pv210/clock.c b/arch/arm/mach-s5pv210/clock.c
index f5f8fa89679c..4c5ac7a69e9e 100644
--- a/arch/arm/mach-s5pv210/clock.c
+++ b/arch/arm/mach-s5pv210/clock.c
@@ -174,6 +174,16 @@ static int s5pv210_clk_mask1_ctrl(struct clk *clk, int enable)
174 return s5p_gatectrl(S5P_CLK_SRC_MASK1, clk, enable); 174 return s5p_gatectrl(S5P_CLK_SRC_MASK1, clk, enable);
175} 175}
176 176
177static int exynos4_clk_hdmiphy_ctrl(struct clk *clk, int enable)
178{
179 return s5p_gatectrl(S5P_HDMI_PHY_CONTROL, clk, enable);
180}
181
182static int exynos4_clk_dac_ctrl(struct clk *clk, int enable)
183{
184 return s5p_gatectrl(S5P_DAC_PHY_CONTROL, clk, enable);
185}
186
177static struct clk clk_sclk_hdmi27m = { 187static struct clk clk_sclk_hdmi27m = {
178 .name = "sclk_hdmi27m", 188 .name = "sclk_hdmi27m",
179 .rate = 27000000, 189 .rate = 27000000,
@@ -203,6 +213,11 @@ static struct clk clk_pcmcdclk2 = {
203 .name = "pcmcdclk", 213 .name = "pcmcdclk",
204}; 214};
205 215
216static struct clk dummy_apb_pclk = {
217 .name = "apb_pclk",
218 .id = -1,
219};
220
206static struct clk *clkset_vpllsrc_list[] = { 221static struct clk *clkset_vpllsrc_list[] = {
207 [0] = &clk_fin_vpll, 222 [0] = &clk_fin_vpll,
208 [1] = &clk_sclk_hdmi27m, 223 [1] = &clk_sclk_hdmi27m,
@@ -289,14 +304,14 @@ static struct clk_ops clk_fout_apll_ops = {
289 304
290static struct clk init_clocks_off[] = { 305static struct clk init_clocks_off[] = {
291 { 306 {
292 .name = "pdma", 307 .name = "dma",
293 .devname = "s3c-pl330.0", 308 .devname = "dma-pl330.0",
294 .parent = &clk_hclk_psys.clk, 309 .parent = &clk_hclk_psys.clk,
295 .enable = s5pv210_clk_ip0_ctrl, 310 .enable = s5pv210_clk_ip0_ctrl,
296 .ctrlbit = (1 << 3), 311 .ctrlbit = (1 << 3),
297 }, { 312 }, {
298 .name = "pdma", 313 .name = "dma",
299 .devname = "s3c-pl330.1", 314 .devname = "dma-pl330.1",
300 .parent = &clk_hclk_psys.clk, 315 .parent = &clk_hclk_psys.clk,
301 .enable = s5pv210_clk_ip0_ctrl, 316 .enable = s5pv210_clk_ip0_ctrl,
302 .ctrlbit = (1 << 4), 317 .ctrlbit = (1 << 4),
@@ -330,6 +345,40 @@ static struct clk init_clocks_off[] = {
330 .enable = s5pv210_clk_ip0_ctrl, 345 .enable = s5pv210_clk_ip0_ctrl,
331 .ctrlbit = (1 << 16), 346 .ctrlbit = (1 << 16),
332 }, { 347 }, {
348 .name = "dac",
349 .devname = "s5p-sdo",
350 .parent = &clk_hclk_dsys.clk,
351 .enable = s5pv210_clk_ip1_ctrl,
352 .ctrlbit = (1 << 10),
353 }, {
354 .name = "mixer",
355 .devname = "s5p-mixer",
356 .parent = &clk_hclk_dsys.clk,
357 .enable = s5pv210_clk_ip1_ctrl,
358 .ctrlbit = (1 << 9),
359 }, {
360 .name = "vp",
361 .devname = "s5p-mixer",
362 .parent = &clk_hclk_dsys.clk,
363 .enable = s5pv210_clk_ip1_ctrl,
364 .ctrlbit = (1 << 8),
365 }, {
366 .name = "hdmi",
367 .devname = "s5pv210-hdmi",
368 .parent = &clk_hclk_dsys.clk,
369 .enable = s5pv210_clk_ip1_ctrl,
370 .ctrlbit = (1 << 11),
371 }, {
372 .name = "hdmiphy",
373 .devname = "s5pv210-hdmi",
374 .enable = exynos4_clk_hdmiphy_ctrl,
375 .ctrlbit = (1 << 0),
376 }, {
377 .name = "dacphy",
378 .devname = "s5p-sdo",
379 .enable = exynos4_clk_dac_ctrl,
380 .ctrlbit = (1 << 0),
381 }, {
333 .name = "otg", 382 .name = "otg",
334 .parent = &clk_hclk_psys.clk, 383 .parent = &clk_hclk_psys.clk,
335 .enable = s5pv210_clk_ip1_ctrl, 384 .enable = s5pv210_clk_ip1_ctrl,
@@ -407,6 +456,12 @@ static struct clk init_clocks_off[] = {
407 .enable = s5pv210_clk_ip3_ctrl, 456 .enable = s5pv210_clk_ip3_ctrl,
408 .ctrlbit = (1<<9), 457 .ctrlbit = (1<<9),
409 }, { 458 }, {
459 .name = "i2c",
460 .devname = "s3c2440-hdmiphy-i2c",
461 .parent = &clk_pclk_psys.clk,
462 .enable = s5pv210_clk_ip3_ctrl,
463 .ctrlbit = (1 << 11),
464 }, {
410 .name = "spi", 465 .name = "spi",
411 .devname = "s3c64xx-spi.0", 466 .devname = "s3c64xx-spi.0",
412 .parent = &clk_pclk_psys.clk, 467 .parent = &clk_pclk_psys.clk,
@@ -594,6 +649,23 @@ static struct clksrc_sources clkset_sclk_mixer = {
594 .nr_sources = ARRAY_SIZE(clkset_sclk_mixer_list), 649 .nr_sources = ARRAY_SIZE(clkset_sclk_mixer_list),
595}; 650};
596 651
652static struct clksrc_clk clk_sclk_mixer = {
653 .clk = {
654 .name = "sclk_mixer",
655 .enable = s5pv210_clk_mask0_ctrl,
656 .ctrlbit = (1 << 1),
657 },
658 .sources = &clkset_sclk_mixer,
659 .reg_src = { .reg = S5P_CLK_SRC1, .shift = 4, .size = 1 },
660};
661
662static struct clksrc_clk *sclk_tv[] = {
663 &clk_sclk_dac,
664 &clk_sclk_pixel,
665 &clk_sclk_hdmi,
666 &clk_sclk_mixer,
667};
668
597static struct clk *clkset_sclk_audio0_list[] = { 669static struct clk *clkset_sclk_audio0_list[] = {
598 [0] = &clk_ext_xtal_mux, 670 [0] = &clk_ext_xtal_mux,
599 [1] = &clk_pcmcdclk0, 671 [1] = &clk_pcmcdclk0,
@@ -777,14 +849,6 @@ static struct clksrc_clk clksrcs[] = {
777 .reg_div = { .reg = S5P_CLK_DIV4, .shift = 28, .size = 4 }, 849 .reg_div = { .reg = S5P_CLK_DIV4, .shift = 28, .size = 4 },
778 }, { 850 }, {
779 .clk = { 851 .clk = {
780 .name = "sclk_mixer",
781 .enable = s5pv210_clk_mask0_ctrl,
782 .ctrlbit = (1 << 1),
783 },
784 .sources = &clkset_sclk_mixer,
785 .reg_src = { .reg = S5P_CLK_SRC1, .shift = 4, .size = 1 },
786 }, {
787 .clk = {
788 .name = "sclk_fimc", 852 .name = "sclk_fimc",
789 .devname = "s5pv210-fimc.0", 853 .devname = "s5pv210-fimc.0",
790 .enable = s5pv210_clk_mask1_ctrl, 854 .enable = s5pv210_clk_mask1_ctrl,
@@ -973,9 +1037,6 @@ static struct clksrc_clk *sysclks[] = {
973 &clk_pclk_psys, 1037 &clk_pclk_psys,
974 &clk_vpllsrc, 1038 &clk_vpllsrc,
975 &clk_sclk_vpll, 1039 &clk_sclk_vpll,
976 &clk_sclk_dac,
977 &clk_sclk_pixel,
978 &clk_sclk_hdmi,
979 &clk_mout_dmc0, 1040 &clk_mout_dmc0,
980 &clk_sclk_dmc0, 1041 &clk_sclk_dmc0,
981 &clk_sclk_audio0, 1042 &clk_sclk_audio0,
@@ -1060,6 +1121,61 @@ static struct clk_ops s5pv210_epll_ops = {
1060 .get_rate = s5p_epll_get_rate, 1121 .get_rate = s5p_epll_get_rate,
1061}; 1122};
1062 1123
1124static u32 vpll_div[][5] = {
1125 { 54000000, 3, 53, 3, 0 },
1126 { 108000000, 3, 53, 2, 0 },
1127};
1128
1129static unsigned long s5pv210_vpll_get_rate(struct clk *clk)
1130{
1131 return clk->rate;
1132}
1133
1134static int s5pv210_vpll_set_rate(struct clk *clk, unsigned long rate)
1135{
1136 unsigned int vpll_con;
1137 unsigned int i;
1138
1139 /* Return if nothing changed */
1140 if (clk->rate == rate)
1141 return 0;
1142
1143 vpll_con = __raw_readl(S5P_VPLL_CON);
1144 vpll_con &= ~(0x1 << 27 | \
1145 PLL90XX_MDIV_MASK << PLL90XX_MDIV_SHIFT | \
1146 PLL90XX_PDIV_MASK << PLL90XX_PDIV_SHIFT | \
1147 PLL90XX_SDIV_MASK << PLL90XX_SDIV_SHIFT);
1148
1149 for (i = 0; i < ARRAY_SIZE(vpll_div); i++) {
1150 if (vpll_div[i][0] == rate) {
1151 vpll_con |= vpll_div[i][1] << PLL90XX_PDIV_SHIFT;
1152 vpll_con |= vpll_div[i][2] << PLL90XX_MDIV_SHIFT;
1153 vpll_con |= vpll_div[i][3] << PLL90XX_SDIV_SHIFT;
1154 vpll_con |= vpll_div[i][4] << 27;
1155 break;
1156 }
1157 }
1158
1159 if (i == ARRAY_SIZE(vpll_div)) {
1160 printk(KERN_ERR "%s: Invalid Clock VPLL Frequency\n",
1161 __func__);
1162 return -EINVAL;
1163 }
1164
1165 __raw_writel(vpll_con, S5P_VPLL_CON);
1166
1167 /* Wait for VPLL lock */
1168 while (!(__raw_readl(S5P_VPLL_CON) & (1 << PLL90XX_LOCKED_SHIFT)))
1169 continue;
1170
1171 clk->rate = rate;
1172 return 0;
1173}
1174static struct clk_ops s5pv210_vpll_ops = {
1175 .get_rate = s5pv210_vpll_get_rate,
1176 .set_rate = s5pv210_vpll_set_rate,
1177};
1178
1063void __init_or_cpufreq s5pv210_setup_clocks(void) 1179void __init_or_cpufreq s5pv210_setup_clocks(void)
1064{ 1180{
1065 struct clk *xtal_clk; 1181 struct clk *xtal_clk;
@@ -1108,6 +1224,7 @@ void __init_or_cpufreq s5pv210_setup_clocks(void)
1108 clk_fout_apll.ops = &clk_fout_apll_ops; 1224 clk_fout_apll.ops = &clk_fout_apll_ops;
1109 clk_fout_mpll.rate = mpll; 1225 clk_fout_mpll.rate = mpll;
1110 clk_fout_epll.rate = epll; 1226 clk_fout_epll.rate = epll;
1227 clk_fout_vpll.ops = &s5pv210_vpll_ops;
1111 clk_fout_vpll.rate = vpll; 1228 clk_fout_vpll.rate = vpll;
1112 1229
1113 printk(KERN_INFO "S5PV210: PLL settings, A=%ld, M=%ld, E=%ld V=%ld", 1230 printk(KERN_INFO "S5PV210: PLL settings, A=%ld, M=%ld, E=%ld V=%ld",
@@ -1153,11 +1270,15 @@ void __init s5pv210_register_clocks(void)
1153 for (ptr = 0; ptr < ARRAY_SIZE(sysclks); ptr++) 1270 for (ptr = 0; ptr < ARRAY_SIZE(sysclks); ptr++)
1154 s3c_register_clksrc(sysclks[ptr], 1); 1271 s3c_register_clksrc(sysclks[ptr], 1);
1155 1272
1273 for (ptr = 0; ptr < ARRAY_SIZE(sclk_tv); ptr++)
1274 s3c_register_clksrc(sclk_tv[ptr], 1);
1275
1156 s3c_register_clksrc(clksrcs, ARRAY_SIZE(clksrcs)); 1276 s3c_register_clksrc(clksrcs, ARRAY_SIZE(clksrcs));
1157 s3c_register_clocks(init_clocks, ARRAY_SIZE(init_clocks)); 1277 s3c_register_clocks(init_clocks, ARRAY_SIZE(init_clocks));
1158 1278
1159 s3c_register_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off)); 1279 s3c_register_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
1160 s3c_disable_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off)); 1280 s3c_disable_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
1161 1281
1282 s3c24xx_register_clock(&dummy_apb_pclk);
1162 s3c_pwmclk_init(); 1283 s3c_pwmclk_init();
1163} 1284}
diff --git a/arch/arm/mach-s5pv210/cpu.c b/arch/arm/mach-s5pv210/cpu.c
index 79907ec78d43..6b8cdccbe931 100644
--- a/arch/arm/mach-s5pv210/cpu.c
+++ b/arch/arm/mach-s5pv210/cpu.c
@@ -41,6 +41,7 @@
41#include <plat/keypad-core.h> 41#include <plat/keypad-core.h>
42#include <plat/sdhci.h> 42#include <plat/sdhci.h>
43#include <plat/reset.h> 43#include <plat/reset.h>
44#include <plat/tv-core.h>
44 45
45/* Initial IO mappings */ 46/* Initial IO mappings */
46 47
@@ -143,6 +144,9 @@ void __init s5pv210_map_io(void)
143 144
144 /* Use s5pv210-keypad instead of samsung-keypad */ 145 /* Use s5pv210-keypad instead of samsung-keypad */
145 samsung_keypad_setname("s5pv210-keypad"); 146 samsung_keypad_setname("s5pv210-keypad");
147
148 /* setup TV devices */
149 s5p_hdmi_setname("s5pv210-hdmi");
146} 150}
147 151
148void __init s5pv210_init_clocks(int xtal) 152void __init s5pv210_init_clocks(int xtal)
diff --git a/arch/arm/mach-s5pv210/dma.c b/arch/arm/mach-s5pv210/dma.c
index 497d3439a142..86b749c18b77 100644
--- a/arch/arm/mach-s5pv210/dma.c
+++ b/arch/arm/mach-s5pv210/dma.c
@@ -1,4 +1,8 @@
1/* 1/* linux/arch/arm/mach-s5pv210/dma.c
2 *
3 * Copyright (c) 2011 Samsung Electronics Co., Ltd.
4 * http://www.samsung.com
5 *
2 * Copyright (C) 2010 Samsung Electronics Co. Ltd. 6 * Copyright (C) 2010 Samsung Electronics Co. Ltd.
3 * Jaswinder Singh <jassi.brar@samsung.com> 7 * Jaswinder Singh <jassi.brar@samsung.com>
4 * 8 *
@@ -17,151 +21,240 @@
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 21 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */ 22 */
19 23
20#include <linux/platform_device.h>
21#include <linux/dma-mapping.h> 24#include <linux/dma-mapping.h>
25#include <linux/amba/bus.h>
26#include <linux/amba/pl330.h>
22 27
28#include <asm/irq.h>
23#include <plat/devs.h> 29#include <plat/devs.h>
24#include <plat/irqs.h> 30#include <plat/irqs.h>
25 31
26#include <mach/map.h> 32#include <mach/map.h>
27#include <mach/irqs.h> 33#include <mach/irqs.h>
28 34#include <mach/dma.h>
29#include <plat/s3c-pl330-pdata.h>
30 35
31static u64 dma_dmamask = DMA_BIT_MASK(32); 36static u64 dma_dmamask = DMA_BIT_MASK(32);
32 37
33static struct resource s5pv210_pdma0_resource[] = { 38struct dma_pl330_peri pdma0_peri[28] = {
34 [0] = { 39 {
35 .start = S5PV210_PA_PDMA0, 40 .peri_id = (u8)DMACH_UART0_RX,
36 .end = S5PV210_PA_PDMA0 + SZ_4K, 41 .rqtype = DEVTOMEM,
37 .flags = IORESOURCE_MEM, 42 }, {
38 }, 43 .peri_id = (u8)DMACH_UART0_TX,
39 [1] = { 44 .rqtype = MEMTODEV,
40 .start = IRQ_PDMA0, 45 }, {
41 .end = IRQ_PDMA0, 46 .peri_id = (u8)DMACH_UART1_RX,
42 .flags = IORESOURCE_IRQ, 47 .rqtype = DEVTOMEM,
48 }, {
49 .peri_id = (u8)DMACH_UART1_TX,
50 .rqtype = MEMTODEV,
51 }, {
52 .peri_id = (u8)DMACH_UART2_RX,
53 .rqtype = DEVTOMEM,
54 }, {
55 .peri_id = (u8)DMACH_UART2_TX,
56 .rqtype = MEMTODEV,
57 }, {
58 .peri_id = (u8)DMACH_UART3_RX,
59 .rqtype = DEVTOMEM,
60 }, {
61 .peri_id = (u8)DMACH_UART3_TX,
62 .rqtype = MEMTODEV,
63 }, {
64 .peri_id = DMACH_MAX,
65 }, {
66 .peri_id = (u8)DMACH_I2S0_RX,
67 .rqtype = DEVTOMEM,
68 }, {
69 .peri_id = (u8)DMACH_I2S0_TX,
70 .rqtype = MEMTODEV,
71 }, {
72 .peri_id = (u8)DMACH_I2S0S_TX,
73 .rqtype = MEMTODEV,
74 }, {
75 .peri_id = (u8)DMACH_I2S1_RX,
76 .rqtype = DEVTOMEM,
77 }, {
78 .peri_id = (u8)DMACH_I2S1_TX,
79 .rqtype = MEMTODEV,
80 }, {
81 .peri_id = (u8)DMACH_MAX,
82 }, {
83 .peri_id = (u8)DMACH_MAX,
84 }, {
85 .peri_id = (u8)DMACH_SPI0_RX,
86 .rqtype = DEVTOMEM,
87 }, {
88 .peri_id = (u8)DMACH_SPI0_TX,
89 .rqtype = MEMTODEV,
90 }, {
91 .peri_id = (u8)DMACH_SPI1_RX,
92 .rqtype = DEVTOMEM,
93 }, {
94 .peri_id = (u8)DMACH_SPI1_TX,
95 .rqtype = MEMTODEV,
96 }, {
97 .peri_id = (u8)DMACH_MAX,
98 }, {
99 .peri_id = (u8)DMACH_MAX,
100 }, {
101 .peri_id = (u8)DMACH_AC97_MICIN,
102 .rqtype = DEVTOMEM,
103 }, {
104 .peri_id = (u8)DMACH_AC97_PCMIN,
105 .rqtype = DEVTOMEM,
106 }, {
107 .peri_id = (u8)DMACH_AC97_PCMOUT,
108 .rqtype = MEMTODEV,
109 }, {
110 .peri_id = (u8)DMACH_MAX,
111 }, {
112 .peri_id = (u8)DMACH_PWM,
113 }, {
114 .peri_id = (u8)DMACH_SPDIF,
115 .rqtype = MEMTODEV,
43 }, 116 },
44}; 117};
45 118
46static struct s3c_pl330_platdata s5pv210_pdma0_pdata = { 119struct dma_pl330_platdata s5pv210_pdma0_pdata = {
47 .peri = { 120 .nr_valid_peri = ARRAY_SIZE(pdma0_peri),
48 [0] = DMACH_UART0_RX, 121 .peri = pdma0_peri,
49 [1] = DMACH_UART0_TX,
50 [2] = DMACH_UART1_RX,
51 [3] = DMACH_UART1_TX,
52 [4] = DMACH_UART2_RX,
53 [5] = DMACH_UART2_TX,
54 [6] = DMACH_UART3_RX,
55 [7] = DMACH_UART3_TX,
56 [8] = DMACH_MAX,
57 [9] = DMACH_I2S0_RX,
58 [10] = DMACH_I2S0_TX,
59 [11] = DMACH_I2S0S_TX,
60 [12] = DMACH_I2S1_RX,
61 [13] = DMACH_I2S1_TX,
62 [14] = DMACH_MAX,
63 [15] = DMACH_MAX,
64 [16] = DMACH_SPI0_RX,
65 [17] = DMACH_SPI0_TX,
66 [18] = DMACH_SPI1_RX,
67 [19] = DMACH_SPI1_TX,
68 [20] = DMACH_MAX,
69 [21] = DMACH_MAX,
70 [22] = DMACH_AC97_MICIN,
71 [23] = DMACH_AC97_PCMIN,
72 [24] = DMACH_AC97_PCMOUT,
73 [25] = DMACH_MAX,
74 [26] = DMACH_PWM,
75 [27] = DMACH_SPDIF,
76 [28] = DMACH_MAX,
77 [29] = DMACH_MAX,
78 [30] = DMACH_MAX,
79 [31] = DMACH_MAX,
80 },
81}; 122};
82 123
83static struct platform_device s5pv210_device_pdma0 = { 124struct amba_device s5pv210_device_pdma0 = {
84 .name = "s3c-pl330", 125 .dev = {
85 .id = 0, 126 .init_name = "dma-pl330.0",
86 .num_resources = ARRAY_SIZE(s5pv210_pdma0_resource),
87 .resource = s5pv210_pdma0_resource,
88 .dev = {
89 .dma_mask = &dma_dmamask, 127 .dma_mask = &dma_dmamask,
90 .coherent_dma_mask = DMA_BIT_MASK(32), 128 .coherent_dma_mask = DMA_BIT_MASK(32),
91 .platform_data = &s5pv210_pdma0_pdata, 129 .platform_data = &s5pv210_pdma0_pdata,
92 }, 130 },
93}; 131 .res = {
94 132 .start = S5PV210_PA_PDMA0,
95static struct resource s5pv210_pdma1_resource[] = { 133 .end = S5PV210_PA_PDMA0 + SZ_4K,
96 [0] = {
97 .start = S5PV210_PA_PDMA1,
98 .end = S5PV210_PA_PDMA1 + SZ_4K,
99 .flags = IORESOURCE_MEM, 134 .flags = IORESOURCE_MEM,
100 }, 135 },
101 [1] = { 136 .irq = {IRQ_PDMA0, NO_IRQ},
102 .start = IRQ_PDMA1, 137 .periphid = 0x00041330,
103 .end = IRQ_PDMA1,
104 .flags = IORESOURCE_IRQ,
105 },
106}; 138};
107 139
108static struct s3c_pl330_platdata s5pv210_pdma1_pdata = { 140struct dma_pl330_peri pdma1_peri[32] = {
109 .peri = { 141 {
110 [0] = DMACH_UART0_RX, 142 .peri_id = (u8)DMACH_UART0_RX,
111 [1] = DMACH_UART0_TX, 143 .rqtype = DEVTOMEM,
112 [2] = DMACH_UART1_RX, 144 }, {
113 [3] = DMACH_UART1_TX, 145 .peri_id = (u8)DMACH_UART0_TX,
114 [4] = DMACH_UART2_RX, 146 .rqtype = MEMTODEV,
115 [5] = DMACH_UART2_TX, 147 }, {
116 [6] = DMACH_UART3_RX, 148 .peri_id = (u8)DMACH_UART1_RX,
117 [7] = DMACH_UART3_TX, 149 .rqtype = DEVTOMEM,
118 [8] = DMACH_MAX, 150 }, {
119 [9] = DMACH_I2S0_RX, 151 .peri_id = (u8)DMACH_UART1_TX,
120 [10] = DMACH_I2S0_TX, 152 .rqtype = MEMTODEV,
121 [11] = DMACH_I2S0S_TX, 153 }, {
122 [12] = DMACH_I2S1_RX, 154 .peri_id = (u8)DMACH_UART2_RX,
123 [13] = DMACH_I2S1_TX, 155 .rqtype = DEVTOMEM,
124 [14] = DMACH_I2S2_RX, 156 }, {
125 [15] = DMACH_I2S2_TX, 157 .peri_id = (u8)DMACH_UART2_TX,
126 [16] = DMACH_SPI0_RX, 158 .rqtype = MEMTODEV,
127 [17] = DMACH_SPI0_TX, 159 }, {
128 [18] = DMACH_SPI1_RX, 160 .peri_id = (u8)DMACH_UART3_RX,
129 [19] = DMACH_SPI1_TX, 161 .rqtype = DEVTOMEM,
130 [20] = DMACH_MAX, 162 }, {
131 [21] = DMACH_MAX, 163 .peri_id = (u8)DMACH_UART3_TX,
132 [22] = DMACH_PCM0_RX, 164 .rqtype = MEMTODEV,
133 [23] = DMACH_PCM0_TX, 165 }, {
134 [24] = DMACH_PCM1_RX, 166 .peri_id = DMACH_MAX,
135 [25] = DMACH_PCM1_TX, 167 }, {
136 [26] = DMACH_MSM_REQ0, 168 .peri_id = (u8)DMACH_I2S0_RX,
137 [27] = DMACH_MSM_REQ1, 169 .rqtype = DEVTOMEM,
138 [28] = DMACH_MSM_REQ2, 170 }, {
139 [29] = DMACH_MSM_REQ3, 171 .peri_id = (u8)DMACH_I2S0_TX,
140 [30] = DMACH_PCM2_RX, 172 .rqtype = MEMTODEV,
141 [31] = DMACH_PCM2_TX, 173 }, {
174 .peri_id = (u8)DMACH_I2S0S_TX,
175 .rqtype = MEMTODEV,
176 }, {
177 .peri_id = (u8)DMACH_I2S1_RX,
178 .rqtype = DEVTOMEM,
179 }, {
180 .peri_id = (u8)DMACH_I2S1_TX,
181 .rqtype = MEMTODEV,
182 }, {
183 .peri_id = (u8)DMACH_I2S2_RX,
184 .rqtype = DEVTOMEM,
185 }, {
186 .peri_id = (u8)DMACH_I2S2_TX,
187 .rqtype = MEMTODEV,
188 }, {
189 .peri_id = (u8)DMACH_SPI0_RX,
190 .rqtype = DEVTOMEM,
191 }, {
192 .peri_id = (u8)DMACH_SPI0_TX,
193 .rqtype = MEMTODEV,
194 }, {
195 .peri_id = (u8)DMACH_SPI1_RX,
196 .rqtype = DEVTOMEM,
197 }, {
198 .peri_id = (u8)DMACH_SPI1_TX,
199 .rqtype = MEMTODEV,
200 }, {
201 .peri_id = (u8)DMACH_MAX,
202 }, {
203 .peri_id = (u8)DMACH_MAX,
204 }, {
205 .peri_id = (u8)DMACH_PCM0_RX,
206 .rqtype = DEVTOMEM,
207 }, {
208 .peri_id = (u8)DMACH_PCM0_TX,
209 .rqtype = MEMTODEV,
210 }, {
211 .peri_id = (u8)DMACH_PCM1_RX,
212 .rqtype = DEVTOMEM,
213 }, {
214 .peri_id = (u8)DMACH_PCM1_TX,
215 .rqtype = MEMTODEV,
216 }, {
217 .peri_id = (u8)DMACH_MSM_REQ0,
218 }, {
219 .peri_id = (u8)DMACH_MSM_REQ1,
220 }, {
221 .peri_id = (u8)DMACH_MSM_REQ2,
222 }, {
223 .peri_id = (u8)DMACH_MSM_REQ3,
224 }, {
225 .peri_id = (u8)DMACH_PCM2_RX,
226 .rqtype = DEVTOMEM,
227 }, {
228 .peri_id = (u8)DMACH_PCM2_TX,
229 .rqtype = MEMTODEV,
142 }, 230 },
143}; 231};
144 232
145static struct platform_device s5pv210_device_pdma1 = { 233struct dma_pl330_platdata s5pv210_pdma1_pdata = {
146 .name = "s3c-pl330", 234 .nr_valid_peri = ARRAY_SIZE(pdma1_peri),
147 .id = 1, 235 .peri = pdma1_peri,
148 .num_resources = ARRAY_SIZE(s5pv210_pdma1_resource), 236};
149 .resource = s5pv210_pdma1_resource, 237
150 .dev = { 238struct amba_device s5pv210_device_pdma1 = {
239 .dev = {
240 .init_name = "dma-pl330.1",
151 .dma_mask = &dma_dmamask, 241 .dma_mask = &dma_dmamask,
152 .coherent_dma_mask = DMA_BIT_MASK(32), 242 .coherent_dma_mask = DMA_BIT_MASK(32),
153 .platform_data = &s5pv210_pdma1_pdata, 243 .platform_data = &s5pv210_pdma1_pdata,
154 }, 244 },
155}; 245 .res = {
156 246 .start = S5PV210_PA_PDMA1,
157static struct platform_device *s5pv210_dmacs[] __initdata = { 247 .end = S5PV210_PA_PDMA1 + SZ_4K,
158 &s5pv210_device_pdma0, 248 .flags = IORESOURCE_MEM,
159 &s5pv210_device_pdma1, 249 },
250 .irq = {IRQ_PDMA1, NO_IRQ},
251 .periphid = 0x00041330,
160}; 252};
161 253
162static int __init s5pv210_dma_init(void) 254static int __init s5pv210_dma_init(void)
163{ 255{
164 platform_add_devices(s5pv210_dmacs, ARRAY_SIZE(s5pv210_dmacs)); 256 amba_device_register(&s5pv210_device_pdma0, &iomem_resource);
257 amba_device_register(&s5pv210_device_pdma1, &iomem_resource);
165 258
166 return 0; 259 return 0;
167} 260}
diff --git a/arch/arm/mach-s5pv210/include/mach/dma.h b/arch/arm/mach-s5pv210/include/mach/dma.h
index 81209eb1409b..201842a3769e 100644
--- a/arch/arm/mach-s5pv210/include/mach/dma.h
+++ b/arch/arm/mach-s5pv210/include/mach/dma.h
@@ -20,7 +20,7 @@
20#ifndef __MACH_DMA_H 20#ifndef __MACH_DMA_H
21#define __MACH_DMA_H 21#define __MACH_DMA_H
22 22
23/* This platform uses the common S3C DMA API driver for PL330 */ 23/* This platform uses the common DMA API driver for PL330 */
24#include <plat/s3c-dma-pl330.h> 24#include <plat/dma-pl330.h>
25 25
26#endif /* __MACH_DMA_H */ 26#endif /* __MACH_DMA_H */
diff --git a/arch/arm/mach-s5pv210/include/mach/i2c-hdmiphy.h b/arch/arm/mach-s5pv210/include/mach/i2c-hdmiphy.h
new file mode 100644
index 000000000000..6afa6242c588
--- /dev/null
+++ b/arch/arm/mach-s5pv210/include/mach/i2c-hdmiphy.h
@@ -0,0 +1,16 @@
1/*
2 * Copyright (C) 2011 Samsung Electronics Co., Ltd.
3 *
4 * S5P series i2c hdmiphy helper definitions
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 */
10
11#ifndef PLAT_S5P_I2C_HDMIPHY_H_
12#define PLAT_S5P_I2C_HDMIPHY_H_
13
14#define S5P_I2C_HDMIPHY_BUS_NUM (3)
15
16#endif
diff --git a/arch/arm/mach-s5pv210/include/mach/irqs.h b/arch/arm/mach-s5pv210/include/mach/irqs.h
index b9f9ec33384d..5e0de3a31f3d 100644
--- a/arch/arm/mach-s5pv210/include/mach/irqs.h
+++ b/arch/arm/mach-s5pv210/include/mach/irqs.h
@@ -56,7 +56,7 @@
56#define IRQ_SPI2 S5P_IRQ_VIC1(17) 56#define IRQ_SPI2 S5P_IRQ_VIC1(17)
57#define IRQ_IRDA S5P_IRQ_VIC1(18) 57#define IRQ_IRDA S5P_IRQ_VIC1(18)
58#define IRQ_IIC2 S5P_IRQ_VIC1(19) 58#define IRQ_IIC2 S5P_IRQ_VIC1(19)
59#define IRQ_IIC3 S5P_IRQ_VIC1(20) 59#define IRQ_IIC_HDMIPHY S5P_IRQ_VIC1(20)
60#define IRQ_HSIRX S5P_IRQ_VIC1(21) 60#define IRQ_HSIRX S5P_IRQ_VIC1(21)
61#define IRQ_HSITX S5P_IRQ_VIC1(22) 61#define IRQ_HSITX S5P_IRQ_VIC1(22)
62#define IRQ_UHOST S5P_IRQ_VIC1(23) 62#define IRQ_UHOST S5P_IRQ_VIC1(23)
@@ -86,7 +86,7 @@
86#define IRQ_HDMI S5P_IRQ_VIC2(12) 86#define IRQ_HDMI S5P_IRQ_VIC2(12)
87#define IRQ_IIC1 S5P_IRQ_VIC2(13) 87#define IRQ_IIC1 S5P_IRQ_VIC2(13)
88#define IRQ_MFC S5P_IRQ_VIC2(14) 88#define IRQ_MFC S5P_IRQ_VIC2(14)
89#define IRQ_TVENC S5P_IRQ_VIC2(15) 89#define IRQ_SDO S5P_IRQ_VIC2(15)
90#define IRQ_I2S0 S5P_IRQ_VIC2(16) 90#define IRQ_I2S0 S5P_IRQ_VIC2(16)
91#define IRQ_I2S1 S5P_IRQ_VIC2(17) 91#define IRQ_I2S1 S5P_IRQ_VIC2(17)
92#define IRQ_I2S2 S5P_IRQ_VIC2(18) 92#define IRQ_I2S2 S5P_IRQ_VIC2(18)
diff --git a/arch/arm/mach-s5pv210/include/mach/map.h b/arch/arm/mach-s5pv210/include/mach/map.h
index aac343c180b2..7ff609f1568b 100644
--- a/arch/arm/mach-s5pv210/include/mach/map.h
+++ b/arch/arm/mach-s5pv210/include/mach/map.h
@@ -90,6 +90,12 @@
90#define S5PV210_PA_FIMC1 0xFB300000 90#define S5PV210_PA_FIMC1 0xFB300000
91#define S5PV210_PA_FIMC2 0xFB400000 91#define S5PV210_PA_FIMC2 0xFB400000
92 92
93#define S5PV210_PA_SDO 0xF9000000
94#define S5PV210_PA_VP 0xF9100000
95#define S5PV210_PA_MIXER 0xF9200000
96#define S5PV210_PA_HDMI 0xFA100000
97#define S5PV210_PA_IIC_HDMIPHY 0xFA900000
98
93/* Compatibiltiy Defines */ 99/* Compatibiltiy Defines */
94 100
95#define S3C_PA_FB S5PV210_PA_FB 101#define S3C_PA_FB S5PV210_PA_FB
@@ -110,6 +116,13 @@
110#define S5P_PA_FIMC2 S5PV210_PA_FIMC2 116#define S5P_PA_FIMC2 S5PV210_PA_FIMC2
111#define S5P_PA_MIPI_CSIS0 S5PV210_PA_MIPI_CSIS 117#define S5P_PA_MIPI_CSIS0 S5PV210_PA_MIPI_CSIS
112#define S5P_PA_MFC S5PV210_PA_MFC 118#define S5P_PA_MFC S5PV210_PA_MFC
119#define S5P_PA_IIC_HDMIPHY S5PV210_PA_IIC_HDMIPHY
120
121#define S5P_PA_SDO S5PV210_PA_SDO
122#define S5P_PA_VP S5PV210_PA_VP
123#define S5P_PA_MIXER S5PV210_PA_MIXER
124#define S5P_PA_HDMI S5PV210_PA_HDMI
125
113#define S5P_PA_ONENAND S5PC110_PA_ONENAND 126#define S5P_PA_ONENAND S5PC110_PA_ONENAND
114#define S5P_PA_ONENAND_DMA S5PC110_PA_ONENAND_DMA 127#define S5P_PA_ONENAND_DMA S5PC110_PA_ONENAND_DMA
115#define S5P_PA_SDRAM S5PV210_PA_SDRAM 128#define S5P_PA_SDRAM S5PV210_PA_SDRAM
diff --git a/arch/arm/mach-s5pv210/include/mach/pm-core.h b/arch/arm/mach-s5pv210/include/mach/pm-core.h
index 3e22109e1b7b..eba8aea63ed8 100644
--- a/arch/arm/mach-s5pv210/include/mach/pm-core.h
+++ b/arch/arm/mach-s5pv210/include/mach/pm-core.h
@@ -43,4 +43,4 @@ static inline void s3c_pm_arch_update_uart(void __iomem *regs,
43} 43}
44 44
45static inline void s3c_pm_restored_gpios(void) { } 45static inline void s3c_pm_restored_gpios(void) { }
46static inline void s3c_pm_saved_gpios(void) { } 46static inline void samsung_pm_saved_gpios(void) { }
diff --git a/arch/arm/mach-s5pv210/include/mach/regs-clock.h b/arch/arm/mach-s5pv210/include/mach/regs-clock.h
index 78925c516346..032de66fb8be 100644
--- a/arch/arm/mach-s5pv210/include/mach/regs-clock.h
+++ b/arch/arm/mach-s5pv210/include/mach/regs-clock.h
@@ -144,8 +144,9 @@
144 144
145#define S5P_OTHERS S5P_CLKREG(0xE000) 145#define S5P_OTHERS S5P_CLKREG(0xE000)
146#define S5P_OM_STAT S5P_CLKREG(0xE100) 146#define S5P_OM_STAT S5P_CLKREG(0xE100)
147#define S5P_HDMI_PHY_CONTROL S5P_CLKREG(0xE804)
147#define S5P_USB_PHY_CONTROL S5P_CLKREG(0xE80C) 148#define S5P_USB_PHY_CONTROL S5P_CLKREG(0xE80C)
148#define S5P_DAC_CONTROL S5P_CLKREG(0xE810) 149#define S5P_DAC_PHY_CONTROL S5P_CLKREG(0xE810)
149#define S5P_MIPI_DPHY_CONTROL(x) S5P_CLKREG(0xE814) 150#define S5P_MIPI_DPHY_CONTROL(x) S5P_CLKREG(0xE814)
150#define S5P_MIPI_DPHY_ENABLE (1 << 0) 151#define S5P_MIPI_DPHY_ENABLE (1 << 0)
151#define S5P_MIPI_DPHY_SRESETN (1 << 1) 152#define S5P_MIPI_DPHY_SRESETN (1 << 1)
diff --git a/arch/arm/mach-s5pv210/mach-goni.c b/arch/arm/mach-s5pv210/mach-goni.c
index 85c2d51a0956..01e4867e25ad 100644
--- a/arch/arm/mach-s5pv210/mach-goni.c
+++ b/arch/arm/mach-s5pv210/mach-goni.c
@@ -48,6 +48,11 @@
48#include <plat/s5p-time.h> 48#include <plat/s5p-time.h>
49#include <plat/mfc.h> 49#include <plat/mfc.h>
50#include <plat/regs-fb-v4.h> 50#include <plat/regs-fb-v4.h>
51#include <plat/camport.h>
52
53#include <media/v4l2-mediabus.h>
54#include <media/s5p_fimc.h>
55#include <media/noon010pc30.h>
51 56
52/* Following are default values for UCON, ULCON and UFCON UART registers */ 57/* Following are default values for UCON, ULCON and UFCON UART registers */
53#define GONI_UCON_DEFAULT (S3C2410_UCON_TXILEVEL | \ 58#define GONI_UCON_DEFAULT (S3C2410_UCON_TXILEVEL | \
@@ -272,6 +277,14 @@ static void __init goni_tsp_init(void)
272 i2c2_devs[0].irq = gpio_to_irq(gpio); 277 i2c2_devs[0].irq = gpio_to_irq(gpio);
273} 278}
274 279
280static void goni_camera_init(void)
281{
282 s5pv210_fimc_setup_gpio(S5P_CAMPORT_A);
283
284 /* Set max driver strength on CAM_A_CLKOUT pin. */
285 s5p_gpio_set_drvstr(S5PV210_GPE1(3), S5P_GPIO_DRVSTR_LV4);
286}
287
275/* MAX8998 regulators */ 288/* MAX8998 regulators */
276#if defined(CONFIG_REGULATOR_MAX8998) || defined(CONFIG_REGULATOR_MAX8998_MODULE) 289#if defined(CONFIG_REGULATOR_MAX8998) || defined(CONFIG_REGULATOR_MAX8998_MODULE)
277 290
@@ -285,6 +298,7 @@ static struct regulator_consumer_supply goni_ldo5_consumers[] = {
285 298
286static struct regulator_consumer_supply goni_ldo8_consumers[] = { 299static struct regulator_consumer_supply goni_ldo8_consumers[] = {
287 REGULATOR_SUPPLY("vusb_d", "s3c-hsotg"), 300 REGULATOR_SUPPLY("vusb_d", "s3c-hsotg"),
301 REGULATOR_SUPPLY("vdd33a_dac", "s5p-sdo"),
288}; 302};
289 303
290static struct regulator_consumer_supply goni_ldo11_consumers[] = { 304static struct regulator_consumer_supply goni_ldo11_consumers[] = {
@@ -475,6 +489,10 @@ static struct regulator_consumer_supply buck1_consumer =
475static struct regulator_consumer_supply buck2_consumer = 489static struct regulator_consumer_supply buck2_consumer =
476 REGULATOR_SUPPLY("vddint", NULL); 490 REGULATOR_SUPPLY("vddint", NULL);
477 491
492static struct regulator_consumer_supply buck3_consumer =
493 REGULATOR_SUPPLY("vdet", "s5p-sdo");
494
495
478static struct regulator_init_data goni_buck1_data = { 496static struct regulator_init_data goni_buck1_data = {
479 .constraints = { 497 .constraints = {
480 .name = "VARM_1.2V", 498 .name = "VARM_1.2V",
@@ -511,6 +529,8 @@ static struct regulator_init_data goni_buck3_data = {
511 .enabled = 1, 529 .enabled = 1,
512 }, 530 },
513 }, 531 },
532 .num_consumer_supplies = 1,
533 .consumer_supplies = &buck3_consumer,
514}; 534};
515 535
516static struct regulator_init_data goni_buck4_data = { 536static struct regulator_init_data goni_buck4_data = {
@@ -801,6 +821,39 @@ static void goni_setup_sdhci(void)
801 s3c_sdhci2_set_platdata(&goni_hsmmc2_data); 821 s3c_sdhci2_set_platdata(&goni_hsmmc2_data);
802}; 822};
803 823
824static struct noon010pc30_platform_data noon010pc30_pldata = {
825 .clk_rate = 16000000UL,
826 .gpio_nreset = S5PV210_GPB(2), /* CAM_CIF_NRST */
827 .gpio_nstby = S5PV210_GPB(0), /* CAM_CIF_NSTBY */
828};
829
830static struct i2c_board_info noon010pc30_board_info = {
831 I2C_BOARD_INFO("NOON010PC30", 0x60 >> 1),
832 .platform_data = &noon010pc30_pldata,
833};
834
835static struct s5p_fimc_isp_info goni_camera_sensors[] = {
836 {
837 .mux_id = 0,
838 .flags = V4L2_MBUS_PCLK_SAMPLE_FALLING |
839 V4L2_MBUS_VSYNC_ACTIVE_LOW,
840 .bus_type = FIMC_ITU_601,
841 .board_info = &noon010pc30_board_info,
842 .i2c_bus_num = 0,
843 .clk_frequency = 16000000UL,
844 },
845};
846
847struct s5p_platform_fimc goni_fimc_md_platdata __initdata = {
848 .isp_info = goni_camera_sensors,
849 .num_clients = ARRAY_SIZE(goni_camera_sensors),
850};
851
852struct platform_device s5p_device_fimc_md = {
853 .name = "s5p-fimc-md",
854 .id = -1,
855};
856
804static struct platform_device *goni_devices[] __initdata = { 857static struct platform_device *goni_devices[] __initdata = {
805 &s3c_device_fb, 858 &s3c_device_fb,
806 &s5p_device_onenand, 859 &s5p_device_onenand,
@@ -812,10 +865,13 @@ static struct platform_device *goni_devices[] __initdata = {
812 &s5p_device_mfc, 865 &s5p_device_mfc,
813 &s5p_device_mfc_l, 866 &s5p_device_mfc_l,
814 &s5p_device_mfc_r, 867 &s5p_device_mfc_r,
868 &s5p_device_mixer,
869 &s5p_device_sdo,
815 &s3c_device_i2c0, 870 &s3c_device_i2c0,
816 &s5p_device_fimc0, 871 &s5p_device_fimc0,
817 &s5p_device_fimc1, 872 &s5p_device_fimc1,
818 &s5p_device_fimc2, 873 &s5p_device_fimc2,
874 &s5p_device_fimc_md,
819 &s3c_device_hsmmc0, 875 &s3c_device_hsmmc0,
820 &s3c_device_hsmmc1, 876 &s3c_device_hsmmc1,
821 &s3c_device_hsmmc2, 877 &s3c_device_hsmmc2,
@@ -884,6 +940,12 @@ static void __init goni_machine_init(void)
884 /* FB */ 940 /* FB */
885 s3c_fb_set_platdata(&goni_lcd_pdata); 941 s3c_fb_set_platdata(&goni_lcd_pdata);
886 942
943 /* FIMC */
944 s3c_set_platdata(&goni_fimc_md_platdata, sizeof(goni_fimc_md_platdata),
945 &s5p_device_fimc_md);
946
947 goni_camera_init();
948
887 /* SPI */ 949 /* SPI */
888 spi_register_board_info(spi_board_info, ARRAY_SIZE(spi_board_info)); 950 spi_register_board_info(spi_board_info, ARRAY_SIZE(spi_board_info));
889 951
diff --git a/arch/arm/plat-s3c24xx/Kconfig b/arch/arm/plat-s3c24xx/Kconfig
index 8c5b3029b39f..d8973ac46bc4 100644
--- a/arch/arm/plat-s3c24xx/Kconfig
+++ b/arch/arm/plat-s3c24xx/Kconfig
@@ -9,7 +9,6 @@ config PLAT_S3C24XX
9 select NO_IOPORT 9 select NO_IOPORT
10 select ARCH_REQUIRE_GPIOLIB 10 select ARCH_REQUIRE_GPIOLIB
11 select S3C_DEV_NAND 11 select S3C_DEV_NAND
12 select S3C_GPIO_CFG_S3C24XX
13 help 12 help
14 Base platform code for any Samsung S3C24XX device 13 Base platform code for any Samsung S3C24XX device
15 14
diff --git a/arch/arm/plat-s3c24xx/Makefile b/arch/arm/plat-s3c24xx/Makefile
index 0291bd6e236e..e4f46495ed30 100644
--- a/arch/arm/plat-s3c24xx/Makefile
+++ b/arch/arm/plat-s3c24xx/Makefile
@@ -15,8 +15,6 @@ obj- :=
15obj-y += cpu.o 15obj-y += cpu.o
16obj-y += irq.o 16obj-y += irq.o
17obj-y += devs.o 17obj-y += devs.o
18obj-y += gpio.o
19obj-y += gpiolib.o
20obj-y += clock.o 18obj-y += clock.o
21obj-$(CONFIG_S3C24XX_DCLK) += clock-dclk.o 19obj-$(CONFIG_S3C24XX_DCLK) += clock-dclk.o
22 20
diff --git a/arch/arm/plat-s3c24xx/dma.c b/arch/arm/plat-s3c24xx/dma.c
index 539bd0e3defd..53754bcf15a7 100644
--- a/arch/arm/plat-s3c24xx/dma.c
+++ b/arch/arm/plat-s3c24xx/dma.c
@@ -1094,14 +1094,14 @@ EXPORT_SYMBOL(s3c2410_dma_config);
1094 * 1094 *
1095 * configure the dma source/destination hardware type and address 1095 * configure the dma source/destination hardware type and address
1096 * 1096 *
1097 * source: S3C2410_DMASRC_HW: source is hardware 1097 * source: DMA_FROM_DEVICE: source is hardware
1098 * S3C2410_DMASRC_MEM: source is memory 1098 * DMA_TO_DEVICE: source is memory
1099 * 1099 *
1100 * devaddr: physical address of the source 1100 * devaddr: physical address of the source
1101*/ 1101*/
1102 1102
1103int s3c2410_dma_devconfig(enum dma_ch channel, 1103int s3c2410_dma_devconfig(enum dma_ch channel,
1104 enum s3c2410_dmasrc source, 1104 enum dma_data_direction source,
1105 unsigned long devaddr) 1105 unsigned long devaddr)
1106{ 1106{
1107 struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel); 1107 struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel);
@@ -1131,7 +1131,7 @@ int s3c2410_dma_devconfig(enum dma_ch channel,
1131 hwcfg |= S3C2410_DISRCC_INC; 1131 hwcfg |= S3C2410_DISRCC_INC;
1132 1132
1133 switch (source) { 1133 switch (source) {
1134 case S3C2410_DMASRC_HW: 1134 case DMA_FROM_DEVICE:
1135 /* source is hardware */ 1135 /* source is hardware */
1136 pr_debug("%s: hw source, devaddr=%08lx, hwcfg=%d\n", 1136 pr_debug("%s: hw source, devaddr=%08lx, hwcfg=%d\n",
1137 __func__, devaddr, hwcfg); 1137 __func__, devaddr, hwcfg);
@@ -1142,7 +1142,7 @@ int s3c2410_dma_devconfig(enum dma_ch channel,
1142 chan->addr_reg = dma_regaddr(chan, S3C2410_DMA_DIDST); 1142 chan->addr_reg = dma_regaddr(chan, S3C2410_DMA_DIDST);
1143 break; 1143 break;
1144 1144
1145 case S3C2410_DMASRC_MEM: 1145 case DMA_TO_DEVICE:
1146 /* source is memory */ 1146 /* source is memory */
1147 pr_debug("%s: mem source, devaddr=%08lx, hwcfg=%d\n", 1147 pr_debug("%s: mem source, devaddr=%08lx, hwcfg=%d\n",
1148 __func__, devaddr, hwcfg); 1148 __func__, devaddr, hwcfg);
diff --git a/arch/arm/plat-s3c24xx/gpio.c b/arch/arm/plat-s3c24xx/gpio.c
deleted file mode 100644
index 2f3d7c089dfa..000000000000
--- a/arch/arm/plat-s3c24xx/gpio.c
+++ /dev/null
@@ -1,96 +0,0 @@
1/* linux/arch/arm/plat-s3c24xx/gpio.c
2 *
3 * Copyright (c) 2004-2010 Simtec Electronics
4 * Ben Dooks <ben@simtec.co.uk>
5 *
6 * S3C24XX GPIO support
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21*/
22
23#include <linux/kernel.h>
24#include <linux/init.h>
25#include <linux/module.h>
26#include <linux/interrupt.h>
27#include <linux/ioport.h>
28#include <linux/gpio.h>
29#include <linux/io.h>
30
31#include <mach/hardware.h>
32#include <mach/gpio-fns.h>
33#include <asm/irq.h>
34
35#include <mach/regs-gpio.h>
36
37#include <plat/gpio-core.h>
38
39/* gpiolib wrappers until these are totally eliminated */
40
41void s3c2410_gpio_pullup(unsigned int pin, unsigned int to)
42{
43 int ret;
44
45 WARN_ON(to); /* should be none of these left */
46
47 if (!to) {
48 /* if pull is enabled, try first with up, and if that
49 * fails, try using down */
50
51 ret = s3c_gpio_setpull(pin, S3C_GPIO_PULL_UP);
52 if (ret)
53 s3c_gpio_setpull(pin, S3C_GPIO_PULL_DOWN);
54 } else {
55 s3c_gpio_setpull(pin, S3C_GPIO_PULL_NONE);
56 }
57}
58EXPORT_SYMBOL(s3c2410_gpio_pullup);
59
60void s3c2410_gpio_setpin(unsigned int pin, unsigned int to)
61{
62 /* do this via gpiolib until all users removed */
63
64 gpio_request(pin, "temporary");
65 gpio_set_value(pin, to);
66 gpio_free(pin);
67}
68
69EXPORT_SYMBOL(s3c2410_gpio_setpin);
70
71unsigned int s3c2410_gpio_getpin(unsigned int pin)
72{
73 struct s3c_gpio_chip *chip = s3c_gpiolib_getchip(pin);
74 unsigned long offs = pin - chip->chip.base;
75
76 return __raw_readl(chip->base + 0x04) & (1<< offs);
77}
78
79EXPORT_SYMBOL(s3c2410_gpio_getpin);
80
81unsigned int s3c2410_modify_misccr(unsigned int clear, unsigned int change)
82{
83 unsigned long flags;
84 unsigned long misccr;
85
86 local_irq_save(flags);
87 misccr = __raw_readl(S3C24XX_MISCCR);
88 misccr &= ~clear;
89 misccr ^= change;
90 __raw_writel(misccr, S3C24XX_MISCCR);
91 local_irq_restore(flags);
92
93 return misccr;
94}
95
96EXPORT_SYMBOL(s3c2410_modify_misccr);
diff --git a/arch/arm/plat-s3c24xx/gpiolib.c b/arch/arm/plat-s3c24xx/gpiolib.c
deleted file mode 100644
index 243b6411050d..000000000000
--- a/arch/arm/plat-s3c24xx/gpiolib.c
+++ /dev/null
@@ -1,229 +0,0 @@
1/* linux/arch/arm/plat-s3c24xx/gpiolib.c
2 *
3 * Copyright (c) 2008-2010 Simtec Electronics
4 * http://armlinux.simtec.co.uk/
5 * Ben Dooks <ben@simtec.co.uk>
6 *
7 * S3C24XX GPIOlib support
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License.
12*/
13
14#include <linux/kernel.h>
15#include <linux/init.h>
16#include <linux/module.h>
17#include <linux/interrupt.h>
18#include <linux/sysdev.h>
19#include <linux/ioport.h>
20#include <linux/io.h>
21#include <linux/gpio.h>
22
23#include <plat/gpio-core.h>
24#include <plat/gpio-cfg.h>
25#include <plat/gpio-cfg-helpers.h>
26#include <mach/hardware.h>
27#include <asm/irq.h>
28#include <plat/pm.h>
29
30#include <mach/regs-gpio.h>
31
32static int s3c24xx_gpiolib_banka_input(struct gpio_chip *chip, unsigned offset)
33{
34 return -EINVAL;
35}
36
37static int s3c24xx_gpiolib_banka_output(struct gpio_chip *chip,
38 unsigned offset, int value)
39{
40 struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
41 void __iomem *base = ourchip->base;
42 unsigned long flags;
43 unsigned long dat;
44 unsigned long con;
45
46 local_irq_save(flags);
47
48 con = __raw_readl(base + 0x00);
49 dat = __raw_readl(base + 0x04);
50
51 dat &= ~(1 << offset);
52 if (value)
53 dat |= 1 << offset;
54
55 __raw_writel(dat, base + 0x04);
56
57 con &= ~(1 << offset);
58
59 __raw_writel(con, base + 0x00);
60 __raw_writel(dat, base + 0x04);
61
62 local_irq_restore(flags);
63 return 0;
64}
65
66static int s3c24xx_gpiolib_bankf_toirq(struct gpio_chip *chip, unsigned offset)
67{
68 if (offset < 4)
69 return IRQ_EINT0 + offset;
70
71 if (offset < 8)
72 return IRQ_EINT4 + offset - 4;
73
74 return -EINVAL;
75}
76
77static struct s3c_gpio_cfg s3c24xx_gpiocfg_banka = {
78 .set_config = s3c_gpio_setcfg_s3c24xx_a,
79 .get_config = s3c_gpio_getcfg_s3c24xx_a,
80};
81
82struct s3c_gpio_cfg s3c24xx_gpiocfg_default = {
83 .set_config = s3c_gpio_setcfg_s3c24xx,
84 .get_config = s3c_gpio_getcfg_s3c24xx,
85};
86
87struct s3c_gpio_chip s3c24xx_gpios[] = {
88 [0] = {
89 .base = S3C2410_GPACON,
90 .pm = __gpio_pm(&s3c_gpio_pm_1bit),
91 .config = &s3c24xx_gpiocfg_banka,
92 .chip = {
93 .base = S3C2410_GPA(0),
94 .owner = THIS_MODULE,
95 .label = "GPIOA",
96 .ngpio = 24,
97 .direction_input = s3c24xx_gpiolib_banka_input,
98 .direction_output = s3c24xx_gpiolib_banka_output,
99 },
100 },
101 [1] = {
102 .base = S3C2410_GPBCON,
103 .pm = __gpio_pm(&s3c_gpio_pm_2bit),
104 .chip = {
105 .base = S3C2410_GPB(0),
106 .owner = THIS_MODULE,
107 .label = "GPIOB",
108 .ngpio = 16,
109 },
110 },
111 [2] = {
112 .base = S3C2410_GPCCON,
113 .pm = __gpio_pm(&s3c_gpio_pm_2bit),
114 .chip = {
115 .base = S3C2410_GPC(0),
116 .owner = THIS_MODULE,
117 .label = "GPIOC",
118 .ngpio = 16,
119 },
120 },
121 [3] = {
122 .base = S3C2410_GPDCON,
123 .pm = __gpio_pm(&s3c_gpio_pm_2bit),
124 .chip = {
125 .base = S3C2410_GPD(0),
126 .owner = THIS_MODULE,
127 .label = "GPIOD",
128 .ngpio = 16,
129 },
130 },
131 [4] = {
132 .base = S3C2410_GPECON,
133 .pm = __gpio_pm(&s3c_gpio_pm_2bit),
134 .chip = {
135 .base = S3C2410_GPE(0),
136 .label = "GPIOE",
137 .owner = THIS_MODULE,
138 .ngpio = 16,
139 },
140 },
141 [5] = {
142 .base = S3C2410_GPFCON,
143 .pm = __gpio_pm(&s3c_gpio_pm_2bit),
144 .chip = {
145 .base = S3C2410_GPF(0),
146 .owner = THIS_MODULE,
147 .label = "GPIOF",
148 .ngpio = 8,
149 .to_irq = s3c24xx_gpiolib_bankf_toirq,
150 },
151 },
152 [6] = {
153 .base = S3C2410_GPGCON,
154 .pm = __gpio_pm(&s3c_gpio_pm_2bit),
155 .irq_base = IRQ_EINT8,
156 .chip = {
157 .base = S3C2410_GPG(0),
158 .owner = THIS_MODULE,
159 .label = "GPIOG",
160 .ngpio = 16,
161 .to_irq = samsung_gpiolib_to_irq,
162 },
163 }, {
164 .base = S3C2410_GPHCON,
165 .pm = __gpio_pm(&s3c_gpio_pm_2bit),
166 .chip = {
167 .base = S3C2410_GPH(0),
168 .owner = THIS_MODULE,
169 .label = "GPIOH",
170 .ngpio = 11,
171 },
172 },
173 /* GPIOS for the S3C2443 and later devices. */
174 {
175 .base = S3C2440_GPJCON,
176 .pm = __gpio_pm(&s3c_gpio_pm_2bit),
177 .chip = {
178 .base = S3C2410_GPJ(0),
179 .owner = THIS_MODULE,
180 .label = "GPIOJ",
181 .ngpio = 16,
182 },
183 }, {
184 .base = S3C2443_GPKCON,
185 .pm = __gpio_pm(&s3c_gpio_pm_2bit),
186 .chip = {
187 .base = S3C2410_GPK(0),
188 .owner = THIS_MODULE,
189 .label = "GPIOK",
190 .ngpio = 16,
191 },
192 }, {
193 .base = S3C2443_GPLCON,
194 .pm = __gpio_pm(&s3c_gpio_pm_2bit),
195 .chip = {
196 .base = S3C2410_GPL(0),
197 .owner = THIS_MODULE,
198 .label = "GPIOL",
199 .ngpio = 15,
200 },
201 }, {
202 .base = S3C2443_GPMCON,
203 .pm = __gpio_pm(&s3c_gpio_pm_2bit),
204 .chip = {
205 .base = S3C2410_GPM(0),
206 .owner = THIS_MODULE,
207 .label = "GPIOM",
208 .ngpio = 2,
209 },
210 },
211};
212
213
214static __init int s3c24xx_gpiolib_init(void)
215{
216 struct s3c_gpio_chip *chip = s3c24xx_gpios;
217 int gpn;
218
219 for (gpn = 0; gpn < ARRAY_SIZE(s3c24xx_gpios); gpn++, chip++) {
220 if (!chip->config)
221 chip->config = &s3c24xx_gpiocfg_default;
222
223 s3c_gpiolib_add(chip);
224 }
225
226 return 0;
227}
228
229core_initcall(s3c24xx_gpiolib_init);
diff --git a/arch/arm/plat-s3c24xx/s3c2443-clock.c b/arch/arm/plat-s3c24xx/s3c2443-clock.c
index 59552c0ea5fb..07a4c81587ac 100644
--- a/arch/arm/plat-s3c24xx/s3c2443-clock.c
+++ b/arch/arm/plat-s3c24xx/s3c2443-clock.c
@@ -205,9 +205,64 @@ static struct clksrc_clk clksrc_clks[] = {
205 }, 205 },
206}; 206};
207 207
208static struct clk clk_i2s_ext = {
209 .name = "i2s-ext",
210};
211
212/* i2s_eplldiv
213 *
214 * This clock is the output from the I2S divisor of ESYSCLK, and is separate
215 * from the mux that comes after it (cannot merge into one single clock)
216*/
217
218static struct clksrc_clk clk_i2s_eplldiv = {
219 .clk = {
220 .name = "i2s-eplldiv",
221 .parent = &clk_esysclk.clk,
222 },
223 .reg_div = { .reg = S3C2443_CLKDIV1, .size = 4, .shift = 12, },
224};
225
226/* i2s-ref
227 *
228 * i2s bus reference clock, selectable from external, esysclk or epllref
229 *
230 * Note, this used to be two clocks, but was compressed into one.
231*/
232
233static struct clk *clk_i2s_srclist[] = {
234 [0] = &clk_i2s_eplldiv.clk,
235 [1] = &clk_i2s_ext,
236 [2] = &clk_epllref.clk,
237 [3] = &clk_epllref.clk,
238};
239
240static struct clksrc_clk clk_i2s = {
241 .clk = {
242 .name = "i2s-if",
243 .ctrlbit = S3C2443_SCLKCON_I2SCLK,
244 .enable = s3c2443_clkcon_enable_s,
245
246 },
247 .sources = &(struct clksrc_sources) {
248 .sources = clk_i2s_srclist,
249 .nr_sources = ARRAY_SIZE(clk_i2s_srclist),
250 },
251 .reg_src = { .reg = S3C2443_CLKSRC, .size = 2, .shift = 14 },
252};
208 253
209static struct clk init_clocks_off[] = { 254static struct clk init_clocks_off[] = {
210 { 255 {
256 .name = "iis",
257 .parent = &clk_p,
258 .enable = s3c2443_clkcon_enable_p,
259 .ctrlbit = S3C2443_PCLKCON_IIS,
260 }, {
261 .name = "hsspi",
262 .parent = &clk_p,
263 .enable = s3c2443_clkcon_enable_p,
264 .ctrlbit = S3C2443_PCLKCON_HSSPI,
265 }, {
211 .name = "adc", 266 .name = "adc",
212 .parent = &clk_p, 267 .parent = &clk_p,
213 .enable = s3c2443_clkcon_enable_p, 268 .enable = s3c2443_clkcon_enable_p,
@@ -406,6 +461,8 @@ static struct clk *clks[] __initdata = {
406}; 461};
407 462
408static struct clksrc_clk *clksrcs[] __initdata = { 463static struct clksrc_clk *clksrcs[] __initdata = {
464 &clk_i2s_eplldiv,
465 &clk_i2s,
409 &clk_usb_bus_host, 466 &clk_usb_bus_host,
410 &clk_epllref, 467 &clk_epllref,
411 &clk_esysclk, 468 &clk_esysclk,
diff --git a/arch/arm/plat-s5p/Kconfig b/arch/arm/plat-s5p/Kconfig
index 9843c954c042..f9241a7a68ca 100644
--- a/arch/arm/plat-s5p/Kconfig
+++ b/arch/arm/plat-s5p/Kconfig
@@ -16,9 +16,6 @@ config PLAT_S5P
16 select S3C_GPIO_TRACK 16 select S3C_GPIO_TRACK
17 select S5P_GPIO_DRVSTR 17 select S5P_GPIO_DRVSTR
18 select SAMSUNG_GPIOLIB_4BIT 18 select SAMSUNG_GPIOLIB_4BIT
19 select S3C_GPIO_CFG_S3C64XX
20 select S3C_GPIO_PULL_UPDOWN
21 select S3C_GPIO_CFG_S3C24XX
22 select PLAT_SAMSUNG 19 select PLAT_SAMSUNG
23 select SAMSUNG_CLKSRC 20 select SAMSUNG_CLKSRC
24 select SAMSUNG_IRQ_VIC_TIMER 21 select SAMSUNG_IRQ_VIC_TIMER
@@ -76,6 +73,11 @@ config S5P_DEV_FIMD0
76 help 73 help
77 Compile in platform device definitions for FIMD controller 0 74 Compile in platform device definitions for FIMD controller 0
78 75
76config S5P_DEV_I2C_HDMIPHY
77 bool
78 help
79 Compile in platform device definitions for I2C HDMIPHY controller
80
79config S5P_DEV_MFC 81config S5P_DEV_MFC
80 bool 82 bool
81 help 83 help
@@ -96,6 +98,11 @@ config S5P_DEV_CSIS1
96 help 98 help
97 Compile in platform device definitions for MIPI-CSIS channel 1 99 Compile in platform device definitions for MIPI-CSIS channel 1
98 100
101config S5P_DEV_TV
102 bool
103 help
104 Compile in platform device definition for TV interface
105
99config S5P_DEV_USB_EHCI 106config S5P_DEV_USB_EHCI
100 bool 107 bool
101 help 108 help
diff --git a/arch/arm/plat-s5p/Makefile b/arch/arm/plat-s5p/Makefile
index 4b53e04eeca4..181201974b41 100644
--- a/arch/arm/plat-s5p/Makefile
+++ b/arch/arm/plat-s5p/Makefile
@@ -31,8 +31,10 @@ obj-$(CONFIG_S5P_DEV_FIMC1) += dev-fimc1.o
31obj-$(CONFIG_S5P_DEV_FIMC2) += dev-fimc2.o 31obj-$(CONFIG_S5P_DEV_FIMC2) += dev-fimc2.o
32obj-$(CONFIG_S5P_DEV_FIMC3) += dev-fimc3.o 32obj-$(CONFIG_S5P_DEV_FIMC3) += dev-fimc3.o
33obj-$(CONFIG_S5P_DEV_FIMD0) += dev-fimd0.o 33obj-$(CONFIG_S5P_DEV_FIMD0) += dev-fimd0.o
34obj-$(CONFIG_S5P_DEV_I2C_HDMIPHY) += dev-i2c-hdmiphy.o
34obj-$(CONFIG_S5P_DEV_ONENAND) += dev-onenand.o 35obj-$(CONFIG_S5P_DEV_ONENAND) += dev-onenand.o
35obj-$(CONFIG_S5P_DEV_CSIS0) += dev-csis0.o 36obj-$(CONFIG_S5P_DEV_CSIS0) += dev-csis0.o
36obj-$(CONFIG_S5P_DEV_CSIS1) += dev-csis1.o 37obj-$(CONFIG_S5P_DEV_CSIS1) += dev-csis1.o
38obj-$(CONFIG_S5P_DEV_TV) += dev-tv.o
37obj-$(CONFIG_S5P_DEV_USB_EHCI) += dev-ehci.o 39obj-$(CONFIG_S5P_DEV_USB_EHCI) += dev-ehci.o
38obj-$(CONFIG_S5P_SETUP_MIPIPHY) += setup-mipiphy.o 40obj-$(CONFIG_S5P_SETUP_MIPIPHY) += setup-mipiphy.o
diff --git a/arch/arm/plat-s5p/dev-i2c-hdmiphy.c b/arch/arm/plat-s5p/dev-i2c-hdmiphy.c
new file mode 100644
index 000000000000..37343f1999f0
--- /dev/null
+++ b/arch/arm/plat-s5p/dev-i2c-hdmiphy.c
@@ -0,0 +1,59 @@
1/*
2 * Copyright (c) 2011 Samsung Electronics Co., Ltd.
3 * http://www.samsung.com/
4 *
5 * S5P series device definition for i2c for hdmiphy device
6 *
7 * Based on plat-samsung/dev-i2c7.c
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
12*/
13
14#include <linux/gfp.h>
15#include <linux/kernel.h>
16#include <linux/string.h>
17#include <linux/platform_device.h>
18
19#include <mach/irqs.h>
20#include <mach/map.h>
21#include <mach/i2c-hdmiphy.h>
22
23#include <plat/regs-iic.h>
24#include <plat/devs.h>
25#include <plat/cpu.h>
26#include <plat/iic.h>
27
28static struct resource s5p_i2c_resource[] = {
29 [0] = {
30 .start = S5P_PA_IIC_HDMIPHY,
31 .end = S5P_PA_IIC_HDMIPHY + SZ_4K - 1,
32 .flags = IORESOURCE_MEM,
33 },
34 [1] = {
35 .start = IRQ_IIC_HDMIPHY,
36 .end = IRQ_IIC_HDMIPHY,
37 .flags = IORESOURCE_IRQ,
38 },
39};
40
41struct platform_device s5p_device_i2c_hdmiphy = {
42 .name = "s3c2440-hdmiphy-i2c",
43 .id = -1,
44 .num_resources = ARRAY_SIZE(s5p_i2c_resource),
45 .resource = s5p_i2c_resource,
46};
47
48void __init s5p_i2c_hdmiphy_set_platdata(struct s3c2410_platform_i2c *pd)
49{
50 struct s3c2410_platform_i2c *npd;
51
52 if (!pd) {
53 pd = &default_i2c_data;
54 pd->bus_num = S5P_I2C_HDMIPHY_BUS_NUM;
55 }
56
57 npd = s3c_set_platdata(pd, sizeof(struct s3c2410_platform_i2c),
58 &s5p_device_i2c_hdmiphy);
59}
diff --git a/arch/arm/plat-s5p/dev-tv.c b/arch/arm/plat-s5p/dev-tv.c
new file mode 100644
index 000000000000..361a1b63a81b
--- /dev/null
+++ b/arch/arm/plat-s5p/dev-tv.c
@@ -0,0 +1,98 @@
1/* linux/arch/arm/plat-s5p/dev-tv.c
2 *
3 * Copyright (C) 2011 Samsung Electronics Co.Ltd
4 * Author: Tomasz Stanislawski <t.stanislaws@samsung.com>
5 *
6 * S5P series device definition for TV device
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11*/
12
13#include <linux/dma-mapping.h>
14
15#include <mach/irqs.h>
16#include <mach/map.h>
17
18#include <plat/devs.h>
19
20/* HDMI interface */
21static struct resource s5p_hdmi_resources[] = {
22 [0] = {
23 .start = S5P_PA_HDMI,
24 .end = S5P_PA_HDMI + SZ_1M - 1,
25 .flags = IORESOURCE_MEM,
26 },
27 [1] = {
28 .start = IRQ_HDMI,
29 .end = IRQ_HDMI,
30 .flags = IORESOURCE_IRQ,
31 },
32};
33
34struct platform_device s5p_device_hdmi = {
35 .name = "s5p-hdmi",
36 .id = -1,
37 .num_resources = ARRAY_SIZE(s5p_hdmi_resources),
38 .resource = s5p_hdmi_resources,
39};
40EXPORT_SYMBOL(s5p_device_hdmi);
41
42/* SDO interface */
43static struct resource s5p_sdo_resources[] = {
44 [0] = {
45 .start = S5P_PA_SDO,
46 .end = S5P_PA_SDO + SZ_64K - 1,
47 .flags = IORESOURCE_MEM,
48 },
49 [1] = {
50 .start = IRQ_SDO,
51 .end = IRQ_SDO,
52 .flags = IORESOURCE_IRQ,
53 }
54};
55
56struct platform_device s5p_device_sdo = {
57 .name = "s5p-sdo",
58 .id = -1,
59 .num_resources = ARRAY_SIZE(s5p_sdo_resources),
60 .resource = s5p_sdo_resources,
61};
62EXPORT_SYMBOL(s5p_device_sdo);
63
64/* MIXER */
65static struct resource s5p_mixer_resources[] = {
66 [0] = {
67 .start = S5P_PA_MIXER,
68 .end = S5P_PA_MIXER + SZ_64K - 1,
69 .flags = IORESOURCE_MEM,
70 .name = "mxr"
71 },
72 [1] = {
73 .start = S5P_PA_VP,
74 .end = S5P_PA_VP + SZ_64K - 1,
75 .flags = IORESOURCE_MEM,
76 .name = "vp"
77 },
78 [2] = {
79 .start = IRQ_MIXER,
80 .end = IRQ_MIXER,
81 .flags = IORESOURCE_IRQ,
82 .name = "irq"
83 }
84};
85
86static u64 s5p_tv_dmamask = DMA_BIT_MASK(32);
87
88struct platform_device s5p_device_mixer = {
89 .name = "s5p-mixer",
90 .id = -1,
91 .num_resources = ARRAY_SIZE(s5p_mixer_resources),
92 .resource = s5p_mixer_resources,
93 .dev = {
94 .coherent_dma_mask = DMA_BIT_MASK(32),
95 .dma_mask = &s5p_tv_dmamask,
96 }
97};
98EXPORT_SYMBOL(s5p_device_mixer);
diff --git a/arch/arm/plat-s5p/include/plat/pll.h b/arch/arm/plat-s5p/include/plat/pll.h
index 3e21b9444cc5..002ec9f28f18 100644
--- a/arch/arm/plat-s5p/include/plat/pll.h
+++ b/arch/arm/plat-s5p/include/plat/pll.h
@@ -97,15 +97,24 @@ static inline unsigned long s5p_get_pll45xx(unsigned long baseclk, u32 pll_con,
97 return (unsigned long)fvco; 97 return (unsigned long)fvco;
98} 98}
99 99
100#define PLL46XX_KDIV_MASK (0xFFFF) 100/* CON0 bit-fields */
101#define PLL4650C_KDIV_MASK (0xFFF)
102#define PLL46XX_MDIV_MASK (0x1FF) 101#define PLL46XX_MDIV_MASK (0x1FF)
103#define PLL46XX_PDIV_MASK (0x3F) 102#define PLL46XX_PDIV_MASK (0x3F)
104#define PLL46XX_SDIV_MASK (0x7) 103#define PLL46XX_SDIV_MASK (0x7)
104#define PLL46XX_LOCKED_SHIFT (29)
105#define PLL46XX_MDIV_SHIFT (16) 105#define PLL46XX_MDIV_SHIFT (16)
106#define PLL46XX_PDIV_SHIFT (8) 106#define PLL46XX_PDIV_SHIFT (8)
107#define PLL46XX_SDIV_SHIFT (0) 107#define PLL46XX_SDIV_SHIFT (0)
108 108
109/* CON1 bit-fields */
110#define PLL46XX_MRR_MASK (0x1F)
111#define PLL46XX_MFR_MASK (0x3F)
112#define PLL46XX_KDIV_MASK (0xFFFF)
113#define PLL4650C_KDIV_MASK (0xFFF)
114#define PLL46XX_MRR_SHIFT (24)
115#define PLL46XX_MFR_SHIFT (16)
116#define PLL46XX_KDIV_SHIFT (0)
117
109enum pll46xx_type_t { 118enum pll46xx_type_t {
110 pll_4600, 119 pll_4600,
111 pll_4650, 120 pll_4650,
@@ -148,6 +157,7 @@ static inline unsigned long s5p_get_pll46xx(unsigned long baseclk,
148#define PLL90XX_PDIV_MASK (0x3F) 157#define PLL90XX_PDIV_MASK (0x3F)
149#define PLL90XX_SDIV_MASK (0x7) 158#define PLL90XX_SDIV_MASK (0x7)
150#define PLL90XX_KDIV_MASK (0xffff) 159#define PLL90XX_KDIV_MASK (0xffff)
160#define PLL90XX_LOCKED_SHIFT (29)
151#define PLL90XX_MDIV_SHIFT (16) 161#define PLL90XX_MDIV_SHIFT (16)
152#define PLL90XX_PDIV_SHIFT (8) 162#define PLL90XX_PDIV_SHIFT (8)
153#define PLL90XX_SDIV_SHIFT (0) 163#define PLL90XX_SDIV_SHIFT (0)
diff --git a/arch/arm/plat-s5p/irq-gpioint.c b/arch/arm/plat-s5p/irq-gpioint.c
index f88216d23991..a566523d34ec 100644
--- a/arch/arm/plat-s5p/irq-gpioint.c
+++ b/arch/arm/plat-s5p/irq-gpioint.c
@@ -37,7 +37,7 @@ struct s5p_gpioint_bank {
37 int start; 37 int start;
38 int nr_groups; 38 int nr_groups;
39 int irq; 39 int irq;
40 struct s3c_gpio_chip **chips; 40 struct samsung_gpio_chip **chips;
41 void (*handler)(unsigned int, struct irq_desc *); 41 void (*handler)(unsigned int, struct irq_desc *);
42}; 42};
43 43
@@ -87,7 +87,7 @@ static void s5p_gpioint_handler(unsigned int irq, struct irq_desc *desc)
87 chained_irq_enter(chip, desc); 87 chained_irq_enter(chip, desc);
88 88
89 for (group = 0; group < bank->nr_groups; group++) { 89 for (group = 0; group < bank->nr_groups; group++) {
90 struct s3c_gpio_chip *chip = bank->chips[group]; 90 struct samsung_gpio_chip *chip = bank->chips[group];
91 if (!chip) 91 if (!chip)
92 continue; 92 continue;
93 93
@@ -110,7 +110,7 @@ static void s5p_gpioint_handler(unsigned int irq, struct irq_desc *desc)
110 chained_irq_exit(chip, desc); 110 chained_irq_exit(chip, desc);
111} 111}
112 112
113static __init int s5p_gpioint_add(struct s3c_gpio_chip *chip) 113static __init int s5p_gpioint_add(struct samsung_gpio_chip *chip)
114{ 114{
115 static int used_gpioint_groups = 0; 115 static int used_gpioint_groups = 0;
116 int group = chip->group; 116 int group = chip->group;
@@ -131,7 +131,7 @@ static __init int s5p_gpioint_add(struct s3c_gpio_chip *chip)
131 return -EINVAL; 131 return -EINVAL;
132 132
133 if (!bank->handler) { 133 if (!bank->handler) {
134 bank->chips = kzalloc(sizeof(struct s3c_gpio_chip *) * 134 bank->chips = kzalloc(sizeof(struct samsung_gpio_chip *) *
135 bank->nr_groups, GFP_KERNEL); 135 bank->nr_groups, GFP_KERNEL);
136 if (!bank->chips) 136 if (!bank->chips)
137 return -ENOMEM; 137 return -ENOMEM;
@@ -174,7 +174,7 @@ static __init int s5p_gpioint_add(struct s3c_gpio_chip *chip)
174 174
175int __init s5p_register_gpio_interrupt(int pin) 175int __init s5p_register_gpio_interrupt(int pin)
176{ 176{
177 struct s3c_gpio_chip *my_chip = s3c_gpiolib_getchip(pin); 177 struct samsung_gpio_chip *my_chip = samsung_gpiolib_getchip(pin);
178 int offset, group; 178 int offset, group;
179 int ret; 179 int ret;
180 180
diff --git a/arch/arm/plat-samsung/Kconfig b/arch/arm/plat-samsung/Kconfig
index b3e10659e4b8..74714c155e14 100644
--- a/arch/arm/plat-samsung/Kconfig
+++ b/arch/arm/plat-samsung/Kconfig
@@ -79,39 +79,12 @@ config SAMSUNG_GPIOLIB_4BIT
79 configuration. GPIOlib shall be compiled only for S3C64XX and S5P 79 configuration. GPIOlib shall be compiled only for S3C64XX and S5P
80 series of processors. 80 series of processors.
81 81
82config S3C_GPIO_CFG_S3C24XX
83 bool
84 help
85 Internal configuration to enable S3C24XX style GPIO configuration
86 functions.
87
88config S3C_GPIO_CFG_S3C64XX 82config S3C_GPIO_CFG_S3C64XX
89 bool 83 bool
90 help 84 help
91 Internal configuration to enable S3C64XX style GPIO configuration 85 Internal configuration to enable S3C64XX style GPIO configuration
92 functions. 86 functions.
93 87
94config S3C_GPIO_PULL_UPDOWN
95 bool
96 help
97 Internal configuration to enable the correct GPIO pull helper
98
99config S3C_GPIO_PULL_S3C2443
100 bool
101 select S3C_GPIO_PULL_UPDOWN
102 help
103 Internal configuration to enable the correct GPIO pull helper for S3C2443-style GPIO
104
105config S3C_GPIO_PULL_DOWN
106 bool
107 help
108 Internal configuration to enable the correct GPIO pull helper
109
110config S3C_GPIO_PULL_UP
111 bool
112 help
113 Internal configuration to enable the correct GPIO pull helper
114
115config S5P_GPIO_DRVSTR 88config S5P_GPIO_DRVSTR
116 bool 89 bool
117 help 90 help
@@ -300,11 +273,14 @@ config S3C_DMA
300 help 273 help
301 Internal configuration for S3C DMA core 274 Internal configuration for S3C DMA core
302 275
303config S3C_PL330_DMA 276config SAMSUNG_DMADEV
304 bool 277 bool
305 select PL330 278 select DMADEVICES
279 select PL330_DMA if (CPU_EXYNOS4210 || CPU_S5PV210 || CPU_S5PC100 || \
280 CPU_S5P6450 || CPU_S5P6440)
281 select ARM_AMBA
306 help 282 help
307 S3C DMA API Driver for PL330 DMAC. 283 Use DMA device engine for PL330 DMAC.
308 284
309comment "Power management" 285comment "Power management"
310 286
diff --git a/arch/arm/plat-samsung/Makefile b/arch/arm/plat-samsung/Makefile
index 3de756da5eaa..5a5435482595 100644
--- a/arch/arm/plat-samsung/Makefile
+++ b/arch/arm/plat-samsung/Makefile
@@ -15,8 +15,6 @@ obj-y += init.o cpu.o
15obj-$(CONFIG_ARCH_USES_GETTIMEOFFSET) += time.o 15obj-$(CONFIG_ARCH_USES_GETTIMEOFFSET) += time.o
16obj-y += clock.o 16obj-y += clock.o
17obj-y += pwm-clock.o 17obj-y += pwm-clock.o
18obj-y += gpio.o
19obj-y += gpio-config.o
20obj-y += dev-asocdma.o 18obj-y += dev-asocdma.o
21 19
22obj-$(CONFIG_SAMSUNG_CLKSRC) += clock-clksrc.o 20obj-$(CONFIG_SAMSUNG_CLKSRC) += clock-clksrc.o
@@ -63,9 +61,9 @@ obj-$(CONFIG_SAMSUNG_DEV_BACKLIGHT) += dev-backlight.o
63 61
64# DMA support 62# DMA support
65 63
66obj-$(CONFIG_S3C_DMA) += dma.o 64obj-$(CONFIG_S3C_DMA) += dma.o s3c-dma-ops.o
67 65
68obj-$(CONFIG_S3C_PL330_DMA) += s3c-pl330.o 66obj-$(CONFIG_SAMSUNG_DMADEV) += dma-ops.o
69 67
70# PM support 68# PM support
71 69
diff --git a/arch/arm/plat-samsung/dma-ops.c b/arch/arm/plat-samsung/dma-ops.c
new file mode 100644
index 000000000000..6e3d9abc9e2e
--- /dev/null
+++ b/arch/arm/plat-samsung/dma-ops.c
@@ -0,0 +1,131 @@
1/* linux/arch/arm/plat-samsung/dma-ops.c
2 *
3 * Copyright (c) 2011 Samsung Electronics Co., Ltd.
4 * http://www.samsung.com
5 *
6 * Samsung DMA Operations
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 */
12
13#include <linux/kernel.h>
14#include <linux/errno.h>
15#include <linux/amba/pl330.h>
16#include <linux/scatterlist.h>
17
18#include <mach/dma.h>
19
20static inline bool pl330_filter(struct dma_chan *chan, void *param)
21{
22 struct dma_pl330_peri *peri = chan->private;
23 return peri->peri_id == (unsigned)param;
24}
25
26static unsigned samsung_dmadev_request(enum dma_ch dma_ch,
27 struct samsung_dma_info *info)
28{
29 struct dma_chan *chan;
30 dma_cap_mask_t mask;
31 struct dma_slave_config slave_config;
32
33 dma_cap_zero(mask);
34 dma_cap_set(info->cap, mask);
35
36 chan = dma_request_channel(mask, pl330_filter, (void *)dma_ch);
37
38 if (info->direction == DMA_FROM_DEVICE) {
39 memset(&slave_config, 0, sizeof(struct dma_slave_config));
40 slave_config.direction = info->direction;
41 slave_config.src_addr = info->fifo;
42 slave_config.src_addr_width = info->width;
43 slave_config.src_maxburst = 1;
44 dmaengine_slave_config(chan, &slave_config);
45 } else if (info->direction == DMA_TO_DEVICE) {
46 memset(&slave_config, 0, sizeof(struct dma_slave_config));
47 slave_config.direction = info->direction;
48 slave_config.dst_addr = info->fifo;
49 slave_config.dst_addr_width = info->width;
50 slave_config.dst_maxburst = 1;
51 dmaengine_slave_config(chan, &slave_config);
52 }
53
54 return (unsigned)chan;
55}
56
57static int samsung_dmadev_release(unsigned ch,
58 struct s3c2410_dma_client *client)
59{
60 dma_release_channel((struct dma_chan *)ch);
61
62 return 0;
63}
64
65static int samsung_dmadev_prepare(unsigned ch,
66 struct samsung_dma_prep_info *info)
67{
68 struct scatterlist sg;
69 struct dma_chan *chan = (struct dma_chan *)ch;
70 struct dma_async_tx_descriptor *desc;
71
72 switch (info->cap) {
73 case DMA_SLAVE:
74 sg_init_table(&sg, 1);
75 sg_dma_len(&sg) = info->len;
76 sg_set_page(&sg, pfn_to_page(PFN_DOWN(info->buf)),
77 info->len, offset_in_page(info->buf));
78 sg_dma_address(&sg) = info->buf;
79
80 desc = chan->device->device_prep_slave_sg(chan,
81 &sg, 1, info->direction, DMA_PREP_INTERRUPT);
82 break;
83 case DMA_CYCLIC:
84 desc = chan->device->device_prep_dma_cyclic(chan,
85 info->buf, info->len, info->period, info->direction);
86 break;
87 default:
88 dev_err(&chan->dev->device, "unsupported format\n");
89 return -EFAULT;
90 }
91
92 if (!desc) {
93 dev_err(&chan->dev->device, "cannot prepare cyclic dma\n");
94 return -EFAULT;
95 }
96
97 desc->callback = info->fp;
98 desc->callback_param = info->fp_param;
99
100 dmaengine_submit((struct dma_async_tx_descriptor *)desc);
101
102 return 0;
103}
104
105static inline int samsung_dmadev_trigger(unsigned ch)
106{
107 dma_async_issue_pending((struct dma_chan *)ch);
108
109 return 0;
110}
111
112static inline int samsung_dmadev_flush(unsigned ch)
113{
114 return dmaengine_terminate_all((struct dma_chan *)ch);
115}
116
117struct samsung_dma_ops dmadev_ops = {
118 .request = samsung_dmadev_request,
119 .release = samsung_dmadev_release,
120 .prepare = samsung_dmadev_prepare,
121 .trigger = samsung_dmadev_trigger,
122 .started = NULL,
123 .flush = samsung_dmadev_flush,
124 .stop = samsung_dmadev_flush,
125};
126
127void *samsung_dmadev_get_ops(void)
128{
129 return &dmadev_ops;
130}
131EXPORT_SYMBOL(samsung_dmadev_get_ops);
diff --git a/arch/arm/plat-samsung/gpio-config.c b/arch/arm/plat-samsung/gpio-config.c
deleted file mode 100644
index 1c0b0401594b..000000000000
--- a/arch/arm/plat-samsung/gpio-config.c
+++ /dev/null
@@ -1,431 +0,0 @@
1/* linux/arch/arm/plat-s3c/gpio-config.c
2 *
3 * Copyright 2008 Openmoko, Inc.
4 * Copyright 2008-2010 Simtec Electronics
5 * Ben Dooks <ben@simtec.co.uk>
6 * http://armlinux.simtec.co.uk/
7 *
8 * S3C series GPIO configuration core
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
13*/
14
15#include <linux/kernel.h>
16#include <linux/module.h>
17#include <linux/gpio.h>
18#include <linux/io.h>
19
20#include <plat/gpio-core.h>
21#include <plat/gpio-cfg.h>
22#include <plat/gpio-cfg-helpers.h>
23
24int s3c_gpio_cfgpin(unsigned int pin, unsigned int config)
25{
26 struct s3c_gpio_chip *chip = s3c_gpiolib_getchip(pin);
27 unsigned long flags;
28 int offset;
29 int ret;
30
31 if (!chip)
32 return -EINVAL;
33
34 offset = pin - chip->chip.base;
35
36 s3c_gpio_lock(chip, flags);
37 ret = s3c_gpio_do_setcfg(chip, offset, config);
38 s3c_gpio_unlock(chip, flags);
39
40 return ret;
41}
42EXPORT_SYMBOL(s3c_gpio_cfgpin);
43
44int s3c_gpio_cfgpin_range(unsigned int start, unsigned int nr,
45 unsigned int cfg)
46{
47 int ret;
48
49 for (; nr > 0; nr--, start++) {
50 ret = s3c_gpio_cfgpin(start, cfg);
51 if (ret != 0)
52 return ret;
53 }
54
55 return 0;
56}
57EXPORT_SYMBOL_GPL(s3c_gpio_cfgpin_range);
58
59int s3c_gpio_cfgall_range(unsigned int start, unsigned int nr,
60 unsigned int cfg, s3c_gpio_pull_t pull)
61{
62 int ret;
63
64 for (; nr > 0; nr--, start++) {
65 s3c_gpio_setpull(start, pull);
66 ret = s3c_gpio_cfgpin(start, cfg);
67 if (ret != 0)
68 return ret;
69 }
70
71 return 0;
72}
73EXPORT_SYMBOL_GPL(s3c_gpio_cfgall_range);
74
75unsigned s3c_gpio_getcfg(unsigned int pin)
76{
77 struct s3c_gpio_chip *chip = s3c_gpiolib_getchip(pin);
78 unsigned long flags;
79 unsigned ret = 0;
80 int offset;
81
82 if (chip) {
83 offset = pin - chip->chip.base;
84
85 s3c_gpio_lock(chip, flags);
86 ret = s3c_gpio_do_getcfg(chip, offset);
87 s3c_gpio_unlock(chip, flags);
88 }
89
90 return ret;
91}
92EXPORT_SYMBOL(s3c_gpio_getcfg);
93
94
95int s3c_gpio_setpull(unsigned int pin, s3c_gpio_pull_t pull)
96{
97 struct s3c_gpio_chip *chip = s3c_gpiolib_getchip(pin);
98 unsigned long flags;
99 int offset, ret;
100
101 if (!chip)
102 return -EINVAL;
103
104 offset = pin - chip->chip.base;
105
106 s3c_gpio_lock(chip, flags);
107 ret = s3c_gpio_do_setpull(chip, offset, pull);
108 s3c_gpio_unlock(chip, flags);
109
110 return ret;
111}
112EXPORT_SYMBOL(s3c_gpio_setpull);
113
114s3c_gpio_pull_t s3c_gpio_getpull(unsigned int pin)
115{
116 struct s3c_gpio_chip *chip = s3c_gpiolib_getchip(pin);
117 unsigned long flags;
118 int offset;
119 u32 pup = 0;
120
121 if (chip) {
122 offset = pin - chip->chip.base;
123
124 s3c_gpio_lock(chip, flags);
125 pup = s3c_gpio_do_getpull(chip, offset);
126 s3c_gpio_unlock(chip, flags);
127 }
128
129 return (__force s3c_gpio_pull_t)pup;
130}
131EXPORT_SYMBOL(s3c_gpio_getpull);
132
133#ifdef CONFIG_S3C_GPIO_CFG_S3C24XX
134int s3c_gpio_setcfg_s3c24xx_a(struct s3c_gpio_chip *chip,
135 unsigned int off, unsigned int cfg)
136{
137 void __iomem *reg = chip->base;
138 unsigned int shift = off;
139 u32 con;
140
141 if (s3c_gpio_is_cfg_special(cfg)) {
142 cfg &= 0xf;
143
144 /* Map output to 0, and SFN2 to 1 */
145 cfg -= 1;
146 if (cfg > 1)
147 return -EINVAL;
148
149 cfg <<= shift;
150 }
151
152 con = __raw_readl(reg);
153 con &= ~(0x1 << shift);
154 con |= cfg;
155 __raw_writel(con, reg);
156
157 return 0;
158}
159
160unsigned s3c_gpio_getcfg_s3c24xx_a(struct s3c_gpio_chip *chip,
161 unsigned int off)
162{
163 u32 con;
164
165 con = __raw_readl(chip->base);
166 con >>= off;
167 con &= 1;
168 con++;
169
170 return S3C_GPIO_SFN(con);
171}
172
173int s3c_gpio_setcfg_s3c24xx(struct s3c_gpio_chip *chip,
174 unsigned int off, unsigned int cfg)
175{
176 void __iomem *reg = chip->base;
177 unsigned int shift = off * 2;
178 u32 con;
179
180 if (s3c_gpio_is_cfg_special(cfg)) {
181 cfg &= 0xf;
182 if (cfg > 3)
183 return -EINVAL;
184
185 cfg <<= shift;
186 }
187
188 con = __raw_readl(reg);
189 con &= ~(0x3 << shift);
190 con |= cfg;
191 __raw_writel(con, reg);
192
193 return 0;
194}
195
196unsigned int s3c_gpio_getcfg_s3c24xx(struct s3c_gpio_chip *chip,
197 unsigned int off)
198{
199 u32 con;
200
201 con = __raw_readl(chip->base);
202 con >>= off * 2;
203 con &= 3;
204
205 /* this conversion works for IN and OUT as well as special mode */
206 return S3C_GPIO_SPECIAL(con);
207}
208#endif
209
210#ifdef CONFIG_S3C_GPIO_CFG_S3C64XX
211int s3c_gpio_setcfg_s3c64xx_4bit(struct s3c_gpio_chip *chip,
212 unsigned int off, unsigned int cfg)
213{
214 void __iomem *reg = chip->base;
215 unsigned int shift = (off & 7) * 4;
216 u32 con;
217
218 if (off < 8 && chip->chip.ngpio > 8)
219 reg -= 4;
220
221 if (s3c_gpio_is_cfg_special(cfg)) {
222 cfg &= 0xf;
223 cfg <<= shift;
224 }
225
226 con = __raw_readl(reg);
227 con &= ~(0xf << shift);
228 con |= cfg;
229 __raw_writel(con, reg);
230
231 return 0;
232}
233
234unsigned s3c_gpio_getcfg_s3c64xx_4bit(struct s3c_gpio_chip *chip,
235 unsigned int off)
236{
237 void __iomem *reg = chip->base;
238 unsigned int shift = (off & 7) * 4;
239 u32 con;
240
241 if (off < 8 && chip->chip.ngpio > 8)
242 reg -= 4;
243
244 con = __raw_readl(reg);
245 con >>= shift;
246 con &= 0xf;
247
248 /* this conversion works for IN and OUT as well as special mode */
249 return S3C_GPIO_SPECIAL(con);
250}
251
252#endif /* CONFIG_S3C_GPIO_CFG_S3C64XX */
253
254#ifdef CONFIG_S3C_GPIO_PULL_UPDOWN
255int s3c_gpio_setpull_updown(struct s3c_gpio_chip *chip,
256 unsigned int off, s3c_gpio_pull_t pull)
257{
258 void __iomem *reg = chip->base + 0x08;
259 int shift = off * 2;
260 u32 pup;
261
262 pup = __raw_readl(reg);
263 pup &= ~(3 << shift);
264 pup |= pull << shift;
265 __raw_writel(pup, reg);
266
267 return 0;
268}
269
270s3c_gpio_pull_t s3c_gpio_getpull_updown(struct s3c_gpio_chip *chip,
271 unsigned int off)
272{
273 void __iomem *reg = chip->base + 0x08;
274 int shift = off * 2;
275 u32 pup = __raw_readl(reg);
276
277 pup >>= shift;
278 pup &= 0x3;
279 return (__force s3c_gpio_pull_t)pup;
280}
281
282#ifdef CONFIG_S3C_GPIO_PULL_S3C2443
283int s3c_gpio_setpull_s3c2443(struct s3c_gpio_chip *chip,
284 unsigned int off, s3c_gpio_pull_t pull)
285{
286 switch (pull) {
287 case S3C_GPIO_PULL_NONE:
288 pull = 0x01;
289 break;
290 case S3C_GPIO_PULL_UP:
291 pull = 0x00;
292 break;
293 case S3C_GPIO_PULL_DOWN:
294 pull = 0x02;
295 break;
296 }
297 return s3c_gpio_setpull_updown(chip, off, pull);
298}
299
300s3c_gpio_pull_t s3c_gpio_getpull_s3c2443(struct s3c_gpio_chip *chip,
301 unsigned int off)
302{
303 s3c_gpio_pull_t pull;
304
305 pull = s3c_gpio_getpull_updown(chip, off);
306
307 switch (pull) {
308 case 0x00:
309 pull = S3C_GPIO_PULL_UP;
310 break;
311 case 0x01:
312 case 0x03:
313 pull = S3C_GPIO_PULL_NONE;
314 break;
315 case 0x02:
316 pull = S3C_GPIO_PULL_DOWN;
317 break;
318 }
319
320 return pull;
321}
322#endif
323#endif
324
325#if defined(CONFIG_S3C_GPIO_PULL_UP) || defined(CONFIG_S3C_GPIO_PULL_DOWN)
326static int s3c_gpio_setpull_1(struct s3c_gpio_chip *chip,
327 unsigned int off, s3c_gpio_pull_t pull,
328 s3c_gpio_pull_t updown)
329{
330 void __iomem *reg = chip->base + 0x08;
331 u32 pup = __raw_readl(reg);
332
333 if (pull == updown)
334 pup &= ~(1 << off);
335 else if (pull == S3C_GPIO_PULL_NONE)
336 pup |= (1 << off);
337 else
338 return -EINVAL;
339
340 __raw_writel(pup, reg);
341 return 0;
342}
343
344static s3c_gpio_pull_t s3c_gpio_getpull_1(struct s3c_gpio_chip *chip,
345 unsigned int off, s3c_gpio_pull_t updown)
346{
347 void __iomem *reg = chip->base + 0x08;
348 u32 pup = __raw_readl(reg);
349
350 pup &= (1 << off);
351 return pup ? S3C_GPIO_PULL_NONE : updown;
352}
353#endif /* CONFIG_S3C_GPIO_PULL_UP || CONFIG_S3C_GPIO_PULL_DOWN */
354
355#ifdef CONFIG_S3C_GPIO_PULL_UP
356s3c_gpio_pull_t s3c_gpio_getpull_1up(struct s3c_gpio_chip *chip,
357 unsigned int off)
358{
359 return s3c_gpio_getpull_1(chip, off, S3C_GPIO_PULL_UP);
360}
361
362int s3c_gpio_setpull_1up(struct s3c_gpio_chip *chip,
363 unsigned int off, s3c_gpio_pull_t pull)
364{
365 return s3c_gpio_setpull_1(chip, off, pull, S3C_GPIO_PULL_UP);
366}
367#endif /* CONFIG_S3C_GPIO_PULL_UP */
368
369#ifdef CONFIG_S3C_GPIO_PULL_DOWN
370s3c_gpio_pull_t s3c_gpio_getpull_1down(struct s3c_gpio_chip *chip,
371 unsigned int off)
372{
373 return s3c_gpio_getpull_1(chip, off, S3C_GPIO_PULL_DOWN);
374}
375
376int s3c_gpio_setpull_1down(struct s3c_gpio_chip *chip,
377 unsigned int off, s3c_gpio_pull_t pull)
378{
379 return s3c_gpio_setpull_1(chip, off, pull, S3C_GPIO_PULL_DOWN);
380}
381#endif /* CONFIG_S3C_GPIO_PULL_DOWN */
382
383#ifdef CONFIG_S5P_GPIO_DRVSTR
384s5p_gpio_drvstr_t s5p_gpio_get_drvstr(unsigned int pin)
385{
386 struct s3c_gpio_chip *chip = s3c_gpiolib_getchip(pin);
387 unsigned int off;
388 void __iomem *reg;
389 int shift;
390 u32 drvstr;
391
392 if (!chip)
393 return -EINVAL;
394
395 off = pin - chip->chip.base;
396 shift = off * 2;
397 reg = chip->base + 0x0C;
398
399 drvstr = __raw_readl(reg);
400 drvstr = drvstr >> shift;
401 drvstr &= 0x3;
402
403 return (__force s5p_gpio_drvstr_t)drvstr;
404}
405EXPORT_SYMBOL(s5p_gpio_get_drvstr);
406
407int s5p_gpio_set_drvstr(unsigned int pin, s5p_gpio_drvstr_t drvstr)
408{
409 struct s3c_gpio_chip *chip = s3c_gpiolib_getchip(pin);
410 unsigned int off;
411 void __iomem *reg;
412 int shift;
413 u32 tmp;
414
415 if (!chip)
416 return -EINVAL;
417
418 off = pin - chip->chip.base;
419 shift = off * 2;
420 reg = chip->base + 0x0C;
421
422 tmp = __raw_readl(reg);
423 tmp &= ~(0x3 << shift);
424 tmp |= drvstr << shift;
425
426 __raw_writel(tmp, reg);
427
428 return 0;
429}
430EXPORT_SYMBOL(s5p_gpio_set_drvstr);
431#endif /* CONFIG_S5P_GPIO_DRVSTR */
diff --git a/arch/arm/plat-samsung/gpio.c b/arch/arm/plat-samsung/gpio.c
deleted file mode 100644
index 7743c4b8b2fb..000000000000
--- a/arch/arm/plat-samsung/gpio.c
+++ /dev/null
@@ -1,167 +0,0 @@
1/* linux/arch/arm/plat-s3c/gpio.c
2 *
3 * Copyright 2008 Simtec Electronics
4 * Ben Dooks <ben@simtec.co.uk>
5 * http://armlinux.simtec.co.uk/
6 *
7 * S3C series GPIO core
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
12*/
13
14#include <linux/kernel.h>
15#include <linux/init.h>
16#include <linux/io.h>
17#include <linux/gpio.h>
18#include <linux/spinlock.h>
19
20#include <plat/gpio-core.h>
21
22#ifdef CONFIG_S3C_GPIO_TRACK
23struct s3c_gpio_chip *s3c_gpios[S3C_GPIO_END];
24
25static __init void s3c_gpiolib_track(struct s3c_gpio_chip *chip)
26{
27 unsigned int gpn;
28 int i;
29
30 gpn = chip->chip.base;
31 for (i = 0; i < chip->chip.ngpio; i++, gpn++) {
32 BUG_ON(gpn >= ARRAY_SIZE(s3c_gpios));
33 s3c_gpios[gpn] = chip;
34 }
35}
36#endif /* CONFIG_S3C_GPIO_TRACK */
37
38/* Default routines for controlling GPIO, based on the original S3C24XX
39 * GPIO functions which deal with the case where each gpio bank of the
40 * chip is as following:
41 *
42 * base + 0x00: Control register, 2 bits per gpio
43 * gpio n: 2 bits starting at (2*n)
44 * 00 = input, 01 = output, others mean special-function
45 * base + 0x04: Data register, 1 bit per gpio
46 * bit n: data bit n
47*/
48
49static int s3c_gpiolib_input(struct gpio_chip *chip, unsigned offset)
50{
51 struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
52 void __iomem *base = ourchip->base;
53 unsigned long flags;
54 unsigned long con;
55
56 s3c_gpio_lock(ourchip, flags);
57
58 con = __raw_readl(base + 0x00);
59 con &= ~(3 << (offset * 2));
60
61 __raw_writel(con, base + 0x00);
62
63 s3c_gpio_unlock(ourchip, flags);
64 return 0;
65}
66
67static int s3c_gpiolib_output(struct gpio_chip *chip,
68 unsigned offset, int value)
69{
70 struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
71 void __iomem *base = ourchip->base;
72 unsigned long flags;
73 unsigned long dat;
74 unsigned long con;
75
76 s3c_gpio_lock(ourchip, flags);
77
78 dat = __raw_readl(base + 0x04);
79 dat &= ~(1 << offset);
80 if (value)
81 dat |= 1 << offset;
82 __raw_writel(dat, base + 0x04);
83
84 con = __raw_readl(base + 0x00);
85 con &= ~(3 << (offset * 2));
86 con |= 1 << (offset * 2);
87
88 __raw_writel(con, base + 0x00);
89 __raw_writel(dat, base + 0x04);
90
91 s3c_gpio_unlock(ourchip, flags);
92 return 0;
93}
94
95static void s3c_gpiolib_set(struct gpio_chip *chip,
96 unsigned offset, int value)
97{
98 struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
99 void __iomem *base = ourchip->base;
100 unsigned long flags;
101 unsigned long dat;
102
103 s3c_gpio_lock(ourchip, flags);
104
105 dat = __raw_readl(base + 0x04);
106 dat &= ~(1 << offset);
107 if (value)
108 dat |= 1 << offset;
109 __raw_writel(dat, base + 0x04);
110
111 s3c_gpio_unlock(ourchip, flags);
112}
113
114static int s3c_gpiolib_get(struct gpio_chip *chip, unsigned offset)
115{
116 struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
117 unsigned long val;
118
119 val = __raw_readl(ourchip->base + 0x04);
120 val >>= offset;
121 val &= 1;
122
123 return val;
124}
125
126__init void s3c_gpiolib_add(struct s3c_gpio_chip *chip)
127{
128 struct gpio_chip *gc = &chip->chip;
129 int ret;
130
131 BUG_ON(!chip->base);
132 BUG_ON(!gc->label);
133 BUG_ON(!gc->ngpio);
134
135 spin_lock_init(&chip->lock);
136
137 if (!gc->direction_input)
138 gc->direction_input = s3c_gpiolib_input;
139 if (!gc->direction_output)
140 gc->direction_output = s3c_gpiolib_output;
141 if (!gc->set)
142 gc->set = s3c_gpiolib_set;
143 if (!gc->get)
144 gc->get = s3c_gpiolib_get;
145
146#ifdef CONFIG_PM
147 if (chip->pm != NULL) {
148 if (!chip->pm->save || !chip->pm->resume)
149 printk(KERN_ERR "gpio: %s has missing PM functions\n",
150 gc->label);
151 } else
152 printk(KERN_ERR "gpio: %s has no PM function\n", gc->label);
153#endif
154
155 /* gpiochip_add() prints own failure message on error. */
156 ret = gpiochip_add(gc);
157 if (ret >= 0)
158 s3c_gpiolib_track(chip);
159}
160
161int samsung_gpiolib_to_irq(struct gpio_chip *chip, unsigned int offset)
162{
163 struct s3c_gpio_chip *s3c_chip = container_of(chip,
164 struct s3c_gpio_chip, chip);
165
166 return s3c_chip->irq_base + offset;
167}
diff --git a/arch/arm/plat-samsung/include/plat/devs.h b/arch/arm/plat-samsung/include/plat/devs.h
index 24ebb1e1de41..ee5014a7cc96 100644
--- a/arch/arm/plat-samsung/include/plat/devs.h
+++ b/arch/arm/plat-samsung/include/plat/devs.h
@@ -62,6 +62,7 @@ extern struct platform_device s3c_device_i2c4;
62extern struct platform_device s3c_device_i2c5; 62extern struct platform_device s3c_device_i2c5;
63extern struct platform_device s3c_device_i2c6; 63extern struct platform_device s3c_device_i2c6;
64extern struct platform_device s3c_device_i2c7; 64extern struct platform_device s3c_device_i2c7;
65extern struct platform_device s5p_device_i2c_hdmiphy;
65extern struct platform_device s3c_device_rtc; 66extern struct platform_device s3c_device_rtc;
66extern struct platform_device s3c_device_adc; 67extern struct platform_device s3c_device_adc;
67extern struct platform_device s3c_device_sdi; 68extern struct platform_device s3c_device_sdi;
@@ -142,6 +143,11 @@ extern struct platform_device s5p_device_fimc3;
142extern struct platform_device s5p_device_mfc; 143extern struct platform_device s5p_device_mfc;
143extern struct platform_device s5p_device_mfc_l; 144extern struct platform_device s5p_device_mfc_l;
144extern struct platform_device s5p_device_mfc_r; 145extern struct platform_device s5p_device_mfc_r;
146
147extern struct platform_device s5p_device_hdmi;
148extern struct platform_device s5p_device_mixer;
149extern struct platform_device s5p_device_sdo;
150
145extern struct platform_device s5p_device_mipi_csis0; 151extern struct platform_device s5p_device_mipi_csis0;
146extern struct platform_device s5p_device_mipi_csis1; 152extern struct platform_device s5p_device_mipi_csis1;
147 153
diff --git a/arch/arm/plat-samsung/include/plat/dma-ops.h b/arch/arm/plat-samsung/include/plat/dma-ops.h
new file mode 100644
index 000000000000..4c1a363526cf
--- /dev/null
+++ b/arch/arm/plat-samsung/include/plat/dma-ops.h
@@ -0,0 +1,63 @@
1/* arch/arm/plat-samsung/include/plat/dma-ops.h
2 *
3 * Copyright (c) 2011 Samsung Electronics Co., Ltd.
4 * http://www.samsung.com
5 *
6 * Samsung DMA support
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 */
12
13#ifndef __SAMSUNG_DMA_OPS_H_
14#define __SAMSUNG_DMA_OPS_H_ __FILE__
15
16#include <linux/dmaengine.h>
17
18struct samsung_dma_prep_info {
19 enum dma_transaction_type cap;
20 enum dma_data_direction direction;
21 dma_addr_t buf;
22 unsigned long period;
23 unsigned long len;
24 void (*fp)(void *data);
25 void *fp_param;
26};
27
28struct samsung_dma_info {
29 enum dma_transaction_type cap;
30 enum dma_data_direction direction;
31 enum dma_slave_buswidth width;
32 dma_addr_t fifo;
33 struct s3c2410_dma_client *client;
34};
35
36struct samsung_dma_ops {
37 unsigned (*request)(enum dma_ch ch, struct samsung_dma_info *info);
38 int (*release)(unsigned ch, struct s3c2410_dma_client *client);
39 int (*prepare)(unsigned ch, struct samsung_dma_prep_info *info);
40 int (*trigger)(unsigned ch);
41 int (*started)(unsigned ch);
42 int (*flush)(unsigned ch);
43 int (*stop)(unsigned ch);
44};
45
46extern void *samsung_dmadev_get_ops(void);
47extern void *s3c_dma_get_ops(void);
48
49static inline void *__samsung_dma_get_ops(void)
50{
51 if (samsung_dma_is_dmadev())
52 return samsung_dmadev_get_ops();
53 else
54 return s3c_dma_get_ops();
55}
56
57/*
58 * samsung_dma_get_ops
59 * get the set of samsung dma operations
60 */
61#define samsung_dma_get_ops() __samsung_dma_get_ops()
62
63#endif /* __SAMSUNG_DMA_OPS_H_ */
diff --git a/arch/arm/plat-samsung/include/plat/s3c-dma-pl330.h b/arch/arm/plat-samsung/include/plat/dma-pl330.h
index 810744213120..2e55e5958674 100644
--- a/arch/arm/plat-samsung/include/plat/s3c-dma-pl330.h
+++ b/arch/arm/plat-samsung/include/plat/dma-pl330.h
@@ -8,11 +8,8 @@
8 * (at your option) any later version. 8 * (at your option) any later version.
9 */ 9 */
10 10
11#ifndef __S3C_DMA_PL330_H_ 11#ifndef __DMA_PL330_H_
12#define __S3C_DMA_PL330_H_ 12#define __DMA_PL330_H_ __FILE__
13
14#define S3C2410_DMAF_AUTOSTART (1 << 0)
15#define S3C2410_DMAF_CIRCULAR (1 << 1)
16 13
17/* 14/*
18 * PL330 can assign any channel to communicate with 15 * PL330 can assign any channel to communicate with
@@ -20,7 +17,7 @@
20 * For the sake of consistency across client drivers, 17 * For the sake of consistency across client drivers,
21 * We keep the channel names unchanged and only add 18 * We keep the channel names unchanged and only add
22 * missing peripherals are added. 19 * missing peripherals are added.
23 * Order is not important since S3C PL330 API driver 20 * Order is not important since DMA PL330 API driver
24 * use these just as IDs. 21 * use these just as IDs.
25 */ 22 */
26enum dma_ch { 23enum dma_ch {
@@ -88,11 +85,20 @@ enum dma_ch {
88 DMACH_MAX, 85 DMACH_MAX,
89}; 86};
90 87
91static inline bool s3c_dma_has_circular(void) 88struct s3c2410_dma_client {
89 char *name;
90};
91
92static inline bool samsung_dma_has_circular(void)
93{
94 return true;
95}
96
97static inline bool samsung_dma_is_dmadev(void)
92{ 98{
93 return true; 99 return true;
94} 100}
95 101
96#include <plat/dma.h> 102#include <plat/dma-ops.h>
97 103
98#endif /* __S3C_DMA_PL330_H_ */ 104#endif /* __DMA_PL330_H_ */
diff --git a/arch/arm/plat-samsung/include/plat/dma-s3c24xx.h b/arch/arm/plat-samsung/include/plat/dma-s3c24xx.h
index ab9bce637cbd..1c1ed5481253 100644
--- a/arch/arm/plat-samsung/include/plat/dma-s3c24xx.h
+++ b/arch/arm/plat-samsung/include/plat/dma-s3c24xx.h
@@ -41,7 +41,7 @@ struct s3c24xx_dma_selection {
41 41
42 void (*direction)(struct s3c2410_dma_chan *chan, 42 void (*direction)(struct s3c2410_dma_chan *chan,
43 struct s3c24xx_dma_map *map, 43 struct s3c24xx_dma_map *map,
44 enum s3c2410_dmasrc dir); 44 enum dma_data_direction dir);
45}; 45};
46 46
47extern int s3c24xx_dma_init_map(struct s3c24xx_dma_selection *sel); 47extern int s3c24xx_dma_init_map(struct s3c24xx_dma_selection *sel);
diff --git a/arch/arm/plat-samsung/include/plat/dma.h b/arch/arm/plat-samsung/include/plat/dma.h
index 8c273b7a6f56..b9061128abde 100644
--- a/arch/arm/plat-samsung/include/plat/dma.h
+++ b/arch/arm/plat-samsung/include/plat/dma.h
@@ -10,17 +10,14 @@
10 * published by the Free Software Foundation. 10 * published by the Free Software Foundation.
11*/ 11*/
12 12
13#include <linux/dma-mapping.h>
14
13enum s3c2410_dma_buffresult { 15enum s3c2410_dma_buffresult {
14 S3C2410_RES_OK, 16 S3C2410_RES_OK,
15 S3C2410_RES_ERR, 17 S3C2410_RES_ERR,
16 S3C2410_RES_ABORT 18 S3C2410_RES_ABORT
17}; 19};
18 20
19enum s3c2410_dmasrc {
20 S3C2410_DMASRC_HW, /* source is memory */
21 S3C2410_DMASRC_MEM /* source is hardware */
22};
23
24/* enum s3c2410_chan_op 21/* enum s3c2410_chan_op
25 * 22 *
26 * operation codes passed to the DMA code by the user, and also used 23 * operation codes passed to the DMA code by the user, and also used
@@ -112,7 +109,7 @@ extern int s3c2410_dma_config(enum dma_ch channel, int xferunit);
112*/ 109*/
113 110
114extern int s3c2410_dma_devconfig(enum dma_ch channel, 111extern int s3c2410_dma_devconfig(enum dma_ch channel,
115 enum s3c2410_dmasrc source, unsigned long devaddr); 112 enum dma_data_direction source, unsigned long devaddr);
116 113
117/* s3c2410_dma_getposition 114/* s3c2410_dma_getposition
118 * 115 *
@@ -126,3 +123,4 @@ extern int s3c2410_dma_set_opfn(enum dma_ch, s3c2410_dma_opfn_t rtn);
126extern int s3c2410_dma_set_buffdone_fn(enum dma_ch, s3c2410_dma_cbfn_t rtn); 123extern int s3c2410_dma_set_buffdone_fn(enum dma_ch, s3c2410_dma_cbfn_t rtn);
127 124
128 125
126#include <plat/dma-ops.h>
diff --git a/arch/arm/plat-samsung/include/plat/fb.h b/arch/arm/plat-samsung/include/plat/fb.h
index 01f10e4d00c7..0fedf47fa502 100644
--- a/arch/arm/plat-samsung/include/plat/fb.h
+++ b/arch/arm/plat-samsung/include/plat/fb.h
@@ -109,4 +109,11 @@ extern void s5pv210_fb_gpio_setup_24bpp(void);
109 */ 109 */
110extern void exynos4_fimd0_gpio_setup_24bpp(void); 110extern void exynos4_fimd0_gpio_setup_24bpp(void);
111 111
112/**
113 * s5p64x0_fb_gpio_setup_24bpp() - S5P6440/S5P6450 setup function for 24bpp LCD
114 *
115 * Initialise the GPIO for an 24bpp LCD display on the RGB interface.
116 */
117extern void s5p64x0_fb_gpio_setup_24bpp(void);
118
112#endif /* __PLAT_S3C_FB_H */ 119#endif /* __PLAT_S3C_FB_H */
diff --git a/arch/arm/plat-samsung/include/plat/gpio-cfg-helpers.h b/arch/arm/plat-samsung/include/plat/gpio-cfg-helpers.h
index 9a4e53d52967..a181d7ce81cf 100644
--- a/arch/arm/plat-samsung/include/plat/gpio-cfg-helpers.h
+++ b/arch/arm/plat-samsung/include/plat/gpio-cfg-helpers.h
@@ -1,11 +1,11 @@
1/* linux/arch/arm/plat-s3c/include/plat/gpio-cfg-helper.h 1/* linux/arch/arm/plat-samsung/include/plat/gpio-cfg-helper.h
2 * 2 *
3 * Copyright 2008 Openmoko, Inc. 3 * Copyright 2008 Openmoko, Inc.
4 * Copyright 2008 Simtec Electronics 4 * Copyright 2008 Simtec Electronics
5 * http://armlinux.simtec.co.uk/ 5 * http://armlinux.simtec.co.uk/
6 * Ben Dooks <ben@simtec.co.uk> 6 * Ben Dooks <ben@simtec.co.uk>
7 * 7 *
8 * S3C Platform - GPIO pin configuration helper definitions 8 * Samsung Platform - GPIO pin configuration helper definitions
9 * 9 *
10 * This program is free software; you can redistribute it and/or modify 10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as 11 * it under the terms of the GNU General Public License version 2 as
@@ -24,120 +24,30 @@
24 * by disabling interrupts. 24 * by disabling interrupts.
25*/ 25*/
26 26
27static inline int s3c_gpio_do_setcfg(struct s3c_gpio_chip *chip, 27static inline int samsung_gpio_do_setcfg(struct samsung_gpio_chip *chip,
28 unsigned int off, unsigned int config) 28 unsigned int off, unsigned int config)
29{ 29{
30 return (chip->config->set_config)(chip, off, config); 30 return (chip->config->set_config)(chip, off, config);
31} 31}
32 32
33static inline unsigned s3c_gpio_do_getcfg(struct s3c_gpio_chip *chip, 33static inline unsigned samsung_gpio_do_getcfg(struct samsung_gpio_chip *chip,
34 unsigned int off) 34 unsigned int off)
35{ 35{
36 return (chip->config->get_config)(chip, off); 36 return (chip->config->get_config)(chip, off);
37} 37}
38 38
39static inline int s3c_gpio_do_setpull(struct s3c_gpio_chip *chip, 39static inline int samsung_gpio_do_setpull(struct samsung_gpio_chip *chip,
40 unsigned int off, s3c_gpio_pull_t pull) 40 unsigned int off, samsung_gpio_pull_t pull)
41{ 41{
42 return (chip->config->set_pull)(chip, off, pull); 42 return (chip->config->set_pull)(chip, off, pull);
43} 43}
44 44
45static inline s3c_gpio_pull_t s3c_gpio_do_getpull(struct s3c_gpio_chip *chip, 45static inline samsung_gpio_pull_t samsung_gpio_do_getpull(struct samsung_gpio_chip *chip,
46 unsigned int off) 46 unsigned int off)
47{ 47{
48 return chip->config->get_pull(chip, off); 48 return chip->config->get_pull(chip, off);
49} 49}
50 50
51/**
52 * s3c_gpio_setcfg_s3c24xx - S3C24XX style GPIO configuration.
53 * @chip: The gpio chip that is being configured.
54 * @off: The offset for the GPIO being configured.
55 * @cfg: The configuration value to set.
56 *
57 * This helper deal with the GPIO cases where the control register
58 * has two bits of configuration per gpio, which have the following
59 * functions:
60 * 00 = input
61 * 01 = output
62 * 1x = special function
63*/
64extern int s3c_gpio_setcfg_s3c24xx(struct s3c_gpio_chip *chip,
65 unsigned int off, unsigned int cfg);
66
67/**
68 * s3c_gpio_getcfg_s3c24xx - S3C24XX style GPIO configuration read.
69 * @chip: The gpio chip that is being configured.
70 * @off: The offset for the GPIO being configured.
71 *
72 * The reverse of s3c_gpio_setcfg_s3c24xx(). Will return a value whicg
73 * could be directly passed back to s3c_gpio_setcfg_s3c24xx(), from the
74 * S3C_GPIO_SPECIAL() macro.
75 */
76unsigned int s3c_gpio_getcfg_s3c24xx(struct s3c_gpio_chip *chip,
77 unsigned int off);
78
79/**
80 * s3c_gpio_setcfg_s3c24xx_a - S3C24XX style GPIO configuration (Bank A)
81 * @chip: The gpio chip that is being configured.
82 * @off: The offset for the GPIO being configured.
83 * @cfg: The configuration value to set.
84 *
85 * This helper deal with the GPIO cases where the control register
86 * has one bit of configuration for the gpio, where setting the bit
87 * means the pin is in special function mode and unset means output.
88*/
89extern int s3c_gpio_setcfg_s3c24xx_a(struct s3c_gpio_chip *chip,
90 unsigned int off, unsigned int cfg);
91
92
93/**
94 * s3c_gpio_getcfg_s3c24xx_a - S3C24XX style GPIO configuration read (Bank A)
95 * @chip: The gpio chip that is being configured.
96 * @off: The offset for the GPIO being configured.
97 *
98 * The reverse of s3c_gpio_setcfg_s3c24xx_a() turning an GPIO into a usable
99 * GPIO configuration value.
100 *
101 * @sa s3c_gpio_getcfg_s3c24xx
102 * @sa s3c_gpio_getcfg_s3c64xx_4bit
103 */
104extern unsigned s3c_gpio_getcfg_s3c24xx_a(struct s3c_gpio_chip *chip,
105 unsigned int off);
106
107/**
108 * s3c_gpio_setcfg_s3c64xx_4bit - S3C64XX 4bit single register GPIO config.
109 * @chip: The gpio chip that is being configured.
110 * @off: The offset for the GPIO being configured.
111 * @cfg: The configuration value to set.
112 *
113 * This helper deal with the GPIO cases where the control register has 4 bits
114 * of control per GPIO, generally in the form of:
115 * 0000 = Input
116 * 0001 = Output
117 * others = Special functions (dependent on bank)
118 *
119 * Note, since the code to deal with the case where there are two control
120 * registers instead of one, we do not have a separate set of functions for
121 * each case.
122*/
123extern int s3c_gpio_setcfg_s3c64xx_4bit(struct s3c_gpio_chip *chip,
124 unsigned int off, unsigned int cfg);
125
126
127/**
128 * s3c_gpio_getcfg_s3c64xx_4bit - S3C64XX 4bit single register GPIO config read.
129 * @chip: The gpio chip that is being configured.
130 * @off: The offset for the GPIO being configured.
131 *
132 * The reverse of s3c_gpio_setcfg_s3c64xx_4bit(), turning a gpio configuration
133 * register setting into a value the software can use, such as could be passed
134 * to s3c_gpio_setcfg_s3c64xx_4bit().
135 *
136 * @sa s3c_gpio_getcfg_s3c24xx
137 */
138extern unsigned s3c_gpio_getcfg_s3c64xx_4bit(struct s3c_gpio_chip *chip,
139 unsigned int off);
140
141/* Pull-{up,down} resistor controls. 51/* Pull-{up,down} resistor controls.
142 * 52 *
143 * S3C2410,S3C2440 = Pull-UP, 53 * S3C2410,S3C2440 = Pull-UP,
@@ -147,7 +57,7 @@ extern unsigned s3c_gpio_getcfg_s3c64xx_4bit(struct s3c_gpio_chip *chip,
147 */ 57 */
148 58
149/** 59/**
150 * s3c_gpio_setpull_1up() - Pull configuration for choice of up or none. 60 * s3c24xx_gpio_setpull_1up() - Pull configuration for choice of up or none.
151 * @chip: The gpio chip that is being configured. 61 * @chip: The gpio chip that is being configured.
152 * @off: The offset for the GPIO being configured. 62 * @off: The offset for the GPIO being configured.
153 * @param: pull: The pull mode being requested. 63 * @param: pull: The pull mode being requested.
@@ -155,11 +65,11 @@ extern unsigned s3c_gpio_getcfg_s3c64xx_4bit(struct s3c_gpio_chip *chip,
155 * This is a helper function for the case where we have GPIOs with one 65 * This is a helper function for the case where we have GPIOs with one
156 * bit configuring the presence of a pull-up resistor. 66 * bit configuring the presence of a pull-up resistor.
157 */ 67 */
158extern int s3c_gpio_setpull_1up(struct s3c_gpio_chip *chip, 68extern int s3c24xx_gpio_setpull_1up(struct samsung_gpio_chip *chip,
159 unsigned int off, s3c_gpio_pull_t pull); 69 unsigned int off, samsung_gpio_pull_t pull);
160 70
161/** 71/**
162 * s3c_gpio_setpull_1down() - Pull configuration for choice of down or none 72 * s3c24xx_gpio_setpull_1down() - Pull configuration for choice of down or none
163 * @chip: The gpio chip that is being configured 73 * @chip: The gpio chip that is being configured
164 * @off: The offset for the GPIO being configured 74 * @off: The offset for the GPIO being configured
165 * @param: pull: The pull mode being requested 75 * @param: pull: The pull mode being requested
@@ -167,11 +77,13 @@ extern int s3c_gpio_setpull_1up(struct s3c_gpio_chip *chip,
167 * This is a helper function for the case where we have GPIOs with one 77 * This is a helper function for the case where we have GPIOs with one
168 * bit configuring the presence of a pull-down resistor. 78 * bit configuring the presence of a pull-down resistor.
169 */ 79 */
170extern int s3c_gpio_setpull_1down(struct s3c_gpio_chip *chip, 80extern int s3c24xx_gpio_setpull_1down(struct samsung_gpio_chip *chip,
171 unsigned int off, s3c_gpio_pull_t pull); 81 unsigned int off, samsung_gpio_pull_t pull);
172 82
173/** 83/**
174 * s3c_gpio_setpull_upown() - Pull configuration for choice of up, down or none 84 * samsung_gpio_setpull_upown() - Pull configuration for choice of up,
85 * down or none
86 *
175 * @chip: The gpio chip that is being configured. 87 * @chip: The gpio chip that is being configured.
176 * @off: The offset for the GPIO being configured. 88 * @off: The offset for the GPIO being configured.
177 * @param: pull: The pull mode being requested. 89 * @param: pull: The pull mode being requested.
@@ -183,45 +95,46 @@ extern int s3c_gpio_setpull_1down(struct s3c_gpio_chip *chip,
183 * 01 = Pull-up resistor connected 95 * 01 = Pull-up resistor connected
184 * 10 = Pull-down resistor connected 96 * 10 = Pull-down resistor connected
185 */ 97 */
186extern int s3c_gpio_setpull_updown(struct s3c_gpio_chip *chip, 98extern int samsung_gpio_setpull_updown(struct samsung_gpio_chip *chip,
187 unsigned int off, s3c_gpio_pull_t pull); 99 unsigned int off, samsung_gpio_pull_t pull);
188
189 100
190/** 101/**
191 * s3c_gpio_getpull_updown() - Get configuration for choice of up, down or none 102 * samsung_gpio_getpull_updown() - Get configuration for choice of up,
103 * down or none
104 *
192 * @chip: The gpio chip that the GPIO pin belongs to 105 * @chip: The gpio chip that the GPIO pin belongs to
193 * @off: The offset to the pin to get the configuration of. 106 * @off: The offset to the pin to get the configuration of.
194 * 107 *
195 * This helper function reads the state of the pull-{up,down} resistor for the 108 * This helper function reads the state of the pull-{up,down} resistor
196 * given GPIO in the same case as s3c_gpio_setpull_upown. 109 * for the given GPIO in the same case as samsung_gpio_setpull_upown.
197*/ 110*/
198extern s3c_gpio_pull_t s3c_gpio_getpull_updown(struct s3c_gpio_chip *chip, 111extern samsung_gpio_pull_t samsung_gpio_getpull_updown(struct samsung_gpio_chip *chip,
199 unsigned int off); 112 unsigned int off);
200 113
201/** 114/**
202 * s3c_gpio_getpull_1up() - Get configuration for choice of up or none 115 * s3c24xx_gpio_getpull_1up() - Get configuration for choice of up or none
203 * @chip: The gpio chip that the GPIO pin belongs to 116 * @chip: The gpio chip that the GPIO pin belongs to
204 * @off: The offset to the pin to get the configuration of. 117 * @off: The offset to the pin to get the configuration of.
205 * 118 *
206 * This helper function reads the state of the pull-up resistor for the 119 * This helper function reads the state of the pull-up resistor for the
207 * given GPIO in the same case as s3c_gpio_setpull_1up. 120 * given GPIO in the same case as s3c24xx_gpio_setpull_1up.
208*/ 121*/
209extern s3c_gpio_pull_t s3c_gpio_getpull_1up(struct s3c_gpio_chip *chip, 122extern samsung_gpio_pull_t s3c24xx_gpio_getpull_1up(struct samsung_gpio_chip *chip,
210 unsigned int off); 123 unsigned int off);
211 124
212/** 125/**
213 * s3c_gpio_getpull_1down() - Get configuration for choice of down or none 126 * s3c24xx_gpio_getpull_1down() - Get configuration for choice of down or none
214 * @chip: The gpio chip that the GPIO pin belongs to 127 * @chip: The gpio chip that the GPIO pin belongs to
215 * @off: The offset to the pin to get the configuration of. 128 * @off: The offset to the pin to get the configuration of.
216 * 129 *
217 * This helper function reads the state of the pull-down resistor for the 130 * This helper function reads the state of the pull-down resistor for the
218 * given GPIO in the same case as s3c_gpio_setpull_1down. 131 * given GPIO in the same case as s3c24xx_gpio_setpull_1down.
219*/ 132*/
220extern s3c_gpio_pull_t s3c_gpio_getpull_1down(struct s3c_gpio_chip *chip, 133extern samsung_gpio_pull_t s3c24xx_gpio_getpull_1down(struct samsung_gpio_chip *chip,
221 unsigned int off); 134 unsigned int off);
222 135
223/** 136/**
224 * s3c_gpio_setpull_s3c2443() - Pull configuration for s3c2443. 137 * s3c2443_gpio_setpull() - Pull configuration for s3c2443.
225 * @chip: The gpio chip that is being configured. 138 * @chip: The gpio chip that is being configured.
226 * @off: The offset for the GPIO being configured. 139 * @off: The offset for the GPIO being configured.
227 * @param: pull: The pull mode being requested. 140 * @param: pull: The pull mode being requested.
@@ -233,19 +146,18 @@ extern s3c_gpio_pull_t s3c_gpio_getpull_1down(struct s3c_gpio_chip *chip,
233 * 10 = Pull-down resistor connected 146 * 10 = Pull-down resistor connected
234 * x1 = No pull up resistor 147 * x1 = No pull up resistor
235 */ 148 */
236extern int s3c_gpio_setpull_s3c2443(struct s3c_gpio_chip *chip, 149extern int s3c2443_gpio_setpull(struct samsung_gpio_chip *chip,
237 unsigned int off, s3c_gpio_pull_t pull); 150 unsigned int off, samsung_gpio_pull_t pull);
238 151
239/** 152/**
240 * s3c_gpio_getpull_s3c2443() - Get configuration for s3c2443 pull resistors 153 * s3c2443_gpio_getpull() - Get configuration for s3c2443 pull resistors
241 * @chip: The gpio chip that the GPIO pin belongs to. 154 * @chip: The gpio chip that the GPIO pin belongs to.
242 * @off: The offset to the pin to get the configuration of. 155 * @off: The offset to the pin to get the configuration of.
243 * 156 *
244 * This helper function reads the state of the pull-{up,down} resistor for the 157 * This helper function reads the state of the pull-{up,down} resistor for the
245 * given GPIO in the same case as s3c_gpio_setpull_upown. 158 * given GPIO in the same case as samsung_gpio_setpull_upown.
246*/ 159*/
247extern s3c_gpio_pull_t s3c_gpio_getpull_s3c2443(struct s3c_gpio_chip *chip, 160extern samsung_gpio_pull_t s3c2443_gpio_getpull(struct samsung_gpio_chip *chip,
248 unsigned int off); 161 unsigned int off);
249 162
250#endif /* __PLAT_GPIO_CFG_HELPERS_H */ 163#endif /* __PLAT_GPIO_CFG_HELPERS_H */
251
diff --git a/arch/arm/plat-samsung/include/plat/gpio-cfg.h b/arch/arm/plat-samsung/include/plat/gpio-cfg.h
index 1762dcb4cb9e..d48245bb02b3 100644
--- a/arch/arm/plat-samsung/include/plat/gpio-cfg.h
+++ b/arch/arm/plat-samsung/include/plat/gpio-cfg.h
@@ -24,14 +24,14 @@
24#ifndef __PLAT_GPIO_CFG_H 24#ifndef __PLAT_GPIO_CFG_H
25#define __PLAT_GPIO_CFG_H __FILE__ 25#define __PLAT_GPIO_CFG_H __FILE__
26 26
27typedef unsigned int __bitwise__ s3c_gpio_pull_t; 27typedef unsigned int __bitwise__ samsung_gpio_pull_t;
28typedef unsigned int __bitwise__ s5p_gpio_drvstr_t; 28typedef unsigned int __bitwise__ s5p_gpio_drvstr_t;
29 29
30/* forward declaration if gpio-core.h hasn't been included */ 30/* forward declaration if gpio-core.h hasn't been included */
31struct s3c_gpio_chip; 31struct samsung_gpio_chip;
32 32
33/** 33/**
34 * struct s3c_gpio_cfg GPIO configuration 34 * struct samsung_gpio_cfg GPIO configuration
35 * @cfg_eint: Configuration setting when used for external interrupt source 35 * @cfg_eint: Configuration setting when used for external interrupt source
36 * @get_pull: Read the current pull configuration for the GPIO 36 * @get_pull: Read the current pull configuration for the GPIO
37 * @set_pull: Set the current pull configuraiton for the GPIO 37 * @set_pull: Set the current pull configuraiton for the GPIO
@@ -44,20 +44,20 @@ struct s3c_gpio_chip;
44 * per-bank configuration information that other systems such as the 44 * per-bank configuration information that other systems such as the
45 * external interrupt code will need. 45 * external interrupt code will need.
46 * 46 *
47 * @sa s3c_gpio_cfgpin 47 * @sa samsung_gpio_cfgpin
48 * @sa s3c_gpio_getcfg 48 * @sa s3c_gpio_getcfg
49 * @sa s3c_gpio_setpull 49 * @sa s3c_gpio_setpull
50 * @sa s3c_gpio_getpull 50 * @sa s3c_gpio_getpull
51 */ 51 */
52struct s3c_gpio_cfg { 52struct samsung_gpio_cfg {
53 unsigned int cfg_eint; 53 unsigned int cfg_eint;
54 54
55 s3c_gpio_pull_t (*get_pull)(struct s3c_gpio_chip *chip, unsigned offs); 55 samsung_gpio_pull_t (*get_pull)(struct samsung_gpio_chip *chip, unsigned offs);
56 int (*set_pull)(struct s3c_gpio_chip *chip, unsigned offs, 56 int (*set_pull)(struct samsung_gpio_chip *chip, unsigned offs,
57 s3c_gpio_pull_t pull); 57 samsung_gpio_pull_t pull);
58 58
59 unsigned (*get_config)(struct s3c_gpio_chip *chip, unsigned offs); 59 unsigned (*get_config)(struct samsung_gpio_chip *chip, unsigned offs);
60 int (*set_config)(struct s3c_gpio_chip *chip, unsigned offs, 60 int (*set_config)(struct samsung_gpio_chip *chip, unsigned offs,
61 unsigned config); 61 unsigned config);
62}; 62};
63 63
@@ -69,7 +69,7 @@ struct s3c_gpio_cfg {
69#define S3C_GPIO_OUTPUT (S3C_GPIO_SPECIAL(1)) 69#define S3C_GPIO_OUTPUT (S3C_GPIO_SPECIAL(1))
70#define S3C_GPIO_SFN(x) (S3C_GPIO_SPECIAL(x)) 70#define S3C_GPIO_SFN(x) (S3C_GPIO_SPECIAL(x))
71 71
72#define s3c_gpio_is_cfg_special(_cfg) \ 72#define samsung_gpio_is_cfg_special(_cfg) \
73 (((_cfg) & S3C_GPIO_SPECIAL_MARK) == S3C_GPIO_SPECIAL_MARK) 73 (((_cfg) & S3C_GPIO_SPECIAL_MARK) == S3C_GPIO_SPECIAL_MARK)
74 74
75/** 75/**
@@ -128,9 +128,9 @@ extern int s3c_gpio_cfgpin_range(unsigned int start, unsigned int nr,
128 * up or down settings, and it may be dependent on the chip that is being 128 * up or down settings, and it may be dependent on the chip that is being
129 * used to whether the particular mode is available. 129 * used to whether the particular mode is available.
130 */ 130 */
131#define S3C_GPIO_PULL_NONE ((__force s3c_gpio_pull_t)0x00) 131#define S3C_GPIO_PULL_NONE ((__force samsung_gpio_pull_t)0x00)
132#define S3C_GPIO_PULL_DOWN ((__force s3c_gpio_pull_t)0x01) 132#define S3C_GPIO_PULL_DOWN ((__force samsung_gpio_pull_t)0x01)
133#define S3C_GPIO_PULL_UP ((__force s3c_gpio_pull_t)0x02) 133#define S3C_GPIO_PULL_UP ((__force samsung_gpio_pull_t)0x02)
134 134
135/** 135/**
136 * s3c_gpio_setpull() - set the state of a gpio pin pull resistor 136 * s3c_gpio_setpull() - set the state of a gpio pin pull resistor
@@ -143,7 +143,7 @@ extern int s3c_gpio_cfgpin_range(unsigned int start, unsigned int nr,
143 * 143 *
144 * @pull is one of S3C_GPIO_PULL_NONE, S3C_GPIO_PULL_DOWN or S3C_GPIO_PULL_UP. 144 * @pull is one of S3C_GPIO_PULL_NONE, S3C_GPIO_PULL_DOWN or S3C_GPIO_PULL_UP.
145*/ 145*/
146extern int s3c_gpio_setpull(unsigned int pin, s3c_gpio_pull_t pull); 146extern int s3c_gpio_setpull(unsigned int pin, samsung_gpio_pull_t pull);
147 147
148/** 148/**
149 * s3c_gpio_getpull() - get the pull resistor state of a gpio pin 149 * s3c_gpio_getpull() - get the pull resistor state of a gpio pin
@@ -151,7 +151,7 @@ extern int s3c_gpio_setpull(unsigned int pin, s3c_gpio_pull_t pull);
151 * 151 *
152 * Read the pull resistor value for the specified pin. 152 * Read the pull resistor value for the specified pin.
153*/ 153*/
154extern s3c_gpio_pull_t s3c_gpio_getpull(unsigned int pin); 154extern samsung_gpio_pull_t s3c_gpio_getpull(unsigned int pin);
155 155
156/* configure `all` aspects of an gpio */ 156/* configure `all` aspects of an gpio */
157 157
@@ -170,7 +170,7 @@ extern s3c_gpio_pull_t s3c_gpio_getpull(unsigned int pin);
170 * @sa s3c_gpio_cfgpin_range 170 * @sa s3c_gpio_cfgpin_range
171 */ 171 */
172extern int s3c_gpio_cfgall_range(unsigned int start, unsigned int nr, 172extern int s3c_gpio_cfgall_range(unsigned int start, unsigned int nr,
173 unsigned int cfg, s3c_gpio_pull_t pull); 173 unsigned int cfg, samsung_gpio_pull_t pull);
174 174
175static inline int s3c_gpio_cfgrange_nopull(unsigned int pin, unsigned int size, 175static inline int s3c_gpio_cfgrange_nopull(unsigned int pin, unsigned int size,
176 unsigned int cfg) 176 unsigned int cfg)
diff --git a/arch/arm/plat-samsung/include/plat/gpio-core.h b/arch/arm/plat-samsung/include/plat/gpio-core.h
index 8cad4cf19c3c..1fe6917f6a2a 100644
--- a/arch/arm/plat-samsung/include/plat/gpio-core.h
+++ b/arch/arm/plat-samsung/include/plat/gpio-core.h
@@ -25,22 +25,22 @@
25 * specific code. 25 * specific code.
26*/ 26*/
27 27
28struct s3c_gpio_chip; 28struct samsung_gpio_chip;
29 29
30/** 30/**
31 * struct s3c_gpio_pm - power management (suspend/resume) information 31 * struct samsung_gpio_pm - power management (suspend/resume) information
32 * @save: Routine to save the state of the GPIO block 32 * @save: Routine to save the state of the GPIO block
33 * @resume: Routine to resume the GPIO block. 33 * @resume: Routine to resume the GPIO block.
34 */ 34 */
35struct s3c_gpio_pm { 35struct samsung_gpio_pm {
36 void (*save)(struct s3c_gpio_chip *chip); 36 void (*save)(struct samsung_gpio_chip *chip);
37 void (*resume)(struct s3c_gpio_chip *chip); 37 void (*resume)(struct samsung_gpio_chip *chip);
38}; 38};
39 39
40struct s3c_gpio_cfg; 40struct samsung_gpio_cfg;
41 41
42/** 42/**
43 * struct s3c_gpio_chip - wrapper for specific implementation of gpio 43 * struct samsung_gpio_chip - wrapper for specific implementation of gpio
44 * @chip: The chip structure to be exported via gpiolib. 44 * @chip: The chip structure to be exported via gpiolib.
45 * @base: The base pointer to the gpio configuration registers. 45 * @base: The base pointer to the gpio configuration registers.
46 * @group: The group register number for gpio interrupt support. 46 * @group: The group register number for gpio interrupt support.
@@ -60,10 +60,10 @@ struct s3c_gpio_cfg;
60 * CPU cores trying to get one lock for different GPIO banks, where each 60 * CPU cores trying to get one lock for different GPIO banks, where each
61 * bank of GPIO has its own register space and configuration registers. 61 * bank of GPIO has its own register space and configuration registers.
62 */ 62 */
63struct s3c_gpio_chip { 63struct samsung_gpio_chip {
64 struct gpio_chip chip; 64 struct gpio_chip chip;
65 struct s3c_gpio_cfg *config; 65 struct samsung_gpio_cfg *config;
66 struct s3c_gpio_pm *pm; 66 struct samsung_gpio_pm *pm;
67 void __iomem *base; 67 void __iomem *base;
68 int irq_base; 68 int irq_base;
69 int group; 69 int group;
@@ -73,58 +73,11 @@ struct s3c_gpio_chip {
73#endif 73#endif
74}; 74};
75 75
76static inline struct s3c_gpio_chip *to_s3c_gpio(struct gpio_chip *gpc) 76static inline struct samsung_gpio_chip *to_samsung_gpio(struct gpio_chip *gpc)
77{ 77{
78 return container_of(gpc, struct s3c_gpio_chip, chip); 78 return container_of(gpc, struct samsung_gpio_chip, chip);
79} 79}
80 80
81/** s3c_gpiolib_add() - add the s3c specific version of a gpio_chip.
82 * @chip: The chip to register
83 *
84 * This is a wrapper to gpiochip_add() that takes our specific gpio chip
85 * information and makes the necessary alterations for the platform and
86 * notes the information for use with the configuration systems and any
87 * other parts of the system.
88 */
89extern void s3c_gpiolib_add(struct s3c_gpio_chip *chip);
90
91/* CONFIG_S3C_GPIO_TRACK enables the tracking of the s3c specific gpios
92 * for use with the configuration calls, and other parts of the s3c gpiolib
93 * support code.
94 *
95 * Not all s3c support code will need this, as some configurations of cpu
96 * may only support one or two different configuration options and have an
97 * easy gpio to s3c_gpio_chip mapping function. If this is the case, then
98 * the machine support file should provide its own s3c_gpiolib_getchip()
99 * and any other necessary functions.
100 */
101
102/**
103 * samsung_gpiolib_add_4bit_chips - 4bit single register GPIO config.
104 * @chip: The gpio chip that is being configured.
105 * @nr_chips: The no of chips (gpio ports) for the GPIO being configured.
106 *
107 * This helper deal with the GPIO cases where the control register has 4 bits
108 * of control per GPIO, generally in the form of:
109 * 0000 = Input
110 * 0001 = Output
111 * others = Special functions (dependent on bank)
112 *
113 * Note, since the code to deal with the case where there are two control
114 * registers instead of one, we do not have a separate set of function
115 * (samsung_gpiolib_add_4bit2_chips)for each case.
116 */
117extern void samsung_gpiolib_add_4bit_chips(struct s3c_gpio_chip *chip,
118 int nr_chips);
119extern void samsung_gpiolib_add_4bit2_chips(struct s3c_gpio_chip *chip,
120 int nr_chips);
121extern void samsung_gpiolib_add_2bit_chips(struct s3c_gpio_chip *chip,
122 int nr_chips);
123
124extern void samsung_gpiolib_add_4bit(struct s3c_gpio_chip *chip);
125extern void samsung_gpiolib_add_4bit2(struct s3c_gpio_chip *chip);
126
127
128/** 81/**
129 * samsung_gpiolib_to_irq - convert gpio pin to irq number 82 * samsung_gpiolib_to_irq - convert gpio pin to irq number
130 * @chip: The gpio chip that the pin belongs to. 83 * @chip: The gpio chip that the pin belongs to.
@@ -136,36 +89,36 @@ extern void samsung_gpiolib_add_4bit2(struct s3c_gpio_chip *chip);
136extern int samsung_gpiolib_to_irq(struct gpio_chip *chip, unsigned int offset); 89extern int samsung_gpiolib_to_irq(struct gpio_chip *chip, unsigned int offset);
137 90
138/* exported for core SoC support to change */ 91/* exported for core SoC support to change */
139extern struct s3c_gpio_cfg s3c24xx_gpiocfg_default; 92extern struct samsung_gpio_cfg s3c24xx_gpiocfg_default;
140 93
141#ifdef CONFIG_S3C_GPIO_TRACK 94#ifdef CONFIG_S3C_GPIO_TRACK
142extern struct s3c_gpio_chip *s3c_gpios[S3C_GPIO_END]; 95extern struct samsung_gpio_chip *s3c_gpios[S3C_GPIO_END];
143 96
144static inline struct s3c_gpio_chip *s3c_gpiolib_getchip(unsigned int chip) 97static inline struct samsung_gpio_chip *samsung_gpiolib_getchip(unsigned int chip)
145{ 98{
146 return (chip < S3C_GPIO_END) ? s3c_gpios[chip] : NULL; 99 return (chip < S3C_GPIO_END) ? s3c_gpios[chip] : NULL;
147} 100}
148#else 101#else
149/* machine specific code should provide s3c_gpiolib_getchip */ 102/* machine specific code should provide samsung_gpiolib_getchip */
150 103
151#include <mach/gpio-track.h> 104#include <mach/gpio-track.h>
152 105
153static inline void s3c_gpiolib_track(struct s3c_gpio_chip *chip) { } 106static inline void s3c_gpiolib_track(struct samsung_gpio_chip *chip) { }
154#endif 107#endif
155 108
156#ifdef CONFIG_PM 109#ifdef CONFIG_PM
157extern struct s3c_gpio_pm s3c_gpio_pm_1bit; 110extern struct samsung_gpio_pm samsung_gpio_pm_1bit;
158extern struct s3c_gpio_pm s3c_gpio_pm_2bit; 111extern struct samsung_gpio_pm samsung_gpio_pm_2bit;
159extern struct s3c_gpio_pm s3c_gpio_pm_4bit; 112extern struct samsung_gpio_pm samsung_gpio_pm_4bit;
160#define __gpio_pm(x) x 113#define __gpio_pm(x) x
161#else 114#else
162#define s3c_gpio_pm_1bit NULL 115#define samsung_gpio_pm_1bit NULL
163#define s3c_gpio_pm_2bit NULL 116#define samsung_gpio_pm_2bit NULL
164#define s3c_gpio_pm_4bit NULL 117#define samsung_gpio_pm_4bit NULL
165#define __gpio_pm(x) NULL 118#define __gpio_pm(x) NULL
166 119
167#endif /* CONFIG_PM */ 120#endif /* CONFIG_PM */
168 121
169/* locking wrappers to deal with multiple access to the same gpio bank */ 122/* locking wrappers to deal with multiple access to the same gpio bank */
170#define s3c_gpio_lock(_oc, _fl) spin_lock_irqsave(&(_oc)->lock, _fl) 123#define samsung_gpio_lock(_oc, _fl) spin_lock_irqsave(&(_oc)->lock, _fl)
171#define s3c_gpio_unlock(_oc, _fl) spin_unlock_irqrestore(&(_oc)->lock, _fl) 124#define samsung_gpio_unlock(_oc, _fl) spin_unlock_irqrestore(&(_oc)->lock, _fl)
diff --git a/arch/arm/plat-samsung/include/plat/gpio-fns.h b/arch/arm/plat-samsung/include/plat/gpio-fns.h
new file mode 100644
index 000000000000..bab139201761
--- /dev/null
+++ b/arch/arm/plat-samsung/include/plat/gpio-fns.h
@@ -0,0 +1,98 @@
1/* arch/arm/mach-s3c2410/include/mach/gpio-fns.h
2 *
3 * Copyright (c) 2003-2009 Simtec Electronics
4 * Ben Dooks <ben@simtec.co.uk>
5 *
6 * S3C2410 - hardware
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11*/
12
13#ifndef __MACH_GPIO_FNS_H
14#define __MACH_GPIO_FNS_H __FILE__
15
16/* These functions are in the to-be-removed category and it is strongly
17 * encouraged not to use these in new code. They will be marked deprecated
18 * very soon.
19 *
20 * Most of the functionality can be either replaced by the gpiocfg calls
21 * for the s3c platform or by the generic GPIOlib API.
22 *
23 * As of 2.6.35-rc, these will be removed, with the few drivers using them
24 * either replaced or given a wrapper until the calls can be removed.
25*/
26
27#include <plat/gpio-cfg.h>
28
29static inline void s3c2410_gpio_cfgpin(unsigned int pin, unsigned int cfg)
30{
31 /* 1:1 mapping between cfgpin and setcfg calls at the moment */
32 s3c_gpio_cfgpin(pin, cfg);
33}
34
35/* external functions for GPIO support
36 *
37 * These allow various different clients to access the same GPIO
38 * registers without conflicting. If your driver only owns the entire
39 * GPIO register, then it is safe to ioremap/__raw_{read|write} to it.
40*/
41
42extern unsigned int s3c2410_gpio_getcfg(unsigned int pin);
43
44/* s3c2410_gpio_getirq
45 *
46 * turn the given pin number into the corresponding IRQ number
47 *
48 * returns:
49 * < 0 = no interrupt for this pin
50 * >=0 = interrupt number for the pin
51*/
52
53extern int s3c2410_gpio_getirq(unsigned int pin);
54
55/* s3c2410_gpio_irqfilter
56 *
57 * set the irq filtering on the given pin
58 *
59 * on = 0 => disable filtering
60 * 1 => enable filtering
61 *
62 * config = S3C2410_EINTFLT_PCLK or S3C2410_EINTFLT_EXTCLK orred with
63 * width of filter (0 through 63)
64 *
65 *
66*/
67
68extern int s3c2410_gpio_irqfilter(unsigned int pin, unsigned int on,
69 unsigned int config);
70
71/* s3c2410_gpio_pullup
72 *
73 * This call should be replaced with s3c_gpio_setpull().
74 *
75 * As a note, there is currently no distinction between pull-up and pull-down
76 * in the s3c24xx series devices with only an on/off configuration.
77 */
78
79/* s3c2410_gpio_pullup
80 *
81 * configure the pull-up control on the given pin
82 *
83 * to = 1 => disable the pull-up
84 * 0 => enable the pull-up
85 *
86 * eg;
87 *
88 * s3c2410_gpio_pullup(S3C2410_GPB(0), 0);
89 * s3c2410_gpio_pullup(S3C2410_GPE(8), 0);
90*/
91
92extern void s3c2410_gpio_pullup(unsigned int pin, unsigned int to);
93
94extern void s3c2410_gpio_setpin(unsigned int pin, unsigned int to);
95
96extern unsigned int s3c2410_gpio_getpin(unsigned int pin);
97
98#endif /* __MACH_GPIO_FNS_H */
diff --git a/arch/arm/plat-samsung/include/plat/iic.h b/arch/arm/plat-samsung/include/plat/iic.h
index 56b0059439e1..51d52e767a19 100644
--- a/arch/arm/plat-samsung/include/plat/iic.h
+++ b/arch/arm/plat-samsung/include/plat/iic.h
@@ -60,6 +60,7 @@ extern void s3c_i2c4_set_platdata(struct s3c2410_platform_i2c *i2c);
60extern void s3c_i2c5_set_platdata(struct s3c2410_platform_i2c *i2c); 60extern void s3c_i2c5_set_platdata(struct s3c2410_platform_i2c *i2c);
61extern void s3c_i2c6_set_platdata(struct s3c2410_platform_i2c *i2c); 61extern void s3c_i2c6_set_platdata(struct s3c2410_platform_i2c *i2c);
62extern void s3c_i2c7_set_platdata(struct s3c2410_platform_i2c *i2c); 62extern void s3c_i2c7_set_platdata(struct s3c2410_platform_i2c *i2c);
63extern void s5p_i2c_hdmiphy_set_platdata(struct s3c2410_platform_i2c *i2c);
63 64
64/* defined by architecture to configure gpio */ 65/* defined by architecture to configure gpio */
65extern void s3c_i2c0_cfg_gpio(struct platform_device *dev); 66extern void s3c_i2c0_cfg_gpio(struct platform_device *dev);
diff --git a/arch/arm/plat-samsung/include/plat/pm.h b/arch/arm/plat-samsung/include/plat/pm.h
index f6749916d194..dcf68709f9cf 100644
--- a/arch/arm/plat-samsung/include/plat/pm.h
+++ b/arch/arm/plat-samsung/include/plat/pm.h
@@ -165,20 +165,20 @@ extern void s3c_pm_check_store(void);
165extern void s3c_pm_configure_extint(void); 165extern void s3c_pm_configure_extint(void);
166 166
167/** 167/**
168 * s3c_pm_restore_gpios() - restore the state of the gpios after sleep. 168 * samsung_pm_restore_gpios() - restore the state of the gpios after sleep.
169 * 169 *
170 * Restore the state of the GPIO pins after sleep, which may involve ensuring 170 * Restore the state of the GPIO pins after sleep, which may involve ensuring
171 * that we do not glitch the state of the pins from that the bootloader's 171 * that we do not glitch the state of the pins from that the bootloader's
172 * resume code has done. 172 * resume code has done.
173*/ 173*/
174extern void s3c_pm_restore_gpios(void); 174extern void samsung_pm_restore_gpios(void);
175 175
176/** 176/**
177 * s3c_pm_save_gpios() - save the state of the GPIOs for restoring after sleep. 177 * samsung_pm_save_gpios() - save the state of the GPIOs for restoring after sleep.
178 * 178 *
179 * Save the GPIO states for resotration on resume. See s3c_pm_restore_gpios(). 179 * Save the GPIO states for resotration on resume. See samsung_pm_restore_gpios().
180 */ 180 */
181extern void s3c_pm_save_gpios(void); 181extern void samsung_pm_save_gpios(void);
182 182
183extern void s3c_pm_save_core(void); 183extern void s3c_pm_save_core(void);
184extern void s3c_pm_restore_core(void); 184extern void s3c_pm_restore_core(void);
diff --git a/arch/arm/plat-samsung/include/plat/s3c-pl330-pdata.h b/arch/arm/plat-samsung/include/plat/s3c-pl330-pdata.h
deleted file mode 100644
index bf5e2a9d408d..000000000000
--- a/arch/arm/plat-samsung/include/plat/s3c-pl330-pdata.h
+++ /dev/null
@@ -1,32 +0,0 @@
1/* linux/arch/arm/plat-samsung/include/plat/s3c-pl330-pdata.h
2 *
3 * Copyright (C) 2010 Samsung Electronics Co. Ltd.
4 * Jaswinder Singh <jassi.brar@samsung.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 */
11
12#ifndef __S3C_PL330_PDATA_H
13#define __S3C_PL330_PDATA_H
14
15#include <plat/s3c-dma-pl330.h>
16
17/*
18 * Every PL330 DMAC has max 32 peripheral interfaces,
19 * of which some may be not be really used in your
20 * DMAC's configuration.
21 * Populate this array of 32 peri i/fs with relevant
22 * channel IDs for used peri i/f and DMACH_MAX for
23 * those unused.
24 *
25 * The platforms just need to provide this info
26 * to the S3C DMA API driver for PL330.
27 */
28struct s3c_pl330_platdata {
29 enum dma_ch peri[32];
30};
31
32#endif /* __S3C_PL330_PDATA_H */
diff --git a/arch/arm/plat-samsung/include/plat/tv-core.h b/arch/arm/plat-samsung/include/plat/tv-core.h
new file mode 100644
index 000000000000..3bc34f3ce28f
--- /dev/null
+++ b/arch/arm/plat-samsung/include/plat/tv-core.h
@@ -0,0 +1,44 @@
1/*
2 * arch/arm/plat-samsung/include/plat/tv.h
3 *
4 * Copyright 2011 Samsung Electronics Co., Ltd.
5 * Tomasz Stanislawski <t.stanislaws@samsung.com>
6 *
7 * Samsung TV driver core functions
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
12 */
13
14#ifndef __SAMSUNG_PLAT_TV_H
15#define __SAMSUNG_PLAT_TV_H __FILE__
16
17/*
18 * These functions are only for use with the core support code, such as
19 * the CPU-specific initialization code.
20 */
21
22/* Re-define device name to differentiate the subsystem in various SoCs. */
23static inline void s5p_hdmi_setname(char *name)
24{
25#ifdef CONFIG_S5P_DEV_TV
26 s5p_device_hdmi.name = name;
27#endif
28}
29
30static inline void s5p_mixer_setname(char *name)
31{
32#ifdef CONFIG_S5P_DEV_TV
33 s5p_device_mixer.name = name;
34#endif
35}
36
37static inline void s5p_sdo_setname(char *name)
38{
39#ifdef CONFIG_S5P_DEV_TV
40 s5p_device_sdo.name = name;
41#endif
42}
43
44#endif /* __SAMSUNG_PLAT_TV_H */
diff --git a/arch/arm/plat-samsung/pm-gpio.c b/arch/arm/plat-samsung/pm-gpio.c
index 96528200eb79..4be016eaa6db 100644
--- a/arch/arm/plat-samsung/pm-gpio.c
+++ b/arch/arm/plat-samsung/pm-gpio.c
@@ -28,13 +28,13 @@
28#define OFFS_DAT (0x04) 28#define OFFS_DAT (0x04)
29#define OFFS_UP (0x08) 29#define OFFS_UP (0x08)
30 30
31static void s3c_gpio_pm_1bit_save(struct s3c_gpio_chip *chip) 31static void samsung_gpio_pm_1bit_save(struct samsung_gpio_chip *chip)
32{ 32{
33 chip->pm_save[0] = __raw_readl(chip->base + OFFS_CON); 33 chip->pm_save[0] = __raw_readl(chip->base + OFFS_CON);
34 chip->pm_save[1] = __raw_readl(chip->base + OFFS_DAT); 34 chip->pm_save[1] = __raw_readl(chip->base + OFFS_DAT);
35} 35}
36 36
37static void s3c_gpio_pm_1bit_resume(struct s3c_gpio_chip *chip) 37static void samsung_gpio_pm_1bit_resume(struct samsung_gpio_chip *chip)
38{ 38{
39 void __iomem *base = chip->base; 39 void __iomem *base = chip->base;
40 u32 old_gpcon = __raw_readl(base + OFFS_CON); 40 u32 old_gpcon = __raw_readl(base + OFFS_CON);
@@ -60,12 +60,12 @@ static void s3c_gpio_pm_1bit_resume(struct s3c_gpio_chip *chip)
60 chip->chip.label, old_gpcon, gps_gpcon, old_gpdat, gps_gpdat); 60 chip->chip.label, old_gpcon, gps_gpcon, old_gpdat, gps_gpdat);
61} 61}
62 62
63struct s3c_gpio_pm s3c_gpio_pm_1bit = { 63struct samsung_gpio_pm samsung_gpio_pm_1bit = {
64 .save = s3c_gpio_pm_1bit_save, 64 .save = samsung_gpio_pm_1bit_save,
65 .resume = s3c_gpio_pm_1bit_resume, 65 .resume = samsung_gpio_pm_1bit_resume,
66}; 66};
67 67
68static void s3c_gpio_pm_2bit_save(struct s3c_gpio_chip *chip) 68static void samsung_gpio_pm_2bit_save(struct samsung_gpio_chip *chip)
69{ 69{
70 chip->pm_save[0] = __raw_readl(chip->base + OFFS_CON); 70 chip->pm_save[0] = __raw_readl(chip->base + OFFS_CON);
71 chip->pm_save[1] = __raw_readl(chip->base + OFFS_DAT); 71 chip->pm_save[1] = __raw_readl(chip->base + OFFS_DAT);
@@ -95,7 +95,7 @@ static inline int is_out(unsigned long con)
95} 95}
96 96
97/** 97/**
98 * s3c_gpio_pm_2bit_resume() - restore the given GPIO bank 98 * samsung_gpio_pm_2bit_resume() - restore the given GPIO bank
99 * @chip: The chip information to resume. 99 * @chip: The chip information to resume.
100 * 100 *
101 * Restore one of the GPIO banks that was saved during suspend. This is 101 * Restore one of the GPIO banks that was saved during suspend. This is
@@ -121,7 +121,7 @@ static inline int is_out(unsigned long con)
121 * [1] this assumes that writing to a pin DAT whilst in SFN will set the 121 * [1] this assumes that writing to a pin DAT whilst in SFN will set the
122 * state for when it is next output. 122 * state for when it is next output.
123 */ 123 */
124static void s3c_gpio_pm_2bit_resume(struct s3c_gpio_chip *chip) 124static void samsung_gpio_pm_2bit_resume(struct samsung_gpio_chip *chip)
125{ 125{
126 void __iomem *base = chip->base; 126 void __iomem *base = chip->base;
127 u32 old_gpcon = __raw_readl(base + OFFS_CON); 127 u32 old_gpcon = __raw_readl(base + OFFS_CON);
@@ -187,13 +187,13 @@ static void s3c_gpio_pm_2bit_resume(struct s3c_gpio_chip *chip)
187 chip->chip.label, old_gpcon, gps_gpcon, old_gpdat, gps_gpdat); 187 chip->chip.label, old_gpcon, gps_gpcon, old_gpdat, gps_gpdat);
188} 188}
189 189
190struct s3c_gpio_pm s3c_gpio_pm_2bit = { 190struct samsung_gpio_pm samsung_gpio_pm_2bit = {
191 .save = s3c_gpio_pm_2bit_save, 191 .save = samsung_gpio_pm_2bit_save,
192 .resume = s3c_gpio_pm_2bit_resume, 192 .resume = samsung_gpio_pm_2bit_resume,
193}; 193};
194 194
195#if defined(CONFIG_ARCH_S3C64XX) || defined(CONFIG_PLAT_S5P) 195#if defined(CONFIG_ARCH_S3C64XX) || defined(CONFIG_PLAT_S5P)
196static void s3c_gpio_pm_4bit_save(struct s3c_gpio_chip *chip) 196static void samsung_gpio_pm_4bit_save(struct samsung_gpio_chip *chip)
197{ 197{
198 chip->pm_save[1] = __raw_readl(chip->base + OFFS_CON); 198 chip->pm_save[1] = __raw_readl(chip->base + OFFS_CON);
199 chip->pm_save[2] = __raw_readl(chip->base + OFFS_DAT); 199 chip->pm_save[2] = __raw_readl(chip->base + OFFS_DAT);
@@ -203,7 +203,7 @@ static void s3c_gpio_pm_4bit_save(struct s3c_gpio_chip *chip)
203 chip->pm_save[0] = __raw_readl(chip->base - 4); 203 chip->pm_save[0] = __raw_readl(chip->base - 4);
204} 204}
205 205
206static u32 s3c_gpio_pm_4bit_mask(u32 old_gpcon, u32 gps_gpcon) 206static u32 samsung_gpio_pm_4bit_mask(u32 old_gpcon, u32 gps_gpcon)
207{ 207{
208 u32 old, new, mask; 208 u32 old, new, mask;
209 u32 change_mask = 0x0; 209 u32 change_mask = 0x0;
@@ -242,14 +242,14 @@ static u32 s3c_gpio_pm_4bit_mask(u32 old_gpcon, u32 gps_gpcon)
242 return change_mask; 242 return change_mask;
243} 243}
244 244
245static void s3c_gpio_pm_4bit_con(struct s3c_gpio_chip *chip, int index) 245static void samsung_gpio_pm_4bit_con(struct samsung_gpio_chip *chip, int index)
246{ 246{
247 void __iomem *con = chip->base + (index * 4); 247 void __iomem *con = chip->base + (index * 4);
248 u32 old_gpcon = __raw_readl(con); 248 u32 old_gpcon = __raw_readl(con);
249 u32 gps_gpcon = chip->pm_save[index + 1]; 249 u32 gps_gpcon = chip->pm_save[index + 1];
250 u32 gpcon, mask; 250 u32 gpcon, mask;
251 251
252 mask = s3c_gpio_pm_4bit_mask(old_gpcon, gps_gpcon); 252 mask = samsung_gpio_pm_4bit_mask(old_gpcon, gps_gpcon);
253 253
254 gpcon = old_gpcon & ~mask; 254 gpcon = old_gpcon & ~mask;
255 gpcon |= gps_gpcon & mask; 255 gpcon |= gps_gpcon & mask;
@@ -257,7 +257,7 @@ static void s3c_gpio_pm_4bit_con(struct s3c_gpio_chip *chip, int index)
257 __raw_writel(gpcon, con); 257 __raw_writel(gpcon, con);
258} 258}
259 259
260static void s3c_gpio_pm_4bit_resume(struct s3c_gpio_chip *chip) 260static void samsung_gpio_pm_4bit_resume(struct samsung_gpio_chip *chip)
261{ 261{
262 void __iomem *base = chip->base; 262 void __iomem *base = chip->base;
263 u32 old_gpcon[2]; 263 u32 old_gpcon[2];
@@ -269,10 +269,10 @@ static void s3c_gpio_pm_4bit_resume(struct s3c_gpio_chip *chip)
269 old_gpcon[0] = 0; 269 old_gpcon[0] = 0;
270 old_gpcon[1] = __raw_readl(base + OFFS_CON); 270 old_gpcon[1] = __raw_readl(base + OFFS_CON);
271 271
272 s3c_gpio_pm_4bit_con(chip, 0); 272 samsung_gpio_pm_4bit_con(chip, 0);
273 if (chip->chip.ngpio > 8) { 273 if (chip->chip.ngpio > 8) {
274 old_gpcon[0] = __raw_readl(base - 4); 274 old_gpcon[0] = __raw_readl(base - 4);
275 s3c_gpio_pm_4bit_con(chip, -1); 275 samsung_gpio_pm_4bit_con(chip, -1);
276 } 276 }
277 277
278 /* Now change the configurations that require DAT,CON */ 278 /* Now change the configurations that require DAT,CON */
@@ -298,19 +298,19 @@ static void s3c_gpio_pm_4bit_resume(struct s3c_gpio_chip *chip)
298 old_gpdat, gps_gpdat); 298 old_gpdat, gps_gpdat);
299} 299}
300 300
301struct s3c_gpio_pm s3c_gpio_pm_4bit = { 301struct samsung_gpio_pm samsung_gpio_pm_4bit = {
302 .save = s3c_gpio_pm_4bit_save, 302 .save = samsung_gpio_pm_4bit_save,
303 .resume = s3c_gpio_pm_4bit_resume, 303 .resume = samsung_gpio_pm_4bit_resume,
304}; 304};
305#endif /* CONFIG_ARCH_S3C64XX || CONFIG_PLAT_S5P */ 305#endif /* CONFIG_ARCH_S3C64XX || CONFIG_PLAT_S5P */
306 306
307/** 307/**
308 * s3c_pm_save_gpio() - save gpio chip data for suspend 308 * samsung_pm_save_gpio() - save gpio chip data for suspend
309 * @ourchip: The chip for suspend. 309 * @ourchip: The chip for suspend.
310 */ 310 */
311static void s3c_pm_save_gpio(struct s3c_gpio_chip *ourchip) 311static void samsung_pm_save_gpio(struct samsung_gpio_chip *ourchip)
312{ 312{
313 struct s3c_gpio_pm *pm = ourchip->pm; 313 struct samsung_gpio_pm *pm = ourchip->pm;
314 314
315 if (pm == NULL || pm->save == NULL) 315 if (pm == NULL || pm->save == NULL)
316 S3C_PMDBG("%s: no pm for %s\n", __func__, ourchip->chip.label); 316 S3C_PMDBG("%s: no pm for %s\n", __func__, ourchip->chip.label);
@@ -319,24 +319,24 @@ static void s3c_pm_save_gpio(struct s3c_gpio_chip *ourchip)
319} 319}
320 320
321/** 321/**
322 * s3c_pm_save_gpios() - Save the state of the GPIO banks. 322 * samsung_pm_save_gpios() - Save the state of the GPIO banks.
323 * 323 *
324 * For all the GPIO banks, save the state of each one ready for going 324 * For all the GPIO banks, save the state of each one ready for going
325 * into a suspend mode. 325 * into a suspend mode.
326 */ 326 */
327void s3c_pm_save_gpios(void) 327void samsung_pm_save_gpios(void)
328{ 328{
329 struct s3c_gpio_chip *ourchip; 329 struct samsung_gpio_chip *ourchip;
330 unsigned int gpio_nr; 330 unsigned int gpio_nr;
331 331
332 for (gpio_nr = 0; gpio_nr < S3C_GPIO_END;) { 332 for (gpio_nr = 0; gpio_nr < S3C_GPIO_END;) {
333 ourchip = s3c_gpiolib_getchip(gpio_nr); 333 ourchip = samsung_gpiolib_getchip(gpio_nr);
334 if (!ourchip) { 334 if (!ourchip) {
335 gpio_nr++; 335 gpio_nr++;
336 continue; 336 continue;
337 } 337 }
338 338
339 s3c_pm_save_gpio(ourchip); 339 samsung_pm_save_gpio(ourchip);
340 340
341 S3C_PMDBG("%s: save %08x,%08x,%08x,%08x\n", 341 S3C_PMDBG("%s: save %08x,%08x,%08x,%08x\n",
342 ourchip->chip.label, 342 ourchip->chip.label,
@@ -351,12 +351,12 @@ void s3c_pm_save_gpios(void)
351} 351}
352 352
353/** 353/**
354 * s3c_pm_resume_gpio() - restore gpio chip data after suspend 354 * samsung_pm_resume_gpio() - restore gpio chip data after suspend
355 * @ourchip: The suspended chip. 355 * @ourchip: The suspended chip.
356 */ 356 */
357static void s3c_pm_resume_gpio(struct s3c_gpio_chip *ourchip) 357static void samsung_pm_resume_gpio(struct samsung_gpio_chip *ourchip)
358{ 358{
359 struct s3c_gpio_pm *pm = ourchip->pm; 359 struct samsung_gpio_pm *pm = ourchip->pm;
360 360
361 if (pm == NULL || pm->resume == NULL) 361 if (pm == NULL || pm->resume == NULL)
362 S3C_PMDBG("%s: no pm for %s\n", __func__, ourchip->chip.label); 362 S3C_PMDBG("%s: no pm for %s\n", __func__, ourchip->chip.label);
@@ -364,19 +364,19 @@ static void s3c_pm_resume_gpio(struct s3c_gpio_chip *ourchip)
364 pm->resume(ourchip); 364 pm->resume(ourchip);
365} 365}
366 366
367void s3c_pm_restore_gpios(void) 367void samsung_pm_restore_gpios(void)
368{ 368{
369 struct s3c_gpio_chip *ourchip; 369 struct samsung_gpio_chip *ourchip;
370 unsigned int gpio_nr; 370 unsigned int gpio_nr;
371 371
372 for (gpio_nr = 0; gpio_nr < S3C_GPIO_END;) { 372 for (gpio_nr = 0; gpio_nr < S3C_GPIO_END;) {
373 ourchip = s3c_gpiolib_getchip(gpio_nr); 373 ourchip = samsung_gpiolib_getchip(gpio_nr);
374 if (!ourchip) { 374 if (!ourchip) {
375 gpio_nr++; 375 gpio_nr++;
376 continue; 376 continue;
377 } 377 }
378 378
379 s3c_pm_resume_gpio(ourchip); 379 samsung_pm_resume_gpio(ourchip);
380 380
381 gpio_nr += ourchip->chip.ngpio; 381 gpio_nr += ourchip->chip.ngpio;
382 gpio_nr += CONFIG_S3C_GPIO_SPACE; 382 gpio_nr += CONFIG_S3C_GPIO_SPACE;
diff --git a/arch/arm/plat-samsung/pm.c b/arch/arm/plat-samsung/pm.c
index ae6f99834cdd..64ab65f0fdbc 100644
--- a/arch/arm/plat-samsung/pm.c
+++ b/arch/arm/plat-samsung/pm.c
@@ -268,8 +268,8 @@ static int s3c_pm_enter(suspend_state_t state)
268 268
269 /* save all necessary core registers not covered by the drivers */ 269 /* save all necessary core registers not covered by the drivers */
270 270
271 s3c_pm_save_gpios(); 271 samsung_pm_save_gpios();
272 s3c_pm_saved_gpios(); 272 samsung_pm_saved_gpios();
273 s3c_pm_save_uarts(); 273 s3c_pm_save_uarts();
274 s3c_pm_save_core(); 274 s3c_pm_save_core();
275 275
@@ -306,7 +306,7 @@ static int s3c_pm_enter(suspend_state_t state)
306 306
307 s3c_pm_restore_core(); 307 s3c_pm_restore_core();
308 s3c_pm_restore_uarts(); 308 s3c_pm_restore_uarts();
309 s3c_pm_restore_gpios(); 309 samsung_pm_restore_gpios();
310 s3c_pm_restored_gpios(); 310 s3c_pm_restored_gpios();
311 311
312 s3c_pm_debug_init(); 312 s3c_pm_debug_init();
diff --git a/arch/arm/plat-samsung/s3c-dma-ops.c b/arch/arm/plat-samsung/s3c-dma-ops.c
new file mode 100644
index 000000000000..582333c70585
--- /dev/null
+++ b/arch/arm/plat-samsung/s3c-dma-ops.c
@@ -0,0 +1,130 @@
1/* linux/arch/arm/plat-samsung/s3c-dma-ops.c
2 *
3 * Copyright (c) 2011 Samsung Electronics Co., Ltd.
4 * http://www.samsung.com
5 *
6 * Samsung S3C-DMA Operations
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 */
12
13#include <linux/kernel.h>
14#include <linux/errno.h>
15#include <linux/slab.h>
16#include <linux/types.h>
17
18#include <mach/dma.h>
19
20struct cb_data {
21 void (*fp) (void *);
22 void *fp_param;
23 unsigned ch;
24 struct list_head node;
25};
26
27static LIST_HEAD(dma_list);
28
29static void s3c_dma_cb(struct s3c2410_dma_chan *channel, void *param,
30 int size, enum s3c2410_dma_buffresult res)
31{
32 struct cb_data *data = param;
33
34 data->fp(data->fp_param);
35}
36
37static unsigned s3c_dma_request(enum dma_ch dma_ch,
38 struct samsung_dma_info *info)
39{
40 struct cb_data *data;
41
42 if (s3c2410_dma_request(dma_ch, info->client, NULL) < 0) {
43 s3c2410_dma_free(dma_ch, info->client);
44 return 0;
45 }
46
47 data = kzalloc(sizeof(struct cb_data), GFP_KERNEL);
48 data->ch = dma_ch;
49 list_add_tail(&data->node, &dma_list);
50
51 s3c2410_dma_devconfig(dma_ch, info->direction, info->fifo);
52
53 if (info->cap == DMA_CYCLIC)
54 s3c2410_dma_setflags(dma_ch, S3C2410_DMAF_CIRCULAR);
55
56 s3c2410_dma_config(dma_ch, info->width);
57
58 return (unsigned)dma_ch;
59}
60
61static int s3c_dma_release(unsigned ch, struct s3c2410_dma_client *client)
62{
63 struct cb_data *data;
64
65 list_for_each_entry(data, &dma_list, node)
66 if (data->ch == ch)
67 break;
68 list_del(&data->node);
69
70 s3c2410_dma_free(ch, client);
71 kfree(data);
72
73 return 0;
74}
75
76static int s3c_dma_prepare(unsigned ch, struct samsung_dma_prep_info *info)
77{
78 struct cb_data *data;
79 int len = (info->cap == DMA_CYCLIC) ? info->period : info->len;
80
81 list_for_each_entry(data, &dma_list, node)
82 if (data->ch == ch)
83 break;
84
85 if (!data->fp) {
86 s3c2410_dma_set_buffdone_fn(ch, s3c_dma_cb);
87 data->fp = info->fp;
88 data->fp_param = info->fp_param;
89 }
90
91 s3c2410_dma_enqueue(ch, (void *)data, info->buf, len);
92
93 return 0;
94}
95
96static inline int s3c_dma_trigger(unsigned ch)
97{
98 return s3c2410_dma_ctrl(ch, S3C2410_DMAOP_START);
99}
100
101static inline int s3c_dma_started(unsigned ch)
102{
103 return s3c2410_dma_ctrl(ch, S3C2410_DMAOP_STARTED);
104}
105
106static inline int s3c_dma_flush(unsigned ch)
107{
108 return s3c2410_dma_ctrl(ch, S3C2410_DMAOP_FLUSH);
109}
110
111static inline int s3c_dma_stop(unsigned ch)
112{
113 return s3c2410_dma_ctrl(ch, S3C2410_DMAOP_STOP);
114}
115
116static struct samsung_dma_ops s3c_dma_ops = {
117 .request = s3c_dma_request,
118 .release = s3c_dma_release,
119 .prepare = s3c_dma_prepare,
120 .trigger = s3c_dma_trigger,
121 .started = s3c_dma_started,
122 .flush = s3c_dma_flush,
123 .stop = s3c_dma_stop,
124};
125
126void *s3c_dma_get_ops(void)
127{
128 return &s3c_dma_ops;
129}
130EXPORT_SYMBOL(s3c_dma_get_ops);
diff --git a/arch/arm/plat-samsung/s3c-pl330.c b/arch/arm/plat-samsung/s3c-pl330.c
deleted file mode 100644
index f85638c6f5ae..000000000000
--- a/arch/arm/plat-samsung/s3c-pl330.c
+++ /dev/null
@@ -1,1244 +0,0 @@
1/* linux/arch/arm/plat-samsung/s3c-pl330.c
2 *
3 * Copyright (C) 2010 Samsung Electronics Co. Ltd.
4 * Jaswinder Singh <jassi.brar@samsung.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 */
11
12#include <linux/init.h>
13#include <linux/module.h>
14#include <linux/interrupt.h>
15#include <linux/io.h>
16#include <linux/slab.h>
17#include <linux/platform_device.h>
18#include <linux/clk.h>
19#include <linux/err.h>
20
21#include <asm/hardware/pl330.h>
22
23#include <plat/s3c-pl330-pdata.h>
24
25/**
26 * struct s3c_pl330_dmac - Logical representation of a PL330 DMAC.
27 * @busy_chan: Number of channels currently busy.
28 * @peri: List of IDs of peripherals this DMAC can work with.
29 * @node: To attach to the global list of DMACs.
30 * @pi: PL330 configuration info for the DMAC.
31 * @kmcache: Pool to quickly allocate xfers for all channels in the dmac.
32 * @clk: Pointer of DMAC operation clock.
33 */
34struct s3c_pl330_dmac {
35 unsigned busy_chan;
36 enum dma_ch *peri;
37 struct list_head node;
38 struct pl330_info *pi;
39 struct kmem_cache *kmcache;
40 struct clk *clk;
41};
42
43/**
44 * struct s3c_pl330_xfer - A request submitted by S3C DMA clients.
45 * @token: Xfer ID provided by the client.
46 * @node: To attach to the list of xfers on a channel.
47 * @px: Xfer for PL330 core.
48 * @chan: Owner channel of this xfer.
49 */
50struct s3c_pl330_xfer {
51 void *token;
52 struct list_head node;
53 struct pl330_xfer px;
54 struct s3c_pl330_chan *chan;
55};
56
57/**
58 * struct s3c_pl330_chan - Logical channel to communicate with
59 * a Physical peripheral.
60 * @pl330_chan_id: Token of a hardware channel thread of PL330 DMAC.
61 * NULL if the channel is available to be acquired.
62 * @id: ID of the peripheral that this channel can communicate with.
63 * @options: Options specified by the client.
64 * @sdaddr: Address provided via s3c2410_dma_devconfig.
65 * @node: To attach to the global list of channels.
66 * @lrq: Pointer to the last submitted pl330_req to PL330 core.
67 * @xfer_list: To manage list of xfers enqueued.
68 * @req: Two requests to communicate with the PL330 engine.
69 * @callback_fn: Callback function to the client.
70 * @rqcfg: Channel configuration for the xfers.
71 * @xfer_head: Pointer to the xfer to be next executed.
72 * @dmac: Pointer to the DMAC that manages this channel, NULL if the
73 * channel is available to be acquired.
74 * @client: Client of this channel. NULL if the
75 * channel is available to be acquired.
76 */
77struct s3c_pl330_chan {
78 void *pl330_chan_id;
79 enum dma_ch id;
80 unsigned int options;
81 unsigned long sdaddr;
82 struct list_head node;
83 struct pl330_req *lrq;
84 struct list_head xfer_list;
85 struct pl330_req req[2];
86 s3c2410_dma_cbfn_t callback_fn;
87 struct pl330_reqcfg rqcfg;
88 struct s3c_pl330_xfer *xfer_head;
89 struct s3c_pl330_dmac *dmac;
90 struct s3c2410_dma_client *client;
91};
92
93/* All DMACs in the platform */
94static LIST_HEAD(dmac_list);
95
96/* All channels to peripherals in the platform */
97static LIST_HEAD(chan_list);
98
99/*
100 * Since we add resources(DMACs and Channels) to the global pool,
101 * we need to guard access to the resources using a global lock
102 */
103static DEFINE_SPINLOCK(res_lock);
104
105/* Returns the channel with ID 'id' in the chan_list */
106static struct s3c_pl330_chan *id_to_chan(const enum dma_ch id)
107{
108 struct s3c_pl330_chan *ch;
109
110 list_for_each_entry(ch, &chan_list, node)
111 if (ch->id == id)
112 return ch;
113
114 return NULL;
115}
116
117/* Allocate a new channel with ID 'id' and add to chan_list */
118static void chan_add(const enum dma_ch id)
119{
120 struct s3c_pl330_chan *ch = id_to_chan(id);
121
122 /* Return if the channel already exists */
123 if (ch)
124 return;
125
126 ch = kmalloc(sizeof(*ch), GFP_KERNEL);
127 /* Return silently to work with other channels */
128 if (!ch)
129 return;
130
131 ch->id = id;
132 ch->dmac = NULL;
133
134 list_add_tail(&ch->node, &chan_list);
135}
136
137/* If the channel is not yet acquired by any client */
138static bool chan_free(struct s3c_pl330_chan *ch)
139{
140 if (!ch)
141 return false;
142
143 /* Channel points to some DMAC only when it's acquired */
144 return ch->dmac ? false : true;
145}
146
147/*
148 * Returns 0 is peripheral i/f is invalid or not present on the dmac.
149 * Index + 1, otherwise.
150 */
151static unsigned iface_of_dmac(struct s3c_pl330_dmac *dmac, enum dma_ch ch_id)
152{
153 enum dma_ch *id = dmac->peri;
154 int i;
155
156 /* Discount invalid markers */
157 if (ch_id == DMACH_MAX)
158 return 0;
159
160 for (i = 0; i < PL330_MAX_PERI; i++)
161 if (id[i] == ch_id)
162 return i + 1;
163
164 return 0;
165}
166
167/* If all channel threads of the DMAC are busy */
168static inline bool dmac_busy(struct s3c_pl330_dmac *dmac)
169{
170 struct pl330_info *pi = dmac->pi;
171
172 return (dmac->busy_chan < pi->pcfg.num_chan) ? false : true;
173}
174
175/*
176 * Returns the number of free channels that
177 * can be handled by this dmac only.
178 */
179static unsigned ch_onlyby_dmac(struct s3c_pl330_dmac *dmac)
180{
181 enum dma_ch *id = dmac->peri;
182 struct s3c_pl330_dmac *d;
183 struct s3c_pl330_chan *ch;
184 unsigned found, count = 0;
185 enum dma_ch p;
186 int i;
187
188 for (i = 0; i < PL330_MAX_PERI; i++) {
189 p = id[i];
190 ch = id_to_chan(p);
191
192 if (p == DMACH_MAX || !chan_free(ch))
193 continue;
194
195 found = 0;
196 list_for_each_entry(d, &dmac_list, node) {
197 if (d != dmac && iface_of_dmac(d, ch->id)) {
198 found = 1;
199 break;
200 }
201 }
202 if (!found)
203 count++;
204 }
205
206 return count;
207}
208
209/*
210 * Measure of suitability of 'dmac' handling 'ch'
211 *
212 * 0 indicates 'dmac' can not handle 'ch' either
213 * because it is not supported by the hardware or
214 * because all dmac channels are currently busy.
215 *
216 * >0 vlaue indicates 'dmac' has the capability.
217 * The bigger the value the more suitable the dmac.
218 */
219#define MAX_SUIT UINT_MAX
220#define MIN_SUIT 0
221
222static unsigned suitablility(struct s3c_pl330_dmac *dmac,
223 struct s3c_pl330_chan *ch)
224{
225 struct pl330_info *pi = dmac->pi;
226 enum dma_ch *id = dmac->peri;
227 struct s3c_pl330_dmac *d;
228 unsigned s;
229 int i;
230
231 s = MIN_SUIT;
232 /* If all the DMAC channel threads are busy */
233 if (dmac_busy(dmac))
234 return s;
235
236 for (i = 0; i < PL330_MAX_PERI; i++)
237 if (id[i] == ch->id)
238 break;
239
240 /* If the 'dmac' can't talk to 'ch' */
241 if (i == PL330_MAX_PERI)
242 return s;
243
244 s = MAX_SUIT;
245 list_for_each_entry(d, &dmac_list, node) {
246 /*
247 * If some other dmac can talk to this
248 * peri and has some channel free.
249 */
250 if (d != dmac && iface_of_dmac(d, ch->id) && !dmac_busy(d)) {
251 s = 0;
252 break;
253 }
254 }
255 if (s)
256 return s;
257
258 s = 100;
259
260 /* Good if free chans are more, bad otherwise */
261 s += (pi->pcfg.num_chan - dmac->busy_chan) - ch_onlyby_dmac(dmac);
262
263 return s;
264}
265
266/* More than one DMAC may have capability to transfer data with the
267 * peripheral. This function assigns most suitable DMAC to manage the
268 * channel and hence communicate with the peripheral.
269 */
270static struct s3c_pl330_dmac *map_chan_to_dmac(struct s3c_pl330_chan *ch)
271{
272 struct s3c_pl330_dmac *d, *dmac = NULL;
273 unsigned sn, sl = MIN_SUIT;
274
275 list_for_each_entry(d, &dmac_list, node) {
276 sn = suitablility(d, ch);
277
278 if (sn == MAX_SUIT)
279 return d;
280
281 if (sn > sl)
282 dmac = d;
283 }
284
285 return dmac;
286}
287
288/* Acquire the channel for peripheral 'id' */
289static struct s3c_pl330_chan *chan_acquire(const enum dma_ch id)
290{
291 struct s3c_pl330_chan *ch = id_to_chan(id);
292 struct s3c_pl330_dmac *dmac;
293
294 /* If the channel doesn't exist or is already acquired */
295 if (!ch || !chan_free(ch)) {
296 ch = NULL;
297 goto acq_exit;
298 }
299
300 dmac = map_chan_to_dmac(ch);
301 /* If couldn't map */
302 if (!dmac) {
303 ch = NULL;
304 goto acq_exit;
305 }
306
307 dmac->busy_chan++;
308 ch->dmac = dmac;
309
310acq_exit:
311 return ch;
312}
313
314/* Delete xfer from the queue */
315static inline void del_from_queue(struct s3c_pl330_xfer *xfer)
316{
317 struct s3c_pl330_xfer *t;
318 struct s3c_pl330_chan *ch;
319 int found;
320
321 if (!xfer)
322 return;
323
324 ch = xfer->chan;
325
326 /* Make sure xfer is in the queue */
327 found = 0;
328 list_for_each_entry(t, &ch->xfer_list, node)
329 if (t == xfer) {
330 found = 1;
331 break;
332 }
333
334 if (!found)
335 return;
336
337 /* If xfer is last entry in the queue */
338 if (xfer->node.next == &ch->xfer_list)
339 t = list_entry(ch->xfer_list.next,
340 struct s3c_pl330_xfer, node);
341 else
342 t = list_entry(xfer->node.next,
343 struct s3c_pl330_xfer, node);
344
345 /* If there was only one node left */
346 if (t == xfer)
347 ch->xfer_head = NULL;
348 else if (ch->xfer_head == xfer)
349 ch->xfer_head = t;
350
351 list_del(&xfer->node);
352}
353
354/* Provides pointer to the next xfer in the queue.
355 * If CIRCULAR option is set, the list is left intact,
356 * otherwise the xfer is removed from the list.
357 * Forced delete 'pluck' can be set to override the CIRCULAR option.
358 */
359static struct s3c_pl330_xfer *get_from_queue(struct s3c_pl330_chan *ch,
360 int pluck)
361{
362 struct s3c_pl330_xfer *xfer = ch->xfer_head;
363
364 if (!xfer)
365 return NULL;
366
367 /* If xfer is last entry in the queue */
368 if (xfer->node.next == &ch->xfer_list)
369 ch->xfer_head = list_entry(ch->xfer_list.next,
370 struct s3c_pl330_xfer, node);
371 else
372 ch->xfer_head = list_entry(xfer->node.next,
373 struct s3c_pl330_xfer, node);
374
375 if (pluck || !(ch->options & S3C2410_DMAF_CIRCULAR))
376 del_from_queue(xfer);
377
378 return xfer;
379}
380
381static inline void add_to_queue(struct s3c_pl330_chan *ch,
382 struct s3c_pl330_xfer *xfer, int front)
383{
384 struct pl330_xfer *xt;
385
386 /* If queue empty */
387 if (ch->xfer_head == NULL)
388 ch->xfer_head = xfer;
389
390 xt = &ch->xfer_head->px;
391 /* If the head already submitted (CIRCULAR head) */
392 if (ch->options & S3C2410_DMAF_CIRCULAR &&
393 (xt == ch->req[0].x || xt == ch->req[1].x))
394 ch->xfer_head = xfer;
395
396 /* If this is a resubmission, it should go at the head */
397 if (front) {
398 ch->xfer_head = xfer;
399 list_add(&xfer->node, &ch->xfer_list);
400 } else {
401 list_add_tail(&xfer->node, &ch->xfer_list);
402 }
403}
404
405static inline void _finish_off(struct s3c_pl330_xfer *xfer,
406 enum s3c2410_dma_buffresult res, int ffree)
407{
408 struct s3c_pl330_chan *ch;
409
410 if (!xfer)
411 return;
412
413 ch = xfer->chan;
414
415 /* Do callback */
416 if (ch->callback_fn)
417 ch->callback_fn(NULL, xfer->token, xfer->px.bytes, res);
418
419 /* Force Free or if buffer is not needed anymore */
420 if (ffree || !(ch->options & S3C2410_DMAF_CIRCULAR))
421 kmem_cache_free(ch->dmac->kmcache, xfer);
422}
423
424static inline int s3c_pl330_submit(struct s3c_pl330_chan *ch,
425 struct pl330_req *r)
426{
427 struct s3c_pl330_xfer *xfer;
428 int ret = 0;
429
430 /* If already submitted */
431 if (r->x)
432 return 0;
433
434 xfer = get_from_queue(ch, 0);
435 if (xfer) {
436 r->x = &xfer->px;
437
438 /* Use max bandwidth for M<->M xfers */
439 if (r->rqtype == MEMTOMEM) {
440 struct pl330_info *pi = xfer->chan->dmac->pi;
441 int burst = 1 << ch->rqcfg.brst_size;
442 u32 bytes = r->x->bytes;
443 int bl;
444
445 bl = pi->pcfg.data_bus_width / 8;
446 bl *= pi->pcfg.data_buf_dep;
447 bl /= burst;
448
449 /* src/dst_burst_len can't be more than 16 */
450 if (bl > 16)
451 bl = 16;
452
453 while (bl > 1) {
454 if (!(bytes % (bl * burst)))
455 break;
456 bl--;
457 }
458
459 ch->rqcfg.brst_len = bl;
460 } else {
461 ch->rqcfg.brst_len = 1;
462 }
463
464 ret = pl330_submit_req(ch->pl330_chan_id, r);
465
466 /* If submission was successful */
467 if (!ret) {
468 ch->lrq = r; /* latest submitted req */
469 return 0;
470 }
471
472 r->x = NULL;
473
474 /* If both of the PL330 ping-pong buffers filled */
475 if (ret == -EAGAIN) {
476 dev_err(ch->dmac->pi->dev, "%s:%d!\n",
477 __func__, __LINE__);
478 /* Queue back again */
479 add_to_queue(ch, xfer, 1);
480 ret = 0;
481 } else {
482 dev_err(ch->dmac->pi->dev, "%s:%d!\n",
483 __func__, __LINE__);
484 _finish_off(xfer, S3C2410_RES_ERR, 0);
485 }
486 }
487
488 return ret;
489}
490
491static void s3c_pl330_rq(struct s3c_pl330_chan *ch,
492 struct pl330_req *r, enum pl330_op_err err)
493{
494 unsigned long flags;
495 struct s3c_pl330_xfer *xfer;
496 struct pl330_xfer *xl = r->x;
497 enum s3c2410_dma_buffresult res;
498
499 spin_lock_irqsave(&res_lock, flags);
500
501 r->x = NULL;
502
503 s3c_pl330_submit(ch, r);
504
505 spin_unlock_irqrestore(&res_lock, flags);
506
507 /* Map result to S3C DMA API */
508 if (err == PL330_ERR_NONE)
509 res = S3C2410_RES_OK;
510 else if (err == PL330_ERR_ABORT)
511 res = S3C2410_RES_ABORT;
512 else
513 res = S3C2410_RES_ERR;
514
515 /* If last request had some xfer */
516 if (xl) {
517 xfer = container_of(xl, struct s3c_pl330_xfer, px);
518 _finish_off(xfer, res, 0);
519 } else {
520 dev_info(ch->dmac->pi->dev, "%s:%d No Xfer?!\n",
521 __func__, __LINE__);
522 }
523}
524
525static void s3c_pl330_rq0(void *token, enum pl330_op_err err)
526{
527 struct pl330_req *r = token;
528 struct s3c_pl330_chan *ch = container_of(r,
529 struct s3c_pl330_chan, req[0]);
530 s3c_pl330_rq(ch, r, err);
531}
532
533static void s3c_pl330_rq1(void *token, enum pl330_op_err err)
534{
535 struct pl330_req *r = token;
536 struct s3c_pl330_chan *ch = container_of(r,
537 struct s3c_pl330_chan, req[1]);
538 s3c_pl330_rq(ch, r, err);
539}
540
541/* Release an acquired channel */
542static void chan_release(struct s3c_pl330_chan *ch)
543{
544 struct s3c_pl330_dmac *dmac;
545
546 if (chan_free(ch))
547 return;
548
549 dmac = ch->dmac;
550 ch->dmac = NULL;
551 dmac->busy_chan--;
552}
553
554int s3c2410_dma_ctrl(enum dma_ch id, enum s3c2410_chan_op op)
555{
556 struct s3c_pl330_xfer *xfer;
557 enum pl330_chan_op pl330op;
558 struct s3c_pl330_chan *ch;
559 unsigned long flags;
560 int idx, ret;
561
562 spin_lock_irqsave(&res_lock, flags);
563
564 ch = id_to_chan(id);
565
566 if (!ch || chan_free(ch)) {
567 ret = -EINVAL;
568 goto ctrl_exit;
569 }
570
571 switch (op) {
572 case S3C2410_DMAOP_START:
573 /* Make sure both reqs are enqueued */
574 idx = (ch->lrq == &ch->req[0]) ? 1 : 0;
575 s3c_pl330_submit(ch, &ch->req[idx]);
576 s3c_pl330_submit(ch, &ch->req[1 - idx]);
577 pl330op = PL330_OP_START;
578 break;
579
580 case S3C2410_DMAOP_STOP:
581 pl330op = PL330_OP_ABORT;
582 break;
583
584 case S3C2410_DMAOP_FLUSH:
585 pl330op = PL330_OP_FLUSH;
586 break;
587
588 case S3C2410_DMAOP_PAUSE:
589 case S3C2410_DMAOP_RESUME:
590 case S3C2410_DMAOP_TIMEOUT:
591 case S3C2410_DMAOP_STARTED:
592 spin_unlock_irqrestore(&res_lock, flags);
593 return 0;
594
595 default:
596 spin_unlock_irqrestore(&res_lock, flags);
597 return -EINVAL;
598 }
599
600 ret = pl330_chan_ctrl(ch->pl330_chan_id, pl330op);
601
602 if (pl330op == PL330_OP_START) {
603 spin_unlock_irqrestore(&res_lock, flags);
604 return ret;
605 }
606
607 idx = (ch->lrq == &ch->req[0]) ? 1 : 0;
608
609 /* Abort the current xfer */
610 if (ch->req[idx].x) {
611 xfer = container_of(ch->req[idx].x,
612 struct s3c_pl330_xfer, px);
613
614 /* Drop xfer during FLUSH */
615 if (pl330op == PL330_OP_FLUSH)
616 del_from_queue(xfer);
617
618 ch->req[idx].x = NULL;
619
620 spin_unlock_irqrestore(&res_lock, flags);
621 _finish_off(xfer, S3C2410_RES_ABORT,
622 pl330op == PL330_OP_FLUSH ? 1 : 0);
623 spin_lock_irqsave(&res_lock, flags);
624 }
625
626 /* Flush the whole queue */
627 if (pl330op == PL330_OP_FLUSH) {
628
629 if (ch->req[1 - idx].x) {
630 xfer = container_of(ch->req[1 - idx].x,
631 struct s3c_pl330_xfer, px);
632
633 del_from_queue(xfer);
634
635 ch->req[1 - idx].x = NULL;
636
637 spin_unlock_irqrestore(&res_lock, flags);
638 _finish_off(xfer, S3C2410_RES_ABORT, 1);
639 spin_lock_irqsave(&res_lock, flags);
640 }
641
642 /* Finish off the remaining in the queue */
643 xfer = ch->xfer_head;
644 while (xfer) {
645
646 del_from_queue(xfer);
647
648 spin_unlock_irqrestore(&res_lock, flags);
649 _finish_off(xfer, S3C2410_RES_ABORT, 1);
650 spin_lock_irqsave(&res_lock, flags);
651
652 xfer = ch->xfer_head;
653 }
654 }
655
656ctrl_exit:
657 spin_unlock_irqrestore(&res_lock, flags);
658
659 return ret;
660}
661EXPORT_SYMBOL(s3c2410_dma_ctrl);
662
663int s3c2410_dma_enqueue(enum dma_ch id, void *token,
664 dma_addr_t addr, int size)
665{
666 struct s3c_pl330_chan *ch;
667 struct s3c_pl330_xfer *xfer;
668 unsigned long flags;
669 int idx, ret = 0;
670
671 spin_lock_irqsave(&res_lock, flags);
672
673 ch = id_to_chan(id);
674
675 /* Error if invalid or free channel */
676 if (!ch || chan_free(ch)) {
677 ret = -EINVAL;
678 goto enq_exit;
679 }
680
681 /* Error if size is unaligned */
682 if (ch->rqcfg.brst_size && size % (1 << ch->rqcfg.brst_size)) {
683 ret = -EINVAL;
684 goto enq_exit;
685 }
686
687 xfer = kmem_cache_alloc(ch->dmac->kmcache, GFP_ATOMIC);
688 if (!xfer) {
689 ret = -ENOMEM;
690 goto enq_exit;
691 }
692
693 xfer->token = token;
694 xfer->chan = ch;
695 xfer->px.bytes = size;
696 xfer->px.next = NULL; /* Single request */
697
698 /* For S3C DMA API, direction is always fixed for all xfers */
699 if (ch->req[0].rqtype == MEMTODEV) {
700 xfer->px.src_addr = addr;
701 xfer->px.dst_addr = ch->sdaddr;
702 } else {
703 xfer->px.src_addr = ch->sdaddr;
704 xfer->px.dst_addr = addr;
705 }
706
707 add_to_queue(ch, xfer, 0);
708
709 /* Try submitting on either request */
710 idx = (ch->lrq == &ch->req[0]) ? 1 : 0;
711
712 if (!ch->req[idx].x)
713 s3c_pl330_submit(ch, &ch->req[idx]);
714 else
715 s3c_pl330_submit(ch, &ch->req[1 - idx]);
716
717 spin_unlock_irqrestore(&res_lock, flags);
718
719 if (ch->options & S3C2410_DMAF_AUTOSTART)
720 s3c2410_dma_ctrl(id, S3C2410_DMAOP_START);
721
722 return 0;
723
724enq_exit:
725 spin_unlock_irqrestore(&res_lock, flags);
726
727 return ret;
728}
729EXPORT_SYMBOL(s3c2410_dma_enqueue);
730
731int s3c2410_dma_request(enum dma_ch id,
732 struct s3c2410_dma_client *client,
733 void *dev)
734{
735 struct s3c_pl330_dmac *dmac;
736 struct s3c_pl330_chan *ch;
737 unsigned long flags;
738 int ret = 0;
739
740 spin_lock_irqsave(&res_lock, flags);
741
742 ch = chan_acquire(id);
743 if (!ch) {
744 ret = -EBUSY;
745 goto req_exit;
746 }
747
748 dmac = ch->dmac;
749
750 ch->pl330_chan_id = pl330_request_channel(dmac->pi);
751 if (!ch->pl330_chan_id) {
752 chan_release(ch);
753 ret = -EBUSY;
754 goto req_exit;
755 }
756
757 ch->client = client;
758 ch->options = 0; /* Clear any option */
759 ch->callback_fn = NULL; /* Clear any callback */
760 ch->lrq = NULL;
761
762 ch->rqcfg.brst_size = 2; /* Default word size */
763 ch->rqcfg.swap = SWAP_NO;
764 ch->rqcfg.scctl = SCCTRL0; /* Noncacheable and nonbufferable */
765 ch->rqcfg.dcctl = DCCTRL0; /* Noncacheable and nonbufferable */
766 ch->rqcfg.privileged = 0;
767 ch->rqcfg.insnaccess = 0;
768
769 /* Set invalid direction */
770 ch->req[0].rqtype = DEVTODEV;
771 ch->req[1].rqtype = ch->req[0].rqtype;
772
773 ch->req[0].cfg = &ch->rqcfg;
774 ch->req[1].cfg = ch->req[0].cfg;
775
776 ch->req[0].peri = iface_of_dmac(dmac, id) - 1; /* Original index */
777 ch->req[1].peri = ch->req[0].peri;
778
779 ch->req[0].token = &ch->req[0];
780 ch->req[0].xfer_cb = s3c_pl330_rq0;
781 ch->req[1].token = &ch->req[1];
782 ch->req[1].xfer_cb = s3c_pl330_rq1;
783
784 ch->req[0].x = NULL;
785 ch->req[1].x = NULL;
786
787 /* Reset xfer list */
788 INIT_LIST_HEAD(&ch->xfer_list);
789 ch->xfer_head = NULL;
790
791req_exit:
792 spin_unlock_irqrestore(&res_lock, flags);
793
794 return ret;
795}
796EXPORT_SYMBOL(s3c2410_dma_request);
797
798int s3c2410_dma_free(enum dma_ch id, struct s3c2410_dma_client *client)
799{
800 struct s3c_pl330_chan *ch;
801 struct s3c_pl330_xfer *xfer;
802 unsigned long flags;
803 int ret = 0;
804 unsigned idx;
805
806 spin_lock_irqsave(&res_lock, flags);
807
808 ch = id_to_chan(id);
809
810 if (!ch || chan_free(ch))
811 goto free_exit;
812
813 /* Refuse if someone else wanted to free the channel */
814 if (ch->client != client) {
815 ret = -EBUSY;
816 goto free_exit;
817 }
818
819 /* Stop any active xfer, Flushe the queue and do callbacks */
820 pl330_chan_ctrl(ch->pl330_chan_id, PL330_OP_FLUSH);
821
822 /* Abort the submitted requests */
823 idx = (ch->lrq == &ch->req[0]) ? 1 : 0;
824
825 if (ch->req[idx].x) {
826 xfer = container_of(ch->req[idx].x,
827 struct s3c_pl330_xfer, px);
828
829 ch->req[idx].x = NULL;
830 del_from_queue(xfer);
831
832 spin_unlock_irqrestore(&res_lock, flags);
833 _finish_off(xfer, S3C2410_RES_ABORT, 1);
834 spin_lock_irqsave(&res_lock, flags);
835 }
836
837 if (ch->req[1 - idx].x) {
838 xfer = container_of(ch->req[1 - idx].x,
839 struct s3c_pl330_xfer, px);
840
841 ch->req[1 - idx].x = NULL;
842 del_from_queue(xfer);
843
844 spin_unlock_irqrestore(&res_lock, flags);
845 _finish_off(xfer, S3C2410_RES_ABORT, 1);
846 spin_lock_irqsave(&res_lock, flags);
847 }
848
849 /* Pluck and Abort the queued requests in order */
850 do {
851 xfer = get_from_queue(ch, 1);
852
853 spin_unlock_irqrestore(&res_lock, flags);
854 _finish_off(xfer, S3C2410_RES_ABORT, 1);
855 spin_lock_irqsave(&res_lock, flags);
856 } while (xfer);
857
858 ch->client = NULL;
859
860 pl330_release_channel(ch->pl330_chan_id);
861
862 ch->pl330_chan_id = NULL;
863
864 chan_release(ch);
865
866free_exit:
867 spin_unlock_irqrestore(&res_lock, flags);
868
869 return ret;
870}
871EXPORT_SYMBOL(s3c2410_dma_free);
872
873int s3c2410_dma_config(enum dma_ch id, int xferunit)
874{
875 struct s3c_pl330_chan *ch;
876 struct pl330_info *pi;
877 unsigned long flags;
878 int i, dbwidth, ret = 0;
879
880 spin_lock_irqsave(&res_lock, flags);
881
882 ch = id_to_chan(id);
883
884 if (!ch || chan_free(ch)) {
885 ret = -EINVAL;
886 goto cfg_exit;
887 }
888
889 pi = ch->dmac->pi;
890 dbwidth = pi->pcfg.data_bus_width / 8;
891
892 /* Max size of xfer can be pcfg.data_bus_width */
893 if (xferunit > dbwidth) {
894 ret = -EINVAL;
895 goto cfg_exit;
896 }
897
898 i = 0;
899 while (xferunit != (1 << i))
900 i++;
901
902 /* If valid value */
903 if (xferunit == (1 << i))
904 ch->rqcfg.brst_size = i;
905 else
906 ret = -EINVAL;
907
908cfg_exit:
909 spin_unlock_irqrestore(&res_lock, flags);
910
911 return ret;
912}
913EXPORT_SYMBOL(s3c2410_dma_config);
914
915/* Options that are supported by this driver */
916#define S3C_PL330_FLAGS (S3C2410_DMAF_CIRCULAR | S3C2410_DMAF_AUTOSTART)
917
918int s3c2410_dma_setflags(enum dma_ch id, unsigned int options)
919{
920 struct s3c_pl330_chan *ch;
921 unsigned long flags;
922 int ret = 0;
923
924 spin_lock_irqsave(&res_lock, flags);
925
926 ch = id_to_chan(id);
927
928 if (!ch || chan_free(ch) || options & ~(S3C_PL330_FLAGS))
929 ret = -EINVAL;
930 else
931 ch->options = options;
932
933 spin_unlock_irqrestore(&res_lock, flags);
934
935 return 0;
936}
937EXPORT_SYMBOL(s3c2410_dma_setflags);
938
939int s3c2410_dma_set_buffdone_fn(enum dma_ch id, s3c2410_dma_cbfn_t rtn)
940{
941 struct s3c_pl330_chan *ch;
942 unsigned long flags;
943 int ret = 0;
944
945 spin_lock_irqsave(&res_lock, flags);
946
947 ch = id_to_chan(id);
948
949 if (!ch || chan_free(ch))
950 ret = -EINVAL;
951 else
952 ch->callback_fn = rtn;
953
954 spin_unlock_irqrestore(&res_lock, flags);
955
956 return ret;
957}
958EXPORT_SYMBOL(s3c2410_dma_set_buffdone_fn);
959
960int s3c2410_dma_devconfig(enum dma_ch id, enum s3c2410_dmasrc source,
961 unsigned long address)
962{
963 struct s3c_pl330_chan *ch;
964 unsigned long flags;
965 int ret = 0;
966
967 spin_lock_irqsave(&res_lock, flags);
968
969 ch = id_to_chan(id);
970
971 if (!ch || chan_free(ch)) {
972 ret = -EINVAL;
973 goto devcfg_exit;
974 }
975
976 switch (source) {
977 case S3C2410_DMASRC_HW: /* P->M */
978 ch->req[0].rqtype = DEVTOMEM;
979 ch->req[1].rqtype = DEVTOMEM;
980 ch->rqcfg.src_inc = 0;
981 ch->rqcfg.dst_inc = 1;
982 break;
983 case S3C2410_DMASRC_MEM: /* M->P */
984 ch->req[0].rqtype = MEMTODEV;
985 ch->req[1].rqtype = MEMTODEV;
986 ch->rqcfg.src_inc = 1;
987 ch->rqcfg.dst_inc = 0;
988 break;
989 default:
990 ret = -EINVAL;
991 goto devcfg_exit;
992 }
993
994 ch->sdaddr = address;
995
996devcfg_exit:
997 spin_unlock_irqrestore(&res_lock, flags);
998
999 return ret;
1000}
1001EXPORT_SYMBOL(s3c2410_dma_devconfig);
1002
1003int s3c2410_dma_getposition(enum dma_ch id, dma_addr_t *src, dma_addr_t *dst)
1004{
1005 struct s3c_pl330_chan *ch = id_to_chan(id);
1006 struct pl330_chanstatus status;
1007 int ret;
1008
1009 if (!ch || chan_free(ch))
1010 return -EINVAL;
1011
1012 ret = pl330_chan_status(ch->pl330_chan_id, &status);
1013 if (ret < 0)
1014 return ret;
1015
1016 *src = status.src_addr;
1017 *dst = status.dst_addr;
1018
1019 return 0;
1020}
1021EXPORT_SYMBOL(s3c2410_dma_getposition);
1022
1023static irqreturn_t pl330_irq_handler(int irq, void *data)
1024{
1025 if (pl330_update(data))
1026 return IRQ_HANDLED;
1027 else
1028 return IRQ_NONE;
1029}
1030
1031static int pl330_probe(struct platform_device *pdev)
1032{
1033 struct s3c_pl330_dmac *s3c_pl330_dmac;
1034 struct s3c_pl330_platdata *pl330pd;
1035 struct pl330_info *pl330_info;
1036 struct resource *res;
1037 int i, ret, irq;
1038
1039 pl330pd = pdev->dev.platform_data;
1040
1041 /* Can't do without the list of _32_ peripherals */
1042 if (!pl330pd || !pl330pd->peri) {
1043 dev_err(&pdev->dev, "platform data missing!\n");
1044 return -ENODEV;
1045 }
1046
1047 pl330_info = kzalloc(sizeof(*pl330_info), GFP_KERNEL);
1048 if (!pl330_info)
1049 return -ENOMEM;
1050
1051 pl330_info->pl330_data = NULL;
1052 pl330_info->dev = &pdev->dev;
1053
1054 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1055 if (!res) {
1056 ret = -ENODEV;
1057 goto probe_err1;
1058 }
1059
1060 request_mem_region(res->start, resource_size(res), pdev->name);
1061
1062 pl330_info->base = ioremap(res->start, resource_size(res));
1063 if (!pl330_info->base) {
1064 ret = -ENXIO;
1065 goto probe_err2;
1066 }
1067
1068 irq = platform_get_irq(pdev, 0);
1069 if (irq < 0) {
1070 ret = irq;
1071 goto probe_err3;
1072 }
1073
1074 ret = request_irq(irq, pl330_irq_handler, 0,
1075 dev_name(&pdev->dev), pl330_info);
1076 if (ret)
1077 goto probe_err4;
1078
1079 /* Allocate a new DMAC */
1080 s3c_pl330_dmac = kmalloc(sizeof(*s3c_pl330_dmac), GFP_KERNEL);
1081 if (!s3c_pl330_dmac) {
1082 ret = -ENOMEM;
1083 goto probe_err5;
1084 }
1085
1086 /* Get operation clock and enable it */
1087 s3c_pl330_dmac->clk = clk_get(&pdev->dev, "pdma");
1088 if (IS_ERR(s3c_pl330_dmac->clk)) {
1089 dev_err(&pdev->dev, "Cannot get operation clock.\n");
1090 ret = -EINVAL;
1091 goto probe_err6;
1092 }
1093 clk_enable(s3c_pl330_dmac->clk);
1094
1095 ret = pl330_add(pl330_info);
1096 if (ret)
1097 goto probe_err7;
1098
1099 /* Hook the info */
1100 s3c_pl330_dmac->pi = pl330_info;
1101
1102 /* No busy channels */
1103 s3c_pl330_dmac->busy_chan = 0;
1104
1105 s3c_pl330_dmac->kmcache = kmem_cache_create(dev_name(&pdev->dev),
1106 sizeof(struct s3c_pl330_xfer), 0, 0, NULL);
1107
1108 if (!s3c_pl330_dmac->kmcache) {
1109 ret = -ENOMEM;
1110 goto probe_err8;
1111 }
1112
1113 /* Get the list of peripherals */
1114 s3c_pl330_dmac->peri = pl330pd->peri;
1115
1116 /* Attach to the list of DMACs */
1117 list_add_tail(&s3c_pl330_dmac->node, &dmac_list);
1118
1119 /* Create a channel for each peripheral in the DMAC
1120 * that is, if it doesn't already exist
1121 */
1122 for (i = 0; i < PL330_MAX_PERI; i++)
1123 if (s3c_pl330_dmac->peri[i] != DMACH_MAX)
1124 chan_add(s3c_pl330_dmac->peri[i]);
1125
1126 printk(KERN_INFO
1127 "Loaded driver for PL330 DMAC-%d %s\n", pdev->id, pdev->name);
1128 printk(KERN_INFO
1129 "\tDBUFF-%ux%ubytes Num_Chans-%u Num_Peri-%u Num_Events-%u\n",
1130 pl330_info->pcfg.data_buf_dep,
1131 pl330_info->pcfg.data_bus_width / 8, pl330_info->pcfg.num_chan,
1132 pl330_info->pcfg.num_peri, pl330_info->pcfg.num_events);
1133
1134 return 0;
1135
1136probe_err8:
1137 pl330_del(pl330_info);
1138probe_err7:
1139 clk_disable(s3c_pl330_dmac->clk);
1140 clk_put(s3c_pl330_dmac->clk);
1141probe_err6:
1142 kfree(s3c_pl330_dmac);
1143probe_err5:
1144 free_irq(irq, pl330_info);
1145probe_err4:
1146probe_err3:
1147 iounmap(pl330_info->base);
1148probe_err2:
1149 release_mem_region(res->start, resource_size(res));
1150probe_err1:
1151 kfree(pl330_info);
1152
1153 return ret;
1154}
1155
1156static int pl330_remove(struct platform_device *pdev)
1157{
1158 struct s3c_pl330_dmac *dmac, *d;
1159 struct s3c_pl330_chan *ch;
1160 unsigned long flags;
1161 int del, found;
1162
1163 if (!pdev->dev.platform_data)
1164 return -EINVAL;
1165
1166 spin_lock_irqsave(&res_lock, flags);
1167
1168 found = 0;
1169 list_for_each_entry(d, &dmac_list, node)
1170 if (d->pi->dev == &pdev->dev) {
1171 found = 1;
1172 break;
1173 }
1174
1175 if (!found) {
1176 spin_unlock_irqrestore(&res_lock, flags);
1177 return 0;
1178 }
1179
1180 dmac = d;
1181
1182 /* Remove all Channels that are managed only by this DMAC */
1183 list_for_each_entry(ch, &chan_list, node) {
1184
1185 /* Only channels that are handled by this DMAC */
1186 if (iface_of_dmac(dmac, ch->id))
1187 del = 1;
1188 else
1189 continue;
1190
1191 /* Don't remove if some other DMAC has it too */
1192 list_for_each_entry(d, &dmac_list, node)
1193 if (d != dmac && iface_of_dmac(d, ch->id)) {
1194 del = 0;
1195 break;
1196 }
1197
1198 if (del) {
1199 spin_unlock_irqrestore(&res_lock, flags);
1200 s3c2410_dma_free(ch->id, ch->client);
1201 spin_lock_irqsave(&res_lock, flags);
1202 list_del(&ch->node);
1203 kfree(ch);
1204 }
1205 }
1206
1207 /* Disable operation clock */
1208 clk_disable(dmac->clk);
1209 clk_put(dmac->clk);
1210
1211 /* Remove the DMAC */
1212 list_del(&dmac->node);
1213 kfree(dmac);
1214
1215 spin_unlock_irqrestore(&res_lock, flags);
1216
1217 return 0;
1218}
1219
1220static struct platform_driver pl330_driver = {
1221 .driver = {
1222 .owner = THIS_MODULE,
1223 .name = "s3c-pl330",
1224 },
1225 .probe = pl330_probe,
1226 .remove = pl330_remove,
1227};
1228
1229static int __init pl330_init(void)
1230{
1231 return platform_driver_register(&pl330_driver);
1232}
1233module_init(pl330_init);
1234
1235static void __exit pl330_exit(void)
1236{
1237 platform_driver_unregister(&pl330_driver);
1238 return;
1239}
1240module_exit(pl330_exit);
1241
1242MODULE_AUTHOR("Jaswinder Singh <jassi.brar@samsung.com>");
1243MODULE_DESCRIPTION("Driver for PL330 DMA Controller");
1244MODULE_LICENSE("GPL");
diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
index 2e3b3d38c465..ab8f469f5cf8 100644
--- a/drivers/dma/Kconfig
+++ b/drivers/dma/Kconfig
@@ -193,7 +193,8 @@ config ARCH_HAS_ASYNC_TX_FIND_CHANNEL
193config PL330_DMA 193config PL330_DMA
194 tristate "DMA API Driver for PL330" 194 tristate "DMA API Driver for PL330"
195 select DMA_ENGINE 195 select DMA_ENGINE
196 depends on PL330 196 depends on ARM_AMBA
197 select PL330
197 help 198 help
198 Select if your platform has one or more PL330 DMACs. 199 Select if your platform has one or more PL330 DMACs.
199 You need to provide platform specific settings via 200 You need to provide platform specific settings via
diff --git a/drivers/dma/amba-pl08x.c b/drivers/dma/amba-pl08x.c
index be21e3f138a8..cd8df7f5b5c8 100644
--- a/drivers/dma/amba-pl08x.c
+++ b/drivers/dma/amba-pl08x.c
@@ -66,32 +66,29 @@
66 * after the final transfer signalled by LBREQ or LSREQ. The DMAC 66 * after the final transfer signalled by LBREQ or LSREQ. The DMAC
67 * will then move to the next LLI entry. 67 * will then move to the next LLI entry.
68 * 68 *
69 * Only the former works sanely with scatter lists, so we only implement
70 * the DMAC flow control method. However, peripherals which use the LBREQ
71 * and LSREQ signals (eg, MMCI) are unable to use this mode, which through
72 * these hardware restrictions prevents them from using scatter DMA.
73 *
74 * Global TODO: 69 * Global TODO:
75 * - Break out common code from arch/arm/mach-s3c64xx and share 70 * - Break out common code from arch/arm/mach-s3c64xx and share
76 */ 71 */
77#include <linux/device.h>
78#include <linux/init.h>
79#include <linux/module.h>
80#include <linux/interrupt.h>
81#include <linux/slab.h>
82#include <linux/delay.h>
83#include <linux/dma-mapping.h>
84#include <linux/dmapool.h>
85#include <linux/dmaengine.h>
86#include <linux/amba/bus.h> 72#include <linux/amba/bus.h>
87#include <linux/amba/pl08x.h> 73#include <linux/amba/pl08x.h>
88#include <linux/debugfs.h> 74#include <linux/debugfs.h>
75#include <linux/delay.h>
76#include <linux/device.h>
77#include <linux/dmaengine.h>
78#include <linux/dmapool.h>
79#include <linux/dma-mapping.h>
80#include <linux/init.h>
81#include <linux/interrupt.h>
82#include <linux/module.h>
83#include <linux/pm_runtime.h>
89#include <linux/seq_file.h> 84#include <linux/seq_file.h>
90 85#include <linux/slab.h>
91#include <asm/hardware/pl080.h> 86#include <asm/hardware/pl080.h>
92 87
93#define DRIVER_NAME "pl08xdmac" 88#define DRIVER_NAME "pl08xdmac"
94 89
90static struct amba_driver pl08x_amba_driver;
91
95/** 92/**
96 * struct vendor_data - vendor-specific config parameters for PL08x derivatives 93 * struct vendor_data - vendor-specific config parameters for PL08x derivatives
97 * @channels: the number of channels available in this variant 94 * @channels: the number of channels available in this variant
@@ -126,7 +123,8 @@ struct pl08x_lli {
126 * @phy_chans: array of data for the physical channels 123 * @phy_chans: array of data for the physical channels
127 * @pool: a pool for the LLI descriptors 124 * @pool: a pool for the LLI descriptors
128 * @pool_ctr: counter of LLIs in the pool 125 * @pool_ctr: counter of LLIs in the pool
129 * @lli_buses: bitmask to or in to LLI pointer selecting AHB port for LLI fetches 126 * @lli_buses: bitmask to or in to LLI pointer selecting AHB port for LLI
127 * fetches
130 * @mem_buses: set to indicate memory transfers on AHB2. 128 * @mem_buses: set to indicate memory transfers on AHB2.
131 * @lock: a spinlock for this struct 129 * @lock: a spinlock for this struct
132 */ 130 */
@@ -149,14 +147,6 @@ struct pl08x_driver_data {
149 * PL08X specific defines 147 * PL08X specific defines
150 */ 148 */
151 149
152/*
153 * Memory boundaries: the manual for PL08x says that the controller
154 * cannot read past a 1KiB boundary, so these defines are used to
155 * create transfer LLIs that do not cross such boundaries.
156 */
157#define PL08X_BOUNDARY_SHIFT (10) /* 1KB 0x400 */
158#define PL08X_BOUNDARY_SIZE (1 << PL08X_BOUNDARY_SHIFT)
159
160/* Size (bytes) of each LLI buffer allocated for one transfer */ 150/* Size (bytes) of each LLI buffer allocated for one transfer */
161# define PL08X_LLI_TSFR_SIZE 0x2000 151# define PL08X_LLI_TSFR_SIZE 0x2000
162 152
@@ -272,7 +262,6 @@ static void pl08x_resume_phy_chan(struct pl08x_phy_chan *ch)
272 writel(val, ch->base + PL080_CH_CONFIG); 262 writel(val, ch->base + PL080_CH_CONFIG);
273} 263}
274 264
275
276/* 265/*
277 * pl08x_terminate_phy_chan() stops the channel, clears the FIFO and 266 * pl08x_terminate_phy_chan() stops the channel, clears the FIFO and
278 * clears any pending interrupt status. This should not be used for 267 * clears any pending interrupt status. This should not be used for
@@ -407,6 +396,7 @@ pl08x_get_phy_channel(struct pl08x_driver_data *pl08x,
407 return NULL; 396 return NULL;
408 } 397 }
409 398
399 pm_runtime_get_sync(&pl08x->adev->dev);
410 return ch; 400 return ch;
411} 401}
412 402
@@ -420,6 +410,8 @@ static inline void pl08x_put_phy_channel(struct pl08x_driver_data *pl08x,
420 /* Stop the channel and clear its interrupts */ 410 /* Stop the channel and clear its interrupts */
421 pl08x_terminate_phy_chan(pl08x, ch); 411 pl08x_terminate_phy_chan(pl08x, ch);
422 412
413 pm_runtime_put(&pl08x->adev->dev);
414
423 /* Mark it as free */ 415 /* Mark it as free */
424 ch->serving = NULL; 416 ch->serving = NULL;
425 spin_unlock_irqrestore(&ch->lock, flags); 417 spin_unlock_irqrestore(&ch->lock, flags);
@@ -499,36 +491,30 @@ struct pl08x_lli_build_data {
499}; 491};
500 492
501/* 493/*
502 * Autoselect a master bus to use for the transfer this prefers the 494 * Autoselect a master bus to use for the transfer. Slave will be the chosen as
503 * destination bus if both available if fixed address on one bus the 495 * victim in case src & dest are not similarly aligned. i.e. If after aligning
504 * other will be chosen 496 * masters address with width requirements of transfer (by sending few byte by
497 * byte data), slave is still not aligned, then its width will be reduced to
498 * BYTE.
499 * - prefers the destination bus if both available
500 * - prefers bus with fixed address (i.e. peripheral)
505 */ 501 */
506static void pl08x_choose_master_bus(struct pl08x_lli_build_data *bd, 502static void pl08x_choose_master_bus(struct pl08x_lli_build_data *bd,
507 struct pl08x_bus_data **mbus, struct pl08x_bus_data **sbus, u32 cctl) 503 struct pl08x_bus_data **mbus, struct pl08x_bus_data **sbus, u32 cctl)
508{ 504{
509 if (!(cctl & PL080_CONTROL_DST_INCR)) { 505 if (!(cctl & PL080_CONTROL_DST_INCR)) {
510 *mbus = &bd->srcbus;
511 *sbus = &bd->dstbus;
512 } else if (!(cctl & PL080_CONTROL_SRC_INCR)) {
513 *mbus = &bd->dstbus; 506 *mbus = &bd->dstbus;
514 *sbus = &bd->srcbus; 507 *sbus = &bd->srcbus;
508 } else if (!(cctl & PL080_CONTROL_SRC_INCR)) {
509 *mbus = &bd->srcbus;
510 *sbus = &bd->dstbus;
515 } else { 511 } else {
516 if (bd->dstbus.buswidth == 4) { 512 if (bd->dstbus.buswidth >= bd->srcbus.buswidth) {
517 *mbus = &bd->dstbus;
518 *sbus = &bd->srcbus;
519 } else if (bd->srcbus.buswidth == 4) {
520 *mbus = &bd->srcbus;
521 *sbus = &bd->dstbus;
522 } else if (bd->dstbus.buswidth == 2) {
523 *mbus = &bd->dstbus; 513 *mbus = &bd->dstbus;
524 *sbus = &bd->srcbus; 514 *sbus = &bd->srcbus;
525 } else if (bd->srcbus.buswidth == 2) { 515 } else {
526 *mbus = &bd->srcbus; 516 *mbus = &bd->srcbus;
527 *sbus = &bd->dstbus; 517 *sbus = &bd->dstbus;
528 } else {
529 /* bd->srcbus.buswidth == 1 */
530 *mbus = &bd->dstbus;
531 *sbus = &bd->srcbus;
532 } 518 }
533 } 519 }
534} 520}
@@ -547,7 +533,8 @@ static void pl08x_fill_lli_for_desc(struct pl08x_lli_build_data *bd,
547 llis_va[num_llis].cctl = cctl; 533 llis_va[num_llis].cctl = cctl;
548 llis_va[num_llis].src = bd->srcbus.addr; 534 llis_va[num_llis].src = bd->srcbus.addr;
549 llis_va[num_llis].dst = bd->dstbus.addr; 535 llis_va[num_llis].dst = bd->dstbus.addr;
550 llis_va[num_llis].lli = llis_bus + (num_llis + 1) * sizeof(struct pl08x_lli); 536 llis_va[num_llis].lli = llis_bus + (num_llis + 1) *
537 sizeof(struct pl08x_lli);
551 llis_va[num_llis].lli |= bd->lli_bus; 538 llis_va[num_llis].lli |= bd->lli_bus;
552 539
553 if (cctl & PL080_CONTROL_SRC_INCR) 540 if (cctl & PL080_CONTROL_SRC_INCR)
@@ -560,16 +547,12 @@ static void pl08x_fill_lli_for_desc(struct pl08x_lli_build_data *bd,
560 bd->remainder -= len; 547 bd->remainder -= len;
561} 548}
562 549
563/* 550static inline void prep_byte_width_lli(struct pl08x_lli_build_data *bd,
564 * Return number of bytes to fill to boundary, or len. 551 u32 *cctl, u32 len, int num_llis, size_t *total_bytes)
565 * This calculation works for any value of addr.
566 */
567static inline size_t pl08x_pre_boundary(u32 addr, size_t len)
568{ 552{
569 size_t boundary_len = PL08X_BOUNDARY_SIZE - 553 *cctl = pl08x_cctl_bits(*cctl, 1, 1, len);
570 (addr & (PL08X_BOUNDARY_SIZE - 1)); 554 pl08x_fill_lli_for_desc(bd, num_llis, len, *cctl);
571 555 (*total_bytes) += len;
572 return min(boundary_len, len);
573} 556}
574 557
575/* 558/*
@@ -583,13 +566,11 @@ static int pl08x_fill_llis_for_desc(struct pl08x_driver_data *pl08x,
583 struct pl08x_bus_data *mbus, *sbus; 566 struct pl08x_bus_data *mbus, *sbus;
584 struct pl08x_lli_build_data bd; 567 struct pl08x_lli_build_data bd;
585 int num_llis = 0; 568 int num_llis = 0;
586 u32 cctl; 569 u32 cctl, early_bytes = 0;
587 size_t max_bytes_per_lli; 570 size_t max_bytes_per_lli, total_bytes = 0;
588 size_t total_bytes = 0;
589 struct pl08x_lli *llis_va; 571 struct pl08x_lli *llis_va;
590 572
591 txd->llis_va = dma_pool_alloc(pl08x->pool, GFP_NOWAIT, 573 txd->llis_va = dma_pool_alloc(pl08x->pool, GFP_NOWAIT, &txd->llis_bus);
592 &txd->llis_bus);
593 if (!txd->llis_va) { 574 if (!txd->llis_va) {
594 dev_err(&pl08x->adev->dev, "%s no memory for llis\n", __func__); 575 dev_err(&pl08x->adev->dev, "%s no memory for llis\n", __func__);
595 return 0; 576 return 0;
@@ -619,55 +600,85 @@ static int pl08x_fill_llis_for_desc(struct pl08x_driver_data *pl08x,
619 bd.srcbus.buswidth = bd.srcbus.maxwidth; 600 bd.srcbus.buswidth = bd.srcbus.maxwidth;
620 bd.dstbus.buswidth = bd.dstbus.maxwidth; 601 bd.dstbus.buswidth = bd.dstbus.maxwidth;
621 602
622 /*
623 * Bytes transferred == tsize * MIN(buswidths), not max(buswidths)
624 */
625 max_bytes_per_lli = min(bd.srcbus.buswidth, bd.dstbus.buswidth) *
626 PL080_CONTROL_TRANSFER_SIZE_MASK;
627
628 /* We need to count this down to zero */ 603 /* We need to count this down to zero */
629 bd.remainder = txd->len; 604 bd.remainder = txd->len;
630 605
631 /*
632 * Choose bus to align to
633 * - prefers destination bus if both available
634 * - if fixed address on one bus chooses other
635 */
636 pl08x_choose_master_bus(&bd, &mbus, &sbus, cctl); 606 pl08x_choose_master_bus(&bd, &mbus, &sbus, cctl);
637 607
638 dev_vdbg(&pl08x->adev->dev, "src=0x%08x%s/%u dst=0x%08x%s/%u len=%zu llimax=%zu\n", 608 dev_vdbg(&pl08x->adev->dev, "src=0x%08x%s/%u dst=0x%08x%s/%u len=%zu\n",
639 bd.srcbus.addr, cctl & PL080_CONTROL_SRC_INCR ? "+" : "", 609 bd.srcbus.addr, cctl & PL080_CONTROL_SRC_INCR ? "+" : "",
640 bd.srcbus.buswidth, 610 bd.srcbus.buswidth,
641 bd.dstbus.addr, cctl & PL080_CONTROL_DST_INCR ? "+" : "", 611 bd.dstbus.addr, cctl & PL080_CONTROL_DST_INCR ? "+" : "",
642 bd.dstbus.buswidth, 612 bd.dstbus.buswidth,
643 bd.remainder, max_bytes_per_lli); 613 bd.remainder);
644 dev_vdbg(&pl08x->adev->dev, "mbus=%s sbus=%s\n", 614 dev_vdbg(&pl08x->adev->dev, "mbus=%s sbus=%s\n",
645 mbus == &bd.srcbus ? "src" : "dst", 615 mbus == &bd.srcbus ? "src" : "dst",
646 sbus == &bd.srcbus ? "src" : "dst"); 616 sbus == &bd.srcbus ? "src" : "dst");
647 617
648 if (txd->len < mbus->buswidth) { 618 /*
649 /* Less than a bus width available - send as single bytes */ 619 * Zero length is only allowed if all these requirements are met:
650 while (bd.remainder) { 620 * - flow controller is peripheral.
651 dev_vdbg(&pl08x->adev->dev, 621 * - src.addr is aligned to src.width
652 "%s single byte LLIs for a transfer of " 622 * - dst.addr is aligned to dst.width
653 "less than a bus width (remain 0x%08x)\n", 623 *
654 __func__, bd.remainder); 624 * sg_len == 1 should be true, as there can be two cases here:
655 cctl = pl08x_cctl_bits(cctl, 1, 1, 1); 625 * - Memory addresses are contiguous and are not scattered. Here, Only
656 pl08x_fill_lli_for_desc(&bd, num_llis++, 1, cctl); 626 * one sg will be passed by user driver, with memory address and zero
657 total_bytes++; 627 * length. We pass this to controller and after the transfer it will
628 * receive the last burst request from peripheral and so transfer
629 * finishes.
630 *
631 * - Memory addresses are scattered and are not contiguous. Here,
632 * Obviously as DMA controller doesn't know when a lli's transfer gets
633 * over, it can't load next lli. So in this case, there has to be an
634 * assumption that only one lli is supported. Thus, we can't have
635 * scattered addresses.
636 */
637 if (!bd.remainder) {
638 u32 fc = (txd->ccfg & PL080_CONFIG_FLOW_CONTROL_MASK) >>
639 PL080_CONFIG_FLOW_CONTROL_SHIFT;
640 if (!((fc >= PL080_FLOW_SRC2DST_DST) &&
641 (fc <= PL080_FLOW_SRC2DST_SRC))) {
642 dev_err(&pl08x->adev->dev, "%s sg len can't be zero",
643 __func__);
644 return 0;
658 } 645 }
659 } else { 646
660 /* Make one byte LLIs until master bus is aligned */ 647 if ((bd.srcbus.addr % bd.srcbus.buswidth) ||
661 while ((mbus->addr) % (mbus->buswidth)) { 648 (bd.srcbus.addr % bd.srcbus.buswidth)) {
662 dev_vdbg(&pl08x->adev->dev, 649 dev_err(&pl08x->adev->dev,
663 "%s adjustment lli for less than bus width " 650 "%s src & dst address must be aligned to src"
664 "(remain 0x%08x)\n", 651 " & dst width if peripheral is flow controller",
665 __func__, bd.remainder); 652 __func__);
666 cctl = pl08x_cctl_bits(cctl, 1, 1, 1); 653 return 0;
667 pl08x_fill_lli_for_desc(&bd, num_llis++, 1, cctl);
668 total_bytes++;
669 } 654 }
670 655
656 cctl = pl08x_cctl_bits(cctl, bd.srcbus.buswidth,
657 bd.dstbus.buswidth, 0);
658 pl08x_fill_lli_for_desc(&bd, num_llis++, 0, cctl);
659 }
660
661 /*
662 * Send byte by byte for following cases
663 * - Less than a bus width available
664 * - until master bus is aligned
665 */
666 if (bd.remainder < mbus->buswidth)
667 early_bytes = bd.remainder;
668 else if ((mbus->addr) % (mbus->buswidth)) {
669 early_bytes = mbus->buswidth - (mbus->addr) % (mbus->buswidth);
670 if ((bd.remainder - early_bytes) < mbus->buswidth)
671 early_bytes = bd.remainder;
672 }
673
674 if (early_bytes) {
675 dev_vdbg(&pl08x->adev->dev, "%s byte width LLIs "
676 "(remain 0x%08x)\n", __func__, bd.remainder);
677 prep_byte_width_lli(&bd, &cctl, early_bytes, num_llis++,
678 &total_bytes);
679 }
680
681 if (bd.remainder) {
671 /* 682 /*
672 * Master now aligned 683 * Master now aligned
673 * - if slave is not then we must set its width down 684 * - if slave is not then we must set its width down
@@ -680,138 +691,55 @@ static int pl08x_fill_llis_for_desc(struct pl08x_driver_data *pl08x,
680 sbus->buswidth = 1; 691 sbus->buswidth = 1;
681 } 692 }
682 693
694 /* Bytes transferred = tsize * src width, not MIN(buswidths) */
695 max_bytes_per_lli = bd.srcbus.buswidth *
696 PL080_CONTROL_TRANSFER_SIZE_MASK;
697
683 /* 698 /*
684 * Make largest possible LLIs until less than one bus 699 * Make largest possible LLIs until less than one bus
685 * width left 700 * width left
686 */ 701 */
687 while (bd.remainder > (mbus->buswidth - 1)) { 702 while (bd.remainder > (mbus->buswidth - 1)) {
688 size_t lli_len, target_len, tsize, odd_bytes; 703 size_t lli_len, tsize, width;
689 704
690 /* 705 /*
691 * If enough left try to send max possible, 706 * If enough left try to send max possible,
692 * otherwise try to send the remainder 707 * otherwise try to send the remainder
693 */ 708 */
694 target_len = min(bd.remainder, max_bytes_per_lli); 709 lli_len = min(bd.remainder, max_bytes_per_lli);
695 710
696 /* 711 /*
697 * Set bus lengths for incrementing buses to the 712 * Check against maximum bus alignment: Calculate actual
698 * number of bytes which fill to next memory boundary, 713 * transfer size in relation to bus width and get a
699 * limiting on the target length calculated above. 714 * maximum remainder of the highest bus width - 1
700 */ 715 */
701 if (cctl & PL080_CONTROL_SRC_INCR) 716 width = max(mbus->buswidth, sbus->buswidth);
702 bd.srcbus.fill_bytes = 717 lli_len = (lli_len / width) * width;
703 pl08x_pre_boundary(bd.srcbus.addr, 718 tsize = lli_len / bd.srcbus.buswidth;
704 target_len);
705 else
706 bd.srcbus.fill_bytes = target_len;
707
708 if (cctl & PL080_CONTROL_DST_INCR)
709 bd.dstbus.fill_bytes =
710 pl08x_pre_boundary(bd.dstbus.addr,
711 target_len);
712 else
713 bd.dstbus.fill_bytes = target_len;
714
715 /* Find the nearest */
716 lli_len = min(bd.srcbus.fill_bytes,
717 bd.dstbus.fill_bytes);
718
719 BUG_ON(lli_len > bd.remainder);
720
721 if (lli_len <= 0) {
722 dev_err(&pl08x->adev->dev,
723 "%s lli_len is %zu, <= 0\n",
724 __func__, lli_len);
725 return 0;
726 }
727
728 if (lli_len == target_len) {
729 /*
730 * Can send what we wanted.
731 * Maintain alignment
732 */
733 lli_len = (lli_len/mbus->buswidth) *
734 mbus->buswidth;
735 odd_bytes = 0;
736 } else {
737 /*
738 * So now we know how many bytes to transfer
739 * to get to the nearest boundary. The next
740 * LLI will past the boundary. However, we
741 * may be working to a boundary on the slave
742 * bus. We need to ensure the master stays
743 * aligned, and that we are working in
744 * multiples of the bus widths.
745 */
746 odd_bytes = lli_len % mbus->buswidth;
747 lli_len -= odd_bytes;
748
749 }
750
751 if (lli_len) {
752 /*
753 * Check against minimum bus alignment:
754 * Calculate actual transfer size in relation
755 * to bus width an get a maximum remainder of
756 * the smallest bus width - 1
757 */
758 /* FIXME: use round_down()? */
759 tsize = lli_len / min(mbus->buswidth,
760 sbus->buswidth);
761 lli_len = tsize * min(mbus->buswidth,
762 sbus->buswidth);
763
764 if (target_len != lli_len) {
765 dev_vdbg(&pl08x->adev->dev,
766 "%s can't send what we want. Desired 0x%08zx, lli of 0x%08zx bytes in txd of 0x%08zx\n",
767 __func__, target_len, lli_len, txd->len);
768 }
769
770 cctl = pl08x_cctl_bits(cctl,
771 bd.srcbus.buswidth,
772 bd.dstbus.buswidth,
773 tsize);
774
775 dev_vdbg(&pl08x->adev->dev,
776 "%s fill lli with single lli chunk of size 0x%08zx (remainder 0x%08zx)\n",
777 __func__, lli_len, bd.remainder);
778 pl08x_fill_lli_for_desc(&bd, num_llis++,
779 lli_len, cctl);
780 total_bytes += lli_len;
781 }
782 719
783 720 dev_vdbg(&pl08x->adev->dev,
784 if (odd_bytes) { 721 "%s fill lli with single lli chunk of "
785 /* 722 "size 0x%08zx (remainder 0x%08zx)\n",
786 * Creep past the boundary, maintaining 723 __func__, lli_len, bd.remainder);
787 * master alignment 724
788 */ 725 cctl = pl08x_cctl_bits(cctl, bd.srcbus.buswidth,
789 int j; 726 bd.dstbus.buswidth, tsize);
790 for (j = 0; (j < mbus->buswidth) 727 pl08x_fill_lli_for_desc(&bd, num_llis++, lli_len, cctl);
791 && (bd.remainder); j++) { 728 total_bytes += lli_len;
792 cctl = pl08x_cctl_bits(cctl, 1, 1, 1);
793 dev_vdbg(&pl08x->adev->dev,
794 "%s align with boundary, single byte (remain 0x%08zx)\n",
795 __func__, bd.remainder);
796 pl08x_fill_lli_for_desc(&bd,
797 num_llis++, 1, cctl);
798 total_bytes++;
799 }
800 }
801 } 729 }
802 730
803 /* 731 /*
804 * Send any odd bytes 732 * Send any odd bytes
805 */ 733 */
806 while (bd.remainder) { 734 if (bd.remainder) {
807 cctl = pl08x_cctl_bits(cctl, 1, 1, 1);
808 dev_vdbg(&pl08x->adev->dev, 735 dev_vdbg(&pl08x->adev->dev,
809 "%s align with boundary, single odd byte (remain %zu)\n", 736 "%s align with boundary, send odd bytes (remain %zu)\n",
810 __func__, bd.remainder); 737 __func__, bd.remainder);
811 pl08x_fill_lli_for_desc(&bd, num_llis++, 1, cctl); 738 prep_byte_width_lli(&bd, &cctl, bd.remainder,
812 total_bytes++; 739 num_llis++, &total_bytes);
813 } 740 }
814 } 741 }
742
815 if (total_bytes != txd->len) { 743 if (total_bytes != txd->len) {
816 dev_err(&pl08x->adev->dev, 744 dev_err(&pl08x->adev->dev,
817 "%s size of encoded lli:s don't match total txd, transferred 0x%08zx from size 0x%08zx\n", 745 "%s size of encoded lli:s don't match total txd, transferred 0x%08zx from size 0x%08zx\n",
@@ -917,9 +845,7 @@ static int prep_phy_channel(struct pl08x_dma_chan *plchan,
917 * need, but for slaves the physical signals may be muxed! 845 * need, but for slaves the physical signals may be muxed!
918 * Can the platform allow us to use this channel? 846 * Can the platform allow us to use this channel?
919 */ 847 */
920 if (plchan->slave && 848 if (plchan->slave && pl08x->pd->get_signal) {
921 ch->signal < 0 &&
922 pl08x->pd->get_signal) {
923 ret = pl08x->pd->get_signal(plchan); 849 ret = pl08x->pd->get_signal(plchan);
924 if (ret < 0) { 850 if (ret < 0) {
925 dev_dbg(&pl08x->adev->dev, 851 dev_dbg(&pl08x->adev->dev,
@@ -1008,10 +934,8 @@ static struct dma_async_tx_descriptor *pl08x_prep_dma_interrupt(
1008 * If slaves are relying on interrupts to signal completion this function 934 * If slaves are relying on interrupts to signal completion this function
1009 * must not be called with interrupts disabled. 935 * must not be called with interrupts disabled.
1010 */ 936 */
1011static enum dma_status 937static enum dma_status pl08x_dma_tx_status(struct dma_chan *chan,
1012pl08x_dma_tx_status(struct dma_chan *chan, 938 dma_cookie_t cookie, struct dma_tx_state *txstate)
1013 dma_cookie_t cookie,
1014 struct dma_tx_state *txstate)
1015{ 939{
1016 struct pl08x_dma_chan *plchan = to_pl08x_chan(chan); 940 struct pl08x_dma_chan *plchan = to_pl08x_chan(chan);
1017 dma_cookie_t last_used; 941 dma_cookie_t last_used;
@@ -1253,7 +1177,9 @@ static int pl08x_prep_channel_resources(struct pl08x_dma_chan *plchan,
1253 1177
1254 num_llis = pl08x_fill_llis_for_desc(pl08x, txd); 1178 num_llis = pl08x_fill_llis_for_desc(pl08x, txd);
1255 if (!num_llis) { 1179 if (!num_llis) {
1256 kfree(txd); 1180 spin_lock_irqsave(&plchan->lock, flags);
1181 pl08x_free_txd(pl08x, txd);
1182 spin_unlock_irqrestore(&plchan->lock, flags);
1257 return -EINVAL; 1183 return -EINVAL;
1258 } 1184 }
1259 1185
@@ -1301,7 +1227,7 @@ static int pl08x_prep_channel_resources(struct pl08x_dma_chan *plchan,
1301static struct pl08x_txd *pl08x_get_txd(struct pl08x_dma_chan *plchan, 1227static struct pl08x_txd *pl08x_get_txd(struct pl08x_dma_chan *plchan,
1302 unsigned long flags) 1228 unsigned long flags)
1303{ 1229{
1304 struct pl08x_txd *txd = kzalloc(sizeof(struct pl08x_txd), GFP_NOWAIT); 1230 struct pl08x_txd *txd = kzalloc(sizeof(*txd), GFP_NOWAIT);
1305 1231
1306 if (txd) { 1232 if (txd) {
1307 dma_async_tx_descriptor_init(&txd->tx, &plchan->chan); 1233 dma_async_tx_descriptor_init(&txd->tx, &plchan->chan);
@@ -1367,7 +1293,7 @@ static struct dma_async_tx_descriptor *pl08x_prep_slave_sg(
1367 struct pl08x_dma_chan *plchan = to_pl08x_chan(chan); 1293 struct pl08x_dma_chan *plchan = to_pl08x_chan(chan);
1368 struct pl08x_driver_data *pl08x = plchan->host; 1294 struct pl08x_driver_data *pl08x = plchan->host;
1369 struct pl08x_txd *txd; 1295 struct pl08x_txd *txd;
1370 int ret; 1296 int ret, tmp;
1371 1297
1372 /* 1298 /*
1373 * Current implementation ASSUMES only one sg 1299 * Current implementation ASSUMES only one sg
@@ -1401,12 +1327,10 @@ static struct dma_async_tx_descriptor *pl08x_prep_slave_sg(
1401 txd->len = sgl->length; 1327 txd->len = sgl->length;
1402 1328
1403 if (direction == DMA_TO_DEVICE) { 1329 if (direction == DMA_TO_DEVICE) {
1404 txd->ccfg |= PL080_FLOW_MEM2PER << PL080_CONFIG_FLOW_CONTROL_SHIFT;
1405 txd->cctl = plchan->dst_cctl; 1330 txd->cctl = plchan->dst_cctl;
1406 txd->src_addr = sgl->dma_address; 1331 txd->src_addr = sgl->dma_address;
1407 txd->dst_addr = plchan->dst_addr; 1332 txd->dst_addr = plchan->dst_addr;
1408 } else if (direction == DMA_FROM_DEVICE) { 1333 } else if (direction == DMA_FROM_DEVICE) {
1409 txd->ccfg |= PL080_FLOW_PER2MEM << PL080_CONFIG_FLOW_CONTROL_SHIFT;
1410 txd->cctl = plchan->src_cctl; 1334 txd->cctl = plchan->src_cctl;
1411 txd->src_addr = plchan->src_addr; 1335 txd->src_addr = plchan->src_addr;
1412 txd->dst_addr = sgl->dma_address; 1336 txd->dst_addr = sgl->dma_address;
@@ -1416,6 +1340,15 @@ static struct dma_async_tx_descriptor *pl08x_prep_slave_sg(
1416 return NULL; 1340 return NULL;
1417 } 1341 }
1418 1342
1343 if (plchan->cd->device_fc)
1344 tmp = (direction == DMA_TO_DEVICE) ? PL080_FLOW_MEM2PER_PER :
1345 PL080_FLOW_PER2MEM_PER;
1346 else
1347 tmp = (direction == DMA_TO_DEVICE) ? PL080_FLOW_MEM2PER :
1348 PL080_FLOW_PER2MEM;
1349
1350 txd->ccfg |= tmp << PL080_CONFIG_FLOW_CONTROL_SHIFT;
1351
1419 ret = pl08x_prep_channel_resources(plchan, txd); 1352 ret = pl08x_prep_channel_resources(plchan, txd);
1420 if (ret) 1353 if (ret)
1421 return NULL; 1354 return NULL;
@@ -1489,9 +1422,15 @@ static int pl08x_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
1489 1422
1490bool pl08x_filter_id(struct dma_chan *chan, void *chan_id) 1423bool pl08x_filter_id(struct dma_chan *chan, void *chan_id)
1491{ 1424{
1492 struct pl08x_dma_chan *plchan = to_pl08x_chan(chan); 1425 struct pl08x_dma_chan *plchan;
1493 char *name = chan_id; 1426 char *name = chan_id;
1494 1427
1428 /* Reject channels for devices not bound to this driver */
1429 if (chan->device->dev->driver != &pl08x_amba_driver.drv)
1430 return false;
1431
1432 plchan = to_pl08x_chan(chan);
1433
1495 /* Check that the channel is not taken! */ 1434 /* Check that the channel is not taken! */
1496 if (!strcmp(plchan->name, name)) 1435 if (!strcmp(plchan->name, name))
1497 return true; 1436 return true;
@@ -1507,13 +1446,7 @@ bool pl08x_filter_id(struct dma_chan *chan, void *chan_id)
1507 */ 1446 */
1508static void pl08x_ensure_on(struct pl08x_driver_data *pl08x) 1447static void pl08x_ensure_on(struct pl08x_driver_data *pl08x)
1509{ 1448{
1510 u32 val; 1449 writel(PL080_CONFIG_ENABLE, pl08x->base + PL080_CONFIG);
1511
1512 val = readl(pl08x->base + PL080_CONFIG);
1513 val &= ~(PL080_CONFIG_M2_BE | PL080_CONFIG_M1_BE | PL080_CONFIG_ENABLE);
1514 /* We implicitly clear bit 1 and that means little-endian mode */
1515 val |= PL080_CONFIG_ENABLE;
1516 writel(val, pl08x->base + PL080_CONFIG);
1517} 1450}
1518 1451
1519static void pl08x_unmap_buffers(struct pl08x_txd *txd) 1452static void pl08x_unmap_buffers(struct pl08x_txd *txd)
@@ -1589,8 +1522,8 @@ static void pl08x_tasklet(unsigned long data)
1589 */ 1522 */
1590 list_for_each_entry(waiting, &pl08x->memcpy.channels, 1523 list_for_each_entry(waiting, &pl08x->memcpy.channels,
1591 chan.device_node) { 1524 chan.device_node) {
1592 if (waiting->state == PL08X_CHAN_WAITING && 1525 if (waiting->state == PL08X_CHAN_WAITING &&
1593 waiting->waiting != NULL) { 1526 waiting->waiting != NULL) {
1594 int ret; 1527 int ret;
1595 1528
1596 /* This should REALLY not fail now */ 1529 /* This should REALLY not fail now */
@@ -1630,38 +1563,40 @@ static void pl08x_tasklet(unsigned long data)
1630static irqreturn_t pl08x_irq(int irq, void *dev) 1563static irqreturn_t pl08x_irq(int irq, void *dev)
1631{ 1564{
1632 struct pl08x_driver_data *pl08x = dev; 1565 struct pl08x_driver_data *pl08x = dev;
1633 u32 mask = 0; 1566 u32 mask = 0, err, tc, i;
1634 u32 val; 1567
1635 int i; 1568 /* check & clear - ERR & TC interrupts */
1636 1569 err = readl(pl08x->base + PL080_ERR_STATUS);
1637 val = readl(pl08x->base + PL080_ERR_STATUS); 1570 if (err) {
1638 if (val) { 1571 dev_err(&pl08x->adev->dev, "%s error interrupt, register value 0x%08x\n",
1639 /* An error interrupt (on one or more channels) */ 1572 __func__, err);
1640 dev_err(&pl08x->adev->dev, 1573 writel(err, pl08x->base + PL080_ERR_CLEAR);
1641 "%s error interrupt, register value 0x%08x\n",
1642 __func__, val);
1643 /*
1644 * Simply clear ALL PL08X error interrupts,
1645 * regardless of channel and cause
1646 * FIXME: should be 0x00000003 on PL081 really.
1647 */
1648 writel(0x000000FF, pl08x->base + PL080_ERR_CLEAR);
1649 } 1574 }
1650 val = readl(pl08x->base + PL080_INT_STATUS); 1575 tc = readl(pl08x->base + PL080_INT_STATUS);
1576 if (tc)
1577 writel(tc, pl08x->base + PL080_TC_CLEAR);
1578
1579 if (!err && !tc)
1580 return IRQ_NONE;
1581
1651 for (i = 0; i < pl08x->vd->channels; i++) { 1582 for (i = 0; i < pl08x->vd->channels; i++) {
1652 if ((1 << i) & val) { 1583 if (((1 << i) & err) || ((1 << i) & tc)) {
1653 /* Locate physical channel */ 1584 /* Locate physical channel */
1654 struct pl08x_phy_chan *phychan = &pl08x->phy_chans[i]; 1585 struct pl08x_phy_chan *phychan = &pl08x->phy_chans[i];
1655 struct pl08x_dma_chan *plchan = phychan->serving; 1586 struct pl08x_dma_chan *plchan = phychan->serving;
1656 1587
1588 if (!plchan) {
1589 dev_err(&pl08x->adev->dev,
1590 "%s Error TC interrupt on unused channel: 0x%08x\n",
1591 __func__, i);
1592 continue;
1593 }
1594
1657 /* Schedule tasklet on this channel */ 1595 /* Schedule tasklet on this channel */
1658 tasklet_schedule(&plchan->tasklet); 1596 tasklet_schedule(&plchan->tasklet);
1659
1660 mask |= (1 << i); 1597 mask |= (1 << i);
1661 } 1598 }
1662 } 1599 }
1663 /* Clear only the terminal interrupts on channels we processed */
1664 writel(mask, pl08x->base + PL080_TC_CLEAR);
1665 1600
1666 return mask ? IRQ_HANDLED : IRQ_NONE; 1601 return mask ? IRQ_HANDLED : IRQ_NONE;
1667} 1602}
@@ -1685,9 +1620,7 @@ static void pl08x_dma_slave_init(struct pl08x_dma_chan *chan)
1685 * Make a local wrapper to hold required data 1620 * Make a local wrapper to hold required data
1686 */ 1621 */
1687static int pl08x_dma_init_virtual_channels(struct pl08x_driver_data *pl08x, 1622static int pl08x_dma_init_virtual_channels(struct pl08x_driver_data *pl08x,
1688 struct dma_device *dmadev, 1623 struct dma_device *dmadev, unsigned int channels, bool slave)
1689 unsigned int channels,
1690 bool slave)
1691{ 1624{
1692 struct pl08x_dma_chan *chan; 1625 struct pl08x_dma_chan *chan;
1693 int i; 1626 int i;
@@ -1700,7 +1633,7 @@ static int pl08x_dma_init_virtual_channels(struct pl08x_driver_data *pl08x,
1700 * to cope with that situation. 1633 * to cope with that situation.
1701 */ 1634 */
1702 for (i = 0; i < channels; i++) { 1635 for (i = 0; i < channels; i++) {
1703 chan = kzalloc(sizeof(struct pl08x_dma_chan), GFP_KERNEL); 1636 chan = kzalloc(sizeof(*chan), GFP_KERNEL);
1704 if (!chan) { 1637 if (!chan) {
1705 dev_err(&pl08x->adev->dev, 1638 dev_err(&pl08x->adev->dev,
1706 "%s no memory for channel\n", __func__); 1639 "%s no memory for channel\n", __func__);
@@ -1728,7 +1661,7 @@ static int pl08x_dma_init_virtual_channels(struct pl08x_driver_data *pl08x,
1728 kfree(chan); 1661 kfree(chan);
1729 continue; 1662 continue;
1730 } 1663 }
1731 dev_info(&pl08x->adev->dev, 1664 dev_dbg(&pl08x->adev->dev,
1732 "initialize virtual channel \"%s\"\n", 1665 "initialize virtual channel \"%s\"\n",
1733 chan->name); 1666 chan->name);
1734 1667
@@ -1837,9 +1770,9 @@ static const struct file_operations pl08x_debugfs_operations = {
1837static void init_pl08x_debugfs(struct pl08x_driver_data *pl08x) 1770static void init_pl08x_debugfs(struct pl08x_driver_data *pl08x)
1838{ 1771{
1839 /* Expose a simple debugfs interface to view all clocks */ 1772 /* Expose a simple debugfs interface to view all clocks */
1840 (void) debugfs_create_file(dev_name(&pl08x->adev->dev), S_IFREG | S_IRUGO, 1773 (void) debugfs_create_file(dev_name(&pl08x->adev->dev),
1841 NULL, pl08x, 1774 S_IFREG | S_IRUGO, NULL, pl08x,
1842 &pl08x_debugfs_operations); 1775 &pl08x_debugfs_operations);
1843} 1776}
1844 1777
1845#else 1778#else
@@ -1860,12 +1793,15 @@ static int pl08x_probe(struct amba_device *adev, const struct amba_id *id)
1860 return ret; 1793 return ret;
1861 1794
1862 /* Create the driver state holder */ 1795 /* Create the driver state holder */
1863 pl08x = kzalloc(sizeof(struct pl08x_driver_data), GFP_KERNEL); 1796 pl08x = kzalloc(sizeof(*pl08x), GFP_KERNEL);
1864 if (!pl08x) { 1797 if (!pl08x) {
1865 ret = -ENOMEM; 1798 ret = -ENOMEM;
1866 goto out_no_pl08x; 1799 goto out_no_pl08x;
1867 } 1800 }
1868 1801
1802 pm_runtime_set_active(&adev->dev);
1803 pm_runtime_enable(&adev->dev);
1804
1869 /* Initialize memcpy engine */ 1805 /* Initialize memcpy engine */
1870 dma_cap_set(DMA_MEMCPY, pl08x->memcpy.cap_mask); 1806 dma_cap_set(DMA_MEMCPY, pl08x->memcpy.cap_mask);
1871 pl08x->memcpy.dev = &adev->dev; 1807 pl08x->memcpy.dev = &adev->dev;
@@ -1939,7 +1875,7 @@ static int pl08x_probe(struct amba_device *adev, const struct amba_id *id)
1939 } 1875 }
1940 1876
1941 /* Initialize physical channels */ 1877 /* Initialize physical channels */
1942 pl08x->phy_chans = kmalloc((vd->channels * sizeof(struct pl08x_phy_chan)), 1878 pl08x->phy_chans = kmalloc((vd->channels * sizeof(*pl08x->phy_chans)),
1943 GFP_KERNEL); 1879 GFP_KERNEL);
1944 if (!pl08x->phy_chans) { 1880 if (!pl08x->phy_chans) {
1945 dev_err(&adev->dev, "%s failed to allocate " 1881 dev_err(&adev->dev, "%s failed to allocate "
@@ -1956,9 +1892,8 @@ static int pl08x_probe(struct amba_device *adev, const struct amba_id *id)
1956 spin_lock_init(&ch->lock); 1892 spin_lock_init(&ch->lock);
1957 ch->serving = NULL; 1893 ch->serving = NULL;
1958 ch->signal = -1; 1894 ch->signal = -1;
1959 dev_info(&adev->dev, 1895 dev_dbg(&adev->dev, "physical channel %d is %s\n",
1960 "physical channel %d is %s\n", i, 1896 i, pl08x_phy_channel_busy(ch) ? "BUSY" : "FREE");
1961 pl08x_phy_channel_busy(ch) ? "BUSY" : "FREE");
1962 } 1897 }
1963 1898
1964 /* Register as many memcpy channels as there are physical channels */ 1899 /* Register as many memcpy channels as there are physical channels */
@@ -1974,8 +1909,7 @@ static int pl08x_probe(struct amba_device *adev, const struct amba_id *id)
1974 1909
1975 /* Register slave channels */ 1910 /* Register slave channels */
1976 ret = pl08x_dma_init_virtual_channels(pl08x, &pl08x->slave, 1911 ret = pl08x_dma_init_virtual_channels(pl08x, &pl08x->slave,
1977 pl08x->pd->num_slave_channels, 1912 pl08x->pd->num_slave_channels, true);
1978 true);
1979 if (ret <= 0) { 1913 if (ret <= 0) {
1980 dev_warn(&pl08x->adev->dev, 1914 dev_warn(&pl08x->adev->dev,
1981 "%s failed to enumerate slave channels - %d\n", 1915 "%s failed to enumerate slave channels - %d\n",
@@ -2005,6 +1939,8 @@ static int pl08x_probe(struct amba_device *adev, const struct amba_id *id)
2005 dev_info(&pl08x->adev->dev, "DMA: PL%03x rev%u at 0x%08llx irq %d\n", 1939 dev_info(&pl08x->adev->dev, "DMA: PL%03x rev%u at 0x%08llx irq %d\n",
2006 amba_part(adev), amba_rev(adev), 1940 amba_part(adev), amba_rev(adev),
2007 (unsigned long long)adev->res.start, adev->irq[0]); 1941 (unsigned long long)adev->res.start, adev->irq[0]);
1942
1943 pm_runtime_put(&adev->dev);
2008 return 0; 1944 return 0;
2009 1945
2010out_no_slave_reg: 1946out_no_slave_reg:
@@ -2023,6 +1959,9 @@ out_no_ioremap:
2023 dma_pool_destroy(pl08x->pool); 1959 dma_pool_destroy(pl08x->pool);
2024out_no_lli_pool: 1960out_no_lli_pool:
2025out_no_platdata: 1961out_no_platdata:
1962 pm_runtime_put(&adev->dev);
1963 pm_runtime_disable(&adev->dev);
1964
2026 kfree(pl08x); 1965 kfree(pl08x);
2027out_no_pl08x: 1966out_no_pl08x:
2028 amba_release_regions(adev); 1967 amba_release_regions(adev);
diff --git a/drivers/dma/at_hdmac.c b/drivers/dma/at_hdmac.c
index 6a483eac7b3f..3b99dc62874b 100644
--- a/drivers/dma/at_hdmac.c
+++ b/drivers/dma/at_hdmac.c
@@ -107,10 +107,11 @@ static struct at_desc *atc_desc_get(struct at_dma_chan *atchan)
107{ 107{
108 struct at_desc *desc, *_desc; 108 struct at_desc *desc, *_desc;
109 struct at_desc *ret = NULL; 109 struct at_desc *ret = NULL;
110 unsigned long flags;
110 unsigned int i = 0; 111 unsigned int i = 0;
111 LIST_HEAD(tmp_list); 112 LIST_HEAD(tmp_list);
112 113
113 spin_lock_bh(&atchan->lock); 114 spin_lock_irqsave(&atchan->lock, flags);
114 list_for_each_entry_safe(desc, _desc, &atchan->free_list, desc_node) { 115 list_for_each_entry_safe(desc, _desc, &atchan->free_list, desc_node) {
115 i++; 116 i++;
116 if (async_tx_test_ack(&desc->txd)) { 117 if (async_tx_test_ack(&desc->txd)) {
@@ -121,7 +122,7 @@ static struct at_desc *atc_desc_get(struct at_dma_chan *atchan)
121 dev_dbg(chan2dev(&atchan->chan_common), 122 dev_dbg(chan2dev(&atchan->chan_common),
122 "desc %p not ACKed\n", desc); 123 "desc %p not ACKed\n", desc);
123 } 124 }
124 spin_unlock_bh(&atchan->lock); 125 spin_unlock_irqrestore(&atchan->lock, flags);
125 dev_vdbg(chan2dev(&atchan->chan_common), 126 dev_vdbg(chan2dev(&atchan->chan_common),
126 "scanned %u descriptors on freelist\n", i); 127 "scanned %u descriptors on freelist\n", i);
127 128
@@ -129,9 +130,9 @@ static struct at_desc *atc_desc_get(struct at_dma_chan *atchan)
129 if (!ret) { 130 if (!ret) {
130 ret = atc_alloc_descriptor(&atchan->chan_common, GFP_ATOMIC); 131 ret = atc_alloc_descriptor(&atchan->chan_common, GFP_ATOMIC);
131 if (ret) { 132 if (ret) {
132 spin_lock_bh(&atchan->lock); 133 spin_lock_irqsave(&atchan->lock, flags);
133 atchan->descs_allocated++; 134 atchan->descs_allocated++;
134 spin_unlock_bh(&atchan->lock); 135 spin_unlock_irqrestore(&atchan->lock, flags);
135 } else { 136 } else {
136 dev_err(chan2dev(&atchan->chan_common), 137 dev_err(chan2dev(&atchan->chan_common),
137 "not enough descriptors available\n"); 138 "not enough descriptors available\n");
@@ -150,8 +151,9 @@ static void atc_desc_put(struct at_dma_chan *atchan, struct at_desc *desc)
150{ 151{
151 if (desc) { 152 if (desc) {
152 struct at_desc *child; 153 struct at_desc *child;
154 unsigned long flags;
153 155
154 spin_lock_bh(&atchan->lock); 156 spin_lock_irqsave(&atchan->lock, flags);
155 list_for_each_entry(child, &desc->tx_list, desc_node) 157 list_for_each_entry(child, &desc->tx_list, desc_node)
156 dev_vdbg(chan2dev(&atchan->chan_common), 158 dev_vdbg(chan2dev(&atchan->chan_common),
157 "moving child desc %p to freelist\n", 159 "moving child desc %p to freelist\n",
@@ -160,7 +162,7 @@ static void atc_desc_put(struct at_dma_chan *atchan, struct at_desc *desc)
160 dev_vdbg(chan2dev(&atchan->chan_common), 162 dev_vdbg(chan2dev(&atchan->chan_common),
161 "moving desc %p to freelist\n", desc); 163 "moving desc %p to freelist\n", desc);
162 list_add(&desc->desc_node, &atchan->free_list); 164 list_add(&desc->desc_node, &atchan->free_list);
163 spin_unlock_bh(&atchan->lock); 165 spin_unlock_irqrestore(&atchan->lock, flags);
164 } 166 }
165} 167}
166 168
@@ -299,7 +301,7 @@ atc_chain_complete(struct at_dma_chan *atchan, struct at_desc *desc)
299 301
300 /* for cyclic transfers, 302 /* for cyclic transfers,
301 * no need to replay callback function while stopping */ 303 * no need to replay callback function while stopping */
302 if (!test_bit(ATC_IS_CYCLIC, &atchan->status)) { 304 if (!atc_chan_is_cyclic(atchan)) {
303 dma_async_tx_callback callback = txd->callback; 305 dma_async_tx_callback callback = txd->callback;
304 void *param = txd->callback_param; 306 void *param = txd->callback_param;
305 307
@@ -471,16 +473,17 @@ static void atc_handle_cyclic(struct at_dma_chan *atchan)
471static void atc_tasklet(unsigned long data) 473static void atc_tasklet(unsigned long data)
472{ 474{
473 struct at_dma_chan *atchan = (struct at_dma_chan *)data; 475 struct at_dma_chan *atchan = (struct at_dma_chan *)data;
476 unsigned long flags;
474 477
475 spin_lock(&atchan->lock); 478 spin_lock_irqsave(&atchan->lock, flags);
476 if (test_and_clear_bit(ATC_IS_ERROR, &atchan->status)) 479 if (test_and_clear_bit(ATC_IS_ERROR, &atchan->status))
477 atc_handle_error(atchan); 480 atc_handle_error(atchan);
478 else if (test_bit(ATC_IS_CYCLIC, &atchan->status)) 481 else if (atc_chan_is_cyclic(atchan))
479 atc_handle_cyclic(atchan); 482 atc_handle_cyclic(atchan);
480 else 483 else
481 atc_advance_work(atchan); 484 atc_advance_work(atchan);
482 485
483 spin_unlock(&atchan->lock); 486 spin_unlock_irqrestore(&atchan->lock, flags);
484} 487}
485 488
486static irqreturn_t at_dma_interrupt(int irq, void *dev_id) 489static irqreturn_t at_dma_interrupt(int irq, void *dev_id)
@@ -539,8 +542,9 @@ static dma_cookie_t atc_tx_submit(struct dma_async_tx_descriptor *tx)
539 struct at_desc *desc = txd_to_at_desc(tx); 542 struct at_desc *desc = txd_to_at_desc(tx);
540 struct at_dma_chan *atchan = to_at_dma_chan(tx->chan); 543 struct at_dma_chan *atchan = to_at_dma_chan(tx->chan);
541 dma_cookie_t cookie; 544 dma_cookie_t cookie;
545 unsigned long flags;
542 546
543 spin_lock_bh(&atchan->lock); 547 spin_lock_irqsave(&atchan->lock, flags);
544 cookie = atc_assign_cookie(atchan, desc); 548 cookie = atc_assign_cookie(atchan, desc);
545 549
546 if (list_empty(&atchan->active_list)) { 550 if (list_empty(&atchan->active_list)) {
@@ -554,7 +558,7 @@ static dma_cookie_t atc_tx_submit(struct dma_async_tx_descriptor *tx)
554 list_add_tail(&desc->desc_node, &atchan->queue); 558 list_add_tail(&desc->desc_node, &atchan->queue);
555 } 559 }
556 560
557 spin_unlock_bh(&atchan->lock); 561 spin_unlock_irqrestore(&atchan->lock, flags);
558 562
559 return cookie; 563 return cookie;
560} 564}
@@ -927,28 +931,29 @@ static int atc_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
927 struct at_dma_chan *atchan = to_at_dma_chan(chan); 931 struct at_dma_chan *atchan = to_at_dma_chan(chan);
928 struct at_dma *atdma = to_at_dma(chan->device); 932 struct at_dma *atdma = to_at_dma(chan->device);
929 int chan_id = atchan->chan_common.chan_id; 933 int chan_id = atchan->chan_common.chan_id;
934 unsigned long flags;
930 935
931 LIST_HEAD(list); 936 LIST_HEAD(list);
932 937
933 dev_vdbg(chan2dev(chan), "atc_control (%d)\n", cmd); 938 dev_vdbg(chan2dev(chan), "atc_control (%d)\n", cmd);
934 939
935 if (cmd == DMA_PAUSE) { 940 if (cmd == DMA_PAUSE) {
936 spin_lock_bh(&atchan->lock); 941 spin_lock_irqsave(&atchan->lock, flags);
937 942
938 dma_writel(atdma, CHER, AT_DMA_SUSP(chan_id)); 943 dma_writel(atdma, CHER, AT_DMA_SUSP(chan_id));
939 set_bit(ATC_IS_PAUSED, &atchan->status); 944 set_bit(ATC_IS_PAUSED, &atchan->status);
940 945
941 spin_unlock_bh(&atchan->lock); 946 spin_unlock_irqrestore(&atchan->lock, flags);
942 } else if (cmd == DMA_RESUME) { 947 } else if (cmd == DMA_RESUME) {
943 if (!test_bit(ATC_IS_PAUSED, &atchan->status)) 948 if (!atc_chan_is_paused(atchan))
944 return 0; 949 return 0;
945 950
946 spin_lock_bh(&atchan->lock); 951 spin_lock_irqsave(&atchan->lock, flags);
947 952
948 dma_writel(atdma, CHDR, AT_DMA_RES(chan_id)); 953 dma_writel(atdma, CHDR, AT_DMA_RES(chan_id));
949 clear_bit(ATC_IS_PAUSED, &atchan->status); 954 clear_bit(ATC_IS_PAUSED, &atchan->status);
950 955
951 spin_unlock_bh(&atchan->lock); 956 spin_unlock_irqrestore(&atchan->lock, flags);
952 } else if (cmd == DMA_TERMINATE_ALL) { 957 } else if (cmd == DMA_TERMINATE_ALL) {
953 struct at_desc *desc, *_desc; 958 struct at_desc *desc, *_desc;
954 /* 959 /*
@@ -957,7 +962,7 @@ static int atc_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
957 * channel. We still have to poll the channel enable bit due 962 * channel. We still have to poll the channel enable bit due
958 * to AHB/HSB limitations. 963 * to AHB/HSB limitations.
959 */ 964 */
960 spin_lock_bh(&atchan->lock); 965 spin_lock_irqsave(&atchan->lock, flags);
961 966
962 /* disabling channel: must also remove suspend state */ 967 /* disabling channel: must also remove suspend state */
963 dma_writel(atdma, CHDR, AT_DMA_RES(chan_id) | atchan->mask); 968 dma_writel(atdma, CHDR, AT_DMA_RES(chan_id) | atchan->mask);
@@ -978,7 +983,7 @@ static int atc_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
978 /* if channel dedicated to cyclic operations, free it */ 983 /* if channel dedicated to cyclic operations, free it */
979 clear_bit(ATC_IS_CYCLIC, &atchan->status); 984 clear_bit(ATC_IS_CYCLIC, &atchan->status);
980 985
981 spin_unlock_bh(&atchan->lock); 986 spin_unlock_irqrestore(&atchan->lock, flags);
982 } else { 987 } else {
983 return -ENXIO; 988 return -ENXIO;
984 } 989 }
@@ -1004,9 +1009,10 @@ atc_tx_status(struct dma_chan *chan,
1004 struct at_dma_chan *atchan = to_at_dma_chan(chan); 1009 struct at_dma_chan *atchan = to_at_dma_chan(chan);
1005 dma_cookie_t last_used; 1010 dma_cookie_t last_used;
1006 dma_cookie_t last_complete; 1011 dma_cookie_t last_complete;
1012 unsigned long flags;
1007 enum dma_status ret; 1013 enum dma_status ret;
1008 1014
1009 spin_lock_bh(&atchan->lock); 1015 spin_lock_irqsave(&atchan->lock, flags);
1010 1016
1011 last_complete = atchan->completed_cookie; 1017 last_complete = atchan->completed_cookie;
1012 last_used = chan->cookie; 1018 last_used = chan->cookie;
@@ -1021,7 +1027,7 @@ atc_tx_status(struct dma_chan *chan,
1021 ret = dma_async_is_complete(cookie, last_complete, last_used); 1027 ret = dma_async_is_complete(cookie, last_complete, last_used);
1022 } 1028 }
1023 1029
1024 spin_unlock_bh(&atchan->lock); 1030 spin_unlock_irqrestore(&atchan->lock, flags);
1025 1031
1026 if (ret != DMA_SUCCESS) 1032 if (ret != DMA_SUCCESS)
1027 dma_set_tx_state(txstate, last_complete, last_used, 1033 dma_set_tx_state(txstate, last_complete, last_used,
@@ -1029,7 +1035,7 @@ atc_tx_status(struct dma_chan *chan,
1029 else 1035 else
1030 dma_set_tx_state(txstate, last_complete, last_used, 0); 1036 dma_set_tx_state(txstate, last_complete, last_used, 0);
1031 1037
1032 if (test_bit(ATC_IS_PAUSED, &atchan->status)) 1038 if (atc_chan_is_paused(atchan))
1033 ret = DMA_PAUSED; 1039 ret = DMA_PAUSED;
1034 1040
1035 dev_vdbg(chan2dev(chan), "tx_status %d: cookie = %d (d%d, u%d)\n", 1041 dev_vdbg(chan2dev(chan), "tx_status %d: cookie = %d (d%d, u%d)\n",
@@ -1046,18 +1052,19 @@ atc_tx_status(struct dma_chan *chan,
1046static void atc_issue_pending(struct dma_chan *chan) 1052static void atc_issue_pending(struct dma_chan *chan)
1047{ 1053{
1048 struct at_dma_chan *atchan = to_at_dma_chan(chan); 1054 struct at_dma_chan *atchan = to_at_dma_chan(chan);
1055 unsigned long flags;
1049 1056
1050 dev_vdbg(chan2dev(chan), "issue_pending\n"); 1057 dev_vdbg(chan2dev(chan), "issue_pending\n");
1051 1058
1052 /* Not needed for cyclic transfers */ 1059 /* Not needed for cyclic transfers */
1053 if (test_bit(ATC_IS_CYCLIC, &atchan->status)) 1060 if (atc_chan_is_cyclic(atchan))
1054 return; 1061 return;
1055 1062
1056 spin_lock_bh(&atchan->lock); 1063 spin_lock_irqsave(&atchan->lock, flags);
1057 if (!atc_chan_is_enabled(atchan)) { 1064 if (!atc_chan_is_enabled(atchan)) {
1058 atc_advance_work(atchan); 1065 atc_advance_work(atchan);
1059 } 1066 }
1060 spin_unlock_bh(&atchan->lock); 1067 spin_unlock_irqrestore(&atchan->lock, flags);
1061} 1068}
1062 1069
1063/** 1070/**
@@ -1073,6 +1080,7 @@ static int atc_alloc_chan_resources(struct dma_chan *chan)
1073 struct at_dma *atdma = to_at_dma(chan->device); 1080 struct at_dma *atdma = to_at_dma(chan->device);
1074 struct at_desc *desc; 1081 struct at_desc *desc;
1075 struct at_dma_slave *atslave; 1082 struct at_dma_slave *atslave;
1083 unsigned long flags;
1076 int i; 1084 int i;
1077 u32 cfg; 1085 u32 cfg;
1078 LIST_HEAD(tmp_list); 1086 LIST_HEAD(tmp_list);
@@ -1116,11 +1124,11 @@ static int atc_alloc_chan_resources(struct dma_chan *chan)
1116 list_add_tail(&desc->desc_node, &tmp_list); 1124 list_add_tail(&desc->desc_node, &tmp_list);
1117 } 1125 }
1118 1126
1119 spin_lock_bh(&atchan->lock); 1127 spin_lock_irqsave(&atchan->lock, flags);
1120 atchan->descs_allocated = i; 1128 atchan->descs_allocated = i;
1121 list_splice(&tmp_list, &atchan->free_list); 1129 list_splice(&tmp_list, &atchan->free_list);
1122 atchan->completed_cookie = chan->cookie = 1; 1130 atchan->completed_cookie = chan->cookie = 1;
1123 spin_unlock_bh(&atchan->lock); 1131 spin_unlock_irqrestore(&atchan->lock, flags);
1124 1132
1125 /* channel parameters */ 1133 /* channel parameters */
1126 channel_writel(atchan, CFG, cfg); 1134 channel_writel(atchan, CFG, cfg);
@@ -1293,15 +1301,13 @@ static int __init at_dma_probe(struct platform_device *pdev)
1293 if (dma_has_cap(DMA_MEMCPY, atdma->dma_common.cap_mask)) 1301 if (dma_has_cap(DMA_MEMCPY, atdma->dma_common.cap_mask))
1294 atdma->dma_common.device_prep_dma_memcpy = atc_prep_dma_memcpy; 1302 atdma->dma_common.device_prep_dma_memcpy = atc_prep_dma_memcpy;
1295 1303
1296 if (dma_has_cap(DMA_SLAVE, atdma->dma_common.cap_mask)) 1304 if (dma_has_cap(DMA_SLAVE, atdma->dma_common.cap_mask)) {
1297 atdma->dma_common.device_prep_slave_sg = atc_prep_slave_sg; 1305 atdma->dma_common.device_prep_slave_sg = atc_prep_slave_sg;
1298 1306 /* controller can do slave DMA: can trigger cyclic transfers */
1299 if (dma_has_cap(DMA_CYCLIC, atdma->dma_common.cap_mask)) 1307 dma_cap_set(DMA_CYCLIC, atdma->dma_common.cap_mask);
1300 atdma->dma_common.device_prep_dma_cyclic = atc_prep_dma_cyclic; 1308 atdma->dma_common.device_prep_dma_cyclic = atc_prep_dma_cyclic;
1301
1302 if (dma_has_cap(DMA_SLAVE, atdma->dma_common.cap_mask) ||
1303 dma_has_cap(DMA_CYCLIC, atdma->dma_common.cap_mask))
1304 atdma->dma_common.device_control = atc_control; 1309 atdma->dma_common.device_control = atc_control;
1310 }
1305 1311
1306 dma_writel(atdma, EN, AT_DMA_ENABLE); 1312 dma_writel(atdma, EN, AT_DMA_ENABLE);
1307 1313
@@ -1377,27 +1383,112 @@ static void at_dma_shutdown(struct platform_device *pdev)
1377 clk_disable(atdma->clk); 1383 clk_disable(atdma->clk);
1378} 1384}
1379 1385
1386static int at_dma_prepare(struct device *dev)
1387{
1388 struct platform_device *pdev = to_platform_device(dev);
1389 struct at_dma *atdma = platform_get_drvdata(pdev);
1390 struct dma_chan *chan, *_chan;
1391
1392 list_for_each_entry_safe(chan, _chan, &atdma->dma_common.channels,
1393 device_node) {
1394 struct at_dma_chan *atchan = to_at_dma_chan(chan);
1395 /* wait for transaction completion (except in cyclic case) */
1396 if (atc_chan_is_enabled(atchan) && !atc_chan_is_cyclic(atchan))
1397 return -EAGAIN;
1398 }
1399 return 0;
1400}
1401
1402static void atc_suspend_cyclic(struct at_dma_chan *atchan)
1403{
1404 struct dma_chan *chan = &atchan->chan_common;
1405
1406 /* Channel should be paused by user
1407 * do it anyway even if it is not done already */
1408 if (!atc_chan_is_paused(atchan)) {
1409 dev_warn(chan2dev(chan),
1410 "cyclic channel not paused, should be done by channel user\n");
1411 atc_control(chan, DMA_PAUSE, 0);
1412 }
1413
1414 /* now preserve additional data for cyclic operations */
1415 /* next descriptor address in the cyclic list */
1416 atchan->save_dscr = channel_readl(atchan, DSCR);
1417
1418 vdbg_dump_regs(atchan);
1419}
1420
1380static int at_dma_suspend_noirq(struct device *dev) 1421static int at_dma_suspend_noirq(struct device *dev)
1381{ 1422{
1382 struct platform_device *pdev = to_platform_device(dev); 1423 struct platform_device *pdev = to_platform_device(dev);
1383 struct at_dma *atdma = platform_get_drvdata(pdev); 1424 struct at_dma *atdma = platform_get_drvdata(pdev);
1425 struct dma_chan *chan, *_chan;
1384 1426
1385 at_dma_off(platform_get_drvdata(pdev)); 1427 /* preserve data */
1428 list_for_each_entry_safe(chan, _chan, &atdma->dma_common.channels,
1429 device_node) {
1430 struct at_dma_chan *atchan = to_at_dma_chan(chan);
1431
1432 if (atc_chan_is_cyclic(atchan))
1433 atc_suspend_cyclic(atchan);
1434 atchan->save_cfg = channel_readl(atchan, CFG);
1435 }
1436 atdma->save_imr = dma_readl(atdma, EBCIMR);
1437
1438 /* disable DMA controller */
1439 at_dma_off(atdma);
1386 clk_disable(atdma->clk); 1440 clk_disable(atdma->clk);
1387 return 0; 1441 return 0;
1388} 1442}
1389 1443
1444static void atc_resume_cyclic(struct at_dma_chan *atchan)
1445{
1446 struct at_dma *atdma = to_at_dma(atchan->chan_common.device);
1447
1448 /* restore channel status for cyclic descriptors list:
1449 * next descriptor in the cyclic list at the time of suspend */
1450 channel_writel(atchan, SADDR, 0);
1451 channel_writel(atchan, DADDR, 0);
1452 channel_writel(atchan, CTRLA, 0);
1453 channel_writel(atchan, CTRLB, 0);
1454 channel_writel(atchan, DSCR, atchan->save_dscr);
1455 dma_writel(atdma, CHER, atchan->mask);
1456
1457 /* channel pause status should be removed by channel user
1458 * We cannot take the initiative to do it here */
1459
1460 vdbg_dump_regs(atchan);
1461}
1462
1390static int at_dma_resume_noirq(struct device *dev) 1463static int at_dma_resume_noirq(struct device *dev)
1391{ 1464{
1392 struct platform_device *pdev = to_platform_device(dev); 1465 struct platform_device *pdev = to_platform_device(dev);
1393 struct at_dma *atdma = platform_get_drvdata(pdev); 1466 struct at_dma *atdma = platform_get_drvdata(pdev);
1467 struct dma_chan *chan, *_chan;
1394 1468
1469 /* bring back DMA controller */
1395 clk_enable(atdma->clk); 1470 clk_enable(atdma->clk);
1396 dma_writel(atdma, EN, AT_DMA_ENABLE); 1471 dma_writel(atdma, EN, AT_DMA_ENABLE);
1472
1473 /* clear any pending interrupt */
1474 while (dma_readl(atdma, EBCISR))
1475 cpu_relax();
1476
1477 /* restore saved data */
1478 dma_writel(atdma, EBCIER, atdma->save_imr);
1479 list_for_each_entry_safe(chan, _chan, &atdma->dma_common.channels,
1480 device_node) {
1481 struct at_dma_chan *atchan = to_at_dma_chan(chan);
1482
1483 channel_writel(atchan, CFG, atchan->save_cfg);
1484 if (atc_chan_is_cyclic(atchan))
1485 atc_resume_cyclic(atchan);
1486 }
1397 return 0; 1487 return 0;
1398} 1488}
1399 1489
1400static const struct dev_pm_ops at_dma_dev_pm_ops = { 1490static const struct dev_pm_ops at_dma_dev_pm_ops = {
1491 .prepare = at_dma_prepare,
1401 .suspend_noirq = at_dma_suspend_noirq, 1492 .suspend_noirq = at_dma_suspend_noirq,
1402 .resume_noirq = at_dma_resume_noirq, 1493 .resume_noirq = at_dma_resume_noirq,
1403}; 1494};
diff --git a/drivers/dma/at_hdmac_regs.h b/drivers/dma/at_hdmac_regs.h
index 087dbf1dd39c..aa4c9aebab7c 100644
--- a/drivers/dma/at_hdmac_regs.h
+++ b/drivers/dma/at_hdmac_regs.h
@@ -204,6 +204,9 @@ enum atc_status {
204 * @status: transmit status information from irq/prep* functions 204 * @status: transmit status information from irq/prep* functions
205 * to tasklet (use atomic operations) 205 * to tasklet (use atomic operations)
206 * @tasklet: bottom half to finish transaction work 206 * @tasklet: bottom half to finish transaction work
207 * @save_cfg: configuration register that is saved on suspend/resume cycle
208 * @save_dscr: for cyclic operations, preserve next descriptor address in
209 * the cyclic list on suspend/resume cycle
207 * @lock: serializes enqueue/dequeue operations to descriptors lists 210 * @lock: serializes enqueue/dequeue operations to descriptors lists
208 * @completed_cookie: identifier for the most recently completed operation 211 * @completed_cookie: identifier for the most recently completed operation
209 * @active_list: list of descriptors dmaengine is being running on 212 * @active_list: list of descriptors dmaengine is being running on
@@ -218,6 +221,8 @@ struct at_dma_chan {
218 u8 mask; 221 u8 mask;
219 unsigned long status; 222 unsigned long status;
220 struct tasklet_struct tasklet; 223 struct tasklet_struct tasklet;
224 u32 save_cfg;
225 u32 save_dscr;
221 226
222 spinlock_t lock; 227 spinlock_t lock;
223 228
@@ -248,6 +253,7 @@ static inline struct at_dma_chan *to_at_dma_chan(struct dma_chan *dchan)
248 * @chan_common: common dmaengine dma_device object members 253 * @chan_common: common dmaengine dma_device object members
249 * @ch_regs: memory mapped register base 254 * @ch_regs: memory mapped register base
250 * @clk: dma controller clock 255 * @clk: dma controller clock
256 * @save_imr: interrupt mask register that is saved on suspend/resume cycle
251 * @all_chan_mask: all channels availlable in a mask 257 * @all_chan_mask: all channels availlable in a mask
252 * @dma_desc_pool: base of DMA descriptor region (DMA address) 258 * @dma_desc_pool: base of DMA descriptor region (DMA address)
253 * @chan: channels table to store at_dma_chan structures 259 * @chan: channels table to store at_dma_chan structures
@@ -256,6 +262,7 @@ struct at_dma {
256 struct dma_device dma_common; 262 struct dma_device dma_common;
257 void __iomem *regs; 263 void __iomem *regs;
258 struct clk *clk; 264 struct clk *clk;
265 u32 save_imr;
259 266
260 u8 all_chan_mask; 267 u8 all_chan_mask;
261 268
@@ -355,6 +362,23 @@ static inline int atc_chan_is_enabled(struct at_dma_chan *atchan)
355 return !!(dma_readl(atdma, CHSR) & atchan->mask); 362 return !!(dma_readl(atdma, CHSR) & atchan->mask);
356} 363}
357 364
365/**
366 * atc_chan_is_paused - test channel pause/resume status
367 * @atchan: channel we want to test status
368 */
369static inline int atc_chan_is_paused(struct at_dma_chan *atchan)
370{
371 return test_bit(ATC_IS_PAUSED, &atchan->status);
372}
373
374/**
375 * atc_chan_is_cyclic - test if given channel has cyclic property set
376 * @atchan: channel we want to test status
377 */
378static inline int atc_chan_is_cyclic(struct at_dma_chan *atchan)
379{
380 return test_bit(ATC_IS_CYCLIC, &atchan->status);
381}
358 382
359/** 383/**
360 * set_desc_eol - set end-of-link to descriptor so it will end transfer 384 * set_desc_eol - set end-of-link to descriptor so it will end transfer
diff --git a/drivers/dma/dmatest.c b/drivers/dma/dmatest.c
index 765f5ff22304..eb1d8641cf5c 100644
--- a/drivers/dma/dmatest.c
+++ b/drivers/dma/dmatest.c
@@ -10,6 +10,7 @@
10#include <linux/delay.h> 10#include <linux/delay.h>
11#include <linux/dma-mapping.h> 11#include <linux/dma-mapping.h>
12#include <linux/dmaengine.h> 12#include <linux/dmaengine.h>
13#include <linux/freezer.h>
13#include <linux/init.h> 14#include <linux/init.h>
14#include <linux/kthread.h> 15#include <linux/kthread.h>
15#include <linux/module.h> 16#include <linux/module.h>
@@ -251,6 +252,7 @@ static int dmatest_func(void *data)
251 int i; 252 int i;
252 253
253 thread_name = current->comm; 254 thread_name = current->comm;
255 set_freezable_with_signal();
254 256
255 ret = -ENOMEM; 257 ret = -ENOMEM;
256 258
@@ -305,7 +307,8 @@ static int dmatest_func(void *data)
305 dma_addr_t dma_srcs[src_cnt]; 307 dma_addr_t dma_srcs[src_cnt];
306 dma_addr_t dma_dsts[dst_cnt]; 308 dma_addr_t dma_dsts[dst_cnt];
307 struct completion cmp; 309 struct completion cmp;
308 unsigned long tmo = msecs_to_jiffies(timeout); 310 unsigned long start, tmo, end = 0 /* compiler... */;
311 bool reload = true;
309 u8 align = 0; 312 u8 align = 0;
310 313
311 total_tests++; 314 total_tests++;
@@ -404,7 +407,17 @@ static int dmatest_func(void *data)
404 } 407 }
405 dma_async_issue_pending(chan); 408 dma_async_issue_pending(chan);
406 409
407 tmo = wait_for_completion_timeout(&cmp, tmo); 410 do {
411 start = jiffies;
412 if (reload)
413 end = start + msecs_to_jiffies(timeout);
414 else if (end <= start)
415 end = start + 1;
416 tmo = wait_for_completion_interruptible_timeout(&cmp,
417 end - start);
418 reload = try_to_freeze();
419 } while (tmo == -ERESTARTSYS);
420
408 status = dma_async_is_tx_complete(chan, cookie, NULL, NULL); 421 status = dma_async_is_tx_complete(chan, cookie, NULL, NULL);
409 422
410 if (tmo == 0) { 423 if (tmo == 0) {
@@ -477,6 +490,8 @@ err_srcs:
477 pr_notice("%s: terminating after %u tests, %u failures (status %d)\n", 490 pr_notice("%s: terminating after %u tests, %u failures (status %d)\n",
478 thread_name, total_tests, failed_tests, ret); 491 thread_name, total_tests, failed_tests, ret);
479 492
493 /* terminate all transfers on specified channels */
494 chan->device->device_control(chan, DMA_TERMINATE_ALL, 0);
480 if (iterations > 0) 495 if (iterations > 0)
481 while (!kthread_should_stop()) { 496 while (!kthread_should_stop()) {
482 DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wait_dmatest_exit); 497 DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wait_dmatest_exit);
@@ -499,6 +514,10 @@ static void dmatest_cleanup_channel(struct dmatest_chan *dtc)
499 list_del(&thread->node); 514 list_del(&thread->node);
500 kfree(thread); 515 kfree(thread);
501 } 516 }
517
518 /* terminate all transfers on specified channels */
519 dtc->chan->device->device_control(dtc->chan, DMA_TERMINATE_ALL, 0);
520
502 kfree(dtc); 521 kfree(dtc);
503} 522}
504 523
diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c
index 7bd7e98548cd..b5cc27dc9a51 100644
--- a/drivers/dma/imx-sdma.c
+++ b/drivers/dma/imx-sdma.c
@@ -318,6 +318,7 @@ struct sdma_engine {
318 dma_addr_t context_phys; 318 dma_addr_t context_phys;
319 struct dma_device dma_device; 319 struct dma_device dma_device;
320 struct clk *clk; 320 struct clk *clk;
321 struct mutex channel_0_lock;
321 struct sdma_script_start_addrs *script_addrs; 322 struct sdma_script_start_addrs *script_addrs;
322}; 323};
323 324
@@ -415,11 +416,15 @@ static int sdma_load_script(struct sdma_engine *sdma, void *buf, int size,
415 dma_addr_t buf_phys; 416 dma_addr_t buf_phys;
416 int ret; 417 int ret;
417 418
419 mutex_lock(&sdma->channel_0_lock);
420
418 buf_virt = dma_alloc_coherent(NULL, 421 buf_virt = dma_alloc_coherent(NULL,
419 size, 422 size,
420 &buf_phys, GFP_KERNEL); 423 &buf_phys, GFP_KERNEL);
421 if (!buf_virt) 424 if (!buf_virt) {
422 return -ENOMEM; 425 ret = -ENOMEM;
426 goto err_out;
427 }
423 428
424 bd0->mode.command = C0_SETPM; 429 bd0->mode.command = C0_SETPM;
425 bd0->mode.status = BD_DONE | BD_INTR | BD_WRAP | BD_EXTD; 430 bd0->mode.status = BD_DONE | BD_INTR | BD_WRAP | BD_EXTD;
@@ -433,6 +438,9 @@ static int sdma_load_script(struct sdma_engine *sdma, void *buf, int size,
433 438
434 dma_free_coherent(NULL, size, buf_virt, buf_phys); 439 dma_free_coherent(NULL, size, buf_virt, buf_phys);
435 440
441err_out:
442 mutex_unlock(&sdma->channel_0_lock);
443
436 return ret; 444 return ret;
437} 445}
438 446
@@ -656,6 +664,8 @@ static int sdma_load_context(struct sdma_channel *sdmac)
656 dev_dbg(sdma->dev, "event_mask0 = 0x%08x\n", sdmac->event_mask0); 664 dev_dbg(sdma->dev, "event_mask0 = 0x%08x\n", sdmac->event_mask0);
657 dev_dbg(sdma->dev, "event_mask1 = 0x%08x\n", sdmac->event_mask1); 665 dev_dbg(sdma->dev, "event_mask1 = 0x%08x\n", sdmac->event_mask1);
658 666
667 mutex_lock(&sdma->channel_0_lock);
668
659 memset(context, 0, sizeof(*context)); 669 memset(context, 0, sizeof(*context));
660 context->channel_state.pc = load_address; 670 context->channel_state.pc = load_address;
661 671
@@ -676,6 +686,8 @@ static int sdma_load_context(struct sdma_channel *sdmac)
676 686
677 ret = sdma_run_channel(&sdma->channel[0]); 687 ret = sdma_run_channel(&sdma->channel[0]);
678 688
689 mutex_unlock(&sdma->channel_0_lock);
690
679 return ret; 691 return ret;
680} 692}
681 693
@@ -1131,18 +1143,17 @@ static void sdma_add_scripts(struct sdma_engine *sdma,
1131 saddr_arr[i] = addr_arr[i]; 1143 saddr_arr[i] = addr_arr[i];
1132} 1144}
1133 1145
1134static int __init sdma_get_firmware(struct sdma_engine *sdma, 1146static void sdma_load_firmware(const struct firmware *fw, void *context)
1135 const char *fw_name)
1136{ 1147{
1137 const struct firmware *fw; 1148 struct sdma_engine *sdma = context;
1138 const struct sdma_firmware_header *header; 1149 const struct sdma_firmware_header *header;
1139 int ret;
1140 const struct sdma_script_start_addrs *addr; 1150 const struct sdma_script_start_addrs *addr;
1141 unsigned short *ram_code; 1151 unsigned short *ram_code;
1142 1152
1143 ret = request_firmware(&fw, fw_name, sdma->dev); 1153 if (!fw) {
1144 if (ret) 1154 dev_err(sdma->dev, "firmware not found\n");
1145 return ret; 1155 return;
1156 }
1146 1157
1147 if (fw->size < sizeof(*header)) 1158 if (fw->size < sizeof(*header))
1148 goto err_firmware; 1159 goto err_firmware;
@@ -1172,6 +1183,16 @@ static int __init sdma_get_firmware(struct sdma_engine *sdma,
1172 1183
1173err_firmware: 1184err_firmware:
1174 release_firmware(fw); 1185 release_firmware(fw);
1186}
1187
1188static int __init sdma_get_firmware(struct sdma_engine *sdma,
1189 const char *fw_name)
1190{
1191 int ret;
1192
1193 ret = request_firmware_nowait(THIS_MODULE,
1194 FW_ACTION_HOTPLUG, fw_name, sdma->dev,
1195 GFP_KERNEL, sdma, sdma_load_firmware);
1175 1196
1176 return ret; 1197 return ret;
1177} 1198}
@@ -1269,11 +1290,14 @@ static int __init sdma_probe(struct platform_device *pdev)
1269 struct sdma_platform_data *pdata = pdev->dev.platform_data; 1290 struct sdma_platform_data *pdata = pdev->dev.platform_data;
1270 int i; 1291 int i;
1271 struct sdma_engine *sdma; 1292 struct sdma_engine *sdma;
1293 s32 *saddr_arr;
1272 1294
1273 sdma = kzalloc(sizeof(*sdma), GFP_KERNEL); 1295 sdma = kzalloc(sizeof(*sdma), GFP_KERNEL);
1274 if (!sdma) 1296 if (!sdma)
1275 return -ENOMEM; 1297 return -ENOMEM;
1276 1298
1299 mutex_init(&sdma->channel_0_lock);
1300
1277 sdma->dev = &pdev->dev; 1301 sdma->dev = &pdev->dev;
1278 1302
1279 iores = platform_get_resource(pdev, IORESOURCE_MEM, 0); 1303 iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -1310,6 +1334,11 @@ static int __init sdma_probe(struct platform_device *pdev)
1310 goto err_alloc; 1334 goto err_alloc;
1311 } 1335 }
1312 1336
1337 /* initially no scripts available */
1338 saddr_arr = (s32 *)sdma->script_addrs;
1339 for (i = 0; i < SDMA_SCRIPT_ADDRS_ARRAY_SIZE_V1; i++)
1340 saddr_arr[i] = -EINVAL;
1341
1313 if (of_id) 1342 if (of_id)
1314 pdev->id_entry = of_id->data; 1343 pdev->id_entry = of_id->data;
1315 sdma->devtype = pdev->id_entry->driver_data; 1344 sdma->devtype = pdev->id_entry->driver_data;
diff --git a/drivers/dma/mxs-dma.c b/drivers/dma/mxs-dma.c
index be641cbd36fc..b4588bdd98bb 100644
--- a/drivers/dma/mxs-dma.c
+++ b/drivers/dma/mxs-dma.c
@@ -130,6 +130,23 @@ struct mxs_dma_engine {
130 struct mxs_dma_chan mxs_chans[MXS_DMA_CHANNELS]; 130 struct mxs_dma_chan mxs_chans[MXS_DMA_CHANNELS];
131}; 131};
132 132
133static inline void mxs_dma_clkgate(struct mxs_dma_chan *mxs_chan, int enable)
134{
135 struct mxs_dma_engine *mxs_dma = mxs_chan->mxs_dma;
136 int chan_id = mxs_chan->chan.chan_id;
137 int set_clr = enable ? MXS_CLR_ADDR : MXS_SET_ADDR;
138
139 /* enable apbh channel clock */
140 if (dma_is_apbh()) {
141 if (apbh_is_old())
142 writel(1 << (chan_id + BP_APBH_CTRL0_CLKGATE_CHANNEL),
143 mxs_dma->base + HW_APBHX_CTRL0 + set_clr);
144 else
145 writel(1 << chan_id,
146 mxs_dma->base + HW_APBHX_CTRL0 + set_clr);
147 }
148}
149
133static void mxs_dma_reset_chan(struct mxs_dma_chan *mxs_chan) 150static void mxs_dma_reset_chan(struct mxs_dma_chan *mxs_chan)
134{ 151{
135 struct mxs_dma_engine *mxs_dma = mxs_chan->mxs_dma; 152 struct mxs_dma_engine *mxs_dma = mxs_chan->mxs_dma;
@@ -148,38 +165,21 @@ static void mxs_dma_enable_chan(struct mxs_dma_chan *mxs_chan)
148 struct mxs_dma_engine *mxs_dma = mxs_chan->mxs_dma; 165 struct mxs_dma_engine *mxs_dma = mxs_chan->mxs_dma;
149 int chan_id = mxs_chan->chan.chan_id; 166 int chan_id = mxs_chan->chan.chan_id;
150 167
168 /* clkgate needs to be enabled before writing other registers */
169 mxs_dma_clkgate(mxs_chan, 1);
170
151 /* set cmd_addr up */ 171 /* set cmd_addr up */
152 writel(mxs_chan->ccw_phys, 172 writel(mxs_chan->ccw_phys,
153 mxs_dma->base + HW_APBHX_CHn_NXTCMDAR(chan_id)); 173 mxs_dma->base + HW_APBHX_CHn_NXTCMDAR(chan_id));
154 174
155 /* enable apbh channel clock */
156 if (dma_is_apbh()) {
157 if (apbh_is_old())
158 writel(1 << (chan_id + BP_APBH_CTRL0_CLKGATE_CHANNEL),
159 mxs_dma->base + HW_APBHX_CTRL0 + MXS_CLR_ADDR);
160 else
161 writel(1 << chan_id,
162 mxs_dma->base + HW_APBHX_CTRL0 + MXS_CLR_ADDR);
163 }
164
165 /* write 1 to SEMA to kick off the channel */ 175 /* write 1 to SEMA to kick off the channel */
166 writel(1, mxs_dma->base + HW_APBHX_CHn_SEMA(chan_id)); 176 writel(1, mxs_dma->base + HW_APBHX_CHn_SEMA(chan_id));
167} 177}
168 178
169static void mxs_dma_disable_chan(struct mxs_dma_chan *mxs_chan) 179static void mxs_dma_disable_chan(struct mxs_dma_chan *mxs_chan)
170{ 180{
171 struct mxs_dma_engine *mxs_dma = mxs_chan->mxs_dma;
172 int chan_id = mxs_chan->chan.chan_id;
173
174 /* disable apbh channel clock */ 181 /* disable apbh channel clock */
175 if (dma_is_apbh()) { 182 mxs_dma_clkgate(mxs_chan, 0);
176 if (apbh_is_old())
177 writel(1 << (chan_id + BP_APBH_CTRL0_CLKGATE_CHANNEL),
178 mxs_dma->base + HW_APBHX_CTRL0 + MXS_SET_ADDR);
179 else
180 writel(1 << chan_id,
181 mxs_dma->base + HW_APBHX_CTRL0 + MXS_SET_ADDR);
182 }
183 183
184 mxs_chan->status = DMA_SUCCESS; 184 mxs_chan->status = DMA_SUCCESS;
185} 185}
@@ -338,7 +338,10 @@ static int mxs_dma_alloc_chan_resources(struct dma_chan *chan)
338 if (ret) 338 if (ret)
339 goto err_clk; 339 goto err_clk;
340 340
341 /* clkgate needs to be enabled for reset to finish */
342 mxs_dma_clkgate(mxs_chan, 1);
341 mxs_dma_reset_chan(mxs_chan); 343 mxs_dma_reset_chan(mxs_chan);
344 mxs_dma_clkgate(mxs_chan, 0);
342 345
343 dma_async_tx_descriptor_init(&mxs_chan->desc, chan); 346 dma_async_tx_descriptor_init(&mxs_chan->desc, chan);
344 mxs_chan->desc.tx_submit = mxs_dma_tx_submit; 347 mxs_chan->desc.tx_submit = mxs_dma_tx_submit;
diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c
index 00eee59e8b33..621134fdba4c 100644
--- a/drivers/dma/pl330.c
+++ b/drivers/dma/pl330.c
@@ -17,6 +17,8 @@
17#include <linux/interrupt.h> 17#include <linux/interrupt.h>
18#include <linux/amba/bus.h> 18#include <linux/amba/bus.h>
19#include <linux/amba/pl330.h> 19#include <linux/amba/pl330.h>
20#include <linux/pm_runtime.h>
21#include <linux/scatterlist.h>
20 22
21#define NR_DEFAULT_DESC 16 23#define NR_DEFAULT_DESC 16
22 24
@@ -68,6 +70,14 @@ struct dma_pl330_chan {
68 * NULL if the channel is available to be acquired. 70 * NULL if the channel is available to be acquired.
69 */ 71 */
70 void *pl330_chid; 72 void *pl330_chid;
73
74 /* For D-to-M and M-to-D channels */
75 int burst_sz; /* the peripheral fifo width */
76 int burst_len; /* the number of burst */
77 dma_addr_t fifo_addr;
78
79 /* for cyclic capability */
80 bool cyclic;
71}; 81};
72 82
73struct dma_pl330_dmac { 83struct dma_pl330_dmac {
@@ -83,6 +93,8 @@ struct dma_pl330_dmac {
83 93
84 /* Peripheral channels connected to this DMAC */ 94 /* Peripheral channels connected to this DMAC */
85 struct dma_pl330_chan *peripherals; /* keep at end */ 95 struct dma_pl330_chan *peripherals; /* keep at end */
96
97 struct clk *clk;
86}; 98};
87 99
88struct dma_pl330_desc { 100struct dma_pl330_desc {
@@ -152,6 +164,31 @@ static inline void free_desc_list(struct list_head *list)
152 spin_unlock_irqrestore(&pdmac->pool_lock, flags); 164 spin_unlock_irqrestore(&pdmac->pool_lock, flags);
153} 165}
154 166
167static inline void handle_cyclic_desc_list(struct list_head *list)
168{
169 struct dma_pl330_desc *desc;
170 struct dma_pl330_chan *pch;
171 unsigned long flags;
172
173 if (list_empty(list))
174 return;
175
176 list_for_each_entry(desc, list, node) {
177 dma_async_tx_callback callback;
178
179 /* Change status to reload it */
180 desc->status = PREP;
181 pch = desc->pchan;
182 callback = desc->txd.callback;
183 if (callback)
184 callback(desc->txd.callback_param);
185 }
186
187 spin_lock_irqsave(&pch->lock, flags);
188 list_splice_tail_init(list, &pch->work_list);
189 spin_unlock_irqrestore(&pch->lock, flags);
190}
191
155static inline void fill_queue(struct dma_pl330_chan *pch) 192static inline void fill_queue(struct dma_pl330_chan *pch)
156{ 193{
157 struct dma_pl330_desc *desc; 194 struct dma_pl330_desc *desc;
@@ -205,7 +242,10 @@ static void pl330_tasklet(unsigned long data)
205 242
206 spin_unlock_irqrestore(&pch->lock, flags); 243 spin_unlock_irqrestore(&pch->lock, flags);
207 244
208 free_desc_list(&list); 245 if (pch->cyclic)
246 handle_cyclic_desc_list(&list);
247 else
248 free_desc_list(&list);
209} 249}
210 250
211static void dma_pl330_rqcb(void *token, enum pl330_op_err err) 251static void dma_pl330_rqcb(void *token, enum pl330_op_err err)
@@ -236,6 +276,7 @@ static int pl330_alloc_chan_resources(struct dma_chan *chan)
236 spin_lock_irqsave(&pch->lock, flags); 276 spin_lock_irqsave(&pch->lock, flags);
237 277
238 pch->completed = chan->cookie = 1; 278 pch->completed = chan->cookie = 1;
279 pch->cyclic = false;
239 280
240 pch->pl330_chid = pl330_request_channel(&pdmac->pif); 281 pch->pl330_chid = pl330_request_channel(&pdmac->pif);
241 if (!pch->pl330_chid) { 282 if (!pch->pl330_chid) {
@@ -253,25 +294,52 @@ static int pl330_alloc_chan_resources(struct dma_chan *chan)
253static int pl330_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, unsigned long arg) 294static int pl330_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, unsigned long arg)
254{ 295{
255 struct dma_pl330_chan *pch = to_pchan(chan); 296 struct dma_pl330_chan *pch = to_pchan(chan);
256 struct dma_pl330_desc *desc; 297 struct dma_pl330_desc *desc, *_dt;
257 unsigned long flags; 298 unsigned long flags;
299 struct dma_pl330_dmac *pdmac = pch->dmac;
300 struct dma_slave_config *slave_config;
301 LIST_HEAD(list);
258 302
259 /* Only supports DMA_TERMINATE_ALL */ 303 switch (cmd) {
260 if (cmd != DMA_TERMINATE_ALL) 304 case DMA_TERMINATE_ALL:
261 return -ENXIO; 305 spin_lock_irqsave(&pch->lock, flags);
262
263 spin_lock_irqsave(&pch->lock, flags);
264
265 /* FLUSH the PL330 Channel thread */
266 pl330_chan_ctrl(pch->pl330_chid, PL330_OP_FLUSH);
267 306
268 /* Mark all desc done */ 307 /* FLUSH the PL330 Channel thread */
269 list_for_each_entry(desc, &pch->work_list, node) 308 pl330_chan_ctrl(pch->pl330_chid, PL330_OP_FLUSH);
270 desc->status = DONE;
271 309
272 spin_unlock_irqrestore(&pch->lock, flags); 310 /* Mark all desc done */
311 list_for_each_entry_safe(desc, _dt, &pch->work_list , node) {
312 desc->status = DONE;
313 pch->completed = desc->txd.cookie;
314 list_move_tail(&desc->node, &list);
315 }
273 316
274 pl330_tasklet((unsigned long) pch); 317 list_splice_tail_init(&list, &pdmac->desc_pool);
318 spin_unlock_irqrestore(&pch->lock, flags);
319 break;
320 case DMA_SLAVE_CONFIG:
321 slave_config = (struct dma_slave_config *)arg;
322
323 if (slave_config->direction == DMA_TO_DEVICE) {
324 if (slave_config->dst_addr)
325 pch->fifo_addr = slave_config->dst_addr;
326 if (slave_config->dst_addr_width)
327 pch->burst_sz = __ffs(slave_config->dst_addr_width);
328 if (slave_config->dst_maxburst)
329 pch->burst_len = slave_config->dst_maxburst;
330 } else if (slave_config->direction == DMA_FROM_DEVICE) {
331 if (slave_config->src_addr)
332 pch->fifo_addr = slave_config->src_addr;
333 if (slave_config->src_addr_width)
334 pch->burst_sz = __ffs(slave_config->src_addr_width);
335 if (slave_config->src_maxburst)
336 pch->burst_len = slave_config->src_maxburst;
337 }
338 break;
339 default:
340 dev_err(pch->dmac->pif.dev, "Not supported command.\n");
341 return -ENXIO;
342 }
275 343
276 return 0; 344 return 0;
277} 345}
@@ -288,6 +356,9 @@ static void pl330_free_chan_resources(struct dma_chan *chan)
288 pl330_release_channel(pch->pl330_chid); 356 pl330_release_channel(pch->pl330_chid);
289 pch->pl330_chid = NULL; 357 pch->pl330_chid = NULL;
290 358
359 if (pch->cyclic)
360 list_splice_tail_init(&pch->work_list, &pch->dmac->desc_pool);
361
291 spin_unlock_irqrestore(&pch->lock, flags); 362 spin_unlock_irqrestore(&pch->lock, flags);
292} 363}
293 364
@@ -453,7 +524,7 @@ static struct dma_pl330_desc *pl330_get_desc(struct dma_pl330_chan *pch)
453 524
454 if (peri) { 525 if (peri) {
455 desc->req.rqtype = peri->rqtype; 526 desc->req.rqtype = peri->rqtype;
456 desc->req.peri = peri->peri_id; 527 desc->req.peri = pch->chan.chan_id;
457 } else { 528 } else {
458 desc->req.rqtype = MEMTOMEM; 529 desc->req.rqtype = MEMTOMEM;
459 desc->req.peri = 0; 530 desc->req.peri = 0;
@@ -524,6 +595,51 @@ static inline int get_burst_len(struct dma_pl330_desc *desc, size_t len)
524 return burst_len; 595 return burst_len;
525} 596}
526 597
598static struct dma_async_tx_descriptor *pl330_prep_dma_cyclic(
599 struct dma_chan *chan, dma_addr_t dma_addr, size_t len,
600 size_t period_len, enum dma_data_direction direction)
601{
602 struct dma_pl330_desc *desc;
603 struct dma_pl330_chan *pch = to_pchan(chan);
604 dma_addr_t dst;
605 dma_addr_t src;
606
607 desc = pl330_get_desc(pch);
608 if (!desc) {
609 dev_err(pch->dmac->pif.dev, "%s:%d Unable to fetch desc\n",
610 __func__, __LINE__);
611 return NULL;
612 }
613
614 switch (direction) {
615 case DMA_TO_DEVICE:
616 desc->rqcfg.src_inc = 1;
617 desc->rqcfg.dst_inc = 0;
618 src = dma_addr;
619 dst = pch->fifo_addr;
620 break;
621 case DMA_FROM_DEVICE:
622 desc->rqcfg.src_inc = 0;
623 desc->rqcfg.dst_inc = 1;
624 src = pch->fifo_addr;
625 dst = dma_addr;
626 break;
627 default:
628 dev_err(pch->dmac->pif.dev, "%s:%d Invalid dma direction\n",
629 __func__, __LINE__);
630 return NULL;
631 }
632
633 desc->rqcfg.brst_size = pch->burst_sz;
634 desc->rqcfg.brst_len = 1;
635
636 pch->cyclic = true;
637
638 fill_px(&desc->px, dst, src, period_len);
639
640 return &desc->txd;
641}
642
527static struct dma_async_tx_descriptor * 643static struct dma_async_tx_descriptor *
528pl330_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dst, 644pl330_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dst,
529 dma_addr_t src, size_t len, unsigned long flags) 645 dma_addr_t src, size_t len, unsigned long flags)
@@ -579,7 +695,7 @@ pl330_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
579 struct dma_pl330_peri *peri = chan->private; 695 struct dma_pl330_peri *peri = chan->private;
580 struct scatterlist *sg; 696 struct scatterlist *sg;
581 unsigned long flags; 697 unsigned long flags;
582 int i, burst_size; 698 int i;
583 dma_addr_t addr; 699 dma_addr_t addr;
584 700
585 if (unlikely(!pch || !sgl || !sg_len || !peri)) 701 if (unlikely(!pch || !sgl || !sg_len || !peri))
@@ -595,8 +711,7 @@ pl330_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
595 return NULL; 711 return NULL;
596 } 712 }
597 713
598 addr = peri->fifo_addr; 714 addr = pch->fifo_addr;
599 burst_size = peri->burst_sz;
600 715
601 first = NULL; 716 first = NULL;
602 717
@@ -644,7 +759,7 @@ pl330_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
644 sg_dma_address(sg), addr, sg_dma_len(sg)); 759 sg_dma_address(sg), addr, sg_dma_len(sg));
645 } 760 }
646 761
647 desc->rqcfg.brst_size = burst_size; 762 desc->rqcfg.brst_size = pch->burst_sz;
648 desc->rqcfg.brst_len = 1; 763 desc->rqcfg.brst_len = 1;
649 } 764 }
650 765
@@ -696,6 +811,30 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)
696 goto probe_err1; 811 goto probe_err1;
697 } 812 }
698 813
814 pdmac->clk = clk_get(&adev->dev, "dma");
815 if (IS_ERR(pdmac->clk)) {
816 dev_err(&adev->dev, "Cannot get operation clock.\n");
817 ret = -EINVAL;
818 goto probe_err1;
819 }
820
821 amba_set_drvdata(adev, pdmac);
822
823#ifdef CONFIG_PM_RUNTIME
824 /* to use the runtime PM helper functions */
825 pm_runtime_enable(&adev->dev);
826
827 /* enable the power domain */
828 if (pm_runtime_get_sync(&adev->dev)) {
829 dev_err(&adev->dev, "failed to get runtime pm\n");
830 ret = -ENODEV;
831 goto probe_err1;
832 }
833#else
834 /* enable dma clk */
835 clk_enable(pdmac->clk);
836#endif
837
699 irq = adev->irq[0]; 838 irq = adev->irq[0];
700 ret = request_irq(irq, pl330_irq_handler, 0, 839 ret = request_irq(irq, pl330_irq_handler, 0,
701 dev_name(&adev->dev), pi); 840 dev_name(&adev->dev), pi);
@@ -732,6 +871,7 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)
732 case MEMTODEV: 871 case MEMTODEV:
733 case DEVTOMEM: 872 case DEVTOMEM:
734 dma_cap_set(DMA_SLAVE, pd->cap_mask); 873 dma_cap_set(DMA_SLAVE, pd->cap_mask);
874 dma_cap_set(DMA_CYCLIC, pd->cap_mask);
735 break; 875 break;
736 default: 876 default:
737 dev_err(&adev->dev, "DEVTODEV Not Supported\n"); 877 dev_err(&adev->dev, "DEVTODEV Not Supported\n");
@@ -760,6 +900,7 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)
760 pd->device_alloc_chan_resources = pl330_alloc_chan_resources; 900 pd->device_alloc_chan_resources = pl330_alloc_chan_resources;
761 pd->device_free_chan_resources = pl330_free_chan_resources; 901 pd->device_free_chan_resources = pl330_free_chan_resources;
762 pd->device_prep_dma_memcpy = pl330_prep_dma_memcpy; 902 pd->device_prep_dma_memcpy = pl330_prep_dma_memcpy;
903 pd->device_prep_dma_cyclic = pl330_prep_dma_cyclic;
763 pd->device_tx_status = pl330_tx_status; 904 pd->device_tx_status = pl330_tx_status;
764 pd->device_prep_slave_sg = pl330_prep_slave_sg; 905 pd->device_prep_slave_sg = pl330_prep_slave_sg;
765 pd->device_control = pl330_control; 906 pd->device_control = pl330_control;
@@ -771,8 +912,6 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)
771 goto probe_err4; 912 goto probe_err4;
772 } 913 }
773 914
774 amba_set_drvdata(adev, pdmac);
775
776 dev_info(&adev->dev, 915 dev_info(&adev->dev,
777 "Loaded driver for PL330 DMAC-%d\n", adev->periphid); 916 "Loaded driver for PL330 DMAC-%d\n", adev->periphid);
778 dev_info(&adev->dev, 917 dev_info(&adev->dev,
@@ -833,6 +972,13 @@ static int __devexit pl330_remove(struct amba_device *adev)
833 res = &adev->res; 972 res = &adev->res;
834 release_mem_region(res->start, resource_size(res)); 973 release_mem_region(res->start, resource_size(res));
835 974
975#ifdef CONFIG_PM_RUNTIME
976 pm_runtime_put(&adev->dev);
977 pm_runtime_disable(&adev->dev);
978#else
979 clk_disable(pdmac->clk);
980#endif
981
836 kfree(pdmac); 982 kfree(pdmac);
837 983
838 return 0; 984 return 0;
@@ -846,10 +992,49 @@ static struct amba_id pl330_ids[] = {
846 { 0, 0 }, 992 { 0, 0 },
847}; 993};
848 994
995#ifdef CONFIG_PM_RUNTIME
996static int pl330_runtime_suspend(struct device *dev)
997{
998 struct dma_pl330_dmac *pdmac = dev_get_drvdata(dev);
999
1000 if (!pdmac) {
1001 dev_err(dev, "failed to get dmac\n");
1002 return -ENODEV;
1003 }
1004
1005 clk_disable(pdmac->clk);
1006
1007 return 0;
1008}
1009
1010static int pl330_runtime_resume(struct device *dev)
1011{
1012 struct dma_pl330_dmac *pdmac = dev_get_drvdata(dev);
1013
1014 if (!pdmac) {
1015 dev_err(dev, "failed to get dmac\n");
1016 return -ENODEV;
1017 }
1018
1019 clk_enable(pdmac->clk);
1020
1021 return 0;
1022}
1023#else
1024#define pl330_runtime_suspend NULL
1025#define pl330_runtime_resume NULL
1026#endif /* CONFIG_PM_RUNTIME */
1027
1028static const struct dev_pm_ops pl330_pm_ops = {
1029 .runtime_suspend = pl330_runtime_suspend,
1030 .runtime_resume = pl330_runtime_resume,
1031};
1032
849static struct amba_driver pl330_driver = { 1033static struct amba_driver pl330_driver = {
850 .drv = { 1034 .drv = {
851 .owner = THIS_MODULE, 1035 .owner = THIS_MODULE,
852 .name = "dma-pl330", 1036 .name = "dma-pl330",
1037 .pm = &pl330_pm_ops,
853 }, 1038 },
854 .id_table = pl330_ids, 1039 .id_table = pl330_ids,
855 .probe = pl330_probe, 1040 .probe = pl330_probe,
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index d539efd96d4b..ca44d2cceb02 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -95,10 +95,6 @@ config GPIO_EP93XX
95 depends on ARCH_EP93XX 95 depends on ARCH_EP93XX
96 select GPIO_GENERIC 96 select GPIO_GENERIC
97 97
98config GPIO_EXYNOS4
99 def_bool y
100 depends on CPU_EXYNOS4210
101
102config GPIO_MPC5200 98config GPIO_MPC5200
103 def_bool y 99 def_bool y
104 depends on PPC_MPC52xx 100 depends on PPC_MPC52xx
@@ -131,18 +127,6 @@ config GPIO_MXS
131 select GPIO_GENERIC 127 select GPIO_GENERIC
132 select GENERIC_IRQ_CHIP 128 select GENERIC_IRQ_CHIP
133 129
134config GPIO_PLAT_SAMSUNG
135 def_bool y
136 depends on SAMSUNG_GPIOLIB_4BIT
137
138config GPIO_S5PC100
139 def_bool y
140 depends on CPU_S5PC100
141
142config GPIO_S5PV210
143 def_bool y
144 depends on CPU_S5PV210
145
146config GPIO_PL061 130config GPIO_PL061
147 bool "PrimeCell PL061 GPIO support" 131 bool "PrimeCell PL061 GPIO support"
148 depends on ARM_AMBA 132 depends on ARM_AMBA
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index 9588948c96f0..62db458c850d 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -15,7 +15,6 @@ obj-$(CONFIG_GPIO_BT8XX) += gpio-bt8xx.o
15obj-$(CONFIG_GPIO_CS5535) += gpio-cs5535.o 15obj-$(CONFIG_GPIO_CS5535) += gpio-cs5535.o
16obj-$(CONFIG_GPIO_DA9052) += gpio-da9052.o 16obj-$(CONFIG_GPIO_DA9052) += gpio-da9052.o
17obj-$(CONFIG_GPIO_EP93XX) += gpio-ep93xx.o 17obj-$(CONFIG_GPIO_EP93XX) += gpio-ep93xx.o
18obj-$(CONFIG_GPIO_EXYNOS4) += gpio-exynos4.o
19obj-$(CONFIG_GPIO_IT8761E) += gpio-it8761e.o 18obj-$(CONFIG_GPIO_IT8761E) += gpio-it8761e.o
20obj-$(CONFIG_GPIO_JANZ_TTL) += gpio-janz-ttl.o 19obj-$(CONFIG_GPIO_JANZ_TTL) += gpio-janz-ttl.o
21obj-$(CONFIG_GPIO_LANGWELL) += gpio-langwell.o 20obj-$(CONFIG_GPIO_LANGWELL) += gpio-langwell.o
@@ -38,11 +37,7 @@ obj-$(CONFIG_GPIO_PCF857X) += gpio-pcf857x.o
38obj-$(CONFIG_GPIO_PCH) += gpio-pch.o 37obj-$(CONFIG_GPIO_PCH) += gpio-pch.o
39obj-$(CONFIG_GPIO_PL061) += gpio-pl061.o 38obj-$(CONFIG_GPIO_PL061) += gpio-pl061.o
40obj-$(CONFIG_GPIO_RDC321X) += gpio-rdc321x.o 39obj-$(CONFIG_GPIO_RDC321X) += gpio-rdc321x.o
41 40obj-$(CONFIG_PLAT_SAMSUNG) += gpio-samsung.o
42obj-$(CONFIG_GPIO_PLAT_SAMSUNG) += gpio-plat-samsung.o
43obj-$(CONFIG_GPIO_S5PC100) += gpio-s5pc100.o
44obj-$(CONFIG_GPIO_S5PV210) += gpio-s5pv210.o
45
46obj-$(CONFIG_GPIO_SCH) += gpio-sch.o 41obj-$(CONFIG_GPIO_SCH) += gpio-sch.o
47obj-$(CONFIG_GPIO_STMPE) += gpio-stmpe.o 42obj-$(CONFIG_GPIO_STMPE) += gpio-stmpe.o
48obj-$(CONFIG_GPIO_SX150X) += gpio-sx150x.o 43obj-$(CONFIG_GPIO_SX150X) += gpio-sx150x.o
diff --git a/drivers/gpio/gpio-exynos4.c b/drivers/gpio/gpio-exynos4.c
deleted file mode 100644
index d24b337cf1ac..000000000000
--- a/drivers/gpio/gpio-exynos4.c
+++ /dev/null
@@ -1,385 +0,0 @@
1/*
2 * EXYNOS4 - GPIOlib support
3 *
4 * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
5 * http://www.samsung.com
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10*/
11
12#include <linux/kernel.h>
13#include <linux/irq.h>
14#include <linux/io.h>
15#include <linux/gpio.h>
16
17#include <mach/map.h>
18
19#include <plat/gpio-core.h>
20#include <plat/gpio-cfg.h>
21#include <plat/gpio-cfg-helpers.h>
22
23int s3c_gpio_setpull_exynos4(struct s3c_gpio_chip *chip,
24 unsigned int off, s3c_gpio_pull_t pull)
25{
26 if (pull == S3C_GPIO_PULL_UP)
27 pull = 3;
28
29 return s3c_gpio_setpull_updown(chip, off, pull);
30}
31
32s3c_gpio_pull_t s3c_gpio_getpull_exynos4(struct s3c_gpio_chip *chip,
33 unsigned int off)
34{
35 s3c_gpio_pull_t pull;
36
37 pull = s3c_gpio_getpull_updown(chip, off);
38 if (pull == 3)
39 pull = S3C_GPIO_PULL_UP;
40
41 return pull;
42}
43
44static struct s3c_gpio_cfg gpio_cfg = {
45 .set_config = s3c_gpio_setcfg_s3c64xx_4bit,
46 .set_pull = s3c_gpio_setpull_exynos4,
47 .get_pull = s3c_gpio_getpull_exynos4,
48};
49
50static struct s3c_gpio_cfg gpio_cfg_noint = {
51 .set_config = s3c_gpio_setcfg_s3c64xx_4bit,
52 .set_pull = s3c_gpio_setpull_exynos4,
53 .get_pull = s3c_gpio_getpull_exynos4,
54};
55
56/*
57 * Following are the gpio banks in v310.
58 *
59 * The 'config' member when left to NULL, is initialized to the default
60 * structure gpio_cfg in the init function below.
61 *
62 * The 'base' member is also initialized in the init function below.
63 * Note: The initialization of 'base' member of s3c_gpio_chip structure
64 * uses the above macro and depends on the banks being listed in order here.
65 */
66static struct s3c_gpio_chip exynos4_gpio_part1_4bit[] = {
67 {
68 .chip = {
69 .base = EXYNOS4_GPA0(0),
70 .ngpio = EXYNOS4_GPIO_A0_NR,
71 .label = "GPA0",
72 },
73 }, {
74 .chip = {
75 .base = EXYNOS4_GPA1(0),
76 .ngpio = EXYNOS4_GPIO_A1_NR,
77 .label = "GPA1",
78 },
79 }, {
80 .chip = {
81 .base = EXYNOS4_GPB(0),
82 .ngpio = EXYNOS4_GPIO_B_NR,
83 .label = "GPB",
84 },
85 }, {
86 .chip = {
87 .base = EXYNOS4_GPC0(0),
88 .ngpio = EXYNOS4_GPIO_C0_NR,
89 .label = "GPC0",
90 },
91 }, {
92 .chip = {
93 .base = EXYNOS4_GPC1(0),
94 .ngpio = EXYNOS4_GPIO_C1_NR,
95 .label = "GPC1",
96 },
97 }, {
98 .chip = {
99 .base = EXYNOS4_GPD0(0),
100 .ngpio = EXYNOS4_GPIO_D0_NR,
101 .label = "GPD0",
102 },
103 }, {
104 .chip = {
105 .base = EXYNOS4_GPD1(0),
106 .ngpio = EXYNOS4_GPIO_D1_NR,
107 .label = "GPD1",
108 },
109 }, {
110 .chip = {
111 .base = EXYNOS4_GPE0(0),
112 .ngpio = EXYNOS4_GPIO_E0_NR,
113 .label = "GPE0",
114 },
115 }, {
116 .chip = {
117 .base = EXYNOS4_GPE1(0),
118 .ngpio = EXYNOS4_GPIO_E1_NR,
119 .label = "GPE1",
120 },
121 }, {
122 .chip = {
123 .base = EXYNOS4_GPE2(0),
124 .ngpio = EXYNOS4_GPIO_E2_NR,
125 .label = "GPE2",
126 },
127 }, {
128 .chip = {
129 .base = EXYNOS4_GPE3(0),
130 .ngpio = EXYNOS4_GPIO_E3_NR,
131 .label = "GPE3",
132 },
133 }, {
134 .chip = {
135 .base = EXYNOS4_GPE4(0),
136 .ngpio = EXYNOS4_GPIO_E4_NR,
137 .label = "GPE4",
138 },
139 }, {
140 .chip = {
141 .base = EXYNOS4_GPF0(0),
142 .ngpio = EXYNOS4_GPIO_F0_NR,
143 .label = "GPF0",
144 },
145 }, {
146 .chip = {
147 .base = EXYNOS4_GPF1(0),
148 .ngpio = EXYNOS4_GPIO_F1_NR,
149 .label = "GPF1",
150 },
151 }, {
152 .chip = {
153 .base = EXYNOS4_GPF2(0),
154 .ngpio = EXYNOS4_GPIO_F2_NR,
155 .label = "GPF2",
156 },
157 }, {
158 .chip = {
159 .base = EXYNOS4_GPF3(0),
160 .ngpio = EXYNOS4_GPIO_F3_NR,
161 .label = "GPF3",
162 },
163 },
164};
165
166static struct s3c_gpio_chip exynos4_gpio_part2_4bit[] = {
167 {
168 .chip = {
169 .base = EXYNOS4_GPJ0(0),
170 .ngpio = EXYNOS4_GPIO_J0_NR,
171 .label = "GPJ0",
172 },
173 }, {
174 .chip = {
175 .base = EXYNOS4_GPJ1(0),
176 .ngpio = EXYNOS4_GPIO_J1_NR,
177 .label = "GPJ1",
178 },
179 }, {
180 .chip = {
181 .base = EXYNOS4_GPK0(0),
182 .ngpio = EXYNOS4_GPIO_K0_NR,
183 .label = "GPK0",
184 },
185 }, {
186 .chip = {
187 .base = EXYNOS4_GPK1(0),
188 .ngpio = EXYNOS4_GPIO_K1_NR,
189 .label = "GPK1",
190 },
191 }, {
192 .chip = {
193 .base = EXYNOS4_GPK2(0),
194 .ngpio = EXYNOS4_GPIO_K2_NR,
195 .label = "GPK2",
196 },
197 }, {
198 .chip = {
199 .base = EXYNOS4_GPK3(0),
200 .ngpio = EXYNOS4_GPIO_K3_NR,
201 .label = "GPK3",
202 },
203 }, {
204 .chip = {
205 .base = EXYNOS4_GPL0(0),
206 .ngpio = EXYNOS4_GPIO_L0_NR,
207 .label = "GPL0",
208 },
209 }, {
210 .chip = {
211 .base = EXYNOS4_GPL1(0),
212 .ngpio = EXYNOS4_GPIO_L1_NR,
213 .label = "GPL1",
214 },
215 }, {
216 .chip = {
217 .base = EXYNOS4_GPL2(0),
218 .ngpio = EXYNOS4_GPIO_L2_NR,
219 .label = "GPL2",
220 },
221 }, {
222 .config = &gpio_cfg_noint,
223 .chip = {
224 .base = EXYNOS4_GPY0(0),
225 .ngpio = EXYNOS4_GPIO_Y0_NR,
226 .label = "GPY0",
227 },
228 }, {
229 .config = &gpio_cfg_noint,
230 .chip = {
231 .base = EXYNOS4_GPY1(0),
232 .ngpio = EXYNOS4_GPIO_Y1_NR,
233 .label = "GPY1",
234 },
235 }, {
236 .config = &gpio_cfg_noint,
237 .chip = {
238 .base = EXYNOS4_GPY2(0),
239 .ngpio = EXYNOS4_GPIO_Y2_NR,
240 .label = "GPY2",
241 },
242 }, {
243 .config = &gpio_cfg_noint,
244 .chip = {
245 .base = EXYNOS4_GPY3(0),
246 .ngpio = EXYNOS4_GPIO_Y3_NR,
247 .label = "GPY3",
248 },
249 }, {
250 .config = &gpio_cfg_noint,
251 .chip = {
252 .base = EXYNOS4_GPY4(0),
253 .ngpio = EXYNOS4_GPIO_Y4_NR,
254 .label = "GPY4",
255 },
256 }, {
257 .config = &gpio_cfg_noint,
258 .chip = {
259 .base = EXYNOS4_GPY5(0),
260 .ngpio = EXYNOS4_GPIO_Y5_NR,
261 .label = "GPY5",
262 },
263 }, {
264 .config = &gpio_cfg_noint,
265 .chip = {
266 .base = EXYNOS4_GPY6(0),
267 .ngpio = EXYNOS4_GPIO_Y6_NR,
268 .label = "GPY6",
269 },
270 }, {
271 .base = (S5P_VA_GPIO2 + 0xC00),
272 .config = &gpio_cfg_noint,
273 .irq_base = IRQ_EINT(0),
274 .chip = {
275 .base = EXYNOS4_GPX0(0),
276 .ngpio = EXYNOS4_GPIO_X0_NR,
277 .label = "GPX0",
278 .to_irq = samsung_gpiolib_to_irq,
279 },
280 }, {
281 .base = (S5P_VA_GPIO2 + 0xC20),
282 .config = &gpio_cfg_noint,
283 .irq_base = IRQ_EINT(8),
284 .chip = {
285 .base = EXYNOS4_GPX1(0),
286 .ngpio = EXYNOS4_GPIO_X1_NR,
287 .label = "GPX1",
288 .to_irq = samsung_gpiolib_to_irq,
289 },
290 }, {
291 .base = (S5P_VA_GPIO2 + 0xC40),
292 .config = &gpio_cfg_noint,
293 .irq_base = IRQ_EINT(16),
294 .chip = {
295 .base = EXYNOS4_GPX2(0),
296 .ngpio = EXYNOS4_GPIO_X2_NR,
297 .label = "GPX2",
298 .to_irq = samsung_gpiolib_to_irq,
299 },
300 }, {
301 .base = (S5P_VA_GPIO2 + 0xC60),
302 .config = &gpio_cfg_noint,
303 .irq_base = IRQ_EINT(24),
304 .chip = {
305 .base = EXYNOS4_GPX3(0),
306 .ngpio = EXYNOS4_GPIO_X3_NR,
307 .label = "GPX3",
308 .to_irq = samsung_gpiolib_to_irq,
309 },
310 },
311};
312
313static struct s3c_gpio_chip exynos4_gpio_part3_4bit[] = {
314 {
315 .chip = {
316 .base = EXYNOS4_GPZ(0),
317 .ngpio = EXYNOS4_GPIO_Z_NR,
318 .label = "GPZ",
319 },
320 },
321};
322
323static __init int exynos4_gpiolib_init(void)
324{
325 struct s3c_gpio_chip *chip;
326 int i;
327 int group = 0;
328 int nr_chips;
329
330 /* GPIO part 1 */
331
332 chip = exynos4_gpio_part1_4bit;
333 nr_chips = ARRAY_SIZE(exynos4_gpio_part1_4bit);
334
335 for (i = 0; i < nr_chips; i++, chip++) {
336 if (chip->config == NULL) {
337 chip->config = &gpio_cfg;
338 /* Assign the GPIO interrupt group */
339 chip->group = group++;
340 }
341 if (chip->base == NULL)
342 chip->base = S5P_VA_GPIO1 + (i) * 0x20;
343 }
344
345 samsung_gpiolib_add_4bit_chips(exynos4_gpio_part1_4bit, nr_chips);
346
347 /* GPIO part 2 */
348
349 chip = exynos4_gpio_part2_4bit;
350 nr_chips = ARRAY_SIZE(exynos4_gpio_part2_4bit);
351
352 for (i = 0; i < nr_chips; i++, chip++) {
353 if (chip->config == NULL) {
354 chip->config = &gpio_cfg;
355 /* Assign the GPIO interrupt group */
356 chip->group = group++;
357 }
358 if (chip->base == NULL)
359 chip->base = S5P_VA_GPIO2 + (i) * 0x20;
360 }
361
362 samsung_gpiolib_add_4bit_chips(exynos4_gpio_part2_4bit, nr_chips);
363
364 /* GPIO part 3 */
365
366 chip = exynos4_gpio_part3_4bit;
367 nr_chips = ARRAY_SIZE(exynos4_gpio_part3_4bit);
368
369 for (i = 0; i < nr_chips; i++, chip++) {
370 if (chip->config == NULL) {
371 chip->config = &gpio_cfg;
372 /* Assign the GPIO interrupt group */
373 chip->group = group++;
374 }
375 if (chip->base == NULL)
376 chip->base = S5P_VA_GPIO3 + (i) * 0x20;
377 }
378
379 samsung_gpiolib_add_4bit_chips(exynos4_gpio_part3_4bit, nr_chips);
380 s5p_register_gpioint_bank(IRQ_GPIO_XA, 0, IRQ_GPIO1_NR_GROUPS);
381 s5p_register_gpioint_bank(IRQ_GPIO_XB, IRQ_GPIO1_NR_GROUPS, IRQ_GPIO2_NR_GROUPS);
382
383 return 0;
384}
385core_initcall(exynos4_gpiolib_init);
diff --git a/drivers/gpio/gpio-plat-samsung.c b/drivers/gpio/gpio-plat-samsung.c
deleted file mode 100644
index ef67f1952a72..000000000000
--- a/drivers/gpio/gpio-plat-samsung.c
+++ /dev/null
@@ -1,205 +0,0 @@
1/*
2 * Copyright 2008 Openmoko, Inc.
3 * Copyright 2008 Simtec Electronics
4 * Ben Dooks <ben@simtec.co.uk>
5 * http://armlinux.simtec.co.uk/
6 *
7 * Copyright (c) 2009 Samsung Electronics Co., Ltd.
8 * http://www.samsung.com/
9 *
10 * SAMSUNG - GPIOlib support
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License version 2 as
14 * published by the Free Software Foundation.
15 */
16
17#include <linux/kernel.h>
18#include <linux/irq.h>
19#include <linux/io.h>
20#include <linux/gpio.h>
21#include <plat/gpio-core.h>
22#include <plat/gpio-cfg.h>
23#include <plat/gpio-cfg-helpers.h>
24
25#ifndef DEBUG_GPIO
26#define gpio_dbg(x...) do { } while (0)
27#else
28#define gpio_dbg(x...) printk(KERN_DEBUG x)
29#endif
30
31/* The samsung_gpiolib_4bit routines are to control the gpio banks where
32 * the gpio configuration register (GPxCON) has 4 bits per GPIO, as the
33 * following example:
34 *
35 * base + 0x00: Control register, 4 bits per gpio
36 * gpio n: 4 bits starting at (4*n)
37 * 0000 = input, 0001 = output, others mean special-function
38 * base + 0x04: Data register, 1 bit per gpio
39 * bit n: data bit n
40 *
41 * Note, since the data register is one bit per gpio and is at base + 0x4
42 * we can use s3c_gpiolib_get and s3c_gpiolib_set to change the state of
43 * the output.
44*/
45
46static int samsung_gpiolib_4bit_input(struct gpio_chip *chip,
47 unsigned int offset)
48{
49 struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
50 void __iomem *base = ourchip->base;
51 unsigned long con;
52
53 con = __raw_readl(base + GPIOCON_OFF);
54 con &= ~(0xf << con_4bit_shift(offset));
55 __raw_writel(con, base + GPIOCON_OFF);
56
57 gpio_dbg("%s: %p: CON now %08lx\n", __func__, base, con);
58
59 return 0;
60}
61
62static int samsung_gpiolib_4bit_output(struct gpio_chip *chip,
63 unsigned int offset, int value)
64{
65 struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
66 void __iomem *base = ourchip->base;
67 unsigned long con;
68 unsigned long dat;
69
70 con = __raw_readl(base + GPIOCON_OFF);
71 con &= ~(0xf << con_4bit_shift(offset));
72 con |= 0x1 << con_4bit_shift(offset);
73
74 dat = __raw_readl(base + GPIODAT_OFF);
75
76 if (value)
77 dat |= 1 << offset;
78 else
79 dat &= ~(1 << offset);
80
81 __raw_writel(dat, base + GPIODAT_OFF);
82 __raw_writel(con, base + GPIOCON_OFF);
83 __raw_writel(dat, base + GPIODAT_OFF);
84
85 gpio_dbg("%s: %p: CON %08lx, DAT %08lx\n", __func__, base, con, dat);
86
87 return 0;
88}
89
90/* The next set of routines are for the case where the GPIO configuration
91 * registers are 4 bits per GPIO but there is more than one register (the
92 * bank has more than 8 GPIOs.
93 *
94 * This case is the similar to the 4 bit case, but the registers are as
95 * follows:
96 *
97 * base + 0x00: Control register, 4 bits per gpio (lower 8 GPIOs)
98 * gpio n: 4 bits starting at (4*n)
99 * 0000 = input, 0001 = output, others mean special-function
100 * base + 0x04: Control register, 4 bits per gpio (up to 8 additions GPIOs)
101 * gpio n: 4 bits starting at (4*n)
102 * 0000 = input, 0001 = output, others mean special-function
103 * base + 0x08: Data register, 1 bit per gpio
104 * bit n: data bit n
105 *
106 * To allow us to use the s3c_gpiolib_get and s3c_gpiolib_set routines we
107 * store the 'base + 0x4' address so that these routines see the data
108 * register at ourchip->base + 0x04.
109 */
110
111static int samsung_gpiolib_4bit2_input(struct gpio_chip *chip,
112 unsigned int offset)
113{
114 struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
115 void __iomem *base = ourchip->base;
116 void __iomem *regcon = base;
117 unsigned long con;
118
119 if (offset > 7)
120 offset -= 8;
121 else
122 regcon -= 4;
123
124 con = __raw_readl(regcon);
125 con &= ~(0xf << con_4bit_shift(offset));
126 __raw_writel(con, regcon);
127
128 gpio_dbg("%s: %p: CON %08lx\n", __func__, base, con);
129
130 return 0;
131}
132
133static int samsung_gpiolib_4bit2_output(struct gpio_chip *chip,
134 unsigned int offset, int value)
135{
136 struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
137 void __iomem *base = ourchip->base;
138 void __iomem *regcon = base;
139 unsigned long con;
140 unsigned long dat;
141 unsigned con_offset = offset;
142
143 if (con_offset > 7)
144 con_offset -= 8;
145 else
146 regcon -= 4;
147
148 con = __raw_readl(regcon);
149 con &= ~(0xf << con_4bit_shift(con_offset));
150 con |= 0x1 << con_4bit_shift(con_offset);
151
152 dat = __raw_readl(base + GPIODAT_OFF);
153
154 if (value)
155 dat |= 1 << offset;
156 else
157 dat &= ~(1 << offset);
158
159 __raw_writel(dat, base + GPIODAT_OFF);
160 __raw_writel(con, regcon);
161 __raw_writel(dat, base + GPIODAT_OFF);
162
163 gpio_dbg("%s: %p: CON %08lx, DAT %08lx\n", __func__, base, con, dat);
164
165 return 0;
166}
167
168void __init samsung_gpiolib_add_4bit(struct s3c_gpio_chip *chip)
169{
170 chip->chip.direction_input = samsung_gpiolib_4bit_input;
171 chip->chip.direction_output = samsung_gpiolib_4bit_output;
172 chip->pm = __gpio_pm(&s3c_gpio_pm_4bit);
173}
174
175void __init samsung_gpiolib_add_4bit2(struct s3c_gpio_chip *chip)
176{
177 chip->chip.direction_input = samsung_gpiolib_4bit2_input;
178 chip->chip.direction_output = samsung_gpiolib_4bit2_output;
179 chip->pm = __gpio_pm(&s3c_gpio_pm_4bit);
180}
181
182void __init samsung_gpiolib_add_4bit_chips(struct s3c_gpio_chip *chip,
183 int nr_chips)
184{
185 for (; nr_chips > 0; nr_chips--, chip++) {
186 samsung_gpiolib_add_4bit(chip);
187 s3c_gpiolib_add(chip);
188 }
189}
190
191void __init samsung_gpiolib_add_4bit2_chips(struct s3c_gpio_chip *chip,
192 int nr_chips)
193{
194 for (; nr_chips > 0; nr_chips--, chip++) {
195 samsung_gpiolib_add_4bit2(chip);
196 s3c_gpiolib_add(chip);
197 }
198}
199
200void __init samsung_gpiolib_add_2bit_chips(struct s3c_gpio_chip *chip,
201 int nr_chips)
202{
203 for (; nr_chips > 0; nr_chips--, chip++)
204 s3c_gpiolib_add(chip);
205}
diff --git a/drivers/gpio/gpio-s5pc100.c b/drivers/gpio/gpio-s5pc100.c
deleted file mode 100644
index 7f87b0c76e0b..000000000000
--- a/drivers/gpio/gpio-s5pc100.c
+++ /dev/null
@@ -1,354 +0,0 @@
1/*
2 * S5PC100 - GPIOlib support
3 *
4 * Copyright (c) 2010 Samsung Electronics Co., Ltd.
5 * http://www.samsung.com
6 *
7 * Copyright 2009 Samsung Electronics Co
8 * Kyungmin Park <kyungmin.park@samsung.com>
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
13 */
14
15#include <linux/kernel.h>
16#include <linux/irq.h>
17#include <linux/io.h>
18#include <linux/gpio.h>
19
20#include <mach/map.h>
21#include <mach/regs-gpio.h>
22
23#include <plat/gpio-core.h>
24#include <plat/gpio-cfg.h>
25#include <plat/gpio-cfg-helpers.h>
26
27/* S5PC100 GPIO bank summary:
28 *
29 * Bank GPIOs Style INT Type
30 * A0 8 4Bit GPIO_INT0
31 * A1 5 4Bit GPIO_INT1
32 * B 8 4Bit GPIO_INT2
33 * C 5 4Bit GPIO_INT3
34 * D 7 4Bit GPIO_INT4
35 * E0 8 4Bit GPIO_INT5
36 * E1 6 4Bit GPIO_INT6
37 * F0 8 4Bit GPIO_INT7
38 * F1 8 4Bit GPIO_INT8
39 * F2 8 4Bit GPIO_INT9
40 * F3 4 4Bit GPIO_INT10
41 * G0 8 4Bit GPIO_INT11
42 * G1 3 4Bit GPIO_INT12
43 * G2 7 4Bit GPIO_INT13
44 * G3 7 4Bit GPIO_INT14
45 * H0 8 4Bit WKUP_INT
46 * H1 8 4Bit WKUP_INT
47 * H2 8 4Bit WKUP_INT
48 * H3 8 4Bit WKUP_INT
49 * I 8 4Bit GPIO_INT15
50 * J0 8 4Bit GPIO_INT16
51 * J1 5 4Bit GPIO_INT17
52 * J2 8 4Bit GPIO_INT18
53 * J3 8 4Bit GPIO_INT19
54 * J4 4 4Bit GPIO_INT20
55 * K0 8 4Bit None
56 * K1 6 4Bit None
57 * K2 8 4Bit None
58 * K3 8 4Bit None
59 * L0 8 4Bit None
60 * L1 8 4Bit None
61 * L2 8 4Bit None
62 * L3 8 4Bit None
63 */
64
65static struct s3c_gpio_cfg gpio_cfg = {
66 .set_config = s3c_gpio_setcfg_s3c64xx_4bit,
67 .set_pull = s3c_gpio_setpull_updown,
68 .get_pull = s3c_gpio_getpull_updown,
69};
70
71static struct s3c_gpio_cfg gpio_cfg_eint = {
72 .cfg_eint = 0xf,
73 .set_config = s3c_gpio_setcfg_s3c64xx_4bit,
74 .set_pull = s3c_gpio_setpull_updown,
75 .get_pull = s3c_gpio_getpull_updown,
76};
77
78static struct s3c_gpio_cfg gpio_cfg_noint = {
79 .set_config = s3c_gpio_setcfg_s3c64xx_4bit,
80 .set_pull = s3c_gpio_setpull_updown,
81 .get_pull = s3c_gpio_getpull_updown,
82};
83
84/*
85 * GPIO bank's base address given the index of the bank in the
86 * list of all gpio banks.
87 */
88#define S5PC100_BANK_BASE(bank_nr) (S5P_VA_GPIO + ((bank_nr) * 0x20))
89
90/*
91 * Following are the gpio banks in S5PC100.
92 *
93 * The 'config' member when left to NULL, is initialized to the default
94 * structure gpio_cfg in the init function below.
95 *
96 * The 'base' member is also initialized in the init function below.
97 * Note: The initialization of 'base' member of s3c_gpio_chip structure
98 * uses the above macro and depends on the banks being listed in order here.
99 */
100static struct s3c_gpio_chip s5pc100_gpio_chips[] = {
101 {
102 .chip = {
103 .base = S5PC100_GPA0(0),
104 .ngpio = S5PC100_GPIO_A0_NR,
105 .label = "GPA0",
106 },
107 }, {
108 .chip = {
109 .base = S5PC100_GPA1(0),
110 .ngpio = S5PC100_GPIO_A1_NR,
111 .label = "GPA1",
112 },
113 }, {
114 .chip = {
115 .base = S5PC100_GPB(0),
116 .ngpio = S5PC100_GPIO_B_NR,
117 .label = "GPB",
118 },
119 }, {
120 .chip = {
121 .base = S5PC100_GPC(0),
122 .ngpio = S5PC100_GPIO_C_NR,
123 .label = "GPC",
124 },
125 }, {
126 .chip = {
127 .base = S5PC100_GPD(0),
128 .ngpio = S5PC100_GPIO_D_NR,
129 .label = "GPD",
130 },
131 }, {
132 .chip = {
133 .base = S5PC100_GPE0(0),
134 .ngpio = S5PC100_GPIO_E0_NR,
135 .label = "GPE0",
136 },
137 }, {
138 .chip = {
139 .base = S5PC100_GPE1(0),
140 .ngpio = S5PC100_GPIO_E1_NR,
141 .label = "GPE1",
142 },
143 }, {
144 .chip = {
145 .base = S5PC100_GPF0(0),
146 .ngpio = S5PC100_GPIO_F0_NR,
147 .label = "GPF0",
148 },
149 }, {
150 .chip = {
151 .base = S5PC100_GPF1(0),
152 .ngpio = S5PC100_GPIO_F1_NR,
153 .label = "GPF1",
154 },
155 }, {
156 .chip = {
157 .base = S5PC100_GPF2(0),
158 .ngpio = S5PC100_GPIO_F2_NR,
159 .label = "GPF2",
160 },
161 }, {
162 .chip = {
163 .base = S5PC100_GPF3(0),
164 .ngpio = S5PC100_GPIO_F3_NR,
165 .label = "GPF3",
166 },
167 }, {
168 .chip = {
169 .base = S5PC100_GPG0(0),
170 .ngpio = S5PC100_GPIO_G0_NR,
171 .label = "GPG0",
172 },
173 }, {
174 .chip = {
175 .base = S5PC100_GPG1(0),
176 .ngpio = S5PC100_GPIO_G1_NR,
177 .label = "GPG1",
178 },
179 }, {
180 .chip = {
181 .base = S5PC100_GPG2(0),
182 .ngpio = S5PC100_GPIO_G2_NR,
183 .label = "GPG2",
184 },
185 }, {
186 .chip = {
187 .base = S5PC100_GPG3(0),
188 .ngpio = S5PC100_GPIO_G3_NR,
189 .label = "GPG3",
190 },
191 }, {
192 .chip = {
193 .base = S5PC100_GPI(0),
194 .ngpio = S5PC100_GPIO_I_NR,
195 .label = "GPI",
196 },
197 }, {
198 .chip = {
199 .base = S5PC100_GPJ0(0),
200 .ngpio = S5PC100_GPIO_J0_NR,
201 .label = "GPJ0",
202 },
203 }, {
204 .chip = {
205 .base = S5PC100_GPJ1(0),
206 .ngpio = S5PC100_GPIO_J1_NR,
207 .label = "GPJ1",
208 },
209 }, {
210 .chip = {
211 .base = S5PC100_GPJ2(0),
212 .ngpio = S5PC100_GPIO_J2_NR,
213 .label = "GPJ2",
214 },
215 }, {
216 .chip = {
217 .base = S5PC100_GPJ3(0),
218 .ngpio = S5PC100_GPIO_J3_NR,
219 .label = "GPJ3",
220 },
221 }, {
222 .chip = {
223 .base = S5PC100_GPJ4(0),
224 .ngpio = S5PC100_GPIO_J4_NR,
225 .label = "GPJ4",
226 },
227 }, {
228 .config = &gpio_cfg_noint,
229 .chip = {
230 .base = S5PC100_GPK0(0),
231 .ngpio = S5PC100_GPIO_K0_NR,
232 .label = "GPK0",
233 },
234 }, {
235 .config = &gpio_cfg_noint,
236 .chip = {
237 .base = S5PC100_GPK1(0),
238 .ngpio = S5PC100_GPIO_K1_NR,
239 .label = "GPK1",
240 },
241 }, {
242 .config = &gpio_cfg_noint,
243 .chip = {
244 .base = S5PC100_GPK2(0),
245 .ngpio = S5PC100_GPIO_K2_NR,
246 .label = "GPK2",
247 },
248 }, {
249 .config = &gpio_cfg_noint,
250 .chip = {
251 .base = S5PC100_GPK3(0),
252 .ngpio = S5PC100_GPIO_K3_NR,
253 .label = "GPK3",
254 },
255 }, {
256 .config = &gpio_cfg_noint,
257 .chip = {
258 .base = S5PC100_GPL0(0),
259 .ngpio = S5PC100_GPIO_L0_NR,
260 .label = "GPL0",
261 },
262 }, {
263 .config = &gpio_cfg_noint,
264 .chip = {
265 .base = S5PC100_GPL1(0),
266 .ngpio = S5PC100_GPIO_L1_NR,
267 .label = "GPL1",
268 },
269 }, {
270 .config = &gpio_cfg_noint,
271 .chip = {
272 .base = S5PC100_GPL2(0),
273 .ngpio = S5PC100_GPIO_L2_NR,
274 .label = "GPL2",
275 },
276 }, {
277 .config = &gpio_cfg_noint,
278 .chip = {
279 .base = S5PC100_GPL3(0),
280 .ngpio = S5PC100_GPIO_L3_NR,
281 .label = "GPL3",
282 },
283 }, {
284 .config = &gpio_cfg_noint,
285 .chip = {
286 .base = S5PC100_GPL4(0),
287 .ngpio = S5PC100_GPIO_L4_NR,
288 .label = "GPL4",
289 },
290 }, {
291 .base = (S5P_VA_GPIO + 0xC00),
292 .config = &gpio_cfg_eint,
293 .irq_base = IRQ_EINT(0),
294 .chip = {
295 .base = S5PC100_GPH0(0),
296 .ngpio = S5PC100_GPIO_H0_NR,
297 .label = "GPH0",
298 .to_irq = samsung_gpiolib_to_irq,
299 },
300 }, {
301 .base = (S5P_VA_GPIO + 0xC20),
302 .config = &gpio_cfg_eint,
303 .irq_base = IRQ_EINT(8),
304 .chip = {
305 .base = S5PC100_GPH1(0),
306 .ngpio = S5PC100_GPIO_H1_NR,
307 .label = "GPH1",
308 .to_irq = samsung_gpiolib_to_irq,
309 },
310 }, {
311 .base = (S5P_VA_GPIO + 0xC40),
312 .config = &gpio_cfg_eint,
313 .irq_base = IRQ_EINT(16),
314 .chip = {
315 .base = S5PC100_GPH2(0),
316 .ngpio = S5PC100_GPIO_H2_NR,
317 .label = "GPH2",
318 .to_irq = samsung_gpiolib_to_irq,
319 },
320 }, {
321 .base = (S5P_VA_GPIO + 0xC60),
322 .config = &gpio_cfg_eint,
323 .irq_base = IRQ_EINT(24),
324 .chip = {
325 .base = S5PC100_GPH3(0),
326 .ngpio = S5PC100_GPIO_H3_NR,
327 .label = "GPH3",
328 .to_irq = samsung_gpiolib_to_irq,
329 },
330 },
331};
332
333static __init int s5pc100_gpiolib_init(void)
334{
335 struct s3c_gpio_chip *chip = s5pc100_gpio_chips;
336 int nr_chips = ARRAY_SIZE(s5pc100_gpio_chips);
337 int gpioint_group = 0;
338 int i;
339
340 for (i = 0; i < nr_chips; i++, chip++) {
341 if (chip->config == NULL) {
342 chip->config = &gpio_cfg;
343 chip->group = gpioint_group++;
344 }
345 if (chip->base == NULL)
346 chip->base = S5PC100_BANK_BASE(i);
347 }
348
349 samsung_gpiolib_add_4bit_chips(s5pc100_gpio_chips, nr_chips);
350 s5p_register_gpioint_bank(IRQ_GPIOINT, 0, S5P_GPIOINT_GROUP_MAXNR);
351
352 return 0;
353}
354core_initcall(s5pc100_gpiolib_init);
diff --git a/drivers/gpio/gpio-s5pv210.c b/drivers/gpio/gpio-s5pv210.c
deleted file mode 100644
index eb12f1602de9..000000000000
--- a/drivers/gpio/gpio-s5pv210.c
+++ /dev/null
@@ -1,287 +0,0 @@
1/*
2 * S5PV210 - GPIOlib support
3 *
4 * Copyright (c) 2010 Samsung Electronics Co., Ltd.
5 * http://www.samsung.com/
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 */
11
12#include <linux/kernel.h>
13#include <linux/irq.h>
14#include <linux/io.h>
15#include <linux/gpio.h>
16#include <plat/gpio-core.h>
17#include <plat/gpio-cfg.h>
18#include <plat/gpio-cfg-helpers.h>
19#include <mach/map.h>
20
21static struct s3c_gpio_cfg gpio_cfg = {
22 .set_config = s3c_gpio_setcfg_s3c64xx_4bit,
23 .set_pull = s3c_gpio_setpull_updown,
24 .get_pull = s3c_gpio_getpull_updown,
25};
26
27static struct s3c_gpio_cfg gpio_cfg_noint = {
28 .set_config = s3c_gpio_setcfg_s3c64xx_4bit,
29 .set_pull = s3c_gpio_setpull_updown,
30 .get_pull = s3c_gpio_getpull_updown,
31};
32
33/* GPIO bank's base address given the index of the bank in the
34 * list of all gpio banks.
35 */
36#define S5PV210_BANK_BASE(bank_nr) (S5P_VA_GPIO + ((bank_nr) * 0x20))
37
38/*
39 * Following are the gpio banks in v210.
40 *
41 * The 'config' member when left to NULL, is initialized to the default
42 * structure gpio_cfg in the init function below.
43 *
44 * The 'base' member is also initialized in the init function below.
45 * Note: The initialization of 'base' member of s3c_gpio_chip structure
46 * uses the above macro and depends on the banks being listed in order here.
47 */
48static struct s3c_gpio_chip s5pv210_gpio_4bit[] = {
49 {
50 .chip = {
51 .base = S5PV210_GPA0(0),
52 .ngpio = S5PV210_GPIO_A0_NR,
53 .label = "GPA0",
54 },
55 }, {
56 .chip = {
57 .base = S5PV210_GPA1(0),
58 .ngpio = S5PV210_GPIO_A1_NR,
59 .label = "GPA1",
60 },
61 }, {
62 .chip = {
63 .base = S5PV210_GPB(0),
64 .ngpio = S5PV210_GPIO_B_NR,
65 .label = "GPB",
66 },
67 }, {
68 .chip = {
69 .base = S5PV210_GPC0(0),
70 .ngpio = S5PV210_GPIO_C0_NR,
71 .label = "GPC0",
72 },
73 }, {
74 .chip = {
75 .base = S5PV210_GPC1(0),
76 .ngpio = S5PV210_GPIO_C1_NR,
77 .label = "GPC1",
78 },
79 }, {
80 .chip = {
81 .base = S5PV210_GPD0(0),
82 .ngpio = S5PV210_GPIO_D0_NR,
83 .label = "GPD0",
84 },
85 }, {
86 .chip = {
87 .base = S5PV210_GPD1(0),
88 .ngpio = S5PV210_GPIO_D1_NR,
89 .label = "GPD1",
90 },
91 }, {
92 .chip = {
93 .base = S5PV210_GPE0(0),
94 .ngpio = S5PV210_GPIO_E0_NR,
95 .label = "GPE0",
96 },
97 }, {
98 .chip = {
99 .base = S5PV210_GPE1(0),
100 .ngpio = S5PV210_GPIO_E1_NR,
101 .label = "GPE1",
102 },
103 }, {
104 .chip = {
105 .base = S5PV210_GPF0(0),
106 .ngpio = S5PV210_GPIO_F0_NR,
107 .label = "GPF0",
108 },
109 }, {
110 .chip = {
111 .base = S5PV210_GPF1(0),
112 .ngpio = S5PV210_GPIO_F1_NR,
113 .label = "GPF1",
114 },
115 }, {
116 .chip = {
117 .base = S5PV210_GPF2(0),
118 .ngpio = S5PV210_GPIO_F2_NR,
119 .label = "GPF2",
120 },
121 }, {
122 .chip = {
123 .base = S5PV210_GPF3(0),
124 .ngpio = S5PV210_GPIO_F3_NR,
125 .label = "GPF3",
126 },
127 }, {
128 .chip = {
129 .base = S5PV210_GPG0(0),
130 .ngpio = S5PV210_GPIO_G0_NR,
131 .label = "GPG0",
132 },
133 }, {
134 .chip = {
135 .base = S5PV210_GPG1(0),
136 .ngpio = S5PV210_GPIO_G1_NR,
137 .label = "GPG1",
138 },
139 }, {
140 .chip = {
141 .base = S5PV210_GPG2(0),
142 .ngpio = S5PV210_GPIO_G2_NR,
143 .label = "GPG2",
144 },
145 }, {
146 .chip = {
147 .base = S5PV210_GPG3(0),
148 .ngpio = S5PV210_GPIO_G3_NR,
149 .label = "GPG3",
150 },
151 }, {
152 .config = &gpio_cfg_noint,
153 .chip = {
154 .base = S5PV210_GPI(0),
155 .ngpio = S5PV210_GPIO_I_NR,
156 .label = "GPI",
157 },
158 }, {
159 .chip = {
160 .base = S5PV210_GPJ0(0),
161 .ngpio = S5PV210_GPIO_J0_NR,
162 .label = "GPJ0",
163 },
164 }, {
165 .chip = {
166 .base = S5PV210_GPJ1(0),
167 .ngpio = S5PV210_GPIO_J1_NR,
168 .label = "GPJ1",
169 },
170 }, {
171 .chip = {
172 .base = S5PV210_GPJ2(0),
173 .ngpio = S5PV210_GPIO_J2_NR,
174 .label = "GPJ2",
175 },
176 }, {
177 .chip = {
178 .base = S5PV210_GPJ3(0),
179 .ngpio = S5PV210_GPIO_J3_NR,
180 .label = "GPJ3",
181 },
182 }, {
183 .chip = {
184 .base = S5PV210_GPJ4(0),
185 .ngpio = S5PV210_GPIO_J4_NR,
186 .label = "GPJ4",
187 },
188 }, {
189 .config = &gpio_cfg_noint,
190 .chip = {
191 .base = S5PV210_MP01(0),
192 .ngpio = S5PV210_GPIO_MP01_NR,
193 .label = "MP01",
194 },
195 }, {
196 .config = &gpio_cfg_noint,
197 .chip = {
198 .base = S5PV210_MP02(0),
199 .ngpio = S5PV210_GPIO_MP02_NR,
200 .label = "MP02",
201 },
202 }, {
203 .config = &gpio_cfg_noint,
204 .chip = {
205 .base = S5PV210_MP03(0),
206 .ngpio = S5PV210_GPIO_MP03_NR,
207 .label = "MP03",
208 },
209 }, {
210 .config = &gpio_cfg_noint,
211 .chip = {
212 .base = S5PV210_MP04(0),
213 .ngpio = S5PV210_GPIO_MP04_NR,
214 .label = "MP04",
215 },
216 }, {
217 .config = &gpio_cfg_noint,
218 .chip = {
219 .base = S5PV210_MP05(0),
220 .ngpio = S5PV210_GPIO_MP05_NR,
221 .label = "MP05",
222 },
223 }, {
224 .base = (S5P_VA_GPIO + 0xC00),
225 .config = &gpio_cfg_noint,
226 .irq_base = IRQ_EINT(0),
227 .chip = {
228 .base = S5PV210_GPH0(0),
229 .ngpio = S5PV210_GPIO_H0_NR,
230 .label = "GPH0",
231 .to_irq = samsung_gpiolib_to_irq,
232 },
233 }, {
234 .base = (S5P_VA_GPIO + 0xC20),
235 .config = &gpio_cfg_noint,
236 .irq_base = IRQ_EINT(8),
237 .chip = {
238 .base = S5PV210_GPH1(0),
239 .ngpio = S5PV210_GPIO_H1_NR,
240 .label = "GPH1",
241 .to_irq = samsung_gpiolib_to_irq,
242 },
243 }, {
244 .base = (S5P_VA_GPIO + 0xC40),
245 .config = &gpio_cfg_noint,
246 .irq_base = IRQ_EINT(16),
247 .chip = {
248 .base = S5PV210_GPH2(0),
249 .ngpio = S5PV210_GPIO_H2_NR,
250 .label = "GPH2",
251 .to_irq = samsung_gpiolib_to_irq,
252 },
253 }, {
254 .base = (S5P_VA_GPIO + 0xC60),
255 .config = &gpio_cfg_noint,
256 .irq_base = IRQ_EINT(24),
257 .chip = {
258 .base = S5PV210_GPH3(0),
259 .ngpio = S5PV210_GPIO_H3_NR,
260 .label = "GPH3",
261 .to_irq = samsung_gpiolib_to_irq,
262 },
263 },
264};
265
266static __init int s5pv210_gpiolib_init(void)
267{
268 struct s3c_gpio_chip *chip = s5pv210_gpio_4bit;
269 int nr_chips = ARRAY_SIZE(s5pv210_gpio_4bit);
270 int gpioint_group = 0;
271 int i = 0;
272
273 for (i = 0; i < nr_chips; i++, chip++) {
274 if (chip->config == NULL) {
275 chip->config = &gpio_cfg;
276 chip->group = gpioint_group++;
277 }
278 if (chip->base == NULL)
279 chip->base = S5PV210_BANK_BASE(i);
280 }
281
282 samsung_gpiolib_add_4bit_chips(s5pv210_gpio_4bit, nr_chips);
283 s5p_register_gpioint_bank(IRQ_GPIOINT, 0, S5P_GPIOINT_GROUP_MAXNR);
284
285 return 0;
286}
287core_initcall(s5pv210_gpiolib_init);
diff --git a/drivers/gpio/gpio-samsung.c b/drivers/gpio/gpio-samsung.c
new file mode 100644
index 000000000000..b6be77ae4973
--- /dev/null
+++ b/drivers/gpio/gpio-samsung.c
@@ -0,0 +1,2688 @@
1/*
2 * Copyright (c) 2009-2011 Samsung Electronics Co., Ltd.
3 * http://www.samsung.com/
4 *
5 * Copyright 2008 Openmoko, Inc.
6 * Copyright 2008 Simtec Electronics
7 * Ben Dooks <ben@simtec.co.uk>
8 * http://armlinux.simtec.co.uk/
9 *
10 * SAMSUNG - GPIOlib support
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License version 2 as
14 * published by the Free Software Foundation.
15 */
16
17#include <linux/kernel.h>
18#include <linux/irq.h>
19#include <linux/io.h>
20#include <linux/gpio.h>
21#include <linux/init.h>
22#include <linux/spinlock.h>
23#include <linux/module.h>
24#include <linux/interrupt.h>
25#include <linux/sysdev.h>
26#include <linux/ioport.h>
27
28#include <asm/irq.h>
29
30#include <mach/hardware.h>
31#include <mach/map.h>
32#include <mach/regs-clock.h>
33#include <mach/regs-gpio.h>
34
35#include <plat/cpu.h>
36#include <plat/gpio-core.h>
37#include <plat/gpio-cfg.h>
38#include <plat/gpio-cfg-helpers.h>
39#include <plat/gpio-fns.h>
40#include <plat/pm.h>
41
42#ifndef DEBUG_GPIO
43#define gpio_dbg(x...) do { } while (0)
44#else
45#define gpio_dbg(x...) printk(KERN_DEBUG x)
46#endif
47
48int samsung_gpio_setpull_updown(struct samsung_gpio_chip *chip,
49 unsigned int off, samsung_gpio_pull_t pull)
50{
51 void __iomem *reg = chip->base + 0x08;
52 int shift = off * 2;
53 u32 pup;
54
55 pup = __raw_readl(reg);
56 pup &= ~(3 << shift);
57 pup |= pull << shift;
58 __raw_writel(pup, reg);
59
60 return 0;
61}
62
63samsung_gpio_pull_t samsung_gpio_getpull_updown(struct samsung_gpio_chip *chip,
64 unsigned int off)
65{
66 void __iomem *reg = chip->base + 0x08;
67 int shift = off * 2;
68 u32 pup = __raw_readl(reg);
69
70 pup >>= shift;
71 pup &= 0x3;
72
73 return (__force samsung_gpio_pull_t)pup;
74}
75
76int s3c2443_gpio_setpull(struct samsung_gpio_chip *chip,
77 unsigned int off, samsung_gpio_pull_t pull)
78{
79 switch (pull) {
80 case S3C_GPIO_PULL_NONE:
81 pull = 0x01;
82 break;
83 case S3C_GPIO_PULL_UP:
84 pull = 0x00;
85 break;
86 case S3C_GPIO_PULL_DOWN:
87 pull = 0x02;
88 break;
89 }
90 return samsung_gpio_setpull_updown(chip, off, pull);
91}
92
93samsung_gpio_pull_t s3c2443_gpio_getpull(struct samsung_gpio_chip *chip,
94 unsigned int off)
95{
96 samsung_gpio_pull_t pull;
97
98 pull = samsung_gpio_getpull_updown(chip, off);
99
100 switch (pull) {
101 case 0x00:
102 pull = S3C_GPIO_PULL_UP;
103 break;
104 case 0x01:
105 case 0x03:
106 pull = S3C_GPIO_PULL_NONE;
107 break;
108 case 0x02:
109 pull = S3C_GPIO_PULL_DOWN;
110 break;
111 }
112
113 return pull;
114}
115
116static int s3c24xx_gpio_setpull_1(struct samsung_gpio_chip *chip,
117 unsigned int off, samsung_gpio_pull_t pull,
118 samsung_gpio_pull_t updown)
119{
120 void __iomem *reg = chip->base + 0x08;
121 u32 pup = __raw_readl(reg);
122
123 if (pull == updown)
124 pup &= ~(1 << off);
125 else if (pull == S3C_GPIO_PULL_NONE)
126 pup |= (1 << off);
127 else
128 return -EINVAL;
129
130 __raw_writel(pup, reg);
131 return 0;
132}
133
134static samsung_gpio_pull_t s3c24xx_gpio_getpull_1(struct samsung_gpio_chip *chip,
135 unsigned int off,
136 samsung_gpio_pull_t updown)
137{
138 void __iomem *reg = chip->base + 0x08;
139 u32 pup = __raw_readl(reg);
140
141 pup &= (1 << off);
142 return pup ? S3C_GPIO_PULL_NONE : updown;
143}
144
145samsung_gpio_pull_t s3c24xx_gpio_getpull_1up(struct samsung_gpio_chip *chip,
146 unsigned int off)
147{
148 return s3c24xx_gpio_getpull_1(chip, off, S3C_GPIO_PULL_UP);
149}
150
151int s3c24xx_gpio_setpull_1up(struct samsung_gpio_chip *chip,
152 unsigned int off, samsung_gpio_pull_t pull)
153{
154 return s3c24xx_gpio_setpull_1(chip, off, pull, S3C_GPIO_PULL_UP);
155}
156
157samsung_gpio_pull_t s3c24xx_gpio_getpull_1down(struct samsung_gpio_chip *chip,
158 unsigned int off)
159{
160 return s3c24xx_gpio_getpull_1(chip, off, S3C_GPIO_PULL_DOWN);
161}
162
163int s3c24xx_gpio_setpull_1down(struct samsung_gpio_chip *chip,
164 unsigned int off, samsung_gpio_pull_t pull)
165{
166 return s3c24xx_gpio_setpull_1(chip, off, pull, S3C_GPIO_PULL_DOWN);
167}
168
169static int exynos4_gpio_setpull(struct samsung_gpio_chip *chip,
170 unsigned int off, samsung_gpio_pull_t pull)
171{
172 if (pull == S3C_GPIO_PULL_UP)
173 pull = 3;
174
175 return samsung_gpio_setpull_updown(chip, off, pull);
176}
177
178static samsung_gpio_pull_t exynos4_gpio_getpull(struct samsung_gpio_chip *chip,
179 unsigned int off)
180{
181 samsung_gpio_pull_t pull;
182
183 pull = samsung_gpio_getpull_updown(chip, off);
184
185 if (pull == 3)
186 pull = S3C_GPIO_PULL_UP;
187
188 return pull;
189}
190
191/*
192 * samsung_gpio_setcfg_2bit - Samsung 2bit style GPIO configuration.
193 * @chip: The gpio chip that is being configured.
194 * @off: The offset for the GPIO being configured.
195 * @cfg: The configuration value to set.
196 *
197 * This helper deal with the GPIO cases where the control register
198 * has two bits of configuration per gpio, which have the following
199 * functions:
200 * 00 = input
201 * 01 = output
202 * 1x = special function
203 */
204
205static int samsung_gpio_setcfg_2bit(struct samsung_gpio_chip *chip,
206 unsigned int off, unsigned int cfg)
207{
208 void __iomem *reg = chip->base;
209 unsigned int shift = off * 2;
210 u32 con;
211
212 if (samsung_gpio_is_cfg_special(cfg)) {
213 cfg &= 0xf;
214 if (cfg > 3)
215 return -EINVAL;
216
217 cfg <<= shift;
218 }
219
220 con = __raw_readl(reg);
221 con &= ~(0x3 << shift);
222 con |= cfg;
223 __raw_writel(con, reg);
224
225 return 0;
226}
227
228/*
229 * samsung_gpio_getcfg_2bit - Samsung 2bit style GPIO configuration read.
230 * @chip: The gpio chip that is being configured.
231 * @off: The offset for the GPIO being configured.
232 *
233 * The reverse of samsung_gpio_setcfg_2bit(). Will return a value whicg
234 * could be directly passed back to samsung_gpio_setcfg_2bit(), from the
235 * S3C_GPIO_SPECIAL() macro.
236 */
237
238static unsigned int samsung_gpio_getcfg_2bit(struct samsung_gpio_chip *chip,
239 unsigned int off)
240{
241 u32 con;
242
243 con = __raw_readl(chip->base);
244 con >>= off * 2;
245 con &= 3;
246
247 /* this conversion works for IN and OUT as well as special mode */
248 return S3C_GPIO_SPECIAL(con);
249}
250
251/*
252 * samsung_gpio_setcfg_4bit - Samsung 4bit single register GPIO config.
253 * @chip: The gpio chip that is being configured.
254 * @off: The offset for the GPIO being configured.
255 * @cfg: The configuration value to set.
256 *
257 * This helper deal with the GPIO cases where the control register has 4 bits
258 * of control per GPIO, generally in the form of:
259 * 0000 = Input
260 * 0001 = Output
261 * others = Special functions (dependent on bank)
262 *
263 * Note, since the code to deal with the case where there are two control
264 * registers instead of one, we do not have a separate set of functions for
265 * each case.
266 */
267
268static int samsung_gpio_setcfg_4bit(struct samsung_gpio_chip *chip,
269 unsigned int off, unsigned int cfg)
270{
271 void __iomem *reg = chip->base;
272 unsigned int shift = (off & 7) * 4;
273 u32 con;
274
275 if (off < 8 && chip->chip.ngpio > 8)
276 reg -= 4;
277
278 if (samsung_gpio_is_cfg_special(cfg)) {
279 cfg &= 0xf;
280 cfg <<= shift;
281 }
282
283 con = __raw_readl(reg);
284 con &= ~(0xf << shift);
285 con |= cfg;
286 __raw_writel(con, reg);
287
288 return 0;
289}
290
291/*
292 * samsung_gpio_getcfg_4bit - Samsung 4bit single register GPIO config read.
293 * @chip: The gpio chip that is being configured.
294 * @off: The offset for the GPIO being configured.
295 *
296 * The reverse of samsung_gpio_setcfg_4bit(), turning a gpio configuration
297 * register setting into a value the software can use, such as could be passed
298 * to samsung_gpio_setcfg_4bit().
299 *
300 * @sa samsung_gpio_getcfg_2bit
301 */
302
303static unsigned samsung_gpio_getcfg_4bit(struct samsung_gpio_chip *chip,
304 unsigned int off)
305{
306 void __iomem *reg = chip->base;
307 unsigned int shift = (off & 7) * 4;
308 u32 con;
309
310 if (off < 8 && chip->chip.ngpio > 8)
311 reg -= 4;
312
313 con = __raw_readl(reg);
314 con >>= shift;
315 con &= 0xf;
316
317 /* this conversion works for IN and OUT as well as special mode */
318 return S3C_GPIO_SPECIAL(con);
319}
320
321/*
322 * s3c24xx_gpio_setcfg_abank - S3C24XX style GPIO configuration (Bank A)
323 * @chip: The gpio chip that is being configured.
324 * @off: The offset for the GPIO being configured.
325 * @cfg: The configuration value to set.
326 *
327 * This helper deal with the GPIO cases where the control register
328 * has one bit of configuration for the gpio, where setting the bit
329 * means the pin is in special function mode and unset means output.
330 */
331
332static int s3c24xx_gpio_setcfg_abank(struct samsung_gpio_chip *chip,
333 unsigned int off, unsigned int cfg)
334{
335 void __iomem *reg = chip->base;
336 unsigned int shift = off;
337 u32 con;
338
339 if (samsung_gpio_is_cfg_special(cfg)) {
340 cfg &= 0xf;
341
342 /* Map output to 0, and SFN2 to 1 */
343 cfg -= 1;
344 if (cfg > 1)
345 return -EINVAL;
346
347 cfg <<= shift;
348 }
349
350 con = __raw_readl(reg);
351 con &= ~(0x1 << shift);
352 con |= cfg;
353 __raw_writel(con, reg);
354
355 return 0;
356}
357
358/*
359 * s3c24xx_gpio_getcfg_abank - S3C24XX style GPIO configuration read (Bank A)
360 * @chip: The gpio chip that is being configured.
361 * @off: The offset for the GPIO being configured.
362 *
363 * The reverse of s3c24xx_gpio_setcfg_abank() turning an GPIO into a usable
364 * GPIO configuration value.
365 *
366 * @sa samsung_gpio_getcfg_2bit
367 * @sa samsung_gpio_getcfg_4bit
368 */
369
370static unsigned s3c24xx_gpio_getcfg_abank(struct samsung_gpio_chip *chip,
371 unsigned int off)
372{
373 u32 con;
374
375 con = __raw_readl(chip->base);
376 con >>= off;
377 con &= 1;
378 con++;
379
380 return S3C_GPIO_SFN(con);
381}
382
383static int s5p64x0_gpio_setcfg_rbank(struct samsung_gpio_chip *chip,
384 unsigned int off, unsigned int cfg)
385{
386 void __iomem *reg = chip->base;
387 unsigned int shift;
388 u32 con;
389
390 switch (off) {
391 case 0:
392 case 1:
393 case 2:
394 case 3:
395 case 4:
396 case 5:
397 shift = (off & 7) * 4;
398 reg -= 4;
399 break;
400 case 6:
401 shift = ((off + 1) & 7) * 4;
402 reg -= 4;
403 default:
404 shift = ((off + 1) & 7) * 4;
405 break;
406 }
407
408 if (samsung_gpio_is_cfg_special(cfg)) {
409 cfg &= 0xf;
410 cfg <<= shift;
411 }
412
413 con = __raw_readl(reg);
414 con &= ~(0xf << shift);
415 con |= cfg;
416 __raw_writel(con, reg);
417
418 return 0;
419}
420
421static void __init samsung_gpiolib_set_cfg(struct samsung_gpio_cfg *chipcfg,
422 int nr_chips)
423{
424 for (; nr_chips > 0; nr_chips--, chipcfg++) {
425 if (!chipcfg->set_config)
426 chipcfg->set_config = samsung_gpio_setcfg_4bit;
427 if (!chipcfg->get_config)
428 chipcfg->get_config = samsung_gpio_getcfg_4bit;
429 if (!chipcfg->set_pull)
430 chipcfg->set_pull = samsung_gpio_setpull_updown;
431 if (!chipcfg->get_pull)
432 chipcfg->get_pull = samsung_gpio_getpull_updown;
433 }
434}
435
436struct samsung_gpio_cfg s3c24xx_gpiocfg_default = {
437 .set_config = samsung_gpio_setcfg_2bit,
438 .get_config = samsung_gpio_getcfg_2bit,
439};
440
441static struct samsung_gpio_cfg s3c24xx_gpiocfg_banka = {
442 .set_config = s3c24xx_gpio_setcfg_abank,
443 .get_config = s3c24xx_gpio_getcfg_abank,
444};
445
446static struct samsung_gpio_cfg exynos4_gpio_cfg = {
447 .set_pull = exynos4_gpio_setpull,
448 .get_pull = exynos4_gpio_getpull,
449 .set_config = samsung_gpio_setcfg_4bit,
450 .get_config = samsung_gpio_getcfg_4bit,
451};
452
453static struct samsung_gpio_cfg s5p64x0_gpio_cfg_rbank = {
454 .cfg_eint = 0x3,
455 .set_config = s5p64x0_gpio_setcfg_rbank,
456 .get_config = samsung_gpio_getcfg_4bit,
457 .set_pull = samsung_gpio_setpull_updown,
458 .get_pull = samsung_gpio_getpull_updown,
459};
460
461static struct samsung_gpio_cfg samsung_gpio_cfgs[] = {
462 {
463 .cfg_eint = 0x0,
464 }, {
465 .cfg_eint = 0x3,
466 }, {
467 .cfg_eint = 0x7,
468 }, {
469 .cfg_eint = 0xF,
470 }, {
471 .cfg_eint = 0x0,
472 .set_config = samsung_gpio_setcfg_2bit,
473 .get_config = samsung_gpio_getcfg_2bit,
474 }, {
475 .cfg_eint = 0x2,
476 .set_config = samsung_gpio_setcfg_2bit,
477 .get_config = samsung_gpio_getcfg_2bit,
478 }, {
479 .cfg_eint = 0x3,
480 .set_config = samsung_gpio_setcfg_2bit,
481 .get_config = samsung_gpio_getcfg_2bit,
482 }, {
483 .set_config = samsung_gpio_setcfg_2bit,
484 .get_config = samsung_gpio_getcfg_2bit,
485 },
486};
487
488/*
489 * Default routines for controlling GPIO, based on the original S3C24XX
490 * GPIO functions which deal with the case where each gpio bank of the
491 * chip is as following:
492 *
493 * base + 0x00: Control register, 2 bits per gpio
494 * gpio n: 2 bits starting at (2*n)
495 * 00 = input, 01 = output, others mean special-function
496 * base + 0x04: Data register, 1 bit per gpio
497 * bit n: data bit n
498*/
499
500static int samsung_gpiolib_2bit_input(struct gpio_chip *chip, unsigned offset)
501{
502 struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
503 void __iomem *base = ourchip->base;
504 unsigned long flags;
505 unsigned long con;
506
507 samsung_gpio_lock(ourchip, flags);
508
509 con = __raw_readl(base + 0x00);
510 con &= ~(3 << (offset * 2));
511
512 __raw_writel(con, base + 0x00);
513
514 samsung_gpio_unlock(ourchip, flags);
515 return 0;
516}
517
518static int samsung_gpiolib_2bit_output(struct gpio_chip *chip,
519 unsigned offset, int value)
520{
521 struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
522 void __iomem *base = ourchip->base;
523 unsigned long flags;
524 unsigned long dat;
525 unsigned long con;
526
527 samsung_gpio_lock(ourchip, flags);
528
529 dat = __raw_readl(base + 0x04);
530 dat &= ~(1 << offset);
531 if (value)
532 dat |= 1 << offset;
533 __raw_writel(dat, base + 0x04);
534
535 con = __raw_readl(base + 0x00);
536 con &= ~(3 << (offset * 2));
537 con |= 1 << (offset * 2);
538
539 __raw_writel(con, base + 0x00);
540 __raw_writel(dat, base + 0x04);
541
542 samsung_gpio_unlock(ourchip, flags);
543 return 0;
544}
545
546/*
547 * The samsung_gpiolib_4bit routines are to control the gpio banks where
548 * the gpio configuration register (GPxCON) has 4 bits per GPIO, as the
549 * following example:
550 *
551 * base + 0x00: Control register, 4 bits per gpio
552 * gpio n: 4 bits starting at (4*n)
553 * 0000 = input, 0001 = output, others mean special-function
554 * base + 0x04: Data register, 1 bit per gpio
555 * bit n: data bit n
556 *
557 * Note, since the data register is one bit per gpio and is at base + 0x4
558 * we can use samsung_gpiolib_get and samsung_gpiolib_set to change the
559 * state of the output.
560 */
561
562static int samsung_gpiolib_4bit_input(struct gpio_chip *chip,
563 unsigned int offset)
564{
565 struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
566 void __iomem *base = ourchip->base;
567 unsigned long con;
568
569 con = __raw_readl(base + GPIOCON_OFF);
570 con &= ~(0xf << con_4bit_shift(offset));
571 __raw_writel(con, base + GPIOCON_OFF);
572
573 gpio_dbg("%s: %p: CON now %08lx\n", __func__, base, con);
574
575 return 0;
576}
577
578static int samsung_gpiolib_4bit_output(struct gpio_chip *chip,
579 unsigned int offset, int value)
580{
581 struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
582 void __iomem *base = ourchip->base;
583 unsigned long con;
584 unsigned long dat;
585
586 con = __raw_readl(base + GPIOCON_OFF);
587 con &= ~(0xf << con_4bit_shift(offset));
588 con |= 0x1 << con_4bit_shift(offset);
589
590 dat = __raw_readl(base + GPIODAT_OFF);
591
592 if (value)
593 dat |= 1 << offset;
594 else
595 dat &= ~(1 << offset);
596
597 __raw_writel(dat, base + GPIODAT_OFF);
598 __raw_writel(con, base + GPIOCON_OFF);
599 __raw_writel(dat, base + GPIODAT_OFF);
600
601 gpio_dbg("%s: %p: CON %08lx, DAT %08lx\n", __func__, base, con, dat);
602
603 return 0;
604}
605
606/*
607 * The next set of routines are for the case where the GPIO configuration
608 * registers are 4 bits per GPIO but there is more than one register (the
609 * bank has more than 8 GPIOs.
610 *
611 * This case is the similar to the 4 bit case, but the registers are as
612 * follows:
613 *
614 * base + 0x00: Control register, 4 bits per gpio (lower 8 GPIOs)
615 * gpio n: 4 bits starting at (4*n)
616 * 0000 = input, 0001 = output, others mean special-function
617 * base + 0x04: Control register, 4 bits per gpio (up to 8 additions GPIOs)
618 * gpio n: 4 bits starting at (4*n)
619 * 0000 = input, 0001 = output, others mean special-function
620 * base + 0x08: Data register, 1 bit per gpio
621 * bit n: data bit n
622 *
623 * To allow us to use the samsung_gpiolib_get and samsung_gpiolib_set
624 * routines we store the 'base + 0x4' address so that these routines see
625 * the data register at ourchip->base + 0x04.
626 */
627
628static int samsung_gpiolib_4bit2_input(struct gpio_chip *chip,
629 unsigned int offset)
630{
631 struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
632 void __iomem *base = ourchip->base;
633 void __iomem *regcon = base;
634 unsigned long con;
635
636 if (offset > 7)
637 offset -= 8;
638 else
639 regcon -= 4;
640
641 con = __raw_readl(regcon);
642 con &= ~(0xf << con_4bit_shift(offset));
643 __raw_writel(con, regcon);
644
645 gpio_dbg("%s: %p: CON %08lx\n", __func__, base, con);
646
647 return 0;
648}
649
650static int samsung_gpiolib_4bit2_output(struct gpio_chip *chip,
651 unsigned int offset, int value)
652{
653 struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
654 void __iomem *base = ourchip->base;
655 void __iomem *regcon = base;
656 unsigned long con;
657 unsigned long dat;
658 unsigned con_offset = offset;
659
660 if (con_offset > 7)
661 con_offset -= 8;
662 else
663 regcon -= 4;
664
665 con = __raw_readl(regcon);
666 con &= ~(0xf << con_4bit_shift(con_offset));
667 con |= 0x1 << con_4bit_shift(con_offset);
668
669 dat = __raw_readl(base + GPIODAT_OFF);
670
671 if (value)
672 dat |= 1 << offset;
673 else
674 dat &= ~(1 << offset);
675
676 __raw_writel(dat, base + GPIODAT_OFF);
677 __raw_writel(con, regcon);
678 __raw_writel(dat, base + GPIODAT_OFF);
679
680 gpio_dbg("%s: %p: CON %08lx, DAT %08lx\n", __func__, base, con, dat);
681
682 return 0;
683}
684
685/* The next set of routines are for the case of s3c24xx bank a */
686
687static int s3c24xx_gpiolib_banka_input(struct gpio_chip *chip, unsigned offset)
688{
689 return -EINVAL;
690}
691
692static int s3c24xx_gpiolib_banka_output(struct gpio_chip *chip,
693 unsigned offset, int value)
694{
695 struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
696 void __iomem *base = ourchip->base;
697 unsigned long flags;
698 unsigned long dat;
699 unsigned long con;
700
701 local_irq_save(flags);
702
703 con = __raw_readl(base + 0x00);
704 dat = __raw_readl(base + 0x04);
705
706 dat &= ~(1 << offset);
707 if (value)
708 dat |= 1 << offset;
709
710 __raw_writel(dat, base + 0x04);
711
712 con &= ~(1 << offset);
713
714 __raw_writel(con, base + 0x00);
715 __raw_writel(dat, base + 0x04);
716
717 local_irq_restore(flags);
718 return 0;
719}
720
721/* The next set of routines are for the case of s5p64x0 bank r */
722
723static int s5p64x0_gpiolib_rbank_input(struct gpio_chip *chip,
724 unsigned int offset)
725{
726 struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
727 void __iomem *base = ourchip->base;
728 void __iomem *regcon = base;
729 unsigned long con;
730 unsigned long flags;
731
732 switch (offset) {
733 case 6:
734 offset += 1;
735 case 0:
736 case 1:
737 case 2:
738 case 3:
739 case 4:
740 case 5:
741 regcon -= 4;
742 break;
743 default:
744 offset -= 7;
745 break;
746 }
747
748 samsung_gpio_lock(ourchip, flags);
749
750 con = __raw_readl(regcon);
751 con &= ~(0xf << con_4bit_shift(offset));
752 __raw_writel(con, regcon);
753
754 samsung_gpio_unlock(ourchip, flags);
755
756 return 0;
757}
758
759static int s5p64x0_gpiolib_rbank_output(struct gpio_chip *chip,
760 unsigned int offset, int value)
761{
762 struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
763 void __iomem *base = ourchip->base;
764 void __iomem *regcon = base;
765 unsigned long con;
766 unsigned long dat;
767 unsigned long flags;
768 unsigned con_offset = offset;
769
770 switch (con_offset) {
771 case 6:
772 con_offset += 1;
773 case 0:
774 case 1:
775 case 2:
776 case 3:
777 case 4:
778 case 5:
779 regcon -= 4;
780 break;
781 default:
782 con_offset -= 7;
783 break;
784 }
785
786 samsung_gpio_lock(ourchip, flags);
787
788 con = __raw_readl(regcon);
789 con &= ~(0xf << con_4bit_shift(con_offset));
790 con |= 0x1 << con_4bit_shift(con_offset);
791
792 dat = __raw_readl(base + GPIODAT_OFF);
793 if (value)
794 dat |= 1 << offset;
795 else
796 dat &= ~(1 << offset);
797
798 __raw_writel(con, regcon);
799 __raw_writel(dat, base + GPIODAT_OFF);
800
801 samsung_gpio_unlock(ourchip, flags);
802
803 return 0;
804}
805
806static void samsung_gpiolib_set(struct gpio_chip *chip,
807 unsigned offset, int value)
808{
809 struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
810 void __iomem *base = ourchip->base;
811 unsigned long flags;
812 unsigned long dat;
813
814 samsung_gpio_lock(ourchip, flags);
815
816 dat = __raw_readl(base + 0x04);
817 dat &= ~(1 << offset);
818 if (value)
819 dat |= 1 << offset;
820 __raw_writel(dat, base + 0x04);
821
822 samsung_gpio_unlock(ourchip, flags);
823}
824
825static int samsung_gpiolib_get(struct gpio_chip *chip, unsigned offset)
826{
827 struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
828 unsigned long val;
829
830 val = __raw_readl(ourchip->base + 0x04);
831 val >>= offset;
832 val &= 1;
833
834 return val;
835}
836
837/*
838 * CONFIG_S3C_GPIO_TRACK enables the tracking of the s3c specific gpios
839 * for use with the configuration calls, and other parts of the s3c gpiolib
840 * support code.
841 *
842 * Not all s3c support code will need this, as some configurations of cpu
843 * may only support one or two different configuration options and have an
844 * easy gpio to samsung_gpio_chip mapping function. If this is the case, then
845 * the machine support file should provide its own samsung_gpiolib_getchip()
846 * and any other necessary functions.
847 */
848
849#ifdef CONFIG_S3C_GPIO_TRACK
850struct samsung_gpio_chip *s3c_gpios[S3C_GPIO_END];
851
852static __init void s3c_gpiolib_track(struct samsung_gpio_chip *chip)
853{
854 unsigned int gpn;
855 int i;
856
857 gpn = chip->chip.base;
858 for (i = 0; i < chip->chip.ngpio; i++, gpn++) {
859 BUG_ON(gpn >= ARRAY_SIZE(s3c_gpios));
860 s3c_gpios[gpn] = chip;
861 }
862}
863#endif /* CONFIG_S3C_GPIO_TRACK */
864
865/*
866 * samsung_gpiolib_add() - add the Samsung gpio_chip.
867 * @chip: The chip to register
868 *
869 * This is a wrapper to gpiochip_add() that takes our specific gpio chip
870 * information and makes the necessary alterations for the platform and
871 * notes the information for use with the configuration systems and any
872 * other parts of the system.
873 */
874
875static void __init samsung_gpiolib_add(struct samsung_gpio_chip *chip)
876{
877 struct gpio_chip *gc = &chip->chip;
878 int ret;
879
880 BUG_ON(!chip->base);
881 BUG_ON(!gc->label);
882 BUG_ON(!gc->ngpio);
883
884 spin_lock_init(&chip->lock);
885
886 if (!gc->direction_input)
887 gc->direction_input = samsung_gpiolib_2bit_input;
888 if (!gc->direction_output)
889 gc->direction_output = samsung_gpiolib_2bit_output;
890 if (!gc->set)
891 gc->set = samsung_gpiolib_set;
892 if (!gc->get)
893 gc->get = samsung_gpiolib_get;
894
895#ifdef CONFIG_PM
896 if (chip->pm != NULL) {
897 if (!chip->pm->save || !chip->pm->resume)
898 printk(KERN_ERR "gpio: %s has missing PM functions\n",
899 gc->label);
900 } else
901 printk(KERN_ERR "gpio: %s has no PM function\n", gc->label);
902#endif
903
904 /* gpiochip_add() prints own failure message on error. */
905 ret = gpiochip_add(gc);
906 if (ret >= 0)
907 s3c_gpiolib_track(chip);
908}
909
910static void __init s3c24xx_gpiolib_add_chips(struct samsung_gpio_chip *chip,
911 int nr_chips, void __iomem *base)
912{
913 int i;
914 struct gpio_chip *gc = &chip->chip;
915
916 for (i = 0 ; i < nr_chips; i++, chip++) {
917 if (!chip->config)
918 chip->config = &s3c24xx_gpiocfg_default;
919 if (!chip->pm)
920 chip->pm = __gpio_pm(&samsung_gpio_pm_2bit);
921 if ((base != NULL) && (chip->base == NULL))
922 chip->base = base + ((i) * 0x10);
923
924 if (!gc->direction_input)
925 gc->direction_input = samsung_gpiolib_2bit_input;
926 if (!gc->direction_output)
927 gc->direction_output = samsung_gpiolib_2bit_output;
928
929 samsung_gpiolib_add(chip);
930 }
931}
932
933static void __init samsung_gpiolib_add_2bit_chips(struct samsung_gpio_chip *chip,
934 int nr_chips, void __iomem *base,
935 unsigned int offset)
936{
937 int i;
938
939 for (i = 0 ; i < nr_chips; i++, chip++) {
940 chip->chip.direction_input = samsung_gpiolib_2bit_input;
941 chip->chip.direction_output = samsung_gpiolib_2bit_output;
942
943 if (!chip->config)
944 chip->config = &samsung_gpio_cfgs[7];
945 if (!chip->pm)
946 chip->pm = __gpio_pm(&samsung_gpio_pm_2bit);
947 if ((base != NULL) && (chip->base == NULL))
948 chip->base = base + ((i) * offset);
949
950 samsung_gpiolib_add(chip);
951 }
952}
953
954/*
955 * samsung_gpiolib_add_4bit_chips - 4bit single register GPIO config.
956 * @chip: The gpio chip that is being configured.
957 * @nr_chips: The no of chips (gpio ports) for the GPIO being configured.
958 *
959 * This helper deal with the GPIO cases where the control register has 4 bits
960 * of control per GPIO, generally in the form of:
961 * 0000 = Input
962 * 0001 = Output
963 * others = Special functions (dependent on bank)
964 *
965 * Note, since the code to deal with the case where there are two control
966 * registers instead of one, we do not have a separate set of function
967 * (samsung_gpiolib_add_4bit2_chips)for each case.
968 */
969
970static void __init samsung_gpiolib_add_4bit_chips(struct samsung_gpio_chip *chip,
971 int nr_chips, void __iomem *base)
972{
973 int i;
974
975 for (i = 0 ; i < nr_chips; i++, chip++) {
976 chip->chip.direction_input = samsung_gpiolib_4bit_input;
977 chip->chip.direction_output = samsung_gpiolib_4bit_output;
978
979 if (!chip->config)
980 chip->config = &samsung_gpio_cfgs[2];
981 if (!chip->pm)
982 chip->pm = __gpio_pm(&samsung_gpio_pm_4bit);
983 if ((base != NULL) && (chip->base == NULL))
984 chip->base = base + ((i) * 0x20);
985
986 samsung_gpiolib_add(chip);
987 }
988}
989
990static void __init samsung_gpiolib_add_4bit2_chips(struct samsung_gpio_chip *chip,
991 int nr_chips)
992{
993 for (; nr_chips > 0; nr_chips--, chip++) {
994 chip->chip.direction_input = samsung_gpiolib_4bit2_input;
995 chip->chip.direction_output = samsung_gpiolib_4bit2_output;
996
997 if (!chip->config)
998 chip->config = &samsung_gpio_cfgs[2];
999 if (!chip->pm)
1000 chip->pm = __gpio_pm(&samsung_gpio_pm_4bit);
1001
1002 samsung_gpiolib_add(chip);
1003 }
1004}
1005
1006static void __init s5p64x0_gpiolib_add_rbank(struct samsung_gpio_chip *chip,
1007 int nr_chips)
1008{
1009 for (; nr_chips > 0; nr_chips--, chip++) {
1010 chip->chip.direction_input = s5p64x0_gpiolib_rbank_input;
1011 chip->chip.direction_output = s5p64x0_gpiolib_rbank_output;
1012
1013 if (!chip->pm)
1014 chip->pm = __gpio_pm(&samsung_gpio_pm_4bit);
1015
1016 samsung_gpiolib_add(chip);
1017 }
1018}
1019
1020int samsung_gpiolib_to_irq(struct gpio_chip *chip, unsigned int offset)
1021{
1022 struct samsung_gpio_chip *samsung_chip = container_of(chip, struct samsung_gpio_chip, chip);
1023
1024 return samsung_chip->irq_base + offset;
1025}
1026
1027#ifdef CONFIG_PLAT_S3C24XX
1028static int s3c24xx_gpiolib_fbank_to_irq(struct gpio_chip *chip, unsigned offset)
1029{
1030 if (offset < 4)
1031 return IRQ_EINT0 + offset;
1032
1033 if (offset < 8)
1034 return IRQ_EINT4 + offset - 4;
1035
1036 return -EINVAL;
1037}
1038#endif
1039
1040#ifdef CONFIG_PLAT_S3C64XX
1041static int s3c64xx_gpiolib_mbank_to_irq(struct gpio_chip *chip, unsigned pin)
1042{
1043 return pin < 5 ? IRQ_EINT(23) + pin : -ENXIO;
1044}
1045
1046static int s3c64xx_gpiolib_lbank_to_irq(struct gpio_chip *chip, unsigned pin)
1047{
1048 return pin >= 8 ? IRQ_EINT(16) + pin - 8 : -ENXIO;
1049}
1050#endif
1051
1052struct samsung_gpio_chip s3c24xx_gpios[] = {
1053#ifdef CONFIG_PLAT_S3C24XX
1054 {
1055 .config = &s3c24xx_gpiocfg_banka,
1056 .chip = {
1057 .base = S3C2410_GPA(0),
1058 .owner = THIS_MODULE,
1059 .label = "GPIOA",
1060 .ngpio = 24,
1061 .direction_input = s3c24xx_gpiolib_banka_input,
1062 .direction_output = s3c24xx_gpiolib_banka_output,
1063 },
1064 }, {
1065 .chip = {
1066 .base = S3C2410_GPB(0),
1067 .owner = THIS_MODULE,
1068 .label = "GPIOB",
1069 .ngpio = 16,
1070 },
1071 }, {
1072 .chip = {
1073 .base = S3C2410_GPC(0),
1074 .owner = THIS_MODULE,
1075 .label = "GPIOC",
1076 .ngpio = 16,
1077 },
1078 }, {
1079 .chip = {
1080 .base = S3C2410_GPD(0),
1081 .owner = THIS_MODULE,
1082 .label = "GPIOD",
1083 .ngpio = 16,
1084 },
1085 }, {
1086 .chip = {
1087 .base = S3C2410_GPE(0),
1088 .label = "GPIOE",
1089 .owner = THIS_MODULE,
1090 .ngpio = 16,
1091 },
1092 }, {
1093 .chip = {
1094 .base = S3C2410_GPF(0),
1095 .owner = THIS_MODULE,
1096 .label = "GPIOF",
1097 .ngpio = 8,
1098 .to_irq = s3c24xx_gpiolib_fbank_to_irq,
1099 },
1100 }, {
1101 .irq_base = IRQ_EINT8,
1102 .chip = {
1103 .base = S3C2410_GPG(0),
1104 .owner = THIS_MODULE,
1105 .label = "GPIOG",
1106 .ngpio = 16,
1107 .to_irq = samsung_gpiolib_to_irq,
1108 },
1109 }, {
1110 .chip = {
1111 .base = S3C2410_GPH(0),
1112 .owner = THIS_MODULE,
1113 .label = "GPIOH",
1114 .ngpio = 11,
1115 },
1116 },
1117 /* GPIOS for the S3C2443 and later devices. */
1118 {
1119 .base = S3C2440_GPJCON,
1120 .chip = {
1121 .base = S3C2410_GPJ(0),
1122 .owner = THIS_MODULE,
1123 .label = "GPIOJ",
1124 .ngpio = 16,
1125 },
1126 }, {
1127 .base = S3C2443_GPKCON,
1128 .chip = {
1129 .base = S3C2410_GPK(0),
1130 .owner = THIS_MODULE,
1131 .label = "GPIOK",
1132 .ngpio = 16,
1133 },
1134 }, {
1135 .base = S3C2443_GPLCON,
1136 .chip = {
1137 .base = S3C2410_GPL(0),
1138 .owner = THIS_MODULE,
1139 .label = "GPIOL",
1140 .ngpio = 15,
1141 },
1142 }, {
1143 .base = S3C2443_GPMCON,
1144 .chip = {
1145 .base = S3C2410_GPM(0),
1146 .owner = THIS_MODULE,
1147 .label = "GPIOM",
1148 .ngpio = 2,
1149 },
1150 },
1151#endif
1152};
1153
1154/*
1155 * GPIO bank summary:
1156 *
1157 * Bank GPIOs Style SlpCon ExtInt Group
1158 * A 8 4Bit Yes 1
1159 * B 7 4Bit Yes 1
1160 * C 8 4Bit Yes 2
1161 * D 5 4Bit Yes 3
1162 * E 5 4Bit Yes None
1163 * F 16 2Bit Yes 4 [1]
1164 * G 7 4Bit Yes 5
1165 * H 10 4Bit[2] Yes 6
1166 * I 16 2Bit Yes None
1167 * J 12 2Bit Yes None
1168 * K 16 4Bit[2] No None
1169 * L 15 4Bit[2] No None
1170 * M 6 4Bit No IRQ_EINT
1171 * N 16 2Bit No IRQ_EINT
1172 * O 16 2Bit Yes 7
1173 * P 15 2Bit Yes 8
1174 * Q 9 2Bit Yes 9
1175 *
1176 * [1] BANKF pins 14,15 do not form part of the external interrupt sources
1177 * [2] BANK has two control registers, GPxCON0 and GPxCON1
1178 */
1179
1180static struct samsung_gpio_chip s3c64xx_gpios_4bit[] = {
1181#ifdef CONFIG_PLAT_S3C64XX
1182 {
1183 .chip = {
1184 .base = S3C64XX_GPA(0),
1185 .ngpio = S3C64XX_GPIO_A_NR,
1186 .label = "GPA",
1187 },
1188 }, {
1189 .chip = {
1190 .base = S3C64XX_GPB(0),
1191 .ngpio = S3C64XX_GPIO_B_NR,
1192 .label = "GPB",
1193 },
1194 }, {
1195 .chip = {
1196 .base = S3C64XX_GPC(0),
1197 .ngpio = S3C64XX_GPIO_C_NR,
1198 .label = "GPC",
1199 },
1200 }, {
1201 .chip = {
1202 .base = S3C64XX_GPD(0),
1203 .ngpio = S3C64XX_GPIO_D_NR,
1204 .label = "GPD",
1205 },
1206 }, {
1207 .config = &samsung_gpio_cfgs[0],
1208 .chip = {
1209 .base = S3C64XX_GPE(0),
1210 .ngpio = S3C64XX_GPIO_E_NR,
1211 .label = "GPE",
1212 },
1213 }, {
1214 .base = S3C64XX_GPG_BASE,
1215 .chip = {
1216 .base = S3C64XX_GPG(0),
1217 .ngpio = S3C64XX_GPIO_G_NR,
1218 .label = "GPG",
1219 },
1220 }, {
1221 .base = S3C64XX_GPM_BASE,
1222 .config = &samsung_gpio_cfgs[1],
1223 .chip = {
1224 .base = S3C64XX_GPM(0),
1225 .ngpio = S3C64XX_GPIO_M_NR,
1226 .label = "GPM",
1227 .to_irq = s3c64xx_gpiolib_mbank_to_irq,
1228 },
1229 },
1230#endif
1231};
1232
1233static struct samsung_gpio_chip s3c64xx_gpios_4bit2[] = {
1234#ifdef CONFIG_PLAT_S3C64XX
1235 {
1236 .base = S3C64XX_GPH_BASE + 0x4,
1237 .chip = {
1238 .base = S3C64XX_GPH(0),
1239 .ngpio = S3C64XX_GPIO_H_NR,
1240 .label = "GPH",
1241 },
1242 }, {
1243 .base = S3C64XX_GPK_BASE + 0x4,
1244 .config = &samsung_gpio_cfgs[0],
1245 .chip = {
1246 .base = S3C64XX_GPK(0),
1247 .ngpio = S3C64XX_GPIO_K_NR,
1248 .label = "GPK",
1249 },
1250 }, {
1251 .base = S3C64XX_GPL_BASE + 0x4,
1252 .config = &samsung_gpio_cfgs[1],
1253 .chip = {
1254 .base = S3C64XX_GPL(0),
1255 .ngpio = S3C64XX_GPIO_L_NR,
1256 .label = "GPL",
1257 .to_irq = s3c64xx_gpiolib_lbank_to_irq,
1258 },
1259 },
1260#endif
1261};
1262
1263static struct samsung_gpio_chip s3c64xx_gpios_2bit[] = {
1264#ifdef CONFIG_PLAT_S3C64XX
1265 {
1266 .base = S3C64XX_GPF_BASE,
1267 .config = &samsung_gpio_cfgs[6],
1268 .chip = {
1269 .base = S3C64XX_GPF(0),
1270 .ngpio = S3C64XX_GPIO_F_NR,
1271 .label = "GPF",
1272 },
1273 }, {
1274 .config = &samsung_gpio_cfgs[7],
1275 .chip = {
1276 .base = S3C64XX_GPI(0),
1277 .ngpio = S3C64XX_GPIO_I_NR,
1278 .label = "GPI",
1279 },
1280 }, {
1281 .config = &samsung_gpio_cfgs[7],
1282 .chip = {
1283 .base = S3C64XX_GPJ(0),
1284 .ngpio = S3C64XX_GPIO_J_NR,
1285 .label = "GPJ",
1286 },
1287 }, {
1288 .config = &samsung_gpio_cfgs[6],
1289 .chip = {
1290 .base = S3C64XX_GPO(0),
1291 .ngpio = S3C64XX_GPIO_O_NR,
1292 .label = "GPO",
1293 },
1294 }, {
1295 .config = &samsung_gpio_cfgs[6],
1296 .chip = {
1297 .base = S3C64XX_GPP(0),
1298 .ngpio = S3C64XX_GPIO_P_NR,
1299 .label = "GPP",
1300 },
1301 }, {
1302 .config = &samsung_gpio_cfgs[6],
1303 .chip = {
1304 .base = S3C64XX_GPQ(0),
1305 .ngpio = S3C64XX_GPIO_Q_NR,
1306 .label = "GPQ",
1307 },
1308 }, {
1309 .base = S3C64XX_GPN_BASE,
1310 .irq_base = IRQ_EINT(0),
1311 .config = &samsung_gpio_cfgs[5],
1312 .chip = {
1313 .base = S3C64XX_GPN(0),
1314 .ngpio = S3C64XX_GPIO_N_NR,
1315 .label = "GPN",
1316 .to_irq = samsung_gpiolib_to_irq,
1317 },
1318 },
1319#endif
1320};
1321
1322/*
1323 * S5P6440 GPIO bank summary:
1324 *
1325 * Bank GPIOs Style SlpCon ExtInt Group
1326 * A 6 4Bit Yes 1
1327 * B 7 4Bit Yes 1
1328 * C 8 4Bit Yes 2
1329 * F 2 2Bit Yes 4 [1]
1330 * G 7 4Bit Yes 5
1331 * H 10 4Bit[2] Yes 6
1332 * I 16 2Bit Yes None
1333 * J 12 2Bit Yes None
1334 * N 16 2Bit No IRQ_EINT
1335 * P 8 2Bit Yes 8
1336 * R 15 4Bit[2] Yes 8
1337 */
1338
1339static struct samsung_gpio_chip s5p6440_gpios_4bit[] = {
1340#ifdef CONFIG_CPU_S5P6440
1341 {
1342 .chip = {
1343 .base = S5P6440_GPA(0),
1344 .ngpio = S5P6440_GPIO_A_NR,
1345 .label = "GPA",
1346 },
1347 }, {
1348 .chip = {
1349 .base = S5P6440_GPB(0),
1350 .ngpio = S5P6440_GPIO_B_NR,
1351 .label = "GPB",
1352 },
1353 }, {
1354 .chip = {
1355 .base = S5P6440_GPC(0),
1356 .ngpio = S5P6440_GPIO_C_NR,
1357 .label = "GPC",
1358 },
1359 }, {
1360 .base = S5P64X0_GPG_BASE,
1361 .chip = {
1362 .base = S5P6440_GPG(0),
1363 .ngpio = S5P6440_GPIO_G_NR,
1364 .label = "GPG",
1365 },
1366 },
1367#endif
1368};
1369
1370static struct samsung_gpio_chip s5p6440_gpios_4bit2[] = {
1371#ifdef CONFIG_CPU_S5P6440
1372 {
1373 .base = S5P64X0_GPH_BASE + 0x4,
1374 .chip = {
1375 .base = S5P6440_GPH(0),
1376 .ngpio = S5P6440_GPIO_H_NR,
1377 .label = "GPH",
1378 },
1379 },
1380#endif
1381};
1382
1383static struct samsung_gpio_chip s5p6440_gpios_rbank[] = {
1384#ifdef CONFIG_CPU_S5P6440
1385 {
1386 .base = S5P64X0_GPR_BASE + 0x4,
1387 .config = &s5p64x0_gpio_cfg_rbank,
1388 .chip = {
1389 .base = S5P6440_GPR(0),
1390 .ngpio = S5P6440_GPIO_R_NR,
1391 .label = "GPR",
1392 },
1393 },
1394#endif
1395};
1396
1397static struct samsung_gpio_chip s5p6440_gpios_2bit[] = {
1398#ifdef CONFIG_CPU_S5P6440
1399 {
1400 .base = S5P64X0_GPF_BASE,
1401 .config = &samsung_gpio_cfgs[6],
1402 .chip = {
1403 .base = S5P6440_GPF(0),
1404 .ngpio = S5P6440_GPIO_F_NR,
1405 .label = "GPF",
1406 },
1407 }, {
1408 .base = S5P64X0_GPI_BASE,
1409 .config = &samsung_gpio_cfgs[4],
1410 .chip = {
1411 .base = S5P6440_GPI(0),
1412 .ngpio = S5P6440_GPIO_I_NR,
1413 .label = "GPI",
1414 },
1415 }, {
1416 .base = S5P64X0_GPJ_BASE,
1417 .config = &samsung_gpio_cfgs[4],
1418 .chip = {
1419 .base = S5P6440_GPJ(0),
1420 .ngpio = S5P6440_GPIO_J_NR,
1421 .label = "GPJ",
1422 },
1423 }, {
1424 .base = S5P64X0_GPN_BASE,
1425 .config = &samsung_gpio_cfgs[5],
1426 .chip = {
1427 .base = S5P6440_GPN(0),
1428 .ngpio = S5P6440_GPIO_N_NR,
1429 .label = "GPN",
1430 },
1431 }, {
1432 .base = S5P64X0_GPP_BASE,
1433 .config = &samsung_gpio_cfgs[6],
1434 .chip = {
1435 .base = S5P6440_GPP(0),
1436 .ngpio = S5P6440_GPIO_P_NR,
1437 .label = "GPP",
1438 },
1439 },
1440#endif
1441};
1442
1443/*
1444 * S5P6450 GPIO bank summary:
1445 *
1446 * Bank GPIOs Style SlpCon ExtInt Group
1447 * A 6 4Bit Yes 1
1448 * B 7 4Bit Yes 1
1449 * C 8 4Bit Yes 2
1450 * D 8 4Bit Yes None
1451 * F 2 2Bit Yes None
1452 * G 14 4Bit[2] Yes 5
1453 * H 10 4Bit[2] Yes 6
1454 * I 16 2Bit Yes None
1455 * J 12 2Bit Yes None
1456 * K 5 4Bit Yes None
1457 * N 16 2Bit No IRQ_EINT
1458 * P 11 2Bit Yes 8
1459 * Q 14 2Bit Yes None
1460 * R 15 4Bit[2] Yes None
1461 * S 8 2Bit Yes None
1462 *
1463 * [1] BANKF pins 14,15 do not form part of the external interrupt sources
1464 * [2] BANK has two control registers, GPxCON0 and GPxCON1
1465 */
1466
1467static struct samsung_gpio_chip s5p6450_gpios_4bit[] = {
1468#ifdef CONFIG_CPU_S5P6450
1469 {
1470 .chip = {
1471 .base = S5P6450_GPA(0),
1472 .ngpio = S5P6450_GPIO_A_NR,
1473 .label = "GPA",
1474 },
1475 }, {
1476 .chip = {
1477 .base = S5P6450_GPB(0),
1478 .ngpio = S5P6450_GPIO_B_NR,
1479 .label = "GPB",
1480 },
1481 }, {
1482 .chip = {
1483 .base = S5P6450_GPC(0),
1484 .ngpio = S5P6450_GPIO_C_NR,
1485 .label = "GPC",
1486 },
1487 }, {
1488 .chip = {
1489 .base = S5P6450_GPD(0),
1490 .ngpio = S5P6450_GPIO_D_NR,
1491 .label = "GPD",
1492 },
1493 }, {
1494 .base = S5P6450_GPK_BASE,
1495 .chip = {
1496 .base = S5P6450_GPK(0),
1497 .ngpio = S5P6450_GPIO_K_NR,
1498 .label = "GPK",
1499 },
1500 },
1501#endif
1502};
1503
1504static struct samsung_gpio_chip s5p6450_gpios_4bit2[] = {
1505#ifdef CONFIG_CPU_S5P6450
1506 {
1507 .base = S5P64X0_GPG_BASE + 0x4,
1508 .chip = {
1509 .base = S5P6450_GPG(0),
1510 .ngpio = S5P6450_GPIO_G_NR,
1511 .label = "GPG",
1512 },
1513 }, {
1514 .base = S5P64X0_GPH_BASE + 0x4,
1515 .chip = {
1516 .base = S5P6450_GPH(0),
1517 .ngpio = S5P6450_GPIO_H_NR,
1518 .label = "GPH",
1519 },
1520 },
1521#endif
1522};
1523
1524static struct samsung_gpio_chip s5p6450_gpios_rbank[] = {
1525#ifdef CONFIG_CPU_S5P6450
1526 {
1527 .base = S5P64X0_GPR_BASE + 0x4,
1528 .config = &s5p64x0_gpio_cfg_rbank,
1529 .chip = {
1530 .base = S5P6450_GPR(0),
1531 .ngpio = S5P6450_GPIO_R_NR,
1532 .label = "GPR",
1533 },
1534 },
1535#endif
1536};
1537
1538static struct samsung_gpio_chip s5p6450_gpios_2bit[] = {
1539#ifdef CONFIG_CPU_S5P6450
1540 {
1541 .base = S5P64X0_GPF_BASE,
1542 .config = &samsung_gpio_cfgs[6],
1543 .chip = {
1544 .base = S5P6450_GPF(0),
1545 .ngpio = S5P6450_GPIO_F_NR,
1546 .label = "GPF",
1547 },
1548 }, {
1549 .base = S5P64X0_GPI_BASE,
1550 .config = &samsung_gpio_cfgs[4],
1551 .chip = {
1552 .base = S5P6450_GPI(0),
1553 .ngpio = S5P6450_GPIO_I_NR,
1554 .label = "GPI",
1555 },
1556 }, {
1557 .base = S5P64X0_GPJ_BASE,
1558 .config = &samsung_gpio_cfgs[4],
1559 .chip = {
1560 .base = S5P6450_GPJ(0),
1561 .ngpio = S5P6450_GPIO_J_NR,
1562 .label = "GPJ",
1563 },
1564 }, {
1565 .base = S5P64X0_GPN_BASE,
1566 .config = &samsung_gpio_cfgs[5],
1567 .chip = {
1568 .base = S5P6450_GPN(0),
1569 .ngpio = S5P6450_GPIO_N_NR,
1570 .label = "GPN",
1571 },
1572 }, {
1573 .base = S5P64X0_GPP_BASE,
1574 .config = &samsung_gpio_cfgs[6],
1575 .chip = {
1576 .base = S5P6450_GPP(0),
1577 .ngpio = S5P6450_GPIO_P_NR,
1578 .label = "GPP",
1579 },
1580 }, {
1581 .base = S5P6450_GPQ_BASE,
1582 .config = &samsung_gpio_cfgs[5],
1583 .chip = {
1584 .base = S5P6450_GPQ(0),
1585 .ngpio = S5P6450_GPIO_Q_NR,
1586 .label = "GPQ",
1587 },
1588 }, {
1589 .base = S5P6450_GPS_BASE,
1590 .config = &samsung_gpio_cfgs[6],
1591 .chip = {
1592 .base = S5P6450_GPS(0),
1593 .ngpio = S5P6450_GPIO_S_NR,
1594 .label = "GPS",
1595 },
1596 },
1597#endif
1598};
1599
1600/*
1601 * S5PC100 GPIO bank summary:
1602 *
1603 * Bank GPIOs Style INT Type
1604 * A0 8 4Bit GPIO_INT0
1605 * A1 5 4Bit GPIO_INT1
1606 * B 8 4Bit GPIO_INT2
1607 * C 5 4Bit GPIO_INT3
1608 * D 7 4Bit GPIO_INT4
1609 * E0 8 4Bit GPIO_INT5
1610 * E1 6 4Bit GPIO_INT6
1611 * F0 8 4Bit GPIO_INT7
1612 * F1 8 4Bit GPIO_INT8
1613 * F2 8 4Bit GPIO_INT9
1614 * F3 4 4Bit GPIO_INT10
1615 * G0 8 4Bit GPIO_INT11
1616 * G1 3 4Bit GPIO_INT12
1617 * G2 7 4Bit GPIO_INT13
1618 * G3 7 4Bit GPIO_INT14
1619 * H0 8 4Bit WKUP_INT
1620 * H1 8 4Bit WKUP_INT
1621 * H2 8 4Bit WKUP_INT
1622 * H3 8 4Bit WKUP_INT
1623 * I 8 4Bit GPIO_INT15
1624 * J0 8 4Bit GPIO_INT16
1625 * J1 5 4Bit GPIO_INT17
1626 * J2 8 4Bit GPIO_INT18
1627 * J3 8 4Bit GPIO_INT19
1628 * J4 4 4Bit GPIO_INT20
1629 * K0 8 4Bit None
1630 * K1 6 4Bit None
1631 * K2 8 4Bit None
1632 * K3 8 4Bit None
1633 * L0 8 4Bit None
1634 * L1 8 4Bit None
1635 * L2 8 4Bit None
1636 * L3 8 4Bit None
1637 */
1638
1639static struct samsung_gpio_chip s5pc100_gpios_4bit[] = {
1640#ifdef CONFIG_CPU_S5PC100
1641 {
1642 .chip = {
1643 .base = S5PC100_GPA0(0),
1644 .ngpio = S5PC100_GPIO_A0_NR,
1645 .label = "GPA0",
1646 },
1647 }, {
1648 .chip = {
1649 .base = S5PC100_GPA1(0),
1650 .ngpio = S5PC100_GPIO_A1_NR,
1651 .label = "GPA1",
1652 },
1653 }, {
1654 .chip = {
1655 .base = S5PC100_GPB(0),
1656 .ngpio = S5PC100_GPIO_B_NR,
1657 .label = "GPB",
1658 },
1659 }, {
1660 .chip = {
1661 .base = S5PC100_GPC(0),
1662 .ngpio = S5PC100_GPIO_C_NR,
1663 .label = "GPC",
1664 },
1665 }, {
1666 .chip = {
1667 .base = S5PC100_GPD(0),
1668 .ngpio = S5PC100_GPIO_D_NR,
1669 .label = "GPD",
1670 },
1671 }, {
1672 .chip = {
1673 .base = S5PC100_GPE0(0),
1674 .ngpio = S5PC100_GPIO_E0_NR,
1675 .label = "GPE0",
1676 },
1677 }, {
1678 .chip = {
1679 .base = S5PC100_GPE1(0),
1680 .ngpio = S5PC100_GPIO_E1_NR,
1681 .label = "GPE1",
1682 },
1683 }, {
1684 .chip = {
1685 .base = S5PC100_GPF0(0),
1686 .ngpio = S5PC100_GPIO_F0_NR,
1687 .label = "GPF0",
1688 },
1689 }, {
1690 .chip = {
1691 .base = S5PC100_GPF1(0),
1692 .ngpio = S5PC100_GPIO_F1_NR,
1693 .label = "GPF1",
1694 },
1695 }, {
1696 .chip = {
1697 .base = S5PC100_GPF2(0),
1698 .ngpio = S5PC100_GPIO_F2_NR,
1699 .label = "GPF2",
1700 },
1701 }, {
1702 .chip = {
1703 .base = S5PC100_GPF3(0),
1704 .ngpio = S5PC100_GPIO_F3_NR,
1705 .label = "GPF3",
1706 },
1707 }, {
1708 .chip = {
1709 .base = S5PC100_GPG0(0),
1710 .ngpio = S5PC100_GPIO_G0_NR,
1711 .label = "GPG0",
1712 },
1713 }, {
1714 .chip = {
1715 .base = S5PC100_GPG1(0),
1716 .ngpio = S5PC100_GPIO_G1_NR,
1717 .label = "GPG1",
1718 },
1719 }, {
1720 .chip = {
1721 .base = S5PC100_GPG2(0),
1722 .ngpio = S5PC100_GPIO_G2_NR,
1723 .label = "GPG2",
1724 },
1725 }, {
1726 .chip = {
1727 .base = S5PC100_GPG3(0),
1728 .ngpio = S5PC100_GPIO_G3_NR,
1729 .label = "GPG3",
1730 },
1731 }, {
1732 .chip = {
1733 .base = S5PC100_GPI(0),
1734 .ngpio = S5PC100_GPIO_I_NR,
1735 .label = "GPI",
1736 },
1737 }, {
1738 .chip = {
1739 .base = S5PC100_GPJ0(0),
1740 .ngpio = S5PC100_GPIO_J0_NR,
1741 .label = "GPJ0",
1742 },
1743 }, {
1744 .chip = {
1745 .base = S5PC100_GPJ1(0),
1746 .ngpio = S5PC100_GPIO_J1_NR,
1747 .label = "GPJ1",
1748 },
1749 }, {
1750 .chip = {
1751 .base = S5PC100_GPJ2(0),
1752 .ngpio = S5PC100_GPIO_J2_NR,
1753 .label = "GPJ2",
1754 },
1755 }, {
1756 .chip = {
1757 .base = S5PC100_GPJ3(0),
1758 .ngpio = S5PC100_GPIO_J3_NR,
1759 .label = "GPJ3",
1760 },
1761 }, {
1762 .chip = {
1763 .base = S5PC100_GPJ4(0),
1764 .ngpio = S5PC100_GPIO_J4_NR,
1765 .label = "GPJ4",
1766 },
1767 }, {
1768 .chip = {
1769 .base = S5PC100_GPK0(0),
1770 .ngpio = S5PC100_GPIO_K0_NR,
1771 .label = "GPK0",
1772 },
1773 }, {
1774 .chip = {
1775 .base = S5PC100_GPK1(0),
1776 .ngpio = S5PC100_GPIO_K1_NR,
1777 .label = "GPK1",
1778 },
1779 }, {
1780 .chip = {
1781 .base = S5PC100_GPK2(0),
1782 .ngpio = S5PC100_GPIO_K2_NR,
1783 .label = "GPK2",
1784 },
1785 }, {
1786 .chip = {
1787 .base = S5PC100_GPK3(0),
1788 .ngpio = S5PC100_GPIO_K3_NR,
1789 .label = "GPK3",
1790 },
1791 }, {
1792 .chip = {
1793 .base = S5PC100_GPL0(0),
1794 .ngpio = S5PC100_GPIO_L0_NR,
1795 .label = "GPL0",
1796 },
1797 }, {
1798 .chip = {
1799 .base = S5PC100_GPL1(0),
1800 .ngpio = S5PC100_GPIO_L1_NR,
1801 .label = "GPL1",
1802 },
1803 }, {
1804 .chip = {
1805 .base = S5PC100_GPL2(0),
1806 .ngpio = S5PC100_GPIO_L2_NR,
1807 .label = "GPL2",
1808 },
1809 }, {
1810 .chip = {
1811 .base = S5PC100_GPL3(0),
1812 .ngpio = S5PC100_GPIO_L3_NR,
1813 .label = "GPL3",
1814 },
1815 }, {
1816 .chip = {
1817 .base = S5PC100_GPL4(0),
1818 .ngpio = S5PC100_GPIO_L4_NR,
1819 .label = "GPL4",
1820 },
1821 }, {
1822 .base = (S5P_VA_GPIO + 0xC00),
1823 .irq_base = IRQ_EINT(0),
1824 .chip = {
1825 .base = S5PC100_GPH0(0),
1826 .ngpio = S5PC100_GPIO_H0_NR,
1827 .label = "GPH0",
1828 .to_irq = samsung_gpiolib_to_irq,
1829 },
1830 }, {
1831 .base = (S5P_VA_GPIO + 0xC20),
1832 .irq_base = IRQ_EINT(8),
1833 .chip = {
1834 .base = S5PC100_GPH1(0),
1835 .ngpio = S5PC100_GPIO_H1_NR,
1836 .label = "GPH1",
1837 .to_irq = samsung_gpiolib_to_irq,
1838 },
1839 }, {
1840 .base = (S5P_VA_GPIO + 0xC40),
1841 .irq_base = IRQ_EINT(16),
1842 .chip = {
1843 .base = S5PC100_GPH2(0),
1844 .ngpio = S5PC100_GPIO_H2_NR,
1845 .label = "GPH2",
1846 .to_irq = samsung_gpiolib_to_irq,
1847 },
1848 }, {
1849 .base = (S5P_VA_GPIO + 0xC60),
1850 .irq_base = IRQ_EINT(24),
1851 .chip = {
1852 .base = S5PC100_GPH3(0),
1853 .ngpio = S5PC100_GPIO_H3_NR,
1854 .label = "GPH3",
1855 .to_irq = samsung_gpiolib_to_irq,
1856 },
1857 },
1858#endif
1859};
1860
1861/*
1862 * Followings are the gpio banks in S5PV210/S5PC110
1863 *
1864 * The 'config' member when left to NULL, is initialized to the default
1865 * structure samsung_gpio_cfgs[3] in the init function below.
1866 *
1867 * The 'base' member is also initialized in the init function below.
1868 * Note: The initialization of 'base' member of samsung_gpio_chip structure
1869 * uses the above macro and depends on the banks being listed in order here.
1870 */
1871
1872static struct samsung_gpio_chip s5pv210_gpios_4bit[] = {
1873#ifdef CONFIG_CPU_S5PV210
1874 {
1875 .chip = {
1876 .base = S5PV210_GPA0(0),
1877 .ngpio = S5PV210_GPIO_A0_NR,
1878 .label = "GPA0",
1879 },
1880 }, {
1881 .chip = {
1882 .base = S5PV210_GPA1(0),
1883 .ngpio = S5PV210_GPIO_A1_NR,
1884 .label = "GPA1",
1885 },
1886 }, {
1887 .chip = {
1888 .base = S5PV210_GPB(0),
1889 .ngpio = S5PV210_GPIO_B_NR,
1890 .label = "GPB",
1891 },
1892 }, {
1893 .chip = {
1894 .base = S5PV210_GPC0(0),
1895 .ngpio = S5PV210_GPIO_C0_NR,
1896 .label = "GPC0",
1897 },
1898 }, {
1899 .chip = {
1900 .base = S5PV210_GPC1(0),
1901 .ngpio = S5PV210_GPIO_C1_NR,
1902 .label = "GPC1",
1903 },
1904 }, {
1905 .chip = {
1906 .base = S5PV210_GPD0(0),
1907 .ngpio = S5PV210_GPIO_D0_NR,
1908 .label = "GPD0",
1909 },
1910 }, {
1911 .chip = {
1912 .base = S5PV210_GPD1(0),
1913 .ngpio = S5PV210_GPIO_D1_NR,
1914 .label = "GPD1",
1915 },
1916 }, {
1917 .chip = {
1918 .base = S5PV210_GPE0(0),
1919 .ngpio = S5PV210_GPIO_E0_NR,
1920 .label = "GPE0",
1921 },
1922 }, {
1923 .chip = {
1924 .base = S5PV210_GPE1(0),
1925 .ngpio = S5PV210_GPIO_E1_NR,
1926 .label = "GPE1",
1927 },
1928 }, {
1929 .chip = {
1930 .base = S5PV210_GPF0(0),
1931 .ngpio = S5PV210_GPIO_F0_NR,
1932 .label = "GPF0",
1933 },
1934 }, {
1935 .chip = {
1936 .base = S5PV210_GPF1(0),
1937 .ngpio = S5PV210_GPIO_F1_NR,
1938 .label = "GPF1",
1939 },
1940 }, {
1941 .chip = {
1942 .base = S5PV210_GPF2(0),
1943 .ngpio = S5PV210_GPIO_F2_NR,
1944 .label = "GPF2",
1945 },
1946 }, {
1947 .chip = {
1948 .base = S5PV210_GPF3(0),
1949 .ngpio = S5PV210_GPIO_F3_NR,
1950 .label = "GPF3",
1951 },
1952 }, {
1953 .chip = {
1954 .base = S5PV210_GPG0(0),
1955 .ngpio = S5PV210_GPIO_G0_NR,
1956 .label = "GPG0",
1957 },
1958 }, {
1959 .chip = {
1960 .base = S5PV210_GPG1(0),
1961 .ngpio = S5PV210_GPIO_G1_NR,
1962 .label = "GPG1",
1963 },
1964 }, {
1965 .chip = {
1966 .base = S5PV210_GPG2(0),
1967 .ngpio = S5PV210_GPIO_G2_NR,
1968 .label = "GPG2",
1969 },
1970 }, {
1971 .chip = {
1972 .base = S5PV210_GPG3(0),
1973 .ngpio = S5PV210_GPIO_G3_NR,
1974 .label = "GPG3",
1975 },
1976 }, {
1977 .chip = {
1978 .base = S5PV210_GPI(0),
1979 .ngpio = S5PV210_GPIO_I_NR,
1980 .label = "GPI",
1981 },
1982 }, {
1983 .chip = {
1984 .base = S5PV210_GPJ0(0),
1985 .ngpio = S5PV210_GPIO_J0_NR,
1986 .label = "GPJ0",
1987 },
1988 }, {
1989 .chip = {
1990 .base = S5PV210_GPJ1(0),
1991 .ngpio = S5PV210_GPIO_J1_NR,
1992 .label = "GPJ1",
1993 },
1994 }, {
1995 .chip = {
1996 .base = S5PV210_GPJ2(0),
1997 .ngpio = S5PV210_GPIO_J2_NR,
1998 .label = "GPJ2",
1999 },
2000 }, {
2001 .chip = {
2002 .base = S5PV210_GPJ3(0),
2003 .ngpio = S5PV210_GPIO_J3_NR,
2004 .label = "GPJ3",
2005 },
2006 }, {
2007 .chip = {
2008 .base = S5PV210_GPJ4(0),
2009 .ngpio = S5PV210_GPIO_J4_NR,
2010 .label = "GPJ4",
2011 },
2012 }, {
2013 .chip = {
2014 .base = S5PV210_MP01(0),
2015 .ngpio = S5PV210_GPIO_MP01_NR,
2016 .label = "MP01",
2017 },
2018 }, {
2019 .chip = {
2020 .base = S5PV210_MP02(0),
2021 .ngpio = S5PV210_GPIO_MP02_NR,
2022 .label = "MP02",
2023 },
2024 }, {
2025 .chip = {
2026 .base = S5PV210_MP03(0),
2027 .ngpio = S5PV210_GPIO_MP03_NR,
2028 .label = "MP03",
2029 },
2030 }, {
2031 .chip = {
2032 .base = S5PV210_MP04(0),
2033 .ngpio = S5PV210_GPIO_MP04_NR,
2034 .label = "MP04",
2035 },
2036 }, {
2037 .chip = {
2038 .base = S5PV210_MP05(0),
2039 .ngpio = S5PV210_GPIO_MP05_NR,
2040 .label = "MP05",
2041 },
2042 }, {
2043 .base = (S5P_VA_GPIO + 0xC00),
2044 .irq_base = IRQ_EINT(0),
2045 .chip = {
2046 .base = S5PV210_GPH0(0),
2047 .ngpio = S5PV210_GPIO_H0_NR,
2048 .label = "GPH0",
2049 .to_irq = samsung_gpiolib_to_irq,
2050 },
2051 }, {
2052 .base = (S5P_VA_GPIO + 0xC20),
2053 .irq_base = IRQ_EINT(8),
2054 .chip = {
2055 .base = S5PV210_GPH1(0),
2056 .ngpio = S5PV210_GPIO_H1_NR,
2057 .label = "GPH1",
2058 .to_irq = samsung_gpiolib_to_irq,
2059 },
2060 }, {
2061 .base = (S5P_VA_GPIO + 0xC40),
2062 .irq_base = IRQ_EINT(16),
2063 .chip = {
2064 .base = S5PV210_GPH2(0),
2065 .ngpio = S5PV210_GPIO_H2_NR,
2066 .label = "GPH2",
2067 .to_irq = samsung_gpiolib_to_irq,
2068 },
2069 }, {
2070 .base = (S5P_VA_GPIO + 0xC60),
2071 .irq_base = IRQ_EINT(24),
2072 .chip = {
2073 .base = S5PV210_GPH3(0),
2074 .ngpio = S5PV210_GPIO_H3_NR,
2075 .label = "GPH3",
2076 .to_irq = samsung_gpiolib_to_irq,
2077 },
2078 },
2079#endif
2080};
2081
2082/*
2083 * Followings are the gpio banks in EXYNOS4210
2084 *
2085 * The 'config' member when left to NULL, is initialized to the default
2086 * structure samsung_gpio_cfgs[3] in the init function below.
2087 *
2088 * The 'base' member is also initialized in the init function below.
2089 * Note: The initialization of 'base' member of samsung_gpio_chip structure
2090 * uses the above macro and depends on the banks being listed in order here.
2091 */
2092
2093static struct samsung_gpio_chip exynos4_gpios_1[] = {
2094#ifdef CONFIG_ARCH_EXYNOS4
2095 {
2096 .chip = {
2097 .base = EXYNOS4_GPA0(0),
2098 .ngpio = EXYNOS4_GPIO_A0_NR,
2099 .label = "GPA0",
2100 },
2101 }, {
2102 .chip = {
2103 .base = EXYNOS4_GPA1(0),
2104 .ngpio = EXYNOS4_GPIO_A1_NR,
2105 .label = "GPA1",
2106 },
2107 }, {
2108 .chip = {
2109 .base = EXYNOS4_GPB(0),
2110 .ngpio = EXYNOS4_GPIO_B_NR,
2111 .label = "GPB",
2112 },
2113 }, {
2114 .chip = {
2115 .base = EXYNOS4_GPC0(0),
2116 .ngpio = EXYNOS4_GPIO_C0_NR,
2117 .label = "GPC0",
2118 },
2119 }, {
2120 .chip = {
2121 .base = EXYNOS4_GPC1(0),
2122 .ngpio = EXYNOS4_GPIO_C1_NR,
2123 .label = "GPC1",
2124 },
2125 }, {
2126 .chip = {
2127 .base = EXYNOS4_GPD0(0),
2128 .ngpio = EXYNOS4_GPIO_D0_NR,
2129 .label = "GPD0",
2130 },
2131 }, {
2132 .chip = {
2133 .base = EXYNOS4_GPD1(0),
2134 .ngpio = EXYNOS4_GPIO_D1_NR,
2135 .label = "GPD1",
2136 },
2137 }, {
2138 .chip = {
2139 .base = EXYNOS4_GPE0(0),
2140 .ngpio = EXYNOS4_GPIO_E0_NR,
2141 .label = "GPE0",
2142 },
2143 }, {
2144 .chip = {
2145 .base = EXYNOS4_GPE1(0),
2146 .ngpio = EXYNOS4_GPIO_E1_NR,
2147 .label = "GPE1",
2148 },
2149 }, {
2150 .chip = {
2151 .base = EXYNOS4_GPE2(0),
2152 .ngpio = EXYNOS4_GPIO_E2_NR,
2153 .label = "GPE2",
2154 },
2155 }, {
2156 .chip = {
2157 .base = EXYNOS4_GPE3(0),
2158 .ngpio = EXYNOS4_GPIO_E3_NR,
2159 .label = "GPE3",
2160 },
2161 }, {
2162 .chip = {
2163 .base = EXYNOS4_GPE4(0),
2164 .ngpio = EXYNOS4_GPIO_E4_NR,
2165 .label = "GPE4",
2166 },
2167 }, {
2168 .chip = {
2169 .base = EXYNOS4_GPF0(0),
2170 .ngpio = EXYNOS4_GPIO_F0_NR,
2171 .label = "GPF0",
2172 },
2173 }, {
2174 .chip = {
2175 .base = EXYNOS4_GPF1(0),
2176 .ngpio = EXYNOS4_GPIO_F1_NR,
2177 .label = "GPF1",
2178 },
2179 }, {
2180 .chip = {
2181 .base = EXYNOS4_GPF2(0),
2182 .ngpio = EXYNOS4_GPIO_F2_NR,
2183 .label = "GPF2",
2184 },
2185 }, {
2186 .chip = {
2187 .base = EXYNOS4_GPF3(0),
2188 .ngpio = EXYNOS4_GPIO_F3_NR,
2189 .label = "GPF3",
2190 },
2191 },
2192#endif
2193};
2194
2195static struct samsung_gpio_chip exynos4_gpios_2[] = {
2196#ifdef CONFIG_ARCH_EXYNOS4
2197 {
2198 .chip = {
2199 .base = EXYNOS4_GPJ0(0),
2200 .ngpio = EXYNOS4_GPIO_J0_NR,
2201 .label = "GPJ0",
2202 },
2203 }, {
2204 .chip = {
2205 .base = EXYNOS4_GPJ1(0),
2206 .ngpio = EXYNOS4_GPIO_J1_NR,
2207 .label = "GPJ1",
2208 },
2209 }, {
2210 .chip = {
2211 .base = EXYNOS4_GPK0(0),
2212 .ngpio = EXYNOS4_GPIO_K0_NR,
2213 .label = "GPK0",
2214 },
2215 }, {
2216 .chip = {
2217 .base = EXYNOS4_GPK1(0),
2218 .ngpio = EXYNOS4_GPIO_K1_NR,
2219 .label = "GPK1",
2220 },
2221 }, {
2222 .chip = {
2223 .base = EXYNOS4_GPK2(0),
2224 .ngpio = EXYNOS4_GPIO_K2_NR,
2225 .label = "GPK2",
2226 },
2227 }, {
2228 .chip = {
2229 .base = EXYNOS4_GPK3(0),
2230 .ngpio = EXYNOS4_GPIO_K3_NR,
2231 .label = "GPK3",
2232 },
2233 }, {
2234 .chip = {
2235 .base = EXYNOS4_GPL0(0),
2236 .ngpio = EXYNOS4_GPIO_L0_NR,
2237 .label = "GPL0",
2238 },
2239 }, {
2240 .chip = {
2241 .base = EXYNOS4_GPL1(0),
2242 .ngpio = EXYNOS4_GPIO_L1_NR,
2243 .label = "GPL1",
2244 },
2245 }, {
2246 .chip = {
2247 .base = EXYNOS4_GPL2(0),
2248 .ngpio = EXYNOS4_GPIO_L2_NR,
2249 .label = "GPL2",
2250 },
2251 }, {
2252 .config = &samsung_gpio_cfgs[0],
2253 .chip = {
2254 .base = EXYNOS4_GPY0(0),
2255 .ngpio = EXYNOS4_GPIO_Y0_NR,
2256 .label = "GPY0",
2257 },
2258 }, {
2259 .config = &samsung_gpio_cfgs[0],
2260 .chip = {
2261 .base = EXYNOS4_GPY1(0),
2262 .ngpio = EXYNOS4_GPIO_Y1_NR,
2263 .label = "GPY1",
2264 },
2265 }, {
2266 .config = &samsung_gpio_cfgs[0],
2267 .chip = {
2268 .base = EXYNOS4_GPY2(0),
2269 .ngpio = EXYNOS4_GPIO_Y2_NR,
2270 .label = "GPY2",
2271 },
2272 }, {
2273 .config = &samsung_gpio_cfgs[0],
2274 .chip = {
2275 .base = EXYNOS4_GPY3(0),
2276 .ngpio = EXYNOS4_GPIO_Y3_NR,
2277 .label = "GPY3",
2278 },
2279 }, {
2280 .config = &samsung_gpio_cfgs[0],
2281 .chip = {
2282 .base = EXYNOS4_GPY4(0),
2283 .ngpio = EXYNOS4_GPIO_Y4_NR,
2284 .label = "GPY4",
2285 },
2286 }, {
2287 .config = &samsung_gpio_cfgs[0],
2288 .chip = {
2289 .base = EXYNOS4_GPY5(0),
2290 .ngpio = EXYNOS4_GPIO_Y5_NR,
2291 .label = "GPY5",
2292 },
2293 }, {
2294 .config = &samsung_gpio_cfgs[0],
2295 .chip = {
2296 .base = EXYNOS4_GPY6(0),
2297 .ngpio = EXYNOS4_GPIO_Y6_NR,
2298 .label = "GPY6",
2299 },
2300 }, {
2301 .base = (S5P_VA_GPIO2 + 0xC00),
2302 .config = &samsung_gpio_cfgs[3],
2303 .irq_base = IRQ_EINT(0),
2304 .chip = {
2305 .base = EXYNOS4_GPX0(0),
2306 .ngpio = EXYNOS4_GPIO_X0_NR,
2307 .label = "GPX0",
2308 .to_irq = samsung_gpiolib_to_irq,
2309 },
2310 }, {
2311 .base = (S5P_VA_GPIO2 + 0xC20),
2312 .config = &samsung_gpio_cfgs[3],
2313 .irq_base = IRQ_EINT(8),
2314 .chip = {
2315 .base = EXYNOS4_GPX1(0),
2316 .ngpio = EXYNOS4_GPIO_X1_NR,
2317 .label = "GPX1",
2318 .to_irq = samsung_gpiolib_to_irq,
2319 },
2320 }, {
2321 .base = (S5P_VA_GPIO2 + 0xC40),
2322 .config = &samsung_gpio_cfgs[3],
2323 .irq_base = IRQ_EINT(16),
2324 .chip = {
2325 .base = EXYNOS4_GPX2(0),
2326 .ngpio = EXYNOS4_GPIO_X2_NR,
2327 .label = "GPX2",
2328 .to_irq = samsung_gpiolib_to_irq,
2329 },
2330 }, {
2331 .base = (S5P_VA_GPIO2 + 0xC60),
2332 .config = &samsung_gpio_cfgs[3],
2333 .irq_base = IRQ_EINT(24),
2334 .chip = {
2335 .base = EXYNOS4_GPX3(0),
2336 .ngpio = EXYNOS4_GPIO_X3_NR,
2337 .label = "GPX3",
2338 .to_irq = samsung_gpiolib_to_irq,
2339 },
2340 },
2341#endif
2342};
2343
2344static struct samsung_gpio_chip exynos4_gpios_3[] = {
2345#ifdef CONFIG_ARCH_EXYNOS4
2346 {
2347 .chip = {
2348 .base = EXYNOS4_GPZ(0),
2349 .ngpio = EXYNOS4_GPIO_Z_NR,
2350 .label = "GPZ",
2351 },
2352 },
2353#endif
2354};
2355
2356/* TODO: cleanup soc_is_* */
2357static __init int samsung_gpiolib_init(void)
2358{
2359 struct samsung_gpio_chip *chip;
2360 int i, nr_chips;
2361 int group = 0;
2362
2363 samsung_gpiolib_set_cfg(samsung_gpio_cfgs, ARRAY_SIZE(samsung_gpio_cfgs));
2364
2365 if (soc_is_s3c24xx()) {
2366 s3c24xx_gpiolib_add_chips(s3c24xx_gpios,
2367 ARRAY_SIZE(s3c24xx_gpios), S3C24XX_VA_GPIO);
2368 } else if (soc_is_s3c64xx()) {
2369 samsung_gpiolib_add_2bit_chips(s3c64xx_gpios_2bit,
2370 ARRAY_SIZE(s3c64xx_gpios_2bit),
2371 S3C64XX_VA_GPIO + 0xE0, 0x20);
2372 samsung_gpiolib_add_4bit_chips(s3c64xx_gpios_4bit,
2373 ARRAY_SIZE(s3c64xx_gpios_4bit),
2374 S3C64XX_VA_GPIO);
2375 samsung_gpiolib_add_4bit2_chips(s3c64xx_gpios_4bit2,
2376 ARRAY_SIZE(s3c64xx_gpios_4bit2));
2377 } else if (soc_is_s5p6440()) {
2378 samsung_gpiolib_add_2bit_chips(s5p6440_gpios_2bit,
2379 ARRAY_SIZE(s5p6440_gpios_2bit), NULL, 0x0);
2380 samsung_gpiolib_add_4bit_chips(s5p6440_gpios_4bit,
2381 ARRAY_SIZE(s5p6440_gpios_4bit), S5P_VA_GPIO);
2382 samsung_gpiolib_add_4bit2_chips(s5p6440_gpios_4bit2,
2383 ARRAY_SIZE(s5p6440_gpios_4bit2));
2384 s5p64x0_gpiolib_add_rbank(s5p6440_gpios_rbank,
2385 ARRAY_SIZE(s5p6440_gpios_rbank));
2386 } else if (soc_is_s5p6450()) {
2387 samsung_gpiolib_add_2bit_chips(s5p6450_gpios_2bit,
2388 ARRAY_SIZE(s5p6450_gpios_2bit), NULL, 0x0);
2389 samsung_gpiolib_add_4bit_chips(s5p6450_gpios_4bit,
2390 ARRAY_SIZE(s5p6450_gpios_4bit), S5P_VA_GPIO);
2391 samsung_gpiolib_add_4bit2_chips(s5p6450_gpios_4bit2,
2392 ARRAY_SIZE(s5p6450_gpios_4bit2));
2393 s5p64x0_gpiolib_add_rbank(s5p6450_gpios_rbank,
2394 ARRAY_SIZE(s5p6450_gpios_rbank));
2395 } else if (soc_is_s5pc100()) {
2396 group = 0;
2397 chip = s5pc100_gpios_4bit;
2398 nr_chips = ARRAY_SIZE(s5pc100_gpios_4bit);
2399
2400 for (i = 0; i < nr_chips; i++, chip++) {
2401 if (!chip->config) {
2402 chip->config = &samsung_gpio_cfgs[3];
2403 chip->group = group++;
2404 }
2405 }
2406 samsung_gpiolib_add_4bit_chips(s5pc100_gpios_4bit, nr_chips, S5P_VA_GPIO);
2407#if defined(CONFIG_CPU_S5PC100) && defined(CONFIG_S5P_GPIO_INT)
2408 s5p_register_gpioint_bank(IRQ_GPIOINT, 0, S5P_GPIOINT_GROUP_MAXNR);
2409#endif
2410 } else if (soc_is_s5pv210()) {
2411 group = 0;
2412 chip = s5pv210_gpios_4bit;
2413 nr_chips = ARRAY_SIZE(s5pv210_gpios_4bit);
2414
2415 for (i = 0; i < nr_chips; i++, chip++) {
2416 if (!chip->config) {
2417 chip->config = &samsung_gpio_cfgs[3];
2418 chip->group = group++;
2419 }
2420 }
2421 samsung_gpiolib_add_4bit_chips(s5pv210_gpios_4bit, nr_chips, S5P_VA_GPIO);
2422#if defined(CONFIG_CPU_S5PV210) && defined(CONFIG_S5P_GPIO_INT)
2423 s5p_register_gpioint_bank(IRQ_GPIOINT, 0, S5P_GPIOINT_GROUP_MAXNR);
2424#endif
2425 } else if (soc_is_exynos4210()) {
2426 group = 0;
2427
2428 /* gpio part1 */
2429 chip = exynos4_gpios_1;
2430 nr_chips = ARRAY_SIZE(exynos4_gpios_1);
2431
2432 for (i = 0; i < nr_chips; i++, chip++) {
2433 if (!chip->config) {
2434 chip->config = &exynos4_gpio_cfg;
2435 chip->group = group++;
2436 }
2437 }
2438 samsung_gpiolib_add_4bit_chips(exynos4_gpios_1, nr_chips, S5P_VA_GPIO1);
2439
2440 /* gpio part2 */
2441 chip = exynos4_gpios_2;
2442 nr_chips = ARRAY_SIZE(exynos4_gpios_2);
2443
2444 for (i = 0; i < nr_chips; i++, chip++) {
2445 if (!chip->config) {
2446 chip->config = &exynos4_gpio_cfg;
2447 chip->group = group++;
2448 }
2449 }
2450 samsung_gpiolib_add_4bit_chips(exynos4_gpios_2, nr_chips, S5P_VA_GPIO2);
2451
2452 /* gpio part3 */
2453 chip = exynos4_gpios_3;
2454 nr_chips = ARRAY_SIZE(exynos4_gpios_3);
2455
2456 for (i = 0; i < nr_chips; i++, chip++) {
2457 if (!chip->config) {
2458 chip->config = &exynos4_gpio_cfg;
2459 chip->group = group++;
2460 }
2461 }
2462 samsung_gpiolib_add_4bit_chips(exynos4_gpios_3, nr_chips, S5P_VA_GPIO3);
2463
2464#if defined(CONFIG_CPU_EXYNOS4210) && defined(CONFIG_S5P_GPIO_INT)
2465 s5p_register_gpioint_bank(IRQ_GPIO_XA, 0, IRQ_GPIO1_NR_GROUPS);
2466 s5p_register_gpioint_bank(IRQ_GPIO_XB, IRQ_GPIO1_NR_GROUPS, IRQ_GPIO2_NR_GROUPS);
2467#endif
2468 }
2469
2470 return 0;
2471}
2472core_initcall(samsung_gpiolib_init);
2473
2474int s3c_gpio_cfgpin(unsigned int pin, unsigned int config)
2475{
2476 struct samsung_gpio_chip *chip = samsung_gpiolib_getchip(pin);
2477 unsigned long flags;
2478 int offset;
2479 int ret;
2480
2481 if (!chip)
2482 return -EINVAL;
2483
2484 offset = pin - chip->chip.base;
2485
2486 samsung_gpio_lock(chip, flags);
2487 ret = samsung_gpio_do_setcfg(chip, offset, config);
2488 samsung_gpio_unlock(chip, flags);
2489
2490 return ret;
2491}
2492EXPORT_SYMBOL(s3c_gpio_cfgpin);
2493
2494int s3c_gpio_cfgpin_range(unsigned int start, unsigned int nr,
2495 unsigned int cfg)
2496{
2497 int ret;
2498
2499 for (; nr > 0; nr--, start++) {
2500 ret = s3c_gpio_cfgpin(start, cfg);
2501 if (ret != 0)
2502 return ret;
2503 }
2504
2505 return 0;
2506}
2507EXPORT_SYMBOL_GPL(s3c_gpio_cfgpin_range);
2508
2509int s3c_gpio_cfgall_range(unsigned int start, unsigned int nr,
2510 unsigned int cfg, samsung_gpio_pull_t pull)
2511{
2512 int ret;
2513
2514 for (; nr > 0; nr--, start++) {
2515 s3c_gpio_setpull(start, pull);
2516 ret = s3c_gpio_cfgpin(start, cfg);
2517 if (ret != 0)
2518 return ret;
2519 }
2520
2521 return 0;
2522}
2523EXPORT_SYMBOL_GPL(s3c_gpio_cfgall_range);
2524
2525unsigned s3c_gpio_getcfg(unsigned int pin)
2526{
2527 struct samsung_gpio_chip *chip = samsung_gpiolib_getchip(pin);
2528 unsigned long flags;
2529 unsigned ret = 0;
2530 int offset;
2531
2532 if (chip) {
2533 offset = pin - chip->chip.base;
2534
2535 samsung_gpio_lock(chip, flags);
2536 ret = samsung_gpio_do_getcfg(chip, offset);
2537 samsung_gpio_unlock(chip, flags);
2538 }
2539
2540 return ret;
2541}
2542EXPORT_SYMBOL(s3c_gpio_getcfg);
2543
2544int s3c_gpio_setpull(unsigned int pin, samsung_gpio_pull_t pull)
2545{
2546 struct samsung_gpio_chip *chip = samsung_gpiolib_getchip(pin);
2547 unsigned long flags;
2548 int offset, ret;
2549
2550 if (!chip)
2551 return -EINVAL;
2552
2553 offset = pin - chip->chip.base;
2554
2555 samsung_gpio_lock(chip, flags);
2556 ret = samsung_gpio_do_setpull(chip, offset, pull);
2557 samsung_gpio_unlock(chip, flags);
2558
2559 return ret;
2560}
2561EXPORT_SYMBOL(s3c_gpio_setpull);
2562
2563samsung_gpio_pull_t s3c_gpio_getpull(unsigned int pin)
2564{
2565 struct samsung_gpio_chip *chip = samsung_gpiolib_getchip(pin);
2566 unsigned long flags;
2567 int offset;
2568 u32 pup = 0;
2569
2570 if (chip) {
2571 offset = pin - chip->chip.base;
2572
2573 samsung_gpio_lock(chip, flags);
2574 pup = samsung_gpio_do_getpull(chip, offset);
2575 samsung_gpio_unlock(chip, flags);
2576 }
2577
2578 return (__force samsung_gpio_pull_t)pup;
2579}
2580EXPORT_SYMBOL(s3c_gpio_getpull);
2581
2582/* gpiolib wrappers until these are totally eliminated */
2583
2584void s3c2410_gpio_pullup(unsigned int pin, unsigned int to)
2585{
2586 int ret;
2587
2588 WARN_ON(to); /* should be none of these left */
2589
2590 if (!to) {
2591 /* if pull is enabled, try first with up, and if that
2592 * fails, try using down */
2593
2594 ret = s3c_gpio_setpull(pin, S3C_GPIO_PULL_UP);
2595 if (ret)
2596 s3c_gpio_setpull(pin, S3C_GPIO_PULL_DOWN);
2597 } else {
2598 s3c_gpio_setpull(pin, S3C_GPIO_PULL_NONE);
2599 }
2600}
2601EXPORT_SYMBOL(s3c2410_gpio_pullup);
2602
2603void s3c2410_gpio_setpin(unsigned int pin, unsigned int to)
2604{
2605 /* do this via gpiolib until all users removed */
2606
2607 gpio_request(pin, "temporary");
2608 gpio_set_value(pin, to);
2609 gpio_free(pin);
2610}
2611EXPORT_SYMBOL(s3c2410_gpio_setpin);
2612
2613unsigned int s3c2410_gpio_getpin(unsigned int pin)
2614{
2615 struct samsung_gpio_chip *chip = samsung_gpiolib_getchip(pin);
2616 unsigned long offs = pin - chip->chip.base;
2617
2618 return __raw_readl(chip->base + 0x04) & (1 << offs);
2619}
2620EXPORT_SYMBOL(s3c2410_gpio_getpin);
2621
2622#ifdef CONFIG_S5P_GPIO_DRVSTR
2623s5p_gpio_drvstr_t s5p_gpio_get_drvstr(unsigned int pin)
2624{
2625 struct samsung_gpio_chip *chip = samsung_gpiolib_getchip(pin);
2626 unsigned int off;
2627 void __iomem *reg;
2628 int shift;
2629 u32 drvstr;
2630
2631 if (!chip)
2632 return -EINVAL;
2633
2634 off = pin - chip->chip.base;
2635 shift = off * 2;
2636 reg = chip->base + 0x0C;
2637
2638 drvstr = __raw_readl(reg);
2639 drvstr = drvstr >> shift;
2640 drvstr &= 0x3;
2641
2642 return (__force s5p_gpio_drvstr_t)drvstr;
2643}
2644EXPORT_SYMBOL(s5p_gpio_get_drvstr);
2645
2646int s5p_gpio_set_drvstr(unsigned int pin, s5p_gpio_drvstr_t drvstr)
2647{
2648 struct samsung_gpio_chip *chip = samsung_gpiolib_getchip(pin);
2649 unsigned int off;
2650 void __iomem *reg;
2651 int shift;
2652 u32 tmp;
2653
2654 if (!chip)
2655 return -EINVAL;
2656
2657 off = pin - chip->chip.base;
2658 shift = off * 2;
2659 reg = chip->base + 0x0C;
2660
2661 tmp = __raw_readl(reg);
2662 tmp &= ~(0x3 << shift);
2663 tmp |= drvstr << shift;
2664
2665 __raw_writel(tmp, reg);
2666
2667 return 0;
2668}
2669EXPORT_SYMBOL(s5p_gpio_set_drvstr);
2670#endif /* CONFIG_S5P_GPIO_DRVSTR */
2671
2672#ifdef CONFIG_PLAT_S3C24XX
2673unsigned int s3c2410_modify_misccr(unsigned int clear, unsigned int change)
2674{
2675 unsigned long flags;
2676 unsigned long misccr;
2677
2678 local_irq_save(flags);
2679 misccr = __raw_readl(S3C24XX_MISCCR);
2680 misccr &= ~clear;
2681 misccr ^= change;
2682 __raw_writel(misccr, S3C24XX_MISCCR);
2683 local_irq_restore(flags);
2684
2685 return misccr;
2686}
2687EXPORT_SYMBOL(s3c2410_modify_misccr);
2688#endif
diff --git a/drivers/mmc/host/s3cmci.c b/drivers/mmc/host/s3cmci.c
index a04f87d7ee3d..03cfdab99c8f 100644
--- a/drivers/mmc/host/s3cmci.c
+++ b/drivers/mmc/host/s3cmci.c
@@ -913,9 +913,9 @@ request_done:
913} 913}
914 914
915static void s3cmci_dma_setup(struct s3cmci_host *host, 915static void s3cmci_dma_setup(struct s3cmci_host *host,
916 enum s3c2410_dmasrc source) 916 enum dma_data_direction source)
917{ 917{
918 static enum s3c2410_dmasrc last_source = -1; 918 static enum dma_data_direction last_source = -1;
919 static int setup_ok; 919 static int setup_ok;
920 920
921 if (last_source == source) 921 if (last_source == source)
@@ -1087,7 +1087,7 @@ static int s3cmci_prepare_dma(struct s3cmci_host *host, struct mmc_data *data)
1087 1087
1088 BUG_ON((data->flags & BOTH_DIR) == BOTH_DIR); 1088 BUG_ON((data->flags & BOTH_DIR) == BOTH_DIR);
1089 1089
1090 s3cmci_dma_setup(host, rw ? S3C2410_DMASRC_MEM : S3C2410_DMASRC_HW); 1090 s3cmci_dma_setup(host, rw ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
1091 s3c2410_dma_ctrl(host->dma, S3C2410_DMAOP_FLUSH); 1091 s3c2410_dma_ctrl(host->dma, S3C2410_DMAOP_FLUSH);
1092 1092
1093 dma_len = dma_map_sg(mmc_dev(host->mmc), data->sg, data->sg_len, 1093 dma_len = dma_map_sg(mmc_dev(host->mmc), data->sg, data->sg_len,
diff --git a/drivers/spi/spi-s3c64xx.c b/drivers/spi/spi-s3c64xx.c
index 595dacc7645f..019a7163572f 100644
--- a/drivers/spi/spi-s3c64xx.c
+++ b/drivers/spi/spi-s3c64xx.c
@@ -131,6 +131,12 @@
131#define RXBUSY (1<<2) 131#define RXBUSY (1<<2)
132#define TXBUSY (1<<3) 132#define TXBUSY (1<<3)
133 133
134struct s3c64xx_spi_dma_data {
135 unsigned ch;
136 enum dma_data_direction direction;
137 enum dma_ch dmach;
138};
139
134/** 140/**
135 * struct s3c64xx_spi_driver_data - Runtime info holder for SPI driver. 141 * struct s3c64xx_spi_driver_data - Runtime info holder for SPI driver.
136 * @clk: Pointer to the spi clock. 142 * @clk: Pointer to the spi clock.
@@ -164,13 +170,14 @@ struct s3c64xx_spi_driver_data {
164 struct work_struct work; 170 struct work_struct work;
165 struct list_head queue; 171 struct list_head queue;
166 spinlock_t lock; 172 spinlock_t lock;
167 enum dma_ch rx_dmach;
168 enum dma_ch tx_dmach;
169 unsigned long sfr_start; 173 unsigned long sfr_start;
170 struct completion xfer_completion; 174 struct completion xfer_completion;
171 unsigned state; 175 unsigned state;
172 unsigned cur_mode, cur_bpw; 176 unsigned cur_mode, cur_bpw;
173 unsigned cur_speed; 177 unsigned cur_speed;
178 struct s3c64xx_spi_dma_data rx_dma;
179 struct s3c64xx_spi_dma_data tx_dma;
180 struct samsung_dma_ops *ops;
174}; 181};
175 182
176static struct s3c2410_dma_client s3c64xx_spi_dma_client = { 183static struct s3c2410_dma_client s3c64xx_spi_dma_client = {
@@ -226,6 +233,78 @@ static void flush_fifo(struct s3c64xx_spi_driver_data *sdd)
226 writel(val, regs + S3C64XX_SPI_CH_CFG); 233 writel(val, regs + S3C64XX_SPI_CH_CFG);
227} 234}
228 235
236static void s3c64xx_spi_dmacb(void *data)
237{
238 struct s3c64xx_spi_driver_data *sdd;
239 struct s3c64xx_spi_dma_data *dma = data;
240 unsigned long flags;
241
242 if (dma->direction == DMA_FROM_DEVICE)
243 sdd = container_of(data,
244 struct s3c64xx_spi_driver_data, rx_dma);
245 else
246 sdd = container_of(data,
247 struct s3c64xx_spi_driver_data, tx_dma);
248
249 spin_lock_irqsave(&sdd->lock, flags);
250
251 if (dma->direction == DMA_FROM_DEVICE) {
252 sdd->state &= ~RXBUSY;
253 if (!(sdd->state & TXBUSY))
254 complete(&sdd->xfer_completion);
255 } else {
256 sdd->state &= ~TXBUSY;
257 if (!(sdd->state & RXBUSY))
258 complete(&sdd->xfer_completion);
259 }
260
261 spin_unlock_irqrestore(&sdd->lock, flags);
262}
263
264static void prepare_dma(struct s3c64xx_spi_dma_data *dma,
265 unsigned len, dma_addr_t buf)
266{
267 struct s3c64xx_spi_driver_data *sdd;
268 struct samsung_dma_prep_info info;
269
270 if (dma->direction == DMA_FROM_DEVICE)
271 sdd = container_of((void *)dma,
272 struct s3c64xx_spi_driver_data, rx_dma);
273 else
274 sdd = container_of((void *)dma,
275 struct s3c64xx_spi_driver_data, tx_dma);
276
277 info.cap = DMA_SLAVE;
278 info.len = len;
279 info.fp = s3c64xx_spi_dmacb;
280 info.fp_param = dma;
281 info.direction = dma->direction;
282 info.buf = buf;
283
284 sdd->ops->prepare(dma->ch, &info);
285 sdd->ops->trigger(dma->ch);
286}
287
288static int acquire_dma(struct s3c64xx_spi_driver_data *sdd)
289{
290 struct samsung_dma_info info;
291
292 sdd->ops = samsung_dma_get_ops();
293
294 info.cap = DMA_SLAVE;
295 info.client = &s3c64xx_spi_dma_client;
296 info.width = sdd->cur_bpw / 8;
297
298 info.direction = sdd->rx_dma.direction;
299 info.fifo = sdd->sfr_start + S3C64XX_SPI_RX_DATA;
300 sdd->rx_dma.ch = sdd->ops->request(sdd->rx_dma.dmach, &info);
301 info.direction = sdd->tx_dma.direction;
302 info.fifo = sdd->sfr_start + S3C64XX_SPI_TX_DATA;
303 sdd->tx_dma.ch = sdd->ops->request(sdd->tx_dma.dmach, &info);
304
305 return 1;
306}
307
229static void enable_datapath(struct s3c64xx_spi_driver_data *sdd, 308static void enable_datapath(struct s3c64xx_spi_driver_data *sdd,
230 struct spi_device *spi, 309 struct spi_device *spi,
231 struct spi_transfer *xfer, int dma_mode) 310 struct spi_transfer *xfer, int dma_mode)
@@ -258,10 +337,7 @@ static void enable_datapath(struct s3c64xx_spi_driver_data *sdd,
258 chcfg |= S3C64XX_SPI_CH_TXCH_ON; 337 chcfg |= S3C64XX_SPI_CH_TXCH_ON;
259 if (dma_mode) { 338 if (dma_mode) {
260 modecfg |= S3C64XX_SPI_MODE_TXDMA_ON; 339 modecfg |= S3C64XX_SPI_MODE_TXDMA_ON;
261 s3c2410_dma_config(sdd->tx_dmach, sdd->cur_bpw / 8); 340 prepare_dma(&sdd->tx_dma, xfer->len, xfer->tx_dma);
262 s3c2410_dma_enqueue(sdd->tx_dmach, (void *)sdd,
263 xfer->tx_dma, xfer->len);
264 s3c2410_dma_ctrl(sdd->tx_dmach, S3C2410_DMAOP_START);
265 } else { 341 } else {
266 switch (sdd->cur_bpw) { 342 switch (sdd->cur_bpw) {
267 case 32: 343 case 32:
@@ -293,10 +369,7 @@ static void enable_datapath(struct s3c64xx_spi_driver_data *sdd,
293 writel(((xfer->len * 8 / sdd->cur_bpw) & 0xffff) 369 writel(((xfer->len * 8 / sdd->cur_bpw) & 0xffff)
294 | S3C64XX_SPI_PACKET_CNT_EN, 370 | S3C64XX_SPI_PACKET_CNT_EN,
295 regs + S3C64XX_SPI_PACKET_CNT); 371 regs + S3C64XX_SPI_PACKET_CNT);
296 s3c2410_dma_config(sdd->rx_dmach, sdd->cur_bpw / 8); 372 prepare_dma(&sdd->rx_dma, xfer->len, xfer->rx_dma);
297 s3c2410_dma_enqueue(sdd->rx_dmach, (void *)sdd,
298 xfer->rx_dma, xfer->len);
299 s3c2410_dma_ctrl(sdd->rx_dmach, S3C2410_DMAOP_START);
300 } 373 }
301 } 374 }
302 375
@@ -482,46 +555,6 @@ static void s3c64xx_spi_config(struct s3c64xx_spi_driver_data *sdd)
482 } 555 }
483} 556}
484 557
485static void s3c64xx_spi_dma_rxcb(struct s3c2410_dma_chan *chan, void *buf_id,
486 int size, enum s3c2410_dma_buffresult res)
487{
488 struct s3c64xx_spi_driver_data *sdd = buf_id;
489 unsigned long flags;
490
491 spin_lock_irqsave(&sdd->lock, flags);
492
493 if (res == S3C2410_RES_OK)
494 sdd->state &= ~RXBUSY;
495 else
496 dev_err(&sdd->pdev->dev, "DmaAbrtRx-%d\n", size);
497
498 /* If the other done */
499 if (!(sdd->state & TXBUSY))
500 complete(&sdd->xfer_completion);
501
502 spin_unlock_irqrestore(&sdd->lock, flags);
503}
504
505static void s3c64xx_spi_dma_txcb(struct s3c2410_dma_chan *chan, void *buf_id,
506 int size, enum s3c2410_dma_buffresult res)
507{
508 struct s3c64xx_spi_driver_data *sdd = buf_id;
509 unsigned long flags;
510
511 spin_lock_irqsave(&sdd->lock, flags);
512
513 if (res == S3C2410_RES_OK)
514 sdd->state &= ~TXBUSY;
515 else
516 dev_err(&sdd->pdev->dev, "DmaAbrtTx-%d \n", size);
517
518 /* If the other done */
519 if (!(sdd->state & RXBUSY))
520 complete(&sdd->xfer_completion);
521
522 spin_unlock_irqrestore(&sdd->lock, flags);
523}
524
525#define XFER_DMAADDR_INVALID DMA_BIT_MASK(32) 558#define XFER_DMAADDR_INVALID DMA_BIT_MASK(32)
526 559
527static int s3c64xx_spi_map_mssg(struct s3c64xx_spi_driver_data *sdd, 560static int s3c64xx_spi_map_mssg(struct s3c64xx_spi_driver_data *sdd,
@@ -696,12 +729,10 @@ static void handle_msg(struct s3c64xx_spi_driver_data *sdd,
696 if (use_dma) { 729 if (use_dma) {
697 if (xfer->tx_buf != NULL 730 if (xfer->tx_buf != NULL
698 && (sdd->state & TXBUSY)) 731 && (sdd->state & TXBUSY))
699 s3c2410_dma_ctrl(sdd->tx_dmach, 732 sdd->ops->stop(sdd->tx_dma.ch);
700 S3C2410_DMAOP_FLUSH);
701 if (xfer->rx_buf != NULL 733 if (xfer->rx_buf != NULL
702 && (sdd->state & RXBUSY)) 734 && (sdd->state & RXBUSY))
703 s3c2410_dma_ctrl(sdd->rx_dmach, 735 sdd->ops->stop(sdd->rx_dma.ch);
704 S3C2410_DMAOP_FLUSH);
705 } 736 }
706 737
707 goto out; 738 goto out;
@@ -739,30 +770,6 @@ out:
739 msg->complete(msg->context); 770 msg->complete(msg->context);
740} 771}
741 772
742static int acquire_dma(struct s3c64xx_spi_driver_data *sdd)
743{
744 if (s3c2410_dma_request(sdd->rx_dmach,
745 &s3c64xx_spi_dma_client, NULL) < 0) {
746 dev_err(&sdd->pdev->dev, "cannot get RxDMA\n");
747 return 0;
748 }
749 s3c2410_dma_set_buffdone_fn(sdd->rx_dmach, s3c64xx_spi_dma_rxcb);
750 s3c2410_dma_devconfig(sdd->rx_dmach, S3C2410_DMASRC_HW,
751 sdd->sfr_start + S3C64XX_SPI_RX_DATA);
752
753 if (s3c2410_dma_request(sdd->tx_dmach,
754 &s3c64xx_spi_dma_client, NULL) < 0) {
755 dev_err(&sdd->pdev->dev, "cannot get TxDMA\n");
756 s3c2410_dma_free(sdd->rx_dmach, &s3c64xx_spi_dma_client);
757 return 0;
758 }
759 s3c2410_dma_set_buffdone_fn(sdd->tx_dmach, s3c64xx_spi_dma_txcb);
760 s3c2410_dma_devconfig(sdd->tx_dmach, S3C2410_DMASRC_MEM,
761 sdd->sfr_start + S3C64XX_SPI_TX_DATA);
762
763 return 1;
764}
765
766static void s3c64xx_spi_work(struct work_struct *work) 773static void s3c64xx_spi_work(struct work_struct *work)
767{ 774{
768 struct s3c64xx_spi_driver_data *sdd = container_of(work, 775 struct s3c64xx_spi_driver_data *sdd = container_of(work,
@@ -799,8 +806,8 @@ static void s3c64xx_spi_work(struct work_struct *work)
799 spin_unlock_irqrestore(&sdd->lock, flags); 806 spin_unlock_irqrestore(&sdd->lock, flags);
800 807
801 /* Free DMA channels */ 808 /* Free DMA channels */
802 s3c2410_dma_free(sdd->tx_dmach, &s3c64xx_spi_dma_client); 809 sdd->ops->release(sdd->rx_dma.ch, &s3c64xx_spi_dma_client);
803 s3c2410_dma_free(sdd->rx_dmach, &s3c64xx_spi_dma_client); 810 sdd->ops->release(sdd->tx_dma.ch, &s3c64xx_spi_dma_client);
804} 811}
805 812
806static int s3c64xx_spi_transfer(struct spi_device *spi, 813static int s3c64xx_spi_transfer(struct spi_device *spi,
@@ -1017,8 +1024,10 @@ static int __init s3c64xx_spi_probe(struct platform_device *pdev)
1017 sdd->cntrlr_info = sci; 1024 sdd->cntrlr_info = sci;
1018 sdd->pdev = pdev; 1025 sdd->pdev = pdev;
1019 sdd->sfr_start = mem_res->start; 1026 sdd->sfr_start = mem_res->start;
1020 sdd->tx_dmach = dmatx_res->start; 1027 sdd->tx_dma.dmach = dmatx_res->start;
1021 sdd->rx_dmach = dmarx_res->start; 1028 sdd->tx_dma.direction = DMA_TO_DEVICE;
1029 sdd->rx_dma.dmach = dmarx_res->start;
1030 sdd->rx_dma.direction = DMA_FROM_DEVICE;
1022 1031
1023 sdd->cur_bpw = 8; 1032 sdd->cur_bpw = 8;
1024 1033
@@ -1106,7 +1115,7 @@ static int __init s3c64xx_spi_probe(struct platform_device *pdev)
1106 pdev->id, master->num_chipselect); 1115 pdev->id, master->num_chipselect);
1107 dev_dbg(&pdev->dev, "\tIOmem=[0x%x-0x%x]\tDMA=[Rx-%d, Tx-%d]\n", 1116 dev_dbg(&pdev->dev, "\tIOmem=[0x%x-0x%x]\tDMA=[Rx-%d, Tx-%d]\n",
1108 mem_res->end, mem_res->start, 1117 mem_res->end, mem_res->start,
1109 sdd->rx_dmach, sdd->tx_dmach); 1118 sdd->rx_dma.dmach, sdd->tx_dma.dmach);
1110 1119
1111 return 0; 1120 return 0;
1112 1121
diff --git a/include/linux/amba/pl08x.h b/include/linux/amba/pl08x.h
index e6e28f37d8ec..a22662c93981 100644
--- a/include/linux/amba/pl08x.h
+++ b/include/linux/amba/pl08x.h
@@ -47,6 +47,9 @@ enum {
47 * @muxval: a number usually used to poke into some mux regiser to 47 * @muxval: a number usually used to poke into some mux regiser to
48 * mux in the signal to this channel 48 * mux in the signal to this channel
49 * @cctl_opt: default options for the channel control register 49 * @cctl_opt: default options for the channel control register
50 * @device_fc: Flow Controller Settings for ccfg register. Only valid for slave
51 * channels. Fill with 'true' if peripheral should be flow controller. Direction
52 * will be selected at Runtime.
50 * @addr: source/target address in physical memory for this DMA channel, 53 * @addr: source/target address in physical memory for this DMA channel,
51 * can be the address of a FIFO register for burst requests for example. 54 * can be the address of a FIFO register for burst requests for example.
52 * This can be left undefined if the PrimeCell API is used for configuring 55 * This can be left undefined if the PrimeCell API is used for configuring
@@ -65,6 +68,7 @@ struct pl08x_channel_data {
65 int max_signal; 68 int max_signal;
66 u32 muxval; 69 u32 muxval;
67 u32 cctl; 70 u32 cctl;
71 bool device_fc;
68 dma_addr_t addr; 72 dma_addr_t addr;
69 bool circular_buffer; 73 bool circular_buffer;
70 bool single; 74 bool single;
@@ -77,13 +81,11 @@ struct pl08x_channel_data {
77 * @addr: current address 81 * @addr: current address
78 * @maxwidth: the maximum width of a transfer on this bus 82 * @maxwidth: the maximum width of a transfer on this bus
79 * @buswidth: the width of this bus in bytes: 1, 2 or 4 83 * @buswidth: the width of this bus in bytes: 1, 2 or 4
80 * @fill_bytes: bytes required to fill to the next bus memory boundary
81 */ 84 */
82struct pl08x_bus_data { 85struct pl08x_bus_data {
83 dma_addr_t addr; 86 dma_addr_t addr;
84 u8 maxwidth; 87 u8 maxwidth;
85 u8 buswidth; 88 u8 buswidth;
86 size_t fill_bytes;
87}; 89};
88 90
89/** 91/**
@@ -105,8 +107,16 @@ struct pl08x_phy_chan {
105 107
106/** 108/**
107 * struct pl08x_txd - wrapper for struct dma_async_tx_descriptor 109 * struct pl08x_txd - wrapper for struct dma_async_tx_descriptor
110 * @tx: async tx descriptor
111 * @node: node for txd list for channels
112 * @src_addr: src address of txd
113 * @dst_addr: dst address of txd
114 * @len: transfer len in bytes
115 * @direction: direction of transfer
108 * @llis_bus: DMA memory address (physical) start for the LLIs 116 * @llis_bus: DMA memory address (physical) start for the LLIs
109 * @llis_va: virtual memory address start for the LLIs 117 * @llis_va: virtual memory address start for the LLIs
118 * @cctl: control reg values for current txd
119 * @ccfg: config reg values for current txd
110 */ 120 */
111struct pl08x_txd { 121struct pl08x_txd {
112 struct dma_async_tx_descriptor tx; 122 struct dma_async_tx_descriptor tx;
diff --git a/include/linux/amba/pl330.h b/include/linux/amba/pl330.h
index cbee7de7dd36..d12f077a6daf 100644
--- a/include/linux/amba/pl330.h
+++ b/include/linux/amba/pl330.h
@@ -19,12 +19,8 @@ struct dma_pl330_peri {
19 * Peri_Req i/f of the DMAC that is 19 * Peri_Req i/f of the DMAC that is
20 * peripheral could be reached from. 20 * peripheral could be reached from.
21 */ 21 */
22 u8 peri_id; /* {0, 31} */ 22 u8 peri_id; /* specific dma id */
23 enum pl330_reqtype rqtype; 23 enum pl330_reqtype rqtype;
24
25 /* For M->D and D->M Channels */
26 int burst_sz; /* in power of 2 */
27 dma_addr_t fifo_addr;
28}; 24};
29 25
30struct dma_pl330_platdata { 26struct dma_pl330_platdata {
diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h
index 8fbf40e0713c..ace51af4369f 100644
--- a/include/linux/dmaengine.h
+++ b/include/linux/dmaengine.h
@@ -24,8 +24,7 @@
24#include <linux/device.h> 24#include <linux/device.h>
25#include <linux/uio.h> 25#include <linux/uio.h>
26#include <linux/dma-direction.h> 26#include <linux/dma-direction.h>
27 27#include <linux/scatterlist.h>
28struct scatterlist;
29 28
30/** 29/**
31 * typedef dma_cookie_t - an opaque DMA cookie 30 * typedef dma_cookie_t - an opaque DMA cookie
@@ -519,6 +518,16 @@ static inline int dmaengine_slave_config(struct dma_chan *chan,
519 (unsigned long)config); 518 (unsigned long)config);
520} 519}
521 520
521static inline struct dma_async_tx_descriptor *dmaengine_prep_slave_single(
522 struct dma_chan *chan, void *buf, size_t len,
523 enum dma_data_direction dir, unsigned long flags)
524{
525 struct scatterlist sg;
526 sg_init_one(&sg, buf, len);
527
528 return chan->device->device_prep_slave_sg(chan, &sg, 1, dir, flags);
529}
530
522static inline int dmaengine_terminate_all(struct dma_chan *chan) 531static inline int dmaengine_terminate_all(struct dma_chan *chan)
523{ 532{
524 return dmaengine_device_control(chan, DMA_TERMINATE_ALL, 0); 533 return dmaengine_device_control(chan, DMA_TERMINATE_ALL, 0);
diff --git a/sound/soc/samsung/ac97.c b/sound/soc/samsung/ac97.c
index f97110e72e85..b4f9b0003685 100644
--- a/sound/soc/samsung/ac97.c
+++ b/sound/soc/samsung/ac97.c
@@ -271,7 +271,10 @@ static int s3c_ac97_trigger(struct snd_pcm_substream *substream, int cmd,
271 271
272 writel(ac_glbctrl, s3c_ac97.regs + S3C_AC97_GLBCTRL); 272 writel(ac_glbctrl, s3c_ac97.regs + S3C_AC97_GLBCTRL);
273 273
274 s3c2410_dma_ctrl(dma_data->channel, S3C2410_DMAOP_STARTED); 274 if (!dma_data->ops)
275 dma_data->ops = samsung_dma_get_ops();
276
277 dma_data->ops->started(dma_data->channel);
275 278
276 return 0; 279 return 0;
277} 280}
@@ -317,7 +320,10 @@ static int s3c_ac97_mic_trigger(struct snd_pcm_substream *substream,
317 320
318 writel(ac_glbctrl, s3c_ac97.regs + S3C_AC97_GLBCTRL); 321 writel(ac_glbctrl, s3c_ac97.regs + S3C_AC97_GLBCTRL);
319 322
320 s3c2410_dma_ctrl(dma_data->channel, S3C2410_DMAOP_STARTED); 323 if (!dma_data->ops)
324 dma_data->ops = samsung_dma_get_ops();
325
326 dma_data->ops->started(dma_data->channel);
321 327
322 return 0; 328 return 0;
323} 329}
diff --git a/sound/soc/samsung/dma.c b/sound/soc/samsung/dma.c
index 9465588b02f2..2d622b635e68 100644
--- a/sound/soc/samsung/dma.c
+++ b/sound/soc/samsung/dma.c
@@ -54,7 +54,6 @@ struct runtime_data {
54 spinlock_t lock; 54 spinlock_t lock;
55 int state; 55 int state;
56 unsigned int dma_loaded; 56 unsigned int dma_loaded;
57 unsigned int dma_limit;
58 unsigned int dma_period; 57 unsigned int dma_period;
59 dma_addr_t dma_start; 58 dma_addr_t dma_start;
60 dma_addr_t dma_pos; 59 dma_addr_t dma_pos;
@@ -62,77 +61,79 @@ struct runtime_data {
62 struct s3c_dma_params *params; 61 struct s3c_dma_params *params;
63}; 62};
64 63
64static void audio_buffdone(void *data);
65
65/* dma_enqueue 66/* dma_enqueue
66 * 67 *
67 * place a dma buffer onto the queue for the dma system 68 * place a dma buffer onto the queue for the dma system
68 * to handle. 69 * to handle.
69*/ 70 */
70static void dma_enqueue(struct snd_pcm_substream *substream) 71static void dma_enqueue(struct snd_pcm_substream *substream)
71{ 72{
72 struct runtime_data *prtd = substream->runtime->private_data; 73 struct runtime_data *prtd = substream->runtime->private_data;
73 dma_addr_t pos = prtd->dma_pos; 74 dma_addr_t pos = prtd->dma_pos;
74 unsigned int limit; 75 unsigned int limit;
75 int ret; 76 struct samsung_dma_prep_info dma_info;
76 77
77 pr_debug("Entered %s\n", __func__); 78 pr_debug("Entered %s\n", __func__);
78 79
79 if (s3c_dma_has_circular()) 80 limit = (prtd->dma_end - prtd->dma_start) / prtd->dma_period;
80 limit = (prtd->dma_end - prtd->dma_start) / prtd->dma_period;
81 else
82 limit = prtd->dma_limit;
83 81
84 pr_debug("%s: loaded %d, limit %d\n", 82 pr_debug("%s: loaded %d, limit %d\n",
85 __func__, prtd->dma_loaded, limit); 83 __func__, prtd->dma_loaded, limit);
86 84
87 while (prtd->dma_loaded < limit) { 85 dma_info.cap = (samsung_dma_has_circular() ? DMA_CYCLIC : DMA_SLAVE);
88 unsigned long len = prtd->dma_period; 86 dma_info.direction =
87 (substream->stream == SNDRV_PCM_STREAM_PLAYBACK
88 ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
89 dma_info.fp = audio_buffdone;
90 dma_info.fp_param = substream;
91 dma_info.period = prtd->dma_period;
92 dma_info.len = prtd->dma_period*limit;
89 93
94 while (prtd->dma_loaded < limit) {
90 pr_debug("dma_loaded: %d\n", prtd->dma_loaded); 95 pr_debug("dma_loaded: %d\n", prtd->dma_loaded);
91 96
92 if ((pos + len) > prtd->dma_end) { 97 if ((pos + dma_info.period) > prtd->dma_end) {
93 len = prtd->dma_end - pos; 98 dma_info.period = prtd->dma_end - pos;
94 pr_debug("%s: corrected dma len %ld\n", __func__, len); 99 pr_debug("%s: corrected dma len %ld\n",
100 __func__, dma_info.period);
95 } 101 }
96 102
97 ret = s3c2410_dma_enqueue(prtd->params->channel, 103 dma_info.buf = pos;
98 substream, pos, len); 104 prtd->params->ops->prepare(prtd->params->ch, &dma_info);
99 105
100 if (ret == 0) { 106 prtd->dma_loaded++;
101 prtd->dma_loaded++; 107 pos += prtd->dma_period;
102 pos += prtd->dma_period; 108 if (pos >= prtd->dma_end)
103 if (pos >= prtd->dma_end) 109 pos = prtd->dma_start;
104 pos = prtd->dma_start;
105 } else
106 break;
107 } 110 }
108 111
109 prtd->dma_pos = pos; 112 prtd->dma_pos = pos;
110} 113}
111 114
112static void audio_buffdone(struct s3c2410_dma_chan *channel, 115static void audio_buffdone(void *data)
113 void *dev_id, int size,
114 enum s3c2410_dma_buffresult result)
115{ 116{
116 struct snd_pcm_substream *substream = dev_id; 117 struct snd_pcm_substream *substream = data;
117 struct runtime_data *prtd; 118 struct runtime_data *prtd = substream->runtime->private_data;
118 119
119 pr_debug("Entered %s\n", __func__); 120 pr_debug("Entered %s\n", __func__);
120 121
121 if (result == S3C2410_RES_ABORT || result == S3C2410_RES_ERR) 122 if (prtd->state & ST_RUNNING) {
122 return; 123 prtd->dma_pos += prtd->dma_period;
123 124 if (prtd->dma_pos >= prtd->dma_end)
124 prtd = substream->runtime->private_data; 125 prtd->dma_pos = prtd->dma_start;
125 126
126 if (substream) 127 if (substream)
127 snd_pcm_period_elapsed(substream); 128 snd_pcm_period_elapsed(substream);
128 129
129 spin_lock(&prtd->lock); 130 spin_lock(&prtd->lock);
130 if (prtd->state & ST_RUNNING && !s3c_dma_has_circular()) { 131 if (!samsung_dma_has_circular()) {
131 prtd->dma_loaded--; 132 prtd->dma_loaded--;
132 dma_enqueue(substream); 133 dma_enqueue(substream);
134 }
135 spin_unlock(&prtd->lock);
133 } 136 }
134
135 spin_unlock(&prtd->lock);
136} 137}
137 138
138static int dma_hw_params(struct snd_pcm_substream *substream, 139static int dma_hw_params(struct snd_pcm_substream *substream,
@@ -144,8 +145,7 @@ static int dma_hw_params(struct snd_pcm_substream *substream,
144 unsigned long totbytes = params_buffer_bytes(params); 145 unsigned long totbytes = params_buffer_bytes(params);
145 struct s3c_dma_params *dma = 146 struct s3c_dma_params *dma =
146 snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); 147 snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
147 int ret = 0; 148 struct samsung_dma_info dma_info;
148
149 149
150 pr_debug("Entered %s\n", __func__); 150 pr_debug("Entered %s\n", __func__);
151 151
@@ -163,30 +163,26 @@ static int dma_hw_params(struct snd_pcm_substream *substream,
163 pr_debug("params %p, client %p, channel %d\n", prtd->params, 163 pr_debug("params %p, client %p, channel %d\n", prtd->params,
164 prtd->params->client, prtd->params->channel); 164 prtd->params->client, prtd->params->channel);
165 165
166 ret = s3c2410_dma_request(prtd->params->channel, 166 prtd->params->ops = samsung_dma_get_ops();
167 prtd->params->client, NULL); 167
168 168 dma_info.cap = (samsung_dma_has_circular() ?
169 if (ret < 0) { 169 DMA_CYCLIC : DMA_SLAVE);
170 printk(KERN_ERR "failed to get dma channel\n"); 170 dma_info.client = prtd->params->client;
171 return ret; 171 dma_info.direction =
172 } 172 (substream->stream == SNDRV_PCM_STREAM_PLAYBACK
173 173 ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
174 /* use the circular buffering if we have it available. */ 174 dma_info.width = prtd->params->dma_size;
175 if (s3c_dma_has_circular()) 175 dma_info.fifo = prtd->params->dma_addr;
176 s3c2410_dma_setflags(prtd->params->channel, 176 prtd->params->ch = prtd->params->ops->request(
177 S3C2410_DMAF_CIRCULAR); 177 prtd->params->channel, &dma_info);
178 } 178 }
179 179
180 s3c2410_dma_set_buffdone_fn(prtd->params->channel,
181 audio_buffdone);
182
183 snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); 180 snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
184 181
185 runtime->dma_bytes = totbytes; 182 runtime->dma_bytes = totbytes;
186 183
187 spin_lock_irq(&prtd->lock); 184 spin_lock_irq(&prtd->lock);
188 prtd->dma_loaded = 0; 185 prtd->dma_loaded = 0;
189 prtd->dma_limit = runtime->hw.periods_min;
190 prtd->dma_period = params_period_bytes(params); 186 prtd->dma_period = params_period_bytes(params);
191 prtd->dma_start = runtime->dma_addr; 187 prtd->dma_start = runtime->dma_addr;
192 prtd->dma_pos = prtd->dma_start; 188 prtd->dma_pos = prtd->dma_start;
@@ -202,11 +198,12 @@ static int dma_hw_free(struct snd_pcm_substream *substream)
202 198
203 pr_debug("Entered %s\n", __func__); 199 pr_debug("Entered %s\n", __func__);
204 200
205 /* TODO - do we need to ensure DMA flushed */
206 snd_pcm_set_runtime_buffer(substream, NULL); 201 snd_pcm_set_runtime_buffer(substream, NULL);
207 202
208 if (prtd->params) { 203 if (prtd->params) {
209 s3c2410_dma_free(prtd->params->channel, prtd->params->client); 204 prtd->params->ops->flush(prtd->params->ch);
205 prtd->params->ops->release(prtd->params->ch,
206 prtd->params->client);
210 prtd->params = NULL; 207 prtd->params = NULL;
211 } 208 }
212 209
@@ -225,23 +222,9 @@ static int dma_prepare(struct snd_pcm_substream *substream)
225 if (!prtd->params) 222 if (!prtd->params)
226 return 0; 223 return 0;
227 224
228 /* channel needs configuring for mem=>device, increment memory addr,
229 * sync to pclk, half-word transfers to the IIS-FIFO. */
230 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
231 s3c2410_dma_devconfig(prtd->params->channel,
232 S3C2410_DMASRC_MEM,
233 prtd->params->dma_addr);
234 } else {
235 s3c2410_dma_devconfig(prtd->params->channel,
236 S3C2410_DMASRC_HW,
237 prtd->params->dma_addr);
238 }
239
240 s3c2410_dma_config(prtd->params->channel,
241 prtd->params->dma_size);
242
243 /* flush the DMA channel */ 225 /* flush the DMA channel */
244 s3c2410_dma_ctrl(prtd->params->channel, S3C2410_DMAOP_FLUSH); 226 prtd->params->ops->flush(prtd->params->ch);
227
245 prtd->dma_loaded = 0; 228 prtd->dma_loaded = 0;
246 prtd->dma_pos = prtd->dma_start; 229 prtd->dma_pos = prtd->dma_start;
247 230
@@ -265,14 +248,14 @@ static int dma_trigger(struct snd_pcm_substream *substream, int cmd)
265 case SNDRV_PCM_TRIGGER_RESUME: 248 case SNDRV_PCM_TRIGGER_RESUME:
266 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 249 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
267 prtd->state |= ST_RUNNING; 250 prtd->state |= ST_RUNNING;
268 s3c2410_dma_ctrl(prtd->params->channel, S3C2410_DMAOP_START); 251 prtd->params->ops->trigger(prtd->params->ch);
269 break; 252 break;
270 253
271 case SNDRV_PCM_TRIGGER_STOP: 254 case SNDRV_PCM_TRIGGER_STOP:
272 case SNDRV_PCM_TRIGGER_SUSPEND: 255 case SNDRV_PCM_TRIGGER_SUSPEND:
273 case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 256 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
274 prtd->state &= ~ST_RUNNING; 257 prtd->state &= ~ST_RUNNING;
275 s3c2410_dma_ctrl(prtd->params->channel, S3C2410_DMAOP_STOP); 258 prtd->params->ops->stop(prtd->params->ch);
276 break; 259 break;
277 260
278 default: 261 default:
@@ -291,21 +274,12 @@ dma_pointer(struct snd_pcm_substream *substream)
291 struct snd_pcm_runtime *runtime = substream->runtime; 274 struct snd_pcm_runtime *runtime = substream->runtime;
292 struct runtime_data *prtd = runtime->private_data; 275 struct runtime_data *prtd = runtime->private_data;
293 unsigned long res; 276 unsigned long res;
294 dma_addr_t src, dst;
295 277
296 pr_debug("Entered %s\n", __func__); 278 pr_debug("Entered %s\n", __func__);
297 279
298 spin_lock(&prtd->lock); 280 res = prtd->dma_pos - prtd->dma_start;
299 s3c2410_dma_getposition(prtd->params->channel, &src, &dst);
300
301 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
302 res = dst - prtd->dma_start;
303 else
304 res = src - prtd->dma_start;
305
306 spin_unlock(&prtd->lock);
307 281
308 pr_debug("Pointer %x %x\n", src, dst); 282 pr_debug("Pointer offset: %lu\n", res);
309 283
310 /* we seem to be getting the odd error from the pcm library due 284 /* we seem to be getting the odd error from the pcm library due
311 * to out-of-bounds pointers. this is maybe due to the dma engine 285 * to out-of-bounds pointers. this is maybe due to the dma engine
diff --git a/sound/soc/samsung/dma.h b/sound/soc/samsung/dma.h
index c50659269a40..7d1ead77ef21 100644
--- a/sound/soc/samsung/dma.h
+++ b/sound/soc/samsung/dma.h
@@ -6,7 +6,7 @@
6 * Free Software Foundation; either version 2 of the License, or (at your 6 * Free Software Foundation; either version 2 of the License, or (at your
7 * option) any later version. 7 * option) any later version.
8 * 8 *
9 * ALSA PCM interface for the Samsung S3C24xx CPU 9 * ALSA PCM interface for the Samsung SoC
10 */ 10 */
11 11
12#ifndef _S3C_AUDIO_H 12#ifndef _S3C_AUDIO_H
@@ -17,6 +17,8 @@ struct s3c_dma_params {
17 int channel; /* Channel ID */ 17 int channel; /* Channel ID */
18 dma_addr_t dma_addr; 18 dma_addr_t dma_addr;
19 int dma_size; /* Size of the DMA transfer */ 19 int dma_size; /* Size of the DMA transfer */
20 unsigned ch;
21 struct samsung_dma_ops *ops;
20}; 22};
21 23
22#endif 24#endif