aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2012-12-13 13:40:13 -0500
committerRalf Baechle <ralf@linux-mips.org>2012-12-13 13:40:13 -0500
commit241738bd51cb0efe58e6c570223153e970afe3ae (patch)
tree05263e1ec3fbd58cc4ba5ee69163612fbb769a4a
parentbdf20507da11a9a5b32ef04fa09f352828189aef (diff)
parentce8f0d0607bcad3ec0e8599be80353204427093e (diff)
Merge branch 'mips-next' of http://dev.phrozen.org/githttp/mips-next into mips-for-linux-next
-rw-r--r--arch/mips/Kconfig11
-rw-r--r--arch/mips/bcm47xx/Kconfig2
-rw-r--r--arch/mips/bcm47xx/Makefile2
-rw-r--r--arch/mips/bcm47xx/gpio.c102
-rw-r--r--arch/mips/bcm47xx/prom.c20
-rw-r--r--arch/mips/bcm47xx/setup.c11
-rw-r--r--arch/mips/bcm47xx/sprom.c780
-rw-r--r--arch/mips/bcm47xx/wgt634u.c8
-rw-r--r--arch/mips/bcm63xx/Makefile7
-rw-r--r--arch/mips/bcm63xx/boards/board_bcm963xx.c71
-rw-r--r--arch/mips/bcm63xx/clk.c34
-rw-r--r--arch/mips/bcm63xx/nvram.c107
-rw-r--r--arch/mips/bcm63xx/reset.c223
-rw-r--r--arch/mips/cavium-octeon/flash_setup.c3
-rw-r--r--arch/mips/configs/ath79_defconfig111
-rw-r--r--arch/mips/include/asm/mach-bcm47xx/bcm47xx.h4
-rw-r--r--arch/mips/include/asm/mach-bcm47xx/gpio.h154
-rw-r--r--arch/mips/include/asm/mach-bcm63xx/bcm63xx_nvram.h35
-rw-r--r--arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h29
-rw-r--r--arch/mips/include/asm/mach-bcm63xx/bcm63xx_reset.h21
-rw-r--r--arch/mips/include/asm/mach-bcm63xx/board_bcm963xx.h17
-rw-r--r--arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h3
-rw-r--r--arch/mips/include/asm/mach-loongson1/platform.h3
-rw-r--r--arch/mips/include/asm/mach-loongson1/regs-clk.h7
-rw-r--r--arch/mips/include/asm/mach-netlogic/irq.h4
-rw-r--r--arch/mips/include/asm/mach-netlogic/multi-node.h54
-rw-r--r--arch/mips/include/asm/netlogic/common.h51
-rw-r--r--arch/mips/include/asm/netlogic/interrupt.h2
-rw-r--r--arch/mips/include/asm/netlogic/mips-extns.h142
-rw-r--r--arch/mips/include/asm/netlogic/xlp-hal/pic.h44
-rw-r--r--arch/mips/include/asm/netlogic/xlp-hal/sys.h1
-rw-r--r--arch/mips/include/asm/netlogic/xlr/fmn.h363
-rw-r--r--arch/mips/include/asm/netlogic/xlr/pic.h2
-rw-r--r--arch/mips/include/asm/netlogic/xlr/xlr.h6
-rw-r--r--arch/mips/kernel/perf_event_mipsxx.c124
-rw-r--r--arch/mips/lantiq/Kconfig4
-rw-r--r--arch/mips/lantiq/prom.c5
-rw-r--r--arch/mips/lantiq/xway/Makefile2
-rw-r--r--arch/mips/lantiq/xway/dma.c9
-rw-r--r--arch/mips/lantiq/xway/reset.c58
-rw-r--r--arch/mips/lantiq/xway/sysctrl.c4
-rw-r--r--arch/mips/lantiq/xway/xrx200_phy_fw.c97
-rw-r--r--arch/mips/loongson1/Kconfig2
-rw-r--r--arch/mips/loongson1/common/clock.c159
-rw-r--r--arch/mips/loongson1/common/platform.c10
-rw-r--r--arch/mips/loongson1/ls1b/board.c5
-rw-r--r--arch/mips/mm/c-r4k.c8
-rw-r--r--arch/mips/mm/tlbex.c8
-rw-r--r--arch/mips/netlogic/Kconfig28
-rw-r--r--arch/mips/netlogic/common/irq.c165
-rw-r--r--arch/mips/netlogic/common/smp.c89
-rw-r--r--arch/mips/netlogic/common/smpboot.S6
-rw-r--r--arch/mips/netlogic/xlp/nlm_hal.c67
-rw-r--r--arch/mips/netlogic/xlp/setup.c50
-rw-r--r--arch/mips/netlogic/xlp/wakeup.c83
-rw-r--r--arch/mips/netlogic/xlr/Makefile4
-rw-r--r--arch/mips/netlogic/xlr/fmn-config.c290
-rw-r--r--arch/mips/netlogic/xlr/fmn.c204
-rw-r--r--arch/mips/netlogic/xlr/setup.c37
-rw-r--r--arch/mips/netlogic/xlr/wakeup.c23
-rw-r--r--arch/mips/oprofile/Makefile1
-rw-r--r--arch/mips/oprofile/common.c1
-rw-r--r--arch/mips/oprofile/op_model_mipsxx.c29
-rw-r--r--arch/mips/pci/pci-bcm63xx.c34
-rw-r--r--arch/mips/pci/pci-xlr.c69
-rw-r--r--drivers/bcma/Kconfig9
-rw-r--r--drivers/bcma/Makefile1
-rw-r--r--drivers/bcma/bcma_private.h10
-rw-r--r--drivers/bcma/driver_chipcommon.c81
-rw-r--r--drivers/bcma/driver_gpio.c98
-rw-r--r--drivers/bcma/main.c5
-rw-r--r--drivers/ssb/Kconfig9
-rw-r--r--drivers/ssb/Makefile1
-rw-r--r--drivers/ssb/driver_chipcommon.c78
-rw-r--r--drivers/ssb/driver_extif.c43
-rw-r--r--drivers/ssb/driver_gpio.c176
-rw-r--r--drivers/ssb/main.c7
-rw-r--r--drivers/ssb/ssb_private.h17
-rw-r--r--include/linux/bcma/bcma_driver_chipcommon.h10
-rw-r--r--include/linux/ssb/ssb.h4
-rw-r--r--include/linux/ssb/ssb_driver_chipcommon.h3
-rw-r--r--include/linux/ssb/ssb_driver_extif.h1
82 files changed, 3436 insertions, 1226 deletions
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 9806a5ae50b..b7dc39c6c84 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -106,6 +106,7 @@ config ATH79
106 106
107config BCM47XX 107config BCM47XX
108 bool "Broadcom BCM47XX based boards" 108 bool "Broadcom BCM47XX based boards"
109 select ARCH_WANT_OPTIONAL_GPIOLIB
109 select CEVT_R4K 110 select CEVT_R4K
110 select CSRC_R4K 111 select CSRC_R4K
111 select DMA_NONCOHERENT 112 select DMA_NONCOHERENT
@@ -114,7 +115,6 @@ config BCM47XX
114 select IRQ_CPU 115 select IRQ_CPU
115 select SYS_SUPPORTS_32BIT_KERNEL 116 select SYS_SUPPORTS_32BIT_KERNEL
116 select SYS_SUPPORTS_LITTLE_ENDIAN 117 select SYS_SUPPORTS_LITTLE_ENDIAN
117 select GENERIC_GPIO
118 select SYS_HAS_EARLY_PRINTK 118 select SYS_HAS_EARLY_PRINTK
119 help 119 help
120 Support for BCM47XX based boards 120 Support for BCM47XX based boards
@@ -798,7 +798,7 @@ config NLM_XLR_BOARD
798 select CSRC_R4K 798 select CSRC_R4K
799 select IRQ_CPU 799 select IRQ_CPU
800 select ARCH_SUPPORTS_MSI 800 select ARCH_SUPPORTS_MSI
801 select ZONE_DMA if 64BIT 801 select ZONE_DMA32 if 64BIT
802 select SYNC_R4K 802 select SYNC_R4K
803 select SYS_HAS_EARLY_PRINTK 803 select SYS_HAS_EARLY_PRINTK
804 select USB_ARCH_HAS_OHCI if USB_SUPPORT 804 select USB_ARCH_HAS_OHCI if USB_SUPPORT
@@ -826,7 +826,7 @@ config NLM_XLP_BOARD
826 select CEVT_R4K 826 select CEVT_R4K
827 select CSRC_R4K 827 select CSRC_R4K
828 select IRQ_CPU 828 select IRQ_CPU
829 select ZONE_DMA if 64BIT 829 select ZONE_DMA32 if 64BIT
830 select SYNC_R4K 830 select SYNC_R4K
831 select SYS_HAS_EARLY_PRINTK 831 select SYS_HAS_EARLY_PRINTK
832 select USE_OF 832 select USE_OF
@@ -1507,6 +1507,7 @@ config CPU_XLP
1507 select WEAK_ORDERING 1507 select WEAK_ORDERING
1508 select WEAK_REORDERING_BEYOND_LLSC 1508 select WEAK_REORDERING_BEYOND_LLSC
1509 select CPU_HAS_PREFETCH 1509 select CPU_HAS_PREFETCH
1510 select CPU_MIPSR2
1510 help 1511 help
1511 Netlogic Microsystems XLP processors. 1512 Netlogic Microsystems XLP processors.
1512endchoice 1513endchoice
@@ -1718,7 +1719,7 @@ config CPU_SUPPORTS_UNCACHED_ACCELERATED
1718 bool 1719 bool
1719config MIPS_PGD_C0_CONTEXT 1720config MIPS_PGD_C0_CONTEXT
1720 bool 1721 bool
1721 default y if 64BIT && CPU_MIPSR2 1722 default y if 64BIT && CPU_MIPSR2 && !CPU_XLP
1722 1723
1723# 1724#
1724# Set to y for ptrace access to watch registers. 1725# Set to y for ptrace access to watch registers.
@@ -2149,7 +2150,7 @@ config NODES_SHIFT
2149 2150
2150config HW_PERF_EVENTS 2151config HW_PERF_EVENTS
2151 bool "Enable hardware performance counter support for perf events" 2152 bool "Enable hardware performance counter support for perf events"
2152 depends on PERF_EVENTS && !MIPS_MT_SMTC && OPROFILE=n && (CPU_MIPS32 || CPU_MIPS64 || CPU_R10000 || CPU_SB1 || CPU_CAVIUM_OCTEON) 2153 depends on PERF_EVENTS && !MIPS_MT_SMTC && OPROFILE=n && (CPU_MIPS32 || CPU_MIPS64 || CPU_R10000 || CPU_SB1 || CPU_CAVIUM_OCTEON || CPU_XLP)
2153 default y 2154 default y
2154 help 2155 help
2155 Enable hardware performance counter support for perf events. If 2156 Enable hardware performance counter support for perf events. If
diff --git a/arch/mips/bcm47xx/Kconfig b/arch/mips/bcm47xx/Kconfig
index b311be45a72..d7af29f1fcf 100644
--- a/arch/mips/bcm47xx/Kconfig
+++ b/arch/mips/bcm47xx/Kconfig
@@ -9,6 +9,7 @@ config BCM47XX_SSB
9 select SSB_EMBEDDED 9 select SSB_EMBEDDED
10 select SSB_B43_PCI_BRIDGE if PCI 10 select SSB_B43_PCI_BRIDGE if PCI
11 select SSB_PCICORE_HOSTMODE if PCI 11 select SSB_PCICORE_HOSTMODE if PCI
12 select SSB_DRIVER_GPIO
12 default y 13 default y
13 help 14 help
14 Add support for old Broadcom BCM47xx boards with Sonics Silicon Backplane support. 15 Add support for old Broadcom BCM47xx boards with Sonics Silicon Backplane support.
@@ -23,6 +24,7 @@ config BCM47XX_BCMA
23 select BCMA_DRIVER_MIPS 24 select BCMA_DRIVER_MIPS
24 select BCMA_HOST_PCI if PCI 25 select BCMA_HOST_PCI if PCI
25 select BCMA_DRIVER_PCI_HOSTMODE if PCI 26 select BCMA_DRIVER_PCI_HOSTMODE if PCI
27 select BCMA_DRIVER_GPIO
26 default y 28 default y
27 help 29 help
28 Add support for new Broadcom BCM47xx boards with Broadcom specific Advanced Microcontroller Bus. 30 Add support for new Broadcom BCM47xx boards with Broadcom specific Advanced Microcontroller Bus.
diff --git a/arch/mips/bcm47xx/Makefile b/arch/mips/bcm47xx/Makefile
index 4389de182eb..1a3567f07e7 100644
--- a/arch/mips/bcm47xx/Makefile
+++ b/arch/mips/bcm47xx/Makefile
@@ -3,5 +3,5 @@
3# under Linux. 3# under Linux.
4# 4#
5 5
6obj-y += gpio.o irq.o nvram.o prom.o serial.o setup.o time.o sprom.o 6obj-y += irq.o nvram.o prom.o serial.o setup.o time.o sprom.o
7obj-$(CONFIG_BCM47XX_SSB) += wgt634u.o 7obj-$(CONFIG_BCM47XX_SSB) += wgt634u.o
diff --git a/arch/mips/bcm47xx/gpio.c b/arch/mips/bcm47xx/gpio.c
deleted file mode 100644
index 5ebdf62e96b..00000000000
--- a/arch/mips/bcm47xx/gpio.c
+++ /dev/null
@@ -1,102 +0,0 @@
1/*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
6 * Copyright (C) 2007 Aurelien Jarno <aurelien@aurel32.net>
7 */
8
9#include <linux/export.h>
10#include <linux/ssb/ssb.h>
11#include <linux/ssb/ssb_driver_chipcommon.h>
12#include <linux/ssb/ssb_driver_extif.h>
13#include <asm/mach-bcm47xx/bcm47xx.h>
14#include <asm/mach-bcm47xx/gpio.h>
15
16#if (BCM47XX_CHIPCO_GPIO_LINES > BCM47XX_EXTIF_GPIO_LINES)
17static DECLARE_BITMAP(gpio_in_use, BCM47XX_CHIPCO_GPIO_LINES);
18#else
19static DECLARE_BITMAP(gpio_in_use, BCM47XX_EXTIF_GPIO_LINES);
20#endif
21
22int gpio_request(unsigned gpio, const char *tag)
23{
24 switch (bcm47xx_bus_type) {
25#ifdef CONFIG_BCM47XX_SSB
26 case BCM47XX_BUS_TYPE_SSB:
27 if (ssb_chipco_available(&bcm47xx_bus.ssb.chipco) &&
28 ((unsigned)gpio >= BCM47XX_CHIPCO_GPIO_LINES))
29 return -EINVAL;
30
31 if (ssb_extif_available(&bcm47xx_bus.ssb.extif) &&
32 ((unsigned)gpio >= BCM47XX_EXTIF_GPIO_LINES))
33 return -EINVAL;
34
35 if (test_and_set_bit(gpio, gpio_in_use))
36 return -EBUSY;
37
38 return 0;
39#endif
40#ifdef CONFIG_BCM47XX_BCMA
41 case BCM47XX_BUS_TYPE_BCMA:
42 if (gpio >= BCM47XX_CHIPCO_GPIO_LINES)
43 return -EINVAL;
44
45 if (test_and_set_bit(gpio, gpio_in_use))
46 return -EBUSY;
47
48 return 0;
49#endif
50 }
51 return -EINVAL;
52}
53EXPORT_SYMBOL(gpio_request);
54
55void gpio_free(unsigned gpio)
56{
57 switch (bcm47xx_bus_type) {
58#ifdef CONFIG_BCM47XX_SSB
59 case BCM47XX_BUS_TYPE_SSB:
60 if (ssb_chipco_available(&bcm47xx_bus.ssb.chipco) &&
61 ((unsigned)gpio >= BCM47XX_CHIPCO_GPIO_LINES))
62 return;
63
64 if (ssb_extif_available(&bcm47xx_bus.ssb.extif) &&
65 ((unsigned)gpio >= BCM47XX_EXTIF_GPIO_LINES))
66 return;
67
68 clear_bit(gpio, gpio_in_use);
69 return;
70#endif
71#ifdef CONFIG_BCM47XX_BCMA
72 case BCM47XX_BUS_TYPE_BCMA:
73 if (gpio >= BCM47XX_CHIPCO_GPIO_LINES)
74 return;
75
76 clear_bit(gpio, gpio_in_use);
77 return;
78#endif
79 }
80}
81EXPORT_SYMBOL(gpio_free);
82
83int gpio_to_irq(unsigned gpio)
84{
85 switch (bcm47xx_bus_type) {
86#ifdef CONFIG_BCM47XX_SSB
87 case BCM47XX_BUS_TYPE_SSB:
88 if (ssb_chipco_available(&bcm47xx_bus.ssb.chipco))
89 return ssb_mips_irq(bcm47xx_bus.ssb.chipco.dev) + 2;
90 else if (ssb_extif_available(&bcm47xx_bus.ssb.extif))
91 return ssb_mips_irq(bcm47xx_bus.ssb.extif.dev) + 2;
92 else
93 return -EINVAL;
94#endif
95#ifdef CONFIG_BCM47XX_BCMA
96 case BCM47XX_BUS_TYPE_BCMA:
97 return bcma_core_mips_irq(bcm47xx_bus.bcma.bus.drv_cc.core) + 2;
98#endif
99 }
100 return -EINVAL;
101}
102EXPORT_SYMBOL_GPL(gpio_to_irq);
diff --git a/arch/mips/bcm47xx/prom.c b/arch/mips/bcm47xx/prom.c
index f6e9063cc4c..8c155afb129 100644
--- a/arch/mips/bcm47xx/prom.c
+++ b/arch/mips/bcm47xx/prom.c
@@ -1,6 +1,7 @@
1/* 1/*
2 * Copyright (C) 2004 Florian Schirmer <jolt@tuxbox.org> 2 * Copyright (C) 2004 Florian Schirmer <jolt@tuxbox.org>
3 * Copyright (C) 2007 Aurelien Jarno <aurelien@aurel32.net> 3 * Copyright (C) 2007 Aurelien Jarno <aurelien@aurel32.net>
4 * Copyright (C) 2010-2012 Hauke Mehrtens <hauke@hauke-m.de>
4 * 5 *
5 * This program is free software; you can redistribute it and/or modify it 6 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the 7 * under the terms of the GNU General Public License as published by the
@@ -27,6 +28,7 @@
27#include <linux/types.h> 28#include <linux/types.h>
28#include <linux/kernel.h> 29#include <linux/kernel.h>
29#include <linux/spinlock.h> 30#include <linux/spinlock.h>
31#include <linux/smp.h>
30#include <asm/bootinfo.h> 32#include <asm/bootinfo.h>
31#include <asm/fw/cfe/cfe_api.h> 33#include <asm/fw/cfe/cfe_api.h>
32#include <asm/fw/cfe/cfe_error.h> 34#include <asm/fw/cfe/cfe_error.h>
@@ -127,6 +129,8 @@ static __init void prom_init_mem(void)
127{ 129{
128 unsigned long mem; 130 unsigned long mem;
129 unsigned long max; 131 unsigned long max;
132 unsigned long off;
133 struct cpuinfo_mips *c = &current_cpu_data;
130 134
131 /* Figure out memory size by finding aliases. 135 /* Figure out memory size by finding aliases.
132 * 136 *
@@ -143,18 +147,26 @@ static __init void prom_init_mem(void)
143 * max contains the biggest possible address supported by the platform. 147 * max contains the biggest possible address supported by the platform.
144 * If the method wants to try something above we assume 128MB ram. 148 * If the method wants to try something above we assume 128MB ram.
145 */ 149 */
146 max = ((unsigned long)(prom_init) | ((128 << 20) - 1)); 150 off = (unsigned long)prom_init;
151 max = off | ((128 << 20) - 1);
147 for (mem = (1 << 20); mem < (128 << 20); mem += (1 << 20)) { 152 for (mem = (1 << 20); mem < (128 << 20); mem += (1 << 20)) {
148 if (((unsigned long)(prom_init) + mem) > max) { 153 if ((off + mem) > max) {
149 mem = (128 << 20); 154 mem = (128 << 20);
150 printk(KERN_DEBUG "assume 128MB RAM\n"); 155 printk(KERN_DEBUG "assume 128MB RAM\n");
151 break; 156 break;
152 } 157 }
153 if (*(unsigned long *)((unsigned long)(prom_init) + mem) == 158 if (!memcmp(prom_init, prom_init + mem, 32))
154 *(unsigned long *)(prom_init))
155 break; 159 break;
156 } 160 }
157 161
162 /* Ignoring the last page when ddr size is 128M. Cached
163 * accesses to last page is causing the processor to prefetch
164 * using address above 128M stepping out of the ddr address
165 * space.
166 */
167 if (c->cputype == CPU_74K && (mem == (128 << 20)))
168 mem -= 0x1000;
169
158 add_memory_region(0, mem, BOOT_MEM_RAM); 170 add_memory_region(0, mem, BOOT_MEM_RAM);
159} 171}
160 172
diff --git a/arch/mips/bcm47xx/setup.c b/arch/mips/bcm47xx/setup.c
index 95bf4d7bac2..4d54b58dbd3 100644
--- a/arch/mips/bcm47xx/setup.c
+++ b/arch/mips/bcm47xx/setup.c
@@ -94,7 +94,7 @@ static int bcm47xx_get_sprom_ssb(struct ssb_bus *bus, struct ssb_sprom *out)
94 snprintf(prefix, sizeof(prefix), "pci/%u/%u/", 94 snprintf(prefix, sizeof(prefix), "pci/%u/%u/",
95 bus->host_pci->bus->number + 1, 95 bus->host_pci->bus->number + 1,
96 PCI_SLOT(bus->host_pci->devfn)); 96 PCI_SLOT(bus->host_pci->devfn));
97 bcm47xx_fill_sprom(out, prefix); 97 bcm47xx_fill_sprom(out, prefix, false);
98 return 0; 98 return 0;
99 } else { 99 } else {
100 printk(KERN_WARNING "bcm47xx: unable to fill SPROM for given bustype.\n"); 100 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,
113 bcm47xx_fill_ssb_boardinfo(&iv->boardinfo, NULL); 113 bcm47xx_fill_ssb_boardinfo(&iv->boardinfo, NULL);
114 114
115 memset(&iv->sprom, 0, sizeof(struct ssb_sprom)); 115 memset(&iv->sprom, 0, sizeof(struct ssb_sprom));
116 bcm47xx_fill_sprom(&iv->sprom, NULL); 116 bcm47xx_fill_sprom(&iv->sprom, NULL, false);
117 117
118 if (nvram_getenv("cardbus", buf, sizeof(buf)) >= 0) 118 if (nvram_getenv("cardbus", buf, sizeof(buf)) >= 0)
119 iv->has_cardbus_slot = !!simple_strtoul(buf, NULL, 10); 119 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)
165 snprintf(prefix, sizeof(prefix), "pci/%u/%u/", 165 snprintf(prefix, sizeof(prefix), "pci/%u/%u/",
166 bus->host_pci->bus->number + 1, 166 bus->host_pci->bus->number + 1,
167 PCI_SLOT(bus->host_pci->devfn)); 167 PCI_SLOT(bus->host_pci->devfn));
168 bcm47xx_fill_sprom(out, prefix); 168 bcm47xx_fill_sprom(out, prefix, false);
169 return 0; 169 return 0;
170 case BCMA_HOSTTYPE_SOC: 170 case BCMA_HOSTTYPE_SOC:
171 memset(out, 0, sizeof(struct ssb_sprom)); 171 memset(out, 0, sizeof(struct ssb_sprom));
172 bcm47xx_fill_sprom_ethernet(out, NULL);
173 core = bcma_find_core(bus, BCMA_CORE_80211); 172 core = bcma_find_core(bus, BCMA_CORE_80211);
174 if (core) { 173 if (core) {
175 snprintf(prefix, sizeof(prefix), "sb/%u/", 174 snprintf(prefix, sizeof(prefix), "sb/%u/",
176 core->core_index); 175 core->core_index);
177 bcm47xx_fill_sprom(out, prefix); 176 bcm47xx_fill_sprom(out, prefix, true);
177 } else {
178 bcm47xx_fill_sprom(out, NULL, false);
178 } 179 }
179 return 0; 180 return 0;
180 default: 181 default:
diff --git a/arch/mips/bcm47xx/sprom.c b/arch/mips/bcm47xx/sprom.c
index d3a889745e2..289cc0a3863 100644
--- a/arch/mips/bcm47xx/sprom.c
+++ b/arch/mips/bcm47xx/sprom.c
@@ -42,25 +42,39 @@ static void create_key(const char *prefix, const char *postfix,
42 snprintf(buf, len, "%s", name); 42 snprintf(buf, len, "%s", name);
43} 43}
44 44
45static int get_nvram_var(const char *prefix, const char *postfix,
46 const char *name, char *buf, int len, bool fallback)
47{
48 char key[40];
49 int err;
50
51 create_key(prefix, postfix, name, key, sizeof(key));
52
53 err = nvram_getenv(key, buf, len);
54 if (fallback && err == NVRAM_ERR_ENVNOTFOUND && prefix) {
55 create_key(NULL, postfix, name, key, sizeof(key));
56 err = nvram_getenv(key, buf, len);
57 }
58 return err;
59}
60
45#define NVRAM_READ_VAL(type) \ 61#define NVRAM_READ_VAL(type) \
46static void nvram_read_ ## type (const char *prefix, \ 62static void nvram_read_ ## type (const char *prefix, \
47 const char *postfix, const char *name, \ 63 const char *postfix, const char *name, \
48 type *val, type allset) \ 64 type *val, type allset, bool fallback) \
49{ \ 65{ \
50 char buf[100]; \ 66 char buf[100]; \
51 char key[40]; \
52 int err; \ 67 int err; \
53 type var; \ 68 type var; \
54 \ 69 \
55 create_key(prefix, postfix, name, key, sizeof(key)); \ 70 err = get_nvram_var(prefix, postfix, name, buf, sizeof(buf), \
56 \ 71 fallback); \
57 err = nvram_getenv(key, buf, sizeof(buf)); \
58 if (err < 0) \ 72 if (err < 0) \
59 return; \ 73 return; \
60 err = kstrto ## type (buf, 0, &var); \ 74 err = kstrto ## type (buf, 0, &var); \
61 if (err) { \ 75 if (err) { \
62 pr_warn("can not parse nvram name %s with value %s" \ 76 pr_warn("can not parse nvram name %s%s%s with value %s got %i\n", \
63 " got %i", key, buf, err); \ 77 prefix, name, postfix, buf, err); \
64 return; \ 78 return; \
65 } \ 79 } \
66 if (allset && var == allset) \ 80 if (allset && var == allset) \
@@ -76,22 +90,19 @@ NVRAM_READ_VAL(u32)
76#undef NVRAM_READ_VAL 90#undef NVRAM_READ_VAL
77 91
78static void nvram_read_u32_2(const char *prefix, const char *name, 92static void nvram_read_u32_2(const char *prefix, const char *name,
79 u16 *val_lo, u16 *val_hi) 93 u16 *val_lo, u16 *val_hi, bool fallback)
80{ 94{
81 char buf[100]; 95 char buf[100];
82 char key[40];
83 int err; 96 int err;
84 u32 val; 97 u32 val;
85 98
86 create_key(prefix, NULL, name, key, sizeof(key)); 99 err = get_nvram_var(prefix, NULL, name, buf, sizeof(buf), fallback);
87
88 err = nvram_getenv(key, buf, sizeof(buf));
89 if (err < 0) 100 if (err < 0)
90 return; 101 return;
91 err = kstrtou32(buf, 0, &val); 102 err = kstrtou32(buf, 0, &val);
92 if (err) { 103 if (err) {
93 pr_warn("can not parse nvram name %s with value %s got %i", 104 pr_warn("can not parse nvram name %s%s with value %s got %i\n",
94 key, buf, err); 105 prefix, name, buf, err);
95 return; 106 return;
96 } 107 }
97 *val_lo = (val & 0x0000FFFFU); 108 *val_lo = (val & 0x0000FFFFU);
@@ -99,22 +110,20 @@ static void nvram_read_u32_2(const char *prefix, const char *name,
99} 110}
100 111
101static void nvram_read_leddc(const char *prefix, const char *name, 112static void nvram_read_leddc(const char *prefix, const char *name,
102 u8 *leddc_on_time, u8 *leddc_off_time) 113 u8 *leddc_on_time, u8 *leddc_off_time,
114 bool fallback)
103{ 115{
104 char buf[100]; 116 char buf[100];
105 char key[40];
106 int err; 117 int err;
107 u32 val; 118 u32 val;
108 119
109 create_key(prefix, NULL, name, key, sizeof(key)); 120 err = get_nvram_var(prefix, NULL, name, buf, sizeof(buf), fallback);
110
111 err = nvram_getenv(key, buf, sizeof(buf));
112 if (err < 0) 121 if (err < 0)
113 return; 122 return;
114 err = kstrtou32(buf, 0, &val); 123 err = kstrtou32(buf, 0, &val);
115 if (err) { 124 if (err) {
116 pr_warn("can not parse nvram name %s with value %s got %i", 125 pr_warn("can not parse nvram name %s%s with value %s got %i\n",
117 key, buf, err); 126 prefix, name, buf, err);
118 return; 127 return;
119 } 128 }
120 129
@@ -126,355 +135,435 @@ static void nvram_read_leddc(const char *prefix, const char *name,
126} 135}
127 136
128static void nvram_read_macaddr(const char *prefix, const char *name, 137static void nvram_read_macaddr(const char *prefix, const char *name,
129 u8 (*val)[6]) 138 u8 (*val)[6], bool fallback)
130{ 139{
131 char buf[100]; 140 char buf[100];
132 char key[40];
133 int err; 141 int err;
134 142
135 create_key(prefix, NULL, name, key, sizeof(key)); 143 err = get_nvram_var(prefix, NULL, name, buf, sizeof(buf), fallback);
136
137 err = nvram_getenv(key, buf, sizeof(buf));
138 if (err < 0) 144 if (err < 0)
139 return; 145 return;
146
140 nvram_parse_macaddr(buf, *val); 147 nvram_parse_macaddr(buf, *val);
141} 148}
142 149
143static void nvram_read_alpha2(const char *prefix, const char *name, 150static void nvram_read_alpha2(const char *prefix, const char *name,
144 char (*val)[2]) 151 char (*val)[2], bool fallback)
145{ 152{
146 char buf[10]; 153 char buf[10];
147 char key[40];
148 int err; 154 int err;
149 155
150 create_key(prefix, NULL, name, key, sizeof(key)); 156 err = get_nvram_var(prefix, NULL, name, buf, sizeof(buf), fallback);
151
152 err = nvram_getenv(key, buf, sizeof(buf));
153 if (err < 0) 157 if (err < 0)
154 return; 158 return;
155 if (buf[0] == '0') 159 if (buf[0] == '0')
156 return; 160 return;
157 if (strlen(buf) > 2) { 161 if (strlen(buf) > 2) {
158 pr_warn("alpha2 is too long %s", buf); 162 pr_warn("alpha2 is too long %s\n", buf);
159 return; 163 return;
160 } 164 }
161 memcpy(val, buf, sizeof(val)); 165 memcpy(val, buf, sizeof(val));
162} 166}
163 167
164static void bcm47xx_fill_sprom_r1234589(struct ssb_sprom *sprom, 168static void bcm47xx_fill_sprom_r1234589(struct ssb_sprom *sprom,
165 const char *prefix) 169 const char *prefix, bool fallback)
166{ 170{
167 nvram_read_u16(prefix, NULL, "boardrev", &sprom->board_rev, 0); 171 nvram_read_u8(prefix, NULL, "ledbh0", &sprom->gpio0, 0xff, fallback);
168 if (!sprom->board_rev) 172 nvram_read_u8(prefix, NULL, "ledbh1", &sprom->gpio1, 0xff, fallback);
169 nvram_read_u16(NULL, NULL, "boardrev", &sprom->board_rev, 0); 173 nvram_read_u8(prefix, NULL, "ledbh2", &sprom->gpio2, 0xff, fallback);
170 nvram_read_u16(prefix, NULL, "boardnum", &sprom->board_num, 0); 174 nvram_read_u8(prefix, NULL, "ledbh3", &sprom->gpio3, 0xff, fallback);
171 nvram_read_u8(prefix, NULL, "ledbh0", &sprom->gpio0, 0xff); 175 nvram_read_u8(prefix, NULL, "aa2g", &sprom->ant_available_bg, 0,
172 nvram_read_u8(prefix, NULL, "ledbh1", &sprom->gpio1, 0xff); 176 fallback);
173 nvram_read_u8(prefix, NULL, "ledbh2", &sprom->gpio2, 0xff); 177 nvram_read_u8(prefix, NULL, "aa5g", &sprom->ant_available_a, 0,
174 nvram_read_u8(prefix, NULL, "ledbh3", &sprom->gpio3, 0xff); 178 fallback);
175 nvram_read_u8(prefix, NULL, "aa2g", &sprom->ant_available_bg, 0); 179 nvram_read_s8(prefix, NULL, "ag0", &sprom->antenna_gain.a0, 0,
176 nvram_read_u8(prefix, NULL, "aa5g", &sprom->ant_available_a, 0); 180 fallback);
177 nvram_read_s8(prefix, NULL, "ag0", &sprom->antenna_gain.a0, 0); 181 nvram_read_s8(prefix, NULL, "ag1", &sprom->antenna_gain.a1, 0,
178 nvram_read_s8(prefix, NULL, "ag1", &sprom->antenna_gain.a1, 0); 182 fallback);
179 nvram_read_alpha2(prefix, "ccode", &sprom->alpha2); 183 nvram_read_alpha2(prefix, "ccode", &sprom->alpha2, fallback);
180} 184}
181 185
182static void bcm47xx_fill_sprom_r12389(struct ssb_sprom *sprom, 186static void bcm47xx_fill_sprom_r12389(struct ssb_sprom *sprom,
183 const char *prefix) 187 const char *prefix, bool fallback)
184{ 188{
185 nvram_read_u16(prefix, NULL, "pa0b0", &sprom->pa0b0, 0); 189 nvram_read_u16(prefix, NULL, "pa0b0", &sprom->pa0b0, 0, fallback);
186 nvram_read_u16(prefix, NULL, "pa0b1", &sprom->pa0b1, 0); 190 nvram_read_u16(prefix, NULL, "pa0b1", &sprom->pa0b1, 0, fallback);
187 nvram_read_u16(prefix, NULL, "pa0b2", &sprom->pa0b2, 0); 191 nvram_read_u16(prefix, NULL, "pa0b2", &sprom->pa0b2, 0, fallback);
188 nvram_read_u8(prefix, NULL, "pa0itssit", &sprom->itssi_bg, 0); 192 nvram_read_u8(prefix, NULL, "pa0itssit", &sprom->itssi_bg, 0, fallback);
189 nvram_read_u8(prefix, NULL, "pa0maxpwr", &sprom->maxpwr_bg, 0); 193 nvram_read_u8(prefix, NULL, "pa0maxpwr", &sprom->maxpwr_bg, 0,
190 nvram_read_u16(prefix, NULL, "pa1b0", &sprom->pa1b0, 0); 194 fallback);
191 nvram_read_u16(prefix, NULL, "pa1b1", &sprom->pa1b1, 0); 195 nvram_read_u16(prefix, NULL, "pa1b0", &sprom->pa1b0, 0, fallback);
192 nvram_read_u16(prefix, NULL, "pa1b2", &sprom->pa1b2, 0); 196 nvram_read_u16(prefix, NULL, "pa1b1", &sprom->pa1b1, 0, fallback);
193 nvram_read_u8(prefix, NULL, "pa1itssit", &sprom->itssi_a, 0); 197 nvram_read_u16(prefix, NULL, "pa1b2", &sprom->pa1b2, 0, fallback);
194 nvram_read_u8(prefix, NULL, "pa1maxpwr", &sprom->maxpwr_a, 0); 198 nvram_read_u8(prefix, NULL, "pa1itssit", &sprom->itssi_a, 0, fallback);
199 nvram_read_u8(prefix, NULL, "pa1maxpwr", &sprom->maxpwr_a, 0, fallback);
195} 200}
196 201
197static void bcm47xx_fill_sprom_r1(struct ssb_sprom *sprom, const char *prefix) 202static void bcm47xx_fill_sprom_r1(struct ssb_sprom *sprom, const char *prefix,
203 bool fallback)
198{ 204{
199 nvram_read_u16(prefix, NULL, "boardflags", &sprom->boardflags_lo, 0); 205 nvram_read_u16(prefix, NULL, "boardflags", &sprom->boardflags_lo, 0,
200 nvram_read_u8(prefix, NULL, "cc", &sprom->country_code, 0); 206 fallback);
207 nvram_read_u8(prefix, NULL, "cc", &sprom->country_code, 0, fallback);
201} 208}
202 209
203static void bcm47xx_fill_sprom_r2389(struct ssb_sprom *sprom, 210static void bcm47xx_fill_sprom_r2389(struct ssb_sprom *sprom,
204 const char *prefix) 211 const char *prefix, bool fallback)
205{
206 nvram_read_u8(prefix, NULL, "opo", &sprom->opo, 0);
207 nvram_read_u16(prefix, NULL, "pa1lob0", &sprom->pa1lob0, 0);
208 nvram_read_u16(prefix, NULL, "pa1lob1", &sprom->pa1lob1, 0);
209 nvram_read_u16(prefix, NULL, "pa1lob2", &sprom->pa1lob2, 0);
210 nvram_read_u16(prefix, NULL, "pa1hib0", &sprom->pa1hib0, 0);
211 nvram_read_u16(prefix, NULL, "pa1hib1", &sprom->pa1hib1, 0);
212 nvram_read_u16(prefix, NULL, "pa1hib2", &sprom->pa1hib2, 0);
213 nvram_read_u8(prefix, NULL, "pa1lomaxpwr", &sprom->maxpwr_al, 0);
214 nvram_read_u8(prefix, NULL, "pa1himaxpwr", &sprom->maxpwr_ah, 0);
215}
216
217static void bcm47xx_fill_sprom_r2(struct ssb_sprom *sprom, const char *prefix)
218{ 212{
219 nvram_read_u32_2(prefix, "boardflags", &sprom->boardflags_lo, 213 nvram_read_u8(prefix, NULL, "opo", &sprom->opo, 0, fallback);
220 &sprom->boardflags_hi); 214 nvram_read_u16(prefix, NULL, "pa1lob0", &sprom->pa1lob0, 0, fallback);
221 nvram_read_u16(prefix, NULL, "boardtype", &sprom->board_type, 0); 215 nvram_read_u16(prefix, NULL, "pa1lob1", &sprom->pa1lob1, 0, fallback);
216 nvram_read_u16(prefix, NULL, "pa1lob2", &sprom->pa1lob2, 0, fallback);
217 nvram_read_u16(prefix, NULL, "pa1hib0", &sprom->pa1hib0, 0, fallback);
218 nvram_read_u16(prefix, NULL, "pa1hib1", &sprom->pa1hib1, 0, fallback);
219 nvram_read_u16(prefix, NULL, "pa1hib2", &sprom->pa1hib2, 0, fallback);
220 nvram_read_u8(prefix, NULL, "pa1lomaxpwr", &sprom->maxpwr_al, 0,
221 fallback);
222 nvram_read_u8(prefix, NULL, "pa1himaxpwr", &sprom->maxpwr_ah, 0,
223 fallback);
222} 224}
223 225
224static void bcm47xx_fill_sprom_r389(struct ssb_sprom *sprom, const char *prefix) 226static void bcm47xx_fill_sprom_r389(struct ssb_sprom *sprom, const char *prefix,
227 bool fallback)
225{ 228{
226 nvram_read_u8(prefix, NULL, "bxa2g", &sprom->bxa2g, 0); 229 nvram_read_u8(prefix, NULL, "bxa2g", &sprom->bxa2g, 0, fallback);
227 nvram_read_u8(prefix, NULL, "rssisav2g", &sprom->rssisav2g, 0); 230 nvram_read_u8(prefix, NULL, "rssisav2g", &sprom->rssisav2g, 0,
228 nvram_read_u8(prefix, NULL, "rssismc2g", &sprom->rssismc2g, 0); 231 fallback);
229 nvram_read_u8(prefix, NULL, "rssismf2g", &sprom->rssismf2g, 0); 232 nvram_read_u8(prefix, NULL, "rssismc2g", &sprom->rssismc2g, 0,
230 nvram_read_u8(prefix, NULL, "bxa5g", &sprom->bxa5g, 0); 233 fallback);
231 nvram_read_u8(prefix, NULL, "rssisav5g", &sprom->rssisav5g, 0); 234 nvram_read_u8(prefix, NULL, "rssismf2g", &sprom->rssismf2g, 0,
232 nvram_read_u8(prefix, NULL, "rssismc5g", &sprom->rssismc5g, 0); 235 fallback);
233 nvram_read_u8(prefix, NULL, "rssismf5g", &sprom->rssismf5g, 0); 236 nvram_read_u8(prefix, NULL, "bxa5g", &sprom->bxa5g, 0, fallback);
234 nvram_read_u8(prefix, NULL, "tri2g", &sprom->tri2g, 0); 237 nvram_read_u8(prefix, NULL, "rssisav5g", &sprom->rssisav5g, 0,
235 nvram_read_u8(prefix, NULL, "tri5g", &sprom->tri5g, 0); 238 fallback);
236 nvram_read_u8(prefix, NULL, "tri5gl", &sprom->tri5gl, 0); 239 nvram_read_u8(prefix, NULL, "rssismc5g", &sprom->rssismc5g, 0,
237 nvram_read_u8(prefix, NULL, "tri5gh", &sprom->tri5gh, 0); 240 fallback);
238 nvram_read_s8(prefix, NULL, "rxpo2g", &sprom->rxpo2g, 0); 241 nvram_read_u8(prefix, NULL, "rssismf5g", &sprom->rssismf5g, 0,
239 nvram_read_s8(prefix, NULL, "rxpo5g", &sprom->rxpo5g, 0); 242 fallback);
243 nvram_read_u8(prefix, NULL, "tri2g", &sprom->tri2g, 0, fallback);
244 nvram_read_u8(prefix, NULL, "tri5g", &sprom->tri5g, 0, fallback);
245 nvram_read_u8(prefix, NULL, "tri5gl", &sprom->tri5gl, 0, fallback);
246 nvram_read_u8(prefix, NULL, "tri5gh", &sprom->tri5gh, 0, fallback);
247 nvram_read_s8(prefix, NULL, "rxpo2g", &sprom->rxpo2g, 0, fallback);
248 nvram_read_s8(prefix, NULL, "rxpo5g", &sprom->rxpo5g, 0, fallback);
240} 249}
241 250
242static void bcm47xx_fill_sprom_r3(struct ssb_sprom *sprom, const char *prefix) 251static void bcm47xx_fill_sprom_r3(struct ssb_sprom *sprom, const char *prefix,
252 bool fallback)
243{ 253{
244 nvram_read_u32_2(prefix, "boardflags", &sprom->boardflags_lo, 254 nvram_read_u8(prefix, NULL, "regrev", &sprom->regrev, 0, fallback);
245 &sprom->boardflags_hi);
246 nvram_read_u16(prefix, NULL, "boardtype", &sprom->board_type, 0);
247 nvram_read_u8(prefix, NULL, "regrev", &sprom->regrev, 0);
248 nvram_read_leddc(prefix, "leddc", &sprom->leddc_on_time, 255 nvram_read_leddc(prefix, "leddc", &sprom->leddc_on_time,
249 &sprom->leddc_off_time); 256 &sprom->leddc_off_time, fallback);
250} 257}
251 258
252static void bcm47xx_fill_sprom_r4589(struct ssb_sprom *sprom, 259static void bcm47xx_fill_sprom_r4589(struct ssb_sprom *sprom,
253 const char *prefix) 260 const char *prefix, bool fallback)
254{ 261{
255 nvram_read_u32_2(prefix, "boardflags", &sprom->boardflags_lo, 262 nvram_read_u8(prefix, NULL, "regrev", &sprom->regrev, 0, fallback);
256 &sprom->boardflags_hi); 263 nvram_read_s8(prefix, NULL, "ag2", &sprom->antenna_gain.a2, 0,
257 nvram_read_u32_2(prefix, "boardflags2", &sprom->boardflags2_lo, 264 fallback);
258 &sprom->boardflags2_hi); 265 nvram_read_s8(prefix, NULL, "ag3", &sprom->antenna_gain.a3, 0,
259 nvram_read_u16(prefix, NULL, "boardtype", &sprom->board_type, 0); 266 fallback);
260 nvram_read_u8(prefix, NULL, "regrev", &sprom->regrev, 0); 267 nvram_read_u8(prefix, NULL, "txchain", &sprom->txchain, 0xf, fallback);
261 nvram_read_s8(prefix, NULL, "ag2", &sprom->antenna_gain.a2, 0); 268 nvram_read_u8(prefix, NULL, "rxchain", &sprom->rxchain, 0xf, fallback);
262 nvram_read_s8(prefix, NULL, "ag3", &sprom->antenna_gain.a3, 0); 269 nvram_read_u8(prefix, NULL, "antswitch", &sprom->antswitch, 0xff,
263 nvram_read_u8(prefix, NULL, "txchain", &sprom->txchain, 0xf); 270 fallback);
264 nvram_read_u8(prefix, NULL, "rxchain", &sprom->rxchain, 0xf);
265 nvram_read_u8(prefix, NULL, "antswitch", &sprom->antswitch, 0xff);
266 nvram_read_leddc(prefix, "leddc", &sprom->leddc_on_time, 271 nvram_read_leddc(prefix, "leddc", &sprom->leddc_on_time,
267 &sprom->leddc_off_time); 272 &sprom->leddc_off_time, fallback);
268} 273}
269 274
270static void bcm47xx_fill_sprom_r458(struct ssb_sprom *sprom, const char *prefix) 275static void bcm47xx_fill_sprom_r458(struct ssb_sprom *sprom, const char *prefix,
276 bool fallback)
271{ 277{
272 nvram_read_u16(prefix, NULL, "cck2gpo", &sprom->cck2gpo, 0); 278 nvram_read_u16(prefix, NULL, "cck2gpo", &sprom->cck2gpo, 0, fallback);
273 nvram_read_u32(prefix, NULL, "ofdm2gpo", &sprom->ofdm2gpo, 0); 279 nvram_read_u32(prefix, NULL, "ofdm2gpo", &sprom->ofdm2gpo, 0, fallback);
274 nvram_read_u32(prefix, NULL, "ofdm5gpo", &sprom->ofdm5gpo, 0); 280 nvram_read_u32(prefix, NULL, "ofdm5gpo", &sprom->ofdm5gpo, 0, fallback);
275 nvram_read_u32(prefix, NULL, "ofdm5glpo", &sprom->ofdm5glpo, 0); 281 nvram_read_u32(prefix, NULL, "ofdm5glpo", &sprom->ofdm5glpo, 0,
276 nvram_read_u32(prefix, NULL, "ofdm5ghpo", &sprom->ofdm5ghpo, 0); 282 fallback);
277 nvram_read_u16(prefix, NULL, "cddpo", &sprom->cddpo, 0); 283 nvram_read_u32(prefix, NULL, "ofdm5ghpo", &sprom->ofdm5ghpo, 0,
278 nvram_read_u16(prefix, NULL, "stbcpo", &sprom->stbcpo, 0); 284 fallback);
279 nvram_read_u16(prefix, NULL, "bw40po", &sprom->bw40po, 0); 285 nvram_read_u16(prefix, NULL, "cddpo", &sprom->cddpo, 0, fallback);
280 nvram_read_u16(prefix, NULL, "bwduppo", &sprom->bwduppo, 0); 286 nvram_read_u16(prefix, NULL, "stbcpo", &sprom->stbcpo, 0, fallback);
281 nvram_read_u16(prefix, NULL, "mcs2gpo0", &sprom->mcs2gpo[0], 0); 287 nvram_read_u16(prefix, NULL, "bw40po", &sprom->bw40po, 0, fallback);
282 nvram_read_u16(prefix, NULL, "mcs2gpo1", &sprom->mcs2gpo[1], 0); 288 nvram_read_u16(prefix, NULL, "bwduppo", &sprom->bwduppo, 0, fallback);
283 nvram_read_u16(prefix, NULL, "mcs2gpo2", &sprom->mcs2gpo[2], 0); 289 nvram_read_u16(prefix, NULL, "mcs2gpo0", &sprom->mcs2gpo[0], 0,
284 nvram_read_u16(prefix, NULL, "mcs2gpo3", &sprom->mcs2gpo[3], 0); 290 fallback);
285 nvram_read_u16(prefix, NULL, "mcs2gpo4", &sprom->mcs2gpo[4], 0); 291 nvram_read_u16(prefix, NULL, "mcs2gpo1", &sprom->mcs2gpo[1], 0,
286 nvram_read_u16(prefix, NULL, "mcs2gpo5", &sprom->mcs2gpo[5], 0); 292 fallback);
287 nvram_read_u16(prefix, NULL, "mcs2gpo6", &sprom->mcs2gpo[6], 0); 293 nvram_read_u16(prefix, NULL, "mcs2gpo2", &sprom->mcs2gpo[2], 0,
288 nvram_read_u16(prefix, NULL, "mcs2gpo7", &sprom->mcs2gpo[7], 0); 294 fallback);
289 nvram_read_u16(prefix, NULL, "mcs5gpo0", &sprom->mcs5gpo[0], 0); 295 nvram_read_u16(prefix, NULL, "mcs2gpo3", &sprom->mcs2gpo[3], 0,
290 nvram_read_u16(prefix, NULL, "mcs5gpo1", &sprom->mcs5gpo[1], 0); 296 fallback);
291 nvram_read_u16(prefix, NULL, "mcs5gpo2", &sprom->mcs5gpo[2], 0); 297 nvram_read_u16(prefix, NULL, "mcs2gpo4", &sprom->mcs2gpo[4], 0,
292 nvram_read_u16(prefix, NULL, "mcs5gpo3", &sprom->mcs5gpo[3], 0); 298 fallback);
293 nvram_read_u16(prefix, NULL, "mcs5gpo4", &sprom->mcs5gpo[4], 0); 299 nvram_read_u16(prefix, NULL, "mcs2gpo5", &sprom->mcs2gpo[5], 0,
294 nvram_read_u16(prefix, NULL, "mcs5gpo5", &sprom->mcs5gpo[5], 0); 300 fallback);
295 nvram_read_u16(prefix, NULL, "mcs5gpo6", &sprom->mcs5gpo[6], 0); 301 nvram_read_u16(prefix, NULL, "mcs2gpo6", &sprom->mcs2gpo[6], 0,
296 nvram_read_u16(prefix, NULL, "mcs5gpo7", &sprom->mcs5gpo[7], 0); 302 fallback);
297 nvram_read_u16(prefix, NULL, "mcs5glpo0", &sprom->mcs5glpo[0], 0); 303 nvram_read_u16(prefix, NULL, "mcs2gpo7", &sprom->mcs2gpo[7], 0,
298 nvram_read_u16(prefix, NULL, "mcs5glpo1", &sprom->mcs5glpo[1], 0); 304 fallback);
299 nvram_read_u16(prefix, NULL, "mcs5glpo2", &sprom->mcs5glpo[2], 0); 305 nvram_read_u16(prefix, NULL, "mcs5gpo0", &sprom->mcs5gpo[0], 0,
300 nvram_read_u16(prefix, NULL, "mcs5glpo3", &sprom->mcs5glpo[3], 0); 306 fallback);
301 nvram_read_u16(prefix, NULL, "mcs5glpo4", &sprom->mcs5glpo[4], 0); 307 nvram_read_u16(prefix, NULL, "mcs5gpo1", &sprom->mcs5gpo[1], 0,
302 nvram_read_u16(prefix, NULL, "mcs5glpo5", &sprom->mcs5glpo[5], 0); 308 fallback);
303 nvram_read_u16(prefix, NULL, "mcs5glpo6", &sprom->mcs5glpo[6], 0); 309 nvram_read_u16(prefix, NULL, "mcs5gpo2", &sprom->mcs5gpo[2], 0,
304 nvram_read_u16(prefix, NULL, "mcs5glpo7", &sprom->mcs5glpo[7], 0); 310 fallback);
305 nvram_read_u16(prefix, NULL, "mcs5ghpo0", &sprom->mcs5ghpo[0], 0); 311 nvram_read_u16(prefix, NULL, "mcs5gpo3", &sprom->mcs5gpo[3], 0,
306 nvram_read_u16(prefix, NULL, "mcs5ghpo1", &sprom->mcs5ghpo[1], 0); 312 fallback);
307 nvram_read_u16(prefix, NULL, "mcs5ghpo2", &sprom->mcs5ghpo[2], 0); 313 nvram_read_u16(prefix, NULL, "mcs5gpo4", &sprom->mcs5gpo[4], 0,
308 nvram_read_u16(prefix, NULL, "mcs5ghpo3", &sprom->mcs5ghpo[3], 0); 314 fallback);
309 nvram_read_u16(prefix, NULL, "mcs5ghpo4", &sprom->mcs5ghpo[4], 0); 315 nvram_read_u16(prefix, NULL, "mcs5gpo5", &sprom->mcs5gpo[5], 0,
310 nvram_read_u16(prefix, NULL, "mcs5ghpo5", &sprom->mcs5ghpo[5], 0); 316 fallback);
311 nvram_read_u16(prefix, NULL, "mcs5ghpo6", &sprom->mcs5ghpo[6], 0); 317 nvram_read_u16(prefix, NULL, "mcs5gpo6", &sprom->mcs5gpo[6], 0,
312 nvram_read_u16(prefix, NULL, "mcs5ghpo7", &sprom->mcs5ghpo[7], 0); 318 fallback);
319 nvram_read_u16(prefix, NULL, "mcs5gpo7", &sprom->mcs5gpo[7], 0,
320 fallback);
321 nvram_read_u16(prefix, NULL, "mcs5glpo0", &sprom->mcs5glpo[0], 0,
322 fallback);
323 nvram_read_u16(prefix, NULL, "mcs5glpo1", &sprom->mcs5glpo[1], 0,
324 fallback);
325 nvram_read_u16(prefix, NULL, "mcs5glpo2", &sprom->mcs5glpo[2], 0,
326 fallback);
327 nvram_read_u16(prefix, NULL, "mcs5glpo3", &sprom->mcs5glpo[3], 0,
328 fallback);
329 nvram_read_u16(prefix, NULL, "mcs5glpo4", &sprom->mcs5glpo[4], 0,
330 fallback);
331 nvram_read_u16(prefix, NULL, "mcs5glpo5", &sprom->mcs5glpo[5], 0,
332 fallback);
333 nvram_read_u16(prefix, NULL, "mcs5glpo6", &sprom->mcs5glpo[6], 0,
334 fallback);
335 nvram_read_u16(prefix, NULL, "mcs5glpo7", &sprom->mcs5glpo[7], 0,
336 fallback);
337 nvram_read_u16(prefix, NULL, "mcs5ghpo0", &sprom->mcs5ghpo[0], 0,
338 fallback);
339 nvram_read_u16(prefix, NULL, "mcs5ghpo1", &sprom->mcs5ghpo[1], 0,
340 fallback);
341 nvram_read_u16(prefix, NULL, "mcs5ghpo2", &sprom->mcs5ghpo[2], 0,
342 fallback);
343 nvram_read_u16(prefix, NULL, "mcs5ghpo3", &sprom->mcs5ghpo[3], 0,
344 fallback);
345 nvram_read_u16(prefix, NULL, "mcs5ghpo4", &sprom->mcs5ghpo[4], 0,
346 fallback);
347 nvram_read_u16(prefix, NULL, "mcs5ghpo5", &sprom->mcs5ghpo[5], 0,
348 fallback);
349 nvram_read_u16(prefix, NULL, "mcs5ghpo6", &sprom->mcs5ghpo[6], 0,
350 fallback);
351 nvram_read_u16(prefix, NULL, "mcs5ghpo7", &sprom->mcs5ghpo[7], 0,
352 fallback);
313} 353}
314 354
315static void bcm47xx_fill_sprom_r45(struct ssb_sprom *sprom, const char *prefix) 355static void bcm47xx_fill_sprom_r45(struct ssb_sprom *sprom, const char *prefix,
356 bool fallback)
316{ 357{
317 nvram_read_u8(prefix, NULL, "txpid2ga0", &sprom->txpid2g[0], 0); 358 nvram_read_u8(prefix, NULL, "txpid2ga0", &sprom->txpid2g[0], 0,
318 nvram_read_u8(prefix, NULL, "txpid2ga1", &sprom->txpid2g[1], 0); 359 fallback);
319 nvram_read_u8(prefix, NULL, "txpid2ga2", &sprom->txpid2g[2], 0); 360 nvram_read_u8(prefix, NULL, "txpid2ga1", &sprom->txpid2g[1], 0,
320 nvram_read_u8(prefix, NULL, "txpid2ga3", &sprom->txpid2g[3], 0); 361 fallback);
321 nvram_read_u8(prefix, NULL, "txpid5ga0", &sprom->txpid5g[0], 0); 362 nvram_read_u8(prefix, NULL, "txpid2ga2", &sprom->txpid2g[2], 0,
322 nvram_read_u8(prefix, NULL, "txpid5ga1", &sprom->txpid5g[1], 0); 363 fallback);
323 nvram_read_u8(prefix, NULL, "txpid5ga2", &sprom->txpid5g[2], 0); 364 nvram_read_u8(prefix, NULL, "txpid2ga3", &sprom->txpid2g[3], 0,
324 nvram_read_u8(prefix, NULL, "txpid5ga3", &sprom->txpid5g[3], 0); 365 fallback);
325 nvram_read_u8(prefix, NULL, "txpid5gla0", &sprom->txpid5gl[0], 0); 366 nvram_read_u8(prefix, NULL, "txpid5ga0", &sprom->txpid5g[0], 0,
326 nvram_read_u8(prefix, NULL, "txpid5gla1", &sprom->txpid5gl[1], 0); 367 fallback);
327 nvram_read_u8(prefix, NULL, "txpid5gla2", &sprom->txpid5gl[2], 0); 368 nvram_read_u8(prefix, NULL, "txpid5ga1", &sprom->txpid5g[1], 0,
328 nvram_read_u8(prefix, NULL, "txpid5gla3", &sprom->txpid5gl[3], 0); 369 fallback);
329 nvram_read_u8(prefix, NULL, "txpid5gha0", &sprom->txpid5gh[0], 0); 370 nvram_read_u8(prefix, NULL, "txpid5ga2", &sprom->txpid5g[2], 0,
330 nvram_read_u8(prefix, NULL, "txpid5gha1", &sprom->txpid5gh[1], 0); 371 fallback);
331 nvram_read_u8(prefix, NULL, "txpid5gha2", &sprom->txpid5gh[2], 0); 372 nvram_read_u8(prefix, NULL, "txpid5ga3", &sprom->txpid5g[3], 0,
332 nvram_read_u8(prefix, NULL, "txpid5gha3", &sprom->txpid5gh[3], 0); 373 fallback);
374 nvram_read_u8(prefix, NULL, "txpid5gla0", &sprom->txpid5gl[0], 0,
375 fallback);
376 nvram_read_u8(prefix, NULL, "txpid5gla1", &sprom->txpid5gl[1], 0,
377 fallback);
378 nvram_read_u8(prefix, NULL, "txpid5gla2", &sprom->txpid5gl[2], 0,
379 fallback);
380 nvram_read_u8(prefix, NULL, "txpid5gla3", &sprom->txpid5gl[3], 0,
381 fallback);
382 nvram_read_u8(prefix, NULL, "txpid5gha0", &sprom->txpid5gh[0], 0,
383 fallback);
384 nvram_read_u8(prefix, NULL, "txpid5gha1", &sprom->txpid5gh[1], 0,
385 fallback);
386 nvram_read_u8(prefix, NULL, "txpid5gha2", &sprom->txpid5gh[2], 0,
387 fallback);
388 nvram_read_u8(prefix, NULL, "txpid5gha3", &sprom->txpid5gh[3], 0,
389 fallback);
333} 390}
334 391
335static void bcm47xx_fill_sprom_r89(struct ssb_sprom *sprom, const char *prefix) 392static void bcm47xx_fill_sprom_r89(struct ssb_sprom *sprom, const char *prefix,
393 bool fallback)
336{ 394{
337 nvram_read_u8(prefix, NULL, "tssipos2g", &sprom->fem.ghz2.tssipos, 0); 395 nvram_read_u8(prefix, NULL, "tssipos2g", &sprom->fem.ghz2.tssipos, 0,
396 fallback);
338 nvram_read_u8(prefix, NULL, "extpagain2g", 397 nvram_read_u8(prefix, NULL, "extpagain2g",
339 &sprom->fem.ghz2.extpa_gain, 0); 398 &sprom->fem.ghz2.extpa_gain, 0, fallback);
340 nvram_read_u8(prefix, NULL, "pdetrange2g", 399 nvram_read_u8(prefix, NULL, "pdetrange2g",
341 &sprom->fem.ghz2.pdet_range, 0); 400 &sprom->fem.ghz2.pdet_range, 0, fallback);
342 nvram_read_u8(prefix, NULL, "triso2g", &sprom->fem.ghz2.tr_iso, 0); 401 nvram_read_u8(prefix, NULL, "triso2g", &sprom->fem.ghz2.tr_iso, 0,
343 nvram_read_u8(prefix, NULL, "antswctl2g", &sprom->fem.ghz2.antswlut, 0); 402 fallback);
344 nvram_read_u8(prefix, NULL, "tssipos5g", &sprom->fem.ghz5.tssipos, 0); 403 nvram_read_u8(prefix, NULL, "antswctl2g", &sprom->fem.ghz2.antswlut, 0,
404 fallback);
405 nvram_read_u8(prefix, NULL, "tssipos5g", &sprom->fem.ghz5.tssipos, 0,
406 fallback);
345 nvram_read_u8(prefix, NULL, "extpagain5g", 407 nvram_read_u8(prefix, NULL, "extpagain5g",
346 &sprom->fem.ghz5.extpa_gain, 0); 408 &sprom->fem.ghz5.extpa_gain, 0, fallback);
347 nvram_read_u8(prefix, NULL, "pdetrange5g", 409 nvram_read_u8(prefix, NULL, "pdetrange5g",
348 &sprom->fem.ghz5.pdet_range, 0); 410 &sprom->fem.ghz5.pdet_range, 0, fallback);
349 nvram_read_u8(prefix, NULL, "triso5g", &sprom->fem.ghz5.tr_iso, 0); 411 nvram_read_u8(prefix, NULL, "triso5g", &sprom->fem.ghz5.tr_iso, 0,
350 nvram_read_u8(prefix, NULL, "antswctl5g", &sprom->fem.ghz5.antswlut, 0); 412 fallback);
351 nvram_read_u8(prefix, NULL, "tempthresh", &sprom->tempthresh, 0); 413 nvram_read_u8(prefix, NULL, "antswctl5g", &sprom->fem.ghz5.antswlut, 0,
352 nvram_read_u8(prefix, NULL, "tempoffset", &sprom->tempoffset, 0); 414 fallback);
353 nvram_read_u16(prefix, NULL, "rawtempsense", &sprom->rawtempsense, 0); 415 nvram_read_u8(prefix, NULL, "tempthresh", &sprom->tempthresh, 0,
354 nvram_read_u8(prefix, NULL, "measpower", &sprom->measpower, 0); 416 fallback);
417 nvram_read_u8(prefix, NULL, "tempoffset", &sprom->tempoffset, 0,
418 fallback);
419 nvram_read_u16(prefix, NULL, "rawtempsense", &sprom->rawtempsense, 0,
420 fallback);
421 nvram_read_u8(prefix, NULL, "measpower", &sprom->measpower, 0,
422 fallback);
355 nvram_read_u8(prefix, NULL, "tempsense_slope", 423 nvram_read_u8(prefix, NULL, "tempsense_slope",
356 &sprom->tempsense_slope, 0); 424 &sprom->tempsense_slope, 0, fallback);
357 nvram_read_u8(prefix, NULL, "tempcorrx", &sprom->tempcorrx, 0); 425 nvram_read_u8(prefix, NULL, "tempcorrx", &sprom->tempcorrx, 0,
426 fallback);
358 nvram_read_u8(prefix, NULL, "tempsense_option", 427 nvram_read_u8(prefix, NULL, "tempsense_option",
359 &sprom->tempsense_option, 0); 428 &sprom->tempsense_option, 0, fallback);
360 nvram_read_u8(prefix, NULL, "freqoffset_corr", 429 nvram_read_u8(prefix, NULL, "freqoffset_corr",
361 &sprom->freqoffset_corr, 0); 430 &sprom->freqoffset_corr, 0, fallback);
362 nvram_read_u8(prefix, NULL, "iqcal_swp_dis", &sprom->iqcal_swp_dis, 0); 431 nvram_read_u8(prefix, NULL, "iqcal_swp_dis", &sprom->iqcal_swp_dis, 0,
363 nvram_read_u8(prefix, NULL, "hw_iqcal_en", &sprom->hw_iqcal_en, 0); 432 fallback);
364 nvram_read_u8(prefix, NULL, "elna2g", &sprom->elna2g, 0); 433 nvram_read_u8(prefix, NULL, "hw_iqcal_en", &sprom->hw_iqcal_en, 0,
365 nvram_read_u8(prefix, NULL, "elna5g", &sprom->elna5g, 0); 434 fallback);
435 nvram_read_u8(prefix, NULL, "elna2g", &sprom->elna2g, 0, fallback);
436 nvram_read_u8(prefix, NULL, "elna5g", &sprom->elna5g, 0, fallback);
366 nvram_read_u8(prefix, NULL, "phycal_tempdelta", 437 nvram_read_u8(prefix, NULL, "phycal_tempdelta",
367 &sprom->phycal_tempdelta, 0); 438 &sprom->phycal_tempdelta, 0, fallback);
368 nvram_read_u8(prefix, NULL, "temps_period", &sprom->temps_period, 0); 439 nvram_read_u8(prefix, NULL, "temps_period", &sprom->temps_period, 0,
440 fallback);
369 nvram_read_u8(prefix, NULL, "temps_hysteresis", 441 nvram_read_u8(prefix, NULL, "temps_hysteresis",
370 &sprom->temps_hysteresis, 0); 442 &sprom->temps_hysteresis, 0, fallback);
371 nvram_read_u8(prefix, NULL, "measpower1", &sprom->measpower1, 0); 443 nvram_read_u8(prefix, NULL, "measpower1", &sprom->measpower1, 0,
372 nvram_read_u8(prefix, NULL, "measpower2", &sprom->measpower2, 0); 444 fallback);
445 nvram_read_u8(prefix, NULL, "measpower2", &sprom->measpower2, 0,
446 fallback);
373 nvram_read_u8(prefix, NULL, "rxgainerr2ga0", 447 nvram_read_u8(prefix, NULL, "rxgainerr2ga0",
374 &sprom->rxgainerr2ga[0], 0); 448 &sprom->rxgainerr2ga[0], 0, fallback);
375 nvram_read_u8(prefix, NULL, "rxgainerr2ga1", 449 nvram_read_u8(prefix, NULL, "rxgainerr2ga1",
376 &sprom->rxgainerr2ga[1], 0); 450 &sprom->rxgainerr2ga[1], 0, fallback);
377 nvram_read_u8(prefix, NULL, "rxgainerr2ga2", 451 nvram_read_u8(prefix, NULL, "rxgainerr2ga2",
378 &sprom->rxgainerr2ga[2], 0); 452 &sprom->rxgainerr2ga[2], 0, fallback);
379 nvram_read_u8(prefix, NULL, "rxgainerr5gla0", 453 nvram_read_u8(prefix, NULL, "rxgainerr5gla0",
380 &sprom->rxgainerr5gla[0], 0); 454 &sprom->rxgainerr5gla[0], 0, fallback);
381 nvram_read_u8(prefix, NULL, "rxgainerr5gla1", 455 nvram_read_u8(prefix, NULL, "rxgainerr5gla1",
382 &sprom->rxgainerr5gla[1], 0); 456 &sprom->rxgainerr5gla[1], 0, fallback);
383 nvram_read_u8(prefix, NULL, "rxgainerr5gla2", 457 nvram_read_u8(prefix, NULL, "rxgainerr5gla2",
384 &sprom->rxgainerr5gla[2], 0); 458 &sprom->rxgainerr5gla[2], 0, fallback);
385 nvram_read_u8(prefix, NULL, "rxgainerr5gma0", 459 nvram_read_u8(prefix, NULL, "rxgainerr5gma0",
386 &sprom->rxgainerr5gma[0], 0); 460 &sprom->rxgainerr5gma[0], 0, fallback);
387 nvram_read_u8(prefix, NULL, "rxgainerr5gma1", 461 nvram_read_u8(prefix, NULL, "rxgainerr5gma1",
388 &sprom->rxgainerr5gma[1], 0); 462 &sprom->rxgainerr5gma[1], 0, fallback);
389 nvram_read_u8(prefix, NULL, "rxgainerr5gma2", 463 nvram_read_u8(prefix, NULL, "rxgainerr5gma2",
390 &sprom->rxgainerr5gma[2], 0); 464 &sprom->rxgainerr5gma[2], 0, fallback);
391 nvram_read_u8(prefix, NULL, "rxgainerr5gha0", 465 nvram_read_u8(prefix, NULL, "rxgainerr5gha0",
392 &sprom->rxgainerr5gha[0], 0); 466 &sprom->rxgainerr5gha[0], 0, fallback);
393 nvram_read_u8(prefix, NULL, "rxgainerr5gha1", 467 nvram_read_u8(prefix, NULL, "rxgainerr5gha1",
394 &sprom->rxgainerr5gha[1], 0); 468 &sprom->rxgainerr5gha[1], 0, fallback);
395 nvram_read_u8(prefix, NULL, "rxgainerr5gha2", 469 nvram_read_u8(prefix, NULL, "rxgainerr5gha2",
396 &sprom->rxgainerr5gha[2], 0); 470 &sprom->rxgainerr5gha[2], 0, fallback);
397 nvram_read_u8(prefix, NULL, "rxgainerr5gua0", 471 nvram_read_u8(prefix, NULL, "rxgainerr5gua0",
398 &sprom->rxgainerr5gua[0], 0); 472 &sprom->rxgainerr5gua[0], 0, fallback);
399 nvram_read_u8(prefix, NULL, "rxgainerr5gua1", 473 nvram_read_u8(prefix, NULL, "rxgainerr5gua1",
400 &sprom->rxgainerr5gua[1], 0); 474 &sprom->rxgainerr5gua[1], 0, fallback);
401 nvram_read_u8(prefix, NULL, "rxgainerr5gua2", 475 nvram_read_u8(prefix, NULL, "rxgainerr5gua2",
402 &sprom->rxgainerr5gua[2], 0); 476 &sprom->rxgainerr5gua[2], 0, fallback);
403 nvram_read_u8(prefix, NULL, "noiselvl2ga0", &sprom->noiselvl2ga[0], 0); 477 nvram_read_u8(prefix, NULL, "noiselvl2ga0", &sprom->noiselvl2ga[0], 0,
404 nvram_read_u8(prefix, NULL, "noiselvl2ga1", &sprom->noiselvl2ga[1], 0); 478 fallback);
405 nvram_read_u8(prefix, NULL, "noiselvl2ga2", &sprom->noiselvl2ga[2], 0); 479 nvram_read_u8(prefix, NULL, "noiselvl2ga1", &sprom->noiselvl2ga[1], 0,
480 fallback);
481 nvram_read_u8(prefix, NULL, "noiselvl2ga2", &sprom->noiselvl2ga[2], 0,
482 fallback);
406 nvram_read_u8(prefix, NULL, "noiselvl5gla0", 483 nvram_read_u8(prefix, NULL, "noiselvl5gla0",
407 &sprom->noiselvl5gla[0], 0); 484 &sprom->noiselvl5gla[0], 0, fallback);
408 nvram_read_u8(prefix, NULL, "noiselvl5gla1", 485 nvram_read_u8(prefix, NULL, "noiselvl5gla1",
409 &sprom->noiselvl5gla[1], 0); 486 &sprom->noiselvl5gla[1], 0, fallback);
410 nvram_read_u8(prefix, NULL, "noiselvl5gla2", 487 nvram_read_u8(prefix, NULL, "noiselvl5gla2",
411 &sprom->noiselvl5gla[2], 0); 488 &sprom->noiselvl5gla[2], 0, fallback);
412 nvram_read_u8(prefix, NULL, "noiselvl5gma0", 489 nvram_read_u8(prefix, NULL, "noiselvl5gma0",
413 &sprom->noiselvl5gma[0], 0); 490 &sprom->noiselvl5gma[0], 0, fallback);
414 nvram_read_u8(prefix, NULL, "noiselvl5gma1", 491 nvram_read_u8(prefix, NULL, "noiselvl5gma1",
415 &sprom->noiselvl5gma[1], 0); 492 &sprom->noiselvl5gma[1], 0, fallback);
416 nvram_read_u8(prefix, NULL, "noiselvl5gma2", 493 nvram_read_u8(prefix, NULL, "noiselvl5gma2",
417 &sprom->noiselvl5gma[2], 0); 494 &sprom->noiselvl5gma[2], 0, fallback);
418 nvram_read_u8(prefix, NULL, "noiselvl5gha0", 495 nvram_read_u8(prefix, NULL, "noiselvl5gha0",
419 &sprom->noiselvl5gha[0], 0); 496 &sprom->noiselvl5gha[0], 0, fallback);
420 nvram_read_u8(prefix, NULL, "noiselvl5gha1", 497 nvram_read_u8(prefix, NULL, "noiselvl5gha1",
421 &sprom->noiselvl5gha[1], 0); 498 &sprom->noiselvl5gha[1], 0, fallback);
422 nvram_read_u8(prefix, NULL, "noiselvl5gha2", 499 nvram_read_u8(prefix, NULL, "noiselvl5gha2",
423 &sprom->noiselvl5gha[2], 0); 500 &sprom->noiselvl5gha[2], 0, fallback);
424 nvram_read_u8(prefix, NULL, "noiselvl5gua0", 501 nvram_read_u8(prefix, NULL, "noiselvl5gua0",
425 &sprom->noiselvl5gua[0], 0); 502 &sprom->noiselvl5gua[0], 0, fallback);
426 nvram_read_u8(prefix, NULL, "noiselvl5gua1", 503 nvram_read_u8(prefix, NULL, "noiselvl5gua1",
427 &sprom->noiselvl5gua[1], 0); 504 &sprom->noiselvl5gua[1], 0, fallback);
428 nvram_read_u8(prefix, NULL, "noiselvl5gua2", 505 nvram_read_u8(prefix, NULL, "noiselvl5gua2",
429 &sprom->noiselvl5gua[2], 0); 506 &sprom->noiselvl5gua[2], 0, fallback);
430 nvram_read_u8(prefix, NULL, "pcieingress_war", 507 nvram_read_u8(prefix, NULL, "pcieingress_war",
431 &sprom->pcieingress_war, 0); 508 &sprom->pcieingress_war, 0, fallback);
432} 509}
433 510
434static void bcm47xx_fill_sprom_r9(struct ssb_sprom *sprom, const char *prefix) 511static void bcm47xx_fill_sprom_r9(struct ssb_sprom *sprom, const char *prefix,
512 bool fallback)
435{ 513{
436 nvram_read_u16(prefix, NULL, "cckbw202gpo", &sprom->cckbw202gpo, 0); 514 nvram_read_u16(prefix, NULL, "cckbw202gpo", &sprom->cckbw202gpo, 0,
437 nvram_read_u16(prefix, NULL, "cckbw20ul2gpo", &sprom->cckbw20ul2gpo, 0); 515 fallback);
516 nvram_read_u16(prefix, NULL, "cckbw20ul2gpo", &sprom->cckbw20ul2gpo, 0,
517 fallback);
438 nvram_read_u32(prefix, NULL, "legofdmbw202gpo", 518 nvram_read_u32(prefix, NULL, "legofdmbw202gpo",
439 &sprom->legofdmbw202gpo, 0); 519 &sprom->legofdmbw202gpo, 0, fallback);
440 nvram_read_u32(prefix, NULL, "legofdmbw20ul2gpo", 520 nvram_read_u32(prefix, NULL, "legofdmbw20ul2gpo",
441 &sprom->legofdmbw20ul2gpo, 0); 521 &sprom->legofdmbw20ul2gpo, 0, fallback);
442 nvram_read_u32(prefix, NULL, "legofdmbw205glpo", 522 nvram_read_u32(prefix, NULL, "legofdmbw205glpo",
443 &sprom->legofdmbw205glpo, 0); 523 &sprom->legofdmbw205glpo, 0, fallback);
444 nvram_read_u32(prefix, NULL, "legofdmbw20ul5glpo", 524 nvram_read_u32(prefix, NULL, "legofdmbw20ul5glpo",
445 &sprom->legofdmbw20ul5glpo, 0); 525 &sprom->legofdmbw20ul5glpo, 0, fallback);
446 nvram_read_u32(prefix, NULL, "legofdmbw205gmpo", 526 nvram_read_u32(prefix, NULL, "legofdmbw205gmpo",
447 &sprom->legofdmbw205gmpo, 0); 527 &sprom->legofdmbw205gmpo, 0, fallback);
448 nvram_read_u32(prefix, NULL, "legofdmbw20ul5gmpo", 528 nvram_read_u32(prefix, NULL, "legofdmbw20ul5gmpo",
449 &sprom->legofdmbw20ul5gmpo, 0); 529 &sprom->legofdmbw20ul5gmpo, 0, fallback);
450 nvram_read_u32(prefix, NULL, "legofdmbw205ghpo", 530 nvram_read_u32(prefix, NULL, "legofdmbw205ghpo",
451 &sprom->legofdmbw205ghpo, 0); 531 &sprom->legofdmbw205ghpo, 0, fallback);
452 nvram_read_u32(prefix, NULL, "legofdmbw20ul5ghpo", 532 nvram_read_u32(prefix, NULL, "legofdmbw20ul5ghpo",
453 &sprom->legofdmbw20ul5ghpo, 0); 533 &sprom->legofdmbw20ul5ghpo, 0, fallback);
454 nvram_read_u32(prefix, NULL, "mcsbw202gpo", &sprom->mcsbw202gpo, 0); 534 nvram_read_u32(prefix, NULL, "mcsbw202gpo", &sprom->mcsbw202gpo, 0,
455 nvram_read_u32(prefix, NULL, "mcsbw20ul2gpo", &sprom->mcsbw20ul2gpo, 0); 535 fallback);
456 nvram_read_u32(prefix, NULL, "mcsbw402gpo", &sprom->mcsbw402gpo, 0); 536 nvram_read_u32(prefix, NULL, "mcsbw20ul2gpo", &sprom->mcsbw20ul2gpo, 0,
457 nvram_read_u32(prefix, NULL, "mcsbw205glpo", &sprom->mcsbw205glpo, 0); 537 fallback);
538 nvram_read_u32(prefix, NULL, "mcsbw402gpo", &sprom->mcsbw402gpo, 0,
539 fallback);
540 nvram_read_u32(prefix, NULL, "mcsbw205glpo", &sprom->mcsbw205glpo, 0,
541 fallback);
458 nvram_read_u32(prefix, NULL, "mcsbw20ul5glpo", 542 nvram_read_u32(prefix, NULL, "mcsbw20ul5glpo",
459 &sprom->mcsbw20ul5glpo, 0); 543 &sprom->mcsbw20ul5glpo, 0, fallback);
460 nvram_read_u32(prefix, NULL, "mcsbw405glpo", &sprom->mcsbw405glpo, 0); 544 nvram_read_u32(prefix, NULL, "mcsbw405glpo", &sprom->mcsbw405glpo, 0,
461 nvram_read_u32(prefix, NULL, "mcsbw205gmpo", &sprom->mcsbw205gmpo, 0); 545 fallback);
546 nvram_read_u32(prefix, NULL, "mcsbw205gmpo", &sprom->mcsbw205gmpo, 0,
547 fallback);
462 nvram_read_u32(prefix, NULL, "mcsbw20ul5gmpo", 548 nvram_read_u32(prefix, NULL, "mcsbw20ul5gmpo",
463 &sprom->mcsbw20ul5gmpo, 0); 549 &sprom->mcsbw20ul5gmpo, 0, fallback);
464 nvram_read_u32(prefix, NULL, "mcsbw405gmpo", &sprom->mcsbw405gmpo, 0); 550 nvram_read_u32(prefix, NULL, "mcsbw405gmpo", &sprom->mcsbw405gmpo, 0,
465 nvram_read_u32(prefix, NULL, "mcsbw205ghpo", &sprom->mcsbw205ghpo, 0); 551 fallback);
552 nvram_read_u32(prefix, NULL, "mcsbw205ghpo", &sprom->mcsbw205ghpo, 0,
553 fallback);
466 nvram_read_u32(prefix, NULL, "mcsbw20ul5ghpo", 554 nvram_read_u32(prefix, NULL, "mcsbw20ul5ghpo",
467 &sprom->mcsbw20ul5ghpo, 0); 555 &sprom->mcsbw20ul5ghpo, 0, fallback);
468 nvram_read_u32(prefix, NULL, "mcsbw405ghpo", &sprom->mcsbw405ghpo, 0); 556 nvram_read_u32(prefix, NULL, "mcsbw405ghpo", &sprom->mcsbw405ghpo, 0,
469 nvram_read_u16(prefix, NULL, "mcs32po", &sprom->mcs32po, 0); 557 fallback);
558 nvram_read_u16(prefix, NULL, "mcs32po", &sprom->mcs32po, 0, fallback);
470 nvram_read_u16(prefix, NULL, "legofdm40duppo", 559 nvram_read_u16(prefix, NULL, "legofdm40duppo",
471 &sprom->legofdm40duppo, 0); 560 &sprom->legofdm40duppo, 0, fallback);
472 nvram_read_u8(prefix, NULL, "sar2g", &sprom->sar2g, 0); 561 nvram_read_u8(prefix, NULL, "sar2g", &sprom->sar2g, 0, fallback);
473 nvram_read_u8(prefix, NULL, "sar5g", &sprom->sar5g, 0); 562 nvram_read_u8(prefix, NULL, "sar5g", &sprom->sar5g, 0, fallback);
474} 563}
475 564
476static void bcm47xx_fill_sprom_path_r4589(struct ssb_sprom *sprom, 565static void bcm47xx_fill_sprom_path_r4589(struct ssb_sprom *sprom,
477 const char *prefix) 566 const char *prefix, bool fallback)
478{ 567{
479 char postfix[2]; 568 char postfix[2];
480 int i; 569 int i;
@@ -483,46 +572,46 @@ static void bcm47xx_fill_sprom_path_r4589(struct ssb_sprom *sprom,
483 struct ssb_sprom_core_pwr_info *pwr_info = &sprom->core_pwr_info[i]; 572 struct ssb_sprom_core_pwr_info *pwr_info = &sprom->core_pwr_info[i];
484 snprintf(postfix, sizeof(postfix), "%i", i); 573 snprintf(postfix, sizeof(postfix), "%i", i);
485 nvram_read_u8(prefix, postfix, "maxp2ga", 574 nvram_read_u8(prefix, postfix, "maxp2ga",
486 &pwr_info->maxpwr_2g, 0); 575 &pwr_info->maxpwr_2g, 0, fallback);
487 nvram_read_u8(prefix, postfix, "itt2ga", 576 nvram_read_u8(prefix, postfix, "itt2ga",
488 &pwr_info->itssi_2g, 0); 577 &pwr_info->itssi_2g, 0, fallback);
489 nvram_read_u8(prefix, postfix, "itt5ga", 578 nvram_read_u8(prefix, postfix, "itt5ga",
490 &pwr_info->itssi_5g, 0); 579 &pwr_info->itssi_5g, 0, fallback);
491 nvram_read_u16(prefix, postfix, "pa2gw0a", 580 nvram_read_u16(prefix, postfix, "pa2gw0a",
492 &pwr_info->pa_2g[0], 0); 581 &pwr_info->pa_2g[0], 0, fallback);
493 nvram_read_u16(prefix, postfix, "pa2gw1a", 582 nvram_read_u16(prefix, postfix, "pa2gw1a",
494 &pwr_info->pa_2g[1], 0); 583 &pwr_info->pa_2g[1], 0, fallback);
495 nvram_read_u16(prefix, postfix, "pa2gw2a", 584 nvram_read_u16(prefix, postfix, "pa2gw2a",
496 &pwr_info->pa_2g[2], 0); 585 &pwr_info->pa_2g[2], 0, fallback);
497 nvram_read_u8(prefix, postfix, "maxp5ga", 586 nvram_read_u8(prefix, postfix, "maxp5ga",
498 &pwr_info->maxpwr_5g, 0); 587 &pwr_info->maxpwr_5g, 0, fallback);
499 nvram_read_u8(prefix, postfix, "maxp5gha", 588 nvram_read_u8(prefix, postfix, "maxp5gha",
500 &pwr_info->maxpwr_5gh, 0); 589 &pwr_info->maxpwr_5gh, 0, fallback);
501 nvram_read_u8(prefix, postfix, "maxp5gla", 590 nvram_read_u8(prefix, postfix, "maxp5gla",
502 &pwr_info->maxpwr_5gl, 0); 591 &pwr_info->maxpwr_5gl, 0, fallback);
503 nvram_read_u16(prefix, postfix, "pa5gw0a", 592 nvram_read_u16(prefix, postfix, "pa5gw0a",
504 &pwr_info->pa_5g[0], 0); 593 &pwr_info->pa_5g[0], 0, fallback);
505 nvram_read_u16(prefix, postfix, "pa5gw1a", 594 nvram_read_u16(prefix, postfix, "pa5gw1a",
506 &pwr_info->pa_5g[1], 0); 595 &pwr_info->pa_5g[1], 0, fallback);
507 nvram_read_u16(prefix, postfix, "pa5gw2a", 596 nvram_read_u16(prefix, postfix, "pa5gw2a",
508 &pwr_info->pa_5g[2], 0); 597 &pwr_info->pa_5g[2], 0, fallback);
509 nvram_read_u16(prefix, postfix, "pa5glw0a", 598 nvram_read_u16(prefix, postfix, "pa5glw0a",
510 &pwr_info->pa_5gl[0], 0); 599 &pwr_info->pa_5gl[0], 0, fallback);
511 nvram_read_u16(prefix, postfix, "pa5glw1a", 600 nvram_read_u16(prefix, postfix, "pa5glw1a",
512 &pwr_info->pa_5gl[1], 0); 601 &pwr_info->pa_5gl[1], 0, fallback);
513 nvram_read_u16(prefix, postfix, "pa5glw2a", 602 nvram_read_u16(prefix, postfix, "pa5glw2a",
514 &pwr_info->pa_5gl[2], 0); 603 &pwr_info->pa_5gl[2], 0, fallback);
515 nvram_read_u16(prefix, postfix, "pa5ghw0a", 604 nvram_read_u16(prefix, postfix, "pa5ghw0a",
516 &pwr_info->pa_5gh[0], 0); 605 &pwr_info->pa_5gh[0], 0, fallback);
517 nvram_read_u16(prefix, postfix, "pa5ghw1a", 606 nvram_read_u16(prefix, postfix, "pa5ghw1a",
518 &pwr_info->pa_5gh[1], 0); 607 &pwr_info->pa_5gh[1], 0, fallback);
519 nvram_read_u16(prefix, postfix, "pa5ghw2a", 608 nvram_read_u16(prefix, postfix, "pa5ghw2a",
520 &pwr_info->pa_5gh[2], 0); 609 &pwr_info->pa_5gh[2], 0, fallback);
521 } 610 }
522} 611}
523 612
524static void bcm47xx_fill_sprom_path_r45(struct ssb_sprom *sprom, 613static void bcm47xx_fill_sprom_path_r45(struct ssb_sprom *sprom,
525 const char *prefix) 614 const char *prefix, bool fallback)
526{ 615{
527 char postfix[2]; 616 char postfix[2];
528 int i; 617 int i;
@@ -531,91 +620,112 @@ static void bcm47xx_fill_sprom_path_r45(struct ssb_sprom *sprom,
531 struct ssb_sprom_core_pwr_info *pwr_info = &sprom->core_pwr_info[i]; 620 struct ssb_sprom_core_pwr_info *pwr_info = &sprom->core_pwr_info[i];
532 snprintf(postfix, sizeof(postfix), "%i", i); 621 snprintf(postfix, sizeof(postfix), "%i", i);
533 nvram_read_u16(prefix, postfix, "pa2gw3a", 622 nvram_read_u16(prefix, postfix, "pa2gw3a",
534 &pwr_info->pa_2g[3], 0); 623 &pwr_info->pa_2g[3], 0, fallback);
535 nvram_read_u16(prefix, postfix, "pa5gw3a", 624 nvram_read_u16(prefix, postfix, "pa5gw3a",
536 &pwr_info->pa_5g[3], 0); 625 &pwr_info->pa_5g[3], 0, fallback);
537 nvram_read_u16(prefix, postfix, "pa5glw3a", 626 nvram_read_u16(prefix, postfix, "pa5glw3a",
538 &pwr_info->pa_5gl[3], 0); 627 &pwr_info->pa_5gl[3], 0, fallback);
539 nvram_read_u16(prefix, postfix, "pa5ghw3a", 628 nvram_read_u16(prefix, postfix, "pa5ghw3a",
540 &pwr_info->pa_5gh[3], 0); 629 &pwr_info->pa_5gh[3], 0, fallback);
541 } 630 }
542} 631}
543 632
544void bcm47xx_fill_sprom_ethernet(struct ssb_sprom *sprom, const char *prefix) 633static void bcm47xx_fill_sprom_ethernet(struct ssb_sprom *sprom,
634 const char *prefix, bool fallback)
545{ 635{
546 nvram_read_macaddr(prefix, "et0macaddr", &sprom->et0mac); 636 nvram_read_macaddr(prefix, "et0macaddr", &sprom->et0mac, fallback);
547 nvram_read_u8(prefix, NULL, "et0mdcport", &sprom->et0mdcport, 0); 637 nvram_read_u8(prefix, NULL, "et0mdcport", &sprom->et0mdcport, 0,
548 nvram_read_u8(prefix, NULL, "et0phyaddr", &sprom->et0phyaddr, 0); 638 fallback);
549 639 nvram_read_u8(prefix, NULL, "et0phyaddr", &sprom->et0phyaddr, 0,
550 nvram_read_macaddr(prefix, "et1macaddr", &sprom->et1mac); 640 fallback);
551 nvram_read_u8(prefix, NULL, "et1mdcport", &sprom->et1mdcport, 0); 641
552 nvram_read_u8(prefix, NULL, "et1phyaddr", &sprom->et1phyaddr, 0); 642 nvram_read_macaddr(prefix, "et1macaddr", &sprom->et1mac, fallback);
643 nvram_read_u8(prefix, NULL, "et1mdcport", &sprom->et1mdcport, 0,
644 fallback);
645 nvram_read_u8(prefix, NULL, "et1phyaddr", &sprom->et1phyaddr, 0,
646 fallback);
647
648 nvram_read_macaddr(prefix, "macaddr", &sprom->il0mac, fallback);
649 nvram_read_macaddr(prefix, "il0macaddr", &sprom->il0mac, fallback);
650}
553 651
554 nvram_read_macaddr(prefix, "macaddr", &sprom->il0mac); 652static void bcm47xx_fill_board_data(struct ssb_sprom *sprom, const char *prefix,
555 nvram_read_macaddr(prefix, "il0macaddr", &sprom->il0mac); 653 bool fallback)
654{
655 nvram_read_u16(prefix, NULL, "boardrev", &sprom->board_rev, 0,
656 fallback);
657 nvram_read_u16(prefix, NULL, "boardnum", &sprom->board_num, 0,
658 fallback);
659 nvram_read_u16(prefix, NULL, "boardtype", &sprom->board_type, 0,
660 fallback);
661 nvram_read_u32_2(prefix, "boardflags", &sprom->boardflags_lo,
662 &sprom->boardflags_hi, fallback);
663 nvram_read_u32_2(prefix, "boardflags2", &sprom->boardflags2_lo,
664 &sprom->boardflags2_hi, fallback);
556} 665}
557 666
558void bcm47xx_fill_sprom(struct ssb_sprom *sprom, const char *prefix) 667void bcm47xx_fill_sprom(struct ssb_sprom *sprom, const char *prefix,
668 bool fallback)
559{ 669{
560 bcm47xx_fill_sprom_ethernet(sprom, prefix); 670 bcm47xx_fill_sprom_ethernet(sprom, prefix, fallback);
671 bcm47xx_fill_board_data(sprom, prefix, fallback);
561 672
562 nvram_read_u8(prefix, NULL, "sromrev", &sprom->revision, 0); 673 nvram_read_u8(prefix, NULL, "sromrev", &sprom->revision, 0, fallback);
563 674
564 switch (sprom->revision) { 675 switch (sprom->revision) {
565 case 1: 676 case 1:
566 bcm47xx_fill_sprom_r1234589(sprom, prefix); 677 bcm47xx_fill_sprom_r1234589(sprom, prefix, fallback);
567 bcm47xx_fill_sprom_r12389(sprom, prefix); 678 bcm47xx_fill_sprom_r12389(sprom, prefix, fallback);
568 bcm47xx_fill_sprom_r1(sprom, prefix); 679 bcm47xx_fill_sprom_r1(sprom, prefix, fallback);
569 break; 680 break;
570 case 2: 681 case 2:
571 bcm47xx_fill_sprom_r1234589(sprom, prefix); 682 bcm47xx_fill_sprom_r1234589(sprom, prefix, fallback);
572 bcm47xx_fill_sprom_r12389(sprom, prefix); 683 bcm47xx_fill_sprom_r12389(sprom, prefix, fallback);
573 bcm47xx_fill_sprom_r2389(sprom, prefix); 684 bcm47xx_fill_sprom_r2389(sprom, prefix, fallback);
574 bcm47xx_fill_sprom_r2(sprom, prefix);
575 break; 685 break;
576 case 3: 686 case 3:
577 bcm47xx_fill_sprom_r1234589(sprom, prefix); 687 bcm47xx_fill_sprom_r1234589(sprom, prefix, fallback);
578 bcm47xx_fill_sprom_r12389(sprom, prefix); 688 bcm47xx_fill_sprom_r12389(sprom, prefix, fallback);
579 bcm47xx_fill_sprom_r2389(sprom, prefix); 689 bcm47xx_fill_sprom_r2389(sprom, prefix, fallback);
580 bcm47xx_fill_sprom_r389(sprom, prefix); 690 bcm47xx_fill_sprom_r389(sprom, prefix, fallback);
581 bcm47xx_fill_sprom_r3(sprom, prefix); 691 bcm47xx_fill_sprom_r3(sprom, prefix, fallback);
582 break; 692 break;
583 case 4: 693 case 4:
584 case 5: 694 case 5:
585 bcm47xx_fill_sprom_r1234589(sprom, prefix); 695 bcm47xx_fill_sprom_r1234589(sprom, prefix, fallback);
586 bcm47xx_fill_sprom_r4589(sprom, prefix); 696 bcm47xx_fill_sprom_r4589(sprom, prefix, fallback);
587 bcm47xx_fill_sprom_r458(sprom, prefix); 697 bcm47xx_fill_sprom_r458(sprom, prefix, fallback);
588 bcm47xx_fill_sprom_r45(sprom, prefix); 698 bcm47xx_fill_sprom_r45(sprom, prefix, fallback);
589 bcm47xx_fill_sprom_path_r4589(sprom, prefix); 699 bcm47xx_fill_sprom_path_r4589(sprom, prefix, fallback);
590 bcm47xx_fill_sprom_path_r45(sprom, prefix); 700 bcm47xx_fill_sprom_path_r45(sprom, prefix, fallback);
591 break; 701 break;
592 case 8: 702 case 8:
593 bcm47xx_fill_sprom_r1234589(sprom, prefix); 703 bcm47xx_fill_sprom_r1234589(sprom, prefix, fallback);
594 bcm47xx_fill_sprom_r12389(sprom, prefix); 704 bcm47xx_fill_sprom_r12389(sprom, prefix, fallback);
595 bcm47xx_fill_sprom_r2389(sprom, prefix); 705 bcm47xx_fill_sprom_r2389(sprom, prefix, fallback);
596 bcm47xx_fill_sprom_r389(sprom, prefix); 706 bcm47xx_fill_sprom_r389(sprom, prefix, fallback);
597 bcm47xx_fill_sprom_r4589(sprom, prefix); 707 bcm47xx_fill_sprom_r4589(sprom, prefix, fallback);
598 bcm47xx_fill_sprom_r458(sprom, prefix); 708 bcm47xx_fill_sprom_r458(sprom, prefix, fallback);
599 bcm47xx_fill_sprom_r89(sprom, prefix); 709 bcm47xx_fill_sprom_r89(sprom, prefix, fallback);
600 bcm47xx_fill_sprom_path_r4589(sprom, prefix); 710 bcm47xx_fill_sprom_path_r4589(sprom, prefix, fallback);
601 break; 711 break;
602 case 9: 712 case 9:
603 bcm47xx_fill_sprom_r1234589(sprom, prefix); 713 bcm47xx_fill_sprom_r1234589(sprom, prefix, fallback);
604 bcm47xx_fill_sprom_r12389(sprom, prefix); 714 bcm47xx_fill_sprom_r12389(sprom, prefix, fallback);
605 bcm47xx_fill_sprom_r2389(sprom, prefix); 715 bcm47xx_fill_sprom_r2389(sprom, prefix, fallback);
606 bcm47xx_fill_sprom_r389(sprom, prefix); 716 bcm47xx_fill_sprom_r389(sprom, prefix, fallback);
607 bcm47xx_fill_sprom_r4589(sprom, prefix); 717 bcm47xx_fill_sprom_r4589(sprom, prefix, fallback);
608 bcm47xx_fill_sprom_r89(sprom, prefix); 718 bcm47xx_fill_sprom_r89(sprom, prefix, fallback);
609 bcm47xx_fill_sprom_r9(sprom, prefix); 719 bcm47xx_fill_sprom_r9(sprom, prefix, fallback);
610 bcm47xx_fill_sprom_path_r4589(sprom, prefix); 720 bcm47xx_fill_sprom_path_r4589(sprom, prefix, fallback);
611 break; 721 break;
612 default: 722 default:
613 pr_warn("Unsupported SPROM revision %d detected. Will extract" 723 pr_warn("Unsupported SPROM revision %d detected. Will extract"
614 " v1\n", sprom->revision); 724 " v1\n", sprom->revision);
615 sprom->revision = 1; 725 sprom->revision = 1;
616 bcm47xx_fill_sprom_r1234589(sprom, prefix); 726 bcm47xx_fill_sprom_r1234589(sprom, prefix, fallback);
617 bcm47xx_fill_sprom_r12389(sprom, prefix); 727 bcm47xx_fill_sprom_r12389(sprom, prefix, fallback);
618 bcm47xx_fill_sprom_r1(sprom, prefix); 728 bcm47xx_fill_sprom_r1(sprom, prefix, fallback);
619 } 729 }
620} 730}
621 731
@@ -623,11 +733,12 @@ void bcm47xx_fill_sprom(struct ssb_sprom *sprom, const char *prefix)
623void bcm47xx_fill_ssb_boardinfo(struct ssb_boardinfo *boardinfo, 733void bcm47xx_fill_ssb_boardinfo(struct ssb_boardinfo *boardinfo,
624 const char *prefix) 734 const char *prefix)
625{ 735{
626 nvram_read_u16(prefix, NULL, "boardvendor", &boardinfo->vendor, 0); 736 nvram_read_u16(prefix, NULL, "boardvendor", &boardinfo->vendor, 0,
737 true);
627 if (!boardinfo->vendor) 738 if (!boardinfo->vendor)
628 boardinfo->vendor = SSB_BOARDVENDOR_BCM; 739 boardinfo->vendor = SSB_BOARDVENDOR_BCM;
629 740
630 nvram_read_u16(prefix, NULL, "boardtype", &boardinfo->type, 0); 741 nvram_read_u16(prefix, NULL, "boardtype", &boardinfo->type, 0, true);
631} 742}
632#endif 743#endif
633 744
@@ -635,10 +746,11 @@ void bcm47xx_fill_ssb_boardinfo(struct ssb_boardinfo *boardinfo,
635void bcm47xx_fill_bcma_boardinfo(struct bcma_boardinfo *boardinfo, 746void bcm47xx_fill_bcma_boardinfo(struct bcma_boardinfo *boardinfo,
636 const char *prefix) 747 const char *prefix)
637{ 748{
638 nvram_read_u16(prefix, NULL, "boardvendor", &boardinfo->vendor, 0); 749 nvram_read_u16(prefix, NULL, "boardvendor", &boardinfo->vendor, 0,
750 true);
639 if (!boardinfo->vendor) 751 if (!boardinfo->vendor)
640 boardinfo->vendor = SSB_BOARDVENDOR_BCM; 752 boardinfo->vendor = SSB_BOARDVENDOR_BCM;
641 753
642 nvram_read_u16(prefix, NULL, "boardtype", &boardinfo->type, 0); 754 nvram_read_u16(prefix, NULL, "boardtype", &boardinfo->type, 0, true);
643} 755}
644#endif 756#endif
diff --git a/arch/mips/bcm47xx/wgt634u.c b/arch/mips/bcm47xx/wgt634u.c
index e9f9ec8d443..6c28f6d891d 100644
--- a/arch/mips/bcm47xx/wgt634u.c
+++ b/arch/mips/bcm47xx/wgt634u.c
@@ -11,6 +11,7 @@
11#include <linux/leds.h> 11#include <linux/leds.h>
12#include <linux/mtd/physmap.h> 12#include <linux/mtd/physmap.h>
13#include <linux/ssb/ssb.h> 13#include <linux/ssb/ssb.h>
14#include <linux/ssb/ssb_embedded.h>
14#include <linux/interrupt.h> 15#include <linux/interrupt.h>
15#include <linux/reboot.h> 16#include <linux/reboot.h>
16#include <linux/gpio.h> 17#include <linux/gpio.h>
@@ -116,7 +117,8 @@ static irqreturn_t gpio_interrupt(int irq, void *ignored)
116 117
117 /* Interrupt are level triggered, revert the interrupt polarity 118 /* Interrupt are level triggered, revert the interrupt polarity
118 to clear the interrupt. */ 119 to clear the interrupt. */
119 gpio_polarity(WGT634U_GPIO_RESET, state); 120 ssb_gpio_polarity(&bcm47xx_bus.ssb, 1 << WGT634U_GPIO_RESET,
121 state ? 1 << WGT634U_GPIO_RESET : 0);
120 122
121 if (!state) { 123 if (!state) {
122 printk(KERN_INFO "Reset button pressed"); 124 printk(KERN_INFO "Reset button pressed");
@@ -150,7 +152,9 @@ static int __init wgt634u_init(void)
150 gpio_interrupt, IRQF_SHARED, 152 gpio_interrupt, IRQF_SHARED,
151 "WGT634U GPIO", &bcm47xx_bus.ssb.chipco)) { 153 "WGT634U GPIO", &bcm47xx_bus.ssb.chipco)) {
152 gpio_direction_input(WGT634U_GPIO_RESET); 154 gpio_direction_input(WGT634U_GPIO_RESET);
153 gpio_intmask(WGT634U_GPIO_RESET, 1); 155 ssb_gpio_intmask(&bcm47xx_bus.ssb,
156 1 << WGT634U_GPIO_RESET,
157 1 << WGT634U_GPIO_RESET);
154 ssb_chipco_irq_mask(&bcm47xx_bus.ssb.chipco, 158 ssb_chipco_irq_mask(&bcm47xx_bus.ssb.chipco,
155 SSB_CHIPCO_IRQ_GPIO, 159 SSB_CHIPCO_IRQ_GPIO,
156 SSB_CHIPCO_IRQ_GPIO); 160 SSB_CHIPCO_IRQ_GPIO);
diff --git a/arch/mips/bcm63xx/Makefile b/arch/mips/bcm63xx/Makefile
index 9bbb30a9dc2..ac2807397c1 100644
--- a/arch/mips/bcm63xx/Makefile
+++ b/arch/mips/bcm63xx/Makefile
@@ -1,6 +1,7 @@
1obj-y += clk.o cpu.o cs.o gpio.o irq.o prom.o setup.o timer.o \ 1obj-y += clk.o cpu.o cs.o gpio.o irq.o nvram.o prom.o reset.o \
2 dev-dsp.o dev-enet.o dev-flash.o dev-pcmcia.o dev-rng.o \ 2 setup.o timer.o dev-dsp.o dev-enet.o dev-flash.o \
3 dev-spi.o dev-uart.o dev-wdt.o dev-usb-usbd.o 3 dev-pcmcia.o dev-rng.o dev-spi.o dev-uart.o dev-wdt.o \
4 dev-usb-usbd.o
4obj-$(CONFIG_EARLY_PRINTK) += early_printk.o 5obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
5 6
6obj-y += boards/ 7obj-y += boards/
diff --git a/arch/mips/bcm63xx/boards/board_bcm963xx.c b/arch/mips/bcm63xx/boards/board_bcm963xx.c
index 1cd4d73f23c..73be9b34969 100644
--- a/arch/mips/bcm63xx/boards/board_bcm963xx.c
+++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c
@@ -18,6 +18,7 @@
18#include <bcm63xx_dev_uart.h> 18#include <bcm63xx_dev_uart.h>
19#include <bcm63xx_regs.h> 19#include <bcm63xx_regs.h>
20#include <bcm63xx_io.h> 20#include <bcm63xx_io.h>
21#include <bcm63xx_nvram.h>
21#include <bcm63xx_dev_pci.h> 22#include <bcm63xx_dev_pci.h>
22#include <bcm63xx_dev_enet.h> 23#include <bcm63xx_dev_enet.h>
23#include <bcm63xx_dev_dsp.h> 24#include <bcm63xx_dev_dsp.h>
@@ -29,8 +30,6 @@
29 30
30#define PFX "board_bcm963xx: " 31#define PFX "board_bcm963xx: "
31 32
32static struct bcm963xx_nvram nvram;
33static unsigned int mac_addr_used;
34static struct board_info board; 33static struct board_info board;
35 34
36/* 35/*
@@ -716,50 +715,14 @@ const char *board_get_name(void)
716} 715}
717 716
718/* 717/*
719 * register & return a new board mac address
720 */
721static int board_get_mac_address(u8 *mac)
722{
723 u8 *oui;
724 int count;
725
726 if (mac_addr_used >= nvram.mac_addr_count) {
727 printk(KERN_ERR PFX "not enough mac address\n");
728 return -ENODEV;
729 }
730
731 memcpy(mac, nvram.mac_addr_base, ETH_ALEN);
732 oui = mac + ETH_ALEN/2 - 1;
733 count = mac_addr_used;
734
735 while (count--) {
736 u8 *p = mac + ETH_ALEN - 1;
737
738 do {
739 (*p)++;
740 if (*p != 0)
741 break;
742 p--;
743 } while (p != oui);
744
745 if (p == oui) {
746 printk(KERN_ERR PFX "unable to fetch mac address\n");
747 return -ENODEV;
748 }
749 }
750
751 mac_addr_used++;
752 return 0;
753}
754
755/*
756 * early init callback, read nvram data from flash and checksum it 718 * early init callback, read nvram data from flash and checksum it
757 */ 719 */
758void __init board_prom_init(void) 720void __init board_prom_init(void)
759{ 721{
760 unsigned int check_len, i; 722 unsigned int i;
761 u8 *boot_addr, *cfe, *p; 723 u8 *boot_addr, *cfe;
762 char cfe_version[32]; 724 char cfe_version[32];
725 char *board_name;
763 u32 val; 726 u32 val;
764 727
765 /* read base address of boot chip select (0) 728 /* read base address of boot chip select (0)
@@ -782,27 +745,15 @@ void __init board_prom_init(void)
782 strcpy(cfe_version, "unknown"); 745 strcpy(cfe_version, "unknown");
783 printk(KERN_INFO PFX "CFE version: %s\n", cfe_version); 746 printk(KERN_INFO PFX "CFE version: %s\n", cfe_version);
784 747
785 /* extract nvram data */ 748 if (bcm63xx_nvram_init(boot_addr + BCM963XX_NVRAM_OFFSET)) {
786 memcpy(&nvram, boot_addr + BCM963XX_NVRAM_OFFSET, sizeof(nvram));
787
788 /* check checksum before using data */
789 if (nvram.version <= 4)
790 check_len = offsetof(struct bcm963xx_nvram, checksum_old);
791 else
792 check_len = sizeof(nvram);
793 val = 0;
794 p = (u8 *)&nvram;
795 while (check_len--)
796 val += *p;
797 if (val) {
798 printk(KERN_ERR PFX "invalid nvram checksum\n"); 749 printk(KERN_ERR PFX "invalid nvram checksum\n");
799 return; 750 return;
800 } 751 }
801 752
753 board_name = bcm63xx_nvram_get_name();
802 /* find board by name */ 754 /* find board by name */
803 for (i = 0; i < ARRAY_SIZE(bcm963xx_boards); i++) { 755 for (i = 0; i < ARRAY_SIZE(bcm963xx_boards); i++) {
804 if (strncmp(nvram.name, bcm963xx_boards[i]->name, 756 if (strncmp(board_name, bcm963xx_boards[i]->name, 16))
805 sizeof(nvram.name)))
806 continue; 757 continue;
807 /* copy, board desc array is marked initdata */ 758 /* copy, board desc array is marked initdata */
808 memcpy(&board, bcm963xx_boards[i], sizeof(board)); 759 memcpy(&board, bcm963xx_boards[i], sizeof(board));
@@ -812,7 +763,7 @@ void __init board_prom_init(void)
812 /* bail out if board is not found, will complain later */ 763 /* bail out if board is not found, will complain later */
813 if (!board.name[0]) { 764 if (!board.name[0]) {
814 char name[17]; 765 char name[17];
815 memcpy(name, nvram.name, 16); 766 memcpy(name, board_name, 16);
816 name[16] = 0; 767 name[16] = 0;
817 printk(KERN_ERR PFX "unknown bcm963xx board: %s\n", 768 printk(KERN_ERR PFX "unknown bcm963xx board: %s\n",
818 name); 769 name);
@@ -890,11 +841,11 @@ int __init board_register_devices(void)
890 bcm63xx_pcmcia_register(); 841 bcm63xx_pcmcia_register();
891 842
892 if (board.has_enet0 && 843 if (board.has_enet0 &&
893 !board_get_mac_address(board.enet0.mac_addr)) 844 !bcm63xx_nvram_get_mac_address(board.enet0.mac_addr))
894 bcm63xx_enet_register(0, &board.enet0); 845 bcm63xx_enet_register(0, &board.enet0);
895 846
896 if (board.has_enet1 && 847 if (board.has_enet1 &&
897 !board_get_mac_address(board.enet1.mac_addr)) 848 !bcm63xx_nvram_get_mac_address(board.enet1.mac_addr))
898 bcm63xx_enet_register(1, &board.enet1); 849 bcm63xx_enet_register(1, &board.enet1);
899 850
900 if (board.has_usbd) 851 if (board.has_usbd)
@@ -907,7 +858,7 @@ int __init board_register_devices(void)
907 * do this after registering enet devices 858 * do this after registering enet devices
908 */ 859 */
909#ifdef CONFIG_SSB_PCIHOST 860#ifdef CONFIG_SSB_PCIHOST
910 if (!board_get_mac_address(bcm63xx_sprom.il0mac)) { 861 if (!bcm63xx_nvram_get_mac_address(bcm63xx_sprom.il0mac)) {
911 memcpy(bcm63xx_sprom.et0mac, bcm63xx_sprom.il0mac, ETH_ALEN); 862 memcpy(bcm63xx_sprom.et0mac, bcm63xx_sprom.il0mac, ETH_ALEN);
912 memcpy(bcm63xx_sprom.et1mac, bcm63xx_sprom.il0mac, ETH_ALEN); 863 memcpy(bcm63xx_sprom.et1mac, bcm63xx_sprom.il0mac, ETH_ALEN);
913 if (ssb_arch_register_fallback_sprom( 864 if (ssb_arch_register_fallback_sprom(
diff --git a/arch/mips/bcm63xx/clk.c b/arch/mips/bcm63xx/clk.c
index dff79ab6005..b9e948d5943 100644
--- a/arch/mips/bcm63xx/clk.c
+++ b/arch/mips/bcm63xx/clk.c
@@ -14,6 +14,7 @@
14#include <bcm63xx_cpu.h> 14#include <bcm63xx_cpu.h>
15#include <bcm63xx_io.h> 15#include <bcm63xx_io.h>
16#include <bcm63xx_regs.h> 16#include <bcm63xx_regs.h>
17#include <bcm63xx_reset.h>
17#include <bcm63xx_clk.h> 18#include <bcm63xx_clk.h>
18 19
19static DEFINE_MUTEX(clocks_mutex); 20static DEFINE_MUTEX(clocks_mutex);
@@ -124,15 +125,10 @@ static void enetsw_set(struct clk *clk, int enable)
124 CKCTL_6368_SWPKT_USB_EN | 125 CKCTL_6368_SWPKT_USB_EN |
125 CKCTL_6368_SWPKT_SAR_EN, enable); 126 CKCTL_6368_SWPKT_SAR_EN, enable);
126 if (enable) { 127 if (enable) {
127 u32 val;
128
129 /* reset switch core afer clock change */ 128 /* reset switch core afer clock change */
130 val = bcm_perf_readl(PERF_SOFTRESET_6368_REG); 129 bcm63xx_core_set_reset(BCM63XX_RESET_ENETSW, 1);
131 val &= ~SOFTRESET_6368_ENETSW_MASK;
132 bcm_perf_writel(val, PERF_SOFTRESET_6368_REG);
133 msleep(10); 130 msleep(10);
134 val |= SOFTRESET_6368_ENETSW_MASK; 131 bcm63xx_core_set_reset(BCM63XX_RESET_ENETSW, 0);
135 bcm_perf_writel(val, PERF_SOFTRESET_6368_REG);
136 msleep(10); 132 msleep(10);
137 } 133 }
138} 134}
@@ -222,15 +218,10 @@ static void xtm_set(struct clk *clk, int enable)
222 CKCTL_6368_SWPKT_SAR_EN, enable); 218 CKCTL_6368_SWPKT_SAR_EN, enable);
223 219
224 if (enable) { 220 if (enable) {
225 u32 val;
226
227 /* reset sar core afer clock change */ 221 /* reset sar core afer clock change */
228 val = bcm_perf_readl(PERF_SOFTRESET_6368_REG); 222 bcm63xx_core_set_reset(BCM63XX_RESET_SAR, 1);
229 val &= ~SOFTRESET_6368_SAR_MASK;
230 bcm_perf_writel(val, PERF_SOFTRESET_6368_REG);
231 mdelay(1); 223 mdelay(1);
232 val |= SOFTRESET_6368_SAR_MASK; 224 bcm63xx_core_set_reset(BCM63XX_RESET_SAR, 0);
233 bcm_perf_writel(val, PERF_SOFTRESET_6368_REG);
234 mdelay(1); 225 mdelay(1);
235 } 226 }
236} 227}
@@ -253,6 +244,19 @@ static struct clk clk_ipsec = {
253}; 244};
254 245
255/* 246/*
247 * PCIe clock
248 */
249
250static void pcie_set(struct clk *clk, int enable)
251{
252 bcm_hwclock_set(CKCTL_6328_PCIE_EN, enable);
253}
254
255static struct clk clk_pcie = {
256 .set = pcie_set,
257};
258
259/*
256 * Internal peripheral clock 260 * Internal peripheral clock
257 */ 261 */
258static struct clk clk_periph = { 262static struct clk clk_periph = {
@@ -313,6 +317,8 @@ struct clk *clk_get(struct device *dev, const char *id)
313 return &clk_pcm; 317 return &clk_pcm;
314 if (BCMCPU_IS_6368() && !strcmp(id, "ipsec")) 318 if (BCMCPU_IS_6368() && !strcmp(id, "ipsec"))
315 return &clk_ipsec; 319 return &clk_ipsec;
320 if (BCMCPU_IS_6328() && !strcmp(id, "pcie"))
321 return &clk_pcie;
316 return ERR_PTR(-ENOENT); 322 return ERR_PTR(-ENOENT);
317} 323}
318 324
diff --git a/arch/mips/bcm63xx/nvram.c b/arch/mips/bcm63xx/nvram.c
new file mode 100644
index 00000000000..62061168083
--- /dev/null
+++ b/arch/mips/bcm63xx/nvram.c
@@ -0,0 +1,107 @@
1/*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
6 * Copyright (C) 2008 Maxime Bizon <mbizon@freebox.fr>
7 * Copyright (C) 2008 Florian Fainelli <florian@openwrt.org>
8 * Copyright (C) 2012 Jonas Gorski <jonas.gorski@gmail.com>
9 */
10
11#define pr_fmt(fmt) "bcm63xx_nvram: " fmt
12
13#include <linux/init.h>
14#include <linux/crc32.h>
15#include <linux/export.h>
16#include <linux/kernel.h>
17#include <linux/if_ether.h>
18
19#include <bcm63xx_nvram.h>
20
21/*
22 * nvram structure
23 */
24struct bcm963xx_nvram {
25 u32 version;
26 u8 reserved1[256];
27 u8 name[16];
28 u32 main_tp_number;
29 u32 psi_size;
30 u32 mac_addr_count;
31 u8 mac_addr_base[ETH_ALEN];
32 u8 reserved2[2];
33 u32 checksum_old;
34 u8 reserved3[720];
35 u32 checksum_high;
36};
37
38static struct bcm963xx_nvram nvram;
39static int mac_addr_used;
40
41int __init bcm63xx_nvram_init(void *addr)
42{
43 unsigned int check_len;
44 u32 crc, expected_crc;
45
46 /* extract nvram data */
47 memcpy(&nvram, addr, sizeof(nvram));
48
49 /* check checksum before using data */
50 if (nvram.version <= 4) {
51 check_len = offsetof(struct bcm963xx_nvram, reserved3);
52 expected_crc = nvram.checksum_old;
53 nvram.checksum_old = 0;
54 } else {
55 check_len = sizeof(nvram);
56 expected_crc = nvram.checksum_high;
57 nvram.checksum_high = 0;
58 }
59
60 crc = crc32_le(~0, (u8 *)&nvram, check_len);
61
62 if (crc != expected_crc)
63 return -EINVAL;
64
65 return 0;
66}
67
68u8 *bcm63xx_nvram_get_name(void)
69{
70 return nvram.name;
71}
72EXPORT_SYMBOL(bcm63xx_nvram_get_name);
73
74int bcm63xx_nvram_get_mac_address(u8 *mac)
75{
76 u8 *oui;
77 int count;
78
79 if (mac_addr_used >= nvram.mac_addr_count) {
80 pr_err("not enough mac addresses\n");
81 return -ENODEV;
82 }
83
84 memcpy(mac, nvram.mac_addr_base, ETH_ALEN);
85 oui = mac + ETH_ALEN/2 - 1;
86 count = mac_addr_used;
87
88 while (count--) {
89 u8 *p = mac + ETH_ALEN - 1;
90
91 do {
92 (*p)++;
93 if (*p != 0)
94 break;
95 p--;
96 } while (p != oui);
97
98 if (p == oui) {
99 pr_err("unable to fetch mac address\n");
100 return -ENODEV;
101 }
102 }
103
104 mac_addr_used++;
105 return 0;
106}
107EXPORT_SYMBOL(bcm63xx_nvram_get_mac_address);
diff --git a/arch/mips/bcm63xx/reset.c b/arch/mips/bcm63xx/reset.c
new file mode 100644
index 00000000000..68a31bb90cb
--- /dev/null
+++ b/arch/mips/bcm63xx/reset.c
@@ -0,0 +1,223 @@
1/*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
6 * Copyright (C) 2012 Jonas Gorski <jonas.gorski@gmail.com>
7 */
8
9#include <linux/module.h>
10#include <linux/mutex.h>
11#include <linux/err.h>
12#include <linux/clk.h>
13#include <linux/delay.h>
14#include <bcm63xx_cpu.h>
15#include <bcm63xx_io.h>
16#include <bcm63xx_regs.h>
17#include <bcm63xx_reset.h>
18
19#define __GEN_RESET_BITS_TABLE(__cpu) \
20 [BCM63XX_RESET_SPI] = BCM## __cpu ##_RESET_SPI, \
21 [BCM63XX_RESET_ENET] = BCM## __cpu ##_RESET_ENET, \
22 [BCM63XX_RESET_USBH] = BCM## __cpu ##_RESET_USBH, \
23 [BCM63XX_RESET_USBD] = BCM## __cpu ##_RESET_USBD, \
24 [BCM63XX_RESET_DSL] = BCM## __cpu ##_RESET_DSL, \
25 [BCM63XX_RESET_SAR] = BCM## __cpu ##_RESET_SAR, \
26 [BCM63XX_RESET_EPHY] = BCM## __cpu ##_RESET_EPHY, \
27 [BCM63XX_RESET_ENETSW] = BCM## __cpu ##_RESET_ENETSW, \
28 [BCM63XX_RESET_PCM] = BCM## __cpu ##_RESET_PCM, \
29 [BCM63XX_RESET_MPI] = BCM## __cpu ##_RESET_MPI, \
30 [BCM63XX_RESET_PCIE] = BCM## __cpu ##_RESET_PCIE, \
31 [BCM63XX_RESET_PCIE_EXT] = BCM## __cpu ##_RESET_PCIE_EXT,
32
33#define BCM6328_RESET_SPI SOFTRESET_6328_SPI_MASK
34#define BCM6328_RESET_ENET 0
35#define BCM6328_RESET_USBH SOFTRESET_6328_USBH_MASK
36#define BCM6328_RESET_USBD SOFTRESET_6328_USBS_MASK
37#define BCM6328_RESET_DSL 0
38#define BCM6328_RESET_SAR SOFTRESET_6328_SAR_MASK
39#define BCM6328_RESET_EPHY SOFTRESET_6328_EPHY_MASK
40#define BCM6328_RESET_ENETSW SOFTRESET_6328_ENETSW_MASK
41#define BCM6328_RESET_PCM SOFTRESET_6328_PCM_MASK
42#define BCM6328_RESET_MPI 0
43#define BCM6328_RESET_PCIE \
44 (SOFTRESET_6328_PCIE_MASK | \
45 SOFTRESET_6328_PCIE_CORE_MASK | \
46 SOFTRESET_6328_PCIE_HARD_MASK)
47#define BCM6328_RESET_PCIE_EXT SOFTRESET_6328_PCIE_EXT_MASK
48
49#define BCM6338_RESET_SPI SOFTRESET_6338_SPI_MASK
50#define BCM6338_RESET_ENET SOFTRESET_6338_ENET_MASK
51#define BCM6338_RESET_USBH SOFTRESET_6338_USBH_MASK
52#define BCM6338_RESET_USBD SOFTRESET_6338_USBS_MASK
53#define BCM6338_RESET_DSL SOFTRESET_6338_ADSL_MASK
54#define BCM6338_RESET_SAR SOFTRESET_6338_SAR_MASK
55#define BCM6338_RESET_EPHY 0
56#define BCM6338_RESET_ENETSW 0
57#define BCM6338_RESET_PCM 0
58#define BCM6338_RESET_MPI 0
59#define BCM6338_RESET_PCIE 0
60#define BCM6338_RESET_PCIE_EXT 0
61
62#define BCM6348_RESET_SPI SOFTRESET_6348_SPI_MASK
63#define BCM6348_RESET_ENET SOFTRESET_6348_ENET_MASK
64#define BCM6348_RESET_USBH SOFTRESET_6348_USBH_MASK
65#define BCM6348_RESET_USBD SOFTRESET_6348_USBS_MASK
66#define BCM6348_RESET_DSL SOFTRESET_6348_ADSL_MASK
67#define BCM6348_RESET_SAR SOFTRESET_6348_SAR_MASK
68#define BCM6348_RESET_EPHY 0
69#define BCM6348_RESET_ENETSW 0
70#define BCM6348_RESET_PCM 0
71#define BCM6348_RESET_MPI 0
72#define BCM6348_RESET_PCIE 0
73#define BCM6348_RESET_PCIE_EXT 0
74
75#define BCM6358_RESET_SPI SOFTRESET_6358_SPI_MASK
76#define BCM6358_RESET_ENET SOFTRESET_6358_ENET_MASK
77#define BCM6358_RESET_USBH SOFTRESET_6358_USBH_MASK
78#define BCM6358_RESET_USBD 0
79#define BCM6358_RESET_DSL SOFTRESET_6358_ADSL_MASK
80#define BCM6358_RESET_SAR SOFTRESET_6358_SAR_MASK
81#define BCM6358_RESET_EPHY SOFTRESET_6358_EPHY_MASK
82#define BCM6358_RESET_ENETSW 0
83#define BCM6358_RESET_PCM SOFTRESET_6358_PCM_MASK
84#define BCM6358_RESET_MPI SOFTRESET_6358_MPI_MASK
85#define BCM6358_RESET_PCIE 0
86#define BCM6358_RESET_PCIE_EXT 0
87
88#define BCM6368_RESET_SPI SOFTRESET_6368_SPI_MASK
89#define BCM6368_RESET_ENET 0
90#define BCM6368_RESET_USBH SOFTRESET_6368_USBH_MASK
91#define BCM6368_RESET_USBD SOFTRESET_6368_USBS_MASK
92#define BCM6368_RESET_DSL 0
93#define BCM6368_RESET_SAR SOFTRESET_6368_SAR_MASK
94#define BCM6368_RESET_EPHY SOFTRESET_6368_EPHY_MASK
95#define BCM6368_RESET_ENETSW 0
96#define BCM6368_RESET_PCM SOFTRESET_6368_PCM_MASK
97#define BCM6368_RESET_MPI SOFTRESET_6368_MPI_MASK
98#define BCM6368_RESET_PCIE 0
99#define BCM6368_RESET_PCIE_EXT 0
100
101#ifdef BCMCPU_RUNTIME_DETECT
102
103/*
104 * core reset bits
105 */
106static const u32 bcm6328_reset_bits[] = {
107 __GEN_RESET_BITS_TABLE(6328)
108};
109
110static const u32 bcm6338_reset_bits[] = {
111 __GEN_RESET_BITS_TABLE(6338)
112};
113
114static const u32 bcm6348_reset_bits[] = {
115 __GEN_RESET_BITS_TABLE(6348)
116};
117
118static const u32 bcm6358_reset_bits[] = {
119 __GEN_RESET_BITS_TABLE(6358)
120};
121
122static const u32 bcm6368_reset_bits[] = {
123 __GEN_RESET_BITS_TABLE(6368)
124};
125
126const u32 *bcm63xx_reset_bits;
127static int reset_reg;
128
129static int __init bcm63xx_reset_bits_init(void)
130{
131 if (BCMCPU_IS_6328()) {
132 reset_reg = PERF_SOFTRESET_6328_REG;
133 bcm63xx_reset_bits = bcm6328_reset_bits;
134 } else if (BCMCPU_IS_6338()) {
135 reset_reg = PERF_SOFTRESET_REG;
136 bcm63xx_reset_bits = bcm6338_reset_bits;
137 } else if (BCMCPU_IS_6348()) {
138 reset_reg = PERF_SOFTRESET_REG;
139 bcm63xx_reset_bits = bcm6348_reset_bits;
140 } else if (BCMCPU_IS_6358()) {
141 reset_reg = PERF_SOFTRESET_6358_REG;
142 bcm63xx_reset_bits = bcm6358_reset_bits;
143 } else if (BCMCPU_IS_6368()) {
144 reset_reg = PERF_SOFTRESET_6368_REG;
145 bcm63xx_reset_bits = bcm6368_reset_bits;
146 }
147
148 return 0;
149}
150#else
151
152#ifdef CONFIG_BCM63XX_CPU_6328
153static const u32 bcm63xx_reset_bits[] = {
154 __GEN_RESET_BITS_TABLE(6328)
155};
156#define reset_reg PERF_SOFTRESET_6328_REG
157#endif
158
159#ifdef CONFIG_BCM63XX_CPU_6338
160static const u32 bcm63xx_reset_bits[] = {
161 __GEN_RESET_BITS_TABLE(6338)
162};
163#define reset_reg PERF_SOFTRESET_REG
164#endif
165
166#ifdef CONFIG_BCM63XX_CPU_6345
167static const u32 bcm63xx_reset_bits[] = { };
168#define reset_reg 0
169#endif
170
171#ifdef CONFIG_BCM63XX_CPU_6348
172static const u32 bcm63xx_reset_bits[] = {
173 __GEN_RESET_BITS_TABLE(6348)
174};
175#define reset_reg PERF_SOFTRESET_REG
176#endif
177
178#ifdef CONFIG_BCM63XX_CPU_6358
179static const u32 bcm63xx_reset_bits[] = {
180 __GEN_RESET_BITS_TABLE(6358)
181};
182#define reset_reg PERF_SOFTRESET_6358_REG
183#endif
184
185#ifdef CONFIG_BCM63XX_CPU_6368
186static const u32 bcm63xx_reset_bits[] = {
187 __GEN_RESET_BITS_TABLE(6368)
188};
189#define reset_reg PERF_SOFTRESET_6368_REG
190#endif
191
192static int __init bcm63xx_reset_bits_init(void) { return 0; }
193#endif
194
195static DEFINE_SPINLOCK(reset_mutex);
196
197static void __bcm63xx_core_set_reset(u32 mask, int enable)
198{
199 unsigned long flags;
200 u32 val;
201
202 if (!mask)
203 return;
204
205 spin_lock_irqsave(&reset_mutex, flags);
206 val = bcm_perf_readl(reset_reg);
207
208 if (enable)
209 val &= ~mask;
210 else
211 val |= mask;
212
213 bcm_perf_writel(val, reset_reg);
214 spin_unlock_irqrestore(&reset_mutex, flags);
215}
216
217void bcm63xx_core_set_reset(enum bcm63xx_core_reset core, int reset)
218{
219 __bcm63xx_core_set_reset(bcm63xx_reset_bits[core], reset);
220}
221EXPORT_SYMBOL(bcm63xx_core_set_reset);
222
223postcore_initcall(bcm63xx_reset_bits_init);
diff --git a/arch/mips/cavium-octeon/flash_setup.c b/arch/mips/cavium-octeon/flash_setup.c
index e44a55bc7f0..237e5b1a72d 100644
--- a/arch/mips/cavium-octeon/flash_setup.c
+++ b/arch/mips/cavium-octeon/flash_setup.c
@@ -51,7 +51,8 @@ static int __init flash_init(void)
51 flash_map.name = "phys_mapped_flash"; 51 flash_map.name = "phys_mapped_flash";
52 flash_map.phys = region_cfg.s.base << 16; 52 flash_map.phys = region_cfg.s.base << 16;
53 flash_map.size = 0x1fc00000 - flash_map.phys; 53 flash_map.size = 0x1fc00000 - flash_map.phys;
54 flash_map.bankwidth = 1; 54 /* 8-bit bus (0 + 1) or 16-bit bus (1 + 1) */
55 flash_map.bankwidth = region_cfg.s.width + 1;
55 flash_map.virt = ioremap(flash_map.phys, flash_map.size); 56 flash_map.virt = ioremap(flash_map.phys, flash_map.size);
56 pr_notice("Bootbus flash: Setting flash for %luMB flash at " 57 pr_notice("Bootbus flash: Setting flash for %luMB flash at "
57 "0x%08llx\n", flash_map.size >> 20, flash_map.phys); 58 "0x%08llx\n", flash_map.size >> 20, flash_map.phys);
diff --git a/arch/mips/configs/ath79_defconfig b/arch/mips/configs/ath79_defconfig
new file mode 100644
index 00000000000..ea87d43ba60
--- /dev/null
+++ b/arch/mips/configs/ath79_defconfig
@@ -0,0 +1,111 @@
1CONFIG_ATH79=y
2CONFIG_ATH79_MACH_AP121=y
3CONFIG_ATH79_MACH_AP81=y
4CONFIG_ATH79_MACH_DB120=y
5CONFIG_ATH79_MACH_PB44=y
6CONFIG_ATH79_MACH_UBNT_XM=y
7CONFIG_HZ_100=y
8# CONFIG_SECCOMP is not set
9CONFIG_EXPERIMENTAL=y
10# CONFIG_LOCALVERSION_AUTO is not set
11CONFIG_SYSVIPC=y
12CONFIG_HIGH_RES_TIMERS=y
13CONFIG_BLK_DEV_INITRD=y
14# CONFIG_RD_GZIP is not set
15CONFIG_RD_LZMA=y
16# CONFIG_KALLSYMS is not set
17# CONFIG_AIO is not set
18CONFIG_EMBEDDED=y
19# CONFIG_VM_EVENT_COUNTERS is not set
20# CONFIG_SLUB_DEBUG is not set
21# CONFIG_COMPAT_BRK is not set
22CONFIG_MODULES=y
23CONFIG_MODULE_UNLOAD=y
24# CONFIG_BLK_DEV_BSG is not set
25# CONFIG_IOSCHED_CFQ is not set
26CONFIG_PCI=y
27# CONFIG_SUSPEND is not set
28CONFIG_NET=y
29CONFIG_PACKET=y
30CONFIG_UNIX=y
31CONFIG_INET=y
32CONFIG_IP_MULTICAST=y
33CONFIG_IP_ADVANCED_ROUTER=y
34# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
35# CONFIG_INET_XFRM_MODE_TUNNEL is not set
36# CONFIG_INET_XFRM_MODE_BEET is not set
37# CONFIG_INET_LRO is not set
38# CONFIG_IPV6 is not set
39CONFIG_CFG80211=m
40CONFIG_MAC80211=m
41CONFIG_MAC80211_DEBUGFS=y
42CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
43# CONFIG_FIRMWARE_IN_KERNEL is not set
44CONFIG_MTD=y
45CONFIG_MTD_REDBOOT_PARTS=y
46CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-2
47CONFIG_MTD_CMDLINE_PARTS=y
48CONFIG_MTD_CHAR=y
49CONFIG_MTD_BLOCK=y
50CONFIG_MTD_CFI=y
51CONFIG_MTD_JEDECPROBE=y
52CONFIG_MTD_CFI_AMDSTD=y
53CONFIG_MTD_COMPLEX_MAPPINGS=y
54CONFIG_MTD_PHYSMAP=y
55CONFIG_MTD_M25P80=y
56# CONFIG_M25PXX_USE_FAST_READ is not set
57CONFIG_NETDEVICES=y
58# CONFIG_NET_PACKET_ENGINE is not set
59CONFIG_ATH_COMMON=m
60CONFIG_ATH9K=m
61CONFIG_ATH9K_AHB=y
62CONFIG_INPUT=m
63# CONFIG_INPUT_MOUSEDEV is not set
64# CONFIG_KEYBOARD_ATKBD is not set
65CONFIG_KEYBOARD_GPIO_POLLED=m
66# CONFIG_INPUT_MOUSE is not set
67CONFIG_INPUT_MISC=y
68# CONFIG_SERIO is not set
69# CONFIG_VT is not set
70# CONFIG_LEGACY_PTYS is not set
71# CONFIG_DEVKMEM is not set
72CONFIG_SERIAL_8250=y
73CONFIG_SERIAL_8250_CONSOLE=y
74# CONFIG_SERIAL_8250_PCI is not set
75CONFIG_SERIAL_8250_NR_UARTS=1
76CONFIG_SERIAL_8250_RUNTIME_UARTS=1
77CONFIG_SERIAL_AR933X=y
78CONFIG_SERIAL_AR933X_CONSOLE=y
79# CONFIG_HW_RANDOM is not set
80CONFIG_I2C=y
81# CONFIG_I2C_COMPAT is not set
82# CONFIG_I2C_HELPER_AUTO is not set
83CONFIG_I2C_GPIO=y
84CONFIG_SPI=y
85CONFIG_SPI_ATH79=y
86CONFIG_SPI_GPIO=y
87CONFIG_GPIO_SYSFS=y
88CONFIG_GPIO_PCF857X=y
89# CONFIG_HWMON is not set
90CONFIG_WATCHDOG=y
91CONFIG_ATH79_WDT=y
92# CONFIG_VGA_ARB is not set
93# CONFIG_HID is not set
94# CONFIG_USB_HID is not set
95CONFIG_USB=y
96CONFIG_USB_EHCI_HCD=y
97# CONFIG_USB_EHCI_TT_NEWSCHED is not set
98CONFIG_USB_OHCI_HCD=y
99CONFIG_LEDS_CLASS=y
100CONFIG_LEDS_GPIO=y
101# CONFIG_IOMMU_SUPPORT is not set
102# CONFIG_DNOTIFY is not set
103# CONFIG_PROC_PAGE_MONITOR is not set
104# CONFIG_ENABLE_MUST_CHECK is not set
105CONFIG_STRIP_ASM_SYMS=y
106CONFIG_DEBUG_FS=y
107# CONFIG_SCHED_DEBUG is not set
108# CONFIG_FTRACE is not set
109CONFIG_CRYPTO=y
110# CONFIG_CRYPTO_ANSI_CPRNG is not set
111CONFIG_CRC_ITU_T=m
diff --git a/arch/mips/include/asm/mach-bcm47xx/bcm47xx.h b/arch/mips/include/asm/mach-bcm47xx/bcm47xx.h
index 26fdaf40b93..cc7563ba1cb 100644
--- a/arch/mips/include/asm/mach-bcm47xx/bcm47xx.h
+++ b/arch/mips/include/asm/mach-bcm47xx/bcm47xx.h
@@ -44,8 +44,8 @@ union bcm47xx_bus {
44extern union bcm47xx_bus bcm47xx_bus; 44extern union bcm47xx_bus bcm47xx_bus;
45extern enum bcm47xx_bus_type bcm47xx_bus_type; 45extern enum bcm47xx_bus_type bcm47xx_bus_type;
46 46
47void bcm47xx_fill_sprom(struct ssb_sprom *sprom, const char *prefix); 47void bcm47xx_fill_sprom(struct ssb_sprom *sprom, const char *prefix,
48void bcm47xx_fill_sprom_ethernet(struct ssb_sprom *sprom, const char *prefix); 48 bool fallback);
49 49
50#ifdef CONFIG_BCM47XX_SSB 50#ifdef CONFIG_BCM47XX_SSB
51void bcm47xx_fill_ssb_boardinfo(struct ssb_boardinfo *boardinfo, 51void bcm47xx_fill_ssb_boardinfo(struct ssb_boardinfo *boardinfo,
diff --git a/arch/mips/include/asm/mach-bcm47xx/gpio.h b/arch/mips/include/asm/mach-bcm47xx/gpio.h
index 2ef17e8df40..90daefa24a4 100644
--- a/arch/mips/include/asm/mach-bcm47xx/gpio.h
+++ b/arch/mips/include/asm/mach-bcm47xx/gpio.h
@@ -1,155 +1,17 @@
1/* 1#ifndef __ASM_MIPS_MACH_BCM47XX_GPIO_H
2 * This file is subject to the terms and conditions of the GNU General Public 2#define __ASM_MIPS_MACH_BCM47XX_GPIO_H
3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
6 * Copyright (C) 2007 Aurelien Jarno <aurelien@aurel32.net>
7 */
8 3
9#ifndef __BCM47XX_GPIO_H 4#include <asm-generic/gpio.h>
10#define __BCM47XX_GPIO_H
11 5
12#include <linux/ssb/ssb_embedded.h> 6#define gpio_get_value __gpio_get_value
13#include <linux/bcma/bcma.h> 7#define gpio_set_value __gpio_set_value
14#include <asm/mach-bcm47xx/bcm47xx.h>
15 8
16#define BCM47XX_EXTIF_GPIO_LINES 5 9#define gpio_cansleep __gpio_cansleep
17#define BCM47XX_CHIPCO_GPIO_LINES 16 10#define gpio_to_irq __gpio_to_irq
18 11
19extern int gpio_request(unsigned gpio, const char *label); 12static inline int irq_to_gpio(unsigned int irq)
20extern void gpio_free(unsigned gpio);
21extern int gpio_to_irq(unsigned gpio);
22
23static inline int gpio_get_value(unsigned gpio)
24{ 13{
25 switch (bcm47xx_bus_type) {
26#ifdef CONFIG_BCM47XX_SSB
27 case BCM47XX_BUS_TYPE_SSB:
28 return ssb_gpio_in(&bcm47xx_bus.ssb, 1 << gpio);
29#endif
30#ifdef CONFIG_BCM47XX_BCMA
31 case BCM47XX_BUS_TYPE_BCMA:
32 return bcma_chipco_gpio_in(&bcm47xx_bus.bcma.bus.drv_cc,
33 1 << gpio);
34#endif
35 }
36 return -EINVAL; 14 return -EINVAL;
37} 15}
38 16
39#define gpio_get_value_cansleep gpio_get_value
40
41static inline void gpio_set_value(unsigned gpio, int value)
42{
43 switch (bcm47xx_bus_type) {
44#ifdef CONFIG_BCM47XX_SSB
45 case BCM47XX_BUS_TYPE_SSB:
46 ssb_gpio_out(&bcm47xx_bus.ssb, 1 << gpio,
47 value ? 1 << gpio : 0);
48 return;
49#endif
50#ifdef CONFIG_BCM47XX_BCMA
51 case BCM47XX_BUS_TYPE_BCMA:
52 bcma_chipco_gpio_out(&bcm47xx_bus.bcma.bus.drv_cc, 1 << gpio,
53 value ? 1 << gpio : 0);
54 return;
55#endif 17#endif
56 }
57}
58
59#define gpio_set_value_cansleep gpio_set_value
60
61static inline int gpio_cansleep(unsigned gpio)
62{
63 return 0;
64}
65
66static inline int gpio_is_valid(unsigned gpio)
67{
68 return gpio < (BCM47XX_EXTIF_GPIO_LINES + BCM47XX_CHIPCO_GPIO_LINES);
69}
70
71
72static inline int gpio_direction_input(unsigned gpio)
73{
74 switch (bcm47xx_bus_type) {
75#ifdef CONFIG_BCM47XX_SSB
76 case BCM47XX_BUS_TYPE_SSB:
77 ssb_gpio_outen(&bcm47xx_bus.ssb, 1 << gpio, 0);
78 return 0;
79#endif
80#ifdef CONFIG_BCM47XX_BCMA
81 case BCM47XX_BUS_TYPE_BCMA:
82 bcma_chipco_gpio_outen(&bcm47xx_bus.bcma.bus.drv_cc, 1 << gpio,
83 0);
84 return 0;
85#endif
86 }
87 return -EINVAL;
88}
89
90static inline int gpio_direction_output(unsigned gpio, int value)
91{
92 switch (bcm47xx_bus_type) {
93#ifdef CONFIG_BCM47XX_SSB
94 case BCM47XX_BUS_TYPE_SSB:
95 /* first set the gpio out value */
96 ssb_gpio_out(&bcm47xx_bus.ssb, 1 << gpio,
97 value ? 1 << gpio : 0);
98 /* then set the gpio mode */
99 ssb_gpio_outen(&bcm47xx_bus.ssb, 1 << gpio, 1 << gpio);
100 return 0;
101#endif
102#ifdef CONFIG_BCM47XX_BCMA
103 case BCM47XX_BUS_TYPE_BCMA:
104 /* first set the gpio out value */
105 bcma_chipco_gpio_out(&bcm47xx_bus.bcma.bus.drv_cc, 1 << gpio,
106 value ? 1 << gpio : 0);
107 /* then set the gpio mode */
108 bcma_chipco_gpio_outen(&bcm47xx_bus.bcma.bus.drv_cc, 1 << gpio,
109 1 << gpio);
110 return 0;
111#endif
112 }
113 return -EINVAL;
114}
115
116static inline int gpio_intmask(unsigned gpio, int value)
117{
118 switch (bcm47xx_bus_type) {
119#ifdef CONFIG_BCM47XX_SSB
120 case BCM47XX_BUS_TYPE_SSB:
121 ssb_gpio_intmask(&bcm47xx_bus.ssb, 1 << gpio,
122 value ? 1 << gpio : 0);
123 return 0;
124#endif
125#ifdef CONFIG_BCM47XX_BCMA
126 case BCM47XX_BUS_TYPE_BCMA:
127 bcma_chipco_gpio_intmask(&bcm47xx_bus.bcma.bus.drv_cc,
128 1 << gpio, value ? 1 << gpio : 0);
129 return 0;
130#endif
131 }
132 return -EINVAL;
133}
134
135static inline int gpio_polarity(unsigned gpio, int value)
136{
137 switch (bcm47xx_bus_type) {
138#ifdef CONFIG_BCM47XX_SSB
139 case BCM47XX_BUS_TYPE_SSB:
140 ssb_gpio_polarity(&bcm47xx_bus.ssb, 1 << gpio,
141 value ? 1 << gpio : 0);
142 return 0;
143#endif
144#ifdef CONFIG_BCM47XX_BCMA
145 case BCM47XX_BUS_TYPE_BCMA:
146 bcma_chipco_gpio_polarity(&bcm47xx_bus.bcma.bus.drv_cc,
147 1 << gpio, value ? 1 << gpio : 0);
148 return 0;
149#endif
150 }
151 return -EINVAL;
152}
153
154
155#endif /* __BCM47XX_GPIO_H */
diff --git a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_nvram.h b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_nvram.h
new file mode 100644
index 00000000000..62d6a3b4d3b
--- /dev/null
+++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_nvram.h
@@ -0,0 +1,35 @@
1#ifndef BCM63XX_NVRAM_H
2#define BCM63XX_NVRAM_H
3
4#include <linux/types.h>
5
6/**
7 * bcm63xx_nvram_init() - initializes nvram
8 * @nvram: address of the nvram data
9 *
10 * Initialized the local nvram copy from the target address and checks
11 * its checksum.
12 *
13 * Returns 0 on success.
14 */
15int __init bcm63xx_nvram_init(void *nvram);
16
17/**
18 * bcm63xx_nvram_get_name() - returns the board name according to nvram
19 *
20 * Returns the board name field from nvram. Note that it might not be
21 * null terminated if it is exactly 16 bytes long.
22 */
23u8 *bcm63xx_nvram_get_name(void);
24
25/**
26 * bcm63xx_nvram_get_mac_address() - register & return a new mac address
27 * @mac: pointer to array for allocated mac
28 *
29 * Registers and returns a mac address from the allocated macs from nvram.
30 *
31 * Returns 0 on success.
32 */
33int bcm63xx_nvram_get_mac_address(u8 *mac);
34
35#endif /* BCM63XX_NVRAM_H */
diff --git a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
index 12963d05da8..c3eeb90b480 100644
--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
+++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
@@ -53,13 +53,18 @@
53 CKCTL_6338_SAR_EN | \ 53 CKCTL_6338_SAR_EN | \
54 CKCTL_6338_SPI_EN) 54 CKCTL_6338_SPI_EN)
55 55
56#define CKCTL_6345_CPU_EN (1 << 0) 56/* BCM6345 clock bits are shifted by 16 on the left, because of the test
57#define CKCTL_6345_BUS_EN (1 << 1) 57 * control register which is 16-bits wide. That way we do not have any
58#define CKCTL_6345_EBI_EN (1 << 2) 58 * specific BCM6345 code for handling clocks, and writing 0 to the test
59#define CKCTL_6345_UART_EN (1 << 3) 59 * control register is fine.
60#define CKCTL_6345_ADSLPHY_EN (1 << 4) 60 */
61#define CKCTL_6345_ENET_EN (1 << 7) 61#define CKCTL_6345_CPU_EN (1 << 16)
62#define CKCTL_6345_USBH_EN (1 << 8) 62#define CKCTL_6345_BUS_EN (1 << 17)
63#define CKCTL_6345_EBI_EN (1 << 18)
64#define CKCTL_6345_UART_EN (1 << 19)
65#define CKCTL_6345_ADSLPHY_EN (1 << 20)
66#define CKCTL_6345_ENET_EN (1 << 23)
67#define CKCTL_6345_USBH_EN (1 << 24)
63 68
64#define CKCTL_6345_ALL_SAFE_EN (CKCTL_6345_ENET_EN | \ 69#define CKCTL_6345_ALL_SAFE_EN (CKCTL_6345_ENET_EN | \
65 CKCTL_6345_USBH_EN | \ 70 CKCTL_6345_USBH_EN | \
@@ -191,6 +196,7 @@
191/* Soft Reset register */ 196/* Soft Reset register */
192#define PERF_SOFTRESET_REG 0x28 197#define PERF_SOFTRESET_REG 0x28
193#define PERF_SOFTRESET_6328_REG 0x10 198#define PERF_SOFTRESET_6328_REG 0x10
199#define PERF_SOFTRESET_6358_REG 0x34
194#define PERF_SOFTRESET_6368_REG 0x10 200#define PERF_SOFTRESET_6368_REG 0x10
195 201
196#define SOFTRESET_6328_SPI_MASK (1 << 0) 202#define SOFTRESET_6328_SPI_MASK (1 << 0)
@@ -244,6 +250,15 @@
244 SOFTRESET_6348_ACLC_MASK | \ 250 SOFTRESET_6348_ACLC_MASK | \
245 SOFTRESET_6348_ADSLMIPSPLL_MASK) 251 SOFTRESET_6348_ADSLMIPSPLL_MASK)
246 252
253#define SOFTRESET_6358_SPI_MASK (1 << 0)
254#define SOFTRESET_6358_ENET_MASK (1 << 2)
255#define SOFTRESET_6358_MPI_MASK (1 << 3)
256#define SOFTRESET_6358_EPHY_MASK (1 << 6)
257#define SOFTRESET_6358_SAR_MASK (1 << 7)
258#define SOFTRESET_6358_USBH_MASK (1 << 12)
259#define SOFTRESET_6358_PCM_MASK (1 << 13)
260#define SOFTRESET_6358_ADSL_MASK (1 << 14)
261
247#define SOFTRESET_6368_SPI_MASK (1 << 0) 262#define SOFTRESET_6368_SPI_MASK (1 << 0)
248#define SOFTRESET_6368_MPI_MASK (1 << 3) 263#define SOFTRESET_6368_MPI_MASK (1 << 3)
249#define SOFTRESET_6368_EPHY_MASK (1 << 6) 264#define SOFTRESET_6368_EPHY_MASK (1 << 6)
diff --git a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_reset.h b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_reset.h
new file mode 100644
index 00000000000..3a6eb9c1adc
--- /dev/null
+++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_reset.h
@@ -0,0 +1,21 @@
1#ifndef __BCM63XX_RESET_H
2#define __BCM63XX_RESET_H
3
4enum bcm63xx_core_reset {
5 BCM63XX_RESET_SPI,
6 BCM63XX_RESET_ENET,
7 BCM63XX_RESET_USBH,
8 BCM63XX_RESET_USBD,
9 BCM63XX_RESET_SAR,
10 BCM63XX_RESET_DSL,
11 BCM63XX_RESET_EPHY,
12 BCM63XX_RESET_ENETSW,
13 BCM63XX_RESET_PCM,
14 BCM63XX_RESET_MPI,
15 BCM63XX_RESET_PCIE,
16 BCM63XX_RESET_PCIE_EXT,
17};
18
19void bcm63xx_core_set_reset(enum bcm63xx_core_reset, int reset);
20
21#endif
diff --git a/arch/mips/include/asm/mach-bcm63xx/board_bcm963xx.h b/arch/mips/include/asm/mach-bcm63xx/board_bcm963xx.h
index b0dd4bb53f7..682bcf3b492 100644
--- a/arch/mips/include/asm/mach-bcm63xx/board_bcm963xx.h
+++ b/arch/mips/include/asm/mach-bcm63xx/board_bcm963xx.h
@@ -15,23 +15,6 @@
15#define BCM963XX_NVRAM_OFFSET 0x580 15#define BCM963XX_NVRAM_OFFSET 0x580
16 16
17/* 17/*
18 * nvram structure
19 */
20struct bcm963xx_nvram {
21 u32 version;
22 u8 reserved1[256];
23 u8 name[16];
24 u32 main_tp_number;
25 u32 psi_size;
26 u32 mac_addr_count;
27 u8 mac_addr_base[6];
28 u8 reserved2[2];
29 u32 checksum_old;
30 u8 reserved3[720];
31 u32 checksum_high;
32};
33
34/*
35 * board definition 18 * board definition
36 */ 19 */
37struct board_info { 20struct board_info {
diff --git a/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h b/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
index 6a2df709c57..133336b493b 100644
--- a/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
+++ b/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
@@ -82,6 +82,9 @@ extern __iomem void *ltq_cgu_membase;
82#define LTQ_MPS_BASE_ADDR (KSEG1 + 0x1F107000) 82#define LTQ_MPS_BASE_ADDR (KSEG1 + 0x1F107000)
83#define LTQ_MPS_CHIPID ((u32 *)(LTQ_MPS_BASE_ADDR + 0x0344)) 83#define LTQ_MPS_CHIPID ((u32 *)(LTQ_MPS_BASE_ADDR + 0x0344))
84 84
85/* allow booting xrx200 phys */
86int xrx200_gphy_boot(struct device *dev, unsigned int id, dma_addr_t dev_addr);
87
85/* request a non-gpio and set the PIO config */ 88/* request a non-gpio and set the PIO config */
86#define PMU_PPE BIT(13) 89#define PMU_PPE BIT(13)
87extern void ltq_pmu_enable(unsigned int module); 90extern void ltq_pmu_enable(unsigned int module);
diff --git a/arch/mips/include/asm/mach-loongson1/platform.h b/arch/mips/include/asm/mach-loongson1/platform.h
index 2f171617bad..718a1228a4f 100644
--- a/arch/mips/include/asm/mach-loongson1/platform.h
+++ b/arch/mips/include/asm/mach-loongson1/platform.h
@@ -18,6 +18,7 @@ extern struct platform_device ls1x_eth0_device;
18extern struct platform_device ls1x_ehci_device; 18extern struct platform_device ls1x_ehci_device;
19extern struct platform_device ls1x_rtc_device; 19extern struct platform_device ls1x_rtc_device;
20 20
21void ls1x_serial_setup(void); 21extern void __init ls1x_clk_init(void);
22extern void __init ls1x_serial_setup(struct platform_device *pdev);
22 23
23#endif /* __ASM_MACH_LOONGSON1_PLATFORM_H */ 24#endif /* __ASM_MACH_LOONGSON1_PLATFORM_H */
diff --git a/arch/mips/include/asm/mach-loongson1/regs-clk.h b/arch/mips/include/asm/mach-loongson1/regs-clk.h
index 8efa7fb9f73..a81fa3d0dc9 100644
--- a/arch/mips/include/asm/mach-loongson1/regs-clk.h
+++ b/arch/mips/include/asm/mach-loongson1/regs-clk.h
@@ -20,14 +20,15 @@
20 20
21/* Clock PLL Divisor Register Bits */ 21/* Clock PLL Divisor Register Bits */
22#define DIV_DC_EN (0x1 << 31) 22#define DIV_DC_EN (0x1 << 31)
23#define DIV_DC (0x1f << 26)
24#define DIV_CPU_EN (0x1 << 25) 23#define DIV_CPU_EN (0x1 << 25)
25#define DIV_CPU (0x1f << 20)
26#define DIV_DDR_EN (0x1 << 19) 24#define DIV_DDR_EN (0x1 << 19)
27#define DIV_DDR (0x1f << 14)
28 25
29#define DIV_DC_SHIFT 26 26#define DIV_DC_SHIFT 26
30#define DIV_CPU_SHIFT 20 27#define DIV_CPU_SHIFT 20
31#define DIV_DDR_SHIFT 14 28#define DIV_DDR_SHIFT 14
32 29
30#define DIV_DC_WIDTH 5
31#define DIV_CPU_WIDTH 5
32#define DIV_DDR_WIDTH 5
33
33#endif /* __ASM_MACH_LOONGSON1_REGS_CLK_H */ 34#endif /* __ASM_MACH_LOONGSON1_REGS_CLK_H */
diff --git a/arch/mips/include/asm/mach-netlogic/irq.h b/arch/mips/include/asm/mach-netlogic/irq.h
index b5902458e7c..868ed8a2ed5 100644
--- a/arch/mips/include/asm/mach-netlogic/irq.h
+++ b/arch/mips/include/asm/mach-netlogic/irq.h
@@ -8,7 +8,9 @@
8#ifndef __ASM_NETLOGIC_IRQ_H 8#ifndef __ASM_NETLOGIC_IRQ_H
9#define __ASM_NETLOGIC_IRQ_H 9#define __ASM_NETLOGIC_IRQ_H
10 10
11#define NR_IRQS 64 11#include <asm/mach-netlogic/multi-node.h>
12#define NR_IRQS (64 * NLM_NR_NODES)
13
12#define MIPS_CPU_IRQ_BASE 0 14#define MIPS_CPU_IRQ_BASE 0
13 15
14#endif /* __ASM_NETLOGIC_IRQ_H */ 16#endif /* __ASM_NETLOGIC_IRQ_H */
diff --git a/arch/mips/include/asm/mach-netlogic/multi-node.h b/arch/mips/include/asm/mach-netlogic/multi-node.h
new file mode 100644
index 00000000000..d62fc773f4d
--- /dev/null
+++ b/arch/mips/include/asm/mach-netlogic/multi-node.h
@@ -0,0 +1,54 @@
1/*
2 * Copyright (c) 2003-2012 Broadcom Corporation
3 * All Rights Reserved
4 *
5 * This software is available to you under a choice of one of two
6 * licenses. You may choose to be licensed under the terms of the GNU
7 * General Public License (GPL) Version 2, available from the file
8 * COPYING in the main directory of this source tree, or the Broadcom
9 * license below:
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 *
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in
19 * the documentation and/or other materials provided with the
20 * distribution.
21 *
22 * THIS SOFTWARE IS PROVIDED BY BROADCOM ``AS IS'' AND ANY EXPRESS OR
23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
24 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL BROADCOM OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
29 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
30 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
31 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
32 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 */
34
35#ifndef _NETLOGIC_MULTI_NODE_H_
36#define _NETLOGIC_MULTI_NODE_H_
37
38#ifndef CONFIG_NLM_MULTINODE
39#define NLM_NR_NODES 1
40#else
41#if defined(CONFIG_NLM_MULTINODE_2)
42#define NLM_NR_NODES 2
43#elif defined(CONFIG_NLM_MULTINODE_4)
44#define NLM_NR_NODES 4
45#else
46#define NLM_NR_NODES 1
47#endif
48#endif
49
50#define NLM_CORES_PER_NODE 8
51#define NLM_THREADS_PER_CORE 4
52#define NLM_CPUS_PER_NODE (NLM_CORES_PER_NODE * NLM_THREADS_PER_CORE)
53
54#endif
diff --git a/arch/mips/include/asm/netlogic/common.h b/arch/mips/include/asm/netlogic/common.h
index fdd2f44c7b5..42bfd5f1eee 100644
--- a/arch/mips/include/asm/netlogic/common.h
+++ b/arch/mips/include/asm/netlogic/common.h
@@ -45,15 +45,19 @@
45#define BOOT_NMI_HANDLER 8 45#define BOOT_NMI_HANDLER 8
46 46
47#ifndef __ASSEMBLY__ 47#ifndef __ASSEMBLY__
48#include <linux/cpumask.h>
49#include <linux/spinlock.h>
50#include <asm/irq.h>
51#include <asm/mach-netlogic/multi-node.h>
52
48struct irq_desc; 53struct irq_desc;
49extern struct plat_smp_ops nlm_smp_ops;
50extern char nlm_reset_entry[], nlm_reset_entry_end[];
51void nlm_smp_function_ipi_handler(unsigned int irq, struct irq_desc *desc); 54void nlm_smp_function_ipi_handler(unsigned int irq, struct irq_desc *desc);
52void nlm_smp_resched_ipi_handler(unsigned int irq, struct irq_desc *desc); 55void nlm_smp_resched_ipi_handler(unsigned int irq, struct irq_desc *desc);
53void nlm_smp_irq_init(void); 56void nlm_smp_irq_init(int hwcpuid);
54void nlm_boot_secondary_cpus(void); 57void nlm_boot_secondary_cpus(void);
55int nlm_wakeup_secondary_cpus(u32 wakeup_mask); 58int nlm_wakeup_secondary_cpus(void);
56void nlm_rmiboot_preboot(void); 59void nlm_rmiboot_preboot(void);
60void nlm_percpu_init(int hwcpuid);
57 61
58static inline void 62static inline void
59nlm_set_nmi_handler(void *handler) 63nlm_set_nmi_handler(void *handler)
@@ -68,9 +72,42 @@ nlm_set_nmi_handler(void *handler)
68 * Misc. 72 * Misc.
69 */ 73 */
70unsigned int nlm_get_cpu_frequency(void); 74unsigned int nlm_get_cpu_frequency(void);
75void nlm_node_init(int node);
76extern struct plat_smp_ops nlm_smp_ops;
77extern char nlm_reset_entry[], nlm_reset_entry_end[];
78
79extern unsigned int nlm_threads_per_core;
80extern cpumask_t nlm_cpumask;
81
82struct nlm_soc_info {
83 unsigned long coremask; /* cores enabled on the soc */
84 unsigned long ebase;
85 uint64_t irqmask;
86 uint64_t sysbase; /* only for XLP */
87 uint64_t picbase;
88 spinlock_t piclock;
89};
90
91#define nlm_get_node(i) (&nlm_nodes[i])
92#ifdef CONFIG_CPU_XLR
93#define nlm_current_node() (&nlm_nodes[0])
94#else
95#define nlm_current_node() (&nlm_nodes[nlm_nodeid()])
96#endif
97
98struct irq_data;
99uint64_t nlm_pci_irqmask(int node);
100void nlm_set_pic_extra_ack(int node, int irq, void (*xack)(struct irq_data *));
101
102/*
103 * The NR_IRQs is divided between nodes, each of them has a separate irq space
104 */
105static inline int nlm_irq_to_xirq(int node, int irq)
106{
107 return node * NR_IRQS / NLM_NR_NODES + irq;
108}
71 109
72extern unsigned long nlm_common_ebase; 110extern struct nlm_soc_info nlm_nodes[NLM_NR_NODES];
73extern int nlm_threads_per_core; 111extern int nlm_cpu_ready[];
74extern uint32_t nlm_cpumask, nlm_coremask;
75#endif 112#endif
76#endif /* _NETLOGIC_COMMON_H_ */ 113#endif /* _NETLOGIC_COMMON_H_ */
diff --git a/arch/mips/include/asm/netlogic/interrupt.h b/arch/mips/include/asm/netlogic/interrupt.h
index a85aadb6cfd..ed5993d9b7b 100644
--- a/arch/mips/include/asm/netlogic/interrupt.h
+++ b/arch/mips/include/asm/netlogic/interrupt.h
@@ -39,7 +39,7 @@
39 39
40#define IRQ_IPI_SMP_FUNCTION 3 40#define IRQ_IPI_SMP_FUNCTION 3
41#define IRQ_IPI_SMP_RESCHEDULE 4 41#define IRQ_IPI_SMP_RESCHEDULE 4
42#define IRQ_MSGRING 6 42#define IRQ_FMN 5
43#define IRQ_TIMER 7 43#define IRQ_TIMER 7
44 44
45#endif 45#endif
diff --git a/arch/mips/include/asm/netlogic/mips-extns.h b/arch/mips/include/asm/netlogic/mips-extns.h
index 8c53d0ba4bf..32ba6d95d47 100644
--- a/arch/mips/include/asm/netlogic/mips-extns.h
+++ b/arch/mips/include/asm/netlogic/mips-extns.h
@@ -73,4 +73,146 @@ static inline int hard_smp_processor_id(void)
73 return __read_32bit_c0_register($15, 1) & 0x3ff; 73 return __read_32bit_c0_register($15, 1) & 0x3ff;
74} 74}
75 75
76static inline int nlm_nodeid(void)
77{
78 return (__read_32bit_c0_register($15, 1) >> 5) & 0x3;
79}
80
81static inline unsigned int nlm_core_id(void)
82{
83 return (read_c0_ebase() & 0x1c) >> 2;
84}
85
86static inline unsigned int nlm_thread_id(void)
87{
88 return read_c0_ebase() & 0x3;
89}
90
91#define __read_64bit_c2_split(source, sel) \
92({ \
93 unsigned long long __val; \
94 unsigned long __flags; \
95 \
96 local_irq_save(__flags); \
97 if (sel == 0) \
98 __asm__ __volatile__( \
99 ".set\tmips64\n\t" \
100 "dmfc2\t%M0, " #source "\n\t" \
101 "dsll\t%L0, %M0, 32\n\t" \
102 "dsra\t%M0, %M0, 32\n\t" \
103 "dsra\t%L0, %L0, 32\n\t" \
104 ".set\tmips0\n\t" \
105 : "=r" (__val)); \
106 else \
107 __asm__ __volatile__( \
108 ".set\tmips64\n\t" \
109 "dmfc2\t%M0, " #source ", " #sel "\n\t" \
110 "dsll\t%L0, %M0, 32\n\t" \
111 "dsra\t%M0, %M0, 32\n\t" \
112 "dsra\t%L0, %L0, 32\n\t" \
113 ".set\tmips0\n\t" \
114 : "=r" (__val)); \
115 local_irq_restore(__flags); \
116 \
117 __val; \
118})
119
120#define __write_64bit_c2_split(source, sel, val) \
121do { \
122 unsigned long __flags; \
123 \
124 local_irq_save(__flags); \
125 if (sel == 0) \
126 __asm__ __volatile__( \
127 ".set\tmips64\n\t" \
128 "dsll\t%L0, %L0, 32\n\t" \
129 "dsrl\t%L0, %L0, 32\n\t" \
130 "dsll\t%M0, %M0, 32\n\t" \
131 "or\t%L0, %L0, %M0\n\t" \
132 "dmtc2\t%L0, " #source "\n\t" \
133 ".set\tmips0\n\t" \
134 : : "r" (val)); \
135 else \
136 __asm__ __volatile__( \
137 ".set\tmips64\n\t" \
138 "dsll\t%L0, %L0, 32\n\t" \
139 "dsrl\t%L0, %L0, 32\n\t" \
140 "dsll\t%M0, %M0, 32\n\t" \
141 "or\t%L0, %L0, %M0\n\t" \
142 "dmtc2\t%L0, " #source ", " #sel "\n\t" \
143 ".set\tmips0\n\t" \
144 : : "r" (val)); \
145 local_irq_restore(__flags); \
146} while (0)
147
148#define __read_32bit_c2_register(source, sel) \
149({ uint32_t __res; \
150 if (sel == 0) \
151 __asm__ __volatile__( \
152 ".set\tmips32\n\t" \
153 "mfc2\t%0, " #source "\n\t" \
154 ".set\tmips0\n\t" \
155 : "=r" (__res)); \
156 else \
157 __asm__ __volatile__( \
158 ".set\tmips32\n\t" \
159 "mfc2\t%0, " #source ", " #sel "\n\t" \
160 ".set\tmips0\n\t" \
161 : "=r" (__res)); \
162 __res; \
163})
164
165#define __read_64bit_c2_register(source, sel) \
166({ unsigned long long __res; \
167 if (sizeof(unsigned long) == 4) \
168 __res = __read_64bit_c2_split(source, sel); \
169 else if (sel == 0) \
170 __asm__ __volatile__( \
171 ".set\tmips64\n\t" \
172 "dmfc2\t%0, " #source "\n\t" \
173 ".set\tmips0\n\t" \
174 : "=r" (__res)); \
175 else \
176 __asm__ __volatile__( \
177 ".set\tmips64\n\t" \
178 "dmfc2\t%0, " #source ", " #sel "\n\t" \
179 ".set\tmips0\n\t" \
180 : "=r" (__res)); \
181 __res; \
182})
183
184#define __write_64bit_c2_register(register, sel, value) \
185do { \
186 if (sizeof(unsigned long) == 4) \
187 __write_64bit_c2_split(register, sel, value); \
188 else if (sel == 0) \
189 __asm__ __volatile__( \
190 ".set\tmips64\n\t" \
191 "dmtc2\t%z0, " #register "\n\t" \
192 ".set\tmips0\n\t" \
193 : : "Jr" (value)); \
194 else \
195 __asm__ __volatile__( \
196 ".set\tmips64\n\t" \
197 "dmtc2\t%z0, " #register ", " #sel "\n\t" \
198 ".set\tmips0\n\t" \
199 : : "Jr" (value)); \
200} while (0)
201
202#define __write_32bit_c2_register(reg, sel, value) \
203({ \
204 if (sel == 0) \
205 __asm__ __volatile__( \
206 ".set\tmips32\n\t" \
207 "mtc2\t%z0, " #reg "\n\t" \
208 ".set\tmips0\n\t" \
209 : : "Jr" (value)); \
210 else \
211 __asm__ __volatile__( \
212 ".set\tmips32\n\t" \
213 "mtc2\t%z0, " #reg ", " #sel "\n\t" \
214 ".set\tmips0\n\t" \
215 : : "Jr" (value)); \
216})
217
76#endif /*_ASM_NLM_MIPS_EXTS_H */ 218#endif /*_ASM_NLM_MIPS_EXTS_H */
diff --git a/arch/mips/include/asm/netlogic/xlp-hal/pic.h b/arch/mips/include/asm/netlogic/xlp-hal/pic.h
index ad8b80233a6..b2e53a5383a 100644
--- a/arch/mips/include/asm/netlogic/xlp-hal/pic.h
+++ b/arch/mips/include/asm/netlogic/xlp-hal/pic.h
@@ -273,36 +273,16 @@ nlm_pic_read_irt(uint64_t base, int irt_index)
273 return nlm_read_pic_reg(base, PIC_IRT(irt_index)); 273 return nlm_read_pic_reg(base, PIC_IRT(irt_index));
274} 274}
275 275
276static inline uint64_t
277nlm_pic_read_control(uint64_t base)
278{
279 return nlm_read_pic_reg(base, PIC_CTRL);
280}
281
282static inline void
283nlm_pic_write_control(uint64_t base, uint64_t control)
284{
285 nlm_write_pic_reg(base, PIC_CTRL, control);
286}
287
288static inline void
289nlm_pic_update_control(uint64_t base, uint64_t control)
290{
291 uint64_t val;
292
293 val = nlm_read_pic_reg(base, PIC_CTRL);
294 nlm_write_pic_reg(base, PIC_CTRL, control | val);
295}
296
297static inline void 276static inline void
298nlm_set_irt_to_cpu(uint64_t base, int irt, int cpu) 277nlm_set_irt_to_cpu(uint64_t base, int irt, int cpu)
299{ 278{
300 uint64_t val; 279 uint64_t val;
301 280
302 val = nlm_read_pic_reg(base, PIC_IRT(irt)); 281 val = nlm_read_pic_reg(base, PIC_IRT(irt));
303 val |= cpu & 0xf; 282 /* clear cpuset and mask */
304 if (cpu > 15) 283 val &= ~((0x7ull << 16) | 0xffff);
305 val |= 1 << 16; 284 /* set DB, cpuset and cpumask */
285 val |= (1 << 19) | ((cpu >> 4) << 16) | (1 << (cpu & 0xf));
306 nlm_write_pic_reg(base, PIC_IRT(irt), val); 286 nlm_write_pic_reg(base, PIC_IRT(irt), val);
307} 287}
308 288
@@ -369,7 +349,7 @@ nlm_pic_enable_irt(uint64_t base, int irt)
369static inline void 349static inline void
370nlm_pic_disable_irt(uint64_t base, int irt) 350nlm_pic_disable_irt(uint64_t base, int irt)
371{ 351{
372 uint32_t reg; 352 uint64_t reg;
373 353
374 reg = nlm_read_pic_reg(base, PIC_IRT(irt)); 354 reg = nlm_read_pic_reg(base, PIC_IRT(irt));
375 nlm_write_pic_reg(base, PIC_IRT(irt), reg & ~((uint64_t)1 << 31)); 355 nlm_write_pic_reg(base, PIC_IRT(irt), reg & ~((uint64_t)1 << 31));
@@ -379,15 +359,9 @@ static inline void
379nlm_pic_send_ipi(uint64_t base, int hwt, int irq, int nmi) 359nlm_pic_send_ipi(uint64_t base, int hwt, int irq, int nmi)
380{ 360{
381 uint64_t ipi; 361 uint64_t ipi;
382 int node, ncpu;
383
384 node = hwt / 32;
385 ncpu = hwt & 0x1f;
386 ipi = ((uint64_t)nmi << 31) | (irq << 20) | (node << 17) |
387 (1 << (ncpu & 0xf));
388 if (ncpu > 15)
389 ipi |= 0x10000; /* Setting bit 16 to select cpus 16-31 */
390 362
363 ipi = (nmi << 31) | (irq << 20);
364 ipi |= ((hwt >> 4) << 16) | (1 << (hwt & 0xf)); /* cpuset and mask */
391 nlm_write_pic_reg(base, PIC_IPI_CTL, ipi); 365 nlm_write_pic_reg(base, PIC_IPI_CTL, ipi);
392} 366}
393 367
@@ -404,12 +378,10 @@ nlm_pic_ack(uint64_t base, int irt_num)
404static inline void 378static inline void
405nlm_pic_init_irt(uint64_t base, int irt, int irq, int hwt) 379nlm_pic_init_irt(uint64_t base, int irt, int irq, int hwt)
406{ 380{
407 nlm_pic_write_irt_direct(base, irt, 0, 0, 0, irq, 0); 381 nlm_pic_write_irt_direct(base, irt, 0, 0, 0, irq, hwt);
408} 382}
409 383
410extern uint64_t nlm_pic_base;
411int nlm_irq_to_irt(int irq); 384int nlm_irq_to_irt(int irq);
412int nlm_irt_to_irq(int irt);
413 385
414#endif /* __ASSEMBLY__ */ 386#endif /* __ASSEMBLY__ */
415#endif /* _NLM_HAL_PIC_H */ 387#endif /* _NLM_HAL_PIC_H */
diff --git a/arch/mips/include/asm/netlogic/xlp-hal/sys.h b/arch/mips/include/asm/netlogic/xlp-hal/sys.h
index 21432f7d89b..258e8cc00e9 100644
--- a/arch/mips/include/asm/netlogic/xlp-hal/sys.h
+++ b/arch/mips/include/asm/netlogic/xlp-hal/sys.h
@@ -124,6 +124,5 @@
124#define nlm_get_sys_pcibase(node) nlm_pcicfg_base(XLP_IO_SYS_OFFSET(node)) 124#define nlm_get_sys_pcibase(node) nlm_pcicfg_base(XLP_IO_SYS_OFFSET(node))
125#define nlm_get_sys_regbase(node) (nlm_get_sys_pcibase(node) + XLP_IO_PCI_HDRSZ) 125#define nlm_get_sys_regbase(node) (nlm_get_sys_pcibase(node) + XLP_IO_PCI_HDRSZ)
126 126
127extern uint64_t nlm_sys_base;
128#endif 127#endif
129#endif 128#endif
diff --git a/arch/mips/include/asm/netlogic/xlr/fmn.h b/arch/mips/include/asm/netlogic/xlr/fmn.h
new file mode 100644
index 00000000000..68d5167c86b
--- /dev/null
+++ b/arch/mips/include/asm/netlogic/xlr/fmn.h
@@ -0,0 +1,363 @@
1/*
2 * Copyright (c) 2003-2012 Broadcom Corporation
3 * All Rights Reserved
4 *
5 * This software is available to you under a choice of one of two
6 * licenses. You may choose to be licensed under the terms of the GNU
7 * General Public License (GPL) Version 2, available from the file
8 * COPYING in the main directory of this source tree, or the Broadcom
9 * license below:
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 *
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in
19 * the documentation and/or other materials provided with the
20 * distribution.
21 *
22 * THIS SOFTWARE IS PROVIDED BY BROADCOM ``AS IS'' AND ANY EXPRESS OR
23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
24 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL BROADCOM OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
29 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
30 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
31 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
32 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 */
34
35#ifndef _NLM_FMN_H_
36#define _NLM_FMN_H_
37
38#include <asm/netlogic/mips-extns.h> /* for COP2 access */
39
40/* Station IDs */
41#define FMN_STNID_CPU0 0x00
42#define FMN_STNID_CPU1 0x08
43#define FMN_STNID_CPU2 0x10
44#define FMN_STNID_CPU3 0x18
45#define FMN_STNID_CPU4 0x20
46#define FMN_STNID_CPU5 0x28
47#define FMN_STNID_CPU6 0x30
48#define FMN_STNID_CPU7 0x38
49
50#define FMN_STNID_XGS0_TX 64
51#define FMN_STNID_XMAC0_00_TX 64
52#define FMN_STNID_XMAC0_01_TX 65
53#define FMN_STNID_XMAC0_02_TX 66
54#define FMN_STNID_XMAC0_03_TX 67
55#define FMN_STNID_XMAC0_04_TX 68
56#define FMN_STNID_XMAC0_05_TX 69
57#define FMN_STNID_XMAC0_06_TX 70
58#define FMN_STNID_XMAC0_07_TX 71
59#define FMN_STNID_XMAC0_08_TX 72
60#define FMN_STNID_XMAC0_09_TX 73
61#define FMN_STNID_XMAC0_10_TX 74
62#define FMN_STNID_XMAC0_11_TX 75
63#define FMN_STNID_XMAC0_12_TX 76
64#define FMN_STNID_XMAC0_13_TX 77
65#define FMN_STNID_XMAC0_14_TX 78
66#define FMN_STNID_XMAC0_15_TX 79
67
68#define FMN_STNID_XGS1_TX 80
69#define FMN_STNID_XMAC1_00_TX 80
70#define FMN_STNID_XMAC1_01_TX 81
71#define FMN_STNID_XMAC1_02_TX 82
72#define FMN_STNID_XMAC1_03_TX 83
73#define FMN_STNID_XMAC1_04_TX 84
74#define FMN_STNID_XMAC1_05_TX 85
75#define FMN_STNID_XMAC1_06_TX 86
76#define FMN_STNID_XMAC1_07_TX 87
77#define FMN_STNID_XMAC1_08_TX 88
78#define FMN_STNID_XMAC1_09_TX 89
79#define FMN_STNID_XMAC1_10_TX 90
80#define FMN_STNID_XMAC1_11_TX 91
81#define FMN_STNID_XMAC1_12_TX 92
82#define FMN_STNID_XMAC1_13_TX 93
83#define FMN_STNID_XMAC1_14_TX 94
84#define FMN_STNID_XMAC1_15_TX 95
85
86#define FMN_STNID_GMAC 96
87#define FMN_STNID_GMACJFR_0 96
88#define FMN_STNID_GMACRFR_0 97
89#define FMN_STNID_GMACTX0 98
90#define FMN_STNID_GMACTX1 99
91#define FMN_STNID_GMACTX2 100
92#define FMN_STNID_GMACTX3 101
93#define FMN_STNID_GMACJFR_1 102
94#define FMN_STNID_GMACRFR_1 103
95
96#define FMN_STNID_DMA 104
97#define FMN_STNID_DMA_0 104
98#define FMN_STNID_DMA_1 105
99#define FMN_STNID_DMA_2 106
100#define FMN_STNID_DMA_3 107
101
102#define FMN_STNID_XGS0FR 112
103#define FMN_STNID_XMAC0JFR 112
104#define FMN_STNID_XMAC0RFR 113
105
106#define FMN_STNID_XGS1FR 114
107#define FMN_STNID_XMAC1JFR 114
108#define FMN_STNID_XMAC1RFR 115
109#define FMN_STNID_SEC 120
110#define FMN_STNID_SEC0 120
111#define FMN_STNID_SEC1 121
112#define FMN_STNID_SEC2 122
113#define FMN_STNID_SEC3 123
114#define FMN_STNID_PK0 124
115#define FMN_STNID_SEC_RSA 124
116#define FMN_STNID_SEC_RSVD0 125
117#define FMN_STNID_SEC_RSVD1 126
118#define FMN_STNID_SEC_RSVD2 127
119
120#define FMN_STNID_GMAC1 80
121#define FMN_STNID_GMAC1_FR_0 81
122#define FMN_STNID_GMAC1_TX0 82
123#define FMN_STNID_GMAC1_TX1 83
124#define FMN_STNID_GMAC1_TX2 84
125#define FMN_STNID_GMAC1_TX3 85
126#define FMN_STNID_GMAC1_FR_1 87
127#define FMN_STNID_GMAC0 96
128#define FMN_STNID_GMAC0_FR_0 97
129#define FMN_STNID_GMAC0_TX0 98
130#define FMN_STNID_GMAC0_TX1 99
131#define FMN_STNID_GMAC0_TX2 100
132#define FMN_STNID_GMAC0_TX3 101
133#define FMN_STNID_GMAC0_FR_1 103
134#define FMN_STNID_CMP_0 108
135#define FMN_STNID_CMP_1 109
136#define FMN_STNID_CMP_2 110
137#define FMN_STNID_CMP_3 111
138#define FMN_STNID_PCIE_0 116
139#define FMN_STNID_PCIE_1 117
140#define FMN_STNID_PCIE_2 118
141#define FMN_STNID_PCIE_3 119
142#define FMN_STNID_XLS_PK0 121
143
144#define nlm_read_c2_cc0(s) __read_32bit_c2_register($16, s)
145#define nlm_read_c2_cc1(s) __read_32bit_c2_register($17, s)
146#define nlm_read_c2_cc2(s) __read_32bit_c2_register($18, s)
147#define nlm_read_c2_cc3(s) __read_32bit_c2_register($19, s)
148#define nlm_read_c2_cc4(s) __read_32bit_c2_register($20, s)
149#define nlm_read_c2_cc5(s) __read_32bit_c2_register($21, s)
150#define nlm_read_c2_cc6(s) __read_32bit_c2_register($22, s)
151#define nlm_read_c2_cc7(s) __read_32bit_c2_register($23, s)
152#define nlm_read_c2_cc8(s) __read_32bit_c2_register($24, s)
153#define nlm_read_c2_cc9(s) __read_32bit_c2_register($25, s)
154#define nlm_read_c2_cc10(s) __read_32bit_c2_register($26, s)
155#define nlm_read_c2_cc11(s) __read_32bit_c2_register($27, s)
156#define nlm_read_c2_cc12(s) __read_32bit_c2_register($28, s)
157#define nlm_read_c2_cc13(s) __read_32bit_c2_register($29, s)
158#define nlm_read_c2_cc14(s) __read_32bit_c2_register($30, s)
159#define nlm_read_c2_cc15(s) __read_32bit_c2_register($31, s)
160
161#define nlm_write_c2_cc0(s, v) __write_32bit_c2_register($16, s, v)
162#define nlm_write_c2_cc1(s, v) __write_32bit_c2_register($17, s, v)
163#define nlm_write_c2_cc2(s, v) __write_32bit_c2_register($18, s, v)
164#define nlm_write_c2_cc3(s, v) __write_32bit_c2_register($19, s, v)
165#define nlm_write_c2_cc4(s, v) __write_32bit_c2_register($20, s, v)
166#define nlm_write_c2_cc5(s, v) __write_32bit_c2_register($21, s, v)
167#define nlm_write_c2_cc6(s, v) __write_32bit_c2_register($22, s, v)
168#define nlm_write_c2_cc7(s, v) __write_32bit_c2_register($23, s, v)
169#define nlm_write_c2_cc8(s, v) __write_32bit_c2_register($24, s, v)
170#define nlm_write_c2_cc9(s, v) __write_32bit_c2_register($25, s, v)
171#define nlm_write_c2_cc10(s, v) __write_32bit_c2_register($26, s, v)
172#define nlm_write_c2_cc11(s, v) __write_32bit_c2_register($27, s, v)
173#define nlm_write_c2_cc12(s, v) __write_32bit_c2_register($28, s, v)
174#define nlm_write_c2_cc13(s, v) __write_32bit_c2_register($29, s, v)
175#define nlm_write_c2_cc14(s, v) __write_32bit_c2_register($30, s, v)
176#define nlm_write_c2_cc15(s, v) __write_32bit_c2_register($31, s, v)
177
178#define nlm_read_c2_status(sel) __read_32bit_c2_register($2, 0)
179#define nlm_read_c2_config() __read_32bit_c2_register($3, 0)
180#define nlm_write_c2_config(v) __write_32bit_c2_register($3, 0, v)
181#define nlm_read_c2_bucksize(b) __read_32bit_c2_register($4, b)
182#define nlm_write_c2_bucksize(b, v) __write_32bit_c2_register($4, b, v)
183
184#define nlm_read_c2_rx_msg0() __read_64bit_c2_register($1, 0)
185#define nlm_read_c2_rx_msg1() __read_64bit_c2_register($1, 1)
186#define nlm_read_c2_rx_msg2() __read_64bit_c2_register($1, 2)
187#define nlm_read_c2_rx_msg3() __read_64bit_c2_register($1, 3)
188
189#define nlm_write_c2_tx_msg0(v) __write_64bit_c2_register($0, 0, v)
190#define nlm_write_c2_tx_msg1(v) __write_64bit_c2_register($0, 1, v)
191#define nlm_write_c2_tx_msg2(v) __write_64bit_c2_register($0, 2, v)
192#define nlm_write_c2_tx_msg3(v) __write_64bit_c2_register($0, 3, v)
193
194#define FMN_STN_RX_QSIZE 256
195#define FMN_NSTATIONS 128
196#define FMN_CORE_NBUCKETS 8
197
198static inline void nlm_msgsnd(unsigned int stid)
199{
200 __asm__ volatile (
201 ".set push\n"
202 ".set noreorder\n"
203 ".set noat\n"
204 "move $1, %0\n"
205 "c2 0x10001\n" /* msgsnd $1 */
206 ".set pop\n"
207 : : "r" (stid) : "$1"
208 );
209}
210
211static inline void nlm_msgld(unsigned int pri)
212{
213 __asm__ volatile (
214 ".set push\n"
215 ".set noreorder\n"
216 ".set noat\n"
217 "move $1, %0\n"
218 "c2 0x10002\n" /* msgld $1 */
219 ".set pop\n"
220 : : "r" (pri) : "$1"
221 );
222}
223
224static inline void nlm_msgwait(unsigned int mask)
225{
226 __asm__ volatile (
227 ".set push\n"
228 ".set noreorder\n"
229 ".set noat\n"
230 "move $8, %0\n"
231 "c2 0x10003\n" /* msgwait $1 */
232 ".set pop\n"
233 : : "r" (mask) : "$1"
234 );
235}
236
237/*
238 * Disable interrupts and enable COP2 access
239 */
240static inline uint32_t nlm_cop2_enable(void)
241{
242 uint32_t sr = read_c0_status();
243
244 write_c0_status((sr & ~ST0_IE) | ST0_CU2);
245 return sr;
246}
247
248static inline void nlm_cop2_restore(uint32_t sr)
249{
250 write_c0_status(sr);
251}
252
253static inline void nlm_fmn_setup_intr(int irq, unsigned int tmask)
254{
255 uint32_t config;
256
257 config = (1 << 24) /* interrupt water mark - 1 msg */
258 | (irq << 16) /* irq */
259 | (tmask << 8) /* thread mask */
260 | 0x2; /* enable watermark intr, disable empty intr */
261 nlm_write_c2_config(config);
262}
263
264struct nlm_fmn_msg {
265 uint64_t msg0;
266 uint64_t msg1;
267 uint64_t msg2;
268 uint64_t msg3;
269};
270
271static inline int nlm_fmn_send(unsigned int size, unsigned int code,
272 unsigned int stid, struct nlm_fmn_msg *msg)
273{
274 unsigned int dest;
275 uint32_t status;
276 int i;
277
278 /*
279 * Make sure that all the writes pending at the cpu are flushed.
280 * Any writes pending on CPU will not be see by devices. L1/L2
281 * caches are coherent with IO, so no cache flush needed.
282 */
283 __asm __volatile("sync");
284
285 /* Load TX message buffers */
286 nlm_write_c2_tx_msg0(msg->msg0);
287 nlm_write_c2_tx_msg1(msg->msg1);
288 nlm_write_c2_tx_msg2(msg->msg2);
289 nlm_write_c2_tx_msg3(msg->msg3);
290 dest = ((size - 1) << 16) | (code << 8) | stid;
291
292 /*
293 * Retry a few times on credit fail, this should be a
294 * transient condition, unless there is a configuration
295 * failure, or the receiver is stuck.
296 */
297 for (i = 0; i < 8; i++) {
298 nlm_msgsnd(dest);
299 status = nlm_read_c2_status(0);
300 if ((status & 0x2) == 1)
301 pr_info("Send pending fail!\n");
302 if ((status & 0x4) == 0)
303 return 0;
304 }
305
306 /* If there is a credit failure, return error */
307 return status & 0x06;
308}
309
310static inline int nlm_fmn_receive(int bucket, int *size, int *code, int *stid,
311 struct nlm_fmn_msg *msg)
312{
313 uint32_t status, tmp;
314
315 nlm_msgld(bucket);
316
317 /* wait for load pending to clear */
318 do {
319 status = nlm_read_c2_status(1);
320 } while ((status & 0x08) != 0);
321
322 /* receive error bits */
323 tmp = status & 0x30;
324 if (tmp != 0)
325 return tmp;
326
327 *size = ((status & 0xc0) >> 6) + 1;
328 *code = (status & 0xff00) >> 8;
329 *stid = (status & 0x7f0000) >> 16;
330 msg->msg0 = nlm_read_c2_rx_msg0();
331 msg->msg1 = nlm_read_c2_rx_msg1();
332 msg->msg2 = nlm_read_c2_rx_msg2();
333 msg->msg3 = nlm_read_c2_rx_msg3();
334
335 return 0;
336}
337
338struct xlr_fmn_info {
339 int num_buckets;
340 int start_stn_id;
341 int end_stn_id;
342 int credit_config[128];
343};
344
345struct xlr_board_fmn_config {
346 int bucket_size[128]; /* size of buckets for all stations */
347 struct xlr_fmn_info cpu[8];
348 struct xlr_fmn_info gmac[2];
349 struct xlr_fmn_info dma;
350 struct xlr_fmn_info cmp;
351 struct xlr_fmn_info sae;
352 struct xlr_fmn_info xgmac[2];
353};
354
355extern int nlm_register_fmn_handler(int start, int end,
356 void (*fn)(int, int, int, int, struct nlm_fmn_msg *, void *),
357 void *arg);
358extern void xlr_percpu_fmn_init(void);
359extern void nlm_setup_fmn_irq(void);
360extern void xlr_board_info_setup(void);
361
362extern struct xlr_board_fmn_config xlr_board_fmn_config;
363#endif
diff --git a/arch/mips/include/asm/netlogic/xlr/pic.h b/arch/mips/include/asm/netlogic/xlr/pic.h
index 868013e62f3..9a691b1f91b 100644
--- a/arch/mips/include/asm/netlogic/xlr/pic.h
+++ b/arch/mips/include/asm/netlogic/xlr/pic.h
@@ -258,7 +258,5 @@ nlm_pic_init_irt(uint64_t base, int irt, int irq, int hwt)
258 nlm_write_reg(base, PIC_IRT_1(irt), 258 nlm_write_reg(base, PIC_IRT_1(irt),
259 (1 << 30) | (1 << 6) | irq); 259 (1 << 30) | (1 << 6) | irq);
260} 260}
261
262extern uint64_t nlm_pic_base;
263#endif 261#endif
264#endif /* _ASM_NLM_XLR_PIC_H */ 262#endif /* _ASM_NLM_XLR_PIC_H */
diff --git a/arch/mips/include/asm/netlogic/xlr/xlr.h b/arch/mips/include/asm/netlogic/xlr/xlr.h
index ff4a17b0bf7..c1667e0c272 100644
--- a/arch/mips/include/asm/netlogic/xlr/xlr.h
+++ b/arch/mips/include/asm/netlogic/xlr/xlr.h
@@ -51,10 +51,8 @@ static inline unsigned int nlm_chip_is_xls_b(void)
51 return ((prid & 0xf000) == 0x4000); 51 return ((prid & 0xf000) == 0x4000);
52} 52}
53 53
54/* 54/* XLR chip types */
55 * XLR chip types 55/* The XLS product line has chip versions 0x[48c]? */
56 */
57 /* The XLS product line has chip versions 0x[48c]? */
58static inline unsigned int nlm_chip_is_xls(void) 56static inline unsigned int nlm_chip_is_xls(void)
59{ 57{
60 uint32_t prid = read_c0_prid(); 58 uint32_t prid = read_c0_prid();
diff --git a/arch/mips/kernel/perf_event_mipsxx.c b/arch/mips/kernel/perf_event_mipsxx.c
index a9b995dcf69..b14c14d90fc 100644
--- a/arch/mips/kernel/perf_event_mipsxx.c
+++ b/arch/mips/kernel/perf_event_mipsxx.c
@@ -840,6 +840,16 @@ static const struct mips_perf_event bmips5000_event_map
840 [PERF_COUNT_HW_BRANCH_MISSES] = { 0x02, CNTR_ODD, T }, 840 [PERF_COUNT_HW_BRANCH_MISSES] = { 0x02, CNTR_ODD, T },
841}; 841};
842 842
843static const struct mips_perf_event xlp_event_map[PERF_COUNT_HW_MAX] = {
844 [PERF_COUNT_HW_CPU_CYCLES] = { 0x01, CNTR_ALL },
845 [PERF_COUNT_HW_INSTRUCTIONS] = { 0x18, CNTR_ALL }, /* PAPI_TOT_INS */
846 [PERF_COUNT_HW_CACHE_REFERENCES] = { 0x04, CNTR_ALL }, /* PAPI_L1_ICA */
847 [PERF_COUNT_HW_CACHE_MISSES] = { 0x07, CNTR_ALL }, /* PAPI_L1_ICM */
848 [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = { 0x1b, CNTR_ALL }, /* PAPI_BR_CN */
849 [PERF_COUNT_HW_BRANCH_MISSES] = { 0x1c, CNTR_ALL }, /* PAPI_BR_MSP */
850 [PERF_COUNT_HW_BUS_CYCLES] = { UNSUPPORTED_PERF_EVENT_ID },
851};
852
843/* 24K/34K/1004K cores can share the same cache event map. */ 853/* 24K/34K/1004K cores can share the same cache event map. */
844static const struct mips_perf_event mipsxxcore_cache_map 854static const struct mips_perf_event mipsxxcore_cache_map
845 [PERF_COUNT_HW_CACHE_MAX] 855 [PERF_COUNT_HW_CACHE_MAX]
@@ -1092,6 +1102,100 @@ static const struct mips_perf_event octeon_cache_map
1092}, 1102},
1093}; 1103};
1094 1104
1105static const struct mips_perf_event xlp_cache_map
1106 [PERF_COUNT_HW_CACHE_MAX]
1107 [PERF_COUNT_HW_CACHE_OP_MAX]
1108 [PERF_COUNT_HW_CACHE_RESULT_MAX] = {
1109[C(L1D)] = {
1110 [C(OP_READ)] = {
1111 [C(RESULT_ACCESS)] = { 0x31, CNTR_ALL }, /* PAPI_L1_DCR */
1112 [C(RESULT_MISS)] = { 0x30, CNTR_ALL }, /* PAPI_L1_LDM */
1113 },
1114 [C(OP_WRITE)] = {
1115 [C(RESULT_ACCESS)] = { 0x2f, CNTR_ALL }, /* PAPI_L1_DCW */
1116 [C(RESULT_MISS)] = { 0x2e, CNTR_ALL }, /* PAPI_L1_STM */
1117 },
1118 [C(OP_PREFETCH)] = {
1119 [C(RESULT_ACCESS)] = { UNSUPPORTED_PERF_EVENT_ID },
1120 [C(RESULT_MISS)] = { UNSUPPORTED_PERF_EVENT_ID },
1121 },
1122},
1123[C(L1I)] = {
1124 [C(OP_READ)] = {
1125 [C(RESULT_ACCESS)] = { 0x04, CNTR_ALL }, /* PAPI_L1_ICA */
1126 [C(RESULT_MISS)] = { 0x07, CNTR_ALL }, /* PAPI_L1_ICM */
1127 },
1128 [C(OP_WRITE)] = {
1129 [C(RESULT_ACCESS)] = { UNSUPPORTED_PERF_EVENT_ID },
1130 [C(RESULT_MISS)] = { UNSUPPORTED_PERF_EVENT_ID },
1131 },
1132 [C(OP_PREFETCH)] = {
1133 [C(RESULT_ACCESS)] = { UNSUPPORTED_PERF_EVENT_ID },
1134 [C(RESULT_MISS)] = { UNSUPPORTED_PERF_EVENT_ID },
1135 },
1136},
1137[C(LL)] = {
1138 [C(OP_READ)] = {
1139 [C(RESULT_ACCESS)] = { 0x35, CNTR_ALL }, /* PAPI_L2_DCR */
1140 [C(RESULT_MISS)] = { 0x37, CNTR_ALL }, /* PAPI_L2_LDM */
1141 },
1142 [C(OP_WRITE)] = {
1143 [C(RESULT_ACCESS)] = { 0x34, CNTR_ALL }, /* PAPI_L2_DCA */
1144 [C(RESULT_MISS)] = { 0x36, CNTR_ALL }, /* PAPI_L2_DCM */
1145 },
1146 [C(OP_PREFETCH)] = {
1147 [C(RESULT_ACCESS)] = { UNSUPPORTED_PERF_EVENT_ID },
1148 [C(RESULT_MISS)] = { UNSUPPORTED_PERF_EVENT_ID },
1149 },
1150},
1151[C(DTLB)] = {
1152 /*
1153 * Only general DTLB misses are counted use the same event for
1154 * read and write.
1155 */
1156 [C(OP_READ)] = {
1157 [C(RESULT_ACCESS)] = { UNSUPPORTED_PERF_EVENT_ID },
1158 [C(RESULT_MISS)] = { 0x2d, CNTR_ALL }, /* PAPI_TLB_DM */
1159 },
1160 [C(OP_WRITE)] = {
1161 [C(RESULT_ACCESS)] = { UNSUPPORTED_PERF_EVENT_ID },
1162 [C(RESULT_MISS)] = { 0x2d, CNTR_ALL }, /* PAPI_TLB_DM */
1163 },
1164 [C(OP_PREFETCH)] = {
1165 [C(RESULT_ACCESS)] = { UNSUPPORTED_PERF_EVENT_ID },
1166 [C(RESULT_MISS)] = { UNSUPPORTED_PERF_EVENT_ID },
1167 },
1168},
1169[C(ITLB)] = {
1170 [C(OP_READ)] = {
1171 [C(RESULT_ACCESS)] = { UNSUPPORTED_PERF_EVENT_ID },
1172 [C(RESULT_MISS)] = { 0x08, CNTR_ALL }, /* PAPI_TLB_IM */
1173 },
1174 [C(OP_WRITE)] = {
1175 [C(RESULT_ACCESS)] = { UNSUPPORTED_PERF_EVENT_ID },
1176 [C(RESULT_MISS)] = { 0x08, CNTR_ALL }, /* PAPI_TLB_IM */
1177 },
1178 [C(OP_PREFETCH)] = {
1179 [C(RESULT_ACCESS)] = { UNSUPPORTED_PERF_EVENT_ID },
1180 [C(RESULT_MISS)] = { UNSUPPORTED_PERF_EVENT_ID },
1181 },
1182},
1183[C(BPU)] = {
1184 [C(OP_READ)] = {
1185 [C(RESULT_ACCESS)] = { UNSUPPORTED_PERF_EVENT_ID },
1186 [C(RESULT_MISS)] = { 0x25, CNTR_ALL },
1187 },
1188 [C(OP_WRITE)] = {
1189 [C(RESULT_ACCESS)] = { UNSUPPORTED_PERF_EVENT_ID },
1190 [C(RESULT_MISS)] = { UNSUPPORTED_PERF_EVENT_ID },
1191 },
1192 [C(OP_PREFETCH)] = {
1193 [C(RESULT_ACCESS)] = { UNSUPPORTED_PERF_EVENT_ID },
1194 [C(RESULT_MISS)] = { UNSUPPORTED_PERF_EVENT_ID },
1195 },
1196},
1197};
1198
1095#ifdef CONFIG_MIPS_MT_SMP 1199#ifdef CONFIG_MIPS_MT_SMP
1096static void check_and_calc_range(struct perf_event *event, 1200static void check_and_calc_range(struct perf_event *event,
1097 const struct mips_perf_event *pev) 1201 const struct mips_perf_event *pev)
@@ -1444,6 +1548,20 @@ static const struct mips_perf_event *octeon_pmu_map_raw_event(u64 config)
1444 return &raw_event; 1548 return &raw_event;
1445} 1549}
1446 1550
1551static const struct mips_perf_event *xlp_pmu_map_raw_event(u64 config)
1552{
1553 unsigned int raw_id = config & 0xff;
1554
1555 /* Only 1-63 are defined */
1556 if ((raw_id < 0x01) || (raw_id > 0x3f))
1557 return ERR_PTR(-EOPNOTSUPP);
1558
1559 raw_event.cntr_mask = CNTR_ALL;
1560 raw_event.event_id = raw_id;
1561
1562 return &raw_event;
1563}
1564
1447static int __init 1565static int __init
1448init_hw_perf_events(void) 1566init_hw_perf_events(void)
1449{ 1567{
@@ -1522,6 +1640,12 @@ init_hw_perf_events(void)
1522 mipspmu.general_event_map = &bmips5000_event_map; 1640 mipspmu.general_event_map = &bmips5000_event_map;
1523 mipspmu.cache_event_map = &bmips5000_cache_map; 1641 mipspmu.cache_event_map = &bmips5000_cache_map;
1524 break; 1642 break;
1643 case CPU_XLP:
1644 mipspmu.name = "xlp";
1645 mipspmu.general_event_map = &xlp_event_map;
1646 mipspmu.cache_event_map = &xlp_cache_map;
1647 mipspmu.map_raw_event = xlp_pmu_map_raw_event;
1648 break;
1525 default: 1649 default:
1526 pr_cont("Either hardware does not support performance " 1650 pr_cont("Either hardware does not support performance "
1527 "counters, or not yet implemented.\n"); 1651 "counters, or not yet implemented.\n");
diff --git a/arch/mips/lantiq/Kconfig b/arch/mips/lantiq/Kconfig
index d84f361f1e4..c0021912131 100644
--- a/arch/mips/lantiq/Kconfig
+++ b/arch/mips/lantiq/Kconfig
@@ -36,4 +36,8 @@ config PCI_LANTIQ
36 bool "PCI Support" 36 bool "PCI Support"
37 depends on SOC_XWAY && PCI 37 depends on SOC_XWAY && PCI
38 38
39config XRX200_PHY_FW
40 bool "XRX200 PHY firmware loader"
41 depends on SOC_XWAY
42
39endif 43endif
diff --git a/arch/mips/lantiq/prom.c b/arch/mips/lantiq/prom.c
index 6cfd6117fbf..9f9e875967a 100644
--- a/arch/mips/lantiq/prom.c
+++ b/arch/mips/lantiq/prom.c
@@ -87,9 +87,6 @@ void __init device_tree_init(void)
87 reserve_bootmem(base, size, BOOTMEM_DEFAULT); 87 reserve_bootmem(base, size, BOOTMEM_DEFAULT);
88 88
89 unflatten_device_tree(); 89 unflatten_device_tree();
90
91 /* free the space reserved for the dt blob */
92 free_bootmem(base, size);
93} 90}
94 91
95void __init prom_init(void) 92void __init prom_init(void)
@@ -119,7 +116,7 @@ int __init plat_of_setup(void)
119 sizeof(of_ids[0].compatible)); 116 sizeof(of_ids[0].compatible));
120 strncpy(of_ids[1].compatible, "simple-bus", 117 strncpy(of_ids[1].compatible, "simple-bus",
121 sizeof(of_ids[1].compatible)); 118 sizeof(of_ids[1].compatible));
122 return of_platform_bus_probe(NULL, of_ids, NULL); 119 return of_platform_populate(NULL, of_ids, NULL, NULL);
123} 120}
124 121
125arch_initcall(plat_of_setup); 122arch_initcall(plat_of_setup);
diff --git a/arch/mips/lantiq/xway/Makefile b/arch/mips/lantiq/xway/Makefile
index 70a58c747bd..7a13660d630 100644
--- a/arch/mips/lantiq/xway/Makefile
+++ b/arch/mips/lantiq/xway/Makefile
@@ -1 +1,3 @@
1obj-y := prom.o sysctrl.o clk.o reset.o dma.o gptu.o 1obj-y := prom.o sysctrl.o clk.o reset.o dma.o gptu.o
2
3obj-$(CONFIG_XRX200_PHY_FW) += xrx200_phy_fw.o
diff --git a/arch/mips/lantiq/xway/dma.c b/arch/mips/lantiq/xway/dma.c
index 0f7228d350d..6453962ac89 100644
--- a/arch/mips/lantiq/xway/dma.c
+++ b/arch/mips/lantiq/xway/dma.c
@@ -25,6 +25,7 @@
25#include <lantiq_soc.h> 25#include <lantiq_soc.h>
26#include <xway_dma.h> 26#include <xway_dma.h>
27 27
28#define LTQ_DMA_ID 0x08
28#define LTQ_DMA_CTRL 0x10 29#define LTQ_DMA_CTRL 0x10
29#define LTQ_DMA_CPOLL 0x14 30#define LTQ_DMA_CPOLL 0x14
30#define LTQ_DMA_CS 0x18 31#define LTQ_DMA_CS 0x18
@@ -214,6 +215,7 @@ ltq_dma_init(struct platform_device *pdev)
214{ 215{
215 struct clk *clk; 216 struct clk *clk;
216 struct resource *res; 217 struct resource *res;
218 unsigned id;
217 int i; 219 int i;
218 220
219 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 221 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -243,7 +245,12 @@ ltq_dma_init(struct platform_device *pdev)
243 ltq_dma_w32(DMA_POLL | DMA_CLK_DIV4, LTQ_DMA_CPOLL); 245 ltq_dma_w32(DMA_POLL | DMA_CLK_DIV4, LTQ_DMA_CPOLL);
244 ltq_dma_w32_mask(DMA_CHAN_ON, 0, LTQ_DMA_CCTRL); 246 ltq_dma_w32_mask(DMA_CHAN_ON, 0, LTQ_DMA_CCTRL);
245 } 247 }
246 dev_info(&pdev->dev, "init done\n"); 248
249 id = ltq_dma_r32(LTQ_DMA_ID);
250 dev_info(&pdev->dev,
251 "Init done - hw rev: %X, ports: %d, channels: %d\n",
252 id & 0x1f, (id >> 16) & 0xf, id >> 20);
253
247 return 0; 254 return 0;
248} 255}
249 256
diff --git a/arch/mips/lantiq/xway/reset.c b/arch/mips/lantiq/xway/reset.c
index 22c55f73aa9..544dbb7fb42 100644
--- a/arch/mips/lantiq/xway/reset.c
+++ b/arch/mips/lantiq/xway/reset.c
@@ -28,17 +28,24 @@
28#define RCU_RST_REQ 0x0010 28#define RCU_RST_REQ 0x0010
29/* reset status register */ 29/* reset status register */
30#define RCU_RST_STAT 0x0014 30#define RCU_RST_STAT 0x0014
31/* vr9 gphy registers */
32#define RCU_GFS_ADD0_XRX200 0x0020
33#define RCU_GFS_ADD1_XRX200 0x0068
31 34
32/* reboot bit */ 35/* reboot bit */
36#define RCU_RD_GPHY0_XRX200 BIT(31)
33#define RCU_RD_SRST BIT(30) 37#define RCU_RD_SRST BIT(30)
38#define RCU_RD_GPHY1_XRX200 BIT(29)
39
34/* reset cause */ 40/* reset cause */
35#define RCU_STAT_SHIFT 26 41#define RCU_STAT_SHIFT 26
36/* boot selection */ 42/* boot selection */
37#define RCU_BOOT_SEL_SHIFT 26 43#define RCU_BOOT_SEL(x) ((x >> 18) & 0x7)
38#define RCU_BOOT_SEL_MASK 0x7 44#define RCU_BOOT_SEL_XRX200(x) (((x >> 17) & 0xf) | ((x >> 8) & 0x10))
39 45
40/* remapped base addr of the reset control unit */ 46/* remapped base addr of the reset control unit */
41static void __iomem *ltq_rcu_membase; 47static void __iomem *ltq_rcu_membase;
48static struct device_node *ltq_rcu_np;
42 49
43/* This function is used by the watchdog driver */ 50/* This function is used by the watchdog driver */
44int ltq_reset_cause(void) 51int ltq_reset_cause(void)
@@ -52,7 +59,41 @@ EXPORT_SYMBOL_GPL(ltq_reset_cause);
52unsigned char ltq_boot_select(void) 59unsigned char ltq_boot_select(void)
53{ 60{
54 u32 val = ltq_rcu_r32(RCU_RST_STAT); 61 u32 val = ltq_rcu_r32(RCU_RST_STAT);
55 return (val >> RCU_BOOT_SEL_SHIFT) & RCU_BOOT_SEL_MASK; 62
63 if (of_device_is_compatible(ltq_rcu_np, "lantiq,rcu-xrx200"))
64 return RCU_BOOT_SEL_XRX200(val);
65
66 return RCU_BOOT_SEL(val);
67}
68
69/* reset / boot a gphy */
70static struct ltq_xrx200_gphy_reset {
71 u32 rd;
72 u32 addr;
73} xrx200_gphy[] = {
74 {RCU_RD_GPHY0_XRX200, RCU_GFS_ADD0_XRX200},
75 {RCU_RD_GPHY1_XRX200, RCU_GFS_ADD1_XRX200},
76};
77
78/* reset and boot a gphy. these phys only exist on xrx200 SoC */
79int xrx200_gphy_boot(struct device *dev, unsigned int id, dma_addr_t dev_addr)
80{
81 if (!of_device_is_compatible(ltq_rcu_np, "lantiq,rcu-xrx200")) {
82 dev_err(dev, "this SoC has no GPHY\n");
83 return -EINVAL;
84 }
85 if (id > 1) {
86 dev_err(dev, "%u is an invalid gphy id\n", id);
87 return -EINVAL;
88 }
89 dev_info(dev, "booting GPHY%u firmware at %X\n", id, dev_addr);
90
91 ltq_rcu_w32(ltq_rcu_r32(RCU_RST_REQ) | xrx200_gphy[id].rd,
92 RCU_RST_REQ);
93 ltq_rcu_w32(dev_addr, xrx200_gphy[id].addr);
94 ltq_rcu_w32(ltq_rcu_r32(RCU_RST_REQ) & ~xrx200_gphy[id].rd,
95 RCU_RST_REQ);
96 return 0;
56} 97}
57 98
58/* reset a io domain for u micro seconds */ 99/* reset a io domain for u micro seconds */
@@ -85,14 +126,17 @@ static void ltq_machine_power_off(void)
85static int __init mips_reboot_setup(void) 126static int __init mips_reboot_setup(void)
86{ 127{
87 struct resource res; 128 struct resource res;
88 struct device_node *np = 129
89 of_find_compatible_node(NULL, NULL, "lantiq,rcu-xway"); 130 ltq_rcu_np = of_find_compatible_node(NULL, NULL, "lantiq,rcu-xway");
131 if (!ltq_rcu_np)
132 ltq_rcu_np = of_find_compatible_node(NULL, NULL,
133 "lantiq,rcu-xrx200");
90 134
91 /* check if all the reset register range is available */ 135 /* check if all the reset register range is available */
92 if (!np) 136 if (!ltq_rcu_np)
93 panic("Failed to load reset resources from devicetree"); 137 panic("Failed to load reset resources from devicetree");
94 138
95 if (of_address_to_resource(np, 0, &res)) 139 if (of_address_to_resource(ltq_rcu_np, 0, &res))
96 panic("Failed to get rcu memory range"); 140 panic("Failed to get rcu memory range");
97 141
98 if (request_mem_region(res.start, resource_size(&res), res.name) < 0) 142 if (request_mem_region(res.start, resource_size(&res), res.name) < 0)
diff --git a/arch/mips/lantiq/xway/sysctrl.c b/arch/mips/lantiq/xway/sysctrl.c
index 2917b56b6b2..3925e6609ac 100644
--- a/arch/mips/lantiq/xway/sysctrl.c
+++ b/arch/mips/lantiq/xway/sysctrl.c
@@ -370,6 +370,10 @@ void __init ltq_soc_init(void)
370 clkdev_add_pmu("1d900000.pcie", "pdi", 1, PMU1_PCIE_PDI); 370 clkdev_add_pmu("1d900000.pcie", "pdi", 1, PMU1_PCIE_PDI);
371 clkdev_add_pmu("1d900000.pcie", "ctl", 1, PMU1_PCIE_CTL); 371 clkdev_add_pmu("1d900000.pcie", "ctl", 1, PMU1_PCIE_CTL);
372 clkdev_add_pmu("1d900000.pcie", "ahb", 0, PMU_AHBM | PMU_AHBS); 372 clkdev_add_pmu("1d900000.pcie", "ahb", 0, PMU_AHBM | PMU_AHBS);
373 clkdev_add_pmu("1e108000.eth", NULL, 0,
374 PMU_SWITCH | PMU_PPE_DPLUS | PMU_PPE_DPLUM |
375 PMU_PPE_EMA | PMU_PPE_TC | PMU_PPE_SLL01 |
376 PMU_PPE_QSB | PMU_PPE_TOP);
373 } else if (of_machine_is_compatible("lantiq,ar9")) { 377 } else if (of_machine_is_compatible("lantiq,ar9")) {
374 clkdev_add_static(ltq_ar9_cpu_hz(), ltq_ar9_fpi_hz(), 378 clkdev_add_static(ltq_ar9_cpu_hz(), ltq_ar9_fpi_hz(),
375 ltq_ar9_fpi_hz()); 379 ltq_ar9_fpi_hz());
diff --git a/arch/mips/lantiq/xway/xrx200_phy_fw.c b/arch/mips/lantiq/xway/xrx200_phy_fw.c
new file mode 100644
index 00000000000..fe808bf5366
--- /dev/null
+++ b/arch/mips/lantiq/xway/xrx200_phy_fw.c
@@ -0,0 +1,97 @@
1/*
2 * This program is free software; you can redistribute it and/or modify it
3 * under the terms of the GNU General Public License version 2 as published
4 * by the Free Software Foundation.
5 *
6 * Copyright (C) 2012 John Crispin <blogic@openwrt.org>
7 */
8
9#include <linux/delay.h>
10#include <linux/dma-mapping.h>
11#include <linux/module.h>
12#include <linux/firmware.h>
13#include <linux/of_platform.h>
14
15#include <lantiq_soc.h>
16
17#define XRX200_GPHY_FW_ALIGN (16 * 1024)
18
19static dma_addr_t xway_gphy_load(struct platform_device *pdev)
20{
21 const struct firmware *fw;
22 dma_addr_t dev_addr = 0;
23 const char *fw_name;
24 void *fw_addr;
25 size_t size;
26
27 if (of_property_read_string(pdev->dev.of_node, "firmware", &fw_name)) {
28 dev_err(&pdev->dev, "failed to load firmware filename\n");
29 return 0;
30 }
31
32 dev_info(&pdev->dev, "requesting %s\n", fw_name);
33 if (request_firmware(&fw, fw_name, &pdev->dev)) {
34 dev_err(&pdev->dev, "failed to load firmware: %s\n", fw_name);
35 return 0;
36 }
37
38 /*
39 * GPHY cores need the firmware code in a persistent and contiguous
40 * memory area with a 16 kB boundary aligned start address
41 */
42 size = fw->size + XRX200_GPHY_FW_ALIGN;
43
44 fw_addr = dma_alloc_coherent(&pdev->dev, size, &dev_addr, GFP_KERNEL);
45 if (fw_addr) {
46 fw_addr = PTR_ALIGN(fw_addr, XRX200_GPHY_FW_ALIGN);
47 dev_addr = ALIGN(dev_addr, XRX200_GPHY_FW_ALIGN);
48 memcpy(fw_addr, fw->data, fw->size);
49 } else {
50 dev_err(&pdev->dev, "failed to alloc firmware memory\n");
51 }
52
53 release_firmware(fw);
54 return dev_addr;
55}
56
57static int __devinit xway_phy_fw_probe(struct platform_device *pdev)
58{
59 dma_addr_t fw_addr;
60 struct property *pp;
61 unsigned char *phyids;
62 int i, ret = 0;
63
64 fw_addr = xway_gphy_load(pdev);
65 if (!fw_addr)
66 return -EINVAL;
67 pp = of_find_property(pdev->dev.of_node, "phys", NULL);
68 if (!pp)
69 return -ENOENT;
70 phyids = pp->value;
71 for (i = 0; i < pp->length && !ret; i++)
72 ret = xrx200_gphy_boot(&pdev->dev, phyids[i], fw_addr);
73 if (!ret)
74 mdelay(100);
75 return ret;
76}
77
78static const struct of_device_id xway_phy_match[] = {
79 { .compatible = "lantiq,phy-xrx200" },
80 {},
81};
82MODULE_DEVICE_TABLE(of, xway_phy_match);
83
84static struct platform_driver xway_phy_driver = {
85 .probe = xway_phy_fw_probe,
86 .driver = {
87 .name = "phy-xrx200",
88 .owner = THIS_MODULE,
89 .of_match_table = xway_phy_match,
90 },
91};
92
93module_platform_driver(xway_phy_driver);
94
95MODULE_AUTHOR("John Crispin <blogic@openwrt.org>");
96MODULE_DESCRIPTION("Lantiq XRX200 PHY Firmware Loader");
97MODULE_LICENSE("GPL");
diff --git a/arch/mips/loongson1/Kconfig b/arch/mips/loongson1/Kconfig
index a9a14d6e81a..fbf75f63579 100644
--- a/arch/mips/loongson1/Kconfig
+++ b/arch/mips/loongson1/Kconfig
@@ -15,7 +15,7 @@ config LOONGSON1_LS1B
15 select SYS_SUPPORTS_LITTLE_ENDIAN 15 select SYS_SUPPORTS_LITTLE_ENDIAN
16 select SYS_SUPPORTS_HIGHMEM 16 select SYS_SUPPORTS_HIGHMEM
17 select SYS_HAS_EARLY_PRINTK 17 select SYS_HAS_EARLY_PRINTK
18 select HAVE_CLK 18 select COMMON_CLK
19 19
20endchoice 20endchoice
21 21
diff --git a/arch/mips/loongson1/common/clock.c b/arch/mips/loongson1/common/clock.c
index 1bbbbec1208..07133defa14 100644
--- a/arch/mips/loongson1/common/clock.c
+++ b/arch/mips/loongson1/common/clock.c
@@ -7,175 +7,22 @@
7 * option) any later version. 7 * option) any later version.
8 */ 8 */
9 9
10#include <linux/module.h>
11#include <linux/list.h>
12#include <linux/mutex.h>
13#include <linux/clk.h> 10#include <linux/clk.h>
14#include <linux/err.h> 11#include <linux/err.h>
15#include <asm/clock.h>
16#include <asm/time.h> 12#include <asm/time.h>
17 13#include <platform.h>
18#include <loongson1.h>
19
20static LIST_HEAD(clocks);
21static DEFINE_MUTEX(clocks_mutex);
22
23struct clk *clk_get(struct device *dev, const char *name)
24{
25 struct clk *c;
26 struct clk *ret = NULL;
27
28 mutex_lock(&clocks_mutex);
29 list_for_each_entry(c, &clocks, node) {
30 if (!strcmp(c->name, name)) {
31 ret = c;
32 break;
33 }
34 }
35 mutex_unlock(&clocks_mutex);
36
37 return ret;
38}
39EXPORT_SYMBOL(clk_get);
40
41int clk_enable(struct clk *clk)
42{
43 return 0;
44}
45EXPORT_SYMBOL(clk_enable);
46
47void clk_disable(struct clk *clk)
48{
49}
50EXPORT_SYMBOL(clk_disable);
51
52unsigned long clk_get_rate(struct clk *clk)
53{
54 return clk->rate;
55}
56EXPORT_SYMBOL(clk_get_rate);
57
58void clk_put(struct clk *clk)
59{
60}
61EXPORT_SYMBOL(clk_put);
62
63static void pll_clk_init(struct clk *clk)
64{
65 u32 pll;
66
67 pll = __raw_readl(LS1X_CLK_PLL_FREQ);
68 clk->rate = (12 + (pll & 0x3f)) * 33 / 2
69 + ((pll >> 8) & 0x3ff) * 33 / 1024 / 2;
70 clk->rate *= 1000000;
71}
72
73static void cpu_clk_init(struct clk *clk)
74{
75 u32 pll, ctrl;
76
77 pll = clk_get_rate(clk->parent);
78 ctrl = __raw_readl(LS1X_CLK_PLL_DIV) & DIV_CPU;
79 clk->rate = pll / (ctrl >> DIV_CPU_SHIFT);
80}
81
82static void ddr_clk_init(struct clk *clk)
83{
84 u32 pll, ctrl;
85
86 pll = clk_get_rate(clk->parent);
87 ctrl = __raw_readl(LS1X_CLK_PLL_DIV) & DIV_DDR;
88 clk->rate = pll / (ctrl >> DIV_DDR_SHIFT);
89}
90
91static void dc_clk_init(struct clk *clk)
92{
93 u32 pll, ctrl;
94
95 pll = clk_get_rate(clk->parent);
96 ctrl = __raw_readl(LS1X_CLK_PLL_DIV) & DIV_DC;
97 clk->rate = pll / (ctrl >> DIV_DC_SHIFT);
98}
99
100static struct clk_ops pll_clk_ops = {
101 .init = pll_clk_init,
102};
103
104static struct clk_ops cpu_clk_ops = {
105 .init = cpu_clk_init,
106};
107
108static struct clk_ops ddr_clk_ops = {
109 .init = ddr_clk_init,
110};
111
112static struct clk_ops dc_clk_ops = {
113 .init = dc_clk_init,
114};
115
116static struct clk pll_clk = {
117 .name = "pll",
118 .ops = &pll_clk_ops,
119};
120
121static struct clk cpu_clk = {
122 .name = "cpu",
123 .parent = &pll_clk,
124 .ops = &cpu_clk_ops,
125};
126
127static struct clk ddr_clk = {
128 .name = "ddr",
129 .parent = &pll_clk,
130 .ops = &ddr_clk_ops,
131};
132
133static struct clk dc_clk = {
134 .name = "dc",
135 .parent = &pll_clk,
136 .ops = &dc_clk_ops,
137};
138
139int clk_register(struct clk *clk)
140{
141 mutex_lock(&clocks_mutex);
142 list_add(&clk->node, &clocks);
143 if (clk->ops->init)
144 clk->ops->init(clk);
145 mutex_unlock(&clocks_mutex);
146
147 return 0;
148}
149EXPORT_SYMBOL(clk_register);
150
151static struct clk *ls1x_clks[] = {
152 &pll_clk,
153 &cpu_clk,
154 &ddr_clk,
155 &dc_clk,
156};
157
158int __init ls1x_clock_init(void)
159{
160 int i;
161
162 for (i = 0; i < ARRAY_SIZE(ls1x_clks); i++)
163 clk_register(ls1x_clks[i]);
164
165 return 0;
166}
167 14
168void __init plat_time_init(void) 15void __init plat_time_init(void)
169{ 16{
170 struct clk *clk; 17 struct clk *clk;
171 18
172 /* Initialize LS1X clocks */ 19 /* Initialize LS1X clocks */
173 ls1x_clock_init(); 20 ls1x_clk_init();
174 21
175 /* setup mips r4k timer */ 22 /* setup mips r4k timer */
176 clk = clk_get(NULL, "cpu"); 23 clk = clk_get(NULL, "cpu");
177 if (IS_ERR(clk)) 24 if (IS_ERR(clk))
178 panic("unable to get dc clock, err=%ld", PTR_ERR(clk)); 25 panic("unable to get cpu clock, err=%ld", PTR_ERR(clk));
179 26
180 mips_hpt_frequency = clk_get_rate(clk) / 2; 27 mips_hpt_frequency = clk_get_rate(clk) / 2;
181} 28}
diff --git a/arch/mips/loongson1/common/platform.c b/arch/mips/loongson1/common/platform.c
index e92d59c4bd7..3a42276b8ea 100644
--- a/arch/mips/loongson1/common/platform.c
+++ b/arch/mips/loongson1/common/platform.c
@@ -42,16 +42,17 @@ struct platform_device ls1x_uart_device = {
42 }, 42 },
43}; 43};
44 44
45void __init ls1x_serial_setup(void) 45void __init ls1x_serial_setup(struct platform_device *pdev)
46{ 46{
47 struct clk *clk; 47 struct clk *clk;
48 struct plat_serial8250_port *p; 48 struct plat_serial8250_port *p;
49 49
50 clk = clk_get(NULL, "dc"); 50 clk = clk_get(NULL, pdev->name);
51 if (IS_ERR(clk)) 51 if (IS_ERR(clk))
52 panic("unable to get dc clock, err=%ld", PTR_ERR(clk)); 52 panic("unable to get %s clock, err=%ld",
53 pdev->name, PTR_ERR(clk));
53 54
54 for (p = ls1x_serial8250_port; p->flags != 0; ++p) 55 for (p = pdev->dev.platform_data; p->flags != 0; ++p)
55 p->uartclk = clk_get_rate(clk); 56 p->uartclk = clk_get_rate(clk);
56} 57}
57 58
@@ -70,7 +71,6 @@ static struct resource ls1x_eth0_resources[] = {
70}; 71};
71 72
72static struct stmmac_mdio_bus_data ls1x_mdio_bus_data = { 73static struct stmmac_mdio_bus_data ls1x_mdio_bus_data = {
73 .bus_id = 0,
74 .phy_mask = 0, 74 .phy_mask = 0,
75}; 75};
76 76
diff --git a/arch/mips/loongson1/ls1b/board.c b/arch/mips/loongson1/ls1b/board.c
index 295b1be893e..1fbd5264f66 100644
--- a/arch/mips/loongson1/ls1b/board.c
+++ b/arch/mips/loongson1/ls1b/board.c
@@ -9,9 +9,6 @@
9 9
10#include <platform.h> 10#include <platform.h>
11 11
12#include <linux/serial_8250.h>
13#include <loongson1.h>
14
15static struct platform_device *ls1b_platform_devices[] __initdata = { 12static struct platform_device *ls1b_platform_devices[] __initdata = {
16 &ls1x_uart_device, 13 &ls1x_uart_device,
17 &ls1x_eth0_device, 14 &ls1x_eth0_device,
@@ -23,7 +20,7 @@ static int __init ls1b_platform_init(void)
23{ 20{
24 int err; 21 int err;
25 22
26 ls1x_serial_setup(); 23 ls1x_serial_setup(&ls1x_uart_device);
27 24
28 err = platform_add_devices(ls1b_platform_devices, 25 err = platform_add_devices(ls1b_platform_devices,
29 ARRAY_SIZE(ls1b_platform_devices)); 26 ARRAY_SIZE(ls1b_platform_devices));
diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c
index d2b5b0c7afa..0f7d788e881 100644
--- a/arch/mips/mm/c-r4k.c
+++ b/arch/mips/mm/c-r4k.c
@@ -1333,10 +1333,10 @@ static int __init cca_setup(char *str)
1333{ 1333{
1334 get_option(&str, &cca); 1334 get_option(&str, &cca);
1335 1335
1336 return 1; 1336 return 0;
1337} 1337}
1338 1338
1339__setup("cca=", cca_setup); 1339early_param("cca", cca_setup);
1340 1340
1341static void __cpuinit coherency_setup(void) 1341static void __cpuinit coherency_setup(void)
1342{ 1342{
@@ -1386,10 +1386,10 @@ static int __init setcoherentio(char *str)
1386{ 1386{
1387 coherentio = 1; 1387 coherentio = 1;
1388 1388
1389 return 1; 1389 return 0;
1390} 1390}
1391 1391
1392__setup("coherentio", setcoherentio); 1392early_param("coherentio", setcoherentio);
1393#endif 1393#endif
1394 1394
1395static void __cpuinit r4k_cache_error_setup(void) 1395static void __cpuinit r4k_cache_error_setup(void)
diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c
index 69a357254e4..05613355627 100644
--- a/arch/mips/mm/tlbex.c
+++ b/arch/mips/mm/tlbex.c
@@ -183,7 +183,9 @@ UASM_L_LA(_tlb_huge_update)
183 183
184static int __cpuinitdata hazard_instance; 184static int __cpuinitdata hazard_instance;
185 185
186static void uasm_bgezl_hazard(u32 **p, struct uasm_reloc **r, int instance) 186static void __cpuinit uasm_bgezl_hazard(u32 **p,
187 struct uasm_reloc **r,
188 int instance)
187{ 189{
188 switch (instance) { 190 switch (instance) {
189 case 0 ... 7: 191 case 0 ... 7:
@@ -194,7 +196,9 @@ static void uasm_bgezl_hazard(u32 **p, struct uasm_reloc **r, int instance)
194 } 196 }
195} 197}
196 198
197static void uasm_bgezl_label(struct uasm_label **l, u32 **p, int instance) 199static void __cpuinit uasm_bgezl_label(struct uasm_label **l,
200 u32 **p,
201 int instance)
198{ 202{
199 switch (instance) { 203 switch (instance) {
200 case 0 ... 7: 204 case 0 ... 7:
diff --git a/arch/mips/netlogic/Kconfig b/arch/mips/netlogic/Kconfig
index 8059eb76f8e..3c05bf9e280 100644
--- a/arch/mips/netlogic/Kconfig
+++ b/arch/mips/netlogic/Kconfig
@@ -9,6 +9,34 @@ config DT_XLP_EVP
9 This DTB will be used if the firmware does not pass in a DTB 9 This DTB will be used if the firmware does not pass in a DTB
10 pointer to the kernel. The corresponding DTS file is at 10 pointer to the kernel. The corresponding DTS file is at
11 arch/mips/netlogic/dts/xlp_evp.dts 11 arch/mips/netlogic/dts/xlp_evp.dts
12
13config NLM_MULTINODE
14 bool "Support for multi-chip boards"
15 depends on NLM_XLP_BOARD
16 default n
17 help
18 Add support for boards with 2 or 4 XLPs connected over ICI.
19
20if NLM_MULTINODE
21choice
22 prompt "Number of XLPs on the board"
23 default NLM_MULTINODE_2
24 help
25 In the multi-node case, specify the number of SoCs on the board.
26
27config NLM_MULTINODE_2
28 bool "Dual-XLP board"
29 help
30 Support boards with upto two XLPs connected over ICI.
31
32config NLM_MULTINODE_4
33 bool "Quad-XLP board"
34 help
35 Support boards with upto four XLPs connected over ICI.
36
37endchoice
38
39endif
12endif 40endif
13 41
14config NLM_COMMON 42config NLM_COMMON
diff --git a/arch/mips/netlogic/common/irq.c b/arch/mips/netlogic/common/irq.c
index e52bfcbce09..00dcc7a2bc5 100644
--- a/arch/mips/netlogic/common/irq.c
+++ b/arch/mips/netlogic/common/irq.c
@@ -36,7 +36,6 @@
36#include <linux/init.h> 36#include <linux/init.h>
37#include <linux/linkage.h> 37#include <linux/linkage.h>
38#include <linux/interrupt.h> 38#include <linux/interrupt.h>
39#include <linux/spinlock.h>
40#include <linux/mm.h> 39#include <linux/mm.h>
41#include <linux/slab.h> 40#include <linux/slab.h>
42#include <linux/irq.h> 41#include <linux/irq.h>
@@ -59,68 +58,70 @@
59#elif defined(CONFIG_CPU_XLR) 58#elif defined(CONFIG_CPU_XLR)
60#include <asm/netlogic/xlr/iomap.h> 59#include <asm/netlogic/xlr/iomap.h>
61#include <asm/netlogic/xlr/pic.h> 60#include <asm/netlogic/xlr/pic.h>
61#include <asm/netlogic/xlr/fmn.h>
62#else 62#else
63#error "Unknown CPU" 63#error "Unknown CPU"
64#endif 64#endif
65/*
66 * These are the routines that handle all the low level interrupt stuff.
67 * Actions handled here are: initialization of the interrupt map, requesting of
68 * interrupt lines by handlers, dispatching if interrupts to handlers, probing
69 * for interrupt lines
70 */
71 65
72/* Globals */ 66#ifdef CONFIG_SMP
73static uint64_t nlm_irq_mask; 67#define SMP_IRQ_MASK ((1ULL << IRQ_IPI_SMP_FUNCTION) | \
74static DEFINE_SPINLOCK(nlm_pic_lock); 68 (1ULL << IRQ_IPI_SMP_RESCHEDULE))
69#else
70#define SMP_IRQ_MASK 0
71#endif
72#define PERCPU_IRQ_MASK (SMP_IRQ_MASK | (1ull << IRQ_TIMER) | \
73 (1ull << IRQ_FMN))
74
75struct nlm_pic_irq {
76 void (*extra_ack)(struct irq_data *);
77 struct nlm_soc_info *node;
78 int picirq;
79 int irt;
80 int flags;
81};
75 82
76static void xlp_pic_enable(struct irq_data *d) 83static void xlp_pic_enable(struct irq_data *d)
77{ 84{
78 unsigned long flags; 85 unsigned long flags;
79 int irt; 86 struct nlm_pic_irq *pd = irq_data_get_irq_handler_data(d);
80 87
81 irt = nlm_irq_to_irt(d->irq); 88 BUG_ON(!pd);
82 if (irt == -1) 89 spin_lock_irqsave(&pd->node->piclock, flags);
83 return; 90 nlm_pic_enable_irt(pd->node->picbase, pd->irt);
84 spin_lock_irqsave(&nlm_pic_lock, flags); 91 spin_unlock_irqrestore(&pd->node->piclock, flags);
85 nlm_pic_enable_irt(nlm_pic_base, irt);
86 spin_unlock_irqrestore(&nlm_pic_lock, flags);
87} 92}
88 93
89static void xlp_pic_disable(struct irq_data *d) 94static void xlp_pic_disable(struct irq_data *d)
90{ 95{
96 struct nlm_pic_irq *pd = irq_data_get_irq_handler_data(d);
91 unsigned long flags; 97 unsigned long flags;
92 int irt;
93 98
94 irt = nlm_irq_to_irt(d->irq); 99 BUG_ON(!pd);
95 if (irt == -1) 100 spin_lock_irqsave(&pd->node->piclock, flags);
96 return; 101 nlm_pic_disable_irt(pd->node->picbase, pd->irt);
97 spin_lock_irqsave(&nlm_pic_lock, flags); 102 spin_unlock_irqrestore(&pd->node->piclock, flags);
98 nlm_pic_disable_irt(nlm_pic_base, irt);
99 spin_unlock_irqrestore(&nlm_pic_lock, flags);
100} 103}
101 104
102static void xlp_pic_mask_ack(struct irq_data *d) 105static void xlp_pic_mask_ack(struct irq_data *d)
103{ 106{
104 uint64_t mask = 1ull << d->irq; 107 struct nlm_pic_irq *pd = irq_data_get_irq_handler_data(d);
108 uint64_t mask = 1ull << pd->picirq;
105 109
106 write_c0_eirr(mask); /* ack by writing EIRR */ 110 write_c0_eirr(mask); /* ack by writing EIRR */
107} 111}
108 112
109static void xlp_pic_unmask(struct irq_data *d) 113static void xlp_pic_unmask(struct irq_data *d)
110{ 114{
111 void *hd = irq_data_get_irq_handler_data(d); 115 struct nlm_pic_irq *pd = irq_data_get_irq_handler_data(d);
112 int irt;
113 116
114 irt = nlm_irq_to_irt(d->irq); 117 if (!pd)
115 if (irt == -1)
116 return; 118 return;
117 119
118 if (hd) { 120 if (pd->extra_ack)
119 void (*extra_ack)(void *) = hd; 121 pd->extra_ack(d);
120 extra_ack(d); 122
121 }
122 /* Ack is a single write, no need to lock */ 123 /* Ack is a single write, no need to lock */
123 nlm_pic_ack(nlm_pic_base, irt); 124 nlm_pic_ack(pd->node->picbase, pd->irt);
124} 125}
125 126
126static struct irq_chip xlp_pic = { 127static struct irq_chip xlp_pic = {
@@ -174,64 +175,108 @@ struct irq_chip nlm_cpu_intr = {
174 .irq_eoi = cpuintr_ack, 175 .irq_eoi = cpuintr_ack,
175}; 176};
176 177
177void __init init_nlm_common_irqs(void) 178static void __init nlm_init_percpu_irqs(void)
178{ 179{
179 int i, irq, irt; 180 int i;
180 181
181 for (i = 0; i < PIC_IRT_FIRST_IRQ; i++) 182 for (i = 0; i < PIC_IRT_FIRST_IRQ; i++)
182 irq_set_chip_and_handler(i, &nlm_cpu_intr, handle_percpu_irq); 183 irq_set_chip_and_handler(i, &nlm_cpu_intr, handle_percpu_irq);
183
184 for (i = PIC_IRT_FIRST_IRQ; i <= PIC_IRT_LAST_IRQ ; i++)
185 irq_set_chip_and_handler(i, &xlp_pic, handle_level_irq);
186
187#ifdef CONFIG_SMP 184#ifdef CONFIG_SMP
188 irq_set_chip_and_handler(IRQ_IPI_SMP_FUNCTION, &nlm_cpu_intr, 185 irq_set_chip_and_handler(IRQ_IPI_SMP_FUNCTION, &nlm_cpu_intr,
189 nlm_smp_function_ipi_handler); 186 nlm_smp_function_ipi_handler);
190 irq_set_chip_and_handler(IRQ_IPI_SMP_RESCHEDULE, &nlm_cpu_intr, 187 irq_set_chip_and_handler(IRQ_IPI_SMP_RESCHEDULE, &nlm_cpu_intr,
191 nlm_smp_resched_ipi_handler); 188 nlm_smp_resched_ipi_handler);
192 nlm_irq_mask |=
193 ((1ULL << IRQ_IPI_SMP_FUNCTION) | (1ULL << IRQ_IPI_SMP_RESCHEDULE));
194#endif 189#endif
190}
191
192void nlm_setup_pic_irq(int node, int picirq, int irq, int irt)
193{
194 struct nlm_pic_irq *pic_data;
195 int xirq;
196
197 xirq = nlm_irq_to_xirq(node, irq);
198 pic_data = kzalloc(sizeof(*pic_data), GFP_KERNEL);
199 BUG_ON(pic_data == NULL);
200 pic_data->irt = irt;
201 pic_data->picirq = picirq;
202 pic_data->node = nlm_get_node(node);
203 irq_set_chip_and_handler(xirq, &xlp_pic, handle_level_irq);
204 irq_set_handler_data(xirq, pic_data);
205}
206
207void nlm_set_pic_extra_ack(int node, int irq, void (*xack)(struct irq_data *))
208{
209 struct nlm_pic_irq *pic_data;
210 int xirq;
211
212 xirq = nlm_irq_to_xirq(node, irq);
213 pic_data = irq_get_handler_data(xirq);
214 pic_data->extra_ack = xack;
215}
195 216
196 for (irq = PIC_IRT_FIRST_IRQ; irq <= PIC_IRT_LAST_IRQ; irq++) { 217static void nlm_init_node_irqs(int node)
197 irt = nlm_irq_to_irt(irq); 218{
219 int i, irt;
220 uint64_t irqmask;
221 struct nlm_soc_info *nodep;
222
223 pr_info("Init IRQ for node %d\n", node);
224 nodep = nlm_get_node(node);
225 irqmask = PERCPU_IRQ_MASK;
226 for (i = PIC_IRT_FIRST_IRQ; i <= PIC_IRT_LAST_IRQ; i++) {
227 irt = nlm_irq_to_irt(i);
198 if (irt == -1) 228 if (irt == -1)
199 continue; 229 continue;
200 nlm_irq_mask |= (1ULL << irq); 230 nlm_setup_pic_irq(node, i, i, irt);
201 nlm_pic_init_irt(nlm_pic_base, irt, irq, 0); 231 /* set interrupts to first cpu in node */
232 nlm_pic_init_irt(nodep->picbase, irt, i,
233 node * NLM_CPUS_PER_NODE);
234 irqmask |= (1ull << i);
202 } 235 }
203 236 nodep->irqmask = irqmask;
204 nlm_irq_mask |= (1ULL << IRQ_TIMER);
205} 237}
206 238
207void __init arch_init_irq(void) 239void __init arch_init_irq(void)
208{ 240{
209 /* Initialize the irq descriptors */ 241 /* Initialize the irq descriptors */
210 init_nlm_common_irqs(); 242 nlm_init_percpu_irqs();
211 243 nlm_init_node_irqs(0);
212 write_c0_eimr(nlm_irq_mask); 244 write_c0_eimr(nlm_current_node()->irqmask);
245#if defined(CONFIG_CPU_XLR)
246 nlm_setup_fmn_irq();
247#endif
213} 248}
214 249
215void __cpuinit nlm_smp_irq_init(void) 250void nlm_smp_irq_init(int hwcpuid)
216{ 251{
217 /* set interrupt mask for non-zero cpus */ 252 int node, cpu;
218 write_c0_eimr(nlm_irq_mask); 253
254 node = hwcpuid / NLM_CPUS_PER_NODE;
255 cpu = hwcpuid % NLM_CPUS_PER_NODE;
256
257 if (cpu == 0 && node != 0)
258 nlm_init_node_irqs(node);
259 write_c0_eimr(nlm_current_node()->irqmask);
219} 260}
220 261
221asmlinkage void plat_irq_dispatch(void) 262asmlinkage void plat_irq_dispatch(void)
222{ 263{
223 uint64_t eirr; 264 uint64_t eirr;
224 int i; 265 int i, node;
225 266
267 node = nlm_nodeid();
226 eirr = read_c0_eirr() & read_c0_eimr(); 268 eirr = read_c0_eirr() & read_c0_eimr();
227 if (eirr & (1 << IRQ_TIMER)) {
228 do_IRQ(IRQ_TIMER);
229 return;
230 }
231 269
232 i = __ilog2_u64(eirr); 270 i = __ilog2_u64(eirr);
233 if (i == -1) 271 if (i == -1)
234 return; 272 return;
235 273
236 do_IRQ(i); 274 /* per-CPU IRQs don't need translation */
275 if (eirr & PERCPU_IRQ_MASK) {
276 do_IRQ(i);
277 return;
278 }
279
280 /* top level irq handling */
281 do_IRQ(nlm_irq_to_xirq(node, i));
237} 282}
diff --git a/arch/mips/netlogic/common/smp.c b/arch/mips/netlogic/common/smp.c
index fab316de57e..a080d9ee3cd 100644
--- a/arch/mips/netlogic/common/smp.c
+++ b/arch/mips/netlogic/common/smp.c
@@ -59,12 +59,17 @@
59 59
60void nlm_send_ipi_single(int logical_cpu, unsigned int action) 60void nlm_send_ipi_single(int logical_cpu, unsigned int action)
61{ 61{
62 int cpu = cpu_logical_map(logical_cpu); 62 int cpu, node;
63 uint64_t picbase;
64
65 cpu = cpu_logical_map(logical_cpu);
66 node = cpu / NLM_CPUS_PER_NODE;
67 picbase = nlm_get_node(node)->picbase;
63 68
64 if (action & SMP_CALL_FUNCTION) 69 if (action & SMP_CALL_FUNCTION)
65 nlm_pic_send_ipi(nlm_pic_base, cpu, IRQ_IPI_SMP_FUNCTION, 0); 70 nlm_pic_send_ipi(picbase, cpu, IRQ_IPI_SMP_FUNCTION, 0);
66 if (action & SMP_RESCHEDULE_YOURSELF) 71 if (action & SMP_RESCHEDULE_YOURSELF)
67 nlm_pic_send_ipi(nlm_pic_base, cpu, IRQ_IPI_SMP_RESCHEDULE, 0); 72 nlm_pic_send_ipi(picbase, cpu, IRQ_IPI_SMP_RESCHEDULE, 0);
68} 73}
69 74
70void nlm_send_ipi_mask(const struct cpumask *mask, unsigned int action) 75void 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)
96void nlm_early_init_secondary(int cpu) 101void nlm_early_init_secondary(int cpu)
97{ 102{
98 change_c0_config(CONF_CM_CMASK, 0x3); 103 change_c0_config(CONF_CM_CMASK, 0x3);
99 write_c0_ebase((uint32_t)nlm_common_ebase);
100#ifdef CONFIG_CPU_XLP 104#ifdef CONFIG_CPU_XLP
101 if (hard_smp_processor_id() % 4 == 0) 105 /* mmu init, once per core */
106 if (cpu % NLM_THREADS_PER_CORE == 0)
102 xlp_mmu_init(); 107 xlp_mmu_init();
103#endif 108#endif
109 write_c0_ebase(nlm_current_node()->ebase);
104} 110}
105 111
106/* 112/*
@@ -108,8 +114,12 @@ void nlm_early_init_secondary(int cpu)
108 */ 114 */
109static void __cpuinit nlm_init_secondary(void) 115static void __cpuinit nlm_init_secondary(void)
110{ 116{
111 current_cpu_data.core = hard_smp_processor_id() / 4; 117 int hwtid;
112 nlm_smp_irq_init(); 118
119 hwtid = hard_smp_processor_id();
120 current_cpu_data.core = hwtid / NLM_THREADS_PER_CORE;
121 nlm_percpu_init(hwtid);
122 nlm_smp_irq_init(hwtid);
113} 123}
114 124
115void nlm_prepare_cpus(unsigned int max_cpus) 125void nlm_prepare_cpus(unsigned int max_cpus)
@@ -120,9 +130,6 @@ void nlm_prepare_cpus(unsigned int max_cpus)
120 130
121void nlm_smp_finish(void) 131void nlm_smp_finish(void)
122{ 132{
123#ifdef notyet
124 nlm_common_msgring_cpu_init();
125#endif
126 local_irq_enable(); 133 local_irq_enable();
127} 134}
128 135
@@ -142,27 +149,27 @@ cpumask_t phys_cpu_present_map;
142 149
143void nlm_boot_secondary(int logical_cpu, struct task_struct *idle) 150void nlm_boot_secondary(int logical_cpu, struct task_struct *idle)
144{ 151{
145 unsigned long gp = (unsigned long)task_thread_info(idle); 152 int cpu, node;
146 unsigned long sp = (unsigned long)__KSTK_TOS(idle);
147 int cpu = cpu_logical_map(logical_cpu);
148 153
149 nlm_next_sp = sp; 154 cpu = cpu_logical_map(logical_cpu);
150 nlm_next_gp = gp; 155 node = cpu / NLM_CPUS_PER_NODE;
156 nlm_next_sp = (unsigned long)__KSTK_TOS(idle);
157 nlm_next_gp = (unsigned long)task_thread_info(idle);
151 158
152 /* barrier */ 159 /* barrier for sp/gp store above */
153 __sync(); 160 __sync();
154 nlm_pic_send_ipi(nlm_pic_base, cpu, 1, 1); 161 nlm_pic_send_ipi(nlm_get_node(node)->picbase, cpu, 1, 1); /* NMI */
155} 162}
156 163
157void __init nlm_smp_setup(void) 164void __init nlm_smp_setup(void)
158{ 165{
159 unsigned int boot_cpu; 166 unsigned int boot_cpu;
160 int num_cpus, i; 167 int num_cpus, i, ncore;
161 168
162 boot_cpu = hard_smp_processor_id(); 169 boot_cpu = hard_smp_processor_id();
163 cpus_clear(phys_cpu_present_map); 170 cpumask_clear(&phys_cpu_present_map);
164 171
165 cpu_set(boot_cpu, phys_cpu_present_map); 172 cpumask_set_cpu(boot_cpu, &phys_cpu_present_map);
166 __cpu_number_map[boot_cpu] = 0; 173 __cpu_number_map[boot_cpu] = 0;
167 __cpu_logical_map[0] = boot_cpu; 174 __cpu_logical_map[0] = boot_cpu;
168 set_cpu_possible(0, true); 175 set_cpu_possible(0, true);
@@ -174,7 +181,7 @@ void __init nlm_smp_setup(void)
174 * it is only set for ASPs (see smpboot.S) 181 * it is only set for ASPs (see smpboot.S)
175 */ 182 */
176 if (nlm_cpu_ready[i]) { 183 if (nlm_cpu_ready[i]) {
177 cpu_set(i, phys_cpu_present_map); 184 cpumask_set_cpu(i, &phys_cpu_present_map);
178 __cpu_number_map[i] = num_cpus; 185 __cpu_number_map[i] = num_cpus;
179 __cpu_logical_map[num_cpus] = i; 186 __cpu_logical_map[num_cpus] = i;
180 set_cpu_possible(num_cpus, true); 187 set_cpu_possible(num_cpus, true);
@@ -182,20 +189,28 @@ void __init nlm_smp_setup(void)
182 } 189 }
183 } 190 }
184 191
192 /* check with the cores we have worken up */
193 for (ncore = 0, i = 0; i < NLM_NR_NODES; i++)
194 ncore += hweight32(nlm_get_node(i)->coremask);
195
185 pr_info("Phys CPU present map: %lx, possible map %lx\n", 196 pr_info("Phys CPU present map: %lx, possible map %lx\n",
186 (unsigned long)phys_cpu_present_map.bits[0], 197 (unsigned long)cpumask_bits(&phys_cpu_present_map)[0],
187 (unsigned long)cpumask_bits(cpu_possible_mask)[0]); 198 (unsigned long)cpumask_bits(cpu_possible_mask)[0]);
188 199
189 pr_info("Detected %i Slave CPU(s)\n", num_cpus); 200 pr_info("Detected (%dc%dt) %d Slave CPU(s)\n", ncore,
201 nlm_threads_per_core, num_cpus);
190 nlm_set_nmi_handler(nlm_boot_secondary_cpus); 202 nlm_set_nmi_handler(nlm_boot_secondary_cpus);
191} 203}
192 204
193static int nlm_parse_cpumask(u32 cpu_mask) 205static int nlm_parse_cpumask(cpumask_t *wakeup_mask)
194{ 206{
195 uint32_t core0_thr_mask, core_thr_mask; 207 uint32_t core0_thr_mask, core_thr_mask;
196 int threadmode, i; 208 int threadmode, i, j;
197 209
198 core0_thr_mask = cpu_mask & 0xf; 210 core0_thr_mask = 0;
211 for (i = 0; i < NLM_THREADS_PER_CORE; i++)
212 if (cpumask_test_cpu(i, wakeup_mask))
213 core0_thr_mask |= (1 << i);
199 switch (core0_thr_mask) { 214 switch (core0_thr_mask) {
200 case 1: 215 case 1:
201 nlm_threads_per_core = 1; 216 nlm_threads_per_core = 1;
@@ -214,25 +229,23 @@ static int nlm_parse_cpumask(u32 cpu_mask)
214 } 229 }
215 230
216 /* Verify other cores CPU masks */ 231 /* Verify other cores CPU masks */
217 nlm_coremask = 1; 232 for (i = 0; i < NR_CPUS; i += NLM_THREADS_PER_CORE) {
218 nlm_cpumask = core0_thr_mask; 233 core_thr_mask = 0;
219 for (i = 1; i < 8; i++) { 234 for (j = 0; j < NLM_THREADS_PER_CORE; j++)
220 core_thr_mask = (cpu_mask >> (i * 4)) & 0xf; 235 if (cpumask_test_cpu(i + j, wakeup_mask))
221 if (core_thr_mask) { 236 core_thr_mask |= (1 << j);
222 if (core_thr_mask != core0_thr_mask) 237 if (core_thr_mask != 0 && core_thr_mask != core0_thr_mask)
223 goto unsupp; 238 goto unsupp;
224 nlm_coremask |= 1 << i;
225 nlm_cpumask |= core0_thr_mask << (4 * i);
226 }
227 } 239 }
228 return threadmode; 240 return threadmode;
229 241
230unsupp: 242unsupp:
231 panic("Unsupported CPU mask %x\n", cpu_mask); 243 panic("Unsupported CPU mask %lx\n",
244 (unsigned long)cpumask_bits(wakeup_mask)[0]);
232 return 0; 245 return 0;
233} 246}
234 247
235int __cpuinit nlm_wakeup_secondary_cpus(u32 wakeup_mask) 248int __cpuinit nlm_wakeup_secondary_cpus(void)
236{ 249{
237 unsigned long reset_vec; 250 unsigned long reset_vec;
238 char *reset_data; 251 char *reset_data;
@@ -244,7 +257,7 @@ int __cpuinit nlm_wakeup_secondary_cpus(u32 wakeup_mask)
244 (nlm_reset_entry_end - nlm_reset_entry)); 257 (nlm_reset_entry_end - nlm_reset_entry));
245 258
246 /* verify the mask and setup core config variables */ 259 /* verify the mask and setup core config variables */
247 threadmode = nlm_parse_cpumask(wakeup_mask); 260 threadmode = nlm_parse_cpumask(&nlm_cpumask);
248 261
249 /* Setup CPU init parameters */ 262 /* Setup CPU init parameters */
250 reset_data = (char *)CKSEG1ADDR(RESET_DATA_PHYS); 263 reset_data = (char *)CKSEG1ADDR(RESET_DATA_PHYS);
diff --git a/arch/mips/netlogic/common/smpboot.S b/arch/mips/netlogic/common/smpboot.S
index a13355cc97e..a0b74874beb 100644
--- a/arch/mips/netlogic/common/smpboot.S
+++ b/arch/mips/netlogic/common/smpboot.S
@@ -61,7 +61,7 @@
61 li t0, LSU_DEFEATURE 61 li t0, LSU_DEFEATURE
62 mfcr t1, t0 62 mfcr t1, t0
63 63
64 lui t2, 0x4080 /* Enable Unaligned Access, L2HPE */ 64 lui t2, 0xc080 /* SUE, Enable Unaligned Access, L2HPE */
65 or t1, t1, t2 65 or t1, t1, t2
66#ifdef XLP_AX_WORKAROUND 66#ifdef XLP_AX_WORKAROUND
67 li t2, ~0xe /* S1RCM */ 67 li t2, ~0xe /* S1RCM */
@@ -186,7 +186,7 @@ EXPORT(nlm_boot_siblings)
186 * jump to the secondary wait function. 186 * jump to the secondary wait function.
187 */ 187 */
188 mfc0 v0, CP0_EBASE, 1 188 mfc0 v0, CP0_EBASE, 1
189 andi v0, 0x7f /* v0 <- node/core */ 189 andi v0, 0x3ff /* v0 <- node/core */
190 190
191 /* Init MMU in the first thread after changing THREAD_MODE 191 /* Init MMU in the first thread after changing THREAD_MODE
192 * register (Ax Errata?) 192 * register (Ax Errata?)
@@ -263,6 +263,8 @@ NESTED(nlm_boot_secondary_cpus, 16, sp)
263 PTR_L gp, 0(t1) 263 PTR_L gp, 0(t1)
264 264
265 /* a0 has the processor id */ 265 /* a0 has the processor id */
266 mfc0 a0, CP0_EBASE, 1
267 andi a0, 0x3ff /* a0 <- node/core */
266 PTR_LA t0, nlm_early_init_secondary 268 PTR_LA t0, nlm_early_init_secondary
267 jalr t0 269 jalr t0
268 nop 270 nop
diff --git a/arch/mips/netlogic/xlp/nlm_hal.c b/arch/mips/netlogic/xlp/nlm_hal.c
index 6c65ac70191..529e74742d9 100644
--- a/arch/mips/netlogic/xlp/nlm_hal.c
+++ b/arch/mips/netlogic/xlp/nlm_hal.c
@@ -40,23 +40,23 @@
40#include <asm/mipsregs.h> 40#include <asm/mipsregs.h>
41#include <asm/time.h> 41#include <asm/time.h>
42 42
43#include <asm/netlogic/common.h>
43#include <asm/netlogic/haldefs.h> 44#include <asm/netlogic/haldefs.h>
44#include <asm/netlogic/xlp-hal/iomap.h> 45#include <asm/netlogic/xlp-hal/iomap.h>
45#include <asm/netlogic/xlp-hal/xlp.h> 46#include <asm/netlogic/xlp-hal/xlp.h>
46#include <asm/netlogic/xlp-hal/pic.h> 47#include <asm/netlogic/xlp-hal/pic.h>
47#include <asm/netlogic/xlp-hal/sys.h> 48#include <asm/netlogic/xlp-hal/sys.h>
48 49
49/* These addresses are computed by the nlm_hal_init() */
50uint64_t nlm_io_base;
51uint64_t nlm_sys_base;
52uint64_t nlm_pic_base;
53
54/* Main initialization */ 50/* Main initialization */
55void nlm_hal_init(void) 51void nlm_node_init(int node)
56{ 52{
57 nlm_io_base = CKSEG1ADDR(XLP_DEFAULT_IO_BASE); 53 struct nlm_soc_info *nodep;
58 nlm_sys_base = nlm_get_sys_regbase(0); /* node 0 */ 54
59 nlm_pic_base = nlm_get_pic_regbase(0); /* node 0 */ 55 nodep = nlm_get_node(node);
56 nodep->sysbase = nlm_get_sys_regbase(node);
57 nodep->picbase = nlm_get_pic_regbase(node);
58 nodep->ebase = read_c0_ebase() & (~((1 << 12) - 1));
59 spin_lock_init(&nodep->piclock);
60} 60}
61 61
62int nlm_irq_to_irt(int irq) 62int nlm_irq_to_irt(int irq)
@@ -100,52 +100,15 @@ int nlm_irq_to_irt(int irq)
100 } 100 }
101} 101}
102 102
103int nlm_irt_to_irq(int irt) 103unsigned int nlm_get_core_frequency(int node, int core)
104{
105 switch (irt) {
106 case PIC_IRT_UART_0_INDEX:
107 return PIC_UART_0_IRQ;
108 case PIC_IRT_UART_1_INDEX:
109 return PIC_UART_1_IRQ;
110 case PIC_IRT_PCIE_LINK_0_INDEX:
111 return PIC_PCIE_LINK_0_IRQ;
112 case PIC_IRT_PCIE_LINK_1_INDEX:
113 return PIC_PCIE_LINK_1_IRQ;
114 case PIC_IRT_PCIE_LINK_2_INDEX:
115 return PIC_PCIE_LINK_2_IRQ;
116 case PIC_IRT_PCIE_LINK_3_INDEX:
117 return PIC_PCIE_LINK_3_IRQ;
118 case PIC_IRT_EHCI_0_INDEX:
119 return PIC_EHCI_0_IRQ;
120 case PIC_IRT_EHCI_1_INDEX:
121 return PIC_EHCI_1_IRQ;
122 case PIC_IRT_OHCI_0_INDEX:
123 return PIC_OHCI_0_IRQ;
124 case PIC_IRT_OHCI_1_INDEX:
125 return PIC_OHCI_1_IRQ;
126 case PIC_IRT_OHCI_2_INDEX:
127 return PIC_OHCI_2_IRQ;
128 case PIC_IRT_OHCI_3_INDEX:
129 return PIC_OHCI_3_IRQ;
130 case PIC_IRT_MMC_INDEX:
131 return PIC_MMC_IRQ;
132 case PIC_IRT_I2C_0_INDEX:
133 return PIC_I2C_0_IRQ;
134 case PIC_IRT_I2C_1_INDEX:
135 return PIC_I2C_1_IRQ;
136 default:
137 return -1;
138 }
139}
140
141unsigned int nlm_get_core_frequency(int core)
142{ 104{
143 unsigned int pll_divf, pll_divr, dfs_div, ext_div; 105 unsigned int pll_divf, pll_divr, dfs_div, ext_div;
144 unsigned int rstval, dfsval, denom; 106 unsigned int rstval, dfsval, denom;
145 uint64_t num; 107 uint64_t num, sysbase;
146 108
147 rstval = nlm_read_sys_reg(nlm_sys_base, SYS_POWER_ON_RESET_CFG); 109 sysbase = nlm_get_node(node)->sysbase;
148 dfsval = nlm_read_sys_reg(nlm_sys_base, SYS_CORE_DFS_DIV_VALUE); 110 rstval = nlm_read_sys_reg(sysbase, SYS_POWER_ON_RESET_CFG);
111 dfsval = nlm_read_sys_reg(sysbase, SYS_CORE_DFS_DIV_VALUE);
149 pll_divf = ((rstval >> 10) & 0x7f) + 1; 112 pll_divf = ((rstval >> 10) & 0x7f) + 1;
150 pll_divr = ((rstval >> 8) & 0x3) + 1; 113 pll_divr = ((rstval >> 8) & 0x3) + 1;
151 ext_div = ((rstval >> 30) & 0x3) + 1; 114 ext_div = ((rstval >> 30) & 0x3) + 1;
@@ -159,5 +122,5 @@ unsigned int nlm_get_core_frequency(int core)
159 122
160unsigned int nlm_get_cpu_frequency(void) 123unsigned int nlm_get_cpu_frequency(void)
161{ 124{
162 return nlm_get_core_frequency(0); 125 return nlm_get_core_frequency(0, 0);
163} 126}
diff --git a/arch/mips/netlogic/xlp/setup.c b/arch/mips/netlogic/xlp/setup.c
index d8997098def..4894d62043a 100644
--- a/arch/mips/netlogic/xlp/setup.c
+++ b/arch/mips/netlogic/xlp/setup.c
@@ -52,26 +52,40 @@
52#include <asm/netlogic/xlp-hal/xlp.h> 52#include <asm/netlogic/xlp-hal/xlp.h>
53#include <asm/netlogic/xlp-hal/sys.h> 53#include <asm/netlogic/xlp-hal/sys.h>
54 54
55unsigned long nlm_common_ebase = 0x0; 55uint64_t nlm_io_base;
56 56struct nlm_soc_info nlm_nodes[NLM_NR_NODES];
57/* default to uniprocessor */ 57cpumask_t nlm_cpumask = CPU_MASK_CPU0;
58uint32_t nlm_coremask = 1, nlm_cpumask = 1; 58unsigned int nlm_threads_per_core;
59int nlm_threads_per_core = 1;
60extern u32 __dtb_start[]; 59extern u32 __dtb_start[];
61 60
62static void nlm_linux_exit(void) 61static void nlm_linux_exit(void)
63{ 62{
64 nlm_write_sys_reg(nlm_sys_base, SYS_CHIP_RESET, 1); 63 uint64_t sysbase = nlm_get_node(0)->sysbase;
64
65 nlm_write_sys_reg(sysbase, SYS_CHIP_RESET, 1);
65 for ( ; ; ) 66 for ( ; ; )
66 cpu_wait(); 67 cpu_wait();
67} 68}
68 69
69void __init plat_mem_setup(void) 70void __init plat_mem_setup(void)
70{ 71{
72 void *fdtp;
73
71 panic_timeout = 5; 74 panic_timeout = 5;
72 _machine_restart = (void (*)(char *))nlm_linux_exit; 75 _machine_restart = (void (*)(char *))nlm_linux_exit;
73 _machine_halt = nlm_linux_exit; 76 _machine_halt = nlm_linux_exit;
74 pm_power_off = nlm_linux_exit; 77 pm_power_off = nlm_linux_exit;
78
79 /*
80 * If no FDT pointer is passed in, use the built-in FDT.
81 * device_tree_init() does not handle CKSEG0 pointers in
82 * 64-bit, so convert pointer.
83 */
84 fdtp = (void *)(long)fw_arg0;
85 if (!fdtp)
86 fdtp = __dtb_start;
87 fdtp = phys_to_virt(__pa(fdtp));
88 early_init_devtree(fdtp);
75} 89}
76 90
77const char *get_system_type(void) 91const char *get_system_type(void)
@@ -94,27 +108,19 @@ void xlp_mmu_init(void)
94 (13 + (ffz(PM_DEFAULT_MASK >> 13) / 2))); 108 (13 + (ffz(PM_DEFAULT_MASK >> 13) / 2)));
95} 109}
96 110
97void __init prom_init(void) 111void nlm_percpu_init(int hwcpuid)
98{ 112{
99 void *fdtp; 113}
100 114
115void __init prom_init(void)
116{
117 nlm_io_base = CKSEG1ADDR(XLP_DEFAULT_IO_BASE);
101 xlp_mmu_init(); 118 xlp_mmu_init();
102 nlm_hal_init(); 119 nlm_node_init(0);
103
104 /*
105 * If no FDT pointer is passed in, use the built-in FDT.
106 * device_tree_init() does not handle CKSEG0 pointers in
107 * 64-bit, so convert pointer.
108 */
109 fdtp = (void *)(long)fw_arg0;
110 if (!fdtp)
111 fdtp = __dtb_start;
112 fdtp = phys_to_virt(__pa(fdtp));
113 early_init_devtree(fdtp);
114 120
115 nlm_common_ebase = read_c0_ebase() & (~((1 << 12) - 1));
116#ifdef CONFIG_SMP 121#ifdef CONFIG_SMP
117 nlm_wakeup_secondary_cpus(0xffffffff); 122 cpumask_setall(&nlm_cpumask);
123 nlm_wakeup_secondary_cpus();
118 124
119 /* update TLB size after waking up threads */ 125 /* update TLB size after waking up threads */
120 current_cpu_data.tlbsize = ((read_c0_config6() >> 16) & 0xffff) + 1; 126 current_cpu_data.tlbsize = ((read_c0_config6() >> 16) & 0xffff) + 1;
diff --git a/arch/mips/netlogic/xlp/wakeup.c b/arch/mips/netlogic/xlp/wakeup.c
index 44d923ff384..cb9010642ac 100644
--- a/arch/mips/netlogic/xlp/wakeup.c
+++ b/arch/mips/netlogic/xlp/wakeup.c
@@ -51,45 +51,72 @@
51#include <asm/netlogic/xlp-hal/xlp.h> 51#include <asm/netlogic/xlp-hal/xlp.h>
52#include <asm/netlogic/xlp-hal/sys.h> 52#include <asm/netlogic/xlp-hal/sys.h>
53 53
54static void xlp_enable_secondary_cores(void) 54static int xlp_wakeup_core(uint64_t sysbase, int core)
55{ 55{
56 uint32_t core, value, coremask, syscoremask; 56 uint32_t coremask, value;
57 int count; 57 int count;
58 58
59 /* read cores in reset from SYS block */ 59 coremask = (1 << core);
60 syscoremask = nlm_read_sys_reg(nlm_sys_base, SYS_CPU_RESET);
61 60
62 /* update user specified */ 61 /* Enable CPU clock */
63 nlm_coremask = nlm_coremask & (syscoremask | 1); 62 value = nlm_read_sys_reg(sysbase, SYS_CORE_DFS_DIS_CTRL);
63 value &= ~coremask;
64 nlm_write_sys_reg(sysbase, SYS_CORE_DFS_DIS_CTRL, value);
64 65
65 for (core = 1; core < 8; core++) { 66 /* Remove CPU Reset */
66 coremask = 1 << core; 67 value = nlm_read_sys_reg(sysbase, SYS_CPU_RESET);
67 if ((nlm_coremask & coremask) == 0) 68 value &= ~coremask;
68 continue; 69 nlm_write_sys_reg(sysbase, SYS_CPU_RESET, value);
69 70
70 /* Enable CPU clock */ 71 /* Poll for CPU to mark itself coherent */
71 value = nlm_read_sys_reg(nlm_sys_base, SYS_CORE_DFS_DIS_CTRL); 72 count = 100000;
72 value &= ~coremask; 73 do {
73 nlm_write_sys_reg(nlm_sys_base, SYS_CORE_DFS_DIS_CTRL, value); 74 value = nlm_read_sys_reg(sysbase, SYS_CPU_NONCOHERENT_MODE);
75 } while ((value & coremask) != 0 && --count > 0);
74 76
75 /* Remove CPU Reset */ 77 return count != 0;
76 value = nlm_read_sys_reg(nlm_sys_base, SYS_CPU_RESET); 78}
77 value &= ~coremask; 79
78 nlm_write_sys_reg(nlm_sys_base, SYS_CPU_RESET, value); 80static void xlp_enable_secondary_cores(const cpumask_t *wakeup_mask)
81{
82 struct nlm_soc_info *nodep;
83 uint64_t syspcibase;
84 uint32_t syscoremask;
85 int core, n, cpu;
86
87 for (n = 0; n < NLM_NR_NODES; n++) {
88 syspcibase = nlm_get_sys_pcibase(n);
89 if (nlm_read_reg(syspcibase, 0) == 0xffffffff)
90 break;
91
92 /* read cores in reset from SYS and account for boot cpu */
93 nlm_node_init(n);
94 nodep = nlm_get_node(n);
95 syscoremask = nlm_read_sys_reg(nodep->sysbase, SYS_CPU_RESET);
96 if (n == 0)
97 syscoremask |= 1;
98
99 for (core = 0; core < NLM_CORES_PER_NODE; core++) {
100 /* see if the core exists */
101 if ((syscoremask & (1 << core)) == 0)
102 continue;
79 103
80 /* Poll for CPU to mark itself coherent */ 104 /* see if at least the first thread is enabled */
81 count = 100000; 105 cpu = (n * NLM_CORES_PER_NODE + core)
82 do { 106 * NLM_THREADS_PER_CORE;
83 value = nlm_read_sys_reg(nlm_sys_base, 107 if (!cpumask_test_cpu(cpu, wakeup_mask))
84 SYS_CPU_NONCOHERENT_MODE); 108 continue;
85 } while ((value & coremask) != 0 && count-- > 0);
86 109
87 if (count == 0) 110 /* wake up the core */
88 pr_err("Failed to enable core %d\n", core); 111 if (xlp_wakeup_core(nodep->sysbase, core))
112 nodep->coremask |= 1u << core;
113 else
114 pr_err("Failed to enable core %d\n", core);
115 }
89 } 116 }
90} 117}
91 118
92void xlp_wakeup_secondary_cpus(void) 119void xlp_wakeup_secondary_cpus()
93{ 120{
94 /* 121 /*
95 * In case of u-boot, the secondaries are in reset 122 * In case of u-boot, the secondaries are in reset
@@ -98,5 +125,5 @@ void xlp_wakeup_secondary_cpus(void)
98 xlp_boot_core0_siblings(); 125 xlp_boot_core0_siblings();
99 126
100 /* now get other cores out of reset */ 127 /* now get other cores out of reset */
101 xlp_enable_secondary_cores(); 128 xlp_enable_secondary_cores(&nlm_cpumask);
102} 129}
diff --git a/arch/mips/netlogic/xlr/Makefile b/arch/mips/netlogic/xlr/Makefile
index c287dea8757..05902bc6f08 100644
--- a/arch/mips/netlogic/xlr/Makefile
+++ b/arch/mips/netlogic/xlr/Makefile
@@ -1,2 +1,2 @@
1obj-y += setup.o platform.o platform-flash.o 1obj-y += fmn.o fmn-config.o setup.o platform.o platform-flash.o
2obj-$(CONFIG_SMP) += wakeup.o 2obj-$(CONFIG_SMP) += wakeup.o
diff --git a/arch/mips/netlogic/xlr/fmn-config.c b/arch/mips/netlogic/xlr/fmn-config.c
new file mode 100644
index 00000000000..bed2cffa100
--- /dev/null
+++ b/arch/mips/netlogic/xlr/fmn-config.c
@@ -0,0 +1,290 @@
1/*
2 * Copyright (c) 2003-2012 Broadcom Corporation
3 * All Rights Reserved
4 *
5 * This software is available to you under a choice of one of two
6 * licenses. You may choose to be licensed under the terms of the GNU
7 * General Public License (GPL) Version 2, available from the file
8 * COPYING in the main directory of this source tree, or the Broadcom
9 * license below:
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 *
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in
19 * the documentation and/or other materials provided with the
20 * distribution.
21 *
22 * THIS SOFTWARE IS PROVIDED BY BROADCOM ``AS IS'' AND ANY EXPRESS OR
23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
24 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL BROADCOM OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
29 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
30 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
31 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
32 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 */
34
35#include <asm/cpu-info.h>
36#include <linux/irq.h>
37#include <linux/interrupt.h>
38
39#include <asm/mipsregs.h>
40#include <asm/netlogic/xlr/fmn.h>
41#include <asm/netlogic/xlr/xlr.h>
42#include <asm/netlogic/common.h>
43#include <asm/netlogic/haldefs.h>
44
45struct xlr_board_fmn_config xlr_board_fmn_config;
46
47static void __maybe_unused print_credit_config(struct xlr_fmn_info *fmn_info)
48{
49 int bkt;
50
51 pr_info("Bucket size :\n");
52 pr_info("Station\t: Size\n");
53 for (bkt = 0; bkt < 16; bkt++)
54 pr_info(" %d %d %d %d %d %d %d %d\n",
55 xlr_board_fmn_config.bucket_size[(bkt * 8) + 0],
56 xlr_board_fmn_config.bucket_size[(bkt * 8) + 1],
57 xlr_board_fmn_config.bucket_size[(bkt * 8) + 2],
58 xlr_board_fmn_config.bucket_size[(bkt * 8) + 3],
59 xlr_board_fmn_config.bucket_size[(bkt * 8) + 4],
60 xlr_board_fmn_config.bucket_size[(bkt * 8) + 5],
61 xlr_board_fmn_config.bucket_size[(bkt * 8) + 6],
62 xlr_board_fmn_config.bucket_size[(bkt * 8) + 7]);
63 pr_info("\n");
64
65 pr_info("Credits distribution :\n");
66 pr_info("Station\t: Size\n");
67 for (bkt = 0; bkt < 16; bkt++)
68 pr_info(" %d %d %d %d %d %d %d %d\n",
69 fmn_info->credit_config[(bkt * 8) + 0],
70 fmn_info->credit_config[(bkt * 8) + 1],
71 fmn_info->credit_config[(bkt * 8) + 2],
72 fmn_info->credit_config[(bkt * 8) + 3],
73 fmn_info->credit_config[(bkt * 8) + 4],
74 fmn_info->credit_config[(bkt * 8) + 5],
75 fmn_info->credit_config[(bkt * 8) + 6],
76 fmn_info->credit_config[(bkt * 8) + 7]);
77 pr_info("\n");
78}
79
80static void check_credit_distribution(void)
81{
82 struct xlr_board_fmn_config *cfg = &xlr_board_fmn_config;
83 int bkt, n, total_credits, ncores;
84
85 ncores = hweight32(nlm_current_node()->coremask);
86 for (bkt = 0; bkt < 128; bkt++) {
87 total_credits = 0;
88 for (n = 0; n < ncores; n++)
89 total_credits += cfg->cpu[n].credit_config[bkt];
90 total_credits += cfg->gmac[0].credit_config[bkt];
91 total_credits += cfg->gmac[1].credit_config[bkt];
92 total_credits += cfg->dma.credit_config[bkt];
93 total_credits += cfg->cmp.credit_config[bkt];
94 total_credits += cfg->sae.credit_config[bkt];
95 total_credits += cfg->xgmac[0].credit_config[bkt];
96 total_credits += cfg->xgmac[1].credit_config[bkt];
97 if (total_credits > cfg->bucket_size[bkt])
98 pr_err("ERROR: Bucket %d: credits (%d) > size (%d)\n",
99 bkt, total_credits, cfg->bucket_size[bkt]);
100 }
101 pr_info("Credit distribution complete.\n");
102}
103
104/**
105 * Configure bucket size and credits for a device. 'size' is the size of
106 * the buckets for the device. This size is distributed among all the CPUs
107 * so that all of them can send messages to the device.
108 *
109 * The device is also given 'cpu_credits' to send messages to the CPUs
110 *
111 * @dev_info: FMN information structure for each devices
112 * @start_stn_id: Starting station id of dev_info
113 * @end_stn_id: End station id of dev_info
114 * @num_buckets: Total number of buckets for den_info
115 * @cpu_credits: Allowed credits to cpu for each devices pointing by dev_info
116 * @size: Size of the each buckets in the device station
117 */
118static void setup_fmn_cc(struct xlr_fmn_info *dev_info, int start_stn_id,
119 int end_stn_id, int num_buckets, int cpu_credits, int size)
120{
121 int i, j, num_core, n, credits_per_cpu;
122 struct xlr_fmn_info *cpu = xlr_board_fmn_config.cpu;
123
124 num_core = hweight32(nlm_current_node()->coremask);
125 dev_info->num_buckets = num_buckets;
126 dev_info->start_stn_id = start_stn_id;
127 dev_info->end_stn_id = end_stn_id;
128
129 n = num_core;
130 if (num_core == 3)
131 n = 4;
132
133 for (i = start_stn_id; i <= end_stn_id; i++) {
134 xlr_board_fmn_config.bucket_size[i] = size;
135
136 /* Dividing device credits equally to cpus */
137 credits_per_cpu = size / n;
138 for (j = 0; j < num_core; j++)
139 cpu[j].credit_config[i] = credits_per_cpu;
140
141 /* credits left to distribute */
142 credits_per_cpu = size - (credits_per_cpu * num_core);
143
144 /* distribute the remaining credits (if any), among cores */
145 for (j = 0; (j < num_core) && (credits_per_cpu >= 4); j++) {
146 cpu[j].credit_config[i] += 4;
147 credits_per_cpu -= 4;
148 }
149 }
150
151 /* Distributing cpu per bucket credits to devices */
152 for (i = 0; i < num_core; i++) {
153 for (j = 0; j < FMN_CORE_NBUCKETS; j++)
154 dev_info->credit_config[(i * 8) + j] = cpu_credits;
155 }
156}
157
158/*
159 * Each core has 256 slots and 8 buckets,
160 * Configure the 8 buckets each with 32 slots
161 */
162static void setup_cpu_fmninfo(struct xlr_fmn_info *cpu, int num_core)
163{
164 int i, j;
165
166 for (i = 0; i < num_core; i++) {
167 cpu[i].start_stn_id = (8 * i);
168 cpu[i].end_stn_id = (8 * i + 8);
169
170 for (j = cpu[i].start_stn_id; j < cpu[i].end_stn_id; j++)
171 xlr_board_fmn_config.bucket_size[j] = 32;
172 }
173}
174
175/**
176 * Setup the FMN details for each devices according to the device available
177 * in each variant of XLR/XLS processor
178 */
179void xlr_board_info_setup(void)
180{
181 struct xlr_fmn_info *cpu = xlr_board_fmn_config.cpu;
182 struct xlr_fmn_info *gmac = xlr_board_fmn_config.gmac;
183 struct xlr_fmn_info *xgmac = xlr_board_fmn_config.xgmac;
184 struct xlr_fmn_info *dma = &xlr_board_fmn_config.dma;
185 struct xlr_fmn_info *cmp = &xlr_board_fmn_config.cmp;
186 struct xlr_fmn_info *sae = &xlr_board_fmn_config.sae;
187 int processor_id, num_core;
188
189 num_core = hweight32(nlm_current_node()->coremask);
190 processor_id = read_c0_prid() & 0xff00;
191
192 setup_cpu_fmninfo(cpu, num_core);
193 switch (processor_id) {
194 case PRID_IMP_NETLOGIC_XLS104:
195 case PRID_IMP_NETLOGIC_XLS108:
196 setup_fmn_cc(&gmac[0], FMN_STNID_GMAC0,
197 FMN_STNID_GMAC0_TX3, 8, 16, 32);
198 setup_fmn_cc(dma, FMN_STNID_DMA_0,
199 FMN_STNID_DMA_3, 4, 8, 64);
200 setup_fmn_cc(sae, FMN_STNID_SEC0,
201 FMN_STNID_SEC1, 2, 8, 128);
202 break;
203
204 case PRID_IMP_NETLOGIC_XLS204:
205 case PRID_IMP_NETLOGIC_XLS208:
206 setup_fmn_cc(&gmac[0], FMN_STNID_GMAC0,
207 FMN_STNID_GMAC0_TX3, 8, 16, 32);
208 setup_fmn_cc(dma, FMN_STNID_DMA_0,
209 FMN_STNID_DMA_3, 4, 8, 64);
210 setup_fmn_cc(sae, FMN_STNID_SEC0,
211 FMN_STNID_SEC1, 2, 8, 128);
212 break;
213
214 case PRID_IMP_NETLOGIC_XLS404:
215 case PRID_IMP_NETLOGIC_XLS408:
216 case PRID_IMP_NETLOGIC_XLS404B:
217 case PRID_IMP_NETLOGIC_XLS408B:
218 case PRID_IMP_NETLOGIC_XLS416B:
219 setup_fmn_cc(&gmac[0], FMN_STNID_GMAC0,
220 FMN_STNID_GMAC0_TX3, 8, 8, 32);
221 setup_fmn_cc(&gmac[1], FMN_STNID_GMAC1_FR_0,
222 FMN_STNID_GMAC1_TX3, 8, 8, 32);
223 setup_fmn_cc(dma, FMN_STNID_DMA_0,
224 FMN_STNID_DMA_3, 4, 4, 64);
225 setup_fmn_cc(cmp, FMN_STNID_CMP_0,
226 FMN_STNID_CMP_3, 4, 4, 64);
227 setup_fmn_cc(sae, FMN_STNID_SEC0,
228 FMN_STNID_SEC1, 2, 8, 128);
229 break;
230
231 case PRID_IMP_NETLOGIC_XLS412B:
232 setup_fmn_cc(&gmac[0], FMN_STNID_GMAC0,
233 FMN_STNID_GMAC0_TX3, 8, 8, 32);
234 setup_fmn_cc(&gmac[1], FMN_STNID_GMAC1_FR_0,
235 FMN_STNID_GMAC1_TX3, 8, 8, 32);
236 setup_fmn_cc(dma, FMN_STNID_DMA_0,
237 FMN_STNID_DMA_3, 4, 4, 64);
238 setup_fmn_cc(cmp, FMN_STNID_CMP_0,
239 FMN_STNID_CMP_3, 4, 4, 64);
240 setup_fmn_cc(sae, FMN_STNID_SEC0,
241 FMN_STNID_SEC1, 2, 8, 128);
242 break;
243
244 case PRID_IMP_NETLOGIC_XLR308:
245 case PRID_IMP_NETLOGIC_XLR308C:
246 setup_fmn_cc(&gmac[0], FMN_STNID_GMAC0,
247 FMN_STNID_GMAC0_TX3, 8, 16, 32);
248 setup_fmn_cc(dma, FMN_STNID_DMA_0,
249 FMN_STNID_DMA_3, 4, 8, 64);
250 setup_fmn_cc(sae, FMN_STNID_SEC0,
251 FMN_STNID_SEC1, 2, 4, 128);
252 break;
253
254 case PRID_IMP_NETLOGIC_XLR532:
255 case PRID_IMP_NETLOGIC_XLR532C:
256 case PRID_IMP_NETLOGIC_XLR516C:
257 case PRID_IMP_NETLOGIC_XLR508C:
258 setup_fmn_cc(&gmac[0], FMN_STNID_GMAC0,
259 FMN_STNID_GMAC0_TX3, 8, 16, 32);
260 setup_fmn_cc(dma, FMN_STNID_DMA_0,
261 FMN_STNID_DMA_3, 4, 8, 64);
262 setup_fmn_cc(sae, FMN_STNID_SEC0,
263 FMN_STNID_SEC1, 2, 4, 128);
264 break;
265
266 case PRID_IMP_NETLOGIC_XLR732:
267 case PRID_IMP_NETLOGIC_XLR716:
268 setup_fmn_cc(&xgmac[0], FMN_STNID_XMAC0_00_TX,
269 FMN_STNID_XMAC0_15_TX, 8, 0, 32);
270 setup_fmn_cc(&xgmac[1], FMN_STNID_XMAC1_00_TX,
271 FMN_STNID_XMAC1_15_TX, 8, 0, 32);
272 setup_fmn_cc(&gmac[0], FMN_STNID_GMAC0,
273 FMN_STNID_GMAC0_TX3, 8, 24, 32);
274 setup_fmn_cc(dma, FMN_STNID_DMA_0,
275 FMN_STNID_DMA_3, 4, 4, 64);
276 setup_fmn_cc(sae, FMN_STNID_SEC0,
277 FMN_STNID_SEC1, 2, 4, 128);
278 break;
279 default:
280 pr_err("Unknown CPU with processor ID [%d]\n", processor_id);
281 pr_err("Error: Cannot initialize FMN credits.\n");
282 }
283
284 check_credit_distribution();
285
286#if 0 /* debug */
287 print_credit_config(&cpu[0]);
288 print_credit_config(&gmac[0]);
289#endif
290}
diff --git a/arch/mips/netlogic/xlr/fmn.c b/arch/mips/netlogic/xlr/fmn.c
new file mode 100644
index 00000000000..4d74f03de50
--- /dev/null
+++ b/arch/mips/netlogic/xlr/fmn.c
@@ -0,0 +1,204 @@
1/*
2 * Copyright (c) 2003-2012 Broadcom Corporation
3 * All Rights Reserved
4 *
5 * This software is available to you under a choice of one of two
6 * licenses. You may choose to be licensed under the terms of the GNU
7 * General Public License (GPL) Version 2, available from the file
8 * COPYING in the main directory of this source tree, or the Broadcom
9 * license below:
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 *
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in
19 * the documentation and/or other materials provided with the
20 * distribution.
21 *
22 * THIS SOFTWARE IS PROVIDED BY BROADCOM ``AS IS'' AND ANY EXPRESS OR
23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
24 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL BROADCOM OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
29 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
30 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
31 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
32 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 */
34
35#include <linux/kernel.h>
36#include <linux/irqreturn.h>
37#include <linux/irq.h>
38#include <linux/interrupt.h>
39
40#include <asm/mipsregs.h>
41#include <asm/netlogic/interrupt.h>
42#include <asm/netlogic/xlr/fmn.h>
43#include <asm/netlogic/common.h>
44
45#define COP2_CC_INIT_CPU_DEST(dest, conf) \
46do { \
47 nlm_write_c2_cc##dest(0, conf[(dest * 8) + 0]); \
48 nlm_write_c2_cc##dest(1, conf[(dest * 8) + 1]); \
49 nlm_write_c2_cc##dest(2, conf[(dest * 8) + 2]); \
50 nlm_write_c2_cc##dest(3, conf[(dest * 8) + 3]); \
51 nlm_write_c2_cc##dest(4, conf[(dest * 8) + 4]); \
52 nlm_write_c2_cc##dest(5, conf[(dest * 8) + 5]); \
53 nlm_write_c2_cc##dest(6, conf[(dest * 8) + 6]); \
54 nlm_write_c2_cc##dest(7, conf[(dest * 8) + 7]); \
55} while (0)
56
57struct fmn_message_handler {
58 void (*action)(int, int, int, int, struct nlm_fmn_msg *, void *);
59 void *arg;
60} msg_handlers[128];
61
62/*
63 * FMN interrupt handler. We configure the FMN so that any messages in
64 * any of the CPU buckets will trigger an interrupt on the CPU.
65 * The message can be from any device on the FMN (like NAE/SAE/DMA).
66 * The source station id is used to figure out which of the registered
67 * handlers have to be called.
68 */
69static irqreturn_t fmn_message_handler(int irq, void *data)
70{
71 struct fmn_message_handler *hndlr;
72 int bucket, rv;
73 int size = 0, code = 0, src_stnid = 0;
74 struct nlm_fmn_msg msg;
75 uint32_t mflags, bkt_status;
76
77 mflags = nlm_cop2_enable();
78 /* Disable message ring interrupt */
79 nlm_fmn_setup_intr(irq, 0);
80 while (1) {
81 /* 8 bkts per core, [24:31] each bit represents one bucket
82 * Bit is Zero if bucket is not empty */
83 bkt_status = (nlm_read_c2_status() >> 24) & 0xff;
84 if (bkt_status == 0xff)
85 break;
86 for (bucket = 0; bucket < 8; bucket++) {
87 /* Continue on empty bucket */
88 if (bkt_status & (1 << bucket))
89 continue;
90 rv = nlm_fmn_receive(bucket, &size, &code, &src_stnid,
91 &msg);
92 if (rv != 0)
93 continue;
94
95 hndlr = &msg_handlers[src_stnid];
96 if (hndlr->action == NULL)
97 pr_warn("No msgring handler for stnid %d\n",
98 src_stnid);
99 else {
100 nlm_cop2_restore(mflags);
101 hndlr->action(bucket, src_stnid, size, code,
102 &msg, hndlr->arg);
103 mflags = nlm_cop2_enable();
104 }
105 }
106 };
107 /* Enable message ring intr, to any thread in core */
108 nlm_fmn_setup_intr(irq, (1 << nlm_threads_per_core) - 1);
109 nlm_cop2_restore(mflags);
110 return IRQ_HANDLED;
111}
112
113struct irqaction fmn_irqaction = {
114 .handler = fmn_message_handler,
115 .flags = IRQF_PERCPU,
116 .name = "fmn",
117};
118
119void xlr_percpu_fmn_init(void)
120{
121 struct xlr_fmn_info *cpu_fmn_info;
122 int *bucket_sizes;
123 uint32_t flags;
124 int id;
125
126 BUG_ON(nlm_thread_id() != 0);
127 id = nlm_core_id();
128
129 bucket_sizes = xlr_board_fmn_config.bucket_size;
130 cpu_fmn_info = &xlr_board_fmn_config.cpu[id];
131 flags = nlm_cop2_enable();
132
133 /* Setup bucket sizes for the core. */
134 nlm_write_c2_bucksize(0, bucket_sizes[id * 8 + 0]);
135 nlm_write_c2_bucksize(1, bucket_sizes[id * 8 + 1]);
136 nlm_write_c2_bucksize(2, bucket_sizes[id * 8 + 2]);
137 nlm_write_c2_bucksize(3, bucket_sizes[id * 8 + 3]);
138 nlm_write_c2_bucksize(4, bucket_sizes[id * 8 + 4]);
139 nlm_write_c2_bucksize(5, bucket_sizes[id * 8 + 5]);
140 nlm_write_c2_bucksize(6, bucket_sizes[id * 8 + 6]);
141 nlm_write_c2_bucksize(7, bucket_sizes[id * 8 + 7]);
142
143 /*
144 * For sending FMN messages, we need credits on the destination
145 * bucket. Program the credits this core has on the 128 possible
146 * destination buckets.
147 * We cannot use a loop here, because the the first argument has
148 * to be a constant integer value.
149 */
150 COP2_CC_INIT_CPU_DEST(0, cpu_fmn_info->credit_config);
151 COP2_CC_INIT_CPU_DEST(1, cpu_fmn_info->credit_config);
152 COP2_CC_INIT_CPU_DEST(2, cpu_fmn_info->credit_config);
153 COP2_CC_INIT_CPU_DEST(3, cpu_fmn_info->credit_config);
154 COP2_CC_INIT_CPU_DEST(4, cpu_fmn_info->credit_config);
155 COP2_CC_INIT_CPU_DEST(5, cpu_fmn_info->credit_config);
156 COP2_CC_INIT_CPU_DEST(6, cpu_fmn_info->credit_config);
157 COP2_CC_INIT_CPU_DEST(7, cpu_fmn_info->credit_config);
158 COP2_CC_INIT_CPU_DEST(8, cpu_fmn_info->credit_config);
159 COP2_CC_INIT_CPU_DEST(9, cpu_fmn_info->credit_config);
160 COP2_CC_INIT_CPU_DEST(10, cpu_fmn_info->credit_config);
161 COP2_CC_INIT_CPU_DEST(11, cpu_fmn_info->credit_config);
162 COP2_CC_INIT_CPU_DEST(12, cpu_fmn_info->credit_config);
163 COP2_CC_INIT_CPU_DEST(13, cpu_fmn_info->credit_config);
164 COP2_CC_INIT_CPU_DEST(14, cpu_fmn_info->credit_config);
165 COP2_CC_INIT_CPU_DEST(15, cpu_fmn_info->credit_config);
166
167 /* enable FMN interrupts on this CPU */
168 nlm_fmn_setup_intr(IRQ_FMN, (1 << nlm_threads_per_core) - 1);
169 nlm_cop2_restore(flags);
170}
171
172
173/*
174 * Register a FMN message handler with respect to the source station id
175 * @stnid: source station id
176 * @action: Handler function pointer
177 */
178int nlm_register_fmn_handler(int start_stnid, int end_stnid,
179 void (*action)(int, int, int, int, struct nlm_fmn_msg *, void *),
180 void *arg)
181{
182 int sstnid;
183
184 for (sstnid = start_stnid; sstnid <= end_stnid; sstnid++) {
185 msg_handlers[sstnid].arg = arg;
186 smp_wmb();
187 msg_handlers[sstnid].action = action;
188 }
189 pr_debug("Registered FMN msg handler for stnid %d-%d\n",
190 start_stnid, end_stnid);
191 return 0;
192}
193
194void nlm_setup_fmn_irq(void)
195{
196 uint32_t flags;
197
198 /* setup irq only once */
199 setup_irq(IRQ_FMN, &fmn_irqaction);
200
201 flags = nlm_cop2_enable();
202 nlm_fmn_setup_intr(IRQ_FMN, (1 << nlm_threads_per_core) - 1);
203 nlm_cop2_restore(flags);
204}
diff --git a/arch/mips/netlogic/xlr/setup.c b/arch/mips/netlogic/xlr/setup.c
index 81b1d311834..4e7f49d3d5a 100644
--- a/arch/mips/netlogic/xlr/setup.c
+++ b/arch/mips/netlogic/xlr/setup.c
@@ -49,16 +49,15 @@
49#include <asm/netlogic/xlr/iomap.h> 49#include <asm/netlogic/xlr/iomap.h>
50#include <asm/netlogic/xlr/pic.h> 50#include <asm/netlogic/xlr/pic.h>
51#include <asm/netlogic/xlr/gpio.h> 51#include <asm/netlogic/xlr/gpio.h>
52#include <asm/netlogic/xlr/fmn.h>
52 53
53uint64_t nlm_io_base = DEFAULT_NETLOGIC_IO_BASE; 54uint64_t nlm_io_base = DEFAULT_NETLOGIC_IO_BASE;
54uint64_t nlm_pic_base;
55struct psb_info nlm_prom_info; 55struct psb_info nlm_prom_info;
56 56
57unsigned long nlm_common_ebase = 0x0;
58
59/* default to uniprocessor */ 57/* default to uniprocessor */
60uint32_t nlm_coremask = 1, nlm_cpumask = 1; 58unsigned int nlm_threads_per_core = 1;
61int nlm_threads_per_core = 1; 59struct nlm_soc_info nlm_nodes[NLM_NR_NODES];
60cpumask_t nlm_cpumask = CPU_MASK_CPU0;
62 61
63static void __init nlm_early_serial_setup(void) 62static void __init nlm_early_serial_setup(void)
64{ 63{
@@ -113,6 +112,12 @@ void __init prom_free_prom_memory(void)
113 /* Nothing yet */ 112 /* Nothing yet */
114} 113}
115 114
115void nlm_percpu_init(int hwcpuid)
116{
117 if (hwcpuid % 4 == 0)
118 xlr_percpu_fmn_init();
119}
120
116static void __init build_arcs_cmdline(int *argv) 121static void __init build_arcs_cmdline(int *argv)
117{ 122{
118 int i, remain, len; 123 int i, remain, len;
@@ -176,9 +181,19 @@ static void prom_add_memory(void)
176 } 181 }
177} 182}
178 183
184static void nlm_init_node(void)
185{
186 struct nlm_soc_info *nodep;
187
188 nodep = nlm_current_node();
189 nodep->picbase = nlm_mmio_base(NETLOGIC_IO_PIC_OFFSET);
190 nodep->ebase = read_c0_ebase() & (~((1 << 12) - 1));
191 spin_lock_init(&nodep->piclock);
192}
193
179void __init prom_init(void) 194void __init prom_init(void)
180{ 195{
181 int *argv, *envp; /* passed as 32 bit ptrs */ 196 int i, *argv, *envp; /* passed as 32 bit ptrs */
182 struct psb_info *prom_infop; 197 struct psb_info *prom_infop;
183 198
184 /* truncate to 32 bit and sign extend all args */ 199 /* truncate to 32 bit and sign extend all args */
@@ -187,15 +202,19 @@ void __init prom_init(void)
187 prom_infop = (struct psb_info *)(long)(int)fw_arg3; 202 prom_infop = (struct psb_info *)(long)(int)fw_arg3;
188 203
189 nlm_prom_info = *prom_infop; 204 nlm_prom_info = *prom_infop;
190 nlm_pic_base = nlm_mmio_base(NETLOGIC_IO_PIC_OFFSET); 205 nlm_init_node();
191 206
192 nlm_early_serial_setup(); 207 nlm_early_serial_setup();
193 build_arcs_cmdline(argv); 208 build_arcs_cmdline(argv);
194 nlm_common_ebase = read_c0_ebase() & (~((1 << 12) - 1));
195 prom_add_memory(); 209 prom_add_memory();
196 210
197#ifdef CONFIG_SMP 211#ifdef CONFIG_SMP
198 nlm_wakeup_secondary_cpus(nlm_prom_info.online_cpu_map); 212 for (i = 0; i < 32; i++)
213 if (nlm_prom_info.online_cpu_map & (1 << i))
214 cpumask_set_cpu(i, &nlm_cpumask);
215 nlm_wakeup_secondary_cpus();
199 register_smp_ops(&nlm_smp_ops); 216 register_smp_ops(&nlm_smp_ops);
200#endif 217#endif
218 xlr_board_info_setup();
219 xlr_percpu_fmn_init();
201} 220}
diff --git a/arch/mips/netlogic/xlr/wakeup.c b/arch/mips/netlogic/xlr/wakeup.c
index db5d987d488..3ebf7411d67 100644
--- a/arch/mips/netlogic/xlr/wakeup.c
+++ b/arch/mips/netlogic/xlr/wakeup.c
@@ -33,6 +33,7 @@
33 */ 33 */
34 34
35#include <linux/init.h> 35#include <linux/init.h>
36#include <linux/delay.h>
36#include <linux/threads.h> 37#include <linux/threads.h>
37 38
38#include <asm/asm.h> 39#include <asm/asm.h>
@@ -50,18 +51,34 @@
50 51
51int __cpuinit xlr_wakeup_secondary_cpus(void) 52int __cpuinit xlr_wakeup_secondary_cpus(void)
52{ 53{
53 unsigned int i, boot_cpu; 54 struct nlm_soc_info *nodep;
55 unsigned int i, j, boot_cpu;
54 56
55 /* 57 /*
56 * In case of RMI boot, hit with NMI to get the cores 58 * In case of RMI boot, hit with NMI to get the cores
57 * from bootloader to linux code. 59 * from bootloader to linux code.
58 */ 60 */
61 nodep = nlm_get_node(0);
59 boot_cpu = hard_smp_processor_id(); 62 boot_cpu = hard_smp_processor_id();
60 nlm_set_nmi_handler(nlm_rmiboot_preboot); 63 nlm_set_nmi_handler(nlm_rmiboot_preboot);
61 for (i = 0; i < NR_CPUS; i++) { 64 for (i = 0; i < NR_CPUS; i++) {
62 if (i == boot_cpu || (nlm_cpumask & (1u << i)) == 0) 65 if (i == boot_cpu || !cpumask_test_cpu(i, &nlm_cpumask))
63 continue; 66 continue;
64 nlm_pic_send_ipi(nlm_pic_base, i, 1, 1); /* send NMI */ 67 nlm_pic_send_ipi(nodep->picbase, i, 1, 1); /* send NMI */
68 }
69
70 /* Fill up the coremask early */
71 nodep->coremask = 1;
72 for (i = 1; i < NLM_CORES_PER_NODE; i++) {
73 for (j = 1000000; j > 0; j--) {
74 if (nlm_cpu_ready[i * NLM_THREADS_PER_CORE])
75 break;
76 udelay(10);
77 }
78 if (j != 0)
79 nodep->coremask |= (1u << i);
80 else
81 pr_err("Failed to wakeup core %d\n", i);
65 } 82 }
66 83
67 return 0; 84 return 0;
diff --git a/arch/mips/oprofile/Makefile b/arch/mips/oprofile/Makefile
index 8232dbd1228..9c0a6782c09 100644
--- a/arch/mips/oprofile/Makefile
+++ b/arch/mips/oprofile/Makefile
@@ -12,4 +12,5 @@ oprofile-$(CONFIG_CPU_MIPS32) += op_model_mipsxx.o
12oprofile-$(CONFIG_CPU_MIPS64) += op_model_mipsxx.o 12oprofile-$(CONFIG_CPU_MIPS64) += op_model_mipsxx.o
13oprofile-$(CONFIG_CPU_R10000) += op_model_mipsxx.o 13oprofile-$(CONFIG_CPU_R10000) += op_model_mipsxx.o
14oprofile-$(CONFIG_CPU_SB1) += op_model_mipsxx.o 14oprofile-$(CONFIG_CPU_SB1) += op_model_mipsxx.o
15oprofile-$(CONFIG_CPU_XLR) += op_model_mipsxx.o
15oprofile-$(CONFIG_CPU_LOONGSON2) += op_model_loongson2.o 16oprofile-$(CONFIG_CPU_LOONGSON2) += op_model_loongson2.o
diff --git a/arch/mips/oprofile/common.c b/arch/mips/oprofile/common.c
index be387faef87..e32db1ff02c 100644
--- a/arch/mips/oprofile/common.c
+++ b/arch/mips/oprofile/common.c
@@ -90,6 +90,7 @@ int __init oprofile_arch_init(struct oprofile_operations *ops)
90 case CPU_R10000: 90 case CPU_R10000:
91 case CPU_R12000: 91 case CPU_R12000:
92 case CPU_R14000: 92 case CPU_R14000:
93 case CPU_XLR:
93 lmodel = &op_model_mipsxx_ops; 94 lmodel = &op_model_mipsxx_ops;
94 break; 95 break;
95 96
diff --git a/arch/mips/oprofile/op_model_mipsxx.c b/arch/mips/oprofile/op_model_mipsxx.c
index 28ea1a4cc57..78625463040 100644
--- a/arch/mips/oprofile/op_model_mipsxx.c
+++ b/arch/mips/oprofile/op_model_mipsxx.c
@@ -31,8 +31,22 @@
31 31
32#define M_COUNTER_OVERFLOW (1UL << 31) 32#define M_COUNTER_OVERFLOW (1UL << 31)
33 33
34/* Netlogic XLR specific, count events in all threads in a core */
35#define M_PERFCTL_COUNT_ALL_THREADS (1UL << 13)
36
34static int (*save_perf_irq)(void); 37static int (*save_perf_irq)(void);
35 38
39/*
40 * XLR has only one set of counters per core. Designate the
41 * first hardware thread in the core for setup and init.
42 * Skip CPUs with non-zero hardware thread id (4 hwt per core)
43 */
44#ifdef CONFIG_CPU_XLR
45#define oprofile_skip_cpu(c) ((cpu_logical_map(c) & 0x3) != 0)
46#else
47#define oprofile_skip_cpu(c) 0
48#endif
49
36#ifdef CONFIG_MIPS_MT_SMP 50#ifdef CONFIG_MIPS_MT_SMP
37static int cpu_has_mipsmt_pertccounters; 51static int cpu_has_mipsmt_pertccounters;
38#define WHAT (M_TC_EN_VPE | \ 52#define WHAT (M_TC_EN_VPE | \
@@ -152,6 +166,8 @@ static void mipsxx_reg_setup(struct op_counter_config *ctr)
152 reg.control[i] |= M_PERFCTL_USER; 166 reg.control[i] |= M_PERFCTL_USER;
153 if (ctr[i].exl) 167 if (ctr[i].exl)
154 reg.control[i] |= M_PERFCTL_EXL; 168 reg.control[i] |= M_PERFCTL_EXL;
169 if (current_cpu_type() == CPU_XLR)
170 reg.control[i] |= M_PERFCTL_COUNT_ALL_THREADS;
155 reg.counter[i] = 0x80000000 - ctr[i].count; 171 reg.counter[i] = 0x80000000 - ctr[i].count;
156 } 172 }
157} 173}
@@ -162,6 +178,9 @@ static void mipsxx_cpu_setup(void *args)
162{ 178{
163 unsigned int counters = op_model_mipsxx_ops.num_counters; 179 unsigned int counters = op_model_mipsxx_ops.num_counters;
164 180
181 if (oprofile_skip_cpu(smp_processor_id()))
182 return;
183
165 switch (counters) { 184 switch (counters) {
166 case 4: 185 case 4:
167 w_c0_perfctrl3(0); 186 w_c0_perfctrl3(0);
@@ -183,6 +202,9 @@ static void mipsxx_cpu_start(void *args)
183{ 202{
184 unsigned int counters = op_model_mipsxx_ops.num_counters; 203 unsigned int counters = op_model_mipsxx_ops.num_counters;
185 204
205 if (oprofile_skip_cpu(smp_processor_id()))
206 return;
207
186 switch (counters) { 208 switch (counters) {
187 case 4: 209 case 4:
188 w_c0_perfctrl3(WHAT | reg.control[3]); 210 w_c0_perfctrl3(WHAT | reg.control[3]);
@@ -200,6 +222,9 @@ static void mipsxx_cpu_stop(void *args)
200{ 222{
201 unsigned int counters = op_model_mipsxx_ops.num_counters; 223 unsigned int counters = op_model_mipsxx_ops.num_counters;
202 224
225 if (oprofile_skip_cpu(smp_processor_id()))
226 return;
227
203 switch (counters) { 228 switch (counters) {
204 case 4: 229 case 4:
205 w_c0_perfctrl3(0); 230 w_c0_perfctrl3(0);
@@ -372,6 +397,10 @@ static int __init mipsxx_init(void)
372 op_model_mipsxx_ops.cpu_type = "mips/loongson1"; 397 op_model_mipsxx_ops.cpu_type = "mips/loongson1";
373 break; 398 break;
374 399
400 case CPU_XLR:
401 op_model_mipsxx_ops.cpu_type = "mips/xlr";
402 break;
403
375 default: 404 default:
376 printk(KERN_ERR "Profiling unsupported for this CPU\n"); 405 printk(KERN_ERR "Profiling unsupported for this CPU\n");
377 406
diff --git a/arch/mips/pci/pci-bcm63xx.c b/arch/mips/pci/pci-bcm63xx.c
index 8a48139d219..ca179b6ff39 100644
--- a/arch/mips/pci/pci-bcm63xx.c
+++ b/arch/mips/pci/pci-bcm63xx.c
@@ -11,8 +11,11 @@
11#include <linux/kernel.h> 11#include <linux/kernel.h>
12#include <linux/init.h> 12#include <linux/init.h>
13#include <linux/delay.h> 13#include <linux/delay.h>
14#include <linux/clk.h>
14#include <asm/bootinfo.h> 15#include <asm/bootinfo.h>
15 16
17#include <bcm63xx_reset.h>
18
16#include "pci-bcm63xx.h" 19#include "pci-bcm63xx.h"
17 20
18/* 21/*
@@ -119,41 +122,36 @@ static void __init bcm63xx_reset_pcie(void)
119{ 122{
120 u32 val; 123 u32 val;
121 124
122 /* enable clock */
123 val = bcm_perf_readl(PERF_CKCTL_REG);
124 val |= CKCTL_6328_PCIE_EN;
125 bcm_perf_writel(val, PERF_CKCTL_REG);
126
127 /* enable SERDES */ 125 /* enable SERDES */
128 val = bcm_misc_readl(MISC_SERDES_CTRL_REG); 126 val = bcm_misc_readl(MISC_SERDES_CTRL_REG);
129 val |= SERDES_PCIE_EN | SERDES_PCIE_EXD_EN; 127 val |= SERDES_PCIE_EN | SERDES_PCIE_EXD_EN;
130 bcm_misc_writel(val, MISC_SERDES_CTRL_REG); 128 bcm_misc_writel(val, MISC_SERDES_CTRL_REG);
131 129
132 /* reset the PCIe core */ 130 /* reset the PCIe core */
133 val = bcm_perf_readl(PERF_SOFTRESET_6328_REG); 131 bcm63xx_core_set_reset(BCM63XX_RESET_PCIE, 1);
134 132 bcm63xx_core_set_reset(BCM63XX_RESET_PCIE_EXT, 1);
135 val &= ~SOFTRESET_6328_PCIE_MASK;
136 val &= ~SOFTRESET_6328_PCIE_CORE_MASK;
137 val &= ~SOFTRESET_6328_PCIE_HARD_MASK;
138 val &= ~SOFTRESET_6328_PCIE_EXT_MASK;
139 bcm_perf_writel(val, PERF_SOFTRESET_6328_REG);
140 mdelay(10); 133 mdelay(10);
141 134
142 val |= SOFTRESET_6328_PCIE_MASK; 135 bcm63xx_core_set_reset(BCM63XX_RESET_PCIE, 0);
143 val |= SOFTRESET_6328_PCIE_CORE_MASK;
144 val |= SOFTRESET_6328_PCIE_HARD_MASK;
145 bcm_perf_writel(val, PERF_SOFTRESET_6328_REG);
146 mdelay(10); 136 mdelay(10);
147 137
148 val |= SOFTRESET_6328_PCIE_EXT_MASK; 138 bcm63xx_core_set_reset(BCM63XX_RESET_PCIE_EXT, 0);
149 bcm_perf_writel(val, PERF_SOFTRESET_6328_REG);
150 mdelay(200); 139 mdelay(200);
151} 140}
152 141
142static struct clk *pcie_clk;
143
153static int __init bcm63xx_register_pcie(void) 144static int __init bcm63xx_register_pcie(void)
154{ 145{
155 u32 val; 146 u32 val;
156 147
148 /* enable clock */
149 pcie_clk = clk_get(NULL, "pcie");
150 if (IS_ERR_OR_NULL(pcie_clk))
151 return -ENODEV;
152
153 clk_prepare_enable(pcie_clk);
154
157 bcm63xx_reset_pcie(); 155 bcm63xx_reset_pcie();
158 156
159 /* configure the PCIe bridge */ 157 /* configure the PCIe bridge */
diff --git a/arch/mips/pci/pci-xlr.c b/arch/mips/pci/pci-xlr.c
index 18af021d289..0c18ccc7962 100644
--- a/arch/mips/pci/pci-xlr.c
+++ b/arch/mips/pci/pci-xlr.c
@@ -47,6 +47,7 @@
47 47
48#include <asm/netlogic/interrupt.h> 48#include <asm/netlogic/interrupt.h>
49#include <asm/netlogic/haldefs.h> 49#include <asm/netlogic/haldefs.h>
50#include <asm/netlogic/common.h>
50 51
51#include <asm/netlogic/xlr/msidef.h> 52#include <asm/netlogic/xlr/msidef.h>
52#include <asm/netlogic/xlr/iomap.h> 53#include <asm/netlogic/xlr/iomap.h>
@@ -174,22 +175,9 @@ static struct pci_dev *xls_get_pcie_link(const struct pci_dev *dev)
174 return p ? bus->self : NULL; 175 return p ? bus->self : NULL;
175} 176}
176 177
177static int get_irq_vector(const struct pci_dev *dev) 178static int nlm_pci_link_to_irq(int link)
178{ 179{
179 struct pci_dev *lnk; 180 switch (link) {
180
181 if (!nlm_chip_is_xls())
182 return PIC_PCIX_IRQ; /* for XLR just one IRQ */
183
184 /*
185 * For XLS PCIe, there is an IRQ per Link, find out which
186 * link the device is on to assign interrupts
187 */
188 lnk = xls_get_pcie_link(dev);
189 if (lnk == NULL)
190 return 0;
191
192 switch (PCI_SLOT(lnk->devfn)) {
193 case 0: 181 case 0:
194 return PIC_PCIE_LINK0_IRQ; 182 return PIC_PCIE_LINK0_IRQ;
195 case 1: 183 case 1:
@@ -205,10 +193,26 @@ static int get_irq_vector(const struct pci_dev *dev)
205 else 193 else
206 return PIC_PCIE_LINK3_IRQ; 194 return PIC_PCIE_LINK3_IRQ;
207 } 195 }
208 WARN(1, "Unexpected devfn %d\n", lnk->devfn); 196 WARN(1, "Unexpected link %d\n", link);
209 return 0; 197 return 0;
210} 198}
211 199
200static int get_irq_vector(const struct pci_dev *dev)
201{
202 struct pci_dev *lnk;
203 int link;
204
205 if (!nlm_chip_is_xls())
206 return PIC_PCIX_IRQ; /* for XLR just one IRQ */
207
208 lnk = xls_get_pcie_link(dev);
209 if (lnk == NULL)
210 return 0;
211
212 link = PCI_SLOT(lnk->devfn);
213 return nlm_pci_link_to_irq(link);
214}
215
212#ifdef CONFIG_PCI_MSI 216#ifdef CONFIG_PCI_MSI
213void destroy_irq(unsigned int irq) 217void destroy_irq(unsigned int irq)
214{ 218{
@@ -332,6 +336,9 @@ int pcibios_plat_dev_init(struct pci_dev *dev)
332 336
333static int __init pcibios_init(void) 337static int __init pcibios_init(void)
334{ 338{
339 void (*extra_ack)(struct irq_data *);
340 int link, irq;
341
335 /* PSB assigns PCI resources */ 342 /* PSB assigns PCI resources */
336 pci_set_flags(PCI_PROBE_ONLY); 343 pci_set_flags(PCI_PROBE_ONLY);
337 pci_config_base = ioremap(DEFAULT_PCI_CONFIG_BASE, 16 << 20); 344 pci_config_base = ioremap(DEFAULT_PCI_CONFIG_BASE, 16 << 20);
@@ -350,27 +357,19 @@ static int __init pcibios_init(void)
350 * For PCI interrupts, we need to ack the PCI controller too, overload 357 * For PCI interrupts, we need to ack the PCI controller too, overload
351 * irq handler data to do this 358 * irq handler data to do this
352 */ 359 */
353 if (nlm_chip_is_xls()) { 360 if (!nlm_chip_is_xls()) {
354 if (nlm_chip_is_xls_b()) {
355 irq_set_handler_data(PIC_PCIE_LINK0_IRQ,
356 xls_pcie_ack_b);
357 irq_set_handler_data(PIC_PCIE_LINK1_IRQ,
358 xls_pcie_ack_b);
359 irq_set_handler_data(PIC_PCIE_XLSB0_LINK2_IRQ,
360 xls_pcie_ack_b);
361 irq_set_handler_data(PIC_PCIE_XLSB0_LINK3_IRQ,
362 xls_pcie_ack_b);
363 } else {
364 irq_set_handler_data(PIC_PCIE_LINK0_IRQ, xls_pcie_ack);
365 irq_set_handler_data(PIC_PCIE_LINK1_IRQ, xls_pcie_ack);
366 irq_set_handler_data(PIC_PCIE_LINK2_IRQ, xls_pcie_ack);
367 irq_set_handler_data(PIC_PCIE_LINK3_IRQ, xls_pcie_ack);
368 }
369 } else {
370 /* XLR PCI controller ACK */ 361 /* XLR PCI controller ACK */
371 irq_set_handler_data(PIC_PCIX_IRQ, xlr_pci_ack); 362 nlm_set_pic_extra_ack(0, PIC_PCIX_IRQ, xlr_pci_ack);
363 } else {
364 if (nlm_chip_is_xls_b())
365 extra_ack = xls_pcie_ack_b;
366 else
367 extra_ack = xls_pcie_ack;
368 for (link = 0; link < 4; link++) {
369 irq = nlm_pci_link_to_irq(link);
370 nlm_set_pic_extra_ack(0, irq, extra_ack);
371 }
372 } 372 }
373
374 return 0; 373 return 0;
375} 374}
376 375
diff --git a/drivers/bcma/Kconfig b/drivers/bcma/Kconfig
index a533af21836..d7b56a88c9f 100644
--- a/drivers/bcma/Kconfig
+++ b/drivers/bcma/Kconfig
@@ -65,6 +65,15 @@ config BCMA_DRIVER_GMAC_CMN
65 65
66 If unsure, say N 66 If unsure, say N
67 67
68config BCMA_DRIVER_GPIO
69 bool "BCMA GPIO driver"
70 depends on BCMA
71 select GPIOLIB
72 help
73 Driver to provide access to the GPIO pins of the bcma bus.
74
75 If unsure, say N
76
68config BCMA_DEBUG 77config BCMA_DEBUG
69 bool "BCMA debugging" 78 bool "BCMA debugging"
70 depends on BCMA 79 depends on BCMA
diff --git a/drivers/bcma/Makefile b/drivers/bcma/Makefile
index 8ad42d41b2f..734b32f09c0 100644
--- a/drivers/bcma/Makefile
+++ b/drivers/bcma/Makefile
@@ -6,6 +6,7 @@ bcma-y += driver_pci.o
6bcma-$(CONFIG_BCMA_DRIVER_PCI_HOSTMODE) += driver_pci_host.o 6bcma-$(CONFIG_BCMA_DRIVER_PCI_HOSTMODE) += driver_pci_host.o
7bcma-$(CONFIG_BCMA_DRIVER_MIPS) += driver_mips.o 7bcma-$(CONFIG_BCMA_DRIVER_MIPS) += driver_mips.o
8bcma-$(CONFIG_BCMA_DRIVER_GMAC_CMN) += driver_gmac_cmn.o 8bcma-$(CONFIG_BCMA_DRIVER_GMAC_CMN) += driver_gmac_cmn.o
9bcma-$(CONFIG_BCMA_DRIVER_GPIO) += driver_gpio.o
9bcma-$(CONFIG_BCMA_HOST_PCI) += host_pci.o 10bcma-$(CONFIG_BCMA_HOST_PCI) += host_pci.o
10bcma-$(CONFIG_BCMA_HOST_SOC) += host_soc.o 11bcma-$(CONFIG_BCMA_HOST_SOC) += host_soc.o
11obj-$(CONFIG_BCMA) += bcma.o 12obj-$(CONFIG_BCMA) += bcma.o
diff --git a/drivers/bcma/bcma_private.h b/drivers/bcma/bcma_private.h
index 169fc58427d..8cd80bff8e9 100644
--- a/drivers/bcma/bcma_private.h
+++ b/drivers/bcma/bcma_private.h
@@ -89,4 +89,14 @@ bool __devinit bcma_core_pci_is_in_hostmode(struct bcma_drv_pci *pc);
89void __devinit bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc); 89void __devinit bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc);
90#endif /* CONFIG_BCMA_DRIVER_PCI_HOSTMODE */ 90#endif /* CONFIG_BCMA_DRIVER_PCI_HOSTMODE */
91 91
92#ifdef CONFIG_BCMA_DRIVER_GPIO
93/* driver_gpio.c */
94int bcma_gpio_init(struct bcma_drv_cc *cc);
95#else
96static inline int bcma_gpio_init(struct bcma_drv_cc *cc)
97{
98 return -ENOTSUPP;
99}
100#endif /* CONFIG_BCMA_DRIVER_GPIO */
101
92#endif 102#endif
diff --git a/drivers/bcma/driver_chipcommon.c b/drivers/bcma/driver_chipcommon.c
index a4c3ebcc4c8..994fce65f77 100644
--- a/drivers/bcma/driver_chipcommon.c
+++ b/drivers/bcma/driver_chipcommon.c
@@ -30,6 +30,8 @@ void bcma_core_chipcommon_init(struct bcma_drv_cc *cc)
30 if (cc->setup_done) 30 if (cc->setup_done)
31 return; 31 return;
32 32
33 spin_lock_init(&cc->gpio_lock);
34
33 if (cc->core->id.rev >= 11) 35 if (cc->core->id.rev >= 11)
34 cc->status = bcma_cc_read32(cc, BCMA_CC_CHIPSTAT); 36 cc->status = bcma_cc_read32(cc, BCMA_CC_CHIPSTAT);
35 cc->capabilities = bcma_cc_read32(cc, BCMA_CC_CAP); 37 cc->capabilities = bcma_cc_read32(cc, BCMA_CC_CAP);
@@ -84,28 +86,97 @@ u32 bcma_chipco_gpio_in(struct bcma_drv_cc *cc, u32 mask)
84 86
85u32 bcma_chipco_gpio_out(struct bcma_drv_cc *cc, u32 mask, u32 value) 87u32 bcma_chipco_gpio_out(struct bcma_drv_cc *cc, u32 mask, u32 value)
86{ 88{
87 return bcma_cc_write32_masked(cc, BCMA_CC_GPIOOUT, mask, value); 89 unsigned long flags;
90 u32 res;
91
92 spin_lock_irqsave(&cc->gpio_lock, flags);
93 res = bcma_cc_write32_masked(cc, BCMA_CC_GPIOOUT, mask, value);
94 spin_unlock_irqrestore(&cc->gpio_lock, flags);
95
96 return res;
88} 97}
89 98
90u32 bcma_chipco_gpio_outen(struct bcma_drv_cc *cc, u32 mask, u32 value) 99u32 bcma_chipco_gpio_outen(struct bcma_drv_cc *cc, u32 mask, u32 value)
91{ 100{
92 return bcma_cc_write32_masked(cc, BCMA_CC_GPIOOUTEN, mask, value); 101 unsigned long flags;
102 u32 res;
103
104 spin_lock_irqsave(&cc->gpio_lock, flags);
105 res = bcma_cc_write32_masked(cc, BCMA_CC_GPIOOUTEN, mask, value);
106 spin_unlock_irqrestore(&cc->gpio_lock, flags);
107
108 return res;
93} 109}
94 110
111/*
112 * If the bit is set to 0, chipcommon controlls this GPIO,
113 * if the bit is set to 1, it is used by some part of the chip and not our code.
114 */
95u32 bcma_chipco_gpio_control(struct bcma_drv_cc *cc, u32 mask, u32 value) 115u32 bcma_chipco_gpio_control(struct bcma_drv_cc *cc, u32 mask, u32 value)
96{ 116{
97 return bcma_cc_write32_masked(cc, BCMA_CC_GPIOCTL, mask, value); 117 unsigned long flags;
118 u32 res;
119
120 spin_lock_irqsave(&cc->gpio_lock, flags);
121 res = bcma_cc_write32_masked(cc, BCMA_CC_GPIOCTL, mask, value);
122 spin_unlock_irqrestore(&cc->gpio_lock, flags);
123
124 return res;
98} 125}
99EXPORT_SYMBOL_GPL(bcma_chipco_gpio_control); 126EXPORT_SYMBOL_GPL(bcma_chipco_gpio_control);
100 127
101u32 bcma_chipco_gpio_intmask(struct bcma_drv_cc *cc, u32 mask, u32 value) 128u32 bcma_chipco_gpio_intmask(struct bcma_drv_cc *cc, u32 mask, u32 value)
102{ 129{
103 return bcma_cc_write32_masked(cc, BCMA_CC_GPIOIRQ, mask, value); 130 unsigned long flags;
131 u32 res;
132
133 spin_lock_irqsave(&cc->gpio_lock, flags);
134 res = bcma_cc_write32_masked(cc, BCMA_CC_GPIOIRQ, mask, value);
135 spin_unlock_irqrestore(&cc->gpio_lock, flags);
136
137 return res;
104} 138}
105 139
106u32 bcma_chipco_gpio_polarity(struct bcma_drv_cc *cc, u32 mask, u32 value) 140u32 bcma_chipco_gpio_polarity(struct bcma_drv_cc *cc, u32 mask, u32 value)
107{ 141{
108 return bcma_cc_write32_masked(cc, BCMA_CC_GPIOPOL, mask, value); 142 unsigned long flags;
143 u32 res;
144
145 spin_lock_irqsave(&cc->gpio_lock, flags);
146 res = bcma_cc_write32_masked(cc, BCMA_CC_GPIOPOL, mask, value);
147 spin_unlock_irqrestore(&cc->gpio_lock, flags);
148
149 return res;
150}
151
152u32 bcma_chipco_gpio_pullup(struct bcma_drv_cc *cc, u32 mask, u32 value)
153{
154 unsigned long flags;
155 u32 res;
156
157 if (cc->core->id.rev < 20)
158 return 0;
159
160 spin_lock_irqsave(&cc->gpio_lock, flags);
161 res = bcma_cc_write32_masked(cc, BCMA_CC_GPIOPULLUP, mask, value);
162 spin_unlock_irqrestore(&cc->gpio_lock, flags);
163
164 return res;
165}
166
167u32 bcma_chipco_gpio_pulldown(struct bcma_drv_cc *cc, u32 mask, u32 value)
168{
169 unsigned long flags;
170 u32 res;
171
172 if (cc->core->id.rev < 20)
173 return 0;
174
175 spin_lock_irqsave(&cc->gpio_lock, flags);
176 res = bcma_cc_write32_masked(cc, BCMA_CC_GPIOPULLDOWN, mask, value);
177 spin_unlock_irqrestore(&cc->gpio_lock, flags);
178
179 return res;
109} 180}
110 181
111#ifdef CONFIG_BCMA_DRIVER_MIPS 182#ifdef CONFIG_BCMA_DRIVER_MIPS
diff --git a/drivers/bcma/driver_gpio.c b/drivers/bcma/driver_gpio.c
new file mode 100644
index 00000000000..9a6f585da2d
--- /dev/null
+++ b/drivers/bcma/driver_gpio.c
@@ -0,0 +1,98 @@
1/*
2 * Broadcom specific AMBA
3 * GPIO driver
4 *
5 * Copyright 2011, Broadcom Corporation
6 * Copyright 2012, Hauke Mehrtens <hauke@hauke-m.de>
7 *
8 * Licensed under the GNU/GPL. See COPYING for details.
9 */
10
11#include <linux/gpio.h>
12#include <linux/export.h>
13#include <linux/bcma/bcma.h>
14
15#include "bcma_private.h"
16
17static inline struct bcma_drv_cc *bcma_gpio_get_cc(struct gpio_chip *chip)
18{
19 return container_of(chip, struct bcma_drv_cc, gpio);
20}
21
22static int bcma_gpio_get_value(struct gpio_chip *chip, unsigned gpio)
23{
24 struct bcma_drv_cc *cc = bcma_gpio_get_cc(chip);
25
26 return !!bcma_chipco_gpio_in(cc, 1 << gpio);
27}
28
29static void bcma_gpio_set_value(struct gpio_chip *chip, unsigned gpio,
30 int value)
31{
32 struct bcma_drv_cc *cc = bcma_gpio_get_cc(chip);
33
34 bcma_chipco_gpio_out(cc, 1 << gpio, value ? 1 << gpio : 0);
35}
36
37static int bcma_gpio_direction_input(struct gpio_chip *chip, unsigned gpio)
38{
39 struct bcma_drv_cc *cc = bcma_gpio_get_cc(chip);
40
41 bcma_chipco_gpio_outen(cc, 1 << gpio, 0);
42 return 0;
43}
44
45static int bcma_gpio_direction_output(struct gpio_chip *chip, unsigned gpio,
46 int value)
47{
48 struct bcma_drv_cc *cc = bcma_gpio_get_cc(chip);
49
50 bcma_chipco_gpio_outen(cc, 1 << gpio, 1 << gpio);
51 bcma_chipco_gpio_out(cc, 1 << gpio, value ? 1 << gpio : 0);
52 return 0;
53}
54
55static int bcma_gpio_request(struct gpio_chip *chip, unsigned gpio)
56{
57 struct bcma_drv_cc *cc = bcma_gpio_get_cc(chip);
58
59 bcma_chipco_gpio_control(cc, 1 << gpio, 0);
60 /* clear pulldown */
61 bcma_chipco_gpio_pulldown(cc, 1 << gpio, 0);
62 /* Set pullup */
63 bcma_chipco_gpio_pullup(cc, 1 << gpio, 1 << gpio);
64
65 return 0;
66}
67
68static void bcma_gpio_free(struct gpio_chip *chip, unsigned gpio)
69{
70 struct bcma_drv_cc *cc = bcma_gpio_get_cc(chip);
71
72 /* clear pullup */
73 bcma_chipco_gpio_pullup(cc, 1 << gpio, 0);
74}
75
76int bcma_gpio_init(struct bcma_drv_cc *cc)
77{
78 struct gpio_chip *chip = &cc->gpio;
79
80 chip->label = "bcma_gpio";
81 chip->owner = THIS_MODULE;
82 chip->request = bcma_gpio_request;
83 chip->free = bcma_gpio_free;
84 chip->get = bcma_gpio_get_value;
85 chip->set = bcma_gpio_set_value;
86 chip->direction_input = bcma_gpio_direction_input;
87 chip->direction_output = bcma_gpio_direction_output;
88 chip->ngpio = 16;
89 /* There is just one SoC in one device and its GPIO addresses should be
90 * deterministic to address them more easily. The other buses could get
91 * a random base number. */
92 if (cc->core->bus->hosttype == BCMA_HOSTTYPE_SOC)
93 chip->base = 0;
94 else
95 chip->base = -1;
96
97 return gpiochip_add(chip);
98}
diff --git a/drivers/bcma/main.c b/drivers/bcma/main.c
index d865470bc95..478ba01ca0c 100644
--- a/drivers/bcma/main.c
+++ b/drivers/bcma/main.c
@@ -152,6 +152,11 @@ static int bcma_register_cores(struct bcma_bus *bus)
152 bcma_err(bus, "Error registering NAND flash\n"); 152 bcma_err(bus, "Error registering NAND flash\n");
153 } 153 }
154#endif 154#endif
155 err = bcma_gpio_init(&bus->drv_cc);
156 if (err == -ENOTSUPP)
157 bcma_debug(bus, "GPIO driver not activated\n");
158 else if (err)
159 bcma_err(bus, "Error registering GPIO driver: %i\n", err);
155 160
156 return 0; 161 return 0;
157} 162}
diff --git a/drivers/ssb/Kconfig b/drivers/ssb/Kconfig
index 42cdaa9a4d8..ff3c8a21f10 100644
--- a/drivers/ssb/Kconfig
+++ b/drivers/ssb/Kconfig
@@ -160,4 +160,13 @@ config SSB_DRIVER_GIGE
160 160
161 If unsure, say N 161 If unsure, say N
162 162
163config SSB_DRIVER_GPIO
164 bool "SSB GPIO driver"
165 depends on SSB
166 select GPIOLIB
167 help
168 Driver to provide access to the GPIO pins on the bus.
169
170 If unsure, say N
171
163endmenu 172endmenu
diff --git a/drivers/ssb/Makefile b/drivers/ssb/Makefile
index 656e58b9261..9159ba77c38 100644
--- a/drivers/ssb/Makefile
+++ b/drivers/ssb/Makefile
@@ -15,6 +15,7 @@ ssb-$(CONFIG_SSB_DRIVER_MIPS) += driver_mipscore.o
15ssb-$(CONFIG_SSB_DRIVER_EXTIF) += driver_extif.o 15ssb-$(CONFIG_SSB_DRIVER_EXTIF) += driver_extif.o
16ssb-$(CONFIG_SSB_DRIVER_PCICORE) += driver_pcicore.o 16ssb-$(CONFIG_SSB_DRIVER_PCICORE) += driver_pcicore.o
17ssb-$(CONFIG_SSB_DRIVER_GIGE) += driver_gige.o 17ssb-$(CONFIG_SSB_DRIVER_GIGE) += driver_gige.o
18ssb-$(CONFIG_SSB_DRIVER_GPIO) += driver_gpio.o
18 19
19# b43 pci-ssb-bridge driver 20# b43 pci-ssb-bridge driver
20# Not strictly a part of SSB, but kept here for convenience 21# Not strictly a part of SSB, but kept here for convenience
diff --git a/drivers/ssb/driver_chipcommon.c b/drivers/ssb/driver_chipcommon.c
index e9d2ca11283..24e02bb2ecd 100644
--- a/drivers/ssb/driver_chipcommon.c
+++ b/drivers/ssb/driver_chipcommon.c
@@ -284,6 +284,9 @@ void ssb_chipcommon_init(struct ssb_chipcommon *cc)
284{ 284{
285 if (!cc->dev) 285 if (!cc->dev)
286 return; /* We don't have a ChipCommon */ 286 return; /* We don't have a ChipCommon */
287
288 spin_lock_init(&cc->gpio_lock);
289
287 if (cc->dev->id.revision >= 11) 290 if (cc->dev->id.revision >= 11)
288 cc->status = chipco_read32(cc, SSB_CHIPCO_CHIPSTAT); 291 cc->status = chipco_read32(cc, SSB_CHIPCO_CHIPSTAT);
289 ssb_dprintk(KERN_INFO PFX "chipcommon status is 0x%x\n", cc->status); 292 ssb_dprintk(KERN_INFO PFX "chipcommon status is 0x%x\n", cc->status);
@@ -418,28 +421,93 @@ u32 ssb_chipco_gpio_in(struct ssb_chipcommon *cc, u32 mask)
418 421
419u32 ssb_chipco_gpio_out(struct ssb_chipcommon *cc, u32 mask, u32 value) 422u32 ssb_chipco_gpio_out(struct ssb_chipcommon *cc, u32 mask, u32 value)
420{ 423{
421 return chipco_write32_masked(cc, SSB_CHIPCO_GPIOOUT, mask, value); 424 unsigned long flags;
425 u32 res = 0;
426
427 spin_lock_irqsave(&cc->gpio_lock, flags);
428 res = chipco_write32_masked(cc, SSB_CHIPCO_GPIOOUT, mask, value);
429 spin_unlock_irqrestore(&cc->gpio_lock, flags);
430
431 return res;
422} 432}
423 433
424u32 ssb_chipco_gpio_outen(struct ssb_chipcommon *cc, u32 mask, u32 value) 434u32 ssb_chipco_gpio_outen(struct ssb_chipcommon *cc, u32 mask, u32 value)
425{ 435{
426 return chipco_write32_masked(cc, SSB_CHIPCO_GPIOOUTEN, mask, value); 436 unsigned long flags;
437 u32 res = 0;
438
439 spin_lock_irqsave(&cc->gpio_lock, flags);
440 res = chipco_write32_masked(cc, SSB_CHIPCO_GPIOOUTEN, mask, value);
441 spin_unlock_irqrestore(&cc->gpio_lock, flags);
442
443 return res;
427} 444}
428 445
429u32 ssb_chipco_gpio_control(struct ssb_chipcommon *cc, u32 mask, u32 value) 446u32 ssb_chipco_gpio_control(struct ssb_chipcommon *cc, u32 mask, u32 value)
430{ 447{
431 return chipco_write32_masked(cc, SSB_CHIPCO_GPIOCTL, mask, value); 448 unsigned long flags;
449 u32 res = 0;
450
451 spin_lock_irqsave(&cc->gpio_lock, flags);
452 res = chipco_write32_masked(cc, SSB_CHIPCO_GPIOCTL, mask, value);
453 spin_unlock_irqrestore(&cc->gpio_lock, flags);
454
455 return res;
432} 456}
433EXPORT_SYMBOL(ssb_chipco_gpio_control); 457EXPORT_SYMBOL(ssb_chipco_gpio_control);
434 458
435u32 ssb_chipco_gpio_intmask(struct ssb_chipcommon *cc, u32 mask, u32 value) 459u32 ssb_chipco_gpio_intmask(struct ssb_chipcommon *cc, u32 mask, u32 value)
436{ 460{
437 return chipco_write32_masked(cc, SSB_CHIPCO_GPIOIRQ, mask, value); 461 unsigned long flags;
462 u32 res = 0;
463
464 spin_lock_irqsave(&cc->gpio_lock, flags);
465 res = chipco_write32_masked(cc, SSB_CHIPCO_GPIOIRQ, mask, value);
466 spin_unlock_irqrestore(&cc->gpio_lock, flags);
467
468 return res;
438} 469}
439 470
440u32 ssb_chipco_gpio_polarity(struct ssb_chipcommon *cc, u32 mask, u32 value) 471u32 ssb_chipco_gpio_polarity(struct ssb_chipcommon *cc, u32 mask, u32 value)
441{ 472{
442 return chipco_write32_masked(cc, SSB_CHIPCO_GPIOPOL, mask, value); 473 unsigned long flags;
474 u32 res = 0;
475
476 spin_lock_irqsave(&cc->gpio_lock, flags);
477 res = chipco_write32_masked(cc, SSB_CHIPCO_GPIOPOL, mask, value);
478 spin_unlock_irqrestore(&cc->gpio_lock, flags);
479
480 return res;
481}
482
483u32 ssb_chipco_gpio_pullup(struct ssb_chipcommon *cc, u32 mask, u32 value)
484{
485 unsigned long flags;
486 u32 res = 0;
487
488 if (cc->dev->id.revision < 20)
489 return 0xffffffff;
490
491 spin_lock_irqsave(&cc->gpio_lock, flags);
492 res = chipco_write32_masked(cc, SSB_CHIPCO_GPIOPULLUP, mask, value);
493 spin_unlock_irqrestore(&cc->gpio_lock, flags);
494
495 return res;
496}
497
498u32 ssb_chipco_gpio_pulldown(struct ssb_chipcommon *cc, u32 mask, u32 value)
499{
500 unsigned long flags;
501 u32 res = 0;
502
503 if (cc->dev->id.revision < 20)
504 return 0xffffffff;
505
506 spin_lock_irqsave(&cc->gpio_lock, flags);
507 res = chipco_write32_masked(cc, SSB_CHIPCO_GPIOPULLDOWN, mask, value);
508 spin_unlock_irqrestore(&cc->gpio_lock, flags);
509
510 return res;
443} 511}
444 512
445#ifdef CONFIG_SSB_SERIAL 513#ifdef CONFIG_SSB_SERIAL
diff --git a/drivers/ssb/driver_extif.c b/drivers/ssb/driver_extif.c
index dc47f30e9cf..e1d0bb8ad72 100644
--- a/drivers/ssb/driver_extif.c
+++ b/drivers/ssb/driver_extif.c
@@ -118,6 +118,13 @@ void ssb_extif_watchdog_timer_set(struct ssb_extif *extif,
118 extif_write32(extif, SSB_EXTIF_WATCHDOG, ticks); 118 extif_write32(extif, SSB_EXTIF_WATCHDOG, ticks);
119} 119}
120 120
121void ssb_extif_init(struct ssb_extif *extif)
122{
123 if (!extif->dev)
124 return; /* We don't have a Extif core */
125 spin_lock_init(&extif->gpio_lock);
126}
127
121u32 ssb_extif_gpio_in(struct ssb_extif *extif, u32 mask) 128u32 ssb_extif_gpio_in(struct ssb_extif *extif, u32 mask)
122{ 129{
123 return extif_read32(extif, SSB_EXTIF_GPIO_IN) & mask; 130 return extif_read32(extif, SSB_EXTIF_GPIO_IN) & mask;
@@ -125,22 +132,50 @@ u32 ssb_extif_gpio_in(struct ssb_extif *extif, u32 mask)
125 132
126u32 ssb_extif_gpio_out(struct ssb_extif *extif, u32 mask, u32 value) 133u32 ssb_extif_gpio_out(struct ssb_extif *extif, u32 mask, u32 value)
127{ 134{
128 return extif_write32_masked(extif, SSB_EXTIF_GPIO_OUT(0), 135 unsigned long flags;
136 u32 res = 0;
137
138 spin_lock_irqsave(&extif->gpio_lock, flags);
139 res = extif_write32_masked(extif, SSB_EXTIF_GPIO_OUT(0),
129 mask, value); 140 mask, value);
141 spin_unlock_irqrestore(&extif->gpio_lock, flags);
142
143 return res;
130} 144}
131 145
132u32 ssb_extif_gpio_outen(struct ssb_extif *extif, u32 mask, u32 value) 146u32 ssb_extif_gpio_outen(struct ssb_extif *extif, u32 mask, u32 value)
133{ 147{
134 return extif_write32_masked(extif, SSB_EXTIF_GPIO_OUTEN(0), 148 unsigned long flags;
149 u32 res = 0;
150
151 spin_lock_irqsave(&extif->gpio_lock, flags);
152 res = extif_write32_masked(extif, SSB_EXTIF_GPIO_OUTEN(0),
135 mask, value); 153 mask, value);
154 spin_unlock_irqrestore(&extif->gpio_lock, flags);
155
156 return res;
136} 157}
137 158
138u32 ssb_extif_gpio_polarity(struct ssb_extif *extif, u32 mask, u32 value) 159u32 ssb_extif_gpio_polarity(struct ssb_extif *extif, u32 mask, u32 value)
139{ 160{
140 return extif_write32_masked(extif, SSB_EXTIF_GPIO_INTPOL, mask, value); 161 unsigned long flags;
162 u32 res = 0;
163
164 spin_lock_irqsave(&extif->gpio_lock, flags);
165 res = extif_write32_masked(extif, SSB_EXTIF_GPIO_INTPOL, mask, value);
166 spin_unlock_irqrestore(&extif->gpio_lock, flags);
167
168 return res;
141} 169}
142 170
143u32 ssb_extif_gpio_intmask(struct ssb_extif *extif, u32 mask, u32 value) 171u32 ssb_extif_gpio_intmask(struct ssb_extif *extif, u32 mask, u32 value)
144{ 172{
145 return extif_write32_masked(extif, SSB_EXTIF_GPIO_INTMASK, mask, value); 173 unsigned long flags;
174 u32 res = 0;
175
176 spin_lock_irqsave(&extif->gpio_lock, flags);
177 res = extif_write32_masked(extif, SSB_EXTIF_GPIO_INTMASK, mask, value);
178 spin_unlock_irqrestore(&extif->gpio_lock, flags);
179
180 return res;
146} 181}
diff --git a/drivers/ssb/driver_gpio.c b/drivers/ssb/driver_gpio.c
new file mode 100644
index 00000000000..97ac0a38e3d
--- /dev/null
+++ b/drivers/ssb/driver_gpio.c
@@ -0,0 +1,176 @@
1/*
2 * Sonics Silicon Backplane
3 * GPIO driver
4 *
5 * Copyright 2011, Broadcom Corporation
6 * Copyright 2012, Hauke Mehrtens <hauke@hauke-m.de>
7 *
8 * Licensed under the GNU/GPL. See COPYING for details.
9 */
10
11#include <linux/gpio.h>
12#include <linux/export.h>
13#include <linux/ssb/ssb.h>
14
15#include "ssb_private.h"
16
17static struct ssb_bus *ssb_gpio_get_bus(struct gpio_chip *chip)
18{
19 return container_of(chip, struct ssb_bus, gpio);
20}
21
22static int ssb_gpio_chipco_get_value(struct gpio_chip *chip, unsigned gpio)
23{
24 struct ssb_bus *bus = ssb_gpio_get_bus(chip);
25
26 return !!ssb_chipco_gpio_in(&bus->chipco, 1 << gpio);
27}
28
29static void ssb_gpio_chipco_set_value(struct gpio_chip *chip, unsigned gpio,
30 int value)
31{
32 struct ssb_bus *bus = ssb_gpio_get_bus(chip);
33
34 ssb_chipco_gpio_out(&bus->chipco, 1 << gpio, value ? 1 << gpio : 0);
35}
36
37static int ssb_gpio_chipco_direction_input(struct gpio_chip *chip,
38 unsigned gpio)
39{
40 struct ssb_bus *bus = ssb_gpio_get_bus(chip);
41
42 ssb_chipco_gpio_outen(&bus->chipco, 1 << gpio, 0);
43 return 0;
44}
45
46static int ssb_gpio_chipco_direction_output(struct gpio_chip *chip,
47 unsigned gpio, int value)
48{
49 struct ssb_bus *bus = ssb_gpio_get_bus(chip);
50
51 ssb_chipco_gpio_outen(&bus->chipco, 1 << gpio, 1 << gpio);
52 ssb_chipco_gpio_out(&bus->chipco, 1 << gpio, value ? 1 << gpio : 0);
53 return 0;
54}
55
56static int ssb_gpio_chipco_request(struct gpio_chip *chip, unsigned gpio)
57{
58 struct ssb_bus *bus = ssb_gpio_get_bus(chip);
59
60 ssb_chipco_gpio_control(&bus->chipco, 1 << gpio, 0);
61 /* clear pulldown */
62 ssb_chipco_gpio_pulldown(&bus->chipco, 1 << gpio, 0);
63 /* Set pullup */
64 ssb_chipco_gpio_pullup(&bus->chipco, 1 << gpio, 1 << gpio);
65
66 return 0;
67}
68
69static void ssb_gpio_chipco_free(struct gpio_chip *chip, unsigned gpio)
70{
71 struct ssb_bus *bus = ssb_gpio_get_bus(chip);
72
73 /* clear pullup */
74 ssb_chipco_gpio_pullup(&bus->chipco, 1 << gpio, 0);
75}
76
77static int ssb_gpio_chipco_init(struct ssb_bus *bus)
78{
79 struct gpio_chip *chip = &bus->gpio;
80
81 chip->label = "ssb_chipco_gpio";
82 chip->owner = THIS_MODULE;
83 chip->request = ssb_gpio_chipco_request;
84 chip->free = ssb_gpio_chipco_free;
85 chip->get = ssb_gpio_chipco_get_value;
86 chip->set = ssb_gpio_chipco_set_value;
87 chip->direction_input = ssb_gpio_chipco_direction_input;
88 chip->direction_output = ssb_gpio_chipco_direction_output;
89 chip->ngpio = 16;
90 /* There is just one SoC in one device and its GPIO addresses should be
91 * deterministic to address them more easily. The other buses could get
92 * a random base number. */
93 if (bus->bustype == SSB_BUSTYPE_SSB)
94 chip->base = 0;
95 else
96 chip->base = -1;
97
98 return gpiochip_add(chip);
99}
100
101#ifdef CONFIG_SSB_DRIVER_EXTIF
102
103static int ssb_gpio_extif_get_value(struct gpio_chip *chip, unsigned gpio)
104{
105 struct ssb_bus *bus = ssb_gpio_get_bus(chip);
106
107 return !!ssb_extif_gpio_in(&bus->extif, 1 << gpio);
108}
109
110static void ssb_gpio_extif_set_value(struct gpio_chip *chip, unsigned gpio,
111 int value)
112{
113 struct ssb_bus *bus = ssb_gpio_get_bus(chip);
114
115 ssb_extif_gpio_out(&bus->extif, 1 << gpio, value ? 1 << gpio : 0);
116}
117
118static int ssb_gpio_extif_direction_input(struct gpio_chip *chip,
119 unsigned gpio)
120{
121 struct ssb_bus *bus = ssb_gpio_get_bus(chip);
122
123 ssb_extif_gpio_outen(&bus->extif, 1 << gpio, 0);
124 return 0;
125}
126
127static int ssb_gpio_extif_direction_output(struct gpio_chip *chip,
128 unsigned gpio, int value)
129{
130 struct ssb_bus *bus = ssb_gpio_get_bus(chip);
131
132 ssb_extif_gpio_outen(&bus->extif, 1 << gpio, 1 << gpio);
133 ssb_extif_gpio_out(&bus->extif, 1 << gpio, value ? 1 << gpio : 0);
134 return 0;
135}
136
137static int ssb_gpio_extif_init(struct ssb_bus *bus)
138{
139 struct gpio_chip *chip = &bus->gpio;
140
141 chip->label = "ssb_extif_gpio";
142 chip->owner = THIS_MODULE;
143 chip->get = ssb_gpio_extif_get_value;
144 chip->set = ssb_gpio_extif_set_value;
145 chip->direction_input = ssb_gpio_extif_direction_input;
146 chip->direction_output = ssb_gpio_extif_direction_output;
147 chip->ngpio = 5;
148 /* There is just one SoC in one device and its GPIO addresses should be
149 * deterministic to address them more easily. The other buses could get
150 * a random base number. */
151 if (bus->bustype == SSB_BUSTYPE_SSB)
152 chip->base = 0;
153 else
154 chip->base = -1;
155
156 return gpiochip_add(chip);
157}
158
159#else
160static int ssb_gpio_extif_init(struct ssb_bus *bus)
161{
162 return -ENOTSUPP;
163}
164#endif
165
166int ssb_gpio_init(struct ssb_bus *bus)
167{
168 if (ssb_chipco_available(&bus->chipco))
169 return ssb_gpio_chipco_init(bus);
170 else if (ssb_extif_available(&bus->extif))
171 return ssb_gpio_extif_init(bus);
172 else
173 SSB_WARN_ON(1);
174
175 return -1;
176}
diff --git a/drivers/ssb/main.c b/drivers/ssb/main.c
index df0f145c22f..87f0ddf4f3f 100644
--- a/drivers/ssb/main.c
+++ b/drivers/ssb/main.c
@@ -796,7 +796,14 @@ static int __devinit ssb_bus_register(struct ssb_bus *bus,
796 if (err) 796 if (err)
797 goto err_pcmcia_exit; 797 goto err_pcmcia_exit;
798 ssb_chipcommon_init(&bus->chipco); 798 ssb_chipcommon_init(&bus->chipco);
799 ssb_extif_init(&bus->extif);
799 ssb_mipscore_init(&bus->mipscore); 800 ssb_mipscore_init(&bus->mipscore);
801 err = ssb_gpio_init(bus);
802 if (err == -ENOTSUPP)
803 ssb_dprintk(KERN_DEBUG PFX "GPIO driver not activated\n");
804 else if (err)
805 ssb_dprintk(KERN_ERR PFX
806 "Error registering GPIO driver: %i\n", err);
800 err = ssb_fetch_invariants(bus, get_invariants); 807 err = ssb_fetch_invariants(bus, get_invariants);
801 if (err) { 808 if (err) {
802 ssb_bus_may_powerdown(bus); 809 ssb_bus_may_powerdown(bus);
diff --git a/drivers/ssb/ssb_private.h b/drivers/ssb/ssb_private.h
index a305550b4b6..463b76a2140 100644
--- a/drivers/ssb/ssb_private.h
+++ b/drivers/ssb/ssb_private.h
@@ -211,4 +211,21 @@ static inline void b43_pci_ssb_bridge_exit(void)
211extern u32 ssb_pmu_get_cpu_clock(struct ssb_chipcommon *cc); 211extern u32 ssb_pmu_get_cpu_clock(struct ssb_chipcommon *cc);
212extern u32 ssb_pmu_get_controlclock(struct ssb_chipcommon *cc); 212extern u32 ssb_pmu_get_controlclock(struct ssb_chipcommon *cc);
213 213
214#ifdef CONFIG_SSB_DRIVER_EXTIF
215extern void ssb_extif_init(struct ssb_extif *extif);
216#else
217static inline void ssb_extif_init(struct ssb_extif *extif)
218{
219}
220#endif
221
222#ifdef CONFIG_SSB_DRIVER_GPIO
223extern int ssb_gpio_init(struct ssb_bus *bus);
224#else /* CONFIG_SSB_DRIVER_GPIO */
225static inline int ssb_gpio_init(struct ssb_bus *bus)
226{
227 return -ENOTSUPP;
228}
229#endif /* CONFIG_SSB_DRIVER_GPIO */
230
214#endif /* LINUX_SSB_PRIVATE_H_ */ 231#endif /* LINUX_SSB_PRIVATE_H_ */
diff --git a/include/linux/bcma/bcma_driver_chipcommon.h b/include/linux/bcma/bcma_driver_chipcommon.h
index 1cf1749440a..7d662a988d2 100644
--- a/include/linux/bcma/bcma_driver_chipcommon.h
+++ b/include/linux/bcma/bcma_driver_chipcommon.h
@@ -1,6 +1,8 @@
1#ifndef LINUX_BCMA_DRIVER_CC_H_ 1#ifndef LINUX_BCMA_DRIVER_CC_H_
2#define LINUX_BCMA_DRIVER_CC_H_ 2#define LINUX_BCMA_DRIVER_CC_H_
3 3
4#include <linux/gpio.h>
5
4/** ChipCommon core registers. **/ 6/** ChipCommon core registers. **/
5#define BCMA_CC_ID 0x0000 7#define BCMA_CC_ID 0x0000
6#define BCMA_CC_ID_ID 0x0000FFFF 8#define BCMA_CC_ID_ID 0x0000FFFF
@@ -567,6 +569,12 @@ struct bcma_drv_cc {
567 int nr_serial_ports; 569 int nr_serial_ports;
568 struct bcma_serial_port serial_ports[4]; 570 struct bcma_serial_port serial_ports[4];
569#endif /* CONFIG_BCMA_DRIVER_MIPS */ 571#endif /* CONFIG_BCMA_DRIVER_MIPS */
572
573 /* Lock for GPIO register access. */
574 spinlock_t gpio_lock;
575#ifdef CONFIG_BCMA_DRIVER_GPIO
576 struct gpio_chip gpio;
577#endif
570}; 578};
571 579
572/* Register access */ 580/* Register access */
@@ -603,6 +611,8 @@ u32 bcma_chipco_gpio_outen(struct bcma_drv_cc *cc, u32 mask, u32 value);
603u32 bcma_chipco_gpio_control(struct bcma_drv_cc *cc, u32 mask, u32 value); 611u32 bcma_chipco_gpio_control(struct bcma_drv_cc *cc, u32 mask, u32 value);
604u32 bcma_chipco_gpio_intmask(struct bcma_drv_cc *cc, u32 mask, u32 value); 612u32 bcma_chipco_gpio_intmask(struct bcma_drv_cc *cc, u32 mask, u32 value);
605u32 bcma_chipco_gpio_polarity(struct bcma_drv_cc *cc, u32 mask, u32 value); 613u32 bcma_chipco_gpio_polarity(struct bcma_drv_cc *cc, u32 mask, u32 value);
614u32 bcma_chipco_gpio_pullup(struct bcma_drv_cc *cc, u32 mask, u32 value);
615u32 bcma_chipco_gpio_pulldown(struct bcma_drv_cc *cc, u32 mask, u32 value);
606 616
607/* PMU support */ 617/* PMU support */
608extern void bcma_pmu_init(struct bcma_drv_cc *cc); 618extern void bcma_pmu_init(struct bcma_drv_cc *cc);
diff --git a/include/linux/ssb/ssb.h b/include/linux/ssb/ssb.h
index bb674c02f30..3862a5bbd73 100644
--- a/include/linux/ssb/ssb.h
+++ b/include/linux/ssb/ssb.h
@@ -6,6 +6,7 @@
6#include <linux/types.h> 6#include <linux/types.h>
7#include <linux/spinlock.h> 7#include <linux/spinlock.h>
8#include <linux/pci.h> 8#include <linux/pci.h>
9#include <linux/gpio.h>
9#include <linux/mod_devicetable.h> 10#include <linux/mod_devicetable.h>
10#include <linux/dma-mapping.h> 11#include <linux/dma-mapping.h>
11 12
@@ -433,6 +434,9 @@ struct ssb_bus {
433 /* Lock for GPIO register access. */ 434 /* Lock for GPIO register access. */
434 spinlock_t gpio_lock; 435 spinlock_t gpio_lock;
435#endif /* EMBEDDED */ 436#endif /* EMBEDDED */
437#ifdef CONFIG_SSB_DRIVER_GPIO
438 struct gpio_chip gpio;
439#endif /* DRIVER_GPIO */
436 440
437 /* Internal-only stuff follows. Do not touch. */ 441 /* Internal-only stuff follows. Do not touch. */
438 struct list_head list; 442 struct list_head list;
diff --git a/include/linux/ssb/ssb_driver_chipcommon.h b/include/linux/ssb/ssb_driver_chipcommon.h
index c2b02a5c86a..30b694345d4 100644
--- a/include/linux/ssb/ssb_driver_chipcommon.h
+++ b/include/linux/ssb/ssb_driver_chipcommon.h
@@ -590,6 +590,7 @@ struct ssb_chipcommon {
590 u32 status; 590 u32 status;
591 /* Fast Powerup Delay constant */ 591 /* Fast Powerup Delay constant */
592 u16 fast_pwrup_delay; 592 u16 fast_pwrup_delay;
593 spinlock_t gpio_lock;
593 struct ssb_chipcommon_pmu pmu; 594 struct ssb_chipcommon_pmu pmu;
594}; 595};
595 596
@@ -644,6 +645,8 @@ u32 ssb_chipco_gpio_outen(struct ssb_chipcommon *cc, u32 mask, u32 value);
644u32 ssb_chipco_gpio_control(struct ssb_chipcommon *cc, u32 mask, u32 value); 645u32 ssb_chipco_gpio_control(struct ssb_chipcommon *cc, u32 mask, u32 value);
645u32 ssb_chipco_gpio_intmask(struct ssb_chipcommon *cc, u32 mask, u32 value); 646u32 ssb_chipco_gpio_intmask(struct ssb_chipcommon *cc, u32 mask, u32 value);
646u32 ssb_chipco_gpio_polarity(struct ssb_chipcommon *cc, u32 mask, u32 value); 647u32 ssb_chipco_gpio_polarity(struct ssb_chipcommon *cc, u32 mask, u32 value);
648u32 ssb_chipco_gpio_pullup(struct ssb_chipcommon *cc, u32 mask, u32 value);
649u32 ssb_chipco_gpio_pulldown(struct ssb_chipcommon *cc, u32 mask, u32 value);
647 650
648#ifdef CONFIG_SSB_SERIAL 651#ifdef CONFIG_SSB_SERIAL
649extern int ssb_chipco_serial_init(struct ssb_chipcommon *cc, 652extern int ssb_chipco_serial_init(struct ssb_chipcommon *cc,
diff --git a/include/linux/ssb/ssb_driver_extif.h b/include/linux/ssb/ssb_driver_extif.h
index 91161f0aa22..bd2306854a9 100644
--- a/include/linux/ssb/ssb_driver_extif.h
+++ b/include/linux/ssb/ssb_driver_extif.h
@@ -158,6 +158,7 @@
158 158
159struct ssb_extif { 159struct ssb_extif {
160 struct ssb_device *dev; 160 struct ssb_device *dev;
161 spinlock_t gpio_lock;
161}; 162};
162 163
163static inline bool ssb_extif_available(struct ssb_extif *extif) 164static inline bool ssb_extif_available(struct ssb_extif *extif)