aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/ethernet/apm/xgene/Makefile3
-rw-r--r--drivers/net/ethernet/apm/xgene/xgene_enet_hw.h14
-rw-r--r--drivers/net/ethernet/apm/xgene/xgene_enet_main.c58
-rw-r--r--drivers/net/ethernet/apm/xgene/xgene_enet_main.h5
-rw-r--r--drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c331
-rw-r--r--drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.h57
6 files changed, 438 insertions, 30 deletions
diff --git a/drivers/net/ethernet/apm/xgene/Makefile b/drivers/net/ethernet/apm/xgene/Makefile
index c643e8a0a0dc..589b35247713 100644
--- a/drivers/net/ethernet/apm/xgene/Makefile
+++ b/drivers/net/ethernet/apm/xgene/Makefile
@@ -2,5 +2,6 @@
2# Makefile for APM X-Gene Ethernet Driver. 2# Makefile for APM X-Gene Ethernet Driver.
3# 3#
4 4
5xgene-enet-objs := xgene_enet_hw.o xgene_enet_main.o xgene_enet_ethtool.o 5xgene-enet-objs := xgene_enet_hw.o xgene_enet_xgmac.o \
6 xgene_enet_main.o xgene_enet_ethtool.o
6obj-$(CONFIG_NET_XGENE) += xgene-enet.o 7obj-$(CONFIG_NET_XGENE) += xgene-enet.o
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h
index 084ac68aed8d..15ec4267779c 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h
@@ -42,6 +42,11 @@ static inline u32 xgene_get_bits(u32 val, u32 start, u32 end)
42 return (val & GENMASK(end, start)) >> start; 42 return (val & GENMASK(end, start)) >> start;
43} 43}
44 44
45enum xgene_enet_rm {
46 RM0,
47 RM3 = 3
48};
49
45#define CSR_RING_ID 0x0008 50#define CSR_RING_ID 0x0008
46#define OVERWRITE BIT(31) 51#define OVERWRITE BIT(31)
47#define IS_BUFFER_POOL BIT(20) 52#define IS_BUFFER_POOL BIT(20)
@@ -52,7 +57,6 @@ static inline u32 xgene_get_bits(u32 val, u32 start, u32 end)
52#define CSR_RING_WR_BASE 0x0070 57#define CSR_RING_WR_BASE 0x0070
53#define NUM_RING_CONFIG 5 58#define NUM_RING_CONFIG 5
54#define BUFPOOL_MODE 3 59#define BUFPOOL_MODE 3
55#define RM3 3
56#define INC_DEC_CMD_ADDR 0x002c 60#define INC_DEC_CMD_ADDR 0x002c
57#define UDP_HDR_SIZE 2 61#define UDP_HDR_SIZE 2
58#define BUF_LEN_CODE_2K 0x5000 62#define BUF_LEN_CODE_2K 0x5000
@@ -94,11 +98,9 @@ static inline u32 xgene_get_bits(u32 val, u32 start, u32 end)
94 98
95#define BLOCK_ETH_CSR_OFFSET 0x2000 99#define BLOCK_ETH_CSR_OFFSET 0x2000
96#define BLOCK_ETH_RING_IF_OFFSET 0x9000 100#define BLOCK_ETH_RING_IF_OFFSET 0x9000
97#define BLOCK_ETH_CLKRST_CSR_OFFSET 0xC000
98#define BLOCK_ETH_DIAG_CSR_OFFSET 0xD000 101#define BLOCK_ETH_DIAG_CSR_OFFSET 0xD000
99 102
100#define BLOCK_ETH_MAC_OFFSET 0x0000 103#define BLOCK_ETH_MAC_OFFSET 0x0000
101#define BLOCK_ETH_STATS_OFFSET 0x0014
102#define BLOCK_ETH_MAC_CSR_OFFSET 0x2800 104#define BLOCK_ETH_MAC_CSR_OFFSET 0x2800
103 105
104#define MAC_ADDR_REG_OFFSET 0x00 106#define MAC_ADDR_REG_OFFSET 0x00
@@ -107,12 +109,6 @@ static inline u32 xgene_get_bits(u32 val, u32 start, u32 end)
107#define MAC_READ_REG_OFFSET 0x0c 109#define MAC_READ_REG_OFFSET 0x0c
108#define MAC_COMMAND_DONE_REG_OFFSET 0x10 110#define MAC_COMMAND_DONE_REG_OFFSET 0x10
109 111
110#define STAT_ADDR_REG_OFFSET 0x00
111#define STAT_COMMAND_REG_OFFSET 0x04
112#define STAT_WRITE_REG_OFFSET 0x08
113#define STAT_READ_REG_OFFSET 0x0c
114#define STAT_COMMAND_DONE_REG_OFFSET 0x10
115
116#define MII_MGMT_CONFIG_ADDR 0x20 112#define MII_MGMT_CONFIG_ADDR 0x20
117#define MII_MGMT_COMMAND_ADDR 0x24 113#define MII_MGMT_COMMAND_ADDR 0x24
118#define MII_MGMT_ADDRESS_ADDR 0x28 114#define MII_MGMT_ADDRESS_ADDR 0x28
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
index c4326444deaf..9b85239ceedf 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
@@ -21,6 +21,7 @@
21 21
22#include "xgene_enet_main.h" 22#include "xgene_enet_main.h"
23#include "xgene_enet_hw.h" 23#include "xgene_enet_hw.h"
24#include "xgene_enet_xgmac.h"
24 25
25static void xgene_enet_init_bufpool(struct xgene_enet_desc_ring *buf_pool) 26static void xgene_enet_init_bufpool(struct xgene_enet_desc_ring *buf_pool)
26{ 27{
@@ -390,7 +391,7 @@ static int xgene_enet_process_ring(struct xgene_enet_desc_ring *ring,
390 } 391 }
391 } 392 }
392 393
393 return budget; 394 return count;
394} 395}
395 396
396static int xgene_enet_napi(struct napi_struct *napi, const int budget) 397static int xgene_enet_napi(struct napi_struct *napi, const int budget)
@@ -456,8 +457,10 @@ static int xgene_enet_open(struct net_device *ndev)
456 return ret; 457 return ret;
457 napi_enable(&pdata->rx_ring->napi); 458 napi_enable(&pdata->rx_ring->napi);
458 459
459 if (pdata->phy_dev) 460 if (pdata->phy_mode == PHY_INTERFACE_MODE_RGMII)
460 phy_start(pdata->phy_dev); 461 phy_start(pdata->phy_dev);
462 else
463 schedule_delayed_work(&pdata->link_work, PHY_POLL_LINK_OFF);
461 464
462 netif_start_queue(ndev); 465 netif_start_queue(ndev);
463 466
@@ -471,8 +474,10 @@ static int xgene_enet_close(struct net_device *ndev)
471 474
472 netif_stop_queue(ndev); 475 netif_stop_queue(ndev);
473 476
474 if (pdata->phy_dev) 477 if (pdata->phy_mode == PHY_INTERFACE_MODE_RGMII)
475 phy_stop(pdata->phy_dev); 478 phy_stop(pdata->phy_dev);
479 else
480 cancel_delayed_work_sync(&pdata->link_work);
476 481
477 napi_disable(&pdata->rx_ring->napi); 482 napi_disable(&pdata->rx_ring->napi);
478 xgene_enet_free_irq(ndev); 483 xgene_enet_free_irq(ndev);
@@ -615,7 +620,6 @@ static struct xgene_enet_desc_ring *xgene_enet_create_desc_ring(
615 620
616 ring->cmd_base = pdata->ring_cmd_addr + (ring->num << 6); 621 ring->cmd_base = pdata->ring_cmd_addr + (ring->num << 6);
617 ring->cmd = ring->cmd_base + INC_DEC_CMD_ADDR; 622 ring->cmd = ring->cmd_base + INC_DEC_CMD_ADDR;
618 pdata->rm = RM3;
619 ring = xgene_enet_setup_ring(ring); 623 ring = xgene_enet_setup_ring(ring);
620 netdev_dbg(ndev, "ring info: num=%d size=%d id=%d slots=%d\n", 624 netdev_dbg(ndev, "ring info: num=%d size=%d id=%d slots=%d\n",
621 ring->num, ring->size, ring->id, ring->slots); 625 ring->num, ring->size, ring->id, ring->slots);
@@ -805,8 +809,13 @@ static int xgene_enet_get_resources(struct xgene_enet_pdata *pdata)
805 809
806 pdata->phy_mode = of_get_phy_mode(pdev->dev.of_node); 810 pdata->phy_mode = of_get_phy_mode(pdev->dev.of_node);
807 if (pdata->phy_mode < 0) { 811 if (pdata->phy_mode < 0) {
808 dev_err(dev, "Incorrect phy-connection-type in DTS\n"); 812 dev_err(dev, "Unable to get phy-connection-type\n");
809 return -EINVAL; 813 return pdata->phy_mode;
814 }
815 if (pdata->phy_mode != PHY_INTERFACE_MODE_RGMII &&
816 pdata->phy_mode != PHY_INTERFACE_MODE_XGMII) {
817 dev_err(dev, "Incorrect phy-connection-type specified\n");
818 return -ENODEV;
810 } 819 }
811 820
812 pdata->clk = devm_clk_get(&pdev->dev, NULL); 821 pdata->clk = devm_clk_get(&pdev->dev, NULL);
@@ -821,12 +830,18 @@ static int xgene_enet_get_resources(struct xgene_enet_pdata *pdata)
821 pdata->eth_csr_addr = base_addr + BLOCK_ETH_CSR_OFFSET; 830 pdata->eth_csr_addr = base_addr + BLOCK_ETH_CSR_OFFSET;
822 pdata->eth_ring_if_addr = base_addr + BLOCK_ETH_RING_IF_OFFSET; 831 pdata->eth_ring_if_addr = base_addr + BLOCK_ETH_RING_IF_OFFSET;
823 pdata->eth_diag_csr_addr = base_addr + BLOCK_ETH_DIAG_CSR_OFFSET; 832 pdata->eth_diag_csr_addr = base_addr + BLOCK_ETH_DIAG_CSR_OFFSET;
824 pdata->mcx_mac_addr = base_addr + BLOCK_ETH_MAC_OFFSET; 833 if (pdata->phy_mode == PHY_INTERFACE_MODE_RGMII) {
825 pdata->mcx_stats_addr = base_addr + BLOCK_ETH_STATS_OFFSET; 834 pdata->mcx_mac_addr = base_addr + BLOCK_ETH_MAC_OFFSET;
826 pdata->mcx_mac_csr_addr = base_addr + BLOCK_ETH_MAC_CSR_OFFSET; 835 pdata->mcx_mac_csr_addr = base_addr + BLOCK_ETH_MAC_CSR_OFFSET;
836 pdata->rm = RM3;
837 } else {
838 pdata->mcx_mac_addr = base_addr + BLOCK_AXG_MAC_OFFSET;
839 pdata->mcx_mac_csr_addr = base_addr + BLOCK_AXG_MAC_CSR_OFFSET;
840 pdata->rm = RM0;
841 }
827 pdata->rx_buff_cnt = NUM_PKT_BUF; 842 pdata->rx_buff_cnt = NUM_PKT_BUF;
828 843
829 return ret; 844 return 0;
830} 845}
831 846
832static int xgene_enet_init_hw(struct xgene_enet_pdata *pdata) 847static int xgene_enet_init_hw(struct xgene_enet_pdata *pdata)
@@ -836,8 +851,7 @@ static int xgene_enet_init_hw(struct xgene_enet_pdata *pdata)
836 u16 dst_ring_num; 851 u16 dst_ring_num;
837 int ret; 852 int ret;
838 853
839 pdata->mac_ops->tx_disable(pdata); 854 pdata->port_ops->reset(pdata);
840 pdata->mac_ops->rx_disable(pdata);
841 855
842 ret = xgene_enet_create_desc_rings(ndev); 856 ret = xgene_enet_create_desc_rings(ndev);
843 if (ret) { 857 if (ret) {
@@ -856,14 +870,23 @@ static int xgene_enet_init_hw(struct xgene_enet_pdata *pdata)
856 870
857 dst_ring_num = xgene_enet_dst_ring_num(pdata->rx_ring); 871 dst_ring_num = xgene_enet_dst_ring_num(pdata->rx_ring);
858 pdata->port_ops->cle_bypass(pdata, dst_ring_num, buf_pool->id); 872 pdata->port_ops->cle_bypass(pdata, dst_ring_num, buf_pool->id);
873 pdata->mac_ops->init(pdata);
859 874
860 return ret; 875 return ret;
861} 876}
862 877
863static void xgene_enet_setup_ops(struct xgene_enet_pdata *pdata) 878static void xgene_enet_setup_ops(struct xgene_enet_pdata *pdata)
864{ 879{
865 pdata->mac_ops = &xgene_gmac_ops; 880 switch (pdata->phy_mode) {
866 pdata->port_ops = &xgene_gport_ops; 881 case PHY_INTERFACE_MODE_RGMII:
882 pdata->mac_ops = &xgene_gmac_ops;
883 pdata->port_ops = &xgene_gport_ops;
884 break;
885 default:
886 pdata->mac_ops = &xgene_xgmac_ops;
887 pdata->port_ops = &xgene_xgport_ops;
888 break;
889 }
867} 890}
868 891
869static int xgene_enet_probe(struct platform_device *pdev) 892static int xgene_enet_probe(struct platform_device *pdev)
@@ -895,8 +918,6 @@ static int xgene_enet_probe(struct platform_device *pdev)
895 goto err; 918 goto err;
896 919
897 xgene_enet_setup_ops(pdata); 920 xgene_enet_setup_ops(pdata);
898 pdata->port_ops->reset(pdata);
899 pdata->mac_ops->init(pdata);
900 921
901 ret = register_netdev(ndev); 922 ret = register_netdev(ndev);
902 if (ret) { 923 if (ret) {
@@ -916,7 +937,10 @@ static int xgene_enet_probe(struct platform_device *pdev)
916 937
917 napi = &pdata->rx_ring->napi; 938 napi = &pdata->rx_ring->napi;
918 netif_napi_add(ndev, napi, xgene_enet_napi, NAPI_POLL_WEIGHT); 939 netif_napi_add(ndev, napi, xgene_enet_napi, NAPI_POLL_WEIGHT);
919 ret = xgene_enet_mdio_config(pdata); 940 if (pdata->phy_mode == PHY_INTERFACE_MODE_RGMII)
941 ret = xgene_enet_mdio_config(pdata);
942 else
943 INIT_DELAYED_WORK(&pdata->link_work, xgene_enet_link_state);
920 944
921 return ret; 945 return ret;
922err: 946err:
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.h b/drivers/net/ethernet/apm/xgene/xgene_enet_main.h
index ac180f980fcd..86cf68b65584 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.h
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.h
@@ -105,18 +105,17 @@ struct xgene_enet_pdata {
105 void __iomem *eth_ring_if_addr; 105 void __iomem *eth_ring_if_addr;
106 void __iomem *eth_diag_csr_addr; 106 void __iomem *eth_diag_csr_addr;
107 void __iomem *mcx_mac_addr; 107 void __iomem *mcx_mac_addr;
108 void __iomem *mcx_stats_addr;
109 void __iomem *mcx_mac_csr_addr; 108 void __iomem *mcx_mac_csr_addr;
110 void __iomem *base_addr; 109 void __iomem *base_addr;
111 void __iomem *ring_csr_addr; 110 void __iomem *ring_csr_addr;
112 void __iomem *ring_cmd_addr; 111 void __iomem *ring_cmd_addr;
113 u32 phy_addr; 112 u32 phy_addr;
114 int phy_mode; 113 int phy_mode;
115 u32 speed; 114 enum xgene_enet_rm rm;
116 u16 rm;
117 struct rtnl_link_stats64 stats; 115 struct rtnl_link_stats64 stats;
118 struct xgene_mac_ops *mac_ops; 116 struct xgene_mac_ops *mac_ops;
119 struct xgene_port_ops *port_ops; 117 struct xgene_port_ops *port_ops;
118 struct delayed_work link_work;
120}; 119};
121 120
122/* Set the specified value into a bit-field defined by its starting position 121/* Set the specified value into a bit-field defined by its starting position
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c b/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c
new file mode 100644
index 000000000000..cd64b9f18b58
--- /dev/null
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c
@@ -0,0 +1,331 @@
1/* Applied Micro X-Gene SoC Ethernet Driver
2 *
3 * Copyright (c) 2014, Applied Micro Circuits Corporation
4 * Authors: Iyappan Subramanian <isubramanian@apm.com>
5 * Keyur Chudgar <kchudgar@apm.com>
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 */
20
21#include "xgene_enet_main.h"
22#include "xgene_enet_hw.h"
23#include "xgene_enet_xgmac.h"
24
25static void xgene_enet_wr_csr(struct xgene_enet_pdata *pdata,
26 u32 offset, u32 val)
27{
28 void __iomem *addr = pdata->eth_csr_addr + offset;
29
30 iowrite32(val, addr);
31}
32
33static void xgene_enet_wr_ring_if(struct xgene_enet_pdata *pdata,
34 u32 offset, u32 val)
35{
36 void __iomem *addr = pdata->eth_ring_if_addr + offset;
37
38 iowrite32(val, addr);
39}
40
41static void xgene_enet_wr_diag_csr(struct xgene_enet_pdata *pdata,
42 u32 offset, u32 val)
43{
44 void __iomem *addr = pdata->eth_diag_csr_addr + offset;
45
46 iowrite32(val, addr);
47}
48
49static bool xgene_enet_wr_indirect(void __iomem *addr, void __iomem *wr,
50 void __iomem *cmd, void __iomem *cmd_done,
51 u32 wr_addr, u32 wr_data)
52{
53 u32 done;
54 u8 wait = 10;
55
56 iowrite32(wr_addr, addr);
57 iowrite32(wr_data, wr);
58 iowrite32(XGENE_ENET_WR_CMD, cmd);
59
60 /* wait for write command to complete */
61 while (!(done = ioread32(cmd_done)) && wait--)
62 udelay(1);
63
64 if (!done)
65 return false;
66
67 iowrite32(0, cmd);
68
69 return true;
70}
71
72static void xgene_enet_wr_mac(struct xgene_enet_pdata *pdata,
73 u32 wr_addr, u32 wr_data)
74{
75 void __iomem *addr, *wr, *cmd, *cmd_done;
76
77 addr = pdata->mcx_mac_addr + MAC_ADDR_REG_OFFSET;
78 wr = pdata->mcx_mac_addr + MAC_WRITE_REG_OFFSET;
79 cmd = pdata->mcx_mac_addr + MAC_COMMAND_REG_OFFSET;
80 cmd_done = pdata->mcx_mac_addr + MAC_COMMAND_DONE_REG_OFFSET;
81
82 if (!xgene_enet_wr_indirect(addr, wr, cmd, cmd_done, wr_addr, wr_data))
83 netdev_err(pdata->ndev, "MCX mac write failed, addr: %04x\n",
84 wr_addr);
85}
86
87static void xgene_enet_rd_csr(struct xgene_enet_pdata *pdata,
88 u32 offset, u32 *val)
89{
90 void __iomem *addr = pdata->eth_csr_addr + offset;
91
92 *val = ioread32(addr);
93}
94
95static void xgene_enet_rd_diag_csr(struct xgene_enet_pdata *pdata,
96 u32 offset, u32 *val)
97{
98 void __iomem *addr = pdata->eth_diag_csr_addr + offset;
99
100 *val = ioread32(addr);
101}
102
103static bool xgene_enet_rd_indirect(void __iomem *addr, void __iomem *rd,
104 void __iomem *cmd, void __iomem *cmd_done,
105 u32 rd_addr, u32 *rd_data)
106{
107 u32 done;
108 u8 wait = 10;
109
110 iowrite32(rd_addr, addr);
111 iowrite32(XGENE_ENET_RD_CMD, cmd);
112
113 /* wait for read command to complete */
114 while (!(done = ioread32(cmd_done)) && wait--)
115 udelay(1);
116
117 if (!done)
118 return false;
119
120 *rd_data = ioread32(rd);
121 iowrite32(0, cmd);
122
123 return true;
124}
125
126static void xgene_enet_rd_mac(struct xgene_enet_pdata *pdata,
127 u32 rd_addr, u32 *rd_data)
128{
129 void __iomem *addr, *rd, *cmd, *cmd_done;
130
131 addr = pdata->mcx_mac_addr + MAC_ADDR_REG_OFFSET;
132 rd = pdata->mcx_mac_addr + MAC_READ_REG_OFFSET;
133 cmd = pdata->mcx_mac_addr + MAC_COMMAND_REG_OFFSET;
134 cmd_done = pdata->mcx_mac_addr + MAC_COMMAND_DONE_REG_OFFSET;
135
136 if (!xgene_enet_rd_indirect(addr, rd, cmd, cmd_done, rd_addr, rd_data))
137 netdev_err(pdata->ndev, "MCX mac read failed, addr: %04x\n",
138 rd_addr);
139}
140
141static int xgene_enet_ecc_init(struct xgene_enet_pdata *pdata)
142{
143 struct net_device *ndev = pdata->ndev;
144 u32 data;
145 u8 wait = 10;
146
147 xgene_enet_wr_diag_csr(pdata, ENET_CFG_MEM_RAM_SHUTDOWN_ADDR, 0x0);
148 do {
149 usleep_range(100, 110);
150 xgene_enet_rd_diag_csr(pdata, ENET_BLOCK_MEM_RDY_ADDR, &data);
151 } while ((data != 0xffffffff) && wait--);
152
153 if (data != 0xffffffff) {
154 netdev_err(ndev, "Failed to release memory from shutdown\n");
155 return -ENODEV;
156 }
157
158 return 0;
159}
160
161static void xgene_enet_config_ring_if_assoc(struct xgene_enet_pdata *pdata)
162{
163 xgene_enet_wr_ring_if(pdata, ENET_CFGSSQMIWQASSOC_ADDR, 0);
164 xgene_enet_wr_ring_if(pdata, ENET_CFGSSQMIFPQASSOC_ADDR, 0);
165 xgene_enet_wr_ring_if(pdata, ENET_CFGSSQMIQMLITEWQASSOC_ADDR, 0);
166 xgene_enet_wr_ring_if(pdata, ENET_CFGSSQMIQMLITEFPQASSOC_ADDR, 0);
167}
168
169static void xgene_xgmac_reset(struct xgene_enet_pdata *pdata)
170{
171 xgene_enet_wr_mac(pdata, AXGMAC_CONFIG_0, HSTMACRST);
172 xgene_enet_wr_mac(pdata, AXGMAC_CONFIG_0, 0);
173}
174
175static void xgene_xgmac_set_mac_addr(struct xgene_enet_pdata *pdata)
176{
177 u32 addr0, addr1;
178 u8 *dev_addr = pdata->ndev->dev_addr;
179
180 addr0 = (dev_addr[3] << 24) | (dev_addr[2] << 16) |
181 (dev_addr[1] << 8) | dev_addr[0];
182 addr1 = (dev_addr[5] << 24) | (dev_addr[4] << 16);
183
184 xgene_enet_wr_mac(pdata, HSTMACADR_LSW_ADDR, addr0);
185 xgene_enet_wr_mac(pdata, HSTMACADR_MSW_ADDR, addr1);
186}
187
188static u32 xgene_enet_link_status(struct xgene_enet_pdata *pdata)
189{
190 u32 data;
191
192 xgene_enet_rd_csr(pdata, XG_LINK_STATUS_ADDR, &data);
193
194 return data;
195}
196
197static void xgene_xgmac_init(struct xgene_enet_pdata *pdata)
198{
199 u32 data;
200
201 xgene_xgmac_reset(pdata);
202
203 xgene_enet_rd_mac(pdata, AXGMAC_CONFIG_1, &data);
204 data |= HSTPPEN;
205 data &= ~HSTLENCHK;
206 xgene_enet_wr_mac(pdata, AXGMAC_CONFIG_1, data);
207
208 xgene_enet_wr_mac(pdata, HSTMAXFRAME_LENGTH_ADDR, 0x06000600);
209 xgene_xgmac_set_mac_addr(pdata);
210
211 xgene_enet_rd_csr(pdata, XG_RSIF_CONFIG_REG_ADDR, &data);
212 data |= CFG_RSIF_FPBUFF_TIMEOUT_EN;
213 xgene_enet_wr_csr(pdata, XG_RSIF_CONFIG_REG_ADDR, data);
214
215 xgene_enet_wr_csr(pdata, XG_CFG_BYPASS_ADDR, RESUME_TX);
216 xgene_enet_wr_csr(pdata, XGENET_RX_DV_GATE_REG_0_ADDR, 0);
217 xgene_enet_rd_csr(pdata, XG_ENET_SPARE_CFG_REG_ADDR, &data);
218 data |= BIT(12);
219 xgene_enet_wr_csr(pdata, XG_ENET_SPARE_CFG_REG_ADDR, data);
220 xgene_enet_wr_csr(pdata, XG_ENET_SPARE_CFG_REG_1_ADDR, 0x82);
221}
222
223static void xgene_xgmac_rx_enable(struct xgene_enet_pdata *pdata)
224{
225 u32 data;
226
227 xgene_enet_rd_mac(pdata, AXGMAC_CONFIG_1, &data);
228 xgene_enet_wr_mac(pdata, AXGMAC_CONFIG_1, data | HSTRFEN);
229}
230
231static void xgene_xgmac_tx_enable(struct xgene_enet_pdata *pdata)
232{
233 u32 data;
234
235 xgene_enet_rd_mac(pdata, AXGMAC_CONFIG_1, &data);
236 xgene_enet_wr_mac(pdata, AXGMAC_CONFIG_1, data | HSTTFEN);
237}
238
239static void xgene_xgmac_rx_disable(struct xgene_enet_pdata *pdata)
240{
241 u32 data;
242
243 xgene_enet_rd_mac(pdata, AXGMAC_CONFIG_1, &data);
244 xgene_enet_wr_mac(pdata, AXGMAC_CONFIG_1, data & ~HSTRFEN);
245}
246
247static void xgene_xgmac_tx_disable(struct xgene_enet_pdata *pdata)
248{
249 u32 data;
250
251 xgene_enet_rd_mac(pdata, AXGMAC_CONFIG_1, &data);
252 xgene_enet_wr_mac(pdata, AXGMAC_CONFIG_1, data & ~HSTTFEN);
253}
254
255static void xgene_enet_reset(struct xgene_enet_pdata *pdata)
256{
257 clk_prepare_enable(pdata->clk);
258 clk_disable_unprepare(pdata->clk);
259 clk_prepare_enable(pdata->clk);
260
261 xgene_enet_ecc_init(pdata);
262 xgene_enet_config_ring_if_assoc(pdata);
263}
264
265static void xgene_enet_xgcle_bypass(struct xgene_enet_pdata *pdata,
266 u32 dst_ring_num, u16 bufpool_id)
267{
268 u32 cb, fpsel;
269
270 xgene_enet_rd_csr(pdata, XCLE_BYPASS_REG0_ADDR, &cb);
271 cb |= CFG_CLE_BYPASS_EN0;
272 CFG_CLE_IP_PROTOCOL0_SET(&cb, 3);
273 xgene_enet_wr_csr(pdata, XCLE_BYPASS_REG0_ADDR, cb);
274
275 fpsel = xgene_enet_ring_bufnum(bufpool_id) - 0x20;
276 xgene_enet_rd_csr(pdata, XCLE_BYPASS_REG1_ADDR, &cb);
277 CFG_CLE_DSTQID0_SET(&cb, dst_ring_num);
278 CFG_CLE_FPSEL0_SET(&cb, fpsel);
279 xgene_enet_wr_csr(pdata, XCLE_BYPASS_REG1_ADDR, cb);
280}
281
282static void xgene_enet_shutdown(struct xgene_enet_pdata *pdata)
283{
284 clk_disable_unprepare(pdata->clk);
285}
286
287void xgene_enet_link_state(struct work_struct *work)
288{
289 struct xgene_enet_pdata *pdata = container_of(to_delayed_work(work),
290 struct xgene_enet_pdata, link_work);
291 struct net_device *ndev = pdata->ndev;
292 u32 link_status, poll_interval;
293
294 link_status = xgene_enet_link_status(pdata);
295 if (link_status) {
296 if (!netif_carrier_ok(ndev)) {
297 netif_carrier_on(ndev);
298 xgene_xgmac_init(pdata);
299 xgene_xgmac_rx_enable(pdata);
300 xgene_xgmac_tx_enable(pdata);
301 netdev_info(ndev, "Link is Up - 10Gbps\n");
302 }
303 poll_interval = PHY_POLL_LINK_ON;
304 } else {
305 if (netif_carrier_ok(ndev)) {
306 xgene_xgmac_rx_disable(pdata);
307 xgene_xgmac_tx_disable(pdata);
308 netif_carrier_off(ndev);
309 netdev_info(ndev, "Link is Down\n");
310 }
311 poll_interval = PHY_POLL_LINK_OFF;
312 }
313
314 schedule_delayed_work(&pdata->link_work, poll_interval);
315}
316
317struct xgene_mac_ops xgene_xgmac_ops = {
318 .init = xgene_xgmac_init,
319 .reset = xgene_xgmac_reset,
320 .rx_enable = xgene_xgmac_rx_enable,
321 .tx_enable = xgene_xgmac_tx_enable,
322 .rx_disable = xgene_xgmac_rx_disable,
323 .tx_disable = xgene_xgmac_tx_disable,
324 .set_mac_addr = xgene_xgmac_set_mac_addr,
325};
326
327struct xgene_port_ops xgene_xgport_ops = {
328 .reset = xgene_enet_reset,
329 .cle_bypass = xgene_enet_xgcle_bypass,
330 .shutdown = xgene_enet_shutdown,
331};
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.h b/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.h
new file mode 100644
index 000000000000..d2d59e7ed9ab
--- /dev/null
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.h
@@ -0,0 +1,57 @@
1/* Applied Micro X-Gene SoC Ethernet Driver
2 *
3 * Copyright (c) 2014, Applied Micro Circuits Corporation
4 * Authors: Iyappan Subramanian <isubramanian@apm.com>
5 * Keyur Chudgar <kchudgar@apm.com>
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 */
20
21#ifndef __XGENE_ENET_XGMAC_H__
22#define __XGENE_ENET_XGMAC_H__
23
24#define BLOCK_AXG_MAC_OFFSET 0x0800
25#define BLOCK_AXG_MAC_CSR_OFFSET 0x2000
26
27#define AXGMAC_CONFIG_0 0x0000
28#define AXGMAC_CONFIG_1 0x0004
29#define HSTMACRST BIT(31)
30#define HSTTCTLEN BIT(31)
31#define HSTTFEN BIT(30)
32#define HSTRCTLEN BIT(29)
33#define HSTRFEN BIT(28)
34#define HSTPPEN BIT(7)
35#define HSTDRPLT64 BIT(5)
36#define HSTLENCHK BIT(3)
37#define HSTMACADR_LSW_ADDR 0x0010
38#define HSTMACADR_MSW_ADDR 0x0014
39#define HSTMAXFRAME_LENGTH_ADDR 0x0020
40
41#define XG_RSIF_CONFIG_REG_ADDR 0x00a0
42#define XCLE_BYPASS_REG0_ADDR 0x0160
43#define XCLE_BYPASS_REG1_ADDR 0x0164
44#define XG_CFG_BYPASS_ADDR 0x0204
45#define XG_LINK_STATUS_ADDR 0x0228
46#define XG_ENET_SPARE_CFG_REG_ADDR 0x040c
47#define XG_ENET_SPARE_CFG_REG_1_ADDR 0x0410
48#define XGENET_RX_DV_GATE_REG_0_ADDR 0x0804
49
50#define PHY_POLL_LINK_ON (10 * HZ)
51#define PHY_POLL_LINK_OFF (PHY_POLL_LINK_ON / 5)
52
53void xgene_enet_link_state(struct work_struct *work);
54extern struct xgene_mac_ops xgene_xgmac_ops;
55extern struct xgene_port_ops xgene_xgport_ops;
56
57#endif /* __XGENE_ENET_XGMAC_H__ */