Initial commit; kernel source import

This commit is contained in:
Nathan
2025-04-06 23:50:55 -05:00
commit 25c6d769f4
45093 changed files with 18199410 additions and 0 deletions

View File

@@ -0,0 +1,54 @@
if NLM_XLP_BOARD || NLM_XLR_BOARD
if NLM_XLP_BOARD
config DT_XLP_EVP
bool "Built-in device tree for XLP EVP boards"
default y
help
Add an FDT blob for XLP EVP boards into the kernel.
This DTB will be used if the firmware does not pass in a DTB
pointer to the kernel. The corresponding DTS file is at
arch/mips/netlogic/dts/xlp_evp.dts
config DT_XLP_SVP
bool "Built-in device tree for XLP SVP boards"
default y
help
Add an FDT blob for XLP VP boards into the kernel.
This DTB will be used if the firmware does not pass in a DTB
pointer to the kernel. The corresponding DTS file is at
arch/mips/netlogic/dts/xlp_svp.dts
config NLM_MULTINODE
bool "Support for multi-chip boards"
depends on NLM_XLP_BOARD
default n
help
Add support for boards with 2 or 4 XLPs connected over ICI.
if NLM_MULTINODE
choice
prompt "Number of XLPs on the board"
default NLM_MULTINODE_2
help
In the multi-node case, specify the number of SoCs on the board.
config NLM_MULTINODE_2
bool "Dual-XLP board"
help
Support boards with upto two XLPs connected over ICI.
config NLM_MULTINODE_4
bool "Quad-XLP board"
help
Support boards with upto four XLPs connected over ICI.
endchoice
endif
endif
config NLM_COMMON
bool
endif

View File

@@ -0,0 +1,4 @@
obj-$(CONFIG_NLM_COMMON) += common/
obj-$(CONFIG_CPU_XLR) += xlr/
obj-$(CONFIG_CPU_XLP) += xlp/
obj-$(CONFIG_CPU_XLP) += dts/

View File

@@ -0,0 +1,17 @@
#
# NETLOGIC includes
#
cflags-$(CONFIG_NLM_COMMON) += -I$(srctree)/arch/mips/include/asm/mach-netlogic
cflags-$(CONFIG_NLM_COMMON) += -I$(srctree)/arch/mips/include/asm/netlogic
#
# use mips64 if xlr is not available
#
cflags-$(CONFIG_CPU_XLR) += $(call cc-option,-march=xlr,-march=mips64)
cflags-$(CONFIG_CPU_XLP) += $(call cc-option,-march=xlp,-march=mips64r2)
#
# NETLOGIC processor support
#
platform-$(CONFIG_NLM_COMMON) += netlogic/
load-$(CONFIG_NLM_COMMON) += 0xffffffff80100000

View File

@@ -0,0 +1,3 @@
obj-y += irq.o time.o
obj-$(CONFIG_SMP) += smp.o smpboot.o
obj-$(CONFIG_EARLY_PRINTK) += earlycons.o

View File

@@ -0,0 +1,60 @@
/*
* Copyright 2003-2011 NetLogic Microsystems, Inc. (NetLogic). All rights
* reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
* General Public License (GPL) Version 2, available from the file
* COPYING in the main directory of this source tree, or the NetLogic
* license below:
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY NETLOGIC ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL NETLOGIC OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <linux/types.h>
#include <linux/serial_reg.h>
#include <asm/mipsregs.h>
#include <asm/netlogic/haldefs.h>
#if defined(CONFIG_CPU_XLP)
#include <asm/netlogic/xlp-hal/iomap.h>
#include <asm/netlogic/xlp-hal/uart.h>
#elif defined(CONFIG_CPU_XLR)
#include <asm/netlogic/xlr/iomap.h>
#endif
void prom_putchar(char c)
{
uint64_t uartbase;
#if defined(CONFIG_CPU_XLP)
uartbase = nlm_get_uart_regbase(0, 0);
#elif defined(CONFIG_CPU_XLR)
uartbase = nlm_mmio_base(NETLOGIC_IO_UART_0_OFFSET);
#endif
while ((nlm_read_reg(uartbase, UART_LSR) & UART_LSR_THRE) == 0)
;
nlm_write_reg(uartbase, UART_TX, c);
}

View File

@@ -0,0 +1,269 @@
/*
* Copyright 2003-2011 NetLogic Microsystems, Inc. (NetLogic). All rights
* reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
* General Public License (GPL) Version 2, available from the file
* COPYING in the main directory of this source tree, or the NetLogic
* license below:
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY NETLOGIC ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL NETLOGIC OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/linkage.h>
#include <linux/interrupt.h>
#include <linux/mm.h>
#include <linux/slab.h>
#include <linux/irq.h>
#include <asm/errno.h>
#include <asm/signal.h>
#include <asm/ptrace.h>
#include <asm/mipsregs.h>
#include <asm/thread_info.h>
#include <asm/netlogic/mips-extns.h>
#include <asm/netlogic/interrupt.h>
#include <asm/netlogic/haldefs.h>
#include <asm/netlogic/common.h>
#if defined(CONFIG_CPU_XLP)
#include <asm/netlogic/xlp-hal/iomap.h>
#include <asm/netlogic/xlp-hal/xlp.h>
#include <asm/netlogic/xlp-hal/pic.h>
#elif defined(CONFIG_CPU_XLR)
#include <asm/netlogic/xlr/iomap.h>
#include <asm/netlogic/xlr/pic.h>
#include <asm/netlogic/xlr/fmn.h>
#else
#error "Unknown CPU"
#endif
#ifdef CONFIG_SMP
#define SMP_IRQ_MASK ((1ULL << IRQ_IPI_SMP_FUNCTION) | \
(1ULL << IRQ_IPI_SMP_RESCHEDULE))
#else
#define SMP_IRQ_MASK 0
#endif
#define PERCPU_IRQ_MASK (SMP_IRQ_MASK | (1ull << IRQ_TIMER) | \
(1ull << IRQ_FMN))
struct nlm_pic_irq {
void (*extra_ack)(struct irq_data *);
struct nlm_soc_info *node;
int picirq;
int irt;
int flags;
};
static void xlp_pic_enable(struct irq_data *d)
{
unsigned long flags;
struct nlm_pic_irq *pd = irq_data_get_irq_handler_data(d);
BUG_ON(!pd);
spin_lock_irqsave(&pd->node->piclock, flags);
nlm_pic_enable_irt(pd->node->picbase, pd->irt);
spin_unlock_irqrestore(&pd->node->piclock, flags);
}
static void xlp_pic_disable(struct irq_data *d)
{
struct nlm_pic_irq *pd = irq_data_get_irq_handler_data(d);
unsigned long flags;
BUG_ON(!pd);
spin_lock_irqsave(&pd->node->piclock, flags);
nlm_pic_disable_irt(pd->node->picbase, pd->irt);
spin_unlock_irqrestore(&pd->node->piclock, flags);
}
static void xlp_pic_mask_ack(struct irq_data *d)
{
struct nlm_pic_irq *pd = irq_data_get_irq_handler_data(d);
clear_c0_eimr(pd->picirq);
ack_c0_eirr(pd->picirq);
}
static void xlp_pic_unmask(struct irq_data *d)
{
struct nlm_pic_irq *pd = irq_data_get_irq_handler_data(d);
BUG_ON(!pd);
if (pd->extra_ack)
pd->extra_ack(d);
/* re-enable the intr on this cpu */
set_c0_eimr(pd->picirq);
/* Ack is a single write, no need to lock */
nlm_pic_ack(pd->node->picbase, pd->irt);
}
static struct irq_chip xlp_pic = {
.name = "XLP-PIC",
.irq_enable = xlp_pic_enable,
.irq_disable = xlp_pic_disable,
.irq_mask_ack = xlp_pic_mask_ack,
.irq_unmask = xlp_pic_unmask,
};
static void cpuintr_disable(struct irq_data *d)
{
clear_c0_eimr(d->irq);
}
static void cpuintr_enable(struct irq_data *d)
{
set_c0_eimr(d->irq);
}
static void cpuintr_ack(struct irq_data *d)
{
ack_c0_eirr(d->irq);
}
/*
* Chip definition for CPU originated interrupts(timer, msg) and
* IPIs
*/
struct irq_chip nlm_cpu_intr = {
.name = "XLP-CPU-INTR",
.irq_enable = cpuintr_enable,
.irq_disable = cpuintr_disable,
.irq_mask = cpuintr_disable,
.irq_ack = cpuintr_ack,
.irq_eoi = cpuintr_enable,
};
static void __init nlm_init_percpu_irqs(void)
{
int i;
for (i = 0; i < PIC_IRT_FIRST_IRQ; i++)
irq_set_chip_and_handler(i, &nlm_cpu_intr, handle_percpu_irq);
#ifdef CONFIG_SMP
irq_set_chip_and_handler(IRQ_IPI_SMP_FUNCTION, &nlm_cpu_intr,
nlm_smp_function_ipi_handler);
irq_set_chip_and_handler(IRQ_IPI_SMP_RESCHEDULE, &nlm_cpu_intr,
nlm_smp_resched_ipi_handler);
#endif
}
void nlm_setup_pic_irq(int node, int picirq, int irq, int irt)
{
struct nlm_pic_irq *pic_data;
int xirq;
xirq = nlm_irq_to_xirq(node, irq);
pic_data = kzalloc(sizeof(*pic_data), GFP_KERNEL);
BUG_ON(pic_data == NULL);
pic_data->irt = irt;
pic_data->picirq = picirq;
pic_data->node = nlm_get_node(node);
irq_set_chip_and_handler(xirq, &xlp_pic, handle_level_irq);
irq_set_handler_data(xirq, pic_data);
}
void nlm_set_pic_extra_ack(int node, int irq, void (*xack)(struct irq_data *))
{
struct nlm_pic_irq *pic_data;
int xirq;
xirq = nlm_irq_to_xirq(node, irq);
pic_data = irq_get_handler_data(xirq);
pic_data->extra_ack = xack;
}
static void nlm_init_node_irqs(int node)
{
int i, irt;
uint64_t irqmask;
struct nlm_soc_info *nodep;
pr_info("Init IRQ for node %d\n", node);
nodep = nlm_get_node(node);
irqmask = PERCPU_IRQ_MASK;
for (i = PIC_IRT_FIRST_IRQ; i <= PIC_IRT_LAST_IRQ; i++) {
irt = nlm_irq_to_irt(i);
if (irt == -1)
continue;
nlm_setup_pic_irq(node, i, i, irt);
/* set interrupts to first cpu in node */
nlm_pic_init_irt(nodep->picbase, irt, i,
node * NLM_CPUS_PER_NODE, 0);
irqmask |= (1ull << i);
}
nodep->irqmask = irqmask;
}
void __init arch_init_irq(void)
{
/* Initialize the irq descriptors */
nlm_init_percpu_irqs();
nlm_init_node_irqs(0);
write_c0_eimr(nlm_current_node()->irqmask);
#if defined(CONFIG_CPU_XLR)
nlm_setup_fmn_irq();
#endif
}
void nlm_smp_irq_init(int hwcpuid)
{
int node, cpu;
node = hwcpuid / NLM_CPUS_PER_NODE;
cpu = hwcpuid % NLM_CPUS_PER_NODE;
if (cpu == 0 && node != 0)
nlm_init_node_irqs(node);
write_c0_eimr(nlm_current_node()->irqmask);
}
asmlinkage void plat_irq_dispatch(void)
{
uint64_t eirr;
int i, node;
node = nlm_nodeid();
eirr = read_c0_eirr_and_eimr();
i = __ilog2_u64(eirr);
if (i == -1)
return;
/* per-CPU IRQs don't need translation */
if (eirr & PERCPU_IRQ_MASK) {
do_IRQ(i);
return;
}
/* top level irq handling */
do_IRQ(nlm_irq_to_xirq(node, i));
}

View File

