Merge branch 'next-samsung-devel' into next-samsung-devel-2
authorKukjin Kim <kgene.kim@samsung.com>
Tue, 4 Oct 2011 11:18:36 +0000 (20:18 +0900)
committerKukjin Kim <kgene.kim@samsung.com>
Tue, 4 Oct 2011 11:18:36 +0000 (20:18 +0900)
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

136 files changed:
arch/arm/Kconfig
arch/arm/include/asm/hardware/pl080.h
arch/arm/mach-exynos4/Kconfig
arch/arm/mach-exynos4/clock.c
arch/arm/mach-exynos4/cpu.c
arch/arm/mach-exynos4/dma.c
arch/arm/mach-exynos4/include/mach/dma.h
arch/arm/mach-exynos4/include/mach/i2c-hdmiphy.h [new file with mode: 0644]
arch/arm/mach-exynos4/include/mach/irqs.h
arch/arm/mach-exynos4/include/mach/map.h
arch/arm/mach-exynos4/include/mach/pm-core.h
arch/arm/mach-exynos4/include/mach/pmu.h
arch/arm/mach-exynos4/include/mach/regs-pmu.h
arch/arm/mach-exynos4/mach-nuri.c
arch/arm/mach-exynos4/mach-origen.c
arch/arm/mach-exynos4/mach-smdkv310.c
arch/arm/mach-exynos4/mach-universal_c210.c
arch/arm/mach-exynos4/pm.c
arch/arm/mach-exynos4/pmu.c
arch/arm/mach-s3c2410/Kconfig
arch/arm/mach-s3c2410/include/mach/dma.h
arch/arm/mach-s3c2410/include/mach/gpio-fns.h
arch/arm/mach-s3c2410/include/mach/gpio-track.h
arch/arm/mach-s3c2410/include/mach/pm-core.h
arch/arm/mach-s3c2410/include/mach/regs-s3c2443-clock.h
arch/arm/mach-s3c2410/s3c2410.c
arch/arm/mach-s3c2412/dma.c
arch/arm/mach-s3c2412/gpio.c [new file with mode: 0644]
arch/arm/mach-s3c2416/Kconfig
arch/arm/mach-s3c2416/clock.c
arch/arm/mach-s3c2416/s3c2416.c
arch/arm/mach-s3c2440/Kconfig
arch/arm/mach-s3c2440/s3c2440.c
arch/arm/mach-s3c2440/s3c2442.c
arch/arm/mach-s3c2443/Kconfig
arch/arm/mach-s3c2443/clock.c
arch/arm/mach-s3c2443/s3c2443.c
arch/arm/mach-s3c64xx/Kconfig
arch/arm/mach-s3c64xx/Makefile
arch/arm/mach-s3c64xx/clock.c
arch/arm/mach-s3c64xx/dma.c
arch/arm/mach-s3c64xx/gpiolib.c [deleted file]
arch/arm/mach-s3c64xx/include/mach/crag6410.h [new file with mode: 0644]
arch/arm/mach-s3c64xx/include/mach/dma.h
arch/arm/mach-s3c64xx/include/mach/pm-core.h
arch/arm/mach-s3c64xx/include/mach/regs-sys.h
arch/arm/mach-s3c64xx/mach-crag6410-module.c [new file with mode: 0644]
arch/arm/mach-s3c64xx/mach-crag6410.c
arch/arm/mach-s3c64xx/pm.c
arch/arm/mach-s5p64x0/Kconfig
arch/arm/mach-s5p64x0/Makefile
arch/arm/mach-s5p64x0/clock-s5p6440.c
arch/arm/mach-s5p64x0/clock-s5p6450.c
arch/arm/mach-s5p64x0/cpu.c
arch/arm/mach-s5p64x0/dma.c
arch/arm/mach-s5p64x0/include/mach/dma.h
arch/arm/mach-s5p64x0/include/mach/irqs.h
arch/arm/mach-s5p64x0/include/mach/map.h
arch/arm/mach-s5p64x0/include/mach/regs-gpio.h
arch/arm/mach-s5p64x0/mach-smdk6440.c
arch/arm/mach-s5p64x0/mach-smdk6450.c
arch/arm/mach-s5p64x0/setup-fb-24bpp.c [new file with mode: 0644]
arch/arm/mach-s5pc100/Kconfig
arch/arm/mach-s5pc100/clock.c
arch/arm/mach-s5pc100/dma.c
arch/arm/mach-s5pc100/include/mach/dma.h
arch/arm/mach-s5pv210/Kconfig
arch/arm/mach-s5pv210/clock.c
arch/arm/mach-s5pv210/cpu.c
arch/arm/mach-s5pv210/dma.c
arch/arm/mach-s5pv210/include/mach/dma.h
arch/arm/mach-s5pv210/include/mach/i2c-hdmiphy.h [new file with mode: 0644]
arch/arm/mach-s5pv210/include/mach/irqs.h
arch/arm/mach-s5pv210/include/mach/map.h
arch/arm/mach-s5pv210/include/mach/pm-core.h
arch/arm/mach-s5pv210/include/mach/regs-clock.h
arch/arm/mach-s5pv210/mach-goni.c
arch/arm/plat-s3c24xx/Kconfig
arch/arm/plat-s3c24xx/Makefile
arch/arm/plat-s3c24xx/dma.c
arch/arm/plat-s3c24xx/gpio.c [deleted file]
arch/arm/plat-s3c24xx/gpiolib.c [deleted file]
arch/arm/plat-s3c24xx/s3c2443-clock.c
arch/arm/plat-s5p/Kconfig
arch/arm/plat-s5p/Makefile
arch/arm/plat-s5p/dev-i2c-hdmiphy.c [new file with mode: 0644]
arch/arm/plat-s5p/dev-tv.c [new file with mode: 0644]
arch/arm/plat-s5p/include/plat/pll.h
arch/arm/plat-s5p/irq-gpioint.c
arch/arm/plat-samsung/Kconfig
arch/arm/plat-samsung/Makefile
arch/arm/plat-samsung/dma-ops.c [new file with mode: 0644]
arch/arm/plat-samsung/gpio-config.c [deleted file]
arch/arm/plat-samsung/gpio.c [deleted file]
arch/arm/plat-samsung/include/plat/devs.h
arch/arm/plat-samsung/include/plat/dma-ops.h [new file with mode: 0644]
arch/arm/plat-samsung/include/plat/dma-pl330.h [new file with mode: 0644]
arch/arm/plat-samsung/include/plat/dma-s3c24xx.h
arch/arm/plat-samsung/include/plat/dma.h
arch/arm/plat-samsung/include/plat/fb.h
arch/arm/plat-samsung/include/plat/gpio-cfg-helpers.h
arch/arm/plat-samsung/include/plat/gpio-cfg.h
arch/arm/plat-samsung/include/plat/gpio-core.h
arch/arm/plat-samsung/include/plat/gpio-fns.h [new file with mode: 0644]
arch/arm/plat-samsung/include/plat/iic.h
arch/arm/plat-samsung/include/plat/pm.h
arch/arm/plat-samsung/include/plat/s3c-dma-pl330.h [deleted file]
arch/arm/plat-samsung/include/plat/s3c-pl330-pdata.h [deleted file]
arch/arm/plat-samsung/include/plat/tv-core.h [new file with mode: 0644]
arch/arm/plat-samsung/pm-gpio.c
arch/arm/plat-samsung/pm.c
arch/arm/plat-samsung/s3c-dma-ops.c [new file with mode: 0644]
arch/arm/plat-samsung/s3c-pl330.c [deleted file]
drivers/dma/Kconfig
drivers/dma/amba-pl08x.c
drivers/dma/at_hdmac.c
drivers/dma/at_hdmac_regs.h
drivers/dma/dmatest.c
drivers/dma/imx-sdma.c
drivers/dma/mxs-dma.c
drivers/dma/pl330.c
drivers/gpio/Kconfig
drivers/gpio/Makefile
drivers/gpio/gpio-exynos4.c [deleted file]
drivers/gpio/gpio-plat-samsung.c [deleted file]
drivers/gpio/gpio-s5pc100.c [deleted file]
drivers/gpio/gpio-s5pv210.c [deleted file]
drivers/gpio/gpio-samsung.c [new file with mode: 0644]
drivers/mmc/host/s3cmci.c
drivers/spi/spi-s3c64xx.c
include/linux/amba/pl08x.h
include/linux/amba/pl330.h
include/linux/dmaengine.h
sound/soc/samsung/ac97.c
sound/soc/samsung/dma.c
sound/soc/samsung/dma.h

index 3146ed3f6eca01a42068454e31f53a3330cc12c6..bea81d018312b7a34b959a9df31ffa9158e9d512 100644 (file)
@@ -724,9 +724,6 @@ config ARCH_S3C64XX
        select SAMSUNG_IRQ_VIC_TIMER
        select SAMSUNG_IRQ_UART
        select S3C_GPIO_TRACK
-       select S3C_GPIO_PULL_UPDOWN
-       select S3C_GPIO_CFG_S3C24XX
-       select S3C_GPIO_CFG_S3C64XX
        select S3C_DEV_NAND
        select USB_ARCH_HAS_OHCI
        select SAMSUNG_GPIOLIB_4BIT
index e4a04e4e5627e998d7f3ff9a8fac4fb1ade84f95..33c78d7af2e15aaf2b7da93b708920fcefab9357 100644 (file)
@@ -21,6 +21,9 @@
  * OneNAND features.
 */
 
+#ifndef ASM_PL080_H
+#define ASM_PL080_H
+
 #define PL080_INT_STATUS                       (0x00)
 #define PL080_TC_STATUS                                (0x04)
 #define PL080_TC_CLEAR                         (0x08)
@@ -138,3 +141,4 @@ struct pl080s_lli {
        u32     control1;
 };
 
+#endif /* ASM_PL080_H */
index c595bb03f417c376350bf646df049447917cfcd5..b6722decff9d7c3c08d369175808a50db2a605d7 100644 (file)
@@ -11,7 +11,7 @@ if ARCH_EXYNOS4
 
 config CPU_EXYNOS4210
        bool
-       select S3C_PL330_DMA
+       select SAMSUNG_DMADEV
        help
          Enable EXYNOS4210 CPU support
 
@@ -131,6 +131,14 @@ config MACH_SMDKV310
        select S3C_DEV_RTC
        select S3C_DEV_WDT
        select S3C_DEV_I2C1
+       select S5P_DEV_FIMC0
+       select S5P_DEV_FIMC1
+       select S5P_DEV_FIMC2
+       select S5P_DEV_FIMC3
+       select S5P_DEV_I2C_HDMIPHY
+       select S5P_DEV_MFC
+       select S5P_DEV_TV
+       select S5P_DEV_USB_EHCI
        select S3C_DEV_HSMMC
        select S3C_DEV_HSMMC1
        select S3C_DEV_HSMMC2
@@ -145,6 +153,7 @@ config MACH_SMDKV310
        select EXYNOS4_SETUP_I2C1
        select EXYNOS4_SETUP_KEYPAD
        select EXYNOS4_SETUP_SDHCI
+       select EXYNOS4_SETUP_USB_PHY
        help
          Machine support for Samsung SMDKV310
 
@@ -170,19 +179,26 @@ config MACH_UNIVERSAL_C210
        select S5P_DEV_FIMC1
        select S5P_DEV_FIMC2
        select S5P_DEV_FIMC3
+       select S5P_DEV_CSIS0
+       select S5P_DEV_FIMD0
        select S3C_DEV_HSMMC
        select S3C_DEV_HSMMC2
        select S3C_DEV_HSMMC3
        select S3C_DEV_I2C1
        select S3C_DEV_I2C3
        select S3C_DEV_I2C5
+       select S5P_DEV_I2C_HDMIPHY
        select S5P_DEV_MFC
        select S5P_DEV_ONENAND
+       select S5P_DEV_TV
        select EXYNOS4_DEV_PD
+       select EXYNOS4_SETUP_FIMD0
        select EXYNOS4_SETUP_I2C1
        select EXYNOS4_SETUP_I2C3
        select EXYNOS4_SETUP_I2C5
        select EXYNOS4_SETUP_SDHCI
+       select EXYNOS4_SETUP_FIMC
+       select S5P_SETUP_MIPIPHY
        help
          Machine support for Samsung Mobile Universal S5PC210 Reference
          Board.
@@ -191,6 +207,8 @@ config MACH_NURI
        bool "Mobile NURI Board"
        select CPU_EXYNOS4210
        select S3C_DEV_WDT
+       select S3C_DEV_RTC
+       select S5P_DEV_FIMD0
        select S3C_DEV_HSMMC
        select S3C_DEV_HSMMC2
        select S3C_DEV_HSMMC3
@@ -200,6 +218,7 @@ config MACH_NURI
        select S5P_DEV_MFC
        select S5P_DEV_USB_EHCI
        select EXYNOS4_DEV_PD
+       select EXYNOS4_SETUP_FIMD0
        select EXYNOS4_SETUP_I2C1
        select EXYNOS4_SETUP_I2C3
        select EXYNOS4_SETUP_I2C5
@@ -215,8 +234,22 @@ config MACH_ORIGEN
        select CPU_EXYNOS4210
        select S3C_DEV_RTC
        select S3C_DEV_WDT
+       select S3C_DEV_HSMMC
        select S3C_DEV_HSMMC2
+       select S5P_DEV_FIMC0
+       select S5P_DEV_FIMC1
+       select S5P_DEV_FIMC2
+       select S5P_DEV_FIMC3
+       select S5P_DEV_FIMD0
+       select S5P_DEV_I2C_HDMIPHY
+       select S5P_DEV_TV
+       select S5P_DEV_USB_EHCI
+       select EXYNOS4_DEV_PD
+       select SAMSUNG_DEV_BACKLIGHT
+       select SAMSUNG_DEV_PWM
+       select EXYNOS4_SETUP_FIMD0
        select EXYNOS4_SETUP_SDHCI
+       select EXYNOS4_SETUP_USB_PHY
        help
          Machine support for ORIGEN based on Samsung EXYNOS4210
 
index 413c7cc81979f47ee6dcf0923063440effaa9f29..a25c818367590dc7345c655567737f33b624f650 100644 (file)
@@ -111,6 +111,11 @@ struct clk clk_sclk_usbphy1 = {
        .name           = "sclk_usbphy1",
 };
 
+static struct clk dummy_apb_pclk = {
+       .name           = "apb_pclk",
+       .id             = -1,
+};
+
 static int exynos4_clksrc_mask_top_ctrl(struct clk *clk, int enable)
 {
        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)
        return s5p_gatectrl(S5P_CLKGATE_IP_MFC, clk, enable);
 }
 
+static int exynos4_clksrc_mask_tv_ctrl(struct clk *clk, int enable)
+{
+       return s5p_gatectrl(S5P_CLKSRC_MASK_TV, clk, enable);
+}
+
 static int exynos4_clk_ip_cam_ctrl(struct clk *clk, int enable)
 {
        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)
        return s5p_gatectrl(S5P_CLKGATE_IP_PERIR, clk, enable);
 }
 
+static int exynos4_clk_hdmiphy_ctrl(struct clk *clk, int enable)
+{
+       return s5p_gatectrl(S5P_HDMI_PHY_CONTROL, clk, enable);
+}
+
+static int exynos4_clk_dac_ctrl(struct clk *clk, int enable)
+{
+       return s5p_gatectrl(S5P_DAC_PHY_CONTROL, clk, enable);
+}
+
 /* Core list of CMU_CPU side */
 
 static struct clksrc_clk clk_mout_apll = {
@@ -503,13 +523,48 @@ static struct clk init_clocks_off[] = {
                .enable         = exynos4_clk_ip_fsys_ctrl,
                .ctrlbit        = (1 << 9),
        }, {
-               .name           = "pdma",
-               .devname        = "s3c-pl330.0",
+               .name           = "dac",
+               .devname        = "s5p-sdo",
+               .enable         = exynos4_clk_ip_tv_ctrl,
+               .ctrlbit        = (1 << 2),
+       }, {
+               .name           = "mixer",
+               .devname        = "s5p-mixer",
+               .enable         = exynos4_clk_ip_tv_ctrl,
+               .ctrlbit        = (1 << 1),
+       }, {
+               .name           = "vp",
+               .devname        = "s5p-mixer",
+               .enable         = exynos4_clk_ip_tv_ctrl,
+               .ctrlbit        = (1 << 0),
+       }, {
+               .name           = "hdmi",
+               .devname        = "exynos4-hdmi",
+               .enable         = exynos4_clk_ip_tv_ctrl,
+               .ctrlbit        = (1 << 3),
+       }, {
+               .name           = "hdmiphy",
+               .devname        = "exynos4-hdmi",
+               .enable         = exynos4_clk_hdmiphy_ctrl,
+               .ctrlbit        = (1 << 0),
+       }, {
+               .name           = "dacphy",
+               .devname        = "s5p-sdo",
+               .enable         = exynos4_clk_dac_ctrl,
+               .ctrlbit        = (1 << 0),
+       }, {
+               .name           = "sata",
+               .parent         = &clk_aclk_133.clk,
+               .enable         = exynos4_clk_ip_fsys_ctrl,
+               .ctrlbit        = (1 << 10),
+       }, {
+               .name           = "dma",
+               .devname        = "dma-pl330.0",
                .enable         = exynos4_clk_ip_fsys_ctrl,
                .ctrlbit        = (1 << 0),
        }, {
-               .name           = "pdma",
-               .devname        = "s3c-pl330.1",
+               .name           = "dma",
+               .devname        = "dma-pl330.1",
                .enable         = exynos4_clk_ip_fsys_ctrl,
                .ctrlbit        = (1 << 1),
        }, {
@@ -629,6 +684,12 @@ static struct clk init_clocks_off[] = {
                .parent         = &clk_aclk_100.clk,
                .enable         = exynos4_clk_ip_peril_ctrl,
                .ctrlbit        = (1 << 13),
+       }, {
+               .name           = "i2c",
+               .devname        = "s3c2440-hdmiphy-i2c",
+               .parent         = &clk_aclk_100.clk,
+               .enable         = exynos4_clk_ip_peril_ctrl,
+               .ctrlbit        = (1 << 14),
        }, {
                .name           = "SYSMMU_MDMA",
                .enable         = exynos4_clk_ip_image_ctrl,
@@ -831,6 +892,81 @@ static struct clksrc_sources clkset_mout_mfc = {
        .nr_sources     = ARRAY_SIZE(clkset_mout_mfc_list),
 };
 
+static struct clk *clkset_sclk_dac_list[] = {
+       [0] = &clk_sclk_vpll.clk,
+       [1] = &clk_sclk_hdmiphy,
+};
+
+static struct clksrc_sources clkset_sclk_dac = {
+       .sources        = clkset_sclk_dac_list,
+       .nr_sources     = ARRAY_SIZE(clkset_sclk_dac_list),
+};
+
+static struct clksrc_clk clk_sclk_dac = {
+       .clk            = {
+               .name           = "sclk_dac",
+               .enable         = exynos4_clksrc_mask_tv_ctrl,
+               .ctrlbit        = (1 << 8),
+       },
+       .sources = &clkset_sclk_dac,
+       .reg_src = { .reg = S5P_CLKSRC_TV, .shift = 8, .size = 1 },
+};
+
+static struct clksrc_clk clk_sclk_pixel = {
+       .clk            = {
+               .name           = "sclk_pixel",
+               .parent = &clk_sclk_vpll.clk,
+       },
+       .reg_div = { .reg = S5P_CLKDIV_TV, .shift = 0, .size = 4 },
+};
+
+static struct clk *clkset_sclk_hdmi_list[] = {
+       [0] = &clk_sclk_pixel.clk,
+       [1] = &clk_sclk_hdmiphy,
+};
+
+static struct clksrc_sources clkset_sclk_hdmi = {
+       .sources        = clkset_sclk_hdmi_list,
+       .nr_sources     = ARRAY_SIZE(clkset_sclk_hdmi_list),
+};
+
+static struct clksrc_clk clk_sclk_hdmi = {
+       .clk            = {
+               .name           = "sclk_hdmi",
+               .enable         = exynos4_clksrc_mask_tv_ctrl,
+               .ctrlbit        = (1 << 0),
+       },
+       .sources = &clkset_sclk_hdmi,
+       .reg_src = { .reg = S5P_CLKSRC_TV, .shift = 0, .size = 1 },
+};
+
+static struct clk *clkset_sclk_mixer_list[] = {
+       [0] = &clk_sclk_dac.clk,
+       [1] = &clk_sclk_hdmi.clk,
+};
+
+static struct clksrc_sources clkset_sclk_mixer = {
+       .sources        = clkset_sclk_mixer_list,
+       .nr_sources     = ARRAY_SIZE(clkset_sclk_mixer_list),
+};
+
+static struct clksrc_clk clk_sclk_mixer = {
+       .clk            = {
+               .name           = "sclk_mixer",
+               .enable         = exynos4_clksrc_mask_tv_ctrl,
+               .ctrlbit        = (1 << 4),
+       },
+       .sources = &clkset_sclk_mixer,
+       .reg_src = { .reg = S5P_CLKSRC_TV, .shift = 4, .size = 1 },
+};
+
+static struct clksrc_clk *sclk_tv[] = {
+       &clk_sclk_dac,
+       &clk_sclk_pixel,
+       &clk_sclk_hdmi,
+       &clk_sclk_mixer,
+};
+
 static struct clksrc_clk clk_dout_mmc0 = {
        .clk            = {
                .name           = "dout_mmc0",
@@ -1157,6 +1293,71 @@ static struct clk_ops exynos4_fout_apll_ops = {
        .get_rate = exynos4_fout_apll_get_rate,
 };
 
+static u32 vpll_div[][8] = {
+       {  54000000, 3, 53, 3, 1024, 0, 17, 0 },
+       { 108000000, 3, 53, 2, 1024, 0, 17, 0 },
+};
+
+static unsigned long exynos4_vpll_get_rate(struct clk *clk)
+{
+       return clk->rate;
+}
+
+static int exynos4_vpll_set_rate(struct clk *clk, unsigned long rate)
+{
+       unsigned int vpll_con0, vpll_con1 = 0;
+       unsigned int i;
+
+       /* Return if nothing changed */
+       if (clk->rate == rate)
+               return 0;
+
+       vpll_con0 = __raw_readl(S5P_VPLL_CON0);
+       vpll_con0 &= ~(0x1 << 27 |                                      \
+                       PLL90XX_MDIV_MASK << PLL46XX_MDIV_SHIFT |       \
+                       PLL90XX_PDIV_MASK << PLL46XX_PDIV_SHIFT |       \
+                       PLL90XX_SDIV_MASK << PLL46XX_SDIV_SHIFT);
+
+       vpll_con1 = __raw_readl(S5P_VPLL_CON1);
+       vpll_con1 &= ~(PLL46XX_MRR_MASK << PLL46XX_MRR_SHIFT |  \
+                       PLL46XX_MFR_MASK << PLL46XX_MFR_SHIFT | \
+                       PLL4650C_KDIV_MASK << PLL46XX_KDIV_SHIFT);
+
+       for (i = 0; i < ARRAY_SIZE(vpll_div); i++) {
+               if (vpll_div[i][0] == rate) {
+                       vpll_con0 |= vpll_div[i][1] << PLL46XX_PDIV_SHIFT;
+                       vpll_con0 |= vpll_div[i][2] << PLL46XX_MDIV_SHIFT;
+                       vpll_con0 |= vpll_div[i][3] << PLL46XX_SDIV_SHIFT;
+                       vpll_con1 |= vpll_div[i][4] << PLL46XX_KDIV_SHIFT;
+                       vpll_con1 |= vpll_div[i][5] << PLL46XX_MFR_SHIFT;
+                       vpll_con1 |= vpll_div[i][6] << PLL46XX_MRR_SHIFT;
+                       vpll_con0 |= vpll_div[i][7] << 27;
+                       break;
+               }
+       }
+
+       if (i == ARRAY_SIZE(vpll_div)) {
+               printk(KERN_ERR "%s: Invalid Clock VPLL Frequency\n",
+                               __func__);
+               return -EINVAL;
+       }
+
+       __raw_writel(vpll_con0, S5P_VPLL_CON0);
+       __raw_writel(vpll_con1, S5P_VPLL_CON1);
+
+       /* Wait for VPLL lock */
+       while (!(__raw_readl(S5P_VPLL_CON0) & (1 << PLL46XX_LOCKED_SHIFT)))
+               continue;
+
+       clk->rate = rate;
+       return 0;
+}
+
+static struct clk_ops exynos4_vpll_ops = {
+       .get_rate = exynos4_vpll_get_rate,
+       .set_rate = exynos4_vpll_set_rate,
+};
+
 void __init_or_cpufreq exynos4_setup_clocks(void)
 {
        struct clk *xtal_clk;
@@ -1214,6 +1415,7 @@ void __init_or_cpufreq exynos4_setup_clocks(void)
        clk_fout_apll.ops = &exynos4_fout_apll_ops;
        clk_fout_mpll.rate = mpll;
        clk_fout_epll.rate = epll;
+       clk_fout_vpll.ops = &exynos4_vpll_ops;
        clk_fout_vpll.rate = vpll;
 
        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)
 }
 
 static struct clk *clks[] __initdata = {
-       /* Nothing here yet */
+       &clk_sclk_hdmi27m,
+       &clk_sclk_hdmiphy,
+       &clk_sclk_usbphy0,
+       &clk_sclk_usbphy1,
 };
 
 #ifdef CONFIG_PM_SLEEP
@@ -1275,6 +1480,9 @@ void __init exynos4_register_clocks(void)
        for (ptr = 0; ptr < ARRAY_SIZE(sysclks); ptr++)
                s3c_register_clksrc(sysclks[ptr], 1);
 
+       for (ptr = 0; ptr < ARRAY_SIZE(sclk_tv); ptr++)
+               s3c_register_clksrc(sclk_tv[ptr], 1);
+
        s3c_register_clksrc(clksrcs, ARRAY_SIZE(clksrcs));
        s3c_register_clocks(init_clocks, ARRAY_SIZE(init_clocks));
 
@@ -1282,5 +1490,7 @@ void __init exynos4_register_clocks(void)
        s3c_disable_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
 
        register_syscore_ops(&exynos4_clock_syscore_ops);
+       s3c24xx_register_clock(&dummy_apb_pclk);
+
        s3c_pwmclk_init();
 }
index 02ec52a99274eea7cdfcdd992ebab1869ce71749..2aa3df00368391c1e94c6a114323322539af7bd5 100644 (file)
@@ -28,6 +28,7 @@
 #include <plat/fimc-core.h>
 #include <plat/iic-core.h>
 #include <plat/reset.h>
+#include <plat/tv-core.h>
 
 #include <mach/regs-irq.h>
 #include <mach/regs-pmu.h>
@@ -180,6 +181,7 @@ void __init exynos4_map_io(void)
        s3c_i2c2_setname("s3c2440-i2c");
 
        s5p_fb_setname(0, "exynos4-fb");
+       s5p_hdmi_setname("exynos4-hdmi");
 }
 
 void __init exynos4_init_clocks(int xtal)
index 564bb530f3322626a23d30735f6905cf9e155f55..9667c61e64fb8d0296ab5d10658e082b83b7153d 100644 (file)
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#include <linux/platform_device.h>
 #include <linux/dma-mapping.h>
+#include <linux/amba/bus.h>
+#include <linux/amba/pl330.h>
 
+#include <asm/irq.h>
 #include <plat/devs.h>
 #include <plat/irqs.h>
 
 #include <mach/map.h>
 #include <mach/irqs.h>
-
-#include <plat/s3c-pl330-pdata.h>
+#include <mach/dma.h>
 
 static u64 dma_dmamask = DMA_BIT_MASK(32);
 
-static struct resource exynos4_pdma0_resource[] = {
-       [0] = {
-               .start  = EXYNOS4_PA_PDMA0,
-               .end    = EXYNOS4_PA_PDMA0 + SZ_4K,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = IRQ_PDMA0,
-               .end    = IRQ_PDMA0,
-               .flags  = IORESOURCE_IRQ,
+struct dma_pl330_peri pdma0_peri[28] = {
+       {
+               .peri_id = (u8)DMACH_PCM0_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_PCM0_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_PCM2_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_PCM2_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_MSM_REQ0,
+       }, {
+               .peri_id = (u8)DMACH_MSM_REQ2,
+       }, {
+               .peri_id = (u8)DMACH_SPI0_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_SPI0_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_SPI2_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_SPI2_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_I2S0S_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_I2S0_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_I2S0_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_UART0_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_UART0_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_UART2_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_UART2_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_UART4_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_UART4_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_SLIMBUS0_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_SLIMBUS0_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_SLIMBUS2_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_SLIMBUS2_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_SLIMBUS4_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_SLIMBUS4_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_AC97_MICIN,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_AC97_PCMIN,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_AC97_PCMOUT,
+               .rqtype = MEMTODEV,
        },
 };
 
-static struct s3c_pl330_platdata exynos4_pdma0_pdata = {
-       .peri = {
-               [0] = DMACH_PCM0_RX,
-               [1] = DMACH_PCM0_TX,
-               [2] = DMACH_PCM2_RX,
-               [3] = DMACH_PCM2_TX,
-               [4] = DMACH_MSM_REQ0,
-               [5] = DMACH_MSM_REQ2,
-               [6] = DMACH_SPI0_RX,
-               [7] = DMACH_SPI0_TX,
-               [8] = DMACH_SPI2_RX,
-               [9] = DMACH_SPI2_TX,
-               [10] = DMACH_I2S0S_TX,
-               [11] = DMACH_I2S0_RX,
-               [12] = DMACH_I2S0_TX,
-               [13] = DMACH_I2S2_RX,
-               [14] = DMACH_I2S2_TX,
-               [15] = DMACH_UART0_RX,
-               [16] = DMACH_UART0_TX,
-               [17] = DMACH_UART2_RX,
-               [18] = DMACH_UART2_TX,
-               [19] = DMACH_UART4_RX,
-               [20] = DMACH_UART4_TX,
-               [21] = DMACH_SLIMBUS0_RX,
-               [22] = DMACH_SLIMBUS0_TX,
-               [23] = DMACH_SLIMBUS2_RX,
-               [24] = DMACH_SLIMBUS2_TX,
-               [25] = DMACH_SLIMBUS4_RX,
-               [26] = DMACH_SLIMBUS4_TX,
-               [27] = DMACH_AC97_MICIN,
-               [28] = DMACH_AC97_PCMIN,
-               [29] = DMACH_AC97_PCMOUT,
-               [30] = DMACH_MAX,
-               [31] = DMACH_MAX,
-       },
+struct dma_pl330_platdata exynos4_pdma0_pdata = {
+       .nr_valid_peri = ARRAY_SIZE(pdma0_peri),
+       .peri = pdma0_peri,
 };
 
-static struct platform_device exynos4_device_pdma0 = {
-       .name           = "s3c-pl330",
-       .id             = 0,
-       .num_resources  = ARRAY_SIZE(exynos4_pdma0_resource),
-       .resource       = exynos4_pdma0_resource,
-       .dev            = {
+struct amba_device exynos4_device_pdma0 = {
+       .dev = {
+               .init_name = "dma-pl330.0",
                .dma_mask = &dma_dmamask,
                .coherent_dma_mask = DMA_BIT_MASK(32),
                .platform_data = &exynos4_pdma0_pdata,
        },
+       .res = {
+               .start = EXYNOS4_PA_PDMA0,
+               .end = EXYNOS4_PA_PDMA0 + SZ_4K,
+               .flags = IORESOURCE_MEM,
+       },
+       .irq = {IRQ_PDMA0, NO_IRQ},
+       .periphid = 0x00041330,
 };
 
-static struct resource exynos4_pdma1_resource[] = {
-       [0] = {
-               .start  = EXYNOS4_PA_PDMA1,
-               .end    = EXYNOS4_PA_PDMA1 + SZ_4K,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = IRQ_PDMA1,
-               .end    = IRQ_PDMA1,
-               .flags  = IORESOURCE_IRQ,
+struct dma_pl330_peri pdma1_peri[25] = {
+       {
+               .peri_id = (u8)DMACH_PCM0_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_PCM0_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_PCM1_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_PCM1_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_MSM_REQ1,
+       }, {
+               .peri_id = (u8)DMACH_MSM_REQ3,
+       }, {
+               .peri_id = (u8)DMACH_SPI1_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_SPI1_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_I2S0S_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_I2S0_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_I2S0_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_I2S1_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_I2S1_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_UART0_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_UART0_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_UART1_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_UART1_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_UART3_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_UART3_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_SLIMBUS1_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_SLIMBUS1_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_SLIMBUS3_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_SLIMBUS3_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_SLIMBUS5_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_SLIMBUS5_TX,
+               .rqtype = MEMTODEV,
        },
 };
 
-static struct s3c_pl330_platdata exynos4_pdma1_pdata = {
-       .peri = {
-               [0] = DMACH_PCM0_RX,
-               [1] = DMACH_PCM0_TX,
-               [2] = DMACH_PCM1_RX,
-               [3] = DMACH_PCM1_TX,
-               [4] = DMACH_MSM_REQ1,
-               [5] = DMACH_MSM_REQ3,
-               [6] = DMACH_SPI1_RX,
-               [7] = DMACH_SPI1_TX,
-               [8] = DMACH_I2S0S_TX,
-               [9] = DMACH_I2S0_RX,
-               [10] = DMACH_I2S0_TX,
-               [11] = DMACH_I2S1_RX,
-               [12] = DMACH_I2S1_TX,
-               [13] = DMACH_UART0_RX,
-               [14] = DMACH_UART0_TX,
-               [15] = DMACH_UART1_RX,
-               [16] = DMACH_UART1_TX,
-               [17] = DMACH_UART3_RX,
-               [18] = DMACH_UART3_TX,
-               [19] = DMACH_SLIMBUS1_RX,
-               [20] = DMACH_SLIMBUS1_TX,
-               [21] = DMACH_SLIMBUS3_RX,
-               [22] = DMACH_SLIMBUS3_TX,
-               [23] = DMACH_SLIMBUS5_RX,
-               [24] = DMACH_SLIMBUS5_TX,
-               [25] = DMACH_SLIMBUS0AUX_RX,
-               [26] = DMACH_SLIMBUS0AUX_TX,
-               [27] = DMACH_SPDIF,
-               [28] = DMACH_MAX,
-               [29] = DMACH_MAX,
-               [30] = DMACH_MAX,
-               [31] = DMACH_MAX,
-       },
+struct dma_pl330_platdata exynos4_pdma1_pdata = {
+       .nr_valid_peri = ARRAY_SIZE(pdma1_peri),
+       .peri = pdma1_peri,
 };
 
-static struct platform_device exynos4_device_pdma1 = {
-       .name           = "s3c-pl330",
-       .id             = 1,
-       .num_resources  = ARRAY_SIZE(exynos4_pdma1_resource),
-       .resource       = exynos4_pdma1_resource,
-       .dev            = {
+struct amba_device exynos4_device_pdma1 = {
+       .dev = {
+               .init_name = "dma-pl330.1",
                .dma_mask = &dma_dmamask,
                .coherent_dma_mask = DMA_BIT_MASK(32),
                .platform_data = &exynos4_pdma1_pdata,
        },
-};
-
-static struct platform_device *exynos4_dmacs[] __initdata = {
-       &exynos4_device_pdma0,
-       &exynos4_device_pdma1,
+       .res = {
+               .start = EXYNOS4_PA_PDMA1,
+               .end = EXYNOS4_PA_PDMA1 + SZ_4K,
+               .flags = IORESOURCE_MEM,
+       },
+       .irq = {IRQ_PDMA1, NO_IRQ},
+       .periphid = 0x00041330,
 };
 
 static int __init exynos4_dma_init(void)
 {
-       platform_add_devices(exynos4_dmacs, ARRAY_SIZE(exynos4_dmacs));
+       amba_device_register(&exynos4_device_pdma0, &iomem_resource);
+       amba_device_register(&exynos4_device_pdma1, &iomem_resource);
 
        return 0;
 }
index 81209eb1409b7ad4c55a70897379547991ea2958..201842a3769e5187067d95b70c9d2e14a5ea3acd 100644 (file)
@@ -20,7 +20,7 @@
 #ifndef __MACH_DMA_H
 #define __MACH_DMA_H
 
-/* This platform uses the common S3C DMA API driver for PL330 */
-#include <plat/s3c-dma-pl330.h>
+/* This platform uses the common DMA API driver for PL330 */
+#include <plat/dma-pl330.h>
 
 #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 (file)
index 0000000..9dbe317
--- /dev/null
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) 2011 Samsung Electronics Co., Ltd.
+ *
+ * S5P series i2c hdmiphy helper definitions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef PLAT_S5P_I2C_HDMIPHY_H_
+#define PLAT_S5P_I2C_HDMIPHY_H_
+
+#define S5P_I2C_HDMIPHY_BUS_NUM                (8)
+
+#endif
index f8952f8f3757760029e7d95d077ed99cd6e119f4..62093b9339db57ef4b980284694b045ba02164b6 100644 (file)
 #define IRQ_2D                 IRQ_SPI(89)
 #define IRQ_PCIE               IRQ_SPI(90)
 
+#define IRQ_MIXER              IRQ_SPI(91)
+#define IRQ_HDMI               IRQ_SPI(92)
+#define IRQ_IIC_HDMIPHY                IRQ_SPI(93)
 #define IRQ_MFC                        IRQ_SPI(94)
+#define IRQ_SDO                        IRQ_SPI(95)
 
 #define IRQ_AUDIO_SS           IRQ_SPI(96)
 #define IRQ_I2S0               IRQ_SPI(97)
index 7073ac7308554fe77672898468b690cd356c71a4..1bea7d139bb0f3c0f38981658e78c7ccfdc009f0 100644 (file)
 
 #define EXYNOS4_PA_UART                        0x13800000
 
+#define EXYNOS4_PA_VP                  0x12C00000
+#define EXYNOS4_PA_MIXER               0x12C10000
+#define EXYNOS4_PA_SDO                 0x12C20000
+#define EXYNOS4_PA_HDMI                        0x12D00000
+#define EXYNOS4_PA_IIC_HDMIPHY         0x138E0000
+
 #define EXYNOS4_PA_IIC(x)              (0x13860000 + ((x) * 0x10000))
 
 #define EXYNOS4_PA_ADC                 0x13910000
 #define S5P_PA_TIMER                   EXYNOS4_PA_TIMER
 #define S5P_PA_EHCI                    EXYNOS4_PA_EHCI
 
+#define S5P_PA_SDO                     EXYNOS4_PA_SDO
+#define S5P_PA_VP                      EXYNOS4_PA_VP
+#define S5P_PA_MIXER                   EXYNOS4_PA_MIXER
+#define S5P_PA_HDMI                    EXYNOS4_PA_HDMI
+#define S5P_PA_IIC_HDMIPHY             EXYNOS4_PA_IIC_HDMIPHY
+
 #define SAMSUNG_PA_KEYPAD              EXYNOS4_PA_KEYPAD
 
 /* UART */
index 1df3b81f96e828a0d9a9d55456485a1254b91494..9d8da51e35caa794ff8d45405c789fa00d2e009d 100644 (file)
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
 */
+
+#ifndef __ASM_ARCH_PM_CORE_H
+#define __ASM_ARCH_PM_CORE_H __FILE__
+
 #include <mach/regs-pmu.h>
 
 static inline void s3c_pm_debug_init_uart(void)
@@ -53,7 +57,9 @@ static inline void s3c_pm_restored_gpios(void)
        /* nothing here yet */
 }
 
-static inline void s3c_pm_saved_gpios(void)
+static inline void samsung_pm_saved_gpios(void)
 {
        /* nothing here yet */
 }
+
+#endif /* __ASM_ARCH_PM_CORE_H */
index a952904b010ed989ccdc04d1b7fd29ab8dfc995c..632dd56301382ad0164972489495446ba0f2eabd 100644 (file)
@@ -13,6 +13,8 @@
 #ifndef __ASM_ARCH_PMU_H
 #define __ASM_ARCH_PMU_H __FILE__
 
+#define PMU_TABLE_END  NULL
+
 enum sys_powerdown {
        SYS_AFTR,
        SYS_LPA,
@@ -20,6 +22,11 @@ enum sys_powerdown {
        NUM_SYS_POWERDOWN,
 };
 
+struct exynos4_pmu_conf {
+       void __iomem *reg;
+       unsigned int val[NUM_SYS_POWERDOWN];
+};
+
 extern void exynos4_sys_powerdown_conf(enum sys_powerdown mode);
 
 #endif /* __ASM_ARCH_PMU_H */
index cdf9b47c303cea185e668f7c52e1c28cb5dac4fd..4fff8e938fecb8c2d839ee4990834229fd44df44 100644 (file)
 
 #define S5P_USE_STANDBY_WFI0                   (1 << 16)
 #define S5P_USE_STANDBY_WFI1                   (1 << 17)
+#define S5P_USE_STANDBYWFI_ISP_ARM             (1 << 18)
 #define S5P_USE_STANDBY_WFE0                   (1 << 24)
 #define S5P_USE_STANDBY_WFE1                   (1 << 25)
-#define S5P_USE_MASK                           ((0x3 << 16) | (0x3 << 24))
+#define S5P_USE_STANDBYWFE_ISP_ARM             (1 << 26)
 
 #define S5P_SWRESET                            S5P_PMUREG(0x0400)
 
 #define S5P_EINT_WAKEUP_MASK                   S5P_PMUREG(0x0604)
 #define S5P_WAKEUP_MASK                                S5P_PMUREG(0x0608)
 
-#define S5P_USBHOST_PHY_CONTROL                        S5P_PMUREG(0x0708)
-#define S5P_USBHOST_PHY_ENABLE                 (1 << 0)
+#define S5P_HDMI_PHY_CONTROL                   S5P_PMUREG(0x0700)
+#define S5P_HDMI_PHY_ENABLE                    (1 << 0)
+
+#define S5P_DAC_PHY_CONTROL                    S5P_PMUREG(0x070C)
+#define S5P_DAC_PHY_ENABLE                     (1 << 0)
 
 #define S5P_MIPI_DPHY_CONTROL(n)               S5P_PMUREG(0x0710 + (n) * 4)
 #define S5P_MIPI_DPHY_ENABLE                   (1 << 0)
 #define S5P_MIPI_DPHY_SRESETN                  (1 << 1)
 #define S5P_MIPI_DPHY_MRESETN                  (1 << 2)
 
-#define S5P_PMU_SATA_PHY_CONTROL               S5P_PMUREG(0x0720)
 #define S5P_INFORM0                            S5P_PMUREG(0x0800)
 #define S5P_INFORM1                            S5P_PMUREG(0x0804)
 #define S5P_INFORM2                            S5P_PMUREG(0x0808)
@@ -76,7 +79,6 @@
 #define S5P_CMU_CLKSTOP_MFC_LOWPWR             S5P_PMUREG(0x1148)
 #define S5P_CMU_CLKSTOP_G3D_LOWPWR             S5P_PMUREG(0x114C)
 #define S5P_CMU_CLKSTOP_LCD0_LOWPWR            S5P_PMUREG(0x1150)
-#define S5P_CMU_CLKSTOP_LCD1_LOWPWR            S5P_PMUREG(0x1154)
 #define S5P_CMU_CLKSTOP_MAUDIO_LOWPWR          S5P_PMUREG(0x1158)
 #define S5P_CMU_CLKSTOP_GPS_LOWPWR             S5P_PMUREG(0x115C)
 #define S5P_CMU_RESET_CAM_LOWPWR               S5P_PMUREG(0x1160)
@@ -84,7 +86,6 @@
 #define S5P_CMU_RESET_MFC_LOWPWR               S5P_PMUREG(0x1168)
 #define S5P_CMU_RESET_G3D_LOWPWR               S5P_PMUREG(0x116C)
 #define S5P_CMU_RESET_LCD0_LOWPWR              S5P_PMUREG(0x1170)
-#define S5P_CMU_RESET_LCD1_LOWPWR              S5P_PMUREG(0x1174)
 #define S5P_CMU_RESET_MAUDIO_LOWPWR            S5P_PMUREG(0x1178)
 #define S5P_CMU_RESET_GPS_LOWPWR               S5P_PMUREG(0x117C)
 #define S5P_TOP_BUS_LOWPWR                     S5P_PMUREG(0x1180)
 #define S5P_TOP_PWR_LOWPWR                     S5P_PMUREG(0x1188)
 #define S5P_LOGIC_RESET_LOWPWR                 S5P_PMUREG(0x11A0)
 #define S5P_ONENAND_MEM_LOWPWR                 S5P_PMUREG(0x11C0)
-#define S5P_MODIMIF_MEM_LOWPWR                 S5P_PMUREG(0x11C4)
 #define S5P_G2D_ACP_MEM_LOWPWR                 S5P_PMUREG(0x11C8)
 #define S5P_USBOTG_MEM_LOWPWR                  S5P_PMUREG(0x11CC)
 #define S5P_HSMMC_MEM_LOWPWR                   S5P_PMUREG(0x11D0)
 #define S5P_CSSYS_MEM_LOWPWR                   S5P_PMUREG(0x11D4)
 #define S5P_SECSS_MEM_LOWPWR                   S5P_PMUREG(0x11D8)
-#define S5P_PCIE_MEM_LOWPWR                    S5P_PMUREG(0x11E0)
-#define S5P_SATA_MEM_LOWPWR                    S5P_PMUREG(0x11E4)
 #define S5P_PAD_RETENTION_DRAM_LOWPWR          S5P_PMUREG(0x1200)
 #define S5P_PAD_RETENTION_MAUDIO_LOWPWR                S5P_PMUREG(0x1204)
 #define S5P_PAD_RETENTION_GPIO_LOWPWR          S5P_PMUREG(0x1220)
 #define S5P_MFC_LOWPWR                         S5P_PMUREG(0x1388)
 #define S5P_G3D_LOWPWR                         S5P_PMUREG(0x138C)
 #define S5P_LCD0_LOWPWR                                S5P_PMUREG(0x1390)
-#define S5P_LCD1_LOWPWR                                S5P_PMUREG(0x1394)
 #define S5P_MAUDIO_LOWPWR                      S5P_PMUREG(0x1398)
 #define S5P_GPS_LOWPWR                         S5P_PMUREG(0x139C)
 #define S5P_GPS_ALIVE_LOWPWR                   S5P_PMUREG(0x13A0)
 #define S5P_PMU_MFC_CONF                       S5P_PMUREG(0x3C40)
 #define S5P_PMU_G3D_CONF                       S5P_PMUREG(0x3C60)
 #define S5P_PMU_LCD0_CONF                      S5P_PMUREG(0x3C80)
-#define S5P_PMU_LCD1_CONF                      S5P_PMUREG(0x3CA0)
 #define S5P_PMU_GPS_CONF                       S5P_PMUREG(0x3CE0)
 
 #define S5P_PMU_SATA_PHY_CONTROL_EN            0x1
 
 #define S5P_CHECK_SLEEP                                0x00000BAD
 
+/* Only for EXYNOS4210 */
+#define S5P_USBHOST_PHY_CONTROL                S5P_PMUREG(0x0708)
+#define S5P_USBHOST_PHY_ENABLE         (1 << 0)
+
+#define S5P_PMU_SATA_PHY_CONTROL       S5P_PMUREG(0x0720)
+
+#define S5P_CMU_CLKSTOP_LCD1_LOWPWR    S5P_PMUREG(0x1154)
+#define S5P_CMU_RESET_LCD1_LOWPWR      S5P_PMUREG(0x1174)
+#define S5P_MODIMIF_MEM_LOWPWR         S5P_PMUREG(0x11C4)
+#define S5P_PCIE_MEM_LOWPWR            S5P_PMUREG(0x11E0)
+#define S5P_SATA_MEM_LOWPWR            S5P_PMUREG(0x11E4)
+#define S5P_LCD1_LOWPWR                        S5P_PMUREG(0x1394)
+
+#define S5P_PMU_LCD1_CONF              S5P_PMUREG(0x3CA0)
+
+/* Only for EXYNOS4212 */
+#define S5P_ISP_ARM_LOWPWR                     S5P_PMUREG(0x1050)
+#define S5P_DIS_IRQ_ISP_ARM_LOCAL_LOWPWR       S5P_PMUREG(0x1054)
+#define S5P_DIS_IRQ_ISP_ARM_CENTRAL_LOWPWR     S5P_PMUREG(0x1058)
+#define S5P_CMU_ACLKSTOP_COREBLK_LOWPWR                S5P_PMUREG(0x1110)
+#define S5P_CMU_SCLKSTOP_COREBLK_LOWPWR                S5P_PMUREG(0x1114)
+#define S5P_CMU_RESET_COREBLK_LOWPWR           S5P_PMUREG(0x111C)
+#define S5P_MPLLUSER_SYSCLK_LOWPWR             S5P_PMUREG(0x1130)
+#define S5P_CMU_CLKSTOP_ISP_LOWPWR             S5P_PMUREG(0x1154)
+#define S5P_CMU_RESET_ISP_LOWPWR               S5P_PMUREG(0x1174)
+#define S5P_TOP_BUS_COREBLK_LOWPWR             S5P_PMUREG(0x1190)
+#define S5P_TOP_RETENTION_COREBLK_LOWPWR       S5P_PMUREG(0x1194)
+#define S5P_TOP_PWR_COREBLK_LOWPWR             S5P_PMUREG(0x1198)
+#define S5P_OSCCLK_GATE_LOWPWR                 S5P_PMUREG(0x11A4)
+#define S5P_LOGIC_RESET_COREBLK_LOWPWR         S5P_PMUREG(0x11B0)
+#define S5P_OSCCLK_GATE_COREBLK_LOWPWR         S5P_PMUREG(0x11B4)
+#define S5P_HSI_MEM_LOWPWR                     S5P_PMUREG(0x11C4)
+#define S5P_ROTATOR_MEM_LOWPWR                 S5P_PMUREG(0x11DC)
+#define S5P_PAD_RETENTION_GPIO_COREBLK_LOWPWR  S5P_PMUREG(0x123C)
+#define S5P_PAD_ISOLATION_COREBLK_LOWPWR       S5P_PMUREG(0x1250)
+#define S5P_GPIO_MODE_COREBLK_LOWPWR           S5P_PMUREG(0x1320)
+#define S5P_TOP_ASB_RESET_LOWPWR               S5P_PMUREG(0x1344)
+#define S5P_TOP_ASB_ISOLATION_LOWPWR           S5P_PMUREG(0x1348)
+#define S5P_ISP_LOWPWR                         S5P_PMUREG(0x1394)
+#define S5P_DRAM_FREQ_DOWN_LOWPWR              S5P_PMUREG(0x13B0)
+#define S5P_DDRPHY_DLLOFF_LOWPWR               S5P_PMUREG(0x13B4)
+#define S5P_CMU_SYSCLK_ISP_LOWPWR              S5P_PMUREG(0x13B8)
+#define S5P_CMU_SYSCLK_GPS_LOWPWR              S5P_PMUREG(0x13BC)
+#define S5P_LPDDR_PHY_DLL_LOCK_LOWPWR          S5P_PMUREG(0x13C0)
+
+#define S5P_ARM_L2_0_OPTION                    S5P_PMUREG(0x2608)
+#define S5P_ARM_L2_1_OPTION                    S5P_PMUREG(0x2628)
+#define S5P_ONENAND_MEM_OPTION                 S5P_PMUREG(0x2E08)
+#define S5P_HSI_MEM_OPTION                     S5P_PMUREG(0x2E28)
+#define S5P_G2D_ACP_MEM_OPTION                 S5P_PMUREG(0x2E48)
+#define S5P_USBOTG_MEM_OPTION                  S5P_PMUREG(0x2E68)
+#define S5P_HSMMC_MEM_OPTION                   S5P_PMUREG(0x2E88)
+#define S5P_CSSYS_MEM_OPTION                   S5P_PMUREG(0x2EA8)
+#define S5P_SECSS_MEM_OPTION                   S5P_PMUREG(0x2EC8)
+#define S5P_ROTATOR_MEM_OPTION                 S5P_PMUREG(0x2F48)
+
 #endif /* __ASM_ARCH_REGS_PMU_H */
index 43be71b799cbce337cc6174badd8c035c44b912b..bbd13f454151bcee0bbbd1a732df19693cafedf2 100644 (file)
 #include <asm/mach-types.h>
 
 #include <plat/adc.h>
+#include <plat/regs-fb-v4.h>
 #include <plat/regs-serial.h>
 #include <plat/exynos4.h>
 #include <plat/cpu.h>
 #include <plat/devs.h>
+#include <plat/fb.h>
 #include <plat/sdhci.h>
 #include <plat/ehci.h>
 #include <plat/clock.h>
@@ -199,6 +201,33 @@ static struct platform_device nuri_gpio_keys = {
        },
 };
 
+/* Frame Buffer */
+static struct s3c_fb_pd_win nuri_fb_win0 = {
+       .win_mode = {
+               .left_margin    = 64,
+               .right_margin   = 16,
+               .upper_margin   = 64,
+               .lower_margin   = 1,
+               .hsync_len      = 48,
+               .vsync_len      = 3,
+               .xres           = 1280,
+               .yres           = 800,
+               .refresh        = 60,
+       },
+       .max_bpp        = 24,
+       .default_bpp    = 16,
+       .virtual_x      = 1280,
+       .virtual_y      = 800,
+};
+
+static struct s3c_fb_platdata nuri_fb_pdata __initdata = {
+       .win[0]         = &nuri_fb_win0,
+       .vidcon0        = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB |
+                         VIDCON0_CLKSEL_LCD,
+       .vidcon1        = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC,
+       .setup_gpio     = exynos4_fimd0_gpio_setup_24bpp,
+};
+
 static void nuri_lcd_power_on(struct plat_lcd_data *pd, unsigned int power)
 {
        int gpio = EXYNOS4_GPE1(5);
@@ -1092,6 +1121,7 @@ static struct platform_device *nuri_devices[] __initdata = {
        /* Samsung Platform Devices */
        &s3c_device_i2c5, /* PMIC should initialize first */
        &emmc_fixed_voltage,
+       &s5p_device_fimd0,
        &s3c_device_hsmmc0,
        &s3c_device_hsmmc2,
        &s3c_device_hsmmc3,
@@ -1106,6 +1136,7 @@ static struct platform_device *nuri_devices[] __initdata = {
        &s5p_device_mfc_l,
        &s5p_device_mfc_r,
        &exynos4_device_pd[PD_MFC],
+       &exynos4_device_pd[PD_LCD0],
 
        /* NURI Devices */
        &nuri_gpio_keys,
@@ -1142,12 +1173,15 @@ static void __init nuri_machine_init(void)
        i2c9_devs[I2C9_MAX17042].irq = gpio_to_irq(EXYNOS4_GPX2(3));
        i2c_register_board_info(9, i2c9_devs, ARRAY_SIZE(i2c9_devs));
 
+       s5p_fimd0_set_platdata(&nuri_fb_pdata);
+
        nuri_ehci_init();
        clk_xusbxti.rate = 24000000;
 
        /* Last */
        platform_add_devices(nuri_devices, ARRAY_SIZE(nuri_devices));
        s5p_device_mfc.dev.parent = &exynos4_device_pd[PD_MFC].dev;
+       s5p_device_fimd0.dev.parent = &exynos4_device_pd[PD_LCD0].dev;
 }
 
 MACHINE_START(NURI, "NURI")
index ed59f86001acd16e609025493104ca0630bd9e17..18909cf6c07d5b3b59be678d43719e6565819485 100644 (file)
 #include <linux/platform_device.h>
 #include <linux/io.h>
 #include <linux/input.h>
+#include <linux/pwm_backlight.h>
+#include <linux/gpio_keys.h>
+#include <linux/i2c.h>
+#include <linux/regulator/machine.h>
+#include <linux/mfd/max8997.h>
+#include <linux/lcd.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach-types.h>
 
+#include <video/platform_lcd.h>
+
 #include <plat/regs-serial.h>
+#include <plat/regs-fb-v4.h>
 #include <plat/exynos4.h>
 #include <plat/cpu.h>
 #include <plat/devs.h>
 #include <plat/sdhci.h>
 #include <plat/iic.h>
+#include <plat/ehci.h>
+#include <plat/clock.h>
+#include <plat/gpio-cfg.h>
+#include <plat/backlight.h>
+#include <plat/pd.h>
+#include <plat/fb.h>
 
 #include <mach/map.h>
 
@@ -72,19 +87,543 @@ static struct s3c2410_uartcfg origen_uartcfgs[] __initdata = {
        },
 };
 
+static struct regulator_consumer_supply __initdata ldo3_consumer[] = {
+       REGULATOR_SUPPLY("vdd11", "s5p-mipi-csis.0"), /* MIPI */
+};
+static struct regulator_consumer_supply __initdata ldo6_consumer[] = {
+       REGULATOR_SUPPLY("vdd18", "s5p-mipi-csis.0"), /* MIPI */
+};
+static struct regulator_consumer_supply __initdata ldo7_consumer[] = {
+       REGULATOR_SUPPLY("avdd", "alc5625"), /* Realtek ALC5625 */
+};
+static struct regulator_consumer_supply __initdata ldo8_consumer[] = {
+       REGULATOR_SUPPLY("vdd", "s5p-adc"), /* ADC */
+};
+static struct regulator_consumer_supply __initdata ldo9_consumer[] = {
+       REGULATOR_SUPPLY("dvdd", "swb-a31"), /* AR6003 WLAN & CSR 8810 BT */
+};
+static struct regulator_consumer_supply __initdata ldo11_consumer[] = {
+       REGULATOR_SUPPLY("dvdd", "alc5625"), /* Realtek ALC5625 */
+};
+static struct regulator_consumer_supply __initdata ldo14_consumer[] = {
+       REGULATOR_SUPPLY("avdd18", "swb-a31"), /* AR6003 WLAN & CSR 8810 BT */
+};
+static struct regulator_consumer_supply __initdata ldo17_consumer[] = {
+       REGULATOR_SUPPLY("vdd33", "swb-a31"), /* AR6003 WLAN & CSR 8810 BT */
+};
+static struct regulator_consumer_supply __initdata buck1_consumer[] = {
+       REGULATOR_SUPPLY("vdd_arm", NULL), /* CPUFREQ */
+};
+static struct regulator_consumer_supply __initdata buck2_consumer[] = {
+       REGULATOR_SUPPLY("vdd_int", NULL), /* CPUFREQ */
+};
+static struct regulator_consumer_supply __initdata buck3_consumer[] = {
+       REGULATOR_SUPPLY("vdd_g3d", "mali_drm"), /* G3D */
+};
+static struct regulator_consumer_supply __initdata buck7_consumer[] = {
+       REGULATOR_SUPPLY("vcc", "platform-lcd"), /* LCD */
+};
+
+static struct regulator_init_data __initdata max8997_ldo1_data = {
+       .constraints    = {
+               .name           = "VDD_ABB_3.3V",
+               .min_uV         = 3300000,
+               .max_uV         = 3300000,
+               .apply_uV       = 1,
+               .state_mem      = {
+                       .disabled       = 1,
+               },
+       },
+};
+
+static struct regulator_init_data __initdata max8997_ldo2_data = {
+       .constraints    = {
+               .name           = "VDD_ALIVE_1.1V",
+               .min_uV         = 1100000,
+               .max_uV         = 1100000,
+               .apply_uV       = 1,
+               .always_on      = 1,
+               .state_mem      = {
+                       .enabled        = 1,
+               },
+       },
+};
+
+static struct regulator_init_data __initdata max8997_ldo3_data = {
+       .constraints    = {
+               .name           = "VMIPI_1.1V",
+               .min_uV         = 1100000,
+               .max_uV         = 1100000,
+               .apply_uV       = 1,
+               .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+               .state_mem      = {
+                       .disabled       = 1,
+               },
+       },
+       .num_consumer_supplies  = ARRAY_SIZE(ldo3_consumer),
+       .consumer_supplies      = ldo3_consumer,
+};
+
+static struct regulator_init_data __initdata max8997_ldo4_data = {
+       .constraints    = {
+               .name           = "VDD_RTC_1.8V",
+               .min_uV         = 1800000,
+               .max_uV         = 1800000,
+               .apply_uV       = 1,
+               .always_on      = 1,
+               .state_mem      = {
+                       .disabled       = 1,
+               },
+       },
+};
+
+static struct regulator_init_data __initdata max8997_ldo6_data = {
+       .constraints    = {
+               .name           = "VMIPI_1.8V",
+               .min_uV         = 1800000,
+               .max_uV         = 1800000,
+               .apply_uV       = 1,
+               .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+               .state_mem      = {
+                       .disabled       = 1,
+               },
+       },
+       .num_consumer_supplies  = ARRAY_SIZE(ldo6_consumer),
+       .consumer_supplies      = ldo6_consumer,
+};
+
+static struct regulator_init_data __initdata max8997_ldo7_data = {
+       .constraints    = {
+               .name           = "VDD_AUD_1.8V",
+               .min_uV         = 1800000,
+               .max_uV         = 1800000,
+               .apply_uV       = 1,
+               .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+               .state_mem      = {
+                       .disabled       = 1,
+               },
+       },
+       .num_consumer_supplies  = ARRAY_SIZE(ldo7_consumer),
+       .consumer_supplies      = ldo7_consumer,
+};
+
+static struct regulator_init_data __initdata max8997_ldo8_data = {
+       .constraints    = {
+               .name           = "VADC_3.3V",
+               .min_uV         = 3300000,
+               .max_uV         = 3300000,
+               .apply_uV       = 1,
+               .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+               .state_mem      = {
+                       .disabled       = 1,
+               },
+       },
+       .num_consumer_supplies  = ARRAY_SIZE(ldo8_consumer),
+       .consumer_supplies      = ldo8_consumer,
+};
+
+static struct regulator_init_data __initdata max8997_ldo9_data = {
+       .constraints    = {
+               .name           = "DVDD_SWB_2.8V",
+               .min_uV         = 2800000,
+               .max_uV         = 2800000,
+               .apply_uV       = 1,
+               .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+               .state_mem      = {
+                       .disabled       = 1,
+               },
+       },
+       .num_consumer_supplies  = ARRAY_SIZE(ldo9_consumer),
+       .consumer_supplies      = ldo9_consumer,
+};
+
+static struct regulator_init_data __initdata max8997_ldo10_data = {
+       .constraints    = {
+               .name           = "VDD_PLL_1.1V",
+               .min_uV         = 1100000,
+               .max_uV         = 1100000,
+               .apply_uV       = 1,
+               .always_on      = 1,
+               .state_mem      = {
+                       .disabled       = 1,
+               },
+       },
+};
+
+static struct regulator_init_data __initdata max8997_ldo11_data = {
+       .constraints    = {
+               .name           = "VDD_AUD_3V",
+               .min_uV         = 3000000,
+               .max_uV         = 3000000,
+               .apply_uV       = 1,
+               .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+               .state_mem      = {
+                       .disabled       = 1,
+               },
+       },
+       .num_consumer_supplies  = ARRAY_SIZE(ldo11_consumer),
+       .consumer_supplies      = ldo11_consumer,
+};
+
+static struct regulator_init_data __initdata max8997_ldo14_data = {
+       .constraints    = {
+               .name           = "AVDD18_SWB_1.8V",
+               .min_uV         = 1800000,
+               .max_uV         = 1800000,
+               .apply_uV       = 1,
+               .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+               .state_mem      = {
+                       .disabled       = 1,
+               },
+       },
+       .num_consumer_supplies  = ARRAY_SIZE(ldo14_consumer),
+       .consumer_supplies      = ldo14_consumer,
+};
+
+static struct regulator_init_data __initdata max8997_ldo17_data = {
+       .constraints    = {
+               .name           = "VDD_SWB_3.3V",
+               .min_uV         = 3300000,
+               .max_uV         = 3300000,
+               .apply_uV       = 1,
+               .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+               .state_mem      = {
+                       .disabled       = 1,
+               },
+       },
+       .num_consumer_supplies  = ARRAY_SIZE(ldo17_consumer),
+       .consumer_supplies      = ldo17_consumer,
+};
+
+static struct regulator_init_data __initdata max8997_ldo21_data = {
+       .constraints    = {
+               .name           = "VDD_MIF_1.2V",
+               .min_uV         = 1200000,
+               .max_uV         = 1200000,
+               .apply_uV       = 1,
+               .always_on      = 1,
+               .state_mem      = {
+                       .disabled       = 1,
+               },
+       },
+};
+
+static struct regulator_init_data __initdata max8997_buck1_data = {
+       .constraints    = {
+               .name           = "VDD_ARM_1.2V",
+               .min_uV         = 950000,
+               .max_uV         = 1350000,
+               .always_on      = 1,
+               .boot_on        = 1,
+               .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+               .state_mem      = {
+                       .disabled       = 1,
+               },
+       },
+       .num_consumer_supplies  = ARRAY_SIZE(buck1_consumer),
+       .consumer_supplies      = buck1_consumer,
+};
+
+static struct regulator_init_data __initdata max8997_buck2_data = {
+       .constraints    = {
+               .name           = "VDD_INT_1.1V",
+               .min_uV         = 900000,
+               .max_uV         = 1100000,
+               .always_on      = 1,
+               .boot_on        = 1,
+               .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+               .state_mem      = {
+                       .disabled       = 1,
+               },
+       },
+       .num_consumer_supplies  = ARRAY_SIZE(buck2_consumer),
+       .consumer_supplies      = buck2_consumer,
+};
+
+static struct regulator_init_data __initdata max8997_buck3_data = {
+       .constraints    = {
+               .name           = "VDD_G3D_1.1V",
+               .min_uV         = 900000,
+               .max_uV         = 1100000,
+               .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+                                       REGULATOR_CHANGE_STATUS,
+               .state_mem      = {
+                       .disabled       = 1,
+               },
+       },
+       .num_consumer_supplies  = ARRAY_SIZE(buck3_consumer),
+       .consumer_supplies      = buck3_consumer,
+};
+
+static struct regulator_init_data __initdata max8997_buck5_data = {
+       .constraints    = {
+               .name           = "VDDQ_M1M2_1.2V",
+               .min_uV         = 1200000,
+               .max_uV         = 1200000,
+               .apply_uV       = 1,
+               .always_on      = 1,
+               .state_mem      = {
+                       .disabled       = 1,
+               },
+       },
+};
+
+static struct regulator_init_data __initdata max8997_buck7_data = {
+       .constraints    = {
+               .name           = "VDD_LCD_3.3V",
+               .min_uV         = 3300000,
+               .max_uV         = 3300000,
+               .boot_on        = 1,
+               .apply_uV       = 1,
+               .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+               .state_mem      = {
+                       .disabled       = 1
+               },
+       },
+       .num_consumer_supplies  = ARRAY_SIZE(buck7_consumer),
+       .consumer_supplies      = buck7_consumer,
+};
+
+static struct max8997_regulator_data __initdata origen_max8997_regulators[] = {
+       { MAX8997_LDO1,         &max8997_ldo1_data },
+       { MAX8997_LDO2,         &max8997_ldo2_data },
+       { MAX8997_LDO3,         &max8997_ldo3_data },
+       { MAX8997_LDO4,         &max8997_ldo4_data },
+       { MAX8997_LDO6,         &max8997_ldo6_data },
+       { MAX8997_LDO7,         &max8997_ldo7_data },
+       { MAX8997_LDO8,         &max8997_ldo8_data },
+       { MAX8997_LDO9,         &max8997_ldo9_data },
+       { MAX8997_LDO10,        &max8997_ldo10_data },
+       { MAX8997_LDO11,        &max8997_ldo11_data },
+       { MAX8997_LDO14,        &max8997_ldo14_data },
+       { MAX8997_LDO17,        &max8997_ldo17_data },
+       { MAX8997_LDO21,        &max8997_ldo21_data },
+       { MAX8997_BUCK1,        &max8997_buck1_data },
+       { MAX8997_BUCK2,        &max8997_buck2_data },
+       { MAX8997_BUCK3,        &max8997_buck3_data },
+       { MAX8997_BUCK5,        &max8997_buck5_data },
+       { MAX8997_BUCK7,        &max8997_buck7_data },
+};
+
+struct max8997_platform_data __initdata origen_max8997_pdata = {
+       .num_regulators = ARRAY_SIZE(origen_max8997_regulators),
+       .regulators     = origen_max8997_regulators,
+
+       .wakeup = true,
+       .buck1_gpiodvs  = false,
+       .buck2_gpiodvs  = false,
+       .buck5_gpiodvs  = false,
+       .irq_base       = IRQ_GPIO_END + 1,
+
+       .ignore_gpiodvs_side_effect = true,
+       .buck125_default_idx = 0x0,
+
+       .buck125_gpios[0]       = EXYNOS4_GPX0(0),
+       .buck125_gpios[1]       = EXYNOS4_GPX0(1),
+       .buck125_gpios[2]       = EXYNOS4_GPX0(2),
+
+       .buck1_voltage[0]       = 1350000,
+       .buck1_voltage[1]       = 1300000,
+       .buck1_voltage[2]       = 1250000,
+       .buck1_voltage[3]       = 1200000,
+       .buck1_voltage[4]       = 1150000,
+       .buck1_voltage[5]       = 1100000,
+       .buck1_voltage[6]       = 1000000,
+       .buck1_voltage[7]       = 950000,
+
+       .buck2_voltage[0]       = 1100000,
+       .buck2_voltage[1]       = 1100000,
+       .buck2_voltage[2]       = 1100000,
+       .buck2_voltage[3]       = 1100000,
+       .buck2_voltage[4]       = 1000000,
+       .buck2_voltage[5]       = 1000000,
+       .buck2_voltage[6]       = 1000000,
+       .buck2_voltage[7]       = 1000000,
+
+       .buck5_voltage[0]       = 1200000,
+       .buck5_voltage[1]       = 1200000,
+       .buck5_voltage[2]       = 1200000,
+       .buck5_voltage[3]       = 1200000,
+       .buck5_voltage[4]       = 1200000,
+       .buck5_voltage[5]       = 1200000,
+       .buck5_voltage[6]       = 1200000,
+       .buck5_voltage[7]       = 1200000,
+};
+
+/* I2C0 */
+static struct i2c_board_info i2c0_devs[] __initdata = {
+       {
+               I2C_BOARD_INFO("max8997", (0xCC >> 1)),
+               .platform_data  = &origen_max8997_pdata,
+               .irq            = IRQ_EINT(4),
+       },
+};
+
+static struct s3c_sdhci_platdata origen_hsmmc0_pdata __initdata = {
+       .cd_type                = S3C_SDHCI_CD_INTERNAL,
+       .clk_type               = S3C_SDHCI_CLK_DIV_EXTERNAL,
+};
+
 static struct s3c_sdhci_platdata origen_hsmmc2_pdata __initdata = {
-       .cd_type                = S3C_SDHCI_CD_GPIO,
-       .ext_cd_gpio            = EXYNOS4_GPK2(2),
-       .ext_cd_gpio_invert     = 1,
+       .cd_type                = S3C_SDHCI_CD_INTERNAL,
        .clk_type               = S3C_SDHCI_CLK_DIV_EXTERNAL,
 };
 
+/* USB EHCI */
+static struct s5p_ehci_platdata origen_ehci_pdata;
+
+static void __init origen_ehci_init(void)
+{
+       struct s5p_ehci_platdata *pdata = &origen_ehci_pdata;
+
+       s5p_ehci_set_platdata(pdata);
+}
+
+static struct gpio_keys_button origen_gpio_keys_table[] = {
+       {
+               .code                   = KEY_MENU,
+               .gpio                   = EXYNOS4_GPX1(5),
+               .desc                   = "gpio-keys: KEY_MENU",
+               .type                   = EV_KEY,
+               .active_low             = 1,
+               .wakeup                 = 1,
+               .debounce_interval      = 1,
+       }, {
+               .code                   = KEY_HOME,
+               .gpio                   = EXYNOS4_GPX1(6),
+               .desc                   = "gpio-keys: KEY_HOME",
+               .type                   = EV_KEY,
+               .active_low             = 1,
+               .wakeup                 = 1,
+               .debounce_interval      = 1,
+       }, {
+               .code                   = KEY_BACK,
+               .gpio                   = EXYNOS4_GPX1(7),
+               .desc                   = "gpio-keys: KEY_BACK",
+               .type                   = EV_KEY,
+               .active_low             = 1,
+               .wakeup                 = 1,
+               .debounce_interval      = 1,
+       }, {
+               .code                   = KEY_UP,
+               .gpio                   = EXYNOS4_GPX2(0),
+               .desc                   = "gpio-keys: KEY_UP",
+               .type                   = EV_KEY,
+               .active_low             = 1,
+               .wakeup                 = 1,
+               .debounce_interval      = 1,
+       }, {
+               .code                   = KEY_DOWN,
+               .gpio                   = EXYNOS4_GPX2(1),
+               .desc                   = "gpio-keys: KEY_DOWN",
+               .type                   = EV_KEY,
+               .active_low             = 1,
+               .wakeup                 = 1,
+               .debounce_interval      = 1,
+       },
+};
+
+static struct gpio_keys_platform_data origen_gpio_keys_data = {
+       .buttons        = origen_gpio_keys_table,
+       .nbuttons       = ARRAY_SIZE(origen_gpio_keys_table),
+};
+
+static struct platform_device origen_device_gpiokeys = {
+       .name           = "gpio-keys",
+       .dev            = {
+               .platform_data  = &origen_gpio_keys_data,
+       },
+};
+
+static void lcd_hv070wsa_set_power(struct plat_lcd_data *pd, unsigned int power)
+{
+       int ret;
+
+       if (power)
+               ret = gpio_request_one(EXYNOS4_GPE3(4),
+                                       GPIOF_OUT_INIT_HIGH, "GPE3_4");
+       else
+               ret = gpio_request_one(EXYNOS4_GPE3(4),
+                                       GPIOF_OUT_INIT_LOW, "GPE3_4");
+
+       gpio_free(EXYNOS4_GPE3(4));
+
+       if (ret)
+               pr_err("failed to request gpio for LCD power: %d\n", ret);
+}
+
+static struct plat_lcd_data origen_lcd_hv070wsa_data = {
+       .set_power = lcd_hv070wsa_set_power,
+};
+
+static struct platform_device origen_lcd_hv070wsa = {
+       .name                   = "platform-lcd",
+       .dev.parent             = &s5p_device_fimd0.dev,
+       .dev.platform_data      = &origen_lcd_hv070wsa_data,
+};
+
+static struct s3c_fb_pd_win origen_fb_win0 = {
+       .win_mode = {
+               .left_margin    = 64,
+               .right_margin   = 16,
+               .upper_margin   = 64,
+               .lower_margin   = 16,
+               .hsync_len      = 48,
+               .vsync_len      = 3,
+               .xres           = 1024,
+               .yres           = 600,
+       },
+       .max_bpp                = 32,
+       .default_bpp            = 24,
+};
+
+static struct s3c_fb_platdata origen_lcd_pdata __initdata = {
+       .win[0]         = &origen_fb_win0,
+       .vidcon0        = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB,
+       .vidcon1        = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC,
+       .setup_gpio     = exynos4_fimd0_gpio_setup_24bpp,
+};
+
 static struct platform_device *origen_devices[] __initdata = {
        &s3c_device_hsmmc2,
+       &s3c_device_hsmmc0,
+       &s3c_device_i2c0,
        &s3c_device_rtc,
        &s3c_device_wdt,
+       &s5p_device_ehci,
+       &s5p_device_fimc0,
+       &s5p_device_fimc1,
+       &s5p_device_fimc2,
+       &s5p_device_fimc3,
+       &s5p_device_fimd0,
+       &s5p_device_hdmi,
+       &s5p_device_i2c_hdmiphy,
+       &s5p_device_mixer,
+       &exynos4_device_pd[PD_LCD0],
+       &exynos4_device_pd[PD_TV],
+       &origen_device_gpiokeys,
+       &origen_lcd_hv070wsa,
+};
+
+/* LCD Backlight data */
+static struct samsung_bl_gpio_info origen_bl_gpio_info = {
+       .no             = EXYNOS4_GPD0(0),
+       .func           = S3C_GPIO_SFN(2),
 };
 
+static struct platform_pwm_backlight_data origen_bl_data = {
+       .pwm_id         = 0,
+       .pwm_period_ns  = 1000,
+};
+
+static void s5p_tv_setup(void)
+{
+       /* Direct HPD to HDMI chip */
+       gpio_request_one(EXYNOS4_GPX3(7), GPIOF_IN, "hpd-plug");
+       s3c_gpio_cfgpin(EXYNOS4_GPX3(7), S3C_GPIO_SFN(0x3));
+       s3c_gpio_setpull(EXYNOS4_GPX3(7), S3C_GPIO_PULL_NONE);
+}
+
 static void __init origen_map_io(void)
 {
        s5p_init_io(NULL, 0, S5P_VA_CHIPID);
@@ -92,10 +631,42 @@ static void __init origen_map_io(void)
        s3c24xx_init_uarts(origen_uartcfgs, ARRAY_SIZE(origen_uartcfgs));
 }
 
+static void __init origen_power_init(void)
+{
+       gpio_request(EXYNOS4_GPX0(4), "PMIC_IRQ");
+       s3c_gpio_cfgpin(EXYNOS4_GPX0(4), S3C_GPIO_SFN(0xf));
+       s3c_gpio_setpull(EXYNOS4_GPX0(4), S3C_GPIO_PULL_NONE);
+}
+
 static void __init origen_machine_init(void)
 {
+       origen_power_init();
+
+       s3c_i2c0_set_platdata(NULL);
+       i2c_register_board_info(0, i2c0_devs, ARRAY_SIZE(i2c0_devs));
+
+       /*
+        * Since sdhci instance 2 can contain a bootable media,
+        * sdhci instance 0 is registered after instance 2.
+        */
        s3c_sdhci2_set_platdata(&origen_hsmmc2_pdata);
+       s3c_sdhci0_set_platdata(&origen_hsmmc0_pdata);
+
+       origen_ehci_init();
+       clk_xusbxti.rate = 24000000;
+
+       s5p_tv_setup();
+       s5p_i2c_hdmiphy_set_platdata(NULL);
+
+       s5p_fimd0_set_platdata(&origen_lcd_pdata);
+
        platform_add_devices(origen_devices, ARRAY_SIZE(origen_devices));
+       s5p_device_fimd0.dev.parent = &exynos4_device_pd[PD_LCD0].dev;
+
+       s5p_device_hdmi.dev.parent = &exynos4_device_pd[PD_TV].dev;
+       s5p_device_mixer.dev.parent = &exynos4_device_pd[PD_TV].dev;
+
+       samsung_bl_set(&origen_bl_gpio_info, &origen_bl_data);
 }
 
 MACHINE_START(ORIGEN, "ORIGEN")
index a16eb569a3e69e06a161d57526629cf4ad66c69b..35a763e9a659b98c764dc2c6adfe2a4be0774349 100644 (file)
@@ -37,6 +37,9 @@
 #include <plat/pd.h>
 #include <plat/gpio-cfg.h>
 #include <plat/backlight.h>
+#include <plat/mfc.h>
+#include <plat/ehci.h>
+#include <plat/clock.h>
 
 #include <mach/map.h>
 
@@ -232,17 +235,36 @@ static struct i2c_board_info i2c_devs1[] __initdata = {
        {I2C_BOARD_INFO("wm8994", 0x1a),},
 };
 
+/* USB EHCI */
+static struct s5p_ehci_platdata smdkv310_ehci_pdata;
+
+static void __init smdkv310_ehci_init(void)
+{
+       struct s5p_ehci_platdata *pdata = &smdkv310_ehci_pdata;
+
+       s5p_ehci_set_platdata(pdata);
+}
+
 static struct platform_device *smdkv310_devices[] __initdata = {
        &s3c_device_hsmmc0,
        &s3c_device_hsmmc1,
        &s3c_device_hsmmc2,
        &s3c_device_hsmmc3,
        &s3c_device_i2c1,
+       &s5p_device_i2c_hdmiphy,
        &s3c_device_rtc,
        &s3c_device_wdt,
+       &s5p_device_ehci,
+       &s5p_device_fimc0,
+       &s5p_device_fimc1,
+       &s5p_device_fimc2,
+       &s5p_device_fimc3,
        &exynos4_device_ac97,
        &exynos4_device_i2s0,
        &samsung_device_keypad,
+       &s5p_device_mfc,
+       &s5p_device_mfc_l,
+       &s5p_device_mfc_r,
        &exynos4_device_pd[PD_MFC],
        &exynos4_device_pd[PD_G3D],
        &exynos4_device_pd[PD_LCD0],
@@ -258,6 +280,8 @@ static struct platform_device *smdkv310_devices[] __initdata = {
        &smdkv310_lcd_lte480wv,
        &smdkv310_smsc911x,
        &exynos4_device_ahci,
+       &s5p_device_hdmi,
+       &s5p_device_mixer,
 };
 
 static void __init smdkv310_smsc911x_init(void)
@@ -294,6 +318,18 @@ static struct platform_pwm_backlight_data smdkv310_bl_data = {
        .pwm_period_ns  = 1000,
 };
 
+static void s5p_tv_setup(void)
+{
+       /* direct HPD to HDMI chip */
+       WARN_ON(gpio_request_one(EXYNOS4_GPX3(7), GPIOF_IN, "hpd-plug"));
+       s3c_gpio_cfgpin(EXYNOS4_GPX3(7), S3C_GPIO_SFN(0x3));
+       s3c_gpio_setpull(EXYNOS4_GPX3(7), S3C_GPIO_PULL_NONE);
+
+       /* setup dependencies between TV devices */
+       s5p_device_hdmi.dev.parent = &exynos4_device_pd[PD_TV].dev;
+       s5p_device_mixer.dev.parent = &exynos4_device_pd[PD_TV].dev;
+}
+
 static void __init smdkv310_map_io(void)
 {
        s5p_init_io(NULL, 0, S5P_VA_CHIPID);
@@ -301,6 +337,11 @@ static void __init smdkv310_map_io(void)
        s3c24xx_init_uarts(smdkv310_uartcfgs, ARRAY_SIZE(smdkv310_uartcfgs));
 }
 
+static void __init smdkv310_reserve(void)
+{
+       s5p_mfc_reserve_mem(0x43000000, 8 << 20, 0x51000000, 8 << 20);
+}
+
 static void __init smdkv310_machine_init(void)
 {
        s3c_i2c1_set_platdata(NULL);
@@ -313,12 +354,19 @@ static void __init smdkv310_machine_init(void)
        s3c_sdhci2_set_platdata(&smdkv310_hsmmc2_pdata);
        s3c_sdhci3_set_platdata(&smdkv310_hsmmc3_pdata);
 
+       s5p_tv_setup();
+       s5p_i2c_hdmiphy_set_platdata(NULL);
+
        samsung_keypad_set_platdata(&smdkv310_keypad_data);
 
        samsung_bl_set(&smdkv310_bl_gpio_info, &smdkv310_bl_data);
        s5p_fimd0_set_platdata(&smdkv310_lcd0_pdata);
 
+       smdkv310_ehci_init();
+       clk_xusbxti.rate = 24000000;
+
        platform_add_devices(smdkv310_devices, ARRAY_SIZE(smdkv310_devices));
+       s5p_device_mfc.dev.parent = &exynos4_device_pd[PD_MFC].dev;
 }
 
 MACHINE_START(SMDKV310, "SMDKV310")
@@ -329,6 +377,7 @@ MACHINE_START(SMDKV310, "SMDKV310")
        .map_io         = smdkv310_map_io,
        .init_machine   = smdkv310_machine_init,
        .timer          = &exynos4_timer,
+       .reserve        = &smdkv310_reserve,
 MACHINE_END
 
 MACHINE_START(SMDKC210, "SMDKC210")
index b3b5d8911004422fdb6cc9001ecb8ab1ae4df475..18cf5c7cf56d90604a15998da8b272bb68b2f118 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/i2c.h>
 #include <linux/gpio_keys.h>
 #include <linux/gpio.h>
+#include <linux/fb.h>
 #include <linux/mfd/max8998.h>
 #include <linux/regulator/machine.h>
 #include <linux/regulator/fixed.h>
 #include <plat/devs.h>
 #include <plat/iic.h>
 #include <plat/gpio-cfg.h>
+#include <plat/fb.h>
 #include <plat/mfc.h>
 #include <plat/sdhci.h>
 #include <plat/pd.h>
+#include <plat/regs-fb-v4.h>
+#include <plat/fimc-core.h>
+#include <plat/camport.h>
+#include <plat/mipi_csis.h>
 
 #include <mach/map.h>
 
+#include <media/v4l2-mediabus.h>
+#include <media/s5p_fimc.h>
+#include <media/m5mols.h>
+
 /* Following are default values for UCON, ULCON and UFCON UART registers */
 #define UNIVERSAL_UCON_DEFAULT (S3C2410_UCON_TXILEVEL |        \
                                 S3C2410_UCON_RXILEVEL |        \
@@ -110,6 +120,9 @@ static struct regulator_consumer_supply lp3974_buck1_consumer =
 static struct regulator_consumer_supply lp3974_buck2_consumer =
        REGULATOR_SUPPLY("vddg3d", NULL);
 
+static struct regulator_consumer_supply lp3974_buck3_consumer =
+       REGULATOR_SUPPLY("vdet", "s5p-sdo");
+
 static struct regulator_init_data lp3974_buck1_data = {
        .constraints    = {
                .name           = "VINT_1.1V",
@@ -153,6 +166,8 @@ static struct regulator_init_data lp3974_buck3_data = {
                        .enabled        = 1,
                },
        },
+       .num_consumer_supplies = 1,
+       .consumer_supplies = &lp3974_buck3_consumer,
 };
 
 static struct regulator_init_data lp3974_buck4_data = {
@@ -181,6 +196,12 @@ static struct regulator_init_data lp3974_ldo2_data = {
        },
 };
 
+static struct regulator_consumer_supply lp3974_ldo3_consumer[] = {
+       REGULATOR_SUPPLY("vdd", "exynos4-hdmi"),
+       REGULATOR_SUPPLY("vdd_pll", "exynos4-hdmi"),
+       REGULATOR_SUPPLY("vdd11", "s5p-mipi-csis.0"),
+};
+
 static struct regulator_init_data lp3974_ldo3_data = {
        .constraints    = {
                .name           = "VUSB+MIPI_1.1V",
@@ -192,6 +213,12 @@ static struct regulator_init_data lp3974_ldo3_data = {
                        .disabled       = 1,
                },
        },
+       .num_consumer_supplies = ARRAY_SIZE(lp3974_ldo3_consumer),
+       .consumer_supplies = lp3974_ldo3_consumer,
+};
+
+static struct regulator_consumer_supply lp3974_ldo4_consumer[] = {
+       REGULATOR_SUPPLY("vdd_osc", "exynos4-hdmi"),
 };
 
 static struct regulator_init_data lp3974_ldo4_data = {
@@ -205,6 +232,8 @@ static struct regulator_init_data lp3974_ldo4_data = {
                        .disabled       = 1,
                },
        },
+       .num_consumer_supplies = ARRAY_SIZE(lp3974_ldo4_consumer),
+       .consumer_supplies = lp3974_ldo4_consumer,
 };
 
 static struct regulator_init_data lp3974_ldo5_data = {
@@ -233,6 +262,10 @@ static struct regulator_init_data lp3974_ldo6_data = {
        },
 };
 
+static struct regulator_consumer_supply lp3974_ldo7_consumer[] = {
+       REGULATOR_SUPPLY("vdd18", "s5p-mipi-csis.0"),
+};
+
 static struct regulator_init_data lp3974_ldo7_data = {
        .constraints    = {
                .name           = "VLCD+VMIPI_1.8V",
@@ -244,6 +277,12 @@ static struct regulator_init_data lp3974_ldo7_data = {
                        .disabled       = 1,
                },
        },
+       .num_consumer_supplies  = ARRAY_SIZE(lp3974_ldo7_consumer),
+       .consumer_supplies      = lp3974_ldo7_consumer,
+};
+
+static struct regulator_consumer_supply lp3974_ldo8_consumer[] = {
+       REGULATOR_SUPPLY("vdd33a_dac", "s5p-sdo"),
 };
 
 static struct regulator_init_data lp3974_ldo8_data = {
@@ -257,6 +296,8 @@ static struct regulator_init_data lp3974_ldo8_data = {
                        .disabled       = 1,
                },
        },
+       .num_consumer_supplies = ARRAY_SIZE(lp3974_ldo8_consumer),
+       .consumer_supplies = lp3974_ldo8_consumer,
 };
 
 static struct regulator_init_data lp3974_ldo9_data = {
@@ -286,6 +327,9 @@ static struct regulator_init_data lp3974_ldo10_data = {
        },
 };
 
+static struct regulator_consumer_supply lp3974_ldo11_consumer =
+       REGULATOR_SUPPLY("dig_28", "0-001f");
+
 static struct regulator_init_data lp3974_ldo11_data = {
        .constraints    = {
                .name           = "CAM_AF_3.3V",
@@ -297,6 +341,8 @@ static struct regulator_init_data lp3974_ldo11_data = {
                        .disabled       = 1,
                },
        },
+       .num_consumer_supplies  = 1,
+       .consumer_supplies      = &lp3974_ldo11_consumer,
 };
 
 static struct regulator_init_data lp3974_ldo12_data = {
@@ -325,6 +371,9 @@ static struct regulator_init_data lp3974_ldo13_data = {
        },
 };
 
+static struct regulator_consumer_supply lp3974_ldo14_consumer =
+       REGULATOR_SUPPLY("dig_18", "0-001f");
+
 static struct regulator_init_data lp3974_ldo14_data = {
        .constraints    = {
                .name           = "CAM_I_HOST_1.8V",
@@ -336,8 +385,14 @@ static struct regulator_init_data lp3974_ldo14_data = {
                        .disabled       = 1,
                },
        },
+       .num_consumer_supplies  = 1,
+       .consumer_supplies      = &lp3974_ldo14_consumer,
 };
 
+
+static struct regulator_consumer_supply lp3974_ldo15_consumer =
+       REGULATOR_SUPPLY("dig_12", "0-001f");
+
 static struct regulator_init_data lp3974_ldo15_data = {
        .constraints    = {
                .name           = "CAM_S_DIG+FM33_CORE_1.2V",
@@ -349,6 +404,12 @@ static struct regulator_init_data lp3974_ldo15_data = {
                        .disabled       = 1,
                },
        },
+       .num_consumer_supplies  = 1,
+       .consumer_supplies      = &lp3974_ldo15_consumer,
+};
+
+static struct regulator_consumer_supply lp3974_ldo16_consumer[] = {
+       REGULATOR_SUPPLY("a_sensor", "0-001f"),
 };
 
 static struct regulator_init_data lp3974_ldo16_data = {
@@ -362,6 +423,8 @@ static struct regulator_init_data lp3974_ldo16_data = {
                        .disabled       = 1,
                },
        },
+       .num_consumer_supplies  = ARRAY_SIZE(lp3974_ldo16_consumer),
+       .consumer_supplies      = lp3974_ldo16_consumer,
 };
 
 static struct regulator_init_data lp3974_ldo17_data = {
@@ -472,6 +535,43 @@ static struct max8998_platform_data universal_lp3974_pdata = {
        .wakeup                 = true,
 };
 
+
+enum fixed_regulator_id {
+       FIXED_REG_ID_MMC0,
+       FIXED_REG_ID_HDMI_5V,
+       FIXED_REG_ID_CAM_S_IF,
+       FIXED_REG_ID_CAM_I_CORE,
+       FIXED_REG_ID_CAM_VT_DIO,
+};
+
+static struct regulator_consumer_supply hdmi_fixed_consumer =
+       REGULATOR_SUPPLY("hdmi-en", "exynos4-hdmi");
+
+static struct regulator_init_data hdmi_fixed_voltage_init_data = {
+       .constraints            = {
+               .name           = "HDMI_5V",
+               .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+       },
+       .num_consumer_supplies  = 1,
+       .consumer_supplies      = &hdmi_fixed_consumer,
+};
+
+static struct fixed_voltage_config hdmi_fixed_voltage_config = {
+       .supply_name            = "HDMI_EN1",
+       .microvolts             = 5000000,
+       .gpio                   = EXYNOS4_GPE0(1),
+       .enable_high            = true,
+       .init_data              = &hdmi_fixed_voltage_init_data,
+};
+
+static struct platform_device hdmi_fixed_voltage = {
+       .name                   = "reg-fixed-voltage",
+       .id                     = FIXED_REG_ID_HDMI_5V,
+       .dev                    = {
+               .platform_data  = &hdmi_fixed_voltage_config,
+       },
+};
+
 /* GPIO I2C 5 (PMIC) */
 static struct i2c_board_info i2c5_devs[] __initdata = {
        {
@@ -573,6 +673,11 @@ static void __init universal_touchkey_init(void)
        gpio_direction_output(gpio, 1);
 }
 
+static struct s3c2410_platform_i2c universal_i2c0_platdata __initdata = {
+       .frequency      = 300 * 1000,
+       .sda_delay      = 200,
+};
+
 /* GPIO KEYS */
 static struct gpio_keys_button universal_gpio_keys_tables[] = {
        {
@@ -658,7 +763,7 @@ static struct fixed_voltage_config mmc0_fixed_voltage_config = {
 
 static struct platform_device mmc0_fixed_voltage = {
        .name                   = "reg-fixed-voltage",
-       .id                     = 0,
+       .id                     = FIXED_REG_ID_MMC0,
        .dev                    = {
                .platform_data  = &mmc0_fixed_voltage_config,
        },
@@ -692,18 +797,170 @@ static void __init universal_sdhci_init(void)
        s3c_sdhci3_set_platdata(&universal_hsmmc3_data);
 }
 
-/* I2C0 */
-static struct i2c_board_info i2c0_devs[] __initdata = {
-       /* Camera, To be updated */
-};
-
 /* I2C1 */
 static struct i2c_board_info i2c1_devs[] __initdata = {
        /* Gyro, To be updated */
 };
 
+/* Frame Buffer */
+static struct s3c_fb_pd_win universal_fb_win0 = {
+       .win_mode = {
+               .left_margin    = 16,
+               .right_margin   = 16,
+               .upper_margin   = 2,
+               .lower_margin   = 28,
+               .hsync_len      = 2,
+               .vsync_len      = 1,
+               .xres           = 480,
+               .yres           = 800,
+               .refresh        = 55,
+       },
+       .max_bpp        = 32,
+       .default_bpp    = 16,
+};
+
+static struct s3c_fb_platdata universal_lcd_pdata __initdata = {
+       .win[0]         = &universal_fb_win0,
+       .vidcon0        = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB |
+                         VIDCON0_CLKSEL_LCD,
+       .vidcon1        = VIDCON1_INV_VCLK | VIDCON1_INV_VDEN
+                         | VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC,
+       .setup_gpio     = exynos4_fimd0_gpio_setup_24bpp,
+};
+
+static struct regulator_consumer_supply cam_i_core_supply =
+       REGULATOR_SUPPLY("core", "0-001f");
+
+static struct regulator_init_data cam_i_core_reg_init_data = {
+       .constraints = { .valid_ops_mask = REGULATOR_CHANGE_STATUS },
+       .num_consumer_supplies = 1,
+       .consumer_supplies = &cam_i_core_supply,
+};
+
+static struct fixed_voltage_config cam_i_core_fixed_voltage_cfg = {
+       .supply_name    = "CAM_I_CORE_1.2V",
+       .microvolts     = 1200000,
+       .gpio           = EXYNOS4_GPE2(2),      /* CAM_8M_CORE_EN */
+       .enable_high    = 1,
+       .init_data      = &cam_i_core_reg_init_data,
+};
+
+static struct platform_device cam_i_core_fixed_reg_dev = {
+       .name = "reg-fixed-voltage", .id = FIXED_REG_ID_CAM_I_CORE,
+       .dev = { .platform_data = &cam_i_core_fixed_voltage_cfg },
+};
+
+static struct regulator_consumer_supply cam_s_if_supply =
+       REGULATOR_SUPPLY("d_sensor", "0-001f");
+
+static struct regulator_init_data cam_s_if_reg_init_data = {
+       .constraints = { .valid_ops_mask = REGULATOR_CHANGE_STATUS },
+       .num_consumer_supplies = 1,
+       .consumer_supplies = &cam_s_if_supply,
+};
+
+static struct fixed_voltage_config cam_s_if_fixed_voltage_cfg = {
+       .supply_name    = "CAM_S_IF_1.8V",
+       .microvolts     = 1800000,
+       .gpio           = EXYNOS4_GPE3(0),      /* CAM_PWR_EN1 */
+       .enable_high    = 1,
+       .init_data      = &cam_s_if_reg_init_data,
+};
+
+static struct platform_device cam_s_if_fixed_reg_dev = {
+       .name = "reg-fixed-voltage", .id = FIXED_REG_ID_CAM_S_IF,
+       .dev = { .platform_data = &cam_s_if_fixed_voltage_cfg },
+};
+
+static struct s5p_platform_mipi_csis mipi_csis_platdata = {
+       .clk_rate       = 166000000UL,
+       .lanes          = 2,
+       .alignment      = 32,
+       .hs_settle      = 12,
+       .phy_enable     = s5p_csis_phy_enable,
+};
+
+#define GPIO_CAM_LEVEL_EN(n)   EXYNOS4_GPE4(n + 3)
+#define GPIO_CAM_8M_ISP_INT    EXYNOS4_GPX1(5) /* XEINT_13 */
+#define GPIO_CAM_MEGA_nRST     EXYNOS4_GPE2(5)
+
+static int m5mols_set_power(struct device *dev, int on)
+{
+       gpio_set_value(GPIO_CAM_LEVEL_EN(1), !on);
+       gpio_set_value(GPIO_CAM_LEVEL_EN(2), !!on);
+       return 0;
+}
+
+static struct m5mols_platform_data m5mols_platdata = {
+       .gpio_reset     = GPIO_CAM_MEGA_nRST,
+       .reset_polarity = 0,
+       .set_power      = m5mols_set_power,
+};
+
+static struct i2c_board_info m5mols_board_info = {
+       I2C_BOARD_INFO("M5MOLS", 0x1F),
+       .platform_data = &m5mols_platdata,
+};
+
+static struct s5p_fimc_isp_info universal_camera_sensors[] = {
+       {
+               .mux_id         = 0,
+               .flags          = V4L2_MBUS_PCLK_SAMPLE_FALLING |
+                                 V4L2_MBUS_VSYNC_ACTIVE_LOW,
+               .bus_type       = FIMC_MIPI_CSI2,
+               .board_info     = &m5mols_board_info,
+               .i2c_bus_num    = 0,
+               .clk_frequency  = 21600000UL,
+               .csi_data_align = 32,
+       },
+};
+
+static struct s5p_platform_fimc fimc_md_platdata = {
+       .isp_info       = universal_camera_sensors,
+       .num_clients    = ARRAY_SIZE(universal_camera_sensors),
+};
+
+struct platform_device s5p_device_fimc_md = {
+       .name   = "s5p-fimc-md",
+       .id     = -1,
+};
+
+static struct gpio universal_camera_gpios[] = {
+       { GPIO_CAM_LEVEL_EN(1), GPIOF_OUT_INIT_HIGH, "CAM_LVL_EN1" },
+       { GPIO_CAM_LEVEL_EN(2), GPIOF_OUT_INIT_LOW,  "CAM_LVL_EN2" },
+       { GPIO_CAM_8M_ISP_INT,  GPIOF_IN,            "8M_ISP_INT"  },
+       { GPIO_CAM_MEGA_nRST,   GPIOF_OUT_INIT_LOW,  "CAM_8M_NRST" },
+};
+
+static void universal_camera_init(void)
+{
+       s3c_set_platdata(&mipi_csis_platdata, sizeof(mipi_csis_platdata),
+                        &s5p_device_mipi_csis0);
+       s3c_set_platdata(&fimc_md_platdata,  sizeof(fimc_md_platdata),
+                        &s5p_device_fimc_md);
+
+       if (gpio_request_array(universal_camera_gpios,
+                              ARRAY_SIZE(universal_camera_gpios))) {
+               pr_err("%s: GPIO request failed\n", __func__);
+               return;
+       }
+
+       if (!s3c_gpio_cfgpin(GPIO_CAM_8M_ISP_INT, S3C_GPIO_SFN(0xf)))
+               m5mols_board_info.irq = gpio_to_irq(GPIO_CAM_8M_ISP_INT);
+       else
+               pr_err("Failed to configure 8M_ISP_INT GPIO\n");
+
+       /* Free GPIOs controlled directly by the sensor drivers. */
+       gpio_free(GPIO_CAM_MEGA_nRST);
+       gpio_free(GPIO_CAM_8M_ISP_INT);
+
+       if (exynos4_fimc_setup_gpio(S5P_CAMPORT_A))
+               pr_err("Camera port A setup failed\n");
+}
+
 static struct platform_device *universal_devices[] __initdata = {
        /* Samsung Platform Devices */
+       &s5p_device_mipi_csis0,
        &s5p_device_fimc0,
        &s5p_device_fimc1,
        &s5p_device_fimc2,
@@ -712,17 +969,30 @@ static struct platform_device *universal_devices[] __initdata = {
        &s3c_device_hsmmc0,
        &s3c_device_hsmmc2,
        &s3c_device_hsmmc3,
+       &s3c_device_i2c0,
        &s3c_device_i2c3,
        &s3c_device_i2c5,
+       &s5p_device_i2c_hdmiphy,
+       &hdmi_fixed_voltage,
+       &exynos4_device_pd[PD_TV],
+       &s5p_device_hdmi,
+       &s5p_device_sdo,
+       &s5p_device_mixer,
 
        /* Universal Devices */
        &i2c_gpio12,
        &universal_gpio_keys,
        &s5p_device_onenand,
+       &s5p_device_fimd0,
        &s5p_device_mfc,
        &s5p_device_mfc_l,
        &s5p_device_mfc_r,
        &exynos4_device_pd[PD_MFC],
+       &exynos4_device_pd[PD_LCD0],
+       &exynos4_device_pd[PD_CAM],
+       &cam_i_core_fixed_reg_dev,
+       &cam_s_if_fixed_reg_dev,
+       &s5p_device_fimc_md,
 };
 
 static void __init universal_map_io(void)
@@ -732,6 +1002,20 @@ static void __init universal_map_io(void)
        s3c24xx_init_uarts(universal_uartcfgs, ARRAY_SIZE(universal_uartcfgs));
 }
 
+void s5p_tv_setup(void)
+{
+       /* direct HPD to HDMI chip */
+       gpio_request(EXYNOS4_GPX3(7), "hpd-plug");
+
+       gpio_direction_input(EXYNOS4_GPX3(7));
+       s3c_gpio_cfgpin(EXYNOS4_GPX3(7), S3C_GPIO_SFN(0x3));
+       s3c_gpio_setpull(EXYNOS4_GPX3(7), S3C_GPIO_PULL_NONE);
+
+       /* setup dependencies between TV devices */
+       s5p_device_hdmi.dev.parent = &exynos4_device_pd[PD_TV].dev;
+       s5p_device_mixer.dev.parent = &exynos4_device_pd[PD_TV].dev;
+}
+
 static void __init universal_reserve(void)
 {
        s5p_mfc_reserve_mem(0x43000000, 8 << 20, 0x51000000, 8 << 20);
@@ -740,8 +1024,9 @@ static void __init universal_reserve(void)
 static void __init universal_machine_init(void)
 {
        universal_sdhci_init();
+       s5p_tv_setup();
 
-       i2c_register_board_info(0, i2c0_devs, ARRAY_SIZE(i2c0_devs));
+       s3c_i2c0_set_platdata(&universal_i2c0_platdata);
        i2c_register_board_info(1, i2c1_devs, ARRAY_SIZE(i2c1_devs));
 
        universal_tsp_init();
@@ -749,15 +1034,28 @@ static void __init universal_machine_init(void)
        i2c_register_board_info(3, i2c3_devs, ARRAY_SIZE(i2c3_devs));
 
        s3c_i2c5_set_platdata(NULL);
+       s5p_i2c_hdmiphy_set_platdata(NULL);
        i2c_register_board_info(5, i2c5_devs, ARRAY_SIZE(i2c5_devs));
 
+       s5p_fimd0_set_platdata(&universal_lcd_pdata);
+
        universal_touchkey_init();
        i2c_register_board_info(I2C_GPIO_BUS_12, i2c_gpio12_devs,
                        ARRAY_SIZE(i2c_gpio12_devs));
 
+       universal_camera_init();
+
        /* Last */
        platform_add_devices(universal_devices, ARRAY_SIZE(universal_devices));
+
        s5p_device_mfc.dev.parent = &exynos4_device_pd[PD_MFC].dev;
+       s5p_device_fimd0.dev.parent = &exynos4_device_pd[PD_LCD0].dev;
+
+       s5p_device_fimc0.dev.parent = &exynos4_device_pd[PD_CAM].dev;
+       s5p_device_fimc1.dev.parent = &exynos4_device_pd[PD_CAM].dev;
+       s5p_device_fimc2.dev.parent = &exynos4_device_pd[PD_CAM].dev;
+       s5p_device_fimc3.dev.parent = &exynos4_device_pd[PD_CAM].dev;
+       s5p_device_mipi_csis0.dev.parent = &exynos4_device_pd[PD_CAM].dev;
 }
 
 MACHINE_START(UNIVERSAL_C210, "UNIVERSAL_C210")
index 62e4f43630068dc9aa852f1ab479f82880724d36..509a435afd4bf85cf4636343b0cdd32bbf94a863 100644 (file)
@@ -339,6 +339,13 @@ static int exynos4_pm_suspend(void)
        tmp &= ~S5P_CENTRAL_LOWPWR_CFG;
        __raw_writel(tmp, S5P_CENTRAL_SEQ_CONFIGURATION);
 
+       if (soc_is_exynos4212()) {
+               tmp = __raw_readl(S5P_CENTRAL_SEQ_OPTION);
+               tmp &= ~(S5P_USE_STANDBYWFI_ISP_ARM |
+                        S5P_USE_STANDBYWFE_ISP_ARM);
+               __raw_writel(tmp, S5P_CENTRAL_SEQ_OPTION);
+       }
+
        /* Save Power control register */
        asm ("mrc p15, 0, %0, c15, c0, 0"
             : "=r" (tmp) : : "cc");
index 7ea9eb2a20d2a734d43966f2f722bb904a049da9..bba48f5c3e8fe21a6d2218949d929ee4e5b08d8a 100644 (file)
 #include <mach/regs-clock.h>
 #include <mach/pmu.h>
 
-static void __iomem *sys_powerdown_reg[] = {
-       S5P_ARM_CORE0_LOWPWR,
-       S5P_DIS_IRQ_CORE0,
-       S5P_DIS_IRQ_CENTRAL0,
-       S5P_ARM_CORE1_LOWPWR,
-       S5P_DIS_IRQ_CORE1,
-       S5P_DIS_IRQ_CENTRAL1,
-       S5P_ARM_COMMON_LOWPWR,
-       S5P_L2_0_LOWPWR,
-       S5P_L2_1_LOWPWR,
-       S5P_CMU_ACLKSTOP_LOWPWR,
-       S5P_CMU_SCLKSTOP_LOWPWR,
-       S5P_CMU_RESET_LOWPWR,
-       S5P_APLL_SYSCLK_LOWPWR,
-       S5P_MPLL_SYSCLK_LOWPWR,
-       S5P_VPLL_SYSCLK_LOWPWR,
-       S5P_EPLL_SYSCLK_LOWPWR,
-       S5P_CMU_CLKSTOP_GPS_ALIVE_LOWPWR,
-       S5P_CMU_RESET_GPSALIVE_LOWPWR,
-       S5P_CMU_CLKSTOP_CAM_LOWPWR,
-       S5P_CMU_CLKSTOP_TV_LOWPWR,
-       S5P_CMU_CLKSTOP_MFC_LOWPWR,
-       S5P_CMU_CLKSTOP_G3D_LOWPWR,
-       S5P_CMU_CLKSTOP_LCD0_LOWPWR,
-       S5P_CMU_CLKSTOP_LCD1_LOWPWR,
-       S5P_CMU_CLKSTOP_MAUDIO_LOWPWR,
-       S5P_CMU_CLKSTOP_GPS_LOWPWR,
-       S5P_CMU_RESET_CAM_LOWPWR,
-       S5P_CMU_RESET_TV_LOWPWR,
-       S5P_CMU_RESET_MFC_LOWPWR,
-       S5P_CMU_RESET_G3D_LOWPWR,
-       S5P_CMU_RESET_LCD0_LOWPWR,
-       S5P_CMU_RESET_LCD1_LOWPWR,
-       S5P_CMU_RESET_MAUDIO_LOWPWR,
-       S5P_CMU_RESET_GPS_LOWPWR,
-       S5P_TOP_BUS_LOWPWR,
-       S5P_TOP_RETENTION_LOWPWR,
-       S5P_TOP_PWR_LOWPWR,
-       S5P_LOGIC_RESET_LOWPWR,
-       S5P_ONENAND_MEM_LOWPWR,
-       S5P_MODIMIF_MEM_LOWPWR,
-       S5P_G2D_ACP_MEM_LOWPWR,
-       S5P_USBOTG_MEM_LOWPWR,
-       S5P_HSMMC_MEM_LOWPWR,
-       S5P_CSSYS_MEM_LOWPWR,
-       S5P_SECSS_MEM_LOWPWR,
-       S5P_PCIE_MEM_LOWPWR,
-       S5P_SATA_MEM_LOWPWR,
-       S5P_PAD_RETENTION_DRAM_LOWPWR,
-       S5P_PAD_RETENTION_MAUDIO_LOWPWR,
-       S5P_PAD_RETENTION_GPIO_LOWPWR,
-       S5P_PAD_RETENTION_UART_LOWPWR,
-       S5P_PAD_RETENTION_MMCA_LOWPWR,
-       S5P_PAD_RETENTION_MMCB_LOWPWR,
-       S5P_PAD_RETENTION_EBIA_LOWPWR,
-       S5P_PAD_RETENTION_EBIB_LOWPWR,
-       S5P_PAD_RETENTION_ISOLATION_LOWPWR,
-       S5P_PAD_RETENTION_ALV_SEL_LOWPWR,
-       S5P_XUSBXTI_LOWPWR,
-       S5P_XXTI_LOWPWR,
-       S5P_EXT_REGULATOR_LOWPWR,
-       S5P_GPIO_MODE_LOWPWR,
-       S5P_GPIO_MODE_MAUDIO_LOWPWR,
-       S5P_CAM_LOWPWR,
-       S5P_TV_LOWPWR,
-       S5P_MFC_LOWPWR,
-       S5P_G3D_LOWPWR,
-       S5P_LCD0_LOWPWR,
-       S5P_LCD1_LOWPWR,
-       S5P_MAUDIO_LOWPWR,
-       S5P_GPS_LOWPWR,
-       S5P_GPS_ALIVE_LOWPWR,
+static struct exynos4_pmu_conf *exynos4_pmu_config;
+
+static struct exynos4_pmu_conf exynos4210_pmu_config[] = {
+       /* { .reg = address, .val = { AFTR, LPA, SLEEP } */
+       { S5P_ARM_CORE0_LOWPWR,                 { 0x0, 0x0, 0x2 } },
+       { S5P_DIS_IRQ_CORE0,                    { 0x0, 0x0, 0x0 } },
+       { S5P_DIS_IRQ_CENTRAL0,                 { 0x0, 0x0, 0x0 } },
+       { S5P_ARM_CORE1_LOWPWR,                 { 0x0, 0x0, 0x2 } },
+       { S5P_DIS_IRQ_CORE1,                    { 0x0, 0x0, 0x0 } },
+       { S5P_DIS_IRQ_CENTRAL1,                 { 0x0, 0x0, 0x0 } },
+       { S5P_ARM_COMMON_LOWPWR,                { 0x0, 0x0, 0x2 } },
+       { S5P_L2_0_LOWPWR,                      { 0x2, 0x2, 0x3 } },
+       { S5P_L2_1_LOWPWR,                      { 0x2, 0x2, 0x3 } },
+       { S5P_CMU_ACLKSTOP_LOWPWR,              { 0x1, 0x0, 0x0 } },
+       { S5P_CMU_SCLKSTOP_LOWPWR,              { 0x1, 0x0, 0x0 } },
+       { S5P_CMU_RESET_LOWPWR,                 { 0x1, 0x1, 0x0 } },
+       { S5P_APLL_SYSCLK_LOWPWR,               { 0x1, 0x0, 0x0 } },
+       { S5P_MPLL_SYSCLK_LOWPWR,               { 0x1, 0x0, 0x0 } },
+       { S5P_VPLL_SYSCLK_LOWPWR,               { 0x1, 0x0, 0x0 } },
+       { S5P_EPLL_SYSCLK_LOWPWR,               { 0x1, 0x1, 0x0 } },
+       { S5P_CMU_CLKSTOP_GPS_ALIVE_LOWPWR,     { 0x1, 0x1, 0x0 } },
+       { S5P_CMU_RESET_GPSALIVE_LOWPWR,        { 0x1, 0x1, 0x0 } },
+       { S5P_CMU_CLKSTOP_CAM_LOWPWR,           { 0x1, 0x1, 0x0 } },
+       { S5P_CMU_CLKSTOP_TV_LOWPWR,            { 0x1, 0x1, 0x0 } },
+       { S5P_CMU_CLKSTOP_MFC_LOWPWR,           { 0x1, 0x1, 0x0 } },
+       { S5P_CMU_CLKSTOP_G3D_LOWPWR,           { 0x1, 0x1, 0x0 } },
+       { S5P_CMU_CLKSTOP_LCD0_LOWPWR,          { 0x1, 0x1, 0x0 } },
+       { S5P_CMU_CLKSTOP_LCD1_LOWPWR,          { 0x1, 0x1, 0x0 } },
+       { S5P_CMU_CLKSTOP_MAUDIO_LOWPWR,        { 0x1, 0x1, 0x0 } },
+       { S5P_CMU_CLKSTOP_GPS_LOWPWR,           { 0x1, 0x1, 0x0 } },
+       { S5P_CMU_RESET_CAM_LOWPWR,             { 0x1, 0x1, 0x0 } },
+       { S5P_CMU_RESET_TV_LOWPWR,              { 0x1, 0x1, 0x0 } },
+       { S5P_CMU_RESET_MFC_LOWPWR,             { 0x1, 0x1, 0x0 } },
+       { S5P_CMU_RESET_G3D_LOWPWR,             { 0x1, 0x1, 0x0 } },
+       { S5P_CMU_RESET_LCD0_LOWPWR,            { 0x1, 0x1, 0x0 } },
+       { S5P_CMU_RESET_LCD1_LOWPWR,            { 0x1, 0x1, 0x0 } },
+       { S5P_CMU_RESET_MAUDIO_LOWPWR,          { 0x1, 0x1, 0x0 } },
+       { S5P_CMU_RESET_GPS_LOWPWR,             { 0x1, 0x1, 0x0 } },
+       { S5P_TOP_BUS_LOWPWR,                   { 0x3, 0x0, 0x0 } },
+       { S5P_TOP_RETENTION_LOWPWR,             { 0x1, 0x0, 0x1 } },
+       { S5P_TOP_PWR_LOWPWR,                   { 0x3, 0x0, 0x3 } },
+       { S5P_LOGIC_RESET_LOWPWR,               { 0x1, 0x1, 0x0 } },
+       { S5P_ONENAND_MEM_LOWPWR,               { 0x3, 0x0, 0x0 } },
+       { S5P_MODIMIF_MEM_LOWPWR,               { 0x3, 0x0, 0x0 } },
+       { S5P_G2D_ACP_MEM_LOWPWR,               { 0x3, 0x0, 0x0 } },
+       { S5P_USBOTG_MEM_LOWPWR,                { 0x3, 0x0, 0x0 } },
+       { S5P_HSMMC_MEM_LOWPWR,                 { 0x3, 0x0, 0x0 } },
+       { S5P_CSSYS_MEM_LOWPWR,                 { 0x3, 0x0, 0x0 } },
+       { S5P_SECSS_MEM_LOWPWR,                 { 0x3, 0x0, 0x0 } },
+       { S5P_PCIE_MEM_LOWPWR,                  { 0x3, 0x0, 0x0 } },
+       { S5P_SATA_MEM_LOWPWR,                  { 0x3, 0x0, 0x0 } },
+       { S5P_PAD_RETENTION_DRAM_LOWPWR,        { 0x1, 0x0, 0x0 } },
+       { S5P_PAD_RETENTION_MAUDIO_LOWPWR,      { 0x1, 0x1, 0x0 } },
+       { S5P_PAD_RETENTION_GPIO_LOWPWR,        { 0x1, 0x0, 0x0 } },
+       { S5P_PAD_RETENTION_UART_LOWPWR,        { 0x1, 0x0, 0x0 } },
+       { S5P_PAD_RETENTION_MMCA_LOWPWR,        { 0x1, 0x0, 0x0 } },
+       { S5P_PAD_RETENTION_MMCB_LOWPWR,        { 0x1, 0x0, 0x0 } },
+       { S5P_PAD_RETENTION_EBIA_LOWPWR,        { 0x1, 0x0, 0x0 } },
+       { S5P_PAD_RETENTION_EBIB_LOWPWR,        { 0x1, 0x0, 0x0 } },
+       { S5P_PAD_RETENTION_ISOLATION_LOWPWR,   { 0x1, 0x0, 0x0 } },
+       { S5P_PAD_RETENTION_ALV_SEL_LOWPWR,     { 0x1, 0x0, 0x0 } },
+       { S5P_XUSBXTI_LOWPWR,                   { 0x1, 0x1, 0x0 } },
+       { S5P_XXTI_LOWPWR,                      { 0x1, 0x1, 0x0 } },
+       { S5P_EXT_REGULATOR_LOWPWR,             { 0x1, 0x1, 0x0 } },
+       { S5P_GPIO_MODE_LOWPWR,                 { 0x1, 0x0, 0x0 } },
+       { S5P_GPIO_MODE_MAUDIO_LOWPWR,          { 0x1, 0x1, 0x0 } },
+       { S5P_CAM_LOWPWR,                       { 0x7, 0x0, 0x0 } },
+       { S5P_TV_LOWPWR,                        { 0x7, 0x0, 0x0 } },
+       { S5P_MFC_LOWPWR,                       { 0x7, 0x0, 0x0 } },
+       { S5P_G3D_LOWPWR,                       { 0x7, 0x0, 0x0 } },
+       { S5P_LCD0_LOWPWR,                      { 0x7, 0x0, 0x0 } },
+       { S5P_LCD1_LOWPWR,                      { 0x7, 0x0, 0x0 } },
+       { S5P_MAUDIO_LOWPWR,                    { 0x7, 0x7, 0x0 } },
+       { S5P_GPS_LOWPWR,                       { 0x7, 0x0, 0x0 } },
+       { S5P_GPS_ALIVE_LOWPWR,                 { 0x7, 0x0, 0x0 } },
+       { PMU_TABLE_END,},
 };
 
-static const unsigned int sys_powerdown_val[][NUM_SYS_POWERDOWN] = {
-       /* { AFTR, LPA, SLEEP }*/
-       { 0, 0, 2 },    /* ARM_CORE0 */
-       { 0, 0, 0 },    /* ARM_DIS_IRQ_CORE0 */
-       { 0, 0, 0 },    /* ARM_DIS_IRQ_CENTRAL0 */
-       { 0, 0, 2 },    /* ARM_CORE1 */
-       { 0, 0, 0 },    /* ARM_DIS_IRQ_CORE1 */
-       { 0, 0, 0 },    /* ARM_DIS_IRQ_CENTRAL1 */
-       { 0, 0, 2 },    /* ARM_COMMON */
-       { 2, 2, 3 },    /* ARM_CPU_L2_0 */
-       { 2, 2, 3 },    /* ARM_CPU_L2_1 */
-       { 1, 0, 0 },    /* CMU_ACLKSTOP */
-       { 1, 0, 0 },    /* CMU_SCLKSTOP */
-       { 1, 1, 0 },    /* CMU_RESET */
-       { 1, 0, 0 },    /* APLL_SYSCLK */
-       { 1, 0, 0 },    /* MPLL_SYSCLK */
-       { 1, 0, 0 },    /* VPLL_SYSCLK */
-       { 1, 1, 0 },    /* EPLL_SYSCLK */
-       { 1, 1, 0 },    /* CMU_CLKSTOP_GPS_ALIVE */
-       { 1, 1, 0 },    /* CMU_RESET_GPS_ALIVE */
-       { 1, 1, 0 },    /* CMU_CLKSTOP_CAM */
-       { 1, 1, 0 },    /* CMU_CLKSTOP_TV */
-       { 1, 1, 0 },    /* CMU_CLKSTOP_MFC */
-       { 1, 1, 0 },    /* CMU_CLKSTOP_G3D */
-       { 1, 1, 0 },    /* CMU_CLKSTOP_LCD0 */
-       { 1, 1, 0 },    /* CMU_CLKSTOP_LCD1 */
-       { 1, 1, 0 },    /* CMU_CLKSTOP_MAUDIO */
-       { 1, 1, 0 },    /* CMU_CLKSTOP_GPS */
-       { 1, 1, 0 },    /* CMU_RESET_CAM */
-       { 1, 1, 0 },    /* CMU_RESET_TV */
-       { 1, 1, 0 },    /* CMU_RESET_MFC */
-       { 1, 1, 0 },    /* CMU_RESET_G3D */
-       { 1, 1, 0 },    /* CMU_RESET_LCD0 */
-       { 1, 1, 0 },    /* CMU_RESET_LCD1 */
-       { 1, 1, 0 },    /* CMU_RESET_MAUDIO */
-       { 1, 1, 0 },    /* CMU_RESET_GPS */
-       { 3, 0, 0 },    /* TOP_BUS */
-       { 1, 0, 1 },    /* TOP_RETENTION */
-       { 3, 0, 3 },    /* TOP_PWR */
-       { 1, 1, 0 },    /* LOGIC_RESET */
-       { 3, 0, 0 },    /* ONENAND_MEM */
-       { 3, 0, 0 },    /* MODIMIF_MEM */
-       { 3, 0, 0 },    /* G2D_ACP_MEM */
-       { 3, 0, 0 },    /* USBOTG_MEM */
-       { 3, 0, 0 },    /* HSMMC_MEM */
-       { 3, 0, 0 },    /* CSSYS_MEM */
-       { 3, 0, 0 },    /* SECSS_MEM */
-       { 3, 0, 0 },    /* PCIE_MEM */
-       { 3, 0, 0 },    /* SATA_MEM */
-       { 1, 0, 0 },    /* PAD_RETENTION_DRAM */
-       { 1, 1, 0 },    /* PAD_RETENTION_MAUDIO */
-       { 1, 0, 0 },    /* PAD_RETENTION_GPIO */
-       { 1, 0, 0 },    /* PAD_RETENTION_UART */
-       { 1, 0, 0 },    /* PAD_RETENTION_MMCA */
-       { 1, 0, 0 },    /* PAD_RETENTION_MMCB */
-       { 1, 0, 0 },    /* PAD_RETENTION_EBIA */
-       { 1, 0, 0 },    /* PAD_RETENTION_EBIB */
-       { 1, 0, 0 },    /* PAD_RETENTION_ISOLATION */
-       { 1, 0, 0 },    /* PAD_RETENTION_ALV_SEL */
-       { 1, 1, 0 },    /* XUSBXTI */
-       { 1, 1, 0 },    /* XXTI */
-       { 1, 1, 0 },    /* EXT_REGULATOR */
-       { 1, 0, 0 },    /* GPIO_MODE */
-       { 1, 1, 0 },    /* GPIO_MODE_MAUDIO */
-       { 7, 0, 0 },    /* CAM */
-       { 7, 0, 0 },    /* TV */
-       { 7, 0, 0 },    /* MFC */
-       { 7, 0, 0 },    /* G3D */
-       { 7, 0, 0 },    /* LCD0 */
-       { 7, 0, 0 },    /* LCD1 */
-       { 7, 7, 0 },    /* MAUDIO */
-       { 7, 0, 0 },    /* GPS */
-       { 7, 0, 0 },    /* GPS_ALIVE */
+static struct exynos4_pmu_conf exynos4212_pmu_config[] = {
+       { S5P_ARM_CORE0_LOWPWR,                 { 0x0, 0x0, 0x2 } },
+       { S5P_DIS_IRQ_CORE0,                    { 0x0, 0x0, 0x0 } },
+       { S5P_DIS_IRQ_CENTRAL0,                 { 0x0, 0x0, 0x0 } },
+       { S5P_ARM_CORE1_LOWPWR,                 { 0x0, 0x0, 0x2 } },
+       { S5P_DIS_IRQ_CORE1,                    { 0x0, 0x0, 0x0 } },
+       { S5P_DIS_IRQ_CENTRAL1,                 { 0x0, 0x0, 0x0 } },
+       { S5P_ISP_ARM_LOWPWR,                   { 0x1, 0x0, 0x0 } },
+       { S5P_DIS_IRQ_ISP_ARM_LOCAL_LOWPWR,     { 0x0, 0x0, 0x0 } },
+       { S5P_DIS_IRQ_ISP_ARM_CENTRAL_LOWPWR,   { 0x0, 0x0, 0x0 } },
+       { S5P_ARM_COMMON_LOWPWR,                { 0x0, 0x0, 0x2 } },
+       { S5P_L2_0_LOWPWR,                      { 0x0, 0x0, 0x3 } },
+       /* XXX_OPTION register should be set other field */
+       { S5P_ARM_L2_0_OPTION,                  { 0x10, 0x10, 0x0 } },
+       { S5P_L2_1_LOWPWR,                      { 0x0, 0x0, 0x3 } },
+       { S5P_ARM_L2_1_OPTION,                  { 0x10, 0x10, 0x0 } },
+       { S5P_CMU_ACLKSTOP_LOWPWR,              { 0x1, 0x0, 0x0 } },
+       { S5P_CMU_SCLKSTOP_LOWPWR,              { 0x1, 0x0, 0x0 } },
+       { S5P_CMU_RESET_LOWPWR,                 { 0x1, 0x1, 0x0 } },
+       { S5P_DRAM_FREQ_DOWN_LOWPWR,            { 0x1, 0x1, 0x1 } },
+       { S5P_DDRPHY_DLLOFF_LOWPWR,             { 0x1, 0x1, 0x1 } },
+       { S5P_LPDDR_PHY_DLL_LOCK_LOWPWR,        { 0x1, 0x1, 0x1 } },
+       { S5P_CMU_ACLKSTOP_COREBLK_LOWPWR,      { 0x1, 0x0, 0x0 } },
+       { S5P_CMU_SCLKSTOP_COREBLK_LOWPWR,      { 0x1, 0x0, 0x0 } },
+       { S5P_CMU_RESET_COREBLK_LOWPWR,         { 0x1, 0x1, 0x0 } },
+       { S5P_APLL_SYSCLK_LOWPWR,               { 0x1, 0x0, 0x0 } },
+       { S5P_MPLL_SYSCLK_LOWPWR,               { 0x1, 0x0, 0x0 } },
+       { S5P_VPLL_SYSCLK_LOWPWR,               { 0x1, 0x0, 0x0 } },
+       { S5P_EPLL_SYSCLK_LOWPWR,               { 0x1, 0x1, 0x0 } },
+       { S5P_MPLLUSER_SYSCLK_LOWPWR,           { 0x1, 0x0, 0x0 } },
+       { S5P_CMU_CLKSTOP_GPS_ALIVE_LOWPWR,     { 0x1, 0x0, 0x0 } },
+       { S5P_CMU_RESET_GPSALIVE_LOWPWR,        { 0x1, 0x0, 0x0 } },
+       { S5P_CMU_CLKSTOP_CAM_LOWPWR,           { 0x1, 0x0, 0x0 } },
+       { S5P_CMU_CLKSTOP_TV_LOWPWR,            { 0x1, 0x0, 0x0 } },
+       { S5P_CMU_CLKSTOP_MFC_LOWPWR,           { 0x1, 0x0, 0x0 } },
+       { S5P_CMU_CLKSTOP_G3D_LOWPWR,           { 0x1, 0x0, 0x0 } },
+       { S5P_CMU_CLKSTOP_LCD0_LOWPWR,          { 0x1, 0x0, 0x0 } },
+       { S5P_CMU_CLKSTOP_ISP_LOWPWR,           { 0x1, 0x0, 0x0 } },
+       { S5P_CMU_CLKSTOP_MAUDIO_LOWPWR,        { 0x1, 0x0, 0x0 } },
+       { S5P_CMU_CLKSTOP_GPS_LOWPWR,           { 0x1, 0x0, 0x0 } },
+       { S5P_CMU_RESET_CAM_LOWPWR,             { 0x1, 0x0, 0x0 } },
+       { S5P_CMU_RESET_TV_LOWPWR,              { 0x1, 0x0, 0x0 } },
+       { S5P_CMU_RESET_MFC_LOWPWR,             { 0x1, 0x0, 0x0 } },
+       { S5P_CMU_RESET_G3D_LOWPWR,             { 0x1, 0x0, 0x0 } },
+       { S5P_CMU_RESET_LCD0_LOWPWR,            { 0x1, 0x0, 0x0 } },
+       { S5P_CMU_RESET_ISP_LOWPWR,             { 0x1, 0x0, 0x0 } },
+       { S5P_CMU_RESET_MAUDIO_LOWPWR,          { 0x1, 0x1, 0x0 } },
+       { S5P_CMU_RESET_GPS_LOWPWR,             { 0x1, 0x0, 0x0 } },
+       { S5P_TOP_BUS_LOWPWR,                   { 0x3, 0x0, 0x0 } },
+       { S5P_TOP_RETENTION_LOWPWR,             { 0x1, 0x0, 0x1 } },
+       { S5P_TOP_PWR_LOWPWR,                   { 0x3, 0x0, 0x3 } },
+       { S5P_TOP_BUS_COREBLK_LOWPWR,           { 0x3, 0x0, 0x0 } },
+       { S5P_TOP_RETENTION_COREBLK_LOWPWR,     { 0x1, 0x0, 0x1 } },
+       { S5P_TOP_PWR_COREBLK_LOWPWR,           { 0x3, 0x0, 0x3 } },
+       { S5P_LOGIC_RESET_LOWPWR,               { 0x1, 0x1, 0x0 } },
+       { S5P_OSCCLK_GATE_LOWPWR,               { 0x1, 0x0, 0x1 } },
+       { S5P_LOGIC_RESET_COREBLK_LOWPWR,       { 0x1, 0x1, 0x0 } },
+       { S5P_OSCCLK_GATE_COREBLK_LOWPWR,       { 0x1, 0x0, 0x1 } },
+       { S5P_ONENAND_MEM_LOWPWR,               { 0x3, 0x0, 0x0 } },
+       { S5P_ONENAND_MEM_OPTION,               { 0x10, 0x10, 0x0 } },
+       { S5P_HSI_MEM_LOWPWR,                   { 0x3, 0x0, 0x0 } },
+       { S5P_HSI_MEM_OPTION,                   { 0x10, 0x10, 0x0 } },
+       { S5P_G2D_ACP_MEM_LOWPWR,               { 0x3, 0x0, 0x0 } },
+       { S5P_G2D_ACP_MEM_OPTION,               { 0x10, 0x10, 0x0 } },
+       { S5P_USBOTG_MEM_LOWPWR,                { 0x3, 0x0, 0x0 } },
+       { S5P_USBOTG_MEM_OPTION,                { 0x10, 0x10, 0x0 } },
+       { S5P_HSMMC_MEM_LOWPWR,                 { 0x3, 0x0, 0x0 } },
+       { S5P_HSMMC_MEM_OPTION,                 { 0x10, 0x10, 0x0 } },
+       { S5P_CSSYS_MEM_LOWPWR,                 { 0x3, 0x0, 0x0 } },
+       { S5P_CSSYS_MEM_OPTION,                 { 0x10, 0x10, 0x0 } },
+       { S5P_SECSS_MEM_LOWPWR,                 { 0x3, 0x0, 0x0 } },
+       { S5P_SECSS_MEM_OPTION,                 { 0x10, 0x10, 0x0 } },
+       { S5P_ROTATOR_MEM_LOWPWR,               { 0x3, 0x0, 0x0 } },
+       { S5P_ROTATOR_MEM_OPTION,               { 0x10, 0x10, 0x0 } },
+       { S5P_PAD_RETENTION_DRAM_LOWPWR,        { 0x1, 0x0, 0x0 } },
+       { S5P_PAD_RETENTION_MAUDIO_LOWPWR,      { 0x1, 0x1, 0x0 } },
+       { S5P_PAD_RETENTION_GPIO_LOWPWR,        { 0x1, 0x0, 0x0 } },
+       { S5P_PAD_RETENTION_UART_LOWPWR,        { 0x1, 0x0, 0x0 } },
+       { S5P_PAD_RETENTION_MMCA_LOWPWR,        { 0x1, 0x0, 0x0 } },
+       { S5P_PAD_RETENTION_MMCB_LOWPWR,        { 0x1, 0x0, 0x0 } },
+       { S5P_PAD_RETENTION_EBIA_LOWPWR,        { 0x1, 0x0, 0x0 } },
+       { S5P_PAD_RETENTION_EBIB_LOWPWR,        { 0x1, 0x0, 0x0 } },
+       { S5P_PAD_RETENTION_GPIO_COREBLK_LOWPWR,{ 0x1, 0x0, 0x0 } },
+       { S5P_PAD_RETENTION_ISOLATION_LOWPWR,   { 0x1, 0x0, 0x0 } },
+       { S5P_PAD_ISOLATION_COREBLK_LOWPWR,     { 0x1, 0x0, 0x0 } },
+       { S5P_PAD_RETENTION_ALV_SEL_LOWPWR,     { 0x1, 0x0, 0x0 } },
+       { S5P_XUSBXTI_LOWPWR,                   { 0x1, 0x1, 0x0 } },
+       { S5P_XXTI_LOWPWR,                      { 0x1, 0x1, 0x0 } },
+       { S5P_EXT_REGULATOR_LOWPWR,             { 0x1, 0x1, 0x0 } },
+       { S5P_GPIO_MODE_LOWPWR,                 { 0x1, 0x0, 0x0 } },
+       { S5P_GPIO_MODE_COREBLK_LOWPWR,         { 0x1, 0x0, 0x0 } },
+       { S5P_GPIO_MODE_MAUDIO_LOWPWR,          { 0x1, 0x1, 0x0 } },
+       { S5P_TOP_ASB_RESET_LOWPWR,             { 0x1, 0x1, 0x1 } },
+       { S5P_TOP_ASB_ISOLATION_LOWPWR,         { 0x1, 0x0, 0x1 } },
+       { S5P_CAM_LOWPWR,                       { 0x7, 0x0, 0x0 } },
+       { S5P_TV_LOWPWR,                        { 0x7, 0x0, 0x0 } },
+       { S5P_MFC_LOWPWR,                       { 0x7, 0x0, 0x0 } },
+       { S5P_G3D_LOWPWR,                       { 0x7, 0x0, 0x0 } },
+       { S5P_LCD0_LOWPWR,                      { 0x7, 0x0, 0x0 } },
+       { S5P_ISP_LOWPWR,                       { 0x7, 0x0, 0x0 } },
+       { S5P_MAUDIO_LOWPWR,                    { 0x7, 0x7, 0x0 } },
+       { S5P_GPS_LOWPWR,                       { 0x7, 0x0, 0x0 } },
+       { S5P_GPS_ALIVE_LOWPWR,                 { 0x7, 0x0, 0x0 } },
+       { S5P_CMU_SYSCLK_ISP_LOWPWR,            { 0x1, 0x0, 0x0 } },
+       { S5P_CMU_SYSCLK_GPS_LOWPWR,            { 0x1, 0x0, 0x0 } },
+       { PMU_TABLE_END,},
 };
 
 void exynos4_sys_powerdown_conf(enum sys_powerdown mode)
 {
-       unsigned int count = ARRAY_SIZE(sys_powerdown_reg);
+       unsigned int i;
+
+       for (i = 0; (exynos4_pmu_config[i].reg != PMU_TABLE_END) ; i++)
+               __raw_writel(exynos4_pmu_config[i].val[mode],
+                               exynos4_pmu_config[i].reg);
+}
+
+static int __init exynos4_pmu_init(void)
+{
+       exynos4_pmu_config = exynos4210_pmu_config;
+
+       if (soc_is_exynos4210()) {
+               exynos4_pmu_config = exynos4210_pmu_config;
+               pr_info("EXYNOS4210 PMU Initialize\n");
+       } else if (soc_is_exynos4212()) {
+               exynos4_pmu_config = exynos4212_pmu_config;
+               pr_info("EXYNOS4212 PMU Initialize\n");
+       } else {
+               pr_info("EXYNOS4: PMU not supported\n");
+       }
 
-       for (; count > 0; count--)
-               __raw_writel(sys_powerdown_val[count - 1][mode],
-                               sys_powerdown_reg[count - 1]);
+       return 0;
 }
+arch_initcall(exynos4_pmu_init);
index 3700cf32af0f4c95b0c7711b08d6768330ef1af0..5261a7ed09991fd9feba227432a851e22ec2bb59 100644 (file)
@@ -6,7 +6,6 @@ config CPU_S3C2410
        bool
        depends on ARCH_S3C2410
        select CPU_ARM920T
-       select S3C_GPIO_PULL_UP
        select S3C2410_CLOCK
        select CPU_LLSERIAL_S3C2410
        select S3C2410_PM if PM
index b2b2a5bb275e2d6aa8ac405ba6a50ed418fa26c1..ae8e482b642708e8bc206abd3e10214f12a397ef 100644 (file)
@@ -13,7 +13,6 @@
 #ifndef __ASM_ARCH_DMA_H
 #define __ASM_ARCH_DMA_H __FILE__
 
-#include <plat/dma.h>
 #include <linux/sysdev.h>
 
 #define MAX_DMA_TRANSFER_SIZE   0x100000 /* Data Unit is half word  */
@@ -51,6 +50,18 @@ enum dma_ch {
        DMACH_MAX,              /* the end entry */
 };
 
+static inline bool samsung_dma_has_circular(void)
+{
+       return false;
+}
+
+static inline bool samsung_dma_is_dmadev(void)
+{
+       return false;
+}
+
+#include <plat/dma.h>
+
 #define DMACH_LOW_LEVEL        (1<<28) /* use this to specifiy hardware ch no */
 
 /* we have 4 dma channels */
@@ -163,7 +174,7 @@ struct s3c2410_dma_chan {
        struct s3c2410_dma_client *client;
 
        /* channel configuration */
-       enum s3c2410_dmasrc      source;
+       enum dma_data_direction  source;
        enum dma_ch              req_ch;
        unsigned long            dev_addr;
        unsigned long            load_timeout;
@@ -196,9 +207,4 @@ struct s3c2410_dma_chan {
 
 typedef unsigned long dma_device_t;
 
-static inline bool s3c_dma_has_circular(void)
-{
-       return false;
-}
-
 #endif /* __ASM_ARCH_DMA_H */
index bab1392017614bc964a6586f92af65287b7b8e7a..c53ad34c6579d53bef8c2acb9fc8e614133521c0 100644 (file)
@@ -1,98 +1 @@
-/* arch/arm/mach-s3c2410/include/mach/gpio-fns.h
- *
- * Copyright (c) 2003-2009 Simtec Electronics
- *     Ben Dooks <ben@simtec.co.uk>
- *
- * S3C2410 - hardware
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifndef __MACH_GPIO_FNS_H
-#define __MACH_GPIO_FNS_H __FILE__
-
-/* These functions are in the to-be-removed category and it is strongly
- * encouraged not to use these in new code. They will be marked deprecated
- * very soon.
- *
- * Most of the functionality can be either replaced by the gpiocfg calls
- * for the s3c platform or by the generic GPIOlib API.
- *
- * As of 2.6.35-rc, these will be removed, with the few drivers using them
- * either replaced or given a wrapper until the calls can be removed.
-*/
-
-#include <plat/gpio-cfg.h>
-
-static inline void s3c2410_gpio_cfgpin(unsigned int pin, unsigned int cfg)
-{
-       /* 1:1 mapping between cfgpin and setcfg calls at the moment */
-       s3c_gpio_cfgpin(pin, cfg);
-}
-
-/* external functions for GPIO support
- *
- * These allow various different clients to access the same GPIO
- * registers without conflicting. If your driver only owns the entire
- * GPIO register, then it is safe to ioremap/__raw_{read|write} to it.
-*/
-
-extern unsigned int s3c2410_gpio_getcfg(unsigned int pin);
-
-/* s3c2410_gpio_getirq
- *
- * turn the given pin number into the corresponding IRQ number
- *
- * returns:
- *     < 0 = no interrupt for this pin
- *     >=0 = interrupt number for the pin
-*/
-
-extern int s3c2410_gpio_getirq(unsigned int pin);
-
-/* s3c2410_gpio_irqfilter
- *
- * set the irq filtering on the given pin
- *
- * on = 0 => disable filtering
- *      1 => enable filtering
- *
- * config = S3C2410_EINTFLT_PCLK or S3C2410_EINTFLT_EXTCLK orred with
- *          width of filter (0 through 63)
- *
- *
-*/
-
-extern int s3c2410_gpio_irqfilter(unsigned int pin, unsigned int on,
-                                 unsigned int config);
-
-/* s3c2410_gpio_pullup
- *
- * This call should be replaced with s3c_gpio_setpull().
- *
- * As a note, there is currently no distinction between pull-up and pull-down
- * in the s3c24xx series devices with only an on/off configuration.
- */
-
-/* s3c2410_gpio_pullup
- *
- * configure the pull-up control on the given pin
- *
- * to = 1 => disable the pull-up
- *      0 => enable the pull-up
- *
- * eg;
- *
- *   s3c2410_gpio_pullup(S3C2410_GPB(0), 0);
- *   s3c2410_gpio_pullup(S3C2410_GPE(8), 0);
-*/
-
-extern void s3c2410_gpio_pullup(unsigned int pin, unsigned int to);
-
-extern void s3c2410_gpio_setpin(unsigned int pin, unsigned int to);
-
-extern unsigned int s3c2410_gpio_getpin(unsigned int pin);
-
-#endif /* __MACH_GPIO_FNS_H */
+#include <plat/gpio-fns.h>
index d67819dde42a11cba9ab5bb6c1abb89ae14f189d..c410a078622ce62efc89bc8b4b2114b7c31a613c 100644 (file)
 
 #include <mach/regs-gpio.h>
 
-extern struct s3c_gpio_chip s3c24xx_gpios[];
+extern struct samsung_gpio_chip s3c24xx_gpios[];
 
-static inline struct s3c_gpio_chip *s3c_gpiolib_getchip(unsigned int pin)
+static inline struct samsung_gpio_chip *samsung_gpiolib_getchip(unsigned int pin)
 {
-       struct s3c_gpio_chip *chip;
+       struct samsung_gpio_chip *chip;
 
        if (pin > S3C_GPIO_END)
                return NULL;
index 45eea5210c87d55a76c34b752fdf20954c8e7df0..2eef7e6f76758497094c1b0fe8865b0ee34cda2a 100644 (file)
@@ -64,4 +64,4 @@ static inline void s3c_pm_arch_update_uart(void __iomem *regs,
 }
 
 static inline void s3c_pm_restored_gpios(void) { }
-static inline void s3c_pm_saved_gpios(void) { }
+static inline void samsung_pm_saved_gpios(void) { }
index 5e06c72658358ef3d263b84e61766635b03c37b3..df6434f326f0585d63d3d5a49115f87de75914e4 100644 (file)
 #define S3C2443_PCLKCON_UART3          (1<<3)
 #define S3C2443_PCLKCON_IIC            (1<<4)
 #define S3C2443_PCLKCON_SDI            (1<<5)
+#define S3C2443_PCLKCON_HSSPI          (1<<6)
 #define S3C2443_PCLKCON_ADC            (1<<7)
 #define S3C2443_PCLKCON_AC97           (1<<8)
 #define S3C2443_PCLKCON_IIS            (1<<9)
index f1d3bd8f6f179dfc9c54ab41953cde1ba389ca2b..a99c2f4a523f2e8e81a71ad6940654a2e1e7c9a4 100644 (file)
@@ -72,8 +72,8 @@ void __init s3c2410_init_uarts(struct s3c2410_uartcfg *cfg, int no)
 
 void __init s3c2410_map_io(void)
 {
-       s3c24xx_gpiocfg_default.set_pull = s3c_gpio_setpull_1up;
-       s3c24xx_gpiocfg_default.get_pull = s3c_gpio_getpull_1up;
+       s3c24xx_gpiocfg_default.set_pull = s3c24xx_gpio_setpull_1up;
+       s3c24xx_gpiocfg_default.get_pull = s3c24xx_gpio_getpull_1up;
 
        iotable_init(s3c2410_iodesc, ARRAY_SIZE(s3c2410_iodesc));
 }
index c61e3261615d28be2444bf8c16f0833f9aefbb83..d2a7d5ef3e67be0178fc66b6dd79f1338cf8f270 100644 (file)
@@ -130,11 +130,11 @@ static struct s3c24xx_dma_map __initdata s3c2412_dma_mappings[] = {
 
 static void s3c2412_dma_direction(struct s3c2410_dma_chan *chan,
                                  struct s3c24xx_dma_map *map,
-                                 enum s3c2410_dmasrc dir)
+                                 enum dma_data_direction dir)
 {
        unsigned long chsel;
 
-       if (dir == S3C2410_DMASRC_HW)
+       if (dir == DMA_FROM_DEVICE)
                chsel = map->channels_rx[0];
        else
                chsel = map->channels[0];
diff --git a/arch/arm/mach-s3c2412/gpio.c b/arch/arm/mach-s3c2412/gpio.c
new file mode 100644 (file)
index 0000000..4526f6b
--- /dev/null
@@ -0,0 +1,62 @@
+/* linux/arch/arm/mach-s3c2412/gpio.c
+ *
+ * Copyright (c) 2007 Simtec Electronics
+ *     Ben Dooks <ben@simtec.co.uk>
+ *
+ * http://armlinux.simtec.co.uk/.
+ *
+ * S3C2412/S3C2413 specific GPIO support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/gpio.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+
+#include <mach/regs-gpio.h>
+#include <mach/hardware.h>
+
+#include <plat/gpio-core.h>
+
+int s3c2412_gpio_set_sleepcfg(unsigned int pin, unsigned int state)
+{
+       struct samsung_gpio_chip *chip = samsung_gpiolib_getchip(pin);
+       unsigned long offs = pin - chip->chip.base;
+       unsigned long flags;
+       unsigned long slpcon;
+
+       offs *= 2;
+
+       if (pin < S3C2410_GPB(0))
+               return -EINVAL;
+
+       if (pin >= S3C2410_GPF(0) &&
+           pin <= S3C2410_GPG(16))
+               return -EINVAL;
+
+       if (pin > S3C2410_GPH(16))
+               return -EINVAL;
+
+       local_irq_save(flags);
+
+       slpcon = __raw_readl(chip->base + 0x0C);
+
+       slpcon &= ~(3 << offs);
+       slpcon |= state << offs;
+
+       __raw_writel(slpcon, chip->base + 0x0C);
+
+       local_irq_restore(flags);
+
+       return 0;
+}
+
+EXPORT_SYMBOL(s3c2412_gpio_set_sleepcfg);
index 69b48a7d1dbdb4502d55d103bb1fa382def5538e..84c7b03e5a306b239d851ad67b967fda1f30719b 100644 (file)
@@ -13,7 +13,6 @@ config CPU_S3C2416
        select CPU_ARM926T
        select S3C2416_DMA if S3C2410_DMA
        select CPU_LLSERIAL_S3C2440
-       select S3C_GPIO_PULL_UPDOWN
        select SAMSUNG_CLKSRC
        select S3C2443_CLOCK
        help
index 21a5e81f0ab570460ba67c99fd017c32df566838..196fb37f4b19750b71c11ad2132c7324da5db330 100644 (file)
@@ -38,6 +38,32 @@ static unsigned int armdiv[8] = {
        [7] = 8,
 };
 
+static struct clksrc_clk hsspi_eplldiv = {
+       .clk = {
+               .name   = "hsspi-eplldiv",
+               .parent = &clk_esysclk.clk,
+               .ctrlbit = (1 << 14),
+               .enable = s3c2443_clkcon_enable_s,
+       },
+       .reg_div = { .reg = S3C2443_CLKDIV1, .size = 2, .shift = 24 },
+};
+
+static struct clk *hsspi_sources[] = {
+       [0] = &hsspi_eplldiv.clk,
+       [1] = NULL, /* to fix */
+};
+
+static struct clksrc_clk hsspi_mux = {
+       .clk    = {
+               .name   = "hsspi-if",
+       },
+       .sources = &(struct clksrc_sources) {
+               .sources = hsspi_sources,
+               .nr_sources = ARRAY_SIZE(hsspi_sources),
+       },
+       .reg_src = { .reg = S3C2443_CLKSRC, .size = 1, .shift = 18 },
+};
+
 static struct clksrc_clk hsmmc_div[] = {
        [0] = {
                .clk = {
@@ -114,6 +140,8 @@ void __init_or_cpufreq s3c2416_setup_clocks(void)
 
 
 static struct clksrc_clk *clksrcs[] __initdata = {
+       &hsspi_eplldiv,
+       &hsspi_mux,
        &hsmmc_div[0],
        &hsmmc_div[1],
        &hsmmc_mux[0],
index 494ce913dc9571752f81590784de2213bfc46bcb..3156b7a71371c5b78c60c52fa0e5c56b65e65d30 100644 (file)
@@ -118,8 +118,8 @@ void __init s3c2416_init_uarts(struct s3c2410_uartcfg *cfg, int no)
 
 void __init s3c2416_map_io(void)
 {
-       s3c24xx_gpiocfg_default.set_pull = s3c_gpio_setpull_updown;
-       s3c24xx_gpiocfg_default.get_pull = s3c_gpio_getpull_updown;
+       s3c24xx_gpiocfg_default.set_pull = samsung_gpio_setpull_updown;
+       s3c24xx_gpiocfg_default.get_pull = samsung_gpio_getpull_updown;
 
        /* initialize device information early */
        s3c2416_default_sdhci0();
index c461fb8e15c02db73448dbfabbb25c4cb46661f5..914e620f1257a75d808077d41d91599466119a58 100644 (file)
@@ -5,7 +5,6 @@
 config CPU_S3C2440
        bool
        select CPU_ARM920T
-       select S3C_GPIO_PULL_UP
        select S3C2410_CLOCK
        select S3C2410_PM if PM
        select S3C2440_DMA if S3C2410_DMA
@@ -17,7 +16,6 @@ config CPU_S3C2440
 config CPU_S3C2442
        bool
        select CPU_ARM920T
-       select S3C_GPIO_PULL_DOWN
        select S3C2410_CLOCK
        select S3C2410_PM if PM
        select CPU_S3C244X
index ce99ff72838defb31fd4fa37f04a61f2660bbc73..fc84e481efcfca3e7da5535590971bb8af4deb27 100644 (file)
@@ -68,6 +68,6 @@ void __init s3c2440_map_io(void)
 {
        s3c244x_map_io();
 
-       s3c24xx_gpiocfg_default.set_pull = s3c_gpio_setpull_1up;
-       s3c24xx_gpiocfg_default.get_pull = s3c_gpio_getpull_1up;
+       s3c24xx_gpiocfg_default.set_pull = s3c24xx_gpio_setpull_1up;
+       s3c24xx_gpiocfg_default.get_pull = s3c24xx_gpio_getpull_1up;
 }
index 9ad99f8016a174b119c3ff46bf51e1191320146f..48e273ce9f9a798a7005c0414cfb77085de9a2b2 100644 (file)
@@ -180,6 +180,6 @@ void __init s3c2442_map_io(void)
 {
        s3c244x_map_io();
 
-       s3c24xx_gpiocfg_default.set_pull = s3c_gpio_setpull_1down;
-       s3c24xx_gpiocfg_default.get_pull = s3c_gpio_getpull_1down;
+       s3c24xx_gpiocfg_default.set_pull = s3c24xx_gpio_setpull_1down;
+       s3c24xx_gpiocfg_default.get_pull = s3c24xx_gpio_getpull_1down;
 }
index d8eb86823df7b92a3027bcd384cebbb0e6941a3f..8814031516ce2de3f15e5d7757b3579df5169763 100644 (file)
@@ -10,7 +10,6 @@ config CPU_S3C2443
        select CPU_LLSERIAL_S3C2440
        select SAMSUNG_CLKSRC
        select S3C2443_CLOCK
-       select S3C_GPIO_PULL_S3C2443
        help
          Support for the S3C2443 SoC from the S3C24XX line
 
index 38058af48972d7cf10409885b6e7578032a94d90..cd51d04e1de7f429a3fce43ff1db4e801a5ed480 100644 (file)
 
 /* clock selections */
 
-static struct clk clk_i2s_ext = {
-       .name           = "i2s-ext",
-};
-
 /* armdiv
  *
  * this clock is sourced from msysclk and can have a number of
@@ -173,7 +169,7 @@ static struct clksrc_clk clk_arm = {
 
 static struct clksrc_clk clk_hsspi = {
        .clk    = {
-               .name           = "hsspi",
+               .name           = "hsspi-if",
                .parent         = &clk_esysclk.clk,
                .ctrlbit        = S3C2443_SCLKCON_HSSPICLK,
                .enable         = s3c2443_clkcon_enable_s,
@@ -235,48 +231,6 @@ static struct clk clk_hsmmc = {
        },
 };
 
-/* i2s_eplldiv
- *
- * This clock is the output from the I2S divisor of ESYSCLK, and is separate
- * from the mux that comes after it (cannot merge into one single clock)
-*/
-
-static struct clksrc_clk clk_i2s_eplldiv = {
-       .clk    = {
-               .name           = "i2s-eplldiv",
-               .parent         = &clk_esysclk.clk,
-       },
-       .reg_div = { .reg = S3C2443_CLKDIV1, .size = 4, .shift = 12, },
-};
-
-/* i2s-ref
- *
- * i2s bus reference clock, selectable from external, esysclk or epllref
- *
- * Note, this used to be two clocks, but was compressed into one.
-*/
-
-struct clk *clk_i2s_srclist[] = {
-       [0] = &clk_i2s_eplldiv.clk,
-       [1] = &clk_i2s_ext,
-       [2] = &clk_epllref.clk,
-       [3] = &clk_epllref.clk,
-};
-
-static struct clksrc_clk clk_i2s = {
-       .clk    = {
-               .name           = "i2s-if",
-               .ctrlbit        = S3C2443_SCLKCON_I2SCLK,
-               .enable         = s3c2443_clkcon_enable_s,
-
-       },
-       .sources = &(struct clksrc_sources) {
-               .sources = clk_i2s_srclist,
-               .nr_sources = ARRAY_SIZE(clk_i2s_srclist),
-       },
-       .reg_src = { .reg = S3C2443_CLKSRC, .size = 2, .shift = 14 },
-};
-
 /* standard clock definitions */
 
 static struct clk init_clocks_off[] = {
@@ -285,11 +239,6 @@ static struct clk init_clocks_off[] = {
                .parent         = &clk_p,
                .enable         = s3c2443_clkcon_enable_p,
                .ctrlbit        = S3C2443_PCLKCON_SDI,
-       }, {
-               .name           = "iis",
-               .parent         = &clk_p,
-               .enable         = s3c2443_clkcon_enable_p,
-               .ctrlbit        = S3C2443_PCLKCON_IIS,
        }, {
                .name           = "spi",
                .devname        = "s3c2410-spi.0",
@@ -312,8 +261,6 @@ static struct clk init_clocks[] = {
 
 static struct clksrc_clk *clksrcs[] __initdata = {
        &clk_arm,
-       &clk_i2s_eplldiv,
-       &clk_i2s,
        &clk_hsspi,
        &clk_hsmmc_div,
 };
index e6a28ba52c7d16f9c8468a4f186bcdf3296b8eb5..5df6458ddd42160e7bed0115d73f5e45a973ea74 100644 (file)
@@ -90,8 +90,8 @@ void __init s3c2443_init_uarts(struct s3c2410_uartcfg *cfg, int no)
 
 void __init s3c2443_map_io(void)
 {
-       s3c24xx_gpiocfg_default.set_pull = s3c_gpio_setpull_s3c2443;
-       s3c24xx_gpiocfg_default.get_pull = s3c_gpio_getpull_s3c2443;
+       s3c24xx_gpiocfg_default.set_pull = s3c2443_gpio_setpull;
+       s3c24xx_gpiocfg_default.get_pull = s3c2443_gpio_getpull;
 
        iotable_init(s3c2443_iodesc, ARRAY_SIZE(s3c2443_iodesc));
 }
index f057b6ae4f905d65f9f837cceebf3e0c573bfd74..5552e048c2be510608bd6fbd1f1418c9e5ab74a7 100644 (file)
@@ -288,5 +288,6 @@ config MACH_WLF_CRAGG_6410
        select S3C_DEV_RTC
        select S3C64XX_DEV_SPI
        select S3C24XX_GPIO_EXTRA128
+       select I2C
        help
          Machine support for the Wolfson Cragganmore S3C6410 variant.
index 61b4034a0c224d24ea95a135487be42ecae112dc..902ab9ace93b48a1e7a0f1b20defefaaa7eea843 100644 (file)
@@ -13,7 +13,6 @@ obj-                          :=
 # Core files
 obj-y                          += cpu.o
 obj-y                          += clock.o
-obj-y                          += gpiolib.o
 
 # Core support for S3C6400 system
 
@@ -55,7 +54,7 @@ obj-$(CONFIG_MACH_HMT)                += mach-hmt.o
 obj-$(CONFIG_MACH_SMARTQ)      += mach-smartq.o
 obj-$(CONFIG_MACH_SMARTQ5)     += mach-smartq5.o
 obj-$(CONFIG_MACH_SMARTQ7)     += mach-smartq7.o
-obj-$(CONFIG_MACH_WLF_CRAGG_6410) += mach-crag6410.o
+obj-$(CONFIG_MACH_WLF_CRAGG_6410) += mach-crag6410.o mach-crag6410-module.o
 
 # device support
 
index 8cf39e33579e3bb9c7d30eceb6afcaa5914e6d2c..872e68361eb44d8f289c963e0cf0456d01dc7822 100644 (file)
@@ -744,7 +744,13 @@ void __init_or_cpufreq s3c6400_setup_clocks(void)
        printk(KERN_INFO "S3C64XX: PLL settings, A=%ld, M=%ld, E=%ld\n",
               apll, mpll, epll);
 
-       hclk2 = mpll / GET_DIV(clkdiv0, S3C6400_CLKDIV0_HCLK2);
+       if(__raw_readl(S3C64XX_OTHERS) & S3C64XX_OTHERS_SYNCMUXSEL)
+               /* Synchronous mode */
+               hclk2 = apll / GET_DIV(clkdiv0, S3C6400_CLKDIV0_HCLK2);
+       else
+               /* Asynchronous mode */
+               hclk2 = mpll / GET_DIV(clkdiv0, S3C6400_CLKDIV0_HCLK2);
+
        hclk = hclk2 / GET_DIV(clkdiv0, S3C6400_CLKDIV0_HCLK);
        pclk = hclk2 / GET_DIV(clkdiv0, S3C6400_CLKDIV0_PCLK);
 
index 204bfafe4bfc214677e60fedbef98e4f43a5dd93..17d62f4f8204a2c551903914f5e5df4588e79fa4 100644 (file)
@@ -147,14 +147,14 @@ static void s3c64xx_dma_fill_lli(struct s3c2410_dma_chan *chan,
        u32 control0, control1;
 
        switch (chan->source) {
-       case S3C2410_DMASRC_HW:
+       case DMA_FROM_DEVICE:
                src = chan->dev_addr;
                dst = data;
                control0 = PL080_CONTROL_SRC_AHB2;
                control0 |= PL080_CONTROL_DST_INCR;
                break;
 
-       case S3C2410_DMASRC_MEM:
+       case DMA_TO_DEVICE:
                src = data;
                dst = chan->dev_addr;
                control0 = PL080_CONTROL_DST_AHB2;
@@ -416,7 +416,7 @@ EXPORT_SYMBOL(s3c2410_dma_enqueue);
 
 
 int s3c2410_dma_devconfig(enum dma_ch channel,
-                         enum s3c2410_dmasrc source,
+                         enum dma_data_direction source,
                          unsigned long devaddr)
 {
        struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel);
@@ -437,11 +437,11 @@ int s3c2410_dma_devconfig(enum dma_ch channel,
        pr_debug("%s: peripheral %d\n", __func__, peripheral);
 
        switch (source) {
-       case S3C2410_DMASRC_HW:
+       case DMA_FROM_DEVICE:
                config = 2 << PL080_CONFIG_FLOW_CONTROL_SHIFT;
                config |= peripheral << PL080_CONFIG_SRC_SEL_SHIFT;
                break;
-       case S3C2410_DMASRC_MEM:
+       case DMA_TO_DEVICE:
                config = 1 << PL080_CONFIG_FLOW_CONTROL_SHIFT;
                config |= peripheral << PL080_CONFIG_DST_SEL_SHIFT;
                break;
@@ -740,7 +740,7 @@ static int __init s3c64xx_dma_init(void)
        }
 
        /* Set all DMA configuration to be DMA, not SDMA */
-       writel(0xffffff, S3C_SYSREG(0x110));
+       writel(0xffffff, S3C64XX_SDMA_SEL);
 
        /* Register standard DMA controllers */
        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 (file)
index 92b0908..0000000
+++ /dev/null
@@ -1,290 +0,0 @@
-/* arch/arm/plat-s3c64xx/gpiolib.c
- *
- * Copyright 2008 Openmoko, Inc.
- * Copyright 2008 Simtec Electronics
- *      Ben Dooks <ben@simtec.co.uk>
- *      http://armlinux.simtec.co.uk/
- *
- * S3C64XX - GPIOlib support 
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/kernel.h>
-#include <linux/irq.h>
-#include <linux/io.h>
-#include <linux/gpio.h>
-
-#include <mach/map.h>
-
-#include <plat/gpio-core.h>
-#include <plat/gpio-cfg.h>
-#include <plat/gpio-cfg-helpers.h>
-#include <mach/regs-gpio.h>
-
-/* GPIO bank summary:
- *
- * Bank        GPIOs   Style   SlpCon  ExtInt Group
- * A   8       4Bit    Yes     1
- * B   7       4Bit    Yes     1
- * C   8       4Bit    Yes     2
- * D   5       4Bit    Yes     3
- * E   5       4Bit    Yes     None
- * F   16      2Bit    Yes     4 [1]
- * G   7       4Bit    Yes     5
- * H   10      4Bit[2] Yes     6
- * I   16      2Bit    Yes     None
- * J   12      2Bit    Yes     None
- * K   16      4Bit[2] No      None
- * L   15      4Bit[2] No      None
- * M   6       4Bit    No      IRQ_EINT
- * N   16      2Bit    No      IRQ_EINT
- * O   16      2Bit    Yes     7
- * P   15      2Bit    Yes     8
- * Q   9       2Bit    Yes     9
- *
- * [1] BANKF pins 14,15 do not form part of the external interrupt sources
- * [2] BANK has two control registers, GPxCON0 and GPxCON1
- */
-
-static struct s3c_gpio_cfg gpio_4bit_cfg_noint = {
-       .set_config     = s3c_gpio_setcfg_s3c64xx_4bit,
-       .get_config     = s3c_gpio_getcfg_s3c64xx_4bit,
-       .set_pull       = s3c_gpio_setpull_updown,
-       .get_pull       = s3c_gpio_getpull_updown,
-};
-
-static struct s3c_gpio_cfg gpio_4bit_cfg_eint0111 = {
-       .cfg_eint       = 7,
-       .set_config     = s3c_gpio_setcfg_s3c64xx_4bit,
-       .get_config     = s3c_gpio_getcfg_s3c64xx_4bit,
-       .set_pull       = s3c_gpio_setpull_updown,
-       .get_pull       = s3c_gpio_getpull_updown,
-};
-
-static struct s3c_gpio_cfg gpio_4bit_cfg_eint0011 = {
-       .cfg_eint       = 3,
-       .get_config     = s3c_gpio_getcfg_s3c64xx_4bit,
-       .set_config     = s3c_gpio_setcfg_s3c64xx_4bit,
-       .set_pull       = s3c_gpio_setpull_updown,
-       .get_pull       = s3c_gpio_getpull_updown,
-};
-
-static int s3c64xx_gpio2int_gpm(struct gpio_chip *chip, unsigned pin)
-{
-       return pin < 5 ? IRQ_EINT(23) + pin : -ENXIO;
-}
-
-static struct s3c_gpio_chip gpio_4bit[] = {
-       {
-               .base   = S3C64XX_GPA_BASE,
-               .config = &gpio_4bit_cfg_eint0111,
-               .chip   = {
-                       .base   = S3C64XX_GPA(0),
-                       .ngpio  = S3C64XX_GPIO_A_NR,
-                       .label  = "GPA",
-               },
-       }, {
-               .base   = S3C64XX_GPB_BASE,
-               .config = &gpio_4bit_cfg_eint0111,
-               .chip   = {
-                       .base   = S3C64XX_GPB(0),
-                       .ngpio  = S3C64XX_GPIO_B_NR,
-                       .label  = "GPB",
-               },
-       }, {
-               .base   = S3C64XX_GPC_BASE,
-               .config = &gpio_4bit_cfg_eint0111,
-               .chip   = {
-                       .base   = S3C64XX_GPC(0),
-                       .ngpio  = S3C64XX_GPIO_C_NR,
-                       .label  = "GPC",
-               },
-       }, {
-               .base   = S3C64XX_GPD_BASE,
-               .config = &gpio_4bit_cfg_eint0111,
-               .chip   = {
-                       .base   = S3C64XX_GPD(0),
-                       .ngpio  = S3C64XX_GPIO_D_NR,
-                       .label  = "GPD",
-               },
-       }, {
-               .base   = S3C64XX_GPE_BASE,
-               .config = &gpio_4bit_cfg_noint,
-               .chip   = {
-                       .base   = S3C64XX_GPE(0),
-                       .ngpio  = S3C64XX_GPIO_E_NR,
-                       .label  = "GPE",
-               },
-       }, {
-               .base   = S3C64XX_GPG_BASE,
-               .config = &gpio_4bit_cfg_eint0111,
-               .chip   = {
-                       .base   = S3C64XX_GPG(0),
-                       .ngpio  = S3C64XX_GPIO_G_NR,
-                       .label  = "GPG",
-               },
-       }, {
-               .base   = S3C64XX_GPM_BASE,
-               .config = &gpio_4bit_cfg_eint0011,
-               .chip   = {
-                       .base   = S3C64XX_GPM(0),
-                       .ngpio  = S3C64XX_GPIO_M_NR,
-                       .label  = "GPM",
-                       .to_irq = s3c64xx_gpio2int_gpm,
-               },
-       },
-};
-
-static int s3c64xx_gpio2int_gpl(struct gpio_chip *chip, unsigned pin)
-{
-       return pin >= 8 ? IRQ_EINT(16) + pin - 8 : -ENXIO;
-}
-
-static struct s3c_gpio_chip gpio_4bit2[] = {
-       {
-               .base   = S3C64XX_GPH_BASE + 0x4,
-               .config = &gpio_4bit_cfg_eint0111,
-               .chip   = {
-                       .base   = S3C64XX_GPH(0),
-                       .ngpio  = S3C64XX_GPIO_H_NR,
-                       .label  = "GPH",
-               },
-       }, {
-               .base   = S3C64XX_GPK_BASE + 0x4,
-               .config = &gpio_4bit_cfg_noint,
-               .chip   = {
-                       .base   = S3C64XX_GPK(0),
-                       .ngpio  = S3C64XX_GPIO_K_NR,
-                       .label  = "GPK",
-               },
-       }, {
-               .base   = S3C64XX_GPL_BASE + 0x4,
-               .config = &gpio_4bit_cfg_eint0011,
-               .chip   = {
-                       .base   = S3C64XX_GPL(0),
-                       .ngpio  = S3C64XX_GPIO_L_NR,
-                       .label  = "GPL",
-                       .to_irq = s3c64xx_gpio2int_gpl,
-               },
-       },
-};
-
-static struct s3c_gpio_cfg gpio_2bit_cfg_noint = {
-       .set_config     = s3c_gpio_setcfg_s3c24xx,
-       .get_config     = s3c_gpio_getcfg_s3c24xx,
-       .set_pull       = s3c_gpio_setpull_updown,
-       .get_pull       = s3c_gpio_getpull_updown,
-};
-
-static struct s3c_gpio_cfg gpio_2bit_cfg_eint10 = {
-       .cfg_eint       = 2,
-       .set_config     = s3c_gpio_setcfg_s3c24xx,
-       .get_config     = s3c_gpio_getcfg_s3c24xx,
-       .set_pull       = s3c_gpio_setpull_updown,
-       .get_pull       = s3c_gpio_getpull_updown,
-};
-
-static struct s3c_gpio_cfg gpio_2bit_cfg_eint11 = {
-       .cfg_eint       = 3,
-       .set_config     = s3c_gpio_setcfg_s3c24xx,
-       .get_config     = s3c_gpio_getcfg_s3c24xx,
-       .set_pull       = s3c_gpio_setpull_updown,
-       .get_pull       = s3c_gpio_getpull_updown,
-};
-
-static struct s3c_gpio_chip gpio_2bit[] = {
-       {
-               .base   = S3C64XX_GPF_BASE,
-               .config = &gpio_2bit_cfg_eint11,
-               .chip   = {
-                       .base   = S3C64XX_GPF(0),
-                       .ngpio  = S3C64XX_GPIO_F_NR,
-                       .label  = "GPF",
-               },
-       }, {
-               .base   = S3C64XX_GPI_BASE,
-               .config = &gpio_2bit_cfg_noint,
-               .chip   = {
-                       .base   = S3C64XX_GPI(0),
-                       .ngpio  = S3C64XX_GPIO_I_NR,
-                       .label  = "GPI",
-               },
-       }, {
-               .base   = S3C64XX_GPJ_BASE,
-               .config = &gpio_2bit_cfg_noint,
-               .chip   = {
-                       .base   = S3C64XX_GPJ(0),
-                       .ngpio  = S3C64XX_GPIO_J_NR,
-                       .label  = "GPJ",
-               },
-       }, {
-               .base   = S3C64XX_GPN_BASE,
-               .irq_base = IRQ_EINT(0),
-               .config = &gpio_2bit_cfg_eint10,
-               .chip   = {
-                       .base   = S3C64XX_GPN(0),
-                       .ngpio  = S3C64XX_GPIO_N_NR,
-                       .label  = "GPN",
-                       .to_irq = samsung_gpiolib_to_irq,
-               },
-       }, {
-               .base   = S3C64XX_GPO_BASE,
-               .config = &gpio_2bit_cfg_eint11,
-               .chip   = {
-                       .base   = S3C64XX_GPO(0),
-                       .ngpio  = S3C64XX_GPIO_O_NR,
-                       .label  = "GPO",
-               },
-       }, {
-               .base   = S3C64XX_GPP_BASE,
-               .config = &gpio_2bit_cfg_eint11,
-               .chip   = {
-                       .base   = S3C64XX_GPP(0),
-                       .ngpio  = S3C64XX_GPIO_P_NR,
-                       .label  = "GPP",
-               },
-       }, {
-               .base   = S3C64XX_GPQ_BASE,
-               .config = &gpio_2bit_cfg_eint11,
-               .chip   = {
-                       .base   = S3C64XX_GPQ(0),
-                       .ngpio  = S3C64XX_GPIO_Q_NR,
-                       .label  = "GPQ",
-               },
-       },
-};
-
-static __init void s3c64xx_gpiolib_add_2bit(struct s3c_gpio_chip *chip)
-{
-       chip->pm = __gpio_pm(&s3c_gpio_pm_2bit);
-}
-
-static __init void s3c64xx_gpiolib_add(struct s3c_gpio_chip *chips,
-                                      int nr_chips,
-                                      void (*fn)(struct s3c_gpio_chip *))
-{
-       for (; nr_chips > 0; nr_chips--, chips++) {
-               if (fn)
-                       (fn)(chips);
-               s3c_gpiolib_add(chips);
-       }
-}
-
-static __init int s3c64xx_gpiolib_init(void)
-{
-       s3c64xx_gpiolib_add(gpio_4bit, ARRAY_SIZE(gpio_4bit),
-                           samsung_gpiolib_add_4bit);
-
-       s3c64xx_gpiolib_add(gpio_4bit2, ARRAY_SIZE(gpio_4bit2),
-                           samsung_gpiolib_add_4bit2);
-
-       s3c64xx_gpiolib_add(gpio_2bit, ARRAY_SIZE(gpio_2bit),
-                           s3c64xx_gpiolib_add_2bit);
-
-       return 0;
-}
-
-core_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 (file)
index 0000000..be9074e
--- /dev/null
@@ -0,0 +1,23 @@
+/* Cragganmore 6410 shared definitions
+ *
+ * Copyright 2011 Wolfson Microelectronics plc
+ *     Mark Brown <broonie@opensource.wolfsonmicro.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef MACH_CRAG6410_H
+#define MACH_CRAG6410_H
+
+#include <linux/gpio.h>
+
+#define BANFF_PMIC_IRQ_BASE            IRQ_BOARD_START
+#define GLENFARCLAS_PMIC_IRQ_BASE      (IRQ_BOARD_START + 64)
+
+#define PCA935X_GPIO_BASE              GPIO_BOARD_START
+#define CODEC_GPIO_BASE                (GPIO_BOARD_START + 8)
+#define GLENFARCLAS_PMIC_GPIO_BASE     (GPIO_BOARD_START + 16)
+
+#endif
index 0a5d9268a23eedb856759f8f367f12510bd52985..fe1a98cf0e4c7cb3a63311efec61f507e9ebf8e2 100644 (file)
@@ -58,11 +58,15 @@ enum dma_ch {
        DMACH_MAX               /* the end */
 };
 
-static __inline__ bool s3c_dma_has_circular(void)
+static inline bool samsung_dma_has_circular(void)
 {
        return true;
 }
 
+static inline bool samsung_dma_is_dmadev(void)
+{
+       return false;
+}
 #define S3C2410_DMAF_CIRCULAR          (1 << 0)
 
 #include <plat/dma.h>
@@ -95,7 +99,7 @@ struct s3c2410_dma_chan {
        unsigned char            peripheral;
 
        unsigned int             flags;
-       enum s3c2410_dmasrc      source;
+       enum dma_data_direction  source;
 
 
        dma_addr_t              dev_addr;
index 38659bebe4b17de87387dfd4f8d60f23615bfe9b..fcf3dcabb6944678e9dfabd5cbc67a3e490deade 100644 (file)
@@ -104,7 +104,7 @@ static inline void s3c_pm_restored_gpios(void)
        __raw_writel(0, S3C64XX_SLPEN);
 }
 
-static inline void s3c_pm_saved_gpios(void)
+static inline void samsung_pm_saved_gpios(void)
 {
        /* turn on the sleep mode and keep it there, as it seems that during
         * suspend the xCON registers get re-set and thus you can end up with
index 69b78d9f83b8f2b4f04b72d85cf3e5562fa10c9a..b91e02093289d6af7c9a216adaa1273acf8f5f4b 100644 (file)
 #define S3C64XX_AHB_CON1       S3C_SYSREG(0x104)
 #define S3C64XX_AHB_CON2       S3C_SYSREG(0x108)
 
+#define S3C64XX_SDMA_SEL       S3C_SYSREG(0x110)
+
 #define S3C64XX_OTHERS         S3C_SYSREG(0x900)
 
 #define S3C64XX_OTHERS_USBMASK (1 << 16)
+#define S3C64XX_OTHERS_SYNCMUXSEL      (1 << 6)
 
 #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 (file)
index 0000000..6666856
--- /dev/null
@@ -0,0 +1,182 @@
+/* Speyside modules for Cragganmore - board data probing
+ *
+ * Copyright 2011 Wolfson Microelectronics plc
+ *     Mark Brown <broonie@opensource.wolfsonmicro.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/i2c.h>
+
+#include <linux/mfd/wm831x/irq.h>
+#include <linux/mfd/wm831x/gpio.h>
+
+#include <sound/wm8996.h>
+#include <sound/wm8962.h>
+#include <sound/wm9081.h>
+
+#include <mach/crag6410.h>
+
+static struct wm8996_retune_mobile_config wm8996_retune[] = {
+       {
+               .name = "Sub LPF",
+               .rate = 48000,
+               .regs = {
+                       0x6318, 0x6300, 0x1000, 0x0000, 0x0004, 0x2000, 0xF000,
+                       0x0000, 0x0004, 0x2000, 0xF000, 0x0000, 0x0004, 0x2000,
+                       0xF000, 0x0000, 0x0004, 0x1000, 0x0800, 0x4000
+               },
+       },
+       {
+               .name = "Sub HPF",
+               .rate = 48000,
+               .regs = {
+                       0x000A, 0x6300, 0x1000, 0x0000, 0x0004, 0x2000, 0xF000,
+                       0x0000, 0x0004, 0x2000, 0xF000, 0x0000, 0x0004, 0x2000,
+                       0xF000, 0x0000, 0x0004, 0x1000, 0x0800, 0x4000
+               },
+       },
+};
+
+static struct wm8996_pdata wm8996_pdata __initdata = {
+       .ldo_ena = S3C64XX_GPN(7),
+       .gpio_base = CODEC_GPIO_BASE,
+       .micdet_def = 1,
+       .inl_mode = WM8996_DIFFERRENTIAL_1,
+       .inr_mode = WM8996_DIFFERRENTIAL_1,
+
+       .irq_flags = IRQF_TRIGGER_RISING,
+
+       .gpio_default = {
+               0x8001, /* GPIO1 == ADCLRCLK1 */
+               0x8001, /* GPIO2 == ADCLRCLK2, input due to CPU */
+               0x0141, /* GPIO3 == HP_SEL */
+               0x0002, /* GPIO4 == IRQ */
+               0x020e, /* GPIO5 == CLKOUT */
+       },
+
+       .retune_mobile_cfgs = wm8996_retune,
+       .num_retune_mobile_cfgs = ARRAY_SIZE(wm8996_retune),
+};
+
+static struct wm8962_pdata wm8962_pdata __initdata = {
+       .gpio_init = {
+               0,
+               WM8962_GPIO_FN_OPCLK,
+               WM8962_GPIO_FN_DMICCLK,
+               0,
+               0x8000 | WM8962_GPIO_FN_DMICDAT,
+               WM8962_GPIO_FN_IRQ,    /* Open drain mode */
+       },
+       .irq_active_low = true,
+};
+
+static struct wm9081_pdata wm9081_pdata __initdata = {
+       .irq_high = false,
+       .irq_cmos = false,
+};
+
+static const struct i2c_board_info wm1254_devs[] = {
+       { I2C_BOARD_INFO("wm8996", 0x1a),
+         .platform_data = &wm8996_pdata,
+         .irq = GLENFARCLAS_PMIC_IRQ_BASE + WM831X_IRQ_GPIO_2,
+       },
+       { I2C_BOARD_INFO("wm9081", 0x6c),
+         .platform_data = &wm9081_pdata, },
+};
+
+static const struct i2c_board_info wm1255_devs[] = {
+       { I2C_BOARD_INFO("wm5100", 0x1a),
+         .irq = GLENFARCLAS_PMIC_IRQ_BASE + WM831X_IRQ_GPIO_2,
+       },
+       { I2C_BOARD_INFO("wm9081", 0x6c),
+         .platform_data = &wm9081_pdata, },
+};
+
+static const struct i2c_board_info wm1259_devs[] = {
+       { I2C_BOARD_INFO("wm8962", 0x1a),
+         .platform_data = &wm8962_pdata,
+         .irq = GLENFARCLAS_PMIC_IRQ_BASE + WM831X_IRQ_GPIO_2,
+       },
+};
+
+
+static __devinitdata const struct {
+       u8 id;
+       const char *name;
+       const struct i2c_board_info *i2c_devs;
+       int num_i2c_devs;
+} gf_mods[] = {
+       { .id = 0x01, .name = "1250-EV1 Springbank" },
+       { .id = 0x02, .name = "1251-EV1 Jura" },
+       { .id = 0x03, .name = "1252-EV1 Glenlivet" },
+       { .id = 0x11, .name = "6249-EV2 Glenfarclas", },
+       { .id = 0x21, .name = "1275-EV1 Mortlach" },
+       { .id = 0x25, .name = "1274-EV1 Glencadam" },
+       { .id = 0x31, .name = "1253-EV1 Tomatin", },
+       { .id = 0x39, .name = "1254-EV1 Dallas Dhu",
+         .i2c_devs = wm1254_devs, .num_i2c_devs = ARRAY_SIZE(wm1254_devs) },
+       { .id = 0x3a, .name = "1259-EV1 Tobermory",
+         .i2c_devs = wm1259_devs, .num_i2c_devs = ARRAY_SIZE(wm1259_devs) },
+       { .id = 0x3b, .name = "1255-EV1 Kilchoman",
+         .i2c_devs = wm1255_devs, .num_i2c_devs = ARRAY_SIZE(wm1255_devs) },
+       { .id = 0x3c, .name = "1273-EV1 Longmorn" },
+};
+
+static __devinit int wlf_gf_module_probe(struct i2c_client *i2c,
+                                        const struct i2c_device_id *i2c_id)
+{
+       int ret, i, j, id, rev;
+
+       ret = i2c_smbus_read_byte_data(i2c, 0);
+       if (ret < 0) {
+               dev_err(&i2c->dev, "Failed to read ID: %d\n", ret);
+               return ret;
+       }
+
+       id = (ret & 0xfe) >> 2;
+       rev = ret & 0x3;
+       for (i = 0; i < ARRAY_SIZE(gf_mods); i++)
+               if (id == gf_mods[i].id)
+                       break;
+
+       if (i < ARRAY_SIZE(gf_mods)) {
+               dev_info(&i2c->dev, "%s revision %d\n",
+                        gf_mods[i].name, rev + 1);
+               for (j = 0; j < gf_mods[i].num_i2c_devs; j++) {
+                       if (!i2c_new_device(i2c->adapter,
+                                           &(gf_mods[i].i2c_devs[j])))
+                               dev_err(&i2c->dev,
+                                       "Failed to register dev: %d\n", ret);
+               }
+       } else {
+               dev_warn(&i2c->dev, "Unknown module ID %d revision %d\n",
+                        id, rev);
+       }
+
+       return 0;
+}
+
+static const struct i2c_device_id wlf_gf_module_id[] = {
+       { "wlf-gf-module", 0 },
+       { }
+};
+
+static struct i2c_driver wlf_gf_module_driver = {
+       .driver = {
+               .name = "wlf-gf-module",
+               .owner = THIS_MODULE,
+       },
+       .probe = wlf_gf_module_probe,
+       .id_table = wlf_gf_module_id,
+};
+
+static int __init wlf_gf_module_register(void)
+{
+       return i2c_add_driver(&wlf_gf_module_driver);
+}
+module_init(wlf_gf_module_register);
index f32ec68002efa9aab6070101e07d5724b36ee9d2..30afaa537fcfa2e6908ba9f7bf543e89f27c027b 100644 (file)
@@ -47,6 +47,7 @@
 #include <mach/regs-sys.h>
 #include <mach/regs-gpio.h>
 #include <mach/regs-modem.h>
+#include <mach/crag6410.h>
 
 #include <mach/regs-gpio-memport.h>
 
 #include <plat/iic.h>
 #include <plat/pm.h>
 
-#include <sound/wm8996.h>
-#include <sound/wm8962.h>
-#include <sound/wm9081.h>
-
-#define BANFF_PMIC_IRQ_BASE            IRQ_BOARD_START
-#define GLENFARCLAS_PMIC_IRQ_BASE      (IRQ_BOARD_START + 64)
-
-#define PCA935X_GPIO_BASE              GPIO_BOARD_START
-#define CODEC_GPIO_BASE                (GPIO_BOARD_START + 8)
-#define GLENFARCLAS_PMIC_GPIO_BASE     (GPIO_BOARD_START + 16)
-
 /* serial port setup */
 
 #define UCON (S3C2410_UCON_DEFAULT | S3C2410_UCON_UCLK)
@@ -287,6 +277,11 @@ static struct platform_device speyside_device = {
        .id             = -1,
 };
 
+static struct platform_device lowland_device = {
+       .name           = "lowland",
+       .id             = -1,
+};
+
 static struct platform_device speyside_wm8962_device = {
        .name           = "speyside-wm8962",
        .id             = -1,
@@ -295,6 +290,8 @@ static struct platform_device speyside_wm8962_device = {
 static struct regulator_consumer_supply wallvdd_consumers[] = {
        REGULATOR_SUPPLY("SPKVDD1", "1-001a"),
        REGULATOR_SUPPLY("SPKVDD2", "1-001a"),
+       REGULATOR_SUPPLY("SPKVDDL", "1-001a"),
+       REGULATOR_SUPPLY("SPKVDDR", "1-001a"),
 };
 
 static struct regulator_init_data wallvdd_data = {
@@ -342,6 +339,7 @@ static struct platform_device *crag6410_devices[] __initdata = {
        &crag6410_backlight_device,
        &speyside_device,
        &speyside_wm8962_device,
+       &lowland_device,
        &wallvdd_device,
 };
 
@@ -350,6 +348,12 @@ static struct pca953x_platform_data crag6410_pca_data = {
        .irq_base       = 0,
 };
 
+/* VDDARM is controlled by DVS1 connected to GPK(0) */
+static struct wm831x_buckv_pdata vddarm_pdata = {
+       .dvs_control_src = 1,
+       .dvs_gpio = S3C64XX_GPK(0),
+};
+
 static struct regulator_consumer_supply vddarm_consumers[] __initdata = {
        REGULATOR_SUPPLY("vddarm", NULL),
 };
@@ -365,6 +369,7 @@ static struct regulator_init_data vddarm __initdata = {
        .num_consumer_supplies = ARRAY_SIZE(vddarm_consumers),
        .consumer_supplies = vddarm_consumers,
        .supply_regulator = "WALLVDD",
+       .driver_data = &vddarm_pdata,
 };
 
 static struct regulator_init_data vddint __initdata = {
@@ -500,6 +505,8 @@ static struct wm831x_pdata crag_pmic_pdata __initdata = {
        .backup = &banff_backup_pdata,
 
        .gpio_defaults = {
+               /* GPIO5: DVS1_REQ - CMOS, DBVDD, active high */
+               [4] = WM831X_GPN_DIR | WM831X_GPN_POL | WM831X_GPN_ENA | 0x8,
                /* GPIO11: Touchscreen data - CMOS, DBVDD, active high*/
                [10] = WM831X_GPN_POL | WM831X_GPN_ENA | 0x6,
                /* GPIO12: Touchscreen pen down - CMOS, DBVDD, active high*/
@@ -557,8 +564,12 @@ static struct regulator_init_data pvdd_1v2 __initdata = {
 };
 
 static struct regulator_consumer_supply pvdd_1v8_consumers[] __initdata = {
+       REGULATOR_SUPPLY("LDOVDD", "1-001a"),
        REGULATOR_SUPPLY("PLLVDD", "1-001a"),
        REGULATOR_SUPPLY("DBVDD", "1-001a"),
+       REGULATOR_SUPPLY("DBVDD1", "1-001a"),
+       REGULATOR_SUPPLY("DBVDD2", "1-001a"),
+       REGULATOR_SUPPLY("DBVDD3", "1-001a"),
        REGULATOR_SUPPLY("CPVDD", "1-001a"),
        REGULATOR_SUPPLY("AVDD2", "1-001a"),
        REGULATOR_SUPPLY("DCVDD", "1-001a"),
@@ -611,81 +622,16 @@ static struct wm831x_pdata glenfarclas_pmic_pdata __initdata = {
        .disable_touch = true,
 };
 
-static struct wm8996_retune_mobile_config wm8996_retune[] = {
-       {
-               .name = "Sub LPF",
-               .rate = 48000,
-               .regs = {
-                       0x6318, 0x6300, 0x1000, 0x0000, 0x0004, 0x2000, 0xF000,
-                       0x0000, 0x0004, 0x2000, 0xF000, 0x0000, 0x0004, 0x2000,
-                       0xF000, 0x0000, 0x0004, 0x1000, 0x0800, 0x4000
-               },
-       },
-       {
-               .name = "Sub HPF",
-               .rate = 48000,
-               .regs = {
-                       0x000A, 0x6300, 0x1000, 0x0000, 0x0004, 0x2000, 0xF000,
-                       0x0000, 0x0004, 0x2000, 0xF000, 0x0000, 0x0004, 0x2000,
-                       0xF000, 0x0000, 0x0004, 0x1000, 0x0800, 0x4000
-               },
-       },
-};
-
-static struct wm8996_pdata wm8996_pdata __initdata = {
-       .ldo_ena = S3C64XX_GPN(7),
-       .gpio_base = CODEC_GPIO_BASE,
-       .micdet_def = 1,
-       .inl_mode = WM8996_DIFFERRENTIAL_1,
-       .inr_mode = WM8996_DIFFERRENTIAL_1,
-
-       .irq_flags = IRQF_TRIGGER_RISING,
-
-       .gpio_default = {
-               0x8001, /* GPIO1 == ADCLRCLK1 */
-               0x8001, /* GPIO2 == ADCLRCLK2, input due to CPU */
-               0x0141, /* GPIO3 == HP_SEL */
-               0x0002, /* GPIO4 == IRQ */
-               0x020e, /* GPIO5 == CLKOUT */
-       },
-
-       .retune_mobile_cfgs = wm8996_retune,
-       .num_retune_mobile_cfgs = ARRAY_SIZE(wm8996_retune),
-};
-
-static struct wm8962_pdata wm8962_pdata __initdata = {
-       .gpio_init = {
-               0,
-               WM8962_GPIO_FN_OPCLK,
-               WM8962_GPIO_FN_DMICCLK,
-               0,
-               0x8000 | WM8962_GPIO_FN_DMICDAT,
-               WM8962_GPIO_FN_IRQ,    /* Open drain mode */
-       },
-       .irq_active_low = true,
-};
-
-static struct wm9081_pdata wm9081_pdata __initdata = {
-       .irq_high = false,
-       .irq_cmos = false,
-};
-
 static struct i2c_board_info i2c_devs1[] __initdata = {
        { I2C_BOARD_INFO("wm8311", 0x34),
          .irq = S3C_EINT(0),
          .platform_data = &glenfarclas_pmic_pdata },
 
+       { I2C_BOARD_INFO("wlf-gf-module", 0x24) },
+       { I2C_BOARD_INFO("wlf-gf-module", 0x25) },
+       { I2C_BOARD_INFO("wlf-gf-module", 0x26) },
+
        { I2C_BOARD_INFO("wm1250-ev1", 0x27) },
-       { I2C_BOARD_INFO("wm8996", 0x1a),
-         .platform_data = &wm8996_pdata,
-         .irq = GLENFARCLAS_PMIC_IRQ_BASE + WM831X_IRQ_GPIO_2,
-       },
-       { I2C_BOARD_INFO("wm9081", 0x6c),
-         .platform_data = &wm9081_pdata, },
-       { I2C_BOARD_INFO("wm8962", 0x1a),
-         .platform_data = &wm8962_pdata,
-         .irq = GLENFARCLAS_PMIC_IRQ_BASE + WM831X_IRQ_GPIO_2,
-       },
 };
 
 static void __init crag6410_map_io(void)
index 055e2858b0dd9a31c027ecd8d7032d6ecefbddc7..b375cd5c47cb2ebe9f7b28ce2f7d0b6c0624ddc8 100644 (file)
@@ -29,6 +29,7 @@
 #include <mach/regs-clock.h>
 #include <mach/regs-syscon-power.h>
 #include <mach/regs-gpio-memport.h>
+#include <mach/regs-modem.h>
 
 #ifdef CONFIG_S3C_PM_DEBUG_LED_SMDK
 void s3c_pm_debug_smdkled(u32 set, u32 clear)
@@ -85,6 +86,9 @@ static struct sleep_save misc_save[] = {
        SAVE_ITEM(S3C64XX_MEM0CONSLP0),
        SAVE_ITEM(S3C64XX_MEM0CONSLP1),
        SAVE_ITEM(S3C64XX_MEM1CONSLP),
+
+       SAVE_ITEM(S3C64XX_SDMA_SEL),
+       SAVE_ITEM(S3C64XX_MODEM_MIFPCON),
 };
 
 void s3c_pm_configure_extint(void)
index 65c7518dad7fe3de3534543407972740baecb8e2..e361c41314e97d7b0a06a70c716ddac77671044d 100644 (file)
@@ -9,18 +9,24 @@ if ARCH_S5P64X0
 
 config CPU_S5P6440
        bool
-       select S3C_PL330_DMA
+       select SAMSUNG_DMADEV
        select S5P_HRT
        help
          Enable S5P6440 CPU support
 
 config CPU_S5P6450
        bool
-       select S3C_PL330_DMA
+       select SAMSUNG_DMADEV
        select S5P_HRT
        help
          Enable S5P6450 CPU support
 
+config S5P64X0_SETUP_FB_24BPP
+       bool
+       help
+         Common setup code for S5P64X0 based boards with a LCD display
+         through RGB interface.
+
 config S5P64X0_SETUP_I2C1
        bool
        help
@@ -31,6 +37,7 @@ config S5P64X0_SETUP_I2C1
 config MACH_SMDK6440
        bool "SMDK6440"
        select CPU_S5P6440
+       select S3C_DEV_FB
        select S3C_DEV_I2C1
        select S3C_DEV_RTC
        select S3C_DEV_WDT
@@ -39,6 +46,7 @@ config MACH_SMDK6440
        select SAMSUNG_DEV_BACKLIGHT
        select SAMSUNG_DEV_PWM
        select SAMSUNG_DEV_TS
+       select S5P64X0_SETUP_FB_24BPP
        select S5P64X0_SETUP_I2C1
        help
          Machine support for the Samsung SMDK6440
@@ -46,6 +54,7 @@ config MACH_SMDK6440
 config MACH_SMDK6450
        bool "SMDK6450"
        select CPU_S5P6450
+       select S3C_DEV_FB
        select S3C_DEV_I2C1
        select S3C_DEV_RTC
        select S3C_DEV_WDT
@@ -54,6 +63,7 @@ config MACH_SMDK6450
        select SAMSUNG_DEV_BACKLIGHT
        select SAMSUNG_DEV_PWM
        select SAMSUNG_DEV_TS
+       select S5P64X0_SETUP_FB_24BPP
        select S5P64X0_SETUP_I2C1
        help
          Machine support for the Samsung SMDK6450
index 5f6afdf067eda5f4ae6379b661f676c10ae26b75..eb7468012a37452230762d840b9b66c5adf8136d 100644 (file)
@@ -12,7 +12,7 @@ obj-                          :=
 
 # Core support for S5P64X0 system
 
-obj-$(CONFIG_ARCH_S5P64X0)     += cpu.o init.o clock.o dma.o gpiolib.o
+obj-$(CONFIG_ARCH_S5P64X0)     += cpu.o init.o clock.o dma.o
 obj-$(CONFIG_ARCH_S5P64X0)     += setup-i2c0.o irq-eint.o
 obj-$(CONFIG_CPU_S5P6440)      += clock-s5p6440.o
 obj-$(CONFIG_CPU_S5P6450)      += clock-s5p6450.o
@@ -28,3 +28,4 @@ obj-y                         += dev-audio.o
 obj-$(CONFIG_S3C64XX_DEV_SPI)  += dev-spi.o
 
 obj-$(CONFIG_S5P64X0_SETUP_I2C1)       += setup-i2c1.o
+obj-$(CONFIG_S5P64X0_SETUP_FB_24BPP)   += setup-fb-24bpp.o
index 0e9cd3092dd241b852c5dcfeb2b17411e33edb92..c54c65d511f04cb67b9a5bfa930257188a2a1a7d 100644 (file)
@@ -146,7 +146,8 @@ static struct clk init_clocks_off[] = {
                .enable         = s5p64x0_hclk0_ctrl,
                .ctrlbit        = (1 << 8),
        }, {
-               .name           = "pdma",
+               .name           = "dma",
+               .devname        = "dma-pl330",
                .parent         = &clk_hclk_low.clk,
                .enable         = s5p64x0_hclk0_ctrl,
                .ctrlbit        = (1 << 12),
@@ -499,6 +500,11 @@ static struct clksrc_clk *sysclks[] = {
        &clk_pclk_low,
 };
 
+static struct clk dummy_apb_pclk = {
+       .name           = "apb_pclk",
+       .id             = -1,
+};
+
 void __init_or_cpufreq s5p6440_setup_clocks(void)
 {
        struct clk *xtal_clk;
@@ -581,5 +587,7 @@ void __init s5p6440_register_clocks(void)
        s3c_register_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
        s3c_disable_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
 
+       s3c24xx_register_clock(&dummy_apb_pclk);
+
        s3c_pwmclk_init();
 }
index d9dc16cde109c22de40bca3c417c528e40c4605e..2d04abfba12ecfcaed6cfd5988984f0128681935 100644 (file)
@@ -179,7 +179,8 @@ static struct clk init_clocks_off[] = {
                .enable         = s5p64x0_hclk0_ctrl,
                .ctrlbit        = (1 << 3),
        }, {
-               .name           = "pdma",
+               .name           = "dma",
+               .devname        = "dma-pl330",
                .parent         = &clk_hclk_low.clk,
                .enable         = s5p64x0_hclk0_ctrl,
                .ctrlbit        = (1 << 12),
@@ -553,6 +554,11 @@ static struct clksrc_clk *sysclks[] = {
        &clk_sclk_audio0,
 };
 
+static struct clk dummy_apb_pclk = {
+       .name           = "apb_pclk",
+       .id             = -1,
+};
+
 void __init_or_cpufreq s5p6450_setup_clocks(void)
 {
        struct clk *xtal_clk;
@@ -632,5 +638,7 @@ void __init s5p6450_register_clocks(void)
        s3c_register_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
        s3c_disable_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
 
+       s3c24xx_register_clock(&dummy_apb_pclk);
+
        s3c_pwmclk_init();
 }
index a5c00952ea35c71047c1362e29735179bd4ac261..617da3b3bfb716a8d7f8082acaccad28b517296d 100644 (file)
@@ -38,6 +38,7 @@
 #include <plat/s5p6440.h>
 #include <plat/s5p6450.h>
 #include <plat/adc-core.h>
+#include <plat/fb-core.h>
 
 /* Initial IO mappings */
 
@@ -108,6 +109,7 @@ void __init s5p6440_map_io(void)
 {
        /* initialize any device information early */
        s3c_adc_setname("s3c64xx-adc");
+       s3c_fb_setname("s5p64x0-fb");
 
        iotable_init(s5p64x0_iodesc, ARRAY_SIZE(s5p64x0_iodesc));
        iotable_init(s5p6440_iodesc, ARRAY_SIZE(s5p6440_iodesc));
@@ -117,6 +119,7 @@ void __init s5p6450_map_io(void)
 {
        /* initialize any device information early */
        s3c_adc_setname("s3c64xx-adc");
+       s3c_fb_setname("s5p64x0-fb");
 
        iotable_init(s5p64x0_iodesc, ARRAY_SIZE(s5p64x0_iodesc));
        iotable_init(s5p6450_iodesc, ARRAY_SIZE(s5p6450_iodesc));
index 0e5b3e63e5b3f388382dc54cb68b31e05677b8f4..442dd4ad12da61a02694e97923ca53386a7854ad 100644 (file)
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
-#include <linux/platform_device.h>
 #include <linux/dma-mapping.h>
+#include <linux/amba/bus.h>
+#include <linux/amba/pl330.h>
+
+#include <asm/irq.h>
 
 #include <mach/map.h>
 #include <mach/irqs.h>
 #include <mach/regs-clock.h>
+#include <mach/dma.h>
 
 #include <plat/cpu.h>
 #include <plat/devs.h>
-#include <plat/s3c-pl330-pdata.h>
+#include <plat/irqs.h>
 
 static u64 dma_dmamask = DMA_BIT_MASK(32);
 
-static struct resource s5p64x0_pdma_resource[] = {
-       [0] = {
-               .start  = S5P64X0_PA_PDMA,
-               .end    = S5P64X0_PA_PDMA + SZ_4K,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = IRQ_DMA0,
-               .end    = IRQ_DMA0,
-               .flags  = IORESOURCE_IRQ,
+struct dma_pl330_peri s5p6440_pdma_peri[22] = {
+       {
+               .peri_id = (u8)DMACH_UART0_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_UART0_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_UART1_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_UART1_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_UART2_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_UART2_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_UART3_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_UART3_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = DMACH_MAX,
+       }, {
+               .peri_id = DMACH_MAX,
+       }, {
+               .peri_id = (u8)DMACH_PCM0_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_PCM0_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_I2S0_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_I2S0_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_SPI0_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_SPI0_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_MAX,
+       }, {
+               .peri_id = (u8)DMACH_MAX,
+       }, {
+               .peri_id = (u8)DMACH_MAX,
+       }, {
+               .peri_id = (u8)DMACH_MAX,
+       }, {
+               .peri_id = (u8)DMACH_SPI1_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_SPI1_RX,
+               .rqtype = DEVTOMEM,
        },
 };
 
-static struct s3c_pl330_platdata s5p6440_pdma_pdata = {
-       .peri = {
-               [0] = DMACH_UART0_RX,
-               [1] = DMACH_UART0_TX,
-               [2] = DMACH_UART1_RX,
-               [3] = DMACH_UART1_TX,
-               [4] = DMACH_UART2_RX,
-               [5] = DMACH_UART2_TX,
-               [6] = DMACH_UART3_RX,
-               [7] = DMACH_UART3_TX,
-               [8] = DMACH_MAX,
-               [9] = DMACH_MAX,
-               [10] = DMACH_PCM0_TX,
-               [11] = DMACH_PCM0_RX,
-               [12] = DMACH_I2S0_TX,
-               [13] = DMACH_I2S0_RX,
-               [14] = DMACH_SPI0_TX,
-               [15] = DMACH_SPI0_RX,
-               [16] = DMACH_MAX,
-               [17] = DMACH_MAX,
-               [18] = DMACH_MAX,
-               [19] = DMACH_MAX,
-               [20] = DMACH_SPI1_TX,
-               [21] = DMACH_SPI1_RX,
-               [22] = DMACH_MAX,
-               [23] = DMACH_MAX,
-               [24] = DMACH_MAX,
-               [25] = DMACH_MAX,
-               [26] = DMACH_MAX,
-               [27] = DMACH_MAX,
-               [28] = DMACH_MAX,
-               [29] = DMACH_PWM,
-               [30] = DMACH_MAX,
-               [31] = DMACH_MAX,
-       },
+struct dma_pl330_platdata s5p6440_pdma_pdata = {
+       .nr_valid_peri = ARRAY_SIZE(s5p6440_pdma_peri),
+       .peri = s5p6440_pdma_peri,
 };
 
-static struct s3c_pl330_platdata s5p6450_pdma_pdata = {
-       .peri = {
-               [0] = DMACH_UART0_RX,
-               [1] = DMACH_UART0_TX,
-               [2] = DMACH_UART1_RX,
-               [3] = DMACH_UART1_TX,
-               [4] = DMACH_UART2_RX,
-               [5] = DMACH_UART2_TX,
-               [6] = DMACH_UART3_RX,
-               [7] = DMACH_UART3_TX,
-               [8] = DMACH_UART4_RX,
-               [9] = DMACH_UART4_TX,
-               [10] = DMACH_PCM0_TX,
-               [11] = DMACH_PCM0_RX,
-               [12] = DMACH_I2S0_TX,
-               [13] = DMACH_I2S0_RX,
-               [14] = DMACH_SPI0_TX,
-               [15] = DMACH_SPI0_RX,
-               [16] = DMACH_PCM1_TX,
-               [17] = DMACH_PCM1_RX,
-               [18] = DMACH_PCM2_TX,
-               [19] = DMACH_PCM2_RX,
-               [20] = DMACH_SPI1_TX,
-               [21] = DMACH_SPI1_RX,
-               [22] = DMACH_USI_TX,
-               [23] = DMACH_USI_RX,
-               [24] = DMACH_MAX,
-               [25] = DMACH_I2S1_TX,
-               [26] = DMACH_I2S1_RX,
-               [27] = DMACH_I2S2_TX,
-               [28] = DMACH_I2S2_RX,
-               [29] = DMACH_PWM,
-               [30] = DMACH_UART5_RX,
-               [31] = DMACH_UART5_TX,
+struct dma_pl330_peri s5p6450_pdma_peri[32] = {
+       {
+               .peri_id = (u8)DMACH_UART0_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_UART0_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_UART1_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_UART1_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_UART2_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_UART2_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_UART3_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_UART3_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_UART4_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_UART4_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_PCM0_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_PCM0_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_I2S0_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_I2S0_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_SPI0_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_SPI0_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_PCM1_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_PCM1_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_PCM2_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_PCM2_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_SPI1_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_SPI1_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_USI_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_USI_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_MAX,
+       }, {
+               .peri_id = (u8)DMACH_I2S1_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_I2S1_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_I2S2_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_I2S2_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_PWM,
+       }, {
+               .peri_id = (u8)DMACH_UART5_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_UART5_TX,
+               .rqtype = MEMTODEV,
        },
 };
 
-static struct platform_device s5p64x0_device_pdma = {
-       .name           = "s3c-pl330",
-       .id             = -1,
-       .num_resources  = ARRAY_SIZE(s5p64x0_pdma_resource),
-       .resource       = s5p64x0_pdma_resource,
-       .dev            = {
+struct dma_pl330_platdata s5p6450_pdma_pdata = {
+       .nr_valid_peri = ARRAY_SIZE(s5p6450_pdma_peri),
+       .peri = s5p6450_pdma_peri,
+};
+
+struct amba_device s5p64x0_device_pdma = {
+       .dev = {
+               .init_name = "dma-pl330",
                .dma_mask = &dma_dmamask,
                .coherent_dma_mask = DMA_BIT_MASK(32),
        },
+       .res = {
+               .start = S5P64X0_PA_PDMA,
+               .end = S5P64X0_PA_PDMA + SZ_4K,
+               .flags = IORESOURCE_MEM,
+       },
+       .irq = {IRQ_DMA0, NO_IRQ},
+       .periphid = 0x00041330,
 };
 
 static int __init s5p64x0_dma_init(void)
@@ -139,7 +232,7 @@ static int __init s5p64x0_dma_init(void)
        else
                s5p64x0_device_pdma.dev.platform_data = &s5p6440_pdma_pdata;
 
-       platform_device_register(&s5p64x0_device_pdma);
+       amba_device_register(&s5p64x0_device_pdma, &iomem_resource);
 
        return 0;
 }
index 81209eb1409b7ad4c55a70897379547991ea2958..5a622af461d7b09397f7c5513e24cdc2706e2b96 100644 (file)
@@ -20,7 +20,7 @@
 #ifndef __MACH_DMA_H
 #define __MACH_DMA_H
 
-/* This platform uses the common S3C DMA API driver for PL330 */
-#include <plat/s3c-dma-pl330.h>
+/* This platform uses the common common DMA API driver for PL330 */
+#include <plat/dma-pl330.h>
 
 #endif /* __MACH_DMA_H */
index 5837a36ece8d6d9a7baec682a242923442666fe5..53982db9d25989d27c09d822b0c595a061c41874 100644 (file)
 
 #define IRQ_I2S0               IRQ_I2SV40
 
+#define IRQ_LCD_FIFO           IRQ_DISPCON0
+#define IRQ_LCD_VSYNC          IRQ_DISPCON1
+#define IRQ_LCD_SYSTEM         IRQ_DISPCON2
+
 /* S5P6450 EINT feature will be added */
 
 /*
index 95c91257c7caf22b0d05ed5ad1c2828443e6da99..c5ef50c26291d30cbfabbe21f07001659d57b119 100644 (file)
@@ -47,6 +47,8 @@
 
 #define S5P64X0_PA_HSMMC(x)    (0xED800000 + ((x) * 0x100000))
 
+#define S5P64X0_PA_FB          0xEE000000
+
 #define S5P64X0_PA_I2S         0xF2000000
 #define S5P6450_PA_I2S1                0xF2800000
 #define S5P6450_PA_I2S2                0xF2900000
@@ -64,6 +66,7 @@
 #define S3C_PA_IIC1            S5P6440_PA_IIC1
 #define S3C_PA_RTC             S5P64X0_PA_RTC
 #define S3C_PA_WDT             S5P64X0_PA_WDT
+#define S3C_PA_FB              S5P64X0_PA_FB
 
 #define S5P_PA_CHIPID          S5P64X0_PA_CHIPID
 #define S5P_PA_SROMC           S5P64X0_PA_SROMC
index 6ce254729f3baaa51b13ea8c09b1046ba21f4938..88269ec70a3817e68b5833ce77bbaa10c5964ce1 100644 (file)
 #define S5P6450_GPQ_BASE               (S5P_VA_GPIO + 0x0180)
 #define S5P6450_GPS_BASE               (S5P_VA_GPIO + 0x0300)
 
+#define S5P64X0_SPCON0                 (S5P_VA_GPIO + 0x1A0)
+#define S5P64X0_SPCON0_LCD_SEL_MASK    (0x3 << 0)
+#define S5P64X0_SPCON0_LCD_SEL_RGB     (0x1 << 0)
+
 /* External interrupt control registers for group0 */
 
 #define EINT0CON0_OFFSET               (0x900)
index 340f30f4a3da1ab54120c235792be436e089112c..b0465d4e84e7aac8e358db7541eb55e04ffa6956 100644 (file)
@@ -23,6 +23,9 @@
 #include <linux/clk.h>
 #include <linux/gpio.h>
 #include <linux/pwm_backlight.h>
+#include <linux/fb.h>
+
+#include <video/platform_lcd.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
@@ -47,6 +50,8 @@
 #include <plat/ts.h>
 #include <plat/s5p-time.h>
 #include <plat/backlight.h>
+#include <plat/fb.h>
+#include <plat/regs-fb.h>
 
 #define SMDK6440_UCON_DEFAULT  (S3C2410_UCON_TXILEVEL |        \
                                S3C2410_UCON_RXILEVEL |         \
@@ -92,6 +97,59 @@ static struct s3c2410_uartcfg smdk6440_uartcfgs[] __initdata = {
        },
 };
 
+/* Frame Buffer */
+static struct s3c_fb_pd_win smdk6440_fb_win0 = {
+       .win_mode = {
+               .left_margin    = 8,
+               .right_margin   = 13,
+               .upper_margin   = 7,
+               .lower_margin   = 5,
+               .hsync_len      = 3,
+               .vsync_len      = 1,
+               .xres           = 800,
+               .yres           = 480,
+       },
+       .max_bpp        = 32,
+       .default_bpp    = 24,
+};
+
+static struct s3c_fb_platdata smdk6440_lcd_pdata __initdata = {
+       .win[0]         = &smdk6440_fb_win0,
+       .vidcon0        = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB,
+       .vidcon1        = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC,
+       .setup_gpio     = s5p64x0_fb_gpio_setup_24bpp,
+};
+
+/* LCD power controller */
+static void smdk6440_lte480_reset_power(struct plat_lcd_data *pd,
+                                        unsigned int power)
+{
+       int err;
+
+       if (power) {
+               err = gpio_request(S5P6440_GPN(5), "GPN");
+               if (err) {
+                       printk(KERN_ERR "failed to request GPN for lcd reset\n");
+                       return;
+               }
+
+               gpio_direction_output(S5P6440_GPN(5), 1);
+               gpio_set_value(S5P6440_GPN(5), 0);
+               gpio_set_value(S5P6440_GPN(5), 1);
+               gpio_free(S5P6440_GPN(5));
+       }
+}
+
+static struct plat_lcd_data smdk6440_lcd_power_data = {
+       .set_power      = smdk6440_lte480_reset_power,
+};
+
+static struct platform_device smdk6440_lcd_lte480wv = {
+       .name                   = "platform-lcd",
+       .dev.parent             = &s3c_device_fb.dev,
+       .dev.platform_data      = &smdk6440_lcd_power_data,
+};
+
 static struct platform_device *smdk6440_devices[] __initdata = {
        &s3c_device_adc,
        &s3c_device_rtc,
@@ -101,6 +159,8 @@ static struct platform_device *smdk6440_devices[] __initdata = {
        &s3c_device_wdt,
        &samsung_asoc_dma,
        &s5p6440_device_iis,
+       &s3c_device_fb,
+       &smdk6440_lcd_lte480wv,
 };
 
 static struct s3c2410_platform_i2c s5p6440_i2c0_data __initdata = {
@@ -147,6 +207,17 @@ static void __init smdk6440_map_io(void)
        s5p_set_timer_source(S5P_PWM3, S5P_PWM4);
 }
 
+static void s5p6440_set_lcd_interface(void)
+{
+       unsigned int cfg;
+
+       /* select TFT LCD type (RGB I/F) */
+       cfg = __raw_readl(S5P64X0_SPCON0);
+       cfg &= ~S5P64X0_SPCON0_LCD_SEL_MASK;
+       cfg |= S5P64X0_SPCON0_LCD_SEL_RGB;
+       __raw_writel(cfg, S5P64X0_SPCON0);
+}
+
 static void __init smdk6440_machine_init(void)
 {
        s3c24xx_ts_set_platdata(NULL);
@@ -160,6 +231,9 @@ static void __init smdk6440_machine_init(void)
 
        samsung_bl_set(&smdk6440_bl_gpio_info, &smdk6440_bl_data);
 
+       s5p6440_set_lcd_interface();
+       s3c_fb_set_platdata(&smdk6440_lcd_pdata);
+
        platform_add_devices(smdk6440_devices, ARRAY_SIZE(smdk6440_devices));
 }
 
index ee0da14665b6d8d2c1481211402734b6e0a66e01..2a69caa70afd648cd8b82ee035642394725286c5 100644 (file)
@@ -23,6 +23,9 @@
 #include <linux/clk.h>
 #include <linux/gpio.h>
 #include <linux/pwm_backlight.h>
+#include <linux/fb.h>
+
+#include <video/platform_lcd.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
@@ -47,6 +50,8 @@
 #include <plat/ts.h>
 #include <plat/s5p-time.h>
 #include <plat/backlight.h>
+#include <plat/fb.h>
+#include <plat/regs-fb.h>
 
 #define SMDK6450_UCON_DEFAULT  (S3C2410_UCON_TXILEVEL |        \
                                S3C2410_UCON_RXILEVEL |         \
@@ -110,6 +115,59 @@ static struct s3c2410_uartcfg smdk6450_uartcfgs[] __initdata = {
 #endif
 };
 
+/* Frame Buffer */
+static struct s3c_fb_pd_win smdk6450_fb_win0 = {
+       .win_mode       = {
+               .left_margin    = 8,
+               .right_margin   = 13,
+               .upper_margin   = 7,
+               .lower_margin   = 5,
+               .hsync_len      = 3,
+               .vsync_len      = 1,
+               .xres           = 800,
+               .yres           = 480,
+       },
+       .max_bpp        = 32,
+       .default_bpp    = 24,
+};
+
+static struct s3c_fb_platdata smdk6450_lcd_pdata __initdata = {
+       .win[0]         = &smdk6450_fb_win0,
+       .vidcon0        = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB,
+       .vidcon1        = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC,
+       .setup_gpio     = s5p64x0_fb_gpio_setup_24bpp,
+};
+
+/* LCD power controller */
+static void smdk6450_lte480_reset_power(struct plat_lcd_data *pd,
+                                        unsigned int power)
+{
+       int err;
+
+       if (power) {
+               err = gpio_request(S5P6450_GPN(5), "GPN");
+               if (err) {
+                       printk(KERN_ERR "failed to request GPN for lcd reset\n");
+                       return;
+               }
+
+               gpio_direction_output(S5P6450_GPN(5), 1);
+               gpio_set_value(S5P6450_GPN(5), 0);
+               gpio_set_value(S5P6450_GPN(5), 1);
+               gpio_free(S5P6450_GPN(5));
+       }
+}
+
+static struct plat_lcd_data smdk6450_lcd_power_data = {
+       .set_power      = smdk6450_lte480_reset_power,
+};
+
+static struct platform_device smdk6450_lcd_lte480wv = {
+       .name                   = "platform-lcd",
+       .dev.parent             = &s3c_device_fb.dev,
+       .dev.platform_data      = &smdk6450_lcd_power_data,
+};
+
 static struct platform_device *smdk6450_devices[] __initdata = {
        &s3c_device_adc,
        &s3c_device_rtc,
@@ -119,6 +177,9 @@ static struct platform_device *smdk6450_devices[] __initdata = {
        &s3c_device_wdt,
        &samsung_asoc_dma,
        &s5p6450_device_iis0,
+       &s3c_device_fb,
+       &smdk6450_lcd_lte480wv,
+
        /* s5p6450_device_spi0 will be added */
 };
 
@@ -166,6 +227,17 @@ static void __init smdk6450_map_io(void)
        s5p_set_timer_source(S5P_PWM3, S5P_PWM4);
 }
 
+static void s5p6450_set_lcd_interface(void)
+{
+       unsigned int cfg;
+
+       /* select TFT LCD type (RGB I/F) */
+       cfg = __raw_readl(S5P64X0_SPCON0);
+       cfg &= ~S5P64X0_SPCON0_LCD_SEL_MASK;
+       cfg |= S5P64X0_SPCON0_LCD_SEL_RGB;
+       __raw_writel(cfg, S5P64X0_SPCON0);
+}
+
 static void __init smdk6450_machine_init(void)
 {
        s3c24xx_ts_set_platdata(NULL);
@@ -179,6 +251,9 @@ static void __init smdk6450_machine_init(void)
 
        samsung_bl_set(&smdk6450_bl_gpio_info, &smdk6450_bl_data);
 
+       s5p6450_set_lcd_interface();
+       s3c_fb_set_platdata(&smdk6450_lcd_pdata);
+
        platform_add_devices(smdk6450_devices, ARRAY_SIZE(smdk6450_devices));
 }
 
diff --git a/arch/arm/mach-s5p64x0/setup-fb-24bpp.c b/arch/arm/mach-s5p64x0/setup-fb-24bpp.c
new file mode 100644 (file)
index 0000000..f346ee4
--- /dev/null
@@ -0,0 +1,29 @@
+/* linux/arch/arm/mach-s5p64x0/setup-fb-24bpp.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ *
+ * Base S5P64X0 GPIO setup information for LCD framebuffer
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/fb.h>
+#include <linux/gpio.h>
+
+#include <plat/cpu.h>
+#include <plat/fb.h>
+#include <plat/gpio-cfg.h>
+
+void s5p64x0_fb_gpio_setup_24bpp(void)
+{
+       if (soc_is_s5p6440()) {
+               s3c_gpio_cfgrange_nopull(S5P6440_GPI(0), 16, S3C_GPIO_SFN(2));
+               s3c_gpio_cfgrange_nopull(S5P6440_GPJ(0), 12, S3C_GPIO_SFN(2));
+       } else if (soc_is_s5p6450()) {
+               s3c_gpio_cfgrange_nopull(S5P6450_GPI(0), 16, S3C_GPIO_SFN(2));
+               s3c_gpio_cfgrange_nopull(S5P6450_GPJ(0), 12, S3C_GPIO_SFN(2));
+       }
+}
index e8a33c4b054cca68c90ce759bd2df5e9198bbf70..e538a4c67e9cc72d18924c3c5945e83c53bbbb4a 100644 (file)
@@ -10,7 +10,7 @@ if ARCH_S5PC100
 config CPU_S5PC100
        bool
        select S5P_EXT_INT
-       select S3C_PL330_DMA
+       select SAMSUNG_DMADEV
        help
          Enable S5PC100 CPU support
 
index ff5cbb30de5bb5fc200928018fdfc3f9f7b0f58b..8d47709da713f22001622b90d67595d3ae0dd7c3 100644 (file)
@@ -33,6 +33,11 @@ static struct clk s5p_clk_otgphy = {
        .name           = "otg_phy",
 };
 
+static struct clk dummy_apb_pclk = {
+       .name           = "apb_pclk",
+       .id             = -1,
+};
+
 static struct clk *clk_src_mout_href_list[] = {
        [0] = &s5p_clk_27m,
        [1] = &clk_fin_hpll,
@@ -454,14 +459,14 @@ static struct clk init_clocks_off[] = {
                .enable         = s5pc100_d1_0_ctrl,
                .ctrlbit        = (1 << 2),
        }, {
-               .name           = "pdma",
-               .devname        = "s3c-pl330.1",
+               .name           = "dma",
+               .devname        = "dma-pl330.1",
                .parent         = &clk_div_d1_bus.clk,
                .enable         = s5pc100_d1_0_ctrl,
                .ctrlbit        = (1 << 1),
        }, {
-               .name           = "pdma",
-               .devname        = "s3c-pl330.0",
+               .name           = "dma",
+               .devname        = "dma-pl330.0",
                .parent         = &clk_div_d1_bus.clk,
                .enable         = s5pc100_d1_0_ctrl,
                .ctrlbit        = (1 << 0),
@@ -1276,5 +1281,7 @@ void __init s5pc100_register_clocks(void)
        s3c_register_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
        s3c_disable_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
 
+       s3c24xx_register_clock(&dummy_apb_pclk);
+
        s3c_pwmclk_init();
 }
index bf4cd0fb97c6afe38d01860412775f5fb52590ae..065a087f5a8bf4edbfb197589f482635d340e55d 100644 (file)
@@ -1,4 +1,8 @@
-/*
+/* linux/arch/arm/mach-s5pc100/dma.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com
+ *
  * Copyright (C) 2010 Samsung Electronics Co. Ltd.
  *     Jaswinder Singh <jassi.brar@samsung.com>
  *
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#include <linux/platform_device.h>
 #include <linux/dma-mapping.h>
+#include <linux/amba/bus.h>
+#include <linux/amba/pl330.h>
 
+#include <asm/irq.h>
 #include <plat/devs.h>
+#include <plat/irqs.h>
 
 #include <mach/map.h>
 #include <mach/irqs.h>
-
-#include <plat/s3c-pl330-pdata.h>
+#include <mach/dma.h>
 
 static u64 dma_dmamask = DMA_BIT_MASK(32);
 
-static struct resource s5pc100_pdma0_resource[] = {
-       [0] = {
-               .start  = S5PC100_PA_PDMA0,
-               .end    = S5PC100_PA_PDMA0 + SZ_4K,
-               .flags = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = IRQ_PDMA0,
-               .end    = IRQ_PDMA0,
-               .flags  = IORESOURCE_IRQ,
+struct dma_pl330_peri pdma0_peri[30] = {
+       {
+               .peri_id = (u8)DMACH_UART0_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_UART0_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_UART1_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_UART1_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_UART2_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_UART2_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_UART3_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_UART3_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = DMACH_IRDA,
+       }, {
+               .peri_id = (u8)DMACH_I2S0_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_I2S0_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_I2S0S_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_I2S1_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_I2S1_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_I2S2_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_I2S2_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_SPI0_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_SPI0_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_SPI1_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_SPI1_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_SPI2_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_SPI2_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_AC97_MICIN,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_AC97_PCMIN,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_AC97_PCMOUT,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_EXTERNAL,
+       }, {
+               .peri_id = (u8)DMACH_PWM,
+       }, {
+               .peri_id = (u8)DMACH_SPDIF,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_HSI_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_HSI_TX,
+               .rqtype = MEMTODEV,
        },
 };
 
-static struct s3c_pl330_platdata s5pc100_pdma0_pdata = {
-       .peri = {
-               [0] = DMACH_UART0_RX,
-               [1] = DMACH_UART0_TX,
-               [2] = DMACH_UART1_RX,
-               [3] = DMACH_UART1_TX,
-               [4] = DMACH_UART2_RX,
-               [5] = DMACH_UART2_TX,
-               [6] = DMACH_UART3_RX,
-               [7] = DMACH_UART3_TX,
-               [8] = DMACH_IRDA,
-               [9] = DMACH_I2S0_RX,
-               [10] = DMACH_I2S0_TX,
-               [11] = DMACH_I2S0S_TX,
-               [12] = DMACH_I2S1_RX,
-               [13] = DMACH_I2S1_TX,
-               [14] = DMACH_I2S2_RX,
-               [15] = DMACH_I2S2_TX,
-               [16] = DMACH_SPI0_RX,
-               [17] = DMACH_SPI0_TX,
-               [18] = DMACH_SPI1_RX,
-               [19] = DMACH_SPI1_TX,
-               [20] = DMACH_SPI2_RX,
-               [21] = DMACH_SPI2_TX,
-               [22] = DMACH_AC97_MICIN,
-               [23] = DMACH_AC97_PCMIN,
-               [24] = DMACH_AC97_PCMOUT,
-               [25] = DMACH_EXTERNAL,
-               [26] = DMACH_PWM,
-               [27] = DMACH_SPDIF,
-               [28] = DMACH_HSI_RX,
-               [29] = DMACH_HSI_TX,
-               [30] = DMACH_MAX,
-               [31] = DMACH_MAX,
-       },
+struct dma_pl330_platdata s5pc100_pdma0_pdata = {
+       .nr_valid_peri = ARRAY_SIZE(pdma0_peri),
+       .peri = pdma0_peri,
 };
 
-static struct platform_device s5pc100_device_pdma0 = {
-       .name           = "s3c-pl330",
-       .id             = 0,
-       .num_resources  = ARRAY_SIZE(s5pc100_pdma0_resource),
-       .resource       = s5pc100_pdma0_resource,
-       .dev            = {
+struct amba_device s5pc100_device_pdma0 = {
+       .dev = {
+               .init_name = "dma-pl330.0",
                .dma_mask = &dma_dmamask,
                .coherent_dma_mask = DMA_BIT_MASK(32),
                .platform_data = &s5pc100_pdma0_pdata,
        },
-};
-
-static struct resource s5pc100_pdma1_resource[] = {
-       [0] = {
-               .start  = S5PC100_PA_PDMA1,
-               .end    = S5PC100_PA_PDMA1 + SZ_4K,
+       .res = {
+               .start = S5PC100_PA_PDMA0,
+               .end = S5PC100_PA_PDMA0 + SZ_4K,
                .flags = IORESOURCE_MEM,
        },
-       [1] = {
-               .start  = IRQ_PDMA1,
-               .end    = IRQ_PDMA1,
-               .flags  = IORESOURCE_IRQ,
-       },
+       .irq = {IRQ_PDMA0, NO_IRQ},
+       .periphid = 0x00041330,
 };
 
-static struct s3c_pl330_platdata s5pc100_pdma1_pdata = {
-       .peri = {
-               [0] = DMACH_UART0_RX,
-               [1] = DMACH_UART0_TX,
-               [2] = DMACH_UART1_RX,
-               [3] = DMACH_UART1_TX,
-               [4] = DMACH_UART2_RX,
-               [5] = DMACH_UART2_TX,
-               [6] = DMACH_UART3_RX,
-               [7] = DMACH_UART3_TX,
-               [8] = DMACH_IRDA,
-               [9] = DMACH_I2S0_RX,
-               [10] = DMACH_I2S0_TX,
-               [11] = DMACH_I2S0S_TX,
-               [12] = DMACH_I2S1_RX,
-               [13] = DMACH_I2S1_TX,
-               [14] = DMACH_I2S2_RX,
-               [15] = DMACH_I2S2_TX,
-               [16] = DMACH_SPI0_RX,
-               [17] = DMACH_SPI0_TX,
-               [18] = DMACH_SPI1_RX,
-               [19] = DMACH_SPI1_TX,
-               [20] = DMACH_SPI2_RX,
-               [21] = DMACH_SPI2_TX,
-               [22] = DMACH_PCM0_RX,
-               [23] = DMACH_PCM0_TX,
-               [24] = DMACH_PCM1_RX,
-               [25] = DMACH_PCM1_TX,
-               [26] = DMACH_MSM_REQ0,
-               [27] = DMACH_MSM_REQ1,
-               [28] = DMACH_MSM_REQ2,
-               [29] = DMACH_MSM_REQ3,
-               [30] = DMACH_MAX,
-               [31] = DMACH_MAX,
+struct dma_pl330_peri pdma1_peri[30] = {
+       {
+               .peri_id = (u8)DMACH_UART0_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_UART0_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_UART1_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_UART1_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_UART2_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_UART2_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_UART3_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_UART3_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = DMACH_IRDA,
+       }, {
+               .peri_id = (u8)DMACH_I2S0_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_I2S0_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_I2S0S_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_I2S1_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_I2S1_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_I2S2_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_I2S2_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_SPI0_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_SPI0_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_SPI1_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_SPI1_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_SPI2_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_SPI2_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_PCM0_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_PCM1_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_PCM1_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_PCM1_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_MSM_REQ0,
+       }, {
+               .peri_id = (u8)DMACH_MSM_REQ1,
+       }, {
+               .peri_id = (u8)DMACH_MSM_REQ2,
+       }, {
+               .peri_id = (u8)DMACH_MSM_REQ3,
        },
 };
 
-static struct platform_device s5pc100_device_pdma1 = {
-       .name           = "s3c-pl330",
-       .id             = 1,
-       .num_resources  = ARRAY_SIZE(s5pc100_pdma1_resource),
-       .resource       = s5pc100_pdma1_resource,
-       .dev            = {
+struct dma_pl330_platdata s5pc100_pdma1_pdata = {
+       .nr_valid_peri = ARRAY_SIZE(pdma1_peri),
+       .peri = pdma1_peri,
+};
+
+struct amba_device s5pc100_device_pdma1 = {
+       .dev = {
+               .init_name = "dma-pl330.1",
                .dma_mask = &dma_dmamask,
                .coherent_dma_mask = DMA_BIT_MASK(32),
                .platform_data = &s5pc100_pdma1_pdata,
        },
-};
-
-static struct platform_device *s5pc100_dmacs[] __initdata = {
-       &s5pc100_device_pdma0,
-       &s5pc100_device_pdma1,
+       .res = {
+               .start = S5PC100_PA_PDMA1,
+               .end = S5PC100_PA_PDMA1 + SZ_4K,
+               .flags = IORESOURCE_MEM,
+       },
+       .irq = {IRQ_PDMA1, NO_IRQ},
+       .periphid = 0x00041330,
 };
 
 static int __init s5pc100_dma_init(void)
 {
-       platform_add_devices(s5pc100_dmacs, ARRAY_SIZE(s5pc100_dmacs));
+       amba_device_register(&s5pc100_device_pdma0, &iomem_resource);
+       amba_device_register(&s5pc100_device_pdma1, &iomem_resource);
 
        return 0;
 }
index 81209eb1409b7ad4c55a70897379547991ea2958..201842a3769e5187067d95b70c9d2e14a5ea3acd 100644 (file)
@@ -20,7 +20,7 @@
 #ifndef __MACH_DMA_H
 #define __MACH_DMA_H
 
-/* This platform uses the common S3C DMA API driver for PL330 */
-#include <plat/s3c-dma-pl330.h>
+/* This platform uses the common DMA API driver for PL330 */
+#include <plat/dma-pl330.h>
 
 #endif /* __MACH_DMA_H */
index aaeb44a73716349f5fa3e18a165b229ced31f18f..f22c683272d3d48f19e7a40a00f8452b594646fb 100644 (file)
@@ -11,7 +11,7 @@ if ARCH_S5PV210
 
 config CPU_S5PV210
        bool
-       select S3C_PL330_DMA
+       select SAMSUNG_DMADEV
        select S5P_EXT_INT
        select S5P_HRT
        help
@@ -93,11 +93,13 @@ config MACH_GONI
        select S3C_DEV_USB_HSOTG
        select S5P_DEV_ONENAND
        select SAMSUNG_DEV_KEYPAD
+       select S5P_DEV_TV
        select S5PV210_SETUP_FB_24BPP
        select S5PV210_SETUP_I2C1
        select S5PV210_SETUP_I2C2
        select S5PV210_SETUP_KEYPAD
        select S5PV210_SETUP_SDHCI
+       select S5PV210_SETUP_FIMC
        help
          Machine support for Samsung GONI board
          S5PC110(MCP) is one of package option of S5PV210
index f5f8fa89679c90f825a47f45898e6adb9e92e225..4c5ac7a69e9e1b75fb7640d698f9ba0116122a0a 100644 (file)
@@ -174,6 +174,16 @@ static int s5pv210_clk_mask1_ctrl(struct clk *clk, int enable)
        return s5p_gatectrl(S5P_CLK_SRC_MASK1, clk, enable);
 }
 
+static int exynos4_clk_hdmiphy_ctrl(struct clk *clk, int enable)
+{
+       return s5p_gatectrl(S5P_HDMI_PHY_CONTROL, clk, enable);
+}
+
+static int exynos4_clk_dac_ctrl(struct clk *clk, int enable)
+{
+       return s5p_gatectrl(S5P_DAC_PHY_CONTROL, clk, enable);
+}
+
 static struct clk clk_sclk_hdmi27m = {
        .name           = "sclk_hdmi27m",
        .rate           = 27000000,
@@ -203,6 +213,11 @@ static struct clk clk_pcmcdclk2 = {
        .name           = "pcmcdclk",
 };
 
+static struct clk dummy_apb_pclk = {
+       .name           = "apb_pclk",
+       .id             = -1,
+};
+
 static struct clk *clkset_vpllsrc_list[] = {
        [0] = &clk_fin_vpll,
        [1] = &clk_sclk_hdmi27m,
@@ -289,14 +304,14 @@ static struct clk_ops clk_fout_apll_ops = {
 
 static struct clk init_clocks_off[] = {
        {
-               .name           = "pdma",
-               .devname        = "s3c-pl330.0",
+               .name           = "dma",
+               .devname        = "dma-pl330.0",
                .parent         = &clk_hclk_psys.clk,
                .enable         = s5pv210_clk_ip0_ctrl,
                .ctrlbit        = (1 << 3),
        }, {
-               .name           = "pdma",
-               .devname        = "s3c-pl330.1",
+               .name           = "dma",
+               .devname        = "dma-pl330.1",
                .parent         = &clk_hclk_psys.clk,
                .enable         = s5pv210_clk_ip0_ctrl,
                .ctrlbit        = (1 << 4),
@@ -329,6 +344,40 @@ static struct clk init_clocks_off[] = {
                .parent         = &clk_pclk_psys.clk,
                .enable         = s5pv210_clk_ip0_ctrl,
                .ctrlbit        = (1 << 16),
+       }, {
+               .name           = "dac",
+               .devname        = "s5p-sdo",
+               .parent         = &clk_hclk_dsys.clk,
+               .enable         = s5pv210_clk_ip1_ctrl,
+               .ctrlbit        = (1 << 10),
+       }, {
+               .name           = "mixer",
+               .devname        = "s5p-mixer",
+               .parent         = &clk_hclk_dsys.clk,
+               .enable         = s5pv210_clk_ip1_ctrl,
+               .ctrlbit        = (1 << 9),
+       }, {
+               .name           = "vp",
+               .devname        = "s5p-mixer",
+               .parent         = &clk_hclk_dsys.clk,
+               .enable         = s5pv210_clk_ip1_ctrl,
+               .ctrlbit        = (1 << 8),
+       }, {
+               .name           = "hdmi",
+               .devname        = "s5pv210-hdmi",
+               .parent         = &clk_hclk_dsys.clk,
+               .enable         = s5pv210_clk_ip1_ctrl,
+               .ctrlbit        = (1 << 11),
+       }, {
+               .name           = "hdmiphy",
+               .devname        = "s5pv210-hdmi",
+               .enable         = exynos4_clk_hdmiphy_ctrl,
+               .ctrlbit        = (1 << 0),
+       }, {
+               .name           = "dacphy",
+               .devname        = "s5p-sdo",
+               .enable         = exynos4_clk_dac_ctrl,
+               .ctrlbit        = (1 << 0),
        }, {
                .name           = "otg",
                .parent         = &clk_hclk_psys.clk,
@@ -406,6 +455,12 @@ static struct clk init_clocks_off[] = {
                .parent         = &clk_pclk_psys.clk,
                .enable         = s5pv210_clk_ip3_ctrl,
                .ctrlbit        = (1<<9),
+       }, {
+               .name           = "i2c",
+               .devname        = "s3c2440-hdmiphy-i2c",
+               .parent         = &clk_pclk_psys.clk,
+               .enable         = s5pv210_clk_ip3_ctrl,
+               .ctrlbit        = (1 << 11),
        }, {
                .name           = "spi",
                .devname        = "s3c64xx-spi.0",
@@ -594,6 +649,23 @@ static struct clksrc_sources clkset_sclk_mixer = {
        .nr_sources     = ARRAY_SIZE(clkset_sclk_mixer_list),
 };
 
+static struct clksrc_clk clk_sclk_mixer = {
+       .clk            = {
+               .name           = "sclk_mixer",
+               .enable         = s5pv210_clk_mask0_ctrl,
+               .ctrlbit        = (1 << 1),
+       },
+       .sources = &clkset_sclk_mixer,
+       .reg_src = { .reg = S5P_CLK_SRC1, .shift = 4, .size = 1 },
+};
+
+static struct clksrc_clk *sclk_tv[] = {
+       &clk_sclk_dac,
+       &clk_sclk_pixel,
+       &clk_sclk_hdmi,
+       &clk_sclk_mixer,
+};
+
 static struct clk *clkset_sclk_audio0_list[] = {
        [0] = &clk_ext_xtal_mux,
        [1] = &clk_pcmcdclk0,
@@ -775,14 +847,6 @@ static struct clksrc_clk clksrcs[] = {
                .sources = &clkset_uart,
                .reg_src = { .reg = S5P_CLK_SRC4, .shift = 28, .size = 4 },
                .reg_div = { .reg = S5P_CLK_DIV4, .shift = 28, .size = 4 },
-       }, {
-               .clk    = {
-                       .name           = "sclk_mixer",
-                       .enable         = s5pv210_clk_mask0_ctrl,
-                       .ctrlbit        = (1 << 1),
-               },
-               .sources = &clkset_sclk_mixer,
-               .reg_src = { .reg = S5P_CLK_SRC1, .shift = 4, .size = 1 },
        }, {
                .clk    = {
                        .name           = "sclk_fimc",
@@ -973,9 +1037,6 @@ static struct clksrc_clk *sysclks[] = {
        &clk_pclk_psys,
        &clk_vpllsrc,
        &clk_sclk_vpll,
-       &clk_sclk_dac,
-       &clk_sclk_pixel,
-       &clk_sclk_hdmi,
        &clk_mout_dmc0,
        &clk_sclk_dmc0,
        &clk_sclk_audio0,
@@ -1060,6 +1121,61 @@ static struct clk_ops s5pv210_epll_ops = {
        .get_rate = s5p_epll_get_rate,
 };
 
+static u32 vpll_div[][5] = {
+       {  54000000, 3, 53, 3, 0 },
+       { 108000000, 3, 53, 2, 0 },
+};
+
+static unsigned long s5pv210_vpll_get_rate(struct clk *clk)
+{
+       return clk->rate;
+}
+
+static int s5pv210_vpll_set_rate(struct clk *clk, unsigned long rate)
+{
+       unsigned int vpll_con;
+       unsigned int i;
+
+       /* Return if nothing changed */
+       if (clk->rate == rate)
+               return 0;
+
+       vpll_con = __raw_readl(S5P_VPLL_CON);
+       vpll_con &= ~(0x1 << 27 |                                       \
+                       PLL90XX_MDIV_MASK << PLL90XX_MDIV_SHIFT |       \
+                       PLL90XX_PDIV_MASK << PLL90XX_PDIV_SHIFT |       \
+                       PLL90XX_SDIV_MASK << PLL90XX_SDIV_SHIFT);
+
+       for (i = 0; i < ARRAY_SIZE(vpll_div); i++) {
+               if (vpll_div[i][0] == rate) {
+                       vpll_con |= vpll_div[i][1] << PLL90XX_PDIV_SHIFT;
+                       vpll_con |= vpll_div[i][2] << PLL90XX_MDIV_SHIFT;
+                       vpll_con |= vpll_div[i][3] << PLL90XX_SDIV_SHIFT;
+                       vpll_con |= vpll_div[i][4] << 27;
+                       break;
+               }
+       }
+
+       if (i == ARRAY_SIZE(vpll_div)) {
+               printk(KERN_ERR "%s: Invalid Clock VPLL Frequency\n",
+                               __func__);
+               return -EINVAL;
+       }
+
+       __raw_writel(vpll_con, S5P_VPLL_CON);
+
+       /* Wait for VPLL lock */
+       while (!(__raw_readl(S5P_VPLL_CON) & (1 << PLL90XX_LOCKED_SHIFT)))
+               continue;
+
+       clk->rate = rate;
+       return 0;
+}
+static struct clk_ops s5pv210_vpll_ops = {
+       .get_rate = s5pv210_vpll_get_rate,
+       .set_rate = s5pv210_vpll_set_rate,
+};
+
 void __init_or_cpufreq s5pv210_setup_clocks(void)
 {
        struct clk *xtal_clk;
@@ -1108,6 +1224,7 @@ void __init_or_cpufreq s5pv210_setup_clocks(void)
        clk_fout_apll.ops = &clk_fout_apll_ops;
        clk_fout_mpll.rate = mpll;
        clk_fout_epll.rate = epll;
+       clk_fout_vpll.ops = &s5pv210_vpll_ops;
        clk_fout_vpll.rate = vpll;
 
        printk(KERN_INFO "S5PV210: PLL settings, A=%ld, M=%ld, E=%ld V=%ld",
@@ -1153,11 +1270,15 @@ void __init s5pv210_register_clocks(void)
        for (ptr = 0; ptr < ARRAY_SIZE(sysclks); ptr++)
                s3c_register_clksrc(sysclks[ptr], 1);
 
+       for (ptr = 0; ptr < ARRAY_SIZE(sclk_tv); ptr++)
+               s3c_register_clksrc(sclk_tv[ptr], 1);
+
        s3c_register_clksrc(clksrcs, ARRAY_SIZE(clksrcs));
        s3c_register_clocks(init_clocks, ARRAY_SIZE(init_clocks));
 
        s3c_register_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
        s3c_disable_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
 
+       s3c24xx_register_clock(&dummy_apb_pclk);
        s3c_pwmclk_init();
 }
index 79907ec78d43440e8eed45a9283f4e2c00874ce4..6b8cdccbe931002710d359fe98cd15e7cf5bc373 100644 (file)
@@ -41,6 +41,7 @@
 #include <plat/keypad-core.h>
 #include <plat/sdhci.h>
 #include <plat/reset.h>
+#include <plat/tv-core.h>
 
 /* Initial IO mappings */
 
@@ -143,6 +144,9 @@ void __init s5pv210_map_io(void)
 
        /* Use s5pv210-keypad instead of samsung-keypad */
        samsung_keypad_setname("s5pv210-keypad");
+
+       /* setup TV devices */
+       s5p_hdmi_setname("s5pv210-hdmi");
 }
 
 void __init s5pv210_init_clocks(int xtal)
index 497d3439a142289e535938961c37313a77a3e1a8..86b749c18b77cfdb0da3215cd2528b44f7429e56 100644 (file)
@@ -1,4 +1,8 @@
-/*
+/* linux/arch/arm/mach-s5pv210/dma.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com
+ *
  * Copyright (C) 2010 Samsung Electronics Co. Ltd.
  *     Jaswinder Singh <jassi.brar@samsung.com>
  *
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#include <linux/platform_device.h>
 #include <linux/dma-mapping.h>
+#include <linux/amba/bus.h>
+#include <linux/amba/pl330.h>
 
+#include <asm/irq.h>
 #include <plat/devs.h>
 #include <plat/irqs.h>
 
 #include <mach/map.h>
 #include <mach/irqs.h>
-
-#include <plat/s3c-pl330-pdata.h>
+#include <mach/dma.h>
 
 static u64 dma_dmamask = DMA_BIT_MASK(32);
 
-static struct resource s5pv210_pdma0_resource[] = {
-       [0] = {
-               .start  = S5PV210_PA_PDMA0,
-               .end    = S5PV210_PA_PDMA0 + SZ_4K,
-               .flags = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = IRQ_PDMA0,
-               .end    = IRQ_PDMA0,
-               .flags  = IORESOURCE_IRQ,
+struct dma_pl330_peri pdma0_peri[28] = {
+       {
+               .peri_id = (u8)DMACH_UART0_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_UART0_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_UART1_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_UART1_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_UART2_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_UART2_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_UART3_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_UART3_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = DMACH_MAX,
+       }, {
+               .peri_id = (u8)DMACH_I2S0_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_I2S0_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_I2S0S_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_I2S1_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_I2S1_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_MAX,
+       }, {
+               .peri_id = (u8)DMACH_MAX,
+       }, {
+               .peri_id = (u8)DMACH_SPI0_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_SPI0_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_SPI1_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_SPI1_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_MAX,
+       }, {
+               .peri_id = (u8)DMACH_MAX,
+       }, {
+               .peri_id = (u8)DMACH_AC97_MICIN,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_AC97_PCMIN,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_AC97_PCMOUT,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_MAX,
+       }, {
+               .peri_id = (u8)DMACH_PWM,
+       }, {
+               .peri_id = (u8)DMACH_SPDIF,
+               .rqtype = MEMTODEV,
        },
 };
 
-static struct s3c_pl330_platdata s5pv210_pdma0_pdata = {
-       .peri = {
-               [0] = DMACH_UART0_RX,
-               [1] = DMACH_UART0_TX,
-               [2] = DMACH_UART1_RX,
-               [3] = DMACH_UART1_TX,
-               [4] = DMACH_UART2_RX,
-               [5] = DMACH_UART2_TX,
-               [6] = DMACH_UART3_RX,
-               [7] = DMACH_UART3_TX,
-               [8] = DMACH_MAX,
-               [9] = DMACH_I2S0_RX,
-               [10] = DMACH_I2S0_TX,
-               [11] = DMACH_I2S0S_TX,
-               [12] = DMACH_I2S1_RX,
-               [13] = DMACH_I2S1_TX,
-               [14] = DMACH_MAX,
-               [15] = DMACH_MAX,
-               [16] = DMACH_SPI0_RX,
-               [17] = DMACH_SPI0_TX,
-               [18] = DMACH_SPI1_RX,
-               [19] = DMACH_SPI1_TX,
-               [20] = DMACH_MAX,
-               [21] = DMACH_MAX,
-               [22] = DMACH_AC97_MICIN,
-               [23] = DMACH_AC97_PCMIN,
-               [24] = DMACH_AC97_PCMOUT,
-               [25] = DMACH_MAX,
-               [26] = DMACH_PWM,
-               [27] = DMACH_SPDIF,
-               [28] = DMACH_MAX,
-               [29] = DMACH_MAX,
-               [30] = DMACH_MAX,
-               [31] = DMACH_MAX,
-       },
+struct dma_pl330_platdata s5pv210_pdma0_pdata = {
+       .nr_valid_peri = ARRAY_SIZE(pdma0_peri),
+       .peri = pdma0_peri,
 };
 
-static struct platform_device s5pv210_device_pdma0 = {
-       .name           = "s3c-pl330",
-       .id             = 0,
-       .num_resources  = ARRAY_SIZE(s5pv210_pdma0_resource),
-       .resource       = s5pv210_pdma0_resource,
-       .dev            = {
+struct amba_device s5pv210_device_pdma0 = {
+       .dev = {
+               .init_name = "dma-pl330.0",
                .dma_mask = &dma_dmamask,
                .coherent_dma_mask = DMA_BIT_MASK(32),
                .platform_data = &s5pv210_pdma0_pdata,
        },
-};
-
-static struct resource s5pv210_pdma1_resource[] = {
-       [0] = {
-               .start  = S5PV210_PA_PDMA1,
-               .end    = S5PV210_PA_PDMA1 + SZ_4K,
+       .res = {
+               .start = S5PV210_PA_PDMA0,
+               .end = S5PV210_PA_PDMA0 + SZ_4K,
                .flags = IORESOURCE_MEM,
        },
-       [1] = {
-               .start  = IRQ_PDMA1,
-               .end    = IRQ_PDMA1,
-               .flags  = IORESOURCE_IRQ,
-       },
+       .irq = {IRQ_PDMA0, NO_IRQ},
+       .periphid = 0x00041330,
 };
 
-static struct s3c_pl330_platdata s5pv210_pdma1_pdata = {
-       .peri = {
-               [0] = DMACH_UART0_RX,
-               [1] = DMACH_UART0_TX,
-               [2] = DMACH_UART1_RX,
-               [3] = DMACH_UART1_TX,
-               [4] = DMACH_UART2_RX,
-               [5] = DMACH_UART2_TX,
-               [6] = DMACH_UART3_RX,
-               [7] = DMACH_UART3_TX,
-               [8] = DMACH_MAX,
-               [9] = DMACH_I2S0_RX,
-               [10] = DMACH_I2S0_TX,
-               [11] = DMACH_I2S0S_TX,
-               [12] = DMACH_I2S1_RX,
-               [13] = DMACH_I2S1_TX,
-               [14] = DMACH_I2S2_RX,
-               [15] = DMACH_I2S2_TX,
-               [16] = DMACH_SPI0_RX,
-               [17] = DMACH_SPI0_TX,
-               [18] = DMACH_SPI1_RX,
-               [19] = DMACH_SPI1_TX,
-               [20] = DMACH_MAX,
-               [21] = DMACH_MAX,
-               [22] = DMACH_PCM0_RX,
-               [23] = DMACH_PCM0_TX,
-               [24] = DMACH_PCM1_RX,
-               [25] = DMACH_PCM1_TX,
-               [26] = DMACH_MSM_REQ0,
-               [27] = DMACH_MSM_REQ1,
-               [28] = DMACH_MSM_REQ2,
-               [29] = DMACH_MSM_REQ3,
-               [30] = DMACH_PCM2_RX,
-               [31] = DMACH_PCM2_TX,
+struct dma_pl330_peri pdma1_peri[32] = {
+       {
+               .peri_id = (u8)DMACH_UART0_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_UART0_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_UART1_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_UART1_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_UART2_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_UART2_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_UART3_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_UART3_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = DMACH_MAX,
+       }, {
+               .peri_id = (u8)DMACH_I2S0_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_I2S0_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_I2S0S_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_I2S1_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_I2S1_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_I2S2_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_I2S2_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_SPI0_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_SPI0_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_SPI1_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_SPI1_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_MAX,
+       }, {
+               .peri_id = (u8)DMACH_MAX,
+       }, {
+               .peri_id = (u8)DMACH_PCM0_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_PCM0_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_PCM1_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_PCM1_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_MSM_REQ0,
+       }, {
+               .peri_id = (u8)DMACH_MSM_REQ1,
+       }, {
+               .peri_id = (u8)DMACH_MSM_REQ2,
+       }, {
+               .peri_id = (u8)DMACH_MSM_REQ3,
+       }, {
+               .peri_id = (u8)DMACH_PCM2_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_PCM2_TX,
+               .rqtype = MEMTODEV,
        },
 };
 
-static struct platform_device s5pv210_device_pdma1 = {
-       .name           = "s3c-pl330",
-       .id             = 1,
-       .num_resources  = ARRAY_SIZE(s5pv210_pdma1_resource),
-       .resource       = s5pv210_pdma1_resource,
-       .dev            = {
+struct dma_pl330_platdata s5pv210_pdma1_pdata = {
+       .nr_valid_peri = ARRAY_SIZE(pdma1_peri),
+       .peri = pdma1_peri,
+};
+
+struct amba_device s5pv210_device_pdma1 = {
+       .dev = {
+               .init_name = "dma-pl330.1",
                .dma_mask = &dma_dmamask,
                .coherent_dma_mask = DMA_BIT_MASK(32),
                .platform_data = &s5pv210_pdma1_pdata,
        },
-};
-
-static struct platform_device *s5pv210_dmacs[] __initdata = {
-       &s5pv210_device_pdma0,
-       &s5pv210_device_pdma1,
+       .res = {
+               .start = S5PV210_PA_PDMA1,
+               .end = S5PV210_PA_PDMA1 + SZ_4K,
+               .flags = IORESOURCE_MEM,
+       },
+       .irq = {IRQ_PDMA1, NO_IRQ},
+       .periphid = 0x00041330,
 };
 
 static int __init s5pv210_dma_init(void)
 {
-       platform_add_devices(s5pv210_dmacs, ARRAY_SIZE(s5pv210_dmacs));
+       amba_device_register(&s5pv210_device_pdma0, &iomem_resource);
+       amba_device_register(&s5pv210_device_pdma1, &iomem_resource);
 
        return 0;
 }
index 81209eb1409b7ad4c55a70897379547991ea2958..201842a3769e5187067d95b70c9d2e14a5ea3acd 100644 (file)
@@ -20,7 +20,7 @@
 #ifndef __MACH_DMA_H
 #define __MACH_DMA_H
 
-/* This platform uses the common S3C DMA API driver for PL330 */
-#include <plat/s3c-dma-pl330.h>
+/* This platform uses the common DMA API driver for PL330 */
+#include <plat/dma-pl330.h>
 
 #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 (file)
index 0000000..6afa624
--- /dev/null
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) 2011 Samsung Electronics Co., Ltd.
+ *
+ * S5P series i2c hdmiphy helper definitions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef PLAT_S5P_I2C_HDMIPHY_H_
+#define PLAT_S5P_I2C_HDMIPHY_H_
+
+#define S5P_I2C_HDMIPHY_BUS_NUM                (3)
+
+#endif
index b9f9ec33384d6cecc1633a90e9aabb3492d556b0..5e0de3a31f3d7f621f32eba0d6e5a448ccdad559 100644 (file)
@@ -56,7 +56,7 @@
 #define IRQ_SPI2               S5P_IRQ_VIC1(17)
 #define IRQ_IRDA               S5P_IRQ_VIC1(18)
 #define IRQ_IIC2               S5P_IRQ_VIC1(19)
-#define IRQ_IIC3               S5P_IRQ_VIC1(20)
+#define IRQ_IIC_HDMIPHY                S5P_IRQ_VIC1(20)
 #define IRQ_HSIRX              S5P_IRQ_VIC1(21)
 #define IRQ_HSITX              S5P_IRQ_VIC1(22)
 #define IRQ_UHOST              S5P_IRQ_VIC1(23)
@@ -86,7 +86,7 @@
 #define IRQ_HDMI               S5P_IRQ_VIC2(12)
 #define IRQ_IIC1               S5P_IRQ_VIC2(13)
 #define IRQ_MFC                        S5P_IRQ_VIC2(14)
-#define IRQ_TVENC              S5P_IRQ_VIC2(15)
+#define IRQ_SDO                        S5P_IRQ_VIC2(15)
 #define IRQ_I2S0               S5P_IRQ_VIC2(16)
 #define IRQ_I2S1               S5P_IRQ_VIC2(17)
 #define IRQ_I2S2               S5P_IRQ_VIC2(18)
index aac343c180b2cffb7bb757248d15286a56bee58a..7ff609f1568b10b4d71b9fd7aca0218248b48235 100644 (file)
 #define S5PV210_PA_FIMC1               0xFB300000
 #define S5PV210_PA_FIMC2               0xFB400000
 
+#define S5PV210_PA_SDO                 0xF9000000
+#define S5PV210_PA_VP                  0xF9100000
+#define S5PV210_PA_MIXER               0xF9200000
+#define S5PV210_PA_HDMI                        0xFA100000
+#define S5PV210_PA_IIC_HDMIPHY         0xFA900000
+
 /* Compatibiltiy Defines */
 
 #define S3C_PA_FB                      S5PV210_PA_FB
 #define S5P_PA_FIMC2                   S5PV210_PA_FIMC2
 #define S5P_PA_MIPI_CSIS0              S5PV210_PA_MIPI_CSIS
 #define S5P_PA_MFC                     S5PV210_PA_MFC
+#define S5P_PA_IIC_HDMIPHY             S5PV210_PA_IIC_HDMIPHY
+
+#define S5P_PA_SDO                     S5PV210_PA_SDO
+#define S5P_PA_VP                      S5PV210_PA_VP
+#define S5P_PA_MIXER                   S5PV210_PA_MIXER
+#define S5P_PA_HDMI                    S5PV210_PA_HDMI
+
 #define S5P_PA_ONENAND                 S5PC110_PA_ONENAND
 #define S5P_PA_ONENAND_DMA             S5PC110_PA_ONENAND_DMA
 #define S5P_PA_SDRAM                   S5PV210_PA_SDRAM
index 3e22109e1b7b4e851f890cb19cffd4d49c89314e..eba8aea63ed8f928b09f9d56a8486d666e31e302 100644 (file)
@@ -43,4 +43,4 @@ static inline void s3c_pm_arch_update_uart(void __iomem *regs,
 }
 
 static inline void s3c_pm_restored_gpios(void) { }
-static inline void s3c_pm_saved_gpios(void) { }
+static inline void samsung_pm_saved_gpios(void) { }
index 78925c5163469f380d7c057625285c5c21570da9..032de66fb8be2817496da9c431a2f5fef69d66f9 100644 (file)
 
 #define S5P_OTHERS             S5P_CLKREG(0xE000)
 #define S5P_OM_STAT            S5P_CLKREG(0xE100)
+#define S5P_HDMI_PHY_CONTROL   S5P_CLKREG(0xE804)
 #define S5P_USB_PHY_CONTROL    S5P_CLKREG(0xE80C)
-#define S5P_DAC_CONTROL                S5P_CLKREG(0xE810)
+#define S5P_DAC_PHY_CONTROL    S5P_CLKREG(0xE810)
 #define S5P_MIPI_DPHY_CONTROL(x) S5P_CLKREG(0xE814)
 #define S5P_MIPI_DPHY_ENABLE   (1 << 0)
 #define S5P_MIPI_DPHY_SRESETN  (1 << 1)
index 85c2d51a095687660d005402aa362d83e3c75e8d..01e4867e25ad96a40160caad4f27581aabd420d8 100644 (file)
 #include <plat/s5p-time.h>
 #include <plat/mfc.h>
 #include <plat/regs-fb-v4.h>
+#include <plat/camport.h>
+
+#include <media/v4l2-mediabus.h>
+#include <media/s5p_fimc.h>
+#include <media/noon010pc30.h>
 
 /* Following are default values for UCON, ULCON and UFCON UART registers */
 #define GONI_UCON_DEFAULT      (S3C2410_UCON_TXILEVEL |        \
@@ -272,6 +277,14 @@ static void __init goni_tsp_init(void)
        i2c2_devs[0].irq = gpio_to_irq(gpio);
 }
 
+static void goni_camera_init(void)
+{
+       s5pv210_fimc_setup_gpio(S5P_CAMPORT_A);
+
+       /* Set max driver strength on CAM_A_CLKOUT pin. */
+       s5p_gpio_set_drvstr(S5PV210_GPE1(3), S5P_GPIO_DRVSTR_LV4);
+}
+
 /* MAX8998 regulators */
 #if defined(CONFIG_REGULATOR_MAX8998) || defined(CONFIG_REGULATOR_MAX8998_MODULE)
 
@@ -285,6 +298,7 @@ static struct regulator_consumer_supply goni_ldo5_consumers[] = {
 
 static struct regulator_consumer_supply goni_ldo8_consumers[] = {
        REGULATOR_SUPPLY("vusb_d", "s3c-hsotg"),
+       REGULATOR_SUPPLY("vdd33a_dac", "s5p-sdo"),
 };
 
 static struct regulator_consumer_supply goni_ldo11_consumers[] = {
@@ -475,6 +489,10 @@ static struct regulator_consumer_supply buck1_consumer =
 static struct regulator_consumer_supply buck2_consumer =
        REGULATOR_SUPPLY("vddint", NULL);
 
+static struct regulator_consumer_supply buck3_consumer =
+       REGULATOR_SUPPLY("vdet", "s5p-sdo");
+
+
 static struct regulator_init_data goni_buck1_data = {
        .constraints    = {
                .name           = "VARM_1.2V",
@@ -511,6 +529,8 @@ static struct regulator_init_data goni_buck3_data = {
                        .enabled = 1,
                },
        },
+       .num_consumer_supplies  = 1,
+       .consumer_supplies      = &buck3_consumer,
 };
 
 static struct regulator_init_data goni_buck4_data = {
@@ -801,6 +821,39 @@ static void goni_setup_sdhci(void)
        s3c_sdhci2_set_platdata(&goni_hsmmc2_data);
 };
 
+static struct noon010pc30_platform_data noon010pc30_pldata = {
+       .clk_rate       = 16000000UL,
+       .gpio_nreset    = S5PV210_GPB(2), /* CAM_CIF_NRST */
+       .gpio_nstby     = S5PV210_GPB(0), /* CAM_CIF_NSTBY */
+};
+
+static struct i2c_board_info noon010pc30_board_info = {
+       I2C_BOARD_INFO("NOON010PC30", 0x60 >> 1),
+       .platform_data = &noon010pc30_pldata,
+};
+
+static struct s5p_fimc_isp_info goni_camera_sensors[] = {
+       {
+               .mux_id         = 0,
+               .flags          = V4L2_MBUS_PCLK_SAMPLE_FALLING |
+                                 V4L2_MBUS_VSYNC_ACTIVE_LOW,
+               .bus_type       = FIMC_ITU_601,
+               .board_info     = &noon010pc30_board_info,
+               .i2c_bus_num    = 0,
+               .clk_frequency  = 16000000UL,
+       },
+};
+
+struct s5p_platform_fimc goni_fimc_md_platdata __initdata = {
+       .isp_info       = goni_camera_sensors,
+       .num_clients    = ARRAY_SIZE(goni_camera_sensors),
+};
+
+struct platform_device s5p_device_fimc_md = {
+       .name           = "s5p-fimc-md",
+       .id             = -1,
+};
+
 static struct platform_device *goni_devices[] __initdata = {
        &s3c_device_fb,
        &s5p_device_onenand,
@@ -812,10 +865,13 @@ static struct platform_device *goni_devices[] __initdata = {
        &s5p_device_mfc,
        &s5p_device_mfc_l,
        &s5p_device_mfc_r,
+       &s5p_device_mixer,
+       &s5p_device_sdo,
        &s3c_device_i2c0,
        &s5p_device_fimc0,
        &s5p_device_fimc1,
        &s5p_device_fimc2,
+       &s5p_device_fimc_md,
        &s3c_device_hsmmc0,
        &s3c_device_hsmmc1,
        &s3c_device_hsmmc2,
@@ -884,6 +940,12 @@ static void __init goni_machine_init(void)
        /* FB */
        s3c_fb_set_platdata(&goni_lcd_pdata);
 
+       /* FIMC */
+       s3c_set_platdata(&goni_fimc_md_platdata, sizeof(goni_fimc_md_platdata),
+                        &s5p_device_fimc_md);
+
+       goni_camera_init();
+
        /* SPI */
        spi_register_board_info(spi_board_info, ARRAY_SIZE(spi_board_info));
 
index 8c5b3029b39fca958703da3a73316daf85a212a7..d8973ac46bc4e909a9f04a6e43883197e8e4acec 100644 (file)
@@ -9,7 +9,6 @@ config PLAT_S3C24XX
        select NO_IOPORT
        select ARCH_REQUIRE_GPIOLIB
        select S3C_DEV_NAND
-       select S3C_GPIO_CFG_S3C24XX
        help
          Base platform code for any Samsung S3C24XX device
 
index 0291bd6e236e832003986d6559eda8699740aba4..e4f46495ed308e707c9a3f274ffb6ea58bbc5a9c 100644 (file)
@@ -15,8 +15,6 @@ obj-                          :=
 obj-y                          += cpu.o
 obj-y                          += irq.o
 obj-y                          += devs.o
-obj-y                          += gpio.o
-obj-y                          += gpiolib.o
 obj-y                          += clock.o
 obj-$(CONFIG_S3C24XX_DCLK)     += clock-dclk.o
 
index 539bd0e3defdc2ab9be00294a997a80fd060f6d6..53754bcf15a758c05b536f5836c2efb6ea2ba57d 100644 (file)
@@ -1094,14 +1094,14 @@ EXPORT_SYMBOL(s3c2410_dma_config);
  *
  * configure the dma source/destination hardware type and address
  *
- * source:    S3C2410_DMASRC_HW: source is hardware
- *            S3C2410_DMASRC_MEM: source is memory
+ * source:    DMA_FROM_DEVICE: source is hardware
+ *            DMA_TO_DEVICE: source is memory
  *
  * devaddr:   physical address of the source
 */
 
 int s3c2410_dma_devconfig(enum dma_ch channel,
-                         enum s3c2410_dmasrc source,
+                         enum dma_data_direction source,
                          unsigned long devaddr)
 {
        struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel);
@@ -1131,7 +1131,7 @@ int s3c2410_dma_devconfig(enum dma_ch channel,
         hwcfg |= S3C2410_DISRCC_INC;
 
        switch (source) {
-       case S3C2410_DMASRC_HW:
+       case DMA_FROM_DEVICE:
                /* source is hardware */
                pr_debug("%s: hw source, devaddr=%08lx, hwcfg=%d\n",
                         __func__, devaddr, hwcfg);
@@ -1142,7 +1142,7 @@ int s3c2410_dma_devconfig(enum dma_ch channel,
                chan->addr_reg = dma_regaddr(chan, S3C2410_DMA_DIDST);
                break;
 
-       case S3C2410_DMASRC_MEM:
+       case DMA_TO_DEVICE:
                /* source is memory */
                pr_debug("%s: mem source, devaddr=%08lx, hwcfg=%d\n",
                         __func__, devaddr, hwcfg);
diff --git a/arch/arm/plat-s3c24xx/gpio.c b/arch/arm/plat-s3c24xx/gpio.c
deleted file mode 100644 (file)
index 2f3d7c0..0000000
+++ /dev/null
@@ -1,96 +0,0 @@
-/* linux/arch/arm/plat-s3c24xx/gpio.c
- *
- * Copyright (c) 2004-2010 Simtec Electronics
- *     Ben Dooks <ben@simtec.co.uk>
- *
- * S3C24XX GPIO support
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/gpio.h>
-#include <linux/io.h>
-
-#include <mach/hardware.h>
-#include <mach/gpio-fns.h>
-#include <asm/irq.h>
-
-#include <mach/regs-gpio.h>
-
-#include <plat/gpio-core.h>
-
-/* gpiolib wrappers until these are totally eliminated */
-
-void s3c2410_gpio_pullup(unsigned int pin, unsigned int to)
-{
-       int ret;
-
-       WARN_ON(to);    /* should be none of these left */
-
-       if (!to) {
-               /* if pull is enabled, try first with up, and if that
-                * fails, try using down */
-
-               ret = s3c_gpio_setpull(pin, S3C_GPIO_PULL_UP);
-               if (ret)
-                       s3c_gpio_setpull(pin, S3C_GPIO_PULL_DOWN);
-       } else {
-               s3c_gpio_setpull(pin, S3C_GPIO_PULL_NONE);
-       }
-}
-EXPORT_SYMBOL(s3c2410_gpio_pullup);
-
-void s3c2410_gpio_setpin(unsigned int pin, unsigned int to)
-{
-       /* do this via gpiolib until all users removed */
-
-       gpio_request(pin, "temporary");
-       gpio_set_value(pin, to);
-       gpio_free(pin);
-}
-
-EXPORT_SYMBOL(s3c2410_gpio_setpin);
-
-unsigned int s3c2410_gpio_getpin(unsigned int pin)
-{
-       struct s3c_gpio_chip *chip = s3c_gpiolib_getchip(pin);
-       unsigned long offs = pin - chip->chip.base;
-
-       return __raw_readl(chip->base + 0x04) & (1<< offs);
-}
-
-EXPORT_SYMBOL(s3c2410_gpio_getpin);
-
-unsigned int s3c2410_modify_misccr(unsigned int clear, unsigned int change)
-{
-       unsigned long flags;
-       unsigned long misccr;
-
-       local_irq_save(flags);
-       misccr = __raw_readl(S3C24XX_MISCCR);
-       misccr &= ~clear;
-       misccr ^= change;
-       __raw_writel(misccr, S3C24XX_MISCCR);
-       local_irq_restore(flags);
-
-       return misccr;
-}
-
-EXPORT_SYMBOL(s3c2410_modify_misccr);
diff --git a/arch/arm/plat-s3c24xx/gpiolib.c b/arch/arm/plat-s3c24xx/gpiolib.c
deleted file mode 100644 (file)
index 243b641..0000000
+++ /dev/null
@@ -1,229 +0,0 @@
-/* linux/arch/arm/plat-s3c24xx/gpiolib.c
- *
- * Copyright (c) 2008-2010 Simtec Electronics
- *     http://armlinux.simtec.co.uk/
- *     Ben Dooks <ben@simtec.co.uk>
- *
- * S3C24XX GPIOlib support
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License.
-*/
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/interrupt.h>
-#include <linux/sysdev.h>
-#include <linux/ioport.h>
-#include <linux/io.h>
-#include <linux/gpio.h>
-
-#include <plat/gpio-core.h>
-#include <plat/gpio-cfg.h>
-#include <plat/gpio-cfg-helpers.h>
-#include <mach/hardware.h>
-#include <asm/irq.h>
-#include <plat/pm.h>
-
-#include <mach/regs-gpio.h>
-
-static int s3c24xx_gpiolib_banka_input(struct gpio_chip *chip, unsigned offset)
-{
-       return -EINVAL;
-}
-
-static int s3c24xx_gpiolib_banka_output(struct gpio_chip *chip,
-                                       unsigned offset, int value)
-{
-       struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
-       void __iomem *base = ourchip->base;
-       unsigned long flags;
-       unsigned long dat;
-       unsigned long con;
-
-       local_irq_save(flags);
-
-       con = __raw_readl(base + 0x00);
-       dat = __raw_readl(base + 0x04);
-
-       dat &= ~(1 << offset);
-       if (value)
-               dat |= 1 << offset;
-
-       __raw_writel(dat, base + 0x04);
-
-       con &= ~(1 << offset);
-
-       __raw_writel(con, base + 0x00);
-       __raw_writel(dat, base + 0x04);
-
-       local_irq_restore(flags);
-       return 0;
-}
-
-static int s3c24xx_gpiolib_bankf_toirq(struct gpio_chip *chip, unsigned offset)
-{
-       if (offset < 4)
-               return IRQ_EINT0 + offset;
-       
-       if (offset < 8)
-               return IRQ_EINT4 + offset - 4;
-       
-       return -EINVAL;
-}
-
-static struct s3c_gpio_cfg s3c24xx_gpiocfg_banka = {
-       .set_config     = s3c_gpio_setcfg_s3c24xx_a,
-       .get_config     = s3c_gpio_getcfg_s3c24xx_a,
-};
-
-struct s3c_gpio_cfg s3c24xx_gpiocfg_default = {
-       .set_config     = s3c_gpio_setcfg_s3c24xx,
-       .get_config     = s3c_gpio_getcfg_s3c24xx,
-};
-
-struct s3c_gpio_chip s3c24xx_gpios[] = {
-       [0] = {
-               .base   = S3C2410_GPACON,
-               .pm     = __gpio_pm(&s3c_gpio_pm_1bit),
-               .config = &s3c24xx_gpiocfg_banka,
-               .chip   = {
-                       .base                   = S3C2410_GPA(0),
-                       .owner                  = THIS_MODULE,
-                       .label                  = "GPIOA",
-                       .ngpio                  = 24,
-                       .direction_input        = s3c24xx_gpiolib_banka_input,
-                       .direction_output       = s3c24xx_gpiolib_banka_output,
-               },
-       },
-       [1] = {
-               .base   = S3C2410_GPBCON,
-               .pm     = __gpio_pm(&s3c_gpio_pm_2bit),
-               .chip   = {
-                       .base                   = S3C2410_GPB(0),
-                       .owner                  = THIS_MODULE,
-                       .label                  = "GPIOB",
-                       .ngpio                  = 16,
-               },
-       },
-       [2] = {
-               .base   = S3C2410_GPCCON,
-               .pm     = __gpio_pm(&s3c_gpio_pm_2bit),
-               .chip   = {
-                       .base                   = S3C2410_GPC(0),
-                       .owner                  = THIS_MODULE,
-                       .label                  = "GPIOC",
-                       .ngpio                  = 16,
-               },
-       },
-       [3] = {
-               .base   = S3C2410_GPDCON,
-               .pm     = __gpio_pm(&s3c_gpio_pm_2bit),
-               .chip   = {
-                       .base                   = S3C2410_GPD(0),
-                       .owner                  = THIS_MODULE,
-                       .label                  = "GPIOD",
-                       .ngpio                  = 16,
-               },
-       },
-       [4] = {
-               .base   = S3C2410_GPECON,
-               .pm     = __gpio_pm(&s3c_gpio_pm_2bit),
-               .chip   = {
-                       .base                   = S3C2410_GPE(0),
-                       .label                  = "GPIOE",
-                       .owner                  = THIS_MODULE,
-                       .ngpio                  = 16,
-               },
-       },
-       [5] = {
-               .base   = S3C2410_GPFCON,
-               .pm     = __gpio_pm(&s3c_gpio_pm_2bit),
-               .chip   = {
-                       .base                   = S3C2410_GPF(0),
-                       .owner                  = THIS_MODULE,
-                       .label                  = "GPIOF",
-                       .ngpio                  = 8,
-                       .to_irq                 = s3c24xx_gpiolib_bankf_toirq,
-               },
-       },
-       [6] = {
-               .base   = S3C2410_GPGCON,
-               .pm     = __gpio_pm(&s3c_gpio_pm_2bit),
-               .irq_base = IRQ_EINT8,
-               .chip   = {
-                       .base                   = S3C2410_GPG(0),
-                       .owner                  = THIS_MODULE,
-                       .label                  = "GPIOG",
-                       .ngpio                  = 16,
-                       .to_irq                 = samsung_gpiolib_to_irq,
-               },
-       }, {
-               .base   = S3C2410_GPHCON,
-               .pm     = __gpio_pm(&s3c_gpio_pm_2bit),
-               .chip   = {
-                       .base                   = S3C2410_GPH(0),
-                       .owner                  = THIS_MODULE,
-                       .label                  = "GPIOH",
-                       .ngpio                  = 11,
-               },
-       },
-               /* GPIOS for the S3C2443 and later devices. */
-       {
-               .base   = S3C2440_GPJCON,
-               .pm     = __gpio_pm(&s3c_gpio_pm_2bit),
-               .chip   = {
-                       .base                   = S3C2410_GPJ(0),
-                       .owner                  = THIS_MODULE,
-                       .label                  = "GPIOJ",
-                       .ngpio                  = 16,
-               },
-       }, {
-               .base   = S3C2443_GPKCON,
-               .pm     = __gpio_pm(&s3c_gpio_pm_2bit),
-               .chip   = {
-                       .base                   = S3C2410_GPK(0),
-                       .owner                  = THIS_MODULE,
-                       .label                  = "GPIOK",
-                       .ngpio                  = 16,
-               },
-       }, {
-               .base   = S3C2443_GPLCON,
-               .pm     = __gpio_pm(&s3c_gpio_pm_2bit),
-               .chip   = {
-                       .base                   = S3C2410_GPL(0),
-                       .owner                  = THIS_MODULE,
-                       .label                  = "GPIOL",
-                       .ngpio                  = 15,
-               },
-       }, {
-               .base   = S3C2443_GPMCON,
-               .pm     = __gpio_pm(&s3c_gpio_pm_2bit),
-               .chip   = {
-                       .base                   = S3C2410_GPM(0),
-                       .owner                  = THIS_MODULE,
-                       .label                  = "GPIOM",
-                       .ngpio                  = 2,
-               },
-       },
-};
-
-
-static __init int s3c24xx_gpiolib_init(void)
-{
-       struct s3c_gpio_chip *chip = s3c24xx_gpios;
-       int gpn;
-
-       for (gpn = 0; gpn < ARRAY_SIZE(s3c24xx_gpios); gpn++, chip++) {
-               if (!chip->config)
-                       chip->config = &s3c24xx_gpiocfg_default;
-
-               s3c_gpiolib_add(chip);
-       }
-
-       return 0;
-}
-
-core_initcall(s3c24xx_gpiolib_init);
index 59552c0ea5fb3efe6feaaa17a42b39a8cfd05685..07a4c81587acbc9788e959e507e04d6c319b51f4 100644 (file)
@@ -205,9 +205,64 @@ static struct clksrc_clk clksrc_clks[] = {
        },
 };
 
+static struct clk clk_i2s_ext = {
+       .name           = "i2s-ext",
+};
+
+/* i2s_eplldiv
+ *
+ * This clock is the output from the I2S divisor of ESYSCLK, and is separate
+ * from the mux that comes after it (cannot merge into one single clock)
+*/
+
+static struct clksrc_clk clk_i2s_eplldiv = {
+       .clk    = {
+               .name           = "i2s-eplldiv",
+               .parent         = &clk_esysclk.clk,
+       },
+       .reg_div = { .reg = S3C2443_CLKDIV1, .size = 4, .shift = 12, },
+};
+
+/* i2s-ref
+ *
+ * i2s bus reference clock, selectable from external, esysclk or epllref
+ *
+ * Note, this used to be two clocks, but was compressed into one.
+*/
+
+static struct clk *clk_i2s_srclist[] = {
+       [0] = &clk_i2s_eplldiv.clk,
+       [1] = &clk_i2s_ext,
+       [2] = &clk_epllref.clk,
+       [3] = &clk_epllref.clk,
+};
+
+static struct clksrc_clk clk_i2s = {
+       .clk    = {
+               .name           = "i2s-if",
+               .ctrlbit        = S3C2443_SCLKCON_I2SCLK,
+               .enable         = s3c2443_clkcon_enable_s,
+
+       },
+       .sources = &(struct clksrc_sources) {
+               .sources = clk_i2s_srclist,
+               .nr_sources = ARRAY_SIZE(clk_i2s_srclist),
+       },
+       .reg_src = { .reg = S3C2443_CLKSRC, .size = 2, .shift = 14 },
+};
 
 static struct clk init_clocks_off[] = {
        {
+               .name           = "iis",
+               .parent         = &clk_p,
+               .enable         = s3c2443_clkcon_enable_p,
+               .ctrlbit        = S3C2443_PCLKCON_IIS,
+       }, {
+               .name           = "hsspi",
+               .parent         = &clk_p,
+               .enable         = s3c2443_clkcon_enable_p,
+               .ctrlbit        = S3C2443_PCLKCON_HSSPI,
+       }, {
                .name           = "adc",
                .parent         = &clk_p,
                .enable         = s3c2443_clkcon_enable_p,
@@ -406,6 +461,8 @@ static struct clk *clks[] __initdata = {
 };
 
 static struct clksrc_clk *clksrcs[] __initdata = {
+       &clk_i2s_eplldiv,
+       &clk_i2s,
        &clk_usb_bus_host,
        &clk_epllref,
        &clk_esysclk,
index 9843c954c0425b89960859c6680a64b100023fff..f9241a7a68ca04a02245de72e0daed57ccc16333 100644 (file)
@@ -16,9 +16,6 @@ config PLAT_S5P
        select S3C_GPIO_TRACK
        select S5P_GPIO_DRVSTR
        select SAMSUNG_GPIOLIB_4BIT
-       select S3C_GPIO_CFG_S3C64XX
-       select S3C_GPIO_PULL_UPDOWN
-       select S3C_GPIO_CFG_S3C24XX
        select PLAT_SAMSUNG
        select SAMSUNG_CLKSRC
        select SAMSUNG_IRQ_VIC_TIMER
@@ -76,6 +73,11 @@ config S5P_DEV_FIMD0
        help
          Compile in platform device definitions for FIMD controller 0
 
+config S5P_DEV_I2C_HDMIPHY
+       bool
+       help
+         Compile in platform device definitions for I2C HDMIPHY controller
+
 config S5P_DEV_MFC
        bool
        help
@@ -96,6 +98,11 @@ config S5P_DEV_CSIS1
        help
          Compile in platform device definitions for MIPI-CSIS channel 1
 
+config S5P_DEV_TV
+       bool
+       help
+         Compile in platform device definition for TV interface
+
 config S5P_DEV_USB_EHCI
        bool
        help
index 4b53e04eeca465266ec5faa2cc61147120e2a311..181201974b4146d997779b113d862033781cd0f6 100644 (file)
@@ -31,8 +31,10 @@ obj-$(CONFIG_S5P_DEV_FIMC1)  += dev-fimc1.o
 obj-$(CONFIG_S5P_DEV_FIMC2)    += dev-fimc2.o
 obj-$(CONFIG_S5P_DEV_FIMC3)    += dev-fimc3.o
 obj-$(CONFIG_S5P_DEV_FIMD0)    += dev-fimd0.o
+obj-$(CONFIG_S5P_DEV_I2C_HDMIPHY) += dev-i2c-hdmiphy.o
 obj-$(CONFIG_S5P_DEV_ONENAND)  += dev-onenand.o
 obj-$(CONFIG_S5P_DEV_CSIS0)    += dev-csis0.o
 obj-$(CONFIG_S5P_DEV_CSIS1)    += dev-csis1.o
+obj-$(CONFIG_S5P_DEV_TV)       += dev-tv.o
 obj-$(CONFIG_S5P_DEV_USB_EHCI) += dev-ehci.o
 obj-$(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 (file)
index 0000000..37343f1
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ *
+ * S5P series device definition for i2c for hdmiphy device
+ *
+ * Based on plat-samsung/dev-i2c7.c
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/gfp.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/platform_device.h>
+
+#include <mach/irqs.h>
+#include <mach/map.h>
+#include <mach/i2c-hdmiphy.h>
+
+#include <plat/regs-iic.h>
+#include <plat/devs.h>
+#include <plat/cpu.h>
+#include <plat/iic.h>
+
+static struct resource s5p_i2c_resource[] = {
+       [0] = {
+               .start = S5P_PA_IIC_HDMIPHY,
+               .end   = S5P_PA_IIC_HDMIPHY + SZ_4K - 1,
+               .flags = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start = IRQ_IIC_HDMIPHY,
+               .end   = IRQ_IIC_HDMIPHY,
+               .flags = IORESOURCE_IRQ,
+       },
+};
+
+struct platform_device s5p_device_i2c_hdmiphy = {
+       .name             = "s3c2440-hdmiphy-i2c",
+       .id               = -1,
+       .num_resources    = ARRAY_SIZE(s5p_i2c_resource),
+       .resource         = s5p_i2c_resource,
+};
+
+void __init s5p_i2c_hdmiphy_set_platdata(struct s3c2410_platform_i2c *pd)
+{
+       struct s3c2410_platform_i2c *npd;
+
+       if (!pd) {
+               pd = &default_i2c_data;
+               pd->bus_num = S5P_I2C_HDMIPHY_BUS_NUM;
+       }
+
+       npd = s3c_set_platdata(pd, sizeof(struct s3c2410_platform_i2c),
+                              &s5p_device_i2c_hdmiphy);
+}
diff --git a/arch/arm/plat-s5p/dev-tv.c b/arch/arm/plat-s5p/dev-tv.c
new file mode 100644 (file)
index 0000000..361a1b6
--- /dev/null
@@ -0,0 +1,98 @@
+/* linux/arch/arm/plat-s5p/dev-tv.c
+ *
+ * Copyright (C) 2011 Samsung Electronics Co.Ltd
+ * Author: Tomasz Stanislawski <t.stanislaws@samsung.com>
+ *
+ * S5P series device definition for TV device
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/dma-mapping.h>
+
+#include <mach/irqs.h>
+#include <mach/map.h>
+
+#include <plat/devs.h>
+
+/* HDMI interface */
+static struct resource s5p_hdmi_resources[] = {
+       [0] = {
+               .start  = S5P_PA_HDMI,
+               .end    = S5P_PA_HDMI + SZ_1M - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = IRQ_HDMI,
+               .end    = IRQ_HDMI,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+struct platform_device s5p_device_hdmi = {
+       .name           = "s5p-hdmi",
+       .id             = -1,
+       .num_resources  = ARRAY_SIZE(s5p_hdmi_resources),
+       .resource       = s5p_hdmi_resources,
+};
+EXPORT_SYMBOL(s5p_device_hdmi);
+
+/* SDO interface */
+static struct resource s5p_sdo_resources[] = {
+       [0] = {
+               .start  = S5P_PA_SDO,
+               .end    = S5P_PA_SDO + SZ_64K - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = IRQ_SDO,
+               .end    = IRQ_SDO,
+               .flags  = IORESOURCE_IRQ,
+       }
+};
+
+struct platform_device s5p_device_sdo = {
+       .name           = "s5p-sdo",
+       .id             = -1,
+       .num_resources  = ARRAY_SIZE(s5p_sdo_resources),
+       .resource       = s5p_sdo_resources,
+};
+EXPORT_SYMBOL(s5p_device_sdo);
+
+/* MIXER */
+static struct resource s5p_mixer_resources[] = {
+       [0] = {
+               .start  = S5P_PA_MIXER,
+               .end    = S5P_PA_MIXER + SZ_64K - 1,
+               .flags  = IORESOURCE_MEM,
+               .name   = "mxr"
+       },
+       [1] = {
+               .start  = S5P_PA_VP,
+               .end    = S5P_PA_VP + SZ_64K - 1,
+               .flags  = IORESOURCE_MEM,
+               .name   = "vp"
+       },
+       [2] = {
+               .start  = IRQ_MIXER,
+               .end    = IRQ_MIXER,
+               .flags  = IORESOURCE_IRQ,
+               .name   = "irq"
+       }
+};
+
+static u64 s5p_tv_dmamask = DMA_BIT_MASK(32);
+
+struct platform_device s5p_device_mixer = {
+       .name           = "s5p-mixer",
+       .id             = -1,
+       .num_resources  = ARRAY_SIZE(s5p_mixer_resources),
+       .resource       = s5p_mixer_resources,
+       .dev            = {
+               .coherent_dma_mask = DMA_BIT_MASK(32),
+               .dma_mask = &s5p_tv_dmamask,
+       }
+};
+EXPORT_SYMBOL(s5p_device_mixer);
index 3e21b9444cc5f130b600ea4474dd0f82fb108e45..002ec9f28f18b0c3e09ecee791d3e6891d92d08d 100644 (file)
@@ -97,15 +97,24 @@ static inline unsigned long s5p_get_pll45xx(unsigned long baseclk, u32 pll_con,
        return (unsigned long)fvco;
 }
 
-#define PLL46XX_KDIV_MASK      (0xFFFF)
-#define PLL4650C_KDIV_MASK     (0xFFF)
+/* CON0 bit-fields */
 #define PLL46XX_MDIV_MASK      (0x1FF)
 #define PLL46XX_PDIV_MASK      (0x3F)
 #define PLL46XX_SDIV_MASK      (0x7)
+#define PLL46XX_LOCKED_SHIFT   (29)
 #define PLL46XX_MDIV_SHIFT     (16)
 #define PLL46XX_PDIV_SHIFT     (8)
 #define PLL46XX_SDIV_SHIFT     (0)
 
+/* CON1 bit-fields */
+#define PLL46XX_MRR_MASK       (0x1F)
+#define PLL46XX_MFR_MASK       (0x3F)
+#define PLL46XX_KDIV_MASK      (0xFFFF)
+#define PLL4650C_KDIV_MASK     (0xFFF)
+#define PLL46XX_MRR_SHIFT      (24)
+#define PLL46XX_MFR_SHIFT      (16)
+#define PLL46XX_KDIV_SHIFT     (0)
+
 enum pll46xx_type_t {
        pll_4600,
        pll_4650,
@@ -148,6 +157,7 @@ static inline unsigned long s5p_get_pll46xx(unsigned long baseclk,
 #define PLL90XX_PDIV_MASK      (0x3F)
 #define PLL90XX_SDIV_MASK      (0x7)
 #define PLL90XX_KDIV_MASK      (0xffff)
+#define PLL90XX_LOCKED_SHIFT   (29)
 #define PLL90XX_MDIV_SHIFT     (16)
 #define PLL90XX_PDIV_SHIFT     (8)
 #define PLL90XX_SDIV_SHIFT     (0)
index f88216d23991bd642e710aeacfc584d4ef4c4cd1..a566523d34ecfe1743f99d2b6df359844da4712e 100644 (file)
@@ -37,7 +37,7 @@ struct s5p_gpioint_bank {
        int                     start;
        int                     nr_groups;
        int                     irq;
-       struct s3c_gpio_chip    **chips;
+       struct samsung_gpio_chip        **chips;
        void                    (*handler)(unsigned int, struct irq_desc *);
 };
 
@@ -87,7 +87,7 @@ static void s5p_gpioint_handler(unsigned int irq, struct irq_desc *desc)
        chained_irq_enter(chip, desc);
 
        for (group = 0; group < bank->nr_groups; group++) {
-               struct s3c_gpio_chip *chip = bank->chips[group];
+               struct samsung_gpio_chip *chip = bank->chips[group];
                if (!chip)
                        continue;
 
@@ -110,7 +110,7 @@ static void s5p_gpioint_handler(unsigned int irq, struct irq_desc *desc)
        chained_irq_exit(chip, desc);
 }
 
-static __init int s5p_gpioint_add(struct s3c_gpio_chip *chip)
+static __init int s5p_gpioint_add(struct samsung_gpio_chip *chip)
 {
        static int used_gpioint_groups = 0;
        int group = chip->group;
@@ -131,7 +131,7 @@ static __init int s5p_gpioint_add(struct s3c_gpio_chip *chip)
                return -EINVAL;
 
        if (!bank->handler) {
-               bank->chips = kzalloc(sizeof(struct s3c_gpio_chip *) *
+               bank->chips = kzalloc(sizeof(struct samsung_gpio_chip *) *
                                      bank->nr_groups, GFP_KERNEL);
                if (!bank->chips)
                        return -ENOMEM;
@@ -174,7 +174,7 @@ static __init int s5p_gpioint_add(struct s3c_gpio_chip *chip)
 
 int __init s5p_register_gpio_interrupt(int pin)
 {
-       struct s3c_gpio_chip *my_chip = s3c_gpiolib_getchip(pin);
+       struct samsung_gpio_chip *my_chip = samsung_gpiolib_getchip(pin);
        int offset, group;
        int ret;
 
index b3e10659e4b80a81fe6e7dcf16703d728b1ea48a..74714c155e14623d33728d8a26f7ead7df6834ce 100644 (file)
@@ -79,39 +79,12 @@ config SAMSUNG_GPIOLIB_4BIT
          configuration. GPIOlib shall be compiled only for S3C64XX and S5P
          series of processors.
 
-config S3C_GPIO_CFG_S3C24XX
-       bool
-       help
-         Internal configuration to enable S3C24XX style GPIO configuration
-         functions.
-
 config S3C_GPIO_CFG_S3C64XX
        bool
        help
          Internal configuration to enable S3C64XX style GPIO configuration
          functions.
 
-config S3C_GPIO_PULL_UPDOWN
-       bool
-       help
-         Internal configuration to enable the correct GPIO pull helper
-
-config S3C_GPIO_PULL_S3C2443
-       bool
-       select S3C_GPIO_PULL_UPDOWN
-       help
-         Internal configuration to enable the correct GPIO pull helper for S3C2443-style GPIO
-
-config S3C_GPIO_PULL_DOWN
-       bool
-       help
-         Internal configuration to enable the correct GPIO pull helper
-
-config S3C_GPIO_PULL_UP
-       bool
-       help
-         Internal configuration to enable the correct GPIO pull helper
-
 config S5P_GPIO_DRVSTR
        bool
        help
@@ -300,11 +273,14 @@ config S3C_DMA
        help
          Internal configuration for S3C DMA core
 
-config S3C_PL330_DMA
+config SAMSUNG_DMADEV
        bool
-       select PL330
+       select DMADEVICES
+       select PL330_DMA if (CPU_EXYNOS4210 || CPU_S5PV210 || CPU_S5PC100 || \
+                                       CPU_S5P6450 || CPU_S5P6440)
+       select ARM_AMBA
        help
-         S3C DMA API Driver for PL330 DMAC.
+         Use DMA device engine for PL330 DMAC.
 
 comment "Power management"
 
index 3de756da5eaa7f582148370778c4bfe29ca7124f..5a5435482595a0e94479c50416bc511413c1f2d1 100644 (file)
@@ -15,8 +15,6 @@ obj-y                         += init.o cpu.o
 obj-$(CONFIG_ARCH_USES_GETTIMEOFFSET)   += time.o
 obj-y                          += clock.o
 obj-y                          += pwm-clock.o
-obj-y                          += gpio.o
-obj-y                          += gpio-config.o
 obj-y                          += dev-asocdma.o
 
 obj-$(CONFIG_SAMSUNG_CLKSRC)   += clock-clksrc.o
@@ -63,9 +61,9 @@ obj-$(CONFIG_SAMSUNG_DEV_BACKLIGHT)   += dev-backlight.o
 
 # DMA support
 
-obj-$(CONFIG_S3C_DMA)          += dma.o
+obj-$(CONFIG_S3C_DMA)          += dma.o s3c-dma-ops.o
 
-obj-$(CONFIG_S3C_PL330_DMA)    += s3c-pl330.o
+obj-$(CONFIG_SAMSUNG_DMADEV)   += dma-ops.o
 
 # PM support
 
diff --git a/arch/arm/plat-samsung/dma-ops.c b/arch/arm/plat-samsung/dma-ops.c
new file mode 100644 (file)
index 0000000..6e3d9ab
--- /dev/null
@@ -0,0 +1,131 @@
+/* linux/arch/arm/plat-samsung/dma-ops.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com
+ *
+ * Samsung DMA Operations
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/amba/pl330.h>
+#include <linux/scatterlist.h>
+
+#include <mach/dma.h>
+
+static inline bool pl330_filter(struct dma_chan *chan, void *param)
+{
+       struct dma_pl330_peri *peri = chan->private;
+       return peri->peri_id == (unsigned)param;
+}
+
+static unsigned samsung_dmadev_request(enum dma_ch dma_ch,
+                               struct samsung_dma_info *info)
+{
+       struct dma_chan *chan;
+       dma_cap_mask_t mask;
+       struct dma_slave_config slave_config;
+
+       dma_cap_zero(mask);
+       dma_cap_set(info->cap, mask);
+
+       chan = dma_request_channel(mask, pl330_filter, (void *)dma_ch);
+
+       if (info->direction == DMA_FROM_DEVICE) {
+               memset(&slave_config, 0, sizeof(struct dma_slave_config));
+               slave_config.direction = info->direction;
+               slave_config.src_addr = info->fifo;
+               slave_config.src_addr_width = info->width;
+               slave_config.src_maxburst = 1;
+               dmaengine_slave_config(chan, &slave_config);
+       } else if (info->direction == DMA_TO_DEVICE) {
+               memset(&slave_config, 0, sizeof(struct dma_slave_config));
+               slave_config.direction = info->direction;
+               slave_config.dst_addr = info->fifo;
+               slave_config.dst_addr_width = info->width;
+               slave_config.dst_maxburst = 1;
+               dmaengine_slave_config(chan, &slave_config);
+       }
+
+       return (unsigned)chan;
+}
+
+static int samsung_dmadev_release(unsigned ch,
+                       struct s3c2410_dma_client *client)
+{
+       dma_release_channel((struct dma_chan *)ch);
+
+       return 0;
+}
+
+static int samsung_dmadev_prepare(unsigned ch,
+                       struct samsung_dma_prep_info *info)
+{
+       struct scatterlist sg;
+       struct dma_chan *chan = (struct dma_chan *)ch;
+       struct dma_async_tx_descriptor *desc;
+
+       switch (info->cap) {
+       case DMA_SLAVE:
+               sg_init_table(&sg, 1);
+               sg_dma_len(&sg) = info->len;
+               sg_set_page(&sg, pfn_to_page(PFN_DOWN(info->buf)),
+                           info->len, offset_in_page(info->buf));
+               sg_dma_address(&sg) = info->buf;
+
+               desc = chan->device->device_prep_slave_sg(chan,
+                       &sg, 1, info->direction, DMA_PREP_INTERRUPT);
+               break;
+       case DMA_CYCLIC:
+               desc = chan->device->device_prep_dma_cyclic(chan,
+                       info->buf, info->len, info->period, info->direction);
+               break;
+       default:
+               dev_err(&chan->dev->device, "unsupported format\n");
+               return -EFAULT;
+       }
+
+       if (!desc) {
+               dev_err(&chan->dev->device, "cannot prepare cyclic dma\n");
+               return -EFAULT;
+       }
+
+       desc->callback = info->fp;
+       desc->callback_param = info->fp_param;
+
+       dmaengine_submit((struct dma_async_tx_descriptor *)desc);
+
+       return 0;
+}
+
+static inline int samsung_dmadev_trigger(unsigned ch)
+{
+       dma_async_issue_pending((struct dma_chan *)ch);
+
+       return 0;
+}
+
+static inline int samsung_dmadev_flush(unsigned ch)
+{
+       return dmaengine_terminate_all((struct dma_chan *)ch);
+}
+
+struct samsung_dma_ops dmadev_ops = {
+       .request        = samsung_dmadev_request,
+       .release        = samsung_dmadev_release,
+       .prepare        = samsung_dmadev_prepare,
+       .trigger        = samsung_dmadev_trigger,
+       .started        = NULL,
+       .flush          = samsung_dmadev_flush,
+       .stop           = samsung_dmadev_flush,
+};
+
+void *samsung_dmadev_get_ops(void)
+{
+       return &dmadev_ops;
+}
+EXPORT_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 (file)
index 1c0b040..0000000
+++ /dev/null
@@ -1,431 +0,0 @@
-/* linux/arch/arm/plat-s3c/gpio-config.c
- *
- * Copyright 2008 Openmoko, Inc.
- * Copyright 2008-2010 Simtec Electronics
- *     Ben Dooks <ben@simtec.co.uk>
- *     http://armlinux.simtec.co.uk/
- *
- * S3C series GPIO configuration core
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/gpio.h>
-#include <linux/io.h>
-
-#include <plat/gpio-core.h>
-#include <plat/gpio-cfg.h>
-#include <plat/gpio-cfg-helpers.h>
-
-int s3c_gpio_cfgpin(unsigned int pin, unsigned int config)
-{
-       struct s3c_gpio_chip *chip = s3c_gpiolib_getchip(pin);
-       unsigned long flags;
-       int offset;
-       int ret;
-
-       if (!chip)
-               return -EINVAL;
-
-       offset = pin - chip->chip.base;
-
-       s3c_gpio_lock(chip, flags);
-       ret = s3c_gpio_do_setcfg(chip, offset, config);
-       s3c_gpio_unlock(chip, flags);
-
-       return ret;
-}
-EXPORT_SYMBOL(s3c_gpio_cfgpin);
-
-int s3c_gpio_cfgpin_range(unsigned int start, unsigned int nr,
-                         unsigned int cfg)
-{
-       int ret;
-
-       for (; nr > 0; nr--, start++) {
-               ret = s3c_gpio_cfgpin(start, cfg);
-               if (ret != 0)
-                       return ret;
-       }
-
-       return 0;
-}
-EXPORT_SYMBOL_GPL(s3c_gpio_cfgpin_range);
-
-int s3c_gpio_cfgall_range(unsigned int start, unsigned int nr,
-                         unsigned int cfg, s3c_gpio_pull_t pull)
-{
-       int ret;
-
-       for (; nr > 0; nr--, start++) {
-               s3c_gpio_setpull(start, pull);
-               ret = s3c_gpio_cfgpin(start, cfg);
-               if (ret != 0)
-                       return ret;
-       }
-
-       return 0;
-}
-EXPORT_SYMBOL_GPL(s3c_gpio_cfgall_range);
-
-unsigned s3c_gpio_getcfg(unsigned int pin)
-{
-       struct s3c_gpio_chip *chip = s3c_gpiolib_getchip(pin);
-       unsigned long flags;
-       unsigned ret = 0;
-       int offset;
-
-       if (chip) {
-               offset = pin - chip->chip.base;
-
-               s3c_gpio_lock(chip, flags);
-               ret = s3c_gpio_do_getcfg(chip, offset);
-               s3c_gpio_unlock(chip, flags);
-       }
-
-       return ret;
-}
-EXPORT_SYMBOL(s3c_gpio_getcfg);
-
-
-int s3c_gpio_setpull(unsigned int pin, s3c_gpio_pull_t pull)
-{
-       struct s3c_gpio_chip *chip = s3c_gpiolib_getchip(pin);
-       unsigned long flags;
-       int offset, ret;
-
-       if (!chip)
-               return -EINVAL;
-
-       offset = pin - chip->chip.base;
-
-       s3c_gpio_lock(chip, flags);
-       ret = s3c_gpio_do_setpull(chip, offset, pull);
-       s3c_gpio_unlock(chip, flags);
-
-       return ret;
-}
-EXPORT_SYMBOL(s3c_gpio_setpull);
-
-s3c_gpio_pull_t s3c_gpio_getpull(unsigned int pin)
-{
-       struct s3c_gpio_chip *chip = s3c_gpiolib_getchip(pin);
-       unsigned long flags;
-       int offset;
-       u32 pup = 0;
-
-       if (chip) {
-               offset = pin - chip->chip.base;
-
-               s3c_gpio_lock(chip, flags);
-               pup = s3c_gpio_do_getpull(chip, offset);
-               s3c_gpio_unlock(chip, flags);
-       }
-
-       return (__force s3c_gpio_pull_t)pup;
-}
-EXPORT_SYMBOL(s3c_gpio_getpull);
-
-#ifdef CONFIG_S3C_GPIO_CFG_S3C24XX
-int s3c_gpio_setcfg_s3c24xx_a(struct s3c_gpio_chip *chip,
-                             unsigned int off, unsigned int cfg)
-{
-       void __iomem *reg = chip->base;
-       unsigned int shift = off;
-       u32 con;
-
-       if (s3c_gpio_is_cfg_special(cfg)) {
-               cfg &= 0xf;
-
-               /* Map output to 0, and SFN2 to 1 */
-               cfg -= 1;
-               if (cfg > 1)
-                       return -EINVAL;
-
-               cfg <<= shift;
-       }
-
-       con = __raw_readl(reg);
-       con &= ~(0x1 << shift);
-       con |= cfg;
-       __raw_writel(con, reg);
-
-       return 0;
-}
-
-unsigned s3c_gpio_getcfg_s3c24xx_a(struct s3c_gpio_chip *chip,
-                                  unsigned int off)
-{
-       u32 con;
-
-       con = __raw_readl(chip->base);
-       con >>= off;
-       con &= 1;
-       con++;
-
-       return S3C_GPIO_SFN(con);
-}
-
-int s3c_gpio_setcfg_s3c24xx(struct s3c_gpio_chip *chip,
-                           unsigned int off, unsigned int cfg)
-{
-       void __iomem *reg = chip->base;
-       unsigned int shift = off * 2;
-       u32 con;
-
-       if (s3c_gpio_is_cfg_special(cfg)) {
-               cfg &= 0xf;
-               if (cfg > 3)
-                       return -EINVAL;
-
-               cfg <<= shift;
-       }
-
-       con = __raw_readl(reg);
-       con &= ~(0x3 << shift);
-       con |= cfg;
-       __raw_writel(con, reg);
-
-       return 0;
-}
-
-unsigned int s3c_gpio_getcfg_s3c24xx(struct s3c_gpio_chip *chip,
-                                    unsigned int off)
-{
-       u32 con;
-
-       con = __raw_readl(chip->base);
-       con >>= off * 2;
-       con &= 3;
-
-       /* this conversion works for IN and OUT as well as special mode */
-       return S3C_GPIO_SPECIAL(con);
-}
-#endif
-
-#ifdef CONFIG_S3C_GPIO_CFG_S3C64XX
-int s3c_gpio_setcfg_s3c64xx_4bit(struct s3c_gpio_chip *chip,
-                                unsigned int off, unsigned int cfg)
-{
-       void __iomem *reg = chip->base;
-       unsigned int shift = (off & 7) * 4;
-       u32 con;
-
-       if (off < 8 && chip->chip.ngpio > 8)
-               reg -= 4;
-
-       if (s3c_gpio_is_cfg_special(cfg)) {
-               cfg &= 0xf;
-               cfg <<= shift;
-       }
-
-       con = __raw_readl(reg);
-       con &= ~(0xf << shift);
-       con |= cfg;
-       __raw_writel(con, reg);
-
-       return 0;
-}
-
-unsigned s3c_gpio_getcfg_s3c64xx_4bit(struct s3c_gpio_chip *chip,
-                                     unsigned int off)
-{
-       void __iomem *reg = chip->base;
-       unsigned int shift = (off & 7) * 4;
-       u32 con;
-
-       if (off < 8 && chip->chip.ngpio > 8)
-               reg -= 4;
-
-       con = __raw_readl(reg);
-       con >>= shift;
-       con &= 0xf;
-
-       /* this conversion works for IN and OUT as well as special mode */
-       return S3C_GPIO_SPECIAL(con);
-}
-
-#endif /* CONFIG_S3C_GPIO_CFG_S3C64XX */
-
-#ifdef CONFIG_S3C_GPIO_PULL_UPDOWN
-int s3c_gpio_setpull_updown(struct s3c_gpio_chip *chip,
-                           unsigned int off, s3c_gpio_pull_t pull)
-{
-       void __iomem *reg = chip->base + 0x08;
-       int shift = off * 2;
-       u32 pup;
-
-       pup = __raw_readl(reg);
-       pup &= ~(3 << shift);
-       pup |= pull << shift;
-       __raw_writel(pup, reg);
-
-       return 0;
-}
-
-s3c_gpio_pull_t s3c_gpio_getpull_updown(struct s3c_gpio_chip *chip,
-                                       unsigned int off)
-{
-       void __iomem *reg = chip->base + 0x08;
-       int shift = off * 2;
-       u32 pup = __raw_readl(reg);
-
-       pup >>= shift;
-       pup &= 0x3;
-       return (__force s3c_gpio_pull_t)pup;
-}
-
-#ifdef CONFIG_S3C_GPIO_PULL_S3C2443
-int s3c_gpio_setpull_s3c2443(struct s3c_gpio_chip *chip,
-                               unsigned int off, s3c_gpio_pull_t pull)
-{
-       switch (pull) {
-       case S3C_GPIO_PULL_NONE:
-               pull = 0x01;
-               break;
-       case S3C_GPIO_PULL_UP:
-               pull = 0x00;
-               break;
-       case S3C_GPIO_PULL_DOWN:
-               pull = 0x02;
-               break;
-       }
-       return s3c_gpio_setpull_updown(chip, off, pull);
-}
-
-s3c_gpio_pull_t s3c_gpio_getpull_s3c2443(struct s3c_gpio_chip *chip,
-                                       unsigned int off)
-{
-       s3c_gpio_pull_t pull;
-
-       pull = s3c_gpio_getpull_updown(chip, off);
-
-       switch (pull) {
-       case 0x00:
-               pull = S3C_GPIO_PULL_UP;
-               break;
-       case 0x01:
-       case 0x03:
-               pull = S3C_GPIO_PULL_NONE;
-               break;
-       case 0x02:
-               pull = S3C_GPIO_PULL_DOWN;
-               break;
-       }
-
-       return pull;
-}
-#endif
-#endif
-
-#if defined(CONFIG_S3C_GPIO_PULL_UP) || defined(CONFIG_S3C_GPIO_PULL_DOWN)
-static int s3c_gpio_setpull_1(struct s3c_gpio_chip *chip,
-                        unsigned int off, s3c_gpio_pull_t pull,
-                        s3c_gpio_pull_t updown)
-{
-       void __iomem *reg = chip->base + 0x08;
-       u32 pup = __raw_readl(reg);
-
-       if (pull == updown)
-               pup &= ~(1 << off);
-       else if (pull == S3C_GPIO_PULL_NONE)
-               pup |= (1 << off);
-       else
-               return -EINVAL;
-
-       __raw_writel(pup, reg);
-       return 0;
-}
-
-static s3c_gpio_pull_t s3c_gpio_getpull_1(struct s3c_gpio_chip *chip,
-                                    unsigned int off, s3c_gpio_pull_t updown)
-{
-       void __iomem *reg = chip->base + 0x08;
-       u32 pup = __raw_readl(reg);
-
-       pup &= (1 << off);
-       return pup ? S3C_GPIO_PULL_NONE : updown;
-}
-#endif /* CONFIG_S3C_GPIO_PULL_UP || CONFIG_S3C_GPIO_PULL_DOWN */
-
-#ifdef CONFIG_S3C_GPIO_PULL_UP
-s3c_gpio_pull_t s3c_gpio_getpull_1up(struct s3c_gpio_chip *chip,
-                                    unsigned int off)
-{
-       return s3c_gpio_getpull_1(chip, off, S3C_GPIO_PULL_UP);
-}
-
-int s3c_gpio_setpull_1up(struct s3c_gpio_chip *chip,
-                        unsigned int off, s3c_gpio_pull_t pull)
-{
-       return s3c_gpio_setpull_1(chip, off, pull, S3C_GPIO_PULL_UP);
-}
-#endif /* CONFIG_S3C_GPIO_PULL_UP */
-
-#ifdef CONFIG_S3C_GPIO_PULL_DOWN
-s3c_gpio_pull_t s3c_gpio_getpull_1down(struct s3c_gpio_chip *chip,
-                                    unsigned int off)
-{
-       return s3c_gpio_getpull_1(chip, off, S3C_GPIO_PULL_DOWN);
-}
-
-int s3c_gpio_setpull_1down(struct s3c_gpio_chip *chip,
-                        unsigned int off, s3c_gpio_pull_t pull)
-{
-       return s3c_gpio_setpull_1(chip, off, pull, S3C_GPIO_PULL_DOWN);
-}
-#endif /* CONFIG_S3C_GPIO_PULL_DOWN */
-
-#ifdef CONFIG_S5P_GPIO_DRVSTR
-s5p_gpio_drvstr_t s5p_gpio_get_drvstr(unsigned int pin)
-{
-       struct s3c_gpio_chip *chip = s3c_gpiolib_getchip(pin);
-       unsigned int off;
-       void __iomem *reg;
-       int shift;
-       u32 drvstr;
-
-       if (!chip)
-               return -EINVAL;
-
-       off = pin - chip->chip.base;
-       shift = off * 2;
-       reg = chip->base + 0x0C;
-
-       drvstr = __raw_readl(reg);
-       drvstr = drvstr >> shift;
-       drvstr &= 0x3;
-
-       return (__force s5p_gpio_drvstr_t)drvstr;
-}
-EXPORT_SYMBOL(s5p_gpio_get_drvstr);
-
-int s5p_gpio_set_drvstr(unsigned int pin, s5p_gpio_drvstr_t drvstr)
-{
-       struct s3c_gpio_chip *chip = s3c_gpiolib_getchip(pin);
-       unsigned int off;
-       void __iomem *reg;
-       int shift;
-       u32 tmp;
-
-       if (!chip)
-               return -EINVAL;
-
-       off = pin - chip->chip.base;
-       shift = off * 2;
-       reg = chip->base + 0x0C;
-
-       tmp = __raw_readl(reg);
-       tmp &= ~(0x3 << shift);
-       tmp |= drvstr << shift;
-
-       __raw_writel(tmp, reg);
-
-       return 0;
-}
-EXPORT_SYMBOL(s5p_gpio_set_drvstr);
-#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 (file)
index 7743c4b..0000000
+++ /dev/null
@@ -1,167 +0,0 @@
-/* linux/arch/arm/plat-s3c/gpio.c
- *
- * Copyright 2008 Simtec Electronics
- *     Ben Dooks <ben@simtec.co.uk>
- *     http://armlinux.simtec.co.uk/
- *
- * S3C series GPIO core
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/io.h>
-#include <linux/gpio.h>
-#include <linux/spinlock.h>
-
-#include <plat/gpio-core.h>
-
-#ifdef CONFIG_S3C_GPIO_TRACK
-struct s3c_gpio_chip *s3c_gpios[S3C_GPIO_END];
-
-static __init void s3c_gpiolib_track(struct s3c_gpio_chip *chip)
-{
-       unsigned int gpn;
-       int i;
-
-       gpn = chip->chip.base;
-       for (i = 0; i < chip->chip.ngpio; i++, gpn++) {
-               BUG_ON(gpn >= ARRAY_SIZE(s3c_gpios));
-               s3c_gpios[gpn] = chip;
-       }
-}
-#endif /* CONFIG_S3C_GPIO_TRACK */
-
-/* Default routines for controlling GPIO, based on the original S3C24XX
- * GPIO functions which deal with the case where each gpio bank of the
- * chip is as following:
- *
- * base + 0x00: Control register, 2 bits per gpio
- *             gpio n: 2 bits starting at (2*n)
- *             00 = input, 01 = output, others mean special-function
- * base + 0x04: Data register, 1 bit per gpio
- *             bit n: data bit n
-*/
-
-static int s3c_gpiolib_input(struct gpio_chip *chip, unsigned offset)
-{
-       struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
-       void __iomem *base = ourchip->base;
-       unsigned long flags;
-       unsigned long con;
-
-       s3c_gpio_lock(ourchip, flags);
-
-       con = __raw_readl(base + 0x00);
-       con &= ~(3 << (offset * 2));
-
-       __raw_writel(con, base + 0x00);
-
-       s3c_gpio_unlock(ourchip, flags);
-       return 0;
-}
-
-static int s3c_gpiolib_output(struct gpio_chip *chip,
-                             unsigned offset, int value)
-{
-       struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
-       void __iomem *base = ourchip->base;
-       unsigned long flags;
-       unsigned long dat;
-       unsigned long con;
-
-       s3c_gpio_lock(ourchip, flags);
-
-       dat = __raw_readl(base + 0x04);
-       dat &= ~(1 << offset);
-       if (value)
-               dat |= 1 << offset;
-       __raw_writel(dat, base + 0x04);
-
-       con = __raw_readl(base + 0x00);
-       con &= ~(3 << (offset * 2));
-       con |= 1 << (offset * 2);
-
-       __raw_writel(con, base + 0x00);
-       __raw_writel(dat, base + 0x04);
-
-       s3c_gpio_unlock(ourchip, flags);
-       return 0;
-}
-
-static void s3c_gpiolib_set(struct gpio_chip *chip,
-                           unsigned offset, int value)
-{
-       struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
-       void __iomem *base = ourchip->base;
-       unsigned long flags;
-       unsigned long dat;
-
-       s3c_gpio_lock(ourchip, flags);
-
-       dat = __raw_readl(base + 0x04);
-       dat &= ~(1 << offset);
-       if (value)
-               dat |= 1 << offset;
-       __raw_writel(dat, base + 0x04);
-
-       s3c_gpio_unlock(ourchip, flags);
-}
-
-static int s3c_gpiolib_get(struct gpio_chip *chip, unsigned offset)
-{
-       struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
-       unsigned long val;
-
-       val = __raw_readl(ourchip->base + 0x04);
-       val >>= offset;
-       val &= 1;
-
-       return val;
-}
-
-__init void s3c_gpiolib_add(struct s3c_gpio_chip *chip)
-{
-       struct gpio_chip *gc = &chip->chip;
-       int ret;
-
-       BUG_ON(!chip->base);
-       BUG_ON(!gc->label);
-       BUG_ON(!gc->ngpio);
-
-       spin_lock_init(&chip->lock);
-
-       if (!gc->direction_input)
-               gc->direction_input = s3c_gpiolib_input;
-       if (!gc->direction_output)
-               gc->direction_output = s3c_gpiolib_output;
-       if (!gc->set)
-               gc->set = s3c_gpiolib_set;
-       if (!gc->get)
-               gc->get = s3c_gpiolib_get;
-
-#ifdef CONFIG_PM
-       if (chip->pm != NULL) {
-               if (!chip->pm->save || !chip->pm->resume)
-                       printk(KERN_ERR "gpio: %s has missing PM functions\n",
-                              gc->label);
-       } else
-               printk(KERN_ERR "gpio: %s has no PM function\n", gc->label);
-#endif
-
-       /* gpiochip_add() prints own failure message on error. */
-       ret = gpiochip_add(gc);
-       if (ret >= 0)
-               s3c_gpiolib_track(chip);
-}
-
-int samsung_gpiolib_to_irq(struct gpio_chip *chip, unsigned int offset)
-{
-       struct s3c_gpio_chip *s3c_chip = container_of(chip,
-                       struct s3c_gpio_chip, chip);
-
-       return s3c_chip->irq_base + offset;
-}
index 24ebb1e1de413c4b1a5b47cdf3347c4275574558..ee5014a7cc962e4d16794e15bab6baca02cd7119 100644 (file)
@@ -62,6 +62,7 @@ extern struct platform_device s3c_device_i2c4;
 extern struct platform_device s3c_device_i2c5;
 extern struct platform_device s3c_device_i2c6;
 extern struct platform_device s3c_device_i2c7;
+extern struct platform_device s5p_device_i2c_hdmiphy;
 extern struct platform_device s3c_device_rtc;
 extern struct platform_device s3c_device_adc;
 extern struct platform_device s3c_device_sdi;
@@ -142,6 +143,11 @@ extern struct platform_device s5p_device_fimc3;
 extern struct platform_device s5p_device_mfc;
 extern struct platform_device s5p_device_mfc_l;
 extern struct platform_device s5p_device_mfc_r;
+
+extern struct platform_device s5p_device_hdmi;
+extern struct platform_device s5p_device_mixer;
+extern struct platform_device s5p_device_sdo;
+
 extern struct platform_device s5p_device_mipi_csis0;
 extern struct platform_device s5p_device_mipi_csis1;
 
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 (file)
index 0000000..4c1a363
--- /dev/null
@@ -0,0 +1,63 @@
+/* arch/arm/plat-samsung/include/plat/dma-ops.h
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com
+ *
+ * Samsung DMA support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __SAMSUNG_DMA_OPS_H_
+#define __SAMSUNG_DMA_OPS_H_ __FILE__
+
+#include <linux/dmaengine.h>
+
+struct samsung_dma_prep_info {
+       enum dma_transaction_type cap;
+       enum dma_data_direction direction;
+       dma_addr_t buf;
+       unsigned long period;
+       unsigned long len;
+       void (*fp)(void *data);
+       void *fp_param;
+};
+
+struct samsung_dma_info {
+       enum dma_transaction_type cap;
+       enum dma_data_direction direction;
+       enum dma_slave_buswidth width;
+       dma_addr_t fifo;
+       struct s3c2410_dma_client *client;
+};
+
+struct samsung_dma_ops {
+       unsigned (*request)(enum dma_ch ch, struct samsung_dma_info *info);
+       int (*release)(unsigned ch, struct s3c2410_dma_client *client);
+       int (*prepare)(unsigned ch, struct samsung_dma_prep_info *info);
+       int (*trigger)(unsigned ch);
+       int (*started)(unsigned ch);
+       int (*flush)(unsigned ch);
+       int (*stop)(unsigned ch);
+};
+
+extern void *samsung_dmadev_get_ops(void);
+extern void *s3c_dma_get_ops(void);
+
+static inline void *__samsung_dma_get_ops(void)
+{
+       if (samsung_dma_is_dmadev())
+               return samsung_dmadev_get_ops();
+       else
+               return s3c_dma_get_ops();
+}
+
+/*
+ * samsung_dma_get_ops
+ * get the set of samsung dma operations
+ */
+#define samsung_dma_get_ops() __samsung_dma_get_ops()
+
+#endif /* __SAMSUNG_DMA_OPS_H_ */
diff --git a/arch/arm/plat-samsung/include/plat/dma-pl330.h b/arch/arm/plat-samsung/include/plat/dma-pl330.h
new file mode 100644 (file)
index 0000000..2e55e59
--- /dev/null
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2010 Samsung Electronics Co. Ltd.
+ *     Jaswinder Singh <jassi.brar@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __DMA_PL330_H_
+#define __DMA_PL330_H_ __FILE__
+
+/*
+ * PL330 can assign any channel to communicate with
+ * any of the peripherals attched to the DMAC.
+ * For the sake of consistency across client drivers,
+ * We keep the channel names unchanged and only add
+ * missing peripherals are added.
+ * Order is not important since DMA PL330 API driver
+ * use these just as IDs.
+ */
+enum dma_ch {
+       DMACH_UART0_RX,
+       DMACH_UART0_TX,
+       DMACH_UART1_RX,
+       DMACH_UART1_TX,
+       DMACH_UART2_RX,
+       DMACH_UART2_TX,
+       DMACH_UART3_RX,
+       DMACH_UART3_TX,
+       DMACH_UART4_RX,
+       DMACH_UART4_TX,
+       DMACH_UART5_RX,
+       DMACH_UART5_TX,
+       DMACH_USI_RX,
+       DMACH_USI_TX,
+       DMACH_IRDA,
+       DMACH_I2S0_RX,
+       DMACH_I2S0_TX,
+       DMACH_I2S0S_TX,
+       DMACH_I2S1_RX,
+       DMACH_I2S1_TX,
+       DMACH_I2S2_RX,
+       DMACH_I2S2_TX,
+       DMACH_SPI0_RX,
+       DMACH_SPI0_TX,
+       DMACH_SPI1_RX,
+       DMACH_SPI1_TX,
+       DMACH_SPI2_RX,
+       DMACH_SPI2_TX,
+       DMACH_AC97_MICIN,
+       DMACH_AC97_PCMIN,
+       DMACH_AC97_PCMOUT,
+       DMACH_EXTERNAL,
+       DMACH_PWM,
+       DMACH_SPDIF,
+       DMACH_HSI_RX,
+       DMACH_HSI_TX,
+       DMACH_PCM0_TX,
+       DMACH_PCM0_RX,
+       DMACH_PCM1_TX,
+       DMACH_PCM1_RX,
+       DMACH_PCM2_TX,
+       DMACH_PCM2_RX,
+       DMACH_MSM_REQ3,
+       DMACH_MSM_REQ2,
+       DMACH_MSM_REQ1,
+       DMACH_MSM_REQ0,
+       DMACH_SLIMBUS0_RX,
+       DMACH_SLIMBUS0_TX,
+       DMACH_SLIMBUS0AUX_RX,
+       DMACH_SLIMBUS0AUX_TX,
+       DMACH_SLIMBUS1_RX,
+       DMACH_SLIMBUS1_TX,
+       DMACH_SLIMBUS2_RX,
+       DMACH_SLIMBUS2_TX,
+       DMACH_SLIMBUS3_RX,
+       DMACH_SLIMBUS3_TX,
+       DMACH_SLIMBUS4_RX,
+       DMACH_SLIMBUS4_TX,
+       DMACH_SLIMBUS5_RX,
+       DMACH_SLIMBUS5_TX,
+       /* END Marker, also used to denote a reserved channel */
+       DMACH_MAX,
+};
+
+struct s3c2410_dma_client {
+       char    *name;
+};
+
+static inline bool samsung_dma_has_circular(void)
+{
+       return true;
+}
+
+static inline bool samsung_dma_is_dmadev(void)
+{
+       return true;
+}
+
+#include <plat/dma-ops.h>
+
+#endif /* __DMA_PL330_H_ */
index ab9bce637cbdfeb8de93e10014cd0f57b722b2ba..1c1ed5481253bd6c5c1d1cea89e5622c402485b7 100644 (file)
@@ -41,7 +41,7 @@ struct s3c24xx_dma_selection {
 
        void    (*direction)(struct s3c2410_dma_chan *chan,
                             struct s3c24xx_dma_map *map,
-                            enum s3c2410_dmasrc dir);
+                            enum dma_data_direction dir);
 };
 
 extern int s3c24xx_dma_init_map(struct s3c24xx_dma_selection *sel);
index 8c273b7a6f56593015ccec86869670bedc1b5a3d..b9061128abdef3bcf76a2e9cdd4bab76732b4fd5 100644 (file)
  * published by the Free Software Foundation.
 */
 
+#include <linux/dma-mapping.h>
+
 enum s3c2410_dma_buffresult {
        S3C2410_RES_OK,
        S3C2410_RES_ERR,
        S3C2410_RES_ABORT
 };
 
-enum s3c2410_dmasrc {
-       S3C2410_DMASRC_HW,              /* source is memory */
-       S3C2410_DMASRC_MEM              /* source is hardware */
-};
-
 /* enum s3c2410_chan_op
  *
  * 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);
 */
 
 extern int s3c2410_dma_devconfig(enum dma_ch channel,
-               enum s3c2410_dmasrc source, unsigned long devaddr);
+               enum dma_data_direction source, unsigned long devaddr);
 
 /* s3c2410_dma_getposition
  *
@@ -126,3 +123,4 @@ extern int s3c2410_dma_set_opfn(enum dma_ch, s3c2410_dma_opfn_t rtn);
 extern int s3c2410_dma_set_buffdone_fn(enum dma_ch, s3c2410_dma_cbfn_t rtn);
 
 
+#include <plat/dma-ops.h>
index 01f10e4d00c71e5f799140bffbeaba650b212592..0fedf47fa502482a117dc9427d5067d11d8e3a3d 100644 (file)
@@ -109,4 +109,11 @@ extern void s5pv210_fb_gpio_setup_24bpp(void);
  */
 extern void exynos4_fimd0_gpio_setup_24bpp(void);
 
+/**
+ * s5p64x0_fb_gpio_setup_24bpp() - S5P6440/S5P6450 setup function for 24bpp LCD
+ *
+ * Initialise the GPIO for an 24bpp LCD display on the RGB interface.
+ */
+extern void s5p64x0_fb_gpio_setup_24bpp(void);
+
 #endif /* __PLAT_S3C_FB_H */
index 9a4e53d5296747b35411b85ae8f5ae572fb4ea9a..a181d7ce81cff4f1bb560d919da8da31141864f3 100644 (file)
@@ -1,11 +1,11 @@
-/* linux/arch/arm/plat-s3c/include/plat/gpio-cfg-helper.h
+/* linux/arch/arm/plat-samsung/include/plat/gpio-cfg-helper.h
  *
  * Copyright 2008 Openmoko, Inc.
  * Copyright 2008 Simtec Electronics
  *     http://armlinux.simtec.co.uk/
  *     Ben Dooks <ben@simtec.co.uk>
  *
- * S3C Platform - GPIO pin configuration helper definitions
+ * Samsung Platform - GPIO pin configuration helper definitions
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  * by disabling interrupts.
 */
 
-static inline int s3c_gpio_do_setcfg(struct s3c_gpio_chip *chip,
-                                    unsigned int off, unsigned int config)
+static inline int samsung_gpio_do_setcfg(struct samsung_gpio_chip *chip,
+                                        unsigned int off, unsigned int config)
 {
        return (chip->config->set_config)(chip, off, config);
 }
 
-static inline unsigned s3c_gpio_do_getcfg(struct s3c_gpio_chip *chip,
-                                         unsigned int off)
+static inline unsigned samsung_gpio_do_getcfg(struct samsung_gpio_chip *chip,
+                                             unsigned int off)
 {
        return (chip->config->get_config)(chip, off);
 }
 
-static inline int s3c_gpio_do_setpull(struct s3c_gpio_chip *chip,
-                                     unsigned int off, s3c_gpio_pull_t pull)
+static inline int samsung_gpio_do_setpull(struct samsung_gpio_chip *chip,
+                                         unsigned int off, samsung_gpio_pull_t pull)
 {
        return (chip->config->set_pull)(chip, off, pull);
 }
 
-static inline s3c_gpio_pull_t s3c_gpio_do_getpull(struct s3c_gpio_chip *chip,
-                                                 unsigned int off)
+static inline samsung_gpio_pull_t samsung_gpio_do_getpull(struct samsung_gpio_chip *chip,
+                                                         unsigned int off)
 {
        return chip->config->get_pull(chip, off);
 }
 
-/**
- * s3c_gpio_setcfg_s3c24xx - S3C24XX style GPIO configuration.
- * @chip: The gpio chip that is being configured.
- * @off: The offset for the GPIO being configured.
- * @cfg: The configuration value to set.
- *
- * This helper deal with the GPIO cases where the control register
- * has two bits of configuration per gpio, which have the following
- * functions:
- *     00 = input
- *     01 = output
- *     1x = special function
-*/
-extern int s3c_gpio_setcfg_s3c24xx(struct s3c_gpio_chip *chip,
-                                  unsigned int off, unsigned int cfg);
-
-/**
- * s3c_gpio_getcfg_s3c24xx - S3C24XX style GPIO configuration read.
- * @chip: The gpio chip that is being configured.
- * @off: The offset for the GPIO being configured.
- *
- * The reverse of s3c_gpio_setcfg_s3c24xx(). Will return a value whicg
- * could be directly passed back to s3c_gpio_setcfg_s3c24xx(), from the
- * S3C_GPIO_SPECIAL() macro.
- */
-unsigned int s3c_gpio_getcfg_s3c24xx(struct s3c_gpio_chip *chip,
-                                    unsigned int off);
-
-/**
- * s3c_gpio_setcfg_s3c24xx_a - S3C24XX style GPIO configuration (Bank A)
- * @chip: The gpio chip that is being configured.
- * @off: The offset for the GPIO being configured.
- * @cfg: The configuration value to set.
- *
- * This helper deal with the GPIO cases where the control register
- * has one bit of configuration for the gpio, where setting the bit
- * means the pin is in special function mode and unset means output.
-*/
-extern int s3c_gpio_setcfg_s3c24xx_a(struct s3c_gpio_chip *chip,
-                                    unsigned int off, unsigned int cfg);
-
-
-/**
- * s3c_gpio_getcfg_s3c24xx_a - S3C24XX style GPIO configuration read (Bank A)
- * @chip: The gpio chip that is being configured.
- * @off: The offset for the GPIO being configured.
- *
- * The reverse of s3c_gpio_setcfg_s3c24xx_a() turning an GPIO into a usable
- * GPIO configuration value.
- *
- * @sa s3c_gpio_getcfg_s3c24xx
- * @sa s3c_gpio_getcfg_s3c64xx_4bit
- */
-extern unsigned s3c_gpio_getcfg_s3c24xx_a(struct s3c_gpio_chip *chip,
-                                         unsigned int off);
-
-/**
- * s3c_gpio_setcfg_s3c64xx_4bit - S3C64XX 4bit single register GPIO config.
- * @chip: The gpio chip that is being configured.
- * @off: The offset for the GPIO being configured.
- * @cfg: The configuration value to set.
- *
- * This helper deal with the GPIO cases where the control register has 4 bits
- * of control per GPIO, generally in the form of:
- *     0000 = Input
- *     0001 = Output
- *     others = Special functions (dependent on bank)
- *
- * Note, since the code to deal with the case where there are two control
- * registers instead of one, we do not have a separate set of functions for
- * each case.
-*/
-extern int s3c_gpio_setcfg_s3c64xx_4bit(struct s3c_gpio_chip *chip,
-                                       unsigned int off, unsigned int cfg);
-
-
-/**
- * s3c_gpio_getcfg_s3c64xx_4bit - S3C64XX 4bit single register GPIO config read.
- * @chip: The gpio chip that is being configured.
- * @off: The offset for the GPIO being configured.
- *
- * The reverse of s3c_gpio_setcfg_s3c64xx_4bit(), turning a gpio configuration
- * register setting into a value the software can use, such as could be passed
- * to s3c_gpio_setcfg_s3c64xx_4bit().
- *
- * @sa s3c_gpio_getcfg_s3c24xx
- */
-extern unsigned s3c_gpio_getcfg_s3c64xx_4bit(struct s3c_gpio_chip *chip,
-                                            unsigned int off);
-
 /* Pull-{up,down} resistor controls.
  *
  * S3C2410,S3C2440 = Pull-UP,
@@ -147,7 +57,7 @@ extern unsigned s3c_gpio_getcfg_s3c64xx_4bit(struct s3c_gpio_chip *chip,
  */
 
 /**
- * s3c_gpio_setpull_1up() - Pull configuration for choice of up or none.
+ * s3c24xx_gpio_setpull_1up() - Pull configuration for choice of up or none.
  * @chip: The gpio chip that is being configured.
  * @off: The offset for the GPIO being configured.
  * @param: pull: The pull mode being requested.
@@ -155,11 +65,11 @@ extern unsigned s3c_gpio_getcfg_s3c64xx_4bit(struct s3c_gpio_chip *chip,
  * This is a helper function for the case where we have GPIOs with one
  * bit configuring the presence of a pull-up resistor.
  */
-extern int s3c_gpio_setpull_1up(struct s3c_gpio_chip *chip,
-                               unsigned int off, s3c_gpio_pull_t pull);
+extern int s3c24xx_gpio_setpull_1up(struct samsung_gpio_chip *chip,
+                                   unsigned int off, samsung_gpio_pull_t pull);
 
 /**
- * s3c_gpio_setpull_1down() - Pull configuration for choice of down or none
+ * s3c24xx_gpio_setpull_1down() - Pull configuration for choice of down or none
  * @chip: The gpio chip that is being configured
  * @off: The offset for the GPIO being configured
  * @param: pull: The pull mode being requested
@@ -167,11 +77,13 @@ extern int s3c_gpio_setpull_1up(struct s3c_gpio_chip *chip,
  * This is a helper function for the case where we have GPIOs with one
  * bit configuring the presence of a pull-down resistor.
  */
-extern int s3c_gpio_setpull_1down(struct s3c_gpio_chip *chip,
-                                 unsigned int off, s3c_gpio_pull_t pull);
+extern int s3c24xx_gpio_setpull_1down(struct samsung_gpio_chip *chip,
+                                     unsigned int off, samsung_gpio_pull_t pull);
 
 /**
- * s3c_gpio_setpull_upown() - Pull configuration for choice of up, down or none
+ * samsung_gpio_setpull_upown() - Pull configuration for choice of up,
+ * down or none
+ *
  * @chip: The gpio chip that is being configured.
  * @off: The offset for the GPIO being configured.
  * @param: pull: The pull mode being requested.
@@ -183,45 +95,46 @@ extern int s3c_gpio_setpull_1down(struct s3c_gpio_chip *chip,
  *     01 = Pull-up resistor connected
  *     10 = Pull-down resistor connected
  */
-extern int s3c_gpio_setpull_updown(struct s3c_gpio_chip *chip,
-                                  unsigned int off, s3c_gpio_pull_t pull);
-
+extern int samsung_gpio_setpull_updown(struct samsung_gpio_chip *chip,
+                                      unsigned int off, samsung_gpio_pull_t pull);
 
 /**
- * s3c_gpio_getpull_updown() - Get configuration for choice of up, down or none
+ * samsung_gpio_getpull_updown() - Get configuration for choice of up,
+ * down or none
+ *
  * @chip: The gpio chip that the GPIO pin belongs to
  * @off: The offset to the pin to get the configuration of.
  *
- * This helper function reads the state of the pull-{up,down} resistor for the
- * given GPIO in the same case as s3c_gpio_setpull_upown.
+ * This helper function reads the state of the pull-{up,down} resistor
+ * for the given GPIO in the same case as samsung_gpio_setpull_upown.
 */
-extern s3c_gpio_pull_t s3c_gpio_getpull_updown(struct s3c_gpio_chip *chip,
-                                              unsigned int off);
+extern samsung_gpio_pull_t samsung_gpio_getpull_updown(struct samsung_gpio_chip *chip,
+                                                      unsigned int off);
 
 /**
- * s3c_gpio_getpull_1up() - Get configuration for choice of up or none
+ * s3c24xx_gpio_getpull_1up() - Get configuration for choice of up or none
  * @chip: The gpio chip that the GPIO pin belongs to
  * @off: The offset to the pin to get the configuration of.
  *
  * This helper function reads the state of the pull-up resistor for the
- * given GPIO in the same case as s3c_gpio_setpull_1up.
+ * given GPIO in the same case as s3c24xx_gpio_setpull_1up.
 */
-extern s3c_gpio_pull_t s3c_gpio_getpull_1up(struct s3c_gpio_chip *chip,
-                                           unsigned int off);
+extern samsung_gpio_pull_t s3c24xx_gpio_getpull_1up(struct samsung_gpio_chip *chip,
+                                                   unsigned int off);
 
 /**
- * s3c_gpio_getpull_1down() - Get configuration for choice of down or none
+ * s3c24xx_gpio_getpull_1down() - Get configuration for choice of down or none
  * @chip: The gpio chip that the GPIO pin belongs to
  * @off: The offset to the pin to get the configuration of.
  *
  * This helper function reads the state of the pull-down resistor for the
- * given GPIO in the same case as s3c_gpio_setpull_1down.
+ * given GPIO in the same case as s3c24xx_gpio_setpull_1down.
 */
-extern s3c_gpio_pull_t s3c_gpio_getpull_1down(struct s3c_gpio_chip *chip,
-                                           unsigned int off);
+extern samsung_gpio_pull_t s3c24xx_gpio_getpull_1down(struct samsung_gpio_chip *chip,
+                                                     unsigned int off);
 
 /**
- * s3c_gpio_setpull_s3c2443() - Pull configuration for s3c2443.
+ * s3c2443_gpio_setpull() - Pull configuration for s3c2443.
  * @chip: The gpio chip that is being configured.
  * @off: The offset for the GPIO being configured.
  * @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,
  *     10 = Pull-down resistor connected
  *     x1 = No pull up resistor
  */
-extern int s3c_gpio_setpull_s3c2443(struct s3c_gpio_chip *chip,
-                                   unsigned int off, s3c_gpio_pull_t pull);
+extern int s3c2443_gpio_setpull(struct samsung_gpio_chip *chip,
+                               unsigned int off, samsung_gpio_pull_t pull);
 
 /**
- * s3c_gpio_getpull_s3c2443() - Get configuration for s3c2443 pull resistors
+ * s3c2443_gpio_getpull() - Get configuration for s3c2443 pull resistors
  * @chip: The gpio chip that the GPIO pin belongs to.
  * @off: The offset to the pin to get the configuration of.
  *
  * This helper function reads the state of the pull-{up,down} resistor for the
- * given GPIO in the same case as s3c_gpio_setpull_upown.
+ * given GPIO in the same case as samsung_gpio_setpull_upown.
 */
-extern s3c_gpio_pull_t s3c_gpio_getpull_s3c2443(struct s3c_gpio_chip *chip,
+extern samsung_gpio_pull_t s3c2443_gpio_getpull(struct samsung_gpio_chip *chip,
                                                unsigned int off);
 
 #endif /* __PLAT_GPIO_CFG_HELPERS_H */
-
index 1762dcb4cb9e96341c5d2a2c6d4181de1aade52d..d48245bb02b3bbf6178a45e7e6ae48ad3ec8d7f6 100644 (file)
 #ifndef __PLAT_GPIO_CFG_H
 #define __PLAT_GPIO_CFG_H __FILE__
 
-typedef unsigned int __bitwise__ s3c_gpio_pull_t;
+typedef unsigned int __bitwise__ samsung_gpio_pull_t;
 typedef unsigned int __bitwise__ s5p_gpio_drvstr_t;
 
 /* forward declaration if gpio-core.h hasn't been included */
-struct s3c_gpio_chip;
+struct samsung_gpio_chip;
 
 /**
- * struct s3c_gpio_cfg GPIO configuration
+ * struct samsung_gpio_cfg GPIO configuration
  * @cfg_eint: Configuration setting when used for external interrupt source
  * @get_pull: Read the current pull configuration for the GPIO
  * @set_pull: Set the current pull configuraiton for the GPIO
@@ -44,20 +44,20 @@ struct s3c_gpio_chip;
  * per-bank configuration information that other systems such as the
  * external interrupt code will need.
  *
- * @sa s3c_gpio_cfgpin
+ * @sa samsung_gpio_cfgpin
  * @sa s3c_gpio_getcfg
  * @sa s3c_gpio_setpull
  * @sa s3c_gpio_getpull
  */
-struct s3c_gpio_cfg {
+struct samsung_gpio_cfg {
        unsigned int    cfg_eint;
 
-       s3c_gpio_pull_t (*get_pull)(struct s3c_gpio_chip *chip, unsigned offs);
-       int             (*set_pull)(struct s3c_gpio_chip *chip, unsigned offs,
-                                   s3c_gpio_pull_t pull);
+       samsung_gpio_pull_t     (*get_pull)(struct samsung_gpio_chip *chip, unsigned offs);
+       int             (*set_pull)(struct samsung_gpio_chip *chip, unsigned offs,
+                                   samsung_gpio_pull_t pull);
 
-       unsigned (*get_config)(struct s3c_gpio_chip *chip, unsigned offs);
-       int      (*set_config)(struct s3c_gpio_chip *chip, unsigned offs,
+       unsigned (*get_config)(struct samsung_gpio_chip *chip, unsigned offs);
+       int      (*set_config)(struct samsung_gpio_chip *chip, unsigned offs,
                               unsigned config);
 };
 
@@ -69,7 +69,7 @@ struct s3c_gpio_cfg {
 #define S3C_GPIO_OUTPUT        (S3C_GPIO_SPECIAL(1))
 #define S3C_GPIO_SFN(x)        (S3C_GPIO_SPECIAL(x))
 
-#define s3c_gpio_is_cfg_special(_cfg) \
+#define samsung_gpio_is_cfg_special(_cfg) \
        (((_cfg) & S3C_GPIO_SPECIAL_MARK) == S3C_GPIO_SPECIAL_MARK)
 
 /**
@@ -128,9 +128,9 @@ extern int s3c_gpio_cfgpin_range(unsigned int start, unsigned int nr,
  * up or down settings, and it may be dependent on the chip that is being
  * used to whether the particular mode is available.
  */
-#define S3C_GPIO_PULL_NONE     ((__force s3c_gpio_pull_t)0x00)
-#define S3C_GPIO_PULL_DOWN     ((__force s3c_gpio_pull_t)0x01)
-#define S3C_GPIO_PULL_UP       ((__force s3c_gpio_pull_t)0x02)
+#define S3C_GPIO_PULL_NONE     ((__force samsung_gpio_pull_t)0x00)
+#define S3C_GPIO_PULL_DOWN     ((__force samsung_gpio_pull_t)0x01)
+#define S3C_GPIO_PULL_UP       ((__force samsung_gpio_pull_t)0x02)
 
 /**
  * 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,
  *
  * @pull is one of S3C_GPIO_PULL_NONE, S3C_GPIO_PULL_DOWN or S3C_GPIO_PULL_UP.
 */
-extern int s3c_gpio_setpull(unsigned int pin, s3c_gpio_pull_t pull);
+extern int s3c_gpio_setpull(unsigned int pin, samsung_gpio_pull_t pull);
 
 /**
  * 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);
  *
  * Read the pull resistor value for the specified pin.
 */
-extern s3c_gpio_pull_t s3c_gpio_getpull(unsigned int pin);
+extern samsung_gpio_pull_t s3c_gpio_getpull(unsigned int pin);
 
 /* configure `all` aspects of an gpio */
 
@@ -170,7 +170,7 @@ extern s3c_gpio_pull_t s3c_gpio_getpull(unsigned int pin);
  * @sa s3c_gpio_cfgpin_range
  */
 extern int s3c_gpio_cfgall_range(unsigned int start, unsigned int nr,
-                                unsigned int cfg, s3c_gpio_pull_t pull);
+                                unsigned int cfg, samsung_gpio_pull_t pull);
 
 static inline int s3c_gpio_cfgrange_nopull(unsigned int pin, unsigned int size,
                                           unsigned int cfg)
index 8cad4cf19c3c019bb81395ef2138359bad36e6d4..1fe6917f6a2a75e9f36cce7c28f46ef13228f113 100644 (file)
  * specific code.
 */
 
-struct s3c_gpio_chip;
+struct samsung_gpio_chip;
 
 /**
- * struct s3c_gpio_pm - power management (suspend/resume) information
+ * struct samsung_gpio_pm - power management (suspend/resume) information
  * @save: Routine to save the state of the GPIO block
  * @resume: Routine to resume the GPIO block.
  */
-struct s3c_gpio_pm {
-       void (*save)(struct s3c_gpio_chip *chip);
-       void (*resume)(struct s3c_gpio_chip *chip);
+struct samsung_gpio_pm {
+       void (*save)(struct samsung_gpio_chip *chip);
+       void (*resume)(struct samsung_gpio_chip *chip);
 };
 
-struct s3c_gpio_cfg;
+struct samsung_gpio_cfg;
 
 /**
- * struct s3c_gpio_chip - wrapper for specific implementation of gpio
+ * struct samsung_gpio_chip - wrapper for specific implementation of gpio
  * @chip: The chip structure to be exported via gpiolib.
  * @base: The base pointer to the gpio configuration registers.
  * @group: The group register number for gpio interrupt support.
@@ -60,10 +60,10 @@ struct s3c_gpio_cfg;
  * CPU cores trying to get one lock for different GPIO banks, where each
  * bank of GPIO has its own register space and configuration registers.
  */
-struct s3c_gpio_chip {
+struct samsung_gpio_chip {
        struct gpio_chip        chip;
-       struct s3c_gpio_cfg     *config;
-       struct s3c_gpio_pm      *pm;
+       struct samsung_gpio_cfg *config;
+       struct samsung_gpio_pm  *pm;
        void __iomem            *base;
        int                     irq_base;
        int                     group;
@@ -73,58 +73,11 @@ struct s3c_gpio_chip {
 #endif
 };
 
-static inline struct s3c_gpio_chip *to_s3c_gpio(struct gpio_chip *gpc)
+static inline struct samsung_gpio_chip *to_samsung_gpio(struct gpio_chip *gpc)
 {
-       return container_of(gpc, struct s3c_gpio_chip, chip);
+       return container_of(gpc, struct samsung_gpio_chip, chip);
 }
 
-/** s3c_gpiolib_add() - add the s3c specific version of a gpio_chip.
- * @chip: The chip to register
- *
- * This is a wrapper to gpiochip_add() that takes our specific gpio chip
- * information and makes the necessary alterations for the platform and
- * notes the information for use with the configuration systems and any
- * other parts of the system.
- */
-extern void s3c_gpiolib_add(struct s3c_gpio_chip *chip);
-
-/* CONFIG_S3C_GPIO_TRACK enables the tracking of the s3c specific gpios
- * for use with the configuration calls, and other parts of the s3c gpiolib
- * support code.
- *
- * Not all s3c support code will need this, as some configurations of cpu
- * may only support one or two different configuration options and have an
- * easy gpio to s3c_gpio_chip mapping function. If this is the case, then
- * the machine support file should provide its own s3c_gpiolib_getchip()
- * and any other necessary functions.
- */
-
-/**
- * samsung_gpiolib_add_4bit_chips - 4bit single register GPIO config.
- * @chip: The gpio chip that is being configured.
- * @nr_chips: The no of chips (gpio ports) for the GPIO being configured.
- *
- * This helper deal with the GPIO cases where the control register has 4 bits
- * of control per GPIO, generally in the form of:
- * 0000 = Input
- * 0001 = Output
- * others = Special functions (dependent on bank)
- *
- * Note, since the code to deal with the case where there are two control
- * registers instead of one, we do not have a separate set of function
- * (samsung_gpiolib_add_4bit2_chips)for each case.
- */
-extern void samsung_gpiolib_add_4bit_chips(struct s3c_gpio_chip *chip,
-                                          int nr_chips);
-extern void samsung_gpiolib_add_4bit2_chips(struct s3c_gpio_chip *chip,
-                                           int nr_chips);
-extern void samsung_gpiolib_add_2bit_chips(struct s3c_gpio_chip *chip,
-                                          int nr_chips);
-
-extern void samsung_gpiolib_add_4bit(struct s3c_gpio_chip *chip);
-extern void samsung_gpiolib_add_4bit2(struct s3c_gpio_chip *chip);
-
-
 /**
  * samsung_gpiolib_to_irq - convert gpio pin to irq number
  * @chip: The gpio chip that the pin belongs to.
@@ -136,36 +89,36 @@ extern void samsung_gpiolib_add_4bit2(struct s3c_gpio_chip *chip);
 extern int samsung_gpiolib_to_irq(struct gpio_chip *chip, unsigned int offset);
 
 /* exported for core SoC support to change */
-extern struct s3c_gpio_cfg s3c24xx_gpiocfg_default;
+extern struct samsung_gpio_cfg s3c24xx_gpiocfg_default;
 
 #ifdef CONFIG_S3C_GPIO_TRACK
-extern struct s3c_gpio_chip *s3c_gpios[S3C_GPIO_END];
+extern struct samsung_gpio_chip *s3c_gpios[S3C_GPIO_END];
 
-static inline struct s3c_gpio_chip *s3c_gpiolib_getchip(unsigned int chip)
+static inline struct samsung_gpio_chip *samsung_gpiolib_getchip(unsigned int chip)
 {
        return (chip < S3C_GPIO_END) ? s3c_gpios[chip] : NULL;
 }
 #else
-/* machine specific code should provide s3c_gpiolib_getchip */
+/* machine specific code should provide samsung_gpiolib_getchip */
 
 #include <mach/gpio-track.h>
 
-static inline void s3c_gpiolib_track(struct s3c_gpio_chip *chip) { }
+static inline void s3c_gpiolib_track(struct samsung_gpio_chip *chip) { }
 #endif
 
 #ifdef CONFIG_PM
-extern struct s3c_gpio_pm s3c_gpio_pm_1bit;
-extern struct s3c_gpio_pm s3c_gpio_pm_2bit;
-extern struct s3c_gpio_pm s3c_gpio_pm_4bit;
+extern struct samsung_gpio_pm samsung_gpio_pm_1bit;
+extern struct samsung_gpio_pm samsung_gpio_pm_2bit;
+extern struct samsung_gpio_pm samsung_gpio_pm_4bit;
 #define __gpio_pm(x) x
 #else
-#define s3c_gpio_pm_1bit NULL
-#define s3c_gpio_pm_2bit NULL
-#define s3c_gpio_pm_4bit NULL
+#define samsung_gpio_pm_1bit NULL
+#define samsung_gpio_pm_2bit NULL
+#define samsung_gpio_pm_4bit NULL
 #define __gpio_pm(x) NULL
 
 #endif /* CONFIG_PM */
 
 /* locking wrappers to deal with multiple access to the same gpio bank */
-#define s3c_gpio_lock(_oc, _fl) spin_lock_irqsave(&(_oc)->lock, _fl)
-#define s3c_gpio_unlock(_oc, _fl) spin_unlock_irqrestore(&(_oc)->lock, _fl)
+#define samsung_gpio_lock(_oc, _fl) spin_lock_irqsave(&(_oc)->lock, _fl)
+#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 (file)
index 0000000..bab1392
--- /dev/null
@@ -0,0 +1,98 @@
+/* arch/arm/mach-s3c2410/include/mach/gpio-fns.h
+ *
+ * Copyright (c) 2003-2009 Simtec Electronics
+ *     Ben Dooks <ben@simtec.co.uk>
+ *
+ * S3C2410 - hardware
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __MACH_GPIO_FNS_H
+#define __MACH_GPIO_FNS_H __FILE__
+
+/* These functions are in the to-be-removed category and it is strongly
+ * encouraged not to use these in new code. They will be marked deprecated
+ * very soon.
+ *
+ * Most of the functionality can be either replaced by the gpiocfg calls
+ * for the s3c platform or by the generic GPIOlib API.
+ *
+ * As of 2.6.35-rc, these will be removed, with the few drivers using them
+ * either replaced or given a wrapper until the calls can be removed.
+*/
+
+#include <plat/gpio-cfg.h>
+
+static inline void s3c2410_gpio_cfgpin(unsigned int pin, unsigned int cfg)
+{
+       /* 1:1 mapping between cfgpin and setcfg calls at the moment */
+       s3c_gpio_cfgpin(pin, cfg);
+}
+
+/* external functions for GPIO support
+ *
+ * These allow various different clients to access the same GPIO
+ * registers without conflicting. If your driver only owns the entire
+ * GPIO register, then it is safe to ioremap/__raw_{read|write} to it.
+*/
+
+extern unsigned int s3c2410_gpio_getcfg(unsigned int pin);
+
+/* s3c2410_gpio_getirq
+ *
+ * turn the given pin number into the corresponding IRQ number
+ *
+ * returns:
+ *     < 0 = no interrupt for this pin
+ *     >=0 = interrupt number for the pin
+*/
+
+extern int s3c2410_gpio_getirq(unsigned int pin);
+
+/* s3c2410_gpio_irqfilter
+ *
+ * set the irq filtering on the given pin
+ *
+ * on = 0 => disable filtering
+ *      1 => enable filtering
+ *
+ * config = S3C2410_EINTFLT_PCLK or S3C2410_EINTFLT_EXTCLK orred with
+ *          width of filter (0 through 63)
+ *
+ *
+*/
+
+extern int s3c2410_gpio_irqfilter(unsigned int pin, unsigned int on,
+                                 unsigned int config);
+
+/* s3c2410_gpio_pullup
+ *
+ * This call should be replaced with s3c_gpio_setpull().
+ *
+ * As a note, there is currently no distinction between pull-up and pull-down
+ * in the s3c24xx series devices with only an on/off configuration.
+ */
+
+/* s3c2410_gpio_pullup
+ *
+ * configure the pull-up control on the given pin
+ *
+ * to = 1 => disable the pull-up
+ *      0 => enable the pull-up
+ *
+ * eg;
+ *
+ *   s3c2410_gpio_pullup(S3C2410_GPB(0), 0);
+ *   s3c2410_gpio_pullup(S3C2410_GPE(8), 0);
+*/
+
+extern void s3c2410_gpio_pullup(unsigned int pin, unsigned int to);
+
+extern void s3c2410_gpio_setpin(unsigned int pin, unsigned int to);
+
+extern unsigned int s3c2410_gpio_getpin(unsigned int pin);
+
+#endif /* __MACH_GPIO_FNS_H */
index 56b0059439e158edba132f10c15fdaa1fba14e1b..51d52e767a1955b52dc83e2510f1b5aec13ea1be 100644 (file)
@@ -60,6 +60,7 @@ extern void s3c_i2c4_set_platdata(struct s3c2410_platform_i2c *i2c);
 extern void s3c_i2c5_set_platdata(struct s3c2410_platform_i2c *i2c);
 extern void s3c_i2c6_set_platdata(struct s3c2410_platform_i2c *i2c);
 extern void s3c_i2c7_set_platdata(struct s3c2410_platform_i2c *i2c);
+extern void s5p_i2c_hdmiphy_set_platdata(struct s3c2410_platform_i2c *i2c);
 
 /* defined by architecture to configure gpio */
 extern void s3c_i2c0_cfg_gpio(struct platform_device *dev);
index f6749916d194b8d1e2a2e0a59cc35ccfa44ded16..dcf68709f9cff7f0f73986638e6643cf35c8fad0 100644 (file)
@@ -165,20 +165,20 @@ extern void s3c_pm_check_store(void);
 extern void s3c_pm_configure_extint(void);
 
 /**
- * s3c_pm_restore_gpios() - restore the state of the gpios after sleep.
+ * samsung_pm_restore_gpios() - restore the state of the gpios after sleep.
  *
  * Restore the state of the GPIO pins after sleep, which may involve ensuring
  * that we do not glitch the state of the pins from that the bootloader's
  * resume code has done.
 */
-extern void s3c_pm_restore_gpios(void);
+extern void samsung_pm_restore_gpios(void);
 
 /**
- * s3c_pm_save_gpios() - save the state of the GPIOs for restoring after sleep.
+ * samsung_pm_save_gpios() - save the state of the GPIOs for restoring after sleep.
  *
- * Save the GPIO states for resotration on resume. See s3c_pm_restore_gpios().
+ * Save the GPIO states for resotration on resume. See samsung_pm_restore_gpios().
  */
-extern void s3c_pm_save_gpios(void);
+extern void samsung_pm_save_gpios(void);
 
 extern void s3c_pm_save_core(void);
 extern void s3c_pm_restore_core(void);
diff --git a/arch/arm/plat-samsung/include/plat/s3c-dma-pl330.h b/arch/arm/plat-samsung/include/plat/s3c-dma-pl330.h
deleted file mode 100644 (file)
index 8107442..0000000
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * Copyright (C) 2010 Samsung Electronics Co. Ltd.
- *     Jaswinder Singh <jassi.brar@samsung.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#ifndef        __S3C_DMA_PL330_H_
-#define        __S3C_DMA_PL330_H_
-
-#define S3C2410_DMAF_AUTOSTART         (1 << 0)
-#define S3C2410_DMAF_CIRCULAR          (1 << 1)
-
-/*
- * PL330 can assign any channel to communicate with
- * any of the peripherals attched to the DMAC.
- * For the sake of consistency across client drivers,
- * We keep the channel names unchanged and only add
- * missing peripherals are added.
- * Order is not important since S3C PL330 API driver
- * use these just as IDs.
- */
-enum dma_ch {
-       DMACH_UART0_RX,
-       DMACH_UART0_TX,
-       DMACH_UART1_RX,
-       DMACH_UART1_TX,
-       DMACH_UART2_RX,
-       DMACH_UART2_TX,
-       DMACH_UART3_RX,
-       DMACH_UART3_TX,
-       DMACH_UART4_RX,
-       DMACH_UART4_TX,
-       DMACH_UART5_RX,
-       DMACH_UART5_TX,
-       DMACH_USI_RX,
-       DMACH_USI_TX,
-       DMACH_IRDA,
-       DMACH_I2S0_RX,
-       DMACH_I2S0_TX,
-       DMACH_I2S0S_TX,
-       DMACH_I2S1_RX,
-       DMACH_I2S1_TX,
-       DMACH_I2S2_RX,
-       DMACH_I2S2_TX,
-       DMACH_SPI0_RX,
-       DMACH_SPI0_TX,
-       DMACH_SPI1_RX,
-       DMACH_SPI1_TX,
-       DMACH_SPI2_RX,
-       DMACH_SPI2_TX,
-       DMACH_AC97_MICIN,
-       DMACH_AC97_PCMIN,
-       DMACH_AC97_PCMOUT,
-       DMACH_EXTERNAL,
-       DMACH_PWM,
-       DMACH_SPDIF,
-       DMACH_HSI_RX,
-       DMACH_HSI_TX,
-       DMACH_PCM0_TX,
-       DMACH_PCM0_RX,
-       DMACH_PCM1_TX,
-       DMACH_PCM1_RX,
-       DMACH_PCM2_TX,
-       DMACH_PCM2_RX,
-       DMACH_MSM_REQ3,
-       DMACH_MSM_REQ2,
-       DMACH_MSM_REQ1,
-       DMACH_MSM_REQ0,
-       DMACH_SLIMBUS0_RX,
-       DMACH_SLIMBUS0_TX,
-       DMACH_SLIMBUS0AUX_RX,
-       DMACH_SLIMBUS0AUX_TX,
-       DMACH_SLIMBUS1_RX,
-       DMACH_SLIMBUS1_TX,
-       DMACH_SLIMBUS2_RX,
-       DMACH_SLIMBUS2_TX,
-       DMACH_SLIMBUS3_RX,
-       DMACH_SLIMBUS3_TX,
-       DMACH_SLIMBUS4_RX,
-       DMACH_SLIMBUS4_TX,
-       DMACH_SLIMBUS5_RX,
-       DMACH_SLIMBUS5_TX,
-       /* END Marker, also used to denote a reserved channel */
-       DMACH_MAX,
-};
-
-static inline bool s3c_dma_has_circular(void)
-{
-       return true;
-}
-
-#include <plat/dma.h>
-
-#endif /* __S3C_DMA_PL330_H_ */
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 (file)
index bf5e2a9..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-/* linux/arch/arm/plat-samsung/include/plat/s3c-pl330-pdata.h
- *
- * Copyright (C) 2010 Samsung Electronics Co. Ltd.
- *     Jaswinder Singh <jassi.brar@samsung.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#ifndef __S3C_PL330_PDATA_H
-#define __S3C_PL330_PDATA_H
-
-#include <plat/s3c-dma-pl330.h>
-
-/*
- * Every PL330 DMAC has max 32 peripheral interfaces,
- * of which some may be not be really used in your
- * DMAC's configuration.
- * Populate this array of 32 peri i/fs with relevant
- * channel IDs for used peri i/f and DMACH_MAX for
- * those unused.
- *
- * The platforms just need to provide this info
- * to the S3C DMA API driver for PL330.
- */
-struct s3c_pl330_platdata {
-       enum dma_ch peri[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 (file)
index 0000000..3bc34f3
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * arch/arm/plat-samsung/include/plat/tv.h
+ *
+ * Copyright 2011 Samsung Electronics Co., Ltd.
+ *     Tomasz Stanislawski <t.stanislaws@samsung.com>
+ *
+ * Samsung TV driver core functions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __SAMSUNG_PLAT_TV_H
+#define __SAMSUNG_PLAT_TV_H __FILE__
+
+/*
+ * These functions are only for use with the core support code, such as
+ * the CPU-specific initialization code.
+ */
+
+/* Re-define device name to differentiate the subsystem in various SoCs. */
+static inline void s5p_hdmi_setname(char *name)
+{
+#ifdef CONFIG_S5P_DEV_TV
+       s5p_device_hdmi.name = name;
+#endif
+}
+
+static inline void s5p_mixer_setname(char *name)
+{
+#ifdef CONFIG_S5P_DEV_TV
+       s5p_device_mixer.name = name;
+#endif
+}
+
+static inline void s5p_sdo_setname(char *name)
+{
+#ifdef CONFIG_S5P_DEV_TV
+       s5p_device_sdo.name = name;
+#endif
+}
+
+#endif /* __SAMSUNG_PLAT_TV_H */
index 96528200eb79aae3ac06928930997e86102bb18c..4be016eaa6dba9c6180a399e0ebdc69794cb0930 100644 (file)
 #define OFFS_DAT       (0x04)
 #define OFFS_UP                (0x08)
 
-static void s3c_gpio_pm_1bit_save(struct s3c_gpio_chip *chip)
+static void samsung_gpio_pm_1bit_save(struct samsung_gpio_chip *chip)
 {
        chip->pm_save[0] = __raw_readl(chip->base + OFFS_CON);
        chip->pm_save[1] = __raw_readl(chip->base + OFFS_DAT);
 }
 
-static void s3c_gpio_pm_1bit_resume(struct s3c_gpio_chip *chip)
+static void samsung_gpio_pm_1bit_resume(struct samsung_gpio_chip *chip)
 {
        void __iomem *base = chip->base;
        u32 old_gpcon = __raw_readl(base + OFFS_CON);
@@ -60,12 +60,12 @@ static void s3c_gpio_pm_1bit_resume(struct s3c_gpio_chip *chip)
                  chip->chip.label, old_gpcon, gps_gpcon, old_gpdat, gps_gpdat);
 }
 
-struct s3c_gpio_pm s3c_gpio_pm_1bit = {
-       .save   = s3c_gpio_pm_1bit_save,
-       .resume = s3c_gpio_pm_1bit_resume,
+struct samsung_gpio_pm samsung_gpio_pm_1bit = {
+       .save   = samsung_gpio_pm_1bit_save,
+       .resume = samsung_gpio_pm_1bit_resume,
 };
 
-static void s3c_gpio_pm_2bit_save(struct s3c_gpio_chip *chip)
+static void samsung_gpio_pm_2bit_save(struct samsung_gpio_chip *chip)
 {
        chip->pm_save[0] = __raw_readl(chip->base + OFFS_CON);
        chip->pm_save[1] = __raw_readl(chip->base + OFFS_DAT);
@@ -95,7 +95,7 @@ static inline int is_out(unsigned long con)
 }
 
 /**
- * s3c_gpio_pm_2bit_resume() - restore the given GPIO bank
+ * samsung_gpio_pm_2bit_resume() - restore the given GPIO bank
  * @chip: The chip information to resume.
  *
  * 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)
  * [1] this assumes that writing to a pin DAT whilst in SFN will set the
  *     state for when it is next output.
  */
-static void s3c_gpio_pm_2bit_resume(struct s3c_gpio_chip *chip)
+static void samsung_gpio_pm_2bit_resume(struct samsung_gpio_chip *chip)
 {
        void __iomem *base = chip->base;
        u32 old_gpcon = __raw_readl(base + OFFS_CON);
@@ -187,13 +187,13 @@ static void s3c_gpio_pm_2bit_resume(struct s3c_gpio_chip *chip)
                  chip->chip.label, old_gpcon, gps_gpcon, old_gpdat, gps_gpdat);
 }
 
-struct s3c_gpio_pm s3c_gpio_pm_2bit = {
-       .save   = s3c_gpio_pm_2bit_save,
-       .resume = s3c_gpio_pm_2bit_resume,
+struct samsung_gpio_pm samsung_gpio_pm_2bit = {
+       .save   = samsung_gpio_pm_2bit_save,
+       .resume = samsung_gpio_pm_2bit_resume,
 };
 
 #if defined(CONFIG_ARCH_S3C64XX) || defined(CONFIG_PLAT_S5P)
-static void s3c_gpio_pm_4bit_save(struct s3c_gpio_chip *chip)
+static void samsung_gpio_pm_4bit_save(struct samsung_gpio_chip *chip)
 {
        chip->pm_save[1] = __raw_readl(chip->base + OFFS_CON);
        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)
                chip->pm_save[0] = __raw_readl(chip->base - 4);
 }
 
-static u32 s3c_gpio_pm_4bit_mask(u32 old_gpcon, u32 gps_gpcon)
+static u32 samsung_gpio_pm_4bit_mask(u32 old_gpcon, u32 gps_gpcon)
 {
        u32 old, new, mask;
        u32 change_mask = 0x0;
@@ -242,14 +242,14 @@ static u32 s3c_gpio_pm_4bit_mask(u32 old_gpcon, u32 gps_gpcon)
        return change_mask;
 }
 
-static void s3c_gpio_pm_4bit_con(struct s3c_gpio_chip *chip, int index)
+static void samsung_gpio_pm_4bit_con(struct samsung_gpio_chip *chip, int index)
 {
        void __iomem *con = chip->base + (index * 4);
        u32 old_gpcon = __raw_readl(con);
        u32 gps_gpcon = chip->pm_save[index + 1];
        u32 gpcon, mask;
 
-       mask = s3c_gpio_pm_4bit_mask(old_gpcon, gps_gpcon);
+       mask = samsung_gpio_pm_4bit_mask(old_gpcon, gps_gpcon);
 
        gpcon = old_gpcon & ~mask;
        gpcon |= gps_gpcon & mask;
@@ -257,7 +257,7 @@ static void s3c_gpio_pm_4bit_con(struct s3c_gpio_chip *chip, int index)
        __raw_writel(gpcon, con);
 }
 
-static void s3c_gpio_pm_4bit_resume(struct s3c_gpio_chip *chip)
+static void samsung_gpio_pm_4bit_resume(struct samsung_gpio_chip *chip)
 {
        void __iomem *base = chip->base;
        u32 old_gpcon[2];
@@ -269,10 +269,10 @@ static void s3c_gpio_pm_4bit_resume(struct s3c_gpio_chip *chip)
        old_gpcon[0] = 0;
        old_gpcon[1] = __raw_readl(base + OFFS_CON);
 
-       s3c_gpio_pm_4bit_con(chip, 0);
+       samsung_gpio_pm_4bit_con(chip, 0);
        if (chip->chip.ngpio > 8) {
                old_gpcon[0] = __raw_readl(base - 4);
-               s3c_gpio_pm_4bit_con(chip, -1);
+               samsung_gpio_pm_4bit_con(chip, -1);
        }
 
        /* Now change the configurations that require DAT,CON */
@@ -298,19 +298,19 @@ static void s3c_gpio_pm_4bit_resume(struct s3c_gpio_chip *chip)
                          old_gpdat, gps_gpdat);
 }
 
-struct s3c_gpio_pm s3c_gpio_pm_4bit = {
-       .save   = s3c_gpio_pm_4bit_save,
-       .resume = s3c_gpio_pm_4bit_resume,
+struct samsung_gpio_pm samsung_gpio_pm_4bit = {
+       .save   = samsung_gpio_pm_4bit_save,
+       .resume = samsung_gpio_pm_4bit_resume,
 };
 #endif /* CONFIG_ARCH_S3C64XX || CONFIG_PLAT_S5P */
 
 /**
- * s3c_pm_save_gpio() - save gpio chip data for suspend
+ * samsung_pm_save_gpio() - save gpio chip data for suspend
  * @ourchip: The chip for suspend.
  */
-static void s3c_pm_save_gpio(struct s3c_gpio_chip *ourchip)
+static void samsung_pm_save_gpio(struct samsung_gpio_chip *ourchip)
 {
-       struct s3c_gpio_pm *pm = ourchip->pm;
+       struct samsung_gpio_pm *pm = ourchip->pm;
 
        if (pm == NULL || pm->save == NULL)
                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)
 }
 
 /**
- * s3c_pm_save_gpios() - Save the state of the GPIO banks.
+ * samsung_pm_save_gpios() - Save the state of the GPIO banks.
  *
  * For all the GPIO banks, save the state of each one ready for going
  * into a suspend mode.
  */
-void s3c_pm_save_gpios(void)
+void samsung_pm_save_gpios(void)
 {
-       struct s3c_gpio_chip *ourchip;
+       struct samsung_gpio_chip *ourchip;
        unsigned int gpio_nr;
 
        for (gpio_nr = 0; gpio_nr < S3C_GPIO_END;) {
-               ourchip = s3c_gpiolib_getchip(gpio_nr);
+               ourchip = samsung_gpiolib_getchip(gpio_nr);
                if (!ourchip) {
                        gpio_nr++;
                        continue;
                }
 
-               s3c_pm_save_gpio(ourchip);
+               samsung_pm_save_gpio(ourchip);
 
                S3C_PMDBG("%s: save %08x,%08x,%08x,%08x\n",
                          ourchip->chip.label,
@@ -351,12 +351,12 @@ void s3c_pm_save_gpios(void)
 }
 
 /**
- * s3c_pm_resume_gpio() - restore gpio chip data after suspend
+ * samsung_pm_resume_gpio() - restore gpio chip data after suspend
  * @ourchip: The suspended chip.
  */
-static void s3c_pm_resume_gpio(struct s3c_gpio_chip *ourchip)
+static void samsung_pm_resume_gpio(struct samsung_gpio_chip *ourchip)
 {
-       struct s3c_gpio_pm *pm = ourchip->pm;
+       struct samsung_gpio_pm *pm = ourchip->pm;
 
        if (pm == NULL || pm->resume == NULL)
                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)
                pm->resume(ourchip);
 }
 
-void s3c_pm_restore_gpios(void)
+void samsung_pm_restore_gpios(void)
 {
-       struct s3c_gpio_chip *ourchip;
+       struct samsung_gpio_chip *ourchip;
        unsigned int gpio_nr;
 
        for (gpio_nr = 0; gpio_nr < S3C_GPIO_END;) {
-               ourchip = s3c_gpiolib_getchip(gpio_nr);
+               ourchip = samsung_gpiolib_getchip(gpio_nr);
                if (!ourchip) {
                        gpio_nr++;
                        continue;
                }
 
-               s3c_pm_resume_gpio(ourchip);
+               samsung_pm_resume_gpio(ourchip);
 
                gpio_nr += ourchip->chip.ngpio;
                gpio_nr += CONFIG_S3C_GPIO_SPACE;
index ae6f99834cddb01ea69b471b22fa823f7c7f0aa8..64ab65f0fdbc652cd1e0f165ec13bf5a61cc6377 100644 (file)
@@ -268,8 +268,8 @@ static int s3c_pm_enter(suspend_state_t state)
 
        /* save all necessary core registers not covered by the drivers */
 
-       s3c_pm_save_gpios();
-       s3c_pm_saved_gpios();
+       samsung_pm_save_gpios();
+       samsung_pm_saved_gpios();
        s3c_pm_save_uarts();
        s3c_pm_save_core();
 
@@ -306,7 +306,7 @@ static int s3c_pm_enter(suspend_state_t state)
 
        s3c_pm_restore_core();
        s3c_pm_restore_uarts();
-       s3c_pm_restore_gpios();
+       samsung_pm_restore_gpios();
        s3c_pm_restored_gpios();
 
        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 (file)
index 0000000..582333c
--- /dev/null
@@ -0,0 +1,130 @@
+/* linux/arch/arm/plat-samsung/s3c-dma-ops.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com
+ *
+ * Samsung S3C-DMA Operations
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+
+#include <mach/dma.h>
+
+struct cb_data {
+       void (*fp) (void *);
+       void *fp_param;
+       unsigned ch;
+       struct list_head node;
+};
+
+static LIST_HEAD(dma_list);
+
+static void s3c_dma_cb(struct s3c2410_dma_chan *channel, void *param,
+                      int size, enum s3c2410_dma_buffresult res)
+{
+       struct cb_data *data = param;
+
+       data->fp(data->fp_param);
+}
+
+static unsigned s3c_dma_request(enum dma_ch dma_ch,
+                                struct samsung_dma_info *info)
+{
+       struct cb_data *data;
+
+       if (s3c2410_dma_request(dma_ch, info->client, NULL) < 0) {
+               s3c2410_dma_free(dma_ch, info->client);
+               return 0;
+       }
+
+       data = kzalloc(sizeof(struct cb_data), GFP_KERNEL);
+       data->ch = dma_ch;
+       list_add_tail(&data->node, &dma_list);
+
+       s3c2410_dma_devconfig(dma_ch, info->direction, info->fifo);
+
+       if (info->cap == DMA_CYCLIC)
+               s3c2410_dma_setflags(dma_ch, S3C2410_DMAF_CIRCULAR);
+
+       s3c2410_dma_config(dma_ch, info->width);
+
+       return (unsigned)dma_ch;
+}
+
+static int s3c_dma_release(unsigned ch, struct s3c2410_dma_client *client)
+{
+       struct cb_data *data;
+
+       list_for_each_entry(data, &dma_list, node)
+               if (data->ch == ch)
+                       break;
+       list_del(&data->node);
+
+       s3c2410_dma_free(ch, client);
+       kfree(data);
+
+       return 0;
+}
+
+static int s3c_dma_prepare(unsigned ch, struct samsung_dma_prep_info *info)
+{
+       struct cb_data *data;
+       int len = (info->cap == DMA_CYCLIC) ? info->period : info->len;
+
+       list_for_each_entry(data, &dma_list, node)
+               if (data->ch == ch)
+                       break;
+
+       if (!data->fp) {
+               s3c2410_dma_set_buffdone_fn(ch, s3c_dma_cb);
+               data->fp = info->fp;
+               data->fp_param = info->fp_param;
+       }
+
+       s3c2410_dma_enqueue(ch, (void *)data, info->buf, len);
+
+       return 0;
+}
+
+static inline int s3c_dma_trigger(unsigned ch)
+{
+       return s3c2410_dma_ctrl(ch, S3C2410_DMAOP_START);
+}
+
+static inline int s3c_dma_started(unsigned ch)
+{
+       return s3c2410_dma_ctrl(ch, S3C2410_DMAOP_STARTED);
+}
+
+static inline int s3c_dma_flush(unsigned ch)
+{
+       return s3c2410_dma_ctrl(ch, S3C2410_DMAOP_FLUSH);
+}
+
+static inline int s3c_dma_stop(unsigned ch)
+{
+       return s3c2410_dma_ctrl(ch, S3C2410_DMAOP_STOP);
+}
+
+static struct samsung_dma_ops s3c_dma_ops = {
+       .request        = s3c_dma_request,
+       .release        = s3c_dma_release,
+       .prepare        = s3c_dma_prepare,
+       .trigger        = s3c_dma_trigger,
+       .started        = s3c_dma_started,
+       .flush          = s3c_dma_flush,
+       .stop           = s3c_dma_stop,
+};
+
+void *s3c_dma_get_ops(void)
+{
+       return &s3c_dma_ops;
+}
+EXPORT_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 (file)
index f85638c..0000000
+++ /dev/null
@@ -1,1244 +0,0 @@
-/* linux/arch/arm/plat-samsung/s3c-pl330.c
- *
- * Copyright (C) 2010 Samsung Electronics Co. Ltd.
- *     Jaswinder Singh <jassi.brar@samsung.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/interrupt.h>
-#include <linux/io.h>
-#include <linux/slab.h>
-#include <linux/platform_device.h>
-#include <linux/clk.h>
-#include <linux/err.h>
-
-#include <asm/hardware/pl330.h>
-
-#include <plat/s3c-pl330-pdata.h>
-
-/**
- * struct s3c_pl330_dmac - Logical representation of a PL330 DMAC.
- * @busy_chan: Number of channels currently busy.
- * @peri: List of IDs of peripherals this DMAC can work with.
- * @node: To attach to the global list of DMACs.
- * @pi: PL330 configuration info for the DMAC.
- * @kmcache: Pool to quickly allocate xfers for all channels in the dmac.
- * @clk: Pointer of DMAC operation clock.
- */
-struct s3c_pl330_dmac {
-       unsigned                busy_chan;
-       enum dma_ch             *peri;
-       struct list_head        node;
-       struct pl330_info       *pi;
-       struct kmem_cache       *kmcache;
-       struct clk              *clk;
-};
-
-/**
- * struct s3c_pl330_xfer - A request submitted by S3C DMA clients.
- * @token: Xfer ID provided by the client.
- * @node: To attach to the list of xfers on a channel.
- * @px: Xfer for PL330 core.
- * @chan: Owner channel of this xfer.
- */
-struct s3c_pl330_xfer {
-       void                    *token;
-       struct list_head        node;
-       struct pl330_xfer       px;
-       struct s3c_pl330_chan   *chan;
-};
-
-/**
- * struct s3c_pl330_chan - Logical channel to communicate with
- *     a Physical peripheral.
- * @pl330_chan_id: Token of a hardware channel thread of PL330 DMAC.
- *     NULL if the channel is available to be acquired.
- * @id: ID of the peripheral that this channel can communicate with.
- * @options: Options specified by the client.
- * @sdaddr: Address provided via s3c2410_dma_devconfig.
- * @node: To attach to the global list of channels.
- * @lrq: Pointer to the last submitted pl330_req to PL330 core.
- * @xfer_list: To manage list of xfers enqueued.
- * @req: Two requests to communicate with the PL330 engine.
- * @callback_fn: Callback function to the client.
- * @rqcfg: Channel configuration for the xfers.
- * @xfer_head: Pointer to the xfer to be next executed.
- * @dmac: Pointer to the DMAC that manages this channel, NULL if the
- *     channel is available to be acquired.
- * @client: Client of this channel. NULL if the
- *     channel is available to be acquired.
- */
-struct s3c_pl330_chan {
-       void                            *pl330_chan_id;
-       enum dma_ch                     id;
-       unsigned int                    options;
-       unsigned long                   sdaddr;
-       struct list_head                node;
-       struct pl330_req                *lrq;
-       struct list_head                xfer_list;
-       struct pl330_req                req[2];
-       s3c2410_dma_cbfn_t              callback_fn;
-       struct pl330_reqcfg             rqcfg;
-       struct s3c_pl330_xfer           *xfer_head;
-       struct s3c_pl330_dmac           *dmac;
-       struct s3c2410_dma_client       *client;
-};
-
-/* All DMACs in the platform */
-static LIST_HEAD(dmac_list);
-
-/* All channels to peripherals in the platform */
-static LIST_HEAD(chan_list);
-
-/*
- * Since we add resources(DMACs and Channels) to the global pool,
- * we need to guard access to the resources using a global lock
- */
-static DEFINE_SPINLOCK(res_lock);
-
-/* Returns the channel with ID 'id' in the chan_list */
-static struct s3c_pl330_chan *id_to_chan(const enum dma_ch id)
-{
-       struct s3c_pl330_chan *ch;
-
-       list_for_each_entry(ch, &chan_list, node)
-               if (ch->id == id)
-                       return ch;
-
-       return NULL;
-}
-
-/* Allocate a new channel with ID 'id' and add to chan_list */
-static void chan_add(const enum dma_ch id)
-{
-       struct s3c_pl330_chan *ch = id_to_chan(id);
-
-       /* Return if the channel already exists */
-       if (ch)
-               return;
-
-       ch = kmalloc(sizeof(*ch), GFP_KERNEL);
-       /* Return silently to work with other channels */
-       if (!ch)
-               return;
-
-       ch->id = id;
-       ch->dmac = NULL;
-
-       list_add_tail(&ch->node, &chan_list);
-}
-
-/* If the channel is not yet acquired by any client */
-static bool chan_free(struct s3c_pl330_chan *ch)
-{
-       if (!ch)
-               return false;
-
-       /* Channel points to some DMAC only when it's acquired */
-       return ch->dmac ? false : true;
-}
-
-/*
- * Returns 0 is peripheral i/f is invalid or not present on the dmac.
- * Index + 1, otherwise.
- */
-static unsigned iface_of_dmac(struct s3c_pl330_dmac *dmac, enum dma_ch ch_id)
-{
-       enum dma_ch *id = dmac->peri;
-       int i;
-
-       /* Discount invalid markers */
-       if (ch_id == DMACH_MAX)
-               return 0;
-
-       for (i = 0; i < PL330_MAX_PERI; i++)
-               if (id[i] == ch_id)
-                       return i + 1;
-
-       return 0;
-}
-
-/* If all channel threads of the DMAC are busy */
-static inline bool dmac_busy(struct s3c_pl330_dmac *dmac)
-{
-       struct pl330_info *pi = dmac->pi;
-
-       return (dmac->busy_chan < pi->pcfg.num_chan) ? false : true;
-}
-
-/*
- * Returns the number of free channels that
- * can be handled by this dmac only.
- */
-static unsigned ch_onlyby_dmac(struct s3c_pl330_dmac *dmac)
-{
-       enum dma_ch *id = dmac->peri;
-       struct s3c_pl330_dmac *d;
-       struct s3c_pl330_chan *ch;
-       unsigned found, count = 0;
-       enum dma_ch p;
-       int i;
-
-       for (i = 0; i < PL330_MAX_PERI; i++) {
-               p = id[i];
-               ch = id_to_chan(p);
-
-               if (p == DMACH_MAX || !chan_free(ch))
-                       continue;
-
-               found = 0;
-               list_for_each_entry(d, &dmac_list, node) {
-                       if (d != dmac && iface_of_dmac(d, ch->id)) {
-                               found = 1;
-                               break;
-                       }
-               }
-               if (!found)
-                       count++;
-       }
-
-       return count;
-}
-
-/*
- * Measure of suitability of 'dmac' handling 'ch'
- *
- * 0 indicates 'dmac' can not handle 'ch' either
- * because it is not supported by the hardware or
- * because all dmac channels are currently busy.
- *
- * >0 vlaue indicates 'dmac' has the capability.
- * The bigger the value the more suitable the dmac.
- */
-#define MAX_SUIT       UINT_MAX
-#define MIN_SUIT       0
-
-static unsigned suitablility(struct s3c_pl330_dmac *dmac,
-               struct s3c_pl330_chan *ch)
-{
-       struct pl330_info *pi = dmac->pi;
-       enum dma_ch *id = dmac->peri;
-       struct s3c_pl330_dmac *d;
-       unsigned s;
-       int i;
-
-       s = MIN_SUIT;
-       /* If all the DMAC channel threads are busy */
-       if (dmac_busy(dmac))
-               return s;
-
-       for (i = 0; i < PL330_MAX_PERI; i++)
-               if (id[i] == ch->id)
-                       break;
-
-       /* If the 'dmac' can't talk to 'ch' */
-       if (i == PL330_MAX_PERI)
-               return s;
-
-       s = MAX_SUIT;
-       list_for_each_entry(d, &dmac_list, node) {
-               /*
-                * If some other dmac can talk to this
-                * peri and has some channel free.
-                */
-               if (d != dmac && iface_of_dmac(d, ch->id) && !dmac_busy(d)) {
-                       s = 0;
-                       break;
-               }
-       }
-       if (s)
-               return s;
-
-       s = 100;
-
-       /* Good if free chans are more, bad otherwise */
-       s += (pi->pcfg.num_chan - dmac->busy_chan) - ch_onlyby_dmac(dmac);
-
-       return s;
-}
-
-/* More than one DMAC may have capability to transfer data with the
- * peripheral. This function assigns most suitable DMAC to manage the
- * channel and hence communicate with the peripheral.
- */
-static struct s3c_pl330_dmac *map_chan_to_dmac(struct s3c_pl330_chan *ch)
-{
-       struct s3c_pl330_dmac *d, *dmac = NULL;
-       unsigned sn, sl = MIN_SUIT;
-
-       list_for_each_entry(d, &dmac_list, node) {
-               sn = suitablility(d, ch);
-
-               if (sn == MAX_SUIT)
-                       return d;
-
-               if (sn > sl)
-                       dmac = d;
-       }
-
-       return dmac;
-}
-
-/* Acquire the channel for peripheral 'id' */
-static struct s3c_pl330_chan *chan_acquire(const enum dma_ch id)
-{
-       struct s3c_pl330_chan *ch = id_to_chan(id);
-       struct s3c_pl330_dmac *dmac;
-
-       /* If the channel doesn't exist or is already acquired */
-       if (!ch || !chan_free(ch)) {
-               ch = NULL;
-               goto acq_exit;
-       }
-
-       dmac = map_chan_to_dmac(ch);
-       /* If couldn't map */
-       if (!dmac) {
-               ch = NULL;
-               goto acq_exit;
-       }
-
-       dmac->busy_chan++;
-       ch->dmac = dmac;
-
-acq_exit:
-       return ch;
-}
-
-/* Delete xfer from the queue */
-static inline void del_from_queue(struct s3c_pl330_xfer *xfer)
-{
-       struct s3c_pl330_xfer *t;
-       struct s3c_pl330_chan *ch;
-       int found;
-
-       if (!xfer)
-               return;
-
-       ch = xfer->chan;
-
-       /* Make sure xfer is in the queue */
-       found = 0;
-       list_for_each_entry(t, &ch->xfer_list, node)
-               if (t == xfer) {
-                       found = 1;
-                       break;
-               }
-
-       if (!found)
-               return;
-
-       /* If xfer is last entry in the queue */
-       if (xfer->node.next == &ch->xfer_list)
-               t = list_entry(ch->xfer_list.next,
-                               struct s3c_pl330_xfer, node);
-       else
-               t = list_entry(xfer->node.next,
-                               struct s3c_pl330_xfer, node);
-
-       /* If there was only one node left */
-       if (t == xfer)
-               ch->xfer_head = NULL;
-       else if (ch->xfer_head == xfer)
-               ch->xfer_head = t;
-
-       list_del(&xfer->node);
-}
-
-/* Provides pointer to the next xfer in the queue.
- * If CIRCULAR option is set, the list is left intact,
- * otherwise the xfer is removed from the list.
- * Forced delete 'pluck' can be set to override the CIRCULAR option.
- */
-static struct s3c_pl330_xfer *get_from_queue(struct s3c_pl330_chan *ch,
-               int pluck)
-{
-       struct s3c_pl330_xfer *xfer = ch->xfer_head;
-
-       if (!xfer)
-               return NULL;
-
-       /* If xfer is last entry in the queue */
-       if (xfer->node.next == &ch->xfer_list)
-               ch->xfer_head = list_entry(ch->xfer_list.next,
-                                       struct s3c_pl330_xfer, node);
-       else
-               ch->xfer_head = list_entry(xfer->node.next,
-                                       struct s3c_pl330_xfer, node);
-
-       if (pluck || !(ch->options & S3C2410_DMAF_CIRCULAR))
-               del_from_queue(xfer);
-
-       return xfer;
-}
-
-static inline void add_to_queue(struct s3c_pl330_chan *ch,
-               struct s3c_pl330_xfer *xfer, int front)
-{
-       struct pl330_xfer *xt;
-
-       /* If queue empty */
-       if (ch->xfer_head == NULL)
-               ch->xfer_head = xfer;
-
-       xt = &ch->xfer_head->px;
-       /* If the head already submitted (CIRCULAR head) */
-       if (ch->options & S3C2410_DMAF_CIRCULAR &&
-               (xt == ch->req[0].x || xt == ch->req[1].x))
-               ch->xfer_head = xfer;
-
-       /* If this is a resubmission, it should go at the head */
-       if (front) {
-               ch->xfer_head = xfer;
-               list_add(&xfer->node, &ch->xfer_list);
-       } else {
-               list_add_tail(&xfer->node, &ch->xfer_list);
-       }
-}
-
-static inline void _finish_off(struct s3c_pl330_xfer *xfer,
-               enum s3c2410_dma_buffresult res, int ffree)
-{
-       struct s3c_pl330_chan *ch;
-
-       if (!xfer)
-               return;
-
-       ch = xfer->chan;
-
-       /* Do callback */
-       if (ch->callback_fn)
-               ch->callback_fn(NULL, xfer->token, xfer->px.bytes, res);
-
-       /* Force Free or if buffer is not needed anymore */
-       if (ffree || !(ch->options & S3C2410_DMAF_CIRCULAR))
-               kmem_cache_free(ch->dmac->kmcache, xfer);
-}
-
-static inline int s3c_pl330_submit(struct s3c_pl330_chan *ch,
-               struct pl330_req *r)
-{
-       struct s3c_pl330_xfer *xfer;
-       int ret = 0;
-
-       /* If already submitted */
-       if (r->x)
-               return 0;
-
-       xfer = get_from_queue(ch, 0);
-       if (xfer) {
-               r->x = &xfer->px;
-
-               /* Use max bandwidth for M<->M xfers */
-               if (r->rqtype == MEMTOMEM) {
-                       struct pl330_info *pi = xfer->chan->dmac->pi;
-                       int burst = 1 << ch->rqcfg.brst_size;
-                       u32 bytes = r->x->bytes;
-                       int bl;
-
-                       bl = pi->pcfg.data_bus_width / 8;
-                       bl *= pi->pcfg.data_buf_dep;
-                       bl /= burst;
-
-                       /* src/dst_burst_len can't be more than 16 */
-                       if (bl > 16)
-                               bl = 16;
-
-                       while (bl > 1) {
-                               if (!(bytes % (bl * burst)))
-                                       break;
-                               bl--;
-                       }
-
-                       ch->rqcfg.brst_len = bl;
-               } else {
-                       ch->rqcfg.brst_len = 1;
-               }
-
-               ret = pl330_submit_req(ch->pl330_chan_id, r);
-
-               /* If submission was successful */
-               if (!ret) {
-                       ch->lrq = r; /* latest submitted req */
-                       return 0;
-               }
-
-               r->x = NULL;
-
-               /* If both of the PL330 ping-pong buffers filled */
-               if (ret == -EAGAIN) {
-                       dev_err(ch->dmac->pi->dev, "%s:%d!\n",
-                               __func__, __LINE__);
-                       /* Queue back again */
-                       add_to_queue(ch, xfer, 1);
-                       ret = 0;
-               } else {
-                       dev_err(ch->dmac->pi->dev, "%s:%d!\n",
-                               __func__, __LINE__);
-                       _finish_off(xfer, S3C2410_RES_ERR, 0);
-               }
-       }
-
-       return ret;
-}
-
-static void s3c_pl330_rq(struct s3c_pl330_chan *ch,
-       struct pl330_req *r, enum pl330_op_err err)
-{
-       unsigned long flags;
-       struct s3c_pl330_xfer *xfer;
-       struct pl330_xfer *xl = r->x;
-       enum s3c2410_dma_buffresult res;
-
-       spin_lock_irqsave(&res_lock, flags);
-
-       r->x = NULL;
-
-       s3c_pl330_submit(ch, r);
-
-       spin_unlock_irqrestore(&res_lock, flags);
-
-       /* Map result to S3C DMA API */
-       if (err == PL330_ERR_NONE)
-               res = S3C2410_RES_OK;
-       else if (err == PL330_ERR_ABORT)
-               res = S3C2410_RES_ABORT;
-       else
-               res = S3C2410_RES_ERR;
-
-       /* If last request had some xfer */
-       if (xl) {
-               xfer = container_of(xl, struct s3c_pl330_xfer, px);
-               _finish_off(xfer, res, 0);
-       } else {
-               dev_info(ch->dmac->pi->dev, "%s:%d No Xfer?!\n",
-                       __func__, __LINE__);
-       }
-}
-
-static void s3c_pl330_rq0(void *token, enum pl330_op_err err)
-{
-       struct pl330_req *r = token;
-       struct s3c_pl330_chan *ch = container_of(r,
-                                       struct s3c_pl330_chan, req[0]);
-       s3c_pl330_rq(ch, r, err);
-}
-
-static void s3c_pl330_rq1(void *token, enum pl330_op_err err)
-{
-       struct pl330_req *r = token;
-       struct s3c_pl330_chan *ch = container_of(r,
-                                       struct s3c_pl330_chan, req[1]);
-       s3c_pl330_rq(ch, r, err);
-}
-
-/* Release an acquired channel */
-static void chan_release(struct s3c_pl330_chan *ch)
-{
-       struct s3c_pl330_dmac *dmac;
-
-       if (chan_free(ch))
-               return;
-
-       dmac = ch->dmac;
-       ch->dmac = NULL;
-       dmac->busy_chan--;
-}
-
-int s3c2410_dma_ctrl(enum dma_ch id, enum s3c2410_chan_op op)
-{
-       struct s3c_pl330_xfer *xfer;
-       enum pl330_chan_op pl330op;
-       struct s3c_pl330_chan *ch;
-       unsigned long flags;
-       int idx, ret;
-
-       spin_lock_irqsave(&res_lock, flags);
-
-       ch = id_to_chan(id);
-
-       if (!ch || chan_free(ch)) {
-               ret = -EINVAL;
-               goto ctrl_exit;
-       }
-
-       switch (op) {
-       case S3C2410_DMAOP_START:
-               /* Make sure both reqs are enqueued */
-               idx = (ch->lrq == &ch->req[0]) ? 1 : 0;
-               s3c_pl330_submit(ch, &ch->req[idx]);
-               s3c_pl330_submit(ch, &ch->req[1 - idx]);
-               pl330op = PL330_OP_START;
-               break;
-
-       case S3C2410_DMAOP_STOP:
-               pl330op = PL330_OP_ABORT;
-               break;
-
-       case S3C2410_DMAOP_FLUSH:
-               pl330op = PL330_OP_FLUSH;
-               break;
-
-       case S3C2410_DMAOP_PAUSE:
-       case S3C2410_DMAOP_RESUME:
-       case S3C2410_DMAOP_TIMEOUT:
-       case S3C2410_DMAOP_STARTED:
-               spin_unlock_irqrestore(&res_lock, flags);
-               return 0;
-
-       default:
-               spin_unlock_irqrestore(&res_lock, flags);
-               return -EINVAL;
-       }
-
-       ret = pl330_chan_ctrl(ch->pl330_chan_id, pl330op);
-
-       if (pl330op == PL330_OP_START) {
-               spin_unlock_irqrestore(&res_lock, flags);
-               return ret;
-       }
-
-       idx = (ch->lrq == &ch->req[0]) ? 1 : 0;
-
-       /* Abort the current xfer */
-       if (ch->req[idx].x) {
-               xfer = container_of(ch->req[idx].x,
-                               struct s3c_pl330_xfer, px);
-
-               /* Drop xfer during FLUSH */
-               if (pl330op == PL330_OP_FLUSH)
-                       del_from_queue(xfer);
-
-               ch->req[idx].x = NULL;
-
-               spin_unlock_irqrestore(&res_lock, flags);
-               _finish_off(xfer, S3C2410_RES_ABORT,
-                               pl330op == PL330_OP_FLUSH ? 1 : 0);
-               spin_lock_irqsave(&res_lock, flags);
-       }
-
-       /* Flush the whole queue */
-       if (pl330op == PL330_OP_FLUSH) {
-
-               if (ch->req[1 - idx].x) {
-                       xfer = container_of(ch->req[1 - idx].x,
-                                       struct s3c_pl330_xfer, px);
-
-                       del_from_queue(xfer);
-
-                       ch->req[1 - idx].x = NULL;
-
-                       spin_unlock_irqrestore(&res_lock, flags);
-                       _finish_off(xfer, S3C2410_RES_ABORT, 1);
-                       spin_lock_irqsave(&res_lock, flags);
-               }
-
-               /* Finish off the remaining in the queue */
-               xfer = ch->xfer_head;
-               while (xfer) {
-
-                       del_from_queue(xfer);
-
-                       spin_unlock_irqrestore(&res_lock, flags);
-                       _finish_off(xfer, S3C2410_RES_ABORT, 1);
-                       spin_lock_irqsave(&res_lock, flags);
-
-                       xfer = ch->xfer_head;
-               }
-       }
-
-ctrl_exit:
-       spin_unlock_irqrestore(&res_lock, flags);
-
-       return ret;
-}
-EXPORT_SYMBOL(s3c2410_dma_ctrl);
-
-int s3c2410_dma_enqueue(enum dma_ch id, void *token,
-                       dma_addr_t addr, int size)
-{
-       struct s3c_pl330_chan *ch;
-       struct s3c_pl330_xfer *xfer;
-       unsigned long flags;
-       int idx, ret = 0;
-
-       spin_lock_irqsave(&res_lock, flags);
-
-       ch = id_to_chan(id);
-
-       /* Error if invalid or free channel */
-       if (!ch || chan_free(ch)) {
-               ret = -EINVAL;
-               goto enq_exit;
-       }
-
-       /* Error if size is unaligned */
-       if (ch->rqcfg.brst_size && size % (1 << ch->rqcfg.brst_size)) {
-               ret = -EINVAL;
-               goto enq_exit;
-       }
-
-       xfer = kmem_cache_alloc(ch->dmac->kmcache, GFP_ATOMIC);
-       if (!xfer) {
-               ret = -ENOMEM;
-               goto enq_exit;
-       }
-
-       xfer->token = token;
-       xfer->chan = ch;
-       xfer->px.bytes = size;
-       xfer->px.next = NULL; /* Single request */
-
-       /* For S3C DMA API, direction is always fixed for all xfers */
-       if (ch->req[0].rqtype == MEMTODEV) {
-               xfer->px.src_addr = addr;
-               xfer->px.dst_addr = ch->sdaddr;
-       } else {
-               xfer->px.src_addr = ch->sdaddr;
-               xfer->px.dst_addr = addr;
-       }
-
-       add_to_queue(ch, xfer, 0);
-
-       /* Try submitting on either request */
-       idx = (ch->lrq == &ch->req[0]) ? 1 : 0;
-
-       if (!ch->req[idx].x)
-               s3c_pl330_submit(ch, &ch->req[idx]);
-       else
-               s3c_pl330_submit(ch, &ch->req[1 - idx]);
-
-       spin_unlock_irqrestore(&res_lock, flags);
-
-       if (ch->options & S3C2410_DMAF_AUTOSTART)
-               s3c2410_dma_ctrl(id, S3C2410_DMAOP_START);
-
-       return 0;
-
-enq_exit:
-       spin_unlock_irqrestore(&res_lock, flags);
-
-       return ret;
-}
-EXPORT_SYMBOL(s3c2410_dma_enqueue);
-
-int s3c2410_dma_request(enum dma_ch id,
-                       struct s3c2410_dma_client *client,
-                       void *dev)
-{
-       struct s3c_pl330_dmac *dmac;
-       struct s3c_pl330_chan *ch;
-       unsigned long flags;
-       int ret = 0;
-
-       spin_lock_irqsave(&res_lock, flags);
-
-       ch = chan_acquire(id);
-       if (!ch) {
-               ret = -EBUSY;
-               goto req_exit;
-       }
-
-       dmac = ch->dmac;
-
-       ch->pl330_chan_id = pl330_request_channel(dmac->pi);
-       if (!ch->pl330_chan_id) {
-               chan_release(ch);
-               ret = -EBUSY;
-               goto req_exit;
-       }
-
-       ch->client = client;
-       ch->options = 0; /* Clear any option */
-       ch->callback_fn = NULL; /* Clear any callback */
-       ch->lrq = NULL;
-
-       ch->rqcfg.brst_size = 2; /* Default word size */
-       ch->rqcfg.swap = SWAP_NO;
-       ch->rqcfg.scctl = SCCTRL0; /* Noncacheable and nonbufferable */
-       ch->rqcfg.dcctl = DCCTRL0; /* Noncacheable and nonbufferable */
-       ch->rqcfg.privileged = 0;
-       ch->rqcfg.insnaccess = 0;
-
-       /* Set invalid direction */
-       ch->req[0].rqtype = DEVTODEV;
-       ch->req[1].rqtype = ch->req[0].rqtype;
-
-       ch->req[0].cfg = &ch->rqcfg;
-       ch->req[1].cfg = ch->req[0].cfg;
-
-       ch->req[0].peri = iface_of_dmac(dmac, id) - 1; /* Original index */
-       ch->req[1].peri = ch->req[0].peri;
-
-       ch->req[0].token = &ch->req[0];
-       ch->req[0].xfer_cb = s3c_pl330_rq0;
-       ch->req[1].token = &ch->req[1];
-       ch->req[1].xfer_cb = s3c_pl330_rq1;
-
-       ch->req[0].x = NULL;
-       ch->req[1].x = NULL;
-
-       /* Reset xfer list */
-       INIT_LIST_HEAD(&ch->xfer_list);
-       ch->xfer_head = NULL;
-
-req_exit:
-       spin_unlock_irqrestore(&res_lock, flags);
-
-       return ret;
-}
-EXPORT_SYMBOL(s3c2410_dma_request);
-
-int s3c2410_dma_free(enum dma_ch id, struct s3c2410_dma_client *client)
-{
-       struct s3c_pl330_chan *ch;
-       struct s3c_pl330_xfer *xfer;
-       unsigned long flags;
-       int ret = 0;
-       unsigned idx;
-
-       spin_lock_irqsave(&res_lock, flags);
-
-       ch = id_to_chan(id);
-
-       if (!ch || chan_free(ch))
-               goto free_exit;
-
-       /* Refuse if someone else wanted to free the channel */
-       if (ch->client != client) {
-               ret = -EBUSY;
-               goto free_exit;
-       }
-
-       /* Stop any active xfer, Flushe the queue and do callbacks */
-       pl330_chan_ctrl(ch->pl330_chan_id, PL330_OP_FLUSH);
-
-       /* Abort the submitted requests */
-       idx = (ch->lrq == &ch->req[0]) ? 1 : 0;
-
-       if (ch->req[idx].x) {
-               xfer = container_of(ch->req[idx].x,
-                               struct s3c_pl330_xfer, px);
-
-               ch->req[idx].x = NULL;
-               del_from_queue(xfer);
-
-               spin_unlock_irqrestore(&res_lock, flags);
-               _finish_off(xfer, S3C2410_RES_ABORT, 1);
-               spin_lock_irqsave(&res_lock, flags);
-       }
-
-       if (ch->req[1 - idx].x) {
-               xfer = container_of(ch->req[1 - idx].x,
-                               struct s3c_pl330_xfer, px);
-
-               ch->req[1 - idx].x = NULL;
-               del_from_queue(xfer);
-
-               spin_unlock_irqrestore(&res_lock, flags);
-               _finish_off(xfer, S3C2410_RES_ABORT, 1);
-               spin_lock_irqsave(&res_lock, flags);
-       }
-
-       /* Pluck and Abort the queued requests in order */
-       do {
-               xfer = get_from_queue(ch, 1);
-
-               spin_unlock_irqrestore(&res_lock, flags);
-               _finish_off(xfer, S3C2410_RES_ABORT, 1);
-               spin_lock_irqsave(&res_lock, flags);
-       } while (xfer);
-
-       ch->client = NULL;
-
-       pl330_release_channel(ch->pl330_chan_id);
-
-       ch->pl330_chan_id = NULL;
-
-       chan_release(ch);
-
-free_exit:
-       spin_unlock_irqrestore(&res_lock, flags);
-
-       return ret;
-}
-EXPORT_SYMBOL(s3c2410_dma_free);
-
-int s3c2410_dma_config(enum dma_ch id, int xferunit)
-{
-       struct s3c_pl330_chan *ch;
-       struct pl330_info *pi;
-       unsigned long flags;
-       int i, dbwidth, ret = 0;
-
-       spin_lock_irqsave(&res_lock, flags);
-
-       ch = id_to_chan(id);
-
-       if (!ch || chan_free(ch)) {
-               ret = -EINVAL;
-               goto cfg_exit;
-       }
-
-       pi = ch->dmac->pi;
-       dbwidth = pi->pcfg.data_bus_width / 8;
-
-       /* Max size of xfer can be pcfg.data_bus_width */
-       if (xferunit > dbwidth) {
-               ret = -EINVAL;
-               goto cfg_exit;
-       }
-
-       i = 0;
-       while (xferunit != (1 << i))
-               i++;
-
-       /* If valid value */
-       if (xferunit == (1 << i))
-               ch->rqcfg.brst_size = i;
-       else
-               ret = -EINVAL;
-
-cfg_exit:
-       spin_unlock_irqrestore(&res_lock, flags);
-
-       return ret;
-}
-EXPORT_SYMBOL(s3c2410_dma_config);
-
-/* Options that are supported by this driver */
-#define S3C_PL330_FLAGS (S3C2410_DMAF_CIRCULAR | S3C2410_DMAF_AUTOSTART)
-
-int s3c2410_dma_setflags(enum dma_ch id, unsigned int options)
-{
-       struct s3c_pl330_chan *ch;
-       unsigned long flags;
-       int ret = 0;
-
-       spin_lock_irqsave(&res_lock, flags);
-
-       ch = id_to_chan(id);
-
-       if (!ch || chan_free(ch) || options & ~(S3C_PL330_FLAGS))
-               ret = -EINVAL;
-       else
-               ch->options = options;
-
-       spin_unlock_irqrestore(&res_lock, flags);
-
-       return 0;
-}
-EXPORT_SYMBOL(s3c2410_dma_setflags);
-
-int s3c2410_dma_set_buffdone_fn(enum dma_ch id, s3c2410_dma_cbfn_t rtn)
-{
-       struct s3c_pl330_chan *ch;
-       unsigned long flags;
-       int ret = 0;
-
-       spin_lock_irqsave(&res_lock, flags);
-
-       ch = id_to_chan(id);
-
-       if (!ch || chan_free(ch))
-               ret = -EINVAL;
-       else
-               ch->callback_fn = rtn;
-
-       spin_unlock_irqrestore(&res_lock, flags);
-
-       return ret;
-}
-EXPORT_SYMBOL(s3c2410_dma_set_buffdone_fn);
-
-int s3c2410_dma_devconfig(enum dma_ch id, enum s3c2410_dmasrc source,
-                         unsigned long address)
-{
-       struct s3c_pl330_chan *ch;
-       unsigned long flags;
-       int ret = 0;
-
-       spin_lock_irqsave(&res_lock, flags);
-
-       ch = id_to_chan(id);
-
-       if (!ch || chan_free(ch)) {
-               ret = -EINVAL;
-               goto devcfg_exit;
-       }
-
-       switch (source) {
-       case S3C2410_DMASRC_HW: /* P->M */
-               ch->req[0].rqtype = DEVTOMEM;
-               ch->req[1].rqtype = DEVTOMEM;
-               ch->rqcfg.src_inc = 0;
-               ch->rqcfg.dst_inc = 1;
-               break;
-       case S3C2410_DMASRC_MEM: /* M->P */
-               ch->req[0].rqtype = MEMTODEV;
-               ch->req[1].rqtype = MEMTODEV;
-               ch->rqcfg.src_inc = 1;
-               ch->rqcfg.dst_inc = 0;
-               break;
-       default:
-               ret = -EINVAL;
-               goto devcfg_exit;
-       }
-
-       ch->sdaddr = address;
-
-devcfg_exit:
-       spin_unlock_irqrestore(&res_lock, flags);
-
-       return ret;
-}
-EXPORT_SYMBOL(s3c2410_dma_devconfig);
-
-int s3c2410_dma_getposition(enum dma_ch id, dma_addr_t *src, dma_addr_t *dst)
-{
-       struct s3c_pl330_chan *ch = id_to_chan(id);
-       struct pl330_chanstatus status;
-       int ret;
-
-       if (!ch || chan_free(ch))
-               return -EINVAL;
-
-       ret = pl330_chan_status(ch->pl330_chan_id, &status);
-       if (ret < 0)
-               return ret;
-
-       *src = status.src_addr;
-       *dst = status.dst_addr;
-
-       return 0;
-}
-EXPORT_SYMBOL(s3c2410_dma_getposition);
-
-static irqreturn_t pl330_irq_handler(int irq, void *data)
-{
-       if (pl330_update(data))
-               return IRQ_HANDLED;
-       else
-               return IRQ_NONE;
-}
-
-static int pl330_probe(struct platform_device *pdev)
-{
-       struct s3c_pl330_dmac *s3c_pl330_dmac;
-       struct s3c_pl330_platdata *pl330pd;
-       struct pl330_info *pl330_info;
-       struct resource *res;
-       int i, ret, irq;
-
-       pl330pd = pdev->dev.platform_data;
-
-       /* Can't do without the list of _32_ peripherals */
-       if (!pl330pd || !pl330pd->peri) {
-               dev_err(&pdev->dev, "platform data missing!\n");
-               return -ENODEV;
-       }
-
-       pl330_info = kzalloc(sizeof(*pl330_info), GFP_KERNEL);
-       if (!pl330_info)
-               return -ENOMEM;
-
-       pl330_info->pl330_data = NULL;
-       pl330_info->dev = &pdev->dev;
-
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!res) {
-               ret = -ENODEV;
-               goto probe_err1;
-       }
-
-       request_mem_region(res->start, resource_size(res), pdev->name);
-
-       pl330_info->base = ioremap(res->start, resource_size(res));
-       if (!pl330_info->base) {
-               ret = -ENXIO;
-               goto probe_err2;
-       }
-
-       irq = platform_get_irq(pdev, 0);
-       if (irq < 0) {
-               ret = irq;
-               goto probe_err3;
-       }
-
-       ret = request_irq(irq, pl330_irq_handler, 0,
-                       dev_name(&pdev->dev), pl330_info);
-       if (ret)
-               goto probe_err4;
-
-       /* Allocate a new DMAC */
-       s3c_pl330_dmac = kmalloc(sizeof(*s3c_pl330_dmac), GFP_KERNEL);
-       if (!s3c_pl330_dmac) {
-               ret = -ENOMEM;
-               goto probe_err5;
-       }
-
-       /* Get operation clock and enable it */
-       s3c_pl330_dmac->clk = clk_get(&pdev->dev, "pdma");
-       if (IS_ERR(s3c_pl330_dmac->clk)) {
-               dev_err(&pdev->dev, "Cannot get operation clock.\n");
-               ret = -EINVAL;
-               goto probe_err6;
-       }
-       clk_enable(s3c_pl330_dmac->clk);
-
-       ret = pl330_add(pl330_info);
-       if (ret)
-               goto probe_err7;
-
-       /* Hook the info */
-       s3c_pl330_dmac->pi = pl330_info;
-
-       /* No busy channels */
-       s3c_pl330_dmac->busy_chan = 0;
-
-       s3c_pl330_dmac->kmcache = kmem_cache_create(dev_name(&pdev->dev),
-                               sizeof(struct s3c_pl330_xfer), 0, 0, NULL);
-
-       if (!s3c_pl330_dmac->kmcache) {
-               ret = -ENOMEM;
-               goto probe_err8;
-       }
-
-       /* Get the list of peripherals */
-       s3c_pl330_dmac->peri = pl330pd->peri;
-
-       /* Attach to the list of DMACs */
-       list_add_tail(&s3c_pl330_dmac->node, &dmac_list);
-
-       /* Create a channel for each peripheral in the DMAC
-        * that is, if it doesn't already exist
-        */
-       for (i = 0; i < PL330_MAX_PERI; i++)
-               if (s3c_pl330_dmac->peri[i] != DMACH_MAX)
-                       chan_add(s3c_pl330_dmac->peri[i]);
-
-       printk(KERN_INFO
-               "Loaded driver for PL330 DMAC-%d %s\n", pdev->id, pdev->name);
-       printk(KERN_INFO
-               "\tDBUFF-%ux%ubytes Num_Chans-%u Num_Peri-%u Num_Events-%u\n",
-               pl330_info->pcfg.data_buf_dep,
-               pl330_info->pcfg.data_bus_width / 8, pl330_info->pcfg.num_chan,
-               pl330_info->pcfg.num_peri, pl330_info->pcfg.num_events);
-
-       return 0;
-
-probe_err8:
-       pl330_del(pl330_info);
-probe_err7:
-       clk_disable(s3c_pl330_dmac->clk);
-       clk_put(s3c_pl330_dmac->clk);
-probe_err6:
-       kfree(s3c_pl330_dmac);
-probe_err5:
-       free_irq(irq, pl330_info);
-probe_err4:
-probe_err3:
-       iounmap(pl330_info->base);
-probe_err2:
-       release_mem_region(res->start, resource_size(res));
-probe_err1:
-       kfree(pl330_info);
-
-       return ret;
-}
-
-static int pl330_remove(struct platform_device *pdev)
-{
-       struct s3c_pl330_dmac *dmac, *d;
-       struct s3c_pl330_chan *ch;
-       unsigned long flags;
-       int del, found;
-
-       if (!pdev->dev.platform_data)
-               return -EINVAL;
-
-       spin_lock_irqsave(&res_lock, flags);
-
-       found = 0;
-       list_for_each_entry(d, &dmac_list, node)
-               if (d->pi->dev == &pdev->dev) {
-                       found = 1;
-                       break;
-               }
-
-       if (!found) {
-               spin_unlock_irqrestore(&res_lock, flags);
-               return 0;
-       }
-
-       dmac = d;
-
-       /* Remove all Channels that are managed only by this DMAC */
-       list_for_each_entry(ch, &chan_list, node) {
-
-               /* Only channels that are handled by this DMAC */
-               if (iface_of_dmac(dmac, ch->id))
-                       del = 1;
-               else
-                       continue;
-
-               /* Don't remove if some other DMAC has it too */
-               list_for_each_entry(d, &dmac_list, node)
-                       if (d != dmac && iface_of_dmac(d, ch->id)) {
-                               del = 0;
-                               break;
-                       }
-
-               if (del) {
-                       spin_unlock_irqrestore(&res_lock, flags);
-                       s3c2410_dma_free(ch->id, ch->client);
-                       spin_lock_irqsave(&res_lock, flags);
-                       list_del(&ch->node);
-                       kfree(ch);
-               }
-       }
-
-       /* Disable operation clock */
-       clk_disable(dmac->clk);
-       clk_put(dmac->clk);
-
-       /* Remove the DMAC */
-       list_del(&dmac->node);
-       kfree(dmac);
-
-       spin_unlock_irqrestore(&res_lock, flags);
-
-       return 0;
-}
-
-static struct platform_driver pl330_driver = {
-       .driver         = {
-               .owner  = THIS_MODULE,
-               .name   = "s3c-pl330",
-       },
-       .probe          = pl330_probe,
-       .remove         = pl330_remove,
-};
-
-static int __init pl330_init(void)
-{
-       return platform_driver_register(&pl330_driver);
-}
-module_init(pl330_init);
-
-static void __exit pl330_exit(void)
-{
-       platform_driver_unregister(&pl330_driver);
-       return;
-}
-module_exit(pl330_exit);
-
-MODULE_AUTHOR("Jaswinder Singh <jassi.brar@samsung.com>");
-MODULE_DESCRIPTION("Driver for PL330 DMA Controller");
-MODULE_LICENSE("GPL");
index 2e3b3d38c4658b150cf1df11633d4b5aec087248..ab8f469f5cf8154a244a59759cbadac01279b1d9 100644 (file)
@@ -193,7 +193,8 @@ config ARCH_HAS_ASYNC_TX_FIND_CHANNEL
 config PL330_DMA
        tristate "DMA API Driver for PL330"
        select DMA_ENGINE
-       depends on PL330
+       depends on ARM_AMBA
+       select PL330
        help
          Select if your platform has one or more PL330 DMACs.
          You need to provide platform specific settings via
index be21e3f138a88a6317da6e40318d3dc79d9bd5e1..cd8df7f5b5c85f992f8c4fa03b986fc6e41af221 100644 (file)
  *    after the final transfer signalled by LBREQ or LSREQ.  The DMAC
  *    will then move to the next LLI entry.
  *
- * Only the former works sanely with scatter lists, so we only implement
- * the DMAC flow control method.  However, peripherals which use the LBREQ
- * and LSREQ signals (eg, MMCI) are unable to use this mode, which through
- * these hardware restrictions prevents them from using scatter DMA.
- *
  * Global TODO:
  * - Break out common code from arch/arm/mach-s3c64xx and share
  */
-#include <linux/device.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/interrupt.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-#include <linux/dma-mapping.h>
-#include <linux/dmapool.h>
-#include <linux/dmaengine.h>
 #include <linux/amba/bus.h>
 #include <linux/amba/pl08x.h>
 #include <linux/debugfs.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/dmaengine.h>
+#include <linux/dmapool.h>
+#include <linux/dma-mapping.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/pm_runtime.h>
 #include <linux/seq_file.h>
-
+#include <linux/slab.h>
 #include <asm/hardware/pl080.h>
 
 #define DRIVER_NAME    "pl08xdmac"
 
+static struct amba_driver pl08x_amba_driver;
+
 /**
  * struct vendor_data - vendor-specific config parameters for PL08x derivatives
  * @channels: the number of channels available in this variant
@@ -126,7 +123,8 @@ struct pl08x_lli {
  * @phy_chans: array of data for the physical channels
  * @pool: a pool for the LLI descriptors
  * @pool_ctr: counter of LLIs in the pool
- * @lli_buses: bitmask to or in to LLI pointer selecting AHB port for LLI fetches
+ * @lli_buses: bitmask to or in to LLI pointer selecting AHB port for LLI
+ * fetches
  * @mem_buses: set to indicate memory transfers on AHB2.
  * @lock: a spinlock for this struct
  */
@@ -149,14 +147,6 @@ struct pl08x_driver_data {
  * PL08X specific defines
  */
 
-/*
- * Memory boundaries: the manual for PL08x says that the controller
- * cannot read past a 1KiB boundary, so these defines are used to
- * create transfer LLIs that do not cross such boundaries.
- */
-#define PL08X_BOUNDARY_SHIFT           (10)    /* 1KB 0x400 */
-#define PL08X_BOUNDARY_SIZE            (1 << PL08X_BOUNDARY_SHIFT)
-
 /* Size (bytes) of each LLI buffer allocated for one transfer */
 # define PL08X_LLI_TSFR_SIZE   0x2000
 
@@ -272,7 +262,6 @@ static void pl08x_resume_phy_chan(struct pl08x_phy_chan *ch)
        writel(val, ch->base + PL080_CH_CONFIG);
 }
 
-
 /*
  * pl08x_terminate_phy_chan() stops the channel, clears the FIFO and
  * clears any pending interrupt status.  This should not be used for
@@ -407,6 +396,7 @@ pl08x_get_phy_channel(struct pl08x_driver_data *pl08x,
                return NULL;
        }
 
+       pm_runtime_get_sync(&pl08x->adev->dev);
        return ch;
 }
 
@@ -420,6 +410,8 @@ static inline void pl08x_put_phy_channel(struct pl08x_driver_data *pl08x,
        /* Stop the channel and clear its interrupts */
        pl08x_terminate_phy_chan(pl08x, ch);
 
+       pm_runtime_put(&pl08x->adev->dev);
+
        /* Mark it as free */
        ch->serving = NULL;
        spin_unlock_irqrestore(&ch->lock, flags);
@@ -499,36 +491,30 @@ struct pl08x_lli_build_data {
 };
 
 /*
- * Autoselect a master bus to use for the transfer this prefers the
- * destination bus if both available if fixed address on one bus the
- * other will be chosen
+ * Autoselect a master bus to use for the transfer. Slave will be the chosen as
+ * victim in case src & dest are not similarly aligned. i.e. If after aligning
+ * masters address with width requirements of transfer (by sending few byte by
+ * byte data), slave is still not aligned, then its width will be reduced to
+ * BYTE.
+ * - prefers the destination bus if both available
+ * - prefers bus with fixed address (i.e. peripheral)
  */
 static void pl08x_choose_master_bus(struct pl08x_lli_build_data *bd,
        struct pl08x_bus_data **mbus, struct pl08x_bus_data **sbus, u32 cctl)
 {
        if (!(cctl & PL080_CONTROL_DST_INCR)) {
-               *mbus = &bd->srcbus;
-               *sbus = &bd->dstbus;
-       } else if (!(cctl & PL080_CONTROL_SRC_INCR)) {
                *mbus = &bd->dstbus;
                *sbus = &bd->srcbus;
+       } else if (!(cctl & PL080_CONTROL_SRC_INCR)) {
+               *mbus = &bd->srcbus;
+               *sbus = &bd->dstbus;
        } else {
-               if (bd->dstbus.buswidth == 4) {
-                       *mbus = &bd->dstbus;
-                       *sbus = &bd->srcbus;
-               } else if (bd->srcbus.buswidth == 4) {
-                       *mbus = &bd->srcbus;
-                       *sbus = &bd->dstbus;
-               } else if (bd->dstbus.buswidth == 2) {
+               if (bd->dstbus.buswidth >= bd->srcbus.buswidth) {
                        *mbus = &bd->dstbus;
                        *sbus = &bd->srcbus;
-               } else if (bd->srcbus.buswidth == 2) {
+               } else {
                        *mbus = &bd->srcbus;
                        *sbus = &bd->dstbus;
-               } else {
-                       /* bd->srcbus.buswidth == 1 */
-                       *mbus = &bd->dstbus;
-                       *sbus = &bd->srcbus;
                }
        }
 }
@@ -547,7 +533,8 @@ static void pl08x_fill_lli_for_desc(struct pl08x_lli_build_data *bd,
        llis_va[num_llis].cctl = cctl;
        llis_va[num_llis].src = bd->srcbus.addr;
        llis_va[num_llis].dst = bd->dstbus.addr;
-       llis_va[num_llis].lli = llis_bus + (num_llis + 1) * sizeof(struct pl08x_lli);
+       llis_va[num_llis].lli = llis_bus + (num_llis + 1) *
+               sizeof(struct pl08x_lli);
        llis_va[num_llis].lli |= bd->lli_bus;
 
        if (cctl & PL080_CONTROL_SRC_INCR)
@@ -560,16 +547,12 @@ static void pl08x_fill_lli_for_desc(struct pl08x_lli_build_data *bd,
        bd->remainder -= len;
 }
 
-/*
- * Return number of bytes to fill to boundary, or len.
- * This calculation works for any value of addr.
- */
-static inline size_t pl08x_pre_boundary(u32 addr, size_t len)
+static inline void prep_byte_width_lli(struct pl08x_lli_build_data *bd,
+               u32 *cctl, u32 len, int num_llis, size_t *total_bytes)
 {
-       size_t boundary_len = PL08X_BOUNDARY_SIZE -
-                       (addr & (PL08X_BOUNDARY_SIZE - 1));
-
-       return min(boundary_len, len);
+       *cctl = pl08x_cctl_bits(*cctl, 1, 1, len);
+       pl08x_fill_lli_for_desc(bd, num_llis, len, *cctl);
+       (*total_bytes) += len;
 }
 
 /*
@@ -583,13 +566,11 @@ static int pl08x_fill_llis_for_desc(struct pl08x_driver_data *pl08x,
        struct pl08x_bus_data *mbus, *sbus;
        struct pl08x_lli_build_data bd;
        int num_llis = 0;
-       u32 cctl;
-       size_t max_bytes_per_lli;
-       size_t total_bytes = 0;
+       u32 cctl, early_bytes = 0;
+       size_t max_bytes_per_lli, total_bytes = 0;
        struct pl08x_lli *llis_va;
 
-       txd->llis_va = dma_pool_alloc(pl08x->pool, GFP_NOWAIT,
-                                     &txd->llis_bus);
+       txd->llis_va = dma_pool_alloc(pl08x->pool, GFP_NOWAIT, &txd->llis_bus);
        if (!txd->llis_va) {
                dev_err(&pl08x->adev->dev, "%s no memory for llis\n", __func__);
                return 0;
@@ -619,55 +600,85 @@ static int pl08x_fill_llis_for_desc(struct pl08x_driver_data *pl08x,
        bd.srcbus.buswidth = bd.srcbus.maxwidth;
        bd.dstbus.buswidth = bd.dstbus.maxwidth;
 
-       /*
-        * Bytes transferred == tsize * MIN(buswidths), not max(buswidths)
-        */
-       max_bytes_per_lli = min(bd.srcbus.buswidth, bd.dstbus.buswidth) *
-               PL080_CONTROL_TRANSFER_SIZE_MASK;
-
        /* We need to count this down to zero */
        bd.remainder = txd->len;
 
-       /*
-        * Choose bus to align to
-        * - prefers destination bus if both available
-        * - if fixed address on one bus chooses other
-        */
        pl08x_choose_master_bus(&bd, &mbus, &sbus, cctl);
 
-       dev_vdbg(&pl08x->adev->dev, "src=0x%08x%s/%u dst=0x%08x%s/%u len=%zu llimax=%zu\n",
+       dev_vdbg(&pl08x->adev->dev, "src=0x%08x%s/%u dst=0x%08x%s/%u len=%zu\n",
                 bd.srcbus.addr, cctl & PL080_CONTROL_SRC_INCR ? "+" : "",
                 bd.srcbus.buswidth,
                 bd.dstbus.addr, cctl & PL080_CONTROL_DST_INCR ? "+" : "",
                 bd.dstbus.buswidth,
-                bd.remainder, max_bytes_per_lli);
+                bd.remainder);
        dev_vdbg(&pl08x->adev->dev, "mbus=%s sbus=%s\n",
                 mbus == &bd.srcbus ? "src" : "dst",
                 sbus == &bd.srcbus ? "src" : "dst");
 
-       if (txd->len < mbus->buswidth) {
-               /* Less than a bus width available - send as single bytes */
-               while (bd.remainder) {
-                       dev_vdbg(&pl08x->adev->dev,
-                                "%s single byte LLIs for a transfer of "
-                                "less than a bus width (remain 0x%08x)\n",
-                                __func__, bd.remainder);
-                       cctl = pl08x_cctl_bits(cctl, 1, 1, 1);
-                       pl08x_fill_lli_for_desc(&bd, num_llis++, 1, cctl);
-                       total_bytes++;
+       /*
+        * Zero length is only allowed if all these requirements are met:
+        * - flow controller is peripheral.
+        * - src.addr is aligned to src.width
+        * - dst.addr is aligned to dst.width
+        *
+        * sg_len == 1 should be true, as there can be two cases here:
+        * - Memory addresses are contiguous and are not scattered. Here, Only
+        * one sg will be passed by user driver, with memory address and zero
+        * length. We pass this to controller and after the transfer it will
+        * receive the last burst request from peripheral and so transfer
+        * finishes.
+        *
+        * - Memory addresses are scattered and are not contiguous. Here,
+        * Obviously as DMA controller doesn't know when a lli's transfer gets
+        * over, it can't load next lli. So in this case, there has to be an
+        * assumption that only one lli is supported. Thus, we can't have
+        * scattered addresses.
+        */
+       if (!bd.remainder) {
+               u32 fc = (txd->ccfg & PL080_CONFIG_FLOW_CONTROL_MASK) >>
+                       PL080_CONFIG_FLOW_CONTROL_SHIFT;
+               if (!((fc >= PL080_FLOW_SRC2DST_DST) &&
+                                       (fc <= PL080_FLOW_SRC2DST_SRC))) {
+                       dev_err(&pl08x->adev->dev, "%s sg len can't be zero",
+                               __func__);
+                       return 0;
                }
-       } else {
-               /* Make one byte LLIs until master bus is aligned */
-               while ((mbus->addr) % (mbus->buswidth)) {
-                       dev_vdbg(&pl08x->adev->dev,
-                               "%s adjustment lli for less than bus width "
-                                "(remain 0x%08x)\n",
-                                __func__, bd.remainder);
-                       cctl = pl08x_cctl_bits(cctl, 1, 1, 1);
-                       pl08x_fill_lli_for_desc(&bd, num_llis++, 1, cctl);
-                       total_bytes++;
+
+               if ((bd.srcbus.addr % bd.srcbus.buswidth) ||
+                               (bd.srcbus.addr % bd.srcbus.buswidth)) {
+                       dev_err(&pl08x->adev->dev,
+                               "%s src & dst address must be aligned to src"
+                               " & dst width if peripheral is flow controller",
+                               __func__);
+                       return 0;
                }
 
+               cctl = pl08x_cctl_bits(cctl, bd.srcbus.buswidth,
+                               bd.dstbus.buswidth, 0);
+               pl08x_fill_lli_for_desc(&bd, num_llis++, 0, cctl);
+       }
+
+       /*
+        * Send byte by byte for following cases
+        * - Less than a bus width available
+        * - until master bus is aligned
+        */
+       if (bd.remainder < mbus->buswidth)
+               early_bytes = bd.remainder;
+       else if ((mbus->addr) % (mbus->buswidth)) {
+               early_bytes = mbus->buswidth - (mbus->addr) % (mbus->buswidth);
+               if ((bd.remainder - early_bytes) < mbus->buswidth)
+                       early_bytes = bd.remainder;
+       }
+
+       if (early_bytes) {
+               dev_vdbg(&pl08x->adev->dev, "%s byte width LLIs "
+                               "(remain 0x%08x)\n", __func__, bd.remainder);
+               prep_byte_width_lli(&bd, &cctl, early_bytes, num_llis++,
+                               &total_bytes);
+       }
+
+       if (bd.remainder) {
                /*
                 * Master now aligned
                 * - 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,
                        sbus->buswidth = 1;
                }
 
+               /* Bytes transferred = tsize * src width, not MIN(buswidths) */
+               max_bytes_per_lli = bd.srcbus.buswidth *
+                       PL080_CONTROL_TRANSFER_SIZE_MASK;
+
                /*
                 * Make largest possible LLIs until less than one bus
                 * width left
                 */
                while (bd.remainder > (mbus->buswidth - 1)) {
-                       size_t lli_len, target_len, tsize, odd_bytes;
+                       size_t lli_len, tsize, width;
 
                        /*
                         * If enough left try to send max possible,
                         * otherwise try to send the remainder
                         */
-                       target_len = min(bd.remainder, max_bytes_per_lli);
+                       lli_len = min(bd.remainder, max_bytes_per_lli);
 
                        /*
-                        * Set bus lengths for incrementing buses to the
-                        * number of bytes which fill to next memory boundary,
-                        * limiting on the target length calculated above.
+                        * Check against maximum bus alignment: Calculate actual
+                        * transfer size in relation to bus width and get a
+                        * maximum remainder of the highest bus width - 1
                         */
-                       if (cctl & PL080_CONTROL_SRC_INCR)
-                               bd.srcbus.fill_bytes =
-                                       pl08x_pre_boundary(bd.srcbus.addr,
-                                               target_len);
-                       else
-                               bd.srcbus.fill_bytes = target_len;
-
-                       if (cctl & PL080_CONTROL_DST_INCR)
-                               bd.dstbus.fill_bytes =
-                                       pl08x_pre_boundary(bd.dstbus.addr,
-                                               target_len);
-                       else
-                               bd.dstbus.fill_bytes = target_len;
-
-                       /* Find the nearest */
-                       lli_len = min(bd.srcbus.fill_bytes,
-                                     bd.dstbus.fill_bytes);
-
-                       BUG_ON(lli_len > bd.remainder);
-
-                       if (lli_len <= 0) {
-                               dev_err(&pl08x->adev->dev,
-                                       "%s lli_len is %zu, <= 0\n",
-                                               __func__, lli_len);
-                               return 0;
-                       }
-
-                       if (lli_len == target_len) {
-                               /*
-                                * Can send what we wanted.
-                                * Maintain alignment
-                                */
-                               lli_len = (lli_len/mbus->buswidth) *
-                                                       mbus->buswidth;
-                               odd_bytes = 0;
-                       } else {
-                               /*
-                                * So now we know how many bytes to transfer
-                                * to get to the nearest boundary.  The next
-                                * LLI will past the boundary.  However, we
-                                * may be working to a boundary on the slave
-                                * bus.  We need to ensure the master stays
-                                * aligned, and that we are working in
-                                * multiples of the bus widths.
-                                */
-                               odd_bytes = lli_len % mbus->buswidth;
-                               lli_len -= odd_bytes;
-
-                       }
-
-                       if (lli_len) {
-                               /*
-                                * Check against minimum bus alignment:
-                                * Calculate actual transfer size in relation
-                                * to bus width an get a maximum remainder of
-                                * the smallest bus width - 1
-                                */
-                               /* FIXME: use round_down()? */
-                               tsize = lli_len / min(mbus->buswidth,
-                                                     sbus->buswidth);
-                               lli_len = tsize * min(mbus->buswidth,
-                                                     sbus->buswidth);
-
-                               if (target_len != lli_len) {
-                                       dev_vdbg(&pl08x->adev->dev,
-                                       "%s can't send what we want. Desired 0x%08zx, lli of 0x%08zx bytes in txd of 0x%08zx\n",
-                                       __func__, target_len, lli_len, txd->len);
-                               }
-
-                               cctl = pl08x_cctl_bits(cctl,
-                                                      bd.srcbus.buswidth,
-                                                      bd.dstbus.buswidth,
-                                                      tsize);
-
-                               dev_vdbg(&pl08x->adev->dev,
-                                       "%s fill lli with single lli chunk of size 0x%08zx (remainder 0x%08zx)\n",
-                                       __func__, lli_len, bd.remainder);
-                               pl08x_fill_lli_for_desc(&bd, num_llis++,
-                                       lli_len, cctl);
-                               total_bytes += lli_len;
-                       }
+                       width = max(mbus->buswidth, sbus->buswidth);
+                       lli_len = (lli_len / width) * width;
+                       tsize = lli_len / bd.srcbus.buswidth;
 
-
-                       if (odd_bytes) {
-                               /*
-                                * Creep past the boundary, maintaining
-                                * master alignment
-                                */
-                               int j;
-                               for (j = 0; (j < mbus->buswidth)
-                                               && (bd.remainder); j++) {
-                                       cctl = pl08x_cctl_bits(cctl, 1, 1, 1);
-                                       dev_vdbg(&pl08x->adev->dev,
-                                               "%s align with boundary, single byte (remain 0x%08zx)\n",
-                                               __func__, bd.remainder);
-                                       pl08x_fill_lli_for_desc(&bd,
-                                               num_llis++, 1, cctl);
-                                       total_bytes++;
-                               }
-                       }
+                       dev_vdbg(&pl08x->adev->dev,
+                               "%s fill lli with single lli chunk of "
+                               "size 0x%08zx (remainder 0x%08zx)\n",
+                               __func__, lli_len, bd.remainder);
+
+                       cctl = pl08x_cctl_bits(cctl, bd.srcbus.buswidth,
+                                       bd.dstbus.buswidth, tsize);
+                       pl08x_fill_lli_for_desc(&bd, num_llis++, lli_len, cctl);
+                       total_bytes += lli_len;
                }
 
                /*
                 * Send any odd bytes
                 */
-               while (bd.remainder) {
-                       cctl = pl08x_cctl_bits(cctl, 1, 1, 1);
+               if (bd.remainder) {
                        dev_vdbg(&pl08x->adev->dev,
-                               "%s align with boundary, single odd byte (remain %zu)\n",
+                               "%s align with boundary, send odd bytes (remain %zu)\n",
                                __func__, bd.remainder);
-                       pl08x_fill_lli_for_desc(&bd, num_llis++, 1, cctl);
-                       total_bytes++;
+                       prep_byte_width_lli(&bd, &cctl, bd.remainder,
+                                       num_llis++, &total_bytes);
                }
        }
+
        if (total_bytes != txd->len) {
                dev_err(&pl08x->adev->dev,
                        "%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,
         * need, but for slaves the physical signals may be muxed!
         * Can the platform allow us to use this channel?
         */
-       if (plchan->slave &&
-           ch->signal < 0 &&
-           pl08x->pd->get_signal) {
+       if (plchan->slave && pl08x->pd->get_signal) {
                ret = pl08x->pd->get_signal(plchan);
                if (ret < 0) {
                        dev_dbg(&pl08x->adev->dev,
@@ -1008,10 +934,8 @@ static struct dma_async_tx_descriptor *pl08x_prep_dma_interrupt(
  * If slaves are relying on interrupts to signal completion this function
  * must not be called with interrupts disabled.
  */
-static enum dma_status
-pl08x_dma_tx_status(struct dma_chan *chan,
-                   dma_cookie_t cookie,
-                   struct dma_tx_state *txstate)
+static enum dma_status pl08x_dma_tx_status(struct dma_chan *chan,
+               dma_cookie_t cookie, struct dma_tx_state *txstate)
 {
        struct pl08x_dma_chan *plchan = to_pl08x_chan(chan);
        dma_cookie_t last_used;
@@ -1253,7 +1177,9 @@ static int pl08x_prep_channel_resources(struct pl08x_dma_chan *plchan,
 
        num_llis = pl08x_fill_llis_for_desc(pl08x, txd);
        if (!num_llis) {
-               kfree(txd);
+               spin_lock_irqsave(&plchan->lock, flags);
+               pl08x_free_txd(pl08x, txd);
+               spin_unlock_irqrestore(&plchan->lock, flags);
                return -EINVAL;
        }
 
@@ -1301,7 +1227,7 @@ static int pl08x_prep_channel_resources(struct pl08x_dma_chan *plchan,
 static struct pl08x_txd *pl08x_get_txd(struct pl08x_dma_chan *plchan,
        unsigned long flags)
 {
-       struct pl08x_txd *txd = kzalloc(sizeof(struct pl08x_txd), GFP_NOWAIT);
+       struct pl08x_txd *txd = kzalloc(sizeof(*txd), GFP_NOWAIT);
 
        if (txd) {
                dma_async_tx_descriptor_init(&txd->tx, &plchan->chan);
@@ -1367,7 +1293,7 @@ static struct dma_async_tx_descriptor *pl08x_prep_slave_sg(
        struct pl08x_dma_chan *plchan = to_pl08x_chan(chan);
        struct pl08x_driver_data *pl08x = plchan->host;
        struct pl08x_txd *txd;
-       int ret;
+       int ret, tmp;
 
        /*
         * Current implementation ASSUMES only one sg
@@ -1401,12 +1327,10 @@ static struct dma_async_tx_descriptor *pl08x_prep_slave_sg(
        txd->len = sgl->length;
 
        if (direction == DMA_TO_DEVICE) {
-               txd->ccfg |= PL080_FLOW_MEM2PER << PL080_CONFIG_FLOW_CONTROL_SHIFT;
                txd->cctl = plchan->dst_cctl;
                txd->src_addr = sgl->dma_address;
                txd->dst_addr = plchan->dst_addr;
        } else if (direction == DMA_FROM_DEVICE) {
-               txd->ccfg |= PL080_FLOW_PER2MEM << PL080_CONFIG_FLOW_CONTROL_SHIFT;
                txd->cctl = plchan->src_cctl;
                txd->src_addr = plchan->src_addr;
                txd->dst_addr = sgl->dma_address;
@@ -1416,6 +1340,15 @@ static struct dma_async_tx_descriptor *pl08x_prep_slave_sg(
                return NULL;
        }
 
+       if (plchan->cd->device_fc)
+               tmp = (direction == DMA_TO_DEVICE) ? PL080_FLOW_MEM2PER_PER :
+                       PL080_FLOW_PER2MEM_PER;
+       else
+               tmp = (direction == DMA_TO_DEVICE) ? PL080_FLOW_MEM2PER :
+                       PL080_FLOW_PER2MEM;
+
+       txd->ccfg |= tmp << PL080_CONFIG_FLOW_CONTROL_SHIFT;
+
        ret = pl08x_prep_channel_resources(plchan, txd);
        if (ret)
                return NULL;
@@ -1489,9 +1422,15 @@ static int pl08x_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
 
 bool pl08x_filter_id(struct dma_chan *chan, void *chan_id)
 {
-       struct pl08x_dma_chan *plchan = to_pl08x_chan(chan);
+       struct pl08x_dma_chan *plchan;
        char *name = chan_id;
 
+       /* Reject channels for devices not bound to this driver */
+       if (chan->device->dev->driver != &pl08x_amba_driver.drv)
+               return false;
+
+       plchan = to_pl08x_chan(chan);
+
        /* Check that the channel is not taken! */
        if (!strcmp(plchan->name, name))
                return true;
@@ -1507,13 +1446,7 @@ bool pl08x_filter_id(struct dma_chan *chan, void *chan_id)
  */
 static void pl08x_ensure_on(struct pl08x_driver_data *pl08x)
 {
-       u32 val;
-
-       val = readl(pl08x->base + PL080_CONFIG);
-       val &= ~(PL080_CONFIG_M2_BE | PL080_CONFIG_M1_BE | PL080_CONFIG_ENABLE);
-       /* We implicitly clear bit 1 and that means little-endian mode */
-       val |= PL080_CONFIG_ENABLE;
-       writel(val, pl08x->base + PL080_CONFIG);
+       writel(PL080_CONFIG_ENABLE, pl08x->base + PL080_CONFIG);
 }
 
 static void pl08x_unmap_buffers(struct pl08x_txd *txd)
@@ -1589,8 +1522,8 @@ static void pl08x_tasklet(unsigned long data)
                 */
                list_for_each_entry(waiting, &pl08x->memcpy.channels,
                                    chan.device_node) {
-                 if (waiting->state == PL08X_CHAN_WAITING &&
-                           waiting->waiting != NULL) {
+                       if (waiting->state == PL08X_CHAN_WAITING &&
+                               waiting->waiting != NULL) {
                                int ret;
 
                                /* This should REALLY not fail now */
@@ -1630,38 +1563,40 @@ static void pl08x_tasklet(unsigned long data)
 static irqreturn_t pl08x_irq(int irq, void *dev)
 {
        struct pl08x_driver_data *pl08x = dev;
-       u32 mask = 0;
-       u32 val;
-       int i;
-
-       val = readl(pl08x->base + PL080_ERR_STATUS);
-       if (val) {
-               /* An error interrupt (on one or more channels) */
-               dev_err(&pl08x->adev->dev,
-                       "%s error interrupt, register value 0x%08x\n",
-                               __func__, val);
-               /*
-                * Simply clear ALL PL08X error interrupts,
-                * regardless of channel and cause
-                * FIXME: should be 0x00000003 on PL081 really.
-                */
-               writel(0x000000FF, pl08x->base + PL080_ERR_CLEAR);
+       u32 mask = 0, err, tc, i;
+
+       /* check & clear - ERR & TC interrupts */
+       err = readl(pl08x->base + PL080_ERR_STATUS);
+       if (err) {
+               dev_err(&pl08x->adev->dev, "%s error interrupt, register value 0x%08x\n",
+                       __func__, err);
+               writel(err, pl08x->base + PL080_ERR_CLEAR);
        }
-       val = readl(pl08x->base + PL080_INT_STATUS);
+       tc = readl(pl08x->base + PL080_INT_STATUS);
+       if (tc)
+               writel(tc, pl08x->base + PL080_TC_CLEAR);
+
+       if (!err && !tc)
+               return IRQ_NONE;
+
        for (i = 0; i < pl08x->vd->channels; i++) {
-               if ((1 << i) & val) {
+               if (((1 << i) & err) || ((1 << i) & tc)) {
                        /* Locate physical channel */
                        struct pl08x_phy_chan *phychan = &pl08x->phy_chans[i];
                        struct pl08x_dma_chan *plchan = phychan->serving;
 
+                       if (!plchan) {
+                               dev_err(&pl08x->adev->dev,
+                                       "%s Error TC interrupt on unused channel: 0x%08x\n",
+                                       __func__, i);
+                               continue;
+                       }
+
                        /* Schedule tasklet on this channel */
                        tasklet_schedule(&plchan->tasklet);
-
                        mask |= (1 << i);
                }
        }
-       /* Clear only the terminal interrupts on channels we processed */
-       writel(mask, pl08x->base + PL080_TC_CLEAR);
 
        return mask ? IRQ_HANDLED : IRQ_NONE;
 }
@@ -1685,9 +1620,7 @@ static void pl08x_dma_slave_init(struct pl08x_dma_chan *chan)
  * Make a local wrapper to hold required data
  */
 static int pl08x_dma_init_virtual_channels(struct pl08x_driver_data *pl08x,
-                                          struct dma_device *dmadev,
-                                          unsigned int channels,
-                                          bool slave)
+               struct dma_device *dmadev, unsigned int channels, bool slave)
 {
        struct pl08x_dma_chan *chan;
        int i;
@@ -1700,7 +1633,7 @@ static int pl08x_dma_init_virtual_channels(struct pl08x_driver_data *pl08x,
         * to cope with that situation.
         */
        for (i = 0; i < channels; i++) {
-               chan = kzalloc(sizeof(struct pl08x_dma_chan), GFP_KERNEL);
+               chan = kzalloc(sizeof(*chan), GFP_KERNEL);
                if (!chan) {
                        dev_err(&pl08x->adev->dev,
                                "%s no memory for channel\n", __func__);
@@ -1728,7 +1661,7 @@ static int pl08x_dma_init_virtual_channels(struct pl08x_driver_data *pl08x,
                        kfree(chan);
                        continue;
                }
-               dev_info(&pl08x->adev->dev,
+               dev_dbg(&pl08x->adev->dev,
                         "initialize virtual channel \"%s\"\n",
                         chan->name);
 
@@ -1837,9 +1770,9 @@ static const struct file_operations pl08x_debugfs_operations = {
 static void init_pl08x_debugfs(struct pl08x_driver_data *pl08x)
 {
        /* Expose a simple debugfs interface to view all clocks */
-       (void) debugfs_create_file(dev_name(&pl08x->adev->dev), S_IFREG | S_IRUGO,
-                                  NULL, pl08x,
-                                  &pl08x_debugfs_operations);
+       (void) debugfs_create_file(dev_name(&pl08x->adev->dev),
+                       S_IFREG | S_IRUGO, NULL, pl08x,
+                       &pl08x_debugfs_operations);
 }
 
 #else
@@ -1860,12 +1793,15 @@ static int pl08x_probe(struct amba_device *adev, const struct amba_id *id)
                return ret;
 
        /* Create the driver state holder */
-       pl08x = kzalloc(sizeof(struct pl08x_driver_data), GFP_KERNEL);
+       pl08x = kzalloc(sizeof(*pl08x), GFP_KERNEL);
        if (!pl08x) {
                ret = -ENOMEM;
                goto out_no_pl08x;
        }
 
+       pm_runtime_set_active(&adev->dev);
+       pm_runtime_enable(&adev->dev);
+
        /* Initialize memcpy engine */
        dma_cap_set(DMA_MEMCPY, pl08x->memcpy.cap_mask);
        pl08x->memcpy.dev = &adev->dev;
@@ -1939,7 +1875,7 @@ static int pl08x_probe(struct amba_device *adev, const struct amba_id *id)
        }
 
        /* Initialize physical channels */
-       pl08x->phy_chans = kmalloc((vd->channels * sizeof(struct pl08x_phy_chan)),
+       pl08x->phy_chans = kmalloc((vd->channels * sizeof(*pl08x->phy_chans)),
                        GFP_KERNEL);
        if (!pl08x->phy_chans) {
                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)
                spin_lock_init(&ch->lock);
                ch->serving = NULL;
                ch->signal = -1;
-               dev_info(&adev->dev,
-                        "physical channel %d is %s\n", i,
-                        pl08x_phy_channel_busy(ch) ? "BUSY" : "FREE");
+               dev_dbg(&adev->dev, "physical channel %d is %s\n",
+                       i, pl08x_phy_channel_busy(ch) ? "BUSY" : "FREE");
        }
 
        /* 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)
 
        /* Register slave channels */
        ret = pl08x_dma_init_virtual_channels(pl08x, &pl08x->slave,
-                                             pl08x->pd->num_slave_channels,
-                                             true);
+                       pl08x->pd->num_slave_channels, true);
        if (ret <= 0) {
                dev_warn(&pl08x->adev->dev,
                        "%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)
        dev_info(&pl08x->adev->dev, "DMA: PL%03x rev%u at 0x%08llx irq %d\n",
                 amba_part(adev), amba_rev(adev),
                 (unsigned long long)adev->res.start, adev->irq[0]);
+
+       pm_runtime_put(&adev->dev);
        return 0;
 
 out_no_slave_reg:
@@ -2023,6 +1959,9 @@ out_no_ioremap:
        dma_pool_destroy(pl08x->pool);
 out_no_lli_pool:
 out_no_platdata:
+       pm_runtime_put(&adev->dev);
+       pm_runtime_disable(&adev->dev);
+
        kfree(pl08x);
 out_no_pl08x:
        amba_release_regions(adev);
index 6a483eac7b3f2d971cabae0aceaf022a42866558..3b99dc62874b5640be9383a70657d593f9cc31e7 100644 (file)
@@ -107,10 +107,11 @@ static struct at_desc *atc_desc_get(struct at_dma_chan *atchan)
 {
        struct at_desc *desc, *_desc;
        struct at_desc *ret = NULL;
+       unsigned long flags;
        unsigned int i = 0;
        LIST_HEAD(tmp_list);
 
-       spin_lock_bh(&atchan->lock);
+       spin_lock_irqsave(&atchan->lock, flags);
        list_for_each_entry_safe(desc, _desc, &atchan->free_list, desc_node) {
                i++;
                if (async_tx_test_ack(&desc->txd)) {
@@ -121,7 +122,7 @@ static struct at_desc *atc_desc_get(struct at_dma_chan *atchan)
                dev_dbg(chan2dev(&atchan->chan_common),
                                "desc %p not ACKed\n", desc);
        }
-       spin_unlock_bh(&atchan->lock);
+       spin_unlock_irqrestore(&atchan->lock, flags);
        dev_vdbg(chan2dev(&atchan->chan_common),
                "scanned %u descriptors on freelist\n", i);
 
@@ -129,9 +130,9 @@ static struct at_desc *atc_desc_get(struct at_dma_chan *atchan)
        if (!ret) {
                ret = atc_alloc_descriptor(&atchan->chan_common, GFP_ATOMIC);
                if (ret) {
-                       spin_lock_bh(&atchan->lock);
+                       spin_lock_irqsave(&atchan->lock, flags);
                        atchan->descs_allocated++;
-                       spin_unlock_bh(&atchan->lock);
+                       spin_unlock_irqrestore(&atchan->lock, flags);
                } else {
                        dev_err(chan2dev(&atchan->chan_common),
                                        "not enough descriptors available\n");
@@ -150,8 +151,9 @@ static void atc_desc_put(struct at_dma_chan *atchan, struct at_desc *desc)
 {
        if (desc) {
                struct at_desc *child;
+               unsigned long flags;
 
-               spin_lock_bh(&atchan->lock);
+               spin_lock_irqsave(&atchan->lock, flags);
                list_for_each_entry(child, &desc->tx_list, desc_node)
                        dev_vdbg(chan2dev(&atchan->chan_common),
                                        "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)
                dev_vdbg(chan2dev(&atchan->chan_common),
                         "moving desc %p to freelist\n", desc);
                list_add(&desc->desc_node, &atchan->free_list);
-               spin_unlock_bh(&atchan->lock);
+               spin_unlock_irqrestore(&atchan->lock, flags);
        }
 }
 
@@ -299,7 +301,7 @@ atc_chain_complete(struct at_dma_chan *atchan, struct at_desc *desc)
 
        /* for cyclic transfers,
         * no need to replay callback function while stopping */
-       if (!test_bit(ATC_IS_CYCLIC, &atchan->status)) {
+       if (!atc_chan_is_cyclic(atchan)) {
                dma_async_tx_callback   callback = txd->callback;
                void                    *param = txd->callback_param;
 
@@ -471,16 +473,17 @@ static void atc_handle_cyclic(struct at_dma_chan *atchan)
 static void atc_tasklet(unsigned long data)
 {
        struct at_dma_chan *atchan = (struct at_dma_chan *)data;
+       unsigned long flags;
 
-       spin_lock(&atchan->lock);
+       spin_lock_irqsave(&atchan->lock, flags);
        if (test_and_clear_bit(ATC_IS_ERROR, &atchan->status))
                atc_handle_error(atchan);
-       else if (test_bit(ATC_IS_CYCLIC, &atchan->status))
+       else if (atc_chan_is_cyclic(atchan))
                atc_handle_cyclic(atchan);
        else
                atc_advance_work(atchan);
 
-       spin_unlock(&atchan->lock);
+       spin_unlock_irqrestore(&atchan->lock, flags);
 }
 
 static 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)
        struct at_desc          *desc = txd_to_at_desc(tx);
        struct at_dma_chan      *atchan = to_at_dma_chan(tx->chan);
        dma_cookie_t            cookie;
+       unsigned long           flags;
 
-       spin_lock_bh(&atchan->lock);
+       spin_lock_irqsave(&atchan->lock, flags);
        cookie = atc_assign_cookie(atchan, desc);
 
        if (list_empty(&atchan->active_list)) {
@@ -554,7 +558,7 @@ static dma_cookie_t atc_tx_submit(struct dma_async_tx_descriptor *tx)
                list_add_tail(&desc->desc_node, &atchan->queue);
        }
 
-       spin_unlock_bh(&atchan->lock);
+       spin_unlock_irqrestore(&atchan->lock, flags);
 
        return cookie;
 }
@@ -927,28 +931,29 @@ static int atc_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
        struct at_dma_chan      *atchan = to_at_dma_chan(chan);
        struct at_dma           *atdma = to_at_dma(chan->device);
        int                     chan_id = atchan->chan_common.chan_id;
+       unsigned long           flags;
 
        LIST_HEAD(list);
 
        dev_vdbg(chan2dev(chan), "atc_control (%d)\n", cmd);
 
        if (cmd == DMA_PAUSE) {
-               spin_lock_bh(&atchan->lock);
+               spin_lock_irqsave(&atchan->lock, flags);
 
                dma_writel(atdma, CHER, AT_DMA_SUSP(chan_id));
                set_bit(ATC_IS_PAUSED, &atchan->status);
 
-               spin_unlock_bh(&atchan->lock);
+               spin_unlock_irqrestore(&atchan->lock, flags);
        } else if (cmd == DMA_RESUME) {
-               if (!test_bit(ATC_IS_PAUSED, &atchan->status))
+               if (!atc_chan_is_paused(atchan))
                        return 0;
 
-               spin_lock_bh(&atchan->lock);
+               spin_lock_irqsave(&atchan->lock, flags);
 
                dma_writel(atdma, CHDR, AT_DMA_RES(chan_id));
                clear_bit(ATC_IS_PAUSED, &atchan->status);
 
-               spin_unlock_bh(&atchan->lock);
+               spin_unlock_irqrestore(&atchan->lock, flags);
        } else if (cmd == DMA_TERMINATE_ALL) {
                struct at_desc  *desc, *_desc;
                /*
@@ -957,7 +962,7 @@ static int atc_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
                 * channel. We still have to poll the channel enable bit due
                 * to AHB/HSB limitations.
                 */
-               spin_lock_bh(&atchan->lock);
+               spin_lock_irqsave(&atchan->lock, flags);
 
                /* disabling channel: must also remove suspend state */
                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,
                /* if channel dedicated to cyclic operations, free it */
                clear_bit(ATC_IS_CYCLIC, &atchan->status);
 
-               spin_unlock_bh(&atchan->lock);
+               spin_unlock_irqrestore(&atchan->lock, flags);
        } else {
                return -ENXIO;
        }
@@ -1004,9 +1009,10 @@ atc_tx_status(struct dma_chan *chan,
        struct at_dma_chan      *atchan = to_at_dma_chan(chan);
        dma_cookie_t            last_used;
        dma_cookie_t            last_complete;
+       unsigned long           flags;
        enum dma_status         ret;
 
-       spin_lock_bh(&atchan->lock);
+       spin_lock_irqsave(&atchan->lock, flags);
 
        last_complete = atchan->completed_cookie;
        last_used = chan->cookie;
@@ -1021,7 +1027,7 @@ atc_tx_status(struct dma_chan *chan,
                ret = dma_async_is_complete(cookie, last_complete, last_used);
        }
 
-       spin_unlock_bh(&atchan->lock);
+       spin_unlock_irqrestore(&atchan->lock, flags);
 
        if (ret != DMA_SUCCESS)
                dma_set_tx_state(txstate, last_complete, last_used,
@@ -1029,7 +1035,7 @@ atc_tx_status(struct dma_chan *chan,
        else
                dma_set_tx_state(txstate, last_complete, last_used, 0);
 
-       if (test_bit(ATC_IS_PAUSED, &atchan->status))
+       if (atc_chan_is_paused(atchan))
                ret = DMA_PAUSED;
 
        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,
 static void atc_issue_pending(struct dma_chan *chan)
 {
        struct at_dma_chan      *atchan = to_at_dma_chan(chan);
+       unsigned long           flags;
 
        dev_vdbg(chan2dev(chan), "issue_pending\n");
 
        /* Not needed for cyclic transfers */
-       if (test_bit(ATC_IS_CYCLIC, &atchan->status))
+       if (atc_chan_is_cyclic(atchan))
                return;
 
-       spin_lock_bh(&atchan->lock);
+       spin_lock_irqsave(&atchan->lock, flags);
        if (!atc_chan_is_enabled(atchan)) {
                atc_advance_work(atchan);
        }
-       spin_unlock_bh(&atchan->lock);
+       spin_unlock_irqrestore(&atchan->lock, flags);
 }
 
 /**
@@ -1073,6 +1080,7 @@ static int atc_alloc_chan_resources(struct dma_chan *chan)
        struct at_dma           *atdma = to_at_dma(chan->device);
        struct at_desc          *desc;
        struct at_dma_slave     *atslave;
+       unsigned long           flags;
        int                     i;
        u32                     cfg;
        LIST_HEAD(tmp_list);
@@ -1116,11 +1124,11 @@ static int atc_alloc_chan_resources(struct dma_chan *chan)
                list_add_tail(&desc->desc_node, &tmp_list);
        }
 
-       spin_lock_bh(&atchan->lock);
+       spin_lock_irqsave(&atchan->lock, flags);
        atchan->descs_allocated = i;
        list_splice(&tmp_list, &atchan->free_list);
        atchan->completed_cookie = chan->cookie = 1;
-       spin_unlock_bh(&atchan->lock);
+       spin_unlock_irqrestore(&atchan->lock, flags);
 
        /* channel parameters */
        channel_writel(atchan, CFG, cfg);
@@ -1293,15 +1301,13 @@ static int __init at_dma_probe(struct platform_device *pdev)
        if (dma_has_cap(DMA_MEMCPY, atdma->dma_common.cap_mask))
                atdma->dma_common.device_prep_dma_memcpy = atc_prep_dma_memcpy;
 
-       if (dma_has_cap(DMA_SLAVE, atdma->dma_common.cap_mask))
+       if (dma_has_cap(DMA_SLAVE, atdma->dma_common.cap_mask)) {
                atdma->dma_common.device_prep_slave_sg = atc_prep_slave_sg;
-
-       if (dma_has_cap(DMA_CYCLIC, atdma->dma_common.cap_mask))
+               /* controller can do slave DMA: can trigger cyclic transfers */
+               dma_cap_set(DMA_CYCLIC, atdma->dma_common.cap_mask);
                atdma->dma_common.device_prep_dma_cyclic = atc_prep_dma_cyclic;
-
-       if (dma_has_cap(DMA_SLAVE, atdma->dma_common.cap_mask) ||
-           dma_has_cap(DMA_CYCLIC, atdma->dma_common.cap_mask))
                atdma->dma_common.device_control = atc_control;
+       }
 
        dma_writel(atdma, EN, AT_DMA_ENABLE);
 
@@ -1377,27 +1383,112 @@ static void at_dma_shutdown(struct platform_device *pdev)
        clk_disable(atdma->clk);
 }
 
+static int at_dma_prepare(struct device *dev)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       struct at_dma *atdma = platform_get_drvdata(pdev);
+       struct dma_chan *chan, *_chan;
+
+       list_for_each_entry_safe(chan, _chan, &atdma->dma_common.channels,
+                       device_node) {
+               struct at_dma_chan *atchan = to_at_dma_chan(chan);
+               /* wait for transaction completion (except in cyclic case) */
+               if (atc_chan_is_enabled(atchan) && !atc_chan_is_cyclic(atchan))
+                       return -EAGAIN;
+       }
+       return 0;
+}
+
+static void atc_suspend_cyclic(struct at_dma_chan *atchan)
+{
+       struct dma_chan *chan = &atchan->chan_common;
+
+       /* Channel should be paused by user
+        * do it anyway even if it is not done already */
+       if (!atc_chan_is_paused(atchan)) {
+               dev_warn(chan2dev(chan),
+               "cyclic channel not paused, should be done by channel user\n");
+               atc_control(chan, DMA_PAUSE, 0);
+       }
+
+       /* now preserve additional data for cyclic operations */
+       /* next descriptor address in the cyclic list */
+       atchan->save_dscr = channel_readl(atchan, DSCR);
+
+       vdbg_dump_regs(atchan);
+}
+
 static int at_dma_suspend_noirq(struct device *dev)
 {
        struct platform_device *pdev = to_platform_device(dev);
        struct at_dma *atdma = platform_get_drvdata(pdev);
+       struct dma_chan *chan, *_chan;
 
-       at_dma_off(platform_get_drvdata(pdev));
+       /* preserve data */
+       list_for_each_entry_safe(chan, _chan, &atdma->dma_common.channels,
+                       device_node) {
+               struct at_dma_chan *atchan = to_at_dma_chan(chan);
+
+               if (atc_chan_is_cyclic(atchan))
+                       atc_suspend_cyclic(atchan);
+               atchan->save_cfg = channel_readl(atchan, CFG);
+       }
+       atdma->save_imr = dma_readl(atdma, EBCIMR);
+
+       /* disable DMA controller */
+       at_dma_off(atdma);
        clk_disable(atdma->clk);
        return 0;
 }
 
+static void atc_resume_cyclic(struct at_dma_chan *atchan)
+{
+       struct at_dma   *atdma = to_at_dma(atchan->chan_common.device);
+
+       /* restore channel status for cyclic descriptors list:
+        * next descriptor in the cyclic list at the time of suspend */
+       channel_writel(atchan, SADDR, 0);
+       channel_writel(atchan, DADDR, 0);
+       channel_writel(atchan, CTRLA, 0);
+       channel_writel(atchan, CTRLB, 0);
+       channel_writel(atchan, DSCR, atchan->save_dscr);
+       dma_writel(atdma, CHER, atchan->mask);
+
+       /* channel pause status should be removed by channel user
+        * We cannot take the initiative to do it here */
+
+       vdbg_dump_regs(atchan);
+}
+
 static int at_dma_resume_noirq(struct device *dev)
 {
        struct platform_device *pdev = to_platform_device(dev);
        struct at_dma *atdma = platform_get_drvdata(pdev);
+       struct dma_chan *chan, *_chan;
 
+       /* bring back DMA controller */
        clk_enable(atdma->clk);
        dma_writel(atdma, EN, AT_DMA_ENABLE);
+
+       /* clear any pending interrupt */
+       while (dma_readl(atdma, EBCISR))
+               cpu_relax();
+
+       /* restore saved data */
+       dma_writel(atdma, EBCIER, atdma->save_imr);
+       list_for_each_entry_safe(chan, _chan, &atdma->dma_common.channels,
+                       device_node) {
+               struct at_dma_chan *atchan = to_at_dma_chan(chan);
+
+               channel_writel(atchan, CFG, atchan->save_cfg);
+               if (atc_chan_is_cyclic(atchan))
+                       atc_resume_cyclic(atchan);
+       }
        return 0;
 }
 
 static const struct dev_pm_ops at_dma_dev_pm_ops = {
+       .prepare = at_dma_prepare,
        .suspend_noirq = at_dma_suspend_noirq,
        .resume_noirq = at_dma_resume_noirq,
 };
index 087dbf1dd39cc0d87416e24e093ca7841a714b3f..aa4c9aebab7cedec68a42aececeb218aaea0208b 100644 (file)
@@ -204,6 +204,9 @@ enum atc_status {
  * @status: transmit status information from irq/prep* functions
  *                to tasklet (use atomic operations)
  * @tasklet: bottom half to finish transaction work
+ * @save_cfg: configuration register that is saved on suspend/resume cycle
+ * @save_dscr: for cyclic operations, preserve next descriptor address in
+ *             the cyclic list on suspend/resume cycle
  * @lock: serializes enqueue/dequeue operations to descriptors lists
  * @completed_cookie: identifier for the most recently completed operation
  * @active_list: list of descriptors dmaengine is being running on
@@ -218,6 +221,8 @@ struct at_dma_chan {
        u8                      mask;
        unsigned long           status;
        struct tasklet_struct   tasklet;
+       u32                     save_cfg;
+       u32                     save_dscr;
 
        spinlock_t              lock;
 
@@ -248,6 +253,7 @@ static inline struct at_dma_chan *to_at_dma_chan(struct dma_chan *dchan)
  * @chan_common: common dmaengine dma_device object members
  * @ch_regs: memory mapped register base
  * @clk: dma controller clock
+ * @save_imr: interrupt mask register that is saved on suspend/resume cycle
  * @all_chan_mask: all channels availlable in a mask
  * @dma_desc_pool: base of DMA descriptor region (DMA address)
  * @chan: channels table to store at_dma_chan structures
@@ -256,6 +262,7 @@ struct at_dma {
        struct dma_device       dma_common;
        void __iomem            *regs;
        struct clk              *clk;
+       u32                     save_imr;
 
        u8                      all_chan_mask;
 
@@ -355,6 +362,23 @@ static inline int atc_chan_is_enabled(struct at_dma_chan *atchan)
        return !!(dma_readl(atdma, CHSR) & atchan->mask);
 }
 
+/**
+ * atc_chan_is_paused - test channel pause/resume status
+ * @atchan: channel we want to test status
+ */
+static inline int atc_chan_is_paused(struct at_dma_chan *atchan)
+{
+       return test_bit(ATC_IS_PAUSED, &atchan->status);
+}
+
+/**
+ * atc_chan_is_cyclic - test if given channel has cyclic property set
+ * @atchan: channel we want to test status
+ */
+static inline int atc_chan_is_cyclic(struct at_dma_chan *atchan)
+{
+       return test_bit(ATC_IS_CYCLIC, &atchan->status);
+}
 
 /**
  * set_desc_eol - set end-of-link to descriptor so it will end transfer
index 765f5ff22304348aa629b5857a02397f93dea8ce..eb1d8641cf5cc6b4bba303a68a9c79eb39f17dd0 100644 (file)
@@ -10,6 +10,7 @@
 #include <linux/delay.h>
 #include <linux/dma-mapping.h>
 #include <linux/dmaengine.h>
+#include <linux/freezer.h>
 #include <linux/init.h>
 #include <linux/kthread.h>
 #include <linux/module.h>
@@ -251,6 +252,7 @@ static int dmatest_func(void *data)
        int                     i;
 
        thread_name = current->comm;
+       set_freezable_with_signal();
 
        ret = -ENOMEM;
 
@@ -305,7 +307,8 @@ static int dmatest_func(void *data)
                dma_addr_t dma_srcs[src_cnt];
                dma_addr_t dma_dsts[dst_cnt];
                struct completion cmp;
-               unsigned long tmo = msecs_to_jiffies(timeout);
+               unsigned long start, tmo, end = 0 /* compiler... */;
+               bool reload = true;
                u8 align = 0;
 
                total_tests++;
@@ -404,7 +407,17 @@ static int dmatest_func(void *data)
                }
                dma_async_issue_pending(chan);
 
-               tmo = wait_for_completion_timeout(&cmp, tmo);
+               do {
+                       start = jiffies;
+                       if (reload)
+                               end = start + msecs_to_jiffies(timeout);
+                       else if (end <= start)
+                               end = start + 1;
+                       tmo = wait_for_completion_interruptible_timeout(&cmp,
+                                                               end - start);
+                       reload = try_to_freeze();
+               } while (tmo == -ERESTARTSYS);
+
                status = dma_async_is_tx_complete(chan, cookie, NULL, NULL);
 
                if (tmo == 0) {
@@ -477,6 +490,8 @@ err_srcs:
        pr_notice("%s: terminating after %u tests, %u failures (status %d)\n",
                        thread_name, total_tests, failed_tests, ret);
 
+       /* terminate all transfers on specified channels */
+       chan->device->device_control(chan, DMA_TERMINATE_ALL, 0);
        if (iterations > 0)
                while (!kthread_should_stop()) {
                        DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wait_dmatest_exit);
@@ -499,6 +514,10 @@ static void dmatest_cleanup_channel(struct dmatest_chan *dtc)
                list_del(&thread->node);
                kfree(thread);
        }
+
+       /* terminate all transfers on specified channels */
+       dtc->chan->device->device_control(dtc->chan, DMA_TERMINATE_ALL, 0);
+
        kfree(dtc);
 }
 
index 7bd7e98548cd34e495910f093ee44e821c1de67b..b5cc27dc9a51d20c87b7648b093d6450e28fe00d 100644 (file)
@@ -318,6 +318,7 @@ struct sdma_engine {
        dma_addr_t                      context_phys;
        struct dma_device               dma_device;
        struct clk                      *clk;
+       struct mutex                    channel_0_lock;
        struct sdma_script_start_addrs  *script_addrs;
 };
 
@@ -415,11 +416,15 @@ static int sdma_load_script(struct sdma_engine *sdma, void *buf, int size,
        dma_addr_t buf_phys;
        int ret;
 
+       mutex_lock(&sdma->channel_0_lock);
+
        buf_virt = dma_alloc_coherent(NULL,
                        size,
                        &buf_phys, GFP_KERNEL);
-       if (!buf_virt)
-               return -ENOMEM;
+       if (!buf_virt) {
+               ret = -ENOMEM;
+               goto err_out;
+       }
 
        bd0->mode.command = C0_SETPM;
        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,
 
        dma_free_coherent(NULL, size, buf_virt, buf_phys);
 
+err_out:
+       mutex_unlock(&sdma->channel_0_lock);
+
        return ret;
 }
 
@@ -656,6 +664,8 @@ static int sdma_load_context(struct sdma_channel *sdmac)
        dev_dbg(sdma->dev, "event_mask0 = 0x%08x\n", sdmac->event_mask0);
        dev_dbg(sdma->dev, "event_mask1 = 0x%08x\n", sdmac->event_mask1);
 
+       mutex_lock(&sdma->channel_0_lock);
+
        memset(context, 0, sizeof(*context));
        context->channel_state.pc = load_address;
 
@@ -676,6 +686,8 @@ static int sdma_load_context(struct sdma_channel *sdmac)
 
        ret = sdma_run_channel(&sdma->channel[0]);
 
+       mutex_unlock(&sdma->channel_0_lock);
+
        return ret;
 }
 
@@ -1131,18 +1143,17 @@ static void sdma_add_scripts(struct sdma_engine *sdma,
                        saddr_arr[i] = addr_arr[i];
 }
 
-static int __init sdma_get_firmware(struct sdma_engine *sdma,
-               const char *fw_name)
+static void sdma_load_firmware(const struct firmware *fw, void *context)
 {
-       const struct firmware *fw;
+       struct sdma_engine *sdma = context;
        const struct sdma_firmware_header *header;
-       int ret;
        const struct sdma_script_start_addrs *addr;
        unsigned short *ram_code;
 
-       ret = request_firmware(&fw, fw_name, sdma->dev);
-       if (ret)
-               return ret;
+       if (!fw) {
+               dev_err(sdma->dev, "firmware not found\n");
+               return;
+       }
 
        if (fw->size < sizeof(*header))
                goto err_firmware;
@@ -1172,6 +1183,16 @@ static int __init sdma_get_firmware(struct sdma_engine *sdma,
 
 err_firmware:
        release_firmware(fw);
+}
+
+static int __init sdma_get_firmware(struct sdma_engine *sdma,
+               const char *fw_name)
+{
+       int ret;
+
+       ret = request_firmware_nowait(THIS_MODULE,
+                       FW_ACTION_HOTPLUG, fw_name, sdma->dev,
+                       GFP_KERNEL, sdma, sdma_load_firmware);
 
        return ret;
 }
@@ -1269,11 +1290,14 @@ static int __init sdma_probe(struct platform_device *pdev)
        struct sdma_platform_data *pdata = pdev->dev.platform_data;
        int i;
        struct sdma_engine *sdma;
+       s32 *saddr_arr;
 
        sdma = kzalloc(sizeof(*sdma), GFP_KERNEL);
        if (!sdma)
                return -ENOMEM;
 
+       mutex_init(&sdma->channel_0_lock);
+
        sdma->dev = &pdev->dev;
 
        iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -1310,6 +1334,11 @@ static int __init sdma_probe(struct platform_device *pdev)
                goto err_alloc;
        }
 
+       /* initially no scripts available */
+       saddr_arr = (s32 *)sdma->script_addrs;
+       for (i = 0; i < SDMA_SCRIPT_ADDRS_ARRAY_SIZE_V1; i++)
+               saddr_arr[i] = -EINVAL;
+
        if (of_id)
                pdev->id_entry = of_id->data;
        sdma->devtype = pdev->id_entry->driver_data;
index be641cbd36fcb30c16aafaf25f279ecc0064b07a..b4588bdd98bb0f0f7dbd3ea5c570f760550ef14d 100644 (file)
@@ -130,6 +130,23 @@ struct mxs_dma_engine {
        struct mxs_dma_chan             mxs_chans[MXS_DMA_CHANNELS];
 };
 
+static inline void mxs_dma_clkgate(struct mxs_dma_chan *mxs_chan, int enable)
+{
+       struct mxs_dma_engine *mxs_dma = mxs_chan->mxs_dma;
+       int chan_id = mxs_chan->chan.chan_id;
+       int set_clr = enable ? MXS_CLR_ADDR : MXS_SET_ADDR;
+
+       /* enable apbh channel clock */
+       if (dma_is_apbh()) {
+               if (apbh_is_old())
+                       writel(1 << (chan_id + BP_APBH_CTRL0_CLKGATE_CHANNEL),
+                               mxs_dma->base + HW_APBHX_CTRL0 + set_clr);
+               else
+                       writel(1 << chan_id,
+                               mxs_dma->base + HW_APBHX_CTRL0 + set_clr);
+       }
+}
+
 static void mxs_dma_reset_chan(struct mxs_dma_chan *mxs_chan)
 {
        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)
        struct mxs_dma_engine *mxs_dma = mxs_chan->mxs_dma;
        int chan_id = mxs_chan->chan.chan_id;
 
+       /* clkgate needs to be enabled before writing other registers */
+       mxs_dma_clkgate(mxs_chan, 1);
+
        /* set cmd_addr up */
        writel(mxs_chan->ccw_phys,
                mxs_dma->base + HW_APBHX_CHn_NXTCMDAR(chan_id));
 
-       /* enable apbh channel clock */
-       if (dma_is_apbh()) {
-               if (apbh_is_old())
-                       writel(1 << (chan_id + BP_APBH_CTRL0_CLKGATE_CHANNEL),
-                               mxs_dma->base + HW_APBHX_CTRL0 + MXS_CLR_ADDR);
-               else
-                       writel(1 << chan_id,
-                               mxs_dma->base + HW_APBHX_CTRL0 + MXS_CLR_ADDR);
-       }
-
        /* write 1 to SEMA to kick off the channel */
        writel(1, mxs_dma->base + HW_APBHX_CHn_SEMA(chan_id));
 }
 
 static void mxs_dma_disable_chan(struct mxs_dma_chan *mxs_chan)
 {
-       struct mxs_dma_engine *mxs_dma = mxs_chan->mxs_dma;
-       int chan_id = mxs_chan->chan.chan_id;
-
        /* disable apbh channel clock */
-       if (dma_is_apbh()) {
-               if (apbh_is_old())
-                       writel(1 << (chan_id + BP_APBH_CTRL0_CLKGATE_CHANNEL),
-                               mxs_dma->base + HW_APBHX_CTRL0 + MXS_SET_ADDR);
-               else
-                       writel(1 << chan_id,
-                               mxs_dma->base + HW_APBHX_CTRL0 + MXS_SET_ADDR);
-       }
+       mxs_dma_clkgate(mxs_chan, 0);
 
        mxs_chan->status = DMA_SUCCESS;
 }
@@ -338,7 +338,10 @@ static int mxs_dma_alloc_chan_resources(struct dma_chan *chan)
        if (ret)
                goto err_clk;
 
+       /* clkgate needs to be enabled for reset to finish */
+       mxs_dma_clkgate(mxs_chan, 1);
        mxs_dma_reset_chan(mxs_chan);
+       mxs_dma_clkgate(mxs_chan, 0);
 
        dma_async_tx_descriptor_init(&mxs_chan->desc, chan);
        mxs_chan->desc.tx_submit = mxs_dma_tx_submit;
index 00eee59e8b3357929a3a42f4861921f8ca2b858b..621134fdba4cadd031ccbebd8a52ed34c571ff8f 100644 (file)
@@ -17,6 +17,8 @@
 #include <linux/interrupt.h>
 #include <linux/amba/bus.h>
 #include <linux/amba/pl330.h>
+#include <linux/pm_runtime.h>
+#include <linux/scatterlist.h>
 
 #define NR_DEFAULT_DESC        16
 
@@ -68,6 +70,14 @@ struct dma_pl330_chan {
         * NULL if the channel is available to be acquired.
         */
        void *pl330_chid;
+
+       /* For D-to-M and M-to-D channels */
+       int burst_sz; /* the peripheral fifo width */
+       int burst_len; /* the number of burst */
+       dma_addr_t fifo_addr;
+
+       /* for cyclic capability */
+       bool cyclic;
 };
 
 struct dma_pl330_dmac {
@@ -83,6 +93,8 @@ struct dma_pl330_dmac {
 
        /* Peripheral channels connected to this DMAC */
        struct dma_pl330_chan *peripherals; /* keep at end */
+
+       struct clk *clk;
 };
 
 struct dma_pl330_desc {
@@ -152,6 +164,31 @@ static inline void free_desc_list(struct list_head *list)
        spin_unlock_irqrestore(&pdmac->pool_lock, flags);
 }
 
+static inline void handle_cyclic_desc_list(struct list_head *list)
+{
+       struct dma_pl330_desc *desc;
+       struct dma_pl330_chan *pch;
+       unsigned long flags;
+
+       if (list_empty(list))
+               return;
+
+       list_for_each_entry(desc, list, node) {
+               dma_async_tx_callback callback;
+
+               /* Change status to reload it */
+               desc->status = PREP;
+               pch = desc->pchan;
+               callback = desc->txd.callback;
+               if (callback)
+                       callback(desc->txd.callback_param);
+       }
+
+       spin_lock_irqsave(&pch->lock, flags);
+       list_splice_tail_init(list, &pch->work_list);
+       spin_unlock_irqrestore(&pch->lock, flags);
+}
+
 static inline void fill_queue(struct dma_pl330_chan *pch)
 {
        struct dma_pl330_desc *desc;
@@ -205,7 +242,10 @@ static void pl330_tasklet(unsigned long data)
 
        spin_unlock_irqrestore(&pch->lock, flags);
 
-       free_desc_list(&list);
+       if (pch->cyclic)
+               handle_cyclic_desc_list(&list);
+       else
+               free_desc_list(&list);
 }
 
 static 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)
        spin_lock_irqsave(&pch->lock, flags);
 
        pch->completed = chan->cookie = 1;
+       pch->cyclic = false;
 
        pch->pl330_chid = pl330_request_channel(&pdmac->pif);
        if (!pch->pl330_chid) {
@@ -253,25 +294,52 @@ static int pl330_alloc_chan_resources(struct dma_chan *chan)
 static int pl330_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, unsigned long arg)
 {
        struct dma_pl330_chan *pch = to_pchan(chan);
-       struct dma_pl330_desc *desc;
+       struct dma_pl330_desc *desc, *_dt;
        unsigned long flags;
+       struct dma_pl330_dmac *pdmac = pch->dmac;
+       struct dma_slave_config *slave_config;
+       LIST_HEAD(list);
 
-       /* Only supports DMA_TERMINATE_ALL */
-       if (cmd != DMA_TERMINATE_ALL)
-               return -ENXIO;
-
-       spin_lock_irqsave(&pch->lock, flags);
-
-       /* FLUSH the PL330 Channel thread */
-       pl330_chan_ctrl(pch->pl330_chid, PL330_OP_FLUSH);
+       switch (cmd) {
+       case DMA_TERMINATE_ALL:
+               spin_lock_irqsave(&pch->lock, flags);
 
-       /* Mark all desc done */
-       list_for_each_entry(desc, &pch->work_list, node)
-               desc->status = DONE;
+               /* FLUSH the PL330 Channel thread */
+               pl330_chan_ctrl(pch->pl330_chid, PL330_OP_FLUSH);
 
-       spin_unlock_irqrestore(&pch->lock, flags);
+               /* Mark all desc done */
+               list_for_each_entry_safe(desc, _dt, &pch->work_list , node) {
+                       desc->status = DONE;
+                       pch->completed = desc->txd.cookie;
+                       list_move_tail(&desc->node, &list);
+               }
 
-       pl330_tasklet((unsigned long) pch);
+               list_splice_tail_init(&list, &pdmac->desc_pool);
+               spin_unlock_irqrestore(&pch->lock, flags);
+               break;
+       case DMA_SLAVE_CONFIG:
+               slave_config = (struct dma_slave_config *)arg;
+
+               if (slave_config->direction == DMA_TO_DEVICE) {
+                       if (slave_config->dst_addr)
+                               pch->fifo_addr = slave_config->dst_addr;
+                       if (slave_config->dst_addr_width)
+                               pch->burst_sz = __ffs(slave_config->dst_addr_width);
+                       if (slave_config->dst_maxburst)
+                               pch->burst_len = slave_config->dst_maxburst;
+               } else if (slave_config->direction == DMA_FROM_DEVICE) {
+                       if (slave_config->src_addr)
+                               pch->fifo_addr = slave_config->src_addr;
+                       if (slave_config->src_addr_width)
+                               pch->burst_sz = __ffs(slave_config->src_addr_width);
+                       if (slave_config->src_maxburst)
+                               pch->burst_len = slave_config->src_maxburst;
+               }
+               break;
+       default:
+               dev_err(pch->dmac->pif.dev, "Not supported command.\n");
+               return -ENXIO;
+       }
 
        return 0;
 }
@@ -288,6 +356,9 @@ static void pl330_free_chan_resources(struct dma_chan *chan)
        pl330_release_channel(pch->pl330_chid);
        pch->pl330_chid = NULL;
 
+       if (pch->cyclic)
+               list_splice_tail_init(&pch->work_list, &pch->dmac->desc_pool);
+
        spin_unlock_irqrestore(&pch->lock, flags);
 }
 
@@ -453,7 +524,7 @@ static struct dma_pl330_desc *pl330_get_desc(struct dma_pl330_chan *pch)
 
        if (peri) {
                desc->req.rqtype = peri->rqtype;
-               desc->req.peri = peri->peri_id;
+               desc->req.peri = pch->chan.chan_id;
        } else {
                desc->req.rqtype = MEMTOMEM;
                desc->req.peri = 0;
@@ -524,6 +595,51 @@ static inline int get_burst_len(struct dma_pl330_desc *desc, size_t len)
        return burst_len;
 }
 
+static struct dma_async_tx_descriptor *pl330_prep_dma_cyclic(
+               struct dma_chan *chan, dma_addr_t dma_addr, size_t len,
+               size_t period_len, enum dma_data_direction direction)
+{
+       struct dma_pl330_desc *desc;
+       struct dma_pl330_chan *pch = to_pchan(chan);
+       dma_addr_t dst;
+       dma_addr_t src;
+
+       desc = pl330_get_desc(pch);
+       if (!desc) {
+               dev_err(pch->dmac->pif.dev, "%s:%d Unable to fetch desc\n",
+                       __func__, __LINE__);
+               return NULL;
+       }
+
+       switch (direction) {
+       case DMA_TO_DEVICE:
+               desc->rqcfg.src_inc = 1;
+               desc->rqcfg.dst_inc = 0;
+               src = dma_addr;
+               dst = pch->fifo_addr;
+               break;
+       case DMA_FROM_DEVICE:
+               desc->rqcfg.src_inc = 0;
+               desc->rqcfg.dst_inc = 1;
+               src = pch->fifo_addr;
+               dst = dma_addr;
+               break;
+       default:
+               dev_err(pch->dmac->pif.dev, "%s:%d Invalid dma direction\n",
+               __func__, __LINE__);
+               return NULL;
+       }
+
+       desc->rqcfg.brst_size = pch->burst_sz;
+       desc->rqcfg.brst_len = 1;
+
+       pch->cyclic = true;
+
+       fill_px(&desc->px, dst, src, period_len);
+
+       return &desc->txd;
+}
+
 static struct dma_async_tx_descriptor *
 pl330_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dst,
                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,
        struct dma_pl330_peri *peri = chan->private;
        struct scatterlist *sg;
        unsigned long flags;
-       int i, burst_size;
+       int i;
        dma_addr_t addr;
 
        if (unlikely(!pch || !sgl || !sg_len || !peri))
@@ -595,8 +711,7 @@ pl330_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
                return NULL;
        }
 
-       addr = peri->fifo_addr;
-       burst_size = peri->burst_sz;
+       addr = pch->fifo_addr;
 
        first = NULL;
 
@@ -644,7 +759,7 @@ pl330_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
                                sg_dma_address(sg), addr, sg_dma_len(sg));
                }
 
-               desc->rqcfg.brst_size = burst_size;
+               desc->rqcfg.brst_size = pch->burst_sz;
                desc->rqcfg.brst_len = 1;
        }
 
@@ -696,6 +811,30 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)
                goto probe_err1;
        }
 
+       pdmac->clk = clk_get(&adev->dev, "dma");
+       if (IS_ERR(pdmac->clk)) {
+               dev_err(&adev->dev, "Cannot get operation clock.\n");
+               ret = -EINVAL;
+               goto probe_err1;
+       }
+
+       amba_set_drvdata(adev, pdmac);
+
+#ifdef CONFIG_PM_RUNTIME
+       /* to use the runtime PM helper functions */
+       pm_runtime_enable(&adev->dev);
+
+       /* enable the power domain */
+       if (pm_runtime_get_sync(&adev->dev)) {
+               dev_err(&adev->dev, "failed to get runtime pm\n");
+               ret = -ENODEV;
+               goto probe_err1;
+       }
+#else
+       /* enable dma clk */
+       clk_enable(pdmac->clk);
+#endif
+
        irq = adev->irq[0];
        ret = request_irq(irq, pl330_irq_handler, 0,
                        dev_name(&adev->dev), pi);
@@ -732,6 +871,7 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)
                        case MEMTODEV:
                        case DEVTOMEM:
                                dma_cap_set(DMA_SLAVE, pd->cap_mask);
+                               dma_cap_set(DMA_CYCLIC, pd->cap_mask);
                                break;
                        default:
                                dev_err(&adev->dev, "DEVTODEV Not Supported\n");
@@ -760,6 +900,7 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)
        pd->device_alloc_chan_resources = pl330_alloc_chan_resources;
        pd->device_free_chan_resources = pl330_free_chan_resources;
        pd->device_prep_dma_memcpy = pl330_prep_dma_memcpy;
+       pd->device_prep_dma_cyclic = pl330_prep_dma_cyclic;
        pd->device_tx_status = pl330_tx_status;
        pd->device_prep_slave_sg = pl330_prep_slave_sg;
        pd->device_control = pl330_control;
@@ -771,8 +912,6 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)
                goto probe_err4;
        }
 
-       amba_set_drvdata(adev, pdmac);
-
        dev_info(&adev->dev,
                "Loaded driver for PL330 DMAC-%d\n", adev->periphid);
        dev_info(&adev->dev,
@@ -833,6 +972,13 @@ static int __devexit pl330_remove(struct amba_device *adev)
        res = &adev->res;
        release_mem_region(res->start, resource_size(res));
 
+#ifdef CONFIG_PM_RUNTIME
+       pm_runtime_put(&adev->dev);
+       pm_runtime_disable(&adev->dev);
+#else
+       clk_disable(pdmac->clk);
+#endif
+
        kfree(pdmac);
 
        return 0;
@@ -846,10 +992,49 @@ static struct amba_id pl330_ids[] = {
        { 0, 0 },
 };
 
+#ifdef CONFIG_PM_RUNTIME
+static int pl330_runtime_suspend(struct device *dev)
+{
+       struct dma_pl330_dmac *pdmac = dev_get_drvdata(dev);
+
+       if (!pdmac) {
+               dev_err(dev, "failed to get dmac\n");
+               return -ENODEV;
+       }
+
+       clk_disable(pdmac->clk);
+
+       return 0;
+}
+
+static int pl330_runtime_resume(struct device *dev)
+{
+       struct dma_pl330_dmac *pdmac = dev_get_drvdata(dev);
+
+       if (!pdmac) {
+               dev_err(dev, "failed to get dmac\n");
+               return -ENODEV;
+       }
+
+       clk_enable(pdmac->clk);
+
+       return 0;
+}
+#else
+#define pl330_runtime_suspend  NULL
+#define pl330_runtime_resume   NULL
+#endif /* CONFIG_PM_RUNTIME */
+
+static const struct dev_pm_ops pl330_pm_ops = {
+       .runtime_suspend = pl330_runtime_suspend,
+       .runtime_resume = pl330_runtime_resume,
+};
+
 static struct amba_driver pl330_driver = {
        .drv = {
                .owner = THIS_MODULE,
                .name = "dma-pl330",
+               .pm = &pl330_pm_ops,
        },
        .id_table = pl330_ids,
        .probe = pl330_probe,
index d539efd96d4b8d5b7c032c5c0767543da7413cd7..ca44d2cceb020a557460dbde9f6de0fc461f27a1 100644 (file)
@@ -95,10 +95,6 @@ config GPIO_EP93XX
        depends on ARCH_EP93XX
        select GPIO_GENERIC
 
-config GPIO_EXYNOS4
-       def_bool y
-       depends on CPU_EXYNOS4210
-
 config GPIO_MPC5200
        def_bool y
        depends on PPC_MPC52xx
@@ -131,18 +127,6 @@ config GPIO_MXS
        select GPIO_GENERIC
        select GENERIC_IRQ_CHIP
 
-config GPIO_PLAT_SAMSUNG
-       def_bool y
-       depends on SAMSUNG_GPIOLIB_4BIT
-
-config GPIO_S5PC100
-       def_bool y
-       depends on CPU_S5PC100
-
-config GPIO_S5PV210
-       def_bool y
-       depends on CPU_S5PV210
-
 config GPIO_PL061
        bool "PrimeCell PL061 GPIO support"
        depends on ARM_AMBA
index 9588948c96f08b2e8487b6333d7151fd1e914267..62db458c850d1e5fc83c544e7a30b412c942d932 100644 (file)
@@ -15,7 +15,6 @@ obj-$(CONFIG_GPIO_BT8XX)      += gpio-bt8xx.o
 obj-$(CONFIG_GPIO_CS5535)      += gpio-cs5535.o
 obj-$(CONFIG_GPIO_DA9052)      += gpio-da9052.o
 obj-$(CONFIG_GPIO_EP93XX)      += gpio-ep93xx.o
-obj-$(CONFIG_GPIO_EXYNOS4)     += gpio-exynos4.o
 obj-$(CONFIG_GPIO_IT8761E)     += gpio-it8761e.o
 obj-$(CONFIG_GPIO_JANZ_TTL)    += gpio-janz-ttl.o
 obj-$(CONFIG_GPIO_LANGWELL)    += gpio-langwell.o
@@ -38,11 +37,7 @@ obj-$(CONFIG_GPIO_PCF857X)   += gpio-pcf857x.o
 obj-$(CONFIG_GPIO_PCH)         += gpio-pch.o
 obj-$(CONFIG_GPIO_PL061)       += gpio-pl061.o
 obj-$(CONFIG_GPIO_RDC321X)     += gpio-rdc321x.o
-
-obj-$(CONFIG_GPIO_PLAT_SAMSUNG)        += gpio-plat-samsung.o
-obj-$(CONFIG_GPIO_S5PC100)     += gpio-s5pc100.o
-obj-$(CONFIG_GPIO_S5PV210)     += gpio-s5pv210.o
-
+obj-$(CONFIG_PLAT_SAMSUNG)     += gpio-samsung.o
 obj-$(CONFIG_GPIO_SCH)         += gpio-sch.o
 obj-$(CONFIG_GPIO_STMPE)       += gpio-stmpe.o
 obj-$(CONFIG_GPIO_SX150X)      += gpio-sx150x.o
diff --git a/drivers/gpio/gpio-exynos4.c b/drivers/gpio/gpio-exynos4.c
deleted file mode 100644 (file)
index d24b337..0000000
+++ /dev/null
@@ -1,385 +0,0 @@
-/*
- * EXYNOS4 - GPIOlib support
- *
- * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/kernel.h>
-#include <linux/irq.h>
-#include <linux/io.h>
-#include <linux/gpio.h>
-
-#include <mach/map.h>
-
-#include <plat/gpio-core.h>
-#include <plat/gpio-cfg.h>
-#include <plat/gpio-cfg-helpers.h>
-
-int s3c_gpio_setpull_exynos4(struct s3c_gpio_chip *chip,
-                               unsigned int off, s3c_gpio_pull_t pull)
-{
-       if (pull == S3C_GPIO_PULL_UP)
-               pull = 3;
-
-       return s3c_gpio_setpull_updown(chip, off, pull);
-}
-
-s3c_gpio_pull_t s3c_gpio_getpull_exynos4(struct s3c_gpio_chip *chip,
-                                               unsigned int off)
-{
-       s3c_gpio_pull_t pull;
-
-       pull = s3c_gpio_getpull_updown(chip, off);
-       if (pull == 3)
-               pull = S3C_GPIO_PULL_UP;
-
-       return pull;
-}
-
-static struct s3c_gpio_cfg gpio_cfg = {
-       .set_config     = s3c_gpio_setcfg_s3c64xx_4bit,
-       .set_pull       = s3c_gpio_setpull_exynos4,
-       .get_pull       = s3c_gpio_getpull_exynos4,
-};
-
-static struct s3c_gpio_cfg gpio_cfg_noint = {
-       .set_config     = s3c_gpio_setcfg_s3c64xx_4bit,
-       .set_pull       = s3c_gpio_setpull_exynos4,
-       .get_pull       = s3c_gpio_getpull_exynos4,
-};
-
-/*
- * Following are the gpio banks in v310.
- *
- * The 'config' member when left to NULL, is initialized to the default
- * structure gpio_cfg in the init function below.
- *
- * The 'base' member is also initialized in the init function below.
- * Note: The initialization of 'base' member of s3c_gpio_chip structure
- * uses the above macro and depends on the banks being listed in order here.
- */
-static struct s3c_gpio_chip exynos4_gpio_part1_4bit[] = {
-       {
-               .chip   = {
-                       .base   = EXYNOS4_GPA0(0),
-                       .ngpio  = EXYNOS4_GPIO_A0_NR,
-                       .label  = "GPA0",
-               },
-       }, {
-               .chip   = {
-                       .base   = EXYNOS4_GPA1(0),
-                       .ngpio  = EXYNOS4_GPIO_A1_NR,
-                       .label  = "GPA1",
-               },
-       }, {
-               .chip   = {
-                       .base   = EXYNOS4_GPB(0),
-                       .ngpio  = EXYNOS4_GPIO_B_NR,
-                       .label  = "GPB",
-               },
-       }, {
-               .chip   = {
-                       .base   = EXYNOS4_GPC0(0),
-                       .ngpio  = EXYNOS4_GPIO_C0_NR,
-                       .label  = "GPC0",
-               },
-       }, {
-               .chip   = {
-                       .base   = EXYNOS4_GPC1(0),
-                       .ngpio  = EXYNOS4_GPIO_C1_NR,
-                       .label  = "GPC1",
-               },
-       }, {
-               .chip   = {
-                       .base   = EXYNOS4_GPD0(0),
-                       .ngpio  = EXYNOS4_GPIO_D0_NR,
-                       .label  = "GPD0",
-               },
-       }, {
-               .chip   = {
-                       .base   = EXYNOS4_GPD1(0),
-                       .ngpio  = EXYNOS4_GPIO_D1_NR,
-                       .label  = "GPD1",
-               },
-       }, {
-               .chip   = {
-                       .base   = EXYNOS4_GPE0(0),
-                       .ngpio  = EXYNOS4_GPIO_E0_NR,
-                       .label  = "GPE0",
-               },
-       }, {
-               .chip   = {
-                       .base   = EXYNOS4_GPE1(0),
-                       .ngpio  = EXYNOS4_GPIO_E1_NR,
-                       .label  = "GPE1",
-               },
-       }, {
-               .chip   = {
-                       .base   = EXYNOS4_GPE2(0),
-                       .ngpio  = EXYNOS4_GPIO_E2_NR,
-                       .label  = "GPE2",
-               },
-       }, {
-               .chip   = {
-                       .base   = EXYNOS4_GPE3(0),
-                       .ngpio  = EXYNOS4_GPIO_E3_NR,
-                       .label  = "GPE3",
-               },
-       }, {
-               .chip   = {
-                       .base   = EXYNOS4_GPE4(0),
-                       .ngpio  = EXYNOS4_GPIO_E4_NR,
-                       .label  = "GPE4",
-               },
-       }, {
-               .chip   = {
-                       .base   = EXYNOS4_GPF0(0),
-                       .ngpio  = EXYNOS4_GPIO_F0_NR,
-                       .label  = "GPF0",
-               },
-       }, {
-               .chip   = {
-                       .base   = EXYNOS4_GPF1(0),
-                       .ngpio  = EXYNOS4_GPIO_F1_NR,
-                       .label  = "GPF1",
-               },
-       }, {
-               .chip   = {
-                       .base   = EXYNOS4_GPF2(0),
-                       .ngpio  = EXYNOS4_GPIO_F2_NR,
-                       .label  = "GPF2",
-               },
-       }, {
-               .chip   = {
-                       .base   = EXYNOS4_GPF3(0),
-                       .ngpio  = EXYNOS4_GPIO_F3_NR,
-                       .label  = "GPF3",
-               },
-       },
-};
-
-static struct s3c_gpio_chip exynos4_gpio_part2_4bit[] = {
-       {
-               .chip   = {
-                       .base   = EXYNOS4_GPJ0(0),
-                       .ngpio  = EXYNOS4_GPIO_J0_NR,
-                       .label  = "GPJ0",
-               },
-       }, {
-               .chip   = {
-                       .base   = EXYNOS4_GPJ1(0),
-                       .ngpio  = EXYNOS4_GPIO_J1_NR,
-                       .label  = "GPJ1",
-               },
-       }, {
-               .chip   = {
-                       .base   = EXYNOS4_GPK0(0),
-                       .ngpio  = EXYNOS4_GPIO_K0_NR,
-                       .label  = "GPK0",
-               },
-       }, {
-               .chip   = {
-                       .base   = EXYNOS4_GPK1(0),
-                       .ngpio  = EXYNOS4_GPIO_K1_NR,
-                       .label  = "GPK1",
-               },
-       }, {
-               .chip   = {
-                       .base   = EXYNOS4_GPK2(0),
-                       .ngpio  = EXYNOS4_GPIO_K2_NR,
-                       .label  = "GPK2",
-               },
-       }, {
-               .chip   = {
-                       .base   = EXYNOS4_GPK3(0),
-                       .ngpio  = EXYNOS4_GPIO_K3_NR,
-                       .label  = "GPK3",
-               },
-       }, {
-               .chip   = {
-                       .base   = EXYNOS4_GPL0(0),
-                       .ngpio  = EXYNOS4_GPIO_L0_NR,
-                       .label  = "GPL0",
-               },
-       }, {
-               .chip   = {
-                       .base   = EXYNOS4_GPL1(0),
-                       .ngpio  = EXYNOS4_GPIO_L1_NR,
-                       .label  = "GPL1",
-               },
-       }, {
-               .chip   = {
-                       .base   = EXYNOS4_GPL2(0),
-                       .ngpio  = EXYNOS4_GPIO_L2_NR,
-                       .label  = "GPL2",
-               },
-       }, {
-               .config = &gpio_cfg_noint,
-               .chip   = {
-                       .base   = EXYNOS4_GPY0(0),
-                       .ngpio  = EXYNOS4_GPIO_Y0_NR,
-                       .label  = "GPY0",
-               },
-       }, {
-               .config = &gpio_cfg_noint,
-               .chip   = {
-                       .base   = EXYNOS4_GPY1(0),
-                       .ngpio  = EXYNOS4_GPIO_Y1_NR,
-                       .label  = "GPY1",
-               },
-       }, {
-               .config = &gpio_cfg_noint,
-               .chip   = {
-                       .base   = EXYNOS4_GPY2(0),
-                       .ngpio  = EXYNOS4_GPIO_Y2_NR,
-                       .label  = "GPY2",
-               },
-       }, {
-               .config = &gpio_cfg_noint,
-               .chip   = {
-                       .base   = EXYNOS4_GPY3(0),
-                       .ngpio  = EXYNOS4_GPIO_Y3_NR,
-                       .label  = "GPY3",
-               },
-       }, {
-               .config = &gpio_cfg_noint,
-               .chip   = {
-                       .base   = EXYNOS4_GPY4(0),
-                       .ngpio  = EXYNOS4_GPIO_Y4_NR,
-                       .label  = "GPY4",
-               },
-       }, {
-               .config = &gpio_cfg_noint,
-               .chip   = {
-                       .base   = EXYNOS4_GPY5(0),
-                       .ngpio  = EXYNOS4_GPIO_Y5_NR,
-                       .label  = "GPY5",
-               },
-       }, {
-               .config = &gpio_cfg_noint,
-               .chip   = {
-                       .base   = EXYNOS4_GPY6(0),
-                       .ngpio  = EXYNOS4_GPIO_Y6_NR,
-                       .label  = "GPY6",
-               },
-       }, {
-               .base   = (S5P_VA_GPIO2 + 0xC00),
-               .config = &gpio_cfg_noint,
-               .irq_base = IRQ_EINT(0),
-               .chip   = {
-                       .base   = EXYNOS4_GPX0(0),
-                       .ngpio  = EXYNOS4_GPIO_X0_NR,
-                       .label  = "GPX0",
-                       .to_irq = samsung_gpiolib_to_irq,
-               },
-       }, {
-               .base   = (S5P_VA_GPIO2 + 0xC20),
-               .config = &gpio_cfg_noint,
-               .irq_base = IRQ_EINT(8),
-               .chip   = {
-                       .base   = EXYNOS4_GPX1(0),
-                       .ngpio  = EXYNOS4_GPIO_X1_NR,
-                       .label  = "GPX1",
-                       .to_irq = samsung_gpiolib_to_irq,
-               },
-       }, {
-               .base   = (S5P_VA_GPIO2 + 0xC40),
-               .config = &gpio_cfg_noint,
-               .irq_base = IRQ_EINT(16),
-               .chip   = {
-                       .base   = EXYNOS4_GPX2(0),
-                       .ngpio  = EXYNOS4_GPIO_X2_NR,
-                       .label  = "GPX2",
-                       .to_irq = samsung_gpiolib_to_irq,
-               },
-       }, {
-               .base   = (S5P_VA_GPIO2 + 0xC60),
-               .config = &gpio_cfg_noint,
-               .irq_base = IRQ_EINT(24),
-               .chip   = {
-                       .base   = EXYNOS4_GPX3(0),
-                       .ngpio  = EXYNOS4_GPIO_X3_NR,
-                       .label  = "GPX3",
-                       .to_irq = samsung_gpiolib_to_irq,
-               },
-       },
-};
-
-static struct s3c_gpio_chip exynos4_gpio_part3_4bit[] = {
-       {
-               .chip   = {
-                       .base   = EXYNOS4_GPZ(0),
-                       .ngpio  = EXYNOS4_GPIO_Z_NR,
-                       .label  = "GPZ",
-               },
-       },
-};
-
-static __init int exynos4_gpiolib_init(void)
-{
-       struct s3c_gpio_chip *chip;
-       int i;
-       int group = 0;
-       int nr_chips;
-
-       /* GPIO part 1 */
-
-       chip = exynos4_gpio_part1_4bit;
-       nr_chips = ARRAY_SIZE(exynos4_gpio_part1_4bit);
-
-       for (i = 0; i < nr_chips; i++, chip++) {
-               if (chip->config == NULL) {
-                       chip->config = &gpio_cfg;
-                       /* Assign the GPIO interrupt group */
-                       chip->group = group++;
-               }
-               if (chip->base == NULL)
-                       chip->base = S5P_VA_GPIO1 + (i) * 0x20;
-       }
-
-       samsung_gpiolib_add_4bit_chips(exynos4_gpio_part1_4bit, nr_chips);
-
-       /* GPIO part 2 */
-
-       chip = exynos4_gpio_part2_4bit;
-       nr_chips = ARRAY_SIZE(exynos4_gpio_part2_4bit);
-
-       for (i = 0; i < nr_chips; i++, chip++) {
-               if (chip->config == NULL) {
-                       chip->config = &gpio_cfg;
-                       /* Assign the GPIO interrupt group */
-                       chip->group = group++;
-               }
-               if (chip->base == NULL)
-                       chip->base = S5P_VA_GPIO2 + (i) * 0x20;
-       }
-
-       samsung_gpiolib_add_4bit_chips(exynos4_gpio_part2_4bit, nr_chips);
-
-       /* GPIO part 3 */
-
-       chip = exynos4_gpio_part3_4bit;
-       nr_chips = ARRAY_SIZE(exynos4_gpio_part3_4bit);
-
-       for (i = 0; i < nr_chips; i++, chip++) {
-               if (chip->config == NULL) {
-                       chip->config = &gpio_cfg;
-                       /* Assign the GPIO interrupt group */
-                       chip->group = group++;
-               }
-               if (chip->base == NULL)
-                       chip->base = S5P_VA_GPIO3 + (i) * 0x20;
-       }
-
-       samsung_gpiolib_add_4bit_chips(exynos4_gpio_part3_4bit, nr_chips);
-       s5p_register_gpioint_bank(IRQ_GPIO_XA, 0, IRQ_GPIO1_NR_GROUPS);
-       s5p_register_gpioint_bank(IRQ_GPIO_XB, IRQ_GPIO1_NR_GROUPS, IRQ_GPIO2_NR_GROUPS);
-
-       return 0;
-}
-core_initcall(exynos4_gpiolib_init);
diff --git a/drivers/gpio/gpio-plat-samsung.c b/drivers/gpio/gpio-plat-samsung.c
deleted file mode 100644 (file)
index ef67f19..0000000
+++ /dev/null
@@ -1,205 +0,0 @@
-/*
- * Copyright 2008 Openmoko, Inc.
- * Copyright 2008 Simtec Electronics
- *      Ben Dooks <ben@simtec.co.uk>
- *      http://armlinux.simtec.co.uk/
- *
- * Copyright (c) 2009 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com/
- *
- * SAMSUNG - GPIOlib support
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/kernel.h>
-#include <linux/irq.h>
-#include <linux/io.h>
-#include <linux/gpio.h>
-#include <plat/gpio-core.h>
-#include <plat/gpio-cfg.h>
-#include <plat/gpio-cfg-helpers.h>
-
-#ifndef DEBUG_GPIO
-#define gpio_dbg(x...) do { } while (0)
-#else
-#define gpio_dbg(x...) printk(KERN_DEBUG x)
-#endif
-
-/* The samsung_gpiolib_4bit routines are to control the gpio banks where
- * the gpio configuration register (GPxCON) has 4 bits per GPIO, as the
- * following example:
- *
- * base + 0x00: Control register, 4 bits per gpio
- *             gpio n: 4 bits starting at (4*n)
- *             0000 = input, 0001 = output, others mean special-function
- * base + 0x04: Data register, 1 bit per gpio
- *             bit n: data bit n
- *
- * Note, since the data register is one bit per gpio and is at base + 0x4
- * we can use s3c_gpiolib_get and s3c_gpiolib_set to change the state of
- * the output.
-*/
-
-static int samsung_gpiolib_4bit_input(struct gpio_chip *chip,
-                                     unsigned int offset)
-{
-       struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
-       void __iomem *base = ourchip->base;
-       unsigned long con;
-
-       con = __raw_readl(base + GPIOCON_OFF);
-       con &= ~(0xf << con_4bit_shift(offset));
-       __raw_writel(con, base + GPIOCON_OFF);
-
-       gpio_dbg("%s: %p: CON now %08lx\n", __func__, base, con);
-
-       return 0;
-}
-
-static int samsung_gpiolib_4bit_output(struct gpio_chip *chip,
-                                      unsigned int offset, int value)
-{
-       struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
-       void __iomem *base = ourchip->base;
-       unsigned long con;
-       unsigned long dat;
-
-       con = __raw_readl(base + GPIOCON_OFF);
-       con &= ~(0xf << con_4bit_shift(offset));
-       con |= 0x1 << con_4bit_shift(offset);
-
-       dat = __raw_readl(base + GPIODAT_OFF);
-
-       if (value)
-               dat |= 1 << offset;
-       else
-               dat &= ~(1 << offset);
-
-       __raw_writel(dat, base + GPIODAT_OFF);
-       __raw_writel(con, base + GPIOCON_OFF);
-       __raw_writel(dat, base + GPIODAT_OFF);
-
-       gpio_dbg("%s: %p: CON %08lx, DAT %08lx\n", __func__, base, con, dat);
-
-       return 0;
-}
-
-/* The next set of routines are for the case where the GPIO configuration
- * registers are 4 bits per GPIO but there is more than one register (the
- * bank has more than 8 GPIOs.
- *
- * This case is the similar to the 4 bit case, but the registers are as
- * follows:
- *
- * base + 0x00: Control register, 4 bits per gpio (lower 8 GPIOs)
- *             gpio n: 4 bits starting at (4*n)
- *             0000 = input, 0001 = output, others mean special-function
- * base + 0x04: Control register, 4 bits per gpio (up to 8 additions GPIOs)
- *             gpio n: 4 bits starting at (4*n)
- *             0000 = input, 0001 = output, others mean special-function
- * base + 0x08: Data register, 1 bit per gpio
- *             bit n: data bit n
- *
- * To allow us to use the s3c_gpiolib_get and s3c_gpiolib_set routines we
- * store the 'base + 0x4' address so that these routines see the data
- * register at ourchip->base + 0x04.
- */
-
-static int samsung_gpiolib_4bit2_input(struct gpio_chip *chip,
-                                      unsigned int offset)
-{
-       struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
-       void __iomem *base = ourchip->base;
-       void __iomem *regcon = base;
-       unsigned long con;
-
-       if (offset > 7)
-               offset -= 8;
-       else
-               regcon -= 4;
-
-       con = __raw_readl(regcon);
-       con &= ~(0xf << con_4bit_shift(offset));
-       __raw_writel(con, regcon);
-
-       gpio_dbg("%s: %p: CON %08lx\n", __func__, base, con);
-
-       return 0;
-}
-
-static int samsung_gpiolib_4bit2_output(struct gpio_chip *chip,
-                                       unsigned int offset, int value)
-{
-       struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
-       void __iomem *base = ourchip->base;
-       void __iomem *regcon = base;
-       unsigned long con;
-       unsigned long dat;
-       unsigned con_offset = offset;
-
-       if (con_offset > 7)
-               con_offset -= 8;
-       else
-               regcon -= 4;
-
-       con = __raw_readl(regcon);
-       con &= ~(0xf << con_4bit_shift(con_offset));
-       con |= 0x1 << con_4bit_shift(con_offset);
-
-       dat = __raw_readl(base + GPIODAT_OFF);
-
-       if (value)
-               dat |= 1 << offset;
-       else
-               dat &= ~(1 << offset);
-
-       __raw_writel(dat, base + GPIODAT_OFF);
-       __raw_writel(con, regcon);
-       __raw_writel(dat, base + GPIODAT_OFF);
-
-       gpio_dbg("%s: %p: CON %08lx, DAT %08lx\n", __func__, base, con, dat);
-
-       return 0;
-}
-
-void __init samsung_gpiolib_add_4bit(struct s3c_gpio_chip *chip)
-{
-       chip->chip.direction_input = samsung_gpiolib_4bit_input;
-       chip->chip.direction_output = samsung_gpiolib_4bit_output;
-       chip->pm = __gpio_pm(&s3c_gpio_pm_4bit);
-}
-
-void __init samsung_gpiolib_add_4bit2(struct s3c_gpio_chip *chip)
-{
-       chip->chip.direction_input = samsung_gpiolib_4bit2_input;
-       chip->chip.direction_output = samsung_gpiolib_4bit2_output;
-       chip->pm = __gpio_pm(&s3c_gpio_pm_4bit);
-}
-
-void __init samsung_gpiolib_add_4bit_chips(struct s3c_gpio_chip *chip,
-                                          int nr_chips)
-{
-       for (; nr_chips > 0; nr_chips--, chip++) {
-               samsung_gpiolib_add_4bit(chip);
-               s3c_gpiolib_add(chip);
-       }
-}
-
-void __init samsung_gpiolib_add_4bit2_chips(struct s3c_gpio_chip *chip,
-                                           int nr_chips)
-{
-       for (; nr_chips > 0; nr_chips--, chip++) {
-               samsung_gpiolib_add_4bit2(chip);
-               s3c_gpiolib_add(chip);
-       }
-}
-
-void __init samsung_gpiolib_add_2bit_chips(struct s3c_gpio_chip *chip,
-                                          int nr_chips)
-{
-       for (; nr_chips > 0; nr_chips--, chip++)
-               s3c_gpiolib_add(chip);
-}
diff --git a/drivers/gpio/gpio-s5pc100.c b/drivers/gpio/gpio-s5pc100.c
deleted file mode 100644 (file)
index 7f87b0c..0000000
+++ /dev/null
@@ -1,354 +0,0 @@
-/*
- * S5PC100 - GPIOlib support
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com
- *
- *  Copyright 2009 Samsung Electronics Co
- *  Kyungmin Park <kyungmin.park@samsung.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/kernel.h>
-#include <linux/irq.h>
-#include <linux/io.h>
-#include <linux/gpio.h>
-
-#include <mach/map.h>
-#include <mach/regs-gpio.h>
-
-#include <plat/gpio-core.h>
-#include <plat/gpio-cfg.h>
-#include <plat/gpio-cfg-helpers.h>
-
-/* S5PC100 GPIO bank summary:
- *
- * Bank        GPIOs   Style   INT Type
- * A0  8       4Bit    GPIO_INT0
- * A1  5       4Bit    GPIO_INT1
- * B   8       4Bit    GPIO_INT2
- * C   5       4Bit    GPIO_INT3
- * D   7       4Bit    GPIO_INT4
- * E0  8       4Bit    GPIO_INT5
- * E1  6       4Bit    GPIO_INT6
- * F0  8       4Bit    GPIO_INT7
- * F1  8       4Bit    GPIO_INT8
- * F2  8       4Bit    GPIO_INT9
- * F3  4       4Bit    GPIO_INT10
- * G0  8       4Bit    GPIO_INT11
- * G1  3       4Bit    GPIO_INT12
- * G2  7       4Bit    GPIO_INT13
- * G3  7       4Bit    GPIO_INT14
- * H0  8       4Bit    WKUP_INT
- * H1  8       4Bit    WKUP_INT
- * H2  8       4Bit    WKUP_INT
- * H3  8       4Bit    WKUP_INT
- * I   8       4Bit    GPIO_INT15
- * J0  8       4Bit    GPIO_INT16
- * J1  5       4Bit    GPIO_INT17
- * J2  8       4Bit    GPIO_INT18
- * J3  8       4Bit    GPIO_INT19
- * J4  4       4Bit    GPIO_INT20
- * K0  8       4Bit    None
- * K1  6       4Bit    None
- * K2  8       4Bit    None
- * K3  8       4Bit    None
- * L0  8       4Bit    None
- * L1  8       4Bit    None
- * L2  8       4Bit    None
- * L3  8       4Bit    None
- */
-
-static struct s3c_gpio_cfg gpio_cfg = {
-       .set_config     = s3c_gpio_setcfg_s3c64xx_4bit,
-       .set_pull       = s3c_gpio_setpull_updown,
-       .get_pull       = s3c_gpio_getpull_updown,
-};
-
-static struct s3c_gpio_cfg gpio_cfg_eint = {
-       .cfg_eint       = 0xf,
-       .set_config     = s3c_gpio_setcfg_s3c64xx_4bit,
-       .set_pull       = s3c_gpio_setpull_updown,
-       .get_pull       = s3c_gpio_getpull_updown,
-};
-
-static struct s3c_gpio_cfg gpio_cfg_noint = {
-       .set_config     = s3c_gpio_setcfg_s3c64xx_4bit,
-       .set_pull       = s3c_gpio_setpull_updown,
-       .get_pull       = s3c_gpio_getpull_updown,
-};
-
-/*
- * GPIO bank's base address given the index of the bank in the
- * list of all gpio banks.
- */
-#define S5PC100_BANK_BASE(bank_nr)     (S5P_VA_GPIO + ((bank_nr) * 0x20))
-
-/*
- * Following are the gpio banks in S5PC100.
- *
- * The 'config' member when left to NULL, is initialized to the default
- * structure gpio_cfg in the init function below.
- *
- * The 'base' member is also initialized in the init function below.
- * Note: The initialization of 'base' member of s3c_gpio_chip structure
- * uses the above macro and depends on the banks being listed in order here.
- */
-static struct s3c_gpio_chip s5pc100_gpio_chips[] = {
-       {
-               .chip   = {
-                       .base   = S5PC100_GPA0(0),
-                       .ngpio  = S5PC100_GPIO_A0_NR,
-                       .label  = "GPA0",
-               },
-       }, {
-               .chip   = {
-                       .base   = S5PC100_GPA1(0),
-                       .ngpio  = S5PC100_GPIO_A1_NR,
-                       .label  = "GPA1",
-               },
-       }, {
-               .chip   = {
-                       .base   = S5PC100_GPB(0),
-                       .ngpio  = S5PC100_GPIO_B_NR,
-                       .label  = "GPB",
-               },
-       }, {
-               .chip   = {
-                       .base   = S5PC100_GPC(0),
-                       .ngpio  = S5PC100_GPIO_C_NR,
-                       .label  = "GPC",
-               },
-       }, {
-               .chip   = {
-                       .base   = S5PC100_GPD(0),
-                       .ngpio  = S5PC100_GPIO_D_NR,
-                       .label  = "GPD",
-               },
-       }, {
-               .chip   = {
-                       .base   = S5PC100_GPE0(0),
-                       .ngpio  = S5PC100_GPIO_E0_NR,
-                       .label  = "GPE0",
-               },
-       }, {
-               .chip   = {
-                       .base   = S5PC100_GPE1(0),
-                       .ngpio  = S5PC100_GPIO_E1_NR,
-                       .label  = "GPE1",
-               },
-       }, {
-               .chip   = {
-                       .base   = S5PC100_GPF0(0),
-                       .ngpio  = S5PC100_GPIO_F0_NR,
-                       .label  = "GPF0",
-               },
-       }, {
-               .chip   = {
-                       .base   = S5PC100_GPF1(0),
-                       .ngpio  = S5PC100_GPIO_F1_NR,
-                       .label  = "GPF1",
-               },
-       }, {
-               .chip   = {
-                       .base   = S5PC100_GPF2(0),
-                       .ngpio  = S5PC100_GPIO_F2_NR,
-                       .label  = "GPF2",
-               },
-       }, {
-               .chip   = {
-                       .base   = S5PC100_GPF3(0),
-                       .ngpio  = S5PC100_GPIO_F3_NR,
-                       .label  = "GPF3",
-               },
-       }, {
-               .chip   = {
-                       .base   = S5PC100_GPG0(0),
-                       .ngpio  = S5PC100_GPIO_G0_NR,
-                       .label  = "GPG0",
-               },
-       }, {
-               .chip   = {
-                       .base   = S5PC100_GPG1(0),
-                       .ngpio  = S5PC100_GPIO_G1_NR,
-                       .label  = "GPG1",
-               },
-       }, {
-               .chip   = {
-                       .base   = S5PC100_GPG2(0),
-                       .ngpio  = S5PC100_GPIO_G2_NR,
-                       .label  = "GPG2",
-               },
-       }, {
-               .chip   = {
-                       .base   = S5PC100_GPG3(0),
-                       .ngpio  = S5PC100_GPIO_G3_NR,
-                       .label  = "GPG3",
-               },
-       }, {
-               .chip   = {
-                       .base   = S5PC100_GPI(0),
-                       .ngpio  = S5PC100_GPIO_I_NR,
-                       .label  = "GPI",
-               },
-       }, {
-               .chip   = {
-                       .base   = S5PC100_GPJ0(0),
-                       .ngpio  = S5PC100_GPIO_J0_NR,
-                       .label  = "GPJ0",
-               },
-       }, {
-               .chip   = {
-                       .base   = S5PC100_GPJ1(0),
-                       .ngpio  = S5PC100_GPIO_J1_NR,
-                       .label  = "GPJ1",
-               },
-       }, {
-               .chip   = {
-                       .base   = S5PC100_GPJ2(0),
-                       .ngpio  = S5PC100_GPIO_J2_NR,
-                       .label  = "GPJ2",
-               },
-       }, {
-               .chip   = {
-                       .base   = S5PC100_GPJ3(0),
-                       .ngpio  = S5PC100_GPIO_J3_NR,
-                       .label  = "GPJ3",
-               },
-       }, {
-               .chip   = {
-                       .base   = S5PC100_GPJ4(0),
-                       .ngpio  = S5PC100_GPIO_J4_NR,
-                       .label  = "GPJ4",
-               },
-       }, {
-               .config = &gpio_cfg_noint,
-               .chip   = {
-                       .base   = S5PC100_GPK0(0),
-                       .ngpio  = S5PC100_GPIO_K0_NR,
-                       .label  = "GPK0",
-               },
-       }, {
-               .config = &gpio_cfg_noint,
-               .chip   = {
-                       .base   = S5PC100_GPK1(0),
-                       .ngpio  = S5PC100_GPIO_K1_NR,
-                       .label  = "GPK1",
-               },
-       }, {
-               .config = &gpio_cfg_noint,
-               .chip   = {
-                       .base   = S5PC100_GPK2(0),
-                       .ngpio  = S5PC100_GPIO_K2_NR,
-                       .label  = "GPK2",
-               },
-       }, {
-               .config = &gpio_cfg_noint,
-               .chip   = {
-                       .base   = S5PC100_GPK3(0),
-                       .ngpio  = S5PC100_GPIO_K3_NR,
-                       .label  = "GPK3",
-               },
-       }, {
-               .config = &gpio_cfg_noint,
-               .chip   = {
-                       .base   = S5PC100_GPL0(0),
-                       .ngpio  = S5PC100_GPIO_L0_NR,
-                       .label  = "GPL0",
-               },
-       }, {
-               .config = &gpio_cfg_noint,
-               .chip   = {
-                       .base   = S5PC100_GPL1(0),
-                       .ngpio  = S5PC100_GPIO_L1_NR,
-                       .label  = "GPL1",
-               },
-       }, {
-               .config = &gpio_cfg_noint,
-               .chip   = {
-                       .base   = S5PC100_GPL2(0),
-                       .ngpio  = S5PC100_GPIO_L2_NR,
-                       .label  = "GPL2",
-               },
-       }, {
-               .config = &gpio_cfg_noint,
-               .chip   = {
-                       .base   = S5PC100_GPL3(0),
-                       .ngpio  = S5PC100_GPIO_L3_NR,
-                       .label  = "GPL3",
-               },
-       }, {
-               .config = &gpio_cfg_noint,
-               .chip   = {
-                       .base   = S5PC100_GPL4(0),
-                       .ngpio  = S5PC100_GPIO_L4_NR,
-                       .label  = "GPL4",
-               },
-       }, {
-               .base   = (S5P_VA_GPIO + 0xC00),
-               .config = &gpio_cfg_eint,
-               .irq_base = IRQ_EINT(0),
-               .chip   = {
-                       .base   = S5PC100_GPH0(0),
-                       .ngpio  = S5PC100_GPIO_H0_NR,
-                       .label  = "GPH0",
-                       .to_irq = samsung_gpiolib_to_irq,
-               },
-       }, {
-               .base   = (S5P_VA_GPIO + 0xC20),
-               .config = &gpio_cfg_eint,
-               .irq_base = IRQ_EINT(8),
-               .chip   = {
-                       .base   = S5PC100_GPH1(0),
-                       .ngpio  = S5PC100_GPIO_H1_NR,
-                       .label  = "GPH1",
-                       .to_irq = samsung_gpiolib_to_irq,
-               },
-       }, {
-               .base   = (S5P_VA_GPIO + 0xC40),
-               .config = &gpio_cfg_eint,
-               .irq_base = IRQ_EINT(16),
-               .chip   = {
-                       .base   = S5PC100_GPH2(0),
-                       .ngpio  = S5PC100_GPIO_H2_NR,
-                       .label  = "GPH2",
-                       .to_irq = samsung_gpiolib_to_irq,
-               },
-       }, {
-               .base   = (S5P_VA_GPIO + 0xC60),
-               .config = &gpio_cfg_eint,
-               .irq_base = IRQ_EINT(24),
-               .chip   = {
-                       .base   = S5PC100_GPH3(0),
-                       .ngpio  = S5PC100_GPIO_H3_NR,
-                       .label  = "GPH3",
-                       .to_irq = samsung_gpiolib_to_irq,
-               },
-       },
-};
-
-static __init int s5pc100_gpiolib_init(void)
-{
-       struct s3c_gpio_chip *chip = s5pc100_gpio_chips;
-       int nr_chips = ARRAY_SIZE(s5pc100_gpio_chips);
-       int gpioint_group = 0;
-       int i;
-
-       for (i = 0; i < nr_chips; i++, chip++) {
-               if (chip->config == NULL) {
-                       chip->config = &gpio_cfg;
-                       chip->group = gpioint_group++;
-               }
-               if (chip->base == NULL)
-                       chip->base = S5PC100_BANK_BASE(i);
-       }
-
-       samsung_gpiolib_add_4bit_chips(s5pc100_gpio_chips, nr_chips);
-       s5p_register_gpioint_bank(IRQ_GPIOINT, 0, S5P_GPIOINT_GROUP_MAXNR);
-
-       return 0;
-}
-core_initcall(s5pc100_gpiolib_init);
diff --git a/drivers/gpio/gpio-s5pv210.c b/drivers/gpio/gpio-s5pv210.c
deleted file mode 100644 (file)
index eb12f16..0000000
+++ /dev/null
@@ -1,287 +0,0 @@
-/*
- * S5PV210 - GPIOlib support
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/kernel.h>
-#include <linux/irq.h>
-#include <linux/io.h>
-#include <linux/gpio.h>
-#include <plat/gpio-core.h>
-#include <plat/gpio-cfg.h>
-#include <plat/gpio-cfg-helpers.h>
-#include <mach/map.h>
-
-static struct s3c_gpio_cfg gpio_cfg = {
-       .set_config     = s3c_gpio_setcfg_s3c64xx_4bit,
-       .set_pull       = s3c_gpio_setpull_updown,
-       .get_pull       = s3c_gpio_getpull_updown,
-};
-
-static struct s3c_gpio_cfg gpio_cfg_noint = {
-       .set_config     = s3c_gpio_setcfg_s3c64xx_4bit,
-       .set_pull       = s3c_gpio_setpull_updown,
-       .get_pull       = s3c_gpio_getpull_updown,
-};
-
-/* GPIO bank's base address given the index of the bank in the
- * list of all gpio banks.
- */
-#define S5PV210_BANK_BASE(bank_nr)     (S5P_VA_GPIO + ((bank_nr) * 0x20))
-
-/*
- * Following are the gpio banks in v210.
- *
- * The 'config' member when left to NULL, is initialized to the default
- * structure gpio_cfg in the init function below.
- *
- * The 'base' member is also initialized in the init function below.
- * Note: The initialization of 'base' member of s3c_gpio_chip structure
- * uses the above macro and depends on the banks being listed in order here.
- */
-static struct s3c_gpio_chip s5pv210_gpio_4bit[] = {
-       {
-               .chip   = {
-                       .base   = S5PV210_GPA0(0),
-                       .ngpio  = S5PV210_GPIO_A0_NR,
-                       .label  = "GPA0",
-               },
-       }, {
-               .chip   = {
-                       .base   = S5PV210_GPA1(0),
-                       .ngpio  = S5PV210_GPIO_A1_NR,
-                       .label  = "GPA1",
-               },
-       }, {
-               .chip   = {
-                       .base   = S5PV210_GPB(0),
-                       .ngpio  = S5PV210_GPIO_B_NR,
-                       .label  = "GPB",
-               },
-       }, {
-               .chip   = {
-                       .base   = S5PV210_GPC0(0),
-                       .ngpio  = S5PV210_GPIO_C0_NR,
-                       .label  = "GPC0",
-               },
-       }, {
-               .chip   = {
-                       .base   = S5PV210_GPC1(0),
-                       .ngpio  = S5PV210_GPIO_C1_NR,
-                       .label  = "GPC1",
-               },
-       }, {
-               .chip   = {
-                       .base   = S5PV210_GPD0(0),
-                       .ngpio  = S5PV210_GPIO_D0_NR,
-                       .label  = "GPD0",
-               },
-       }, {
-               .chip   = {
-                       .base   = S5PV210_GPD1(0),
-                       .ngpio  = S5PV210_GPIO_D1_NR,
-                       .label  = "GPD1",
-               },
-       }, {
-               .chip   = {
-                       .base   = S5PV210_GPE0(0),
-                       .ngpio  = S5PV210_GPIO_E0_NR,
-                       .label  = "GPE0",
-               },
-       }, {
-               .chip   = {
-                       .base   = S5PV210_GPE1(0),
-                       .ngpio  = S5PV210_GPIO_E1_NR,
-                       .label  = "GPE1",
-               },
-       }, {
-               .chip   = {
-                       .base   = S5PV210_GPF0(0),
-                       .ngpio  = S5PV210_GPIO_F0_NR,
-                       .label  = "GPF0",
-               },
-       }, {
-               .chip   = {
-                       .base   = S5PV210_GPF1(0),
-                       .ngpio  = S5PV210_GPIO_F1_NR,
-                       .label  = "GPF1",
-               },
-       }, {
-               .chip   = {
-                       .base   = S5PV210_GPF2(0),
-                       .ngpio  = S5PV210_GPIO_F2_NR,
-                       .label  = "GPF2",
-               },
-       }, {
-               .chip   = {
-                       .base   = S5PV210_GPF3(0),
-                       .ngpio  = S5PV210_GPIO_F3_NR,
-                       .label  = "GPF3",
-               },
-       }, {
-               .chip   = {
-                       .base   = S5PV210_GPG0(0),
-                       .ngpio  = S5PV210_GPIO_G0_NR,
-                       .label  = "GPG0",
-               },
-       }, {
-               .chip   = {
-                       .base   = S5PV210_GPG1(0),
-                       .ngpio  = S5PV210_GPIO_G1_NR,
-                       .label  = "GPG1",
-               },
-       }, {
-               .chip   = {
-                       .base   = S5PV210_GPG2(0),
-                       .ngpio  = S5PV210_GPIO_G2_NR,
-                       .label  = "GPG2",
-               },
-       }, {
-               .chip   = {
-                       .base   = S5PV210_GPG3(0),
-                       .ngpio  = S5PV210_GPIO_G3_NR,
-                       .label  = "GPG3",
-               },
-       }, {
-               .config = &gpio_cfg_noint,
-               .chip   = {
-                       .base   = S5PV210_GPI(0),
-                       .ngpio  = S5PV210_GPIO_I_NR,
-                       .label  = "GPI",
-               },
-       }, {
-               .chip   = {
-                       .base   = S5PV210_GPJ0(0),
-                       .ngpio  = S5PV210_GPIO_J0_NR,
-                       .label  = "GPJ0",
-               },
-       }, {
-               .chip   = {
-                       .base   = S5PV210_GPJ1(0),
-                       .ngpio  = S5PV210_GPIO_J1_NR,
-                       .label  = "GPJ1",
-               },
-       }, {
-               .chip   = {
-                       .base   = S5PV210_GPJ2(0),
-                       .ngpio  = S5PV210_GPIO_J2_NR,
-                       .label  = "GPJ2",
-               },
-       }, {
-               .chip   = {
-                       .base   = S5PV210_GPJ3(0),
-                       .ngpio  = S5PV210_GPIO_J3_NR,
-                       .label  = "GPJ3",
-               },
-       }, {
-               .chip   = {
-                       .base   = S5PV210_GPJ4(0),
-                       .ngpio  = S5PV210_GPIO_J4_NR,
-                       .label  = "GPJ4",
-               },
-       }, {
-               .config = &gpio_cfg_noint,
-               .chip   = {
-                       .base   = S5PV210_MP01(0),
-                       .ngpio  = S5PV210_GPIO_MP01_NR,
-                       .label  = "MP01",
-               },
-       }, {
-               .config = &gpio_cfg_noint,
-               .chip   = {
-                       .base   = S5PV210_MP02(0),
-                       .ngpio  = S5PV210_GPIO_MP02_NR,
-                       .label  = "MP02",
-               },
-       }, {
-               .config = &gpio_cfg_noint,
-               .chip   = {
-                       .base   = S5PV210_MP03(0),
-                       .ngpio  = S5PV210_GPIO_MP03_NR,
-                       .label  = "MP03",
-               },
-       }, {
-               .config = &gpio_cfg_noint,
-               .chip   = {
-                       .base   = S5PV210_MP04(0),
-                       .ngpio  = S5PV210_GPIO_MP04_NR,
-                       .label  = "MP04",
-               },
-       }, {
-               .config = &gpio_cfg_noint,
-               .chip   = {
-                       .base   = S5PV210_MP05(0),
-                       .ngpio  = S5PV210_GPIO_MP05_NR,
-                       .label  = "MP05",
-               },
-       }, {
-               .base   = (S5P_VA_GPIO + 0xC00),
-               .config = &gpio_cfg_noint,
-               .irq_base = IRQ_EINT(0),
-               .chip   = {
-                       .base   = S5PV210_GPH0(0),
-                       .ngpio  = S5PV210_GPIO_H0_NR,
-                       .label  = "GPH0",
-                       .to_irq = samsung_gpiolib_to_irq,
-               },
-       }, {
-               .base   = (S5P_VA_GPIO + 0xC20),
-               .config = &gpio_cfg_noint,
-               .irq_base = IRQ_EINT(8),
-               .chip   = {
-                       .base   = S5PV210_GPH1(0),
-                       .ngpio  = S5PV210_GPIO_H1_NR,
-                       .label  = "GPH1",
-                       .to_irq = samsung_gpiolib_to_irq,
-               },
-       }, {
-               .base   = (S5P_VA_GPIO + 0xC40),
-               .config = &gpio_cfg_noint,
-               .irq_base = IRQ_EINT(16),
-               .chip   = {
-                       .base   = S5PV210_GPH2(0),
-                       .ngpio  = S5PV210_GPIO_H2_NR,
-                       .label  = "GPH2",
-                       .to_irq = samsung_gpiolib_to_irq,
-               },
-       }, {
-               .base   = (S5P_VA_GPIO + 0xC60),
-               .config = &gpio_cfg_noint,
-               .irq_base = IRQ_EINT(24),
-               .chip   = {
-                       .base   = S5PV210_GPH3(0),
-                       .ngpio  = S5PV210_GPIO_H3_NR,
-                       .label  = "GPH3",
-                       .to_irq = samsung_gpiolib_to_irq,
-               },
-       },
-};
-
-static __init int s5pv210_gpiolib_init(void)
-{
-       struct s3c_gpio_chip *chip = s5pv210_gpio_4bit;
-       int nr_chips = ARRAY_SIZE(s5pv210_gpio_4bit);
-       int gpioint_group = 0;
-       int i = 0;
-
-       for (i = 0; i < nr_chips; i++, chip++) {
-               if (chip->config == NULL) {
-                       chip->config = &gpio_cfg;
-                       chip->group = gpioint_group++;
-               }
-               if (chip->base == NULL)
-                       chip->base = S5PV210_BANK_BASE(i);
-       }
-
-       samsung_gpiolib_add_4bit_chips(s5pv210_gpio_4bit, nr_chips);
-       s5p_register_gpioint_bank(IRQ_GPIOINT, 0, S5P_GPIOINT_GROUP_MAXNR);
-
-       return 0;
-}
-core_initcall(s5pv210_gpiolib_init);
diff --git a/drivers/gpio/gpio-samsung.c b/drivers/gpio/gpio-samsung.c
new file mode 100644 (file)
index 0000000..b6be77a
--- /dev/null
@@ -0,0 +1,2688 @@
+/*
+ * Copyright (c) 2009-2011 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ *
+ * Copyright 2008 Openmoko, Inc.
+ * Copyright 2008 Simtec Electronics
+ *      Ben Dooks <ben@simtec.co.uk>
+ *      http://armlinux.simtec.co.uk/
+ *
+ * SAMSUNG - GPIOlib support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+#include <linux/gpio.h>
+#include <linux/init.h>
+#include <linux/spinlock.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/sysdev.h>
+#include <linux/ioport.h>
+
+#include <asm/irq.h>
+
+#include <mach/hardware.h>
+#include <mach/map.h>
+#include <mach/regs-clock.h>
+#include <mach/regs-gpio.h>
+
+#include <plat/cpu.h>
+#include <plat/gpio-core.h>
+#include <plat/gpio-cfg.h>
+#include <plat/gpio-cfg-helpers.h>
+#include <plat/gpio-fns.h>
+#include <plat/pm.h>
+
+#ifndef DEBUG_GPIO
+#define gpio_dbg(x...) do { } while (0)
+#else
+#define gpio_dbg(x...) printk(KERN_DEBUG x)
+#endif
+
+int samsung_gpio_setpull_updown(struct samsung_gpio_chip *chip,
+                               unsigned int off, samsung_gpio_pull_t pull)
+{
+       void __iomem *reg = chip->base + 0x08;
+       int shift = off * 2;
+       u32 pup;
+
+       pup = __raw_readl(reg);
+       pup &= ~(3 << shift);
+       pup |= pull << shift;
+       __raw_writel(pup, reg);
+
+       return 0;
+}
+
+samsung_gpio_pull_t samsung_gpio_getpull_updown(struct samsung_gpio_chip *chip,
+                                               unsigned int off)
+{
+       void __iomem *reg = chip->base + 0x08;
+       int shift = off * 2;
+       u32 pup = __raw_readl(reg);
+
+       pup >>= shift;
+       pup &= 0x3;
+
+       return (__force samsung_gpio_pull_t)pup;
+}
+
+int s3c2443_gpio_setpull(struct samsung_gpio_chip *chip,
+                        unsigned int off, samsung_gpio_pull_t pull)
+{
+       switch (pull) {
+       case S3C_GPIO_PULL_NONE:
+               pull = 0x01;
+               break;
+       case S3C_GPIO_PULL_UP:
+               pull = 0x00;
+               break;
+       case S3C_GPIO_PULL_DOWN:
+               pull = 0x02;
+               break;
+       }
+       return samsung_gpio_setpull_updown(chip, off, pull);
+}
+
+samsung_gpio_pull_t s3c2443_gpio_getpull(struct samsung_gpio_chip *chip,
+                                        unsigned int off)
+{
+       samsung_gpio_pull_t pull;
+
+       pull = samsung_gpio_getpull_updown(chip, off);
+
+       switch (pull) {
+       case 0x00:
+               pull = S3C_GPIO_PULL_UP;
+               break;
+       case 0x01:
+       case 0x03:
+               pull = S3C_GPIO_PULL_NONE;
+               break;
+       case 0x02:
+               pull = S3C_GPIO_PULL_DOWN;
+               break;
+       }
+
+       return pull;
+}
+
+static int s3c24xx_gpio_setpull_1(struct samsung_gpio_chip *chip,
+                                 unsigned int off, samsung_gpio_pull_t pull,
+                                 samsung_gpio_pull_t updown)
+{
+       void __iomem *reg = chip->base + 0x08;
+       u32 pup = __raw_readl(reg);
+
+       if (pull == updown)
+               pup &= ~(1 << off);
+       else if (pull == S3C_GPIO_PULL_NONE)
+               pup |= (1 << off);
+       else
+               return -EINVAL;
+
+       __raw_writel(pup, reg);
+       return 0;
+}
+
+static samsung_gpio_pull_t s3c24xx_gpio_getpull_1(struct samsung_gpio_chip *chip,
+                                                 unsigned int off,
+                                                 samsung_gpio_pull_t updown)
+{
+       void __iomem *reg = chip->base + 0x08;
+       u32 pup = __raw_readl(reg);
+
+       pup &= (1 << off);
+       return pup ? S3C_GPIO_PULL_NONE : updown;
+}
+
+samsung_gpio_pull_t s3c24xx_gpio_getpull_1up(struct samsung_gpio_chip *chip,
+                                            unsigned int off)
+{
+       return s3c24xx_gpio_getpull_1(chip, off, S3C_GPIO_PULL_UP);
+}
+
+int s3c24xx_gpio_setpull_1up(struct samsung_gpio_chip *chip,
+                            unsigned int off, samsung_gpio_pull_t pull)
+{
+       return s3c24xx_gpio_setpull_1(chip, off, pull, S3C_GPIO_PULL_UP);
+}
+
+samsung_gpio_pull_t s3c24xx_gpio_getpull_1down(struct samsung_gpio_chip *chip,
+                                              unsigned int off)
+{
+       return s3c24xx_gpio_getpull_1(chip, off, S3C_GPIO_PULL_DOWN);
+}
+
+int s3c24xx_gpio_setpull_1down(struct samsung_gpio_chip *chip,
+                              unsigned int off, samsung_gpio_pull_t pull)
+{
+       return s3c24xx_gpio_setpull_1(chip, off, pull, S3C_GPIO_PULL_DOWN);
+}
+
+static int exynos4_gpio_setpull(struct samsung_gpio_chip *chip,
+                               unsigned int off, samsung_gpio_pull_t pull)
+{
+       if (pull == S3C_GPIO_PULL_UP)
+               pull = 3;
+
+       return samsung_gpio_setpull_updown(chip, off, pull);
+}
+
+static samsung_gpio_pull_t exynos4_gpio_getpull(struct samsung_gpio_chip *chip,
+                                               unsigned int off)
+{
+       samsung_gpio_pull_t pull;
+
+       pull = samsung_gpio_getpull_updown(chip, off);
+
+       if (pull == 3)
+               pull = S3C_GPIO_PULL_UP;
+
+       return pull;
+}
+
+/*
+ * samsung_gpio_setcfg_2bit - Samsung 2bit style GPIO configuration.
+ * @chip: The gpio chip that is being configured.
+ * @off: The offset for the GPIO being configured.
+ * @cfg: The configuration value to set.
+ *
+ * This helper deal with the GPIO cases where the control register
+ * has two bits of configuration per gpio, which have the following
+ * functions:
+ *     00 = input
+ *     01 = output
+ *     1x = special function
+ */
+
+static int samsung_gpio_setcfg_2bit(struct samsung_gpio_chip *chip,
+                                   unsigned int off, unsigned int cfg)
+{
+       void __iomem *reg = chip->base;
+       unsigned int shift = off * 2;
+       u32 con;
+
+       if (samsung_gpio_is_cfg_special(cfg)) {
+               cfg &= 0xf;
+               if (cfg > 3)
+                       return -EINVAL;
+
+               cfg <<= shift;
+       }
+
+       con = __raw_readl(reg);
+       con &= ~(0x3 << shift);
+       con |= cfg;
+       __raw_writel(con, reg);
+
+       return 0;
+}
+
+/*
+ * samsung_gpio_getcfg_2bit - Samsung 2bit style GPIO configuration read.
+ * @chip: The gpio chip that is being configured.
+ * @off: The offset for the GPIO being configured.
+ *
+ * The reverse of samsung_gpio_setcfg_2bit(). Will return a value whicg
+ * could be directly passed back to samsung_gpio_setcfg_2bit(), from the
+ * S3C_GPIO_SPECIAL() macro.
+ */
+
+static unsigned int samsung_gpio_getcfg_2bit(struct samsung_gpio_chip *chip,
+                                            unsigned int off)
+{
+       u32 con;
+
+       con = __raw_readl(chip->base);
+       con >>= off * 2;
+       con &= 3;
+
+       /* this conversion works for IN and OUT as well as special mode */
+       return S3C_GPIO_SPECIAL(con);
+}
+
+/*
+ * samsung_gpio_setcfg_4bit - Samsung 4bit single register GPIO config.
+ * @chip: The gpio chip that is being configured.
+ * @off: The offset for the GPIO being configured.
+ * @cfg: The configuration value to set.
+ *
+ * This helper deal with the GPIO cases where the control register has 4 bits
+ * of control per GPIO, generally in the form of:
+ *     0000 = Input
+ *     0001 = Output
+ *     others = Special functions (dependent on bank)
+ *
+ * Note, since the code to deal with the case where there are two control
+ * registers instead of one, we do not have a separate set of functions for
+ * each case.
+ */
+
+static int samsung_gpio_setcfg_4bit(struct samsung_gpio_chip *chip,
+                                   unsigned int off, unsigned int cfg)
+{
+       void __iomem *reg = chip->base;
+       unsigned int shift = (off & 7) * 4;
+       u32 con;
+
+       if (off < 8 && chip->chip.ngpio > 8)
+               reg -= 4;
+
+       if (samsung_gpio_is_cfg_special(cfg)) {
+               cfg &= 0xf;
+               cfg <<= shift;
+       }
+
+       con = __raw_readl(reg);
+       con &= ~(0xf << shift);
+       con |= cfg;
+       __raw_writel(con, reg);
+
+       return 0;
+}
+
+/*
+ * samsung_gpio_getcfg_4bit - Samsung 4bit single register GPIO config read.
+ * @chip: The gpio chip that is being configured.
+ * @off: The offset for the GPIO being configured.
+ *
+ * The reverse of samsung_gpio_setcfg_4bit(), turning a gpio configuration
+ * register setting into a value the software can use, such as could be passed
+ * to samsung_gpio_setcfg_4bit().
+ *
+ * @sa samsung_gpio_getcfg_2bit
+ */
+
+static unsigned samsung_gpio_getcfg_4bit(struct samsung_gpio_chip *chip,
+                                        unsigned int off)
+{
+       void __iomem *reg = chip->base;
+       unsigned int shift = (off & 7) * 4;
+       u32 con;
+
+       if (off < 8 && chip->chip.ngpio > 8)
+               reg -= 4;
+
+       con = __raw_readl(reg);
+       con >>= shift;
+       con &= 0xf;
+
+       /* this conversion works for IN and OUT as well as special mode */
+       return S3C_GPIO_SPECIAL(con);
+}
+
+/*
+ * s3c24xx_gpio_setcfg_abank - S3C24XX style GPIO configuration (Bank A)
+ * @chip: The gpio chip that is being configured.
+ * @off: The offset for the GPIO being configured.
+ * @cfg: The configuration value to set.
+ *
+ * This helper deal with the GPIO cases where the control register
+ * has one bit of configuration for the gpio, where setting the bit
+ * means the pin is in special function mode and unset means output.
+ */
+
+static int s3c24xx_gpio_setcfg_abank(struct samsung_gpio_chip *chip,
+                                    unsigned int off, unsigned int cfg)
+{
+       void __iomem *reg = chip->base;
+       unsigned int shift = off;
+       u32 con;
+
+       if (samsung_gpio_is_cfg_special(cfg)) {
+               cfg &= 0xf;
+
+               /* Map output to 0, and SFN2 to 1 */
+               cfg -= 1;
+               if (cfg > 1)
+                       return -EINVAL;
+
+               cfg <<= shift;
+       }
+
+       con = __raw_readl(reg);
+       con &= ~(0x1 << shift);
+       con |= cfg;
+       __raw_writel(con, reg);
+
+       return 0;
+}
+
+/*
+ * s3c24xx_gpio_getcfg_abank - S3C24XX style GPIO configuration read (Bank A)
+ * @chip: The gpio chip that is being configured.
+ * @off: The offset for the GPIO being configured.
+ *
+ * The reverse of s3c24xx_gpio_setcfg_abank() turning an GPIO into a usable
+ * GPIO configuration value.
+ *
+ * @sa samsung_gpio_getcfg_2bit
+ * @sa samsung_gpio_getcfg_4bit
+ */
+
+static unsigned s3c24xx_gpio_getcfg_abank(struct samsung_gpio_chip *chip,
+                                         unsigned int off)
+{
+       u32 con;
+
+       con = __raw_readl(chip->base);
+       con >>= off;
+       con &= 1;
+       con++;
+
+       return S3C_GPIO_SFN(con);
+}
+
+static int s5p64x0_gpio_setcfg_rbank(struct samsung_gpio_chip *chip,
+                                    unsigned int off, unsigned int cfg)
+{
+       void __iomem *reg = chip->base;
+       unsigned int shift;
+       u32 con;
+
+       switch (off) {
+       case 0:
+       case 1:
+       case 2:
+       case 3:
+       case 4:
+       case 5:
+               shift = (off & 7) * 4;
+               reg -= 4;
+               break;
+       case 6:
+               shift = ((off + 1) & 7) * 4;
+               reg -= 4;
+       default:
+               shift = ((off + 1) & 7) * 4;
+               break;
+       }
+
+       if (samsung_gpio_is_cfg_special(cfg)) {
+               cfg &= 0xf;
+               cfg <<= shift;
+       }
+
+       con = __raw_readl(reg);
+       con &= ~(0xf << shift);
+       con |= cfg;
+       __raw_writel(con, reg);
+
+       return 0;
+}
+
+static void __init samsung_gpiolib_set_cfg(struct samsung_gpio_cfg *chipcfg,
+                                          int nr_chips)
+{
+       for (; nr_chips > 0; nr_chips--, chipcfg++) {
+               if (!chipcfg->set_config)
+                       chipcfg->set_config = samsung_gpio_setcfg_4bit;
+               if (!chipcfg->get_config)
+                       chipcfg->get_config = samsung_gpio_getcfg_4bit;
+               if (!chipcfg->set_pull)
+                       chipcfg->set_pull = samsung_gpio_setpull_updown;
+               if (!chipcfg->get_pull)
+                       chipcfg->get_pull = samsung_gpio_getpull_updown;
+       }
+}
+
+struct samsung_gpio_cfg s3c24xx_gpiocfg_default = {
+       .set_config     = samsung_gpio_setcfg_2bit,
+       .get_config     = samsung_gpio_getcfg_2bit,
+};
+
+static struct samsung_gpio_cfg s3c24xx_gpiocfg_banka = {
+       .set_config     = s3c24xx_gpio_setcfg_abank,
+       .get_config     = s3c24xx_gpio_getcfg_abank,
+};
+
+static struct samsung_gpio_cfg exynos4_gpio_cfg = {
+       .set_pull       = exynos4_gpio_setpull,
+       .get_pull       = exynos4_gpio_getpull,
+       .set_config     = samsung_gpio_setcfg_4bit,
+       .get_config     = samsung_gpio_getcfg_4bit,
+};
+
+static struct samsung_gpio_cfg s5p64x0_gpio_cfg_rbank = {
+       .cfg_eint       = 0x3,
+       .set_config     = s5p64x0_gpio_setcfg_rbank,
+       .get_config     = samsung_gpio_getcfg_4bit,
+       .set_pull       = samsung_gpio_setpull_updown,
+       .get_pull       = samsung_gpio_getpull_updown,
+};
+
+static struct samsung_gpio_cfg samsung_gpio_cfgs[] = {
+       {
+               .cfg_eint       = 0x0,
+       }, {
+               .cfg_eint       = 0x3,
+       }, {
+               .cfg_eint       = 0x7,
+       }, {
+               .cfg_eint       = 0xF,
+       }, {
+               .cfg_eint       = 0x0,
+               .set_config     = samsung_gpio_setcfg_2bit,
+               .get_config     = samsung_gpio_getcfg_2bit,
+       }, {
+               .cfg_eint       = 0x2,
+               .set_config     = samsung_gpio_setcfg_2bit,
+               .get_config     = samsung_gpio_getcfg_2bit,
+       }, {
+               .cfg_eint       = 0x3,
+               .set_config     = samsung_gpio_setcfg_2bit,
+               .get_config     = samsung_gpio_getcfg_2bit,
+       }, {
+               .set_config     = samsung_gpio_setcfg_2bit,
+               .get_config     = samsung_gpio_getcfg_2bit,
+       },
+};
+
+/*
+ * Default routines for controlling GPIO, based on the original S3C24XX
+ * GPIO functions which deal with the case where each gpio bank of the
+ * chip is as following:
+ *
+ * base + 0x00: Control register, 2 bits per gpio
+ *             gpio n: 2 bits starting at (2*n)
+ *             00 = input, 01 = output, others mean special-function
+ * base + 0x04: Data register, 1 bit per gpio
+ *             bit n: data bit n
+*/
+
+static int samsung_gpiolib_2bit_input(struct gpio_chip *chip, unsigned offset)
+{
+       struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
+       void __iomem *base = ourchip->base;
+       unsigned long flags;
+       unsigned long con;
+
+       samsung_gpio_lock(ourchip, flags);
+
+       con = __raw_readl(base + 0x00);
+       con &= ~(3 << (offset * 2));
+
+       __raw_writel(con, base + 0x00);
+
+       samsung_gpio_unlock(ourchip, flags);
+       return 0;
+}
+
+static int samsung_gpiolib_2bit_output(struct gpio_chip *chip,
+                                      unsigned offset, int value)
+{
+       struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
+       void __iomem *base = ourchip->base;
+       unsigned long flags;
+       unsigned long dat;
+       unsigned long con;
+
+       samsung_gpio_lock(ourchip, flags);
+
+       dat = __raw_readl(base + 0x04);
+       dat &= ~(1 << offset);
+       if (value)
+               dat |= 1 << offset;
+       __raw_writel(dat, base + 0x04);
+
+       con = __raw_readl(base + 0x00);
+       con &= ~(3 << (offset * 2));
+       con |= 1 << (offset * 2);
+
+       __raw_writel(con, base + 0x00);
+       __raw_writel(dat, base + 0x04);
+
+       samsung_gpio_unlock(ourchip, flags);
+       return 0;
+}
+
+/*
+ * The samsung_gpiolib_4bit routines are to control the gpio banks where
+ * the gpio configuration register (GPxCON) has 4 bits per GPIO, as the
+ * following example:
+ *
+ * base + 0x00: Control register, 4 bits per gpio
+ *             gpio n: 4 bits starting at (4*n)
+ *             0000 = input, 0001 = output, others mean special-function
+ * base + 0x04: Data register, 1 bit per gpio
+ *             bit n: data bit n
+ *
+ * Note, since the data register is one bit per gpio and is at base + 0x4
+ * we can use samsung_gpiolib_get and samsung_gpiolib_set to change the
+ * state of the output.
+ */
+
+static int samsung_gpiolib_4bit_input(struct gpio_chip *chip,
+                                     unsigned int offset)
+{
+       struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
+       void __iomem *base = ourchip->base;
+       unsigned long con;
+
+       con = __raw_readl(base + GPIOCON_OFF);
+       con &= ~(0xf << con_4bit_shift(offset));
+       __raw_writel(con, base + GPIOCON_OFF);
+
+       gpio_dbg("%s: %p: CON now %08lx\n", __func__, base, con);
+
+       return 0;
+}
+
+static int samsung_gpiolib_4bit_output(struct gpio_chip *chip,
+                                      unsigned int offset, int value)
+{
+       struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
+       void __iomem *base = ourchip->base;
+       unsigned long con;
+       unsigned long dat;
+
+       con = __raw_readl(base + GPIOCON_OFF);
+       con &= ~(0xf << con_4bit_shift(offset));
+       con |= 0x1 << con_4bit_shift(offset);
+
+       dat = __raw_readl(base + GPIODAT_OFF);
+
+       if (value)
+               dat |= 1 << offset;
+       else
+               dat &= ~(1 << offset);
+
+       __raw_writel(dat, base + GPIODAT_OFF);
+       __raw_writel(con, base + GPIOCON_OFF);
+       __raw_writel(dat, base + GPIODAT_OFF);
+
+       gpio_dbg("%s: %p: CON %08lx, DAT %08lx\n", __func__, base, con, dat);
+
+       return 0;
+}
+
+/*
+ * The next set of routines are for the case where the GPIO configuration
+ * registers are 4 bits per GPIO but there is more than one register (the
+ * bank has more than 8 GPIOs.
+ *
+ * This case is the similar to the 4 bit case, but the registers are as
+ * follows:
+ *
+ * base + 0x00: Control register, 4 bits per gpio (lower 8 GPIOs)
+ *             gpio n: 4 bits starting at (4*n)
+ *             0000 = input, 0001 = output, others mean special-function
+ * base + 0x04: Control register, 4 bits per gpio (up to 8 additions GPIOs)
+ *             gpio n: 4 bits starting at (4*n)
+ *             0000 = input, 0001 = output, others mean special-function
+ * base + 0x08: Data register, 1 bit per gpio
+ *             bit n: data bit n
+ *
+ * To allow us to use the samsung_gpiolib_get and samsung_gpiolib_set
+ * routines we store the 'base + 0x4' address so that these routines see
+ * the data register at ourchip->base + 0x04.
+ */
+
+static int samsung_gpiolib_4bit2_input(struct gpio_chip *chip,
+                                      unsigned int offset)
+{
+       struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
+       void __iomem *base = ourchip->base;
+       void __iomem *regcon = base;
+       unsigned long con;
+
+       if (offset > 7)
+               offset -= 8;
+       else
+               regcon -= 4;
+
+       con = __raw_readl(regcon);
+       con &= ~(0xf << con_4bit_shift(offset));
+       __raw_writel(con, regcon);
+
+       gpio_dbg("%s: %p: CON %08lx\n", __func__, base, con);
+
+       return 0;
+}
+
+static int samsung_gpiolib_4bit2_output(struct gpio_chip *chip,
+                                       unsigned int offset, int value)
+{
+       struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
+       void __iomem *base = ourchip->base;
+       void __iomem *regcon = base;
+       unsigned long con;
+       unsigned long dat;
+       unsigned con_offset = offset;
+
+       if (con_offset > 7)
+               con_offset -= 8;
+       else
+               regcon -= 4;
+
+       con = __raw_readl(regcon);
+       con &= ~(0xf << con_4bit_shift(con_offset));
+       con |= 0x1 << con_4bit_shift(con_offset);
+
+       dat = __raw_readl(base + GPIODAT_OFF);
+
+       if (value)
+               dat |= 1 << offset;
+       else
+               dat &= ~(1 << offset);
+
+       __raw_writel(dat, base + GPIODAT_OFF);
+       __raw_writel(con, regcon);
+       __raw_writel(dat, base + GPIODAT_OFF);
+
+       gpio_dbg("%s: %p: CON %08lx, DAT %08lx\n", __func__, base, con, dat);
+
+       return 0;
+}
+
+/* The next set of routines are for the case of s3c24xx bank a */
+
+static int s3c24xx_gpiolib_banka_input(struct gpio_chip *chip, unsigned offset)
+{
+       return -EINVAL;
+}
+
+static int s3c24xx_gpiolib_banka_output(struct gpio_chip *chip,
+                                       unsigned offset, int value)
+{
+       struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
+       void __iomem *base = ourchip->base;
+       unsigned long flags;
+       unsigned long dat;
+       unsigned long con;
+
+       local_irq_save(flags);
+
+       con = __raw_readl(base + 0x00);
+       dat = __raw_readl(base + 0x04);
+
+       dat &= ~(1 << offset);
+       if (value)
+               dat |= 1 << offset;
+
+       __raw_writel(dat, base + 0x04);
+
+       con &= ~(1 << offset);
+
+       __raw_writel(con, base + 0x00);
+       __raw_writel(dat, base + 0x04);
+
+       local_irq_restore(flags);
+       return 0;
+}
+
+/* The next set of routines are for the case of s5p64x0 bank r */
+
+static int s5p64x0_gpiolib_rbank_input(struct gpio_chip *chip,
+                                      unsigned int offset)
+{
+       struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
+       void __iomem *base = ourchip->base;
+       void __iomem *regcon = base;
+       unsigned long con;
+       unsigned long flags;
+
+       switch (offset) {
+       case 6:
+               offset += 1;
+       case 0:
+       case 1:
+       case 2:
+       case 3:
+       case 4:
+       case 5:
+               regcon -= 4;
+               break;
+       default:
+               offset -= 7;
+               break;
+       }
+
+       samsung_gpio_lock(ourchip, flags);
+
+       con = __raw_readl(regcon);
+       con &= ~(0xf << con_4bit_shift(offset));
+       __raw_writel(con, regcon);
+
+       samsung_gpio_unlock(ourchip, flags);
+
+       return 0;
+}
+
+static int s5p64x0_gpiolib_rbank_output(struct gpio_chip *chip,
+                                       unsigned int offset, int value)
+{
+       struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
+       void __iomem *base = ourchip->base;
+       void __iomem *regcon = base;
+       unsigned long con;
+       unsigned long dat;
+       unsigned long flags;
+       unsigned con_offset  = offset;
+
+       switch (con_offset) {
+       case 6:
+               con_offset += 1;
+       case 0:
+       case 1:
+       case 2:
+       case 3:
+       case 4:
+       case 5:
+               regcon -= 4;
+               break;
+       default:
+               con_offset -= 7;
+               break;
+       }
+
+       samsung_gpio_lock(ourchip, flags);
+
+       con = __raw_readl(regcon);
+       con &= ~(0xf << con_4bit_shift(con_offset));
+       con |= 0x1 << con_4bit_shift(con_offset);
+
+       dat = __raw_readl(base + GPIODAT_OFF);
+       if (value)
+               dat |= 1 << offset;
+       else
+               dat &= ~(1 << offset);
+
+       __raw_writel(con, regcon);
+       __raw_writel(dat, base + GPIODAT_OFF);
+
+       samsung_gpio_unlock(ourchip, flags);
+
+       return 0;
+}
+
+static void samsung_gpiolib_set(struct gpio_chip *chip,
+                               unsigned offset, int value)
+{
+       struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
+       void __iomem *base = ourchip->base;
+       unsigned long flags;
+       unsigned long dat;
+
+       samsung_gpio_lock(ourchip, flags);
+
+       dat = __raw_readl(base + 0x04);
+       dat &= ~(1 << offset);
+       if (value)
+               dat |= 1 << offset;
+       __raw_writel(dat, base + 0x04);
+
+       samsung_gpio_unlock(ourchip, flags);
+}
+
+static int samsung_gpiolib_get(struct gpio_chip *chip, unsigned offset)
+{
+       struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
+       unsigned long val;
+
+       val = __raw_readl(ourchip->base + 0x04);
+       val >>= offset;
+       val &= 1;
+
+       return val;
+}
+
+/*
+ * CONFIG_S3C_GPIO_TRACK enables the tracking of the s3c specific gpios
+ * for use with the configuration calls, and other parts of the s3c gpiolib
+ * support code.
+ *
+ * Not all s3c support code will need this, as some configurations of cpu
+ * may only support one or two different configuration options and have an
+ * easy gpio to samsung_gpio_chip mapping function. If this is the case, then
+ * the machine support file should provide its own samsung_gpiolib_getchip()
+ * and any other necessary functions.
+ */
+
+#ifdef CONFIG_S3C_GPIO_TRACK
+struct samsung_gpio_chip *s3c_gpios[S3C_GPIO_END];
+
+static __init void s3c_gpiolib_track(struct samsung_gpio_chip *chip)
+{
+       unsigned int gpn;
+       int i;
+
+       gpn = chip->chip.base;
+       for (i = 0; i < chip->chip.ngpio; i++, gpn++) {
+               BUG_ON(gpn >= ARRAY_SIZE(s3c_gpios));
+               s3c_gpios[gpn] = chip;
+       }
+}
+#endif /* CONFIG_S3C_GPIO_TRACK */
+
+/*
+ * samsung_gpiolib_add() - add the Samsung gpio_chip.
+ * @chip: The chip to register
+ *
+ * This is a wrapper to gpiochip_add() that takes our specific gpio chip
+ * information and makes the necessary alterations for the platform and
+ * notes the information for use with the configuration systems and any
+ * other parts of the system.
+ */
+
+static void __init samsung_gpiolib_add(struct samsung_gpio_chip *chip)
+{
+       struct gpio_chip *gc = &chip->chip;
+       int ret;
+
+       BUG_ON(!chip->base);
+       BUG_ON(!gc->label);
+       BUG_ON(!gc->ngpio);
+
+       spin_lock_init(&chip->lock);
+
+       if (!gc->direction_input)
+               gc->direction_input = samsung_gpiolib_2bit_input;
+       if (!gc->direction_output)
+               gc->direction_output = samsung_gpiolib_2bit_output;
+       if (!gc->set)
+               gc->set = samsung_gpiolib_set;
+       if (!gc->get)
+               gc->get = samsung_gpiolib_get;
+
+#ifdef CONFIG_PM
+       if (chip->pm != NULL) {
+               if (!chip->pm->save || !chip->pm->resume)
+                       printk(KERN_ERR "gpio: %s has missing PM functions\n",
+                              gc->label);
+       } else
+               printk(KERN_ERR "gpio: %s has no PM function\n", gc->label);
+#endif
+
+       /* gpiochip_add() prints own failure message on error. */
+       ret = gpiochip_add(gc);
+       if (ret >= 0)
+               s3c_gpiolib_track(chip);
+}
+
+static void __init s3c24xx_gpiolib_add_chips(struct samsung_gpio_chip *chip,
+                                            int nr_chips, void __iomem *base)
+{
+       int i;
+       struct gpio_chip *gc = &chip->chip;
+
+       for (i = 0 ; i < nr_chips; i++, chip++) {
+               if (!chip->config)
+                       chip->config = &s3c24xx_gpiocfg_default;
+               if (!chip->pm)
+                       chip->pm = __gpio_pm(&samsung_gpio_pm_2bit);
+               if ((base != NULL) && (chip->base == NULL))
+                       chip->base = base + ((i) * 0x10);
+
+               if (!gc->direction_input)
+                       gc->direction_input = samsung_gpiolib_2bit_input;
+               if (!gc->direction_output)
+                       gc->direction_output = samsung_gpiolib_2bit_output;
+
+               samsung_gpiolib_add(chip);
+       }
+}
+
+static void __init samsung_gpiolib_add_2bit_chips(struct samsung_gpio_chip *chip,
+                                                 int nr_chips, void __iomem *base,
+                                                 unsigned int offset)
+{
+       int i;
+
+       for (i = 0 ; i < nr_chips; i++, chip++) {
+               chip->chip.direction_input = samsung_gpiolib_2bit_input;
+               chip->chip.direction_output = samsung_gpiolib_2bit_output;
+
+               if (!chip->config)
+                       chip->config = &samsung_gpio_cfgs[7];
+               if (!chip->pm)
+                       chip->pm = __gpio_pm(&samsung_gpio_pm_2bit);
+               if ((base != NULL) && (chip->base == NULL))
+                       chip->base = base + ((i) * offset);
+
+               samsung_gpiolib_add(chip);
+       }
+}
+
+/*
+ * samsung_gpiolib_add_4bit_chips - 4bit single register GPIO config.
+ * @chip: The gpio chip that is being configured.
+ * @nr_chips: The no of chips (gpio ports) for the GPIO being configured.
+ *
+ * This helper deal with the GPIO cases where the control register has 4 bits
+ * of control per GPIO, generally in the form of:
+ * 0000 = Input
+ * 0001 = Output
+ * others = Special functions (dependent on bank)
+ *
+ * Note, since the code to deal with the case where there are two control
+ * registers instead of one, we do not have a separate set of function
+ * (samsung_gpiolib_add_4bit2_chips)for each case.
+ */
+
+static void __init samsung_gpiolib_add_4bit_chips(struct samsung_gpio_chip *chip,
+                                                 int nr_chips, void __iomem *base)
+{
+       int i;
+
+       for (i = 0 ; i < nr_chips; i++, chip++) {
+               chip->chip.direction_input = samsung_gpiolib_4bit_input;
+               chip->chip.direction_output = samsung_gpiolib_4bit_output;
+
+               if (!chip->config)
+                       chip->config = &samsung_gpio_cfgs[2];
+               if (!chip->pm)
+                       chip->pm = __gpio_pm(&samsung_gpio_pm_4bit);
+               if ((base != NULL) && (chip->base == NULL))
+                       chip->base = base + ((i) * 0x20);
+
+               samsung_gpiolib_add(chip);
+       }
+}
+
+static void __init samsung_gpiolib_add_4bit2_chips(struct samsung_gpio_chip *chip,
+                                                  int nr_chips)
+{
+       for (; nr_chips > 0; nr_chips--, chip++) {
+               chip->chip.direction_input = samsung_gpiolib_4bit2_input;
+               chip->chip.direction_output = samsung_gpiolib_4bit2_output;
+
+               if (!chip->config)
+                       chip->config = &samsung_gpio_cfgs[2];
+               if (!chip->pm)
+                       chip->pm = __gpio_pm(&samsung_gpio_pm_4bit);
+
+               samsung_gpiolib_add(chip);
+       }
+}
+
+static void __init s5p64x0_gpiolib_add_rbank(struct samsung_gpio_chip *chip,
+                                            int nr_chips)
+{
+       for (; nr_chips > 0; nr_chips--, chip++) {
+               chip->chip.direction_input = s5p64x0_gpiolib_rbank_input;
+               chip->chip.direction_output = s5p64x0_gpiolib_rbank_output;
+
+               if (!chip->pm)
+                       chip->pm = __gpio_pm(&samsung_gpio_pm_4bit);
+
+               samsung_gpiolib_add(chip);
+       }
+}
+
+int samsung_gpiolib_to_irq(struct gpio_chip *chip, unsigned int offset)
+{
+       struct samsung_gpio_chip *samsung_chip = container_of(chip, struct samsung_gpio_chip, chip);
+
+       return samsung_chip->irq_base + offset;
+}
+
+#ifdef CONFIG_PLAT_S3C24XX
+static int s3c24xx_gpiolib_fbank_to_irq(struct gpio_chip *chip, unsigned offset)
+{
+       if (offset < 4)
+               return IRQ_EINT0 + offset;
+
+       if (offset < 8)
+               return IRQ_EINT4 + offset - 4;
+
+       return -EINVAL;
+}
+#endif
+
+#ifdef CONFIG_PLAT_S3C64XX
+static int s3c64xx_gpiolib_mbank_to_irq(struct gpio_chip *chip, unsigned pin)
+{
+       return pin < 5 ? IRQ_EINT(23) + pin : -ENXIO;
+}
+
+static int s3c64xx_gpiolib_lbank_to_irq(struct gpio_chip *chip, unsigned pin)
+{
+       return pin >= 8 ? IRQ_EINT(16) + pin - 8 : -ENXIO;
+}
+#endif
+
+struct samsung_gpio_chip s3c24xx_gpios[] = {
+#ifdef CONFIG_PLAT_S3C24XX
+       {
+               .config = &s3c24xx_gpiocfg_banka,
+               .chip   = {
+                       .base                   = S3C2410_GPA(0),
+                       .owner                  = THIS_MODULE,
+                       .label                  = "GPIOA",
+                       .ngpio                  = 24,
+                       .direction_input        = s3c24xx_gpiolib_banka_input,
+                       .direction_output       = s3c24xx_gpiolib_banka_output,
+               },
+       }, {
+               .chip   = {
+                       .base   = S3C2410_GPB(0),
+                       .owner  = THIS_MODULE,
+                       .label  = "GPIOB",
+                       .ngpio  = 16,
+               },
+       }, {
+               .chip   = {
+                       .base   = S3C2410_GPC(0),
+                       .owner  = THIS_MODULE,
+                       .label  = "GPIOC",
+                       .ngpio  = 16,
+               },
+       }, {
+               .chip   = {
+                       .base   = S3C2410_GPD(0),
+                       .owner  = THIS_MODULE,
+                       .label  = "GPIOD",
+                       .ngpio  = 16,
+               },
+       }, {
+               .chip   = {
+                       .base   = S3C2410_GPE(0),
+                       .label  = "GPIOE",
+                       .owner  = THIS_MODULE,
+                       .ngpio  = 16,
+               },
+       }, {
+               .chip   = {
+                       .base   = S3C2410_GPF(0),
+                       .owner  = THIS_MODULE,
+                       .label  = "GPIOF",
+                       .ngpio  = 8,
+                       .to_irq = s3c24xx_gpiolib_fbank_to_irq,
+               },
+       }, {
+               .irq_base = IRQ_EINT8,
+               .chip   = {
+                       .base   = S3C2410_GPG(0),
+                       .owner  = THIS_MODULE,
+                       .label  = "GPIOG",
+                       .ngpio  = 16,
+                       .to_irq = samsung_gpiolib_to_irq,
+               },
+       }, {
+               .chip   = {
+                       .base   = S3C2410_GPH(0),
+                       .owner  = THIS_MODULE,
+                       .label  = "GPIOH",
+                       .ngpio  = 11,
+               },
+       },
+               /* GPIOS for the S3C2443 and later devices. */
+       {
+               .base   = S3C2440_GPJCON,
+               .chip   = {
+                       .base   = S3C2410_GPJ(0),
+                       .owner  = THIS_MODULE,
+                       .label  = "GPIOJ",
+                       .ngpio  = 16,
+               },
+       }, {
+               .base   = S3C2443_GPKCON,
+               .chip   = {
+                       .base   = S3C2410_GPK(0),
+                       .owner  = THIS_MODULE,
+                       .label  = "GPIOK",
+                       .ngpio  = 16,
+               },
+       }, {
+               .base   = S3C2443_GPLCON,
+               .chip   = {
+                       .base   = S3C2410_GPL(0),
+                       .owner  = THIS_MODULE,
+                       .label  = "GPIOL",
+                       .ngpio  = 15,
+               },
+       }, {
+               .base   = S3C2443_GPMCON,
+               .chip   = {
+                       .base   = S3C2410_GPM(0),
+                       .owner  = THIS_MODULE,
+                       .label  = "GPIOM",
+                       .ngpio  = 2,
+               },
+       },
+#endif
+};
+
+/*
+ * GPIO bank summary:
+ *
+ * Bank        GPIOs   Style   SlpCon  ExtInt Group
+ * A   8       4Bit    Yes     1
+ * B   7       4Bit    Yes     1
+ * C   8       4Bit    Yes     2
+ * D   5       4Bit    Yes     3
+ * E   5       4Bit    Yes     None
+ * F   16      2Bit    Yes     4 [1]
+ * G   7       4Bit    Yes     5
+ * H   10      4Bit[2] Yes     6
+ * I   16      2Bit    Yes     None
+ * J   12      2Bit    Yes     None
+ * K   16      4Bit[2] No      None
+ * L   15      4Bit[2] No      None
+ * M   6       4Bit    No      IRQ_EINT
+ * N   16      2Bit    No      IRQ_EINT
+ * O   16      2Bit    Yes     7
+ * P   15      2Bit    Yes     8
+ * Q   9       2Bit    Yes     9
+ *
+ * [1] BANKF pins 14,15 do not form part of the external interrupt sources
+ * [2] BANK has two control registers, GPxCON0 and GPxCON1
+ */
+
+static struct samsung_gpio_chip s3c64xx_gpios_4bit[] = {
+#ifdef CONFIG_PLAT_S3C64XX
+       {
+               .chip   = {
+                       .base   = S3C64XX_GPA(0),
+                       .ngpio  = S3C64XX_GPIO_A_NR,
+                       .label  = "GPA",
+               },
+       }, {
+               .chip   = {
+                       .base   = S3C64XX_GPB(0),
+                       .ngpio  = S3C64XX_GPIO_B_NR,
+                       .label  = "GPB",
+               },
+       }, {
+               .chip   = {
+                       .base   = S3C64XX_GPC(0),
+                       .ngpio  = S3C64XX_GPIO_C_NR,
+                       .label  = "GPC",
+               },
+       }, {
+               .chip   = {
+                       .base   = S3C64XX_GPD(0),
+                       .ngpio  = S3C64XX_GPIO_D_NR,
+                       .label  = "GPD",
+               },
+       }, {
+               .config = &samsung_gpio_cfgs[0],
+               .chip   = {
+                       .base   = S3C64XX_GPE(0),
+                       .ngpio  = S3C64XX_GPIO_E_NR,
+                       .label  = "GPE",
+               },
+       }, {
+               .base   = S3C64XX_GPG_BASE,
+               .chip   = {
+                       .base   = S3C64XX_GPG(0),
+                       .ngpio  = S3C64XX_GPIO_G_NR,
+                       .label  = "GPG",
+               },
+       }, {
+               .base   = S3C64XX_GPM_BASE,
+               .config = &samsung_gpio_cfgs[1],
+               .chip   = {
+                       .base   = S3C64XX_GPM(0),
+                       .ngpio  = S3C64XX_GPIO_M_NR,
+                       .label  = "GPM",
+                       .to_irq = s3c64xx_gpiolib_mbank_to_irq,
+               },
+       },
+#endif
+};
+
+static struct samsung_gpio_chip s3c64xx_gpios_4bit2[] = {
+#ifdef CONFIG_PLAT_S3C64XX
+       {
+               .base   = S3C64XX_GPH_BASE + 0x4,
+               .chip   = {
+                       .base   = S3C64XX_GPH(0),
+                       .ngpio  = S3C64XX_GPIO_H_NR,
+                       .label  = "GPH",
+               },
+       }, {
+               .base   = S3C64XX_GPK_BASE + 0x4,
+               .config = &samsung_gpio_cfgs[0],
+               .chip   = {
+                       .base   = S3C64XX_GPK(0),
+                       .ngpio  = S3C64XX_GPIO_K_NR,
+                       .label  = "GPK",
+               },
+       }, {
+               .base   = S3C64XX_GPL_BASE + 0x4,
+               .config = &samsung_gpio_cfgs[1],
+               .chip   = {
+                       .base   = S3C64XX_GPL(0),
+                       .ngpio  = S3C64XX_GPIO_L_NR,
+                       .label  = "GPL",
+                       .to_irq = s3c64xx_gpiolib_lbank_to_irq,
+               },
+       },
+#endif
+};
+
+static struct samsung_gpio_chip s3c64xx_gpios_2bit[] = {
+#ifdef CONFIG_PLAT_S3C64XX
+       {
+               .base   = S3C64XX_GPF_BASE,
+               .config = &samsung_gpio_cfgs[6],
+               .chip   = {
+                       .base   = S3C64XX_GPF(0),
+                       .ngpio  = S3C64XX_GPIO_F_NR,
+                       .label  = "GPF",
+               },
+       }, {
+               .config = &samsung_gpio_cfgs[7],
+               .chip   = {
+                       .base   = S3C64XX_GPI(0),
+                       .ngpio  = S3C64XX_GPIO_I_NR,
+                       .label  = "GPI",
+               },
+       }, {
+               .config = &samsung_gpio_cfgs[7],
+               .chip   = {
+                       .base   = S3C64XX_GPJ(0),
+                       .ngpio  = S3C64XX_GPIO_J_NR,
+                       .label  = "GPJ",
+               },
+       }, {
+               .config = &samsung_gpio_cfgs[6],
+               .chip   = {
+                       .base   = S3C64XX_GPO(0),
+                       .ngpio  = S3C64XX_GPIO_O_NR,
+                       .label  = "GPO",
+               },
+       }, {
+               .config = &samsung_gpio_cfgs[6],
+               .chip   = {
+                       .base   = S3C64XX_GPP(0),
+                       .ngpio  = S3C64XX_GPIO_P_NR,
+                       .label  = "GPP",
+               },
+       }, {
+               .config = &samsung_gpio_cfgs[6],
+               .chip   = {
+                       .base   = S3C64XX_GPQ(0),
+                       .ngpio  = S3C64XX_GPIO_Q_NR,
+                       .label  = "GPQ",
+               },
+       }, {
+               .base   = S3C64XX_GPN_BASE,
+               .irq_base = IRQ_EINT(0),
+               .config = &samsung_gpio_cfgs[5],
+               .chip   = {
+                       .base   = S3C64XX_GPN(0),
+                       .ngpio  = S3C64XX_GPIO_N_NR,
+                       .label  = "GPN",
+                       .to_irq = samsung_gpiolib_to_irq,
+               },
+       },
+#endif
+};
+
+/*
+ * S5P6440 GPIO bank summary:
+ *
+ * Bank        GPIOs   Style   SlpCon  ExtInt Group
+ * A   6       4Bit    Yes     1
+ * B   7       4Bit    Yes     1
+ * C   8       4Bit    Yes     2
+ * F   2       2Bit    Yes     4 [1]
+ * G   7       4Bit    Yes     5
+ * H   10      4Bit[2] Yes     6
+ * I   16      2Bit    Yes     None
+ * J   12      2Bit    Yes     None
+ * N   16      2Bit    No      IRQ_EINT
+ * P   8       2Bit    Yes     8
+ * R   15      4Bit[2] Yes     8
+ */
+
+static struct samsung_gpio_chip s5p6440_gpios_4bit[] = {
+#ifdef CONFIG_CPU_S5P6440
+       {
+               .chip   = {
+                       .base   = S5P6440_GPA(0),
+                       .ngpio  = S5P6440_GPIO_A_NR,
+                       .label  = "GPA",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5P6440_GPB(0),
+                       .ngpio  = S5P6440_GPIO_B_NR,
+                       .label  = "GPB",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5P6440_GPC(0),
+                       .ngpio  = S5P6440_GPIO_C_NR,
+                       .label  = "GPC",
+               },
+       }, {
+               .base   = S5P64X0_GPG_BASE,
+               .chip   = {
+                       .base   = S5P6440_GPG(0),
+                       .ngpio  = S5P6440_GPIO_G_NR,
+                       .label  = "GPG",
+               },
+       },
+#endif
+};
+
+static struct samsung_gpio_chip s5p6440_gpios_4bit2[] = {
+#ifdef CONFIG_CPU_S5P6440
+       {
+               .base   = S5P64X0_GPH_BASE + 0x4,
+               .chip   = {
+                       .base   = S5P6440_GPH(0),
+                       .ngpio  = S5P6440_GPIO_H_NR,
+                       .label  = "GPH",
+               },
+       },
+#endif
+};
+
+static struct samsung_gpio_chip s5p6440_gpios_rbank[] = {
+#ifdef CONFIG_CPU_S5P6440
+       {
+               .base   = S5P64X0_GPR_BASE + 0x4,
+               .config = &s5p64x0_gpio_cfg_rbank,
+               .chip   = {
+                       .base   = S5P6440_GPR(0),
+                       .ngpio  = S5P6440_GPIO_R_NR,
+                       .label  = "GPR",
+               },
+       },
+#endif
+};
+
+static struct samsung_gpio_chip s5p6440_gpios_2bit[] = {
+#ifdef CONFIG_CPU_S5P6440
+       {
+               .base   = S5P64X0_GPF_BASE,
+               .config = &samsung_gpio_cfgs[6],
+               .chip   = {
+                       .base   = S5P6440_GPF(0),
+                       .ngpio  = S5P6440_GPIO_F_NR,
+                       .label  = "GPF",
+               },
+       }, {
+               .base   = S5P64X0_GPI_BASE,
+               .config = &samsung_gpio_cfgs[4],
+               .chip   = {
+                       .base   = S5P6440_GPI(0),
+                       .ngpio  = S5P6440_GPIO_I_NR,
+                       .label  = "GPI",
+               },
+       }, {
+               .base   = S5P64X0_GPJ_BASE,
+               .config = &samsung_gpio_cfgs[4],
+               .chip   = {
+                       .base   = S5P6440_GPJ(0),
+                       .ngpio  = S5P6440_GPIO_J_NR,
+                       .label  = "GPJ",
+               },
+       }, {
+               .base   = S5P64X0_GPN_BASE,
+               .config = &samsung_gpio_cfgs[5],
+               .chip   = {
+                       .base   = S5P6440_GPN(0),
+                       .ngpio  = S5P6440_GPIO_N_NR,
+                       .label  = "GPN",
+               },
+       }, {
+               .base   = S5P64X0_GPP_BASE,
+               .config = &samsung_gpio_cfgs[6],
+               .chip   = {
+                       .base   = S5P6440_GPP(0),
+                       .ngpio  = S5P6440_GPIO_P_NR,
+                       .label  = "GPP",
+               },
+       },
+#endif
+};
+
+/*
+ * S5P6450 GPIO bank summary:
+ *
+ * Bank        GPIOs   Style   SlpCon  ExtInt Group
+ * A   6       4Bit    Yes     1
+ * B   7       4Bit    Yes     1
+ * C   8       4Bit    Yes     2
+ * D   8       4Bit    Yes     None
+ * F   2       2Bit    Yes     None
+ * G   14      4Bit[2] Yes     5
+ * H   10      4Bit[2] Yes     6
+ * I   16      2Bit    Yes     None
+ * J   12      2Bit    Yes     None
+ * K   5       4Bit    Yes     None
+ * N   16      2Bit    No      IRQ_EINT
+ * P   11      2Bit    Yes     8
+ * Q   14      2Bit    Yes     None
+ * R   15      4Bit[2] Yes     None
+ * S   8       2Bit    Yes     None
+ *
+ * [1] BANKF pins 14,15 do not form part of the external interrupt sources
+ * [2] BANK has two control registers, GPxCON0 and GPxCON1
+ */
+
+static struct samsung_gpio_chip s5p6450_gpios_4bit[] = {
+#ifdef CONFIG_CPU_S5P6450
+       {
+               .chip   = {
+                       .base   = S5P6450_GPA(0),
+                       .ngpio  = S5P6450_GPIO_A_NR,
+                       .label  = "GPA",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5P6450_GPB(0),
+                       .ngpio  = S5P6450_GPIO_B_NR,
+                       .label  = "GPB",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5P6450_GPC(0),
+                       .ngpio  = S5P6450_GPIO_C_NR,
+                       .label  = "GPC",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5P6450_GPD(0),
+                       .ngpio  = S5P6450_GPIO_D_NR,
+                       .label  = "GPD",
+               },
+       }, {
+               .base   = S5P6450_GPK_BASE,
+               .chip   = {
+                       .base   = S5P6450_GPK(0),
+                       .ngpio  = S5P6450_GPIO_K_NR,
+                       .label  = "GPK",
+               },
+       },
+#endif
+};
+
+static struct samsung_gpio_chip s5p6450_gpios_4bit2[] = {
+#ifdef CONFIG_CPU_S5P6450
+       {
+               .base   = S5P64X0_GPG_BASE + 0x4,
+               .chip   = {
+                       .base   = S5P6450_GPG(0),
+                       .ngpio  = S5P6450_GPIO_G_NR,
+                       .label  = "GPG",
+               },
+       }, {
+               .base   = S5P64X0_GPH_BASE + 0x4,
+               .chip   = {
+                       .base   = S5P6450_GPH(0),
+                       .ngpio  = S5P6450_GPIO_H_NR,
+                       .label  = "GPH",
+               },
+       },
+#endif
+};
+
+static struct samsung_gpio_chip s5p6450_gpios_rbank[] = {
+#ifdef CONFIG_CPU_S5P6450
+       {
+               .base   = S5P64X0_GPR_BASE + 0x4,
+               .config = &s5p64x0_gpio_cfg_rbank,
+               .chip   = {
+                       .base   = S5P6450_GPR(0),
+                       .ngpio  = S5P6450_GPIO_R_NR,
+                       .label  = "GPR",
+               },
+       },
+#endif
+};
+
+static struct samsung_gpio_chip s5p6450_gpios_2bit[] = {
+#ifdef CONFIG_CPU_S5P6450
+       {
+               .base   = S5P64X0_GPF_BASE,
+               .config = &samsung_gpio_cfgs[6],
+               .chip   = {
+                       .base   = S5P6450_GPF(0),
+                       .ngpio  = S5P6450_GPIO_F_NR,
+                       .label  = "GPF",
+               },
+       }, {
+               .base   = S5P64X0_GPI_BASE,
+               .config = &samsung_gpio_cfgs[4],
+               .chip   = {
+                       .base   = S5P6450_GPI(0),
+                       .ngpio  = S5P6450_GPIO_I_NR,
+                       .label  = "GPI",
+               },
+       }, {
+               .base   = S5P64X0_GPJ_BASE,
+               .config = &samsung_gpio_cfgs[4],
+               .chip   = {
+                       .base   = S5P6450_GPJ(0),
+                       .ngpio  = S5P6450_GPIO_J_NR,
+                       .label  = "GPJ",
+               },
+       }, {
+               .base   = S5P64X0_GPN_BASE,
+               .config = &samsung_gpio_cfgs[5],
+               .chip   = {
+                       .base   = S5P6450_GPN(0),
+                       .ngpio  = S5P6450_GPIO_N_NR,
+                       .label  = "GPN",
+               },
+       }, {
+               .base   = S5P64X0_GPP_BASE,
+               .config = &samsung_gpio_cfgs[6],
+               .chip   = {
+                       .base   = S5P6450_GPP(0),
+                       .ngpio  = S5P6450_GPIO_P_NR,
+                       .label  = "GPP",
+               },
+       }, {
+               .base   = S5P6450_GPQ_BASE,
+               .config = &samsung_gpio_cfgs[5],
+               .chip   = {
+                       .base   = S5P6450_GPQ(0),
+                       .ngpio  = S5P6450_GPIO_Q_NR,
+                       .label  = "GPQ",
+               },
+       }, {
+               .base   = S5P6450_GPS_BASE,
+               .config = &samsung_gpio_cfgs[6],
+               .chip   = {
+                       .base   = S5P6450_GPS(0),
+                       .ngpio  = S5P6450_GPIO_S_NR,
+                       .label  = "GPS",
+               },
+       },
+#endif
+};
+
+/*
+ * S5PC100 GPIO bank summary:
+ *
+ * Bank        GPIOs   Style   INT Type
+ * A0  8       4Bit    GPIO_INT0
+ * A1  5       4Bit    GPIO_INT1
+ * B   8       4Bit    GPIO_INT2
+ * C   5       4Bit    GPIO_INT3
+ * D   7       4Bit    GPIO_INT4
+ * E0  8       4Bit    GPIO_INT5
+ * E1  6       4Bit    GPIO_INT6
+ * F0  8       4Bit    GPIO_INT7
+ * F1  8       4Bit    GPIO_INT8
+ * F2  8       4Bit    GPIO_INT9
+ * F3  4       4Bit    GPIO_INT10
+ * G0  8       4Bit    GPIO_INT11
+ * G1  3       4Bit    GPIO_INT12
+ * G2  7       4Bit    GPIO_INT13
+ * G3  7       4Bit    GPIO_INT14
+ * H0  8       4Bit    WKUP_INT
+ * H1  8       4Bit    WKUP_INT
+ * H2  8       4Bit    WKUP_INT
+ * H3  8       4Bit    WKUP_INT
+ * I   8       4Bit    GPIO_INT15
+ * J0  8       4Bit    GPIO_INT16
+ * J1  5       4Bit    GPIO_INT17
+ * J2  8       4Bit    GPIO_INT18
+ * J3  8       4Bit    GPIO_INT19
+ * J4  4       4Bit    GPIO_INT20
+ * K0  8       4Bit    None
+ * K1  6       4Bit    None
+ * K2  8       4Bit    None
+ * K3  8       4Bit    None
+ * L0  8       4Bit    None
+ * L1  8       4Bit    None
+ * L2  8       4Bit    None
+ * L3  8       4Bit    None
+ */
+
+static struct samsung_gpio_chip s5pc100_gpios_4bit[] = {
+#ifdef CONFIG_CPU_S5PC100
+       {
+               .chip   = {
+                       .base   = S5PC100_GPA0(0),
+                       .ngpio  = S5PC100_GPIO_A0_NR,
+                       .label  = "GPA0",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PC100_GPA1(0),
+                       .ngpio  = S5PC100_GPIO_A1_NR,
+                       .label  = "GPA1",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PC100_GPB(0),
+                       .ngpio  = S5PC100_GPIO_B_NR,
+                       .label  = "GPB",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PC100_GPC(0),
+                       .ngpio  = S5PC100_GPIO_C_NR,
+                       .label  = "GPC",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PC100_GPD(0),
+                       .ngpio  = S5PC100_GPIO_D_NR,
+                       .label  = "GPD",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PC100_GPE0(0),
+                       .ngpio  = S5PC100_GPIO_E0_NR,
+                       .label  = "GPE0",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PC100_GPE1(0),
+                       .ngpio  = S5PC100_GPIO_E1_NR,
+                       .label  = "GPE1",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PC100_GPF0(0),
+                       .ngpio  = S5PC100_GPIO_F0_NR,
+                       .label  = "GPF0",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PC100_GPF1(0),
+                       .ngpio  = S5PC100_GPIO_F1_NR,
+                       .label  = "GPF1",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PC100_GPF2(0),
+                       .ngpio  = S5PC100_GPIO_F2_NR,
+                       .label  = "GPF2",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PC100_GPF3(0),
+                       .ngpio  = S5PC100_GPIO_F3_NR,
+                       .label  = "GPF3",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PC100_GPG0(0),
+                       .ngpio  = S5PC100_GPIO_G0_NR,
+                       .label  = "GPG0",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PC100_GPG1(0),
+                       .ngpio  = S5PC100_GPIO_G1_NR,
+                       .label  = "GPG1",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PC100_GPG2(0),
+                       .ngpio  = S5PC100_GPIO_G2_NR,
+                       .label  = "GPG2",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PC100_GPG3(0),
+                       .ngpio  = S5PC100_GPIO_G3_NR,
+                       .label  = "GPG3",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PC100_GPI(0),
+                       .ngpio  = S5PC100_GPIO_I_NR,
+                       .label  = "GPI",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PC100_GPJ0(0),
+                       .ngpio  = S5PC100_GPIO_J0_NR,
+                       .label  = "GPJ0",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PC100_GPJ1(0),
+                       .ngpio  = S5PC100_GPIO_J1_NR,
+                       .label  = "GPJ1",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PC100_GPJ2(0),
+                       .ngpio  = S5PC100_GPIO_J2_NR,
+                       .label  = "GPJ2",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PC100_GPJ3(0),
+                       .ngpio  = S5PC100_GPIO_J3_NR,
+                       .label  = "GPJ3",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PC100_GPJ4(0),
+                       .ngpio  = S5PC100_GPIO_J4_NR,
+                       .label  = "GPJ4",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PC100_GPK0(0),
+                       .ngpio  = S5PC100_GPIO_K0_NR,
+                       .label  = "GPK0",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PC100_GPK1(0),
+                       .ngpio  = S5PC100_GPIO_K1_NR,
+                       .label  = "GPK1",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PC100_GPK2(0),
+                       .ngpio  = S5PC100_GPIO_K2_NR,
+                       .label  = "GPK2",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PC100_GPK3(0),
+                       .ngpio  = S5PC100_GPIO_K3_NR,
+                       .label  = "GPK3",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PC100_GPL0(0),
+                       .ngpio  = S5PC100_GPIO_L0_NR,
+                       .label  = "GPL0",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PC100_GPL1(0),
+                       .ngpio  = S5PC100_GPIO_L1_NR,
+                       .label  = "GPL1",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PC100_GPL2(0),
+                       .ngpio  = S5PC100_GPIO_L2_NR,
+                       .label  = "GPL2",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PC100_GPL3(0),
+                       .ngpio  = S5PC100_GPIO_L3_NR,
+                       .label  = "GPL3",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PC100_GPL4(0),
+                       .ngpio  = S5PC100_GPIO_L4_NR,
+                       .label  = "GPL4",
+               },
+       }, {
+               .base   = (S5P_VA_GPIO + 0xC00),
+               .irq_base = IRQ_EINT(0),
+               .chip   = {
+                       .base   = S5PC100_GPH0(0),
+                       .ngpio  = S5PC100_GPIO_H0_NR,
+                       .label  = "GPH0",
+                       .to_irq = samsung_gpiolib_to_irq,
+               },
+       }, {
+               .base   = (S5P_VA_GPIO + 0xC20),
+               .irq_base = IRQ_EINT(8),
+               .chip   = {
+                       .base   = S5PC100_GPH1(0),
+                       .ngpio  = S5PC100_GPIO_H1_NR,
+                       .label  = "GPH1",
+                       .to_irq = samsung_gpiolib_to_irq,
+               },
+       }, {
+               .base   = (S5P_VA_GPIO + 0xC40),
+               .irq_base = IRQ_EINT(16),
+               .chip   = {
+                       .base   = S5PC100_GPH2(0),
+                       .ngpio  = S5PC100_GPIO_H2_NR,
+                       .label  = "GPH2",
+                       .to_irq = samsung_gpiolib_to_irq,
+               },
+       }, {
+               .base   = (S5P_VA_GPIO + 0xC60),
+               .irq_base = IRQ_EINT(24),
+               .chip   = {
+                       .base   = S5PC100_GPH3(0),
+                       .ngpio  = S5PC100_GPIO_H3_NR,
+                       .label  = "GPH3",
+                       .to_irq = samsung_gpiolib_to_irq,
+               },
+       },
+#endif
+};
+
+/*
+ * Followings are the gpio banks in S5PV210/S5PC110
+ *
+ * The 'config' member when left to NULL, is initialized to the default
+ * structure samsung_gpio_cfgs[3] in the init function below.
+ *
+ * The 'base' member is also initialized in the init function below.
+ * Note: The initialization of 'base' member of samsung_gpio_chip structure
+ * uses the above macro and depends on the banks being listed in order here.
+ */
+
+static struct samsung_gpio_chip s5pv210_gpios_4bit[] = {
+#ifdef CONFIG_CPU_S5PV210
+       {
+               .chip   = {
+                       .base   = S5PV210_GPA0(0),
+                       .ngpio  = S5PV210_GPIO_A0_NR,
+                       .label  = "GPA0",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PV210_GPA1(0),
+                       .ngpio  = S5PV210_GPIO_A1_NR,
+                       .label  = "GPA1",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PV210_GPB(0),
+                       .ngpio  = S5PV210_GPIO_B_NR,
+                       .label  = "GPB",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PV210_GPC0(0),
+                       .ngpio  = S5PV210_GPIO_C0_NR,
+                       .label  = "GPC0",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PV210_GPC1(0),
+                       .ngpio  = S5PV210_GPIO_C1_NR,
+                       .label  = "GPC1",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PV210_GPD0(0),
+                       .ngpio  = S5PV210_GPIO_D0_NR,
+                       .label  = "GPD0",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PV210_GPD1(0),
+                       .ngpio  = S5PV210_GPIO_D1_NR,
+                       .label  = "GPD1",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PV210_GPE0(0),
+                       .ngpio  = S5PV210_GPIO_E0_NR,
+                       .label  = "GPE0",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PV210_GPE1(0),
+                       .ngpio  = S5PV210_GPIO_E1_NR,
+                       .label  = "GPE1",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PV210_GPF0(0),
+                       .ngpio  = S5PV210_GPIO_F0_NR,
+                       .label  = "GPF0",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PV210_GPF1(0),
+                       .ngpio  = S5PV210_GPIO_F1_NR,
+                       .label  = "GPF1",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PV210_GPF2(0),
+                       .ngpio  = S5PV210_GPIO_F2_NR,
+                       .label  = "GPF2",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PV210_GPF3(0),
+                       .ngpio  = S5PV210_GPIO_F3_NR,
+                       .label  = "GPF3",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PV210_GPG0(0),
+                       .ngpio  = S5PV210_GPIO_G0_NR,
+                       .label  = "GPG0",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PV210_GPG1(0),
+                       .ngpio  = S5PV210_GPIO_G1_NR,
+                       .label  = "GPG1",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PV210_GPG2(0),
+                       .ngpio  = S5PV210_GPIO_G2_NR,
+                       .label  = "GPG2",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PV210_GPG3(0),
+                       .ngpio  = S5PV210_GPIO_G3_NR,
+                       .label  = "GPG3",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PV210_GPI(0),
+                       .ngpio  = S5PV210_GPIO_I_NR,
+                       .label  = "GPI",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PV210_GPJ0(0),
+                       .ngpio  = S5PV210_GPIO_J0_NR,
+                       .label  = "GPJ0",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PV210_GPJ1(0),
+                       .ngpio  = S5PV210_GPIO_J1_NR,
+                       .label  = "GPJ1",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PV210_GPJ2(0),
+                       .ngpio  = S5PV210_GPIO_J2_NR,
+                       .label  = "GPJ2",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PV210_GPJ3(0),
+                       .ngpio  = S5PV210_GPIO_J3_NR,
+                       .label  = "GPJ3",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PV210_GPJ4(0),
+                       .ngpio  = S5PV210_GPIO_J4_NR,
+                       .label  = "GPJ4",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PV210_MP01(0),
+                       .ngpio  = S5PV210_GPIO_MP01_NR,
+                       .label  = "MP01",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PV210_MP02(0),
+                       .ngpio  = S5PV210_GPIO_MP02_NR,
+                       .label  = "MP02",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PV210_MP03(0),
+                       .ngpio  = S5PV210_GPIO_MP03_NR,
+                       .label  = "MP03",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PV210_MP04(0),
+                       .ngpio  = S5PV210_GPIO_MP04_NR,
+                       .label  = "MP04",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PV210_MP05(0),
+                       .ngpio  = S5PV210_GPIO_MP05_NR,
+                       .label  = "MP05",
+               },
+       }, {
+               .base   = (S5P_VA_GPIO + 0xC00),
+               .irq_base = IRQ_EINT(0),
+               .chip   = {
+                       .base   = S5PV210_GPH0(0),
+                       .ngpio  = S5PV210_GPIO_H0_NR,
+                       .label  = "GPH0",
+                       .to_irq = samsung_gpiolib_to_irq,
+               },
+       }, {
+               .base   = (S5P_VA_GPIO + 0xC20),
+               .irq_base = IRQ_EINT(8),
+               .chip   = {
+                       .base   = S5PV210_GPH1(0),
+                       .ngpio  = S5PV210_GPIO_H1_NR,
+                       .label  = "GPH1",
+                       .to_irq = samsung_gpiolib_to_irq,
+               },
+       }, {
+               .base   = (S5P_VA_GPIO + 0xC40),
+               .irq_base = IRQ_EINT(16),
+               .chip   = {
+                       .base   = S5PV210_GPH2(0),
+                       .ngpio  = S5PV210_GPIO_H2_NR,
+                       .label  = "GPH2",
+                       .to_irq = samsung_gpiolib_to_irq,
+               },
+       }, {
+               .base   = (S5P_VA_GPIO + 0xC60),
+               .irq_base = IRQ_EINT(24),
+               .chip   = {
+                       .base   = S5PV210_GPH3(0),
+                       .ngpio  = S5PV210_GPIO_H3_NR,
+                       .label  = "GPH3",
+                       .to_irq = samsung_gpiolib_to_irq,
+               },
+       },
+#endif
+};
+
+/*
+ * Followings are the gpio banks in EXYNOS4210
+ *
+ * The 'config' member when left to NULL, is initialized to the default
+ * structure samsung_gpio_cfgs[3] in the init function below.
+ *
+ * The 'base' member is also initialized in the init function below.
+ * Note: The initialization of 'base' member of samsung_gpio_chip structure
+ * uses the above macro and depends on the banks being listed in order here.
+ */
+
+static struct samsung_gpio_chip exynos4_gpios_1[] = {
+#ifdef CONFIG_ARCH_EXYNOS4
+       {
+               .chip   = {
+                       .base   = EXYNOS4_GPA0(0),
+                       .ngpio  = EXYNOS4_GPIO_A0_NR,
+                       .label  = "GPA0",
+               },
+       }, {
+               .chip   = {
+                       .base   = EXYNOS4_GPA1(0),
+                       .ngpio  = EXYNOS4_GPIO_A1_NR,
+                       .label  = "GPA1",
+               },
+       }, {
+               .chip   = {
+                       .base   = EXYNOS4_GPB(0),
+                       .ngpio  = EXYNOS4_GPIO_B_NR,
+                       .label  = "GPB",
+               },
+       }, {
+               .chip   = {
+                       .base   = EXYNOS4_GPC0(0),
+                       .ngpio  = EXYNOS4_GPIO_C0_NR,
+                       .label  = "GPC0",
+               },
+       }, {
+               .chip   = {
+                       .base   = EXYNOS4_GPC1(0),
+                       .ngpio  = EXYNOS4_GPIO_C1_NR,
+                       .label  = "GPC1",
+               },
+       }, {
+               .chip   = {
+                       .base   = EXYNOS4_GPD0(0),
+                       .ngpio  = EXYNOS4_GPIO_D0_NR,
+                       .label  = "GPD0",
+               },
+       }, {
+               .chip   = {
+                       .base   = EXYNOS4_GPD1(0),
+                       .ngpio  = EXYNOS4_GPIO_D1_NR,
+                       .label  = "GPD1",
+               },
+       }, {
+               .chip   = {
+                       .base   = EXYNOS4_GPE0(0),
+                       .ngpio  = EXYNOS4_GPIO_E0_NR,
+                       .label  = "GPE0",
+               },
+       }, {
+               .chip   = {
+                       .base   = EXYNOS4_GPE1(0),
+                       .ngpio  = EXYNOS4_GPIO_E1_NR,
+                       .label  = "GPE1",
+               },
+       }, {
+               .chip   = {
+                       .base   = EXYNOS4_GPE2(0),
+                       .ngpio  = EXYNOS4_GPIO_E2_NR,
+                       .label  = "GPE2",
+               },
+       }, {
+               .chip   = {
+                       .base   = EXYNOS4_GPE3(0),
+                       .ngpio  = EXYNOS4_GPIO_E3_NR,
+                       .label  = "GPE3",
+               },
+       }, {
+               .chip   = {
+                       .base   = EXYNOS4_GPE4(0),
+                       .ngpio  = EXYNOS4_GPIO_E4_NR,
+                       .label  = "GPE4",
+               },
+       }, {
+               .chip   = {
+                       .base   = EXYNOS4_GPF0(0),
+                       .ngpio  = EXYNOS4_GPIO_F0_NR,
+                       .label  = "GPF0",
+               },
+       }, {
+               .chip   = {
+                       .base   = EXYNOS4_GPF1(0),
+                       .ngpio  = EXYNOS4_GPIO_F1_NR,
+                       .label  = "GPF1",
+               },
+       }, {
+               .chip   = {
+                       .base   = EXYNOS4_GPF2(0),
+                       .ngpio  = EXYNOS4_GPIO_F2_NR,
+                       .label  = "GPF2",
+               },
+       }, {
+               .chip   = {
+                       .base   = EXYNOS4_GPF3(0),
+                       .ngpio  = EXYNOS4_GPIO_F3_NR,
+                       .label  = "GPF3",
+               },
+       },
+#endif
+};
+
+static struct samsung_gpio_chip exynos4_gpios_2[] = {
+#ifdef CONFIG_ARCH_EXYNOS4
+       {
+               .chip   = {
+                       .base   = EXYNOS4_GPJ0(0),
+                       .ngpio  = EXYNOS4_GPIO_J0_NR,
+                       .label  = "GPJ0",
+               },
+       }, {
+               .chip   = {
+                       .base   = EXYNOS4_GPJ1(0),
+                       .ngpio  = EXYNOS4_GPIO_J1_NR,
+                       .label  = "GPJ1",
+               },
+       }, {
+               .chip   = {
+                       .base   = EXYNOS4_GPK0(0),
+                       .ngpio  = EXYNOS4_GPIO_K0_NR,
+                       .label  = "GPK0",
+               },
+       }, {
+               .chip   = {
+                       .base   = EXYNOS4_GPK1(0),
+                       .ngpio  = EXYNOS4_GPIO_K1_NR,
+                       .label  = "GPK1",
+               },
+       }, {
+               .chip   = {
+                       .base   = EXYNOS4_GPK2(0),
+                       .ngpio  = EXYNOS4_GPIO_K2_NR,
+                       .label  = "GPK2",
+               },
+       }, {
+               .chip   = {
+                       .base   = EXYNOS4_GPK3(0),
+                       .ngpio  = EXYNOS4_GPIO_K3_NR,
+                       .label  = "GPK3",
+               },
+       }, {
+               .chip   = {
+                       .base   = EXYNOS4_GPL0(0),
+                       .ngpio  = EXYNOS4_GPIO_L0_NR,
+                       .label  = "GPL0",
+               },
+       }, {
+               .chip   = {
+                       .base   = EXYNOS4_GPL1(0),
+                       .ngpio  = EXYNOS4_GPIO_L1_NR,
+                       .label  = "GPL1",
+               },
+       }, {
+               .chip   = {
+                       .base   = EXYNOS4_GPL2(0),
+                       .ngpio  = EXYNOS4_GPIO_L2_NR,
+                       .label  = "GPL2",
+               },
+       }, {
+               .config = &samsung_gpio_cfgs[0],
+               .chip   = {
+                       .base   = EXYNOS4_GPY0(0),
+                       .ngpio  = EXYNOS4_GPIO_Y0_NR,
+                       .label  = "GPY0",
+               },
+       }, {
+               .config = &samsung_gpio_cfgs[0],
+               .chip   = {
+                       .base   = EXYNOS4_GPY1(0),
+                       .ngpio  = EXYNOS4_GPIO_Y1_NR,
+                       .label  = "GPY1",
+               },
+       }, {
+               .config = &samsung_gpio_cfgs[0],
+               .chip   = {
+                       .base   = EXYNOS4_GPY2(0),
+                       .ngpio  = EXYNOS4_GPIO_Y2_NR,
+                       .label  = "GPY2",
+               },
+       }, {
+               .config = &samsung_gpio_cfgs[0],
+               .chip   = {
+                       .base   = EXYNOS4_GPY3(0),
+                       .ngpio  = EXYNOS4_GPIO_Y3_NR,
+                       .label  = "GPY3",
+               },
+       }, {
+               .config = &samsung_gpio_cfgs[0],
+               .chip   = {
+                       .base   = EXYNOS4_GPY4(0),
+                       .ngpio  = EXYNOS4_GPIO_Y4_NR,
+                       .label  = "GPY4",
+               },
+       }, {
+               .config = &samsung_gpio_cfgs[0],
+               .chip   = {
+                       .base   = EXYNOS4_GPY5(0),
+                       .ngpio  = EXYNOS4_GPIO_Y5_NR,
+                       .label  = "GPY5",
+               },
+       }, {
+               .config = &samsung_gpio_cfgs[0],
+               .chip   = {
+                       .base   = EXYNOS4_GPY6(0),
+                       .ngpio  = EXYNOS4_GPIO_Y6_NR,
+                       .label  = "GPY6",
+               },
+       }, {
+               .base   = (S5P_VA_GPIO2 + 0xC00),
+               .config = &samsung_gpio_cfgs[3],
+               .irq_base = IRQ_EINT(0),
+               .chip   = {
+                       .base   = EXYNOS4_GPX0(0),
+                       .ngpio  = EXYNOS4_GPIO_X0_NR,
+                       .label  = "GPX0",
+                       .to_irq = samsung_gpiolib_to_irq,
+               },
+       }, {
+               .base   = (S5P_VA_GPIO2 + 0xC20),
+               .config = &samsung_gpio_cfgs[3],
+               .irq_base = IRQ_EINT(8),
+               .chip   = {
+                       .base   = EXYNOS4_GPX1(0),
+                       .ngpio  = EXYNOS4_GPIO_X1_NR,
+                       .label  = "GPX1",
+                       .to_irq = samsung_gpiolib_to_irq,
+               },
+       }, {
+               .base   = (S5P_VA_GPIO2 + 0xC40),
+               .config = &samsung_gpio_cfgs[3],
+               .irq_base = IRQ_EINT(16),
+               .chip   = {
+                       .base   = EXYNOS4_GPX2(0),
+                       .ngpio  = EXYNOS4_GPIO_X2_NR,
+                       .label  = "GPX2",
+                       .to_irq = samsung_gpiolib_to_irq,
+               },
+       }, {
+               .base   = (S5P_VA_GPIO2 + 0xC60),
+               .config = &samsung_gpio_cfgs[3],
+               .irq_base = IRQ_EINT(24),
+               .chip   = {
+                       .base   = EXYNOS4_GPX3(0),
+                       .ngpio  = EXYNOS4_GPIO_X3_NR,
+                       .label  = "GPX3",
+                       .to_irq = samsung_gpiolib_to_irq,
+               },
+       },
+#endif
+};
+
+static struct samsung_gpio_chip exynos4_gpios_3[] = {
+#ifdef CONFIG_ARCH_EXYNOS4
+       {
+               .chip   = {
+                       .base   = EXYNOS4_GPZ(0),
+                       .ngpio  = EXYNOS4_GPIO_Z_NR,
+                       .label  = "GPZ",
+               },
+       },
+#endif
+};
+
+/* TODO: cleanup soc_is_* */
+static __init int samsung_gpiolib_init(void)
+{
+       struct samsung_gpio_chip *chip;
+       int i, nr_chips;
+       int group = 0;
+
+       samsung_gpiolib_set_cfg(samsung_gpio_cfgs, ARRAY_SIZE(samsung_gpio_cfgs));
+
+       if (soc_is_s3c24xx()) {
+               s3c24xx_gpiolib_add_chips(s3c24xx_gpios,
+                               ARRAY_SIZE(s3c24xx_gpios), S3C24XX_VA_GPIO);
+       } else if (soc_is_s3c64xx()) {
+               samsung_gpiolib_add_2bit_chips(s3c64xx_gpios_2bit,
+                               ARRAY_SIZE(s3c64xx_gpios_2bit),
+                               S3C64XX_VA_GPIO + 0xE0, 0x20);
+               samsung_gpiolib_add_4bit_chips(s3c64xx_gpios_4bit,
+                               ARRAY_SIZE(s3c64xx_gpios_4bit),
+                               S3C64XX_VA_GPIO);
+               samsung_gpiolib_add_4bit2_chips(s3c64xx_gpios_4bit2,
+                               ARRAY_SIZE(s3c64xx_gpios_4bit2));
+       } else if (soc_is_s5p6440()) {
+               samsung_gpiolib_add_2bit_chips(s5p6440_gpios_2bit,
+                               ARRAY_SIZE(s5p6440_gpios_2bit), NULL, 0x0);
+               samsung_gpiolib_add_4bit_chips(s5p6440_gpios_4bit,
+                               ARRAY_SIZE(s5p6440_gpios_4bit), S5P_VA_GPIO);
+               samsung_gpiolib_add_4bit2_chips(s5p6440_gpios_4bit2,
+                               ARRAY_SIZE(s5p6440_gpios_4bit2));
+               s5p64x0_gpiolib_add_rbank(s5p6440_gpios_rbank,
+                               ARRAY_SIZE(s5p6440_gpios_rbank));
+       } else if (soc_is_s5p6450()) {
+               samsung_gpiolib_add_2bit_chips(s5p6450_gpios_2bit,
+                               ARRAY_SIZE(s5p6450_gpios_2bit), NULL, 0x0);
+               samsung_gpiolib_add_4bit_chips(s5p6450_gpios_4bit,
+                               ARRAY_SIZE(s5p6450_gpios_4bit), S5P_VA_GPIO);
+               samsung_gpiolib_add_4bit2_chips(s5p6450_gpios_4bit2,
+                               ARRAY_SIZE(s5p6450_gpios_4bit2));
+               s5p64x0_gpiolib_add_rbank(s5p6450_gpios_rbank,
+                               ARRAY_SIZE(s5p6450_gpios_rbank));
+       } else if (soc_is_s5pc100()) {
+               group = 0;
+               chip = s5pc100_gpios_4bit;
+               nr_chips = ARRAY_SIZE(s5pc100_gpios_4bit);
+
+               for (i = 0; i < nr_chips; i++, chip++) {
+                       if (!chip->config) {
+                               chip->config = &samsung_gpio_cfgs[3];
+                               chip->group = group++;
+                       }
+               }
+               samsung_gpiolib_add_4bit_chips(s5pc100_gpios_4bit, nr_chips, S5P_VA_GPIO);
+#if defined(CONFIG_CPU_S5PC100) && defined(CONFIG_S5P_GPIO_INT)
+               s5p_register_gpioint_bank(IRQ_GPIOINT, 0, S5P_GPIOINT_GROUP_MAXNR);
+#endif
+       } else if (soc_is_s5pv210()) {
+               group = 0;
+               chip = s5pv210_gpios_4bit;
+               nr_chips = ARRAY_SIZE(s5pv210_gpios_4bit);
+
+               for (i = 0; i < nr_chips; i++, chip++) {
+                       if (!chip->config) {
+                               chip->config = &samsung_gpio_cfgs[3];
+                               chip->group = group++;
+                       }
+               }
+               samsung_gpiolib_add_4bit_chips(s5pv210_gpios_4bit, nr_chips, S5P_VA_GPIO);
+#if defined(CONFIG_CPU_S5PV210) && defined(CONFIG_S5P_GPIO_INT)
+               s5p_register_gpioint_bank(IRQ_GPIOINT, 0, S5P_GPIOINT_GROUP_MAXNR);
+#endif
+       } else if (soc_is_exynos4210()) {
+               group = 0;
+
+               /* gpio part1 */
+               chip = exynos4_gpios_1;
+               nr_chips = ARRAY_SIZE(exynos4_gpios_1);
+
+               for (i = 0; i < nr_chips; i++, chip++) {
+                       if (!chip->config) {
+                               chip->config = &exynos4_gpio_cfg;
+                               chip->group = group++;
+                       }
+               }
+               samsung_gpiolib_add_4bit_chips(exynos4_gpios_1, nr_chips, S5P_VA_GPIO1);
+
+               /* gpio part2 */
+               chip = exynos4_gpios_2;
+               nr_chips = ARRAY_SIZE(exynos4_gpios_2);
+
+               for (i = 0; i < nr_chips; i++, chip++) {
+                       if (!chip->config) {
+                               chip->config = &exynos4_gpio_cfg;
+                               chip->group = group++;
+                       }
+               }
+               samsung_gpiolib_add_4bit_chips(exynos4_gpios_2, nr_chips, S5P_VA_GPIO2);
+
+               /* gpio part3 */
+               chip = exynos4_gpios_3;
+               nr_chips = ARRAY_SIZE(exynos4_gpios_3);
+
+               for (i = 0; i < nr_chips; i++, chip++) {
+                       if (!chip->config) {
+                               chip->config = &exynos4_gpio_cfg;
+                               chip->group = group++;
+                       }
+               }
+               samsung_gpiolib_add_4bit_chips(exynos4_gpios_3, nr_chips, S5P_VA_GPIO3);
+
+#if defined(CONFIG_CPU_EXYNOS4210) && defined(CONFIG_S5P_GPIO_INT)
+               s5p_register_gpioint_bank(IRQ_GPIO_XA, 0, IRQ_GPIO1_NR_GROUPS);
+               s5p_register_gpioint_bank(IRQ_GPIO_XB, IRQ_GPIO1_NR_GROUPS, IRQ_GPIO2_NR_GROUPS);
+#endif
+       }
+
+       return 0;
+}
+core_initcall(samsung_gpiolib_init);
+
+int s3c_gpio_cfgpin(unsigned int pin, unsigned int config)
+{
+       struct samsung_gpio_chip *chip = samsung_gpiolib_getchip(pin);
+       unsigned long flags;
+       int offset;
+       int ret;
+
+       if (!chip)
+               return -EINVAL;
+
+       offset = pin - chip->chip.base;
+
+       samsung_gpio_lock(chip, flags);
+       ret = samsung_gpio_do_setcfg(chip, offset, config);
+       samsung_gpio_unlock(chip, flags);
+
+       return ret;
+}
+EXPORT_SYMBOL(s3c_gpio_cfgpin);
+
+int s3c_gpio_cfgpin_range(unsigned int start, unsigned int nr,
+                         unsigned int cfg)
+{
+       int ret;
+
+       for (; nr > 0; nr--, start++) {
+               ret = s3c_gpio_cfgpin(start, cfg);
+               if (ret != 0)
+                       return ret;
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(s3c_gpio_cfgpin_range);
+
+int s3c_gpio_cfgall_range(unsigned int start, unsigned int nr,
+                         unsigned int cfg, samsung_gpio_pull_t pull)
+{
+       int ret;
+
+       for (; nr > 0; nr--, start++) {
+               s3c_gpio_setpull(start, pull);
+               ret = s3c_gpio_cfgpin(start, cfg);
+               if (ret != 0)
+                       return ret;
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(s3c_gpio_cfgall_range);
+
+unsigned s3c_gpio_getcfg(unsigned int pin)
+{
+       struct samsung_gpio_chip *chip = samsung_gpiolib_getchip(pin);
+       unsigned long flags;
+       unsigned ret = 0;
+       int offset;
+
+       if (chip) {
+               offset = pin - chip->chip.base;
+
+               samsung_gpio_lock(chip, flags);
+               ret = samsung_gpio_do_getcfg(chip, offset);
+               samsung_gpio_unlock(chip, flags);
+       }
+
+       return ret;
+}
+EXPORT_SYMBOL(s3c_gpio_getcfg);
+
+int s3c_gpio_setpull(unsigned int pin, samsung_gpio_pull_t pull)
+{
+       struct samsung_gpio_chip *chip = samsung_gpiolib_getchip(pin);
+       unsigned long flags;
+       int offset, ret;
+
+       if (!chip)
+               return -EINVAL;
+
+       offset = pin - chip->chip.base;
+
+       samsung_gpio_lock(chip, flags);
+       ret = samsung_gpio_do_setpull(chip, offset, pull);
+       samsung_gpio_unlock(chip, flags);
+
+       return ret;
+}
+EXPORT_SYMBOL(s3c_gpio_setpull);
+
+samsung_gpio_pull_t s3c_gpio_getpull(unsigned int pin)
+{
+       struct samsung_gpio_chip *chip = samsung_gpiolib_getchip(pin);
+       unsigned long flags;
+       int offset;
+       u32 pup = 0;
+
+       if (chip) {
+               offset = pin - chip->chip.base;
+
+               samsung_gpio_lock(chip, flags);
+               pup = samsung_gpio_do_getpull(chip, offset);
+               samsung_gpio_unlock(chip, flags);
+       }
+
+       return (__force samsung_gpio_pull_t)pup;
+}
+EXPORT_SYMBOL(s3c_gpio_getpull);
+
+/* gpiolib wrappers until these are totally eliminated */
+
+void s3c2410_gpio_pullup(unsigned int pin, unsigned int to)
+{
+       int ret;
+
+       WARN_ON(to);    /* should be none of these left */
+
+       if (!to) {
+               /* if pull is enabled, try first with up, and if that
+                * fails, try using down */
+
+               ret = s3c_gpio_setpull(pin, S3C_GPIO_PULL_UP);
+               if (ret)
+                       s3c_gpio_setpull(pin, S3C_GPIO_PULL_DOWN);
+       } else {
+               s3c_gpio_setpull(pin, S3C_GPIO_PULL_NONE);
+       }
+}
+EXPORT_SYMBOL(s3c2410_gpio_pullup);
+
+void s3c2410_gpio_setpin(unsigned int pin, unsigned int to)
+{
+       /* do this via gpiolib until all users removed */
+
+       gpio_request(pin, "temporary");
+       gpio_set_value(pin, to);
+       gpio_free(pin);
+}
+EXPORT_SYMBOL(s3c2410_gpio_setpin);
+
+unsigned int s3c2410_gpio_getpin(unsigned int pin)
+{
+       struct samsung_gpio_chip *chip = samsung_gpiolib_getchip(pin);
+       unsigned long offs = pin - chip->chip.base;
+
+       return __raw_readl(chip->base + 0x04) & (1 << offs);
+}
+EXPORT_SYMBOL(s3c2410_gpio_getpin);
+
+#ifdef CONFIG_S5P_GPIO_DRVSTR
+s5p_gpio_drvstr_t s5p_gpio_get_drvstr(unsigned int pin)
+{
+       struct samsung_gpio_chip *chip = samsung_gpiolib_getchip(pin);
+       unsigned int off;
+       void __iomem *reg;
+       int shift;
+       u32 drvstr;
+
+       if (!chip)
+               return -EINVAL;
+
+       off = pin - chip->chip.base;
+       shift = off * 2;
+       reg = chip->base + 0x0C;
+
+       drvstr = __raw_readl(reg);
+       drvstr = drvstr >> shift;
+       drvstr &= 0x3;
+
+       return (__force s5p_gpio_drvstr_t)drvstr;
+}
+EXPORT_SYMBOL(s5p_gpio_get_drvstr);
+
+int s5p_gpio_set_drvstr(unsigned int pin, s5p_gpio_drvstr_t drvstr)
+{
+       struct samsung_gpio_chip *chip = samsung_gpiolib_getchip(pin);
+       unsigned int off;
+       void __iomem *reg;
+       int shift;
+       u32 tmp;
+
+       if (!chip)
+               return -EINVAL;
+
+       off = pin - chip->chip.base;
+       shift = off * 2;
+       reg = chip->base + 0x0C;
+
+       tmp = __raw_readl(reg);
+       tmp &= ~(0x3 << shift);
+       tmp |= drvstr << shift;
+
+       __raw_writel(tmp, reg);
+
+       return 0;
+}
+EXPORT_SYMBOL(s5p_gpio_set_drvstr);
+#endif /* CONFIG_S5P_GPIO_DRVSTR */
+
+#ifdef CONFIG_PLAT_S3C24XX
+unsigned int s3c2410_modify_misccr(unsigned int clear, unsigned int change)
+{
+       unsigned long flags;
+       unsigned long misccr;
+
+       local_irq_save(flags);
+       misccr = __raw_readl(S3C24XX_MISCCR);
+       misccr &= ~clear;
+       misccr ^= change;
+       __raw_writel(misccr, S3C24XX_MISCCR);
+       local_irq_restore(flags);
+
+       return misccr;
+}
+EXPORT_SYMBOL(s3c2410_modify_misccr);
+#endif
index a04f87d7ee3d13a79be90146b2cfa004014d01be..03cfdab99c8fb9fce176efaed161d3c4d0967471 100644 (file)
@@ -913,9 +913,9 @@ request_done:
 }
 
 static void s3cmci_dma_setup(struct s3cmci_host *host,
-                            enum s3c2410_dmasrc source)
+                            enum dma_data_direction source)
 {
-       static enum s3c2410_dmasrc last_source = -1;
+       static enum dma_data_direction last_source = -1;
        static int setup_ok;
 
        if (last_source == source)
@@ -1087,7 +1087,7 @@ static int s3cmci_prepare_dma(struct s3cmci_host *host, struct mmc_data *data)
 
        BUG_ON((data->flags & BOTH_DIR) == BOTH_DIR);
 
-       s3cmci_dma_setup(host, rw ? S3C2410_DMASRC_MEM : S3C2410_DMASRC_HW);
+       s3cmci_dma_setup(host, rw ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
        s3c2410_dma_ctrl(host->dma, S3C2410_DMAOP_FLUSH);
 
        dma_len = dma_map_sg(mmc_dev(host->mmc), data->sg, data->sg_len,
index 595dacc7645f48e00a105fa9afb389fc1835692c..019a7163572f460fd5d36f61a88a352d598d51a1 100644 (file)
 #define RXBUSY    (1<<2)
 #define TXBUSY    (1<<3)
 
+struct s3c64xx_spi_dma_data {
+       unsigned                ch;
+       enum dma_data_direction direction;
+       enum dma_ch     dmach;
+};
+
 /**
  * struct s3c64xx_spi_driver_data - Runtime info holder for SPI driver.
  * @clk: Pointer to the spi clock.
@@ -164,13 +170,14 @@ struct s3c64xx_spi_driver_data {
        struct work_struct              work;
        struct list_head                queue;
        spinlock_t                      lock;
-       enum dma_ch                     rx_dmach;
-       enum dma_ch                     tx_dmach;
        unsigned long                   sfr_start;
        struct completion               xfer_completion;
        unsigned                        state;
        unsigned                        cur_mode, cur_bpw;
        unsigned                        cur_speed;
+       struct s3c64xx_spi_dma_data     rx_dma;
+       struct s3c64xx_spi_dma_data     tx_dma;
+       struct samsung_dma_ops          *ops;
 };
 
 static struct s3c2410_dma_client s3c64xx_spi_dma_client = {
@@ -226,6 +233,78 @@ static void flush_fifo(struct s3c64xx_spi_driver_data *sdd)
        writel(val, regs + S3C64XX_SPI_CH_CFG);
 }
 
+static void s3c64xx_spi_dmacb(void *data)
+{
+       struct s3c64xx_spi_driver_data *sdd;
+       struct s3c64xx_spi_dma_data *dma = data;
+       unsigned long flags;
+
+       if (dma->direction == DMA_FROM_DEVICE)
+               sdd = container_of(data,
+                       struct s3c64xx_spi_driver_data, rx_dma);
+       else
+               sdd = container_of(data,
+                       struct s3c64xx_spi_driver_data, tx_dma);
+
+       spin_lock_irqsave(&sdd->lock, flags);
+
+       if (dma->direction == DMA_FROM_DEVICE) {
+               sdd->state &= ~RXBUSY;
+               if (!(sdd->state & TXBUSY))
+                       complete(&sdd->xfer_completion);
+       } else {
+               sdd->state &= ~TXBUSY;
+               if (!(sdd->state & RXBUSY))
+                       complete(&sdd->xfer_completion);
+       }
+
+       spin_unlock_irqrestore(&sdd->lock, flags);
+}
+
+static void prepare_dma(struct s3c64xx_spi_dma_data *dma,
+                                       unsigned len, dma_addr_t buf)
+{
+       struct s3c64xx_spi_driver_data *sdd;
+       struct samsung_dma_prep_info info;
+
+       if (dma->direction == DMA_FROM_DEVICE)
+               sdd = container_of((void *)dma,
+                       struct s3c64xx_spi_driver_data, rx_dma);
+       else
+               sdd = container_of((void *)dma,
+                       struct s3c64xx_spi_driver_data, tx_dma);
+
+       info.cap = DMA_SLAVE;
+       info.len = len;
+       info.fp = s3c64xx_spi_dmacb;
+       info.fp_param = dma;
+       info.direction = dma->direction;
+       info.buf = buf;
+
+       sdd->ops->prepare(dma->ch, &info);
+       sdd->ops->trigger(dma->ch);
+}
+
+static int acquire_dma(struct s3c64xx_spi_driver_data *sdd)
+{
+       struct samsung_dma_info info;
+
+       sdd->ops = samsung_dma_get_ops();
+
+       info.cap = DMA_SLAVE;
+       info.client = &s3c64xx_spi_dma_client;
+       info.width = sdd->cur_bpw / 8;
+
+       info.direction = sdd->rx_dma.direction;
+       info.fifo = sdd->sfr_start + S3C64XX_SPI_RX_DATA;
+       sdd->rx_dma.ch = sdd->ops->request(sdd->rx_dma.dmach, &info);
+       info.direction =  sdd->tx_dma.direction;
+       info.fifo = sdd->sfr_start + S3C64XX_SPI_TX_DATA;
+       sdd->tx_dma.ch = sdd->ops->request(sdd->tx_dma.dmach, &info);
+
+       return 1;
+}
+
 static void enable_datapath(struct s3c64xx_spi_driver_data *sdd,
                                struct spi_device *spi,
                                struct spi_transfer *xfer, int dma_mode)
@@ -258,10 +337,7 @@ static void enable_datapath(struct s3c64xx_spi_driver_data *sdd,
                chcfg |= S3C64XX_SPI_CH_TXCH_ON;
                if (dma_mode) {
                        modecfg |= S3C64XX_SPI_MODE_TXDMA_ON;
-                       s3c2410_dma_config(sdd->tx_dmach, sdd->cur_bpw / 8);
-                       s3c2410_dma_enqueue(sdd->tx_dmach, (void *)sdd,
-                                               xfer->tx_dma, xfer->len);
-                       s3c2410_dma_ctrl(sdd->tx_dmach, S3C2410_DMAOP_START);
+                       prepare_dma(&sdd->tx_dma, xfer->len, xfer->tx_dma);
                } else {
                        switch (sdd->cur_bpw) {
                        case 32:
@@ -293,10 +369,7 @@ static void enable_datapath(struct s3c64xx_spi_driver_data *sdd,
                        writel(((xfer->len * 8 / sdd->cur_bpw) & 0xffff)
                                        | S3C64XX_SPI_PACKET_CNT_EN,
                                        regs + S3C64XX_SPI_PACKET_CNT);
-                       s3c2410_dma_config(sdd->rx_dmach, sdd->cur_bpw / 8);
-                       s3c2410_dma_enqueue(sdd->rx_dmach, (void *)sdd,
-                                               xfer->rx_dma, xfer->len);
-                       s3c2410_dma_ctrl(sdd->rx_dmach, S3C2410_DMAOP_START);
+                       prepare_dma(&sdd->rx_dma, xfer->len, xfer->rx_dma);
                }
        }
 
@@ -482,46 +555,6 @@ static void s3c64xx_spi_config(struct s3c64xx_spi_driver_data *sdd)
        }
 }
 
-static void s3c64xx_spi_dma_rxcb(struct s3c2410_dma_chan *chan, void *buf_id,
-                                int size, enum s3c2410_dma_buffresult res)
-{
-       struct s3c64xx_spi_driver_data *sdd = buf_id;
-       unsigned long flags;
-
-       spin_lock_irqsave(&sdd->lock, flags);
-
-       if (res == S3C2410_RES_OK)
-               sdd->state &= ~RXBUSY;
-       else
-               dev_err(&sdd->pdev->dev, "DmaAbrtRx-%d\n", size);
-
-       /* If the other done */
-       if (!(sdd->state & TXBUSY))
-               complete(&sdd->xfer_completion);
-
-       spin_unlock_irqrestore(&sdd->lock, flags);
-}
-
-static void s3c64xx_spi_dma_txcb(struct s3c2410_dma_chan *chan, void *buf_id,
-                                int size, enum s3c2410_dma_buffresult res)
-{
-       struct s3c64xx_spi_driver_data *sdd = buf_id;
-       unsigned long flags;
-
-       spin_lock_irqsave(&sdd->lock, flags);
-
-       if (res == S3C2410_RES_OK)
-               sdd->state &= ~TXBUSY;
-       else
-               dev_err(&sdd->pdev->dev, "DmaAbrtTx-%d \n", size);
-
-       /* If the other done */
-       if (!(sdd->state & RXBUSY))
-               complete(&sdd->xfer_completion);
-
-       spin_unlock_irqrestore(&sdd->lock, flags);
-}
-
 #define XFER_DMAADDR_INVALID DMA_BIT_MASK(32)
 
 static 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,
                        if (use_dma) {
                                if (xfer->tx_buf != NULL
                                                && (sdd->state & TXBUSY))
-                                       s3c2410_dma_ctrl(sdd->tx_dmach,
-                                                       S3C2410_DMAOP_FLUSH);
+                                       sdd->ops->stop(sdd->tx_dma.ch);
                                if (xfer->rx_buf != NULL
                                                && (sdd->state & RXBUSY))
-                                       s3c2410_dma_ctrl(sdd->rx_dmach,
-                                                       S3C2410_DMAOP_FLUSH);
+                                       sdd->ops->stop(sdd->rx_dma.ch);
                        }
 
                        goto out;
@@ -739,30 +770,6 @@ out:
                msg->complete(msg->context);
 }
 
-static int acquire_dma(struct s3c64xx_spi_driver_data *sdd)
-{
-       if (s3c2410_dma_request(sdd->rx_dmach,
-                                       &s3c64xx_spi_dma_client, NULL) < 0) {
-               dev_err(&sdd->pdev->dev, "cannot get RxDMA\n");
-               return 0;
-       }
-       s3c2410_dma_set_buffdone_fn(sdd->rx_dmach, s3c64xx_spi_dma_rxcb);
-       s3c2410_dma_devconfig(sdd->rx_dmach, S3C2410_DMASRC_HW,
-                                       sdd->sfr_start + S3C64XX_SPI_RX_DATA);
-
-       if (s3c2410_dma_request(sdd->tx_dmach,
-                                       &s3c64xx_spi_dma_client, NULL) < 0) {
-               dev_err(&sdd->pdev->dev, "cannot get TxDMA\n");
-               s3c2410_dma_free(sdd->rx_dmach, &s3c64xx_spi_dma_client);
-               return 0;
-       }
-       s3c2410_dma_set_buffdone_fn(sdd->tx_dmach, s3c64xx_spi_dma_txcb);
-       s3c2410_dma_devconfig(sdd->tx_dmach, S3C2410_DMASRC_MEM,
-                                       sdd->sfr_start + S3C64XX_SPI_TX_DATA);
-
-       return 1;
-}
-
 static void s3c64xx_spi_work(struct work_struct *work)
 {
        struct s3c64xx_spi_driver_data *sdd = container_of(work,
@@ -799,8 +806,8 @@ static void s3c64xx_spi_work(struct work_struct *work)
        spin_unlock_irqrestore(&sdd->lock, flags);
 
        /* Free DMA channels */
-       s3c2410_dma_free(sdd->tx_dmach, &s3c64xx_spi_dma_client);
-       s3c2410_dma_free(sdd->rx_dmach, &s3c64xx_spi_dma_client);
+       sdd->ops->release(sdd->rx_dma.ch, &s3c64xx_spi_dma_client);
+       sdd->ops->release(sdd->tx_dma.ch, &s3c64xx_spi_dma_client);
 }
 
 static int s3c64xx_spi_transfer(struct spi_device *spi,
@@ -1017,8 +1024,10 @@ static int __init s3c64xx_spi_probe(struct platform_device *pdev)
        sdd->cntrlr_info = sci;
        sdd->pdev = pdev;
        sdd->sfr_start = mem_res->start;
-       sdd->tx_dmach = dmatx_res->start;
-       sdd->rx_dmach = dmarx_res->start;
+       sdd->tx_dma.dmach = dmatx_res->start;
+       sdd->tx_dma.direction = DMA_TO_DEVICE;
+       sdd->rx_dma.dmach = dmarx_res->start;
+       sdd->rx_dma.direction = DMA_FROM_DEVICE;
 
        sdd->cur_bpw = 8;
 
@@ -1106,7 +1115,7 @@ static int __init s3c64xx_spi_probe(struct platform_device *pdev)
                                        pdev->id, master->num_chipselect);
        dev_dbg(&pdev->dev, "\tIOmem=[0x%x-0x%x]\tDMA=[Rx-%d, Tx-%d]\n",
                                        mem_res->end, mem_res->start,
-                                       sdd->rx_dmach, sdd->tx_dmach);
+                                       sdd->rx_dma.dmach, sdd->tx_dma.dmach);
 
        return 0;
 
index e6e28f37d8ec472c9be9052039510fa4ce29a7cd..a22662c939812026cb29e775c2f7529264407016 100644 (file)
@@ -47,6 +47,9 @@ enum {
  * @muxval: a number usually used to poke into some mux regiser to
  * mux in the signal to this channel
  * @cctl_opt: default options for the channel control register
+ * @device_fc: Flow Controller Settings for ccfg register. Only valid for slave
+ * channels. Fill with 'true' if peripheral should be flow controller. Direction
+ * will be selected at Runtime.
  * @addr: source/target address in physical memory for this DMA channel,
  * can be the address of a FIFO register for burst requests for example.
  * This can be left undefined if the PrimeCell API is used for configuring
@@ -65,6 +68,7 @@ struct pl08x_channel_data {
        int max_signal;
        u32 muxval;
        u32 cctl;
+       bool device_fc;
        dma_addr_t addr;
        bool circular_buffer;
        bool single;
@@ -77,13 +81,11 @@ struct pl08x_channel_data {
  * @addr: current address
  * @maxwidth: the maximum width of a transfer on this bus
  * @buswidth: the width of this bus in bytes: 1, 2 or 4
- * @fill_bytes: bytes required to fill to the next bus memory boundary
  */
 struct pl08x_bus_data {
        dma_addr_t addr;
        u8 maxwidth;
        u8 buswidth;
-       size_t fill_bytes;
 };
 
 /**
@@ -105,8 +107,16 @@ struct pl08x_phy_chan {
 
 /**
  * struct pl08x_txd - wrapper for struct dma_async_tx_descriptor
+ * @tx: async tx descriptor
+ * @node: node for txd list for channels
+ * @src_addr: src address of txd
+ * @dst_addr: dst address of txd
+ * @len: transfer len in bytes
+ * @direction: direction of transfer
  * @llis_bus: DMA memory address (physical) start for the LLIs
  * @llis_va: virtual memory address start for the LLIs
+ * @cctl: control reg values for current txd
+ * @ccfg: config reg values for current txd
  */
 struct pl08x_txd {
        struct dma_async_tx_descriptor tx;
index cbee7de7dd367227e89560039b0feab7b0a98416..d12f077a6dafb7eb505eb5142c13327558001800 100644 (file)
@@ -19,12 +19,8 @@ struct dma_pl330_peri {
         * Peri_Req i/f of the DMAC that is
         * peripheral could be reached from.
         */
-       u8 peri_id; /* {0, 31} */
+       u8 peri_id; /* specific dma id */
        enum pl330_reqtype rqtype;
-
-       /* For M->D and D->M Channels */
-       int burst_sz; /* in power of 2 */
-       dma_addr_t fifo_addr;
 };
 
 struct dma_pl330_platdata {
index 8fbf40e0713cfc9a4dd7ec64bc66010a42afc644..ace51af4369f668ea647f47c2d87f76d4478b121 100644 (file)
@@ -24,8 +24,7 @@
 #include <linux/device.h>
 #include <linux/uio.h>
 #include <linux/dma-direction.h>
-
-struct scatterlist;
+#include <linux/scatterlist.h>
 
 /**
  * typedef dma_cookie_t - an opaque DMA cookie
@@ -519,6 +518,16 @@ static inline int dmaengine_slave_config(struct dma_chan *chan,
                        (unsigned long)config);
 }
 
+static inline struct dma_async_tx_descriptor *dmaengine_prep_slave_single(
+       struct dma_chan *chan, void *buf, size_t len,
+       enum dma_data_direction dir, unsigned long flags)
+{
+       struct scatterlist sg;
+       sg_init_one(&sg, buf, len);
+
+       return chan->device->device_prep_slave_sg(chan, &sg, 1, dir, flags);
+}
+
 static inline int dmaengine_terminate_all(struct dma_chan *chan)
 {
        return dmaengine_device_control(chan, DMA_TERMINATE_ALL, 0);
index f97110e72e855d1da85253ec83212f185a29e152..b4f9b000368501301672a2f073eb86cc12711252 100644 (file)
@@ -271,7 +271,10 @@ static int s3c_ac97_trigger(struct snd_pcm_substream *substream, int cmd,
 
        writel(ac_glbctrl, s3c_ac97.regs + S3C_AC97_GLBCTRL);
 
-       s3c2410_dma_ctrl(dma_data->channel, S3C2410_DMAOP_STARTED);
+       if (!dma_data->ops)
+               dma_data->ops = samsung_dma_get_ops();
+
+       dma_data->ops->started(dma_data->channel);
 
        return 0;
 }
@@ -317,7 +320,10 @@ static int s3c_ac97_mic_trigger(struct snd_pcm_substream *substream,
 
        writel(ac_glbctrl, s3c_ac97.regs + S3C_AC97_GLBCTRL);
 
-       s3c2410_dma_ctrl(dma_data->channel, S3C2410_DMAOP_STARTED);
+       if (!dma_data->ops)
+               dma_data->ops = samsung_dma_get_ops();
+
+       dma_data->ops->started(dma_data->channel);
 
        return 0;
 }
index 9465588b02f2c99e478e4297da001521d13f9b35..2d622b635e68babe502615286aaf7e475741918e 100644 (file)
@@ -54,7 +54,6 @@ struct runtime_data {
        spinlock_t lock;
        int state;
        unsigned int dma_loaded;
-       unsigned int dma_limit;
        unsigned int dma_period;
        dma_addr_t dma_start;
        dma_addr_t dma_pos;
@@ -62,77 +61,79 @@ struct runtime_data {
        struct s3c_dma_params *params;
 };
 
+static void audio_buffdone(void *data);
+
 /* dma_enqueue
  *
  * place a dma buffer onto the queue for the dma system
  * to handle.
-*/
+ */
 static void dma_enqueue(struct snd_pcm_substream *substream)
 {
        struct runtime_data *prtd = substream->runtime->private_data;
        dma_addr_t pos = prtd->dma_pos;
        unsigned int limit;
-       int ret;
+       struct samsung_dma_prep_info dma_info;
 
        pr_debug("Entered %s\n", __func__);
 
-       if (s3c_dma_has_circular())
-               limit = (prtd->dma_end - prtd->dma_start) / prtd->dma_period;
-       else
-               limit = prtd->dma_limit;
+       limit = (prtd->dma_end - prtd->dma_start) / prtd->dma_period;
 
        pr_debug("%s: loaded %d, limit %d\n",
                                __func__, prtd->dma_loaded, limit);
 
-       while (prtd->dma_loaded < limit) {
-               unsigned long len = prtd->dma_period;
+       dma_info.cap = (samsung_dma_has_circular() ? DMA_CYCLIC : DMA_SLAVE);
+       dma_info.direction =
+               (substream->stream == SNDRV_PCM_STREAM_PLAYBACK
+               ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
+       dma_info.fp = audio_buffdone;
+       dma_info.fp_param = substream;
+       dma_info.period = prtd->dma_period;
+       dma_info.len = prtd->dma_period*limit;
 
+       while (prtd->dma_loaded < limit) {
                pr_debug("dma_loaded: %d\n", prtd->dma_loaded);
 
-               if ((pos + len) > prtd->dma_end) {
-                       len  = prtd->dma_end - pos;
-                       pr_debug("%s: corrected dma len %ld\n", __func__, len);
+               if ((pos + dma_info.period) > prtd->dma_end) {
+                       dma_info.period  = prtd->dma_end - pos;
+                       pr_debug("%s: corrected dma len %ld\n",
+                                       __func__, dma_info.period);
                }
 
-               ret = s3c2410_dma_enqueue(prtd->params->channel,
-                       substream, pos, len);
+               dma_info.buf = pos;
+               prtd->params->ops->prepare(prtd->params->ch, &dma_info);
 
-               if (ret == 0) {
-                       prtd->dma_loaded++;
-                       pos += prtd->dma_period;
-                       if (pos >= prtd->dma_end)
-                               pos = prtd->dma_start;
-               } else
-                       break;
+               prtd->dma_loaded++;
+               pos += prtd->dma_period;
+               if (pos >= prtd->dma_end)
+                       pos = prtd->dma_start;
        }
 
        prtd->dma_pos = pos;
 }
 
-static void audio_buffdone(struct s3c2410_dma_chan *channel,
-                               void *dev_id, int size,
-                               enum s3c2410_dma_buffresult result)
+static void audio_buffdone(void *data)
 {
-       struct snd_pcm_substream *substream = dev_id;
-       struct runtime_data *prtd;
+       struct snd_pcm_substream *substream = data;
+       struct runtime_data *prtd = substream->runtime->private_data;
 
        pr_debug("Entered %s\n", __func__);
 
-       if (result == S3C2410_RES_ABORT || result == S3C2410_RES_ERR)
-               return;
-
-       prtd = substream->runtime->private_data;
+       if (prtd->state & ST_RUNNING) {
+               prtd->dma_pos += prtd->dma_period;
+               if (prtd->dma_pos >= prtd->dma_end)
+                       prtd->dma_pos = prtd->dma_start;
 
-       if (substream)
-               snd_pcm_period_elapsed(substream);
+               if (substream)
+                       snd_pcm_period_elapsed(substream);
 
-       spin_lock(&prtd->lock);
-       if (prtd->state & ST_RUNNING && !s3c_dma_has_circular()) {
-               prtd->dma_loaded--;
-               dma_enqueue(substream);
+               spin_lock(&prtd->lock);
+               if (!samsung_dma_has_circular()) {
+                       prtd->dma_loaded--;
+                       dma_enqueue(substream);
+               }
+               spin_unlock(&prtd->lock);
        }
-
-       spin_unlock(&prtd->lock);
 }
 
 static int dma_hw_params(struct snd_pcm_substream *substream,
@@ -144,8 +145,7 @@ static int dma_hw_params(struct snd_pcm_substream *substream,
        unsigned long totbytes = params_buffer_bytes(params);
        struct s3c_dma_params *dma =
                snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
-       int ret = 0;
-
+       struct samsung_dma_info dma_info;
 
        pr_debug("Entered %s\n", __func__);
 
@@ -163,30 +163,26 @@ static int dma_hw_params(struct snd_pcm_substream *substream,
                pr_debug("params %p, client %p, channel %d\n", prtd->params,
                        prtd->params->client, prtd->params->channel);
 
-               ret = s3c2410_dma_request(prtd->params->channel,
-                                         prtd->params->client, NULL);
-
-               if (ret < 0) {
-                       printk(KERN_ERR "failed to get dma channel\n");
-                       return ret;
-               }
-
-               /* use the circular buffering if we have it available. */
-               if (s3c_dma_has_circular())
-                       s3c2410_dma_setflags(prtd->params->channel,
-                                            S3C2410_DMAF_CIRCULAR);
+               prtd->params->ops = samsung_dma_get_ops();
+
+               dma_info.cap = (samsung_dma_has_circular() ?
+                       DMA_CYCLIC : DMA_SLAVE);
+               dma_info.client = prtd->params->client;
+               dma_info.direction =
+                       (substream->stream == SNDRV_PCM_STREAM_PLAYBACK
+                       ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
+               dma_info.width = prtd->params->dma_size;
+               dma_info.fifo = prtd->params->dma_addr;
+               prtd->params->ch = prtd->params->ops->request(
+                               prtd->params->channel, &dma_info);
        }
 
-       s3c2410_dma_set_buffdone_fn(prtd->params->channel,
-                                   audio_buffdone);
-
        snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
 
        runtime->dma_bytes = totbytes;
 
        spin_lock_irq(&prtd->lock);
        prtd->dma_loaded = 0;
-       prtd->dma_limit = runtime->hw.periods_min;
        prtd->dma_period = params_period_bytes(params);
        prtd->dma_start = runtime->dma_addr;
        prtd->dma_pos = prtd->dma_start;
@@ -202,11 +198,12 @@ static int dma_hw_free(struct snd_pcm_substream *substream)
 
        pr_debug("Entered %s\n", __func__);
 
-       /* TODO - do we need to ensure DMA flushed */
        snd_pcm_set_runtime_buffer(substream, NULL);
 
        if (prtd->params) {
-               s3c2410_dma_free(prtd->params->channel, prtd->params->client);
+               prtd->params->ops->flush(prtd->params->ch);
+               prtd->params->ops->release(prtd->params->ch,
+                                       prtd->params->client);
                prtd->params = NULL;
        }
 
@@ -225,23 +222,9 @@ static int dma_prepare(struct snd_pcm_substream *substream)
        if (!prtd->params)
                return 0;
 
-       /* channel needs configuring for mem=>device, increment memory addr,
-        * sync to pclk, half-word transfers to the IIS-FIFO. */
-       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-               s3c2410_dma_devconfig(prtd->params->channel,
-                                     S3C2410_DMASRC_MEM,
-                                     prtd->params->dma_addr);
-       } else {
-               s3c2410_dma_devconfig(prtd->params->channel,
-                                     S3C2410_DMASRC_HW,
-                                     prtd->params->dma_addr);
-       }
-
-       s3c2410_dma_config(prtd->params->channel,
-                          prtd->params->dma_size);
-
        /* flush the DMA channel */
-       s3c2410_dma_ctrl(prtd->params->channel, S3C2410_DMAOP_FLUSH);
+       prtd->params->ops->flush(prtd->params->ch);
+
        prtd->dma_loaded = 0;
        prtd->dma_pos = prtd->dma_start;
 
@@ -265,14 +248,14 @@ static int dma_trigger(struct snd_pcm_substream *substream, int cmd)
        case SNDRV_PCM_TRIGGER_RESUME:
        case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
                prtd->state |= ST_RUNNING;
-               s3c2410_dma_ctrl(prtd->params->channel, S3C2410_DMAOP_START);
+               prtd->params->ops->trigger(prtd->params->ch);
                break;
 
        case SNDRV_PCM_TRIGGER_STOP:
        case SNDRV_PCM_TRIGGER_SUSPEND:
        case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
                prtd->state &= ~ST_RUNNING;
-               s3c2410_dma_ctrl(prtd->params->channel, S3C2410_DMAOP_STOP);
+               prtd->params->ops->stop(prtd->params->ch);
                break;
 
        default:
@@ -291,21 +274,12 @@ dma_pointer(struct snd_pcm_substream *substream)
        struct snd_pcm_runtime *runtime = substream->runtime;
        struct runtime_data *prtd = runtime->private_data;
        unsigned long res;
-       dma_addr_t src, dst;
 
        pr_debug("Entered %s\n", __func__);
 
-       spin_lock(&prtd->lock);
-       s3c2410_dma_getposition(prtd->params->channel, &src, &dst);
-
-       if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
-               res = dst - prtd->dma_start;
-       else
-               res = src - prtd->dma_start;
-
-       spin_unlock(&prtd->lock);
+       res = prtd->dma_pos - prtd->dma_start;
 
-       pr_debug("Pointer %x %x\n", src, dst);
+       pr_debug("Pointer offset: %lu\n", res);
 
        /* we seem to be getting the odd error from the pcm library due
         * to out-of-bounds pointers. this is maybe due to the dma engine
index c50659269a40353c262d7134d26c8d8aa2a57af4..7d1ead77ef2121751269bb74ca80681033f5d00c 100644 (file)
@@ -6,7 +6,7 @@
  *  Free Software Foundation;  either version 2 of the  License, or (at your
  *  option) any later version.
  *
- *  ALSA PCM interface for the Samsung S3C24xx CPU
+ *  ALSA PCM interface for the Samsung SoC
  */
 
 #ifndef _S3C_AUDIO_H
@@ -17,6 +17,8 @@ struct s3c_dma_params {
        int channel;                            /* Channel ID */
        dma_addr_t dma_addr;
        int dma_size;                   /* Size of the DMA transfer */
+       unsigned ch;
+       struct samsung_dma_ops *ops;
 };
 
 #endif
This page took 0.246811 seconds and 5 git commands to generate.