xref: /dpdk/drivers/common/cnxk/roc_bphy_cgx.c (revision 6169517c111e5fefb9bb22458191e6c402d2ae9c)
10399ff9dSTomasz Duszynski /* SPDX-License-Identifier: BSD-3-Clause
20399ff9dSTomasz Duszynski  * Copyright(C) 2021 Marvell.
30399ff9dSTomasz Duszynski  */
40399ff9dSTomasz Duszynski 
5857721d6STomasz Duszynski #include <pthread.h>
60399ff9dSTomasz Duszynski 
7857721d6STomasz Duszynski #include "roc_api.h"
8857721d6STomasz Duszynski #include "roc_priv.h"
9857721d6STomasz Duszynski 
102c19694cSTomasz Duszynski #define CGX_CMRX_CONFIG		       0x00
112c19694cSTomasz Duszynski #define CGX_CMRX_CONFIG_DATA_PKT_RX_EN BIT_ULL(54)
122c19694cSTomasz Duszynski #define CGX_CMRX_CONFIG_DATA_PKT_TX_EN BIT_ULL(53)
13857721d6STomasz Duszynski #define CGX_CMRX_INT		       0x40
14857721d6STomasz Duszynski #define CGX_CMRX_INT_OVERFLW	       BIT_ULL(1)
150399ff9dSTomasz Duszynski /*
160399ff9dSTomasz Duszynski  * CN10K stores number of lmacs in 4 bit filed
177be78d02SJosh Soref  * in contrary to CN9K which uses only 3 bits.
180399ff9dSTomasz Duszynski  *
190399ff9dSTomasz Duszynski  * In theory masks should differ yet on CN9K
200399ff9dSTomasz Duszynski  * bits beyond specified range contain zeros.
210399ff9dSTomasz Duszynski  *
220399ff9dSTomasz Duszynski  * Hence common longer mask may be used.
230399ff9dSTomasz Duszynski  */
240399ff9dSTomasz Duszynski #define CGX_CMRX_RX_LMACS                     0x128
250399ff9dSTomasz Duszynski #define CGX_CMRX_RX_LMACS_LMACS               GENMASK_ULL(3, 0)
26857721d6STomasz Duszynski #define CGX_CMRX_SCRATCH0                     0x1050
27857721d6STomasz Duszynski #define CGX_CMRX_SCRATCH1                     0x1058
288d3ba6bfSTomasz Duszynski #define CGX_MTI_MAC100X_COMMAND_CONFIG        0x8010
298d3ba6bfSTomasz Duszynski #define CGX_MTI_MAC100X_COMMAND_CONFIG_RX_ENA BIT_ULL(1)
308d3ba6bfSTomasz Duszynski #define CGX_MTI_MAC100X_COMMAND_CONFIG_TX_ENA BIT_ULL(0)
310399ff9dSTomasz Duszynski 
320399ff9dSTomasz Duszynski static uint64_t
330399ff9dSTomasz Duszynski roc_bphy_cgx_read(struct roc_bphy_cgx *roc_cgx, uint64_t lmac, uint64_t offset)
340399ff9dSTomasz Duszynski {
350399ff9dSTomasz Duszynski 	int shift = roc_model_is_cn10k() ? 20 : 18;
360399ff9dSTomasz Duszynski 	uint64_t base = (uint64_t)roc_cgx->bar0_va;
370399ff9dSTomasz Duszynski 
380399ff9dSTomasz Duszynski 	return plt_read64(base + (lmac << shift) + offset);
390399ff9dSTomasz Duszynski }
400399ff9dSTomasz Duszynski 
41857721d6STomasz Duszynski static void
42857721d6STomasz Duszynski roc_bphy_cgx_write(struct roc_bphy_cgx *roc_cgx, uint64_t lmac, uint64_t offset,
43857721d6STomasz Duszynski 		   uint64_t value)
44857721d6STomasz Duszynski {
45857721d6STomasz Duszynski 	int shift = roc_model_is_cn10k() ? 20 : 18;
46857721d6STomasz Duszynski 	uint64_t base = (uint64_t)roc_cgx->bar0_va;
47857721d6STomasz Duszynski 
48857721d6STomasz Duszynski 	plt_write64(value, base + (lmac << shift) + offset);
49857721d6STomasz Duszynski }
50857721d6STomasz Duszynski 
51857721d6STomasz Duszynski static void
52857721d6STomasz Duszynski roc_bphy_cgx_ack(struct roc_bphy_cgx *roc_cgx, unsigned int lmac,
53857721d6STomasz Duszynski 		 uint64_t *scr0)
54857721d6STomasz Duszynski {
55857721d6STomasz Duszynski 	uint64_t val;
56857721d6STomasz Duszynski 
57857721d6STomasz Duszynski 	/* clear interrupt */
58857721d6STomasz Duszynski 	val = roc_bphy_cgx_read(roc_cgx, lmac, CGX_CMRX_INT);
59857721d6STomasz Duszynski 	val |= FIELD_PREP(CGX_CMRX_INT_OVERFLW, 1);
60857721d6STomasz Duszynski 	roc_bphy_cgx_write(roc_cgx, lmac, CGX_CMRX_INT, val);
61857721d6STomasz Duszynski 
62857721d6STomasz Duszynski 	/* ack fw response */
63857721d6STomasz Duszynski 	*scr0 &= ~SCR0_ETH_EVT_STS_S_ACK;
64857721d6STomasz Duszynski 	roc_bphy_cgx_write(roc_cgx, lmac, CGX_CMRX_SCRATCH0, *scr0);
65857721d6STomasz Duszynski }
66857721d6STomasz Duszynski 
67857721d6STomasz Duszynski static int
68857721d6STomasz Duszynski roc_bphy_cgx_wait_for_ownership(struct roc_bphy_cgx *roc_cgx, unsigned int lmac,
69857721d6STomasz Duszynski 				uint64_t *scr0)
70857721d6STomasz Duszynski {
71857721d6STomasz Duszynski 	int tries = 5000;
72857721d6STomasz Duszynski 	uint64_t scr1;
73857721d6STomasz Duszynski 
74857721d6STomasz Duszynski 	do {
75857721d6STomasz Duszynski 		*scr0 = roc_bphy_cgx_read(roc_cgx, lmac, CGX_CMRX_SCRATCH0);
76857721d6STomasz Duszynski 		scr1 = roc_bphy_cgx_read(roc_cgx, lmac, CGX_CMRX_SCRATCH1);
77857721d6STomasz Duszynski 
78857721d6STomasz Duszynski 		if (FIELD_GET(SCR1_OWN_STATUS, scr1) == ETH_OWN_NON_SECURE_SW &&
79857721d6STomasz Duszynski 		    FIELD_GET(SCR0_ETH_EVT_STS_S_ACK, *scr0) == 0)
80857721d6STomasz Duszynski 			break;
81857721d6STomasz Duszynski 
82857721d6STomasz Duszynski 		/* clear async events if any */
83857721d6STomasz Duszynski 		if (FIELD_GET(SCR0_ETH_EVT_STS_S_EVT_TYPE, *scr0) ==
84857721d6STomasz Duszynski 		    ETH_EVT_ASYNC &&
85857721d6STomasz Duszynski 		    FIELD_GET(SCR0_ETH_EVT_STS_S_ACK, *scr0))
86857721d6STomasz Duszynski 			roc_bphy_cgx_ack(roc_cgx, lmac, scr0);
87857721d6STomasz Duszynski 
88857721d6STomasz Duszynski 		plt_delay_ms(1);
89857721d6STomasz Duszynski 	} while (--tries);
90857721d6STomasz Duszynski 
91857721d6STomasz Duszynski 	return tries ? 0 : -ETIMEDOUT;
92857721d6STomasz Duszynski }
93857721d6STomasz Duszynski 
94857721d6STomasz Duszynski static int
95857721d6STomasz Duszynski roc_bphy_cgx_wait_for_ack(struct roc_bphy_cgx *roc_cgx, unsigned int lmac,
96857721d6STomasz Duszynski 			  uint64_t *scr0)
97857721d6STomasz Duszynski {
98857721d6STomasz Duszynski 	int tries = 5000;
99857721d6STomasz Duszynski 	uint64_t scr1;
100857721d6STomasz Duszynski 
101857721d6STomasz Duszynski 	do {
102857721d6STomasz Duszynski 		*scr0 = roc_bphy_cgx_read(roc_cgx, lmac, CGX_CMRX_SCRATCH0);
103857721d6STomasz Duszynski 		scr1 = roc_bphy_cgx_read(roc_cgx, lmac, CGX_CMRX_SCRATCH1);
104857721d6STomasz Duszynski 
105857721d6STomasz Duszynski 		if (FIELD_GET(SCR1_OWN_STATUS, scr1) == ETH_OWN_NON_SECURE_SW &&
106857721d6STomasz Duszynski 		    FIELD_GET(SCR0_ETH_EVT_STS_S_ACK, *scr0))
107857721d6STomasz Duszynski 			break;
108857721d6STomasz Duszynski 
109857721d6STomasz Duszynski 		plt_delay_ms(1);
110857721d6STomasz Duszynski 	} while (--tries);
111857721d6STomasz Duszynski 
112857721d6STomasz Duszynski 	return tries ? 0 : -ETIMEDOUT;
113857721d6STomasz Duszynski }
114857721d6STomasz Duszynski 
1151fa00451STomasz Duszynski static int
116857721d6STomasz Duszynski roc_bphy_cgx_intf_req(struct roc_bphy_cgx *roc_cgx, unsigned int lmac,
117857721d6STomasz Duszynski 		      uint64_t scr1, uint64_t *scr0)
118857721d6STomasz Duszynski {
119857721d6STomasz Duszynski 	uint8_t cmd_id = FIELD_GET(SCR1_ETH_CMD_ID, scr1);
120857721d6STomasz Duszynski 	int ret;
121857721d6STomasz Duszynski 
122857721d6STomasz Duszynski 	pthread_mutex_lock(&roc_cgx->lock);
123857721d6STomasz Duszynski 
124857721d6STomasz Duszynski 	/* wait for ownership */
125857721d6STomasz Duszynski 	ret = roc_bphy_cgx_wait_for_ownership(roc_cgx, lmac, scr0);
126857721d6STomasz Duszynski 	if (ret) {
127857721d6STomasz Duszynski 		plt_err("timed out waiting for ownership");
128857721d6STomasz Duszynski 		goto out;
129857721d6STomasz Duszynski 	}
130857721d6STomasz Duszynski 
131857721d6STomasz Duszynski 	/* write command */
132857721d6STomasz Duszynski 	scr1 |= FIELD_PREP(SCR1_OWN_STATUS, ETH_OWN_FIRMWARE);
133857721d6STomasz Duszynski 	roc_bphy_cgx_write(roc_cgx, lmac, CGX_CMRX_SCRATCH1, scr1);
134857721d6STomasz Duszynski 
135857721d6STomasz Duszynski 	/* wait for command ack */
136857721d6STomasz Duszynski 	ret = roc_bphy_cgx_wait_for_ack(roc_cgx, lmac, scr0);
137857721d6STomasz Duszynski 	if (ret) {
138857721d6STomasz Duszynski 		plt_err("timed out waiting for response");
139857721d6STomasz Duszynski 		goto out;
140857721d6STomasz Duszynski 	}
141857721d6STomasz Duszynski 
142857721d6STomasz Duszynski 	if (cmd_id == ETH_CMD_INTF_SHUTDOWN)
143857721d6STomasz Duszynski 		goto out;
144857721d6STomasz Duszynski 
145857721d6STomasz Duszynski 	if (FIELD_GET(SCR0_ETH_EVT_STS_S_EVT_TYPE, *scr0) != ETH_EVT_CMD_RESP) {
146857721d6STomasz Duszynski 		plt_err("received async event instead of cmd resp event");
147857721d6STomasz Duszynski 		ret = -EIO;
148857721d6STomasz Duszynski 		goto out;
149857721d6STomasz Duszynski 	}
150857721d6STomasz Duszynski 
151857721d6STomasz Duszynski 	if (FIELD_GET(SCR0_ETH_EVT_STS_S_ID, *scr0) != cmd_id) {
152857721d6STomasz Duszynski 		plt_err("received resp for cmd %d expected for cmd %d",
153857721d6STomasz Duszynski 			(int)FIELD_GET(SCR0_ETH_EVT_STS_S_ID, *scr0), cmd_id);
154857721d6STomasz Duszynski 		ret = -EIO;
155857721d6STomasz Duszynski 		goto out;
156857721d6STomasz Duszynski 	}
157857721d6STomasz Duszynski 
158857721d6STomasz Duszynski 	if (FIELD_GET(SCR0_ETH_EVT_STS_S_STAT, *scr0) != ETH_STAT_SUCCESS) {
159857721d6STomasz Duszynski 		plt_err("cmd %d failed on cgx%u lmac%u with errcode %d", cmd_id,
160857721d6STomasz Duszynski 			roc_cgx->id, lmac,
161857721d6STomasz Duszynski 			(int)FIELD_GET(SCR0_ETH_LNK_STS_S_ERR_TYPE, *scr0));
162857721d6STomasz Duszynski 		ret = -EIO;
163857721d6STomasz Duszynski 	}
164857721d6STomasz Duszynski 
165857721d6STomasz Duszynski out:
166857721d6STomasz Duszynski 	roc_bphy_cgx_ack(roc_cgx, lmac, scr0);
167857721d6STomasz Duszynski 
168857721d6STomasz Duszynski 	pthread_mutex_unlock(&roc_cgx->lock);
169857721d6STomasz Duszynski 
170857721d6STomasz Duszynski 	return ret;
171857721d6STomasz Duszynski }
172857721d6STomasz Duszynski 
1730399ff9dSTomasz Duszynski static unsigned int
1740399ff9dSTomasz Duszynski roc_bphy_cgx_dev_id(struct roc_bphy_cgx *roc_cgx)
1750399ff9dSTomasz Duszynski {
17681388ad1STomasz Duszynski 	uint64_t cgx_id;
17781388ad1STomasz Duszynski 
17881388ad1STomasz Duszynski 	if (roc_model_is_cnf10kb())
17981388ad1STomasz Duszynski 		cgx_id = GENMASK_ULL(27, 24);
18081388ad1STomasz Duszynski 	else if (roc_model_is_cn10k())
18181388ad1STomasz Duszynski 		cgx_id = GENMASK_ULL(26, 24);
18281388ad1STomasz Duszynski 	else
18381388ad1STomasz Duszynski 		cgx_id = GENMASK_ULL(25, 24);
1840399ff9dSTomasz Duszynski 
1850399ff9dSTomasz Duszynski 	return FIELD_GET(cgx_id, roc_cgx->bar0_pa);
1860399ff9dSTomasz Duszynski }
1870399ff9dSTomasz Duszynski 
1880399ff9dSTomasz Duszynski int
1890399ff9dSTomasz Duszynski roc_bphy_cgx_dev_init(struct roc_bphy_cgx *roc_cgx)
1900399ff9dSTomasz Duszynski {
1910399ff9dSTomasz Duszynski 	uint64_t val;
1920399ff9dSTomasz Duszynski 
1930399ff9dSTomasz Duszynski 	if (!roc_cgx || !roc_cgx->bar0_va || !roc_cgx->bar0_pa)
1940399ff9dSTomasz Duszynski 		return -EINVAL;
1950399ff9dSTomasz Duszynski 
196*6169517cSAriel Otilibili 	pthread_mutex_init(&roc_cgx->lock, NULL);
197857721d6STomasz Duszynski 
1980399ff9dSTomasz Duszynski 	val = roc_bphy_cgx_read(roc_cgx, 0, CGX_CMRX_RX_LMACS);
1990399ff9dSTomasz Duszynski 	val = FIELD_GET(CGX_CMRX_RX_LMACS_LMACS, val);
2000399ff9dSTomasz Duszynski 	if (roc_model_is_cn9k())
2010399ff9dSTomasz Duszynski 		val = GENMASK_ULL(val - 1, 0);
2020399ff9dSTomasz Duszynski 	roc_cgx->lmac_bmap = val;
2030399ff9dSTomasz Duszynski 	roc_cgx->id = roc_bphy_cgx_dev_id(roc_cgx);
2040399ff9dSTomasz Duszynski 
2050399ff9dSTomasz Duszynski 	return 0;
2060399ff9dSTomasz Duszynski }
2070399ff9dSTomasz Duszynski 
2080399ff9dSTomasz Duszynski int
2090399ff9dSTomasz Duszynski roc_bphy_cgx_dev_fini(struct roc_bphy_cgx *roc_cgx)
2100399ff9dSTomasz Duszynski {
2110399ff9dSTomasz Duszynski 	if (!roc_cgx)
2120399ff9dSTomasz Duszynski 		return -EINVAL;
2130399ff9dSTomasz Duszynski 
214857721d6STomasz Duszynski 	pthread_mutex_destroy(&roc_cgx->lock);
215857721d6STomasz Duszynski 
2160399ff9dSTomasz Duszynski 	return 0;
2170399ff9dSTomasz Duszynski }
2181fa00451STomasz Duszynski 
2191fa00451STomasz Duszynski static bool
2201fa00451STomasz Duszynski roc_bphy_cgx_lmac_exists(struct roc_bphy_cgx *roc_cgx, unsigned int lmac)
2211fa00451STomasz Duszynski {
2221fa00451STomasz Duszynski 	return (lmac < MAX_LMACS_PER_CGX) &&
2231fa00451STomasz Duszynski 	       (roc_cgx->lmac_bmap & BIT_ULL(lmac));
2241fa00451STomasz Duszynski }
2251fa00451STomasz Duszynski 
2266c870ee8STomasz Duszynski static int
2272c19694cSTomasz Duszynski roc_bphy_cgx_start_stop_rxtx(struct roc_bphy_cgx *roc_cgx, unsigned int lmac,
2282c19694cSTomasz Duszynski 			     bool start)
2292c19694cSTomasz Duszynski {
2308d3ba6bfSTomasz Duszynski 	uint64_t val, reg, rx_field, tx_field;
2312c19694cSTomasz Duszynski 
2322c19694cSTomasz Duszynski 	if (!roc_cgx)
2332c19694cSTomasz Duszynski 		return -EINVAL;
2342c19694cSTomasz Duszynski 
2352c19694cSTomasz Duszynski 	if (!roc_bphy_cgx_lmac_exists(roc_cgx, lmac))
2362c19694cSTomasz Duszynski 		return -ENODEV;
2372c19694cSTomasz Duszynski 
2388d3ba6bfSTomasz Duszynski 	if (roc_model_is_cnf10kb()) {
2398d3ba6bfSTomasz Duszynski 		reg = CGX_MTI_MAC100X_COMMAND_CONFIG;
2408d3ba6bfSTomasz Duszynski 		rx_field = CGX_MTI_MAC100X_COMMAND_CONFIG_RX_ENA;
2418d3ba6bfSTomasz Duszynski 		tx_field = CGX_MTI_MAC100X_COMMAND_CONFIG_TX_ENA;
2428d3ba6bfSTomasz Duszynski 	} else {
2438d3ba6bfSTomasz Duszynski 		reg = CGX_CMRX_CONFIG;
2448d3ba6bfSTomasz Duszynski 		rx_field = CGX_CMRX_CONFIG_DATA_PKT_RX_EN;
2458d3ba6bfSTomasz Duszynski 		tx_field = CGX_CMRX_CONFIG_DATA_PKT_TX_EN;
2468d3ba6bfSTomasz Duszynski 	}
2478d3ba6bfSTomasz Duszynski 
2482c19694cSTomasz Duszynski 	pthread_mutex_lock(&roc_cgx->lock);
2498d3ba6bfSTomasz Duszynski 	val = roc_bphy_cgx_read(roc_cgx, lmac, reg);
2508d3ba6bfSTomasz Duszynski 	val &= ~(rx_field | tx_field);
2512c19694cSTomasz Duszynski 
2522c19694cSTomasz Duszynski 	if (start)
2538d3ba6bfSTomasz Duszynski 		val |= FIELD_PREP(rx_field, 1) | FIELD_PREP(tx_field, 1);
2542c19694cSTomasz Duszynski 
2558d3ba6bfSTomasz Duszynski 	roc_bphy_cgx_write(roc_cgx, lmac, reg, val);
2562c19694cSTomasz Duszynski 	pthread_mutex_unlock(&roc_cgx->lock);
2572c19694cSTomasz Duszynski 
2582c19694cSTomasz Duszynski 	return 0;
2592c19694cSTomasz Duszynski }
2602c19694cSTomasz Duszynski 
2612c19694cSTomasz Duszynski static int
2626c870ee8STomasz Duszynski roc_bphy_cgx_intlbk_ena_dis(struct roc_bphy_cgx *roc_cgx, unsigned int lmac,
2636c870ee8STomasz Duszynski 			    bool enable)
2646c870ee8STomasz Duszynski {
2656c870ee8STomasz Duszynski 	uint64_t scr1, scr0;
2666c870ee8STomasz Duszynski 
2676c870ee8STomasz Duszynski 	if (!roc_cgx)
2686c870ee8STomasz Duszynski 		return -EINVAL;
2696c870ee8STomasz Duszynski 
2706c870ee8STomasz Duszynski 	if (!roc_bphy_cgx_lmac_exists(roc_cgx, lmac))
2716c870ee8STomasz Duszynski 		return -ENODEV;
2726c870ee8STomasz Duszynski 
2736c870ee8STomasz Duszynski 	scr1 = FIELD_PREP(SCR1_ETH_CMD_ID, ETH_CMD_INTERNAL_LBK) |
2746c870ee8STomasz Duszynski 	       FIELD_PREP(SCR1_ETH_CTL_ARGS_ENABLE, enable);
2756c870ee8STomasz Duszynski 
2766c870ee8STomasz Duszynski 	return roc_bphy_cgx_intf_req(roc_cgx, lmac, scr1, &scr0);
2776c870ee8STomasz Duszynski }
2786c870ee8STomasz Duszynski 
27972096a47STomasz Duszynski static int
28072096a47STomasz Duszynski roc_bphy_cgx_ptp_rx_ena_dis(struct roc_bphy_cgx *roc_cgx, unsigned int lmac,
28172096a47STomasz Duszynski 			    bool enable)
28272096a47STomasz Duszynski {
28372096a47STomasz Duszynski 	uint64_t scr1, scr0;
28472096a47STomasz Duszynski 
28572096a47STomasz Duszynski 	if (!roc_cgx)
28672096a47STomasz Duszynski 		return -EINVAL;
28772096a47STomasz Duszynski 
28872096a47STomasz Duszynski 	if (!roc_bphy_cgx_lmac_exists(roc_cgx, lmac))
28972096a47STomasz Duszynski 		return -ENODEV;
29072096a47STomasz Duszynski 
29172096a47STomasz Duszynski 	scr1 = FIELD_PREP(SCR1_ETH_CMD_ID, ETH_CMD_SET_PTP_MODE) |
29272096a47STomasz Duszynski 	       FIELD_PREP(SCR1_ETH_CTL_ARGS_ENABLE, enable);
29372096a47STomasz Duszynski 
29472096a47STomasz Duszynski 	return roc_bphy_cgx_intf_req(roc_cgx, lmac, scr1, &scr0);
29572096a47STomasz Duszynski }
29672096a47STomasz Duszynski 
2971fa00451STomasz Duszynski int
2982c19694cSTomasz Duszynski roc_bphy_cgx_start_rxtx(struct roc_bphy_cgx *roc_cgx, unsigned int lmac)
2992c19694cSTomasz Duszynski {
3002c19694cSTomasz Duszynski 	return roc_bphy_cgx_start_stop_rxtx(roc_cgx, lmac, true);
3012c19694cSTomasz Duszynski }
3022c19694cSTomasz Duszynski 
3032c19694cSTomasz Duszynski int
3042c19694cSTomasz Duszynski roc_bphy_cgx_stop_rxtx(struct roc_bphy_cgx *roc_cgx, unsigned int lmac)
3052c19694cSTomasz Duszynski {
3062c19694cSTomasz Duszynski 	return roc_bphy_cgx_start_stop_rxtx(roc_cgx, lmac, false);
3072c19694cSTomasz Duszynski }
3082c19694cSTomasz Duszynski 
3092c19694cSTomasz Duszynski int
3107fb5075aSTomasz Duszynski roc_bphy_cgx_set_link_state(struct roc_bphy_cgx *roc_cgx, unsigned int lmac,
3116576ef65STomasz Duszynski 			    struct roc_bphy_cgx_link_state *state)
3127fb5075aSTomasz Duszynski {
3137fb5075aSTomasz Duszynski 	uint64_t scr1, scr0;
3147fb5075aSTomasz Duszynski 
3157fb5075aSTomasz Duszynski 	if (!roc_cgx)
3167fb5075aSTomasz Duszynski 		return -EINVAL;
3177fb5075aSTomasz Duszynski 
3187fb5075aSTomasz Duszynski 	if (!roc_bphy_cgx_lmac_exists(roc_cgx, lmac))
3197fb5075aSTomasz Duszynski 		return -ENODEV;
3207fb5075aSTomasz Duszynski 
3216576ef65STomasz Duszynski 	if (!state)
3226576ef65STomasz Duszynski 		return -EINVAL;
3236576ef65STomasz Duszynski 
3246576ef65STomasz Duszynski 	scr1 = (state->state ? FIELD_PREP(SCR1_ETH_CMD_ID, ETH_CMD_LINK_BRING_UP) :
3256576ef65STomasz Duszynski 			       FIELD_PREP(SCR1_ETH_CMD_ID, ETH_CMD_LINK_BRING_DOWN)) |
3266576ef65STomasz Duszynski 	       FIELD_PREP(SCR1_CGX_LINK_BRINGUP_ARGS_TIMEOUT, state->timeout) |
3276576ef65STomasz Duszynski 	       FIELD_PREP(SCR1_CGX_LINK_BRINGUP_ARGS_RX_TX_DIS, state->rx_tx_dis);
3287fb5075aSTomasz Duszynski 
3297fb5075aSTomasz Duszynski 	return roc_bphy_cgx_intf_req(roc_cgx, lmac, scr1, &scr0);
3307fb5075aSTomasz Duszynski }
3317fb5075aSTomasz Duszynski 
3327fb5075aSTomasz Duszynski int
3331fa00451STomasz Duszynski roc_bphy_cgx_get_linkinfo(struct roc_bphy_cgx *roc_cgx, unsigned int lmac,
3341fa00451STomasz Duszynski 			  struct roc_bphy_cgx_link_info *info)
3351fa00451STomasz Duszynski {
3361fa00451STomasz Duszynski 	uint64_t scr1, scr0;
3371fa00451STomasz Duszynski 	int ret;
3381fa00451STomasz Duszynski 
3391fa00451STomasz Duszynski 	if (!roc_cgx)
3401fa00451STomasz Duszynski 		return -EINVAL;
3411fa00451STomasz Duszynski 
3421fa00451STomasz Duszynski 	if (!roc_bphy_cgx_lmac_exists(roc_cgx, lmac))
3431fa00451STomasz Duszynski 		return -ENODEV;
3441fa00451STomasz Duszynski 
3451fa00451STomasz Duszynski 	if (!info)
3461fa00451STomasz Duszynski 		return -EINVAL;
3471fa00451STomasz Duszynski 
3481fa00451STomasz Duszynski 	scr1 = FIELD_PREP(SCR1_ETH_CMD_ID, ETH_CMD_GET_LINK_STS);
3491fa00451STomasz Duszynski 	ret = roc_bphy_cgx_intf_req(roc_cgx, lmac, scr1, &scr0);
3501fa00451STomasz Duszynski 	if (ret)
3511fa00451STomasz Duszynski 		return ret;
3521fa00451STomasz Duszynski 
3531fa00451STomasz Duszynski 	info->link_up = FIELD_GET(SCR0_ETH_LNK_STS_S_LINK_UP, scr0);
3541fa00451STomasz Duszynski 	info->full_duplex = FIELD_GET(SCR0_ETH_LNK_STS_S_FULL_DUPLEX, scr0);
3551fa00451STomasz Duszynski 	info->speed = FIELD_GET(SCR0_ETH_LNK_STS_S_SPEED, scr0);
3561fa00451STomasz Duszynski 	info->an = FIELD_GET(SCR0_ETH_LNK_STS_S_AN, scr0);
3571fa00451STomasz Duszynski 	info->fec = FIELD_GET(SCR0_ETH_LNK_STS_S_FEC, scr0);
3581fa00451STomasz Duszynski 	info->mode = FIELD_GET(SCR0_ETH_LNK_STS_S_MODE, scr0);
3591fa00451STomasz Duszynski 
3601fa00451STomasz Duszynski 	return 0;
3611fa00451STomasz Duszynski }
3626c870ee8STomasz Duszynski 
3636c870ee8STomasz Duszynski int
364ba901d33STomasz Duszynski roc_bphy_cgx_set_link_mode(struct roc_bphy_cgx *roc_cgx, unsigned int lmac,
365ba901d33STomasz Duszynski 			   struct roc_bphy_cgx_link_mode *mode)
366ba901d33STomasz Duszynski {
367ba901d33STomasz Duszynski 	uint64_t scr1, scr0;
368ba901d33STomasz Duszynski 
369bd2fd34aSTomasz Duszynski 	if (roc_model_is_cn9k() &&
370bd2fd34aSTomasz Duszynski 	    (mode->use_portm_idx || mode->portm_idx || mode->mode_group_idx)) {
371ba901d33STomasz Duszynski 		return -ENOTSUP;
372bd2fd34aSTomasz Duszynski 	}
373ba901d33STomasz Duszynski 
374ba901d33STomasz Duszynski 	if (!roc_cgx)
375ba901d33STomasz Duszynski 		return -EINVAL;
376ba901d33STomasz Duszynski 
377ba901d33STomasz Duszynski 	if (!roc_bphy_cgx_lmac_exists(roc_cgx, lmac))
378ba901d33STomasz Duszynski 		return -ENODEV;
379ba901d33STomasz Duszynski 
380ba901d33STomasz Duszynski 	if (!mode)
381ba901d33STomasz Duszynski 		return -EINVAL;
382ba901d33STomasz Duszynski 
383ba901d33STomasz Duszynski 	scr1 = FIELD_PREP(SCR1_ETH_CMD_ID, ETH_CMD_MODE_CHANGE) |
384ba901d33STomasz Duszynski 	       FIELD_PREP(SCR1_ETH_MODE_CHANGE_ARGS_SPEED, mode->speed) |
385ba901d33STomasz Duszynski 	       FIELD_PREP(SCR1_ETH_MODE_CHANGE_ARGS_DUPLEX, mode->full_duplex) |
386ba901d33STomasz Duszynski 	       FIELD_PREP(SCR1_ETH_MODE_CHANGE_ARGS_AN, mode->an) |
387bd2fd34aSTomasz Duszynski 	       FIELD_PREP(SCR1_ETH_MODE_CHANGE_ARGS_USE_PORTM_IDX,
388bd2fd34aSTomasz Duszynski 			  mode->use_portm_idx) |
389bd2fd34aSTomasz Duszynski 	       FIELD_PREP(SCR1_ETH_MODE_CHANGE_ARGS_PORTM_IDX,
390bd2fd34aSTomasz Duszynski 			  mode->portm_idx) |
391bd2fd34aSTomasz Duszynski 	       FIELD_PREP(SCR1_ETH_MODE_CHANGE_ARGS_MODE_GROUP_IDX,
392bd2fd34aSTomasz Duszynski 			  mode->mode_group_idx) |
393ba901d33STomasz Duszynski 	       FIELD_PREP(SCR1_ETH_MODE_CHANGE_ARGS_MODE, BIT_ULL(mode->mode));
394ba901d33STomasz Duszynski 
395ba901d33STomasz Duszynski 	return roc_bphy_cgx_intf_req(roc_cgx, lmac, scr1, &scr0);
396ba901d33STomasz Duszynski }
397ba901d33STomasz Duszynski 
398ba901d33STomasz Duszynski int
3996c870ee8STomasz Duszynski roc_bphy_cgx_intlbk_enable(struct roc_bphy_cgx *roc_cgx, unsigned int lmac)
4006c870ee8STomasz Duszynski {
4016c870ee8STomasz Duszynski 	return roc_bphy_cgx_intlbk_ena_dis(roc_cgx, lmac, true);
4026c870ee8STomasz Duszynski }
4036c870ee8STomasz Duszynski 
4046c870ee8STomasz Duszynski int
4056c870ee8STomasz Duszynski roc_bphy_cgx_intlbk_disable(struct roc_bphy_cgx *roc_cgx, unsigned int lmac)
4066c870ee8STomasz Duszynski {
4076c870ee8STomasz Duszynski 	return roc_bphy_cgx_intlbk_ena_dis(roc_cgx, lmac, false);
4086c870ee8STomasz Duszynski }
40972096a47STomasz Duszynski 
41072096a47STomasz Duszynski int
41172096a47STomasz Duszynski roc_bphy_cgx_ptp_rx_enable(struct roc_bphy_cgx *roc_cgx, unsigned int lmac)
41272096a47STomasz Duszynski {
41372096a47STomasz Duszynski 	return roc_bphy_cgx_ptp_rx_ena_dis(roc_cgx, lmac, true);
41472096a47STomasz Duszynski }
41572096a47STomasz Duszynski 
41672096a47STomasz Duszynski int
41772096a47STomasz Duszynski roc_bphy_cgx_ptp_rx_disable(struct roc_bphy_cgx *roc_cgx, unsigned int lmac)
41872096a47STomasz Duszynski {
41972096a47STomasz Duszynski 	return roc_bphy_cgx_ptp_rx_ena_dis(roc_cgx, lmac, false);
42072096a47STomasz Duszynski }
4217ab475a0STomasz Duszynski 
4227ab475a0STomasz Duszynski int
42359cdf690STomasz Duszynski roc_bphy_cgx_fec_set(struct roc_bphy_cgx *roc_cgx, unsigned int lmac,
42459cdf690STomasz Duszynski 		     enum roc_bphy_cgx_eth_link_fec fec)
42559cdf690STomasz Duszynski {
42659cdf690STomasz Duszynski 	uint64_t scr1, scr0;
42759cdf690STomasz Duszynski 
42859cdf690STomasz Duszynski 	if (!roc_cgx)
42959cdf690STomasz Duszynski 		return -EINVAL;
43059cdf690STomasz Duszynski 
43159cdf690STomasz Duszynski 	if (!roc_bphy_cgx_lmac_exists(roc_cgx, lmac))
432b816b6f4STomasz Duszynski 		return -ENODEV;
43359cdf690STomasz Duszynski 
43459cdf690STomasz Duszynski 	scr1 = FIELD_PREP(SCR1_ETH_CMD_ID, ETH_CMD_SET_FEC) |
43559cdf690STomasz Duszynski 	       FIELD_PREP(SCR1_ETH_SET_FEC_ARGS, fec);
43659cdf690STomasz Duszynski 
43759cdf690STomasz Duszynski 	return roc_bphy_cgx_intf_req(roc_cgx, lmac, scr1, &scr0);
43859cdf690STomasz Duszynski }
43959cdf690STomasz Duszynski 
44059cdf690STomasz Duszynski int
4417ab475a0STomasz Duszynski roc_bphy_cgx_fec_supported_get(struct roc_bphy_cgx *roc_cgx, unsigned int lmac,
4427ab475a0STomasz Duszynski 			       enum roc_bphy_cgx_eth_link_fec *fec)
4437ab475a0STomasz Duszynski {
4447ab475a0STomasz Duszynski 	uint64_t scr1, scr0;
4457ab475a0STomasz Duszynski 	int ret;
4467ab475a0STomasz Duszynski 
4477ab475a0STomasz Duszynski 	if (!roc_cgx || !fec)
4487ab475a0STomasz Duszynski 		return -EINVAL;
4497ab475a0STomasz Duszynski 
4507ab475a0STomasz Duszynski 	if (!roc_bphy_cgx_lmac_exists(roc_cgx, lmac))
451b816b6f4STomasz Duszynski 		return -ENODEV;
4527ab475a0STomasz Duszynski 
4537ab475a0STomasz Duszynski 	scr1 = FIELD_PREP(SCR1_ETH_CMD_ID, ETH_CMD_GET_SUPPORTED_FEC);
4547ab475a0STomasz Duszynski 
4557ab475a0STomasz Duszynski 	ret = roc_bphy_cgx_intf_req(roc_cgx, lmac, scr1, &scr0);
4567ab475a0STomasz Duszynski 	if (ret)
4577ab475a0STomasz Duszynski 		return ret;
4587ab475a0STomasz Duszynski 
4597ab475a0STomasz Duszynski 	scr0 = FIELD_GET(SCR0_ETH_FEC_TYPES_S_FEC, scr0);
4607ab475a0STomasz Duszynski 	*fec = (enum roc_bphy_cgx_eth_link_fec)scr0;
4617ab475a0STomasz Duszynski 
4627ab475a0STomasz Duszynski 	return 0;
4637ab475a0STomasz Duszynski }
4647af3e7aaSTomasz Duszynski 
4657af3e7aaSTomasz Duszynski int
4667af3e7aaSTomasz Duszynski roc_bphy_cgx_cpri_mode_change(struct roc_bphy_cgx *roc_cgx, unsigned int lmac,
4677af3e7aaSTomasz Duszynski 			      struct roc_bphy_cgx_cpri_mode_change *mode)
4687af3e7aaSTomasz Duszynski {
4697af3e7aaSTomasz Duszynski 	uint64_t scr1, scr0;
4707af3e7aaSTomasz Duszynski 
4717af3e7aaSTomasz Duszynski 	if (!(roc_model_is_cnf95xxn_a0() ||
4727af3e7aaSTomasz Duszynski 	      roc_model_is_cnf95xxn_a1() ||
4737af3e7aaSTomasz Duszynski 	      roc_model_is_cnf95xxn_b0()))
4747af3e7aaSTomasz Duszynski 		return -ENOTSUP;
4757af3e7aaSTomasz Duszynski 
4767af3e7aaSTomasz Duszynski 	if (!roc_cgx)
4777af3e7aaSTomasz Duszynski 		return -EINVAL;
4787af3e7aaSTomasz Duszynski 
4797af3e7aaSTomasz Duszynski 	if (!roc_bphy_cgx_lmac_exists(roc_cgx, lmac))
4807af3e7aaSTomasz Duszynski 		return -ENODEV;
4817af3e7aaSTomasz Duszynski 
4827af3e7aaSTomasz Duszynski 	if (!mode)
4837af3e7aaSTomasz Duszynski 		return -EINVAL;
4847af3e7aaSTomasz Duszynski 
4857af3e7aaSTomasz Duszynski 	scr1 = FIELD_PREP(SCR1_ETH_CMD_ID, ETH_CMD_CPRI_MODE_CHANGE) |
4867af3e7aaSTomasz Duszynski 	       FIELD_PREP(SCR1_CPRI_MODE_CHANGE_ARGS_GSERC_IDX,
4877af3e7aaSTomasz Duszynski 			  mode->gserc_idx) |
4887af3e7aaSTomasz Duszynski 	       FIELD_PREP(SCR1_CPRI_MODE_CHANGE_ARGS_LANE_IDX, mode->lane_idx) |
4897af3e7aaSTomasz Duszynski 	       FIELD_PREP(SCR1_CPRI_MODE_CHANGE_ARGS_RATE, mode->rate) |
4907af3e7aaSTomasz Duszynski 	       FIELD_PREP(SCR1_CPRI_MODE_CHANGE_ARGS_DISABLE_LEQ,
4917af3e7aaSTomasz Duszynski 			  mode->disable_leq) |
4927af3e7aaSTomasz Duszynski 	       FIELD_PREP(SCR1_CPRI_MODE_CHANGE_ARGS_DISABLE_DFE,
4937af3e7aaSTomasz Duszynski 			  mode->disable_dfe);
4947af3e7aaSTomasz Duszynski 
4957af3e7aaSTomasz Duszynski 	return roc_bphy_cgx_intf_req(roc_cgx, lmac, scr1, &scr0);
4967af3e7aaSTomasz Duszynski }
497283c9175STomasz Duszynski 
498283c9175STomasz Duszynski int
499283c9175STomasz Duszynski roc_bphy_cgx_cpri_mode_tx_control(struct roc_bphy_cgx *roc_cgx,
500283c9175STomasz Duszynski 				  unsigned int lmac,
501283c9175STomasz Duszynski 				  struct roc_bphy_cgx_cpri_mode_tx_ctrl *mode)
502283c9175STomasz Duszynski {
503283c9175STomasz Duszynski 	uint64_t scr1, scr0;
504283c9175STomasz Duszynski 
505283c9175STomasz Duszynski 	if (!(roc_model_is_cnf95xxn_a0() ||
506283c9175STomasz Duszynski 	      roc_model_is_cnf95xxn_a1() ||
507283c9175STomasz Duszynski 	      roc_model_is_cnf95xxn_b0()))
508283c9175STomasz Duszynski 		return -ENOTSUP;
509283c9175STomasz Duszynski 
510283c9175STomasz Duszynski 	if (!roc_cgx)
511283c9175STomasz Duszynski 		return -EINVAL;
512283c9175STomasz Duszynski 
513283c9175STomasz Duszynski 	if (!roc_bphy_cgx_lmac_exists(roc_cgx, lmac))
514283c9175STomasz Duszynski 		return -ENODEV;
515283c9175STomasz Duszynski 
516283c9175STomasz Duszynski 	if (!mode)
517283c9175STomasz Duszynski 		return -EINVAL;
518283c9175STomasz Duszynski 
519283c9175STomasz Duszynski 	scr1 = FIELD_PREP(SCR1_ETH_CMD_ID, ETH_CMD_CPRI_TX_CONTROL) |
520283c9175STomasz Duszynski 	       FIELD_PREP(SCR1_CPRI_MODE_TX_CTRL_ARGS_GSERC_IDX,
521283c9175STomasz Duszynski 			  mode->gserc_idx) |
522283c9175STomasz Duszynski 	       FIELD_PREP(SCR1_CPRI_MODE_TX_CTRL_ARGS_LANE_IDX,
523283c9175STomasz Duszynski 			  mode->lane_idx) |
524283c9175STomasz Duszynski 	       FIELD_PREP(SCR1_CPRI_MODE_TX_CTRL_ARGS_ENABLE, mode->enable);
525283c9175STomasz Duszynski 
526283c9175STomasz Duszynski 	return roc_bphy_cgx_intf_req(roc_cgx, lmac, scr1, &scr0);
527283c9175STomasz Duszynski }
528888123a6STomasz Duszynski 
529888123a6STomasz Duszynski int
530888123a6STomasz Duszynski roc_bphy_cgx_cpri_mode_misc(struct roc_bphy_cgx *roc_cgx, unsigned int lmac,
531888123a6STomasz Duszynski 			    struct roc_bphy_cgx_cpri_mode_misc *mode)
532888123a6STomasz Duszynski {
533888123a6STomasz Duszynski 	uint64_t scr1, scr0;
534888123a6STomasz Duszynski 
535888123a6STomasz Duszynski 	if (!(roc_model_is_cnf95xxn_a0() ||
536888123a6STomasz Duszynski 	      roc_model_is_cnf95xxn_a1() ||
537888123a6STomasz Duszynski 	      roc_model_is_cnf95xxn_b0()))
538888123a6STomasz Duszynski 		return -ENOTSUP;
539888123a6STomasz Duszynski 
540888123a6STomasz Duszynski 	if (!roc_cgx)
541888123a6STomasz Duszynski 		return -EINVAL;
542888123a6STomasz Duszynski 
543888123a6STomasz Duszynski 	if (!roc_bphy_cgx_lmac_exists(roc_cgx, lmac))
544888123a6STomasz Duszynski 		return -ENODEV;
545888123a6STomasz Duszynski 
546888123a6STomasz Duszynski 	if (!mode)
547888123a6STomasz Duszynski 		return -EINVAL;
548888123a6STomasz Duszynski 
549888123a6STomasz Duszynski 	scr1 = FIELD_PREP(SCR1_ETH_CMD_ID, ETH_CMD_CPRI_MISC) |
550888123a6STomasz Duszynski 	       FIELD_PREP(SCR1_CPRI_MODE_MISC_ARGS_GSERC_IDX,
551888123a6STomasz Duszynski 			  mode->gserc_idx) |
552888123a6STomasz Duszynski 	       FIELD_PREP(SCR1_CPRI_MODE_MISC_ARGS_LANE_IDX,
553888123a6STomasz Duszynski 			  mode->lane_idx) |
554888123a6STomasz Duszynski 	       FIELD_PREP(SCR1_CPRI_MODE_MISC_ARGS_FLAGS, mode->flags);
555888123a6STomasz Duszynski 
556888123a6STomasz Duszynski 	return roc_bphy_cgx_intf_req(roc_cgx, lmac, scr1, &scr0);
557888123a6STomasz Duszynski }
558