(5/6) bcm57xx: bcm4785 incomplete reboot
[librecmc/librecmc.git] / target / linux / brcm-2.4 / files / arch / mips / bcm947xx / setup.c
1 /*
2  *  Generic setup routines for Broadcom MIPS boards
3  *
4  *  Copyright (C) 2005 Felix Fietkau <nbd@openwrt.org>
5  *
6  *  This program is free software; you can redistribute  it and/or modify it
7  *  under  the terms of  the GNU General  Public License as published by the
8  *  Free Software Foundation;  either version 2 of the  License, or (at your
9  *  option) any later version.
10  *
11  *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
12  *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
13  *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
14  *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
15  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
16  *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
17  *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
18  *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
19  *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
20  *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
21  *
22  *  You should have received a copy of the  GNU General Public License along
23  *  with this program; if not, write  to the Free Software Foundation, Inc.,
24  *  675 Mass Ave, Cambridge, MA 02139, USA.
25  *
26  *
27  * Copyright 2005, Broadcom Corporation
28  * All Rights Reserved.
29  * 
30  * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
31  * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
32  * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
33  * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
34  *
35  */
36
37 #include <linux/config.h>
38 #include <linux/init.h>
39 #include <linux/kernel.h>
40 #include <linux/module.h>
41 #include <linux/serialP.h>
42 #include <linux/ide.h>
43 #include <asm/bootinfo.h>
44 #include <asm/cpu.h>
45 #include <asm/time.h>
46 #include <asm/reboot.h>
47
48 #include <typedefs.h>
49 #include <osl.h>
50 #include <sbutils.h>
51 #include <bcmnvram.h>
52 #include <bcmdevs.h>
53 #include <sbhndmips.h>
54 #include <hndmips.h>
55 #include <trxhdr.h>
56
57 /* Virtual IRQ base, after last hw IRQ */
58 #define SBMIPS_VIRTIRQ_BASE 6
59
60 /* # IRQs, hw and sw IRQs */
61 #define SBMIPS_NUMIRQS  8
62
63 /* Global SB handle */
64 sb_t *bcm947xx_sbh = NULL;
65 spinlock_t bcm947xx_sbh_lock = SPIN_LOCK_UNLOCKED;
66
67 /* Convenience */
68 #define sbh bcm947xx_sbh
69 #define sbh_lock bcm947xx_sbh_lock
70
71 extern void bcm947xx_time_init(void);
72 extern void bcm947xx_timer_setup(struct irqaction *irq);
73
74 #ifdef CONFIG_REMOTE_DEBUG
75 extern void set_debug_traps(void);
76 extern void rs_kgdb_hook(struct serial_state *);
77 extern void breakpoint(void);
78 #endif
79
80 #if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
81 extern struct ide_ops std_ide_ops;
82 #endif
83
84 /* Kernel command line */
85 char arcs_cmdline[CL_SIZE] __initdata = CONFIG_CMDLINE;
86 extern void sb_serial_init(sb_t *sbh, void (*add)(void *regs, uint irq, uint baud_base, uint reg_shift));
87
88 void
89 bcm947xx_machine_restart(char *command)
90 {
91         printk("Please stand by while rebooting the system...\n");
92
93         if (sb_chip(sbh) == BCM4785_CHIP_ID)
94                 MTC0(C0_BROADCOM, 4, (1 << 22));
95
96         /* Set the watchdog timer to reset immediately */
97         __cli();
98         sb_watchdog(sbh, 1);
99
100         if (sb_chip(sbh) == BCM4785_CHIP_ID) {
101                 __asm__ __volatile__(
102                         ".set\tmips3\n\t"
103                         "sync\n\t"
104                         "wait\n\t"
105                         ".set\tmips0");
106         }
107
108         while (1);
109 }
110
111 void
112 bcm947xx_machine_halt(void)
113 {
114         printk("System halted\n");
115
116         /* Disable interrupts and watchdog and spin forever */
117         __cli();
118         sb_watchdog(sbh, 0);
119         while (1);
120 }
121
122 #ifdef CONFIG_SERIAL
123
124 static int ser_line = 0;
125
126 typedef struct {
127         void *regs;
128         uint irq;
129         uint baud_base;
130         uint reg_shift;
131 } serial_port;
132
133 static serial_port ports[4];
134 static int num_ports = 0;
135
136 static void
137 serial_add(void *regs, uint irq, uint baud_base, uint reg_shift)
138 {
139         ports[num_ports].regs = regs;
140         ports[num_ports].irq = irq;
141         ports[num_ports].baud_base = baud_base;
142         ports[num_ports].reg_shift = reg_shift;
143         num_ports++;
144 }
145
146 static void
147 do_serial_add(serial_port *port)
148 {
149         void *regs;
150         uint irq;
151         uint baud_base;
152         uint reg_shift;
153         struct serial_struct s;
154         
155         regs = port->regs;
156         irq = port->irq;
157         baud_base = port->baud_base;
158         reg_shift = port->reg_shift;
159
160         memset(&s, 0, sizeof(s));
161
162         s.line = ser_line++;
163         s.iomem_base = regs;
164         s.irq = irq + 2;
165         s.baud_base = baud_base / 16;
166         s.flags = ASYNC_BOOT_AUTOCONF;
167         s.io_type = SERIAL_IO_MEM;
168         s.iomem_reg_shift = reg_shift;
169
170         if (early_serial_setup(&s) != 0) {
171                 printk(KERN_ERR "Serial setup failed!\n");
172         }
173 }
174
175 #endif /* CONFIG_SERIAL */
176
177 void __init
178 brcm_setup(void)
179 {
180         char *s;
181         int i;
182         char *value;
183
184         /* Get global SB handle */
185         sbh = sb_kattach(SB_OSH);
186
187         /* Initialize clocks and interrupts */
188         sb_mips_init(sbh, SBMIPS_VIRTIRQ_BASE);
189
190         if (BCM330X(current_cpu_data.processor_id) &&
191                 (read_c0_diag() & BRCM_PFC_AVAIL)) {
192                 /* 
193                  * Now that the sbh is inited set the  proper PFC value 
194                  */     
195                 printk("Setting the PFC to its default value\n");
196                 enable_pfc(PFC_AUTO);
197         }
198
199
200 #ifdef CONFIG_SERIAL
201         sb_serial_init(sbh, serial_add);
202
203         /* reverse serial ports if nvram variable starts with console=ttyS1 */
204         /* Initialize UARTs */
205         s = nvram_get("kernel_args");
206         if (!s) s = "";
207         if (!strncmp(s, "console=ttyS1", 13)) {
208                 for (i = num_ports; i; i--)
209                         do_serial_add(&ports[i - 1]);
210         } else {
211                 for (i = 0; i < num_ports; i++)
212                         do_serial_add(&ports[i]);
213         }
214 #endif
215
216 #if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
217         ide_ops = &std_ide_ops;
218 #endif
219
220         /* Override default command line arguments */
221         value = nvram_get("kernel_cmdline");
222         if (value && strlen(value) && strncmp(value, "empty", 5))
223                 strncpy(arcs_cmdline, value, sizeof(arcs_cmdline));
224
225
226         /* Generic setup */
227         _machine_restart = bcm947xx_machine_restart;
228         _machine_halt = bcm947xx_machine_halt;
229         _machine_power_off = bcm947xx_machine_halt;
230
231         board_time_init = bcm947xx_time_init;
232         board_timer_setup = bcm947xx_timer_setup;
233 }
234
235 const char *
236 get_system_type(void)
237 {
238         static char s[32];
239
240         if (bcm947xx_sbh) {
241                 sprintf(s, "Broadcom BCM%X chip rev %d", sb_chip(bcm947xx_sbh),
242                         sb_chiprev(bcm947xx_sbh));
243                 return s;
244         }
245         else
246                 return "Broadcom BCM947XX";
247 }
248
249 void __init
250 bus_error_init(void)
251 {
252 }
253