Merge branch 'qca8k-QCA8334-switch-support'
Michal Vokáč says: ==================== Add support for QCA8334 switch This series basically adds support for a QCA8334 ethernet switch to the qca8k driver. It is a four-port variant of the already supported seven port QCA8337. Register map is the same for the whole familly and all chips have the same device ID. Major part of this series enhances the CPU port setting. Currently the CPU port is not set to any sensible defaults compatible with the xGMII interface. This series forces the CPU port to its maximum bandwidth and also allows to adjust the new defaults using fixed-link device tree sub-node. Alongside these changes I fixed two checkpatch warnings regarding SPDX and redundant parentheses. Changes in v3: - Rebased on latest net-next/master. - Corrected fixed-link documentation. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
5a867abdf6
@ -2,7 +2,10 @@
|
|||||||
|
|
||||||
Required properties:
|
Required properties:
|
||||||
|
|
||||||
- compatible: should be "qca,qca8337"
|
- compatible: should be one of:
|
||||||
|
"qca,qca8334"
|
||||||
|
"qca,qca8337"
|
||||||
|
|
||||||
- #size-cells: must be 0
|
- #size-cells: must be 0
|
||||||
- #address-cells: must be 1
|
- #address-cells: must be 1
|
||||||
|
|
||||||
@ -14,6 +17,20 @@ port and PHY id, each subnode describing a port needs to have a valid phandle
|
|||||||
referencing the internal PHY connected to it. The CPU port of this switch is
|
referencing the internal PHY connected to it. The CPU port of this switch is
|
||||||
always port 0.
|
always port 0.
|
||||||
|
|
||||||
|
A CPU port node has the following optional node:
|
||||||
|
|
||||||
|
- fixed-link : Fixed-link subnode describing a link to a non-MDIO
|
||||||
|
managed entity. See
|
||||||
|
Documentation/devicetree/bindings/net/fixed-link.txt
|
||||||
|
for details.
|
||||||
|
|
||||||
|
For QCA8K the 'fixed-link' sub-node supports only the following properties:
|
||||||
|
|
||||||
|
- 'speed' (integer, mandatory), to indicate the link speed. Accepted
|
||||||
|
values are 10, 100 and 1000
|
||||||
|
- 'full-duplex' (boolean, optional), to indicate that full duplex is
|
||||||
|
used. When absent, half duplex is assumed.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
|
|
||||||
@ -53,6 +70,10 @@ Example:
|
|||||||
label = "cpu";
|
label = "cpu";
|
||||||
ethernet = <&gmac1>;
|
ethernet = <&gmac1>;
|
||||||
phy-mode = "rgmii";
|
phy-mode = "rgmii";
|
||||||
|
fixed-link {
|
||||||
|
speed = 1000;
|
||||||
|
full-duplex;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
port@1 {
|
port@1 {
|
||||||
|
@ -1,17 +1,9 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-2.0
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2009 Felix Fietkau <nbd@nbd.name>
|
* Copyright (C) 2009 Felix Fietkau <nbd@nbd.name>
|
||||||
* Copyright (C) 2011-2012 Gabor Juhos <juhosg@openwrt.org>
|
* Copyright (C) 2011-2012 Gabor Juhos <juhosg@openwrt.org>
|
||||||
* Copyright (c) 2015, The Linux Foundation. All rights reserved.
|
* Copyright (c) 2015, The Linux Foundation. All rights reserved.
|
||||||
* Copyright (c) 2016 John Crispin <john@phrozen.org>
|
* Copyright (c) 2016 John Crispin <john@phrozen.org>
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License version 2 and
|
|
||||||
* only version 2 as published by the Free Software Foundation.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
@ -473,10 +465,10 @@ qca8k_set_pad_ctrl(struct qca8k_priv *priv, int port, int mode)
|
|||||||
static void
|
static void
|
||||||
qca8k_port_set_status(struct qca8k_priv *priv, int port, int enable)
|
qca8k_port_set_status(struct qca8k_priv *priv, int port, int enable)
|
||||||
{
|
{
|
||||||
u32 mask = QCA8K_PORT_STATUS_TXMAC;
|
u32 mask = QCA8K_PORT_STATUS_TXMAC | QCA8K_PORT_STATUS_RXMAC;
|
||||||
|
|
||||||
/* Port 0 and 6 have no internal PHY */
|
/* Port 0 and 6 have no internal PHY */
|
||||||
if ((port > 0) && (port < 6))
|
if (port > 0 && port < 6)
|
||||||
mask |= QCA8K_PORT_STATUS_LINK_AUTO;
|
mask |= QCA8K_PORT_STATUS_LINK_AUTO;
|
||||||
|
|
||||||
if (enable)
|
if (enable)
|
||||||
@ -490,6 +482,7 @@ qca8k_setup(struct dsa_switch *ds)
|
|||||||
{
|
{
|
||||||
struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv;
|
struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv;
|
||||||
int ret, i, phy_mode = -1;
|
int ret, i, phy_mode = -1;
|
||||||
|
u32 mask;
|
||||||
|
|
||||||
/* Make sure that port 0 is the cpu port */
|
/* Make sure that port 0 is the cpu port */
|
||||||
if (!dsa_is_cpu_port(ds, 0)) {
|
if (!dsa_is_cpu_port(ds, 0)) {
|
||||||
@ -515,7 +508,10 @@ qca8k_setup(struct dsa_switch *ds)
|
|||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
/* Enable CPU Port */
|
/* Enable CPU Port, force it to maximum bandwidth and full-duplex */
|
||||||
|
mask = QCA8K_PORT_STATUS_SPEED_1000 | QCA8K_PORT_STATUS_TXFLOW |
|
||||||
|
QCA8K_PORT_STATUS_RXFLOW | QCA8K_PORT_STATUS_DUPLEX;
|
||||||
|
qca8k_write(priv, QCA8K_REG_PORT_STATUS(QCA8K_CPU_PORT), mask);
|
||||||
qca8k_reg_set(priv, QCA8K_REG_GLOBAL_FW_CTRL0,
|
qca8k_reg_set(priv, QCA8K_REG_GLOBAL_FW_CTRL0,
|
||||||
QCA8K_GLOBAL_FW_CTRL0_CPU_PORT_EN);
|
QCA8K_GLOBAL_FW_CTRL0_CPU_PORT_EN);
|
||||||
qca8k_port_set_status(priv, QCA8K_CPU_PORT, 1);
|
qca8k_port_set_status(priv, QCA8K_CPU_PORT, 1);
|
||||||
@ -583,6 +579,47 @@ qca8k_setup(struct dsa_switch *ds)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
qca8k_adjust_link(struct dsa_switch *ds, int port, struct phy_device *phy)
|
||||||
|
{
|
||||||
|
struct qca8k_priv *priv = ds->priv;
|
||||||
|
u32 reg;
|
||||||
|
|
||||||
|
/* Force fixed-link setting for CPU port, skip others. */
|
||||||
|
if (!phy_is_pseudo_fixed_link(phy))
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* Set port speed */
|
||||||
|
switch (phy->speed) {
|
||||||
|
case 10:
|
||||||
|
reg = QCA8K_PORT_STATUS_SPEED_10;
|
||||||
|
break;
|
||||||
|
case 100:
|
||||||
|
reg = QCA8K_PORT_STATUS_SPEED_100;
|
||||||
|
break;
|
||||||
|
case 1000:
|
||||||
|
reg = QCA8K_PORT_STATUS_SPEED_1000;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
dev_dbg(priv->dev, "port%d link speed %dMbps not supported.\n",
|
||||||
|
port, phy->speed);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set duplex mode */
|
||||||
|
if (phy->duplex == DUPLEX_FULL)
|
||||||
|
reg |= QCA8K_PORT_STATUS_DUPLEX;
|
||||||
|
|
||||||
|
/* Force flow control */
|
||||||
|
if (dsa_is_cpu_port(ds, port))
|
||||||
|
reg |= QCA8K_PORT_STATUS_RXFLOW | QCA8K_PORT_STATUS_TXFLOW;
|
||||||
|
|
||||||
|
/* Force link down before changing MAC options */
|
||||||
|
qca8k_port_set_status(priv, port, 0);
|
||||||
|
qca8k_write(priv, QCA8K_REG_PORT_STATUS(port), reg);
|
||||||
|
qca8k_port_set_status(priv, port, 1);
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
qca8k_phy_read(struct dsa_switch *ds, int phy, int regnum)
|
qca8k_phy_read(struct dsa_switch *ds, int phy, int regnum)
|
||||||
{
|
{
|
||||||
@ -837,6 +874,7 @@ qca8k_get_tag_protocol(struct dsa_switch *ds, int port)
|
|||||||
static const struct dsa_switch_ops qca8k_switch_ops = {
|
static const struct dsa_switch_ops qca8k_switch_ops = {
|
||||||
.get_tag_protocol = qca8k_get_tag_protocol,
|
.get_tag_protocol = qca8k_get_tag_protocol,
|
||||||
.setup = qca8k_setup,
|
.setup = qca8k_setup,
|
||||||
|
.adjust_link = qca8k_adjust_link,
|
||||||
.get_strings = qca8k_get_strings,
|
.get_strings = qca8k_get_strings,
|
||||||
.phy_read = qca8k_phy_read,
|
.phy_read = qca8k_phy_read,
|
||||||
.phy_write = qca8k_phy_write,
|
.phy_write = qca8k_phy_write,
|
||||||
@ -868,6 +906,7 @@ qca8k_sw_probe(struct mdio_device *mdiodev)
|
|||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
priv->bus = mdiodev->bus;
|
priv->bus = mdiodev->bus;
|
||||||
|
priv->dev = &mdiodev->dev;
|
||||||
|
|
||||||
/* read the switches ID register */
|
/* read the switches ID register */
|
||||||
id = qca8k_read(priv, QCA8K_REG_MASK_CTRL);
|
id = qca8k_read(priv, QCA8K_REG_MASK_CTRL);
|
||||||
@ -939,6 +978,7 @@ static SIMPLE_DEV_PM_OPS(qca8k_pm_ops,
|
|||||||
qca8k_suspend, qca8k_resume);
|
qca8k_suspend, qca8k_resume);
|
||||||
|
|
||||||
static const struct of_device_id qca8k_of_match[] = {
|
static const struct of_device_id qca8k_of_match[] = {
|
||||||
|
{ .compatible = "qca,qca8334" },
|
||||||
{ .compatible = "qca,qca8337" },
|
{ .compatible = "qca,qca8337" },
|
||||||
{ /* sentinel */ },
|
{ /* sentinel */ },
|
||||||
};
|
};
|
||||||
|
@ -51,8 +51,10 @@
|
|||||||
#define QCA8K_GOL_MAC_ADDR0 0x60
|
#define QCA8K_GOL_MAC_ADDR0 0x60
|
||||||
#define QCA8K_GOL_MAC_ADDR1 0x64
|
#define QCA8K_GOL_MAC_ADDR1 0x64
|
||||||
#define QCA8K_REG_PORT_STATUS(_i) (0x07c + (_i) * 4)
|
#define QCA8K_REG_PORT_STATUS(_i) (0x07c + (_i) * 4)
|
||||||
#define QCA8K_PORT_STATUS_SPEED GENMASK(2, 0)
|
#define QCA8K_PORT_STATUS_SPEED GENMASK(1, 0)
|
||||||
#define QCA8K_PORT_STATUS_SPEED_S 0
|
#define QCA8K_PORT_STATUS_SPEED_10 0
|
||||||
|
#define QCA8K_PORT_STATUS_SPEED_100 0x1
|
||||||
|
#define QCA8K_PORT_STATUS_SPEED_1000 0x2
|
||||||
#define QCA8K_PORT_STATUS_TXMAC BIT(2)
|
#define QCA8K_PORT_STATUS_TXMAC BIT(2)
|
||||||
#define QCA8K_PORT_STATUS_RXMAC BIT(3)
|
#define QCA8K_PORT_STATUS_RXMAC BIT(3)
|
||||||
#define QCA8K_PORT_STATUS_TXFLOW BIT(4)
|
#define QCA8K_PORT_STATUS_TXFLOW BIT(4)
|
||||||
@ -165,6 +167,7 @@ struct qca8k_priv {
|
|||||||
struct ar8xxx_port_status port_sts[QCA8K_NUM_PORTS];
|
struct ar8xxx_port_status port_sts[QCA8K_NUM_PORTS];
|
||||||
struct dsa_switch *ds;
|
struct dsa_switch *ds;
|
||||||
struct mutex reg_mutex;
|
struct mutex reg_mutex;
|
||||||
|
struct device *dev;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct qca8k_mib_desc {
|
struct qca8k_mib_desc {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user