diff options
Diffstat (limited to 'drivers/net/mpc8xx_fec.c')
-rw-r--r-- | drivers/net/mpc8xx_fec.c | 189 |
1 files changed, 98 insertions, 91 deletions
diff --git a/drivers/net/mpc8xx_fec.c b/drivers/net/mpc8xx_fec.c index 4eb8260281..78337731e1 100644 --- a/drivers/net/mpc8xx_fec.c +++ b/drivers/net/mpc8xx_fec.c @@ -41,7 +41,7 @@ DECLARE_GLOBAL_DATA_PTR; #endif #ifdef CONFIG_SYS_DISCOVER_PHY -static int mii_discover_phy(struct eth_device *dev); +static int mii_discover_phy(struct udevice *dev); #endif int fec8xx_miiphy_read(struct mii_dev *bus, int addr, int devad, int reg); @@ -111,50 +111,24 @@ struct common_buf_desc { static struct common_buf_desc __iomem *rtx; -static int fec_send(struct eth_device *dev, void *packet, int length); -static int fec_recv(struct eth_device *dev); -static int fec_init(struct eth_device *dev, struct bd_info *bd); -static void fec_halt(struct eth_device *dev); #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) static void __mii_init(void); #endif -int fec_initialize(struct bd_info *bis) +static int fec_probe(struct udevice *dev) { - struct eth_device *dev; - struct ether_fcc_info_s *efis; + struct ether_fcc_info_s *efis = dev_get_priv(dev); + int index = dev_get_driver_data(dev); int i; for (i = 0; i < ARRAY_SIZE(ether_fcc_info); i++) { - dev = malloc(sizeof(*dev)); - if (dev == NULL) - hang(); + if (ether_fcc_info[i].ether_index != index) + continue; - memset(dev, 0, sizeof(*dev)); + memcpy(efis, ðer_fcc_info[i], sizeof(*efis)); - /* for FEC1 make sure that the name of the interface is the same - as the old one for compatibility reasons */ - if (i == 0) - strcpy(dev->name, "FEC"); - else - sprintf(dev->name, "FEC%d", - ether_fcc_info[i].ether_index + 1); - - efis = ðer_fcc_info[i]; - - /* - * reset actual phy addr - */ efis->actual_phy_addr = -1; - dev->priv = efis; - dev->init = fec_init; - dev->halt = fec_halt; - dev->send = fec_send; - dev->recv = fec_recv; - - eth_register(dev); - #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) int retval; struct mii_dev *mdiodev = mdio_alloc(); @@ -169,13 +143,13 @@ int fec_initialize(struct bd_info *bis) return retval; #endif } - return 1; + return 0; } -static int fec_send(struct eth_device *dev, void *packet, int length) +static int fec_send(struct udevice *dev, void *packet, int length) { int j, rc; - struct ether_fcc_info_s *efis = dev->priv; + struct ether_fcc_info_s *efis = dev_get_priv(dev); fec_t __iomem *fecp = (fec_t __iomem *)(CONFIG_SYS_IMMR + efis->fecp_offset); @@ -217,59 +191,57 @@ static int fec_send(struct eth_device *dev, void *packet, int length) return rc; } -static int fec_recv(struct eth_device *dev) +static int fec_recv(struct udevice *dev, int flags, uchar **packetp) { - struct ether_fcc_info_s *efis = dev->priv; - fec_t __iomem *fecp = - (fec_t __iomem *)(CONFIG_SYS_IMMR + efis->fecp_offset); int length; - for (;;) { - /* section 16.9.23.2 */ - if (in_be16(&rtx->rxbd[rxIdx].cbd_sc) & BD_ENET_RX_EMPTY) { - length = -1; - break; /* nothing received - leave for() loop */ - } - - length = in_be16(&rtx->rxbd[rxIdx].cbd_datlen); + /* section 16.9.23.2 */ + if (in_be16(&rtx->rxbd[rxIdx].cbd_sc) & BD_ENET_RX_EMPTY) + return -EAGAIN; - if (!(in_be16(&rtx->rxbd[rxIdx].cbd_sc) & 0x003f)) { - uchar *rx = net_rx_packets[rxIdx]; + length = in_be16(&rtx->rxbd[rxIdx].cbd_datlen); - length -= 4; + if (!(in_be16(&rtx->rxbd[rxIdx].cbd_sc) & 0x003f)) { + uchar *rx = net_rx_packets[rxIdx]; #if defined(CONFIG_CMD_CDP) - if ((rx[0] & 1) != 0 && - memcmp((uchar *)rx, net_bcast_ethaddr, 6) != 0 && - !is_cdp_packet((uchar *)rx)) - rx = NULL; + if ((rx[0] & 1) != 0 && + memcmp((uchar *)rx, net_bcast_ethaddr, 6) != 0 && + !is_cdp_packet((uchar *)rx)) + return 0; #endif - /* - * Pass the packet up to the protocol layers. - */ - if (rx != NULL) - net_process_received_packet(rx, length); - } + *packetp = rx; - /* Give the buffer back to the FEC. */ - out_be16(&rtx->rxbd[rxIdx].cbd_datlen, 0); - - /* wrap around buffer index when necessary */ - if ((rxIdx + 1) >= PKTBUFSRX) { - out_be16(&rtx->rxbd[PKTBUFSRX - 1].cbd_sc, - BD_ENET_RX_WRAP | BD_ENET_RX_EMPTY); - rxIdx = 0; - } else { - out_be16(&rtx->rxbd[rxIdx].cbd_sc, BD_ENET_RX_EMPTY); - rxIdx++; - } + return length - 4; + } else { + return 0; + } +} - /* Try to fill Buffer Descriptors */ - /* Descriptor polling active */ - out_be32(&fecp->fec_r_des_active, 0x01000000); +static int fec_free_pkt(struct udevice *dev, uchar *packet, int length) +{ + struct ether_fcc_info_s *efis = dev_get_priv(dev); + fec_t __iomem *fecp = + (fec_t __iomem *)(CONFIG_SYS_IMMR + efis->fecp_offset); + + /* Give the buffer back to the FEC. */ + out_be16(&rtx->rxbd[rxIdx].cbd_datlen, 0); + + /* wrap around buffer index when necessary */ + if ((rxIdx + 1) >= PKTBUFSRX) { + out_be16(&rtx->rxbd[PKTBUFSRX - 1].cbd_sc, + BD_ENET_RX_WRAP | BD_ENET_RX_EMPTY); + rxIdx = 0; + } else { + out_be16(&rtx->rxbd[rxIdx].cbd_sc, BD_ENET_RX_EMPTY); + rxIdx++; } - return length; + /* Try to fill Buffer Descriptors */ + /* Descriptor polling active */ + out_be32(&fecp->fec_r_des_active, 0x01000000); + + return 0; } /************************************************************** @@ -296,9 +268,9 @@ static int fec_recv(struct eth_device *dev) #if defined(CONFIG_RMII) -static inline void fec_10Mbps(struct eth_device *dev) +static inline void fec_10Mbps(struct udevice *dev) { - struct ether_fcc_info_s *efis = dev->priv; + struct ether_fcc_info_s *efis = dev_get_priv(dev); int fecidx = efis->ether_index; uint mask = (fecidx == 0) ? 0x0000010 : 0x0000008; immap_t __iomem *immr = (immap_t __iomem *)CONFIG_SYS_IMMR; @@ -309,9 +281,9 @@ static inline void fec_10Mbps(struct eth_device *dev) setbits_be32(&immr->im_cpm.cp_cptr, mask); } -static inline void fec_100Mbps(struct eth_device *dev) +static inline void fec_100Mbps(struct udevice *dev) { - struct ether_fcc_info_s *efis = dev->priv; + struct ether_fcc_info_s *efis = dev_get_priv(dev); int fecidx = efis->ether_index; uint mask = (fecidx == 0) ? 0x0000010 : 0x0000008; immap_t __iomem *immr = (immap_t __iomem *)CONFIG_SYS_IMMR; @@ -324,9 +296,9 @@ static inline void fec_100Mbps(struct eth_device *dev) #endif -static inline void fec_full_duplex(struct eth_device *dev) +static inline void fec_full_duplex(struct udevice *dev) { - struct ether_fcc_info_s *efis = dev->priv; + struct ether_fcc_info_s *efis = dev_get_priv(dev); fec_t __iomem *fecp = (fec_t __iomem *)(CONFIG_SYS_IMMR + efis->fecp_offset); @@ -334,9 +306,9 @@ static inline void fec_full_duplex(struct eth_device *dev) setbits_be32(&fecp->fec_x_cntrl, FEC_TCNTRL_FDEN); /* FD enable */ } -static inline void fec_half_duplex(struct eth_device *dev) +static inline void fec_half_duplex(struct udevice *dev) { - struct ether_fcc_info_s *efis = dev->priv; + struct ether_fcc_info_s *efis = dev_get_priv(dev); fec_t __iomem *fecp = (fec_t __iomem *)(CONFIG_SYS_IMMR + efis->fecp_offset); @@ -497,9 +469,10 @@ static int fec_reset(fec_t __iomem *fecp) return 0; } -static int fec_init(struct eth_device *dev, struct bd_info *bd) +static int fec_start(struct udevice *dev) { - struct ether_fcc_info_s *efis = dev->priv; + struct eth_pdata *plat = dev_get_plat(dev); + struct ether_fcc_info_s *efis = dev_get_priv(dev); immap_t __iomem *immr = (immap_t __iomem *)CONFIG_SYS_IMMR; fec_t __iomem *fecp = (fec_t __iomem *)(CONFIG_SYS_IMMR + efis->fecp_offset); @@ -529,7 +502,7 @@ static int fec_init(struct eth_device *dev, struct bd_info *bd) /* Set station address */ -#define ea dev->enetaddr +#define ea plat->enetaddr out_be32(&fecp->fec_addr_low, (ea[0] << 24) | (ea[1] << 16) | (ea[2] << 8) | ea[3]); out_be16(&fecp->fec_addr_high, (ea[4] << 8) | ea[5]); @@ -665,9 +638,9 @@ static int fec_init(struct eth_device *dev, struct bd_info *bd) } -static void fec_halt(struct eth_device *dev) +static void fec_stop(struct udevice *dev) { - struct ether_fcc_info_s *efis = dev->priv; + struct ether_fcc_info_s *efis = dev_get_priv(dev); fec_t __iomem *fecp = (fec_t __iomem *)(CONFIG_SYS_IMMR + efis->fecp_offset); int i; @@ -750,7 +723,7 @@ mii_send(uint mii_cmd) #endif #if defined(CONFIG_SYS_DISCOVER_PHY) -static int mii_discover_phy(struct eth_device *dev) +static int mii_discover_phy(struct udevice *dev) { #define MAX_PHY_PASSES 11 uint phyno; @@ -854,3 +827,37 @@ int fec8xx_miiphy_write(struct mii_dev *bus, int addr, int devad, int reg, return 0; } #endif + +static const struct eth_ops fec_ops = { + .start = fec_start, + .send = fec_send, + .recv = fec_recv, + .stop = fec_stop, + .free_pkt = fec_free_pkt, +}; + +static const struct udevice_id fec_ids[] = { +#ifdef CONFIG_ETHER_ON_FEC1 + { + .compatible = "fsl,pq1-fec1", + .data = 0, + }, +#endif +#ifdef CONFIG_ETHER_ON_FEC2 + { + .compatible = "fsl,pq1-fec2", + .data = 1, + }, +#endif + { } +}; + +U_BOOT_DRIVER(fec) = { + .name = "fec", + .id = UCLASS_ETH, + .of_match = fec_ids, + .probe = fec_probe, + .ops = &fec_ops, + .priv_auto = sizeof(struct ether_fcc_info_s), + .plat_auto = sizeof(struct eth_pdata), +}; |