mirror of
				git://git.openwrt.org/openwrt/openwrt.git
				synced 2025-10-29 21:14:28 -04:00 
			
		
		
		
	This is a backport of bcma from wireless-tesing/master tag master-2014-07-29-1. For kernel < 3.10 this only adds the header changes needed by more recent b43 versions. Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de> SVN-Revision: 41899
		
			
				
	
	
		
			1989 lines
		
	
	
		
			61 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
			
		
		
	
	
			1989 lines
		
	
	
		
			61 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
| --- 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/drivers/bcma/Kconfig
 | |
| +++ b/drivers/bcma/Kconfig
 | |
| @@ -26,6 +26,7 @@ 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"
 | |
| @@ -34,8 +35,14 @@ config BCMA_DRIVER_PCI_HOSTMODE
 | |
|  	  PCI core hostmode operation (external PCI bus).
 | |
|  
 | |
|  config BCMA_HOST_SOC
 | |
| -	bool
 | |
| -	depends on BCMA_DRIVER_MIPS
 | |
| +	bool "Support for BCMA in a SoC"
 | |
| +	depends on BCMA
 | |
| +	help
 | |
| +	  Host interface for a Broadcom AIX bus directly mapped into
 | |
| +	  the memory. This only works with the Broadcom SoCs from the
 | |
| +	  BCM47XX line.
 | |
| +
 | |
| +	  If unsure, say N
 | |
|  
 | |
|  config BCMA_DRIVER_MIPS
 | |
|  	bool "BCMA Broadcom MIPS core driver"
 | |
| --- a/drivers/bcma/bcma_private.h
 | |
| +++ b/drivers/bcma/bcma_private.h
 | |
| @@ -22,6 +22,8 @@
 | |
|  struct bcma_bus;
 | |
|  
 | |
|  /* main.c */
 | |
| +bool bcma_wait_value(struct bcma_device *core, u16 reg, u32 mask, u32 value,
 | |
| +		     int timeout);
 | |
|  int 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,
 | |
| @@ -31,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);
 | |
| @@ -45,6 +49,7 @@ int bcma_sprom_get(struct bcma_bus *bus)
 | |
|  /* driver_chipcommon.c */
 | |
|  #ifdef CONFIG_BCMA_DRIVER_MIPS
 | |
|  void bcma_chipco_serial_init(struct bcma_drv_cc *cc);
 | |
| +extern struct platform_device bcma_pflash_dev;
 | |
|  #endif /* CONFIG_BCMA_DRIVER_MIPS */
 | |
|  
 | |
|  /* driver_chipcommon_pmu.c */
 | |
| --- a/drivers/bcma/core.c
 | |
| +++ b/drivers/bcma/core.c
 | |
| @@ -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,13 +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);
 | |
|  
 | |
| @@ -43,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));
 | |
| @@ -104,7 +126,13 @@ void bcma_core_pll_ctl(struct bcma_devic
 | |
|  		if (i)
 | |
|  			bcma_err(core->bus, "PLL enable timeout\n");
 | |
|  	} else {
 | |
| -		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);
 | |
| --- a/drivers/bcma/driver_chipcommon.c
 | |
| +++ b/drivers/bcma/driver_chipcommon.c
 | |
| @@ -25,13 +25,14 @@ static inline u32 bcma_cc_write32_masked
 | |
|  	return value;
 | |
|  }
 | |
|  
 | |
| -static u32 bcma_chipco_get_alp_clock(struct bcma_drv_cc *cc)
 | |
| +u32 bcma_chipco_get_alp_clock(struct bcma_drv_cc *cc)
 | |
|  {
 | |
|  	if (cc->capabilities & BCMA_CC_CAP_PMU)
 | |
|  		return bcma_pmu_get_alp_clock(cc);
 | |
|  
 | |
|  	return 20000000;
 | |
|  }
 | |
| +EXPORT_SYMBOL_GPL(bcma_chipco_get_alp_clock);
 | |
|  
 | |
|  static u32 bcma_chipco_watchdog_get_max_timer(struct bcma_drv_cc *cc)
 | |
