xref: /linux/arch/powerpc/platforms/8xx/m8xx_setup.c (revision df34403dcaacef541a67c955aebc37c51f53ca7c)
1*df34403dSVitaly Bordug /*
2*df34403dSVitaly Bordug  *  Copyright (C) 1995  Linus Torvalds
3*df34403dSVitaly Bordug  *  Adapted from 'alpha' version by Gary Thomas
4*df34403dSVitaly Bordug  *  Modified by Cort Dougan (cort@cs.nmt.edu)
5*df34403dSVitaly Bordug  *  Modified for MBX using prep/chrp/pmac functions by Dan (dmalek@jlc.net)
6*df34403dSVitaly Bordug  *  Further modified for generic 8xx by Dan.
7*df34403dSVitaly Bordug  */
8*df34403dSVitaly Bordug 
9*df34403dSVitaly Bordug /*
10*df34403dSVitaly Bordug  * bootup setup stuff..
11*df34403dSVitaly Bordug  */
12*df34403dSVitaly Bordug 
13*df34403dSVitaly Bordug #include <linux/errno.h>
14*df34403dSVitaly Bordug #include <linux/sched.h>
15*df34403dSVitaly Bordug #include <linux/kernel.h>
16*df34403dSVitaly Bordug #include <linux/mm.h>
17*df34403dSVitaly Bordug #include <linux/stddef.h>
18*df34403dSVitaly Bordug #include <linux/unistd.h>
19*df34403dSVitaly Bordug #include <linux/ptrace.h>
20*df34403dSVitaly Bordug #include <linux/slab.h>
21*df34403dSVitaly Bordug #include <linux/user.h>
22*df34403dSVitaly Bordug #include <linux/a.out.h>
23*df34403dSVitaly Bordug #include <linux/tty.h>
24*df34403dSVitaly Bordug #include <linux/major.h>
25*df34403dSVitaly Bordug #include <linux/interrupt.h>
26*df34403dSVitaly Bordug #include <linux/reboot.h>
27*df34403dSVitaly Bordug #include <linux/init.h>
28*df34403dSVitaly Bordug #include <linux/initrd.h>
29*df34403dSVitaly Bordug #include <linux/ioport.h>
30*df34403dSVitaly Bordug #include <linux/bootmem.h>
31*df34403dSVitaly Bordug #include <linux/seq_file.h>
32*df34403dSVitaly Bordug #include <linux/root_dev.h>
33*df34403dSVitaly Bordug #include <linux/time.h>
34*df34403dSVitaly Bordug #include <linux/rtc.h>
35*df34403dSVitaly Bordug 
36*df34403dSVitaly Bordug #include <asm/mmu.h>
37*df34403dSVitaly Bordug #include <asm/reg.h>
38*df34403dSVitaly Bordug #include <asm/residual.h>
39*df34403dSVitaly Bordug #include <asm/io.h>
40*df34403dSVitaly Bordug #include <asm/pgtable.h>
41*df34403dSVitaly Bordug #include <asm/mpc8xx.h>
42*df34403dSVitaly Bordug #include <asm/8xx_immap.h>
43*df34403dSVitaly Bordug #include <asm/machdep.h>
44*df34403dSVitaly Bordug #include <asm/bootinfo.h>
45*df34403dSVitaly Bordug #include <asm/time.h>
46*df34403dSVitaly Bordug #include <asm/prom.h>
47*df34403dSVitaly Bordug #include <asm/fs_pd.h>
48*df34403dSVitaly Bordug #include <mm/mmu_decl.h>
49*df34403dSVitaly Bordug 
50*df34403dSVitaly Bordug #include "sysdev/mpc8xx_pic.h"
51*df34403dSVitaly Bordug 
52*df34403dSVitaly Bordug void m8xx_calibrate_decr(void);
53*df34403dSVitaly Bordug extern void m8xx_wdt_handler_install(bd_t *bp);
54*df34403dSVitaly Bordug extern int cpm_pic_init(void);
55*df34403dSVitaly Bordug extern int cpm_get_irq(void);
56*df34403dSVitaly Bordug 
57*df34403dSVitaly Bordug /* A place holder for time base interrupts, if they are ever enabled. */
58*df34403dSVitaly Bordug irqreturn_t timebase_interrupt(int irq, void * dev)
59*df34403dSVitaly Bordug {
60*df34403dSVitaly Bordug 	printk ("timebase_interrupt()\n");
61*df34403dSVitaly Bordug 
62*df34403dSVitaly Bordug 	return IRQ_HANDLED;
63*df34403dSVitaly Bordug }
64*df34403dSVitaly Bordug 
65*df34403dSVitaly Bordug static struct irqaction tbint_irqaction = {
66*df34403dSVitaly Bordug 	.handler = timebase_interrupt,
67*df34403dSVitaly Bordug 	.mask = CPU_MASK_NONE,
68*df34403dSVitaly Bordug 	.name = "tbint",
69*df34403dSVitaly Bordug };
70*df34403dSVitaly Bordug 
71*df34403dSVitaly Bordug /* per-board overridable init_internal_rtc() function. */
72*df34403dSVitaly Bordug void __init __attribute__ ((weak))
73*df34403dSVitaly Bordug init_internal_rtc(void)
74*df34403dSVitaly Bordug {
75*df34403dSVitaly Bordug 	sit8xx_t *sys_tmr = (sit8xx_t *) immr_map(im_sit);
76*df34403dSVitaly Bordug 
77*df34403dSVitaly Bordug 	/* Disable the RTC one second and alarm interrupts. */
78*df34403dSVitaly Bordug 	clrbits16(&sys_tmr->sit_rtcsc, (RTCSC_SIE | RTCSC_ALE));
79*df34403dSVitaly Bordug 
80*df34403dSVitaly Bordug 	/* Enable the RTC */
81*df34403dSVitaly Bordug 	setbits16(&sys_tmr->sit_rtcsc, (RTCSC_RTF | RTCSC_RTE));
82*df34403dSVitaly Bordug 	immr_unmap(sys_tmr);
83*df34403dSVitaly Bordug }
84*df34403dSVitaly Bordug 
85*df34403dSVitaly Bordug static int __init get_freq(char *name, unsigned long *val)
86*df34403dSVitaly Bordug {
87*df34403dSVitaly Bordug         struct device_node *cpu;
88*df34403dSVitaly Bordug         unsigned int *fp;
89*df34403dSVitaly Bordug         int found = 0;
90*df34403dSVitaly Bordug 
91*df34403dSVitaly Bordug         /* The cpu node should have timebase and clock frequency properties */
92*df34403dSVitaly Bordug         cpu = of_find_node_by_type(NULL, "cpu");
93*df34403dSVitaly Bordug 
94*df34403dSVitaly Bordug         if (cpu) {
95*df34403dSVitaly Bordug                 fp = (unsigned int *)get_property(cpu, name, NULL);
96*df34403dSVitaly Bordug                 if (fp) {
97*df34403dSVitaly Bordug                         found = 1;
98*df34403dSVitaly Bordug                         *val = *fp++;
99*df34403dSVitaly Bordug                 }
100*df34403dSVitaly Bordug 
101*df34403dSVitaly Bordug                 of_node_put(cpu);
102*df34403dSVitaly Bordug         }
103*df34403dSVitaly Bordug 
104*df34403dSVitaly Bordug         return found;
105*df34403dSVitaly Bordug }
106*df34403dSVitaly Bordug 
107*df34403dSVitaly Bordug /* The decrementer counts at the system (internal) clock frequency divided by
108*df34403dSVitaly Bordug  * sixteen, or external oscillator divided by four.  We force the processor
109*df34403dSVitaly Bordug  * to use system clock divided by sixteen.
110*df34403dSVitaly Bordug  */
111*df34403dSVitaly Bordug void __init mpc8xx_calibrate_decr(void)
112*df34403dSVitaly Bordug {
113*df34403dSVitaly Bordug 	struct device_node *cpu;
114*df34403dSVitaly Bordug 	cark8xx_t *clk_r1;
115*df34403dSVitaly Bordug 	car8xx_t *clk_r2;
116*df34403dSVitaly Bordug 	sitk8xx_t *sys_tmr1;
117*df34403dSVitaly Bordug 	sit8xx_t *sys_tmr2;
118*df34403dSVitaly Bordug 	int irq, virq;
119*df34403dSVitaly Bordug 
120*df34403dSVitaly Bordug         clk_r1 = (cark8xx_t *) immr_map(im_clkrstk);
121*df34403dSVitaly Bordug 
122*df34403dSVitaly Bordug 	/* Unlock the SCCR. */
123*df34403dSVitaly Bordug 	out_be32(&clk_r1->cark_sccrk, ~KAPWR_KEY);
124*df34403dSVitaly Bordug 	out_be32(&clk_r1->cark_sccrk, KAPWR_KEY);
125*df34403dSVitaly Bordug 	immr_unmap(clk_r1);
126*df34403dSVitaly Bordug 
127*df34403dSVitaly Bordug 	/* Force all 8xx processors to use divide by 16 processor clock. */
128*df34403dSVitaly Bordug         clk_r2 = (car8xx_t *) immr_map(im_clkrst);
129*df34403dSVitaly Bordug 	setbits32(&clk_r2->car_sccr, 0x02000000);
130*df34403dSVitaly Bordug 	immr_unmap(clk_r2);
131*df34403dSVitaly Bordug 
132*df34403dSVitaly Bordug 	/* Processor frequency is MHz.
133*df34403dSVitaly Bordug 	 */
134*df34403dSVitaly Bordug         ppc_tb_freq = 50000000;
135*df34403dSVitaly Bordug         if (!get_freq("bus-frequency", &ppc_tb_freq)) {
136*df34403dSVitaly Bordug                 printk(KERN_ERR "WARNING: Estimating decrementer frequency "
137*df34403dSVitaly Bordug                                 "(not found)\n");
138*df34403dSVitaly Bordug         }
139*df34403dSVitaly Bordug         ppc_tb_freq /= 16;
140*df34403dSVitaly Bordug         ppc_proc_freq = 50000000;
141*df34403dSVitaly Bordug         if (!get_freq("clock-frequency", &ppc_proc_freq))
142*df34403dSVitaly Bordug                 printk(KERN_ERR "WARNING: Estimating processor frequency"
143*df34403dSVitaly Bordug                                 "(not found)\n");
144*df34403dSVitaly Bordug 
145*df34403dSVitaly Bordug         printk("Decrementer Frequency = 0x%lx\n", ppc_tb_freq);
146*df34403dSVitaly Bordug 
147*df34403dSVitaly Bordug 	/* Perform some more timer/timebase initialization.  This used
148*df34403dSVitaly Bordug 	 * to be done elsewhere, but other changes caused it to get
149*df34403dSVitaly Bordug 	 * called more than once....that is a bad thing.
150*df34403dSVitaly Bordug 	 *
151*df34403dSVitaly Bordug 	 * First, unlock all of the registers we are going to modify.
152*df34403dSVitaly Bordug 	 * To protect them from corruption during power down, registers
153*df34403dSVitaly Bordug 	 * that are maintained by keep alive power are "locked".  To
154*df34403dSVitaly Bordug 	 * modify these registers we have to write the key value to
155*df34403dSVitaly Bordug 	 * the key location associated with the register.
156*df34403dSVitaly Bordug 	 * Some boards power up with these unlocked, while others
157*df34403dSVitaly Bordug 	 * are locked.  Writing anything (including the unlock code?)
158*df34403dSVitaly Bordug 	 * to the unlocked registers will lock them again.  So, here
159*df34403dSVitaly Bordug 	 * we guarantee the registers are locked, then we unlock them
160*df34403dSVitaly Bordug 	 * for our use.
161*df34403dSVitaly Bordug 	 */
162*df34403dSVitaly Bordug         sys_tmr1 = (sitk8xx_t *) immr_map(im_sitk);
163*df34403dSVitaly Bordug 	out_be32(&sys_tmr1->sitk_tbscrk, ~KAPWR_KEY);
164*df34403dSVitaly Bordug 	out_be32(&sys_tmr1->sitk_rtcsck, ~KAPWR_KEY);
165*df34403dSVitaly Bordug 	out_be32(&sys_tmr1->sitk_tbk, ~KAPWR_KEY);
166*df34403dSVitaly Bordug 	out_be32(&sys_tmr1->sitk_tbscrk, KAPWR_KEY);
167*df34403dSVitaly Bordug 	out_be32(&sys_tmr1->sitk_rtcsck, KAPWR_KEY);
168*df34403dSVitaly Bordug 	out_be32(&sys_tmr1->sitk_tbk, KAPWR_KEY);
169*df34403dSVitaly Bordug 	immr_unmap(sys_tmr1);
170*df34403dSVitaly Bordug 
171*df34403dSVitaly Bordug 	init_internal_rtc();
172*df34403dSVitaly Bordug 
173*df34403dSVitaly Bordug 	/* Enabling the decrementer also enables the timebase interrupts
174*df34403dSVitaly Bordug 	 * (or from the other point of view, to get decrementer interrupts
175*df34403dSVitaly Bordug 	 * we have to enable the timebase).  The decrementer interrupt
176*df34403dSVitaly Bordug 	 * is wired into the vector table, nothing to do here for that.
177*df34403dSVitaly Bordug 	 */
178*df34403dSVitaly Bordug         cpu = of_find_node_by_type(NULL, "cpu");
179*df34403dSVitaly Bordug         virq= irq_of_parse_and_map(cpu, 0);
180*df34403dSVitaly Bordug 	irq = irq_map[virq].hwirq;
181*df34403dSVitaly Bordug 
182*df34403dSVitaly Bordug 	sys_tmr2 = (sit8xx_t *) immr_map(im_sit);
183*df34403dSVitaly Bordug 	out_be16(&sys_tmr2->sit_tbscr, ((1 << (7 - (irq/2))) << 8) |
184*df34403dSVitaly Bordug 					(TBSCR_TBF | TBSCR_TBE));
185*df34403dSVitaly Bordug 	immr_unmap(sys_tmr2);
186*df34403dSVitaly Bordug 
187*df34403dSVitaly Bordug 	if (setup_irq(virq, &tbint_irqaction))
188*df34403dSVitaly Bordug 		panic("Could not allocate timer IRQ!");
189*df34403dSVitaly Bordug 
190*df34403dSVitaly Bordug #ifdef CONFIG_8xx_WDT
191*df34403dSVitaly Bordug 	/* Install watchdog timer handler early because it might be
192*df34403dSVitaly Bordug 	 * already enabled by the bootloader
193*df34403dSVitaly Bordug 	 */
194*df34403dSVitaly Bordug 	m8xx_wdt_handler_install(binfo);
195*df34403dSVitaly Bordug #endif
196*df34403dSVitaly Bordug }
197*df34403dSVitaly Bordug 
198*df34403dSVitaly Bordug /* The RTC on the MPC8xx is an internal register.
199*df34403dSVitaly Bordug  * We want to protect this during power down, so we need to unlock,
200*df34403dSVitaly Bordug  * modify, and re-lock.
201*df34403dSVitaly Bordug  */
202*df34403dSVitaly Bordug 
203*df34403dSVitaly Bordug int mpc8xx_set_rtc_time(struct rtc_time *tm)
204*df34403dSVitaly Bordug {
205*df34403dSVitaly Bordug 	sitk8xx_t *sys_tmr1;
206*df34403dSVitaly Bordug 	sit8xx_t *sys_tmr2;
207*df34403dSVitaly Bordug 	int time;
208*df34403dSVitaly Bordug 
209*df34403dSVitaly Bordug         sys_tmr1 = (sitk8xx_t *) immr_map(im_sitk);
210*df34403dSVitaly Bordug 	sys_tmr2 = (sit8xx_t *) immr_map(im_sit);
211*df34403dSVitaly Bordug 	time = mktime(tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday,
212*df34403dSVitaly Bordug                       tm->tm_hour, tm->tm_min, tm->tm_sec);
213*df34403dSVitaly Bordug 
214*df34403dSVitaly Bordug 	out_be32(&sys_tmr1->sitk_rtck, KAPWR_KEY);
215*df34403dSVitaly Bordug 	out_be32(&sys_tmr2->sit_rtc, time);
216*df34403dSVitaly Bordug 	out_be32(&sys_tmr1->sitk_rtck, ~KAPWR_KEY);
217*df34403dSVitaly Bordug 
218*df34403dSVitaly Bordug 	immr_unmap(sys_tmr2);
219*df34403dSVitaly Bordug 	immr_unmap(sys_tmr1);
220*df34403dSVitaly Bordug 	return 0;
221*df34403dSVitaly Bordug }
222*df34403dSVitaly Bordug 
223*df34403dSVitaly Bordug void mpc8xx_get_rtc_time(struct rtc_time *tm)
224*df34403dSVitaly Bordug {
225*df34403dSVitaly Bordug 	unsigned long data;
226*df34403dSVitaly Bordug 	sit8xx_t *sys_tmr = (sit8xx_t *) immr_map(im_sit);
227*df34403dSVitaly Bordug 
228*df34403dSVitaly Bordug 	/* Get time from the RTC. */
229*df34403dSVitaly Bordug 	data = in_be32(&sys_tmr->sit_rtc);
230*df34403dSVitaly Bordug 	to_tm(data, tm);
231*df34403dSVitaly Bordug         tm->tm_year -= 1900;
232*df34403dSVitaly Bordug         tm->tm_mon -= 1;
233*df34403dSVitaly Bordug 	immr_unmap(sys_tmr);
234*df34403dSVitaly Bordug 	return;
235*df34403dSVitaly Bordug }
236*df34403dSVitaly Bordug 
237*df34403dSVitaly Bordug void mpc8xx_restart(char *cmd)
238*df34403dSVitaly Bordug {
239*df34403dSVitaly Bordug 	__volatile__ unsigned char dummy;
240*df34403dSVitaly Bordug 	car8xx_t * clk_r = (car8xx_t *) immr_map(im_clkrst);
241*df34403dSVitaly Bordug 
242*df34403dSVitaly Bordug 
243*df34403dSVitaly Bordug 	local_irq_disable();
244*df34403dSVitaly Bordug 
245*df34403dSVitaly Bordug 	setbits32(&clk_r->car_plprcr, 0x00000080);
246*df34403dSVitaly Bordug 	/* Clear the ME bit in MSR to cause checkstop on machine check
247*df34403dSVitaly Bordug 	*/
248*df34403dSVitaly Bordug 	mtmsr(mfmsr() & ~0x1000);
249*df34403dSVitaly Bordug 
250*df34403dSVitaly Bordug 	dummy = in_8(&clk_r->res[0]);
251*df34403dSVitaly Bordug 	printk("Restart failed\n");
252*df34403dSVitaly Bordug 	while(1);
253*df34403dSVitaly Bordug }
254*df34403dSVitaly Bordug 
255*df34403dSVitaly Bordug void mpc8xx_show_cpuinfo(struct seq_file *m)
256*df34403dSVitaly Bordug {
257*df34403dSVitaly Bordug 	struct device_node *root;
258*df34403dSVitaly Bordug 	uint memsize = total_memory;
259*df34403dSVitaly Bordug 	const char *model = "";
260*df34403dSVitaly Bordug 
261*df34403dSVitaly Bordug 	seq_printf(m, "Vendor\t\t: Freescale Semiconductor\n");
262*df34403dSVitaly Bordug 
263*df34403dSVitaly Bordug 	root = of_find_node_by_path("/");
264*df34403dSVitaly Bordug 	if (root)
265*df34403dSVitaly Bordug 		model = get_property(root, "model", NULL);
266*df34403dSVitaly Bordug 	seq_printf(m, "Machine\t\t: %s\n", model);
267*df34403dSVitaly Bordug 	of_node_put(root);
268*df34403dSVitaly Bordug 
269*df34403dSVitaly Bordug 	seq_printf(m, "Memory\t\t: %d MB\n", memsize / (1024 * 1024));
270*df34403dSVitaly Bordug }
271*df34403dSVitaly Bordug 
272*df34403dSVitaly Bordug static void cpm_cascade(unsigned int irq, struct irq_desc *desc)
273*df34403dSVitaly Bordug {
274*df34403dSVitaly Bordug 	int cascade_irq;
275*df34403dSVitaly Bordug 
276*df34403dSVitaly Bordug 	if ((cascade_irq = cpm_get_irq()) >= 0) {
277*df34403dSVitaly Bordug 		struct irq_desc *cdesc = irq_desc + cascade_irq;
278*df34403dSVitaly Bordug 
279*df34403dSVitaly Bordug 		generic_handle_irq(cascade_irq);
280*df34403dSVitaly Bordug 		cdesc->chip->eoi(cascade_irq);
281*df34403dSVitaly Bordug 	}
282*df34403dSVitaly Bordug 	desc->chip->eoi(irq);
283*df34403dSVitaly Bordug }
284*df34403dSVitaly Bordug 
285*df34403dSVitaly Bordug /* Initialize the internal interrupt controller.  The number of
286*df34403dSVitaly Bordug  * interrupts supported can vary with the processor type, and the
287*df34403dSVitaly Bordug  * 82xx family can have up to 64.
288*df34403dSVitaly Bordug  * External interrupts can be either edge or level triggered, and
289*df34403dSVitaly Bordug  * need to be initialized by the appropriate driver.
290*df34403dSVitaly Bordug  */
291*df34403dSVitaly Bordug void __init m8xx_pic_init(void)
292*df34403dSVitaly Bordug {
293*df34403dSVitaly Bordug 	int irq;
294*df34403dSVitaly Bordug 
295*df34403dSVitaly Bordug 	if (mpc8xx_pic_init()) {
296*df34403dSVitaly Bordug                 printk(KERN_ERR "Failed interrupt 8xx controller  initialization\n");
297*df34403dSVitaly Bordug 		return;
298*df34403dSVitaly Bordug 	}
299*df34403dSVitaly Bordug 
300*df34403dSVitaly Bordug 	irq = cpm_pic_init();
301*df34403dSVitaly Bordug 	if (irq != NO_IRQ)
302*df34403dSVitaly Bordug 		set_irq_chained_handler(irq, cpm_cascade);
303*df34403dSVitaly Bordug }
304