summaryrefslogtreecommitdiff
path: root/arch/arm/mach-mx28/emi.S
blob: ec25b4e942e5c1f3b390ca466d35e15003dd15e8 (plain)
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
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
/*
 * Freescale MX28 low level RAM frequency manipulation
 *
 * Author: Vitaly Wool <vital@embeddedalley.com>
 *
 * Copyright 2008-2010 Freescale Semiconductor, Inc.
 * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

#include <linux/linkage.h>
#include <asm/assembler.h>
#include <asm/system.h>
#include <asm/pgtable-hwdef.h>

#include <mach/hardware.h>
#include <mach/regs-power.h>
#include "regs-clkctrl.h"
#include "regs-dram.h"
#include "regs-digctl.h"

#include "emi_settings.h"

.global cpu_arm926_switch_mm

.align 8
ENTRY(mxs_ram_freq_scale)
	stmfd	sp!, {r1 - r10, lr}
	ldr	r5, [r0, #SCALING_DATA_NEW_FREQ_OFFSET]
	ldr	r6, [r0, #SCALING_DATA_CUR_FREQ_OFFSET]
	ldr	r7, [r0, #SCALING_DATA_EMI_DIV_OFFSET]
	mov	r7, r7,	LSL #BP_CLKCTRL_EMI_DIV_EMI
	ldr	r8, [r0, #SCALING_DATA_FRAC_DIV_OFFSET]
	mov	r8, r8,	LSL #BP_CLKCTRL_FRAC0_EMIFRAC

	@copy memory setting to iram
	mov	r2, #MX28_DRAMCTRLREGNUM
	adr	r0, __mx28_emisetting
1:	ldr	r3, [r1]
	str 	r3, [r0]
	add 	r0, r0, #4
	add 	r1, r1, #4
	subs 	r2, r2, #1
	bne 1b

	@set temp static to iram.
	adr	r9, __mxs_temp_stack

	@ clean cache
	ldr	r1, __mxs_flush_cache_addr
	mov	lr, pc
	mov	pc, r1

	mov r2, #MX28_SOC_IO_ADDRESS(CLKCTRL_PHYS_ADDR)&0xFF
	orr r2, r2,  #MX28_SOC_IO_ADDRESS(CLKCTRL_PHYS_ADDR)&0xFF00
	orr r2, r2,  #MX28_SOC_IO_ADDRESS(CLKCTRL_PHYS_ADDR)&0xFF0000
	orr r2, r2,  #MX28_SOC_IO_ADDRESS(CLKCTRL_PHYS_ADDR)&0xFF000000

	mov r0, r2
	bl lock_vector_tlb

	mov r0, #MX28_SOC_IO_ADDRESS(DRAM_PHYS_ADDR)&0xFF
	orr r0, r0, #MX28_SOC_IO_ADDRESS(DRAM_PHYS_ADDR)&0xFF00
	orr r0, r0, #MX28_SOC_IO_ADDRESS(DRAM_PHYS_ADDR)&0xFF0000
	orr r0, r0, #MX28_SOC_IO_ADDRESS(DRAM_PHYS_ADDR)&0xFF000000

	@ Make sure emi not busy
2:
	ldr r1, [r0, #HW_DRAM_CTL08]
	tst r1, #BM_DRAM_CTL08_CONTROLLER_BUSY
	bne 2b

	@ put DRAM into self refresh
	ldr r1, [r0, #HW_DRAM_CTL17]
	orr r1, r1, #BM_DRAM_CTL17_SREFRESH
	str	r1,  [r0, #HW_DRAM_CTL17]
3:
	ldr r1, [r0, #HW_DRAM_CTL172]
	tst r1, #BM_DRAM_CTL172_CKE_STATUS
	beq 3b

	ldr r1, [r0, #HW_DRAM_CTL58]
	orr r1, #BF_DRAM_CTL58_INT_MASK(0x100)
	str r1, [r0, #HW_DRAM_CTL58]

	@stop emi controller
	ldr r1, [r0, #HW_DRAM_CTL16]
	bic r1, r1, #BM_DRAM_CTL16_START
	str r1, [r0, #HW_DRAM_CTL16]

	@clear lock status HW_DRAM_CTL164_CLR(BF_DRAM_CTL164_INT_ACK(0x3ff));
	ldr r1, [r0, #HW_DRAM_CTL164]
	bic r1, r1, #BF_DRAM_CTL164_INT_ACK(0xff)
	bic r1, r1, #BF_DRAM_CTL164_INT_ACK(0x300)
	str r1, [r0, #HW_DRAM_CTL164]

	ldr r1, [r2, #HW_CLKCTRL_FRAC0]
	and r1, #BM_CLKCTRL_FRAC0_EMIFRAC
	ldr r3, [r2, #HW_CLKCTRL_EMI]
	and r3, #BM_CLKCTRL_EMI_DIV_EMI

/*
 *	The fractional divider and integer divider must be written in such
 *	an order to guarantee that when going from a lower frequency to a
 *	higher frequency that any intermediate frequencies do not exceed
 *	the final frequency. For this reason, we must make sure to check
 *	the current divider values with the new divider values and write
 *	them in the correct order.
 */

	ldr r9, [r2, #HW_CLKCTRL_FRAC0]
	bic r9, #BM_CLKCTRL_FRAC0_EMIFRAC
	orr r9, r8

	ldr r10, [r2, #HW_CLKCTRL_EMI]
	bic r10, #BM_CLKCTRL_EMI_DIV_EMI
	orr r10, r7

	cmp r8, r1
	strgt r9,   [r2, #HW_CLKCTRL_FRAC0]
	cmp r7, r3
	strgt r10,  [r2, #HW_CLKCTRL_EMI]

	cmp r8, r1
	strlt r9,   [r2, #HW_CLKCTRL_FRAC0]
	cmp r7, r3
	strlt r10,  [r2, #HW_CLKCTRL_EMI]

	@copy memory setting to iram
	mov     r3, r0
	adr     r4, __mx28_emisetting
	mov 	r6, #MX28_DRAMCTRLREGNUM
8:	ldr     r5, [r4]
	str     r5, [r3]
	add     r3, r3, #4
	add     r4, r4, #4
	subs    r6, r6, #1
	bne 8b

7:      ldr     r1, [r2, #HW_CLKCTRL_EMI]
        tst     r1, #BM_CLKCTRL_EMI_BUSY_REF_EMI
	bne     7b

	@Restart memory controller
	ldr r1, [r0, #HW_DRAM_CTL16]
	orr r1, #BM_DRAM_CTL16_START
	str	r1, [r0, #HW_DRAM_CTL16]

	/*Wait DLL is locked*/
9:
	ldr r1, [r0, #HW_DRAM_CTL21]
	tst r1, #BM_DRAM_CTL21_DLLLOCKREG
	beq 9b


    	@11. Exit Memory self-refresh
	ldr r1, [r0, #HW_DRAM_CTL17]
	bic r1, r1, #BM_DRAM_CTL17_SREFRESH
	str r1, [r0, #HW_DRAM_CTL17]

	@Wait Memory device exit into self-refresh
10:
	ldr r1, [r0, #HW_DRAM_CTL172]
	tst r1, #BM_DRAM_CTL172_CKE_STATUS
	bne 10b

	mov	r2, #MX28_SOC_IO_ADDRESS(DIGCTL_PHYS_ADDR)&0xFF
	orr	r2, r2, #MX28_SOC_IO_ADDRESS(DIGCTL_PHYS_ADDR)&0xFF00
	orr	r2, r2, #MX28_SOC_IO_ADDRESS(DIGCTL_PHYS_ADDR)&0xFF0000
	orr	r2, r2, #MX28_SOC_IO_ADDRESS(DIGCTL_PHYS_ADDR)&0xFF000000

	ldr 	r0, [r2, #HW_DIGCTL_MICROSECONDS];
	add	r0, #100
11:	ldr	r1, [r2, #HW_DIGCTL_MICROSECONDS];
	cmp	r1, r0
	blt	11b

@ restore regs and return
	ldmfd   sp!, {r1 - r10, lr}
	mov	pc, lr

	.space	0x100
__mxs_temp_stack:
	.word	0
__mx28_emisetting:
	.space MX28_DRAMCTRLREGNUM*4

lock_vector_tlb:
        mov r1, r0 @ set r1 to the value of the address to be locked down
        mcr p15,0,r1,c8,c7,1    @ invalidate TLB single entry to ensure that
                                @ LockAddr is not already in the TLB
        mrc p15,0,r0,c10,c0,0   @ read the lockdown register
        orr r0,r0,#1            @ set the preserve bit
        mcr p15,0,r0,c10,c0,0   @ write to the lockdown register
        ldr r1,[r1]             @ TLB will miss, and entry will be loaded
        mrc p15,0,r0,c10,c0,0   @ read the lockdown register (victim will have
                                @ incremented)
        bic r0,r0,#1            @ clear preserve bit
        mcr p15,0,r0,c10,c0,0   @ write to the lockdown registerADR r1,LockAddr
        mov pc,lr

__mxs_flush_cache_addr:
	.word	arm926_flush_kern_cache_all

ENTRY(mxs_ram_funcs_sz)
	.word	. - mxs_ram_freq_scale
ENTRY(mxs_ram_freq_scale_end)