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 ...
This commit is contained in:
commit
dfd8317d33
|
@ -273,7 +273,7 @@ ENTRY(iwmmxt_task_restore)
|
|||
*
|
||||
* r0 = previous task_struct pointer (must be preserved)
|
||||
* 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.
|
||||
* No need to care about preserving r4 and above.
|
||||
|
|
|
@ -134,17 +134,6 @@ sys_sigaction(int sig, const struct old_sigaction __user *act,
|
|||
|
||||
#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)
|
||||
{
|
||||
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 */
|
||||
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);
|
||||
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);
|
||||
if (__copy_from_user(kframe, frame, sizeof(*frame)))
|
||||
return -1;
|
||||
if (kframe->magic0 != IWMMXT_MAGIC0 ||
|
||||
kframe->magic1 != IWMMXT_MAGIC1)
|
||||
if (kframe->magic != IWMMXT_MAGIC ||
|
||||
kframe->size != IWMMXT_STORAGE_SIZE)
|
||||
return -1;
|
||||
iwmmxt_task_restore(current_thread_info(), &kframe->storage);
|
||||
return 0;
|
||||
|
@ -176,71 +165,62 @@ static int restore_iwmmxt_context(struct iwmmxt_sigframe *frame)
|
|||
|
||||
#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.
|
||||
*/
|
||||
struct sigframe {
|
||||
struct sigcontext sc;
|
||||
unsigned long extramask[_NSIG_WORDS-1];
|
||||
struct ucontext uc;
|
||||
unsigned long retcode[2];
|
||||
struct aux_sigframe aux __attribute__((aligned(8)));
|
||||
};
|
||||
|
||||
struct rt_sigframe {
|
||||
struct siginfo __user *pinfo;
|
||||
void __user *puc;
|
||||
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;
|
||||
|
||||
__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);
|
||||
err = __copy_from_user(&set, &sf->uc.uc_sigmask, sizeof(set));
|
||||
if (err == 0) {
|
||||
sigdelsetmask(&set, ~_BLOCKABLE);
|
||||
spin_lock_irq(¤t->sighand->siglock);
|
||||
current->blocked = set;
|
||||
recalc_sigpending();
|
||||
spin_unlock_irq(¤t->sighand->siglock);
|
||||
}
|
||||
|
||||
__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);
|
||||
|
||||
aux = (struct aux_sigframe __user *) sf->uc.uc_regspace;
|
||||
#ifdef CONFIG_IWMMXT
|
||||
if (err == 0 && test_thread_flag(TIF_USING_IWMMXT))
|
||||
err |= restore_iwmmxt_context(&aux->iwmmxt);
|
||||
#endif
|
||||
#ifdef CONFIG_VFP
|
||||
// if (err == 0)
|
||||
// err |= vfp_restore_state(&aux->vfp);
|
||||
// err |= vfp_restore_state(&sf->aux.vfp);
|
||||
#endif
|
||||
|
||||
return err;
|
||||
|
@ -249,7 +229,6 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc,
|
|||
asmlinkage int sys_sigreturn(struct pt_regs *regs)
|
||||
{
|
||||
struct sigframe __user *frame;
|
||||
sigset_t set;
|
||||
|
||||
/* Always make any pending restarted system calls return -EINTR */
|
||||
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)))
|
||||
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(¤t->sighand->siglock);
|
||||
current->blocked = set;
|
||||
recalc_sigpending();
|
||||
spin_unlock_irq(¤t->sighand->siglock);
|
||||
|
||||
if (restore_sigcontext(regs, &frame->sc, &frame->aux))
|
||||
if (restore_sigframe(regs, frame))
|
||||
goto badframe;
|
||||
|
||||
/* Send SIGTRAP if we're single-stepping */
|
||||
|
@ -297,7 +265,6 @@ badframe:
|
|||
asmlinkage int sys_rt_sigreturn(struct pt_regs *regs)
|
||||
{
|
||||
struct rt_sigframe __user *frame;
|
||||
sigset_t set;
|
||||
|
||||
/* Always make any pending restarted system calls return -EINTR */
|
||||
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)))
|
||||
goto badframe;
|
||||
if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
|
||||
|
||||
if (restore_sigframe(regs, &frame->sig))
|
||||
goto badframe;
|
||||
|
||||
sigdelsetmask(&set, ~_BLOCKABLE);
|
||||
spin_lock_irq(¤t->sighand->siglock);
|
||||
current->blocked = set;
|
||||
recalc_sigpending();
|
||||
spin_unlock_irq(¤t->sighand->siglock);
|
||||
|
||||
if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &frame->aux))
|
||||
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;
|
||||
|
||||
/* Send SIGTRAP if we're single-stepping */
|
||||
|
@ -343,42 +302,46 @@ badframe:
|
|||
}
|
||||
|
||||
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;
|
||||
|
||||
__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(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, &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(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
|
||||
if (err == 0 && test_thread_flag(TIF_USING_IWMMXT))
|
||||
err |= preserve_iwmmxt_context(&aux->iwmmxt);
|
||||
#endif
|
||||
#ifdef CONFIG_VFP
|
||||
// if (err == 0)
|
||||
// err |= vfp_save_state(&aux->vfp);
|
||||
// err |= vfp_save_state(&sf->aux.vfp);
|
||||
#endif
|
||||
__put_user_error(0, &aux->end_magic, err);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
@ -487,13 +450,12 @@ setup_frame(int usig, struct k_sigaction *ka, sigset_t *set, struct pt_regs *reg
|
|||
if (!frame)
|
||||
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)
|
||||
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)
|
||||
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);
|
||||
|
||||
__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));
|
||||
stack.ss_sp = (void __user *)current->sas_ss_sp;
|
||||
stack.ss_flags = sas_ss_flags(regs->ARM_sp);
|
||||
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)
|
||||
err = setup_return(regs, ka, frame->retcode, frame, usig);
|
||||
err = setup_return(regs, ka, frame->sig.retcode, frame, usig);
|
||||
|
||||
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
|
||||
*/
|
||||
regs->ARM_r1 = (unsigned long)&frame->info;
|
||||
regs->ARM_r2 = (unsigned long)&frame->uc;
|
||||
regs->ARM_r2 = (unsigned long)&frame->sig.uc;
|
||||
}
|
||||
|
||||
return err;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#
|
||||
# Makefile for the linux kernel.
|
||||
#
|
||||
obj-y := core.o
|
||||
obj-y := core.o clock.o
|
||||
obj-m :=
|
||||
obj-n :=
|
||||
obj- :=
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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)
|
||||
{
|
||||
unsigned int v;
|
||||
|
||||
ep93xx_clock_init();
|
||||
|
||||
/*
|
||||
* Disallow access to MaverickCrunch initially.
|
||||
*/
|
||||
|
@ -450,4 +477,5 @@ void __init ep93xx_init_devices(void)
|
|||
amba_device_register(&uart3_device, &iomem_resource);
|
||||
|
||||
platform_device_register(&ep93xx_rtc_device);
|
||||
platform_device_register(&ep93xx_ohci_device);
|
||||
}
|
||||
|
|
|
@ -302,6 +302,7 @@ void gpio_line_config(int line, int direction)
|
|||
}
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
EXPORT_SYMBOL(gpio_line_config);
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
|
|
|
@ -81,6 +81,12 @@ config SMDK2440_CPU2442
|
|||
depends on ARCH_S3C2440
|
||||
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
|
||||
bool "Thorcom VR1000"
|
||||
|
@ -127,6 +133,20 @@ config CPU_S3C2410
|
|||
Support for S3C2410 and S3C2410A family from the S3C24XX line
|
||||
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
|
||||
bool
|
||||
depends on ARCH_S3C2410 && (CPU_S3C2440 || CPU_S3C2442)
|
||||
|
|
|
@ -24,6 +24,11 @@ obj-$(CONFIG_S3C2410_DMA) += dma.o
|
|||
obj-$(CONFIG_PM) += pm.o sleep.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
|
||||
|
||||
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_MACH_N30) += mach-n30.o
|
||||
obj-$(CONFIG_ARCH_SMDK2410) += mach-smdk2410.o
|
||||
obj-$(CONFIG_MACH_SMDK2413) += mach-smdk2413.o
|
||||
obj-$(CONFIG_ARCH_S3C2440) += mach-smdk2440.o
|
||||
obj-$(CONFIG_MACH_VR1000) += mach-vr1000.o usb-simtec.o
|
||||
obj-$(CONFIG_MACH_RX3715) += mach-rx3715.o
|
||||
|
|
|
@ -213,7 +213,7 @@ EXPORT_SYMBOL(clk_set_parent);
|
|||
|
||||
/* base clocks */
|
||||
|
||||
static struct clk clk_xtal = {
|
||||
struct clk clk_xtal = {
|
||||
.name = "xtal",
|
||||
.id = -1,
|
||||
.rate = 0,
|
||||
|
@ -221,6 +221,11 @@ static struct clk clk_xtal = {
|
|||
.ctrlbit = 0,
|
||||
};
|
||||
|
||||
struct clk clk_mpll = {
|
||||
.name = "mpll",
|
||||
.id = -1,
|
||||
};
|
||||
|
||||
struct clk clk_upll = {
|
||||
.name = "upll",
|
||||
.id = -1,
|
||||
|
@ -232,7 +237,7 @@ struct clk clk_f = {
|
|||
.name = "fclk",
|
||||
.id = -1,
|
||||
.rate = 0,
|
||||
.parent = NULL,
|
||||
.parent = &clk_mpll,
|
||||
.ctrlbit = 0,
|
||||
};
|
||||
|
||||
|
@ -263,14 +268,14 @@ struct clk clk_usb_bus = {
|
|||
|
||||
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)
|
||||
dclkcon |= clk->ctrlbit;
|
||||
else
|
||||
dclkcon &= ~clk->ctrlbit;
|
||||
|
||||
__raw_writel(dclkcon, S3C2410_DCLKCON);
|
||||
__raw_writel(dclkcon, S3C24XX_DCLKCON);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -289,7 +294,7 @@ static int s3c24xx_dclk_setparent(struct clk *clk, struct clk *parent)
|
|||
|
||||
clk->parent = parent;
|
||||
|
||||
dclkcon = __raw_readl(S3C2410_DCLKCON);
|
||||
dclkcon = __raw_readl(S3C24XX_DCLKCON);
|
||||
|
||||
if (clk->ctrlbit == S3C2410_DCLKCON_DCLK0EN) {
|
||||
if (uclk)
|
||||
|
@ -303,7 +308,7 @@ static int s3c24xx_dclk_setparent(struct clk *clk, struct clk *parent)
|
|||
dclkcon &= ~S3C2410_DCLKCON_DCLK1_UCLK;
|
||||
}
|
||||
|
||||
__raw_writel(dclkcon, S3C2410_DCLKCON);
|
||||
__raw_writel(dclkcon, S3C24XX_DCLKCON);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -413,6 +418,7 @@ int __init s3c24xx_setup_clocks(unsigned long xtal,
|
|||
clk_xtal.rate = xtal;
|
||||
clk_upll.rate = s3c2410_get_pll(__raw_readl(S3C2410_UPLLCON), xtal);
|
||||
|
||||
clk_mpll.rate = fclk;
|
||||
clk_h.rate = hclk;
|
||||
clk_p.rate = pclk;
|
||||
clk_f.rate = fclk;
|
||||
|
@ -424,6 +430,9 @@ int __init s3c24xx_setup_clocks(unsigned long xtal,
|
|||
if (s3c24xx_register_clock(&clk_xtal) < 0)
|
||||
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)
|
||||
printk(KERN_ERR "failed to register upll clock\n");
|
||||
|
||||
|
|
|
@ -42,7 +42,9 @@ extern struct clk clk_usb_bus;
|
|||
extern struct clk clk_f;
|
||||
extern struct clk clk_h;
|
||||
extern struct clk clk_p;
|
||||
extern struct clk clk_mpll;
|
||||
extern struct clk clk_upll;
|
||||
extern struct clk clk_xtal;
|
||||
|
||||
/* exports for arch/arm/mach-s3c2410
|
||||
*
|
||||
|
|
|
@ -44,6 +44,7 @@
|
|||
#include "clock.h"
|
||||
#include "s3c2400.h"
|
||||
#include "s3c2410.h"
|
||||
#include "s3c2412.h"
|
||||
#include "s3c244x.h"
|
||||
#include "s3c2440.h"
|
||||
#include "s3c2442.h"
|
||||
|
@ -62,6 +63,7 @@ struct cpu_table {
|
|||
|
||||
static const char name_s3c2400[] = "S3C2400";
|
||||
static const char name_s3c2410[] = "S3C2410";
|
||||
static const char name_s3c2412[] = "S3C2412";
|
||||
static const char name_s3c2440[] = "S3C2440";
|
||||
static const char name_s3c2442[] = "S3C2442";
|
||||
static const char name_s3c2410a[] = "S3C2410A";
|
||||
|
@ -113,6 +115,15 @@ static struct cpu_table cpu_ids[] __initdata = {
|
|||
.init = s3c2442_init,
|
||||
.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 */
|
||||
.idmask = 0xffffffff,
|
||||
|
@ -171,6 +182,24 @@ void s3c24xx_set_board(struct s3c24xx_board *b)
|
|||
|
||||
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)
|
||||
{
|
||||
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 */
|
||||
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);
|
||||
|
||||
|
|
|
@ -74,5 +74,6 @@ extern struct sys_timer s3c24xx_timer;
|
|||
/* system device classes */
|
||||
|
||||
extern struct sysdev_class s3c2410_sysclass;
|
||||
extern struct sysdev_class s3c2412_sysclass;
|
||||
extern struct sysdev_class s3c2440_sysclass;
|
||||
extern struct sysdev_class s3c2442_sysclass;
|
||||
|
|
|
@ -191,13 +191,9 @@ static struct irqchip s3c_irq_chip = {
|
|||
.ack = s3c_irq_ack,
|
||||
.mask = s3c_irq_mask,
|
||||
.unmask = s3c_irq_unmask,
|
||||
.set_wake = s3c_irq_wake
|
||||
.set_wake = s3c_irq_wake
|
||||
};
|
||||
|
||||
/* S3C2410_EINTMASK
|
||||
* S3C2410_EINTPEND
|
||||
*/
|
||||
|
||||
static void
|
||||
s3c_irqext_mask(unsigned int irqno)
|
||||
{
|
||||
|
@ -205,9 +201,9 @@ s3c_irqext_mask(unsigned int irqno)
|
|||
|
||||
irqno -= EXTINT_OFF;
|
||||
|
||||
mask = __raw_readl(S3C2410_EINTMASK);
|
||||
mask = __raw_readl(S3C24XX_EINTMASK);
|
||||
mask |= ( 1UL << irqno);
|
||||
__raw_writel(mask, S3C2410_EINTMASK);
|
||||
__raw_writel(mask, S3C24XX_EINTMASK);
|
||||
|
||||
if (irqno <= (IRQ_EINT7 - EXTINT_OFF)) {
|
||||
/* check to see if all need masking */
|
||||
|
@ -232,11 +228,11 @@ s3c_irqext_ack(unsigned int irqno)
|
|||
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;
|
||||
|
||||
/* not sure if we should be acking the parent irq... */
|
||||
|
@ -257,9 +253,9 @@ s3c_irqext_unmask(unsigned int irqno)
|
|||
|
||||
irqno -= EXTINT_OFF;
|
||||
|
||||
mask = __raw_readl(S3C2410_EINTMASK);
|
||||
mask = __raw_readl(S3C24XX_EINTMASK);
|
||||
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);
|
||||
}
|
||||
|
@ -275,28 +271,28 @@ s3c_irqext_type(unsigned int irq, unsigned int type)
|
|||
if ((irq >= IRQ_EINT0) && (irq <= IRQ_EINT3))
|
||||
{
|
||||
gpcon_reg = S3C2410_GPFCON;
|
||||
extint_reg = S3C2410_EXTINT0;
|
||||
extint_reg = S3C24XX_EXTINT0;
|
||||
gpcon_offset = (irq - IRQ_EINT0) * 2;
|
||||
extint_offset = (irq - IRQ_EINT0) * 4;
|
||||
}
|
||||
else if ((irq >= IRQ_EINT4) && (irq <= IRQ_EINT7))
|
||||
{
|
||||
gpcon_reg = S3C2410_GPFCON;
|
||||
extint_reg = S3C2410_EXTINT0;
|
||||
extint_reg = S3C24XX_EXTINT0;
|
||||
gpcon_offset = (irq - (EXTINT_OFF)) * 2;
|
||||
extint_offset = (irq - (EXTINT_OFF)) * 4;
|
||||
}
|
||||
else if ((irq >= IRQ_EINT8) && (irq <= IRQ_EINT15))
|
||||
{
|
||||
gpcon_reg = S3C2410_GPGCON;
|
||||
extint_reg = S3C2410_EXTINT1;
|
||||
extint_reg = S3C24XX_EXTINT1;
|
||||
gpcon_offset = (irq - IRQ_EINT8) * 2;
|
||||
extint_offset = (irq - IRQ_EINT8) * 4;
|
||||
}
|
||||
else if ((irq >= IRQ_EINT16) && (irq <= IRQ_EINT23))
|
||||
{
|
||||
gpcon_reg = S3C2410_GPGCON;
|
||||
extint_reg = S3C2410_EXTINT2;
|
||||
extint_reg = S3C24XX_EXTINT2;
|
||||
gpcon_offset = (irq - IRQ_EINT8) * 2;
|
||||
extint_offset = (irq - IRQ_EINT16) * 4;
|
||||
} else
|
||||
|
@ -572,6 +568,23 @@ s3c_irq_demux_uart2(unsigned int irq,
|
|||
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
|
||||
*
|
||||
|
@ -591,12 +604,12 @@ void __init s3c24xx_init_irq(void)
|
|||
|
||||
last = 0;
|
||||
for (i = 0; i < 4; i++) {
|
||||
pend = __raw_readl(S3C2410_EINTPEND);
|
||||
pend = __raw_readl(S3C24XX_EINTPEND);
|
||||
|
||||
if (pend == 0 || pend == last)
|
||||
break;
|
||||
|
||||
__raw_writel(pend, S3C2410_EINTPEND);
|
||||
__raw_writel(pend, S3C24XX_EINTPEND);
|
||||
printk("irq: clearing pending ext status %08x\n", (int)pend);
|
||||
last = pend;
|
||||
}
|
||||
|
@ -630,12 +643,14 @@ void __init s3c24xx_init_irq(void)
|
|||
|
||||
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 */
|
||||
|
||||
switch (irqno) {
|
||||
/* deal with the special IRQs (cascaded) */
|
||||
|
||||
case IRQ_EINT4t7:
|
||||
case IRQ_EINT8t23:
|
||||
case IRQ_UART0:
|
||||
case IRQ_UART1:
|
||||
case IRQ_UART2:
|
||||
|
@ -659,12 +674,14 @@ void __init s3c24xx_init_irq(void)
|
|||
|
||||
/* 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_UART1, s3c_irq_demux_uart1);
|
||||
set_irq_chained_handler(IRQ_UART2, s3c_irq_demux_uart2);
|
||||
set_irq_chained_handler(IRQ_ADCPARENT, s3c_irq_demux_adc);
|
||||
|
||||
|
||||
/* external interrupts */
|
||||
|
||||
for (irqno = IRQ_EINT0; irqno <= IRQ_EINT3; irqno++) {
|
||||
|
|
|
@ -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
|
|
@ -48,7 +48,8 @@ static __init int pm_simtec_init(void)
|
|||
|
||||
/* 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;
|
||||
|
||||
printk(KERN_INFO "Simtec Board Power Manangement" COPYRIGHT "\n");
|
||||
|
|
|
@ -182,7 +182,15 @@ static struct clk init_clocks[] = {
|
|||
.id = -1,
|
||||
.parent = &clk_p,
|
||||
.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()
|
||||
|
|
|
@ -18,9 +18,6 @@
|
|||
* 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
|
||||
*
|
||||
* Changelog
|
||||
* 15-Jan-2006 LCVR Splitted from gpio.c
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
|
@ -38,7 +35,7 @@
|
|||
int s3c2410_gpio_irqfilter(unsigned int pin, unsigned int on,
|
||||
unsigned int config)
|
||||
{
|
||||
void __iomem *reg = S3C2410_EINFLT0;
|
||||
void __iomem *reg = S3C24XX_EINFLT0;
|
||||
unsigned long flags;
|
||||
unsigned long val;
|
||||
|
||||
|
@ -47,7 +44,7 @@ int s3c2410_gpio_irqfilter(unsigned int pin, unsigned int on,
|
|||
|
||||
config &= 0xff;
|
||||
|
||||
pin -= S3C2410_GPG8_EINT16;
|
||||
pin -= S3C2410_GPG8;
|
||||
reg += pin & ~3;
|
||||
|
||||
local_irq_save(flags);
|
||||
|
@ -61,10 +58,10 @@ int s3c2410_gpio_irqfilter(unsigned int pin, unsigned int on,
|
|||
|
||||
/* update filter enable */
|
||||
|
||||
val = __raw_readl(S3C2410_EXTINT2);
|
||||
val = __raw_readl(S3C24XX_EXTINT2);
|
||||
val &= ~(1 << ((pin * 4) + 3));
|
||||
val |= on << ((pin * 4) + 3);
|
||||
__raw_writel(val, S3C2410_EXTINT2);
|
||||
__raw_writel(val, S3C24XX_EXTINT2);
|
||||
|
||||
local_irq_restore(flags);
|
||||
|
||||
|
@ -75,7 +72,7 @@ EXPORT_SYMBOL(s3c2410_gpio_irqfilter);
|
|||
|
||||
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 */
|
||||
|
||||
if (pin < S3C2410_GPG0 && pin > S3C2410_GPF7)
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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
|
|
@ -61,9 +61,9 @@ config CPU_ARM720T
|
|||
|
||||
# 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_ABRT_EV4T
|
||||
select CPU_CACHE_V4WT
|
||||
|
@ -121,8 +121,8 @@ config CPU_ARM925T
|
|||
# ARM926T
|
||||
config CPU_ARM926T
|
||||
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_ABRT_EV5TJ
|
||||
select CPU_CACHE_VIVT
|
||||
|
|
|
@ -354,21 +354,24 @@ config SERIAL_CLPS711X_CONSOLE
|
|||
kernel at boot time.)
|
||||
|
||||
config SERIAL_S3C2410
|
||||
tristate "Samsung S3C2410 Serial port support"
|
||||
tristate "Samsung S3C2410/S3C2440/S3C2442/S3C2412 Serial port support"
|
||||
depends on ARM && ARCH_S3C2410
|
||||
select SERIAL_CORE
|
||||
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
|
||||
provide all of these ports, depending on how the serial port
|
||||
pins are configured.
|
||||
|
||||
Currently this driver supports the UARTS on the S3C2410, S3C2440,
|
||||
S3C2442, S3C2412 and S3C2413 CPUs.
|
||||
|
||||
config SERIAL_S3C2410_CONSOLE
|
||||
bool "Support for console on S3C2410 serial port"
|
||||
depends on SERIAL_S3C2410=y
|
||||
select SERIAL_CORE_CONSOLE
|
||||
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.
|
||||
|
||||
Even if you say Y here, the currently visible virtual console
|
||||
|
|
|
@ -872,6 +872,8 @@ static const char *s3c24xx_serial_type(struct uart_port *port)
|
|||
return "S3C2410";
|
||||
case PORT_S3C2440:
|
||||
return "S3C2440";
|
||||
case PORT_S3C2412:
|
||||
return "S3C2412";
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
|
@ -1528,6 +1530,141 @@ static inline void s3c2440_serial_exit(void)
|
|||
#define s3c2440_uart_inf_at NULL
|
||||
#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 */
|
||||
|
||||
static int __init s3c24xx_serial_modinit(void)
|
||||
|
@ -1542,6 +1679,7 @@ static int __init s3c24xx_serial_modinit(void)
|
|||
|
||||
s3c2400_serial_init();
|
||||
s3c2410_serial_init();
|
||||
s3c2412_serial_init();
|
||||
s3c2440_serial_init();
|
||||
|
||||
return 0;
|
||||
|
@ -1551,6 +1689,7 @@ static void __exit s3c24xx_serial_modexit(void)
|
|||
{
|
||||
s3c2400_serial_exit();
|
||||
s3c2410_serial_exit();
|
||||
s3c2412_serial_exit();
|
||||
s3c2440_serial_exit();
|
||||
|
||||
uart_unregister_driver(&s3c24xx_uart_drv);
|
||||
|
@ -1773,6 +1912,8 @@ static int s3c24xx_serial_initconsole(void)
|
|||
info = s3c2410_uart_inf_at;
|
||||
} else if (strcmp(dev->name, "s3c2440-uart") == 0) {
|
||||
info = s3c2440_uart_inf_at;
|
||||
} else if (strcmp(dev->name, "s3c2412-uart") == 0) {
|
||||
info = s3c2412_uart_inf_at;
|
||||
} else {
|
||||
printk(KERN_ERR "s3c24xx: no driver for %s\n", dev->name);
|
||||
return 0;
|
||||
|
@ -1796,4 +1937,4 @@ console_initcall(s3c24xx_serial_initconsole);
|
|||
|
||||
MODULE_LICENSE("GPL");
|
||||
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");
|
||||
|
|
|
@ -16,6 +16,5 @@
|
|||
*/
|
||||
#define __io(a) ((void __iomem *)(a))
|
||||
#define __mem_pci(a) (a)
|
||||
#define __mem_isa(a) (a)
|
||||
|
||||
#endif
|
||||
|
|
|
@ -26,7 +26,6 @@
|
|||
|
||||
#define __io(a) ((void __iomem *)(a))
|
||||
#define __mem_pci(a) (a)
|
||||
#define __mem_isa(a) (a)
|
||||
|
||||
/*
|
||||
* We don't support ins[lb]/outs[lb]. Make them fault.
|
||||
|
|
|
@ -24,7 +24,6 @@
|
|||
#define __io(a) ((void __iomem *)(PCIO_BASE + (a)))
|
||||
#if 1
|
||||
#define __mem_pci(a) (a)
|
||||
#define __mem_isa(a) ((a) + PCIMEM_BASE)
|
||||
#else
|
||||
|
||||
static inline void __iomem *___mem_pci(void __iomem *p)
|
||||
|
@ -34,14 +33,7 @@ static inline void __iomem *___mem_pci(void __iomem *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_isa(a) ___mem_isa(a)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
@ -115,6 +115,8 @@
|
|||
#define EP93XX_SYSCON_CLOCK_USH_EN 0x10000000
|
||||
#define EP93XX_SYSCON_HALT EP93XX_SYSCON_REG(0x08)
|
||||
#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_CRUNCH_ENABLE 0x00800000
|
||||
#define EP93XX_SYSCON_SWLOCK EP93XX_SYSCON_REG(0xc0)
|
||||
|
|
|
@ -8,6 +8,7 @@ void ep93xx_map_io(void);
|
|||
void ep93xx_init_irq(void);
|
||||
void ep93xx_init_time(unsigned long);
|
||||
void ep93xx_init_devices(void);
|
||||
void ep93xx_clock_init(void);
|
||||
extern struct sys_timer ep93xx_timer;
|
||||
|
||||
|
||||
|
|
|
@ -32,6 +32,5 @@
|
|||
|
||||
#define __io(a) ((void __iomem *)(PCI_IO_VADDR + (a)))
|
||||
#define __mem_pci(a) (a)
|
||||
#define __mem_isa(a) ((a) + PCI_MEMORY_VADDR)
|
||||
|
||||
#endif
|
||||
|
|
|
@ -17,6 +17,5 @@
|
|||
|
||||
#define __io(p) ((void __iomem *)(p))
|
||||
#define __mem_pci(a) (a)
|
||||
#define __mem_isa(a) (a)
|
||||
|
||||
#endif
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
*/
|
||||
#define __io_pci(a) ((void __iomem *)(PCIO_BASE + (a)))
|
||||
#define __mem_pci(a) (a)
|
||||
#define __mem_isa(a) (a)
|
||||
|
||||
#define __ioaddr(p) __io_pci(p)
|
||||
|
||||
|
|
|
@ -18,6 +18,5 @@
|
|||
/* No ISA or PCI bus on this machine. */
|
||||
#define __io(a) ((void __iomem *)(a))
|
||||
#define __mem_pci(a) (a)
|
||||
#define __mem_isa(a) (a)
|
||||
|
||||
#endif /* __ASM_ARCH_IO_H */
|
||||
|
|
|
@ -24,6 +24,5 @@
|
|||
|
||||
#define __io(a) ((void __iomem *)(a))
|
||||
#define __mem_pci(a) (a)
|
||||
#define __mem_isa(a) (a)
|
||||
|
||||
#endif
|
||||
|
|
|
@ -44,7 +44,6 @@
|
|||
*/
|
||||
#define __io(a) ((void __iomem *)(PCIO_BASE + (a)))
|
||||
#define __mem_pci(a) (a)
|
||||
#define __mem_isa(a) (a)
|
||||
|
||||
/*
|
||||
* ----------------------------------------------------------------------------
|
||||
|
|
|
@ -16,6 +16,5 @@
|
|||
*/
|
||||
#define __io(a) ((void __iomem *)(a))
|
||||
#define __mem_pci(a) (a)
|
||||
#define __mem_isa(a) (a)
|
||||
|
||||
#endif
|
||||
|
|
|
@ -29,6 +29,5 @@ static inline void __iomem *__io(unsigned long addr)
|
|||
|
||||
#define __io(a) __io(a)
|
||||
#define __mem_pci(a) (a)
|
||||
#define __mem_isa(a) (a)
|
||||
|
||||
#endif
|
||||
|
|
|
@ -33,7 +33,7 @@
|
|||
.endm
|
||||
|
||||
.macro senduart,rd,rx
|
||||
str \rd, [\rx, # S3C2410_UTXH ]
|
||||
strb \rd, [\rx, # S3C2410_UTXH ]
|
||||
.endm
|
||||
|
||||
.macro busyuart, rd, rx
|
||||
|
@ -42,6 +42,12 @@
|
|||
beq 1001f @
|
||||
@ FIFO enabled...
|
||||
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
|
||||
tst \rd, #1
|
||||
addeq \rd, \rx, #(S3C24XX_PA_GPIO - S3C24XX_PA_UART)
|
||||
|
@ -50,7 +56,7 @@
|
|||
ldr \rd, [ \rd, # S3C2410_GSTATUS1 - S3C2410_GPIOREG(0) ]
|
||||
and \rd, \rd, #0x00ff0000
|
||||
teq \rd, #0x00440000 @ is it 2440?
|
||||
|
||||
1004:
|
||||
ldr \rd, [ \rx, # S3C2410_UFSTAT ]
|
||||
moveq \rd, \rd, lsr #SHIFT_2440TXF
|
||||
tst \rd, #S3C2410_UFSTAT_TXFULL
|
||||
|
|
|
@ -18,8 +18,6 @@
|
|||
|
||||
#define INTPND (0x10)
|
||||
#define INTOFFSET (0x14)
|
||||
#define EXTINTPEND (0xa8)
|
||||
#define EXTINTMASK (0xa4)
|
||||
|
||||
#include <asm/hardware.h>
|
||||
#include <asm/arch/irqs.h>
|
||||
|
@ -28,37 +26,23 @@
|
|||
|
||||
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
|
||||
|
||||
ldr \irqstat, [ \base, #INTPND ]
|
||||
teq \irqstat, #0
|
||||
beq 1002f
|
||||
ldr \irqnr, [ \base, #INTOFFSET ]
|
||||
mov \tmp, #1
|
||||
tst \irqstat, \tmp, lsl \irqnr
|
||||
addne \irqnr, \irqnr, #IRQ_EINT0
|
||||
bne 1001f
|
||||
|
||||
@@ the number specified is not a valid irq, so try
|
||||
@@ 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
|
||||
3000:
|
||||
|
||||
movs \tmp, \irqstat, lsl#16
|
||||
addeq \irqnr, \irqnr, #16
|
||||
moveq \irqstat, \irqstat, lsr#16
|
||||
|
@ -75,9 +59,9 @@
|
|||
addeq \irqnr, \irqnr, #1
|
||||
|
||||
@@ we have the value
|
||||
movs \irqnr, \irqnr
|
||||
|
||||
1001:
|
||||
adds \irqnr, \irqnr, #IRQ_EINT0
|
||||
1002:
|
||||
@@ exit here, Z flag unset if IRQ
|
||||
|
||||
.endm
|
||||
|
|
|
@ -236,4 +236,20 @@
|
|||
#define S3C24XX_PA_SPI S3C2410_PA_SPI
|
||||
#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 */
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* 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/
|
||||
*
|
||||
* 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 */
|
||||
|
||||
#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 */
|
||||
|
|
|
@ -23,6 +23,9 @@
|
|||
#define S3C2440_DSC0 S3C2410_GPIOREG(0xc4)
|
||||
#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_DSC1 (1<<31)
|
||||
|
||||
|
|
|
@ -45,7 +45,7 @@
|
|||
#define S3C24XX_MISCCR S3C2400_MISCCR
|
||||
#else
|
||||
#define S3C24XX_GPIO_BASE(x) S3C2410_GPIO_BASE(x)
|
||||
#define S3C24XX_MISCCR S3C2410_MISCCR
|
||||
#define S3C24XX_MISCCR S3C24XX_GPIOREG2(0x80)
|
||||
#endif /* CONFIG_CPU_S3C2400 */
|
||||
|
||||
|
||||
|
@ -73,9 +73,15 @@
|
|||
#define S3C2410_GPIO_SFN2 (0xFFFFFFF2) /* 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 S3C24XX_GPIOREG2(x) ((x) + S3C24XX_VA_GPIO2)
|
||||
|
||||
|
||||
/* configure GPIO ports A..G */
|
||||
|
||||
/* port A - S3C2410: 22bits, 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_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 */
|
||||
#define S3C2400_MISCCR S3C2410_GPIOREG(0x54)
|
||||
#define S3C2410_MISCCR S3C2410_GPIOREG(0x80)
|
||||
#define S3C2410_DCLKCON S3C2410_GPIOREG(0x84)
|
||||
|
||||
#define S3C24XX_DCLKCON S3C24XX_GPIOREG2(0x84)
|
||||
|
||||
/* see clock.h for dclk definitions */
|
||||
|
||||
/* pullup control on databus */
|
||||
|
@ -985,6 +998,8 @@
|
|||
#define S3C2410_MISCCR_CLK0_DCLK0 (5<<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_UPLL (1<<8)
|
||||
#define S3C2410_MISCCR_CLK1_FCLK (2<<8)
|
||||
|
@ -993,6 +1008,8 @@
|
|||
#define S3C2410_MISCCR_CLK1_DCLK1 (5<<8)
|
||||
#define S3C2410_MISCCR_CLK1_MASK (7<<8)
|
||||
|
||||
#define S3C2412_MISCCR_CLK1_CLKsrc (0<<8)
|
||||
|
||||
#define S3C2410_MISCCR_USBSUSPND0 (1<<12)
|
||||
#define S3C2410_MISCCR_USBSUSPND1 (1<<13)
|
||||
|
||||
|
@ -1000,7 +1017,7 @@
|
|||
|
||||
#define S3C2410_MISCCR_nEN_SCLK0 (1<<17)
|
||||
#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)
|
||||
|
||||
/* external interrupt control... */
|
||||
|
@ -1017,6 +1034,10 @@
|
|||
#define S3C2410_EXTINT1 S3C2410_GPIOREG(0x8C)
|
||||
#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 */
|
||||
#define S3C2410_EXTINT_LOWLEV (0x00)
|
||||
#define S3C2410_EXTINT_HILEV (0x01)
|
||||
|
@ -1030,6 +1051,11 @@
|
|||
#define S3C2410_EINFLT2 S3C2410_GPIOREG(0x9C)
|
||||
#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 */
|
||||
#define S3C2410_EINTFLT_PCLK (0x00)
|
||||
#define S3C2410_EINTFLT_EXTCLK (1<<7)
|
||||
|
@ -1039,6 +1065,7 @@
|
|||
|
||||
/* GSTATUS have miscellaneous information in them
|
||||
*
|
||||
* These move between s3c2410 and s3c2412 style systems.
|
||||
*/
|
||||
|
||||
#define S3C2410_GSTATUS0 S3C2410_GPIOREG(0x0AC)
|
||||
|
@ -1047,6 +1074,18 @@
|
|||
#define S3C2410_GSTATUS3 S3C2410_GPIOREG(0x0B8)
|
||||
#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_NCON (1<<2)
|
||||
#define S3C2410_GSTATUS0_RnB (1<<1)
|
||||
|
@ -1054,6 +1093,7 @@
|
|||
|
||||
#define S3C2410_GSTATUS1_IDMASK (0xffff0000)
|
||||
#define S3C2410_GSTATUS1_2410 (0x32410000)
|
||||
#define S3C2410_GSTATUS1_2412 (0x32412001)
|
||||
#define S3C2410_GSTATUS1_2440 (0x32440000)
|
||||
#define S3C2410_GSTATUS1_2442 (0x32440aaa)
|
||||
|
||||
|
@ -1077,5 +1117,22 @@
|
|||
#define S3C2400_OPENCR_OPC_MOSIDIS (0<<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 */
|
||||
|
||||
|
|
|
@ -32,6 +32,11 @@
|
|||
#define S3C2440_GPJDAT S3C2410_GPIOREG(0xd4)
|
||||
#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_INP (0x00 << 0)
|
||||
#define S3C2440_GPJ0_OUTP (0x01 << 0)
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
|
||||
#define S3C2410_IRQREG(x) ((x) + S3C24XX_VA_IRQ)
|
||||
#define S3C2410_EINTREG(x) ((x) + S3C24XX_VA_GPIO)
|
||||
#define S3C24XX_EINTREG(x) ((x) + S3C24XX_VA_GPIO2)
|
||||
|
||||
#define S3C2410_SRCPND S3C2410_IRQREG(0x000)
|
||||
#define S3C2410_INTMOD S3C2410_IRQREG(0x004)
|
||||
|
@ -40,5 +41,10 @@
|
|||
|
||||
#define S3C2410_EINTMASK S3C2410_EINTREG(0x0A4)
|
||||
#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 */
|
||||
|
|
|
@ -82,6 +82,12 @@
|
|||
#define S3C2440_UCON2_DIVMASK (7 << 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_SBREAK (1<<4)
|
||||
|
||||
|
@ -124,6 +130,15 @@
|
|||
#define S3C2410_UMCOM_AFC (1<<4)
|
||||
#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_RXFULL (1<<8)
|
||||
#define S3C2410_UFSTAT_TXMASK (15<<4)
|
||||
|
|
|
@ -22,6 +22,5 @@ static inline void __iomem *__io(unsigned long addr)
|
|||
}
|
||||
#define __io(a) __io(a)
|
||||
#define __mem_pci(a) (a)
|
||||
#define __mem_isa(a) (a)
|
||||
|
||||
#endif
|
||||
|
|
|
@ -28,6 +28,5 @@ static inline void __iomem *__io(unsigned long addr)
|
|||
}
|
||||
#define __io(a) __io(a)
|
||||
#define __mem_pci(a) (a)
|
||||
#define __mem_isa(a) (a)
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,12 +1,89 @@
|
|||
#ifndef _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 {
|
||||
unsigned long uc_flags;
|
||||
struct ucontext *uc_link;
|
||||
stack_t uc_stack;
|
||||
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 */
|
||||
|
|
|
@ -130,6 +130,9 @@
|
|||
/* SUN4V Hypervisor Console */
|
||||
#define PORT_SUNHV 72
|
||||
|
||||
#define PORT_S3C2412 73
|
||||
|
||||
|
||||
#ifdef __KERNEL__
|
||||
|
||||
#include <linux/compiler.h>
|
||||
|
|
Loading…
Reference in New Issue