@@ -0,0 +1,290 @@
/*
* Copyright 2003-2011 NetLogic Microsystems, Inc. (NetLogic). All rights
* reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
* General Public License (GPL) Version 2, available from the file
* COPYING in the main directory of this source tree, or the NetLogic
* license below:
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY NETLOGIC ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL NETLOGIC OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/smp.h>
#include <linux/irq.h>
#include <asm/mmu_context.h>
#include <asm/netlogic/interrupt.h>
#include <asm/netlogic/mips-extns.h>
#include <asm/netlogic/haldefs.h>
#include <asm/netlogic/common.h>
#if defined(CONFIG_CPU_XLP)
#include <asm/netlogic/xlp-hal/iomap.h>
#include <asm/netlogic/xlp-hal/xlp.h>
#include <asm/netlogic/xlp-hal/pic.h>
#elif defined(CONFIG_CPU_XLR)
#include <asm/netlogic/xlr/iomap.h>
#include <asm/netlogic/xlr/pic.h>
#include <asm/netlogic/xlr/xlr.h>
#else
#error "Unknown CPU"
#endif
void nlm_send_ipi_single(int logical_cpu, unsigned int action)
{
int cpu, node;
uint64_t picbase;
cpu = cpu_logical_map(logical_cpu);
node = cpu / NLM_CPUS_PER_NODE;
picbase = nlm_get_node(node)->picbase;
if (action & SMP_CALL_FUNCTION)
nlm_pic_send_ipi(picbase, cpu, IRQ_IPI_SMP_FUNCTION, 0);
if (action & SMP_RESCHEDULE_YOURSELF)
nlm_pic_send_ipi(picbase, cpu, IRQ_IPI_SMP_RESCHEDULE, 0);
}
void nlm_send_ipi_mask(const struct cpumask *mask, unsigned int action)
{
int cpu;
for_each_cpu(cpu, mask) {
nlm_send_ipi_single(cpu, action);
}
}
/* IRQ_IPI_SMP_FUNCTION Handler */
void nlm_smp_function_ipi_handler(unsigned int irq, struct irq_desc *desc)
{
clear_c0_eimr(irq);
ack_c0_eirr(irq);
smp_call_function_interrupt();
set_c0_eimr(irq);
}
/* IRQ_IPI_SMP_RESCHEDULE handler */
void nlm_smp_resched_ipi_handler(unsigned int irq, struct irq_desc *desc)
{
clear_c0_eimr(irq);
ack_c0_eirr(irq);
scheduler_ipi();
set_c0_eimr(irq);
}
/*
* Called before going into mips code, early cpu init
*/
void nlm_early_init_secondary(int cpu)
{
change_c0_config(CONF_CM_CMASK, 0x3);
#ifdef CONFIG_CPU_XLP
/* mmu init, once per core */
if (cpu % NLM_THREADS_PER_CORE == 0)
xlp_mmu_init();
#endif
write_c0_ebase(nlm_current_node()->ebase);
}
/*
* Code to run on secondary just after probing the CPU
*/
static void __cpuinit nlm_init_secondary(void)
{
int hwtid;
hwtid = hard_smp_processor_id();
current_cpu_data.core = hwtid / NLM_THREADS_PER_CORE;
nlm_percpu_init(hwtid);
nlm_smp_irq_init(hwtid);
}
void nlm_prepare_cpus(unsigned int max_cpus)
{
/* declare we are SMT capable */
smp_num_siblings = nlm_threads_per_core;
}
void nlm_smp_finish(void)
{
local_irq_enable();
}
void nlm_cpus_done(void)
{
}
/*
* Boot all other cpus in the system, initialize them, and bring them into
* the boot function
*/
int nlm_cpu_ready[NR_CPUS];
unsigned long nlm_next_gp;
unsigned long nlm_next_sp;
static cpumask_t phys_cpu_present_mask;
void nlm_boot_secondary(int logical_cpu, struct task_struct *idle)
{
int cpu, node;
cpu = cpu_logical_map(logical_cpu);
node = cpu / NLM_CPUS_PER_NODE;
nlm_next_sp = (unsigned long)__KSTK_TOS(idle);
nlm_next_gp = (unsigned long)task_thread_info(idle);
/* barrier for sp/gp store above */
__sync();
nlm_pic_send_ipi(nlm_get_node(node)->picbase, cpu, 1, 1); /* NMI */
}
void __init nlm_smp_setup(void)
{
unsigned int boot_cpu;
int num_cpus, i, ncore;
char buf[64];
boot_cpu = hard_smp_processor_id();
cpumask_clear(&phys_cpu_present_mask);
cpumask_set_cpu(boot_cpu, &phys_cpu_present_mask);
__cpu_number_map[boot_cpu] = 0;
__cpu_logical_map[0] = boot_cpu;
set_cpu_possible(0, true);
num_cpus = 1;
for (i = 0; i < NR_CPUS; i++) {
/*
* nlm_cpu_ready array is not set for the boot_cpu,
* it is only set for ASPs (see smpboot.S)
*/
if (nlm_cpu_ready[i]) {
cpumask_set_cpu(i, &phys_cpu_present_mask);
__cpu_number_map[i] = num_cpus;
__cpu_logical_map[num_cpus] = i;
set_cpu_possible(num_cpus, true);
++num_cpus;
}
}
cpumask_scnprintf(buf, ARRAY_SIZE(buf), &phys_cpu_present_mask);
pr_info("Physical CPU mask: %s\n", buf);
cpumask_scnprintf(buf, ARRAY_SIZE(buf), cpu_possible_mask);
pr_info("Possible CPU mask: %s\n", buf);
/* check with the cores we have worken up */
for (ncore = 0, i = 0; i < NLM_NR_NODES; i++)
ncore += hweight32(nlm_get_node(i)->coremask);
pr_info("Detected (%dc%dt) %d Slave CPU(s)\n", ncore,
nlm_threads_per_core, num_cpus);
/* switch NMI handler to boot CPUs */
nlm_set_nmi_handler(nlm_boot_secondary_cpus);
}
static int nlm_parse_cpumask(cpumask_t *wakeup_mask)
{
uint32_t core0_thr_mask, core_thr_mask;
int threadmode, i, j;
core0_thr_mask = 0;
for (i = 0; i < NLM_THREADS_PER_CORE; i++)
if (cpumask_test_cpu(i, wakeup_mask))
core0_thr_mask |= (1 << i);
switch (core0_thr_mask) {
case 1:
nlm_threads_per_core = 1;
threadmode = 0;
break;
case 3:
nlm_threads_per_core = 2;
threadmode = 2;
break;
case 0xf:
nlm_threads_per_core = 4;
threadmode = 3;
break;
default:
goto unsupp;
}
/* Verify other cores CPU masks */
for (i = 0; i < NR_CPUS; i += NLM_THREADS_PER_CORE) {
core_thr_mask = 0;
for (j = 0; j < NLM_THREADS_PER_CORE; j++)
if (cpumask_test_cpu(i + j, wakeup_mask))
core_thr_mask |= (1 << j);
if (core_thr_mask != 0 && core_thr_mask != core0_thr_mask)
goto unsupp;
}
return threadmode;
unsupp:
panic("Unsupported CPU mask %lx\n",
(unsigned long)cpumask_bits(wakeup_mask)[0]);
return 0;
}
int __cpuinit nlm_wakeup_secondary_cpus(void)
{
unsigned long reset_vec;
char *reset_data;
int threadmode;
/* Update reset entry point with CPU init code */
reset_vec = CKSEG1ADDR(RESET_VEC_PHYS);
memcpy((void *)reset_vec, (void *)nlm_reset_entry,
(nlm_reset_entry_end - nlm_reset_entry));
/* verify the mask and setup core config variables */
threadmode = nlm_parse_cpumask(&nlm_cpumask);
/* Setup CPU init parameters */
reset_data = (char *)CKSEG1ADDR(RESET_DATA_PHYS);
*(int *)(reset_data + BOOT_THREAD_MODE) = threadmode;
#ifdef CONFIG_CPU_XLP
xlp_wakeup_secondary_cpus();
#else
xlr_wakeup_secondary_cpus();
#endif
return 0;
}
struct plat_smp_ops nlm_smp_ops = {
.send_ipi_single = nlm_send_ipi_single,
.send_ipi_mask = nlm_send_ipi_mask,
.init_secondary = nlm_init_secondary,
.smp_finish = nlm_smp_finish,
.cpus_done = nlm_cpus_done,
.boot_secondary = nlm_boot_secondary,
.smp_setup = nlm_smp_setup,
.prepare_cpus = nlm_prepare_cpus,
};

View File

