From patchwork Sat Jan 31 09:28:04 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Heiner Kallweit X-Patchwork-Id: 435109 X-Patchwork-Delegate: nbd@openwrt.org Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from arrakis.dune.hu (arrakis.dune.hu [78.24.191.176]) (using TLSv1.1 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 7799E1402CF for ; Sat, 31 Jan 2015 20:30:31 +1100 (AEDT) Received: from arrakis.dune.hu (localhost [127.0.0.1]) by arrakis.dune.hu (Postfix) with ESMTP id 0DEA02801E8; Sat, 31 Jan 2015 10:27:33 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on arrakis.dune.hu X-Spam-Level: X-Spam-Status: No, score=-1.2 required=5.0 tests=BAYES_00, FREEMAIL_ENVFROM_END_DIGIT, FREEMAIL_FROM, T_DKIM_INVALID autolearn=no version=3.3.2 Received: from arrakis.dune.hu (localhost [127.0.0.1]) by arrakis.dune.hu (Postfix) with ESMTP id 1B02A2801E8 for ; Sat, 31 Jan 2015 10:27:12 +0100 (CET) X-policyd-weight: using cached result; rate: -8.5 Received: from mail-wi0-f173.google.com (mail-wi0-f173.google.com [209.85.212.173]) by arrakis.dune.hu (Postfix) with ESMTPS for ; Sat, 31 Jan 2015 10:27:11 +0100 (CET) Received: by mail-wi0-f173.google.com with SMTP id r20so7628075wiv.0 for ; Sat, 31 Jan 2015 01:29:40 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=message-id:date:from:user-agent:mime-version:to:cc:subject :content-type:content-transfer-encoding; bh=K/y6mMGYQn1z5aopcf9HB0pqXuVH8+pBzgf8IEXyGHI=; b=lmTRdCb64crkxxFNiRat/PST+8Pm0jIOJttE8uTfZzhl0uQ7wHxji8kPFIQKz2XyFz d4YXlFiObJuIss/Zarbjwt3CwJAJMRFPA4DqKHWYImdHucMRfhDVLO8nrSZOQXHtvoZh 1dXsaDpw7BOwBhZko9w9mNOD5gmYZEYO8QM5fblRDNBALNgeUBuiYd22eP0m8TySqFkN sV2bVu+FS546gP1b11rClPrP0YcNKfTwep6ryF1Q+2bDeZWzFHT8/HU9QowHhodmk9t+ RvwRGXRi4Y8yg6SMgeb+Z/T8KzswEDoUT/hgiw4d1/V5S7+uG4rfKBBYrjKNe5PjaMsu 4ocg== X-Received: by 10.181.13.176 with SMTP id ez16mr2947138wid.78.1422696579987; Sat, 31 Jan 2015 01:29:39 -0800 (PST) Received: from ?IPv6:2003:63:231f:ff00:a574:a623:8907:1aab? (p20030063231FFF00A574A62389071AAB.dip0.t-ipconnect.de. [2003:63:231f:ff00:a574:a623:8907:1aab]) by mx.google.com with ESMTPSA id fo15sm10473074wic.19.2015.01.31.01.29.38 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Sat, 31 Jan 2015 01:29:39 -0800 (PST) Message-ID: <54CCA024.2050101@gmail.com> Date: Sat, 31 Jan 2015 10:28:04 +0100 From: Heiner Kallweit User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:31.0) Gecko/20100101 Thunderbird/31.4.0 MIME-Version: 1.0 To: Felix Fietkau Cc: OpenWrt Development List Subject: [OpenWrt-Devel] [PATCH 1/4] ar8216: add reading ARL table for AR8216/AR8236/AR8316 X-BeenThere: openwrt-devel@lists.openwrt.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: OpenWrt Development List List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: openwrt-devel-bounces@lists.openwrt.org Sender: "openwrt-devel" Adds the chip-specific part of reading ARL table for AR8216/AR8236/AR8316. It's based on the AR8236 datasheet and compile-tested only as I couldn't find datasheets for AR8216/AR8316 and don't own devices with these chips. The existing ar8216_atu_flush implementation was used for all three chip types, therefore I guess they share a common ATU register layout. More testing would be appreciated. Signed-off-by: Heiner Kallweit --- .../linux/generic/files/drivers/net/phy/ar8216.c | 81 ++++++++++++++++++++-- .../linux/generic/files/drivers/net/phy/ar8216.h | 25 +++++-- 2 files changed, 98 insertions(+), 8 deletions(-) diff --git a/target/linux/generic/files/drivers/net/phy/ar8216.c b/target/linux/generic/files/drivers/net/phy/ar8216.c index e39d540..595f144 100644 --- a/target/linux/generic/files/drivers/net/phy/ar8216.c +++ b/target/linux/generic/files/drivers/net/phy/ar8216.c @@ -598,10 +598,10 @@ ar8216_atu_flush(struct ar8xxx_priv *priv) { int ret; - ret = ar8216_wait_bit(priv, AR8216_REG_ATU, AR8216_ATU_ACTIVE, 0); + ret = ar8216_wait_bit(priv, AR8216_REG_ATU_FUNC0, AR8216_ATU_ACTIVE, 0); if (!ret) - ar8xxx_write(priv, AR8216_REG_ATU, AR8216_ATU_OP_FLUSH | - AR8216_ATU_ACTIVE); + ar8xxx_write(priv, AR8216_REG_ATU_FUNC0, AR8216_ATU_OP_FLUSH | + AR8216_ATU_ACTIVE); return ret; } @@ -702,6 +702,77 @@ ar8216_init_port(struct ar8xxx_priv *priv, int port) } static void +ar8216_wait_atu_ready(struct ar8xxx_priv *priv, u16 r2, u16 r1) +{ + int timeout = 20; + + while (ar8xxx_mii_read32(priv, r2, r1) & AR8216_ATU_ACTIVE && --timeout) + udelay(10); + + if (!timeout) + pr_err("ar8216: timeout waiting for atu to become ready\n"); +} + +static void ar8216_get_arl_entry(struct ar8xxx_priv *priv, + struct arl_entry *a, u32 *status, enum arl_op op) +{ + struct mii_bus *bus = priv->mii_bus; + u16 r2, page; + u16 r1_func0, r1_func1, r1_func2; + u32 t, val0, val1, val2; + int i; + + split_addr(AR8216_REG_ATU_FUNC0, &r1_func0, &r2, &page); + r2 |= 0x10; + + r1_func1 = (AR8216_REG_ATU_FUNC1 >> 1) & 0x1e; + r1_func2 = (AR8216_REG_ATU_FUNC2 >> 1) & 0x1e; + + switch (op) { + case AR8XXX_ARL_INITIALIZE: + /* all ATU registers are on the same page + * therefore set page only once + */ + bus->write(bus, 0x18, 0, page); + wait_for_page_switch(); + + ar8216_wait_atu_ready(priv, r2, r1_func0); + + ar8xxx_mii_write32(priv, r2, r1_func0, AR8216_ATU_OP_GET_NEXT); + ar8xxx_mii_write32(priv, r2, r1_func1, 0); + ar8xxx_mii_write32(priv, r2, r1_func2, 0); + break; + case AR8XXX_ARL_GET_NEXT: + t = ar8xxx_mii_read32(priv, r2, r1_func0); + t |= AR8216_ATU_ACTIVE; + ar8xxx_mii_write32(priv, r2, r1_func0, t); + ar8216_wait_atu_ready(priv, r2, r1_func0); + + val0 = ar8xxx_mii_read32(priv, r2, r1_func0); + val1 = ar8xxx_mii_read32(priv, r2, r1_func1); + val2 = ar8xxx_mii_read32(priv, r2, r1_func2); + + *status = (val2 & AR8216_ATU_STATUS) >> AR8216_ATU_STATUS_S; + if (!*status) + break; + + i = 0; + t = AR8216_ATU_PORT0; + while (!(val2 & t) && ++i < priv->dev.ports) + t <<= 1; + + a->port = i; + a->mac[0] = (val0 & AR8216_ATU_ADDR5) >> AR8216_ATU_ADDR5_S; + a->mac[1] = (val0 & AR8216_ATU_ADDR4) >> AR8216_ATU_ADDR4_S; + a->mac[2] = (val1 & AR8216_ATU_ADDR3) >> AR8216_ATU_ADDR3_S; + a->mac[3] = (val1 & AR8216_ATU_ADDR2) >> AR8216_ATU_ADDR2_S; + a->mac[4] = (val1 & AR8216_ATU_ADDR1) >> AR8216_ATU_ADDR1_S; + a->mac[5] = (val1 & AR8216_ATU_ADDR0) >> AR8216_ATU_ADDR0_S; + break; + } +} + +static void ar8236_setup_port(struct ar8xxx_priv *priv, int port, u32 members) { u32 egress, ingress; @@ -1349,7 +1420,6 @@ ar8xxx_sw_get_arl_table(struct switch_dev *dev, return 0; } - static const struct switch_attr ar8xxx_sw_attr_globals[] = { { .type = SWITCH_TYPE_INT, @@ -1475,6 +1545,7 @@ static const struct ar8xxx_chip ar8216_chip = { .vtu_flush = ar8216_vtu_flush, .vtu_load_vlan = ar8216_vtu_load_vlan, .set_mirror_regs = ar8216_set_mirror_regs, + .get_arl_entry = ar8216_get_arl_entry, .sw_hw_apply = ar8xxx_sw_hw_apply, .num_mibs = ARRAY_SIZE(ar8216_mibs), @@ -1502,6 +1573,7 @@ static const struct ar8xxx_chip ar8236_chip = { .vtu_flush = ar8216_vtu_flush, .vtu_load_vlan = ar8216_vtu_load_vlan, .set_mirror_regs = ar8216_set_mirror_regs, + .get_arl_entry = ar8216_get_arl_entry, .sw_hw_apply = ar8xxx_sw_hw_apply, .num_mibs = ARRAY_SIZE(ar8236_mibs), @@ -1529,6 +1601,7 @@ static const struct ar8xxx_chip ar8316_chip = { .vtu_flush = ar8216_vtu_flush, .vtu_load_vlan = ar8216_vtu_load_vlan, .set_mirror_regs = ar8216_set_mirror_regs, + .get_arl_entry = ar8216_get_arl_entry, .sw_hw_apply = ar8xxx_sw_hw_apply, .num_mibs = ARRAY_SIZE(ar8236_mibs), diff --git a/target/linux/generic/files/drivers/net/phy/ar8216.h b/target/linux/generic/files/drivers/net/phy/ar8216.h index 0f53f23..934a8b5 100644 --- a/target/linux/generic/files/drivers/net/phy/ar8216.h +++ b/target/linux/generic/files/drivers/net/phy/ar8216.h @@ -79,7 +79,7 @@ #define AR8236_VTUDATA_MEMBER BITS(0, 7) #define AR8216_VTUDATA_VALID BIT(11) -#define AR8216_REG_ATU 0x0050 +#define AR8216_REG_ATU_FUNC0 0x0050 #define AR8216_ATU_OP BITS(0, 3) #define AR8216_ATU_OP_NOOP 0x0 #define AR8216_ATU_OP_FLUSH 0x1 @@ -91,14 +91,31 @@ #define AR8216_ATU_ACTIVE BIT(3) #define AR8216_ATU_PORT_NUM BITS(8, 4) #define AR8216_ATU_FULL_VIO BIT(12) -#define AR8216_ATU_ADDR4 BITS(16, 8) -#define AR8216_ATU_ADDR5 BITS(24, 8) +#define AR8216_ATU_ADDR5 BITS(16, 8) +#define AR8216_ATU_ADDR5_S 16 +#define AR8216_ATU_ADDR4 BITS(24, 8) +#define AR8216_ATU_ADDR4_S 24 -#define AR8216_REG_ATU_DATA 0x0054 +#define AR8216_REG_ATU_FUNC1 0x0054 #define AR8216_ATU_ADDR3 BITS(0, 8) +#define AR8216_ATU_ADDR3_S 0 #define AR8216_ATU_ADDR2 BITS(8, 8) +#define AR8216_ATU_ADDR2_S 8 #define AR8216_ATU_ADDR1 BITS(16, 8) +#define AR8216_ATU_ADDR1_S 16 #define AR8216_ATU_ADDR0 BITS(24, 8) +#define AR8216_ATU_ADDR0_S 24 + +#define AR8216_REG_ATU_FUNC2 0x0058 +#define AR8216_ATU_PORTS BITS(0, 6) +#define AR8216_ATU_PORT0 BIT(0) +#define AR8216_ATU_PORT1 BIT(1) +#define AR8216_ATU_PORT2 BIT(2) +#define AR8216_ATU_PORT3 BIT(3) +#define AR8216_ATU_PORT4 BIT(4) +#define AR8216_ATU_PORT5 BIT(5) +#define AR8216_ATU_STATUS BITS(16, 4) +#define AR8216_ATU_STATUS_S 16 #define AR8216_REG_ATU_CTRL 0x005C #define AR8216_ATU_CTRL_AGE_EN BIT(17)