Merge branch 'master'
[pandora-kernel.git] / arch / ppc / syslib / mpc52xx_setup.c
1 /*
2  * Common code for the boards based on Freescale MPC52xx embedded CPU.
3  *
4  * 
5  * Maintainer : Sylvain Munaut <tnt@246tNt.com>
6  *
7  * Support for other bootloaders than UBoot by Dale Farnsworth 
8  * <dfarnsworth@mvista.com>
9  * 
10  * Copyright (C) 2004 Sylvain Munaut <tnt@246tNt.com>
11  * Copyright (C) 2003 Montavista Software, Inc
12  * 
13  * This file is licensed under the terms of the GNU General Public License
14  * version 2. This program is licensed "as is" without any warranty of any
15  * kind, whether express or implied.
16  */
17
18 #include <linux/config.h>
19
20 #include <asm/io.h>
21 #include <asm/time.h>
22 #include <asm/mpc52xx.h>
23 #include <asm/mpc52xx_psc.h>
24 #include <asm/pgtable.h>
25 #include <asm/ppcboot.h>
26
27 extern bd_t __res;
28
29 static int core_mult[] = {              /* CPU Frequency multiplier, taken    */
30         0,  0,  0,  10, 20, 20, 25, 45, /* from the datasheet used to compute */
31         30, 55, 40, 50, 0,  60, 35, 0,  /* CPU frequency from XLB freq and    */
32         30, 25, 65, 10, 70, 20, 75, 45, /* external jumper config             */
33         0,  55, 40, 50, 80, 60, 35, 0
34 };
35
36 void
37 mpc52xx_restart(char *cmd)
38 {
39         struct mpc52xx_gpt __iomem *gpt0 = MPC52xx_VA(MPC52xx_GPTx_OFFSET(0));
40
41         local_irq_disable();
42
43         /* Turn on the watchdog and wait for it to expire. It effectively
44           does a reset */
45         out_be32(&gpt0->count, 0x000000ff);
46         out_be32(&gpt0->mode, 0x00009004);
47
48         while (1);
49 }
50
51 void
52 mpc52xx_halt(void)
53 {
54         local_irq_disable();
55
56         while (1);
57 }
58
59 void
60 mpc52xx_power_off(void)
61 {
62         /* By default we don't have any way of shut down.
63            If a specific board wants to, it can set the power down
64            code to any hardware implementation dependent code */
65         mpc52xx_halt();
66 }
67
68
69 void __init
70 mpc52xx_set_bat(void)
71 {
72         /* Set BAT 2 to map the 0xf0000000 area */
73         /* This mapping is used during mpc52xx_progress,
74          * mpc52xx_find_end_of_memory, and UARTs/GPIO access for debug
75          */
76         mb();
77         mtspr(SPRN_DBAT2U, 0xf0001ffe);
78         mtspr(SPRN_DBAT2L, 0xf000002a);
79         mb();
80 }
81
82 void __init
83 mpc52xx_map_io(void)
84 {
85         /* Here we map the MBAR and the whole upper zone. MBAR is only
86            64k but we can't map only 64k with BATs. Map the whole
87            0xf0000000 range is ok and helps eventual lpb devices placed there */
88         io_block_mapping(
89                 MPC52xx_MBAR_VIRT, MPC52xx_MBAR, 0x10000000, _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 }