@@ -0,0 +1,327 @@
/*
* Copyright 2003-2011 NetLogic Microsystems, Inc. (NetLogic). All rights
* reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
* General Public License (GPL) Version 2, available from the file
* COPYING in the main directory of this source tree, or the NetLogic
* license below:
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY NETLOGIC ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL NETLOGIC OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <linux/init.h>
#include <asm/asm.h>
#include <asm/asm-offsets.h>
#include <asm/regdef.h>
#include <asm/mipsregs.h>
#include <asm/stackframe.h>
#include <asm/asmmacro.h>
#include <asm/addrspace.h>
#include <asm/netlogic/common.h>
#include <asm/netlogic/xlp-hal/iomap.h>
#include <asm/netlogic/xlp-hal/xlp.h>
#include <asm/netlogic/xlp-hal/sys.h>
#include <asm/netlogic/xlp-hal/cpucontrol.h>
#define CP0_EBASE $15
#define SYS_CPU_COHERENT_BASE(node) CKSEG1ADDR(XLP_DEFAULT_IO_BASE) + \
XLP_IO_SYS_OFFSET(node) + XLP_IO_PCI_HDRSZ + \
SYS_CPU_NONCOHERENT_MODE * 4
#define XLP_AX_WORKAROUND /* enable Ax silicon workarounds */
/* Enable XLP features and workarounds in the LSU */
.macro xlp_config_lsu
li t0, LSU_DEFEATURE
mfcr t1, t0
lui t2, 0xc080 /* SUE, Enable Unaligned Access, L2HPE */
or t1, t1, t2
#ifdef XLP_AX_WORKAROUND
li t2, ~0xe /* S1RCM */
and t1, t1, t2
#endif
mtcr t1, t0
li t0, ICU_DEFEATURE
mfcr t1, t0
ori t1, 0x1000 /* Enable Icache partitioning */
mtcr t1, t0
#ifdef XLP_AX_WORKAROUND
li t0, SCHED_DEFEATURE
lui t1, 0x0100 /* Disable BRU accepting ALU ops */
mtcr t1, t0
#endif
.endm
/*
* This is the code that will be copied to the reset entry point for
* XLR and XLP. The XLP cores start here when they are woken up. This
* is also the NMI entry point.
*/
.macro xlp_flush_l1_dcache
li t0, LSU_DEBUG_DATA0
li t1, LSU_DEBUG_ADDR
li t2, 0 /* index */
li t3, 0x1000 /* loop count */
1:
sll v0, t2, 5
mtcr zero, t0
ori v1, v0, 0x3 /* way0 | write_enable | write_active */
mtcr v1, t1
2:
mfcr v1, t1
andi v1, 0x1 /* wait for write_active == 0 */
bnez v1, 2b
nop
mtcr zero, t0
ori v1, v0, 0x7 /* way1 | write_enable | write_active */
mtcr v1, t1
3:
mfcr v1, t1
andi v1, 0x1 /* wait for write_active == 0 */
bnez v1, 3b
nop
addi t2, 1
bne t3, t2, 1b
nop
.endm
/*
* The cores can come start when they are woken up. This is also the NMI
* entry, so check that first.
*
* The data corresponding to reset/NMI is stored at RESET_DATA_PHYS
* location, this will have the thread mask (used when core is woken up)
* and the current NMI handler in case we reached here for an NMI.
*
* When a core or thread is newly woken up, it loops in a 'wait'. When
* the CPU really needs waking up, we send an NMI to it, with the NMI
* handler set to prom_boot_secondary_cpus
*/
.set noreorder
.set noat
.set arch=xlr /* for mfcr/mtcr, XLR is sufficient */
FEXPORT(nlm_reset_entry)
dmtc0 k0, $22, 6
dmtc0 k1, $22, 7
mfc0 k0, CP0_STATUS
li k1, 0x80000
and k1, k0, k1
beqz k1, 1f /* go to real reset entry */
nop
li k1, CKSEG1ADDR(RESET_DATA_PHYS) /* NMI */
ld k0, BOOT_NMI_HANDLER(k1)
jr k0
nop
1: /* Entry point on core wakeup */
mfc0 t0, CP0_EBASE, 1
mfc0 t1, CP0_EBASE, 1
srl t1, 5
andi t1, 0x3 /* t1 <- node */
li t2, 0x40000
mul t3, t2, t1 /* t3 = node * 0x40000 */
srl t0, t0, 2
and t0, t0, 0x7 /* t0 <- core */
li t1, 0x1
sll t0, t1, t0
nor t0, t0, zero /* t0 <- ~(1 << core) */
li t2, SYS_CPU_COHERENT_BASE(0)
add t2, t2, t3 /* t2 <- SYS offset for node */
lw t1, 0(t2)
and t1, t1, t0
sw t1, 0(t2)
/* read back to ensure complete */
lw t1, 0(t2)
sync
/* Configure LSU on Non-0 Cores. */
xlp_config_lsu
/* FALL THROUGH */
/*
* Wake up sibling threads from the initial thread in
* a core.
*/
EXPORT(nlm_boot_siblings)
/* core L1D flush before enable threads */
xlp_flush_l1_dcache
/* Enable hw threads by writing to MAP_THREADMODE of the core */
li t0, CKSEG1ADDR(RESET_DATA_PHYS)
lw t1, BOOT_THREAD_MODE(t0) /* t1 <- thread mode */
li t0, ((CPU_BLOCKID_MAP << 8) | MAP_THREADMODE)
mfcr t2, t0
or t2, t2, t1
mtcr t2, t0
/*
* The new hardware thread starts at the next instruction
* For all the cases other than core 0 thread 0, we will
* jump to the secondary wait function.
*/
mfc0 v0, CP0_EBASE, 1
andi v0, 0x3ff /* v0 <- node/core */
/* Init MMU in the first thread after changing THREAD_MODE
* register (Ax Errata?)
*/
andi v1, v0, 0x3 /* v1 <- thread id */
bnez v1, 2f
nop
li t0, MMU_SETUP
li t1, 0
mtcr t1, t0
_ehb
2: beqz v0, 4f /* boot cpu (cpuid == 0)? */
nop
/* setup status reg */
move t1, zero
#ifdef CONFIG_64BIT
ori t1, ST0_KX
#endif
mtc0 t1, CP0_STATUS
/* mark CPU ready */
PTR_LA t1, nlm_cpu_ready
sll v1, v0, 2
PTR_ADDU t1, v1
li t2, 1
sw t2, 0(t1)
/* Wait until NMI hits */
3: wait
j 3b
nop
/*
* For the boot CPU, we have to restore registers and
* return
*/
4: dmfc0 t0, $4, 2 /* restore SP from UserLocal */
li t1, 0xfadebeef
dmtc0 t1, $4, 2 /* restore SP from UserLocal */
PTR_SUBU sp, t0, PT_SIZE
RESTORE_ALL
jr ra
nop
EXPORT(nlm_reset_entry_end)
FEXPORT(xlp_boot_core0_siblings) /* "Master" cpu starts from here */
xlp_config_lsu
dmtc0 sp, $4, 2 /* SP saved in UserLocal */
SAVE_ALL
sync
/* find the location to which nlm_boot_siblings was relocated */
li t0, CKSEG1ADDR(RESET_VEC_PHYS)
dla t1, nlm_reset_entry
dla t2, nlm_boot_siblings
dsubu t2, t1
daddu t2, t0
/* call it */
jr t2
nop
/* not reached */
__CPUINIT
NESTED(nlm_boot_secondary_cpus, 16, sp)
/* Initialize CP0 Status */
move t1, zero
#ifdef CONFIG_64BIT
ori t1, ST0_KX
#endif
mtc0 t1, CP0_STATUS
PTR_LA t1, nlm_next_sp
PTR_L sp, 0(t1)
PTR_LA t1, nlm_next_gp
PTR_L gp, 0(t1)
/* a0 has the processor id */
mfc0 a0, CP0_EBASE, 1
andi a0, 0x3ff /* a0 <- node/core */
PTR_LA t0, nlm_early_init_secondary
jalr t0
nop
PTR_LA t0, smp_bootstrap
jr t0
nop
END(nlm_boot_secondary_cpus)
__FINIT
/*
* In case of RMIboot bootloader which is used on XLR boards, the CPUs
* be already woken up and waiting in bootloader code.
* This will get them out of the bootloader code and into linux. Needed
* because the bootloader area will be taken and initialized by linux.
*/
__CPUINIT
NESTED(nlm_rmiboot_preboot, 16, sp)
mfc0 t0, $15, 1 /* read ebase */
andi t0, 0x1f /* t0 has the processor_id() */
andi t2, t0, 0x3 /* thread num */
sll t0, 2 /* offset in cpu array */
PTR_LA t1, nlm_cpu_ready /* mark CPU ready */
PTR_ADDU t1, t0
li t3, 1
sw t3, 0(t1)
bnez t2, 1f /* skip thread programming */
nop /* for thread id != 0 */
/*
* XLR MMU setup only for first thread in core
*/
li t0, 0x400
mfcr t1, t0
li t2, 6 /* XLR thread mode mask */
nor t3, t2, zero
and t2, t1, t2 /* t2 - current thread mode */
li v0, CKSEG1ADDR(RESET_DATA_PHYS)
lw v1, BOOT_THREAD_MODE(v0) /* v1 - new thread mode */
sll v1, 1
beq v1, t2, 1f /* same as request value */
nop /* nothing to do */
and t2, t1, t3 /* mask out old thread mode */
or t1, t2, v1 /* put in new value */
mtcr t1, t0 /* update core control */
1: wait
j 1b
nop
END(nlm_rmiboot_preboot)
__FINIT

View File

@@ -0,0 +1,107 @@
/*
* Copyright 2003-2011 NetLogic Microsystems, Inc. (NetLogic). All rights
* reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
* General Public License (GPL) Version 2, available from the file
* COPYING in the main directory of this source tree, or the NetLogic
* license below:
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY NETLOGIC ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL NETLOGIC OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <linux/init.h>
#include <asm/time.h>
#include <asm/cpu-features.h>
#include <asm/netlogic/interrupt.h>
#include <asm/netlogic/common.h>
#include <asm/netlogic/haldefs.h>
#include <asm/netlogic/common.h>
#if defined(CONFIG_CPU_XLP)
#include <asm/netlogic/xlp-hal/iomap.h>
#include <asm/netlogic/xlp-hal/xlp.h>
#include <asm/netlogic/xlp-hal/pic.h>
#elif defined(CONFIG_CPU_XLR)
#include <asm/netlogic/xlr/iomap.h>
#include <asm/netlogic/xlr/pic.h>
#include <asm/netlogic/xlr/xlr.h>
#else
#error "Unknown CPU"
#endif
unsigned int __cpuinit get_c0_compare_int(void)
{
return IRQ_TIMER;
}
static cycle_t nlm_get_pic_timer(struct clocksource *cs)
{
uint64_t picbase = nlm_get_node(0)->picbase;
return ~nlm_pic_read_timer(picbase, PIC_CLOCK_TIMER);
}
static cycle_t nlm_get_pic_timer32(struct clocksource *cs)
{
uint64_t picbase = nlm_get_node(0)->picbase;
return ~nlm_pic_read_timer32(picbase, PIC_CLOCK_TIMER);
}
static struct clocksource csrc_pic = {
.name = "PIC",
.flags = CLOCK_SOURCE_IS_CONTINUOUS,
};
static void nlm_init_pic_timer(void)
{
uint64_t picbase = nlm_get_node(0)->picbase;
nlm_pic_set_timer(picbase, PIC_CLOCK_TIMER, ~0ULL, 0, 0);
if (current_cpu_data.cputype == CPU_XLR) {
csrc_pic.mask = CLOCKSOURCE_MASK(32);
csrc_pic.read = nlm_get_pic_timer32;
} else {
csrc_pic.mask = CLOCKSOURCE_MASK(64);
csrc_pic.read = nlm_get_pic_timer;
}
csrc_pic.rating = 1000;
clocksource_register_hz(&csrc_pic, PIC_CLK_HZ);
}
void __init plat_time_init(void)
{
nlm_init_pic_timer();
mips_hpt_frequency = nlm_get_cpu_frequency();
if (current_cpu_type() == CPU_XLR)
preset_lpj = mips_hpt_frequency / (3 * HZ);
else
preset_lpj = mips_hpt_frequency / (2 * HZ);
pr_info("MIPS counter frequency [%ld]\n",
(unsigned long)mips_hpt_frequency);
}

View File

@@ -0,0 +1,2 @@
obj-$(CONFIG_DT_XLP_EVP) := xlp_evp.dtb.o
obj-$(CONFIG_DT_XLP_SVP) += xlp_svp.dtb.o

View File

@@ -0,0 +1,124 @@
/*
* XLP8XX Device Tree Source for EVP boards
*/
/dts-v1/;
/ {
model = "netlogic,XLP-EVP";
compatible = "netlogic,xlp";
#address-cells = <2>;
#size-cells = <2>;
memory {
device_type = "memory";
reg = <0 0x00100000 0 0x0FF00000 // 255M at 1M
0 0x20000000 0 0xa0000000 // 2560M at 512M
0 0xe0000000 1 0x00000000>;
};
soc {
#address-cells = <2>;
#size-cells = <1>;
compatible = "simple-bus";
ranges = <0 0 0 0x18000000 0x04000000 // PCIe CFG
1 0 0 0x16000000 0x01000000>; // GBU chipselects
serial0: serial@30000 {
device_type = "serial";
compatible = "ns16550";
reg = <0 0x30100 0xa00>;
reg-shift = <2>;
reg-io-width = <4>;
clock-frequency = <133333333>;
interrupt-parent = <&pic>;
interrupts = <17>;
};
serial1: serial@31000 {
device_type = "serial";
compatible = "ns16550";
reg = <0 0x31100 0xa00>;
reg-shift = <2>;
reg-io-width = <4>;
clock-frequency = <133333333>;
interrupt-parent = <&pic>;
interrupts = <18>;
};
i2c0: ocores@32000 {
compatible = "opencores,i2c-ocores";
#address-cells = <1>;
#size-cells = <0>;
reg = <0 0x32100 0xa00>;
reg-shift = <2>;
reg-io-width = <4>;
clock-frequency = <32000000>;
interrupt-parent = <&pic>;
interrupts = <30>;
};
i2c1: ocores@33000 {
compatible = "opencores,i2c-ocores";
#address-cells = <1>;
#size-cells = <0>;
reg = <0 0x33100 0xa00>;
reg-shift = <2>;
reg-io-width = <4>;
clock-frequency = <32000000>;
interrupt-parent = <&pic>;
interrupts = <31>;
rtc@68 {
compatible = "dallas,ds1374";
reg = <0x68>;
};
dtt@4c {
compatible = "national,lm90";
reg = <0x4c>;
};
};
pic: pic@4000 {
interrupt-controller;
#address-cells = <0>;
#interrupt-cells = <1>;
reg = <0 0x4000 0x200>;
};
nor_flash@1,0 {
compatible = "cfi-flash";
#address-cells = <1>;
#size-cells = <1>;
bank-width = <2>;
reg = <1 0 0x1000000>;
partition@0 {
label = "x-loader";
reg = <0x0 0x100000>; /* 1M */
read-only;
};
partition@100000 {
label = "u-boot";
reg = <0x100000 0x100000>; /* 1M */
};
partition@200000 {
label = "kernel";
reg = <0x200000 0x500000>; /* 5M */
};
partition@700000 {
label = "rootfs";
reg = <0x700000 0x800000>; /* 8M */
};
partition@f00000 {
label = "env";
reg = <0xf00000 0x100000>; /* 1M */
read-only;
};
};
};
chosen {
bootargs = "console=ttyS0,115200 rdinit=/sbin/init";
};
};

View File

