diff options
| author | nbd <nbd@3c298f89-4303-0410-b956-a3cf2f4a3e73> | 2007-10-14 02:47:36 +0000 | 
|---|---|---|
| committer | nbd <nbd@3c298f89-4303-0410-b956-a3cf2f4a3e73> | 2007-10-14 02:47:36 +0000 | 
| commit | 532249b5072aacee71b437b5be6de44840dc6e00 (patch) | |
| tree | 2458e4ed779fe626b1c5335f2f5f411e277300a6 /target/linux/generic-2.6/files/drivers/ssb | |
| parent | d124ab28a821a801862dba6d4e87a3facc140df5 (diff) | |
sync ssb with upstream
git-svn-id: svn://svn.openwrt.org/openwrt/trunk@9302 3c298f89-4303-0410-b956-a3cf2f4a3e73
Diffstat (limited to 'target/linux/generic-2.6/files/drivers/ssb')
12 files changed, 691 insertions, 297 deletions
| diff --git a/target/linux/generic-2.6/files/drivers/ssb/Kconfig b/target/linux/generic-2.6/files/drivers/ssb/Kconfig index 03c494586..b4a5e5e9d 100644 --- a/target/linux/generic-2.6/files/drivers/ssb/Kconfig +++ b/target/linux/generic-2.6/files/drivers/ssb/Kconfig @@ -1,18 +1,33 @@  menu "Sonics Silicon Backplane" +config SSB_POSSIBLE +	bool +	depends on HAS_IOMEM +	default y +  config SSB  	tristate "Sonics Silicon Backplane support" -	depends on EXPERIMENTAL +	depends on SSB_POSSIBLE  	help -	  Support for the Sonics Silicon Backplane bus +	  Support for the Sonics Silicon Backplane bus. +	  You only need to enable this option, if you are +	  configuring a kernel for an embedded system with +	  this bus. +	  It will be auto-selected if needed in other +	  environments. + +	  The module will be called ssb. -	  The module will be called ssb +	  If unsure, say N. -	  If unsure, say M +config SSB_PCIHOST_POSSIBLE +	bool +	depends on SSB && PCI +	default y  config SSB_PCIHOST  	bool "Support for SSB on PCI-bus host" -	depends on SSB && PCI +	depends on SSB_PCIHOST_POSSIBLE  	default y  	help  	  Support for a Sonics Silicon Backplane on top @@ -20,9 +35,14 @@ config SSB_PCIHOST  	  If unsure, say Y +config SSB_PCMCIAHOST_POSSIBLE +	bool +	depends on SSB && PCMCIA && EXPERIMENTAL +	default y +  config SSB_PCMCIAHOST -	bool "Support for SSB on PCMCIA-bus host" -	depends on SSB && PCMCIA +	bool "Support for SSB on PCMCIA-bus host (EXPERIMENTAL)" +	depends on SSB_PCMCIAHOST_POSSIBLE  	help  	  Support for a Sonics Silicon Backplane on top  	  of a PCMCIA device. @@ -31,7 +51,7 @@ config SSB_PCMCIAHOST  config SSB_SILENT  	bool "No SSB kernel messages" -	depends on SSB +	depends on SSB && EMBEDDED  	help  	  This option turns off all Sonics Silicon Backplane printks.  	  Note that you won't be able to identify problems, once @@ -55,10 +75,14 @@ config SSB_SERIAL  	depends on SSB  	# ChipCommon and ExtIf serial support routines. +config SSB_DRIVER_PCICORE_POSSIBLE +	bool +	depends on SSB_PCIHOST +	default y +  config SSB_DRIVER_PCICORE  	bool "SSB PCI core driver" -	depends on SSB && SSB_PCIHOST -	default y +	depends on SSB_DRIVER_PCICORE_POSSIBLE  	help  	  Driver for the Sonics Silicon Backplane attached  	  Broadcom PCI core. @@ -66,14 +90,14 @@ config SSB_DRIVER_PCICORE  	  If unsure, say Y  config SSB_PCICORE_HOSTMODE -	bool "Hostmode support for SSB PCI core" -	depends on SSB_DRIVER_PCICORE && SSB_DRIVER_MIPS +	bool "Hostmode support for SSB PCI core (EXPERIMENTAL)" +	depends on SSB_DRIVER_PCICORE && SSB_DRIVER_MIPS && EXPERIMENTAL  	help  	  PCIcore hostmode operation (external PCI bus).  config SSB_DRIVER_MIPS -	bool "SSB Broadcom MIPS core driver" -	depends on SSB && MIPS +	bool "SSB Broadcom MIPS core driver (EXPERIMENTAL)" +	depends on SSB && MIPS && EXPERIMENTAL  	select SSB_SERIAL  	help  	  Driver for the Sonics Silicon Backplane attached @@ -82,8 +106,8 @@ config SSB_DRIVER_MIPS  	  If unsure, say N  config SSB_DRIVER_EXTIF -	bool "SSB Broadcom EXTIF core driver" -	depends on SSB_DRIVER_MIPS +	bool "SSB Broadcom EXTIF core driver (EXPERIMENTAL)" +	depends on SSB_DRIVER_MIPS && EXPERIMENTAL  	help  	  Driver for the Sonics Silicon Backplane attached  	  Broadcom EXTIF core. diff --git a/target/linux/generic-2.6/files/drivers/ssb/Makefile b/target/linux/generic-2.6/files/drivers/ssb/Makefile index 9a2b379fb..7be397595 100644 --- a/target/linux/generic-2.6/files/drivers/ssb/Makefile +++ b/target/linux/generic-2.6/files/drivers/ssb/Makefile @@ -1,11 +1,18 @@ -ssb-builtin-drivers-y					+= driver_chipcommon.o -ssb-builtin-drivers-$(CONFIG_SSB_DRIVER_MIPS)		+= driver_mipscore.o -ssb-builtin-drivers-$(CONFIG_SSB_DRIVER_PCICORE)	+= driver_pcicore.o +# core +ssb-y					+= main.o scan.o -ssb-hostsupport-$(CONFIG_SSB_PCIHOST)			+= pci.o pcihost_wrapper.o -ssb-hostsupport-$(CONFIG_SSB_PCMCIAHOST)		+= pcmcia.o +# host support +ssb-$(CONFIG_SSB_PCIHOST)		+= pci.o pcihost_wrapper.o +ssb-$(CONFIG_SSB_PCMCIAHOST)		+= pcmcia.o -obj-$(CONFIG_SSB) += ssb.o +# built-in drivers +ssb-y					+= driver_chipcommon.o +ssb-$(CONFIG_SSB_DRIVER_MIPS)		+= driver_mipscore.o +ssb-$(CONFIG_SSB_DRIVER_EXTIF)		+= driver_extif.o +ssb-$(CONFIG_SSB_DRIVER_PCICORE)	+= driver_pcicore.o -ssb-objs	:= main.o scan.o \ -		   $(ssb-hostsupport-y) $(ssb-builtin-drivers-y) +# b43 pci-ssb-bridge driver +# Not strictly a part of SSB, but kept here for convenience +ssb-$(CONFIG_SSB_PCIHOST)		+= b43_pci_bridge.o + +obj-$(CONFIG_SSB)			+= ssb.o diff --git a/target/linux/generic-2.6/files/drivers/ssb/b43_pci_bridge.c b/target/linux/generic-2.6/files/drivers/ssb/b43_pci_bridge.c new file mode 100644 index 000000000..f145d8a4c --- /dev/null +++ b/target/linux/generic-2.6/files/drivers/ssb/b43_pci_bridge.c @@ -0,0 +1,48 @@ +/* + * Broadcom 43xx PCI-SSB bridge module + * + * This technically is a seperate PCI driver module, but + * because of its small size we include it in the SSB core + * instead of creating a standalone module. + * + * Copyright 2007  Michael Buesch <mb@bu3sch.de> + * + * Licensed under the GNU/GPL. See COPYING for details. + */ + +#include <linux/pci.h> +#include <linux/ssb/ssb.h> + +#include "ssb_private.h" + + +static const struct pci_device_id b43_pci_bridge_tbl[] = { +	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4301) }, +	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4307) }, +	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4311) }, +	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4312) }, +	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4318) }, +	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4319) }, +	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4320) }, +	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4321) }, +	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4324) }, +	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4325) }, +	{ 0, }, +}; +MODULE_DEVICE_TABLE(pci, b43_pci_bridge_tbl); + +static struct pci_driver b43_pci_bridge_driver = { +	.name = "b43-pci-bridge", +	.id_table = b43_pci_bridge_tbl, +}; + + +int __init b43_pci_ssb_bridge_init(void) +{ +	return ssb_pcihost_register(&b43_pci_bridge_driver); +} + +void __exit b43_pci_ssb_bridge_exit(void) +{ +	ssb_pcihost_unregister(&b43_pci_bridge_driver); +} diff --git a/target/linux/generic-2.6/files/drivers/ssb/driver_chipcommon.c b/target/linux/generic-2.6/files/drivers/ssb/driver_chipcommon.c index a283de9e3..6fbf1c53b 100644 --- a/target/linux/generic-2.6/files/drivers/ssb/driver_chipcommon.c +++ b/target/linux/generic-2.6/files/drivers/ssb/driver_chipcommon.c @@ -16,7 +16,7 @@  /* Clock sources */ -enum { +enum ssb_clksrc {  	/* PCI clock */  	SSB_CHIPCO_CLKSRC_PCI,  	/* Crystal slow clock oscillator */ @@ -39,6 +39,14 @@ static inline void chipco_write32(struct ssb_chipcommon *cc,  	ssb_write32(cc->dev, offset, value);  } +static inline void chipco_write32_masked(struct ssb_chipcommon *cc, u16 offset, +					 u32 mask, u32 value) +{ +	value &= mask; +	value |= chipco_read32(cc, offset) & ~mask; +	chipco_write32(cc, offset, value); +} +  void ssb_chipco_set_clockmode(struct ssb_chipcommon *cc,  			      enum ssb_clkmode mode)  { @@ -85,15 +93,15 @@ void ssb_chipco_set_clockmode(struct ssb_chipcommon *cc,  			ssb_pci_xtal(bus, SSB_GPIO_XTAL, 0);  		break;  	default: -		assert(0); +		SSB_WARN_ON(1);  	}  }  /* Get the Slow Clock Source */ -static int chipco_pctl_get_slowclksrc(struct ssb_chipcommon *cc) +static enum ssb_clksrc chipco_pctl_get_slowclksrc(struct ssb_chipcommon *cc)  {  	struct ssb_bus *bus = cc->dev->bus; -	u32 tmp = 0; +	u32 uninitialized_var(tmp);  	if (cc->dev->id.revision < 6) {  		if (bus->bustype == SSB_BUSTYPE_SSB || @@ -123,9 +131,9 @@ static int chipco_pctl_get_slowclksrc(struct ssb_chipcommon *cc)  /* Get maximum or minimum (depending on get_max flag) slowclock frequency. */  static int chipco_pctl_clockfreqlimit(struct ssb_chipcommon *cc, int get_max)  { -	int limit; -	int clocksrc; -	int divisor; +	int uninitialized_var(limit); +	enum ssb_clksrc clocksrc; +	int divisor = 1;  	u32 tmp;  	clocksrc = chipco_pctl_get_slowclksrc(cc); @@ -138,13 +146,11 @@ static int chipco_pctl_clockfreqlimit(struct ssb_chipcommon *cc, int get_max)  			divisor = 32;  			break;  		default: -			assert(0); -			divisor = 1; +			SSB_WARN_ON(1);  		}  	} else if (cc->dev->id.revision < 10) {  		switch (clocksrc) {  		case SSB_CHIPCO_CLKSRC_LOPWROS: -			divisor = 1;  			break;  		case SSB_CHIPCO_CLKSRC_XTALOS:  		case SSB_CHIPCO_CLKSRC_PCI: @@ -152,9 +158,6 @@ static int chipco_pctl_clockfreqlimit(struct ssb_chipcommon *cc, int get_max)  			divisor = (tmp >> 16) + 1;  			divisor *= 4;  			break; -		default: -			assert(0); -			divisor = 1;  		}  	} else {  		tmp = chipco_read32(cc, SSB_CHIPCO_SYSCLKCTL); @@ -181,9 +184,6 @@ static int chipco_pctl_clockfreqlimit(struct ssb_chipcommon *cc, int get_max)  		else  			limit = 25000000;  		break; -	default: -		assert(0); -		limit = 0;  	}  	limit /= divisor; @@ -235,7 +235,7 @@ static void calc_fast_powerup_delay(struct ssb_chipcommon *cc)  	minfreq = chipco_pctl_clockfreqlimit(cc, 0);  	pll_on_delay = chipco_read32(cc, SSB_CHIPCO_PLLONDELAY);  	tmp = (((pll_on_delay + 2) * 1000000) + (minfreq - 1)) / minfreq; -	assert((tmp & ~0xFFFF) == 0); +	SSB_WARN_ON(tmp & ~0xFFFF);  	cc->fast_pwrup_delay = tmp;  } @@ -264,6 +264,30 @@ void ssb_chipco_resume(struct ssb_chipcommon *cc)  	ssb_chipco_set_clockmode(cc, SSB_CLKMODE_FAST);  } +/* Get the processor clock */ +void ssb_chipco_get_clockcpu(struct ssb_chipcommon *cc, +                             u32 *plltype, u32 *n, u32 *m) +{ +	*n = chipco_read32(cc, SSB_CHIPCO_CLOCK_N); +	*plltype = (cc->capabilities & SSB_CHIPCO_CAP_PLLT); +	switch (*plltype) { +	case SSB_PLLTYPE_2: +	case SSB_PLLTYPE_4: +	case SSB_PLLTYPE_6: +	case SSB_PLLTYPE_7: +		*m = chipco_read32(cc, SSB_CHIPCO_CLOCK_MIPS); +		break; +	case SSB_PLLTYPE_3: +		/* 5350 uses m2 to control mips */ +		*m = chipco_read32(cc, SSB_CHIPCO_CLOCK_M2); +		break; +	default: +		*m = chipco_read32(cc, SSB_CHIPCO_CLOCK_SB); +		break; +	} +} + +/* Get the bus clock */  void ssb_chipco_get_clockcontrol(struct ssb_chipcommon *cc,  				 u32 *plltype, u32 *n, u32 *m)  { @@ -320,6 +344,27 @@ void ssb_chipco_timing_init(struct ssb_chipcommon *cc,  	}  } +/* Set chip watchdog reset timer to fire in 'ticks' backplane cycles */ +void ssb_chipco_watchdog_timer_set(struct ssb_chipcommon *cc, u32 ticks) +{ +	/* instant NMI */ +	chipco_write32(cc, SSB_CHIPCO_WATCHDOG, ticks); +} + +u32 ssb_chipco_gpio_in(struct ssb_chipcommon *cc, u32 mask) +{ +	return chipco_read32(cc, SSB_CHIPCO_GPIOIN) & mask; +} + +void ssb_chipco_gpio_out(struct ssb_chipcommon *cc, u32 mask, u32 value) +{ +	chipco_write32_masked(cc, SSB_CHIPCO_GPIOOUT, mask, value); +} + +void ssb_chipco_gpio_outen(struct ssb_chipcommon *cc, u32 mask, u32 value) +{ +	chipco_write32_masked(cc, SSB_CHIPCO_GPIOOUTEN, mask, value); +}  #ifdef CONFIG_SSB_SERIAL  int ssb_chipco_serial_init(struct ssb_chipcommon *cc, @@ -352,10 +397,8 @@ int ssb_chipco_serial_init(struct ssb_chipcommon *cc,  		} else if (cc->dev->id.revision >= 3) {  			/* Internal backplane clock */  			baud_base = ssb_clockspeed(bus); -			div = 2; /* Minimum divisor */ -			chipco_write32(cc, SSB_CHIPCO_CLKDIV, -				       (chipco_read32(cc, SSB_CHIPCO_CLKDIV) -				        & ~SSB_CHIPCO_CLKDIV_UART) | div); +			div = chipco_read32(cc, SSB_CHIPCO_CLKDIV) +			      & SSB_CHIPCO_CLKDIV_UART;  		} else {  			/* Fixed internal backplane clock */  			baud_base = 88000000; diff --git a/target/linux/generic-2.6/files/drivers/ssb/driver_extif.c b/target/linux/generic-2.6/files/drivers/ssb/driver_extif.c new file mode 100644 index 000000000..fe55eb8b0 --- /dev/null +++ b/target/linux/generic-2.6/files/drivers/ssb/driver_extif.c @@ -0,0 +1,129 @@ +/* + * Sonics Silicon Backplane + * Broadcom EXTIF core driver + * + * Copyright 2005, Broadcom Corporation + * Copyright 2006, 2007, Michael Buesch <mb@bu3sch.de> + * Copyright 2006, 2007, Felix Fietkau <nbd@openwrt.org> + * Copyright 2007, Aurelien Jarno <aurelien@aurel32.net> + * + * Licensed under the GNU/GPL. See COPYING for details. + */ + +#include <linux/serial.h> +#include <linux/serial_core.h> +#include <linux/serial_reg.h> + +#include "ssb_private.h" + + +static inline u32 extif_read32(struct ssb_extif *extif, u16 offset) +{ +	return ssb_read32(extif->dev, offset); +} + +static inline void extif_write32(struct ssb_extif *extif, u16 offset, u32 value) +{ +	ssb_write32(extif->dev, offset, value); +} + +static inline void extif_write32_masked(struct ssb_extif *extif, u16 offset, +					u32 mask, u32 value) +{ +	value &= mask; +	value |= extif_read32(extif, offset) & ~mask; +	extif_write32(extif, offset, value); +} + +#ifdef CONFIG_SSB_SERIAL +static bool serial_exists(u8 *regs) +{ +	u8 save_mcr, msr = 0; + +	if (regs) { +		save_mcr = regs[UART_MCR]; +		regs[UART_MCR] = (UART_MCR_LOOP | UART_MCR_OUT2 | UART_MCR_RTS); +		msr = regs[UART_MSR] & (UART_MSR_DCD | UART_MSR_RI +					| UART_MSR_CTS | UART_MSR_DSR); +		regs[UART_MCR] = save_mcr; +	} +	return (msr == (UART_MSR_DCD | UART_MSR_CTS)); +} + +int ssb_extif_serial_init(struct ssb_extif *extif, struct ssb_serial_port *ports) +{ +	u32 i, nr_ports = 0; + +	/* Disable GPIO interrupt initially */ +	extif_write32(extif, SSB_EXTIF_GPIO_INTPOL, 0); +	extif_write32(extif, SSB_EXTIF_GPIO_INTMASK, 0); + +	for (i = 0; i < 2; i++) { +		void __iomem *uart_regs; + +		uart_regs = ioremap_nocache(SSB_EUART, 16); +		if (uart_regs) { +			uart_regs += (i * 8); + +			if (serial_exists(uart_regs) && ports) { +				extif_write32(extif, SSB_EXTIF_GPIO_INTMASK, 2); + +				nr_ports++; +				ports[i].regs = uart_regs; +				ports[i].irq = 2; +				ports[i].baud_base = 13500000; +				ports[i].reg_shift = 0; +			} +			iounmap(uart_regs); +		} +	} +	return nr_ports; +} +#endif /* CONFIG_SSB_SERIAL */ + +void ssb_extif_timing_init(struct ssb_extif *extif, unsigned long ns) +{ +	u32 tmp; + +	/* Initialize extif so we can get to the LEDs and external UART */ +	extif_write32(extif, SSB_EXTIF_PROG_CFG, SSB_EXTCFG_EN); + +	/* Set timing for the flash */ +	tmp  = DIV_ROUND_UP(10, ns) << SSB_PROG_WCNT_3_SHIFT; +	tmp |= DIV_ROUND_UP(40, ns) << SSB_PROG_WCNT_1_SHIFT; +	tmp |= DIV_ROUND_UP(120, ns); +	extif_write32(extif, SSB_EXTIF_PROG_WAITCNT, tmp); + +	/* Set programmable interface timing for external uart */ +	tmp  = DIV_ROUND_UP(10, ns) << SSB_PROG_WCNT_3_SHIFT; +	tmp |= DIV_ROUND_UP(20, ns) << SSB_PROG_WCNT_2_SHIFT; +	tmp |= DIV_ROUND_UP(100, ns) << SSB_PROG_WCNT_1_SHIFT; +	tmp |= DIV_ROUND_UP(120, ns); +	extif_write32(extif, SSB_EXTIF_PROG_WAITCNT, tmp); +} + +void ssb_extif_get_clockcontrol(struct ssb_extif *extif, +				u32 *pll_type, u32 *n, u32 *m) +{ +	*pll_type = SSB_PLLTYPE_1; +	*n = extif_read32(extif, SSB_EXTIF_CLOCK_N); +	*m = extif_read32(extif, SSB_EXTIF_CLOCK_SB); +} + +u32 ssb_extif_gpio_in(struct ssb_extif *extif, u32 mask) +{ +	return extif_read32(extif, SSB_EXTIF_GPIO_IN) & mask; +} + +void ssb_extif_gpio_out(struct ssb_extif *extif, u32 mask, u32 value) +{ +	return extif_write32_masked(extif, SSB_EXTIF_GPIO_OUT(0), +				   mask, value); +} + +void ssb_extif_gpio_outen(struct ssb_extif *extif, u32 mask, u32 value) +{ +	return extif_write32_masked(extif, SSB_EXTIF_GPIO_OUTEN(0), +				   mask, value); +} + diff --git a/target/linux/generic-2.6/files/drivers/ssb/driver_mipscore.c b/target/linux/generic-2.6/files/drivers/ssb/driver_mipscore.c index 67d10178b..3d3dd32bf 100644 --- a/target/linux/generic-2.6/files/drivers/ssb/driver_mipscore.c +++ b/target/linux/generic-2.6/files/drivers/ssb/driver_mipscore.c @@ -13,7 +13,7 @@  #include <linux/serial.h>  #include <linux/serial_core.h>  #include <linux/serial_reg.h> -#include <asm/time.h> +#include <linux/time.h>  #include "ssb_private.h" @@ -117,51 +117,10 @@ static void set_irq(struct ssb_device *dev, unsigned int irq)  	ssb_write32(mdev, SSB_IPSFLAG, irqflag);  } -/* XXX: leave here or move into separate extif driver? */ -static int ssb_extif_serial_init(struct ssb_device *dev, struct ssb_serial_ports *ports) -{ - -} - -  static void ssb_mips_serial_init(struct ssb_mipscore *mcore)  {  	struct ssb_bus *bus = mcore->dev->bus; -	//TODO if (EXTIF available -#if 0 -		extifregs_t *eir = (extifregs_t *) regs; -		sbconfig_t *sb; - -		/* Determine external UART register base */ -		sb = (sbconfig_t *)((ulong) eir + SBCONFIGOFF); -		base = EXTIF_CFGIF_BASE(sb_base(R_REG(&sb->sbadmatch1))); - -		/* Determine IRQ */ -		irq = sb_irq(sbh); - -		/* Disable GPIO interrupt initially */ -		W_REG(&eir->gpiointpolarity, 0); -		W_REG(&eir->gpiointmask, 0); - -		/* Search for external UARTs */ -		n = 2; -		for (i = 0; i < 2; i++) { -			regs = (void *) REG_MAP(base + (i * 8), 8); -			if (BCMINIT(serial_exists)(regs)) { -				/* Set GPIO 1 to be the external UART IRQ */ -				W_REG(&eir->gpiointmask, 2); -				if (add) -					add(regs, irq, 13500000, 0); -			} -		} - -		/* Add internal UART if enabled */ -		if (R_REG(&eir->corecontrol) & CC_UE) -			if (add) -				add((void *) &eir->uartdata, irq, sb_clock(sbh), 2); - -#endif  	if (bus->extif.dev)  		mcore->nr_serial_ports = ssb_extif_serial_init(&bus->extif, mcore->serial_ports);  	else if (bus->chipco.dev) @@ -174,23 +133,47 @@ static void ssb_mips_flash_detect(struct ssb_mipscore *mcore)  {  	struct ssb_bus *bus = mcore->dev->bus; +	mcore->flash_buswidth = 2;  	if (bus->chipco.dev) {  		mcore->flash_window = 0x1c000000; -		mcore->flash_window_size = 0x800000; +		mcore->flash_window_size = 0x02000000; +		if ((ssb_read32(bus->chipco.dev, SSB_CHIPCO_FLASH_CFG) +		               & SSB_CHIPCO_CFG_DS16) == 0) +			mcore->flash_buswidth = 1;  	} else {  		mcore->flash_window = 0x1fc00000; -		mcore->flash_window_size = 0x400000; +		mcore->flash_window_size = 0x00400000;  	}  } - -static void ssb_cpu_clock(struct ssb_mipscore *mcore) +u32 ssb_cpu_clock(struct ssb_mipscore *mcore)  { +	struct ssb_bus *bus = mcore->dev->bus; +	u32 pll_type, n, m, rate = 0; + +	if (bus->extif.dev) { +		ssb_extif_get_clockcontrol(&bus->extif, &pll_type, &n, &m); +	} else if (bus->chipco.dev) { +		ssb_chipco_get_clockcpu(&bus->chipco, &pll_type, &n, &m); +	} else +		return 0; + +	if ((pll_type == SSB_PLLTYPE_5) || (bus->chip_id == 0x5365)) { +		rate = 200000000; +	} else { +		rate = ssb_calc_clock_rate(pll_type, n, m); +	} + +	if (pll_type == SSB_PLLTYPE_6) { +		rate *= 2; +	} + +	return rate;  }  void ssb_mipscore_init(struct ssb_mipscore *mcore)  { -	struct ssb_bus *bus = mcore->dev->bus; +	struct ssb_bus *bus;  	struct ssb_device *dev;  	unsigned long hz, ns;  	unsigned int irq, i; @@ -200,56 +183,39 @@ void ssb_mipscore_init(struct ssb_mipscore *mcore)  	ssb_dprintk(KERN_INFO PFX "Initializing MIPS core...\n"); +	bus = mcore->dev->bus;  	hz = ssb_clockspeed(bus);  	if (!hz)  		hz = 100000000;  	ns = 1000000000 / hz; -//TODO -#if 0 -	if (have EXTIF) { -		/* Initialize extif so we can get to the LEDs and external UART */ -		W_REG(&eir->prog_config, CF_EN); - -		/* Set timing for the flash */ -		tmp = CEIL(10, ns) << FW_W3_SHIFT;	/* W3 = 10nS */ -		tmp = tmp | (CEIL(40, ns) << FW_W1_SHIFT); /* W1 = 40nS */ -		tmp = tmp | CEIL(120, ns);		/* W0 = 120nS */ -		W_REG(&eir->prog_waitcount, tmp);	/* 0x01020a0c for a 100Mhz clock */ - -		/* Set programmable interface timing for external uart */ -		tmp = CEIL(10, ns) << FW_W3_SHIFT;	/* W3 = 10nS */ -		tmp = tmp | (CEIL(20, ns) << FW_W2_SHIFT); /* W2 = 20nS */ -		tmp = tmp | (CEIL(100, ns) << FW_W1_SHIFT); /* W1 = 100nS */ -		tmp = tmp | CEIL(120, ns);		/* W0 = 120nS */ -		W_REG(&eir->prog_waitcount, tmp); -	} -	else... chipcommon -#endif -	if (bus->chipco.dev) +	if (bus->extif.dev) +		ssb_extif_timing_init(&bus->extif, ns); +	else if (bus->chipco.dev)  		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 */  	for (irq = 2, i = 0; i < bus->nr_devices; i++) {  		dev = &(bus->devices[i]);  		dev->irq = ssb_mips_irq(dev) + 2; -		switch(dev->id.coreid) { -			case SSB_DEV_USB11_HOST: -				/* shouldn't need a separate irq line for non-4710, most of them have a proper -				 * external usb controller on the pci */ -				if ((bus->chip_id == 0x4710) && (irq <= 4)) { -					set_irq(dev, irq++); -					break; -				} -			case SSB_DEV_PCI: -			case SSB_DEV_ETHERNET: -			case SSB_DEV_80211: -			case SSB_DEV_USB20_HOST: -				/* These devices get their own IRQ line if available, the rest goes on IRQ0 */ -				if (irq <= 4) { -					set_irq(dev, irq++); -					break; -				} +		switch (dev->id.coreid) { +		case SSB_DEV_USB11_HOST: +			/* shouldn't need a separate irq line for non-4710, most of them have a proper +			 * external usb controller on the pci */ +			if ((bus->chip_id == 0x4710) && (irq <= 4)) { +				set_irq(dev, irq++); +				break; +			} +			/* fallthrough */ +		case SSB_DEV_PCI: +		case SSB_DEV_ETHERNET: +		case SSB_DEV_80211: +		case SSB_DEV_USB20_HOST: +			/* These devices get their own IRQ line if available, the rest goes on IRQ0 */ +			if (irq <= 4) { +				set_irq(dev, irq++); +				break; +			}  		}  	} diff --git a/target/linux/generic-2.6/files/drivers/ssb/driver_pcicore.c b/target/linux/generic-2.6/files/drivers/ssb/driver_pcicore.c index a59dff083..2faaa906d 100644 --- a/target/linux/generic-2.6/files/drivers/ssb/driver_pcicore.c +++ b/target/linux/generic-2.6/files/drivers/ssb/driver_pcicore.c @@ -34,8 +34,10 @@ void pcicore_write32(struct ssb_pcicore *pc, u16 offset, u32 value)  #ifdef CONFIG_SSB_PCICORE_HOSTMODE  #include <asm/paccess.h> -/* Read the bus and catch bus exceptions. This is MIPS specific. */ -#define mips_busprobe(val, addr)	get_dbe((val), (addr)) +/* Probe a 32bit value on the bus and catch bus exceptions. + * Returns nonzero on a bus exception. + * This is MIPS specific */ +#define mips_busprobe32(val, addr)	get_dbe((val), ((u32 *)(addr)))  /* Assume one-hot slot wiring */  #define SSB_PCI_SLOT_MAX	16 @@ -45,8 +47,8 @@ static DEFINE_SPINLOCK(cfgspace_lock);  /* Core to access the external PCI config space. Can only have one. */  static struct ssb_pcicore *extpci_core; -u32 pci_iobase = 0x100; -u32 pci_membase = SSB_PCI_DMA; +static u32 ssb_pcicore_pcibus_iobase = 0x100; +static u32 ssb_pcicore_pcibus_membase = SSB_PCI_DMA;  int pcibios_plat_dev_init(struct pci_dev *d)  { @@ -54,12 +56,16 @@ int pcibios_plat_dev_init(struct pci_dev *d)  	int pos, size;  	u32 *base; -	printk("PCI: Fixing up device %s\n", pci_name(d)); +	ssb_printk(KERN_INFO "PCI: Fixing up device %s\n", +		   pci_name(d));  	/* Fix up resource bases */  	for (pos = 0; pos < 6; pos++) {  		res = &d->resource[pos]; -		base = ((res->flags & IORESOURCE_IO) ? &pci_iobase : &pci_membase); +		if (res->flags & IORESOURCE_IO) +			base = &ssb_pcicore_pcibus_iobase; +		else +			base = &ssb_pcicore_pcibus_membase;  		if (res->end) {  			size = res->end - res->start + 1;  			if (*base & (size - 1)) @@ -85,7 +91,7 @@ static void __init ssb_fixup_pcibridge(struct pci_dev *dev)  	if (dev->bus->number != 0 || PCI_SLOT(dev->devfn) != 0)  		return; -	printk("PCI: fixing up bridge\n"); +	ssb_printk(KERN_INFO "PCI: fixing up bridge\n");  	/* Enable PCI bridge bus mastering and memory space */  	pci_set_master(dev); @@ -93,10 +99,13 @@ static void __init ssb_fixup_pcibridge(struct pci_dev *dev)  	/* Enable PCI bridge BAR1 prefetch and burst */  	pci_write_config_dword(dev, SSB_BAR1_CONTROL, 3); + +	/* Make sure our latency is high enough to handle the devices behind us */ +	pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0xa8);  }  DECLARE_PCI_FIXUP_EARLY(PCI_ANY_ID, PCI_ANY_ID, ssb_fixup_pcibridge); -int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) +int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)  {  	return ssb_mips_irq(extpci_core->dev) + 2;  } @@ -147,7 +156,7 @@ static int ssb_extpci_read_config(struct ssb_pcicore *pc,  	u32 addr, val;  	void __iomem *mmio; -	assert(pc->hostmode); +	SSB_WARN_ON(!pc->hostmode);  	if (unlikely(len != 1 && len != 2 && len != 4))  		goto out;  	addr = get_cfgspace_addr(pc, bus, dev, func, off); @@ -158,7 +167,7 @@ static int ssb_extpci_read_config(struct ssb_pcicore *pc,  	if (!mmio)  		goto out; -	if (mips_busprobe(val, (u32 *) mmio)) { +	if (mips_busprobe32(val, mmio)) {  		val = 0xffffffff;  		goto unmap;  	} @@ -193,7 +202,7 @@ static int ssb_extpci_write_config(struct ssb_pcicore *pc,  	u32 addr, val = 0;  	void __iomem *mmio; -	assert(pc->hostmode); +	SSB_WARN_ON(!pc->hostmode);  	if (unlikely(len != 1 && len != 2 && len != 4))  		goto out;  	addr = get_cfgspace_addr(pc, bus, dev, func, off); @@ -204,7 +213,7 @@ static int ssb_extpci_write_config(struct ssb_pcicore *pc,  	if (!mmio)  		goto out; -	if (mips_busprobe(val, (u32 *) mmio)) { +	if (mips_busprobe32(val, mmio)) {  		val = 0xffffffff;  		goto unmap;  	} @@ -224,7 +233,7 @@ static int ssb_extpci_write_config(struct ssb_pcicore *pc,  		val = *((const u32 *)buf);  		break;  	} -	writel(*((const u32 *)buf), mmio); +	writel(val, mmio);  	err = 0;  unmap: @@ -269,7 +278,7 @@ static struct pci_ops ssb_pcicore_pciops = {  static struct resource ssb_pcicore_mem_resource = {  	.name	= "SSB PCIcore external memory",  	.start	= SSB_PCI_DMA, -	.end	= (u32)SSB_PCI_DMA + (u32)SSB_PCI_DMA_SZ - 1, +	.end	= SSB_PCI_DMA + SSB_PCI_DMA_SZ - 1,  	.flags	= IORESOURCE_MEM,  }; @@ -291,10 +300,8 @@ static void ssb_pcicore_init_hostmode(struct ssb_pcicore *pc)  {  	u32 val; -	if (extpci_core) { -		WARN_ON(1); +	if (WARN_ON(extpci_core))  		return; -	}  	extpci_core = pc;  	ssb_dprintk(KERN_INFO PFX "PCIcore in host mode found\n"); @@ -304,12 +311,14 @@ static void ssb_pcicore_init_hostmode(struct ssb_pcicore *pc)  	pcicore_write32(pc, SSB_PCICORE_CTL, val);  	val |= SSB_PCICORE_CTL_CLK; /* Clock on */  	pcicore_write32(pc, SSB_PCICORE_CTL, val); -	udelay(150); +	udelay(150); /* Assertion time demanded by the PCI standard */  	val |= SSB_PCICORE_CTL_RST; /* Deassert RST# */  	pcicore_write32(pc, SSB_PCICORE_CTL, val); -	udelay(1); +	val = SSB_PCICORE_ARBCTL_INTERN; +	pcicore_write32(pc, SSB_PCICORE_ARBCTL, val); +	udelay(1); /* Assertion time demanded by the PCI standard */ -	//TODO cardbus mode +	/*TODO cardbus mode */  	/* 64MB I/O window */  	pcicore_write32(pc, SSB_PCICORE_SBTOPCI0, @@ -336,6 +345,9 @@ static void ssb_pcicore_init_hostmode(struct ssb_pcicore *pc)  	 * The following needs change, if we want to port hostmode  	 * to non-MIPS platform. */  	set_io_port_base((unsigned long)ioremap_nocache(SSB_PCI_MEM, 0x04000000)); +	/* 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);  	register_pci_controller(&ssb_pcicore_controller);  } @@ -364,7 +376,7 @@ static int pcicore_is_in_hostmode(struct ssb_pcicore *pc)  	if (bus->chip_id == 0x5350)  		return 0; -	return !mips_busprobe(tmp, (u32 *) (bus->mmio + (pc->dev->core_index * SSB_CORE_SIZE))); +	return !mips_busprobe32(tmp, (bus->mmio + (pc->dev->core_index * SSB_CORE_SIZE)));  }  #endif /* CONFIG_SSB_PCICORE_HOSTMODE */ @@ -430,6 +442,7 @@ static void ssb_pcie_mdio_write(struct ssb_pcicore *pc, u8 device,  	v |= (u32)address << 18;  	v |= data;  	pcicore_write32(pc, mdio_data, v); +	/* Wait for the device to complete the transaction */  	udelay(10);  	for (i = 0; i < 10; i++) {  		v = pcicore_read32(pc, mdio_control); @@ -458,7 +471,8 @@ static void ssb_commit_settings(struct ssb_bus *bus)  	struct ssb_device *dev;  	dev = bus->chipco.dev ? bus->chipco.dev : bus->pcicore.dev; -	assert(dev); +	if (WARN_ON(!dev)) +		return;  	/* This forces an update of the cached registers. */  	ssb_broadcast_value(dev, 0xFD8, 0);  } @@ -496,9 +510,15 @@ int ssb_pcicore_dev_irqvecs_enable(struct ssb_pcicore *pc,  		u32 intvec;  		intvec = ssb_read32(pdev, SSB_INTVEC); -		tmp = ssb_read32(dev, SSB_TPSFLAG); -		tmp &= SSB_TPSFLAG_BPFLAG; -		intvec |= tmp; +		if ((bus->chip_id & 0xFF00) == 0x4400) { +			/* Workaround: On the BCM44XX the BPFLAG routing +			 * bit is wrong. Use a hardcoded constant. */ +			intvec |= 0x00000002; +		} else { +			tmp = ssb_read32(dev, SSB_TPSFLAG); +			tmp &= SSB_TPSFLAG_BPFLAG; +			intvec |= tmp; +		}  		ssb_write32(pdev, SSB_INTVEC, intvec);  	} @@ -525,7 +545,7 @@ int ssb_pcicore_dev_irqvecs_enable(struct ssb_pcicore *pc,  			pcicore_write32(pc, SSB_PCICORE_SBTOPCI2, tmp);  		}  	} else { -		assert(pdev->id.coreid == SSB_DEV_PCIE); +		WARN_ON(pdev->id.coreid != SSB_DEV_PCIE);  		//TODO: Better make defines for all these magic PCIE values.  		if ((pdev->id.revision == 0) || (pdev->id.revision == 1)) {  			/* TLP Workaround register. */ diff --git a/target/linux/generic-2.6/files/drivers/ssb/main.c b/target/linux/generic-2.6/files/drivers/ssb/main.c index a892f1daf..74d5182db 100644 --- a/target/linux/generic-2.6/files/drivers/ssb/main.c +++ b/target/linux/generic-2.6/files/drivers/ssb/main.c @@ -13,34 +13,43 @@  #include <linux/delay.h>  #include <linux/ssb/ssb.h>  #include <linux/ssb/ssb_regs.h> +#include <linux/dma-mapping.h> +#include <linux/pci.h> -#ifdef CONFIG_SSB_PCIHOST -# include <linux/pci.h> -#endif - -#ifdef CONFIG_SSB_PCMCIAHOST -# include <pcmcia/cs_types.h> -# include <pcmcia/cs.h> -# include <pcmcia/cistpl.h> -# include <pcmcia/ds.h> -#endif +#include <pcmcia/cs_types.h> +#include <pcmcia/cs.h> +#include <pcmcia/cistpl.h> +#include <pcmcia/ds.h>  MODULE_DESCRIPTION("Sonics Silicon Backplane driver");  MODULE_LICENSE("GPL"); +/* Temporary list of yet-to-be-attached buses */  static LIST_HEAD(attach_queue); +/* List if running buses */  static LIST_HEAD(buses); +/* Software ID counter */  static unsigned int next_busnumber; +/* buses_mutes locks the two buslists and the next_busnumber. + * Don't lock this directly, but use ssb_buses_[un]lock() below. */  static DEFINE_MUTEX(buses_mutex); +/* There are differences in the codeflow, if the bus is + * initialized from early boot, as various needed services + * are not available early. This is a mechanism to delay + * these initializations to after early boot has finished. + * It's also used to avoid mutex locking, as that's not + * available and needed early. */ +static bool ssb_is_early_boot = 1; +  static void ssb_buses_lock(void);  static void ssb_buses_unlock(void);  #ifdef CONFIG_SSB_PCIHOST -struct ssb_bus * ssb_pci_dev_to_bus(struct pci_dev *pdev) +struct ssb_bus *ssb_pci_dev_to_bus(struct pci_dev *pdev)  {  	struct ssb_bus *bus; @@ -58,7 +67,7 @@ found:  }  #endif /* CONFIG_SSB_PCIHOST */ -static struct ssb_device * ssb_device_get(struct ssb_device *dev) +static struct ssb_device *ssb_device_get(struct ssb_device *dev)  {  	if (dev)  		get_device(dev->dev); @@ -122,6 +131,9 @@ static void ssb_bus_suspend(struct ssb_bus *bus, pm_message_t state)  #ifdef CONFIG_SSB_DRIVER_PCICORE  	bus->pcicore.setup_done = 0;  #endif +#ifdef CONFIG_SSB_DEBUG +	bus->powered_up = 0; +#endif  }  static int ssb_device_suspend(struct device *dev, pm_message_t state) @@ -159,20 +171,53 @@ int ssb_devices_freeze(struct ssb_bus *bus)  	int i;  	pm_message_t state = PMSG_FREEZE; +	/* First check that we are capable to freeze all devices. */  	for (i = 0; i < bus->nr_devices; i++) {  		dev = &(bus->devices[i]); -		if (!dev->dev->driver) +		if (!dev->dev || +		    !dev->dev->driver || +		    !device_is_registered(dev->dev))  			continue; -		if (!device_is_registered(dev->dev)) +		drv = drv_to_ssb_drv(dev->dev->driver); +		if (!drv) +			continue; +		if (!drv->suspend) { +			/* Nope, can't suspend this one. */ +			return -EOPNOTSUPP; +		} +	} +	/* Now suspend all devices */ +	for (i = 0; i < bus->nr_devices; i++) { +		dev = &(bus->devices[i]); +		if (!dev->dev || +		    !dev->dev->driver || +		    !device_is_registered(dev->dev))  			continue;  		drv = drv_to_ssb_drv(dev->dev->driver); -		if (drv && drv->suspend) { -			err = drv->suspend(dev, state); -			if (err) -				goto out; +		if (!drv) +			continue; +		err = drv->suspend(dev, state); +		if (err) { +			ssb_printk(KERN_ERR PFX "Failed to freeze device %s\n", +				   dev->dev->bus_id); +			goto err_unwind;  		}  	} -out: + +	return 0; +err_unwind: +	for (i--; i >= 0; i--) { +		dev = &(bus->devices[i]); +		if (!dev->dev || +		    !dev->dev->driver || +		    !device_is_registered(dev->dev)) +			continue; +		drv = drv_to_ssb_drv(dev->dev->driver); +		if (!drv) +			continue; +		if (drv->resume) +			drv->resume(dev); +	}  	return err;  } @@ -180,24 +225,28 @@ int ssb_devices_thaw(struct ssb_bus *bus)  {  	struct ssb_device *dev;  	struct ssb_driver *drv; -	int err = 0; +	int err;  	int i;  	for (i = 0; i < bus->nr_devices; i++) {  		dev = &(bus->devices[i]); -		if (!dev->dev->driver) -			continue; -		if (!device_is_registered(dev->dev)) +		if (!dev->dev || +		    !dev->dev->driver || +		    !device_is_registered(dev->dev))  			continue;  		drv = drv_to_ssb_drv(dev->dev->driver); -		if (drv && drv->resume) { -			err = drv->resume(dev); -			if (err) -				goto out; +		if (!drv) +			continue; +		if (SSB_WARN_ON(!drv->resume)) +			continue; +		err = drv->resume(dev); +		if (err) { +			ssb_printk(KERN_ERR PFX "Failed to thaw device %s\n", +				   dev->dev->bus_id);  		}  	} -out: -	return err; + +	return 0;  }  #endif /* CONFIG_SSB_PCIHOST */ @@ -271,27 +320,47 @@ static int ssb_bus_match(struct device *dev, struct device_driver *drv)  	return 0;  } +static int ssb_device_uevent(struct device *dev, char **envp, int num_envp, +			     char *buffer, int buffer_size) +{ +	struct ssb_device *ssb_dev = dev_to_ssb_dev(dev); +	int ret, i = 0, length = 0; + +	if (!dev) +		return -ENODEV; + +	ret = add_uevent_var(envp, num_envp, &i, +			     buffer, buffer_size, &length, +			     "MODALIAS=ssb:v%04Xid%04Xrev%02X", +			     ssb_dev->id.vendor, ssb_dev->id.coreid, +			     ssb_dev->id.revision); +	envp[i] = NULL; + +	return ret; +} +  static struct bus_type ssb_bustype = { -	.name		= NULL, /* Intentionally NULL to indicate early boot */ +	.name		= "ssb",  	.match		= ssb_bus_match,  	.probe		= ssb_device_probe,  	.remove		= ssb_device_remove,  	.shutdown	= ssb_device_shutdown,  	.suspend	= ssb_device_suspend,  	.resume		= ssb_device_resume, +	.uevent		= ssb_device_uevent,  }; -#define is_early_boot()		(ssb_bustype.name == NULL) -  static void ssb_buses_lock(void)  { -	if (!is_early_boot()) +	/* See the comment at the ssb_is_early_boot definition */ +	if (!ssb_is_early_boot)  		mutex_lock(&buses_mutex);  }  static void ssb_buses_unlock(void)  { -	if (!is_early_boot()) +	/* See the comment at the ssb_is_early_boot definition */ +	if (!ssb_is_early_boot)  		mutex_unlock(&buses_mutex);  } @@ -421,9 +490,14 @@ static int ssb_attach_queued_buses(void)  		 * is too early in boot for embedded systems  		 * (no udelay() available). So do it here in attach stage.  		 */ +		err = ssb_bus_powerup(bus, 0); +		if (err) +			goto error;  		ssb_pcicore_init(&bus->pcicore); +		ssb_bus_may_powerdown(bus);  		err = ssb_devices_register(bus); +error:  		if (err) {  			drop_them_all = 1;  			list_del(&bus->list); @@ -467,6 +541,7 @@ static void ssb_ssb_write32(struct ssb_device *dev, u16 offset, u32 value)  	writel(value, bus->mmio + offset);  } +/* Ops for the plain SSB bus without a host-device (no PCI or PCMCIA). */  static const struct ssb_bus_ops ssb_ssb_ops = {  	.read16		= ssb_ssb_read16,  	.read32		= ssb_ssb_read32, @@ -475,8 +550,7 @@ static const struct ssb_bus_ops ssb_ssb_ops = {  };  static int ssb_fetch_invariants(struct ssb_bus *bus, -				int (*get_invariants)(struct ssb_bus *bus, -						      struct ssb_init_invariants *iv)) +				ssb_invariants_func_t get_invariants)  {  	struct ssb_init_invariants iv;  	int err; @@ -492,8 +566,7 @@ out:  }  static int ssb_bus_register(struct ssb_bus *bus, -			    int (*get_invariants)(struct ssb_bus *bus, -			    			  struct ssb_init_invariants *iv), +			    ssb_invariants_func_t get_invariants,  			    unsigned long baseaddr)  {  	int err; @@ -522,15 +595,22 @@ static int ssb_bus_register(struct ssb_bus *bus,  		goto err_pci_exit;  	/* Initialize basic system devices (if available) */ +	err = ssb_bus_powerup(bus, 0); +	if (err) +		goto err_pcmcia_exit;  	ssb_chipcommon_init(&bus->chipco);  	ssb_mipscore_init(&bus->mipscore);  	err = ssb_fetch_invariants(bus, get_invariants); -	if (err) +	if (err) { +		ssb_bus_may_powerdown(bus);  		goto err_pcmcia_exit; +	} +	ssb_bus_may_powerdown(bus); -	/* Queue it for attach */ +	/* Queue it for attach. +	 * See the comment at the ssb_is_early_boot definition. */  	list_add_tail(&bus->list, &attach_queue); -	if (!is_early_boot()) { +	if (!ssb_is_early_boot) {  		/* This is not early boot, so we must attach the bus now */  		err = ssb_attach_queued_buses();  		if (err) @@ -601,8 +681,7 @@ EXPORT_SYMBOL(ssb_bus_pcmciabus_register);  int ssb_bus_ssbbus_register(struct ssb_bus *bus,  			    unsigned long baseaddr, -			    int (*get_invariants)(struct ssb_bus *bus, -			    			  struct ssb_init_invariants *iv)) +			    ssb_invariants_func_t get_invariants)  {  	int err; @@ -695,13 +774,13 @@ u32 ssb_calc_clock_rate(u32 plltype, u32 n, u32 m)  	case SSB_PLLTYPE_2: /* 48Mhz, 4 dividers */  		n1 += SSB_CHIPCO_CLK_T2_BIAS;  		n2 += SSB_CHIPCO_CLK_T2_BIAS; -		assert((n1 >= 2) && (n1 <= 7)); -		assert((n2 >= 5) && (n2 <= 23)); +		SSB_WARN_ON(!((n1 >= 2) && (n1 <= 7))); +		SSB_WARN_ON(!((n2 >= 5) && (n2 <= 23)));  		break;  	case SSB_PLLTYPE_5: /* 25Mhz, 4 dividers */  		return 100000000;  	default: -		assert(0); +		SSB_WARN_ON(1);  	}  	switch (plltype) { @@ -750,9 +829,9 @@ u32 ssb_calc_clock_rate(u32 plltype, u32 n, u32 m)  		m1 += SSB_CHIPCO_CLK_T2_BIAS;  		m2 += SSB_CHIPCO_CLK_T2M2_BIAS;  		m3 += SSB_CHIPCO_CLK_T2_BIAS; -		assert((m1 >= 2) && (m1 <= 7)); -		assert((m2 >= 3) && (m2 <= 10)); -		assert((m3 >= 2) && (m3 <= 7)); +		SSB_WARN_ON(!((m1 >= 2) && (m1 <= 7))); +		SSB_WARN_ON(!((m2 >= 3) && (m2 <= 10))); +		SSB_WARN_ON(!((m3 >= 2) && (m3 <= 7)));  		if (!(mc & SSB_CHIPCO_CLK_T2MC_M1BYP))  			clock /= m1; @@ -762,7 +841,7 @@ u32 ssb_calc_clock_rate(u32 plltype, u32 n, u32 m)  			clock /= m3;  		return clock;  	default: -		assert(0); +		SSB_WARN_ON(1);  	}  	return 0;  } @@ -774,12 +853,13 @@ u32 ssb_clockspeed(struct ssb_bus *bus)  	u32 plltype;  	u32 clkctl_n, clkctl_m; -	//TODO if EXTIF: PLLTYPE == 1, read n from clockcontrol_n, m from clockcontrol_sb - -	if (bus->chipco.dev) { +	if (ssb_extif_available(&bus->extif)) +		ssb_extif_get_clockcontrol(&bus->extif, &plltype, +					   &clkctl_n, &clkctl_m); +	else if (bus->chipco.dev)  		ssb_chipco_get_clockcontrol(&bus->chipco, &plltype,  					    &clkctl_n, &clkctl_m); -	} else +	else  		return 0;  	if (bus->chip_id == 0x5365) { @@ -804,7 +884,7 @@ static u32 ssb_tmslow_reject_bitmask(struct ssb_device *dev)  	case SSB_IDLOW_SSBREV_23:  		return SSB_TMSLOW_REJECT_23;  	default: -		assert(0); +		WARN_ON(1);  	}  	return (SSB_TMSLOW_REJECT_22 | SSB_TMSLOW_REJECT_23);  } @@ -822,6 +902,18 @@ int ssb_device_is_enabled(struct ssb_device *dev)  }  EXPORT_SYMBOL(ssb_device_is_enabled); +static void ssb_flush_tmslow(struct ssb_device *dev) +{ +	/* Make _really_ sure the device has finished the TMSLOW +	 * register write transaction, as we risk running into +	 * a machine check exception otherwise. +	 * Do this by reading the register back to commit the +	 * PCI write and delay an additional usec for the device +	 * to react to the change. */ +	ssb_read32(dev, SSB_TMSLOW); +	udelay(1); +} +  void ssb_device_enable(struct ssb_device *dev, u32 core_specific_flags)  {  	u32 val; @@ -830,9 +922,7 @@ void ssb_device_enable(struct ssb_device *dev, u32 core_specific_flags)  	ssb_write32(dev, SSB_TMSLOW,  		    SSB_TMSLOW_RESET | SSB_TMSLOW_CLOCK |  		    SSB_TMSLOW_FGC | core_specific_flags); -	/* flush */ -	ssb_read32(dev, SSB_TMSLOW); -	udelay(1); +	ssb_flush_tmslow(dev);  	/* Clear SERR if set. This is a hw bug workaround. */  	if (ssb_read32(dev, SSB_TMSHIGH) & SSB_TMSHIGH_SERR) @@ -847,18 +937,16 @@ void ssb_device_enable(struct ssb_device *dev, u32 core_specific_flags)  	ssb_write32(dev, SSB_TMSLOW,  		    SSB_TMSLOW_CLOCK | SSB_TMSLOW_FGC |  		    core_specific_flags); -	/* flush */ -	ssb_read32(dev, SSB_TMSLOW); -	udelay(1); +	ssb_flush_tmslow(dev);  	ssb_write32(dev, SSB_TMSLOW, SSB_TMSLOW_CLOCK |  		    core_specific_flags); -	/* flush */ -	ssb_read32(dev, SSB_TMSLOW); -	udelay(1); +	ssb_flush_tmslow(dev);  }  EXPORT_SYMBOL(ssb_device_enable); +/* Wait for a bit in a register to get set or unset. + * timeout is in units of ten-microseconds */  static int ssb_wait_bit(struct ssb_device *dev, u16 reg, u32 bitmask,  			int timeout, int set)  { @@ -898,22 +986,18 @@ void ssb_device_disable(struct ssb_device *dev, u32 core_specific_flags)  		    SSB_TMSLOW_FGC | SSB_TMSLOW_CLOCK |  		    reject | SSB_TMSLOW_RESET |  		    core_specific_flags); -	/* flush */ -	ssb_read32(dev, SSB_TMSLOW); -	udelay(1); +	ssb_flush_tmslow(dev);  	ssb_write32(dev, SSB_TMSLOW,  		    reject | SSB_TMSLOW_RESET |  		    core_specific_flags); -	/* flush */ -	ssb_read32(dev, SSB_TMSLOW); -	udelay(1); +	ssb_flush_tmslow(dev);  }  EXPORT_SYMBOL(ssb_device_disable);  u32 ssb_dma_translation(struct ssb_device *dev)  { -	switch(dev->bus->bustype) { +	switch (dev->bus->bustype) {  	case SSB_BUSTYPE_SSB:  		return 0;  	case SSB_BUSTYPE_PCI: @@ -943,28 +1027,31 @@ EXPORT_SYMBOL(ssb_dma_set_mask);  int ssb_bus_may_powerdown(struct ssb_bus *bus)  {  	struct ssb_chipcommon *cc; -	int err; +	int err = 0;  	/* On buses where more than one core may be working  	 * at a time, we must not powerdown stuff if there are  	 * still cores that may want to run. */  	if (bus->bustype == SSB_BUSTYPE_SSB) -		return 0; +		goto out;  	cc = &bus->chipco;  	ssb_chipco_set_clockmode(cc, SSB_CLKMODE_SLOW);  	err = ssb_pci_xtal(bus, SSB_GPIO_XTAL | SSB_GPIO_PLL, 0);  	if (err)  		goto error; - -	return 0; +out: +#ifdef CONFIG_SSB_DEBUG +	bus->powered_up = 0; +#endif +	return err;  error:  	ssb_printk(KERN_ERR PFX "Bus powerdown failed\n"); -	return err; +	goto out;  }  EXPORT_SYMBOL(ssb_bus_may_powerdown); -int ssb_bus_powerup(struct ssb_bus *bus, int dynamic_pctl) +int ssb_bus_powerup(struct ssb_bus *bus, bool dynamic_pctl)  {  	struct ssb_chipcommon *cc;  	int err; @@ -977,6 +1064,9 @@ int ssb_bus_powerup(struct ssb_bus *bus, int dynamic_pctl)  	mode = dynamic_pctl ? SSB_CLKMODE_DYNAMIC : SSB_CLKMODE_FAST;  	ssb_chipco_set_clockmode(cc, mode); +#ifdef CONFIG_SSB_DEBUG +	bus->powered_up = 1; +#endif  	return 0;  error:  	ssb_printk(KERN_ERR PFX "Bus powerup failed\n"); @@ -993,15 +1083,15 @@ u32 ssb_admatch_base(u32 adm)  		base = (adm & SSB_ADM_BASE0);  		break;  	case SSB_ADM_TYPE1: -		assert(!(adm & SSB_ADM_NEG)); /* unsupported */ +		SSB_WARN_ON(adm & SSB_ADM_NEG); /* unsupported */  		base = (adm & SSB_ADM_BASE1);  		break;  	case SSB_ADM_TYPE2: -		assert(!(adm & SSB_ADM_NEG)); /* unsupported */ +		SSB_WARN_ON(adm & SSB_ADM_NEG); /* unsupported */  		base = (adm & SSB_ADM_BASE2);  		break;  	default: -		assert(0); +		SSB_WARN_ON(1);  	}  	return base; @@ -1017,15 +1107,15 @@ u32 ssb_admatch_size(u32 adm)  		size = ((adm & SSB_ADM_SZ0) >> SSB_ADM_SZ0_SHIFT);  		break;  	case SSB_ADM_TYPE1: -		assert(!(adm & SSB_ADM_NEG)); /* unsupported */ +		SSB_WARN_ON(adm & SSB_ADM_NEG); /* unsupported */  		size = ((adm & SSB_ADM_SZ1) >> SSB_ADM_SZ1_SHIFT);  		break;  	case SSB_ADM_TYPE2: -		assert(!(adm & SSB_ADM_NEG)); /* unsupported */ +		SSB_WARN_ON(adm & SSB_ADM_NEG); /* unsupported */  		size = ((adm & SSB_ADM_SZ2) >> SSB_ADM_SZ2_SHIFT);  		break;  	default: -		assert(0); +		SSB_WARN_ON(1);  	}  	size = (1 << (size + 1)); @@ -1037,7 +1127,8 @@ static int __init ssb_modinit(void)  {  	int err; -	ssb_bustype.name = "ssb"; +	/* See the comment at the ssb_is_early_boot definition */ +	ssb_is_early_boot = 0;  	err = bus_register(&ssb_bustype);  	if (err)  		return err; @@ -1051,12 +1142,21 @@ static int __init ssb_modinit(void)  	if (err)  		bus_unregister(&ssb_bustype); +	err = b43_pci_ssb_bridge_init(); +	if (err) { +		ssb_printk(KERN_ERR "Broadcom 43xx PCI-SSB-bridge " +			   "initialization failed"); +		/* don't fail SSB init because of this */ +		err = 0; +	} +  	return err;  }  subsys_initcall(ssb_modinit);  static void __exit ssb_modexit(void)  { +	b43_pci_ssb_bridge_exit();  	bus_unregister(&ssb_bustype);  }  module_exit(ssb_modexit) diff --git a/target/linux/generic-2.6/files/drivers/ssb/pci.c b/target/linux/generic-2.6/files/drivers/ssb/pci.c index f9dc28f51..0ab095c65 100644 --- a/target/linux/generic-2.6/files/drivers/ssb/pci.c +++ b/target/linux/generic-2.6/files/drivers/ssb/pci.c @@ -23,6 +23,11 @@  #include "ssb_private.h" +/* Define the following to 1 to enable a printk on each coreswitch. */ +#define SSB_VERBOSE_PCICORESWITCH_DEBUG		0 + + +/* Lowlevel coreswitching */  int ssb_pci_switch_coreidx(struct ssb_bus *bus, u8 coreidx)  {  	int err; @@ -60,10 +65,12 @@ int ssb_pci_switch_core(struct ssb_bus *bus,  	int err;  	unsigned long flags; -	ssb_dprintk(KERN_INFO PFX -		    "Switching to %s core, index %d\n", -		    ssb_core_name(dev->id.coreid), -		    dev->core_index); +#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); +#endif  	spin_lock_irqsave(&bus->bar_lock, flags);  	err = ssb_pci_switch_coreidx(bus, dev->core_index); @@ -74,6 +81,7 @@ int ssb_pci_switch_core(struct ssb_bus *bus,  	return err;  } +/* Enable/disable the on board crystal oscillator and/or PLL. */  int ssb_pci_xtal(struct ssb_bus *bus, u32 what, int turn_on)  {  	int err; @@ -158,7 +166,9 @@ err_pci:  	goto out;  } +/* Get the word-offset for a SSB_SPROM_XXX define. */  #define SPOFF(offset)	(((offset) - SSB_SPROM_BASE) / sizeof(u16)) +/* Helper to extract some _offset, which is one of the SSB_SPROM_XXX defines. */  #define SPEX(_outvar, _offset, _mask, _shift)	\  	out->_outvar = ((in[SPOFF(_offset)] & (_mask)) >> (_shift)) @@ -296,15 +306,15 @@ static void sprom_extract_r1(struct ssb_sprom_r1 *out, const u16 *in)  	SPEX(pci_pid, SSB_SPROM1_PID, 0xFFFF, 0);  	for (i = 0; i < 3; i++) {  		v = in[SPOFF(SSB_SPROM1_IL0MAC) + i]; -		*(((u16 *)out->il0mac) + i) = cpu_to_be16(v); +		*(((__be16 *)out->il0mac) + i) = cpu_to_be16(v);  	}  	for (i = 0; i < 3; i++) {  		v = in[SPOFF(SSB_SPROM1_ET0MAC) + i]; -		*(((u16 *)out->et0mac) + i) = cpu_to_be16(v); +		*(((__be16 *)out->et0mac) + i) = cpu_to_be16(v);  	}  	for (i = 0; i < 3; i++) {  		v = in[SPOFF(SSB_SPROM1_ET1MAC) + i]; -		*(((u16 *)out->et1mac) + i) = cpu_to_be16(v); +		*(((__be16 *)out->et1mac) + i) = cpu_to_be16(v);  	}  	SPEX(et0phyaddr, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET0A, 0);  	SPEX(et1phyaddr, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET1A, @@ -342,7 +352,7 @@ static void sprom_extract_r1(struct ssb_sprom_r1 *out, const u16 *in)  	     SSB_SPROM1_AGAIN_BG_SHIFT);  	for (i = 0; i < 4; i++) {  		v = in[SPOFF(SSB_SPROM1_OEM) + i]; -		*(((u16 *)out->oem) + i) = cpu_to_le16(v); +		*(((__le16 *)out->oem) + i) = cpu_to_le16(v);  	}  } @@ -364,7 +374,7 @@ static void sprom_extract_r2(struct ssb_sprom_r2 *out, const u16 *in)  	SPEX(ofdm_pwr_off, SSB_SPROM2_OPO, SSB_SPROM2_OPO_VALUE, 0);  	for (i = 0; i < 4; i++) {  		v = in[SPOFF(SSB_SPROM2_CCODE) + i]; -		*(((u16 *)out->country_str) + i) = cpu_to_le16(v); +		*(((__le16 *)out->country_str) + i) = cpu_to_le16(v);  	}  } @@ -489,50 +499,81 @@ out:  	return err;  } +#ifdef CONFIG_SSB_DEBUG +static int ssb_pci_assert_buspower(struct ssb_bus *bus) +{ +	if (likely(bus->powered_up)) +		return 0; + +	printk(KERN_ERR PFX "FATAL ERROR: Bus powered down " +	       "while accessing PCI MMIO space\n"); +	if (bus->power_warn_count <= 10) { +		bus->power_warn_count++; +		dump_stack(); +	} + +	return -ENODEV; +} +#else /* DEBUG */ +static inline int ssb_pci_assert_buspower(struct ssb_bus *bus) +{ +	return 0; +} +#endif /* DEBUG */ +  static u16 ssb_pci_read16(struct ssb_device *dev, u16 offset)  {  	struct ssb_bus *bus = dev->bus; +	if (unlikely(ssb_pci_assert_buspower(bus))) +		return 0xFFFF;  	if (unlikely(bus->mapped_device != dev)) {  		if (unlikely(ssb_pci_switch_core(bus, dev)))  			return 0xFFFF;  	} -	return readw(bus->mmio + offset); +	return ioread16(bus->mmio + offset);  }  static u32 ssb_pci_read32(struct ssb_device *dev, u16 offset)  {  	struct ssb_bus *bus = dev->bus; +	if (unlikely(ssb_pci_assert_buspower(bus))) +		return 0xFFFFFFFF;  	if (unlikely(bus->mapped_device != dev)) {  		if (unlikely(ssb_pci_switch_core(bus, dev)))  			return 0xFFFFFFFF;  	} -	return readl(bus->mmio + offset); +	return ioread32(bus->mmio + offset);  }  static void ssb_pci_write16(struct ssb_device *dev, u16 offset, u16 value)  {  	struct ssb_bus *bus = dev->bus; +	if (unlikely(ssb_pci_assert_buspower(bus))) +		return;  	if (unlikely(bus->mapped_device != dev)) {  		if (unlikely(ssb_pci_switch_core(bus, dev)))  			return;  	} -	writew(value, bus->mmio + offset); +	iowrite16(value, bus->mmio + offset);  }  static void ssb_pci_write32(struct ssb_device *dev, u16 offset, u32 value)  {  	struct ssb_bus *bus = dev->bus; +	if (unlikely(ssb_pci_assert_buspower(bus))) +		return;  	if (unlikely(bus->mapped_device != dev)) {  		if (unlikely(ssb_pci_switch_core(bus, dev)))  			return;  	} -	writel(value, bus->mmio + offset); +	iowrite32(value, bus->mmio + offset);  } +/* Not "static", as it's used in main.c */  const struct ssb_bus_ops ssb_pci_ops = {  	.read16		= ssb_pci_read16,  	.read32		= ssb_pci_read32, @@ -590,6 +631,9 @@ static ssize_t ssb_pci_attr_sprom_show(struct device *pcidev,  	if (!sprom)  		goto out; +	/* Use interruptible locking, as the SPROM write might +	 * be holding the lock for several seconds. So allow userspace +	 * to cancel operation. */  	err = -ERESTARTSYS;  	if (mutex_lock_interruptible(&bus->pci_sprom_mutex))  		goto out_kfree; @@ -632,10 +676,18 @@ static ssize_t ssb_pci_attr_sprom_store(struct device *pcidev,  		goto out_kfree;  	} +	/* Use interruptible locking, as the SPROM write might +	 * be holding the lock for several seconds. So allow userspace +	 * to cancel operation. */  	err = -ERESTARTSYS;  	if (mutex_lock_interruptible(&bus->pci_sprom_mutex))  		goto out_kfree;  	err = ssb_devices_freeze(bus); +	if (err == -EOPNOTSUPP) { +		ssb_printk(KERN_ERR PFX "SPROM write: Could not freeze devices. " +			   "No suspend support. Is CONFIG_PM enabled?\n"); +		goto out_unlock; +	}  	if (err) {  		ssb_printk(KERN_ERR PFX "SPROM write: Could not freeze all devices\n");  		goto out_unlock; diff --git a/target/linux/generic-2.6/files/drivers/ssb/pcmcia.c b/target/linux/generic-2.6/files/drivers/ssb/pcmcia.c index b9085633e..7c773603b 100644 --- a/target/linux/generic-2.6/files/drivers/ssb/pcmcia.c +++ b/target/linux/generic-2.6/files/drivers/ssb/pcmcia.c @@ -21,6 +21,10 @@  #include "ssb_private.h" +/* Define the following to 1 to enable a printk on each coreswitch. */ +#define SSB_VERBOSE_PCMCIACORESWITCH_DEBUG		0 + +  int ssb_pcmcia_switch_coreidx(struct ssb_bus *bus,  			      u8 coreidx)  { @@ -91,10 +95,12 @@ int ssb_pcmcia_switch_core(struct ssb_bus *bus,  	int err;  	unsigned long flags; -	ssb_dprintk(KERN_INFO PFX -		    "Switching to %s core, index %d\n", -		    ssb_core_name(dev->id.coreid), -		    dev->core_index); +#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); +#endif  	spin_lock_irqsave(&bus->bar_lock, flags);  	err = ssb_pcmcia_switch_coreidx(bus, dev->core_index); @@ -112,7 +118,7 @@ int ssb_pcmcia_switch_segment(struct ssb_bus *bus, u8 seg)  	conf_reg_t reg;  	int res, err = 0; -	assert(seg == 0 || seg == 1); +	SSB_WARN_ON((seg != 0) && (seg != 1));  	reg.Offset = 0x34;  	reg.Function = 0;  	spin_lock_irqsave(&bus->bar_lock, flags); @@ -145,6 +151,9 @@ error:  	goto out_unlock;  } +/* These are the main device register access functions. + * do_select_core is inline to have the likely hotpath inline. + * All unlikely codepaths are out-of-line. */  static inline int do_select_core(struct ssb_bus *bus,  				 struct ssb_device *dev,  				 u16 *offset) @@ -176,7 +185,7 @@ static u16 ssb_pcmcia_read16(struct ssb_device *dev, u16 offset)  	if (unlikely(do_select_core(bus, dev, &offset)))  		return 0xFFFF;  	x = readw(bus->mmio + offset); -//printk("R16 0x%04X, 0x%04X\n", offset, x); +  	return x;  } @@ -188,7 +197,7 @@ static u32 ssb_pcmcia_read32(struct ssb_device *dev, u16 offset)  	if (unlikely(do_select_core(bus, dev, &offset)))  		return 0xFFFFFFFF;  	x = readl(bus->mmio + offset); -//printk("R32 0x%04X, 0x%08X\n", offset, x); +  	return x;  } @@ -198,7 +207,6 @@ static void ssb_pcmcia_write16(struct ssb_device *dev, u16 offset, u16 value)  	if (unlikely(do_select_core(bus, dev, &offset)))  		return; -//printk("W16 0x%04X, 0x%04X\n", offset, value);  	writew(value, bus->mmio + offset);  } @@ -208,13 +216,13 @@ static void ssb_pcmcia_write32(struct ssb_device *dev, u16 offset, u32 value)  	if (unlikely(do_select_core(bus, dev, &offset)))  		return; -//printk("W32 0x%04X, 0x%08X\n", offset, value);  	readw(bus->mmio + offset);  	writew(value >> 16, bus->mmio + offset + 2);  	readw(bus->mmio + offset);  	writew(value, bus->mmio + offset);  } +/* Not "static", as it's used in main.c */  const struct ssb_bus_ops ssb_pcmcia_ops = {  	.read16		= ssb_pcmcia_read16,  	.read32		= ssb_pcmcia_read32, diff --git a/target/linux/generic-2.6/files/drivers/ssb/scan.c b/target/linux/generic-2.6/files/drivers/ssb/scan.c index b5d909c3a..96258c609 100644 --- a/target/linux/generic-2.6/files/drivers/ssb/scan.c +++ b/target/linux/generic-2.6/files/drivers/ssb/scan.c @@ -15,19 +15,17 @@  #include <linux/ssb/ssb.h>  #include <linux/ssb/ssb_regs.h>  #include <linux/pci.h> -#include <asm/io.h> +#include <linux/io.h> -#ifdef CONFIG_SSB_PCMCIAHOST -# include <pcmcia/cs_types.h> -# include <pcmcia/cs.h> -# include <pcmcia/cistpl.h> -# include <pcmcia/ds.h> -#endif +#include <pcmcia/cs_types.h> +#include <pcmcia/cs.h> +#include <pcmcia/cistpl.h> +#include <pcmcia/ds.h>  #include "ssb_private.h" -const char * ssb_core_name(u16 coreid) +const char *ssb_core_name(u16 coreid)  {  	switch (coreid) {  	case SSB_DEV_CHIPCOMMON: @@ -205,7 +203,7 @@ void ssb_iounmap(struct ssb_bus *bus)  #ifdef CONFIG_SSB_PCIHOST  		pci_iounmap(bus->host_pci, bus->mmio);  #else -		assert(0); /* Can't reach this code. */ +		SSB_BUG_ON(1); /* Can't reach this code. */  #endif  		break;  	} @@ -213,8 +211,8 @@ void ssb_iounmap(struct ssb_bus *bus)  	bus->mapped_device = NULL;  } -static void __iomem * ssb_ioremap(struct ssb_bus *bus, -				  unsigned long baseaddr) +static void __iomem *ssb_ioremap(struct ssb_bus *bus, +				 unsigned long baseaddr)  {  	void __iomem *mmio = NULL; @@ -229,7 +227,7 @@ static void __iomem * ssb_ioremap(struct ssb_bus *bus,  #ifdef CONFIG_SSB_PCIHOST  		mmio = pci_iomap(bus->host_pci, 0, ~0UL);  #else -		assert(0); /* Can't reach this code. */ +		SSB_BUG_ON(1); /* Can't reach this code. */  #endif  		break;  	} diff --git a/target/linux/generic-2.6/files/drivers/ssb/ssb_private.h b/target/linux/generic-2.6/files/drivers/ssb/ssb_private.h index d00d18607..a78936426 100644 --- a/target/linux/generic-2.6/files/drivers/ssb/ssb_private.h +++ b/target/linux/generic-2.6/files/drivers/ssb/ssb_private.h @@ -3,7 +3,6 @@  #include <linux/ssb/ssb.h>  #include <linux/types.h> -#include <asm/io.h>  #define PFX	"ssb: " @@ -16,32 +15,20 @@  /* dprintk: Debugging printk; vanishes for non-debug compilation */  #ifdef CONFIG_SSB_DEBUG -# define ssb_dprintk(fmt, x...)	ssb_printk(fmt ,##x) +# define ssb_dprintk(fmt, x...)	ssb_printk(fmt , ##x)  #else  # define ssb_dprintk(fmt, x...)	do { /* nothing */ } while (0)  #endif -/* printkl: Rate limited printk */ -#define ssb_printkl(fmt, x...)	do {		\ -	if (printk_ratelimit())			\ -		ssb_printk(fmt ,##x);		\ -				} while (0) - -/* dprintkl: Rate limited debugging printk */  #ifdef CONFIG_SSB_DEBUG -# define ssb_dprintkl			ssb_printkl +# define SSB_WARN_ON(x)		WARN_ON(x) +# define SSB_BUG_ON(x)		BUG_ON(x)  #else -# define ssb_dprintkl(fmt, x...)	do { /* nothing */ } while (0) +static inline int __ssb_do_nothing(int x) { return x; } +# define SSB_WARN_ON(x)		__ssb_do_nothing(unlikely(!!(x))) +# define SSB_BUG_ON(x)		__ssb_do_nothing(unlikely(!!(x)))  #endif -#define assert(cond)	do {						\ -	if (unlikely(!(cond))) {					\ -		ssb_dprintk(KERN_ERR PFX "BUG: Assertion failed (%s) "	\ -			    "at: %s:%d:%s()\n",				\ -			    #cond, __FILE__, __LINE__, __func__);	\ -	}								\ -		       } while (0) -  /* pci.c */  #ifdef CONFIG_SSB_PCIHOST @@ -120,7 +107,7 @@ static inline int ssb_pcmcia_init(struct ssb_bus *bus)  /* scan.c */ -extern const char * ssb_core_name(u16 coreid); +extern const char *ssb_core_name(u16 coreid);  extern int ssb_bus_scan(struct ssb_bus *bus,  			unsigned long baseaddr);  extern void ssb_iounmap(struct ssb_bus *ssb); @@ -128,10 +115,22 @@ extern void ssb_iounmap(struct ssb_bus *ssb);  /* core.c */  extern u32 ssb_calc_clock_rate(u32 plltype, u32 n, u32 m); -#ifdef CONFIG_SSB_PCIHOST  extern int ssb_devices_freeze(struct ssb_bus *bus);  extern int ssb_devices_thaw(struct ssb_bus *bus); -extern struct ssb_bus * ssb_pci_dev_to_bus(struct pci_dev *pdev); +extern struct ssb_bus *ssb_pci_dev_to_bus(struct pci_dev *pdev); + +/* b43_pci_bridge.c */ +#ifdef CONFIG_SSB_PCIHOST +extern int __init b43_pci_ssb_bridge_init(void); +extern void __exit b43_pci_ssb_bridge_exit(void); +#else /* CONFIG_SSB_PCIHOST */ +static inline int b43_pci_ssb_bridge_init(void) +{ +	return 0; +} +static inline void b43_pci_ssb_bridge_exit(void) +{ +}  #endif /* CONFIG_SSB_PCIHOST */  #endif /* LINUX_SSB_PRIVATE_H_ */ | 
