Commit 2ce66f9c authored by David S. Miller's avatar David S. Miller

Merge branch 'xgene-next'

Iyappan Subramanian says:

====================
Fix warning and issues

This patch set fixes the following warning and issues,

  1. Fix compiler warnings
  	- drivers: net: xgene: Fix compiler warnings
  2. unmap DMA memory on xgene_Enet_delete_bufpoool()
	- drivers: net: xgene: fix: Add dma_unmap_single
  3. Delete descriptor rings and buffer pools on error
	- drivers: net: xgene: fix: Delete descriptor rings and buffer pools
  4. Fix error desconstruction on probe()
 	- drivers: net: xgene: Fix error deconstruction path
  5. Fix RSS indirection table fields
 	- drivers: net: xgene: Fix RSS indirection table fields
  6. Change the port init sequence as per hardware specification
	- drivers: net: xgene: Change port init sequence
  7. Fix link not recovered after link is down issue
	- drivers: net: xgene: XFI PCS reset when link is down
  8. Fix link up is reported when no SFP+ module is plugged in issue
	- drivers: net: xgene: Poll link status via GPIO
	- dtb: xgene: Add rxlos-gpios property
	- Documentation: dtb: xgene: Add rxlos GPIO mapping
  9. Fix backward compatibility when used with older driver
	- drivers: net: xgene: Fix backward compatibility
	- dtb: xgene: Fix backward compatibility

v2: Address review comments from v1
	- Fixed compiler warnings
	- Removed kbuild fix patch, since Arnd submitted the same
	- Changed Kconfig to select GPIOLIB (to fix kbuild warning)
	- Added rxlos-gpio documentation
	- Fixed backward compatibility with older driver

v1:
	- Initial version
