[ARM] S3C: Merge next-s3c64xx-dma2 into for-rmk-devel
authorBen Dooks <ben-linux@fluff.org>
Mon, 18 May 2009 15:32:29 +0000 (16:32 +0100)
committerBen Dooks <ben-linux@fluff.org>
Mon, 18 May 2009 15:32:29 +0000 (16:32 +0100)
Merge branch 'next-s3c64xx-dma2' into for-rmk-devel

Conflicts:

arch/arm/plat-s3c64xx/Makefile

65 files changed:
arch/arm/common/Kconfig
arch/arm/common/vic.c
arch/arm/include/asm/hardware/vic.h
arch/arm/mach-ep93xx/core.c
arch/arm/mach-netx/generic.c
arch/arm/mach-s3c2410/Kconfig
arch/arm/mach-s3c2410/include/mach/map.h
arch/arm/mach-s3c2410/include/mach/system-reset.h
arch/arm/mach-s3c2412/Kconfig
arch/arm/mach-s3c2440/Kconfig
arch/arm/mach-s3c6400/Kconfig
arch/arm/mach-s3c6400/Makefile
arch/arm/mach-s3c6400/include/mach/map.h
arch/arm/mach-s3c6400/include/mach/regs-clock.h [new file with mode: 0644]
arch/arm/mach-s3c6400/include/mach/system.h
arch/arm/mach-s3c6400/mach-smdk6400.c [new file with mode: 0644]
arch/arm/mach-s3c6400/s3c6400.c [new file with mode: 0644]
arch/arm/mach-s3c6400/setup-sdhci.c [new file with mode: 0644]
arch/arm/mach-s3c6410/Kconfig
arch/arm/mach-s3c6410/Makefile
arch/arm/mach-s3c6410/cpu.c
arch/arm/mach-s3c6410/mach-anw6410.c [new file with mode: 0644]
arch/arm/mach-s3c6410/mach-ncp.c [new file with mode: 0644]
arch/arm/mach-s3c6410/mach-smdk6410.c
arch/arm/mach-s3c6410/setup-sdhci.c
arch/arm/mach-versatile/core.c
arch/arm/plat-s3c/Kconfig
arch/arm/plat-s3c/Makefile
arch/arm/plat-s3c/dev-usb-hsotg.c [new file with mode: 0644]
arch/arm/plat-s3c/dev-usb.c [new file with mode: 0644]
arch/arm/plat-s3c/gpio.c
arch/arm/plat-s3c/include/plat/adc.h
arch/arm/plat-s3c/include/plat/clock.h
arch/arm/plat-s3c/include/plat/cpu.h
arch/arm/plat-s3c/include/plat/devs.h
arch/arm/plat-s3c/include/plat/gpio-core.h
arch/arm/plat-s3c/include/plat/pm.h
arch/arm/plat-s3c/include/plat/regs-serial.h
arch/arm/plat-s3c/include/plat/sdhci.h
arch/arm/plat-s3c/include/plat/udc-hs.h [new file with mode: 0644]
arch/arm/plat-s3c/include/plat/watchdog-reset.h [new file with mode: 0644]
arch/arm/plat-s3c/pm-gpio.c [new file with mode: 0644]
arch/arm/plat-s3c/pm.c
arch/arm/plat-s3c24xx/adc.c
arch/arm/plat-s3c24xx/devs.c
arch/arm/plat-s3c24xx/gpiolib.c
arch/arm/plat-s3c24xx/include/plat/map.h
arch/arm/plat-s3c24xx/include/plat/pm-core.h
arch/arm/plat-s3c24xx/pm.c
arch/arm/plat-s3c64xx/Kconfig
arch/arm/plat-s3c64xx/Makefile
arch/arm/plat-s3c64xx/clock.c
arch/arm/plat-s3c64xx/cpu.c
arch/arm/plat-s3c64xx/gpiolib.c
arch/arm/plat-s3c64xx/include/plat/irqs.h
arch/arm/plat-s3c64xx/include/plat/pm-core.h [new file with mode: 0644]
arch/arm/plat-s3c64xx/include/plat/regs-clock.h
arch/arm/plat-s3c64xx/include/plat/s3c6400.h
arch/arm/plat-s3c64xx/irq-eint.c
arch/arm/plat-s3c64xx/irq-pm.c [new file with mode: 0644]
arch/arm/plat-s3c64xx/irq.c
arch/arm/plat-s3c64xx/pm.c [new file with mode: 0644]
arch/arm/plat-s3c64xx/s3c6400-clock.c
arch/arm/plat-s3c64xx/setup-sdhci-gpio.c [new file with mode: 0644]
arch/arm/plat-s3c64xx/sleep.S [new file with mode: 0644]

index a2cd9be..38518d4 100644 (file)
@@ -4,6 +4,13 @@ config ARM_GIC
 config ARM_VIC
        bool
 
+config ARM_VIC_NR
+       int
+       default 2
+       help
+         The maximum number of VICs available in the system, for
+         power management.
+
 config ICST525
        bool
 
index b2a781d..887c6eb 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/init.h>
 #include <linux/list.h>
 #include <linux/io.h>
+#include <linux/sysdev.h>
 
 #include <asm/mach/irq.h>
 #include <asm/hardware/vic.h>
@@ -39,11 +40,219 @@ static void vic_unmask_irq(unsigned int irq)
        writel(1 << irq, base + VIC_INT_ENABLE);
 }
 
