Пример #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;
}
Пример #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;
}
Пример #3
0
void __init bcm947xx_time_init(void)
{
	unsigned int hz;
	extifregs_t *eir;

	/*
	 * Use deterministic values for initial counter interrupt
	 * so that calibrate delay avoids encountering a counter wrap.
	 */
	write_c0_count(0);
	write_c0_compare(0xffff);

	if (!(hz = sb_mips_clock(sbh)))
		hz = 100000000;

#if defined(CONFIG_BCM94702_CPCI) || defined(CONFIG_BCM94704_CPCI)
	/* Init RTC */

	rtc17xx_tod_init();
	rtc17xx_tod_print();
	/* Use RTC from local bus */
	rtc_get_time = rtc17xx_get_time;
	rtc_set_time = rtc17xx_set_time;
#endif
	printk("CPU: BCM%04x rev %d at %d MHz\n", sb_chip(sbh),
	       sb_chiprev(sbh), (hz + 500000) / 1000000);

	/* Set MIPS counter frequency for fixed_rate_gettimeoffset() */
	mips_hpt_frequency = hz / 2;

	/* Set watchdog interval in ms */
	watchdog = simple_strtoul(nvram_safe_get("watchdog"), NULL, 0);

	/* Set panic timeout in seconds */
	panic_timeout = watchdog / 1000;

	/* Setup blink */
	if ((eir = sb_setcore(sbh, SB_EXTIF, 0))) {
		sbconfig_t *sb =
		    (sbconfig_t *) ((unsigned int) eir + SBCONFIGOFF);
		unsigned long base =
		    EXTIF_CFGIF_BASE(sb_base
				     (readl((void *) (&sb->sbadmatch1))));
		mcr = (u8 *) ioremap_nocache(base + UART_MCR, 1);
	}
}
Пример #4
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;
}
Пример #5
0
/*
 * Initialize jtag master and return handle for
 * jtag_rwreg. Returns NULL on failure.
 */
void *sb_jtagm_init(sb_t * sbh, uint clkd, bool exttap)
{
	void *regs;

	if ((regs = sb_setcore(sbh, SB_CC, 0)) != NULL) {
		chipcregs_t *cc = (chipcregs_t *) regs;
		uint32 tmp;

		/*
		 * Determine jtagm availability from
		 * core revision and capabilities.
		 */

		/*
		 * Corerev 10 has jtagm, but the only chip
		 * with it does not have a mips, and
		 * the layout of the jtagcmd register is
		 * different. We'll only accept >= 11.
		 */
		if (sbh->ccrev < 11)
			return (NULL);

		if ((sbh->cccaps & CC_CAP_JTAGP) == 0)
			return (NULL);

		/* Set clock divider if requested */
		if (clkd != 0) {
			tmp = R_REG(osh, &cc->clkdiv);
			tmp =
			    (tmp & ~CLKD_JTAG) | ((clkd << CLKD_JTAG_SHIFT) &
						  CLKD_JTAG);
			W_REG(osh, &cc->clkdiv, tmp);
		}

		/* Enable jtagm */
		tmp = JCTRL_EN | (exttap ? JCTRL_EXT_EN : 0);
		W_REG(osh, &cc->jtagctrl, tmp);
	}

	return (regs);
}
Пример #6
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;
}
Пример #7
0
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;
}
Пример #8
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;
	}
Пример #9
0
/*
 * Initializes UART access. The callback function will be called once
 * per found UART.
 */