|  {
 | |
| @@ -139,8 +140,15 @@ void bcma_core_chipcommon_init(struct bc
 | |
|  	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)
 | |
| @@ -213,6 +221,7 @@ u32 bcma_chipco_gpio_out(struct bcma_drv
 | |
|  
 | |
|  	return res;
 | |
|  }
 | |
| +EXPORT_SYMBOL_GPL(bcma_chipco_gpio_out);
 | |
|  
 | |
|  u32 bcma_chipco_gpio_outen(struct bcma_drv_cc *cc, u32 mask, u32 value)
 | |
|  {
 | |
| @@ -225,6 +234,7 @@ u32 bcma_chipco_gpio_outen(struct bcma_d
 | |
|  
 | |
|  	return res;
 | |
|  }
 | |
| +EXPORT_SYMBOL_GPL(bcma_chipco_gpio_outen);
 | |
|  
 | |
|  /*
 | |
|   * If the bit is set to 0, chipcommon controlls this GPIO,
 | |
| @@ -329,7 +339,7 @@ void bcma_chipco_serial_init(struct bcma
 | |
|  		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_nflash.c
 | |
| +++ b/drivers/bcma/driver_chipcommon_nflash.c
 | |
| @@ -5,11 +5,11 @@
 | |
|   * Licensed under the GNU/GPL. See COPYING for details.
 | |
|   */
 | |
|  
 | |
| +#include "bcma_private.h"
 | |
| +
 | |
|  #include <linux/platform_device.h>
 | |
|  #include <linux/bcma/bcma.h>
 | |
|  
 | |
| -#include "bcma_private.h"
 | |
| -
 | |
|  struct platform_device bcma_nflash_dev = {
 | |
|  	.name		= "bcma_nflash",
 | |
|  	.num_resources	= 0,
 | |
| --- a/drivers/bcma/driver_chipcommon_pmu.c
 | |
| +++ b/drivers/bcma/driver_chipcommon_pmu.c
 | |
| @@ -56,6 +56,109 @@ void bcma_chipco_regctl_maskset(struct b
 | |
|  }
 | |
|  EXPORT_SYMBOL_GPL(bcma_chipco_regctl_maskset);
 | |
|  
 | |
| +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 BCMA_CHIP_ID_BCM43142:
 | |
| +		if (xtalfreq == 0)
 | |
| +			xtalfreq = 20000;
 | |
| +		bcma_pmu2_pll_init0(cc, xtalfreq);
 | |
| +		break;
 | |
| +	}
 | |
| +}
 | |
| +
 | |
|  static void bcma_pmu_resources_init(struct bcma_drv_cc *cc)
 | |
|  {
 | |
|  	struct bcma_bus *bus = cc->core->bus;
 | |
| @@ -66,6 +169,25 @@ static void bcma_pmu_resources_init(stru
 | |
|  		min_msk = 0x200D;
 | |
|  		max_msk = 0xFFFF;
 | |
|  		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:
 | |
|  		bcma_debug(bus, "PMU resource config unknown or not needed for device 0x%04X\n",
 | |
|  			   bus->chipinfo.id);
 | |
| @@ -165,6 +287,7 @@ void bcma_pmu_init(struct bcma_drv_cc *c
 | |
|  		bcma_cc_set32(cc, BCMA_CC_PMU_CTL,
 | |
|  			     BCMA_CC_PMU_CTL_NOILPONW);
 | |
|  
 | |
| +	bcma_pmu_pll_init(cc);
 | |
|  	bcma_pmu_resources_init(cc);
 | |
|  	bcma_pmu_workarounds(cc);
 | |
|  }
 | |
| @@ -174,19 +297,35 @@ u32 bcma_pmu_get_alp_clock(struct bcma_d
 | |
|  	struct bcma_bus *bus = cc->core->bus;
 | |
|  
 | |
|  	switch (bus->chipinfo.id) {
 | |
| +	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_BCM4748:
 | |
|  	case BCMA_CHIP_ID_BCM47162:
 | |
| -	case BCMA_CHIP_ID_BCM4313:
 | |
| -	case BCMA_CHIP_ID_BCM5357:
 | |
| +	case BCMA_CHIP_ID_BCM4748:
 | |
|  	case BCMA_CHIP_ID_BCM4749:
 | |
| +	case BCMA_CHIP_ID_BCM5357:
 | |
|  	case BCMA_CHIP_ID_BCM53572:
 | |
| +	case BCMA_CHIP_ID_BCM6362:
 | |
|  		/* always 20Mhz */
 | |
|  		return 20000 * 1000;
 | |
| -	case BCMA_CHIP_ID_BCM5356:
 | |
|  	case BCMA_CHIP_ID_BCM4706:
 | |
| +	case BCMA_CHIP_ID_BCM5356:
 | |
|  		/* 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:
 | |
|  		bcma_warn(bus, "No ALP clock specified for %04X device, pmu rev. %d, using default %d Hz\n",
 | |
|  			  bus->chipinfo.id, cc->pmu.rev, BCMA_CC_PMU_ALP_CLOCK);
 | |
| @@ -264,7 +403,7 @@ static u32 bcma_pmu_pll_clock_bcm4706(st
 | |
|  }
 | |
|  
 | |
|  /* query bus clock frequency for PMU-enabled chipcommon */
 | |
| -static u32 bcma_pmu_get_bus_clock(struct bcma_drv_cc *cc)
 | |
| +u32 bcma_pmu_get_bus_clock(struct bcma_drv_cc *cc)
 | |
|  {
 | |
|  	struct bcma_bus *bus = cc->core->bus;
 | |
|  
 | |
| @@ -293,6 +432,7 @@ static u32 bcma_pmu_get_bus_clock(struct
 | |
|  	}
 | |
|  	return BCMA_CC_PMU_HT_CLOCK;
 | |
|  }
 | |
| +EXPORT_SYMBOL_GPL(bcma_pmu_get_bus_clock);
 | |
|  
 | |
|  /* query cpu clock frequency for PMU-enabled chipcommon */
 | |
|  u32 bcma_pmu_get_cpu_clock(struct bcma_drv_cc *cc)
 | |
| @@ -372,7 +512,7 @@ void bcma_pmu_spuravoid_pllupdate(struct
 | |
|  		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:
 | |
| @@ -393,7 +533,7 @@ void bcma_pmu_spuravoid_pllupdate(struct
 | |
|  			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:
 | |
| @@ -426,7 +566,7 @@ void bcma_pmu_spuravoid_pllupdate(struct
 | |
|  			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:
 | |
| @@ -460,7 +600,7 @@ void bcma_pmu_spuravoid_pllupdate(struct
 | |
|  						     0x88888815);
 | |
|  		}
 | |
|  
 | |
| -		tmp = 3 << 9;
 | |
| +		tmp = BCMA_CC_PMU_CTL_PLL_UPD | BCMA_CC_PMU_CTL_NOILPONW;
 | |
|  		break;
 | |
|  
 | |
|  	case BCMA_CHIP_ID_BCM43227:
 | |
| @@ -496,7 +636,7 @@ void bcma_pmu_spuravoid_pllupdate(struct
 | |
|  			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",
 | |
| --- a/drivers/bcma/driver_chipcommon_sflash.c
 | |
| +++ b/drivers/bcma/driver_chipcommon_sflash.c
 | |
| @@ -5,11 +5,11 @@
 | |
|   * Licensed under the GNU/GPL. See COPYING for details.
 | |
|   */
 | |
|  
 | |
| +#include "bcma_private.h"
 | |
| +
 | |
|  #include <linux/platform_device.h>
 | |
|  #include <linux/bcma/bcma.h>
 | |
|  
 | |
| -#include "bcma_private.h"
 | |
| -
 | |
|  static struct resource bcma_sflash_resource = {
 | |
|  	.name	= "bcma_sflash",
 | |
|  	.start	= BCMA_SOC_FLASH2,
 | |
| @@ -30,7 +30,7 @@ struct bcma_sflash_tbl_e {
 | |
|  	u16 numblocks;
 | |
|  };
 | |
|  
 | |
| -static struct bcma_sflash_tbl_e bcma_sflash_st_tbl[] = {
 | |
| +static const struct bcma_sflash_tbl_e bcma_sflash_st_tbl[] = {
 | |
|  	{ "M25P20", 0x11, 0x10000, 4, },
 | |
|  	{ "M25P40", 0x12, 0x10000, 8, },
 | |
|  
 | |
| @@ -41,7 +41,7 @@ static struct bcma_sflash_tbl_e bcma_sfl
 | |
|  	{ 0 },
 | |
|  };
 | |
|  
 | |
| -static struct bcma_sflash_tbl_e bcma_sflash_sst_tbl[] = {
 | |
| +static const struct bcma_sflash_tbl_e bcma_sflash_sst_tbl[] = {
 | |
|  	{ "SST25WF512", 1, 0x1000, 16, },
 | |
|  	{ "SST25VF512", 0x48, 0x1000, 16, },
 | |
|  	{ "SST25WF010", 2, 0x1000, 32, },
 | |
| @@ -59,7 +59,7 @@ static struct bcma_sflash_tbl_e bcma_sfl
 | |
|  	{ 0 },
 | |
|  };
 | |
|  
 | |
| -static struct bcma_sflash_tbl_e bcma_sflash_at_tbl[] = {
 | |
| +static const struct bcma_sflash_tbl_e bcma_sflash_at_tbl[] = {
 | |
|  	{ "AT45DB011", 0xc, 256, 512, },
 | |
|  	{ "AT45DB021", 0x14, 256, 1024, },
 | |
|  	{ "AT45DB041", 0x1c, 256, 2048, },
 | |
| @@ -89,7 +89,7 @@ int bcma_sflash_init(struct bcma_drv_cc
 | |
|  {
 | |
|  	struct bcma_bus *bus = cc->core->bus;
 | |
|  	struct bcma_sflash *sflash = &cc->sflash;
 | |
| -	struct bcma_sflash_tbl_e *e;
 | |
| +	const struct bcma_sflash_tbl_e *e;
 | |
|  	u32 id, id2;
 | |
|  
 | |
|  	switch (cc->capabilities & BCMA_CC_CAP_FLASHT) {
 | |
| --- a/drivers/bcma/driver_gpio.c
 | |
| +++ b/drivers/bcma/driver_gpio.c
 | |
| @@ -73,6 +73,16 @@ static void bcma_gpio_free(struct gpio_c
 | |
|  	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;
 | |
| @@ -85,6 +95,7 @@ int bcma_gpio_init(struct bcma_drv_cc *c
 | |
|  	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/drivers/bcma/driver_mips.c
 | |
| +++ b/drivers/bcma/driver_mips.c
 | |
| @@ -14,11 +14,33 @@
 | |
|  
 | |
|  #include <linux/bcma/bcma.h>
 | |
|  
 | |
| +#include <linux/mtd/physmap.h>
 | |
| +#include <linux/platform_device.h>
 | |
|  #include <linux/serial.h>
 | |
|  #include <linux/serial_core.h>
 | |
|  #include <linux/serial_reg.h>
 | |
|  #include <linux/time.h>
 | |
|  
 | |
| +static const char *part_probes[] = { "bcm47xxpart", NULL };
 | |
| +
 | |
| +static struct physmap_flash_data bcma_pflash_data = {
 | |
| +	.part_probe_types	= part_probes,
 | |
| +};
 | |
| +
 | |
| +static struct resource bcma_pflash_resource = {
 | |
| +	.name	= "bcma_pflash",
 | |
| +	.flags  = IORESOURCE_MEM,
 | |
| +};
 | |
| +
 | |
| +struct platform_device bcma_pflash_dev = {
 | |
| +	.name		= "physmap-flash",
 | |
| +	.dev		= {
 | |
| +		.platform_data  = &bcma_pflash_data,
 | |
| +	},
 | |
| +	.resource	= &bcma_pflash_resource,
 | |
| +	.num_resources	= 1,
 | |
| +};
 | |
| +
 | |
|  /* The 47162a0 hangs when reading MIPS DMP registers registers */
 | |
|  static inline bool bcma_core_mips_bcm47162a0_quirk(struct bcma_device *dev)
 | |
|  {
 | |
| @@ -74,28 +96,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;
 | |
|  }
 | |
| -EXPORT_SYMBOL(bcma_core_mips_irq);
 | |
| +
 | |
| +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_irq);
 | |
|  
 | |
|  static void bcma_core_mips_set_irq(struct bcma_device *dev, unsigned int irq)
 | |
|  {
 | |
| @@ -114,7 +149,7 @@ 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
 | |
| +	else if (oldirq != 5)
 | |
|  		bcma_write32(mdev, BCMA_MIPS_MIPS74K_INTMASK(oldirq), 0);
 | |
|  
 | |
|  	/* assign the new one */
 | |
| @@ -123,9 +158,9 @@ 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
 | |
| @@ -133,7 +168,7 @@ static void bcma_core_mips_set_irq(struc
 | |
|  			 */
 | |
|  			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 +178,31 @@ static void bcma_core_mips_set_irq(struc
 | |
|  			     1 << irqflag);
 | |
|  	}
 | |
|  
 | |
| -	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)
 | |
|  {
 | |
|  	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");
 | |
| @@ -182,6 +233,7 @@ static void bcma_core_mips_flash_detect(
 | |
|  {
 | |
|  	struct bcma_bus *bus = mcore->core->bus;
 | |
|  	struct bcma_drv_cc *cc = &bus->drv_cc;
 | |
| +	struct bcma_pflash *pflash = &cc->pflash;
 | |
|  
 | |
|  	switch (cc->capabilities & BCMA_CC_CAP_FLASHT) {
 | |
|  	case BCMA_CC_FLASHT_STSER:
 | |
| @@ -191,15 +243,20 @@ static void bcma_core_mips_flash_detect(
 | |
|  		break;
 | |
|  	case BCMA_CC_FLASHT_PARA:
 | |
|  		bcma_debug(bus, "Found parallel flash\n");
 | |
| -		cc->pflash.present = true;
 | |
| -		cc->pflash.window = BCMA_SOC_FLASH2;
 | |
| -		cc->pflash.window_size = BCMA_SOC_FLASH2_SZ;
 | |
| +		pflash->present = true;
 | |
| +		pflash->window = BCMA_SOC_FLASH2;
 | |
| +		pflash->window_size = BCMA_SOC_FLASH2_SZ;
 | |
|  
 | |
|  		if ((bcma_read32(cc->core, BCMA_CC_FLASH_CFG) &
 | |
|  		     BCMA_CC_FLASH_CFG_DS) == 0)
 | |
| -			cc->pflash.buswidth = 1;
 | |
| +			pflash->buswidth = 1;
 | |
|  		else
 | |
| -			cc->pflash.buswidth = 2;
 | |
| +			pflash->buswidth = 2;
 | |
| +
 | |
| +		bcma_pflash_data.width = pflash->buswidth;
 | |
| +		bcma_pflash_resource.start = pflash->window;
 | |
| +		bcma_pflash_resource.end = pflash->window + pflash->window_size;
 | |
| +
 | |
|  		break;
 | |
|  	default:
 | |
|  		bcma_err(bus, "Flash type not supported\n");
 | |
| @@ -227,6 +284,32 @@ void bcma_core_mips_early_init(struct bc
 | |
|  	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");
 | |
| +	}
 | |
| +}
 | |
| +
 | |
|  void bcma_core_mips_init(struct bcma_drv_mips *mcore)
 | |
|  {
 | |
|  	struct bcma_bus *bus;
 | |
| @@ -236,43 +319,55 @@ void bcma_core_mips_init(struct bcma_drv
 | |
|  	if (mcore->setup_done)
 | |
|  		return;
 | |
|  
 | |
| -	bcma_info(bus, "Initializing MIPS core...\n");
 | |
| +	bcma_debug(bus, "Initializing MIPS core...\n");
 | |
|  
 | |
|  	bcma_core_mips_early_init(mcore);
 | |
|  
 | |
| -	mcore->assigned_irqs = 1;
 | |
| +	bcma_fix_i2s_irqflag(bus);
 | |
|  
 | |
| -	/* Assign IRQs to all cores on the bus */
 | |
| -	list_for_each_entry(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;
 | |
| +	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);
 | |
|  	}
 | |
| -	bcma_info(bus, "IRQ reconfiguration done\n");
 | |
| +	bcma_debug(bus, "IRQ reconfiguration done\n");
 | |
|  	bcma_core_mips_dump_irq(bus);
 | |
|  
 | |
|  	mcore->setup_done = true;
 | |
| --- a/drivers/bcma/driver_pci_host.c
 | |
| +++ b/drivers/bcma/driver_pci_host.c
 | |
| @@ -94,19 +94,19 @@ static int bcma_extpci_read_config(struc
 | |
|  	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 {
 | |
| @@ -119,11 +119,9 @@ static int bcma_extpci_read_config(struc
 | |
|  			goto out;
 | |
|  
 | |
|  		if (mips_busprobe32(val, mmio)) {
 | |
| -			val = 0xffffffff;
 | |
| +			val = 0xFFFFFFFF;
 | |
|  			goto unmap;
 | |
|  		}
 | |
| -
 | |
| -		val = readl(mmio);
 | |
|  	}
 | |
|  	val >>= (8 * (off & 3));
 | |
|  
 | |
| @@ -151,7 +149,7 @@ static int bcma_extpci_write_config(stru
 | |
|  				   const void *buf, int len)
 | |
|  {
 | |
|  	int err = -EINVAL;
 | |
| -	u32 addr = 0, val = 0;
 | |
| +	u32 addr, val;
 | |
|  	void __iomem *mmio = 0;
 | |
|  	u16 chipid = pc->core->bus->chipinfo.id;
 | |
|  
 | |
| @@ -159,16 +157,22 @@ static int bcma_extpci_write_config(stru
 | |
|  	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);
 | |
| @@ -180,19 +184,17 @@ static int bcma_extpci_write_config(stru
 | |
|  			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;
 | |
| @@ -200,13 +202,14 @@ static int bcma_extpci_write_config(stru
 | |
|  		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);
 | |
|  
 | |
| @@ -276,7 +279,7 @@ static u8 bcma_find_pci_capability(struc
 | |
|  	/* 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 */
 | |
| @@ -401,6 +404,8 @@ void bcma_core_pci_hostmode_init(struct
 | |
|  		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;
 | |
| @@ -426,7 +431,7 @@ void bcma_core_pci_hostmode_init(struct
 | |
|  	/* Reset RC */
 | |
|  	usleep_range(3000, 5000);
 | |
|  	pcicore_write32(pc, BCMA_CORE_PCI_CTL, BCMA_CORE_PCI_CTL_RST_OE);
 | |
| -	usleep_range(1000, 2000);
 | |
| +	msleep(50);
 | |
|  	pcicore_write32(pc, BCMA_CORE_PCI_CTL, BCMA_CORE_PCI_CTL_RST |
 | |
|  			BCMA_CORE_PCI_CTL_RST_OE);
 | |
|  
 | |
| @@ -488,6 +493,17 @@ void bcma_core_pci_hostmode_init(struct
 | |
|  
 | |
|  	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));
 | |
| @@ -565,6 +581,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI
 | |
|  int bcma_core_pci_plat_dev_init(struct pci_dev *dev)
 | |
|  {
 | |
|  	struct bcma_drv_pci_host *pc_host;
 | |
| +	int readrq;
 | |
|  
 | |
|  	if (dev->bus->ops->read != bcma_core_pci_hostmode_read_config) {
 | |
|  		/* This is not a device on the PCI-core bridge. */
 | |
| @@ -576,9 +593,14 @@ int bcma_core_pci_plat_dev_init(struct p
 | |
|  	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);
 | |
|  
 | |
| +	readrq = pcie_get_readrq(dev);
 | |
| +	if (readrq > 128) {
 | |
| +		pr_info("change PCIe max read request size from %i to 128\n", readrq);
 | |
| +		pcie_set_readrq(dev, 128);
 | |
| +	}
 | |
|  	return 0;
 | |
|  }
 | |
|  EXPORT_SYMBOL(bcma_core_pci_plat_dev_init);
 | |
| @@ -595,6 +617,6 @@ int bcma_core_pci_pcibios_map_irq(const
 | |
|  
 | |
|  	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
 | |
| +++ b/drivers/bcma/host_pci.c
 | |
| @@ -275,6 +275,7 @@ static DEFINE_PCI_DEVICE_TABLE(bcma_pci_
 | |
|  	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4357) },
 | |
|  	{ 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, },
 | |
|  };
 | |
| --- a/drivers/bcma/main.c
 | |
| +++ b/drivers/bcma/main.c
 | |
| @@ -81,8 +81,8 @@ struct bcma_device *bcma_find_core(struc
 | |
|  }
 | |
|  EXPORT_SYMBOL_GPL(bcma_find_core);
 | |
|  
 | |
| -static struct bcma_device *bcma_find_core_unit(struct bcma_bus *bus, u16 coreid,
 | |
| -					       u8 unit)
 | |
| +struct bcma_device *bcma_find_core_unit(struct bcma_bus *bus, u16 coreid,
 | |
| +					u8 unit)
 | |
|  {
 | |
|  	struct bcma_device *core;
 | |
|  
 | |
| @@ -93,6 +93,25 @@ static struct bcma_device *bcma_find_cor
 | |
|  	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)
 | |
|  {
 | |
|  	struct bcma_device *core = container_of(dev, struct bcma_device, dev);
 | |
| @@ -120,6 +139,11 @@ static int bcma_register_cores(struct bc
 | |
|  			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", bus->num, dev_id);
 | |
| @@ -149,6 +173,14 @@ static int bcma_register_cores(struct bc
 | |
|  		dev_id++;
 | |
|  	}
 | |
|  
 | |
| +#ifdef CONFIG_BCMA_DRIVER_MIPS
 | |
| +	if (bus->drv_cc.pflash.present) {
 | |
| +		err = platform_device_register(&bcma_pflash_dev);
 | |
| +		if (err)
 | |
| +			bcma_err(bus, "Error registering parallel flash\n");
 | |
| +	}
 | |
| +#endif
 | |
| +
 | |
|  #ifdef CONFIG_BCMA_SFLASH
 | |
|  	if (bus->drv_cc.sflash.present) {
 | |
|  		err = platform_device_register(&bcma_sflash_dev);
 | |
| @@ -205,7 +237,7 @@ int bcma_bus_register(struct bcma_bus *b
 | |
|  	err = bcma_bus_scan(bus);
 | |
|  	if (err) {
 | |
|  		bcma_err(bus, "Failed to scan: %d\n", err);
 | |
| -		return -1;
 | |
| +		return err;
 | |
|  	}
 | |
|  
 | |
|  	/* Early init CC core */
 | |
| --- a/drivers/bcma/scan.c
 | |
| +++ b/drivers/bcma/scan.c
 | |
| @@ -32,6 +32,18 @@ static const struct bcma_device_id_name
 | |
|  	{ BCMA_CORE_4706_CHIPCOMMON, "BCM4706 ChipCommon" },
 | |
|  	{ BCMA_CORE_4706_SOC_RAM, "BCM4706 SOC RAM" },
 | |
|  	{ BCMA_CORE_4706_MAC_GBIT, "BCM4706 GBit MAC" },
 | |
| +	{ BCMA_CORE_PCIEG2, "PCIe Gen 2" },
 | |
| +	{ BCMA_CORE_DMA, "DMA" },
 | |
| +	{ BCMA_CORE_SDIO3, "SDIO3" },
 | |
| +	{ BCMA_CORE_USB20, "USB 2.0" },
 | |
| +	{ BCMA_CORE_USB30, "USB 3.0" },
 | |
| +	{ BCMA_CORE_A9JTAG, "ARM Cortex A9 JTAG" },
 | |
| +	{ BCMA_CORE_DDR23, "Denali DDR2/DDR3 memory controller" },
 | |
| +	{ BCMA_CORE_ROM, "ROM" },
 | |
| +	{ BCMA_CORE_NAND, "NAND flash controller" },
 | |
| +	{ BCMA_CORE_QSPI, "SPI flash controller" },
 | |
| +	{ BCMA_CORE_CHIPCOMMON_B, "Chipcommon B" },
 | |
| +	{ BCMA_CORE_ARMCA9, "ARM Cortex A9 core (ihost)" },
 | |
|  	{ BCMA_CORE_AMEMC, "AMEMC (DDR)" },
 | |
|  	{ BCMA_CORE_ALTA, "ALTA (I2S)" },
 | |
|  	{ BCMA_CORE_INVALID, "Invalid" },
 | |
| @@ -84,6 +96,8 @@ static const struct bcma_device_id_name
 | |
|  	{ 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" },
 | |
|  };
 | |
|  
 | |
| @@ -137,19 +151,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))
 | |
| @@ -159,14 +173,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);
 | |
| @@ -175,7 +189,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) {
 | |
| @@ -189,7 +203,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))
 | |
| @@ -199,7 +213,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 u32 bcma_erom_get_addr_desc(struct bcma_bus *bus, u32 __iomem **eromptr,
 | |
|  				  u32 type, u8 port)
 | |
|  {
 | |
|  	u32 addrl, addrh, sizel, sizeh = 0;
 | |
| @@ -211,7 +225,7 @@ static s32 bcma_erom_get_addr_desc(struc
 | |
|  	    ((ent & SCAN_ADDR_TYPE) != type) ||
 | |
|  	    (((ent & SCAN_ADDR_PORT) >> SCAN_ADDR_PORT_SHIFT) != port)) {
 | |
|  		bcma_erom_push_ent(eromptr);
 | |
| -		return -EINVAL;
 | |
| +		return (u32)-EINVAL;
 | |
|  	}
 | |
|  
 | |
|  	addrl = ent & SCAN_ADDR_ADDR;
 | |
| @@ -255,11 +269,13 @@ static struct bcma_device *bcma_find_cor
 | |
|  	return NULL;
 | |
|  }
 | |
|  
 | |
| +#define IS_ERR_VALUE_U32(x) ((x) >= (u32)-MAX_ERRNO)
 | |
| +
 | |
|  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)
 | |
|  {
 | |
| -	s32 tmp;
 | |
| +	u32 tmp;
 | |
|  	u8 i, j;
 | |
|  	s32 cia, cib;
 | |
|  	u8 ports[2], wrappers[2];
 | |
| @@ -337,11 +353,11 @@ static int bcma_get_next_core(struct bcm
 | |
|  	 * the main register space for the core
 | |
|  	 */
 | |
|  	tmp = bcma_erom_get_addr_desc(bus, eromptr, SCAN_ADDR_TYPE_SLAVE, 0);
 | |
| -	if (tmp <= 0) {
 | |
| +	if (tmp == 0 || IS_ERR_VALUE_U32(tmp)) {
 | |
|  		/* Try again to see if it is a bridge */
 | |
|  		tmp = bcma_erom_get_addr_desc(bus, eromptr,
 | |
|  					      SCAN_ADDR_TYPE_BRIDGE, 0);
 | |
| -		if (tmp <= 0) {
 | |
| +		if (tmp == 0 || IS_ERR_VALUE_U32(tmp)) {
 | |
|  			return -EILSEQ;
 | |
|  		} else {
 | |
|  			bcma_info(bus, "Bridge found\n");
 | |
| @@ -355,7 +371,7 @@ static int bcma_get_next_core(struct bcm
 | |
|  		for (j = 0; ; j++) {
 | |
|  			tmp = bcma_erom_get_addr_desc(bus, eromptr,
 | |
|  				SCAN_ADDR_TYPE_SLAVE, i);
 | |
| -			if (tmp < 0) {
 | |
| +			if (IS_ERR_VALUE_U32(tmp)) {
 | |
|  				/* no more entries for port _i_ */
 | |
|  				/* pr_debug("erom: slave port %d "
 | |
|  				 * "has %d descriptors\n", i, j); */
 | |
| @@ -372,7 +388,7 @@ static int bcma_get_next_core(struct bcm
 | |
|  		for (j = 0; ; j++) {
 | |
|  			tmp = bcma_erom_get_addr_desc(bus, eromptr,
 | |
|  				SCAN_ADDR_TYPE_MWRAP, i);
 | |
| -			if (tmp < 0) {
 | |
| +			if (IS_ERR_VALUE_U32(tmp)) {
 | |
|  				/* no more entries for port _i_ */
 | |
|  				/* pr_debug("erom: master wrapper %d "
 | |
|  				 * "has %d descriptors\n", i, j); */
 | |
| @@ -390,7 +406,7 @@ static int bcma_get_next_core(struct bcm
 | |
|  		for (j = 0; ; j++) {
 | |
|  			tmp = bcma_erom_get_addr_desc(bus, eromptr,
 | |
|  				SCAN_ADDR_TYPE_SWRAP, i + hack);
 | |
| -			if (tmp < 0) {
 | |
| +			if (IS_ERR_VALUE_U32(tmp)) {
 | |
|  				/* no more entries for port _i_ */
 | |
|  				/* pr_debug("erom: master wrapper %d "
 | |
|  				 * has %d descriptors\n", i, j); */
 | |
| --- a/drivers/bcma/sprom.c
 | |
| +++ b/drivers/bcma/sprom.c
 | |
| @@ -72,12 +72,12 @@ fail:
 | |
|   * R/W ops.
 | |
|   **************************************************/
 | |
|  
 | |
| -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));
 | |
|  }
 | |
|  
 | |
|  /**************************************************
 | |
| @@ -124,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;
 | |
| @@ -154,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;
 | |
|  }
 | |
|  
 | |
| @@ -208,15 +212,13 @@ static void bcma_sprom_extract_r8(struct
 | |
|  	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;
 | |
| -
 | |
|  	for (i = 0; i < 3; i++) {
 | |
|  		v = sprom[SPOFF(SSB_SPROM8_IL0MAC) + i];
 | |
|  		*(((__be16 *)bus->sprom.il0mac) + i) = cpu_to_be16(v);
 | |
|  	}
 | |
|  
 | |
|  	SPEX(board_rev, SSB_SPROM8_BOARDREV, ~0, 0);
 | |
| +	SPEX(board_type, SSB_SPROM1_SPID, ~0, 0);
 | |
|  
 | |
|  	SPEX(txpid2g[0], SSB_SPROM4_TXPID2G01, SSB_SPROM4_TXPID2G0,
 | |
|  	     SSB_SPROM4_TXPID2G0_SHIFT);
 | |
| @@ -501,7 +503,7 @@ static bool bcma_sprom_onchip_available(
 | |
|  	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 */
 | |
| @@ -549,7 +551,9 @@ int bcma_sprom_get(struct bcma_bus *bus)
 | |
|  {
 | |
|  	u16 offset = BCMA_CC_SPROM;
 | |
|  	u16 *sprom;
 | |
| -	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;
 | |
| @@ -578,32 +582,37 @@ int bcma_sprom_get(struct bcma_bus *bus)
 | |
|  		}
 | |
|  	}
 | |
|  
 | |
| -	sprom = kcalloc(SSB_SPROMSIZE_WORDS_R4, sizeof(u16),
 | |
| -			GFP_KERNEL);
 | |
| -	if (!sprom)
 | |
| -		return -ENOMEM;
 | |
| -
 | |
|  	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, false);
 | |
|  
 | |
|  	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;
 | |
| +
 | |
| +		kfree(sprom);
 | |
| +	}
 | |
|  
 | |
|  	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);
 | |
|  
 | |
| -	err = bcma_sprom_valid(sprom);
 | |
|  	if (err) {
 | |
| -		bcma_warn(bus, "invalid sprom read from the PCIe card, try to use fallback sprom\n");
 | |
| +		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);
 | |
| -		goto out;
 | |
| +	} else {
 | |
| +		bcma_sprom_extract_r8(bus, sprom);
 | |
| +		kfree(sprom);
 | |
|  	}
 | |
|  
 | |
| -	bcma_sprom_extract_r8(bus, sprom);
 | |
| -
 | |
| -out:
 | |
| -	kfree(sprom);
 | |
|  	return err;
 | |
|  }
 | |
| --- a/include/linux/bcma/bcma.h
 | |
| +++ b/include/linux/bcma/bcma.h
 | |
| @@ -72,7 +72,19 @@ struct bcma_host_ops {
 | |
|  /* Core-ID values. */
 | |
|  #define BCMA_CORE_OOB_ROUTER		0x367	/* Out of band */
 | |
|  #define BCMA_CORE_4706_CHIPCOMMON	0x500
 | |
| +#define BCMA_CORE_PCIEG2		0x501
 | |
| +#define BCMA_CORE_DMA			0x502
 | |
| +#define BCMA_CORE_SDIO3			0x503
 | |
| +#define BCMA_CORE_USB20			0x504
 | |
| +#define BCMA_CORE_USB30			0x505
 | |
| +#define BCMA_CORE_A9JTAG		0x506
 | |
| +#define BCMA_CORE_DDR23			0x507
 | |
| +#define BCMA_CORE_ROM			0x508
 | |
| +#define BCMA_CORE_NAND			0x509
 | |
| +#define BCMA_CORE_QSPI			0x50A
 | |
| +#define BCMA_CORE_CHIPCOMMON_B		0x50B
 | |
|  #define BCMA_CORE_4706_SOC_RAM		0x50E
 | |
| +#define BCMA_CORE_ARMCA9		0x510
 | |
|  #define BCMA_CORE_4706_MAC_GBIT		0x52D
 | |
|  #define BCMA_CORE_AMEMC			0x52E	/* DDR1/2 memory controller core */
 | |
|  #define BCMA_CORE_ALTA			0x534	/* I2S core */
 | |
| @@ -134,12 +146,20 @@ 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_BCM43131  43131
 | |
| +#define BCMA_CHIP_ID_BCM43217  43217
 | |
| +#define BCMA_CHIP_ID_BCM43222  43222
 | |
|  #define BCMA_CHIP_ID_BCM43224	43224
 | |
|  #define  BCMA_PKG_ID_BCM43224_FAB_CSM	0x8
 | |
|  #define  BCMA_PKG_ID_BCM43224_FAB_SMIC	0xa
 | |
| @@ -172,6 +192,65 @@ struct bcma_host_ops {
 | |
|  #define  BCMA_PKG_ID_BCM5357	11
 | |
|  #define BCMA_CHIP_ID_BCM53572	53572
 | |
|  #define  BCMA_PKG_ID_BCM47188	9
 | |
| +#define BCMA_CHIP_ID_BCM4707	53010
 | |
| +#define  BCMA_PKG_ID_BCM4707	1
 | |
| +#define  BCMA_PKG_ID_BCM4708	2
 | |
| +#define  BCMA_PKG_ID_BCM4709	0
 | |
| +#define BCMA_CHIP_ID_BCM53018	53018
 | |
| +
 | |
| +/* 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;
 | |
| --- a/include/linux/bcma/bcma_driver_chipcommon.h
 | |
| +++ b/include/linux/bcma/bcma_driver_chipcommon.h
 | |
| @@ -27,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	/* NAND flash */
 | |
| +#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
 | |
| @@ -104,6 +104,7 @@
 | |
|  #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
 | |
| @@ -315,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 */
 | |
| @@ -326,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 */
 | |
| @@ -351,6 +357,11 @@
 | |
|  #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 */
 | |
|  /* NAND flash MLC controller registers (corerev >= 38) */
 | |
|  #define BCMA_CC_NAND_REVISION		0x0C00
 | |
| @@ -431,6 +442,23 @@
 | |
|  #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
 | |
|  /* HT clock for systems with PMU-enabled chipcommon */
 | |
| @@ -503,6 +531,37 @@
 | |
|  #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)
 | |
|   */
 | |
| @@ -528,6 +587,7 @@ struct bcma_sflash {
 | |
|  	u32 size;
 | |
|  
 | |
|  	struct mtd_info *mtd;
 | |
| +	void *priv;
 | |
|  };
 | |
|  #endif
 | |
|  
 | |
| @@ -606,6 +666,8 @@ void bcma_chipco_bcm4331_ext_pa_lines_ct
 | |
|  
 | |
|  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);
 | |
|  
 | |
|  u32 bcma_chipco_irq_status(struct bcma_drv_cc *cc, u32 mask);
 | |
| @@ -634,4 +696,6 @@ extern void bcma_chipco_regctl_maskset(s
 | |
|  				       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_ */
 | |
| --- 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;
 | |
| @@ -36,19 +37,23 @@ struct bcma_drv_mips {
 | |
|  	struct bcma_device *core;
 | |
|  	u8 setup_done:1;
 | |
|  	u8 early_setup_done:1;
 | |
| -	unsigned int assigned_irqs;
 | |
|  };
 | |
|  
 | |
|  #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
 | |
| @@ -179,10 +179,33 @@ struct pci_dev;
 | |
|  #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
 | |
| +
 | |
| +#define BCMA_CORE_PCI_
 | |
| +
 | |
| +/* MDIO devices (SERDES modules) */
 | |
| +#define BCMA_CORE_PCI_MDIO_IEEE0		0x000
 | |
| +#define BCMA_CORE_PCI_MDIO_IEEE1		0x001
 | |
| +#define BCMA_CORE_PCI_MDIO_BLK0			0x800
 | |
| +#define BCMA_CORE_PCI_MDIO_BLK1			0x801
 | |
| +#define  BCMA_CORE_PCI_MDIO_BLK1_MGMT0		0x16
 | |
| +#define  BCMA_CORE_PCI_MDIO_BLK1_MGMT1		0x17
 | |
| +#define  BCMA_CORE_PCI_MDIO_BLK1_MGMT2		0x18
 | |
| +#define  BCMA_CORE_PCI_MDIO_BLK1_MGMT3		0x19
 | |
| +#define  BCMA_CORE_PCI_MDIO_BLK1_MGMT4		0x1A
 | |
| +#define BCMA_CORE_PCI_MDIO_BLK2			0x802
 | |
| +#define BCMA_CORE_PCI_MDIO_BLK3			0x803
 | |
| +#define BCMA_CORE_PCI_MDIO_BLK4			0x804
 | |
| +#define BCMA_CORE_PCI_MDIO_TXPLL		0x808	/* TXPLL register block idx */
 | |
| +#define BCMA_CORE_PCI_MDIO_TXCTRL0		0x820
 | |
| +#define BCMA_CORE_PCI_MDIO_SERDESID		0x831
 | |
| +#define BCMA_CORE_PCI_MDIO_RXCTRL0		0x840
 | |
| +
 | |
|  /* PCIE Root Capability Register bits (Host mode only) */
 | |
|  #define BCMA_CORE_PCI_RC_CRS_VISIBILITY		0x0001
 | |
|  
 | |
|  struct bcma_drv_pci;
 | |
| +struct bcma_bus;
 | |
|  
 | |
|  #ifdef CONFIG_BCMA_DRIVER_PCI_HOSTMODE
 | |
|  struct bcma_drv_pci_host {
 | |
| @@ -217,7 +240,9 @@ struct bcma_drv_pci {
 | |
|  extern void bcma_core_pci_init(struct bcma_drv_pci *pc);
 | |
|  extern int bcma_core_pci_irq_ctl(struct bcma_drv_pci *pc,
 | |
|  				 struct bcma_device *core, bool enable);
 | |
| -extern void bcma_core_pci_extend_L1timer(struct bcma_drv_pci *pc, bool extend);
 | |
| +extern void bcma_core_pci_up(struct bcma_bus *bus);
 | |
| +extern void bcma_core_pci_down(struct bcma_bus *bus);
 | |
| +extern void bcma_core_pci_power_save(struct bcma_bus *bus, bool up);
 | |
|  
 | |
|  extern int bcma_core_pci_pcibios_map_irq(const struct pci_dev *dev);
 | |
|  extern int bcma_core_pci_plat_dev_init(struct pci_dev *dev);
 | |
| --- a/include/linux/bcma/bcma_regs.h
 | |
| +++ b/include/linux/bcma/bcma_regs.h
 | |
| @@ -37,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
 | |
| --- a/drivers/bcma/driver_pci.c
 | |
| +++ b/drivers/bcma/driver_pci.c
 | |
| @@ -31,7 +31,7 @@ static void bcma_pcie_write(struct bcma_
 | |
|  	pcicore_write32(pc, BCMA_CORE_PCI_PCIEIND_DATA, data);
 | |
|  }
 | |
|  
 | |
| -static void bcma_pcie_mdio_set_phy(struct bcma_drv_pci *pc, u8 phy)
 | |
| +static void bcma_pcie_mdio_set_phy(struct bcma_drv_pci *pc, u16 phy)
 | |
|  {
 | |
|  	u32 v;
 | |
|  	int i;
 | |
| @@ -55,7 +55,7 @@ static void bcma_pcie_mdio_set_phy(struc
 | |
|  	}
 | |
|  }
 | |
|  
 | |
| -static u16 bcma_pcie_mdio_read(struct bcma_drv_pci *pc, u8 device, u8 address)
 | |
| +static u16 bcma_pcie_mdio_read(struct bcma_drv_pci *pc, u16 device, u8 address)
 | |
|  {
 | |
|  	int max_retries = 10;
 | |
|  	u16 ret = 0;
 | |
| @@ -98,7 +98,7 @@ static u16 bcma_pcie_mdio_read(struct bc
 | |
|  	return ret;
 | |
|  }
 | |
|  
 | |
| -static void bcma_pcie_mdio_write(struct bcma_drv_pci *pc, u8 device,
 | |
| +static void bcma_pcie_mdio_write(struct bcma_drv_pci *pc, u16 device,
 | |
|  				u8 address, u16 data)
 | |
|  {
 | |
|  	int max_retries = 10;
 | |
| @@ -137,6 +137,13 @@ static void bcma_pcie_mdio_write(struct
 | |
|  	pcicore_write32(pc, BCMA_CORE_PCI_MDIO_CONTROL, 0);
 | |
|  }
 | |
|  
 | |
| +static u16 bcma_pcie_mdio_writeread(struct bcma_drv_pci *pc, u16 device,
 | |
| +				    u8 address, u16 data)
 | |
| +{
 | |
| +	bcma_pcie_mdio_write(pc, device, address, data);
 | |
| +	return bcma_pcie_mdio_read(pc, device, address);
 | |
| +}
 | |
| +
 | |
|  /**************************************************
 | |
|   * Workarounds.
 | |
|   **************************************************/
 | |
| @@ -229,6 +236,32 @@ void bcma_core_pci_init(struct bcma_drv_
 | |
|  		bcma_core_pci_clientmode_init(pc);
 | |
|  }
 | |
|  
 | |
| +void bcma_core_pci_power_save(struct bcma_bus *bus, bool up)
 | |
| +{
 | |
| +	struct bcma_drv_pci *pc;
 | |
| +	u16 data;
 | |
| +
 | |
| +	if (bus->hosttype != BCMA_HOSTTYPE_PCI)
 | |
| +		return;
 | |
| +
 | |
| +	pc = &bus->drv_pci[0];
 | |
| +
 | |
| +	if (pc->core->id.rev >= 15 && pc->core->id.rev <= 20) {
 | |
| +		data = up ? 0x74 : 0x7C;
 | |
| +		bcma_pcie_mdio_writeread(pc, BCMA_CORE_PCI_MDIO_BLK1,
 | |
| +					 BCMA_CORE_PCI_MDIO_BLK1_MGMT1, 0x7F64);
 | |
| +		bcma_pcie_mdio_writeread(pc, BCMA_CORE_PCI_MDIO_BLK1,
 | |
| +					 BCMA_CORE_PCI_MDIO_BLK1_MGMT3, data);
 | |
| +	} else if (pc->core->id.rev >= 21 && pc->core->id.rev <= 22) {
 | |
| +		data = up ? 0x75 : 0x7D;
 | |
| +		bcma_pcie_mdio_writeread(pc, BCMA_CORE_PCI_MDIO_BLK1,
 | |
| +					 BCMA_CORE_PCI_MDIO_BLK1_MGMT1, 0x7E65);
 | |
| +		bcma_pcie_mdio_writeread(pc, BCMA_CORE_PCI_MDIO_BLK1,
 | |
| +					 BCMA_CORE_PCI_MDIO_BLK1_MGMT3, data);
 | |
| +	}
 | |
| +}
 | |
| +EXPORT_SYMBOL_GPL(bcma_core_pci_power_save);
 | |
| +
 | |
|  int bcma_core_pci_irq_ctl(struct bcma_drv_pci *pc, struct bcma_device *core,
 | |
|  			  bool enable)
 | |
|  {
 | |
| @@ -262,7 +295,7 @@ out:
 | |
|  }
 | |
|  EXPORT_SYMBOL_GPL(bcma_core_pci_irq_ctl);
 | |
|  
 | |
| -void bcma_core_pci_extend_L1timer(struct bcma_drv_pci *pc, bool extend)
 | |
| +static void bcma_core_pci_extend_L1timer(struct bcma_drv_pci *pc, bool extend)
 | |
|  {
 | |
|  	u32 w;
 | |
|  
 | |
| @@ -274,4 +307,29 @@ void bcma_core_pci_extend_L1timer(struct
 | |
|  	bcma_pcie_write(pc, BCMA_CORE_PCI_DLLP_PMTHRESHREG, w);
 | |
|  	bcma_pcie_read(pc, BCMA_CORE_PCI_DLLP_PMTHRESHREG);
 | |
|  }
 | |
| -EXPORT_SYMBOL_GPL(bcma_core_pci_extend_L1timer);
 | |
| +
 | |
| +void bcma_core_pci_up(struct bcma_bus *bus)
 | |
| +{
 | |
| +	struct bcma_drv_pci *pc;
 | |
| +
 | |
| +	if (bus->hosttype != BCMA_HOSTTYPE_PCI)
 | |
| +		return;
 | |
| +
 | |
| +	pc = &bus->drv_pci[0];
 | |
| +
 | |
| +	bcma_core_pci_extend_L1timer(pc, true);
 | |
| +}
 | |
| +EXPORT_SYMBOL_GPL(bcma_core_pci_up);
 | |
| +
 | |
| +void bcma_core_pci_down(struct bcma_bus *bus)
 | |
| +{
 | |
| +	struct bcma_drv_pci *pc;
 | |
| +
 | |
| +	if (bus->hosttype != BCMA_HOSTTYPE_PCI)
 | |
| +		return;
 | |
| +
 | |
| +	pc = &bus->drv_pci[0];
 | |
| +
 | |
| +	bcma_core_pci_extend_L1timer(pc, false);
 | |
| +}
 | |
| +EXPORT_SYMBOL_GPL(bcma_core_pci_down);
 | |
| --- a/drivers/net/wireless/brcm80211/brcmsmac/aiutils.c
 | |
| +++ b/drivers/net/wireless/brcm80211/brcmsmac/aiutils.c
 | |
| @@ -685,27 +685,6 @@ bool ai_clkctl_cc(struct si_pub *sih, en
 | |
|  	return mode == BCMA_CLKMODE_FAST;
 | |
|  }
 | |
|  
 | |
| -void ai_pci_up(struct si_pub *sih)
 | |
| -{
 | |
| -	struct si_info *sii;
 | |
| -
 | |
| -	sii = container_of(sih, struct si_info, pub);
 | |
| -
 | |
| -	if (sii->icbus->hosttype == BCMA_HOSTTYPE_PCI)
 | |
| -		bcma_core_pci_extend_L1timer(&sii->icbus->drv_pci[0], true);
 | |
| -}
 | |
| -
 | |
| -/* Unconfigure and/or apply various WARs when going down */
 | |
| -void ai_pci_down(struct si_pub *sih)
 | |
| -{
 | |
| -	struct si_info *sii;
 | |
| -
 | |
| -	sii = container_of(sih, struct si_info, pub);
 | |
| -
 | |
| -	if (sii->icbus->hosttype == BCMA_HOSTTYPE_PCI)
 | |
| -		bcma_core_pci_extend_L1timer(&sii->icbus->drv_pci[0], false);
 | |
| -}
 | |
| -
 | |
|  /* Enable BT-COEX & Ex-PA for 4313 */
 | |
|  void ai_epa_4313war(struct si_pub *sih)
 | |
|  {
 | |
| --- a/drivers/net/wireless/brcm80211/brcmsmac/aiutils.h
 | |
| +++ b/drivers/net/wireless/brcm80211/brcmsmac/aiutils.h
 | |
| @@ -183,9 +183,6 @@ extern u16 ai_clkctl_fast_pwrup_delay(st
 | |
|  extern bool ai_clkctl_cc(struct si_pub *sih, enum bcma_clkmode mode);
 | |
|  extern bool ai_deviceremoved(struct si_pub *sih);
 | |
|  
 | |
| -extern void ai_pci_down(struct si_pub *sih);
 | |
| -extern void ai_pci_up(struct si_pub *sih);
 | |
| -
 | |
|  /* Enable Ex-PA for 4313 */
 | |
|  extern void ai_epa_4313war(struct si_pub *sih);
 | |
|  
 | |
| --- a/drivers/net/wireless/brcm80211/brcmsmac/main.c
 | |
| +++ b/drivers/net/wireless/brcm80211/brcmsmac/main.c
 | |
| @@ -4648,7 +4648,7 @@ static int brcms_b_attach(struct brcms_c
 | |
|  	brcms_c_coredisable(wlc_hw);
 | |
|  
 | |
|  	/* Match driver "down" state */
 | |
| -	ai_pci_down(wlc_hw->sih);
 | |
| +	bcma_core_pci_down(wlc_hw->d11core->bus);
 | |
|  
 | |
|  	/* turn off pll and xtal to match driver "down" state */
 | |
|  	brcms_b_xtal(wlc_hw, OFF);
 | |
| @@ -4991,12 +4991,12 @@ static int brcms_b_up_prep(struct brcms_
 | |
|  	 */
 | |
|  	if (brcms_b_radio_read_hwdisabled(wlc_hw)) {
 | |
|  		/* put SB PCI in down state again */
 | |
| -		ai_pci_down(wlc_hw->sih);
 | |
| +		bcma_core_pci_down(wlc_hw->d11core->bus);
 | |
|  		brcms_b_xtal(wlc_hw, OFF);
 | |
|  		return -ENOMEDIUM;
 | |
|  	}
 | |
|  
 | |
| -	ai_pci_up(wlc_hw->sih);
 | |
| +	bcma_core_pci_up(wlc_hw->d11core->bus);
 | |
|  
 | |
|  	/* reset the d11 core */
 | |
|  	brcms_b_corereset(wlc_hw, BRCMS_USE_COREFLAGS);
 | |
| @@ -5193,7 +5193,7 @@ static int brcms_b_down_finish(struct br
 | |
|  
 | |
|  		/* turn off primary xtal and pll */
 | |
|  		if (!wlc_hw->noreset) {
 | |
| -			ai_pci_down(wlc_hw->sih);
 | |
| +			bcma_core_pci_down(wlc_hw->d11core->bus);
 | |
|  			brcms_b_xtal(wlc_hw, OFF);
 | |
|  		}
 | |
|  	}
 |