@@ -0,0 +1,124 @@
/*
* XLP3XX Device Tree Source for SVP boards
*/
/dts-v1/;
/ {
model = "netlogic,XLP-SVP";
compatible = "netlogic,xlp";
#address-cells = <2>;
#size-cells = <2>;
memory {
device_type = "memory";
reg = <0 0x00100000 0 0x0FF00000 // 255M at 1M
0 0x20000000 0 0xa0000000 // 2560M at 512M
0 0xe0000000 0 0x40000000>;
};
soc {
#address-cells = <2>;
#size-cells = <1>;
compatible = "simple-bus";
ranges = <0 0 0 0x18000000 0x04000000 // PCIe CFG
1 0 0 0x16000000 0x01000000>; // GBU chipselects
serial0: serial@30000 {
device_type = "serial";
compatible = "ns16550";
reg = <0 0x30100 0xa00>;
reg-shift = <2>;
reg-io-width = <4>;
clock-frequency = <133333333>;
interrupt-parent = <&pic>;
interrupts = <17>;
};
serial1: serial@31000 {
device_type = "serial";
compatible = "ns16550";
reg = <0 0x31100 0xa00>;
reg-shift = <2>;
reg-io-width = <4>;
clock-frequency = <133333333>;
interrupt-parent = <&pic>;
interrupts = <18>;
};
i2c0: ocores@32000 {
compatible = "opencores,i2c-ocores";
#address-cells = <1>;
#size-cells = <0>;
reg = <0 0x32100 0xa00>;
reg-shift = <2>;
reg-io-width = <4>;
clock-frequency = <32000000>;
interrupt-parent = <&pic>;
interrupts = <30>;
};
i2c1: ocores@33000 {
compatible = "opencores,i2c-ocores";
#address-cells = <1>;
#size-cells = <0>;
reg = <0 0x33100 0xa00>;
reg-shift = <2>;
reg-io-width = <4>;
clock-frequency = <32000000>;
interrupt-parent = <&pic>;
interrupts = <31>;
rtc@68 {
compatible = "dallas,ds1374";
reg = <0x68>;
};
dtt@4c {
compatible = "national,lm90";
reg = <0x4c>;
};
};
pic: pic@4000 {
interrupt-controller;
#address-cells = <0>;
#interrupt-cells = <1>;
reg = <0 0x4000 0x200>;
};
nor_flash@1,0 {
compatible = "cfi-flash";
#address-cells = <1>;
#size-cells = <1>;
bank-width = <2>;
reg = <1 0 0x1000000>;
partition@0 {
label = "x-loader";
reg = <0x0 0x100000>; /* 1M */
read-only;
};
partition@100000 {
label = "u-boot";
reg = <0x100000 0x100000>; /* 1M */
};
partition@200000 {
label = "kernel";
reg = <0x200000 0x500000>; /* 5M */
};
partition@700000 {
label = "rootfs";
reg = <0x700000 0x800000>; /* 8M */
};
partition@f00000 {
label = "env";
reg = <0xf00000 0x100000>; /* 1M */
read-only;
};
};
};
chosen {
bootargs = "console=ttyS0,115200 rdinit=/sbin/init";
};
};

View File

@@ -0,0 +1,3 @@
obj-y += setup.o nlm_hal.o
obj-$(CONFIG_SMP) += wakeup.o
obj-$(CONFIG_USB) += usb-init.o

View File

@@ -0,0 +1,144 @@
/*
* Copyright 2003-2011 NetLogic Microsystems, Inc. (NetLogic). All rights
* reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
* General Public License (GPL) Version 2, available from the file
* COPYING in the main directory of this source tree, or the NetLogic
* license below:
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY NETLOGIC ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL NETLOGIC OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/delay.h>
#include <asm/mipsregs.h>
#include <asm/time.h>
#include <asm/netlogic/common.h>
#include <asm/netlogic/haldefs.h>
#include <asm/netlogic/xlp-hal/iomap.h>
#include <asm/netlogic/xlp-hal/xlp.h>
#include <asm/netlogic/xlp-hal/pic.h>
#include <asm/netlogic/xlp-hal/sys.h>
/* Main initialization */
void nlm_node_init(int node)
{
struct nlm_soc_info *nodep;
nodep = nlm_get_node(node);
nodep->sysbase = nlm_get_sys_regbase(node);
nodep->picbase = nlm_get_pic_regbase(node);
nodep->ebase = read_c0_ebase() & (~((1 << 12) - 1));
spin_lock_init(&nodep->piclock);
}
int nlm_irq_to_irt(int irq)
{
uint64_t pcibase;
int devoff, irt;
switch (irq) {
case PIC_UART_0_IRQ:
devoff = XLP_IO_UART0_OFFSET(0);
break;
case PIC_UART_1_IRQ:
devoff = XLP_IO_UART1_OFFSET(0);
break;
case PIC_EHCI_0_IRQ:
devoff = XLP_IO_USB_EHCI0_OFFSET(0);
break;
case PIC_EHCI_1_IRQ:
devoff = XLP_IO_USB_EHCI1_OFFSET(0);
break;
case PIC_OHCI_0_IRQ:
devoff = XLP_IO_USB_OHCI0_OFFSET(0);
break;
case PIC_OHCI_1_IRQ:
devoff = XLP_IO_USB_OHCI1_OFFSET(0);
break;
case PIC_OHCI_2_IRQ:
devoff = XLP_IO_USB_OHCI2_OFFSET(0);
break;
case PIC_OHCI_3_IRQ:
devoff = XLP_IO_USB_OHCI3_OFFSET(0);
break;
case PIC_MMC_IRQ:
devoff = XLP_IO_SD_OFFSET(0);
break;
case PIC_I2C_0_IRQ:
devoff = XLP_IO_I2C0_OFFSET(0);
break;
case PIC_I2C_1_IRQ:
devoff = XLP_IO_I2C1_OFFSET(0);
break;
default:
devoff = 0;
break;
}
if (devoff != 0) {
pcibase = nlm_pcicfg_base(devoff);
irt = nlm_read_reg(pcibase, XLP_PCI_IRTINFO_REG) & 0xffff;
/* HW bug, I2C 1 irt entry is off by one */
if (irq == PIC_I2C_1_IRQ)
irt = irt + 1;
} else if (irq >= PIC_PCIE_LINK_0_IRQ && irq <= PIC_PCIE_LINK_3_IRQ) {
/* HW bug, PCI IRT entries are bad on early silicon, fix */
irt = PIC_IRT_PCIE_LINK_INDEX(irq - PIC_PCIE_LINK_0_IRQ);
} else {
irt = -1;
}
return irt;
}
unsigned int nlm_get_core_frequency(int node, int core)
{
unsigned int pll_divf, pll_divr, dfs_div, ext_div;
unsigned int rstval, dfsval, denom;
uint64_t num, sysbase;
sysbase = nlm_get_node(node)->sysbase;
rstval = nlm_read_sys_reg(sysbase, SYS_POWER_ON_RESET_CFG);
dfsval = nlm_read_sys_reg(sysbase, SYS_CORE_DFS_DIV_VALUE);
pll_divf = ((rstval >> 10) & 0x7f) + 1;
pll_divr = ((rstval >> 8) & 0x3) + 1;
ext_div = ((rstval >> 30) & 0x3) + 1;
dfs_div = ((dfsval >> (core * 4)) & 0xf) + 1;
num = 800000000ULL * pll_divf;
denom = 3 * pll_divr * ext_div * dfs_div;
do_div(num, denom);
return (unsigned int)num;
}
unsigned int nlm_get_cpu_frequency(void)
{
return nlm_get_core_frequency(0, 0);
}

View File

@@ -0,0 +1,180 @@
/*
* Copyright 2003-2011 NetLogic Microsystems, Inc. (NetLogic). All rights
* reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
* General Public License (GPL) Version 2, available from the file
* COPYING in the main directory of this source tree, or the NetLogic
* license below:
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY NETLOGIC ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL NETLOGIC OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <linux/kernel.h>
#include <linux/serial_8250.h>
#include <linux/pm.h>
#include <linux/bootmem.h>
#include <asm/idle.h>
#include <asm/reboot.h>
#include <asm/time.h>
#include <asm/bootinfo.h>
#include <linux/of_fdt.h>
#include <linux/of_platform.h>
#include <linux/of_device.h>
#include <asm/netlogic/haldefs.h>
#include <asm/netlogic/common.h>
#include <asm/netlogic/xlp-hal/iomap.h>
#include <asm/netlogic/xlp-hal/xlp.h>
#include <asm/netlogic/xlp-hal/sys.h>
uint64_t nlm_io_base;
struct nlm_soc_info nlm_nodes[NLM_NR_NODES];
cpumask_t nlm_cpumask = CPU_MASK_CPU0;
unsigned int nlm_threads_per_core;
extern u32 __dtb_xlp_evp_begin[], __dtb_xlp_svp_begin[], __dtb_start[];
static void nlm_linux_exit(void)
{
uint64_t sysbase = nlm_get_node(0)->sysbase;
nlm_write_sys_reg(sysbase, SYS_CHIP_RESET, 1);
for ( ; ; )
cpu_wait();
}
void __init plat_mem_setup(void)
{
void *fdtp;
panic_timeout = 5;
_machine_restart = (void (*)(char *))nlm_linux_exit;
_machine_halt = nlm_linux_exit;
pm_power_off = nlm_linux_exit;
/*
* If no FDT pointer is passed in, use the built-in FDT.
* device_tree_init() does not handle CKSEG0 pointers in
* 64-bit, so convert pointer.
*/
fdtp = (void *)(long)fw_arg0;
if (!fdtp) {
switch (current_cpu_data.processor_id & 0xff00) {
#ifdef CONFIG_DT_XLP_SVP
case PRID_IMP_NETLOGIC_XLP3XX:
fdtp = __dtb_xlp_svp_begin;
break;
#endif
#ifdef CONFIG_DT_XLP_EVP
case PRID_IMP_NETLOGIC_XLP8XX:
fdtp = __dtb_xlp_evp_begin;
break;
#endif
default:
/* Pick a built-in if any, and hope for the best */
fdtp = __dtb_start;
break;
}
}
fdtp = phys_to_virt(__pa(fdtp));
early_init_devtree(fdtp);
}
const char *get_system_type(void)
{
return "Netlogic XLP Series";
}
void __init prom_free_prom_memory(void)
{
/* Nothing yet */
}
void xlp_mmu_init(void)
{
/* enable extended TLB and Large Fixed TLB */
write_c0_config6(read_c0_config6() | 0x24);
/* set page mask of Fixed TLB in config7 */
write_c0_config7(PM_DEFAULT_MASK >>
(13 + (ffz(PM_DEFAULT_MASK >> 13) / 2)));
}
void nlm_percpu_init(int hwcpuid)
{
}
void __init prom_init(void)
{
nlm_io_base = CKSEG1ADDR(XLP_DEFAULT_IO_BASE);
xlp_mmu_init();
nlm_node_init(0);
#ifdef CONFIG_SMP
cpumask_setall(&nlm_cpumask);
nlm_wakeup_secondary_cpus();
/* update TLB size after waking up threads */
current_cpu_data.tlbsize = ((read_c0_config6() >> 16) & 0xffff) + 1;
register_smp_ops(&nlm_smp_ops);
#endif
}
void __init device_tree_init(void)
{
unsigned long base, size;
if (!initial_boot_params)
return;
base = virt_to_phys((void *)initial_boot_params);
size = be32_to_cpu(initial_boot_params->totalsize);
/* Before we do anything, lets reserve the dt blob */
reserve_bootmem(base, size, BOOTMEM_DEFAULT);
unflatten_device_tree();
/* free the space reserved for the dt blob */
free_bootmem(base, size);
}
static struct of_device_id __initdata xlp_ids[] = {
{ .compatible = "simple-bus", },
{},
};
int __init xlp8xx_ds_publish_devices(void)
{
if (!of_have_populated_dt())
return 0;
return of_platform_bus_probe(NULL, xlp_ids, NULL);
}
device_initcall(xlp8xx_ds_publish_devices);

View File

