Commit 241738bd authored by Ralf Baechle's avatar Ralf Baechle

Merge branch 'mips-next' of http://dev.phrozen.org/githttp/mips-next into mips-for-linux-next

parents bdf20507 ce8f0d06
......@@ -106,6 +106,7 @@ config ATH79
config BCM47XX
bool "Broadcom BCM47XX based boards"
select ARCH_WANT_OPTIONAL_GPIOLIB
select CEVT_R4K
select CSRC_R4K
select DMA_NONCOHERENT
......@@ -114,7 +115,6 @@ config BCM47XX
select IRQ_CPU
select SYS_SUPPORTS_32BIT_KERNEL
select SYS_SUPPORTS_LITTLE_ENDIAN
select GENERIC_GPIO
select SYS_HAS_EARLY_PRINTK
help
Support for BCM47XX based boards
......@@ -798,7 +798,7 @@ config NLM_XLR_BOARD
select CSRC_R4K
select IRQ_CPU
select ARCH_SUPPORTS_MSI
select ZONE_DMA if 64BIT
select ZONE_DMA32 if 64BIT
select SYNC_R4K
select SYS_HAS_EARLY_PRINTK
select USB_ARCH_HAS_OHCI if USB_SUPPORT
......@@ -826,7 +826,7 @@ config NLM_XLP_BOARD
select CEVT_R4K
select CSRC_R4K
select IRQ_CPU
select ZONE_DMA if 64BIT
select ZONE_DMA32 if 64BIT
select SYNC_R4K
select SYS_HAS_EARLY_PRINTK
select USE_OF
......@@ -1507,6 +1507,7 @@ config CPU_XLP
select WEAK_ORDERING
select WEAK_REORDERING_BEYOND_LLSC
select CPU_HAS_PREFETCH
select CPU_MIPSR2
help
Netlogic Microsystems XLP processors.
endchoice
......@@ -1718,7 +1719,7 @@ config CPU_SUPPORTS_UNCACHED_ACCELERATED
bool
config MIPS_PGD_C0_CONTEXT
bool
default y if 64BIT && CPU_MIPSR2
default y if 64BIT && CPU_MIPSR2 && !CPU_XLP
#
# Set to y for ptrace access to watch registers.
......@@ -2149,7 +2150,7 @@ config NODES_SHIFT
config HW_PERF_EVENTS
bool "Enable hardware performance counter support for perf events"
depends on PERF_EVENTS && !MIPS_MT_SMTC && OPROFILE=n && (CPU_MIPS32 || CPU_MIPS64 || CPU_R10000 || CPU_SB1 || CPU_CAVIUM_OCTEON)
depends on PERF_EVENTS && !MIPS_MT_SMTC && OPROFILE=n && (CPU_MIPS32 || CPU_MIPS64 || CPU_R10000 || CPU_SB1 || CPU_CAVIUM_OCTEON || CPU_XLP)
default y
help
Enable hardware performance counter support for perf events. If
......
......@@ -9,6 +9,7 @@ config BCM47XX_SSB
select SSB_EMBEDDED
select SSB_B43_PCI_BRIDGE if PCI
select SSB_PCICORE_HOSTMODE if PCI
select SSB_DRIVER_GPIO
default y
help
Add support for old Broadcom BCM47xx boards with Sonics Silicon Backplane support.
......@@ -23,6 +24,7 @@ config BCM47XX_BCMA
select BCMA_DRIVER_MIPS
select BCMA_HOST_PCI if PCI
select BCMA_DRIVER_PCI_HOSTMODE if PCI
select BCMA_DRIVER_GPIO
default y
help
Add support for new Broadcom BCM47xx boards with Broadcom specific Advanced Microcontroller Bus.
......
......@@ -3,5 +3,5 @@
# under Linux.
#
obj-y += gpio.o irq.o nvram.o prom.o serial.o setup.o time.o sprom.o
obj-y += irq.o nvram.o prom.o serial.o setup.o time.o sprom.o
obj-$(CONFIG_BCM47XX_SSB) += wgt634u.o
/*
* 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) 2007 Aurelien Jarno <aurelien@aurel32.net>
*/
#include <linux/export.h>
#include <linux/ssb/ssb.h>
#include <linux/ssb/ssb_driver_chipcommon.h>
#include <linux/ssb/ssb_driver_extif.h>
#include <asm/mach-bcm47xx/bcm47xx.h>
#include <asm/mach-bcm47xx/gpio.h>
#if (BCM47XX_CHIPCO_GPIO_LINES > BCM47XX_EXTIF_GPIO_LINES)
static DECLARE_BITMAP(gpio_in_use, BCM47XX_CHIPCO_GPIO_LINES);
#else
static DECLARE_BITMAP(gpio_in_use, BCM47XX_EXTIF_GPIO_LINES);
#endif
int gpio_request(unsigned gpio, const char *tag)
{
switch (bcm47xx_bus_type) {
#ifdef CONFIG_BCM47XX_SSB
case BCM47XX_BUS_TYPE_SSB:
if (ssb_chipco_available(&bcm47xx_bus.ssb.chipco) &&
((unsigned)gpio >= BCM47XX_CHIPCO_GPIO_LINES))
return -EINVAL;
if (ssb_extif_available(&bcm47xx_bus.ssb.extif) &&
((unsigned)gpio >= BCM47XX_EXTIF_GPIO_LINES))
return -EINVAL;
if (test_and_set_bit(gpio, gpio_in_use))
return -EBUSY;
return 0;
#endif
#ifdef CONFIG_BCM47XX_BCMA
case BCM47XX_BUS_TYPE_BCMA:
if (gpio >= BCM47XX_CHIPCO_GPIO_LINES)
return -EINVAL;
if (test_and_set_bit(gpio, gpio_in_use))
return -EBUSY;
return 0;
#endif
}
return -EINVAL;
}
EXPORT_SYMBOL(gpio_request);
void gpio_free(unsigned gpio)
{
switch (bcm47xx_bus_type) {
#ifdef CONFIG_BCM47XX_SSB
case BCM47XX_BUS_TYPE_SSB:
if (ssb_chipco_available(&bcm47xx_bus.ssb.chipco) &&
((unsigned)gpio >= BCM47XX_CHIPCO_GPIO_LINES))
return;
if (ssb_extif_available(&bcm47xx_bus.ssb.extif) &&
((unsigned)gpio >= BCM47XX_EXTIF_GPIO_LINES))
return;
clear_bit(gpio, gpio_in_use);
return;
#endif
#ifdef CONFIG_BCM47XX_BCMA
case BCM47XX_BUS_TYPE_BCMA:
if (gpio >= BCM47XX_CHIPCO_GPIO_LINES)
return;
clear_bit(gpio, gpio_in_use);
return;
#endif
}
}
EXPORT_SYMBOL(gpio_free);
int gpio_to_irq(unsigned gpio)
{
switch (bcm47xx_bus_type) {
#ifdef CONFIG_BCM47XX_SSB
case BCM47XX_BUS_TYPE_SSB:
if (ssb_chipco_available(&bcm47xx_bus.ssb.chipco))
return ssb_mips_irq(bcm47xx_bus.ssb.chipco.dev) + 2;
else if (ssb_extif_available(&bcm47xx_bus.ssb.extif))
return ssb_mips_irq(bcm47xx_bus.ssb.extif.dev) + 2;
else
return -EINVAL;
#endif
#ifdef CONFIG_BCM47XX_BCMA
case BCM47XX_BUS_TYPE_BCMA:
return bcma_core_mips_irq(bcm47xx_bus.bcma.bus.drv_cc.core) + 2;
#endif
}
return -EINVAL;
}
EXPORT_SYMBOL_GPL(gpio_to_irq);
/*
* Copyright (C) 2004 Florian Schirmer <jolt@tuxbox.org>
* Copyright (C) 2007 Aurelien Jarno <aurelien@aurel32.net>
* Copyright (C) 2010-2012 Hauke Mehrtens <hauke@hauke-m.de>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
......@@ -27,6 +28,7 @@
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/spinlock.h>
#include <linux/smp.h>
#include <asm/bootinfo.h>
#include <asm/fw/cfe/cfe_api.h>
#include <asm/fw/cfe/cfe_error.h>
......@@ -127,6 +129,8 @@ static __init void prom_init_mem(void)
{
unsigned long mem;
unsigned long max;
unsigned long off;
struct cpuinfo_mips *c = &current_cpu_data;
/* Figure out memory size by finding aliases.
*
......@@ -143,18 +147,26 @@ static __init void prom_init_mem(void)
* max contains the biggest possible address supported by the platform.
* If the method wants to try something above we assume 128MB ram.
*/
max = ((unsigned long)(prom_init) | ((128 << 20) - 1));
off = (unsigned long)prom_init;
max = off | ((128 << 20) - 1);
for (mem = (1 << 20); mem < (128 << 20); mem += (1 << 20)) {
if (((unsigned long)(prom_init) + mem) > max) {
if ((off + mem) > max) {
mem = (128 << 20);
printk(KERN_DEBUG "assume 128MB RAM\n");
break;
}
if (*(unsigned long *)((unsigned long)(prom_init) + mem) ==
*(unsigned long *)(prom_init))
if (!memcmp(prom_init, prom_init + mem, 32))
break;
}
/* Ignoring the last page when ddr size is 128M. Cached
* accesses to last page is causing the processor to prefetch
* using address above 128M stepping out of the ddr address
* space.
*/
if (c->cputype == CPU_74K && (mem == (128 << 20)))
mem -= 0x1000;
add_memory_region(0, mem, BOOT_MEM_RAM);
}
......
......@@ -94,7 +94,7 @@ static int bcm47xx_get_sprom_ssb(struct ssb_bus *bus, struct ssb_sprom *out)
snprintf(prefix, sizeof(prefix), "pci/%u/%u/",
bus->host_pci->bus->number + 1,
PCI_SLOT(bus->host_pci->devfn));
bcm47xx_fill_sprom(out, prefix);
bcm47xx_fill_sprom(out, prefix, false);
return 0;
} else {
printk(KERN_WARNING "bcm47xx: unable to fill SPROM for given bustype.\n");
......@@ -113,7 +113,7 @@ static int bcm47xx_get_invariants(struct ssb_bus *bus,
bcm47xx_fill_ssb_boardinfo(&iv->boardinfo, NULL);
memset(&iv->sprom, 0, sizeof(struct ssb_sprom));
bcm47xx_fill_sprom(&iv->sprom, NULL);
bcm47xx_fill_sprom(&iv->sprom, NULL, false);
if (nvram_getenv("cardbus", buf, sizeof(buf)) >= 0)
iv->has_cardbus_slot = !!simple_strtoul(buf, NULL, 10);
......@@ -165,16 +165,17 @@ static int bcm47xx_get_sprom_bcma(struct bcma_bus *bus, struct ssb_sprom *out)
snprintf(prefix, sizeof(prefix), "pci/%u/%u/",
bus->host_pci->bus->number + 1,
PCI_SLOT(bus->host_pci->devfn));
bcm47xx_fill_sprom(out, prefix);
bcm47xx_fill_sprom(out, prefix, false);
return 0;
case BCMA_HOSTTYPE_SOC:
memset(out, 0, sizeof(struct ssb_sprom));
bcm47xx_fill_sprom_ethernet(out, NULL);
core = bcma_find_core(bus, BCMA_CORE_80211);
if (core) {
snprintf(prefix, sizeof(prefix), "sb/%u/",
core->core_index);
bcm47xx_fill_sprom(out, prefix);
bcm47xx_fill_sprom(out, prefix, true);
} else {
bcm47xx_fill_sprom(out, NULL, false);
}
return 0;
default:
......
This diff is collapsed.
......@@ -11,6 +11,7 @@
#include <linux/leds.h>
#include <linux/mtd/physmap.h>
#include <linux/ssb/ssb.h>
#include <linux/ssb/ssb_embedded.h>
#include <linux/interrupt.h>
#include <linux/reboot.h>
#include <linux/gpio.h>
......@@ -116,7 +117,8 @@ static irqreturn_t gpio_interrupt(int irq, void *ignored)
/* Interrupt are level triggered, revert the interrupt polarity
to clear the interrupt. */
gpio_polarity(WGT634U_GPIO_RESET, state);
ssb_gpio_polarity(&bcm47xx_bus.ssb, 1 << WGT634U_GPIO_RESET,
state ? 1 << WGT634U_GPIO_RESET : 0);
if (!state) {
printk(KERN_INFO "Reset button pressed");
......@@ -150,7 +152,9 @@ static int __init wgt634u_init(void)
gpio_interrupt, IRQF_SHARED,
"WGT634U GPIO", &bcm47xx_bus.ssb.chipco)) {
gpio_direction_input(WGT634U_GPIO_RESET);
gpio_intmask(WGT634U_GPIO_RESET, 1);
ssb_gpio_intmask(&bcm47xx_bus.ssb,
1 << WGT634U_GPIO_RESET,
1 << WGT634U_GPIO_RESET);
ssb_chipco_irq_mask(&bcm47xx_bus.ssb.chipco,
SSB_CHIPCO_IRQ_GPIO,
SSB_CHIPCO_IRQ_GPIO);
......
obj-y += clk.o cpu.o cs.o gpio.o irq.o prom.o setup.o timer.o \
dev-dsp.o dev-enet.o dev-flash.o dev-pcmcia.o dev-rng.o \
dev-spi.o dev-uart.o dev-wdt.o dev-usb-usbd.o
obj-y += clk.o cpu.o cs.o gpio.o irq.o nvram.o prom.o reset.o \
setup.o timer.o dev-dsp.o dev-enet.o dev-flash.o \
dev-pcmcia.o dev-rng.o dev-spi.o dev-uart.o dev-wdt.o \
dev-usb-usbd.o
obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
obj-y += boards/
......@@ -18,6 +18,7 @@
#include <bcm63xx_dev_uart.h>
#include <bcm63xx_regs.h>
#include <bcm63xx_io.h>
#include <bcm63xx_nvram.h>
#include <bcm63xx_dev_pci.h>
#include <bcm63xx_dev_enet.h>
#include <bcm63xx_dev_dsp.h>
......@@ -29,8 +30,6 @@
#define PFX "board_bcm963xx: "
static struct bcm963xx_nvram nvram;
static unsigned int mac_addr_used;
static struct board_info board;
/*
......@@ -715,51 +714,15 @@ const char *board_get_name(void)
return board.name;
}
/*
* register & return a new board mac address
*/
static int board_get_mac_address(u8 *mac)
{
u8 *oui;
int count;
if (mac_addr_used >= nvram.mac_addr_count) {
printk(KERN_ERR PFX "not enough mac address\n");
return -ENODEV;
}
memcpy(mac, nvram.mac_addr_base, ETH_ALEN);
oui = mac + ETH_ALEN/2 - 1;
count = mac_addr_used;
while (count--) {
u8 *p = mac + ETH_ALEN - 1;
do {
(*p)++;
if (*p != 0)
break;
p--;
} while (p != oui);
if (p == oui) {
printk(KERN_ERR PFX "unable to fetch mac address\n");
return -ENODEV;
}
}
mac_addr_used++;
return 0;
}
/*
* early init callback, read nvram data from flash and checksum it
*/
void __init board_prom_init(void)
{
unsigned int check_len, i;
u8 *boot_addr, *cfe, *p;
unsigned int i;
u8 *boot_addr, *cfe;
char cfe_version[32];
char *board_name;
u32 val;
/* read base address of boot chip select (0)
......@@ -782,27 +745,15 @@ void __init board_prom_init(void)
strcpy(cfe_version, "unknown");
printk(KERN_INFO PFX "CFE version: %s\n", cfe_version);
/* extract nvram data */
memcpy(&nvram, boot_addr + BCM963XX_NVRAM_OFFSET, sizeof(nvram));
/* check checksum before using data */
if (nvram.version <= 4)
check_len = offsetof(struct bcm963xx_nvram, checksum_old);
else
check_len = sizeof(nvram);
val = 0;
p = (u8 *)&nvram;
while (check_len--)
val += *p;
if (val) {
if (bcm63xx_nvram_init(boot_addr + BCM963XX_NVRAM_OFFSET)) {
printk(KERN_ERR PFX "invalid nvram checksum\n");
return;
}
board_name = bcm63xx_nvram_get_name();
/* find board by name */
for (i = 0; i < ARRAY_SIZE(bcm963xx_boards); i++) {
if (strncmp(nvram.name, bcm963xx_boards[i]->name,
sizeof(nvram.name)))
if (strncmp(board_name, bcm963xx_boards[i]->name, 16))
continue;
/* copy, board desc array is marked initdata */
memcpy(&board, bcm963xx_boards[i], sizeof(board));
......@@ -812,7 +763,7 @@ void __init board_prom_init(void)
/* bail out if board is not found, will complain later */
if (!board.name[0]) {
char name[17];
memcpy(name, nvram.name, 16);
memcpy(name, board_name, 16);
name[16] = 0;
printk(KERN_ERR PFX "unknown bcm963xx board: %s\n",
name);
......@@ -890,11 +841,11 @@ int __init board_register_devices(void)
bcm63xx_pcmcia_register();
if (board.has_enet0 &&
!board_get_mac_address(board.enet0.mac_addr))
!bcm63xx_nvram_get_mac_address(board.enet0.mac_addr))
bcm63xx_enet_register(0, &board.enet0);
if (board.has_enet1 &&
!board_get_mac_address(board.enet1.mac_addr))
!bcm63xx_nvram_get_mac_address(board.enet1.mac_addr))
bcm63xx_enet_register(1, &board.enet1);
if (board.has_usbd)
......@@ -907,7 +858,7 @@ int __init board_register_devices(void)
* do this after registering enet devices
*/
#ifdef CONFIG_SSB_PCIHOST
if (!board_get_mac_address(bcm63xx_sprom.il0mac)) {
if (!bcm63xx_nvram_get_mac_address(bcm63xx_sprom.il0mac)) {
memcpy(bcm63xx_sprom.et0mac, bcm63xx_sprom.il0mac, ETH_ALEN);
memcpy(bcm63xx_sprom.et1mac, bcm63xx_sprom.il0mac, ETH_ALEN);
if (ssb_arch_register_fallback_sprom(
......
......@@ -14,6 +14,7 @@
#include <bcm63xx_cpu.h>
#include <bcm63xx_io.h>
#include <bcm63xx_regs.h>
#include <bcm63xx_reset.h>
#include <bcm63xx_clk.h>
static DEFINE_MUTEX(clocks_mutex);
......@@ -124,15 +125,10 @@ static void enetsw_set(struct clk *clk, int enable)
CKCTL_6368_SWPKT_USB_EN |
CKCTL_6368_SWPKT_SAR_EN, enable);
if (enable) {
u32 val;
/* reset switch core afer clock change */
val = bcm_perf_readl(PERF_SOFTRESET_6368_REG);
val &= ~SOFTRESET_6368_ENETSW_MASK;
bcm_perf_writel(val, PERF_SOFTRESET_6368_REG);
bcm63xx_core_set_reset(BCM63XX_RESET_ENETSW, 1);
msleep(10);
val |= SOFTRESET_6368_ENETSW_MASK;
bcm_perf_writel(val, PERF_SOFTRESET_6368_REG);
bcm63xx_core_set_reset(BCM63XX_RESET_ENETSW, 0);
msleep(10);
}
}
......@@ -222,15 +218,10 @@ static void xtm_set(struct clk *clk, int enable)
CKCTL_6368_SWPKT_SAR_EN, enable);
if (enable) {
u32 val;
/* reset sar core afer clock change */
val = bcm_perf_readl(PERF_SOFTRESET_6368_REG);
val &= ~SOFTRESET_6368_SAR_MASK;
bcm_perf_writel(val, PERF_SOFTRESET_6368_REG);
bcm63xx_core_set_reset(BCM63XX_RESET_SAR, 1);
mdelay(1);
val |= SOFTRESET_6368_SAR_MASK;
bcm_perf_writel(val, PERF_SOFTRESET_6368_REG);
bcm63xx_core_set_reset(BCM63XX_RESET_SAR, 0);
mdelay(1);
}
}
......@@ -252,6 +243,19 @@ static struct clk clk_ipsec = {
.set = ipsec_set,
};
/*
* PCIe clock
*/
static void pcie_set(struct clk *clk, int enable)
{
bcm_hwclock_set(CKCTL_6328_PCIE_EN, enable);
}
static struct clk clk_pcie = {
.set = pcie_set,
};
/*
* Internal peripheral clock
*/
......@@ -313,6 +317,8 @@ struct clk *clk_get(struct device *dev, const char *id)
return &clk_pcm;
if (BCMCPU_IS_6368() && !strcmp(id, "ipsec"))
return &clk_ipsec;
if (BCMCPU_IS_6328() && !strcmp(id, "pcie"))
return &clk_pcie;
return ERR_PTR(-ENOENT);
}
......
/*
* 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) 2008 Maxime Bizon <mbizon@freebox.fr>
* Copyright (C) 2008 Florian Fainelli <florian@openwrt.org>
* Copyright (C) 2012 Jonas Gorski <jonas.gorski@gmail.com>
*/
#define pr_fmt(fmt) "bcm63xx_nvram: " fmt
#include <linux/init.h>
#include <linux/crc32.h>
#include <linux/export.h>
#include <linux/kernel.h>
#include <linux/if_ether.h>
#include <bcm63xx_nvram.h>
/*
* nvram structure
*/
struct bcm963xx_nvram {
u32 version;
u8 reserved1[256];
u8 name[16];
u32 main_tp_number;
u32 psi_size;
u32 mac_addr_count;
u8 mac_addr_base[ETH_ALEN];
u8 reserved2[2];
u32 checksum_old;
u8 reserved3[720];
u32 checksum_high;
};
static struct bcm963xx_nvram nvram;
static int mac_addr_used;
int __init bcm63xx_nvram_init(void *addr)
{
unsigned int check_len;
u32 crc, expected_crc;
/* extract nvram data */
memcpy(&nvram, addr, sizeof(nvram));
/* check checksum before using data */
if (nvram.version <= 4) {
check_len = offsetof(struct bcm963xx_nvram, reserved3);
expected_crc = nvram.checksum_old;
nvram.checksum_old = 0;
} else {
check_len = sizeof(nvram);
expected_crc = nvram.checksum_high;
nvram.checksum_high = 0;
}
crc = crc32_le(~0, (u8 *)&nvram, check_len);
if (crc != expected_crc)
return -EINVAL;
return 0;
}
u8 *bcm63xx_nvram_get_name(void)
{
return nvram.name;
}
EXPORT_SYMBOL(bcm63xx_nvram_get_name);
int bcm63xx_nvram_get_mac_address(u8 *mac)
{
u8 *oui;
int count;
if (mac_addr_used >= nvram.mac_addr_count) {
pr_err("not enough mac addresses\n");
return -ENODEV;
}
memcpy(mac, nvram.mac_addr_base, ETH_ALEN);
oui = mac + ETH_ALEN/2 - 1;
count = mac_addr_used;
while (count--) {
u8 *p = mac + ETH_ALEN - 1;
do {
(*p)++;
if (*p != 0)
break;
p--;
} while (p != oui);
if (p == oui) {
pr_err("unable to fetch mac address\n");
return -ENODEV;
}
}
mac_addr_used++;
return 0;
}
EXPORT_SYMBOL(bcm63xx_nvram_get_mac_address);
/*
* 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) 2012 Jonas Gorski <jonas.gorski@gmail.com>
*/
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/err.h>
#include <linux/clk.h>
#include <linux/delay.h>
#include <bcm63xx_cpu.h>
#include <bcm63xx_io.h>
#include <bcm63xx_regs.h>
#include <bcm63xx_reset.h>
#define __GEN_RESET_BITS_TABLE(__cpu) \
[BCM63XX_RESET_SPI] = BCM## __cpu ##_RESET_SPI, \
[BCM63XX_RESET_ENET] = BCM## __cpu ##_RESET_ENET, \
[BCM63XX_RESET_USBH] = BCM## __cpu ##_RESET_USBH, \
[BCM63XX_RESET_USBD] = BCM## __cpu ##_RESET_USBD, \
[BCM63XX_RESET_DSL] = BCM## __cpu ##_RESET_DSL, \
[BCM63XX_RESET_SAR] = BCM## __cpu ##_RESET_SAR, \
[BCM63XX_RESET_EPHY] = BCM## __cpu ##_RESET_EPHY, \
[BCM63XX_RESET_ENETSW] = BCM## __cpu ##_RESET_ENETSW, \
[BCM63XX_RESET_PCM] = BCM## __cpu ##_RESET_PCM, \
[BCM63XX_RESET_MPI] = BCM## __cpu ##_RESET_MPI, \
[BCM63XX_RESET_PCIE] = BCM## __cpu ##_RESET_PCIE, \
[BCM63XX_RESET_PCIE_EXT] = BCM## __cpu ##_RESET_PCIE_EXT,
#define BCM6328_RESET_SPI SOFTRESET_6328_SPI_MASK
#define BCM6328_RESET_ENET 0
#define BCM6328_RESET_USBH SOFTRESET_6328_USBH_MASK
#define BCM6328_RESET_USBD SOFTRESET_6328_USBS_MASK
#define BCM6328_RESET_DSL 0
#define BCM6328_RESET_SAR SOFTRESET_6328_SAR_MASK
#define BCM6328_RESET_EPHY SOFTRESET_6328_EPHY_MASK
#define BCM6328_RESET_ENETSW SOFTRESET_6328_ENETSW_MASK
#define BCM6328_RESET_PCM SOFTRESET_6328_PCM_MASK
#define BCM6328_RESET_MPI 0
#define BCM6328_RESET_PCIE \
(SOFTRESET_6328_PCIE_MASK | \
SOFTRESET_6328_PCIE_CORE_MASK | \
SOFTRESET_6328_PCIE_HARD_MASK)
#define BCM6328_RESET_PCIE_EXT SOFTRESET_6328_PCIE_EXT_MASK
#define BCM6338_RESET_SPI SOFTRESET_6338_SPI_MASK
#define BCM6338_RESET_ENET SOFTRESET_6338_ENET_MASK
#define BCM6338_RESET_USBH SOFTRESET_6338_USBH_MASK
#define BCM6338_RESET_USBD SOFTRESET_6338_USBS_MASK
#define BCM6338_RESET_DSL SOFTRESET_6338_ADSL_MASK
#define BCM6338_RESET_SAR SOFTRESET_6338_SAR_MASK
#define BCM6338_RESET_EPHY 0
#define BCM6338_RESET_ENETSW 0
#define BCM6338_RESET_PCM 0
#define BCM6338_RESET_MPI 0
#define BCM6338_RESET_PCIE 0
#define BCM6338_RESET_PCIE_EXT 0
#define BCM6348_RESET_SPI SOFTRESET_6348_SPI_MASK
#define BCM6348_RESET_ENET SOFTRESET_6348_ENET_MASK
#define BCM6348_RESET_USBH SOFTRESET_6348_USBH_MASK
#define BCM6348_RESET_USBD SOFTRESET_6348_USBS_MASK
#define BCM6348_RESET_DSL SOFTRESET_6348_ADSL_MASK
#define BCM6348_RESET_SAR SOFTRESET_6348_SAR_MASK
#define BCM6348_RESET_EPHY 0
#define BCM6348_RESET_ENETSW 0
#define BCM6348_RESET_PCM 0
#define BCM6348_RESET_MPI 0
#define BCM6348_RESET_PCIE 0
#define BCM6348_RESET_PCIE_EXT 0
#define BCM6358_RESET_SPI SOFTRESET_6358_SPI_MASK
#define BCM6358_RESET_ENET SOFTRESET_6358_ENET_MASK
#define BCM6358_RESET_USBH SOFTRESET_6358_USBH_MASK
#define BCM6358_RESET_USBD 0
#define BCM6358_RESET_DSL SOFTRESET_6358_ADSL_MASK
#define BCM6358_RESET_SAR SOFTRESET_6358_SAR_MASK
#define BCM6358_RESET_EPHY SOFTRESET_6358_EPHY_MASK
#define BCM6358_RESET_ENETSW 0
#define BCM6358_RESET_PCM SOFTRESET_6358_PCM_MASK
#define BCM6358_RESET_MPI SOFTRESET_6358_MPI_MASK
#define BCM6358_RESET_PCIE 0
#define BCM6358_RESET_PCIE_EXT 0
#define BCM6368_RESET_SPI SOFTRESET_6368_SPI_MASK
#define BCM6368_RESET_ENET 0
#define BCM6368_RESET_USBH SOFTRESET_6368_USBH_MASK
#define BCM6368_RESET_USBD SOFTRESET_6368_USBS_MASK
#define BCM6368_RESET_DSL 0
#define BCM6368_RESET_SAR SOFTRESET_6368_SAR_MASK
#define BCM6368_RESET_EPHY SOFTRESET_6368_EPHY_MASK
#define BCM6368_RESET_ENETSW 0
#define BCM6368_RESET_PCM SOFTRESET_6368_PCM_MASK
#define BCM6368_RESET_MPI SOFTRESET_6368_MPI_MASK
#define BCM6368_RESET_PCIE 0
#define BCM6368_RESET_PCIE_EXT 0
#ifdef BCMCPU_RUNTIME_DETECT
/*
* core reset bits
*/
static const u32 bcm6328_reset_bits[] = {
__GEN_RESET_BITS_TABLE(6328)
};
static const u32 bcm6338_reset_bits[] = {
__GEN_RESET_BITS_TABLE(6338)
};
static const u32 bcm6348_reset_bits[] = {
__GEN_RESET_BITS_TABLE(6348)
};
static const u32 bcm6358_reset_bits[] = {
__GEN_RESET_BITS_TABLE(6358)
};
static const u32 bcm6368_reset_bits[] = {
__GEN_RESET_BITS_TABLE(6368)
};
const u32 *bcm63xx_reset_bits;
static int reset_reg;
static int __init bcm63xx_reset_bits_init(void)
{
if (BCMCPU_IS_6328()) {
reset_reg = PERF_SOFTRESET_6328_REG;
bcm63xx_reset_bits = bcm6328_reset_bits;
} else if (BCMCPU_IS_6338()) {
reset_reg = PERF_SOFTRESET_REG;
bcm63xx_reset_bits = bcm6338_reset_bits;
} else if (BCMCPU_IS_6348()) {
reset_reg = PERF_SOFTRESET_REG;
bcm63xx_reset_bits = bcm6348_reset_bits;
} else if (BCMCPU_IS_6358()) {
reset_reg = PERF_SOFTRESET_6358_REG;
bcm63xx_reset_bits = bcm6358_reset_bits;
} else if (BCMCPU_IS_6368()) {
reset_reg = PERF_SOFTRESET_6368_REG;
bcm63xx_reset_bits = bcm6368_reset_bits;
}
return 0;
}
#else
#ifdef CONFIG_BCM63XX_CPU_6328
static const u32 bcm63xx_reset_bits[] = {
__GEN_RESET_BITS_TABLE(6328)
};
#define reset_reg PERF_SOFTRESET_6328_REG
#endif
#ifdef CONFIG_BCM63XX_CPU_6338
static const u32 bcm63xx_reset_bits[] = {
__GEN_RESET_BITS_TABLE(6338)
};
#define reset_reg PERF_SOFTRESET_REG
#endif
#ifdef CONFIG_BCM63XX_CPU_6345
static const u32 bcm63xx_reset_bits[] = { };
#define reset_reg 0
#endif
#ifdef CONFIG_BCM63XX_CPU_6348
static const u32 bcm63xx_reset_bits[] = {
__GEN_RESET_BITS_TABLE(6348)
};
#define reset_reg PERF_SOFTRESET_REG
#endif
#ifdef CONFIG_BCM63XX_CPU_6358
static const u32 bcm63xx_reset_bits[] = {
__GEN_RESET_BITS_TABLE(6358)
};
#define reset_reg PERF_SOFTRESET_6358_REG
#endif
#ifdef CONFIG_BCM63XX_CPU_6368
static const u32 bcm63xx_reset_bits[] = {
__GEN_RESET_BITS_TABLE(6368)
};
#define reset_reg PERF_SOFTRESET_6368_REG
#endif
static int __init bcm63xx_reset_bits_init(void) { return 0; }
#endif
static DEFINE_SPINLOCK(reset_mutex);
static void __bcm63xx_core_set_reset(u32 mask, int enable)
{
unsigned long flags;
u32 val;
if (!mask)
return;
spin_lock_irqsave(&reset_mutex, flags);
val = bcm_perf_readl(reset_reg);
if (enable)
val &= ~mask;
else
val |= mask;
bcm_perf_writel(val, reset_reg);
spin_unlock_irqrestore(&reset_mutex, flags);
}
void bcm63xx_core_set_reset(enum bcm63xx_core_reset core, int reset)
{
__bcm63xx_core_set_reset(bcm63xx_reset_bits[core], reset);
}
EXPORT_SYMBOL(bcm63xx_core_set_reset);
postcore_initcall(bcm63xx_reset_bits_init);
......@@ -51,7 +51,8 @@ static int __init flash_init(void)
flash_map.name = "phys_mapped_flash";
flash_map.phys = region_cfg.s.base << 16;
flash_map.size = 0x1fc00000 - flash_map.phys;
flash_map.bankwidth = 1;
/* 8-bit bus (0 + 1) or 16-bit bus (1 + 1) */
flash_map.bankwidth = region_cfg.s.width + 1;
flash_map.virt = ioremap(flash_map.phys, flash_map.size);
pr_notice("Bootbus flash: Setting flash for %luMB flash at "
"0x%08llx\n", flash_map.size >> 20, flash_map.phys);
......
CONFIG_ATH79=y
CONFIG_ATH79_MACH_AP121=y
CONFIG_ATH79_MACH_AP81=y
CONFIG_ATH79_MACH_DB120=y
CONFIG_ATH79_MACH_PB44=y
CONFIG_ATH79_MACH_UBNT_XM=y
CONFIG_HZ_100=y
# CONFIG_SECCOMP is not set
CONFIG_EXPERIMENTAL=y
# CONFIG_LOCALVERSION_AUTO is not set
CONFIG_SYSVIPC=y
CONFIG_HIGH_RES_TIMERS=y
CONFIG_BLK_DEV_INITRD=y
# CONFIG_RD_GZIP is not set
CONFIG_RD_LZMA=y
# CONFIG_KALLSYMS is not set
# CONFIG_AIO is not set
CONFIG_EMBEDDED=y
# CONFIG_VM_EVENT_COUNTERS is not set
# CONFIG_SLUB_DEBUG is not set
# CONFIG_COMPAT_BRK is not set
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_IOSCHED_CFQ is not set
CONFIG_PCI=y
# CONFIG_SUSPEND is not set
CONFIG_NET=y
CONFIG_PACKET=y
CONFIG_UNIX=y
CONFIG_INET=y
CONFIG_IP_MULTICAST=y
CONFIG_IP_ADVANCED_ROUTER=y
# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
# CONFIG_INET_XFRM_MODE_TUNNEL is not set
# CONFIG_INET_XFRM_MODE_BEET is not set
# CONFIG_INET_LRO is not set
# CONFIG_IPV6 is not set
CONFIG_CFG80211=m
CONFIG_MAC80211=m
CONFIG_MAC80211_DEBUGFS=y
CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
# CONFIG_FIRMWARE_IN_KERNEL is not set
CONFIG_MTD=y
CONFIG_MTD_REDBOOT_PARTS=y
CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-2
CONFIG_MTD_CMDLINE_PARTS=y
CONFIG_MTD_CHAR=y
CONFIG_MTD_BLOCK=y
CONFIG_MTD_CFI=y
CONFIG_MTD_JEDECPROBE=y
CONFIG_MTD_CFI_AMDSTD=y
CONFIG_MTD_COMPLEX_MAPPINGS=y
CONFIG_MTD_PHYSMAP=y
CONFIG_MTD_M25P80=y
# CONFIG_M25PXX_USE_FAST_READ is not set
CONFIG_NETDEVICES=y
# CONFIG_NET_PACKET_ENGINE is not set
CONFIG_ATH_COMMON=m
CONFIG_ATH9K=m
CONFIG_ATH9K_AHB=y
CONFIG_INPUT=m
# CONFIG_INPUT_MOUSEDEV is not set
# CONFIG_KEYBOARD_ATKBD is not set
CONFIG_KEYBOARD_GPIO_POLLED=m
# CONFIG_INPUT_MOUSE is not set
CONFIG_INPUT_MISC=y
# CONFIG_SERIO is not set
# CONFIG_VT is not set
# CONFIG_LEGACY_PTYS is not set
# CONFIG_DEVKMEM is not set
CONFIG_SERIAL_8250=y
CONFIG_SERIAL_8250_CONSOLE=y
# CONFIG_SERIAL_8250_PCI is not set
CONFIG_SERIAL_8250_NR_UARTS=1
CONFIG_SERIAL_8250_RUNTIME_UARTS=1
CONFIG_SERIAL_AR933X=y
CONFIG_SERIAL_AR933X_CONSOLE=y
# CONFIG_HW_RANDOM is not set
CONFIG_I2C=y
# CONFIG_I2C_COMPAT is not set
# CONFIG_I2C_HELPER_AUTO is not set
CONFIG_I2C_GPIO=y
CONFIG_SPI=y
CONFIG_SPI_ATH79=y
CONFIG_SPI_GPIO=y
CONFIG_GPIO_SYSFS=y
CONFIG_GPIO_PCF857X=y
# CONFIG_HWMON is not set
CONFIG_WATCHDOG=y
CONFIG_ATH79_WDT=y
# CONFIG_VGA_ARB is not set
# CONFIG_HID is not set
# CONFIG_USB_HID is not set
CONFIG_USB=y
CONFIG_USB_EHCI_HCD=y
# CONFIG_USB_EHCI_TT_NEWSCHED is not set
CONFIG_USB_OHCI_HCD=y
CONFIG_LEDS_CLASS=y
CONFIG_LEDS_GPIO=y
# CONFIG_IOMMU_SUPPORT is not set
# CONFIG_DNOTIFY is not set
# CONFIG_PROC_PAGE_MONITOR is not set
# CONFIG_ENABLE_MUST_CHECK is not set
CONFIG_STRIP_ASM_SYMS=y
CONFIG_DEBUG_FS=y
# CONFIG_SCHED_DEBUG is not set
# CONFIG_FTRACE is not set
CONFIG_CRYPTO=y
# CONFIG_CRYPTO_ANSI_CPRNG is not set
CONFIG_CRC_ITU_T=m
......@@ -44,8 +44,8 @@ union bcm47xx_bus {
extern union bcm47xx_bus bcm47xx_bus;
extern enum bcm47xx_bus_type bcm47xx_bus_type;
void bcm47xx_fill_sprom(struct ssb_sprom *sprom, const char *prefix);
void bcm47xx_fill_sprom_ethernet(struct ssb_sprom *sprom, const char *prefix);
void bcm47xx_fill_sprom(struct ssb_sprom *sprom, const char *prefix,
bool fallback);
#ifdef CONFIG_BCM47XX_SSB
void bcm47xx_fill_ssb_boardinfo(struct ssb_boardinfo *boardinfo,
......
/*
* 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) 2007 Aurelien Jarno <aurelien@aurel32.net>
*/
#ifndef __ASM_MIPS_MACH_BCM47XX_GPIO_H
#define __ASM_MIPS_MACH_BCM47XX_GPIO_H
#ifndef __BCM47XX_GPIO_H
#define __BCM47XX_GPIO_H
#include <asm-generic/gpio.h>
#include <linux/ssb/ssb_embedded.h>
#include <linux/bcma/bcma.h>
#include <asm/mach-bcm47xx/bcm47xx.h>
#define gpio_get_value __gpio_get_value
#define gpio_set_value __gpio_set_value
#define BCM47XX_EXTIF_GPIO_LINES 5
#define BCM47XX_CHIPCO_GPIO_LINES 16
#define gpio_cansleep __gpio_cansleep
#define gpio_to_irq __gpio_to_irq
extern int gpio_request(unsigned gpio, const char *label);
extern void gpio_free(unsigned gpio);
extern int gpio_to_irq(unsigned gpio);
static inline int gpio_get_value(unsigned gpio)
static inline int irq_to_gpio(unsigned int irq)
{
switch (bcm47xx_bus_type) {
#ifdef CONFIG_BCM47XX_SSB
case BCM47XX_BUS_TYPE_SSB:
return ssb_gpio_in(&bcm47xx_bus.ssb, 1 << gpio);
#endif
#ifdef CONFIG_BCM47XX_BCMA
case BCM47XX_BUS_TYPE_BCMA:
return bcma_chipco_gpio_in(&bcm47xx_bus.bcma.bus.drv_cc,
1 << gpio);
#endif
}
return -EINVAL;
}
#define gpio_get_value_cansleep gpio_get_value
static inline void gpio_set_value(unsigned gpio, int value)
{
switch (bcm47xx_bus_type) {
#ifdef CONFIG_BCM47XX_SSB
case BCM47XX_BUS_TYPE_SSB:
ssb_gpio_out(&bcm47xx_bus.ssb, 1 << gpio,
value ? 1 << gpio : 0);
return;
#endif
#ifdef CONFIG_BCM47XX_BCMA
case BCM47XX_BUS_TYPE_BCMA:
bcma_chipco_gpio_out(&bcm47xx_bus.bcma.bus.drv_cc, 1 << gpio,
value ? 1 << gpio : 0);
return;
#endif
}
}
#define gpio_set_value_cansleep gpio_set_value
static inline int gpio_cansleep(unsigned gpio)
{
return 0;
}
static inline int gpio_is_valid(unsigned gpio)
{
return gpio < (BCM47XX_EXTIF_GPIO_LINES + BCM47XX_CHIPCO_GPIO_LINES);
}
static inline int gpio_direction_input(unsigned gpio)
{
switch (bcm47xx_bus_type) {
#ifdef CONFIG_BCM47XX_SSB
case BCM47XX_BUS_TYPE_SSB:
ssb_gpio_outen(&bcm47xx_bus.ssb, 1 << gpio, 0);
return 0;
#endif
#ifdef CONFIG_BCM47XX_BCMA
case BCM47XX_BUS_TYPE_BCMA:
bcma_chipco_gpio_outen(&bcm47xx_bus.bcma.bus.drv_cc, 1 << gpio,
0);
return 0;
#endif
}
return -EINVAL;
}
static inline int gpio_direction_output(unsigned gpio, int value)
{
switch (bcm47xx_bus_type) {
#ifdef CONFIG_BCM47XX_SSB
case BCM47XX_BUS_TYPE_SSB:
/* first set the gpio out value */
ssb_gpio_out(&bcm47xx_bus.ssb, 1 << gpio,
value ? 1 << gpio : 0);
/* then set the gpio mode */
ssb_gpio_outen(&bcm47xx_bus.ssb, 1 << gpio, 1 << gpio);
return 0;
#endif
#ifdef CONFIG_BCM47XX_BCMA
case BCM47XX_BUS_TYPE_BCMA:
/* first set the gpio out value */
bcma_chipco_gpio_out(&bcm47xx_bus.bcma.bus.drv_cc, 1 << gpio,
value ? 1 << gpio : 0);
/* then set the gpio mode */
bcma_chipco_gpio_outen(&bcm47xx_bus.bcma.bus.drv_cc, 1 << gpio,
1 << gpio);
return 0;
#endif
}
return -EINVAL;
}
static inline int gpio_intmask(unsigned gpio, int value)
{
switch (bcm47xx_bus_type) {
#ifdef CONFIG_BCM47XX_SSB
case BCM47XX_BUS_TYPE_SSB:
ssb_gpio_intmask(&bcm47xx_bus.ssb, 1 << gpio,
value ? 1 << gpio : 0);
return 0;
#endif
#ifdef CONFIG_BCM47XX_BCMA
case BCM47XX_BUS_TYPE_BCMA:
bcma_chipco_gpio_intmask(&bcm47xx_bus.bcma.bus.drv_cc,
1 << gpio, value ? 1 << gpio : 0);
return 0;
#endif
}
return -EINVAL;
}
static inline int gpio_polarity(unsigned gpio, int value)
{
switch (bcm47xx_bus_type) {
#ifdef CONFIG_BCM47XX_SSB
case BCM47XX_BUS_TYPE_SSB:
ssb_gpio_polarity(&bcm47xx_bus.ssb, 1 << gpio,
value ? 1 << gpio : 0);
return 0;
#endif
#ifdef CONFIG_BCM47XX_BCMA
case BCM47XX_BUS_TYPE_BCMA:
bcma_chipco_gpio_polarity(&bcm47xx_bus.bcma.bus.drv_cc,
1 << gpio, value ? 1 << gpio : 0);
return 0;
#endif
}
return -EINVAL;
}
#endif /* __BCM47XX_GPIO_H */
#ifndef BCM63XX_NVRAM_H
#define BCM63XX_NVRAM_H
#include <linux/types.h>
/**
* bcm63xx_nvram_init() - initializes nvram
* @nvram: address of the nvram data
*
* Initialized the local nvram copy from the target address and checks
* its checksum.
*
* Returns 0 on success.
*/
int __init bcm63xx_nvram_init(void *nvram);
/**
* bcm63xx_nvram_get_name() - returns the board name according to nvram
*
* Returns the board name field from nvram. Note that it might not be
* null terminated if it is exactly 16 bytes long.
*/
u8 *bcm63xx_nvram_get_name(void);
/**
* bcm63xx_nvram_get_mac_address() - register & return a new mac address
* @mac: pointer to array for allocated mac
*
* Registers and returns a mac address from the allocated macs from nvram.
*
* Returns 0 on success.
*/
int bcm63xx_nvram_get_mac_address(u8 *mac);
#endif /* BCM63XX_NVRAM_H */
......@@ -53,13 +53,18 @@
CKCTL_6338_SAR_EN | \
CKCTL_6338_SPI_EN)
#define CKCTL_6345_CPU_EN (1 << 0)
#define CKCTL_6345_BUS_EN (1 << 1)
#define CKCTL_6345_EBI_EN (1 << 2)
#define CKCTL_6345_UART_EN (1 << 3)
#define CKCTL_6345_ADSLPHY_EN (1 << 4)
#define CKCTL_6345_ENET_EN (1 << 7)
#define CKCTL_6345_USBH_EN (1 << 8)
/* BCM6345 clock bits are shifted by 16 on the left, because of the test
* control register which is 16-bits wide. That way we do not have any
* specific BCM6345 code for handling clocks, and writing 0 to the test
* control register is fine.
*/
#define CKCTL_6345_CPU_EN (1 << 16)
#define CKCTL_6345_BUS_EN (1 << 17)
#define CKCTL_6345_EBI_EN (1 << 18)
#define CKCTL_6345_UART_EN (1 << 19)
#define CKCTL_6345_ADSLPHY_EN (1 << 20)
#define CKCTL_6345_ENET_EN (1 << 23)
#define CKCTL_6345_USBH_EN (1 << 24)
#define CKCTL_6345_ALL_SAFE_EN (CKCTL_6345_ENET_EN | \
CKCTL_6345_USBH_EN | \
......@@ -191,6 +196,7 @@
/* Soft Reset register */
#define PERF_SOFTRESET_REG 0x28
#define PERF_SOFTRESET_6328_REG 0x10
#define PERF_SOFTRESET_6358_REG 0x34
#define PERF_SOFTRESET_6368_REG 0x10
#define SOFTRESET_6328_SPI_MASK (1 << 0)
......@@ -244,6 +250,15 @@
SOFTRESET_6348_ACLC_MASK | \
SOFTRESET_6348_ADSLMIPSPLL_MASK)
#define SOFTRESET_6358_SPI_MASK (1 << 0)
#define SOFTRESET_6358_ENET_MASK (1 << 2)
#define SOFTRESET_6358_MPI_MASK (1 << 3)
#define SOFTRESET_6358_EPHY_MASK (1 << 6)
#define SOFTRESET_6358_SAR_MASK (1 << 7)
#define SOFTRESET_6358_USBH_MASK (1 << 12)
#define SOFTRESET_6358_PCM_MASK (1 << 13)
#define SOFTRESET_6358_ADSL_MASK (1 << 14)
#define SOFTRESET_6368_SPI_MASK (1 << 0)
#define SOFTRESET_6368_MPI_MASK (1 << 3)
#define SOFTRESET_6368_EPHY_MASK (1 << 6)
......
#ifndef __BCM63XX_RESET_H
#define __BCM63XX_RESET_H
enum bcm63xx_core_reset {
BCM63XX_RESET_SPI,
BCM63XX_RESET_ENET,
BCM63XX_RESET_USBH,
BCM63XX_RESET_USBD,
BCM63XX_RESET_SAR,
BCM63XX_RESET_DSL,
BCM63XX_RESET_EPHY,
BCM63XX_RESET_ENETSW,
BCM63XX_RESET_PCM,
BCM63XX_RESET_MPI,
BCM63XX_RESET_PCIE,
BCM63XX_RESET_PCIE_EXT,
};
void bcm63xx_core_set_reset(enum bcm63xx_core_reset, int reset);
#endif
......@@ -14,23 +14,6 @@
#define BCM963XX_CFE_VERSION_OFFSET 0x570
#define BCM963XX_NVRAM_OFFSET 0x580
/*
* nvram structure
*/
struct bcm963xx_nvram {
u32 version;
u8 reserved1[256];
u8 name[16];
u32 main_tp_number;
u32 psi_size;
u32 mac_addr_count;
u8 mac_addr_base[6];
u8 reserved2[2];
u32 checksum_old;
u8 reserved3[720];
u32 checksum_high;
};
/*
* board definition
*/
......
......@@ -82,6 +82,9 @@ extern __iomem void *ltq_cgu_membase;
#define LTQ_MPS_BASE_ADDR (KSEG1 + 0x1F107000)
#define LTQ_MPS_CHIPID ((u32 *)(LTQ_MPS_BASE_ADDR + 0x0344))
/* allow booting xrx200 phys */
int xrx200_gphy_boot(struct device *dev, unsigned int id, dma_addr_t dev_addr);
/* request a non-gpio and set the PIO config */
#define PMU_PPE BIT(13)
extern void ltq_pmu_enable(unsigned int module);
......
......@@ -18,6 +18,7 @@ extern struct platform_device ls1x_eth0_device;
extern struct platform_device ls1x_ehci_device;
extern struct platform_device ls1x_rtc_device;
void ls1x_serial_setup(void);
extern void __init ls1x_clk_init(void);
extern void __init ls1x_serial_setup(struct platform_device *pdev);
#endif /* __ASM_MACH_LOONGSON1_PLATFORM_H */
......@@ -20,14 +20,15 @@
/* Clock PLL Divisor Register Bits */
#define DIV_DC_EN (0x1 << 31)
#define DIV_DC (0x1f << 26)
#define DIV_CPU_EN (0x1 << 25)
#define DIV_CPU (0x1f << 20)
#define DIV_DDR_EN (0x1 << 19)
#define DIV_DDR (0x1f << 14)
#define DIV_DC_SHIFT 26
#define DIV_CPU_SHIFT 20
#define DIV_DDR_SHIFT 14
#define DIV_DC_WIDTH 5
#define DIV_CPU_WIDTH 5
#define DIV_DDR_WIDTH 5
#endif /* __ASM_MACH_LOONGSON1_REGS_CLK_H */
......@@ -8,7 +8,9 @@
#ifndef __ASM_NETLOGIC_IRQ_H
#define __ASM_NETLOGIC_IRQ_H
#define NR_IRQS 64
#include <asm/mach-netlogic/multi-node.h>
#define NR_IRQS (64 * NLM_NR_NODES)
#define MIPS_CPU_IRQ_BASE 0
#endif /* __ASM_NETLOGIC_IRQ_H */
/*
* 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.
*/
#ifndef _NETLOGIC_MULTI_NODE_H_
#define _NETLOGIC_MULTI_NODE_H_
#ifndef CONFIG_NLM_MULTINODE
#define NLM_NR_NODES 1
#else
#if defined(CONFIG_NLM_MULTINODE_2)
#define NLM_NR_NODES 2
#elif defined(CONFIG_NLM_MULTINODE_4)
#define NLM_NR_NODES 4
#else
#define NLM_NR_NODES 1
#endif
#endif
#define NLM_CORES_PER_NODE 8
#define NLM_THREADS_PER_CORE 4
#define NLM_CPUS_PER_NODE (NLM_CORES_PER_NODE * NLM_THREADS_PER_CORE)
#endif
......@@ -45,15 +45,19 @@
#define BOOT_NMI_HANDLER 8
#ifndef __ASSEMBLY__
#include <linux/cpumask.h>
#include <linux/spinlock.h>
#include <asm/irq.h>
#include <asm/mach-netlogic/multi-node.h>
struct irq_desc;
extern struct plat_smp_ops nlm_smp_ops;
extern char nlm_reset_entry[], nlm_reset_entry_end[];
void nlm_smp_function_ipi_handler(unsigned int irq, struct irq_desc *desc);
void nlm_smp_resched_ipi_handler(unsigned int irq, struct irq_desc *desc);
void nlm_smp_irq_init(void);
void nlm_smp_irq_init(int hwcpuid);
void nlm_boot_secondary_cpus(void);
int nlm_wakeup_secondary_cpus(u32 wakeup_mask);
int nlm_wakeup_secondary_cpus(void);
void nlm_rmiboot_preboot(void);
void nlm_percpu_init(int hwcpuid);
static inline void
nlm_set_nmi_handler(void *handler)
......@@ -68,9 +72,42 @@ nlm_set_nmi_handler(void *handler)
* Misc.
*/
unsigned int nlm_get_cpu_frequency(void);
void nlm_node_init(int node);
extern struct plat_smp_ops nlm_smp_ops;
extern char nlm_reset_entry[], nlm_reset_entry_end[];
extern unsigned int nlm_threads_per_core;
extern cpumask_t nlm_cpumask;
struct nlm_soc_info {
unsigned long coremask; /* cores enabled on the soc */
unsigned long ebase;
uint64_t irqmask;
uint64_t sysbase; /* only for XLP */
uint64_t picbase;
spinlock_t piclock;
};
#define nlm_get_node(i) (&nlm_nodes[i])
#ifdef CONFIG_CPU_XLR
#define nlm_current_node() (&nlm_nodes[0])
#else
#define nlm_current_node() (&nlm_nodes[nlm_nodeid()])
#endif
struct irq_data;
uint64_t nlm_pci_irqmask(int node);
void nlm_set_pic_extra_ack(int node, int irq, void (*xack)(struct irq_data *));
/*
* The NR_IRQs is divided between nodes, each of them has a separate irq space
*/
static inline int nlm_irq_to_xirq(int node, int irq)
{
return node * NR_IRQS / NLM_NR_NODES + irq;
}
extern unsigned long nlm_common_ebase;
extern int nlm_threads_per_core;
extern uint32_t nlm_cpumask, nlm_coremask;
extern struct nlm_soc_info nlm_nodes[NLM_NR_NODES];
extern int nlm_cpu_ready[];
#endif
#endif /* _NETLOGIC_COMMON_H_ */
......@@ -39,7 +39,7 @@
#define IRQ_IPI_SMP_FUNCTION 3
#define IRQ_IPI_SMP_RESCHEDULE 4
#define IRQ_MSGRING 6
#define IRQ_FMN 5
#define IRQ_TIMER 7
#endif
......@@ -73,4 +73,146 @@ static inline int hard_smp_processor_id(void)
return __read_32bit_c0_register($15, 1) & 0x3ff;
}
static inline int nlm_nodeid(void)
{
return (__read_32bit_c0_register($15, 1) >> 5) & 0x3;
}
static inline unsigned int nlm_core_id(void)
{
return (read_c0_ebase() & 0x1c) >> 2;
}
static inline unsigned int nlm_thread_id(void)
{
return read_c0_ebase() & 0x3;
}
#define __read_64bit_c2_split(source, sel) \
({ \
unsigned long long __val; \
unsigned long __flags; \
\
local_irq_save(__flags); \
if (sel == 0) \
__asm__ __volatile__( \
".set\tmips64\n\t" \
"dmfc2\t%M0, " #source "\n\t" \
"dsll\t%L0, %M0, 32\n\t" \
"dsra\t%M0, %M0, 32\n\t" \
"dsra\t%L0, %L0, 32\n\t" \
".set\tmips0\n\t" \
: "=r" (__val)); \
else \
__asm__ __volatile__( \
".set\tmips64\n\t" \
"dmfc2\t%M0, " #source ", " #sel "\n\t" \
"dsll\t%L0, %M0, 32\n\t" \
"dsra\t%M0, %M0, 32\n\t" \
"dsra\t%L0, %L0, 32\n\t" \
".set\tmips0\n\t" \
: "=r" (__val)); \
local_irq_restore(__flags); \
\
__val; \
})
#define __write_64bit_c2_split(source, sel, val) \
do { \
unsigned long __flags; \
\
local_irq_save(__flags); \
if (sel == 0) \
__asm__ __volatile__( \
".set\tmips64\n\t" \
"dsll\t%L0, %L0, 32\n\t" \
"dsrl\t%L0, %L0, 32\n\t" \
"dsll\t%M0, %M0, 32\n\t" \
"or\t%L0, %L0, %M0\n\t" \
"dmtc2\t%L0, " #source "\n\t" \
".set\tmips0\n\t" \
: : "r" (val)); \
else \
__asm__ __volatile__( \
".set\tmips64\n\t" \
"dsll\t%L0, %L0, 32\n\t" \
"dsrl\t%L0, %L0, 32\n\t" \
"dsll\t%M0, %M0, 32\n\t" \
"or\t%L0, %L0, %M0\n\t" \
"dmtc2\t%L0, " #source ", " #sel "\n\t" \
".set\tmips0\n\t" \
: : "r" (val)); \
local_irq_restore(__flags); \
} while (0)
#define __read_32bit_c2_register(source, sel) \
({ uint32_t __res; \
if (sel == 0) \
__asm__ __volatile__( \
".set\tmips32\n\t" \
"mfc2\t%0, " #source "\n\t" \
".set\tmips0\n\t" \
: "=r" (__res)); \
else \
__asm__ __volatile__( \
".set\tmips32\n\t" \
"mfc2\t%0, " #source ", " #sel "\n\t" \
".set\tmips0\n\t" \
: "=r" (__res)); \
__res; \
})
#define __read_64bit_c2_register(source, sel) \
({ unsigned long long __res; \
if (sizeof(unsigned long) == 4) \
__res = __read_64bit_c2_split(source, sel); \
else if (sel == 0) \
__asm__ __volatile__( \
".set\tmips64\n\t" \
"dmfc2\t%0, " #source "\n\t" \
".set\tmips0\n\t" \
: "=r" (__res)); \
else \
__asm__ __volatile__( \
".set\tmips64\n\t" \
"dmfc2\t%0, " #source ", " #sel "\n\t" \
".set\tmips0\n\t" \
: "=r" (__res)); \
__res; \
})
#define __write_64bit_c2_register(register, sel, value) \
do { \
if (sizeof(unsigned long) == 4) \
__write_64bit_c2_split(register, sel, value); \
else if (sel == 0) \
__asm__ __volatile__( \
".set\tmips64\n\t" \
"dmtc2\t%z0, " #register "\n\t" \
".set\tmips0\n\t" \
: : "Jr" (value)); \
else \
__asm__ __volatile__( \
".set\tmips64\n\t" \
"dmtc2\t%z0, " #register ", " #sel "\n\t" \
".set\tmips0\n\t" \
: : "Jr" (value)); \
} while (0)
#define __write_32bit_c2_register(reg, sel, value) \
({ \
if (sel == 0) \
__asm__ __volatile__( \
".set\tmips32\n\t" \
"mtc2\t%z0, " #reg "\n\t" \
".set\tmips0\n\t" \
: : "Jr" (value)); \
else \
__asm__ __volatile__( \
".set\tmips32\n\t" \
"mtc2\t%z0, " #reg ", " #sel "\n\t" \
".set\tmips0\n\t" \
: : "Jr" (value)); \
})
#endif /*_ASM_NLM_MIPS_EXTS_H */
......@@ -273,36 +273,16 @@ nlm_pic_read_irt(uint64_t base, int irt_index)
return nlm_read_pic_reg(base, PIC_IRT(irt_index));
}
static inline uint64_t
nlm_pic_read_control(uint64_t base)
{
return nlm_read_pic_reg(base, PIC_CTRL);
}
static inline void
nlm_pic_write_control(uint64_t base, uint64_t control)
{
nlm_write_pic_reg(base, PIC_CTRL, control);
}
static inline void
nlm_pic_update_control(uint64_t base, uint64_t control)
{
uint64_t val;
val = nlm_read_pic_reg(base, PIC_CTRL);
nlm_write_pic_reg(base, PIC_CTRL, control | val);
}
static inline void
nlm_set_irt_to_cpu(uint64_t base, int irt, int cpu)
{
uint64_t val;
val = nlm_read_pic_reg(base, PIC_IRT(irt));
val |= cpu & 0xf;
if (cpu > 15)
val |= 1 << 16;
/* clear cpuset and mask */
val &= ~((0x7ull << 16) | 0xffff);
/* set DB, cpuset and cpumask */
val |= (1 << 19) | ((cpu >> 4) << 16) | (1 << (cpu & 0xf));
nlm_write_pic_reg(base, PIC_IRT(irt), val);
}
......@@ -369,7 +349,7 @@ nlm_pic_enable_irt(uint64_t base, int irt)
static inline void
nlm_pic_disable_irt(uint64_t base, int irt)
{
uint32_t reg;
uint64_t reg;
reg = nlm_read_pic_reg(base, PIC_IRT(irt));
nlm_write_pic_reg(base, PIC_IRT(irt), reg & ~((uint64_t)1 << 31));
......@@ -379,15 +359,9 @@ static inline void
nlm_pic_send_ipi(uint64_t base, int hwt, int irq, int nmi)
{
uint64_t ipi;
int node, ncpu;
node = hwt / 32;
ncpu = hwt & 0x1f;
ipi = ((uint64_t)nmi << 31) | (irq << 20) | (node << 17) |
(1 << (ncpu & 0xf));
if (ncpu > 15)
ipi |= 0x10000; /* Setting bit 16 to select cpus 16-31 */
ipi = (nmi << 31) | (irq << 20);
ipi |= ((hwt >> 4) << 16) | (1 << (hwt & 0xf)); /* cpuset and mask */
nlm_write_pic_reg(base, PIC_IPI_CTL, ipi);
}
......@@ -404,12 +378,10 @@ nlm_pic_ack(uint64_t base, int irt_num)
static inline void
nlm_pic_init_irt(uint64_t base, int irt, int irq, int hwt)
{
nlm_pic_write_irt_direct(base, irt, 0, 0, 0, irq, 0);
nlm_pic_write_irt_direct(base, irt, 0, 0, 0, irq, hwt);
}
extern uint64_t nlm_pic_base;
int nlm_irq_to_irt(int irq);
int nlm_irt_to_irq(int irt);
#endif /* __ASSEMBLY__ */
#endif /* _NLM_HAL_PIC_H */
......@@ -124,6 +124,5 @@
#define nlm_get_sys_pcibase(node) nlm_pcicfg_base(XLP_IO_SYS_OFFSET(node))
#define nlm_get_sys_regbase(node) (nlm_get_sys_pcibase(node) + XLP_IO_PCI_HDRSZ)
extern uint64_t nlm_sys_base;
#endif
#endif
This diff is collapsed.
......@@ -258,7 +258,5 @@ nlm_pic_init_irt(uint64_t base, int irt, int irq, int hwt)
nlm_write_reg(base, PIC_IRT_1(irt),
(1 << 30) | (1 << 6) | irq);
}
extern uint64_t nlm_pic_base;
#endif
#endif /* _ASM_NLM_XLR_PIC_H */
......@@ -51,10 +51,8 @@ static inline unsigned int nlm_chip_is_xls_b(void)
return ((prid & 0xf000) == 0x4000);
}
/*
* XLR chip types
*/
/* The XLS product line has chip versions 0x[48c]? */
/* XLR chip types */
/* The XLS product line has chip versions 0x[48c]? */
static inline unsigned int nlm_chip_is_xls(void)
{
uint32_t prid = read_c0_prid();
......
......@@ -840,6 +840,16 @@ static const struct mips_perf_event bmips5000_event_map
[PERF_COUNT_HW_BRANCH_MISSES] = { 0x02, CNTR_ODD, T },
};
static const struct mips_perf_event xlp_event_map[PERF_COUNT_HW_MAX] = {
[PERF_COUNT_HW_CPU_CYCLES] = { 0x01, CNTR_ALL },
[PERF_COUNT_HW_INSTRUCTIONS] = { 0x18, CNTR_ALL }, /* PAPI_TOT_INS */
[PERF_COUNT_HW_CACHE_REFERENCES] = { 0x04, CNTR_ALL }, /* PAPI_L1_ICA */
[PERF_COUNT_HW_CACHE_MISSES] = { 0x07, CNTR_ALL }, /* PAPI_L1_ICM */
[PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = { 0x1b, CNTR_ALL }, /* PAPI_BR_CN */
[PERF_COUNT_HW_BRANCH_MISSES] = { 0x1c, CNTR_ALL }, /* PAPI_BR_MSP */
[PERF_COUNT_HW_BUS_CYCLES] = { UNSUPPORTED_PERF_EVENT_ID },
};
/* 24K/34K/1004K cores can share the same cache event map. */
static const struct mips_perf_event mipsxxcore_cache_map
[PERF_COUNT_HW_CACHE_MAX]
......@@ -1092,6 +1102,100 @@ static const struct mips_perf_event octeon_cache_map
},
};
static const struct mips_perf_event xlp_cache_map
[PERF_COUNT_HW_CACHE_MAX]
[PERF_COUNT_HW_CACHE_OP_MAX]
[PERF_COUNT_HW_CACHE_RESULT_MAX] = {
[C(L1D)] = {
[C(OP_READ)] = {
[C(RESULT_ACCESS)] = { 0x31, CNTR_ALL }, /* PAPI_L1_DCR */
[C(RESULT_MISS)] = { 0x30, CNTR_ALL }, /* PAPI_L1_LDM */
},
[C(OP_WRITE)] = {
[C(RESULT_ACCESS)] = { 0x2f, CNTR_ALL }, /* PAPI_L1_DCW */
[C(RESULT_MISS)] = { 0x2e, CNTR_ALL }, /* PAPI_L1_STM */
},
[C(OP_PREFETCH)] = {
[C(RESULT_ACCESS)] = { UNSUPPORTED_PERF_EVENT_ID },
[C(RESULT_MISS)] = { UNSUPPORTED_PERF_EVENT_ID },
},
},
[C(L1I)] = {
[C(OP_READ)] = {
[C(RESULT_ACCESS)] = { 0x04, CNTR_ALL }, /* PAPI_L1_ICA */
[C(RESULT_MISS)] = { 0x07, CNTR_ALL }, /* PAPI_L1_ICM */
},
[C(OP_WRITE)] = {
[C(RESULT_ACCESS)] = { UNSUPPORTED_PERF_EVENT_ID },
[C(RESULT_MISS)] = { UNSUPPORTED_PERF_EVENT_ID },
},
[C(OP_PREFETCH)] = {
[C(RESULT_ACCESS)] = { UNSUPPORTED_PERF_EVENT_ID },
[C(RESULT_MISS)] = { UNSUPPORTED_PERF_EVENT_ID },
},
},
[C(LL)] = {
[C(OP_READ)] = {
[C(RESULT_ACCESS)] = { 0x35, CNTR_ALL }, /* PAPI_L2_DCR */
[C(RESULT_MISS)] = { 0x37, CNTR_ALL }, /* PAPI_L2_LDM */
},
[C(OP_WRITE)] = {
[C(RESULT_ACCESS)] = { 0x34, CNTR_ALL }, /* PAPI_L2_DCA */
[C(RESULT_MISS)] = { 0x36, CNTR_ALL }, /* PAPI_L2_DCM */
},
[C(OP_PREFETCH)] = {
[C(RESULT_ACCESS)] = { UNSUPPORTED_PERF_EVENT_ID },
[C(RESULT_MISS)] = { UNSUPPORTED_PERF_EVENT_ID },
},
},
[C(DTLB)] = {
/*
* Only general DTLB misses are counted use the same event for
* read and write.
*/
[C(OP_READ)] = {
[C(RESULT_ACCESS)] = { UNSUPPORTED_PERF_EVENT_ID },
[C(RESULT_MISS)] = { 0x2d, CNTR_ALL }, /* PAPI_TLB_DM */
},
[C(OP_WRITE)] = {
[C(RESULT_ACCESS)] = { UNSUPPORTED_PERF_EVENT_ID },
[C(RESULT_MISS)] = { 0x2d, CNTR_ALL }, /* PAPI_TLB_DM */
},
[C(OP_PREFETCH)] = {
[C(RESULT_ACCESS)] = { UNSUPPORTED_PERF_EVENT_ID },
[C(RESULT_MISS)] = { UNSUPPORTED_PERF_EVENT_ID },
},
},
[C(ITLB)] = {
[C(OP_READ)] = {
[C(RESULT_ACCESS)] = { UNSUPPORTED_PERF_EVENT_ID },
[C(RESULT_MISS)] = { 0x08, CNTR_ALL }, /* PAPI_TLB_IM */
},
[C(OP_WRITE)] = {
[C(RESULT_ACCESS)] = { UNSUPPORTED_PERF_EVENT_ID },
[C(RESULT_MISS)] = { 0x08, CNTR_ALL }, /* PAPI_TLB_IM */
},
[C(OP_PREFETCH)] = {
[C(RESULT_ACCESS)] = { UNSUPPORTED_PERF_EVENT_ID },
[C(RESULT_MISS)] = { UNSUPPORTED_PERF_EVENT_ID },
},
},
[C(BPU)] = {
[C(OP_READ)] = {
[C(RESULT_ACCESS)] = { UNSUPPORTED_PERF_EVENT_ID },
[C(RESULT_MISS)] = { 0x25, CNTR_ALL },
},
[C(OP_WRITE)] = {
[C(RESULT_ACCESS)] = { UNSUPPORTED_PERF_EVENT_ID },
[C(RESULT_MISS)] = { UNSUPPORTED_PERF_EVENT_ID },
},
[C(OP_PREFETCH)] = {
[C(RESULT_ACCESS)] = { UNSUPPORTED_PERF_EVENT_ID },
[C(RESULT_MISS)] = { UNSUPPORTED_PERF_EVENT_ID },
},
},
};
#ifdef CONFIG_MIPS_MT_SMP
static void check_and_calc_range(struct perf_event *event,
const struct mips_perf_event *pev)
......@@ -1444,6 +1548,20 @@ static const struct mips_perf_event *octeon_pmu_map_raw_event(u64 config)
return &raw_event;
}
static const struct mips_perf_event *xlp_pmu_map_raw_event(u64 config)
{
unsigned int raw_id = config & 0xff;
/* Only 1-63 are defined */
if ((raw_id < 0x01) || (raw_id > 0x3f))
return ERR_PTR(-EOPNOTSUPP);
raw_event.cntr_mask = CNTR_ALL;
raw_event.event_id = raw_id;
return &raw_event;
}
static int __init
init_hw_perf_events(void)
{
......@@ -1522,6 +1640,12 @@ init_hw_perf_events(void)
mipspmu.general_event_map = &bmips5000_event_map;
mipspmu.cache_event_map = &bmips5000_cache_map;
break;
case CPU_XLP:
mipspmu.name = "xlp";
mipspmu.general_event_map = &xlp_event_map;
mipspmu.cache_event_map = &xlp_cache_map;
mipspmu.map_raw_event = xlp_pmu_map_raw_event;
break;
default:
pr_cont("Either hardware does not support performance "
"counters, or not yet implemented.\n");
......
......@@ -36,4 +36,8 @@ config PCI_LANTIQ
bool "PCI Support"
depends on SOC_XWAY && PCI
config XRX200_PHY_FW
bool "XRX200 PHY firmware loader"
depends on SOC_XWAY
endif
......@@ -87,9 +87,6 @@ void __init device_tree_init(void)
reserve_bootmem(base, size, BOOTMEM_DEFAULT);
unflatten_device_tree();
/* free the space reserved for the dt blob */
free_bootmem(base, size);
}
void __init prom_init(void)
......@@ -119,7 +116,7 @@ int __init plat_of_setup(void)
sizeof(of_ids[0].compatible));
strncpy(of_ids[1].compatible, "simple-bus",
sizeof(of_ids[1].compatible));
return of_platform_bus_probe(NULL, of_ids, NULL);
return of_platform_populate(NULL, of_ids, NULL, NULL);
}
arch_initcall(plat_of_setup);
obj-y := prom.o sysctrl.o clk.o reset.o dma.o gptu.o
obj-$(CONFIG_XRX200_PHY_FW) += xrx200_phy_fw.o
......@@ -25,6 +25,7 @@
#include <lantiq_soc.h>
#include <xway_dma.h>
#define LTQ_DMA_ID 0x08
#define LTQ_DMA_CTRL 0x10
#define LTQ_DMA_CPOLL 0x14
#define LTQ_DMA_CS 0x18
......@@ -214,6 +215,7 @@ ltq_dma_init(struct platform_device *pdev)
{
struct clk *clk;
struct resource *res;
unsigned id;
int i;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
......@@ -243,7 +245,12 @@ ltq_dma_init(struct platform_device *pdev)
ltq_dma_w32(DMA_POLL | DMA_CLK_DIV4, LTQ_DMA_CPOLL);
ltq_dma_w32_mask(DMA_CHAN_ON, 0, LTQ_DMA_CCTRL);
}
dev_info(&pdev->dev, "init done\n");
id = ltq_dma_r32(LTQ_DMA_ID);
dev_info(&pdev->dev,
"Init done - hw rev: %X, ports: %d, channels: %d\n",
id & 0x1f, (id >> 16) & 0xf, id >> 20);
return 0;
}
......
......@@ -28,17 +28,24 @@
#define RCU_RST_REQ 0x0010
/* reset status register */
#define RCU_RST_STAT 0x0014
/* vr9 gphy registers */
#define RCU_GFS_ADD0_XRX200 0x0020
#define RCU_GFS_ADD1_XRX200 0x0068
/* reboot bit */
#define RCU_RD_GPHY0_XRX200 BIT(31)
#define RCU_RD_SRST BIT(30)
#define RCU_RD_GPHY1_XRX200 BIT(29)
/* reset cause */
#define RCU_STAT_SHIFT 26
/* boot selection */
#define RCU_BOOT_SEL_SHIFT 26
#define RCU_BOOT_SEL_MASK 0x7
#define RCU_BOOT_SEL(x) ((x >> 18) & 0x7)
#define RCU_BOOT_SEL_XRX200(x) (((x >> 17) & 0xf) | ((x >> 8) & 0x10))
/* remapped base addr of the reset control unit */
static void __iomem *ltq_rcu_membase;
static struct device_node *ltq_rcu_np;
/* This function is used by the watchdog driver */
int ltq_reset_cause(void)
......@@ -52,7 +59,41 @@ EXPORT_SYMBOL_GPL(ltq_reset_cause);
unsigned char ltq_boot_select(void)
{
u32 val = ltq_rcu_r32(RCU_RST_STAT);
return (val >> RCU_BOOT_SEL_SHIFT) & RCU_BOOT_SEL_MASK;
if (of_device_is_compatible(ltq_rcu_np, "lantiq,rcu-xrx200"))
return RCU_BOOT_SEL_XRX200(val);
return RCU_BOOT_SEL(val);
}
/* reset / boot a gphy */
static struct ltq_xrx200_gphy_reset {
u32 rd;
u32 addr;
} xrx200_gphy[] = {
{RCU_RD_GPHY0_XRX200, RCU_GFS_ADD0_XRX200},
{RCU_RD_GPHY1_XRX200, RCU_GFS_ADD1_XRX200},
};
/* reset and boot a gphy. these phys only exist on xrx200 SoC */
int xrx200_gphy_boot(struct device *dev, unsigned int id, dma_addr_t dev_addr)
{
if (!of_device_is_compatible(ltq_rcu_np, "lantiq,rcu-xrx200")) {
dev_err(dev, "this SoC has no GPHY\n");
return -EINVAL;
}
if (id > 1) {
dev_err(dev, "%u is an invalid gphy id\n", id);
return -EINVAL;
}
dev_info(dev, "booting GPHY%u firmware at %X\n", id, dev_addr);
ltq_rcu_w32(ltq_rcu_r32(RCU_RST_REQ) | xrx200_gphy[id].rd,
RCU_RST_REQ);
ltq_rcu_w32(dev_addr, xrx200_gphy[id].addr);
ltq_rcu_w32(ltq_rcu_r32(RCU_RST_REQ) & ~xrx200_gphy[id].rd,
RCU_RST_REQ);
return 0;
}
/* reset a io domain for u micro seconds */
......@@ -85,14 +126,17 @@ static void ltq_machine_power_off(void)
static int __init mips_reboot_setup(void)
{
struct resource res;
struct device_node *np =
of_find_compatible_node(NULL, NULL, "lantiq,rcu-xway");
ltq_rcu_np = of_find_compatible_node(NULL, NULL, "lantiq,rcu-xway");
if (!ltq_rcu_np)
ltq_rcu_np = of_find_compatible_node(NULL, NULL,
"lantiq,rcu-xrx200");
/* check if all the reset register range is available */
if (!np)
if (!ltq_rcu_np)
panic("Failed to load reset resources from devicetree");
if (of_address_to_resource(np, 0, &res))
if (of_address_to_resource(ltq_rcu_np, 0, &res))
panic("Failed to get rcu memory range");
if (request_mem_region(res.start, resource_size(&res), res.name) < 0)
......
......@@ -370,6 +370,10 @@ void __init ltq_soc_init(void)
clkdev_add_pmu("1d900000.pcie", "pdi", 1, PMU1_PCIE_PDI);
clkdev_add_pmu("1d900000.pcie", "ctl", 1, PMU1_PCIE_CTL);
clkdev_add_pmu("1d900000.pcie", "ahb", 0, PMU_AHBM | PMU_AHBS);
clkdev_add_pmu("1e108000.eth", NULL, 0,
PMU_SWITCH | PMU_PPE_DPLUS | PMU_PPE_DPLUM |
PMU_PPE_EMA | PMU_PPE_TC | PMU_PPE_SLL01 |
PMU_PPE_QSB | PMU_PPE_TOP);
} else if (of_machine_is_compatible("lantiq,ar9")) {
clkdev_add_static(ltq_ar9_cpu_hz(), ltq_ar9_fpi_hz(),
ltq_ar9_fpi_hz());
......
/*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published
* by the Free Software Foundation.
*
* Copyright (C) 2012 John Crispin <blogic@openwrt.org>
*/
#include <linux/delay.h>
#include <linux/dma-mapping.h>
#include <linux/module.h>
#include <linux/firmware.h>
#include <linux/of_platform.h>
#include <lantiq_soc.h>
#define XRX200_GPHY_FW_ALIGN (16 * 1024)
static dma_addr_t xway_gphy_load(struct platform_device *pdev)
{
const struct firmware *fw;
dma_addr_t dev_addr = 0;
const char *fw_name;
void *fw_addr;
size_t size;
if (of_property_read_string(pdev->dev.of_node, "firmware", &fw_name)) {
dev_err(&pdev->dev, "failed to load firmware filename\n");
return 0;
}
dev_info(&pdev->dev, "requesting %s\n", fw_name);
if (request_firmware(&fw, fw_name, &pdev->dev)) {
dev_err(&pdev->dev, "failed to load firmware: %s\n", fw_name);
return 0;
}
/*
* GPHY cores need the firmware code in a persistent and contiguous
* memory area with a 16 kB boundary aligned start address
*/
size = fw->size + XRX200_GPHY_FW_ALIGN;
fw_addr = dma_alloc_coherent(&pdev->dev, size, &dev_addr, GFP_KERNEL);
if (fw_addr) {
fw_addr = PTR_ALIGN(fw_addr, XRX200_GPHY_FW_ALIGN);
dev_addr = ALIGN(dev_addr, XRX200_GPHY_FW_ALIGN);
memcpy(fw_addr, fw->data, fw->size);
} else {
dev_err(&pdev->dev, "failed to alloc firmware memory\n");
}
release_firmware(fw);
return dev_addr;
}
static int __devinit xway_phy_fw_probe(struct platform_device *pdev)
{
dma_addr_t fw_addr;
struct property *pp;
unsigned char *phyids;
int i, ret = 0;
fw_addr = xway_gphy_load(pdev);
if (!fw_addr)
return -EINVAL;
pp = of_find_property(pdev->dev.of_node, "phys", NULL);
if (!pp)
return -ENOENT;
phyids = pp->value;
for (i = 0; i < pp->length && !ret; i++)
ret = xrx200_gphy_boot(&pdev->dev, phyids[i], fw_addr);
if (!ret)
mdelay(100);
return ret;
}
static const struct of_device_id xway_phy_match[] = {
{ .compatible = "lantiq,phy-xrx200" },
{},
};
MODULE_DEVICE_TABLE(of, xway_phy_match);
static struct platform_driver xway_phy_driver = {
.probe = xway_phy_fw_probe,
.driver = {
.name = "phy-xrx200",
.owner = THIS_MODULE,
.of_match_table = xway_phy_match,
},
};
module_platform_driver(xway_phy_driver);
MODULE_AUTHOR("John Crispin <blogic@openwrt.org>");
MODULE_DESCRIPTION("Lantiq XRX200 PHY Firmware Loader");
MODULE_LICENSE("GPL");
......@@ -15,7 +15,7 @@ config LOONGSON1_LS1B
select SYS_SUPPORTS_LITTLE_ENDIAN
select SYS_SUPPORTS_HIGHMEM
select SYS_HAS_EARLY_PRINTK
select HAVE_CLK
select COMMON_CLK
endchoice
......
......@@ -7,175 +7,22 @@
* option) any later version.
*/
#include <linux/module.h>
#include <linux/list.h>
#include <linux/mutex.h>
#include <linux/clk.h>
#include <linux/err.h>
#include <asm/clock.h>
#include <asm/time.h>
#include <loongson1.h>
static LIST_HEAD(clocks);
static DEFINE_MUTEX(clocks_mutex);
struct clk *clk_get(struct device *dev, const char *name)
{
struct clk *c;
struct clk *ret = NULL;
mutex_lock(&clocks_mutex);
list_for_each_entry(c, &clocks, node) {
if (!strcmp(c->name, name)) {
ret = c;
break;
}
}
mutex_unlock(&clocks_mutex);
return ret;
}
EXPORT_SYMBOL(clk_get);
int clk_enable(struct clk *clk)
{
return 0;
}
EXPORT_SYMBOL(clk_enable);
void clk_disable(struct clk *clk)
{
}
EXPORT_SYMBOL(clk_disable);
unsigned long clk_get_rate(struct clk *clk)
{
return clk->rate;
}
EXPORT_SYMBOL(clk_get_rate);
void clk_put(struct clk *clk)
{
}
EXPORT_SYMBOL(clk_put);
static void pll_clk_init(struct clk *clk)
{
u32 pll;
pll = __raw_readl(LS1X_CLK_PLL_FREQ);
clk->rate = (12 + (pll & 0x3f)) * 33 / 2
+ ((pll >> 8) & 0x3ff) * 33 / 1024 / 2;
clk->rate *= 1000000;
}
static void cpu_clk_init(struct clk *clk)
{
u32 pll, ctrl;
pll = clk_get_rate(clk->parent);
ctrl = __raw_readl(LS1X_CLK_PLL_DIV) & DIV_CPU;
clk->rate = pll / (ctrl >> DIV_CPU_SHIFT);
}
static void ddr_clk_init(struct clk *clk)
{
u32 pll, ctrl;
pll = clk_get_rate(clk->parent);
ctrl = __raw_readl(LS1X_CLK_PLL_DIV) & DIV_DDR;
clk->rate = pll / (ctrl >> DIV_DDR_SHIFT);
}
static void dc_clk_init(struct clk *clk)
{
u32 pll, ctrl;
pll = clk_get_rate(clk->parent);
ctrl = __raw_readl(LS1X_CLK_PLL_DIV) & DIV_DC;
clk->rate = pll / (ctrl >> DIV_DC_SHIFT);
}
static struct clk_ops pll_clk_ops = {
.init = pll_clk_init,
};
static struct clk_ops cpu_clk_ops = {
.init = cpu_clk_init,
};
static struct clk_ops ddr_clk_ops = {
.init = ddr_clk_init,
};
static struct clk_ops dc_clk_ops = {
.init = dc_clk_init,
};
static struct clk pll_clk = {
.name = "pll",
.ops = &pll_clk_ops,
};
static struct clk cpu_clk = {
.name = "cpu",
.parent = &pll_clk,
.ops = &cpu_clk_ops,
};
static struct clk ddr_clk = {
.name = "ddr",
.parent = &pll_clk,
.ops = &ddr_clk_ops,
};
static struct clk dc_clk = {
.name = "dc",
.parent = &pll_clk,
.ops = &dc_clk_ops,
};
int clk_register(struct clk *clk)
{
mutex_lock(&clocks_mutex);
list_add(&clk->node, &clocks);
if (clk->ops->init)
clk->ops->init(clk);
mutex_unlock(&clocks_mutex);
return 0;
}
EXPORT_SYMBOL(clk_register);
static struct clk *ls1x_clks[] = {
&pll_clk,
&cpu_clk,
&ddr_clk,
&dc_clk,
};
int __init ls1x_clock_init(void)
{
int i;
for (i = 0; i < ARRAY_SIZE(ls1x_clks); i++)
clk_register(ls1x_clks[i]);
return 0;
}
#include <platform.h>
void __init plat_time_init(void)
{
struct clk *clk;
/* Initialize LS1X clocks */
ls1x_clock_init();
ls1x_clk_init();
/* setup mips r4k timer */
clk = clk_get(NULL, "cpu");
if (IS_ERR(clk))
panic("unable to get dc clock, err=%ld", PTR_ERR(clk));
panic("unable to get cpu clock, err=%ld", PTR_ERR(clk));
mips_hpt_frequency = clk_get_rate(clk) / 2;
}
......@@ -42,16 +42,17 @@ struct platform_device ls1x_uart_device = {
},
};
void __init ls1x_serial_setup(void)
void __init ls1x_serial_setup(struct platform_device *pdev)
{
struct clk *clk;
struct plat_serial8250_port *p;
clk = clk_get(NULL, "dc");
clk = clk_get(NULL, pdev->name);
if (IS_ERR(clk))
panic("unable to get dc clock, err=%ld", PTR_ERR(clk));
panic("unable to get %s clock, err=%ld",
pdev->name, PTR_ERR(clk));
for (p = ls1x_serial8250_port; p->flags != 0; ++p)
for (p = pdev->dev.platform_data; p->flags != 0; ++p)
p->uartclk = clk_get_rate(clk);
}
......@@ -70,7 +71,6 @@ static struct resource ls1x_eth0_resources[] = {
};
static struct stmmac_mdio_bus_data ls1x_mdio_bus_data = {
.bus_id = 0,
.phy_mask = 0,
};
......
......@@ -9,9 +9,6 @@
#include <platform.h>
#include <linux/serial_8250.h>
#include <loongson1.h>
static struct platform_device *ls1b_platform_devices[] __initdata = {
&ls1x_uart_device,
&ls1x_eth0_device,
......@@ -23,7 +20,7 @@ static int __init ls1b_platform_init(void)
{
int err;
ls1x_serial_setup();
ls1x_serial_setup(&ls1x_uart_device);
err = platform_add_devices(ls1b_platform_devices,
ARRAY_SIZE(ls1b_platform_devices));
......
......@@ -1333,10 +1333,10 @@ static int __init cca_setup(char *str)
{
get_option(&str, &cca);
return 1;
return 0;
}
__setup("cca=", cca_setup);
early_param("cca", cca_setup);
static void __cpuinit coherency_setup(void)
{
......@@ -1386,10 +1386,10 @@ static int __init setcoherentio(char *str)
{
coherentio = 1;
return 1;
return 0;
}
__setup("coherentio", setcoherentio);
early_param("coherentio", setcoherentio);
#endif
static void __cpuinit r4k_cache_error_setup(void)
......
......@@ -183,7 +183,9 @@ UASM_L_LA(_tlb_huge_update)
static int __cpuinitdata hazard_instance;
static void uasm_bgezl_hazard(u32 **p, struct uasm_reloc **r, int instance)
static void __cpuinit uasm_bgezl_hazard(u32 **p,
struct uasm_reloc **r,
int instance)
{
switch (instance) {
case 0 ... 7:
......@@ -194,7 +196,9 @@ static void uasm_bgezl_hazard(u32 **p, struct uasm_reloc **r, int instance)
}
}
static void uasm_bgezl_label(struct uasm_label **l, u32 **p, int instance)
static void __cpuinit uasm_bgezl_label(struct uasm_label **l,
u32 **p,
int instance)
{
switch (instance) {
case 0 ... 7:
......
......@@ -9,6 +9,34 @@ config DT_XLP_EVP
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 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
......
......@@ -36,7 +36,6 @@
#include <linux/init.h>
#include <linux/linkage.h>
#include <linux/interrupt.h>
#include <linux/spinlock.h>
#include <linux/mm.h>
#include <linux/slab.h>
#include <linux/irq.h>
......@@ -59,68 +58,70 @@
#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
/*
* These are the routines that handle all the low level interrupt stuff.
* Actions handled here are: initialization of the interrupt map, requesting of
* interrupt lines by handlers, dispatching if interrupts to handlers, probing
* for interrupt lines
*/
/* Globals */
static uint64_t nlm_irq_mask;
static DEFINE_SPINLOCK(nlm_pic_lock);
#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;
int irt;
struct nlm_pic_irq *pd = irq_data_get_irq_handler_data(d);
irt = nlm_irq_to_irt(d->irq);
if (irt == -1)
return;
spin_lock_irqsave(&nlm_pic_lock, flags);
nlm_pic_enable_irt(nlm_pic_base, irt);
spin_unlock_irqrestore(&nlm_pic_lock, flags);
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;
int irt;
irt = nlm_irq_to_irt(d->irq);
if (irt == -1)
return;
spin_lock_irqsave(&nlm_pic_lock, flags);
nlm_pic_disable_irt(nlm_pic_base, irt);
spin_unlock_irqrestore(&nlm_pic_lock, 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)
{
uint64_t mask = 1ull << d->irq;
struct nlm_pic_irq *pd = irq_data_get_irq_handler_data(d);
uint64_t mask = 1ull << pd->picirq;
write_c0_eirr(mask); /* ack by writing EIRR */
}
static void xlp_pic_unmask(struct irq_data *d)
{
void *hd = irq_data_get_irq_handler_data(d);
int irt;
struct nlm_pic_irq *pd = irq_data_get_irq_handler_data(d);
irt = nlm_irq_to_irt(d->irq);
if (irt == -1)
if (!pd)
return;
if (hd) {
void (*extra_ack)(void *) = hd;
extra_ack(d);
}
if (pd->extra_ack)
pd->extra_ack(d);
/* Ack is a single write, no need to lock */
nlm_pic_ack(nlm_pic_base, irt);
nlm_pic_ack(pd->node->picbase, pd->irt);
}
static struct irq_chip xlp_pic = {
......@@ -174,64 +175,108 @@ struct irq_chip nlm_cpu_intr = {
.irq_eoi = cpuintr_ack,
};
void __init init_nlm_common_irqs(void)
static void __init nlm_init_percpu_irqs(void)
{
int i, irq, irt;
int i;
for (i = 0; i < PIC_IRT_FIRST_IRQ; i++)
irq_set_chip_and_handler(i, &nlm_cpu_intr, handle_percpu_irq);
for (i = PIC_IRT_FIRST_IRQ; i <= PIC_IRT_LAST_IRQ ; i++)
irq_set_chip_and_handler(i, &xlp_pic, handle_level_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);
nlm_irq_mask |=
((1ULL << IRQ_IPI_SMP_FUNCTION) | (1ULL << IRQ_IPI_SMP_RESCHEDULE));
#endif
}
void nlm_setup_pic_irq(int node, int picirq, int irq, int irt)
{
struct nlm_pic_irq *pic_data;
int xirq;
xirq = nlm_irq_to_xirq(node, irq);
pic_data = kzalloc(sizeof(*pic_data), GFP_KERNEL);
BUG_ON(pic_data == NULL);
pic_data->irt = irt;
pic_data->picirq = picirq;
pic_data->node = nlm_get_node(node);
irq_set_chip_and_handler(xirq, &xlp_pic, handle_level_irq);
irq_set_handler_data(xirq, pic_data);
}
void nlm_set_pic_extra_ack(int node, int irq, void (*xack)(struct irq_data *))
{
struct nlm_pic_irq *pic_data;
int xirq;
xirq = nlm_irq_to_xirq(node, irq);
pic_data = irq_get_handler_data(xirq);
pic_data->extra_ack = xack;
}
for (irq = PIC_IRT_FIRST_IRQ; irq <= PIC_IRT_LAST_IRQ; irq++) {
irt = nlm_irq_to_irt(irq);
static void nlm_init_node_irqs(int node)
{
int i, irt;
uint64_t irqmask;
struct nlm_soc_info *nodep;
pr_info("Init IRQ for node %d\n", node);
nodep = nlm_get_node(node);
irqmask = PERCPU_IRQ_MASK;
for (i = PIC_IRT_FIRST_IRQ; i <= PIC_IRT_LAST_IRQ; i++) {
irt = nlm_irq_to_irt(i);
if (irt == -1)
continue;
nlm_irq_mask |= (1ULL << irq);
nlm_pic_init_irt(nlm_pic_base, irt, irq, 0);
nlm_setup_pic_irq(node, i, i, irt);
/* set interrupts to first cpu in node */
nlm_pic_init_irt(nodep->picbase, irt, i,
node * NLM_CPUS_PER_NODE);
irqmask |= (1ull << i);
}
nlm_irq_mask |= (1ULL << IRQ_TIMER);
nodep->irqmask = irqmask;
}
void __init arch_init_irq(void)
{
/* Initialize the irq descriptors */
init_nlm_common_irqs();
write_c0_eimr(nlm_irq_mask);
nlm_init_percpu_irqs();
nlm_init_node_irqs(0);
write_c0_eimr(nlm_current_node()->irqmask);
#if defined(CONFIG_CPU_XLR)
nlm_setup_fmn_irq();
#endif
}
void __cpuinit nlm_smp_irq_init(void)
void nlm_smp_irq_init(int hwcpuid)
{
/* set interrupt mask for non-zero cpus */
write_c0_eimr(nlm_irq_mask);
int node, cpu;
node = hwcpuid / NLM_CPUS_PER_NODE;
cpu = hwcpuid % NLM_CPUS_PER_NODE;
if (cpu == 0 && node != 0)
nlm_init_node_irqs(node);
write_c0_eimr(nlm_current_node()->irqmask);
}
asmlinkage void plat_irq_dispatch(void)
{
uint64_t eirr;
int i;
int i, node;
node = nlm_nodeid();
eirr = read_c0_eirr() & read_c0_eimr();
if (eirr & (1 << IRQ_TIMER)) {
do_IRQ(IRQ_TIMER);
return;
}
i = __ilog2_u64(eirr);
if (i == -1)
return;
do_IRQ(i);
/* per-CPU IRQs don't need translation */
if (eirr & PERCPU_IRQ_MASK) {
do_IRQ(i);
return;
}
/* top level irq handling */
do_IRQ(nlm_irq_to_xirq(node, i));
}
......@@ -59,12 +59,17 @@
void nlm_send_ipi_single(int logical_cpu, unsigned int action)
{
int cpu = cpu_logical_map(logical_cpu);
int cpu, node;
uint64_t picbase;
cpu = cpu_logical_map(logical_cpu);
node = cpu / NLM_CPUS_PER_NODE;
picbase = nlm_get_node(node)->picbase;
if (action & SMP_CALL_FUNCTION)
nlm_pic_send_ipi(nlm_pic_base, cpu, IRQ_IPI_SMP_FUNCTION, 0);
nlm_pic_send_ipi(picbase, cpu, IRQ_IPI_SMP_FUNCTION, 0);
if (action & SMP_RESCHEDULE_YOURSELF)
nlm_pic_send_ipi(nlm_pic_base, cpu, IRQ_IPI_SMP_RESCHEDULE, 0);
nlm_pic_send_ipi(picbase, cpu, IRQ_IPI_SMP_RESCHEDULE, 0);
}
void nlm_send_ipi_mask(const struct cpumask *mask, unsigned int action)
......@@ -96,11 +101,12 @@ void nlm_smp_resched_ipi_handler(unsigned int irq, struct irq_desc *desc)
void nlm_early_init_secondary(int cpu)
{
change_c0_config(CONF_CM_CMASK, 0x3);
write_c0_ebase((uint32_t)nlm_common_ebase);
#ifdef CONFIG_CPU_XLP
if (hard_smp_processor_id() % 4 == 0)
/* mmu init, once per core */
if (cpu % NLM_THREADS_PER_CORE == 0)
xlp_mmu_init();
#endif
write_c0_ebase(nlm_current_node()->ebase);
}
/*
......@@ -108,8 +114,12 @@ void nlm_early_init_secondary(int cpu)
*/
static void __cpuinit nlm_init_secondary(void)
{
current_cpu_data.core = hard_smp_processor_id() / 4;
nlm_smp_irq_init();
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)
......@@ -120,9 +130,6 @@ void nlm_prepare_cpus(unsigned int max_cpus)
void nlm_smp_finish(void)
{
#ifdef notyet
nlm_common_msgring_cpu_init();
#endif
local_irq_enable();
}
......@@ -142,27 +149,27 @@ cpumask_t phys_cpu_present_map;
void nlm_boot_secondary(int logical_cpu, struct task_struct *idle)
{
unsigned long gp = (unsigned long)task_thread_info(idle);
unsigned long sp = (unsigned long)__KSTK_TOS(idle);
int cpu = cpu_logical_map(logical_cpu);
int cpu, node;
nlm_next_sp = sp;
nlm_next_gp = gp;
cpu = cpu_logical_map(logical_cpu);
node = cpu / NLM_CPUS_PER_NODE;
nlm_next_sp = (unsigned long)__KSTK_TOS(idle);
nlm_next_gp = (unsigned long)task_thread_info(idle);
/* barrier */
/* barrier for sp/gp store above */
__sync();
nlm_pic_send_ipi(nlm_pic_base, cpu, 1, 1);
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;
int num_cpus, i, ncore;
boot_cpu = hard_smp_processor_id();
cpus_clear(phys_cpu_present_map);
cpumask_clear(&phys_cpu_present_map);
cpu_set(boot_cpu, phys_cpu_present_map);
cpumask_set_cpu(boot_cpu, &phys_cpu_present_map);
__cpu_number_map[boot_cpu] = 0;
__cpu_logical_map[0] = boot_cpu;
set_cpu_possible(0, true);
......@@ -174,7 +181,7 @@ void __init nlm_smp_setup(void)
* it is only set for ASPs (see smpboot.S)
*/
if (nlm_cpu_ready[i]) {
cpu_set(i, phys_cpu_present_map);
cpumask_set_cpu(i, &phys_cpu_present_map);
__cpu_number_map[i] = num_cpus;
__cpu_logical_map[num_cpus] = i;
set_cpu_possible(num_cpus, true);
......@@ -182,20 +189,28 @@ void __init nlm_smp_setup(void)
}
}
/* check with the cores we have worken up */
for (ncore = 0, i = 0; i < NLM_NR_NODES; i++)
ncore += hweight32(nlm_get_node(i)->coremask);
pr_info("Phys CPU present map: %lx, possible map %lx\n",
(unsigned long)phys_cpu_present_map.bits[0],
(unsigned long)cpumask_bits(&phys_cpu_present_map)[0],
(unsigned long)cpumask_bits(cpu_possible_mask)[0]);
pr_info("Detected %i Slave CPU(s)\n", num_cpus);
pr_info("Detected (%dc%dt) %d Slave CPU(s)\n", ncore,
nlm_threads_per_core, num_cpus);
nlm_set_nmi_handler(nlm_boot_secondary_cpus);
}
static int nlm_parse_cpumask(u32 cpu_mask)
static int nlm_parse_cpumask(cpumask_t *wakeup_mask)
{
uint32_t core0_thr_mask, core_thr_mask;
int threadmode, i;
int threadmode, i, j;
core0_thr_mask = cpu_mask & 0xf;
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;
......@@ -214,25 +229,23 @@ static int nlm_parse_cpumask(u32 cpu_mask)
}
/* Verify other cores CPU masks */
nlm_coremask = 1;
nlm_cpumask = core0_thr_mask;
for (i = 1; i < 8; i++) {
core_thr_mask = (cpu_mask >> (i * 4)) & 0xf;
if (core_thr_mask) {
if (core_thr_mask != core0_thr_mask)
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;
nlm_coremask |= 1 << i;
nlm_cpumask |= core0_thr_mask << (4 * i);
}
}
return threadmode;
unsupp:
panic("Unsupported CPU mask %x\n", cpu_mask);
panic("Unsupported CPU mask %lx\n",
(unsigned long)cpumask_bits(wakeup_mask)[0]);
return 0;
}
int __cpuinit nlm_wakeup_secondary_cpus(u32 wakeup_mask)
int __cpuinit nlm_wakeup_secondary_cpus(void)
{
unsigned long reset_vec;
char *reset_data;
......@@ -244,7 +257,7 @@ int __cpuinit nlm_wakeup_secondary_cpus(u32 wakeup_mask)
(nlm_reset_entry_end - nlm_reset_entry));
/* verify the mask and setup core config variables */
threadmode = nlm_parse_cpumask(wakeup_mask);
threadmode = nlm_parse_cpumask(&nlm_cpumask);
/* Setup CPU init parameters */
reset_data = (char *)CKSEG1ADDR(RESET_DATA_PHYS);
......
......@@ -61,7 +61,7 @@
li t0, LSU_DEFEATURE
mfcr t1, t0
lui t2, 0x4080 /* Enable Unaligned Access, L2HPE */
lui t2, 0xc080 /* SUE, Enable Unaligned Access, L2HPE */
or t1, t1, t2
#ifdef XLP_AX_WORKAROUND
li t2, ~0xe /* S1RCM */
......@@ -186,7 +186,7 @@ EXPORT(nlm_boot_siblings)
* jump to the secondary wait function.
*/
mfc0 v0, CP0_EBASE, 1
andi v0, 0x7f /* v0 <- node/core */
andi v0, 0x3ff /* v0 <- node/core */
/* Init MMU in the first thread after changing THREAD_MODE
* register (Ax Errata?)
......@@ -263,6 +263,8 @@ NESTED(nlm_boot_secondary_cpus, 16, sp)
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
......
......@@ -40,23 +40,23 @@
#include <asm/mipsregs.h>
#include <asm/time.h>
#include <asm/netlogic/common.h>
#include <asm/netlogic/haldefs.h>
#include <asm/netlogic/xlp-hal/iomap.h>
#include <asm/netlogic/xlp-hal/xlp.h>
#include <asm/netlogic/xlp-hal/pic.h>
#include <asm/netlogic/xlp-hal/sys.h>
/* These addresses are computed by the nlm_hal_init() */
uint64_t nlm_io_base;
uint64_t nlm_sys_base;
uint64_t nlm_pic_base;
/* Main initialization */
void nlm_hal_init(void)
void nlm_node_init(int node)
{
nlm_io_base = CKSEG1ADDR(XLP_DEFAULT_IO_BASE);
nlm_sys_base = nlm_get_sys_regbase(0); /* node 0 */
nlm_pic_base = nlm_get_pic_regbase(0); /* node 0 */
struct nlm_soc_info *nodep;
nodep = nlm_get_node(node);
nodep->sysbase = nlm_get_sys_regbase(node);
nodep->picbase = nlm_get_pic_regbase(node);
nodep->ebase = read_c0_ebase() & (~((1 << 12) - 1));
spin_lock_init(&nodep->piclock);
}
int nlm_irq_to_irt(int irq)
......@@ -100,52 +100,15 @@ int nlm_irq_to_irt(int irq)
}
}
int nlm_irt_to_irq(int irt)
{
switch (irt) {
case PIC_IRT_UART_0_INDEX:
return PIC_UART_0_IRQ;
case PIC_IRT_UART_1_INDEX:
return PIC_UART_1_IRQ;
case PIC_IRT_PCIE_LINK_0_INDEX:
return PIC_PCIE_LINK_0_IRQ;
case PIC_IRT_PCIE_LINK_1_INDEX:
return PIC_PCIE_LINK_1_IRQ;
case PIC_IRT_PCIE_LINK_2_INDEX:
return PIC_PCIE_LINK_2_IRQ;
case PIC_IRT_PCIE_LINK_3_INDEX:
return PIC_PCIE_LINK_3_IRQ;
case PIC_IRT_EHCI_0_INDEX:
return PIC_EHCI_0_IRQ;
case PIC_IRT_EHCI_1_INDEX:
return PIC_EHCI_1_IRQ;
case PIC_IRT_OHCI_0_INDEX:
return PIC_OHCI_0_IRQ;
case PIC_IRT_OHCI_1_INDEX:
return PIC_OHCI_1_IRQ;
case PIC_IRT_OHCI_2_INDEX:
return PIC_OHCI_2_IRQ;
case PIC_IRT_OHCI_3_INDEX:
return PIC_OHCI_3_IRQ;
case PIC_IRT_MMC_INDEX:
return PIC_MMC_IRQ;
case PIC_IRT_I2C_0_INDEX:
return PIC_I2C_0_IRQ;
case PIC_IRT_I2C_1_INDEX:
return PIC_I2C_1_IRQ;
default:
return -1;
}
}
unsigned int nlm_get_core_frequency(int core)
unsigned int nlm_get_core_frequency(int node, int core)
{
unsigned int pll_divf, pll_divr, dfs_div, ext_div;
unsigned int rstval, dfsval, denom;
uint64_t num;
uint64_t num, sysbase;
rstval = nlm_read_sys_reg(nlm_sys_base, SYS_POWER_ON_RESET_CFG);
dfsval = nlm_read_sys_reg(nlm_sys_base, SYS_CORE_DFS_DIV_VALUE);
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;
......@@ -159,5 +122,5 @@ unsigned int nlm_get_core_frequency(int core)
unsigned int nlm_get_cpu_frequency(void)
{
return nlm_get_core_frequency(0);
return nlm_get_core_frequency(0, 0);
}
......@@ -52,26 +52,40 @@
#include <asm/netlogic/xlp-hal/xlp.h>
#include <asm/netlogic/xlp-hal/sys.h>
unsigned long nlm_common_ebase = 0x0;
/* default to uniprocessor */
uint32_t nlm_coremask = 1, nlm_cpumask = 1;
int nlm_threads_per_core = 1;
uint64_t nlm_io_base;
struct nlm_soc_info nlm_nodes[NLM_NR_NODES];
cpumask_t nlm_cpumask = CPU_MASK_CPU0;
unsigned int nlm_threads_per_core;
extern u32 __dtb_start[];
static void nlm_linux_exit(void)
{
nlm_write_sys_reg(nlm_sys_base, SYS_CHIP_RESET, 1);
uint64_t sysbase = nlm_get_node(0)->sysbase;
nlm_write_sys_reg(sysbase, SYS_CHIP_RESET, 1);
for ( ; ; )
cpu_wait();
}
void __init plat_mem_setup(void)
{
void *fdtp;
panic_timeout = 5;
_machine_restart = (void (*)(char *))nlm_linux_exit;
_machine_halt = nlm_linux_exit;
pm_power_off = nlm_linux_exit;
/*
* If no FDT pointer is passed in, use the built-in FDT.
* device_tree_init() does not handle CKSEG0 pointers in
* 64-bit, so convert pointer.
*/
fdtp = (void *)(long)fw_arg0;
if (!fdtp)
fdtp = __dtb_start;
fdtp = phys_to_virt(__pa(fdtp));
early_init_devtree(fdtp);
}
const char *get_system_type(void)
......@@ -94,27 +108,19 @@ void xlp_mmu_init(void)
(13 + (ffz(PM_DEFAULT_MASK >> 13) / 2)));
}
void __init prom_init(void)
void nlm_percpu_init(int hwcpuid)
{
void *fdtp;
}
void __init prom_init(void)
{
nlm_io_base = CKSEG1ADDR(XLP_DEFAULT_IO_BASE);
xlp_mmu_init();
nlm_hal_init();
/*
* If no FDT pointer is passed in, use the built-in FDT.
* device_tree_init() does not handle CKSEG0 pointers in
* 64-bit, so convert pointer.
*/
fdtp = (void *)(long)fw_arg0;
if (!fdtp)
fdtp = __dtb_start;
fdtp = phys_to_virt(__pa(fdtp));
early_init_devtree(fdtp);
nlm_node_init(0);
nlm_common_ebase = read_c0_ebase() & (~((1 << 12) - 1));
#ifdef CONFIG_SMP
nlm_wakeup_secondary_cpus(0xffffffff);
cpumask_setall(&nlm_cpumask);
nlm_wakeup_secondary_cpus();
/* update TLB size after waking up threads */
current_cpu_data.tlbsize = ((read_c0_config6() >> 16) & 0xffff) + 1;
......
......@@ -51,45 +51,72 @@
#include <asm/netlogic/xlp-hal/xlp.h>
#include <asm/netlogic/xlp-hal/sys.h>
static void xlp_enable_secondary_cores(void)
static int xlp_wakeup_core(uint64_t sysbase, int core)
{
uint32_t core, value, coremask, syscoremask;
uint32_t coremask, value;
int count;
/* read cores in reset from SYS block */
syscoremask = nlm_read_sys_reg(nlm_sys_base, SYS_CPU_RESET);
coremask = (1 << core);
/* update user specified */
nlm_coremask = nlm_coremask & (syscoremask | 1);
/* Enable CPU clock */
value = nlm_read_sys_reg(sysbase, SYS_CORE_DFS_DIS_CTRL);
value &= ~coremask;
nlm_write_sys_reg(sysbase, SYS_CORE_DFS_DIS_CTRL, value);
for (core = 1; core < 8; core++) {
coremask = 1 << core;
if ((nlm_coremask & coremask) == 0)
continue;
/* Remove CPU Reset */
value = nlm_read_sys_reg(sysbase, SYS_CPU_RESET);
value &= ~coremask;
nlm_write_sys_reg(sysbase, SYS_CPU_RESET, value);
/* Enable CPU clock */
value = nlm_read_sys_reg(nlm_sys_base, SYS_CORE_DFS_DIS_CTRL);
value &= ~coremask;
nlm_write_sys_reg(nlm_sys_base, SYS_CORE_DFS_DIS_CTRL, value);
/* Poll for CPU to mark itself coherent */
count = 100000;
do {
value = nlm_read_sys_reg(sysbase, SYS_CPU_NONCOHERENT_MODE);
} while ((value & coremask) != 0 && --count > 0);
/* Remove CPU Reset */
value = nlm_read_sys_reg(nlm_sys_base, SYS_CPU_RESET);
value &= ~coremask;
nlm_write_sys_reg(nlm_sys_base, SYS_CPU_RESET, value);
return count != 0;
}
static void xlp_enable_secondary_cores(const cpumask_t *wakeup_mask)
{
struct nlm_soc_info *nodep;
uint64_t syspcibase;
uint32_t syscoremask;
int core, n, cpu;
for (n = 0; n < NLM_NR_NODES; n++) {
syspcibase = nlm_get_sys_pcibase(n);
if (nlm_read_reg(syspcibase, 0) == 0xffffffff)
break;
/* read cores in reset from SYS and account for boot cpu */
nlm_node_init(n);
nodep = nlm_get_node(n);
syscoremask = nlm_read_sys_reg(nodep->sysbase, SYS_CPU_RESET);
if (n == 0)
syscoremask |= 1;
for (core = 0; core < NLM_CORES_PER_NODE; core++) {
/* see if the core exists */
if ((syscoremask & (1 << core)) == 0)
continue;
/* Poll for CPU to mark itself coherent */
count = 100000;
do {
value = nlm_read_sys_reg(nlm_sys_base,
SYS_CPU_NONCOHERENT_MODE);
} while ((value & coremask) != 0 && count-- > 0);
/* see if at least the first thread is enabled */
cpu = (n * NLM_CORES_PER_NODE + core)
* NLM_THREADS_PER_CORE;
if (!cpumask_test_cpu(cpu, wakeup_mask))
continue;
if (count == 0)
pr_err("Failed to enable core %d\n", core);
/* wake up the core */
if (xlp_wakeup_core(nodep->sysbase, core))
nodep->coremask |= 1u << core;
else
pr_err("Failed to enable core %d\n", core);
}
}
}
void xlp_wakeup_secondary_cpus(void)
void xlp_wakeup_secondary_cpus()
{
/*
* In case of u-boot, the secondaries are in reset
......@@ -98,5 +125,5 @@ void xlp_wakeup_secondary_cpus(void)
xlp_boot_core0_siblings();
/* now get other cores out of reset */
xlp_enable_secondary_cores();
xlp_enable_secondary_cores(&nlm_cpumask);
}
obj-y += setup.o platform.o platform-flash.o
obj-$(CONFIG_SMP) += wakeup.o
obj-y += fmn.o fmn-config.o setup.o platform.o platform-flash.o
obj-$(CONFIG_SMP) += wakeup.o
/*
* Copyright (c) 2003-2012 Broadcom Corporation
* All Rights Reserved
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
* General Public License (GPL) Version 2, available from the file
* COPYING in the main directory of this source tree, or the Broadcom
* license below:
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY BROADCOM ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL BROADCOM OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <asm/cpu-info.h>
#include <linux/irq.h>
#include <linux/interrupt.h>
#include <asm/mipsregs.h>
#include <asm/netlogic/xlr/fmn.h>
#include <asm/netlogic/xlr/xlr.h>
#include <asm/netlogic/common.h>
#include <asm/netlogic/haldefs.h>
struct xlr_board_fmn_config xlr_board_fmn_config;
static void __maybe_unused print_credit_config(struct xlr_fmn_info *fmn_info)
{
int bkt;
pr_info("Bucket size :\n");
pr_info("Station\t: Size\n");
for (bkt = 0; bkt < 16; bkt++)
pr_info(" %d %d %d %d %d %d %d %d\n",
xlr_board_fmn_config.bucket_size[(bkt * 8) + 0],
xlr_board_fmn_config.bucket_size[(bkt * 8) + 1],
xlr_board_fmn_config.bucket_size[(bkt * 8) + 2],
xlr_board_fmn_config.bucket_size[(bkt * 8) + 3],
xlr_board_fmn_config.bucket_size[(bkt * 8) + 4],
xlr_board_fmn_config.bucket_size[(bkt * 8) + 5],
xlr_board_fmn_config.bucket_size[(bkt * 8) + 6],
xlr_board_fmn_config.bucket_size[(bkt * 8) + 7]);
pr_info("\n");
pr_info("Credits distribution :\n");
pr_info("Station\t: Size\n");
for (bkt = 0; bkt < 16; bkt++)
pr_info(" %d %d %d %d %d %d %d %d\n",
fmn_info->credit_config[(bkt * 8) + 0],
fmn_info->credit_config[(bkt * 8) + 1],
fmn_info->credit_config[(bkt * 8) + 2],
fmn_info->credit_config[(bkt * 8) + 3],
fmn_info->credit_config[(bkt * 8) + 4],
fmn_info->credit_config[(bkt * 8) + 5],
fmn_info->credit_config[(bkt * 8) + 6],
fmn_info->credit_config[(bkt * 8) + 7]);
pr_info("\n");
}
static void check_credit_distribution(void)
{
struct xlr_board_fmn_config *cfg = &xlr_board_fmn_config;
int bkt, n, total_credits, ncores;
ncores = hweight32(nlm_current_node()->coremask);
for (bkt = 0; bkt < 128; bkt++) {
total_credits = 0;
for (n = 0; n < ncores; n++)
total_credits += cfg->cpu[n].credit_config[bkt];
total_credits += cfg->gmac[0].credit_config[bkt];
total_credits += cfg->gmac[1].credit_config[bkt];
total_credits += cfg->dma.credit_config[bkt];
total_credits += cfg->cmp.credit_config[bkt];
total_credits += cfg->sae.credit_config[bkt];
total_credits += cfg->xgmac[0].credit_config[bkt];
total_credits += cfg->xgmac[1].credit_config[bkt];
if (total_credits > cfg->bucket_size[bkt])
pr_err("ERROR: Bucket %d: credits (%d) > size (%d)\n",
bkt, total_credits, cfg->bucket_size[bkt]);
}
pr_info("Credit distribution complete.\n");
}
/**
* Configure bucket size and credits for a device. 'size' is the size of
* the buckets for the device. This size is distributed among all the CPUs
* so that all of them can send messages to the device.
*
* The device is also given 'cpu_credits' to send messages to the CPUs
*
* @dev_info: FMN information structure for each devices
* @start_stn_id: Starting station id of dev_info
* @end_stn_id: End station id of dev_info
* @num_buckets: Total number of buckets for den_info
* @cpu_credits: Allowed credits to cpu for each devices pointing by dev_info
* @size: Size of the each buckets in the device station
*/
static void setup_fmn_cc(struct xlr_fmn_info *dev_info, int start_stn_id,
int end_stn_id, int num_buckets, int cpu_credits, int size)
{
int i, j, num_core, n, credits_per_cpu;
struct xlr_fmn_info *cpu = xlr_board_fmn_config.cpu;
num_core = hweight32(nlm_current_node()->coremask);
dev_info->num_buckets = num_buckets;
dev_info->start_stn_id = start_stn_id;
dev_info->end_stn_id = end_stn_id;
n = num_core;
if (num_core == 3)
n = 4;
for (i = start_stn_id; i <= end_stn_id; i++) {
xlr_board_fmn_config.bucket_size[i] = size;
/* Dividing device credits equally to cpus */
credits_per_cpu = size / n;
for (j = 0; j < num_core; j++)
cpu[j].credit_config[i] = credits_per_cpu;
/* credits left to distribute */
credits_per_cpu = size - (credits_per_cpu * num_core);
/* distribute the remaining credits (if any), among cores */
for (j = 0; (j < num_core) && (credits_per_cpu >= 4); j++) {
cpu[j].credit_config[i] += 4;
credits_per_cpu -= 4;
}
}
/* Distributing cpu per bucket credits to devices */
for (i = 0; i < num_core; i++) {
for (j = 0; j < FMN_CORE_NBUCKETS; j++)
dev_info->credit_config[(i * 8) + j] = cpu_credits;
}
}
/*
* Each core has 256 slots and 8 buckets,
* Configure the 8 buckets each with 32 slots
*/
static void setup_cpu_fmninfo(struct xlr_fmn_info *cpu, int num_core)
{
int i, j;
for (i = 0; i < num_core; i++) {
cpu[i].start_stn_id = (8 * i);
cpu[i].end_stn_id = (8 * i + 8);
for (j = cpu[i].start_stn_id; j < cpu[i].end_stn_id; j++)
xlr_board_fmn_config.bucket_size[j] = 32;
}
}
/**
* Setup the FMN details for each devices according to the device available
* in each variant of XLR/XLS processor
*/
void xlr_board_info_setup(void)
{
struct xlr_fmn_info *cpu = xlr_board_fmn_config.cpu;
struct xlr_fmn_info *gmac = xlr_board_fmn_config.gmac;
struct xlr_fmn_info *xgmac = xlr_board_fmn_config.xgmac;
struct xlr_fmn_info *dma = &xlr_board_fmn_config.dma;
struct xlr_fmn_info *cmp = &xlr_board_fmn_config.cmp;
struct xlr_fmn_info *sae = &xlr_board_fmn_config.sae;
int processor_id, num_core;
num_core = hweight32(nlm_current_node()->coremask);
processor_id = read_c0_prid() & 0xff00;
setup_cpu_fmninfo(cpu, num_core);
switch (processor_id) {
case PRID_IMP_NETLOGIC_XLS104:
case PRID_IMP_NETLOGIC_XLS108:
setup_fmn_cc(&gmac[0], FMN_STNID_GMAC0,
FMN_STNID_GMAC0_TX3, 8, 16, 32);
setup_fmn_cc(dma, FMN_STNID_DMA_0,
FMN_STNID_DMA_3, 4, 8, 64);
setup_fmn_cc(sae, FMN_STNID_SEC0,
FMN_STNID_SEC1, 2, 8, 128);
break;
case PRID_IMP_NETLOGIC_XLS204:
case PRID_IMP_NETLOGIC_XLS208:
setup_fmn_cc(&gmac[0], FMN_STNID_GMAC0,
FMN_STNID_GMAC0_TX3, 8, 16, 32);
setup_fmn_cc(dma, FMN_STNID_DMA_0,
FMN_STNID_DMA_3, 4, 8, 64);
setup_fmn_cc(sae, FMN_STNID_SEC0,
FMN_STNID_SEC1, 2, 8, 128);
break;
case PRID_IMP_NETLOGIC_XLS404:
case PRID_IMP_NETLOGIC_XLS408:
case PRID_IMP_NETLOGIC_XLS404B:
case PRID_IMP_NETLOGIC_XLS408B:
case PRID_IMP_NETLOGIC_XLS416B:
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
}
/*
* Copyright (c) 2003-2012 Broadcom Corporation
* All Rights Reserved
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
* General Public License (GPL) Version 2, available from the file
* COPYING in the main directory of this source tree, or the Broadcom
* license below:
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY BROADCOM ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL BROADCOM OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <linux/kernel.h>
#include <linux/irqreturn.h>
#include <linux/irq.h>
#include <linux/interrupt.h>
#include <asm/mipsregs.h>
#include <asm/netlogic/interrupt.h>
#include <asm/netlogic/xlr/fmn.h>
#include <asm/netlogic/common.h>
#define COP2_CC_INIT_CPU_DEST(dest, conf) \
do { \
nlm_write_c2_cc##dest(0, conf[(dest * 8) + 0]); \
nlm_write_c2_cc##dest(1, conf[(dest * 8) + 1]); \
nlm_write_c2_cc##dest(2, conf[(dest * 8) + 2]); \
nlm_write_c2_cc##dest(3, conf[(dest * 8) + 3]); \
nlm_write_c2_cc##dest(4, conf[(dest * 8) + 4]); \
nlm_write_c2_cc##dest(5, conf[(dest * 8) + 5]); \
nlm_write_c2_cc##dest(6, conf[(dest * 8) + 6]); \
nlm_write_c2_cc##dest(7, conf[(dest * 8) + 7]); \
} while (0)
struct fmn_message_handler {
void (*action)(int, int, int, int, struct nlm_fmn_msg *, void *);
void *arg;
} msg_handlers[128];
/*
* FMN interrupt handler. We configure the FMN so that any messages in
* any of the CPU buckets will trigger an interrupt on the CPU.
* The message can be from any device on the FMN (like NAE/SAE/DMA).
* The source station id is used to figure out which of the registered
* handlers have to be called.
*/
static irqreturn_t fmn_message_handler(int irq, void *data)
{
struct fmn_message_handler *hndlr;
int bucket, rv;
int size = 0, code = 0, src_stnid = 0;
struct nlm_fmn_msg msg;
uint32_t mflags, bkt_status;
mflags = nlm_cop2_enable();
/* Disable message ring interrupt */
nlm_fmn_setup_intr(irq, 0);
while (1) {
/* 8 bkts per core, [24:31] each bit represents one bucket
* Bit is Zero if bucket is not empty */
bkt_status = (nlm_read_c2_status() >> 24) & 0xff;
if (bkt_status == 0xff)
break;
for (bucket = 0; bucket < 8; bucket++) {
/* Continue on empty bucket */
if (bkt_status & (1 << bucket))
continue;
rv = nlm_fmn_receive(bucket, &size, &code, &src_stnid,
&msg);
if (rv != 0)
continue;
hndlr = &msg_handlers[src_stnid];
if (hndlr->action == NULL)
pr_warn("No msgring handler for stnid %d\n",
src_stnid);
else {
nlm_cop2_restore(mflags);
hndlr->action(bucket, src_stnid, size, code,
&msg, hndlr->arg);
mflags = nlm_cop2_enable();
}
}
};
/* Enable message ring intr, to any thread in core */
nlm_fmn_setup_intr(irq, (1 << nlm_threads_per_core) - 1);
nlm_cop2_restore(mflags);
return IRQ_HANDLED;
}
struct irqaction fmn_irqaction = {
.handler = fmn_message_handler,
.flags = IRQF_PERCPU,
.name = "fmn",
};
void xlr_percpu_fmn_init(void)
{
struct xlr_fmn_info *cpu_fmn_info;
int *bucket_sizes;
uint32_t flags;
int id;
BUG_ON(nlm_thread_id() != 0);
id = nlm_core_id();
bucket_sizes = xlr_board_fmn_config.bucket_size;
cpu_fmn_info = &xlr_board_fmn_config.cpu[id];
flags = nlm_cop2_enable();
/* Setup bucket sizes for the core. */
nlm_write_c2_bucksize(0, bucket_sizes[id * 8 + 0]);
nlm_write_c2_bucksize(1, bucket_sizes[id * 8 + 1]);
nlm_write_c2_bucksize(2, bucket_sizes[id * 8 + 2]);
nlm_write_c2_bucksize(3, bucket_sizes[id * 8 + 3]);
nlm_write_c2_bucksize(4, bucket_sizes[id * 8 + 4]);
nlm_write_c2_bucksize(5, bucket_sizes[id * 8 + 5]);
nlm_write_c2_bucksize(6, bucket_sizes[id * 8 + 6]);
nlm_write_c2_bucksize(7, bucket_sizes[id * 8 + 7]);
/*
* For sending FMN messages, we need credits on the destination
* bucket. Program the credits this core has on the 128 possible
* destination buckets.
* We cannot use a loop here, because the the first argument has
* to be a constant integer value.
*/
COP2_CC_INIT_CPU_DEST(0, cpu_fmn_info->credit_config);
COP2_CC_INIT_CPU_DEST(1, cpu_fmn_info->credit_config);
COP2_CC_INIT_CPU_DEST(2, cpu_fmn_info->credit_config);
COP2_CC_INIT_CPU_DEST(3, cpu_fmn_info->credit_config);
COP2_CC_INIT_CPU_DEST(4, cpu_fmn_info->credit_config);
COP2_CC_INIT_CPU_DEST(5, cpu_fmn_info->credit_config);
COP2_CC_INIT_CPU_DEST(6, cpu_fmn_info->credit_config);
COP2_CC_INIT_CPU_DEST(7, cpu_fmn_info->credit_config);
COP2_CC_INIT_CPU_DEST(8, cpu_fmn_info->credit_config);
COP2_CC_INIT_CPU_DEST(9, cpu_fmn_info->credit_config);
COP2_CC_INIT_CPU_DEST(10, cpu_fmn_info->credit_config);
COP2_CC_INIT_CPU_DEST(11, cpu_fmn_info->credit_config);
COP2_CC_INIT_CPU_DEST(12, cpu_fmn_info->credit_config);
COP2_CC_INIT_CPU_DEST(13, cpu_fmn_info->credit_config);
COP2_CC_INIT_CPU_DEST(14, cpu_fmn_info->credit_config);
COP2_CC_INIT_CPU_DEST(15, cpu_fmn_info->credit_config);
/* enable FMN interrupts on this CPU */
nlm_fmn_setup_intr(IRQ_FMN, (1 << nlm_threads_per_core) - 1);
nlm_cop2_restore(flags);
}
/*
* Register a FMN message handler with respect to the source station id
* @stnid: source station id
* @action: Handler function pointer
*/
int nlm_register_fmn_handler(int start_stnid, int end_stnid,
void (*action)(int, int, int, int, struct nlm_fmn_msg *, void *),
void *arg)
{
int sstnid;
for (sstnid = start_stnid; sstnid <= end_stnid; sstnid++) {
msg_handlers[sstnid].arg = arg;
smp_wmb();
msg_handlers[sstnid].action = action;
}
pr_debug("Registered FMN msg handler for stnid %d-%d\n",
start_stnid, end_stnid);
return 0;
}
void nlm_setup_fmn_irq(void)
{
uint32_t flags;
/* setup irq only once */
setup_irq(IRQ_FMN, &fmn_irqaction);
flags = nlm_cop2_enable();
nlm_fmn_setup_intr(IRQ_FMN, (1 << nlm_threads_per_core) - 1);
nlm_cop2_restore(flags);
}
This diff is collapsed.
This diff is collapsed.
......@@ -12,4 +12,5 @@ oprofile-$(CONFIG_CPU_MIPS32) += op_model_mipsxx.o
oprofile-$(CONFIG_CPU_MIPS64) += op_model_mipsxx.o
oprofile-$(CONFIG_CPU_R10000) += op_model_mipsxx.o
oprofile-$(CONFIG_CPU_SB1) += op_model_mipsxx.o
oprofile-$(CONFIG_CPU_XLR) += op_model_mipsxx.o
oprofile-$(CONFIG_CPU_LOONGSON2) += op_model_loongson2.o
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment