Browse Source

Merge master.kernel.org:/home/rmk/linux-2.6-arm

* master.kernel.org:/home/rmk/linux-2.6-arm: (25 commits)
  [ARM] 3648/1: Update struct ucontext layout for coprocessor registers
  [ARM] Add identifying number for non-rt sigframe
  [ARM] Gather common sigframe saving code into setup_sigframe()
  [ARM] Gather common sigframe restoration code into restore_sigframe()
  [ARM] Re-use sigframe within rt_sigframe
  [ARM] Merge sigcontext and sigmask members of sigframe
  [ARM] Replace extramask with a full copy of the sigmask
  [ARM] Remove rt_sigframe puc and pinfo pointers
  [ARM] 3647/1: S3C24XX: add Osiris to the list of simtec pm machines
  [ARM] 3645/1: S3C2412: irq support for external interrupts
  [ARM] 3643/1: S3C2410: Add new usb clocks
  [ARM] 3642/1: S3C24XX: Add machine SMDK2413
  [ARM] 3641/1: S3C2412: Fixup gpio register naming
  [ARM] 3640/1: S3C2412: Use S3C24XX_DCLKCON instead of S3C2410_DCLKCON
  [ARM] 3639/1: S3C2412: serial port support
  [ARM] 3638/1: S3C2412: core clocks
  [ARM] 3637/1: S3C24XX: Add mpll clock, and set as fclk parent
  [ARM] 3636/1: S3C2412: Add selection of CPU_ARM926
  [ARM] 3635/1: S3C24XX: Add S3C2412 core cpu support
  [ARM] 3633/1: S3C24XX: s3c2410 gpio bugfix - wrong pin nos
  ...
Linus Torvalds 19 years ago
parent
commit
dfd8317d33
49 changed files with 1880 additions and 225 deletions
  1. 1 1
      arch/arm/kernel/iwmmxt.S
  2. 82 125
      arch/arm/kernel/signal.c
  3. 1 1
      arch/arm/mach-ep93xx/Makefile
  4. 156 0
      arch/arm/mach-ep93xx/clock.c
  5. 28 0
      arch/arm/mach-ep93xx/core.c
  6. 1 0
      arch/arm/mach-ixp2000/core.c
  7. 20 0
      arch/arm/mach-s3c2410/Kconfig
  8. 6 0
      arch/arm/mach-s3c2410/Makefile
  9. 15 6
      arch/arm/mach-s3c2410/clock.c
  10. 2 0
      arch/arm/mach-s3c2410/clock.h
  11. 34 3
      arch/arm/mach-s3c2410/cpu.c
  12. 1 0
      arch/arm/mach-s3c2410/cpu.h
  13. 37 20
      arch/arm/mach-s3c2410/irq.c
  14. 126 0
      arch/arm/mach-s3c2410/mach-smdk2413.c
  15. 2 1
      arch/arm/mach-s3c2410/pm-simtec.c
  16. 9 1
      arch/arm/mach-s3c2410/s3c2410-clock.c
  17. 5 8
      arch/arm/mach-s3c2410/s3c2410-gpio.c
  18. 711 0
      arch/arm/mach-s3c2410/s3c2412-clock.c
  19. 195 0
      arch/arm/mach-s3c2410/s3c2412.c
  20. 29 0
      arch/arm/mach-s3c2410/s3c2412.h
  21. 5 5
      arch/arm/mm/Kconfig
  22. 6 3
      drivers/serial/Kconfig
  23. 142 1
      drivers/serial/s3c2410.c
  24. 0 1
      include/asm-arm/arch-aaec2000/io.h
  25. 0 1
      include/asm-arm/arch-clps711x/io.h
  26. 0 8
      include/asm-arm/arch-ebsa285/io.h
  27. 2 0
      include/asm-arm/arch-ep93xx/ep93xx-regs.h
  28. 1 0
      include/asm-arm/arch-ep93xx/platform.h
  29. 0 1
      include/asm-arm/arch-integrator/io.h
  30. 0 1
      include/asm-arm/arch-iop3xx/io.h
  31. 0 1
      include/asm-arm/arch-l7200/io.h
  32. 0 1
      include/asm-arm/arch-lh7a40x/io.h
  33. 0 1
      include/asm-arm/arch-netx/io.h
  34. 0 1
      include/asm-arm/arch-omap/io.h
  35. 0 1
      include/asm-arm/arch-pxa/io.h
  36. 0 1
      include/asm-arm/arch-realview/io.h
  37. 8 2
      include/asm-arm/arch-s3c2410/debug-macro.S
  38. 7 23
      include/asm-arm/arch-s3c2410/entry-macro.S
  39. 16 0
      include/asm-arm/arch-s3c2410/map.h
  40. 62 1
      include/asm-arm/arch-s3c2410/regs-clock.h
  41. 3 0
      include/asm-arm/arch-s3c2410/regs-dsc.h
  42. 60 3
      include/asm-arm/arch-s3c2410/regs-gpio.h
  43. 5 0
      include/asm-arm/arch-s3c2410/regs-gpioj.h
  44. 6 0
      include/asm-arm/arch-s3c2410/regs-irq.h
  45. 15 0
      include/asm-arm/arch-s3c2410/regs-serial.h
  46. 0 1
      include/asm-arm/arch-sa1100/io.h
  47. 0 1
      include/asm-arm/arch-versatile/io.h
  48. 78 1
      include/asm-arm/ucontext.h
  49. 3 0
      include/linux/serial_core.h

+ 1 - 1
arch/arm/kernel/iwmmxt.S

@@ -273,7 +273,7 @@ ENTRY(iwmmxt_task_restore)
  *
  *
  * r0 = previous task_struct pointer (must be preserved)
  * r0 = previous task_struct pointer (must be preserved)
  * r1 = previous thread_info pointer
  * r1 = previous thread_info pointer
- * r2 = next thread_info.cpu_domain pointer (must be preserved)
+ * r2 = next thread_info pointer (must be preserved)
  *
  *
  * Called only from __switch_to with task preemption disabled.
  * Called only from __switch_to with task preemption disabled.
  * No need to care about preserving r4 and above.
  * No need to care about preserving r4 and above.

+ 82 - 125
arch/arm/kernel/signal.c

