forked from freifunk-franken/firmware
5cbc7a9816
This also integrates the ffol packages feed into this repo. Signed-off-by: Tim Niemeyer <tim.niemeyer@mastersword.de>
6842 lines
218 KiB
Diff
6842 lines
218 KiB
Diff
Index: files/include/linux/ath9k_platform.h
|
|
===================================================================
|
|
--- files/include/linux/ath9k_platform.h (Revision 35298)
|
|
+++ files/include/linux/ath9k_platform.h (Revision 37768)
|
|
@@ -22,6 +22,8 @@
|
|
#define ATH9K_PLAT_EEP_MAX_WORDS 2048
|
|
|
|
struct ath9k_platform_data {
|
|
+ const char *eeprom_name;
|
|
+
|
|
u16 eeprom_data[ATH9K_PLAT_EEP_MAX_WORDS];
|
|
u8 *macaddr;
|
|
|
|
Index: config-3.3
|
|
===================================================================
|
|
--- config-3.3 (Revision 35298)
|
|
+++ config-3.3 (Revision 37768)
|
|
@@ -193,6 +193,7 @@
|
|
# CONFIG_BCM63XX is not set
|
|
# CONFIG_BCM63XX_PHY is not set
|
|
# CONFIG_BCMA is not set
|
|
+# CONFIG_BCMA_DRIVER_GPIO is not set
|
|
# CONFIG_BCM_WIMAX is not set
|
|
# CONFIG_BDI_SWITCH is not set
|
|
# CONFIG_BE2ISCSI is not set
|
|
@@ -2842,6 +2843,7 @@
|
|
CONFIG_SQUASHFS_XZ=y
|
|
# CONFIG_SQUASHFS_ZLIB is not set
|
|
# CONFIG_SSB is not set
|
|
+# CONFIG_SSB_DRIVER_GPIO is not set
|
|
# CONFIG_SSB_DEBUG is not set
|
|
# CONFIG_SSB_PCMCIAHOST is not set
|
|
CONFIG_SSB_POSSIBLE=y
|
|
Index: patches-3.3/028-bcma-fix-regression-in-interrupt-assignment-on-mips.patch
|
|
===================================================================
|
|
--- patches-3.3/028-bcma-fix-regression-in-interrupt-assignment-on-mips.patch (Revision 35298)
|
|
+++ patches-3.3/028-bcma-fix-regression-in-interrupt-assignment-on-mips.patch (Revision 37768)
|
|
@@ -1,29 +0,0 @@
|
|
---- a/drivers/bcma/driver_mips.c
|
|
-+++ b/drivers/bcma/driver_mips.c
|
|
-@@ -131,7 +131,7 @@ static void bcma_core_mips_set_irq(struc
|
|
- /* backplane irq line is in use, find out who uses
|
|
- * it and set user to irq 0
|
|
- */
|
|
-- list_for_each_entry_reverse(core, &bus->cores, list) {
|
|
-+ list_for_each_entry(core, &bus->cores, list) {
|
|
- if ((1 << bcma_core_mips_irqflag(core)) ==
|
|
- oldirqflag) {
|
|
- bcma_core_mips_set_irq(core, 0);
|
|
-@@ -161,7 +161,7 @@ static void bcma_core_mips_dump_irq(stru
|
|
- {
|
|
- struct bcma_device *core;
|
|
-
|
|
-- list_for_each_entry_reverse(core, &bus->cores, list) {
|
|
-+ list_for_each_entry(core, &bus->cores, list) {
|
|
- bcma_core_mips_print_irq(core, bcma_core_mips_irq(core));
|
|
- }
|
|
- }
|
|
-@@ -215,7 +215,7 @@ void bcma_core_mips_init(struct bcma_drv
|
|
- mcore->assigned_irqs = 1;
|
|
-
|
|
- /* Assign IRQs to all cores on the bus */
|
|
-- list_for_each_entry_reverse(core, &bus->cores, list) {
|
|
-+ list_for_each_entry(core, &bus->cores, list) {
|
|
- int mips_irq;
|
|
- if (core->irq)
|
|
- continue;
|
|
Index: patches-3.3/027-bcma-add-missing-iounmap-on-error-path.patch
|
|
===================================================================
|
|
--- patches-3.3/027-bcma-add-missing-iounmap-on-error-path.patch (Revision 35298)
|
|
+++ patches-3.3/027-bcma-add-missing-iounmap-on-error-path.patch (Revision 37768)
|
|
@@ -1,55 +0,0 @@
|
|
---- a/drivers/bcma/scan.c
|
|
-+++ b/drivers/bcma/scan.c
|
|
-@@ -462,8 +462,10 @@ int bcma_bus_scan(struct bcma_bus *bus)
|
|
- while (eromptr < eromend) {
|
|
- struct bcma_device *other_core;
|
|
- struct bcma_device *core = kzalloc(sizeof(*core), GFP_KERNEL);
|
|
-- if (!core)
|
|
-- return -ENOMEM;
|
|
-+ if (!core) {
|
|
-+ err = -ENOMEM;
|
|
-+ goto out;
|
|
-+ }
|
|
- INIT_LIST_HEAD(&core->list);
|
|
- core->bus = bus;
|
|
-
|
|
-@@ -478,7 +480,7 @@ int bcma_bus_scan(struct bcma_bus *bus)
|
|
- } else if (err == -ESPIPE) {
|
|
- break;
|
|
- }
|
|
-- return err;
|
|
-+ goto out;
|
|
- }
|
|
-
|
|
- core->core_index = core_num++;
|
|
-@@ -494,10 +496,12 @@ int bcma_bus_scan(struct bcma_bus *bus)
|
|
- list_add_tail(&core->list, &bus->cores);
|
|
- }
|
|
-
|
|
-+ err = 0;
|
|
-+out:
|
|
- if (bus->hosttype == BCMA_HOSTTYPE_SOC)
|
|
- iounmap(eromptr);
|
|
-
|
|
-- return 0;
|
|
-+ return err;
|
|
- }
|
|
-
|
|
- int __init bcma_bus_scan_early(struct bcma_bus *bus,
|
|
-@@ -537,7 +541,7 @@ int __init bcma_bus_scan_early(struct bc
|
|
- else if (err == -ESPIPE)
|
|
- break;
|
|
- else if (err < 0)
|
|
-- return err;
|
|
-+ goto out;
|
|
-
|
|
- core->core_index = core_num++;
|
|
- bus->nr_cores++;
|
|
-@@ -551,6 +555,7 @@ int __init bcma_bus_scan_early(struct bc
|
|
- break;
|
|
- }
|
|
-
|
|
-+out:
|
|
- if (bus->hosttype == BCMA_HOSTTYPE_SOC)
|
|
- iounmap(eromptr);
|
|
-
|
|
Index: patches-3.3/026-bcma_pmu_regression.patch
|
|
===================================================================
|
|
--- patches-3.3/026-bcma_pmu_regression.patch (Revision 35298)
|
|
+++ patches-3.3/026-bcma_pmu_regression.patch (Revision 37768)
|
|
@@ -1,29 +0,0 @@
|
|
---- a/drivers/bcma/driver_chipcommon_pmu.c
|
|
-+++ b/drivers/bcma/driver_chipcommon_pmu.c
|
|
-@@ -110,7 +110,7 @@ void bcma_pmu_workarounds(struct bcma_dr
|
|
- /* enable 12 mA drive strenth for 4313 and set chipControl
|
|
- register bit 1 */
|
|
- bcma_chipco_chipctl_maskset(cc, 0,
|
|
-- BCMA_CCTRL_4313_12MA_LED_DRIVE,
|
|
-+ ~BCMA_CCTRL_4313_12MA_LED_DRIVE,
|
|
- BCMA_CCTRL_4313_12MA_LED_DRIVE);
|
|
- break;
|
|
- case BCMA_CHIP_ID_BCM4331:
|
|
-@@ -124,14 +124,14 @@ void bcma_pmu_workarounds(struct bcma_dr
|
|
- register bit 15 */
|
|
- if (bus->chipinfo.rev == 0) {
|
|
- bcma_cc_maskset32(cc, BCMA_CC_CHIPCTL,
|
|
-- BCMA_CCTRL_43224_GPIO_TOGGLE,
|
|
-+ ~BCMA_CCTRL_43224_GPIO_TOGGLE,
|
|
- BCMA_CCTRL_43224_GPIO_TOGGLE);
|
|
- bcma_chipco_chipctl_maskset(cc, 0,
|
|
-- BCMA_CCTRL_43224A0_12MA_LED_DRIVE,
|
|
-+ ~BCMA_CCTRL_43224A0_12MA_LED_DRIVE,
|
|
- BCMA_CCTRL_43224A0_12MA_LED_DRIVE);
|
|
- } else {
|
|
- bcma_chipco_chipctl_maskset(cc, 0,
|
|
-- BCMA_CCTRL_43224B0_12MA_LED_DRIVE,
|
|
-+ ~BCMA_CCTRL_43224B0_12MA_LED_DRIVE,
|
|
- BCMA_CCTRL_43224B0_12MA_LED_DRIVE);
|
|
- }
|
|
- break;
|
|
Index: patches-3.3/660-ipv6-loopback-policy-routing.patch
|
|
===================================================================
|
|
--- patches-3.3/660-ipv6-loopback-policy-routing.patch (Revision 0)
|
|
+++ patches-3.3/660-ipv6-loopback-policy-routing.patch (Revision 37768)
|
|
@@ -0,0 +1,11 @@
|
|
+--- a/net/ipv6/route.c
|
|
++++ b/net/ipv6/route.c
|
|
+@@ -899,6 +899,8 @@ struct dst_entry * ip6_route_output(stru
|
|
+ {
|
|
+ int flags = 0;
|
|
+
|
|
++ fl6->flowi6_iif = net->loopback_dev->ifindex;
|
|
++
|
|
+ if ((sk && sk->sk_bound_dev_if) || rt6_need_strict(&fl6->daddr))
|
|
+ flags |= RT6_LOOKUP_F_IFACE;
|
|
+
|
|
Index: patches-3.3/065-8139cp-fixes.patch
|
|
===================================================================
|
|
--- patches-3.3/065-8139cp-fixes.patch (Revision 35298)
|
|
+++ patches-3.3/065-8139cp-fixes.patch (Revision 37768)
|
|
@@ -66,11 +66,9 @@
|
|
|
|
Signed-off-by: David S. Miller <davem@davemloft.net>
|
|
|
|
-diff --git a/drivers/net/ethernet/realtek/8139cp.c b/drivers/net/ethernet/realtek/8139cp.c
|
|
-index b01f83a..6cb96b4 100644
|
|
--- a/drivers/net/ethernet/realtek/8139cp.c
|
|
+++ b/drivers/net/ethernet/realtek/8139cp.c
|
|
-@@ -648,6 +648,7 @@ static void cp_tx (struct cp_private *cp)
|
|
+@@ -645,6 +645,7 @@ static void cp_tx (struct cp_private *cp
|
|
{
|
|
unsigned tx_head = cp->tx_head;
|
|
unsigned tx_tail = cp->tx_tail;
|
|
@@ -78,7 +76,7 @@
|
|
|
|
while (tx_tail != tx_head) {
|
|
struct cp_desc *txd = cp->tx_ring + tx_tail;
|
|
-@@ -666,6 +667,9 @@ static void cp_tx (struct cp_private *cp)
|
|
+@@ -663,6 +664,9 @@ static void cp_tx (struct cp_private *cp
|
|
le32_to_cpu(txd->opts1) & 0xffff,
|
|
PCI_DMA_TODEVICE);
|
|
|
|
@@ -88,7 +86,7 @@
|
|
if (status & LastFrag) {
|
|
if (status & (TxError | TxFIFOUnder)) {
|
|
netif_dbg(cp, tx_err, cp->dev,
|
|
-@@ -697,6 +701,7 @@ static void cp_tx (struct cp_private *cp)
|
|
+@@ -694,6 +698,7 @@ static void cp_tx (struct cp_private *cp
|
|
|
|
cp->tx_tail = tx_tail;
|
|
|
|
@@ -96,7 +94,7 @@
|
|
if (TX_BUFFS_AVAIL(cp) > (MAX_SKB_FRAGS + 1))
|
|
netif_wake_queue(cp->dev);
|
|
}
|
|
-@@ -843,6 +848,8 @@ static netdev_tx_t cp_start_xmit (struct sk_buff *skb,
|
|
+@@ -840,6 +845,8 @@ static netdev_tx_t cp_start_xmit (struct
|
|
wmb();
|
|
}
|
|
cp->tx_head = entry;
|
|
@@ -105,7 +103,7 @@
|
|
netif_dbg(cp, tx_queued, cp->dev, "tx queued, slot %d, skblen %d\n",
|
|
entry, skb->len);
|
|
if (TX_BUFFS_AVAIL(cp) <= (MAX_SKB_FRAGS + 1))
|
|
-@@ -937,6 +944,8 @@ static void cp_stop_hw (struct cp_private *cp)
|
|
+@@ -934,6 +941,8 @@ static void cp_stop_hw (struct cp_privat
|
|
|
|
cp->rx_tail = 0;
|
|
cp->tx_head = cp->tx_tail = 0;
|
|
@@ -114,7 +112,7 @@
|
|
}
|
|
|
|
static void cp_reset_hw (struct cp_private *cp)
|
|
-@@ -957,8 +966,38 @@ static void cp_reset_hw (struct cp_private *cp)
|
|
+@@ -954,8 +963,38 @@ static void cp_reset_hw (struct cp_priva
|
|
|
|
static inline void cp_start_hw (struct cp_private *cp)
|
|
{
|
|
@@ -153,7 +151,7 @@
|
|
}
|
|
|
|
static void cp_enable_irq(struct cp_private *cp)
|
|
-@@ -969,7 +1008,6 @@ static void cp_enable_irq(struct cp_private *cp)
|
|
+@@ -966,7 +1005,6 @@ static void cp_enable_irq(struct cp_priv
|
|
static void cp_init_hw (struct cp_private *cp)
|
|
{
|
|
struct net_device *dev = cp->dev;
|
|
@@ -161,7 +159,7 @@
|
|
|
|
cp_reset_hw(cp);
|
|
|
|
-@@ -992,17 +1030,6 @@ static void cp_init_hw (struct cp_private *cp)
|
|
+@@ -989,17 +1027,6 @@ static void cp_init_hw (struct cp_privat
|
|
|
|
cpw8(Config5, cpr8(Config5) & PMEStatus);
|
|
|
|
@@ -179,7 +177,7 @@
|
|
cpw16(MultiIntr, 0);
|
|
|
|
cpw8_f(Cfg9346, Cfg9346_Lock);
|
|
-@@ -1192,6 +1219,7 @@ static void cp_tx_timeout(struct net_device *dev)
|
|
+@@ -1188,6 +1215,7 @@ static void cp_tx_timeout(struct net_dev
|
|
cp_clean_rings(cp);
|
|
rc = cp_init_rings(cp);
|
|
cp_start_hw(cp);
|
|
Index: patches-3.3/259-compressor_kconfig_hack.patch
|
|
===================================================================
|
|
--- patches-3.3/259-compressor_kconfig_hack.patch (Revision 0)
|
|
+++ patches-3.3/259-compressor_kconfig_hack.patch (Revision 37768)
|
|
@@ -0,0 +1,23 @@
|
|
+--- a/lib/Kconfig
|
|
++++ b/lib/Kconfig
|
|
+@@ -105,16 +105,16 @@ config AUDIT_GENERIC
|
|
+ # compression support is select'ed if needed
|
|
+ #
|
|
+ config ZLIB_INFLATE
|
|
+- tristate
|
|
++ tristate "ZLIB inflate support"
|
|
+
|
|
+ config ZLIB_DEFLATE
|
|
+- tristate
|
|
++ tristate "ZLIB deflate support"
|
|
+
|
|
+ config LZO_COMPRESS
|
|
+- tristate
|
|
++ tristate "LZO compress support"
|
|
+
|
|
+ config LZO_DECOMPRESS
|
|
+- tristate
|
|
++ tristate "LZO decompress support"
|
|
+
|
|
+ source "lib/xz/Kconfig"
|
|
+
|
|
Index: patches-3.3/020-ssb_update.patch
|
|
===================================================================
|
|
--- patches-3.3/020-ssb_update.patch (Revision 35298)
|
|
+++ patches-3.3/020-ssb_update.patch (Revision 37768)
|
|
@@ -1,6 +1,31 @@
|
|
+--- a/drivers/ssb/Kconfig
|
|
++++ b/drivers/ssb/Kconfig
|
|
+@@ -160,4 +160,12 @@ config SSB_DRIVER_GIGE
|
|
+
|
|
+ If unsure, say N
|
|
+
|
|
++config SSB_DRIVER_GPIO
|
|
++ bool "SSB GPIO driver"
|
|
++ depends on SSB && GPIOLIB
|
|
++ help
|
|
++ Driver to provide access to the GPIO pins on the bus.
|
|
++
|
|
++ If unsure, say N
|
|
++
|
|
+ endmenu
|
|
+--- a/drivers/ssb/Makefile
|
|
++++ b/drivers/ssb/Makefile
|
|
+@@ -15,6 +15,7 @@ ssb-$(CONFIG_SSB_DRIVER_MIPS) += driver
|
|
+ ssb-$(CONFIG_SSB_DRIVER_EXTIF) += driver_extif.o
|
|
+ ssb-$(CONFIG_SSB_DRIVER_PCICORE) += driver_pcicore.o
|
|
+ ssb-$(CONFIG_SSB_DRIVER_GIGE) += driver_gige.o
|
|
++ssb-$(CONFIG_SSB_DRIVER_GPIO) += driver_gpio.o
|
|
+
|
|
+ # b43 pci-ssb-bridge driver
|
|
+ # Not strictly a part of SSB, but kept here for convenience
|
|
--- a/drivers/ssb/b43_pci_bridge.c
|
|
+++ b/drivers/ssb/b43_pci_bridge.c
|
|
-@@ -29,11 +29,14 @@ static const struct pci_device_id b43_pc
|
|
+@@ -29,11 +29,15 @@ static const struct pci_device_id b43_pc
|
|
{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4319) },
|
|
{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4320) },
|
|
{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4321) },
|
|
@@ -12,9 +37,265 @@
|
|
{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4329) },
|
|
{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x432b) },
|
|
+ { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x432c) },
|
|
++ { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4350) },
|
|
{ 0, },
|
|
};
|
|
MODULE_DEVICE_TABLE(pci, b43_pci_bridge_tbl);
|
|
+--- a/drivers/ssb/driver_chipcommon.c
|
|
++++ b/drivers/ssb/driver_chipcommon.c
|
|
+@@ -4,6 +4,7 @@
|
|
+ *
|
|
+ * Copyright 2005, Broadcom Corporation
|
|
+ * Copyright 2006, 2007, Michael Buesch <m@bues.ch>
|
|
++ * Copyright 2012, Hauke Mehrtens <hauke@hauke-m.de>
|
|
+ *
|
|
+ * Licensed under the GNU/GPL. See COPYING for details.
|
|
+ */
|
|
+@@ -12,6 +13,7 @@
|
|
+ #include <linux/ssb/ssb_regs.h>
|
|
+ #include <linux/export.h>
|
|
+ #include <linux/pci.h>
|
|
++#include <linux/bcm47xx_wdt.h>
|
|
+
|
|
+ #include "ssb_private.h"
|
|
+
|
|
+@@ -280,13 +282,79 @@ static void calc_fast_powerup_delay(stru
|
|
+ cc->fast_pwrup_delay = tmp;
|
|
+ }
|
|
+
|
|
++static u32 ssb_chipco_alp_clock(struct ssb_chipcommon *cc)
|
|
++{
|
|
++ if (cc->capabilities & SSB_CHIPCO_CAP_PMU)
|
|
++ return ssb_pmu_get_alp_clock(cc);
|
|
++
|
|
++ return 20000000;
|
|
++}
|
|
++
|
|
++static u32 ssb_chipco_watchdog_get_max_timer(struct ssb_chipcommon *cc)
|
|
++{
|
|
++ u32 nb;
|
|
++
|
|
++ if (cc->capabilities & SSB_CHIPCO_CAP_PMU) {
|
|
++ if (cc->dev->id.revision < 26)
|
|
++ nb = 16;
|
|
++ else
|
|
++ nb = (cc->dev->id.revision >= 37) ? 32 : 24;
|
|
++ } else {
|
|
++ nb = 28;
|
|
++ }
|
|
++ if (nb == 32)
|
|
++ return 0xffffffff;
|
|
++ else
|
|
++ return (1 << nb) - 1;
|
|
++}
|
|
++
|
|
++u32 ssb_chipco_watchdog_timer_set_wdt(struct bcm47xx_wdt *wdt, u32 ticks)
|
|
++{
|
|
++ struct ssb_chipcommon *cc = bcm47xx_wdt_get_drvdata(wdt);
|
|
++
|
|
++ if (cc->dev->bus->bustype != SSB_BUSTYPE_SSB)
|
|
++ return 0;
|
|
++
|
|
++ return ssb_chipco_watchdog_timer_set(cc, ticks);
|
|
++}
|
|
++
|
|
++u32 ssb_chipco_watchdog_timer_set_ms(struct bcm47xx_wdt *wdt, u32 ms)
|
|
++{
|
|
++ struct ssb_chipcommon *cc = bcm47xx_wdt_get_drvdata(wdt);
|
|
++ u32 ticks;
|
|
++
|
|
++ if (cc->dev->bus->bustype != SSB_BUSTYPE_SSB)
|
|
++ return 0;
|
|
++
|
|
++ ticks = ssb_chipco_watchdog_timer_set(cc, cc->ticks_per_ms * ms);
|
|
++ return ticks / cc->ticks_per_ms;
|
|
++}
|
|
++
|
|
++static int ssb_chipco_watchdog_ticks_per_ms(struct ssb_chipcommon *cc)
|
|
++{
|
|
++ struct ssb_bus *bus = cc->dev->bus;
|
|
++
|
|
++ if (cc->capabilities & SSB_CHIPCO_CAP_PMU) {
|
|
++ /* based on 32KHz ILP clock */
|
|
++ return 32;
|
|
++ } else {
|
|
++ if (cc->dev->id.revision < 18)
|
|
++ return ssb_clockspeed(bus) / 1000;
|
|
++ else
|
|
++ return ssb_chipco_alp_clock(cc) / 1000;
|
|
++ }
|
|
++}
|
|
++
|
|
+ void ssb_chipcommon_init(struct ssb_chipcommon *cc)
|
|
+ {
|
|
+ if (!cc->dev)
|
|
+ return; /* We don't have a ChipCommon */
|
|
++
|
|
++ spin_lock_init(&cc->gpio_lock);
|
|
++
|
|
+ if (cc->dev->id.revision >= 11)
|
|
+ cc->status = chipco_read32(cc, SSB_CHIPCO_CHIPSTAT);
|
|
+- ssb_dprintk(KERN_INFO PFX "chipcommon status is 0x%x\n", cc->status);
|
|
++ ssb_dbg("chipcommon status is 0x%x\n", cc->status);
|
|
+
|
|
+ if (cc->dev->id.revision >= 20) {
|
|
+ chipco_write32(cc, SSB_CHIPCO_GPIOPULLUP, 0);
|
|
+@@ -297,6 +365,11 @@ void ssb_chipcommon_init(struct ssb_chip
|
|
+ chipco_powercontrol_init(cc);
|
|
+ ssb_chipco_set_clockmode(cc, SSB_CLKMODE_FAST);
|
|
+ calc_fast_powerup_delay(cc);
|
|
++
|
|
++ if (cc->dev->bus->bustype == SSB_BUSTYPE_SSB) {
|
|
++ cc->ticks_per_ms = ssb_chipco_watchdog_ticks_per_ms(cc);
|
|
++ cc->max_timer_ms = ssb_chipco_watchdog_get_max_timer(cc) / cc->ticks_per_ms;
|
|
++ }
|
|
+ }
|
|
+
|
|
+ void ssb_chipco_suspend(struct ssb_chipcommon *cc)
|
|
+@@ -395,10 +468,27 @@ void ssb_chipco_timing_init(struct ssb_c
|
|
+ }
|
|
+
|
|
+ /* Set chip watchdog reset timer to fire in 'ticks' backplane cycles */
|
|
+-void ssb_chipco_watchdog_timer_set(struct ssb_chipcommon *cc, u32 ticks)
|
|
++u32 ssb_chipco_watchdog_timer_set(struct ssb_chipcommon *cc, u32 ticks)
|
|
+ {
|
|
+- /* instant NMI */
|
|
+- chipco_write32(cc, SSB_CHIPCO_WATCHDOG, ticks);
|
|
++ u32 maxt;
|
|
++ enum ssb_clkmode clkmode;
|
|
++
|
|
++ maxt = ssb_chipco_watchdog_get_max_timer(cc);
|
|
++ if (cc->capabilities & SSB_CHIPCO_CAP_PMU) {
|
|
++ if (ticks == 1)
|
|
++ ticks = 2;
|
|
++ else if (ticks > maxt)
|
|
++ ticks = maxt;
|
|
++ chipco_write32(cc, SSB_CHIPCO_PMU_WATCHDOG, ticks);
|
|
++ } else {
|
|
++ clkmode = ticks ? SSB_CLKMODE_FAST : SSB_CLKMODE_DYNAMIC;
|
|
++ ssb_chipco_set_clockmode(cc, clkmode);
|
|
++ if (ticks > maxt)
|
|
++ ticks = maxt;
|
|
++ /* instant NMI */
|
|
++ chipco_write32(cc, SSB_CHIPCO_WATCHDOG, ticks);
|
|
++ }
|
|
++ return ticks;
|
|
+ }
|
|
+
|
|
+ void ssb_chipco_irq_mask(struct ssb_chipcommon *cc, u32 mask, u32 value)
|
|
+@@ -418,28 +508,93 @@ u32 ssb_chipco_gpio_in(struct ssb_chipco
|
|
+
|
|
+ u32 ssb_chipco_gpio_out(struct ssb_chipcommon *cc, u32 mask, u32 value)
|
|
+ {
|
|
+- return chipco_write32_masked(cc, SSB_CHIPCO_GPIOOUT, mask, value);
|
|
++ unsigned long flags;
|
|
++ u32 res = 0;
|
|
++
|
|
++ spin_lock_irqsave(&cc->gpio_lock, flags);
|
|
++ res = chipco_write32_masked(cc, SSB_CHIPCO_GPIOOUT, mask, value);
|
|
++ spin_unlock_irqrestore(&cc->gpio_lock, flags);
|
|
++
|
|
++ return res;
|
|
+ }
|
|
+
|
|
+ u32 ssb_chipco_gpio_outen(struct ssb_chipcommon *cc, u32 mask, u32 value)
|
|
+ {
|
|
+- return chipco_write32_masked(cc, SSB_CHIPCO_GPIOOUTEN, mask, value);
|
|
++ unsigned long flags;
|
|
++ u32 res = 0;
|
|
++
|
|
++ spin_lock_irqsave(&cc->gpio_lock, flags);
|
|
++ res = chipco_write32_masked(cc, SSB_CHIPCO_GPIOOUTEN, mask, value);
|
|
++ spin_unlock_irqrestore(&cc->gpio_lock, flags);
|
|
++
|
|
++ return res;
|
|
+ }
|
|
+
|
|
+ u32 ssb_chipco_gpio_control(struct ssb_chipcommon *cc, u32 mask, u32 value)
|
|
+ {
|
|
+- return chipco_write32_masked(cc, SSB_CHIPCO_GPIOCTL, mask, value);
|
|
++ unsigned long flags;
|
|
++ u32 res = 0;
|
|
++
|
|
++ spin_lock_irqsave(&cc->gpio_lock, flags);
|
|
++ res = chipco_write32_masked(cc, SSB_CHIPCO_GPIOCTL, mask, value);
|
|
++ spin_unlock_irqrestore(&cc->gpio_lock, flags);
|
|
++
|
|
++ return res;
|
|
+ }
|
|
+ EXPORT_SYMBOL(ssb_chipco_gpio_control);
|
|
+
|
|
+ u32 ssb_chipco_gpio_intmask(struct ssb_chipcommon *cc, u32 mask, u32 value)
|
|
+ {
|
|
+- return chipco_write32_masked(cc, SSB_CHIPCO_GPIOIRQ, mask, value);
|
|
++ unsigned long flags;
|
|
++ u32 res = 0;
|
|
++
|
|
++ spin_lock_irqsave(&cc->gpio_lock, flags);
|
|
++ res = chipco_write32_masked(cc, SSB_CHIPCO_GPIOIRQ, mask, value);
|
|
++ spin_unlock_irqrestore(&cc->gpio_lock, flags);
|
|
++
|
|
++ return res;
|
|
+ }
|
|
+
|
|
+ u32 ssb_chipco_gpio_polarity(struct ssb_chipcommon *cc, u32 mask, u32 value)
|
|
+ {
|
|
+- return chipco_write32_masked(cc, SSB_CHIPCO_GPIOPOL, mask, value);
|
|
++ unsigned long flags;
|
|
++ u32 res = 0;
|
|
++
|
|
++ spin_lock_irqsave(&cc->gpio_lock, flags);
|
|
++ res = chipco_write32_masked(cc, SSB_CHIPCO_GPIOPOL, mask, value);
|
|
++ spin_unlock_irqrestore(&cc->gpio_lock, flags);
|
|
++
|
|
++ return res;
|
|
++}
|
|
++
|
|
++u32 ssb_chipco_gpio_pullup(struct ssb_chipcommon *cc, u32 mask, u32 value)
|
|
++{
|
|
++ unsigned long flags;
|
|
++ u32 res = 0;
|
|
++
|
|
++ if (cc->dev->id.revision < 20)
|
|
++ return 0xffffffff;
|
|
++
|
|
++ spin_lock_irqsave(&cc->gpio_lock, flags);
|
|
++ res = chipco_write32_masked(cc, SSB_CHIPCO_GPIOPULLUP, mask, value);
|
|
++ spin_unlock_irqrestore(&cc->gpio_lock, flags);
|
|
++
|
|
++ return res;
|
|
++}
|
|
++
|
|
++u32 ssb_chipco_gpio_pulldown(struct ssb_chipcommon *cc, u32 mask, u32 value)
|
|
++{
|
|
++ unsigned long flags;
|
|
++ u32 res = 0;
|
|
++
|
|
++ if (cc->dev->id.revision < 20)
|
|
++ return 0xffffffff;
|
|
++
|
|
++ spin_lock_irqsave(&cc->gpio_lock, flags);
|
|
++ res = chipco_write32_masked(cc, SSB_CHIPCO_GPIOPULLDOWN, mask, value);
|
|
++ spin_unlock_irqrestore(&cc->gpio_lock, flags);
|
|
++
|
|
++ return res;
|
|
+ }
|
|
+
|
|
+ #ifdef CONFIG_SSB_SERIAL
|
|
+@@ -473,12 +628,7 @@ int ssb_chipco_serial_init(struct ssb_ch
|
|
+ chipco_read32(cc, SSB_CHIPCO_CORECTL)
|
|
+ | SSB_CHIPCO_CORECTL_UARTCLK0);
|
|
+ } else if ((ccrev >= 11) && (ccrev != 15)) {
|
|
+- /* Fixed ALP clock */
|
|
+- baud_base = 20000000;
|
|
+- if (cc->capabilities & SSB_CHIPCO_CAP_PMU) {
|
|
+- /* FIXME: baud_base is different for devices with a PMU */
|
|
+- SSB_WARN_ON(1);
|
|
+- }
|
|
++ baud_base = ssb_chipco_alp_clock(cc);
|
|
+ div = 1;
|
|
+ if (ccrev >= 21) {
|
|
+ /* Turn off UART clock before switching clocksource. */
|
|
--- a/drivers/ssb/driver_chipcommon_pmu.c
|
|
+++ b/drivers/ssb/driver_chipcommon_pmu.c
|
|
@@ -13,6 +13,9 @@
|
|
@@ -22,7 +303,7 @@
|
|
#include <linux/delay.h>
|
|
#include <linux/export.h>
|
|
+#ifdef CONFIG_BCM47XX
|
|
-+#include <asm/mach-bcm47xx/nvram.h>
|
|
++#include <nvram.h>
|
|
+#endif
|
|
|
|
#include "ssb_private.h"
|
|
@@ -38,6 +319,46 @@
|
|
if (crystalfreq)
|
|
e = pmu0_plltab_find_entry(crystalfreq);
|
|
if (!e)
|
|
+@@ -111,8 +110,8 @@ static void ssb_pmu0_pllinit_r0(struct s
|
|
+ return;
|
|
+ }
|
|
+
|
|
+- ssb_printk(KERN_INFO PFX "Programming PLL to %u.%03u MHz\n",
|
|
+- (crystalfreq / 1000), (crystalfreq % 1000));
|
|
++ ssb_info("Programming PLL to %u.%03u MHz\n",
|
|
++ crystalfreq / 1000, crystalfreq % 1000);
|
|
+
|
|
+ /* First turn the PLL off. */
|
|
+ switch (bus->chip_id) {
|
|
+@@ -139,7 +138,7 @@ static void ssb_pmu0_pllinit_r0(struct s
|
|
+ }
|
|
+ tmp = chipco_read32(cc, SSB_CHIPCO_CLKCTLST);
|
|
+ if (tmp & SSB_CHIPCO_CLKCTLST_HAVEHT)
|
|
+- ssb_printk(KERN_EMERG PFX "Failed to turn the PLL off!\n");
|
|
++ ssb_emerg("Failed to turn the PLL off!\n");
|
|
+
|
|
+ /* Set PDIV in PLL control 0. */
|
|
+ pllctl = ssb_chipco_pll_read(cc, SSB_PMU0_PLLCTL0);
|
|
+@@ -250,8 +249,8 @@ static void ssb_pmu1_pllinit_r0(struct s
|
|
+ return;
|
|
+ }
|
|
+
|
|
+- ssb_printk(KERN_INFO PFX "Programming PLL to %u.%03u MHz\n",
|
|
+- (crystalfreq / 1000), (crystalfreq % 1000));
|
|
++ ssb_info("Programming PLL to %u.%03u MHz\n",
|
|
++ crystalfreq / 1000, crystalfreq % 1000);
|
|
+
|
|
+ /* First turn the PLL off. */
|
|
+ switch (bus->chip_id) {
|
|
+@@ -276,7 +275,7 @@ static void ssb_pmu1_pllinit_r0(struct s
|
|
+ }
|
|
+ tmp = chipco_read32(cc, SSB_CHIPCO_CLKCTLST);
|
|
+ if (tmp & SSB_CHIPCO_CLKCTLST_HAVEHT)
|
|
+- ssb_printk(KERN_EMERG PFX "Failed to turn the PLL off!\n");
|
|
++ ssb_emerg("Failed to turn the PLL off!\n");
|
|
+
|
|
+ /* Set p1div and p2div. */
|
|
+ pllctl = ssb_chipco_pll_read(cc, SSB_PMU1_PLLCTL0);
|
|
@@ -321,7 +320,11 @@ static void ssb_pmu_pll_init(struct ssb_
|
|
u32 crystalfreq = 0; /* in kHz. 0 = keep default freq. */
|
|
|
|
@@ -63,11 +384,83 @@
|
|
ssb_pmu0_pllinit_r0(cc, crystalfreq);
|
|
break;
|
|
case 0x4322:
|
|
-@@ -607,3 +614,34 @@ void ssb_pmu_set_ldo_paref(struct ssb_ch
|
|
+@@ -339,10 +346,11 @@ static void ssb_pmu_pll_init(struct ssb_
|
|
+ chipco_write32(cc, SSB_CHIPCO_PLLCTL_DATA, 0x380005C0);
|
|
+ }
|
|
+ break;
|
|
++ case 43222:
|
|
++ break;
|
|
+ default:
|
|
+- ssb_printk(KERN_ERR PFX
|
|
+- "ERROR: PLL init unknown for device %04X\n",
|
|
+- bus->chip_id);
|
|
++ ssb_err("ERROR: PLL init unknown for device %04X\n",
|
|
++ bus->chip_id);
|
|
+ }
|
|
+ }
|
|
|
|
+@@ -427,6 +435,7 @@ static void ssb_pmu_resources_init(struc
|
|
+ min_msk = 0xCBB;
|
|
+ break;
|
|
+ case 0x4322:
|
|
++ case 43222:
|
|
+ /* We keep the default settings:
|
|
+ * min_msk = 0xCBB
|
|
+ * max_msk = 0x7FFFF
|
|
+@@ -462,9 +471,8 @@ static void ssb_pmu_resources_init(struc
|
|
+ max_msk = 0xFFFFF;
|
|
+ break;
|
|
+ default:
|
|
+- ssb_printk(KERN_ERR PFX
|
|
+- "ERROR: PMU resource config unknown for device %04X\n",
|
|
+- bus->chip_id);
|
|
++ ssb_err("ERROR: PMU resource config unknown for device %04X\n",
|
|
++ bus->chip_id);
|
|
+ }
|
|
+
|
|
+ if (updown_tab) {
|
|
+@@ -516,8 +524,8 @@ void ssb_pmu_init(struct ssb_chipcommon
|
|
+ pmucap = chipco_read32(cc, SSB_CHIPCO_PMU_CAP);
|
|
+ cc->pmu.rev = (pmucap & SSB_CHIPCO_PMU_CAP_REVISION);
|
|
+
|
|
+- ssb_dprintk(KERN_DEBUG PFX "Found rev %u PMU (capabilities 0x%08X)\n",
|
|
+- cc->pmu.rev, pmucap);
|
|
++ ssb_dbg("Found rev %u PMU (capabilities 0x%08X)\n",
|
|
++ cc->pmu.rev, pmucap);
|
|
+
|
|
+ if (cc->pmu.rev == 1)
|
|
+ chipco_mask32(cc, SSB_CHIPCO_PMU_CTL,
|
|
+@@ -607,3 +615,102 @@ void ssb_pmu_set_ldo_paref(struct ssb_ch
|
|
+
|
|
EXPORT_SYMBOL(ssb_pmu_set_ldo_voltage);
|
|
EXPORT_SYMBOL(ssb_pmu_set_ldo_paref);
|
|
+
|
|
++static u32 ssb_pmu_get_alp_clock_clk0(struct ssb_chipcommon *cc)
|
|
++{
|
|
++ u32 crystalfreq;
|
|
++ const struct pmu0_plltab_entry *e = NULL;
|
|
++
|
|
++ crystalfreq = chipco_read32(cc, SSB_CHIPCO_PMU_CTL) &
|
|
++ SSB_CHIPCO_PMU_CTL_XTALFREQ >> SSB_CHIPCO_PMU_CTL_XTALFREQ_SHIFT;
|
|
++ e = pmu0_plltab_find_entry(crystalfreq);
|
|
++ BUG_ON(!e);
|
|
++ return e->freq * 1000;
|
|
++}
|
|
++
|
|
++u32 ssb_pmu_get_alp_clock(struct ssb_chipcommon *cc)
|
|
++{
|
|
++ struct ssb_bus *bus = cc->dev->bus;
|
|
++
|
|
++ switch (bus->chip_id) {
|
|
++ case 0x5354:
|
|
++ ssb_pmu_get_alp_clock_clk0(cc);
|
|
++ default:
|
|
++ ssb_err("ERROR: PMU alp clock unknown for device %04X\n",
|
|
++ bus->chip_id);
|
|
++ return 0;
|
|
++ }
|
|
++}
|
|
++
|
|
+u32 ssb_pmu_get_cpu_clock(struct ssb_chipcommon *cc)
|
|
+{
|
|
+ struct ssb_bus *bus = cc->dev->bus;
|
|
@@ -77,9 +470,8 @@
|
|
+ /* 5354 chip uses a non programmable PLL of frequency 240MHz */
|
|
+ return 240000000;
|
|
+ default:
|
|
-+ ssb_printk(KERN_ERR PFX
|
|
-+ "ERROR: PMU cpu clock unknown for device %04X\n",
|
|
-+ bus->chip_id);
|
|
++ ssb_err("ERROR: PMU cpu clock unknown for device %04X\n",
|
|
++ bus->chip_id);
|
|
+ return 0;
|
|
+ }
|
|
+}
|
|
@@ -92,27 +484,596 @@
|
|
+ case 0x5354:
|
|
+ return 120000000;
|
|
+ default:
|
|
-+ ssb_printk(KERN_ERR PFX
|
|
-+ "ERROR: PMU controlclock unknown for device %04X\n",
|
|
-+ bus->chip_id);
|
|
++ ssb_err("ERROR: PMU controlclock unknown for device %04X\n",
|
|
++ bus->chip_id);
|
|
+ return 0;
|
|
+ }
|
|
+}
|
|
++
|
|
++void ssb_pmu_spuravoid_pllupdate(struct ssb_chipcommon *cc, int spuravoid)
|
|
++{
|
|
++ u32 pmu_ctl = 0;
|
|
++
|
|
++ switch (cc->dev->bus->chip_id) {
|
|
++ case 0x4322:
|
|
++ ssb_chipco_pll_write(cc, SSB_PMU1_PLLCTL0, 0x11100070);
|
|
++ ssb_chipco_pll_write(cc, SSB_PMU1_PLLCTL1, 0x1014140a);
|
|
++ ssb_chipco_pll_write(cc, SSB_PMU1_PLLCTL5, 0x88888854);
|
|
++ if (spuravoid == 1)
|
|
++ ssb_chipco_pll_write(cc, SSB_PMU1_PLLCTL2, 0x05201828);
|
|
++ else
|
|
++ ssb_chipco_pll_write(cc, SSB_PMU1_PLLCTL2, 0x05001828);
|
|
++ pmu_ctl = SSB_CHIPCO_PMU_CTL_PLL_UPD;
|
|
++ break;
|
|
++ case 43222:
|
|
++ if (spuravoid == 1) {
|
|
++ ssb_chipco_pll_write(cc, SSB_PMU1_PLLCTL0, 0x11500008);
|
|
++ ssb_chipco_pll_write(cc, SSB_PMU1_PLLCTL1, 0x0C000C06);
|
|
++ ssb_chipco_pll_write(cc, SSB_PMU1_PLLCTL2, 0x0F600a08);
|
|
++ ssb_chipco_pll_write(cc, SSB_PMU1_PLLCTL3, 0x00000000);
|
|
++ ssb_chipco_pll_write(cc, SSB_PMU1_PLLCTL4, 0x2001E920);
|
|
++ ssb_chipco_pll_write(cc, SSB_PMU1_PLLCTL5, 0x88888815);
|
|
++ } else {
|
|
++ ssb_chipco_pll_write(cc, SSB_PMU1_PLLCTL0, 0x11100008);
|
|
++ ssb_chipco_pll_write(cc, SSB_PMU1_PLLCTL1, 0x0c000c06);
|
|
++ ssb_chipco_pll_write(cc, SSB_PMU1_PLLCTL2, 0x03000a08);
|
|
++ ssb_chipco_pll_write(cc, SSB_PMU1_PLLCTL3, 0x00000000);
|
|
++ ssb_chipco_pll_write(cc, SSB_PMU1_PLLCTL4, 0x200005c0);
|
|
++ ssb_chipco_pll_write(cc, SSB_PMU1_PLLCTL5, 0x88888855);
|
|
++ }
|
|
++ pmu_ctl = SSB_CHIPCO_PMU_CTL_PLL_UPD;
|
|
++ break;
|
|
++ default:
|
|
++ ssb_printk(KERN_ERR PFX
|
|
++ "Unknown spuravoidance settings for chip 0x%04X, not changing PLL\n",
|
|
++ cc->dev->bus->chip_id);
|
|
++ return;
|
|
++ }
|
|
++
|
|
++ chipco_set32(cc, SSB_CHIPCO_PMU_CTL, pmu_ctl);
|
|
++}
|
|
++EXPORT_SYMBOL_GPL(ssb_pmu_spuravoid_pllupdate);
|
|
+--- a/drivers/ssb/driver_extif.c
|
|
++++ b/drivers/ssb/driver_extif.c
|
|
+@@ -112,10 +112,37 @@ void ssb_extif_get_clockcontrol(struct s
|
|
+ *m = extif_read32(extif, SSB_EXTIF_CLOCK_SB);
|
|
+ }
|
|
+
|
|
+-void ssb_extif_watchdog_timer_set(struct ssb_extif *extif,
|
|
+- u32 ticks)
|
|
++u32 ssb_extif_watchdog_timer_set_wdt(struct bcm47xx_wdt *wdt, u32 ticks)
|
|
+ {
|
|
++ struct ssb_extif *extif = bcm47xx_wdt_get_drvdata(wdt);
|
|
++
|
|
++ return ssb_extif_watchdog_timer_set(extif, ticks);
|
|
++}
|
|
++
|
|
++u32 ssb_extif_watchdog_timer_set_ms(struct bcm47xx_wdt *wdt, u32 ms)
|
|
++{
|
|
++ struct ssb_extif *extif = bcm47xx_wdt_get_drvdata(wdt);
|
|
++ u32 ticks = (SSB_EXTIF_WATCHDOG_CLK / 1000) * ms;
|
|
++
|
|
++ ticks = ssb_extif_watchdog_timer_set(extif, ticks);
|
|
++
|
|
++ return (ticks * 1000) / SSB_EXTIF_WATCHDOG_CLK;
|
|
++}
|
|
++
|
|
++u32 ssb_extif_watchdog_timer_set(struct ssb_extif *extif, u32 ticks)
|
|
++{
|
|
++ if (ticks > SSB_EXTIF_WATCHDOG_MAX_TIMER)
|
|
++ ticks = SSB_EXTIF_WATCHDOG_MAX_TIMER;
|
|
+ extif_write32(extif, SSB_EXTIF_WATCHDOG, ticks);
|
|
++
|
|
++ return ticks;
|
|
++}
|
|
++
|
|
++void ssb_extif_init(struct ssb_extif *extif)
|
|
++{
|
|
++ if (!extif->dev)
|
|
++ return; /* We don't have a Extif core */
|
|
++ spin_lock_init(&extif->gpio_lock);
|
|
+ }
|
|
+
|
|
+ u32 ssb_extif_gpio_in(struct ssb_extif *extif, u32 mask)
|
|
+@@ -125,22 +152,50 @@ u32 ssb_extif_gpio_in(struct ssb_extif *
|
|
+
|
|
+ u32 ssb_extif_gpio_out(struct ssb_extif *extif, u32 mask, u32 value)
|
|
+ {
|
|
+- return extif_write32_masked(extif, SSB_EXTIF_GPIO_OUT(0),
|
|
++ unsigned long flags;
|
|
++ u32 res = 0;
|
|
++
|
|
++ spin_lock_irqsave(&extif->gpio_lock, flags);
|
|
++ res = extif_write32_masked(extif, SSB_EXTIF_GPIO_OUT(0),
|
|
+ mask, value);
|
|
++ spin_unlock_irqrestore(&extif->gpio_lock, flags);
|
|
++
|
|
++ return res;
|
|
+ }
|
|
+
|
|
+ u32 ssb_extif_gpio_outen(struct ssb_extif *extif, u32 mask, u32 value)
|
|
+ {
|
|
+- return extif_write32_masked(extif, SSB_EXTIF_GPIO_OUTEN(0),
|
|
++ unsigned long flags;
|
|
++ u32 res = 0;
|
|
++
|
|
++ spin_lock_irqsave(&extif->gpio_lock, flags);
|
|
++ res = extif_write32_masked(extif, SSB_EXTIF_GPIO_OUTEN(0),
|
|
+ mask, value);
|
|
++ spin_unlock_irqrestore(&extif->gpio_lock, flags);
|
|
++
|
|
++ return res;
|
|
+ }
|
|
+
|
|
+ u32 ssb_extif_gpio_polarity(struct ssb_extif *extif, u32 mask, u32 value)
|
|
+ {
|
|
+- return extif_write32_masked(extif, SSB_EXTIF_GPIO_INTPOL, mask, value);
|
|
++ unsigned long flags;
|
|
++ u32 res = 0;
|
|
++
|
|
++ spin_lock_irqsave(&extif->gpio_lock, flags);
|
|
++ res = extif_write32_masked(extif, SSB_EXTIF_GPIO_INTPOL, mask, value);
|
|
++ spin_unlock_irqrestore(&extif->gpio_lock, flags);
|
|
++
|
|
++ return res;
|
|
+ }
|
|
+
|
|
+ u32 ssb_extif_gpio_intmask(struct ssb_extif *extif, u32 mask, u32 value)
|
|
+ {
|
|
+- return extif_write32_masked(extif, SSB_EXTIF_GPIO_INTMASK, mask, value);
|
|
++ unsigned long flags;
|
|
++ u32 res = 0;
|
|
++
|
|
++ spin_lock_irqsave(&extif->gpio_lock, flags);
|
|
++ res = extif_write32_masked(extif, SSB_EXTIF_GPIO_INTMASK, mask, value);
|
|
++ spin_unlock_irqrestore(&extif->gpio_lock, flags);
|
|
++
|
|
++ return res;
|
|
+ }
|
|
+--- /dev/null
|
|
++++ b/drivers/ssb/driver_gpio.c
|
|
+@@ -0,0 +1,210 @@
|
|
++/*
|
|
++ * Sonics Silicon Backplane
|
|
++ * GPIO driver
|
|
++ *
|
|
++ * Copyright 2011, Broadcom Corporation
|
|
++ * Copyright 2012, Hauke Mehrtens <hauke@hauke-m.de>
|
|
++ *
|
|
++ * Licensed under the GNU/GPL. See COPYING for details.
|
|
++ */
|
|
++
|
|
++#include <linux/gpio.h>
|
|
++#include <linux/export.h>
|
|
++#include <linux/ssb/ssb.h>
|
|
++
|
|
++#include "ssb_private.h"
|
|
++
|
|
++static struct ssb_bus *ssb_gpio_get_bus(struct gpio_chip *chip)
|
|
++{
|
|
++ return container_of(chip, struct ssb_bus, gpio);
|
|
++}
|
|
++
|
|
++static int ssb_gpio_chipco_get_value(struct gpio_chip *chip, unsigned gpio)
|
|
++{
|
|
++ struct ssb_bus *bus = ssb_gpio_get_bus(chip);
|
|
++
|
|
++ return !!ssb_chipco_gpio_in(&bus->chipco, 1 << gpio);
|
|
++}
|
|
++
|
|
++static void ssb_gpio_chipco_set_value(struct gpio_chip *chip, unsigned gpio,
|
|
++ int value)
|
|
++{
|
|
++ struct ssb_bus *bus = ssb_gpio_get_bus(chip);
|
|
++
|
|
++ ssb_chipco_gpio_out(&bus->chipco, 1 << gpio, value ? 1 << gpio : 0);
|
|
++}
|
|
++
|
|
++static int ssb_gpio_chipco_direction_input(struct gpio_chip *chip,
|
|
++ unsigned gpio)
|
|
++{
|
|
++ struct ssb_bus *bus = ssb_gpio_get_bus(chip);
|
|
++
|
|
++ ssb_chipco_gpio_outen(&bus->chipco, 1 << gpio, 0);
|
|
++ return 0;
|
|
++}
|
|
++
|
|
++static int ssb_gpio_chipco_direction_output(struct gpio_chip *chip,
|
|
++ unsigned gpio, int value)
|
|
++{
|
|
++ struct ssb_bus *bus = ssb_gpio_get_bus(chip);
|
|
++
|
|
++ ssb_chipco_gpio_outen(&bus->chipco, 1 << gpio, 1 << gpio);
|
|
++ ssb_chipco_gpio_out(&bus->chipco, 1 << gpio, value ? 1 << gpio : 0);
|
|
++ return 0;
|
|
++}
|
|
++
|
|
++static int ssb_gpio_chipco_request(struct gpio_chip *chip, unsigned gpio)
|
|
++{
|
|
++ struct ssb_bus *bus = ssb_gpio_get_bus(chip);
|
|
++
|
|
++ ssb_chipco_gpio_control(&bus->chipco, 1 << gpio, 0);
|
|
++ /* clear pulldown */
|
|
++ ssb_chipco_gpio_pulldown(&bus->chipco, 1 << gpio, 0);
|
|
++ /* Set pullup */
|
|
++ ssb_chipco_gpio_pullup(&bus->chipco, 1 << gpio, 1 << gpio);
|
|
++
|
|
++ return 0;
|
|
++}
|
|
++
|
|
++static void ssb_gpio_chipco_free(struct gpio_chip *chip, unsigned gpio)
|
|
++{
|
|
++ struct ssb_bus *bus = ssb_gpio_get_bus(chip);
|
|
++
|
|
++ /* clear pullup */
|
|
++ ssb_chipco_gpio_pullup(&bus->chipco, 1 << gpio, 0);
|
|
++}
|
|
++
|
|
++static int ssb_gpio_chipco_to_irq(struct gpio_chip *chip, unsigned gpio)
|
|
++{
|
|
++ struct ssb_bus *bus = ssb_gpio_get_bus(chip);
|
|
++
|
|
++ if (bus->bustype == SSB_BUSTYPE_SSB)
|
|
++ return ssb_mips_irq(bus->chipco.dev) + 2;
|
|
++ else
|
|
++ return -EINVAL;
|
|
++}
|
|
++
|
|
++static int ssb_gpio_chipco_init(struct ssb_bus *bus)
|
|
++{
|
|
++ struct gpio_chip *chip = &bus->gpio;
|
|
++
|
|
++ chip->label = "ssb_chipco_gpio";
|
|
++ chip->owner = THIS_MODULE;
|
|
++ chip->request = ssb_gpio_chipco_request;
|
|
++ chip->free = ssb_gpio_chipco_free;
|
|
++ chip->get = ssb_gpio_chipco_get_value;
|
|
++ chip->set = ssb_gpio_chipco_set_value;
|
|
++ chip->direction_input = ssb_gpio_chipco_direction_input;
|
|
++ chip->direction_output = ssb_gpio_chipco_direction_output;
|
|
++ chip->to_irq = ssb_gpio_chipco_to_irq;
|
|
++ chip->ngpio = 16;
|
|
++ /* There is just one SoC in one device and its GPIO addresses should be
|
|
++ * deterministic to address them more easily. The other buses could get
|
|
++ * a random base number. */
|
|
++ if (bus->bustype == SSB_BUSTYPE_SSB)
|
|
++ chip->base = 0;
|
|
++ else
|
|
++ chip->base = -1;
|
|
++
|
|
++ return gpiochip_add(chip);
|
|
++}
|
|
++
|
|
++#ifdef CONFIG_SSB_DRIVER_EXTIF
|
|
++
|
|
++static int ssb_gpio_extif_get_value(struct gpio_chip *chip, unsigned gpio)
|
|
++{
|
|
++ struct ssb_bus *bus = ssb_gpio_get_bus(chip);
|
|
++
|
|
++ return !!ssb_extif_gpio_in(&bus->extif, 1 << gpio);
|
|
++}
|
|
++
|
|
++static void ssb_gpio_extif_set_value(struct gpio_chip *chip, unsigned gpio,
|
|
++ int value)
|
|
++{
|
|
++ struct ssb_bus *bus = ssb_gpio_get_bus(chip);
|
|
++
|
|
++ ssb_extif_gpio_out(&bus->extif, 1 << gpio, value ? 1 << gpio : 0);
|
|
++}
|
|
++
|
|
++static int ssb_gpio_extif_direction_input(struct gpio_chip *chip,
|
|
++ unsigned gpio)
|
|
++{
|
|
++ struct ssb_bus *bus = ssb_gpio_get_bus(chip);
|
|
++
|
|
++ ssb_extif_gpio_outen(&bus->extif, 1 << gpio, 0);
|
|
++ return 0;
|
|
++}
|
|
++
|
|
++static int ssb_gpio_extif_direction_output(struct gpio_chip *chip,
|
|
++ unsigned gpio, int value)
|
|
++{
|
|
++ struct ssb_bus *bus = ssb_gpio_get_bus(chip);
|
|
++
|
|
++ ssb_extif_gpio_outen(&bus->extif, 1 << gpio, 1 << gpio);
|
|
++ ssb_extif_gpio_out(&bus->extif, 1 << gpio, value ? 1 << gpio : 0);
|
|
++ return 0;
|
|
++}
|
|
++
|
|
++static int ssb_gpio_extif_to_irq(struct gpio_chip *chip, unsigned gpio)
|
|
++{
|
|
++ struct ssb_bus *bus = ssb_gpio_get_bus(chip);
|
|
++
|
|
++ if (bus->bustype == SSB_BUSTYPE_SSB)
|
|
++ return ssb_mips_irq(bus->extif.dev) + 2;
|
|
++ else
|
|
++ return -EINVAL;
|
|
++}
|
|
++
|
|
++static int ssb_gpio_extif_init(struct ssb_bus *bus)
|
|
++{
|
|
++ struct gpio_chip *chip = &bus->gpio;
|
|
++
|
|
++ chip->label = "ssb_extif_gpio";
|
|
++ chip->owner = THIS_MODULE;
|
|
++ chip->get = ssb_gpio_extif_get_value;
|
|
++ chip->set = ssb_gpio_extif_set_value;
|
|
++ chip->direction_input = ssb_gpio_extif_direction_input;
|
|
++ chip->direction_output = ssb_gpio_extif_direction_output;
|
|
++ chip->to_irq = ssb_gpio_extif_to_irq;
|
|
++ chip->ngpio = 5;
|
|
++ /* There is just one SoC in one device and its GPIO addresses should be
|
|
++ * deterministic to address them more easily. The other buses could get
|
|
++ * a random base number. */
|
|
++ if (bus->bustype == SSB_BUSTYPE_SSB)
|
|
++ chip->base = 0;
|
|
++ else
|
|
++ chip->base = -1;
|
|
++
|
|
++ return gpiochip_add(chip);
|
|
++}
|
|
++
|
|
++#else
|
|
++static int ssb_gpio_extif_init(struct ssb_bus *bus)
|
|
++{
|
|
++ return -ENOTSUPP;
|
|
++}
|
|
++#endif
|
|
++
|
|
++int ssb_gpio_init(struct ssb_bus *bus)
|
|
++{
|
|
++ if (ssb_chipco_available(&bus->chipco))
|
|
++ return ssb_gpio_chipco_init(bus);
|
|
++ else if (ssb_extif_available(&bus->extif))
|
|
++ return ssb_gpio_extif_init(bus);
|
|
++ else
|
|
++ SSB_WARN_ON(1);
|
|
++
|
|
++ return -1;
|
|
++}
|
|
++
|
|
++int ssb_gpio_unregister(struct ssb_bus *bus)
|
|
++{
|
|
++ if (ssb_chipco_available(&bus->chipco) ||
|
|
++ ssb_extif_available(&bus->extif)) {
|
|
++ return gpiochip_remove(&bus->gpio);
|
|
++ } else {
|
|
++ SSB_WARN_ON(1);
|
|
++ }
|
|
++
|
|
++ return -1;
|
|
++}
|
|
--- a/drivers/ssb/driver_mipscore.c
|
|
+++ b/drivers/ssb/driver_mipscore.c
|
|
-@@ -208,6 +208,9 @@ u32 ssb_cpu_clock(struct ssb_mipscore *m
|
|
+@@ -17,7 +17,6 @@
|
|
+
|
|
+ #include "ssb_private.h"
|
|
+
|
|
+-
|
|
+ static inline u32 mips_read32(struct ssb_mipscore *mcore,
|
|
+ u16 offset)
|
|
+ {
|
|
+@@ -147,21 +146,22 @@ static void set_irq(struct ssb_device *d
|
|
+ irqflag |= (ipsflag & ~ipsflag_irq_mask[irq]);
|
|
+ ssb_write32(mdev, SSB_IPSFLAG, irqflag);
|
|
+ }
|
|
+- ssb_dprintk(KERN_INFO PFX
|
|
+- "set_irq: core 0x%04x, irq %d => %d\n",
|
|
+- dev->id.coreid, oldirq+2, irq+2);
|
|
++ ssb_dbg("set_irq: core 0x%04x, irq %d => %d\n",
|
|
++ dev->id.coreid, oldirq+2, irq+2);
|
|
+ }
|
|
+
|
|
+ static void print_irq(struct ssb_device *dev, unsigned int irq)
|
|
+ {
|
|
+- int i;
|
|
+ static const char *irq_name[] = {"2(S)", "3", "4", "5", "6", "D", "I"};
|
|
+- ssb_dprintk(KERN_INFO PFX
|
|
+- "core 0x%04x, irq :", dev->id.coreid);
|
|
+- for (i = 0; i <= 6; i++) {
|
|
+- ssb_dprintk(" %s%s", irq_name[i], i==irq?"*":" ");
|
|
+- }
|
|
+- ssb_dprintk("\n");
|
|
++ ssb_dbg("core 0x%04x, irq : %s%s %s%s %s%s %s%s %s%s %s%s %s%s\n",
|
|
++ dev->id.coreid,
|
|
++ irq_name[0], irq == 0 ? "*" : " ",
|
|
++ irq_name[1], irq == 1 ? "*" : " ",
|
|
++ irq_name[2], irq == 2 ? "*" : " ",
|
|
++ irq_name[3], irq == 3 ? "*" : " ",
|
|
++ irq_name[4], irq == 4 ? "*" : " ",
|
|
++ irq_name[5], irq == 5 ? "*" : " ",
|
|
++ irq_name[6], irq == 6 ? "*" : " ");
|
|
+ }
|
|
+
|
|
+ static void dump_irq(struct ssb_bus *bus)
|
|
+@@ -178,9 +178,9 @@ static void ssb_mips_serial_init(struct
|
|
+ {
|
|
struct ssb_bus *bus = mcore->dev->bus;
|
|
+
|
|
+- if (bus->extif.dev)
|
|
++ if (ssb_extif_available(&bus->extif))
|
|
+ mcore->nr_serial_ports = ssb_extif_serial_init(&bus->extif, mcore->serial_ports);
|
|
+- else if (bus->chipco.dev)
|
|
++ else if (ssb_chipco_available(&bus->chipco))
|
|
+ mcore->nr_serial_ports = ssb_chipco_serial_init(&bus->chipco, mcore->serial_ports);
|
|
+ else
|
|
+ mcore->nr_serial_ports = 0;
|
|
+@@ -191,7 +191,7 @@ static void ssb_mips_flash_detect(struct
|
|
+ struct ssb_bus *bus = mcore->dev->bus;
|
|
+
|
|
+ mcore->flash_buswidth = 2;
|
|
+- if (bus->chipco.dev) {
|
|
++ if (ssb_chipco_available(&bus->chipco)) {
|
|
+ mcore->flash_window = 0x1c000000;
|
|
+ mcore->flash_window_size = 0x02000000;
|
|
+ if ((ssb_read32(bus->chipco.dev, SSB_CHIPCO_FLASH_CFG)
|
|
+@@ -208,9 +208,12 @@ u32 ssb_cpu_clock(struct ssb_mipscore *m
|
|
+ struct ssb_bus *bus = mcore->dev->bus;
|
|
u32 pll_type, n, m, rate = 0;
|
|
|
|
+- if (bus->extif.dev) {
|
|
+ if (bus->chipco.capabilities & SSB_CHIPCO_CAP_PMU)
|
|
+ return ssb_pmu_get_cpu_clock(&bus->chipco);
|
|
+
|
|
- if (bus->extif.dev) {
|
|
++ if (ssb_extif_available(&bus->extif)) {
|
|
ssb_extif_get_clockcontrol(&bus->extif, &pll_type, &n, &m);
|
|
- } else if (bus->chipco.dev) {
|
|
+- } else if (bus->chipco.dev) {
|
|
++ } else if (ssb_chipco_available(&bus->chipco)) {
|
|
+ ssb_chipco_get_clockcpu(&bus->chipco, &pll_type, &n, &m);
|
|
+ } else
|
|
+ return 0;
|
|
+@@ -238,7 +241,7 @@ void ssb_mipscore_init(struct ssb_mipsco
|
|
+ if (!mcore->dev)
|
|
+ return; /* We don't have a MIPS core */
|
|
+
|
|
+- ssb_dprintk(KERN_INFO PFX "Initializing MIPS core...\n");
|
|
++ ssb_dbg("Initializing MIPS core...\n");
|
|
+
|
|
+ bus = mcore->dev->bus;
|
|
+ hz = ssb_clockspeed(bus);
|
|
+@@ -246,9 +249,9 @@ void ssb_mipscore_init(struct ssb_mipsco
|
|
+ hz = 100000000;
|
|
+ ns = 1000000000 / hz;
|
|
+
|
|
+- if (bus->extif.dev)
|
|
++ if (ssb_extif_available(&bus->extif))
|
|
+ ssb_extif_timing_init(&bus->extif, ns);
|
|
+- else if (bus->chipco.dev)
|
|
++ else if (ssb_chipco_available(&bus->chipco))
|
|
+ ssb_chipco_timing_init(&bus->chipco, ns);
|
|
+
|
|
+ /* Assign IRQs to all cores on the bus, start with irq line 2, because serial usually takes 1 */
|
|
+@@ -286,7 +289,7 @@ void ssb_mipscore_init(struct ssb_mipsco
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+- ssb_dprintk(KERN_INFO PFX "after irq reconfiguration\n");
|
|
++ ssb_dbg("after irq reconfiguration\n");
|
|
+ dump_irq(bus);
|
|
+
|
|
+ ssb_mips_serial_init(mcore);
|
|
+--- a/drivers/ssb/driver_pcicore.c
|
|
++++ b/drivers/ssb/driver_pcicore.c
|
|
+@@ -263,8 +263,7 @@ int ssb_pcicore_plat_dev_init(struct pci
|
|
+ return -ENODEV;
|
|
+ }
|
|
+
|
|
+- ssb_printk(KERN_INFO "PCI: Fixing up device %s\n",
|
|
+- pci_name(d));
|
|
++ ssb_info("PCI: Fixing up device %s\n", pci_name(d));
|
|
+
|
|
+ /* Fix up interrupt lines */
|
|
+ d->irq = ssb_mips_irq(extpci_core->dev) + 2;
|
|
+@@ -285,12 +284,12 @@ static void ssb_pcicore_fixup_pcibridge(
|
|
+ if (dev->bus->number != 0 || PCI_SLOT(dev->devfn) != 0)
|
|
+ return;
|
|
+
|
|
+- ssb_printk(KERN_INFO "PCI: Fixing up bridge %s\n", pci_name(dev));
|
|
++ ssb_info("PCI: Fixing up bridge %s\n", pci_name(dev));
|
|
+
|
|
+ /* Enable PCI bridge bus mastering and memory space */
|
|
+ pci_set_master(dev);
|
|
+ if (pcibios_enable_device(dev, ~0) < 0) {
|
|
+- ssb_printk(KERN_ERR "PCI: SSB bridge enable failed\n");
|
|
++ ssb_err("PCI: SSB bridge enable failed\n");
|
|
+ return;
|
|
+ }
|
|
+
|
|
+@@ -299,8 +298,8 @@ static void ssb_pcicore_fixup_pcibridge(
|
|
+
|
|
+ /* Make sure our latency is high enough to handle the devices behind us */
|
|
+ lat = 168;
|
|
+- ssb_printk(KERN_INFO "PCI: Fixing latency timer of device %s to %u\n",
|
|
+- pci_name(dev), lat);
|
|
++ ssb_info("PCI: Fixing latency timer of device %s to %u\n",
|
|
++ pci_name(dev), lat);
|
|
+ pci_write_config_byte(dev, PCI_LATENCY_TIMER, lat);
|
|
+ }
|
|
+ DECLARE_PCI_FIXUP_EARLY(PCI_ANY_ID, PCI_ANY_ID, ssb_pcicore_fixup_pcibridge);
|
|
+@@ -323,7 +322,7 @@ static void __devinit ssb_pcicore_init_h
|
|
+ return;
|
|
+ extpci_core = pc;
|
|
+
|
|
+- ssb_dprintk(KERN_INFO PFX "PCIcore in host mode found\n");
|
|
++ ssb_dbg("PCIcore in host mode found\n");
|
|
+ /* Reset devices on the external PCI bus */
|
|
+ val = SSB_PCICORE_CTL_RST_OE;
|
|
+ val |= SSB_PCICORE_CTL_CLK_OE;
|
|
+@@ -338,7 +337,7 @@ static void __devinit ssb_pcicore_init_h
|
|
+ udelay(1); /* Assertion time demanded by the PCI standard */
|
|
+
|
|
+ if (pc->dev->bus->has_cardbus_slot) {
|
|
+- ssb_dprintk(KERN_INFO PFX "CardBus slot detected\n");
|
|
++ ssb_dbg("CardBus slot detected\n");
|
|
+ pc->cardbusmode = 1;
|
|
+ /* GPIO 1 resets the bridge */
|
|
+ ssb_gpio_out(pc->dev->bus, 1, 1);
|
|
+--- a/drivers/ssb/embedded.c
|
|
++++ b/drivers/ssb/embedded.c
|
|
+@@ -4,11 +4,13 @@
|
|
+ *
|
|
+ * Copyright 2005-2008, Broadcom Corporation
|
|
+ * Copyright 2006-2008, Michael Buesch <m@bues.ch>
|
|
++ * Copyright 2012, Hauke Mehrtens <hauke@hauke-m.de>
|
|
+ *
|
|
+ * Licensed under the GNU/GPL. See COPYING for details.
|
|
+ */
|
|
+
|
|
+ #include <linux/export.h>
|
|
++#include <linux/platform_device.h>
|
|
+ #include <linux/ssb/ssb.h>
|
|
+ #include <linux/ssb/ssb_embedded.h>
|
|
+ #include <linux/ssb/ssb_driver_pci.h>
|
|
+@@ -32,6 +34,38 @@ int ssb_watchdog_timer_set(struct ssb_bu
|
|
+ }
|
|
+ EXPORT_SYMBOL(ssb_watchdog_timer_set);
|
|
+
|
|
++int ssb_watchdog_register(struct ssb_bus *bus)
|
|
++{
|
|
++ struct bcm47xx_wdt wdt = {};
|
|
++ struct platform_device *pdev;
|
|
++
|
|
++ if (ssb_chipco_available(&bus->chipco)) {
|
|
++ wdt.driver_data = &bus->chipco;
|
|
++ wdt.timer_set = ssb_chipco_watchdog_timer_set_wdt;
|
|
++ wdt.timer_set_ms = ssb_chipco_watchdog_timer_set_ms;
|
|
++ wdt.max_timer_ms = bus->chipco.max_timer_ms;
|
|
++ } else if (ssb_extif_available(&bus->extif)) {
|
|
++ wdt.driver_data = &bus->extif;
|
|
++ wdt.timer_set = ssb_extif_watchdog_timer_set_wdt;
|
|
++ wdt.timer_set_ms = ssb_extif_watchdog_timer_set_ms;
|
|
++ wdt.max_timer_ms = SSB_EXTIF_WATCHDOG_MAX_TIMER_MS;
|
|
++ } else {
|
|
++ return -ENODEV;
|
|
++ }
|
|
++
|
|
++ pdev = platform_device_register_data(NULL, "bcm47xx-wdt",
|
|
++ bus->busnumber, &wdt,
|
|
++ sizeof(wdt));
|
|
++ if (IS_ERR(pdev)) {
|
|
++ ssb_dbg("can not register watchdog device, err: %li\n",
|
|
++ PTR_ERR(pdev));
|
|
++ return PTR_ERR(pdev);
|
|
++ }
|
|
++
|
|
++ bus->watchdog = pdev;
|
|
++ return 0;
|
|
++}
|
|
++
|
|
+ u32 ssb_gpio_in(struct ssb_bus *bus, u32 mask)
|
|
+ {
|
|
+ unsigned long flags;
|
|
--- a/drivers/ssb/main.c
|
|
+++ b/drivers/ssb/main.c
|
|
-@@ -140,19 +140,6 @@ static void ssb_device_put(struct ssb_de
|
|
+@@ -13,6 +13,7 @@
|
|
+ #include <linux/delay.h>
|
|
+ #include <linux/io.h>
|
|
+ #include <linux/module.h>
|
|
++#include <linux/platform_device.h>
|
|
+ #include <linux/ssb/ssb.h>
|
|
+ #include <linux/ssb/ssb_regs.h>
|
|
+ #include <linux/ssb/ssb_driver_gige.h>
|
|
+@@ -140,19 +141,6 @@ static void ssb_device_put(struct ssb_de
|
|
put_device(dev->dev);
|
|
}
|
|
|
|
@@ -132,7 +1093,7 @@
|
|
static int ssb_device_resume(struct device *dev)
|
|
{
|
|
struct ssb_device *ssb_dev = dev_to_ssb_dev(dev);
|
|
-@@ -250,11 +237,9 @@ int ssb_devices_freeze(struct ssb_bus *b
|
|
+@@ -250,11 +238,9 @@ int ssb_devices_freeze(struct ssb_bus *b
|
|
ssb_device_put(sdev);
|
|
continue;
|
|
}
|
|
@@ -146,15 +1107,138 @@
|
|
sdrv->remove(sdev);
|
|
ctx->device_frozen[i] = 1;
|
|
}
|
|
-@@ -293,7 +278,6 @@ int ssb_devices_thaw(struct ssb_freeze_c
|
|
- dev_name(sdev->dev));
|
|
+@@ -289,11 +275,10 @@ int ssb_devices_thaw(struct ssb_freeze_c
|
|
+
|
|
+ err = sdrv->probe(sdev, &sdev->id);
|
|
+ if (err) {
|
|
+- ssb_printk(KERN_ERR PFX "Failed to thaw device %s\n",
|
|
+- dev_name(sdev->dev));
|
|
++ ssb_err("Failed to thaw device %s\n",
|
|
++ dev_name(sdev->dev));
|
|
result = err;
|
|
}
|
|
- ssb_driver_put(sdrv);
|
|
ssb_device_put(sdev);
|
|
}
|
|
|
|
-@@ -1094,6 +1078,9 @@ u32 ssb_clockspeed(struct ssb_bus *bus)
|
|
+@@ -449,10 +434,23 @@ static void ssb_devices_unregister(struc
|
|
+ if (sdev->dev)
|
|
+ device_unregister(sdev->dev);
|
|
+ }
|
|
++
|
|
++#ifdef CONFIG_SSB_EMBEDDED
|
|
++ if (bus->bustype == SSB_BUSTYPE_SSB)
|
|
++ platform_device_unregister(bus->watchdog);
|
|
++#endif
|
|
+ }
|
|
+
|
|
+ void ssb_bus_unregister(struct ssb_bus *bus)
|
|
+ {
|
|
++ int err;
|
|
++
|
|
++ err = ssb_gpio_unregister(bus);
|
|
++ if (err == -EBUSY)
|
|
++ ssb_dbg("Some GPIOs are still in use\n");
|
|
++ else if (err)
|
|
++ ssb_dbg("Can not unregister GPIO driver: %i\n", err);
|
|
++
|
|
+ ssb_buses_lock();
|
|
+ ssb_devices_unregister(bus);
|
|
+ list_del(&bus->list);
|
|
+@@ -498,8 +496,7 @@ static int ssb_devices_register(struct s
|
|
+
|
|
+ devwrap = kzalloc(sizeof(*devwrap), GFP_KERNEL);
|
|
+ if (!devwrap) {
|
|
+- ssb_printk(KERN_ERR PFX
|
|
+- "Could not allocate device\n");
|
|
++ ssb_err("Could not allocate device\n");
|
|
+ err = -ENOMEM;
|
|
+ goto error;
|
|
+ }
|
|
+@@ -538,9 +535,7 @@ static int ssb_devices_register(struct s
|
|
+ sdev->dev = dev;
|
|
+ err = device_register(dev);
|
|
+ if (err) {
|
|
+- ssb_printk(KERN_ERR PFX
|
|
+- "Could not register %s\n",
|
|
+- dev_name(dev));
|
|
++ ssb_err("Could not register %s\n", dev_name(dev));
|
|
+ /* Set dev to NULL to not unregister
|
|
+ * dev on error unwinding. */
|
|
+ sdev->dev = NULL;
|
|
+@@ -577,6 +572,8 @@ static int __devinit ssb_attach_queued_b
|
|
+ if (err)
|
|
+ goto error;
|
|
+ ssb_pcicore_init(&bus->pcicore);
|
|
++ if (bus->bustype == SSB_BUSTYPE_SSB)
|
|
++ ssb_watchdog_register(bus);
|
|
+ ssb_bus_may_powerdown(bus);
|
|
+
|
|
+ err = ssb_devices_register(bus);
|
|
+@@ -812,7 +809,13 @@ static int __devinit ssb_bus_register(st
|
|
+ if (err)
|
|
+ goto err_pcmcia_exit;
|
|
+ ssb_chipcommon_init(&bus->chipco);
|
|
++ ssb_extif_init(&bus->extif);
|
|
+ ssb_mipscore_init(&bus->mipscore);
|
|
++ err = ssb_gpio_init(bus);
|
|
++ if (err == -ENOTSUPP)
|
|
++ ssb_dbg("GPIO driver not activated\n");
|
|
++ else if (err)
|
|
++ ssb_dbg("Error registering GPIO driver: %i\n", err);
|
|
+ err = ssb_fetch_invariants(bus, get_invariants);
|
|
+ if (err) {
|
|
+ ssb_bus_may_powerdown(bus);
|
|
+@@ -863,11 +866,11 @@ int __devinit ssb_bus_pcibus_register(st
|
|
+
|
|
+ err = ssb_bus_register(bus, ssb_pci_get_invariants, 0);
|
|
+ if (!err) {
|
|
+- ssb_printk(KERN_INFO PFX "Sonics Silicon Backplane found on "
|
|
+- "PCI device %s\n", dev_name(&host_pci->dev));
|
|
++ ssb_info("Sonics Silicon Backplane found on PCI device %s\n",
|
|
++ dev_name(&host_pci->dev));
|
|
+ } else {
|
|
+- ssb_printk(KERN_ERR PFX "Failed to register PCI version"
|
|
+- " of SSB with error %d\n", err);
|
|
++ ssb_err("Failed to register PCI version of SSB with error %d\n",
|
|
++ err);
|
|
+ }
|
|
+
|
|
+ return err;
|
|
+@@ -888,8 +891,8 @@ int __devinit ssb_bus_pcmciabus_register
|
|
+
|
|
+ err = ssb_bus_register(bus, ssb_pcmcia_get_invariants, baseaddr);
|
|
+ if (!err) {
|
|
+- ssb_printk(KERN_INFO PFX "Sonics Silicon Backplane found on "
|
|
+- "PCMCIA device %s\n", pcmcia_dev->devname);
|
|
++ ssb_info("Sonics Silicon Backplane found on PCMCIA device %s\n",
|
|
++ pcmcia_dev->devname);
|
|
+ }
|
|
+
|
|
+ return err;
|
|
+@@ -911,8 +914,8 @@ int __devinit ssb_bus_sdiobus_register(s
|
|
+
|
|
+ err = ssb_bus_register(bus, ssb_sdio_get_invariants, ~0);
|
|
+ if (!err) {
|
|
+- ssb_printk(KERN_INFO PFX "Sonics Silicon Backplane found on "
|
|
+- "SDIO device %s\n", sdio_func_id(func));
|
|
++ ssb_info("Sonics Silicon Backplane found on SDIO device %s\n",
|
|
++ sdio_func_id(func));
|
|
+ }
|
|
+
|
|
+ return err;
|
|
+@@ -931,8 +934,8 @@ int __devinit ssb_bus_ssbbus_register(st
|
|
+
|
|
+ err = ssb_bus_register(bus, get_invariants, baseaddr);
|
|
+ if (!err) {
|
|
+- ssb_printk(KERN_INFO PFX "Sonics Silicon Backplane found at "
|
|
+- "address 0x%08lX\n", baseaddr);
|
|
++ ssb_info("Sonics Silicon Backplane found at address 0x%08lX\n",
|
|
++ baseaddr);
|
|
+ }
|
|
+
|
|
+ return err;
|
|
+@@ -1094,6 +1097,9 @@ u32 ssb_clockspeed(struct ssb_bus *bus)
|
|
u32 plltype;
|
|
u32 clkctl_n, clkctl_m;
|
|
|
|
@@ -164,9 +1248,78 @@
|
|
if (ssb_extif_available(&bus->extif))
|
|
ssb_extif_get_clockcontrol(&bus->extif, &plltype,
|
|
&clkctl_n, &clkctl_m);
|
|
+@@ -1131,8 +1137,7 @@ static u32 ssb_tmslow_reject_bitmask(str
|
|
+ case SSB_IDLOW_SSBREV_27: /* same here */
|
|
+ return SSB_TMSLOW_REJECT; /* this is a guess */
|
|
+ default:
|
|
+- printk(KERN_INFO "ssb: Backplane Revision 0x%.8X\n", rev);
|
|
+- WARN_ON(1);
|
|
++ WARN(1, KERN_INFO "ssb: Backplane Revision 0x%.8X\n", rev);
|
|
+ }
|
|
+ return (SSB_TMSLOW_REJECT | SSB_TMSLOW_REJECT_23);
|
|
+ }
|
|
+@@ -1324,7 +1329,7 @@ out:
|
|
+ #endif
|
|
+ return err;
|
|
+ error:
|
|
+- ssb_printk(KERN_ERR PFX "Bus powerdown failed\n");
|
|
++ ssb_err("Bus powerdown failed\n");
|
|
+ goto out;
|
|
+ }
|
|
+ EXPORT_SYMBOL(ssb_bus_may_powerdown);
|
|
+@@ -1347,7 +1352,7 @@ int ssb_bus_powerup(struct ssb_bus *bus,
|
|
+
|
|
+ return 0;
|
|
+ error:
|
|
+- ssb_printk(KERN_ERR PFX "Bus powerup failed\n");
|
|
++ ssb_err("Bus powerup failed\n");
|
|
+ return err;
|
|
+ }
|
|
+ EXPORT_SYMBOL(ssb_bus_powerup);
|
|
+@@ -1455,15 +1460,13 @@ static int __init ssb_modinit(void)
|
|
+
|
|
+ err = b43_pci_ssb_bridge_init();
|
|
+ if (err) {
|
|
+- ssb_printk(KERN_ERR "Broadcom 43xx PCI-SSB-bridge "
|
|
+- "initialization failed\n");
|
|
++ ssb_err("Broadcom 43xx PCI-SSB-bridge initialization failed\n");
|
|
+ /* don't fail SSB init because of this */
|
|
+ err = 0;
|
|
+ }
|
|
+ err = ssb_gige_init();
|
|
+ if (err) {
|
|
+- ssb_printk(KERN_ERR "SSB Broadcom Gigabit Ethernet "
|
|
+- "driver initialization failed\n");
|
|
++ ssb_err("SSB Broadcom Gigabit Ethernet driver initialization failed\n");
|
|
+ /* don't fail SSB init because of this */
|
|
+ err = 0;
|
|
+ }
|
|
--- a/drivers/ssb/pci.c
|
|
+++ b/drivers/ssb/pci.c
|
|
-@@ -178,6 +178,18 @@ err_pci:
|
|
+@@ -56,7 +56,7 @@ int ssb_pci_switch_coreidx(struct ssb_bu
|
|
+ }
|
|
+ return 0;
|
|
+ error:
|
|
+- ssb_printk(KERN_ERR PFX "Failed to switch to core %u\n", coreidx);
|
|
++ ssb_err("Failed to switch to core %u\n", coreidx);
|
|
+ return -ENODEV;
|
|
+ }
|
|
+
|
|
+@@ -67,10 +67,9 @@ int ssb_pci_switch_core(struct ssb_bus *
|
|
+ unsigned long flags;
|
|
+
|
|
+ #if SSB_VERBOSE_PCICORESWITCH_DEBUG
|
|
+- ssb_printk(KERN_INFO PFX
|
|
+- "Switching to %s core, index %d\n",
|
|
+- ssb_core_name(dev->id.coreid),
|
|
+- dev->core_index);
|
|
++ ssb_info("Switching to %s core, index %d\n",
|
|
++ ssb_core_name(dev->id.coreid),
|
|
++ dev->core_index);
|
|
+ #endif
|
|
+
|
|
+ spin_lock_irqsave(&bus->bar_lock, flags);
|
|
+@@ -178,6 +177,18 @@ err_pci:
|
|
#define SPEX(_outvar, _offset, _mask, _shift) \
|
|
SPEX16(_outvar, _offset, _mask, _shift)
|
|
|
|
@@ -185,30 +1338,140 @@
|
|
|
|
static inline u8 ssb_crc8(u8 crc, u8 data)
|
|
{
|
|
-@@ -331,7 +343,6 @@ static void sprom_extract_r123(struct ss
|
|
+@@ -219,6 +230,15 @@ static inline u8 ssb_crc8(u8 crc, u8 dat
|
|
+ return t[crc ^ data];
|
|
+ }
|
|
+
|
|
++static void sprom_get_mac(char *mac, const u16 *in)
|
|
++{
|
|
++ int i;
|
|
++ for (i = 0; i < 3; i++) {
|
|
++ *mac++ = in[i] >> 8;
|
|
++ *mac++ = in[i];
|
|
++ }
|
|
++}
|
|
++
|
|
+ static u8 ssb_sprom_crc(const u16 *sprom, u16 size)
|
|
{
|
|
- int i;
|
|
- u16 v;
|
|
+ int word;
|
|
+@@ -266,7 +286,7 @@ static int sprom_do_write(struct ssb_bus
|
|
+ u32 spromctl;
|
|
+ u16 size = bus->sprom_size;
|
|
+
|
|
+- ssb_printk(KERN_NOTICE PFX "Writing SPROM. Do NOT turn off the power! Please stand by...\n");
|
|
++ ssb_notice("Writing SPROM. Do NOT turn off the power! Please stand by...\n");
|
|
+ err = pci_read_config_dword(pdev, SSB_SPROMCTL, &spromctl);
|
|
+ if (err)
|
|
+ goto err_ctlreg;
|
|
+@@ -274,17 +294,17 @@ static int sprom_do_write(struct ssb_bus
|
|
+ err = pci_write_config_dword(pdev, SSB_SPROMCTL, spromctl);
|
|
+ if (err)
|
|
+ goto err_ctlreg;
|
|
+- ssb_printk(KERN_NOTICE PFX "[ 0%%");
|
|
++ ssb_notice("[ 0%%");
|
|
+ msleep(500);
|
|
+ for (i = 0; i < size; i++) {
|
|
+ if (i == size / 4)
|
|
+- ssb_printk("25%%");
|
|
++ ssb_cont("25%%");
|
|
+ else if (i == size / 2)
|
|
+- ssb_printk("50%%");
|
|
++ ssb_cont("50%%");
|
|
+ else if (i == (size * 3) / 4)
|
|
+- ssb_printk("75%%");
|
|
++ ssb_cont("75%%");
|
|
+ else if (i % 2)
|
|
+- ssb_printk(".");
|
|
++ ssb_cont(".");
|
|
+ writew(sprom[i], bus->mmio + bus->sprom_offset + (i * 2));
|
|
+ mmiowb();
|
|
+ msleep(20);
|
|
+@@ -297,12 +317,12 @@ static int sprom_do_write(struct ssb_bus
|
|
+ if (err)
|
|
+ goto err_ctlreg;
|
|
+ msleep(500);
|
|
+- ssb_printk("100%% ]\n");
|
|
+- ssb_printk(KERN_NOTICE PFX "SPROM written.\n");
|
|
++ ssb_cont("100%% ]\n");
|
|
++ ssb_notice("SPROM written\n");
|
|
+
|
|
+ return 0;
|
|
+ err_ctlreg:
|
|
+- ssb_printk(KERN_ERR PFX "Could not access SPROM control register.\n");
|
|
++ ssb_err("Could not access SPROM control register.\n");
|
|
+ return err;
|
|
+ }
|
|
+
|
|
+@@ -327,11 +347,23 @@ static s8 r123_extract_antgain(u8 sprom_
|
|
+ return (s8)gain;
|
|
+ }
|
|
+
|
|
++static void sprom_extract_r23(struct ssb_sprom *out, const u16 *in)
|
|
++{
|
|
++ SPEX(boardflags_hi, SSB_SPROM2_BFLHI, 0xFFFF, 0);
|
|
++ SPEX(opo, SSB_SPROM2_OPO, SSB_SPROM2_OPO_VALUE, 0);
|
|
++ SPEX(pa1lob0, SSB_SPROM2_PA1LOB0, 0xFFFF, 0);
|
|
++ SPEX(pa1lob1, SSB_SPROM2_PA1LOB1, 0xFFFF, 0);
|
|
++ SPEX(pa1lob2, SSB_SPROM2_PA1LOB2, 0xFFFF, 0);
|
|
++ SPEX(pa1hib0, SSB_SPROM2_PA1HIB0, 0xFFFF, 0);
|
|
++ SPEX(pa1hib1, SSB_SPROM2_PA1HIB1, 0xFFFF, 0);
|
|
++ SPEX(pa1hib2, SSB_SPROM2_PA1HIB2, 0xFFFF, 0);
|
|
++ SPEX(maxpwr_ah, SSB_SPROM2_MAXP_A, SSB_SPROM2_MAXP_A_HI, 0);
|
|
++ SPEX(maxpwr_al, SSB_SPROM2_MAXP_A, SSB_SPROM2_MAXP_A_LO,
|
|
++ SSB_SPROM2_MAXP_A_LO_SHIFT);
|
|
++}
|
|
++
|
|
+ static void sprom_extract_r123(struct ssb_sprom *out, const u16 *in)
|
|
+ {
|
|
+- int i;
|
|
+- u16 v;
|
|
- s8 gain;
|
|
u16 loc[3];
|
|
|
|
if (out->revision == 3) /* rev 3 moved MAC */
|
|
-@@ -361,8 +372,9 @@ static void sprom_extract_r123(struct ss
|
|
+@@ -341,19 +373,10 @@ static void sprom_extract_r123(struct ss
|
|
+ loc[1] = SSB_SPROM1_ET0MAC;
|
|
+ loc[2] = SSB_SPROM1_ET1MAC;
|
|
+ }
|
|
+- for (i = 0; i < 3; i++) {
|
|
+- v = in[SPOFF(loc[0]) + i];
|
|
+- *(((__be16 *)out->il0mac) + i) = cpu_to_be16(v);
|
|
+- }
|
|
++ sprom_get_mac(out->il0mac, &in[SPOFF(loc[0])]);
|
|
+ if (out->revision < 3) { /* only rev 1-2 have et0, et1 */
|
|
+- for (i = 0; i < 3; i++) {
|
|
+- v = in[SPOFF(loc[1]) + i];
|
|
+- *(((__be16 *)out->et0mac) + i) = cpu_to_be16(v);
|
|
+- }
|
|
+- for (i = 0; i < 3; i++) {
|
|
+- v = in[SPOFF(loc[2]) + i];
|
|
+- *(((__be16 *)out->et1mac) + i) = cpu_to_be16(v);
|
|
+- }
|
|
++ sprom_get_mac(out->et0mac, &in[SPOFF(loc[1])]);
|
|
++ sprom_get_mac(out->et1mac, &in[SPOFF(loc[2])]);
|
|
+ }
|
|
+ SPEX(et0phyaddr, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET0A, 0);
|
|
+ SPEX(et1phyaddr, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET1A,
|
|
+@@ -361,8 +384,10 @@ static void sprom_extract_r123(struct ss
|
|
SPEX(et0mdcport, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET0M, 14);
|
|
SPEX(et1mdcport, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET1M, 15);
|
|
SPEX(board_rev, SSB_SPROM1_BINF, SSB_SPROM1_BINF_BREV, 0);
|
|
- SPEX(country_code, SSB_SPROM1_BINF, SSB_SPROM1_BINF_CCODE,
|
|
- SSB_SPROM1_BINF_CCODE_SHIFT);
|
|
++ SPEX(board_type, SSB_SPROM1_SPID, 0xFFFF, 0);
|
|
+ if (out->revision == 1)
|
|
+ SPEX(country_code, SSB_SPROM1_BINF, SSB_SPROM1_BINF_CCODE,
|
|
+ SSB_SPROM1_BINF_CCODE_SHIFT);
|
|
SPEX(ant_available_a, SSB_SPROM1_BINF, SSB_SPROM1_BINF_ANTA,
|
|
SSB_SPROM1_BINF_ANTA_SHIFT);
|
|
SPEX(ant_available_bg, SSB_SPROM1_BINF, SSB_SPROM1_BINF_ANTBG,
|
|
-@@ -388,22 +400,16 @@ static void sprom_extract_r123(struct ss
|
|
+@@ -386,24 +411,19 @@ static void sprom_extract_r123(struct ss
|
|
+ SSB_SPROM1_ITSSI_A_SHIFT);
|
|
+ SPEX(itssi_bg, SSB_SPROM1_ITSSI, SSB_SPROM1_ITSSI_BG, 0);
|
|
SPEX(boardflags_lo, SSB_SPROM1_BFLLO, 0xFFFF, 0);
|
|
- if (out->revision >= 2)
|
|
- SPEX(boardflags_hi, SSB_SPROM2_BFLHI, 0xFFFF, 0);
|
|
+- if (out->revision >= 2)
|
|
+- SPEX(boardflags_hi, SSB_SPROM2_BFLHI, 0xFFFF, 0);
|
|
++
|
|
+ SPEX(alpha2[0], SSB_SPROM1_CCODE, 0xff00, 8);
|
|
+ SPEX(alpha2[1], SSB_SPROM1_CCODE, 0x00ff, 0);
|
|
|
|
@@ -233,14 +1496,36 @@
|
|
+ out->antenna_gain.a1 = r123_extract_antgain(out->revision, in,
|
|
+ SSB_SPROM1_AGAIN_A,
|
|
+ SSB_SPROM1_AGAIN_A_SHIFT);
|
|
++ if (out->revision >= 2)
|
|
++ sprom_extract_r23(out, in);
|
|
}
|
|
|
|
/* Revs 4 5 and 8 have partially shared layout */
|
|
-@@ -464,14 +470,17 @@ static void sprom_extract_r45(struct ssb
|
|
+@@ -448,30 +468,30 @@ static void sprom_extract_r458(struct ss
|
|
+
|
|
+ static void sprom_extract_r45(struct ssb_sprom *out, const u16 *in)
|
|
+ {
|
|
+- int i;
|
|
+- u16 v;
|
|
+ u16 il0mac_offset;
|
|
+
|
|
+ if (out->revision == 4)
|
|
+ il0mac_offset = SSB_SPROM4_IL0MAC;
|
|
+ else
|
|
+ il0mac_offset = SSB_SPROM5_IL0MAC;
|
|
+- /* extract the MAC address */
|
|
+- for (i = 0; i < 3; i++) {
|
|
+- v = in[SPOFF(il0mac_offset) + i];
|
|
+- *(((__be16 *)out->il0mac) + i) = cpu_to_be16(v);
|
|
+- }
|
|
++
|
|
++ sprom_get_mac(out->il0mac, &in[SPOFF(il0mac_offset)]);
|
|
++
|
|
SPEX(et0phyaddr, SSB_SPROM4_ETHPHY, SSB_SPROM4_ETHPHY_ET0A, 0);
|
|
SPEX(et1phyaddr, SSB_SPROM4_ETHPHY, SSB_SPROM4_ETHPHY_ET1A,
|
|
SSB_SPROM4_ETHPHY_ET1A_SHIFT);
|
|
+ SPEX(board_rev, SSB_SPROM4_BOARDREV, 0xFFFF, 0);
|
|
++ SPEX(board_type, SSB_SPROM1_SPID, 0xFFFF, 0);
|
|
if (out->revision == 4) {
|
|
- SPEX(country_code, SSB_SPROM4_CCODE, 0xFFFF, 0);
|
|
+ SPEX(alpha2[0], SSB_SPROM4_CCODE, 0xff00, 8);
|
|
@@ -256,7 +1541,7 @@
|
|
SPEX(boardflags_lo, SSB_SPROM5_BFLLO, 0xFFFF, 0);
|
|
SPEX(boardflags_hi, SSB_SPROM5_BFLHI, 0xFFFF, 0);
|
|
SPEX(boardflags2_lo, SSB_SPROM5_BFL2LO, 0xFFFF, 0);
|
|
-@@ -504,16 +513,14 @@ static void sprom_extract_r45(struct ssb
|
|
+@@ -504,16 +524,14 @@ static void sprom_extract_r45(struct ssb
|
|
}
|
|
|
|
/* Extract the antenna gain values. */
|
|
@@ -277,12 +1562,12 @@
|
|
|
|
sprom_extract_r458(out, in);
|
|
|
|
-@@ -523,14 +530,22 @@ static void sprom_extract_r45(struct ssb
|
|
+@@ -523,14 +541,21 @@ static void sprom_extract_r45(struct ssb
|
|
static void sprom_extract_r8(struct ssb_sprom *out, const u16 *in)
|
|
{
|
|
int i;
|
|
- u16 v;
|
|
-+ u16 v, o;
|
|
++ u16 o;
|
|
+ u16 pwr_info_offset[] = {
|
|
+ SSB_SROM8_PWR_INFO_CORE0, SSB_SROM8_PWR_INFO_CORE1,
|
|
+ SSB_SROM8_PWR_INFO_CORE2, SSB_SROM8_PWR_INFO_CORE3
|
|
@@ -291,18 +1576,21 @@
|
|
+ ARRAY_SIZE(out->core_pwr_info));
|
|
|
|
/* extract the MAC address */
|
|
- for (i = 0; i < 3; i++) {
|
|
- v = in[SPOFF(SSB_SPROM8_IL0MAC) + i];
|
|
- *(((__be16 *)out->il0mac) + i) = cpu_to_be16(v);
|
|
- }
|
|
+- for (i = 0; i < 3; i++) {
|
|
+- v = in[SPOFF(SSB_SPROM8_IL0MAC) + i];
|
|
+- *(((__be16 *)out->il0mac) + i) = cpu_to_be16(v);
|
|
+- }
|
|
- SPEX(country_code, SSB_SPROM8_CCODE, 0xFFFF, 0);
|
|
++ sprom_get_mac(out->il0mac, &in[SPOFF(SSB_SPROM8_IL0MAC)]);
|
|
++
|
|
+ SPEX(board_rev, SSB_SPROM8_BOARDREV, 0xFFFF, 0);
|
|
++ SPEX(board_type, SSB_SPROM1_SPID, 0xFFFF, 0);
|
|
+ SPEX(alpha2[0], SSB_SPROM8_CCODE, 0xff00, 8);
|
|
+ SPEX(alpha2[1], SSB_SPROM8_CCODE, 0x00ff, 0);
|
|
SPEX(boardflags_lo, SSB_SPROM8_BFLLO, 0xFFFF, 0);
|
|
SPEX(boardflags_hi, SSB_SPROM8_BFLHI, 0xFFFF, 0);
|
|
SPEX(boardflags2_lo, SSB_SPROM8_BFL2LO, 0xFFFF, 0);
|
|
-@@ -596,16 +611,46 @@ static void sprom_extract_r8(struct ssb_
|
|
+@@ -596,16 +621,46 @@ static void sprom_extract_r8(struct ssb_
|
|
SPEX32(ofdm5ghpo, SSB_SPROM8_OFDM5GHPO, 0xFFFFFFFF, 0);
|
|
|
|
/* Extract the antenna gain values. */
|
|
@@ -355,7 +1643,7 @@
|
|
|
|
/* Extract FEM info */
|
|
SPEX(fem.ghz2.tssipos, SSB_SPROM8_FEM2G,
|
|
-@@ -630,6 +675,63 @@ static void sprom_extract_r8(struct ssb_
|
|
+@@ -630,6 +685,63 @@ static void sprom_extract_r8(struct ssb_
|
|
SPEX(fem.ghz5.antswlut, SSB_SPROM8_FEM5G,
|
|
SSB_SROM8_FEM_ANTSWLUT, SSB_SROM8_FEM_ANTSWLUT_SHIFT);
|
|
|
|
@@ -419,7 +1707,79 @@
|
|
sprom_extract_r458(out, in);
|
|
|
|
/* TODO - get remaining rev 8 stuff needed */
|
|
-@@ -759,7 +861,6 @@ static void ssb_pci_get_boardinfo(struct
|
|
+@@ -641,7 +753,7 @@ static int sprom_extract(struct ssb_bus
|
|
+ memset(out, 0, sizeof(*out));
|
|
+
|
|
+ out->revision = in[size - 1] & 0x00FF;
|
|
+- ssb_dprintk(KERN_DEBUG PFX "SPROM revision %d detected.\n", out->revision);
|
|
++ ssb_dbg("SPROM revision %d detected\n", out->revision);
|
|
+ memset(out->et0mac, 0xFF, 6); /* preset et0 and et1 mac */
|
|
+ memset(out->et1mac, 0xFF, 6);
|
|
+
|
|
+@@ -650,7 +762,7 @@ static int sprom_extract(struct ssb_bus
|
|
+ * number stored in the SPROM.
|
|
+ * Always extract r1. */
|
|
+ out->revision = 1;
|
|
+- ssb_dprintk(KERN_DEBUG PFX "SPROM treated as revision %d\n", out->revision);
|
|
++ ssb_dbg("SPROM treated as revision %d\n", out->revision);
|
|
+ }
|
|
+
|
|
+ switch (out->revision) {
|
|
+@@ -667,9 +779,8 @@ static int sprom_extract(struct ssb_bus
|
|
+ sprom_extract_r8(out, in);
|
|
+ break;
|
|
+ default:
|
|
+- ssb_printk(KERN_WARNING PFX "Unsupported SPROM"
|
|
+- " revision %d detected. Will extract"
|
|
+- " v1\n", out->revision);
|
|
++ ssb_warn("Unsupported SPROM revision %d detected. Will extract v1\n",
|
|
++ out->revision);
|
|
+ out->revision = 1;
|
|
+ sprom_extract_r123(out, in);
|
|
+ }
|
|
+@@ -689,7 +800,7 @@ static int ssb_pci_sprom_get(struct ssb_
|
|
+ u16 *buf;
|
|
+
|
|
+ if (!ssb_is_sprom_available(bus)) {
|
|
+- ssb_printk(KERN_ERR PFX "No SPROM available!\n");
|
|
++ ssb_err("No SPROM available!\n");
|
|
+ return -ENODEV;
|
|
+ }
|
|
+ if (bus->chipco.dev) { /* can be unavailable! */
|
|
+@@ -708,7 +819,7 @@ static int ssb_pci_sprom_get(struct ssb_
|
|
+ } else {
|
|
+ bus->sprom_offset = SSB_SPROM_BASE1;
|
|
+ }
|
|
+- ssb_dprintk(KERN_INFO PFX "SPROM offset is 0x%x\n", bus->sprom_offset);
|
|
++ ssb_dbg("SPROM offset is 0x%x\n", bus->sprom_offset);
|
|
+
|
|
+ buf = kcalloc(SSB_SPROMSIZE_WORDS_R123, sizeof(u16), GFP_KERNEL);
|
|
+ if (!buf)
|
|
+@@ -733,18 +844,15 @@ static int ssb_pci_sprom_get(struct ssb_
|
|
+ * available for this device in some other storage */
|
|
+ err = ssb_fill_sprom_with_fallback(bus, sprom);
|
|
+ if (err) {
|
|
+- ssb_printk(KERN_WARNING PFX "WARNING: Using"
|
|
+- " fallback SPROM failed (err %d)\n",
|
|
+- err);
|
|
++ ssb_warn("WARNING: Using fallback SPROM failed (err %d)\n",
|
|
++ err);
|
|
+ } else {
|
|
+- ssb_dprintk(KERN_DEBUG PFX "Using SPROM"
|
|
+- " revision %d provided by"
|
|
+- " platform.\n", sprom->revision);
|
|
++ ssb_dbg("Using SPROM revision %d provided by platform\n",
|
|
++ sprom->revision);
|
|
+ err = 0;
|
|
+ goto out_free;
|
|
+ }
|
|
+- ssb_printk(KERN_WARNING PFX "WARNING: Invalid"
|
|
+- " SPROM CRC (corrupt SPROM)\n");
|
|
++ ssb_warn("WARNING: Invalid SPROM CRC (corrupt SPROM)\n");
|
|
+ }
|
|
+ }
|
|
+ err = sprom_extract(bus, sprom, buf, bus->sprom_size);
|
|
+@@ -759,7 +867,6 @@ static void ssb_pci_get_boardinfo(struct
|
|
{
|
|
bi->vendor = bus->host_pci->subsystem_vendor;
|
|
bi->type = bus->host_pci->subsystem_device;
|
|
@@ -429,7 +1789,95 @@
|
|
int ssb_pci_get_invariants(struct ssb_bus *bus,
|
|
--- a/drivers/ssb/pcmcia.c
|
|
+++ b/drivers/ssb/pcmcia.c
|
|
-@@ -676,14 +676,10 @@ static int ssb_pcmcia_do_get_invariants(
|
|
+@@ -143,7 +143,7 @@ int ssb_pcmcia_switch_coreidx(struct ssb
|
|
+
|
|
+ return 0;
|
|
+ error:
|
|
+- ssb_printk(KERN_ERR PFX "Failed to switch to core %u\n", coreidx);
|
|
++ ssb_err("Failed to switch to core %u\n", coreidx);
|
|
+ return err;
|
|
+ }
|
|
+
|
|
+@@ -153,10 +153,9 @@ int ssb_pcmcia_switch_core(struct ssb_bu
|
|
+ int err;
|
|
+
|
|
+ #if SSB_VERBOSE_PCMCIACORESWITCH_DEBUG
|
|
+- ssb_printk(KERN_INFO PFX
|
|
+- "Switching to %s core, index %d\n",
|
|
+- ssb_core_name(dev->id.coreid),
|
|
+- dev->core_index);
|
|
++ ssb_info("Switching to %s core, index %d\n",
|
|
++ ssb_core_name(dev->id.coreid),
|
|
++ dev->core_index);
|
|
+ #endif
|
|
+
|
|
+ err = ssb_pcmcia_switch_coreidx(bus, dev->core_index);
|
|
+@@ -192,7 +191,7 @@ int ssb_pcmcia_switch_segment(struct ssb
|
|
+
|
|
+ return 0;
|
|
+ error:
|
|
+- ssb_printk(KERN_ERR PFX "Failed to switch pcmcia segment\n");
|
|
++ ssb_err("Failed to switch pcmcia segment\n");
|
|
+ return err;
|
|
+ }
|
|
+
|
|
+@@ -549,44 +548,39 @@ static int ssb_pcmcia_sprom_write_all(st
|
|
+ bool failed = 0;
|
|
+ size_t size = SSB_PCMCIA_SPROM_SIZE;
|
|
+
|
|
+- ssb_printk(KERN_NOTICE PFX
|
|
+- "Writing SPROM. Do NOT turn off the power! "
|
|
+- "Please stand by...\n");
|
|
++ ssb_notice("Writing SPROM. Do NOT turn off the power! Please stand by...\n");
|
|
+ err = ssb_pcmcia_sprom_command(bus, SSB_PCMCIA_SPROMCTL_WRITEEN);
|
|
+ if (err) {
|
|
+- ssb_printk(KERN_NOTICE PFX
|
|
+- "Could not enable SPROM write access.\n");
|
|
++ ssb_notice("Could not enable SPROM write access\n");
|
|
+ return -EBUSY;
|
|
+ }
|
|
+- ssb_printk(KERN_NOTICE PFX "[ 0%%");
|
|
++ ssb_notice("[ 0%%");
|
|
+ msleep(500);
|
|
+ for (i = 0; i < size; i++) {
|
|
+ if (i == size / 4)
|
|
+- ssb_printk("25%%");
|
|
++ ssb_cont("25%%");
|
|
+ else if (i == size / 2)
|
|
+- ssb_printk("50%%");
|
|
++ ssb_cont("50%%");
|
|
+ else if (i == (size * 3) / 4)
|
|
+- ssb_printk("75%%");
|
|
++ ssb_cont("75%%");
|
|
+ else if (i % 2)
|
|
+- ssb_printk(".");
|
|
++ ssb_cont(".");
|
|
+ err = ssb_pcmcia_sprom_write(bus, i, sprom[i]);
|
|
+ if (err) {
|
|
+- ssb_printk(KERN_NOTICE PFX
|
|
+- "Failed to write to SPROM.\n");
|
|
++ ssb_notice("Failed to write to SPROM\n");
|
|
+ failed = 1;
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ err = ssb_pcmcia_sprom_command(bus, SSB_PCMCIA_SPROMCTL_WRITEDIS);
|
|
+ if (err) {
|
|
+- ssb_printk(KERN_NOTICE PFX
|
|
+- "Could not disable SPROM write access.\n");
|
|
++ ssb_notice("Could not disable SPROM write access\n");
|
|
+ failed = 1;
|
|
+ }
|
|
+ msleep(500);
|
|
+ if (!failed) {
|
|
+- ssb_printk("100%% ]\n");
|
|
+- ssb_printk(KERN_NOTICE PFX "SPROM written.\n");
|
|
++ ssb_cont("100%% ]\n");
|
|
++ ssb_notice("SPROM written\n");
|
|
+ }
|
|
+
|
|
+ return failed ? -EBUSY : 0;
|
|
+@@ -676,14 +670,10 @@ static int ssb_pcmcia_do_get_invariants(
|
|
case SSB_PCMCIA_CIS_ANTGAIN:
|
|
GOTO_ERROR_ON(tuple->TupleDataLen != 2,
|
|
"antg tpl size");
|
|
@@ -448,6 +1896,41 @@
|
|
break;
|
|
case SSB_PCMCIA_CIS_BFLAGS:
|
|
GOTO_ERROR_ON((tuple->TupleDataLen != 3) &&
|
|
+@@ -704,7 +694,7 @@ static int ssb_pcmcia_do_get_invariants(
|
|
+ return -ENOSPC; /* continue with next entry */
|
|
+
|
|
+ error:
|
|
+- ssb_printk(KERN_ERR PFX
|
|
++ ssb_err(
|
|
+ "PCMCIA: Failed to fetch device invariants: %s\n",
|
|
+ error_description);
|
|
+ return -ENODEV;
|
|
+@@ -726,7 +716,7 @@ int ssb_pcmcia_get_invariants(struct ssb
|
|
+ res = pcmcia_loop_tuple(bus->host_pcmcia, CISTPL_FUNCE,
|
|
+ ssb_pcmcia_get_mac, sprom);
|
|
+ if (res != 0) {
|
|
+- ssb_printk(KERN_ERR PFX
|
|
++ ssb_err(
|
|
+ "PCMCIA: Failed to fetch MAC address\n");
|
|
+ return -ENODEV;
|
|
+ }
|
|
+@@ -737,7 +727,7 @@ int ssb_pcmcia_get_invariants(struct ssb
|
|
+ if ((res == 0) || (res == -ENOSPC))
|
|
+ return 0;
|
|
+
|
|
+- ssb_printk(KERN_ERR PFX
|
|
++ ssb_err(
|
|
+ "PCMCIA: Failed to fetch device invariants\n");
|
|
+ return -ENODEV;
|
|
+ }
|
|
+@@ -847,6 +837,6 @@ int ssb_pcmcia_init(struct ssb_bus *bus)
|
|
+
|
|
+ return 0;
|
|
+ error:
|
|
+- ssb_printk(KERN_ERR PFX "Failed to initialize PCMCIA host device\n");
|
|
++ ssb_err("Failed to initialize PCMCIA host device\n");
|
|
+ return err;
|
|
+ }
|
|
--- a/drivers/ssb/scan.c
|
|
+++ b/drivers/ssb/scan.c
|
|
@@ -90,6 +90,8 @@ const char *ssb_core_name(u16 coreid)
|
|
@@ -459,16 +1942,93 @@
|
|
}
|
|
return "UNKNOWN";
|
|
}
|
|
-@@ -318,6 +320,9 @@ int ssb_bus_scan(struct ssb_bus *bus,
|
|
+@@ -123,8 +125,7 @@ static u16 pcidev_to_chipid(struct pci_d
|
|
+ chipid_fallback = 0x4401;
|
|
+ break;
|
|
+ default:
|
|
+- ssb_printk(KERN_ERR PFX
|
|
+- "PCI-ID not in fallback list\n");
|
|
++ ssb_err("PCI-ID not in fallback list\n");
|
|
+ }
|
|
+
|
|
+ return chipid_fallback;
|
|
+@@ -150,8 +151,7 @@ static u8 chipid_to_nrcores(u16 chipid)
|
|
+ case 0x4704:
|
|
+ return 9;
|
|
+ default:
|
|
+- ssb_printk(KERN_ERR PFX
|
|
+- "CHIPID not in nrcores fallback list\n");
|
|
++ ssb_err("CHIPID not in nrcores fallback list\n");
|
|
+ }
|
|
+
|
|
+ return 1;
|
|
+@@ -318,12 +318,13 @@ int ssb_bus_scan(struct ssb_bus *bus,
|
|
bus->chip_package = 0;
|
|
}
|
|
}
|
|
-+ ssb_printk(KERN_INFO PFX "Found chip with id 0x%04X, rev 0x%02X and "
|
|
-+ "package 0x%02X\n", bus->chip_id, bus->chip_rev,
|
|
-+ bus->chip_package);
|
|
++ ssb_info("Found chip with id 0x%04X, rev 0x%02X and package 0x%02X\n",
|
|
++ bus->chip_id, bus->chip_rev, bus->chip_package);
|
|
if (!bus->nr_devices)
|
|
bus->nr_devices = chipid_to_nrcores(bus->chip_id);
|
|
if (bus->nr_devices > ARRAY_SIZE(bus->devices)) {
|
|
+- ssb_printk(KERN_ERR PFX
|
|
+- "More than %d ssb cores found (%d)\n",
|
|
+- SSB_MAX_NR_CORES, bus->nr_devices);
|
|
++ ssb_err("More than %d ssb cores found (%d)\n",
|
|
++ SSB_MAX_NR_CORES, bus->nr_devices);
|
|
+ goto err_unmap;
|
|
+ }
|
|
+ if (bus->bustype == SSB_BUSTYPE_SSB) {
|
|
+@@ -365,8 +366,7 @@ int ssb_bus_scan(struct ssb_bus *bus,
|
|
+ nr_80211_cores++;
|
|
+ if (nr_80211_cores > 1) {
|
|
+ if (!we_support_multiple_80211_cores(bus)) {
|
|
+- ssb_dprintk(KERN_INFO PFX "Ignoring additional "
|
|
+- "802.11 core\n");
|
|
++ ssb_dbg("Ignoring additional 802.11 core\n");
|
|
+ continue;
|
|
+ }
|
|
+ }
|
|
+@@ -374,8 +374,7 @@ int ssb_bus_scan(struct ssb_bus *bus,
|
|
+ case SSB_DEV_EXTIF:
|
|
+ #ifdef CONFIG_SSB_DRIVER_EXTIF
|
|
+ if (bus->extif.dev) {
|
|
+- ssb_printk(KERN_WARNING PFX
|
|
+- "WARNING: Multiple EXTIFs found\n");
|
|
++ ssb_warn("WARNING: Multiple EXTIFs found\n");
|
|
+ break;
|
|
+ }
|
|
+ bus->extif.dev = dev;
|
|
+@@ -383,8 +382,7 @@ int ssb_bus_scan(struct ssb_bus *bus,
|
|
+ break;
|
|
+ case SSB_DEV_CHIPCOMMON:
|
|
+ if (bus->chipco.dev) {
|
|
+- ssb_printk(KERN_WARNING PFX
|
|
+- "WARNING: Multiple ChipCommon found\n");
|
|
++ ssb_warn("WARNING: Multiple ChipCommon found\n");
|
|
+ break;
|
|
+ }
|
|
+ bus->chipco.dev = dev;
|
|
+@@ -393,8 +391,7 @@ int ssb_bus_scan(struct ssb_bus *bus,
|
|
+ case SSB_DEV_MIPS_3302:
|
|
+ #ifdef CONFIG_SSB_DRIVER_MIPS
|
|
+ if (bus->mipscore.dev) {
|
|
+- ssb_printk(KERN_WARNING PFX
|
|
+- "WARNING: Multiple MIPS cores found\n");
|
|
++ ssb_warn("WARNING: Multiple MIPS cores found\n");
|
|
+ break;
|
|
+ }
|
|
+ bus->mipscore.dev = dev;
|
|
+@@ -415,8 +412,7 @@ int ssb_bus_scan(struct ssb_bus *bus,
|
|
+ }
|
|
+ }
|
|
+ if (bus->pcicore.dev) {
|
|
+- ssb_printk(KERN_WARNING PFX
|
|
+- "WARNING: Multiple PCI(E) cores found\n");
|
|
++ ssb_warn("WARNING: Multiple PCI(E) cores found\n");
|
|
+ break;
|
|
+ }
|
|
+ bus->pcicore.dev = dev;
|
|
--- a/drivers/ssb/sdio.c
|
|
+++ b/drivers/ssb/sdio.c
|
|
@@ -551,14 +551,10 @@ int ssb_sdio_get_invariants(struct ssb_b
|
|
@@ -490,20 +2050,139 @@
|
|
break;
|
|
case SSB_SDIO_CIS_BFLAGS:
|
|
GOTO_ERROR_ON((tuple->size != 3) &&
|
|
+--- a/drivers/ssb/sprom.c
|
|
++++ b/drivers/ssb/sprom.c
|
|
+@@ -127,13 +127,13 @@ ssize_t ssb_attr_sprom_store(struct ssb_
|
|
+ goto out_kfree;
|
|
+ err = ssb_devices_freeze(bus, &freeze);
|
|
+ if (err) {
|
|
+- ssb_printk(KERN_ERR PFX "SPROM write: Could not freeze all devices\n");
|
|
++ ssb_err("SPROM write: Could not freeze all devices\n");
|
|
+ goto out_unlock;
|
|
+ }
|
|
+ res = sprom_write(bus, sprom);
|
|
+ err = ssb_devices_thaw(&freeze);
|
|
+ if (err)
|
|
+- ssb_printk(KERN_ERR PFX "SPROM write: Could not thaw all devices\n");
|
|
++ ssb_err("SPROM write: Could not thaw all devices\n");
|
|
+ out_unlock:
|
|
+ mutex_unlock(&bus->sprom_mutex);
|
|
+ out_kfree:
|
|
--- a/drivers/ssb/ssb_private.h
|
|
+++ b/drivers/ssb/ssb_private.h
|
|
-@@ -207,4 +207,8 @@ static inline void b43_pci_ssb_bridge_ex
|
|
+@@ -3,21 +3,33 @@
|
|
+
|
|
+ #include <linux/ssb/ssb.h>
|
|
+ #include <linux/types.h>
|
|
++#include <linux/bcm47xx_wdt.h>
|
|
+
|
|
+
|
|
+ #define PFX "ssb: "
|
|
+
|
|
+ #ifdef CONFIG_SSB_SILENT
|
|
+-# define ssb_printk(fmt, x...) do { /* nothing */ } while (0)
|
|
++# define ssb_printk(fmt, ...) \
|
|
++ do { if (0) printk(fmt, ##__VA_ARGS__); } while (0)
|
|
+ #else
|
|
+-# define ssb_printk printk
|
|
++# define ssb_printk(fmt, ...) \
|
|
++ printk(fmt, ##__VA_ARGS__)
|
|
+ #endif /* CONFIG_SSB_SILENT */
|
|
+
|
|
++#define ssb_emerg(fmt, ...) ssb_printk(KERN_EMERG PFX fmt, ##__VA_ARGS__)
|
|
++#define ssb_err(fmt, ...) ssb_printk(KERN_ERR PFX fmt, ##__VA_ARGS__)
|
|
++#define ssb_warn(fmt, ...) ssb_printk(KERN_WARNING PFX fmt, ##__VA_ARGS__)
|
|
++#define ssb_notice(fmt, ...) ssb_printk(KERN_NOTICE PFX fmt, ##__VA_ARGS__)
|
|
++#define ssb_info(fmt, ...) ssb_printk(KERN_INFO PFX fmt, ##__VA_ARGS__)
|
|
++#define ssb_cont(fmt, ...) ssb_printk(KERN_CONT fmt, ##__VA_ARGS__)
|
|
++
|
|
+ /* dprintk: Debugging printk; vanishes for non-debug compilation */
|
|
+ #ifdef CONFIG_SSB_DEBUG
|
|
+-# define ssb_dprintk(fmt, x...) ssb_printk(fmt , ##x)
|
|
++# define ssb_dbg(fmt, ...) \
|
|
++ ssb_printk(KERN_DEBUG PFX fmt, ##__VA_ARGS__)
|
|
+ #else
|
|
+-# define ssb_dprintk(fmt, x...) do { /* nothing */ } while (0)
|
|
++# define ssb_dbg(fmt, ...) \
|
|
++ do { if (0) printk(KERN_DEBUG PFX fmt, ##__VA_ARGS__); } while (0)
|
|
+ #endif
|
|
+
|
|
+ #ifdef CONFIG_SSB_DEBUG
|
|
+@@ -207,4 +219,60 @@ static inline void b43_pci_ssb_bridge_ex
|
|
}
|
|
#endif /* CONFIG_SSB_B43_PCI_BRIDGE */
|
|
|
|
+/* driver_chipcommon_pmu.c */
|
|
+extern u32 ssb_pmu_get_cpu_clock(struct ssb_chipcommon *cc);
|
|
+extern u32 ssb_pmu_get_controlclock(struct ssb_chipcommon *cc);
|
|
++extern u32 ssb_pmu_get_alp_clock(struct ssb_chipcommon *cc);
|
|
+
|
|
++extern u32 ssb_chipco_watchdog_timer_set_wdt(struct bcm47xx_wdt *wdt,
|
|
++ u32 ticks);
|
|
++extern u32 ssb_chipco_watchdog_timer_set_ms(struct bcm47xx_wdt *wdt, u32 ms);
|
|
++
|
|
++#ifdef CONFIG_SSB_DRIVER_EXTIF
|
|
++extern u32 ssb_extif_watchdog_timer_set_wdt(struct bcm47xx_wdt *wdt, u32 ticks);
|
|
++extern u32 ssb_extif_watchdog_timer_set_ms(struct bcm47xx_wdt *wdt, u32 ms);
|
|
++#else
|
|
++static inline u32 ssb_extif_watchdog_timer_set_wdt(struct bcm47xx_wdt *wdt,
|
|
++ u32 ticks)
|
|
++{
|
|
++ return 0;
|
|
++}
|
|
++static inline u32 ssb_extif_watchdog_timer_set_ms(struct bcm47xx_wdt *wdt,
|
|
++ u32 ms)
|
|
++{
|
|
++ return 0;
|
|
++}
|
|
++#endif
|
|
++
|
|
++#ifdef CONFIG_SSB_EMBEDDED
|
|
++extern int ssb_watchdog_register(struct ssb_bus *bus);
|
|
++#else /* CONFIG_SSB_EMBEDDED */
|
|
++static inline int ssb_watchdog_register(struct ssb_bus *bus)
|
|
++{
|
|
++ return 0;
|
|
++}
|
|
++#endif /* CONFIG_SSB_EMBEDDED */
|
|
++
|
|
++#ifdef CONFIG_SSB_DRIVER_EXTIF
|
|
++extern void ssb_extif_init(struct ssb_extif *extif);
|
|
++#else
|
|
++static inline void ssb_extif_init(struct ssb_extif *extif)
|
|
++{
|
|
++}
|
|
++#endif
|
|
++
|
|
++#ifdef CONFIG_SSB_DRIVER_GPIO
|
|
++extern int ssb_gpio_init(struct ssb_bus *bus);
|
|
++extern int ssb_gpio_unregister(struct ssb_bus *bus);
|
|
++#else /* CONFIG_SSB_DRIVER_GPIO */
|
|
++static inline int ssb_gpio_init(struct ssb_bus *bus)
|
|
++{
|
|
++ return -ENOTSUPP;
|
|
++}
|
|
++static inline int ssb_gpio_unregister(struct ssb_bus *bus)
|
|
++{
|
|
++ return 0;
|
|
++}
|
|
++#endif /* CONFIG_SSB_DRIVER_GPIO */
|
|
++
|
|
#endif /* LINUX_SSB_PRIVATE_H_ */
|
|
--- a/include/linux/ssb/ssb.h
|
|
+++ b/include/linux/ssb/ssb.h
|
|
-@@ -16,6 +16,12 @@ struct pcmcia_device;
|
|
+@@ -6,8 +6,10 @@
|
|
+ #include <linux/types.h>
|
|
+ #include <linux/spinlock.h>
|
|
+ #include <linux/pci.h>
|
|
++#include <linux/gpio.h>
|
|
+ #include <linux/mod_devicetable.h>
|
|
+ #include <linux/dma-mapping.h>
|
|
++#include <linux/platform_device.h>
|
|
+
|
|
+ #include <linux/ssb/ssb_regs.h>
|
|
+
|
|
+@@ -16,19 +18,28 @@ struct pcmcia_device;
|
|
struct ssb_bus;
|
|
struct ssb_driver;
|
|
|
|
@@ -515,8 +2194,14 @@
|
|
+
|
|
struct ssb_sprom {
|
|
u8 revision;
|
|
- u8 il0mac[6]; /* MAC address for 802.11b/g */
|
|
-@@ -26,9 +32,12 @@ struct ssb_sprom {
|
|
+- u8 il0mac[6]; /* MAC address for 802.11b/g */
|
|
+- u8 et0mac[6]; /* MAC address for Ethernet */
|
|
+- u8 et1mac[6]; /* MAC address for 802.11a */
|
|
++ u8 il0mac[6] __aligned(sizeof(u16)); /* MAC address for 802.11b/g */
|
|
++ u8 et0mac[6] __aligned(sizeof(u16)); /* MAC address for Ethernet */
|
|
++ u8 et1mac[6] __aligned(sizeof(u16)); /* MAC address for 802.11a */
|
|
+ u8 et0phyaddr; /* MII address for enet0 */
|
|
+ u8 et1phyaddr; /* MII address for enet1 */
|
|
u8 et0mdcport; /* MDIO for enet0 */
|
|
u8 et1mdcport; /* MDIO for enet1 */
|
|
u16 board_rev; /* Board revision number from SPROM. */
|
|
@@ -531,7 +2216,7 @@
|
|
u8 ant_available_a; /* 2GHz antenna available bits (up to 4) */
|
|
u8 ant_available_bg; /* 5GHz antenna available bits (up to 4) */
|
|
u16 pa0b0;
|
|
-@@ -47,10 +56,10 @@ struct ssb_sprom {
|
|
+@@ -47,10 +58,10 @@ struct ssb_sprom {
|
|
u8 gpio1; /* GPIO pin 1 */
|
|
u8 gpio2; /* GPIO pin 2 */
|
|
u8 gpio3; /* GPIO pin 3 */
|
|
@@ -546,7 +2231,7 @@
|
|
u8 itssi_a; /* Idle TSSI Target for A-PHY */
|
|
u8 itssi_bg; /* Idle TSSI Target for B/G-PHY */
|
|
u8 tri2g; /* 2.4GHz TX isolation */
|
|
-@@ -61,8 +70,8 @@ struct ssb_sprom {
|
|
+@@ -61,8 +72,8 @@ struct ssb_sprom {
|
|
u8 txpid5gl[4]; /* 4.9 - 5.1GHz TX power index */
|
|
u8 txpid5g[4]; /* 5.1 - 5.5GHz TX power index */
|
|
u8 txpid5gh[4]; /* 5.5 - ...GHz TX power index */
|
|
@@ -557,7 +2242,7 @@
|
|
u8 rssisav2g; /* 2GHz RSSI params */
|
|
u8 rssismc2g;
|
|
u8 rssismf2g;
|
|
-@@ -82,16 +91,13 @@ struct ssb_sprom {
|
|
+@@ -82,16 +93,13 @@ struct ssb_sprom {
|
|
u16 boardflags2_hi; /* Board flags (bits 48-63) */
|
|
/* TODO store board flags in a single u64 */
|
|
|
|
@@ -577,7 +2262,7 @@
|
|
} antenna_gain;
|
|
|
|
struct {
|
|
-@@ -103,14 +109,85 @@ struct ssb_sprom {
|
|
+@@ -103,14 +111,85 @@ struct ssb_sprom {
|
|
} ghz5;
|
|
} fem;
|
|
|
|
@@ -665,7 +2350,7 @@
|
|
};
|
|
|
|
|
|
-@@ -166,6 +243,7 @@ struct ssb_bus_ops {
|
|
+@@ -166,6 +245,7 @@ struct ssb_bus_ops {
|
|
#define SSB_DEV_MINI_MACPHY 0x823
|
|
#define SSB_DEV_ARM_1176 0x824
|
|
#define SSB_DEV_ARM_7TDMI 0x825
|
|
@@ -673,6 +2358,214 @@
|
|
|
|
/* Vendor-ID values */
|
|
#define SSB_VENDOR_BROADCOM 0x4243
|
|
+@@ -260,13 +340,61 @@ enum ssb_bustype {
|
|
+ #define SSB_BOARDVENDOR_DELL 0x1028 /* Dell */
|
|
+ #define SSB_BOARDVENDOR_HP 0x0E11 /* HP */
|
|
+ /* board_type */
|
|
++#define SSB_BOARD_BCM94301CB 0x0406
|
|
++#define SSB_BOARD_BCM94301MP 0x0407
|
|
++#define SSB_BOARD_BU4309 0x040A
|
|
++#define SSB_BOARD_BCM94309CB 0x040B
|
|
++#define SSB_BOARD_BCM4309MP 0x040C
|
|
++#define SSB_BOARD_BU4306 0x0416
|
|
+ #define SSB_BOARD_BCM94306MP 0x0418
|
|
+ #define SSB_BOARD_BCM4309G 0x0421
|
|
+ #define SSB_BOARD_BCM4306CB 0x0417
|
|
+-#define SSB_BOARD_BCM4309MP 0x040C
|
|
++#define SSB_BOARD_BCM94306PC 0x0425 /* pcmcia 3.3v 4306 card */
|
|
++#define SSB_BOARD_BCM94306CBSG 0x042B /* with SiGe PA */
|
|
++#define SSB_BOARD_PCSG94306 0x042D /* with SiGe PA */
|
|
++#define SSB_BOARD_BU4704SD 0x042E /* with sdram */
|
|
++#define SSB_BOARD_BCM94704AGR 0x042F /* dual 11a/11g Router */
|
|
++#define SSB_BOARD_BCM94308MP 0x0430 /* 11a-only minipci */
|
|
++#define SSB_BOARD_BU4318 0x0447
|
|
++#define SSB_BOARD_CB4318 0x0448
|
|
++#define SSB_BOARD_MPG4318 0x0449
|
|
+ #define SSB_BOARD_MP4318 0x044A
|
|
+-#define SSB_BOARD_BU4306 0x0416
|
|
+-#define SSB_BOARD_BU4309 0x040A
|
|
++#define SSB_BOARD_SD4318 0x044B
|
|
++#define SSB_BOARD_BCM94306P 0x044C /* with SiGe */
|
|
++#define SSB_BOARD_BCM94303MP 0x044E
|
|
++#define SSB_BOARD_BCM94306MPM 0x0450
|
|
++#define SSB_BOARD_BCM94306MPL 0x0453
|
|
++#define SSB_BOARD_PC4303 0x0454 /* pcmcia */
|
|
++#define SSB_BOARD_BCM94306MPLNA 0x0457
|
|
++#define SSB_BOARD_BCM94306MPH 0x045B
|
|
++#define SSB_BOARD_BCM94306PCIV 0x045C
|
|
++#define SSB_BOARD_BCM94318MPGH 0x0463
|
|
++#define SSB_BOARD_BU4311 0x0464
|
|
++#define SSB_BOARD_BCM94311MC 0x0465
|
|
++#define SSB_BOARD_BCM94311MCAG 0x0466
|
|
++/* 4321 boards */
|
|
++#define SSB_BOARD_BU4321 0x046B
|
|
++#define SSB_BOARD_BU4321E 0x047C
|
|
++#define SSB_BOARD_MP4321 0x046C
|
|
++#define SSB_BOARD_CB2_4321 0x046D
|
|
++#define SSB_BOARD_CB2_4321_AG 0x0066
|
|
++#define SSB_BOARD_MC4321 0x046E
|
|
++/* 4325 boards */
|
|
++#define SSB_BOARD_BCM94325DEVBU 0x0490
|
|
++#define SSB_BOARD_BCM94325BGABU 0x0491
|
|
++#define SSB_BOARD_BCM94325SDGWB 0x0492
|
|
++#define SSB_BOARD_BCM94325SDGMDL 0x04AA
|
|
++#define SSB_BOARD_BCM94325SDGMDL2 0x04C6
|
|
++#define SSB_BOARD_BCM94325SDGMDL3 0x04C9
|
|
++#define SSB_BOARD_BCM94325SDABGWBA 0x04E1
|
|
++/* 4322 boards */
|
|
++#define SSB_BOARD_BCM94322MC 0x04A4
|
|
++#define SSB_BOARD_BCM94322USB 0x04A8 /* dualband */
|
|
++#define SSB_BOARD_BCM94322HM 0x04B0
|
|
++#define SSB_BOARD_BCM94322USB2D 0x04Bf /* single band discrete front end */
|
|
++/* 4312 boards */
|
|
++#define SSB_BOARD_BU4312 0x048A
|
|
++#define SSB_BOARD_BCM4312MCGSG 0x04B5
|
|
+ /* chip_package */
|
|
+ #define SSB_CHIPPACK_BCM4712S 1 /* Small 200pin 4712 */
|
|
+ #define SSB_CHIPPACK_BCM4712M 2 /* Medium 225pin 4712 */
|
|
+@@ -354,7 +482,11 @@ struct ssb_bus {
|
|
+ #ifdef CONFIG_SSB_EMBEDDED
|
|
+ /* Lock for GPIO register access. */
|
|
+ spinlock_t gpio_lock;
|
|
++ struct platform_device *watchdog;
|
|
+ #endif /* EMBEDDED */
|
|
++#ifdef CONFIG_SSB_DRIVER_GPIO
|
|
++ struct gpio_chip gpio;
|
|
++#endif /* DRIVER_GPIO */
|
|
+
|
|
+ /* Internal-only stuff follows. Do not touch. */
|
|
+ struct list_head list;
|
|
+--- a/include/linux/ssb/ssb_driver_chipcommon.h
|
|
++++ b/include/linux/ssb/ssb_driver_chipcommon.h
|
|
+@@ -219,6 +219,7 @@
|
|
+ #define SSB_CHIPCO_PMU_CTL 0x0600 /* PMU control */
|
|
+ #define SSB_CHIPCO_PMU_CTL_ILP_DIV 0xFFFF0000 /* ILP div mask */
|
|
+ #define SSB_CHIPCO_PMU_CTL_ILP_DIV_SHIFT 16
|
|
++#define SSB_CHIPCO_PMU_CTL_PLL_UPD 0x00000400
|
|
+ #define SSB_CHIPCO_PMU_CTL_NOILPONW 0x00000200 /* No ILP on wait */
|
|
+ #define SSB_CHIPCO_PMU_CTL_HTREQEN 0x00000100 /* HT req enable */
|
|
+ #define SSB_CHIPCO_PMU_CTL_ALPREQEN 0x00000080 /* ALP req enable */
|
|
+@@ -588,7 +589,10 @@ struct ssb_chipcommon {
|
|
+ u32 status;
|
|
+ /* Fast Powerup Delay constant */
|
|
+ u16 fast_pwrup_delay;
|
|
++ spinlock_t gpio_lock;
|
|
+ struct ssb_chipcommon_pmu pmu;
|
|
++ u32 ticks_per_ms;
|
|
++ u32 max_timer_ms;
|
|
+ };
|
|
+
|
|
+ static inline bool ssb_chipco_available(struct ssb_chipcommon *cc)
|
|
+@@ -628,8 +632,7 @@ enum ssb_clkmode {
|
|
+ extern void ssb_chipco_set_clockmode(struct ssb_chipcommon *cc,
|
|
+ enum ssb_clkmode mode);
|
|
+
|
|
+-extern void ssb_chipco_watchdog_timer_set(struct ssb_chipcommon *cc,
|
|
+- u32 ticks);
|
|
++extern u32 ssb_chipco_watchdog_timer_set(struct ssb_chipcommon *cc, u32 ticks);
|
|
+
|
|
+ void ssb_chipco_irq_mask(struct ssb_chipcommon *cc, u32 mask, u32 value);
|
|
+
|
|
+@@ -642,6 +645,8 @@ u32 ssb_chipco_gpio_outen(struct ssb_chi
|
|
+ u32 ssb_chipco_gpio_control(struct ssb_chipcommon *cc, u32 mask, u32 value);
|
|
+ u32 ssb_chipco_gpio_intmask(struct ssb_chipcommon *cc, u32 mask, u32 value);
|
|
+ u32 ssb_chipco_gpio_polarity(struct ssb_chipcommon *cc, u32 mask, u32 value);
|
|
++u32 ssb_chipco_gpio_pullup(struct ssb_chipcommon *cc, u32 mask, u32 value);
|
|
++u32 ssb_chipco_gpio_pulldown(struct ssb_chipcommon *cc, u32 mask, u32 value);
|
|
+
|
|
+ #ifdef CONFIG_SSB_SERIAL
|
|
+ extern int ssb_chipco_serial_init(struct ssb_chipcommon *cc,
|
|
+@@ -661,5 +666,6 @@ enum ssb_pmu_ldo_volt_id {
|
|
+ void ssb_pmu_set_ldo_voltage(struct ssb_chipcommon *cc,
|
|
+ enum ssb_pmu_ldo_volt_id id, u32 voltage);
|
|
+ void ssb_pmu_set_ldo_paref(struct ssb_chipcommon *cc, bool on);
|
|
++void ssb_pmu_spuravoid_pllupdate(struct ssb_chipcommon *cc, int spuravoid);
|
|
+
|
|
+ #endif /* LINUX_SSB_CHIPCO_H_ */
|
|
+--- a/include/linux/ssb/ssb_driver_extif.h
|
|
++++ b/include/linux/ssb/ssb_driver_extif.h
|
|
+@@ -152,12 +152,16 @@
|
|
+ /* watchdog */
|
|
+ #define SSB_EXTIF_WATCHDOG_CLK 48000000 /* Hz */
|
|
+
|
|
++#define SSB_EXTIF_WATCHDOG_MAX_TIMER ((1 << 28) - 1)
|
|
++#define SSB_EXTIF_WATCHDOG_MAX_TIMER_MS (SSB_EXTIF_WATCHDOG_MAX_TIMER \
|
|
++ / (SSB_EXTIF_WATCHDOG_CLK / 1000))
|
|
+
|
|
+
|
|
+ #ifdef CONFIG_SSB_DRIVER_EXTIF
|
|
+
|
|
+ struct ssb_extif {
|
|
+ struct ssb_device *dev;
|
|
++ spinlock_t gpio_lock;
|
|
+ };
|
|
+
|
|
+ static inline bool ssb_extif_available(struct ssb_extif *extif)
|
|
+@@ -171,8 +175,7 @@ extern void ssb_extif_get_clockcontrol(s
|
|
+ extern void ssb_extif_timing_init(struct ssb_extif *extif,
|
|
+ unsigned long ns);
|
|
+
|
|
+-extern void ssb_extif_watchdog_timer_set(struct ssb_extif *extif,
|
|
+- u32 ticks);
|
|
++extern u32 ssb_extif_watchdog_timer_set(struct ssb_extif *extif, u32 ticks);
|
|
+
|
|
+ /* Extif GPIO pin access */
|
|
+ u32 ssb_extif_gpio_in(struct ssb_extif *extif, u32 mask);
|
|
+@@ -205,10 +208,52 @@ void ssb_extif_get_clockcontrol(struct s
|
|
+ }
|
|
+
|
|
+ static inline
|
|
+-void ssb_extif_watchdog_timer_set(struct ssb_extif *extif,
|
|
+- u32 ticks)
|
|
++void ssb_extif_timing_init(struct ssb_extif *extif, unsigned long ns)
|
|
+ {
|
|
+ }
|
|
+
|
|
++static inline
|
|
++u32 ssb_extif_watchdog_timer_set(struct ssb_extif *extif, u32 ticks)
|
|
++{
|
|
++ return 0;
|
|
++}
|
|
++
|
|
++static inline u32 ssb_extif_gpio_in(struct ssb_extif *extif, u32 mask)
|
|
++{
|
|
++ return 0;
|
|
++}
|
|
++
|
|
++static inline u32 ssb_extif_gpio_out(struct ssb_extif *extif, u32 mask,
|
|
++ u32 value)
|
|
++{
|
|
++ return 0;
|
|
++}
|
|
++
|
|
++static inline u32 ssb_extif_gpio_outen(struct ssb_extif *extif, u32 mask,
|
|
++ u32 value)
|
|
++{
|
|
++ return 0;
|
|
++}
|
|
++
|
|
++static inline u32 ssb_extif_gpio_polarity(struct ssb_extif *extif, u32 mask,
|
|
++ u32 value)
|
|
++{
|
|
++ return 0;
|
|
++}
|
|
++
|
|
++static inline u32 ssb_extif_gpio_intmask(struct ssb_extif *extif, u32 mask,
|
|
++ u32 value)
|
|
++{
|
|
++ return 0;
|
|
++}
|
|
++
|
|
++#ifdef CONFIG_SSB_SERIAL
|
|
++static inline int ssb_extif_serial_init(struct ssb_extif *extif,
|
|
++ struct ssb_serial_port *ports)
|
|
++{
|
|
++ return 0;
|
|
++}
|
|
++#endif /* CONFIG_SSB_SERIAL */
|
|
++
|
|
+ #endif /* CONFIG_SSB_DRIVER_EXTIF */
|
|
+ #endif /* LINUX_SSB_EXTIFCORE_H_ */
|
|
--- a/include/linux/ssb/ssb_driver_gige.h
|
|
+++ b/include/linux/ssb/ssb_driver_gige.h
|
|
@@ -2,6 +2,7 @@
|
|
@@ -683,9 +2576,71 @@
|
|
#include <linux/pci.h>
|
|
#include <linux/spinlock.h>
|
|
|
|
+@@ -96,21 +97,16 @@ static inline bool ssb_gige_must_flush_p
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+-#ifdef CONFIG_BCM47XX
|
|
+-#include <asm/mach-bcm47xx/nvram.h>
|
|
+ /* Get the device MAC address */
|
|
+-static inline void ssb_gige_get_macaddr(struct pci_dev *pdev, u8 *macaddr)
|
|
+-{
|
|
+- char buf[20];
|
|
+- if (nvram_getenv("et0macaddr", buf, sizeof(buf)) < 0)
|
|
+- return;
|
|
+- nvram_parse_macaddr(buf, macaddr);
|
|
+-}
|
|
+-#else
|
|
+-static inline void ssb_gige_get_macaddr(struct pci_dev *pdev, u8 *macaddr)
|
|
++static inline int ssb_gige_get_macaddr(struct pci_dev *pdev, u8 *macaddr)
|
|
+ {
|
|
++ struct ssb_gige *dev = pdev_to_ssb_gige(pdev);
|
|
++ if (!dev)
|
|
++ return -ENODEV;
|
|
++
|
|
++ memcpy(macaddr, dev->dev->bus->sprom.et0mac, 6);
|
|
++ return 0;
|
|
+ }
|
|
+-#endif
|
|
+
|
|
+ extern int ssb_gige_pcibios_plat_dev_init(struct ssb_device *sdev,
|
|
+ struct pci_dev *pdev);
|
|
+@@ -174,6 +170,10 @@ static inline bool ssb_gige_must_flush_p
|
|
+ {
|
|
+ return 0;
|
|
+ }
|
|
++static inline int ssb_gige_get_macaddr(struct pci_dev *pdev, u8 *macaddr)
|
|
++{
|
|
++ return -ENODEV;
|
|
++}
|
|
+
|
|
+ #endif /* CONFIG_SSB_DRIVER_GIGE */
|
|
+ #endif /* LINUX_SSB_DRIVER_GIGE_H_ */
|
|
+--- a/include/linux/ssb/ssb_driver_mips.h
|
|
++++ b/include/linux/ssb/ssb_driver_mips.h
|
|
+@@ -41,6 +41,11 @@ void ssb_mipscore_init(struct ssb_mipsco
|
|
+ {
|
|
+ }
|
|
+
|
|
++static inline unsigned int ssb_mips_irq(struct ssb_device *dev)
|
|
++{
|
|
++ return 0;
|
|
++}
|
|
++
|
|
+ #endif /* CONFIG_SSB_DRIVER_MIPS */
|
|
+
|
|
+ #endif /* LINUX_SSB_MIPSCORE_H_ */
|
|
--- a/include/linux/ssb/ssb_regs.h
|
|
+++ b/include/linux/ssb/ssb_regs.h
|
|
-@@ -228,6 +228,7 @@
|
|
+@@ -172,6 +172,7 @@
|
|
+ #define SSB_SPROMSIZE_WORDS_R4 220
|
|
+ #define SSB_SPROMSIZE_BYTES_R123 (SSB_SPROMSIZE_WORDS_R123 * sizeof(u16))
|
|
+ #define SSB_SPROMSIZE_BYTES_R4 (SSB_SPROMSIZE_WORDS_R4 * sizeof(u16))
|
|
++#define SSB_SPROMSIZE_WORDS_R10 230
|
|
+ #define SSB_SPROM_BASE1 0x1000
|
|
+ #define SSB_SPROM_BASE31 0x0800
|
|
+ #define SSB_SPROM_REVISION 0x007E
|
|
+@@ -228,6 +229,7 @@
|
|
#define SSB_SPROM1_AGAIN_BG_SHIFT 0
|
|
#define SSB_SPROM1_AGAIN_A 0xFF00 /* A-PHY */
|
|
#define SSB_SPROM1_AGAIN_A_SHIFT 8
|
|
@@ -693,7 +2648,7 @@
|
|
|
|
/* SPROM Revision 2 (inherits from rev 1) */
|
|
#define SSB_SPROM2_BFLHI 0x0038 /* Boardflags (high 16 bits) */
|
|
-@@ -267,6 +268,7 @@
|
|
+@@ -267,6 +269,7 @@
|
|
#define SSB_SPROM3_OFDMGPO 0x107A /* G-PHY OFDM Power Offset (4 bytes, BigEndian) */
|
|
|
|
/* SPROM Revision 4 */
|
|
@@ -701,7 +2656,24 @@
|
|
#define SSB_SPROM4_BFLLO 0x0044 /* Boardflags (low 16 bits) */
|
|
#define SSB_SPROM4_BFLHI 0x0046 /* Board Flags Hi */
|
|
#define SSB_SPROM4_BFL2LO 0x0048 /* Board flags 2 (low 16 bits) */
|
|
-@@ -389,6 +391,11 @@
|
|
+@@ -287,11 +290,11 @@
|
|
+ #define SSB_SPROM4_ETHPHY_ET1A_SHIFT 5
|
|
+ #define SSB_SPROM4_ETHPHY_ET0M (1<<14) /* MDIO for enet0 */
|
|
+ #define SSB_SPROM4_ETHPHY_ET1M (1<<15) /* MDIO for enet1 */
|
|
+-#define SSB_SPROM4_ANTAVAIL 0x005D /* Antenna available bitfields */
|
|
+-#define SSB_SPROM4_ANTAVAIL_A 0x00FF /* A-PHY bitfield */
|
|
+-#define SSB_SPROM4_ANTAVAIL_A_SHIFT 0
|
|
+-#define SSB_SPROM4_ANTAVAIL_BG 0xFF00 /* B-PHY and G-PHY bitfield */
|
|
+-#define SSB_SPROM4_ANTAVAIL_BG_SHIFT 8
|
|
++#define SSB_SPROM4_ANTAVAIL 0x005C /* Antenna available bitfields */
|
|
++#define SSB_SPROM4_ANTAVAIL_BG 0x00FF /* B-PHY and G-PHY bitfield */
|
|
++#define SSB_SPROM4_ANTAVAIL_BG_SHIFT 0
|
|
++#define SSB_SPROM4_ANTAVAIL_A 0xFF00 /* A-PHY bitfield */
|
|
++#define SSB_SPROM4_ANTAVAIL_A_SHIFT 8
|
|
+ #define SSB_SPROM4_AGAIN01 0x005E /* Antenna Gain (in dBm Q5.2) */
|
|
+ #define SSB_SPROM4_AGAIN0 0x00FF /* Antenna 0 */
|
|
+ #define SSB_SPROM4_AGAIN0_SHIFT 0
|
|
+@@ -389,6 +392,11 @@
|
|
#define SSB_SPROM8_GPIOB_P2 0x00FF /* Pin 2 */
|
|
#define SSB_SPROM8_GPIOB_P3 0xFF00 /* Pin 3 */
|
|
#define SSB_SPROM8_GPIOB_P3_SHIFT 8
|
|
@@ -713,7 +2685,7 @@
|
|
#define SSB_SPROM8_ANTAVAIL 0x009C /* Antenna available bitfields*/
|
|
#define SSB_SPROM8_ANTAVAIL_A 0xFF00 /* A-PHY bitfield */
|
|
#define SSB_SPROM8_ANTAVAIL_A_SHIFT 8
|
|
-@@ -404,6 +411,13 @@
|
|
+@@ -404,6 +412,13 @@
|
|
#define SSB_SPROM8_AGAIN2_SHIFT 0
|
|
#define SSB_SPROM8_AGAIN3 0xFF00 /* Antenna 3 */
|
|
#define SSB_SPROM8_AGAIN3_SHIFT 8
|
|
@@ -727,7 +2699,7 @@
|
|
#define SSB_SPROM8_RSSIPARM2G 0x00A4 /* RSSI params for 2GHz */
|
|
#define SSB_SPROM8_RSSISMF2G 0x000F
|
|
#define SSB_SPROM8_RSSISMC2G 0x00F0
|
|
-@@ -430,6 +444,7 @@
|
|
+@@ -430,6 +445,7 @@
|
|
#define SSB_SPROM8_TRI5GH_SHIFT 8
|
|
#define SSB_SPROM8_RXPO 0x00AC /* RX power offsets */
|
|
#define SSB_SPROM8_RXPO2G 0x00FF /* 2GHz RX power offset */
|
|
@@ -735,7 +2707,7 @@
|
|
#define SSB_SPROM8_RXPO5G 0xFF00 /* 5GHz RX power offset */
|
|
#define SSB_SPROM8_RXPO5G_SHIFT 8
|
|
#define SSB_SPROM8_FEM2G 0x00AE
|
|
-@@ -445,10 +460,71 @@
|
|
+@@ -445,10 +461,71 @@
|
|
#define SSB_SROM8_FEM_ANTSWLUT 0xF800
|
|
#define SSB_SROM8_FEM_ANTSWLUT_SHIFT 11
|
|
#define SSB_SPROM8_THERMAL 0x00B2
|
|
@@ -768,7 +2740,7 @@
|
|
+#define SSB_SPROM8_HWIQ_IQSWP_IQCAL_SWP_SHIFT 4
|
|
+#define SSB_SPROM8_HWIQ_IQSWP_HW_IQCAL 0x0020
|
|
+#define SSB_SPROM8_HWIQ_IQSWP_HW_IQCAL_SHIFT 5
|
|
-+#define SSB_SPROM8_TEMPDELTA 0x00BA
|
|
++#define SSB_SPROM8_TEMPDELTA 0x00BC
|
|
+#define SSB_SPROM8_TEMPDELTA_PHYCAL 0x00ff
|
|
+#define SSB_SPROM8_TEMPDELTA_PHYCAL_SHIFT 0
|
|
+#define SSB_SPROM8_TEMPDELTA_PERIOD 0x0f00
|
|
@@ -811,7 +2783,7 @@
|
|
#define SSB_SPROM8_MAXP_BG 0x00C0 /* Max Power 2GHz in path 1 */
|
|
#define SSB_SPROM8_MAXP_BG_MASK 0x00FF /* Mask for Max Power 2GHz */
|
|
#define SSB_SPROM8_ITSSI_BG 0xFF00 /* Mask for path 1 itssi_bg */
|
|
-@@ -473,12 +549,23 @@
|
|
+@@ -473,12 +550,23 @@
|
|
#define SSB_SPROM8_PA1HIB0 0x00D8 /* 5.8GHz power amp settings */
|
|
#define SSB_SPROM8_PA1HIB1 0x00DA
|
|
#define SSB_SPROM8_PA1HIB2 0x00DC
|
|
@@ -835,3 +2807,37 @@
|
|
/* Values for boardflags_lo read from SPROM */
|
|
#define SSB_BFL_BTCOEXIST 0x0001 /* implements Bluetooth coexistance */
|
|
#define SSB_BFL_PACTRL 0x0002 /* GPIO 9 controlling the PA */
|
|
+--- /dev/null
|
|
++++ b/include/linux/bcm47xx_wdt.h
|
|
+@@ -0,0 +1,19 @@
|
|
++#ifndef LINUX_BCM47XX_WDT_H_
|
|
++#define LINUX_BCM47XX_WDT_H_
|
|
++
|
|
++#include <linux/types.h>
|
|
++
|
|
++
|
|
++struct bcm47xx_wdt {
|
|
++ u32 (*timer_set)(struct bcm47xx_wdt *, u32);
|
|
++ u32 (*timer_set_ms)(struct bcm47xx_wdt *, u32);
|
|
++ u32 max_timer_ms;
|
|
++
|
|
++ void *driver_data;
|
|
++};
|
|
++
|
|
++static inline void *bcm47xx_wdt_get_drvdata(struct bcm47xx_wdt *wdt)
|
|
++{
|
|
++ return wdt->driver_data;
|
|
++}
|
|
++#endif /* LINUX_BCM47XX_WDT_H_ */
|
|
+--- a/drivers/net/wireless/b43/phy_n.c
|
|
++++ b/drivers/net/wireless/b43/phy_n.c
|
|
+@@ -4259,7 +4259,8 @@ static void b43_nphy_pmu_spur_avoid(stru
|
|
+ #endif
|
|
+ #ifdef CONFIG_B43_SSB
|
|
+ case B43_BUS_SSB:
|
|
+- /* FIXME */
|
|
++ ssb_pmu_spuravoid_pllupdate(&dev->dev->sdev->bus->chipco,
|
|
++ avoid);
|
|
+ break;
|
|
+ #endif
|
|
+ }
|
|
Index: patches-3.3/080-prot-release-cb.patch
|
|
===================================================================
|
|
--- patches-3.3/080-prot-release-cb.patch (Revision 35298)
|
|
+++ patches-3.3/080-prot-release-cb.patch (Revision 37768)
|
|
@@ -3,8 +3,8 @@
|
|
|
|
--- a/include/net/sock.h
|
|
+++ b/include/net/sock.h
|
|
-@@ -858,6 +858,8 @@ struct proto {
|
|
- int (*backlog_rcv) (struct sock *sk,
|
|
+@@ -810,6 +810,8 @@ struct proto {
|
|
+ int (*backlog_rcv) (struct sock *sk,
|
|
struct sk_buff *skb);
|
|
|
|
+ void (*release_cb)(struct sock *sk);
|
|
@@ -14,7 +14,7 @@
|
|
void (*unhash)(struct sock *sk);
|
|
--- a/net/core/sock.c
|
|
+++ b/net/core/sock.c
|
|
-@@ -2159,6 +2159,10 @@ void release_sock(struct sock *sk)
|
|
+@@ -2138,6 +2138,10 @@ void release_sock(struct sock *sk)
|
|
spin_lock_bh(&sk->sk_lock.slock);
|
|
if (sk->sk_backlog.tail)
|
|
__release_sock(sk);
|
|
Index: patches-3.3/668-ipv6-fix-handling-of-throw-routes.patch
|
|
===================================================================
|
|
--- patches-3.3/668-ipv6-fix-handling-of-throw-routes.patch (Revision 0)
|
|
+++ patches-3.3/668-ipv6-fix-handling-of-throw-routes.patch (Revision 37768)
|
|
@@ -0,0 +1,32 @@
|
|
+--- a/net/ipv6/route.c
|
|
++++ b/net/ipv6/route.c
|
|
+@@ -1341,6 +1341,9 @@ int ip6_route_add(struct fib6_config *cf
|
|
+ case RTN_PROHIBIT:
|
|
+ rt->dst.error = -EACCES;
|
|
+ break;
|
|
++ case RTN_THROW:
|
|
++ rt->dst.error = -EAGAIN;
|
|
++ break;
|
|
+ default:
|
|
+ rt->dst.error = -ENETUNREACH;
|
|
+ break;
|
|
+@@ -2279,7 +2282,8 @@ static int rtm_to_fib6_config(struct sk_
|
|
+
|
|
+ if (rtm->rtm_type == RTN_UNREACHABLE ||
|
|
+ rtm->rtm_type == RTN_BLACKHOLE ||
|
|
+- rtm->rtm_type == RTN_PROHIBIT)
|
|
++ rtm->rtm_type == RTN_PROHIBIT ||
|
|
++ rtm->rtm_type == RTN_THROW)
|
|
+ cfg->fc_flags |= RTF_REJECT;
|
|
+
|
|
+ if (rtm->rtm_type == RTN_LOCAL)
|
|
+@@ -2417,6 +2421,9 @@ static int rt6_fill_node(struct net *net
|
|
+ case -EACCES:
|
|
+ rtm->rtm_type = RTN_PROHIBIT;
|
|
+ break;
|
|
++ case -EAGAIN:
|
|
++ rtm->rtm_type = RTN_THROW;
|
|
++ break;
|
|
+ default:
|
|
+ rtm->rtm_type = RTN_UNREACHABLE;
|
|
+ break;
|
|
Index: patches-3.3/670-ipv6-allow-rejecting-with-source-address-failed-policy.patch
|
|
===================================================================
|
|
--- patches-3.3/670-ipv6-allow-rejecting-with-source-address-failed-policy.patch (Revision 0)
|
|
+++ patches-3.3/670-ipv6-allow-rejecting-with-source-address-failed-policy.patch (Revision 37768)
|
|
@@ -0,0 +1,241 @@
|
|
+--- a/include/net/netns/ipv6.h
|
|
++++ b/include/net/netns/ipv6.h
|
|
+@@ -50,6 +50,7 @@ struct netns_ipv6 {
|
|
+ unsigned long ip6_rt_last_gc;
|
|
+ #ifdef CONFIG_IPV6_MULTIPLE_TABLES
|
|
+ struct rt6_info *ip6_prohibit_entry;
|
|
++ struct rt6_info *ip6_failed_policy_entry;
|
|
+ struct rt6_info *ip6_blk_hole_entry;
|
|
+ struct fib6_table *fib6_local_tbl;
|
|
+ struct fib_rules_ops *fib6_rules_ops;
|
|
+--- a/include/linux/fib_rules.h
|
|
++++ b/include/linux/fib_rules.h
|
|
+@@ -64,6 +64,10 @@ enum {
|
|
+ FR_ACT_BLACKHOLE, /* Drop without notification */
|
|
+ FR_ACT_UNREACHABLE, /* Drop with ENETUNREACH */
|
|
+ FR_ACT_PROHIBIT, /* Drop with EACCES */
|
|
++ FR_ACT_RES9,
|
|
++ FR_ACT_RES10,
|
|
++ FR_ACT_RES11,
|
|
++ FR_ACT_FAILED_POLICY, /* Drop with EPERM */
|
|
+ __FR_ACT_MAX,
|
|
+ };
|
|
+
|
|
+--- a/include/linux/icmpv6.h
|
|
++++ b/include/linux/icmpv6.h
|
|
+@@ -123,6 +123,7 @@ static inline struct icmp6hdr *icmp6_hdr
|
|
+ #define ICMPV6_NOT_NEIGHBOUR 2
|
|
+ #define ICMPV6_ADDR_UNREACH 3
|
|
+ #define ICMPV6_PORT_UNREACH 4
|
|
++#define ICMPV6_FAILED_POLICY 5
|
|
+
|
|
+ /*
|
|
+ * Codes for Time Exceeded
|
|
+--- a/include/linux/rtnetlink.h
|
|
++++ b/include/linux/rtnetlink.h
|
|
+@@ -191,6 +191,7 @@ enum {
|
|
+ RTN_THROW, /* Not in this table */
|
|
+ RTN_NAT, /* Translate this address */
|
|
+ RTN_XRESOLVE, /* Use external resolver */
|
|
++ RTN_FAILED_POLICY, /* Failed ingress/egress policy */
|
|
+ __RTN_MAX
|
|
+ };
|
|
+
|
|
+--- a/net/ipv4/fib_rules.c
|
|
++++ b/net/ipv4/fib_rules.c
|
|
+@@ -87,6 +87,10 @@ static int fib4_rule_action(struct fib_r
|
|
+ err = -EACCES;
|
|
+ goto errout;
|
|
+
|
|
++ case FR_ACT_FAILED_POLICY:
|
|
++ err = -EPERM;
|
|
++ goto errout;
|
|
++
|
|
+ case FR_ACT_BLACKHOLE:
|
|
+ default:
|
|
+ err = -EINVAL;
|
|
+--- a/net/ipv4/fib_semantics.c
|
|
++++ b/net/ipv4/fib_semantics.c
|
|
+@@ -139,6 +139,10 @@ const struct fib_prop fib_props[RTN_MAX
|
|
+ .error = -EINVAL,
|
|
+ .scope = RT_SCOPE_NOWHERE,
|
|
+ },
|
|
++ [RTN_FAILED_POLICY] = {
|
|
++ .error = -EPERM,
|
|
++ .scope = RT_SCOPE_UNIVERSE,
|
|
++ },
|
|
+ };
|
|
+
|
|
+ /* Release a nexthop info record */
|
|
+--- a/net/ipv4/fib_trie.c
|
|
++++ b/net/ipv4/fib_trie.c
|
|
+@@ -2349,6 +2349,7 @@ static const char *const rtn_type_names[
|
|
+ [RTN_THROW] = "THROW",
|
|
+ [RTN_NAT] = "NAT",
|
|
+ [RTN_XRESOLVE] = "XRESOLVE",
|
|
++ [RTN_FAILED_POLICY] = "FAILED_POLICY",
|
|
+ };
|
|
+
|
|
+ static inline const char *rtn_type(char *buf, size_t len, unsigned int t)
|
|
+--- a/net/ipv4/ipmr.c
|
|
++++ b/net/ipv4/ipmr.c
|
|
+@@ -176,6 +176,7 @@ static int ipmr_rule_action(struct fib_r
|
|
+ case FR_ACT_UNREACHABLE:
|
|
+ return -ENETUNREACH;
|
|
+ case FR_ACT_PROHIBIT:
|
|
++ case FR_ACT_FAILED_POLICY:
|
|
+ return -EACCES;
|
|
+ case FR_ACT_BLACKHOLE:
|
|
+ default:
|
|
+--- a/net/ipv6/fib6_rules.c
|
|
++++ b/net/ipv6/fib6_rules.c
|
|
+@@ -70,6 +70,9 @@ static int fib6_rule_action(struct fib_r
|
|
+ case FR_ACT_PROHIBIT:
|
|
+ rt = net->ipv6.ip6_prohibit_entry;
|
|
+ goto discard_pkt;
|
|
++ case FR_ACT_FAILED_POLICY:
|
|
++ rt = net->ipv6.ip6_failed_policy_entry;
|
|
++ goto discard_pkt;
|
|
+ }
|
|
+
|
|
+ table = fib6_get_table(net, rule->table);
|
|
+--- a/net/ipv6/ip6mr.c
|
|
++++ b/net/ipv6/ip6mr.c
|
|
+@@ -164,6 +164,8 @@ static int ip6mr_rule_action(struct fib_
|
|
+ return -ENETUNREACH;
|
|
+ case FR_ACT_PROHIBIT:
|
|
+ return -EACCES;
|
|
++ case FR_ACT_FAILED_POLICY:
|
|
++ return -EPERM;
|
|
+ case FR_ACT_BLACKHOLE:
|
|
+ default:
|
|
+ return -EINVAL;
|
|
+--- a/net/ipv6/route.c
|
|
++++ b/net/ipv6/route.c
|
|
+@@ -228,6 +228,24 @@ static struct rt6_info ip6_prohibit_entr
|
|
+ .rt6i_ref = ATOMIC_INIT(1),
|
|
+ };
|
|
+
|
|
++static int ip6_pkt_failed_policy(struct sk_buff *skb);
|
|
++static int ip6_pkt_failed_policy_out(struct sk_buff *skb);
|
|
++
|
|
++static const struct rt6_info ip6_failed_policy_entry_template = {
|
|
++ .dst = {
|
|
++ .__refcnt = ATOMIC_INIT(1),
|
|
++ .__use = 1,
|
|
++ .obsolete = -1,
|
|
++ .error = -EPERM,
|
|
++ .input = ip6_pkt_failed_policy,
|
|
++ .output = ip6_pkt_failed_policy_out,
|
|
++ },
|
|
++ .rt6i_flags = (RTF_REJECT | RTF_NONEXTHOP),
|
|
++ .rt6i_protocol = RTPROT_KERNEL,
|
|
++ .rt6i_metric = ~(u32) 0,
|
|
++ .rt6i_ref = ATOMIC_INIT(1),
|
|
++};
|
|
++
|
|
+ static struct rt6_info ip6_blk_hole_entry_template = {
|
|
+ .dst = {
|
|
+ .__refcnt = ATOMIC_INIT(1),
|
|
+@@ -1344,6 +1362,9 @@ int ip6_route_add(struct fib6_config *cf
|
|
+ case RTN_THROW:
|
|
+ rt->dst.error = -EAGAIN;
|
|
+ break;
|
|
++ case RTN_FAILED_POLICY:
|
|
++ rt->dst.error = -EPERM;
|
|
++ break;
|
|
+ default:
|
|
+ rt->dst.error = -ENETUNREACH;
|
|
+ break;
|
|
+@@ -2068,6 +2089,17 @@ static int ip6_pkt_prohibit_out(struct s
|
|
+ return ip6_pkt_drop(skb, ICMPV6_ADM_PROHIBITED, IPSTATS_MIB_OUTNOROUTES);
|
|
+ }
|
|
+
|
|
++static int ip6_pkt_failed_policy(struct sk_buff *skb)
|
|
++{
|
|
++ return ip6_pkt_drop(skb, ICMPV6_FAILED_POLICY, IPSTATS_MIB_INNOROUTES);
|
|
++}
|
|
++
|
|
++static int ip6_pkt_failed_policy_out(struct sk_buff *skb)
|
|
++{
|
|
++ skb->dev = skb_dst(skb)->dev;
|
|
++ return ip6_pkt_drop(skb, ICMPV6_FAILED_POLICY, IPSTATS_MIB_OUTNOROUTES);
|
|
++}
|
|
++
|
|
+ #endif
|
|
+
|
|
+ /*
|
|
+@@ -2283,7 +2315,8 @@ static int rtm_to_fib6_config(struct sk_
|
|
+ if (rtm->rtm_type == RTN_UNREACHABLE ||
|
|
+ rtm->rtm_type == RTN_BLACKHOLE ||
|
|
+ rtm->rtm_type == RTN_PROHIBIT ||
|
|
+- rtm->rtm_type == RTN_THROW)
|
|
++ rtm->rtm_type == RTN_THROW ||
|
|
++ rtm->rtm_type == RTN_FAILED_POLICY)
|
|
+ cfg->fc_flags |= RTF_REJECT;
|
|
+
|
|
+ if (rtm->rtm_type == RTN_LOCAL)
|
|
+@@ -2421,6 +2454,9 @@ static int rt6_fill_node(struct net *net
|
|
+ case -EACCES:
|
|
+ rtm->rtm_type = RTN_PROHIBIT;
|
|
+ break;
|
|
++ case -EPERM:
|
|
++ rtm->rtm_type = RTN_FAILED_POLICY;
|
|
++ break;
|
|
+ case -EAGAIN:
|
|
+ rtm->rtm_type = RTN_THROW;
|
|
+ break;
|
|
+@@ -2665,6 +2701,8 @@ static int ip6_route_dev_notify(struct n
|
|
+ #ifdef CONFIG_IPV6_MULTIPLE_TABLES
|
|
+ net->ipv6.ip6_prohibit_entry->dst.dev = dev;
|
|
+ net->ipv6.ip6_prohibit_entry->rt6i_idev = in6_dev_get(dev);
|
|
++ net->ipv6.ip6_failed_policy_entry->dst.dev = dev;
|
|
++ net->ipv6.ip6_failed_policy_entry->rt6i_idev = in6_dev_get(dev);
|
|
+ net->ipv6.ip6_blk_hole_entry->dst.dev = dev;
|
|
+ net->ipv6.ip6_blk_hole_entry->rt6i_idev = in6_dev_get(dev);
|
|
+ #endif
|
|
+@@ -2925,6 +2963,17 @@ static int __net_init ip6_route_net_init
|
|
+ net->ipv6.ip6_blk_hole_entry->dst.ops = &net->ipv6.ip6_dst_ops;
|
|
+ dst_init_metrics(&net->ipv6.ip6_blk_hole_entry->dst,
|
|
+ ip6_template_metrics, true);
|
|
++
|
|
++ net->ipv6.ip6_failed_policy_entry =
|
|
++ kmemdup(&ip6_failed_policy_entry_template,
|
|
++ sizeof(*net->ipv6.ip6_failed_policy_entry), GFP_KERNEL);
|
|
++ if (!net->ipv6.ip6_failed_policy_entry)
|
|
++ goto out_ip6_blk_hole_entry;
|
|
++ net->ipv6.ip6_failed_policy_entry->dst.path =
|
|
++ (struct dst_entry *)net->ipv6.ip6_failed_policy_entry;
|
|
++ net->ipv6.ip6_failed_policy_entry->dst.ops = &net->ipv6.ip6_dst_ops;
|
|
++ dst_init_metrics(&net->ipv6.ip6_failed_policy_entry->dst,
|
|
++ ip6_template_metrics, true);
|
|
+ #endif
|
|
+
|
|
+ net->ipv6.sysctl.flush_delay = 0;
|
|
+@@ -2947,6 +2996,8 @@ out:
|
|
+ return ret;
|
|
+
|
|
+ #ifdef CONFIG_IPV6_MULTIPLE_TABLES
|
|
++out_ip6_blk_hole_entry:
|
|
++ kfree(net->ipv6.ip6_blk_hole_entry);
|
|
+ out_ip6_prohibit_entry:
|
|
+ kfree(net->ipv6.ip6_prohibit_entry);
|
|
+ out_ip6_null_entry:
|
|
+@@ -2968,6 +3019,7 @@ static void __net_exit ip6_route_net_exi
|
|
+ #ifdef CONFIG_IPV6_MULTIPLE_TABLES
|
|
+ kfree(net->ipv6.ip6_prohibit_entry);
|
|
+ kfree(net->ipv6.ip6_blk_hole_entry);
|
|
++ kfree(net->ipv6.ip6_failed_policy_entry);
|
|
+ #endif
|
|
+ dst_entries_destroy(&net->ipv6.ip6_dst_ops);
|
|
+ }
|
|
+@@ -3013,6 +3065,9 @@ int __init ip6_route_init(void)
|
|
+ init_net.ipv6.ip6_prohibit_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev);
|
|
+ init_net.ipv6.ip6_blk_hole_entry->dst.dev = init_net.loopback_dev;
|
|
+ init_net.ipv6.ip6_blk_hole_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev);
|
|
++ init_net.ipv6.ip6_failed_policy_entry->dst.dev = init_net.loopback_dev;
|
|
++ init_net.ipv6.ip6_failed_policy_entry->rt6i_idev =
|
|
++ in6_dev_get(init_net.loopback_dev);
|
|
+ #endif
|
|
+ ret = fib6_init();
|
|
+ if (ret)
|
|
Index: patches-3.3/665-ipv6-fix-handling-of-blackhole-and-prohibit-routes.patch
|
|
===================================================================
|
|
--- patches-3.3/665-ipv6-fix-handling-of-blackhole-and-prohibit-routes.patch (Revision 0)
|
|
+++ patches-3.3/665-ipv6-fix-handling-of-blackhole-and-prohibit-routes.patch (Revision 37768)
|
|
@@ -0,0 +1,67 @@
|
|
+--- a/include/net/ip6_fib.h
|
|
++++ b/include/net/ip6_fib.h
|
|
+@@ -37,6 +37,7 @@ struct fib6_config {
|
|
+ int fc_ifindex;
|
|
+ u32 fc_flags;
|
|
+ u32 fc_protocol;
|
|
++ u32 fc_type; /* only 8 bits are used */
|
|
+
|
|
+ struct in6_addr fc_dst;
|
|
+ struct in6_addr fc_src;
|
|
+--- a/net/ipv6/route.c
|
|
++++ b/net/ipv6/route.c
|
|
+@@ -1333,8 +1333,18 @@ int ip6_route_add(struct fib6_config *cf
|
|
+ }
|
|
+ rt->dst.output = ip6_pkt_discard_out;
|
|
+ rt->dst.input = ip6_pkt_discard;
|
|
+- rt->dst.error = -ENETUNREACH;
|
|
+ rt->rt6i_flags = RTF_REJECT|RTF_NONEXTHOP;
|
|
++ switch (cfg->fc_type) {
|
|
++ case RTN_BLACKHOLE:
|
|
++ rt->dst.error = -EINVAL;
|
|
++ break;
|
|
++ case RTN_PROHIBIT:
|
|
++ rt->dst.error = -EACCES;
|
|
++ break;
|
|
++ default:
|
|
++ rt->dst.error = -ENETUNREACH;
|
|
++ break;
|
|
++ }
|
|
+ goto install_route;
|
|
+ }
|
|
+
|
|
+@@ -2265,8 +2275,11 @@ static int rtm_to_fib6_config(struct sk_
|
|
+ cfg->fc_src_len = rtm->rtm_src_len;
|
|
+ cfg->fc_flags = RTF_UP;
|
|
+ cfg->fc_protocol = rtm->rtm_protocol;
|
|
++ cfg->fc_type = rtm->rtm_type;
|
|
+
|
|
+- if (rtm->rtm_type == RTN_UNREACHABLE)
|
|
++ if (rtm->rtm_type == RTN_UNREACHABLE ||
|
|
++ rtm->rtm_type == RTN_BLACKHOLE ||
|
|
++ rtm->rtm_type == RTN_PROHIBIT)
|
|
+ cfg->fc_flags |= RTF_REJECT;
|
|
+
|
|
+ if (rtm->rtm_type == RTN_LOCAL)
|
|
+@@ -2396,8 +2409,19 @@ static int rt6_fill_node(struct net *net
|
|
+ table = RT6_TABLE_UNSPEC;
|
|
+ rtm->rtm_table = table;
|
|
+ NLA_PUT_U32(skb, RTA_TABLE, table);
|
|
+- if (rt->rt6i_flags & RTF_REJECT)
|
|
+- rtm->rtm_type = RTN_UNREACHABLE;
|
|
++ if (rt->rt6i_flags & RTF_REJECT) {
|
|
++ switch (rt->dst.error) {
|
|
++ case -EINVAL:
|
|
++ rtm->rtm_type = RTN_BLACKHOLE;
|
|
++ break;
|
|
++ case -EACCES:
|
|
++ rtm->rtm_type = RTN_PROHIBIT;
|
|
++ break;
|
|
++ default:
|
|
++ rtm->rtm_type = RTN_UNREACHABLE;
|
|
++ break;
|
|
++ }
|
|
++ }
|
|
+ else if (rt->rt6i_flags & RTF_LOCAL)
|
|
+ rtm->rtm_type = RTN_LOCAL;
|
|
+ else if (rt->dst.dev && (rt->dst.dev->flags & IFF_LOOPBACK))
|
|
Index: patches-3.3/721-phy_packets.patch
|
|
===================================================================
|
|
--- patches-3.3/721-phy_packets.patch (Revision 35298)
|
|
+++ patches-3.3/721-phy_packets.patch (Revision 37768)
|
|
@@ -145,7 +145,7 @@
|
|
+ struct sk_buff *skb = __netdev_alloc_skb(dev, length + NET_IP_ALIGN, gfp);
|
|
+
|
|
+#ifdef CONFIG_ETHERNET_PACKET_MANGLE
|
|
-+ if (dev->priv_flags & IFF_NO_IP_ALIGN)
|
|
++ if (dev && (dev->priv_flags & IFF_NO_IP_ALIGN))
|
|
+ return skb;
|
|
+#endif
|
|
+
|
|
Index: patches-3.3/729-phy-tantos.patch
|
|
===================================================================
|
|
--- patches-3.3/729-phy-tantos.patch (Revision 35298)
|
|
+++ patches-3.3/729-phy-tantos.patch (Revision 37768)
|
|
@@ -1,6 +1,6 @@
|
|
--- a/drivers/net/phy/Kconfig
|
|
+++ b/drivers/net/phy/Kconfig
|
|
-@@ -206,3 +206,8 @@ endif # PHYLIB
|
|
+@@ -210,3 +210,8 @@ endif # PHYLIB
|
|
config MICREL_KS8995MA
|
|
tristate "Micrel KS8995MA 5-ports 10/100 managed Ethernet switch"
|
|
depends on SPI
|
|
@@ -11,8 +11,8 @@
|
|
+ select ETHERNET_PACKET_MANGLE
|
|
--- a/drivers/net/phy/Makefile
|
|
+++ b/drivers/net/phy/Makefile
|
|
-@@ -28,6 +28,7 @@ obj-$(CONFIG_RTL8366RB_PHY) += rtl8366rb
|
|
- obj-$(CONFIG_RTL8367_PHY) += rtl8367.o
|
|
+@@ -29,6 +29,7 @@ obj-$(CONFIG_RTL8367_PHY) += rtl8367.o
|
|
+ obj-$(CONFIG_RTL8367B_PHY) += rtl8367b.o
|
|
obj-$(CONFIG_LSI_ET1011C_PHY) += et1011c.o
|
|
obj-$(CONFIG_MICREL_PHY) += micrel.o
|
|
+obj-$(CONFIG_PSB6970_PHY) += psb6970.o
|
|
Index: patches-3.3/090-CVE-2013-1763.patch
|
|
===================================================================
|
|
--- patches-3.3/090-CVE-2013-1763.patch (Revision 0)
|
|
+++ patches-3.3/090-CVE-2013-1763.patch (Revision 37768)
|
|
@@ -0,0 +1,27 @@
|
|
+From 6e601a53566d84e1ffd25e7b6fe0b6894ffd79c0 Mon Sep 17 00:00:00 2001
|
|
+From: Mathias Krause <minipli@googlemail.com>
|
|
+Date: Sat, 23 Feb 2013 01:13:47 +0000
|
|
+Subject: sock_diag: Fix out-of-bounds access to sock_diag_handlers[]
|
|
+
|
|
+Userland can send a netlink message requesting SOCK_DIAG_BY_FAMILY
|
|
+with a family greater or equal then AF_MAX -- the array size of
|
|
+sock_diag_handlers[]. The current code does not test for this
|
|
+condition therefore is vulnerable to an out-of-bound access opening
|
|
+doors for a privilege escalation.
|
|
+
|
|
+Signed-off-by: Mathias Krause <minipli@googlemail.com>
|
|
+Acked-by: Eric Dumazet <edumazet@google.com>
|
|
+Signed-off-by: David S. Miller <davem@davemloft.net>
|
|
+---
|
|
+--- a/net/core/sock_diag.c
|
|
++++ b/net/core/sock_diag.c
|
|
+@@ -126,6 +126,9 @@ static int __sock_diag_rcv_msg(struct sk
|
|
+ if (nlmsg_len(nlh) < sizeof(*req))
|
|
+ return -EINVAL;
|
|
+
|
|
++ if (req->sdiag_family >= AF_MAX)
|
|
++ return -EINVAL;
|
|
++
|
|
+ hndl = sock_diag_lock_handler(req->sdiag_family);
|
|
+ if (hndl == NULL)
|
|
+ err = -ENOENT;
|
|
Index: patches-3.3/605-netfilter_conntrack_flush.patch
|
|
===================================================================
|
|
--- patches-3.3/605-netfilter_conntrack_flush.patch (Revision 0)
|
|
+++ patches-3.3/605-netfilter_conntrack_flush.patch (Revision 37768)
|
|
@@ -0,0 +1,46 @@
|
|
+--- a/net/netfilter/nf_conntrack_standalone.c
|
|
++++ b/net/netfilter/nf_conntrack_standalone.c
|
|
+@@ -267,10 +267,34 @@ static int ct_open(struct inode *inode,
|
|
+ sizeof(struct ct_iter_state));
|
|
+ }
|
|
+
|
|
++static int kill_all(struct nf_conn *i, void *data)
|
|
++{
|
|
++ return 1;
|
|
++}
|
|
++
|
|
++static ssize_t ct_file_write(struct file *file, const char __user *buf,
|
|
++ size_t count, loff_t *ppos)
|
|
++{
|
|
++ struct seq_file *seq = file->private_data;
|
|
++ struct net *net = seq_file_net(seq);
|
|
++
|
|
++ if (count) {
|
|
++ char c;
|
|
++
|
|
++ if (get_user(c, buf))
|
|
++ return -EFAULT;
|
|
++
|
|
++ if (c == 'f')
|
|
++ nf_ct_iterate_cleanup(net, kill_all, NULL);
|
|
++ }
|
|
++ return count;
|
|
++}
|
|
++
|
|
+ static const struct file_operations ct_file_ops = {
|
|
+ .owner = THIS_MODULE,
|
|
+ .open = ct_open,
|
|
+ .read = seq_read,
|
|
++ .write = ct_file_write,
|
|
+ .llseek = seq_lseek,
|
|
+ .release = seq_release_net,
|
|
+ };
|
|
+@@ -372,7 +396,7 @@ static int nf_conntrack_standalone_init_
|
|
+ {
|
|
+ struct proc_dir_entry *pde;
|
|
+
|
|
+- pde = proc_net_fops_create(net, "nf_conntrack", 0440, &ct_file_ops);
|
|
++ pde = proc_net_fops_create(net, "nf_conntrack", 0660, &ct_file_ops);
|
|
+ if (!pde)
|
|
+ goto out_nf_conntrack;
|
|
+
|
|
Index: patches-3.3/025-bcma_backport.patch
|
|
===================================================================
|
|
--- patches-3.3/025-bcma_backport.patch (Revision 35298)
|
|
+++ patches-3.3/025-bcma_backport.patch (Revision 37768)
|
|
@@ -1,6 +1,32 @@
|
|
+--- a/arch/mips/bcm47xx/serial.c
|
|
++++ b/arch/mips/bcm47xx/serial.c
|
|
+@@ -62,7 +62,7 @@ static int __init uart8250_init_bcma(voi
|
|
+
|
|
+ p->mapbase = (unsigned int) bcma_port->regs;
|
|
+ p->membase = (void *) bcma_port->regs;
|
|
+- p->irq = bcma_port->irq + 2;
|
|
++ p->irq = bcma_port->irq;
|
|
+ p->uartclk = bcma_port->baud_base;
|
|
+ p->regshift = bcma_port->reg_shift;
|
|
+ p->iotype = UPIO_MEM;
|
|
+--- a/arch/mips/bcm47xx/gpio.c
|
|
++++ b/arch/mips/bcm47xx/gpio.c
|
|
+@@ -94,7 +94,7 @@ int gpio_to_irq(unsigned gpio)
|
|
+ #endif
|
|
+ #ifdef CONFIG_BCM47XX_BCMA
|
|
+ case BCM47XX_BUS_TYPE_BCMA:
|
|
+- return bcma_core_mips_irq(bcm47xx_bus.bcma.bus.drv_cc.core) + 2;
|
|
++ return bcma_core_irq(bcm47xx_bus.bcma.bus.drv_cc.core);
|
|
+ #endif
|
|
+ }
|
|
+ return -EINVAL;
|
|
--- a/drivers/bcma/Kconfig
|
|
+++ b/drivers/bcma/Kconfig
|
|
-@@ -29,7 +29,7 @@ config BCMA_HOST_PCI
|
|
+@@ -26,10 +26,11 @@ config BCMA_HOST_PCI_POSSIBLE
|
|
+ config BCMA_HOST_PCI
|
|
+ bool "Support for BCMA on PCI-host bus"
|
|
+ depends on BCMA_HOST_PCI_POSSIBLE
|
|
++ default y
|
|
|
|
config BCMA_DRIVER_PCI_HOSTMODE
|
|
bool "Driver for PCI core working in hostmode"
|
|
@@ -9,7 +35,7 @@
|
|
help
|
|
PCI core hostmode operation (external PCI bus).
|
|
|
|
-@@ -46,6 +46,15 @@ config BCMA_DRIVER_MIPS
|
|
+@@ -46,6 +47,23 @@ config BCMA_DRIVER_MIPS
|
|
|
|
If unsure, say N
|
|
|
|
@@ -22,22 +48,31 @@
|
|
+
|
|
+ If unsure, say N
|
|
+
|
|
++config BCMA_DRIVER_GPIO
|
|
++ bool "BCMA GPIO driver"
|
|
++ depends on BCMA && GPIOLIB
|
|
++ help
|
|
++ Driver to provide access to the GPIO pins of the bcma bus.
|
|
++
|
|
++ If unsure, say N
|
|
++
|
|
config BCMA_DEBUG
|
|
bool "BCMA debugging"
|
|
depends on BCMA
|
|
--- a/drivers/bcma/Makefile
|
|
+++ b/drivers/bcma/Makefile
|
|
-@@ -3,6 +3,7 @@ bcma-y += driver_chipcommon.o driver
|
|
+@@ -3,6 +3,8 @@ bcma-y += driver_chipcommon.o driver
|
|
bcma-y += driver_pci.o
|
|
bcma-$(CONFIG_BCMA_DRIVER_PCI_HOSTMODE) += driver_pci_host.o
|
|
bcma-$(CONFIG_BCMA_DRIVER_MIPS) += driver_mips.o
|
|
+bcma-$(CONFIG_BCMA_DRIVER_GMAC_CMN) += driver_gmac_cmn.o
|
|
++bcma-$(CONFIG_BCMA_DRIVER_GPIO) += driver_gpio.o
|
|
bcma-$(CONFIG_BCMA_HOST_PCI) += host_pci.o
|
|
bcma-$(CONFIG_BCMA_HOST_SOC) += host_soc.o
|
|
obj-$(CONFIG_BCMA) += bcma.o
|
|
--- a/drivers/bcma/bcma_private.h
|
|
+++ b/drivers/bcma/bcma_private.h
|
|
-@@ -10,10 +10,19 @@
|
|
+@@ -10,10 +10,21 @@
|
|
|
|
#define BCMA_CORE_SIZE 0x1000
|
|
|
|
@@ -54,35 +89,128 @@
|
|
|
|
/* main.c */
|
|
-int bcma_bus_register(struct bcma_bus *bus);
|
|
++bool bcma_wait_value(struct bcma_device *core, u16 reg, u32 mask, u32 value,
|
|
++ int timeout);
|
|
+int __devinit bcma_bus_register(struct bcma_bus *bus);
|
|
void bcma_bus_unregister(struct bcma_bus *bus);
|
|
int __init bcma_bus_early_register(struct bcma_bus *bus,
|
|
struct bcma_device *core_cc,
|
|
-@@ -48,8 +57,12 @@ extern int __init bcma_host_pci_init(voi
|
|
+@@ -22,6 +33,8 @@ int __init bcma_bus_early_register(struc
|
|
+ int bcma_bus_suspend(struct bcma_bus *bus);
|
|
+ int bcma_bus_resume(struct bcma_bus *bus);
|
|
+ #endif
|
|
++struct bcma_device *bcma_find_core_unit(struct bcma_bus *bus, u16 coreid,
|
|
++ u8 unit);
|
|
+
|
|
+ /* scan.c */
|
|
+ int bcma_bus_scan(struct bcma_bus *bus);
|
|
+@@ -39,8 +52,8 @@ void bcma_chipco_serial_init(struct bcma
|
|
+ #endif /* CONFIG_BCMA_DRIVER_MIPS */
|
|
+
|
|
+ /* driver_chipcommon_pmu.c */
|
|
+-u32 bcma_pmu_alp_clock(struct bcma_drv_cc *cc);
|
|
+-u32 bcma_pmu_get_clockcpu(struct bcma_drv_cc *cc);
|
|
++u32 bcma_pmu_get_alp_clock(struct bcma_drv_cc *cc);
|
|
++u32 bcma_pmu_get_cpu_clock(struct bcma_drv_cc *cc);
|
|
+
|
|
+ #ifdef CONFIG_BCMA_HOST_PCI
|
|
+ /* host_pci.c */
|
|
+@@ -48,8 +61,29 @@ extern int __init bcma_host_pci_init(voi
|
|
extern void __exit bcma_host_pci_exit(void);
|
|
#endif /* CONFIG_BCMA_HOST_PCI */
|
|
|
|
+/* driver_pci.c */
|
|
+u32 bcma_pcie_read(struct bcma_drv_pci *pc, u32 address);
|
|
+
|
|
++extern int bcma_chipco_watchdog_register(struct bcma_drv_cc *cc);
|
|
++
|
|
#ifdef CONFIG_BCMA_DRIVER_PCI_HOSTMODE
|
|
-void bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc);
|
|
+bool __devinit bcma_core_pci_is_in_hostmode(struct bcma_drv_pci *pc);
|
|
+void __devinit bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc);
|
|
#endif /* CONFIG_BCMA_DRIVER_PCI_HOSTMODE */
|
|
|
|
++#ifdef CONFIG_BCMA_DRIVER_GPIO
|
|
++/* driver_gpio.c */
|
|
++int bcma_gpio_init(struct bcma_drv_cc *cc);
|
|
++int bcma_gpio_unregister(struct bcma_drv_cc *cc);
|
|
++#else
|
|
++static inline int bcma_gpio_init(struct bcma_drv_cc *cc)
|
|
++{
|
|
++ return -ENOTSUPP;
|
|
++}
|
|
++static inline int bcma_gpio_unregister(struct bcma_drv_cc *cc)
|
|
++{
|
|
++ return 0;
|
|
++}
|
|
++#endif /* CONFIG_BCMA_DRIVER_GPIO */
|
|
++
|
|
#endif
|
|
--- a/drivers/bcma/core.c
|
|
+++ b/drivers/bcma/core.c
|
|
-@@ -30,6 +30,7 @@ void bcma_core_disable(struct bcma_devic
|
|
- udelay(10);
|
|
+@@ -9,6 +9,25 @@
|
|
+ #include <linux/export.h>
|
|
+ #include <linux/bcma/bcma.h>
|
|
|
|
++static bool bcma_core_wait_value(struct bcma_device *core, u16 reg, u32 mask,
|
|
++ u32 value, int timeout)
|
|
++{
|
|
++ unsigned long deadline = jiffies + timeout;
|
|
++ u32 val;
|
|
++
|
|
++ do {
|
|
++ val = bcma_aread32(core, reg);
|
|
++ if ((val & mask) == value)
|
|
++ return true;
|
|
++ cpu_relax();
|
|
++ udelay(10);
|
|
++ } while (!time_after_eq(jiffies, deadline));
|
|
++
|
|
++ bcma_warn(core->bus, "Timeout waiting for register 0x%04X!\n", reg);
|
|
++
|
|
++ return false;
|
|
++}
|
|
++
|
|
+ bool bcma_core_is_enabled(struct bcma_device *core)
|
|
+ {
|
|
+ if ((bcma_aread32(core, BCMA_IOCTL) & (BCMA_IOCTL_CLK | BCMA_IOCTL_FGC))
|
|
+@@ -25,12 +44,15 @@ void bcma_core_disable(struct bcma_devic
|
|
+ if (bcma_aread32(core, BCMA_RESET_CTL) & BCMA_RESET_CTL_RESET)
|
|
+ return;
|
|
+
|
|
+- bcma_awrite32(core, BCMA_IOCTL, flags);
|
|
+- bcma_aread32(core, BCMA_IOCTL);
|
|
+- udelay(10);
|
|
++ bcma_core_wait_value(core, BCMA_RESET_ST, ~0, 0, 300);
|
|
+
|
|
bcma_awrite32(core, BCMA_RESET_CTL, BCMA_RESET_CTL_RESET);
|
|
+ bcma_aread32(core, BCMA_RESET_CTL);
|
|
udelay(1);
|
|
++
|
|
++ bcma_awrite32(core, BCMA_IOCTL, flags);
|
|
++ bcma_aread32(core, BCMA_IOCTL);
|
|
++ udelay(10);
|
|
}
|
|
EXPORT_SYMBOL_GPL(bcma_core_disable);
|
|
-@@ -74,10 +75,10 @@ void bcma_core_set_clockmode(struct bcma
|
|
+
|
|
+@@ -42,6 +64,7 @@ int bcma_core_enable(struct bcma_device
|
|
+ bcma_aread32(core, BCMA_IOCTL);
|
|
+
|
|
+ bcma_awrite32(core, BCMA_RESET_CTL, 0);
|
|
++ bcma_aread32(core, BCMA_RESET_CTL);
|
|
+ udelay(1);
|
|
+
|
|
+ bcma_awrite32(core, BCMA_IOCTL, (BCMA_IOCTL_CLK | flags));
|
|
+@@ -64,7 +87,7 @@ void bcma_core_set_clockmode(struct bcma
|
|
+ switch (clkmode) {
|
|
+ case BCMA_CLKMODE_FAST:
|
|
+ bcma_set32(core, BCMA_CLKCTLST, BCMA_CLKCTLST_FORCEHT);
|
|
+- udelay(64);
|
|
++ usleep_range(64, 300);
|
|
+ for (i = 0; i < 1500; i++) {
|
|
+ if (bcma_read32(core, BCMA_CLKCTLST) &
|
|
+ BCMA_CLKCTLST_HAVEHT) {
|
|
+@@ -74,10 +97,10 @@ void bcma_core_set_clockmode(struct bcma
|
|
udelay(10);
|
|
}
|
|
if (i)
|
|
@@ -95,7 +223,7 @@
|
|
break;
|
|
}
|
|
}
|
|
-@@ -101,9 +102,9 @@ void bcma_core_pll_ctl(struct bcma_devic
|
|
+@@ -101,9 +124,15 @@ void bcma_core_pll_ctl(struct bcma_devic
|
|
udelay(10);
|
|
}
|
|
if (i)
|
|
@@ -103,11 +231,17 @@
|
|
+ bcma_err(core->bus, "PLL enable timeout\n");
|
|
} else {
|
|
- pr_warn("Disabling PLL not supported yet!\n");
|
|
-+ bcma_warn(core->bus, "Disabling PLL not supported yet!\n");
|
|
++ /*
|
|
++ * Mask the PLL but don't wait for it to be disabled. PLL may be
|
|
++ * shared between cores and will be still up if there is another
|
|
++ * core using it.
|
|
++ */
|
|
++ bcma_mask32(core, BCMA_CLKCTLST, ~req);
|
|
++ bcma_read32(core, BCMA_CLKCTLST);
|
|
}
|
|
}
|
|
EXPORT_SYMBOL_GPL(bcma_core_pll_ctl);
|
|
-@@ -119,8 +120,8 @@ u32 bcma_core_dma_translation(struct bcm
|
|
+@@ -119,8 +148,8 @@ u32 bcma_core_dma_translation(struct bcm
|
|
else
|
|
return BCMA_DMA_TRANSLATION_DMA32_CMT;
|
|
default:
|
|
@@ -120,7 +254,158 @@
|
|
}
|
|
--- a/drivers/bcma/driver_chipcommon.c
|
|
+++ b/drivers/bcma/driver_chipcommon.c
|
|
-@@ -44,7 +44,7 @@ void bcma_core_chipcommon_init(struct bc
|
|
+@@ -4,12 +4,15 @@
|
|
+ *
|
|
+ * Copyright 2005, Broadcom Corporation
|
|
+ * Copyright 2006, 2007, Michael Buesch <m@bues.ch>
|
|
++ * Copyright 2012, Hauke Mehrtens <hauke@hauke-m.de>
|
|
+ *
|
|
+ * Licensed under the GNU/GPL. See COPYING for details.
|
|
+ */
|
|
+
|
|
+ #include "bcma_private.h"
|
|
++#include <linux/bcm47xx_wdt.h>
|
|
+ #include <linux/export.h>
|
|
++#include <linux/platform_device.h>
|
|
+ #include <linux/bcma/bcma.h>
|
|
+
|
|
+ static inline u32 bcma_cc_write32_masked(struct bcma_drv_cc *cc, u16 offset,
|
|
+@@ -22,29 +25,136 @@ static inline u32 bcma_cc_write32_masked
|
|
+ return value;
|
|
+ }
|
|
+
|
|
+-void bcma_core_chipcommon_init(struct bcma_drv_cc *cc)
|
|
++u32 bcma_chipco_get_alp_clock(struct bcma_drv_cc *cc)
|
|
+ {
|
|
+- u32 leddc_on = 10;
|
|
+- u32 leddc_off = 90;
|
|
++ if (cc->capabilities & BCMA_CC_CAP_PMU)
|
|
++ return bcma_pmu_get_alp_clock(cc);
|
|
+
|
|
+- if (cc->setup_done)
|
|
++ return 20000000;
|
|
++}
|
|
++EXPORT_SYMBOL_GPL(bcma_chipco_get_alp_clock);
|
|
++
|
|
++static u32 bcma_chipco_watchdog_get_max_timer(struct bcma_drv_cc *cc)
|
|
++{
|
|
++ struct bcma_bus *bus = cc->core->bus;
|
|
++ u32 nb;
|
|
++
|
|
++ if (cc->capabilities & BCMA_CC_CAP_PMU) {
|
|
++ if (bus->chipinfo.id == BCMA_CHIP_ID_BCM4706)
|
|
++ nb = 32;
|
|
++ else if (cc->core->id.rev < 26)
|
|
++ nb = 16;
|
|
++ else
|
|
++ nb = (cc->core->id.rev >= 37) ? 32 : 24;
|
|
++ } else {
|
|
++ nb = 28;
|
|
++ }
|
|
++ if (nb == 32)
|
|
++ return 0xffffffff;
|
|
++ else
|
|
++ return (1 << nb) - 1;
|
|
++}
|
|
++
|
|
++static u32 bcma_chipco_watchdog_timer_set_wdt(struct bcm47xx_wdt *wdt,
|
|
++ u32 ticks)
|
|
++{
|
|
++ struct bcma_drv_cc *cc = bcm47xx_wdt_get_drvdata(wdt);
|
|
++
|
|
++ return bcma_chipco_watchdog_timer_set(cc, ticks);
|
|
++}
|
|
++
|
|
++static u32 bcma_chipco_watchdog_timer_set_ms_wdt(struct bcm47xx_wdt *wdt,
|
|
++ u32 ms)
|
|
++{
|
|
++ struct bcma_drv_cc *cc = bcm47xx_wdt_get_drvdata(wdt);
|
|
++ u32 ticks;
|
|
++
|
|
++ ticks = bcma_chipco_watchdog_timer_set(cc, cc->ticks_per_ms * ms);
|
|
++ return ticks / cc->ticks_per_ms;
|
|
++}
|
|
++
|
|
++static int bcma_chipco_watchdog_ticks_per_ms(struct bcma_drv_cc *cc)
|
|
++{
|
|
++ struct bcma_bus *bus = cc->core->bus;
|
|
++
|
|
++ if (cc->capabilities & BCMA_CC_CAP_PMU) {
|
|
++ if (bus->chipinfo.id == BCMA_CHIP_ID_BCM4706)
|
|
++ /* 4706 CC and PMU watchdogs are clocked at 1/4 of ALP clock */
|
|
++ return bcma_chipco_get_alp_clock(cc) / 4000;
|
|
++ else
|
|
++ /* based on 32KHz ILP clock */
|
|
++ return 32;
|
|
++ } else {
|
|
++ return bcma_chipco_get_alp_clock(cc) / 1000;
|
|
++ }
|
|
++}
|
|
++
|
|
++int bcma_chipco_watchdog_register(struct bcma_drv_cc *cc)
|
|
++{
|
|
++ struct bcm47xx_wdt wdt = {};
|
|
++ struct platform_device *pdev;
|
|
++
|
|
++ wdt.driver_data = cc;
|
|
++ wdt.timer_set = bcma_chipco_watchdog_timer_set_wdt;
|
|
++ wdt.timer_set_ms = bcma_chipco_watchdog_timer_set_ms_wdt;
|
|
++ wdt.max_timer_ms = bcma_chipco_watchdog_get_max_timer(cc) / cc->ticks_per_ms;
|
|
++
|
|
++ pdev = platform_device_register_data(NULL, "bcm47xx-wdt",
|
|
++ cc->core->bus->num, &wdt,
|
|
++ sizeof(wdt));
|
|
++ if (IS_ERR(pdev))
|
|
++ return PTR_ERR(pdev);
|
|
++
|
|
++ cc->watchdog = pdev;
|
|
++
|
|
++ return 0;
|
|
++}
|
|
++
|
|
++void bcma_core_chipcommon_early_init(struct bcma_drv_cc *cc)
|
|
++{
|
|
++ if (cc->early_setup_done)
|
|
+ return;
|
|
+
|
|
++ spin_lock_init(&cc->gpio_lock);
|
|
++
|
|
+ if (cc->core->id.rev >= 11)
|
|
+ cc->status = bcma_cc_read32(cc, BCMA_CC_CHIPSTAT);
|
|
+ cc->capabilities = bcma_cc_read32(cc, BCMA_CC_CAP);
|
|
+ if (cc->core->id.rev >= 35)
|
|
+ cc->capabilities_ext = bcma_cc_read32(cc, BCMA_CC_CAP_EXT);
|
|
+
|
|
++ if (cc->capabilities & BCMA_CC_CAP_PMU)
|
|
++ bcma_pmu_early_init(cc);
|
|
++
|
|
++ cc->early_setup_done = true;
|
|
++}
|
|
++
|
|
++void bcma_core_chipcommon_init(struct bcma_drv_cc *cc)
|
|
++{
|
|
++ u32 leddc_on = 10;
|
|
++ u32 leddc_off = 90;
|
|
++
|
|
++ if (cc->setup_done)
|
|
++ return;
|
|
++
|
|
++ bcma_core_chipcommon_early_init(cc);
|
|
++
|
|
+ if (cc->core->id.rev >= 20) {
|
|
+- bcma_cc_write32(cc, BCMA_CC_GPIOPULLUP, 0);
|
|
+- bcma_cc_write32(cc, BCMA_CC_GPIOPULLDOWN, 0);
|
|
++ u32 pullup = 0, pulldown = 0;
|
|
++
|
|
++ if (cc->core->bus->chipinfo.id == BCMA_CHIP_ID_BCM43142) {
|
|
++ pullup = 0x402e0;
|
|
++ pulldown = 0x20500;
|
|
++ }
|
|
++
|
|
++ bcma_cc_write32(cc, BCMA_CC_GPIOPULLUP, pullup);
|
|
++ bcma_cc_write32(cc, BCMA_CC_GPIOPULLDOWN, pulldown);
|
|
+ }
|
|
+
|
|
if (cc->capabilities & BCMA_CC_CAP_PMU)
|
|
bcma_pmu_init(cc);
|
|
if (cc->capabilities & BCMA_CC_CAP_PCTL)
|
|
@@ -129,7 +414,159 @@
|
|
|
|
if (cc->core->id.rev >= 16) {
|
|
if (cc->core->bus->sprom.leddc_on_time &&
|
|
-@@ -137,8 +137,7 @@ void bcma_chipco_serial_init(struct bcma
|
|
+@@ -56,15 +166,33 @@ void bcma_core_chipcommon_init(struct bc
|
|
+ ((leddc_on << BCMA_CC_GPIOTIMER_ONTIME_SHIFT) |
|
|
+ (leddc_off << BCMA_CC_GPIOTIMER_OFFTIME_SHIFT)));
|
|
+ }
|
|
++ cc->ticks_per_ms = bcma_chipco_watchdog_ticks_per_ms(cc);
|
|
+
|
|
+ cc->setup_done = true;
|
|
+ }
|
|
+
|
|
+ /* Set chip watchdog reset timer to fire in 'ticks' backplane cycles */
|
|
+-void bcma_chipco_watchdog_timer_set(struct bcma_drv_cc *cc, u32 ticks)
|
|
++u32 bcma_chipco_watchdog_timer_set(struct bcma_drv_cc *cc, u32 ticks)
|
|
+ {
|
|
+- /* instant NMI */
|
|
+- bcma_cc_write32(cc, BCMA_CC_WATCHDOG, ticks);
|
|
++ u32 maxt;
|
|
++ enum bcma_clkmode clkmode;
|
|
++
|
|
++ maxt = bcma_chipco_watchdog_get_max_timer(cc);
|
|
++ if (cc->capabilities & BCMA_CC_CAP_PMU) {
|
|
++ if (ticks == 1)
|
|
++ ticks = 2;
|
|
++ else if (ticks > maxt)
|
|
++ ticks = maxt;
|
|
++ bcma_cc_write32(cc, BCMA_CC_PMU_WATCHDOG, ticks);
|
|
++ } else {
|
|
++ clkmode = ticks ? BCMA_CLKMODE_FAST : BCMA_CLKMODE_DYNAMIC;
|
|
++ bcma_core_set_clockmode(cc->core, clkmode);
|
|
++ if (ticks > maxt)
|
|
++ ticks = maxt;
|
|
++ /* instant NMI */
|
|
++ bcma_cc_write32(cc, BCMA_CC_WATCHDOG, ticks);
|
|
++ }
|
|
++ return ticks;
|
|
+ }
|
|
+
|
|
+ void bcma_chipco_irq_mask(struct bcma_drv_cc *cc, u32 mask, u32 value)
|
|
+@@ -84,28 +212,99 @@ u32 bcma_chipco_gpio_in(struct bcma_drv_
|
|
+
|
|
+ u32 bcma_chipco_gpio_out(struct bcma_drv_cc *cc, u32 mask, u32 value)
|
|
+ {
|
|
+- return bcma_cc_write32_masked(cc, BCMA_CC_GPIOOUT, mask, value);
|
|
++ unsigned long flags;
|
|
++ u32 res;
|
|
++
|
|
++ spin_lock_irqsave(&cc->gpio_lock, flags);
|
|
++ res = bcma_cc_write32_masked(cc, BCMA_CC_GPIOOUT, mask, value);
|
|
++ spin_unlock_irqrestore(&cc->gpio_lock, flags);
|
|
++
|
|
++ return res;
|
|
+ }
|
|
++EXPORT_SYMBOL_GPL(bcma_chipco_gpio_out);
|
|
+
|
|
+ u32 bcma_chipco_gpio_outen(struct bcma_drv_cc *cc, u32 mask, u32 value)
|
|
+ {
|
|
+- return bcma_cc_write32_masked(cc, BCMA_CC_GPIOOUTEN, mask, value);
|
|
++ unsigned long flags;
|
|
++ u32 res;
|
|
++
|
|
++ spin_lock_irqsave(&cc->gpio_lock, flags);
|
|
++ res = bcma_cc_write32_masked(cc, BCMA_CC_GPIOOUTEN, mask, value);
|
|
++ spin_unlock_irqrestore(&cc->gpio_lock, flags);
|
|
++
|
|
++ return res;
|
|
+ }
|
|
++EXPORT_SYMBOL_GPL(bcma_chipco_gpio_outen);
|
|
+
|
|
++/*
|
|
++ * If the bit is set to 0, chipcommon controlls this GPIO,
|
|
++ * if the bit is set to 1, it is used by some part of the chip and not our code.
|
|
++ */
|
|
+ u32 bcma_chipco_gpio_control(struct bcma_drv_cc *cc, u32 mask, u32 value)
|
|
+ {
|
|
+- return bcma_cc_write32_masked(cc, BCMA_CC_GPIOCTL, mask, value);
|
|
++ unsigned long flags;
|
|
++ u32 res;
|
|
++
|
|
++ spin_lock_irqsave(&cc->gpio_lock, flags);
|
|
++ res = bcma_cc_write32_masked(cc, BCMA_CC_GPIOCTL, mask, value);
|
|
++ spin_unlock_irqrestore(&cc->gpio_lock, flags);
|
|
++
|
|
++ return res;
|
|
+ }
|
|
+ EXPORT_SYMBOL_GPL(bcma_chipco_gpio_control);
|
|
+
|
|
+ u32 bcma_chipco_gpio_intmask(struct bcma_drv_cc *cc, u32 mask, u32 value)
|
|
+ {
|
|
+- return bcma_cc_write32_masked(cc, BCMA_CC_GPIOIRQ, mask, value);
|
|
++ unsigned long flags;
|
|
++ u32 res;
|
|
++
|
|
++ spin_lock_irqsave(&cc->gpio_lock, flags);
|
|
++ res = bcma_cc_write32_masked(cc, BCMA_CC_GPIOIRQ, mask, value);
|
|
++ spin_unlock_irqrestore(&cc->gpio_lock, flags);
|
|
++
|
|
++ return res;
|
|
+ }
|
|
+
|
|
+ u32 bcma_chipco_gpio_polarity(struct bcma_drv_cc *cc, u32 mask, u32 value)
|
|
+ {
|
|
+- return bcma_cc_write32_masked(cc, BCMA_CC_GPIOPOL, mask, value);
|
|
++ unsigned long flags;
|
|
++ u32 res;
|
|
++
|
|
++ spin_lock_irqsave(&cc->gpio_lock, flags);
|
|
++ res = bcma_cc_write32_masked(cc, BCMA_CC_GPIOPOL, mask, value);
|
|
++ spin_unlock_irqrestore(&cc->gpio_lock, flags);
|
|
++
|
|
++ return res;
|
|
++}
|
|
++
|
|
++u32 bcma_chipco_gpio_pullup(struct bcma_drv_cc *cc, u32 mask, u32 value)
|
|
++{
|
|
++ unsigned long flags;
|
|
++ u32 res;
|
|
++
|
|
++ if (cc->core->id.rev < 20)
|
|
++ return 0;
|
|
++
|
|
++ spin_lock_irqsave(&cc->gpio_lock, flags);
|
|
++ res = bcma_cc_write32_masked(cc, BCMA_CC_GPIOPULLUP, mask, value);
|
|
++ spin_unlock_irqrestore(&cc->gpio_lock, flags);
|
|
++
|
|
++ return res;
|
|
++}
|
|
++
|
|
++u32 bcma_chipco_gpio_pulldown(struct bcma_drv_cc *cc, u32 mask, u32 value)
|
|
++{
|
|
++ unsigned long flags;
|
|
++ u32 res;
|
|
++
|
|
++ if (cc->core->id.rev < 20)
|
|
++ return 0;
|
|
++
|
|
++ spin_lock_irqsave(&cc->gpio_lock, flags);
|
|
++ res = bcma_cc_write32_masked(cc, BCMA_CC_GPIOPULLDOWN, mask, value);
|
|
++ spin_unlock_irqrestore(&cc->gpio_lock, flags);
|
|
++
|
|
++ return res;
|
|
+ }
|
|
+
|
|
+ #ifdef CONFIG_BCMA_DRIVER_MIPS
|
|
+@@ -118,8 +317,7 @@ void bcma_chipco_serial_init(struct bcma
|
|
+ struct bcma_serial_port *ports = cc->serial_ports;
|
|
+
|
|
+ if (ccrev >= 11 && ccrev != 15) {
|
|
+- /* Fixed ALP clock */
|
|
+- baud_base = bcma_pmu_alp_clock(cc);
|
|
++ baud_base = bcma_chipco_get_alp_clock(cc);
|
|
+ if (ccrev >= 21) {
|
|
+ /* Turn off UART clock before switching clocksource. */
|
|
+ bcma_cc_write32(cc, BCMA_CC_CORECTL,
|
|
+@@ -137,12 +335,11 @@ void bcma_chipco_serial_init(struct bcma
|
|
| BCMA_CC_CORECTL_UARTCLKEN);
|
|
}
|
|
} else {
|
|
@@ -139,6 +576,11 @@
|
|
return;
|
|
}
|
|
|
|
+- irq = bcma_core_mips_irq(cc->core);
|
|
++ irq = bcma_core_irq(cc->core);
|
|
+
|
|
+ /* Determine the registers of the UARTs */
|
|
+ cc->nr_serial_ports = (cc->capabilities & BCMA_CC_CAP_NRUART);
|
|
--- a/drivers/bcma/driver_chipcommon_pmu.c
|
|
+++ b/drivers/bcma/driver_chipcommon_pmu.c
|
|
@@ -3,7 +3,8 @@
|
|
@@ -151,29 +593,136 @@
|
|
*
|
|
* Licensed under the GNU/GPL. See COPYING for details.
|
|
*/
|
|
-@@ -54,38 +55,19 @@ void bcma_chipco_regctl_maskset(struct b
|
|
+@@ -12,12 +13,13 @@
|
|
+ #include <linux/export.h>
|
|
+ #include <linux/bcma/bcma.h>
|
|
+
|
|
+-static u32 bcma_chipco_pll_read(struct bcma_drv_cc *cc, u32 offset)
|
|
++u32 bcma_chipco_pll_read(struct bcma_drv_cc *cc, u32 offset)
|
|
+ {
|
|
+ bcma_cc_write32(cc, BCMA_CC_PLLCTL_ADDR, offset);
|
|
+ bcma_cc_read32(cc, BCMA_CC_PLLCTL_ADDR);
|
|
+ return bcma_cc_read32(cc, BCMA_CC_PLLCTL_DATA);
|
|
}
|
|
++EXPORT_SYMBOL_GPL(bcma_chipco_pll_read);
|
|
+
|
|
+ void bcma_chipco_pll_write(struct bcma_drv_cc *cc, u32 offset, u32 value)
|
|
+ {
|
|
+@@ -54,19 +56,106 @@ void bcma_chipco_regctl_maskset(struct b
|
|
+ }
|
|
EXPORT_SYMBOL_GPL(bcma_chipco_regctl_maskset);
|
|
|
|
--static void bcma_pmu_pll_init(struct bcma_drv_cc *cc)
|
|
--{
|
|
-- struct bcma_bus *bus = cc->core->bus;
|
|
--
|
|
-- switch (bus->chipinfo.id) {
|
|
++static u32 bcma_pmu_xtalfreq(struct bcma_drv_cc *cc)
|
|
++{
|
|
++ u32 ilp_ctl, alp_hz;
|
|
++
|
|
++ if (!(bcma_cc_read32(cc, BCMA_CC_PMU_STAT) &
|
|
++ BCMA_CC_PMU_STAT_EXT_LPO_AVAIL))
|
|
++ return 0;
|
|
++
|
|
++ bcma_cc_write32(cc, BCMA_CC_PMU_XTAL_FREQ,
|
|
++ BIT(BCMA_CC_PMU_XTAL_FREQ_MEASURE_SHIFT));
|
|
++ usleep_range(1000, 2000);
|
|
++
|
|
++ ilp_ctl = bcma_cc_read32(cc, BCMA_CC_PMU_XTAL_FREQ);
|
|
++ ilp_ctl &= BCMA_CC_PMU_XTAL_FREQ_ILPCTL_MASK;
|
|
++
|
|
++ bcma_cc_write32(cc, BCMA_CC_PMU_XTAL_FREQ, 0);
|
|
++
|
|
++ alp_hz = ilp_ctl * 32768 / 4;
|
|
++ return (alp_hz + 50000) / 100000 * 100;
|
|
++}
|
|
++
|
|
++static void bcma_pmu2_pll_init0(struct bcma_drv_cc *cc, u32 xtalfreq)
|
|
++{
|
|
++ struct bcma_bus *bus = cc->core->bus;
|
|
++ u32 freq_tgt_target = 0, freq_tgt_current;
|
|
++ u32 pll0, mask;
|
|
++
|
|
++ switch (bus->chipinfo.id) {
|
|
++ case BCMA_CHIP_ID_BCM43142:
|
|
++ /* pmu2_xtaltab0_adfll_485 */
|
|
++ switch (xtalfreq) {
|
|
++ case 12000:
|
|
++ freq_tgt_target = 0x50D52;
|
|
++ break;
|
|
++ case 20000:
|
|
++ freq_tgt_target = 0x307FE;
|
|
++ break;
|
|
++ case 26000:
|
|
++ freq_tgt_target = 0x254EA;
|
|
++ break;
|
|
++ case 37400:
|
|
++ freq_tgt_target = 0x19EF8;
|
|
++ break;
|
|
++ case 52000:
|
|
++ freq_tgt_target = 0x12A75;
|
|
++ break;
|
|
++ }
|
|
++ break;
|
|
++ }
|
|
++
|
|
++ if (!freq_tgt_target) {
|
|
++ bcma_err(bus, "Unknown TGT frequency for xtalfreq %d\n",
|
|
++ xtalfreq);
|
|
++ return;
|
|
++ }
|
|
++
|
|
++ pll0 = bcma_chipco_pll_read(cc, BCMA_CC_PMU15_PLL_PLLCTL0);
|
|
++ freq_tgt_current = (pll0 & BCMA_CC_PMU15_PLL_PC0_FREQTGT_MASK) >>
|
|
++ BCMA_CC_PMU15_PLL_PC0_FREQTGT_SHIFT;
|
|
++
|
|
++ if (freq_tgt_current == freq_tgt_target) {
|
|
++ bcma_debug(bus, "Target TGT frequency already set\n");
|
|
++ return;
|
|
++ }
|
|
++
|
|
++ /* Turn off PLL */
|
|
++ switch (bus->chipinfo.id) {
|
|
++ case BCMA_CHIP_ID_BCM43142:
|
|
++ mask = (u32)~(BCMA_RES_4314_HT_AVAIL |
|
|
++ BCMA_RES_4314_MACPHY_CLK_AVAIL);
|
|
++
|
|
++ bcma_cc_mask32(cc, BCMA_CC_PMU_MINRES_MSK, mask);
|
|
++ bcma_cc_mask32(cc, BCMA_CC_PMU_MAXRES_MSK, mask);
|
|
++ bcma_wait_value(cc->core, BCMA_CLKCTLST,
|
|
++ BCMA_CLKCTLST_HAVEHT, 0, 20000);
|
|
++ break;
|
|
++ }
|
|
++
|
|
++ pll0 &= ~BCMA_CC_PMU15_PLL_PC0_FREQTGT_MASK;
|
|
++ pll0 |= freq_tgt_target << BCMA_CC_PMU15_PLL_PC0_FREQTGT_SHIFT;
|
|
++ bcma_chipco_pll_write(cc, BCMA_CC_PMU15_PLL_PLLCTL0, pll0);
|
|
++
|
|
++ /* Flush */
|
|
++ if (cc->pmu.rev >= 2)
|
|
++ bcma_cc_set32(cc, BCMA_CC_PMU_CTL, BCMA_CC_PMU_CTL_PLL_UPD);
|
|
++
|
|
++ /* TODO: Do we need to update OTP? */
|
|
++}
|
|
++
|
|
+ static void bcma_pmu_pll_init(struct bcma_drv_cc *cc)
|
|
+ {
|
|
+ struct bcma_bus *bus = cc->core->bus;
|
|
++ u32 xtalfreq = bcma_pmu_xtalfreq(cc);
|
|
+
|
|
+ switch (bus->chipinfo.id) {
|
|
- case 0x4313:
|
|
- case 0x4331:
|
|
- case 43224:
|
|
- case 43225:
|
|
-- break;
|
|
++ case BCMA_CHIP_ID_BCM43142:
|
|
++ if (xtalfreq == 0)
|
|
++ xtalfreq = 20000;
|
|
++ bcma_pmu2_pll_init0(cc, xtalfreq);
|
|
+ break;
|
|
- default:
|
|
- pr_err("PLL init unknown for device 0x%04X\n",
|
|
- bus->chipinfo.id);
|
|
-- }
|
|
--}
|
|
--
|
|
- static void bcma_pmu_resources_init(struct bcma_drv_cc *cc)
|
|
- {
|
|
- struct bcma_bus *bus = cc->core->bus;
|
|
+ }
|
|
+ }
|
|
+
|
|
+@@ -76,16 +165,32 @@ static void bcma_pmu_resources_init(stru
|
|
u32 min_msk = 0, max_msk = 0;
|
|
|
|
switch (bus->chipinfo.id) {
|
|
@@ -184,7 +733,25 @@
|
|
break;
|
|
- case 43224:
|
|
- case 43225:
|
|
-- break;
|
|
++ case BCMA_CHIP_ID_BCM43142:
|
|
++ min_msk = BCMA_RES_4314_LPLDO_PU |
|
|
++ BCMA_RES_4314_PMU_SLEEP_DIS |
|
|
++ BCMA_RES_4314_PMU_BG_PU |
|
|
++ BCMA_RES_4314_CBUCK_LPOM_PU |
|
|
++ BCMA_RES_4314_CBUCK_PFM_PU |
|
|
++ BCMA_RES_4314_CLDO_PU |
|
|
++ BCMA_RES_4314_LPLDO2_LVM |
|
|
++ BCMA_RES_4314_WL_PMU_PU |
|
|
++ BCMA_RES_4314_LDO3P3_PU |
|
|
++ BCMA_RES_4314_OTP_PU |
|
|
++ BCMA_RES_4314_WL_PWRSW_PU |
|
|
++ BCMA_RES_4314_LQ_AVAIL |
|
|
++ BCMA_RES_4314_LOGIC_RET |
|
|
++ BCMA_RES_4314_MEM_SLEEP |
|
|
++ BCMA_RES_4314_MACPHY_RET |
|
|
++ BCMA_RES_4314_WL_CORE_READY;
|
|
++ max_msk = 0x3FFFFFFF;
|
|
+ break;
|
|
default:
|
|
- pr_err("PMU resource config unknown for device 0x%04X\n",
|
|
- bus->chipinfo.id);
|
|
@@ -193,16 +760,16 @@
|
|
}
|
|
|
|
/* Set the resource masks. */
|
|
-@@ -93,22 +75,9 @@ static void bcma_pmu_resources_init(stru
|
|
+@@ -93,22 +198,12 @@ static void bcma_pmu_resources_init(stru
|
|
bcma_cc_write32(cc, BCMA_CC_PMU_MINRES_MSK, min_msk);
|
|
if (max_msk)
|
|
bcma_cc_write32(cc, BCMA_CC_PMU_MAXRES_MSK, max_msk);
|
|
-}
|
|
--
|
|
+
|
|
-void bcma_pmu_swreg_init(struct bcma_drv_cc *cc)
|
|
-{
|
|
- struct bcma_bus *bus = cc->core->bus;
|
|
-
|
|
+-
|
|
- switch (bus->chipinfo.id) {
|
|
- case 0x4313:
|
|
- case 0x4331:
|
|
@@ -213,12 +780,15 @@
|
|
- pr_err("PMU switch/regulators init unknown for device "
|
|
- "0x%04X\n", bus->chipinfo.id);
|
|
- }
|
|
-+ /* Add some delay; allow resources to come up and settle. */
|
|
++ /*
|
|
++ * Add some delay; allow resources to come up and settle.
|
|
++ * Delay is required for SoC (early init).
|
|
++ */
|
|
+ mdelay(2);
|
|
}
|
|
|
|
/* Disable to allow reading SPROM. Don't know the adventages of enabling it. */
|
|
-@@ -122,8 +91,11 @@ void bcma_chipco_bcm4331_ext_pa_lines_ct
|
|
+@@ -122,51 +217,69 @@ void bcma_chipco_bcm4331_ext_pa_lines_ct
|
|
val |= BCMA_CHIPCTL_4331_EXTPA_EN;
|
|
if (bus->chipinfo.pkg == 9 || bus->chipinfo.pkg == 11)
|
|
val |= BCMA_CHIPCTL_4331_EXTPA_ON_GPIO2_5;
|
|
@@ -230,7 +800,11 @@
|
|
val &= ~BCMA_CHIPCTL_4331_EXTPA_ON_GPIO2_5;
|
|
}
|
|
bcma_cc_write32(cc, BCMA_CC_CHIPCTL, val);
|
|
-@@ -134,26 +106,38 @@ void bcma_pmu_workarounds(struct bcma_dr
|
|
+ }
|
|
+
|
|
+-void bcma_pmu_workarounds(struct bcma_drv_cc *cc)
|
|
++static void bcma_pmu_workarounds(struct bcma_drv_cc *cc)
|
|
+ {
|
|
struct bcma_bus *bus = cc->core->bus;
|
|
|
|
switch (bus->chipinfo.id) {
|
|
@@ -240,7 +814,7 @@
|
|
+ /* enable 12 mA drive strenth for 4313 and set chipControl
|
|
+ register bit 1 */
|
|
+ bcma_chipco_chipctl_maskset(cc, 0,
|
|
-+ BCMA_CCTRL_4313_12MA_LED_DRIVE,
|
|
++ ~BCMA_CCTRL_4313_12MA_LED_DRIVE,
|
|
+ BCMA_CCTRL_4313_12MA_LED_DRIVE);
|
|
break;
|
|
- case 0x4331:
|
|
@@ -260,15 +834,15 @@
|
|
- "implemented\n");
|
|
- bcma_chipco_chipctl_maskset(cc, 0, ~0, 0x00F000F0);
|
|
+ bcma_cc_maskset32(cc, BCMA_CC_CHIPCTL,
|
|
-+ BCMA_CCTRL_43224_GPIO_TOGGLE,
|
|
++ ~BCMA_CCTRL_43224_GPIO_TOGGLE,
|
|
+ BCMA_CCTRL_43224_GPIO_TOGGLE);
|
|
+ bcma_chipco_chipctl_maskset(cc, 0,
|
|
-+ BCMA_CCTRL_43224A0_12MA_LED_DRIVE,
|
|
++ ~BCMA_CCTRL_43224A0_12MA_LED_DRIVE,
|
|
+ BCMA_CCTRL_43224A0_12MA_LED_DRIVE);
|
|
} else {
|
|
- bcma_chipco_chipctl_maskset(cc, 0, ~0, 0xF0);
|
|
+ bcma_chipco_chipctl_maskset(cc, 0,
|
|
-+ BCMA_CCTRL_43224B0_12MA_LED_DRIVE,
|
|
++ ~BCMA_CCTRL_43224B0_12MA_LED_DRIVE,
|
|
+ BCMA_CCTRL_43224B0_12MA_LED_DRIVE);
|
|
}
|
|
break;
|
|
@@ -282,7 +856,11 @@
|
|
}
|
|
}
|
|
|
|
-@@ -164,8 +148,8 @@ void bcma_pmu_init(struct bcma_drv_cc *c
|
|
+-void bcma_pmu_init(struct bcma_drv_cc *cc)
|
|
++void bcma_pmu_early_init(struct bcma_drv_cc *cc)
|
|
+ {
|
|
+ u32 pmucap;
|
|
+
|
|
pmucap = bcma_cc_read32(cc, BCMA_CC_PMU_CAP);
|
|
cc->pmu.rev = (pmucap & BCMA_CC_PMU_CAP_REVISION);
|
|
|
|
@@ -290,23 +868,29 @@
|
|
- pmucap);
|
|
+ bcma_debug(cc->core->bus, "Found rev %u PMU (capabilities 0x%08X)\n",
|
|
+ cc->pmu.rev, pmucap);
|
|
++}
|
|
|
|
++void bcma_pmu_init(struct bcma_drv_cc *cc)
|
|
++{
|
|
if (cc->pmu.rev == 1)
|
|
bcma_cc_mask32(cc, BCMA_CC_PMU_CTL,
|
|
-@@ -174,12 +158,7 @@ void bcma_pmu_init(struct bcma_drv_cc *c
|
|
+ ~BCMA_CC_PMU_CTL_NOILPONW);
|
|
+@@ -174,37 +287,48 @@ void bcma_pmu_init(struct bcma_drv_cc *c
|
|
bcma_cc_set32(cc, BCMA_CC_PMU_CTL,
|
|
BCMA_CC_PMU_CTL_NOILPONW);
|
|
|
|
- if (cc->core->id.id == 0x4329 && cc->core->id.rev == 2)
|
|
- pr_err("Fix for 4329b0 bad LPOM state not implemented!\n");
|
|
-
|
|
-- bcma_pmu_pll_init(cc);
|
|
+ bcma_pmu_pll_init(cc);
|
|
bcma_pmu_resources_init(cc);
|
|
- bcma_pmu_swreg_init(cc);
|
|
bcma_pmu_workarounds(cc);
|
|
}
|
|
|
|
-@@ -188,23 +167,22 @@ u32 bcma_pmu_alp_clock(struct bcma_drv_c
|
|
+-u32 bcma_pmu_alp_clock(struct bcma_drv_cc *cc)
|
|
++u32 bcma_pmu_get_alp_clock(struct bcma_drv_cc *cc)
|
|
+ {
|
|
struct bcma_bus *bus = cc->core->bus;
|
|
|
|
switch (bus->chipinfo.id) {
|
|
@@ -317,21 +901,37 @@
|
|
- case 0x5357:
|
|
- case 0x4749:
|
|
- case 53572:
|
|
++ case BCMA_CHIP_ID_BCM4313:
|
|
++ case BCMA_CHIP_ID_BCM43224:
|
|
++ case BCMA_CHIP_ID_BCM43225:
|
|
++ case BCMA_CHIP_ID_BCM43227:
|
|
++ case BCMA_CHIP_ID_BCM43228:
|
|
++ case BCMA_CHIP_ID_BCM4331:
|
|
++ case BCMA_CHIP_ID_BCM43421:
|
|
++ case BCMA_CHIP_ID_BCM43428:
|
|
++ case BCMA_CHIP_ID_BCM43431:
|
|
+ case BCMA_CHIP_ID_BCM4716:
|
|
++ case BCMA_CHIP_ID_BCM47162:
|
|
+ case BCMA_CHIP_ID_BCM4748:
|
|
-+ case BCMA_CHIP_ID_BCM47162:
|
|
-+ case BCMA_CHIP_ID_BCM4313:
|
|
++ case BCMA_CHIP_ID_BCM4749:
|
|
+ case BCMA_CHIP_ID_BCM5357:
|
|
-+ case BCMA_CHIP_ID_BCM4749:
|
|
+ case BCMA_CHIP_ID_BCM53572:
|
|
++ case BCMA_CHIP_ID_BCM6362:
|
|
/* always 20Mhz */
|
|
return 20000 * 1000;
|
|
- case 0x5356:
|
|
- case 0x5300:
|
|
++ case BCMA_CHIP_ID_BCM4706:
|
|
+ case BCMA_CHIP_ID_BCM5356:
|
|
-+ case BCMA_CHIP_ID_BCM4706:
|
|
/* always 25Mhz */
|
|
return 25000 * 1000;
|
|
++ case BCMA_CHIP_ID_BCM43460:
|
|
++ case BCMA_CHIP_ID_BCM4352:
|
|
++ case BCMA_CHIP_ID_BCM4360:
|
|
++ if (cc->status & BCMA_CC_CHIPST_4360_XTAL_40MZ)
|
|
++ return 40000 * 1000;
|
|
++ else
|
|
++ return 20000 * 1000;
|
|
default:
|
|
- pr_warn("No ALP clock specified for %04X device, "
|
|
- "pmu rev. %d, using default %d Hz\n",
|
|
@@ -341,7 +941,16 @@
|
|
}
|
|
return BCMA_CC_PMU_ALP_CLOCK;
|
|
}
|
|
-@@ -221,7 +199,8 @@ static u32 bcma_pmu_clock(struct bcma_dr
|
|
+@@ -212,7 +336,7 @@ u32 bcma_pmu_alp_clock(struct bcma_drv_c
|
|
+ /* Find the output of the "m" pll divider given pll controls that start with
|
|
+ * pllreg "pll0" i.e. 12 for main 6 for phy, 0 for misc.
|
|
+ */
|
|
+-static u32 bcma_pmu_clock(struct bcma_drv_cc *cc, u32 pll0, u32 m)
|
|
++static u32 bcma_pmu_pll_clock(struct bcma_drv_cc *cc, u32 pll0, u32 m)
|
|
+ {
|
|
+ u32 tmp, div, ndiv, p1, p2, fc;
|
|
+ struct bcma_bus *bus = cc->core->bus;
|
|
+@@ -221,7 +345,8 @@ static u32 bcma_pmu_clock(struct bcma_dr
|
|
|
|
BUG_ON(!m || m > 4);
|
|
|
|
@@ -351,11 +960,19 @@
|
|
/* Detect failure in clock setting */
|
|
tmp = bcma_cc_read32(cc, BCMA_CC_CHIPSTAT);
|
|
if (tmp & 0x40000)
|
|
-@@ -247,33 +226,62 @@ static u32 bcma_pmu_clock(struct bcma_dr
|
|
+@@ -240,60 +365,96 @@ static u32 bcma_pmu_clock(struct bcma_dr
|
|
+ ndiv = (tmp & BCMA_CC_PPL_NDIV_MASK) >> BCMA_CC_PPL_NDIV_SHIFT;
|
|
+
|
|
+ /* Do calculation in Mhz */
|
|
+- fc = bcma_pmu_alp_clock(cc) / 1000000;
|
|
++ fc = bcma_pmu_get_alp_clock(cc) / 1000000;
|
|
+ fc = (p1 * ndiv * fc) / p2;
|
|
+
|
|
+ /* Return clock in Hertz */
|
|
return (fc / div) * 1000000;
|
|
}
|
|
|
|
-+static u32 bcma_pmu_clock_bcm4706(struct bcma_drv_cc *cc, u32 pll0, u32 m)
|
|
++static u32 bcma_pmu_pll_clock_bcm4706(struct bcma_drv_cc *cc, u32 pll0, u32 m)
|
|
+{
|
|
+ u32 tmp, ndiv, p1div, p2div;
|
|
+ u32 clock;
|
|
@@ -386,7 +1003,8 @@
|
|
+}
|
|
+
|
|
/* query bus clock frequency for PMU-enabled chipcommon */
|
|
- u32 bcma_pmu_get_clockcontrol(struct bcma_drv_cc *cc)
|
|
+-u32 bcma_pmu_get_clockcontrol(struct bcma_drv_cc *cc)
|
|
++u32 bcma_pmu_get_bus_clock(struct bcma_drv_cc *cc)
|
|
{
|
|
struct bcma_bus *bus = cc->core->bus;
|
|
|
|
@@ -394,40 +1012,51 @@
|
|
- case 0x4716:
|
|
- case 0x4748:
|
|
- case 47162:
|
|
-+ case BCMA_CHIP_ID_BCM4716:
|
|
-+ case BCMA_CHIP_ID_BCM4748:
|
|
-+ case BCMA_CHIP_ID_BCM47162:
|
|
- return bcma_pmu_clock(cc, BCMA_CC_PMU4716_MAINPLL_PLL0,
|
|
- BCMA_CC_PMU5_MAINPLL_SSB);
|
|
+- return bcma_pmu_clock(cc, BCMA_CC_PMU4716_MAINPLL_PLL0,
|
|
+- BCMA_CC_PMU5_MAINPLL_SSB);
|
|
- case 0x5356:
|
|
-+ case BCMA_CHIP_ID_BCM5356:
|
|
- return bcma_pmu_clock(cc, BCMA_CC_PMU5356_MAINPLL_PLL0,
|
|
- BCMA_CC_PMU5_MAINPLL_SSB);
|
|
+- return bcma_pmu_clock(cc, BCMA_CC_PMU5356_MAINPLL_PLL0,
|
|
+- BCMA_CC_PMU5_MAINPLL_SSB);
|
|
- case 0x5357:
|
|
- case 0x4749:
|
|
-+ case BCMA_CHIP_ID_BCM5357:
|
|
-+ case BCMA_CHIP_ID_BCM4749:
|
|
- return bcma_pmu_clock(cc, BCMA_CC_PMU5357_MAINPLL_PLL0,
|
|
- BCMA_CC_PMU5_MAINPLL_SSB);
|
|
+- return bcma_pmu_clock(cc, BCMA_CC_PMU5357_MAINPLL_PLL0,
|
|
+- BCMA_CC_PMU5_MAINPLL_SSB);
|
|
- case 0x5300:
|
|
- return bcma_pmu_clock(cc, BCMA_CC_PMU4706_MAINPLL_PLL0,
|
|
- BCMA_CC_PMU5_MAINPLL_SSB);
|
|
- case 53572:
|
|
++ case BCMA_CHIP_ID_BCM4716:
|
|
++ case BCMA_CHIP_ID_BCM4748:
|
|
++ case BCMA_CHIP_ID_BCM47162:
|
|
++ return bcma_pmu_pll_clock(cc, BCMA_CC_PMU4716_MAINPLL_PLL0,
|
|
++ BCMA_CC_PMU5_MAINPLL_SSB);
|
|
++ case BCMA_CHIP_ID_BCM5356:
|
|
++ return bcma_pmu_pll_clock(cc, BCMA_CC_PMU5356_MAINPLL_PLL0,
|
|
++ BCMA_CC_PMU5_MAINPLL_SSB);
|
|
++ case BCMA_CHIP_ID_BCM5357:
|
|
++ case BCMA_CHIP_ID_BCM4749:
|
|
++ return bcma_pmu_pll_clock(cc, BCMA_CC_PMU5357_MAINPLL_PLL0,
|
|
++ BCMA_CC_PMU5_MAINPLL_SSB);
|
|
+ case BCMA_CHIP_ID_BCM4706:
|
|
-+ return bcma_pmu_clock_bcm4706(cc, BCMA_CC_PMU4706_MAINPLL_PLL0,
|
|
-+ BCMA_CC_PMU5_MAINPLL_SSB);
|
|
++ return bcma_pmu_pll_clock_bcm4706(cc,
|
|
++ BCMA_CC_PMU4706_MAINPLL_PLL0,
|
|
++ BCMA_CC_PMU5_MAINPLL_SSB);
|
|
+ case BCMA_CHIP_ID_BCM53572:
|
|
return 75000000;
|
|
default:
|
|
- pr_warn("No backplane clock specified for %04X device, "
|
|
- "pmu rev. %d, using default %d Hz\n",
|
|
- bus->chipinfo.id, cc->pmu.rev, BCMA_CC_PMU_HT_CLOCK);
|
|
-+ bcma_warn(bus, "No backplane clock specified for %04X device, pmu rev. %d, using default %d Hz\n",
|
|
++ bcma_warn(bus, "No bus clock specified for %04X device, pmu rev. %d, using default %d Hz\n",
|
|
+ bus->chipinfo.id, cc->pmu.rev, BCMA_CC_PMU_HT_CLOCK);
|
|
}
|
|
return BCMA_CC_PMU_HT_CLOCK;
|
|
}
|
|
-@@ -283,17 +291,21 @@ u32 bcma_pmu_get_clockcpu(struct bcma_dr
|
|
++EXPORT_SYMBOL_GPL(bcma_pmu_get_bus_clock);
|
|
+
|
|
+ /* query cpu clock frequency for PMU-enabled chipcommon */
|
|
+-u32 bcma_pmu_get_clockcpu(struct bcma_drv_cc *cc)
|
|
++u32 bcma_pmu_get_cpu_clock(struct bcma_drv_cc *cc)
|
|
{
|
|
struct bcma_bus *bus = cc->core->bus;
|
|
|
|
@@ -435,12 +1064,13 @@
|
|
+ if (bus->chipinfo.id == BCMA_CHIP_ID_BCM53572)
|
|
return 300000000;
|
|
|
|
++ /* New PMUs can have different clock for bus and CPU */
|
|
if (cc->pmu.rev >= 5) {
|
|
u32 pll;
|
|
switch (bus->chipinfo.id) {
|
|
- case 0x5356:
|
|
+ case BCMA_CHIP_ID_BCM4706:
|
|
-+ return bcma_pmu_clock_bcm4706(cc,
|
|
++ return bcma_pmu_pll_clock_bcm4706(cc,
|
|
+ BCMA_CC_PMU4706_MAINPLL_PLL0,
|
|
+ BCMA_CC_PMU5_MAINPLL_CPU);
|
|
+ case BCMA_CHIP_ID_BCM5356:
|
|
@@ -453,18 +1083,20 @@
|
|
pll = BCMA_CC_PMU5357_MAINPLL_PLL0;
|
|
break;
|
|
default:
|
|
-@@ -301,10 +313,188 @@ u32 bcma_pmu_get_clockcpu(struct bcma_dr
|
|
+@@ -301,10 +462,189 @@ u32 bcma_pmu_get_clockcpu(struct bcma_dr
|
|
break;
|
|
}
|
|
|
|
- /* TODO: if (bus->chipinfo.id == 0x5300)
|
|
- return si_4706_pmu_clock(sih, osh, cc, PMU4706_MAINPLL_PLL0, PMU5_MAINPLL_CPU); */
|
|
- return bcma_pmu_clock(cc, pll, BCMA_CC_PMU5_MAINPLL_CPU);
|
|
- }
|
|
-
|
|
- return bcma_pmu_get_clockcontrol(cc);
|
|
- }
|
|
+- return bcma_pmu_clock(cc, pll, BCMA_CC_PMU5_MAINPLL_CPU);
|
|
++ return bcma_pmu_pll_clock(cc, pll, BCMA_CC_PMU5_MAINPLL_CPU);
|
|
++ }
|
|
+
|
|
++ /* On old PMUs CPU has the same clock as the bus */
|
|
++ return bcma_pmu_get_bus_clock(cc);
|
|
++}
|
|
++
|
|
+static void bcma_pmu_spuravoid_pll_write(struct bcma_drv_cc *cc, u32 offset,
|
|
+ u32 value)
|
|
+{
|
|
@@ -508,7 +1140,7 @@
|
|
+ tmp |= (bcm5357_bcm43236_ndiv[spuravoid]) << BCMA_CC_PMU1_PLL0_PC2_NDIV_INT_SHIFT;
|
|
+ bcma_cc_write32(cc, BCMA_CC_PLLCTL_DATA, tmp);
|
|
+
|
|
-+ tmp = 1 << 10;
|
|
++ tmp = BCMA_CC_PMU_CTL_PLL_UPD;
|
|
+ break;
|
|
+
|
|
+ case BCMA_CHIP_ID_BCM4331:
|
|
@@ -529,7 +1161,7 @@
|
|
+ bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL2,
|
|
+ 0x03000a08);
|
|
+ }
|
|
-+ tmp = 1 << 10;
|
|
++ tmp = BCMA_CC_PMU_CTL_PLL_UPD;
|
|
+ break;
|
|
+
|
|
+ case BCMA_CHIP_ID_BCM43224:
|
|
@@ -562,7 +1194,7 @@
|
|
+ bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL5,
|
|
+ 0x88888815);
|
|
+ }
|
|
-+ tmp = 1 << 10;
|
|
++ tmp = BCMA_CC_PMU_CTL_PLL_UPD;
|
|
+ break;
|
|
+
|
|
+ case BCMA_CHIP_ID_BCM4716:
|
|
@@ -596,7 +1228,7 @@
|
|
+ 0x88888815);
|
|
+ }
|
|
+
|
|
-+ tmp = 3 << 9;
|
|
++ tmp = BCMA_CC_PMU_CTL_PLL_UPD | BCMA_CC_PMU_CTL_NOILPONW;
|
|
+ break;
|
|
+
|
|
+ case BCMA_CHIP_ID_BCM43227:
|
|
@@ -632,17 +1264,18 @@
|
|
+ bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL5,
|
|
+ 0x88888815);
|
|
+ }
|
|
-+ tmp = 1 << 10;
|
|
++ tmp = BCMA_CC_PMU_CTL_PLL_UPD;
|
|
+ break;
|
|
+ default:
|
|
+ bcma_err(bus, "Unknown spuravoidance settings for chip 0x%04X, not changing PLL\n",
|
|
+ bus->chipinfo.id);
|
|
+ break;
|
|
-+ }
|
|
-+
|
|
+ }
|
|
+
|
|
+- return bcma_pmu_get_clockcontrol(cc);
|
|
+ tmp |= bcma_cc_read32(cc, BCMA_CC_PMU_CTL);
|
|
+ bcma_cc_write32(cc, BCMA_CC_PMU_CTL, tmp);
|
|
-+}
|
|
+ }
|
|
+EXPORT_SYMBOL_GPL(bcma_pmu_spuravoid_pllupdate);
|
|
--- /dev/null
|
|
+++ b/drivers/bcma/driver_gmac_cmn.c
|
|
@@ -661,6 +1294,123 @@
|
|
+{
|
|
+ mutex_init(&gc->phy_mutex);
|
|
+}
|
|
+--- /dev/null
|
|
++++ b/drivers/bcma/driver_gpio.c
|
|
+@@ -0,0 +1,114 @@
|
|
++/*
|
|
++ * Broadcom specific AMBA
|
|
++ * GPIO driver
|
|
++ *
|
|
++ * Copyright 2011, Broadcom Corporation
|
|
++ * Copyright 2012, Hauke Mehrtens <hauke@hauke-m.de>
|
|
++ *
|
|
++ * Licensed under the GNU/GPL. See COPYING for details.
|
|
++ */
|
|
++
|
|
++#include <linux/gpio.h>
|
|
++#include <linux/export.h>
|
|
++#include <linux/bcma/bcma.h>
|
|
++
|
|
++#include "bcma_private.h"
|
|
++
|
|
++static inline struct bcma_drv_cc *bcma_gpio_get_cc(struct gpio_chip *chip)
|
|
++{
|
|
++ return container_of(chip, struct bcma_drv_cc, gpio);
|
|
++}
|
|
++
|
|
++static int bcma_gpio_get_value(struct gpio_chip *chip, unsigned gpio)
|
|
++{
|
|
++ struct bcma_drv_cc *cc = bcma_gpio_get_cc(chip);
|
|
++
|
|
++ return !!bcma_chipco_gpio_in(cc, 1 << gpio);
|
|
++}
|
|
++
|
|
++static void bcma_gpio_set_value(struct gpio_chip *chip, unsigned gpio,
|
|
++ int value)
|
|
++{
|
|
++ struct bcma_drv_cc *cc = bcma_gpio_get_cc(chip);
|
|
++
|
|
++ bcma_chipco_gpio_out(cc, 1 << gpio, value ? 1 << gpio : 0);
|
|
++}
|
|
++
|
|
++static int bcma_gpio_direction_input(struct gpio_chip *chip, unsigned gpio)
|
|
++{
|
|
++ struct bcma_drv_cc *cc = bcma_gpio_get_cc(chip);
|
|
++
|
|
++ bcma_chipco_gpio_outen(cc, 1 << gpio, 0);
|
|
++ return 0;
|
|
++}
|
|
++
|
|
++static int bcma_gpio_direction_output(struct gpio_chip *chip, unsigned gpio,
|
|
++ int value)
|
|
++{
|
|
++ struct bcma_drv_cc *cc = bcma_gpio_get_cc(chip);
|
|
++
|
|
++ bcma_chipco_gpio_outen(cc, 1 << gpio, 1 << gpio);
|
|
++ bcma_chipco_gpio_out(cc, 1 << gpio, value ? 1 << gpio : 0);
|
|
++ return 0;
|
|
++}
|
|
++
|
|
++static int bcma_gpio_request(struct gpio_chip *chip, unsigned gpio)
|
|
++{
|
|
++ struct bcma_drv_cc *cc = bcma_gpio_get_cc(chip);
|
|
++
|
|
++ bcma_chipco_gpio_control(cc, 1 << gpio, 0);
|
|
++ /* clear pulldown */
|
|
++ bcma_chipco_gpio_pulldown(cc, 1 << gpio, 0);
|
|
++ /* Set pullup */
|
|
++ bcma_chipco_gpio_pullup(cc, 1 << gpio, 1 << gpio);
|
|
++
|
|
++ return 0;
|
|
++}
|
|
++
|
|
++static void bcma_gpio_free(struct gpio_chip *chip, unsigned gpio)
|
|
++{
|
|
++ struct bcma_drv_cc *cc = bcma_gpio_get_cc(chip);
|
|
++
|
|
++ /* clear pullup */
|
|
++ bcma_chipco_gpio_pullup(cc, 1 << gpio, 0);
|
|
++}
|
|
++
|
|
++static int bcma_gpio_to_irq(struct gpio_chip *chip, unsigned gpio)
|
|
++{
|
|
++ struct bcma_drv_cc *cc = bcma_gpio_get_cc(chip);
|
|
++
|
|
++ if (cc->core->bus->hosttype == BCMA_HOSTTYPE_SOC)
|
|
++ return bcma_core_irq(cc->core);
|
|
++ else
|
|
++ return -EINVAL;
|
|
++}
|
|
++
|
|
++int bcma_gpio_init(struct bcma_drv_cc *cc)
|
|
++{
|
|
++ struct gpio_chip *chip = &cc->gpio;
|
|
++
|
|
++ chip->label = "bcma_gpio";
|
|
++ chip->owner = THIS_MODULE;
|
|
++ chip->request = bcma_gpio_request;
|
|
++ chip->free = bcma_gpio_free;
|
|
++ chip->get = bcma_gpio_get_value;
|
|
++ chip->set = bcma_gpio_set_value;
|
|
++ chip->direction_input = bcma_gpio_direction_input;
|
|
++ chip->direction_output = bcma_gpio_direction_output;
|
|
++ chip->to_irq = bcma_gpio_to_irq;
|
|
++ chip->ngpio = 16;
|
|
++ /* There is just one SoC in one device and its GPIO addresses should be
|
|
++ * deterministic to address them more easily. The other buses could get
|
|
++ * a random base number. */
|
|
++ if (cc->core->bus->hosttype == BCMA_HOSTTYPE_SOC)
|
|
++ chip->base = 0;
|
|
++ else
|
|
++ chip->base = -1;
|
|
++
|
|
++ return gpiochip_add(chip);
|
|
++}
|
|
++
|
|
++int bcma_gpio_unregister(struct bcma_drv_cc *cc)
|
|
++{
|
|
++ return gpiochip_remove(&cc->gpio);
|
|
++}
|
|
--- a/drivers/bcma/driver_mips.c
|
|
+++ b/drivers/bcma/driver_mips.c
|
|
@@ -22,15 +22,15 @@
|
|
@@ -683,27 +1433,144 @@
|
|
dev->bus->chipinfo.pkg == 11 &&
|
|
dev->id.id == BCMA_CORE_USB20_HOST;
|
|
}
|
|
-@@ -143,8 +143,8 @@ static void bcma_core_mips_set_irq(struc
|
|
+@@ -74,28 +74,41 @@ static u32 bcma_core_mips_irqflag(struct
|
|
+ return dev->core_index;
|
|
+ flag = bcma_aread32(dev, BCMA_MIPS_OOBSELOUTA30);
|
|
+
|
|
+- return flag & 0x1F;
|
|
++ if (flag)
|
|
++ return flag & 0x1F;
|
|
++ else
|
|
++ return 0x3f;
|
|
+ }
|
|
+
|
|
+ /* Get the MIPS IRQ assignment for a specified device.
|
|
+ * If unassigned, 0 is returned.
|
|
++ * If disabled, 5 is returned.
|
|
++ * If not supported, 6 is returned.
|
|
+ */
|
|
+-unsigned int bcma_core_mips_irq(struct bcma_device *dev)
|
|
++static unsigned int bcma_core_mips_irq(struct bcma_device *dev)
|
|
+ {
|
|
+ struct bcma_device *mdev = dev->bus->drv_mips.core;
|
|
+ u32 irqflag;
|
|
+ unsigned int irq;
|
|
+
|
|
+ irqflag = bcma_core_mips_irqflag(dev);
|
|
++ if (irqflag == 0x3f)
|
|
++ return 6;
|
|
+
|
|
+- for (irq = 1; irq <= 4; irq++)
|
|
++ for (irq = 0; irq <= 4; irq++)
|
|
+ if (bcma_read32(mdev, BCMA_MIPS_MIPS74K_INTMASK(irq)) &
|
|
+ (1 << irqflag))
|
|
+ return irq;
|
|
+
|
|
+- return 0;
|
|
++ return 5;
|
|
++}
|
|
++
|
|
++unsigned int bcma_core_irq(struct bcma_device *dev)
|
|
++{
|
|
++ unsigned int mips_irq = bcma_core_mips_irq(dev);
|
|
++ return mips_irq <= 4 ? mips_irq + 2 : 0;
|
|
+ }
|
|
+-EXPORT_SYMBOL(bcma_core_mips_irq);
|
|
++EXPORT_SYMBOL(bcma_core_irq);
|
|
+
|
|
+ static void bcma_core_mips_set_irq(struct bcma_device *dev, unsigned int irq)
|
|
+ {
|
|
+@@ -114,8 +127,8 @@ static void bcma_core_mips_set_irq(struc
|
|
+ bcma_write32(mdev, BCMA_MIPS_MIPS74K_INTMASK(0),
|
|
+ bcma_read32(mdev, BCMA_MIPS_MIPS74K_INTMASK(0)) &
|
|
+ ~(1 << irqflag));
|
|
+- else
|
|
+- bcma_write32(mdev, BCMA_MIPS_MIPS74K_INTMASK(irq), 0);
|
|
++ else if (oldirq != 5)
|
|
++ bcma_write32(mdev, BCMA_MIPS_MIPS74K_INTMASK(oldirq), 0);
|
|
+
|
|
+ /* assign the new one */
|
|
+ if (irq == 0) {
|
|
+@@ -123,17 +136,17 @@ static void bcma_core_mips_set_irq(struc
|
|
+ bcma_read32(mdev, BCMA_MIPS_MIPS74K_INTMASK(0)) |
|
|
+ (1 << irqflag));
|
|
+ } else {
|
|
+- u32 oldirqflag = bcma_read32(mdev,
|
|
+- BCMA_MIPS_MIPS74K_INTMASK(irq));
|
|
+- if (oldirqflag) {
|
|
++ u32 irqinitmask = bcma_read32(mdev,
|
|
++ BCMA_MIPS_MIPS74K_INTMASK(irq));
|
|
++ if (irqinitmask) {
|
|
+ struct bcma_device *core;
|
|
+
|
|
+ /* backplane irq line is in use, find out who uses
|
|
+ * it and set user to irq 0
|
|
+ */
|
|
+- list_for_each_entry_reverse(core, &bus->cores, list) {
|
|
++ list_for_each_entry(core, &bus->cores, list) {
|
|
+ if ((1 << bcma_core_mips_irqflag(core)) ==
|
|
+- oldirqflag) {
|
|
++ irqinitmask) {
|
|
+ bcma_core_mips_set_irq(core, 0);
|
|
+ break;
|
|
+ }
|
|
+@@ -143,15 +156,31 @@ static void bcma_core_mips_set_irq(struc
|
|
1 << irqflag);
|
|
}
|
|
|
|
- pr_info("set_irq: core 0x%04x, irq %d => %d\n",
|
|
- dev->id.id, oldirq + 2, irq + 2);
|
|
-+ bcma_info(bus, "set_irq: core 0x%04x, irq %d => %d\n",
|
|
-+ dev->id.id, oldirq + 2, irq + 2);
|
|
++ bcma_debug(bus, "set_irq: core 0x%04x, irq %d => %d\n",
|
|
++ dev->id.id, oldirq <= 4 ? oldirq + 2 : 0, irq + 2);
|
|
++}
|
|
++
|
|
++static void bcma_core_mips_set_irq_name(struct bcma_bus *bus, unsigned int irq,
|
|
++ u16 coreid, u8 unit)
|
|
++{
|
|
++ struct bcma_device *core;
|
|
++
|
|
++ core = bcma_find_core_unit(bus, coreid, unit);
|
|
++ if (!core) {
|
|
++ bcma_warn(bus,
|
|
++ "Can not find core (id: 0x%x, unit %i) for IRQ configuration.\n",
|
|
++ coreid, unit);
|
|
++ return;
|
|
++ }
|
|
++
|
|
++ bcma_core_mips_set_irq(core, irq);
|
|
}
|
|
|
|
static void bcma_core_mips_print_irq(struct bcma_device *dev, unsigned int irq)
|
|
-@@ -173,7 +173,7 @@ u32 bcma_cpu_clock(struct bcma_drv_mips
|
|
+ {
|
|
+ int i;
|
|
+ static const char *irq_name[] = {"2(S)", "3", "4", "5", "6", "D", "I"};
|
|
+- printk(KERN_INFO KBUILD_MODNAME ": core 0x%04x, irq :", dev->id.id);
|
|
++ printk(KERN_DEBUG KBUILD_MODNAME ": core 0x%04x, irq :", dev->id.id);
|
|
+ for (i = 0; i <= 6; i++)
|
|
+ printk(" %s%s", irq_name[i], i == irq ? "*" : " ");
|
|
+ printk("\n");
|
|
+@@ -161,7 +190,7 @@ static void bcma_core_mips_dump_irq(stru
|
|
+ {
|
|
+ struct bcma_device *core;
|
|
+
|
|
+- list_for_each_entry_reverse(core, &bus->cores, list) {
|
|
++ list_for_each_entry(core, &bus->cores, list) {
|
|
+ bcma_core_mips_print_irq(core, bcma_core_mips_irq(core));
|
|
+ }
|
|
+ }
|
|
+@@ -171,9 +200,9 @@ u32 bcma_cpu_clock(struct bcma_drv_mips
|
|
+ struct bcma_bus *bus = mcore->core->bus;
|
|
+
|
|
if (bus->drv_cc.capabilities & BCMA_CC_CAP_PMU)
|
|
- return bcma_pmu_get_clockcpu(&bus->drv_cc);
|
|
+- return bcma_pmu_get_clockcpu(&bus->drv_cc);
|
|
++ return bcma_pmu_get_cpu_clock(&bus->drv_cc);
|
|
|
|
- pr_err("No PMU available, need this to get the cpu clock\n");
|
|
+ bcma_err(bus, "No PMU available, need this to get the cpu clock\n");
|
|
return 0;
|
|
}
|
|
EXPORT_SYMBOL(bcma_cpu_clock);
|
|
-@@ -185,10 +185,10 @@ static void bcma_core_mips_flash_detect(
|
|
+@@ -185,10 +214,10 @@ static void bcma_core_mips_flash_detect(
|
|
switch (bus->drv_cc.capabilities & BCMA_CC_CAP_FLASHT) {
|
|
case BCMA_CC_FLASHT_STSER:
|
|
case BCMA_CC_FLASHT_ATSER:
|
|
@@ -716,33 +1583,151 @@
|
|
bus->drv_cc.pflash.window = 0x1c000000;
|
|
bus->drv_cc.pflash.window_size = 0x02000000;
|
|
|
|
-@@ -199,7 +199,7 @@ static void bcma_core_mips_flash_detect(
|
|
+@@ -199,7 +228,46 @@ static void bcma_core_mips_flash_detect(
|
|
bus->drv_cc.pflash.buswidth = 2;
|
|
break;
|
|
default:
|
|
- pr_err("flash not supported.\n");
|
|
+ bcma_err(bus, "flash not supported.\n");
|
|
++ }
|
|
++}
|
|
++
|
|
++void bcma_core_mips_early_init(struct bcma_drv_mips *mcore)
|
|
++{
|
|
++ struct bcma_bus *bus = mcore->core->bus;
|
|
++
|
|
++ if (mcore->early_setup_done)
|
|
++ return;
|
|
++
|
|
++ bcma_chipco_serial_init(&bus->drv_cc);
|
|
++ bcma_core_mips_flash_detect(mcore);
|
|
++
|
|
++ mcore->early_setup_done = true;
|
|
++}
|
|
++
|
|
++static void bcma_fix_i2s_irqflag(struct bcma_bus *bus)
|
|
++{
|
|
++ struct bcma_device *cpu, *pcie, *i2s;
|
|
++
|
|
++ /* Fixup the interrupts in 4716/4748 for i2s core (2010 Broadcom SDK)
|
|
++ * (IRQ flags > 7 are ignored when setting the interrupt masks)
|
|
++ */
|
|
++ if (bus->chipinfo.id != BCMA_CHIP_ID_BCM4716 &&
|
|
++ bus->chipinfo.id != BCMA_CHIP_ID_BCM4748)
|
|
++ return;
|
|
++
|
|
++ cpu = bcma_find_core(bus, BCMA_CORE_MIPS_74K);
|
|
++ pcie = bcma_find_core(bus, BCMA_CORE_PCIE);
|
|
++ i2s = bcma_find_core(bus, BCMA_CORE_I2S);
|
|
++ if (cpu && pcie && i2s &&
|
|
++ bcma_aread32(cpu, BCMA_MIPS_OOBSELINA74) == 0x08060504 &&
|
|
++ bcma_aread32(pcie, BCMA_MIPS_OOBSELINA74) == 0x08060504 &&
|
|
++ bcma_aread32(i2s, BCMA_MIPS_OOBSELOUTA30) == 0x88) {
|
|
++ bcma_awrite32(cpu, BCMA_MIPS_OOBSELINA74, 0x07060504);
|
|
++ bcma_awrite32(pcie, BCMA_MIPS_OOBSELINA74, 0x07060504);
|
|
++ bcma_awrite32(i2s, BCMA_MIPS_OOBSELOUTA30, 0x87);
|
|
++ bcma_debug(bus,
|
|
++ "Moved i2s interrupt to oob line 7 instead of 8\n");
|
|
}
|
|
}
|
|
|
|
-@@ -209,7 +209,7 @@ void bcma_core_mips_init(struct bcma_drv
|
|
+@@ -209,48 +277,59 @@ void bcma_core_mips_init(struct bcma_drv
|
|
struct bcma_device *core;
|
|
bus = mcore->core->bus;
|
|
|
|
- pr_info("Initializing MIPS core...\n");
|
|
-+ bcma_info(bus, "Initializing MIPS core...\n");
|
|
++ if (mcore->setup_done)
|
|
++ return;
|
|
++
|
|
++ bcma_debug(bus, "Initializing MIPS core...\n");
|
|
|
|
- if (!mcore->setup_done)
|
|
- mcore->assigned_irqs = 1;
|
|
-@@ -244,7 +244,7 @@ void bcma_core_mips_init(struct bcma_drv
|
|
- break;
|
|
+- if (!mcore->setup_done)
|
|
+- mcore->assigned_irqs = 1;
|
|
++ bcma_core_mips_early_init(mcore);
|
|
+
|
|
+- /* Assign IRQs to all cores on the bus */
|
|
+- list_for_each_entry_reverse(core, &bus->cores, list) {
|
|
+- int mips_irq;
|
|
+- if (core->irq)
|
|
+- continue;
|
|
+-
|
|
+- mips_irq = bcma_core_mips_irq(core);
|
|
+- if (mips_irq > 4)
|
|
+- core->irq = 0;
|
|
+- else
|
|
+- core->irq = mips_irq + 2;
|
|
+- if (core->irq > 5)
|
|
+- continue;
|
|
+- switch (core->id.id) {
|
|
+- case BCMA_CORE_PCI:
|
|
+- case BCMA_CORE_PCIE:
|
|
+- case BCMA_CORE_ETHERNET:
|
|
+- case BCMA_CORE_ETHERNET_GBIT:
|
|
+- case BCMA_CORE_MAC_GBIT:
|
|
+- case BCMA_CORE_80211:
|
|
+- case BCMA_CORE_USB20_HOST:
|
|
+- /* These devices get their own IRQ line if available,
|
|
+- * the rest goes on IRQ0
|
|
+- */
|
|
+- if (mcore->assigned_irqs <= 4)
|
|
+- bcma_core_mips_set_irq(core,
|
|
+- mcore->assigned_irqs++);
|
|
+- break;
|
|
++ bcma_fix_i2s_irqflag(bus);
|
|
++
|
|
++ switch (bus->chipinfo.id) {
|
|
++ case BCMA_CHIP_ID_BCM4716:
|
|
++ case BCMA_CHIP_ID_BCM4748:
|
|
++ bcma_core_mips_set_irq_name(bus, 1, BCMA_CORE_80211, 0);
|
|
++ bcma_core_mips_set_irq_name(bus, 2, BCMA_CORE_MAC_GBIT, 0);
|
|
++ bcma_core_mips_set_irq_name(bus, 3, BCMA_CORE_USB20_HOST, 0);
|
|
++ bcma_core_mips_set_irq_name(bus, 4, BCMA_CORE_PCIE, 0);
|
|
++ bcma_core_mips_set_irq_name(bus, 0, BCMA_CORE_CHIPCOMMON, 0);
|
|
++ bcma_core_mips_set_irq_name(bus, 0, BCMA_CORE_I2S, 0);
|
|
++ break;
|
|
++ case BCMA_CHIP_ID_BCM5356:
|
|
++ case BCMA_CHIP_ID_BCM47162:
|
|
++ case BCMA_CHIP_ID_BCM53572:
|
|
++ bcma_core_mips_set_irq_name(bus, 1, BCMA_CORE_80211, 0);
|
|
++ bcma_core_mips_set_irq_name(bus, 2, BCMA_CORE_MAC_GBIT, 0);
|
|
++ bcma_core_mips_set_irq_name(bus, 0, BCMA_CORE_CHIPCOMMON, 0);
|
|
++ break;
|
|
++ case BCMA_CHIP_ID_BCM5357:
|
|
++ case BCMA_CHIP_ID_BCM4749:
|
|
++ bcma_core_mips_set_irq_name(bus, 1, BCMA_CORE_80211, 0);
|
|
++ bcma_core_mips_set_irq_name(bus, 2, BCMA_CORE_MAC_GBIT, 0);
|
|
++ bcma_core_mips_set_irq_name(bus, 3, BCMA_CORE_USB20_HOST, 0);
|
|
++ bcma_core_mips_set_irq_name(bus, 0, BCMA_CORE_CHIPCOMMON, 0);
|
|
++ bcma_core_mips_set_irq_name(bus, 0, BCMA_CORE_I2S, 0);
|
|
++ break;
|
|
++ case BCMA_CHIP_ID_BCM4706:
|
|
++ bcma_core_mips_set_irq_name(bus, 1, BCMA_CORE_PCIE, 0);
|
|
++ bcma_core_mips_set_irq_name(bus, 2, BCMA_CORE_4706_MAC_GBIT,
|
|
++ 0);
|
|
++ bcma_core_mips_set_irq_name(bus, 3, BCMA_CORE_PCIE, 1);
|
|
++ bcma_core_mips_set_irq_name(bus, 4, BCMA_CORE_USB20_HOST, 0);
|
|
++ bcma_core_mips_set_irq_name(bus, 0, BCMA_CORE_4706_CHIPCOMMON,
|
|
++ 0);
|
|
++ break;
|
|
++ default:
|
|
++ list_for_each_entry(core, &bus->cores, list) {
|
|
++ core->irq = bcma_core_irq(core);
|
|
}
|
|
++ bcma_err(bus,
|
|
++ "Unknown device (0x%x) found, can not configure IRQs\n",
|
|
++ bus->chipinfo.id);
|
|
}
|
|
- pr_info("IRQ reconfiguration done\n");
|
|
-+ bcma_info(bus, "IRQ reconfiguration done\n");
|
|
++ bcma_debug(bus, "IRQ reconfiguration done\n");
|
|
bcma_core_mips_dump_irq(bus);
|
|
|
|
- if (mcore->setup_done)
|
|
+- if (mcore->setup_done)
|
|
+- return;
|
|
+-
|
|
+- bcma_chipco_serial_init(&bus->drv_cc);
|
|
+- bcma_core_mips_flash_detect(mcore);
|
|
+ mcore->setup_done = true;
|
|
+ }
|
|
--- a/drivers/bcma/driver_pci.c
|
|
+++ b/drivers/bcma/driver_pci.c
|
|
@@ -2,8 +2,9 @@
|
|
@@ -756,7 +1741,7 @@
|
|
*
|
|
* Licensed under the GNU/GPL. See COPYING for details.
|
|
*/
|
|
-@@ -16,40 +17,39 @@
|
|
+@@ -16,120 +17,124 @@
|
|
* R/W ops.
|
|
**************************************************/
|
|
|
|
@@ -812,9 +1797,10 @@
|
|
+ v = pcicore_read32(pc, BCMA_CORE_PCI_MDIO_CONTROL);
|
|
+ if (v & BCMA_CORE_PCI_MDIOCTL_ACCESS_DONE)
|
|
break;
|
|
- msleep(1);
|
|
+- msleep(1);
|
|
++ usleep_range(1000, 2000);
|
|
}
|
|
-@@ -57,79 +57,84 @@ static void bcma_pcie_mdio_set_phy(struc
|
|
+ }
|
|
|
|
static u16 bcma_pcie_mdio_read(struct bcma_drv_pci *pc, u8 device, u8 address)
|
|
{
|
|
@@ -868,7 +1854,8 @@
|
|
+ ret = pcicore_read32(pc, BCMA_CORE_PCI_MDIO_DATA);
|
|
break;
|
|
}
|
|
- msleep(1);
|
|
+- msleep(1);
|
|
++ usleep_range(1000, 2000);
|
|
}
|
|
- pcicore_write32(pc, mdio_control, 0);
|
|
+ pcicore_write32(pc, BCMA_CORE_PCI_MDIO_CONTROL, 0);
|
|
@@ -923,7 +1910,8 @@
|
|
+ v = pcicore_read32(pc, BCMA_CORE_PCI_MDIO_CONTROL);
|
|
+ if (v & BCMA_CORE_PCI_MDIOCTL_ACCESS_DONE)
|
|
break;
|
|
- msleep(1);
|
|
+- msleep(1);
|
|
++ usleep_range(1000, 2000);
|
|
}
|
|
- pcicore_write32(pc, mdio_control, 0);
|
|
+ pcicore_write32(pc, BCMA_CORE_PCI_MDIO_CONTROL, 0);
|
|
@@ -1103,7 +2091,7 @@
|
|
+EXPORT_SYMBOL_GPL(bcma_core_pci_extend_L1timer);
|
|
--- a/drivers/bcma/driver_pci_host.c
|
|
+++ b/drivers/bcma/driver_pci_host.c
|
|
-@@ -2,13 +2,592 @@
|
|
+@@ -2,13 +2,616 @@
|
|
* Broadcom specific AMBA
|
|
* PCI Core in hostmode
|
|
*
|
|
@@ -1140,11 +2128,6 @@
|
|
+ chipid_top != 0x5300)
|
|
+ return false;
|
|
+
|
|
-+ if (bus->sprom.boardflags_lo & BCMA_CORE_PCI_BFL_NOPCI) {
|
|
-+ bcma_info(bus, "This PCI core is disabled and not working\n");
|
|
-+ return false;
|
|
-+ }
|
|
-+
|
|
+ bcma_core_enable(pc->core, 0);
|
|
+
|
|
+ return !mips_busprobe32(tmp, pc->core->io_addr);
|
|
@@ -1189,13 +2172,11 @@
|
|
+out:
|
|
+ return addr;
|
|
+}
|
|
-
|
|
--void bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc)
|
|
++
|
|
+static int bcma_extpci_read_config(struct bcma_drv_pci *pc, unsigned int dev,
|
|
+ unsigned int func, unsigned int off,
|
|
+ void *buf, int len)
|
|
- {
|
|
-- pr_err("No support for PCI core in hostmode yet\n");
|
|
++{
|
|
+ int err = -EINVAL;
|
|
+ u32 addr, val;
|
|
+ void __iomem *mmio = 0;
|
|
@@ -1206,19 +2187,19 @@
|
|
+ if (dev == 0) {
|
|
+ /* we support only two functions on device 0 */
|
|
+ if (func > 1)
|
|
-+ return -EINVAL;
|
|
++ goto out;
|
|
+
|
|
+ /* accesses to config registers with offsets >= 256
|
|
+ * requires indirect access.
|
|
+ */
|
|
+ if (off >= PCI_CONFIG_SPACE_SIZE) {
|
|
+ addr = (func << 12);
|
|
-+ addr |= (off & 0x0FFF);
|
|
++ addr |= (off & 0x0FFC);
|
|
+ val = bcma_pcie_read_config(pc, addr);
|
|
+ } else {
|
|
+ addr = BCMA_CORE_PCI_PCICFG0;
|
|
+ addr |= (func << 8);
|
|
-+ addr |= (off & 0xfc);
|
|
++ addr |= (off & 0xFC);
|
|
+ val = pcicore_read32(pc, addr);
|
|
+ }
|
|
+ } else {
|
|
@@ -1231,11 +2212,9 @@
|
|
+ goto out;
|
|
+
|
|
+ if (mips_busprobe32(val, mmio)) {
|
|
-+ val = 0xffffffff;
|
|
++ val = 0xFFFFFFFF;
|
|
+ goto unmap;
|
|
+ }
|
|
-+
|
|
-+ val = readl(mmio);
|
|
+ }
|
|
+ val >>= (8 * (off & 3));
|
|
+
|
|
@@ -1257,13 +2236,15 @@
|
|
+out:
|
|
+ return err;
|
|
+}
|
|
-+
|
|
+
|
|
+-void bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc)
|
|
+static int bcma_extpci_write_config(struct bcma_drv_pci *pc, unsigned int dev,
|
|
+ unsigned int func, unsigned int off,
|
|
+ const void *buf, int len)
|
|
-+{
|
|
+ {
|
|
+- pr_err("No support for PCI core in hostmode yet\n");
|
|
+ int err = -EINVAL;
|
|
-+ u32 addr = 0, val = 0;
|
|
++ u32 addr, val;
|
|
+ void __iomem *mmio = 0;
|
|
+ u16 chipid = pc->core->bus->chipinfo.id;
|
|
+
|
|
@@ -1271,16 +2252,22 @@
|
|
+ if (unlikely(len != 1 && len != 2 && len != 4))
|
|
+ goto out;
|
|
+ if (dev == 0) {
|
|
++ /* we support only two functions on device 0 */
|
|
++ if (func > 1)
|
|
++ goto out;
|
|
++
|
|
+ /* accesses to config registers with offsets >= 256
|
|
+ * requires indirect access.
|
|
+ */
|
|
-+ if (off < PCI_CONFIG_SPACE_SIZE) {
|
|
-+ addr = pc->core->addr + BCMA_CORE_PCI_PCICFG0;
|
|
++ if (off >= PCI_CONFIG_SPACE_SIZE) {
|
|
++ addr = (func << 12);
|
|
++ addr |= (off & 0x0FFC);
|
|
++ val = bcma_pcie_read_config(pc, addr);
|
|
++ } else {
|
|
++ addr = BCMA_CORE_PCI_PCICFG0;
|
|
+ addr |= (func << 8);
|
|
-+ addr |= (off & 0xfc);
|
|
-+ mmio = ioremap_nocache(addr, sizeof(val));
|
|
-+ if (!mmio)
|
|
-+ goto out;
|
|
++ addr |= (off & 0xFC);
|
|
++ val = pcicore_read32(pc, addr);
|
|
+ }
|
|
+ } else {
|
|
+ addr = bcma_get_cfgspace_addr(pc, dev, func, off);
|
|
@@ -1292,19 +2279,17 @@
|
|
+ goto out;
|
|
+
|
|
+ if (mips_busprobe32(val, mmio)) {
|
|
-+ val = 0xffffffff;
|
|
++ val = 0xFFFFFFFF;
|
|
+ goto unmap;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ switch (len) {
|
|
+ case 1:
|
|
-+ val = readl(mmio);
|
|
+ val &= ~(0xFF << (8 * (off & 3)));
|
|
+ val |= *((const u8 *)buf) << (8 * (off & 3));
|
|
+ break;
|
|
+ case 2:
|
|
-+ val = readl(mmio);
|
|
+ val &= ~(0xFFFF << (8 * (off & 3)));
|
|
+ val |= *((const u16 *)buf) << (8 * (off & 3));
|
|
+ break;
|
|
@@ -1312,13 +2297,14 @@
|
|
+ val = *((const u32 *)buf);
|
|
+ break;
|
|
+ }
|
|
-+ if (dev == 0 && !addr) {
|
|
++ if (dev == 0) {
|
|
+ /* accesses to config registers with offsets >= 256
|
|
+ * requires indirect access.
|
|
+ */
|
|
-+ addr = (func << 12);
|
|
-+ addr |= (off & 0x0FFF);
|
|
-+ bcma_pcie_write_config(pc, addr, val);
|
|
++ if (off >= PCI_CONFIG_SPACE_SIZE)
|
|
++ bcma_pcie_write_config(pc, addr, val);
|
|
++ else
|
|
++ pcicore_write32(pc, addr, val);
|
|
+ } else {
|
|
+ writel(val, mmio);
|
|
+
|
|
@@ -1389,7 +2375,7 @@
|
|
+ /* check for Header type 0 */
|
|
+ bcma_extpci_read_config(pc, dev, func, PCI_HEADER_TYPE, &byte_val,
|
|
+ sizeof(u8));
|
|
-+ if ((byte_val & 0x7f) != PCI_HEADER_TYPE_NORMAL)
|
|
++ if ((byte_val & 0x7F) != PCI_HEADER_TYPE_NORMAL)
|
|
+ return cap_ptr;
|
|
+
|
|
+ /* check if the capability pointer field exists */
|
|
@@ -1503,12 +2489,19 @@
|
|
+
|
|
+ bcma_info(bus, "PCIEcore in host mode found\n");
|
|
+
|
|
++ if (bus->sprom.boardflags_lo & BCMA_CORE_PCI_BFL_NOPCI) {
|
|
++ bcma_info(bus, "This PCIE core is disabled and not working\n");
|
|
++ return;
|
|
++ }
|
|
++
|
|
+ pc_host = kzalloc(sizeof(*pc_host), GFP_KERNEL);
|
|
+ if (!pc_host) {
|
|
+ bcma_err(bus, "can not allocate memory");
|
|
+ return;
|
|
+ }
|
|
+
|
|
++ spin_lock_init(&pc_host->cfgspace_lock);
|
|
++
|
|
+ pc->host_controller = pc_host;
|
|
+ pc_host->pci_controller.io_resource = &pc_host->io_resource;
|
|
+ pc_host->pci_controller.mem_resource = &pc_host->mem_resource;
|
|
@@ -1532,9 +2525,9 @@
|
|
+ pc_host->io_resource.flags = IORESOURCE_IO | IORESOURCE_PCI_FIXED;
|
|
+
|
|
+ /* Reset RC */
|
|
-+ udelay(3000);
|
|
++ usleep_range(3000, 5000);
|
|
+ pcicore_write32(pc, BCMA_CORE_PCI_CTL, BCMA_CORE_PCI_CTL_RST_OE);
|
|
-+ udelay(1000);
|
|
++ msleep(50);
|
|
+ pcicore_write32(pc, BCMA_CORE_PCI_CTL, BCMA_CORE_PCI_CTL_RST |
|
|
+ BCMA_CORE_PCI_CTL_RST_OE);
|
|
+
|
|
@@ -1559,6 +2552,8 @@
|
|
+ pc_host->mem_resource.start = BCMA_SOC_PCI_MEM;
|
|
+ pc_host->mem_resource.end = BCMA_SOC_PCI_MEM +
|
|
+ BCMA_SOC_PCI_MEM_SZ - 1;
|
|
++ pc_host->io_resource.start = 0x100;
|
|
++ pc_host->io_resource.end = 0x47F;
|
|
+ pci_membase_1G = BCMA_SOC_PCIE_DMA_H32;
|
|
+ pcicore_write32(pc, BCMA_CORE_PCI_SBTOPCI0,
|
|
+ tmp | BCMA_SOC_PCI_MEM);
|
|
@@ -1566,6 +2561,8 @@
|
|
+ pc_host->mem_resource.start = BCMA_SOC_PCI1_MEM;
|
|
+ pc_host->mem_resource.end = BCMA_SOC_PCI1_MEM +
|
|
+ BCMA_SOC_PCI_MEM_SZ - 1;
|
|
++ pc_host->io_resource.start = 0x480;
|
|
++ pc_host->io_resource.end = 0x7FF;
|
|
+ pci_membase_1G = BCMA_SOC_PCIE1_DMA_H32;
|
|
+ pc_host->host_cfg_addr = BCMA_SOC_PCI1_CFG;
|
|
+ pcicore_write32(pc, BCMA_CORE_PCI_SBTOPCI0,
|
|
@@ -1588,10 +2585,21 @@
|
|
+ * before issuing configuration requests to PCI Express
|
|
+ * devices.
|
|
+ */
|
|
-+ udelay(100000);
|
|
++ msleep(100);
|
|
+
|
|
+ bcma_core_pci_enable_crs(pc);
|
|
+
|
|
++ if (bus->chipinfo.id == BCMA_CHIP_ID_BCM4706 ||
|
|
++ bus->chipinfo.id == BCMA_CHIP_ID_BCM4716) {
|
|
++ u16 val16;
|
|
++ bcma_extpci_read_config(pc, 0, 0, BCMA_CORE_PCI_CFG_DEVCTRL,
|
|
++ &val16, sizeof(val16));
|
|
++ val16 |= (2 << 5); /* Max payload size of 512 */
|
|
++ val16 |= (2 << 12); /* MRRS 512 */
|
|
++ bcma_extpci_write_config(pc, 0, 0, BCMA_CORE_PCI_CFG_DEVCTRL,
|
|
++ &val16, sizeof(val16));
|
|
++ }
|
|
++
|
|
+ /* Enable PCI bridge BAR0 memory & master access */
|
|
+ tmp = PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY;
|
|
+ bcma_extpci_write_config(pc, 0, 0, PCI_COMMAND, &tmp, sizeof(tmp));
|
|
@@ -1608,7 +2616,7 @@
|
|
+ set_io_port_base(pc_host->pci_controller.io_map_base);
|
|
+ /* Give some time to the PCI controller to configure itself with the new
|
|
+ * values. Not waiting at this point causes crashes of the machine. */
|
|
-+ mdelay(10);
|
|
++ usleep_range(10000, 15000);
|
|
+ register_pci_controller(&pc_host->pci_controller);
|
|
+ return;
|
|
+}
|
|
@@ -1641,7 +2649,7 @@
|
|
+static void bcma_core_pci_fixup_addresses(struct pci_dev *dev)
|
|
+{
|
|
+ struct resource *res;
|
|
-+ int pos;
|
|
++ int pos, err;
|
|
+
|
|
+ if (dev->bus->ops->read != bcma_core_pci_hostmode_read_config) {
|
|
+ /* This is not a device on the PCI-core bridge. */
|
|
@@ -1654,8 +2662,12 @@
|
|
+
|
|
+ for (pos = 0; pos < 6; pos++) {
|
|
+ res = &dev->resource[pos];
|
|
-+ if (res->flags & (IORESOURCE_IO | IORESOURCE_MEM))
|
|
-+ pci_assign_resource(dev, pos);
|
|
++ if (res->flags & (IORESOURCE_IO | IORESOURCE_MEM)) {
|
|
++ err = pci_assign_resource(dev, pos);
|
|
++ if (err)
|
|
++ pr_err("PCI: Problem fixing up the addresses on %s\n",
|
|
++ pci_name(dev));
|
|
++ }
|
|
+ }
|
|
+}
|
|
+DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, bcma_core_pci_fixup_addresses);
|
|
@@ -1676,7 +2688,7 @@
|
|
+ pr_info("PCI: Fixing up device %s\n", pci_name(dev));
|
|
+
|
|
+ /* Fix up interrupt lines */
|
|
-+ dev->irq = bcma_core_mips_irq(pc_host->pdev->core) + 2;
|
|
++ dev->irq = bcma_core_irq(pc_host->pdev->core);
|
|
+ pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
|
|
+
|
|
+ return 0;
|
|
@@ -1695,7 +2707,7 @@
|
|
+
|
|
+ pc_host = container_of(dev->bus->ops, struct bcma_drv_pci_host,
|
|
+ pci_ops);
|
|
-+ return bcma_core_mips_irq(pc_host->pdev->core) + 2;
|
|
++ return bcma_core_irq(pc_host->pdev->core);
|
|
}
|
|
+EXPORT_SYMBOL(bcma_core_pci_pcibios_map_irq);
|
|
--- a/drivers/bcma/host_pci.c
|
|
@@ -1709,7 +2721,39 @@
|
|
}
|
|
|
|
/* Provides access to the requested core. Returns base offset that has to be
|
|
-@@ -154,8 +154,8 @@ const struct bcma_host_ops bcma_host_pci
|
|
+@@ -77,8 +77,8 @@ static void bcma_host_pci_write32(struct
|
|
+ }
|
|
+
|
|
+ #ifdef CONFIG_BCMA_BLOCKIO
|
|
+-void bcma_host_pci_block_read(struct bcma_device *core, void *buffer,
|
|
+- size_t count, u16 offset, u8 reg_width)
|
|
++static void bcma_host_pci_block_read(struct bcma_device *core, void *buffer,
|
|
++ size_t count, u16 offset, u8 reg_width)
|
|
+ {
|
|
+ void __iomem *addr = core->bus->mmio + offset;
|
|
+ if (core->bus->mapped_core != core)
|
|
+@@ -100,8 +100,9 @@ void bcma_host_pci_block_read(struct bcm
|
|
+ }
|
|
+ }
|
|
+
|
|
+-void bcma_host_pci_block_write(struct bcma_device *core, const void *buffer,
|
|
+- size_t count, u16 offset, u8 reg_width)
|
|
++static void bcma_host_pci_block_write(struct bcma_device *core,
|
|
++ const void *buffer, size_t count,
|
|
++ u16 offset, u8 reg_width)
|
|
+ {
|
|
+ void __iomem *addr = core->bus->mmio + offset;
|
|
+ if (core->bus->mapped_core != core)
|
|
+@@ -139,7 +140,7 @@ static void bcma_host_pci_awrite32(struc
|
|
+ iowrite32(value, core->bus->mmio + (1 * BCMA_CORE_SIZE) + offset);
|
|
+ }
|
|
+
|
|
+-const struct bcma_host_ops bcma_host_pci_ops = {
|
|
++static const struct bcma_host_ops bcma_host_pci_ops = {
|
|
+ .read8 = bcma_host_pci_read8,
|
|
+ .read16 = bcma_host_pci_read16,
|
|
+ .read32 = bcma_host_pci_read32,
|
|
+@@ -154,8 +155,8 @@ const struct bcma_host_ops bcma_host_pci
|
|
.awrite32 = bcma_host_pci_awrite32,
|
|
};
|
|
|
|
@@ -1720,7 +2764,7 @@
|
|
{
|
|
struct bcma_bus *bus;
|
|
int err = -ENOMEM;
|
|
-@@ -188,7 +188,7 @@ static int bcma_host_pci_probe(struct pc
|
|
+@@ -188,7 +189,7 @@ static int bcma_host_pci_probe(struct pc
|
|
|
|
/* SSB needed additional powering up, do we have any AMBA PCI cards? */
|
|
if (!pci_is_pcie(dev))
|
|
@@ -1729,7 +2773,7 @@
|
|
|
|
/* Map MMIO */
|
|
err = -ENOMEM;
|
|
-@@ -201,6 +201,9 @@ static int bcma_host_pci_probe(struct pc
|
|
+@@ -201,6 +202,9 @@ static int bcma_host_pci_probe(struct pc
|
|
bus->hosttype = BCMA_HOSTTYPE_PCI;
|
|
bus->ops = &bcma_host_pci_ops;
|
|
|
|
@@ -1739,7 +2783,7 @@
|
|
/* Register */
|
|
err = bcma_bus_register(bus);
|
|
if (err)
|
|
-@@ -222,7 +225,7 @@ err_kfree_bus:
|
|
+@@ -222,7 +226,7 @@ err_kfree_bus:
|
|
return err;
|
|
}
|
|
|
|
@@ -1748,15 +2792,40 @@
|
|
{
|
|
struct bcma_bus *bus = pci_get_drvdata(dev);
|
|
|
|
-@@ -265,6 +268,7 @@ static SIMPLE_DEV_PM_OPS(bcma_pm_ops, bc
|
|
+@@ -234,7 +238,7 @@ static void bcma_host_pci_remove(struct
|
|
+ pci_set_drvdata(dev, NULL);
|
|
+ }
|
|
|
|
+-#ifdef CONFIG_PM
|
|
++#ifdef CONFIG_PM_SLEEP
|
|
+ static int bcma_host_pci_suspend(struct device *dev)
|
|
+ {
|
|
+ struct pci_dev *pdev = to_pci_dev(dev);
|
|
+@@ -257,17 +261,21 @@ static SIMPLE_DEV_PM_OPS(bcma_pm_ops, bc
|
|
+ bcma_host_pci_resume);
|
|
+ #define BCMA_PM_OPS (&bcma_pm_ops)
|
|
+
|
|
+-#else /* CONFIG_PM */
|
|
++#else /* CONFIG_PM_SLEEP */
|
|
+
|
|
+ #define BCMA_PM_OPS NULL
|
|
+
|
|
+-#endif /* CONFIG_PM */
|
|
++#endif /* CONFIG_PM_SLEEP */
|
|
+
|
|
static DEFINE_PCI_DEVICE_TABLE(bcma_pci_bridge_tbl) = {
|
|
{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x0576) },
|
|
+ { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 43224) },
|
|
{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4331) },
|
|
{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4353) },
|
|
{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4357) },
|
|
-@@ -277,7 +281,7 @@ static struct pci_driver bcma_pci_bridge
|
|
++ { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4358) },
|
|
++ { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4359) },
|
|
++ { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4365) },
|
|
+ { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4727) },
|
|
+ { 0, },
|
|
+ };
|
|
+@@ -277,7 +285,7 @@ static struct pci_driver bcma_pci_bridge
|
|
.name = "bcma-pci-bridge",
|
|
.id_table = bcma_pci_bridge_tbl,
|
|
.probe = bcma_host_pci_probe,
|
|
@@ -1765,6 +2834,17 @@
|
|
.driver.pm = BCMA_PM_OPS,
|
|
};
|
|
|
|
+--- a/drivers/bcma/host_soc.c
|
|
++++ b/drivers/bcma/host_soc.c
|
|
+@@ -143,7 +143,7 @@ static void bcma_host_soc_awrite32(struc
|
|
+ writel(value, core->io_wrap + offset);
|
|
+ }
|
|
+
|
|
+-const struct bcma_host_ops bcma_host_soc_ops = {
|
|
++static const struct bcma_host_ops bcma_host_soc_ops = {
|
|
+ .read8 = bcma_host_soc_read8,
|
|
+ .read16 = bcma_host_soc_read16,
|
|
+ .read32 = bcma_host_soc_read32,
|
|
--- a/drivers/bcma/main.c
|
|
+++ b/drivers/bcma/main.c
|
|
@@ -13,6 +13,12 @@
|
|
@@ -1796,15 +2876,46 @@
|
|
{
|
|
struct bcma_device *core;
|
|
|
|
-@@ -65,6 +78,7 @@ static struct bcma_device *bcma_find_cor
|
|
+@@ -65,6 +78,38 @@ static struct bcma_device *bcma_find_cor
|
|
}
|
|
return NULL;
|
|
}
|
|
+EXPORT_SYMBOL_GPL(bcma_find_core);
|
|
++
|
|
++struct bcma_device *bcma_find_core_unit(struct bcma_bus *bus, u16 coreid,
|
|
++ u8 unit)
|
|
++{
|
|
++ struct bcma_device *core;
|
|
++
|
|
++ list_for_each_entry(core, &bus->cores, list) {
|
|
++ if (core->id.id == coreid && core->core_unit == unit)
|
|
++ return core;
|
|
++ }
|
|
++ return NULL;
|
|
++}
|
|
++
|
|
++bool bcma_wait_value(struct bcma_device *core, u16 reg, u32 mask, u32 value,
|
|
++ int timeout)
|
|
++{
|
|
++ unsigned long deadline = jiffies + timeout;
|
|
++ u32 val;
|
|
++
|
|
++ do {
|
|
++ val = bcma_read32(core, reg);
|
|
++ if ((val & mask) == value)
|
|
++ return true;
|
|
++ cpu_relax();
|
|
++ udelay(10);
|
|
++ } while (!time_after_eq(jiffies, deadline));
|
|
++
|
|
++ bcma_warn(core->bus, "Timeout waiting for register 0x%04X!\n", reg);
|
|
++
|
|
++ return false;
|
|
++}
|
|
|
|
static void bcma_release_core_dev(struct device *dev)
|
|
{
|
|
-@@ -84,16 +98,18 @@ static int bcma_register_cores(struct bc
|
|
+@@ -84,16 +129,23 @@ static int bcma_register_cores(struct bc
|
|
list_for_each_entry(core, &bus->cores, list) {
|
|
/* We support that cores ourself */
|
|
switch (core->id.id) {
|
|
@@ -1817,6 +2928,11 @@
|
|
continue;
|
|
}
|
|
|
|
++ /* Only first GMAC core on BCM4706 is connected and working */
|
|
++ if (core->id.id == BCMA_CORE_4706_MAC_GBIT &&
|
|
++ core->core_unit > 0)
|
|
++ continue;
|
|
++
|
|
core->dev.release = bcma_release_core_dev;
|
|
core->dev.bus = &bcma_bus_type;
|
|
- dev_set_name(&core->dev, "bcma%d:%d", 0/*bus->num*/, dev_id);
|
|
@@ -1824,7 +2940,7 @@
|
|
|
|
switch (bus->hosttype) {
|
|
case BCMA_HOSTTYPE_PCI:
|
|
-@@ -111,8 +127,9 @@ static int bcma_register_cores(struct bc
|
|
+@@ -111,41 +163,75 @@ static int bcma_register_cores(struct bc
|
|
|
|
err = device_register(&core->dev);
|
|
if (err) {
|
|
@@ -1836,10 +2952,39 @@
|
|
continue;
|
|
}
|
|
core->dev_registered = true;
|
|
-@@ -132,20 +149,24 @@ static void bcma_unregister_cores(struct
|
|
+ dev_id++;
|
|
}
|
|
+
|
|
++ err = bcma_gpio_init(&bus->drv_cc);
|
|
++ if (err == -ENOTSUPP)
|
|
++ bcma_debug(bus, "GPIO driver not activated\n");
|
|
++ else if (err)
|
|
++ bcma_err(bus, "Error registering GPIO driver: %i\n", err);
|
|
++
|
|
++ if (bus->hosttype == BCMA_HOSTTYPE_SOC) {
|
|
++ err = bcma_chipco_watchdog_register(&bus->drv_cc);
|
|
++ if (err)
|
|
++ bcma_err(bus, "Error registering watchdog driver\n");
|
|
++ }
|
|
++
|
|
+ return 0;
|
|
}
|
|
|
|
+ static void bcma_unregister_cores(struct bcma_bus *bus)
|
|
+ {
|
|
+- struct bcma_device *core;
|
|
++ struct bcma_device *core, *tmp;
|
|
+
|
|
+- list_for_each_entry(core, &bus->cores, list) {
|
|
++ list_for_each_entry_safe(core, tmp, &bus->cores, list) {
|
|
++ list_del(&core->list);
|
|
+ if (core->dev_registered)
|
|
+ device_unregister(&core->dev);
|
|
+ }
|
|
++ if (bus->hosttype == BCMA_HOSTTYPE_SOC)
|
|
++ platform_device_unregister(bus->drv_cc.watchdog);
|
|
+ }
|
|
+
|
|
-int bcma_bus_register(struct bcma_bus *bus)
|
|
+int __devinit bcma_bus_register(struct bcma_bus *bus)
|
|
{
|
|
@@ -1858,31 +3003,58 @@
|
|
return -1;
|
|
}
|
|
|
|
++ /* Early init CC core */
|
|
++ core = bcma_find_core(bus, bcma_cc_core_id(bus));
|
|
++ if (core) {
|
|
++ bus->drv_cc.core = core;
|
|
++ bcma_core_chipcommon_early_init(&bus->drv_cc);
|
|
++ }
|
|
++
|
|
++ /* Try to get SPROM */
|
|
++ err = bcma_sprom_get(bus);
|
|
++ if (err == -ENOENT) {
|
|
++ bcma_err(bus, "No SPROM available\n");
|
|
++ } else if (err)
|
|
++ bcma_err(bus, "Failed to get SPROM: %d\n", err);
|
|
++
|
|
/* Init CC core */
|
|
- core = bcma_find_core(bus, BCMA_CORE_CHIPCOMMON);
|
|
+ core = bcma_find_core(bus, bcma_cc_core_id(bus));
|
|
if (core) {
|
|
bus->drv_cc.core = core;
|
|
bcma_core_chipcommon_init(&bus->drv_cc);
|
|
-@@ -165,17 +186,24 @@ int bcma_bus_register(struct bcma_bus *b
|
|
- bcma_core_pci_init(&bus->drv_pci);
|
|
+@@ -159,30 +245,54 @@ int bcma_bus_register(struct bcma_bus *b
|
|
}
|
|
|
|
+ /* Init PCIE core */
|
|
+- core = bcma_find_core(bus, BCMA_CORE_PCIE);
|
|
++ core = bcma_find_core_unit(bus, BCMA_CORE_PCIE, 0);
|
|
+ if (core) {
|
|
+- bus->drv_pci.core = core;
|
|
+- bcma_core_pci_init(&bus->drv_pci);
|
|
++ bus->drv_pci[0].core = core;
|
|
++ bcma_core_pci_init(&bus->drv_pci[0]);
|
|
+ }
|
|
+
|
|
+- /* Try to get SPROM */
|
|
+- err = bcma_sprom_get(bus);
|
|
+- if (err == -ENOENT) {
|
|
+- pr_err("No SPROM available\n");
|
|
+- } else if (err)
|
|
+- pr_err("Failed to get SPROM: %d\n", err);
|
|
++ /* Init PCIE core */
|
|
++ core = bcma_find_core_unit(bus, BCMA_CORE_PCIE, 1);
|
|
++ if (core) {
|
|
++ bus->drv_pci[1].core = core;
|
|
++ bcma_core_pci_init(&bus->drv_pci[1]);
|
|
++ }
|
|
++
|
|
+ /* Init GBIT MAC COMMON core */
|
|
+ core = bcma_find_core(bus, BCMA_CORE_4706_MAC_GBIT_COMMON);
|
|
+ if (core) {
|
|
+ bus->drv_gmac_cmn.core = core;
|
|
+ bcma_core_gmac_cmn_init(&bus->drv_gmac_cmn);
|
|
+ }
|
|
-+
|
|
- /* Try to get SPROM */
|
|
- err = bcma_sprom_get(bus);
|
|
- if (err == -ENOENT) {
|
|
-- pr_err("No SPROM available\n");
|
|
-+ bcma_err(bus, "No SPROM available\n");
|
|
- } else if (err)
|
|
-- pr_err("Failed to get SPROM: %d\n", err);
|
|
-+ bcma_err(bus, "Failed to get SPROM: %d\n", err);
|
|
|
|
/* Register found cores */
|
|
bcma_register_cores(bus);
|
|
@@ -1892,7 +3064,31 @@
|
|
|
|
return 0;
|
|
}
|
|
-@@ -196,14 +224,14 @@ int __init bcma_bus_early_register(struc
|
|
+
|
|
+ void bcma_bus_unregister(struct bcma_bus *bus)
|
|
+ {
|
|
++ struct bcma_device *cores[3];
|
|
++ int err;
|
|
++
|
|
++ err = bcma_gpio_unregister(&bus->drv_cc);
|
|
++ if (err == -EBUSY)
|
|
++ bcma_err(bus, "Some GPIOs are still in use.\n");
|
|
++ else if (err)
|
|
++ bcma_err(bus, "Can not unregister GPIO driver: %i\n", err);
|
|
++
|
|
++ cores[0] = bcma_find_core(bus, BCMA_CORE_MIPS_74K);
|
|
++ cores[1] = bcma_find_core(bus, BCMA_CORE_PCIE);
|
|
++ cores[2] = bcma_find_core(bus, BCMA_CORE_4706_MAC_GBIT_COMMON);
|
|
++
|
|
+ bcma_unregister_cores(bus);
|
|
++
|
|
++ kfree(cores[2]);
|
|
++ kfree(cores[1]);
|
|
++ kfree(cores[0]);
|
|
+ }
|
|
+
|
|
+ int __init bcma_bus_early_register(struct bcma_bus *bus,
|
|
+@@ -196,14 +306,14 @@ int __init bcma_bus_early_register(struc
|
|
bcma_init_bus(bus);
|
|
|
|
match.manuf = BCMA_MANUF_BCM;
|
|
@@ -1909,7 +3105,7 @@
|
|
return -1;
|
|
}
|
|
|
|
-@@ -215,12 +243,12 @@ int __init bcma_bus_early_register(struc
|
|
+@@ -215,25 +325,25 @@ int __init bcma_bus_early_register(struc
|
|
/* Scan for mips core */
|
|
err = bcma_bus_scan_early(bus, &match, core_mips);
|
|
if (err) {
|
|
@@ -1918,22 +3114,31 @@
|
|
return -1;
|
|
}
|
|
|
|
- /* Init CC core */
|
|
+- /* Init CC core */
|
|
- core = bcma_find_core(bus, BCMA_CORE_CHIPCOMMON);
|
|
++ /* Early init CC core */
|
|
+ core = bcma_find_core(bus, bcma_cc_core_id(bus));
|
|
if (core) {
|
|
bus->drv_cc.core = core;
|
|
- bcma_core_chipcommon_init(&bus->drv_cc);
|
|
-@@ -233,7 +261,7 @@ int __init bcma_bus_early_register(struc
|
|
- bcma_core_mips_init(&bus->drv_mips);
|
|
+- bcma_core_chipcommon_init(&bus->drv_cc);
|
|
++ bcma_core_chipcommon_early_init(&bus->drv_cc);
|
|
}
|
|
|
|
+- /* Init MIPS core */
|
|
++ /* Early init MIPS core */
|
|
+ core = bcma_find_core(bus, BCMA_CORE_MIPS_74K);
|
|
+ if (core) {
|
|
+ bus->drv_mips.core = core;
|
|
+- bcma_core_mips_init(&bus->drv_mips);
|
|
++ bcma_core_mips_early_init(&bus->drv_mips);
|
|
+ }
|
|
+
|
|
- pr_info("Early bus registered\n");
|
|
+ bcma_info(bus, "Early bus registered\n");
|
|
|
|
return 0;
|
|
}
|
|
-@@ -259,8 +287,7 @@ int bcma_bus_resume(struct bcma_bus *bus
|
|
+@@ -259,8 +369,7 @@ int bcma_bus_resume(struct bcma_bus *bus
|
|
struct bcma_device *core;
|
|
|
|
/* Init CC core */
|
|
@@ -1999,8 +3204,12 @@
|
|
{ BCMA_CORE_MAC_GBIT, "GBit MAC" },
|
|
{ BCMA_CORE_DDR12_MEM_CTL, "DDR1/DDR2 Memory Controller" },
|
|
{ BCMA_CORE_PCIE_RC, "PCIe Root Complex" },
|
|
-@@ -79,16 +86,41 @@ struct bcma_device_id_name bcma_device_n
|
|
+@@ -77,18 +84,45 @@ struct bcma_device_id_name bcma_device_n
|
|
+ { BCMA_CORE_I2S, "I2S" },
|
|
+ { BCMA_CORE_SDR_DDR1_MEM_CTL, "SDR/DDR1 Memory Controller" },
|
|
{ BCMA_CORE_SHIM, "SHIM" },
|
|
++ { BCMA_CORE_PCIE2, "PCIe Gen2" },
|
|
++ { BCMA_CORE_ARM_CR4, "ARM CR4" },
|
|
{ BCMA_CORE_DEFAULT, "Default" },
|
|
};
|
|
-const char *bcma_device_name(struct bcma_device_id *id)
|
|
@@ -2038,17 +3247,84 @@
|
|
+ break;
|
|
+ default:
|
|
+ return "UNKNOWN";
|
|
-+ }
|
|
+ }
|
|
+
|
|
+ for (i = 0; i < size; i++) {
|
|
+ if (names[i].id == id->id)
|
|
+ return names[i].name;
|
|
- }
|
|
++ }
|
|
+
|
|
return "UNKNOWN";
|
|
}
|
|
|
|
-@@ -212,6 +244,17 @@ static struct bcma_device *bcma_find_cor
|
|
+@@ -105,19 +139,19 @@ static void bcma_scan_switch_core(struct
|
|
+ addr);
|
|
+ }
|
|
+
|
|
+-static u32 bcma_erom_get_ent(struct bcma_bus *bus, u32 **eromptr)
|
|
++static u32 bcma_erom_get_ent(struct bcma_bus *bus, u32 __iomem **eromptr)
|
|
+ {
|
|
+ u32 ent = readl(*eromptr);
|
|
+ (*eromptr)++;
|
|
+ return ent;
|
|
+ }
|
|
+
|
|
+-static void bcma_erom_push_ent(u32 **eromptr)
|
|
++static void bcma_erom_push_ent(u32 __iomem **eromptr)
|
|
+ {
|
|
+ (*eromptr)--;
|
|
+ }
|
|
+
|
|
+-static s32 bcma_erom_get_ci(struct bcma_bus *bus, u32 **eromptr)
|
|
++static s32 bcma_erom_get_ci(struct bcma_bus *bus, u32 __iomem **eromptr)
|
|
+ {
|
|
+ u32 ent = bcma_erom_get_ent(bus, eromptr);
|
|
+ if (!(ent & SCAN_ER_VALID))
|
|
+@@ -127,14 +161,14 @@ static s32 bcma_erom_get_ci(struct bcma_
|
|
+ return ent;
|
|
+ }
|
|
+
|
|
+-static bool bcma_erom_is_end(struct bcma_bus *bus, u32 **eromptr)
|
|
++static bool bcma_erom_is_end(struct bcma_bus *bus, u32 __iomem **eromptr)
|
|
+ {
|
|
+ u32 ent = bcma_erom_get_ent(bus, eromptr);
|
|
+ bcma_erom_push_ent(eromptr);
|
|
+ return (ent == (SCAN_ER_TAG_END | SCAN_ER_VALID));
|
|
+ }
|
|
+
|
|
+-static bool bcma_erom_is_bridge(struct bcma_bus *bus, u32 **eromptr)
|
|
++static bool bcma_erom_is_bridge(struct bcma_bus *bus, u32 __iomem **eromptr)
|
|
+ {
|
|
+ u32 ent = bcma_erom_get_ent(bus, eromptr);
|
|
+ bcma_erom_push_ent(eromptr);
|
|
+@@ -143,7 +177,7 @@ static bool bcma_erom_is_bridge(struct b
|
|
+ ((ent & SCAN_ADDR_TYPE) == SCAN_ADDR_TYPE_BRIDGE));
|
|
+ }
|
|
+
|
|
+-static void bcma_erom_skip_component(struct bcma_bus *bus, u32 **eromptr)
|
|
++static void bcma_erom_skip_component(struct bcma_bus *bus, u32 __iomem **eromptr)
|
|
+ {
|
|
+ u32 ent;
|
|
+ while (1) {
|
|
+@@ -157,7 +191,7 @@ static void bcma_erom_skip_component(str
|
|
+ bcma_erom_push_ent(eromptr);
|
|
+ }
|
|
+
|
|
+-static s32 bcma_erom_get_mst_port(struct bcma_bus *bus, u32 **eromptr)
|
|
++static s32 bcma_erom_get_mst_port(struct bcma_bus *bus, u32 __iomem **eromptr)
|
|
+ {
|
|
+ u32 ent = bcma_erom_get_ent(bus, eromptr);
|
|
+ if (!(ent & SCAN_ER_VALID))
|
|
+@@ -167,7 +201,7 @@ static s32 bcma_erom_get_mst_port(struct
|
|
+ return ent;
|
|
+ }
|
|
+
|
|
+-static s32 bcma_erom_get_addr_desc(struct bcma_bus *bus, u32 **eromptr,
|
|
++static s32 bcma_erom_get_addr_desc(struct bcma_bus *bus, u32 __iomem **eromptr,
|
|
+ u32 type, u8 port)
|
|
+ {
|
|
+ u32 addrl, addrh, sizel, sizeh = 0;
|
|
+@@ -212,6 +246,17 @@ static struct bcma_device *bcma_find_cor
|
|
return NULL;
|
|
}
|
|
|
|
@@ -2066,7 +3342,7 @@
|
|
static int bcma_get_next_core(struct bcma_bus *bus, u32 __iomem **eromptr,
|
|
struct bcma_device_id *match, int core_num,
|
|
struct bcma_device *core)
|
|
-@@ -252,11 +295,15 @@ static int bcma_get_next_core(struct bcm
|
|
+@@ -252,11 +297,15 @@ static int bcma_get_next_core(struct bcm
|
|
|
|
/* check if component is a core at all */
|
|
if (wrappers[0] + wrappers[1] == 0) {
|
|
@@ -2087,7 +3363,7 @@
|
|
}
|
|
|
|
if (bcma_erom_is_bridge(bus, eromptr)) {
|
|
-@@ -286,6 +333,23 @@ static int bcma_get_next_core(struct bcm
|
|
+@@ -286,6 +335,23 @@ static int bcma_get_next_core(struct bcm
|
|
return -EILSEQ;
|
|
}
|
|
|
|
@@ -2111,7 +3387,7 @@
|
|
/* get & parse slave ports */
|
|
for (i = 0; i < ports[1]; i++) {
|
|
for (j = 0; ; j++) {
|
|
-@@ -298,7 +362,7 @@ static int bcma_get_next_core(struct bcm
|
|
+@@ -298,7 +364,7 @@ static int bcma_get_next_core(struct bcm
|
|
break;
|
|
} else {
|
|
if (i == 0 && j == 0)
|
|
@@ -2120,7 +3396,7 @@
|
|
}
|
|
}
|
|
}
|
|
-@@ -353,6 +417,7 @@ static int bcma_get_next_core(struct bcm
|
|
+@@ -353,6 +419,7 @@ static int bcma_get_next_core(struct bcm
|
|
void bcma_init_bus(struct bcma_bus *bus)
|
|
{
|
|
s32 tmp;
|
|
@@ -2128,7 +3404,7 @@
|
|
|
|
if (bus->init_done)
|
|
return;
|
|
-@@ -363,9 +428,12 @@ void bcma_init_bus(struct bcma_bus *bus)
|
|
+@@ -363,9 +430,12 @@ void bcma_init_bus(struct bcma_bus *bus)
|
|
bcma_scan_switch_core(bus, BCMA_ADDR_BASE);
|
|
|
|
tmp = bcma_scan_read32(bus, 0, BCMA_CC_ID);
|
|
@@ -2144,16 +3420,29 @@
|
|
bus->init_done = true;
|
|
}
|
|
|
|
-@@ -392,6 +460,7 @@ int bcma_bus_scan(struct bcma_bus *bus)
|
|
+@@ -392,9 +462,12 @@ int bcma_bus_scan(struct bcma_bus *bus)
|
|
bcma_scan_switch_core(bus, erombase);
|
|
|
|
while (eromptr < eromend) {
|
|
+ struct bcma_device *other_core;
|
|
struct bcma_device *core = kzalloc(sizeof(*core), GFP_KERNEL);
|
|
- if (!core)
|
|
- return -ENOMEM;
|
|
-@@ -414,14 +483,15 @@ int bcma_bus_scan(struct bcma_bus *bus)
|
|
+- if (!core)
|
|
+- return -ENOMEM;
|
|
++ if (!core) {
|
|
++ err = -ENOMEM;
|
|
++ goto out;
|
|
++ }
|
|
+ INIT_LIST_HEAD(&core->list);
|
|
+ core->bus = bus;
|
|
|
|
+@@ -409,25 +482,28 @@ int bcma_bus_scan(struct bcma_bus *bus)
|
|
+ } else if (err == -ESPIPE) {
|
|
+ break;
|
|
+ }
|
|
+- return err;
|
|
++ goto out;
|
|
+ }
|
|
+
|
|
core->core_index = core_num++;
|
|
bus->nr_cores++;
|
|
+ other_core = bcma_find_core_reverse(bus, core->id.id);
|
|
@@ -2173,9 +3462,23 @@
|
|
+ list_add_tail(&core->list, &bus->cores);
|
|
}
|
|
|
|
++ err = 0;
|
|
++out:
|
|
if (bus->hosttype == BCMA_HOSTTYPE_SOC)
|
|
-@@ -471,13 +541,12 @@ int __init bcma_bus_scan_early(struct bc
|
|
+ iounmap(eromptr);
|
|
|
|
+- return 0;
|
|
++ return err;
|
|
+ }
|
|
+
|
|
+ int __init bcma_bus_scan_early(struct bcma_bus *bus,
|
|
+@@ -467,21 +543,21 @@ int __init bcma_bus_scan_early(struct bc
|
|
+ else if (err == -ESPIPE)
|
|
+ break;
|
|
+ else if (err < 0)
|
|
+- return err;
|
|
++ goto out;
|
|
+
|
|
core->core_index = core_num++;
|
|
bus->nr_cores++;
|
|
- pr_info("Core %d found: %s "
|
|
@@ -2193,6 +3496,11 @@
|
|
err = 0;
|
|
break;
|
|
}
|
|
+
|
|
++out:
|
|
+ if (bus->hosttype == BCMA_HOSTTYPE_SOC)
|
|
+ iounmap(eromptr);
|
|
+
|
|
--- a/drivers/bcma/scan.h
|
|
+++ b/drivers/bcma/scan.h
|
|
@@ -27,7 +27,7 @@
|
|
@@ -2215,7 +3523,7 @@
|
|
* Licensed under the GNU/GPL. See COPYING for details.
|
|
*/
|
|
|
|
-@@ -14,7 +16,57 @@
|
|
+@@ -14,18 +16,68 @@
|
|
#include <linux/dma-mapping.h>
|
|
#include <linux/slab.h>
|
|
|
|
@@ -2274,7 +3582,88 @@
|
|
|
|
/**************************************************
|
|
* R/W ops.
|
|
-@@ -124,10 +176,37 @@ static int bcma_sprom_valid(const u16 *s
|
|
+ **************************************************/
|
|
+
|
|
+-static void bcma_sprom_read(struct bcma_bus *bus, u16 offset, u16 *sprom)
|
|
++static void bcma_sprom_read(struct bcma_bus *bus, u16 offset, u16 *sprom,
|
|
++ size_t words)
|
|
+ {
|
|
+ int i;
|
|
+- for (i = 0; i < SSB_SPROMSIZE_WORDS_R4; i++)
|
|
+- sprom[i] = bcma_read16(bus->drv_cc.core,
|
|
+- offset + (i * 2));
|
|
++ for (i = 0; i < words; i++)
|
|
++ sprom[i] = bcma_read16(bus->drv_cc.core, offset + (i * 2));
|
|
+ }
|
|
+
|
|
+ /**************************************************
|
|
+@@ -72,29 +124,29 @@ static inline u8 bcma_crc8(u8 crc, u8 da
|
|
+ return t[crc ^ data];
|
|
+ }
|
|
+
|
|
+-static u8 bcma_sprom_crc(const u16 *sprom)
|
|
++static u8 bcma_sprom_crc(const u16 *sprom, size_t words)
|
|
+ {
|
|
+ int word;
|
|
+ u8 crc = 0xFF;
|
|
+
|
|
+- for (word = 0; word < SSB_SPROMSIZE_WORDS_R4 - 1; word++) {
|
|
++ for (word = 0; word < words - 1; word++) {
|
|
+ crc = bcma_crc8(crc, sprom[word] & 0x00FF);
|
|
+ crc = bcma_crc8(crc, (sprom[word] & 0xFF00) >> 8);
|
|
+ }
|
|
+- crc = bcma_crc8(crc, sprom[SSB_SPROMSIZE_WORDS_R4 - 1] & 0x00FF);
|
|
++ crc = bcma_crc8(crc, sprom[words - 1] & 0x00FF);
|
|
+ crc ^= 0xFF;
|
|
+
|
|
+ return crc;
|
|
+ }
|
|
+
|
|
+-static int bcma_sprom_check_crc(const u16 *sprom)
|
|
++static int bcma_sprom_check_crc(const u16 *sprom, size_t words)
|
|
+ {
|
|
+ u8 crc;
|
|
+ u8 expected_crc;
|
|
+ u16 tmp;
|
|
+
|
|
+- crc = bcma_sprom_crc(sprom);
|
|
+- tmp = sprom[SSB_SPROMSIZE_WORDS_R4 - 1] & SSB_SPROM_REVISION_CRC;
|
|
++ crc = bcma_sprom_crc(sprom, words);
|
|
++ tmp = sprom[words - 1] & SSB_SPROM_REVISION_CRC;
|
|
+ expected_crc = tmp >> SSB_SPROM_REVISION_CRC_SHIFT;
|
|
+ if (crc != expected_crc)
|
|
+ return -EPROTO;
|
|
+@@ -102,21 +154,25 @@ static int bcma_sprom_check_crc(const u1
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+-static int bcma_sprom_valid(const u16 *sprom)
|
|
++static int bcma_sprom_valid(struct bcma_bus *bus, const u16 *sprom,
|
|
++ size_t words)
|
|
+ {
|
|
+ u16 revision;
|
|
+ int err;
|
|
+
|
|
+- err = bcma_sprom_check_crc(sprom);
|
|
++ err = bcma_sprom_check_crc(sprom, words);
|
|
+ if (err)
|
|
+ return err;
|
|
+
|
|
+- revision = sprom[SSB_SPROMSIZE_WORDS_R4 - 1] & SSB_SPROM_REVISION_REV;
|
|
+- if (revision != 8 && revision != 9) {
|
|
++ revision = sprom[words - 1] & SSB_SPROM_REVISION_REV;
|
|
++ if (revision != 8 && revision != 9 && revision != 10) {
|
|
+ pr_err("Unsupported SPROM revision: %d\n", revision);
|
|
+ return -ENOENT;
|
|
+ }
|
|
+
|
|
++ bus->sprom.revision = revision;
|
|
++ bcma_debug(bus, "Found SPROM revision %d\n", revision);
|
|
++
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+@@ -124,124 +180,439 @@ static int bcma_sprom_valid(const u16 *s
|
|
* SPROM extraction.
|
|
**************************************************/
|
|
|
|
@@ -2304,6 +3693,9 @@
|
|
- u16 v;
|
|
+ u16 v, o;
|
|
int i;
|
|
+-
|
|
+- bus->sprom.revision = sprom[SSB_SPROMSIZE_WORDS_R4 - 1] &
|
|
+- SSB_SPROM_REVISION_REV;
|
|
+ u16 pwr_info_offset[] = {
|
|
+ SSB_SROM8_PWR_INFO_CORE0, SSB_SROM8_PWR_INFO_CORE1,
|
|
+ SSB_SROM8_PWR_INFO_CORE2, SSB_SROM8_PWR_INFO_CORE3
|
|
@@ -2311,79 +3703,15 @@
|
|
+ BUILD_BUG_ON(ARRAY_SIZE(pwr_info_offset) !=
|
|
+ ARRAY_SIZE(bus->sprom.core_pwr_info));
|
|
|
|
- bus->sprom.revision = sprom[SSB_SPROMSIZE_WORDS_R4 - 1] &
|
|
- SSB_SPROM_REVISION_REV;
|
|
-@@ -137,102 +216,378 @@ static void bcma_sprom_extract_r8(struct
|
|
+ for (i = 0; i < 3; i++) {
|
|
+ v = sprom[SPOFF(SSB_SPROM8_IL0MAC) + i];
|
|
*(((__be16 *)bus->sprom.il0mac) + i) = cpu_to_be16(v);
|
|
}
|
|
|
|
- bus->sprom.board_rev = sprom[SPOFF(SSB_SPROM8_BOARDREV)];
|
|
+ SPEX(board_rev, SSB_SPROM8_BOARDREV, ~0, 0);
|
|
-
|
|
-- bus->sprom.txpid2g[0] = (sprom[SPOFF(SSB_SPROM4_TXPID2G01)] &
|
|
-- SSB_SPROM4_TXPID2G0) >> SSB_SPROM4_TXPID2G0_SHIFT;
|
|
-- bus->sprom.txpid2g[1] = (sprom[SPOFF(SSB_SPROM4_TXPID2G01)] &
|
|
-- SSB_SPROM4_TXPID2G1) >> SSB_SPROM4_TXPID2G1_SHIFT;
|
|
-- bus->sprom.txpid2g[2] = (sprom[SPOFF(SSB_SPROM4_TXPID2G23)] &
|
|
-- SSB_SPROM4_TXPID2G2) >> SSB_SPROM4_TXPID2G2_SHIFT;
|
|
-- bus->sprom.txpid2g[3] = (sprom[SPOFF(SSB_SPROM4_TXPID2G23)] &
|
|
-- SSB_SPROM4_TXPID2G3) >> SSB_SPROM4_TXPID2G3_SHIFT;
|
|
--
|
|
-- bus->sprom.txpid5gl[0] = (sprom[SPOFF(SSB_SPROM4_TXPID5GL01)] &
|
|
-- SSB_SPROM4_TXPID5GL0) >> SSB_SPROM4_TXPID5GL0_SHIFT;
|
|
-- bus->sprom.txpid5gl[1] = (sprom[SPOFF(SSB_SPROM4_TXPID5GL01)] &
|
|
-- SSB_SPROM4_TXPID5GL1) >> SSB_SPROM4_TXPID5GL1_SHIFT;
|
|
-- bus->sprom.txpid5gl[2] = (sprom[SPOFF(SSB_SPROM4_TXPID5GL23)] &
|
|
-- SSB_SPROM4_TXPID5GL2) >> SSB_SPROM4_TXPID5GL2_SHIFT;
|
|
-- bus->sprom.txpid5gl[3] = (sprom[SPOFF(SSB_SPROM4_TXPID5GL23)] &
|
|
-- SSB_SPROM4_TXPID5GL3) >> SSB_SPROM4_TXPID5GL3_SHIFT;
|
|
--
|
|
-- bus->sprom.txpid5g[0] = (sprom[SPOFF(SSB_SPROM4_TXPID5G01)] &
|
|
-- SSB_SPROM4_TXPID5G0) >> SSB_SPROM4_TXPID5G0_SHIFT;
|
|
-- bus->sprom.txpid5g[1] = (sprom[SPOFF(SSB_SPROM4_TXPID5G01)] &
|
|
-- SSB_SPROM4_TXPID5G1) >> SSB_SPROM4_TXPID5G1_SHIFT;
|
|
-- bus->sprom.txpid5g[2] = (sprom[SPOFF(SSB_SPROM4_TXPID5G23)] &
|
|
-- SSB_SPROM4_TXPID5G2) >> SSB_SPROM4_TXPID5G2_SHIFT;
|
|
-- bus->sprom.txpid5g[3] = (sprom[SPOFF(SSB_SPROM4_TXPID5G23)] &
|
|
-- SSB_SPROM4_TXPID5G3) >> SSB_SPROM4_TXPID5G3_SHIFT;
|
|
--
|
|
-- bus->sprom.txpid5gh[0] = (sprom[SPOFF(SSB_SPROM4_TXPID5GH01)] &
|
|
-- SSB_SPROM4_TXPID5GH0) >> SSB_SPROM4_TXPID5GH0_SHIFT;
|
|
-- bus->sprom.txpid5gh[1] = (sprom[SPOFF(SSB_SPROM4_TXPID5GH01)] &
|
|
-- SSB_SPROM4_TXPID5GH1) >> SSB_SPROM4_TXPID5GH1_SHIFT;
|
|
-- bus->sprom.txpid5gh[2] = (sprom[SPOFF(SSB_SPROM4_TXPID5GH23)] &
|
|
-- SSB_SPROM4_TXPID5GH2) >> SSB_SPROM4_TXPID5GH2_SHIFT;
|
|
-- bus->sprom.txpid5gh[3] = (sprom[SPOFF(SSB_SPROM4_TXPID5GH23)] &
|
|
-- SSB_SPROM4_TXPID5GH3) >> SSB_SPROM4_TXPID5GH3_SHIFT;
|
|
--
|
|
-- bus->sprom.boardflags_lo = sprom[SPOFF(SSB_SPROM8_BFLLO)];
|
|
-- bus->sprom.boardflags_hi = sprom[SPOFF(SSB_SPROM8_BFLHI)];
|
|
-- bus->sprom.boardflags2_lo = sprom[SPOFF(SSB_SPROM8_BFL2LO)];
|
|
-- bus->sprom.boardflags2_hi = sprom[SPOFF(SSB_SPROM8_BFL2HI)];
|
|
--
|
|
-- bus->sprom.country_code = sprom[SPOFF(SSB_SPROM8_CCODE)];
|
|
--
|
|
-- bus->sprom.fem.ghz2.tssipos = (sprom[SPOFF(SSB_SPROM8_FEM2G)] &
|
|
-- SSB_SROM8_FEM_TSSIPOS) >> SSB_SROM8_FEM_TSSIPOS_SHIFT;
|
|
-- bus->sprom.fem.ghz2.extpa_gain = (sprom[SPOFF(SSB_SPROM8_FEM2G)] &
|
|
-- SSB_SROM8_FEM_EXTPA_GAIN) >> SSB_SROM8_FEM_EXTPA_GAIN_SHIFT;
|
|
-- bus->sprom.fem.ghz2.pdet_range = (sprom[SPOFF(SSB_SPROM8_FEM2G)] &
|
|
-- SSB_SROM8_FEM_PDET_RANGE) >> SSB_SROM8_FEM_PDET_RANGE_SHIFT;
|
|
-- bus->sprom.fem.ghz2.tr_iso = (sprom[SPOFF(SSB_SPROM8_FEM2G)] &
|
|
-- SSB_SROM8_FEM_TR_ISO) >> SSB_SROM8_FEM_TR_ISO_SHIFT;
|
|
-- bus->sprom.fem.ghz2.antswlut = (sprom[SPOFF(SSB_SPROM8_FEM2G)] &
|
|
-- SSB_SROM8_FEM_ANTSWLUT) >> SSB_SROM8_FEM_ANTSWLUT_SHIFT;
|
|
--
|
|
-- bus->sprom.fem.ghz5.tssipos = (sprom[SPOFF(SSB_SPROM8_FEM5G)] &
|
|
-- SSB_SROM8_FEM_TSSIPOS) >> SSB_SROM8_FEM_TSSIPOS_SHIFT;
|
|
-- bus->sprom.fem.ghz5.extpa_gain = (sprom[SPOFF(SSB_SPROM8_FEM5G)] &
|
|
-- SSB_SROM8_FEM_EXTPA_GAIN) >> SSB_SROM8_FEM_EXTPA_GAIN_SHIFT;
|
|
-- bus->sprom.fem.ghz5.pdet_range = (sprom[SPOFF(SSB_SPROM8_FEM5G)] &
|
|
-- SSB_SROM8_FEM_PDET_RANGE) >> SSB_SROM8_FEM_PDET_RANGE_SHIFT;
|
|
-- bus->sprom.fem.ghz5.tr_iso = (sprom[SPOFF(SSB_SPROM8_FEM5G)] &
|
|
-- SSB_SROM8_FEM_TR_ISO) >> SSB_SROM8_FEM_TR_ISO_SHIFT;
|
|
-- bus->sprom.fem.ghz5.antswlut = (sprom[SPOFF(SSB_SPROM8_FEM5G)] &
|
|
-- SSB_SROM8_FEM_ANTSWLUT) >> SSB_SROM8_FEM_ANTSWLUT_SHIFT;
|
|
++ SPEX(board_type, SSB_SPROM1_SPID, ~0, 0);
|
|
++
|
|
+ SPEX(txpid2g[0], SSB_SPROM4_TXPID2G01, SSB_SPROM4_TXPID2G0,
|
|
+ SSB_SPROM4_TXPID2G0_SHIFT);
|
|
+ SPEX(txpid2g[1], SSB_SPROM4_TXPID2G01, SSB_SPROM4_TXPID2G1,
|
|
@@ -2641,7 +3969,71 @@
|
|
+ case BCMA_CHIP_ID_BCM4331:
|
|
+ present_mask = BCMA_CC_CHIPST_4331_SPROM_PRESENT;
|
|
+ break;
|
|
-+
|
|
+
|
|
+- bus->sprom.txpid2g[0] = (sprom[SPOFF(SSB_SPROM4_TXPID2G01)] &
|
|
+- SSB_SPROM4_TXPID2G0) >> SSB_SPROM4_TXPID2G0_SHIFT;
|
|
+- bus->sprom.txpid2g[1] = (sprom[SPOFF(SSB_SPROM4_TXPID2G01)] &
|
|
+- SSB_SPROM4_TXPID2G1) >> SSB_SPROM4_TXPID2G1_SHIFT;
|
|
+- bus->sprom.txpid2g[2] = (sprom[SPOFF(SSB_SPROM4_TXPID2G23)] &
|
|
+- SSB_SPROM4_TXPID2G2) >> SSB_SPROM4_TXPID2G2_SHIFT;
|
|
+- bus->sprom.txpid2g[3] = (sprom[SPOFF(SSB_SPROM4_TXPID2G23)] &
|
|
+- SSB_SPROM4_TXPID2G3) >> SSB_SPROM4_TXPID2G3_SHIFT;
|
|
+-
|
|
+- bus->sprom.txpid5gl[0] = (sprom[SPOFF(SSB_SPROM4_TXPID5GL01)] &
|
|
+- SSB_SPROM4_TXPID5GL0) >> SSB_SPROM4_TXPID5GL0_SHIFT;
|
|
+- bus->sprom.txpid5gl[1] = (sprom[SPOFF(SSB_SPROM4_TXPID5GL01)] &
|
|
+- SSB_SPROM4_TXPID5GL1) >> SSB_SPROM4_TXPID5GL1_SHIFT;
|
|
+- bus->sprom.txpid5gl[2] = (sprom[SPOFF(SSB_SPROM4_TXPID5GL23)] &
|
|
+- SSB_SPROM4_TXPID5GL2) >> SSB_SPROM4_TXPID5GL2_SHIFT;
|
|
+- bus->sprom.txpid5gl[3] = (sprom[SPOFF(SSB_SPROM4_TXPID5GL23)] &
|
|
+- SSB_SPROM4_TXPID5GL3) >> SSB_SPROM4_TXPID5GL3_SHIFT;
|
|
+-
|
|
+- bus->sprom.txpid5g[0] = (sprom[SPOFF(SSB_SPROM4_TXPID5G01)] &
|
|
+- SSB_SPROM4_TXPID5G0) >> SSB_SPROM4_TXPID5G0_SHIFT;
|
|
+- bus->sprom.txpid5g[1] = (sprom[SPOFF(SSB_SPROM4_TXPID5G01)] &
|
|
+- SSB_SPROM4_TXPID5G1) >> SSB_SPROM4_TXPID5G1_SHIFT;
|
|
+- bus->sprom.txpid5g[2] = (sprom[SPOFF(SSB_SPROM4_TXPID5G23)] &
|
|
+- SSB_SPROM4_TXPID5G2) >> SSB_SPROM4_TXPID5G2_SHIFT;
|
|
+- bus->sprom.txpid5g[3] = (sprom[SPOFF(SSB_SPROM4_TXPID5G23)] &
|
|
+- SSB_SPROM4_TXPID5G3) >> SSB_SPROM4_TXPID5G3_SHIFT;
|
|
+-
|
|
+- bus->sprom.txpid5gh[0] = (sprom[SPOFF(SSB_SPROM4_TXPID5GH01)] &
|
|
+- SSB_SPROM4_TXPID5GH0) >> SSB_SPROM4_TXPID5GH0_SHIFT;
|
|
+- bus->sprom.txpid5gh[1] = (sprom[SPOFF(SSB_SPROM4_TXPID5GH01)] &
|
|
+- SSB_SPROM4_TXPID5GH1) >> SSB_SPROM4_TXPID5GH1_SHIFT;
|
|
+- bus->sprom.txpid5gh[2] = (sprom[SPOFF(SSB_SPROM4_TXPID5GH23)] &
|
|
+- SSB_SPROM4_TXPID5GH2) >> SSB_SPROM4_TXPID5GH2_SHIFT;
|
|
+- bus->sprom.txpid5gh[3] = (sprom[SPOFF(SSB_SPROM4_TXPID5GH23)] &
|
|
+- SSB_SPROM4_TXPID5GH3) >> SSB_SPROM4_TXPID5GH3_SHIFT;
|
|
+-
|
|
+- bus->sprom.boardflags_lo = sprom[SPOFF(SSB_SPROM8_BFLLO)];
|
|
+- bus->sprom.boardflags_hi = sprom[SPOFF(SSB_SPROM8_BFLHI)];
|
|
+- bus->sprom.boardflags2_lo = sprom[SPOFF(SSB_SPROM8_BFL2LO)];
|
|
+- bus->sprom.boardflags2_hi = sprom[SPOFF(SSB_SPROM8_BFL2HI)];
|
|
+-
|
|
+- bus->sprom.country_code = sprom[SPOFF(SSB_SPROM8_CCODE)];
|
|
+-
|
|
+- bus->sprom.fem.ghz2.tssipos = (sprom[SPOFF(SSB_SPROM8_FEM2G)] &
|
|
+- SSB_SROM8_FEM_TSSIPOS) >> SSB_SROM8_FEM_TSSIPOS_SHIFT;
|
|
+- bus->sprom.fem.ghz2.extpa_gain = (sprom[SPOFF(SSB_SPROM8_FEM2G)] &
|
|
+- SSB_SROM8_FEM_EXTPA_GAIN) >> SSB_SROM8_FEM_EXTPA_GAIN_SHIFT;
|
|
+- bus->sprom.fem.ghz2.pdet_range = (sprom[SPOFF(SSB_SPROM8_FEM2G)] &
|
|
+- SSB_SROM8_FEM_PDET_RANGE) >> SSB_SROM8_FEM_PDET_RANGE_SHIFT;
|
|
+- bus->sprom.fem.ghz2.tr_iso = (sprom[SPOFF(SSB_SPROM8_FEM2G)] &
|
|
+- SSB_SROM8_FEM_TR_ISO) >> SSB_SROM8_FEM_TR_ISO_SHIFT;
|
|
+- bus->sprom.fem.ghz2.antswlut = (sprom[SPOFF(SSB_SPROM8_FEM2G)] &
|
|
+- SSB_SROM8_FEM_ANTSWLUT) >> SSB_SROM8_FEM_ANTSWLUT_SHIFT;
|
|
+-
|
|
+- bus->sprom.fem.ghz5.tssipos = (sprom[SPOFF(SSB_SPROM8_FEM5G)] &
|
|
+- SSB_SROM8_FEM_TSSIPOS) >> SSB_SROM8_FEM_TSSIPOS_SHIFT;
|
|
+- bus->sprom.fem.ghz5.extpa_gain = (sprom[SPOFF(SSB_SPROM8_FEM5G)] &
|
|
+- SSB_SROM8_FEM_EXTPA_GAIN) >> SSB_SROM8_FEM_EXTPA_GAIN_SHIFT;
|
|
+- bus->sprom.fem.ghz5.pdet_range = (sprom[SPOFF(SSB_SPROM8_FEM5G)] &
|
|
+- SSB_SROM8_FEM_PDET_RANGE) >> SSB_SROM8_FEM_PDET_RANGE_SHIFT;
|
|
+- bus->sprom.fem.ghz5.tr_iso = (sprom[SPOFF(SSB_SPROM8_FEM5G)] &
|
|
+- SSB_SROM8_FEM_TR_ISO) >> SSB_SROM8_FEM_TR_ISO_SHIFT;
|
|
+- bus->sprom.fem.ghz5.antswlut = (sprom[SPOFF(SSB_SPROM8_FEM5G)] &
|
|
+- SSB_SROM8_FEM_ANTSWLUT) >> SSB_SROM8_FEM_ANTSWLUT_SHIFT;
|
|
+ default:
|
|
+ return true;
|
|
+ }
|
|
@@ -2667,13 +4059,17 @@
|
|
+ case BCMA_CHIP_ID_BCM4331:
|
|
+ present = chip_status & BCMA_CC_CHIPST_4331_OTP_PRESENT;
|
|
+ break;
|
|
-+
|
|
++ case BCMA_CHIP_ID_BCM43142:
|
|
+ case BCMA_CHIP_ID_BCM43224:
|
|
+ case BCMA_CHIP_ID_BCM43225:
|
|
+ /* for these chips OTP is always available */
|
|
+ present = true;
|
|
+ break;
|
|
-+
|
|
++ case BCMA_CHIP_ID_BCM43227:
|
|
++ case BCMA_CHIP_ID_BCM43228:
|
|
++ case BCMA_CHIP_ID_BCM43428:
|
|
++ present = chip_status & BCMA_CC_CHIPST_43228_OTP_PRESENT;
|
|
++ break;
|
|
+ default:
|
|
+ present = false;
|
|
+ break;
|
|
@@ -2712,7 +4108,10 @@
|
|
- u16 offset;
|
|
+ u16 offset = BCMA_CC_SPROM;
|
|
u16 *sprom;
|
|
- int err = 0;
|
|
+- int err = 0;
|
|
++ size_t sprom_sizes[] = { SSB_SPROMSIZE_WORDS_R4,
|
|
++ SSB_SPROMSIZE_WORDS_R10, };
|
|
++ int i, err = 0;
|
|
|
|
if (!bus->drv_cc.core)
|
|
return -EOPNOTSUPP;
|
|
@@ -2721,7 +4120,11 @@
|
|
- return -ENOENT;
|
|
+ if (!bcma_sprom_ext_available(bus)) {
|
|
+ bool sprom_onchip;
|
|
-+
|
|
+
|
|
+- sprom = kcalloc(SSB_SPROMSIZE_WORDS_R4, sizeof(u16),
|
|
+- GFP_KERNEL);
|
|
+- if (!sprom)
|
|
+- return -ENOMEM;
|
|
+ /*
|
|
+ * External SPROM takes precedence so check
|
|
+ * on-chip OTP only when no external SPROM
|
|
@@ -2743,11 +4146,6 @@
|
|
+ }
|
|
+ }
|
|
|
|
- sprom = kcalloc(SSB_SPROMSIZE_WORDS_R4, sizeof(u16),
|
|
- GFP_KERNEL);
|
|
- if (!sprom)
|
|
- return -ENOMEM;
|
|
-
|
|
- if (bus->chipinfo.id == 0x4331)
|
|
+ if (bus->chipinfo.id == BCMA_CHIP_ID_BCM4331 ||
|
|
+ bus->chipinfo.id == BCMA_CHIP_ID_BCM43431)
|
|
@@ -2758,25 +4156,59 @@
|
|
- * TODO: understand this condition and use it */
|
|
- offset = (bus->chipinfo.id == 0x4331) ? BCMA_CC_SPROM :
|
|
- BCMA_CC_SPROM_PCIE6;
|
|
+- bcma_sprom_read(bus, offset, sprom);
|
|
+ bcma_debug(bus, "SPROM offset 0x%x\n", offset);
|
|
- bcma_sprom_read(bus, offset, sprom);
|
|
++ for (i = 0; i < ARRAY_SIZE(sprom_sizes); i++) {
|
|
++ size_t words = sprom_sizes[i];
|
|
++
|
|
++ sprom = kcalloc(words, sizeof(u16), GFP_KERNEL);
|
|
++ if (!sprom)
|
|
++ return -ENOMEM;
|
|
++
|
|
++ bcma_sprom_read(bus, offset, sprom, words);
|
|
++ err = bcma_sprom_valid(bus, sprom, words);
|
|
++ if (!err)
|
|
++ break;
|
|
|
|
- if (bus->chipinfo.id == 0x4331)
|
|
+- bcma_chipco_bcm4331_ext_pa_lines_ctl(&bus->drv_cc, true);
|
|
++ kfree(sprom);
|
|
++ }
|
|
+
|
|
+- err = bcma_sprom_valid(sprom);
|
|
+- if (err)
|
|
+- goto out;
|
|
+ if (bus->chipinfo.id == BCMA_CHIP_ID_BCM4331 ||
|
|
+ bus->chipinfo.id == BCMA_CHIP_ID_BCM43431)
|
|
- bcma_chipco_bcm4331_ext_pa_lines_ctl(&bus->drv_cc, true);
|
|
++ bcma_chipco_bcm4331_ext_pa_lines_ctl(&bus->drv_cc, true);
|
|
|
|
- err = bcma_sprom_valid(sprom);
|
|
+- bcma_sprom_extract_r8(bus, sprom);
|
|
++ if (err) {
|
|
++ bcma_warn(bus, "Invalid SPROM read from the PCIe card, trying to use fallback SPROM\n");
|
|
++ err = bcma_fill_sprom_with_fallback(bus, &bus->sprom);
|
|
++ } else {
|
|
++ bcma_sprom_extract_r8(bus, sprom);
|
|
++ kfree(sprom);
|
|
++ }
|
|
+
|
|
+-out:
|
|
+- kfree(sprom);
|
|
+ return err;
|
|
+ }
|
|
--- a/include/linux/bcma/bcma.h
|
|
+++ b/include/linux/bcma/bcma.h
|
|
-@@ -7,6 +7,7 @@
|
|
+@@ -7,9 +7,10 @@
|
|
#include <linux/bcma/bcma_driver_chipcommon.h>
|
|
#include <linux/bcma/bcma_driver_pci.h>
|
|
#include <linux/bcma/bcma_driver_mips.h>
|
|
+#include <linux/bcma/bcma_driver_gmac_cmn.h>
|
|
#include <linux/ssb/ssb.h> /* SPROM sharing */
|
|
|
|
- #include "bcma_regs.h"
|
|
+-#include "bcma_regs.h"
|
|
++#include <linux/bcma/bcma_regs.h>
|
|
+
|
|
+ struct bcma_device;
|
|
+ struct bcma_bus;
|
|
@@ -26,6 +27,11 @@ struct bcma_chipinfo {
|
|
u8 pkg;
|
|
};
|
|
@@ -2803,12 +4235,21 @@
|
|
#define BCMA_CORE_INVALID 0x700
|
|
#define BCMA_CORE_CHIPCOMMON 0x800
|
|
#define BCMA_CORE_ILINE20 0x801
|
|
-@@ -125,6 +138,36 @@ struct bcma_host_ops {
|
|
+@@ -121,10 +134,104 @@ struct bcma_host_ops {
|
|
+ #define BCMA_CORE_I2S 0x834
|
|
+ #define BCMA_CORE_SDR_DDR1_MEM_CTL 0x835 /* SDR/DDR1 memory controller core */
|
|
+ #define BCMA_CORE_SHIM 0x837 /* SHIM component in ubus/6362 */
|
|
++#define BCMA_CORE_PHY_AC 0x83B
|
|
++#define BCMA_CORE_PCIE2 0x83C /* PCI Express Gen2 */
|
|
++#define BCMA_CORE_USB30_DEV 0x83D
|
|
++#define BCMA_CORE_ARM_CR4 0x83E
|
|
+ #define BCMA_CORE_DEFAULT 0xFFF
|
|
|
|
#define BCMA_MAX_NR_CORES 16
|
|
|
|
+/* Chip IDs of PCIe devices */
|
|
+#define BCMA_CHIP_ID_BCM4313 0x4313
|
|
++#define BCMA_CHIP_ID_BCM43142 43142
|
|
+#define BCMA_CHIP_ID_BCM43224 43224
|
|
+#define BCMA_PKG_ID_BCM43224_FAB_CSM 0x8
|
|
+#define BCMA_PKG_ID_BCM43224_FAB_SMIC 0xa
|
|
@@ -2826,6 +4267,7 @@
|
|
+
|
|
+/* Chip IDs of SoCs */
|
|
+#define BCMA_CHIP_ID_BCM4706 0x5300
|
|
++#define BCMA_PKG_ID_BCM4706L 1
|
|
+#define BCMA_CHIP_ID_BCM4716 0x4716
|
|
+#define BCMA_PKG_ID_BCM4716 8
|
|
+#define BCMA_PKG_ID_BCM4717 9
|
|
@@ -2835,12 +4277,70 @@
|
|
+#define BCMA_CHIP_ID_BCM4749 0x4749
|
|
+#define BCMA_CHIP_ID_BCM5356 0x5356
|
|
+#define BCMA_CHIP_ID_BCM5357 0x5357
|
|
++#define BCMA_PKG_ID_BCM5358 9
|
|
++#define BCMA_PKG_ID_BCM47186 10
|
|
++#define BCMA_PKG_ID_BCM5357 11
|
|
+#define BCMA_CHIP_ID_BCM53572 53572
|
|
++#define BCMA_PKG_ID_BCM47188 9
|
|
+
|
|
++/* Board types (on PCI usually equals to the subsystem dev id) */
|
|
++/* BCM4313 */
|
|
++#define BCMA_BOARD_TYPE_BCM94313BU 0X050F
|
|
++#define BCMA_BOARD_TYPE_BCM94313HM 0X0510
|
|
++#define BCMA_BOARD_TYPE_BCM94313EPA 0X0511
|
|
++#define BCMA_BOARD_TYPE_BCM94313HMG 0X051C
|
|
++/* BCM4716 */
|
|
++#define BCMA_BOARD_TYPE_BCM94716NR2 0X04CD
|
|
++/* BCM43224 */
|
|
++#define BCMA_BOARD_TYPE_BCM943224X21 0X056E
|
|
++#define BCMA_BOARD_TYPE_BCM943224X21_FCC 0X00D1
|
|
++#define BCMA_BOARD_TYPE_BCM943224X21B 0X00E9
|
|
++#define BCMA_BOARD_TYPE_BCM943224M93 0X008B
|
|
++#define BCMA_BOARD_TYPE_BCM943224M93A 0X0090
|
|
++#define BCMA_BOARD_TYPE_BCM943224X16 0X0093
|
|
++#define BCMA_BOARD_TYPE_BCM94322X9 0X008D
|
|
++#define BCMA_BOARD_TYPE_BCM94322M35E 0X008E
|
|
++/* BCM43228 */
|
|
++#define BCMA_BOARD_TYPE_BCM943228BU8 0X0540
|
|
++#define BCMA_BOARD_TYPE_BCM943228BU9 0X0541
|
|
++#define BCMA_BOARD_TYPE_BCM943228BU 0X0542
|
|
++#define BCMA_BOARD_TYPE_BCM943227HM4L 0X0543
|
|
++#define BCMA_BOARD_TYPE_BCM943227HMB 0X0544
|
|
++#define BCMA_BOARD_TYPE_BCM943228HM4L 0X0545
|
|
++#define BCMA_BOARD_TYPE_BCM943228SD 0X0573
|
|
++/* BCM4331 */
|
|
++#define BCMA_BOARD_TYPE_BCM94331X19 0X00D6
|
|
++#define BCMA_BOARD_TYPE_BCM94331X28 0X00E4
|
|
++#define BCMA_BOARD_TYPE_BCM94331X28B 0X010E
|
|
++#define BCMA_BOARD_TYPE_BCM94331PCIEBT3AX 0X00E4
|
|
++#define BCMA_BOARD_TYPE_BCM94331X12_2G 0X00EC
|
|
++#define BCMA_BOARD_TYPE_BCM94331X12_5G 0X00ED
|
|
++#define BCMA_BOARD_TYPE_BCM94331X29B 0X00EF
|
|
++#define BCMA_BOARD_TYPE_BCM94331CSAX 0X00EF
|
|
++#define BCMA_BOARD_TYPE_BCM94331X19C 0X00F5
|
|
++#define BCMA_BOARD_TYPE_BCM94331X33 0X00F4
|
|
++#define BCMA_BOARD_TYPE_BCM94331BU 0X0523
|
|
++#define BCMA_BOARD_TYPE_BCM94331S9BU 0X0524
|
|
++#define BCMA_BOARD_TYPE_BCM94331MC 0X0525
|
|
++#define BCMA_BOARD_TYPE_BCM94331MCI 0X0526
|
|
++#define BCMA_BOARD_TYPE_BCM94331PCIEBT4 0X0527
|
|
++#define BCMA_BOARD_TYPE_BCM94331HM 0X0574
|
|
++#define BCMA_BOARD_TYPE_BCM94331PCIEDUAL 0X059B
|
|
++#define BCMA_BOARD_TYPE_BCM94331MCH5 0X05A9
|
|
++#define BCMA_BOARD_TYPE_BCM94331CS 0X05C6
|
|
++#define BCMA_BOARD_TYPE_BCM94331CD 0X05DA
|
|
++/* BCM53572 */
|
|
++#define BCMA_BOARD_TYPE_BCM953572BU 0X058D
|
|
++#define BCMA_BOARD_TYPE_BCM953572NR2 0X058E
|
|
++#define BCMA_BOARD_TYPE_BCM947188NR2 0X058F
|
|
++#define BCMA_BOARD_TYPE_BCM953572SDRNR2 0X0590
|
|
++/* BCM43142 */
|
|
++#define BCMA_BOARD_TYPE_BCM943142HM 0X05E0
|
|
++
|
|
struct bcma_device {
|
|
struct bcma_bus *bus;
|
|
struct bcma_device_id id;
|
|
-@@ -136,8 +179,10 @@ struct bcma_device {
|
|
+@@ -136,8 +243,10 @@ struct bcma_device {
|
|
bool dev_registered;
|
|
|
|
u8 core_index;
|
|
@@ -2851,7 +4351,7 @@
|
|
u32 wrap;
|
|
|
|
void __iomem *io_addr;
|
|
-@@ -175,6 +220,12 @@ int __bcma_driver_register(struct bcma_d
|
|
+@@ -175,6 +284,12 @@ int __bcma_driver_register(struct bcma_d
|
|
|
|
extern void bcma_driver_unregister(struct bcma_driver *drv);
|
|
|
|
@@ -2864,7 +4364,7 @@
|
|
struct bcma_bus {
|
|
/* The MMIO area. */
|
|
void __iomem *mmio;
|
|
-@@ -191,14 +242,18 @@ struct bcma_bus {
|
|
+@@ -191,14 +306,18 @@ struct bcma_bus {
|
|
|
|
struct bcma_chipinfo chipinfo;
|
|
|
|
@@ -2877,13 +4377,14 @@
|
|
+ u8 num;
|
|
|
|
struct bcma_drv_cc drv_cc;
|
|
- struct bcma_drv_pci drv_pci;
|
|
+- struct bcma_drv_pci drv_pci;
|
|
++ struct bcma_drv_pci drv_pci[2];
|
|
struct bcma_drv_mips drv_mips;
|
|
+ struct bcma_drv_gmac_cmn drv_gmac_cmn;
|
|
|
|
/* We decided to share SPROM struct with SSB as long as we do not need
|
|
* any hacks for BCMA. This simplifies drivers code. */
|
|
-@@ -282,6 +337,7 @@ static inline void bcma_maskset16(struct
|
|
+@@ -282,6 +401,7 @@ static inline void bcma_maskset16(struct
|
|
bcma_write16(cc, offset, (bcma_read16(cc, offset) & mask) | set);
|
|
}
|
|
|
|
@@ -2891,9 +4392,44 @@
|
|
extern bool bcma_core_is_enabled(struct bcma_device *core);
|
|
extern void bcma_core_disable(struct bcma_device *core, u32 flags);
|
|
extern int bcma_core_enable(struct bcma_device *core, u32 flags);
|
|
+@@ -289,6 +409,7 @@ extern void bcma_core_set_clockmode(stru
|
|
+ enum bcma_clkmode clkmode);
|
|
+ extern void bcma_core_pll_ctl(struct bcma_device *core, u32 req, u32 status,
|
|
+ bool on);
|
|
++extern u32 bcma_chipco_pll_read(struct bcma_drv_cc *cc, u32 offset);
|
|
+ #define BCMA_DMA_TRANSLATION_MASK 0xC0000000
|
|
+ #define BCMA_DMA_TRANSLATION_NONE 0x00000000
|
|
+ #define BCMA_DMA_TRANSLATION_DMA32_CMT 0x40000000 /* Client Mode Translation for 32-bit DMA */
|
|
--- a/include/linux/bcma/bcma_driver_chipcommon.h
|
|
+++ b/include/linux/bcma/bcma_driver_chipcommon.h
|
|
-@@ -56,6 +56,9 @@
|
|
+@@ -1,6 +1,9 @@
|
|
+ #ifndef LINUX_BCMA_DRIVER_CC_H_
|
|
+ #define LINUX_BCMA_DRIVER_CC_H_
|
|
+
|
|
++#include <linux/platform_device.h>
|
|
++#include <linux/gpio.h>
|
|
++
|
|
+ /** ChipCommon core registers. **/
|
|
+ #define BCMA_CC_ID 0x0000
|
|
+ #define BCMA_CC_ID_ID 0x0000FFFF
|
|
+@@ -24,7 +27,7 @@
|
|
+ #define BCMA_CC_FLASHT_NONE 0x00000000 /* No flash */
|
|
+ #define BCMA_CC_FLASHT_STSER 0x00000100 /* ST serial flash */
|
|
+ #define BCMA_CC_FLASHT_ATSER 0x00000200 /* Atmel serial flash */
|
|
+-#define BCMA_CC_FLASHT_NFLASH 0x00000200
|
|
++#define BCMA_CC_FLASHT_NAND 0x00000300 /* NAND flash */
|
|
+ #define BCMA_CC_FLASHT_PARA 0x00000700 /* Parallel flash */
|
|
+ #define BCMA_CC_CAP_PLLT 0x00038000 /* PLL Type */
|
|
+ #define BCMA_PLLTYPE_NONE 0x00000000
|
|
+@@ -45,6 +48,7 @@
|
|
+ #define BCMA_CC_CAP_PMU 0x10000000 /* PMU available (rev >= 20) */
|
|
+ #define BCMA_CC_CAP_ECI 0x20000000 /* ECI available (rev >= 20) */
|
|
+ #define BCMA_CC_CAP_SPROM 0x40000000 /* SPROM present */
|
|
++#define BCMA_CC_CAP_NFLASH 0x80000000 /* NAND flash present (rev >= 35 or BCM4706?) */
|
|
+ #define BCMA_CC_CORECTL 0x0008
|
|
+ #define BCMA_CC_CORECTL_UARTCLK0 0x00000001 /* Drive UART with internal clock */
|
|
+ #define BCMA_CC_CORECTL_SE 0x00000002 /* sync clk out enable (corerev >= 3) */
|
|
+@@ -56,6 +60,9 @@
|
|
#define BCMA_CC_OTPS_HW_PROTECT 0x00000001
|
|
#define BCMA_CC_OTPS_SW_PROTECT 0x00000002
|
|
#define BCMA_CC_OTPS_CID_PROTECT 0x00000004
|
|
@@ -2903,7 +4439,7 @@
|
|
#define BCMA_CC_OTPC 0x0014 /* OTP control */
|
|
#define BCMA_CC_OTPC_RECWAIT 0xFF000000
|
|
#define BCMA_CC_OTPC_PROGWAIT 0x00FFFF00
|
|
-@@ -72,6 +75,8 @@
|
|
+@@ -72,6 +79,8 @@
|
|
#define BCMA_CC_OTPP_READ 0x40000000
|
|
#define BCMA_CC_OTPP_START 0x80000000
|
|
#define BCMA_CC_OTPP_BUSY 0x80000000
|
|
@@ -2912,7 +4448,7 @@
|
|
#define BCMA_CC_IRQSTAT 0x0020
|
|
#define BCMA_CC_IRQMASK 0x0024
|
|
#define BCMA_CC_IRQ_GPIO 0x00000001 /* gpio intr */
|
|
-@@ -79,6 +84,15 @@
|
|
+@@ -79,6 +88,23 @@
|
|
#define BCMA_CC_IRQ_WDRESET 0x80000000 /* watchdog reset occurred */
|
|
#define BCMA_CC_CHIPCTL 0x0028 /* Rev >= 11 only */
|
|
#define BCMA_CC_CHIPSTAT 0x002C /* Rev >= 11 only */
|
|
@@ -2920,15 +4456,82 @@
|
|
+#define BCMA_CC_CHIPST_4313_OTP_PRESENT 2
|
|
+#define BCMA_CC_CHIPST_4331_SPROM_PRESENT 2
|
|
+#define BCMA_CC_CHIPST_4331_OTP_PRESENT 4
|
|
++#define BCMA_CC_CHIPST_43228_ILP_DIV_EN 0x00000001
|
|
++#define BCMA_CC_CHIPST_43228_OTP_PRESENT 0x00000002
|
|
++#define BCMA_CC_CHIPST_43228_SERDES_REFCLK_PADSEL 0x00000004
|
|
++#define BCMA_CC_CHIPST_43228_SDIO_MODE 0x00000008
|
|
++#define BCMA_CC_CHIPST_43228_SDIO_OTP_PRESENT 0x00000010
|
|
++#define BCMA_CC_CHIPST_43228_SDIO_RESET 0x00000020
|
|
+#define BCMA_CC_CHIPST_4706_PKG_OPTION BIT(0) /* 0: full-featured package 1: low-cost package */
|
|
+#define BCMA_CC_CHIPST_4706_SFLASH_PRESENT BIT(1) /* 0: parallel, 1: serial flash is present */
|
|
+#define BCMA_CC_CHIPST_4706_SFLASH_TYPE BIT(2) /* 0: 8b-p/ST-s flash, 1: 16b-p/Atmal-s flash */
|
|
+#define BCMA_CC_CHIPST_4706_MIPS_BENDIAN BIT(3) /* 0: little, 1: big endian */
|
|
+#define BCMA_CC_CHIPST_4706_PCIE1_DISABLE BIT(5) /* PCIE1 enable strap pin */
|
|
++#define BCMA_CC_CHIPST_5357_NAND_BOOT BIT(4) /* NAND boot, valid for CC rev 38 and/or BCM5357 */
|
|
++#define BCMA_CC_CHIPST_4360_XTAL_40MZ 0x00000001
|
|
#define BCMA_CC_JCMD 0x0030 /* Rev >= 10 only */
|
|
#define BCMA_CC_JCMD_START 0x80000000
|
|
#define BCMA_CC_JCMD_BUSY 0x80000000
|
|
-@@ -181,6 +195,22 @@
|
|
+@@ -108,10 +134,58 @@
|
|
+ #define BCMA_CC_JCTL_EXT_EN 2 /* Enable external targets */
|
|
+ #define BCMA_CC_JCTL_EN 1 /* Enable Jtag master */
|
|
+ #define BCMA_CC_FLASHCTL 0x0040
|
|
++/* Start/busy bit in flashcontrol */
|
|
++#define BCMA_CC_FLASHCTL_OPCODE 0x000000ff
|
|
++#define BCMA_CC_FLASHCTL_ACTION 0x00000700
|
|
++#define BCMA_CC_FLASHCTL_CS_ACTIVE 0x00001000 /* Chip Select Active, rev >= 20 */
|
|
+ #define BCMA_CC_FLASHCTL_START 0x80000000
|
|
+ #define BCMA_CC_FLASHCTL_BUSY BCMA_CC_FLASHCTL_START
|
|
++/* Flashcontrol action + opcodes for ST flashes */
|
|
++#define BCMA_CC_FLASHCTL_ST_WREN 0x0006 /* Write Enable */
|
|
++#define BCMA_CC_FLASHCTL_ST_WRDIS 0x0004 /* Write Disable */
|
|
++#define BCMA_CC_FLASHCTL_ST_RDSR 0x0105 /* Read Status Register */
|
|
++#define BCMA_CC_FLASHCTL_ST_WRSR 0x0101 /* Write Status Register */
|
|
++#define BCMA_CC_FLASHCTL_ST_READ 0x0303 /* Read Data Bytes */
|
|
++#define BCMA_CC_FLASHCTL_ST_PP 0x0302 /* Page Program */
|
|
++#define BCMA_CC_FLASHCTL_ST_SE 0x02d8 /* Sector Erase */
|
|
++#define BCMA_CC_FLASHCTL_ST_BE 0x00c7 /* Bulk Erase */
|
|
++#define BCMA_CC_FLASHCTL_ST_DP 0x00b9 /* Deep Power-down */
|
|
++#define BCMA_CC_FLASHCTL_ST_RES 0x03ab /* Read Electronic Signature */
|
|
++#define BCMA_CC_FLASHCTL_ST_CSA 0x1000 /* Keep chip select asserted */
|
|
++#define BCMA_CC_FLASHCTL_ST_SSE 0x0220 /* Sub-sector Erase */
|
|
++/* Flashcontrol action + opcodes for Atmel flashes */
|
|
++#define BCMA_CC_FLASHCTL_AT_READ 0x07e8
|
|
++#define BCMA_CC_FLASHCTL_AT_PAGE_READ 0x07d2
|
|
++#define BCMA_CC_FLASHCTL_AT_STATUS 0x01d7
|
|
++#define BCMA_CC_FLASHCTL_AT_BUF1_WRITE 0x0384
|
|
++#define BCMA_CC_FLASHCTL_AT_BUF2_WRITE 0x0387
|
|
++#define BCMA_CC_FLASHCTL_AT_BUF1_ERASE_PROGRAM 0x0283
|
|
++#define BCMA_CC_FLASHCTL_AT_BUF2_ERASE_PROGRAM 0x0286
|
|
++#define BCMA_CC_FLASHCTL_AT_BUF1_PROGRAM 0x0288
|
|
++#define BCMA_CC_FLASHCTL_AT_BUF2_PROGRAM 0x0289
|
|
++#define BCMA_CC_FLASHCTL_AT_PAGE_ERASE 0x0281
|
|
++#define BCMA_CC_FLASHCTL_AT_BLOCK_ERASE 0x0250
|
|
++#define BCMA_CC_FLASHCTL_AT_BUF1_WRITE_ERASE_PROGRAM 0x0382
|
|
++#define BCMA_CC_FLASHCTL_AT_BUF2_WRITE_ERASE_PROGRAM 0x0385
|
|
++#define BCMA_CC_FLASHCTL_AT_BUF1_LOAD 0x0253
|
|
++#define BCMA_CC_FLASHCTL_AT_BUF2_LOAD 0x0255
|
|
++#define BCMA_CC_FLASHCTL_AT_BUF1_COMPARE 0x0260
|
|
++#define BCMA_CC_FLASHCTL_AT_BUF2_COMPARE 0x0261
|
|
++#define BCMA_CC_FLASHCTL_AT_BUF1_REPROGRAM 0x0258
|
|
++#define BCMA_CC_FLASHCTL_AT_BUF2_REPROGRAM 0x0259
|
|
+ #define BCMA_CC_FLASHADDR 0x0044
|
|
+ #define BCMA_CC_FLASHDATA 0x0048
|
|
++/* Status register bits for ST flashes */
|
|
++#define BCMA_CC_FLASHDATA_ST_WIP 0x01 /* Write In Progress */
|
|
++#define BCMA_CC_FLASHDATA_ST_WEL 0x02 /* Write Enable Latch */
|
|
++#define BCMA_CC_FLASHDATA_ST_BP_MASK 0x1c /* Block Protect */
|
|
++#define BCMA_CC_FLASHDATA_ST_BP_SHIFT 2
|
|
++#define BCMA_CC_FLASHDATA_ST_SRWD 0x80 /* Status Register Write Disable */
|
|
++/* Status register bits for Atmel flashes */
|
|
++#define BCMA_CC_FLASHDATA_AT_READY 0x80
|
|
++#define BCMA_CC_FLASHDATA_AT_MISMATCH 0x40
|
|
++#define BCMA_CC_FLASHDATA_AT_ID_MASK 0x38
|
|
++#define BCMA_CC_FLASHDATA_AT_ID_SHIFT 3
|
|
+ #define BCMA_CC_BCAST_ADDR 0x0050
|
|
+ #define BCMA_CC_BCAST_DATA 0x0054
|
|
+ #define BCMA_CC_GPIOPULLUP 0x0058 /* Rev >= 20 only */
|
|
+@@ -181,6 +255,45 @@
|
|
#define BCMA_CC_FLASH_CFG 0x0128
|
|
#define BCMA_CC_FLASH_CFG_DS 0x0010 /* Data size, 0=8bit, 1=16bit */
|
|
#define BCMA_CC_FLASH_WAITCNT 0x012C
|
|
@@ -2948,18 +4551,120 @@
|
|
+#define BCMA_CC_SROM_CONTROL_SIZE_16K 0x00000004
|
|
+#define BCMA_CC_SROM_CONTROL_SIZE_SHIFT 1
|
|
+#define BCMA_CC_SROM_CONTROL_PRESENT 0x00000001
|
|
++/* Block 0x140 - 0x190 registers are chipset specific */
|
|
++#define BCMA_CC_4706_FLASHSCFG 0x18C /* Flash struct configuration */
|
|
++#define BCMA_CC_4706_FLASHSCFG_MASK 0x000000ff
|
|
++#define BCMA_CC_4706_FLASHSCFG_SF1 0x00000001 /* 2nd serial flash present */
|
|
++#define BCMA_CC_4706_FLASHSCFG_PF1 0x00000002 /* 2nd parallel flash present */
|
|
++#define BCMA_CC_4706_FLASHSCFG_SF1_TYPE 0x00000004 /* 2nd serial flash type : 0 : ST, 1 : Atmel */
|
|
++#define BCMA_CC_4706_FLASHSCFG_NF1 0x00000008 /* 2nd NAND flash present */
|
|
++#define BCMA_CC_4706_FLASHSCFG_1ST_MADDR_SEG_MASK 0x000000f0
|
|
++#define BCMA_CC_4706_FLASHSCFG_1ST_MADDR_SEG_4MB 0x00000010 /* 4MB */
|
|
++#define BCMA_CC_4706_FLASHSCFG_1ST_MADDR_SEG_8MB 0x00000020 /* 8MB */
|
|
++#define BCMA_CC_4706_FLASHSCFG_1ST_MADDR_SEG_16MB 0x00000030 /* 16MB */
|
|
++#define BCMA_CC_4706_FLASHSCFG_1ST_MADDR_SEG_32MB 0x00000040 /* 32MB */
|
|
++#define BCMA_CC_4706_FLASHSCFG_1ST_MADDR_SEG_64MB 0x00000050 /* 64MB */
|
|
++#define BCMA_CC_4706_FLASHSCFG_1ST_MADDR_SEG_128MB 0x00000060 /* 128MB */
|
|
++#define BCMA_CC_4706_FLASHSCFG_1ST_MADDR_SEG_256MB 0x00000070 /* 256MB */
|
|
++/* NAND flash registers for BCM4706 (corerev = 31) */
|
|
++#define BCMA_CC_NFLASH_CTL 0x01A0
|
|
++#define BCMA_CC_NFLASH_CTL_ERR 0x08000000
|
|
++#define BCMA_CC_NFLASH_CONF 0x01A4
|
|
++#define BCMA_CC_NFLASH_COL_ADDR 0x01A8
|
|
++#define BCMA_CC_NFLASH_ROW_ADDR 0x01AC
|
|
++#define BCMA_CC_NFLASH_DATA 0x01B0
|
|
++#define BCMA_CC_NFLASH_WAITCNT0 0x01B4
|
|
/* 0x1E0 is defined as shared BCMA_CLKCTLST */
|
|
#define BCMA_CC_HW_WORKAROUND 0x01E4 /* Hardware workaround (rev >= 20) */
|
|
#define BCMA_CC_UART0_DATA 0x0300
|
|
-@@ -240,7 +270,6 @@
|
|
+@@ -203,6 +316,9 @@
|
|
+ #define BCMA_CC_PMU_CTL 0x0600 /* PMU control */
|
|
+ #define BCMA_CC_PMU_CTL_ILP_DIV 0xFFFF0000 /* ILP div mask */
|
|
+ #define BCMA_CC_PMU_CTL_ILP_DIV_SHIFT 16
|
|
++#define BCMA_CC_PMU_CTL_RES 0x00006000 /* reset control mask */
|
|
++#define BCMA_CC_PMU_CTL_RES_SHIFT 13
|
|
++#define BCMA_CC_PMU_CTL_RES_RELOAD 0x2 /* reload POR values */
|
|
+ #define BCMA_CC_PMU_CTL_PLL_UPD 0x00000400
|
|
+ #define BCMA_CC_PMU_CTL_NOILPONW 0x00000200 /* No ILP on wait */
|
|
+ #define BCMA_CC_PMU_CTL_HTREQEN 0x00000100 /* HT req enable */
|
|
+@@ -214,6 +330,8 @@
|
|
+ #define BCMA_CC_PMU_CAP 0x0604 /* PMU capabilities */
|
|
+ #define BCMA_CC_PMU_CAP_REVISION 0x000000FF /* Revision mask */
|
|
+ #define BCMA_CC_PMU_STAT 0x0608 /* PMU status */
|
|
++#define BCMA_CC_PMU_STAT_EXT_LPO_AVAIL 0x00000100
|
|
++#define BCMA_CC_PMU_STAT_WDRESET 0x00000080
|
|
+ #define BCMA_CC_PMU_STAT_INTPEND 0x00000040 /* Interrupt pending */
|
|
+ #define BCMA_CC_PMU_STAT_SBCLKST 0x00000030 /* Backplane clock status? */
|
|
+ #define BCMA_CC_PMU_STAT_HAVEALP 0x00000008 /* ALP available */
|
|
+@@ -239,8 +357,66 @@
|
|
+ #define BCMA_CC_REGCTL_DATA 0x065C
|
|
#define BCMA_CC_PLLCTL_ADDR 0x0660
|
|
#define BCMA_CC_PLLCTL_DATA 0x0664
|
|
++#define BCMA_CC_PMU_STRAPOPT 0x0668 /* (corerev >= 28) */
|
|
++#define BCMA_CC_PMU_XTAL_FREQ 0x066C /* (pmurev >= 10) */
|
|
++#define BCMA_CC_PMU_XTAL_FREQ_ILPCTL_MASK 0x00001FFF
|
|
++#define BCMA_CC_PMU_XTAL_FREQ_MEASURE_MASK 0x80000000
|
|
++#define BCMA_CC_PMU_XTAL_FREQ_MEASURE_SHIFT 31
|
|
#define BCMA_CC_SPROM 0x0800 /* SPROM beginning */
|
|
-#define BCMA_CC_SPROM_PCIE6 0x0830 /* SPROM beginning on PCIe rev >= 6 */
|
|
++/* NAND flash MLC controller registers (corerev >= 38) */
|
|
++#define BCMA_CC_NAND_REVISION 0x0C00
|
|
++#define BCMA_CC_NAND_CMD_START 0x0C04
|
|
++#define BCMA_CC_NAND_CMD_ADDR_X 0x0C08
|
|
++#define BCMA_CC_NAND_CMD_ADDR 0x0C0C
|
|
++#define BCMA_CC_NAND_CMD_END_ADDR 0x0C10
|
|
++#define BCMA_CC_NAND_CS_NAND_SELECT 0x0C14
|
|
++#define BCMA_CC_NAND_CS_NAND_XOR 0x0C18
|
|
++#define BCMA_CC_NAND_SPARE_RD0 0x0C20
|
|
++#define BCMA_CC_NAND_SPARE_RD4 0x0C24
|
|
++#define BCMA_CC_NAND_SPARE_RD8 0x0C28
|
|
++#define BCMA_CC_NAND_SPARE_RD12 0x0C2C
|
|
++#define BCMA_CC_NAND_SPARE_WR0 0x0C30
|
|
++#define BCMA_CC_NAND_SPARE_WR4 0x0C34
|
|
++#define BCMA_CC_NAND_SPARE_WR8 0x0C38
|
|
++#define BCMA_CC_NAND_SPARE_WR12 0x0C3C
|
|
++#define BCMA_CC_NAND_ACC_CONTROL 0x0C40
|
|
++#define BCMA_CC_NAND_CONFIG 0x0C48
|
|
++#define BCMA_CC_NAND_TIMING_1 0x0C50
|
|
++#define BCMA_CC_NAND_TIMING_2 0x0C54
|
|
++#define BCMA_CC_NAND_SEMAPHORE 0x0C58
|
|
++#define BCMA_CC_NAND_DEVID 0x0C60
|
|
++#define BCMA_CC_NAND_DEVID_X 0x0C64
|
|
++#define BCMA_CC_NAND_BLOCK_LOCK_STATUS 0x0C68
|
|
++#define BCMA_CC_NAND_INTFC_STATUS 0x0C6C
|
|
++#define BCMA_CC_NAND_ECC_CORR_ADDR_X 0x0C70
|
|
++#define BCMA_CC_NAND_ECC_CORR_ADDR 0x0C74
|
|
++#define BCMA_CC_NAND_ECC_UNC_ADDR_X 0x0C78
|
|
++#define BCMA_CC_NAND_ECC_UNC_ADDR 0x0C7C
|
|
++#define BCMA_CC_NAND_READ_ERROR_COUNT 0x0C80
|
|
++#define BCMA_CC_NAND_CORR_STAT_THRESHOLD 0x0C84
|
|
++#define BCMA_CC_NAND_READ_ADDR_X 0x0C90
|
|
++#define BCMA_CC_NAND_READ_ADDR 0x0C94
|
|
++#define BCMA_CC_NAND_PAGE_PROGRAM_ADDR_X 0x0C98
|
|
++#define BCMA_CC_NAND_PAGE_PROGRAM_ADDR 0x0C9C
|
|
++#define BCMA_CC_NAND_COPY_BACK_ADDR_X 0x0CA0
|
|
++#define BCMA_CC_NAND_COPY_BACK_ADDR 0x0CA4
|
|
++#define BCMA_CC_NAND_BLOCK_ERASE_ADDR_X 0x0CA8
|
|
++#define BCMA_CC_NAND_BLOCK_ERASE_ADDR 0x0CAC
|
|
++#define BCMA_CC_NAND_INV_READ_ADDR_X 0x0CB0
|
|
++#define BCMA_CC_NAND_INV_READ_ADDR 0x0CB4
|
|
++#define BCMA_CC_NAND_BLK_WR_PROTECT 0x0CC0
|
|
++#define BCMA_CC_NAND_ACC_CONTROL_CS1 0x0CD0
|
|
++#define BCMA_CC_NAND_CONFIG_CS1 0x0CD4
|
|
++#define BCMA_CC_NAND_TIMING_1_CS1 0x0CD8
|
|
++#define BCMA_CC_NAND_TIMING_2_CS1 0x0CDC
|
|
++#define BCMA_CC_NAND_SPARE_RD16 0x0D30
|
|
++#define BCMA_CC_NAND_SPARE_RD20 0x0D34
|
|
++#define BCMA_CC_NAND_SPARE_RD24 0x0D38
|
|
++#define BCMA_CC_NAND_SPARE_RD28 0x0D3C
|
|
++#define BCMA_CC_NAND_CACHE_ADDR 0x0D40
|
|
++#define BCMA_CC_NAND_CACHE_DATA 0x0D44
|
|
++#define BCMA_CC_NAND_CTRL_CONFIG 0x0D48
|
|
++#define BCMA_CC_NAND_CTRL_STATUS 0x0D4C
|
|
|
|
/* Divider allocation in 4716/47162/5356 */
|
|
#define BCMA_CC_PMU5_MAINPLL_CPU 1
|
|
-@@ -256,6 +285,15 @@
|
|
+@@ -256,6 +432,32 @@
|
|
|
|
/* 4706 PMU */
|
|
#define BCMA_CC_PMU4706_MAINPLL_PLL0 0
|
|
@@ -2972,10 +4677,27 @@
|
|
+#define BCMA_CC_PMU6_4706_PROC_NDIV_INT_SHIFT 3
|
|
+#define BCMA_CC_PMU6_4706_PROC_NDIV_MODE_MASK 0x00000007
|
|
+#define BCMA_CC_PMU6_4706_PROC_NDIV_MODE_SHIFT 0
|
|
++
|
|
++/* PMU rev 15 */
|
|
++#define BCMA_CC_PMU15_PLL_PLLCTL0 0
|
|
++#define BCMA_CC_PMU15_PLL_PC0_CLKSEL_MASK 0x00000003
|
|
++#define BCMA_CC_PMU15_PLL_PC0_CLKSEL_SHIFT 0
|
|
++#define BCMA_CC_PMU15_PLL_PC0_FREQTGT_MASK 0x003FFFFC
|
|
++#define BCMA_CC_PMU15_PLL_PC0_FREQTGT_SHIFT 2
|
|
++#define BCMA_CC_PMU15_PLL_PC0_PRESCALE_MASK 0x00C00000
|
|
++#define BCMA_CC_PMU15_PLL_PC0_PRESCALE_SHIFT 22
|
|
++#define BCMA_CC_PMU15_PLL_PC0_KPCTRL_MASK 0x07000000
|
|
++#define BCMA_CC_PMU15_PLL_PC0_KPCTRL_SHIFT 24
|
|
++#define BCMA_CC_PMU15_PLL_PC0_FCNTCTRL_MASK 0x38000000
|
|
++#define BCMA_CC_PMU15_PLL_PC0_FCNTCTRL_SHIFT 27
|
|
++#define BCMA_CC_PMU15_PLL_PC0_FDCMODE_MASK 0x40000000
|
|
++#define BCMA_CC_PMU15_PLL_PC0_FDCMODE_SHIFT 30
|
|
++#define BCMA_CC_PMU15_PLL_PC0_CTRLBIAS_MASK 0x80000000
|
|
++#define BCMA_CC_PMU15_PLL_PC0_CTRLBIAS_SHIFT 31
|
|
|
|
/* ALP clock on pre-PMU chips */
|
|
#define BCMA_CC_PMU_ALP_CLOCK 20000000
|
|
-@@ -284,6 +322,19 @@
|
|
+@@ -284,6 +486,19 @@
|
|
#define BCMA_CC_PPL_PCHI_OFF 5
|
|
#define BCMA_CC_PPL_PCHI_MASK 0x0000003f
|
|
|
|
@@ -2995,7 +4717,7 @@
|
|
/* BCM4331 ChipControl numbers. */
|
|
#define BCMA_CHIPCTL_4331_BT_COEXIST BIT(0) /* 0 disable */
|
|
#define BCMA_CHIPCTL_4331_SECI BIT(1) /* 0 SECI is disabled (JATG functional) */
|
|
-@@ -297,9 +348,18 @@
|
|
+@@ -297,9 +512,56 @@
|
|
#define BCMA_CHIPCTL_4331_OVR_PIPEAUXPWRDOWN BIT(9) /* override core control on pipe_AuxPowerDown */
|
|
#define BCMA_CHIPCTL_4331_PCIE_AUXCLKEN BIT(10) /* pcie_auxclkenable */
|
|
#define BCMA_CHIPCTL_4331_PCIE_PIPE_PLLDOWN BIT(11) /* pcie_pipe_pllpowerdown */
|
|
@@ -3011,14 +4733,109 @@
|
|
+/* 4313 Chip specific ChipControl register bits */
|
|
+#define BCMA_CCTRL_4313_12MA_LED_DRIVE 0x00000007 /* 12 mA drive strengh for later 4313 */
|
|
+
|
|
++/* BCM5357 ChipControl register bits */
|
|
++#define BCMA_CHIPCTL_5357_EXTPA BIT(14)
|
|
++#define BCMA_CHIPCTL_5357_ANT_MUX_2O3 BIT(15)
|
|
++#define BCMA_CHIPCTL_5357_NFLASH BIT(16)
|
|
++#define BCMA_CHIPCTL_5357_I2S_PINS_ENABLE BIT(18)
|
|
++#define BCMA_CHIPCTL_5357_I2CSPI_PINS_ENABLE BIT(19)
|
|
++
|
|
++#define BCMA_RES_4314_LPLDO_PU BIT(0)
|
|
++#define BCMA_RES_4314_PMU_SLEEP_DIS BIT(1)
|
|
++#define BCMA_RES_4314_PMU_BG_PU BIT(2)
|
|
++#define BCMA_RES_4314_CBUCK_LPOM_PU BIT(3)
|
|
++#define BCMA_RES_4314_CBUCK_PFM_PU BIT(4)
|
|
++#define BCMA_RES_4314_CLDO_PU BIT(5)
|
|
++#define BCMA_RES_4314_LPLDO2_LVM BIT(6)
|
|
++#define BCMA_RES_4314_WL_PMU_PU BIT(7)
|
|
++#define BCMA_RES_4314_LNLDO_PU BIT(8)
|
|
++#define BCMA_RES_4314_LDO3P3_PU BIT(9)
|
|
++#define BCMA_RES_4314_OTP_PU BIT(10)
|
|
++#define BCMA_RES_4314_XTAL_PU BIT(11)
|
|
++#define BCMA_RES_4314_WL_PWRSW_PU BIT(12)
|
|
++#define BCMA_RES_4314_LQ_AVAIL BIT(13)
|
|
++#define BCMA_RES_4314_LOGIC_RET BIT(14)
|
|
++#define BCMA_RES_4314_MEM_SLEEP BIT(15)
|
|
++#define BCMA_RES_4314_MACPHY_RET BIT(16)
|
|
++#define BCMA_RES_4314_WL_CORE_READY BIT(17)
|
|
++#define BCMA_RES_4314_ILP_REQ BIT(18)
|
|
++#define BCMA_RES_4314_ALP_AVAIL BIT(19)
|
|
++#define BCMA_RES_4314_MISC_PWRSW_PU BIT(20)
|
|
++#define BCMA_RES_4314_SYNTH_PWRSW_PU BIT(21)
|
|
++#define BCMA_RES_4314_RX_PWRSW_PU BIT(22)
|
|
++#define BCMA_RES_4314_RADIO_PU BIT(23)
|
|
++#define BCMA_RES_4314_VCO_LDO_PU BIT(24)
|
|
++#define BCMA_RES_4314_AFE_LDO_PU BIT(25)
|
|
++#define BCMA_RES_4314_RX_LDO_PU BIT(26)
|
|
++#define BCMA_RES_4314_TX_LDO_PU BIT(27)
|
|
++#define BCMA_RES_4314_HT_AVAIL BIT(28)
|
|
++#define BCMA_RES_4314_MACPHY_CLK_AVAIL BIT(29)
|
|
++
|
|
/* Data for the PMU, if available.
|
|
* Check availability with ((struct bcma_chipcommon)->capabilities & BCMA_CC_CAP_PMU)
|
|
*/
|
|
-@@ -387,5 +447,6 @@ extern void bcma_chipco_chipctl_maskset(
|
|
+@@ -330,6 +592,7 @@ struct bcma_drv_cc {
|
|
+ u32 capabilities;
|
|
+ u32 capabilities_ext;
|
|
+ u8 setup_done:1;
|
|
++ u8 early_setup_done:1;
|
|
+ /* Fast Powerup Delay constant */
|
|
+ u16 fast_pwrup_delay;
|
|
+ struct bcma_chipcommon_pmu pmu;
|
|
+@@ -339,6 +602,14 @@ struct bcma_drv_cc {
|
|
+ int nr_serial_ports;
|
|
+ struct bcma_serial_port serial_ports[4];
|
|
+ #endif /* CONFIG_BCMA_DRIVER_MIPS */
|
|
++ u32 ticks_per_ms;
|
|
++ struct platform_device *watchdog;
|
|
++
|
|
++ /* Lock for GPIO register access. */
|
|
++ spinlock_t gpio_lock;
|
|
++#ifdef CONFIG_BCMA_DRIVER_GPIO
|
|
++ struct gpio_chip gpio;
|
|
++#endif
|
|
+ };
|
|
+
|
|
+ /* Register access */
|
|
+@@ -355,14 +626,16 @@ struct bcma_drv_cc {
|
|
+ bcma_cc_write32(cc, offset, (bcma_cc_read32(cc, offset) & (mask)) | (set))
|
|
+
|
|
+ extern void bcma_core_chipcommon_init(struct bcma_drv_cc *cc);
|
|
++extern void bcma_core_chipcommon_early_init(struct bcma_drv_cc *cc);
|
|
+
|
|
+ extern void bcma_chipco_suspend(struct bcma_drv_cc *cc);
|
|
+ extern void bcma_chipco_resume(struct bcma_drv_cc *cc);
|
|
+
|
|
+ void bcma_chipco_bcm4331_ext_pa_lines_ctl(struct bcma_drv_cc *cc, bool enable);
|
|
+
|
|
+-extern void bcma_chipco_watchdog_timer_set(struct bcma_drv_cc *cc,
|
|
+- u32 ticks);
|
|
++extern u32 bcma_chipco_watchdog_timer_set(struct bcma_drv_cc *cc, u32 ticks);
|
|
++
|
|
++extern u32 bcma_chipco_get_alp_clock(struct bcma_drv_cc *cc);
|
|
+
|
|
+ void bcma_chipco_irq_mask(struct bcma_drv_cc *cc, u32 mask, u32 value);
|
|
+
|
|
+@@ -375,9 +648,12 @@ u32 bcma_chipco_gpio_outen(struct bcma_d
|
|
+ u32 bcma_chipco_gpio_control(struct bcma_drv_cc *cc, u32 mask, u32 value);
|
|
+ u32 bcma_chipco_gpio_intmask(struct bcma_drv_cc *cc, u32 mask, u32 value);
|
|
+ u32 bcma_chipco_gpio_polarity(struct bcma_drv_cc *cc, u32 mask, u32 value);
|
|
++u32 bcma_chipco_gpio_pullup(struct bcma_drv_cc *cc, u32 mask, u32 value);
|
|
++u32 bcma_chipco_gpio_pulldown(struct bcma_drv_cc *cc, u32 mask, u32 value);
|
|
+
|
|
+ /* PMU support */
|
|
+ extern void bcma_pmu_init(struct bcma_drv_cc *cc);
|
|
++extern void bcma_pmu_early_init(struct bcma_drv_cc *cc);
|
|
+
|
|
+ extern void bcma_chipco_pll_write(struct bcma_drv_cc *cc, u32 offset,
|
|
+ u32 value);
|
|
+@@ -387,5 +663,8 @@ extern void bcma_chipco_chipctl_maskset(
|
|
u32 offset, u32 mask, u32 set);
|
|
extern void bcma_chipco_regctl_maskset(struct bcma_drv_cc *cc,
|
|
u32 offset, u32 mask, u32 set);
|
|
+extern void bcma_pmu_spuravoid_pllupdate(struct bcma_drv_cc *cc, int spuravoid);
|
|
++
|
|
++extern u32 bcma_pmu_get_bus_clock(struct bcma_drv_cc *cc);
|
|
|
|
#endif /* LINUX_BCMA_DRIVER_CC_H_ */
|
|
--- /dev/null
|
|
@@ -3124,6 +4941,44 @@
|
|
+#endif
|
|
+
|
|
+#endif /* LINUX_BCMA_DRIVER_GMAC_CMN_H_ */
|
|
+--- a/include/linux/bcma/bcma_driver_mips.h
|
|
++++ b/include/linux/bcma/bcma_driver_mips.h
|
|
+@@ -28,6 +28,7 @@
|
|
+ #define BCMA_MIPS_MIPS74K_GPIOEN 0x0048
|
|
+ #define BCMA_MIPS_MIPS74K_CLKCTLST 0x01E0
|
|
+
|
|
++#define BCMA_MIPS_OOBSELINA74 0x004
|
|
+ #define BCMA_MIPS_OOBSELOUTA30 0x100
|
|
+
|
|
+ struct bcma_device;
|
|
+@@ -35,17 +36,24 @@ struct bcma_device;
|
|
+ struct bcma_drv_mips {
|
|
+ struct bcma_device *core;
|
|
+ u8 setup_done:1;
|
|
+- unsigned int assigned_irqs;
|
|
++ u8 early_setup_done:1;
|
|
+ };
|
|
+
|
|
+ #ifdef CONFIG_BCMA_DRIVER_MIPS
|
|
+ extern void bcma_core_mips_init(struct bcma_drv_mips *mcore);
|
|
++extern void bcma_core_mips_early_init(struct bcma_drv_mips *mcore);
|
|
++
|
|
++extern unsigned int bcma_core_irq(struct bcma_device *core);
|
|
+ #else
|
|
+ static inline void bcma_core_mips_init(struct bcma_drv_mips *mcore) { }
|
|
++static inline void bcma_core_mips_early_init(struct bcma_drv_mips *mcore) { }
|
|
++
|
|
++static inline unsigned int bcma_core_irq(struct bcma_device *core)
|
|
++{
|
|
++ return 0;
|
|
++}
|
|
+ #endif
|
|
+
|
|
+ extern u32 bcma_cpu_clock(struct bcma_drv_mips *mcore);
|
|
+
|
|
+-extern unsigned int bcma_core_mips_irq(struct bcma_device *dev);
|
|
+-
|
|
+ #endif /* LINUX_BCMA_DRIVER_MIPS_H_ */
|
|
--- a/include/linux/bcma/bcma_driver_pci.h
|
|
+++ b/include/linux/bcma/bcma_driver_pci.h
|
|
@@ -53,11 +53,47 @@ struct pci_dev;
|
|
@@ -3174,7 +5029,7 @@
|
|
|
|
/* SBtoPCIx */
|
|
#define BCMA_CORE_PCI_SBTOPCI_MEM 0x00000000
|
|
-@@ -72,20 +108,118 @@ struct pci_dev;
|
|
+@@ -72,20 +108,120 @@ struct pci_dev;
|
|
#define BCMA_CORE_PCI_SBTOPCI_RC_READL 0x00000010 /* Memory read line */
|
|
#define BCMA_CORE_PCI_SBTOPCI_RC_READM 0x00000020 /* Memory read multiple */
|
|
|
|
@@ -3249,6 +5104,8 @@
|
|
+#define BCMA_CORE_PCI_CFG_FUN_MASK 7 /* Function mask */
|
|
+#define BCMA_CORE_PCI_CFG_OFF_MASK 0xfff /* Register mask */
|
|
+
|
|
++#define BCMA_CORE_PCI_CFG_DEVCTRL 0xd8
|
|
++
|
|
+/* PCIE Root Capability Register bits (Host mode only) */
|
|
+#define BCMA_CORE_PCI_RC_CRS_VISIBILITY 0x0001
|
|
+
|
|
@@ -3296,7 +5153,29 @@
|
|
#endif /* LINUX_BCMA_DRIVER_PCI_H_ */
|
|
--- a/include/linux/bcma/bcma_regs.h
|
|
+++ b/include/linux/bcma/bcma_regs.h
|
|
-@@ -56,4 +56,31 @@
|
|
+@@ -11,11 +11,13 @@
|
|
+ #define BCMA_CLKCTLST_HAVEHTREQ 0x00000010 /* HT available request */
|
|
+ #define BCMA_CLKCTLST_HWCROFF 0x00000020 /* Force HW clock request off */
|
|
+ #define BCMA_CLKCTLST_EXTRESREQ 0x00000700 /* Mask of external resource requests */
|
|
++#define BCMA_CLKCTLST_EXTRESREQ_SHIFT 8
|
|
+ #define BCMA_CLKCTLST_HAVEALP 0x00010000 /* ALP available */
|
|
+ #define BCMA_CLKCTLST_HAVEHT 0x00020000 /* HT available */
|
|
+ #define BCMA_CLKCTLST_BP_ON_ALP 0x00040000 /* RO: running on ALP clock */
|
|
+ #define BCMA_CLKCTLST_BP_ON_HT 0x00080000 /* RO: running on HT clock */
|
|
+ #define BCMA_CLKCTLST_EXTRESST 0x07000000 /* Mask of external resource status */
|
|
++#define BCMA_CLKCTLST_EXTRESST_SHIFT 24
|
|
+ /* Is there any BCM4328 on BCMA bus? */
|
|
+ #define BCMA_CLKCTLST_4328A0_HAVEHT 0x00010000 /* 4328a0 has reversed bits */
|
|
+ #define BCMA_CLKCTLST_4328A0_HAVEALP 0x00020000 /* 4328a0 has reversed bits */
|
|
+@@ -35,6 +37,7 @@
|
|
+ #define BCMA_IOST_BIST_DONE 0x8000
|
|
+ #define BCMA_RESET_CTL 0x0800
|
|
+ #define BCMA_RESET_CTL_RESET 0x0001
|
|
++#define BCMA_RESET_ST 0x0804
|
|
+
|
|
+ /* BCMA PCI config space registers. */
|
|
+ #define BCMA_PCI_PMCSR 0x44
|
|
+@@ -56,4 +59,31 @@
|
|
#define BCMA_PCI_GPIO_XTAL 0x40 /* PCI config space GPIO 14 for Xtal powerup */
|
|
#define BCMA_PCI_GPIO_PLL 0x80 /* PCI config space GPIO 15 for PLL powerdown */
|
|
|
|
@@ -3328,3 +5207,25 @@
|
|
+ */
|
|
+
|
|
#endif /* LINUX_BCMA_REGS_H_ */
|
|
+--- a/drivers/net/wireless/b43/main.c
|
|
++++ b/drivers/net/wireless/b43/main.c
|
|
+@@ -4618,7 +4618,7 @@ static int b43_wireless_core_init(struct
|
|
+ switch (dev->dev->bus_type) {
|
|
+ #ifdef CONFIG_B43_BCMA
|
|
+ case B43_BUS_BCMA:
|
|
+- bcma_core_pci_irq_ctl(&dev->dev->bdev->bus->drv_pci,
|
|
++ bcma_core_pci_irq_ctl(&dev->dev->bdev->bus->drv_pci[0],
|
|
+ dev->dev->bdev, true);
|
|
+ break;
|
|
+ #endif
|
|
+--- a/drivers/net/wireless/brcm80211/brcmsmac/aiutils.c
|
|
++++ b/drivers/net/wireless/brcm80211/brcmsmac/aiutils.c
|
|
+@@ -533,7 +533,7 @@ ai_buscore_setup(struct si_info *sii, st
|
|
+
|
|
+ /* fixup necessary chip/core configurations */
|
|
+ if (!sii->pch) {
|
|
+- sii->pch = pcicore_init(&sii->pub, sii->icbus->drv_pci.core);
|
|
++ sii->pch = pcicore_init(&sii->pub, sii->icbus->drv_pci[0].core);
|
|
+ if (sii->pch == NULL)
|
|
+ return false;
|
|
+ }
|