diff options
Diffstat (limited to 'drivers/staging/octeon')
-rw-r--r-- | drivers/staging/octeon/Kconfig | 1 | ||||
-rw-r--r-- | drivers/staging/octeon/TODO | 9 | ||||
-rw-r--r-- | drivers/staging/octeon/ethernet-mdio.c | 2 | ||||
-rw-r--r-- | drivers/staging/octeon/ethernet-tx.c | 20 | ||||
-rw-r--r-- | drivers/staging/octeon/ethernet.c | 42 | ||||
-rw-r--r-- | drivers/staging/octeon/octeon-ethernet.h | 4 |
6 files changed, 61 insertions, 17 deletions
diff --git a/drivers/staging/octeon/Kconfig b/drivers/staging/octeon/Kconfig index 6e1d5f8d3ec1..1e3012b9991c 100644 --- a/drivers/staging/octeon/Kconfig +++ b/drivers/staging/octeon/Kconfig @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 config OCTEON_ETHERNET tristate "Cavium Networks Octeon Ethernet support" depends on CAVIUM_OCTEON_SOC && NETDEVICES diff --git a/drivers/staging/octeon/TODO b/drivers/staging/octeon/TODO new file mode 100644 index 000000000000..67a0a1f6b922 --- /dev/null +++ b/drivers/staging/octeon/TODO @@ -0,0 +1,9 @@ +This driver is functional and supports Ethernet on OCTEON+/OCTEON2/OCTEON3 +chips at least up to CN7030. + +TODO: + - general code review and clean up + - make driver self-contained instead of being split between staging and + arch/mips/cavium-octeon. + +Contact: Aaro Koskinen <aaro.koskinen@iki.fi> diff --git a/drivers/staging/octeon/ethernet-mdio.c b/drivers/staging/octeon/ethernet-mdio.c index d6248eecf123..2aee64fdaec5 100644 --- a/drivers/staging/octeon/ethernet-mdio.c +++ b/drivers/staging/octeon/ethernet-mdio.c @@ -163,7 +163,7 @@ int cvm_oct_phy_setup_device(struct net_device *dev) goto no_phy; phydev = of_phy_connect(dev, phy_node, cvm_oct_adjust_link, 0, - PHY_INTERFACE_MODE_GMII); + priv->phy_mode); of_node_put(phy_node); if (!phydev) diff --git a/drivers/staging/octeon/ethernet-tx.c b/drivers/staging/octeon/ethernet-tx.c index 317c9720467c..20f513fbaa85 100644 --- a/drivers/staging/octeon/ethernet-tx.c +++ b/drivers/staging/octeon/ethernet-tx.c @@ -214,8 +214,10 @@ int cvm_oct_xmit(struct sk_buff *skb, struct net_device *dev) * Get the number of skbuffs in use * by the hardware */ - skb_to_free = cvmx_fau_fetch_and_add32( - priv->fau + qos * 4, MAX_SKB_TO_FREE); + skb_to_free = + cvmx_fau_fetch_and_add32(priv->fau + + qos * 4, + MAX_SKB_TO_FREE); } skb_to_free = cvm_oct_adjust_skb_to_free(skb_to_free, priv->fau + @@ -280,9 +282,9 @@ int cvm_oct_xmit(struct sk_buff *skb, struct net_device *dev) for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { struct skb_frag_struct *fs = skb_shinfo(skb)->frags + i; - hw_buffer.s.addr = XKPHYS_TO_PHYS( - (u64)(page_address(fs->page.p) + - fs->page_offset)); + hw_buffer.s.addr = + XKPHYS_TO_PHYS((u64)(page_address(fs->page.p) + + fs->page_offset)); hw_buffer.s.size = fs->size; CVM_OCT_SKB_CB(skb)[i + 1] = hw_buffer.u64; } @@ -413,8 +415,8 @@ dont_put_skbuff_in_hw: queue_type = QUEUE_HW; } if (USE_ASYNC_IOBDMA) - cvmx_fau_async_fetch_and_add32( - CVMX_SCR_SCRATCH, FAU_TOTAL_TX_TO_CLEAN, 1); + cvmx_fau_async_fetch_and_add32(CVMX_SCR_SCRATCH, + FAU_TOTAL_TX_TO_CLEAN, 1); spin_lock_irqsave(&priv->tx_free_list[qos].lock, flags); @@ -491,8 +493,8 @@ skip_xmit: cvmx_scratch_write64(CVMX_SCR_SCRATCH, old_scratch); cvmx_scratch_write64(CVMX_SCR_SCRATCH + 8, old_scratch2); } else { - total_to_clean = cvmx_fau_fetch_and_add32( - FAU_TOTAL_TX_TO_CLEAN, 1); + total_to_clean = + cvmx_fau_fetch_and_add32(FAU_TOTAL_TX_TO_CLEAN, 1); } if (total_to_clean & 0x3ff) { diff --git a/drivers/staging/octeon/ethernet.c b/drivers/staging/octeon/ethernet.c index ce61c5670ef6..8847a11c212f 100644 --- a/drivers/staging/octeon/ethernet.c +++ b/drivers/staging/octeon/ethernet.c @@ -421,7 +421,7 @@ int cvm_oct_common_init(struct net_device *dev) if (priv->of_node) mac = of_get_mac_address(priv->of_node); - if (mac) + if (!IS_ERR_OR_NULL(mac)) ether_addr_copy(dev->dev_addr, mac); else eth_hw_addr_random(dev); @@ -653,14 +653,37 @@ static struct device_node *cvm_oct_node_for_port(struct device_node *pip, return np; } -static void cvm_set_rgmii_delay(struct device_node *np, int iface, int port) +static void cvm_set_rgmii_delay(struct octeon_ethernet *priv, int iface, + int port) { + struct device_node *np = priv->of_node; u32 delay_value; + bool rx_delay; + bool tx_delay; - if (!of_property_read_u32(np, "rx-delay", &delay_value)) + /* By default, both RX/TX delay is enabled in + * __cvmx_helper_rgmii_enable(). + */ + rx_delay = true; + tx_delay = true; + + if (!of_property_read_u32(np, "rx-delay", &delay_value)) { cvmx_write_csr(CVMX_ASXX_RX_CLK_SETX(port, iface), delay_value); - if (!of_property_read_u32(np, "tx-delay", &delay_value)) + rx_delay = delay_value > 0; + } + if (!of_property_read_u32(np, "tx-delay", &delay_value)) { cvmx_write_csr(CVMX_ASXX_TX_CLK_SETX(port, iface), delay_value); + tx_delay = delay_value > 0; + } + + if (!rx_delay && !tx_delay) + priv->phy_mode = PHY_INTERFACE_MODE_RGMII_ID; + else if (!rx_delay) + priv->phy_mode = PHY_INTERFACE_MODE_RGMII_RXID; + else if (!tx_delay) + priv->phy_mode = PHY_INTERFACE_MODE_RGMII_TXID; + else + priv->phy_mode = PHY_INTERFACE_MODE_RGMII; } static int cvm_oct_probe(struct platform_device *pdev) @@ -825,6 +848,7 @@ static int cvm_oct_probe(struct platform_device *pdev) priv->port = port; priv->queue = cvmx_pko_get_base_queue(priv->port); priv->fau = fau - cvmx_pko_get_num_queues(port) * 4; + priv->phy_mode = PHY_INTERFACE_MODE_NA; for (qos = 0; qos < 16; qos++) skb_queue_head_init(&priv->tx_free_list[qos]); for (qos = 0; qos < cvmx_pko_get_num_queues(port); @@ -856,6 +880,7 @@ static int cvm_oct_probe(struct platform_device *pdev) break; case CVMX_HELPER_INTERFACE_MODE_SGMII: + priv->phy_mode = PHY_INTERFACE_MODE_SGMII; dev->netdev_ops = &cvm_oct_sgmii_netdev_ops; strcpy(dev->name, "eth%d"); break; @@ -865,11 +890,16 @@ static int cvm_oct_probe(struct platform_device *pdev) strcpy(dev->name, "spi%d"); break; - case CVMX_HELPER_INTERFACE_MODE_RGMII: case CVMX_HELPER_INTERFACE_MODE_GMII: + priv->phy_mode = PHY_INTERFACE_MODE_GMII; + dev->netdev_ops = &cvm_oct_rgmii_netdev_ops; + strcpy(dev->name, "eth%d"); + break; + + case CVMX_HELPER_INTERFACE_MODE_RGMII: dev->netdev_ops = &cvm_oct_rgmii_netdev_ops; strcpy(dev->name, "eth%d"); - cvm_set_rgmii_delay(priv->of_node, interface, + cvm_set_rgmii_delay(priv, interface, port_index); break; } diff --git a/drivers/staging/octeon/octeon-ethernet.h b/drivers/staging/octeon/octeon-ethernet.h index 4a07e7f43d12..be570d33685a 100644 --- a/drivers/staging/octeon/octeon-ethernet.h +++ b/drivers/staging/octeon/octeon-ethernet.h @@ -12,7 +12,7 @@ #define OCTEON_ETHERNET_H #include <linux/of.h> - +#include <linux/phy.h> #include <asm/octeon/cvmx-helper-board.h> /** @@ -33,6 +33,8 @@ struct octeon_ethernet { * cvmx_helper_interface_mode_t */ int imode; + /* PHY mode */ + phy_interface_t phy_mode; /* List of outstanding tx buffers per queue */ struct sk_buff_head tx_free_list[16]; unsigned int last_speed; |