@@ -134,17 +134,6 @@ sys_sigaction(int sig, const struct old_sigaction __user *act,
 
 
 #ifdef CONFIG_IWMMXT
 #ifdef CONFIG_IWMMXT
 
 
-/* iwmmxt_area is 0x98 bytes long, preceeded by 8 bytes of signature */
-#define IWMMXT_STORAGE_SIZE	(0x98 + 8)
-#define IWMMXT_MAGIC0		0x12ef842a
-#define IWMMXT_MAGIC1		0x1c07ca71
-
-struct iwmmxt_sigframe {
-	unsigned long	magic0;
-	unsigned long	magic1;
-	unsigned long	storage[0x98/4];
-};
-
 static int preserve_iwmmxt_context(struct iwmmxt_sigframe *frame)
 static int preserve_iwmmxt_context(struct iwmmxt_sigframe *frame)
 {
 {
 	char kbuf[sizeof(*frame) + 8];
 	char kbuf[sizeof(*frame) + 8];
@@ -152,8 +141,8 @@ static int preserve_iwmmxt_context(struct iwmmxt_sigframe *frame)
 
 
 	/* the iWMMXt context must be 64 bit aligned */
 	/* the iWMMXt context must be 64 bit aligned */
 	kframe = (struct iwmmxt_sigframe *)((unsigned long)(kbuf + 8) & ~7);
 	kframe = (struct iwmmxt_sigframe *)((unsigned long)(kbuf + 8) & ~7);
-	kframe->magic0 = IWMMXT_MAGIC0;
-	kframe->magic1 = IWMMXT_MAGIC1;
+	kframe->magic = IWMMXT_MAGIC;
+	kframe->size = IWMMXT_STORAGE_SIZE;
 	iwmmxt_task_copy(current_thread_info(), &kframe->storage);
 	iwmmxt_task_copy(current_thread_info(), &kframe->storage);
 	return __copy_to_user(frame, kframe, sizeof(*frame));
 	return __copy_to_user(frame, kframe, sizeof(*frame));
 }
 }
@@ -167,8 +156,8 @@ static int restore_iwmmxt_context(struct iwmmxt_sigframe *frame)
 	kframe = (struct iwmmxt_sigframe *)((unsigned long)(kbuf + 8) & ~7);
 	kframe = (struct iwmmxt_sigframe *)((unsigned long)(kbuf + 8) & ~7);
 	if (__copy_from_user(kframe, frame, sizeof(*frame)))
 	if (__copy_from_user(kframe, frame, sizeof(*frame)))
 		return -1;
 		return -1;
-	if (kframe->magic0 != IWMMXT_MAGIC0 ||
-	    kframe->magic1 != IWMMXT_MAGIC1)
+	if (kframe->magic != IWMMXT_MAGIC ||
+	    kframe->size != IWMMXT_STORAGE_SIZE)
 		return -1;
 		return -1;
 	iwmmxt_task_restore(current_thread_info(), &kframe->storage);
 	iwmmxt_task_restore(current_thread_info(), &kframe->storage);
 	return 0;
 	return 0;
@@ -176,71 +165,62 @@ static int restore_iwmmxt_context(struct iwmmxt_sigframe *frame)
 
 
 #endif
 #endif
 
 
-/*
- * Auxiliary signal frame.  This saves stuff like FP state.
- * The layout of this structure is not part of the user ABI.
- */
-struct aux_sigframe {
-#ifdef CONFIG_IWMMXT
-	struct iwmmxt_sigframe	iwmmxt;
-#endif
-#ifdef CONFIG_VFP
-	union vfp_state		vfp;
-#endif
-};
-
 /*
 /*
  * Do a signal return; undo the signal stack.  These are aligned to 64-bit.
  * Do a signal return; undo the signal stack.  These are aligned to 64-bit.
  */
  */
 struct sigframe {
 struct sigframe {
-	struct sigcontext sc;
-	unsigned long extramask[_NSIG_WORDS-1];
+	struct ucontext uc;
 	unsigned long retcode[2];
 	unsigned long retcode[2];
-	struct aux_sigframe aux __attribute__((aligned(8)));
 };
 };
 
 
 struct rt_sigframe {
 struct rt_sigframe {
-	struct siginfo __user *pinfo;
-	void __user *puc;
 	struct siginfo info;
 	struct siginfo info;
-	struct ucontext uc;
-	unsigned long retcode[2];
-	struct aux_sigframe aux __attribute__((aligned(8)));
+	struct sigframe sig;
 };
 };
 
 
-static int
-restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc,
-		   struct aux_sigframe __user *aux)
+static int restore_sigframe(struct pt_regs *regs, struct sigframe __user *sf)
 {
 {
-	int err = 0;
+	struct aux_sigframe __user *aux;
+	sigset_t set;
+	int err;
+
+	err = __copy_from_user(&set, &sf->uc.uc_sigmask, sizeof(set));
+	if (err == 0) {
+		sigdelsetmask(&set, ~_BLOCKABLE);
+		spin_lock_irq(&current->sighand->siglock);
+		current->blocked = set;
+		recalc_sigpending();
+		spin_unlock_irq(&current->sighand->siglock);
+	}
 
 
-	__get_user_error(regs->ARM_r0, &sc->arm_r0, err);
-	__get_user_error(regs->ARM_r1, &sc->arm_r1, err);
-	__get_user_error(regs->ARM_r2, &sc->arm_r2, err);
-	__get_user_error(regs->ARM_r3, &sc->arm_r3, err);
-	__get_user_error(regs->ARM_r4, &sc->arm_r4, err);
-	__get_user_error(regs->ARM_r5, &sc->arm_r5, err);
-	__get_user_error(regs->ARM_r6, &sc->arm_r6, err);
-	__get_user_error(regs->ARM_r7, &sc->arm_r7, err);
-	__get_user_error(regs->ARM_r8, &sc->arm_r8, err);
-	__get_user_error(regs->ARM_r9, &sc->arm_r9, err);
-	__get_user_error(regs->ARM_r10, &sc->arm_r10, err);
-	__get_user_error(regs->ARM_fp, &sc->arm_fp, err);
-	__get_user_error(regs->ARM_ip, &sc->arm_ip, err);
-	__get_user_error(regs->ARM_sp, &sc->arm_sp, err);
-	__get_user_error(regs->ARM_lr, &sc->arm_lr, err);
-	__get_user_error(regs->ARM_pc, &sc->arm_pc, err);
-	__get_user_error(regs->ARM_cpsr, &sc->arm_cpsr, err);
+	__get_user_error(regs->ARM_r0, &sf->uc.uc_mcontext.arm_r0, err);
+	__get_user_error(regs->ARM_r1, &sf->uc.uc_mcontext.arm_r1, err);
+	__get_user_error(regs->ARM_r2, &sf->uc.uc_mcontext.arm_r2, err);
+	__get_user_error(regs->ARM_r3, &sf->uc.uc_mcontext.arm_r3, err);
+	__get_user_error(regs->ARM_r4, &sf->uc.uc_mcontext.arm_r4, err);
+	__get_user_error(regs->ARM_r5, &sf->uc.uc_mcontext.arm_r5, err);
+	__get_user_error(regs->ARM_r6, &sf->uc.uc_mcontext.arm_r6, err);
+	__get_user_error(regs->ARM_r7, &sf->uc.uc_mcontext.arm_r7, err);
+	__get_user_error(regs->ARM_r8, &sf->uc.uc_mcontext.arm_r8, err);
+	__get_user_error(regs->ARM_r9, &sf->uc.uc_mcontext.arm_r9, err);
+	__get_user_error(regs->ARM_r10, &sf->uc.uc_mcontext.arm_r10, err);
+	__get_user_error(regs->ARM_fp, &sf->uc.uc_mcontext.arm_fp, err);
+	__get_user_error(regs->ARM_ip, &sf->uc.uc_mcontext.arm_ip, err);
+	__get_user_error(regs->ARM_sp, &sf->uc.uc_mcontext.arm_sp, err);
+	__get_user_error(regs->ARM_lr, &sf->uc.uc_mcontext.arm_lr, err);
+	__get_user_error(regs->ARM_pc, &sf->uc.uc_mcontext.arm_pc, err);
+	__get_user_error(regs->ARM_cpsr, &sf->uc.uc_mcontext.arm_cpsr, err);
 
 
 	err |= !valid_user_regs(regs);
 	err |= !valid_user_regs(regs);
 
 
+	aux = (struct aux_sigframe __user *) sf->uc.uc_regspace;
 #ifdef CONFIG_IWMMXT
 #ifdef CONFIG_IWMMXT
 	if (err == 0 && test_thread_flag(TIF_USING_IWMMXT))
 	if (err == 0 && test_thread_flag(TIF_USING_IWMMXT))
 		err |= restore_iwmmxt_context(&aux->iwmmxt);
 		err |= restore_iwmmxt_context(&aux->iwmmxt);
 #endif
 #endif
 #ifdef CONFIG_VFP
 #ifdef CONFIG_VFP
 //	if (err == 0)
 //	if (err == 0)
-//		err |= vfp_restore_state(&aux->vfp);
+//		err |= vfp_restore_state(&sf->aux.vfp);
 #endif
 #endif
 
 
 	return err;
 	return err;
@@ -249,7 +229,6 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc,
 asmlinkage int sys_sigreturn(struct pt_regs *regs)
 asmlinkage int sys_sigreturn(struct pt_regs *regs)
 {
 {
 	struct sigframe __user *frame;
 	struct sigframe __user *frame;
-	sigset_t set;
 
 
 	/* Always make any pending restarted system calls return -EINTR */
 	/* Always make any pending restarted system calls return -EINTR */
 	current_thread_info()->restart_block.fn = do_no_restart_syscall;
 	current_thread_info()->restart_block.fn = do_no_restart_syscall;
@@ -266,19 +245,8 @@ asmlinkage int sys_sigreturn(struct pt_regs *regs)
 
 
 	if (!access_ok(VERIFY_READ, frame, sizeof (*frame)))
 	if (!access_ok(VERIFY_READ, frame, sizeof (*frame)))
 		goto badframe;
 		goto badframe;
-	if (__get_user(set.sig[0], &frame->sc.oldmask)
-	    || (_NSIG_WORDS > 1
-	        && __copy_from_user(&set.sig[1], &frame->extramask,
-				    sizeof(frame->extramask))))
-		goto badframe;
-
-	sigdelsetmask(&set, ~_BLOCKABLE);
-	spin_lock_irq(&current->sighand->siglock);
-	current->blocked = set;
-	recalc_sigpending();
-	spin_unlock_irq(&current->sighand->siglock);
 
 
-	if (restore_sigcontext(regs, &frame->sc, &frame->aux))
+	if (restore_sigframe(regs, frame))
 		goto badframe;
 		goto badframe;
 
 
 	/* Send SIGTRAP if we're single-stepping */
 	/* Send SIGTRAP if we're single-stepping */
@@ -297,7 +265,6 @@ badframe:
 asmlinkage int sys_rt_sigreturn(struct pt_regs *regs)
 asmlinkage int sys_rt_sigreturn(struct pt_regs *regs)
 {
 {
 	struct rt_sigframe __user *frame;
 	struct rt_sigframe __user *frame;
-	sigset_t set;
 
 
 	/* Always make any pending restarted system calls return -EINTR */
 	/* Always make any pending restarted system calls return -EINTR */
 	current_thread_info()->restart_block.fn = do_no_restart_syscall;
 	current_thread_info()->restart_block.fn = do_no_restart_syscall;
@@ -314,19 +281,11 @@ asmlinkage int sys_rt_sigreturn(struct pt_regs *regs)
 
 
 	if (!access_ok(VERIFY_READ, frame, sizeof (*frame)))
 	if (!access_ok(VERIFY_READ, frame, sizeof (*frame)))
 		goto badframe;
 		goto badframe;
-	if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
-		goto badframe;
 
 
-	sigdelsetmask(&set, ~_BLOCKABLE);
-	spin_lock_irq(&current->sighand->siglock);
-	current->blocked = set;
-	recalc_sigpending();
-	spin_unlock_irq(&current->sighand->siglock);
-
-	if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &frame->aux))
+	if (restore_sigframe(regs, &frame->sig))
 		goto badframe;
 		goto badframe;
 
 
-	if (do_sigaltstack(&frame->uc.uc_stack, NULL, regs->ARM_sp) == -EFAULT)
+	if (do_sigaltstack(&frame->sig.uc.uc_stack, NULL, regs->ARM_sp) == -EFAULT)
 		goto badframe;
 		goto badframe;
 
 
 	/* Send SIGTRAP if we're single-stepping */
 	/* Send SIGTRAP if we're single-stepping */
@@ -343,42 +302,46 @@ badframe:
 }
 }
 
 
 static int
 static int
-setup_sigcontext(struct sigcontext __user *sc, struct aux_sigframe __user *aux,
-		 struct pt_regs *regs, unsigned long mask)
+setup_sigframe(struct sigframe __user *sf, struct pt_regs *regs, sigset_t *set)
 {
 {
+	struct aux_sigframe __user *aux;
 	int err = 0;
 	int err = 0;
 
 
-	__put_user_error(regs->ARM_r0, &sc->arm_r0, err);
-	__put_user_error(regs->ARM_r1, &sc->arm_r1, err);
-	__put_user_error(regs->ARM_r2, &sc->arm_r2, err);
-	__put_user_error(regs->ARM_r3, &sc->arm_r3, err);
-	__put_user_error(regs->ARM_r4, &sc->arm_r4, err);
-	__put_user_error(regs->ARM_r5, &sc->arm_r5, err);
-	__put_user_error(regs->ARM_r6, &sc->arm_r6, err);
-	__put_user_error(regs->ARM_r7, &sc->arm_r7, err);
-	__put_user_error(regs->ARM_r8, &sc->arm_r8, err);
-	__put_user_error(regs->ARM_r9, &sc->arm_r9, err);
-	__put_user_error(regs->ARM_r10, &sc->arm_r10, err);
-	__put_user_error(regs->ARM_fp, &sc->arm_fp, err);
-	__put_user_error(regs->ARM_ip, &sc->arm_ip, err);
-	__put_user_error(regs->ARM_sp, &sc->arm_sp, err);
-	__put_user_error(regs->ARM_lr, &sc->arm_lr, err);
-	__put_user_error(regs->ARM_pc, &sc->arm_pc, err);
-	__put_user_error(regs->ARM_cpsr, &sc->arm_cpsr, err);
-
-	__put_user_error(current->thread.trap_no, &sc->trap_no, err);
-	__put_user_error(current->thread.error_code, &sc->error_code, err);
-	__put_user_error(current->thread.address, &sc->fault_address, err);
-	__put_user_error(mask, &sc->oldmask, err);
-
+	__put_user_error(regs->ARM_r0, &sf->uc.uc_mcontext.arm_r0, err);
+	__put_user_error(regs->ARM_r1, &sf->uc.uc_mcontext.arm_r1, err);
+	__put_user_error(regs->ARM_r2, &sf->uc.uc_mcontext.arm_r2, err);
+	__put_user_error(regs->ARM_r3, &sf->uc.uc_mcontext.arm_r3, err);
+	__put_user_error(regs->ARM_r4, &sf->uc.uc_mcontext.arm_r4, err);
+	__put_user_error(regs->ARM_r5, &sf->uc.uc_mcontext.arm_r5, err);
+	__put_user_error(regs->ARM_r6, &sf->uc.uc_mcontext.arm_r6, err);
+	__put_user_error(regs->ARM_r7, &sf->uc.uc_mcontext.arm_r7, err);
+	__put_user_error(regs->ARM_r8, &sf->uc.uc_mcontext.arm_r8, err);
+	__put_user_error(regs->ARM_r9, &sf->uc.uc_mcontext.arm_r9, err);
+	__put_user_error(regs->ARM_r10, &sf->uc.uc_mcontext.arm_r10, err);
+	__put_user_error(regs->ARM_fp, &sf->uc.uc_mcontext.arm_fp, err);
+	__put_user_error(regs->ARM_ip, &sf->uc.uc_mcontext.arm_ip, err);
+	__put_user_error(regs->ARM_sp, &sf->uc.uc_mcontext.arm_sp, err);
+	__put_user_error(regs->ARM_lr, &sf->uc.uc_mcontext.arm_lr, err);
+	__put_user_error(regs->ARM_pc, &sf->uc.uc_mcontext.arm_pc, err);
+	__put_user_error(regs->ARM_cpsr, &sf->uc.uc_mcontext.arm_cpsr, err);
+
+	__put_user_error(current->thread.trap_no, &sf->uc.uc_mcontext.trap_no, err);
+	__put_user_error(current->thread.error_code, &sf->uc.uc_mcontext.error_code, err);
+	__put_user_error(current->thread.address, &sf->uc.uc_mcontext.fault_address, err);
+	__put_user_error(set->sig[0], &sf->uc.uc_mcontext.oldmask, err);
+
+	err |= __copy_to_user(&sf->uc.uc_sigmask, set, sizeof(*set));
+
+	aux = (struct aux_sigframe __user *) sf->uc.uc_regspace;
 #ifdef CONFIG_IWMMXT
 #ifdef CONFIG_IWMMXT
 	if (err == 0 && test_thread_flag(TIF_USING_IWMMXT))
 	if (err == 0 && test_thread_flag(TIF_USING_IWMMXT))
 		err |= preserve_iwmmxt_context(&aux->iwmmxt);
 		err |= preserve_iwmmxt_context(&aux->iwmmxt);
 #endif
 #endif
 #ifdef CONFIG_VFP
 #ifdef CONFIG_VFP
 //	if (err == 0)
 //	if (err == 0)
-//		err |= vfp_save_state(&aux->vfp);
+//		err |= vfp_save_state(&sf->aux.vfp);
 #endif
 #endif
+	__put_user_error(0, &aux->end_magic, err);
 
 
 	return err;
 	return err;
 }
 }
@@ -487,13 +450,12 @@ setup_frame(int usig, struct k_sigaction *ka, sigset_t *set, struct pt_regs *reg
 	if (!frame)
 	if (!frame)
 		return 1;
 		return 1;
 
 
-	err |= setup_sigcontext(&frame->sc, &frame->aux, regs, set->sig[0]);
-
-	if (_NSIG_WORDS > 1) {
-		err |= __copy_to_user(frame->extramask, &set->sig[1],
-				      sizeof(frame->extramask));
-	}
+	/*
+	 * Set uc.uc_flags to a value which sc.trap_no would never have.
+	 */
+	__put_user_error(0x5ac3c35a, &frame->uc.uc_flags, err);
 
 
+	err |= setup_sigframe(frame, regs, set);
 	if (err == 0)
 	if (err == 0)
 		err = setup_return(regs, ka, frame->retcode, frame, usig);
 		err = setup_return(regs, ka, frame->retcode, frame, usig);
 
 
@@ -511,25 +473,20 @@ setup_rt_frame(int usig, struct k_sigaction *ka, siginfo_t *info,
 	if (!frame)
 	if (!frame)
 		return 1;
 		return 1;
 
 
-	__put_user_error(&frame->info, &frame->pinfo, err);
-	__put_user_error(&frame->uc, &frame->puc, err);
 	err |= copy_siginfo_to_user(&frame->info, info);
 	err |= copy_siginfo_to_user(&frame->info, info);
 
 
-	__put_user_error(0, &frame->uc.uc_flags, err);
-	__put_user_error(NULL, &frame->uc.uc_link, err);
+	__put_user_error(0, &frame->sig.uc.uc_flags, err);
+	__put_user_error(NULL, &frame->sig.uc.uc_link, err);
 
 
 	memset(&stack, 0, sizeof(stack));
 	memset(&stack, 0, sizeof(stack));
 	stack.ss_sp = (void __user *)current->sas_ss_sp;
 	stack.ss_sp = (void __user *)current->sas_ss_sp;
 	stack.ss_flags = sas_ss_flags(regs->ARM_sp);
 	stack.ss_flags = sas_ss_flags(regs->ARM_sp);
 	stack.ss_size = current->sas_ss_size;
 	stack.ss_size = current->sas_ss_size;
-	err |= __copy_to_user(&frame->uc.uc_stack, &stack, sizeof(stack));
-
-	err |= setup_sigcontext(&frame->uc.uc_mcontext, &frame->aux,
-				regs, set->sig[0]);
-	err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
+	err |= __copy_to_user(&frame->sig.uc.uc_stack, &stack, sizeof(stack));
 
 
+	err |= setup_sigframe(&frame->sig, regs, set);
 	if (err == 0)
 	if (err == 0)
-		err = setup_return(regs, ka, frame->retcode, frame, usig);
+		err = setup_return(regs, ka, frame->sig.retcode, frame, usig);
 
 
 	if (err == 0) {
 	if (err == 0) {
 		/*
 		/*
@@ -538,7 +495,7 @@ setup_rt_frame(int usig, struct k_sigaction *ka, siginfo_t *info,
 		 *   -- Peter Maydell <pmaydell@chiark.greenend.org.uk> 2000-12-06
 		 *   -- Peter Maydell <pmaydell@chiark.greenend.org.uk> 2000-12-06
 		 */
 		 */
 		regs->ARM_r1 = (unsigned long)&frame->info;
 		regs->ARM_r1 = (unsigned long)&frame->info;
-		regs->ARM_r2 = (unsigned long)&frame->uc;
+		regs->ARM_r2 = (unsigned long)&frame->sig.uc;
 	}
 	}
 
 
 	return err;
 	return err;

+ 1 - 1
arch/arm/mach-ep93xx/Makefile

@@ -1,7 +1,7 @@
 #
 #
 # Makefile for the linux kernel.
 # Makefile for the linux kernel.
 #
 #
-obj-y			:= core.o
+obj-y			:= core.o clock.o
 obj-m			:=
 obj-m			:=
 obj-n			:=
 obj-n			:=
 obj-			:=
 obj-			:=

+ 156 - 0
arch/arm/mach-ep93xx/clock.c

@@ -0,0 +1,156 @@
+/*
+ * arch/arm/mach-ep93xx/clock.c
+ * Clock control for Cirrus EP93xx chips.
+ *
+ * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ */
+
+#include <linux/kernel.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/string.h>
+#include <asm/div64.h>
+#include <asm/hardware.h>
+#include <asm/io.h>
+
+struct clk {
+	char		*name;
+	unsigned long	rate;
+	int		users;
+	u32		enable_reg;
+	u32		enable_mask;
+};
+
+static struct clk clk_pll1 = {
+	.name		= "pll1",
+};
+static struct clk clk_f = {
+	.name		= "fclk",
+};
+static struct clk clk_h = {
+	.name		= "hclk",
+};
+static struct clk clk_p = {
+	.name		= "pclk",
+};
+static struct clk clk_pll2 = {
+	.name		= "pll2",
+};
+static struct clk clk_usb_host = {
+	.name		= "usb_host",
+	.enable_reg	= EP93XX_SYSCON_CLOCK_CONTROL,
+	.enable_mask	= EP93XX_SYSCON_CLOCK_USH_EN,
+};
+
+
+static struct clk *clocks[] = {
+	&clk_pll1,
+	&clk_f,
+	&clk_h,
+	&clk_p,
+	&clk_pll2,
+	&clk_usb_host,
+};
+
+struct clk *clk_get(struct device *dev, const char *id)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(clocks); i++) {
+		if (!strcmp(clocks[i]->name, id))
+			return clocks[i];
+	}
+
+	return ERR_PTR(-ENOENT);
+}
+
+int clk_enable(struct clk *clk)
+{
+	if (!clk->users++ && clk->enable_reg) {
+		u32 value;
+
+		value = __raw_readl(clk->enable_reg);
+		__raw_writel(value | clk->enable_mask, clk->enable_reg);
+	}
+
+	return 0;
+}
+
+void clk_disable(struct clk *clk)
+{
+	if (!--clk->users && clk->enable_reg) {
+		u32 value;
+
+		value = __raw_readl(clk->enable_reg);
+		__raw_writel(value & ~clk->enable_mask, clk->enable_reg);
+	}
+}
+
+unsigned long clk_get_rate(struct clk *clk)
+{
+	return clk->rate;
+}
+
+void clk_put(struct clk *clk)
+{
+}
+
+
+
+static char fclk_divisors[] = { 1, 2, 4, 8, 16, 1, 1, 1 };
+static char hclk_divisors[] = { 1, 2, 4, 5, 6, 8, 16, 32 };
+static char pclk_divisors[] = { 1, 2, 4, 8 };
+
+/*
+ * PLL rate = 14.7456 MHz * (X1FBD + 1) * (X2FBD + 1) / (X2IPD + 1) / 2^PS
+ */
+static unsigned long calc_pll_rate(u32 config_word)
+{
+	unsigned long long rate;
+	int i;
+
+	rate = 14745600;
+	rate *= ((config_word >> 11) & 0x1f) + 1;		/* X1FBD */
+	rate *= ((config_word >> 5) & 0x3f) + 1;		/* X2FBD */
+	do_div(rate, (config_word & 0x1f) + 1);			/* X2IPD */
+	for (i = 0; i < ((config_word >> 16) & 3); i++)		/* PS */
+		rate >>= 1;
+
+	return (unsigned long)rate;
+}
+
+void ep93xx_clock_init(void)
+{
+	u32 value;
+
+	value = __raw_readl(EP93XX_SYSCON_CLOCK_SET1);
+	if (!(value & 0x00800000)) {			/* PLL1 bypassed?  */
+		clk_pll1.rate = 14745600;
+	} else {
+		clk_pll1.rate = calc_pll_rate(value);
+	}
+	clk_f.rate = clk_pll1.rate / fclk_divisors[(value >> 25) & 0x7];
+	clk_h.rate = clk_pll1.rate / hclk_divisors[(value >> 20) & 0x7];
+	clk_p.rate = clk_h.rate / pclk_divisors[(value >> 18) & 0x3];
+
+	value = __raw_readl(EP93XX_SYSCON_CLOCK_SET2);
+	if (!(value & 0x00080000)) {			/* PLL2 bypassed?  */
+		clk_pll2.rate = 14745600;
+	} else if (value & 0x00040000) {		/* PLL2 enabled?  */
+		clk_pll2.rate = calc_pll_rate(value);
+	} else {
+		clk_pll2.rate = 0;
+	}
+	clk_usb_host.rate = clk_pll2.rate / (((value >> 28) & 0xf) + 1);
+
+	printk(KERN_INFO "ep93xx: PLL1 running at %ld MHz, PLL2 at %ld MHz\n",
+		clk_pll1.rate / 1000000, clk_pll2.rate / 1000000);
+	printk(KERN_INFO "ep93xx: FCLK %ld MHz, HCLK %ld MHz, PCLK %ld MHz\n",
+		clk_f.rate / 1000000, clk_h.rate / 1000000,
+		clk_p.rate / 1000000);
+}

+ 28 - 0
arch/arm/mach-ep93xx/core.c

@@ -433,10 +433,37 @@ static struct platform_device ep93xx_rtc_device = {
 };
 };
 
 
 
 
+static struct resource ep93xx_ohci_resources[] = {
+	[0] = {
+		.start	= EP93XX_USB_PHYS_BASE,
+		.end	= EP93XX_USB_PHYS_BASE + 0x0fff,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= IRQ_EP93XX_USB,
+		.end	= IRQ_EP93XX_USB,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device ep93xx_ohci_device = {
+	.name		= "ep93xx-ohci",
+	.id		= -1,
+	.dev		= {
+		.dma_mask		= (void *)0xffffffff,
+		.coherent_dma_mask	= 0xffffffff,
+	},
+	.num_resources	= ARRAY_SIZE(ep93xx_ohci_resources),
+	.resource	= ep93xx_ohci_resources,
+};
+
+
 void __init ep93xx_init_devices(void)
 void __init ep93xx_init_devices(void)
 {
 {
 	unsigned int v;
 	unsigned int v;
 
 
+	ep93xx_clock_init();
+
 	/*
 	/*
 	 * Disallow access to MaverickCrunch initially.
 	 * Disallow access to MaverickCrunch initially.
 	 */
 	 */
@@ -450,4 +477,5 @@ void __init ep93xx_init_devices(void)
 	amba_device_register(&uart3_device, &iomem_resource);
 	amba_device_register(&uart3_device, &iomem_resource);
 
 
 	platform_device_register(&ep93xx_rtc_device);
 	platform_device_register(&ep93xx_rtc_device);
+	platform_device_register(&ep93xx_ohci_device);
 }
 }

+ 1 - 0
arch/arm/mach-ixp2000/core.c

@@ -302,6 +302,7 @@ void gpio_line_config(int line, int direction)
 	}
 	}
 	local_irq_restore(flags);
 	local_irq_restore(flags);
 }
 }
+EXPORT_SYMBOL(gpio_line_config);
 
 
 
 
 /*************************************************************************
 /*************************************************************************

+ 20 - 0
arch/arm/mach-s3c2410/Kconfig

@@ -81,6 +81,12 @@ config SMDK2440_CPU2442
 	depends on ARCH_S3C2440
 	depends on ARCH_S3C2440
 	select CPU_S3C2442
 	select CPU_S3C2442
 
 
+config MACH_SMDK2413
+	bool "SMDK2413"
+	select CPU_S3C2412
+	select MACH_SMDK
+	help
+	  Say Y here if you are using an SMDK2413
 
 
 config MACH_VR1000
 config MACH_VR1000
 	bool "Thorcom VR1000"
 	bool "Thorcom VR1000"
@@ -127,6 +133,20 @@ config CPU_S3C2410
 	  Support for S3C2410 and S3C2410A family from the S3C24XX line
 	  Support for S3C2410 and S3C2410A family from the S3C24XX line
 	  of Samsung Mobile CPUs.
 	  of Samsung Mobile CPUs.
 
 
+# internal node to signify if we are only dealing with an S3C2412
+
+config CPU_S3C2412_ONLY
+	bool
+	depends on ARCH_S3C2410 && !CPU_S3C2400 && !CPU_S3C2410 && \
+		   !CPU_S3C2440 && !CPU_S3C2442 && CPU_S3C2412
+	default y if CPU_S3C2412
+
+config CPU_S3C2412
+	bool
+	depends on ARCH_S3C2410
+	help
+	  Support for the S3C2412 and S3C2413 SoCs from the S3C24XX line
+
 config CPU_S3C244X
 config CPU_S3C244X
 	bool
 	bool
 	depends on ARCH_S3C2410 && (CPU_S3C2440 || CPU_S3C2442)
 	depends on ARCH_S3C2410 && (CPU_S3C2440 || CPU_S3C2442)

+ 6 - 0
arch/arm/mach-s3c2410/Makefile

@@ -24,6 +24,11 @@ obj-$(CONFIG_S3C2410_DMA)  += dma.o
 obj-$(CONFIG_PM)	   += pm.o sleep.o
 obj-$(CONFIG_PM)	   += pm.o sleep.o
 obj-$(CONFIG_PM_SIMTEC)	   += pm-simtec.o
 obj-$(CONFIG_PM_SIMTEC)	   += pm-simtec.o
 
 
+# S3C2412 support
+obj-$(CONFIG_CPU_S3C2412)  += s3c2412.o
+obj-$(CONFIG_CPU_S3C2412)  += s3c2412-clock.o
+
+#
 # S3C244X support
 # S3C244X support
 
 
 obj-$(CONFIG_CPU_S3C244X)  += s3c244x.o
 obj-$(CONFIG_CPU_S3C244X)  += s3c244x.o
@@ -57,6 +62,7 @@ obj-$(CONFIG_ARCH_BAST)		+= mach-bast.o usb-simtec.o
 obj-$(CONFIG_ARCH_H1940)	+= mach-h1940.o
 obj-$(CONFIG_ARCH_H1940)	+= mach-h1940.o
 obj-$(CONFIG_MACH_N30)		+= mach-n30.o
 obj-$(CONFIG_MACH_N30)		+= mach-n30.o
 obj-$(CONFIG_ARCH_SMDK2410)	+= mach-smdk2410.o
 obj-$(CONFIG_ARCH_SMDK2410)	+= mach-smdk2410.o
+obj-$(CONFIG_MACH_SMDK2413)	+= mach-smdk2413.o
 obj-$(CONFIG_ARCH_S3C2440)	+= mach-smdk2440.o
 obj-$(CONFIG_ARCH_S3C2440)	+= mach-smdk2440.o
 obj-$(CONFIG_MACH_VR1000)	+= mach-vr1000.o usb-simtec.o
 obj-$(CONFIG_MACH_VR1000)	+= mach-vr1000.o usb-simtec.o
 obj-$(CONFIG_MACH_RX3715)	+= mach-rx3715.o
 obj-$(CONFIG_MACH_RX3715)	+= mach-rx3715.o

+ 15 - 6
arch/arm/mach-s3c2410/clock.c

@@ -213,7 +213,7 @@ EXPORT_SYMBOL(clk_set_parent);
 
 
 /* base clocks */
 /* base clocks */
 
 
