18c2ecf20Sopenharmony_ci/* 28c2ecf20Sopenharmony_ci * Copyright 2003-2011 NetLogic Microsystems, Inc. (NetLogic). All rights 38c2ecf20Sopenharmony_ci * reserved. 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * This software is available to you under a choice of one of two 68c2ecf20Sopenharmony_ci * licenses. You may choose to be licensed under the terms of the GNU 78c2ecf20Sopenharmony_ci * General Public License (GPL) Version 2, available from the file 88c2ecf20Sopenharmony_ci * COPYING in the main directory of this source tree, or the NetLogic 98c2ecf20Sopenharmony_ci * license below: 108c2ecf20Sopenharmony_ci * 118c2ecf20Sopenharmony_ci * Redistribution and use in source and binary forms, with or without 128c2ecf20Sopenharmony_ci * modification, are permitted provided that the following conditions 138c2ecf20Sopenharmony_ci * are met: 148c2ecf20Sopenharmony_ci * 158c2ecf20Sopenharmony_ci * 1. Redistributions of source code must retain the above copyright 168c2ecf20Sopenharmony_ci * notice, this list of conditions and the following disclaimer. 178c2ecf20Sopenharmony_ci * 2. Redistributions in binary form must reproduce the above copyright 188c2ecf20Sopenharmony_ci * notice, this list of conditions and the following disclaimer in 198c2ecf20Sopenharmony_ci * the documentation and/or other materials provided with the 208c2ecf20Sopenharmony_ci * distribution. 218c2ecf20Sopenharmony_ci * 228c2ecf20Sopenharmony_ci * THIS SOFTWARE IS PROVIDED BY NETLOGIC ``AS IS'' AND ANY EXPRESS OR 238c2ecf20Sopenharmony_ci * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 248c2ecf20Sopenharmony_ci * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 258c2ecf20Sopenharmony_ci * ARE DISCLAIMED. IN NO EVENT SHALL NETLOGIC OR CONTRIBUTORS BE LIABLE 268c2ecf20Sopenharmony_ci * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 278c2ecf20Sopenharmony_ci * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 288c2ecf20Sopenharmony_ci * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 298c2ecf20Sopenharmony_ci * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 308c2ecf20Sopenharmony_ci * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 318c2ecf20Sopenharmony_ci * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 328c2ecf20Sopenharmony_ci * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 338c2ecf20Sopenharmony_ci */ 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_ci#include <linux/kernel.h> 368c2ecf20Sopenharmony_ci#include <linux/serial_8250.h> 378c2ecf20Sopenharmony_ci#include <linux/memblock.h> 388c2ecf20Sopenharmony_ci#include <linux/pm.h> 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_ci#include <asm/idle.h> 418c2ecf20Sopenharmony_ci#include <asm/reboot.h> 428c2ecf20Sopenharmony_ci#include <asm/time.h> 438c2ecf20Sopenharmony_ci#include <asm/bootinfo.h> 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_ci#include <asm/netlogic/interrupt.h> 468c2ecf20Sopenharmony_ci#include <asm/netlogic/psb-bootinfo.h> 478c2ecf20Sopenharmony_ci#include <asm/netlogic/haldefs.h> 488c2ecf20Sopenharmony_ci#include <asm/netlogic/common.h> 498c2ecf20Sopenharmony_ci 508c2ecf20Sopenharmony_ci#include <asm/netlogic/xlr/xlr.h> 518c2ecf20Sopenharmony_ci#include <asm/netlogic/xlr/iomap.h> 528c2ecf20Sopenharmony_ci#include <asm/netlogic/xlr/pic.h> 538c2ecf20Sopenharmony_ci#include <asm/netlogic/xlr/gpio.h> 548c2ecf20Sopenharmony_ci#include <asm/netlogic/xlr/fmn.h> 558c2ecf20Sopenharmony_ci 568c2ecf20Sopenharmony_ciuint64_t nlm_io_base = DEFAULT_NETLOGIC_IO_BASE; 578c2ecf20Sopenharmony_cistruct psb_info nlm_prom_info; 588c2ecf20Sopenharmony_ci 598c2ecf20Sopenharmony_ci/* default to uniprocessor */ 608c2ecf20Sopenharmony_ciunsigned int nlm_threads_per_core = 1; 618c2ecf20Sopenharmony_cistruct nlm_soc_info nlm_nodes[NLM_NR_NODES]; 628c2ecf20Sopenharmony_cicpumask_t nlm_cpumask = CPU_MASK_CPU0; 638c2ecf20Sopenharmony_ci 648c2ecf20Sopenharmony_cistatic void nlm_linux_exit(void) 658c2ecf20Sopenharmony_ci{ 668c2ecf20Sopenharmony_ci uint64_t gpiobase; 678c2ecf20Sopenharmony_ci 688c2ecf20Sopenharmony_ci gpiobase = nlm_mmio_base(NETLOGIC_IO_GPIO_OFFSET); 698c2ecf20Sopenharmony_ci /* trigger a chip reset by writing 1 to GPIO_SWRESET_REG */ 708c2ecf20Sopenharmony_ci nlm_write_reg(gpiobase, GPIO_SWRESET_REG, 1); 718c2ecf20Sopenharmony_ci for ( ; ; ) 728c2ecf20Sopenharmony_ci cpu_wait(); 738c2ecf20Sopenharmony_ci} 748c2ecf20Sopenharmony_ci 758c2ecf20Sopenharmony_civoid __init plat_mem_setup(void) 768c2ecf20Sopenharmony_ci{ 778c2ecf20Sopenharmony_ci _machine_restart = (void (*)(char *))nlm_linux_exit; 788c2ecf20Sopenharmony_ci _machine_halt = nlm_linux_exit; 798c2ecf20Sopenharmony_ci pm_power_off = nlm_linux_exit; 808c2ecf20Sopenharmony_ci} 818c2ecf20Sopenharmony_ci 828c2ecf20Sopenharmony_ciconst char *get_system_type(void) 838c2ecf20Sopenharmony_ci{ 848c2ecf20Sopenharmony_ci return "Netlogic XLR/XLS Series"; 858c2ecf20Sopenharmony_ci} 868c2ecf20Sopenharmony_ci 878c2ecf20Sopenharmony_ciunsigned int nlm_get_cpu_frequency(void) 888c2ecf20Sopenharmony_ci{ 898c2ecf20Sopenharmony_ci return (unsigned int)nlm_prom_info.cpu_frequency; 908c2ecf20Sopenharmony_ci} 918c2ecf20Sopenharmony_ci 928c2ecf20Sopenharmony_civoid __init prom_free_prom_memory(void) 938c2ecf20Sopenharmony_ci{ 948c2ecf20Sopenharmony_ci /* Nothing yet */ 958c2ecf20Sopenharmony_ci} 968c2ecf20Sopenharmony_ci 978c2ecf20Sopenharmony_civoid nlm_percpu_init(int hwcpuid) 988c2ecf20Sopenharmony_ci{ 998c2ecf20Sopenharmony_ci if (hwcpuid % 4 == 0) 1008c2ecf20Sopenharmony_ci xlr_percpu_fmn_init(); 1018c2ecf20Sopenharmony_ci} 1028c2ecf20Sopenharmony_ci 1038c2ecf20Sopenharmony_cistatic void __init build_arcs_cmdline(int *argv) 1048c2ecf20Sopenharmony_ci{ 1058c2ecf20Sopenharmony_ci int i, remain, len; 1068c2ecf20Sopenharmony_ci char *arg; 1078c2ecf20Sopenharmony_ci 1088c2ecf20Sopenharmony_ci remain = sizeof(arcs_cmdline) - 1; 1098c2ecf20Sopenharmony_ci arcs_cmdline[0] = '\0'; 1108c2ecf20Sopenharmony_ci for (i = 0; argv[i] != 0; i++) { 1118c2ecf20Sopenharmony_ci arg = (char *)(long)argv[i]; 1128c2ecf20Sopenharmony_ci len = strlen(arg); 1138c2ecf20Sopenharmony_ci if (len + 1 > remain) 1148c2ecf20Sopenharmony_ci break; 1158c2ecf20Sopenharmony_ci strcat(arcs_cmdline, arg); 1168c2ecf20Sopenharmony_ci strcat(arcs_cmdline, " "); 1178c2ecf20Sopenharmony_ci remain -= len + 1; 1188c2ecf20Sopenharmony_ci } 1198c2ecf20Sopenharmony_ci 1208c2ecf20Sopenharmony_ci /* Add the default options here */ 1218c2ecf20Sopenharmony_ci if ((strstr(arcs_cmdline, "console=")) == NULL) { 1228c2ecf20Sopenharmony_ci arg = "console=ttyS0,38400 "; 1238c2ecf20Sopenharmony_ci len = strlen(arg); 1248c2ecf20Sopenharmony_ci if (len > remain) 1258c2ecf20Sopenharmony_ci goto fail; 1268c2ecf20Sopenharmony_ci strcat(arcs_cmdline, arg); 1278c2ecf20Sopenharmony_ci remain -= len; 1288c2ecf20Sopenharmony_ci } 1298c2ecf20Sopenharmony_ci#ifdef CONFIG_BLK_DEV_INITRD 1308c2ecf20Sopenharmony_ci if ((strstr(arcs_cmdline, "rdinit=")) == NULL) { 1318c2ecf20Sopenharmony_ci arg = "rdinit=/sbin/init "; 1328c2ecf20Sopenharmony_ci len = strlen(arg); 1338c2ecf20Sopenharmony_ci if (len > remain) 1348c2ecf20Sopenharmony_ci goto fail; 1358c2ecf20Sopenharmony_ci strcat(arcs_cmdline, arg); 1368c2ecf20Sopenharmony_ci remain -= len; 1378c2ecf20Sopenharmony_ci } 1388c2ecf20Sopenharmony_ci#endif 1398c2ecf20Sopenharmony_ci return; 1408c2ecf20Sopenharmony_cifail: 1418c2ecf20Sopenharmony_ci panic("Cannot add %s, command line too big!", arg); 1428c2ecf20Sopenharmony_ci} 1438c2ecf20Sopenharmony_ci 1448c2ecf20Sopenharmony_cistatic void prom_add_memory(void) 1458c2ecf20Sopenharmony_ci{ 1468c2ecf20Sopenharmony_ci struct nlm_boot_mem_map *bootm; 1478c2ecf20Sopenharmony_ci u64 start, size; 1488c2ecf20Sopenharmony_ci u64 pref_backup = 512; /* avoid pref walking beyond end */ 1498c2ecf20Sopenharmony_ci int i; 1508c2ecf20Sopenharmony_ci 1518c2ecf20Sopenharmony_ci bootm = (void *)(long)nlm_prom_info.psb_mem_map; 1528c2ecf20Sopenharmony_ci for (i = 0; i < bootm->nr_map; i++) { 1538c2ecf20Sopenharmony_ci if (bootm->map[i].type != NLM_BOOT_MEM_RAM) 1548c2ecf20Sopenharmony_ci continue; 1558c2ecf20Sopenharmony_ci start = bootm->map[i].addr; 1568c2ecf20Sopenharmony_ci size = bootm->map[i].size; 1578c2ecf20Sopenharmony_ci 1588c2ecf20Sopenharmony_ci /* Work around for using bootloader mem */ 1598c2ecf20Sopenharmony_ci if (i == 0 && start == 0 && size == 0x0c000000) 1608c2ecf20Sopenharmony_ci size = 0x0ff00000; 1618c2ecf20Sopenharmony_ci 1628c2ecf20Sopenharmony_ci memblock_add(start, size - pref_backup); 1638c2ecf20Sopenharmony_ci } 1648c2ecf20Sopenharmony_ci} 1658c2ecf20Sopenharmony_ci 1668c2ecf20Sopenharmony_cistatic void nlm_init_node(void) 1678c2ecf20Sopenharmony_ci{ 1688c2ecf20Sopenharmony_ci struct nlm_soc_info *nodep; 1698c2ecf20Sopenharmony_ci 1708c2ecf20Sopenharmony_ci nodep = nlm_current_node(); 1718c2ecf20Sopenharmony_ci nodep->picbase = nlm_mmio_base(NETLOGIC_IO_PIC_OFFSET); 1728c2ecf20Sopenharmony_ci nodep->ebase = read_c0_ebase() & MIPS_EBASE_BASE; 1738c2ecf20Sopenharmony_ci spin_lock_init(&nodep->piclock); 1748c2ecf20Sopenharmony_ci} 1758c2ecf20Sopenharmony_ci 1768c2ecf20Sopenharmony_civoid __init prom_init(void) 1778c2ecf20Sopenharmony_ci{ 1788c2ecf20Sopenharmony_ci int *argv, *envp; /* passed as 32 bit ptrs */ 1798c2ecf20Sopenharmony_ci struct psb_info *prom_infop; 1808c2ecf20Sopenharmony_ci void *reset_vec; 1818c2ecf20Sopenharmony_ci#ifdef CONFIG_SMP 1828c2ecf20Sopenharmony_ci int i; 1838c2ecf20Sopenharmony_ci#endif 1848c2ecf20Sopenharmony_ci 1858c2ecf20Sopenharmony_ci /* truncate to 32 bit and sign extend all args */ 1868c2ecf20Sopenharmony_ci argv = (int *)(long)(int)fw_arg1; 1878c2ecf20Sopenharmony_ci envp = (int *)(long)(int)fw_arg2; 1888c2ecf20Sopenharmony_ci prom_infop = (struct psb_info *)(long)(int)fw_arg3; 1898c2ecf20Sopenharmony_ci 1908c2ecf20Sopenharmony_ci nlm_prom_info = *prom_infop; 1918c2ecf20Sopenharmony_ci nlm_init_node(); 1928c2ecf20Sopenharmony_ci 1938c2ecf20Sopenharmony_ci /* Update reset entry point with CPU init code */ 1948c2ecf20Sopenharmony_ci reset_vec = (void *)CKSEG1ADDR(RESET_VEC_PHYS); 1958c2ecf20Sopenharmony_ci memset(reset_vec, 0, RESET_VEC_SIZE); 1968c2ecf20Sopenharmony_ci memcpy(reset_vec, (void *)nlm_reset_entry, 1978c2ecf20Sopenharmony_ci (nlm_reset_entry_end - nlm_reset_entry)); 1988c2ecf20Sopenharmony_ci 1998c2ecf20Sopenharmony_ci build_arcs_cmdline(argv); 2008c2ecf20Sopenharmony_ci prom_add_memory(); 2018c2ecf20Sopenharmony_ci 2028c2ecf20Sopenharmony_ci#ifdef CONFIG_SMP 2038c2ecf20Sopenharmony_ci for (i = 0; i < 32; i++) 2048c2ecf20Sopenharmony_ci if (nlm_prom_info.online_cpu_map & (1 << i)) 2058c2ecf20Sopenharmony_ci cpumask_set_cpu(i, &nlm_cpumask); 2068c2ecf20Sopenharmony_ci nlm_wakeup_secondary_cpus(); 2078c2ecf20Sopenharmony_ci register_smp_ops(&nlm_smp_ops); 2088c2ecf20Sopenharmony_ci#endif 2098c2ecf20Sopenharmony_ci xlr_board_info_setup(); 2108c2ecf20Sopenharmony_ci xlr_percpu_fmn_init(); 2118c2ecf20Sopenharmony_ci} 212