1/*
2 **************************************************************************
3 * Copyright (c) 2014-2015, The Linux Foundation. All rights reserved.
4 *
5 * Permission to use, copy, modify, and/or distribute this software for
6 * any purpose with or without fee is hereby granted, provided that the
7 * above copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
15 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 **************************************************************************
17 */
18/*
19 * @file
20 * This file defines the APIs for accessing global NSS GMAC
21 * software interface register space.
22 * ------------------------REVISION HISTORY-----------------------------
23 * Qualcomm Atheros         01/Mar/2013              Created
24 */
25
26#include <linux/module.h>
27#include <linux/types.h>
28#include <linux/kernel.h>
29#include <linux/notifier.h>
30
31#include <nss_gmac_dev.h>
32#include <nss_gmac_clocks.h>
33#include <nss_gmac_network_interface.h>
34
35#ifndef CONFIG_OF
36#include <mach/msm_nss_gmac.h>
37#include <mach/msm_nss_macsec.h>
38#include <mach/socinfo.h>
39#else
40#include <linux/of.h>
41#include <msm_nss_gmac.h>
42#include <msm_nss_macsec.h>
43
44#define SOCINFO_VERSION_MAJOR(ver) (ver)
45#endif
46
47/* Initialize notifier list for NSS GMAC */
48static BLOCKING_NOTIFIER_HEAD(nss_gmac_notifier_list);
49
50#ifdef RUMI_EMULATION_SUPPORT
51/**
52 * @brief Emulation specific initialization.
53 *
54 * @param[in] nss_gmac_dev *
55 * @return void
56 */
57void nss_gmac_spare_ctl(struct nss_gmac_dev *gmacdev)
58{
59	uint32_t val;
60	uint32_t count;
61	uint32_t id = gmacdev->macid;
62	uint32_t *nss_base = (uint32_t *)(gmacdev->ctx->nss_base);
63
64	val = 1 << id;
65	nss_gmac_set_reg_bits(nss_base, NSS_ETH_SPARE_CTL, val);
66
67	val = nss_gmac_read_reg(nss_base, NSS_ETH_SPARE_CTL);
68	netdev_dbg(gmacdev->netdev, "NSS_ETH_SPARE_CTL - 0x%x\n", val);
69
70	val = 1 << id;
71	nss_gmac_clear_reg_bits(nss_base, NSS_ETH_SPARE_CTL, val);
72
73	val = nss_gmac_read_reg(nss_base, NSS_ETH_SPARE_CTL);
74	netdev_dbg(gmacdev->netdev,
75		      "NSS_ETH_SPARE_CTL - 0x%x after clear for gmac %d\n", val,
76		      id);
77
78	val = nss_gmac_read_reg(nss_base, NSS_ETH_SPARE_STAT);
79	netdev_dbg(gmacdev->netdev,
80		      "NSS_ETH_SPARE_STAT - 0x%x; gmac %d spare ctl reset...\n",
81		      val, id);
82	count = 0;
83	while ((val & (1 << id)) != (1 << id)) {
84		usleep_range(10000, 12000);
85		val = nss_gmac_read_reg(nss_base,
86					NSS_ETH_SPARE_STAT);
87		if (count++ > 20) {
88			netdev_dbg(gmacdev->netdev,
89				      "!!!!!! Timeout waiting for NSS_ETH_SPARE_STAT bit to set.\n");
90			break;
91		}
92	}
93}
94
95
96/**
97 * @brief QSGMII Init for Emulation
98 *
99 * @param[in] nss_gmac_dev *
100 * @return void
101 */
102static void nss_gmac_rumi_qsgmii_init(struct nss_gmac_dev *gmacdev)
103{
104	struct nss_gmac_dev *gmac1_dev;
105	uint16_t phy_reg_val;
106	uint32_t *qsgmii_base;
107	uint8_t *nss_base;
108
109	netdev_dbg(gmacdev->netdev, "%s:\n", __func__);
110
111	gmac1_dev = gmacdev->ctx->nss_gmac[1];
112	qsgmii_base = gmacdev->ctx->qsgmii_base;
113	nss_base = (uint8_t *)(gmacdev->ctx->nss_base);
114
115	/*
116	 * _SGMII: Set only bit 3, with no polling for reset completion
117	 * inside status register for GMAC2
118	 */
119	netdev_dbg(gmacdev->netdev, "Eth2: spare_ctl_reg value before setting = 0x%x\n",
120	      nss_gmac_read_reg((uint32_t *)nss_base, NSS_ETH_SPARE_CTL));
121	nss_gmac_set_reg_bits((uint32_t *)nss_base, NSS_ETH_SPARE_CTL, 0x8);
122	netdev_dbg(gmacdev->netdev, "Eth2: spare_ctl_reg value after setting = 0x%x\n",
123	      nss_gmac_read_reg((uint32_t *)nss_base, NSS_ETH_SPARE_CTL));
124
125	netdev_dbg(gmac1_dev->netdev, "%s: GMAC1's MACBASE = 0x%p\n", __func__,
126							gmac1_dev->mac_base);
127
128	/* Put PHY in SGMII Mode */
129	nss_gmac_write_reg(qsgmii_base, QSGMII_PHY_MODE_CTL, 0x0);
130
131	/* Set SERDES signal detects for channel2, bypass SDO */
132	nss_gmac_write_reg(qsgmii_base, PCS_QSGMII_CTL, 0x4213B);
133
134	/* SERDES Configuration, drive strength settings through GMAC1's MDIO */
135
136	/* Configure SERDES to SGMII-1+SGMII-2 mode */
137	nss_gmac_mii_wr_reg(gmac1_dev, 0x0, 0x1, 0x8241);
138	nss_gmac_mii_wr_reg(gmac1_dev, 0x0, 0x3, 0xB909);
139
140	/* Writes to SERDES registers using MDIO debug registers */
141	nss_gmac_mii_wr_reg(gmac1_dev, 0x0, 0x1D, 0x10);
142	phy_reg_val = nss_gmac_mii_rd_reg(gmac1_dev, 0x0, 0x1E);
143
144	nss_gmac_mii_wr_reg(gmac1_dev, 0x0, 0x1D, 0x10);
145	nss_gmac_mii_wr_reg(gmac1_dev, 0x0, 0x1E, 0x2000);
146	nss_gmac_mii_wr_reg(gmac1_dev, 0x0, 0x1D, 0x10);
147	nss_gmac_mii_wr_reg(gmac1_dev, 0x0, 0x1E, 0x0);
148	nss_gmac_mii_wr_reg(gmac1_dev, 0x0, 0x1D, 0x10);
149
150	phy_reg_val = nss_gmac_mii_rd_reg(gmac1_dev, 0x0, 0x1E);
151
152	nss_gmac_mii_wr_reg(gmac1_dev, 0x0, 0x1D, 0x0A);
153	phy_reg_val = nss_gmac_mii_rd_reg(gmac1_dev, 0x0, 0x1E);
154
155	netdev_dbg(gmacdev->netdev, "Reg 1A reset val:  0x%x\n", phy_reg_val);
156
157	nss_gmac_mii_wr_reg(gmac1_dev, 0x0, 0x1D, 0x0A);
158	nss_gmac_mii_wr_reg(gmac1_dev, 0x0, 0x1E, 0x3F9);
159	nss_gmac_mii_wr_reg(gmac1_dev, 0x0, 0x1D, 0x0A);
160
161	phy_reg_val = nss_gmac_mii_rd_reg(gmac1_dev, 0x0, 0x1E);
162
163	netdev_dbg(gmacdev->netdev, "Reg 1A after programming:  0x%x\n",
164								phy_reg_val);
165	nss_gmac_mii_wr_reg(gmac1_dev, 0x0, 0x18, 0x30);
166
167	/* Put PCS in SGMII Mode */
168	nss_gmac_write_reg(qsgmii_base, PCS_QSGMII_SGMII_MODE, 0x0);
169
170	/* Channel 2 force speed */
171	nss_gmac_write_reg(qsgmii_base, PCS_ALL_CH_CTL, 0xF0000600);
172}
173#endif
174
175/**
176 * @brief QSGMII dev init
177 *
178 * @param[in] nss_gmac_dev *
179 * @return void
180 */
181void nss_gmac_qsgmii_dev_init(struct nss_gmac_dev *gmacdev)
182{
183	uint32_t val = 0;
184	uint32_t id = gmacdev->macid;
185	uint8_t *nss_base = (uint8_t *)(gmacdev->ctx->nss_base);
186	uint32_t *qsgmii_base = (uint32_t *)(gmacdev->ctx->qsgmii_base);
187	uint32_t qsgmii_tx_param;
188
189#ifdef RUMI_EMULATION_SUPPORT
190	nss_gmac_rumi_qsgmii_init(gmacdev);
191#endif
192	if (gmacdev->phy_mii_type == PHY_INTERFACE_MODE_SGMII) {
193		switch (gmacdev->macid) {
194		case 1:
195			if (SOCINFO_VERSION_MAJOR(gmacdev->ctx->socver) < 2) {
196				qsgmii_tx_param = QSGMII_PHY_TX_DRV_AMP(0xC)
197					| QSGMII_PHY_TX_SLEW(0x2)
198					| QSGMII_PHY_DEEMPHASIS_LVL(0x2);
199			} else {
200				qsgmii_tx_param = QSGMII_PHY_TX_DRV_AMP(0xD)
201					| QSGMII_PHY_TX_SLEW(0)
202					| QSGMII_PHY_DEEMPHASIS_LVL(0);
203			}
204
205			nss_gmac_write_reg((uint32_t *)qsgmii_base,
206				   QSGMII_PHY_QSGMII_CTL, QSGMII_PHY_CDR_EN
207					  | QSGMII_PHY_RX_FRONT_EN
208					  | QSGMII_PHY_RX_SIGNAL_DETECT_EN
209					  | QSGMII_PHY_TX_DRIVER_EN
210					  | QSGMII_PHY_QSGMII_EN
211					  | QSGMII_PHY_PHASE_LOOP_GAIN(0x4)
212					  | QSGMII_PHY_RX_DC_BIAS(0x2)
213					  | QSGMII_PHY_RX_INPUT_EQU(0x1)
214					  | QSGMII_PHY_CDR_PI_SLEW(0x2)
215					  | qsgmii_tx_param);
216
217			val = nss_gmac_read_reg((uint32_t *)qsgmii_base,
218							QSGMII_PHY_QSGMII_CTL);
219			netdev_dbg(gmacdev->netdev, "%s: QSGMII_PHY_QSGMII_CTL(0x%x) - 0x%x\n",
220					__func__, QSGMII_PHY_QSGMII_CTL, val);
221
222			break;
223
224		case 2:
225			nss_gmac_write_reg((uint32_t *)qsgmii_base,
226				   QSGMII_PHY_SGMII_1_CTL, QSGMII_PHY_CDR_EN
227					  | QSGMII_PHY_RX_FRONT_EN
228					  | QSGMII_PHY_RX_SIGNAL_DETECT_EN
229					  | QSGMII_PHY_TX_DRIVER_EN
230					  | QSGMII_PHY_QSGMII_EN
231					  | QSGMII_PHY_PHASE_LOOP_GAIN(0x4)
232					  | QSGMII_PHY_RX_DC_BIAS(0x3)
233					  | QSGMII_PHY_RX_INPUT_EQU(0x1)
234					  | QSGMII_PHY_CDR_PI_SLEW(0x2)
235					  | QSGMII_PHY_TX_DRV_AMP(0xC));
236
237			val = nss_gmac_read_reg((uint32_t *)qsgmii_base,
238							QSGMII_PHY_SGMII_1_CTL);
239			netdev_dbg(gmacdev->netdev, "%s: QSGMII_PHY_SGMII_1_CTL(0x%x) - 0x%x\n",
240					__func__, QSGMII_PHY_SGMII_1_CTL, val);
241			break;
242
243		case 3:
244			nss_gmac_write_reg((uint32_t *)qsgmii_base,
245				   QSGMII_PHY_SGMII_2_CTL, QSGMII_PHY_CDR_EN
246					  | QSGMII_PHY_RX_FRONT_EN
247					  | QSGMII_PHY_RX_SIGNAL_DETECT_EN
248					  | QSGMII_PHY_TX_DRIVER_EN
249					  | QSGMII_PHY_QSGMII_EN
250					  | QSGMII_PHY_PHASE_LOOP_GAIN(0x4)
251					  | QSGMII_PHY_RX_DC_BIAS(0x3)
252					  | QSGMII_PHY_RX_INPUT_EQU(0x1)
253					  | QSGMII_PHY_CDR_PI_SLEW(0x2)
254					  | QSGMII_PHY_TX_DRV_AMP(0xC));
255
256			val = nss_gmac_read_reg((uint32_t *)qsgmii_base,
257							QSGMII_PHY_SGMII_2_CTL);
258			netdev_dbg(gmacdev->netdev, "%s: QSGMII_PHY_SGMII_2_CTL(0x%x) - 0x%x\n",
259					__func__, QSGMII_PHY_SGMII_2_CTL, val);
260			break;
261		}
262	}
263
264	/* Enable clk for GMACn */
265	val = 0;
266	if ((gmacdev->phy_mii_type == PHY_INTERFACE_MODE_SGMII)
267		|| (gmacdev->phy_mii_type == PHY_INTERFACE_MODE_QSGMII)) {
268		val |= GMACn_QSGMII_RX_CLK(id) | GMACn_QSGMII_TX_CLK(id);
269	}
270
271	nss_gmac_clear_reg_bits((uint32_t *)nss_base, NSS_QSGMII_CLK_CTL, val);
272
273	val = nss_gmac_read_reg((uint32_t *)nss_base, NSS_QSGMII_CLK_CTL);
274	netdev_dbg(gmacdev->netdev, "%s: NSS_QSGMII_CLK_CTL(0x%x) - 0x%x\n",
275		      __func__, NSS_QSGMII_CLK_CTL, val);
276
277	/*
278	 * Enable autonegotiation between PCS and PHY if speed is
279	 * not forced for this interface
280	 */
281	if (gmacdev->forced_speed == SPEED_UNKNOWN) {
282		nss_gmac_clear_reg_bits(qsgmii_base, PCS_ALL_CH_CTL,
283					PCS_CHn_SPEED_MASK(gmacdev->macid));
284		nss_gmac_clear_reg_bits(qsgmii_base, PCS_ALL_CH_CTL,
285					PCS_CHn_FORCE_SPEED(gmacdev->macid));
286	}
287}
288
289
290/**
291 * @brief Clear all NSS GMAC interface registers.
292 * @return returns 0 on success.
293 */
294static void nss_gmac_clear_all_regs(uint32_t *nss_base)
295{
296	nss_gmac_clear_reg_bits((uint32_t *)nss_base,
297				NSS_ETH_CLK_GATE_CTL, 0xFFFFFFFF);
298	nss_gmac_clear_reg_bits((uint32_t *)nss_base,
299				NSS_ETH_CLK_DIV0, 0xFFFFFFFF);
300	nss_gmac_clear_reg_bits((uint32_t *)nss_base,
301				NSS_ETH_CLK_DIV1, 0xFFFFFFFF);
302	nss_gmac_clear_reg_bits((uint32_t *)nss_base,
303				NSS_ETH_CLK_SRC_CTL, 0xFFFFFFFF);
304	nss_gmac_clear_reg_bits((uint32_t *)nss_base,
305				NSS_ETH_CLK_INV_CTL, 0xFFFFFFFF);
306	nss_gmac_clear_reg_bits((uint32_t *)nss_base,
307				NSS_GMAC0_CTL, 0xFFFFFFFF);
308	nss_gmac_clear_reg_bits((uint32_t *)nss_base,
309				NSS_GMAC1_CTL, 0xFFFFFFFF);
310	nss_gmac_clear_reg_bits((uint32_t *)nss_base,
311				NSS_GMAC2_CTL, 0xFFFFFFFF);
312	nss_gmac_clear_reg_bits((uint32_t *)nss_base,
313				NSS_GMAC3_CTL, 0xFFFFFFFF);
314	nss_gmac_clear_reg_bits((uint32_t *)nss_base,
315				NSS_QSGMII_CLK_CTL, 0xFFFFFFFF);
316}
317
318#ifdef CONFIG_OF
319/**
320 * @brief Determine board type and return relevant
321 *	NSS GMAC Phy profile.
322 *
323 * @return Phy profile
324 */
325int32_t nss_gmac_get_phy_profile(void)
326{
327	if (of_machine_is_compatible("qcom,ipq8064"))
328		return NSS_GMAC_PHY_PROFILE_2R_2S;
329
330	return NSS_GMAC_PHY_PROFILE_1R_3S;
331}
332#endif
333
334/**
335 * @brief QSGMII common init
336 *
337 * @param[in] nss_gmac_dev *
338 * @return void
339 */
340static void nss_gmac_qsgmii_common_init(struct nss_gmac_global_ctx *ctx)
341{
342	uint32_t val;
343	uint32_t *qsgmii_base = ctx->qsgmii_base;
344
345	if (nss_gmac_get_phy_profile() == NSS_GMAC_PHY_PROFILE_QS) {
346		/* Configure QSGMII Block for QSGMII mode */
347
348		/* Put PHY in QSGMII Mode */
349		nss_gmac_write_reg(qsgmii_base, QSGMII_PHY_MODE_CTL,
350						QSGMII_PHY_MODE_QSGMII);
351
352		/* Put PCS in QSGMII Mode */
353		nss_gmac_write_reg(qsgmii_base, PCS_QSGMII_SGMII_MODE,
354						PCS_QSGMII_MODE_QSGMII);
355
356		/* QSGMII Ctrl Register settings */
357		val = nss_gmac_read_reg(qsgmii_base, QSGMII_PHY_QSGMII_CTL);
358		val &= ~(QSGMII_PHY_TX_DRV_AMP_MASK
359			| QSGMII_PHY_TX_SLEW_MASK
360			| QSGMII_PHY_DEEMPHASIS_LVL_MASK
361			| QSGMII_PHY_RX_INPUT_EQU_MASK);
362
363		val |= (QSGMII_PHY_TX_DRV_AMP(0xD)
364			| QSGMII_PHY_TX_SLEW(0)
365			| QSGMII_PHY_DEEMPHASIS_LVL(0)
366			| QSGMII_PHY_RX_INPUT_EQU(0x1));
367
368		nss_gmac_write_reg(qsgmii_base, QSGMII_PHY_QSGMII_CTL, val);
369		val = nss_gmac_read_reg(qsgmii_base, QSGMII_PHY_QSGMII_CTL);
370		pr_debug("%s: QSGMII_PHY_QSGMII_CTL(0x%x) - 0x%x\n",
371					__func__, QSGMII_PHY_QSGMII_CTL, val);
372		goto out;
373	}
374
375	/* Configure QSGMII Block for 3xSGMII mode */
376
377	/* Put PHY in SGMII Mode */
378	nss_gmac_write_reg(qsgmii_base, QSGMII_PHY_MODE_CTL,
379							QSGMII_PHY_MODE_SGMII);
380
381	/* Put PCS in SGMII Mode */
382	nss_gmac_write_reg(qsgmii_base, PCS_QSGMII_SGMII_MODE,
383							PCS_QSGMII_MODE_SGMII);
384
385out:
386	val = nss_gmac_read_reg(qsgmii_base, QSGMII_PHY_MODE_CTL);
387	pr_debug("%s: qsgmii_base(0x%x) + QSGMII_PHY_MODE_CTL(0x%x): 0x%x\n",
388					__func__, (uint32_t)qsgmii_base,
389					(uint32_t)QSGMII_PHY_MODE_CTL, val);
390
391	val = nss_gmac_read_reg(qsgmii_base, PCS_QSGMII_SGMII_MODE);
392	pr_debug("%s: qsgmii_base(0x%x) + PCS_QSGMII_SGMII_MODE(0x%x): 0x%x\n",
393					 __func__, (uint32_t)qsgmii_base,
394					(uint32_t)PCS_QSGMII_SGMII_MODE, val);
395
396	/* Mode ctrl signal for mode selection */
397	nss_gmac_clear_reg_bits(qsgmii_base, PCS_MODE_CTL,
398			PCS_MODE_CTL_SGMII_MAC | PCS_MODE_CTL_SGMII_PHY);
399	nss_gmac_set_reg_bits(qsgmii_base, PCS_MODE_CTL,
400						PCS_MODE_CTL_SGMII_MAC);
401
402	/* Apply reset to PCS and release */
403	nss_gmac_write_reg((uint32_t *)(ctx->clk_ctl_base),
404					NSS_RESET_SPARE, 0x3FFFFFF);
405	udelay(100);
406	nss_gmac_write_reg((uint32_t *)(ctx->clk_ctl_base),
407					NSS_RESET_SPARE, 0x0);
408
409	val = nss_gmac_read_reg((uint32_t *)(ctx->clk_ctl_base),
410							NSS_RESET_SPARE);
411	pr_debug("%s: qsgmii_base(0x%x) + NSS_RESET_SPARE(0x%x): 0x%x\n",
412					__func__, (uint32_t)(ctx->clk_ctl_base),
413					(uint32_t)NSS_RESET_SPARE, val);
414
415	/* signal detect and channel enable */
416	nss_gmac_write_reg(qsgmii_base,
417		PCS_QSGMII_CTL, PCS_QSGMII_SW_VER_1_7
418		| PCS_QSGMII_ATHR_CSCO_AUTONEG
419		/*| PCS_QSGMII_CUTTHROUGH_TX | PCS_QSGMII_CUTTHROUGH_RX*/
420		| PCS_QSGMII_SHORT_THRESH | PCS_QSGMII_SHORT_LATENCY
421		| PCS_QSGMII_DEPTH_THRESH(1) | PCS_CHn_SERDES_SN_DETECT(0)
422		| PCS_CHn_SERDES_SN_DETECT(1) | PCS_CHn_SERDES_SN_DETECT(2)
423		| PCS_CHn_SERDES_SN_DETECT(3) | PCS_CHn_SERDES_SN_DETECT_2(0)
424		| PCS_CHn_SERDES_SN_DETECT_2(1) | PCS_CHn_SERDES_SN_DETECT_2(2)
425		| PCS_CHn_SERDES_SN_DETECT_2(3));
426	val = nss_gmac_read_reg(qsgmii_base, PCS_QSGMII_CTL);
427	pr_debug("%s: qsgmii_base(0x%x) + PCS_QSGMII_CTL(0x%x): 0x%x\n",
428	       __func__, (uint32_t)qsgmii_base, (uint32_t)PCS_QSGMII_CTL, val);
429
430	/* set debug bits */
431	nss_gmac_set_reg_bits((uint32_t *)qsgmii_base, PCS_ALL_CH_CTL,
432								0xF0000000);
433
434}
435
436
437/*
438 * @brief Initialization commom to all GMACs.
439 * @return returns 0 on success.
440 */
441int32_t nss_gmac_common_init(struct nss_gmac_global_ctx *ctx)
442{
443	uint32_t val;
444
445	nss_gmac_clear_all_regs((uint32_t *)ctx->nss_base);
446
447	nss_gmac_write_reg((uint32_t *)(ctx->qsgmii_base),
448		QSGMII_PHY_QSGMII_CTL, QSGMII_PHY_CDR_EN
449		| QSGMII_PHY_RX_FRONT_EN | QSGMII_PHY_RX_SIGNAL_DETECT_EN
450		| QSGMII_PHY_TX_DRIVER_EN | QSGMII_PHY_QSGMII_EN
451		| QSGMII_PHY_DEEMPHASIS_LVL(0x2)
452		| QSGMII_PHY_PHASE_LOOP_GAIN(0x2) | QSGMII_PHY_RX_DC_BIAS(0x2)
453		| QSGMII_PHY_RX_INPUT_EQU(0x1) | QSGMII_PHY_CDR_PI_SLEW(0x2)
454		| QSGMII_PHY_TX_SLEW(0x2) | QSGMII_PHY_TX_DRV_AMP(0xC));
455
456	nss_gmac_write_reg((uint32_t *)(ctx->qsgmii_base), PCS_CAL_LCKDT_CTL,
457								PCS_LCKDT_RST);
458	/*
459	 * TCSR cannot be accessed from HLOS drivers after XPUs are enabled.
460	 * TrustZone will initialize this register during init.
461	 *
462	 * nss_gmac_write_reg((msm_tcsr_base), 0xc0, 0x0);
463	 */
464
465	/*
466	 * Deaassert GMAC AHB reset
467	 */
468	nss_gmac_clear_reg_bits((uint32_t *)(ctx->clk_ctl_base),
469							GMAC_AHB_RESET, 0x1);
470	val = nss_gmac_read_reg(ctx->clk_ctl_base, GMAC_AHB_RESET);
471	pr_debug("%s: ctx->clk_ctl_base(0x%x) + GMAC_AHB_RESET(0x%x): 0x%x\n",
472					__func__, (uint32_t)ctx->clk_ctl_base,
473					(uint32_t)GMAC_AHB_RESET, val);
474
475	/* Bypass MACSEC */
476	nss_gmac_set_reg_bits((uint32_t *)(ctx->nss_base), NSS_MACSEC_CTL,
477				GMACn_MACSEC_BYPASS(1) | GMACn_MACSEC_BYPASS(2)
478				| GMACn_MACSEC_BYPASS(3));
479
480	val = nss_gmac_read_reg((uint32_t *)ctx->nss_base, NSS_MACSEC_CTL);
481	pr_debug("%s: nss_bsae(0x%x) + NSS_MACSEC_CTL(0x%x): 0x%x\n",
482					__func__, (uint32_t)ctx->nss_base,
483					(uint32_t)NSS_MACSEC_CTL, val);
484
485	nss_gmac_qsgmii_common_init(ctx);
486
487	/*
488	 * Initialize ACC_GMAC_CUST field of NSS_ACC_REG register
489	 * for GMAC and MACSEC memories.
490	 */
491	nss_gmac_clear_reg_bits((uint32_t *)(ctx->clk_ctl_base), NSS_ACC_REG,
492							GMAC_ACC_CUST_MASK);
493	val = nss_gmac_read_reg(ctx->clk_ctl_base, NSS_ACC_REG);
494	pr_debug("%s: ctx->clk_ctl_base(0x%x) + NSS_ACC_REG(0x%x): 0x%x\n",
495					__func__, (uint32_t)ctx->clk_ctl_base,
496					(uint32_t)NSS_ACC_REG, val);
497
498	return 0;
499}
500
501/**
502 * @brief Global common deinitialization.
503 * @return void
504 */
505void nss_gmac_common_deinit(struct nss_gmac_global_ctx *ctx)
506{
507	nss_gmac_clear_all_regs((uint32_t *)ctx->nss_base);
508
509	if (ctx->qsgmii_base) {
510		iounmap(ctx->qsgmii_base);
511		ctx->qsgmii_base = NULL;
512	}
513
514	if (ctx->clk_ctl_base) {
515		iounmap(ctx->clk_ctl_base);
516		ctx->clk_ctl_base = NULL;
517	}
518
519	if (ctx->nss_base) {
520		iounmap(ctx->nss_base);
521		ctx->nss_base = NULL;
522	}
523}
524
525/*
526 * @brief Return clock divider value for QSGMII PHY.
527 * @param[in] nss_gmac_dev *
528 * @return returns QSGMII clock divider value.
529 */
530static uint32_t clk_div_qsgmii(struct nss_gmac_dev *gmacdev)
531{
532	uint32_t div;
533
534	switch (gmacdev->speed) {
535	case SPEED_1000:
536		div = QSGMII_CLK_DIV_1000;
537		break;
538
539	case SPEED_100:
540		div = QSGMII_CLK_DIV_100;
541		break;
542
543	case SPEED_10:
544		div = QSGMII_CLK_DIV_10;
545		break;
546
547	default:
548		div = QSGMII_CLK_DIV_1000;
549		break;
550	}
551
552	return div;
553}
554
555/**
556 * @brief Return clock divider value for SGMII PHY.
557 * @param[in] nss_gmac_dev *
558 * @return returns SGMII clock divider value.
559 */
560static uint32_t clk_div_sgmii(struct nss_gmac_dev *gmacdev)
561{
562	uint32_t div;
563
564	switch (gmacdev->speed) {
565	case SPEED_1000:
566		div = SGMII_CLK_DIV_1000;
567		break;
568
569	case SPEED_100:
570		div = SGMII_CLK_DIV_100;
571		break;
572
573	case SPEED_10:
574		div = SGMII_CLK_DIV_10;
575		break;
576
577	default:
578		div = SGMII_CLK_DIV_1000;
579		break;
580	}
581
582	return div;
583}
584
585/**
586 * @brief Return clock divider value for RGMII PHY.
587 * @param[in] nss_gmac_dev *
588 * @return returns RGMII clock divider value.
589 */
590static uint32_t clk_div_rgmii(struct nss_gmac_dev *gmacdev)
591{
592	uint32_t div;
593
594	switch (gmacdev->speed) {
595	case SPEED_1000:
596		div = RGMII_CLK_DIV_1000;
597		break;
598
599	case SPEED_100:
600		div = RGMII_CLK_DIV_100;
601		break;
602
603	case SPEED_10:
604		div = RGMII_CLK_DIV_10;
605		break;
606
607	default:
608		div = RGMII_CLK_DIV_1000;
609		break;
610	}
611
612	return div;
613}
614
615/**
616 * @brief Return PCS Channel speed values
617 * @param[in] nss_gmac_dev *
618 * @return returns PCS speed values.
619 */
620static uint32_t get_pcs_speed(struct nss_gmac_dev *gmacdev)
621{
622	uint32_t speed;
623
624	switch (gmacdev->speed) {
625	case SPEED_1000:
626		speed = PCS_CH_SPEED_1000;
627		break;
628
629	case SPEED_100:
630		speed = PCS_CH_SPEED_100;
631		break;
632
633	case SPEED_10:
634		speed = PCS_CH_SPEED_10;
635		break;
636
637	default:
638		speed = PCS_CH_SPEED_1000;
639		break;
640	}
641
642	return speed;
643}
644/**
645 * @brief Set GMAC speed.
646 * @param[in] nss_gmac_dev *
647 * @return returns 0 on success.
648 */
649int32_t nss_gmac_dev_set_speed(struct nss_gmac_dev *gmacdev)
650{
651	uint32_t val = 0;
652	uint32_t id = gmacdev->macid;
653	uint32_t div = 0, pcs_speed = 0;
654	uint32_t clk = 0;
655	uint32_t *nss_base = (uint32_t *)(gmacdev->ctx->nss_base);
656	uint32_t *qsgmii_base = (uint32_t *)(gmacdev->ctx->qsgmii_base);
657	struct nss_gmac_speed_ctx gmac_speed_ctx = {0, 0};
658	int force_speed = 0;
659
660	switch (gmacdev->phy_mii_type) {
661	case PHY_INTERFACE_MODE_RGMII:
662		div = clk_div_rgmii(gmacdev);
663		break;
664
665	case PHY_INTERFACE_MODE_SGMII:
666		div = clk_div_sgmii(gmacdev);
667		break;
668
669	case PHY_INTERFACE_MODE_QSGMII:
670		div = clk_div_qsgmii(gmacdev);
671		break;
672
673	default:
674		netdev_dbg(gmacdev->netdev, "%s: Invalid MII type\n", __func__);
675		return -EINVAL;
676	}
677
678	if (gmacdev->forced_speed != SPEED_UNKNOWN)
679		force_speed = 1;
680
681	/*
682	 * Set SGMII force speed control signal if necessary
683	 */
684	if (((gmacdev->phy_mii_type == PHY_INTERFACE_MODE_SGMII) ||
685			(gmacdev->phy_mii_type == PHY_INTERFACE_MODE_QSGMII))
686			&& (force_speed == 1)) {
687			pcs_speed = get_pcs_speed(gmacdev);
688			nss_gmac_set_reg_bits(qsgmii_base, PCS_ALL_CH_CTL,
689						PCS_CHn_FORCE_SPEED(id));
690			nss_gmac_clear_reg_bits(qsgmii_base, PCS_ALL_CH_CTL,
691						PCS_CHn_SPEED_MASK(id));
692			nss_gmac_set_reg_bits(qsgmii_base, PCS_ALL_CH_CTL,
693						PCS_CHn_SPEED(id, pcs_speed));
694	}
695
696	clk = 0;
697	/* Disable GMACn Tx/Rx clk */
698	if (gmacdev->phy_mii_type == PHY_INTERFACE_MODE_RGMII)
699		clk |= GMACn_RGMII_RX_CLK(id) | GMACn_RGMII_TX_CLK(id);
700	else
701		clk |= GMACn_GMII_RX_CLK(id) | GMACn_GMII_TX_CLK(id);
702	nss_gmac_clear_reg_bits(nss_base, NSS_ETH_CLK_GATE_CTL, clk);
703
704	/* set clock divider */
705	val = nss_gmac_read_reg(nss_base, NSS_ETH_CLK_DIV0);
706	val &= ~GMACn_CLK_DIV(id, GMACn_CLK_DIV_SIZE);
707	val |= GMACn_CLK_DIV(id, div);
708	nss_gmac_write_reg(nss_base, NSS_ETH_CLK_DIV0, val);
709
710	/* Enable GMACn Tx/Rx clk */
711	nss_gmac_set_reg_bits(nss_base, NSS_ETH_CLK_GATE_CTL, clk);
712
713	val = nss_gmac_read_reg(nss_base, NSS_ETH_CLK_DIV0);
714	netdev_dbg(gmacdev->netdev, "%s:NSS_ETH_CLK_DIV0(0x%x) - 0x%x\n",
715		      __func__, NSS_ETH_CLK_DIV0, val);
716
717	if (gmacdev->phy_mii_type == PHY_INTERFACE_MODE_SGMII
718	    || gmacdev->phy_mii_type == PHY_INTERFACE_MODE_QSGMII) {
719		nss_gmac_clear_reg_bits(qsgmii_base, PCS_MODE_CTL,
720					PCS_MODE_CTL_CHn_AUTONEG_EN(id));
721
722		/*
723		 * Enable autonegotiation from MII register of PHY
724		 * if the speed is not forced
725		 */
726		if (!force_speed) {
727			nss_gmac_set_reg_bits(qsgmii_base, PCS_MODE_CTL,
728					      PCS_MODE_CTL_CHn_AUTONEG_EN(id));
729		}
730
731		val = nss_gmac_read_reg(qsgmii_base, PCS_MODE_CTL);
732		netdev_dbg(gmacdev->netdev, "%s: qsgmii_base(0x%x) + PCS_MODE_CTL(0x%x): 0x%x\n",
733		       __func__, (uint32_t)qsgmii_base, (uint32_t)PCS_MODE_CTL, val);
734
735	}
736
737	/* Notify link speed change to notifier list */
738	gmac_speed_ctx.mac_id = gmacdev->macid;
739	gmac_speed_ctx.speed = gmacdev->speed;
740	blocking_notifier_call_chain(&nss_gmac_notifier_list,
741					NSS_GMAC_SPEED_SET, &gmac_speed_ctx);
742
743	return 0;
744}
745
746/**
747 * @brief GMAC device initializaton.
748 * @param[in] nss_gmac_dev *
749 * @return void
750 */
751void nss_gmac_dev_init(struct nss_gmac_dev *gmacdev)
752{
753	uint32_t val = 0;
754	uint32_t div = 0;
755	uint32_t id = gmacdev->macid;
756	uint32_t *nss_base = (uint32_t *)(gmacdev->ctx->nss_base);
757	struct nss_gmac_global_ctx *ctx = gmacdev->ctx;
758
759	/*
760	 * Initialize wake and sleep counter values of
761	 * GMAC memory footswitch control.
762	 */
763	nss_gmac_set_reg_bits(ctx->clk_ctl_base, GMAC_COREn_CLK_FS(id),
764							 GMAC_FS_S_W_VAL);
765	val = nss_gmac_read_reg(ctx->clk_ctl_base, GMAC_COREn_CLK_FS(id));
766	netdev_dbg(gmacdev->netdev, "%s: ctx->clk_ctl_base(0x%x) + GMAC_COREn_CLK_FS(%d)(0x%x): 0x%x\n",
767		       __func__, (uint32_t)ctx->clk_ctl_base, id, (uint32_t)GMAC_COREn_CLK_FS(id), val);
768
769	/*
770	 * Bring up GMAC core clock
771	 */
772	/* a) Program GMAC_COREn_CLK_SRC_CTL register */
773	nss_gmac_clear_reg_bits(ctx->clk_ctl_base, GMAC_COREn_CLK_SRC_CTL(id),
774				GMAC_DUAL_MN8_SEL |
775				GMAC_CLK_ROOT_ENA |
776				GMAC_CLK_LOW_PWR_ENA);
777	nss_gmac_set_reg_bits(ctx->clk_ctl_base, GMAC_COREn_CLK_SRC_CTL(id),
778			      GMAC_CLK_ROOT_ENA);
779
780	val = nss_gmac_read_reg(ctx->clk_ctl_base, GMAC_COREn_CLK_SRC_CTL(id));
781	netdev_dbg(gmacdev->netdev, "%s: ctx->clk_ctl_base(0x%x) + GMAC_COREn_CLK_SRC_CTL(%d)(0x%x): 0x%x\n",
782				__func__, (uint32_t)ctx->clk_ctl_base, id,
783				(uint32_t)GMAC_COREn_CLK_SRC_CTL(id), val);
784
785	/* b) Program M & D values in GMAC_COREn_CLK_SRC[0,1]_MD register. */
786	nss_gmac_write_reg(ctx->clk_ctl_base, GMAC_COREn_CLK_SRC0_MD(id), 0);
787	nss_gmac_write_reg(ctx->clk_ctl_base, GMAC_COREn_CLK_SRC1_MD(id), 0);
788	nss_gmac_set_reg_bits(ctx->clk_ctl_base, GMAC_COREn_CLK_SRC0_MD(id),
789			      GMAC_CORE_CLK_M_VAL | GMAC_CORE_CLK_D_VAL);
790	nss_gmac_set_reg_bits(ctx->clk_ctl_base, GMAC_COREn_CLK_SRC1_MD(id),
791			      GMAC_CORE_CLK_M_VAL | GMAC_CORE_CLK_D_VAL);
792
793	val = nss_gmac_read_reg(ctx->clk_ctl_base, GMAC_COREn_CLK_SRC0_MD(id));
794	netdev_dbg(gmacdev->netdev, "%s: ctx->clk_ctl_base(0x%x) + GMAC_COREn_CLK_SRC0_MD(%d)(0x%x): 0x%x\n",
795				__func__, (uint32_t)ctx->clk_ctl_base, id,
796				(uint32_t)GMAC_COREn_CLK_SRC0_MD(id), val);
797	val = nss_gmac_read_reg(ctx->clk_ctl_base, GMAC_COREn_CLK_SRC1_MD(id));
798	netdev_dbg(gmacdev->netdev, "%s: ctx->clk_ctl_base(0x%x) + GMAC_COREn_CLK_SRC1_MD(%d)(0x%x): 0x%x\n",
799				__func__, (uint32_t)ctx->clk_ctl_base, id,
800				(uint32_t)GMAC_COREn_CLK_SRC1_MD(id), val);
801
802	/* c) Program N values on GMAC_COREn_CLK_SRC[0,1]_NS register */
803	nss_gmac_write_reg(ctx->clk_ctl_base, GMAC_COREn_CLK_SRC0_NS(id), 0);
804	nss_gmac_write_reg(ctx->clk_ctl_base, GMAC_COREn_CLK_SRC1_NS(id), 0);
805	nss_gmac_set_reg_bits(ctx->clk_ctl_base, GMAC_COREn_CLK_SRC0_NS(id),
806			      GMAC_CORE_CLK_N_VAL
807			      | GMAC_CORE_CLK_MNCNTR_EN
808			      | GMAC_CORE_CLK_MNCNTR_MODE_DUAL
809			      | GMAC_CORE_CLK_PRE_DIV_SEL_BYP
810			      | GMAC_CORE_CLK_SRC_SEL_PLL0);
811	nss_gmac_set_reg_bits(ctx->clk_ctl_base, GMAC_COREn_CLK_SRC1_NS(id),
812			      GMAC_CORE_CLK_N_VAL
813			      | GMAC_CORE_CLK_MNCNTR_EN
814			      | GMAC_CORE_CLK_MNCNTR_MODE_DUAL
815			      | GMAC_CORE_CLK_PRE_DIV_SEL_BYP
816			      | GMAC_CORE_CLK_SRC_SEL_PLL0);
817
818	val = nss_gmac_read_reg(ctx->clk_ctl_base, GMAC_COREn_CLK_SRC0_NS(id));
819	netdev_dbg(gmacdev->netdev, "%s: ctx->clk_ctl_base(0x%x) + GMAC_COREn_CLK_SRC0_NS(%d)(0x%x): 0x%x\n",
820				__func__, (uint32_t)ctx->clk_ctl_base, id,
821				(uint32_t)GMAC_COREn_CLK_SRC0_NS(id), val);
822	val = nss_gmac_read_reg(ctx->clk_ctl_base, GMAC_COREn_CLK_SRC1_NS(id));
823	netdev_dbg(gmacdev->netdev, "%s: ctx->clk_ctl_base(0x%x) + GMAC_COREn_CLK_SRC1_NS(%d)(0x%x): 0x%x\n",
824				__func__, (uint32_t)ctx->clk_ctl_base, id,
825				(uint32_t)GMAC_COREn_CLK_SRC1_NS(id), val);
826
827	/* d) Un-halt GMACn clock */
828	nss_gmac_clear_reg_bits(ctx->clk_ctl_base,
829		CLK_HALT_NSSFAB0_NSSFAB1_STATEA, GMACn_CORE_CLK_HALT(id));
830	val = nss_gmac_read_reg(ctx->clk_ctl_base,
831					CLK_HALT_NSSFAB0_NSSFAB1_STATEA);
832	netdev_dbg(gmacdev->netdev, "%s: ctx->clk_ctl_base(0x%x) + CLK_HALT_NSSFAB0_NSSFAB1_STATEA(0x%x): 0x%x\n",
833				__func__, (uint32_t)ctx->clk_ctl_base,
834				(uint32_t)CLK_HALT_NSSFAB0_NSSFAB1_STATEA, val);
835
836	/* e) CLK_COREn_CLK_CTL: select branch enable and disable clk invert */
837	nss_gmac_clear_reg_bits(ctx->clk_ctl_base, GMAC_COREn_CLK_CTL(id),
838							GMAC_CLK_INV);
839	nss_gmac_set_reg_bits(ctx->clk_ctl_base, GMAC_COREn_CLK_CTL(id),
840							GMAC_CLK_BRANCH_EN);
841	val = nss_gmac_read_reg(ctx->clk_ctl_base, GMAC_COREn_CLK_CTL(id));
842	netdev_dbg(gmacdev->netdev, "%s: ctx->clk_ctl_base(0x%x) + GMAC_COREn_CLK_CTL(%d)(0x%x): 0x%x\n",
843				__func__, (uint32_t)ctx->clk_ctl_base, id,
844				(uint32_t)GMAC_COREn_CLK_CTL(id), val);
845
846	/* Set GMACn Ctl: Phy interface select, IFG, AXI low power request
847	 * signal (CSYSREQ)
848	 */
849	val = GMAC_IFG_CTL(GMAC_IFG) | GMAC_IFG_LIMIT(GMAC_IFG) | GMAC_CSYS_REQ;
850	if (gmacdev->phy_mii_type == PHY_INTERFACE_MODE_RGMII)
851		val |= GMAC_PHY_RGMII;
852	else
853		val &= ~GMAC_PHY_RGMII;
854
855	nss_gmac_write_reg(nss_base, NSS_GMACn_CTL(id), 0x0);
856	nss_gmac_write_reg(nss_base, NSS_GMACn_CTL(id), val);
857
858	val = nss_gmac_read_reg(nss_base, NSS_GMACn_CTL(id));
859	netdev_dbg(gmacdev->netdev, "%s: nss_base(0x%x) + NSS_GMACn_CTL(%d)(0x%x): 0x%x\n",
860					__func__, (uint32_t)nss_base, id,
861					(uint32_t)NSS_GMACn_CTL(id), val);
862
863	/*
864	 * Optionally enable/disable MACSEC bypass.
865	 * We are doing this in nss_gmac_plat_init()
866	 */
867
868	/*
869	 * Deassert GMACn power on reset
870	 */
871	nss_gmac_clear_reg_bits(ctx->clk_ctl_base, GMAC_COREn_RESET(id), 0x1);
872
873	/* Configure clock dividers for 1000Mbps default */
874	gmacdev->speed = SPEED_1000;
875	switch (gmacdev->phy_mii_type) {
876	case PHY_INTERFACE_MODE_RGMII:
877		div = clk_div_rgmii(gmacdev);
878		break;
879
880	case PHY_INTERFACE_MODE_SGMII:
881		div = clk_div_sgmii(gmacdev);
882		break;
883
884	case PHY_INTERFACE_MODE_QSGMII:
885		div = clk_div_qsgmii(gmacdev);
886		break;
887	}
888	val = nss_gmac_read_reg(nss_base, NSS_ETH_CLK_DIV0);
889	val &= ~GMACn_CLK_DIV(id, GMACn_CLK_DIV_SIZE);
890	val |= GMACn_CLK_DIV(id, div);
891	nss_gmac_write_reg(nss_base, NSS_ETH_CLK_DIV0, val);
892
893	val = nss_gmac_read_reg(nss_base, NSS_ETH_CLK_DIV0);
894	netdev_dbg(gmacdev->netdev, "%s: nss_base(0x%x) + NSS_ETH_CLK_DIV0(0x%x): 0x%x\n",
895		__func__, (uint32_t)nss_base, (uint32_t)NSS_ETH_CLK_DIV0, val);
896
897	/* Select Tx/Rx CLK source */
898	val = 0;
899	if (id == 0 || id == 1) {
900		if (gmacdev->phy_mii_type == PHY_INTERFACE_MODE_RGMII)
901			val |= (1 << id);
902	} else {
903		if (gmacdev->phy_mii_type == PHY_INTERFACE_MODE_SGMII)
904			val |= (1 << id);
905	}
906	nss_gmac_set_reg_bits(nss_base, NSS_ETH_CLK_SRC_CTL, val);
907
908	/* Enable xGMII clk for GMACn */
909	val = 0;
910	if (gmacdev->phy_mii_type == PHY_INTERFACE_MODE_RGMII)
911		val |= GMACn_RGMII_RX_CLK(id) | GMACn_RGMII_TX_CLK(id);
912	else
913		val |= GMACn_GMII_RX_CLK(id) | GMACn_GMII_TX_CLK(id);
914
915	/* Optionally configure RGMII CDC delay */
916
917	/* Enable PTP clock */
918	val |= GMACn_PTP_CLK(id);
919	nss_gmac_set_reg_bits(nss_base, NSS_ETH_CLK_GATE_CTL, val);
920
921	if ((gmacdev->phy_mii_type == PHY_INTERFACE_MODE_SGMII)
922	     || (gmacdev->phy_mii_type == PHY_INTERFACE_MODE_QSGMII)) {
923		nss_gmac_qsgmii_dev_init(gmacdev);
924		netdev_dbg(gmacdev->netdev, "SGMII Specific Init for GMAC%d Done!\n", id);
925	}
926}
927
928/**
929 * @brief Do macsec related initialization in gmac register scope.
930 * @return void.
931 */
932void nss_macsec_pre_init(void)
933{
934	uint32_t val = 0;
935	uint32_t *nss_base = (uint32_t *)ctx.nss_base;
936
937	/*
938	 * Initialize wake and sleep counter values of
939	 * MACSEC memory footswitch control.
940	 */
941	nss_gmac_write_reg(nss_base, NSS_MACSEC1_CORE_CLK_FS_CTL,
942						MACSEC_CLK_FS_CTL_S_W_VAL);
943	nss_gmac_write_reg(nss_base, NSS_MACSEC2_CORE_CLK_FS_CTL,
944						MACSEC_CLK_FS_CTL_S_W_VAL);
945	nss_gmac_write_reg(nss_base, NSS_MACSEC3_CORE_CLK_FS_CTL,
946						MACSEC_CLK_FS_CTL_S_W_VAL);
947
948	/* MACSEC reset */
949	nss_gmac_write_reg(ctx.clk_ctl_base, MACSEC_CORE1_RESET, 1);
950	nss_gmac_write_reg(ctx.clk_ctl_base, MACSEC_CORE2_RESET, 1);
951	nss_gmac_write_reg(ctx.clk_ctl_base, MACSEC_CORE3_RESET, 1);
952	msleep(100);
953
954	/* Deassert MACSEC reset */
955	nss_gmac_write_reg(ctx.clk_ctl_base, MACSEC_CORE1_RESET, 0);
956	nss_gmac_write_reg(ctx.clk_ctl_base, MACSEC_CORE2_RESET, 0);
957	nss_gmac_write_reg(ctx.clk_ctl_base, MACSEC_CORE3_RESET, 0);
958
959	/* Enable MACSEC clocks */
960	val = nss_gmac_read_reg(nss_base, NSS_ETH_CLK_GATE_CTL);
961	val |= (MACSEC_CORE_CLKEN_VAL | MACSEC_GMII_RX_CLKEN_VAL |
962						MACSEC_GMII_TX_CLKEN_VAL);
963	nss_gmac_write_reg(nss_base, NSS_ETH_CLK_GATE_CTL, val);
964
965	/* Bypass all MACSECs */
966	nss_gmac_write_reg(nss_base, NSS_MACSEC_CTL, MACSEC_EXT_BYPASS_EN_MASK |
967						MACSEC_DP_RST_VAL);
968}
969EXPORT_SYMBOL(nss_macsec_pre_init);
970
971/**
972 * @brief reset MACSEC IFG register
973 * @param[in] gmac_id
974 * @return void
975 */
976static void nss_gmac_ifg_reset(uint32_t gmac_id)
977{
978	uint32_t val = 0;
979	uint32_t *nss_base = (uint32_t *)ctx.nss_base;
980
981	val = nss_gmac_read_reg(nss_base, NSS_GMACn_CTL(gmac_id));
982	val &= ~(IFG_MASK | GMAC_IFG_LIMIT(IFG_MASK));
983	val |= (GMAC_IFG_CTL(GMAC_IFG) | GMAC_IFG_LIMIT(GMAC_IFG));
984	nss_gmac_write_reg(nss_base, NSS_GMACn_CTL(gmac_id), val);
985}
986
987/**
988 * @brief set gmac link status into expected state
989 * @param[in] gmac_id
990 * @param[in] link_state
991 * @return void
992 */
993static void nss_gmac_link_status_set(uint32_t gmac_id, uint32_t link_state)
994{
995	struct nss_gmac_dev *gmac_dev = NULL;
996
997	gmac_dev = ctx.nss_gmac[gmac_id];
998	if (gmac_dev == NULL)
999		return;
1000
1001	if (!test_bit(__NSS_GMAC_UP, &gmac_dev->flags))
1002		return;
1003
1004	if (link_state == LINKDOWN && gmac_dev->link_state == LINKUP)
1005		nss_gmac_linkdown(gmac_dev);
1006	else if (link_state == LINKUP && gmac_dev->link_state == LINKDOWN)
1007		nss_gmac_linkup(gmac_dev);
1008}
1009
1010/**
1011 * @brief enable or disable MACSEC bypass function
1012 * @param[in] gmac_id
1013 * @param[in] enable
1014 * @return void
1015 */
1016void nss_macsec_bypass_en_set(uint32_t gmac_id, bool enable)
1017{
1018	uint32_t val = 0;
1019	uint32_t *nss_base = (uint32_t *)ctx.nss_base;
1020	struct nss_gmac_dev *gmac_dev = NULL;
1021	uint32_t link_reset_flag = 0;
1022	struct nss_gmac_speed_ctx gmac_speed_ctx = {0, 0};
1023
1024	if ((gmac_id == 0) || (gmac_id > 3))
1025		return;
1026
1027	gmac_dev = ctx.nss_gmac[gmac_id];
1028	if (gmac_dev == NULL)
1029		return;
1030
1031	mutex_lock(&gmac_dev->link_mutex);
1032
1033	/* If gmac is in link up state, it need to simulate link down event
1034	 * before setting IFG and simulate link up event after the operation
1035	 */
1036	if (gmac_dev->link_state == LINKUP)
1037		link_reset_flag = 1;
1038
1039	/* simulate a gmac link down event */
1040	if (link_reset_flag)
1041		nss_gmac_link_status_set(gmac_id, LINKDOWN);
1042
1043	/* Set MACSEC_IFG value */
1044	if (enable) {
1045		nss_gmac_ifg_reset(gmac_id);
1046	} else {
1047		val = nss_gmac_read_reg(nss_base, NSS_GMACn_CTL(gmac_id));
1048		val &= ~(IFG_MASK | GMAC_IFG_LIMIT(IFG_MASK));
1049		val |= (GMAC_IFG_CTL(MACSEC_IFG) | GMAC_IFG_LIMIT(MACSEC_IFG));
1050		nss_gmac_write_reg(nss_base, NSS_GMACn_CTL(gmac_id), val);
1051	}
1052
1053	/* Enable/Disable MACSEC for related port */
1054	val = nss_gmac_read_reg(nss_base, NSS_MACSEC_CTL);
1055	val |= MACSEC_DP_RST_VAL;
1056	if (enable)
1057		val |= (1<<(gmac_id - 1));
1058	else
1059		val &= ~(1<<(gmac_id - 1));
1060	nss_gmac_write_reg(nss_base, NSS_MACSEC_CTL, val);
1061
1062	/* simulate a gmac link up event */
1063	if (link_reset_flag)
1064		nss_gmac_link_status_set(gmac_id, LINKUP);
1065
1066	mutex_unlock(&gmac_dev->link_mutex);
1067
1068	/* Set MACSEC speed */
1069	gmac_speed_ctx.mac_id = gmac_dev->macid;
1070	gmac_speed_ctx.speed = gmac_dev->speed;
1071	blocking_notifier_call_chain(&nss_gmac_notifier_list,
1072					NSS_GMAC_SPEED_SET, &gmac_speed_ctx);
1073}
1074EXPORT_SYMBOL(nss_macsec_bypass_en_set);
1075
1076/**
1077 * @brief  Do macsec related exist function in gmac register scope
1078 * @return void
1079 */
1080void nss_macsec_pre_exit(void)
1081{
1082	uint32_t *nss_base = (uint32_t *)ctx.nss_base;
1083	struct nss_gmac_dev *gmac_dev = NULL;
1084	uint32_t gmac_id = 0;
1085	uint32_t link_reset_flag = 0;
1086
1087	/* MACSEC reset */
1088	nss_gmac_write_reg(ctx.clk_ctl_base, MACSEC_CORE1_RESET, 1);
1089	nss_gmac_write_reg(ctx.clk_ctl_base, MACSEC_CORE2_RESET, 1);
1090	nss_gmac_write_reg(ctx.clk_ctl_base, MACSEC_CORE3_RESET, 1);
1091
1092	/* Bypass all MACSECs */
1093	nss_gmac_write_reg(nss_base, NSS_MACSEC_CTL,
1094				MACSEC_EXT_BYPASS_EN_MASK | MACSEC_DP_RST_VAL);
1095
1096	/* Reset GMAC_IFG value */
1097	for (gmac_id = 1; gmac_id < 4; gmac_id++) {
1098		gmac_dev = ctx.nss_gmac[gmac_id];
1099		if (gmac_dev == NULL)
1100			continue;
1101
1102		/*
1103		 * If gmac is in link up state, it need to simulate link down
1104		 * event before setting IFG and simulate link up event after the
1105		 * operation
1106		 */
1107		link_reset_flag = 0;
1108
1109		mutex_lock(&gmac_dev->link_mutex);
1110
1111		if (gmac_dev->link_state == LINKUP)
1112			link_reset_flag = 1;
1113
1114		/* simulate a gmac link down event */
1115		if (link_reset_flag)
1116			nss_gmac_link_status_set(gmac_id, LINKDOWN);
1117
1118		nss_gmac_ifg_reset(gmac_id);
1119
1120		/* simulate a gmac link up event */
1121		if (link_reset_flag)
1122			nss_gmac_link_status_set(gmac_id, LINKUP);
1123
1124		mutex_unlock(&gmac_dev->link_mutex);
1125	}
1126}
1127EXPORT_SYMBOL(nss_macsec_pre_exit);
1128
1129/**
1130 * @brief register notifier into gmac module
1131 * @param[in] struct notifier_block *
1132 * @return void
1133 */
1134void nss_gmac_link_state_change_notify_register(struct notifier_block *nb)
1135{
1136	blocking_notifier_chain_register(&nss_gmac_notifier_list, nb);
1137}
1138EXPORT_SYMBOL_GPL(nss_gmac_link_state_change_notify_register);
1139
1140/**
1141 * @brief unregister notifier into gmac module
1142 * @param[in] struct notifier_block *
1143 * @return void
1144 */
1145void nss_gmac_link_state_change_notify_unregister(struct notifier_block *nb)
1146{
1147	blocking_notifier_chain_unregister(&nss_gmac_notifier_list, nb);
1148}
1149EXPORT_SYMBOL_GPL(nss_gmac_link_state_change_notify_unregister);
1150