xref: /openbmc/linux/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c (revision 03ab8e6297acd1bc0eedaa050e2a1635c576fd11)
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