@@ -0,0 +1,147 @@
/*
* Copyright (c) 2003-2012 Broadcom Corporation
* All Rights Reserved
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
* General Public License (GPL) Version 2, available from the file
* COPYING in the main directory of this source tree, or the Broadcom
* license below:
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY BROADCOM ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL BROADCOM OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <linux/dma-mapping.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/pci.h>
#include <linux/platform_device.h>
#include <asm/netlogic/haldefs.h>
#include <asm/netlogic/xlp-hal/iomap.h>
#include <asm/netlogic/xlp-hal/xlp.h>
/*
* USB glue logic registers, used only during initialization
*/
#define USB_CTL_0 0x01
#define USB_PHY_0 0x0A
#define USB_PHY_RESET 0x01
#define USB_PHY_PORT_RESET_0 0x10
#define USB_PHY_PORT_RESET_1 0x20
#define USB_CONTROLLER_RESET 0x01
#define USB_INT_STATUS 0x0E
#define USB_INT_EN 0x0F
#define USB_PHY_INTERRUPT_EN 0x01
#define USB_OHCI_INTERRUPT_EN 0x02
#define USB_OHCI_INTERRUPT1_EN 0x04
#define USB_OHCI_INTERRUPT2_EN 0x08
#define USB_CTRL_INTERRUPT_EN 0x10
#define nlm_read_usb_reg(b, r) nlm_read_reg(b, r)
#define nlm_write_usb_reg(b, r, v) nlm_write_reg(b, r, v)
#define nlm_get_usb_pcibase(node, inst) \
nlm_pcicfg_base(XLP_IO_USB_OFFSET(node, inst))
#define nlm_get_usb_regbase(node, inst) \
(nlm_get_usb_pcibase(node, inst) + XLP_IO_PCI_HDRSZ)
static void nlm_usb_intr_en(int node, int port)
{
uint32_t val;
uint64_t port_addr;
port_addr = nlm_get_usb_regbase(node, port);
val = nlm_read_usb_reg(port_addr, USB_INT_EN);
val = USB_CTRL_INTERRUPT_EN | USB_OHCI_INTERRUPT_EN |
USB_OHCI_INTERRUPT1_EN | USB_CTRL_INTERRUPT_EN |
USB_OHCI_INTERRUPT_EN | USB_OHCI_INTERRUPT2_EN;
nlm_write_usb_reg(port_addr, USB_INT_EN, val);
}
static void nlm_usb_hw_reset(int node, int port)
{
uint64_t port_addr;
uint32_t val;
/* reset USB phy */
port_addr = nlm_get_usb_regbase(node, port);
val = nlm_read_usb_reg(port_addr, USB_PHY_0);
val &= ~(USB_PHY_RESET | USB_PHY_PORT_RESET_0 | USB_PHY_PORT_RESET_1);
nlm_write_usb_reg(port_addr, USB_PHY_0, val);
mdelay(100);
val = nlm_read_usb_reg(port_addr, USB_CTL_0);
val &= ~(USB_CONTROLLER_RESET);
val |= 0x4;
nlm_write_usb_reg(port_addr, USB_CTL_0, val);
}
static int __init nlm_platform_usb_init(void)
{
pr_info("Initializing USB Interface\n");
nlm_usb_hw_reset(0, 0);
nlm_usb_hw_reset(0, 3);
/* Enable PHY interrupts */
nlm_usb_intr_en(0, 0);
nlm_usb_intr_en(0, 3);
return 0;
}
arch_initcall(nlm_platform_usb_init);
static u64 xlp_usb_dmamask = ~(u32)0;
/* Fixup the IRQ for USB devices which is exist on XLP SOC PCIE bus */
static void nlm_usb_fixup_final(struct pci_dev *dev)
{
dev->dev.dma_mask = &xlp_usb_dmamask;
dev->dev.coherent_dma_mask = DMA_BIT_MASK(64);
switch (dev->devfn) {
case 0x10:
dev->irq = PIC_EHCI_0_IRQ;
break;
case 0x11:
dev->irq = PIC_OHCI_0_IRQ;
break;
case 0x12:
dev->irq = PIC_OHCI_1_IRQ;
break;
case 0x13:
dev->irq = PIC_EHCI_1_IRQ;
break;
case 0x14:
dev->irq = PIC_OHCI_2_IRQ;
break;
case 0x15:
dev->irq = PIC_OHCI_3_IRQ;
break;
}
}
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_NETLOGIC, PCI_DEVICE_ID_NLM_EHCI,
nlm_usb_fixup_final);
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_NETLOGIC, PCI_DEVICE_ID_NLM_OHCI,
nlm_usb_fixup_final);

View File

@@ -0,0 +1,144 @@
/*
* Copyright 2003-2011 NetLogic Microsystems, Inc. (NetLogic). All rights
* reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
* General Public License (GPL) Version 2, available from the file
* COPYING in the main directory of this source tree, or the NetLogic
* license below:
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY NETLOGIC ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL NETLOGIC OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/threads.h>
#include <asm/asm.h>
#include <asm/asm-offsets.h>
#include <asm/mipsregs.h>
#include <asm/addrspace.h>
#include <asm/string.h>
#include <asm/netlogic/haldefs.h>
#include <asm/netlogic/common.h>
#include <asm/netlogic/mips-extns.h>
#include <asm/netlogic/xlp-hal/iomap.h>
#include <asm/netlogic/xlp-hal/pic.h>
#include <asm/netlogic/xlp-hal/xlp.h>
#include <asm/netlogic/xlp-hal/sys.h>
static int xlp_wakeup_core(uint64_t sysbase, int node, int core)
{
uint32_t coremask, value;
int count;
coremask = (1 << core);
/* Enable CPU clock */
value = nlm_read_sys_reg(sysbase, SYS_CORE_DFS_DIS_CTRL);
value &= ~coremask;
nlm_write_sys_reg(sysbase, SYS_CORE_DFS_DIS_CTRL, value);
/* Remove CPU Reset */
value = nlm_read_sys_reg(sysbase, SYS_CPU_RESET);
value &= ~coremask;
nlm_write_sys_reg(sysbase, SYS_CPU_RESET, value);
/* Poll for CPU to mark itself coherent */
count = 100000;
do {
value = nlm_read_sys_reg(sysbase, SYS_CPU_NONCOHERENT_MODE);
} while ((value & coremask) != 0 && --count > 0);
return count != 0;
}
static void xlp_enable_secondary_cores(const cpumask_t *wakeup_mask)
{
struct nlm_soc_info *nodep;
uint64_t syspcibase;
uint32_t syscoremask;
int core, n, cpu, count, val;
for (n = 0; n < NLM_NR_NODES; n++) {
syspcibase = nlm_get_sys_pcibase(n);
if (nlm_read_reg(syspcibase, 0) == 0xffffffff)
break;
/* read cores in reset from SYS */
if (n != 0)
nlm_node_init(n);
nodep = nlm_get_node(n);
syscoremask = nlm_read_sys_reg(nodep->sysbase, SYS_CPU_RESET);
/* The boot cpu */
if (n == 0) {
syscoremask |= 1;
nodep->coremask = 1;
}
for (core = 0; core < NLM_CORES_PER_NODE; core++) {
/* we will be on node 0 core 0 */
if (n == 0 && core == 0)
continue;
/* see if the core exists */
if ((syscoremask & (1 << core)) == 0)
continue;
/* see if at least the first hw thread is enabled */
cpu = (n * NLM_CORES_PER_NODE + core)
* NLM_THREADS_PER_CORE;
if (!cpumask_test_cpu(cpu, wakeup_mask))
continue;
/* wake up the core */
if (!xlp_wakeup_core(nodep->sysbase, n, core))
continue;
/* core is up */
nodep->coremask |= 1u << core;
/* spin until the first hw thread sets its ready */
count = 0x20000000;
do {
val = *(volatile int *)&nlm_cpu_ready[cpu];
} while (val == 0 && --count > 0);
}
}
}
void xlp_wakeup_secondary_cpus()
{
/*
* In case of u-boot, the secondaries are in reset
* first wakeup core 0 threads
*/
xlp_boot_core0_siblings();
/* now get other cores out of reset */
xlp_enable_secondary_cores(&nlm_cpumask);
}

View File

@@ -0,0 +1,2 @@
obj-y += fmn.o fmn-config.o setup.o platform.o platform-flash.o
obj-$(CONFIG_SMP) += wakeup.o

View File

