xref: /linux/arch/mips/bcm63xx/setup.c (revision 3de96d810ffd712b7ad2bd764c1390fac2436551)
1 /*
2  * This file is subject to the terms and conditions of the GNU General Public
3  * License.  See the file "COPYING" in the main directory of this archive
4  * for more details.
5  *
6  * Copyright (C) 2008 Maxime Bizon <mbizon@freebox.fr>
7  */
8 
9 #include <linux/init.h>
10 #include <linux/kernel.h>
11 #include <linux/delay.h>
12 #include <linux/memblock.h>
13 #include <linux/ioport.h>
14 #include <linux/pm.h>
15 #include <asm/bmips.h>
16 #include <asm/bootinfo.h>
17 #include <asm/time.h>
18 #include <asm/reboot.h>
19 #include <asm/cacheflush.h>
20 #include <bcm63xx_board.h>
21 #include <bcm63xx_cpu.h>
22 #include <bcm63xx_regs.h>
23 #include <bcm63xx_io.h>
24 #include <bcm63xx_gpio.h>
25 
26 /* CBR addr doesn't change and we can cache it */
27 void __iomem *bmips_cbr_addr __read_mostly;
28 
29 void bcm63xx_machine_halt(void)
30 {
31 	pr_info("System halted\n");
32 	while (1)
33 		;
34 }
35 
36 static void bcm6348_a1_reboot(void)
37 {
38 	u32 reg;
39 
40 	/* soft reset all blocks */
41 	pr_info("soft-resetting all blocks ...\n");
42 	reg = bcm_perf_readl(PERF_SOFTRESET_REG);
43 	reg &= ~SOFTRESET_6348_ALL;
44 	bcm_perf_writel(reg, PERF_SOFTRESET_REG);
45 	mdelay(10);
46 
47 	reg = bcm_perf_readl(PERF_SOFTRESET_REG);
48 	reg |= SOFTRESET_6348_ALL;
49 	bcm_perf_writel(reg, PERF_SOFTRESET_REG);
50 	mdelay(10);
51 
52 	/* Jump to the power on address. */
53 	pr_info("jumping to reset vector.\n");
54 	/* set high vectors (base at 0xbfc00000 */
55 	set_c0_status(ST0_BEV | ST0_ERL);
56 	/* run uncached in kseg0 */
57 	change_c0_config(CONF_CM_CMASK, CONF_CM_UNCACHED);
58 	__flush_cache_all();
59 	/* remove all wired TLB entries */
60 	write_c0_wired(0);
61 	__asm__ __volatile__(
62 		"jr\t%0"
63 		:
64 		: "r" (0xbfc00000));
65 	while (1)
66 		;
67 }
68 
69 void bcm63xx_machine_reboot(void)
70 {
71 	u32 reg, perf_regs[2] = { 0, 0 };
72 	unsigned int i;
73 
74 	/* mask and clear all external irq */
75 	switch (bcm63xx_get_cpu_id()) {
76 	case BCM3368_CPU_ID:
77 		perf_regs[0] = PERF_EXTIRQ_CFG_REG_3368;
78 		break;
79 	case BCM6328_CPU_ID:
80 		perf_regs[0] = PERF_EXTIRQ_CFG_REG_6328;
81 		break;
82 	case BCM6338_CPU_ID:
83 		perf_regs[0] = PERF_EXTIRQ_CFG_REG_6338;
84 		break;
85 	case BCM6345_CPU_ID:
86 		perf_regs[0] = PERF_EXTIRQ_CFG_REG_6345;
87 		break;
88 	case BCM6348_CPU_ID:
89 		perf_regs[0] = PERF_EXTIRQ_CFG_REG_6348;
90 		break;
91 	case BCM6358_CPU_ID:
92 		perf_regs[0] = PERF_EXTIRQ_CFG_REG_6358;
93 		break;
94 	case BCM6362_CPU_ID:
95 		perf_regs[0] = PERF_EXTIRQ_CFG_REG_6362;
96 		break;
97 	}
98 
99 	for (i = 0; i < 2; i++) {
100 		if (!perf_regs[i])
101 			break;
102 
103 		reg = bcm_perf_readl(perf_regs[i]);
104 		if (BCMCPU_IS_6348()) {
105 			reg &= ~EXTIRQ_CFG_MASK_ALL_6348;
106 			reg |= EXTIRQ_CFG_CLEAR_ALL_6348;
107 		} else {
108 			reg &= ~EXTIRQ_CFG_MASK_ALL;
109 			reg |= EXTIRQ_CFG_CLEAR_ALL;
110 		}
111 		bcm_perf_writel(reg, perf_regs[i]);
112 	}
113 
114 	if (BCMCPU_IS_6348() && (bcm63xx_get_cpu_rev() == 0xa1))
115 		bcm6348_a1_reboot();
116 
117 	pr_info("triggering watchdog soft-reset...\n");
118 	if (BCMCPU_IS_6328()) {
119 		bcm_wdt_writel(1, WDT_SOFTRESET_REG);
120 	} else {
121 		reg = bcm_perf_readl(PERF_SYS_PLL_CTL_REG);
122 		reg |= SYS_PLL_SOFT_RESET;
123 		bcm_perf_writel(reg, PERF_SYS_PLL_CTL_REG);
124 	}
125 	while (1)
126 		;
127 }
128 
129 static void __bcm63xx_machine_reboot(char *p)
130 {
131 	bcm63xx_machine_reboot();
132 }
133 
134 /*
135  * return system type in /proc/cpuinfo
136  */
137 const char *get_system_type(void)
138 {
139 	static char buf[128];
140 	snprintf(buf, sizeof(buf), "bcm63xx/%s (0x%04x/0x%02X)",
141 		 board_get_name(),
142 		 bcm63xx_get_cpu_id(), bcm63xx_get_cpu_rev());
143 	return buf;
144 }
145 
146 void __init plat_time_init(void)
147 {
148 	mips_hpt_frequency = bcm63xx_get_cpu_freq() / 2;
149 }
150 
151 void __init plat_mem_setup(void)
152 {
153 	memblock_add(0, bcm63xx_get_memory_size());
154 
155 	_machine_halt = bcm63xx_machine_halt;
156 	_machine_restart = __bcm63xx_machine_reboot;
157 	pm_power_off = bcm63xx_machine_halt;
158 
159 	set_io_port_base(0);
160 	ioport_resource.start = 0;
161 	ioport_resource.end = ~0;
162 
163 	board_setup();
164 }
165 
166 static int __init bcm63xx_register_devices(void)
167 {
168 	/* register gpiochip */
169 	bcm63xx_gpio_init();
170 
171 	return board_register_devices();
172 }
173 
174 arch_initcall(bcm63xx_register_devices);
175