From patchwork Tue Aug 2 11:31:06 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Max Filippov X-Patchwork-Id: 654682 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 3s3Yvy3WNZz9t3p for ; Tue, 2 Aug 2016 21:32:30 +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=apKd/ssD; dkim-atps=neutral Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 7AF3FA7613; Tue, 2 Aug 2016 13:32:26 +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 71CjTF2W1kzC; Tue, 2 Aug 2016 13:32:26 +0200 (CEST) Received: from theia.denx.de (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 74103A75CC; Tue, 2 Aug 2016 13:32:23 +0200 (CEST) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 7C178A7527 for ; Tue, 2 Aug 2016 13:32:17 +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 cPSBMBS2v1tG for ; Tue, 2 Aug 2016 13:32:17 +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-f66.google.com (mail-lf0-f66.google.com [209.85.215.66]) by theia.denx.de (Postfix) with ESMTPS id 37820A74FB for ; Tue, 2 Aug 2016 13:32:14 +0200 (CEST) Received: by mail-lf0-f66.google.com with SMTP id f93so9800043lfi.0 for ; Tue, 02 Aug 2016 04:32:14 -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=F4E2Me2C09gzNRbtzoMsLeEpAgmhjD3WmGMa7Eo4Bw0=; b=apKd/ssDAkdAWltaGAH96/FveROZ2mjT5HqUcD46DFun6sVEbxige8HZIBOYNv8BRF FNLt4LwQdlTUV5HNTIi57jq+dmpWnXNn2SQu3Y2ZrUjYA9iLZXRKxsAGIcg5YvH0htEO kuK0gdNRp3ZmokAhmKwG7dThyK87cMYAxrKutrj/+HNDD5zE+h9as/k51zl4znsBfqIl 7NiZoHomtMhxfpbDb1WjkSfoTTspCvw4Q5/0Fo77X5LBg7XbhAfo2XtDYDt6r08wo99p qk5ovHiPAVIlCprqKJ6xQAFZhMnK6lwYr7c1MJCh7RY/xpNdTV+8tDt8dBxPIK5mxRov vy6w== 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=F4E2Me2C09gzNRbtzoMsLeEpAgmhjD3WmGMa7Eo4Bw0=; b=LJk/2LGGN5jqBsEEf373aaH8iWiA3enN4QLCFBqfmQJcH0UG2sIID9EhuIYAY8pQb0 BCO6cyXeOnouC+HinOcowObVn00wuFRNVwltur3Wcy8qB6UNM5IQUrIcsFSZndqSAbz4 FoI8kle3HaJNZdNyG/LMZ9KFmP4Yy4JV+WDwGC0WUfzCq8n/K9Qy/kSPdz04Ob4nY9qf QfO9M/S/CXjuKcTwlL0EjDY0dkhKAHi0NpmmYDMHHfQDe5FNMv1OJquX96Y9YfTogxoT zk2l27GSFkVNlqSYMUEd/NW4zdUdJjJy+IugNOKHRZgSTahOdu1HGUNdtKiJimCjoYrd xxSg== X-Gm-Message-State: AEkooutSteWs9LET8pH9YF8SZbYRNhpYfN3f09dG5KoyRE4PtqcfO+l8z0DQmzX57noLJg== X-Received: by 10.46.32.5 with SMTP id g5mr17310097ljg.53.1470137533482; Tue, 02 Aug 2016 04:32:13 -0700 (PDT) Received: from octofox.metropolis ([5.19.183.212]) by smtp.gmail.com with ESMTPSA id f69sm417906lji.19.2016.08.02.04.32.12 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Tue, 02 Aug 2016 04:32:12 -0700 (PDT) From: Max Filippov To: u-boot@lists.denx.de Date: Tue, 2 Aug 2016 14:31:06 +0300 Message-Id: <1470137470-6051-4-git-send-email-jcmvbkbc@gmail.com> X-Mailer: git-send-email 2.1.4 In-Reply-To: <1470137470-6051-1-git-send-email-jcmvbkbc@gmail.com> References: <1470137470-6051-1-git-send-email-jcmvbkbc@gmail.com> Cc: Joe Hershberger Subject: [U-Boot] [PATCH 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 --- 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..0225595 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_set_mac_address(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_recv_common(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,47 @@ 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; +} + +#ifndef CONFIG_DM_ETH + +static int ethoc_init(struct eth_device *dev, bd_t *bd) +{ + struct ethoc *priv = (struct ethoc *)dev->priv; + + priv->iobase = ioremap(dev->iobase, ETHOC_IOSIZE); + 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_set_mac_address(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 +510,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_recv_common(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 +549,91 @@ 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; } + +#else + +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_set_mac_address(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) + ethoc_recv_common(priv); + + 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), +}; + +#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 */