@@ -0,0 +1,292 @@
/*
* Copyright (c) 2003-2012 Broadcom Corporation
* All Rights Reserved
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
* General Public License (GPL) Version 2, available from the file
* COPYING in the main directory of this source tree, or the Broadcom
* license below:
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY BROADCOM ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL BROADCOM OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <asm/cpu-info.h>
#include <linux/irq.h>
#include <linux/interrupt.h>
#include <asm/mipsregs.h>
#include <asm/netlogic/xlr/fmn.h>
#include <asm/netlogic/xlr/xlr.h>
#include <asm/netlogic/common.h>
#include <asm/netlogic/haldefs.h>
struct xlr_board_fmn_config xlr_board_fmn_config;
static void __maybe_unused print_credit_config(struct xlr_fmn_info *fmn_info)
{
int bkt;
pr_info("Bucket size :\n");
pr_info("Station\t: Size\n");
for (bkt = 0; bkt < 16; bkt++)
pr_info(" %d %d %d %d %d %d %d %d\n",
xlr_board_fmn_config.bucket_size[(bkt * 8) + 0],
xlr_board_fmn_config.bucket_size[(bkt * 8) + 1],
xlr_board_fmn_config.bucket_size[(bkt * 8) + 2],
xlr_board_fmn_config.bucket_size[(bkt * 8) + 3],
xlr_board_fmn_config.bucket_size[(bkt * 8) + 4],
xlr_board_fmn_config.bucket_size[(bkt * 8) + 5],
xlr_board_fmn_config.bucket_size[(bkt * 8) + 6],
xlr_board_fmn_config.bucket_size[(bkt * 8) + 7]);
pr_info("\n");
pr_info("Credits distribution :\n");
pr_info("Station\t: Size\n");
for (bkt = 0; bkt < 16; bkt++)
pr_info(" %d %d %d %d %d %d %d %d\n",
fmn_info->credit_config[(bkt * 8) + 0],
fmn_info->credit_config[(bkt * 8) + 1],
fmn_info->credit_config[(bkt * 8) + 2],
fmn_info->credit_config[(bkt * 8) + 3],
fmn_info->credit_config[(bkt * 8) + 4],
fmn_info->credit_config[(bkt * 8) + 5],
fmn_info->credit_config[(bkt * 8) + 6],
fmn_info->credit_config[(bkt * 8) + 7]);
pr_info("\n");
}
static void check_credit_distribution(void)
{
struct xlr_board_fmn_config *cfg = &xlr_board_fmn_config;
int bkt, n, total_credits, ncores;
ncores = hweight32(nlm_current_node()->coremask);
for (bkt = 0; bkt < 128; bkt++) {
total_credits = 0;
for (n = 0; n < ncores; n++)
total_credits += cfg->cpu[n].credit_config[bkt];
total_credits += cfg->gmac[0].credit_config[bkt];
total_credits += cfg->gmac[1].credit_config[bkt];
total_credits += cfg->dma.credit_config[bkt];
total_credits += cfg->cmp.credit_config[bkt];
total_credits += cfg->sae.credit_config[bkt];
total_credits += cfg->xgmac[0].credit_config[bkt];
total_credits += cfg->xgmac[1].credit_config[bkt];
if (total_credits > cfg->bucket_size[bkt])
pr_err("ERROR: Bucket %d: credits (%d) > size (%d)\n",
bkt, total_credits, cfg->bucket_size[bkt]);
}
pr_info("Credit distribution complete.\n");
}
/**
* Configure bucket size and credits for a device. 'size' is the size of
* the buckets for the device. This size is distributed among all the CPUs
* so that all of them can send messages to the device.
*
* The device is also given 'cpu_credits' to send messages to the CPUs
*
* @dev_info: FMN information structure for each devices
* @start_stn_id: Starting station id of dev_info
* @end_stn_id: End station id of dev_info
* @num_buckets: Total number of buckets for den_info
* @cpu_credits: Allowed credits to cpu for each devices pointing by dev_info
* @size: Size of the each buckets in the device station
*/
static void setup_fmn_cc(struct xlr_fmn_info *dev_info, int start_stn_id,
int end_stn_id, int num_buckets, int cpu_credits, int size)
{
int i, j, num_core, n, credits_per_cpu;
struct xlr_fmn_info *cpu = xlr_board_fmn_config.cpu;
num_core = hweight32(nlm_current_node()->coremask);
dev_info->num_buckets = num_buckets;
dev_info->start_stn_id = start_stn_id;
dev_info->end_stn_id = end_stn_id;
n = num_core;
if (num_core == 3)
n = 4;
for (i = start_stn_id; i <= end_stn_id; i++) {
xlr_board_fmn_config.bucket_size[i] = size;
/* Dividing device credits equally to cpus */
credits_per_cpu = size / n;
for (j = 0; j < num_core; j++)
cpu[j].credit_config[i] = credits_per_cpu;
/* credits left to distribute */
credits_per_cpu = size - (credits_per_cpu * num_core);
/* distribute the remaining credits (if any), among cores */
for (j = 0; (j < num_core) && (credits_per_cpu >= 4); j++) {
cpu[j].credit_config[i] += 4;
credits_per_cpu -= 4;
}
}
/* Distributing cpu per bucket credits to devices */
for (i = 0; i < num_core; i++) {
for (j = 0; j < FMN_CORE_NBUCKETS; j++)
dev_info->credit_config[(i * 8) + j] = cpu_credits;
}
}
/*
* Each core has 256 slots and 8 buckets,
* Configure the 8 buckets each with 32 slots
*/
static void setup_cpu_fmninfo(struct xlr_fmn_info *cpu, int num_core)
{
int i, j;
for (i = 0; i < num_core; i++) {
cpu[i].start_stn_id = (8 * i);
cpu[i].end_stn_id = (8 * i + 8);
for (j = cpu[i].start_stn_id; j < cpu[i].end_stn_id; j++)
xlr_board_fmn_config.bucket_size[j] = 32;
}
}
/**
* Setup the FMN details for each devices according to the device available
* in each variant of XLR/XLS processor
*/
void xlr_board_info_setup(void)
{
struct xlr_fmn_info *cpu = xlr_board_fmn_config.cpu;
struct xlr_fmn_info *gmac = xlr_board_fmn_config.gmac;
struct xlr_fmn_info *xgmac = xlr_board_fmn_config.xgmac;
struct xlr_fmn_info *dma = &xlr_board_fmn_config.dma;
struct xlr_fmn_info *cmp = &xlr_board_fmn_config.cmp;
struct xlr_fmn_info *sae = &xlr_board_fmn_config.sae;
int processor_id, num_core;
num_core = hweight32(nlm_current_node()->coremask);
processor_id = read_c0_prid() & 0xff00;
setup_cpu_fmninfo(cpu, num_core);
switch (processor_id) {
case PRID_IMP_NETLOGIC_XLS104:
case PRID_IMP_NETLOGIC_XLS108:
setup_fmn_cc(&gmac[0], FMN_STNID_GMAC0,
FMN_STNID_GMAC0_TX3, 8, 16, 32);
setup_fmn_cc(dma, FMN_STNID_DMA_0,
FMN_STNID_DMA_3, 4, 8, 64);
setup_fmn_cc(sae, FMN_STNID_SEC0,
FMN_STNID_SEC1, 2, 8, 128);
break;
case PRID_IMP_NETLOGIC_XLS204:
case PRID_IMP_NETLOGIC_XLS208:
setup_fmn_cc(&gmac[0], FMN_STNID_GMAC0,
FMN_STNID_GMAC0_TX3, 8, 16, 32);
setup_fmn_cc(dma, FMN_STNID_DMA_0,
FMN_STNID_DMA_3, 4, 8, 64);
setup_fmn_cc(sae, FMN_STNID_SEC0,
FMN_STNID_SEC1, 2, 8, 128);
break;
case PRID_IMP_NETLOGIC_XLS404:
case PRID_IMP_NETLOGIC_XLS408:
case PRID_IMP_NETLOGIC_XLS404B:
case PRID_IMP_NETLOGIC_XLS408B:
case PRID_IMP_NETLOGIC_XLS416B:
case PRID_IMP_NETLOGIC_XLS608B:
case PRID_IMP_NETLOGIC_XLS616B:
setup_fmn_cc(&gmac[0], FMN_STNID_GMAC0,
FMN_STNID_GMAC0_TX3, 8, 8, 32);
setup_fmn_cc(&gmac[1], FMN_STNID_GMAC1_FR_0,
FMN_STNID_GMAC1_TX3, 8, 8, 32);
setup_fmn_cc(dma, FMN_STNID_DMA_0,
FMN_STNID_DMA_3, 4, 4, 64);
setup_fmn_cc(cmp, FMN_STNID_CMP_0,
FMN_STNID_CMP_3, 4, 4, 64);
setup_fmn_cc(sae, FMN_STNID_SEC0,
FMN_STNID_SEC1, 2, 8, 128);
break;
case PRID_IMP_NETLOGIC_XLS412B:
setup_fmn_cc(&gmac[0], FMN_STNID_GMAC0,
FMN_STNID_GMAC0_TX3, 8, 8, 32);
setup_fmn_cc(&gmac[1], FMN_STNID_GMAC1_FR_0,
FMN_STNID_GMAC1_TX3, 8, 8, 32);
setup_fmn_cc(dma, FMN_STNID_DMA_0,
FMN_STNID_DMA_3, 4, 4, 64);
setup_fmn_cc(cmp, FMN_STNID_CMP_0,
FMN_STNID_CMP_3, 4, 4, 64);
setup_fmn_cc(sae, FMN_STNID_SEC0,
FMN_STNID_SEC1, 2, 8, 128);
break;
case PRID_IMP_NETLOGIC_XLR308:
case PRID_IMP_NETLOGIC_XLR308C:
setup_fmn_cc(&gmac[0], FMN_STNID_GMAC0,
FMN_STNID_GMAC0_TX3, 8, 16, 32);
setup_fmn_cc(dma, FMN_STNID_DMA_0,
FMN_STNID_DMA_3, 4, 8, 64);
setup_fmn_cc(sae, FMN_STNID_SEC0,
FMN_STNID_SEC1, 2, 4, 128);
break;
case PRID_IMP_NETLOGIC_XLR532:
case PRID_IMP_NETLOGIC_XLR532C:
case PRID_IMP_NETLOGIC_XLR516C:
case PRID_IMP_NETLOGIC_XLR508C:
setup_fmn_cc(&gmac[0], FMN_STNID_GMAC0,
FMN_STNID_GMAC0_TX3, 8, 16, 32);
setup_fmn_cc(dma, FMN_STNID_DMA_0,
FMN_STNID_DMA_3, 4, 8, 64);
setup_fmn_cc(sae, FMN_STNID_SEC0,
FMN_STNID_SEC1, 2, 4, 128);
break;
case PRID_IMP_NETLOGIC_XLR732:
case PRID_IMP_NETLOGIC_XLR716:
setup_fmn_cc(&xgmac[0], FMN_STNID_XMAC0_00_TX,
FMN_STNID_XMAC0_15_TX, 8, 0, 32);
setup_fmn_cc(&xgmac[1], FMN_STNID_XMAC1_00_TX,
FMN_STNID_XMAC1_15_TX, 8, 0, 32);
setup_fmn_cc(&gmac[0], FMN_STNID_GMAC0,
FMN_STNID_GMAC0_TX3, 8, 24, 32);
setup_fmn_cc(dma, FMN_STNID_DMA_0,
FMN_STNID_DMA_3, 4, 4, 64);
setup_fmn_cc(sae, FMN_STNID_SEC0,
FMN_STNID_SEC1, 2, 4, 128);
break;
default:
pr_err("Unknown CPU with processor ID [%d]\n", processor_id);
pr_err("Error: Cannot initialize FMN credits.\n");
}
check_credit_distribution();
#if 0 /* debug */
print_credit_config(&cpu[0]);
print_credit_config(&gmac[0]);
#endif
}

View File

@@ -0,0 +1,204 @@
/*
* Copyright (c) 2003-2012 Broadcom Corporation
* All Rights Reserved
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
* General Public License (GPL) Version 2, available from the file
* COPYING in the main directory of this source tree, or the Broadcom
* license below:
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY BROADCOM ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL BROADCOM OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <linux/kernel.h>
#include <linux/irqreturn.h>
#include <linux/irq.h>
#include <linux/interrupt.h>
#include <asm/mipsregs.h>
#include <asm/netlogic/interrupt.h>
#include <asm/netlogic/xlr/fmn.h>
#include <asm/netlogic/common.h>
#define COP2_CC_INIT_CPU_DEST(dest, conf) \
do { \
nlm_write_c2_cc##dest(0, conf[(dest * 8) + 0]); \
nlm_write_c2_cc##dest(1, conf[(dest * 8) + 1]); \
nlm_write_c2_cc##dest(2, conf[(dest * 8) + 2]); \
nlm_write_c2_cc##dest(3, conf[(dest * 8) + 3]); \
nlm_write_c2_cc##dest(4, conf[(dest * 8) + 4]); \
nlm_write_c2_cc##dest(5, conf[(dest * 8) + 5]); \
nlm_write_c2_cc##dest(6, conf[(dest * 8) + 6]); \
nlm_write_c2_cc##dest(7, conf[(dest * 8) + 7]); \
} while (0)
struct fmn_message_handler {
void (*action)(int, int, int, int, struct nlm_fmn_msg *, void *);
void *arg;
} msg_handlers[128];
/*
* FMN interrupt handler. We configure the FMN so that any messages in
* any of the CPU buckets will trigger an interrupt on the CPU.
* The message can be from any device on the FMN (like NAE/SAE/DMA).
* The source station id is used to figure out which of the registered
* handlers have to be called.
*/
static irqreturn_t fmn_message_handler(int irq, void *data)
{
struct fmn_message_handler *hndlr;
int bucket, rv;
int size = 0, code = 0, src_stnid = 0;
struct nlm_fmn_msg msg;
uint32_t mflags, bkt_status;
mflags = nlm_cop2_enable();
/* Disable message ring interrupt */
nlm_fmn_setup_intr(irq, 0);
while (1) {
/* 8 bkts per core, [24:31] each bit represents one bucket
* Bit is Zero if bucket is not empty */
bkt_status = (nlm_read_c2_status() >> 24) & 0xff;
if (bkt_status == 0xff)
break;
for (bucket = 0; bucket < 8; bucket++) {
/* Continue on empty bucket */
if (bkt_status & (1 << bucket))
continue;
rv = nlm_fmn_receive(bucket, &size, &code, &src_stnid,
&msg);
if (rv != 0)
continue;
hndlr = &msg_handlers[src_stnid];
if (hndlr->action == NULL)
pr_warn("No msgring handler for stnid %d\n",
src_stnid);
else {
nlm_cop2_restore(mflags);
hndlr->action(bucket, src_stnid, size, code,
&msg, hndlr->arg);
mflags = nlm_cop2_enable();
}
}
};
/* Enable message ring intr, to any thread in core */
nlm_fmn_setup_intr(irq, (1 << nlm_threads_per_core) - 1);
nlm_cop2_restore(mflags);
return IRQ_HANDLED;
}
struct irqaction fmn_irqaction = {
.handler = fmn_message_handler,
.flags = IRQF_PERCPU,
.name = "fmn",
};
void xlr_percpu_fmn_init(void)
{
struct xlr_fmn_info *cpu_fmn_info;
int *bucket_sizes;
uint32_t flags;
int id;
BUG_ON(nlm_thread_id() != 0);
id = nlm_core_id();
bucket_sizes = xlr_board_fmn_config.bucket_size;
cpu_fmn_info = &xlr_board_fmn_config.cpu[id];
flags = nlm_cop2_enable();
/* Setup bucket sizes for the core. */
nlm_write_c2_bucksize(0, bucket_sizes[id * 8 + 0]);
nlm_write_c2_bucksize(1, bucket_sizes[id * 8 + 1]);
nlm_write_c2_bucksize(2, bucket_sizes[id * 8 + 2]);
nlm_write_c2_bucksize(3, bucket_sizes[id * 8 + 3]);
nlm_write_c2_bucksize(4, bucket_sizes[id * 8 + 4]);
nlm_write_c2_bucksize(5, bucket_sizes[id * 8 + 5]);
nlm_write_c2_bucksize(6, bucket_sizes[id * 8 + 6]);
nlm_write_c2_bucksize(7, bucket_sizes[id * 8 + 7]);
/*
* For sending FMN messages, we need credits on the destination
* bucket. Program the credits this core has on the 128 possible
* destination buckets.
* We cannot use a loop here, because the the first argument has
* to be a constant integer value.
*/
COP2_CC_INIT_CPU_DEST(0, cpu_fmn_info->credit_config);
COP2_CC_INIT_CPU_DEST(1, cpu_fmn_info->credit_config);
COP2_CC_INIT_CPU_DEST(2, cpu_fmn_info->credit_config);
COP2_CC_INIT_CPU_DEST(3, cpu_fmn_info->credit_config);
COP2_CC_INIT_CPU_DEST(4, cpu_fmn_info->credit_config);
COP2_CC_INIT_CPU_DEST(5, cpu_fmn_info->credit_config);
COP2_CC_INIT_CPU_DEST(6, cpu_fmn_info->credit_config);
COP2_CC_INIT_CPU_DEST(7, cpu_fmn_info->credit_config);
COP2_CC_INIT_CPU_DEST(8, cpu_fmn_info->credit_config);
COP2_CC_INIT_CPU_DEST(9, cpu_fmn_info->credit_config);
COP2_CC_INIT_CPU_DEST(10, cpu_fmn_info->credit_config);
COP2_CC_INIT_CPU_DEST(11, cpu_fmn_info->credit_config);
COP2_CC_INIT_CPU_DEST(12, cpu_fmn_info->credit_config);
COP2_CC_INIT_CPU_DEST(13, cpu_fmn_info->credit_config);
COP2_CC_INIT_CPU_DEST(14, cpu_fmn_info->credit_config);
COP2_CC_INIT_CPU_DEST(15, cpu_fmn_info->credit_config);
/* enable FMN interrupts on this CPU */
nlm_fmn_setup_intr(IRQ_FMN, (1 << nlm_threads_per_core) - 1);
nlm_cop2_restore(flags);
}
/*
* Register a FMN message handler with respect to the source station id
* @stnid: source station id
* @action: Handler function pointer
*/
int nlm_register_fmn_handler(int start_stnid, int end_stnid,
void (*action)(int, int, int, int, struct nlm_fmn_msg *, void *),
void *arg)
{
int sstnid;
for (sstnid = start_stnid; sstnid <= end_stnid; sstnid++) {
msg_handlers[sstnid].arg = arg;
smp_wmb();
msg_handlers[sstnid].action = action;
}
pr_debug("Registered FMN msg handler for stnid %d-%d\n",
start_stnid, end_stnid);
return 0;
}
void nlm_setup_fmn_irq(void)
{
uint32_t flags;
/* setup irq only once */
setup_irq(IRQ_FMN, &fmn_irqaction);
flags = nlm_cop2_enable();
nlm_fmn_setup_intr(IRQ_FMN, (1 << nlm_threads_per_core) - 1);
nlm_cop2_restore(flags);
}

