aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@g5.osdl.org>2006-06-24 20:48:14 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2006-06-24 20:48:14 -0400
commitdfd8317d3340f03bc06eba6b58f0ec0861da4a13 (patch)
tree43bd5c93ad045355687c26beb0983fcf6ca18a6b /arch/arm
parent83626b01275d0228516b4d97da008328fc37c934 (diff)
parentc0897856553d45aee1780bed455b7c2e888dd64b (diff)
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 ...
Diffstat (limited to 'arch/arm')
-rw-r--r--arch/arm/kernel/iwmmxt.S2
-rw-r--r--arch/arm/kernel/signal.c207
-rw-r--r--arch/arm/mach-ep93xx/Makefile2
-rw-r--r--arch/arm/mach-ep93xx/clock.c156
-rw-r--r--arch/arm/mach-ep93xx/core.c28
-rw-r--r--arch/arm/mach-ixp2000/core.c1
-rw-r--r--arch/arm/mach-s3c2410/Kconfig20
-rw-r--r--arch/arm/mach-s3c2410/Makefile6
-rw-r--r--arch/arm/mach-s3c2410/clock.c21
-rw-r--r--arch/arm/mach-s3c2410/clock.h2
-rw-r--r--arch/arm/mach-s3c2410/cpu.c37
-rw-r--r--arch/arm/mach-s3c2410/cpu.h1
-rw-r--r--arch/arm/mach-s3c2410/irq.c57
-rw-r--r--arch/arm/mach-s3c2410/mach-smdk2413.c126
-rw-r--r--arch/arm/mach-s3c2410/pm-simtec.c3
-rw-r--r--arch/arm/mach-s3c2410/s3c2410-clock.c10
-rw-r--r--arch/arm/mach-s3c2410/s3c2410-gpio.c13
-rw-r--r--arch/arm/mach-s3c2410/s3c2412-clock.c711
-rw-r--r--arch/arm/mach-s3c2410/s3c2412.c195
-rw-r--r--arch/arm/mach-s3c2410/s3c2412.h29
-rw-r--r--arch/arm/mm/Kconfig10
21 files changed, 1466 insertions, 171 deletions
diff --git a/arch/arm/kernel/iwmmxt.S b/arch/arm/kernel/iwmmxt.S
index af9e0ae952d5..a3bae95e536c 100644
--- a/arch/arm/kernel/iwmmxt.S
+++ b/arch/arm/kernel/iwmmxt.S
@@ -273,7 +273,7 @@ ENTRY(iwmmxt_task_restore)
273 * 273 *
274 * r0 = previous task_struct pointer (must be preserved) 274 * r0 = previous task_struct pointer (must be preserved)
275 * r1 = previous thread_info pointer 275 * r1 = previous thread_info pointer
276 * r2 = next thread_info.cpu_domain pointer (must be preserved) 276 * r2 = next thread_info pointer (must be preserved)
277 * 277 *
278 * Called only from __switch_to with task preemption disabled. 278 * Called only from __switch_to with task preemption disabled.
279 * No need to care about preserving r4 and above. 279 * No need to care about preserving r4 and above.
diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c
index f094277485c8..1ce05ec086c6 100644
--- a/arch/arm/kernel/signal.c
+++ b/arch/arm/kernel/signal.c
@@ -134,17 +134,6 @@ sys_sigaction(int sig, const struct old_sigaction __user *act,
134 134
135#ifdef CONFIG_IWMMXT 135#ifdef CONFIG_IWMMXT
136 136
137/* iwmmxt_area is 0x98 bytes long, preceeded by 8 bytes of signature */
138#define IWMMXT_STORAGE_SIZE (0x98 + 8)
139#define IWMMXT_MAGIC0 0x12ef842a
140#define IWMMXT_MAGIC1 0x1c07ca71
141
142struct iwmmxt_sigframe {
143 unsigned long magic0;
144 unsigned long magic1;
145 unsigned long storage[0x98/4];
146};
147
148static int preserve_iwmmxt_context(struct iwmmxt_sigframe *frame) 137static int preserve_iwmmxt_context(struct iwmmxt_sigframe *frame)
149{ 138{
150 char kbuf[sizeof(*frame) + 8]; 139 char kbuf[sizeof(*frame) + 8];
@@ -152,8 +141,8 @@ static int preserve_iwmmxt_context(struct iwmmxt_sigframe *frame)
152 141
153 /* the iWMMXt context must be 64 bit aligned */ 142 /* the iWMMXt context must be 64 bit aligned */
154 kframe = (struct iwmmxt_sigframe *)((unsigned long)(kbuf + 8) & ~7); 143 kframe = (struct iwmmxt_sigframe *)((unsigned long)(kbuf + 8) & ~7);
155 kframe->magic0 = IWMMXT_MAGIC0; 144 kframe->magic = IWMMXT_MAGIC;
156 kframe->magic1 = IWMMXT_MAGIC1; 145 kframe->size = IWMMXT_STORAGE_SIZE;
157 iwmmxt_task_copy(current_thread_info(), &kframe->storage); 146 iwmmxt_task_copy(current_thread_info(), &kframe->storage);
158 return __copy_to_user(frame, kframe, sizeof(*frame)); 147 return __copy_to_user(frame, kframe, sizeof(*frame));
159} 148}
@@ -167,8 +156,8 @@ static int restore_iwmmxt_context(struct iwmmxt_sigframe *frame)
167 kframe = (struct iwmmxt_sigframe *)((unsigned long)(kbuf + 8) & ~7); 156 kframe = (struct iwmmxt_sigframe *)((unsigned long)(kbuf + 8) & ~7);
168 if (__copy_from_user(kframe, frame, sizeof(*frame))) 157 if (__copy_from_user(kframe, frame, sizeof(*frame)))
169 return -1; 158 return -1;
170 if (kframe->magic0 != IWMMXT_MAGIC0 || 159 if (kframe->magic != IWMMXT_MAGIC ||
171 kframe->magic1 != IWMMXT_MAGIC1) 160 kframe->size != IWMMXT_STORAGE_SIZE)
172 return -1; 161 return -1;
173 iwmmxt_task_restore(current_thread_info(), &kframe->storage); 162 iwmmxt_task_restore(current_thread_info(), &kframe->storage);
174 return 0; 163 return 0;
@@ -177,70 +166,61 @@ static int restore_iwmmxt_context(struct iwmmxt_sigframe *frame)
177#endif 166#endif
178 167
179/* 168/*
180 * Auxiliary signal frame. This saves stuff like FP state.
181 * The layout of this structure is not part of the user ABI.
182 */
183struct aux_sigframe {
184#ifdef CONFIG_IWMMXT
185 struct iwmmxt_sigframe iwmmxt;
186#endif
187#ifdef CONFIG_VFP
188 union vfp_state vfp;
189#endif
190};
191
192/*
193 * Do a signal return; undo the signal stack. These are aligned to 64-bit. 169 * Do a signal return; undo the signal stack. These are aligned to 64-bit.
194 */ 170 */
195struct sigframe { 171struct sigframe {
196 struct sigcontext sc; 172 struct ucontext uc;
197 unsigned long extramask[_NSIG_WORDS-1];
198 unsigned long retcode[2]; 173 unsigned long retcode[2];
199 struct aux_sigframe aux __attribute__((aligned(8)));
200}; 174};
201 175
202struct rt_sigframe { 176struct rt_sigframe {
203 struct siginfo __user *pinfo;
204 void __user *puc;
205 struct siginfo info; 177 struct siginfo info;
206 struct ucontext uc; 178 struct sigframe sig;
207 unsigned long retcode[2];
208 struct aux_sigframe aux __attribute__((aligned(8)));
209}; 179};
210 180
211static int 181static int restore_sigframe(struct pt_regs *regs, struct sigframe __user *sf)
212restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc,
213 struct aux_sigframe __user *aux)
214{ 182{
215 int err = 0; 183 struct aux_sigframe __user *aux;
184 sigset_t set;
185 int err;
186
187 err = __copy_from_user(&set, &sf->uc.uc_sigmask, sizeof(set));
188 if (err == 0) {
189 sigdelsetmask(&set, ~_BLOCKABLE);
190 spin_lock_irq(&current->sighand->siglock);
191 current->blocked = set;
192 recalc_sigpending();
193 spin_unlock_irq(&current->sighand->siglock);
194 }
216 195
217 __get_user_error(regs->ARM_r0, &sc->arm_r0, err); 196 __get_user_error(regs->ARM_r0, &sf->uc.uc_mcontext.arm_r0, err);
218 __get_user_error(regs->ARM_r1, &sc->arm_r1, err); 197 __get_user_error(regs->ARM_r1, &sf->uc.uc_mcontext.arm_r1, err);
219 __get_user_error(regs->ARM_r2, &sc->arm_r2, err); 198 __get_user_error(regs->ARM_r2, &sf->uc.uc_mcontext.arm_r2, err);
220 __get_user_error(regs->ARM_r3, &sc->arm_r3, err); 199 __get_user_error(regs->ARM_r3, &sf->uc.uc_mcontext.arm_r3, err);
221 __get_user_error(regs->ARM_r4, &sc->arm_r4, err); 200 __get_user_error(regs->ARM_r4, &sf->uc.uc_mcontext.arm_r4, err);
222 __get_user_error(regs->ARM_r5, &sc->arm_r5, err); 201 __get_user_error(regs->ARM_r5, &sf->uc.uc_mcontext.arm_r5, err);
223 __get_user_error(regs->ARM_r6, &sc->arm_r6, err); 202 __get_user_error(regs->ARM_r6, &sf->uc.uc_mcontext.arm_r6, err);
224 __get_user_error(regs->ARM_r7, &sc->arm_r7, err); 203 __get_user_error(regs->ARM_r7, &sf->uc.uc_mcontext.arm_r7, err);
225 __get_user_error(regs->ARM_r8, &sc->arm_r8, err); 204 __get_user_error(regs->ARM_r8, &sf->uc.uc_mcontext.arm_r8, err);
226 __get_user_error(regs->ARM_r9, &sc->arm_r9, err); 205 __get_user_error(regs->ARM_r9, &sf->uc.uc_mcontext.arm_r9, err);
227 __get_user_error(regs->ARM_r10, &sc->arm_r10, err); 206 __get_user_error(regs->ARM_r10, &sf->uc.uc_mcontext.arm_r10, err);
228 __get_user_error(regs->ARM_fp, &sc->arm_fp, err); 207 __get_user_error(regs->ARM_fp, &sf->uc.uc_mcontext.arm_fp, err);
229 __get_user_error(regs->ARM_ip, &sc->arm_ip, err); 208 __get_user_error(regs->ARM_ip, &sf->uc.uc_mcontext.arm_ip, err);
230 __get_user_error(regs->ARM_sp, &sc->arm_sp, err); 209 __get_user_error(regs->ARM_sp, &sf->uc.uc_mcontext.arm_sp, err);
231 __get_user_error(regs->ARM_lr, &sc->arm_lr, err); 210 __get_user_error(regs->ARM_lr, &sf->uc.uc_mcontext.arm_lr, err);
232 __get_user_error(regs->ARM_pc, &sc->arm_pc, err); 211 __get_user_error(regs->ARM_pc, &sf->uc.uc_mcontext.arm_pc, err);
233 __get_user_error(regs->ARM_cpsr, &sc->arm_cpsr, err); 212 __get_user_error(regs->ARM_cpsr, &sf->uc.uc_mcontext.arm_cpsr, err);
234 213
235 err |= !valid_user_regs(regs); 214 err |= !valid_user_regs(regs);
236 215
216 aux = (struct aux_sigframe __user *) sf->uc.uc_regspace;
237#ifdef CONFIG_IWMMXT 217#ifdef CONFIG_IWMMXT
238 if (err == 0 && test_thread_flag(TIF_USING_IWMMXT)) 218 if (err == 0 && test_thread_flag(TIF_USING_IWMMXT))
239 err |= restore_iwmmxt_context(&aux->iwmmxt); 219 err |= restore_iwmmxt_context(&aux->iwmmxt);
240#endif 220#endif
241#ifdef CONFIG_VFP 221#ifdef CONFIG_VFP
242// if (err == 0) 222// if (err == 0)
243// err |= vfp_restore_state(&aux->vfp); 223// err |= vfp_restore_state(&sf->aux.vfp);
244#endif 224#endif
245 225
246 return err; 226 return err;
@@ -249,7 +229,6 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc,
249asmlinkage int sys_sigreturn(struct pt_regs *regs) 229asmlinkage int sys_sigreturn(struct pt_regs *regs)
250{ 230{
251 struct sigframe __user *frame; 231 struct sigframe __user *frame;
252 sigset_t set;
253 232
254 /* Always make any pending restarted system calls return -EINTR */ 233 /* Always make any pending restarted system calls return -EINTR */
255 current_thread_info()->restart_block.fn = do_no_restart_syscall; 234 current_thread_info()->restart_block.fn = do_no_restart_syscall;
@@ -266,19 +245,8 @@ asmlinkage int sys_sigreturn(struct pt_regs *regs)
266 245
267 if (!access_ok(VERIFY_READ, frame, sizeof (*frame))) 246 if (!access_ok(VERIFY_READ, frame, sizeof (*frame)))
268 goto badframe; 247 goto badframe;
269 if (__get_user(set.sig[0], &frame->sc.oldmask)
270 || (_NSIG_WORDS > 1
271 && __copy_from_user(&set.sig[1], &frame->extramask,
272 sizeof(frame->extramask))))
273 goto badframe;
274
275 sigdelsetmask(&set, ~_BLOCKABLE);
276 spin_lock_irq(&current->sighand->siglock);
277 current->blocked = set;
278 recalc_sigpending();
279 spin_unlock_irq(&current->sighand->siglock);
280 248
281 if (restore_sigcontext(regs, &frame->sc, &frame->aux)) 249 if (restore_sigframe(regs, frame))
282 goto badframe; 250 goto badframe;
283 251
284 /* Send SIGTRAP if we're single-stepping */ 252 /* Send SIGTRAP if we're single-stepping */
@@ -297,7 +265,6 @@ badframe:
297asmlinkage int sys_rt_sigreturn(struct pt_regs *regs) 265asmlinkage int sys_rt_sigreturn(struct pt_regs *regs)
298{ 266{
299 struct rt_sigframe __user *frame; 267 struct rt_sigframe __user *frame;
300 sigset_t set;
301 268
302 /* Always make any pending restarted system calls return -EINTR */ 269 /* Always make any pending restarted system calls return -EINTR */
303 current_thread_info()->restart_block.fn = do_no_restart_syscall; 270 current_thread_info()->restart_block.fn = do_no_restart_syscall;
@@ -314,19 +281,11 @@ asmlinkage int sys_rt_sigreturn(struct pt_regs *regs)
314 281
315 if (!access_ok(VERIFY_READ, frame, sizeof (*frame))) 282 if (!access_ok(VERIFY_READ, frame, sizeof (*frame)))
316 goto badframe; 283 goto badframe;
317 if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
318 goto badframe;
319 284
320 sigdelsetmask(&set, ~_BLOCKABLE); 285 if (restore_sigframe(regs, &frame->sig))
321 spin_lock_irq(&current->sighand->siglock);
322 current->blocked = set;
323 recalc_sigpending();
324 spin_unlock_irq(&current->sighand->siglock);
325
326 if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &frame->aux))
327 goto badframe; 286 goto badframe;
328 287
329 if (do_sigaltstack(&frame->uc.uc_stack, NULL, regs->ARM_sp) == -EFAULT) 288 if (do_sigaltstack(&frame->sig.uc.uc_stack, NULL, regs->ARM_sp) == -EFAULT)
330 goto badframe; 289 goto badframe;
331 290
332 /* Send SIGTRAP if we're single-stepping */ 291 /* Send SIGTRAP if we're single-stepping */
@@ -343,42 +302,46 @@ badframe:
343} 302}
344 303
345static int 304static int
346setup_sigcontext(struct sigcontext __user *sc, struct aux_sigframe __user *aux, 305setup_sigframe(struct sigframe __user *sf, struct pt_regs *regs, sigset_t *set)
347 struct pt_regs *regs, unsigned long mask)
348{ 306{
307 struct aux_sigframe __user *aux;
349 int err = 0; 308 int err = 0;
350 309
351 __put_user_error(regs->ARM_r0, &sc->arm_r0, err); 310 __put_user_error(regs->ARM_r0, &sf->uc.uc_mcontext.arm_r0, err);
352 __put_user_error(regs->ARM_r1, &sc->arm_r1, err); 311 __put_user_error(regs->ARM_r1, &sf->uc.uc_mcontext.arm_r1, err);
353 __put_user_error(regs->ARM_r2, &sc->arm_r2, err); 312 __put_user_error(regs->ARM_r2, &sf->uc.uc_mcontext.arm_r2, err);
354 __put_user_error(regs->ARM_r3, &sc->arm_r3, err); 313 __put_user_error(regs->ARM_r3, &sf->uc.uc_mcontext.arm_r3, err);
355 __put_user_error(regs->ARM_r4, &sc->arm_r4, err); 314 __put_user_error(regs->ARM_r4, &sf->uc.uc_mcontext.arm_r4, err);
356 __put_user_error(regs->ARM_r5, &sc->arm_r5, err); 315 __put_user_error(regs->ARM_r5, &sf->uc.uc_mcontext.arm_r5, err);
357 __put_user_error(regs->ARM_r6, &sc->arm_r6, err); 316 __put_user_error(regs->ARM_r6, &sf->uc.uc_mcontext.arm_r6, err);
358 __put_user_error(regs->ARM_r7, &sc->arm_r7, err); 317 __put_user_error(regs->ARM_r7, &sf->uc.uc_mcontext.arm_r7, err);
359 __put_user_error(regs->ARM_r8, &sc->arm_r8, err); 318 __put_user_error(regs->ARM_r8, &sf->uc.uc_mcontext.arm_r8, err);
360 __put_user_error(regs->ARM_r9, &sc->arm_r9, err); 319 __put_user_error(regs->ARM_r9, &sf->uc.uc_mcontext.arm_r9, err);
361 __put_user_error(regs->ARM_r10, &sc->arm_r10, err); 320 __put_user_error(regs->ARM_r10, &sf->uc.uc_mcontext.arm_r10, err);
362 __put_user_error(regs->ARM_fp, &sc->arm_fp, err); 321 __put_user_error(regs->ARM_fp, &sf->uc.uc_mcontext.arm_fp, err);
363 __put_user_error(regs->ARM_ip, &sc->arm_ip, err); 322 __put_user_error(regs->ARM_ip, &sf->uc.uc_mcontext.arm_ip, err);
364 __put_user_error(regs->ARM_sp, &sc->arm_sp, err); 323 __put_user_error(regs->ARM_sp, &sf->uc.uc_mcontext.arm_sp, err);
365 __put_user_error(regs->ARM_lr, &sc->arm_lr, err); 324 __put_user_error(regs->ARM_lr, &sf->uc.uc_mcontext.arm_lr, err);
366 __put_user_error(regs->ARM_pc, &sc->arm_pc, err); 325 __put_user_error(regs->ARM_pc, &sf->uc.uc_mcontext.arm_pc, err);
367 __put_user_error(regs->ARM_cpsr, &sc->arm_cpsr, err); 326 __put_user_error(regs->ARM_cpsr, &sf->uc.uc_mcontext.arm_cpsr, err);
368 327
369 __put_user_error(current->thread.trap_no, &sc->trap_no, err); 328 __put_user_error(current->thread.trap_no, &sf->uc.uc_mcontext.trap_no, err);
370 __put_user_error(current->thread.error_code, &sc->error_code, err); 329 __put_user_error(current->thread.error_code, &sf->uc.uc_mcontext.error_code, err);
371 __put_user_error(current->thread.address, &sc->fault_address, err); 330 __put_user_error(current->thread.address, &sf->uc.uc_mcontext.fault_address, err);
372 __put_user_error(mask, &sc->oldmask, err); 331 __put_user_error(set->sig[0], &sf->uc.uc_mcontext.oldmask, err);
373 332
333 err |= __copy_to_user(&sf->uc.uc_sigmask, set, sizeof(*set));
334
335 aux = (struct aux_sigframe __user *) sf->uc.uc_regspace;
374#ifdef CONFIG_IWMMXT 336#ifdef CONFIG_IWMMXT
375 if (err == 0 && test_thread_flag(TIF_USING_IWMMXT)) 337 if (err == 0 && test_thread_flag(TIF_USING_IWMMXT))
376 err |= preserve_iwmmxt_context(&aux->iwmmxt); 338 err |= preserve_iwmmxt_context(&aux->iwmmxt);
377#endif 339#endif
378#ifdef CONFIG_VFP 340#ifdef CONFIG_VFP
379// if (err == 0) 341// if (err == 0)
380// err |= vfp_save_state(&aux->vfp); 342// err |= vfp_save_state(&sf->aux.vfp);
381#endif 343#endif
344 __put_user_error(0, &aux->end_magic, err);
382 345
383 return err; 346 return err;
384} 347}
@@ -487,13 +450,12 @@ setup_frame(int usig, struct k_sigaction *ka, sigset_t *set, struct pt_regs *reg
487 if (!frame) 450 if (!frame)
488 return 1; 451 return 1;
489 452
490 err |= setup_sigcontext(&frame->sc, &frame->aux, regs, set->sig[0]); 453 /*
491 454 * Set uc.uc_flags to a value which sc.trap_no would never have.
492 if (_NSIG_WORDS > 1) { 455 */
493 err |= __copy_to_user(frame->extramask, &set->sig[1], 456 __put_user_error(0x5ac3c35a, &frame->uc.uc_flags, err);
494 sizeof(frame->extramask));
495 }
496 457
458 err |= setup_sigframe(frame, regs, set);
497 if (err == 0) 459 if (err == 0)
498 err = setup_return(regs, ka, frame->retcode, frame, usig); 460 err = setup_return(regs, ka, frame->retcode, frame, usig);
499 461
@@ -511,25 +473,20 @@ setup_rt_frame(int usig, struct k_sigaction *ka, siginfo_t *info,
511 if (!frame) 473 if (!frame)
512 return 1; 474 return 1;
513 475
514 __put_user_error(&frame->info, &frame->pinfo, err);
515 __put_user_error(&frame->uc, &frame->puc, err);
516 err |= copy_siginfo_to_user(&frame->info, info); 476 err |= copy_siginfo_to_user(&frame->info, info);
517 477
518 __put_user_error(0, &frame->uc.uc_flags, err); 478 __put_user_error(0, &frame->sig.uc.uc_flags, err);
519 __put_user_error(NULL, &frame->uc.uc_link, err); 479 __put_user_error(NULL, &frame->sig.uc.uc_link, err);
520 480
521 memset(&stack, 0, sizeof(stack)); 481 memset(&stack, 0, sizeof(stack));
522 stack.ss_sp = (void __user *)current->sas_ss_sp; 482 stack.ss_sp = (void __user *)current->sas_ss_sp;
523 stack.ss_flags = sas_ss_flags(regs->ARM_sp); 483 stack.ss_flags = sas_ss_flags(regs->ARM_sp);
524 stack.ss_size = current->sas_ss_size; 484 stack.ss_size = current->sas_ss_size;
525 err |= __copy_to_user(&frame->uc.uc_stack, &stack, sizeof(stack)); 485 err |= __copy_to_user(&frame->sig.uc.uc_stack, &stack, sizeof(stack));
526
527 err |= setup_sigcontext(&frame->uc.uc_mcontext, &frame->aux,
528 regs, set->sig[0]);
529 err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
530 486
487 err |= setup_sigframe(&frame->sig, regs, set);
531 if (err == 0) 488 if (err == 0)
532 err = setup_return(regs, ka, frame->retcode, frame, usig); 489 err = setup_return(regs, ka, frame->sig.retcode, frame, usig);
533 490
534 if (err == 0) { 491 if (err == 0) {
535 /* 492 /*
@@ -538,7 +495,7 @@ setup_rt_frame(int usig, struct k_sigaction *ka, siginfo_t *info,
538 * -- Peter Maydell <pmaydell@chiark.greenend.org.uk> 2000-12-06 495 * -- Peter Maydell <pmaydell@chiark.greenend.org.uk> 2000-12-06
539 */ 496 */
540 regs->ARM_r1 = (unsigned long)&frame->info; 497 regs->ARM_r1 = (unsigned long)&frame->info;
541 regs->ARM_r2 = (unsigned long)&frame->uc; 498 regs->ARM_r2 = (unsigned long)&frame->sig.uc;
542 } 499 }
543 500
544 return err; 501 return err;
diff --git a/arch/arm/mach-ep93xx/Makefile b/arch/arm/mach-ep93xx/Makefile
index 5393af989e94..05a48a21038e 100644
--- a/arch/arm/mach-ep93xx/Makefile
+++ b/arch/arm/mach-ep93xx/Makefile
@@ -1,7 +1,7 @@
1# 1#
2# Makefile for the linux kernel. 2# Makefile for the linux kernel.
3# 3#
4obj-y := core.o 4obj-y := core.o clock.o
5obj-m := 5obj-m :=
6obj-n := 6obj-n :=
7obj- := 7obj- :=
diff --git a/arch/arm/mach-ep93xx/clock.c b/arch/arm/mach-ep93xx/clock.c
new file mode 100644
index 000000000000..08ad782c1649
--- /dev/null
+++ b/arch/arm/mach-ep93xx/clock.c
@@ -0,0 +1,156 @@
1/*
2 * arch/arm/mach-ep93xx/clock.c
3 * Clock control for Cirrus EP93xx chips.
4 *
5 * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or (at
10 * your option) any later version.
11 */
12
13#include <linux/kernel.h>
14#include <linux/clk.h>
15#include <linux/err.h>
16#include <linux/string.h>
17#include <asm/div64.h>
18#include <asm/hardware.h>
19#include <asm/io.h>
20
21struct clk {
22 char *name;
23 unsigned long rate;
24 int users;
25 u32 enable_reg;
26 u32 enable_mask;
27};
28
29static struct clk clk_pll1 = {
30 .name = "pll1",
31};
32static struct clk clk_f = {
33 .name = "fclk",
34};
35static struct clk clk_h = {
36 .name = "hclk",
37};
38static struct clk clk_p = {
39 .name = "pclk",
40};
41static struct clk clk_pll2 = {
42 .name = "pll2",
43};
44static struct clk clk_usb_host = {
45 .name = "usb_host",
46 .enable_reg = EP93XX_SYSCON_CLOCK_CONTROL,
47 .enable_mask = EP93XX_SYSCON_CLOCK_USH_EN,
48};
49
50
51static struct clk *clocks[] = {
52 &clk_pll1,
53 &clk_f,
54 &clk_h,
55 &clk_p,
56 &clk_pll2,
57 &clk_usb_host,
58};
59
60struct clk *clk_get(struct device *dev, const char *id)
61{
62 int i;
63
64 for (i = 0; i < ARRAY_SIZE(clocks); i++) {
65 if (!strcmp(clocks[i]->name, id))
66 return clocks[i];
67 }
68
69 return ERR_PTR(-ENOENT);
70}
71
72int clk_enable(struct clk *clk)
73{
74 if (!clk->users++ && clk->enable_reg) {
75 u32 value;
76
77 value = __raw_readl(clk->enable_reg);
78 __raw_writel(value | clk->enable_mask, clk->enable_reg);
79 }
80
81 return 0;
82}
83
84void clk_disable(struct clk *clk)
85{
86 if (!--clk->users && clk->enable_reg) {
87 u32 value;
88
89 value = __raw_readl(clk->enable_reg);
90 __raw_writel(value & ~clk->enable_mask, clk->enable_reg);
91 }
92}
93
94unsigned long clk_get_rate(struct clk *clk)
95{
96 return clk->rate;
97}
98
99void clk_put(struct clk *clk)
100{
101}
102
103
104
105static char fclk_divisors[] = { 1, 2, 4, 8, 16, 1, 1, 1 };
106static char hclk_divisors[] = { 1, 2, 4, 5, 6, 8, 16, 32 };
107static char pclk_divisors[] = { 1, 2, 4, 8 };
108
109/*
110 * PLL rate = 14.7456 MHz * (X1FBD + 1) * (X2FBD + 1) / (X2IPD + 1) / 2^PS
111 */
112static unsigned long calc_pll_rate(u32 config_word)
113{
114 unsigned long long rate;
115 int i;
116
117 rate = 14745600;
118 rate *= ((config_word >> 11) & 0x1f) + 1; /* X1FBD */
119 rate *= ((config_word >> 5) & 0x3f) + 1; /* X2FBD */
120 do_div(rate, (config_word & 0x1f) + 1); /* X2IPD */
121 for (i = 0; i < ((config_word >> 16) & 3); i++) /* PS */
122 rate >>= 1;
123
124 return (unsigned long)rate;
125}
126
127void ep93xx_clock_init(void)
128{
129 u32 value;
130
131 value = __raw_readl(EP93XX_SYSCON_CLOCK_SET1);
132 if (!(value & 0x00800000)) { /* PLL1 bypassed? */
133 clk_pll1.rate = 14745600;
134 } else {
135 clk_pll1.rate = calc_pll_rate(value);
136 }
137 clk_f.rate = clk_pll1.rate / fclk_divisors[(value >> 25) & 0x7];
138 clk_h.rate = clk_pll1.rate / hclk_divisors[(value >> 20) & 0x7];
139 clk_p.rate = clk_h.rate / pclk_divisors[(value >> 18) & 0x3];
140
141 value = __raw_readl(EP93XX_SYSCON_CLOCK_SET2);
142 if (!(value & 0x00080000)) { /* PLL2 bypassed? */
143 clk_pll2.rate = 14745600;
144 } else if (value & 0x00040000) { /* PLL2 enabled? */
145 clk_pll2.rate = calc_pll_rate(value);
146 } else {
147 clk_pll2.rate = 0;
148 }
149 clk_usb_host.rate = clk_pll2.rate / (((value >> 28) & 0xf) + 1);
150
151 printk(KERN_INFO "ep93xx: PLL1 running at %ld MHz, PLL2 at %ld MHz\n",
152 clk_pll1.rate / 1000000, clk_pll2.rate / 1000000);
153 printk(KERN_INFO "ep93xx: FCLK %ld MHz, HCLK %ld MHz, PCLK %ld MHz\n",
154 clk_f.rate / 1000000, clk_h.rate / 1000000,
155 clk_p.rate / 1000000);
156}
diff --git a/arch/arm/mach-ep93xx/core.c b/arch/arm/mach-ep93xx/core.c
index bf6bd71bdd08..1fe73c0a9d01 100644
--- a/arch/arm/mach-ep93xx/core.c
+++ b/arch/arm/mach-ep93xx/core.c
@@ -433,10 +433,37 @@ static struct platform_device ep93xx_rtc_device = {
433}; 433};
434 434
435 435
436static struct resource ep93xx_ohci_resources[] = {
437 [0] = {
438 .start = EP93XX_USB_PHYS_BASE,
439 .end = EP93XX_USB_PHYS_BASE + 0x0fff,
440 .flags = IORESOURCE_MEM,
441 },
442 [1] = {
443 .start = IRQ_EP93XX_USB,
444 .end = IRQ_EP93XX_USB,
445 .flags = IORESOURCE_IRQ,
446 },
447};
448
449static struct platform_device ep93xx_ohci_device = {
450 .name = "ep93xx-ohci",
451 .id = -1,
452 .dev = {
453 .dma_mask = (void *)0xffffffff,
454 .coherent_dma_mask = 0xffffffff,
455 },
456 .num_resources = ARRAY_SIZE(ep93xx_ohci_resources),
457 .resource = ep93xx_ohci_resources,
458};
459
460
436void __init ep93xx_init_devices(void) 461void __init ep93xx_init_devices(void)
437{ 462{
438 unsigned int v; 463 unsigned int v;
439 464
465 ep93xx_clock_init();
466
440 /* 467 /*
441 * Disallow access to MaverickCrunch initially. 468 * Disallow access to MaverickCrunch initially.
442 */ 469 */
@@ -450,4 +477,5 @@ void __init ep93xx_init_devices(void)
450 amba_device_register(&uart3_device, &iomem_resource); 477 amba_device_register(&uart3_device, &iomem_resource);
451 478
452 platform_device_register(&ep93xx_rtc_device); 479 platform_device_register(&ep93xx_rtc_device);
480 platform_device_register(&ep93xx_ohci_device);
453} 481}
diff --git a/arch/arm/mach-ixp2000/core.c b/arch/arm/mach-ixp2000/core.c
index 186f632035b8..ebe4391dd7f9 100644
--- a/arch/arm/mach-ixp2000/core.c
+++ b/arch/arm/mach-ixp2000/core.c
@@ -302,6 +302,7 @@ void gpio_line_config(int line, int direction)
302 } 302 }
303 local_irq_restore(flags); 303 local_irq_restore(flags);
304} 304}
305EXPORT_SYMBOL(gpio_line_config);
305 306
306 307
307/************************************************************************* 308/*************************************************************************
diff --git a/arch/arm/mach-s3c2410/Kconfig b/arch/arm/mach-s3c2410/Kconfig
index 7b786d725636..f5d9cd498a5f 100644
--- a/arch/arm/mach-s3c2410/Kconfig
+++ b/arch/arm/mach-s3c2410/Kconfig
@@ -81,6 +81,12 @@ config SMDK2440_CPU2442
81 depends on ARCH_S3C2440 81 depends on ARCH_S3C2440
82 select CPU_S3C2442 82 select CPU_S3C2442
83 83
84config MACH_SMDK2413
85 bool "SMDK2413"
86 select CPU_S3C2412
87 select MACH_SMDK
88 help
89 Say Y here if you are using an SMDK2413
84 90
85config MACH_VR1000 91config MACH_VR1000
86 bool "Thorcom VR1000" 92 bool "Thorcom VR1000"
@@ -127,6 +133,20 @@ config CPU_S3C2410
127 Support for S3C2410 and S3C2410A family from the S3C24XX line 133 Support for S3C2410 and S3C2410A family from the S3C24XX line
128 of Samsung Mobile CPUs. 134 of Samsung Mobile CPUs.
129 135
136# internal node to signify if we are only dealing with an S3C2412
137
138config CPU_S3C2412_ONLY
139 bool
140 depends on ARCH_S3C2410 && !CPU_S3C2400 && !CPU_S3C2410 && \
141 !CPU_S3C2440 && !CPU_S3C2442 && CPU_S3C2412
142 default y if CPU_S3C2412
143
144config CPU_S3C2412
145 bool
146 depends on ARCH_S3C2410
147 help
148 Support for the S3C2412 and S3C2413 SoCs from the S3C24XX line
149
130config CPU_S3C244X 150config CPU_S3C244X
131 bool 151 bool
132 depends on ARCH_S3C2410 && (CPU_S3C2440 || CPU_S3C2442) 152 depends on ARCH_S3C2410 && (CPU_S3C2440 || CPU_S3C2442)
diff --git a/arch/arm/mach-s3c2410/Makefile b/arch/arm/mach-s3c2410/Makefile
index 372dbcea1434..0c7938645df6 100644
--- a/arch/arm/mach-s3c2410/Makefile
+++ b/arch/arm/mach-s3c2410/Makefile
@@ -24,6 +24,11 @@ obj-$(CONFIG_S3C2410_DMA) += dma.o
24obj-$(CONFIG_PM) += pm.o sleep.o 24obj-$(CONFIG_PM) += pm.o sleep.o
25obj-$(CONFIG_PM_SIMTEC) += pm-simtec.o 25obj-$(CONFIG_PM_SIMTEC) += pm-simtec.o
26 26
27# S3C2412 support
28obj-$(CONFIG_CPU_S3C2412) += s3c2412.o
29obj-$(CONFIG_CPU_S3C2412) += s3c2412-clock.o
30
31#
27# S3C244X support 32# S3C244X support
28 33
29obj-$(CONFIG_CPU_S3C244X) += s3c244x.o 34obj-$(CONFIG_CPU_S3C244X) += s3c244x.o
@@ -57,6 +62,7 @@ obj-$(CONFIG_ARCH_BAST) += mach-bast.o usb-simtec.o
57obj-$(CONFIG_ARCH_H1940) += mach-h1940.o 62obj-$(CONFIG_ARCH_H1940) += mach-h1940.o
58obj-$(CONFIG_MACH_N30) += mach-n30.o 63obj-$(CONFIG_MACH_N30) += mach-n30.o
59obj-$(CONFIG_ARCH_SMDK2410) += mach-smdk2410.o 64obj-$(CONFIG_ARCH_SMDK2410) += mach-smdk2410.o
65obj-$(CONFIG_MACH_SMDK2413) += mach-smdk2413.o
60obj-$(CONFIG_ARCH_S3C2440) += mach-smdk2440.o 66obj-$(CONFIG_ARCH_S3C2440) += mach-smdk2440.o
61obj-$(CONFIG_MACH_VR1000) += mach-vr1000.o usb-simtec.o 67obj-$(CONFIG_MACH_VR1000) += mach-vr1000.o usb-simtec.o
62obj-$(CONFIG_MACH_RX3715) += mach-rx3715.o 68obj-$(CONFIG_MACH_RX3715) += mach-rx3715.o
diff --git a/arch/arm/mach-s3c2410/clock.c b/arch/arm/mach-s3c2410/clock.c
index c5c93c333ac6..e13fb6778890 100644
--- a/arch/arm/mach-s3c2410/clock.c
+++ b/arch/arm/mach-s3c2410/clock.c
@@ -213,7 +213,7 @@ EXPORT_SYMBOL(clk_set_parent);
213 213
214/* base clocks */ 214/* base clocks */
215 215
216static struct clk clk_xtal = { 216struct clk clk_xtal = {
217 .name = "xtal", 217 .name = "xtal",
218 .id = -1, 218 .id = -1,
219 .rate = 0, 219 .rate = 0,
@@ -221,6 +221,11 @@ static struct clk clk_xtal = {
221 .ctrlbit = 0, 221 .ctrlbit = 0,
222}; 222};
223 223
224struct clk clk_mpll = {
225 .name = "mpll",
226 .id = -1,
227};
228
224struct clk clk_upll = { 229struct clk clk_upll = {
225 .name = "upll", 230 .name = "upll",
226 .id = -1, 231 .id = -1,
@@ -232,7 +237,7 @@ struct clk clk_f = {
232 .name = "fclk", 237 .name = "fclk",
233 .id = -1, 238 .id = -1,
234 .rate = 0, 239 .rate = 0,
235 .parent = NULL, 240 .parent = &clk_mpll,
236 .ctrlbit = 0, 241 .ctrlbit = 0,
237}; 242};
238 243
@@ -263,14 +268,14 @@ struct clk clk_usb_bus = {
263 268
264static int s3c24xx_dclk_enable(struct clk *clk, int enable) 269static int s3c24xx_dclk_enable(struct clk *clk, int enable)
265{ 270{
266 unsigned long dclkcon = __raw_readl(S3C2410_DCLKCON); 271 unsigned long dclkcon = __raw_readl(S3C24XX_DCLKCON);
267 272
268 if (enable) 273 if (enable)
269 dclkcon |= clk->ctrlbit; 274 dclkcon |= clk->ctrlbit;
270 else 275 else
271 dclkcon &= ~clk->ctrlbit; 276 dclkcon &= ~clk->ctrlbit;
272 277
273 __raw_writel(dclkcon, S3C2410_DCLKCON); 278 __raw_writel(dclkcon, S3C24XX_DCLKCON);
274 279
275 return 0; 280 return 0;
276} 281}
@@ -289,7 +294,7 @@ static int s3c24xx_dclk_setparent(struct clk *clk, struct clk *parent)
289 294
290 clk->parent = parent; 295 clk->parent = parent;
291 296
292 dclkcon = __raw_readl(S3C2410_DCLKCON); 297 dclkcon = __raw_readl(S3C24XX_DCLKCON);
293 298
294 if (clk->ctrlbit == S3C2410_DCLKCON_DCLK0EN) { 299 if (clk->ctrlbit == S3C2410_DCLKCON_DCLK0EN) {
295 if (uclk) 300 if (uclk)
@@ -303,7 +308,7 @@ static int s3c24xx_dclk_setparent(struct clk *clk, struct clk *parent)
303 dclkcon &= ~S3C2410_DCLKCON_DCLK1_UCLK; 308 dclkcon &= ~S3C2410_DCLKCON_DCLK1_UCLK;
304 } 309 }
305 310
306 __raw_writel(dclkcon, S3C2410_DCLKCON); 311 __raw_writel(dclkcon, S3C24XX_DCLKCON);
307 312
308 return 0; 313 return 0;
309} 314}
@@ -413,6 +418,7 @@ int __init s3c24xx_setup_clocks(unsigned long xtal,
413 clk_xtal.rate = xtal; 418 clk_xtal.rate = xtal;
414 clk_upll.rate = s3c2410_get_pll(__raw_readl(S3C2410_UPLLCON), xtal); 419 clk_upll.rate = s3c2410_get_pll(__raw_readl(S3C2410_UPLLCON), xtal);
415 420
421 clk_mpll.rate = fclk;
416 clk_h.rate = hclk; 422 clk_h.rate = hclk;
417 clk_p.rate = pclk; 423 clk_p.rate = pclk;
418 clk_f.rate = fclk; 424 clk_f.rate = fclk;
@@ -424,6 +430,9 @@ int __init s3c24xx_setup_clocks(unsigned long xtal,
424 if (s3c24xx_register_clock(&clk_xtal) < 0) 430 if (s3c24xx_register_clock(&clk_xtal) < 0)
425 printk(KERN_ERR "failed to register master xtal\n"); 431 printk(KERN_ERR "failed to register master xtal\n");
426 432
433 if (s3c24xx_register_clock(&clk_mpll) < 0)
434 printk(KERN_ERR "failed to register mpll clock\n");
435
427 if (s3c24xx_register_clock(&clk_upll) < 0) 436 if (s3c24xx_register_clock(&clk_upll) < 0)
428 printk(KERN_ERR "failed to register upll clock\n"); 437 printk(KERN_ERR "failed to register upll clock\n");
429 438
diff --git a/arch/arm/mach-s3c2410/clock.h b/arch/arm/mach-s3c2410/clock.h
index 9456c81eb5d3..7f0ea03e1d49 100644
--- a/arch/arm/mach-s3c2410/clock.h
+++ b/arch/arm/mach-s3c2410/clock.h
@@ -42,7 +42,9 @@ extern struct clk clk_usb_bus;
42extern struct clk clk_f; 42extern struct clk clk_f;
43extern struct clk clk_h; 43extern struct clk clk_h;
44extern struct clk clk_p; 44extern struct clk clk_p;
45extern struct clk clk_mpll;
45extern struct clk clk_upll; 46extern struct clk clk_upll;
47extern struct clk clk_xtal;
46 48
47/* exports for arch/arm/mach-s3c2410 49/* exports for arch/arm/mach-s3c2410
48 * 50 *
diff --git a/arch/arm/mach-s3c2410/cpu.c b/arch/arm/mach-s3c2410/cpu.c
index 52842e6e86e6..1c3c6adae6c4 100644
--- a/arch/arm/mach-s3c2410/cpu.c
+++ b/arch/arm/mach-s3c2410/cpu.c
@@ -44,6 +44,7 @@
44#include "clock.h" 44#include "clock.h"
45#include "s3c2400.h" 45#include "s3c2400.h"
46#include "s3c2410.h" 46#include "s3c2410.h"
47#include "s3c2412.h"
47#include "s3c244x.h" 48#include "s3c244x.h"
48#include "s3c2440.h" 49#include "s3c2440.h"
49#include "s3c2442.h" 50#include "s3c2442.h"
@@ -62,6 +63,7 @@ struct cpu_table {
62 63
63static const char name_s3c2400[] = "S3C2400"; 64static const char name_s3c2400[] = "S3C2400";
64static const char name_s3c2410[] = "S3C2410"; 65static const char name_s3c2410[] = "S3C2410";
66static const char name_s3c2412[] = "S3C2412";
65static const char name_s3c2440[] = "S3C2440"; 67static const char name_s3c2440[] = "S3C2440";
66static const char name_s3c2442[] = "S3C2442"; 68static const char name_s3c2442[] = "S3C2442";
67static const char name_s3c2410a[] = "S3C2410A"; 69static const char name_s3c2410a[] = "S3C2410A";
@@ -114,6 +116,15 @@ static struct cpu_table cpu_ids[] __initdata = {
114 .name = name_s3c2442 116 .name = name_s3c2442
115 }, 117 },
116 { 118 {
119 .idcode = 0x32412001,
120 .idmask = 0xffffffff,
121 .map_io = s3c2412_map_io,
122 .init_clocks = s3c2412_init_clocks,
123 .init_uarts = s3c2412_init_uarts,
124 .init = s3c2412_init,
125 .name = name_s3c2412,
126 },
127 {
117 .idcode = 0x0, /* S3C2400 doesn't have an idcode */ 128 .idcode = 0x0, /* S3C2400 doesn't have an idcode */
118 .idmask = 0xffffffff, 129 .idmask = 0xffffffff,
119 .map_io = s3c2400_map_io, 130 .map_io = s3c2400_map_io,
@@ -171,6 +182,24 @@ void s3c24xx_set_board(struct s3c24xx_board *b)
171 182
172static struct cpu_table *cpu; 183static struct cpu_table *cpu;
173 184
185static unsigned long s3c24xx_read_idcode_v5(void)
186{
187#if defined(CONFIG_CPU_S3C2412) || defined(CONFIG_CPU_S3C2413)
188 return __raw_readl(S3C2412_GSTATUS1);
189#else
190 return 1UL; /* don't look like an 2400 */
191#endif
192}
193
194static unsigned long s3c24xx_read_idcode_v4(void)
195{
196#ifndef CONFIG_CPU_S3C2400
197 return __raw_readl(S3C2410_GSTATUS1);
198#else
199 return 0UL;
200#endif
201}
202
174void __init s3c24xx_init_io(struct map_desc *mach_desc, int size) 203void __init s3c24xx_init_io(struct map_desc *mach_desc, int size)
175{ 204{
176 unsigned long idcode = 0x0; 205 unsigned long idcode = 0x0;
@@ -178,9 +207,11 @@ void __init s3c24xx_init_io(struct map_desc *mach_desc, int size)
178 /* initialise the io descriptors we need for initialisation */ 207 /* initialise the io descriptors we need for initialisation */
179 iotable_init(s3c_iodesc, ARRAY_SIZE(s3c_iodesc)); 208 iotable_init(s3c_iodesc, ARRAY_SIZE(s3c_iodesc));
180 209
181#ifndef CONFIG_CPU_S3C2400 210 if (cpu_architecture() >= CPU_ARCH_ARMv5) {
182 idcode = __raw_readl(S3C2410_GSTATUS1); 211 idcode = s3c24xx_read_idcode_v5();
183#endif 212 } else {
213 idcode = s3c24xx_read_idcode_v4();
214 }
184 215
185 cpu = s3c_lookup_cpu(idcode); 216 cpu = s3c_lookup_cpu(idcode);
186 217
diff --git a/arch/arm/mach-s3c2410/cpu.h b/arch/arm/mach-s3c2410/cpu.h
index 21c62dc29bb2..b0ed9d2d141b 100644
--- a/arch/arm/mach-s3c2410/cpu.h
+++ b/arch/arm/mach-s3c2410/cpu.h
@@ -74,5 +74,6 @@ extern struct sys_timer s3c24xx_timer;
74/* system device classes */ 74/* system device classes */
75 75
76extern struct sysdev_class s3c2410_sysclass; 76extern struct sysdev_class s3c2410_sysclass;
77extern struct sysdev_class s3c2412_sysclass;
77extern struct sysdev_class s3c2440_sysclass; 78extern struct sysdev_class s3c2440_sysclass;
78extern struct sysdev_class s3c2442_sysclass; 79extern struct sysdev_class s3c2442_sysclass;
diff --git a/arch/arm/mach-s3c2410/irq.c b/arch/arm/mach-s3c2410/irq.c
index 66d8c068e940..6822dc7f7799 100644
--- a/arch/arm/mach-s3c2410/irq.c
+++ b/arch/arm/mach-s3c2410/irq.c
@@ -191,13 +191,9 @@ static struct irqchip s3c_irq_chip = {
191 .ack = s3c_irq_ack, 191 .ack = s3c_irq_ack,
192 .mask = s3c_irq_mask, 192 .mask = s3c_irq_mask,
193 .unmask = s3c_irq_unmask, 193 .unmask = s3c_irq_unmask,
194 .set_wake = s3c_irq_wake 194 .set_wake = s3c_irq_wake
195}; 195};
196 196
197/* S3C2410_EINTMASK
198 * S3C2410_EINTPEND
199 */
200
201static void 197static void
202s3c_irqext_mask(unsigned int irqno) 198s3c_irqext_mask(unsigned int irqno)
203{ 199{
@@ -205,9 +201,9 @@ s3c_irqext_mask(unsigned int irqno)
205 201
206 irqno -= EXTINT_OFF; 202 irqno -= EXTINT_OFF;
207 203
208 mask = __raw_readl(S3C2410_EINTMASK); 204 mask = __raw_readl(S3C24XX_EINTMASK);
209 mask |= ( 1UL << irqno); 205 mask |= ( 1UL << irqno);
210 __raw_writel(mask, S3C2410_EINTMASK); 206 __raw_writel(mask, S3C24XX_EINTMASK);
211 207
212 if (irqno <= (IRQ_EINT7 - EXTINT_OFF)) { 208 if (irqno <= (IRQ_EINT7 - EXTINT_OFF)) {
213 /* check to see if all need masking */ 209 /* check to see if all need masking */
@@ -232,11 +228,11 @@ s3c_irqext_ack(unsigned int irqno)
232 bit = 1UL << (irqno - EXTINT_OFF); 228 bit = 1UL << (irqno - EXTINT_OFF);
233 229
234 230
235 mask = __raw_readl(S3C2410_EINTMASK); 231 mask = __raw_readl(S3C24XX_EINTMASK);
236 232
237 __raw_writel(bit, S3C2410_EINTPEND); 233 __raw_writel(bit, S3C24XX_EINTPEND);
238 234
239 req = __raw_readl(S3C2410_EINTPEND); 235 req = __raw_readl(S3C24XX_EINTPEND);
240 req &= ~mask; 236 req &= ~mask;
241 237
242 /* not sure if we should be acking the parent irq... */ 238 /* not sure if we should be acking the parent irq... */
@@ -257,9 +253,9 @@ s3c_irqext_unmask(unsigned int irqno)
257 253
258 irqno -= EXTINT_OFF; 254 irqno -= EXTINT_OFF;
259 255
260 mask = __raw_readl(S3C2410_EINTMASK); 256 mask = __raw_readl(S3C24XX_EINTMASK);
261 mask &= ~( 1UL << irqno); 257 mask &= ~( 1UL << irqno);
262 __raw_writel(mask, S3C2410_EINTMASK); 258 __raw_writel(mask, S3C24XX_EINTMASK);
263 259
264 s3c_irq_unmask((irqno <= (IRQ_EINT7 - EXTINT_OFF)) ? IRQ_EINT4t7 : IRQ_EINT8t23); 260 s3c_irq_unmask((irqno <= (IRQ_EINT7 - EXTINT_OFF)) ? IRQ_EINT4t7 : IRQ_EINT8t23);
265} 261}
@@ -275,28 +271,28 @@ s3c_irqext_type(unsigned int irq, unsigned int type)
275 if ((irq >= IRQ_EINT0) && (irq <= IRQ_EINT3)) 271 if ((irq >= IRQ_EINT0) && (irq <= IRQ_EINT3))
276 { 272 {
277 gpcon_reg = S3C2410_GPFCON; 273 gpcon_reg = S3C2410_GPFCON;
278 extint_reg = S3C2410_EXTINT0; 274 extint_reg = S3C24XX_EXTINT0;
279 gpcon_offset = (irq - IRQ_EINT0) * 2; 275 gpcon_offset = (irq - IRQ_EINT0) * 2;
280 extint_offset = (irq - IRQ_EINT0) * 4; 276 extint_offset = (irq - IRQ_EINT0) * 4;
281 } 277 }
282 else if ((irq >= IRQ_EINT4) && (irq <= IRQ_EINT7)) 278 else if ((irq >= IRQ_EINT4) && (irq <= IRQ_EINT7))
283 { 279 {
284 gpcon_reg = S3C2410_GPFCON; 280 gpcon_reg = S3C2410_GPFCON;
285 extint_reg = S3C2410_EXTINT0; 281 extint_reg = S3C24XX_EXTINT0;
286 gpcon_offset = (irq - (EXTINT_OFF)) * 2; 282 gpcon_offset = (irq - (EXTINT_OFF)) * 2;
287 extint_offset = (irq - (EXTINT_OFF)) * 4; 283 extint_offset = (irq - (EXTINT_OFF)) * 4;
288 } 284 }
289 else if ((irq >= IRQ_EINT8) && (irq <= IRQ_EINT15)) 285 else if ((irq >= IRQ_EINT8) && (irq <= IRQ_EINT15))
290 { 286 {
291 gpcon_reg = S3C2410_GPGCON; 287 gpcon_reg = S3C2410_GPGCON;
292 extint_reg = S3C2410_EXTINT1; 288 extint_reg = S3C24XX_EXTINT1;
293 gpcon_offset = (irq - IRQ_EINT8) * 2; 289 gpcon_offset = (irq - IRQ_EINT8) * 2;
294 extint_offset = (irq - IRQ_EINT8) * 4; 290 extint_offset = (irq - IRQ_EINT8) * 4;
295 } 291 }
296 else if ((irq >= IRQ_EINT16) && (irq <= IRQ_EINT23)) 292 else if ((irq >= IRQ_EINT16) && (irq <= IRQ_EINT23))
297 { 293 {
298 gpcon_reg = S3C2410_GPGCON; 294 gpcon_reg = S3C2410_GPGCON;
299 extint_reg = S3C2410_EXTINT2; 295 extint_reg = S3C24XX_EXTINT2;
300 gpcon_offset = (irq - IRQ_EINT8) * 2; 296 gpcon_offset = (irq - IRQ_EINT8) * 2;
301 extint_offset = (irq - IRQ_EINT16) * 4; 297 extint_offset = (irq - IRQ_EINT16) * 4;
302 } else 298 } else
@@ -572,6 +568,23 @@ s3c_irq_demux_uart2(unsigned int irq,
572 s3c_irq_demux_uart(IRQ_S3CUART_RX2, regs); 568 s3c_irq_demux_uart(IRQ_S3CUART_RX2, regs);
573} 569}
574 570
571static void
572s3c_irq_demux_extint(unsigned int irq,
573 struct irqdesc *desc,
574 struct pt_regs *regs)
575{
576 unsigned long eintpnd = __raw_readl(S3C24XX_EINTPEND);
577 unsigned long eintmsk = __raw_readl(S3C24XX_EINTMASK);
578
579 eintpnd &= ~eintmsk;
580
581 if (eintpnd) {
582 irq = fls(eintpnd);
583 irq += (IRQ_EINT4 - (4 + 1));
584
585 desc_handle_irq(irq, irq_desc + irq, regs);
586 }
587}
575 588
576/* s3c24xx_init_irq 589/* s3c24xx_init_irq
577 * 590 *
@@ -591,12 +604,12 @@ void __init s3c24xx_init_irq(void)
591 604
592 last = 0; 605 last = 0;
593 for (i = 0; i < 4; i++) { 606 for (i = 0; i < 4; i++) {
594 pend = __raw_readl(S3C2410_EINTPEND); 607 pend = __raw_readl(S3C24XX_EINTPEND);
595 608
596 if (pend == 0 || pend == last) 609 if (pend == 0 || pend == last)
597 break; 610 break;
598 611
599 __raw_writel(pend, S3C2410_EINTPEND); 612 __raw_writel(pend, S3C24XX_EINTPEND);
600 printk("irq: clearing pending ext status %08x\n", (int)pend); 613 printk("irq: clearing pending ext status %08x\n", (int)pend);
601 last = pend; 614 last = pend;
602 } 615 }
@@ -630,12 +643,14 @@ void __init s3c24xx_init_irq(void)
630 643
631 irqdbf("s3c2410_init_irq: registering s3c2410 interrupt handlers\n"); 644 irqdbf("s3c2410_init_irq: registering s3c2410 interrupt handlers\n");
632 645
633 for (irqno = IRQ_BATT_FLT; irqno <= IRQ_ADCPARENT; irqno++) { 646 for (irqno = IRQ_EINT4t7; irqno <= IRQ_ADCPARENT; irqno++) {
634 /* set all the s3c2410 internal irqs */ 647 /* set all the s3c2410 internal irqs */
635 648
636 switch (irqno) { 649 switch (irqno) {
637 /* deal with the special IRQs (cascaded) */ 650 /* deal with the special IRQs (cascaded) */
638 651
652 case IRQ_EINT4t7:
653 case IRQ_EINT8t23:
639 case IRQ_UART0: 654 case IRQ_UART0:
640 case IRQ_UART1: 655 case IRQ_UART1:
641 case IRQ_UART2: 656 case IRQ_UART2:
@@ -659,12 +674,14 @@ void __init s3c24xx_init_irq(void)
659 674
660 /* setup the cascade irq handlers */ 675 /* setup the cascade irq handlers */
661 676
677 set_irq_chained_handler(IRQ_EINT4t7, s3c_irq_demux_extint);
678 set_irq_chained_handler(IRQ_EINT8t23, s3c_irq_demux_extint);
679
662 set_irq_chained_handler(IRQ_UART0, s3c_irq_demux_uart0); 680 set_irq_chained_handler(IRQ_UART0, s3c_irq_demux_uart0);
663 set_irq_chained_handler(IRQ_UART1, s3c_irq_demux_uart1); 681 set_irq_chained_handler(IRQ_UART1, s3c_irq_demux_uart1);
664 set_irq_chained_handler(IRQ_UART2, s3c_irq_demux_uart2); 682 set_irq_chained_handler(IRQ_UART2, s3c_irq_demux_uart2);
665 set_irq_chained_handler(IRQ_ADCPARENT, s3c_irq_demux_adc); 683 set_irq_chained_handler(IRQ_ADCPARENT, s3c_irq_demux_adc);
666 684
667
668 /* external interrupts */ 685 /* external interrupts */
669 686
670 for (irqno = IRQ_EINT0; irqno <= IRQ_EINT3; irqno++) { 687 for (irqno = IRQ_EINT0; irqno <= IRQ_EINT3; irqno++) {
diff --git a/arch/arm/mach-s3c2410/mach-smdk2413.c b/arch/arm/mach-s3c2410/mach-smdk2413.c
new file mode 100644
index 000000000000..b7ef7d3c54a9
--- /dev/null
+++ b/arch/arm/mach-s3c2410/mach-smdk2413.c
@@ -0,0 +1,126 @@
1/* linux/arch/arm/mach-s3c2410/mach-smdk2413.c
2 *
3 * Copyright (c) 2006 Simtec Electronics
4 * Ben Dooks <ben@simtec.co.uk>
5 *
6 * Thanks to Dimity Andric (TomTom) and Steven Ryu (Samsung) for the
7 * loans of SMDK2413 to work with.
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
12*/
13
14#include <linux/kernel.h>
15#include <linux/types.h>
16#include <linux/interrupt.h>
17#include <linux/list.h>
18#include <linux/timer.h>
19#include <linux/init.h>
20#include <linux/platform_device.h>
21
22#include <asm/mach/arch.h>
23#include <asm/mach/map.h>
24#include <asm/mach/irq.h>
25
26#include <asm/hardware.h>
27#include <asm/hardware/iomd.h>
28#include <asm/setup.h>
29#include <asm/io.h>
30#include <asm/irq.h>
31#include <asm/mach-types.h>
32
33//#include <asm/debug-ll.h>
34#include <asm/arch/regs-serial.h>
35#include <asm/arch/regs-gpio.h>
36#include <asm/arch/regs-lcd.h>
37
38#include <asm/arch/idle.h>
39#include <asm/arch/fb.h>
40
41#include "s3c2410.h"
42#include "s3c2412.h"
43#include "clock.h"
44#include "devs.h"
45#include "cpu.h"
46
47#include "common-smdk.h"
48
49static struct map_desc smdk2413_iodesc[] __initdata = {
50};
51
52static struct s3c2410_uartcfg smdk2413_uartcfgs[] __initdata = {
53 [0] = {
54 .hwport = 0,
55 .flags = 0,
56 .ucon = 0x3c5,
57 .ulcon = 0x03,
58 .ufcon = 0x51,
59 },
60 [1] = {
61 .hwport = 1,
62 .flags = 0,
63 .ucon = 0x3c5,
64 .ulcon = 0x03,
65 .ufcon = 0x51,
66 },
67 /* IR port */
68 [2] = {
69 .hwport = 2,
70 .flags = 0,
71 .ucon = 0x3c5,
72 .ulcon = 0x43,
73 .ufcon = 0x51,
74 }
75};
76
77static struct platform_device *smdk2413_devices[] __initdata = {
78 &s3c_device_usb,
79 //&s3c_device_lcd,
80 &s3c_device_wdt,
81 &s3c_device_i2c,
82 &s3c_device_iis,
83};
84
85static struct s3c24xx_board smdk2413_board __initdata = {
86 .devices = smdk2413_devices,
87 .devices_count = ARRAY_SIZE(smdk2413_devices)
88};
89
90static void __init smdk2413_fixup(struct machine_desc *desc,
91 struct tag *tags, char **cmdline,
92 struct meminfo *mi)
93{
94 if (tags != phys_to_virt(S3C2410_SDRAM_PA + 0x100)) {
95 mi->nr_banks=1;
96 mi->bank[0].start = 0x30000000;
97 mi->bank[0].size = SZ_64M;
98 mi->bank[0].node = 0;
99 }
100}
101
102static void __init smdk2413_map_io(void)
103{
104 s3c24xx_init_io(smdk2413_iodesc, ARRAY_SIZE(smdk2413_iodesc));
105 s3c24xx_init_clocks(12000000);
106 s3c24xx_init_uarts(smdk2413_uartcfgs, ARRAY_SIZE(smdk2413_uartcfgs));
107 s3c24xx_set_board(&smdk2413_board);
108}
109
110static void __init smdk2413_machine_init(void)
111{
112 smdk_machine_init();
113}
114
115MACHINE_START(S3C2413, "SMDK2413")
116 /* Maintainer: Ben Dooks <ben@fluff.org> */
117 .phys_io = S3C2410_PA_UART,
118 .io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
119 .boot_params = S3C2410_SDRAM_PA + 0x100,
120
121 .fixup = smdk2413_fixup,
122 .init_irq = s3c24xx_init_irq,
123 .map_io = smdk2413_map_io,
124 .init_machine = smdk2413_machine_init,
125 .timer = &s3c24xx_timer,
126MACHINE_END
diff --git a/arch/arm/mach-s3c2410/pm-simtec.c b/arch/arm/mach-s3c2410/pm-simtec.c
index 4c7ccef6c207..7b244566a436 100644
--- a/arch/arm/mach-s3c2410/pm-simtec.c
+++ b/arch/arm/mach-s3c2410/pm-simtec.c
@@ -48,7 +48,8 @@ static __init int pm_simtec_init(void)
48 48
49 /* check which machine we are running on */ 49 /* check which machine we are running on */
50 50
51 if (!machine_is_bast() && !machine_is_vr1000() && !machine_is_anubis()) 51 if (!machine_is_bast() && !machine_is_vr1000() &&
52 !machine_is_anubis() && !machine_is_osiris())
52 return 0; 53 return 0;
53 54
54 printk(KERN_INFO "Simtec Board Power Manangement" COPYRIGHT "\n"); 55 printk(KERN_INFO "Simtec Board Power Manangement" COPYRIGHT "\n");
diff --git a/arch/arm/mach-s3c2410/s3c2410-clock.c b/arch/arm/mach-s3c2410/s3c2410-clock.c
index fd17c60e1132..99718663318e 100644
--- a/arch/arm/mach-s3c2410/s3c2410-clock.c
+++ b/arch/arm/mach-s3c2410/s3c2410-clock.c
@@ -182,7 +182,15 @@ static struct clk init_clocks[] = {
182 .id = -1, 182 .id = -1,
183 .parent = &clk_p, 183 .parent = &clk_p,
184 .ctrlbit = 0, 184 .ctrlbit = 0,
185 } 185 }, {
186 .name = "usb-bus-host",
187 .id = -1,
188 .parent = &clk_usb_bus,
189 }, {
190 .name = "usb-bus-gadget",
191 .id = -1,
192 .parent = &clk_usb_bus,
193 },
186}; 194};
187 195
188/* s3c2410_baseclk_add() 196/* s3c2410_baseclk_add()
diff --git a/arch/arm/mach-s3c2410/s3c2410-gpio.c b/arch/arm/mach-s3c2410/s3c2410-gpio.c
index d5e1caea1d23..471a71490010 100644
--- a/arch/arm/mach-s3c2410/s3c2410-gpio.c
+++ b/arch/arm/mach-s3c2410/s3c2410-gpio.c
@@ -18,9 +18,6 @@
18 * You should have received a copy of the GNU General Public License 18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software 19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 *
22 * Changelog
23 * 15-Jan-2006 LCVR Splitted from gpio.c
24 */ 21 */
25 22
26#include <linux/kernel.h> 23#include <linux/kernel.h>
@@ -38,7 +35,7 @@
38int s3c2410_gpio_irqfilter(unsigned int pin, unsigned int on, 35int s3c2410_gpio_irqfilter(unsigned int pin, unsigned int on,
39 unsigned int config) 36 unsigned int config)
40{ 37{
41 void __iomem *reg = S3C2410_EINFLT0; 38 void __iomem *reg = S3C24XX_EINFLT0;
42 unsigned long flags; 39 unsigned long flags;
43 unsigned long val; 40 unsigned long val;
44 41
@@ -47,7 +44,7 @@ int s3c2410_gpio_irqfilter(unsigned int pin, unsigned int on,
47 44
48 config &= 0xff; 45 config &= 0xff;
49 46
50 pin -= S3C2410_GPG8_EINT16; 47 pin -= S3C2410_GPG8;
51 reg += pin & ~3; 48 reg += pin & ~3;
52 49
53 local_irq_save(flags); 50 local_irq_save(flags);
@@ -61,10 +58,10 @@ int s3c2410_gpio_irqfilter(unsigned int pin, unsigned int on,
61 58
62 /* update filter enable */ 59 /* update filter enable */
63 60
64 val = __raw_readl(S3C2410_EXTINT2); 61 val = __raw_readl(S3C24XX_EXTINT2);
65 val &= ~(1 << ((pin * 4) + 3)); 62 val &= ~(1 << ((pin * 4) + 3));
66 val |= on << ((pin * 4) + 3); 63 val |= on << ((pin * 4) + 3);
67 __raw_writel(val, S3C2410_EXTINT2); 64 __raw_writel(val, S3C24XX_EXTINT2);
68 65
69 local_irq_restore(flags); 66 local_irq_restore(flags);
70 67
@@ -75,7 +72,7 @@ EXPORT_SYMBOL(s3c2410_gpio_irqfilter);
75 72
76int s3c2410_gpio_getirq(unsigned int pin) 73int s3c2410_gpio_getirq(unsigned int pin)
77{ 74{
78 if (pin < S3C2410_GPF0 || pin > S3C2410_GPG15_EINT23) 75 if (pin < S3C2410_GPF0 || pin > S3C2410_GPG15)
79 return -1; /* not valid interrupts */ 76 return -1; /* not valid interrupts */
80 77
81 if (pin < S3C2410_GPG0 && pin > S3C2410_GPF7) 78 if (pin < S3C2410_GPG0 && pin > S3C2410_GPF7)
diff --git a/arch/arm/mach-s3c2410/s3c2412-clock.c b/arch/arm/mach-s3c2410/s3c2412-clock.c
new file mode 100644
index 000000000000..c95ed3e18580
--- /dev/null
+++ b/arch/arm/mach-s3c2410/s3c2412-clock.c
@@ -0,0 +1,711 @@
1/* linux/arch/arm/mach-s3c2410/s3c2412-clock.c
2 *
3 * Copyright (c) 2006 Simtec Electronics
4 * Ben Dooks <ben@simtec.co.uk>
5 *
6 * S3C2412,S3C2413 Clock control support
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21*/
22
23#include <linux/init.h>
24#include <linux/module.h>
25#include <linux/kernel.h>
26#include <linux/list.h>
27#include <linux/errno.h>
28#include <linux/err.h>
29#include <linux/sysdev.h>
30#include <linux/clk.h>
31#include <linux/mutex.h>
32#include <linux/delay.h>
33
34#include <asm/hardware.h>
35#include <asm/io.h>
36
37#include <asm/arch/regs-clock.h>
38#include <asm/arch/regs-gpio.h>
39
40#include "clock.h"
41#include "cpu.h"
42
43/* We currently have to assume that the system is running
44 * from the XTPll input, and that all ***REFCLKs are being
45 * fed from it, as we cannot read the state of OM[4] from
46 * software.
47 *
48 * It would be possible for each board initialisation to
49 * set the correct muxing at initialisation
50*/
51
52int s3c2412_clkcon_enable(struct clk *clk, int enable)
53{
54 unsigned int clocks = clk->ctrlbit;
55 unsigned long clkcon;
56
57 clkcon = __raw_readl(S3C2410_CLKCON);
58
59 if (enable)
60 clkcon |= clocks;
61 else
62 clkcon &= ~clocks;
63
64 __raw_writel(clkcon, S3C2410_CLKCON);
65
66 return 0;
67}
68
69static int s3c2412_upll_enable(struct clk *clk, int enable)
70{
71 unsigned long upllcon = __raw_readl(S3C2410_UPLLCON);
72 unsigned long orig = upllcon;
73
74 if (!enable)
75 upllcon |= S3C2412_PLLCON_OFF;
76 else
77 upllcon &= ~S3C2412_PLLCON_OFF;
78
79 __raw_writel(upllcon, S3C2410_UPLLCON);
80
81 /* allow ~150uS for the PLL to settle and lock */
82
83 if (enable && (orig & S3C2412_PLLCON_OFF))
84 udelay(150);
85
86 return 0;
87}
88
89/* clock selections */
90
91/* CPU EXTCLK input */
92static struct clk clk_ext = {
93 .name = "extclk",
94 .id = -1,
95};
96
97static struct clk clk_erefclk = {
98 .name = "erefclk",
99 .id = -1,
100};
101
102static struct clk clk_urefclk = {
103 .name = "urefclk",
104 .id = -1,
105};
106
107static int s3c2412_setparent_usysclk(struct clk *clk, struct clk *parent)
108{
109 unsigned long clksrc = __raw_readl(S3C2412_CLKSRC);
110
111 if (parent == &clk_urefclk)
112 clksrc &= ~S3C2412_CLKSRC_USYSCLK_UPLL;
113 else if (parent == &clk_upll)
114 clksrc |= S3C2412_CLKSRC_USYSCLK_UPLL;
115 else
116 return -EINVAL;
117
118 clk->parent = parent;
119
120 __raw_writel(clksrc, S3C2412_CLKSRC);
121 return 0;
122}
123
124static struct clk clk_usysclk = {
125 .name = "usysclk",
126 .id = -1,
127 .parent = &clk_xtal,
128 .set_parent = s3c2412_setparent_usysclk,
129};
130
131static struct clk clk_mrefclk = {
132 .name = "mrefclk",
133 .parent = &clk_xtal,
134 .id = -1,
135};
136
137static struct clk clk_mdivclk = {
138 .name = "mdivclk",
139 .parent = &clk_xtal,
140 .id = -1,
141};
142
143static int s3c2412_setparent_usbsrc(struct clk *clk, struct clk *parent)
144{
145 unsigned long clksrc = __raw_readl(S3C2412_CLKSRC);
146
147 if (parent == &clk_usysclk)
148 clksrc &= ~S3C2412_CLKSRC_USBCLK_HCLK;
149 else if (parent == &clk_h)
150 clksrc |= S3C2412_CLKSRC_USBCLK_HCLK;
151 else
152 return -EINVAL;
153
154 clk->parent = parent;
155
156 __raw_writel(clksrc, S3C2412_CLKSRC);
157 return 0;
158}
159
160static unsigned long s3c2412_roundrate_usbsrc(struct clk *clk,
161 unsigned long rate)
162{
163 unsigned long parent_rate = clk_get_rate(clk->parent);
164 int div;
165
166 if (rate > parent_rate)
167 return parent_rate;
168
169 div = parent_rate / rate;
170 if (div > 2)
171 div = 2;
172
173 return parent_rate / div;
174}
175
176static unsigned long s3c2412_getrate_usbsrc(struct clk *clk)
177{
178 unsigned long parent_rate = clk_get_rate(clk->parent);
179 unsigned long div = __raw_readl(S3C2410_CLKDIVN);
180
181 return parent_rate / ((div & S3C2412_CLKDIVN_USB48DIV) ? 2 : 1);
182}
183
184static int s3c2412_setrate_usbsrc(struct clk *clk, unsigned long rate)
185{
186 unsigned long parent_rate = clk_get_rate(clk->parent);
187 unsigned long clkdivn = __raw_readl(S3C2410_CLKDIVN);
188
189 rate = s3c2412_roundrate_usbsrc(clk, rate);
190
191 if ((parent_rate / rate) == 2)
192 clkdivn |= S3C2412_CLKDIVN_USB48DIV;
193 else
194 clkdivn &= ~S3C2412_CLKDIVN_USB48DIV;
195
196 __raw_writel(clkdivn, S3C2410_CLKDIVN);
197 return 0;
198}
199
200static struct clk clk_usbsrc = {
201 .name = "usbsrc",
202 .id = -1,
203 .get_rate = s3c2412_getrate_usbsrc,
204 .set_rate = s3c2412_setrate_usbsrc,
205 .round_rate = s3c2412_roundrate_usbsrc,
206 .set_parent = s3c2412_setparent_usbsrc,
207};
208
209static int s3c2412_setparent_msysclk(struct clk *clk, struct clk *parent)
210{
211 unsigned long clksrc = __raw_readl(S3C2412_CLKSRC);
212
213 if (parent == &clk_mdivclk)
214 clksrc &= ~S3C2412_CLKSRC_MSYSCLK_MPLL;
215 else if (parent == &clk_upll)
216 clksrc |= S3C2412_CLKSRC_MSYSCLK_MPLL;
217 else
218 return -EINVAL;
219
220 clk->parent = parent;
221
222 __raw_writel(clksrc, S3C2412_CLKSRC);
223 return 0;
224}
225
226static struct clk clk_msysclk = {
227 .name = "msysclk",
228 .id = -1,
229 .set_parent = s3c2412_setparent_msysclk,
230};
231
232/* these next clocks have an divider immediately after them,
233 * so we can register them with their divider and leave out the
234 * intermediate clock stage
235*/
236static unsigned long s3c2412_roundrate_clksrc(struct clk *clk,
237 unsigned long rate)
238{
239 unsigned long parent_rate = clk_get_rate(clk->parent);
240 int div;
241
242 if (rate > parent_rate)
243 return parent_rate;
244
245 /* note, we remove the +/- 1 calculations as they cancel out */
246
247 div = (rate / parent_rate);
248
249 if (div < 1)
250 div = 1;
251 else if (div > 16)
252 div = 16;
253
254 return parent_rate / div;
255}
256
257static int s3c2412_setparent_uart(struct clk *clk, struct clk *parent)
258{
259 unsigned long clksrc = __raw_readl(S3C2412_CLKSRC);
260
261 if (parent == &clk_erefclk)
262 clksrc &= ~S3C2412_CLKSRC_UARTCLK_MPLL;
263 else if (parent == &clk_mpll)
264 clksrc |= S3C2412_CLKSRC_UARTCLK_MPLL;
265 else
266 return -EINVAL;
267
268 clk->parent = parent;
269
270 __raw_writel(clksrc, S3C2412_CLKSRC);
271 return 0;
272}
273
274static unsigned long s3c2412_getrate_uart(struct clk *clk)
275{
276 unsigned long parent_rate = clk_get_rate(clk->parent);
277 unsigned long div = __raw_readl(S3C2410_CLKDIVN);
278
279 div &= S3C2412_CLKDIVN_UARTDIV_MASK;
280 div >>= S3C2412_CLKDIVN_UARTDIV_SHIFT;
281
282 return parent_rate / (div + 1);
283}
284
285static int s3c2412_setrate_uart(struct clk *clk, unsigned long rate)
286{
287 unsigned long parent_rate = clk_get_rate(clk->parent);
288 unsigned long clkdivn = __raw_readl(S3C2410_CLKDIVN);
289
290 rate = s3c2412_roundrate_clksrc(clk, rate);
291
292 clkdivn &= ~S3C2412_CLKDIVN_UARTDIV_MASK;
293 clkdivn |= ((parent_rate / rate) - 1) << S3C2412_CLKDIVN_UARTDIV_SHIFT;
294
295 __raw_writel(clkdivn, S3C2410_CLKDIVN);
296 return 0;
297}
298
299static struct clk clk_uart = {
300 .name = "uartclk",
301 .id = -1,
302 .get_rate = s3c2412_getrate_uart,
303 .set_rate = s3c2412_setrate_uart,
304 .set_parent = s3c2412_setparent_uart,
305 .round_rate = s3c2412_roundrate_clksrc,
306};
307
308static int s3c2412_setparent_i2s(struct clk *clk, struct clk *parent)
309{
310 unsigned long clksrc = __raw_readl(S3C2412_CLKSRC);
311
312 if (parent == &clk_erefclk)
313 clksrc &= ~S3C2412_CLKSRC_I2SCLK_MPLL;
314 else if (parent == &clk_mpll)
315 clksrc |= S3C2412_CLKSRC_I2SCLK_MPLL;
316 else
317 return -EINVAL;
318
319 clk->parent = parent;
320
321 __raw_writel(clksrc, S3C2412_CLKSRC);
322 return 0;
323}
324
325static unsigned long s3c2412_getrate_i2s(struct clk *clk)
326{
327 unsigned long parent_rate = clk_get_rate(clk->parent);
328 unsigned long div = __raw_readl(S3C2410_CLKDIVN);
329
330 div &= S3C2412_CLKDIVN_I2SDIV_MASK;
331 div >>= S3C2412_CLKDIVN_I2SDIV_SHIFT;
332
333 return parent_rate / (div + 1);
334}
335
336static int s3c2412_setrate_i2s(struct clk *clk, unsigned long rate)
337{
338 unsigned long parent_rate = clk_get_rate(clk->parent);
339 unsigned long clkdivn = __raw_readl(S3C2410_CLKDIVN);
340
341 rate = s3c2412_roundrate_clksrc(clk, rate);
342
343 clkdivn &= ~S3C2412_CLKDIVN_I2SDIV_MASK;
344 clkdivn |= ((parent_rate / rate) - 1) << S3C2412_CLKDIVN_I2SDIV_SHIFT;
345
346 __raw_writel(clkdivn, S3C2410_CLKDIVN);
347 return 0;
348}
349
350static struct clk clk_i2s = {
351 .name = "i2sclk",
352 .id = -1,
353 .get_rate = s3c2412_getrate_i2s,
354 .set_rate = s3c2412_setrate_i2s,
355 .set_parent = s3c2412_setparent_i2s,
356 .round_rate = s3c2412_roundrate_clksrc,
357};
358
359static int s3c2412_setparent_cam(struct clk *clk, struct clk *parent)
360{
361 unsigned long clksrc = __raw_readl(S3C2412_CLKSRC);
362
363 if (parent == &clk_usysclk)
364 clksrc &= ~S3C2412_CLKSRC_CAMCLK_HCLK;
365 else if (parent == &clk_h)
366 clksrc |= S3C2412_CLKSRC_CAMCLK_HCLK;
367 else
368 return -EINVAL;
369
370 clk->parent = parent;
371
372 __raw_writel(clksrc, S3C2412_CLKSRC);
373 return 0;
374}
375static unsigned long s3c2412_getrate_cam(struct clk *clk)
376{
377 unsigned long parent_rate = clk_get_rate(clk->parent);
378 unsigned long div = __raw_readl(S3C2410_CLKDIVN);
379
380 div &= S3C2412_CLKDIVN_CAMDIV_MASK;
381 div >>= S3C2412_CLKDIVN_CAMDIV_SHIFT;
382
383 return parent_rate / (div + 1);
384}
385
386static int s3c2412_setrate_cam(struct clk *clk, unsigned long rate)
387{
388 unsigned long parent_rate = clk_get_rate(clk->parent);
389 unsigned long clkdivn = __raw_readl(S3C2410_CLKDIVN);
390
391 rate = s3c2412_roundrate_clksrc(clk, rate);
392
393 clkdivn &= ~S3C2412_CLKDIVN_CAMDIV_MASK;
394 clkdivn |= ((parent_rate / rate) - 1) << S3C2412_CLKDIVN_CAMDIV_SHIFT;
395
396 __raw_writel(clkdivn, S3C2410_CLKDIVN);
397 return 0;
398}
399
400static struct clk clk_cam = {
401 .name = "camif-upll", /* same as 2440 name */
402 .id = -1,
403 .get_rate = s3c2412_getrate_cam,
404 .set_rate = s3c2412_setrate_cam,
405 .set_parent = s3c2412_setparent_cam,
406 .round_rate = s3c2412_roundrate_clksrc,
407};
408
409/* standard clock definitions */
410
411static struct clk init_clocks_disable[] = {
412 {
413 .name = "nand",
414 .id = -1,
415 .parent = &clk_h,
416 .enable = s3c2412_clkcon_enable,
417 .ctrlbit = S3C2412_CLKCON_NAND,
418 }, {
419 .name = "sdi",
420 .id = -1,
421 .parent = &clk_p,
422 .enable = s3c2412_clkcon_enable,
423 .ctrlbit = S3C2412_CLKCON_SDI,
424 }, {
425 .name = "adc",
426 .id = -1,
427 .parent = &clk_p,
428 .enable = s3c2412_clkcon_enable,
429 .ctrlbit = S3C2412_CLKCON_ADC,
430 }, {
431 .name = "i2c",
432 .id = -1,
433 .parent = &clk_p,
434 .enable = s3c2412_clkcon_enable,
435 .ctrlbit = S3C2412_CLKCON_IIC,
436 }, {
437 .name = "iis",
438 .id = -1,
439 .parent = &clk_p,
440 .enable = s3c2412_clkcon_enable,
441 .ctrlbit = S3C2412_CLKCON_IIS,
442 }, {
443 .name = "spi",
444 .id = -1,
445 .parent = &clk_p,
446 .enable = s3c2412_clkcon_enable,
447 .ctrlbit = S3C2412_CLKCON_SPI,
448 }
449};
450
451static struct clk init_clocks[] = {
452 {
453 .name = "dma",
454 .id = 0,
455 .parent = &clk_h,
456 .enable = s3c2412_clkcon_enable,
457 .ctrlbit = S3C2412_CLKCON_DMA0,
458 }, {
459 .name = "dma",
460 .id = 1,
461 .parent = &clk_h,
462 .enable = s3c2412_clkcon_enable,
463 .ctrlbit = S3C2412_CLKCON_DMA1,
464 }, {
465 .name = "dma",
466 .id = 2,
467 .parent = &clk_h,
468 .enable = s3c2412_clkcon_enable,
469 .ctrlbit = S3C2412_CLKCON_DMA2,
470 }, {
471 .name = "dma",
472 .id = 3,
473 .parent = &clk_h,
474 .enable = s3c2412_clkcon_enable,
475 .ctrlbit = S3C2412_CLKCON_DMA3,
476 }, {
477 .name = "lcd",
478 .id = -1,
479 .parent = &clk_h,
480 .enable = s3c2412_clkcon_enable,
481 .ctrlbit = S3C2412_CLKCON_LCDC,
482 }, {
483 .name = "gpio",
484 .id = -1,
485 .parent = &clk_p,
486 .enable = s3c2412_clkcon_enable,
487 .ctrlbit = S3C2412_CLKCON_GPIO,
488 }, {
489 .name = "usb-host",
490 .id = -1,
491 .parent = &clk_h,
492 .enable = s3c2412_clkcon_enable,
493 .ctrlbit = S3C2412_CLKCON_USBH,
494 }, {
495 .name = "usb-device",
496 .id = -1,
497 .parent = &clk_h,
498 .enable = s3c2412_clkcon_enable,
499 .ctrlbit = S3C2412_CLKCON_USBD,
500 }, {
501 .name = "timers",
502 .id = -1,
503 .parent = &clk_p,
504 .enable = s3c2412_clkcon_enable,
505 .ctrlbit = S3C2412_CLKCON_PWMT,
506 }, {
507 .name = "uart",
508 .id = 0,
509 .parent = &clk_p,
510 .enable = s3c2412_clkcon_enable,
511 .ctrlbit = S3C2412_CLKCON_UART0,
512 }, {
513 .name = "uart",
514 .id = 1,
515 .parent = &clk_p,
516 .enable = s3c2412_clkcon_enable,
517 .ctrlbit = S3C2412_CLKCON_UART1,
518 }, {
519 .name = "uart",
520 .id = 2,
521 .parent = &clk_p,
522 .enable = s3c2412_clkcon_enable,
523 .ctrlbit = S3C2412_CLKCON_UART2,
524 }, {
525 .name = "rtc",
526 .id = -1,
527 .parent = &clk_p,
528 .enable = s3c2412_clkcon_enable,
529 .ctrlbit = S3C2412_CLKCON_RTC,
530 }, {
531 .name = "watchdog",
532 .id = -1,
533 .parent = &clk_p,
534 .ctrlbit = 0,
535 }, {
536 .name = "usb-bus-gadget",
537 .id = -1,
538 .parent = &clk_usb_bus,
539 .enable = s3c2412_clkcon_enable,
540 .ctrlbit = S3C2412_CLKCON_USB_DEV48,
541 }, {
542 .name = "usb-bus-host",
543 .id = -1,
544 .parent = &clk_usb_bus,
545 .enable = s3c2412_clkcon_enable,
546 .ctrlbit = S3C2412_CLKCON_USB_HOST48,
547 }
548};
549
550/* clocks to add where we need to check their parentage */
551
552struct clk_init {
553 struct clk *clk;
554 unsigned int bit;
555 struct clk *src_0;
556 struct clk *src_1;
557};
558
559struct clk_init clks_src[] __initdata = {
560 {
561 .clk = &clk_usysclk,
562 .bit = S3C2412_CLKSRC_USBCLK_HCLK,
563 .src_0 = &clk_urefclk,
564 .src_1 = &clk_upll,
565 }, {
566 .clk = &clk_i2s,
567 .bit = S3C2412_CLKSRC_I2SCLK_MPLL,
568 .src_0 = &clk_erefclk,
569 .src_1 = &clk_mpll,
570 }, {
571 .clk = &clk_cam,
572 .bit = S3C2412_CLKSRC_CAMCLK_HCLK,
573 .src_0 = &clk_usysclk,
574 .src_1 = &clk_h,
575 }, {
576 .clk = &clk_msysclk,
577 .bit = S3C2412_CLKSRC_MSYSCLK_MPLL,
578 .src_0 = &clk_mdivclk,
579 .src_1 = &clk_mpll,
580 }, {
581 .clk = &clk_uart,
582 .bit = S3C2412_CLKSRC_UARTCLK_MPLL,
583 .src_0 = &clk_erefclk,
584 .src_1 = &clk_mpll,
585 }, {
586 .clk = &clk_usbsrc,
587 .bit = S3C2412_CLKSRC_USBCLK_HCLK,
588 .src_0 = &clk_usysclk,
589 .src_1 = &clk_h,
590 },
591};
592
593/* s3c2412_clk_initparents
594 *
595 * Initialise the parents for the clocks that we get at start-time
596*/
597
598static void __init s3c2412_clk_initparents(void)
599{
600 unsigned long clksrc = __raw_readl(S3C2412_CLKSRC);
601 struct clk_init *cip = clks_src;
602 struct clk *src;
603 int ptr;
604 int ret;
605
606 for (ptr = 0; ptr < ARRAY_SIZE(clks_src); ptr++, cip++) {
607 ret = s3c24xx_register_clock(cip->clk);
608 if (ret < 0) {
609 printk(KERN_ERR "Failed to register clock %s (%d)\n",
610 cip->clk->name, ret);
611 }
612
613 src = (clksrc & cip->bit) ? cip->src_1 : cip->src_0;
614
615 printk(KERN_INFO "%s: parent %s\n", cip->clk->name, src->name);
616 clk_set_parent(cip->clk, src);
617 }
618}
619
620/* clocks to add straight away */
621
622struct clk *clks[] __initdata = {
623 &clk_ext,
624 &clk_usb_bus,
625 &clk_erefclk,
626 &clk_urefclk,
627 &clk_mrefclk,
628};
629
630int __init s3c2412_baseclk_add(void)
631{
632 unsigned long clkcon = __raw_readl(S3C2410_CLKCON);
633 struct clk *clkp;
634 int ret;
635 int ptr;
636
637 clk_upll.enable = s3c2412_upll_enable;
638 clk_usb_bus.parent = &clk_usbsrc;
639 clk_usb_bus.rate = 0x0;
640
641 s3c2412_clk_initparents();
642
643 for (ptr = 0; ptr < ARRAY_SIZE(clks); ptr++) {
644 clkp = clks[ptr];
645
646 ret = s3c24xx_register_clock(clkp);
647 if (ret < 0) {
648 printk(KERN_ERR "Failed to register clock %s (%d)\n",
649 clkp->name, ret);
650 }
651 }
652
653 /* ensure usb bus clock is within correct rate of 48MHz */
654
655 if (clk_get_rate(&clk_usb_bus) != (48 * 1000 * 1000)) {
656 printk(KERN_INFO "Warning: USB bus clock not at 48MHz\n");
657
658 /* for the moment, let's use the UPLL, and see if we can
659 * get 48MHz */
660
661 clk_set_parent(&clk_usysclk, &clk_upll);
662 clk_set_parent(&clk_usbsrc, &clk_usysclk);
663 clk_set_rate(&clk_usbsrc, 48*1000*1000);
664 }
665
666 printk("S3C2412: upll %s, %ld.%03ld MHz, usb-bus %ld.%03ld MHz\n",
667 (__raw_readl(S3C2410_UPLLCON) & S3C2412_PLLCON_OFF) ? "off":"on",
668 print_mhz(clk_get_rate(&clk_upll)),
669 print_mhz(clk_get_rate(&clk_usb_bus)));
670
671 /* register clocks from clock array */
672
673 clkp = init_clocks;
674 for (ptr = 0; ptr < ARRAY_SIZE(init_clocks); ptr++, clkp++) {
675 /* ensure that we note the clock state */
676
677 clkp->usage = clkcon & clkp->ctrlbit ? 1 : 0;
678
679 ret = s3c24xx_register_clock(clkp);
680 if (ret < 0) {
681 printk(KERN_ERR "Failed to register clock %s (%d)\n",
682 clkp->name, ret);
683 }
684 }
685
686 /* We must be careful disabling the clocks we are not intending to
687 * be using at boot time, as subsytems such as the LCD which do
688 * their own DMA requests to the bus can cause the system to lockup
689 * if they where in the middle of requesting bus access.
690 *
691 * Disabling the LCD clock if the LCD is active is very dangerous,
692 * and therefore the bootloader should be careful to not enable
693 * the LCD clock if it is not needed.
694 */
695
696 /* install (and disable) the clocks we do not need immediately */
697
698 clkp = init_clocks_disable;
699 for (ptr = 0; ptr < ARRAY_SIZE(init_clocks_disable); ptr++, clkp++) {
700
701 ret = s3c24xx_register_clock(clkp);
702 if (ret < 0) {
703 printk(KERN_ERR "Failed to register clock %s (%d)\n",
704 clkp->name, ret);
705 }
706
707 s3c2412_clkcon_enable(clkp, 0);
708 }
709
710 return 0;
711}
diff --git a/arch/arm/mach-s3c2410/s3c2412.c b/arch/arm/mach-s3c2410/s3c2412.c
new file mode 100644
index 000000000000..e24ffd5e478b
--- /dev/null
+++ b/arch/arm/mach-s3c2410/s3c2412.c
@@ -0,0 +1,195 @@
1/* linux/arch/arm/mach-s3c2410/s3c2412.c
2 *
3 * Copyright (c) 2006 Simtec Electronics
4 * Ben Dooks <ben@simtec.co.uk>
5 *
6 * http://armlinux.simtec.co.uk/.
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 *
12 * Modifications:
13 * 16-May-2003 BJD Created initial version
14 * 16-Aug-2003 BJD Fixed header files and copyright, added URL
15 * 05-Sep-2003 BJD Moved to kernel v2.6
16 * 18-Jan-2004 BJD Added serial port configuration
17 * 21-Aug-2004 BJD Added new struct s3c2410_board handler
18 * 28-Sep-2004 BJD Updates for new serial port bits
19 * 04-Nov-2004 BJD Updated UART configuration process
20 * 10-Jan-2005 BJD Removed s3c2410_clock_tick_rate
21 * 13-Aug-2005 DA Removed UART from initial I/O mappings
22*/
23
24#include <linux/kernel.h>
25#include <linux/types.h>
26#include <linux/interrupt.h>
27#include <linux/list.h>
28#include <linux/timer.h>
29#include <linux/init.h>
30#include <linux/sysdev.h>
31#include <linux/platform_device.h>
32
33#include <asm/mach/arch.h>
34#include <asm/mach/map.h>
35#include <asm/mach/irq.h>
36
37#include <asm/hardware.h>
38#include <asm/io.h>
39#include <asm/irq.h>
40
41#include <asm/arch/regs-clock.h>
42#include <asm/arch/regs-serial.h>
43#include <asm/arch/regs-gpio.h>
44#include <asm/arch/regs-gpioj.h>
45#include <asm/arch/regs-dsc.h>
46
47#include "s3c2412.h"
48#include "cpu.h"
49#include "devs.h"
50#include "clock.h"
51#include "pm.h"
52
53#ifndef CONFIG_CPU_S3C2412_ONLY
54void __iomem *s3c24xx_va_gpio2 = S3C24XX_VA_GPIO;
55#endif
56
57/* Initial IO mappings */
58
59static struct map_desc s3c2412_iodesc[] __initdata = {
60 IODESC_ENT(CLKPWR),
61 IODESC_ENT(LCD),
62 IODESC_ENT(TIMER),
63 IODESC_ENT(ADC),
64 IODESC_ENT(WATCHDOG),
65};
66
67/* uart registration process */
68
69void __init s3c2412_init_uarts(struct s3c2410_uartcfg *cfg, int no)
70{
71 s3c24xx_init_uartdevs("s3c2412-uart", s3c2410_uart_resources, cfg, no);
72
73 /* rename devices that are s3c2412/s3c2413 specific */
74 s3c_device_sdi.name = "s3c2412-sdi";
75 s3c_device_nand.name = "s3c2412-nand";
76}
77
78/* s3c2412_map_io
79 *
80 * register the standard cpu IO areas, and any passed in from the
81 * machine specific initialisation.
82*/
83
84void __init s3c2412_map_io(struct map_desc *mach_desc, int mach_size)
85{
86 /* move base of IO */
87
88 s3c24xx_va_gpio2 = S3C24XX_VA_GPIO + 0x10;
89
90 /* register our io-tables */
91
92 iotable_init(s3c2412_iodesc, ARRAY_SIZE(s3c2412_iodesc));
93 iotable_init(mach_desc, mach_size);
94}
95
96void __init s3c2412_init_clocks(int xtal)
97{
98 unsigned long tmp;
99 unsigned long fclk;
100 unsigned long hclk;
101 unsigned long pclk;
102
103 /* now we've got our machine bits initialised, work out what
104 * clocks we've got */
105
106 fclk = s3c2410_get_pll(__raw_readl(S3C2410_MPLLCON), xtal*2);
107
108 tmp = __raw_readl(S3C2410_CLKDIVN);
109
110 /* work out clock scalings */
111
112 hclk = fclk / ((tmp & S3C2412_CLKDIVN_HDIVN_MASK) + 1);
113 hclk /= ((tmp & S3C2421_CLKDIVN_ARMDIVN) ? 2 : 1);
114 pclk = hclk / ((tmp & S3C2412_CLKDIVN_PDIVN) ? 2 : 1);
115
116 /* print brieft summary of clocks, etc */
117
118 printk("S3C2412: core %ld.%03ld MHz, memory %ld.%03ld MHz, peripheral %ld.%03ld MHz\n",
119 print_mhz(fclk), print_mhz(hclk), print_mhz(pclk));
120
121 /* initialise the clocks here, to allow other things like the
122 * console to use them
123 */
124
125 s3c24xx_setup_clocks(xtal, fclk, hclk, pclk);
126 s3c2412_baseclk_add();
127}
128
129/* need to register class before we actually register the device, and
130 * we also need to ensure that it has been initialised before any of the
131 * drivers even try to use it (even if not on an s3c2412 based system)
132 * as a driver which may support both 2410 and 2440 may try and use it.
133*/
134
135#ifdef CONFIG_PM
136static struct sleep_save s3c2412_sleep[] = {
137 SAVE_ITEM(S3C2412_DSC0),
138 SAVE_ITEM(S3C2412_DSC1),
139 SAVE_ITEM(S3C2413_GPJDAT),
140 SAVE_ITEM(S3C2413_GPJCON),
141 SAVE_ITEM(S3C2413_GPJUP),
142
143 /* save the sleep configuration anyway, just in case these
144 * get damaged during wakeup */
145
146 SAVE_ITEM(S3C2412_GPBSLPCON),
147 SAVE_ITEM(S3C2412_GPCSLPCON),
148 SAVE_ITEM(S3C2412_GPDSLPCON),
149 SAVE_ITEM(S3C2412_GPESLPCON),
150 SAVE_ITEM(S3C2412_GPFSLPCON),
151 SAVE_ITEM(S3C2412_GPGSLPCON),
152 SAVE_ITEM(S3C2412_GPHSLPCON),
153 SAVE_ITEM(S3C2413_GPJSLPCON),
154};
155
156static int s3c2412_suspend(struct sys_device *dev, pm_message_t state)
157{
158 s3c2410_pm_do_save(s3c2412_sleep, ARRAY_SIZE(s3c2412_sleep));
159 return 0;
160}
161
162static int s3c2412_resume(struct sys_device *dev)
163{
164 s3c2410_pm_do_restore(s3c2412_sleep, ARRAY_SIZE(s3c2412_sleep));
165 return 0;
166}
167
168#else
169#define s3c2412_suspend NULL
170#define s3c2412_resume NULL
171#endif
172
173struct sysdev_class s3c2412_sysclass = {
174 set_kset_name("s3c2412-core"),
175 .suspend = s3c2412_suspend,
176 .resume = s3c2412_resume
177};
178
179static int __init s3c2412_core_init(void)
180{
181 return sysdev_class_register(&s3c2412_sysclass);
182}
183
184core_initcall(s3c2412_core_init);
185
186static struct sys_device s3c2412_sysdev = {
187 .cls = &s3c2412_sysclass,
188};
189
190int __init s3c2412_init(void)
191{
192 printk("S3C2412: Initialising architecture\n");
193
194 return sysdev_register(&s3c2412_sysdev);
195}
diff --git a/arch/arm/mach-s3c2410/s3c2412.h b/arch/arm/mach-s3c2410/s3c2412.h
new file mode 100644
index 000000000000..c6e56032a6e7
--- /dev/null
+++ b/arch/arm/mach-s3c2410/s3c2412.h
@@ -0,0 +1,29 @@
1/* arch/arm/mach-s3c2410/s3c2412.h
2 *
3 * Copyright (c) 2006 Simtec Electronics
4 * Ben Dooks <ben@simtec.co.uk>
5 *
6 * Header file for s3c2412 cpu support
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11*/
12
13#ifdef CONFIG_CPU_S3C2412
14
15extern int s3c2412_init(void);
16
17extern void s3c2412_map_io(struct map_desc *mach_desc, int size);
18
19extern void s3c2412_init_uarts(struct s3c2410_uartcfg *cfg, int no);
20
21extern void s3c2412_init_clocks(int xtal);
22
23extern int s3c2412_baseclk_add(void);
24#else
25#define s3c2412_init_clocks NULL
26#define s3c2412_init_uarts NULL
27#define s3c2412_map_io NULL
28#define s3c2412_init NULL
29#endif
diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig
index 4221d054a1e9..ecf5e232a6fc 100644
--- a/arch/arm/mm/Kconfig
+++ b/arch/arm/mm/Kconfig
@@ -61,9 +61,9 @@ config CPU_ARM720T
61 61
62# ARM920T 62# ARM920T
63config CPU_ARM920T 63config CPU_ARM920T
64 bool "Support ARM920T processor" if !ARCH_S3C2410 64 bool "Support ARM920T processor"
65 depends on ARCH_EP93XX || ARCH_INTEGRATOR || ARCH_S3C2410 || ARCH_IMX || ARCH_AAEC2000 || ARCH_AT91RM9200 65 depends on ARCH_EP93XX || ARCH_INTEGRATOR || CPU_S3C2410 || CPU_S3C2440 || CPU_S3C2442 || ARCH_IMX || ARCH_AAEC2000 || ARCH_AT91RM9200
66 default y if ARCH_S3C2410 || ARCH_AT91RM9200 66 default y if CPU_S3C2410 || CPU_S3C2440 || CPU_S3C2442 || ARCH_AT91RM9200
67 select CPU_32v4 67 select CPU_32v4
68 select CPU_ABRT_EV4T 68 select CPU_ABRT_EV4T
69 select CPU_CACHE_V4WT 69 select CPU_CACHE_V4WT
@@ -121,8 +121,8 @@ config CPU_ARM925T
121# ARM926T 121# ARM926T
122config CPU_ARM926T 122config CPU_ARM926T
123 bool "Support ARM926T processor" 123 bool "Support ARM926T processor"
124 depends on ARCH_INTEGRATOR || ARCH_VERSATILE_PB || MACH_VERSATILE_AB || ARCH_OMAP730 || ARCH_OMAP16XX || MACH_REALVIEW_EB || ARCH_PNX4008 || ARCH_NETX 124 depends on ARCH_INTEGRATOR || ARCH_VERSATILE_PB || MACH_VERSATILE_AB || ARCH_OMAP730 || ARCH_OMAP16XX || MACH_REALVIEW_EB || ARCH_PNX4008 || ARCH_NETX || CPU_S3C2412
125 default y if ARCH_VERSATILE_PB || MACH_VERSATILE_AB || ARCH_OMAP730 || ARCH_OMAP16XX || ARCH_PNX4008 || ARCH_NETX 125 default y if ARCH_VERSATILE_PB || MACH_VERSATILE_AB || ARCH_OMAP730 || ARCH_OMAP16XX || ARCH_PNX4008 || ARCH_NETX || CPU_S3C2412
126 select CPU_32v5 126 select CPU_32v5
127 select CPU_ABRT_EV5TJ 127 select CPU_ABRT_EV5TJ
128 select CPU_CACHE_VIVT 128 select CPU_CACHE_VIVT