X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=drivers%2Fnet%2Fks8851_mll.c;h=3ff173ad3391c7ff9a32873d0765761c8b59b356;hb=d5ce2631000be075f3243d1117468cf72d7f43a5;hp=1420ee9dbd9979e0339be8e9e8a9cd1fb11001d5;hpb=b7c6ae2e82832b98572a538ddfe7c365c07f57d9;p=oweals%2Fu-boot.git diff --git a/drivers/net/ks8851_mll.c b/drivers/net/ks8851_mll.c index 1420ee9dbd..3ff173ad33 100644 --- a/drivers/net/ks8851_mll.c +++ b/drivers/net/ks8851_mll.c @@ -28,10 +28,13 @@ * @extra_byte : number of extra byte prepended rx pkt. */ struct ks_net { +#ifndef CONFIG_DM_ETH struct eth_device dev; +#endif phys_addr_t iobase; int bus_width; u16 sharedbus; + u16 rxfc; u8 extra_byte; }; @@ -225,33 +228,31 @@ static inline void ks_read_qmu(struct ks_net *ks, u16 *buf, u32 len) ks_wrreg16(ks, KS_RXQCR, RXQCR_CMD_CNTL); } -static void ks_rcv(struct ks_net *ks, uchar **pv_data) +static int ks_rcv(struct ks_net *ks, uchar *data) { - unsigned int frame_cnt; u16 sts, len; - int i; - - frame_cnt = ks_rdreg16(ks, KS_RXFCTR) >> 8; - - /* read all header information */ - for (i = 0; i < frame_cnt; i++) { - /* Checking Received packet status */ - sts = ks_rdreg16(ks, KS_RXFHSR); - /* Get packet len from hardware */ - len = ks_rdreg16(ks, KS_RXFHBCR); - - if ((sts & RXFSHR_RXFV) && len && (len < RX_BUF_SIZE)) { - /* read data block including CRC 4 bytes */ - ks_read_qmu(ks, (u16 *)(*pv_data), len); - - /* net_rx_packets buffer size is ok (*pv_data) */ - net_process_received_packet(*pv_data, len); - pv_data++; - } else { - ks_wrreg16(ks, KS_RXQCR, RXQCR_CMD_CNTL | RXQCR_RRXEF); - printf(DRIVERNAME ": bad packet\n"); - } + + if (!ks->rxfc) + ks->rxfc = ks_rdreg16(ks, KS_RXFCTR) >> 8; + + if (!ks->rxfc) + return 0; + + /* Checking Received packet status */ + sts = ks_rdreg16(ks, KS_RXFHSR); + /* Get packet len from hardware */ + len = ks_rdreg16(ks, KS_RXFHBCR); + + if ((sts & RXFSHR_RXFV) && len && (len < RX_BUF_SIZE)) { + /* read data block including CRC 4 bytes */ + ks_read_qmu(ks, (u16 *)data, len); + ks->rxfc--; + return len - 4; } + + ks_wrreg16(ks, KS_RXQCR, RXQCR_CMD_CNTL | RXQCR_RRXEF); + printf(DRIVERNAME ": bad packet\n"); + return 0; } /* @@ -395,10 +396,8 @@ static void ks8851_mll_enable(struct ks_net *ks) ks_enable_qmu(ks); } -static int ks8851_mll_init(struct eth_device *dev, bd_t *bd) +static int ks8851_mll_init_common(struct ks_net *ks) { - struct ks_net *ks = container_of(dev, struct ks_net, dev); - if (ks_read_selftest(ks)) { printf(DRIVERNAME ": Selftest failed\n"); return -1; @@ -409,6 +408,8 @@ static int ks8851_mll_init(struct eth_device *dev, bd_t *bd) /* Configure the PHY, initialize the link state */ ks8851_mll_phy_configure(ks); + ks->rxfc = 0; + /* Turn on Tx + Rx */ ks8851_mll_enable(ks); @@ -437,9 +438,8 @@ static void ks_write_qmu(struct ks_net *ks, u8 *pdata, u16 len) do { } while (ks_rdreg16(ks, KS_TXQCR) & TXQCR_METFE); } -static int ks8851_mll_send(struct eth_device *dev, void *packet, int length) +static int ks8851_mll_send_common(struct ks_net *ks, void *packet, int length) { - struct ks_net *ks = container_of(dev, struct ks_net, dev); u8 *data = (u8 *)packet; u16 tmplen = (u16)length; u16 retv; @@ -458,10 +458,8 @@ static int ks8851_mll_send(struct eth_device *dev, void *packet, int length) return -1; } -static void ks8851_mll_halt(struct eth_device *dev) +static void ks8851_mll_halt_common(struct ks_net *ks) { - struct ks_net *ks = container_of(dev, struct ks_net, dev); - ks8851_mll_reset(ks); } @@ -471,17 +469,17 @@ static void ks8851_mll_halt(struct eth_device *dev) * needs to be enough to prevent a packet being discarded while * we are processing the previous one. */ -static int ks8851_mll_recv(struct eth_device *dev) +static int ks8851_mll_recv_common(struct ks_net *ks, uchar *data) { - struct ks_net *ks = container_of(dev, struct ks_net, dev); u16 status; + int ret = 0; status = ks_rdreg16(ks, KS_ISR); ks_wrreg16(ks, KS_ISR, status); - if (status & IRQ_RXI) - ks_rcv(ks, (uchar **)net_rx_packets); + if (ks->rxfc || (status & IRQ_RXI)) + ret = ks_rcv(ks, data); if (status & IRQ_LDI) { u16 pmecr = ks_rdreg16(ks, KS_PMECR); @@ -490,21 +488,61 @@ static int ks8851_mll_recv(struct eth_device *dev) ks_wrreg16(ks, KS_PMECR, pmecr | PMECR_WKEVT_LINK); } - return 0; + return ret; } -static int ks8851_mll_write_hwaddr(struct eth_device *dev) +static void ks8851_mll_write_hwaddr_common(struct ks_net *ks, u8 enetaddr[6]) { - struct ks_net *ks = container_of(dev, struct ks_net, dev); u16 addrl, addrm, addrh; - addrh = (ks->dev.enetaddr[0] << 8) | ks->dev.enetaddr[1]; - addrm = (ks->dev.enetaddr[2] << 8) | ks->dev.enetaddr[3]; - addrl = (ks->dev.enetaddr[4] << 8) | ks->dev.enetaddr[5]; + addrh = (enetaddr[0] << 8) | enetaddr[1]; + addrm = (enetaddr[2] << 8) | enetaddr[3]; + addrl = (enetaddr[4] << 8) | enetaddr[5]; ks_wrreg16(ks, KS_MARH, addrh); ks_wrreg16(ks, KS_MARM, addrm); ks_wrreg16(ks, KS_MARL, addrl); +} + +#ifndef CONFIG_DM_ETH +static int ks8851_mll_init(struct eth_device *dev, bd_t *bd) +{ + struct ks_net *ks = container_of(dev, struct ks_net, dev); + + return ks8851_mll_init_common(ks); +} + +static void ks8851_mll_halt(struct eth_device *dev) +{ + struct ks_net *ks = container_of(dev, struct ks_net, dev); + + ks8851_mll_halt_common(ks); +} + +static int ks8851_mll_send(struct eth_device *dev, void *packet, int length) +{ + struct ks_net *ks = container_of(dev, struct ks_net, dev); + + return ks8851_mll_send_common(ks, packet, length); +} + +static int ks8851_mll_recv(struct eth_device *dev) +{ + struct ks_net *ks = container_of(dev, struct ks_net, dev); + int ret; + + ret = ks8851_mll_recv_common(ks, net_rx_packets[0]); + if (ret) + net_process_received_packet(net_rx_packets[0], ret); + + return ret; +} + +static int ks8851_mll_write_hwaddr(struct eth_device *dev) +{ + struct ks_net *ks = container_of(dev, struct ks_net, dev); + + ks8851_mll_write_hwaddr_common(ks, ks->dev.enetaddr); return 0; } @@ -536,3 +574,103 @@ int ks8851_mll_initialize(u8 dev_num, int base_addr) return 0; } +#else /* ifdef CONFIG_DM_ETH */ +static int ks8851_start(struct udevice *dev) +{ + struct ks_net *ks = dev_get_priv(dev); + + return ks8851_mll_init_common(ks); +} + +static void ks8851_stop(struct udevice *dev) +{ + struct ks_net *ks = dev_get_priv(dev); + + ks8851_mll_halt_common(ks); +} + +static int ks8851_send(struct udevice *dev, void *packet, int length) +{ + struct ks_net *ks = dev_get_priv(dev); + int ret; + + ret = ks8851_mll_send_common(ks, packet, length); + + return ret ? 0 : -ETIMEDOUT; +} + +static int ks8851_recv(struct udevice *dev, int flags, uchar **packetp) +{ + struct ks_net *ks = dev_get_priv(dev); + uchar *data = net_rx_packets[0]; + int ret; + + ret = ks8851_mll_recv_common(ks, data); + if (ret) + *packetp = (void *)data; + + return ret ? ret : -EAGAIN; +} + +static int ks8851_write_hwaddr(struct udevice *dev) +{ + struct ks_net *ks = dev_get_priv(dev); + struct eth_pdata *pdata = dev_get_platdata(dev); + + ks8851_mll_write_hwaddr_common(ks, pdata->enetaddr); + + return 0; +} + +static int ks8851_bind(struct udevice *dev) +{ + return device_set_name(dev, dev->name); +} + +static int ks8851_probe(struct udevice *dev) +{ + struct ks_net *ks = dev_get_priv(dev); + + /* Try to detect chip. Will fail if not present. */ + ks8851_mll_detect_chip(ks); + + return 0; +} + +static int ks8851_ofdata_to_platdata(struct udevice *dev) +{ + struct ks_net *ks = dev_get_priv(dev); + struct eth_pdata *pdata = dev_get_platdata(dev); + + pdata->iobase = devfdt_get_addr(dev); + ks->iobase = pdata->iobase; + + return 0; +} + +static const struct eth_ops ks8851_ops = { + .start = ks8851_start, + .stop = ks8851_stop, + .send = ks8851_send, + .recv = ks8851_recv, + .write_hwaddr = ks8851_write_hwaddr, +}; + +static const struct udevice_id ks8851_ids[] = { + { .compatible = "micrel,ks8851-mll" }, + { } +}; + +U_BOOT_DRIVER(ks8851) = { + .name = "eth_ks8851", + .id = UCLASS_ETH, + .of_match = ks8851_ids, + .bind = ks8851_bind, + .ofdata_to_platdata = ks8851_ofdata_to_platdata, + .probe = ks8851_probe, + .ops = &ks8851_ops, + .priv_auto_alloc_size = sizeof(struct ks_net), + .platdata_auto_alloc_size = sizeof(struct eth_pdata), + .flags = DM_FLAG_ALLOC_PRIV_DMA, +}; +#endif