diff options
| author | Marian Balakowicz <m8@semihalf.com> | 2005-10-28 22:30:33 +0200 | 
|---|---|---|
| committer | Marian Balakowicz <m8@semihalf.com> | 2005-10-28 22:30:33 +0200 | 
| commit | 63ff004c4fcad9f690bf44dbd15d568bb47aac2d (patch) | |
| tree | 7b64074a85da8118b6c862f14de1171b36ade0f7 /common | |
| parent | fe93483a0ab9dcbf7794ffbf0b029ba138380e81 (diff) | |
| download | olio-uboot-2014.01-63ff004c4fcad9f690bf44dbd15d568bb47aac2d.tar.xz olio-uboot-2014.01-63ff004c4fcad9f690bf44dbd15d568bb47aac2d.zip | |
Add support for multiple PHYs.
Diffstat (limited to 'common')
| -rw-r--r-- | common/cmd_mii.c | 109 | ||||
| -rw-r--r-- | common/miiphybb.c | 6 | ||||
| -rw-r--r-- | common/miiphyutil.c | 246 | 
3 files changed, 305 insertions, 56 deletions
| diff --git a/common/cmd_mii.c b/common/cmd_mii.c index f93232c32..48a4e77c5 100644 --- a/common/cmd_mii.c +++ b/common/cmd_mii.c @@ -41,19 +41,21 @@ uint last_data;  uint last_reg;  /* - * MII read/write + * MII device/info/read/write   *   * Syntax: - *  mii read {addr} {reg} - *  mii write {addr} {reg} {data} + *  mii device {devname} + *  mii info   {addr} + *  mii read   {addr} {reg} + *  mii write  {addr} {reg} {data}   */ -  int do_mii (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])  {  	char		op;  	unsigned char	addr, reg;  	unsigned short	data;  	int		rcode = 0; +	char		*devname;  #if defined(CONFIG_8xx) || defined(CONFIG_MCF52x2)  	mii_init (); @@ -78,8 +80,11 @@ int do_mii (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])  			data = simple_strtoul (argv[4], NULL, 16);  	} +	/* use current device */ +	devname = miiphy_get_current_dev(); +  	/* -	 * check info/read/write. +	 * check device/read/write/list.  	 */  	if (op == 'i') {  		unsigned char j, start, end; @@ -91,34 +96,43 @@ int do_mii (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])  		 * Look for any and all PHYs.  Valid addresses are 0..31.  		 */  		if (argc >= 3) { -			start = addrlo; end = addrhi + 1; +			start = addr; end = addr + 1;  		} else { -			start = 0; end = 32; +			start = 0; end = 31;  		}  		for (j = start; j < end; j++) { -			if (miiphy_info (j, &oui, &model, &rev) == 0) { +			if (miiphy_info (devname, j, &oui, &model, &rev) == 0) {  				printf ("PHY 0x%02X: "  					"OUI = 0x%04X, "  					"Model = 0x%02X, "  					"Rev = 0x%02X, "  					"%3dbaseT, %s\n",  					j, oui, model, rev, -					miiphy_speed (j), -					miiphy_duplex (j) == FULL ? "FDX" : "HDX"); +					miiphy_speed (devname, j), +					(miiphy_duplex (devname, j) == FULL) +						? "FDX" : "HDX"); +			} else { +				puts ("Error reading info from the PHY\n");  			}  		}  	} else if (op == 'r') { -		if (miiphy_read (addr, reg, &data) != 0) { +		if (miiphy_read (devname, addr, reg, &data) != 0) {  			puts ("Error reading from the PHY\n");  			rcode = 1; +		} else { +			printf ("%04X\n", data & 0x0000FFFF);  		} -		printf ("%04X\n", data & 0x0000FFFF);  	} else if (op == 'w') { -		if (miiphy_write (addr, reg, data) != 0) { +		if (miiphy_write (devname, addr, reg, data) != 0) {  			puts ("Error writing to the PHY\n");  			rcode = 1;  		} +	} else if (op == 'd') { +		if (argc == 2) +			miiphy_listdev (); +		else +			miiphy_set_current_dev (argv[2]);  	} else {  		printf ("Usage:\n%s\n", cmdtp->usage);  		return 1; @@ -140,9 +154,11 @@ int do_mii (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])  U_BOOT_CMD(  	mii,	5,	1,	do_mii,  	"mii     - MII utility commands\n", -	"info  <addr>              - display MII PHY info\n" -	"mii read  <addr> <reg>        - read  MII PHY <addr> register <reg>\n" -	"mii write <addr> <reg> <data> - write MII PHY <addr> register <reg>\n" +	"device                     - list available devices\n" +	"mii device <devname>           - set current device\n" +	"mii info   <addr>              - display MII PHY info\n" +	"mii read   <addr> <reg>        - read  MII PHY <addr> register <reg>\n" +	"mii write  <addr> <reg> <data> - write MII PHY <addr> register <reg>\n"  );  #else /* ! CONFIG_TERSE_MII ================================================= */ @@ -386,7 +402,7 @@ static int special_field(  	return 0;  } -uint last_op; +char last_op[2];  uint last_data;  uint last_addr_lo;  uint last_addr_hi; @@ -412,11 +428,12 @@ static void extract_range(  /* ---------------------------------------------------------------- */  int do_mii (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])  { -	char		op; +	char		op[2];  	unsigned char	addrlo, addrhi, reglo, reghi;  	unsigned char	addr, reg;  	unsigned short	data;  	int		rcode = 0; +	char		*devname;  #ifdef CONFIG_8xx  	mii_init (); @@ -426,7 +443,8 @@ int do_mii (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])  	 * We use the last specified parameters, unless new ones are  	 * entered.  	 */ -	op     = last_op; +	op[0] = last_op[0]; +	op[1] = last_op[1];  	addrlo = last_addr_lo;  	addrhi = last_addr_hi;  	reglo  = last_reg_lo; @@ -434,7 +452,12 @@ int do_mii (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])  	data   = last_data;  	if ((flag & CMD_FLAG_REPEAT) == 0) { -		op = argv[1][0]; +		op[0] = argv[1][0]; +		if (strlen(argv[1]) > 1) +			op[1] = argv[1][1]; +		else +			op[1] = '\0'; +  		if (argc >= 3)  			extract_range(argv[2], &addrlo, &addrhi);  		if (argc >= 4) @@ -443,10 +466,13 @@ int do_mii (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])  			data = simple_strtoul (argv[4], NULL, 16);  	} +	/* use current device */ +	devname = miiphy_get_current_dev(); +  	/*  	 * check info/read/write.  	 */ -	if (op == 'i') { +	if (op[0] == 'i') {  		unsigned char j, start, end;  		unsigned int oui;  		unsigned char model; @@ -462,22 +488,25 @@ int do_mii (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])  		}  		for (j = start; j <= end; j++) { -			if (miiphy_info (j, &oui, &model, &rev) == 0) { +			if (miiphy_info (devname, j, &oui, &model, &rev) == 0) {  				printf("PHY 0x%02X: "  					"OUI = 0x%04X, "  					"Model = 0x%02X, "  					"Rev = 0x%02X, "  					"%3dbaseT, %s\n",  					j, oui, model, rev, -					miiphy_speed (j), -					miiphy_duplex (j) == FULL ? "FDX" : "HDX"); +					miiphy_speed (devname, j), +					(miiphy_duplex (devname, j) == FULL) +						? "FDX" : "HDX"); +			} else { +				puts ("Error reading info from the PHY\n");  			}  		} -	} else if (op == 'r') { +	} else if (op[0] == 'r') {  		for (addr = addrlo; addr <= addrhi; addr++) {  			for (reg = reglo; reg <= reghi; reg++) {  				data = 0xffff; -				if (miiphy_read (addr, reg, &data) != 0) { +				if (miiphy_read (devname, addr, reg, &data) != 0) {  					printf(  					"Error reading from the PHY addr=%02x reg=%02x\n",  						addr, reg); @@ -492,17 +521,17 @@ int do_mii (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])  			if ((addrlo != addrhi) && (reglo != reghi))  				printf("\n");  		} -	} else if (op == 'w') { +	} else if (op[0] == 'w') {  		for (addr = addrlo; addr <= addrhi; addr++) {  			for (reg = reglo; reg <= reghi; reg++) { -				if (miiphy_write (addr, reg, data) != 0) { +				if (miiphy_write (devname, addr, reg, data) != 0) {  					printf("Error writing to the PHY addr=%02x reg=%02x\n",  						addr, reg);  					rcode = 1;  				}  			}  		} -	} else if (op == 'd') { +	} else if (strncmp(op, "du", 2) == 0) {  		ushort regs[6];  		int ok = 1;  		if ((reglo > 5) || (reghi > 5)) { @@ -512,8 +541,8 @@ int do_mii (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])  			return 1;  		}  		for (addr = addrlo; addr <= addrhi; addr++) { -			for (reg = 0; reg < 6; reg++) { -				if (miiphy_read(addr, reg, ®s[reg]) != 0) { +			for (reg = reglo; reg < reghi + 1; reg++) { +				if (miiphy_read(devname, addr, reg, ®s[reg]) != 0) {  					ok = 0;  					printf(  					"Error reading from the PHY addr=%02x reg=%02x\n", @@ -525,6 +554,11 @@ int do_mii (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])  				MII_dump_0_to_5(regs, reglo, reghi);  			printf("\n");  		} +	} else if (strncmp(op, "de", 2) == 0) { +		if (argc == 2) +			miiphy_listdev (); +		else +			miiphy_set_current_dev (argv[2]);  	} else {  		printf("Usage:\n%s\n", cmdtp->usage);  		return 1; @@ -533,7 +567,8 @@ int do_mii (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])  	/*  	 * Save the parameters for repeats.  	 */ -	last_op      = op; +	last_op[0] = op[0]; +	last_op[1] = op[1];  	last_addr_lo = addrlo;  	last_addr_hi = addrhi;  	last_reg_lo  = reglo; @@ -548,10 +583,12 @@ int do_mii (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])  U_BOOT_CMD(  	mii,	5,	1,	do_mii,  	"mii     - MII utility commands\n", -	"info  <addr>              - display MII PHY info\n" -	"mii read  <addr> <reg>        - read  MII PHY <addr> register <reg>\n" -	"mii write <addr> <reg> <data> - write MII PHY <addr> register <reg>\n" -	"mii dump  <addr> <reg>        - pretty-print <addr> <reg> (0-5 only)\n" +	"device                     - list available devices\n" +	"mii device <devname>           - set current device\n" +	"mii info   <addr>              - display MII PHY info\n" +	"mii read   <addr> <reg>        - read  MII PHY <addr> register <reg>\n" +	"mii write  <addr> <reg> <data> - write MII PHY <addr> register <reg>\n" +	"mii dump   <addr> <reg>        - pretty-print <addr> <reg> (0-5 only)\n"  	"Addr and/or reg may be ranges, e.g. 2-7.\n"  ); diff --git a/common/miiphybb.c b/common/miiphybb.c index b6af88f7d..adb697ca6 100644 --- a/common/miiphybb.c +++ b/common/miiphybb.c @@ -121,7 +121,8 @@ static void miiphy_pre (char read, unsigned char addr, unsigned char reg)   * Returns:   *   0 on success   */ -int miiphy_read (unsigned char addr, unsigned char reg, unsigned short *value) +int bb_miiphy_read (char *devname, unsigned char addr, +		unsigned char reg, unsigned short *value)  {  	short rdreg;		/* register working value */  	int j;			/* counter */ @@ -188,7 +189,8 @@ int miiphy_read (unsigned char addr, unsigned char reg, unsigned short *value)   * Returns:   *   0 on success   */ -int miiphy_write (unsigned char addr, unsigned char reg, unsigned short value) +int bb_miiphy_write (char *devname, unsigned char addr, +		unsigned char reg, unsigned short value)  {  	int j;			/* counter */  #ifndef CONFIG_EP8248 diff --git a/common/miiphyutil.c b/common/miiphyutil.c index 13b9c65dc..d67c8b537 100644 --- a/common/miiphyutil.c +++ b/common/miiphyutil.c @@ -30,6 +30,215 @@  #include <miiphy.h>  #if defined(CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII) +#include <asm/types.h> +#include <linux/list.h> +#include <malloc.h> +#include <net.h> + +/* local debug macro */ +#define MII_DEBUG +#undef MII_DEBUG + +#undef debug +#ifdef MII_DEBUG +#define debug(fmt,args...)	printf (fmt ,##args) +#else +#define debug(fmt,args...) +#endif /* MII_DEBUG */ + +struct mii_dev { +	struct list_head link; +	char *name; +	int (* read)(char *devname, unsigned char addr, +			unsigned char reg, unsigned short *value); +	int (* write)(char *devname, unsigned char addr, +			unsigned char reg, unsigned short value); +}; + +static struct list_head mii_devs; +static struct mii_dev *current_mii; + +/***************************************************************************** + * + * Register read and write MII access routines for the device <name>. + */ +void miiphy_register(char *name, +		int (* read)(char *devname, unsigned char addr, +			unsigned char reg, unsigned short *value), +		int (* write)(char *devname, unsigned char addr, +			unsigned char reg, unsigned short value)) +{ +	struct list_head *entry; +	struct mii_dev *new_dev; +	struct mii_dev *miidev; +	static int head_initialized = 0; +	unsigned int name_len; + +	if (head_initialized == 0) { +		INIT_LIST_HEAD(&mii_devs); +		current_mii = NULL; +		head_initialized = 1; +	} + +	/* check if we have unique name */ +	list_for_each(entry, &mii_devs) { +		miidev = list_entry(entry, struct mii_dev, link); +		if (strcmp(miidev->name, name) == 0) { +			printf("miiphy_register: non unique device name '%s'\n", +					name); +			return; +		} +	} + +	/* allocate memory */ +	name_len = strlen(name); +	new_dev = (struct mii_dev *)malloc(sizeof(struct mii_dev) + name_len + 1); + +	if(new_dev == NULL) { +		printf("miiphy_register: cannot allocate memory for '%s'\n", +				name); +		return; +	} +	memset(new_dev, 0, sizeof(struct mii_dev) + name_len); + +	/* initalize mii_dev struct fields */ +	INIT_LIST_HEAD(&new_dev->link); +	new_dev->read = read; +	new_dev->write = write; +	new_dev->name = (char *)(new_dev + 1); +	strncpy(new_dev->name, name, name_len); +	new_dev->name[name_len] = '\0'; + +	debug("miiphy_register: added '%s', read=0x%08lx, write=0x%08lx\n", +			new_dev->name, new_dev->read, new_dev->write); + +	/* add it to the list */ +	list_add_tail(&new_dev->link, &mii_devs); + +	if (!current_mii) +		current_mii = new_dev; +} + +int miiphy_set_current_dev(char *devname) +{ +	struct list_head *entry; +	struct mii_dev *dev; + +	list_for_each(entry, &mii_devs) { +		dev = list_entry(entry, struct mii_dev, link); + +		if (strcmp(devname, dev->name) == 0) { +			current_mii = dev; +			return 0; +		} +	} + +	printf("No such device: %s\n", devname); +	return 1; +} + +char *miiphy_get_current_dev() +{ +	if (current_mii) +		return current_mii->name; + +	return NULL; +} + +/***************************************************************************** + * + * Read to variable <value> from the PHY attached to device <devname>, + * use PHY address <addr> and register <reg>. + * + * Returns: + *   0 on success + */ +int miiphy_read(char *devname, unsigned char addr, unsigned char reg, +		unsigned short *value) +{ +	struct list_head *entry; +	struct mii_dev *dev; +	int found_dev = 0; +	int read_ret = 0; + +	if (!devname) { +		printf("NULL device name!\n"); +		return 1; +	} + +	list_for_each(entry, &mii_devs) { +		dev = list_entry(entry, struct mii_dev, link); + +		if (strcmp(devname, dev->name) == 0) { +			found_dev = 1; +			read_ret = dev->read(devname, addr, reg, value); +			break; +		} +	} + +	if (found_dev == 0) +		printf("No such device: %s\n", devname); + +	return ((found_dev) ? read_ret : 1); +} + +/***************************************************************************** + * + * Write <value> to the PHY attached to device <devname>, + * use PHY address <addr> and register <reg>. + * + * Returns: + *   0 on success + */ +int miiphy_write(char *devname, unsigned char addr, unsigned char reg, +		unsigned short value) +{ +	struct list_head *entry; +	struct mii_dev *dev; +	int found_dev = 0; +	int write_ret = 0; + +	if (!devname) { +		printf("NULL device name!\n"); +		return 1; +	} + +	list_for_each(entry, &mii_devs) { +		dev = list_entry(entry, struct mii_dev, link); + +		if (strcmp(devname, dev->name) == 0) { +			found_dev = 1; +			write_ret = dev->write(devname, addr, reg, value); +			break; +		} +	} + +	if (found_dev == 0) +		printf("No such device: %s\n", devname); + +	return ((found_dev) ? write_ret : 1); +} + +/***************************************************************************** + * + * Print out list of registered MII capable devices. + */ +void miiphy_listdev(void) +{ +	struct list_head *entry; +	struct mii_dev *dev; + +	puts("MII devices: "); +	list_for_each(entry, &mii_devs) { +		dev = list_entry(entry, struct mii_dev, link); +		printf("'%s' ", dev->name); +	} +	puts("\n"); + +	if (current_mii) +		printf("Current device: '%s'\n", current_mii->name); +} +  /*****************************************************************************   * @@ -42,14 +251,15 @@   * Returns:   *   0 on success   */ -int miiphy_info (unsigned char addr, +int miiphy_info (char *devname, +		 unsigned char addr,  		 unsigned int *oui,  		 unsigned char *model, unsigned char *rev)  {  	unsigned int reg = 0;  	unsigned short tmp; -	if (miiphy_read (addr, PHY_PHYIDR2, &tmp) != 0) { +	if (miiphy_read (devname, addr, PHY_PHYIDR2, &tmp) != 0) {  #ifdef DEBUG  		puts ("PHY ID register 2 read failed\n");  #endif @@ -65,7 +275,7 @@ int miiphy_info (unsigned char addr,  		return (-1);  	} -	if (miiphy_read (addr, PHY_PHYIDR1, &tmp) != 0) { +	if (miiphy_read (devname, addr, PHY_PHYIDR1, &tmp) != 0) {  #ifdef DEBUG  		puts ("PHY ID register 1 read failed\n");  #endif @@ -88,18 +298,18 @@ int miiphy_info (unsigned char addr,   * Returns:   *   0 on success   */ -int miiphy_reset (unsigned char addr) +int miiphy_reset (char *devname, unsigned char addr)  {  	unsigned short reg;  	int loop_cnt; -	if (miiphy_read (addr, PHY_BMCR, ®) != 0) { +	if (miiphy_read (devname, addr, PHY_BMCR, ®) != 0) {  #ifdef DEBUG  		printf ("PHY status read failed\n");  #endif  		return (-1);  	} -	if (miiphy_write (addr, PHY_BMCR, reg | 0x8000) != 0) { +	if (miiphy_write (devname, addr, PHY_BMCR, reg | 0x8000) != 0) {  #ifdef DEBUG  		puts ("PHY reset failed\n");  #endif @@ -116,7 +326,7 @@ int miiphy_reset (unsigned char addr)  	loop_cnt = 0;  	reg = 0x8000;  	while (((reg & 0x8000) != 0) && (loop_cnt++ < 1000000)) { -		if (miiphy_read (addr, PHY_BMCR, ®) != 0) { +		if (miiphy_read (devname, addr, PHY_BMCR, ®) != 0) {  #     ifdef DEBUG  			puts ("PHY status read failed\n");  #     endif @@ -137,12 +347,12 @@ int miiphy_reset (unsigned char addr)   *   * Determine the ethernet speed (10/100).   */ -int miiphy_speed (unsigned char addr) +int miiphy_speed (char *devname, unsigned char addr)  {  	unsigned short reg;  #if defined(CONFIG_PHY_GIGE) -	if (miiphy_read (addr, PHY_1000BTSR, ®)) { +	if (miiphy_read (devname, addr, PHY_1000BTSR, ®)) {  		printf ("PHY 1000BT Status read failed\n");  	} else {  		if (reg != 0xFFFF) { @@ -154,14 +364,14 @@ int miiphy_speed (unsigned char addr)  #endif /* CONFIG_PHY_GIGE */  	/* Check Basic Management Control Register first. */ -	if (miiphy_read (addr, PHY_BMCR, ®)) { +	if (miiphy_read (devname, addr, PHY_BMCR, ®)) {  		puts ("PHY speed read failed, assuming 10bT\n");  		return (_10BASET);  	}  	/* Check if auto-negotiation is on. */  	if ((reg & PHY_BMCR_AUTON) != 0) {  		/* Get auto-negotiation results. */ -		if (miiphy_read (addr, PHY_ANLPAR, ®)) { +		if (miiphy_read (devname, addr, PHY_ANLPAR, ®)) {  			puts ("PHY AN speed read failed, assuming 10bT\n");  			return (_10BASET);  		} @@ -185,12 +395,12 @@ int miiphy_speed (unsigned char addr)   *   * Determine full/half duplex.   */ -int miiphy_duplex (unsigned char addr) +int miiphy_duplex (char *devname, unsigned char addr)  {  	unsigned short reg;  #if defined(CONFIG_PHY_GIGE) -	if (miiphy_read (addr, PHY_1000BTSR, ®)) { +	if (miiphy_read (devname, addr, PHY_1000BTSR, ®)) {  		printf ("PHY 1000BT Status read failed\n");  	} else {  		if ( (reg != 0xFFFF) && @@ -205,14 +415,14 @@ int miiphy_duplex (unsigned char addr)  #endif /* CONFIG_PHY_GIGE */  	/* Check Basic Management Control Register first. */ -	if (miiphy_read (addr, PHY_BMCR, ®)) { +	if (miiphy_read (devname, addr, PHY_BMCR, ®)) {  		puts ("PHY duplex read failed, assuming half duplex\n");  		return (HALF);  	}  	/* Check if auto-negotiation is on. */  	if ((reg & PHY_BMCR_AUTON) != 0) {  		/* Get auto-negotiation results. */ -		if (miiphy_read (addr, PHY_ANLPAR, ®)) { +		if (miiphy_read (devname, addr, PHY_ANLPAR, ®)) {  			puts ("PHY AN duplex read failed, assuming half duplex\n");  			return (HALF);  		} @@ -237,13 +447,13 @@ int miiphy_duplex (unsigned char addr)   *   * Determine link status   */ -int miiphy_link (unsigned char addr) +int miiphy_link (char *devname, unsigned char addr)  {  	unsigned short reg;  	/* dummy read; needed to latch some phys */ -	(void)miiphy_read(addr, PHY_BMSR, ®); -	if (miiphy_read (addr, PHY_BMSR, ®)) { +	(void)miiphy_read(devname, addr, PHY_BMSR, ®); +	if (miiphy_read (devname, addr, PHY_BMSR, ®)) {  		puts ("PHY_BMSR read failed, assuming no link\n");  		return (0);  	} |