102 lines
2.2 KiB
ArmAsm
102 lines
2.2 KiB
ArmAsm
|
/* init_clock.S -- AT91SAM7 clock coldstart code
|
||
|
**
|
||
|
** Copyright 2006, Brian Swetland. All rights reserved.
|
||
|
** See provided LICENSE file or http://frotz.net/LICENSE for details.
|
||
|
*/
|
||
|
|
||
|
.globl init_clock
|
||
|
|
||
|
init_clock:
|
||
|
/* init flash controller timing for 18.432MHz */
|
||
|
mov r1, #0xffffff00
|
||
|
ldr r0, =0x00340100
|
||
|
str r0, [r1, #0x60]
|
||
|
|
||
|
#define PMC_MOR 0x20
|
||
|
#define PMC_MCFR 0x24
|
||
|
#define PMC_PLLR 0x2c
|
||
|
#define PMC_MCKR 0x30
|
||
|
#define PMC_SR 0x68
|
||
|
|
||
|
/* PMC_MOR */
|
||
|
#define PMC_MOSCEN 0x01
|
||
|
#define PMC_OSCBYPASS 0x02
|
||
|
|
||
|
/* PMC_MCFR */
|
||
|
#define PMC_MAINRDY 0x00010000
|
||
|
|
||
|
/* PMC_SR */
|
||
|
#define PMC_MOSCS 0x01
|
||
|
#define PMC_LOCK 0x04
|
||
|
#define PMC_MCKRDY 0x08
|
||
|
|
||
|
/* PMC_MCKR */
|
||
|
#define PMC_CSS_SLOW 0x00
|
||
|
#define PMC_CSS_MAIN 0x01
|
||
|
#define PMC_CSS_PLL 0x03
|
||
|
#define PMC_PRES_NONE 0x00
|
||
|
#define PMC_PRES_DIV2 0x04
|
||
|
#define PMC_PRES_DIV4 0x08
|
||
|
|
||
|
/* Oscillator Init Sequence based on the Atmel sample code
|
||
|
** in cstartup_boot_SAM7S32_64.s
|
||
|
**
|
||
|
** I cleaned it up a bit -- why they use a temporary register,
|
||
|
** AND and then CMP instead of just TSTing against an immediate
|
||
|
** boggles my mind. I think this could be a bit simpler yet,
|
||
|
** but debugging it is a pain, so Good Enough wins for now.
|
||
|
*/
|
||
|
ldr r1, =0xfffffc00
|
||
|
|
||
|
/* bypass main oscillator */
|
||
|
mov r0, #PMC_OSCBYPASS
|
||
|
str r0, [r1, #PMC_MOR]
|
||
|
|
||
|
/* compensate MAINRDY rising flag (45 SCLK) */
|
||
|
mov r0, #45
|
||
|
1: subs r0, r0, #1
|
||
|
bhi 1b
|
||
|
|
||
|
/* if MAINRDY is set, we have an external oscillator */
|
||
|
ldr r0, [r1, #PMC_MCFR]
|
||
|
tst r0, #PMC_MAINRDY
|
||
|
bne ext_osc_found
|
||
|
|
||
|
/* reset MOSCS flag */
|
||
|
mov r0, #0
|
||
|
str r0, [r1, #PMC_MOR]
|
||
|
|
||
|
/* enable main oscillator */
|
||
|
ldr r0, =((0x40 << 8) | PMC_MOSCEN)
|
||
|
str r0, [r1, #PMC_MOR]
|
||
|
|
||
|
/* wait for main oscillator to come online */
|
||
|
1: ldr r0, [r1, #PMC_SR]
|
||
|
tst r0, #PMC_MOSCS
|
||
|
beq 1b
|
||
|
|
||
|
ext_osc_found:
|
||
|
/* select main oscillator, no prescaler for MCK */
|
||
|
mov r0, #(PMC_CSS_MAIN | PMC_PRES_NONE)
|
||
|
str r0, [r1, #PMC_MCKR]
|
||
|
|
||
|
/* wait until MCK settles to continue */
|
||
|
1: ldr r0, [r1, #PMC_SR]
|
||
|
tst r0, #PMC_MCKRDY
|
||
|
beq 1b
|
||
|
|
||
|
/* this is a bit of voodoo for selecting a 96.109MHz PLL
|
||
|
** freq (MUL=72, DIV=14, OUT=0, USBDIV=/1) from the 18.432MHz
|
||
|
** main clock.
|
||
|
*/
|
||
|
ldr r0, =0x10483f0e
|
||
|
str r0, [r1, #PMC_PLLR]
|
||
|
|
||
|
/* let the PLL lock before we continue */
|
||
|
1: ldr r0, [r1, #PMC_SR]
|
||
|
tst r0, #PMC_LOCK
|
||
|
beq 1b
|
||
|
|
||
|
mov pc, lr
|
||
|
|