Merge branch 'net-ethernet-ti-am65-cpsw-update-and-enable-sr2-0-soc'

Grygorii Strashko says:

====================
net: ethernet: ti: am65-cpsw: update and enable sr2.0 soc

This series contains set of improvements for TI AM654x/J721E CPSW2G driver and
adds support for TI AM654x SR2.0 SoC.

Patch 1: adds vlans restoration after "if down/up"
Patches 2-5: improvments
Patch 6: adds support for TI AM654x SR2.0 SoC which allows to disable errata i2027 W/A.
By default, errata i2027 W/A (TX csum offload disabled) is enabled on AM654x SoC
for backward compatibility, unless SR2.0 SoC is identified using SOC BUS framework.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
David S. Miller 2020-06-29 17:06:19 -07:00
commit 5e701e49b7
3 changed files with 69 additions and 16 deletions

View file

@ -445,7 +445,7 @@ static int am65_cpsw_set_channels(struct net_device *ndev,
/* Check if interface is up. Can change the num queues when
* the interface is down.
*/
if (netif_running(ndev))
if (common->usage_count)
return -EBUSY;
am65_cpsw_nuss_remove_tx_chns(common);
@ -734,6 +734,9 @@ static int am65_cpsw_set_ethtool_priv_flags(struct net_device *ndev, u32 flags)
rrobin = !!(flags & AM65_CPSW_PRIV_P0_RX_PTYPE_RROBIN);
if (common->usage_count)
return -EBUSY;
if (common->est_enabled && rrobin) {
netdev_err(ndev,
"p0-rx-ptype-rrobin flag conflicts with QOS\n");
@ -741,7 +744,6 @@ static int am65_cpsw_set_ethtool_priv_flags(struct net_device *ndev, u32 flags)
}
common->pf_p0_rx_ptype_rrobin = rrobin;
am65_cpsw_nuss_set_p0_ptype(common);
return 0;
}

View file

