blob: 2de137ff5cc0d96b89f0e2ea20bf66e32b8134ad [file] [log] [blame]
Travis Geiselbrecht1d0df692008-09-01 02:26:09 -07001/* init_clock.S -- AT91SAM7 clock coldstart code
2**
3** Copyright 2006, Brian Swetland. All rights reserved.
4** See provided LICENSE file or http://frotz.net/LICENSE for details.
5*/
6
7.globl init_clock
8
9init_clock:
10/* init flash controller timing for 18.432MHz */
11 mov r1, #0xffffff00
12 ldr r0, =0x00340100
13 str r0, [r1, #0x60]
14
15#define PMC_MOR 0x20
16#define PMC_MCFR 0x24
17#define PMC_PLLR 0x2c
18#define PMC_MCKR 0x30
19#define PMC_SR 0x68
20
21/* PMC_MOR */
22#define PMC_MOSCEN 0x01
23#define PMC_OSCBYPASS 0x02
24
25/* PMC_MCFR */
26#define PMC_MAINRDY 0x00010000
27
28/* PMC_SR */
29#define PMC_MOSCS 0x01
30#define PMC_LOCK 0x04
31#define PMC_MCKRDY 0x08
32
33/* PMC_MCKR */
34#define PMC_CSS_SLOW 0x00
35#define PMC_CSS_MAIN 0x01
36#define PMC_CSS_PLL 0x03
37#define PMC_PRES_NONE 0x00
38#define PMC_PRES_DIV2 0x04
39#define PMC_PRES_DIV4 0x08
40
41/* Oscillator Init Sequence based on the Atmel sample code
42** in cstartup_boot_SAM7S32_64.s
43**
44** I cleaned it up a bit -- why they use a temporary register,
45** AND and then CMP instead of just TSTing against an immediate
46** boggles my mind. I think this could be a bit simpler yet,
47** but debugging it is a pain, so Good Enough wins for now.
48*/
49 ldr r1, =0xfffffc00
50
51/* bypass main oscillator */
52 mov r0, #PMC_OSCBYPASS
53 str r0, [r1, #PMC_MOR]
54
55/* compensate MAINRDY rising flag (45 SCLK) */
56 mov r0, #45
571: subs r0, r0, #1
58 bhi 1b
59
60/* if MAINRDY is set, we have an external oscillator */
61 ldr r0, [r1, #PMC_MCFR]
62 tst r0, #PMC_MAINRDY
63 bne ext_osc_found
64
65/* reset MOSCS flag */
66 mov r0, #0
67 str r0, [r1, #PMC_MOR]
68
69/* enable main oscillator */
70 ldr r0, =((0x40 << 8) | PMC_MOSCEN)
71 str r0, [r1, #PMC_MOR]
72
73/* wait for main oscillator to come online */
741: ldr r0, [r1, #PMC_SR]
75 tst r0, #PMC_MOSCS
76 beq 1b
77
78ext_osc_found:
79/* select main oscillator, no prescaler for MCK */
80 mov r0, #(PMC_CSS_MAIN | PMC_PRES_NONE)
81 str r0, [r1, #PMC_MCKR]
82
83/* wait until MCK settles to continue */
841: ldr r0, [r1, #PMC_SR]
85 tst r0, #PMC_MCKRDY
86 beq 1b
87
88/* this is a bit of voodoo for selecting a 96.109MHz PLL
89** freq (MUL=72, DIV=14, OUT=0, USBDIV=/1) from the 18.432MHz
90** main clock.
91*/
92 ldr r0, =0x10483f0e
93 str r0, [r1, #PMC_PLLR]
94
95/* let the PLL lock before we continue */
961: ldr r0, [r1, #PMC_SR]
97 tst r0, #PMC_LOCK
98 beq 1b
99
100 mov pc, lr
101