11ccea77eSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
2e6ad7673SIyappan Subramanian /* Applied Micro X-Gene SoC Ethernet Driver
3e6ad7673SIyappan Subramanian *
4e6ad7673SIyappan Subramanian * Copyright (c) 2014, Applied Micro Circuits Corporation
5e6ad7673SIyappan Subramanian * Authors: Iyappan Subramanian <isubramanian@apm.com>
6e6ad7673SIyappan Subramanian * Ravi Patel <rapatel@apm.com>
7e6ad7673SIyappan Subramanian * Keyur Chudgar <kchudgar@apm.com>
8e6ad7673SIyappan Subramanian */
9e6ad7673SIyappan Subramanian
10e6ad7673SIyappan Subramanian #include "xgene_enet_main.h"
11e6ad7673SIyappan Subramanian #include "xgene_enet_hw.h"
12e6ad7673SIyappan Subramanian
xgene_enet_ring_init(struct xgene_enet_desc_ring * ring)13e6ad7673SIyappan Subramanian static void xgene_enet_ring_init(struct xgene_enet_desc_ring *ring)
14e6ad7673SIyappan Subramanian {
15e6ad7673SIyappan Subramanian u32 *ring_cfg = ring->state;
16e6ad7673SIyappan Subramanian u64 addr = ring->dma;
17e6ad7673SIyappan Subramanian enum xgene_enet_ring_cfgsize cfgsize = ring->cfgsize;
18e6ad7673SIyappan Subramanian
19e6ad7673SIyappan Subramanian ring_cfg[4] |= (1 << SELTHRSH_POS) &
20e6ad7673SIyappan Subramanian CREATE_MASK(SELTHRSH_POS, SELTHRSH_LEN);
21e6ad7673SIyappan Subramanian ring_cfg[3] |= ACCEPTLERR;
22e6ad7673SIyappan Subramanian ring_cfg[2] |= QCOHERENT;
23e6ad7673SIyappan Subramanian
24e6ad7673SIyappan Subramanian addr >>= 8;
25e6ad7673SIyappan Subramanian ring_cfg[2] |= (addr << RINGADDRL_POS) &
26e6ad7673SIyappan Subramanian CREATE_MASK_ULL(RINGADDRL_POS, RINGADDRL_LEN);
27e6ad7673SIyappan Subramanian addr >>= RINGADDRL_LEN;
28e6ad7673SIyappan Subramanian ring_cfg[3] |= addr & CREATE_MASK_ULL(RINGADDRH_POS, RINGADDRH_LEN);
29e6ad7673SIyappan Subramanian ring_cfg[3] |= ((u32)cfgsize << RINGSIZE_POS) &
30e6ad7673SIyappan Subramanian CREATE_MASK(RINGSIZE_POS, RINGSIZE_LEN);
31e6ad7673SIyappan Subramanian }
32e6ad7673SIyappan Subramanian
xgene_enet_ring_set_type(struct xgene_enet_desc_ring * ring)33e6ad7673SIyappan Subramanian static void xgene_enet_ring_set_type(struct xgene_enet_desc_ring *ring)
34e6ad7673SIyappan Subramanian {
35e6ad7673SIyappan Subramanian u32 *ring_cfg = ring->state;
36e6ad7673SIyappan Subramanian bool is_bufpool;
37e6ad7673SIyappan Subramanian u32 val;
38e6ad7673SIyappan Subramanian
39e6ad7673SIyappan Subramanian is_bufpool = xgene_enet_is_bufpool(ring->id);
40e6ad7673SIyappan Subramanian val = (is_bufpool) ? RING_BUFPOOL : RING_REGULAR;
41e6ad7673SIyappan Subramanian ring_cfg[4] |= (val << RINGTYPE_POS) &
42e6ad7673SIyappan Subramanian CREATE_MASK(RINGTYPE_POS, RINGTYPE_LEN);
43e6ad7673SIyappan Subramanian
44e6ad7673SIyappan Subramanian if (is_bufpool) {
45e6ad7673SIyappan Subramanian ring_cfg[3] |= (BUFPOOL_MODE << RINGMODE_POS) &
46e6ad7673SIyappan Subramanian CREATE_MASK(RINGMODE_POS, RINGMODE_LEN);
47e6ad7673SIyappan Subramanian }
48e6ad7673SIyappan Subramanian }
49e6ad7673SIyappan Subramanian
xgene_enet_ring_set_recombbuf(struct xgene_enet_desc_ring * ring)50e6ad7673SIyappan Subramanian static void xgene_enet_ring_set_recombbuf(struct xgene_enet_desc_ring *ring)
51e6ad7673SIyappan Subramanian {
52e6ad7673SIyappan Subramanian u32 *ring_cfg = ring->state;
53e6ad7673SIyappan Subramanian
54e6ad7673SIyappan Subramanian ring_cfg[3] |= RECOMBBUF;
55e6ad7673SIyappan Subramanian ring_cfg[3] |= (0xf << RECOMTIMEOUTL_POS) &
56e6ad7673SIyappan Subramanian CREATE_MASK(RECOMTIMEOUTL_POS, RECOMTIMEOUTL_LEN);
57e6ad7673SIyappan Subramanian ring_cfg[4] |= 0x7 & CREATE_MASK(RECOMTIMEOUTH_POS, RECOMTIMEOUTH_LEN);
58e6ad7673SIyappan Subramanian }
59e6ad7673SIyappan Subramanian
xgene_enet_ring_wr32(struct xgene_enet_desc_ring * ring,u32 offset,u32 data)60e6ad7673SIyappan Subramanian static void xgene_enet_ring_wr32(struct xgene_enet_desc_ring *ring,
61e6ad7673SIyappan Subramanian u32 offset, u32 data)
62e6ad7673SIyappan Subramanian {
63e6ad7673SIyappan Subramanian struct xgene_enet_pdata *pdata = netdev_priv(ring->ndev);
64e6ad7673SIyappan Subramanian
65e6ad7673SIyappan Subramanian iowrite32(data, pdata->ring_csr_addr + offset);
66e6ad7673SIyappan Subramanian }
67e6ad7673SIyappan Subramanian
xgene_enet_ring_rd32(struct xgene_enet_desc_ring * ring,u32 offset,u32 * data)68e6ad7673SIyappan Subramanian static void xgene_enet_ring_rd32(struct xgene_enet_desc_ring *ring,
69e6ad7673SIyappan Subramanian u32 offset, u32 *data)
70e6ad7673SIyappan Subramanian {
71e6ad7673SIyappan Subramanian struct xgene_enet_pdata *pdata = netdev_priv(ring->ndev);
72e6ad7673SIyappan Subramanian
73e6ad7673SIyappan Subramanian *data = ioread32(pdata->ring_csr_addr + offset);
74e6ad7673SIyappan Subramanian }
75e6ad7673SIyappan Subramanian
xgene_enet_write_ring_state(struct xgene_enet_desc_ring * ring)76e6ad7673SIyappan Subramanian static void xgene_enet_write_ring_state(struct xgene_enet_desc_ring *ring)
77e6ad7673SIyappan Subramanian {
7881cefb81SIyappan Subramanian struct xgene_enet_pdata *pdata = netdev_priv(ring->ndev);
79e6ad7673SIyappan Subramanian int i;
80e6ad7673SIyappan Subramanian
81e6ad7673SIyappan Subramanian xgene_enet_ring_wr32(ring, CSR_RING_CONFIG, ring->num);
8281cefb81SIyappan Subramanian for (i = 0; i < pdata->ring_ops->num_ring_config; i++) {
83e6ad7673SIyappan Subramanian xgene_enet_ring_wr32(ring, CSR_RING_WR_BASE + (i * 4),
84e6ad7673SIyappan Subramanian ring->state[i]);
85e6ad7673SIyappan Subramanian }
86e6ad7673SIyappan Subramanian }
87e6ad7673SIyappan Subramanian
xgene_enet_clr_ring_state(struct xgene_enet_desc_ring * ring)88e6ad7673SIyappan Subramanian static void xgene_enet_clr_ring_state(struct xgene_enet_desc_ring *ring)
89e6ad7673SIyappan Subramanian {
9081cefb81SIyappan Subramanian memset(ring->state, 0, sizeof(ring->state));
91e6ad7673SIyappan Subramanian xgene_enet_write_ring_state(ring);
92e6ad7673SIyappan Subramanian }
93e6ad7673SIyappan Subramanian
xgene_enet_set_ring_state(struct xgene_enet_desc_ring * ring)94e6ad7673SIyappan Subramanian static void xgene_enet_set_ring_state(struct xgene_enet_desc_ring *ring)
95e6ad7673SIyappan Subramanian {
96e6ad7673SIyappan Subramanian xgene_enet_ring_set_type(ring);
97e6ad7673SIyappan Subramanian
98149e9ab4SIyappan Subramanian if (xgene_enet_ring_owner(ring->id) == RING_OWNER_ETH0 ||
99149e9ab4SIyappan Subramanian xgene_enet_ring_owner(ring->id) == RING_OWNER_ETH1)
100e6ad7673SIyappan Subramanian xgene_enet_ring_set_recombbuf(ring);
101e6ad7673SIyappan Subramanian
102e6ad7673SIyappan Subramanian xgene_enet_ring_init(ring);
103e6ad7673SIyappan Subramanian xgene_enet_write_ring_state(ring);
104e6ad7673SIyappan Subramanian }
105e6ad7673SIyappan Subramanian
xgene_enet_set_ring_id(struct xgene_enet_desc_ring * ring)106e6ad7673SIyappan Subramanian static void xgene_enet_set_ring_id(struct xgene_enet_desc_ring *ring)
107e6ad7673SIyappan Subramanian {
108e6ad7673SIyappan Subramanian u32 ring_id_val, ring_id_buf;
109e6ad7673SIyappan Subramanian bool is_bufpool;
110e6ad7673SIyappan Subramanian
111e6ad7673SIyappan Subramanian is_bufpool = xgene_enet_is_bufpool(ring->id);
112e6ad7673SIyappan Subramanian
113e6ad7673SIyappan Subramanian ring_id_val = ring->id & GENMASK(9, 0);
114e6ad7673SIyappan Subramanian ring_id_val |= OVERWRITE;
115e6ad7673SIyappan Subramanian
116e6ad7673SIyappan Subramanian ring_id_buf = (ring->num << 9) & GENMASK(18, 9);
117e6ad7673SIyappan Subramanian ring_id_buf |= PREFETCH_BUF_EN;
118e6ad7673SIyappan Subramanian if (is_bufpool)
119e6ad7673SIyappan Subramanian ring_id_buf |= IS_BUFFER_POOL;
120e6ad7673SIyappan Subramanian
121e6ad7673SIyappan Subramanian xgene_enet_ring_wr32(ring, CSR_RING_ID, ring_id_val);
122e6ad7673SIyappan Subramanian xgene_enet_ring_wr32(ring, CSR_RING_ID_BUF, ring_id_buf);
123e6ad7673SIyappan Subramanian }
124e6ad7673SIyappan Subramanian
xgene_enet_clr_desc_ring_id(struct xgene_enet_desc_ring * ring)125e6ad7673SIyappan Subramanian static void xgene_enet_clr_desc_ring_id(struct xgene_enet_desc_ring *ring)
126e6ad7673SIyappan Subramanian {
127e6ad7673SIyappan Subramanian u32 ring_id;
128e6ad7673SIyappan Subramanian
129e6ad7673SIyappan Subramanian ring_id = ring->id | OVERWRITE;
130e6ad7673SIyappan Subramanian xgene_enet_ring_wr32(ring, CSR_RING_ID, ring_id);
131e6ad7673SIyappan Subramanian xgene_enet_ring_wr32(ring, CSR_RING_ID_BUF, 0);
132e6ad7673SIyappan Subramanian }
133e6ad7673SIyappan Subramanian
xgene_enet_setup_ring(struct xgene_enet_desc_ring * ring)13481cefb81SIyappan Subramanian static struct xgene_enet_desc_ring *xgene_enet_setup_ring(
135e6ad7673SIyappan Subramanian struct xgene_enet_desc_ring *ring)
136e6ad7673SIyappan Subramanian {
137e6ad7673SIyappan Subramanian u32 size = ring->size;
138e6ad7673SIyappan Subramanian u32 i, data;
139e6ad7673SIyappan Subramanian bool is_bufpool;
140e6ad7673SIyappan Subramanian
141e6ad7673SIyappan Subramanian xgene_enet_clr_ring_state(ring);
142e6ad7673SIyappan Subramanian xgene_enet_set_ring_state(ring);
143e6ad7673SIyappan Subramanian xgene_enet_set_ring_id(ring);
144e6ad7673SIyappan Subramanian
145e6ad7673SIyappan Subramanian ring->slots = xgene_enet_get_numslots(ring->id, size);
146e6ad7673SIyappan Subramanian
147e6ad7673SIyappan Subramanian is_bufpool = xgene_enet_is_bufpool(ring->id);
148e6ad7673SIyappan Subramanian if (is_bufpool || xgene_enet_ring_owner(ring->id) != RING_OWNER_CPU)
149e6ad7673SIyappan Subramanian return ring;
150e6ad7673SIyappan Subramanian
151e6ad7673SIyappan Subramanian for (i = 0; i < ring->slots; i++)
152e6ad7673SIyappan Subramanian xgene_enet_mark_desc_slot_empty(&ring->raw_desc[i]);
153e6ad7673SIyappan Subramanian
154e6ad7673SIyappan Subramanian xgene_enet_ring_rd32(ring, CSR_RING_NE_INT_MODE, &data);
155e6ad7673SIyappan Subramanian data |= BIT(31 - xgene_enet_ring_bufnum(ring->id));
156e6ad7673SIyappan Subramanian xgene_enet_ring_wr32(ring, CSR_RING_NE_INT_MODE, data);
157e6ad7673SIyappan Subramanian
158e6ad7673SIyappan Subramanian return ring;
159e6ad7673SIyappan Subramanian }
160e6ad7673SIyappan Subramanian
xgene_enet_clear_ring(struct xgene_enet_desc_ring * ring)16181cefb81SIyappan Subramanian static void xgene_enet_clear_ring(struct xgene_enet_desc_ring *ring)
162e6ad7673SIyappan Subramanian {
163e6ad7673SIyappan Subramanian u32 data;
164e6ad7673SIyappan Subramanian bool is_bufpool;
165e6ad7673SIyappan Subramanian
166e6ad7673SIyappan Subramanian is_bufpool = xgene_enet_is_bufpool(ring->id);
167e6ad7673SIyappan Subramanian if (is_bufpool || xgene_enet_ring_owner(ring->id) != RING_OWNER_CPU)
168e6ad7673SIyappan Subramanian goto out;
169e6ad7673SIyappan Subramanian
170e6ad7673SIyappan Subramanian xgene_enet_ring_rd32(ring, CSR_RING_NE_INT_MODE, &data);
171e6ad7673SIyappan Subramanian data &= ~BIT(31 - xgene_enet_ring_bufnum(ring->id));
172e6ad7673SIyappan Subramanian xgene_enet_ring_wr32(ring, CSR_RING_NE_INT_MODE, data);
173e6ad7673SIyappan Subramanian
174e6ad7673SIyappan Subramanian out:
175e6ad7673SIyappan Subramanian xgene_enet_clr_desc_ring_id(ring);
176e6ad7673SIyappan Subramanian xgene_enet_clr_ring_state(ring);
177e6ad7673SIyappan Subramanian }
178e6ad7673SIyappan Subramanian
xgene_enet_wr_cmd(struct xgene_enet_desc_ring * ring,int count)17981cefb81SIyappan Subramanian static void xgene_enet_wr_cmd(struct xgene_enet_desc_ring *ring, int count)
18081cefb81SIyappan Subramanian {
18181cefb81SIyappan Subramanian iowrite32(count, ring->cmd);
18281cefb81SIyappan Subramanian }
18381cefb81SIyappan Subramanian
xgene_enet_ring_len(struct xgene_enet_desc_ring * ring)18481cefb81SIyappan Subramanian static u32 xgene_enet_ring_len(struct xgene_enet_desc_ring *ring)
18581cefb81SIyappan Subramanian {
18681cefb81SIyappan Subramanian u32 __iomem *cmd_base = ring->cmd_base;
18781cefb81SIyappan Subramanian u32 ring_state, num_msgs;
18881cefb81SIyappan Subramanian
18981cefb81SIyappan Subramanian ring_state = ioread32(&cmd_base[1]);
19081cefb81SIyappan Subramanian num_msgs = GET_VAL(NUMMSGSINQ, ring_state);
19181cefb81SIyappan Subramanian
19281cefb81SIyappan Subramanian return num_msgs;
19381cefb81SIyappan Subramanian }
19481cefb81SIyappan Subramanian
xgene_enet_parse_error(struct xgene_enet_desc_ring * ring,enum xgene_enet_err_code status)195e6ad7673SIyappan Subramanian void xgene_enet_parse_error(struct xgene_enet_desc_ring *ring,
196e6ad7673SIyappan Subramanian enum xgene_enet_err_code status)
197e6ad7673SIyappan Subramanian {
198e6ad7673SIyappan Subramanian switch (status) {
199e6ad7673SIyappan Subramanian case INGRESS_CRC:
2003bb502f8SIyappan Subramanian ring->rx_crc_errors++;
201e6ad7673SIyappan Subramanian break;
202e6ad7673SIyappan Subramanian case INGRESS_CHECKSUM:
203e6ad7673SIyappan Subramanian case INGRESS_CHECKSUM_COMPUTE:
2043bb502f8SIyappan Subramanian ring->rx_errors++;
205e6ad7673SIyappan Subramanian break;
206e6ad7673SIyappan Subramanian case INGRESS_TRUNC_FRAME:
2073bb502f8SIyappan Subramanian ring->rx_frame_errors++;
208e6ad7673SIyappan Subramanian break;
209e6ad7673SIyappan Subramanian case INGRESS_PKT_LEN:
2103bb502f8SIyappan Subramanian ring->rx_length_errors++;
211e6ad7673SIyappan Subramanian break;
212e6ad7673SIyappan Subramanian case INGRESS_PKT_UNDER:
2133bb502f8SIyappan Subramanian ring->rx_frame_errors++;
214e6ad7673SIyappan Subramanian break;
215e6ad7673SIyappan Subramanian case INGRESS_FIFO_OVERRUN:
2163bb502f8SIyappan Subramanian ring->rx_fifo_errors++;
217e6ad7673SIyappan Subramanian break;
218e6ad7673SIyappan Subramanian default:
219e6ad7673SIyappan Subramanian break;
220e6ad7673SIyappan Subramanian }
221e6ad7673SIyappan Subramanian }
222e6ad7673SIyappan Subramanian
xgene_enet_wr_csr(struct xgene_enet_pdata * pdata,u32 offset,u32 val)223e6ad7673SIyappan Subramanian static void xgene_enet_wr_csr(struct xgene_enet_pdata *pdata,
224e6ad7673SIyappan Subramanian u32 offset, u32 val)
225e6ad7673SIyappan Subramanian {
226e6ad7673SIyappan Subramanian void __iomem *addr = pdata->eth_csr_addr + offset;
227e6ad7673SIyappan Subramanian
228e6ad7673SIyappan Subramanian iowrite32(val, addr);
229e6ad7673SIyappan Subramanian }
230e6ad7673SIyappan Subramanian
xgene_enet_wr_ring_if(struct xgene_enet_pdata * pdata,u32 offset,u32 val)231e6ad7673SIyappan Subramanian static void xgene_enet_wr_ring_if(struct xgene_enet_pdata *pdata,
232e6ad7673SIyappan Subramanian u32 offset, u32 val)
233e6ad7673SIyappan Subramanian {
234e6ad7673SIyappan Subramanian void __iomem *addr = pdata->eth_ring_if_addr + offset;
235e6ad7673SIyappan Subramanian
236e6ad7673SIyappan Subramanian iowrite32(val, addr);
237e6ad7673SIyappan Subramanian }
238e6ad7673SIyappan Subramanian
xgene_enet_wr_diag_csr(struct xgene_enet_pdata * pdata,u32 offset,u32 val)239e6ad7673SIyappan Subramanian static void xgene_enet_wr_diag_csr(struct xgene_enet_pdata *pdata,
240e6ad7673SIyappan Subramanian u32 offset, u32 val)
241e6ad7673SIyappan Subramanian {
242e6ad7673SIyappan Subramanian void __iomem *addr = pdata->eth_diag_csr_addr + offset;
243e6ad7673SIyappan Subramanian
244e6ad7673SIyappan Subramanian iowrite32(val, addr);
245e6ad7673SIyappan Subramanian }
246e6ad7673SIyappan Subramanian
xgene_enet_wr_mcx_csr(struct xgene_enet_pdata * pdata,u32 offset,u32 val)247e6ad7673SIyappan Subramanian static void xgene_enet_wr_mcx_csr(struct xgene_enet_pdata *pdata,
248e6ad7673SIyappan Subramanian u32 offset, u32 val)
249e6ad7673SIyappan Subramanian {
250e6ad7673SIyappan Subramanian void __iomem *addr = pdata->mcx_mac_csr_addr + offset;
251e6ad7673SIyappan Subramanian
252e6ad7673SIyappan Subramanian iowrite32(val, addr);
253e6ad7673SIyappan Subramanian }
254e6ad7673SIyappan Subramanian
xgene_enet_wr_mac(struct xgene_enet_pdata * pdata,u32 wr_addr,u32 wr_data)255ae1aed95SIyappan Subramanian void xgene_enet_wr_mac(struct xgene_enet_pdata *pdata, u32 wr_addr, u32 wr_data)
256e6ad7673SIyappan Subramanian {
257e6ad7673SIyappan Subramanian void __iomem *addr, *wr, *cmd, *cmd_done;
258ae1aed95SIyappan Subramanian struct net_device *ndev = pdata->ndev;
259ae1aed95SIyappan Subramanian u8 wait = 10;
260ae1aed95SIyappan Subramanian u32 done;
261e6ad7673SIyappan Subramanian
262d09d3629SQuan Nguyen if (pdata->mdio_driver && ndev->phydev &&
263326dde3eSIyappan Subramanian phy_interface_mode_is_rgmii(pdata->phy_mode)) {
264d09d3629SQuan Nguyen struct mii_bus *bus = ndev->phydev->mdio.bus;
265d09d3629SQuan Nguyen
266d09d3629SQuan Nguyen return xgene_mdio_wr_mac(bus->priv, wr_addr, wr_data);
267d09d3629SQuan Nguyen }
268d09d3629SQuan Nguyen
269e6ad7673SIyappan Subramanian addr = pdata->mcx_mac_addr + MAC_ADDR_REG_OFFSET;
270e6ad7673SIyappan Subramanian wr = pdata->mcx_mac_addr + MAC_WRITE_REG_OFFSET;
271e6ad7673SIyappan Subramanian cmd = pdata->mcx_mac_addr + MAC_COMMAND_REG_OFFSET;
272e6ad7673SIyappan Subramanian cmd_done = pdata->mcx_mac_addr + MAC_COMMAND_DONE_REG_OFFSET;
273e6ad7673SIyappan Subramanian
274ae1aed95SIyappan Subramanian spin_lock(&pdata->mac_lock);
275ae1aed95SIyappan Subramanian iowrite32(wr_addr, addr);
276ae1aed95SIyappan Subramanian iowrite32(wr_data, wr);
277ae1aed95SIyappan Subramanian iowrite32(XGENE_ENET_WR_CMD, cmd);
278ae1aed95SIyappan Subramanian
279ae1aed95SIyappan Subramanian while (!(done = ioread32(cmd_done)) && wait--)
280ae1aed95SIyappan Subramanian udelay(1);
281ae1aed95SIyappan Subramanian
282ae1aed95SIyappan Subramanian if (!done)
283ae1aed95SIyappan Subramanian netdev_err(ndev, "mac write failed, addr: %04x data: %08x\n",
284ae1aed95SIyappan Subramanian wr_addr, wr_data);
285ae1aed95SIyappan Subramanian
286ae1aed95SIyappan Subramanian iowrite32(0, cmd);
287ae1aed95SIyappan Subramanian spin_unlock(&pdata->mac_lock);
288e6ad7673SIyappan Subramanian }
289e6ad7673SIyappan Subramanian
xgene_enet_rd_csr(struct xgene_enet_pdata * pdata,u32 offset,u32 * val)290e6ad7673SIyappan Subramanian static void xgene_enet_rd_csr(struct xgene_enet_pdata *pdata,
291e6ad7673SIyappan Subramanian u32 offset, u32 *val)
292e6ad7673SIyappan Subramanian {
293e6ad7673SIyappan Subramanian void __iomem *addr = pdata->eth_csr_addr + offset;
294e6ad7673SIyappan Subramanian
295e6ad7673SIyappan Subramanian *val = ioread32(addr);
296e6ad7673SIyappan Subramanian }
297e6ad7673SIyappan Subramanian
xgene_enet_rd_diag_csr(struct xgene_enet_pdata * pdata,u32 offset,u32 * val)298e6ad7673SIyappan Subramanian static void xgene_enet_rd_diag_csr(struct xgene_enet_pdata *pdata,
299e6ad7673SIyappan Subramanian u32 offset, u32 *val)
300e6ad7673SIyappan Subramanian {
301e6ad7673SIyappan Subramanian void __iomem *addr = pdata->eth_diag_csr_addr + offset;
302e6ad7673SIyappan Subramanian
303e6ad7673SIyappan Subramanian *val = ioread32(addr);
304e6ad7673SIyappan Subramanian }
305e6ad7673SIyappan Subramanian
xgene_enet_rd_mcx_csr(struct xgene_enet_pdata * pdata,u32 offset,u32 * val)306e6ad7673SIyappan Subramanian static void xgene_enet_rd_mcx_csr(struct xgene_enet_pdata *pdata,
307e6ad7673SIyappan Subramanian u32 offset, u32 *val)
308e6ad7673SIyappan Subramanian {
309e6ad7673SIyappan Subramanian void __iomem *addr = pdata->mcx_mac_csr_addr + offset;
310e6ad7673SIyappan Subramanian
311e6ad7673SIyappan Subramanian *val = ioread32(addr);
312e6ad7673SIyappan Subramanian }
313e6ad7673SIyappan Subramanian
xgene_enet_rd_mac(struct xgene_enet_pdata * pdata,u32 rd_addr)314ae1aed95SIyappan Subramanian u32 xgene_enet_rd_mac(struct xgene_enet_pdata *pdata, u32 rd_addr)
315e6ad7673SIyappan Subramanian {
316e6ad7673SIyappan Subramanian void __iomem *addr, *rd, *cmd, *cmd_done;
317326dde3eSIyappan Subramanian struct net_device *ndev = pdata->ndev;
318ae1aed95SIyappan Subramanian u32 done, rd_data;
319ae1aed95SIyappan Subramanian u8 wait = 10;
320e6ad7673SIyappan Subramanian
321326dde3eSIyappan Subramanian if (pdata->mdio_driver && ndev->phydev &&
322326dde3eSIyappan Subramanian phy_interface_mode_is_rgmii(pdata->phy_mode)) {
323326dde3eSIyappan Subramanian struct mii_bus *bus = ndev->phydev->mdio.bus;
324d09d3629SQuan Nguyen
325d09d3629SQuan Nguyen return xgene_mdio_rd_mac(bus->priv, rd_addr);
326d09d3629SQuan Nguyen }
327d09d3629SQuan Nguyen
328e6ad7673SIyappan Subramanian addr = pdata->mcx_mac_addr + MAC_ADDR_REG_OFFSET;
329e6ad7673SIyappan Subramanian rd = pdata->mcx_mac_addr + MAC_READ_REG_OFFSET;
330e6ad7673SIyappan Subramanian cmd = pdata->mcx_mac_addr + MAC_COMMAND_REG_OFFSET;
331e6ad7673SIyappan Subramanian cmd_done = pdata->mcx_mac_addr + MAC_COMMAND_DONE_REG_OFFSET;
332e6ad7673SIyappan Subramanian
333ae1aed95SIyappan Subramanian spin_lock(&pdata->mac_lock);
334ae1aed95SIyappan Subramanian iowrite32(rd_addr, addr);
335ae1aed95SIyappan Subramanian iowrite32(XGENE_ENET_RD_CMD, cmd);
336ae1aed95SIyappan Subramanian
337ae1aed95SIyappan Subramanian while (!(done = ioread32(cmd_done)) && wait--)
338ae1aed95SIyappan Subramanian udelay(1);
339ae1aed95SIyappan Subramanian
340ae1aed95SIyappan Subramanian if (!done)
341326dde3eSIyappan Subramanian netdev_err(ndev, "mac read failed, addr: %04x\n", rd_addr);
342ae1aed95SIyappan Subramanian
343ae1aed95SIyappan Subramanian rd_data = ioread32(rd);
344ae1aed95SIyappan Subramanian iowrite32(0, cmd);
345ae1aed95SIyappan Subramanian spin_unlock(&pdata->mac_lock);
346ae1aed95SIyappan Subramanian
347ae1aed95SIyappan Subramanian return rd_data;
348e6ad7673SIyappan Subramanian }
349e6ad7673SIyappan Subramanian
xgene_enet_rd_stat(struct xgene_enet_pdata * pdata,u32 rd_addr)3502d07d8e4SQuan Nguyen u32 xgene_enet_rd_stat(struct xgene_enet_pdata *pdata, u32 rd_addr)
3512d07d8e4SQuan Nguyen {
3522d07d8e4SQuan Nguyen void __iomem *addr, *rd, *cmd, *cmd_done;
3532d07d8e4SQuan Nguyen u32 done, rd_data;
3542d07d8e4SQuan Nguyen u8 wait = 10;
3552d07d8e4SQuan Nguyen
3562d07d8e4SQuan Nguyen addr = pdata->mcx_stats_addr + STAT_ADDR_REG_OFFSET;
3572d07d8e4SQuan Nguyen rd = pdata->mcx_stats_addr + STAT_READ_REG_OFFSET;
3582d07d8e4SQuan Nguyen cmd = pdata->mcx_stats_addr + STAT_COMMAND_REG_OFFSET;
3592d07d8e4SQuan Nguyen cmd_done = pdata->mcx_stats_addr + STAT_COMMAND_DONE_REG_OFFSET;
3602d07d8e4SQuan Nguyen
3612d07d8e4SQuan Nguyen spin_lock(&pdata->stats_lock);
3622d07d8e4SQuan Nguyen iowrite32(rd_addr, addr);
3632d07d8e4SQuan Nguyen iowrite32(XGENE_ENET_RD_CMD, cmd);
3642d07d8e4SQuan Nguyen
3652d07d8e4SQuan Nguyen while (!(done = ioread32(cmd_done)) && wait--)
3662d07d8e4SQuan Nguyen udelay(1);
3672d07d8e4SQuan Nguyen
3682d07d8e4SQuan Nguyen if (!done)
3692d07d8e4SQuan Nguyen netdev_err(pdata->ndev, "mac stats read failed, addr: %04x\n",
3702d07d8e4SQuan Nguyen rd_addr);
3712d07d8e4SQuan Nguyen
3722d07d8e4SQuan Nguyen rd_data = ioread32(rd);
3732d07d8e4SQuan Nguyen iowrite32(0, cmd);
3742d07d8e4SQuan Nguyen spin_unlock(&pdata->stats_lock);
3752d07d8e4SQuan Nguyen
3762d07d8e4SQuan Nguyen return rd_data;
3772d07d8e4SQuan Nguyen }
3782d07d8e4SQuan Nguyen
xgene_gmac_set_mac_addr(struct xgene_enet_pdata * pdata)379d0eb7458SIyappan Subramanian static void xgene_gmac_set_mac_addr(struct xgene_enet_pdata *pdata)
380e6ad7673SIyappan Subramanian {
381*76660757SJakub Kicinski const u8 *dev_addr = pdata->ndev->dev_addr;
382e6ad7673SIyappan Subramanian u32 addr0, addr1;
383e6ad7673SIyappan Subramanian
384e6ad7673SIyappan Subramanian addr0 = (dev_addr[3] << 24) | (dev_addr[2] << 16) |
385e6ad7673SIyappan Subramanian (dev_addr[1] << 8) | dev_addr[0];
386e6ad7673SIyappan Subramanian addr1 = (dev_addr[5] << 24) | (dev_addr[4] << 16);
387e6ad7673SIyappan Subramanian
388ae1aed95SIyappan Subramanian xgene_enet_wr_mac(pdata, STATION_ADDR0_ADDR, addr0);
389ae1aed95SIyappan Subramanian xgene_enet_wr_mac(pdata, STATION_ADDR1_ADDR, addr1);
390e6ad7673SIyappan Subramanian }
391e6ad7673SIyappan Subramanian
xgene_enet_ecc_init(struct xgene_enet_pdata * pdata)392e6ad7673SIyappan Subramanian static int xgene_enet_ecc_init(struct xgene_enet_pdata *pdata)
393e6ad7673SIyappan Subramanian {
394e6ad7673SIyappan Subramanian struct net_device *ndev = pdata->ndev;
395e6ad7673SIyappan Subramanian u32 data;
396e6ad7673SIyappan Subramanian u8 wait = 10;
397e6ad7673SIyappan Subramanian
398e6ad7673SIyappan Subramanian xgene_enet_wr_diag_csr(pdata, ENET_CFG_MEM_RAM_SHUTDOWN_ADDR, 0x0);
399e6ad7673SIyappan Subramanian do {
400e6ad7673SIyappan Subramanian usleep_range(100, 110);
401e6ad7673SIyappan Subramanian xgene_enet_rd_diag_csr(pdata, ENET_BLOCK_MEM_RDY_ADDR, &data);
402e6ad7673SIyappan Subramanian } while ((data != 0xffffffff) && wait--);
403e6ad7673SIyappan Subramanian
404e6ad7673SIyappan Subramanian if (data != 0xffffffff) {
405e6ad7673SIyappan Subramanian netdev_err(ndev, "Failed to release memory from shutdown\n");
406e6ad7673SIyappan Subramanian return -ENODEV;
407e6ad7673SIyappan Subramanian }
408e6ad7673SIyappan Subramanian
409e6ad7673SIyappan Subramanian return 0;
410e6ad7673SIyappan Subramanian }
411e6ad7673SIyappan Subramanian
xgene_gmac_reset(struct xgene_enet_pdata * pdata)412d0eb7458SIyappan Subramanian static void xgene_gmac_reset(struct xgene_enet_pdata *pdata)
413e6ad7673SIyappan Subramanian {
414ae1aed95SIyappan Subramanian xgene_enet_wr_mac(pdata, MAC_CONFIG_1_ADDR, SOFT_RESET1);
415ae1aed95SIyappan Subramanian xgene_enet_wr_mac(pdata, MAC_CONFIG_1_ADDR, 0);
416e6ad7673SIyappan Subramanian }
417e6ad7673SIyappan Subramanian
xgene_enet_configure_clock(struct xgene_enet_pdata * pdata)418761d4be5SIyappan Subramanian static void xgene_enet_configure_clock(struct xgene_enet_pdata *pdata)
419761d4be5SIyappan Subramanian {
420761d4be5SIyappan Subramanian struct device *dev = &pdata->pdev->dev;
421761d4be5SIyappan Subramanian
422761d4be5SIyappan Subramanian if (dev->of_node) {
423761d4be5SIyappan Subramanian struct clk *parent = clk_get_parent(pdata->clk);
424761d4be5SIyappan Subramanian
425761d4be5SIyappan Subramanian switch (pdata->phy_speed) {
426761d4be5SIyappan Subramanian case SPEED_10:
427761d4be5SIyappan Subramanian clk_set_rate(parent, 2500000);
428761d4be5SIyappan Subramanian break;
429761d4be5SIyappan Subramanian case SPEED_100:
430761d4be5SIyappan Subramanian clk_set_rate(parent, 25000000);
431761d4be5SIyappan Subramanian break;
432761d4be5SIyappan Subramanian default:
433761d4be5SIyappan Subramanian clk_set_rate(parent, 125000000);
434761d4be5SIyappan Subramanian break;
435761d4be5SIyappan Subramanian }
436761d4be5SIyappan Subramanian }
437761d4be5SIyappan Subramanian #ifdef CONFIG_ACPI
438761d4be5SIyappan Subramanian else {
439761d4be5SIyappan Subramanian switch (pdata->phy_speed) {
440761d4be5SIyappan Subramanian case SPEED_10:
441761d4be5SIyappan Subramanian acpi_evaluate_object(ACPI_HANDLE(dev),
442761d4be5SIyappan Subramanian "S10", NULL, NULL);
443761d4be5SIyappan Subramanian break;
444761d4be5SIyappan Subramanian case SPEED_100:
445761d4be5SIyappan Subramanian acpi_evaluate_object(ACPI_HANDLE(dev),
446761d4be5SIyappan Subramanian "S100", NULL, NULL);
447761d4be5SIyappan Subramanian break;
448761d4be5SIyappan Subramanian default:
449761d4be5SIyappan Subramanian acpi_evaluate_object(ACPI_HANDLE(dev),
450761d4be5SIyappan Subramanian "S1G", NULL, NULL);
451761d4be5SIyappan Subramanian break;
452761d4be5SIyappan Subramanian }
453761d4be5SIyappan Subramanian }
454761d4be5SIyappan Subramanian #endif
455761d4be5SIyappan Subramanian }
456761d4be5SIyappan Subramanian
xgene_gmac_set_speed(struct xgene_enet_pdata * pdata)4579a8c5ddeSIyappan Subramanian static void xgene_gmac_set_speed(struct xgene_enet_pdata *pdata)
458e6ad7673SIyappan Subramanian {
4599a8c5ddeSIyappan Subramanian u32 icm0, icm2, mc2;
4609a8c5ddeSIyappan Subramanian u32 intf_ctl, rgmii, value;
461e6ad7673SIyappan Subramanian
462e6ad7673SIyappan Subramanian xgene_enet_rd_mcx_csr(pdata, ICM_CONFIG0_REG_0_ADDR, &icm0);
463e6ad7673SIyappan Subramanian xgene_enet_rd_mcx_csr(pdata, ICM_CONFIG2_REG_0_ADDR, &icm2);
464ae1aed95SIyappan Subramanian mc2 = xgene_enet_rd_mac(pdata, MAC_CONFIG_2_ADDR);
465ae1aed95SIyappan Subramanian intf_ctl = xgene_enet_rd_mac(pdata, INTERFACE_CONTROL_ADDR);
466e6ad7673SIyappan Subramanian xgene_enet_rd_csr(pdata, RGMII_REG_0_ADDR, &rgmii);
467e6ad7673SIyappan Subramanian
468d0eb7458SIyappan Subramanian switch (pdata->phy_speed) {
469e6ad7673SIyappan Subramanian case SPEED_10:
470e6ad7673SIyappan Subramanian ENET_INTERFACE_MODE2_SET(&mc2, 1);
471761d4be5SIyappan Subramanian intf_ctl &= ~(ENET_LHD_MODE | ENET_GHD_MODE);
472e6ad7673SIyappan Subramanian CFG_MACMODE_SET(&icm0, 0);
473e6ad7673SIyappan Subramanian CFG_WAITASYNCRD_SET(&icm2, 500);
474e6ad7673SIyappan Subramanian rgmii &= ~CFG_SPEED_1250;
475e6ad7673SIyappan Subramanian break;
476e6ad7673SIyappan Subramanian case SPEED_100:
477e6ad7673SIyappan Subramanian ENET_INTERFACE_MODE2_SET(&mc2, 1);
478761d4be5SIyappan Subramanian intf_ctl &= ~ENET_GHD_MODE;
479e6ad7673SIyappan Subramanian intf_ctl |= ENET_LHD_MODE;
480e6ad7673SIyappan Subramanian CFG_MACMODE_SET(&icm0, 1);
481e6ad7673SIyappan Subramanian CFG_WAITASYNCRD_SET(&icm2, 80);
482e6ad7673SIyappan Subramanian rgmii &= ~CFG_SPEED_1250;
483e6ad7673SIyappan Subramanian break;
484e6ad7673SIyappan Subramanian default:
485e6ad7673SIyappan Subramanian ENET_INTERFACE_MODE2_SET(&mc2, 2);
486761d4be5SIyappan Subramanian intf_ctl &= ~ENET_LHD_MODE;
487e6ad7673SIyappan Subramanian intf_ctl |= ENET_GHD_MODE;
488761d4be5SIyappan Subramanian CFG_MACMODE_SET(&icm0, 2);
489761d4be5SIyappan Subramanian CFG_WAITASYNCRD_SET(&icm2, 0);
49016615a4cSIyappan Subramanian CFG_TXCLK_MUXSEL0_SET(&rgmii, pdata->tx_delay);
49116615a4cSIyappan Subramanian CFG_RXCLK_MUXSEL0_SET(&rgmii, pdata->rx_delay);
492761d4be5SIyappan Subramanian rgmii |= CFG_SPEED_1250;
49316615a4cSIyappan Subramanian
494e6ad7673SIyappan Subramanian xgene_enet_rd_csr(pdata, DEBUG_REG_ADDR, &value);
495e6ad7673SIyappan Subramanian value |= CFG_BYPASS_UNISEC_TX | CFG_BYPASS_UNISEC_RX;
496e6ad7673SIyappan Subramanian xgene_enet_wr_csr(pdata, DEBUG_REG_ADDR, value);
497e6ad7673SIyappan Subramanian break;
498e6ad7673SIyappan Subramanian }
499e6ad7673SIyappan Subramanian
5004902a922SIyappan Subramanian mc2 |= FULL_DUPLEX2 | PAD_CRC | LENGTH_CHK;
501ae1aed95SIyappan Subramanian xgene_enet_wr_mac(pdata, MAC_CONFIG_2_ADDR, mc2);
502ae1aed95SIyappan Subramanian xgene_enet_wr_mac(pdata, INTERFACE_CONTROL_ADDR, intf_ctl);
5039a8c5ddeSIyappan Subramanian xgene_enet_wr_csr(pdata, RGMII_REG_0_ADDR, rgmii);
5049a8c5ddeSIyappan Subramanian xgene_enet_configure_clock(pdata);
505e6ad7673SIyappan Subramanian
5069a8c5ddeSIyappan Subramanian xgene_enet_wr_mcx_csr(pdata, ICM_CONFIG0_REG_0_ADDR, icm0);
5079a8c5ddeSIyappan Subramanian xgene_enet_wr_mcx_csr(pdata, ICM_CONFIG2_REG_0_ADDR, icm2);
5089a8c5ddeSIyappan Subramanian }
5099a8c5ddeSIyappan Subramanian
xgene_enet_set_frame_size(struct xgene_enet_pdata * pdata,int size)510350b4e33SIyappan Subramanian static void xgene_enet_set_frame_size(struct xgene_enet_pdata *pdata, int size)
511350b4e33SIyappan Subramanian {
512ae1aed95SIyappan Subramanian xgene_enet_wr_mac(pdata, MAX_FRAME_LEN_ADDR, size);
513350b4e33SIyappan Subramanian }
514350b4e33SIyappan Subramanian
xgene_gmac_enable_tx_pause(struct xgene_enet_pdata * pdata,bool enable)515bb64fa09SIyappan Subramanian static void xgene_gmac_enable_tx_pause(struct xgene_enet_pdata *pdata,
516bb64fa09SIyappan Subramanian bool enable)
517bb64fa09SIyappan Subramanian {
518bb64fa09SIyappan Subramanian u32 data;
519bb64fa09SIyappan Subramanian
520bb64fa09SIyappan Subramanian xgene_enet_rd_mcx_csr(pdata, CSR_ECM_CFG_0_ADDR, &data);
521bb64fa09SIyappan Subramanian
522bb64fa09SIyappan Subramanian if (enable)
523bb64fa09SIyappan Subramanian data |= MULTI_DPF_AUTOCTRL | PAUSE_XON_EN;
524bb64fa09SIyappan Subramanian else
525bb64fa09SIyappan Subramanian data &= ~(MULTI_DPF_AUTOCTRL | PAUSE_XON_EN);
526bb64fa09SIyappan Subramanian
527bb64fa09SIyappan Subramanian xgene_enet_wr_mcx_csr(pdata, CSR_ECM_CFG_0_ADDR, data);
528bb64fa09SIyappan Subramanian }
529bb64fa09SIyappan Subramanian
xgene_gmac_flowctl_tx(struct xgene_enet_pdata * pdata,bool enable)530bb64fa09SIyappan Subramanian static void xgene_gmac_flowctl_tx(struct xgene_enet_pdata *pdata, bool enable)
531bb64fa09SIyappan Subramanian {
532bb64fa09SIyappan Subramanian u32 data;
533bb64fa09SIyappan Subramanian
534ae1aed95SIyappan Subramanian data = xgene_enet_rd_mac(pdata, MAC_CONFIG_1_ADDR);
535bb64fa09SIyappan Subramanian
536bb64fa09SIyappan Subramanian if (enable)
537bb64fa09SIyappan Subramanian data |= TX_FLOW_EN;
538bb64fa09SIyappan Subramanian else
539bb64fa09SIyappan Subramanian data &= ~TX_FLOW_EN;
540bb64fa09SIyappan Subramanian
541ae1aed95SIyappan Subramanian xgene_enet_wr_mac(pdata, MAC_CONFIG_1_ADDR, data);
542bb64fa09SIyappan Subramanian
543bb64fa09SIyappan Subramanian pdata->mac_ops->enable_tx_pause(pdata, enable);
544bb64fa09SIyappan Subramanian }
545bb64fa09SIyappan Subramanian
xgene_gmac_flowctl_rx(struct xgene_enet_pdata * pdata,bool enable)546bb64fa09SIyappan Subramanian static void xgene_gmac_flowctl_rx(struct xgene_enet_pdata *pdata, bool enable)
547bb64fa09SIyappan Subramanian {
548bb64fa09SIyappan Subramanian u32 data;
549bb64fa09SIyappan Subramanian
550ae1aed95SIyappan Subramanian data = xgene_enet_rd_mac(pdata, MAC_CONFIG_1_ADDR);
551bb64fa09SIyappan Subramanian
552bb64fa09SIyappan Subramanian if (enable)
553bb64fa09SIyappan Subramanian data |= RX_FLOW_EN;
554bb64fa09SIyappan Subramanian else
555bb64fa09SIyappan Subramanian data &= ~RX_FLOW_EN;
556bb64fa09SIyappan Subramanian
557ae1aed95SIyappan Subramanian xgene_enet_wr_mac(pdata, MAC_CONFIG_1_ADDR, data);
558bb64fa09SIyappan Subramanian }
559bb64fa09SIyappan Subramanian
xgene_gmac_init(struct xgene_enet_pdata * pdata)5609a8c5ddeSIyappan Subramanian static void xgene_gmac_init(struct xgene_enet_pdata *pdata)
5619a8c5ddeSIyappan Subramanian {
5629a8c5ddeSIyappan Subramanian u32 value;
5639a8c5ddeSIyappan Subramanian
5648089a96fSIyappan Subramanian if (!pdata->mdio_driver)
5659a8c5ddeSIyappan Subramanian xgene_gmac_reset(pdata);
5668089a96fSIyappan Subramanian
5679a8c5ddeSIyappan Subramanian xgene_gmac_set_speed(pdata);
568e6ad7673SIyappan Subramanian xgene_gmac_set_mac_addr(pdata);
569e6ad7673SIyappan Subramanian
570e6ad7673SIyappan Subramanian /* Adjust MDC clock frequency */
571ae1aed95SIyappan Subramanian value = xgene_enet_rd_mac(pdata, MII_MGMT_CONFIG_ADDR);
572e6ad7673SIyappan Subramanian MGMT_CLOCK_SEL_SET(&value, 7);
573ae1aed95SIyappan Subramanian xgene_enet_wr_mac(pdata, MII_MGMT_CONFIG_ADDR, value);
574e6ad7673SIyappan Subramanian
575e6ad7673SIyappan Subramanian /* Enable drop if bufpool not available */
576e6ad7673SIyappan Subramanian xgene_enet_rd_csr(pdata, RSIF_CONFIG_REG_ADDR, &value);
577e6ad7673SIyappan Subramanian value |= CFG_RSIF_FPBUFF_TIMEOUT_EN;
578e6ad7673SIyappan Subramanian xgene_enet_wr_csr(pdata, RSIF_CONFIG_REG_ADDR, value);
579e6ad7673SIyappan Subramanian
580e6ad7673SIyappan Subramanian /* Rtype should be copied from FP */
581e6ad7673SIyappan Subramanian xgene_enet_wr_csr(pdata, RSIF_RAM_DBG_REG0_ADDR, 0);
582e6ad7673SIyappan Subramanian
58356090b12SIyappan Subramanian /* Configure HW pause frame generation */
58456090b12SIyappan Subramanian xgene_enet_rd_mcx_csr(pdata, CSR_MULTI_DPF0_ADDR, &value);
58556090b12SIyappan Subramanian value = (DEF_QUANTA << 16) | (value & 0xFFFF);
58656090b12SIyappan Subramanian xgene_enet_wr_mcx_csr(pdata, CSR_MULTI_DPF0_ADDR, value);
58756090b12SIyappan Subramanian
58856090b12SIyappan Subramanian xgene_enet_wr_csr(pdata, RXBUF_PAUSE_THRESH, DEF_PAUSE_THRES);
58956090b12SIyappan Subramanian xgene_enet_wr_csr(pdata, RXBUF_PAUSE_OFF_THRESH, DEF_PAUSE_OFF_THRES);
59056090b12SIyappan Subramanian
59156090b12SIyappan Subramanian xgene_gmac_flowctl_tx(pdata, pdata->tx_pause);
59256090b12SIyappan Subramanian xgene_gmac_flowctl_rx(pdata, pdata->rx_pause);
59356090b12SIyappan Subramanian
594e6ad7673SIyappan Subramanian /* Rx-Tx traffic resume */
595e6ad7673SIyappan Subramanian xgene_enet_wr_csr(pdata, CFG_LINK_AGGR_RESUME_0_ADDR, TX_PORT0);
596e6ad7673SIyappan Subramanian
597e6ad7673SIyappan Subramanian xgene_enet_rd_mcx_csr(pdata, RX_DV_GATE_REG_0_ADDR, &value);
598e6ad7673SIyappan Subramanian value &= ~TX_DV_GATE_EN0;
599e6ad7673SIyappan Subramanian value &= ~RX_DV_GATE_EN0;
600e6ad7673SIyappan Subramanian value |= RESUME_RX0;
601e6ad7673SIyappan Subramanian xgene_enet_wr_mcx_csr(pdata, RX_DV_GATE_REG_0_ADDR, value);
602e6ad7673SIyappan Subramanian
603e6ad7673SIyappan Subramanian xgene_enet_wr_csr(pdata, CFG_BYPASS_ADDR, RESUME_TX);
604e6ad7673SIyappan Subramanian }
605e6ad7673SIyappan Subramanian
xgene_gmac_get_drop_cnt(struct xgene_enet_pdata * pdata,u32 * rx,u32 * tx)606ca6d550cSIyappan Subramanian static void xgene_gmac_get_drop_cnt(struct xgene_enet_pdata *pdata,
607ca6d550cSIyappan Subramanian u32 *rx, u32 *tx)
608ca6d550cSIyappan Subramanian {
609ca6d550cSIyappan Subramanian u32 count;
610ca6d550cSIyappan Subramanian
611ca6d550cSIyappan Subramanian xgene_enet_rd_mcx_csr(pdata, ICM_ECM_DROP_COUNT_REG0_ADDR, &count);
612ca6d550cSIyappan Subramanian *rx = ICM_DROP_COUNT(count);
613ca6d550cSIyappan Subramanian *tx = ECM_DROP_COUNT(count);
614a844e7d1SQuan Nguyen /* Errata: 10GE_4 - Fix ICM_ECM_DROP_COUNT not clear-on-read */
615a844e7d1SQuan Nguyen xgene_enet_rd_mcx_csr(pdata, ECM_CONFIG0_REG_0_ADDR, &count);
616ca6d550cSIyappan Subramanian }
617ca6d550cSIyappan Subramanian
xgene_enet_config_ring_if_assoc(struct xgene_enet_pdata * pdata)618e6ad7673SIyappan Subramanian static void xgene_enet_config_ring_if_assoc(struct xgene_enet_pdata *pdata)
619e6ad7673SIyappan Subramanian {
620e6ad7673SIyappan Subramanian u32 val = 0xffffffff;
621e6ad7673SIyappan Subramanian
622e6ad7673SIyappan Subramanian xgene_enet_wr_ring_if(pdata, ENET_CFGSSQMIWQASSOC_ADDR, val);
623e6ad7673SIyappan Subramanian xgene_enet_wr_ring_if(pdata, ENET_CFGSSQMIFPQASSOC_ADDR, val);
624e6ad7673SIyappan Subramanian xgene_enet_wr_ring_if(pdata, ENET_CFGSSQMIQMLITEWQASSOC_ADDR, val);
625e6ad7673SIyappan Subramanian xgene_enet_wr_ring_if(pdata, ENET_CFGSSQMIQMLITEFPQASSOC_ADDR, val);
626e6ad7673SIyappan Subramanian }
627e6ad7673SIyappan Subramanian
xgene_enet_cle_bypass(struct xgene_enet_pdata * pdata,u32 dst_ring_num,u16 bufpool_id,u16 nxtbufpool_id)628d0eb7458SIyappan Subramanian static void xgene_enet_cle_bypass(struct xgene_enet_pdata *pdata,
629d6d48969SIyappan Subramanian u32 dst_ring_num, u16 bufpool_id,
630d6d48969SIyappan Subramanian u16 nxtbufpool_id)
631e6ad7673SIyappan Subramanian {
632e6ad7673SIyappan Subramanian u32 cb;
633d6d48969SIyappan Subramanian u32 fpsel, nxtfpsel;
634e6ad7673SIyappan Subramanian
6352c839337SIyappan Subramanian fpsel = xgene_enet_get_fpsel(bufpool_id);
636d6d48969SIyappan Subramanian nxtfpsel = xgene_enet_get_fpsel(nxtbufpool_id);
637e6ad7673SIyappan Subramanian
638e6ad7673SIyappan Subramanian xgene_enet_rd_csr(pdata, CLE_BYPASS_REG0_0_ADDR, &cb);
639e6ad7673SIyappan Subramanian cb |= CFG_CLE_BYPASS_EN0;
640e6ad7673SIyappan Subramanian CFG_CLE_IP_PROTOCOL0_SET(&cb, 3);
641e026e700SQuan Nguyen CFG_CLE_IP_HDR_LEN_SET(&cb, 0);
642e6ad7673SIyappan Subramanian xgene_enet_wr_csr(pdata, CLE_BYPASS_REG0_0_ADDR, cb);
643e6ad7673SIyappan Subramanian
644e6ad7673SIyappan Subramanian xgene_enet_rd_csr(pdata, CLE_BYPASS_REG1_0_ADDR, &cb);
645e6ad7673SIyappan Subramanian CFG_CLE_DSTQID0_SET(&cb, dst_ring_num);
646e6ad7673SIyappan Subramanian CFG_CLE_FPSEL0_SET(&cb, fpsel);
647d6d48969SIyappan Subramanian CFG_CLE_NXTFPSEL0_SET(&cb, nxtfpsel);
648e6ad7673SIyappan Subramanian xgene_enet_wr_csr(pdata, CLE_BYPASS_REG1_0_ADDR, cb);
649e6ad7673SIyappan Subramanian }
650e6ad7673SIyappan Subramanian
xgene_gmac_rx_enable(struct xgene_enet_pdata * pdata)651d0eb7458SIyappan Subramanian static void xgene_gmac_rx_enable(struct xgene_enet_pdata *pdata)
652e6ad7673SIyappan Subramanian {
653e6ad7673SIyappan Subramanian u32 data;
654e6ad7673SIyappan Subramanian
655ae1aed95SIyappan Subramanian data = xgene_enet_rd_mac(pdata, MAC_CONFIG_1_ADDR);
656ae1aed95SIyappan Subramanian xgene_enet_wr_mac(pdata, MAC_CONFIG_1_ADDR, data | RX_EN);
657e6ad7673SIyappan Subramanian }
658e6ad7673SIyappan Subramanian
xgene_gmac_tx_enable(struct xgene_enet_pdata * pdata)659d0eb7458SIyappan Subramanian static void xgene_gmac_tx_enable(struct xgene_enet_pdata *pdata)
660e6ad7673SIyappan Subramanian {
661e6ad7673SIyappan Subramanian u32 data;
662e6ad7673SIyappan Subramanian
663ae1aed95SIyappan Subramanian data = xgene_enet_rd_mac(pdata, MAC_CONFIG_1_ADDR);
664ae1aed95SIyappan Subramanian xgene_enet_wr_mac(pdata, MAC_CONFIG_1_ADDR, data | TX_EN);
665e6ad7673SIyappan Subramanian }
666e6ad7673SIyappan Subramanian
xgene_gmac_rx_disable(struct xgene_enet_pdata * pdata)667d0eb7458SIyappan Subramanian static void xgene_gmac_rx_disable(struct xgene_enet_pdata *pdata)
668e6ad7673SIyappan Subramanian {
669e6ad7673SIyappan Subramanian u32 data;
670e6ad7673SIyappan Subramanian
671ae1aed95SIyappan Subramanian data = xgene_enet_rd_mac(pdata, MAC_CONFIG_1_ADDR);
672ae1aed95SIyappan Subramanian xgene_enet_wr_mac(pdata, MAC_CONFIG_1_ADDR, data & ~RX_EN);
673e6ad7673SIyappan Subramanian }
674e6ad7673SIyappan Subramanian
xgene_gmac_tx_disable(struct xgene_enet_pdata * pdata)675d0eb7458SIyappan Subramanian static void xgene_gmac_tx_disable(struct xgene_enet_pdata *pdata)
676e6ad7673SIyappan Subramanian {
677e6ad7673SIyappan Subramanian u32 data;
678e6ad7673SIyappan Subramanian
679ae1aed95SIyappan Subramanian data = xgene_enet_rd_mac(pdata, MAC_CONFIG_1_ADDR);
680ae1aed95SIyappan Subramanian xgene_enet_wr_mac(pdata, MAC_CONFIG_1_ADDR, data & ~TX_EN);
681e6ad7673SIyappan Subramanian }
682e6ad7673SIyappan Subramanian
xgene_ring_mgr_init(struct xgene_enet_pdata * p)683c3f4465dSIyappan Subramanian bool xgene_ring_mgr_init(struct xgene_enet_pdata *p)
684c3f4465dSIyappan Subramanian {
685c3f4465dSIyappan Subramanian if (!ioread32(p->ring_csr_addr + CLKEN_ADDR))
686c3f4465dSIyappan Subramanian return false;
687c3f4465dSIyappan Subramanian
688c3f4465dSIyappan Subramanian if (ioread32(p->ring_csr_addr + SRST_ADDR))
689c3f4465dSIyappan Subramanian return false;
690c3f4465dSIyappan Subramanian
691c3f4465dSIyappan Subramanian return true;
692c3f4465dSIyappan Subramanian }
693c3f4465dSIyappan Subramanian
xgene_enet_reset(struct xgene_enet_pdata * pdata)694c3f4465dSIyappan Subramanian static int xgene_enet_reset(struct xgene_enet_pdata *pdata)
695e6ad7673SIyappan Subramanian {
696bc61167aSIyappan Subramanian struct device *dev = &pdata->pdev->dev;
697e6ad7673SIyappan Subramanian
698c3f4465dSIyappan Subramanian if (!xgene_ring_mgr_init(pdata))
699c3f4465dSIyappan Subramanian return -ENODEV;
700c3f4465dSIyappan Subramanian
7018089a96fSIyappan Subramanian if (pdata->mdio_driver) {
7028089a96fSIyappan Subramanian xgene_enet_config_ring_if_assoc(pdata);
7038089a96fSIyappan Subramanian return 0;
7048089a96fSIyappan Subramanian }
7058089a96fSIyappan Subramanian
706bc61167aSIyappan Subramanian if (dev->of_node) {
707e6ad7673SIyappan Subramanian clk_prepare_enable(pdata->clk);
708bc61167aSIyappan Subramanian udelay(5);
709e6ad7673SIyappan Subramanian clk_disable_unprepare(pdata->clk);
710bc61167aSIyappan Subramanian udelay(5);
711e6ad7673SIyappan Subramanian clk_prepare_enable(pdata->clk);
712bc61167aSIyappan Subramanian udelay(5);
713bc61167aSIyappan Subramanian } else {
714bc61167aSIyappan Subramanian #ifdef CONFIG_ACPI
71585d2c5cdSNathan Chancellor acpi_status status;
71685d2c5cdSNathan Chancellor
717570d785bSKelsey Skunberg status = acpi_evaluate_object(ACPI_HANDLE(&pdata->pdev->dev),
718bc61167aSIyappan Subramanian "_RST", NULL, NULL);
719570d785bSKelsey Skunberg if (ACPI_FAILURE(status)) {
720bc61167aSIyappan Subramanian acpi_evaluate_object(ACPI_HANDLE(&pdata->pdev->dev),
721bc61167aSIyappan Subramanian "_INI", NULL, NULL);
722de7b5b3dSFeng Kan }
723bc61167aSIyappan Subramanian #endif
724bc61167aSIyappan Subramanian }
725e6ad7673SIyappan Subramanian
726bc61167aSIyappan Subramanian xgene_enet_ecc_init(pdata);
727bc61167aSIyappan Subramanian xgene_enet_config_ring_if_assoc(pdata);
728c3f4465dSIyappan Subramanian
729c3f4465dSIyappan Subramanian return 0;
730e6ad7673SIyappan Subramanian }
731e6ad7673SIyappan Subramanian
xgene_enet_clear(struct xgene_enet_pdata * pdata,struct xgene_enet_desc_ring * ring)732cb11c062SIyappan Subramanian static void xgene_enet_clear(struct xgene_enet_pdata *pdata,
733cb11c062SIyappan Subramanian struct xgene_enet_desc_ring *ring)
734cb11c062SIyappan Subramanian {
7352c839337SIyappan Subramanian u32 addr, data;
736cb11c062SIyappan Subramanian
737cb11c062SIyappan Subramanian if (xgene_enet_is_bufpool(ring->id)) {
738cb11c062SIyappan Subramanian addr = ENET_CFGSSQMIFPRESET_ADDR;
7392c839337SIyappan Subramanian data = BIT(xgene_enet_get_fpsel(ring->id));
740cb11c062SIyappan Subramanian } else {
741cb11c062SIyappan Subramanian addr = ENET_CFGSSQMIWQRESET_ADDR;
7422c839337SIyappan Subramanian data = BIT(xgene_enet_ring_bufnum(ring->id));
743cb11c062SIyappan Subramanian }
744cb11c062SIyappan Subramanian
745cb11c062SIyappan Subramanian xgene_enet_wr_ring_if(pdata, addr, data);
746cb11c062SIyappan Subramanian }
747cb11c062SIyappan Subramanian
xgene_gport_shutdown(struct xgene_enet_pdata * pdata)748d0eb7458SIyappan Subramanian static void xgene_gport_shutdown(struct xgene_enet_pdata *pdata)
749e6ad7673SIyappan Subramanian {
750bc61167aSIyappan Subramanian struct device *dev = &pdata->pdev->dev;
751cb11c062SIyappan Subramanian
752bc61167aSIyappan Subramanian if (dev->of_node) {
753c2d33bdcSSuman Tripathi if (!IS_ERR(pdata->clk))
754e6ad7673SIyappan Subramanian clk_disable_unprepare(pdata->clk);
755e6ad7673SIyappan Subramanian }
756bc61167aSIyappan Subramanian }
757e6ad7673SIyappan Subramanian
xgene_enet_flowctrl_cfg(struct net_device * ndev)75856090b12SIyappan Subramanian static u32 xgene_enet_flowctrl_cfg(struct net_device *ndev)
75956090b12SIyappan Subramanian {
76056090b12SIyappan Subramanian struct xgene_enet_pdata *pdata = netdev_priv(ndev);
76156090b12SIyappan Subramanian struct phy_device *phydev = ndev->phydev;
76256090b12SIyappan Subramanian u16 lcladv, rmtadv = 0;
76356090b12SIyappan Subramanian u32 rx_pause, tx_pause;
76456090b12SIyappan Subramanian u8 flowctl = 0;
76556090b12SIyappan Subramanian
76656090b12SIyappan Subramanian if (!phydev->duplex || !pdata->pause_autoneg)
76756090b12SIyappan Subramanian return 0;
76856090b12SIyappan Subramanian
76956090b12SIyappan Subramanian if (pdata->tx_pause)
77056090b12SIyappan Subramanian flowctl |= FLOW_CTRL_TX;
77156090b12SIyappan Subramanian
77256090b12SIyappan Subramanian if (pdata->rx_pause)
77356090b12SIyappan Subramanian flowctl |= FLOW_CTRL_RX;
77456090b12SIyappan Subramanian
77556090b12SIyappan Subramanian lcladv = mii_advertise_flowctrl(flowctl);
77656090b12SIyappan Subramanian
77756090b12SIyappan Subramanian if (phydev->pause)
77856090b12SIyappan Subramanian rmtadv = LPA_PAUSE_CAP;
77956090b12SIyappan Subramanian
78056090b12SIyappan Subramanian if (phydev->asym_pause)
78156090b12SIyappan Subramanian rmtadv |= LPA_PAUSE_ASYM;
78256090b12SIyappan Subramanian
78356090b12SIyappan Subramanian flowctl = mii_resolve_flowctrl_fdx(lcladv, rmtadv);
78456090b12SIyappan Subramanian tx_pause = !!(flowctl & FLOW_CTRL_TX);
78556090b12SIyappan Subramanian rx_pause = !!(flowctl & FLOW_CTRL_RX);
78656090b12SIyappan Subramanian
78756090b12SIyappan Subramanian if (tx_pause != pdata->tx_pause) {
78856090b12SIyappan Subramanian pdata->tx_pause = tx_pause;
78956090b12SIyappan Subramanian pdata->mac_ops->flowctl_tx(pdata, pdata->tx_pause);
79056090b12SIyappan Subramanian }
79156090b12SIyappan Subramanian
79256090b12SIyappan Subramanian if (rx_pause != pdata->rx_pause) {
79356090b12SIyappan Subramanian pdata->rx_pause = rx_pause;
79456090b12SIyappan Subramanian pdata->mac_ops->flowctl_rx(pdata, pdata->rx_pause);
79556090b12SIyappan Subramanian }
79656090b12SIyappan Subramanian
79756090b12SIyappan Subramanian return 0;
79856090b12SIyappan Subramanian }
79956090b12SIyappan Subramanian
xgene_enet_adjust_link(struct net_device * ndev)800e6ad7673SIyappan Subramanian static void xgene_enet_adjust_link(struct net_device *ndev)
801e6ad7673SIyappan Subramanian {
802e6ad7673SIyappan Subramanian struct xgene_enet_pdata *pdata = netdev_priv(ndev);
8039a8c5ddeSIyappan Subramanian const struct xgene_mac_ops *mac_ops = pdata->mac_ops;
804971d3a44SPhilippe Reynes struct phy_device *phydev = ndev->phydev;
805e6ad7673SIyappan Subramanian
806e6ad7673SIyappan Subramanian if (phydev->link) {
807e6ad7673SIyappan Subramanian if (pdata->phy_speed != phydev->speed) {
808d0eb7458SIyappan Subramanian pdata->phy_speed = phydev->speed;
8099a8c5ddeSIyappan Subramanian mac_ops->set_speed(pdata);
81047c62b6dSIyappan Subramanian mac_ops->rx_enable(pdata);
81147c62b6dSIyappan Subramanian mac_ops->tx_enable(pdata);
812e6ad7673SIyappan Subramanian phy_print_status(phydev);
813e6ad7673SIyappan Subramanian }
81456090b12SIyappan Subramanian
81556090b12SIyappan Subramanian xgene_enet_flowctrl_cfg(ndev);
816e6ad7673SIyappan Subramanian } else {
81747c62b6dSIyappan Subramanian mac_ops->rx_disable(pdata);
81847c62b6dSIyappan Subramanian mac_ops->tx_disable(pdata);
819e6ad7673SIyappan Subramanian pdata->phy_speed = SPEED_UNKNOWN;
820e6ad7673SIyappan Subramanian phy_print_status(phydev);
821e6ad7673SIyappan Subramanian }
822e6ad7673SIyappan Subramanian }
823e6ad7673SIyappan Subramanian
8248089a96fSIyappan Subramanian #ifdef CONFIG_ACPI
acpi_phy_find_device(struct device * dev)8258089a96fSIyappan Subramanian static struct acpi_device *acpi_phy_find_device(struct device *dev)
8268089a96fSIyappan Subramanian {
827977d5ad3SSakari Ailus struct fwnode_reference_args args;
8288089a96fSIyappan Subramanian struct fwnode_handle *fw_node;
8298089a96fSIyappan Subramanian int status;
8308089a96fSIyappan Subramanian
8318089a96fSIyappan Subramanian fw_node = acpi_fwnode_handle(ACPI_COMPANION(dev));
8328089a96fSIyappan Subramanian status = acpi_node_get_property_reference(fw_node, "phy-handle", 0,
8338089a96fSIyappan Subramanian &args);
834977d5ad3SSakari Ailus if (ACPI_FAILURE(status) || !is_acpi_device_node(args.fwnode)) {
8358089a96fSIyappan Subramanian dev_dbg(dev, "No matching phy in ACPI table\n");
8368089a96fSIyappan Subramanian return NULL;
8378089a96fSIyappan Subramanian }
8388089a96fSIyappan Subramanian
839977d5ad3SSakari Ailus return to_acpi_device_node(args.fwnode);
8408089a96fSIyappan Subramanian }
8418089a96fSIyappan Subramanian #endif
8428089a96fSIyappan Subramanian
xgene_enet_phy_connect(struct net_device * ndev)8438089a96fSIyappan Subramanian int xgene_enet_phy_connect(struct net_device *ndev)
844e6ad7673SIyappan Subramanian {
845e6ad7673SIyappan Subramanian struct xgene_enet_pdata *pdata = netdev_priv(ndev);
8468089a96fSIyappan Subramanian struct device_node *np;
847e6ad7673SIyappan Subramanian struct phy_device *phy_dev;
848e6ad7673SIyappan Subramanian struct device *dev = &pdata->pdev->dev;
8498089a96fSIyappan Subramanian int i;
850e6ad7673SIyappan Subramanian
851de7b5b3dSFeng Kan if (dev->of_node) {
8528089a96fSIyappan Subramanian for (i = 0 ; i < 2; i++) {
8538089a96fSIyappan Subramanian np = of_parse_phandle(dev->of_node, "phy-handle", i);
85403377e38SIyappan Subramanian phy_dev = of_phy_connect(ndev, np,
85503377e38SIyappan Subramanian &xgene_enet_adjust_link,
85603377e38SIyappan Subramanian 0, pdata->phy_mode);
85703377e38SIyappan Subramanian of_node_put(np);
85803377e38SIyappan Subramanian if (phy_dev)
8598089a96fSIyappan Subramanian break;
8608089a96fSIyappan Subramanian }
8618089a96fSIyappan Subramanian
86204d53b20SRussell King if (!phy_dev) {
86304d53b20SRussell King netdev_err(ndev, "Could not connect to PHY\n");
86404d53b20SRussell King return -ENODEV;
865de7b5b3dSFeng Kan }
86604d53b20SRussell King } else {
8678089a96fSIyappan Subramanian #ifdef CONFIG_ACPI
86836232012SDavid S. Miller struct acpi_device *adev = acpi_phy_find_device(dev);
8698089a96fSIyappan Subramanian if (adev)
870971d3a44SPhilippe Reynes phy_dev = adev->driver_data;
871971d3a44SPhilippe Reynes else
872971d3a44SPhilippe Reynes phy_dev = NULL;
873de7b5b3dSFeng Kan
874de7b5b3dSFeng Kan if (!phy_dev ||
875de7b5b3dSFeng Kan phy_connect_direct(ndev, phy_dev, &xgene_enet_adjust_link,
876de7b5b3dSFeng Kan pdata->phy_mode)) {
877e6ad7673SIyappan Subramanian netdev_err(ndev, "Could not connect to PHY\n");
878e6ad7673SIyappan Subramanian return -ENODEV;
879e6ad7673SIyappan Subramanian }
880ea966cb6SArnd Bergmann #else
881ea966cb6SArnd Bergmann return -ENODEV;
8828089a96fSIyappan Subramanian #endif
88304d53b20SRussell King }
884e6ad7673SIyappan Subramanian
885e6ad7673SIyappan Subramanian pdata->phy_speed = SPEED_UNKNOWN;
88641124fa6SAndrew Lunn phy_remove_link_mode(phy_dev, ETHTOOL_LINK_MODE_10baseT_Half_BIT);
88741124fa6SAndrew Lunn phy_remove_link_mode(phy_dev, ETHTOOL_LINK_MODE_100baseT_Half_BIT);
88841124fa6SAndrew Lunn phy_remove_link_mode(phy_dev, ETHTOOL_LINK_MODE_1000baseT_Half_BIT);
889af8d9bb2SAndrew Lunn phy_support_asym_pause(phy_dev);
890e6ad7673SIyappan Subramanian
891e6ad7673SIyappan Subramanian return 0;
892e6ad7673SIyappan Subramanian }
893e6ad7673SIyappan Subramanian
xgene_mdiobus_register(struct xgene_enet_pdata * pdata,struct mii_bus * mdio)894de7b5b3dSFeng Kan static int xgene_mdiobus_register(struct xgene_enet_pdata *pdata,
895de7b5b3dSFeng Kan struct mii_bus *mdio)
896e6ad7673SIyappan Subramanian {
897e6ad7673SIyappan Subramanian struct device *dev = &pdata->pdev->dev;
898de7b5b3dSFeng Kan struct net_device *ndev = pdata->ndev;
899de7b5b3dSFeng Kan struct phy_device *phy;
900e6ad7673SIyappan Subramanian struct device_node *child_np;
901e6ad7673SIyappan Subramanian struct device_node *mdio_np = NULL;
9028c151963SIyappan Subramanian u32 phy_addr;
903e6ad7673SIyappan Subramanian int ret;
904e6ad7673SIyappan Subramanian
905de7b5b3dSFeng Kan if (dev->of_node) {
906e6ad7673SIyappan Subramanian for_each_child_of_node(dev->of_node, child_np) {
907de7b5b3dSFeng Kan if (of_device_is_compatible(child_np,
908de7b5b3dSFeng Kan "apm,xgene-mdio")) {
909e6ad7673SIyappan Subramanian mdio_np = child_np;
910e6ad7673SIyappan Subramanian break;
911e6ad7673SIyappan Subramanian }
912e6ad7673SIyappan Subramanian }
913e6ad7673SIyappan Subramanian
914e6ad7673SIyappan Subramanian if (!mdio_np) {
915e6ad7673SIyappan Subramanian netdev_dbg(ndev, "No mdio node in the dts\n");
916e6ad7673SIyappan Subramanian return -ENXIO;
917e6ad7673SIyappan Subramanian }
918e6ad7673SIyappan Subramanian
919de7b5b3dSFeng Kan return of_mdiobus_register(mdio, mdio_np);
920de7b5b3dSFeng Kan }
921de7b5b3dSFeng Kan
922de7b5b3dSFeng Kan /* Mask out all PHYs from auto probing. */
923de7b5b3dSFeng Kan mdio->phy_mask = ~0;
924de7b5b3dSFeng Kan
925de7b5b3dSFeng Kan /* Register the MDIO bus */
926de7b5b3dSFeng Kan ret = mdiobus_register(mdio);
927de7b5b3dSFeng Kan if (ret)
928de7b5b3dSFeng Kan return ret;
929de7b5b3dSFeng Kan
9308c151963SIyappan Subramanian ret = device_property_read_u32(dev, "phy-channel", &phy_addr);
931de7b5b3dSFeng Kan if (ret)
9328c151963SIyappan Subramanian ret = device_property_read_u32(dev, "phy-addr", &phy_addr);
933de7b5b3dSFeng Kan if (ret)
934de7b5b3dSFeng Kan return -EINVAL;
935de7b5b3dSFeng Kan
9368c151963SIyappan Subramanian phy = xgene_enet_phy_register(mdio, phy_addr);
9378c151963SIyappan Subramanian if (!phy)
938de7b5b3dSFeng Kan return -EIO;
939de7b5b3dSFeng Kan
940de7b5b3dSFeng Kan return ret;
941de7b5b3dSFeng Kan }
942de7b5b3dSFeng Kan
xgene_enet_mdio_config(struct xgene_enet_pdata * pdata)943de7b5b3dSFeng Kan int xgene_enet_mdio_config(struct xgene_enet_pdata *pdata)
944de7b5b3dSFeng Kan {
945de7b5b3dSFeng Kan struct net_device *ndev = pdata->ndev;
946de7b5b3dSFeng Kan struct mii_bus *mdio_bus;
947de7b5b3dSFeng Kan int ret;
948de7b5b3dSFeng Kan
949e6ad7673SIyappan Subramanian mdio_bus = mdiobus_alloc();
950e6ad7673SIyappan Subramanian if (!mdio_bus)
951e6ad7673SIyappan Subramanian return -ENOMEM;
952e6ad7673SIyappan Subramanian
953e6ad7673SIyappan Subramanian mdio_bus->name = "APM X-Gene MDIO bus";
9548c151963SIyappan Subramanian mdio_bus->read = xgene_mdio_rgmii_read;
9558c151963SIyappan Subramanian mdio_bus->write = xgene_mdio_rgmii_write;
956e6ad7673SIyappan Subramanian snprintf(mdio_bus->id, MII_BUS_ID_SIZE, "%s-%s", "xgene-mii",
957e6ad7673SIyappan Subramanian ndev->name);
958e6ad7673SIyappan Subramanian
9598c151963SIyappan Subramanian mdio_bus->priv = (void __force *)pdata->mcx_mac_addr;
960cb0366b7SIyappan Subramanian mdio_bus->parent = &pdata->pdev->dev;
961e6ad7673SIyappan Subramanian
962de7b5b3dSFeng Kan ret = xgene_mdiobus_register(pdata, mdio_bus);
963e6ad7673SIyappan Subramanian if (ret) {
964e6ad7673SIyappan Subramanian netdev_err(ndev, "Failed to register MDIO bus\n");
965e6ad7673SIyappan Subramanian mdiobus_free(mdio_bus);
966e6ad7673SIyappan Subramanian return ret;
967e6ad7673SIyappan Subramanian }
968e6ad7673SIyappan Subramanian pdata->mdio_bus = mdio_bus;
969e6ad7673SIyappan Subramanian
970e6ad7673SIyappan Subramanian ret = xgene_enet_phy_connect(ndev);
971e6ad7673SIyappan Subramanian if (ret)
972e6ad7673SIyappan Subramanian xgene_enet_mdio_remove(pdata);
973e6ad7673SIyappan Subramanian
974e6ad7673SIyappan Subramanian return ret;
975e6ad7673SIyappan Subramanian }
976e6ad7673SIyappan Subramanian
xgene_enet_phy_disconnect(struct xgene_enet_pdata * pdata)9778089a96fSIyappan Subramanian void xgene_enet_phy_disconnect(struct xgene_enet_pdata *pdata)
9788089a96fSIyappan Subramanian {
979971d3a44SPhilippe Reynes struct net_device *ndev = pdata->ndev;
980971d3a44SPhilippe Reynes
981971d3a44SPhilippe Reynes if (ndev->phydev)
982971d3a44SPhilippe Reynes phy_disconnect(ndev->phydev);
9838089a96fSIyappan Subramanian }
9848089a96fSIyappan Subramanian
xgene_enet_mdio_remove(struct xgene_enet_pdata * pdata)985e6ad7673SIyappan Subramanian void xgene_enet_mdio_remove(struct xgene_enet_pdata *pdata)
986e6ad7673SIyappan Subramanian {
987971d3a44SPhilippe Reynes struct net_device *ndev = pdata->ndev;
988971d3a44SPhilippe Reynes
989971d3a44SPhilippe Reynes if (ndev->phydev)
990971d3a44SPhilippe Reynes phy_disconnect(ndev->phydev);
991ccc02ddbSIyappan Subramanian
992e6ad7673SIyappan Subramanian mdiobus_unregister(pdata->mdio_bus);
993e6ad7673SIyappan Subramanian mdiobus_free(pdata->mdio_bus);
994e6ad7673SIyappan Subramanian pdata->mdio_bus = NULL;
995e6ad7673SIyappan Subramanian }
996d0eb7458SIyappan Subramanian
9973cdb7309SJulia Lawall const struct xgene_mac_ops xgene_gmac_ops = {
998d0eb7458SIyappan Subramanian .init = xgene_gmac_init,
999d0eb7458SIyappan Subramanian .reset = xgene_gmac_reset,
1000d0eb7458SIyappan Subramanian .rx_enable = xgene_gmac_rx_enable,
1001d0eb7458SIyappan Subramanian .tx_enable = xgene_gmac_tx_enable,
1002d0eb7458SIyappan Subramanian .rx_disable = xgene_gmac_rx_disable,
1003d0eb7458SIyappan Subramanian .tx_disable = xgene_gmac_tx_disable,
1004ca6d550cSIyappan Subramanian .get_drop_cnt = xgene_gmac_get_drop_cnt,
10059a8c5ddeSIyappan Subramanian .set_speed = xgene_gmac_set_speed,
1006d0eb7458SIyappan Subramanian .set_mac_addr = xgene_gmac_set_mac_addr,
1007350b4e33SIyappan Subramanian .set_framesize = xgene_enet_set_frame_size,
1008bb64fa09SIyappan Subramanian .enable_tx_pause = xgene_gmac_enable_tx_pause,
1009bb64fa09SIyappan Subramanian .flowctl_tx = xgene_gmac_flowctl_tx,
1010bb64fa09SIyappan Subramanian .flowctl_rx = xgene_gmac_flowctl_rx,
1011d0eb7458SIyappan Subramanian };
1012d0eb7458SIyappan Subramanian
10133cdb7309SJulia Lawall const struct xgene_port_ops xgene_gport_ops = {
1014d0eb7458SIyappan Subramanian .reset = xgene_enet_reset,
1015cb11c062SIyappan Subramanian .clear = xgene_enet_clear,
1016d0eb7458SIyappan Subramanian .cle_bypass = xgene_enet_cle_bypass,
1017d0eb7458SIyappan Subramanian .shutdown = xgene_gport_shutdown,
1018d0eb7458SIyappan Subramanian };
101981cefb81SIyappan Subramanian
102081cefb81SIyappan Subramanian struct xgene_ring_ops xgene_ring1_ops = {
102181cefb81SIyappan Subramanian .num_ring_config = NUM_RING_CONFIG,
102281cefb81SIyappan Subramanian .num_ring_id_shift = 6,
102381cefb81SIyappan Subramanian .setup = xgene_enet_setup_ring,
102481cefb81SIyappan Subramanian .clear = xgene_enet_clear_ring,
102581cefb81SIyappan Subramanian .wr_cmd = xgene_enet_wr_cmd,
102681cefb81SIyappan Subramanian .len = xgene_enet_ring_len,
102781cefb81SIyappan Subramanian };
1028