Beispiel #1
0
/*
 * Interface to register chipc secondary isr
 */
bool
BCMINITFN(sb_cc_register_isr) (sb_t * sbh, cc_isr_fn isr, uint32 ccintmask,
			       void *cbdata) {
	bool done = FALSE;
	chipcregs_t *regs;
	uint origidx;
	uint i;

	/* Save the current core index */
	origidx = sb_coreidx(sbh);
	regs = sb_setcore(sbh, SB_CC, 0);
	ASSERT(regs);

	for (i = 0; i < MAX_CC_INT_SOURCE; i++) {
		if (cc_isr_desc[i].isr == NULL) {
			cc_isr_desc[i].isr = isr;
			cc_isr_desc[i].cbdata = cbdata;
			cc_isr_desc[i].intmask = ccintmask;
			done = TRUE;
			break;
		}
	}

	if (done) {
		cc_intmask = R_REG(sb_osh(sbh), &regs->intmask);
		cc_intmask |= ccintmask;
		W_REG(sb_osh(sbh), &regs->intmask, cc_intmask);
	}

	/* restore original coreidx */
	sb_setcoreidx(sbh, origidx);
	return done;
}
Beispiel #2
0
static uint32
config_cmd(sb_t *sbh, uint bus, uint dev, uint func, uint off)
{
	uint coreidx;
	sbpciregs_t *regs;
	uint32 addr = 0;

	/* CardBusMode supports only one device */
	if (cardbus && dev > 1)
		return 0;

	coreidx = sb_coreidx(sbh);
	regs = (sbpciregs_t *) sb_setcore(sbh, SB_PCI, 0);

	/* Type 0 transaction */
	if (bus == 1) {
		/* Skip unwired slots */
		if (dev < PCI_SLOT_MAX) {
			/* Slide the PCI window to the appropriate slot */
			W_REG(&regs->sbtopci1, SBTOPCI_CFG0 | ((1 << (dev + 16)) & SBTOPCI1_MASK));
			addr = SB_PCI_CFG | ((1 << (dev + 16)) & ~SBTOPCI1_MASK) |
				(func << 8) | (off & ~3);
		}
	}

	/* Type 1 transaction */
	else {
		W_REG(&regs->sbtopci1, SBTOPCI_CFG1);
		addr = SB_PCI_CFG | (bus << 16) | (dev << 11) | (func << 8) | (off & ~3);
	}

	sb_setcoreidx(sbh, coreidx);

	return addr;
}
Beispiel #3
0
static int
sb_write_config(sb_t *sbh, uint bus, uint dev, uint func, uint off, void *buf, int len)
{
	uint coreidx, n;
	void *regs;
	sbconfig_t *sb;
	pci_config_regs *cfg;

	if (dev >= SB_MAXCORES || (off + len) > sizeof(pci_config_regs))
		return -1;
	cfg = &sb_config_regs[dev];

	ASSERT(ISALIGNED(off, len));
	ASSERT(ISALIGNED((uintptr)buf, len));

	/* Emulate BAR sizing */
	if (off >= OFFSETOF(pci_config_regs, base[0]) && off <= OFFSETOF(pci_config_regs, base[3]) &&
	    len == 4 && *((uint32 *) buf) == ~0) {
		coreidx = sb_coreidx(sbh);
		if ((regs = sb_setcoreidx(sbh, dev))) {
			sb = (sbconfig_t *)((ulong) regs + SBCONFIGOFF);
			/* Highest numbered address match register */
			n = (R_REG(&sb->sbidlow) & SBIDL_AR_MASK) >> SBIDL_AR_SHIFT;
			if (off == OFFSETOF(pci_config_regs, base[0]))
				cfg->base[0] = ~(sb_size(R_REG(&sb->sbadmatch0)) - 1);
			else if (off == OFFSETOF(pci_config_regs, base[1]) && n >= 1)
				cfg->base[1] = ~(sb_size(R_REG(&sb->sbadmatch1)) - 1);
			else if (off == OFFSETOF(pci_config_regs, base[2]) && n >= 2)
				cfg->base[2] = ~(sb_size(R_REG(&sb->sbadmatch2)) - 1);
			else if (off == OFFSETOF(pci_config_regs, base[3]) && n >= 3)
				cfg->base[3] = ~(sb_size(R_REG(&sb->sbadmatch3)) - 1);
		}
Beispiel #4
0
static void __init pcibios_fixup_resources(struct pci_dev *dev)
{
	ulong flags;
	uint coreidx;

	if (dev->bus->number == 0) {

		/*
		 * Chipcommon, RAM controller and PCI bridge must not be reset!
		 */
		if (dev->device == SB_MIPS ||
		    dev->device == SB_MIPS33 ||
		    dev->device == SB_EXTIF ||
		    dev->device == SB_MEMC ||
		    dev->device == SB_PCI || dev->device == SB_CC)
			return;

		spin_lock_irqsave(&sbh_lock, flags);
		coreidx = sb_coreidx(sbh);
		if (!sb_setcoreidx(sbh, PCI_SLOT(dev->devfn)))
			return;

		/*
		 * The USB core requires a special bit to be set during core
		 * reset to enable host (OHCI) mode. Resetting the SB core here
		 * is a hack for compatibility with vanilla usb-ohci so that it
		 * does not have to know about SB.  A driver that wants to  use
		 * the  USB core in device mode should know about SB and should
		 * reset the bit back to 0.
		 */
		if (sb_coreid(sbh) == SB_USB) {
			sb_core_disable(sbh, sb_coreflags(sbh, 0, 0));
			sb_core_reset(sbh, 1 << 29);
		} else
			sb_core_reset(sbh, 0);

		sb_setcoreidx(sbh, coreidx);
		spin_unlock_irqrestore(&sbh_lock, flags);

		return;
	}

	if (dev->bus->number != 1 || PCI_SLOT(dev->devfn) != 0)
		return;

	printk("PCI: Fixing up bridge\n");

	/* Enable PCI bridge bus mastering */
	pci_set_master(dev);

	/* Enable PCI bridge BAR1 prefetch and burst */
	pci_write_config_dword(dev, PCI_BAR1_CONTROL, 0x3);
}
Beispiel #5
0
static uint32
config_cmd(sb_t *sbh, uint bus, uint dev, uint func, uint off)
{
	uint coreidx;
	sbpciregs_t *regs;
	uint32 addr = 0;
	osl_t *osh;

	/* CardBusMode supports only one device */
	if (cardbus && dev > 1)
		return 0;

	osh = sb_osh(sbh);

	coreidx = sb_coreidx(sbh);
	regs = (sbpciregs_t *) sb_setcore(sbh, SB_PCI, 0);

	/* Type 0 transaction */
	if (bus == 1) {
		/* Skip unwired slots */
		if (dev < PCI_SLOT_MAX) {
			uint32 win;

			/* Slide the PCI window to the appropriate slot */
			win = (SBTOPCI_CFG0 | ((1 << (dev + PCI_SLOTAD_MAP)) & SBTOPCI1_MASK));
			W_REG(osh, &regs->sbtopci1, win);
			addr = SB_PCI_CFG |
			        ((1 << (dev + PCI_SLOTAD_MAP)) & ~SBTOPCI1_MASK) |
			        (func << PCICFG_FUN_SHIFT) |
			        (off & ~3);
		}
	} else {
		/* Type 1 transaction */
		W_REG(osh, &regs->sbtopci1, SBTOPCI_CFG1);
		addr = SB_PCI_CFG |
		        (bus << PCICFG_BUS_SHIFT) |
		        (dev << PCICFG_SLOT_SHIFT) |
		        (func << PCICFG_FUN_SHIFT) |
		        (off & ~3);
	}

	sb_setcoreidx(sbh, coreidx);

	return addr;
}
Beispiel #6
0
/* get gpio registers base addr */
static uint32* get_gpio_base_addr(void) {
        sb_info_t *si;
	uint origidx;
	uint32 *addr = NULL;
	uint intr_val = 0;
	
        si = SB_INFO(sbh);

	INTR_OFF(si, intr_val);

	/* save current core index */
        origidx = sb_coreidx(sbh);

	addr = (uint32*) sb_setcoreidx(sbh, si->gpioidx);

	/* restore core index */
        if (origidx != si->gpioidx) sb_setcoreidx(sbh, origidx);

        INTR_RESTORE(si, intr_val);

	return addr;
}
Beispiel #7
0
static bool
nvram_reset(void *sbh)
{
	chipcregs_t *cc;
	char *value;
	uint32 watchdog = 0, gpio;
	uint idx, msec;

	idx = sb_coreidx(sbh);

	/* Check if we were soft reset */
	if ((cc = sb_setcore(sbh, SB_CC, 0))) {
		watchdog = R_REG(&cc->intstatus) & 0x80000000;
		sb_setcoreidx(sbh, idx);
	}
	if (watchdog)
		return FALSE;

	value = nvram_get("reset_gpio");
	if (!value)
		return FALSE;

	gpio = (uint32) bcm_atoi(value);
	if (gpio > 7)
		return FALSE;

	/* Setup GPIO input */
	sb_gpioouten(sbh, (1 << gpio), 0);

	/* GPIO reset is asserted low */
	for (msec = 0; msec < 5000; msec++) {
		if (sb_gpioin(sbh) & (1 << gpio))
			return FALSE;
		OSL_DELAY(1000);
	}

	return TRUE;
}
int 
BCMINITFN(nvram_init)(void *sbh)
{
	uint idx;
	bool isemb;
	int ret;


	idx = sb_coreidx(sbh);
	if (sb_setcore(sbh, SB_CC, 0) != NULL) {
		flash_base = SB_FLASH2;
		sb_setcoreidx(sbh, idx);
	} else
		flash_base = SB_FLASH1;

	/* Temporarily initialize with embedded NVRAM */
	nvram_header = BCMINIT(find_nvram)(TRUE, &isemb);
	ret = BCMINIT(_nvram_init)();
	if (ret == 0) {
		/* Restore defaults from embedded NVRAM if button held down */
		if (BCMINIT(nvram_reset)(sbh)) {
			return 1;
		}

		BCMINIT(_nvram_exit)();
	}

	/* Find NVRAM */
	nvram_header = BCMINIT(find_nvram)(FALSE, &isemb);
	ret = BCMINIT(_nvram_init)();
	if (ret == 0) {
		/* Restore defaults if embedded NVRAM used */
		if (nvram_header && isemb) {
			ret = 1;
		}
	}
	return ret;
}
Beispiel #9
0
/*
 * Read host bridge PCI config registers from Silicon Backplane (>=rev8).
 *
 * It returns TRUE to indicate that access to the host bridge's pci config
 * from SB is ok, and values in 'addr' and 'val' are valid.
 *
 * It can only read registers at multiple of 4-bytes. Callers must pick up
 * needed bytes from 'val' based on 'off' value. Value in 'addr' reflects
 * the register address where value in 'val' is read.
 */
static bool
sb_pcihb_read_config(sb_t *sbh, uint bus, uint dev, uint func, uint off,
                  uint32 **addr, uint32 *val)
{
	sbpciregs_t *regs;
	osl_t *osh;
	uint coreidx;
	bool ret = FALSE;

	/* sanity check */
	ASSERT(bus == 1);
	ASSERT(dev == pci_hbslot);
	ASSERT(func == 0);

	osh = sb_osh(sbh);

	/* read pci config when core rev >= 8 */
	coreidx = sb_coreidx(sbh);
	regs = (sbpciregs_t *)sb_setcore(sbh, SB_PCI, 0);
	if (regs && sb_corerev(sbh) >= PCI_HBSBCFG_REV) {
		*addr = (uint32 *)&regs->pcicfg[func][off >> 2];
		*val = R_REG(osh, *addr);
		ret = TRUE;
	}
Beispiel #10
0
/*
 * Setup the gige core.
 * Resetting the core will lose all settings.
 */
void
sb_gige_init(sb_t *sbh, uint32 unit, bool *rgmii)
{
	volatile pci_config_regs *pci;
	sbgige_pcishim_t *ocp;
	sbconfig_t *sb;
	osl_t *osh;
	uint32 statelow;
	uint32 statehigh;
	uint32 base;
	uint32 idx;
	void *regs;

	/* Sanity checks */
	ASSERT(sbh);
	ASSERT(rgmii);

	idx = sb_coreidx(sbh);

	/* point to the gige core registers */
	regs = sb_setcore(sbh, SB_GIGETH, unit);
	ASSERT(regs);

	osh = sb_osh(sbh);

	pci = &((sbgige_t *)regs)->pcicfg;
	ocp = &((sbgige_t *)regs)->pcishim;
	sb = &((sbgige_t *)regs)->sbconfig;

	/* Enable the core clock and memory access */
	if (!sb_iscoreup(sbh))
		sb_core_reset(sbh, 0, 0);

	/*
	 * Setup the 64K memory-mapped region base address through BAR0.
	 * Leave the other BAR values alone.
	 */
	base = sb_base(R_REG(osh, &sb->sbadmatch1));
	W_REG(osh, &pci->base[0], base);
	W_REG(osh, &pci->base[1], 0);

	/*
	 * Enable the PCI memory access anyway. Any PCI config commands
	 * issued before the core is enabled will go to the emulation
	 * only and will not go to the real PCI config registers.
	 */
	OR_REG(osh, &pci->command, 2);

	/*
	 * Enable the posted write flush scheme as follows:
	 *
	 * - Enable flush on any core register read
	 * - Enable timeout on the flush
	 * - Disable the interrupt mask when flushing
	 *
	 * This differs from the default setting only in that interrupts are
	 * not masked.  Since posted writes are not flushed on interrupt, the
	 * driver must explicitly request a flush in its interrupt handling
	 * by reading a core register.
	 */
	W_REG(osh, &ocp->FlushStatusControl, 0x68);

	/*
	 * Determine whether the GbE is in GMII or RGMII mode.  This is
	 * indicated in bit 16 of the SBTMStateHigh register, which is
	 * part of the core-specific flags field.
	 *
	 * For GMII, bypass the Rx/Tx DLLs, i.e. add no delay to RXC/GTXC
	 * within the core.  For RGMII, do not bypass the DLLs, resulting
	 * in added delay for RXC/GTXC.  The SBTMStateLow register contains
	 * the controls for doing this in the core-specific flags field:
	 *
	 *   bit 24 - Enable DLL controls
	 *   bit 20 - Bypass Rx DLL
	 *   bit 19 - Bypass Tx DLL
	 */
	statelow = R_REG(osh, &sb->sbtmstatelow);	/* DLL controls */
	statehigh = R_REG(osh, &sb->sbtmstatehigh);	/* GMII/RGMII mode */
	if ((statehigh & (1 << 16)) != 0)	/* RGMII */
	{
		statelow &= ~(1 << 20);		/* no Rx bypass (delay) */
		statelow &= ~(1 << 19);		/* no Tx bypass (delay) */
		*rgmii = TRUE;
	}
	else					/* GMII */
	{
		statelow |= (1 << 20);		/* Rx bypass (no delay) */
		statelow |= (1 << 19);		/* Tx bypass (no delay) */
		*rgmii = FALSE;
	}
	statelow |= (1 << 24);			/* enable DLL controls */
	W_REG(osh, &sb->sbtmstatelow, statelow);

	sb_setcoreidx(sbh, idx);
}
Beispiel #11
0
int
pcibios_enable_device(struct pci_dev *dev, int mask)
{
	ulong flags;
	uint coreidx;
	void *regs;

	/* External PCI device enable */
	if (dev->bus->number != 0)
		return pcibios_enable_resources(dev);

	/* These cores come out of reset enabled */
	if (dev->device == SB_MIPS ||
	    dev->device == SB_MIPS33 ||
	    dev->device == SB_EXTIF ||
	    dev->device == SB_CC)
		return 0;

	spin_lock_irqsave(&sbh_lock, flags);
	coreidx = sb_coreidx(sbh);
	regs = sb_setcoreidx(sbh, PCI_SLOT(dev->devfn));
	if (!regs)
		return PCIBIOS_DEVICE_NOT_FOUND;

	/* 
	 * The USB core requires a special bit to be set during core
	 * reset to enable host (OHCI) mode. Resetting the SB core in
	 * pcibios_enable_device() is a hack for compatibility with
	 * vanilla usb-ohci so that it does not have to know about
	 * SB. A driver that wants to use the USB core in device mode
	 * should know about SB and should reset the bit back to 0
	 * after calling pcibios_enable_device().
	 */
	if (sb_coreid(sbh) == SB_USB) {
		sb_core_disable(sbh, sb_coreflags(sbh, 0, 0));
		sb_core_reset(sbh, 1 << 29, 0);
	}
	/*
	 * USB 2.0 special considerations:
	 *
	 * 1. Since the core supports both OHCI and EHCI functions, it must
	 *    only be reset once.
	 *
	 * 2. In addition to the standard SB reset sequence, the Host Control
	 *    Register must be programmed to bring the USB core and various
	 *    phy components out of reset.
	 */
	else if (sb_coreid(sbh) == SB_USB20H) {
		if (!sb_iscoreup(sbh)) {
			sb_core_reset(sbh, 0, 0);
			writel(0x7FF, (ulong)regs + 0x200);
			udelay(1);
		}
	} else
		sb_core_reset(sbh, 0, 0);

	sb_setcoreidx(sbh, coreidx);
	spin_unlock_irqrestore(&sbh_lock, flags);

	return 0;
}