[U-Boot] [PATCH 1/3 v3] Bit-banged MII driver with multi-bus support.

Ben Warren biggerbadderben at gmail.com
Mon Oct 5 08:27:44 CEST 2009


Hi Luigi,

Luigi 'Comio' Mantellini wrote:
> From: Luigi 'Comio' Mantellini <luigi.mantellini at idf-hit.com>
>
>   
Please add some descriptive information here.  This is a big patch and 
deserves a changelong
> Signed-off-by: Luigi 'Comio' Mantellini <luigi.mantellini at idf-hit.com>
> ---
>  drivers/net/phy/miiphybb.c |  324 +++++++++++++++++++++++++++++++-------------
>  include/miiphy.h           |   22 +++
>  2 files changed, 250 insertions(+), 96 deletions(-)
>
> diff --git a/drivers/net/phy/miiphybb.c b/drivers/net/phy/miiphybb.c
> index b77c917..1ed27f1 100644
> --- a/drivers/net/phy/miiphybb.c
> +++ b/drivers/net/phy/miiphybb.c
> @@ -1,4 +1,7 @@
>  /*
> + * (C) Copyright 2009 Industrie Dial Face S.p.A.
> + * Luigi 'Comio' Mantellini <luigi.mantellini at idf-hit.com>
> + *
>   * (C) Copyright 2001
>   * Gerald Van Baren, Custom IDEAS, vanbaren at cideas.com.
>   *
> @@ -29,18 +32,137 @@
>  #include <common.h>
>  #include <ioports.h>
>  #include <ppc_asm.tmpl>
> +#include <miiphy.h>
> +
> +#define BBMII_RELOATE(v,off) (v += (v?off:0))
>   
s/RELOATE/RELOCATE/

Please apply globally
> +
> +DECLARE_GLOBAL_DATA_PTR;
> +
> +#ifndef CONFIG_BITBANGMII_MULTI
> +/*
> + * If CONFIG_BITBANGMII_MULTI is not defined we use a
> + * compatibility layer with the previous miiphybb implementation
> + * based on macros usage.
> + *
> + */
> +static int bb_mii_init_wrap(struct bbmiibus *bus)
> +{
> +#ifdef MII_INIT
> +	MII_INIT;
> +#endif
> +	return 0;
> +}
> +
> +static int bb_mdio_active_wrap(struct bbmiibus *bus)
> +{
> +#ifdef MDIO_DECLARE
> +	MDIO_DECLARE;
> +#endif
> +	MDIO_ACTIVE;
> +	return 0;
> +}
> +
> +static int bb_mdio_tristate_wrap(struct bbmiibus *bus)
> +{
> +#ifdef MDIO_DECLARE
> +	MDIO_DECLARE;
> +#endif
> +	MDIO_TRISTATE;
> +	return 0;
> +}
> +
> +static int bb_set_mdio_wrap(struct bbmiibus *bus, int v)
> +{
> +#ifdef MDIO_DECLARE
> +	MDIO_DECLARE;
> +#endif
> +	MDIO (v);
> +	return 0;
> +}
> +
> +static int bb_get_mdio_wrap(struct bbmiibus *bus, int *v)
> +{
> +#ifdef MDIO_DECLARE
> +	MDIO_DECLARE;
> +#endif
> +	*v = MDIO_READ;
> +	return 0;
> +}
> +
> +static int bb_set_mdc_wrap(struct bbmiibus *bus, int v)
> +{
> +#ifdef MDC_DECLARE
> +	MDC_DECLARE;
> +#endif
> +	MDC (v);
> +	return 0;
> +}
> +
> +static int bb_delay_wrap(struct bbmiibus *bus)
> +{
> +	MIIDELAY;
> +	return 0;
> +}
> +
> +struct bbmiibus bbmiibusses[] = {
>   
Elsewhere, you name things 'bb_mii', but here it's 'bbmii'.  I 
personally prefer adding the underscores, but please be consistent.
> +	{
> +		.name = BB_MII_DEVNAME,
> +		.init = bb_mii_init_wrap,
> +		.mdio_active = bb_mdio_active_wrap,
> +		.mdio_tristate = bb_mdio_tristate_wrap,
> +		.set_mdio = bb_set_mdio_wrap,
> +		.get_mdio = bb_get_mdio_wrap,
> +		.set_mdc = bb_set_mdc_wrap,
> +		.delay = bb_delay_wrap,
> +	}
> +};
> +#endif
> +
> +void bb_miiphy_init(void)
> +{
> +	int i;
> +	for (i = 0; i < sizeof(bbmiibusses)/sizeof(bbmiibusses[0]); i++) {
> +#if !defined(CONFIG_RELOC_FIXUP_WORKS)
> +		/* Reloate the hooks pointers*/
>   
s/Reloate/Relocate/
s/hooks/hook/
> +		BBMII_RELOATE(bbmiibusses[i].init, gd->reloc_off);
> +		BBMII_RELOATE(bbmiibusses[i].mdio_active, gd->reloc_off);
> +		BBMII_RELOATE(bbmiibusses[i].mdio_tristate, gd->reloc_off);
> +		BBMII_RELOATE(bbmiibusses[i].set_mdio, gd->reloc_off);
> +		BBMII_RELOATE(bbmiibusses[i].get_mdio, gd->reloc_off);
> +		BBMII_RELOATE(bbmiibusses[i].set_mdc, gd->reloc_off);
> +		BBMII_RELOATE(bbmiibusses[i].delay, gd->reloc_off);
> +#endif
> +
> +		if (bbmiibusses[i].init != NULL) {
> +			bbmiibusses[i].init(&bbmiibusses[i]);
> +		}
> +	}
> +}
> +
> +static inline struct bbmiibus *bb_miiphy_getbus(char *devname)
> +{
> +#ifdef CONFIG_BITBANGMII_MULTI
> +	/* Search the correct bus */
> +	for (j = 0; j < sizeof(bbmiibusses)/sizeof(bbmmis[0]); j++) {
> +		if (!strcmp(bbmiibusses[i].name, devname)) {
> +			return &bbmiibusses[i];
> +		}
> +	}
> +	return NULL;
> +#else
> +	/* We have just one bitbanging bus */
> +	return &bbmiibusses[0];
> +#endif
> +}
>  
>  /*****************************************************************************
>   *
>   * Utility to send the preamble, address, and register (common to read
>   * and write).
>   */
> -static void miiphy_pre (char read, unsigned char addr, unsigned char reg)
> +static void miiphy_pre (struct bbmiibus *bus, char read, unsigned char addr, unsigned char reg)
>   
This line's too long (please keep < 78 characters).  Apply globally
>  {
>  	int j;			/* counter */
> -#if !(defined(CONFIG_EP8248) || defined(CONFIG_EP82XXM))
> -	volatile ioport_t *iop = ioport_addr ((immap_t *) CONFIG_SYS_IMMR, MDIO_PORT);
> -#endif
>  
>  	/*
>  	 * Send a 32 bit preamble ('1's) with an extra '1' bit for good measure.
> @@ -50,67 +172,66 @@ static void miiphy_pre (char read, unsigned char addr, unsigned char reg)
>  	 * but it is safer and will be much more robust.
>  	 */
>  
> -	MDIO_ACTIVE;
> -	MDIO (1);
> +	bus->mdio_active(bus);
> +	bus->set_mdio (bus, 1);
>  	for (j = 0; j < 32; j++) {
> -		MDC (0);
> -		MIIDELAY;
> -		MDC (1);
> -		MIIDELAY;
> +		bus->set_mdc (bus, 0);
> +		bus->delay(bus);
> +		bus->set_mdc (bus, 1);
> +		bus->delay(bus);
>  	}
>  
>  	/* send the start bit (01) and the read opcode (10) or write (10) */
> -	MDC (0);
> -	MDIO (0);
> -	MIIDELAY;
> -	MDC (1);
> -	MIIDELAY;
> -	MDC (0);
> -	MDIO (1);
> -	MIIDELAY;
> -	MDC (1);
> -	MIIDELAY;
> -	MDC (0);
> -	MDIO (read);
> -	MIIDELAY;
> -	MDC (1);
> -	MIIDELAY;
> -	MDC (0);
> -	MDIO (!read);
> -	MIIDELAY;
> -	MDC (1);
> -	MIIDELAY;
> +	bus->set_mdc (bus, 0);
> +	bus->set_mdio (bus, 0);
> +	bus->delay(bus);
>   
Please be consistent with whitespace.  I prefer no space before the 
opening paren, although I think Wolfgang likes that.   He's funny that 
way.  Note that this only relates to function calls.  Control logic (if, 
for, while etc.) should always have a space before the opening paren.
> +	bus->set_mdc (bus, 1);
> +	bus->delay(bus);
> +	bus->set_mdc (bus, 0);
> +	bus->set_mdio (bus, 1);
> +	bus->delay(bus);
> +	bus->set_mdc (bus, 1);
> +	bus->delay(bus);
> +	bus->set_mdc (bus, 0);
> +	bus->set_mdio (bus, read);
> +	bus->delay(bus);
> +	bus->set_mdc (bus, 1);
> +	bus->delay(bus);
> +	bus->set_mdc (bus, 0);
> +	bus->set_mdio (bus, !read);
> +	bus->delay(bus);
> +	bus->set_mdc (bus, 1);
> +	bus->delay(bus);
>  
>  	/* send the PHY address */
>  	for (j = 0; j < 5; j++) {
> -		MDC (0);
> +		bus->set_mdc (bus, 0);
>  		if ((addr & 0x10) == 0) {
> -			MDIO (0);
> +			bus->set_mdio (bus, 0);
>  		} else {
> -			MDIO (1);
> +			bus->set_mdio (bus, 1);
>  		}
> -		MIIDELAY;
> -		MDC (1);
> -		MIIDELAY;
> +		bus->delay(bus);
> +		bus->set_mdc (bus, 1);
> +		bus->delay(bus);
>  		addr <<= 1;
>  	}
>  
>  	/* send the register address */
>  	for (j = 0; j < 5; j++) {
> -		MDC (0);
> +		bus->set_mdc (bus, 0);
>  		if ((reg & 0x10) == 0) {
> -			MDIO (0);
> +			bus->set_mdio (bus, 0);
>  		} else {
> -			MDIO (1);
> +			bus->set_mdio (bus, 1);
>  		}
> -		MIIDELAY;
> -		MDC (1);
> -		MIIDELAY;
> +		bus->delay(bus);
> +		bus->set_mdc (bus, 1);
> +		bus->delay(bus);
>  		reg <<= 1;
>  	}
>  }
>  
> -
>  /*****************************************************************************
>   *
>   * Read a MII PHY register.
> @@ -122,59 +243,66 @@ int bb_miiphy_read (char *devname, unsigned char addr,
>  		unsigned char reg, unsigned short *value)
>  {
>  	short rdreg;		/* register working value */
> +	int v;
>  	int j;			/* counter */
> -#if !(defined(CONFIG_EP8248) || defined(CONFIG_EP82XXM))
> -	volatile ioport_t *iop = ioport_addr ((immap_t *) CONFIG_SYS_IMMR, MDIO_PORT);
> -#endif
> +	struct bbmiibus *bus;
> +
> +	bus = bb_miiphy_getbus(devname);
> +	if (bus == NULL) {
> +		/* Bus not found! */
>   
Comment's kinda superfluous...
> +		return -1;
> +	}
>  
>  	if (value == NULL) {
>  		puts("NULL value pointer\n");
>  		return (-1);
>  	}
>  
> -	miiphy_pre (1, addr, reg);
> +	miiphy_pre (bus, 1, addr, reg);
>  
>  	/* tri-state our MDIO I/O pin so we can read */
> -	MDC (0);
> -	MDIO_TRISTATE;
> -	MIIDELAY;
> -	MDC (1);
> -	MIIDELAY;
> +	bus->set_mdc (bus, 0);
> +	bus->mdio_tristate(bus);
> +	bus->delay(bus);
> +	bus->set_mdc (bus, 1);
> +	bus->delay(bus);
>  
>  	/* check the turnaround bit: the PHY should be driving it to zero */
> -	if (MDIO_READ != 0) {
> +	bus->get_mdio(bus, &v);
> +	if (v != 0) {
>  		/* puts ("PHY didn't drive TA low\n"); */
>  		for (j = 0; j < 32; j++) {
> -			MDC (0);
> -			MIIDELAY;
> -			MDC (1);
> -			MIIDELAY;
> +			bus->set_mdc (bus, 0);
> +			bus->delay(bus);
> +			bus->set_mdc (bus, 1);
> +			bus->delay(bus);
>  		}
>  		/* There is no PHY, set value to 0xFFFF and return */
>  		*value = 0xFFFF;
>  		return (-1);
>  	}
>  
> -	MDC (0);
> -	MIIDELAY;
> +	bus->set_mdc (bus, 0);
> +	bus->delay(bus);
>  
>  	/* read 16 bits of register data, MSB first */
>  	rdreg = 0;
>  	for (j = 0; j < 16; j++) {
> -		MDC (1);
> -		MIIDELAY;
> +		bus->set_mdc (bus, 1);
> +		bus->delay(bus);
>  		rdreg <<= 1;
> -		rdreg |= MDIO_READ;
> -		MDC (0);
> -		MIIDELAY;
> +		bus->get_mdio(bus, &v);
> +		rdreg |= (v & 0x1);
> +		bus->set_mdc (bus, 0);
> +		bus->delay(bus);
>  	}
>  
> -	MDC (1);
> -	MIIDELAY;
> -	MDC (0);
> -	MIIDELAY;
> -	MDC (1);
> -	MIIDELAY;
> +	bus->set_mdc (bus, 1);
> +	bus->delay(bus);
> +	bus->set_mdc (bus, 0);
> +	bus->delay(bus);
> +	bus->set_mdc (bus, 1);
> +	bus->delay(bus);
>  
>  	*value = rdreg;
>  
> @@ -196,47 +324,51 @@ int bb_miiphy_read (char *devname, unsigned char addr,
>  int bb_miiphy_write (char *devname, unsigned char addr,
>  		unsigned char reg, unsigned short value)
>  {
> +	struct bbmiibus *bus;
>  	int j;			/* counter */
> -#if !(defined(CONFIG_EP8248) || defined(CONFIG_EP82XXM))
> -	volatile ioport_t *iop = ioport_addr ((immap_t *) CONFIG_SYS_IMMR, MDIO_PORT);
> -#endif
>  
> -	miiphy_pre (0, addr, reg);
> +	bus = bb_miiphy_getbus(devname);
> +	if (bus == NULL) {
> +		/* Bus not found! */
> +		return -1;
> +	}
> +
> +	miiphy_pre (bus, 0, addr, reg);
>  
>  	/* send the turnaround (10) */
> -	MDC (0);
> -	MDIO (1);
> -	MIIDELAY;
> -	MDC (1);
> -	MIIDELAY;
> -	MDC (0);
> -	MDIO (0);
> -	MIIDELAY;
> -	MDC (1);
> -	MIIDELAY;
> +	bus->set_mdc (bus, 0);
> +	bus->set_mdio (bus, 1);
> +	bus->delay(bus);
> +	bus->set_mdc (bus, 1);
> +	bus->delay(bus);
> +	bus->set_mdc (bus, 0);
> +	bus->set_mdio (bus, 0);
> +	bus->delay(bus);
> +	bus->set_mdc (bus, 1);
> +	bus->delay(bus);
>  
>  	/* write 16 bits of register data, MSB first */
>  	for (j = 0; j < 16; j++) {
> -		MDC (0);
> +		bus->set_mdc (bus, 0);
>  		if ((value & 0x00008000) == 0) {
> -			MDIO (0);
> +			bus->set_mdio (bus, 0);
>  		} else {
> -			MDIO (1);
> +			bus->set_mdio (bus, 1);
>  		}
> -		MIIDELAY;
> -		MDC (1);
> -		MIIDELAY;
> +		bus->delay(bus);
> +		bus->set_mdc (bus, 1);
> +		bus->delay(bus);
>  		value <<= 1;
>  	}
>  
>  	/*
>  	 * Tri-state the MDIO line.
>  	 */
> -	MDIO_TRISTATE;
> -	MDC (0);
> -	MIIDELAY;
> -	MDC (1);
> -	MIIDELAY;
> +	bus->mdio_tristate(bus);
> +	bus->set_mdc (bus, 0);
> +	bus->delay(bus);
> +	bus->set_mdc (bus, 1);
> +	bus->delay(bus);
>  
>  	return 0;
> -}
> +}
> \ No newline at end of file
> diff --git a/include/miiphy.h b/include/miiphy.h
> index fa33ec7..478c050 100644
> --- a/include/miiphy.h
> +++ b/include/miiphy.h
> @@ -19,6 +19,8 @@
>  |
>  |	COPYRIGHT   I B M   CORPORATION 1999
>  |	LICENSED MATERIAL  -  PROGRAM PROPERTY OF I B M
> +|
> +|   Additions (C) Copyright 2009 Industrie Dial Face S.p.A.
>  +----------------------------------------------------------------------------*/
>  /*----------------------------------------------------------------------------+
>  |
> @@ -61,12 +63,32 @@ char *miiphy_get_current_dev (void);
>  
>  void miiphy_listdev (void);
>  
> +#ifdef CONFIG_BITBANGMII
> +
>  #define BB_MII_DEVNAME	"bbmii"
>  
> +struct bbmiibus {
> +	char name[NAMESIZE];
> +	int (*init)(struct bbmiibus *bus);
> +	int (*mdio_active)(struct bbmiibus *bus);
> +	int (*mdio_tristate)(struct bbmiibus *bus);
> +	int (*set_mdio)(struct bbmiibus *bus, int v);
> +	int (*get_mdio)(struct bbmiibus *bus, int *v);
> +	int (*set_mdc)(struct bbmiibus *bus, int v);
> +	int (*delay)(struct bbmiibus *bus);
> +#ifdef CONFIG_BITBANGMII_MULTI
> +	void *priv;
> +#endif
> +};
> +
> +extern struct bbmiibus bbmiibusses[];
> +
> +void bb_miiphy_init (void);
>  int bb_miiphy_read (char *devname, unsigned char addr,
>  		    unsigned char reg, unsigned short *value);
>  int bb_miiphy_write (char *devname, unsigned char addr,
>  		     unsigned char reg, unsigned short value);
> +#endif
>  
>  /* phy seed setup */
>  #define AUTO			99
>   
Thanks for this submission.  It's a really big improvement.

regards,
Ben


More information about the U-Boot mailing list