1e7300d04SMaxime Bizon /*
2e7300d04SMaxime Bizon * This file is subject to the terms and conditions of the GNU General Public
3e7300d04SMaxime Bizon * License. See the file "COPYING" in the main directory of this archive
4e7300d04SMaxime Bizon * for more details.
5e7300d04SMaxime Bizon *
6e7300d04SMaxime Bizon * Copyright (C) 2008 Maxime Bizon <mbizon@freebox.fr>
7e7300d04SMaxime Bizon */
8e7300d04SMaxime Bizon
9e7300d04SMaxime Bizon #include <linux/init.h>
10e7300d04SMaxime Bizon #include <linux/kernel.h>
11e7300d04SMaxime Bizon #include <linux/delay.h>
1257c8a661SMike Rapoport #include <linux/memblock.h>
13e7300d04SMaxime Bizon #include <linux/ioport.h>
14e7300d04SMaxime Bizon #include <linux/pm.h>
15e7300d04SMaxime Bizon #include <asm/bootinfo.h>
16e7300d04SMaxime Bizon #include <asm/time.h>
17e7300d04SMaxime Bizon #include <asm/reboot.h>
18e7300d04SMaxime Bizon #include <asm/cacheflush.h>
19e7300d04SMaxime Bizon #include <bcm63xx_board.h>
20e7300d04SMaxime Bizon #include <bcm63xx_cpu.h>
21e7300d04SMaxime Bizon #include <bcm63xx_regs.h>
22e7300d04SMaxime Bizon #include <bcm63xx_io.h>
232ec459f2SNicolas Schichan #include <bcm63xx_gpio.h>
24e7300d04SMaxime Bizon
bcm63xx_machine_halt(void)25e7300d04SMaxime Bizon void bcm63xx_machine_halt(void)
26e7300d04SMaxime Bizon {
2763893ea5SGregory Fong pr_info("System halted\n");
28e7300d04SMaxime Bizon while (1)
29e7300d04SMaxime Bizon ;
30e7300d04SMaxime Bizon }
31e7300d04SMaxime Bizon
bcm6348_a1_reboot(void)32e7300d04SMaxime Bizon static void bcm6348_a1_reboot(void)
33e7300d04SMaxime Bizon {
34e7300d04SMaxime Bizon u32 reg;
35e7300d04SMaxime Bizon
36e7300d04SMaxime Bizon /* soft reset all blocks */
3763893ea5SGregory Fong pr_info("soft-resetting all blocks ...\n");
38e7300d04SMaxime Bizon reg = bcm_perf_readl(PERF_SOFTRESET_REG);
39e7300d04SMaxime Bizon reg &= ~SOFTRESET_6348_ALL;
40e7300d04SMaxime Bizon bcm_perf_writel(reg, PERF_SOFTRESET_REG);
41e7300d04SMaxime Bizon mdelay(10);
42e7300d04SMaxime Bizon
43e7300d04SMaxime Bizon reg = bcm_perf_readl(PERF_SOFTRESET_REG);
44e7300d04SMaxime Bizon reg |= SOFTRESET_6348_ALL;
45e7300d04SMaxime Bizon bcm_perf_writel(reg, PERF_SOFTRESET_REG);
46e7300d04SMaxime Bizon mdelay(10);
47e7300d04SMaxime Bizon
48e7300d04SMaxime Bizon /* Jump to the power on address. */
4963893ea5SGregory Fong pr_info("jumping to reset vector.\n");
50e7300d04SMaxime Bizon /* set high vectors (base at 0xbfc00000 */
51e7300d04SMaxime Bizon set_c0_status(ST0_BEV | ST0_ERL);
52e7300d04SMaxime Bizon /* run uncached in kseg0 */
53e7300d04SMaxime Bizon change_c0_config(CONF_CM_CMASK, CONF_CM_UNCACHED);
54e7300d04SMaxime Bizon __flush_cache_all();
55e7300d04SMaxime Bizon /* remove all wired TLB entries */
56e7300d04SMaxime Bizon write_c0_wired(0);
57e7300d04SMaxime Bizon __asm__ __volatile__(
58e7300d04SMaxime Bizon "jr\t%0"
59e7300d04SMaxime Bizon :
60e7300d04SMaxime Bizon : "r" (0xbfc00000));
61e7300d04SMaxime Bizon while (1)
62e7300d04SMaxime Bizon ;
63e7300d04SMaxime Bizon }
64e7300d04SMaxime Bizon
bcm63xx_machine_reboot(void)65e7300d04SMaxime Bizon void bcm63xx_machine_reboot(void)
66e7300d04SMaxime Bizon {
676224892cSMaxime Bizon u32 reg, perf_regs[2] = { 0, 0 };
686224892cSMaxime Bizon unsigned int i;
69e7300d04SMaxime Bizon
70e7300d04SMaxime Bizon /* mask and clear all external irq */
716224892cSMaxime Bizon switch (bcm63xx_get_cpu_id()) {
727b933421SFlorian Fainelli case BCM3368_CPU_ID:
737b933421SFlorian Fainelli perf_regs[0] = PERF_EXTIRQ_CFG_REG_3368;
747b933421SFlorian Fainelli break;
75e5766aeaSJonas Gorski case BCM6328_CPU_ID:
76e5766aeaSJonas Gorski perf_regs[0] = PERF_EXTIRQ_CFG_REG_6328;
77e5766aeaSJonas Gorski break;
786224892cSMaxime Bizon case BCM6338_CPU_ID:
796224892cSMaxime Bizon perf_regs[0] = PERF_EXTIRQ_CFG_REG_6338;
806224892cSMaxime Bizon break;
8164eaea4aSMaxime Bizon case BCM6345_CPU_ID:
8264eaea4aSMaxime Bizon perf_regs[0] = PERF_EXTIRQ_CFG_REG_6345;
8364eaea4aSMaxime Bizon break;
846224892cSMaxime Bizon case BCM6348_CPU_ID:
856224892cSMaxime Bizon perf_regs[0] = PERF_EXTIRQ_CFG_REG_6348;
866224892cSMaxime Bizon break;
876224892cSMaxime Bizon case BCM6358_CPU_ID:
886224892cSMaxime Bizon perf_regs[0] = PERF_EXTIRQ_CFG_REG_6358;
896224892cSMaxime Bizon break;
902c8aaf71SJonas Gorski case BCM6362_CPU_ID:
912c8aaf71SJonas Gorski perf_regs[0] = PERF_EXTIRQ_CFG_REG_6362;
922c8aaf71SJonas Gorski break;
936224892cSMaxime Bizon }
946224892cSMaxime Bizon
956224892cSMaxime Bizon for (i = 0; i < 2; i++) {
966d591805SMaxime Bizon if (!perf_regs[i])
976d591805SMaxime Bizon break;
986d591805SMaxime Bizon
996224892cSMaxime Bizon reg = bcm_perf_readl(perf_regs[i]);
1006224892cSMaxime Bizon if (BCMCPU_IS_6348()) {
1016224892cSMaxime Bizon reg &= ~EXTIRQ_CFG_MASK_ALL_6348;
1026224892cSMaxime Bizon reg |= EXTIRQ_CFG_CLEAR_ALL_6348;
1036224892cSMaxime Bizon } else {
104e7300d04SMaxime Bizon reg &= ~EXTIRQ_CFG_MASK_ALL;
105e7300d04SMaxime Bizon reg |= EXTIRQ_CFG_CLEAR_ALL;
1066224892cSMaxime Bizon }
1076224892cSMaxime Bizon bcm_perf_writel(reg, perf_regs[i]);
1086224892cSMaxime Bizon }
109e7300d04SMaxime Bizon
110e7300d04SMaxime Bizon if (BCMCPU_IS_6348() && (bcm63xx_get_cpu_rev() == 0xa1))
111e7300d04SMaxime Bizon bcm6348_a1_reboot();
112e7300d04SMaxime Bizon
11363893ea5SGregory Fong pr_info("triggering watchdog soft-reset...\n");
114e5766aeaSJonas Gorski if (BCMCPU_IS_6328()) {
115e5766aeaSJonas Gorski bcm_wdt_writel(1, WDT_SOFTRESET_REG);
116e5766aeaSJonas Gorski } else {
117e85d59dfSFlorian Fainelli reg = bcm_perf_readl(PERF_SYS_PLL_CTL_REG);
118e85d59dfSFlorian Fainelli reg |= SYS_PLL_SOFT_RESET;
119e85d59dfSFlorian Fainelli bcm_perf_writel(reg, PERF_SYS_PLL_CTL_REG);
120e5766aeaSJonas Gorski }
121e7300d04SMaxime Bizon while (1)
122e7300d04SMaxime Bizon ;
123e7300d04SMaxime Bizon }
124e7300d04SMaxime Bizon
__bcm63xx_machine_reboot(char * p)125e7300d04SMaxime Bizon static void __bcm63xx_machine_reboot(char *p)
126e7300d04SMaxime Bizon {
127e7300d04SMaxime Bizon bcm63xx_machine_reboot();
128e7300d04SMaxime Bizon }
129e7300d04SMaxime Bizon
130e7300d04SMaxime Bizon /*
131e7300d04SMaxime Bizon * return system type in /proc/cpuinfo
132e7300d04SMaxime Bizon */
get_system_type(void)133e7300d04SMaxime Bizon const char *get_system_type(void)
134e7300d04SMaxime Bizon {
135e7300d04SMaxime Bizon static char buf[128];
1366605428cSJonas Gorski snprintf(buf, sizeof(buf), "bcm63xx/%s (0x%04x/0x%02X)",
137e7300d04SMaxime Bizon board_get_name(),
138e7300d04SMaxime Bizon bcm63xx_get_cpu_id(), bcm63xx_get_cpu_rev());
139e7300d04SMaxime Bizon return buf;
140e7300d04SMaxime Bizon }
141e7300d04SMaxime Bizon
plat_time_init(void)142e7300d04SMaxime Bizon void __init plat_time_init(void)
143e7300d04SMaxime Bizon {
144e7300d04SMaxime Bizon mips_hpt_frequency = bcm63xx_get_cpu_freq() / 2;
145e7300d04SMaxime Bizon }
146e7300d04SMaxime Bizon
plat_mem_setup(void)147e7300d04SMaxime Bizon void __init plat_mem_setup(void)
148e7300d04SMaxime Bizon {
149*e7ae8d17SThomas Bogendoerfer memblock_add(0, bcm63xx_get_memory_size());
150e7300d04SMaxime Bizon
151e7300d04SMaxime Bizon _machine_halt = bcm63xx_machine_halt;
152e7300d04SMaxime Bizon _machine_restart = __bcm63xx_machine_reboot;
153e7300d04SMaxime Bizon pm_power_off = bcm63xx_machine_halt;
154e7300d04SMaxime Bizon
155e7300d04SMaxime Bizon set_io_port_base(0);
156e7300d04SMaxime Bizon ioport_resource.start = 0;
157e7300d04SMaxime Bizon ioport_resource.end = ~0;
158e7300d04SMaxime Bizon
159e7300d04SMaxime Bizon board_setup();
160e7300d04SMaxime Bizon }
161e7300d04SMaxime Bizon
bcm63xx_register_devices(void)162e7300d04SMaxime Bizon int __init bcm63xx_register_devices(void)
163e7300d04SMaxime Bizon {
1642ec459f2SNicolas Schichan /* register gpiochip */
1652ec459f2SNicolas Schichan bcm63xx_gpio_init();
1662ec459f2SNicolas Schichan
167e7300d04SMaxime Bizon return board_register_devices();
168e7300d04SMaxime Bizon }
169e7300d04SMaxime Bizon
1701762c5abSJonas Gorski arch_initcall(bcm63xx_register_devices);
171