vserver 1.9.5.x5
[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/ocp.h>
27 #include <asm/pgtable.h>
28 #include <asm/ppcboot.h>
29
30 extern bd_t __res;
31
32 static int core_mult[] = {              /* CPU Frequency multiplier, taken    */
33         0,  0,  0,  10, 20, 20, 25, 45, /* from the datasheet used to compute */
34         30, 55, 40, 50, 0,  60, 35, 0,  /* CPU frequency from XLB freq and    */
35         30, 25, 65, 10, 70, 20, 75, 45, /* external jumper config             */
36         0,  55, 40, 50, 80, 60, 35, 0
37 };
38
39 void
40 mpc52xx_restart(char *cmd)
41 {
42         struct mpc52xx_gpt* gpt0 = (struct mpc52xx_gpt*) MPC52xx_GPTx(0);
43
44         local_irq_disable();
45
46         /* Turn on the watchdog and wait for it to expire. It effectively
47           does a reset */
48         if (gpt0 != NULL) {
49                 out_be32(&gpt0->count, 0x000000ff);
50                 out_be32(&gpt0->mode, 0x00009004);
51         } else
52                 printk(KERN_ERR "mpc52xx_restart: Unable to ioremap GPT0 registers, -> looping ...");
53
54         while (1);
55 }
56
57 void
58 mpc52xx_halt(void)
59 {
60         local_irq_disable();
61
62         while (1);
63 }
64
65 void
66 mpc52xx_power_off(void)
67 {
68         /* By default we don't have any way of shut down.
69            If a specific board wants to, it can set the power down
70            code to any hardware implementation dependent code */
71         mpc52xx_halt();
72 }
73
74
75 void __init
76 mpc52xx_set_bat(void)
77 {
78         /* Set BAT 2 to map the 0xf0000000 area */
79         /* This mapping is used during mpc52xx_progress,
80          * mpc52xx_find_end_of_memory, and UARTs/GPIO access for debug
81          */
82         mb();
83         mtspr(DBAT2U, 0xf0001ffe);
84         mtspr(DBAT2L, 0xf000002a);
85         mb();
86 }
87
88 void __init
89 mpc52xx_map_io(void)
90 {
91         /* Here we only map the MBAR */
92         io_block_mapping(
93                 MPC52xx_MBAR_VIRT, MPC52xx_MBAR, MPC52xx_MBAR_SIZE, _PAGE_IO);
94 }
95
96
97 #ifdef CONFIG_SERIAL_TEXT_DEBUG
98 #ifdef MPC52xx_PF_CONSOLE_PORT
99 #define MPC52xx_CONSOLE MPC52xx_PSCx(MPC52xx_PF_CONSOLE_PORT)
100 #else
101 #error "mpc52xx PSC for console not selected"
102 #endif
103
104 static void
105 mpc52xx_psc_putc(struct mpc52xx_psc * psc, unsigned char c)
106 {
107         while (!(in_be16(&psc->mpc52xx_psc_status) &
108                  MPC52xx_PSC_SR_TXRDY));
109         out_8(&psc->mpc52xx_psc_buffer_8, c);
110 }
111
112 void
113 mpc52xx_progress(char *s, unsigned short hex)
114 {
115         struct mpc52xx_psc *psc = (struct mpc52xx_psc *)MPC52xx_CONSOLE;
116         char c;
117
118         while ((c = *s++) != 0) {
119                 if (c == '\n')
120                         mpc52xx_psc_putc(psc, '\r');
121                 mpc52xx_psc_putc(psc, c);
122         }
123
124         mpc52xx_psc_putc(psc, '\r');
125         mpc52xx_psc_putc(psc, '\n');
126 }
127
128 #endif  /* CONFIG_SERIAL_TEXT_DEBUG */
129
130
131 unsigned long __init
132 mpc52xx_find_end_of_memory(void)
133 {
134         u32 ramsize = __res.bi_memsize;
135
136         /*
137          * if bootloader passed a memsize, just use it
138          * else get size from sdram config registers
139          */
140         if (ramsize == 0) {
141                 struct mpc52xx_mmap_ctl *mmap_ctl;
142                 u32 sdram_config_0, sdram_config_1;
143
144                 /* Temp BAT2 mapping active when this is called ! */
145                 mmap_ctl = (struct mpc52xx_mmap_ctl*) MPC52xx_MMAP_CTL;
146
147                 sdram_config_0 = in_be32(&mmap_ctl->sdram0);
148                 sdram_config_1 = in_be32(&mmap_ctl->sdram1);
149
150                 if ((sdram_config_0 & 0x1f) >= 0x13)
151                         ramsize = 1 << ((sdram_config_0 & 0xf) + 17);
152
153                 if (((sdram_config_1 & 0x1f) >= 0x13) &&
154                                 ((sdram_config_1 & 0xfff00000) == ramsize))
155                         ramsize += 1 << ((sdram_config_1 & 0xf) + 17);
156         }
157
158         return ramsize;
159 }
160
161 void __init
162 mpc52xx_calibrate_decr(void)
163 {
164         int current_time, previous_time;
165         int tbl_start, tbl_end;
166         unsigned int xlbfreq, cpufreq, ipbfreq, pcifreq, divisor;
167
168         xlbfreq = __res.bi_busfreq;
169         /* if bootloader didn't pass bus frequencies, calculate them */
170         if (xlbfreq == 0) {
171                 /* Get RTC & Clock manager modules */
172                 struct mpc52xx_rtc *rtc;
173                 struct mpc52xx_cdm *cdm;
174
175                 rtc = (struct mpc52xx_rtc*)
176                         ioremap(MPC52xx_RTC, sizeof(struct mpc52xx_rtc));
177                 cdm = (struct mpc52xx_cdm*)
178                         ioremap(MPC52xx_CDM, sizeof(struct mpc52xx_cdm));
179
180                 if ((rtc==NULL) || (cdm==NULL))
181                         panic("Can't ioremap RTC/CDM while computing bus freq");
182
183                 /* Count bus clock during 1/64 sec */
184                 out_be32(&rtc->dividers, 0x8f1f0000);   /* Set RTC 64x faster */
185                 previous_time = in_be32(&rtc->time);
186                 while ((current_time = in_be32(&rtc->time)) == previous_time) ;
187                 tbl_start = get_tbl();
188                 previous_time = current_time;
189                 while ((current_time = in_be32(&rtc->time)) == previous_time) ;
190                 tbl_end = get_tbl();
191                 out_be32(&rtc->dividers, 0xffff0000);   /* Restore RTC */
192
193                 /* Compute all frequency from that & CDM settings */
194                 xlbfreq = (tbl_end - tbl_start) << 8;
195                 cpufreq = (xlbfreq * core_mult[in_be32(&cdm->rstcfg)&0x1f])/10;
196                 ipbfreq = (in_8(&cdm->ipb_clk_sel) & 1) ?
197                                         xlbfreq / 2 : xlbfreq;
198                 switch (in_8(&cdm->pci_clk_sel) & 3) {
199                 case 0:
200                         pcifreq = ipbfreq;
201                         break;
202                 case 1:
203                         pcifreq = ipbfreq / 2;
204                         break;
205                 default:
206                         pcifreq = xlbfreq / 4;
207                         break;
208                 }
209                 __res.bi_busfreq = xlbfreq;
210                 __res.bi_intfreq = cpufreq;
211                 __res.bi_ipbfreq = ipbfreq;
212                 __res.bi_pcifreq = pcifreq;
213
214                 /* Release mapping */
215                 iounmap((void*)rtc);
216                 iounmap((void*)cdm);
217         }
218
219         divisor = 4;
220
221         tb_ticks_per_jiffy = xlbfreq / HZ / divisor;
222         tb_to_us = mulhwu_scale_factor(xlbfreq / divisor, 1000000);
223 }
224
225
226 void __init
227 mpc52xx_add_board_devices(struct ocp_def board_ocp[]) {
228         while (board_ocp->vendor != OCP_VENDOR_INVALID)
229                 if(ocp_add_one_device(board_ocp++))
230                         printk("mpc5200-ocp: Failed to add board device !\n");
231 }
232