Exemple #1
0
/*
 . Function: smc_reset( void )
 . Purpose:
 .	This sets the SMC91111 chip to its normal state, hopefully from whatever
 .	mess that any other DOS driver has put it in.
 .
 . Maybe I should reset more registers to defaults in here?  SOFTRST  should
 . do that for me.
 .
 . Method:
 .	1.  send a SOFT RESET
 .	2.  wait for it to finish
 .	3.  enable autorelease mode
 .	4.  reset the memory management unit
 .	5.  clear all interrupts
 .
*/
static void smc_reset (struct eth_device *dev)
{
	PRINTK2 ("%s: smc_reset\n", SMC_DEV_NAME);

	/* This resets the registers mostly to defaults, but doesn't
	   affect EEPROM.  That seems unnecessary */
	SMC_SELECT_BANK (dev, 0);
	SMC_outw (dev, RCR_SOFTRST, RCR_REG);

	/* Setup the Configuration Register */
	/* This is necessary because the CONFIG_REG is not affected */
	/* by a soft reset */

	SMC_SELECT_BANK (dev, 1);
#if defined(CONFIG_SMC91111_EXT_PHY)
	SMC_outw (dev, CONFIG_DEFAULT | CONFIG_EXT_PHY, CONFIG_REG);
#else
	SMC_outw (dev, CONFIG_DEFAULT, CONFIG_REG);
#endif


	/* Release from possible power-down state */
	/* Configuration register is not affected by Soft Reset */
	SMC_outw (dev, SMC_inw (dev, CONFIG_REG) | CONFIG_EPH_POWER_EN,
		CONFIG_REG);

	SMC_SELECT_BANK (dev, 0);

	/* this should pause enough for the chip to be happy */
	udelay (10);

	/* Disable transmit and receive functionality */
	SMC_outw (dev, RCR_CLEAR, RCR_REG);
	SMC_outw (dev, TCR_CLEAR, TCR_REG);

	/* set the control register */
	SMC_SELECT_BANK (dev, 1);
	SMC_outw (dev, CTL_DEFAULT, CTL_REG);

	/* Reset the MMU */
	SMC_SELECT_BANK (dev, 2);
	smc_wait_mmu_release_complete (dev);
	SMC_outw (dev, MC_RESET, MMU_CMD_REG);
	while (SMC_inw (dev, MMU_CMD_REG) & MC_BUSY)
		udelay (1);	/* Wait until not busy */

	/* Note:  It doesn't seem that waiting for the MMU busy is needed here,
	   but this is a place where future chipsets _COULD_ break.  Be wary
	   of issuing another MMU command right after this */

	/* Disable all interrupts */
	SMC_outb (dev, 0, IM_REG);
}
/***********************************************
 * Show available memory		       *
 ***********************************************/