+/**
+ * vic_init2 - common initialisation code
+ * @base: Base of the VIC.
+ *
+ * Common initialisation code for registeration
+ * and resume.
+*/
+static void vic_init2(void __iomem *base)
+{
+       int i;
+
+       for (i = 0; i < 16; i++) {
+               void __iomem *reg = base + VIC_VECT_CNTL0 + (i * 4);
+               writel(VIC_VECT_CNTL_ENABLE | i, reg);
+       }
+
+       writel(32, base + VIC_PL190_DEF_VECT_ADDR);
+}
+
+#if defined(CONFIG_PM)
+/**
+ * struct vic_device - VIC PM device
+ * @sysdev: The system device which is registered.
+ * @irq: The IRQ number for the base of the VIC.
+ * @base: The register base for the VIC.
+ * @resume_sources: A bitmask of interrupts for resume.
+ * @resume_irqs: The IRQs enabled for resume.
+ * @int_select: Save for VIC_INT_SELECT.
+ * @int_enable: Save for VIC_INT_ENABLE.
+ * @soft_int: Save for VIC_INT_SOFT.
+ * @protect: Save for VIC_PROTECT.
+ */
+struct vic_device {
+       struct sys_device sysdev;
+
+       void __iomem    *base;
+       int             irq;
+       u32             resume_sources;
+       u32             resume_irqs;
+       u32             int_select;
+       u32             int_enable;
+       u32             soft_int;
+       u32             protect;
+};
+
+/* we cannot allocate memory when VICs are initially registered */
+static struct vic_device vic_devices[CONFIG_ARM_VIC_NR];
+
+static inline struct vic_device *to_vic(struct sys_device *sys)
+{
+       return container_of(sys, struct vic_device, sysdev);
+}
+
+static int vic_id;
+
+static int vic_class_resume(struct sys_device *dev)
+{
+       struct vic_device *vic = to_vic(dev);
+       void __iomem *base = vic->base;
+
+       printk(KERN_DEBUG "%s: resuming vic at %p\n", __func__, base);
+
+       /* re-initialise static settings */
+       vic_init2(base);
+
+       writel(vic->int_select, base + VIC_INT_SELECT);
+       writel(vic->protect, base + VIC_PROTECT);
+
+       /* set the enabled ints and then clear the non-enabled */
+       writel(vic->int_enable, base + VIC_INT_ENABLE);
+       writel(~vic->int_enable, base + VIC_INT_ENABLE_CLEAR);
+
+       /* and the same for the soft-int register */
+
+       writel(vic->soft_int, base + VIC_INT_SOFT);
+       writel(~vic->soft_int, base + VIC_INT_SOFT_CLEAR);
+
+       return 0;
+}
+
+static int vic_class_suspend(struct sys_device *dev, pm_message_t state)
+{
+       struct vic_device *vic = to_vic(dev);
+       void __iomem *base = vic->base;
+
+       printk(KERN_DEBUG "%s: suspending vic at %p\n", __func__, base);
+
+       vic->int_select = readl(base + VIC_INT_SELECT);
+       vic->int_enable = readl(base + VIC_INT_ENABLE);
+       vic->soft_int = readl(base + VIC_INT_SOFT);
+       vic->protect = readl(base + VIC_PROTECT);
+
+       /* set the interrupts (if any) that are used for
+        * resuming the system */
+
+       writel(vic->resume_irqs, base + VIC_INT_ENABLE);
+       writel(~vic->resume_irqs, base + VIC_INT_ENABLE_CLEAR);
+
+       return 0;
+}
+
+struct sysdev_class vic_class = {
+       .name           = "vic",
+       .suspend        = vic_class_suspend,
+       .resume         = vic_class_resume,
+};
+
+/**
+ * vic_pm_register - Register a VIC for later power management control
+ * @base: The base address of the VIC.
+ * @irq: The base IRQ for the VIC.
+ * @resume_sources: bitmask of interrupts allowed for resume sources.
+ *
+ * Register the VIC with the system device tree so that it can be notified
+ * of suspend and resume requests and ensure that the correct actions are
+ * taken to re-instate the settings on resume.
+ */
+static void __init vic_pm_register(void __iomem *base, unsigned int irq, u32 resume_sources)
+{
+       struct vic_device *v;
+
+       if (vic_id >= ARRAY_SIZE(vic_devices))
+               printk(KERN_ERR "%s: too few VICs, increase CONFIG_ARM_VIC_NR\n", __func__);
+       else {
+               v = &vic_devices[vic_id];
+               v->base = base;
+               v->resume_sources = resume_sources;
+               v->irq = irq;
+               vic_id++;
+       }
+}
+
+/**
+ * vic_pm_init - initicall to register VIC pm
+ *
+ * This is called via late_initcall() to register
+ * the resources for the VICs due to the early
+ * nature of the VIC's registration.
+*/
+static int __init vic_pm_init(void)
+{
+       struct vic_device *dev = vic_devices;
+       int err;
+       int id;
+
+       if (vic_id == 0)
+               return 0;
+
+       err = sysdev_class_register(&vic_class);
+       if (err) {
+               printk(KERN_ERR "%s: cannot register class\n", __func__);
+               return err;
+       }
+
+       for (id = 0; id < vic_id; id++, dev++) {
+               dev->sysdev.id = id;
+               dev->sysdev.cls = &vic_class;
+
+               err = sysdev_register(&dev->sysdev);
+               if (err) {
+                       printk(KERN_ERR "%s: failed to register device\n",
+                              __func__);
+                       return err;
+               }
+       }
+
+       return 0;
+}
+
+late_initcall(vic_pm_init);
+
+static struct vic_device *vic_from_irq(unsigned int irq)
+{
+        struct vic_device *v = vic_devices;
+       unsigned int base_irq = irq & ~31;
+       int id;
+
+       for (id = 0; id < vic_id; id++, v++) {
+               if (v->irq == base_irq)
+                       return v;
+       }
+
+       return NULL;
+}
+
+static int vic_set_wake(unsigned int irq, unsigned int on)
+{
+       struct vic_device *v = vic_from_irq(irq);
+       unsigned int off = irq & 31;
+
+       if (!v)
+               return -EINVAL;
+
+       if (on)
+               v->resume_irqs |= 1 << off;
+       else
+               v->resume_irqs &= ~(1 << off);
+
+       return 0;
+}
+
+#else
+static inline void vic_pm_register(void __iomem *base, unsigned int irq, u32 arg1) { }
+
+#define vic_set_wake NULL
+#endif /* CONFIG_PM */
+
 static struct irq_chip vic_chip = {
        .name   = "VIC",
        .ack    = vic_mask_irq,
        .mask   = vic_mask_irq,
        .unmask = vic_unmask_irq,
+       .set_wake = vic_set_wake,
 };
 
 /**
@@ -51,9 +260,10 @@ static struct irq_chip vic_chip = {
  * @base: iomem base address
  * @irq_start: starting interrupt number, must be muliple of 32
  * @vic_sources: bitmask of interrupt sources to allow
+ * @resume_sources: bitmask of interrupt sources to allow for resume
  */
 void __init vic_init(void __iomem *base, unsigned int irq_start,
-                    u32 vic_sources)
+                    u32 vic_sources, u32 resume_sources)
 {
        unsigned int i;
 
@@ -77,12 +287,7 @@ void __init vic_init(void __iomem *base, unsigned int irq_start,
                writel(value, base + VIC_PL190_VECT_ADDR);
        }
 
-       for (i = 0; i < 16; i++) {
-               void __iomem *reg = base + VIC_VECT_CNTL0 + (i * 4);
-               writel(VIC_VECT_CNTL_ENABLE | i, reg);
-       }
-
-       writel(32, base + VIC_PL190_DEF_VECT_ADDR);
+       vic_init2(base);
 
        for (i = 0; i < 32; i++) {
                if (vic_sources & (1 << i)) {
@@ -94,4 +299,6 @@ void __init vic_init(void __iomem *base, unsigned int irq_start,
                        set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
                }
        }
+
+       vic_pm_register(base, irq_start, resume_sources);
 }
index f87328d..5d72550 100644 (file)
@@ -41,7 +41,7 @@
 #define VIC_PL192_VECT_ADDR            0xF00
 
 #ifndef __ASSEMBLY__
-void vic_init(void __iomem *base, unsigned int irq_start, u32 vic_sources);
+void vic_init(void __iomem *base, unsigned int irq_start, u32 vic_sources, u32 resume_sources);
 #endif
 
 #endif
index ae24486..6faa3dc 100644 (file)
@@ -362,8 +362,8 @@ void __init ep93xx_init_irq(void)
 {
        int gpio_irq;
 
-       vic_init((void *)EP93XX_VIC1_BASE, 0, EP93XX_VIC1_VALID_IRQ_MASK);
-       vic_init((void *)EP93XX_VIC2_BASE, 32, EP93XX_VIC2_VALID_IRQ_MASK);
+       vic_init((void *)EP93XX_VIC1_BASE, 0, EP93XX_VIC1_VALID_IRQ_MASK, 0);
+       vic_init((void *)EP93XX_VIC2_BASE, 32, EP93XX_VIC2_VALID_IRQ_MASK, 0);
 
        for (gpio_irq = gpio_to_irq(0);
             gpio_irq <= gpio_to_irq(EP93XX_GPIO_LINE_MAX_IRQ); ++gpio_irq) {
index 79df60c..43da8bb 100644 (file)
@@ -168,7 +168,7 @@ void __init netx_init_irq(void)
 {
        int irq;
 
-       vic_init(__io(io_p2v(NETX_PA_VIC)), 0, ~0);
+       vic_init(__io(io_p2v(NETX_PA_VIC)), 0, ~0, 0);
 
        for (irq = NETX_IRQ_HIF_CHAINED(0); irq <= NETX_IRQ_HIF_LAST; irq++) {
                set_irq_chip(irq, &netx_hif_chip);
index 63a30d1..41bb65d 100644 (file)
@@ -59,6 +59,7 @@ config ARCH_H1940
        bool "IPAQ H1940"
        select CPU_S3C2410
        select PM_H1940 if PM
+       select S3C_DEV_USB_HOST
        help
          Say Y here if you are using the HP IPAQ H1940
 
@@ -70,6 +71,7 @@ config PM_H1940
 config MACH_N30
        bool "Acer N30 family"
        select CPU_S3C2410
+       select S3C_DEV_USB_HOST
        help
          Say Y here if you want suppt for the Acer N30, Acer N35,
          Navman PiN570, Yakumo AlphaX or Airis NC05 PDAs.
@@ -82,6 +84,7 @@ config ARCH_BAST
        select MACH_BAST_IDE
        select S3C24XX_DCLK
        select ISA
+       select S3C_DEV_USB_HOST
        help
          Say Y here if you are using the Simtec Electronics EB2410ITX
          development board (also known as BAST)
@@ -89,6 +92,7 @@ config ARCH_BAST
 config MACH_OTOM
        bool "NexVision OTOM Board"
        select CPU_S3C2410
+       select S3C_DEV_USB_HOST
        help
          Say Y here if you are using the Nex Vision OTOM board
 
@@ -96,6 +100,7 @@ config MACH_AML_M5900
        bool "AML M5900 Series"
        select CPU_S3C2410
        select PM_SIMTEC if PM
+       select S3C_DEV_USB_HOST
        help
           Say Y here if you are using the American Microsystems M5900 Series
            <http://www.amltd.com>
@@ -111,6 +116,7 @@ config BAST_PC104_IRQ
 config MACH_TCT_HAMMER
        bool "TCT Hammer Board"
        select CPU_S3C2410
+       select S3C_DEV_USB_HOST
        help
           Say Y here if you are using the TinCanTools Hammer Board
            <http://www.tincantools.com>
@@ -122,12 +128,14 @@ config MACH_VR1000
        select SIMTEC_NOR
        select MACH_BAST_IDE
        select CPU_S3C2410
+       select S3C_DEV_USB_HOST
        help
          Say Y here if you are using the Thorcom VR1000 board.
 
 config MACH_QT2410
        bool "QT2410"
        select CPU_S3C2410
+       select S3C_DEV_USB_HOST
        help
           Say Y here if you are using the Armzone QT2410
 
index 255fdfe..e99b212 100644 (file)
@@ -84,7 +84,6 @@
 
 #define S3C24XX_PA_IRQ      S3C2410_PA_IRQ
 #define S3C24XX_PA_MEMCTRL  S3C2410_PA_MEMCTRL
-#define S3C24XX_PA_USBHOST  S3C2410_PA_USBHOST
 #define S3C24XX_PA_DMA      S3C2410_PA_DMA
 #define S3C24XX_PA_CLKPWR   S3C2410_PA_CLKPWR
 #define S3C24XX_PA_LCD      S3C2410_PA_LCD
 
 #define S3C_PA_IIC          S3C2410_PA_IIC
 #define S3C_PA_UART        S3C24XX_PA_UART
+#define S3C_PA_USBHOST S3C2410_PA_USBHOST
 #define S3C_PA_HSMMC0      S3C2443_PA_HSMMC
 
 #endif /* __ASM_ARCH_MAP_H */
index b8687f7..6faadce 100644 (file)
 */
 
 #include <mach/hardware.h>
-#include <linux/io.h>
-
-#include <plat/regs-watchdog.h>
-#include <mach/regs-clock.h>
-
-#include <linux/clk.h>
-#include <linux/err.h>
+#include <plat/watchdog-reset.h>
 
 extern void (*s3c24xx_reset_hook)(void);
 
 static void
 arch_reset(char mode, const char *cmd)
 {
-       struct clk *wdtclk;
-
        if (mode == 's') {
                cpu_reset(0);
        }
@@ -33,31 +25,7 @@ arch_reset(char mode, const char *cmd)
        if (s3c24xx_reset_hook)
                s3c24xx_reset_hook();
 
-       printk("arch_reset: attempting watchdog reset\n");
-
-       __raw_writel(0, S3C2410_WTCON);   /* disable watchdog, to be safe  */
-
-       wdtclk = clk_get(NULL, "watchdog");
-       if (!IS_ERR(wdtclk)) {
-               clk_enable(wdtclk);
-       } else
-               printk(KERN_WARNING "%s: warning: cannot get watchdog clock\n", __func__);
-
-       /* put initial values into count and data */
-       __raw_writel(0x80, S3C2410_WTCNT);
-       __raw_writel(0x80, S3C2410_WTDAT);
-
-       /* set the watchdog to go and reset... */
-       __raw_writel(S3C2410_WTCON_ENABLE|S3C2410_WTCON_DIV16|S3C2410_WTCON_RSTEN |
-                    S3C2410_WTCON_PRESCALE(0x20), S3C2410_WTCON);
-
-       /* wait for reset to assert... */
-       mdelay(500);
-
-       printk(KERN_ERR "Watchdog reset failed to assert reset\n");
-
-       /* delay to allow the serial port to show the message */
-       mdelay(50);
+       arch_wdt_reset();
 
        /* we'll take a jump through zero as a poor second */
        cpu_reset(0);
index ca99564..63586ff 100644 (file)
@@ -38,6 +38,7 @@ menu "S3C2412 Machines"
 config MACH_JIVE
        bool "Logitech Jive"
        select CPU_S3C2412
+       select S3C_DEV_USB_HOST
        help
          Say Y here if you are using the Logitech Jive.
 
@@ -50,6 +51,7 @@ config MACH_SMDK2413
        select CPU_S3C2412
        select MACH_S3C2413
        select MACH_SMDK
+       select S3C_DEV_USB_HOST
        help
          Say Y here if you are using an SMDK2413
 
@@ -72,6 +74,7 @@ config MACH_SMDK2412
 config MACH_VSTMS
        bool "VMSTMS"
        select CPU_S3C2412
+       select S3C_DEV_USB_HOST
        help
          Say Y here if you are using an VSTMS board
 
index cde5ae9..5df73cb 100644 (file)
@@ -33,6 +33,7 @@ config MACH_ANUBIS
        select PM_SIMTEC if PM
        select HAVE_PATA_PLATFORM
        select S3C24XX_GPIO_EXTRA64
+       select S3C_DEV_USB_HOST
        help
          Say Y here if you are using the Simtec Electronics ANUBIS
          development system
@@ -43,6 +44,7 @@ config MACH_OSIRIS
        select S3C24XX_DCLK
        select PM_SIMTEC if PM
        select S3C24XX_GPIO_EXTRA128
+       select S3C_DEV_USB_HOST
        help
          Say Y here if you are using the Simtec IM2440D20 module, also
          known as the Osiris.
@@ -58,12 +60,14 @@ config ARCH_S3C2440
        bool "SMDK2440"
        select CPU_S3C2440
        select MACH_SMDK
+       select S3C_DEV_USB_HOST
        help
          Say Y here if you are using the SMDK2440.
 
 config MACH_NEXCODER_2440
        bool "NexVision NEXCODER 2440 Light Board"
        select CPU_S3C2440
+       select S3C_DEV_USB_HOST
        help
          Say Y here if you are using the Nex Vision NEXCODER 2440 Light Board
 
@@ -76,6 +80,7 @@ config SMDK2440_CPU2440
 config MACH_AT2440EVB
        bool "Avantech AT2440EVB development board"
        select CPU_S3C2440
+       select S3C_DEV_USB_HOST
        help
          Say Y here if you are using the AT2440EVB development board
 
index 6da82b5..f5af212 100644 (file)
@@ -5,4 +5,27 @@
 #
 # Licensed under GPLv2
 
-# Currently nothing here, this will be added later
+# Configuration options for the S3C6410 CPU
+
+config CPU_S3C6400
+       bool
+       select CPU_S3C6400_INIT
+       select CPU_S3C6400_CLOCK
+       help
+         Enable S3C6400 CPU support
+
+config S3C6400_SETUP_SDHCI
+       bool
+       help
+         Internal configuration for default SDHCI
+         setup for S3C6400.
+
+# S36400 Macchine support
+
+config MACH_SMDK6400
+       bool "SMDK6400"
+       select CPU_S3C6400
+       select S3C_DEV_HSMMC
+       select S3C6400_SETUP_SDHCI
+       help
+         Machine support for the Samsung SMDK6400
index 8f397db..df1ce4a 100644 (file)
@@ -12,4 +12,12 @@ obj-                         :=
 
 # Core support for S3C6400 system
 
-obj-n                          += blank.o
+obj-$(CONFIG_CPU_S3C6400)      += s3c6400.o
+
+# setup support
+
+obj-$(CONFIG_S3C6400_SETUP_SDHCI) += setup-sdhci.o
+
+# Machine support
+
+obj-$(CONFIG_MACH_SMDK6400)    += mach-smdk6400.o
index baf1c0f..7a1e5a2 100644 (file)
@@ -39,6 +39,8 @@
 #define S3C_VA_UART3           S3C_VA_UARTx(3)
 
 #define S3C64XX_PA_FB          (0x77100000)
+#define S3C64XX_PA_USB_HSOTG   (0x7C000000)
+#define S3C64XX_PA_WATCHDOG    (0x7E004000)
 #define S3C64XX_PA_SYSCON      (0x7E00F000)
 #define S3C64XX_PA_TIMER       (0x7F006000)
 #define S3C64XX_PA_IIC0                (0x7F004000)
@@ -55,6 +57,8 @@
 #define S3C64XX_PA_MODEM       (0x74108000)
 #define S3C64XX_VA_MODEM       S3C_ADDR(0x00600000)
 
+#define S3C64XX_PA_USBHOST     (0x74300000)
+
 /* place VICs close together */
 #define S3C_VA_VIC0            (S3C_VA_IRQ + 0x00)
 #define S3C_VA_VIC1            (S3C_VA_IRQ + 0x10000)
@@ -67,5 +71,7 @@
 #define S3C_PA_IIC             S3C64XX_PA_IIC0
 #define S3C_PA_IIC1            S3C64XX_PA_IIC1
 #define S3C_PA_FB              S3C64XX_PA_FB
+#define S3C_PA_USBHOST         S3C64XX_PA_USBHOST
+#define S3C_PA_USB_HSOTG       S3C64XX_PA_USB_HSOTG
 
 #endif /* __ASM_ARCH_6400_MAP_H */
diff --git a/arch/arm/mach-s3c6400/include/mach/regs-clock.h b/arch/arm/mach-s3c6400/include/mach/regs-clock.h
new file mode 100644 (file)
index 0000000..a6c7f4e
--- /dev/null
@@ -0,0 +1,16 @@
+/* linux/arch/arm/mach-s3c6400/include/mach/regs-clock.h
+ *
+ * Copyright 2008 Openmoko, Inc.
+ * Copyright 2008 Simtec Electronics
+ *     http://armlinux.simtec.co.uk/
+ *     Ben Dooks <ben@simtec.co.uk>
+ *
+ * S3C64XX - clock register compatibility with s3c24xx
+ *
+ * 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 <plat/regs-clock.h>
+
index 090cfd9..2e58cb7 100644 (file)
@@ -11,6 +11,8 @@
 #ifndef __ASM_ARCH_SYSTEM_H
 #define __ASM_ARCH_SYSTEM_H __FILE__
 
+#include <plat/watchdog-reset.h>
+
 static void arch_idle(void)
 {
        /* nothing here yet */
@@ -18,7 +20,11 @@ static void arch_idle(void)
 
 static void arch_reset(char mode, const char *cmd)
 {
-       /* nothing here yet */
+       if (mode != 's')
+               arch_wdt_reset();
+
+       /* if all else fails, or mode was for soft, jump to 0 */
+       cpu_reset(0);
 }
 
 #endif /* __ASM_ARCH_IRQ_H */
diff --git a/arch/arm/mach-s3c6400/mach-smdk6400.c b/arch/arm/mach-s3c6400/mach-smdk6400.c
new file mode 100644 (file)
index 0000000..ab19285
--- /dev/null
@@ -0,0 +1,96 @@
+/* linux/arch/arm/mach-s3c6400/mach-smdk6400.c
+ *
+ * Copyright 2008 Simtec Electronics
+ *     Ben Dooks <ben@simtec.co.uk>
+ *     http://armlinux.simtec.co.uk/
+ *
+ * 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/interrupt.h>
+#include <linux/list.h>
+#include <linux/timer.h>
+#include <linux/init.h>
+#include <linux/serial_core.h>
+#include <linux/platform_device.h>
+#include <linux/i2c.h>
+#include <linux/io.h>
+
+#include <asm/mach-types.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <mach/hardware.h>
+#include <mach/map.h>
+
+#include <plat/regs-serial.h>
+
+#include <plat/s3c6400.h>
+#include <plat/clock.h>
+#include <plat/devs.h>
+#include <plat/cpu.h>
+#include <plat/iic.h>
+
+#define UCON S3C2410_UCON_DEFAULT | S3C2410_UCON_UCLK
+#define ULCON S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB
+#define UFCON S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE
+
+static struct s3c2410_uartcfg smdk6400_uartcfgs[] __initdata = {
+       [0] = {
+               .hwport      = 0,
+               .flags       = 0,
+               .ucon        = 0x3c5,
+               .ulcon       = 0x03,
+               .ufcon       = 0x51,
+       },
+       [1] = {
+               .hwport      = 1,
+               .flags       = 0,
+               .ucon        = 0x3c5,
+               .ulcon       = 0x03,
+               .ufcon       = 0x51,
+       },
+};
+
+static struct map_desc smdk6400_iodesc[] = {};
+
+static void __init smdk6400_map_io(void)
+{
+       s3c64xx_init_io(smdk6400_iodesc, ARRAY_SIZE(smdk6400_iodesc));
+       s3c24xx_init_clocks(12000000);
+       s3c24xx_init_uarts(smdk6400_uartcfgs, ARRAY_SIZE(smdk6400_uartcfgs));
+}
+
+static struct platform_device *smdk6400_devices[] __initdata = {
+       &s3c_device_hsmmc1,
+       &s3c_device_i2c0,
+};
+
+static struct i2c_board_info i2c_devs[] __initdata = {
+       { I2C_BOARD_INFO("wm8753", 0x1A), },
+       { I2C_BOARD_INFO("24c08", 0x50), },
+};
+
+static void __init smdk6400_machine_init(void)
+{
+       i2c_register_board_info(0, i2c_devs, ARRAY_SIZE(i2c_devs));
+       platform_add_devices(smdk6400_devices, ARRAY_SIZE(smdk6400_devices));
+}
+
+MACHINE_START(SMDK6400, "SMDK6400")
+       /* Maintainer: Ben Dooks <ben@fluff.org> */
+       .phys_io        = S3C_PA_UART & 0xfff00000,
+       .io_pg_offst    = (((u32)S3C_VA_UART) >> 18) & 0xfffc,
+       .boot_params    = S3C64XX_PA_SDRAM + 0x100,
+
+       .init_irq       = s3c6400_init_irq,
+       .map_io         = smdk6400_map_io,
+       .init_machine   = smdk6400_machine_init,
+       .timer          = &s3c24xx_timer,
+MACHINE_END
diff --git a/arch/arm/mach-s3c6400/s3c6400.c b/arch/arm/mach-s3c6400/s3c6400.c
new file mode 100644 (file)
index 0000000..1ece887
--- /dev/null
@@ -0,0 +1,89 @@
+/* linux/arch/arm/mach-s3c6410/cpu.c
+ *
+ * Copyright 2009 Simtec Electronics
+ *     Ben Dooks <ben@simtec.co.uk>
+ *     http://armlinux.simtec.co.uk/
+ *
+ * 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/interrupt.h>
+#include <linux/list.h>
+#include <linux/timer.h>
+#include <linux/init.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/sysdev.h>
+#include <linux/serial_core.h>
+#include <linux/platform_device.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <mach/hardware.h>
+#include <asm/irq.h>
+
+#include <plat/cpu-freq.h>
+#include <plat/regs-serial.h>
+#include <plat/regs-clock.h>
+
+#include <plat/cpu.h>
+#include <plat/devs.h>
+#include <plat/clock.h>
+#include <plat/sdhci.h>
+#include <plat/iic-core.h>
+#include <plat/s3c6400.h>
+
+void __init s3c6400_map_io(void)
+{
+       /* setup SDHCI */
+
+       s3c6400_default_sdhci0();
+       s3c6400_default_sdhci1();
+
+       /* the i2c devices are directly compatible with s3c2440 */
+       s3c_i2c0_setname("s3c2440-i2c");
+}
+
+void __init s3c6400_init_clocks(int xtal)
+{
+       printk(KERN_DEBUG "%s: initialising clocks\n", __func__);
+       s3c24xx_register_baseclocks(xtal);
+       s3c64xx_register_clocks();
+       s3c6400_register_clocks(S3C6400_CLKDIV0_ARM_MASK);
+       s3c6400_setup_clocks();
+}
+
+void __init s3c6400_init_irq(void)
+{
+       /* VIC0 does not have IRQS 5..7,
+        * VIC1 is fully populated. */
+       s3c64xx_init_irq(~0 & ~(0xf << 5), ~0);
+}
+
+struct sysdev_class s3c6400_sysclass = {
+       .name   = "s3c6400-core",
+};
+
+static struct sys_device s3c6400_sysdev = {
+       .cls    = &s3c6400_sysclass,
+};
+
+static int __init s3c6400_core_init(void)
+{
+       return sysdev_class_register(&s3c6400_sysclass);
+}
+
+core_initcall(s3c6400_core_init);
+
+int __init s3c6400_init(void)
+{
+       printk("S3C6400: Initialising architecture\n");
+
+       return sysdev_register(&s3c6400_sysdev);
+}
diff --git a/arch/arm/mach-s3c6400/setup-sdhci.c b/arch/arm/mach-s3c6400/setup-sdhci.c
new file mode 100644 (file)
index 0000000..b93dafb
--- /dev/null
@@ -0,0 +1,63 @@
+/* linux/arch/arm/mach-s3c6410/setup-sdhci.c
+ *
+ * Copyright 2008 Simtec Electronics
+ * Copyright 2008 Simtec Electronics
+ *     Ben Dooks <ben@simtec.co.uk>
+ *     http://armlinux.simtec.co.uk/
+ *
+ * S3C6410 - Helper functions for settign up SDHCI device(s) (HSMMC)
+ *
+ * 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/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+
+#include <linux/mmc/card.h>
+#include <linux/mmc/host.h>
+
+#include <plat/regs-sdhci.h>
+#include <plat/sdhci.h>
+
+/* clock sources for the mmc bus clock, order as for the ctrl2[5..4] */
+
+char *s3c6400_hsmmc_clksrcs[4] = {
+       [0] = "hsmmc",
+       [1] = "hsmmc",
+       [2] = "mmc_bus",
+       /* [3] = "48m", - note not succesfully used yet */
+};
+
+void s3c6400_setup_sdhci_cfg_card(struct platform_device *dev,
+                                 void __iomem *r,
+                                 struct mmc_ios *ios,
+                                 struct mmc_card *card)
+{
+       u32 ctrl2, ctrl3;
+
+       ctrl2 = readl(r + S3C_SDHCI_CONTROL2);
+       ctrl2 &= S3C_SDHCI_CTRL2_SELBASECLK_MASK;
+       ctrl2 |= (S3C64XX_SDHCI_CTRL2_ENSTAASYNCCLR |
+                 S3C64XX_SDHCI_CTRL2_ENCMDCNFMSK |
+                 S3C_SDHCI_CTRL2_ENFBCLKRX |
+                 S3C_SDHCI_CTRL2_DFCNT_NONE |
+                 S3C_SDHCI_CTRL2_ENCLKOUTHOLD);
+
+       if (ios->clock < 25 * 1000000)
+               ctrl3 = (S3C_SDHCI_CTRL3_FCSEL3 |
+                        S3C_SDHCI_CTRL3_FCSEL2 |
+                        S3C_SDHCI_CTRL3_FCSEL1 |
+                        S3C_SDHCI_CTRL3_FCSEL0);
+       else
+               ctrl3 = (S3C_SDHCI_CTRL3_FCSEL1 | S3C_SDHCI_CTRL3_FCSEL0);
+
+       printk(KERN_INFO "%s: CTRL 2=%08x, 3=%08x\n", __func__, ctrl2, ctrl3);
+       writel(ctrl2, r + S3C_SDHCI_CONTROL2);
+       writel(ctrl3, r + S3C_SDHCI_CONTROL3);
+}
+
index 1d50100..e63aac7 100644 (file)
@@ -16,9 +16,18 @@ config CPU_S3C6410
 
 config S3C6410_SETUP_SDHCI
        bool
+       select S3C64XX_SETUP_SDHCI_GPIO
        help
          Internal helper functions for S3C6410 based SDHCI systems
 
+config MACH_ANW6410
+       bool "A&W6410"
+       select CPU_S3C6410
+       select S3C_DEV_FB
+       select S3C64XX_SETUP_FB_24BPP
+       help
+         Machine support for the A&W6410
+
 config MACH_SMDK6410
        bool "SMDK6410"
        select CPU_S3C6410
@@ -26,6 +35,8 @@ config MACH_SMDK6410
        select S3C_DEV_HSMMC1
        select S3C_DEV_I2C1
        select S3C_DEV_FB
+       select S3C_DEV_USB_HOST
+       select S3C_DEV_USB_HSOTG
        select S3C6410_SETUP_SDHCI
        select S3C64XX_SETUP_I2C1
        select S3C64XX_SETUP_FB_24BPP
@@ -60,3 +71,29 @@ config SMDK6410_SD_CH1
          channels 0 and 1 are the same.
 
 endchoice
+
+config SMDK6410_WM1190_EV1
+       bool "Support Wolfson Microelectronics 1190-EV1 PMIC card"
+       depends on MACH_SMDK6410
+       select REGULATOR
+       select REGULATOR_WM8350
+       select MFD_WM8350_I2C
+       select MFD_WM8350_CONFIG_MODE_0
+       select MFD_WM8350_CONFIG_MODE_3
+       select MFD_WM8352_CONFIG_MODE_0
+       help
+         The Wolfson Microelectronics 1190-EV1 is a WM835x based PMIC
+         and audio daughtercard for the Samsung SMDK6410 reference
+         platform.  Enabling this option will build support for this
+         module into the kernel.  The presence of the module will be
+         detected at runtime so the the resulting kernel can be used
+         with or without the 1190-EV1 fitted.
+
+config MACH_NCP
+       bool "NCP"
+       select CPU_S3C6410
+       select S3C_DEV_I2C1
+       select S3C_DEV_HSMMC1
+       select S3C64XX_SETUP_I2C1
+       help
+          Machine support for the Samsung NCP
index 2cd4f18..6f9deac 100644 (file)
@@ -20,4 +20,8 @@ obj-$(CONFIG_S3C6410_SETUP_SDHCI)     += setup-sdhci.o
 
 # machine support
 
+obj-$(CONFIG_MACH_ANW6410)     += mach-anw6410.o
 obj-$(CONFIG_MACH_SMDK6410)    += mach-smdk6410.o
+obj-$(CONFIG_MACH_NCP)         += mach-ncp.o
+
+
index 6a73ca6..ade904d 100644 (file)
@@ -31,6 +31,7 @@
 
 #include <plat/cpu-freq.h>
 #include <plat/regs-serial.h>
+#include <plat/regs-clock.h>
 
 #include <plat/cpu.h>
 #include <plat/devs.h>
@@ -68,7 +69,7 @@ void __init s3c6410_init_clocks(int xtal)
        printk(KERN_DEBUG "%s: initialising clocks\n", __func__);
        s3c24xx_register_baseclocks(xtal);
        s3c64xx_register_clocks();
-       s3c6400_register_clocks();
+       s3c6400_register_clocks(S3C6410_CLKDIV0_ARM_MASK);
        s3c6400_setup_clocks();
 }
 
diff --git a/arch/arm/mach-s3c6410/mach-anw6410.c b/arch/arm/mach-s3c6410/mach-anw6410.c
new file mode 100644 (file)
index 0000000..661cca6
--- /dev/null
@@ -0,0 +1,245 @@
+/* linux/arch/arm/mach-s3c6410/mach-anw6410.c
+ *
+ * Copyright 2008 Openmoko, Inc.
+ * Copyright 2008 Simtec Electronics
+ *     Ben Dooks <ben@simtec.co.uk>
+ *     http://armlinux.simtec.co.uk/
+ * Copyright 2009 Kwangwoo Lee
+ *     Kwangwoo Lee <kwangwoo.lee@gmail.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/types.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/timer.h>
+#include <linux/init.h>
+#include <linux/serial_core.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/i2c.h>
+#include <linux/fb.h>
+#include <linux/gpio.h>
+#include <linux/delay.h>
+#include <linux/dm9000.h>
+
+#include <video/platform_lcd.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <mach/hardware.h>
+#include <mach/regs-fb.h>
+#include <mach/map.h>
+
+#include <asm/irq.h>
+#include <asm/mach-types.h>
+
+#include <plat/regs-serial.h>
+#include <plat/iic.h>
+#include <plat/fb.h>
+
+#include <plat/s3c6410.h>
+#include <plat/clock.h>
+#include <plat/devs.h>
+#include <plat/cpu.h>
+#include <plat/regs-gpio.h>
+#include <plat/regs-modem.h>
+
+/* DM9000 */
+#define ANW6410_PA_DM9000      (0x18000000)
+
+/* A hardware buffer to control external devices is mapped at 0x30000000.
+ * It can not be read. So current status must be kept in anw6410_extdev_status.
+ */
+#define ANW6410_VA_EXTDEV      S3C_ADDR(0x02000000)
+#define ANW6410_PA_EXTDEV      (0x30000000)
+
+#define ANW6410_EN_DM9000      (1<<11)
+#define ANW6410_EN_LCD         (1<<14)
+
+static __u32 anw6410_extdev_status;
+
+static struct s3c2410_uartcfg anw6410_uartcfgs[] __initdata = {
+       [0] = {
+               .hwport      = 0,
+               .flags       = 0,
+               .ucon        = 0x3c5,
+               .ulcon       = 0x03,
+               .ufcon       = 0x51,
+       },
+       [1] = {
+               .hwport      = 1,
+               .flags       = 0,
+               .ucon        = 0x3c5,
+               .ulcon       = 0x03,
+               .ufcon       = 0x51,
+       },
+};
+
+/* framebuffer and LCD setup. */
+static void __init anw6410_lcd_mode_set(void)
+{
+       u32 tmp;
+
+       /* set the LCD type */
+       tmp = __raw_readl(S3C64XX_SPCON);
+       tmp &= ~S3C64XX_SPCON_LCD_SEL_MASK;
+       tmp |= S3C64XX_SPCON_LCD_SEL_RGB;
+       __raw_writel(tmp, S3C64XX_SPCON);
+
+       /* remove the LCD bypass */
+       tmp = __raw_readl(S3C64XX_MODEM_MIFPCON);
+       tmp &= ~MIFPCON_LCD_BYPASS;
+       __raw_writel(tmp, S3C64XX_MODEM_MIFPCON);
+}
+
+/* GPF1 = LCD panel power
+ * GPF4 = LCD backlight control
+ */
+static void anw6410_lcd_power_set(struct plat_lcd_data *pd,
+                                  unsigned int power)
+{
+       if (power) {
+               anw6410_extdev_status |= (ANW6410_EN_LCD << 16);
+               __raw_writel(anw6410_extdev_status, ANW6410_VA_EXTDEV);
+
+               gpio_direction_output(S3C64XX_GPF(1), 1);
+               gpio_direction_output(S3C64XX_GPF(4), 1);
+       } else {
+               anw6410_extdev_status &= ~(ANW6410_EN_LCD << 16);
+               __raw_writel(anw6410_extdev_status, ANW6410_VA_EXTDEV);
+
+               gpio_direction_output(S3C64XX_GPF(1), 0);
+               gpio_direction_output(S3C64XX_GPF(4), 0);
+       }
+}
+
+static struct plat_lcd_data anw6410_lcd_power_data = {
+       .set_power      = anw6410_lcd_power_set,
+};
+
+static struct platform_device anw6410_lcd_powerdev = {
+       .name                   = "platform-lcd",
+       .dev.parent             = &s3c_device_fb.dev,
+       .dev.platform_data      = &anw6410_lcd_power_data,
+};
+
+static struct s3c_fb_pd_win anw6410_fb_win0 = {
+       /* this is to ensure we use win0 */
+       .win_mode       = {
+               .pixclock       = 41094,
+               .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    = 16,
+};
+
+/* 405566 clocks per frame => 60Hz refresh requires 24333960Hz clock */
+static struct s3c_fb_platdata anw6410_lcd_pdata __initdata = {
+       .setup_gpio     = s3c64xx_fb_gpio_setup_24bpp,
+       .win[0]         = &anw6410_fb_win0,
+       .vidcon0        = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB,
+       .vidcon1        = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC,
+};
+
+/* DM9000AEP 10/100 ethernet controller */
+static void __init anw6410_dm9000_enable(void)
+{
+       anw6410_extdev_status |= (ANW6410_EN_DM9000 << 16);
+       __raw_writel(anw6410_extdev_status, ANW6410_VA_EXTDEV);
+}
+
+static struct resource anw6410_dm9000_resource[] = {
+       [0] = {
+               .start = ANW6410_PA_DM9000,
+               .end   = ANW6410_PA_DM9000 + 3,
+               .flags = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start = ANW6410_PA_DM9000 + 4,
+               .end   = ANW6410_PA_DM9000 + 4 + 500,
+               .flags = IORESOURCE_MEM,
+       },
+       [2] = {
+               .start = IRQ_EINT(15),
+               .end   = IRQ_EINT(15),
+               .flags = IORESOURCE_IRQ | IRQF_TRIGGER_HIGH,
+       },
+};
+
+static struct dm9000_plat_data anw6410_dm9000_pdata = {
+       .flags    = (DM9000_PLATF_16BITONLY | DM9000_PLATF_NO_EEPROM),
+       /* dev_addr can be set to provide hwaddr. */
+};
+
+static struct platform_device anw6410_device_eth = {
+       .name   = "dm9000",
+       .id     = -1,
+       .num_resources  = ARRAY_SIZE(anw6410_dm9000_resource),
+       .resource       = anw6410_dm9000_resource,
+       .dev    = {
+               .platform_data  = &anw6410_dm9000_pdata,
+       },
+};
+
+static struct map_desc anw6410_iodesc[] __initdata = {
+       {
+               .virtual        = (unsigned long)ANW6410_VA_EXTDEV,
+               .pfn            = __phys_to_pfn(ANW6410_PA_EXTDEV),
+               .length         = SZ_64K,
+               .type           = MT_DEVICE,
+       },
+};
+
+static struct platform_device *anw6410_devices[] __initdata = {
+       &s3c_device_fb,
+       &anw6410_lcd_powerdev,
+       &anw6410_device_eth,
+};
+
+static void __init anw6410_map_io(void)
+{
+       s3c64xx_init_io(anw6410_iodesc, ARRAY_SIZE(anw6410_iodesc));
+       s3c24xx_init_clocks(12000000);
+       s3c24xx_init_uarts(anw6410_uartcfgs, ARRAY_SIZE(anw6410_uartcfgs));
+
+       anw6410_lcd_mode_set();
+}
+
+static void __init anw6410_machine_init(void)
+{
+       s3c_fb_set_platdata(&anw6410_lcd_pdata);
+
+       gpio_request(S3C64XX_GPF(1), "panel power");
+       gpio_request(S3C64XX_GPF(4), "LCD backlight");
+
+       anw6410_dm9000_enable();
+
+       platform_add_devices(anw6410_devices, ARRAY_SIZE(anw6410_devices));
+}
+
+MACHINE_START(ANW6410, "A&W6410")
+       /* Maintainer: Kwangwoo Lee <kwangwoo.lee@gmail.com> */
+       .phys_io        = S3C_PA_UART & 0xfff00000,
+       .io_pg_offst    = (((u32)S3C_VA_UART) >> 18) & 0xfffc,
+       .boot_params    = S3C64XX_PA_SDRAM + 0x100,
+
+       .init_irq       = s3c6410_init_irq,
+       .map_io         = anw6410_map_io,
+       .init_machine   = anw6410_machine_init,
+       .timer          = &s3c24xx_timer,
+MACHINE_END
diff --git a/arch/arm/mach-s3c6410/mach-ncp.c b/arch/arm/mach-s3c6410/mach-ncp.c
new file mode 100644 (file)
index 0000000..6030636
--- /dev/null
@@ -0,0 +1,107 @@
+/*
+ * linux/arch/arm/mach-s3c6410/mach-ncp.c
+ *
+ * Copyright (C) 2008-2009 Samsung Electronics
+ *
+ * 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/interrupt.h>
+#include <linux/list.h>
+#include <linux/timer.h>
+#include <linux/init.h>
+#include <linux/serial_core.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/i2c.h>
+#include <linux/fb.h>
+#include <linux/gpio.h>
+#include <linux/delay.h>
+
+#include <video/platform_lcd.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <mach/hardware.h>
+#include <mach/regs-fb.h>
+#include <mach/map.h>
+
+#include <asm/irq.h>
+#include <asm/mach-types.h>
+
+#include <plat/regs-serial.h>
+#include <plat/iic.h>
+#include <plat/fb.h>
+
+#include <plat/s3c6410.h>
+#include <plat/clock.h>
+#include <plat/devs.h>
+#include <plat/cpu.h>
+
+#define UCON S3C2410_UCON_DEFAULT
+#define ULCON S3C2410_LCON_CS8 | S3C2410_LCON_PNONE
+#define UFCON S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE
+
+static struct s3c2410_uartcfg ncp_uartcfgs[] __initdata = {
+       /* REVISIT: NCP uses only serial 1, 2 */
+       [0] = {
+               .hwport      = 0,
+               .flags       = 0,
+               .ucon        = UCON,
+               .ulcon       = ULCON,
+               .ufcon       = UFCON,
+       },
+       [1] = {
+               .hwport      = 1,
+               .flags       = 0,
+               .ucon        = UCON,
+               .ulcon       = ULCON,
+               .ufcon       = UFCON,
+       },
+       [2] = {
+               .hwport      = 2,
+               .flags       = 0,
+               .ucon        = UCON,
+               .ulcon       = ULCON,
+               .ufcon       = UFCON,
+       },
+};
+
+static struct platform_device *ncp_devices[] __initdata = {
+       &s3c_device_hsmmc1,
+       &s3c_device_i2c0,
+};
+
+struct map_desc ncp_iodesc[] = {};
+
+static void __init ncp_map_io(void)
+{
+       s3c64xx_init_io(ncp_iodesc, ARRAY_SIZE(ncp_iodesc));
+       s3c24xx_init_clocks(12000000);
+       s3c24xx_init_uarts(ncp_uartcfgs, ARRAY_SIZE(ncp_uartcfgs));
+}
+
+static void __init ncp_machine_init(void)
+{
+       s3c_i2c0_set_platdata(NULL);
+
+       platform_add_devices(ncp_devices, ARRAY_SIZE(ncp_devices));
+}
+
+MACHINE_START(NCP, "NCP")
+       /* Maintainer: Samsung Electronics */
+       .phys_io        = S3C_PA_UART & 0xfff00000,
+       .io_pg_offst    = (((u32)S3C_VA_UART) >> 18) & 0xfffc,
+       .boot_params    = S3C64XX_PA_SDRAM + 0x100,
+       .init_irq       = s3c6410_init_irq,
+       .map_io         = ncp_map_io,
+       .init_machine   = ncp_machine_init,
+       .timer          = &s3c24xx_timer,
+MACHINE_END
index 7f473e4..bc9a7de 100644 (file)
 #include <linux/fb.h>
 #include <linux/gpio.h>
 #include <linux/delay.h>
+#include <linux/smsc911x.h>
+
+#ifdef CONFIG_SMDK6410_WM1190_EV1
+#include <linux/mfd/wm8350/core.h>
+#include <linux/mfd/wm8350/pmic.h>
+#endif
 
 #include <video/platform_lcd.h>
 
 #include <asm/mach-types.h>
 
 #include <plat/regs-serial.h>
+#include <plat/regs-modem.h>
+#include <plat/regs-gpio.h>
+#include <plat/regs-sys.h>
 #include <plat/iic.h>
 #include <plat/fb.h>
+#include <plat/gpio-cfg.h>
 
 #include <plat/s3c6410.h>
 #include <plat/clock.h>
@@ -129,6 +139,37 @@ static struct s3c_fb_platdata smdk6410_lcd_pdata __initdata = {
        .vidcon1        = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC,
 };
 
+static struct resource smdk6410_smsc911x_resources[] = {
+       [0] = {
+               .start = 0x18000000,
+               .end   = 0x18000000 + SZ_64K - 1,
+               .flags = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start = S3C_EINT(10),
+               .end   = S3C_EINT(10),
+               .flags = IORESOURCE_IRQ | IRQ_TYPE_LEVEL_LOW,
+       },
+};
+
+static struct smsc911x_platform_config smdk6410_smsc911x_pdata = {
+       .irq_polarity  = SMSC911X_IRQ_POLARITY_ACTIVE_LOW,
+       .irq_type      = SMSC911X_IRQ_TYPE_OPEN_DRAIN,
+       .flags         = SMSC911X_USE_32BIT | SMSC911X_FORCE_INTERNAL_PHY,
+       .phy_interface = PHY_INTERFACE_MODE_MII,
+};
+
+
+static struct platform_device smdk6410_smsc911x = {
+       .name          = "smsc911x",
+       .id            = -1,
+       .num_resources = ARRAY_SIZE(smdk6410_smsc911x_resources),
+       .resource      = &smdk6410_smsc911x_resources[0],
+       .dev = {
+               .platform_data = &smdk6410_smsc911x_pdata,
+       },
+};
+
 static struct map_desc smdk6410_iodesc[] = {};
 
 static struct platform_device *smdk6410_devices[] __initdata = {
@@ -141,12 +182,155 @@ static struct platform_device *smdk6410_devices[] __initdata = {
        &s3c_device_i2c0,
        &s3c_device_i2c1,
        &s3c_device_fb,
+       &s3c_device_usb,
+       &s3c_device_usb_hsotg,
        &smdk6410_lcd_powerdev,
+
+       &smdk6410_smsc911x,
+};
+
+#ifdef CONFIG_SMDK6410_WM1190_EV1
+/* S3C64xx internal logic & PLL */
+static struct regulator_init_data wm8350_dcdc1_data = {
+       .constraints = {
+               .name = "PVDD_INT/PVDD_PLL",
+               .min_uV = 1200000,
+               .max_uV = 1200000,
+               .always_on = 1,
+               .apply_uV = 1,
+       },
+};
+
+/* Memory */
+static struct regulator_init_data wm8350_dcdc3_data = {
+       .constraints = {
+               .name = "PVDD_MEM",
+               .min_uV = 1800000,
+               .max_uV = 1800000,
+               .always_on = 1,
+               .state_mem = {
+                        .uV = 1800000,
+                        .mode = REGULATOR_MODE_NORMAL,
+                        .enabled = 1,
+                },
+               .initial_state = PM_SUSPEND_MEM,
+       },
+};
+
+/* USB, EXT, PCM, ADC/DAC, USB, MMC */
+static struct regulator_init_data wm8350_dcdc4_data = {
+       .constraints = {
+               .name = "PVDD_HI/PVDD_EXT/PVDD_SYS/PVCCM2MTV",
+               .min_uV = 3000000,
+               .max_uV = 3000000,
+               .always_on = 1,
+       },
+};
+
+/* ARM core */
+static struct regulator_consumer_supply dcdc6_consumers[] = {
+       {
+               .supply = "vddarm",
+       }
+};
+
+static struct regulator_init_data wm8350_dcdc6_data = {
+       .constraints = {
+               .name = "PVDD_ARM",
+               .min_uV = 1000000,
+               .max_uV = 1300000,
+               .always_on = 1,
+               .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+       },
+       .num_consumer_supplies = ARRAY_SIZE(dcdc6_consumers),
+       .consumer_supplies = dcdc6_consumers,
 };
 
+/* Alive */
+static struct regulator_init_data wm8350_ldo1_data = {
+       .constraints = {
+               .name = "PVDD_ALIVE",
+               .min_uV = 1200000,
+               .max_uV = 1200000,
+               .always_on = 1,
+               .apply_uV = 1,
+       },
+};
+
+/* OTG */
+static struct regulator_init_data wm8350_ldo2_data = {
+       .constraints = {
+               .name = "PVDD_OTG",
+               .min_uV = 3300000,
+               .max_uV = 3300000,
+               .always_on = 1,
+       },
+};
+
+/* LCD */
+static struct regulator_init_data wm8350_ldo3_data = {
+       .constraints = {
+               .name = "PVDD_LCD",
+               .min_uV = 3000000,
+               .max_uV = 3000000,
+               .always_on = 1,
+       },
+};
+
+/* OTGi/1190-EV1 HPVDD & AVDD */
+static struct regulator_init_data wm8350_ldo4_data = {
+       .constraints = {
+               .name = "PVDD_OTGI/HPVDD/AVDD",
+               .min_uV = 1200000,
+               .max_uV = 1200000,
+               .apply_uV = 1,
+               .always_on = 1,
+       },
+};
+
+static struct {
+       int regulator;
+       struct regulator_init_data *initdata;
+} wm1190_regulators[] = {
+       { WM8350_DCDC_1, &wm8350_dcdc1_data },
+       { WM8350_DCDC_3, &wm8350_dcdc3_data },
+       { WM8350_DCDC_4, &wm8350_dcdc4_data },
+       { WM8350_DCDC_6, &wm8350_dcdc6_data },
+       { WM8350_LDO_1, &wm8350_ldo1_data },
+       { WM8350_LDO_2, &wm8350_ldo2_data },
+       { WM8350_LDO_3, &wm8350_ldo3_data },
+       { WM8350_LDO_4, &wm8350_ldo4_data },
+};
+
+static int __init smdk6410_wm8350_init(struct wm8350 *wm8350)
+{
+       int i;
+
+       /* Instantiate the regulators */
+       for (i = 0; i < ARRAY_SIZE(wm1190_regulators); i++)
+               wm8350_register_regulator(wm8350,
+                                         wm1190_regulators[i].regulator,
+                                         wm1190_regulators[i].initdata);
+
+       return 0;
+}
+
+static struct wm8350_platform_data __initdata smdk6410_wm8350_pdata = {
+       .init = smdk6410_wm8350_init,
+       .irq_high = 1,
+};
+#endif
+
 static struct i2c_board_info i2c_devs0[] __initdata = {
        { I2C_BOARD_INFO("24c08", 0x50), },
        { I2C_BOARD_INFO("wm8580", 0x1b), },
+
+#ifdef CONFIG_SMDK6410_WM1190_EV1
+       { I2C_BOARD_INFO("wm8350", 0x1a),
+         .platform_data = &smdk6410_wm8350_pdata,
+         .irq = S3C_EINT(12),
+       },
+#endif
 };
 
 static struct i2c_board_info i2c_devs1[] __initdata = {
@@ -155,9 +339,23 @@ static struct i2c_board_info i2c_devs1[] __initdata = {
 
 static void __init smdk6410_map_io(void)
 {
+       u32 tmp;
+
        s3c64xx_init_io(smdk6410_iodesc, ARRAY_SIZE(smdk6410_iodesc));
        s3c24xx_init_clocks(12000000);
        s3c24xx_init_uarts(smdk6410_uartcfgs, ARRAY_SIZE(smdk6410_uartcfgs));
+
+       /* set the LCD type */
+
+       tmp = __raw_readl(S3C64XX_SPCON);
+       tmp &= ~S3C64XX_SPCON_LCD_SEL_MASK;
+       tmp |= S3C64XX_SPCON_LCD_SEL_RGB;
+       __raw_writel(tmp, S3C64XX_SPCON);
+
+       /* remove the lcd bypass */
+       tmp = __raw_readl(S3C64XX_MODEM_MIFPCON);
+       tmp &= ~MIFPCON_LCD_BYPASS;
+       __raw_writel(tmp, S3C64XX_MODEM_MIFPCON);
 }
 
 static void __init smdk6410_machine_init(void)
index 0b5788b..20666f3 100644 (file)
@@ -21,8 +21,6 @@
 #include <linux/mmc/card.h>
 #include <linux/mmc/host.h>
 
-#include <mach/gpio.h>
-#include <plat/gpio-cfg.h>
 #include <plat/regs-sdhci.h>
 #include <plat/sdhci.h>
 
@@ -35,22 +33,6 @@ char *s3c6410_hsmmc_clksrcs[4] = {
        /* [3] = "48m", - note not succesfully used yet */
 };
 
-void s3c6410_setup_sdhci0_cfg_gpio(struct platform_device *dev, int width)
-{
-       unsigned int gpio;
-       unsigned int end;
-
-       end = S3C64XX_GPG(2 + width);
-
-       /* Set all the necessary GPG pins to special-function 0 */
-       for (gpio = S3C64XX_GPG(0); gpio < end; gpio++) {
-               s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2));
-               s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
-       }
-
-       s3c_gpio_setpull(S3C64XX_GPG(6), S3C_GPIO_PULL_UP);
-       s3c_gpio_cfgpin(S3C64XX_GPG(6), S3C_GPIO_SFN(2));
-}
 
 void s3c6410_setup_sdhci0_cfg_card(struct platform_device *dev,
                                    void __iomem *r,
@@ -84,19 +66,3 @@ void s3c6410_setup_sdhci0_cfg_card(struct platform_device *dev,
        writel(ctrl3, r + S3C_SDHCI_CONTROL3);
 }
 
-void s3c6410_setup_sdhci1_cfg_gpio(struct platform_device *dev, int width)
-{
-       unsigned int gpio;
-       unsigned int end;
-
-       end = S3C64XX_GPH(2 + width);
-
-       /* Set all the necessary GPG pins to special-function 0 */
-       for (gpio = S3C64XX_GPH(0); gpio < end; gpio++) {
-               s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2));
-               s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
-       }
-
-       s3c_gpio_setpull(S3C64XX_GPG(6), S3C_GPIO_PULL_UP);
-       s3c_gpio_cfgpin(S3C64XX_GPG(6), S3C_GPIO_SFN(3));
-}
index 1f929c3..c39c788 100644 (file)
@@ -116,7 +116,7 @@ void __init versatile_init_irq(void)
 {
        unsigned int i;
 
-       vic_init(VA_VIC_BASE, IRQ_VIC_START, ~0);
+       vic_init(VA_VIC_BASE, IRQ_VIC_START, ~0, 0);
 
        set_irq_chained_handler(IRQ_VICSOURCE31, sic_handle_irq);
 
index d4fc89f..935c755 100644 (file)
@@ -71,6 +71,15 @@ config S3C2410_PM_DEBUG
          Resume code. See <file:Documentation/arm/Samsung-S3C24XX/Suspend.txt>
          for more information.
 
+config S3C_PM_DEBUG_LED_SMDK
+       bool "SMDK LED suspend/resume debugging"
+       depends on PM && (MACH_SMDK6410)
+       help
+         Say Y here to enable the use of the SMDK LEDs on the baseboard
+        for debugging of the state of the suspend and resume process.
+
+        Note, this currently only works for S3C64XX based SMDK boards.
+
 config S3C2410_PM_CHECK
        bool "S3C2410 PM Suspend Memory CRC"
        depends on PM && CRC32
@@ -179,4 +188,14 @@ config S3C_DEV_FB
        help
          Compile in platform device definition for framebuffer
 
+config S3C_DEV_USB_HOST
+       bool
+       help
+         Compile in platform device definition for USB host.
+
+config S3C_DEV_USB_HSOTG
+       bool
+       help
+         Compile in platform device definition for USB high-speed OtG
+
 endif
index e8b23fc..6106514 100644 (file)
@@ -25,6 +25,7 @@ obj-$(CONFIG_S3C_DMA)         += dma.o
 # PM support
 
 obj-$(CONFIG_PM)               += pm.o
+obj-$(CONFIG_PM)               += pm-gpio.o
 obj-$(CONFIG_S3C2410_PM_CHECK) += pm-check.o
 
 # devices
@@ -34,3 +35,5 @@ obj-$(CONFIG_S3C_DEV_HSMMC1)  += dev-hsmmc1.o
 obj-y                          += dev-i2c0.o
 obj-$(CONFIG_S3C_DEV_I2C1)     += dev-i2c1.o
 obj-$(CONFIG_S3C_DEV_FB)       += dev-fb.o
+obj-$(CONFIG_S3C_DEV_USB_HOST) += dev-usb.o
+obj-$(CONFIG_S3C_DEV_USB_HSOTG)        += dev-usb-hsotg.o
diff --git a/arch/arm/plat-s3c/dev-usb-hsotg.c b/arch/arm/plat-s3c/dev-usb-hsotg.c
new file mode 100644 (file)
index 0000000..e2f604b
--- /dev/null
@@ -0,0 +1,41 @@
+/* linux/arch/arm/plat-s3c/dev-usb-hsotg.c
+ *
+ * Copyright 2008 Simtec Electronics
+ *     Ben Dooks <ben@simtec.co.uk>
+ *     http://armlinux.simtec.co.uk/
+ *
+ * S3C series device definition for USB high-speed UDC/OtG block
+ *
+ * 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/string.h>
+#include <linux/platform_device.h>
+
+#include <mach/irqs.h>
+#include <mach/map.h>
+
+#include <plat/devs.h>
+
+static struct resource s3c_usb_hsotg_resources[] = {
+       [0] = {
+               .start  = S3C_PA_USB_HSOTG,
+               .end    = S3C_PA_USB_HSOTG + 0x10000 - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = IRQ_OTG,
+               .end    = IRQ_OTG,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+struct platform_device s3c_device_usb_hsotg = {
+       .name           = "s3c-hsotg",
+       .id             = -1,
+       .num_resources  = ARRAY_SIZE(s3c_usb_hsotg_resources),
+       .resource       = s3c_usb_hsotg_resources,
+};
diff --git a/arch/arm/plat-s3c/dev-usb.c b/arch/arm/plat-s3c/dev-usb.c
new file mode 100644 (file)
index 0000000..2ee85ab
--- /dev/null
@@ -0,0 +1,50 @@
+/* linux/arch/arm/plat-s3c/dev-usb.c
+ *
+ * Copyright 2008 Simtec Electronics
+ *     Ben Dooks <ben@simtec.co.uk>
+ *     http://armlinux.simtec.co.uk/
+ *
+ * S3C series device definition for USB host
+ *
+ * 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/string.h>
+#include <linux/platform_device.h>
+
+#include <mach/irqs.h>
+#include <mach/map.h>
+
+#include <plat/devs.h>
+
+
+static struct resource s3c_usb_resource[] = {
+       [0] = {
+               .start = S3C_PA_USBHOST,
+               .end   = S3C_PA_USBHOST + 0x100 - 1,
+               .flags = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start = IRQ_USBH,
+               .end   = IRQ_USBH,
+               .flags = IORESOURCE_IRQ,
+       }
+};
+
+static u64 s3c_device_usb_dmamask = 0xffffffffUL;
+
+struct platform_device s3c_device_usb = {
+       .name             = "s3c2410-ohci",
+       .id               = -1,
+       .num_resources    = ARRAY_SIZE(s3c_usb_resource),
+       .resource         = s3c_usb_resource,
+       .dev              = {
+               .dma_mask = &s3c_device_usb_dmamask,
+               .coherent_dma_mask = 0xffffffffUL
+       }
+};
+
+EXPORT_SYMBOL(s3c_device_usb);
index d71dd6d..260fdc6 100644 (file)
@@ -16,7 +16,7 @@
 #include <linux/io.h>
 #include <linux/gpio.h>
 
-#include <plat/gpio-core.h>
+#include <mach/gpio-core.h>
 
 #ifdef CONFIG_S3C_GPIO_TRACK
 struct s3c_gpio_chip *s3c_gpios[S3C_GPIO_END];
@@ -140,6 +140,15 @@ __init void s3c_gpiolib_add(struct s3c_gpio_chip *chip)
        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)
index 43df2a4..d847bd4 100644 (file)
@@ -19,10 +19,12 @@ struct s3c_adc_client;
 extern int s3c_adc_start(struct s3c_adc_client *client,
                         unsigned int channel, unsigned int nr_samples);
 
-extern struct s3c_adc_client *s3c_adc_register(struct platform_device *pdev,
-                                              void (*select)(unsigned selected),
-                                              void (*conv)(unsigned d0, unsigned d1),
-                                              unsigned int is_ts);
+extern struct s3c_adc_client *
+       s3c_adc_register(struct platform_device *pdev,
+                        void (*select)(unsigned selected),
+                        void (*conv)(unsigned d0, unsigned d1,
+                                     unsigned *samples_left),
+                        unsigned int is_ts);
 
 extern void s3c_adc_release(struct s3c_adc_client *client);
 
index a10622e..d86af84 100644 (file)
@@ -50,6 +50,7 @@ extern struct clk clk_xtal;
 extern struct clk clk_ext;
 
 /* S3C64XX specific clocks */
+extern struct clk clk_h2;
 extern struct clk clk_27m;
 extern struct clk clk_48m;
 
index e62ae0f..be541cb 100644 (file)
@@ -69,3 +69,6 @@ extern struct sysdev_class s3c2412_sysclass;
 extern struct sysdev_class s3c2440_sysclass;
 extern struct sysdev_class s3c2442_sysclass;
 extern struct sysdev_class s3c2443_sysclass;
+extern struct sysdev_class s3c6410_sysclass;
+extern struct sysdev_class s3c64xx_sysclass;
+
index 26f0cec..a0b6768 100644 (file)
@@ -45,6 +45,7 @@ extern struct platform_device s3c_device_spi1;
 extern struct platform_device s3c_device_nand;
 
 extern struct platform_device s3c_device_usbgadget;
+extern struct platform_device s3c_device_usb_hsotg;
 
 /* s3c2440 specific devices */
 
index 2fc60a5..32af612 100644 (file)
  * specific code.
 */
 
+struct s3c_gpio_chip;
+
+/**
+ * struct s3c_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 s3c_gpio_cfg;
 
 /**
@@ -27,6 +39,7 @@ struct s3c_gpio_cfg;
  * @chip: The chip structure to be exported via gpiolib.
  * @base: The base pointer to the gpio configuration registers.
  * @config: special function and pull-resistor control information.
+ * @pm_save: Save information for suspend/resume support.
  *
  * This wrapper provides the necessary information for the Samsung
  * specific gpios being registered with gpiolib.
@@ -34,7 +47,11 @@ struct s3c_gpio_cfg;
 struct s3c_gpio_chip {
        struct gpio_chip        chip;
        struct s3c_gpio_cfg     *config;
+       struct s3c_gpio_pm      *pm;
        void __iomem            *base;
+#ifdef CONFIG_PM
+       u32                     pm_save[4];
+#endif
 };
 
 static inline struct s3c_gpio_chip *to_s3c_gpio(struct gpio_chip *gpc)
@@ -75,3 +92,16 @@ static inline struct s3c_gpio_chip *s3c_gpiolib_getchip(unsigned int chip)
 
 static inline void s3c_gpiolib_track(struct s3c_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;
+#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 __gpio_pm(x) NULL
+
+#endif /* CONFIG_PM */
index 3779775..7a79719 100644 (file)
@@ -44,6 +44,8 @@ extern void (*pm_cpu_sleep)(void);
 
 extern unsigned long s3c_pm_flags;
 
+extern unsigned char pm_uart_udivslot;  /* true to save UART UDIVSLOT */
+
 /* from sleep.S */
 
 extern int  s3c_cpu_save(unsigned long *saveblk);
@@ -88,6 +90,7 @@ struct pm_uart_save {
        u32     ufcon;
        u32     umcon;
        u32     ubrdiv;
+       u32     udivslot;
 };
 
 /* helper functions to save/restore lists of registers. */
@@ -124,6 +127,18 @@ extern void s3c_pm_dbg(const char *msg, ...);
 #define S3C_PMDBG(fmt...) printk(KERN_DEBUG fmt)
 #endif
 
+#ifdef CONFIG_S3C_PM_DEBUG_LED_SMDK
+/**
+ * s3c_pm_debug_smdkled() - Debug PM suspend/resume via SMDK Board LEDs
+ * @set: set bits for the state of the LEDs
+ * @clear: clear bits for the state of the LEDs.
+ */
+extern void s3c_pm_debug_smdkled(u32 set, u32 clear);
+
+#else
+static inline void s3c_pm_debug_smdkled(u32 set, u32 clear) { }
+#endif /* CONFIG_S3C_PM_DEBUG_LED_SMDK */
+
 /* suspend memory checking */
 
 #ifdef CONFIG_S3C2410_PM_CHECK
index 487d7d2..66af75a 100644 (file)
 
 #define S3C2443_DIVSLOT                  (0x2C)
 
+/* S3C64XX interrupt registers. */
+#define S3C64XX_UINTP          0x30
+#define S3C64XX_UINTSP         0x34
+#define S3C64XX_UINTM          0x38
+
 #ifndef __ASSEMBLY__
 
 /* struct s3c24xx_uart_clksrc
index c4ca392..f615308 100644 (file)
@@ -67,12 +67,52 @@ extern struct s3c_sdhci_platdata s3c_hsmmc1_def_platdata;
 
 /* Helper function availablity */
 
+extern void s3c64xx_setup_sdhci0_cfg_gpio(struct platform_device *, int w);
+extern void s3c64xx_setup_sdhci1_cfg_gpio(struct platform_device *, int w);
+
+/* S3C6400 SDHCI setup */
+
+#ifdef CONFIG_S3C6400_SETUP_SDHCI
+extern char *s3c6400_hsmmc_clksrcs[4];
+
+#ifdef CONFIG_S3C_DEV_HSMMC
+extern void s3c6400_setup_sdhci_cfg_card(struct platform_device *dev,
+                                        void __iomem *r,
+                                        struct mmc_ios *ios,
+                                        struct mmc_card *card);
+
+static inline void s3c6400_default_sdhci0(void)
+{
+       s3c_hsmmc0_def_platdata.clocks = s3c6400_hsmmc_clksrcs;
+       s3c_hsmmc0_def_platdata.cfg_gpio = s3c64xx_setup_sdhci0_cfg_gpio;
+       s3c_hsmmc0_def_platdata.cfg_card = s3c6400_setup_sdhci_cfg_card;
+}
+
+#else
+static inline void s3c6400_default_sdhci0(void) { }
+#endif  /* CONFIG_S3C_DEV_HSMMC */
+
+#ifdef CONFIG_S3C_DEV_HSMMC1
+static inline void s3c6400_default_sdhci1(void)
+{
+       s3c_hsmmc1_def_platdata.clocks = s3c6400_hsmmc_clksrcs;
+       s3c_hsmmc1_def_platdata.cfg_gpio = s3c64xx_setup_sdhci1_cfg_gpio;
+       s3c_hsmmc1_def_platdata.cfg_card = s3c6400_setup_sdhci_cfg_card;
+}
+#else
+static inline void s3c6400_default_sdhci1(void) { }
+#endif /* CONFIG_S3C_DEV_HSMMC1 */
+
+#else
+static inline void s3c6400_default_sdhci0(void) { }
+static inline void s3c6400_default_sdhci1(void) { }
+#endif /* CONFIG_S3C6400_SETUP_SDHCI */
+
+/* S3C6410 SDHCI setup */
+
 #ifdef CONFIG_S3C6410_SETUP_SDHCI
 extern char *s3c6410_hsmmc_clksrcs[4];
 
-extern void s3c6410_setup_sdhci0_cfg_gpio(struct platform_device *, int w);
-extern void s3c6410_setup_sdhci1_cfg_gpio(struct platform_device *, int w);
-
 extern void s3c6410_setup_sdhci0_cfg_card(struct platform_device *dev,
                                           void __iomem *r,
                                           struct mmc_ios *ios,
@@ -82,7 +122,7 @@ extern void s3c6410_setup_sdhci0_cfg_card(struct platform_device *dev,
 static inline void s3c6410_default_sdhci0(void)
 {
        s3c_hsmmc0_def_platdata.clocks = s3c6410_hsmmc_clksrcs;
-       s3c_hsmmc0_def_platdata.cfg_gpio = s3c6410_setup_sdhci0_cfg_gpio;
+       s3c_hsmmc0_def_platdata.cfg_gpio = s3c64xx_setup_sdhci0_cfg_gpio;
        s3c_hsmmc0_def_platdata.cfg_card = s3c6410_setup_sdhci0_cfg_card;
 }
 #else
@@ -93,7 +133,7 @@ static inline void s3c6410_default_sdhci0(void) { }
 static inline void s3c6410_default_sdhci1(void)
 {
        s3c_hsmmc1_def_platdata.clocks = s3c6410_hsmmc_clksrcs;
-       s3c_hsmmc1_def_platdata.cfg_gpio = s3c6410_setup_sdhci1_cfg_gpio;
+       s3c_hsmmc1_def_platdata.cfg_gpio = s3c64xx_setup_sdhci1_cfg_gpio;
        s3c_hsmmc1_def_platdata.cfg_card = s3c6410_setup_sdhci0_cfg_card;
 }
 #else
diff --git a/arch/arm/plat-s3c/include/plat/udc-hs.h b/arch/arm/plat-s3c/include/plat/udc-hs.h
new file mode 100644 (file)
index 0000000..dd04db0
--- /dev/null
@@ -0,0 +1,29 @@
+/* arch/arm/plat-s3c/include/plat/udc-hs.h
+ *
+ * Copyright 2008 Openmoko, Inc.
+ * Copyright 2008 Simtec Electronics
+ *      Ben Dooks <ben@simtec.co.uk>
+ *      http://armlinux.simtec.co.uk/
+ *
+ * S3C USB2.0 High-speed / OtG platform information
+ *
+ * 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.
+*/
+
+enum s3c_hostg_dmamode {
+       S3C_HSOTG_DMA_NONE,     /* do not use DMA at-all */
+       S3C_HSOTG_DMA_ONLY,     /* always use DMA */
+       S3C_HSOTG_DMA_DRV,      /* DMA is chosen by driver */
+};
+
+/**
+ * struct s3c_hsotg_plat - platform data for high-speed otg/udc
+ * @dma: Whether to use DMA or not.
+ * @is_osc: The clock source is an oscillator, not a crystal
+ */
+struct s3c_hsotg_plat {
+       enum s3c_hostg_dmamode  dma;
+       unsigned int            is_osc : 1;
+};
diff --git a/arch/arm/plat-s3c/include/plat/watchdog-reset.h b/arch/arm/plat-s3c/include/plat/watchdog-reset.h
new file mode 100644 (file)
index 0000000..54b762a
--- /dev/null
@@ -0,0 +1,49 @@
+/* arch/arm/plat-s3c/include/plat/watchdog-reset.h
+ *
+ * Copyright (c) 2008 Simtec Electronics
+ *     Ben Dooks <ben@simtec.co.uk>
+ *
+ * S3C2410 - System define for arch_reset() function
+ *
+ * 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 <plat/regs-watchdog.h>
+#include <mach/map.h>
+
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/io.h>
+
+static inline void arch_wdt_reset(void)
+{
+       struct clk *wdtclk;
+
+       printk("arch_reset: attempting watchdog reset\n");
+
+       __raw_writel(0, S3C2410_WTCON);   /* disable watchdog, to be safe  */
+
+       wdtclk = clk_get(NULL, "watchdog");
+       if (!IS_ERR(wdtclk)) {
+               clk_enable(wdtclk);
+       } else
+               printk(KERN_WARNING "%s: warning: cannot get watchdog clock\n", __func__);
+
+       /* put initial values into count and data */
+       __raw_writel(0x80, S3C2410_WTCNT);
+       __raw_writel(0x80, S3C2410_WTDAT);
+
+       /* set the watchdog to go and reset... */
+       __raw_writel(S3C2410_WTCON_ENABLE|S3C2410_WTCON_DIV16|S3C2410_WTCON_RSTEN |
+                    S3C2410_WTCON_PRESCALE(0x20), S3C2410_WTCON);
+
+       /* wait for reset to assert... */
+       mdelay(500);
+
+       printk(KERN_ERR "Watchdog reset failed to assert reset\n");
+
+       /* delay to allow the serial port to show the message */
+       mdelay(50);
+}
diff --git a/arch/arm/plat-s3c/pm-gpio.c b/arch/arm/plat-s3c/pm-gpio.c
new file mode 100644 (file)
index 0000000..cfd326a
--- /dev/null
@@ -0,0 +1,380 @@
+
+/* linux/arch/arm/plat-s3c/pm-gpio.c
+ *
+ * Copyright 2008 Openmoko, Inc.
+ * Copyright 2008 Simtec Electronics
+ *     Ben Dooks <ben@simtec.co.uk>
+ *     http://armlinux.simtec.co.uk/
+ *
+ * S3C series GPIO PM code
+ *
+ * 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/sysdev.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/gpio.h>
+
+#include <mach/gpio-core.h>
+#include <plat/pm.h>
+
+/* PM GPIO helpers */
+
+#define OFFS_CON       (0x00)
+#define OFFS_DAT       (0x04)
+#define OFFS_UP                (0x08)
+
+static void s3c_gpio_pm_1bit_save(struct s3c_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)
+{
+       void __iomem *base = chip->base;
+       u32 old_gpcon = __raw_readl(base + OFFS_CON);
+       u32 old_gpdat = __raw_readl(base + OFFS_DAT);
+       u32 gps_gpcon = chip->pm_save[0];
+       u32 gps_gpdat = chip->pm_save[1];
+       u32 gpcon;
+
+       /* GPACON only has one bit per control / data and no PULLUPs.
+        * GPACON[x] = 0 => Output, 1 => SFN */
+
+       /* first set all SFN bits to SFN */
+
+       gpcon = old_gpcon | gps_gpcon;
+       __raw_writel(gpcon, base + OFFS_CON);
+
+       /* now set all the other bits */
+
+       __raw_writel(gps_gpdat, base + OFFS_DAT);
+       __raw_writel(gps_gpcon, base + OFFS_CON);
+
+       S3C_PMDBG("%s: CON %08x => %08x, DAT %08x => %08x\n",
+                 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,
+};
+
+static void s3c_gpio_pm_2bit_save(struct s3c_gpio_chip *chip)
+{
+       chip->pm_save[0] = __raw_readl(chip->base + OFFS_CON);
+       chip->pm_save[1] = __raw_readl(chip->base + OFFS_DAT);
+       chip->pm_save[2] = __raw_readl(chip->base + OFFS_UP);
+}
+
+/* Test whether the given masked+shifted bits of an GPIO configuration
+ * are one of the SFN (special function) modes. */
+
+static inline int is_sfn(unsigned long con)
+{
+       return con >= 2;
+}
+
+/* Test if the given masked+shifted GPIO configuration is an input */
+
+static inline int is_in(unsigned long con)
+{
+       return con == 0;
+}
+
+/* Test if the given masked+shifted GPIO configuration is an output */
+
+static inline int is_out(unsigned long con)
+{
+       return con == 1;
+}
+
+/**
+ * s3c_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
+ * not as simple as once thought, due to the possibility of glitches
+ * from the order that the CON and DAT registers are set in.
+ *
+ * The three states the pin can be are {IN,OUT,SFN} which gives us 9
+ * combinations of changes to check. Three of these, if the pin stays
+ * in the same configuration can be discounted. This leaves us with
+ * the following:
+ *
+ * { IN => OUT }  Change DAT first
+ * { IN => SFN }  Change CON first
+ * { OUT => SFN } Change CON first, so new data will not glitch
+ * { OUT => IN }  Change CON first, so new data will not glitch
+ * { SFN => IN }  Change CON first
+ * { SFN => OUT } Change DAT first, so new data will not glitch [1]
+ *
+ * We do not currently deal with the UP registers as these control
+ * weak resistors, so a small delay in change should not need to bring
+ * these into the calculations.
+ *
+ * [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)
+{
+       void __iomem *base = chip->base;
+       u32 old_gpcon = __raw_readl(base + OFFS_CON);
+       u32 old_gpdat = __raw_readl(base + OFFS_DAT);
+       u32 gps_gpcon = chip->pm_save[0];
+       u32 gps_gpdat = chip->pm_save[1];
+       u32 gpcon, old, new, mask;
+       u32 change_mask = 0x0;
+       int nr;
+
+       /* restore GPIO pull-up settings */
+       __raw_writel(chip->pm_save[2], base + OFFS_UP);
+
+       /* Create a change_mask of all the items that need to have
+        * their CON value changed before their DAT value, so that
+        * we minimise the work between the two settings.
+        */
+
+       for (nr = 0, mask = 0x03; nr < 32; nr += 2, mask <<= 2) {
+               old = (old_gpcon & mask) >> nr;
+               new = (gps_gpcon & mask) >> nr;
+
+               /* If there is no change, then skip */
+
+               if (old == new)
+                       continue;
+
+               /* If both are special function, then skip */
+
+               if (is_sfn(old) && is_sfn(new))
+                       continue;
+
+               /* Change is IN => OUT, do not change now */
+
+               if (is_in(old) && is_out(new))
+                       continue;
+
+               /* Change is SFN => OUT, do not change now */
+
+               if (is_sfn(old) && is_out(new))
+                       continue;
+
+               /* We should now be at the case of IN=>SFN,
+                * OUT=>SFN, OUT=>IN, SFN=>IN. */
+
+               change_mask |= mask;
+       }
+
+
+       /* Write the new CON settings */
+
+       gpcon = old_gpcon & ~change_mask;
+       gpcon |= gps_gpcon & change_mask;
+
+       __raw_writel(gpcon, base + OFFS_CON);
+
+       /* Now change any items that require DAT,CON */
+
+       __raw_writel(gps_gpdat, base + OFFS_DAT);
+       __raw_writel(gps_gpcon, base + OFFS_CON);
+
+       S3C_PMDBG("%s: CON %08x => %08x, DAT %08x => %08x\n",
+                 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,
+};
+
+#ifdef CONFIG_ARCH_S3C64XX
+static void s3c_gpio_pm_4bit_save(struct s3c_gpio_chip *chip)
+{
+       chip->pm_save[1] = __raw_readl(chip->base + OFFS_CON);
+       chip->pm_save[2] = __raw_readl(chip->base + OFFS_DAT);
+       chip->pm_save[3] = __raw_readl(chip->base + OFFS_UP);
+
+       if (chip->chip.ngpio > 8)
+               chip->pm_save[0] = __raw_readl(chip->base - 4);
+}
+
+static u32 s3c_gpio_pm_4bit_mask(u32 old_gpcon, u32 gps_gpcon)
+{
+       u32 old, new, mask;
+       u32 change_mask = 0x0;
+       int nr;
+
+       for (nr = 0, mask = 0x0f; nr < 16; nr += 4, mask <<= 4) {
+               old = (old_gpcon & mask) >> nr;
+               new = (gps_gpcon & mask) >> nr;
+
+               /* If there is no change, then skip */
+
+               if (old == new)
+                       continue;
+
+               /* If both are special function, then skip */
+
+               if (is_sfn(old) && is_sfn(new))
+                       continue;
+
+               /* Change is IN => OUT, do not change now */
+
+               if (is_in(old) && is_out(new))
+                       continue;
+
+               /* Change is SFN => OUT, do not change now */
+
+               if (is_sfn(old) && is_out(new))
+                       continue;
+
+               /* We should now be at the case of IN=>SFN,
+                * OUT=>SFN, OUT=>IN, SFN=>IN. */
+
+               change_mask |= mask;
+       }
+
+       return change_mask;
+}
+
+static void s3c_gpio_pm_4bit_con(struct s3c_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);
+
+       gpcon = old_gpcon & ~mask;
+       gpcon |= gps_gpcon & mask;
+
+       __raw_writel(gpcon, con);
+}
+
+static void s3c_gpio_pm_4bit_resume(struct s3c_gpio_chip *chip)
+{
+       void __iomem *base = chip->base;
+       u32 old_gpcon[2];
+       u32 old_gpdat = __raw_readl(base + OFFS_DAT);
+       u32 gps_gpdat = chip->pm_save[2];
+
+       /* First, modify the CON settings */
+
+       old_gpcon[0] = 0;
+       old_gpcon[1] = __raw_readl(base + OFFS_CON);
+
+       s3c_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);
+       }
+
+       /* Now change the configurations that require DAT,CON */
+
+       __raw_writel(chip->pm_save[2], base + OFFS_DAT);
+       __raw_writel(chip->pm_save[1], base + OFFS_CON);
+       if (chip->chip.ngpio > 8)
+               __raw_writel(chip->pm_save[0], base - 4);
+
+       __raw_writel(chip->pm_save[2], base + OFFS_DAT);
+       __raw_writel(chip->pm_save[3], base + OFFS_UP);
+
+       if (chip->chip.ngpio > 8) {
+               S3C_PMDBG("%s: CON4 %08x,%08x => %08x,%08x, DAT %08x => %08x\n",
+                         chip->chip.label, old_gpcon[0], old_gpcon[1],
+                         __raw_readl(base - 4),
+                         __raw_readl(base + OFFS_CON),
+                         old_gpdat, gps_gpdat);
+       } else
+               S3C_PMDBG("%s: CON4 %08x => %08x, DAT %08x => %08x\n",
+                         chip->chip.label, old_gpcon[1],
+                         __raw_readl(base + OFFS_CON),
+                         old_gpdat, gps_gpdat);
+}
+
+struct s3c_gpio_pm s3c_gpio_pm_4bit = {
+       .save   = s3c_gpio_pm_4bit_save,
+       .resume = s3c_gpio_pm_4bit_resume,
+};
+#endif /* CONFIG_ARCH_S3C64XX */
+
+/**
+ * s3c_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)
+{
+       struct s3c_gpio_pm *pm = ourchip->pm;
+
+       if (pm == NULL || pm->save == NULL)
+               S3C_PMDBG("%s: no pm for %s\n", __func__, ourchip->chip.label);
+       else
+               pm->save(ourchip);
+}
+
+/**
+ * s3c_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)
+{
+       struct s3c_gpio_chip *ourchip;
+       unsigned int gpio_nr;
+
+       for (gpio_nr = 0; gpio_nr < S3C_GPIO_END; gpio_nr++) {
+               ourchip = s3c_gpiolib_getchip(gpio_nr);
+               if (!ourchip)
+                       continue;
+
+               s3c_pm_save_gpio(ourchip);
+
+               S3C_PMDBG("%s: save %08x,%08x,%08x,%08x\n",
+                         ourchip->chip.label,
+                         ourchip->pm_save[0],
+                         ourchip->pm_save[1],
+                         ourchip->pm_save[2],
+                         ourchip->pm_save[3]);
+
+               gpio_nr += ourchip->chip.ngpio;
+               gpio_nr += CONFIG_S3C_GPIO_SPACE;
+       }
+}
+
+/**
+ * s3c_pm_resume_gpio() - restore gpio chip data after suspend
+ * @ourchip: The suspended chip.
+ */
+static void s3c_pm_resume_gpio(struct s3c_gpio_chip *ourchip)
+{
+       struct s3c_gpio_pm *pm = ourchip->pm;
+
+       if (pm == NULL || pm->resume == NULL)
+               S3C_PMDBG("%s: no pm for %s\n", __func__, ourchip->chip.label);
+       else
+               pm->resume(ourchip);
+}
+
+void s3c_pm_restore_gpios(void)
+{
+       struct s3c_gpio_chip *ourchip;
+       unsigned int gpio_nr;
+
+       for (gpio_nr = 0; gpio_nr < S3C_GPIO_END; gpio_nr++) {
+               ourchip = s3c_gpiolib_getchip(gpio_nr);
+               if (!ourchip)
+                       continue;
+
+               s3c_pm_resume_gpio(ourchip);
+
+               gpio_nr += ourchip->chip.ngpio;
+               gpio_nr += CONFIG_S3C_GPIO_SPACE;
+       }
+}
index 061182c..8d97db2 100644 (file)
 
 #include <asm/cacheflush.h>
 #include <mach/hardware.h>
+#include <mach/map.h>
 
 #include <plat/regs-serial.h>
 #include <mach/regs-clock.h>
-#include <mach/regs-gpio.h>
-#include <mach/regs-mem.h>
 #include <mach/regs-irq.h>
 #include <asm/irq.h>
 
@@ -70,6 +69,8 @@ static inline void s3c_pm_debug_init(void)
 
 /* Save the UART configurations if we are configured for debug. */
 
+unsigned char pm_uart_udivslot;
+
 #ifdef CONFIG_S3C2410_PM_DEBUG
 
 struct pm_uart_save uart_save[CONFIG_SERIAL_SAMSUNG_UARTS];
@@ -83,6 +84,12 @@ static void s3c_pm_save_uart(unsigned int uart, struct pm_uart_save *save)
        save->ufcon = __raw_readl(regs + S3C2410_UFCON);
        save->umcon = __raw_readl(regs + S3C2410_UMCON);
        save->ubrdiv = __raw_readl(regs + S3C2410_UBRDIV);
+
+       if (pm_uart_udivslot)
+               save->udivslot = __raw_readl(regs + S3C2443_DIVSLOT);
+
+       S3C_PMDBG("UART[%d]: ULCON=%04x, UCON=%04x, UFCON=%04x, UBRDIV=%04x\n",
+                 uart, save->ulcon, save->ucon, save->ufcon, save->ubrdiv);
 }
 
 static void s3c_pm_save_uarts(void)
@@ -98,11 +105,16 @@ static void s3c_pm_restore_uart(unsigned int uart, struct pm_uart_save *save)
 {
        void __iomem *regs = S3C_VA_UARTx(uart);
 
+       s3c_pm_arch_update_uart(regs, save);
+
        __raw_writel(save->ulcon, regs + S3C2410_ULCON);
        __raw_writel(save->ucon,  regs + S3C2410_UCON);
        __raw_writel(save->ufcon, regs + S3C2410_UFCON);
        __raw_writel(save->umcon, regs + S3C2410_UMCON);
        __raw_writel(save->ubrdiv, regs + S3C2410_UBRDIV);
+
+       if (pm_uart_udivslot)
+               __raw_writel(save->udivslot, regs + S3C2443_DIVSLOT);
 }
 
 static void s3c_pm_restore_uarts(void)
@@ -313,6 +325,9 @@ static int s3c_pm_enter(suspend_state_t state)
 
        S3C_PMDBG("%s: post sleep, preparing to return\n", __func__);
 
+       /* LEDs should now be 1110 */
+       s3c_pm_debug_smdkled(1 << 1, 0);
+
        s3c_pm_check_restore();
 
        /* ok, let's return from sleep */
index 91adfa7..ee1baf1 100644 (file)
@@ -45,7 +45,8 @@ struct s3c_adc_client {
        unsigned char            channel;
 
        void    (*select_cb)(unsigned selected);
-       void    (*convert_cb)(unsigned val1, unsigned val2);
+       void    (*convert_cb)(unsigned val1, unsigned val2,
+                             unsigned *samples_left);
 };
 
 struct adc_device {
@@ -158,7 +159,8 @@ static void s3c_adc_default_select(unsigned select)
 
 struct s3c_adc_client *s3c_adc_register(struct platform_device *pdev,
                                        void (*select)(unsigned int selected),
-                                       void (*conv)(unsigned d0, unsigned d1),
+                                       void (*conv)(unsigned d0, unsigned d1,
+                                                    unsigned *samples_left),
                                        unsigned int is_ts)
 {
        struct s3c_adc_client *client;
@@ -227,9 +229,10 @@ static irqreturn_t s3c_adc_irq(int irq, void *pw)
        data1 = readl(adc->regs + S3C2410_ADCDAT1);
        adc_dbg(adc, "read %d: 0x%04x, 0x%04x\n", client->nr_samples, data0, data1);
 
-       (client->convert_cb)(data0 & 0x3ff, data1 & 0x3ff);
+       client->nr_samples--;
+       (client->convert_cb)(data0 & 0x3ff, data1 & 0x3ff, &client->nr_samples);
 
-       if (--client->nr_samples > 0) {
+       if (client->nr_samples > 0) {
                /* fire another conversion for this */
 
                client->select_cb(1);
index 16ac01d..4eb378c 100644 (file)
@@ -136,36 +136,6 @@ struct platform_device *s3c24xx_uart_src[4] = {
 struct platform_device *s3c24xx_uart_devs[4] = {
 };
 
-/* USB Host Controller */
-
-static struct resource s3c_usb_resource[] = {
-       [0] = {
-               .start = S3C24XX_PA_USBHOST,
-               .end   = S3C24XX_PA_USBHOST + S3C24XX_SZ_USBHOST - 1,
-               .flags = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start = IRQ_USBH,
-               .end   = IRQ_USBH,
-               .flags = IORESOURCE_IRQ,
-       }
-};
-
-static u64 s3c_device_usb_dmamask = 0xffffffffUL;
-
-struct platform_device s3c_device_usb = {
-       .name             = "s3c2410-ohci",
-       .id               = -1,
-       .num_resources    = ARRAY_SIZE(s3c_usb_resource),
-       .resource         = s3c_usb_resource,
-       .dev              = {
-               .dma_mask = &s3c_device_usb_dmamask,
-               .coherent_dma_mask = 0xffffffffUL
-       }
-};
-
-EXPORT_SYMBOL(s3c_device_usb);
-
 /* LCD Controller */
 
 static struct resource s3c_lcd_resource[] = {
index 5c0491b..4bac12d 100644 (file)
@@ -22,6 +22,7 @@
 #include <mach/gpio-core.h>
 #include <mach/hardware.h>
 #include <asm/irq.h>
+#include <plat/pm.h>
 
 #include <mach/regs-gpio.h>
 
@@ -78,6 +79,7 @@ static int s3c24xx_gpiolib_bankg_toirq(struct gpio_chip *chip, unsigned offset)
 struct s3c_gpio_chip s3c24xx_gpios[] = {
        [0] = {
                .base   = S3C24XX_GPIO_BASE(S3C2410_GPA0),
+               .pm     = __gpio_pm(&s3c_gpio_pm_1bit),
                .chip   = {
                        .base                   = S3C2410_GPA0,
                        .owner                  = THIS_MODULE,
@@ -89,6 +91,7 @@ struct s3c_gpio_chip s3c24xx_gpios[] = {
        },
        [1] = {
                .base   = S3C24XX_GPIO_BASE(S3C2410_GPB0),
+               .pm     = __gpio_pm(&s3c_gpio_pm_2bit),
                .chip   = {
                        .base                   = S3C2410_GPB0,
                        .owner                  = THIS_MODULE,
@@ -98,6 +101,7 @@ struct s3c_gpio_chip s3c24xx_gpios[] = {
        },
        [2] = {
                .base   = S3C24XX_GPIO_BASE(S3C2410_GPC0),
+               .pm     = __gpio_pm(&s3c_gpio_pm_2bit),
                .chip   = {
                        .base                   = S3C2410_GPC0,
                        .owner                  = THIS_MODULE,
@@ -107,6 +111,7 @@ struct s3c_gpio_chip s3c24xx_gpios[] = {
        },
        [3] = {
                .base   = S3C24XX_GPIO_BASE(S3C2410_GPD0),
+               .pm     = __gpio_pm(&s3c_gpio_pm_2bit),
                .chip   = {
                        .base                   = S3C2410_GPD0,
                        .owner                  = THIS_MODULE,
@@ -116,6 +121,7 @@ struct s3c_gpio_chip s3c24xx_gpios[] = {
        },
        [4] = {
                .base   = S3C24XX_GPIO_BASE(S3C2410_GPE0),
+               .pm     = __gpio_pm(&s3c_gpio_pm_2bit),
                .chip   = {
                        .base                   = S3C2410_GPE0,
                        .label                  = "GPIOE",
@@ -125,6 +131,7 @@ struct s3c_gpio_chip s3c24xx_gpios[] = {
        },
        [5] = {
                .base   = S3C24XX_GPIO_BASE(S3C2410_GPF0),
+               .pm     = __gpio_pm(&s3c_gpio_pm_2bit),
                .chip   = {
                        .base                   = S3C2410_GPF0,
                        .owner                  = THIS_MODULE,
@@ -135,6 +142,7 @@ struct s3c_gpio_chip s3c24xx_gpios[] = {
        },
        [6] = {
                .base   = S3C24XX_GPIO_BASE(S3C2410_GPG0),
+               .pm     = __gpio_pm(&s3c_gpio_pm_2bit),
                .chip   = {
                        .base                   = S3C2410_GPG0,
                        .owner                  = THIS_MODULE,
index eed8f78..c4d1334 100644 (file)
@@ -58,7 +58,6 @@
 #define S3C24XX_SZ_SPI         SZ_1M
 #define S3C24XX_SZ_SDI         SZ_1M
 #define S3C24XX_SZ_NAND                SZ_1M
-#define S3C24XX_SZ_USBHOST     SZ_1M
 
 /* GPIO ports */
 
index c758821..fb45dd9 100644 (file)
@@ -57,3 +57,8 @@ static inline void s3c_pm_arch_show_resume_irqs(void)
        s3c_pm_show_resume_irqs(IRQ_EINT4-4, __raw_readl(S3C2410_EINTPEND),
                                s3c_irqwake_eintmask);
 }
+
+static inline void s3c_pm_arch_update_uart(void __iomem *regs,
+                                          struct pm_uart_save *save)
+{
+}
index 062a293..5135c40 100644 (file)
@@ -75,43 +75,10 @@ static struct sleep_save core_save[] = {
        SAVE_ITEM(S3C2410_CLKSLOW),
 };
 
-static struct gpio_sleep {
-       void __iomem    *base;
-       unsigned int     gpcon;
-       unsigned int     gpdat;
-       unsigned int     gpup;
-} gpio_save[] = {
-       [0] = {
-               .base   = S3C2410_GPACON,
-       },
-       [1] = {
-               .base   = S3C2410_GPBCON,
-       },
-       [2] = {
-               .base   = S3C2410_GPCCON,
-       },
-       [3] = {
-               .base   = S3C2410_GPDCON,
-       },
-       [4] = {
-               .base   = S3C2410_GPECON,
-       },
-       [5] = {
-               .base   = S3C2410_GPFCON,
-       },
-       [6] = {
-               .base   = S3C2410_GPGCON,
-       },
-       [7] = {
-               .base   = S3C2410_GPHCON,
-       },
-};
-
 static struct sleep_save misc_save[] = {
        SAVE_ITEM(S3C2410_DCLKCON),
 };
 
-
 /* s3c_pm_check_resume_pin
  *
  * check to see if the pin is configured correctly for sleep mode, and
@@ -165,186 +132,6 @@ void s3c_pm_configure_extint(void)
        }
 }
 
-/* offsets for CON/DAT/UP registers */
-
-#define OFFS_CON       (S3C2410_GPACON - S3C2410_GPACON)
-#define OFFS_DAT       (S3C2410_GPADAT - S3C2410_GPACON)
-#define OFFS_UP                (S3C2410_GPBUP  - S3C2410_GPBCON)
-
-/* s3c_pm_save_gpios()
- *
- * Save the state of the GPIOs
- */
-
-void s3c_pm_save_gpios(void)
-{
-       struct gpio_sleep *gps = gpio_save;
-       unsigned int gpio;
-
-       for (gpio = 0; gpio < ARRAY_SIZE(gpio_save); gpio++, gps++) {
-               void __iomem *base = gps->base;
-
-               gps->gpcon = __raw_readl(base + OFFS_CON);
-               gps->gpdat = __raw_readl(base + OFFS_DAT);
-
-               if (gpio > 0)
-                       gps->gpup = __raw_readl(base + OFFS_UP);
-
-       }
-}
-
-/* Test whether the given masked+shifted bits of an GPIO configuration
- * are one of the SFN (special function) modes. */
-
-static inline int is_sfn(unsigned long con)
-{
-       return (con == 2 || con == 3);
-}
-
-/* Test if the given masked+shifted GPIO configuration is an input */
-
-static inline int is_in(unsigned long con)
-{
-       return con == 0;
-}
-
-/* Test if the given masked+shifted GPIO configuration is an output */
-
-static inline int is_out(unsigned long con)
-{
-       return con == 1;
-}
-
-/**
- * s3c2410_pm_restore_gpio() - restore the given GPIO bank
- * @index: The number of the GPIO bank being resumed.
- * @gps: The sleep confgiuration for the bank.
- *
- * Restore one of the GPIO banks that was saved during suspend. This is
- * not as simple as once thought, due to the possibility of glitches
- * from the order that the CON and DAT registers are set in.
- *
- * The three states the pin can be are {IN,OUT,SFN} which gives us 9
- * combinations of changes to check. Three of these, if the pin stays
- * in the same configuration can be discounted. This leaves us with
- * the following:
- *
- * { IN => OUT }  Change DAT first
- * { IN => SFN }  Change CON first
- * { OUT => SFN } Change CON first, so new data will not glitch
- * { OUT => IN }  Change CON first, so new data will not glitch
- * { SFN => IN }  Change CON first
- * { SFN => OUT } Change DAT first, so new data will not glitch [1]
- *
- * We do not currently deal with the UP registers as these control
- * weak resistors, so a small delay in change should not need to bring
- * these into the calculations.
- *
- * [1] this assumes that writing to a pin DAT whilst in SFN will set the
- *     state for when it is next output.
- */
-
-static void s3c2410_pm_restore_gpio(int index, struct gpio_sleep *gps)
-{
-       void __iomem *base = gps->base;
-       unsigned long gps_gpcon = gps->gpcon;
-       unsigned long gps_gpdat = gps->gpdat;
-       unsigned long old_gpcon;
-       unsigned long old_gpdat;
-       unsigned long old_gpup = 0x0;
-       unsigned long gpcon;
-       int nr;
-
-       old_gpcon = __raw_readl(base + OFFS_CON);
-       old_gpdat = __raw_readl(base + OFFS_DAT);
-
-       if (base == S3C2410_GPACON) {
-               /* GPACON only has one bit per control / data and no PULLUPs.
-                * GPACON[x] = 0 => Output, 1 => SFN */
-
-               /* first set all SFN bits to SFN */
-
-               gpcon = old_gpcon | gps->gpcon;
-               __raw_writel(gpcon, base + OFFS_CON);
-
-               /* now set all the other bits */
-
-               __raw_writel(gps_gpdat, base + OFFS_DAT);
-               __raw_writel(gps_gpcon, base + OFFS_CON);
-       } else {
-               unsigned long old, new, mask;
-               unsigned long change_mask = 0x0;
-
-               old_gpup = __raw_readl(base + OFFS_UP);
-
-               /* Create a change_mask of all the items that need to have
-                * their CON value changed before their DAT value, so that
-                * we minimise the work between the two settings.
-                */
-
-               for (nr = 0, mask = 0x03; nr < 32; nr += 2, mask <<= 2) {
-                       old = (old_gpcon & mask) >> nr;
-                       new = (gps_gpcon & mask) >> nr;
-
-                       /* If there is no change, then skip */
-
-                       if (old == new)
-                               continue;
-
-                       /* If both are special function, then skip */
-
-                       if (is_sfn(old) && is_sfn(new))
-                               continue;
-
-                       /* Change is IN => OUT, do not change now */
-
-                       if (is_in(old) && is_out(new))
-                               continue;
-
-                       /* Change is SFN => OUT, do not change now */
-
-                       if (is_sfn(old) && is_out(new))
-                               continue;
-
-                       /* We should now be at the case of IN=>SFN,
-                        * OUT=>SFN, OUT=>IN, SFN=>IN. */
-
-                       change_mask |= mask;
-               }
-
-               /* Write the new CON settings */
-
-               gpcon = old_gpcon & ~change_mask;
-               gpcon |= gps_gpcon & change_mask;
-
-               __raw_writel(gpcon, base + OFFS_CON);
-
-               /* Now change any items that require DAT,CON */
-
-               __raw_writel(gps_gpdat, base + OFFS_DAT);
-               __raw_writel(gps_gpcon, base + OFFS_CON);
-               __raw_writel(gps->gpup, base + OFFS_UP);
-       }
-
-       S3C_PMDBG("GPIO[%d] CON %08lx => %08lx, DAT %08lx => %08lx\n",
-                 index, old_gpcon, gps_gpcon, old_gpdat, gps_gpdat);
-}
-
-
-/** s3c2410_pm_restore_gpios()
- *
- * Restore the state of the GPIOs
- */
-
-void s3c_pm_restore_gpios(void)
-{
-       struct gpio_sleep *gps = gpio_save;
-       int gpio;
-
-       for (gpio = 0; gpio < ARRAY_SIZE(gpio_save); gpio++, gps++) {
-               s3c2410_pm_restore_gpio(gpio, gps);
-       }
-}
 
 void s3c_pm_restore_core(void)
 {
index 9ce6615..5ebd8b4 100644 (file)
@@ -19,6 +19,7 @@ config PLAT_S3C64XX
        select S3C_GPIO_PULL_UPDOWN
        select S3C_GPIO_CFG_S3C24XX
        select S3C_GPIO_CFG_S3C64XX
+       select USB_ARCH_HAS_OHCI
        help
          Base platform code for any Samsung S3C64XX device
 
@@ -63,4 +64,9 @@ config S3C64XX_SETUP_FB_24BPP
        help
          Common setup code for S3C64XX with an 24bpp RGB display helper.
 
+config S3C64XX_SETUP_SDHCI_GPIO
+       bool
+       help
+         Common setup code for S3C64XX SDHCI GPIO configurations
+
 endif
index 61bdb67..2ed5df3 100644 (file)
@@ -24,6 +24,12 @@ obj-y                                += gpiolib.o
 obj-$(CONFIG_CPU_S3C6400_INIT) += s3c6400-init.o
 obj-$(CONFIG_CPU_S3C6400_CLOCK)        += s3c6400-clock.o
 
+# PM support
+
+obj-$(CONFIG_PM)               += pm.o
+obj-$(CONFIG_PM)               += sleep.o
+obj-$(CONFIG_PM)               += irq-pm.o
+
 # DMA support
 
 obj-$(CONFIG_S3C64XX_DMA)      += dma.o
@@ -33,3 +39,4 @@ obj-$(CONFIG_S3C64XX_DMA)     += dma.o
 obj-$(CONFIG_S3C64XX_SETUP_I2C0) += setup-i2c0.o
 obj-$(CONFIG_S3C64XX_SETUP_I2C1) += setup-i2c1.o
 obj-$(CONFIG_S3C64XX_SETUP_FB_24BPP) += setup-fb-24bpp.o
+obj-$(CONFIG_S3C64XX_SETUP_SDHCI_GPIO) += setup-sdhci-gpio.o
\ No newline at end of file
index ad1b968..0bc2fa1 100644 (file)
 #include <plat/devs.h>
 #include <plat/clock.h>
 
+struct clk clk_h2 = {
+       .name           = "hclk2",
+       .id             = -1,
+       .rate           = 0,
+};
+
 struct clk clk_27m = {
        .name           = "clk_27m",
        .id             = -1,
@@ -152,6 +158,18 @@ static struct clk init_clocks_disable[] = {
                .parent         = &clk_48m,
                .enable         = s3c64xx_sclk_ctrl,
                .ctrlbit        = S3C_CLKCON_SCLK_MMC2_48,
+       }, {
+               .name           = "dma0",
+               .id             = -1,
+               .parent         = &clk_h,
+               .enable         = s3c64xx_hclk_ctrl,
+               .ctrlbit        = S3C_CLKCON_HCLK_DMA0,
+       }, {
+               .name           = "dma1",
+               .id             = -1,
+               .parent         = &clk_h,
+               .enable         = s3c64xx_hclk_ctrl,
+               .ctrlbit        = S3C_CLKCON_HCLK_DMA1,
        },
 };
 
@@ -246,6 +264,7 @@ static struct clk *clks[] __initdata = {
        &clk_epll,
        &clk_27m,
        &clk_48m,
+       &clk_h2,
 };
 
 void __init s3c64xx_register_clocks(void)
index 91f49a3..b1fdd83 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/module.h>
 #include <linux/interrupt.h>
 #include <linux/ioport.h>
+#include <linux/sysdev.h>
 #include <linux/serial_core.h>
 #include <linux/platform_device.h>
 #include <linux/io.h>
@@ -101,9 +102,24 @@ static struct map_desc s3c_iodesc[] __initdata = {
                .pfn            = __phys_to_pfn(S3C64XX_PA_MODEM),
                .length         = SZ_4K,
                .type           = MT_DEVICE,
+       }, {
+               .virtual        = (unsigned long)S3C_VA_WATCHDOG,
+               .pfn            = __phys_to_pfn(S3C64XX_PA_WATCHDOG),
+               .length         = SZ_4K,
+               .type           = MT_DEVICE,
        },
 };
 
+
+struct sysdev_class s3c64xx_sysclass = {
+       .name   = "s3c64xx-core",
+};
+
+static struct sys_device s3c64xx_sysdev = {
+       .cls    = &s3c64xx_sysclass,
+};
+
+
 /* read cpu identification code */
 
 void __init s3c64xx_init_io(struct map_desc *mach_desc, int size)
@@ -115,5 +131,21 @@ void __init s3c64xx_init_io(struct map_desc *mach_desc, int size)
        iotable_init(mach_desc, size);
 
        idcode = __raw_readl(S3C_VA_SYS + 0x118);
+       if (!idcode) {
+               /* S3C6400 has the ID register in a different place,
+                * and needs a write before it can be read. */
+
+               __raw_writel(0x0, S3C_VA_SYS + 0xA1C);
+               idcode = __raw_readl(S3C_VA_SYS + 0xA1C);
+       }
+
        s3c_init_cpu(idcode, cpu_ids, ARRAY_SIZE(cpu_ids));
 }
+
+static __init int s3c64xx_sysdev_init(void)
+{
+       sysdev_class_register(&s3c64xx_sysclass);
+       return sysdev_register(&s3c64xx_sysdev);
+}
+
+core_initcall(s3c64xx_sysdev_init);
index ee9188a..ccb82e8 100644 (file)
@@ -385,12 +385,19 @@ static __init void s3c64xx_gpiolib_add_4bit(struct s3c_gpio_chip *chip)
 {
        chip->chip.direction_input = s3c64xx_gpiolib_4bit_input;
        chip->chip.direction_output = s3c64xx_gpiolib_4bit_output;
+       chip->pm = __gpio_pm(&s3c_gpio_pm_4bit);
 }
 
 static __init void s3c64xx_gpiolib_add_4bit2(struct s3c_gpio_chip *chip)
 {
        chip->chip.direction_input = s3c64xx_gpiolib_4bit2_input;
        chip->chip.direction_output = s3c64xx_gpiolib_4bit2_output;
+       chip->pm = __gpio_pm(&s3c_gpio_pm_4bit);
+}
+
+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,
@@ -412,7 +419,8 @@ static __init int s3c64xx_gpiolib_init(void)
        s3c64xx_gpiolib_add(gpio_4bit2, ARRAY_SIZE(gpio_4bit2),
                            s3c64xx_gpiolib_add_4bit2);
 
-       s3c64xx_gpiolib_add(gpio_2bit, ARRAY_SIZE(gpio_2bit), NULL);
+       s3c64xx_gpiolib_add(gpio_2bit, ARRAY_SIZE(gpio_2bit),
+                           s3c64xx_gpiolib_add_2bit);
 
        return 0;
 }
index f865bf4..743a700 100644 (file)
 
 #define S3C_EINT(x)            ((x) + S3C_IRQ_EINT_BASE)
 #define IRQ_EINT(x)            S3C_EINT(x)
+#define IRQ_EINT_BIT(x)                ((x) - S3C_EINT(0))
 
 /* Next the external interrupt groups. These are similar to the IRQ_EINT(x)
  * that they are sourced from the GPIO pins but with a different scheme for
diff --git a/arch/arm/plat-s3c64xx/include/plat/pm-core.h b/arch/arm/plat-s3c64xx/include/plat/pm-core.h
new file mode 100644 (file)
index 0000000..d347de3
--- /dev/null
@@ -0,0 +1,98 @@
+/* linux/arch/arm/plat-s3c64xx/include/plat/pm-core.h
+ *
+ * Copyright 2008 Openmoko, Inc.
+ * Copyright 2008 Simtec Electronics
+ *      Ben Dooks <ben@simtec.co.uk>
+ *      http://armlinux.simtec.co.uk/
+ *
+ * S3C64XX - PM core support for arch/arm/plat-s3c/pm.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 <plat/regs-gpio.h>
+
+static inline void s3c_pm_debug_init_uart(void)
+{
+       u32 tmp = __raw_readl(S3C_PCLK_GATE);
+
+       /* As a note, since the S3C64XX UARTs generally have multiple
+        * clock sources, we simply enable PCLK at the moment and hope
+        * that the resume settings for the UART are suitable for the
+        * use with PCLK.
+        */
+
+       tmp |= S3C_CLKCON_PCLK_UART0;
+       tmp |= S3C_CLKCON_PCLK_UART1;
+       tmp |= S3C_CLKCON_PCLK_UART2;
+       tmp |= S3C_CLKCON_PCLK_UART3;
+
+       __raw_writel(tmp, S3C_PCLK_GATE);
+       udelay(10);
+}
+
+static inline void s3c_pm_arch_prepare_irqs(void)
+{
+       /* VIC should have already been taken care of */
+
+       /* clear any pending EINT0 interrupts */
+       __raw_writel(__raw_readl(S3C64XX_EINT0PEND), S3C64XX_EINT0PEND);
+}
+
+static inline void s3c_pm_arch_stop_clocks(void)
+{
+}
+
+static inline void s3c_pm_arch_show_resume_irqs(void)
+{
+}
+
+/* make these defines, we currently do not have any need to change
+ * the IRQ wake controls depending on the CPU we are running on */
+
+#define s3c_irqwake_eintallow  ((1 << 28) - 1)
+#define s3c_irqwake_intallow   (0)
+
+static inline void s3c_pm_arch_update_uart(void __iomem *regs,
+                                          struct pm_uart_save *save)
+{
+       u32 ucon = __raw_readl(regs + S3C2410_UCON);
+       u32 ucon_clk = ucon & S3C6400_UCON_CLKMASK;
+       u32 save_clk = save->ucon & S3C6400_UCON_CLKMASK;
+       u32 new_ucon;
+       u32 delta;
+
+       /* S3C64XX UART blocks only support level interrupts, so ensure that
+        * when we restore unused UART blocks we force the level interrupt
+        * settigs. */
+       save->ucon |= S3C2410_UCON_TXILEVEL | S3C2410_UCON_RXILEVEL;
+
+       /* We have a constraint on changing the clock type of the UART
+        * between UCLKx and PCLK, so ensure that when we restore UCON
+        * that the CLK field is correctly modified if the bootloader
+        * has changed anything.
+        */
+       if (ucon_clk != save_clk) {
+               new_ucon = save->ucon;
+               delta = ucon_clk ^ save_clk;
+
+               /* change from UCLKx => wrong PCLK,
+                * either UCLK can be tested for by a bit-test
+                * with UCLK0 */
+               if (ucon_clk & S3C6400_UCON_UCLK0 &&
+                   !(save_clk & S3C6400_UCON_UCLK0) &&
+                   delta & S3C6400_UCON_PCLK2) {
+                       new_ucon &= ~S3C6400_UCON_UCLK0;
+               } else if (delta == S3C6400_UCON_PCLK2) {
+                       /* as an precaution, don't change from
+                        * PCLK2 => PCLK or vice-versa */
+                       new_ucon ^= S3C6400_UCON_PCLK2;
+               }
+
+               S3C_PMDBG("ucon change %04x => %04x (save=%04x)\n",
+                         ucon, new_ucon, save->ucon);
+               save->ucon = new_ucon;
+       }
+}
index b1082c1..52836d4 100644 (file)
@@ -32,6 +32,7 @@
 #define S3C_HCLK_GATE          S3C_CLKREG(0x30)
 #define S3C_PCLK_GATE          S3C_CLKREG(0x34)
 #define S3C_SCLK_GATE          S3C_CLKREG(0x38)
+#define S3C_MEM0_GATE          S3C_CLKREG(0x3C)
 
 /* CLKDIV0 */
 #define S3C6400_CLKDIV0_MFC_MASK       (0xf << 28)
index 571eaa2..11f2e1e 100644 (file)
 /* Common init code for S3C6400 related SoCs */
 
 extern void s3c6400_common_init_uarts(struct s3c2410_uartcfg *cfg, int no);
-extern void s3c6400_register_clocks(void);
+extern void s3c6400_register_clocks(unsigned armclk_divlimit);
 extern void s3c6400_setup_clocks(void);
 
 #ifdef CONFIG_CPU_S3C6400
 
 extern  int s3c6400_init(void);
+extern void s3c6400_init_irq(void);
 extern void s3c6400_map_io(void);
 extern void s3c6400_init_clocks(int xtal);
 
index 47e5155..f81b7b8 100644 (file)
@@ -14,6 +14,7 @@
 
 #include <linux/kernel.h>
 #include <linux/interrupt.h>
+#include <linux/sysdev.h>
 #include <linux/gpio.h>
 #include <linux/irq.h>
 #include <linux/io.h>
@@ -26,6 +27,7 @@
 
 #include <mach/map.h>
 #include <plat/cpu.h>
+#include <plat/pm.h>
 
 #define eint_offset(irq)       ((irq) - IRQ_EINT(0))
 #define eint_irq_to_bit(irq)   (1 << eint_offset(irq))
@@ -134,6 +136,7 @@ static struct irq_chip s3c_irq_eint = {
        .mask_ack       = s3c_irq_eint_maskack,
        .ack            = s3c_irq_eint_ack,
        .set_type       = s3c_irq_eint_set_type,
+       .set_wake       = s3c_irqext_wake,
 };
 
 /* s3c_irq_demux_eint
diff --git a/arch/arm/plat-s3c64xx/irq-pm.c b/arch/arm/plat-s3c64xx/irq-pm.c
new file mode 100644 (file)
index 0000000..ca523b5
--- /dev/null
@@ -0,0 +1,111 @@
+/* arch/arm/plat-s3c64xx/irq-pm.c
+ *
+ * Copyright 2008 Openmoko, Inc.
+ * Copyright 2008 Simtec Electronics
+ *      Ben Dooks <ben@simtec.co.uk>
+ *      http://armlinux.simtec.co.uk/
+ *
+ * S3C64XX - Interrupt handling Power Management
+ *
+ * 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/sysdev.h>
+#include <linux/interrupt.h>
+#include <linux/serial_core.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+
+#include <mach/map.h>
+
+#include <plat/regs-serial.h>
+#include <plat/regs-timer.h>
+#include <plat/regs-gpio.h>
+#include <plat/cpu.h>
+#include <plat/pm.h>
+
+/* We handled all the IRQ types in this code, to save having to make several
+ * small files to handle each different type separately. Having the EINT_GRP
+ * code here shouldn't be as much bloat as the IRQ table space needed when
+ * they are enabled. The added benefit is we ensure that these registers are
+ * in the same state as we suspended.
+ */
+
+static struct sleep_save irq_save[] = {
+       SAVE_ITEM(S3C64XX_PRIORITY),
+       SAVE_ITEM(S3C64XX_EINT0CON0),
+       SAVE_ITEM(S3C64XX_EINT0CON1),
+       SAVE_ITEM(S3C64XX_EINT0FLTCON0),
+       SAVE_ITEM(S3C64XX_EINT0FLTCON1),
+       SAVE_ITEM(S3C64XX_EINT0FLTCON2),
+       SAVE_ITEM(S3C64XX_EINT0FLTCON3),
+       SAVE_ITEM(S3C64XX_EINT0MASK),
+       SAVE_ITEM(S3C64XX_TINT_CSTAT),
+};
+
+static struct irq_grp_save {
+       u32     fltcon;
+       u32     con;
+       u32     mask;
+} eint_grp_save[5];
+
+static u32 irq_uart_mask[CONFIG_SERIAL_SAMSUNG_UARTS];
+
+static int s3c64xx_irq_pm_suspend(struct sys_device *dev, pm_message_t state)
+{
+       struct irq_grp_save *grp = eint_grp_save;
+       int i;
+
+       S3C_PMDBG("%s: suspending IRQs\n", __func__);
+
+       s3c_pm_do_save(irq_save, ARRAY_SIZE(irq_save));
+
+       for (i = 0; i < CONFIG_SERIAL_SAMSUNG_UARTS; i++)
+               irq_uart_mask[i] = __raw_readl(S3C_VA_UARTx(i) + S3C64XX_UINTM);
+
+       for (i = 0; i < ARRAY_SIZE(eint_grp_save); i++, grp++) {
+               grp->con = __raw_readl(S3C64XX_EINT12CON + (i * 4));
+               grp->mask = __raw_readl(S3C64XX_EINT12MASK + (i * 4));
+               grp->fltcon = __raw_readl(S3C64XX_EINT12FLTCON + (i * 4));
+       }
+
+       return 0;
+}
+
+static int s3c64xx_irq_pm_resume(struct sys_device *dev)
+{
+       struct irq_grp_save *grp = eint_grp_save;
+       int i;
+
+       S3C_PMDBG("%s: resuming IRQs\n", __func__);
+
+       s3c_pm_do_restore(irq_save, ARRAY_SIZE(irq_save));
+
+       for (i = 0; i < CONFIG_SERIAL_SAMSUNG_UARTS; i++)
+               __raw_writel(irq_uart_mask[i], S3C_VA_UARTx(i) + S3C64XX_UINTM);
+
+       for (i = 0; i < ARRAY_SIZE(eint_grp_save); i++, grp++) {
+               __raw_writel(grp->con, S3C64XX_EINT12CON + (i * 4));
+               __raw_writel(grp->mask, S3C64XX_EINT12MASK + (i * 4));
+               __raw_writel(grp->fltcon, S3C64XX_EINT12FLTCON + (i * 4));
+       }
+
+       S3C_PMDBG("%s: IRQ configuration restored\n", __func__);
+       return 0;
+}
+
+static struct sysdev_driver s3c64xx_irq_driver = {
+       .suspend = s3c64xx_irq_pm_suspend,
+       .resume  = s3c64xx_irq_pm_resume,
+};
+
+static int __init s3c64xx_irq_pm_init(void)
+{
+       return sysdev_driver_register(&s3c64xx_sysclass, &s3c64xx_irq_driver);
+}
+
+arch_initcall(s3c64xx_irq_pm_init);
+
index f22edf7..8dc5b6d 100644 (file)
 
 #include <linux/kernel.h>
 #include <linux/interrupt.h>
+#include <linux/serial_core.h>
 #include <linux/irq.h>
 #include <linux/io.h>
 
 #include <asm/hardware/vic.h>
 
 #include <mach/map.h>
+#include <plat/regs-serial.h>
 #include <plat/regs-timer.h>
 #include <plat/cpu.h>
 
@@ -135,9 +137,6 @@ static inline unsigned int s3c_irq_uart_bit(unsigned int irq)
 }
 
 /* UART interrupt registers, not worth adding to seperate include header */
-#define S3C64XX_UINTP  0x30
-#define S3C64XX_UINTSP 0x34
-#define S3C64XX_UINTM  0x38
 
 static void s3c_irq_uart_mask(unsigned int irq)
 {
@@ -233,8 +232,8 @@ void __init s3c64xx_init_irq(u32 vic0_valid, u32 vic1_valid)
        printk(KERN_DEBUG "%s: initialising interrupts\n", __func__);
 
        /* initialise the pair of VICs */
-       vic_init(S3C_VA_VIC0, S3C_VIC0_BASE, vic0_valid);
-       vic_init(S3C_VA_VIC1, S3C_VIC1_BASE, vic1_valid);
+       vic_init(S3C_VA_VIC0, S3C_VIC0_BASE, vic0_valid, 0);
+       vic_init(S3C_VA_VIC1, S3C_VIC1_BASE, vic1_valid, 0);
 
        /* add the timer sub-irqs */
 
diff --git a/arch/arm/plat-s3c64xx/pm.c b/arch/arm/plat-s3c64xx/pm.c
new file mode 100644 (file)
index 0000000..07a6516
--- /dev/null
@@ -0,0 +1,175 @@
+/* linux/arch/arm/plat-s3c64xx/pm.c
+ *
+ * Copyright 2008 Openmoko, Inc.
+ * Copyright 2008 Simtec Electronics
+ *     Ben Dooks <ben@simtec.co.uk>
+ *     http://armlinux.simtec.co.uk/
+ *
+ * S3C64XX CPU PM 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/init.h>
+#include <linux/suspend.h>
+#include <linux/serial_core.h>
+#include <linux/io.h>
+
+#include <mach/map.h>
+
+#include <plat/pm.h>
+#include <plat/regs-sys.h>
+#include <plat/regs-gpio.h>
+#include <plat/regs-clock.h>
+#include <plat/regs-syscon-power.h>
+#include <plat/regs-gpio-memport.h>
+
+#ifdef CONFIG_S3C_PM_DEBUG_LED_SMDK
+#include <plat/gpio-bank-n.h>
+
+void s3c_pm_debug_smdkled(u32 set, u32 clear)
+{
+       unsigned long flags;
+       u32 reg;
+
+       local_irq_save(flags);
+       reg = __raw_readl(S3C64XX_GPNCON);
+       reg &= ~(S3C64XX_GPN_CONMASK(12) | S3C64XX_GPN_CONMASK(13) |
+                S3C64XX_GPN_CONMASK(14) | S3C64XX_GPN_CONMASK(15));
+       reg |= S3C64XX_GPN_OUTPUT(12) | S3C64XX_GPN_OUTPUT(13) |
+              S3C64XX_GPN_OUTPUT(14) | S3C64XX_GPN_OUTPUT(15);
+       __raw_writel(reg, S3C64XX_GPNCON);
+
+       reg = __raw_readl(S3C64XX_GPNDAT);
+       reg &= ~(clear << 12);
+       reg |= set << 12;
+       __raw_writel(reg, S3C64XX_GPNDAT);
+
+       local_irq_restore(flags);
+}
+#endif
+
+static struct sleep_save core_save[] = {
+       SAVE_ITEM(S3C_APLL_LOCK),
+       SAVE_ITEM(S3C_MPLL_LOCK),
+       SAVE_ITEM(S3C_EPLL_LOCK),
+       SAVE_ITEM(S3C_CLK_SRC),
+       SAVE_ITEM(S3C_CLK_DIV0),
+       SAVE_ITEM(S3C_CLK_DIV1),
+       SAVE_ITEM(S3C_CLK_DIV2),
+       SAVE_ITEM(S3C_CLK_OUT),
+       SAVE_ITEM(S3C_HCLK_GATE),
+       SAVE_ITEM(S3C_PCLK_GATE),
+       SAVE_ITEM(S3C_SCLK_GATE),
+       SAVE_ITEM(S3C_MEM0_GATE),
+
+       SAVE_ITEM(S3C_EPLL_CON1),
+       SAVE_ITEM(S3C_EPLL_CON0),
+
+       SAVE_ITEM(S3C64XX_MEM0DRVCON),
+       SAVE_ITEM(S3C64XX_MEM1DRVCON),
+
+#ifndef CONFIG_CPU_FREQ
+       SAVE_ITEM(S3C_APLL_CON),
+       SAVE_ITEM(S3C_MPLL_CON),
+#endif
+};
+
+static struct sleep_save misc_save[] = {
+       SAVE_ITEM(S3C64XX_AHB_CON0),
+       SAVE_ITEM(S3C64XX_AHB_CON1),
+       SAVE_ITEM(S3C64XX_AHB_CON2),
+       
+       SAVE_ITEM(S3C64XX_SPCON),
+
+       SAVE_ITEM(S3C64XX_MEM0CONSTOP),
+       SAVE_ITEM(S3C64XX_MEM1CONSTOP),
+       SAVE_ITEM(S3C64XX_MEM0CONSLP0),
+       SAVE_ITEM(S3C64XX_MEM0CONSLP1),
+       SAVE_ITEM(S3C64XX_MEM1CONSLP),
+};
+
+void s3c_pm_configure_extint(void)
+{
+       __raw_writel(s3c_irqwake_eintmask, S3C64XX_EINT_MASK);
+}
+
+void s3c_pm_restore_core(void)
+{
+       __raw_writel(0, S3C64XX_EINT_MASK);
+
+       s3c_pm_debug_smdkled(1 << 2, 0);
+
+       s3c_pm_do_restore_core(core_save, ARRAY_SIZE(core_save));
+       s3c_pm_do_restore(misc_save, ARRAY_SIZE(misc_save));
+}
+
+void s3c_pm_save_core(void)
+{
+       s3c_pm_do_save(misc_save, ARRAY_SIZE(misc_save));
+       s3c_pm_do_save(core_save, ARRAY_SIZE(core_save));
+}
+
+/* since both s3c6400 and s3c6410 share the same sleep pm calls, we
+ * put the per-cpu code in here until any new cpu comes along and changes
+ * this.
+ */
+
+#include <plat/regs-gpio.h>
+
+static void s3c64xx_cpu_suspend(void)
+{
+       unsigned long tmp;
+
+       /* set our standby method to sleep */
+
+       tmp = __raw_readl(S3C64XX_PWR_CFG);
+       tmp &= ~S3C64XX_PWRCFG_CFG_WFI_MASK;
+       tmp |= S3C64XX_PWRCFG_CFG_WFI_SLEEP;
+       __raw_writel(tmp, S3C64XX_PWR_CFG);
+
+       /* clear any old wakeup */
+
+       __raw_writel(__raw_readl(S3C64XX_WAKEUP_STAT),
+                    S3C64XX_WAKEUP_STAT);
+
+       /* set the LED state to 0110 over sleep */
+       s3c_pm_debug_smdkled(3 << 1, 0xf);
+
+       /* issue the standby signal into the pm unit. Note, we
+        * issue a write-buffer drain just in case */
+
+       tmp = 0;
+
+       asm("b 1f\n\t"
+           ".align 5\n\t"
+           "1:\n\t"
+           "mcr p15, 0, %0, c7, c10, 5\n\t"
+           "mcr p15, 0, %0, c7, c10, 4\n\t"
+           "mcr p15, 0, %0, c7, c0, 4" :: "r" (tmp));
+
+       /* we should never get past here */
+
+       panic("sleep resumed to originator?");
+}
+
+static void s3c64xx_pm_prepare(void)
+{
+       /* store address of resume. */
+       __raw_writel(virt_to_phys(s3c_cpu_resume), S3C64XX_INFORM0);
+
+       /* ensure previous wakeup state is cleared before sleeping */
+       __raw_writel(__raw_readl(S3C64XX_WAKEUP_STAT), S3C64XX_WAKEUP_STAT);
+}
+
+static int s3c64xx_pm_init(void)
+{
+       pm_cpu_prep = s3c64xx_pm_prepare;
+       pm_cpu_sleep = s3c64xx_cpu_suspend;
+       pm_uart_udivslot = 1;
+       return 0;
+}
+
+arch_initcall(s3c64xx_pm_init);
index 05b1752..1debc1f 100644 (file)
@@ -133,6 +133,65 @@ static struct clksrc_clk clk_mout_mpll = {
        .sources        = &clk_src_mpll,
 };
 
+static unsigned int armclk_mask;
+
+static unsigned long s3c64xx_clk_arm_get_rate(struct clk *clk)
+{
+       unsigned long rate = clk_get_rate(clk->parent);
+       u32 clkdiv;
+
+       /* divisor mask starts at bit0, so no need to shift */
+       clkdiv = __raw_readl(S3C_CLK_DIV0) & armclk_mask;
+
+       return rate / (clkdiv + 1);
+}
+
+static unsigned long s3c64xx_clk_arm_round_rate(struct clk *clk,
+                                               unsigned long rate)
+{
+       unsigned long parent = clk_get_rate(clk->parent);
+       u32 div;
+
+       if (parent < rate)
+               return rate;
+
+       div = (parent / rate) - 1;
+       if (div > armclk_mask)
+               div = armclk_mask;
+
+       return parent / (div + 1);
+}
+
+static int s3c64xx_clk_arm_set_rate(struct clk *clk, unsigned long rate)
+{
+       unsigned long parent = clk_get_rate(clk->parent);
+       u32 div;
+       u32 val;
+
+       if (rate < parent / (armclk_mask + 1))
+               return -EINVAL;
+
+       rate = clk_round_rate(clk, rate);
+       div = clk_get_rate(clk->parent) / rate;
+
+       val = __raw_readl(S3C_CLK_DIV0);
+       val &= armclk_mask;
+       val |= (div - 1);
+       __raw_writel(val, S3C_CLK_DIV0);
+
+       return 0;
+
+}
+
+static struct clk clk_arm = {
+       .name           = "armclk",
+       .id             = -1,
+       .parent         = &clk_mout_apll.clk,
+       .get_rate       = s3c64xx_clk_arm_get_rate,
+       .set_rate       = s3c64xx_clk_arm_set_rate,
+       .round_rate     = s3c64xx_clk_arm_round_rate,
+};
+
 static unsigned long s3c64xx_clk_doutmpll_get_rate(struct clk *clk)
 {
        unsigned long rate = clk_get_rate(clk->parent);
@@ -520,6 +579,33 @@ static struct clksrc_clk clk_irda = {
        .reg_divider    = S3C_CLK_DIV2,
 };
 
+static struct clk *clkset_camif_list[] = {
+       &clk_h2,
+};
+
+static struct clk_sources clkset_camif = {
+       .sources        = clkset_camif_list,
+       .nr_sources     = ARRAY_SIZE(clkset_camif_list),
+};
+
+static struct clksrc_clk clk_camif = {
+       .clk    = {
+               .name           = "camera",
+               .id             = -1,
+               .ctrlbit        = S3C_CLKCON_SCLK_CAM,
+               .enable         = s3c64xx_sclk_ctrl,
+               .set_parent     = s3c64xx_setparent_clksrc,
+               .get_rate       = s3c64xx_getrate_clksrc,
+               .set_rate       = s3c64xx_setrate_clksrc,
+               .round_rate     = s3c64xx_roundrate_clksrc,
+       },
+       .shift          = 0,
+       .mask           = 0,
+       .sources        = &clkset_camif,
+       .divider_shift  = S3C6400_CLKDIV0_CAM_SHIFT,
+       .reg_divider    = S3C_CLK_DIV0,
+};
+
 /* Clock initialisation code */
 
 static struct clksrc_clk *init_parents[] = {
@@ -536,6 +622,7 @@ static struct clksrc_clk *init_parents[] = {
        &clk_audio0,
        &clk_audio1,
        &clk_irda,
+       &clk_camif,
 };
 
 static void __init_or_cpufreq s3c6400_set_clksrc(struct clksrc_clk *clk)
@@ -608,6 +695,7 @@ void __init_or_cpufreq s3c6400_setup_clocks(void)
        clk_fout_epll.rate = epll;
        clk_fout_apll.rate = apll;
 
+       clk_h2.rate = hclk2;
        clk_h.rate = hclk;
        clk_p.rate = pclk;
        clk_f.rate = fclk;
@@ -635,14 +723,30 @@ static struct clk *clks[] __initdata = {
        &clk_audio0.clk,
        &clk_audio1.clk,
        &clk_irda.clk,
+       &clk_camif.clk,
+       &clk_arm,
 };
 
-void __init s3c6400_register_clocks(void)
+/**
+ * s3c6400_register_clocks - register clocks for s3c6400 and above
+ * @armclk_divlimit: Divisor mask for ARMCLK
+ *
+ * Register the clocks for the S3C6400 and above SoC range, such
+ * as ARMCLK and the clocks which have divider chains attached.
+ *
+ * This call does not setup the clocks, which is left to the
+ * s3c6400_setup_clocks() call which may be needed by the cpufreq
+ * or resume code to re-set the clocks if the bootloader has changed
+ * them.
+ */
+void __init s3c6400_register_clocks(unsigned armclk_divlimit)
 {
        struct clk *clkp;
        int ret;
        int ptr;
 
+       armclk_mask = armclk_divlimit;
+
        for (ptr = 0; ptr < ARRAY_SIZE(clks); ptr++) {
                clkp = clks[ptr];
                ret = s3c24xx_register_clock(clkp);
diff --git a/arch/arm/plat-s3c64xx/setup-sdhci-gpio.c b/arch/arm/plat-s3c64xx/setup-sdhci-gpio.c
new file mode 100644 (file)
index 0000000..5417123
--- /dev/null
@@ -0,0 +1,55 @@
+/* linux/arch/arm/plat-s3c64xx/setup-sdhci-gpio.c
+ *
+ * Copyright 2008 Simtec Electronics
+ *     Ben Dooks <ben@simtec.co.uk>
+ *     http://armlinux.simtec.co.uk/
+ *
+ * S3C64XX - Helper functions for setting up SDHCI device(s) GPIO (HSMMC)
+ *
+ * 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/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+
+#include <mach/gpio.h>
+#include <plat/gpio-cfg.h>
+
+void s3c64xx_setup_sdhci0_cfg_gpio(struct platform_device *dev, int width)
+{
+       unsigned int gpio;
+       unsigned int end;
+
+       end = S3C64XX_GPG(2 + width);
+
+       /* Set all the necessary GPG pins to special-function 0 */
+       for (gpio = S3C64XX_GPG(0); gpio < end; gpio++) {
+               s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2));
+               s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
+       }
+
+       s3c_gpio_setpull(S3C64XX_GPG(6), S3C_GPIO_PULL_UP);
+       s3c_gpio_cfgpin(S3C64XX_GPG(6), S3C_GPIO_SFN(2));
+}
+
+void s3c64xx_setup_sdhci1_cfg_gpio(struct platform_device *dev, int width)
+{
+       unsigned int gpio;
+       unsigned int end;
+
+       end = S3C64XX_GPH(2 + width);
+
+       /* Set all the necessary GPG pins to special-function 0 */
+       for (gpio = S3C64XX_GPH(0); gpio < end; gpio++) {
+               s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2));
+               s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
+       }
+
+       s3c_gpio_setpull(S3C64XX_GPG(6), S3C_GPIO_PULL_UP);
+       s3c_gpio_cfgpin(S3C64XX_GPG(6), S3C_GPIO_SFN(3));
+}
diff --git a/arch/arm/plat-s3c64xx/sleep.S b/arch/arm/plat-s3c64xx/sleep.S
new file mode 100644 (file)
index 0000000..8e71fe9
--- /dev/null
@@ -0,0 +1,144 @@
+/* linux/0arch/arm/plat-s3c64xx/sleep.S
+ *
+ * Copyright 2008 Openmoko, Inc.
+ * Copyright 2008 Simtec Electronics
+ *     Ben Dooks <ben@simtec.co.uk>
+ *     http://armlinux.simtec.co.uk/
+ *
+ * S3C64XX CPU sleep code
+ *
+ * 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/linkage.h>
+#include <asm/assembler.h>
+#include <mach/map.h>
+
+#undef S3C64XX_VA_GPIO
+#define S3C64XX_VA_GPIO (0x0)
+
+#include <plat/regs-gpio.h>
+#include <plat/gpio-bank-n.h>
+
+#define LL_UART (S3C_PA_UART + (0x400 * CONFIG_S3C_LOWLEVEL_UART_PORT))
+
+       .text
+
+       /* s3c_cpu_save
+        *
+        * Save enough processor state to allow the restart of the pm.c
+        * code after resume.
+        *
+        * entry:
+        *      r0 = pointer to the save block
+       */
+
+ENTRY(s3c_cpu_save)
+       stmfd   sp!, { r4 - r12, lr }
+
+       mrc     p15, 0, r4, c13, c0, 0  @ FCSE/PID
+       mrc     p15, 0, r5, c3, c0, 0   @ Domain ID
+       mrc     p15, 0, r6, c2, c0, 0   @ Translation Table BASE0
+       mrc     p15, 0, r7, c2, c0, 1   @ Translation Table BASE1
+       mrc     p15, 0, r8, c2, c0, 2   @ Translation Table Control
+       mrc     p15, 0, r9, c1, c0, 0   @ Control register
+       mrc     p15, 0, r10, c1, c0, 1  @ Auxiliary control register
+       mrc     p15, 0, r11, c1, c0, 2  @ Co-processor access controls
+
+       stmia   r0, { r4 - r13 }        @ Save CP registers and SP
+
+       @@ save our state to ram
+       bl      s3c_pm_cb_flushcache
+
+       @@ call final suspend code
+       ldr     r0, =pm_cpu_sleep
+       ldr     pc, [r0]
+       
+       @@ return to the caller, after the MMU is turned on.
+       @@ restore the last bits of the stack and return.
+resume_with_mmu:
+       ldmfd   sp!, { r4 - r12, pc }   @ return, from sp from s3c_cpu_save
+
+       .data
+
+       /* the next bit is code, but it requires easy access to the
+        * s3c_sleep_save_phys data before the MMU is switched on, so
+        * we store the code that needs this variable in the .data where
+        * the value can be written to (the .text segment is RO).
+       */
+
+       .global s3c_sleep_save_phys
+s3c_sleep_save_phys:
+       .word   0
+
+       /* Sleep magic, the word before the resume entry point so that the
+        * bootloader can check for a resumeable image. */
+
+       .word   0x2bedf00d
+
+       /* s3c_cpu_reusme
+        *
+        * This is the entry point, stored by whatever method the bootloader
+        * requires to get the kernel runnign again. This code expects to be
+        * entered with no caches live and the MMU disabled. It will then
+        * restore the MMU and other basic CP registers saved and restart
+        * the kernel C code to finish the resume code.
+       */
+
+ENTRY(s3c_cpu_resume)
+       msr     cpsr_c, #PSR_I_BIT | PSR_F_BIT | SVC_MODE
+       ldr     r2, =LL_UART            /* for debug */
+
+#ifdef CONFIG_S3C_PM_DEBUG_LED_SMDK
+       /* Initialise the GPIO state if we are debugging via the SMDK LEDs,
+        * as the uboot version supplied resets these to inputs during the
+        * resume checks.
+       */
+
+       ldr     r3, =S3C64XX_PA_GPIO
+       ldr     r0, [ r3, #S3C64XX_GPNCON ]
+       bic     r0, r0, #(S3C64XX_GPN_CONMASK(12) | S3C64XX_GPN_CONMASK(13) | \
+                         S3C64XX_GPN_CONMASK(14) | S3C64XX_GPN_CONMASK(15))
+       orr     r0, r0, #(S3C64XX_GPN_OUTPUT(12) | S3C64XX_GPN_OUTPUT(13) | \
+                         S3C64XX_GPN_OUTPUT(14) | S3C64XX_GPN_OUTPUT(15))
+       str     r0, [ r3, #S3C64XX_GPNCON ]
+
+       ldr     r0, [ r3, #S3C64XX_GPNDAT ]
+       bic     r0, r0, #0xf << 12                      @ GPN12..15
+       orr     r0, r0, #1 << 15                        @ GPN15
+       str     r0, [ r3, #S3C64XX_GPNDAT ]
+#endif
+
+       /* __v6_setup from arch/arm/mm/proc-v6.S, ensure that the caches
+        * are thoroughly cleaned just in case the bootloader didn't do it
+        * for us. */
+       mov     r0, #0
+       mcr     p15, 0, r0, c7, c14, 0          @ clean+invalidate D cache
+       mcr     p15, 0, r0, c7, c5, 0           @ invalidate I cache
+       mcr     p15, 0, r0, c7, c15, 0          @ clean+invalidate cache
+       mcr     p15, 0, r0, c7, c10, 4          @ drain write buffer
+       @@mcr   p15, 0, r0, c8, c7, 0           @ invalidate I + D TLBs
+       @@mcr   p15, 0, r0, c7, c7, 0           @ Invalidate I + D caches
+
+       ldr     r0, s3c_sleep_save_phys
+       ldmia   r0, { r4 - r13 }
+
+       mcr     p15, 0, r4, c13, c0, 0  @ FCSE/PID
+       mcr     p15, 0, r5, c3, c0, 0   @ Domain ID
+       mcr     p15, 0, r6, c2, c0, 0   @ Translation Table BASE0
+       mcr     p15, 0, r7, c2, c0, 1   @ Translation Table BASE1
+       mcr     p15, 0, r8, c2, c0, 2   @ Translation Table Control
+       mcr     p15, 0, r10, c1, c0, 1  @ Auxiliary control register
+
+       mov     r0, #0                  @ restore copro access controls
+       mcr     p15, 0, r11, c1, c0, 2  @ Co-processor access controls
+       mcr     p15, 0, r0, c7, c5, 4
+
+       ldr     r2, =resume_with_mmu
+       mcr     p15, 0, r9, c1, c0, 0           /* turn mmu back on */
+       nop
+       mov     pc, r2                          /* jump back */
+
+       .end