summaryrefslogtreecommitdiffstats
path: root/c/src/lib/libcpu/powerpc/mpc55xx/misc/fmpll.S
blob: 162abb5e09c0c1a036091bb9391dce0e12ef0bab (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
/**
 * @file
 *
 * @ingroup mpc55xx_asm
 *
 * @brief FMPLL setup.
 */

/*
 * Copyright (c) 2008
 * Embedded Brains GmbH
 * Obere Lagerstr. 30
 * D-82178 Puchheim
 * Germany
 * rtems@embedded-brains.de
 *
 * The license and distribution terms for this file may be found in the file
 * LICENSE in this distribution or at http://www.rtems.com/license/LICENSE.
 */

#include <libcpu/powerpc-utility.h>
#include <mpc55xx/reg-defs.h>

.section ".text"

/* Timeout for delay in clocks */
.equ FMPLL_TIMEOUT, 6000

/* Reference clock */
.equ FMPLL_REF_CLOCK, 8000000

/* Settings for FMPLL from 12 MHz up to 128 MHz with 8 MHz reference frequency */
.equ FMPLL_128_8_SYNCR_SETTING_0, (FMPLL_SYNCR_PREDIV_0 | FMPLL_SYNCR_MFD_12 | FMPLL_SYNCR_RFD_2 | FMPLL_SYNCR_LOCEN)
.equ FMPLL_128_8_SYNCR_SETTING_1, (FMPLL_SYNCR_PREDIV_0 | FMPLL_SYNCR_MFD_12 | FMPLL_SYNCR_RFD_0 | FMPLL_SYNCR_LOCEN)

.macro DO_SETTING setting
	LWI r5, FMPLL_128_8_SYNCR_SETTING_\setting
	stw r5, 0(r4)
	msync
	bl mpc55xx_fmpll_wait_for_lock
.endm

/**
 * @fn void mpc55xx_fmpll_reset_config()
 * @brief Configure FMPLL after reset.
 *
 * Sets the system clock from 12 MHz in two steps up to 128 MHz.
 */
GLOBAL_FUNCTION mpc55xx_fmpll_reset_config
	/* Save link register */
	mflr r3

	LA r4, FMPLL_SYNCR

	DO_SETTING 0
	DO_SETTING 1

	/* Enable loss-of-clock and loss-of-lock IRQs */
	lwz r5, 0(r4)
	LWI r6, FMPLL_SYNCR_LOCIRQ | FMPLL_SYNCR_LOLIRQ
	or r5, r5, r6

	/* Disable loss-of-clock and loss-of-lock resets */
	LWI r6, ~FMPLL_SYNCR_LOCRE & ~FMPLL_SYNCR_LOLRE
	and r5, r5, r6
	stw r5, 0(r4)

	/* Restore link register and return */
	mtlr r3
	blr

/**
 * @fn void mpc55xx_fmpll_wait_for_lock()
 * @brief Wait for FMPLL lock.
 * @warning If the lock cannot be obtained within some clock cycles a software
 * system reset will be initiated.
 */
GLOBAL_FUNCTION mpc55xx_fmpll_wait_for_lock
	LWI r6, FMPLL_TIMEOUT
	mtctr r6

	LWI r7, FMPLL_SYNSR_LOCK

	LA r6, FMPLL_SYNSR

fmpll_not_locked:
	bdnz fmpll_continue

	b mpc55xx_system_reset
fmpll_continue:
	lwz r8, 0(r6)
	and. r8, r8, r7
	beq fmpll_not_locked

	blr

/**
 * @fn int mpc55xx_get_system_clock()
 * @brief Returns the system clock.
 */
GLOBAL_FUNCTION mpc55xx_get_system_clock
	LA r4, FMPLL_SYNCR
	lwz r3, 0(r4)

	/* PREDIV */
	rlwinm r5, r3, 4, 29, 31

	/* MFD */
	rlwinm r6, r3, 9, 27, 31

	/* RFD */
	rlwinm r7, r3, 13, 29, 31

	/* Calculate system clock (Table 11-10 [MPC5567 Microcontroller Reference Manual]) */
	LWI r8, FMPLL_REF_CLOCK
	addi r5, r5, 1
	addi r6, r6, 4
	mullw r6, r6, r8
	sraw r6, r6, r7
	divw r3, r6, r5

	blr

/**
 * @fn void mpc55xx_system_reset()
 * @brief Software system reset.
 */
GLOBAL_FUNCTION mpc55xx_system_reset
	LA r8, SIU_SRCR
	LWI r9, SIU_SRCR_SSR
	stw r9, 0(r8)
twiddle:
	b twiddle