====================
Signed-off-by: default avatarIyappan Subramanian <isubramanian@apm.com>
Tested-by: default avatarFushen Chen <fchen@apm.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 1c238763 5ac6caab
...@@ -47,6 +47,9 @@ Optional properties: ...@@ -47,6 +47,9 @@ Optional properties:
Valid values are between 0 to 7, that maps to Valid values are between 0 to 7, that maps to
273, 589, 899, 1222, 1480, 1806, 2147, 2464 ps 273, 589, 899, 1222, 1480, 1806, 2147, 2464 ps
Default value is 2, which corresponds to 899 ps Default value is 2, which corresponds to 899 ps
- rxlos-gpios: Input gpio from SFP+ module to indicate availability of
incoming signal.
Example: Example:
menetclk: menetclk { menetclk: menetclk {
......
...@@ -74,6 +74,7 @@ &sgenet1 { ...@@ -74,6 +74,7 @@ &sgenet1 {
&xgenet { &xgenet {
status = "ok"; status = "ok";
rxlos-gpios = <&sbgpio 12 1>;
}; };
&mmc0 { &mmc0 {
......
...@@ -923,7 +923,7 @@ menet: ethernet@17020000 { ...@@ -923,7 +923,7 @@ menet: ethernet@17020000 {
/* mac address will be overwritten by the bootloader */ /* mac address will be overwritten by the bootloader */
local-mac-address = [00 00 00 00 00 00]; local-mac-address = [00 00 00 00 00 00];
phy-connection-type = "rgmii"; phy-connection-type = "rgmii";
phy-handle = <&menet0phy>,<&menetphy>; phy-handle = <&menetphy>,<&menet0phy>;
mdio { mdio {
compatible = "apm,xgene-mdio"; compatible = "apm,xgene-mdio";
#address-cells = <1>; #address-cells = <1>;
......
...@@ -4,6 +4,7 @@ config NET_XGENE ...@@ -4,6 +4,7 @@ config NET_XGENE
depends on ARCH_XGENE || COMPILE_TEST depends on ARCH_XGENE || COMPILE_TEST
select PHYLIB select PHYLIB
select MDIO_XGENE select MDIO_XGENE
select GPIOLIB
help help
This is the Ethernet driver for the on-chip ethernet interface on the This is the Ethernet driver for the on-chip ethernet interface on the
APM X-Gene SoC. APM X-Gene SoC.
......
...@@ -32,12 +32,19 @@ static void xgene_cle_sband_to_hw(u8 frag, enum xgene_cle_prot_version ver, ...@@ -32,12 +32,19 @@ static void xgene_cle_sband_to_hw(u8 frag, enum xgene_cle_prot_version ver,
SET_VAL(SB_HDRLEN, len); SET_VAL(SB_HDRLEN, len);
} }
static void xgene_cle_idt_to_hw(u32 dstqid, u32 fpsel, static void xgene_cle_idt_to_hw(struct xgene_enet_pdata *pdata,
u32 dstqid, u32 fpsel,
u32 nfpsel, u32 *idt_reg) u32 nfpsel, u32 *idt_reg)
{ {
if (pdata->enet_id == XGENE_ENET1) {
*idt_reg = SET_VAL(IDT_DSTQID, dstqid) |
SET_VAL(IDT_FPSEL1, fpsel) |
SET_VAL(IDT_NFPSEL1, nfpsel);
} else {
*idt_reg = SET_VAL(IDT_DSTQID, dstqid) | *idt_reg = SET_VAL(IDT_DSTQID, dstqid) |
SET_VAL(IDT_FPSEL, fpsel) | SET_VAL(IDT_FPSEL, fpsel) |
SET_VAL(IDT_NFPSEL, nfpsel); SET_VAL(IDT_NFPSEL, nfpsel);
}
} }
static void xgene_cle_dbptr_to_hw(struct xgene_enet_pdata *pdata, static void xgene_cle_dbptr_to_hw(struct xgene_enet_pdata *pdata,
...@@ -344,7 +351,7 @@ static int xgene_cle_set_rss_idt(struct xgene_enet_pdata *pdata) ...@@ -344,7 +351,7 @@ static int xgene_cle_set_rss_idt(struct xgene_enet_pdata *pdata)
nfpsel = 0; nfpsel = 0;
idt_reg = 0; idt_reg = 0;
xgene_cle_idt_to_hw(dstqid, fpsel, nfpsel, &idt_reg); xgene_cle_idt_to_hw(pdata, dstqid, fpsel, nfpsel, &idt_reg);
ret = xgene_cle_dram_wr(&pdata->cle, &idt_reg, 1, i, ret = xgene_cle_dram_wr(&pdata->cle, &idt_reg, 1, i,
RSS_IDT, CLE_CMD_WR); RSS_IDT, CLE_CMD_WR);
if (ret) if (ret)
......
...@@ -196,9 +196,13 @@ enum xgene_cle_ptree_dbptrs { ...@@ -196,9 +196,13 @@ enum xgene_cle_ptree_dbptrs {
#define IDT_DSTQID_POS 0 #define IDT_DSTQID_POS 0
#define IDT_DSTQID_LEN 12 #define IDT_DSTQID_LEN 12
#define IDT_FPSEL_POS 12 #define IDT_FPSEL_POS 12
#define IDT_FPSEL_LEN 4 #define IDT_FPSEL_LEN 5
#define IDT_NFPSEL_POS 16 #define IDT_NFPSEL_POS 17
#define IDT_NFPSEL_LEN 4 #define IDT_NFPSEL_LEN 5
#define IDT_FPSEL1_POS 12
#define IDT_FPSEL1_LEN 4
#define IDT_NFPSEL1_POS 16
#define IDT_NFPSEL1_LEN 4
struct xgene_cle_ptree_branch { struct xgene_cle_ptree_branch {
bool valid; bool valid;
......
...@@ -761,18 +761,18 @@ int xgene_enet_phy_connect(struct net_device *ndev) ...@@ -761,18 +761,18 @@ int xgene_enet_phy_connect(struct net_device *ndev)
if (dev->of_node) { if (dev->of_node) {
for (i = 0 ; i < 2; i++) { for (i = 0 ; i < 2; i++) {
np = of_parse_phandle(dev->of_node, "phy-handle", i); np = of_parse_phandle(dev->of_node, "phy-handle", i);
if (np)
break;
}
if (!np) { if (!np)
netdev_dbg(ndev, "No phy-handle found in DT\n"); continue;
return -ENODEV;
}
phy_dev = of_phy_connect(ndev, np, &xgene_enet_adjust_link, phy_dev = of_phy_connect(ndev, np,
&xgene_enet_adjust_link,
0, pdata->phy_mode); 0, pdata->phy_mode);
of_node_put(np); of_node_put(np);
if (phy_dev)
break;
}
if (!phy_dev) { if (!phy_dev) {
netdev_err(ndev, "Could not connect to PHY\n"); netdev_err(ndev, "Could not connect to PHY\n");
return -ENODEV; return -ENODEV;
......
...@@ -124,6 +124,12 @@ enum xgene_enet_rm { ...@@ -124,6 +124,12 @@ enum xgene_enet_rm {
#define MAC_READ_REG_OFFSET 0x0c #define MAC_READ_REG_OFFSET 0x0c
#define MAC_COMMAND_DONE_REG_OFFSET 0x10 #define MAC_COMMAND_DONE_REG_OFFSET 0x10
#define PCS_ADDR_REG_OFFSET 0x00
#define PCS_COMMAND_REG_OFFSET 0x04
#define PCS_WRITE_REG_OFFSET 0x08
#define PCS_READ_REG_OFFSET 0x0c
#define PCS_COMMAND_DONE_REG_OFFSET 0x10
#define MII_MGMT_CONFIG_ADDR 0x20 #define MII_MGMT_CONFIG_ADDR 0x20
#define MII_MGMT_COMMAND_ADDR 0x24 #define MII_MGMT_COMMAND_ADDR 0x24
#define MII_MGMT_ADDRESS_ADDR 0x28 #define MII_MGMT_ADDRESS_ADDR 0x28
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <linux/gpio.h>
#include "xgene_enet_main.h" #include "xgene_enet_main.h"
#include "xgene_enet_hw.h" #include "xgene_enet_hw.h"
#include "xgene_enet_sgmac.h" #include "xgene_enet_sgmac.h"
...@@ -72,7 +73,6 @@ static int xgene_enet_refill_bufpool(struct xgene_enet_desc_ring *buf_pool, ...@@ -72,7 +73,6 @@ static int xgene_enet_refill_bufpool(struct xgene_enet_desc_ring *buf_pool,
skb = netdev_alloc_skb_ip_align(ndev, len); skb = netdev_alloc_skb_ip_align(ndev, len);
if (unlikely(!skb)) if (unlikely(!skb))
return -ENOMEM; return -ENOMEM;
buf_pool->rx_skb[tail] = skb;
dma_addr = dma_map_single(dev, skb->data, len, DMA_FROM_DEVICE); dma_addr = dma_map_single(dev, skb->data, len, DMA_FROM_DEVICE);
if (dma_mapping_error(dev, dma_addr)) { if (dma_mapping_error(dev, dma_addr)) {
...@@ -81,6 +81,8 @@ static int xgene_enet_refill_bufpool(struct xgene_enet_desc_ring *buf_pool, ...@@ -81,6 +81,8 @@ static int xgene_enet_refill_bufpool(struct xgene_enet_desc_ring *buf_pool,
return -EINVAL; return -EINVAL;
} }
buf_pool->rx_skb[tail] = skb;
raw_desc->m1 = cpu_to_le64(SET_VAL(DATAADDR, dma_addr) | raw_desc->m1 = cpu_to_le64(SET_VAL(DATAADDR, dma_addr) |
SET_VAL(BUFDATALEN, bufdatalen) | SET_VAL(BUFDATALEN, bufdatalen) |
SET_BIT(COHERENT)); SET_BIT(COHERENT));
...@@ -102,12 +104,21 @@ static u8 xgene_enet_hdr_len(const void *data) ...@@ -102,12 +104,21 @@ static u8 xgene_enet_hdr_len(const void *data)
static void xgene_enet_delete_bufpool(struct xgene_enet_desc_ring *buf_pool) static void xgene_enet_delete_bufpool(struct xgene_enet_desc_ring *buf_pool)
{ {
struct device *dev = ndev_to_dev(buf_pool->ndev);
struct xgene_enet_raw_desc16 *raw_desc;
dma_addr_t dma_addr;
int i; int i;
/* Free up the buffers held by hardware */ /* Free up the buffers held by hardware */
for (i = 0; i < buf_pool->slots; i++) { for (i = 0; i < buf_pool->slots; i++) {
if (buf_pool->rx_skb[i]) if (buf_pool->rx_skb[i]) {
dev_kfree_skb_any(buf_pool->rx_skb[i]); dev_kfree_skb_any(buf_pool->rx_skb[i]);
raw_desc = &buf_pool->raw_desc16[i];
dma_addr = GET_VAL(DATAADDR, le64_to_cpu(raw_desc->m1));
dma_unmap_single(dev, dma_addr, XGENE_ENET_MAX_MTU,
DMA_FROM_DEVICE);
}
} }
} }
...@@ -452,7 +463,6 @@ static int xgene_enet_rx_frame(struct xgene_enet_desc_ring *rx_ring, ...@@ -452,7 +463,6 @@ static int xgene_enet_rx_frame(struct xgene_enet_desc_ring *rx_ring,
struct xgene_enet_raw_desc *raw_desc) struct xgene_enet_raw_desc *raw_desc)
{ {
struct net_device *ndev; struct net_device *ndev;
struct xgene_enet_pdata *pdata;
struct device *dev; struct device *dev;
struct xgene_enet_desc_ring *buf_pool; struct xgene_enet_desc_ring *buf_pool;
u32 datalen, skb_index; u32 datalen, skb_index;
...@@ -461,7 +471,6 @@ static int xgene_enet_rx_frame(struct xgene_enet_desc_ring *rx_ring, ...@@ -461,7 +471,6 @@ static int xgene_enet_rx_frame(struct xgene_enet_desc_ring *rx_ring,
int ret = 0; int ret = 0;
ndev = rx_ring->ndev; ndev = rx_ring->ndev;
pdata = netdev_priv(ndev);
dev = ndev_to_dev(rx_ring->ndev); dev = ndev_to_dev(rx_ring->ndev);
buf_pool = rx_ring->buf_pool; buf_pool = rx_ring->buf_pool;
...@@ -1312,6 +1321,18 @@ static int xgene_enet_check_phy_handle(struct xgene_enet_pdata *pdata) ...@@ -1312,6 +1321,18 @@ static int xgene_enet_check_phy_handle(struct xgene_enet_pdata *pdata)
return 0; return 0;
} }
static void xgene_enet_gpiod_get(struct xgene_enet_pdata *pdata)
{
struct device *dev = &pdata->pdev->dev;
if (pdata->phy_mode != PHY_INTERFACE_MODE_XGMII)
return;
pdata->sfp_rdy = gpiod_get(dev, "rxlos", GPIOD_IN);
if (IS_ERR(pdata->sfp_rdy))
pdata->sfp_rdy = gpiod_get(dev, "sfp", GPIOD_IN);
}
static int xgene_enet_get_resources(struct xgene_enet_pdata *pdata) static int xgene_enet_get_resources(struct xgene_enet_pdata *pdata)
{ {
struct platform_device *pdev; struct platform_device *pdev;
...@@ -1401,6 +1422,8 @@ static int xgene_enet_get_resources(struct xgene_enet_pdata *pdata) ...@@ -1401,6 +1422,8 @@ static int xgene_enet_get_resources(struct xgene_enet_pdata *pdata)
if (ret) if (ret)
return ret; return ret;
xgene_enet_gpiod_get(pdata);
pdata->clk = devm_clk_get(&pdev->dev, NULL); pdata->clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(pdata->clk)) { if (IS_ERR(pdata->clk)) {
/* Firmware may have set up the clock already. */ /* Firmware may have set up the clock already. */
...@@ -1425,6 +1448,7 @@ static int xgene_enet_get_resources(struct xgene_enet_pdata *pdata) ...@@ -1425,6 +1448,7 @@ static int xgene_enet_get_resources(struct xgene_enet_pdata *pdata)
} else { } else {
pdata->mcx_mac_addr = base_addr + BLOCK_AXG_MAC_OFFSET; pdata->mcx_mac_addr = base_addr + BLOCK_AXG_MAC_OFFSET;
pdata->mcx_mac_csr_addr = base_addr + BLOCK_AXG_MAC_CSR_OFFSET; pdata->mcx_mac_csr_addr = base_addr + BLOCK_AXG_MAC_CSR_OFFSET;
pdata->pcs_addr = base_addr + BLOCK_PCS_OFFSET;
} }
pdata->rx_buff_cnt = NUM_PKT_BUF; pdata->rx_buff_cnt = NUM_PKT_BUF;
...@@ -1454,10 +1478,8 @@ static int xgene_enet_init_hw(struct xgene_enet_pdata *pdata) ...@@ -1454,10 +1478,8 @@ static int xgene_enet_init_hw(struct xgene_enet_pdata *pdata)
buf_pool = pdata->rx_ring[i]->buf_pool; buf_pool = pdata->rx_ring[i]->buf_pool;
xgene_enet_init_bufpool(buf_pool); xgene_enet_init_bufpool(buf_pool);
ret = xgene_enet_refill_bufpool(buf_pool, pdata->rx_buff_cnt); ret = xgene_enet_refill_bufpool(buf_pool, pdata->rx_buff_cnt);
if (ret) { if (ret)
xgene_enet_delete_desc_rings(pdata); goto err;
return ret;
}
} }
dst_ring_num = xgene_enet_dst_ring_num(pdata->rx_ring[0]); dst_ring_num = xgene_enet_dst_ring_num(pdata->rx_ring[0]);
...@@ -1474,7 +1496,7 @@ static int xgene_enet_init_hw(struct xgene_enet_pdata *pdata) ...@@ -1474,7 +1496,7 @@ static int xgene_enet_init_hw(struct xgene_enet_pdata *pdata)
ret = pdata->cle_ops->cle_init(pdata); ret = pdata->cle_ops->cle_init(pdata);
if (ret) { if (ret) {
netdev_err(ndev, "Preclass Tree init error\n"); netdev_err(ndev, "Preclass Tree init error\n");
return ret; goto err;
} }
} else { } else {
pdata->port_ops->cle_bypass(pdata, dst_ring_num, buf_pool->id); pdata->port_ops->cle_bypass(pdata, dst_ring_num, buf_pool->id);
...@@ -1484,6 +1506,10 @@ static int xgene_enet_init_hw(struct xgene_enet_pdata *pdata) ...@@ -1484,6 +1506,10 @@ static int xgene_enet_init_hw(struct xgene_enet_pdata *pdata)
pdata->mac_ops->init(pdata); pdata->mac_ops->init(pdata);
return ret; return ret;
err:
xgene_enet_delete_desc_rings(pdata);
return ret;
} }
static void xgene_enet_setup_ops(struct xgene_enet_pdata *pdata) static void xgene_enet_setup_ops(struct xgene_enet_pdata *pdata)
...@@ -1631,8 +1657,8 @@ static int xgene_enet_probe(struct platform_device *pdev) ...@@ -1631,8 +1657,8 @@ static int xgene_enet_probe(struct platform_device *pdev)
} }
#endif #endif
if (!pdata->enet_id) { if (!pdata->enet_id) {
free_netdev(ndev); ret = -ENODEV;
return -ENODEV; goto err;
} }
ret = xgene_enet_get_resources(pdata); ret = xgene_enet_get_resources(pdata);
...@@ -1655,7 +1681,7 @@ static int xgene_enet_probe(struct platform_device *pdev) ...@@ -1655,7 +1681,7 @@ static int xgene_enet_probe(struct platform_device *pdev)
ret = xgene_enet_init_hw(pdata); ret = xgene_enet_init_hw(pdata);
if (ret) if (ret)
goto err_netdev; goto err;
link_state = pdata->mac_ops->link_state; link_state = pdata->mac_ops->link_state;
if (pdata->phy_mode == PHY_INTERFACE_MODE_XGMII) { if (pdata->phy_mode == PHY_INTERFACE_MODE_XGMII) {
...@@ -1665,21 +1691,32 @@ static int xgene_enet_probe(struct platform_device *pdev) ...@@ -1665,21 +1691,32 @@ static int xgene_enet_probe(struct platform_device *pdev)
ret = xgene_enet_mdio_config(pdata); ret = xgene_enet_mdio_config(pdata);
else else
INIT_DELAYED_WORK(&pdata->link_work, link_state); INIT_DELAYED_WORK(&pdata->link_work, link_state);
}
if (ret) if (ret)
goto err; goto err1;
}
xgene_enet_napi_add(pdata); xgene_enet_napi_add(pdata);
ret = register_netdev(ndev); ret = register_netdev(ndev);
if (ret) { if (ret) {
netdev_err(ndev, "Failed to register netdev\n"); netdev_err(ndev, "Failed to register netdev\n");
goto err; goto err2;
} }
return 0; return 0;
err_netdev: err2:
unregister_netdev(ndev); /*
* If necessary, free_netdev() will call netif_napi_del() and undo
* the effects of xgene_enet_napi_add()'s calls to netif_napi_add().
*/
if (pdata->mdio_driver)
xgene_enet_phy_disconnect(pdata);
else if (pdata->phy_mode == PHY_INTERFACE_MODE_RGMII)
xgene_enet_mdio_remove(pdata);
err1:
xgene_enet_delete_desc_rings(pdata);
err: err:
free_netdev(ndev); free_netdev(ndev);
return ret; return ret;
...@@ -1688,11 +1725,9 @@ static int xgene_enet_probe(struct platform_device *pdev) ...@@ -1688,11 +1725,9 @@ static int xgene_enet_probe(struct platform_device *pdev)
static int xgene_enet_remove(struct platform_device *pdev) static int xgene_enet_remove(struct platform_device *pdev)
{ {
struct xgene_enet_pdata *pdata; struct xgene_enet_pdata *pdata;
const struct xgene_mac_ops *mac_ops;
struct net_device *ndev; struct net_device *ndev;
pdata = platform_get_drvdata(pdev); pdata = platform_get_drvdata(pdev);
mac_ops = pdata->mac_ops;
ndev = pdata->ndev; ndev = pdata->ndev;
rtnl_lock(); rtnl_lock();
......
...@@ -196,6 +196,7 @@ struct xgene_enet_pdata { ...@@ -196,6 +196,7 @@ struct xgene_enet_pdata {
void __iomem *mcx_mac_addr; void __iomem *mcx_mac_addr;
void __iomem *mcx_mac_csr_addr; void __iomem *mcx_mac_csr_addr;
void __iomem *base_addr; void __iomem *base_addr;
void __iomem *pcs_addr;
void __iomem *ring_csr_addr; void __iomem *ring_csr_addr;
void __iomem *ring_cmd_addr; void __iomem *ring_cmd_addr;
int phy_mode; int phy_mode;
...@@ -216,6 +217,7 @@ struct xgene_enet_pdata { ...@@ -216,6 +217,7 @@ struct xgene_enet_pdata {
u8 tx_delay; u8 tx_delay;
u8 rx_delay; u8 rx_delay;
bool mdio_driver; bool mdio_driver;
struct gpio_desc *sfp_rdy;
}; };
struct xgene_indirect_ctl { struct xgene_indirect_ctl {
......
...@@ -18,6 +18,8 @@ ...@@ -18,6 +18,8 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <linux/of_gpio.h>
#include <linux/gpio.h>
#include "xgene_enet_main.h" #include "xgene_enet_main.h"
#include "xgene_enet_hw.h" #include "xgene_enet_hw.h"
#include "xgene_enet_xgmac.h" #include "xgene_enet_xgmac.h"
...@@ -84,6 +86,21 @@ static void xgene_enet_wr_mac(struct xgene_enet_pdata *pdata, ...@@ -84,6 +86,21 @@ static void xgene_enet_wr_mac(struct xgene_enet_pdata *pdata,
wr_addr); wr_addr);
} }
static void xgene_enet_wr_pcs(struct xgene_enet_pdata *pdata,
u32 wr_addr, u32 wr_data)
{
void __iomem *addr, *wr, *cmd, *cmd_done;
addr = pdata->pcs_addr + PCS_ADDR_REG_OFFSET;
wr = pdata->pcs_addr + PCS_WRITE_REG_OFFSET;
cmd = pdata->pcs_addr + PCS_COMMAND_REG_OFFSET;
cmd_done = pdata->pcs_addr + PCS_COMMAND_DONE_REG_OFFSET;
if (!xgene_enet_wr_indirect(addr, wr, cmd, cmd_done, wr_addr, wr_data))
netdev_err(pdata->ndev, "PCS write failed, addr: %04x\n",
wr_addr);
}
static void xgene_enet_rd_csr(struct xgene_enet_pdata *pdata, static void xgene_enet_rd_csr(struct xgene_enet_pdata *pdata,
u32 offset, u32 *val) u32 offset, u32 *val)
{ {
...@@ -122,6 +139,7 @@ static bool xgene_enet_rd_indirect(void __iomem *addr, void __iomem *rd, ...@@ -122,6 +139,7 @@ static bool xgene_enet_rd_indirect(void __iomem *addr, void __iomem *rd,
return true; return true;
} }
static void xgene_enet_rd_mac(struct xgene_enet_pdata *pdata, static void xgene_enet_rd_mac(struct xgene_enet_pdata *pdata,
u32 rd_addr, u32 *rd_data) u32 rd_addr, u32 *rd_data)
{ {
...@@ -137,6 +155,21 @@ static void xgene_enet_rd_mac(struct xgene_enet_pdata *pdata, ...@@ -137,6 +155,21 @@ static void xgene_enet_rd_mac(struct xgene_enet_pdata *pdata,
rd_addr); rd_addr);
} }
static void xgene_enet_rd_pcs(struct xgene_enet_pdata *pdata,
u32 rd_addr, u32 *rd_data)
{
void __iomem *addr, *rd, *cmd, *cmd_done;
addr = pdata->pcs_addr + PCS_ADDR_REG_OFFSET;
rd = pdata->pcs_addr + PCS_READ_REG_OFFSET;
cmd = pdata->pcs_addr + PCS_COMMAND_REG_OFFSET;
cmd_done = pdata->pcs_addr + PCS_COMMAND_DONE_REG_OFFSET;
if (!xgene_enet_rd_indirect(addr, rd, cmd, cmd_done, rd_addr, rd_data))
netdev_err(pdata->ndev, "PCS read failed, addr: %04x\n",
rd_addr);
}
static int xgene_enet_ecc_init(struct xgene_enet_pdata *pdata) static int xgene_enet_ecc_init(struct xgene_enet_pdata *pdata)
{ {
struct net_device *ndev = pdata->ndev; struct net_device *ndev = pdata->ndev;
...@@ -171,6 +204,15 @@ static void xgene_xgmac_reset(struct xgene_enet_pdata *pdata) ...@@ -171,6 +204,15 @@ static void xgene_xgmac_reset(struct xgene_enet_pdata *pdata)
xgene_enet_wr_mac(pdata, AXGMAC_CONFIG_0, 0); xgene_enet_wr_mac(pdata, AXGMAC_CONFIG_0, 0);
} }
static void xgene_pcs_reset(struct xgene_enet_pdata *pdata)
{
u32 data;
xgene_enet_rd_pcs(pdata, PCS_CONTROL_1, &data);
xgene_enet_wr_pcs(pdata, PCS_CONTROL_1, data | PCS_CTRL_PCS_RST);
xgene_enet_wr_pcs(pdata, PCS_CONTROL_1, data & ~PCS_CTRL_PCS_RST);
}
static void xgene_xgmac_set_mac_addr(struct xgene_enet_pdata *pdata) static void xgene_xgmac_set_mac_addr(struct xgene_enet_pdata *pdata)
{ {
u32 addr0, addr1; u32 addr0, addr1;
...@@ -216,12 +258,12 @@ static void xgene_xgmac_init(struct xgene_enet_pdata *pdata) ...@@ -216,12 +258,12 @@ static void xgene_xgmac_init(struct xgene_enet_pdata *pdata)
data |= CFG_RSIF_FPBUFF_TIMEOUT_EN; data |= CFG_RSIF_FPBUFF_TIMEOUT_EN;
xgene_enet_wr_csr(pdata, XG_RSIF_CONFIG_REG_ADDR, data); xgene_enet_wr_csr(pdata, XG_RSIF_CONFIG_REG_ADDR, data);
xgene_enet_wr_csr(pdata, XG_CFG_BYPASS_ADDR, RESUME_TX);
xgene_enet_wr_csr(pdata, XGENET_RX_DV_GATE_REG_0_ADDR, 0);
xgene_enet_rd_csr(pdata, XG_ENET_SPARE_CFG_REG_ADDR, &data); xgene_enet_rd_csr(pdata, XG_ENET_SPARE_CFG_REG_ADDR, &data);
data |= BIT(12); data |= BIT(12);
xgene_enet_wr_csr(pdata, XG_ENET_SPARE_CFG_REG_ADDR, data); xgene_enet_wr_csr(pdata, XG_ENET_SPARE_CFG_REG_ADDR, data);
xgene_enet_wr_csr(pdata, XG_ENET_SPARE_CFG_REG_1_ADDR, 0x82); xgene_enet_wr_csr(pdata, XG_ENET_SPARE_CFG_REG_1_ADDR, 0x82);
xgene_enet_wr_csr(pdata, XGENET_RX_DV_GATE_REG_0_ADDR, 0);
xgene_enet_wr_csr(pdata, XG_CFG_BYPASS_ADDR, RESUME_TX);
} }
static void xgene_xgmac_rx_enable(struct xgene_enet_pdata *pdata) static void xgene_xgmac_rx_enable(struct xgene_enet_pdata *pdata)
...@@ -359,14 +401,17 @@ static void xgene_enet_link_state(struct work_struct *work) ...@@ -359,14 +401,17 @@ static void xgene_enet_link_state(struct work_struct *work)
{ {
struct xgene_enet_pdata *pdata = container_of(to_delayed_work(work), struct xgene_enet_pdata *pdata = container_of(to_delayed_work(work),
struct xgene_enet_pdata, link_work); struct xgene_enet_pdata, link_work);
struct gpio_desc *sfp_rdy = pdata->sfp_rdy;
struct net_device *ndev = pdata->ndev; struct net_device *ndev = pdata->ndev;
u32 link_status, poll_interval; u32 link_status, poll_interval;
link_status = xgene_enet_link_status(pdata); link_status = xgene_enet_link_status(pdata);
if (link_status && !IS_ERR(sfp_rdy) && !gpiod_get_value(sfp_rdy))
link_status = 0;
if (link_status) { if (link_status) {
if (!netif_carrier_ok(ndev)) { if (!netif_carrier_ok(ndev)) {
netif_carrier_on(ndev); netif_carrier_on(ndev);
xgene_xgmac_init(pdata);
xgene_xgmac_rx_enable(pdata); xgene_xgmac_rx_enable(pdata);
xgene_xgmac_tx_enable(pdata); xgene_xgmac_tx_enable(pdata);
netdev_info(ndev, "Link is Up - 10Gbps\n"); netdev_info(ndev, "Link is Up - 10Gbps\n");
...@@ -380,6 +425,8 @@ static void xgene_enet_link_state(struct work_struct *work) ...@@ -380,6 +425,8 @@ static void xgene_enet_link_state(struct work_struct *work)
netdev_info(ndev, "Link is Down\n"); netdev_info(ndev, "Link is Down\n");
} }
poll_interval = PHY_POLL_LINK_OFF; poll_interval = PHY_POLL_LINK_OFF;
xgene_pcs_reset(pdata);
} }
schedule_delayed_work(&pdata->link_work, poll_interval); schedule_delayed_work(&pdata->link_work, poll_interval);
......
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#define X2_BLOCK_ETH_MAC_CSR_OFFSET 0x3000 #define X2_BLOCK_ETH_MAC_CSR_OFFSET 0x3000
#define BLOCK_AXG_MAC_OFFSET 0x0800 #define BLOCK_AXG_MAC_OFFSET 0x0800
#define BLOCK_AXG_MAC_CSR_OFFSET 0x2000 #define BLOCK_AXG_MAC_CSR_OFFSET 0x2000
#define BLOCK_PCS_OFFSET 0x3800
#define XGENET_CONFIG_REG_ADDR 0x20 #define XGENET_CONFIG_REG_ADDR 0x20
#define XGENET_SRST_ADDR 0x00 #define XGENET_SRST_ADDR 0x00
...@@ -72,6 +73,9 @@ ...@@ -72,6 +73,9 @@
#define XG_MCX_ICM_CONFIG0_REG_0_ADDR 0x00e0 #define XG_MCX_ICM_CONFIG0_REG_0_ADDR 0x00e0
#define XG_MCX_ICM_CONFIG2_REG_0_ADDR 0x00e8 #define XG_MCX_ICM_CONFIG2_REG_0_ADDR 0x00e8
#define PCS_CONTROL_1 0x0000
#define PCS_CTRL_PCS_RST BIT(15)
extern const struct xgene_mac_ops xgene_xgmac_ops; extern const struct xgene_mac_ops xgene_xgmac_ops;
extern const struct xgene_port_ops xgene_xgport_ops; extern const struct xgene_port_ops xgene_xgport_ops;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment