Merge branch 'master' of git://www.denx.de/git/u-boot-mpc85xx
[platform/kernel/u-boot.git] / cpu / ppc4xx / dcr.S
1 /*
2  * (C) Copyright 2001
3  * Erik Theisen, Wave 7 Optics, etheisen@mindspring.com
4  *
5  * See file CREDITS for list of people who contributed to this
6  * project.
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License as
10  * published by the Free Software Foundation; either version 2 of
11  * the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
21  * MA 02111-1307 USA
22  */
23 #include <config.h>
24
25 #if defined(CONFIG_4xx) && defined(CONFIG_CMD_SETGETDCR)
26
27 #include <ppc4xx.h>
28
29 #define _LINUX_CONFIG_H 1       /* avoid reading Linux autoconf.h file  */
30
31 #include <ppc_asm.tmpl>
32 #include <ppc_defs.h>
33
34 #include <asm/cache.h>
35 #include <asm/mmu.h>
36
37 #define _ASMLANGUAGE
38
39 /*****************************************************************************
40  *
41  *  XXX - DANGER
42  *        These routines make use of self modifying code.  DO NOT CALL THEM
43  *        UNTIL THEY ARE RELOCATED TO RAM.  Additionally, I do not
44  *        recommend them for use in anything other than an interactive
45  *        debugging environment.  This is mainly due to performance reasons.
46  *
47  ****************************************************************************/
48
49 /*
50  * static void _create_MFDCR(unsigned short dcrn)
51  *
52  * Builds a 'mfdcr' instruction for get_dcr
53  * function.
54  */
55                 .section ".text"
56                 .align 2
57                 .type    _create_MFDCR,@function
58 _create_MFDCR:
59                 /*
60                  * Build up a 'mfdcr' instruction formatted as follows:
61                  *
62                  *  OPCD |   RT   |    DCRF      |     XO       | CR |
63                  * ---------------|--------------|--------------|----|
64                  * 0   5 | 6   10 | 11        20 | 21        30 | 31 |
65                  *       |        |    DCRN      |              |    |
66                  *   31  |  %r3   | (5..9|0..4)  |      323     |  0 |
67                  *
68                  * Where:
69                  *      OPCD = opcode - 31
70                  *      RT   = destination register - %r3 return register
71                  *      DCRF = DCRN # with upper and lower halves swapped
72                  *      XO   = extended opcode - 323
73                  *      CR   = CR[CR0] NOT undefined - 0
74                  */
75                 rlwinm  r0, r3, 27, 27, 31      /* OPCD = 31 */
76                 rlwinm  r3, r3, 5, 22, 26
77                 or      r3, r3, r0
78                 slwi    r3, r3, 10
79                 oris    r3, r3, 0x3e30          /* RT = %r3 */
80                 ori     r3, r3, 323             /* XO = 323 */
81                 slwi    r3, r3, 1               /* CR = 0 */
82
83                 mflr    r4
84                 stw     r3, 0(r4)               /* Store instr in get_dcr() */
85                 dcbst   r0, r4                  /* Make sure val is written out */
86                 sync                            /* Wait for write to complete */
87                 icbi    r0, r4                  /* Make sure old instr is dumped */
88                 isync                           /* Wait for icbi to complete */
89
90                 blr
91 .Lfe1:          .size    _create_MFDCR,.Lfe1-_create_MFDCR
92 /* end _create_MFDCR() */
93
94 /*
95  * static void _create_MTDCR(unsigned short dcrn, unsigned long value)
96  *
97  * Builds a 'mtdcr' instruction for set_dcr
98  * function.
99  */
100                 .section ".text"
101                 .align 2
102                 .type    _create_MTDCR,@function
103 _create_MTDCR:
104                 /*
105                  * Build up a 'mtdcr' instruction formatted as follows:
106                  *
107                  *  OPCD |   RS   |    DCRF      |     XO       | CR |
108                  * ---------------|--------------|--------------|----|
109                  * 0   5 | 6   10 | 11        20 | 21        30 | 31 |
110                  *       |        |    DCRN      |              |    |
111                  *   31  |  %r3   | (5..9|0..4)  |      451     |  0 |
112                  *
113                  * Where:
114                  *      OPCD = opcode - 31
115                  *      RS   = source register - %r4
116                  *      DCRF = dest. DCRN # with upper and lower halves swapped
117                  *      XO   = extended opcode - 451
118                  *      CR   = CR[CR0] NOT undefined - 0
119                  */
120                 rlwinm  r0, r3, 27, 27, 31      /* OPCD = 31 */
121                 rlwinm  r3, r3, 5, 22, 26
122                 or      r3, r3, r0
123                 slwi    r3, r3, 10
124                 oris    r3, r3, 0x3e40          /* RS = %r4 */
125                 ori     r3, r3, 451             /* XO = 451 */
126                 slwi    r3, r3, 1               /* CR = 0 */
127
128                 mflr    r5
129                 stw     r3, 0(r5)               /* Store instr in set_dcr() */
130                 dcbst   r0, r5                  /* Make sure val is written out */
131                 sync                            /* Wait for write to complete */
132                 icbi    r0, r5                  /* Make sure old instr is dumped */
133                 isync                           /* Wait for icbi to complete */
134
135                 blr
136 .Lfe2:          .size    _create_MTDCR,.Lfe2-_create_MTDCR
137 /* end _create_MTDCR() */
138
139
140 /*
141  * unsigned long get_dcr(unsigned short dcrn)
142  *
143  * Return a given DCR's value.
144  */
145                 /* */
146                 /* XXX - This is self modifying code, hence */
147                 /* it is in the data section. */
148                 /* */
149                 .section ".data"
150                 .align  2
151                 .globl  get_dcr
152                 .type   get_dcr,@function
153 get_dcr:
154                 mflr    r0                      /* Get link register */
155                 stwu    r1, -32(r1)             /* Save back chain and move SP */
156                 stw     r0, +36(r1)             /* Save link register */
157
158                 bl      _create_MFDCR           /* Build following instruction */
159                 /* XXX - we build this instuction up on the fly. */
160                 .long   0                       /* Get DCR's value */
161
162                 lwz     r0, +36(r1)             /* Get saved link register */
163                 mtlr    r0                      /* Restore link register */
164                 addi    r1, r1, +32             /* Remove frame from stack */
165                 blr                             /* Return to calling function */
166 .Lfe3:          .size   get_dcr,.Lfe3-get_dcr
167 /* end get_dcr() */
168
169
170 /*
171  * unsigned void set_dcr(unsigned short dcrn, unsigned long value)
172  *
173  * Return a given DCR's value.
174  */
175                 /*
176                  * XXX - This is self modifying code, hence
177                  * it is in the data section.
178                  */
179                 .section ".data"
180                 .align  2
181                 .globl  set_dcr
182                 .type   set_dcr,@function
183 set_dcr:
184                 mflr    r0                      /* Get link register */
185                 stwu    r1, -32(r1)             /* Save back chain and move SP */
186                 stw     r0, +36(r1)             /* Save link register */
187
188                 bl      _create_MTDCR           /* Build following instruction */
189                 /* XXX - we build this instuction up on the fly. */
190                 .long   0                       /* Set DCR's value */
191
192                 lwz     r0, +36(r1)             /* Get saved link register */
193                 mtlr    r0                      /* Restore link register */
194                 addi    r1, r1, +32             /* Remove frame from stack */
195                 blr                             /* Return to calling function */
196 .Lfe4:          .size   set_dcr,.Lfe4-set_dcr
197 /* end set_dcr() */
198 #endif