-static struct clk clk_xtal = {
+struct clk clk_xtal = {
 	.name		= "xtal",
 	.name		= "xtal",
 	.id		= -1,
 	.id		= -1,
 	.rate		= 0,
 	.rate		= 0,
@@ -221,6 +221,11 @@ static struct clk clk_xtal = {
 	.ctrlbit	= 0,
 	.ctrlbit	= 0,
 };
 };
 
 
+struct clk clk_mpll = {
+	.name		= "mpll",
+	.id		= -1,
+};
+
 struct clk clk_upll = {
 struct clk clk_upll = {
 	.name		= "upll",
 	.name		= "upll",
 	.id		= -1,
 	.id		= -1,
@@ -232,7 +237,7 @@ struct clk clk_f = {
 	.name		= "fclk",
 	.name		= "fclk",
 	.id		= -1,
 	.id		= -1,
 	.rate		= 0,
 	.rate		= 0,
-	.parent		= NULL,
+	.parent		= &clk_mpll,
 	.ctrlbit	= 0,
 	.ctrlbit	= 0,
 };
 };
 
 
@@ -263,14 +268,14 @@ struct clk clk_usb_bus = {
 
 
 static int s3c24xx_dclk_enable(struct clk *clk, int enable)
 static int s3c24xx_dclk_enable(struct clk *clk, int enable)
 {
 {
-	unsigned long dclkcon = __raw_readl(S3C2410_DCLKCON);
+	unsigned long dclkcon = __raw_readl(S3C24XX_DCLKCON);
 
 
 	if (enable)
 	if (enable)
 		dclkcon |= clk->ctrlbit;
 		dclkcon |= clk->ctrlbit;
 	else
 	else
 		dclkcon &= ~clk->ctrlbit;
 		dclkcon &= ~clk->ctrlbit;
 
 
-	__raw_writel(dclkcon, S3C2410_DCLKCON);
+	__raw_writel(dclkcon, S3C24XX_DCLKCON);
 
 
 	return 0;
 	return 0;
 }
 }
@@ -289,7 +294,7 @@ static int s3c24xx_dclk_setparent(struct clk *clk, struct clk *parent)
 
 
 	clk->parent = parent;
 	clk->parent = parent;
 
 
-	dclkcon = __raw_readl(S3C2410_DCLKCON);
+	dclkcon = __raw_readl(S3C24XX_DCLKCON);
 
 
 	if (clk->ctrlbit == S3C2410_DCLKCON_DCLK0EN) {
 	if (clk->ctrlbit == S3C2410_DCLKCON_DCLK0EN) {
 		if (uclk)
 		if (uclk)
@@ -303,7 +308,7 @@ static int s3c24xx_dclk_setparent(struct clk *clk, struct clk *parent)
 			dclkcon &= ~S3C2410_DCLKCON_DCLK1_UCLK;
 			dclkcon &= ~S3C2410_DCLKCON_DCLK1_UCLK;
 	}
 	}
 
 
-	__raw_writel(dclkcon, S3C2410_DCLKCON);
+	__raw_writel(dclkcon, S3C24XX_DCLKCON);
 
 
 	return 0;
 	return 0;
 }
 }
@@ -413,6 +418,7 @@ int __init s3c24xx_setup_clocks(unsigned long xtal,
 	clk_xtal.rate = xtal;
 	clk_xtal.rate = xtal;
 	clk_upll.rate = s3c2410_get_pll(__raw_readl(S3C2410_UPLLCON), xtal);
 	clk_upll.rate = s3c2410_get_pll(__raw_readl(S3C2410_UPLLCON), xtal);
 
 
+	clk_mpll.rate = fclk;
 	clk_h.rate = hclk;
 	clk_h.rate = hclk;
 	clk_p.rate = pclk;
 	clk_p.rate = pclk;
 	clk_f.rate = fclk;
 	clk_f.rate = fclk;
@@ -424,6 +430,9 @@ int __init s3c24xx_setup_clocks(unsigned long xtal,
 	if (s3c24xx_register_clock(&clk_xtal) < 0)
 	if (s3c24xx_register_clock(&clk_xtal) < 0)
 		printk(KERN_ERR "failed to register master xtal\n");
 		printk(KERN_ERR "failed to register master xtal\n");
 
 
+	if (s3c24xx_register_clock(&clk_mpll) < 0)
+		printk(KERN_ERR "failed to register mpll clock\n");
+
 	if (s3c24xx_register_clock(&clk_upll) < 0)
 	if (s3c24xx_register_clock(&clk_upll) < 0)
 		printk(KERN_ERR "failed to register upll clock\n");
 		printk(KERN_ERR "failed to register upll clock\n");
 
 

+ 2 - 0
arch/arm/mach-s3c2410/clock.h

@@ -42,7 +42,9 @@ extern struct clk clk_usb_bus;
 extern struct clk clk_f;
 extern struct clk clk_f;
 extern struct clk clk_h;
 extern struct clk clk_h;
 extern struct clk clk_p;
 extern struct clk clk_p;
+extern struct clk clk_mpll;
 extern struct clk clk_upll;
 extern struct clk clk_upll;
+extern struct clk clk_xtal;
 
 
 /* exports for arch/arm/mach-s3c2410
 /* exports for arch/arm/mach-s3c2410
  *
  *

+ 34 - 3
arch/arm/mach-s3c2410/cpu.c

@@ -44,6 +44,7 @@
 #include "clock.h"
 #include "clock.h"
 #include "s3c2400.h"
 #include "s3c2400.h"
 #include "s3c2410.h"
 #include "s3c2410.h"
+#include "s3c2412.h"
 #include "s3c244x.h"
 #include "s3c244x.h"
 #include "s3c2440.h"
 #include "s3c2440.h"
 #include "s3c2442.h"
 #include "s3c2442.h"
@@ -62,6 +63,7 @@ struct cpu_table {
 
 
 static const char name_s3c2400[]  = "S3C2400";
 static const char name_s3c2400[]  = "S3C2400";
 static const char name_s3c2410[]  = "S3C2410";
 static const char name_s3c2410[]  = "S3C2410";
+static const char name_s3c2412[]  = "S3C2412";
 static const char name_s3c2440[]  = "S3C2440";
 static const char name_s3c2440[]  = "S3C2440";
 static const char name_s3c2442[]  = "S3C2442";
 static const char name_s3c2442[]  = "S3C2442";
 static const char name_s3c2410a[] = "S3C2410A";
 static const char name_s3c2410a[] = "S3C2410A";
@@ -113,6 +115,15 @@ static struct cpu_table cpu_ids[] __initdata = {
 		.init		= s3c2442_init,
 		.init		= s3c2442_init,
 		.name		= name_s3c2442
 		.name		= name_s3c2442
 	},
 	},
+	{
+		.idcode		= 0x32412001,
+		.idmask		= 0xffffffff,
+		.map_io		= s3c2412_map_io,
+		.init_clocks	= s3c2412_init_clocks,
+		.init_uarts	= s3c2412_init_uarts,
+		.init		= s3c2412_init,
+		.name		= name_s3c2412,
+	},
 	{
 	{
 		.idcode		= 0x0,   /* S3C2400 doesn't have an idcode */
 		.idcode		= 0x0,   /* S3C2400 doesn't have an idcode */
 		.idmask		= 0xffffffff,
 		.idmask		= 0xffffffff,
@@ -171,6 +182,24 @@ void s3c24xx_set_board(struct s3c24xx_board *b)
 
 
 static struct cpu_table *cpu;
 static struct cpu_table *cpu;
 
 
+static unsigned long s3c24xx_read_idcode_v5(void)
+{
+#if defined(CONFIG_CPU_S3C2412) || defined(CONFIG_CPU_S3C2413)
+	return __raw_readl(S3C2412_GSTATUS1);
+#else
+	return 1UL;	/* don't look like an 2400 */
+#endif
+}
+
+static unsigned long s3c24xx_read_idcode_v4(void)
+{
+#ifndef CONFIG_CPU_S3C2400
+	return __raw_readl(S3C2410_GSTATUS1);
+#else
+	return 0UL;
+#endif
+}
+
 void __init s3c24xx_init_io(struct map_desc *mach_desc, int size)
 void __init s3c24xx_init_io(struct map_desc *mach_desc, int size)
 {
 {
 	unsigned long idcode = 0x0;
 	unsigned long idcode = 0x0;
@@ -178,9 +207,11 @@ void __init s3c24xx_init_io(struct map_desc *mach_desc, int size)
 	/* initialise the io descriptors we need for initialisation */
 	/* initialise the io descriptors we need for initialisation */
 	iotable_init(s3c_iodesc, ARRAY_SIZE(s3c_iodesc));
 	iotable_init(s3c_iodesc, ARRAY_SIZE(s3c_iodesc));
 
 
-#ifndef CONFIG_CPU_S3C2400
-	idcode = __raw_readl(S3C2410_GSTATUS1);
-#endif
+	if (cpu_architecture() >= CPU_ARCH_ARMv5) {
+		idcode = s3c24xx_read_idcode_v5();
+	} else {
+		idcode = s3c24xx_read_idcode_v4();
+	}
 
 
 	cpu = s3c_lookup_cpu(idcode);
 	cpu = s3c_lookup_cpu(idcode);
 
 

+ 1 - 0
arch/arm/mach-s3c2410/cpu.h

@@ -74,5 +74,6 @@ extern struct sys_timer s3c24xx_timer;
 /* system device classes */
 /* system device classes */
 
 
 extern struct sysdev_class s3c2410_sysclass;
 extern struct sysdev_class s3c2410_sysclass;
+extern struct sysdev_class s3c2412_sysclass;
 extern struct sysdev_class s3c2440_sysclass;
 extern struct sysdev_class s3c2440_sysclass;
 extern struct sysdev_class s3c2442_sysclass;
 extern struct sysdev_class s3c2442_sysclass;

+ 37 - 20
arch/arm/mach-s3c2410/irq.c

@@ -191,13 +191,9 @@ static struct irqchip s3c_irq_chip = {
 	.ack	   = s3c_irq_ack,
 	.ack	   = s3c_irq_ack,
 	.mask	   = s3c_irq_mask,
 	.mask	   = s3c_irq_mask,
 	.unmask	   = s3c_irq_unmask,
 	.unmask	   = s3c_irq_unmask,
-	.set_wake	   = s3c_irq_wake
+	.set_wake  = s3c_irq_wake
 };
 };
 
 
-/* S3C2410_EINTMASK
- * S3C2410_EINTPEND
- */
-
 static void
 static void
 s3c_irqext_mask(unsigned int irqno)
 s3c_irqext_mask(unsigned int irqno)
 {
 {
@@ -205,9 +201,9 @@ s3c_irqext_mask(unsigned int irqno)
 
 
 	irqno -= EXTINT_OFF;
 	irqno -= EXTINT_OFF;
 
 
-	mask = __raw_readl(S3C2410_EINTMASK);
+	mask = __raw_readl(S3C24XX_EINTMASK);
 	mask |= ( 1UL << irqno);
 	mask |= ( 1UL << irqno);
-	__raw_writel(mask, S3C2410_EINTMASK);
+	__raw_writel(mask, S3C24XX_EINTMASK);
 
 
 	if (irqno <= (IRQ_EINT7 - EXTINT_OFF)) {
 	if (irqno <= (IRQ_EINT7 - EXTINT_OFF)) {
 		/* check to see if all need masking */
 		/* check to see if all need masking */
@@ -232,11 +228,11 @@ s3c_irqext_ack(unsigned int irqno)
 	bit = 1UL << (irqno - EXTINT_OFF);
 	bit = 1UL << (irqno - EXTINT_OFF);
 
 
 
 
-	mask = __raw_readl(S3C2410_EINTMASK);
+	mask = __raw_readl(S3C24XX_EINTMASK);
 
 
-	__raw_writel(bit, S3C2410_EINTPEND);
+	__raw_writel(bit, S3C24XX_EINTPEND);
 
 
-	req = __raw_readl(S3C2410_EINTPEND);
+	req = __raw_readl(S3C24XX_EINTPEND);
 	req &= ~mask;
 	req &= ~mask;
 
 
 	/* not sure if we should be acking the parent irq... */
 	/* not sure if we should be acking the parent irq... */
@@ -257,9 +253,9 @@ s3c_irqext_unmask(unsigned int irqno)
 
 
 	irqno -= EXTINT_OFF;
 	irqno -= EXTINT_OFF;
 
 
-	mask = __raw_readl(S3C2410_EINTMASK);
+	mask = __raw_readl(S3C24XX_EINTMASK);
 	mask &= ~( 1UL << irqno);
 	mask &= ~( 1UL << irqno);
-	__raw_writel(mask, S3C2410_EINTMASK);
+	__raw_writel(mask, S3C24XX_EINTMASK);
 
 
 	s3c_irq_unmask((irqno <= (IRQ_EINT7 - EXTINT_OFF)) ? IRQ_EINT4t7 : IRQ_EINT8t23);
 	s3c_irq_unmask((irqno <= (IRQ_EINT7 - EXTINT_OFF)) ? IRQ_EINT4t7 : IRQ_EINT8t23);
 }
 }
@@ -275,28 +271,28 @@ s3c_irqext_type(unsigned int irq, unsigned int type)
 	if ((irq >= IRQ_EINT0) && (irq <= IRQ_EINT3))
 	if ((irq >= IRQ_EINT0) && (irq <= IRQ_EINT3))
 	{
 	{
 		gpcon_reg = S3C2410_GPFCON;
 		gpcon_reg = S3C2410_GPFCON;
-		extint_reg = S3C2410_EXTINT0;
+		extint_reg = S3C24XX_EXTINT0;
 		gpcon_offset = (irq - IRQ_EINT0) * 2;
 		gpcon_offset = (irq - IRQ_EINT0) * 2;
 		extint_offset = (irq - IRQ_EINT0) * 4;
 		extint_offset = (irq - IRQ_EINT0) * 4;
 	}
 	}
 	else if ((irq >= IRQ_EINT4) && (irq <= IRQ_EINT7))
 	else if ((irq >= IRQ_EINT4) && (irq <= IRQ_EINT7))
 	{
 	{
 		gpcon_reg = S3C2410_GPFCON;
 		gpcon_reg = S3C2410_GPFCON;
-		extint_reg = S3C2410_EXTINT0;
+		extint_reg = S3C24XX_EXTINT0;
 		gpcon_offset = (irq - (EXTINT_OFF)) * 2;
 		gpcon_offset = (irq - (EXTINT_OFF)) * 2;
 		extint_offset = (irq - (EXTINT_OFF)) * 4;
 		extint_offset = (irq - (EXTINT_OFF)) * 4;
 	}
 	}
 	else if ((irq >= IRQ_EINT8) && (irq <= IRQ_EINT15))
 	else if ((irq >= IRQ_EINT8) && (irq <= IRQ_EINT15))
 	{
 	{
 		gpcon_reg = S3C2410_GPGCON;
 		gpcon_reg = S3C2410_GPGCON;
-		extint_reg = S3C2410_EXTINT1;
+		extint_reg = S3C24XX_EXTINT1;
 		gpcon_offset = (irq - IRQ_EINT8) * 2;
 		gpcon_offset = (irq - IRQ_EINT8) * 2;
 		extint_offset = (irq - IRQ_EINT8) * 4;
 		extint_offset = (irq - IRQ_EINT8) * 4;
 	}
 	}
 	else if ((irq >= IRQ_EINT16) && (irq <= IRQ_EINT23))
 	else if ((irq >= IRQ_EINT16) && (irq <= IRQ_EINT23))
 	{
 	{
 		gpcon_reg = S3C2410_GPGCON;
 		gpcon_reg = S3C2410_GPGCON;
-		extint_reg = S3C2410_EXTINT2;
+		extint_reg = S3C24XX_EXTINT2;
 		gpcon_offset = (irq - IRQ_EINT8) * 2;
 		gpcon_offset = (irq - IRQ_EINT8) * 2;
 		extint_offset = (irq - IRQ_EINT16) * 4;
 		extint_offset = (irq - IRQ_EINT16) * 4;
 	} else
 	} else
@@ -572,6 +568,23 @@ s3c_irq_demux_uart2(unsigned int irq,
 	s3c_irq_demux_uart(IRQ_S3CUART_RX2, regs);
 	s3c_irq_demux_uart(IRQ_S3CUART_RX2, regs);
 }
 }
 
 
+static void
+s3c_irq_demux_extint(unsigned int irq,
+		     struct irqdesc *desc,
+		     struct pt_regs *regs)
+{
+	unsigned long eintpnd = __raw_readl(S3C24XX_EINTPEND);
+	unsigned long eintmsk = __raw_readl(S3C24XX_EINTMASK);
+
+	eintpnd &= ~eintmsk;
+
+	if (eintpnd) {
+		irq = fls(eintpnd);
+		irq += (IRQ_EINT4 - (4 + 1));
+
+		desc_handle_irq(irq, irq_desc + irq, regs);
+	}
+}
 
 
 /* s3c24xx_init_irq
 /* s3c24xx_init_irq
  *
  *
@@ -591,12 +604,12 @@ void __init s3c24xx_init_irq(void)
 
 
 	last = 0;
 	last = 0;
 	for (i = 0; i < 4; i++) {
 	for (i = 0; i < 4; i++) {
-		pend = __raw_readl(S3C2410_EINTPEND);
+		pend = __raw_readl(S3C24XX_EINTPEND);
 
 
 		if (pend == 0 || pend == last)
 		if (pend == 0 || pend == last)
 			break;
 			break;
 
 
-		__raw_writel(pend, S3C2410_EINTPEND);
+		__raw_writel(pend, S3C24XX_EINTPEND);
 		printk("irq: clearing pending ext status %08x\n", (int)pend);
 		printk("irq: clearing pending ext status %08x\n", (int)pend);
 		last = pend;
 		last = pend;
 	}
 	}
@@ -630,12 +643,14 @@ void __init s3c24xx_init_irq(void)
 
 
 	irqdbf("s3c2410_init_irq: registering s3c2410 interrupt handlers\n");
 	irqdbf("s3c2410_init_irq: registering s3c2410 interrupt handlers\n");
 
 
-	for (irqno = IRQ_BATT_FLT; irqno <= IRQ_ADCPARENT; irqno++) {
+	for (irqno = IRQ_EINT4t7; irqno <= IRQ_ADCPARENT; irqno++) {
 		/* set all the s3c2410 internal irqs */
 		/* set all the s3c2410 internal irqs */
 
 
 		switch (irqno) {
 		switch (irqno) {
 			/* deal with the special IRQs (cascaded) */
 			/* deal with the special IRQs (cascaded) */
 
 
+		case IRQ_EINT4t7:
+		case IRQ_EINT8t23:
 		case IRQ_UART0:
 		case IRQ_UART0:
 		case IRQ_UART1:
 		case IRQ_UART1:
 		case IRQ_UART2:
 		case IRQ_UART2:
@@ -659,12 +674,14 @@ void __init s3c24xx_init_irq(void)
 
 
 	/* setup the cascade irq handlers */
 	/* setup the cascade irq handlers */
 
 
+	set_irq_chained_handler(IRQ_EINT4t7, s3c_irq_demux_extint);
+	set_irq_chained_handler(IRQ_EINT8t23, s3c_irq_demux_extint);
+
 	set_irq_chained_handler(IRQ_UART0, s3c_irq_demux_uart0);
 	set_irq_chained_handler(IRQ_UART0, s3c_irq_demux_uart0);
 	set_irq_chained_handler(IRQ_UART1, s3c_irq_demux_uart1);
 	set_irq_chained_handler(IRQ_UART1, s3c_irq_demux_uart1);
 	set_irq_chained_handler(IRQ_UART2, s3c_irq_demux_uart2);
 	set_irq_chained_handler(IRQ_UART2, s3c_irq_demux_uart2);
 	set_irq_chained_handler(IRQ_ADCPARENT, s3c_irq_demux_adc);
 	set_irq_chained_handler(IRQ_ADCPARENT, s3c_irq_demux_adc);
 
 
-
 	/* external interrupts */
 	/* external interrupts */
 
 
 	for (irqno = IRQ_EINT0; irqno <= IRQ_EINT3; irqno++) {
 	for (irqno = IRQ_EINT0; irqno <= IRQ_EINT3; irqno++) {

+ 126 - 0
arch/arm/mach-s3c2410/mach-smdk2413.c

@@ -0,0 +1,126 @@
+/* linux/arch/arm/mach-s3c2410/mach-smdk2413.c
+ *
+ * Copyright (c) 2006 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * Thanks to Dimity Andric (TomTom) and Steven Ryu (Samsung) for the
+ * loans of SMDK2413 to work with.
+ *
+ * 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/platform_device.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <asm/hardware.h>
+#include <asm/hardware/iomd.h>
+#include <asm/setup.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/mach-types.h>
+
+//#include <asm/debug-ll.h>
+#include <asm/arch/regs-serial.h>
+#include <asm/arch/regs-gpio.h>
+#include <asm/arch/regs-lcd.h>
+
+#include <asm/arch/idle.h>
+#include <asm/arch/fb.h>
+
+#include "s3c2410.h"
+#include "s3c2412.h"
+#include "clock.h"
+#include "devs.h"
+#include "cpu.h"
+
+#include "common-smdk.h"
+
+static struct map_desc smdk2413_iodesc[] __initdata = {
+};
+
+static struct s3c2410_uartcfg smdk2413_uartcfgs[] __initdata = {
+	[0] = {
+		.hwport	     = 0,
+		.flags	     = 0,
+		.ucon	     = 0x3c5,
+		.ulcon	     = 0x03,
+		.ufcon	     = 0x51,
+	},
+	[1] = {
+		.hwport	     = 1,
+		.flags	     = 0,
+		.ucon	     = 0x3c5,
+		.ulcon	     = 0x03,
+		.ufcon	     = 0x51,
+	},
+	/* IR port */
+	[2] = {
+		.hwport	     = 2,
+		.flags	     = 0,
+		.ucon	     = 0x3c5,
+		.ulcon	     = 0x43,
+		.ufcon	     = 0x51,
+	}
+};
+
+static struct platform_device *smdk2413_devices[] __initdata = {
+	&s3c_device_usb,
+	//&s3c_device_lcd,
+	&s3c_device_wdt,
+	&s3c_device_i2c,
+	&s3c_device_iis,
+};
+
+static struct s3c24xx_board smdk2413_board __initdata = {
+	.devices       = smdk2413_devices,
+	.devices_count = ARRAY_SIZE(smdk2413_devices)
+};
+
+static void __init smdk2413_fixup(struct machine_desc *desc,
+				  struct tag *tags, char **cmdline,
+				  struct meminfo *mi)
+{
+	if (tags != phys_to_virt(S3C2410_SDRAM_PA + 0x100)) {
+		mi->nr_banks=1;
+		mi->bank[0].start = 0x30000000;
+		mi->bank[0].size = SZ_64M;
+		mi->bank[0].node = 0;
+	}
+}
+
+static void __init smdk2413_map_io(void)
+{
+	s3c24xx_init_io(smdk2413_iodesc, ARRAY_SIZE(smdk2413_iodesc));
+	s3c24xx_init_clocks(12000000);
+	s3c24xx_init_uarts(smdk2413_uartcfgs, ARRAY_SIZE(smdk2413_uartcfgs));
+	s3c24xx_set_board(&smdk2413_board);
+}
+
+static void __init smdk2413_machine_init(void)
+{
+	smdk_machine_init();
+}
+
+MACHINE_START(S3C2413, "SMDK2413")
+	/* Maintainer: Ben Dooks <ben@fluff.org> */
+	.phys_io	= S3C2410_PA_UART,
+	.io_pg_offst	= (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
+	.boot_params	= S3C2410_SDRAM_PA + 0x100,
+
+	.fixup		= smdk2413_fixup,
+	.init_irq	= s3c24xx_init_irq,
+	.map_io		= smdk2413_map_io,
+	.init_machine	= smdk2413_machine_init,
+	.timer		= &s3c24xx_timer,
+MACHINE_END

+ 2 - 1
arch/arm/mach-s3c2410/pm-simtec.c

@@ -48,7 +48,8 @@ static __init int pm_simtec_init(void)
 
 
 	/* check which machine we are running on */
 	/* check which machine we are running on */
 
 
-	if (!machine_is_bast() && !machine_is_vr1000() && !machine_is_anubis())
+	if (!machine_is_bast() && !machine_is_vr1000() &&
+	    !machine_is_anubis() && !machine_is_osiris())
 		return 0;
 		return 0;
 
 
 	printk(KERN_INFO "Simtec Board Power Manangement" COPYRIGHT "\n");
 	printk(KERN_INFO "Simtec Board Power Manangement" COPYRIGHT "\n");

+ 9 - 1
arch/arm/mach-s3c2410/s3c2410-clock.c

@@ -182,7 +182,15 @@ static struct clk init_clocks[] = {
 		.id		= -1,
 		.id		= -1,
 		.parent		= &clk_p,
 		.parent		= &clk_p,
 		.ctrlbit	= 0,
 		.ctrlbit	= 0,
-	}
+	}, {
+		.name		= "usb-bus-host",
+		.id		= -1,
+		.parent		= &clk_usb_bus,
+	}, {
+		.name		= "usb-bus-gadget",
+		.id		= -1,
+		.parent		= &clk_usb_bus,
+	},
 };
 };
 
 
 /* s3c2410_baseclk_add()
 /* s3c2410_baseclk_add()

+ 5 - 8
arch/arm/mach-s3c2410/s3c2410-gpio.c

@@ -18,9 +18,6 @@
  * You should have received a copy of the GNU General Public License
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- * Changelog
- *	15-Jan-2006  LCVR  Splitted from gpio.c
  */
  */
 
 
 #include <linux/kernel.h>
 #include <linux/kernel.h>
@@ -38,7 +35,7 @@
 int s3c2410_gpio_irqfilter(unsigned int pin, unsigned int on,
 int s3c2410_gpio_irqfilter(unsigned int pin, unsigned int on,
 			   unsigned int config)
 			   unsigned int config)
 {
 {
-	void __iomem *reg = S3C2410_EINFLT0;
+	void __iomem *reg = S3C24XX_EINFLT0;
 	unsigned long flags;
 	unsigned long flags;
 	unsigned long val;
 	unsigned long val;
 
 
@@ -47,7 +44,7 @@ int s3c2410_gpio_irqfilter(unsigned int pin, unsigned int on,
 
 
 	config &= 0xff;
 	config &= 0xff;
 
 
-	pin -= S3C2410_GPG8_EINT16;
+	pin -= S3C2410_GPG8;
 	reg += pin & ~3;
 	reg += pin & ~3;
 
 
 	local_irq_save(flags);
 	local_irq_save(flags);
@@ -61,10 +58,10 @@ int s3c2410_gpio_irqfilter(unsigned int pin, unsigned int on,
 
 
 	/* update filter enable */
 	/* update filter enable */
 
 
-	val = __raw_readl(S3C2410_EXTINT2);
+	val = __raw_readl(S3C24XX_EXTINT2);
 	val &= ~(1 << ((pin * 4) + 3));
 	val &= ~(1 << ((pin * 4) + 3));
 	val |= on << ((pin * 4) + 3);
 	val |= on << ((pin * 4) + 3);
-	__raw_writel(val, S3C2410_EXTINT2);
+	__raw_writel(val, S3C24XX_EXTINT2);
 
 
 	local_irq_restore(flags);
 	local_irq_restore(flags);
 
 
@@ -75,7 +72,7 @@ EXPORT_SYMBOL(s3c2410_gpio_irqfilter);
 
 
 int s3c2410_gpio_getirq(unsigned int pin)
 int s3c2410_gpio_getirq(unsigned int pin)
 {
 {
-	if (pin < S3C2410_GPF0 || pin > S3C2410_GPG15_EINT23)
+	if (pin < S3C2410_GPF0 || pin > S3C2410_GPG15)
 		return -1;	/* not valid interrupts */
 		return -1;	/* not valid interrupts */
 
 
 	if (pin < S3C2410_GPG0 && pin > S3C2410_GPF7)
 	if (pin < S3C2410_GPG0 && pin > S3C2410_GPF7)

+ 711 - 0
arch/arm/mach-s3c2410/s3c2412-clock.c

@@ -0,0 +1,711 @@
+/* linux/arch/arm/mach-s3c2410/s3c2412-clock.c
+ *
+ * Copyright (c) 2006 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * S3C2412,S3C2413 Clock control support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/sysdev.h>
+#include <linux/clk.h>
+#include <linux/mutex.h>
+#include <linux/delay.h>
+
+#include <asm/hardware.h>
+#include <asm/io.h>
+
+#include <asm/arch/regs-clock.h>
+#include <asm/arch/regs-gpio.h>
+
+#include "clock.h"
+#include "cpu.h"
+
+/* We currently have to assume that the system is running
+ * from the XTPll input, and that all ***REFCLKs are being
+ * fed from it, as we cannot read the state of OM[4] from
+ * software.
+ *
+ * It would be possible for each board initialisation to
+ * set the correct muxing at initialisation
+*/
+
+int s3c2412_clkcon_enable(struct clk *clk, int enable)
+{
+	unsigned int clocks = clk->ctrlbit;
+	unsigned long clkcon;
+
+	clkcon = __raw_readl(S3C2410_CLKCON);
+
+	if (enable)
+		clkcon |= clocks;
+	else
+		clkcon &= ~clocks;
+
+	__raw_writel(clkcon, S3C2410_CLKCON);
+
+	return 0;
+}
+
+static int s3c2412_upll_enable(struct clk *clk, int enable)
+{
+	unsigned long upllcon = __raw_readl(S3C2410_UPLLCON);
+	unsigned long orig = upllcon;
+
+	if (!enable)
+		upllcon |= S3C2412_PLLCON_OFF;
+	else
+		upllcon &= ~S3C2412_PLLCON_OFF;
+
+	__raw_writel(upllcon, S3C2410_UPLLCON);
+
+	/* allow ~150uS for the PLL to settle and lock */
+
+	if (enable && (orig & S3C2412_PLLCON_OFF))
+		udelay(150);
+
+	return 0;
+}
+
+/* clock selections */
+
+/* CPU EXTCLK input */
+static struct clk clk_ext = {
+	.name		= "extclk",
+	.id		= -1,
+};
+
+static struct clk clk_erefclk = {
+	.name		= "erefclk",
+	.id		= -1,
+};
+
+static struct clk clk_urefclk = {
+	.name		= "urefclk",
+	.id		= -1,
+};
+
+static int s3c2412_setparent_usysclk(struct clk *clk, struct clk *parent)
+{
+	unsigned long clksrc = __raw_readl(S3C2412_CLKSRC);
+
+	if (parent == &clk_urefclk)
+		clksrc &= ~S3C2412_CLKSRC_USYSCLK_UPLL;
+	else if (parent == &clk_upll)
+		clksrc |= S3C2412_CLKSRC_USYSCLK_UPLL;
+	else
+		return -EINVAL;
+
+	clk->parent = parent;
+
+	__raw_writel(clksrc, S3C2412_CLKSRC);
+	return 0;
+}
+
+static struct clk clk_usysclk = {
+	.name		= "usysclk",
+	.id		= -1,
+	.parent		= &clk_xtal,
+	.set_parent	= s3c2412_setparent_usysclk,
+};
+
+static struct clk clk_mrefclk = {
+	.name		= "mrefclk",
+	.parent		= &clk_xtal,
+	.id		= -1,
+};
+
+static struct clk clk_mdivclk = {
+	.name		= "mdivclk",
+	.parent		= &clk_xtal,
+	.id		= -1,
+};
+
+static int s3c2412_setparent_usbsrc(struct clk *clk, struct clk *parent)
+{
+	unsigned long clksrc = __raw_readl(S3C2412_CLKSRC);
+
+	if (parent == &clk_usysclk)
+		clksrc &= ~S3C2412_CLKSRC_USBCLK_HCLK;
+	else if (parent == &clk_h)
+		clksrc |= S3C2412_CLKSRC_USBCLK_HCLK;
+	else
+		return -EINVAL;
+
+	clk->parent = parent;
+
+	__raw_writel(clksrc, S3C2412_CLKSRC);
+	return 0;
+}
+
+static unsigned long s3c2412_roundrate_usbsrc(struct clk *clk,
+					      unsigned long rate)
+{
+	unsigned long parent_rate = clk_get_rate(clk->parent);
+	int div;
+
+	if (rate > parent_rate)
+		return parent_rate;
+
+	div = parent_rate / rate;
+	if (div > 2)
+		div = 2;
+
+	return parent_rate / div;
+}
+
+static unsigned long s3c2412_getrate_usbsrc(struct clk *clk)
+{
+	unsigned long parent_rate = clk_get_rate(clk->parent);
+	unsigned long div = __raw_readl(S3C2410_CLKDIVN);
+
+	return parent_rate / ((div & S3C2412_CLKDIVN_USB48DIV) ? 2 : 1);
+}
+
+static int s3c2412_setrate_usbsrc(struct clk *clk, unsigned long rate)
+{
+	unsigned long parent_rate = clk_get_rate(clk->parent);
+	unsigned long clkdivn = __raw_readl(S3C2410_CLKDIVN);
+
+	rate = s3c2412_roundrate_usbsrc(clk, rate);
+
+	if ((parent_rate / rate) == 2)
+		clkdivn |= S3C2412_CLKDIVN_USB48DIV;
+	else
+		clkdivn &= ~S3C2412_CLKDIVN_USB48DIV;
+
+	__raw_writel(clkdivn, S3C2410_CLKDIVN);
+	return 0;
+}
+
+static struct clk clk_usbsrc = {
+	.name		= "usbsrc",
+	.id		= -1,
+	.get_rate	= s3c2412_getrate_usbsrc,
+	.set_rate	= s3c2412_setrate_usbsrc,
+	.round_rate	= s3c2412_roundrate_usbsrc,
+	.set_parent	= s3c2412_setparent_usbsrc,
+};
+
+static int s3c2412_setparent_msysclk(struct clk *clk, struct clk *parent)
+{
+	unsigned long clksrc = __raw_readl(S3C2412_CLKSRC);
+
+	if (parent == &clk_mdivclk)
+		clksrc &= ~S3C2412_CLKSRC_MSYSCLK_MPLL;
+	else if (parent == &clk_upll)
+		clksrc |= S3C2412_CLKSRC_MSYSCLK_MPLL;
+	else
+		return -EINVAL;
+
+	clk->parent = parent;
+
+	__raw_writel(clksrc, S3C2412_CLKSRC);
+	return 0;
+}
+
+static struct clk clk_msysclk = {
+	.name		= "msysclk",
+	.id		= -1,
+	.set_parent	= s3c2412_setparent_msysclk,
+};
+
+/* these next clocks have an divider immediately after them,
+ * so we can register them with their divider and leave out the
+ * intermediate clock stage
+*/
+static unsigned long s3c2412_roundrate_clksrc(struct clk *clk,
+					      unsigned long rate)
+{
+	unsigned long parent_rate = clk_get_rate(clk->parent);
+	int div;
+
+	if (rate > parent_rate)
+		return parent_rate;
+
+	/* note, we remove the +/- 1 calculations as they cancel out */
+
+	div = (rate / parent_rate);
+
+	if (div < 1)
+		div = 1;
+	else if (div > 16)
+		div = 16;
+
+	return parent_rate / div;
+}
+
+static int s3c2412_setparent_uart(struct clk *clk, struct clk *parent)
+{
+	unsigned long clksrc = __raw_readl(S3C2412_CLKSRC);
+
+	if (parent == &clk_erefclk)
+		clksrc &= ~S3C2412_CLKSRC_UARTCLK_MPLL;
+	else if (parent == &clk_mpll)
+		clksrc |= S3C2412_CLKSRC_UARTCLK_MPLL;
+	else
+		return -EINVAL;
+
+	clk->parent = parent;
+
+	__raw_writel(clksrc, S3C2412_CLKSRC);
+	return 0;
+}
+
+static unsigned long s3c2412_getrate_uart(struct clk *clk)
+{
+	unsigned long parent_rate = clk_get_rate(clk->parent);
+	unsigned long div = __raw_readl(S3C2410_CLKDIVN);
+
+	div &= S3C2412_CLKDIVN_UARTDIV_MASK;
+	div >>= S3C2412_CLKDIVN_UARTDIV_SHIFT;
+
+	return parent_rate / (div + 1);
+}
+
+static int s3c2412_setrate_uart(struct clk *clk, unsigned long rate)
+{
+	unsigned long parent_rate = clk_get_rate(clk->parent);
+	unsigned long clkdivn = __raw_readl(S3C2410_CLKDIVN);
+
+	rate = s3c2412_roundrate_clksrc(clk, rate);
+
+	clkdivn &= ~S3C2412_CLKDIVN_UARTDIV_MASK;
+	clkdivn |= ((parent_rate / rate) - 1) << S3C2412_CLKDIVN_UARTDIV_SHIFT;
+
+	__raw_writel(clkdivn, S3C2410_CLKDIVN);
+	return 0;
+}
+
+static struct clk clk_uart = {
+	.name		= "uartclk",
+	.id		= -1,
+	.get_rate	= s3c2412_getrate_uart,
+	.set_rate	= s3c2412_setrate_uart,
+	.set_parent	= s3c2412_setparent_uart,
+	.round_rate	= s3c2412_roundrate_clksrc,
+};
+
+static int s3c2412_setparent_i2s(struct clk *clk, struct clk *parent)
+{
+	unsigned long clksrc = __raw_readl(S3C2412_CLKSRC);
+
+	if (parent == &clk_erefclk)
+		clksrc &= ~S3C2412_CLKSRC_I2SCLK_MPLL;
+	else if (parent == &clk_mpll)
+		clksrc |= S3C2412_CLKSRC_I2SCLK_MPLL;
+	else
+		return -EINVAL;
+
+	clk->parent = parent;
+
+	__raw_writel(clksrc, S3C2412_CLKSRC);
+	return 0;
+}
+
+static unsigned long s3c2412_getrate_i2s(struct clk *clk)
+{
+	unsigned long parent_rate = clk_get_rate(clk->parent);
+	unsigned long div = __raw_readl(S3C2410_CLKDIVN);
+
+	div &= S3C2412_CLKDIVN_I2SDIV_MASK;
+	div >>= S3C2412_CLKDIVN_I2SDIV_SHIFT;
+
+	return parent_rate / (div + 1);
+}
+
+static int s3c2412_setrate_i2s(struct clk *clk, unsigned long rate)
+{
+	unsigned long parent_rate = clk_get_rate(clk->parent);
+	unsigned long clkdivn = __raw_readl(S3C2410_CLKDIVN);
+
+	rate = s3c2412_roundrate_clksrc(clk, rate);
+
+	clkdivn &= ~S3C2412_CLKDIVN_I2SDIV_MASK;
+	clkdivn |= ((parent_rate / rate) - 1) << S3C2412_CLKDIVN_I2SDIV_SHIFT;
+
+	__raw_writel(clkdivn, S3C2410_CLKDIVN);
+	return 0;
+}
+
+static struct clk clk_i2s = {
+	.name		= "i2sclk",
+	.id		= -1,
+	.get_rate	= s3c2412_getrate_i2s,
+	.set_rate	= s3c2412_setrate_i2s,
+	.set_parent	= s3c2412_setparent_i2s,
+	.round_rate	= s3c2412_roundrate_clksrc,
+};
+
+static int s3c2412_setparent_cam(struct clk *clk, struct clk *parent)
+{
+	unsigned long clksrc = __raw_readl(S3C2412_CLKSRC);
+
+	if (parent == &clk_usysclk)
+		clksrc &= ~S3C2412_CLKSRC_CAMCLK_HCLK;
+	else if (parent == &clk_h)
+		clksrc |= S3C2412_CLKSRC_CAMCLK_HCLK;
+	else
+		return -EINVAL;
+
+	clk->parent = parent;
+
+	__raw_writel(clksrc, S3C2412_CLKSRC);
+	return 0;
+}
+static unsigned long s3c2412_getrate_cam(struct clk *clk)
+{
+	unsigned long parent_rate = clk_get_rate(clk->parent);
+	unsigned long div = __raw_readl(S3C2410_CLKDIVN);
+
+	div &= S3C2412_CLKDIVN_CAMDIV_MASK;
+	div >>= S3C2412_CLKDIVN_CAMDIV_SHIFT;
+
+	return parent_rate / (div + 1);
+}
+
+static int s3c2412_setrate_cam(struct clk *clk, unsigned long rate)
+{
+	unsigned long parent_rate = clk_get_rate(clk->parent);
+	unsigned long clkdivn = __raw_readl(S3C2410_CLKDIVN);
+
+	rate = s3c2412_roundrate_clksrc(clk, rate);
+
+	clkdivn &= ~S3C2412_CLKDIVN_CAMDIV_MASK;
+	clkdivn |= ((parent_rate / rate) - 1) << S3C2412_CLKDIVN_CAMDIV_SHIFT;
+
+	__raw_writel(clkdivn, S3C2410_CLKDIVN);
+	return 0;
+}
+
+static struct clk clk_cam = {
+	.name		= "camif-upll",	/* same as 2440 name */
+	.id		= -1,
+	.get_rate	= s3c2412_getrate_cam,
+	.set_rate	= s3c2412_setrate_cam,
+	.set_parent	= s3c2412_setparent_cam,
+	.round_rate	= s3c2412_roundrate_clksrc,
+};
+
+/* standard clock definitions */
+
+static struct clk init_clocks_disable[] = {
+	{
+		.name		= "nand",
+		.id		= -1,
+		.parent		= &clk_h,
+		.enable		= s3c2412_clkcon_enable,
+		.ctrlbit	= S3C2412_CLKCON_NAND,
+	}, {
+		.name		= "sdi",
+		.id		= -1,
+		.parent		= &clk_p,
+		.enable		= s3c2412_clkcon_enable,
+		.ctrlbit	= S3C2412_CLKCON_SDI,
+	}, {
+		.name		= "adc",
+		.id		= -1,
+		.parent		= &clk_p,
+		.enable		= s3c2412_clkcon_enable,
+		.ctrlbit	= S3C2412_CLKCON_ADC,
+	}, {
+		.name		= "i2c",
+		.id		= -1,
+		.parent		= &clk_p,
+		.enable		= s3c2412_clkcon_enable,
+		.ctrlbit	= S3C2412_CLKCON_IIC,
+	}, {
+		.name		= "iis",
+		.id		= -1,
+		.parent		= &clk_p,
+		.enable		= s3c2412_clkcon_enable,
+		.ctrlbit	= S3C2412_CLKCON_IIS,
+	}, {
+		.name		= "spi",
+		.id		= -1,
+		.parent		= &clk_p,
+		.enable		= s3c2412_clkcon_enable,
+		.ctrlbit	= S3C2412_CLKCON_SPI,
+	}
+};
+
+static struct clk init_clocks[] = {
+	{
+		.name		= "dma",
+		.id		= 0,
+		.parent		= &clk_h,
+		.enable		= s3c2412_clkcon_enable,
+		.ctrlbit	= S3C2412_CLKCON_DMA0,
+	}, {
+		.name		= "dma",
+		.id		= 1,
+		.parent		= &clk_h,
+		.enable		= s3c2412_clkcon_enable,
+		.ctrlbit	= S3C2412_CLKCON_DMA1,
+	}, {
+		.name		= "dma",
+		.id		= 2,
+		.parent		= &clk_h,
+		.enable		= s3c2412_clkcon_enable,
+		.ctrlbit	= S3C2412_CLKCON_DMA2,
+	}, {
+		.name		= "dma",
+		.id		= 3,
+		.parent		= &clk_h,
+		.enable		= s3c2412_clkcon_enable,
+		.ctrlbit	= S3C2412_CLKCON_DMA3,
+	}, {
+		.name		= "lcd",
+		.id		= -1,
+		.parent		= &clk_h,
+		.enable		= s3c2412_clkcon_enable,
+		.ctrlbit	= S3C2412_CLKCON_LCDC,
+	}, {
+		.name		= "gpio",
+		.id		= -1,
+		.parent		= &clk_p,
+		.enable		= s3c2412_clkcon_enable,
+		.ctrlbit	= S3C2412_CLKCON_GPIO,
+	}, {
+		.name		= "usb-host",
+		.id		= -1,
+		.parent		= &clk_h,
+		.enable		= s3c2412_clkcon_enable,
+		.ctrlbit	= S3C2412_CLKCON_USBH,
+	}, {
+		.name		= "usb-device",
+		.id		= -1,
+		.parent		= &clk_h,
+		.enable		= s3c2412_clkcon_enable,
+		.ctrlbit	= S3C2412_CLKCON_USBD,
+	}, {
+		.name		= "timers",
+		.id		= -1,
+		.parent		= &clk_p,
+		.enable		= s3c2412_clkcon_enable,
+		.ctrlbit	= S3C2412_CLKCON_PWMT,
+	}, {
+		.name		= "uart",
+		.id		= 0,
+		.parent		= &clk_p,
+		.enable		= s3c2412_clkcon_enable,
+		.ctrlbit	= S3C2412_CLKCON_UART0,
+	}, {
+		.name		= "uart",
+		.id		= 1,
+		.parent		= &clk_p,
+		.enable		= s3c2412_clkcon_enable,
+		.ctrlbit	= S3C2412_CLKCON_UART1,
+	}, {
+		.name		= "uart",
+		.id		= 2,
+		.parent		= &clk_p,
+		.enable		= s3c2412_clkcon_enable,
+		.ctrlbit	= S3C2412_CLKCON_UART2,
+	}, {
+		.name		= "rtc",
+		.id		= -1,
+		.parent		= &clk_p,
+		.enable		= s3c2412_clkcon_enable,
+		.ctrlbit	= S3C2412_CLKCON_RTC,
+	}, {
+		.name		= "watchdog",
+		.id		= -1,
+		.parent		= &clk_p,
+		.ctrlbit	= 0,
+	}, {
+		.name		= "usb-bus-gadget",
+		.id		= -1,
+		.parent		= &clk_usb_bus,
+		.enable		= s3c2412_clkcon_enable,
+		.ctrlbit	= S3C2412_CLKCON_USB_DEV48,
+	}, {
+		.name		= "usb-bus-host",
+		.id		= -1,
+		.parent		= &clk_usb_bus,
+		.enable		= s3c2412_clkcon_enable,
+		.ctrlbit	= S3C2412_CLKCON_USB_HOST48,
+	}
+};
+
+/* clocks to add where we need to check their parentage */
+
+struct clk_init {
+	struct clk	*clk;
+	unsigned int	 bit;
+	struct clk	*src_0;
+	struct clk	*src_1;
+};
+
+struct clk_init clks_src[] __initdata = {
+	{
+		.clk	= &clk_usysclk,
+		.bit	= S3C2412_CLKSRC_USBCLK_HCLK,
+		.src_0	= &clk_urefclk,
+		.src_1	= &clk_upll,
+	}, {
+		.clk	= &clk_i2s,
+		.bit	= S3C2412_CLKSRC_I2SCLK_MPLL,
+		.src_0	= &clk_erefclk,
+		.src_1	= &clk_mpll,
+	}, {
+		.clk	= &clk_cam,
+		.bit	= S3C2412_CLKSRC_CAMCLK_HCLK,
+		.src_0	= &clk_usysclk,
+		.src_1	= &clk_h,
+	}, {
+		.clk	= &clk_msysclk,
+		.bit	= S3C2412_CLKSRC_MSYSCLK_MPLL,
+		.src_0	= &clk_mdivclk,
+		.src_1	= &clk_mpll,
+	}, {
+		.clk	= &clk_uart,
+		.bit	= S3C2412_CLKSRC_UARTCLK_MPLL,
+		.src_0	= &clk_erefclk,
+		.src_1	= &clk_mpll,
+	}, {
+		.clk	= &clk_usbsrc,
+		.bit	= S3C2412_CLKSRC_USBCLK_HCLK,
+		.src_0	= &clk_usysclk,
+		.src_1	= &clk_h,
+	},
+};
+
+/* s3c2412_clk_initparents
+ *
+ * Initialise the parents for the clocks that we get at start-time
+*/
+
+static void __init s3c2412_clk_initparents(void)
+{
+	unsigned long clksrc = __raw_readl(S3C2412_CLKSRC);
+	struct clk_init *cip = clks_src;
+	struct clk *src;
+	int ptr;
+	int ret;
+
+	for (ptr = 0; ptr < ARRAY_SIZE(clks_src); ptr++, cip++) {
+		ret = s3c24xx_register_clock(cip->clk);
+		if (ret < 0) {
+			printk(KERN_ERR "Failed to register clock %s (%d)\n",
+			       cip->clk->name, ret);
+		}
+
+		src = (clksrc & cip->bit) ? cip->src_1 : cip->src_0;
+
+		printk(KERN_INFO "%s: parent %s\n", cip->clk->name, src->name);
+		clk_set_parent(cip->clk, src);
+	}
+}
+
+/* clocks to add straight away */
+
+struct clk *clks[] __initdata = {
+	&clk_ext,
+	&clk_usb_bus,
+	&clk_erefclk,
+	&clk_urefclk,
+	&clk_mrefclk,
+};
+
+int __init s3c2412_baseclk_add(void)
+{
+	unsigned long clkcon  = __raw_readl(S3C2410_CLKCON);
+	struct clk *clkp;
+	int ret;
+	int ptr;
+
+	clk_upll.enable = s3c2412_upll_enable;
+	clk_usb_bus.parent = &clk_usbsrc;
+	clk_usb_bus.rate = 0x0;
+
+	s3c2412_clk_initparents();
+
+	for (ptr = 0; ptr < ARRAY_SIZE(clks); ptr++) {
+		clkp = clks[ptr];
+
+		ret = s3c24xx_register_clock(clkp);
+		if (ret < 0) {
+			printk(KERN_ERR "Failed to register clock %s (%d)\n",
+			       clkp->name, ret);
+		}
+	}
+
+	/* ensure usb bus clock is within correct rate of 48MHz */
+
+	if (clk_get_rate(&clk_usb_bus) != (48 * 1000 * 1000)) {
+		printk(KERN_INFO "Warning: USB bus clock not at 48MHz\n");
+
+		/* for the moment, let's use the UPLL, and see if we can
+		 * get 48MHz */
+
+		clk_set_parent(&clk_usysclk, &clk_upll);
+		clk_set_parent(&clk_usbsrc, &clk_usysclk);
+		clk_set_rate(&clk_usbsrc, 48*1000*1000);
+	}
+
+	printk("S3C2412: upll %s, %ld.%03ld MHz, usb-bus %ld.%03ld MHz\n",
+	       (__raw_readl(S3C2410_UPLLCON) & S3C2412_PLLCON_OFF) ? "off":"on",
+	       print_mhz(clk_get_rate(&clk_upll)),
+	       print_mhz(clk_get_rate(&clk_usb_bus)));
+
+	/* register clocks from clock array */
+
+	clkp = init_clocks;
+	for (ptr = 0; ptr < ARRAY_SIZE(init_clocks); ptr++, clkp++) {
+		/* ensure that we note the clock state */
+
+		clkp->usage = clkcon & clkp->ctrlbit ? 1 : 0;
+
+		ret = s3c24xx_register_clock(clkp);
+		if (ret < 0) {
+			printk(KERN_ERR "Failed to register clock %s (%d)\n",
+			       clkp->name, ret);
+		}
+	}
+
+	/* We must be careful disabling the clocks we are not intending to
+	 * be using at boot time, as subsytems such as the LCD which do
+	 * their own DMA requests to the bus can cause the system to lockup
+	 * if they where in the middle of requesting bus access.
+	 *
+	 * Disabling the LCD clock if the LCD is active is very dangerous,
+	 * and therefore the bootloader should be careful to not enable
+	 * the LCD clock if it is not needed.
+	*/
+
+	/* install (and disable) the clocks we do not need immediately */
+
+	clkp = init_clocks_disable;
+	for (ptr = 0; ptr < ARRAY_SIZE(init_clocks_disable); ptr++, clkp++) {
+
+		ret = s3c24xx_register_clock(clkp);
+		if (ret < 0) {
+			printk(KERN_ERR "Failed to register clock %s (%d)\n",
+			       clkp->name, ret);
+		}
+
+		s3c2412_clkcon_enable(clkp, 0);
+	}
+
+	return 0;
+}

+ 195 - 0
arch/arm/mach-s3c2410/s3c2412.c

@@ -0,0 +1,195 @@
+/* linux/arch/arm/mach-s3c2410/s3c2412.c
+ *
+ * Copyright (c) 2006 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.
+ *
+ * Modifications:
+ *     16-May-2003 BJD  Created initial version
+ *     16-Aug-2003 BJD  Fixed header files and copyright, added URL
+ *     05-Sep-2003 BJD  Moved to kernel v2.6
+ *     18-Jan-2004 BJD  Added serial port configuration
+ *     21-Aug-2004 BJD  Added new struct s3c2410_board handler
+ *     28-Sep-2004 BJD  Updates for new serial port bits
+ *     04-Nov-2004 BJD  Updated UART configuration process
+ *     10-Jan-2005 BJD  Removed s3c2410_clock_tick_rate
+ *     13-Aug-2005 DA   Removed UART from initial I/O mappings
+*/
+
+#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/sysdev.h>
+#include <linux/platform_device.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+
+#include <asm/arch/regs-clock.h>
+#include <asm/arch/regs-serial.h>
+#include <asm/arch/regs-gpio.h>
+#include <asm/arch/regs-gpioj.h>
+#include <asm/arch/regs-dsc.h>
+
+#include "s3c2412.h"
+#include "cpu.h"
+#include "devs.h"
+#include "clock.h"
+#include "pm.h"
+
+#ifndef CONFIG_CPU_S3C2412_ONLY
+void __iomem *s3c24xx_va_gpio2 = S3C24XX_VA_GPIO;
+#endif
+
+/* Initial IO mappings */
+
+static struct map_desc s3c2412_iodesc[] __initdata = {
+	IODESC_ENT(CLKPWR),
+	IODESC_ENT(LCD),
+	IODESC_ENT(TIMER),
+	IODESC_ENT(ADC),
+	IODESC_ENT(WATCHDOG),
+};
+
+/* uart registration process */
+
+void __init s3c2412_init_uarts(struct s3c2410_uartcfg *cfg, int no)
+{
+	s3c24xx_init_uartdevs("s3c2412-uart", s3c2410_uart_resources, cfg, no);
+
+	/* rename devices that are s3c2412/s3c2413 specific */
+	s3c_device_sdi.name  = "s3c2412-sdi";
+	s3c_device_nand.name = "s3c2412-nand";
+}
+
+/* s3c2412_map_io
+ *
+ * register the standard cpu IO areas, and any passed in from the
+ * machine specific initialisation.
+*/
+
+void __init s3c2412_map_io(struct map_desc *mach_desc, int mach_size)
+{
+	/* move base of IO */
+
+	s3c24xx_va_gpio2 = S3C24XX_VA_GPIO + 0x10;
+
+	/* register our io-tables */
+
+	iotable_init(s3c2412_iodesc, ARRAY_SIZE(s3c2412_iodesc));
+	iotable_init(mach_desc, mach_size);
+}
+
+void __init s3c2412_init_clocks(int xtal)
+{
+	unsigned long tmp;
+	unsigned long fclk;
+	unsigned long hclk;
+	unsigned long pclk;
+
+	/* now we've got our machine bits initialised, work out what
+	 * clocks we've got */
+
+	fclk = s3c2410_get_pll(__raw_readl(S3C2410_MPLLCON), xtal*2);
+
+	tmp = __raw_readl(S3C2410_CLKDIVN);
+
+	/* work out clock scalings */
+
+	hclk = fclk / ((tmp & S3C2412_CLKDIVN_HDIVN_MASK) + 1);
+	hclk /= ((tmp & S3C2421_CLKDIVN_ARMDIVN) ? 2 : 1);
+	pclk = hclk / ((tmp & S3C2412_CLKDIVN_PDIVN) ? 2 : 1);
+
+	/* print brieft summary of clocks, etc */
+
+	printk("S3C2412: core %ld.%03ld MHz, memory %ld.%03ld MHz, peripheral %ld.%03ld MHz\n",
+	       print_mhz(fclk), print_mhz(hclk), print_mhz(pclk));
+
+	/* initialise the clocks here, to allow other things like the
+	 * console to use them
+	 */
+
+	s3c24xx_setup_clocks(xtal, fclk, hclk, pclk);
+	s3c2412_baseclk_add();
+}
+
+/* need to register class before we actually register the device, and
+ * we also need to ensure that it has been initialised before any of the
+ * drivers even try to use it (even if not on an s3c2412 based system)
+ * as a driver which may support both 2410 and 2440 may try and use it.
+*/
+
+#ifdef CONFIG_PM
+static struct sleep_save s3c2412_sleep[] = {
+	SAVE_ITEM(S3C2412_DSC0),
+	SAVE_ITEM(S3C2412_DSC1),
+	SAVE_ITEM(S3C2413_GPJDAT),
+	SAVE_ITEM(S3C2413_GPJCON),
+	SAVE_ITEM(S3C2413_GPJUP),
+
+	/* save the sleep configuration anyway, just in case these
+	 * get damaged during wakeup */
+
+	SAVE_ITEM(S3C2412_GPBSLPCON),
+	SAVE_ITEM(S3C2412_GPCSLPCON),
+	SAVE_ITEM(S3C2412_GPDSLPCON),
+	SAVE_ITEM(S3C2412_GPESLPCON),
+	SAVE_ITEM(S3C2412_GPFSLPCON),
+	SAVE_ITEM(S3C2412_GPGSLPCON),
+	SAVE_ITEM(S3C2412_GPHSLPCON),
+	SAVE_ITEM(S3C2413_GPJSLPCON),
+};
+
+static int s3c2412_suspend(struct sys_device *dev, pm_message_t state)
+{
+	s3c2410_pm_do_save(s3c2412_sleep, ARRAY_SIZE(s3c2412_sleep));
+	return 0;
+}
+
+static int s3c2412_resume(struct sys_device *dev)
+{
+	s3c2410_pm_do_restore(s3c2412_sleep, ARRAY_SIZE(s3c2412_sleep));
+	return 0;
+}
+
+#else
+#define s3c2412_suspend NULL
+#define s3c2412_resume  NULL
+#endif
+
+struct sysdev_class s3c2412_sysclass = {
+	set_kset_name("s3c2412-core"),
+	.suspend	= s3c2412_suspend,
+	.resume		= s3c2412_resume
+};
+
+static int __init s3c2412_core_init(void)
+{
+	return sysdev_class_register(&s3c2412_sysclass);
+}
+
+core_initcall(s3c2412_core_init);
+
+static struct sys_device s3c2412_sysdev = {
+	.cls		= &s3c2412_sysclass,
+};
+
+int __init s3c2412_init(void)
+{
+	printk("S3C2412: Initialising architecture\n");
+
+	return sysdev_register(&s3c2412_sysdev);
+}

+ 29 - 0
arch/arm/mach-s3c2410/s3c2412.h

@@ -0,0 +1,29 @@
+/* arch/arm/mach-s3c2410/s3c2412.h
+ *
+ * Copyright (c) 2006 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * Header file for s3c2412 cpu 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.
+*/
+
+#ifdef CONFIG_CPU_S3C2412
+
+extern  int s3c2412_init(void);
+
+extern void s3c2412_map_io(struct map_desc *mach_desc, int size);
+
+extern void s3c2412_init_uarts(struct s3c2410_uartcfg *cfg, int no);
+
+extern void s3c2412_init_clocks(int xtal);
+
+extern  int s3c2412_baseclk_add(void);
+#else
+#define s3c2412_init_clocks NULL
+#define s3c2412_init_uarts NULL
+#define s3c2412_map_io NULL
+#define s3c2412_init NULL
+#endif

+ 5 - 5
arch/arm/mm/Kconfig

@@ -61,9 +61,9 @@ config CPU_ARM720T
 
 
 # ARM920T
 # ARM920T
 config CPU_ARM920T
 config CPU_ARM920T
-	bool "Support ARM920T processor" if !ARCH_S3C2410
-	depends on ARCH_EP93XX || ARCH_INTEGRATOR || ARCH_S3C2410 || ARCH_IMX || ARCH_AAEC2000 || ARCH_AT91RM9200
-	default y if ARCH_S3C2410 || ARCH_AT91RM9200
+	bool "Support ARM920T processor"
+	depends on ARCH_EP93XX || ARCH_INTEGRATOR || CPU_S3C2410 || CPU_S3C2440 || CPU_S3C2442 || ARCH_IMX || ARCH_AAEC2000 || ARCH_AT91RM9200
+	default y if CPU_S3C2410 || CPU_S3C2440 || CPU_S3C2442 || ARCH_AT91RM9200
 	select CPU_32v4
 	select CPU_32v4
 	select CPU_ABRT_EV4T
 	select CPU_ABRT_EV4T
 	select CPU_CACHE_V4WT
 	select CPU_CACHE_V4WT
@@ -121,8 +121,8 @@ config CPU_ARM925T
 # ARM926T
 # ARM926T
 config CPU_ARM926T
 config CPU_ARM926T
 	bool "Support ARM926T processor"
 	bool "Support ARM926T processor"
-	depends on ARCH_INTEGRATOR || ARCH_VERSATILE_PB || MACH_VERSATILE_AB || ARCH_OMAP730 || ARCH_OMAP16XX || MACH_REALVIEW_EB || ARCH_PNX4008 || ARCH_NETX
-	default y if ARCH_VERSATILE_PB || MACH_VERSATILE_AB || ARCH_OMAP730 || ARCH_OMAP16XX || ARCH_PNX4008 || ARCH_NETX
+	depends on ARCH_INTEGRATOR || ARCH_VERSATILE_PB || MACH_VERSATILE_AB || ARCH_OMAP730 || ARCH_OMAP16XX || MACH_REALVIEW_EB || ARCH_PNX4008 || ARCH_NETX || CPU_S3C2412
+	default y if ARCH_VERSATILE_PB || MACH_VERSATILE_AB || ARCH_OMAP730 || ARCH_OMAP16XX || ARCH_PNX4008 || ARCH_NETX || CPU_S3C2412
 	select CPU_32v5
 	select CPU_32v5
 	select CPU_ABRT_EV5TJ
 	select CPU_ABRT_EV5TJ
 	select CPU_CACHE_VIVT
 	select CPU_CACHE_VIVT

+ 6 - 3
drivers/serial/Kconfig

@@ -354,21 +354,24 @@ config SERIAL_CLPS711X_CONSOLE
 	  kernel at boot time.)
 	  kernel at boot time.)
 
 
 config SERIAL_S3C2410
 config SERIAL_S3C2410
-	tristate "Samsung S3C2410 Serial port support"
+	tristate "Samsung S3C2410/S3C2440/S3C2442/S3C2412 Serial port support"
 	depends on ARM && ARCH_S3C2410
 	depends on ARM && ARCH_S3C2410
 	select SERIAL_CORE
 	select SERIAL_CORE
 	help
 	help
-	  Support for the on-chip UARTs on the Samsung S3C2410X CPU,
+	  Support for the on-chip UARTs on the Samsung S3C24XX series CPUs,
 	  providing /dev/ttySAC0, 1 and 2 (note, some machines may not
 	  providing /dev/ttySAC0, 1 and 2 (note, some machines may not
 	  provide all of these ports, depending on how the serial port
 	  provide all of these ports, depending on how the serial port
 	  pins are configured.
 	  pins are configured.
 
 
+	  Currently this driver supports the UARTS on the S3C2410, S3C2440,
+	  S3C2442, S3C2412 and S3C2413 CPUs.
+
 config SERIAL_S3C2410_CONSOLE
 config SERIAL_S3C2410_CONSOLE
 	bool "Support for console on S3C2410 serial port"
 	bool "Support for console on S3C2410 serial port"
 	depends on SERIAL_S3C2410=y
 	depends on SERIAL_S3C2410=y
 	select SERIAL_CORE_CONSOLE
 	select SERIAL_CORE_CONSOLE
 	help
 	help
-	  Allow selection of the S3C2410 on-board serial ports for use as
+	  Allow selection of the S3C24XX on-board serial ports for use as
 	  an virtual console.
 	  an virtual console.
 
 
 	  Even if you say Y here, the currently visible virtual console
 	  Even if you say Y here, the currently visible virtual console

+ 142 - 1
drivers/serial/s3c2410.c

@@ -872,6 +872,8 @@ static const char *s3c24xx_serial_type(struct uart_port *port)
 		return "S3C2410";
 		return "S3C2410";
 	case PORT_S3C2440:
 	case PORT_S3C2440:
 		return "S3C2440";
 		return "S3C2440";
+	case PORT_S3C2412:
+		return "S3C2412";
 	default:
 	default:
 		return NULL;
 		return NULL;
 	}
 	}
@@ -1528,6 +1530,141 @@ static inline void s3c2440_serial_exit(void)
 #define s3c2440_uart_inf_at NULL
 #define s3c2440_uart_inf_at NULL
 #endif /* CONFIG_CPU_S3C2440 */
 #endif /* CONFIG_CPU_S3C2440 */
 
 
+#if defined(CONFIG_CPU_S3C2412) || defined(CONFIG_CPU_S3C2413)
+
+static int s3c2412_serial_setsource(struct uart_port *port,
+				     struct s3c24xx_uart_clksrc *clk)
+{
+	unsigned long ucon = rd_regl(port, S3C2410_UCON);
+
+	ucon &= ~S3C2412_UCON_CLKMASK;
+
+	if (strcmp(clk->name, "uclk") == 0)
+		ucon |= S3C2440_UCON_UCLK;
+	else if (strcmp(clk->name, "pclk") == 0)
+		ucon |= S3C2440_UCON_PCLK;
+	else if (strcmp(clk->name, "usysclk") == 0)
+		ucon |= S3C2412_UCON_USYSCLK;
+	else {
+		printk(KERN_ERR "unknown clock source %s\n", clk->name);
+		return -EINVAL;
+	}
+
+	wr_regl(port, S3C2410_UCON, ucon);
+	return 0;
+}
+
+
+static int s3c2412_serial_getsource(struct uart_port *port,
+				    struct s3c24xx_uart_clksrc *clk)
+{
+	unsigned long ucon = rd_regl(port, S3C2410_UCON);
+
+	switch (ucon & S3C2412_UCON_CLKMASK) {
+	case S3C2412_UCON_UCLK:
+		clk->divisor = 1;
+		clk->name = "uclk";
+		break;
+
+	case S3C2412_UCON_PCLK:
+	case S3C2412_UCON_PCLK2:
+		clk->divisor = 1;
+		clk->name = "pclk";
+		break;
+
+	case S3C2412_UCON_USYSCLK:
+		clk->divisor = 1;
+		clk->name = "usysclk";
+		break;
+	}
+
+	return 0;
+}
+
+static int s3c2412_serial_resetport(struct uart_port *port,
+				    struct s3c2410_uartcfg *cfg)
+{
+	unsigned long ucon = rd_regl(port, S3C2410_UCON);
+
+	dbg("%s: port=%p (%08lx), cfg=%p\n",
+	    __FUNCTION__, port, port->mapbase, cfg);
+
+	/* ensure we don't change the clock settings... */
+
+	ucon &= S3C2412_UCON_CLKMASK;
+
+	wr_regl(port, S3C2410_UCON,  ucon | cfg->ucon);
+	wr_regl(port, S3C2410_ULCON, cfg->ulcon);
+
+	/* reset both fifos */
+
+	wr_regl(port, S3C2410_UFCON, cfg->ufcon | S3C2410_UFCON_RESETBOTH);
+	wr_regl(port, S3C2410_UFCON, cfg->ufcon);
+
+	return 0;
+}
+
+static struct s3c24xx_uart_info s3c2412_uart_inf = {
+	.name		= "Samsung S3C2412 UART",
+	.type		= PORT_S3C2412,
+	.fifosize	= 64,
+	.rx_fifomask	= S3C2440_UFSTAT_RXMASK,
+	.rx_fifoshift	= S3C2440_UFSTAT_RXSHIFT,
+	.rx_fifofull	= S3C2440_UFSTAT_RXFULL,
+	.tx_fifofull	= S3C2440_UFSTAT_TXFULL,
+	.tx_fifomask	= S3C2440_UFSTAT_TXMASK,
+	.tx_fifoshift	= S3C2440_UFSTAT_TXSHIFT,
+	.get_clksrc	= s3c2412_serial_getsource,
+	.set_clksrc	= s3c2412_serial_setsource,
+	.reset_port	= s3c2412_serial_resetport,
+};
+
+/* device management */
+
+static int s3c2412_serial_probe(struct platform_device *dev)
+{
+	dbg("s3c2440_serial_probe: dev=%p\n", dev);
+	return s3c24xx_serial_probe(dev, &s3c2440_uart_inf);
+}
+
+static struct platform_driver s3c2412_serial_drv = {
+	.probe		= s3c2412_serial_probe,
+	.remove		= s3c24xx_serial_remove,
+	.suspend	= s3c24xx_serial_suspend,
+	.resume		= s3c24xx_serial_resume,
+	.driver		= {
+		.name	= "s3c2412-uart",
+		.owner	= THIS_MODULE,
+	},
+};
+
+
+static inline int s3c2412_serial_init(void)
+{
+	return s3c24xx_serial_init(&s3c2412_serial_drv, &s3c2412_uart_inf);
+}
+
+static inline void s3c2412_serial_exit(void)
+{
+	platform_driver_unregister(&s3c2412_serial_drv);
+}
+
+#define s3c2412_uart_inf_at &s3c2412_uart_inf
+#else
+
+static inline int s3c2412_serial_init(void)
+{
+	return 0;
+}
+
+static inline void s3c2412_serial_exit(void)
+{
+}
+
+#define s3c2412_uart_inf_at NULL
+#endif /* CONFIG_CPU_S3C2440 */
+
+
 /* module initialisation code */
 /* module initialisation code */
 
 
 static int __init s3c24xx_serial_modinit(void)
 static int __init s3c24xx_serial_modinit(void)
@@ -1542,6 +1679,7 @@ static int __init s3c24xx_serial_modinit(void)
 
 
 	s3c2400_serial_init();
 	s3c2400_serial_init();
 	s3c2410_serial_init();
 	s3c2410_serial_init();
+	s3c2412_serial_init();
 	s3c2440_serial_init();
 	s3c2440_serial_init();
 
 
 	return 0;
 	return 0;
@@ -1551,6 +1689,7 @@ static void __exit s3c24xx_serial_modexit(void)
 {
 {
 	s3c2400_serial_exit();
 	s3c2400_serial_exit();
 	s3c2410_serial_exit();
 	s3c2410_serial_exit();
+	s3c2412_serial_exit();
 	s3c2440_serial_exit();
 	s3c2440_serial_exit();
 
 
 	uart_unregister_driver(&s3c24xx_uart_drv);
 	uart_unregister_driver(&s3c24xx_uart_drv);
@@ -1773,6 +1912,8 @@ static int s3c24xx_serial_initconsole(void)
 		info = s3c2410_uart_inf_at;
 		info = s3c2410_uart_inf_at;
 	} else if (strcmp(dev->name, "s3c2440-uart") == 0) {
 	} else if (strcmp(dev->name, "s3c2440-uart") == 0) {
 		info = s3c2440_uart_inf_at;
 		info = s3c2440_uart_inf_at;
+	} else if (strcmp(dev->name, "s3c2412-uart") == 0) {
+		info = s3c2412_uart_inf_at;
 	} else {
 	} else {
 		printk(KERN_ERR "s3c24xx: no driver for %s\n", dev->name);
 		printk(KERN_ERR "s3c24xx: no driver for %s\n", dev->name);
 		return 0;
 		return 0;
@@ -1796,4 +1937,4 @@ console_initcall(s3c24xx_serial_initconsole);
 
 
 MODULE_LICENSE("GPL");
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
 MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
-MODULE_DESCRIPTION("Samsung S3C2410/S3C2440 Serial port driver");
+MODULE_DESCRIPTION("Samsung S3C2410/S3C2440/S3C2412 Serial port driver");

+ 0 - 1
include/asm-arm/arch-aaec2000/io.h

@@ -16,6 +16,5 @@
  */
  */
 #define __io(a)			((void __iomem *)(a))
 #define __io(a)			((void __iomem *)(a))
 #define __mem_pci(a)		(a)
 #define __mem_pci(a)		(a)
-#define __mem_isa(a)		(a)
 
 
 #endif
 #endif

+ 0 - 1
include/asm-arm/arch-clps711x/io.h

@@ -26,7 +26,6 @@
 
 
 #define __io(a)			((void __iomem *)(a))
 #define __io(a)			((void __iomem *)(a))
 #define __mem_pci(a)		(a)
 #define __mem_pci(a)		(a)
-#define __mem_isa(a)		(a)
 
 
 /*
 /*
  * We don't support ins[lb]/outs[lb].  Make them fault.
  * We don't support ins[lb]/outs[lb].  Make them fault.

+ 0 - 8
include/asm-arm/arch-ebsa285/io.h

@@ -24,7 +24,6 @@
 #define __io(a)			((void __iomem *)(PCIO_BASE + (a)))
 #define __io(a)			((void __iomem *)(PCIO_BASE + (a)))
 #if 1
 #if 1
 #define __mem_pci(a)		(a)
 #define __mem_pci(a)		(a)
-#define __mem_isa(a)		((a) + PCIMEM_BASE)
 #else
 #else
 
 
 static inline void __iomem *___mem_pci(void __iomem *p)
 static inline void __iomem *___mem_pci(void __iomem *p)
@@ -34,14 +33,7 @@ static inline void __iomem *___mem_pci(void __iomem *p)
 	return p;
 	return p;
 }
 }
 
 
-static inline void __iomem *___mem_isa(void __iomem *p)
-{
-	unsigned long a = (unsigned long)p;
-	BUG_ON(a >= 16*1048576);
-	return p + PCIMEM_BASE;
-}
 #define __mem_pci(a)		___mem_pci(a)
 #define __mem_pci(a)		___mem_pci(a)
-#define __mem_isa(a)		___mem_isa(a)
 #endif
 #endif
 
 
 #endif
 #endif

+ 2 - 0
include/asm-arm/arch-ep93xx/ep93xx-regs.h

@@ -115,6 +115,8 @@
 #define EP93XX_SYSCON_CLOCK_USH_EN	0x10000000
 #define EP93XX_SYSCON_CLOCK_USH_EN	0x10000000
 #define EP93XX_SYSCON_HALT		EP93XX_SYSCON_REG(0x08)
 #define EP93XX_SYSCON_HALT		EP93XX_SYSCON_REG(0x08)
 #define EP93XX_SYSCON_STANDBY		EP93XX_SYSCON_REG(0x0c)
 #define EP93XX_SYSCON_STANDBY		EP93XX_SYSCON_REG(0x0c)
+#define EP93XX_SYSCON_CLOCK_SET1	EP93XX_SYSCON_REG(0x20)
+#define EP93XX_SYSCON_CLOCK_SET2	EP93XX_SYSCON_REG(0x24)
 #define EP93XX_SYSCON_DEVICE_CONFIG	EP93XX_SYSCON_REG(0x80)
 #define EP93XX_SYSCON_DEVICE_CONFIG	EP93XX_SYSCON_REG(0x80)
 #define EP93XX_SYSCON_DEVICE_CONFIG_CRUNCH_ENABLE	0x00800000
 #define EP93XX_SYSCON_DEVICE_CONFIG_CRUNCH_ENABLE	0x00800000
 #define EP93XX_SYSCON_SWLOCK		EP93XX_SYSCON_REG(0xc0)
 #define EP93XX_SYSCON_SWLOCK		EP93XX_SYSCON_REG(0xc0)

+ 1 - 0
include/asm-arm/arch-ep93xx/platform.h

@@ -8,6 +8,7 @@ void ep93xx_map_io(void);
 void ep93xx_init_irq(void);
 void ep93xx_init_irq(void);
 void ep93xx_init_time(unsigned long);
 void ep93xx_init_time(unsigned long);
 void ep93xx_init_devices(void);
 void ep93xx_init_devices(void);
+void ep93xx_clock_init(void);
 extern struct sys_timer ep93xx_timer;
 extern struct sys_timer ep93xx_timer;
 
 
 
 

+ 0 - 1
include/asm-arm/arch-integrator/io.h

@@ -32,6 +32,5 @@
 
 
 #define __io(a)			((void __iomem *)(PCI_IO_VADDR + (a)))
 #define __io(a)			((void __iomem *)(PCI_IO_VADDR + (a)))
 #define __mem_pci(a)		(a)
 #define __mem_pci(a)		(a)
-#define __mem_isa(a)		((a) + PCI_MEMORY_VADDR)
 
 
 #endif
 #endif

+ 0 - 1
include/asm-arm/arch-iop3xx/io.h

@@ -17,6 +17,5 @@
 
 
 #define __io(p)			((void __iomem *)(p))
 #define __io(p)			((void __iomem *)(p))
 #define __mem_pci(a)		(a)
 #define __mem_pci(a)		(a)
-#define __mem_isa(a)		(a)
 
 
 #endif
 #endif

+ 0 - 1
include/asm-arm/arch-l7200/io.h

@@ -19,7 +19,6 @@
  */
  */
 #define __io_pci(a)		((void __iomem *)(PCIO_BASE + (a)))
 #define __io_pci(a)		((void __iomem *)(PCIO_BASE + (a)))
 #define __mem_pci(a)		(a)
 #define __mem_pci(a)		(a)
-#define __mem_isa(a)		(a)
 
 
 #define __ioaddr(p)             __io_pci(p)
 #define __ioaddr(p)             __io_pci(p)
 
 

+ 0 - 1
include/asm-arm/arch-lh7a40x/io.h

@@ -18,6 +18,5 @@
 /* No ISA or PCI bus on this machine. */
 /* No ISA or PCI bus on this machine. */
 #define __io(a)			((void __iomem *)(a))
 #define __io(a)			((void __iomem *)(a))
 #define __mem_pci(a)		(a)
 #define __mem_pci(a)		(a)
-#define __mem_isa(a)		(a)
 
 
 #endif /* __ASM_ARCH_IO_H */
 #endif /* __ASM_ARCH_IO_H */

+ 0 - 1
include/asm-arm/arch-netx/io.h

@@ -24,6 +24,5 @@
 
 
 #define __io(a)         ((void __iomem *)(a))
 #define __io(a)         ((void __iomem *)(a))
 #define __mem_pci(a)            (a)
 #define __mem_pci(a)            (a)
-#define __mem_isa(a)            (a)
 
 
 #endif
 #endif

+ 0 - 1
include/asm-arm/arch-omap/io.h

@@ -44,7 +44,6 @@
  */
  */
 #define __io(a)			((void __iomem *)(PCIO_BASE + (a)))
 #define __io(a)			((void __iomem *)(PCIO_BASE + (a)))
 #define __mem_pci(a)		(a)
 #define __mem_pci(a)		(a)
-#define __mem_isa(a)		(a)
 
 
 /*
 /*
  * ----------------------------------------------------------------------------
  * ----------------------------------------------------------------------------

+ 0 - 1
include/asm-arm/arch-pxa/io.h

@@ -16,6 +16,5 @@
  */
  */
 #define __io(a)			((void __iomem *)(a))
 #define __io(a)			((void __iomem *)(a))
 #define __mem_pci(a)		(a)
 #define __mem_pci(a)		(a)
-#define __mem_isa(a)		(a)
 
 
 #endif
 #endif

+ 0 - 1
include/asm-arm/arch-realview/io.h

@@ -29,6 +29,5 @@ static inline void __iomem *__io(unsigned long addr)
 
 
 #define __io(a)			__io(a)
 #define __io(a)			__io(a)
 #define __mem_pci(a)		(a)
 #define __mem_pci(a)		(a)
-#define __mem_isa(a)		(a)
 
 
 #endif
 #endif

+ 8 - 2
include/asm-arm/arch-s3c2410/debug-macro.S

@@ -33,7 +33,7 @@
 		.endm
 		.endm
 
 
 		.macro	senduart,rd,rx
 		.macro	senduart,rd,rx
-		str	\rd, [\rx, # S3C2410_UTXH ]
+		strb 	\rd, [\rx, # S3C2410_UTXH ]
 		.endm
 		.endm
 
 
 		.macro	busyuart, rd, rx
 		.macro	busyuart, rd, rx
@@ -42,6 +42,12 @@
 		beq	1001f				@
 		beq	1001f				@
 		@ FIFO enabled...
 		@ FIFO enabled...
 1003:
 1003:
+		@ check for arm920 vs arm926. currently assume all arm926
+		@ devices have an 64 byte FIFO identical to the s3c2440
+		mrc	p15, 0, \rd, c0, c0
+		and	\rd, \rd, #0xff0
+		teq	\rd, #0x260
+		beq	1004f
 		mrc	p15, 0, \rd, c1, c0
 		mrc	p15, 0, \rd, c1, c0
 		tst	\rd, #1
 		tst	\rd, #1
 		addeq	\rd, \rx, #(S3C24XX_PA_GPIO - S3C24XX_PA_UART)
 		addeq	\rd, \rx, #(S3C24XX_PA_GPIO - S3C24XX_PA_UART)
@@ -50,7 +56,7 @@
 		ldr	\rd, [ \rd, # S3C2410_GSTATUS1 - S3C2410_GPIOREG(0) ]
 		ldr	\rd, [ \rd, # S3C2410_GSTATUS1 - S3C2410_GPIOREG(0) ]
 		and	\rd, \rd, #0x00ff0000
 		and	\rd, \rd, #0x00ff0000
 		teq	\rd, #0x00440000		@ is it 2440?
 		teq	\rd, #0x00440000		@ is it 2440?
-
+1004:
 		ldr	\rd, [ \rx, # S3C2410_UFSTAT ]
 		ldr	\rd, [ \rx, # S3C2410_UFSTAT ]
 		moveq	\rd, \rd, lsr #SHIFT_2440TXF
 		moveq	\rd, \rd, lsr #SHIFT_2440TXF
 		tst	\rd, #S3C2410_UFSTAT_TXFULL
 		tst	\rd, #S3C2410_UFSTAT_TXFULL

+ 7 - 23
include/asm-arm/arch-s3c2410/entry-macro.S

@@ -18,8 +18,6 @@
 
 
 #define INTPND		(0x10)
 #define INTPND		(0x10)
 #define INTOFFSET	(0x14)
 #define INTOFFSET	(0x14)
-#define EXTINTPEND	(0xa8)
-#define EXTINTMASK	(0xa4)
 
 
 #include <asm/hardware.h>
 #include <asm/hardware.h>
 #include <asm/arch/irqs.h>
 #include <asm/arch/irqs.h>
@@ -28,37 +26,23 @@
 
 
 		mov	\base, #S3C24XX_VA_IRQ
 		mov	\base, #S3C24XX_VA_IRQ
 
 
-		ldr	\irqstat, [ \base, #INTPND]
-		bics	\irqnr, \irqstat, #3<<4		@@ only an GPIO IRQ
-		beq	2000f
-
 		@@ try the interrupt offset register, since it is there
 		@@ try the interrupt offset register, since it is there
 
 
+		ldr	\irqstat, [ \base, #INTPND ]
+		teq	\irqstat, #0
+		beq	1002f
 		ldr	\irqnr, [ \base, #INTOFFSET ]
 		ldr	\irqnr, [ \base, #INTOFFSET ]
 		mov	\tmp, #1
 		mov	\tmp, #1
 		tst	\irqstat, \tmp, lsl \irqnr
 		tst	\irqstat, \tmp, lsl \irqnr
-		addne	\irqnr, \irqnr, #IRQ_EINT0
 		bne	1001f
 		bne	1001f
 
 
 		@@ the number specified is not a valid irq, so try
 		@@ the number specified is not a valid irq, so try
 		@@ and work it out for ourselves
 		@@ and work it out for ourselves
 
 
-		mov	\irqnr, #IRQ_EINT0		@@ start here
-		b	3000f
-
-2000:
-		@@ load the GPIO interrupt register, and check it
-
-		add	\tmp, \base, #S3C24XX_VA_GPIO - S3C24XX_VA_IRQ
-		ldr	\irqstat, [ \tmp, # EXTINTPEND ]
-		ldr	\irqnr,   [ \tmp, # EXTINTMASK ]
-		bics	\irqstat, \irqstat, \irqnr
-		beq	1001f
-
-		mov	\irqnr, #(IRQ_EINT4 - 4)
+		mov	\irqnr, #0		@@ start here
 
 
 		@@ work out which irq (if any) we got
 		@@ work out which irq (if any) we got
-3000:
+
 		movs	\tmp, \irqstat, lsl#16
 		movs	\tmp, \irqstat, lsl#16
 		addeq	\irqnr, \irqnr, #16
 		addeq	\irqnr, \irqnr, #16
 		moveq	\irqstat, \irqstat, lsr#16
 		moveq	\irqstat, \irqstat, lsr#16
@@ -75,9 +59,9 @@
 		addeq	\irqnr, \irqnr, #1
 		addeq	\irqnr, \irqnr, #1
 
 
 		@@ we have the value
 		@@ we have the value
-		movs	\irqnr, \irqnr
-
 1001:
 1001:
+		adds	\irqnr, \irqnr, #IRQ_EINT0
+1002:
 		@@ exit here, Z flag unset if IRQ
 		@@ exit here, Z flag unset if IRQ
 
 
 	.endm
 	.endm

+ 16 - 0
include/asm-arm/arch-s3c2410/map.h

@@ -236,4 +236,20 @@
 #define S3C24XX_PA_SPI      S3C2410_PA_SPI
 #define S3C24XX_PA_SPI      S3C2410_PA_SPI
 #endif
 #endif
 
 
+/* deal with the registers that move under the 2412/2413 */
+
+#if defined(CONFIG_CPU_S3C2412) || defined(CONFIG_CPU_S3C2413)
+#ifndef __ASSEMBLY__
+extern void __iomem *s3c24xx_va_gpio2;
+#endif
+#ifdef CONFIG_CPU_S3C2412_ONLY
+#define S3C24XX_VA_GPIO2 (S3C24XX_VA_GPIO + 0x10)
+#else
+#define S3C24XX_VA_GPIO2 s3c24xx_va_gpio2
+#endif
+#else
+#define s3c24xx_va_gpio2 S3C24XX_VA_GPIO
+#define S3C24XX_VA_GPIO2 S3C24XX_VA_GPIO
+#endif
+
 #endif /* __ASM_ARCH_MAP_H */
 #endif /* __ASM_ARCH_MAP_H */

+ 62 - 1
include/asm-arm/arch-s3c2410/regs-clock.h

@@ -1,6 +1,6 @@
 /* linux/include/asm/arch-s3c2410/regs-clock.h
 /* linux/include/asm/arch-s3c2410/regs-clock.h
  *
  *
- * Copyright (c) 2003,2004,2005 Simtec Electronics <linux@simtec.co.uk>
+ * Copyright (c) 2003,2004,2005,2006 Simtec Electronics <linux@simtec.co.uk>
  *		      http://armlinux.simtec.co.uk/
  *		      http://armlinux.simtec.co.uk/
  *
  *
  * This program is free software; you can redistribute it and/or modify
  * This program is free software; you can redistribute it and/or modify
@@ -140,5 +140,66 @@ s3c2410_get_pll(unsigned int pllval, unsigned int baseclk)
 
 
 #endif /* CONFIG_CPU_S3C2440 or CONFIG_CPU_S3C2442 */
 #endif /* CONFIG_CPU_S3C2440 or CONFIG_CPU_S3C2442 */
 
 
+#if defined(CONFIG_CPU_S3C2412) || defined(CONFIG_CPU_S3C2413)
+
+#define S3C2412_OSCSET		S3C2410_CLKREG(0x18)
+#define S3C2412_CLKSRC		S3C2410_CLKREG(0x1C)
+
+#define S3C2412_PLLCON_OFF		(1<<20)
+
+#define S3C2412_CLKDIVN_PDIVN		(1<<2)
+#define S3C2412_CLKDIVN_HDIVN_MASK	(3<<0)
+#define S3C2421_CLKDIVN_ARMDIVN		(1<<3)
+#define S3C2412_CLKDIVN_USB48DIV	(1<<6)
+#define S3C2412_CLKDIVN_UARTDIV_MASK	(15<<8)
+#define S3C2412_CLKDIVN_UARTDIV_SHIFT	(8)
+#define S3C2412_CLKDIVN_I2SDIV_MASK	(15<<12)
+#define S3C2412_CLKDIVN_I2SDIV_SHIFT	(12)
+#define S3C2412_CLKDIVN_CAMDIV_MASK	(15<<16)
+#define S3C2412_CLKDIVN_CAMDIV_SHIFT	(16)
+
+#define S3C2412_CLKCON_WDT		(1<<28)
+#define S3C2412_CLKCON_SPI		(1<<27)
+#define S3C2412_CLKCON_IIS		(1<<26)
+#define S3C2412_CLKCON_IIC		(1<<25)
+#define S3C2412_CLKCON_ADC		(1<<24)
+#define S3C2412_CLKCON_RTC		(1<<23)
+#define S3C2412_CLKCON_GPIO		(1<<22)
+#define S3C2412_CLKCON_UART2		(1<<21)
+#define S3C2412_CLKCON_UART1		(1<<20)
+#define S3C2412_CLKCON_UART0		(1<<19)
+#define S3C2412_CLKCON_SDI		(1<<18)
+#define S3C2412_CLKCON_PWMT		(1<<17)
+#define S3C2412_CLKCON_USBD		(1<<16)
+#define S3C2412_CLKCON_CAMCLK		(1<<15)
+#define S3C2412_CLKCON_UARTCLK		(1<<14)
+/* missing 13 */
+#define S3C2412_CLKCON_USB_HOST48	(1<<12)
+#define S3C2412_CLKCON_USB_DEV48	(1<<11)
+#define S3C2412_CLKCON_HCLKdiv2		(1<<10)
+#define S3C2412_CLKCON_HCLKx2		(1<<9)
+#define S3C2412_CLKCON_SDRAM		(1<<8)
+/* missing 7 */
+#define S3C2412_CLKCON_USBH		S3C2410_CLKCON_USBH
+#define S3C2412_CLKCON_LCDC		S3C2410_CLKCON_LCDC
+#define S3C2412_CLKCON_NAND		S3C2410_CLKCON_NAND
+#define S3C2412_CLKCON_DMA3		(1<<3)
+#define S3C2412_CLKCON_DMA2		(1<<2)
+#define S3C2412_CLKCON_DMA1		(1<<1)
+#define S3C2412_CLKCON_DMA0		(1<<0)
+
+/* clock sourec controls */
+
+#define S3C2412_CLKSRC_EXTCLKDIV_MASK		(7 << 0)
+#define S3C2412_CLKSRC_EXTCLKDIV_SHIFT		(0)
+#define S3C2412_CLKSRC_MDIVCLK_EXTCLKDIV	(1<<3)
+#define S3C2412_CLKSRC_MSYSCLK_MPLL		(1<<4)
+#define S3C2412_CLKSRC_USYSCLK_UPLL		(1<<5)
+#define S3C2412_CLKSRC_UARTCLK_MPLL		(1<<8)
+#define S3C2412_CLKSRC_I2SCLK_MPLL		(1<<9)
+#define S3C2412_CLKSRC_USBCLK_HCLK		(1<<10)
+#define S3C2412_CLKSRC_CAMCLK_HCLK		(1<<11)
+
+#endif /* CONFIG_CPU_S3C2412 | CONFIG_CPU_S3C2413 */
 
 
 #endif /* __ASM_ARM_REGS_CLOCK */
 #endif /* __ASM_ARM_REGS_CLOCK */

+ 3 - 0
include/asm-arm/arch-s3c2410/regs-dsc.h

@@ -23,6 +23,9 @@
 #define S3C2440_DSC0	   S3C2410_GPIOREG(0xc4)
 #define S3C2440_DSC0	   S3C2410_GPIOREG(0xc4)
 #define S3C2440_DSC1	   S3C2410_GPIOREG(0xc8)
 #define S3C2440_DSC1	   S3C2410_GPIOREG(0xc8)
 
 
+#define S3C2412_DSC0	   S3C2410_GPIOREG(0xdc)
+#define S3C2412_DSC1	   S3C2410_GPIOREG(0xe0)
+
 #define S3C2440_SELECT_DSC0 (0)
 #define S3C2440_SELECT_DSC0 (0)
 #define S3C2440_SELECT_DSC1 (1<<31)
 #define S3C2440_SELECT_DSC1 (1<<31)
 
 

+ 60 - 3
include/asm-arm/arch-s3c2410/regs-gpio.h

@@ -45,7 +45,7 @@
 #define S3C24XX_MISCCR        S3C2400_MISCCR
 #define S3C24XX_MISCCR        S3C2400_MISCCR
 #else
 #else
 #define S3C24XX_GPIO_BASE(x)  S3C2410_GPIO_BASE(x)
 #define S3C24XX_GPIO_BASE(x)  S3C2410_GPIO_BASE(x)
-#define S3C24XX_MISCCR        S3C2410_MISCCR
+#define S3C24XX_MISCCR	      S3C24XX_GPIOREG2(0x80)
 #endif /* CONFIG_CPU_S3C2400 */
 #endif /* CONFIG_CPU_S3C2400 */
 
 
 
 
@@ -73,9 +73,15 @@
 #define S3C2410_GPIO_SFN2    (0xFFFFFFF2)	/* not available on A */
 #define S3C2410_GPIO_SFN2    (0xFFFFFFF2)	/* not available on A */
 #define S3C2410_GPIO_SFN3    (0xFFFFFFF3)	/* not available on A */
 #define S3C2410_GPIO_SFN3    (0xFFFFFFF3)	/* not available on A */
 
 
-/* configure GPIO ports A..G */
+/* register address for the GPIO registers.
+ * S3C24XX_GPIOREG2 is for the second set of registers in the
+ * GPIO which move between s3c2410 and s3c2412 type systems */
 
 
 #define S3C2410_GPIOREG(x) ((x) + S3C24XX_VA_GPIO)
 #define S3C2410_GPIOREG(x) ((x) + S3C24XX_VA_GPIO)
+#define S3C24XX_GPIOREG2(x) ((x) + S3C24XX_VA_GPIO2)
+
+
+/* configure GPIO ports A..G */
 
 
 /* port A - S3C2410: 22bits, zero in bit X makes pin X output
 /* port A - S3C2410: 22bits, zero in bit X makes pin X output
  *          S3C2400: 18bits, zero in bit X makes pin X output
  *          S3C2400: 18bits, zero in bit X makes pin X output
@@ -953,11 +959,18 @@
 #define S3C2410_GPH10_OUTP    (0x01 << 20)
 #define S3C2410_GPH10_OUTP    (0x01 << 20)
 #define S3C2410_GPH10_CLKOUT1 (0x02 << 20)
 #define S3C2410_GPH10_CLKOUT1 (0x02 << 20)
 
 
+/* The S3C2412 and S3C2413 move the GPJ register set to after
+ * GPH, which means all registers after 0x80 are now offset by 0x10
+ * for the 2412/2413 from the 2410/2440/2442
+*/
+
 /* miscellaneous control */
 /* miscellaneous control */
 #define S3C2400_MISCCR	   S3C2410_GPIOREG(0x54)
 #define S3C2400_MISCCR	   S3C2410_GPIOREG(0x54)
 #define S3C2410_MISCCR	   S3C2410_GPIOREG(0x80)
 #define S3C2410_MISCCR	   S3C2410_GPIOREG(0x80)
 #define S3C2410_DCLKCON	   S3C2410_GPIOREG(0x84)
 #define S3C2410_DCLKCON	   S3C2410_GPIOREG(0x84)
 
 
+#define S3C24XX_DCLKCON	   S3C24XX_GPIOREG2(0x84)
+
 /* see clock.h for dclk definitions */
 /* see clock.h for dclk definitions */
 
 
 /* pullup control on databus */
 /* pullup control on databus */
@@ -985,6 +998,8 @@
 #define S3C2410_MISCCR_CLK0_DCLK0   (5<<4)
 #define S3C2410_MISCCR_CLK0_DCLK0   (5<<4)
 #define S3C2410_MISCCR_CLK0_MASK    (7<<4)
 #define S3C2410_MISCCR_CLK0_MASK    (7<<4)
 
 
+#define S3C2412_MISCCR_CLK0_RTC	    (2<<4)
+
 #define S3C2410_MISCCR_CLK1_MPLL    (0<<8)
 #define S3C2410_MISCCR_CLK1_MPLL    (0<<8)
 #define S3C2410_MISCCR_CLK1_UPLL    (1<<8)
 #define S3C2410_MISCCR_CLK1_UPLL    (1<<8)
 #define S3C2410_MISCCR_CLK1_FCLK    (2<<8)
 #define S3C2410_MISCCR_CLK1_FCLK    (2<<8)
@@ -993,6 +1008,8 @@
 #define S3C2410_MISCCR_CLK1_DCLK1   (5<<8)
 #define S3C2410_MISCCR_CLK1_DCLK1   (5<<8)
 #define S3C2410_MISCCR_CLK1_MASK    (7<<8)
 #define S3C2410_MISCCR_CLK1_MASK    (7<<8)
 
 
+#define S3C2412_MISCCR_CLK1_CLKsrc  (0<<8)
+
 #define S3C2410_MISCCR_USBSUSPND0   (1<<12)
 #define S3C2410_MISCCR_USBSUSPND0   (1<<12)
 #define S3C2410_MISCCR_USBSUSPND1   (1<<13)
 #define S3C2410_MISCCR_USBSUSPND1   (1<<13)
 
 
@@ -1000,7 +1017,7 @@
 
 
 #define S3C2410_MISCCR_nEN_SCLK0    (1<<17)
 #define S3C2410_MISCCR_nEN_SCLK0    (1<<17)
 #define S3C2410_MISCCR_nEN_SCLK1    (1<<18)
 #define S3C2410_MISCCR_nEN_SCLK1    (1<<18)
-#define S3C2410_MISCCR_nEN_SCLKE    (1<<19)
+#define S3C2410_MISCCR_nEN_SCLKE    (1<<19)	/* not 2412 */
 #define S3C2410_MISCCR_SDSLEEP	    (7<<17)
 #define S3C2410_MISCCR_SDSLEEP	    (7<<17)
 
 
 /* external interrupt control... */
 /* external interrupt control... */
@@ -1017,6 +1034,10 @@
 #define S3C2410_EXTINT1	   S3C2410_GPIOREG(0x8C)
 #define S3C2410_EXTINT1	   S3C2410_GPIOREG(0x8C)
 #define S3C2410_EXTINT2	   S3C2410_GPIOREG(0x90)
 #define S3C2410_EXTINT2	   S3C2410_GPIOREG(0x90)
 
 
+#define S3C24XX_EXTINT0	   S3C24XX_GPIOREG2(0x88)
+#define S3C24XX_EXTINT1	   S3C24XX_GPIOREG2(0x8C)
+#define S3C24XX_EXTINT2	   S3C24XX_GPIOREG2(0x90)
+
 /* values for S3C2410_EXTINT0/1/2 */
 /* values for S3C2410_EXTINT0/1/2 */
 #define S3C2410_EXTINT_LOWLEV	 (0x00)
 #define S3C2410_EXTINT_LOWLEV	 (0x00)
 #define S3C2410_EXTINT_HILEV	 (0x01)
 #define S3C2410_EXTINT_HILEV	 (0x01)
@@ -1030,6 +1051,11 @@
 #define S3C2410_EINFLT2	   S3C2410_GPIOREG(0x9C)
 #define S3C2410_EINFLT2	   S3C2410_GPIOREG(0x9C)
 #define S3C2410_EINFLT3	   S3C2410_GPIOREG(0xA0)
 #define S3C2410_EINFLT3	   S3C2410_GPIOREG(0xA0)
 
 
+#define S3C24XX_EINFLT0	   S3C24XX_GPIOREG2(0x94)
+#define S3C24XX_EINFLT1	   S3C24XX_GPIOREG2(0x98)
+#define S3C24XX_EINFLT2	   S3C24XX_GPIOREG2(0x9C)
+#define S3C24XX_EINFLT3	   S3C24XX_GPIOREG2(0xA0)
+
 /* values for interrupt filtering */
 /* values for interrupt filtering */
 #define S3C2410_EINTFLT_PCLK		(0x00)
 #define S3C2410_EINTFLT_PCLK		(0x00)
 #define S3C2410_EINTFLT_EXTCLK		(1<<7)
 #define S3C2410_EINTFLT_EXTCLK		(1<<7)
@@ -1039,6 +1065,7 @@
 
 
 /* GSTATUS have miscellaneous information in them
 /* GSTATUS have miscellaneous information in them
  *
  *
+ * These move between s3c2410 and s3c2412 style systems.
  */
  */
 
 
 #define S3C2410_GSTATUS0   S3C2410_GPIOREG(0x0AC)
 #define S3C2410_GSTATUS0   S3C2410_GPIOREG(0x0AC)
@@ -1047,6 +1074,18 @@
 #define S3C2410_GSTATUS3   S3C2410_GPIOREG(0x0B8)
 #define S3C2410_GSTATUS3   S3C2410_GPIOREG(0x0B8)
 #define S3C2410_GSTATUS4   S3C2410_GPIOREG(0x0BC)
 #define S3C2410_GSTATUS4   S3C2410_GPIOREG(0x0BC)
 
 
+#define S3C2412_GSTATUS0   S3C2410_GPIOREG(0x0BC)
+#define S3C2412_GSTATUS1   S3C2410_GPIOREG(0x0C0)
+#define S3C2412_GSTATUS2   S3C2410_GPIOREG(0x0C4)
+#define S3C2412_GSTATUS3   S3C2410_GPIOREG(0x0C8)
+#define S3C2412_GSTATUS4   S3C2410_GPIOREG(0x0CC)
+
+#define S3C24XX_GSTATUS0   S3C24XX_GPIOREG2(0x0AC)
+#define S3C24XX_GSTATUS1   S3C24XX_GPIOREG2(0x0B0)
+#define S3C24XX_GSTATUS2   S3C24XX_GPIOREG2(0x0B4)
+#define S3C24XX_GSTATUS3   S3C24XX_GPIOREG2(0x0B8)
+#define S3C24XX_GSTATUS4   S3C24XX_GPIOREG2(0x0BC)
+
 #define S3C2410_GSTATUS0_nWAIT	   (1<<3)
 #define S3C2410_GSTATUS0_nWAIT	   (1<<3)
 #define S3C2410_GSTATUS0_NCON	   (1<<2)
 #define S3C2410_GSTATUS0_NCON	   (1<<2)
 #define S3C2410_GSTATUS0_RnB	   (1<<1)
 #define S3C2410_GSTATUS0_RnB	   (1<<1)
@@ -1054,6 +1093,7 @@
 
 
 #define S3C2410_GSTATUS1_IDMASK	   (0xffff0000)
 #define S3C2410_GSTATUS1_IDMASK	   (0xffff0000)
 #define S3C2410_GSTATUS1_2410	   (0x32410000)
 #define S3C2410_GSTATUS1_2410	   (0x32410000)
+#define S3C2410_GSTATUS1_2412	   (0x32412001)
 #define S3C2410_GSTATUS1_2440	   (0x32440000)
 #define S3C2410_GSTATUS1_2440	   (0x32440000)
 #define S3C2410_GSTATUS1_2442	   (0x32440aaa)
 #define S3C2410_GSTATUS1_2442	   (0x32440aaa)
 
 
@@ -1077,5 +1117,22 @@
 #define S3C2400_OPENCR_OPC_MOSIDIS  (0<<5)
 #define S3C2400_OPENCR_OPC_MOSIDIS  (0<<5)
 #define S3C2400_OPENCR_OPC_MOSIEN   (1<<5)
 #define S3C2400_OPENCR_OPC_MOSIEN   (1<<5)
 
 
+/* 2412/2413 sleep configuration registers */
+
+#define S3C2412_GPBSLPCON	S3C2410_GPIOREG(0x1C)
+#define S3C2412_GPCSLPCON	S3C2410_GPIOREG(0x2C)
+#define S3C2412_GPDSLPCON	S3C2410_GPIOREG(0x3C)
+#define S3C2412_GPESLPCON	S3C2410_GPIOREG(0x4C)
+#define S3C2412_GPFSLPCON	S3C2410_GPIOREG(0x5C)
+#define S3C2412_GPGSLPCON	S3C2410_GPIOREG(0x6C)
+#define S3C2412_GPHSLPCON	S3C2410_GPIOREG(0x7C)
+
+/* definitions for each pin bit */
+#define S3C2412_SLPCON_LOW(x)	( 0x00 << ((x) * 2))
+#define S3C2412_SLPCON_HI(x)	( 0x01 << ((x) * 2))
+#define S3C2412_SLPCON_IN(x)	( 0x02 << ((x) * 2))
+#define S3C2412_SLPCON_PDWN(x)	( 0x03 << ((x) * 2))
+#define S3C2412_SLPCON_MASK(x)	( 0x03 << ((x) * 2))
+
 #endif	/* __ASM_ARCH_REGS_GPIO_H */
 #endif	/* __ASM_ARCH_REGS_GPIO_H */
 
 

+ 5 - 0
include/asm-arm/arch-s3c2410/regs-gpioj.h

@@ -32,6 +32,11 @@
 #define S3C2440_GPJDAT	    S3C2410_GPIOREG(0xd4)
 #define S3C2440_GPJDAT	    S3C2410_GPIOREG(0xd4)
 #define S3C2440_GPJUP	    S3C2410_GPIOREG(0xd8)
 #define S3C2440_GPJUP	    S3C2410_GPIOREG(0xd8)
 
 
+#define S3C2413_GPJCON		S3C2410_GPIOREG(0x80)
+#define S3C2413_GPJDAT		S3C2410_GPIOREG(0x84)
+#define S3C2413_GPJUP		S3C2410_GPIOREG(0x88)
+#define S3C2413_GPJSLPCON	S3C2410_GPIOREG(0x8C)
+
 #define S3C2440_GPJ0            S3C2410_GPIONO(S3C2440_GPIO_BANKJ, 0)
 #define S3C2440_GPJ0            S3C2410_GPIONO(S3C2440_GPIO_BANKJ, 0)
 #define S3C2440_GPJ0_INP        (0x00 << 0)
 #define S3C2440_GPJ0_INP        (0x00 << 0)
 #define S3C2440_GPJ0_OUTP       (0x01 << 0)
 #define S3C2440_GPJ0_OUTP       (0x01 << 0)

+ 6 - 0
include/asm-arm/arch-s3c2410/regs-irq.h

@@ -23,6 +23,7 @@
 
 
 #define S3C2410_IRQREG(x)   ((x) + S3C24XX_VA_IRQ)
 #define S3C2410_IRQREG(x)   ((x) + S3C24XX_VA_IRQ)
 #define S3C2410_EINTREG(x)  ((x) + S3C24XX_VA_GPIO)
 #define S3C2410_EINTREG(x)  ((x) + S3C24XX_VA_GPIO)
+#define S3C24XX_EINTREG(x)  ((x) + S3C24XX_VA_GPIO2)
 
 
 #define S3C2410_SRCPND	       S3C2410_IRQREG(0x000)
 #define S3C2410_SRCPND	       S3C2410_IRQREG(0x000)
 #define S3C2410_INTMOD	       S3C2410_IRQREG(0x004)
 #define S3C2410_INTMOD	       S3C2410_IRQREG(0x004)
@@ -40,5 +41,10 @@
 
 
 #define S3C2410_EINTMASK       S3C2410_EINTREG(0x0A4)
 #define S3C2410_EINTMASK       S3C2410_EINTREG(0x0A4)
 #define S3C2410_EINTPEND       S3C2410_EINTREG(0X0A8)
 #define S3C2410_EINTPEND       S3C2410_EINTREG(0X0A8)
+#define S3C2412_EINTMASK       S3C2410_EINTREG(0x0B4)
+#define S3C2412_EINTPEND       S3C2410_EINTREG(0X0B8)
+
+#define S3C24XX_EINTMASK       S3C24XX_EINTREG(0x0A4)
+#define S3C24XX_EINTPEND       S3C24XX_EINTREG(0X0A8)
 
 
 #endif /* ___ASM_ARCH_REGS_IRQ_H */
 #endif /* ___ASM_ARCH_REGS_IRQ_H */

+ 15 - 0
include/asm-arm/arch-s3c2410/regs-serial.h

@@ -82,6 +82,12 @@
 #define S3C2440_UCON2_DIVMASK	  (7 << 12)
 #define S3C2440_UCON2_DIVMASK	  (7 << 12)
 #define S3C2440_UCON_DIVSHIFT	  (12)
 #define S3C2440_UCON_DIVSHIFT	  (12)
 
 
+#define S3C2412_UCON_CLKMASK	(3<<10)
+#define S3C2412_UCON_UCLK	(1<<10)
+#define S3C2412_UCON_USYSCLK	(3<<10)
+#define S3C2412_UCON_PCLK	(0<<10)
+#define S3C2412_UCON_PCLK2	(2<<10)
+
 #define S3C2410_UCON_UCLK	  (1<<10)
 #define S3C2410_UCON_UCLK	  (1<<10)
 #define S3C2410_UCON_SBREAK	  (1<<4)
 #define S3C2410_UCON_SBREAK	  (1<<4)
 
 
@@ -124,6 +130,15 @@
 #define	S3C2410_UMCOM_AFC	  (1<<4)
 #define	S3C2410_UMCOM_AFC	  (1<<4)
 #define	S3C2410_UMCOM_RTS_LOW	  (1<<0)
 #define	S3C2410_UMCOM_RTS_LOW	  (1<<0)
 
 
+#define S3C2412_UMCON_AFC_63	(0<<5)
+#define S3C2412_UMCON_AFC_56	(1<<5)
+#define S3C2412_UMCON_AFC_48	(2<<5)
+#define S3C2412_UMCON_AFC_40	(3<<5)
+#define S3C2412_UMCON_AFC_32	(4<<5)
+#define S3C2412_UMCON_AFC_24	(5<<5)
+#define S3C2412_UMCON_AFC_16	(6<<5)
+#define S3C2412_UMCON_AFC_8	(7<<5)
+
 #define S3C2410_UFSTAT_TXFULL	  (1<<9)
 #define S3C2410_UFSTAT_TXFULL	  (1<<9)
 #define S3C2410_UFSTAT_RXFULL	  (1<<8)
 #define S3C2410_UFSTAT_RXFULL	  (1<<8)
 #define S3C2410_UFSTAT_TXMASK	  (15<<4)
 #define S3C2410_UFSTAT_TXMASK	  (15<<4)

+ 0 - 1
include/asm-arm/arch-sa1100/io.h

@@ -22,6 +22,5 @@ static inline void __iomem *__io(unsigned long addr)
 }
 }
 #define __io(a)			__io(a)
 #define __io(a)			__io(a)
 #define __mem_pci(a)		(a)
 #define __mem_pci(a)		(a)
-#define __mem_isa(a)		(a)
 
 
 #endif
 #endif

+ 0 - 1
include/asm-arm/arch-versatile/io.h

@@ -28,6 +28,5 @@ static inline void __iomem *__io(unsigned long addr)
 }
 }
 #define __io(a)	__io(a)
 #define __io(a)	__io(a)
 #define __mem_pci(a)		(a)
 #define __mem_pci(a)		(a)
-#define __mem_isa(a)		(a)
 
 
 #endif
 #endif

+ 78 - 1
include/asm-arm/ucontext.h

@@ -1,12 +1,89 @@
 #ifndef _ASMARM_UCONTEXT_H
 #ifndef _ASMARM_UCONTEXT_H
 #define _ASMARM_UCONTEXT_H
 #define _ASMARM_UCONTEXT_H
 
 
+#include <asm/fpstate.h>
+
+/*
+ * struct sigcontext only has room for the basic registers, but struct
+ * ucontext now has room for all registers which need to be saved and
+ * restored.  Coprocessor registers are stored in uc_regspace.  Each
+ * coprocessor's saved state should start with a documented 32-bit magic
+ * number, followed by a 32-bit word giving the coproccesor's saved size.
+ * uc_regspace may be expanded if necessary, although this takes some
+ * coordination with glibc.
+ */
+
 struct ucontext {
 struct ucontext {
 	unsigned long	  uc_flags;
 	unsigned long	  uc_flags;
 	struct ucontext  *uc_link;
 	struct ucontext  *uc_link;
 	stack_t		  uc_stack;
 	stack_t		  uc_stack;
 	struct sigcontext uc_mcontext;
 	struct sigcontext uc_mcontext;
-	sigset_t	  uc_sigmask;	/* mask last for extensibility */
+	sigset_t	  uc_sigmask;
+	/* Allow for uc_sigmask growth.  Glibc uses a 1024-bit sigset_t.  */
+	int		  __unused[32 - (sizeof (sigset_t) / sizeof (int))];
+	/* Last for extensibility.  Eight byte aligned because some
+	   coprocessors require eight byte alignment.  */
+ 	unsigned long	  uc_regspace[128] __attribute__((__aligned__(8)));
 };
 };
 
 
+#ifdef __KERNEL__
+
+/*
+ * Coprocessor save state.  The magic values and specific
+ * coprocessor's layouts are part of the userspace ABI.  Each one of
+ * these should be a multiple of eight bytes and aligned to eight
+ * bytes, to prevent unpredictable padding in the signal frame.
+ */
+
+#ifdef CONFIG_IWMMXT
+/* iwmmxt_area is 0x98 bytes long, preceeded by 8 bytes of signature */
+#define IWMMXT_MAGIC		0x12ef842a
+#define IWMMXT_STORAGE_SIZE	(IWMMXT_SIZE + 8)
+
+struct iwmmxt_sigframe {
+	unsigned long	magic;
+	unsigned long	size;
+	struct iwmmxt_struct storage;
+} __attribute__((__aligned__(8)));
+#endif /* CONFIG_IWMMXT */
+
+#ifdef CONFIG_VFP
+#if __LINUX_ARM_ARCH__ < 6
+/* For ARM pre-v6, we use fstmiax and fldmiax.  This adds one extra
+ * word after the registers, and a word of padding at the end for
+ * alignment.  */
+#define VFP_MAGIC		0x56465001
+#define VFP_STORAGE_SIZE	152
+#else
+#define VFP_MAGIC		0x56465002
+#define VFP_STORAGE_SIZE	144
+#endif
+
+struct vfp_sigframe
+{
+	unsigned long		magic;
+	unsigned long		size;
+	union vfp_state		storage;
+};
+#endif /* CONFIG_VFP */
+
+/*
+ * Auxiliary signal frame.  This saves stuff like FP state.
+ * The layout of this structure is not part of the user ABI,
+ * because the config options aren't.  uc_regspace is really
+ * one of these.
+ */
+struct aux_sigframe {
+#ifdef CONFIG_IWMMXT
+	struct iwmmxt_sigframe	iwmmxt;
+#endif
+#if 0 && defined CONFIG_VFP /* Not yet saved.  */
+	struct vfp_sigframe	vfp;
+#endif
+	/* Something that isn't a valid magic number for any coprocessor.  */
+	unsigned long		end_magic;
+} __attribute__((__aligned__(8)));
+
+#endif
+
 #endif /* !_ASMARM_UCONTEXT_H */
 #endif /* !_ASMARM_UCONTEXT_H */

+ 3 - 0
include/linux/serial_core.h

@@ -130,6 +130,9 @@
 /* SUN4V Hypervisor Console */
 /* SUN4V Hypervisor Console */
 #define PORT_SUNHV	72
 #define PORT_SUNHV	72
 
 
+#define PORT_S3C2412	73
+
+
 #ifdef __KERNEL__
 #ifdef __KERNEL__
 
 
 #include <linux/compiler.h>
 #include <linux/compiler.h>