View File

@@ -0,0 +1,220 @@
/*
* Copyright 2011, Netlogic Microsystems.
* Copyright 2004, Matt Porter <mporter@kernel.crashing.org>
*
* This file is licensed under the terms of the GNU General Public
* License version 2. This program is licensed "as is" without any
* warranty of any kind, whether express or implied.
*/
#include <linux/device.h>
#include <linux/platform_device.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/io.h>
#include <linux/delay.h>
#include <linux/ioport.h>
#include <linux/resource.h>
#include <linux/spi/flash.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/physmap.h>
#include <linux/mtd/nand.h>
#include <linux/mtd/partitions.h>
#include <asm/netlogic/haldefs.h>
#include <asm/netlogic/xlr/iomap.h>
#include <asm/netlogic/xlr/flash.h>
#include <asm/netlogic/xlr/bridge.h>
#include <asm/netlogic/xlr/gpio.h>
#include <asm/netlogic/xlr/xlr.h>
/*
* Default NOR partition layout
*/
static struct mtd_partition xlr_nor_parts[] = {
{
.name = "User FS",
.offset = 0x800000,
.size = MTDPART_SIZ_FULL,
}
};
/*
* Default NAND partition layout
*/
static struct mtd_partition xlr_nand_parts[] = {
{
.name = "Root Filesystem",
.offset = 64 * 64 * 2048,
.size = 432 * 64 * 2048,
},
{
.name = "Home Filesystem",
.offset = MTDPART_OFS_APPEND,
.size = MTDPART_SIZ_FULL,
},
};
/* Use PHYSMAP flash for NOR */
struct physmap_flash_data xlr_nor_data = {
.width = 2,
.parts = xlr_nor_parts,
.nr_parts = ARRAY_SIZE(xlr_nor_parts),
};
static struct resource xlr_nor_res[] = {
{
.flags = IORESOURCE_MEM,
},
};
static struct platform_device xlr_nor_dev = {
.name = "physmap-flash",
.dev = {
.platform_data = &xlr_nor_data,
},
.num_resources = ARRAY_SIZE(xlr_nor_res),
.resource = xlr_nor_res,
};
const char *xlr_part_probes[] = { "cmdlinepart", NULL };
/*
* Use "gen_nand" driver for NAND flash
*
* There seems to be no way to store a private pointer containing
* platform specific info in gen_nand drivier. We will use a global
* struct for now, since we currently have only one NAND chip per board.
*/
struct xlr_nand_flash_priv {
int cs;
uint64_t flash_mmio;
};
static struct xlr_nand_flash_priv nand_priv;
static void xlr_nand_ctrl(struct mtd_info *mtd, int cmd,
unsigned int ctrl)
{
if (ctrl & NAND_CLE)
nlm_write_reg(nand_priv.flash_mmio,
FLASH_NAND_CLE(nand_priv.cs), cmd);
else if (ctrl & NAND_ALE)
nlm_write_reg(nand_priv.flash_mmio,
FLASH_NAND_ALE(nand_priv.cs), cmd);
}
struct platform_nand_data xlr_nand_data = {
.chip = {
.nr_chips = 1,
.nr_partitions = ARRAY_SIZE(xlr_nand_parts),
.chip_delay = 50,
.partitions = xlr_nand_parts,
.part_probe_types = xlr_part_probes,
},
.ctrl = {
.cmd_ctrl = xlr_nand_ctrl,
},
};
static struct resource xlr_nand_res[] = {
{
.flags = IORESOURCE_MEM,
},
};
static struct platform_device xlr_nand_dev = {
.name = "gen_nand",
.id = -1,
.num_resources = ARRAY_SIZE(xlr_nand_res),
.resource = xlr_nand_res,
.dev = {
.platform_data = &xlr_nand_data,
}
};
/*
* XLR/XLS supports upto 8 devices on its FLASH interface. The value in
* FLASH_BAR (on the MEM/IO bridge) gives the base for mapping all the
* flash devices.
* Under this, each flash device has an offset and size given by the
* CSBASE_ADDR and CSBASE_MASK registers for the device.
*
* The CSBASE_ registers are expected to be setup by the bootloader.
*/
static void setup_flash_resource(uint64_t flash_mmio,
uint64_t flash_map_base, int cs, struct resource *res)
{
u32 base, mask;
base = nlm_read_reg(flash_mmio, FLASH_CSBASE_ADDR(cs));
mask = nlm_read_reg(flash_mmio, FLASH_CSADDR_MASK(cs));
res->start = flash_map_base + ((unsigned long)base << 16);
res->end = res->start + (mask + 1) * 64 * 1024;
}
static int __init xlr_flash_init(void)
{
uint64_t gpio_mmio, flash_mmio, flash_map_base;
u32 gpio_resetcfg, flash_bar;
int cs, boot_nand, boot_nor;
/* Flash address bits 39:24 is in bridge flash BAR */
flash_bar = nlm_read_reg(nlm_io_base, BRIDGE_FLASH_BAR);
flash_map_base = (flash_bar & 0xffff0000) << 8;
gpio_mmio = nlm_mmio_base(NETLOGIC_IO_GPIO_OFFSET);
flash_mmio = nlm_mmio_base(NETLOGIC_IO_FLASH_OFFSET);
/* Get the chip reset config */
gpio_resetcfg = nlm_read_reg(gpio_mmio, GPIO_PWRON_RESET_CFG_REG);
/* Check for boot flash type */
boot_nor = boot_nand = 0;
if (nlm_chip_is_xls()) {
/* On XLS, check boot from NAND bit (GPIO reset reg bit 16) */
if (gpio_resetcfg & (1 << 16))
boot_nand = 1;
/* check boot from PCMCIA, (GPIO reset reg bit 15 */
if ((gpio_resetcfg & (1 << 15)) == 0)
boot_nor = 1; /* not set, booted from NOR */
} else { /* XLR */
/* check boot from PCMCIA (bit 16 in GPIO reset on XLR) */
if ((gpio_resetcfg & (1 << 16)) == 0)
boot_nor = 1; /* not set, booted from NOR */
}
/* boot flash at chip select 0 */
cs = 0;
if (boot_nand) {
nand_priv.cs = cs;
nand_priv.flash_mmio = flash_mmio;
setup_flash_resource(flash_mmio, flash_map_base, cs,
xlr_nand_res);
/* Initialize NAND flash at CS 0 */
nlm_write_reg(flash_mmio, FLASH_CSDEV_PARM(cs),
FLASH_NAND_CSDEV_PARAM);
nlm_write_reg(flash_mmio, FLASH_CSTIME_PARMA(cs),
FLASH_NAND_CSTIME_PARAMA);
nlm_write_reg(flash_mmio, FLASH_CSTIME_PARMB(cs),
FLASH_NAND_CSTIME_PARAMB);
pr_info("ChipSelect %d: NAND Flash %pR\n", cs, xlr_nand_res);
return platform_device_register(&xlr_nand_dev);
}
if (boot_nor) {
setup_flash_resource(flash_mmio, flash_map_base, cs,
xlr_nor_res);
pr_info("ChipSelect %d: NOR Flash %pR\n", cs, xlr_nor_res);
return platform_device_register(&xlr_nor_dev);
}
return 0;
}
arch_initcall(xlr_flash_init);

View File