@ -23,6 +23,7 @@
#include <linux/pm_runtime.h>
#include <linux/regmap.h>
#include <linux/mfd/syscon.h>
#include <linux/sys_soc.h>
#include <linux/dma/ti-cppi5.h>
#include <linux/dma/k3-udma-glue.h>
@ -148,10 +149,11 @@ static void am65_cpsw_nuss_get_ver(struct am65_cpsw_common *common)
common->nuss_ver = readl(common->ss_base);
common->cpsw_ver = readl(common->cpsw_base);
dev_info(common->dev,
"initializing am65 cpsw nuss version 0x%08X, cpsw version 0x%08X Ports: %u\n",
"initializing am65 cpsw nuss version 0x%08X, cpsw version 0x%08X Ports: %u quirks:%08x\n",
common->nuss_ver,
common->cpsw_ver,
common->port_num + 1);
common->port_num + 1,
common->pdata.quirks);
}
void am65_cpsw_nuss_adjust_link(struct net_device *ndev)
@ -223,6 +225,9 @@ static int am65_cpsw_nuss_ndo_slave_add_vid(struct net_device *ndev,
u32 port_mask, unreg_mcast = 0;
int ret;
if (!netif_running(ndev) || !vid)
return 0;
ret = pm_runtime_get_sync(common->dev);
if (ret < 0) {
pm_runtime_put_noidle(common->dev);
@ -246,6 +251,9 @@ static int am65_cpsw_nuss_ndo_slave_kill_vid(struct net_device *ndev,
struct am65_cpsw_common *common = am65_ndev_to_common(ndev);
int ret;
if (!netif_running(ndev) || !vid)
return 0;
ret = pm_runtime_get_sync(common->dev);
if (ret < 0) {
pm_runtime_put_noidle(common->dev);
@ -571,6 +579,16 @@ static int am65_cpsw_nuss_ndo_slave_stop(struct net_device *ndev)
return 0;
}
static int cpsw_restore_vlans(struct net_device *vdev, int vid, void *arg)
{
struct am65_cpsw_port *port = arg;
if (!vdev)
return 0;
return am65_cpsw_nuss_ndo_slave_add_vid(port->ndev, 0, vid);
}
static int am65_cpsw_nuss_ndo_slave_open(struct net_device *ndev)
{
struct am65_cpsw_common *common = am65_ndev_to_common(ndev);
@ -644,6 +662,9 @@ static int am65_cpsw_nuss_ndo_slave_open(struct net_device *ndev)
}
}
/* restore vlan configurations */
vlan_for_each(ndev, cpsw_restore_vlans, port);
phy_attached_info(port->slave.phy);
phy_start(port->slave.phy);
@ -1749,6 +1770,10 @@ static int am65_cpsw_nuss_init_slave_ports(struct am65_cpsw_common *common)
common->cpsw_base + AM65_CPSW_NU_FRAM_BASE +
(AM65_CPSW_NU_FRAM_PORT_OFFSET * (port_id - 1));
port->slave.mac_sl = cpsw_sl_get("am65", dev, port->port_base);
if (IS_ERR(port->slave.mac_sl))
return PTR_ERR(port->slave.mac_sl);
port->disabled = !of_device_is_available(port_np);
if (port->disabled)
continue;
@ -1792,10 +1817,6 @@ static int am65_cpsw_nuss_init_slave_ports(struct am65_cpsw_common *common)
return ret;
}
port->slave.mac_sl = cpsw_sl_get("am65", dev, port->port_base);
if (IS_ERR(port->slave.mac_sl))
return PTR_ERR(port->slave.mac_sl);
mac_addr = of_get_mac_address(port_np);
if (!IS_ERR(mac_addr)) {
ether_addr_copy(port->slave.mac_addr, mac_addr);
@ -1858,7 +1879,7 @@ static int am65_cpsw_nuss_init_ndev_2g(struct am65_cpsw_common *common)
port->ndev->ethtool_ops = &am65_cpsw_ethtool_ops_slave;
/* Disable TX checksum offload by default due to HW bug */
if (common->pdata->quirks & AM65_CPSW_QUIRK_I2027_NO_TX_CSUM)
if (common->pdata.quirks & AM65_CPSW_QUIRK_I2027_NO_TX_CSUM)
port->ndev->features &= ~NETIF_F_HW_CSUM;
ndev_priv->stats = netdev_alloc_pcpu_stats(struct am65_cpsw_ndev_stats);
@ -1875,8 +1896,6 @@ static int am65_cpsw_nuss_init_ndev_2g(struct am65_cpsw_common *common)
netif_napi_add(port->ndev, &common->napi_rx,
am65_cpsw_nuss_rx_poll, NAPI_POLL_WEIGHT);
common->pf_p0_rx_ptype_rrobin = false;
return ret;
}
@ -1964,21 +1983,50 @@ static void am65_cpsw_nuss_cleanup_ndev(struct am65_cpsw_common *common)
}
}
struct am65_cpsw_soc_pdata {
u32 quirks_dis;
};
static const struct am65_cpsw_soc_pdata am65x_soc_sr2_0 = {
.quirks_dis = AM65_CPSW_QUIRK_I2027_NO_TX_CSUM,
};
static const struct soc_device_attribute am65_cpsw_socinfo[] = {
{ .family = "AM65X",
.revision = "SR2.0",
.data = &am65x_soc_sr2_0
},
{/* sentinel */}
};
static const struct am65_cpsw_pdata am65x_sr1_0 = {
.quirks = AM65_CPSW_QUIRK_I2027_NO_TX_CSUM,
};
static const struct am65_cpsw_pdata j721e_sr1_0 = {
static const struct am65_cpsw_pdata j721e_pdata = {
.quirks = 0,
};
static const struct of_device_id am65_cpsw_nuss_of_mtable[] = {
{ .compatible = "ti,am654-cpsw-nuss", .data = &am65x_sr1_0 },
{ .compatible = "ti,j721e-cpsw-nuss", .data = &j721e_sr1_0 },
{ .compatible = "ti,am654-cpsw-nuss", .data = &am65x_sr1_0},
{ .compatible = "ti,j721e-cpsw-nuss", .data = &j721e_pdata},
{ /* sentinel */ },
};
MODULE_DEVICE_TABLE(of, am65_cpsw_nuss_of_mtable);
static void am65_cpsw_nuss_apply_socinfo(struct am65_cpsw_common *common)
{
const struct soc_device_attribute *soc;
soc = soc_device_match(am65_cpsw_socinfo);
if (soc && soc->data) {
const struct am65_cpsw_soc_pdata *socdata = soc->data;
/* disable quirks */
common->pdata.quirks &= ~socdata->quirks_dis;
}
}
static int am65_cpsw_nuss_probe(struct platform_device *pdev)
{
struct cpsw_ale_params ale_params = { 0 };
@ -1997,7 +2045,9 @@ static int am65_cpsw_nuss_probe(struct platform_device *pdev)
of_id = of_match_device(am65_cpsw_nuss_of_mtable, dev);
if (!of_id)
return -EINVAL;
common->pdata = of_id->data;
common->pdata = *(const struct am65_cpsw_pdata *)of_id->data;
am65_cpsw_nuss_apply_socinfo(common);
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "cpsw_nuss");
common->ss_base = devm_ioremap_resource(&pdev->dev, res);
@ -2019,6 +2069,7 @@ static int am65_cpsw_nuss_probe(struct platform_device *pdev)
common->rx_flow_id_base = -1;
init_completion(&common->tdown_complete);
common->tx_ch_num = 1;
common->pf_p0_rx_ptype_rrobin = false;
ret = dma_coerce_mask_and_coherent(dev, DMA_BIT_MASK(48));
if (ret) {

View file

@ -82,7 +82,7 @@ struct am65_cpsw_pdata {
struct am65_cpsw_common {
struct device *dev;
struct device *mdio_dev;
const struct am65_cpsw_pdata *pdata;
struct am65_cpsw_pdata pdata;
void __iomem *ss_base;
void __iomem *cpsw_base;