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