void
BCMINITFN(sb_serial_init)(sb_t *sbh, void (*add)(void *regs, uint irq, uint baud_base,
                                                 uint reg_shift))
{
	osl_t *osh;
	void *regs;
	ulong base;
	uint irq;
	int i, n;

	osh = sb_osh(sbh);

	if ((regs = sb_setcore(sbh, SB_EXTIF, 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(osh, &sb->sbadmatch1)));

		/* Determine IRQ */
		irq = sb_irq(sbh);

		/* Disable GPIO interrupt initially */
		W_REG(osh, &eir->gpiointpolarity, 0);
		W_REG(osh, &eir->gpiointmask, 0);

		/* Search for external UARTs */
		n = 2;
		for (i = 0; i < 2; i++) {
			regs = (void *) REG_MAP(base + (i * 8), 8);
			if (serial_exists(osh, regs)) {
				/* Set GPIO 1 to be the external UART IRQ */
				W_REG(osh, &eir->gpiointmask, 2);
				/* XXXDetermine external UART clock */
				if (add)
					add(regs, irq, 13500000, 0);
			}
		}

		/* Add internal UART if enabled */
		if (R_REG(osh, &eir->corecontrol) & CC_UE)
			if (add)
				add((void *) &eir->uartdata, irq, sb_clock(sbh), 2);
	} else if ((regs = sb_setcore(sbh, SB_CC, 0))) {
		chipcregs_t *cc = (chipcregs_t *) regs;
		uint32 rev, cap, pll, baud_base, div;

		/* Default value */
		div = 48;

		/* Determine core revision and capabilities */
		rev = sb_corerev(sbh);
		cap = R_REG(osh, &cc->capabilities);
		pll = cap & CAP_PLL_MASK;

		/* Determine IRQ */
		irq = sb_irq(sbh);

		if (pll == PLL_TYPE1) {
			/* PLL clock */
			baud_base = sb_clock_rate(pll,
			                          R_REG(osh, &cc->clockcontrol_n),
			                          R_REG(osh, &cc->clockcontrol_m2));
			div = 1;
		} else {
			/* 5354 chip common uart uses a constant clock
			 * frequency of 25MHz */
			if (sb_corerev(sbh) == 20) {
				/* Set the override bit so we don't divide it */
				W_REG(osh, &cc->corecontrol, CC_UARTCLKO);
				baud_base = 25000000;
			} else if (rev >= 11 && rev != 15) {
				/* Fixed ALP clock */
				baud_base = sb_alp_clock(sbh);
				div = 1;
				/* Set the override bit so we don't divide it */
				W_REG(osh, &cc->corecontrol, CC_UARTCLKO);
			} else if (rev >= 3) {
				/* Internal backplane clock */
				baud_base = sb_clock(sbh);
				div = 2;	/* Minimum divisor */
				W_REG(osh, &cc->clkdiv,
				      ((R_REG(osh, &cc->clkdiv) & ~CLKD_UART) | div));
			} else {
				/* Fixed internal backplane clock */
				baud_base = 88000000;
				div = 48;
			}

			/* Clock source depends on strapping if UartClkOverride is unset */
			if ((rev > 0) &&
			    ((R_REG(osh, &cc->corecontrol) & CC_UARTCLKO) == 0)) {
				if ((cap & CAP_UCLKSEL) == CAP_UINTCLK) {
					/* Internal divided backplane clock */
					baud_base /= div;
				} else {
					/* Assume external clock of 1.8432 MHz */
					baud_base = 1843200;
				}
			}
		}

		/* Add internal UARTs */
		n = cap & CAP_UARTS_MASK;
		for (i = 0; i < n; i++) {
			/* Register offset changed after revision 0 */
			if (rev)
				regs = (void *)((ulong) &cc->uart0data + (i * 256));
			else
				regs = (void *)((ulong) &cc->uart0data + (i * 8));

			if (add)
				add(regs, irq, baud_base, 0);
		}
	}
}
Пример #10
0
/*
 * Initializes UART access. The callback function will be called once
 * per found UART.
 */
