diff options
Diffstat (limited to 'drivers/net/ethernet/ti/keystone_ethss.c')
-rw-r--r-- | drivers/net/ethernet/ti/keystone_ethss.c | 87 |
1 files changed, 57 insertions, 30 deletions
diff --git a/drivers/net/ethernet/ti/keystone_ethss.c b/drivers/net/ethernet/ti/keystone_ethss.c index e2aebf708dc..dc0ed03df54 100644 --- a/drivers/net/ethernet/ti/keystone_ethss.c +++ b/drivers/net/ethernet/ti/keystone_ethss.c | |||
@@ -63,6 +63,9 @@ | |||
63 | #define MACSL_RX_ENABLE_CSF BIT(23) | 63 | #define MACSL_RX_ENABLE_CSF BIT(23) |
64 | #define MACSL_RX_ENABLE_EXT_CTL BIT(18) | 64 | #define MACSL_RX_ENABLE_EXT_CTL BIT(18) |
65 | #define MACSL_ENABLE BIT(5) | 65 | #define MACSL_ENABLE BIT(5) |
66 | #define MACSL_DEFAULT_CONFIG (MACSL_ENABLE |\ | ||
67 | MACSL_RX_ENABLE_EXT_CTL |\ | ||
68 | MACSL_RX_ENABLE_CSF) | ||
66 | #define GMACSL_RET_WARN_RESET_INCOMPLETE -2 | 69 | #define GMACSL_RET_WARN_RESET_INCOMPLETE -2 |
67 | 70 | ||
68 | #define CPSW_NUM_PORTS 5 | 71 | #define CPSW_NUM_PORTS 5 |
@@ -154,10 +157,13 @@ | |||
154 | 157 | ||
155 | #define MAX_SLAVES 4 | 158 | #define MAX_SLAVES 4 |
156 | 159 | ||
157 | /* s: 0-based slave_port */ | 160 | /* s: 0-based slave_num */ |
158 | #define SGMII_BASE(s) \ | 161 | #define SGMII_BASE(s) \ |
159 | (((s) < 2) ? cpsw_dev->sgmii_port_regs : cpsw_dev->sgmii_port34_regs) | 162 | (((s) < 2) ? cpsw_dev->sgmii_port_regs : cpsw_dev->sgmii_port34_regs) |
160 | 163 | ||
164 | #define IS_SGMII_MAC_PHY(i) \ | ||
165 | (((i) == SGMII_LINK_MAC_PHY) || ((i) == SGMII_LINK_MAC_PHY_MASTER)) | ||
166 | |||
161 | /* CPSW SERDES */ | 167 | /* CPSW SERDES */ |
162 | #define CPSW_SERDES_MAX_NUM 1 | 168 | #define CPSW_SERDES_MAX_NUM 1 |
163 | #define CPSW_LANE_NUM_PER_SERDES 4 | 169 | #define CPSW_LANE_NUM_PER_SERDES 4 |
@@ -169,6 +175,9 @@ struct cpts_port_ts_ctl { | |||
169 | u8 ts_mcast_type; | 175 | u8 ts_mcast_type; |
170 | }; | 176 | }; |
171 | 177 | ||
178 | /* slave_num: 0-based | ||
179 | * port_num: 1-based | ||
180 | */ | ||
172 | struct cpsw_slave { | 181 | struct cpsw_slave { |
173 | struct cpsw_slave_regs __iomem *regs; | 182 | struct cpsw_slave_regs __iomem *regs; |
174 | struct cpsw_sliver_regs __iomem *sliver; | 183 | struct cpsw_sliver_regs __iomem *sliver; |
@@ -547,8 +556,11 @@ struct cpsw_priv { | |||
547 | u32 num_serdes; | 556 | u32 num_serdes; |
548 | u32 serdes_lanes; | 557 | u32 serdes_lanes; |
549 | struct serdes serdes; | 558 | struct serdes serdes; |
559 | u32 opened; | ||
550 | }; | 560 | }; |
551 | 561 | ||
562 | /* slave_port: 0-based (currently relevant only in multi_if mode) | ||
563 | */ | ||
552 | struct cpsw_intf { | 564 | struct cpsw_intf { |
553 | struct net_device *ndev; | 565 | struct net_device *ndev; |
554 | struct device *dev; | 566 | struct device *dev; |
@@ -564,7 +576,7 @@ struct cpsw_intf { | |||
564 | u32 multi_if; | 576 | u32 multi_if; |
565 | struct list_head cpsw_intf_list; | 577 | struct list_head cpsw_intf_list; |
566 | struct timer_list timer; | 578 | struct timer_list timer; |
567 | u32 sgmii_link; | 579 | u32 link_state; |
568 | }; | 580 | }; |
569 | 581 | ||
570 | static struct cpsw_priv *global_priv; /* FIXME: REMOVE THIS!! */ | 582 | static struct cpsw_priv *global_priv; /* FIXME: REMOVE THIS!! */ |
@@ -2101,8 +2113,7 @@ static void _cpsw_adjust_link(struct cpsw_slave *slave, bool *link) | |||
2101 | 2113 | ||
2102 | if (phy->link) { | 2114 | if (phy->link) { |
2103 | mac_control = slave->mac_control; | 2115 | mac_control = slave->mac_control; |
2104 | mac_control |= MACSL_ENABLE | MACSL_RX_ENABLE_EXT_CTL | | 2116 | mac_control |= MACSL_DEFAULT_CONFIG; |
2105 | MACSL_RX_ENABLE_CSF; | ||
2106 | /* enable forwarding */ | 2117 | /* enable forwarding */ |
2107 | cpsw_ale_control_set(slave->ale, slave_port, | 2118 | cpsw_ale_control_set(slave->ale, slave_port, |
2108 | ALE_PORT_STATE, ALE_PORT_STATE_FORWARD); | 2119 | ALE_PORT_STATE, ALE_PORT_STATE_FORWARD); |
@@ -2137,9 +2148,9 @@ static void cpsw_adjust_link(struct net_device *n_dev, void *context) | |||
2137 | _cpsw_adjust_link(slave, &link); | 2148 | _cpsw_adjust_link(slave, &link); |
2138 | 2149 | ||
2139 | if (link) | 2150 | if (link) |
2140 | netcp->link_state |= BIT(slave->slave_num); | 2151 | netcp->phy_link_state_mask |= BIT(slave->slave_num); |
2141 | else | 2152 | else |
2142 | netcp->link_state &= ~BIT(slave->slave_num); | 2153 | netcp->phy_link_state_mask &= ~BIT(slave->slave_num); |
2143 | } | 2154 | } |
2144 | 2155 | ||
2145 | /* | 2156 | /* |
@@ -2174,11 +2185,12 @@ static void cpsw_port_config(struct cpsw_slave *slave, int max_rx_len) | |||
2174 | if (max_rx_len > MAX_SIZE_STREAM_BUFFER) | 2185 | if (max_rx_len > MAX_SIZE_STREAM_BUFFER) |
2175 | max_rx_len = MAX_SIZE_STREAM_BUFFER; | 2186 | max_rx_len = MAX_SIZE_STREAM_BUFFER; |
2176 | 2187 | ||
2188 | slave->mac_control = MACSL_DEFAULT_CONFIG; | ||
2189 | |||
2177 | __raw_writel(max_rx_len, &slave->sliver->rx_maxlen); | 2190 | __raw_writel(max_rx_len, &slave->sliver->rx_maxlen); |
2178 | 2191 | ||
2179 | __iowmb(); | 2192 | __iowmb(); |
2180 | __raw_writel(MACSL_ENABLE | MACSL_RX_ENABLE_EXT_CTL | | 2193 | __raw_writel(slave->mac_control, &slave->sliver->mac_control); |
2181 | MACSL_RX_ENABLE_CSF, &slave->sliver->mac_control); | ||
2182 | } | 2194 | } |
2183 | 2195 | ||
2184 | static void cpsw_slave_stop(struct cpsw_slave *slave, | 2196 | static void cpsw_slave_stop(struct cpsw_slave *slave, |
@@ -2213,12 +2225,14 @@ static void cpsw_slave_link(struct cpsw_slave *slave, | |||
2213 | struct cpsw_intf *cpsw_intf) | 2225 | struct cpsw_intf *cpsw_intf) |
2214 | { | 2226 | { |
2215 | struct netcp_priv *netcp = netdev_priv(cpsw_intf->ndev); | 2227 | struct netcp_priv *netcp = netdev_priv(cpsw_intf->ndev); |
2228 | int sn = slave->slave_num; | ||
2216 | 2229 | ||
2217 | if (slave->link_interface == SGMII_LINK_MAC_PHY) { | 2230 | if (IS_SGMII_MAC_PHY(slave->link_interface)) { |
2218 | if (netcp->link_state) | 2231 | /* check only the bit in phy_link_state_mask |
2219 | cpsw_intf->sgmii_link |= BIT(slave->slave_num); | 2232 | * that corresponds to the slave |
2220 | else | 2233 | */ |
2221 | cpsw_intf->sgmii_link &= ~BIT(slave->slave_num); | 2234 | if (!(netcp->phy_link_state_mask & BIT(sn))) |
2235 | cpsw_intf->link_state &= ~BIT(sn); | ||
2222 | } | 2236 | } |
2223 | } | 2237 | } |
2224 | 2238 | ||
@@ -2247,9 +2261,6 @@ static void cpsw_slave_open(struct cpsw_slave *slave, | |||
2247 | 2261 | ||
2248 | cpsw_set_slave_mac(slave, cpsw_intf); | 2262 | cpsw_set_slave_mac(slave, cpsw_intf); |
2249 | 2263 | ||
2250 | slave->mac_control = MACSL_ENABLE | MACSL_RX_ENABLE_EXT_CTL | | ||
2251 | MACSL_RX_ENABLE_CSF; | ||
2252 | |||
2253 | /* this slave port here is 1 based */ | 2264 | /* this slave port here is 1 based */ |
2254 | slave_port = cpsw_get_slave_port(priv, slave->slave_num); | 2265 | slave_port = cpsw_get_slave_port(priv, slave->slave_num); |
2255 | 2266 | ||
@@ -2264,7 +2275,7 @@ static void cpsw_slave_open(struct cpsw_slave *slave, | |||
2264 | cpsw_ale_add_mcast(priv->ale, cpsw_intf->ndev->broadcast, | 2275 | cpsw_ale_add_mcast(priv->ale, cpsw_intf->ndev->broadcast, |
2265 | 1 << slave_port, 0, 0, ALE_MCAST_FWD_2); | 2276 | 1 << slave_port, 0, 0, ALE_MCAST_FWD_2); |
2266 | 2277 | ||
2267 | if (slave->link_interface == SGMII_LINK_MAC_PHY) { | 2278 | if (IS_SGMII_MAC_PHY(slave->link_interface)) { |
2268 | slave->phy = of_phy_connect(cpsw_intf->ndev, | 2279 | slave->phy = of_phy_connect(cpsw_intf->ndev, |
2269 | cpsw_intf->phy_node, | 2280 | cpsw_intf->phy_node, |
2270 | &cpsw_adjust_link, 0, | 2281 | &cpsw_adjust_link, 0, |
@@ -2393,6 +2404,9 @@ int cpsw_add_addr(void *intf_priv, struct netcp_addr *naddr) | |||
2393 | struct cpsw_intf *cpsw_intf = intf_priv; | 2404 | struct cpsw_intf *cpsw_intf = intf_priv; |
2394 | struct cpsw_priv *cpsw_dev = cpsw_intf->cpsw_priv; | 2405 | struct cpsw_priv *cpsw_dev = cpsw_intf->cpsw_priv; |
2395 | 2406 | ||
2407 | if (!cpsw_dev->opened) | ||
2408 | return -ENXIO; | ||
2409 | |||
2396 | dev_dbg(cpsw_dev->dev, "ethss adding address %pM, type %d\n", | 2410 | dev_dbg(cpsw_dev->dev, "ethss adding address %pM, type %d\n", |
2397 | naddr->addr, naddr->type); | 2411 | naddr->addr, naddr->type); |
2398 | 2412 | ||
@@ -2419,6 +2433,9 @@ int cpsw_del_addr(void *intf_priv, struct netcp_addr *naddr) | |||
2419 | struct cpsw_intf *cpsw_intf = intf_priv; | 2433 | struct cpsw_intf *cpsw_intf = intf_priv; |
2420 | struct cpsw_priv *cpsw_dev = cpsw_intf->cpsw_priv; | 2434 | struct cpsw_priv *cpsw_dev = cpsw_intf->cpsw_priv; |
2421 | 2435 | ||
2436 | if (!cpsw_dev->opened) | ||
2437 | return -ENXIO; | ||
2438 | |||
2422 | dev_dbg(cpsw_dev->dev, "ethss deleting address %pM, type %d\n", | 2439 | dev_dbg(cpsw_dev->dev, "ethss deleting address %pM, type %d\n", |
2423 | naddr->addr, naddr->type); | 2440 | naddr->addr, naddr->type); |
2424 | 2441 | ||
@@ -2639,10 +2656,10 @@ static void cpsw_timer(unsigned long arg) | |||
2639 | struct cpsw_priv *cpsw_dev = cpsw_intf->cpsw_priv; | 2656 | struct cpsw_priv *cpsw_dev = cpsw_intf->cpsw_priv; |
2640 | u32 sp = cpsw_intf->slave_port; | 2657 | u32 sp = cpsw_intf->slave_port; |
2641 | u32 ns = cpsw_intf->num_slaves; | 2658 | u32 ns = cpsw_intf->num_slaves; |
2642 | u32 sgmii_link; | 2659 | u32 link_state; |
2643 | 2660 | ||
2644 | if (cpsw_dev->multi_if) | 2661 | if (cpsw_dev->multi_if) |
2645 | sgmii_link = keystone_sgmii_get_port_link(SGMII_BASE(sp), sp); | 2662 | link_state = keystone_sgmii_get_port_link(SGMII_BASE(sp), sp); |
2646 | else { | 2663 | else { |
2647 | /* Single interface mode. Link is up if any one slave | 2664 | /* Single interface mode. Link is up if any one slave |
2648 | * port is up. It assumes slave port always starts from | 2665 | * port is up. It assumes slave port always starts from |
@@ -2650,28 +2667,36 @@ static void cpsw_timer(unsigned long arg) | |||
2650 | */ | 2667 | */ |
2651 | 2668 | ||
2652 | /* slave port 2, 3 status */ | 2669 | /* slave port 2, 3 status */ |
2653 | sgmii_link = keystone_sgmii_link_status(SGMII_BASE(2), | 2670 | link_state = keystone_sgmii_link_status(SGMII_BASE(2), |
2654 | max_t(u32, ns, 2) - 2); | 2671 | max_t(u32, ns, 2) - 2); |
2655 | 2672 | ||
2656 | sgmii_link <<= 2; | 2673 | link_state <<= 2; |
2657 | 2674 | ||
2658 | /* slave port 0, 1 status */ | 2675 | /* slave port 0, 1 status */ |
2659 | sgmii_link |= keystone_sgmii_link_status(SGMII_BASE(0), | 2676 | link_state |= keystone_sgmii_link_status(SGMII_BASE(0), |
2660 | min_t(u32, ns, 2)); | 2677 | min_t(u32, ns, 2)); |
2661 | } | 2678 | } |
2662 | 2679 | ||
2663 | cpsw_intf->sgmii_link = sgmii_link; | 2680 | cpsw_intf->link_state = link_state; |
2664 | 2681 | ||
2682 | /* if MAC-to-PHY, check phy link status also | ||
2683 | * to conclude the intf link's status | ||
2684 | */ | ||
2665 | for_each_slave(cpsw_intf, cpsw_slave_link, cpsw_intf); | 2685 | for_each_slave(cpsw_intf, cpsw_slave_link, cpsw_intf); |
2666 | 2686 | ||
2667 | /* FIXME: Don't aggregate link statuses in multi-interface case */ | 2687 | /* Is this the right logic? |
2668 | if (cpsw_intf->sgmii_link) { | 2688 | * multi_if & MAC_PHY: phy state machine already reported carrier |
2669 | /* link ON */ | 2689 | * multi_if & !MAC_PHY: report carrier |
2670 | if (!netif_carrier_ok(cpsw_intf->ndev)) | 2690 | * !multi_if: any one slave up means intf is up, reporting carrier |
2691 | * here corrects what phy state machine (if it exists) | ||
2692 | * might have reported. | ||
2693 | */ | ||
2694 | if (!cpsw_dev->multi_if || | ||
2695 | (cpsw_dev->multi_if && | ||
2696 | !IS_SGMII_MAC_PHY(cpsw_intf->slaves->link_interface))) { | ||
2697 | if (cpsw_intf->link_state) | ||
2671 | netif_carrier_on(cpsw_intf->ndev); | 2698 | netif_carrier_on(cpsw_intf->ndev); |
2672 | } else { | 2699 | else |
2673 | /* link OFF */ | ||
2674 | if (netif_carrier_ok(cpsw_intf->ndev)) | ||
2675 | netif_carrier_off(cpsw_intf->ndev); | 2700 | netif_carrier_off(cpsw_intf->ndev); |
2676 | } | 2701 | } |
2677 | 2702 | ||
@@ -3078,6 +3103,7 @@ static int cpsw_open(void *intf_priv, struct net_device *ndev) | |||
3078 | PSTREAM_ROUTE_DMA); | 3103 | PSTREAM_ROUTE_DMA); |
3079 | 3104 | ||
3080 | cpsw_register_cpts(cpsw_dev); | 3105 | cpsw_register_cpts(cpsw_dev); |
3106 | cpsw_dev->opened = 1; | ||
3081 | return 0; | 3107 | return 0; |
3082 | 3108 | ||
3083 | ale_fail: | 3109 | ale_fail: |
@@ -3117,6 +3143,7 @@ static int cpsw_close(void *intf_priv, struct net_device *ndev) | |||
3117 | clk_put(cpsw_dev->cpgmac); | 3143 | clk_put(cpsw_dev->cpgmac); |
3118 | 3144 | ||
3119 | cpsw_unregister_cpts(cpsw_dev); | 3145 | cpsw_unregister_cpts(cpsw_dev); |
3146 | cpsw_dev->opened = 0; | ||
3120 | return 0; | 3147 | return 0; |
3121 | } | 3148 | } |
3122 | 3149 | ||