summaryrefslogtreecommitdiff
path: root/arch/ppc/cpu/mpc8xx/plprcr_write.S
blob: e32567114218869edb0e742a6b8bcdab57349be0 (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
/*
 * (C) Copyright 2004
 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
 *
 * See file CREDITS for list of people who contributed to this
 * project.
 *
 * 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., 59 Temple Place, Suite 330, Boston,
 * MA 02111-1307 USA
 */

#include <mpc8xx.h>
#include <ppc_asm.tmpl>
#include <asm/cache.h>

#define CACHE_CMD_ENABLE	0x02000000
#define CACHE_CMD_DISABLE	0x04000000
#define CACHE_CMD_LOAD_LOCK	0x06000000
#define CACHE_CMD_UNLOCK_LINE	0x08000000
#define CACHE_CMD_UNLOCK_ALL	0x0A000000
#define CACHE_CMD_INVALIDATE	0x0C000000
#define SPEED_PLPRCR_WAIT_5CYC	150
#define _CACHE_ALIGN_SIZE	16


	.text
	.align 2
	.globl plprcr_write_866

/*
 * void plprcr_write_866 (long plprcr)
 * Write PLPRCR, including workaround for device errata SIU4 and SIU9.
 */

plprcr_write_866:
	mfspr	r10, LR		/* save the Link Register value */

	/* turn instruction cache on (no MMU required for instructions)
	 */
	lis	r4, CACHE_CMD_ENABLE@h
	ori	r4, r4, CACHE_CMD_ENABLE@l
	mtspr	IC_CST, r4
	isync

	/* clear IC_CST error bits
	 */
	mfspr	r4, IC_CST

	bl	plprcr_here

plprcr_here:
	mflr	r5

	/* calculate relocation offset
	 */
	lis	r4, plprcr_here@h
	ori	r4, r4, plprcr_here@l
	sub	r5, r5, r4

	/* calculate first address of this function
	 */
	lis	r6, plprcr_write_866@h
	ori	r6, r6, plprcr_write_866@l
	add	r6, r6, r5

	/* calculate end address of this function
	 */
	lis	r7, plprcr_end@h
	ori	r7, r7, plprcr_end@l
	add	r7, r7, r5

	/* load and lock code addresses
	 */
	mr	r5, r6

plprcr_loop:
	mtspr	IC_ADR, r5
	addi	r5, r5, _CACHE_ALIGN_SIZE	/* increment by one line */

	lis	r4, CACHE_CMD_LOAD_LOCK@h
	ori	r4, r4, CACHE_CMD_LOAD_LOCK@l
	mtspr	IC_CST, r4
	isync

	cmpw	r5, r7
	blt	plprcr_loop

	/* IC_CST error bits not evaluated
	 */

	/* switch PLPRCR
	 */
	mfspr	r4, IMMR		/* read IMMR */
	rlwinm	r4, r4, 0, 0, 15	/* only high 16 bits count */

	/* write sequence according to MPC866 Errata
	 */
	stw	r3, PLPRCR(r4)
	isync

	lis	r3, SPEED_PLPRCR_WAIT_5CYC@h
	ori	r3, r3, SPEED_PLPRCR_WAIT_5CYC@l

plprcr_wait:
	cmpwi	r3, 0
	beq	plprcr_wait_end
	nop
	subi	r3, r3, 1
	b	plprcr_wait

plprcr_wait_end:

	/* unlock instruction cache but leave it enabled
	 */
	lis	r4, CACHE_CMD_UNLOCK_ALL@h
	ori	r4, r4, CACHE_CMD_UNLOCK_ALL@l
	mtspr	IC_CST, r4
	isync

	mtspr	LR, r10		/* restore original Link Register value */
	blr

plprcr_end: