summaryrefslogtreecommitdiffstats
path: root/c/src/lib/libcpu/powerpc/mpc55xx/misc/fmpll.S
blob: 6613f0bd1b88b28ae496adcfda9b2e7b991fa74a (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
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
/**
 * @file
 *
 * @ingroup mpc55xx_asm
 *
 * @brief FMPLL setup.
 */

/*
 * Copyright (c) 2008-2011 embedded brains GmbH.  All rights reserved.
 *
 *  embedded brains GmbH
 *  Obere Lagerstr. 30
 *  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.
 *
 * $Id$
 */

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

#define FMPLL_IS_MPC551X (5510 <= MPC55XX_CHIP_TYPE && MPC55XX_CHIP_TYPE <= 5517)

#define FMPLL_IS_MPC5674 (MPC55XX_CHIP_TYPE == 5674)

#define FMPLL_HAS_ENHANCED_FMPLL (FMPLL_IS_MPC551X || FMPLL_IS_MPC5674)
	
	.section ".bsp_start_text", "ax"

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

.macro DO_SETTING setting
	lwz r5, \setting
	stw r5, 0(r4)
	msync
	bl fmpll_wait_for_lock
.endm

/**
 * @fn void mpc55xx_fmpll_init()
 * @brief Configure FMPLL after reset.
 */
GLOBAL_FUNCTION mpc55xx_fmpll_init
	/* Save link register */
	mflr r9

#if FMPLL_HAS_ENHANCED_FMPLL
	/*
	 * for MPC5510: pass in ptr to array with:
	 * off 0:  temp setting for ESYNCR2
	 * off 4: final setting for ESYNCR2
	 * off 8: final setting for ESYNCR1
	 */
	LA r4, FMPLL_ESYNCR2

	lwz r5, 0(r3)
	stw r5, 0(r4)
	msync

	lwz r5, 8(r3)
	stw r5, (FMPLL_ESYNCR1-FMPLL_ESYNCR2)(r4)	
	msync
	bl fmpll_wait_for_lock

	DO_SETTING 4(r3)

#if FMPLL_IS_MPC551X
	/*
	 * switch to PLL clock in SIU
	 */
	LA r4, SIU_SYSCLK
	lwz r5, 0(r4)
	LWI r6, ~SIU_SYSCLK_SYSCLKSEL_MASK
	and r5, r5, r6
	LWI r6, SIU_SYSCLK_SYSCLKSEL_PLL
	or  r5, r5, r6
	stw r5, 0(r4)
#endif /* FMPLL_IS_MPC551X */
#else /* !FMPLL_HAS_ENHANCED_FMPLL */
	/*
	 * for MPC5566: pass in ptr to array with:
	 * off 0:  temp setting for SYNCR
	 * off 4: final setting for SYNCR
	 */

	LA r4, FMPLL_SYNCR

	DO_SETTING 0(r3)
	DO_SETTING 4(r3)

	/* 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)
#endif /* !FMPLL_HAS_ENHANCED_FMPLL */

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

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 r5, 0(r6)
	and. r5, r5, r7
	beq fmpll_not_locked

	blr

	.section ".text", "aw"

/**
 * @fn int mpc55xx_get_system_clock()
 * @brief Returns the system clock.
 */
GLOBAL_FUNCTION mpc55xx_get_system_clock
#if FMPLL_HAS_ENHANCED_FMPLL
	LA r4, FMPLL_ESYNCR1
	lwz r3, 0(r4)
	/* EPREDIV */
	rlwinm r5, r3,16, 28, 31

	/* MFD */
	rlwinm r6, r3,0, 24, 31

	LA r4, FMPLL_ESYNCR2
	lwz r3, 0(r4)
	/* ERFD */
	rlwinm r7, r3,0, 26, 31

	LWI r8, MPC55XX_FMPLL_REF_CLOCK
	addi r5, r5, 1
	addi r6, r6,16
	addi r7, r7, 1
	divw r3, r8, r5  /* REF_CLOCK/PREDIV */
	mullw r3, r6, r3 /* REF_CLOCK/PREDIV*MFD */
	divw r3, r3, r7  /* REF_CLOCK/PREDIV*MFD/RFD */
#else /* !FMPLL_HAS_ENHANCED_FMPLL */
	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, MPC55XX_FMPLL_REF_CLOCK
	addi r5, r5, 1
	addi r6, r6, 4
	mullw r6, r6, r8
	sraw r6, r6, r7
	divw r3, r6, r5
#endif /* !FMPLL_HAS_ENHANCED_FMPLL */

	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