void dump_memory_info(void)
{
	word mem_info;
	word old_bank;

	old_bank = SMC_inw(BANK_SELECT)&0xF;

	SMC_SELECT_BANK(0);
	mem_info = SMC_inw( MIR_REG );
	PRINTK2("Memory: %4d available\n", (mem_info >> 8)*2048);

	SMC_SELECT_BANK(old_bank);
}
Exemple #3
0
static inline byte SMC_inb(struct eth_device *dev, dword offset)
{
	word  _w;

	_w = SMC_inw(dev, offset & ~((dword)1));
	return (offset & 1) ? (byte)(_w >> 8) : (byte)(_w);
}
static inline byte SMC_inb(dword offset)
{
	word  _w;

	_w = SMC_inw(offset & ~((dword)1));
	return (offset & 1) ? (byte)(_w >> 8) : (byte)(_w);
}
static inline void SMC_insw(dword offset, volatile uchar* buf, dword len)
{
	volatile word *p = (volatile word *)buf;

	while (len-- > 0) {
		*p++ = SMC_inw(offset);
		barrier();
		*((volatile u32*)(0xc0000000));
	}
}
static inline void SMC_outb(byte value, dword offset)
{
	word  _w;

	_w = SMC_inw(offset & ~((dword)1));
	if (offset & 1)
			*((volatile word*)(SMC_BASE_ADDRESS+(offset & ~((dword)1)))) = (value<<8) | (_w & 0x00ff);
	else
			*((volatile word*)(SMC_BASE_ADDRESS+offset)) = value | (_w & 0xff00);
}
Exemple #7
0
static int write_eeprom_reg(struct eth_device *dev, u16 value, u16 reg)
{
	int timeout;

	SMC_SELECT_BANK(dev, 2);
	SMC_outw(dev, reg, PTR_REG);

	SMC_SELECT_BANK(dev, 1);
	SMC_outw(dev, value, GP_REG);
	SMC_outw(dev, SMC_inw (dev, CTL_REG) | CTL_EEPROM_SELECT | CTL_STORE, CTL_REG);
	timeout = 100;
	while ((SMC_inw(dev, CTL_REG) & CTL_STORE) && --timeout)
		udelay (100);
	if (timeout == 0) {
		printf("Timeout Writing EEPROM register %02x\n", reg);
		return 0;
	}

	return 1;
}
Exemple #8
0
static u16 read_eeprom_reg(struct eth_device *dev, u16 reg)
{
	int timeout;

	SMC_SELECT_BANK(dev, 2);
	SMC_outw(dev, reg, PTR_REG);

	SMC_SELECT_BANK(dev, 1);
	SMC_outw(dev, SMC_inw (dev, CTL_REG) | CTL_EEPROM_SELECT | CTL_RELOAD,
		 CTL_REG);
	timeout = 100;
	while((SMC_inw (dev, CTL_REG) & CTL_RELOAD) && --timeout)
		udelay(100);
	if (timeout == 0) {
		printf("Timeout Reading EEPROM register %02x\n", reg);
		return 0;
	}

	return SMC_inw (dev, GP_REG);
}
Exemple #9
0
/* Only one release command at a time, please */
static inline void smc_wait_mmu_release_complete (struct eth_device *dev)
{
	int count = 0;

	/* assume bank 2 selected */
	while (SMC_inw (dev, MMU_CMD_REG) & MC_BUSY) {
		udelay (1);	/* Wait until not busy */
		if (++count > 200)
			break;
	}
}
Exemple #10
0
static inline void SMC_outb(struct eth_device *dev, byte value, dword offset)
{
	word  _w;

	_w = SMC_inw(dev, offset & ~((dword)1));
	if (offset & 1)
		*((volatile word*)(dev->iobase + (offset & ~((dword)1)))) =
			(value<<8) | (_w & 0x00ff);
	else
		*((volatile word*)(dev->iobase + offset)) =
			value | (_w & 0xff00);
}
Exemple #11
0
static int poll4int (struct eth_device *dev, byte mask, int timeout)
{
	int tmo = get_timer (0) + timeout * CONFIG_SYS_HZ;
	int is_timeout = 0;
	word old_bank = SMC_inw (dev, BSR_REG);

	PRINTK2 ("Polling...\n");
	SMC_SELECT_BANK (dev, 2);
	while ((SMC_inw (dev, SMC91111_INT_REG) & mask) == 0) {
		if (get_timer (0) >= tmo) {
			is_timeout = 1;
			break;
		}
	}

	/* restore old bank selection */
	SMC_SELECT_BANK (dev, old_bank);

	if (is_timeout)
		return 1;
	else
		return 0;
}
static int poll4int (byte mask, int timeout)
{
	int tmo = get_timer (0) + timeout * CFG_HZ;
	int is_timeout = 0;
	word old_bank = SMC_inw (BSR_REG);

	PRINTK2 ("Polling...\n");
	SMC_SELECT_BANK (2);
	while ((SMC_inw (SMC91111_INT_REG) & mask) == 0) {
		if (get_timer (0) >= tmo) {
			is_timeout = 1;
			break;
		}
	}

	/* restore old bank selection */
	SMC_SELECT_BANK (old_bank);

	if (is_timeout)
		return 1;
	else
		return 0;
}
Exemple #13
0
int eeprom(int argc, char *argv[])
{
	int i, len, ret;
	unsigned char buf[58], *p;

	struct eth_device dev = {
		.iobase = CONFIG_SMC91111_BASE
	};

	app_startup(argv);
	if (get_version() != XF_VERSION) {
		printf("Wrong XF_VERSION.\n");
		printf("Application expects ABI version %d\n", XF_VERSION);
		printf("Actual U-Boot ABI version %d\n", (int)get_version());
		return 1;
	}

	return crcek();

	if ((SMC_inw (&dev, BANK_SELECT) & 0xFF00) != 0x3300) {
		printf("SMSC91111 not found.\n");
		return 2;
	}

	/* Called without parameters - print MAC address */
	if (argc < 2) {
		verify_macaddr(&dev, NULL);
		return 0;
	}

	/* Print help message */
	if (argv[1][1] == 'h') {
		printf("VoiceBlue EEPROM writer\n");
		printf("Built: %s at %s\n", U_BOOT_DATE, U_BOOT_TIME);
		printf("Usage:\n\t<mac_address> [<element_1>] [<...>]\n");
		return 0;
	}

	/* Try to parse information elements */
	len = sizeof(buf);
	p = buf;
	for (i = 2; i < argc; i++) {
		ret = parse_element(argv[i], p, len);
		switch (ret) {
		case -1:
			printf("Element %d: malformed\n", i - 1);
			return 3;
		case -2:
			printf("Element %d: odd character count\n", i - 1);
			return 3;
		case -3:
			printf("Out of EEPROM memory\n");
			return 3;
		default:
			p += ret;
			len -= ret;
		}
	}

	/* First argument (MAC) is mandatory */
	set_mac(&dev, argv[1]);
	if (verify_macaddr(&dev, argv[1])) {
		printf("*** MAC address does not match! ***\n");
		return 4;
	}

	while (len--)
		*p++ = 0;

	write_data(&dev, (u16 *)buf, sizeof(buf) >> 1);

	return 0;
}
Exemple #14
0
/*
 . Function:  smc_send(struct net_device * )
 . Purpose:
 .	This sends the actual packet to the SMC9xxx chip.
 .
 . Algorithm:
 .	First, see if a saved_skb is available.
 .		( this should NOT be called if there is no 'saved_skb'
 .	Now, find the packet number that the chip allocated
 .	Point the data pointers at it in memory
 .	Set the length word in the chip's memory
 .	Dump the packet to chip memory
 .	Check if a last byte is needed ( odd length packet )
 .		if so, set the control flag right
 .	Tell the card to send it
 .	Enable the transmit interrupt, so I know if it failed
 .	Free the kernel data if I actually sent it.
*/
static int smc_send(struct eth_device *dev, void *packet, int packet_length)
{
	byte packet_no;
	byte *buf;
	int length;
	int numPages;
	int try = 0;
	int time_out;
	byte status;
	byte saved_pnr;
	word saved_ptr;

	/* save PTR and PNR registers before manipulation */
	SMC_SELECT_BANK (dev, 2);
	saved_pnr = SMC_inb( dev, PN_REG );
	saved_ptr = SMC_inw( dev, PTR_REG );

	PRINTK3 ("%s: smc_hardware_send_packet\n", SMC_DEV_NAME);

	length = ETH_ZLEN < packet_length ? packet_length : ETH_ZLEN;

	/* allocate memory
	 ** The MMU wants the number of pages to be the number of 256 bytes
	 ** 'pages', minus 1 ( since a packet can't ever have 0 pages :) )
	 **
	 ** The 91C111 ignores the size bits, but the code is left intact
	 ** for backwards and future compatibility.
	 **
	 ** Pkt size for allocating is data length +6 (for additional status
	 ** words, length and ctl!)
	 **
	 ** If odd size then last byte is included in this header.
	 */
	numPages = ((length & 0xfffe) + 6);
	numPages >>= 8;		/* Divide by 256 */

	if (numPages > 7) {
		printf ("%s: Far too big packet error. \n", SMC_DEV_NAME);
		return 0;
	}

	/* now, try to allocate the memory */
	SMC_SELECT_BANK (dev, 2);
	SMC_outw (dev, MC_ALLOC | numPages, MMU_CMD_REG);

	/* FIXME: the ALLOC_INT bit never gets set *
	 * so the following will always give a	   *
	 * memory allocation error.		   *
	 * same code works in armboot though	   *
	 * -ro
	 */

again:
	try++;
	time_out = MEMORY_WAIT_TIME;
	do {
		status = SMC_inb (dev, SMC91111_INT_REG);
		if (status & IM_ALLOC_INT) {
			/* acknowledge the interrupt */
			SMC_outb (dev, IM_ALLOC_INT, SMC91111_INT_REG);
			break;
		}
	} while (--time_out);

	if (!time_out) {
		PRINTK2 ("%s: memory allocation, try %d failed ...\n",
			 SMC_DEV_NAME, try);
		if (try < SMC_ALLOC_MAX_TRY)
			goto again;
		else
			return 0;
	}
Exemple #15
0
int eeprom(int argc, char * const argv[])
{
	int i, len, ret;
	unsigned char buf[58], *p;

	app_startup(argv);
	i = get_version();
	if (i != XF_VERSION) {
		printf("Using ABI version %d, but U-Boot provides %d\n",
			XF_VERSION, i);
		return 1;
	}

	if ((SMC_inw(&dev, BANK_SELECT) & 0xFF00) != 0x3300) {
		puts("SMSC91111 not found\n");
		return 2;
	}

	/* Called without parameters - print MAC address */
	if (argc < 2) {
		verify_macaddr(NULL);
		return 0;
	}

	/* Print help message */
	if (argv[1][1] == 'h') {
		puts("NetStar EEPROM writer\n"
			"Built: " U_BOOT_DATE " at " U_BOOT_TIME "\n"
			"Usage:\n\t<mac_address> [<element_1>] [<...>]\n");
		return 0;
	}

	/* Try to parse information elements */
	len = sizeof(buf);
	p = buf;
	for (i = 2; i < argc; i++) {
		ret = parse_element(argv[i], p, len);
		switch (ret) {
		case -1:
			printf("Element %d: malformed\n", i - 1);
			return 3;
		case -2:
			printf("Element %d: odd character count\n", i - 1);
			return 3;
		case -3:
			puts("Out of EEPROM memory\n");
			return 3;
		default:
			p += ret;
			len -= ret;
		}
	}

	/* First argument (MAC) is mandatory */
	set_mac(argv[1]);
	if (verify_macaddr(argv[1])) {
		puts("*** HWaddr does not match! ***\n");
		return 4;
	}

	while (len--)
		*p++ = 0;

	write_data((u16 *)buf, sizeof(buf) >> 1);

	return 0;
}