Merge branch 'drm-forlinus' of git://git.kernel.org/pub/scm/linux/kernel/git/airlied...
[pandora-kernel.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 map the MBAR and the whole upper zone. MBAR is only
88            64k but we can't map only 64k with BATs. Map the whole
89            0xf0000000 range is ok and helps eventual lpb devices placed there */
90         io_block_mapping(
91                 MPC52xx_MBAR_VIRT, MPC52xx_MBAR, 0x10000000, _PAGE_IO);
92 }
93
94
95 #ifdef CONFIG_SERIAL_TEXT_DEBUG
96 #ifndef MPC52xx_PF_CONSOLE_PORT
97 #error "mpc52xx PSC for console not selected"
98 #endif
99
100 static void
101 mpc52xx_psc_putc(struct mpc52xx_psc __iomem *psc, unsigned char c)
102 {
103         while (!(in_be16(&psc->mpc52xx_psc_status) &
104                  MPC52xx_PSC_SR_TXRDY));
105         out_8(&psc->mpc52xx_psc_buffer_8, c);
106 }
107
108 void
109 mpc52xx_progress(char *s, unsigned short hex)
110 {
111         char c;
112         struct mpc52xx_psc __iomem *psc;
113
114         psc = MPC52xx_VA(MPC52xx_PSCx_OFFSET(MPC52xx_PF_CONSOLE_PORT));
115
116         while ((c = *s++) != 0) {
117                 if (c == '\n')
118                         mpc52xx_psc_putc(psc, '\r');
119                 mpc52xx_psc_putc(psc, c);
120         }
121
122         mpc52xx_psc_putc(psc, '\r');
123         mpc52xx_psc_putc(psc, '\n');
124 }
125
126 #endif  /* CONFIG_SERIAL_TEXT_DEBUG */
127
128
129 unsigned long __init
130 mpc52xx_find_end_of_memory(void)
131 {
132         u32 ramsize = __res.bi_memsize;
133
134         /*
135          * if bootloader passed a memsize, just use it
136          * else get size from sdram config registers
137          */
138         if (ramsize == 0) {
139                 struct mpc52xx_mmap_ctl __iomem *mmap_ctl;
140                 u32 sdram_config_0, sdram_config_1;
141
142                 /* Temp BAT2 mapping active when this is called ! */
143                 mmap_ctl = MPC52xx_VA(MPC52xx_MMAP_CTL_OFFSET);
144
145                 sdram_config_0 = in_be32(&mmap_ctl->sdram0);
146                 sdram_config_1 = in_be32(&mmap_ctl->sdram1);
147
148                 if ((sdram_config_0 & 0x1f) >= 0x13)
149                         ramsize = 1 << ((sdram_config_0 & 0xf) + 17);
150
151                 if (((sdram_config_1 & 0x1f) >= 0x13) &&
152                                 ((sdram_config_1 & 0xfff00000) == ramsize))
153                         ramsize += 1 << ((sdram_config_1 & 0xf) + 17);
154         }
155
156         return ramsize;
157 }
158
159 void __init
160 mpc52xx_calibrate_decr(void)
161 {
162         int current_time, previous_time;
163         int tbl_start, tbl_end;
164         unsigned int xlbfreq, cpufreq, ipbfreq, pcifreq, divisor;
165
166         xlbfreq = __res.bi_busfreq;
167         /* if bootloader didn't pass bus frequencies, calculate them */
168         if (xlbfreq == 0) {
169                 /* Get RTC & Clock manager modules */
170                 struct mpc52xx_rtc __iomem *rtc;
171                 struct mpc52xx_cdm __iomem *cdm;
172
173                 rtc = ioremap(MPC52xx_PA(MPC52xx_RTC_OFFSET), MPC52xx_RTC_SIZE);
174                 cdm = ioremap(MPC52xx_PA(MPC52xx_CDM_OFFSET), MPC52xx_CDM_SIZE);
175
176                 if ((rtc==NULL) || (cdm==NULL))
177                         panic("Can't ioremap RTC/CDM while computing bus freq");
178
179                 /* Count bus clock during 1/64 sec */
180                 out_be32(&rtc->dividers, 0x8f1f0000);   /* Set RTC 64x faster */
181                 previous_time = in_be32(&rtc->time);
182                 while ((current_time = in_be32(&rtc->time)) == previous_time) ;
183                 tbl_start = get_tbl();
184                 previous_time = current_time;
185                 while ((current_time = in_be32(&rtc->time)) == previous_time) ;
186                 tbl_end = get_tbl();
187                 out_be32(&rtc->dividers, 0xffff0000);   /* Restore RTC */
188
189                 /* Compute all frequency from that & CDM settings */
190                 xlbfreq = (tbl_end - tbl_start) << 8;
191                 cpufreq = (xlbfreq * core_mult[in_be32(&cdm->rstcfg)&0x1f])/10;
192                 ipbfreq = (in_8(&cdm->ipb_clk_sel) & 1) ?
193                                         xlbfreq / 2 : xlbfreq;
194                 switch (in_8(&cdm->pci_clk_sel) & 3) {
195                 case 0:
196                         pcifreq = ipbfreq;
197                         break;
198                 case 1:
199                         pcifreq = ipbfreq / 2;
200                         break;
201                 default:
202                         pcifreq = xlbfreq / 4;
203                         break;
204                 }
205                 __res.bi_busfreq = xlbfreq;
206                 __res.bi_intfreq = cpufreq;
207                 __res.bi_ipbfreq = ipbfreq;
208                 __res.bi_pcifreq = pcifreq;
209
210                 /* Release mapping */
211                 iounmap(rtc);
212                 iounmap(cdm);
213         }
214
215         divisor = 4;
216
217         tb_ticks_per_jiffy = xlbfreq / HZ / divisor;
218         tb_to_us = mulhwu_scale_factor(xlbfreq / divisor, 1000000);
219 }
220
221 int mpc52xx_match_psc_function(int psc_idx, const char *func)
222 {
223         struct mpc52xx_psc_func *cf = mpc52xx_psc_functions;
224
225         while ((cf->id != -1) && (cf->func != NULL)) {
226                 if ((cf->id == psc_idx) && !strcmp(cf->func,func))
227                         return 1;
228                 cf++;
229         }
230
231         return 0;
232 }