void BCMINITFN(sb_serial_init) (sb_t * sbh, sb_serial_init_fn add) {
	osl_t *osh;
	void *regs;
	chipcregs_t *cc;
	uint32 rev, cap, pll, baud_base, div;
	uint irq;
	int i, n;

	osh = sb_osh(sbh);

	regs = sb_setcore(sbh, SB_EXTIF, 0);
	if (regs) {
		sb_extif_serial_init(sbh, regs, add);
		return;
	}

	cc = (chipcregs_t *) sb_setcore(sbh, SB_CC, 0);
	ASSERT(cc);

	/* Determine core revision and capabilities */
	rev = sbh->ccrev;
	cap = sbh->cccaps;
	pll = cap & CC_CAP_PLL_MASK;

	/* Determine IRQ */
	irq = sb_irq(sbh);

	if (pll == PLL_TYPE1) {
		/* PLL clock */
		baud_base = sb_clock_rate(pll,
					  R_REG(osh, &cc->clockcontrol_n),
					  R_REG(osh, &cc->clockcontrol_m2));
		div = 1;
	} else {
		/* 5354 chip common uart uses a constant clock
		 * frequency of 25MHz */
		if (sb_corerev(sbh) == 20) {
			/* Set the override bit so we don't divide it */
			W_REG(osh, &cc->corecontrol, CC_UARTCLKO);
			baud_base = 25000000;
		} else if (rev >= 11 && rev != 15) {
			/* Fixed ALP clock */
			baud_base = sb_alp_clock(sbh);
			div = 1;
			/* Turn off UART clock before switching clock source */
			if (rev >= 21)
				AND_REG(osh, &cc->corecontrol, ~CC_UARTCLKEN);
			/* Set the override bit so we don't divide it */
			OR_REG(osh, &cc->corecontrol, CC_UARTCLKO);
			if (rev >= 21)
				OR_REG(osh, &cc->corecontrol, CC_UARTCLKEN);
		} else if (rev >= 3) {
			/* Internal backplane clock */
			baud_base = sb_clock(sbh);
			div = 2;	/* Minimum divisor */
			W_REG(osh, &cc->clkdiv,
			      ((R_REG(osh, &cc->clkdiv) & ~CLKD_UART) | div));
		} else {
			/* Fixed internal backplane clock */
			baud_base = 88000000;
			div = 48;
		}

		/* Clock source depends on strapping if UartClkOverride is unset */
		if ((rev > 0)
		    && ((R_REG(osh, &cc->corecontrol) & CC_UARTCLKO) == 0)) {
			if ((cap & CC_CAP_UCLKSEL) == CC_CAP_UINTCLK) {
				/* Internal divided backplane clock */
				baud_base /= div;
			} else {
				/* Assume external clock of 1.8432 MHz */
				baud_base = 1843200;
			}
		}
	}

	/* Add internal UARTs */
	n = cap & CC_CAP_UARTS_MASK;
	for (i = 0; i < n; i++) {
		/* Register offset changed after revision 0 */
		if (rev)
			regs = (void *)((ulong) & cc->uart0data + (i * 256));
		else
			regs = (void *)((ulong) & cc->uart0data + (i * 8));

		if (add)
			add(regs, irq, baud_base, 0);
	}
}
Пример #11
0
/* Probe for NVRAM header */
static void __init
early_nvram_init(void)
{
	struct nvram_header *header;
	chipcregs_t *cc;
	struct sflash *info = NULL;
	int i;
	uint32 base, off, lim;
	u32 *src, *dst;

	if ((cc = sb_setcore(sbh, SB_CC, 0)) != NULL) {
		base = KSEG1ADDR(SB_FLASH2);
		switch (readl(&cc->capabilities) & CAP_FLASH_MASK) {
		case PFLASH:
			lim = SB_FLASH2_SZ;
			break;

		case SFLASH_ST:
		case SFLASH_AT:
			if ((info = sflash_init(cc)) == NULL)
				return;
			lim = info->size;
			break;

		case FLASH_NONE:
		default:
			return;
		}
	} else {
		/* extif assumed, Stop at 4 MB */
		base = KSEG1ADDR(SB_FLASH1);
		lim = SB_FLASH1_SZ;
	}

	/* XXX: hack for supporting the CFE environment stuff on WGT634U */
	src = (u32 *) KSEG1ADDR(base + 8 * 1024 * 1024 - 0x2000);
	dst = (u32 *) nvram_buf;
	if ((lim == 0x02000000) && ((*src & 0xff00ff) == 0x000001)) {
		printk("early_nvram_init: WGT634U NVRAM found.\n");

		for (i = 0; i < 0x1ff0; i++) {
			if (*src == 0xFFFFFFFF)
				break;
			*dst++ = *src++;
		}
		return;
	}

	off = FLASH_MIN;
	while (off <= lim) {
		/* Windowed flash access */
		header = (struct nvram_header *) KSEG1ADDR(base + off - NVRAM_SPACE);
		if (header->magic == NVRAM_MAGIC)
			goto found;
		off <<= 1;
	}

	/* Try embedded NVRAM at 4 KB and 1 KB as last resorts */
	header = (struct nvram_header *) KSEG1ADDR(base + 4 KB);
	if (header->magic == NVRAM_MAGIC)
		goto found;
	
	header = (struct nvram_header *) KSEG1ADDR(base + 1 KB);
	if (header->magic == NVRAM_MAGIC)
		goto found;
	
	printk("early_nvram_init: NVRAM not found\n");
	return;

found:
	src = (u32 *) header;
	dst = (u32 *) nvram_buf;
	for (i = 0; i < sizeof(struct nvram_header); i += 4)
		*dst++ = *src++;
	for (; i < header->len && i < NVRAM_SPACE; i += 4)
		*dst++ = ltoh32(*src++);
}
Пример #12
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);
}
Пример #13
0
/* Read the flash ID and set the globals */
int
sysFlashInit(char *flash_str)
{
	osl_t *osh;
	uint32 fltype = PFLASH;
	uint16 flash_vendid = 0;
	uint16 flash_devid = 0;
	int idx;
	struct sflash *sflash;

	/*
	 * Check for serial flash.
	 */
	sbh = sb_kattach(SB_OSH);
	ASSERT(sbh);

	osh = sb_osh(sbh);

	flashutl_base = (uint8*)OSL_UNCACHED(SB_FLASH1);
	flashutl_wsz = sizeof(uint16);
	cc = (chipcregs_t *)sb_setcore(sbh, SB_CC, 0);
	if (cc) {
		flashutl_base = (uint8*)OSL_UNCACHED(SB_FLASH2);
		flashutl_wsz = (R_REG(osh, &cc->flash_config) & CC_CFG_DS) ?
		        sizeof(uint16) : sizeof(uint8);
		/* Select SFLASH ? */
		fltype = R_REG(osh, &cc->capabilities) & CC_CAP_FLASH_MASK;
		if (fltype == SFLASH_ST || fltype == SFLASH_AT) {
			sflash = sflash_init(sbh, cc);
			flashutl_cmd = &sflash_cmd_t;
			flashutl_desc = &sflash_desc;
			flashutl_desc->size = sflash->size;
			if (flash_str) 
				sprintf(flash_str, "SFLASH %d kB", sflash->size/1024);
			return (0);
		}
	}

	ASSERT(flashutl_wsz == sizeof(uint8) || flashutl_wsz == sizeof(uint16));

	/* 
	 * Parallel flash support
	 *  Some flashes have different unlock addresses, try each it turn
	 */
	for (idx = 0;
	     fltype == PFLASH && idx < ARRAYSIZE(flash_cmds);
	     idx ++) {
		flashutl_cmd = &flash_cmds[idx];
		if (flashutl_cmd->type == OLD)
			continue;

		if (flashutl_cmd->read_id)
			cmd(flashutl_cmd->read_id, CMD_ADDR);

#ifdef MIPSEB
		flash_vendid = flash_readword(FLASH_ADDR(2));
		flash_devid = flash_readword(FLASH_ADDR(0));
#else
		flash_vendid = flash_readword(FLASH_ADDR(0));
		flash_devid = flash_readword(FLASH_ADDR(2));
#endif /* MIPSEB */

		/* Funky AMD, uses 3 byte device ID so use first byte (4th addr) to
		 * identify it is a 3-byte ID and use the next two bytes (5th & 6th addr)
		 * to form a word for unique identification of format xxyy, where
		 * xx = 5th addr and yy = 6th addr
		 */
		if ((flash_vendid == 1) && (flash_devid == 0x227e)) {
			/* Get real devid */
			uint16 flash_devid_5th;
#ifdef MIPSEB
			flash_devid_5th = flash_readword(FLASH_ADDR(0x1e)) << 8;
			flash_devid = (flash_readword(FLASH_ADDR(0x1c)) & 0xff) | flash_devid_5th;
#else
			flash_devid_5th = flash_readword(FLASH_ADDR(0x1c)) << 8;
			flash_devid = (flash_readword(FLASH_ADDR(0x1e)) & 0xff) | flash_devid_5th;
#endif /* MIPSEB */
		}

		flashutl_desc = flashes;
		while (flashutl_desc->mfgid != 0 &&
			   !(flashutl_desc->mfgid == flash_vendid &&
			 flashutl_desc->devid == flash_devid)) {
			flashutl_desc++;
		}
		if (flashutl_desc->mfgid != 0)
			break;
	}

	if (flashutl_desc->mfgid == 0) {
		flashutl_desc = NULL;
		flashutl_cmd = NULL;
	} else {
		flashutl_cmd = flash_cmds;
		while (flashutl_cmd->type != 0 && flashutl_cmd->type != flashutl_desc->type)
			flashutl_cmd++;
		if (flashutl_cmd->type == 0)
			flashutl_cmd = NULL;
	}

	if (flashutl_cmd != NULL) {
		flash_reset();
	}

	if (flashutl_desc == NULL) {
		if (flash_str)
			sprintf(flash_str, "UNKNOWN 0x%x 0x%x", flash_vendid, flash_devid);
		DPRINT(("Flash type UNKNOWN\n"));
		return 1;
	}
	
	if (flash_str)
		strcpy(flash_str, flashutl_desc->desc);
	DPRINT(("Flash type \"%s\"\n", flashutl_desc->desc));

	return 0;
}
Пример #14
0
/* Read the flash ID and set the globals */
int
sysFlashInit(char *flash_str)
{
	uint32 fltype = PFLASH;
	uint16 flash_vendid = 0;
	uint16 flash_devid = 0;
	uint16* flash = (uint16*)0xbfc00000;
	int idx;
	struct sflash *sflash;
	void *sbh;

	/*
	 * Check for serial flash.
	 */
	sbh = sb_kattach();
	ASSERT(sbh);
	cc = (chipcregs_t *) sb_setcore(sbh, SB_CC, 0);

	if (cc) {
		flash = (uint16*)0xbc000000;
		fltype = R_REG(&cc->capabilities) & CAP_FLASH_MASK;
		/* Select SFLASH ? */
		if (fltype == SFLASH_ST || fltype == SFLASH_AT) {
			sflash = sflash_init(cc);
			flashutl_cmd = &sflash_cmd_t;
			flashutl_desc = &sflash_desc;
			flashutl_desc->size = sflash->size;
			if (flash_str) 
				sprintf(flash_str, "SFLASH %d kB", sflash->size/1024);
			return(0);
		}
	}

	flashutl_base = (uint8*)flash;

	/* 
	 * Parallel flash support
	 *  Some flashes have different unlock addresses, try each it turn
	 */
	idx = sizeof(flash_cmds)/sizeof(flash_cmds_t) - 2;
	flashutl_cmd = &flash_cmds[idx--];
	while((fltype == PFLASH) && flashutl_cmd->type) {

		if (flashutl_cmd->read_id)
			cmd(flashutl_cmd->read_id, CMD_ADDR);

#ifdef MIPSEB
		flash_vendid = *(flash + 1);
		flash_devid = *flash;	
#else
		flash_vendid = *flash;
		flash_devid = *(flash + 1);
#endif

		/* Funky AMD */
		if ((flash_vendid == 1) && (flash_devid == 0x227e)) {
			/* Get real devid */
#ifdef MIPSEB
			flash_devid = *(flash+0xe);	
#else
			flash_devid = *(flash+0xf);
#endif
		}

		flashutl_desc = flashes;
		while (flashutl_desc->mfgid != 0 &&
			   !(flashutl_desc->mfgid == flash_vendid &&
			 flashutl_desc->devid == flash_devid)) {
			flashutl_desc++;
		}
		if (flashutl_desc->mfgid != 0)
			break;

		flashutl_cmd = &flash_cmds[idx--];
	}

	if (flashutl_desc->mfgid == 0) {
		flashutl_desc = NULL;
		flashutl_cmd = NULL;
	} else {
		flashutl_cmd = flash_cmds;
		while (flashutl_cmd->type != 0 && flashutl_cmd->type != flashutl_desc->type)
			flashutl_cmd++;
		if (flashutl_cmd->type == 0)
			flashutl_cmd = NULL;
	}

	if (flashutl_cmd != NULL) {
		flash_reset();
	}

	if (flashutl_desc == NULL) {
		if (flash_str)
			sprintf(flash_str, "UNKNOWN 0x%x 0x%x", flash_vendid, flash_devid);
		DPRINT(("Flash type UNKNOWN\n"));
		return 1;
	}
	
	if (flash_str)
		strcpy(flash_str, flashutl_desc->desc);
	DPRINT(("Flash type \"%s\"\n", flashutl_desc->desc));

	return 0;
}