1 /* 2 * Copyright (c) 2014-2015 Hisilicon Limited. 3 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation; either version 2 of the License, or 7 * (at your option) any later version. 8 */ 9 10 #include "hns_dsaf_misc.h" 11 #include "hns_dsaf_mac.h" 12 #include "hns_dsaf_reg.h" 13 #include "hns_dsaf_ppe.h" 14 15 void hns_cpld_set_led(struct hns_mac_cb *mac_cb, int link_status, 16 u16 speed, int data) 17 { 18 int speed_reg = 0; 19 u8 value; 20 21 if (!mac_cb) { 22 pr_err("sfp_led_opt mac_dev is null!\n"); 23 return; 24 } 25 if (!mac_cb->cpld_vaddr) { 26 dev_err(mac_cb->dev, "mac_id=%d, cpld_vaddr is null !\n", 27 mac_cb->mac_id); 28 return; 29 } 30 31 if (speed == MAC_SPEED_10000) 32 speed_reg = 1; 33 34 value = mac_cb->cpld_led_value; 35 36 if (link_status) { 37 dsaf_set_bit(value, DSAF_LED_LINK_B, link_status); 38 dsaf_set_field(value, DSAF_LED_SPEED_M, 39 DSAF_LED_SPEED_S, speed_reg); 40 dsaf_set_bit(value, DSAF_LED_DATA_B, data); 41 42 if (value != mac_cb->cpld_led_value) { 43 dsaf_write_b(mac_cb->cpld_vaddr, value); 44 mac_cb->cpld_led_value = value; 45 } 46 } else { 47 dsaf_write_b(mac_cb->cpld_vaddr, CPLD_LED_DEFAULT_VALUE); 48 mac_cb->cpld_led_value = CPLD_LED_DEFAULT_VALUE; 49 } 50 } 51 52 void cpld_led_reset(struct hns_mac_cb *mac_cb) 53 { 54 if (!mac_cb || !mac_cb->cpld_vaddr) 55 return; 56 57 dsaf_write_b(mac_cb->cpld_vaddr, CPLD_LED_DEFAULT_VALUE); 58 mac_cb->cpld_led_value = CPLD_LED_DEFAULT_VALUE; 59 } 60 61 int cpld_set_led_id(struct hns_mac_cb *mac_cb, 62 enum hnae_led_state status) 63 { 64 switch (status) { 65 case HNAE_LED_ACTIVE: 66 mac_cb->cpld_led_value = dsaf_read_b(mac_cb->cpld_vaddr); 67 return 2; 68 case HNAE_LED_ON: 69 dsaf_set_bit(mac_cb->cpld_led_value, DSAF_LED_ANCHOR_B, 70 CPLD_LED_ON_VALUE); 71 dsaf_write_b(mac_cb->cpld_vaddr, mac_cb->cpld_led_value); 72 break; 73 case HNAE_LED_OFF: 74 dsaf_set_bit(mac_cb->cpld_led_value, DSAF_LED_ANCHOR_B, 75 CPLD_LED_DEFAULT_VALUE); 76 dsaf_write_b(mac_cb->cpld_vaddr, mac_cb->cpld_led_value); 77 break; 78 case HNAE_LED_INACTIVE: 79 dsaf_set_bit(mac_cb->cpld_led_value, DSAF_LED_ANCHOR_B, 80 CPLD_LED_DEFAULT_VALUE); 81 dsaf_write_b(mac_cb->cpld_vaddr, mac_cb->cpld_led_value); 82 break; 83 default: 84 break; 85 } 86 87 return 0; 88 } 89 90 #define RESET_REQ_OR_DREQ 1 91 92 void hns_dsaf_rst(struct dsaf_device *dsaf_dev, u32 val) 93 { 94 u32 xbar_reg_addr; 95 u32 nt_reg_addr; 96 97 if (!val) { 98 xbar_reg_addr = DSAF_SUB_SC_XBAR_RESET_REQ_REG; 99 nt_reg_addr = DSAF_SUB_SC_NT_RESET_REQ_REG; 100 } else { 101 xbar_reg_addr = DSAF_SUB_SC_XBAR_RESET_DREQ_REG; 102 nt_reg_addr = DSAF_SUB_SC_NT_RESET_DREQ_REG; 103 } 104 105 dsaf_write_reg(dsaf_dev->sc_base, xbar_reg_addr, 106 RESET_REQ_OR_DREQ); 107 dsaf_write_reg(dsaf_dev->sc_base, nt_reg_addr, 108 RESET_REQ_OR_DREQ); 109 } 110 111 void hns_dsaf_xge_srst_by_port(struct dsaf_device *dsaf_dev, u32 port, u32 val) 112 { 113 u32 reg_val = 0; 114 u32 reg_addr; 115 116 if (port >= DSAF_XGE_NUM) 117 return; 118 119 reg_val |= RESET_REQ_OR_DREQ; 120 reg_val |= 0x2082082 << port; 121 122 if (val == 0) 123 reg_addr = DSAF_SUB_SC_XGE_RESET_REQ_REG; 124 else 125 reg_addr = DSAF_SUB_SC_XGE_RESET_DREQ_REG; 126 127 dsaf_write_reg(dsaf_dev->sc_base, reg_addr, reg_val); 128 } 129 130 void hns_dsaf_xge_core_srst_by_port(struct dsaf_device *dsaf_dev, 131 u32 port, u32 val) 132 { 133 u32 reg_val = 0; 134 u32 reg_addr; 135 136 if (port >= DSAF_XGE_NUM) 137 return; 138 139 reg_val |= XGMAC_TRX_CORE_SRST_M << port; 140 141 if (val == 0) 142 reg_addr = DSAF_SUB_SC_XGE_RESET_REQ_REG; 143 else 144 reg_addr = DSAF_SUB_SC_XGE_RESET_DREQ_REG; 145 146 dsaf_write_reg(dsaf_dev->sc_base, reg_addr, reg_val); 147 } 148 149 void hns_dsaf_ge_srst_by_port(struct dsaf_device *dsaf_dev, u32 port, u32 val) 150 { 151 u32 reg_val_1; 152 u32 reg_val_2; 153 154 if (port >= DSAF_GE_NUM) 155 return; 156 157 if (port < DSAF_SERVICE_NW_NUM) { 158 reg_val_1 = 0x1 << port; 159 reg_val_2 = 0x1041041 << port; 160 161 if (val == 0) { 162 dsaf_write_reg(dsaf_dev->sc_base, 163 DSAF_SUB_SC_GE_RESET_REQ1_REG, 164 reg_val_1); 165 166 dsaf_write_reg(dsaf_dev->sc_base, 167 DSAF_SUB_SC_GE_RESET_REQ0_REG, 168 reg_val_2); 169 } else { 170 dsaf_write_reg(dsaf_dev->sc_base, 171 DSAF_SUB_SC_GE_RESET_DREQ0_REG, 172 reg_val_2); 173 174 dsaf_write_reg(dsaf_dev->sc_base, 175 DSAF_SUB_SC_GE_RESET_DREQ1_REG, 176 reg_val_1); 177 } 178 } else { 179 reg_val_1 = 0x15540 << (port - 6); 180 reg_val_2 = 0x100 << (port - 6); 181 182 if (val == 0) { 183 dsaf_write_reg(dsaf_dev->sc_base, 184 DSAF_SUB_SC_GE_RESET_REQ1_REG, 185 reg_val_1); 186 187 dsaf_write_reg(dsaf_dev->sc_base, 188 DSAF_SUB_SC_PPE_RESET_REQ_REG, 189 reg_val_2); 190 } else { 191 dsaf_write_reg(dsaf_dev->sc_base, 192 DSAF_SUB_SC_GE_RESET_DREQ1_REG, 193 reg_val_1); 194 195 dsaf_write_reg(dsaf_dev->sc_base, 196 DSAF_SUB_SC_PPE_RESET_DREQ_REG, 197 reg_val_2); 198 } 199 } 200 } 201 202 void hns_ppe_srst_by_port(struct dsaf_device *dsaf_dev, u32 port, u32 val) 203 { 204 u32 reg_val = 0; 205 u32 reg_addr; 206 207 reg_val |= RESET_REQ_OR_DREQ << port; 208 209 if (val == 0) 210 reg_addr = DSAF_SUB_SC_PPE_RESET_REQ_REG; 211 else 212 reg_addr = DSAF_SUB_SC_PPE_RESET_DREQ_REG; 213 214 dsaf_write_reg(dsaf_dev->sc_base, reg_addr, reg_val); 215 } 216 217 void hns_ppe_com_srst(struct ppe_common_cb *ppe_common, u32 val) 218 { 219 int comm_index = ppe_common->comm_index; 220 struct dsaf_device *dsaf_dev = ppe_common->dsaf_dev; 221 u32 reg_val; 222 u32 reg_addr; 223 224 if (comm_index == HNS_DSAF_COMM_SERVICE_NW_IDX) { 225 reg_val = RESET_REQ_OR_DREQ; 226 if (val == 0) 227 reg_addr = DSAF_SUB_SC_RCB_PPE_COM_RESET_REQ_REG; 228 else 229 reg_addr = DSAF_SUB_SC_RCB_PPE_COM_RESET_DREQ_REG; 230 231 } else { 232 reg_val = 0x100 << (comm_index - 1); 233 234 if (val == 0) 235 reg_addr = DSAF_SUB_SC_PPE_RESET_REQ_REG; 236 else 237 reg_addr = DSAF_SUB_SC_PPE_RESET_DREQ_REG; 238 } 239 240 dsaf_write_reg(dsaf_dev->sc_base, reg_addr, reg_val); 241 } 242 243 /** 244 * hns_mac_get_sds_mode - get phy ifterface form serdes mode 245 * @mac_cb: mac control block 246 * retuen phy interface 247 */ 248 phy_interface_t hns_mac_get_phy_if(struct hns_mac_cb *mac_cb) 249 { 250 u32 hilink3_mode; 251 u32 hilink4_mode; 252 void __iomem *sys_ctl_vaddr = mac_cb->sys_ctl_vaddr; 253 int dev_id = mac_cb->mac_id; 254 phy_interface_t phy_if = PHY_INTERFACE_MODE_NA; 255 256 hilink3_mode = dsaf_read_reg(sys_ctl_vaddr, HNS_MAC_HILINK3_REG); 257 hilink4_mode = dsaf_read_reg(sys_ctl_vaddr, HNS_MAC_HILINK4_REG); 258 if (dev_id >= 0 && dev_id <= 3) { 259 if (hilink4_mode == 0) 260 phy_if = PHY_INTERFACE_MODE_SGMII; 261 else 262 phy_if = PHY_INTERFACE_MODE_XGMII; 263 } else if (dev_id >= 4 && dev_id <= 5) { 264 if (hilink3_mode == 0) 265 phy_if = PHY_INTERFACE_MODE_SGMII; 266 else 267 phy_if = PHY_INTERFACE_MODE_XGMII; 268 } else { 269 phy_if = PHY_INTERFACE_MODE_SGMII; 270 } 271 272 dev_dbg(mac_cb->dev, 273 "hilink3_mode=%d, hilink4_mode=%d dev_id=%d, phy_if=%d\n", 274 hilink3_mode, hilink4_mode, dev_id, phy_if); 275 return phy_if; 276 } 277 278 /** 279 * hns_mac_config_sds_loopback - set loop back for serdes 280 * @mac_cb: mac control block 281 * retuen 0 == success 282 */ 283 int hns_mac_config_sds_loopback(struct hns_mac_cb *mac_cb, u8 en) 284 { 285 /* port 0-3 hilink4 base is serdes_vaddr + 0x00280000 286 * port 4-7 hilink3 base is serdes_vaddr + 0x00200000 287 */ 288 u8 *base_addr = (u8 *)mac_cb->serdes_vaddr + 289 (mac_cb->mac_id <= 3 ? 0x00280000 : 0x00200000); 290 const u8 lane_id[] = { 291 0, /* mac 0 -> lane 0 */ 292 1, /* mac 1 -> lane 1 */ 293 2, /* mac 2 -> lane 2 */ 294 3, /* mac 3 -> lane 3 */ 295 2, /* mac 4 -> lane 2 */ 296 3, /* mac 5 -> lane 3 */ 297 0, /* mac 6 -> lane 0 */ 298 1 /* mac 7 -> lane 1 */ 299 }; 300 #define RX_CSR(lane, reg) ((0x4080 + (reg) * 0x0002 + (lane) * 0x0200) * 2) 301 u64 reg_offset = RX_CSR(lane_id[mac_cb->mac_id], 0); 302 303 int sfp_prsnt; 304 int ret = hns_mac_get_sfp_prsnt(mac_cb, &sfp_prsnt); 305 306 if (!mac_cb->phy_node) { 307 if (ret) 308 pr_info("please confirm sfp is present or not\n"); 309 else 310 if (!sfp_prsnt) 311 pr_info("no sfp in this eth\n"); 312 } 313 314 dsaf_set_reg_field(base_addr, reg_offset, 1ull << 10, 10, !!en); 315 316 return 0; 317 } 318