Commit a706a042 authored by David S. Miller's avatar David S. Miller

Merge branch 'add-dsa-switch-support-for-ar9331'

Oleksij Rempel says:

====================
add dsa switch support for ar9331

changes v6:
- remove ag71xx changes from this patch set. It needs more work.
- ar9331: fix register definition and add ASCII art switch documentation.

changes v6:
- rebase against net-next

changes v5:
- remote support for port5. The effort of using this port is
  questionable. Currently, it is better to not use it at all, then
  adding buggy support.
- remove port enable call back. There is nothing what we actually need
  to enable.
- rebase it against v5.5-rc1

changes v4:
- ag71xx: ag71xx_mac_validate fix always false comparison (&& -> ||)
- tag_ar9331: use skb_pull_rcsum() instead of skb_pull().
- tag_ar9331: drop skb_set_mac_header()

changes v3:
- ag71xx: ag71xx_mac_config: ignore MLO_AN_INBAND mode. It is not
  supported by HW and SW.
- ag71xx: ag71xx_mac_validate: return all supported bits on
  PHY_INTERFACE_MODE_NA

changes v2:
- move Atheros AR9331 TAG format to separate patch
- use netdev_warn_once in the tag driver to reduce potential message spam
- typo fixes
- reorder tag driver alphabetically
- configure switch to maximal frame size
- use mdiobus_read/write
- fail if mdio sub node is not found
- add comment for post reset state
- remove deprecated comment about device id
- remove phy-handle option for node with fixed-link
- ag71xx: set 1G support only for GMII mode