@@ -0,0 +1,250 @@
/*
* Copyright 2011, Netlogic Microsystems.
* Copyright 2004, Matt Porter <mporter@kernel.crashing.org>
*
* This file is licensed under the terms of the GNU General Public
* License version 2. This program is licensed "as is" without any
* warranty of any kind, whether express or implied.
*/
#include <linux/device.h>
#include <linux/platform_device.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/resource.h>
#include <linux/serial_8250.h>
#include <linux/serial_reg.h>
#include <linux/i2c.h>
#include <linux/usb/ehci_pdriver.h>
#include <linux/usb/ohci_pdriver.h>
#include <asm/netlogic/haldefs.h>
#include <asm/netlogic/xlr/iomap.h>
#include <asm/netlogic/xlr/pic.h>
#include <asm/netlogic/xlr/xlr.h>
unsigned int nlm_xlr_uart_in(struct uart_port *p, int offset)
{
uint64_t uartbase;
unsigned int value;
/* sign extend to 64 bits, if needed */
uartbase = (uint64_t)(long)p->membase;
value = nlm_read_reg(uartbase, offset);
/* See XLR/XLS errata */
if (offset == UART_MSR)
value ^= 0xF0;
else if (offset == UART_MCR)
value ^= 0x3;
return value;
}
void nlm_xlr_uart_out(struct uart_port *p, int offset, int value)
{
uint64_t uartbase;
/* sign extend to 64 bits, if needed */
uartbase = (uint64_t)(long)p->membase;
/* See XLR/XLS errata */
if (offset == UART_MSR)
value ^= 0xF0;
else if (offset == UART_MCR)
value ^= 0x3;
nlm_write_reg(uartbase, offset, value);
}
#define PORT(_irq) \
{ \
.irq = _irq, \
.regshift = 2, \
.iotype = UPIO_MEM32, \
.flags = (UPF_SKIP_TEST | \
UPF_FIXED_TYPE | UPF_BOOT_AUTOCONF),\
.uartclk = PIC_CLK_HZ, \
.type = PORT_16550A, \
.serial_in = nlm_xlr_uart_in, \
.serial_out = nlm_xlr_uart_out, \
}
static struct plat_serial8250_port xlr_uart_data[] = {
PORT(PIC_UART_0_IRQ),
PORT(PIC_UART_1_IRQ),
{},
};
static struct platform_device uart_device = {
.name = "serial8250",
.id = PLAT8250_DEV_PLATFORM,
.dev = {
.platform_data = xlr_uart_data,
},
};
static int __init nlm_uart_init(void)
{
unsigned long uartbase;
uartbase = (unsigned long)nlm_mmio_base(NETLOGIC_IO_UART_0_OFFSET);
xlr_uart_data[0].membase = (void __iomem *)uartbase;
xlr_uart_data[0].mapbase = CPHYSADDR(uartbase);
uartbase = (unsigned long)nlm_mmio_base(NETLOGIC_IO_UART_1_OFFSET);
xlr_uart_data[1].membase = (void __iomem *)uartbase;
xlr_uart_data[1].mapbase = CPHYSADDR(uartbase);
return platform_device_register(&uart_device);
}
arch_initcall(nlm_uart_init);
#ifdef CONFIG_USB
/* Platform USB devices, only on XLS chips */
static u64 xls_usb_dmamask = ~(u32)0;
#define USB_PLATFORM_DEV(n, i, irq) \
{ \
.name = n, \
.id = i, \
.num_resources = 2, \
.dev = { \
.dma_mask = &xls_usb_dmamask, \
.coherent_dma_mask = 0xffffffff, \
}, \
.resource = (struct resource[]) { \
{ \
.flags = IORESOURCE_MEM, \
}, \
{ \
.start = irq, \
.end = irq, \
.flags = IORESOURCE_IRQ, \
}, \
}, \
}
static struct usb_ehci_pdata xls_usb_ehci_pdata = {
.caps_offset = 0,
};
static struct usb_ohci_pdata xls_usb_ohci_pdata;
static struct platform_device xls_usb_ehci_device =
USB_PLATFORM_DEV("ehci-platform", 0, PIC_USB_IRQ);
static struct platform_device xls_usb_ohci_device_0 =
USB_PLATFORM_DEV("ohci-platform", 1, PIC_USB_IRQ);
static struct platform_device xls_usb_ohci_device_1 =
USB_PLATFORM_DEV("ohci-platform", 2, PIC_USB_IRQ);
static struct platform_device *xls_platform_devices[] = {
&xls_usb_ehci_device,
&xls_usb_ohci_device_0,
&xls_usb_ohci_device_1,
};
int xls_platform_usb_init(void)
{
uint64_t usb_mmio, gpio_mmio;
unsigned long memres;
uint32_t val;
if (!nlm_chip_is_xls())
return 0;
gpio_mmio = nlm_mmio_base(NETLOGIC_IO_GPIO_OFFSET);
usb_mmio = nlm_mmio_base(NETLOGIC_IO_USB_1_OFFSET);
/* Clear Rogue Phy INTs */
nlm_write_reg(usb_mmio, 49, 0x10000000);
/* Enable all interrupts */
nlm_write_reg(usb_mmio, 50, 0x1f000000);
/* Enable ports */
nlm_write_reg(usb_mmio, 1, 0x07000500);
val = nlm_read_reg(gpio_mmio, 21);
if (((val >> 22) & 0x01) == 0) {
pr_info("Detected USB Device mode - Not supported!\n");
nlm_write_reg(usb_mmio, 0, 0x01000000);
return 0;
}
pr_info("Detected USB Host mode - Adding XLS USB devices.\n");
/* Clear reset, host mode */
nlm_write_reg(usb_mmio, 0, 0x02000000);
/* Memory resource for various XLS usb ports */
usb_mmio = nlm_mmio_base(NETLOGIC_IO_USB_0_OFFSET);
memres = CPHYSADDR((unsigned long)usb_mmio);
xls_usb_ehci_device.resource[0].start = memres;
xls_usb_ehci_device.resource[0].end = memres + 0x400 - 1;
xls_usb_ehci_device.dev.platform_data = &xls_usb_ehci_pdata;
memres += 0x400;
xls_usb_ohci_device_0.resource[0].start = memres;
xls_usb_ohci_device_0.resource[0].end = memres + 0x400 - 1;
xls_usb_ohci_device_0.dev.platform_data = &xls_usb_ohci_pdata;
memres += 0x400;
xls_usb_ohci_device_1.resource[0].start = memres;
xls_usb_ohci_device_1.resource[0].end = memres + 0x400 - 1;
xls_usb_ohci_device_1.dev.platform_data = &xls_usb_ohci_pdata;
return platform_add_devices(xls_platform_devices,
ARRAY_SIZE(xls_platform_devices));
}
arch_initcall(xls_platform_usb_init);
#endif
#ifdef CONFIG_I2C
static struct i2c_board_info nlm_i2c_board_info1[] __initdata = {
/* All XLR boards have this RTC and Max6657 Temp Chip */
[0] = {
.type = "ds1374",
.addr = 0x68
},
[1] = {
.type = "lm90",
.addr = 0x4c
},
};
static struct resource i2c_resources[] = {
[0] = {
.start = 0, /* filled at init */
.end = 0,
.flags = IORESOURCE_MEM,
},
};
static struct platform_device nlm_xlr_i2c_1 = {
.name = "xlr-i2cbus",
.id = 1,
.num_resources = 1,
.resource = i2c_resources,
};
static int __init nlm_i2c_init(void)
{
int err = 0;
unsigned int offset;
/* I2C bus 0 does not have any useful devices, configure only bus 1 */
offset = NETLOGIC_IO_I2C_1_OFFSET;
nlm_xlr_i2c_1.resource[0].start = CPHYSADDR(nlm_mmio_base(offset));
nlm_xlr_i2c_1.resource[0].end = nlm_xlr_i2c_1.resource[0].start + 0xfff;
platform_device_register(&nlm_xlr_i2c_1);
err = i2c_register_board_info(1, nlm_i2c_board_info1,
ARRAY_SIZE(nlm_i2c_board_info1));
if (err < 0)
pr_err("nlm-i2c: cannot register board I2C devices\n");
return err;
}
arch_initcall(nlm_i2c_init);
#endif

View File

@@ -0,0 +1,224 @@
/*
* Copyright 2003-2011 NetLogic Microsystems, Inc. (NetLogic). All rights
* reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
* General Public License (GPL) Version 2, available from the file
* COPYING in the main directory of this source tree, or the NetLogic
* license below:
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY NETLOGIC ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL NETLOGIC OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <linux/kernel.h>
#include <linux/serial_8250.h>
#include <linux/pm.h>
#include <asm/idle.h>
#include <asm/reboot.h>
#include <asm/time.h>
#include <asm/bootinfo.h>
#include <asm/netlogic/interrupt.h>
#include <asm/netlogic/psb-bootinfo.h>
#include <asm/netlogic/haldefs.h>
#include <asm/netlogic/common.h>
#include <asm/netlogic/xlr/xlr.h>
#include <asm/netlogic/xlr/iomap.h>
#include <asm/netlogic/xlr/pic.h>
#include <asm/netlogic/xlr/gpio.h>
#include <asm/netlogic/xlr/fmn.h>
uint64_t nlm_io_base = DEFAULT_NETLOGIC_IO_BASE;
struct psb_info nlm_prom_info;
/* default to uniprocessor */
unsigned int nlm_threads_per_core = 1;
struct nlm_soc_info nlm_nodes[NLM_NR_NODES];
cpumask_t nlm_cpumask = CPU_MASK_CPU0;
static void __init nlm_early_serial_setup(void)
{
struct uart_port s;
unsigned long uart_base;
uart_base = (unsigned long)nlm_mmio_base(NETLOGIC_IO_UART_0_OFFSET);
memset(&s, 0, sizeof(s));
s.flags = ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST;
s.iotype = UPIO_MEM32;
s.regshift = 2;
s.irq = PIC_UART_0_IRQ;
s.uartclk = PIC_CLK_HZ;
s.serial_in = nlm_xlr_uart_in;
s.serial_out = nlm_xlr_uart_out;
s.mapbase = uart_base;
s.membase = (unsigned char __iomem *)uart_base;
early_serial_setup(&s);
}
static void nlm_linux_exit(void)
{
uint64_t gpiobase;
gpiobase = nlm_mmio_base(NETLOGIC_IO_GPIO_OFFSET);
/* trigger a chip reset by writing 1 to GPIO_SWRESET_REG */
nlm_write_reg(gpiobase, GPIO_SWRESET_REG, 1);
for ( ; ; )
cpu_wait();
}
void __init plat_mem_setup(void)
{
panic_timeout = 5;
_machine_restart = (void (*)(char *))nlm_linux_exit;
_machine_halt = nlm_linux_exit;
pm_power_off = nlm_linux_exit;
}
const char *get_system_type(void)
{
return "Netlogic XLR/XLS Series";
}
unsigned int nlm_get_cpu_frequency(void)
{
return (unsigned int)nlm_prom_info.cpu_frequency;
}
void __init prom_free_prom_memory(void)
{
/* Nothing yet */
}
void nlm_percpu_init(int hwcpuid)
{
if (hwcpuid % 4 == 0)
xlr_percpu_fmn_init();
}
static void __init build_arcs_cmdline(int *argv)
{
int i, remain, len;
char *arg;
remain = sizeof(arcs_cmdline) - 1;
arcs_cmdline[0] = '\0';
for (i = 0; argv[i] != 0; i++) {
arg = (char *)(long)argv[i];
len = strlen(arg);
if (len + 1 > remain)
break;
strcat(arcs_cmdline, arg);
strcat(arcs_cmdline, " ");
remain -= len + 1;
}
/* Add the default options here */
if ((strstr(arcs_cmdline, "console=")) == NULL) {
arg = "console=ttyS0,38400 ";
len = strlen(arg);
if (len > remain)
goto fail;
strcat(arcs_cmdline, arg);
remain -= len;
}
#ifdef CONFIG_BLK_DEV_INITRD
if ((strstr(arcs_cmdline, "rdinit=")) == NULL) {
arg = "rdinit=/sbin/init ";
len = strlen(arg);
if (len > remain)
goto fail;
strcat(arcs_cmdline, arg);
remain -= len;
}
#endif
return;
fail:
panic("Cannot add %s, command line too big!", arg);
}
static void prom_add_memory(void)
{
struct nlm_boot_mem_map *bootm;
u64 start, size;
u64 pref_backup = 512; /* avoid pref walking beyond end */
int i;
bootm = (void *)(long)nlm_prom_info.psb_mem_map;
for (i = 0; i < bootm->nr_map; i++) {
if (bootm->map[i].type != BOOT_MEM_RAM)
continue;
start = bootm->map[i].addr;
size = bootm->map[i].size;
/* Work around for using bootloader mem */
if (i == 0 && start == 0 && size == 0x0c000000)
size = 0x0ff00000;
add_memory_region(start, size - pref_backup, BOOT_MEM_RAM);
}
}
static void nlm_init_node(void)
{
struct nlm_soc_info *nodep;
nodep = nlm_current_node();
nodep->picbase = nlm_mmio_base(NETLOGIC_IO_PIC_OFFSET);
nodep->ebase = read_c0_ebase() & (~((1 << 12) - 1));
spin_lock_init(&nodep->piclock);
}
void __init prom_init(void)
{
int *argv, *envp; /* passed as 32 bit ptrs */
struct psb_info *prom_infop;
#ifdef CONFIG_SMP
int i;
#endif
/* truncate to 32 bit and sign extend all args */
argv = (int *)(long)(int)fw_arg1;
envp = (int *)(long)(int)fw_arg2;
prom_infop = (struct psb_info *)(long)(int)fw_arg3;
nlm_prom_info = *prom_infop;
nlm_init_node();
nlm_early_serial_setup();
build_arcs_cmdline(argv);
prom_add_memory();
#ifdef CONFIG_SMP
for (i = 0; i < 32; i++)
if (nlm_prom_info.online_cpu_map & (1 << i))
cpumask_set_cpu(i, &nlm_cpumask);
nlm_wakeup_secondary_cpus();
register_smp_ops(&nlm_smp_ops);
#endif
xlr_board_info_setup();
xlr_percpu_fmn_init();
}

View File

@@ -0,0 +1,85 @@
/*
* Copyright 2003-2011 NetLogic Microsystems, Inc. (NetLogic). All rights
* reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
* General Public License (GPL) Version 2, available from the file
* COPYING in the main directory of this source tree, or the NetLogic
* license below:
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY NETLOGIC ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL NETLOGIC OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/threads.h>
#include <asm/asm.h>
#include <asm/asm-offsets.h>
#include <asm/mipsregs.h>
#include <asm/addrspace.h>
#include <asm/string.h>
#include <asm/netlogic/haldefs.h>
#include <asm/netlogic/common.h>
#include <asm/netlogic/mips-extns.h>
#include <asm/netlogic/xlr/iomap.h>
#include <asm/netlogic/xlr/pic.h>
int __cpuinit xlr_wakeup_secondary_cpus(void)
{
struct nlm_soc_info *nodep;
unsigned int i, j, boot_cpu;
/*
* In case of RMI boot, hit with NMI to get the cores
* from bootloader to linux code.
*/
nodep = nlm_get_node(0);
boot_cpu = hard_smp_processor_id();
nlm_set_nmi_handler(nlm_rmiboot_preboot);
for (i = 0; i < NR_CPUS; i++) {
if (i == boot_cpu || !cpumask_test_cpu(i, &nlm_cpumask))
continue;
nlm_pic_send_ipi(nodep->picbase, i, 1, 1); /* send NMI */
}
/* Fill up the coremask early */
nodep->coremask = 1;
for (i = 1; i < NLM_CORES_PER_NODE; i++) {
for (j = 1000000; j > 0; j--) {
if (nlm_cpu_ready[i * NLM_THREADS_PER_CORE])
break;
udelay(10);
}
if (j != 0)
nodep->coremask |= (1u << i);
else
pr_err("Failed to wakeup core %d\n", i);
}
return 0;
}