aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/ethernet/ti/keystone_xgess.c')
-rw-r--r--drivers/net/ethernet/ti/keystone_xgess.c79
1 files changed, 47 insertions, 32 deletions
diff --git a/drivers/net/ethernet/ti/keystone_xgess.c b/drivers/net/ethernet/ti/keystone_xgess.c
index a09de9044d2..0af8126a11e 100644
--- a/drivers/net/ethernet/ti/keystone_xgess.c
+++ b/drivers/net/ethernet/ti/keystone_xgess.c
@@ -69,6 +69,11 @@
69 (MACSL_XGMII_ENABLE | MACSL_XGIG_MODE) : \ 69 (MACSL_XGMII_ENABLE | MACSL_XGIG_MODE) : \
70 MACSL_GMII_ENABLE) 70 MACSL_GMII_ENABLE)
71 71
72#define MACSL_DEFAULT_CONFIG(s) \
73 (MACSL_SIG_ENABLE((s)) | \
74 MACSL_RX_ENABLE_EXT_CTL | \
75 MACSL_RX_ENABLE_CSF)
76
72#define CPSW_NUM_PORTS 3 77#define CPSW_NUM_PORTS 3
73#define CPSW_CTL_P0_ENABLE BIT(2) 78#define CPSW_CTL_P0_ENABLE BIT(2)
74#define CPSW_CTL_VLAN_AWARE BIT(1) 79#define CPSW_CTL_VLAN_AWARE BIT(1)
@@ -85,6 +90,9 @@
85#define HOST_TX_PRI_MAP_DEFAULT 0x00000000 90#define HOST_TX_PRI_MAP_DEFAULT 0x00000000
86#define MAX_SIZE_STREAM_BUFFER 9504 91#define MAX_SIZE_STREAM_BUFFER 9504
87 92
93/* slave_num: 0-based
94 * port_num: 1-based
95 */
88struct cpswx_slave { 96struct cpswx_slave {
89 struct cpswx_slave_regs __iomem *regs; 97 struct cpswx_slave_regs __iomem *regs;
90 struct cpswx_sliver_regs __iomem *sliver; 98 struct cpswx_sliver_regs __iomem *sliver;
@@ -303,6 +311,8 @@ struct cpswx_priv {
303 struct device_node *serdes; 311 struct device_node *serdes;
304}; 312};
305 313
314/* slave_port: 0-based (currently relevant only in multi_if mode)
315*/
306struct cpswx_intf { 316struct cpswx_intf {
307 struct net_device *ndev; 317 struct net_device *ndev;
308 struct device *dev; 318 struct device *dev;
@@ -318,7 +328,7 @@ struct cpswx_intf {
318 u32 multi_if; 328 u32 multi_if;
319 struct list_head cpsw_intf_list; 329 struct list_head cpsw_intf_list;
320 struct timer_list timer; 330 struct timer_list timer;
321 u32 sgmii_link; 331 u32 link_state;
322}; 332};
323 333
324/* 334/*
@@ -1524,9 +1534,7 @@ static void _cpsw_adjust_link(struct cpswx_slave *slave, bool *link)
1524 1534
1525 if (phy->link) { 1535 if (phy->link) {
1526 mac_control = slave->mac_control; 1536 mac_control = slave->mac_control;
1527 mac_control |= MACSL_SIG_ENABLE(slave) | 1537 mac_control |= MACSL_DEFAULT_CONFIG(slave);
1528 MACSL_RX_ENABLE_EXT_CTL |
1529 MACSL_RX_ENABLE_CSF;
1530 /* enable forwarding */ 1538 /* enable forwarding */
1531 cpsw_ale_control_set(slave->ale, slave_port, 1539 cpsw_ale_control_set(slave->ale, slave_port,
1532 ALE_PORT_STATE, ALE_PORT_STATE_FORWARD); 1540 ALE_PORT_STATE, ALE_PORT_STATE_FORWARD);
@@ -1561,9 +1569,9 @@ static void cpsw_adjust_link(struct net_device *n_dev, void *context)
1561 _cpsw_adjust_link(slave, &link); 1569 _cpsw_adjust_link(slave, &link);
1562 1570
1563 if (link) 1571 if (link)
1564 netcp->link_state |= BIT(slave->slave_num); 1572 netcp->phy_link_state_mask |= BIT(slave->slave_num);
1565 else 1573 else
1566 netcp->link_state &= ~BIT(slave->slave_num); 1574 netcp->phy_link_state_mask &= ~BIT(slave->slave_num);
1567} 1575}
1568 1576
1569/* 1577/*
@@ -1595,17 +1603,15 @@ static int cpsw_port_reset(struct cpswx_slave *slave)
1595 */ 1603 */
1596static void cpsw_port_config(struct cpswx_slave *slave, int max_rx_len) 1604static void cpsw_port_config(struct cpswx_slave *slave, int max_rx_len)
1597{ 1605{
1598 u32 mac_control;
1599
1600 if (max_rx_len > MAX_SIZE_STREAM_BUFFER) 1606 if (max_rx_len > MAX_SIZE_STREAM_BUFFER)
1601 max_rx_len = MAX_SIZE_STREAM_BUFFER; 1607 max_rx_len = MAX_SIZE_STREAM_BUFFER;
1602 1608
1609 slave->mac_control = MACSL_DEFAULT_CONFIG(slave);
1610
1603 __raw_writel(max_rx_len, &slave->sliver->rx_maxlen); 1611 __raw_writel(max_rx_len, &slave->sliver->rx_maxlen);
1604 1612
1605 mac_control = (MACSL_SIG_ENABLE(slave) | 1613 __iowmb();
1606 MACSL_RX_ENABLE_EXT_CTL | 1614 __raw_writel(slave->mac_control, &slave->sliver->mac_control);
1607 MACSL_RX_ENABLE_CSF);
1608 __raw_writel(mac_control, &slave->sliver->mac_control);
1609} 1615}
1610 1616
1611static void cpsw_slave_stop(struct cpswx_slave *slave, struct cpswx_priv *priv) 1617static void cpsw_slave_stop(struct cpswx_slave *slave, struct cpswx_priv *priv)
@@ -1624,15 +1630,17 @@ static void cpsw_slave_link(struct cpswx_slave *slave,
1624 struct cpswx_intf *cpsw_intf) 1630 struct cpswx_intf *cpsw_intf)
1625{ 1631{
1626 struct netcp_priv *netcp = netdev_priv(cpsw_intf->ndev); 1632 struct netcp_priv *netcp = netdev_priv(cpsw_intf->ndev);
1633 int sn = slave->slave_num;
1627 1634
1628 if ((slave->link_interface == SGMII_LINK_MAC_PHY) || 1635 if ((slave->link_interface == SGMII_LINK_MAC_PHY) ||
1629 (slave->link_interface == XGMII_LINK_MAC_PHY)) { 1636 (slave->link_interface == XGMII_LINK_MAC_PHY)) {
1630 if (netcp->link_state) 1637 /* check only the bit in phy_link_state_mask
1631 cpsw_intf->sgmii_link |= BIT(slave->slave_num); 1638 * that corresponds to the slave
1632 else 1639 */
1633 cpsw_intf->sgmii_link &= ~BIT(slave->slave_num); 1640 if (!(netcp->phy_link_state_mask & BIT(sn)))
1641 cpsw_intf->link_state &= ~BIT(sn);
1634 } else if (slave->link_interface == XGMII_LINK_MAC_MAC_FORCED) 1642 } else if (slave->link_interface == XGMII_LINK_MAC_MAC_FORCED)
1635 cpsw_intf->sgmii_link |= BIT(slave->slave_num); 1643 cpsw_intf->link_state |= BIT(slave->slave_num);
1636} 1644}
1637 1645
1638static void cpsw_slave_open(struct cpswx_slave *slave, 1646static void cpsw_slave_open(struct cpswx_slave *slave,
@@ -1661,9 +1669,6 @@ static void cpsw_slave_open(struct cpswx_slave *slave,
1661 1669
1662 cpsw_set_slave_mac(slave, cpsw_intf); 1670 cpsw_set_slave_mac(slave, cpsw_intf);
1663 1671
1664 slave->mac_control = MACSL_SIG_ENABLE(slave) | MACSL_RX_ENABLE_EXT_CTL |
1665 MACSL_RX_ENABLE_CSF;
1666
1667 slave_port = cpsw_get_slave_port(priv, slave->slave_num); 1672 slave_port = cpsw_get_slave_port(priv, slave->slave_num);
1668 1673
1669 slave->port_num = slave_port; 1674 slave->port_num = slave_port;
@@ -1884,34 +1889,44 @@ static void cpswx_timer(unsigned long arg)
1884 struct cpswx_priv *cpsw_dev = cpsw_intf->cpsw_priv; 1889 struct cpswx_priv *cpsw_dev = cpsw_intf->cpsw_priv;
1885 1890
1886 /* 1891 /*
1887 * if the slave's link_interface is not XGMII, sgmii_link bit 1892 * if the slave's link_interface is not XGMII, link_state bit
1888 * will not be set 1893 * will not be set
1889 */ 1894 */
1890 if (cpsw_dev->multi_if) 1895 if (cpsw_dev->multi_if)
1891 cpsw_intf->sgmii_link = 1896 cpsw_intf->link_state =
1892 keystone_sgmii_get_port_link(cpsw_dev->sgmii_port_regs, 1897 keystone_sgmii_get_port_link(cpsw_dev->sgmii_port_regs,
1893 cpsw_intf->slave_port); 1898 cpsw_intf->slave_port);
1894 else 1899 else
1895 cpsw_intf->sgmii_link = 1900 cpsw_intf->link_state =
1896 keystone_sgmii_link_status(cpsw_dev->sgmii_port_regs, 1901 keystone_sgmii_link_status(cpsw_dev->sgmii_port_regs,
1897 cpsw_intf->num_slaves); 1902 cpsw_intf->num_slaves);
1898 1903
1904 /* if MAC-to-PHY, check phy link status also
1905 * to conclude the intf link's status
1906 */
1899 for_each_slave(cpsw_intf, cpsw_slave_link, cpsw_intf); 1907 for_each_slave(cpsw_intf, cpsw_slave_link, cpsw_intf);
1900 1908
1901 /* FIXME: Don't aggregate link statuses in multi-interface case */ 1909 /* Is this the right logic?
1902 if (cpsw_intf->sgmii_link) { 1910 * multi_if & MAC_PHY: phy state machine already reported carrier
1903 /* link ON */ 1911 * multi_if & !MAC_PHY: report carrier
1904 if (!netif_carrier_ok(cpsw_intf->ndev)) 1912 * !multi_if: any one slave up means intf is up, reporting carrier
1913 * here corrects what phy state machine (if it exists)
1914 * might have reported.
1915 */
1916 if (!cpsw_dev->multi_if ||
1917 (cpsw_dev->multi_if &&
1918 (cpsw_intf->slaves->link_interface != SGMII_LINK_MAC_PHY) &&
1919 (cpsw_intf->slaves->link_interface != XGMII_LINK_MAC_PHY))) {
1920 if (cpsw_intf->link_state)
1905 netif_carrier_on(cpsw_intf->ndev); 1921 netif_carrier_on(cpsw_intf->ndev);
1906 } else { 1922 else
1907 /* link OFF */
1908 if (netif_carrier_ok(cpsw_intf->ndev))
1909 netif_carrier_off(cpsw_intf->ndev); 1923 netif_carrier_off(cpsw_intf->ndev);
1910 } 1924 }
1911 1925
1912 spin_lock_bh(&cpsw_dev->hw_stats_lock); 1926 /* A timer runs as a BH, no need to block them */
1927 spin_lock(&cpsw_dev->hw_stats_lock);
1913 cpswx_update_stats(cpsw_dev, NULL); 1928 cpswx_update_stats(cpsw_dev, NULL);
1914 spin_unlock_bh(&cpsw_dev->hw_stats_lock); 1929 spin_unlock(&cpsw_dev->hw_stats_lock);
1915 1930
1916 cpsw_intf->timer.expires = jiffies + (HZ/10); 1931 cpsw_intf->timer.expires = jiffies + (HZ/10);
1917 add_timer(&cpsw_intf->timer); 1932 add_timer(&cpsw_intf->timer);