diff options
| -rw-r--r-- | drivers/net/fec_mxc.c | 144 | ||||
| -rw-r--r-- | drivers/net/fec_mxc.h | 5 | 
2 files changed, 101 insertions, 48 deletions
| diff --git a/drivers/net/fec_mxc.c b/drivers/net/fec_mxc.c index db8ebfaf8..1fdd071e3 100644 --- a/drivers/net/fec_mxc.c +++ b/drivers/net/fec_mxc.c @@ -70,34 +70,15 @@ static void swap_packet(uint32_t *packet, int length)  #endif  /* - * The i.MX28 has two ethernet interfaces, but they are not equal. - * Only the first one can access the MDIO bus. - */ -#ifdef	CONFIG_MX28 -static inline struct ethernet_regs *fec_miiphy_fec_to_eth(struct fec_priv *fec) -{ -	return (struct ethernet_regs *)MXS_ENET0_BASE; -} -#else -static inline struct ethernet_regs *fec_miiphy_fec_to_eth(struct fec_priv *fec) -{ -	return fec->eth; -} -#endif - -/*   * MII-interface related functions   */ -static int fec_miiphy_read(const char *dev, uint8_t phyAddr, uint8_t regAddr, -		uint16_t *retVal) +static int fec_mdio_read(struct ethernet_regs *eth, uint8_t phyAddr, +		uint8_t regAddr)  { -	struct eth_device *edev = eth_get_dev_by_name(dev); -	struct fec_priv *fec = (struct fec_priv *)edev->priv; -	struct ethernet_regs *eth = fec_miiphy_fec_to_eth(fec); -  	uint32_t reg;		/* convenient holder for the PHY register */  	uint32_t phy;		/* convenient holder for the PHY */  	uint32_t start; +	int val;  	/*  	 * reading from any PHY's register is done by properly @@ -129,10 +110,10 @@ static int fec_miiphy_read(const char *dev, uint8_t phyAddr, uint8_t regAddr,  	/*  	 * it's now safe to read the PHY's register  	 */ -	*retVal = readl(ð->mii_data); -	debug("fec_miiphy_read: phy: %02x reg:%02x val:%#x\n", phyAddr, -			regAddr, *retVal); -	return 0; +	val = (unsigned short)readl(ð->mii_data); +	debug("%s: phy: %02x reg:%02x val:%#x\n", __func__, phyAddr, +			regAddr, val); +	return val;  }  static void fec_mii_setspeed(struct fec_priv *fec) @@ -143,16 +124,12 @@ static void fec_mii_setspeed(struct fec_priv *fec)  	 */  	writel((((imx_get_fecclk() / 1000000) + 2) / 5) << 1,  			&fec->eth->mii_speed); -	debug("fec_init: mii_speed %08x\n", -			readl(&fec->eth->mii_speed)); +	debug("%s: mii_speed %08x\n", __func__, readl(&fec->eth->mii_speed));  } -static int fec_miiphy_write(const char *dev, uint8_t phyAddr, uint8_t regAddr, -		uint16_t data) -{ -	struct eth_device *edev = eth_get_dev_by_name(dev); -	struct fec_priv *fec = (struct fec_priv *)edev->priv; -	struct ethernet_regs *eth = fec_miiphy_fec_to_eth(fec); +static int fec_mdio_write(struct ethernet_regs *eth, uint8_t phyAddr, +		uint8_t regAddr, uint16_t data) +{  	uint32_t reg;		/* convenient holder for the PHY register */  	uint32_t phy;		/* convenient holder for the PHY */  	uint32_t start; @@ -178,15 +155,28 @@ static int fec_miiphy_write(const char *dev, uint8_t phyAddr, uint8_t regAddr,  	 * clear MII interrupt bit  	 */  	writel(FEC_IEVENT_MII, ð->ievent); -	debug("fec_miiphy_write: phy: %02x reg:%02x val:%#x\n", phyAddr, +	debug("%s: phy: %02x reg:%02x val:%#x\n", __func__, phyAddr,  			regAddr, data);  	return 0;  } +int fec_phy_read(struct mii_dev *bus, int phyAddr, int dev_addr, int regAddr) +{ +	return fec_mdio_read(bus->priv, phyAddr, regAddr); +} + +int fec_phy_write(struct mii_dev *bus, int phyAddr, int dev_addr, int regAddr, +		u16 data) +{ +	return fec_mdio_write(bus->priv, phyAddr, regAddr, data); +} + +#ifndef CONFIG_PHYLIB  static int miiphy_restart_aneg(struct eth_device *dev)  {  	struct fec_priv *fec = (struct fec_priv *)dev->priv; +	struct ethernet_regs *eth = fec->bus->priv;  	int ret = 0;  	/* @@ -194,19 +184,18 @@ static int miiphy_restart_aneg(struct eth_device *dev)  	 * Reset PHY, then delay 300ns  	 */  #ifdef CONFIG_MX27 -	miiphy_write(dev->name, fec->phy_id, MII_DCOUNTER, 0x00FF); +	fec_mdio_write(eth, fec->phy_id, MII_DCOUNTER, 0x00FF);  #endif -	miiphy_write(dev->name, fec->phy_id, MII_BMCR, -			BMCR_RESET); +	fec_mdio_write(eth, fec->phy_id, MII_BMCR, BMCR_RESET);  	udelay(1000);  	/*  	 * Set the auto-negotiation advertisement register bits  	 */ -	miiphy_write(dev->name, fec->phy_id, MII_ADVERTISE, +	fec_mdio_write(eth, fec->phy_id, MII_ADVERTISE,  			LPA_100FULL | LPA_100HALF | LPA_10FULL |  			LPA_10HALF | PHY_ANLPAR_PSB_802_3); -	miiphy_write(dev->name, fec->phy_id, MII_BMCR, +	fec_mdio_write(eth, fec->phy_id, MII_BMCR,  			BMCR_ANENABLE | BMCR_ANRESTART);  	if (fec->mii_postcall) @@ -218,8 +207,9 @@ static int miiphy_restart_aneg(struct eth_device *dev)  static int miiphy_wait_aneg(struct eth_device *dev)  {  	uint32_t start; -	uint16_t status; +	int status;  	struct fec_priv *fec = (struct fec_priv *)dev->priv; +	struct ethernet_regs *eth = fec->bus->priv;  	/*  	 * Wait for AN completion @@ -231,9 +221,9 @@ static int miiphy_wait_aneg(struct eth_device *dev)  			return -1;  		} -		if (miiphy_read(dev->name, fec->phy_id, -					MII_BMSR, &status)) { -			printf("%s: Autonegotiation failed. status: 0x%04x\n", +		status = fec_mdio_read(eth, fec->phy_id, MII_BMSR); +		if (status < 0) { +			printf("%s: Autonegotiation failed. status: %d\n",  					dev->name, status);  			return -1;  		} @@ -241,6 +231,8 @@ static int miiphy_wait_aneg(struct eth_device *dev)  	return 0;  } +#endif +  static int fec_rx_task_enable(struct fec_priv *fec)  {  	writel(1 << 24, &fec->eth->r_des_active); @@ -372,6 +364,21 @@ static int fec_set_hwaddr(struct eth_device *dev)  	return 0;  } +static void fec_eth_phy_config(struct eth_device *dev) +{ +#ifdef CONFIG_PHYLIB +	struct fec_priv *fec = (struct fec_priv *)dev->priv; +	struct phy_device *phydev; + +	phydev = phy_connect(fec->bus, fec->phy_id, dev, +			PHY_INTERFACE_MODE_RGMII); +	if (phydev) { +		fec->phydev = phydev; +		phy_config(phydev); +	} +#endif +} +  /**   * Start the FEC engine   * @param[in] dev Our device to handle @@ -428,9 +435,21 @@ static int fec_open(struct eth_device *edev)  	}  #endif +#ifdef CONFIG_PHYLIB +	if (!fec->phydev) +		fec_eth_phy_config(edev); +	if (fec->phydev) { +		/* Start up the PHY */ +		phy_startup(fec->phydev); +		speed = fec->phydev->speed; +	} else { +		speed = _100BASET; +	} +#else  	miiphy_wait_aneg(edev);  	speed = miiphy_speed(edev->name, fec->phy_id);  	miiphy_duplex(edev->name, fec->phy_id); +#endif  #ifdef FEC_QUIRK_ENET_MAC  	{ @@ -558,9 +577,10 @@ static int fec_init(struct eth_device *dev, bd_t* bd)  	fec_tbd_init(fec); +#ifndef CONFIG_PHYLIB  	if (fec->xcv_type != SEVENWIRE)  		miiphy_restart_aneg(dev); - +#endif  	fec_open(dev);  	return 0;  } @@ -762,6 +782,7 @@ static int fec_probe(bd_t *bd, int dev_id, int phy_id, uint32_t base_addr)  {  	struct eth_device *edev;  	struct fec_priv *fec; +	struct mii_dev *bus;  	unsigned char ethaddr[6];  	uint32_t start;  	int ret = 0; @@ -836,15 +857,40 @@ static int fec_probe(bd_t *bd, int dev_id, int phy_id, uint32_t base_addr)  	}  	fec->phy_id = phy_id; -	miiphy_register(edev->name, fec_miiphy_read, fec_miiphy_write); - +	bus = mdio_alloc(); +	if (!bus) { +		printf("mdio_alloc failed\n"); +		ret = -ENOMEM; +		goto err3; +	} +	bus->read = fec_phy_read; +	bus->write = fec_phy_write; +	sprintf(bus->name, edev->name); +#ifdef	CONFIG_MX28 +	/* +	 * The i.MX28 has two ethernet interfaces, but they are not equal. +	 * Only the first one can access the MDIO bus. +	 */ +	bus->priv = (struct ethernet_regs *)MXS_ENET0_BASE; +#else +	bus->priv = fec->eth; +#endif +	ret = mdio_register(bus); +	if (ret) { +		printf("mdio_register failed\n"); +		free(bus); +		ret = -ENOMEM; +		goto err3; +	} +	fec->bus = bus;  	eth_register(edev);  	if (fec_get_hwaddr(edev, dev_id, ethaddr) == 0) {  		debug("got MAC%d address from fuse: %pM\n", dev_id, ethaddr);  		memcpy(edev->enetaddr, ethaddr, 6);  	} - +	/* Configure phy */ +	fec_eth_phy_config(edev);  	return ret;  err3: @@ -877,9 +923,11 @@ int fecmxc_initialize_multi(bd_t *bd, int dev_id, int phy_id, uint32_t addr)  	return lout;  } +#ifndef CONFIG_PHYLIB  int fecmxc_register_mii_postcall(struct eth_device *dev, int (*cb)(int))  {  	struct fec_priv *fec = (struct fec_priv *)dev->priv;  	fec->mii_postcall = cb;  	return 0;  } +#endif diff --git a/drivers/net/fec_mxc.h b/drivers/net/fec_mxc.h index af33d2169..2eb78037f 100644 --- a/drivers/net/fec_mxc.h +++ b/drivers/net/fec_mxc.h @@ -286,7 +286,12 @@ struct fec_priv {  	void *base_ptr;  	int dev_id;  	int phy_id; +	struct mii_dev *bus; +#ifdef CONFIG_PHYLIB +	struct phy_device *phydev; +#else  	int (*mii_postcall)(int); +#endif  };  /** |