This patch series provides dsa switch support for Atheros ar9331 WiSoC.
As side effect ag71xx needed to be ported to phylink to make the switch
driver (as well phylink based) work properly.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 50808326 ec6698c2
Atheros AR9331 built-in switch
=============================
It is a switch built-in to Atheros AR9331 WiSoC and addressable over internal
MDIO bus. All PHYs are built-in as well.
Required properties:
- compatible: should be: "qca,ar9331-switch"
- reg: Address on the MII bus for the switch.
- resets : Must contain an entry for each entry in reset-names.
- reset-names : Must include the following entries: "switch"
- interrupt-parent: Phandle to the parent interrupt controller
- interrupts: IRQ line for the switch
- interrupt-controller: Indicates the switch is itself an interrupt
controller. This is used for the PHY interrupts.
- #interrupt-cells: must be 1
- mdio: Container of PHY and devices on the switches MDIO bus.
See Documentation/devicetree/bindings/net/dsa/dsa.txt for a list of additional
required and optional properties.
Examples:
eth0: ethernet@19000000 {
compatible = "qca,ar9330-eth";
reg = <0x19000000 0x200>;
interrupts = <4>;
resets = <&rst 9>, <&rst 22>;
reset-names = "mac", "mdio";
clocks = <&pll ATH79_CLK_AHB>, <&pll ATH79_CLK_AHB>;
clock-names = "eth", "mdio";
phy-mode = "mii";
phy-handle = <&phy_port4>;
};
eth1: ethernet@1a000000 {
compatible = "qca,ar9330-eth";
reg = <0x1a000000 0x200>;
interrupts = <5>;
resets = <&rst 13>, <&rst 23>;
reset-names = "mac", "mdio";
clocks = <&pll ATH79_CLK_AHB>, <&pll ATH79_CLK_AHB>;
clock-names = "eth", "mdio";
phy-mode = "gmii";
fixed-link {
speed = <1000>;
full-duplex;
};
mdio {
#address-cells = <1>;
#size-cells = <0>;
switch10: switch@10 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "qca,ar9331-switch";
reg = <0x10>;
resets = <&rst 8>;
reset-names = "switch";
interrupt-parent = <&miscintc>;
interrupts = <12>;
interrupt-controller;
#interrupt-cells = <1>;
ports {
#address-cells = <1>;
#size-cells = <0>;
switch_port0: port@0 {
reg = <0x0>;
label = "cpu";
ethernet = <&eth1>;
phy-mode = "gmii";
fixed-link {
speed = <1000>;
full-duplex;
};
};
switch_port1: port@1 {
reg = <0x1>;
phy-handle = <&phy_port0>;
phy-mode = "internal";
};
switch_port2: port@2 {
reg = <0x2>;
phy-handle = <&phy_port1>;
phy-mode = "internal";
};
switch_port3: port@3 {
reg = <0x3>;
phy-handle = <&phy_port2>;
phy-mode = "internal";
};
switch_port4: port@4 {
reg = <0x4>;
phy-handle = <&phy_port3>;
phy-mode = "internal";
};
};
mdio {
#address-cells = <1>;
#size-cells = <0>;
interrupt-parent = <&switch10>;
phy_port0: phy@0 {
reg = <0x0>;
interrupts = <0>;
};
phy_port1: phy@1 {
reg = <0x1>;
interrupts = <0>;
};
phy_port2: phy@2 {
reg = <0x2>;
interrupts = <0>;
};
phy_port3: phy@3 {
reg = <0x3>;
interrupts = <0>;
};
phy_port4: phy@4 {
reg = <0x4>;
interrupts = <0>;
};
};
};
};
};
......@@ -126,6 +126,9 @@ eth0: ethernet@19000000 {
clocks = <&pll ATH79_CLK_AHB>, <&pll ATH79_CLK_AHB>;
clock-names = "eth", "mdio";
phy-mode = "mii";
phy-handle = <&phy_port4>;
status = "disabled";
};
......@@ -133,13 +136,127 @@ eth1: ethernet@1a000000 {
compatible = "qca,ar9330-eth";
reg = <0x1a000000 0x200>;
interrupts = <5>;
resets = <&rst 13>, <&rst 23>;
reset-names = "mac", "mdio";
clocks = <&pll ATH79_CLK_AHB>, <&pll ATH79_CLK_AHB>;
clock-names = "eth", "mdio";
phy-mode = "gmii";
status = "disabled";
fixed-link {
speed = <1000>;
full-duplex;
};
mdio {
#address-cells = <1>;
#size-cells = <0>;
switch10: switch@10 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "qca,ar9331-switch";
reg = <0x10>;
resets = <&rst 8>;
reset-names = "switch";
interrupt-parent = <&miscintc>;
interrupts = <12>;
interrupt-controller;
#interrupt-cells = <1>;
ports {
#address-cells = <1>;
#size-cells = <0>;
switch_port0: port@0 {
reg = <0x0>;
label = "cpu";
ethernet = <&eth1>;
phy-mode = "gmii";
fixed-link {
speed = <1000>;
full-duplex;
};
};
switch_port1: port@1 {
reg = <0x1>;
phy-handle = <&phy_port0>;
phy-mode = "internal";
status = "disabled";
};
switch_port2: port@2 {
reg = <0x2>;
phy-handle = <&phy_port1>;
phy-mode = "internal";
status = "disabled";
};
switch_port3: port@3 {
reg = <0x3>;
phy-handle = <&phy_port2>;
phy-mode = "internal";
status = "disabled";
};
switch_port4: port@4 {
reg = <0x4>;
phy-handle = <&phy_port3>;
phy-mode = "internal";
status = "disabled";
};
};
mdio {
#address-cells = <1>;
#size-cells = <0>;
interrupt-parent = <&switch10>;
phy_port0: phy@0 {
reg = <0x0>;
interrupts = <0>;
status = "disabled";
};
phy_port1: phy@1 {
reg = <0x1>;
interrupts = <0>;
status = "disabled";
};
phy_port2: phy@2 {
reg = <0x2>;
interrupts = <0>;
status = "disabled";
};
phy_port3: phy@3 {
reg = <0x3>;
interrupts = <0>;
status = "disabled";
};
phy_port4: phy@4 {
reg = <0x4>;
interrupts = <0>;
status = "disabled";
};
};
};
};
};
usb: usb@1b000100 {
......
......@@ -84,3 +84,16 @@ &eth0 {
&eth1 {
status = "okay";
};
&switch_port1 {
label = "lan0";
status = "okay";
};
&phy_port0 {
status = "okay";
};
&phy_port4 {
status = "okay";
};
......@@ -54,6 +54,8 @@ source "drivers/net/dsa/mv88e6xxx/Kconfig"
source "drivers/net/dsa/ocelot/Kconfig"
source "drivers/net/dsa/qca/Kconfig"
source "drivers/net/dsa/sja1105/Kconfig"
config NET_DSA_QCA8K
......
......@@ -21,4 +21,5 @@ obj-y += b53/
obj-y += microchip/
obj-y += mv88e6xxx/
obj-y += ocelot/
obj-y += qca/
obj-y += sja1105/
# SPDX-License-Identifier: GPL-2.0-only
config NET_DSA_AR9331
tristate "Qualcomm Atheros AR9331 Ethernet switch support"
depends on NET_DSA
select NET_DSA_TAG_AR9331
select REGMAP
---help---
This enables support for the Qualcomm Atheros AR9331 built-in Ethernet
switch.
# SPDX-License-Identifier: GPL-2.0-only
obj-$(CONFIG_NET_DSA_AR9331) += ar9331.o
This diff is collapsed.
......@@ -43,6 +43,7 @@ struct phylink_link_state;
#define DSA_TAG_PROTO_SJA1105_VALUE 13
#define DSA_TAG_PROTO_KSZ8795_VALUE 14
#define DSA_TAG_PROTO_OCELOT_VALUE 15
#define DSA_TAG_PROTO_AR9331_VALUE 16
enum dsa_tag_protocol {
DSA_TAG_PROTO_NONE = DSA_TAG_PROTO_NONE_VALUE,
......@@ -61,6 +62,7 @@ enum dsa_tag_protocol {
DSA_TAG_PROTO_SJA1105 = DSA_TAG_PROTO_SJA1105_VALUE,
DSA_TAG_PROTO_KSZ8795 = DSA_TAG_PROTO_KSZ8795_VALUE,
DSA_TAG_PROTO_OCELOT = DSA_TAG_PROTO_OCELOT_VALUE,
DSA_TAG_PROTO_AR9331 = DSA_TAG_PROTO_AR9331_VALUE,
};
struct packet_type;
......
......@@ -29,6 +29,12 @@ config NET_DSA_TAG_8021Q
Drivers which use these helpers should select this as dependency.
config NET_DSA_TAG_AR9331
tristate "Tag driver for Atheros AR9331 SoC with built-in switch"
help
Say Y or M if you want to enable support for tagging frames for
the Atheros AR9331 SoC with built-in switch.
config NET_DSA_TAG_BRCM_COMMON
tristate
default n
......
......@@ -5,6 +5,7 @@ dsa_core-y += dsa.o dsa2.o master.o port.o slave.o switch.o
# tagging formats
obj-$(CONFIG_NET_DSA_TAG_8021Q) += tag_8021q.o
obj-$(CONFIG_NET_DSA_TAG_AR9331) += tag_ar9331.o
obj-$(CONFIG_NET_DSA_TAG_BRCM_COMMON) += tag_brcm.o
obj-$(CONFIG_NET_DSA_TAG_DSA) += tag_dsa.o
obj-$(CONFIG_NET_DSA_TAG_EDSA) += tag_edsa.o
......
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2019 Pengutronix, Oleksij Rempel <kernel@pengutronix.de>
*/
#include <linux/bitfield.h>
#include <linux/etherdevice.h>
#include "dsa_priv.h"
#define AR9331_HDR_LEN 2
#define AR9331_HDR_VERSION 1
#define AR9331_HDR_VERSION_MASK GENMASK(15, 14)
#define AR9331_HDR_PRIORITY_MASK GENMASK(13, 12)
#define AR9331_HDR_TYPE_MASK GENMASK(10, 8)
#define AR9331_HDR_BROADCAST BIT(7)
#define AR9331_HDR_FROM_CPU BIT(6)
/* AR9331_HDR_RESERVED - not used or may be version field.
* According to the AR8216 doc it should 0b10. On AR9331 it is 0b11 on RX path
* and should be set to 0b11 to make it work.
*/
#define AR9331_HDR_RESERVED_MASK GENMASK(5, 4)
#define AR9331_HDR_PORT_NUM_MASK GENMASK(3, 0)
static struct sk_buff *ar9331_tag_xmit(struct sk_buff *skb,
struct net_device *dev)
{
struct dsa_port *dp = dsa_slave_to_port(dev);
__le16 *phdr;
u16 hdr;
if (skb_cow_head(skb, 0) < 0)
return NULL;
phdr = skb_push(skb, AR9331_HDR_LEN);
hdr = FIELD_PREP(AR9331_HDR_VERSION_MASK, AR9331_HDR_VERSION);
hdr |= AR9331_HDR_FROM_CPU | dp->index;
/* 0b10 for AR8216 and 0b11 for AR9331 */
hdr |= AR9331_HDR_RESERVED_MASK;
phdr[0] = cpu_to_le16(hdr);
return skb;
}
static struct sk_buff *ar9331_tag_rcv(struct sk_buff *skb,
struct net_device *ndev,
struct packet_type *pt)
{
u8 ver, port;
u16 hdr;
if (unlikely(!pskb_may_pull(skb, AR9331_HDR_LEN)))
return NULL;
hdr = le16_to_cpu(*(__le16 *)skb_mac_header(skb));
ver = FIELD_GET(AR9331_HDR_VERSION_MASK, hdr);
if (unlikely(ver != AR9331_HDR_VERSION)) {
netdev_warn_once(ndev, "%s:%i wrong header version 0x%2x\n",
__func__, __LINE__, hdr);
return NULL;
}
if (unlikely(hdr & AR9331_HDR_FROM_CPU)) {
netdev_warn_once(ndev, "%s:%i packet should not be from cpu 0x%2x\n",
__func__, __LINE__, hdr);
return NULL;
}
skb_pull_rcsum(skb, AR9331_HDR_LEN);
/* Get source port information */
port = FIELD_GET(AR9331_HDR_PORT_NUM_MASK, hdr);
skb->dev = dsa_master_find_slave(ndev, 0, port);
if (!skb->dev)
return NULL;
return skb;
}
static const struct dsa_device_ops ar9331_netdev_ops = {
.name = "ar9331",
.proto = DSA_TAG_PROTO_AR9331,
.xmit = ar9331_tag_xmit,
.rcv = ar9331_tag_rcv,
.overhead = AR9331_HDR_LEN,
};
MODULE_LICENSE("GPL v2");
MODULE_ALIAS_DSA_TAG_DRIVER(DSA_TAG_PROTO_AR9331);
module_dsa_tag_driver(ar9331_netdev_ops);
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment