From patchwork Fri Aug 5 15:26:17 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Max Filippov X-Patchwork-Id: 656240 X-Patchwork-Delegate: joe.hershberger@gmail.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from theia.denx.de (theia.denx.de [85.214.87.163]) by ozlabs.org (Postfix) with ESMTP id 3s5W0M6kyVz9t0F for ; Sat, 6 Aug 2016 01:28:03 +1000 (AEST) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b=q+FNb+Yt; dkim-atps=neutral Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 7C547A7558; Fri, 5 Aug 2016 17:27:36 +0200 (CEST) Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id CECnPOxb1w9D; Fri, 5 Aug 2016 17:27:36 +0200 (CEST) Received: from theia.denx.de (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id A5380A754E; Fri, 5 Aug 2016 17:27:16 +0200 (CEST) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 9BD764BA7F for ; Fri, 5 Aug 2016 17:27:06 +0200 (CEST) Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id CZ0bzk39BeCG for ; Fri, 5 Aug 2016 17:27:06 +0200 (CEST) X-policyd-weight: NOT_IN_SBL_XBL_SPAMHAUS=-1.5 NOT_IN_SPAMCOP=-1.5 NOT_IN_BL_NJABL=-1.5 (only DNSBL check requested) Received: from mail-lf0-f65.google.com (mail-lf0-f65.google.com [209.85.215.65]) by theia.denx.de (Postfix) with ESMTPS id 8E1B54BA35 for ; Fri, 5 Aug 2016 17:27:00 +0200 (CEST) Received: by mail-lf0-f65.google.com with SMTP id f93so17028036lfi.0 for ; Fri, 05 Aug 2016 08:27:00 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=akopseNIQBRScoNFXAc1a8bNgXPAd/bxkfGOB/AeQUs=; b=q+FNb+YtoX6EbwMiWYrQISp2ZLPY0OtTJBwj3CLNf1LxLzI/8OZhUx7hpp2nB8OxqY eipPvvNUowA8bLoQsiiWzWIMbgo3K3TjE9LQlzwMIPbQA3JU3DGO91SkcyssTnruCevl RxCWaiQvGLr+5GXexTf2LCTHSAslkRORsZrmw8GF6OnoahxRy1qUJ97FEOVqGuWq24Fu 7EPBuhO/ouAKiy3srPzFWAkFoDzU+uDwUwXLVwDEdnf+jU6nVgy9A+0yo9tb7gWRXIHi hNMJPJpB5lXuQzmeRorwzJrJcZ8XFUNOjiT7wnajAAzrLsM5Pc7oJJMzaVTtZifFpBGI Tphw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=akopseNIQBRScoNFXAc1a8bNgXPAd/bxkfGOB/AeQUs=; b=Vq5Wwaws2lDngs1USaTz4dULwsts2V7RFyKHNU6gOUPDzUY+yaAf6Kp5//23Yf4hgH iQfgLifmEQcgZnj+DcguJytqVeAd8bHkztQsDnz/LKYfV5VZpQeg6QXFNd4DAxwaC6n5 T4xax+X5wxmVYTP1cSOn0fb5uNE67m6nGoOVz9jPcrTw8iHjx3hnY0dDn/8nJowTNVaZ ArCsCzsQoN7VtmdhrI1k3LZ2E19PJPx2i/54k0K9273idKuMAVG6HpeQkIq5PrWVbAsr GFlSTVx4HbFOGzTVLBGAy9/ShdSNr7ID0RH83+6Mrhtf3RnB8iN3IbUo+wwIb1MwE8ru ORjg== X-Gm-Message-State: AEkooutSFlTMgScUvwthvKQSkiLlP+K+4tyMjW3SWojytjpnPFGW2zzjxOntVdAe6TxEDA== X-Received: by 10.25.209.195 with SMTP id i186mr27115454lfg.230.1470410819470; Fri, 05 Aug 2016 08:26:59 -0700 (PDT) Received: from octofox.metropolis ([5.19.183.212]) by smtp.gmail.com with ESMTPSA id u11sm3211980lja.12.2016.08.05.08.26.58 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Fri, 05 Aug 2016 08:26:58 -0700 (PDT) From: Max Filippov To: u-boot@lists.denx.de Date: Fri, 5 Aug 2016 18:26:17 +0300 Message-Id: <1470410781-7944-4-git-send-email-jcmvbkbc@gmail.com> X-Mailer: git-send-email 2.1.4 In-Reply-To: <1470410781-7944-1-git-send-email-jcmvbkbc@gmail.com> References: <1470410781-7944-1-git-send-email-jcmvbkbc@gmail.com> Cc: Joe Hershberger Subject: [U-Boot] [PATCH v2 3/7] net/ethoc: add CONFIG_DM_ETH support X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.15 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" Extract reusable parts from ethoc_init, ethoc_set_mac_address, ethoc_send and ethoc_receive, move the rest under #ifdef CONFIG_DM_ETH. Add U_BOOT_DRIVER, eth_ops structure and implement required methods. Signed-off-by: Max Filippov Reviewed-by: Simon Glass Acked-by: Joe Hershberger --- Changes v1->v2: - rename ethoc_set_mac_address to ethoc_write_hwaddr_common; - rename ethoc_recv_common to ethoc_is_new_packet_received; - use positive logic with CONFIG_DM_ETH; - return from DM ethoc_recv when ethoc_is_new_packet_received returns 0; - remove stray ioremap addition. drivers/net/ethoc.c | 221 +++++++++++++++++++++++++++-------- include/dm/platform_data/net_ethoc.h | 20 ++++ 2 files changed, 194 insertions(+), 47 deletions(-) create mode 100644 include/dm/platform_data/net_ethoc.h diff --git a/drivers/net/ethoc.c b/drivers/net/ethoc.c index f5bd1ab..4846c58 100644 --- a/drivers/net/ethoc.c +++ b/drivers/net/ethoc.c @@ -5,13 +5,14 @@ * Copyright (C) 2008-2009 Avionic Design GmbH * Thierry Reding * Copyright (C) 2010 Thomas Chou + * Copyright (C) 2016 Cadence Design Systems Inc. * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. + * SPDX-License-Identifier: GPL-2.0 */ #include +#include +#include #include #include #include @@ -216,11 +217,8 @@ static inline void ethoc_write_bd(struct ethoc *priv, int index, ethoc_write(priv, offset + 4, bd->addr); } -static int ethoc_set_mac_address(struct eth_device *dev) +static int ethoc_write_hwaddr_common(struct ethoc *priv, u8 *mac) { - struct ethoc *priv = (struct ethoc *)dev->priv; - u8 *mac = dev->enetaddr; - ethoc_write(priv, MAC_ADDR0, (mac[2] << 24) | (mac[3] << 16) | (mac[4] << 8) | (mac[5] << 0)); ethoc_write(priv, MAC_ADDR1, (mac[0] << 8) | (mac[1] << 0)); @@ -305,11 +303,8 @@ static int ethoc_reset(struct ethoc *priv) return 0; } -static int ethoc_init(struct eth_device *dev, bd_t * bd) +static int ethoc_init_common(struct ethoc *priv) { - struct ethoc *priv = (struct ethoc *)dev->priv; - printf("ethoc\n"); - priv->num_tx = 1; priv->num_rx = PKTBUFSRX; ethoc_write(priv, TX_BD_NUM, priv->num_tx); @@ -354,36 +349,43 @@ static int ethoc_update_rx_stats(struct ethoc_bd *bd) return ret; } -static int ethoc_rx(struct ethoc *priv, int limit) +static int ethoc_rx_common(struct ethoc *priv, uchar **packetp) { - int count; - - for (count = 0; count < limit; ++count) { - u32 entry; - struct ethoc_bd bd; + u32 entry; + struct ethoc_bd bd; - entry = priv->num_tx + (priv->cur_rx % priv->num_rx); - ethoc_read_bd(priv, entry, &bd); - if (bd.stat & RX_BD_EMPTY) - break; + entry = priv->num_tx + (priv->cur_rx % priv->num_rx); + ethoc_read_bd(priv, entry, &bd); + if (bd.stat & RX_BD_EMPTY) + return -EAGAIN; + + debug("%s(): RX buffer %d, %x received\n", + __func__, priv->cur_rx, bd.stat); + if (ethoc_update_rx_stats(&bd) == 0) { + int size = bd.stat >> 16; + + size -= 4; /* strip the CRC */ + *packetp = (void *)bd.addr; + return size; + } else { + return 0; + } +} - debug("%s(): RX buffer %d, %x received\n", - __func__, priv->cur_rx, bd.stat); - if (ethoc_update_rx_stats(&bd) == 0) { - int size = bd.stat >> 16; - size -= 4; /* strip the CRC */ - net_process_received_packet((void *)bd.addr, size); - } +static int ethoc_is_new_packet_received(struct ethoc *priv) +{ + u32 pending; - /* clear the buffer descriptor so it can be reused */ - flush_dcache_range(bd.addr, bd.addr + PKTSIZE_ALIGN); - bd.stat &= ~RX_BD_STATS; - bd.stat |= RX_BD_EMPTY; - ethoc_write_bd(priv, entry, &bd); - priv->cur_rx++; + pending = ethoc_read(priv, INT_SOURCE); + ethoc_ack_irq(priv, pending); + if (pending & INT_MASK_BUSY) + debug("%s(): packet dropped\n", __func__); + if (pending & INT_MASK_RX) { + debug("%s(): rx irq\n", __func__); + return 1; } - return count; + return 0; } static int ethoc_update_tx_stats(struct ethoc_bd *bd) @@ -413,9 +415,8 @@ static void ethoc_tx(struct ethoc *priv) (void)ethoc_update_tx_stats(&bd); } -static int ethoc_send(struct eth_device *dev, void *packet, int length) +static int ethoc_send_common(struct ethoc *priv, void *packet, int length) { - struct ethoc *priv = (struct ethoc *)dev->priv; struct ethoc_bd bd; u32 entry; u32 pending; @@ -460,6 +461,126 @@ static int ethoc_send(struct eth_device *dev, void *packet, int length) return 0; } +static int ethoc_free_pkt_common(struct ethoc *priv) +{ + u32 entry; + struct ethoc_bd bd; + + entry = priv->num_tx + (priv->cur_rx % priv->num_rx); + ethoc_read_bd(priv, entry, &bd); + + /* clear the buffer descriptor so it can be reused */ + flush_dcache_range(bd.addr, bd.addr + PKTSIZE_ALIGN); + bd.stat &= ~RX_BD_STATS; + bd.stat |= RX_BD_EMPTY; + ethoc_write_bd(priv, entry, &bd); + priv->cur_rx++; + + return 0; +} + +#ifdef CONFIG_DM_ETH + +static int ethoc_write_hwaddr(struct udevice *dev) +{ + struct ethoc_eth_pdata *pdata = dev_get_platdata(dev); + struct ethoc *priv = dev_get_priv(dev); + u8 *mac = pdata->eth_pdata.enetaddr; + + return ethoc_write_hwaddr_common(priv, mac); +} + +static int ethoc_send(struct udevice *dev, void *packet, int length) +{ + return ethoc_send_common(dev_get_priv(dev), packet, length); +} + +static int ethoc_free_pkt(struct udevice *dev, uchar *packet, int length) +{ + return ethoc_free_pkt_common(dev_get_priv(dev)); +} + +static int ethoc_recv(struct udevice *dev, int flags, uchar **packetp) +{ + struct ethoc *priv = dev_get_priv(dev); + + if (flags & ETH_RECV_CHECK_DEVICE) + if (!ethoc_is_new_packet_received(priv)) + return -EAGAIN; + + return ethoc_rx_common(priv, packetp); +} + +static int ethoc_start(struct udevice *dev) +{ + return ethoc_init_common(dev_get_priv(dev)); +} + +static void ethoc_stop(struct udevice *dev) +{ + struct ethoc *priv = dev_get_priv(dev); + + ethoc_disable_rx_and_tx(priv); +} + +static int ethoc_probe(struct udevice *dev) +{ + struct ethoc_eth_pdata *pdata = dev_get_platdata(dev); + struct ethoc *priv = dev_get_priv(dev); + + priv->iobase = ioremap(pdata->eth_pdata.iobase, ETHOC_IOSIZE); + return 0; +} + +static int ethoc_remove(struct udevice *dev) +{ + struct ethoc *priv = dev_get_priv(dev); + + iounmap(priv->iobase); + return 0; +} + +static const struct eth_ops ethoc_ops = { + .start = ethoc_start, + .stop = ethoc_stop, + .send = ethoc_send, + .recv = ethoc_recv, + .free_pkt = ethoc_free_pkt, + .write_hwaddr = ethoc_write_hwaddr, +}; + +U_BOOT_DRIVER(ethoc) = { + .name = "ethoc", + .id = UCLASS_ETH, + .probe = ethoc_probe, + .remove = ethoc_remove, + .ops = ðoc_ops, + .priv_auto_alloc_size = sizeof(struct ethoc), + .platdata_auto_alloc_size = sizeof(struct ethoc_eth_pdata), +}; + +#else + +static int ethoc_init(struct eth_device *dev, bd_t *bd) +{ + struct ethoc *priv = (struct ethoc *)dev->priv; + + return ethoc_init_common(priv); +} + +static int ethoc_write_hwaddr(struct eth_device *dev) +{ + struct ethoc *priv = (struct ethoc *)dev->priv; + u8 *mac = dev->enetaddr; + + return ethoc_write_hwaddr_common(priv, mac); +} + +static int ethoc_send(struct eth_device *dev, void *packet, int length) +{ + return ethoc_send_common(dev->priv, packet, length); +} + static void ethoc_halt(struct eth_device *dev) { ethoc_disable_rx_and_tx(dev->priv); @@ -468,17 +589,21 @@ static void ethoc_halt(struct eth_device *dev) static int ethoc_recv(struct eth_device *dev) { struct ethoc *priv = (struct ethoc *)dev->priv; - u32 pending; + int count; - pending = ethoc_read(priv, INT_SOURCE); - ethoc_ack_irq(priv, pending); - if (pending & INT_MASK_BUSY) - debug("%s(): packet dropped\n", __func__); - if (pending & INT_MASK_RX) { - debug("%s(): rx irq\n", __func__); - ethoc_rx(priv, PKTBUFSRX); - } + if (!ethoc_is_new_packet_received(priv)) + return 0; + + for (count = 0; count < PKTBUFSRX; ++count) { + uchar *packetp; + int size = ethoc_rx_common(priv, &packetp); + if (size < 0) + break; + if (size > 0) + net_process_received_packet(packetp, size); + ethoc_free_pkt_common(priv); + } return 0; } @@ -503,10 +628,12 @@ int ethoc_initialize(u8 dev_num, int base_addr) dev->halt = ethoc_halt; dev->send = ethoc_send; dev->recv = ethoc_recv; - dev->write_hwaddr = ethoc_set_mac_address; + dev->write_hwaddr = ethoc_write_hwaddr; sprintf(dev->name, "%s-%hu", "ETHOC", dev_num); priv->iobase = ioremap(dev->iobase, ETHOC_IOSIZE); eth_register(dev); return 1; } + +#endif diff --git a/include/dm/platform_data/net_ethoc.h b/include/dm/platform_data/net_ethoc.h new file mode 100644 index 0000000..1d8c73c --- /dev/null +++ b/include/dm/platform_data/net_ethoc.h @@ -0,0 +1,20 @@ +/* + * Copyright (C) 2016 Cadence Design Systems Inc. + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#ifndef _ETHOC_H +#define _ETHOC_H + +#include + +#ifdef CONFIG_DM_ETH + +struct ethoc_eth_pdata { + struct eth_pdata eth_pdata; +}; + +#endif + +#endif /* _ETHOC_H */