vserver 2.0 rc7
[linux-2.6.git] / arch / ppc / syslib / mpc52xx_setup.c
1 /*
2  * arch/ppc/syslib/mpc52xx_setup.c
3  *
4  * Common code for the boards based on Freescale MPC52xx embedded CPU.
5  *
6  * 
7  * Maintainer : Sylvain Munaut <tnt@246tNt.com>
8  *
9  * Support for other bootloaders than UBoot by Dale Farnsworth 
10  * <dfarnsworth@mvista.com>
11  * 
12  * Copyright (C) 2004 Sylvain Munaut <tnt@246tNt.com>
13  * Copyright (C) 2003 Montavista Software, Inc
14  * 
15  * This file is licensed under the terms of the GNU General Public License
16  * version 2. This program is licensed "as is" without any warranty of any
17  * kind, whether express or implied.
18  */
19
20 #include <linux/config.h>
21
22 #include <asm/io.h>
23 #include <asm/time.h>
24 #include <asm/mpc52xx.h>
25 #include <asm/mpc52xx_psc.h>
26 #include <asm/pgtable.h>
27 #include <asm/ppcboot.h>
28
29 extern bd_t __res;
30
31 static int core_mult[] = {              /* CPU Frequency multiplier, taken    */
32         0,  0,  0,  10, 20, 20, 25, 45, /* from the datasheet used to compute */
33         30, 55, 40, 50, 0,  60, 35, 0,  /* CPU frequency from XLB freq and    */
34         30, 25, 65, 10, 70, 20, 75, 45, /* external jumper config             */
35         0,  55, 40, 50, 80, 60, 35, 0
36 };
37
38 void
39 mpc52xx_restart(char *cmd)
40 {
41         struct mpc52xx_gpt __iomem *gpt0 = MPC52xx_VA(MPC52xx_GPTx_OFFSET(0));
42
43         local_irq_disable();
44
45         /* Turn on the watchdog and wait for it to expire. It effectively
46           does a reset */
47         out_be32(&gpt0->count, 0x000000ff);
48         out_be32(&gpt0->mode, 0x00009004);
49
50         while (1);
51 }
52
53 void
54 mpc52xx_halt(void)
55 {
56         local_irq_disable();
57
58         while (1);
59 }
60
61 void
62 mpc52xx_power_off(void)
63 {
64         /* By default we don't have any way of shut down.
65            If a specific board wants to, it can set the power down
66            code to any hardware implementation dependent code */
67         mpc52xx_halt();
68 }
69
70
71 void __init
72 mpc52xx_set_bat(void)
73 {
74         /* Set BAT 2 to map the 0xf0000000 area */
75         /* This mapping is used during mpc52xx_progress,
76          * mpc52xx_find_end_of_memory, and UARTs/GPIO access for debug
77          */
78         mb();
79         mtspr(SPRN_DBAT2U, 0xf0001ffe);
80         mtspr(SPRN_DBAT2L, 0xf000002a);
81         mb();
82 }
83
84 void __init
85 mpc52xx_map_io(void)
86 {
87         /* Here we only map the MBAR */
88         io_block_mapping(
89                 MPC52xx_MBAR_VIRT, MPC52xx_MBAR, MPC52xx_MBAR_SIZE, _PAGE_IO);
90 }
91
92
93 #ifdef CONFIG_SERIAL_TEXT_DEBUG
94 #ifndef MPC52xx_PF_CONSOLE_PORT
95 #error "mpc52xx PSC for console not selected"
96 #endif
97
98 static void
99 mpc52xx_psc_putc(struct mpc52xx_psc __iomem *psc, unsigned char c)
100 {
101         while (!(in_be16(&psc->mpc52xx_psc_status) &
102                  MPC52xx_PSC_SR_TXRDY));
103         out_8(&psc->mpc52xx_psc_buffer_8, c);
104 }
105
106 void
107 mpc52xx_progress(char *s, unsigned short hex)
108 {
109         char c;
110         struct mpc52xx_psc __iomem *psc;
111
112         psc = MPC52xx_VA(MPC52xx_PSCx_OFFSET(MPC52xx_PF_CONSOLE_PORT));
113
114         while ((c = *s++) != 0) {
115                 if (c == '\n')
116                         mpc52xx_psc_putc(psc, '\r');
117                 mpc52xx_psc_putc(psc, c);
118         }
119
120         mpc52xx_psc_putc(psc, '\r');
121         mpc52xx_psc_putc(psc, '\n');
122 }
123
124 #endif  /* CONFIG_SERIAL_TEXT_DEBUG */
125
126
127 unsigned long __init
128 mpc52xx_find_end_of_memory(void)
129 {
130         u32 ramsize = __res.bi_memsize;
131
132         /*
133          * if bootloader passed a memsize, just use it
134          * else get size from sdram config registers
135          */
136         if (ramsize == 0) {
137                 struct mpc52xx_mmap_ctl __iomem *mmap_ctl;
138                 u32 sdram_config_0, sdram_config_1;
139
140                 /* Temp BAT2 mapping active when this is called ! */
141                 mmap_ctl = MPC52xx_VA(MPC52xx_MMAP_CTL_OFFSET);
142
143                 sdram_config_0 = in_be32(&mmap_ctl->sdram0);
144                 sdram_config_1 = in_be32(&mmap_ctl->sdram1);
145
146                 if ((sdram_config_0 & 0x1f) >= 0x13)
147                         ramsize = 1 << ((sdram_config_0 & 0xf) + 17);
148
149                 if (((sdram_config_1 & 0x1f) >= 0x13) &&
150                                 ((sdram_config_1 & 0xfff00000) == ramsize))
151                         ramsize += 1 << ((sdram_config_1 & 0xf) + 17);
152         }
153
154         return ramsize;
155 }
156
157 void __init
158 mpc52xx_calibrate_decr(void)
159 {
160         int current_time, previous_time;
161         int tbl_start, tbl_end;
162         unsigned int xlbfreq, cpufreq, ipbfreq, pcifreq, divisor;
163
164         xlbfreq = __res.bi_busfreq;
165         /* if bootloader didn't pass bus frequencies, calculate them */
166         if (xlbfreq == 0) {
167                 /* Get RTC & Clock manager modules */
168                 struct mpc52xx_rtc __iomem *rtc;
169                 struct mpc52xx_cdm __iomem *cdm;
170
171                 rtc = ioremap(MPC52xx_PA(MPC52xx_RTC_OFFSET), MPC52xx_RTC_SIZE);
172                 cdm = ioremap(MPC52xx_PA(MPC52xx_CDM_OFFSET), MPC52xx_CDM_SIZE);
173
174                 if ((rtc==NULL) || (cdm==NULL))
175                         panic("Can't ioremap RTC/CDM while computing bus freq");
176
177                 /* Count bus clock during 1/64 sec */
178                 out_be32(&rtc->dividers, 0x8f1f0000);   /* Set RTC 64x faster */
179                 previous_time = in_be32(&rtc->time);
180                 while ((current_time = in_be32(&rtc->time)) == previous_time) ;
181                 tbl_start = get_tbl();
182                 previous_time = current_time;
183                 while ((current_time = in_be32(&rtc->time)) == previous_time) ;
184                 tbl_end = get_tbl();
185                 out_be32(&rtc->dividers, 0xffff0000);   /* Restore RTC */
186
187                 /* Compute all frequency from that & CDM settings */
188                 xlbfreq = (tbl_end - tbl_start) << 8;
189                 cpufreq = (xlbfreq * core_mult[in_be32(&cdm->rstcfg)&0x1f])/10;
190                 ipbfreq = (in_8(&cdm->ipb_clk_sel) & 1) ?
191                                         xlbfreq / 2 : xlbfreq;
192                 switch (in_8(&cdm->pci_clk_sel) & 3) {
193                 case 0:
194                         pcifreq = ipbfreq;
195                         break;
196                 case 1:
197                         pcifreq = ipbfreq / 2;
198                         break;
199                 default:
200                         pcifreq = xlbfreq / 4;
201                         break;
202                 }
203                 __res.bi_busfreq = xlbfreq;
204                 __res.bi_intfreq = cpufreq;
205                 __res.bi_ipbfreq = ipbfreq;
206                 __res.bi_pcifreq = pcifreq;
207
208                 /* Release mapping */
209                 iounmap(rtc);
210                 iounmap(cdm);
211         }
212
213         divisor = 4;
214
215         tb_ticks_per_jiffy = xlbfreq / HZ / divisor;
216         tb_to_us = mulhwu_scale_factor(xlbfreq / divisor, 1000000);
217 }
218
219 int mpc52xx_match_psc_function(int psc_idx, const char *func)
220 {
221         struct mpc52xx_psc_func *cf = mpc52xx_psc_functions;
222
223         while ((cf->id != -1) && (cf->func != NULL)) {
224                 if ((cf->id == psc_idx) && !strcmp(cf->func,func))
225                         return 1;
226                 cf++;
227         }
228
229         return 0;
230 }