Commit | Line | Data |
---|---|---|
511e6bc0 | 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); | |
511e6bc0 | 67 | dsaf_set_bit(mac_cb->cpld_led_value, DSAF_LED_ANCHOR_B, |
68 | CPLD_LED_ON_VALUE); | |
69 | dsaf_write_b(mac_cb->cpld_vaddr, mac_cb->cpld_led_value); | |
edc9b427 | 70 | return 2; |
511e6bc0 | 71 | case HNAE_LED_INACTIVE: |
72 | dsaf_set_bit(mac_cb->cpld_led_value, DSAF_LED_ANCHOR_B, | |
73 | CPLD_LED_DEFAULT_VALUE); | |
74 | dsaf_write_b(mac_cb->cpld_vaddr, mac_cb->cpld_led_value); | |
75 | break; | |
76 | default: | |
77 | break; | |
78 | } | |
79 | ||
80 | return 0; | |
81 | } | |
82 | ||
83 | #define RESET_REQ_OR_DREQ 1 | |
84 | ||
85 | void hns_dsaf_rst(struct dsaf_device *dsaf_dev, u32 val) | |
86 | { | |
87 | u32 xbar_reg_addr; | |
88 | u32 nt_reg_addr; | |
89 | ||
90 | if (!val) { | |
91 | xbar_reg_addr = DSAF_SUB_SC_XBAR_RESET_REQ_REG; | |
92 | nt_reg_addr = DSAF_SUB_SC_NT_RESET_REQ_REG; | |
93 | } else { | |
94 | xbar_reg_addr = DSAF_SUB_SC_XBAR_RESET_DREQ_REG; | |
95 | nt_reg_addr = DSAF_SUB_SC_NT_RESET_DREQ_REG; | |
96 | } | |
97 | ||
98 | dsaf_write_reg(dsaf_dev->sc_base, xbar_reg_addr, | |
99 | RESET_REQ_OR_DREQ); | |
100 | dsaf_write_reg(dsaf_dev->sc_base, nt_reg_addr, | |
101 | RESET_REQ_OR_DREQ); | |
102 | } | |
103 | ||
104 | void hns_dsaf_xge_srst_by_port(struct dsaf_device *dsaf_dev, u32 port, u32 val) | |
105 | { | |
106 | u32 reg_val = 0; | |
107 | u32 reg_addr; | |
108 | ||
109 | if (port >= DSAF_XGE_NUM) | |
110 | return; | |
111 | ||
112 | reg_val |= RESET_REQ_OR_DREQ; | |
113 | reg_val |= 0x2082082 << port; | |
114 | ||
115 | if (val == 0) | |
116 | reg_addr = DSAF_SUB_SC_XGE_RESET_REQ_REG; | |
117 | else | |
118 | reg_addr = DSAF_SUB_SC_XGE_RESET_DREQ_REG; | |
119 | ||
120 | dsaf_write_reg(dsaf_dev->sc_base, reg_addr, reg_val); | |
121 | } | |
122 | ||
123 | void hns_dsaf_xge_core_srst_by_port(struct dsaf_device *dsaf_dev, | |
124 | u32 port, u32 val) | |
125 | { | |
126 | u32 reg_val = 0; | |
127 | u32 reg_addr; | |
128 | ||
129 | if (port >= DSAF_XGE_NUM) | |
130 | return; | |
131 | ||
132 | reg_val |= XGMAC_TRX_CORE_SRST_M << port; | |
133 | ||
134 | if (val == 0) | |
135 | reg_addr = DSAF_SUB_SC_XGE_RESET_REQ_REG; | |
136 | else | |
137 | reg_addr = DSAF_SUB_SC_XGE_RESET_DREQ_REG; | |
138 | ||
139 | dsaf_write_reg(dsaf_dev->sc_base, reg_addr, reg_val); | |
140 | } | |
141 | ||
142 | void hns_dsaf_ge_srst_by_port(struct dsaf_device *dsaf_dev, u32 port, u32 val) | |
143 | { | |
144 | u32 reg_val_1; | |
145 | u32 reg_val_2; | |
146 | ||
147 | if (port >= DSAF_GE_NUM) | |
148 | return; | |
149 | ||
89a44093 | 150 | if (!HNS_DSAF_IS_DEBUG(dsaf_dev)) { |
511e6bc0 | 151 | reg_val_1 = 0x1 << port; |
13ac695e S |
152 | /* there is difference between V1 and V2 in register.*/ |
153 | if (AE_IS_VER1(dsaf_dev->dsaf_ver)) | |
154 | reg_val_2 = 0x1041041 << port; | |
155 | else | |
156 | reg_val_2 = 0x2082082 << port; | |
511e6bc0 | 157 | |
158 | if (val == 0) { | |
159 | dsaf_write_reg(dsaf_dev->sc_base, | |
160 | DSAF_SUB_SC_GE_RESET_REQ1_REG, | |
161 | reg_val_1); | |
162 | ||
163 | dsaf_write_reg(dsaf_dev->sc_base, | |
164 | DSAF_SUB_SC_GE_RESET_REQ0_REG, | |
165 | reg_val_2); | |
166 | } else { | |
167 | dsaf_write_reg(dsaf_dev->sc_base, | |
168 | DSAF_SUB_SC_GE_RESET_DREQ0_REG, | |
169 | reg_val_2); | |
170 | ||
171 | dsaf_write_reg(dsaf_dev->sc_base, | |
172 | DSAF_SUB_SC_GE_RESET_DREQ1_REG, | |
173 | reg_val_1); | |
174 | } | |
175 | } else { | |
176 | reg_val_1 = 0x15540 << (port - 6); | |
177 | reg_val_2 = 0x100 << (port - 6); | |
178 | ||
179 | if (val == 0) { | |
180 | dsaf_write_reg(dsaf_dev->sc_base, | |
181 | DSAF_SUB_SC_GE_RESET_REQ1_REG, | |
182 | reg_val_1); | |
183 | ||
184 | dsaf_write_reg(dsaf_dev->sc_base, | |
185 | DSAF_SUB_SC_PPE_RESET_REQ_REG, | |
186 | reg_val_2); | |
187 | } else { | |
188 | dsaf_write_reg(dsaf_dev->sc_base, | |
189 | DSAF_SUB_SC_GE_RESET_DREQ1_REG, | |
190 | reg_val_1); | |
191 | ||
192 | dsaf_write_reg(dsaf_dev->sc_base, | |
193 | DSAF_SUB_SC_PPE_RESET_DREQ_REG, | |
194 | reg_val_2); | |
195 | } | |
196 | } | |
197 | } | |
198 | ||
199 | void hns_ppe_srst_by_port(struct dsaf_device *dsaf_dev, u32 port, u32 val) | |
200 | { | |
201 | u32 reg_val = 0; | |
202 | u32 reg_addr; | |
203 | ||
204 | reg_val |= RESET_REQ_OR_DREQ << port; | |
205 | ||
206 | if (val == 0) | |
207 | reg_addr = DSAF_SUB_SC_PPE_RESET_REQ_REG; | |
208 | else | |
209 | reg_addr = DSAF_SUB_SC_PPE_RESET_DREQ_REG; | |
210 | ||
211 | dsaf_write_reg(dsaf_dev->sc_base, reg_addr, reg_val); | |
212 | } | |
213 | ||
214 | void hns_ppe_com_srst(struct ppe_common_cb *ppe_common, u32 val) | |
215 | { | |
216 | int comm_index = ppe_common->comm_index; | |
217 | struct dsaf_device *dsaf_dev = ppe_common->dsaf_dev; | |
218 | u32 reg_val; | |
219 | u32 reg_addr; | |
220 | ||
89a44093 | 221 | if (!HNS_DSAF_IS_DEBUG(dsaf_dev)) { |
511e6bc0 | 222 | reg_val = RESET_REQ_OR_DREQ; |
223 | if (val == 0) | |
224 | reg_addr = DSAF_SUB_SC_RCB_PPE_COM_RESET_REQ_REG; | |
225 | else | |
226 | reg_addr = DSAF_SUB_SC_RCB_PPE_COM_RESET_DREQ_REG; | |
227 | ||
228 | } else { | |
229 | reg_val = 0x100 << (comm_index - 1); | |
230 | ||
231 | if (val == 0) | |
232 | reg_addr = DSAF_SUB_SC_PPE_RESET_REQ_REG; | |
233 | else | |
234 | reg_addr = DSAF_SUB_SC_PPE_RESET_DREQ_REG; | |
235 | } | |
236 | ||
237 | dsaf_write_reg(dsaf_dev->sc_base, reg_addr, reg_val); | |
238 | } | |
239 | ||
240 | /** | |
241 | * hns_mac_get_sds_mode - get phy ifterface form serdes mode | |
242 | * @mac_cb: mac control block | |
243 | * retuen phy interface | |
244 | */ | |
245 | phy_interface_t hns_mac_get_phy_if(struct hns_mac_cb *mac_cb) | |
246 | { | |
c1203fe7 SL |
247 | u32 mode; |
248 | u32 reg; | |
249 | u32 shift; | |
250 | bool is_ver1 = AE_IS_VER1(mac_cb->dsaf_dev->dsaf_ver); | |
511e6bc0 | 251 | void __iomem *sys_ctl_vaddr = mac_cb->sys_ctl_vaddr; |
c1203fe7 | 252 | int mac_id = mac_cb->mac_id; |
511e6bc0 | 253 | phy_interface_t phy_if = PHY_INTERFACE_MODE_NA; |
254 | ||
c1203fe7 SL |
255 | if (is_ver1 && (mac_id >= 6 && mac_id <= 7)) { |
256 | phy_if = PHY_INTERFACE_MODE_SGMII; | |
257 | } else if (mac_id >= 0 && mac_id <= 3) { | |
258 | reg = is_ver1 ? HNS_MAC_HILINK4_REG : HNS_MAC_HILINK4V2_REG; | |
259 | mode = dsaf_read_reg(sys_ctl_vaddr, reg); | |
260 | /* mac_id 0, 1, 2, 3 ---> hilink4 lane 0, 1, 2, 3 */ | |
261 | shift = is_ver1 ? 0 : mac_id; | |
262 | if (dsaf_get_bit(mode, shift)) | |
511e6bc0 | 263 | phy_if = PHY_INTERFACE_MODE_XGMII; |
511e6bc0 | 264 | else |
c1203fe7 SL |
265 | phy_if = PHY_INTERFACE_MODE_SGMII; |
266 | } else if (mac_id >= 4 && mac_id <= 7) { | |
267 | reg = is_ver1 ? HNS_MAC_HILINK3_REG : HNS_MAC_HILINK3V2_REG; | |
268 | mode = dsaf_read_reg(sys_ctl_vaddr, reg); | |
269 | /* mac_id 4, 5, 6, 7 ---> hilink3 lane 2, 3, 0, 1 */ | |
270 | shift = is_ver1 ? 0 : mac_id <= 5 ? mac_id - 2 : mac_id - 6; | |
271 | if (dsaf_get_bit(mode, shift)) | |
511e6bc0 | 272 | phy_if = PHY_INTERFACE_MODE_XGMII; |
c1203fe7 SL |
273 | else |
274 | phy_if = PHY_INTERFACE_MODE_SGMII; | |
511e6bc0 | 275 | } |
511e6bc0 | 276 | return phy_if; |
277 | } | |
278 | ||
279 | /** | |
280 | * hns_mac_config_sds_loopback - set loop back for serdes | |
281 | * @mac_cb: mac control block | |
282 | * retuen 0 == success | |
283 | */ | |
284 | int hns_mac_config_sds_loopback(struct hns_mac_cb *mac_cb, u8 en) | |
285 | { | |
286 | /* port 0-3 hilink4 base is serdes_vaddr + 0x00280000 | |
287 | * port 4-7 hilink3 base is serdes_vaddr + 0x00200000 | |
288 | */ | |
289 | u8 *base_addr = (u8 *)mac_cb->serdes_vaddr + | |
290 | (mac_cb->mac_id <= 3 ? 0x00280000 : 0x00200000); | |
291 | const u8 lane_id[] = { | |
292 | 0, /* mac 0 -> lane 0 */ | |
293 | 1, /* mac 1 -> lane 1 */ | |
294 | 2, /* mac 2 -> lane 2 */ | |
295 | 3, /* mac 3 -> lane 3 */ | |
296 | 2, /* mac 4 -> lane 2 */ | |
297 | 3, /* mac 5 -> lane 3 */ | |
298 | 0, /* mac 6 -> lane 0 */ | |
299 | 1 /* mac 7 -> lane 1 */ | |
300 | }; | |
301 | #define RX_CSR(lane, reg) ((0x4080 + (reg) * 0x0002 + (lane) * 0x0200) * 2) | |
302 | u64 reg_offset = RX_CSR(lane_id[mac_cb->mac_id], 0); | |
303 | ||
304 | int sfp_prsnt; | |
305 | int ret = hns_mac_get_sfp_prsnt(mac_cb, &sfp_prsnt); | |
306 | ||
307 | if (!mac_cb->phy_node) { | |
308 | if (ret) | |
309 | pr_info("please confirm sfp is present or not\n"); | |
310 | else | |
311 | if (!sfp_prsnt) | |
312 | pr_info("no sfp in this eth\n"); | |
313 | } | |
314 | ||
315 | dsaf_set_reg_field(base_addr, reg_offset, 1ull << 10, 10, !!en); | |
316 | ||
317 | return 0; | |
318 | } |