15c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C/*
25c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C * Copyright 2003-2011 NetLogic Microsystems, Inc. (NetLogic). All rights
35c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C * reserved.
45c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C *
55c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C * This software is available to you under a choice of one of two
65c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C * licenses.  You may choose to be licensed under the terms of the GNU
75c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C * General Public License (GPL) Version 2, available from the file
85c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C * COPYING in the main directory of this source tree, or the NetLogic
95c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C * license below:
105c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C *
115c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C * Redistribution and use in source and binary forms, with or without
125c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C * modification, are permitted provided that the following conditions
135c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C * are met:
145c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C *
155c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C * 1. Redistributions of source code must retain the above copyright
165c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C *    notice, this list of conditions and the following disclaimer.
175c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C * 2. Redistributions in binary form must reproduce the above copyright
185c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C *    notice, this list of conditions and the following disclaimer in
195c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C *    the documentation and/or other materials provided with the
205c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C *    distribution.
215c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C *
225c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C * THIS SOFTWARE IS PROVIDED BY NETLOGIC ``AS IS'' AND ANY EXPRESS OR
235c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
245c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
255c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C * ARE DISCLAIMED. IN NO EVENT SHALL NETLOGIC OR CONTRIBUTORS BE LIABLE
265c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
275c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
285c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
295c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
305c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
315c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
325c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
335c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C */
345c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C
355c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C#include <linux/kernel.h>
365c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C#include <linux/serial_8250.h>
375c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C#include <linux/pm.h>
385c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C
39bdc92d74e0ec95a8101447467c25f015105f2e5aRalf Baechle#include <asm/idle.h>
405c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C#include <asm/reboot.h>
415c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C#include <asm/time.h>
425c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C#include <asm/bootinfo.h>
435c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C
445c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C#include <asm/netlogic/interrupt.h>
455c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C#include <asm/netlogic/psb-bootinfo.h>
460c9654072a6e15aa3da9b314f0c5c01e90938268Jayachandran C#include <asm/netlogic/haldefs.h>
470c9654072a6e15aa3da9b314f0c5c01e90938268Jayachandran C#include <asm/netlogic/common.h>
485c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C
495c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C#include <asm/netlogic/xlr/xlr.h>
505c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C#include <asm/netlogic/xlr/iomap.h>
515c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C#include <asm/netlogic/xlr/pic.h>
525c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C#include <asm/netlogic/xlr/gpio.h>
53ed21cfe207276e2d2883173399dd0380db372e18Ganesan Ramalingam#include <asm/netlogic/xlr/fmn.h>
545c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C
550c9654072a6e15aa3da9b314f0c5c01e90938268Jayachandran Cuint64_t nlm_io_base = DEFAULT_NETLOGIC_IO_BASE;
565c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran Cstruct psb_info nlm_prom_info;
575c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C
5866d29985fab8207b1b2c03ac34a2c294c5b47a30Jayachandran C/* default to uniprocessor */
5977ae798f5b736dfdc692b86b393d9699052ac77aJayachandran Cunsigned int  nlm_threads_per_core = 1;
6077ae798f5b736dfdc692b86b393d9699052ac77aJayachandran Cstruct nlm_soc_info nlm_nodes[NLM_NR_NODES];
612a37b1ae443f20470a789b12a45cbc249c9e50a6Jayachandran Ccpumask_t nlm_cpumask = CPU_MASK_CPU0;
6266d29985fab8207b1b2c03ac34a2c294c5b47a30Jayachandran C
635c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran Cstatic void nlm_linux_exit(void)
645c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C{
650c9654072a6e15aa3da9b314f0c5c01e90938268Jayachandran C	uint64_t gpiobase;
665c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C
670c9654072a6e15aa3da9b314f0c5c01e90938268Jayachandran C	gpiobase = nlm_mmio_base(NETLOGIC_IO_GPIO_OFFSET);
685c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C	/* trigger a chip reset by writing 1 to GPIO_SWRESET_REG */
69c5a48ff81e25c8585dae981a6cc19ed55788cadfJayachandran C	nlm_write_reg(gpiobase, GPIO_SWRESET_REG, 1);
705c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C	for ( ; ; )
715c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C		cpu_wait();
725c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C}
735c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C
745c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran Cvoid __init plat_mem_setup(void)
755c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C{
765c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C	_machine_restart = (void (*)(char *))nlm_linux_exit;
775c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C	_machine_halt	= nlm_linux_exit;
785c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C	pm_power_off	= nlm_linux_exit;
795c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C}
805c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C
815c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran Cconst char *get_system_type(void)
825c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C{
835c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C	return "Netlogic XLR/XLS Series";
845c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C}
855c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C
860c9654072a6e15aa3da9b314f0c5c01e90938268Jayachandran Cunsigned int nlm_get_cpu_frequency(void)
870c9654072a6e15aa3da9b314f0c5c01e90938268Jayachandran C{
880c9654072a6e15aa3da9b314f0c5c01e90938268Jayachandran C	return (unsigned int)nlm_prom_info.cpu_frequency;
890c9654072a6e15aa3da9b314f0c5c01e90938268Jayachandran C}
900c9654072a6e15aa3da9b314f0c5c01e90938268Jayachandran C
915c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran Cvoid __init prom_free_prom_memory(void)
925c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C{
935c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C	/* Nothing yet */
945c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C}
955c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C
96ed21cfe207276e2d2883173399dd0380db372e18Ganesan Ramalingamvoid nlm_percpu_init(int hwcpuid)
97ed21cfe207276e2d2883173399dd0380db372e18Ganesan Ramalingam{
98ed21cfe207276e2d2883173399dd0380db372e18Ganesan Ramalingam	if (hwcpuid % 4 == 0)
99ed21cfe207276e2d2883173399dd0380db372e18Ganesan Ramalingam		xlr_percpu_fmn_init();
100ed21cfe207276e2d2883173399dd0380db372e18Ganesan Ramalingam}
101ed21cfe207276e2d2883173399dd0380db372e18Ganesan Ramalingam
102a74e33535fa27c758d2a23ebf5f8964bf19940bcJayachandran Cstatic void __init build_arcs_cmdline(int *argv)
1035c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C{
1045c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C	int i, remain, len;
1055c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C	char *arg;
1065c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C
1075c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C	remain = sizeof(arcs_cmdline) - 1;
1085c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C	arcs_cmdline[0] = '\0';
1095c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C	for (i = 0; argv[i] != 0; i++) {
1105c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C		arg = (char *)(long)argv[i];
1115c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C		len = strlen(arg);
1125c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C		if (len + 1 > remain)
1135c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C			break;
1145c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C		strcat(arcs_cmdline, arg);
1155c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C		strcat(arcs_cmdline, " ");
1165c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C		remain -=  len + 1;
1175c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C	}
1185c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C
1195c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C	/* Add the default options here */
1205c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C	if ((strstr(arcs_cmdline, "console=")) == NULL) {
1215c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C		arg = "console=ttyS0,38400 ";
1225c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C		len = strlen(arg);
1235c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C		if (len > remain)
1245c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C			goto fail;
1255c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C		strcat(arcs_cmdline, arg);
1265c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C		remain -= len;
1275c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C	}
1285c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C#ifdef CONFIG_BLK_DEV_INITRD
1295c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C	if ((strstr(arcs_cmdline, "rdinit=")) == NULL) {
1305c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C		arg = "rdinit=/sbin/init ";
1315c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C		len = strlen(arg);
1325c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C		if (len > remain)
1335c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C			goto fail;
1345c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C		strcat(arcs_cmdline, arg);
1355c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C		remain -= len;
1365c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C	}
1375c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C#endif
1385c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C	return;
1395c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran Cfail:
1405c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C	panic("Cannot add %s, command line too big!", arg);
1415c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C}
1425c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C
1435c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran Cstatic void prom_add_memory(void)
1445c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C{
1455c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C	struct nlm_boot_mem_map *bootm;
1465c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C	u64 start, size;
1477034228792cc561e79ff8600f02884bd4c80e287Ralf Baechle	u64 pref_backup = 512;	/* avoid pref walking beyond end */
1485c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C	int i;
1495c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C
1505c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C	bootm = (void *)(long)nlm_prom_info.psb_mem_map;
1515c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C	for (i = 0; i < bootm->nr_map; i++) {
1525c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C		if (bootm->map[i].type != BOOT_MEM_RAM)
1535c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C			continue;
1545c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C		start = bootm->map[i].addr;
1555c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C		size   = bootm->map[i].size;
1565c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C
1575c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C		/* Work around for using bootloader mem */
1585c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C		if (i == 0 && start == 0 && size == 0x0c000000)
1595c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C			size = 0x0ff00000;
1605c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C
1615c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C		add_memory_region(start, size - pref_backup, BOOT_MEM_RAM);
1625c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C	}
1635c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C}
1645c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C
16577ae798f5b736dfdc692b86b393d9699052ac77aJayachandran Cstatic void nlm_init_node(void)
16677ae798f5b736dfdc692b86b393d9699052ac77aJayachandran C{
16777ae798f5b736dfdc692b86b393d9699052ac77aJayachandran C	struct nlm_soc_info *nodep;
16877ae798f5b736dfdc692b86b393d9699052ac77aJayachandran C
16977ae798f5b736dfdc692b86b393d9699052ac77aJayachandran C	nodep = nlm_current_node();
17077ae798f5b736dfdc692b86b393d9699052ac77aJayachandran C	nodep->picbase = nlm_mmio_base(NETLOGIC_IO_PIC_OFFSET);
17177ae798f5b736dfdc692b86b393d9699052ac77aJayachandran C	nodep->ebase = read_c0_ebase() & (~((1 << 12) - 1));
17277ae798f5b736dfdc692b86b393d9699052ac77aJayachandran C	spin_lock_init(&nodep->piclock);
17377ae798f5b736dfdc692b86b393d9699052ac77aJayachandran C}
17477ae798f5b736dfdc692b86b393d9699052ac77aJayachandran C
1755c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran Cvoid __init prom_init(void)
1765c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C{
17726f5ae865d7b324e46fff91acf43c485939bf6eaJayachandran C	int *argv, *envp;		/* passed as 32 bit ptrs */
1785c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C	struct psb_info *prom_infop;
179571886b2a52395f030d439c6259663a033e11e6aJayachandran C	void *reset_vec;
18026f5ae865d7b324e46fff91acf43c485939bf6eaJayachandran C#ifdef CONFIG_SMP
18126f5ae865d7b324e46fff91acf43c485939bf6eaJayachandran C	int i;
18226f5ae865d7b324e46fff91acf43c485939bf6eaJayachandran C#endif
1835c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C
1845c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C	/* truncate to 32 bit and sign extend all args */
1855c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C	argv = (int *)(long)(int)fw_arg1;
1865c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C	envp = (int *)(long)(int)fw_arg2;
1875c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C	prom_infop = (struct psb_info *)(long)(int)fw_arg3;
1885c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C
1895c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C	nlm_prom_info = *prom_infop;
19077ae798f5b736dfdc692b86b393d9699052ac77aJayachandran C	nlm_init_node();
1915c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C
192571886b2a52395f030d439c6259663a033e11e6aJayachandran C	/* Update reset entry point with CPU init code */
193571886b2a52395f030d439c6259663a033e11e6aJayachandran C	reset_vec = (void *)CKSEG1ADDR(RESET_VEC_PHYS);
194919f9abb3723f088290c62648b12fbfc7600d923Jayachandran C	memset(reset_vec, 0, RESET_VEC_SIZE);
195571886b2a52395f030d439c6259663a033e11e6aJayachandran C	memcpy(reset_vec, (void *)nlm_reset_entry,
196571886b2a52395f030d439c6259663a033e11e6aJayachandran C			(nlm_reset_entry_end - nlm_reset_entry));
197571886b2a52395f030d439c6259663a033e11e6aJayachandran C
1985c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C	build_arcs_cmdline(argv);
1995c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C	prom_add_memory();
2005c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C
2015c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C#ifdef CONFIG_SMP
2022a37b1ae443f20470a789b12a45cbc249c9e50a6Jayachandran C	for (i = 0; i < 32; i++)
2032a37b1ae443f20470a789b12a45cbc249c9e50a6Jayachandran C		if (nlm_prom_info.online_cpu_map & (1 << i))
2042a37b1ae443f20470a789b12a45cbc249c9e50a6Jayachandran C			cpumask_set_cpu(i, &nlm_cpumask);
2052a37b1ae443f20470a789b12a45cbc249c9e50a6Jayachandran C	nlm_wakeup_secondary_cpus();
2065c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C	register_smp_ops(&nlm_smp_ops);
2075c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C#endif
208ed21cfe207276e2d2883173399dd0380db372e18Ganesan Ramalingam	xlr_board_info_setup();
209ed21cfe207276e2d2883173399dd0380db372e18Ganesan Ramalingam	xlr_percpu_fmn_init();
2105c642506740ecbf20fb7a9e482287e4e5c639e5cJayachandran C}
211