mirror of
https://github.com/AetherDroid/android_kernel_samsung_on5xelte.git
synced 2025-09-08 17:18:05 -04:00
Fixed MTP to work with TWRP
This commit is contained in:
commit
f6dfaef42e
50820 changed files with 20846062 additions and 0 deletions
87
arch/mips/netlogic/Kconfig
Normal file
87
arch/mips/netlogic/Kconfig
Normal file
|
@ -0,0 +1,87 @@
|
|||
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
|
||||
select BUILTIN_DTB
|
||||
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
|
||||
select BUILTIN_DTB
|
||||
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 DT_XLP_FVP
|
||||
bool "Built-in device tree for XLP FVP boards"
|
||||
default y
|
||||
select BUILTIN_DTB
|
||||
help
|
||||
Add an FDT blob for XLP FVP board 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_fvp.dts
|
||||
|
||||
config DT_XLP_GVP
|
||||
bool "Built-in device tree for XLP GVP boards"
|
||||
default y
|
||||
select BUILTIN_DTB
|
||||
help
|
||||
Add an FDT blob for XLP GVP board 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_gvp.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
|
||||
|
||||
config IOMMU_HELPER
|
||||
bool
|
||||
|
||||
config NEED_SG_DMA_LENGTH
|
||||
bool
|
||||
|
||||
config SWIOTLB
|
||||
def_bool y
|
||||
select NEED_SG_DMA_LENGTH
|
||||
select IOMMU_HELPER
|
||||
|
||||
endif
|
3
arch/mips/netlogic/Makefile
Normal file
3
arch/mips/netlogic/Makefile
Normal file
|
@ -0,0 +1,3 @@
|
|||
obj-$(CONFIG_NLM_COMMON) += common/
|
||||
obj-$(CONFIG_CPU_XLR) += xlr/
|
||||
obj-$(CONFIG_CPU_XLP) += xlp/
|
17
arch/mips/netlogic/Platform
Normal file
17
arch/mips/netlogic/Platform
Normal 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
|
5
arch/mips/netlogic/common/Makefile
Normal file
5
arch/mips/netlogic/common/Makefile
Normal file
|
@ -0,0 +1,5 @@
|
|||
obj-y += irq.o time.o
|
||||
obj-y += nlm-dma.o
|
||||
obj-y += reset.o
|
||||
obj-$(CONFIG_SMP) += smp.o smpboot.o
|
||||
obj-$(CONFIG_EARLY_PRINTK) += earlycons.o
|
62
arch/mips/netlogic/common/earlycons.c
Normal file
62
arch/mips/netlogic/common/earlycons.c
Normal file
|
@ -0,0 +1,62 @@
|
|||
/*
|
||||
* 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>
|
||||
#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/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);
|
||||
}
|
354
arch/mips/netlogic/common/irq.c
Normal file
354
arch/mips/netlogic/common/irq.c
Normal file
|
@ -0,0 +1,354 @@
|
|||
/*
|
||||
* 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 <linux/irqdomain.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_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);
|
||||
if (WARN_ON(!pic_data))
|
||||
return;
|
||||
pic_data->extra_ack = xack;
|
||||
}
|
||||
|
||||
static void nlm_init_node_irqs(int node)
|
||||
{
|
||||
struct nlm_soc_info *nodep;
|
||||
int i, irt;
|
||||
|
||||
pr_info("Init IRQ for node %d\n", node);
|
||||
nodep = nlm_get_node(node);
|
||||
nodep->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) /* unused irq */
|
||||
continue;
|
||||
nodep->irqmask |= 1ull << i;
|
||||
if (irt == -2) /* not a direct PIC irq */
|
||||
continue;
|
||||
|
||||
nlm_pic_init_irt(nodep->picbase, irt, i,
|
||||
node * nlm_threads_per_node(), 0);
|
||||
nlm_setup_pic_irq(node, i, i, irt);
|
||||
}
|
||||
}
|
||||
|
||||
void nlm_smp_irq_init(int hwcpuid)
|
||||
{
|
||||
int node, cpu;
|
||||
|
||||
node = nlm_cpuid_to_node(hwcpuid);
|
||||
cpu = hwcpuid % nlm_threads_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();
|
||||
if (eirr == 0)
|
||||
return;
|
||||
|
||||
i = __ffs64(eirr);
|
||||
/* per-CPU IRQs don't need translation */
|
||||
if (i < PIC_IRQ_BASE) {
|
||||
do_IRQ(i);
|
||||
return;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_PCI_MSI) && defined(CONFIG_CPU_XLP)
|
||||
/* PCI interrupts need a second level dispatch for MSI bits */
|
||||
if (i >= PIC_PCIE_LINK_MSI_IRQ(0) && i <= PIC_PCIE_LINK_MSI_IRQ(3)) {
|
||||
nlm_dispatch_msi(node, i);
|
||||
return;
|
||||
}
|
||||
if (i >= PIC_PCIE_MSIX_IRQ(0) && i <= PIC_PCIE_MSIX_IRQ(3)) {
|
||||
nlm_dispatch_msix(node, i);
|
||||
return;
|
||||
}
|
||||
|
||||
#endif
|
||||
/* top level irq handling */
|
||||
do_IRQ(nlm_irq_to_xirq(node, i));
|
||||
}
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
static const struct irq_domain_ops xlp_pic_irq_domain_ops = {
|
||||
.xlate = irq_domain_xlate_onetwocell,
|
||||
};
|
||||
|
||||
static int __init xlp_of_pic_init(struct device_node *node,
|
||||
struct device_node *parent)
|
||||
{
|
||||
const int n_picirqs = PIC_IRT_LAST_IRQ - PIC_IRQ_BASE + 1;
|
||||
struct irq_domain *xlp_pic_domain;
|
||||
struct resource res;
|
||||
int socid, ret, bus;
|
||||
|
||||
/* we need a hack to get the PIC's SoC chip id */
|
||||
ret = of_address_to_resource(node, 0, &res);
|
||||
if (ret < 0) {
|
||||
pr_err("PIC %s: reg property not found!\n", node->name);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (cpu_is_xlp9xx()) {
|
||||
bus = (res.start >> 20) & 0xf;
|
||||
for (socid = 0; socid < NLM_NR_NODES; socid++) {
|
||||
if (!nlm_node_present(socid))
|
||||
continue;
|
||||
if (nlm_get_node(socid)->socbus == bus)
|
||||
break;
|
||||
}
|
||||
if (socid == NLM_NR_NODES) {
|
||||
pr_err("PIC %s: Node mapping for bus %d not found!\n",
|
||||
node->name, bus);
|
||||
return -EINVAL;
|
||||
}
|
||||
} else {
|
||||
socid = (res.start >> 18) & 0x3;
|
||||
if (!nlm_node_present(socid)) {
|
||||
pr_err("PIC %s: node %d does not exist!\n",
|
||||
node->name, socid);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
if (!nlm_node_present(socid)) {
|
||||
pr_err("PIC %s: node %d does not exist!\n", node->name, socid);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
xlp_pic_domain = irq_domain_add_legacy(node, n_picirqs,
|
||||
nlm_irq_to_xirq(socid, PIC_IRQ_BASE), PIC_IRQ_BASE,
|
||||
&xlp_pic_irq_domain_ops, NULL);
|
||||
if (xlp_pic_domain == NULL) {
|
||||
pr_err("PIC %s: Creating legacy domain failed!\n", node->name);
|
||||
return -EINVAL;
|
||||
}
|
||||
pr_info("Node %d: IRQ domain created for PIC@%pR\n", socid, &res);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct of_device_id __initdata xlp_pic_irq_ids[] = {
|
||||
{ .compatible = "netlogic,xlp-pic", .data = xlp_of_pic_init },
|
||||
{},
|
||||
};
|
||||
#endif
|
||||
|
||||
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
|
||||
#if defined(CONFIG_OF)
|
||||
of_irq_init(xlp_pic_irq_ids);
|
||||
#endif
|
||||
}
|
107
arch/mips/netlogic/common/nlm-dma.c
Normal file
107
arch/mips/netlogic/common/nlm-dma.c
Normal file
|
@ -0,0 +1,107 @@
|
|||
/*
|
||||
* Copyright (C) 2003-2013 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/scatterlist.h>
|
||||
#include <linux/bootmem.h>
|
||||
#include <linux/export.h>
|
||||
#include <linux/swiotlb.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/mm.h>
|
||||
|
||||
#include <asm/bootinfo.h>
|
||||
|
||||
static char *nlm_swiotlb;
|
||||
|
||||
static void *nlm_dma_alloc_coherent(struct device *dev, size_t size,
|
||||
dma_addr_t *dma_handle, gfp_t gfp, struct dma_attrs *attrs)
|
||||
{
|
||||
void *ret;
|
||||
|
||||
if (dma_alloc_from_coherent(dev, size, dma_handle, &ret))
|
||||
return ret;
|
||||
|
||||
/* ignore region specifiers */
|
||||
gfp &= ~(__GFP_DMA | __GFP_DMA32 | __GFP_HIGHMEM);
|
||||
|
||||
#ifdef CONFIG_ZONE_DMA32
|
||||
if (dev->coherent_dma_mask <= DMA_BIT_MASK(32))
|
||||
gfp |= __GFP_DMA32;
|
||||
#endif
|
||||
|
||||
/* Don't invoke OOM killer */
|
||||
gfp |= __GFP_NORETRY;
|
||||
|
||||
return swiotlb_alloc_coherent(dev, size, dma_handle, gfp);
|
||||
}
|
||||
|
||||
static void nlm_dma_free_coherent(struct device *dev, size_t size,
|
||||
void *vaddr, dma_addr_t dma_handle, struct dma_attrs *attrs)
|
||||
{
|
||||
int order = get_order(size);
|
||||
|
||||
if (dma_release_from_coherent(dev, order, vaddr))
|
||||
return;
|
||||
|
||||
swiotlb_free_coherent(dev, size, vaddr, dma_handle);
|
||||
}
|
||||
|
||||
struct dma_map_ops nlm_swiotlb_dma_ops = {
|
||||
.alloc = nlm_dma_alloc_coherent,
|
||||
.free = nlm_dma_free_coherent,
|
||||
.map_page = swiotlb_map_page,
|
||||
.unmap_page = swiotlb_unmap_page,
|
||||
.map_sg = swiotlb_map_sg_attrs,
|
||||
.unmap_sg = swiotlb_unmap_sg_attrs,
|
||||
.sync_single_for_cpu = swiotlb_sync_single_for_cpu,
|
||||
.sync_single_for_device = swiotlb_sync_single_for_device,
|
||||
.sync_sg_for_cpu = swiotlb_sync_sg_for_cpu,
|
||||
.sync_sg_for_device = swiotlb_sync_sg_for_device,
|
||||
.mapping_error = swiotlb_dma_mapping_error,
|
||||
.dma_supported = swiotlb_dma_supported
|
||||
};
|
||||
|
||||
void __init plat_swiotlb_setup(void)
|
||||
{
|
||||
size_t swiotlbsize;
|
||||
unsigned long swiotlb_nslabs;
|
||||
|
||||
swiotlbsize = 1 << 20; /* 1 MB for now */
|
||||
swiotlb_nslabs = swiotlbsize >> IO_TLB_SHIFT;
|
||||
swiotlb_nslabs = ALIGN(swiotlb_nslabs, IO_TLB_SEGSIZE);
|
||||
swiotlbsize = swiotlb_nslabs << IO_TLB_SHIFT;
|
||||
|
||||
nlm_swiotlb = alloc_bootmem_low_pages(swiotlbsize);
|
||||
swiotlb_init_with_tbl(nlm_swiotlb, swiotlb_nslabs, 1);
|
||||
}
|
280
arch/mips/netlogic/common/reset.S
Normal file
280
arch/mips/netlogic/common/reset.S
Normal file
|
@ -0,0 +1,280 @@
|
|||
/*
|
||||
* Copyright 2003-2013 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/asm.h>
|
||||
#include <asm/asm-offsets.h>
|
||||
#include <asm/cpu.h>
|
||||
#include <asm/cacheops.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 CKSEG1ADDR(XLP_DEFAULT_IO_BASE) + \
|
||||
XLP_IO_SYS_OFFSET(0) + XLP_IO_PCI_HDRSZ + \
|
||||
SYS_CPU_NONCOHERENT_MODE * 4
|
||||
|
||||
/* 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
|
||||
mtcr t1, t0
|
||||
|
||||
li t0, ICU_DEFEATURE
|
||||
mfcr t1, t0
|
||||
ori t1, 0x1000 /* Enable Icache partitioning */
|
||||
mtcr t1, t0
|
||||
|
||||
li t0, SCHED_DEFEATURE
|
||||
lui t1, 0x0100 /* Disable BRU accepting ALU ops */
|
||||
mtcr t1, t0
|
||||
.endm
|
||||
|
||||
/*
|
||||
* Allow access to physical mem >64G by enabling ELPA in PAGEGRAIN
|
||||
* register. This is needed before going to C code since the SP can
|
||||
* in this region. Called from all HW threads.
|
||||
*/
|
||||
.macro xlp_early_mmu_init
|
||||
mfc0 t0, CP0_PAGEMASK, 1
|
||||
li t1, (1 << 29) /* ELPA bit */
|
||||
or t0, t1
|
||||
mtc0 t0, CP0_PAGEMASK, 1
|
||||
.endm
|
||||
|
||||
/*
|
||||
* L1D cache has to be flushed before enabling threads in XLP.
|
||||
* On XLP8xx/XLP3xx, we do a low level flush using processor control
|
||||
* registers. On XLPII CPUs, usual cache instructions work.
|
||||
*/
|
||||
.macro xlp_flush_l1_dcache
|
||||
mfc0 t0, CP0_EBASE, 0
|
||||
andi t0, t0, PRID_IMP_MASK
|
||||
slt t1, t0, 0x1200
|
||||
beqz t1, 15f
|
||||
nop
|
||||
|
||||
/* XLP8xx low level cache flush */
|
||||
li t0, LSU_DEBUG_DATA0
|
||||
li t1, LSU_DEBUG_ADDR
|
||||
li t2, 0 /* index */
|
||||
li t3, 0x1000 /* loop count */
|
||||
11:
|
||||
sll v0, t2, 5
|
||||
mtcr zero, t0
|
||||
ori v1, v0, 0x3 /* way0 | write_enable | write_active */
|
||||
mtcr v1, t1
|
||||
12:
|
||||
mfcr v1, t1
|
||||
andi v1, 0x1 /* wait for write_active == 0 */
|
||||
bnez v1, 12b
|
||||
nop
|
||||
mtcr zero, t0
|
||||
ori v1, v0, 0x7 /* way1 | write_enable | write_active */
|
||||
mtcr v1, t1
|
||||
13:
|
||||
mfcr v1, t1
|
||||
andi v1, 0x1 /* wait for write_active == 0 */
|
||||
bnez v1, 13b
|
||||
nop
|
||||
addi t2, 1
|
||||
bne t3, t2, 11b
|
||||
nop
|
||||
b 17f
|
||||
nop
|
||||
|
||||
/* XLPII CPUs, Invalidate all 64k of L1 D-cache */
|
||||
15:
|
||||
li t0, 0x80000000
|
||||
li t1, 0x80010000
|
||||
16: cache Index_Writeback_Inv_D, 0(t0)
|
||||
addiu t0, t0, 32
|
||||
bne t0, t1, 16b
|
||||
nop
|
||||
17:
|
||||
.endm
|
||||
|
||||
/*
|
||||
* nlm_reset_entry 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.
|
||||
*
|
||||
* We use scratch reg 6/7 to save k0/k1 and check for NMI 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 marks itself ready and
|
||||
* loops in a 'wait'. When the CPU really needs waking up, we send an NMI
|
||||
* IPI 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, 0 /* processor ID */
|
||||
andi t0, PRID_IMP_MASK
|
||||
li t1, 0x1500 /* XLP 9xx */
|
||||
beq t0, t1, 2f /* does not need to set coherent */
|
||||
nop
|
||||
|
||||
li t1, 0x1300 /* XLP 5xx */
|
||||
beq t0, t1, 2f /* does not need to set coherent */
|
||||
nop
|
||||
|
||||
/* set bit in SYS coherent register for the core */
|
||||
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
|
||||
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
|
||||
|
||||
2:
|
||||
/* 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
|
||||
/* save ra and sp, will be used later (only for boot cpu) */
|
||||
dmtc0 ra, $22, 6
|
||||
dmtc0 sp, $22, 7
|
||||
/* 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.
|
||||
|
||||
* NOTE: All GPR contents are lost after the mtcr above!
|
||||
*/
|
||||
mfc0 v0, CP0_EBASE, 1
|
||||
andi v0, 0x3ff /* v0 <- node/core */
|
||||
|
||||
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
|
||||
|
||||
xlp_early_mmu_init
|
||||
|
||||
/* mark CPU ready */
|
||||
li t3, CKSEG1ADDR(RESET_DATA_PHYS)
|
||||
ADDIU t1, t3, BOOT_CPU_READY
|
||||
sll v1, v0, 2
|
||||
PTR_ADDU t1, v1
|
||||
li t2, 1
|
||||
sw t2, 0(t1)
|
||||
/* Wait until NMI hits */
|
||||
3: wait
|
||||
b 3b
|
||||
nop
|
||||
|
||||
/*
|
||||
* For the boot CPU, we have to restore ra and sp and return, rest
|
||||
* of the registers will be restored by the caller
|
||||
*/
|
||||
4:
|
||||
dmfc0 ra, $22, 6
|
||||
dmfc0 sp, $22, 7
|
||||
jr ra
|
||||
nop
|
||||
EXPORT(nlm_reset_entry_end)
|
||||
|
||||
LEAF(nlm_init_boot_cpu)
|
||||
#ifdef CONFIG_CPU_XLP
|
||||
xlp_config_lsu
|
||||
xlp_early_mmu_init
|
||||
#endif
|
||||
jr ra
|
||||
nop
|
||||
END(nlm_init_boot_cpu)
|
280
arch/mips/netlogic/common/smp.c
Normal file
280
arch/mips/netlogic/common/smp.c
Normal file
|
@ -0,0 +1,280 @@
|
|||
/*
|
||||
* 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 = nlm_cpuid_to_node(cpu);
|
||||
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
|
||||
xlp_mmu_init();
|
||||
#endif
|
||||
write_c0_ebase(nlm_current_node()->ebase);
|
||||
}
|
||||
|
||||
/*
|
||||
* Code to run on secondary just after probing the CPU
|
||||
*/
|
||||
static void 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();
|
||||
}
|
||||
|
||||
/*
|
||||
* Boot all other cpus in the system, initialize them, and bring them into
|
||||
* the boot function
|
||||
*/
|
||||
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 = nlm_cpuid_to_node(logical_cpu);
|
||||
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, node;
|
||||
volatile u32 *cpu_ready = nlm_get_boot_data(BOOT_CPU_READY);
|
||||
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++) {
|
||||
/*
|
||||
* cpu_ready array is not set for the boot_cpu,
|
||||
* it is only set for ASPs (see smpboot.S)
|
||||
*/
|
||||
if (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);
|
||||
node = nlm_cpuid_to_node(i);
|
||||
cpumask_set_cpu(num_cpus, &nlm_get_node(node)->cpumask);
|
||||
++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 woken 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;
|
||||
char buf[64];
|
||||
|
||||
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:
|
||||
cpumask_scnprintf(buf, ARRAY_SIZE(buf), wakeup_mask);
|
||||
panic("Unsupported CPU mask %s", buf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int nlm_wakeup_secondary_cpus(void)
|
||||
{
|
||||
u32 *reset_data;
|
||||
int threadmode;
|
||||
|
||||
/* verify the mask and setup core config variables */
|
||||
threadmode = nlm_parse_cpumask(&nlm_cpumask);
|
||||
|
||||
/* Setup CPU init parameters */
|
||||
reset_data = nlm_get_boot_data(BOOT_THREAD_MODE);
|
||||
*reset_data = 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,
|
||||
.boot_secondary = nlm_boot_secondary,
|
||||
.smp_setup = nlm_smp_setup,
|
||||
.prepare_cpus = nlm_prepare_cpus,
|
||||
};
|
143
arch/mips/netlogic/common/smpboot.S
Normal file
143
arch/mips/netlogic/common/smpboot.S
Normal file
|
@ -0,0 +1,143 @@
|
|||
/*
|
||||
* 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 <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
|
||||
|
||||
.set noreorder
|
||||
.set noat
|
||||
.set arch=xlr /* for mfcr/mtcr, XLR is sufficient */
|
||||
|
||||
/* Called by the boot cpu to wake up its sibling threads */
|
||||
NESTED(xlp_boot_core0_siblings, PT_SIZE, sp)
|
||||
/* CPU register contents lost when enabling threads, save them first */
|
||||
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 */
|
||||
jalr t2
|
||||
nop
|
||||
RESTORE_ALL
|
||||
jr ra
|
||||
nop
|
||||
END(xlp_boot_core0_siblings)
|
||||
|
||||
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)
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
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 */
|
||||
|
||||
li t3, CKSEG1ADDR(RESET_DATA_PHYS)
|
||||
ADDIU t1, t3, BOOT_CPU_READY
|
||||
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 */
|
||||
|
||||
/* wait for NMI to hit */
|
||||
1: wait
|
||||
b 1b
|
||||
nop
|
||||
END(nlm_rmiboot_preboot)
|
111
arch/mips/netlogic/common/time.c
Normal file
111
arch/mips/netlogic/common/time.c
Normal file
|
@ -0,0 +1,111 @@
|
|||
/*
|
||||
* 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/sys.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 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;
|
||||
u32 picfreq;
|
||||
|
||||
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;
|
||||
picfreq = pic_timer_freq();
|
||||
clocksource_register_hz(&csrc_pic, picfreq);
|
||||
pr_info("PIC clock source added, frequency %d\n", picfreq);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
10
arch/mips/netlogic/xlp/Makefile
Normal file
10
arch/mips/netlogic/xlp/Makefile
Normal file
|
@ -0,0 +1,10 @@
|
|||
obj-y += setup.o nlm_hal.o cop2-ex.o dt.o
|
||||
obj-$(CONFIG_SMP) += wakeup.o
|
||||
ifdef CONFIG_USB
|
||||
obj-y += usb-init.o
|
||||
obj-y += usb-init-xlp2.o
|
||||
endif
|
||||
ifdef CONFIG_SATA_AHCI
|
||||
obj-y += ahci-init.o
|
||||
obj-y += ahci-init-xlp2.o
|
||||
endif
|
390
arch/mips/netlogic/xlp/ahci-init-xlp2.c
Normal file
390
arch/mips/netlogic/xlp/ahci-init-xlp2.c
Normal file
|
@ -0,0 +1,390 @@
|
|||
/*
|
||||
* Copyright (c) 2003-2014 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/irq.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/pci_ids.h>
|
||||
#include <linux/nodemask.h>
|
||||
|
||||
#include <asm/cpu.h>
|
||||
#include <asm/mipsregs.h>
|
||||
|
||||
#include <asm/netlogic/common.h>
|
||||
#include <asm/netlogic/haldefs.h>
|
||||
#include <asm/netlogic/mips-extns.h>
|
||||
#include <asm/netlogic/xlp-hal/xlp.h>
|
||||
#include <asm/netlogic/xlp-hal/iomap.h>
|
||||
|
||||
#define SATA_CTL 0x0
|
||||
#define SATA_STATUS 0x1 /* Status Reg */
|
||||
#define SATA_INT 0x2 /* Interrupt Reg */
|
||||
#define SATA_INT_MASK 0x3 /* Interrupt Mask Reg */
|
||||
#define SATA_BIU_TIMEOUT 0x4
|
||||
#define AXIWRSPERRLOG 0x5
|
||||
#define AXIRDSPERRLOG 0x6
|
||||
#define BiuTimeoutLow 0x7
|
||||
#define BiuTimeoutHi 0x8
|
||||
#define BiuSlvErLow 0x9
|
||||
#define BiuSlvErHi 0xa
|
||||
#define IO_CONFIG_SWAP_DIS 0xb
|
||||
#define CR_REG_TIMER 0xc
|
||||
#define CORE_ID 0xd
|
||||
#define AXI_SLAVE_OPT1 0xe
|
||||
#define PHY_MEM_ACCESS 0xf
|
||||
#define PHY0_CNTRL 0x10
|
||||
#define PHY0_STAT 0x11
|
||||
#define PHY0_RX_ALIGN 0x12
|
||||
#define PHY0_RX_EQ_LO 0x13
|
||||
#define PHY0_RX_EQ_HI 0x14
|
||||
#define PHY0_BIST_LOOP 0x15
|
||||
#define PHY1_CNTRL 0x16
|
||||
#define PHY1_STAT 0x17
|
||||
#define PHY1_RX_ALIGN 0x18
|
||||
#define PHY1_RX_EQ_LO 0x19
|
||||
#define PHY1_RX_EQ_HI 0x1a
|
||||
#define PHY1_BIST_LOOP 0x1b
|
||||
#define RdExBase 0x1c
|
||||
#define RdExLimit 0x1d
|
||||
#define CacheAllocBase 0x1e
|
||||
#define CacheAllocLimit 0x1f
|
||||
#define BiuSlaveCmdGstNum 0x20
|
||||
|
||||
/*SATA_CTL Bits */
|
||||
#define SATA_RST_N BIT(0) /* Active low reset sata_core phy */
|
||||
#define SataCtlReserve0 BIT(1)
|
||||
#define M_CSYSREQ BIT(2) /* AXI master low power, not used */
|
||||
#define S_CSYSREQ BIT(3) /* AXI slave low power, not used */
|
||||
#define P0_CP_DET BIT(8) /* Reserved, bring in from pad */
|
||||
#define P0_MP_SW BIT(9) /* Mech Switch */
|
||||
#define P0_DISABLE BIT(10) /* disable p0 */
|
||||
#define P0_ACT_LED_EN BIT(11) /* Active LED enable */
|
||||
#define P0_IRST_HARD_SYNTH BIT(12) /* PHY hard synth reset */
|
||||
#define P0_IRST_HARD_TXRX BIT(13) /* PHY lane hard reset */
|
||||
#define P0_IRST_POR BIT(14) /* PHY power on reset*/
|
||||
#define P0_IPDTXL BIT(15) /* PHY Tx lane dis/power down */
|
||||
#define P0_IPDRXL BIT(16) /* PHY Rx lane dis/power down */
|
||||
#define P0_IPDIPDMSYNTH BIT(17) /* PHY synthesizer dis/porwer down */
|
||||
#define P0_CP_POD_EN BIT(18) /* CP_POD enable */
|
||||
#define P0_AT_BYPASS BIT(19) /* P0 address translation by pass */
|
||||
#define P1_CP_DET BIT(20) /* Reserved,Cold Detect */
|
||||
#define P1_MP_SW BIT(21) /* Mech Switch */
|
||||
#define P1_DISABLE BIT(22) /* disable p1 */
|
||||
#define P1_ACT_LED_EN BIT(23) /* Active LED enable */
|
||||
#define P1_IRST_HARD_SYNTH BIT(24) /* PHY hard synth reset */
|
||||
#define P1_IRST_HARD_TXRX BIT(25) /* PHY lane hard reset */
|
||||
#define P1_IRST_POR BIT(26) /* PHY power on reset*/
|
||||
#define P1_IPDTXL BIT(27) /* PHY Tx lane dis/porwer down */
|
||||
#define P1_IPDRXL BIT(28) /* PHY Rx lane dis/porwer down */
|
||||
#define P1_IPDIPDMSYNTH BIT(29) /* PHY synthesizer dis/porwer down */
|
||||
#define P1_CP_POD_EN BIT(30)
|
||||
#define P1_AT_BYPASS BIT(31) /* P1 address translation by pass */
|
||||
|
||||
/* Status register */
|
||||
#define M_CACTIVE BIT(0) /* m_cactive, not used */
|
||||
#define S_CACTIVE BIT(1) /* s_cactive, not used */
|
||||
#define P0_PHY_READY BIT(8) /* phy is ready */
|
||||
#define P0_CP_POD BIT(9) /* Cold PowerOn */
|
||||
#define P0_SLUMBER BIT(10) /* power mode slumber */
|
||||
#define P0_PATIAL BIT(11) /* power mode patial */
|
||||
#define P0_PHY_SIG_DET BIT(12) /* phy dignal detect */
|
||||
#define P0_PHY_CALI BIT(13) /* phy calibration done */
|
||||
#define P1_PHY_READY BIT(16) /* phy is ready */
|
||||
#define P1_CP_POD BIT(17) /* Cold PowerOn */
|
||||
#define P1_SLUMBER BIT(18) /* power mode slumber */
|
||||
#define P1_PATIAL BIT(19) /* power mode patial */
|
||||
#define P1_PHY_SIG_DET BIT(20) /* phy dignal detect */
|
||||
#define P1_PHY_CALI BIT(21) /* phy calibration done */
|
||||
|
||||
/* SATA CR_REG_TIMER bits */
|
||||
#define CR_TIME_SCALE (0x1000 << 0)
|
||||
|
||||
/* SATA PHY specific registers start and end address */
|
||||
#define RXCDRCALFOSC0 0x0065
|
||||
#define CALDUTY 0x006e
|
||||
#define RXDPIF 0x8065
|
||||
#define PPMDRIFTMAX_HI 0x80A4
|
||||
|
||||
#define nlm_read_sata_reg(b, r) nlm_read_reg(b, r)
|
||||
#define nlm_write_sata_reg(b, r, v) nlm_write_reg(b, r, v)
|
||||
#define nlm_get_sata_pcibase(node) \
|
||||
nlm_pcicfg_base(XLP9XX_IO_SATA_OFFSET(node))
|
||||
#define nlm_get_sata_regbase(node) \
|
||||
(nlm_get_sata_pcibase(node) + 0x100)
|
||||
|
||||
/* SATA PHY config for register block 1 0x0065 .. 0x006e */
|
||||
static const u8 sata_phy_config1[] = {
|
||||
0xC9, 0xC9, 0x07, 0x07, 0x18, 0x18, 0x01, 0x01, 0x22, 0x00
|
||||
};
|
||||
|
||||
/* SATA PHY config for register block 2 0x0x8065 .. 0x0x80A4 */
|
||||
static const u8 sata_phy_config2[] = {
|
||||
0xAA, 0x00, 0x4C, 0xC9, 0xC9, 0x07, 0x07, 0x18,
|
||||
0x18, 0x05, 0x0C, 0x10, 0x00, 0x10, 0x00, 0xFF,
|
||||
0xCF, 0xF7, 0xE1, 0xF5, 0xFD, 0xFD, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xE3, 0xE7, 0xDB, 0xF5, 0xFD, 0xFD,
|
||||
0xF5, 0xF5, 0xFF, 0xFF, 0xE3, 0xE7, 0xDB, 0xF5,
|
||||
0xFD, 0xFD, 0xF5, 0xF5, 0xFF, 0xFF, 0xFF, 0xF5,
|
||||
0x3F, 0x00, 0x32, 0x00, 0x03, 0x01, 0x05, 0x05,
|
||||
0x04, 0x00, 0x00, 0x08, 0x04, 0x00, 0x00, 0x04,
|
||||
};
|
||||
|
||||
const int sata_phy_debug = 0; /* set to verify PHY writes */
|
||||
|
||||
static void sata_clear_glue_reg(u64 regbase, u32 off, u32 bit)
|
||||
{
|
||||
u32 reg_val;
|
||||
|
||||
reg_val = nlm_read_sata_reg(regbase, off);
|
||||
nlm_write_sata_reg(regbase, off, (reg_val & ~bit));
|
||||
}
|
||||
|
||||
static void sata_set_glue_reg(u64 regbase, u32 off, u32 bit)
|
||||
{
|
||||
u32 reg_val;
|
||||
|
||||
reg_val = nlm_read_sata_reg(regbase, off);
|
||||
nlm_write_sata_reg(regbase, off, (reg_val | bit));
|
||||
}
|
||||
|
||||
static void write_phy_reg(u64 regbase, u32 addr, u32 physel, u8 data)
|
||||
{
|
||||
nlm_write_sata_reg(regbase, PHY_MEM_ACCESS,
|
||||
(1u << 31) | (physel << 24) | (data << 16) | addr);
|
||||
udelay(850);
|
||||
}
|
||||
|
||||
static u8 read_phy_reg(u64 regbase, u32 addr, u32 physel)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
nlm_write_sata_reg(regbase, PHY_MEM_ACCESS,
|
||||
(0 << 31) | (physel << 24) | (0 << 16) | addr);
|
||||
udelay(850);
|
||||
val = nlm_read_sata_reg(regbase, PHY_MEM_ACCESS);
|
||||
return (val >> 16) & 0xff;
|
||||
}
|
||||
|
||||
static void config_sata_phy(u64 regbase)
|
||||
{
|
||||
u32 port, i, reg;
|
||||
u8 val;
|
||||
|
||||
for (port = 0; port < 2; port++) {
|
||||
for (i = 0, reg = RXCDRCALFOSC0; reg <= CALDUTY; reg++, i++)
|
||||
write_phy_reg(regbase, reg, port, sata_phy_config1[i]);
|
||||
|
||||
for (i = 0, reg = RXDPIF; reg <= PPMDRIFTMAX_HI; reg++, i++)
|
||||
write_phy_reg(regbase, reg, port, sata_phy_config2[i]);
|
||||
|
||||
/* Fix for PHY link up failures at lower temperatures */
|
||||
write_phy_reg(regbase, 0x800F, port, 0x1f);
|
||||
|
||||
val = read_phy_reg(regbase, 0x0029, port);
|
||||
write_phy_reg(regbase, 0x0029, port, val | (0x7 << 1));
|
||||
|
||||
val = read_phy_reg(regbase, 0x0056, port);
|
||||
write_phy_reg(regbase, 0x0056, port, val & ~(1 << 3));
|
||||
|
||||
val = read_phy_reg(regbase, 0x0018, port);
|
||||
write_phy_reg(regbase, 0x0018, port, val & ~(0x7 << 0));
|
||||
}
|
||||
}
|
||||
|
||||
static void check_phy_register(u64 regbase, u32 addr, u32 physel, u8 xdata)
|
||||
{
|
||||
u8 data;
|
||||
|
||||
data = read_phy_reg(regbase, addr, physel);
|
||||
pr_info("PHY read addr = 0x%x physel = %d data = 0x%x %s\n",
|
||||
addr, physel, data, data == xdata ? "TRUE" : "FALSE");
|
||||
}
|
||||
|
||||
static void verify_sata_phy_config(u64 regbase)
|
||||
{
|
||||
u32 port, i, reg;
|
||||
|
||||
for (port = 0; port < 2; port++) {
|
||||
for (i = 0, reg = RXCDRCALFOSC0; reg <= CALDUTY; reg++, i++)
|
||||
check_phy_register(regbase, reg, port,
|
||||
sata_phy_config1[i]);
|
||||
|
||||
for (i = 0, reg = RXDPIF; reg <= PPMDRIFTMAX_HI; reg++, i++)
|
||||
check_phy_register(regbase, reg, port,
|
||||
sata_phy_config2[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static void nlm_sata_firmware_init(int node)
|
||||
{
|
||||
u32 reg_val;
|
||||
u64 regbase;
|
||||
int n;
|
||||
|
||||
pr_info("Initializing XLP9XX On-chip AHCI...\n");
|
||||
regbase = nlm_get_sata_regbase(node);
|
||||
|
||||
/* Reset port0 */
|
||||
sata_clear_glue_reg(regbase, SATA_CTL, P0_IRST_POR);
|
||||
sata_clear_glue_reg(regbase, SATA_CTL, P0_IRST_HARD_TXRX);
|
||||
sata_clear_glue_reg(regbase, SATA_CTL, P0_IRST_HARD_SYNTH);
|
||||
sata_clear_glue_reg(regbase, SATA_CTL, P0_IPDTXL);
|
||||
sata_clear_glue_reg(regbase, SATA_CTL, P0_IPDRXL);
|
||||
sata_clear_glue_reg(regbase, SATA_CTL, P0_IPDIPDMSYNTH);
|
||||
|
||||
/* port1 */
|
||||
sata_clear_glue_reg(regbase, SATA_CTL, P1_IRST_POR);
|
||||
sata_clear_glue_reg(regbase, SATA_CTL, P1_IRST_HARD_TXRX);
|
||||
sata_clear_glue_reg(regbase, SATA_CTL, P1_IRST_HARD_SYNTH);
|
||||
sata_clear_glue_reg(regbase, SATA_CTL, P1_IPDTXL);
|
||||
sata_clear_glue_reg(regbase, SATA_CTL, P1_IPDRXL);
|
||||
sata_clear_glue_reg(regbase, SATA_CTL, P1_IPDIPDMSYNTH);
|
||||
udelay(300);
|
||||
|
||||
/* Set PHY */
|
||||
sata_set_glue_reg(regbase, SATA_CTL, P0_IPDTXL);
|
||||
sata_set_glue_reg(regbase, SATA_CTL, P0_IPDRXL);
|
||||
sata_set_glue_reg(regbase, SATA_CTL, P0_IPDIPDMSYNTH);
|
||||
sata_set_glue_reg(regbase, SATA_CTL, P1_IPDTXL);
|
||||
sata_set_glue_reg(regbase, SATA_CTL, P1_IPDRXL);
|
||||
sata_set_glue_reg(regbase, SATA_CTL, P1_IPDIPDMSYNTH);
|
||||
|
||||
udelay(1000);
|
||||
sata_set_glue_reg(regbase, SATA_CTL, P0_IRST_POR);
|
||||
udelay(1000);
|
||||
sata_set_glue_reg(regbase, SATA_CTL, P1_IRST_POR);
|
||||
udelay(1000);
|
||||
|
||||
/* setup PHY */
|
||||
config_sata_phy(regbase);
|
||||
if (sata_phy_debug)
|
||||
verify_sata_phy_config(regbase);
|
||||
|
||||
udelay(1000);
|
||||
sata_set_glue_reg(regbase, SATA_CTL, P0_IRST_HARD_TXRX);
|
||||
sata_set_glue_reg(regbase, SATA_CTL, P0_IRST_HARD_SYNTH);
|
||||
sata_set_glue_reg(regbase, SATA_CTL, P1_IRST_HARD_TXRX);
|
||||
sata_set_glue_reg(regbase, SATA_CTL, P1_IRST_HARD_SYNTH);
|
||||
udelay(300);
|
||||
|
||||
/* Override reset in serial PHY mode */
|
||||
sata_set_glue_reg(regbase, CR_REG_TIMER, CR_TIME_SCALE);
|
||||
/* Set reset SATA */
|
||||
sata_set_glue_reg(regbase, SATA_CTL, SATA_RST_N);
|
||||
sata_set_glue_reg(regbase, SATA_CTL, M_CSYSREQ);
|
||||
sata_set_glue_reg(regbase, SATA_CTL, S_CSYSREQ);
|
||||
|
||||
pr_debug("Waiting for PHYs to come up.\n");
|
||||
n = 10000;
|
||||
do {
|
||||
reg_val = nlm_read_sata_reg(regbase, SATA_STATUS);
|
||||
if ((reg_val & P1_PHY_READY) && (reg_val & P0_PHY_READY))
|
||||
break;
|
||||
udelay(10);
|
||||
} while (--n > 0);
|
||||
|
||||
if (reg_val & P0_PHY_READY)
|
||||
pr_info("PHY0 is up.\n");
|
||||
else
|
||||
pr_info("PHY0 is down.\n");
|
||||
if (reg_val & P1_PHY_READY)
|
||||
pr_info("PHY1 is up.\n");
|
||||
else
|
||||
pr_info("PHY1 is down.\n");
|
||||
|
||||
pr_info("XLP AHCI Init Done.\n");
|
||||
}
|
||||
|
||||
static int __init nlm_ahci_init(void)
|
||||
{
|
||||
int node;
|
||||
|
||||
if (!cpu_is_xlp9xx())
|
||||
return 0;
|
||||
for (node = 0; node < NLM_NR_NODES; node++)
|
||||
if (nlm_node_present(node))
|
||||
nlm_sata_firmware_init(node);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void nlm_sata_intr_ack(struct irq_data *data)
|
||||
{
|
||||
u64 regbase;
|
||||
u32 val;
|
||||
int node;
|
||||
|
||||
node = data->irq / NLM_IRQS_PER_NODE;
|
||||
regbase = nlm_get_sata_regbase(node);
|
||||
val = nlm_read_sata_reg(regbase, SATA_INT);
|
||||
sata_set_glue_reg(regbase, SATA_INT, val);
|
||||
}
|
||||
|
||||
static void nlm_sata_fixup_bar(struct pci_dev *dev)
|
||||
{
|
||||
dev->resource[5] = dev->resource[0];
|
||||
memset(&dev->resource[0], 0, sizeof(dev->resource[0]));
|
||||
}
|
||||
|
||||
static void nlm_sata_fixup_final(struct pci_dev *dev)
|
||||
{
|
||||
u32 val;
|
||||
u64 regbase;
|
||||
int node;
|
||||
|
||||
/* Find end bridge function to find node */
|
||||
node = xlp_socdev_to_node(dev);
|
||||
regbase = nlm_get_sata_regbase(node);
|
||||
|
||||
/* clear pending interrupts and then enable them */
|
||||
val = nlm_read_sata_reg(regbase, SATA_INT);
|
||||
sata_set_glue_reg(regbase, SATA_INT, val);
|
||||
|
||||
/* Enable only the core interrupt */
|
||||
sata_set_glue_reg(regbase, SATA_INT_MASK, 0x1);
|
||||
|
||||
dev->irq = nlm_irq_to_xirq(node, PIC_SATA_IRQ);
|
||||
nlm_set_pic_extra_ack(node, PIC_SATA_IRQ, nlm_sata_intr_ack);
|
||||
}
|
||||
|
||||
arch_initcall(nlm_ahci_init);
|
||||
|
||||
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_XLP9XX_SATA,
|
||||
nlm_sata_fixup_bar);
|
||||
|
||||
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_XLP9XX_SATA,
|
||||
nlm_sata_fixup_final);
|
209
arch/mips/netlogic/xlp/ahci-init.c
Normal file
209
arch/mips/netlogic/xlp/ahci-init.c
Normal file
|
@ -0,0 +1,209 @@
|
|||
/*
|
||||
* Copyright (c) 2003-2014 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/irq.h>
|
||||
#include <linux/bitops.h>
|
||||
|
||||
#include <asm/cpu.h>
|
||||
#include <asm/mipsregs.h>
|
||||
|
||||
#include <asm/netlogic/haldefs.h>
|
||||
#include <asm/netlogic/xlp-hal/xlp.h>
|
||||
#include <asm/netlogic/common.h>
|
||||
#include <asm/netlogic/xlp-hal/iomap.h>
|
||||
#include <asm/netlogic/mips-extns.h>
|
||||
|
||||
#define SATA_CTL 0x0
|
||||
#define SATA_STATUS 0x1 /* Status Reg */
|
||||
#define SATA_INT 0x2 /* Interrupt Reg */
|
||||
#define SATA_INT_MASK 0x3 /* Interrupt Mask Reg */
|
||||
#define SATA_CR_REG_TIMER 0x4 /* PHY Conrol Timer Reg */
|
||||
#define SATA_CORE_ID 0x5 /* Core ID Reg */
|
||||
#define SATA_AXI_SLAVE_OPT1 0x6 /* AXI Slave Options Reg */
|
||||
#define SATA_PHY_LOS_LEV 0x7 /* PHY LOS Level Reg */
|
||||
#define SATA_PHY_MULTI 0x8 /* PHY Multiplier Reg */
|
||||
#define SATA_PHY_CLK_SEL 0x9 /* Clock Select Reg */
|
||||
#define SATA_PHY_AMP1_GEN1 0xa /* PHY Transmit Amplitude Reg 1 */
|
||||
#define SATA_PHY_AMP1_GEN2 0xb /* PHY Transmit Amplitude Reg 2 */
|
||||
#define SATA_PHY_AMP1_GEN3 0xc /* PHY Transmit Amplitude Reg 3 */
|
||||
#define SATA_PHY_PRE1 0xd /* PHY Transmit Preemphasis Reg 1 */
|
||||
#define SATA_PHY_PRE2 0xe /* PHY Transmit Preemphasis Reg 2 */
|
||||
#define SATA_PHY_PRE3 0xf /* PHY Transmit Preemphasis Reg 3 */
|
||||
#define SATA_SPDMODE 0x10 /* Speed Mode Reg */
|
||||
#define SATA_REFCLK 0x11 /* Reference Clock Control Reg */
|
||||
#define SATA_BYTE_SWAP_DIS 0x12 /* byte swap disable */
|
||||
|
||||
/*SATA_CTL Bits */
|
||||
#define SATA_RST_N BIT(0)
|
||||
#define PHY0_RESET_N BIT(16)
|
||||
#define PHY1_RESET_N BIT(17)
|
||||
#define PHY2_RESET_N BIT(18)
|
||||
#define PHY3_RESET_N BIT(19)
|
||||
#define M_CSYSREQ BIT(2)
|
||||
#define S_CSYSREQ BIT(3)
|
||||
|
||||
/*SATA_STATUS Bits */
|
||||
#define P0_PHY_READY BIT(4)
|
||||
#define P1_PHY_READY BIT(5)
|
||||
#define P2_PHY_READY BIT(6)
|
||||
#define P3_PHY_READY BIT(7)
|
||||
|
||||
#define nlm_read_sata_reg(b, r) nlm_read_reg(b, r)
|
||||
#define nlm_write_sata_reg(b, r, v) nlm_write_reg(b, r, v)
|
||||
#define nlm_get_sata_pcibase(node) \
|
||||
nlm_pcicfg_base(XLP_IO_SATA_OFFSET(node))
|
||||
/* SATA device specific configuration registers are starts at 0x900 offset */
|
||||
#define nlm_get_sata_regbase(node) \
|
||||
(nlm_get_sata_pcibase(node) + 0x900)
|
||||
|
||||
static void sata_clear_glue_reg(uint64_t regbase, uint32_t off, uint32_t bit)
|
||||
{
|
||||
uint32_t reg_val;
|
||||
|
||||
reg_val = nlm_read_sata_reg(regbase, off);
|
||||
nlm_write_sata_reg(regbase, off, (reg_val & ~bit));
|
||||
}
|
||||
|
||||
static void sata_set_glue_reg(uint64_t regbase, uint32_t off, uint32_t bit)
|
||||
{
|
||||
uint32_t reg_val;
|
||||
|
||||
reg_val = nlm_read_sata_reg(regbase, off);
|
||||
nlm_write_sata_reg(regbase, off, (reg_val | bit));
|
||||
}
|
||||
|
||||
static void nlm_sata_firmware_init(int node)
|
||||
{
|
||||
uint32_t reg_val;
|
||||
uint64_t regbase;
|
||||
int i;
|
||||
|
||||
pr_info("XLP AHCI Initialization started.\n");
|
||||
regbase = nlm_get_sata_regbase(node);
|
||||
|
||||
/* Reset SATA */
|
||||
sata_clear_glue_reg(regbase, SATA_CTL, SATA_RST_N);
|
||||
/* Reset PHY */
|
||||
sata_clear_glue_reg(regbase, SATA_CTL,
|
||||
(PHY3_RESET_N | PHY2_RESET_N
|
||||
| PHY1_RESET_N | PHY0_RESET_N));
|
||||
|
||||
/* Set SATA */
|
||||
sata_set_glue_reg(regbase, SATA_CTL, SATA_RST_N);
|
||||
/* Set PHY */
|
||||
sata_set_glue_reg(regbase, SATA_CTL,
|
||||
(PHY3_RESET_N | PHY2_RESET_N
|
||||
| PHY1_RESET_N | PHY0_RESET_N));
|
||||
|
||||
pr_debug("Waiting for PHYs to come up.\n");
|
||||
i = 0;
|
||||
do {
|
||||
reg_val = nlm_read_sata_reg(regbase, SATA_STATUS);
|
||||
i++;
|
||||
} while (((reg_val & 0xF0) != 0xF0) && (i < 10000));
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
if (reg_val & (P0_PHY_READY << i))
|
||||
pr_info("PHY%d is up.\n", i);
|
||||
else
|
||||
pr_info("PHY%d is down.\n", i);
|
||||
}
|
||||
|
||||
pr_info("XLP AHCI init done.\n");
|
||||
}
|
||||
|
||||
static int __init nlm_ahci_init(void)
|
||||
{
|
||||
int node = 0;
|
||||
int chip = read_c0_prid() & PRID_REV_MASK;
|
||||
|
||||
if (chip == PRID_IMP_NETLOGIC_XLP3XX)
|
||||
nlm_sata_firmware_init(node);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void nlm_sata_intr_ack(struct irq_data *data)
|
||||
{
|
||||
uint32_t val = 0;
|
||||
uint64_t regbase;
|
||||
|
||||
regbase = nlm_get_sata_regbase(nlm_nodeid());
|
||||
val = nlm_read_sata_reg(regbase, SATA_INT);
|
||||
sata_set_glue_reg(regbase, SATA_INT, val);
|
||||
}
|
||||
|
||||
static void nlm_sata_fixup_bar(struct pci_dev *dev)
|
||||
{
|
||||
/*
|
||||
* The AHCI resource is in BAR 0, move it to
|
||||
* BAR 5, where it is expected
|
||||
*/
|
||||
dev->resource[5] = dev->resource[0];
|
||||
memset(&dev->resource[0], 0, sizeof(dev->resource[0]));
|
||||
}
|
||||
|
||||
static void nlm_sata_fixup_final(struct pci_dev *dev)
|
||||
{
|
||||
uint32_t val;
|
||||
uint64_t regbase;
|
||||
int node = 0; /* XLP3XX does not support multi-node */
|
||||
|
||||
regbase = nlm_get_sata_regbase(node);
|
||||
|
||||
/* clear pending interrupts and then enable them */
|
||||
val = nlm_read_sata_reg(regbase, SATA_INT);
|
||||
sata_set_glue_reg(regbase, SATA_INT, val);
|
||||
|
||||
/* Mask the core interrupt. If all the interrupts
|
||||
* are enabled there are spurious interrupt flow
|
||||
* happening, to avoid only enable core interrupt
|
||||
* mask.
|
||||
*/
|
||||
sata_set_glue_reg(regbase, SATA_INT_MASK, 0x1);
|
||||
|
||||
dev->irq = PIC_SATA_IRQ;
|
||||
nlm_set_pic_extra_ack(node, PIC_SATA_IRQ, nlm_sata_intr_ack);
|
||||
}
|
||||
|
||||
arch_initcall(nlm_ahci_init);
|
||||
|
||||
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_NETLOGIC, PCI_DEVICE_ID_NLM_SATA,
|
||||
nlm_sata_fixup_bar);
|
||||
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_NETLOGIC, PCI_DEVICE_ID_NLM_SATA,
|
||||
nlm_sata_fixup_final);
|
118
arch/mips/netlogic/xlp/cop2-ex.c
Normal file
118
arch/mips/netlogic/xlp/cop2-ex.c
Normal file
|
@ -0,0 +1,118 @@
|
|||
/*
|
||||
* This file is subject to the terms and conditions of the GNU General Public
|
||||
* License. See the file "COPYING" in the main directory of this archive
|
||||
* for more details.
|
||||
*
|
||||
* Copyright (C) 2013 Broadcom Corporation.
|
||||
*
|
||||
* based on arch/mips/cavium-octeon/cpu.c
|
||||
* Copyright (C) 2009 Wind River Systems,
|
||||
* written by Ralf Baechle <ralf@linux-mips.org>
|
||||
*/
|
||||
#include <linux/init.h>
|
||||
#include <linux/irqflags.h>
|
||||
#include <linux/notifier.h>
|
||||
#include <linux/prefetch.h>
|
||||
#include <linux/sched.h>
|
||||
|
||||
#include <asm/cop2.h>
|
||||
#include <asm/current.h>
|
||||
#include <asm/mipsregs.h>
|
||||
#include <asm/page.h>
|
||||
|
||||
#include <asm/netlogic/mips-extns.h>
|
||||
|
||||
/*
|
||||
* 64 bit ops are done in inline assembly to support 32 bit
|
||||
* compilation
|
||||
*/
|
||||
void nlm_cop2_save(struct nlm_cop2_state *r)
|
||||
{
|
||||
asm volatile(
|
||||
".set push\n"
|
||||
".set noat\n"
|
||||
"dmfc2 $1, $0, 0\n"
|
||||
"sd $1, 0(%1)\n"
|
||||
"dmfc2 $1, $0, 1\n"
|
||||
"sd $1, 8(%1)\n"
|
||||
"dmfc2 $1, $0, 2\n"
|
||||
"sd $1, 16(%1)\n"
|
||||
"dmfc2 $1, $0, 3\n"
|
||||
"sd $1, 24(%1)\n"
|
||||
"dmfc2 $1, $1, 0\n"
|
||||
"sd $1, 0(%2)\n"
|
||||
"dmfc2 $1, $1, 1\n"
|
||||
"sd $1, 8(%2)\n"
|
||||
"dmfc2 $1, $1, 2\n"
|
||||
"sd $1, 16(%2)\n"
|
||||
"dmfc2 $1, $1, 3\n"
|
||||
"sd $1, 24(%2)\n"
|
||||
".set pop\n"
|
||||
: "=m"(*r)
|
||||
: "r"(r->tx), "r"(r->rx));
|
||||
|
||||
r->tx_msg_status = __read_32bit_c2_register($2, 0);
|
||||
r->rx_msg_status = __read_32bit_c2_register($3, 0) & 0x0fffffff;
|
||||
}
|
||||
|
||||
void nlm_cop2_restore(struct nlm_cop2_state *r)
|
||||
{
|
||||
u32 rstat;
|
||||
|
||||
asm volatile(
|
||||
".set push\n"
|
||||
".set noat\n"
|
||||
"ld $1, 0(%1)\n"
|
||||
"dmtc2 $1, $0, 0\n"
|
||||
"ld $1, 8(%1)\n"
|
||||
"dmtc2 $1, $0, 1\n"
|
||||
"ld $1, 16(%1)\n"
|
||||
"dmtc2 $1, $0, 2\n"
|
||||
"ld $1, 24(%1)\n"
|
||||
"dmtc2 $1, $0, 3\n"
|
||||
"ld $1, 0(%2)\n"
|
||||
"dmtc2 $1, $1, 0\n"
|
||||
"ld $1, 8(%2)\n"
|
||||
"dmtc2 $1, $1, 1\n"
|
||||
"ld $1, 16(%2)\n"
|
||||
"dmtc2 $1, $1, 2\n"
|
||||
"ld $1, 24(%2)\n"
|
||||
"dmtc2 $1, $1, 3\n"
|
||||
".set pop\n"
|
||||
: : "m"(*r), "r"(r->tx), "r"(r->rx));
|
||||
|
||||
__write_32bit_c2_register($2, 0, r->tx_msg_status);
|
||||
rstat = __read_32bit_c2_register($3, 0) & 0xf0000000u;
|
||||
__write_32bit_c2_register($3, 0, r->rx_msg_status | rstat);
|
||||
}
|
||||
|
||||
static int nlm_cu2_call(struct notifier_block *nfb, unsigned long action,
|
||||
void *data)
|
||||
{
|
||||
unsigned long flags;
|
||||
unsigned int status;
|
||||
|
||||
switch (action) {
|
||||
case CU2_EXCEPTION:
|
||||
if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO))
|
||||
break;
|
||||
local_irq_save(flags);
|
||||
KSTK_STATUS(current) |= ST0_CU2;
|
||||
status = read_c0_status();
|
||||
write_c0_status(status | ST0_CU2);
|
||||
nlm_cop2_restore(&(current->thread.cp2));
|
||||
write_c0_status(status & ~ST0_CU2);
|
||||
local_irq_restore(flags);
|
||||
pr_info("COP2 access enabled for pid %d (%s)\n",
|
||||
current->pid, current->comm);
|
||||
return NOTIFY_BAD; /* Don't call default notifier */
|
||||
}
|
||||
|
||||
return NOTIFY_OK; /* Let default notifier send signals */
|
||||
}
|
||||
|
||||
static int __init nlm_cu2_setup(void)
|
||||
{
|
||||
return cu2_notifier(nlm_cu2_call, 0);
|
||||
}
|
||||
early_initcall(nlm_cu2_setup);
|
106
arch/mips/netlogic/xlp/dt.c
Normal file
106
arch/mips/netlogic/xlp/dt.c
Normal file
|
@ -0,0 +1,106 @@
|
|||
/*
|
||||
* Copyright 2003-2013 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/bootmem.h>
|
||||
|
||||
#include <linux/of_fdt.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/of_device.h>
|
||||
|
||||
#include <asm/prom.h>
|
||||
|
||||
extern u32 __dtb_xlp_evp_begin[], __dtb_xlp_svp_begin[],
|
||||
__dtb_xlp_fvp_begin[], __dtb_xlp_gvp_begin[];
|
||||
static void *xlp_fdt_blob;
|
||||
|
||||
void __init *xlp_dt_init(void *fdtp)
|
||||
{
|
||||
if (!fdtp) {
|
||||
switch (current_cpu_data.processor_id & PRID_IMP_MASK) {
|
||||
#ifdef CONFIG_DT_XLP_GVP
|
||||
case PRID_IMP_NETLOGIC_XLP9XX:
|
||||
case PRID_IMP_NETLOGIC_XLP5XX:
|
||||
fdtp = __dtb_xlp_gvp_begin;
|
||||
break;
|
||||
#endif
|
||||
#ifdef CONFIG_DT_XLP_FVP
|
||||
case PRID_IMP_NETLOGIC_XLP2XX:
|
||||
fdtp = __dtb_xlp_fvp_begin;
|
||||
break;
|
||||
#endif
|
||||
#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;
|
||||
}
|
||||
}
|
||||
xlp_fdt_blob = fdtp;
|
||||
return fdtp;
|
||||
}
|
||||
|
||||
void __init xlp_early_init_devtree(void)
|
||||
{
|
||||
__dt_setup_arch(xlp_fdt_blob);
|
||||
strlcpy(arcs_cmdline, boot_command_line, COMMAND_LINE_SIZE);
|
||||
}
|
||||
|
||||
void __init device_tree_init(void)
|
||||
{
|
||||
unflatten_and_copy_device_tree();
|
||||
}
|
||||
|
||||
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);
|
487
arch/mips/netlogic/xlp/nlm_hal.c
Normal file
487
arch/mips/netlogic/xlp/nlm_hal.c
Normal file
|
@ -0,0 +1,487 @@
|
|||
/*
|
||||
* 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/bridge.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);
|
||||
if (node == 0)
|
||||
nodep->coremask = 1; /* node 0, boot cpu */
|
||||
nodep->sysbase = nlm_get_sys_regbase(node);
|
||||
nodep->picbase = nlm_get_pic_regbase(node);
|
||||
nodep->ebase = read_c0_ebase() & (~((1 << 12) - 1));
|
||||
if (cpu_is_xlp9xx())
|
||||
nodep->socbus = xlp9xx_get_socbus(node);
|
||||
else
|
||||
nodep->socbus = 0;
|
||||
spin_lock_init(&nodep->piclock);
|
||||
}
|
||||
|
||||
static int xlp9xx_irq_to_irt(int irq)
|
||||
{
|
||||
switch (irq) {
|
||||
case PIC_GPIO_IRQ:
|
||||
return 12;
|
||||
case PIC_9XX_XHCI_0_IRQ:
|
||||
return 114;
|
||||
case PIC_9XX_XHCI_1_IRQ:
|
||||
return 115;
|
||||
case PIC_UART_0_IRQ:
|
||||
return 133;
|
||||
case PIC_UART_1_IRQ:
|
||||
return 134;
|
||||
case PIC_SATA_IRQ:
|
||||
return 143;
|
||||
case PIC_SPI_IRQ:
|
||||
return 152;
|
||||
case PIC_MMC_IRQ:
|
||||
return 153;
|
||||
case PIC_PCIE_LINK_LEGACY_IRQ(0):
|
||||
case PIC_PCIE_LINK_LEGACY_IRQ(1):
|
||||
case PIC_PCIE_LINK_LEGACY_IRQ(2):
|
||||
case PIC_PCIE_LINK_LEGACY_IRQ(3):
|
||||
return 191 + irq - PIC_PCIE_LINK_LEGACY_IRQ_BASE;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int xlp_irq_to_irt(int irq)
|
||||
{
|
||||
uint64_t pcibase;
|
||||
int devoff, irt;
|
||||
|
||||
devoff = 0;
|
||||
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_MMC_IRQ:
|
||||
devoff = XLP_IO_MMC_OFFSET(0);
|
||||
break;
|
||||
case PIC_I2C_0_IRQ: /* I2C will be fixed up */
|
||||
case PIC_I2C_1_IRQ:
|
||||
case PIC_I2C_2_IRQ:
|
||||
case PIC_I2C_3_IRQ:
|
||||
if (cpu_is_xlpii())
|
||||
devoff = XLP2XX_IO_I2C_OFFSET(0);
|
||||
else
|
||||
devoff = XLP_IO_I2C0_OFFSET(0);
|
||||
break;
|
||||
case PIC_SATA_IRQ:
|
||||
devoff = XLP_IO_SATA_OFFSET(0);
|
||||
break;
|
||||
case PIC_GPIO_IRQ:
|
||||
devoff = XLP_IO_GPIO_OFFSET(0);
|
||||
break;
|
||||
case PIC_NAND_IRQ:
|
||||
devoff = XLP_IO_NAND_OFFSET(0);
|
||||
break;
|
||||
case PIC_SPI_IRQ:
|
||||
devoff = XLP_IO_SPI_OFFSET(0);
|
||||
break;
|
||||
default:
|
||||
if (cpu_is_xlpii()) {
|
||||
switch (irq) {
|
||||
/* XLP2XX has three XHCI USB controller */
|
||||
case PIC_2XX_XHCI_0_IRQ:
|
||||
devoff = XLP2XX_IO_USB_XHCI0_OFFSET(0);
|
||||
break;
|
||||
case PIC_2XX_XHCI_1_IRQ:
|
||||
devoff = XLP2XX_IO_USB_XHCI1_OFFSET(0);
|
||||
break;
|
||||
case PIC_2XX_XHCI_2_IRQ:
|
||||
devoff = XLP2XX_IO_USB_XHCI2_OFFSET(0);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
switch (irq) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (devoff != 0) {
|
||||
pcibase = nlm_pcicfg_base(devoff);
|
||||
irt = nlm_read_reg(pcibase, XLP_PCI_IRTINFO_REG) & 0xffff;
|
||||
/* HW weirdness, I2C IRT entry has to be fixed up */
|
||||
switch (irq) {
|
||||
case PIC_I2C_1_IRQ:
|
||||
irt = irt + 1; break;
|
||||
case PIC_I2C_2_IRQ:
|
||||
irt = irt + 2; break;
|
||||
case PIC_I2C_3_IRQ:
|
||||
irt = irt + 3; break;
|
||||
}
|
||||
} else if (irq >= PIC_PCIE_LINK_LEGACY_IRQ(0) &&
|
||||
irq <= PIC_PCIE_LINK_LEGACY_IRQ(3)) {
|
||||
/* HW bug, PCI IRT entries are bad on early silicon, fix */
|
||||
irt = PIC_IRT_PCIE_LINK_INDEX(irq -
|
||||
PIC_PCIE_LINK_LEGACY_IRQ_BASE);
|
||||
} else {
|
||||
irt = -1;
|
||||
}
|
||||
return irt;
|
||||
}
|
||||
|
||||
int nlm_irq_to_irt(int irq)
|
||||
{
|
||||
/* return -2 for irqs without 1-1 mapping */
|
||||
if (irq >= PIC_PCIE_LINK_MSI_IRQ(0) && irq <= PIC_PCIE_LINK_MSI_IRQ(3))
|
||||
return -2;
|
||||
if (irq >= PIC_PCIE_MSIX_IRQ(0) && irq <= PIC_PCIE_MSIX_IRQ(3))
|
||||
return -2;
|
||||
|
||||
if (cpu_is_xlp9xx())
|
||||
return xlp9xx_irq_to_irt(irq);
|
||||
else
|
||||
return xlp_irq_to_irt(irq);
|
||||
}
|
||||
|
||||
static unsigned int nlm_xlp2_get_core_frequency(int node, int core)
|
||||
{
|
||||
unsigned int pll_post_div, ctrl_val0, ctrl_val1, denom;
|
||||
uint64_t num, sysbase, clockbase;
|
||||
|
||||
if (cpu_is_xlp9xx()) {
|
||||
clockbase = nlm_get_clock_regbase(node);
|
||||
ctrl_val0 = nlm_read_sys_reg(clockbase,
|
||||
SYS_9XX_CPU_PLL_CTRL0(core));
|
||||
ctrl_val1 = nlm_read_sys_reg(clockbase,
|
||||
SYS_9XX_CPU_PLL_CTRL1(core));
|
||||
} else {
|
||||
sysbase = nlm_get_node(node)->sysbase;
|
||||
ctrl_val0 = nlm_read_sys_reg(sysbase,
|
||||
SYS_CPU_PLL_CTRL0(core));
|
||||
ctrl_val1 = nlm_read_sys_reg(sysbase,
|
||||
SYS_CPU_PLL_CTRL1(core));
|
||||
}
|
||||
|
||||
/* Find PLL post divider value */
|
||||
switch ((ctrl_val0 >> 24) & 0x7) {
|
||||
case 1:
|
||||
pll_post_div = 2;
|
||||
break;
|
||||
case 3:
|
||||
pll_post_div = 4;
|
||||
break;
|
||||
case 7:
|
||||
pll_post_div = 8;
|
||||
break;
|
||||
case 6:
|
||||
pll_post_div = 16;
|
||||
break;
|
||||
case 0:
|
||||
default:
|
||||
pll_post_div = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
num = 1000000ULL * (400 * 3 + 100 * (ctrl_val1 & 0x3f));
|
||||
denom = 3 * pll_post_div;
|
||||
do_div(num, denom);
|
||||
|
||||
return (unsigned int)num;
|
||||
}
|
||||
|
||||
static unsigned int nlm_xlp_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_core_frequency(int node, int core)
|
||||
{
|
||||
if (cpu_is_xlpii())
|
||||
return nlm_xlp2_get_core_frequency(node, core);
|
||||
else
|
||||
return nlm_xlp_get_core_frequency(node, core);
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculate PIC frequency from PLL registers.
|
||||
* freq_out = (ref_freq/2 * (6 + ctrl2[7:0]) + ctrl2[20:8]/2^13) /
|
||||
* ((2^ctrl0[7:5]) * Table(ctrl0[26:24]))
|
||||
*/
|
||||
static unsigned int nlm_xlp2_get_pic_frequency(int node)
|
||||
{
|
||||
u32 ctrl_val0, ctrl_val2, vco_post_div, pll_post_div, cpu_xlp9xx;
|
||||
u32 mdiv, fdiv, pll_out_freq_den, reg_select, ref_div, pic_div;
|
||||
u64 sysbase, pll_out_freq_num, ref_clk_select, clockbase, ref_clk;
|
||||
|
||||
sysbase = nlm_get_node(node)->sysbase;
|
||||
clockbase = nlm_get_clock_regbase(node);
|
||||
cpu_xlp9xx = cpu_is_xlp9xx();
|
||||
|
||||
/* Find ref_clk_base */
|
||||
if (cpu_xlp9xx)
|
||||
ref_clk_select = (nlm_read_sys_reg(sysbase,
|
||||
SYS_9XX_POWER_ON_RESET_CFG) >> 18) & 0x3;
|
||||
else
|
||||
ref_clk_select = (nlm_read_sys_reg(sysbase,
|
||||
SYS_POWER_ON_RESET_CFG) >> 18) & 0x3;
|
||||
switch (ref_clk_select) {
|
||||
case 0:
|
||||
ref_clk = 200000000ULL;
|
||||
ref_div = 3;
|
||||
break;
|
||||
case 1:
|
||||
ref_clk = 100000000ULL;
|
||||
ref_div = 1;
|
||||
break;
|
||||
case 2:
|
||||
ref_clk = 125000000ULL;
|
||||
ref_div = 1;
|
||||
break;
|
||||
case 3:
|
||||
ref_clk = 400000000ULL;
|
||||
ref_div = 3;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Find the clock source PLL device for PIC */
|
||||
if (cpu_xlp9xx) {
|
||||
reg_select = nlm_read_sys_reg(clockbase,
|
||||
SYS_9XX_CLK_DEV_SEL) & 0x3;
|
||||
switch (reg_select) {
|
||||
case 0:
|
||||
ctrl_val0 = nlm_read_sys_reg(clockbase,
|
||||
SYS_9XX_PLL_CTRL0);
|
||||
ctrl_val2 = nlm_read_sys_reg(clockbase,
|
||||
SYS_9XX_PLL_CTRL2);
|
||||
break;
|
||||
case 1:
|
||||
ctrl_val0 = nlm_read_sys_reg(clockbase,
|
||||
SYS_9XX_PLL_CTRL0_DEVX(0));
|
||||
ctrl_val2 = nlm_read_sys_reg(clockbase,
|
||||
SYS_9XX_PLL_CTRL2_DEVX(0));
|
||||
break;
|
||||
case 2:
|
||||
ctrl_val0 = nlm_read_sys_reg(clockbase,
|
||||
SYS_9XX_PLL_CTRL0_DEVX(1));
|
||||
ctrl_val2 = nlm_read_sys_reg(clockbase,
|
||||
SYS_9XX_PLL_CTRL2_DEVX(1));
|
||||
break;
|
||||
case 3:
|
||||
ctrl_val0 = nlm_read_sys_reg(clockbase,
|
||||
SYS_9XX_PLL_CTRL0_DEVX(2));
|
||||
ctrl_val2 = nlm_read_sys_reg(clockbase,
|
||||
SYS_9XX_PLL_CTRL2_DEVX(2));
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
reg_select = (nlm_read_sys_reg(sysbase,
|
||||
SYS_CLK_DEV_SEL) >> 22) & 0x3;
|
||||
switch (reg_select) {
|
||||
case 0:
|
||||
ctrl_val0 = nlm_read_sys_reg(sysbase,
|
||||
SYS_PLL_CTRL0);
|
||||
ctrl_val2 = nlm_read_sys_reg(sysbase,
|
||||
SYS_PLL_CTRL2);
|
||||
break;
|
||||
case 1:
|
||||
ctrl_val0 = nlm_read_sys_reg(sysbase,
|
||||
SYS_PLL_CTRL0_DEVX(0));
|
||||
ctrl_val2 = nlm_read_sys_reg(sysbase,
|
||||
SYS_PLL_CTRL2_DEVX(0));
|
||||
break;
|
||||
case 2:
|
||||
ctrl_val0 = nlm_read_sys_reg(sysbase,
|
||||
SYS_PLL_CTRL0_DEVX(1));
|
||||
ctrl_val2 = nlm_read_sys_reg(sysbase,
|
||||
SYS_PLL_CTRL2_DEVX(1));
|
||||
break;
|
||||
case 3:
|
||||
ctrl_val0 = nlm_read_sys_reg(sysbase,
|
||||
SYS_PLL_CTRL0_DEVX(2));
|
||||
ctrl_val2 = nlm_read_sys_reg(sysbase,
|
||||
SYS_PLL_CTRL2_DEVX(2));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
vco_post_div = (ctrl_val0 >> 5) & 0x7;
|
||||
pll_post_div = (ctrl_val0 >> 24) & 0x7;
|
||||
mdiv = ctrl_val2 & 0xff;
|
||||
fdiv = (ctrl_val2 >> 8) & 0x1fff;
|
||||
|
||||
/* Find PLL post divider value */
|
||||
switch (pll_post_div) {
|
||||
case 1:
|
||||
pll_post_div = 2;
|
||||
break;
|
||||
case 3:
|
||||
pll_post_div = 4;
|
||||
break;
|
||||
case 7:
|
||||
pll_post_div = 8;
|
||||
break;
|
||||
case 6:
|
||||
pll_post_div = 16;
|
||||
break;
|
||||
case 0:
|
||||
default:
|
||||
pll_post_div = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
fdiv = fdiv/(1 << 13);
|
||||
pll_out_freq_num = ((ref_clk >> 1) * (6 + mdiv)) + fdiv;
|
||||
pll_out_freq_den = (1 << vco_post_div) * pll_post_div * 3;
|
||||
|
||||
if (pll_out_freq_den > 0)
|
||||
do_div(pll_out_freq_num, pll_out_freq_den);
|
||||
|
||||
/* PIC post divider, which happens after PLL */
|
||||
if (cpu_xlp9xx)
|
||||
pic_div = nlm_read_sys_reg(clockbase,
|
||||
SYS_9XX_CLK_DEV_DIV) & 0x3;
|
||||
else
|
||||
pic_div = (nlm_read_sys_reg(sysbase,
|
||||
SYS_CLK_DEV_DIV) >> 22) & 0x3;
|
||||
do_div(pll_out_freq_num, 1 << pic_div);
|
||||
|
||||
return pll_out_freq_num;
|
||||
}
|
||||
|
||||
unsigned int nlm_get_pic_frequency(int node)
|
||||
{
|
||||
if (cpu_is_xlpii())
|
||||
return nlm_xlp2_get_pic_frequency(node);
|
||||
else
|
||||
return 133333333;
|
||||
}
|
||||
|
||||
unsigned int nlm_get_cpu_frequency(void)
|
||||
{
|
||||
return nlm_get_core_frequency(0, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Fills upto 8 pairs of entries containing the DRAM map of a node
|
||||
* if n < 0, get dram map for all nodes
|
||||
*/
|
||||
int xlp_get_dram_map(int n, uint64_t *dram_map)
|
||||
{
|
||||
uint64_t bridgebase, base, lim;
|
||||
uint32_t val;
|
||||
unsigned int barreg, limreg, xlatreg;
|
||||
int i, node, rv;
|
||||
|
||||
/* Look only at mapping on Node 0, we don't handle crazy configs */
|
||||
bridgebase = nlm_get_bridge_regbase(0);
|
||||
rv = 0;
|
||||
for (i = 0; i < 8; i++) {
|
||||
if (cpu_is_xlp9xx()) {
|
||||
barreg = BRIDGE_9XX_DRAM_BAR(i);
|
||||
limreg = BRIDGE_9XX_DRAM_LIMIT(i);
|
||||
xlatreg = BRIDGE_9XX_DRAM_NODE_TRANSLN(i);
|
||||
} else {
|
||||
barreg = BRIDGE_DRAM_BAR(i);
|
||||
limreg = BRIDGE_DRAM_LIMIT(i);
|
||||
xlatreg = BRIDGE_DRAM_NODE_TRANSLN(i);
|
||||
}
|
||||
if (n >= 0) {
|
||||
/* node specified, get node mapping of BAR */
|
||||
val = nlm_read_bridge_reg(bridgebase, xlatreg);
|
||||
node = (val >> 1) & 0x3;
|
||||
if (n != node)
|
||||
continue;
|
||||
}
|
||||
val = nlm_read_bridge_reg(bridgebase, barreg);
|
||||
val = (val >> 12) & 0xfffff;
|
||||
base = (uint64_t) val << 20;
|
||||
val = nlm_read_bridge_reg(bridgebase, limreg);
|
||||
val = (val >> 12) & 0xfffff;
|
||||
if (val == 0) /* BAR not used */
|
||||
continue;
|
||||
lim = ((uint64_t)val + 1) << 20;
|
||||
dram_map[rv] = base;
|
||||
dram_map[rv + 1] = lim;
|
||||
rv += 2;
|
||||
}
|
||||
return rv;
|
||||
}
|
184
arch/mips/netlogic/xlp/setup.c
Normal file
184
arch/mips/netlogic/xlp/setup.c
Normal file
|
@ -0,0 +1,184 @@
|
|||
/*
|
||||
* 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/of_fdt.h>
|
||||
|
||||
#include <asm/idle.h>
|
||||
#include <asm/reboot.h>
|
||||
#include <asm/time.h>
|
||||
#include <asm/bootinfo.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;
|
||||
unsigned int xlp_cores_per_node;
|
||||
|
||||
static void nlm_linux_exit(void)
|
||||
{
|
||||
uint64_t sysbase = nlm_get_node(0)->sysbase;
|
||||
|
||||
if (cpu_is_xlp9xx())
|
||||
nlm_write_sys_reg(sysbase, SYS_9XX_CHIP_RESET, 1);
|
||||
else
|
||||
nlm_write_sys_reg(sysbase, SYS_CHIP_RESET, 1);
|
||||
for ( ; ; )
|
||||
cpu_wait();
|
||||
}
|
||||
|
||||
static void nlm_fixup_mem(void)
|
||||
{
|
||||
const int pref_backup = 512;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < boot_mem_map.nr_map; i++) {
|
||||
if (boot_mem_map.map[i].type != BOOT_MEM_RAM)
|
||||
continue;
|
||||
boot_mem_map.map[i].size -= pref_backup;
|
||||
}
|
||||
}
|
||||
|
||||
static void __init xlp_init_mem_from_bars(void)
|
||||
{
|
||||
uint64_t map[16];
|
||||
int i, n;
|
||||
|
||||
n = xlp_get_dram_map(-1, map); /* -1: info for all nodes */
|
||||
for (i = 0; i < n; i += 2) {
|
||||
/* exclude 0x1000_0000-0x2000_0000, u-boot device */
|
||||
if (map[i] <= 0x10000000 && map[i+1] > 0x10000000)
|
||||
map[i+1] = 0x10000000;
|
||||
if (map[i] > 0x10000000 && map[i] < 0x20000000)
|
||||
map[i] = 0x20000000;
|
||||
|
||||
add_memory_region(map[i], map[i+1] - map[i], BOOT_MEM_RAM);
|
||||
}
|
||||
}
|
||||
|
||||
void __init plat_mem_setup(void)
|
||||
{
|
||||
#ifdef CONFIG_SMP
|
||||
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
|
||||
_machine_restart = (void (*)(char *))nlm_linux_exit;
|
||||
_machine_halt = nlm_linux_exit;
|
||||
pm_power_off = nlm_linux_exit;
|
||||
|
||||
/* memory and bootargs from DT */
|
||||
xlp_early_init_devtree();
|
||||
|
||||
if (boot_mem_map.nr_map == 0) {
|
||||
pr_info("Using DRAM BARs for memory map.\n");
|
||||
xlp_init_mem_from_bars();
|
||||
}
|
||||
/* Calculate and setup wired entries for mapped kernel */
|
||||
nlm_fixup_mem();
|
||||
}
|
||||
|
||||
const char *get_system_type(void)
|
||||
{
|
||||
switch (read_c0_prid() & PRID_IMP_MASK) {
|
||||
case PRID_IMP_NETLOGIC_XLP9XX:
|
||||
case PRID_IMP_NETLOGIC_XLP5XX:
|
||||
case PRID_IMP_NETLOGIC_XLP2XX:
|
||||
return "Broadcom XLPII Series";
|
||||
default:
|
||||
return "Netlogic XLP Series";
|
||||
}
|
||||
}
|
||||
|
||||
void __init prom_free_prom_memory(void)
|
||||
{
|
||||
/* Nothing yet */
|
||||
}
|
||||
|
||||
void xlp_mmu_init(void)
|
||||
{
|
||||
u32 conf4;
|
||||
|
||||
if (cpu_is_xlpii()) {
|
||||
/* XLPII series has extended pagesize in config 4 */
|
||||
conf4 = read_c0_config4() & ~0x1f00u;
|
||||
write_c0_config4(conf4 | ((PAGE_SHIFT - 10) / 2 << 8));
|
||||
} else {
|
||||
/* enable extended TLB and Large Fixed TLB */
|
||||
write_c0_config6(read_c0_config6() | 0x24);
|
||||
|
||||
/* set page mask of extended 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)
|
||||
{
|
||||
void *reset_vec;
|
||||
|
||||
nlm_io_base = CKSEG1ADDR(XLP_DEFAULT_IO_BASE);
|
||||
if (cpu_is_xlp9xx())
|
||||
xlp_cores_per_node = 32;
|
||||
else
|
||||
xlp_cores_per_node = 8;
|
||||
nlm_init_boot_cpu();
|
||||
xlp_mmu_init();
|
||||
nlm_node_init(0);
|
||||
xlp_dt_init((void *)(long)fw_arg0);
|
||||
|
||||
/* Update reset entry point with CPU init code */
|
||||
reset_vec = (void *)CKSEG1ADDR(RESET_VEC_PHYS);
|
||||
memset(reset_vec, 0, RESET_VEC_SIZE);
|
||||
memcpy(reset_vec, (void *)nlm_reset_entry,
|
||||
(nlm_reset_entry_end - nlm_reset_entry));
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
cpumask_setall(&nlm_cpumask);
|
||||
#endif
|
||||
}
|
280
arch/mips/netlogic/xlp/usb-init-xlp2.c
Normal file
280
arch/mips/netlogic/xlp/usb-init-xlp2.c
Normal file
|
@ -0,0 +1,280 @@
|
|||
/*
|
||||
* Copyright (c) 2003-2013 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/pci_ids.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/irq.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>
|
||||
|
||||
#define XLPII_USB3_CTL_0 0xc0
|
||||
#define XLPII_VAUXRST BIT(0)
|
||||
#define XLPII_VCCRST BIT(1)
|
||||
#define XLPII_NUM2PORT 9
|
||||
#define XLPII_NUM3PORT 13
|
||||
#define XLPII_RTUNEREQ BIT(20)
|
||||
#define XLPII_MS_CSYSREQ BIT(21)
|
||||
#define XLPII_XS_CSYSREQ BIT(22)
|
||||
#define XLPII_RETENABLEN BIT(23)
|
||||
#define XLPII_TX2RX BIT(24)
|
||||
#define XLPII_XHCIREV BIT(25)
|
||||
#define XLPII_ECCDIS BIT(26)
|
||||
|
||||
#define XLPII_USB3_INT_REG 0xc2
|
||||
#define XLPII_USB3_INT_MASK 0xc3
|
||||
|
||||
#define XLPII_USB_PHY_TEST 0xc6
|
||||
#define XLPII_PRESET BIT(0)
|
||||
#define XLPII_ATERESET BIT(1)
|
||||
#define XLPII_LOOPEN BIT(2)
|
||||
#define XLPII_TESTPDHSP BIT(3)
|
||||
#define XLPII_TESTPDSSP BIT(4)
|
||||
#define XLPII_TESTBURNIN BIT(5)
|
||||
|
||||
#define XLPII_USB_PHY_LOS_LV 0xc9
|
||||
#define XLPII_LOSLEV 0
|
||||
#define XLPII_LOSBIAS 5
|
||||
#define XLPII_SQRXTX 8
|
||||
#define XLPII_TXBOOST 11
|
||||
#define XLPII_RSLKSEL 16
|
||||
#define XLPII_FSEL 20
|
||||
|
||||
#define XLPII_USB_RFCLK_REG 0xcc
|
||||
#define XLPII_VVLD 30
|
||||
|
||||
#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_xlpii_get_usb_pcibase(node, inst) \
|
||||
nlm_pcicfg_base(cpu_is_xlp9xx() ? \
|
||||
XLP9XX_IO_USB_OFFSET(node, inst) : \
|
||||
XLP2XX_IO_USB_OFFSET(node, inst))
|
||||
#define nlm_xlpii_get_usb_regbase(node, inst) \
|
||||
(nlm_xlpii_get_usb_pcibase(node, inst) + XLP_IO_PCI_HDRSZ)
|
||||
|
||||
static void xlp2xx_usb_ack(struct irq_data *data)
|
||||
{
|
||||
u64 port_addr;
|
||||
|
||||
switch (data->irq) {
|
||||
case PIC_2XX_XHCI_0_IRQ:
|
||||
port_addr = nlm_xlpii_get_usb_regbase(0, 1);
|
||||
break;
|
||||
case PIC_2XX_XHCI_1_IRQ:
|
||||
port_addr = nlm_xlpii_get_usb_regbase(0, 2);
|
||||
break;
|
||||
case PIC_2XX_XHCI_2_IRQ:
|
||||
port_addr = nlm_xlpii_get_usb_regbase(0, 3);
|
||||
break;
|
||||
default:
|
||||
pr_err("No matching USB irq!\n");
|
||||
return;
|
||||
}
|
||||
nlm_write_usb_reg(port_addr, XLPII_USB3_INT_REG, 0xffffffff);
|
||||
}
|
||||
|
||||
static void xlp9xx_usb_ack(struct irq_data *data)
|
||||
{
|
||||
u64 port_addr;
|
||||
int node, irq;
|
||||
|
||||
/* Find the node and irq on the node */
|
||||
irq = data->irq % NLM_IRQS_PER_NODE;
|
||||
node = data->irq / NLM_IRQS_PER_NODE;
|
||||
|
||||
switch (irq) {
|
||||
case PIC_9XX_XHCI_0_IRQ:
|
||||
port_addr = nlm_xlpii_get_usb_regbase(node, 1);
|
||||
break;
|
||||
case PIC_9XX_XHCI_1_IRQ:
|
||||
port_addr = nlm_xlpii_get_usb_regbase(node, 2);
|
||||
break;
|
||||
default:
|
||||
pr_err("No matching USB irq %d node %d!\n", irq, node);
|
||||
return;
|
||||
}
|
||||
nlm_write_usb_reg(port_addr, XLPII_USB3_INT_REG, 0xffffffff);
|
||||
}
|
||||
|
||||
static void nlm_xlpii_usb_hw_reset(int node, int port)
|
||||
{
|
||||
u64 port_addr, xhci_base, pci_base;
|
||||
void __iomem *corebase;
|
||||
u32 val;
|
||||
|
||||
port_addr = nlm_xlpii_get_usb_regbase(node, port);
|
||||
|
||||
/* Set frequency */
|
||||
val = nlm_read_usb_reg(port_addr, XLPII_USB_PHY_LOS_LV);
|
||||
val &= ~(0x3f << XLPII_FSEL);
|
||||
val |= (0x27 << XLPII_FSEL);
|
||||
nlm_write_usb_reg(port_addr, XLPII_USB_PHY_LOS_LV, val);
|
||||
|
||||
val = nlm_read_usb_reg(port_addr, XLPII_USB_RFCLK_REG);
|
||||
val |= (1 << XLPII_VVLD);
|
||||
nlm_write_usb_reg(port_addr, XLPII_USB_RFCLK_REG, val);
|
||||
|
||||
/* PHY reset */
|
||||
val = nlm_read_usb_reg(port_addr, XLPII_USB_PHY_TEST);
|
||||
val &= (XLPII_ATERESET | XLPII_LOOPEN | XLPII_TESTPDHSP
|
||||
| XLPII_TESTPDSSP | XLPII_TESTBURNIN);
|
||||
nlm_write_usb_reg(port_addr, XLPII_USB_PHY_TEST, val);
|
||||
|
||||
/* Setup control register */
|
||||
val = XLPII_VAUXRST | XLPII_VCCRST | (1 << XLPII_NUM2PORT)
|
||||
| (1 << XLPII_NUM3PORT) | XLPII_MS_CSYSREQ | XLPII_XS_CSYSREQ
|
||||
| XLPII_RETENABLEN | XLPII_XHCIREV;
|
||||
nlm_write_usb_reg(port_addr, XLPII_USB3_CTL_0, val);
|
||||
|
||||
/* Enable interrupts */
|
||||
nlm_write_usb_reg(port_addr, XLPII_USB3_INT_MASK, 0x00000001);
|
||||
|
||||
/* Clear all interrupts */
|
||||
nlm_write_usb_reg(port_addr, XLPII_USB3_INT_REG, 0xffffffff);
|
||||
|
||||
udelay(2000);
|
||||
|
||||
/* XHCI configuration at PCI mem */
|
||||
pci_base = nlm_xlpii_get_usb_pcibase(node, port);
|
||||
xhci_base = nlm_read_usb_reg(pci_base, 0x4) & ~0xf;
|
||||
corebase = ioremap(xhci_base, 0x10000);
|
||||
if (!corebase)
|
||||
return;
|
||||
|
||||
writel(0x240002, corebase + 0xc2c0);
|
||||
/* GCTL 0xc110 */
|
||||
val = readl(corebase + 0xc110);
|
||||
val &= ~(0x3 << 12);
|
||||
val |= (1 << 12);
|
||||
writel(val, corebase + 0xc110);
|
||||
udelay(100);
|
||||
|
||||
/* PHYCFG 0xc200 */
|
||||
val = readl(corebase + 0xc200);
|
||||
val &= ~(1 << 6);
|
||||
writel(val, corebase + 0xc200);
|
||||
udelay(100);
|
||||
|
||||
/* PIPECTL 0xc2c0 */
|
||||
val = readl(corebase + 0xc2c0);
|
||||
val &= ~(1 << 17);
|
||||
writel(val, corebase + 0xc2c0);
|
||||
|
||||
iounmap(corebase);
|
||||
}
|
||||
|
||||
static int __init nlm_platform_xlpii_usb_init(void)
|
||||
{
|
||||
int node;
|
||||
|
||||
if (!cpu_is_xlpii())
|
||||
return 0;
|
||||
|
||||
if (!cpu_is_xlp9xx()) {
|
||||
/* XLP 2XX single node */
|
||||
pr_info("Initializing 2XX USB Interface\n");
|
||||
nlm_xlpii_usb_hw_reset(0, 1);
|
||||
nlm_xlpii_usb_hw_reset(0, 2);
|
||||
nlm_xlpii_usb_hw_reset(0, 3);
|
||||
nlm_set_pic_extra_ack(0, PIC_2XX_XHCI_0_IRQ, xlp2xx_usb_ack);
|
||||
nlm_set_pic_extra_ack(0, PIC_2XX_XHCI_1_IRQ, xlp2xx_usb_ack);
|
||||
nlm_set_pic_extra_ack(0, PIC_2XX_XHCI_2_IRQ, xlp2xx_usb_ack);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* XLP 9XX, multi-node */
|
||||
pr_info("Initializing 9XX USB Interface\n");
|
||||
for (node = 0; node < NLM_NR_NODES; node++) {
|
||||
if (!nlm_node_present(node))
|
||||
continue;
|
||||
nlm_xlpii_usb_hw_reset(node, 1);
|
||||
nlm_xlpii_usb_hw_reset(node, 2);
|
||||
nlm_set_pic_extra_ack(node, PIC_9XX_XHCI_0_IRQ, xlp9xx_usb_ack);
|
||||
nlm_set_pic_extra_ack(node, PIC_9XX_XHCI_1_IRQ, xlp9xx_usb_ack);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
arch_initcall(nlm_platform_xlpii_usb_init);
|
||||
|
||||
static u64 xlp_usb_dmamask = ~(u32)0;
|
||||
|
||||
/* Fixup the IRQ for USB devices which is exist on XLP9XX SOC PCIE bus */
|
||||
static void nlm_xlp9xx_usb_fixup_final(struct pci_dev *dev)
|
||||
{
|
||||
int node;
|
||||
|
||||
node = xlp_socdev_to_node(dev);
|
||||
dev->dev.dma_mask = &xlp_usb_dmamask;
|
||||
dev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
|
||||
switch (dev->devfn) {
|
||||
case 0x21:
|
||||
dev->irq = nlm_irq_to_xirq(node, PIC_9XX_XHCI_0_IRQ);
|
||||
break;
|
||||
case 0x22:
|
||||
dev->irq = nlm_irq_to_xirq(node, PIC_9XX_XHCI_1_IRQ);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Fixup the IRQ for USB devices which is exist on XLP2XX SOC PCIE bus */
|
||||
static void nlm_xlp2xx_usb_fixup_final(struct pci_dev *dev)
|
||||
{
|
||||
dev->dev.dma_mask = &xlp_usb_dmamask;
|
||||
dev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
|
||||
switch (dev->devfn) {
|
||||
case 0x21:
|
||||
dev->irq = PIC_2XX_XHCI_0_IRQ;
|
||||
break;
|
||||
case 0x22:
|
||||
dev->irq = PIC_2XX_XHCI_1_IRQ;
|
||||
break;
|
||||
case 0x23:
|
||||
dev->irq = PIC_2XX_XHCI_2_IRQ;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_XLP9XX_XHCI,
|
||||
nlm_xlp9xx_usb_fixup_final);
|
||||
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_NETLOGIC, PCI_DEVICE_ID_NLM_XHCI,
|
||||
nlm_xlp2xx_usb_fixup_final);
|
149
arch/mips/netlogic/xlp/usb-init.c
Normal file
149
arch/mips/netlogic/xlp/usb-init.c
Normal file
|
@ -0,0 +1,149 @@
|
|||
/*
|
||||
* 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_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)
|
||||
{
|
||||
if (cpu_is_xlpii())
|
||||
return 0;
|
||||
|
||||
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(32);
|
||||
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);
|
212
arch/mips/netlogic/xlp/wakeup.c
Normal file
212
arch/mips/netlogic/xlp/wakeup.c
Normal file
|
@ -0,0 +1,212 @@
|
|||
/*
|
||||
* 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/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/xlp.h>
|
||||
#include <asm/netlogic/xlp-hal/pic.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, resetreg;
|
||||
|
||||
coremask = (1 << core);
|
||||
|
||||
/* Enable CPU clock in case of 8xx/3xx */
|
||||
if (!cpu_is_xlpii()) {
|
||||
value = nlm_read_sys_reg(sysbase, SYS_CORE_DFS_DIS_CTRL);
|
||||
value &= ~coremask;
|
||||
nlm_write_sys_reg(sysbase, SYS_CORE_DFS_DIS_CTRL, value);
|
||||
}
|
||||
|
||||
/* On 9XX, mark coherent first */
|
||||
if (cpu_is_xlp9xx()) {
|
||||
value = nlm_read_sys_reg(sysbase, SYS_9XX_CPU_NONCOHERENT_MODE);
|
||||
value &= ~coremask;
|
||||
nlm_write_sys_reg(sysbase, SYS_9XX_CPU_NONCOHERENT_MODE, value);
|
||||
}
|
||||
|
||||
/* Remove CPU Reset */
|
||||
resetreg = cpu_is_xlp9xx() ? SYS_9XX_CPU_RESET : SYS_CPU_RESET;
|
||||
value = nlm_read_sys_reg(sysbase, resetreg);
|
||||
value &= ~coremask;
|
||||
nlm_write_sys_reg(sysbase, resetreg, value);
|
||||
|
||||
/* We are done on 9XX */
|
||||
if (cpu_is_xlp9xx())
|
||||
return 1;
|
||||
|
||||
/* Poll for CPU to mark itself coherent on other type of XLP */
|
||||
count = 100000;
|
||||
do {
|
||||
value = nlm_read_sys_reg(sysbase, SYS_CPU_NONCOHERENT_MODE);
|
||||
} while ((value & coremask) != 0 && --count > 0);
|
||||
|
||||
return count != 0;
|
||||
}
|
||||
|
||||
static int wait_for_cpus(int cpu, int bootcpu)
|
||||
{
|
||||
volatile uint32_t *cpu_ready = nlm_get_boot_data(BOOT_CPU_READY);
|
||||
int i, count, notready;
|
||||
|
||||
count = 0x800000;
|
||||
do {
|
||||
notready = nlm_threads_per_core;
|
||||
for (i = 0; i < nlm_threads_per_core; i++)
|
||||
if (cpu_ready[cpu + i] || cpu == bootcpu)
|
||||
--notready;
|
||||
} while (notready != 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, fusebase;
|
||||
uint32_t syscoremask, mask, fusemask;
|
||||
int core, n, cpu;
|
||||
|
||||
for (n = 0; n < NLM_NR_NODES; n++) {
|
||||
if (n != 0) {
|
||||
/* check if node exists and is online */
|
||||
if (cpu_is_xlp9xx()) {
|
||||
int b = xlp9xx_get_socbus(n);
|
||||
pr_info("Node %d SoC PCI bus %d.\n", n, b);
|
||||
if (b == 0)
|
||||
break;
|
||||
} else {
|
||||
syspcibase = nlm_get_sys_pcibase(n);
|
||||
if (nlm_read_reg(syspcibase, 0) == 0xffffffff)
|
||||
break;
|
||||
}
|
||||
nlm_node_init(n);
|
||||
}
|
||||
|
||||
/* read cores in reset from SYS */
|
||||
nodep = nlm_get_node(n);
|
||||
|
||||
if (cpu_is_xlp9xx()) {
|
||||
fusebase = nlm_get_fuse_regbase(n);
|
||||
fusemask = nlm_read_reg(fusebase, FUSE_9XX_DEVCFG6);
|
||||
switch (read_c0_prid() & PRID_IMP_MASK) {
|
||||
case PRID_IMP_NETLOGIC_XLP5XX:
|
||||
mask = 0xff;
|
||||
break;
|
||||
case PRID_IMP_NETLOGIC_XLP9XX:
|
||||
default:
|
||||
mask = 0xfffff;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
fusemask = nlm_read_sys_reg(nodep->sysbase,
|
||||
SYS_EFUSE_DEVICE_CFG_STATUS0);
|
||||
switch (read_c0_prid() & PRID_IMP_MASK) {
|
||||
case PRID_IMP_NETLOGIC_XLP3XX:
|
||||
mask = 0xf;
|
||||
break;
|
||||
case PRID_IMP_NETLOGIC_XLP2XX:
|
||||
mask = 0x3;
|
||||
break;
|
||||
case PRID_IMP_NETLOGIC_XLP8XX:
|
||||
default:
|
||||
mask = 0xff;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Fused out cores are set in the fusemask, and the remaining
|
||||
* cores are renumbered to range 0 .. nactive-1
|
||||
*/
|
||||
syscoremask = (1 << hweight32(~fusemask & mask)) - 1;
|
||||
|
||||
pr_info("Node %d - SYS/FUSE coremask %x\n", n, syscoremask);
|
||||
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 hw threads sets their ready */
|
||||
if (!wait_for_cpus(cpu, 0))
|
||||
pr_err("Node %d : timeout core %d\n", n, core);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void xlp_wakeup_secondary_cpus()
|
||||
{
|
||||
/*
|
||||
* In case of u-boot, the secondaries are in reset
|
||||
* first wakeup core 0 threads
|
||||
*/
|
||||
xlp_boot_core0_siblings();
|
||||
if (!wait_for_cpus(0, 0))
|
||||
pr_err("Node 0 : timeout core 0\n");
|
||||
|
||||
/* now get other cores out of reset */
|
||||
xlp_enable_secondary_cores(&nlm_cpumask);
|
||||
}
|
2
arch/mips/netlogic/xlr/Makefile
Normal file
2
arch/mips/netlogic/xlr/Makefile
Normal file
|
@ -0,0 +1,2 @@
|
|||
obj-y += fmn.o fmn-config.o setup.o platform.o platform-flash.o
|
||||
obj-$(CONFIG_SMP) += wakeup.o
|
293
arch/mips/netlogic/xlr/fmn-config.c
Normal file
293
arch/mips/netlogic/xlr/fmn-config.c
Normal file
|
@ -0,0 +1,293 @@
|
|||
/*
|
||||
* 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/cpu.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() & PRID_IMP_MASK;
|
||||
|
||||
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
|
||||
}
|
204
arch/mips/netlogic/xlr/fmn.c
Normal file
204
arch/mips/netlogic/xlr/fmn.c
Normal 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_irqsave();
|
||||
/* 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_status0() >> 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_disable_irqrestore(mflags);
|
||||
hndlr->action(bucket, src_stnid, size, code,
|
||||
&msg, hndlr->arg);
|
||||
mflags = nlm_cop2_enable_irqsave();
|
||||
}
|
||||
}
|
||||
};
|
||||
/* Enable message ring intr, to any thread in core */
|
||||
nlm_fmn_setup_intr(irq, (1 << nlm_threads_per_core) - 1);
|
||||
nlm_cop2_disable_irqrestore(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_irqsave();
|
||||
|
||||
/* 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_disable_irqrestore(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_irqsave();
|
||||
nlm_fmn_setup_intr(IRQ_FMN, (1 << nlm_threads_per_core) - 1);
|
||||
nlm_cop2_disable_irqrestore(flags);
|
||||
}
|
220
arch/mips/netlogic/xlr/platform-flash.c
Normal file
220
arch/mips/netlogic/xlr/platform-flash.c
Normal 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);
|
250
arch/mips/netlogic/xlr/platform.c
Normal file
250
arch/mips/netlogic/xlr/platform.c
Normal 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>
|
||||
|
||||
static 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;
|
||||
}
|
||||
|
||||
static 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
|
210
arch/mips/netlogic/xlr/setup.c
Normal file
210
arch/mips/netlogic/xlr/setup.c
Normal file
|
@ -0,0 +1,210 @@
|
|||
/*
|
||||
* 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 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)
|
||||
{
|
||||
_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;
|
||||
void *reset_vec;
|
||||
#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();
|
||||
|
||||
/* Update reset entry point with CPU init code */
|
||||
reset_vec = (void *)CKSEG1ADDR(RESET_VEC_PHYS);
|
||||
memset(reset_vec, 0, RESET_VEC_SIZE);
|
||||
memcpy(reset_vec, (void *)nlm_reset_entry,
|
||||
(nlm_reset_entry_end - nlm_reset_entry));
|
||||
|
||||
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();
|
||||
}
|
85
arch/mips/netlogic/xlr/wakeup.c
Normal file
85
arch/mips/netlogic/xlr/wakeup.c
Normal 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/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 xlr_wakeup_secondary_cpus(void)
|
||||
{
|
||||
struct nlm_soc_info *nodep;
|
||||
unsigned int i, j, boot_cpu;
|
||||
volatile u32 *cpu_ready = nlm_get_boot_data(BOOT_CPU_READY);
|
||||
|
||||
/*
|
||||
* 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 (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;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue