1 | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | /* |
3 | * Copyright (c) 2014-2015 Hisilicon Limited. |
4 | */ |
5 | |
6 | #include "hns_dsaf_mac.h" |
7 | #include "hns_dsaf_misc.h" |
8 | #include "hns_dsaf_ppe.h" |
9 | #include "hns_dsaf_reg.h" |
10 | |
11 | enum _dsm_op_index { |
12 | HNS_OP_RESET_FUNC = 0x1, |
13 | HNS_OP_SERDES_LP_FUNC = 0x2, |
14 | HNS_OP_LED_SET_FUNC = 0x3, |
15 | HNS_OP_GET_PORT_TYPE_FUNC = 0x4, |
16 | HNS_OP_GET_SFP_STAT_FUNC = 0x5, |
17 | HNS_OP_LOCATE_LED_SET_FUNC = 0x6, |
18 | }; |
19 | |
20 | enum _dsm_rst_type { |
21 | HNS_DSAF_RESET_FUNC = 0x1, |
22 | HNS_PPE_RESET_FUNC = 0x2, |
23 | HNS_XGE_RESET_FUNC = 0x4, |
24 | HNS_GE_RESET_FUNC = 0x5, |
25 | HNS_DSAF_CHN_RESET_FUNC = 0x6, |
26 | HNS_ROCE_RESET_FUNC = 0x7, |
27 | }; |
28 | |
29 | static const guid_t hns_dsaf_acpi_dsm_guid = |
30 | GUID_INIT(0x1A85AA1A, 0xE293, 0x415E, |
31 | 0x8E, 0x28, 0x8D, 0x69, 0x0A, 0x0F, 0x82, 0x0A); |
32 | |
33 | static void dsaf_write_sub(struct dsaf_device *dsaf_dev, u32 reg, u32 val) |
34 | { |
35 | if (dsaf_dev->sub_ctrl) |
36 | dsaf_write_syscon(base: dsaf_dev->sub_ctrl, reg, value: val); |
37 | else |
38 | dsaf_write_reg(base: dsaf_dev->sc_base, reg, value: val); |
39 | } |
40 | |
41 | static u32 dsaf_read_sub(struct dsaf_device *dsaf_dev, u32 reg) |
42 | { |
43 | u32 ret = 0; |
44 | int err; |
45 | |
46 | if (dsaf_dev->sub_ctrl) { |
47 | err = dsaf_read_syscon(base: dsaf_dev->sub_ctrl, reg, val: &ret); |
48 | if (err) |
49 | dev_err(dsaf_dev->dev, "dsaf_read_syscon error %d!\n" , |
50 | err); |
51 | } else { |
52 | ret = dsaf_read_reg(base: dsaf_dev->sc_base, reg); |
53 | } |
54 | |
55 | return ret; |
56 | } |
57 | |
58 | static void hns_dsaf_acpi_ledctrl_by_port(struct hns_mac_cb *mac_cb, u8 op_type, |
59 | u32 link, u32 port, u32 act) |
60 | { |
61 | union acpi_object *obj; |
62 | union acpi_object obj_args[3], argv4; |
63 | |
64 | obj_args[0].integer.type = ACPI_TYPE_INTEGER; |
65 | obj_args[0].integer.value = link; |
66 | obj_args[1].integer.type = ACPI_TYPE_INTEGER; |
67 | obj_args[1].integer.value = port; |
68 | obj_args[2].integer.type = ACPI_TYPE_INTEGER; |
69 | obj_args[2].integer.value = act; |
70 | |
71 | argv4.type = ACPI_TYPE_PACKAGE; |
72 | argv4.package.count = 3; |
73 | argv4.package.elements = obj_args; |
74 | |
75 | obj = acpi_evaluate_dsm(ACPI_HANDLE(mac_cb->dev), |
76 | guid: &hns_dsaf_acpi_dsm_guid, rev: 0, func: op_type, argv4: &argv4); |
77 | if (!obj) { |
78 | dev_warn(mac_cb->dev, "ledctrl fail, link:%d port:%d act:%d!\n" , |
79 | link, port, act); |
80 | return; |
81 | } |
82 | |
83 | ACPI_FREE(obj); |
84 | } |
85 | |
86 | static void hns_dsaf_acpi_locate_ledctrl_by_port(struct hns_mac_cb *mac_cb, |
87 | u8 op_type, u32 locate, |
88 | u32 port) |
89 | { |
90 | union acpi_object obj_args[2], argv4; |
91 | union acpi_object *obj; |
92 | |
93 | obj_args[0].integer.type = ACPI_TYPE_INTEGER; |
94 | obj_args[0].integer.value = locate; |
95 | obj_args[1].integer.type = ACPI_TYPE_INTEGER; |
96 | obj_args[1].integer.value = port; |
97 | |
98 | argv4.type = ACPI_TYPE_PACKAGE; |
99 | argv4.package.count = 2; |
100 | argv4.package.elements = obj_args; |
101 | |
102 | obj = acpi_evaluate_dsm(ACPI_HANDLE(mac_cb->dev), |
103 | guid: &hns_dsaf_acpi_dsm_guid, rev: 0, func: op_type, argv4: &argv4); |
104 | if (!obj) { |
105 | dev_err(mac_cb->dev, "ledctrl fail, locate:%d port:%d!\n" , |
106 | locate, port); |
107 | return; |
108 | } |
109 | |
110 | ACPI_FREE(obj); |
111 | } |
112 | |
113 | static void hns_cpld_set_led(struct hns_mac_cb *mac_cb, int link_status, |
114 | u16 speed, int data) |
115 | { |
116 | int speed_reg = 0; |
117 | u8 value; |
118 | |
119 | if (!mac_cb) { |
120 | pr_err("sfp_led_opt mac_dev is null!\n" ); |
121 | return; |
122 | } |
123 | if (!mac_cb->cpld_ctrl) { |
124 | dev_err(mac_cb->dev, "mac_id=%d, cpld syscon is null !\n" , |
125 | mac_cb->mac_id); |
126 | return; |
127 | } |
128 | |
129 | if (speed == MAC_SPEED_10000) |
130 | speed_reg = 1; |
131 | |
132 | value = mac_cb->cpld_led_value; |
133 | |
134 | if (link_status) { |
135 | dsaf_set_bit(value, DSAF_LED_LINK_B, link_status); |
136 | dsaf_set_field(value, DSAF_LED_SPEED_M, |
137 | DSAF_LED_SPEED_S, speed_reg); |
138 | dsaf_set_bit(value, DSAF_LED_DATA_B, data); |
139 | |
140 | if (value != mac_cb->cpld_led_value) { |
141 | dsaf_write_syscon(base: mac_cb->cpld_ctrl, |
142 | reg: mac_cb->cpld_ctrl_reg, value); |
143 | mac_cb->cpld_led_value = value; |
144 | } |
145 | } else { |
146 | value = (mac_cb->cpld_led_value) & (0x1 << DSAF_LED_ANCHOR_B); |
147 | dsaf_write_syscon(base: mac_cb->cpld_ctrl, |
148 | reg: mac_cb->cpld_ctrl_reg, value); |
149 | mac_cb->cpld_led_value = value; |
150 | } |
151 | } |
152 | |
153 | static void hns_cpld_set_led_acpi(struct hns_mac_cb *mac_cb, int link_status, |
154 | u16 speed, int data) |
155 | { |
156 | if (!mac_cb) { |
157 | pr_err("cpld_led_set mac_cb is null!\n" ); |
158 | return; |
159 | } |
160 | |
161 | hns_dsaf_acpi_ledctrl_by_port(mac_cb, op_type: HNS_OP_LED_SET_FUNC, |
162 | link: link_status, port: mac_cb->mac_id, act: data); |
163 | } |
164 | |
165 | static void cpld_led_reset(struct hns_mac_cb *mac_cb) |
166 | { |
167 | if (!mac_cb || !mac_cb->cpld_ctrl) |
168 | return; |
169 | |
170 | dsaf_write_syscon(base: mac_cb->cpld_ctrl, reg: mac_cb->cpld_ctrl_reg, |
171 | CPLD_LED_DEFAULT_VALUE); |
172 | mac_cb->cpld_led_value = CPLD_LED_DEFAULT_VALUE; |
173 | } |
174 | |
175 | static void cpld_led_reset_acpi(struct hns_mac_cb *mac_cb) |
176 | { |
177 | if (!mac_cb) { |
178 | pr_err("cpld_led_reset mac_cb is null!\n" ); |
179 | return; |
180 | } |
181 | |
182 | if (mac_cb->media_type != HNAE_MEDIA_TYPE_FIBER) |
183 | return; |
184 | |
185 | hns_dsaf_acpi_ledctrl_by_port(mac_cb, op_type: HNS_OP_LED_SET_FUNC, |
186 | link: 0, port: mac_cb->mac_id, act: 0); |
187 | } |
188 | |
189 | static int cpld_set_led_id(struct hns_mac_cb *mac_cb, |
190 | enum hnae_led_state status) |
191 | { |
192 | u32 val = 0; |
193 | int ret; |
194 | |
195 | if (!mac_cb->cpld_ctrl) |
196 | return 0; |
197 | |
198 | switch (status) { |
199 | case HNAE_LED_ACTIVE: |
200 | ret = dsaf_read_syscon(base: mac_cb->cpld_ctrl, reg: mac_cb->cpld_ctrl_reg, |
201 | val: &val); |
202 | if (ret) |
203 | return ret; |
204 | |
205 | dsaf_set_bit(val, DSAF_LED_ANCHOR_B, CPLD_LED_ON_VALUE); |
206 | dsaf_write_syscon(base: mac_cb->cpld_ctrl, reg: mac_cb->cpld_ctrl_reg, |
207 | value: val); |
208 | mac_cb->cpld_led_value = val; |
209 | break; |
210 | case HNAE_LED_INACTIVE: |
211 | dsaf_set_bit(mac_cb->cpld_led_value, DSAF_LED_ANCHOR_B, |
212 | CPLD_LED_DEFAULT_VALUE); |
213 | dsaf_write_syscon(base: mac_cb->cpld_ctrl, reg: mac_cb->cpld_ctrl_reg, |
214 | value: mac_cb->cpld_led_value); |
215 | break; |
216 | default: |
217 | dev_err(mac_cb->dev, "invalid led state: %d!" , status); |
218 | return -EINVAL; |
219 | } |
220 | |
221 | return 0; |
222 | } |
223 | |
224 | static int cpld_set_led_id_acpi(struct hns_mac_cb *mac_cb, |
225 | enum hnae_led_state status) |
226 | { |
227 | switch (status) { |
228 | case HNAE_LED_ACTIVE: |
229 | hns_dsaf_acpi_locate_ledctrl_by_port(mac_cb, |
230 | op_type: HNS_OP_LOCATE_LED_SET_FUNC, |
231 | CPLD_LED_ON_VALUE, |
232 | port: mac_cb->mac_id); |
233 | break; |
234 | case HNAE_LED_INACTIVE: |
235 | hns_dsaf_acpi_locate_ledctrl_by_port(mac_cb, |
236 | op_type: HNS_OP_LOCATE_LED_SET_FUNC, |
237 | CPLD_LED_DEFAULT_VALUE, |
238 | port: mac_cb->mac_id); |
239 | break; |
240 | default: |
241 | dev_err(mac_cb->dev, "invalid led state: %d!" , status); |
242 | return -EINVAL; |
243 | } |
244 | |
245 | return 0; |
246 | } |
247 | |
248 | #define RESET_REQ_OR_DREQ 1 |
249 | |
250 | static void hns_dsaf_acpi_srst_by_port(struct dsaf_device *dsaf_dev, u8 op_type, |
251 | u32 port_type, u32 port, u32 val) |
252 | { |
253 | union acpi_object *obj; |
254 | union acpi_object obj_args[3], argv4; |
255 | |
256 | obj_args[0].integer.type = ACPI_TYPE_INTEGER; |
257 | obj_args[0].integer.value = port_type; |
258 | obj_args[1].integer.type = ACPI_TYPE_INTEGER; |
259 | obj_args[1].integer.value = port; |
260 | obj_args[2].integer.type = ACPI_TYPE_INTEGER; |
261 | obj_args[2].integer.value = val; |
262 | |
263 | argv4.type = ACPI_TYPE_PACKAGE; |
264 | argv4.package.count = 3; |
265 | argv4.package.elements = obj_args; |
266 | |
267 | obj = acpi_evaluate_dsm(ACPI_HANDLE(dsaf_dev->dev), |
268 | guid: &hns_dsaf_acpi_dsm_guid, rev: 0, func: op_type, argv4: &argv4); |
269 | if (!obj) { |
270 | dev_warn(dsaf_dev->dev, "reset port_type%d port%d fail!" , |
271 | port_type, port); |
272 | return; |
273 | } |
274 | |
275 | ACPI_FREE(obj); |
276 | } |
277 | |
278 | static void hns_dsaf_rst(struct dsaf_device *dsaf_dev, bool dereset) |
279 | { |
280 | u32 xbar_reg_addr; |
281 | u32 nt_reg_addr; |
282 | |
283 | if (!dereset) { |
284 | xbar_reg_addr = DSAF_SUB_SC_XBAR_RESET_REQ_REG; |
285 | nt_reg_addr = DSAF_SUB_SC_NT_RESET_REQ_REG; |
286 | } else { |
287 | xbar_reg_addr = DSAF_SUB_SC_XBAR_RESET_DREQ_REG; |
288 | nt_reg_addr = DSAF_SUB_SC_NT_RESET_DREQ_REG; |
289 | } |
290 | |
291 | dsaf_write_sub(dsaf_dev, reg: xbar_reg_addr, RESET_REQ_OR_DREQ); |
292 | dsaf_write_sub(dsaf_dev, reg: nt_reg_addr, RESET_REQ_OR_DREQ); |
293 | } |
294 | |
295 | static void hns_dsaf_rst_acpi(struct dsaf_device *dsaf_dev, bool dereset) |
296 | { |
297 | hns_dsaf_acpi_srst_by_port(dsaf_dev, op_type: HNS_OP_RESET_FUNC, |
298 | port_type: HNS_DSAF_RESET_FUNC, |
299 | port: 0, val: dereset); |
300 | } |
301 | |
302 | static void hns_dsaf_xge_srst_by_port(struct dsaf_device *dsaf_dev, u32 port, |
303 | bool dereset) |
304 | { |
305 | u32 reg_val = 0; |
306 | u32 reg_addr; |
307 | |
308 | if (port >= DSAF_XGE_NUM) |
309 | return; |
310 | |
311 | reg_val |= RESET_REQ_OR_DREQ; |
312 | reg_val |= 0x2082082 << dsaf_dev->mac_cb[port]->port_rst_off; |
313 | |
314 | if (!dereset) |
315 | reg_addr = DSAF_SUB_SC_XGE_RESET_REQ_REG; |
316 | else |
317 | reg_addr = DSAF_SUB_SC_XGE_RESET_DREQ_REG; |
318 | |
319 | dsaf_write_sub(dsaf_dev, reg: reg_addr, val: reg_val); |
320 | } |
321 | |
322 | static void hns_dsaf_xge_srst_by_port_acpi(struct dsaf_device *dsaf_dev, |
323 | u32 port, bool dereset) |
324 | { |
325 | hns_dsaf_acpi_srst_by_port(dsaf_dev, op_type: HNS_OP_RESET_FUNC, |
326 | port_type: HNS_XGE_RESET_FUNC, port, val: dereset); |
327 | } |
328 | |
329 | /** |
330 | * hns_dsaf_srst_chns - reset dsaf channels |
331 | * @dsaf_dev: dsaf device struct pointer |
332 | * @msk: xbar channels mask value: |
333 | * @dereset: false - request reset , true - drop reset |
334 | * |
335 | * bit0-5 for xge0-5 |
336 | * bit6-11 for ppe0-5 |
337 | * bit12-17 for roce0-5 |
338 | * bit18-19 for com/dfx |
339 | */ |
340 | static void |
341 | hns_dsaf_srst_chns(struct dsaf_device *dsaf_dev, u32 msk, bool dereset) |
342 | { |
343 | u32 reg_addr; |
344 | |
345 | if (!dereset) |
346 | reg_addr = DSAF_SUB_SC_DSAF_RESET_REQ_REG; |
347 | else |
348 | reg_addr = DSAF_SUB_SC_DSAF_RESET_DREQ_REG; |
349 | |
350 | dsaf_write_sub(dsaf_dev, reg: reg_addr, val: msk); |
351 | } |
352 | |
353 | /** |
354 | * hns_dsaf_srst_chns_acpi - reset dsaf channels |
355 | * @dsaf_dev: dsaf device struct pointer |
356 | * @msk: xbar channels mask value: |
357 | * @dereset: false - request reset , true - drop reset |
358 | * |
359 | * bit0-5 for xge0-5 |
360 | * bit6-11 for ppe0-5 |
361 | * bit12-17 for roce0-5 |
362 | * bit18-19 for com/dfx |
363 | */ |
364 | static void |
365 | hns_dsaf_srst_chns_acpi(struct dsaf_device *dsaf_dev, u32 msk, bool dereset) |
366 | { |
367 | hns_dsaf_acpi_srst_by_port(dsaf_dev, op_type: HNS_OP_RESET_FUNC, |
368 | port_type: HNS_DSAF_CHN_RESET_FUNC, |
369 | port: msk, val: dereset); |
370 | } |
371 | |
372 | static void hns_dsaf_roce_srst(struct dsaf_device *dsaf_dev, bool dereset) |
373 | { |
374 | if (!dereset) { |
375 | dsaf_write_sub(dsaf_dev, DSAF_SUB_SC_ROCEE_RESET_REQ_REG, val: 1); |
376 | } else { |
377 | dsaf_write_sub(dsaf_dev, |
378 | DSAF_SUB_SC_ROCEE_CLK_DIS_REG, val: 1); |
379 | dsaf_write_sub(dsaf_dev, |
380 | DSAF_SUB_SC_ROCEE_RESET_DREQ_REG, val: 1); |
381 | msleep(msecs: 20); |
382 | dsaf_write_sub(dsaf_dev, DSAF_SUB_SC_ROCEE_CLK_EN_REG, val: 1); |
383 | } |
384 | } |
385 | |
386 | static void hns_dsaf_roce_srst_acpi(struct dsaf_device *dsaf_dev, bool dereset) |
387 | { |
388 | hns_dsaf_acpi_srst_by_port(dsaf_dev, op_type: HNS_OP_RESET_FUNC, |
389 | port_type: HNS_ROCE_RESET_FUNC, port: 0, val: dereset); |
390 | } |
391 | |
392 | static void hns_dsaf_ge_srst_by_port(struct dsaf_device *dsaf_dev, u32 port, |
393 | bool dereset) |
394 | { |
395 | u32 reg_val_1; |
396 | u32 reg_val_2; |
397 | u32 port_rst_off; |
398 | |
399 | if (port >= DSAF_GE_NUM) |
400 | return; |
401 | |
402 | if (!HNS_DSAF_IS_DEBUG(dsaf_dev)) { |
403 | /* DSAF_MAX_PORT_NUM is 6, but DSAF_GE_NUM is 8. |
404 | We need check to prevent array overflow */ |
405 | if (port >= DSAF_MAX_PORT_NUM) |
406 | return; |
407 | reg_val_1 = 0x1 << port; |
408 | port_rst_off = dsaf_dev->mac_cb[port]->port_rst_off; |
409 | /* there is difference between V1 and V2 in register.*/ |
410 | reg_val_2 = AE_IS_VER1(dsaf_dev->dsaf_ver) ? |
411 | 0x1041041 : 0x2082082; |
412 | reg_val_2 <<= port_rst_off; |
413 | |
414 | if (!dereset) { |
415 | dsaf_write_sub(dsaf_dev, DSAF_SUB_SC_GE_RESET_REQ1_REG, |
416 | val: reg_val_1); |
417 | |
418 | dsaf_write_sub(dsaf_dev, DSAF_SUB_SC_GE_RESET_REQ0_REG, |
419 | val: reg_val_2); |
420 | } else { |
421 | dsaf_write_sub(dsaf_dev, DSAF_SUB_SC_GE_RESET_DREQ0_REG, |
422 | val: reg_val_2); |
423 | |
424 | dsaf_write_sub(dsaf_dev, DSAF_SUB_SC_GE_RESET_DREQ1_REG, |
425 | val: reg_val_1); |
426 | } |
427 | } else { |
428 | reg_val_1 = 0x15540; |
429 | reg_val_2 = AE_IS_VER1(dsaf_dev->dsaf_ver) ? 0x100 : 0x40; |
430 | |
431 | reg_val_1 <<= dsaf_dev->reset_offset; |
432 | reg_val_2 <<= dsaf_dev->reset_offset; |
433 | |
434 | if (!dereset) { |
435 | dsaf_write_sub(dsaf_dev, DSAF_SUB_SC_GE_RESET_REQ1_REG, |
436 | val: reg_val_1); |
437 | |
438 | dsaf_write_sub(dsaf_dev, DSAF_SUB_SC_PPE_RESET_REQ_REG, |
439 | val: reg_val_2); |
440 | } else { |
441 | dsaf_write_sub(dsaf_dev, DSAF_SUB_SC_GE_RESET_DREQ1_REG, |
442 | val: reg_val_1); |
443 | |
444 | dsaf_write_sub(dsaf_dev, DSAF_SUB_SC_PPE_RESET_DREQ_REG, |
445 | val: reg_val_2); |
446 | } |
447 | } |
448 | } |
449 | |
450 | static void hns_dsaf_ge_srst_by_port_acpi(struct dsaf_device *dsaf_dev, |
451 | u32 port, bool dereset) |
452 | { |
453 | hns_dsaf_acpi_srst_by_port(dsaf_dev, op_type: HNS_OP_RESET_FUNC, |
454 | port_type: HNS_GE_RESET_FUNC, port, val: dereset); |
455 | } |
456 | |
457 | static void hns_ppe_srst_by_port(struct dsaf_device *dsaf_dev, u32 port, |
458 | bool dereset) |
459 | { |
460 | u32 reg_val = 0; |
461 | u32 reg_addr; |
462 | |
463 | reg_val |= RESET_REQ_OR_DREQ << dsaf_dev->mac_cb[port]->port_rst_off; |
464 | |
465 | if (!dereset) |
466 | reg_addr = DSAF_SUB_SC_PPE_RESET_REQ_REG; |
467 | else |
468 | reg_addr = DSAF_SUB_SC_PPE_RESET_DREQ_REG; |
469 | |
470 | dsaf_write_sub(dsaf_dev, reg: reg_addr, val: reg_val); |
471 | } |
472 | |
473 | static void |
474 | hns_ppe_srst_by_port_acpi(struct dsaf_device *dsaf_dev, u32 port, bool dereset) |
475 | { |
476 | hns_dsaf_acpi_srst_by_port(dsaf_dev, op_type: HNS_OP_RESET_FUNC, |
477 | port_type: HNS_PPE_RESET_FUNC, port, val: dereset); |
478 | } |
479 | |
480 | static void hns_ppe_com_srst(struct dsaf_device *dsaf_dev, bool dereset) |
481 | { |
482 | u32 reg_val; |
483 | u32 reg_addr; |
484 | |
485 | if (!(dev_of_node(dev: dsaf_dev->dev))) |
486 | return; |
487 | |
488 | if (!HNS_DSAF_IS_DEBUG(dsaf_dev)) { |
489 | reg_val = RESET_REQ_OR_DREQ; |
490 | if (!dereset) |
491 | reg_addr = DSAF_SUB_SC_RCB_PPE_COM_RESET_REQ_REG; |
492 | else |
493 | reg_addr = DSAF_SUB_SC_RCB_PPE_COM_RESET_DREQ_REG; |
494 | |
495 | } else { |
496 | reg_val = 0x100 << dsaf_dev->reset_offset; |
497 | |
498 | if (!dereset) |
499 | reg_addr = DSAF_SUB_SC_PPE_RESET_REQ_REG; |
500 | else |
501 | reg_addr = DSAF_SUB_SC_PPE_RESET_DREQ_REG; |
502 | } |
503 | |
504 | dsaf_write_sub(dsaf_dev, reg: reg_addr, val: reg_val); |
505 | } |
506 | |
507 | /** |
508 | * hns_mac_get_phy_if - get phy ifterface form serdes mode |
509 | * @mac_cb: mac control block |
510 | * retuen phy interface |
511 | */ |
512 | static phy_interface_t hns_mac_get_phy_if(struct hns_mac_cb *mac_cb) |
513 | { |
514 | u32 mode; |
515 | u32 reg; |
516 | bool is_ver1 = AE_IS_VER1(mac_cb->dsaf_dev->dsaf_ver); |
517 | int mac_id = mac_cb->mac_id; |
518 | phy_interface_t phy_if; |
519 | |
520 | if (is_ver1) { |
521 | if (HNS_DSAF_IS_DEBUG(mac_cb->dsaf_dev)) |
522 | return PHY_INTERFACE_MODE_SGMII; |
523 | |
524 | if (mac_id >= 0 && mac_id <= 3) |
525 | reg = HNS_MAC_HILINK4_REG; |
526 | else |
527 | reg = HNS_MAC_HILINK3_REG; |
528 | } else { |
529 | if (!HNS_DSAF_IS_DEBUG(mac_cb->dsaf_dev) && mac_id <= 3) |
530 | reg = HNS_MAC_HILINK4V2_REG; |
531 | else |
532 | reg = HNS_MAC_HILINK3V2_REG; |
533 | } |
534 | |
535 | mode = dsaf_read_sub(dsaf_dev: mac_cb->dsaf_dev, reg); |
536 | if (dsaf_get_bit(mode, mac_cb->port_mode_off)) |
537 | phy_if = PHY_INTERFACE_MODE_XGMII; |
538 | else |
539 | phy_if = PHY_INTERFACE_MODE_SGMII; |
540 | |
541 | return phy_if; |
542 | } |
543 | |
544 | static phy_interface_t hns_mac_get_phy_if_acpi(struct hns_mac_cb *mac_cb) |
545 | { |
546 | phy_interface_t phy_if = PHY_INTERFACE_MODE_NA; |
547 | union acpi_object *obj; |
548 | union acpi_object obj_args, argv4; |
549 | |
550 | obj_args.integer.type = ACPI_TYPE_INTEGER; |
551 | obj_args.integer.value = mac_cb->mac_id; |
552 | |
553 | argv4.type = ACPI_TYPE_PACKAGE; |
554 | argv4.package.count = 1; |
555 | argv4.package.elements = &obj_args; |
556 | |
557 | obj = acpi_evaluate_dsm_typed(ACPI_HANDLE(mac_cb->dev), |
558 | guid: &hns_dsaf_acpi_dsm_guid, rev: 0, |
559 | func: HNS_OP_GET_PORT_TYPE_FUNC, argv4: &argv4, |
560 | ACPI_TYPE_INTEGER); |
561 | if (!obj) |
562 | return phy_if; |
563 | |
564 | phy_if = obj->integer.value ? |
565 | PHY_INTERFACE_MODE_XGMII : PHY_INTERFACE_MODE_SGMII; |
566 | |
567 | dev_dbg(mac_cb->dev, "mac_id=%d, phy_if=%d\n" , mac_cb->mac_id, phy_if); |
568 | |
569 | ACPI_FREE(obj); |
570 | |
571 | return phy_if; |
572 | } |
573 | |
574 | static int hns_mac_get_sfp_prsnt(struct hns_mac_cb *mac_cb, int *sfp_prsnt) |
575 | { |
576 | u32 val = 0; |
577 | int ret; |
578 | |
579 | if (!mac_cb->cpld_ctrl) |
580 | return -ENODEV; |
581 | |
582 | ret = dsaf_read_syscon(base: mac_cb->cpld_ctrl, |
583 | reg: mac_cb->cpld_ctrl_reg + MAC_SFP_PORT_OFFSET, |
584 | val: &val); |
585 | if (ret) |
586 | return ret; |
587 | |
588 | *sfp_prsnt = !val; |
589 | return 0; |
590 | } |
591 | |
592 | static int hns_mac_get_sfp_prsnt_acpi(struct hns_mac_cb *mac_cb, int *sfp_prsnt) |
593 | { |
594 | union acpi_object *obj; |
595 | union acpi_object obj_args, argv4; |
596 | |
597 | obj_args.integer.type = ACPI_TYPE_INTEGER; |
598 | obj_args.integer.value = mac_cb->mac_id; |
599 | |
600 | argv4.type = ACPI_TYPE_PACKAGE; |
601 | argv4.package.count = 1; |
602 | argv4.package.elements = &obj_args; |
603 | |
604 | obj = acpi_evaluate_dsm_typed(ACPI_HANDLE(mac_cb->dev), |
605 | guid: &hns_dsaf_acpi_dsm_guid, rev: 0, |
606 | func: HNS_OP_GET_SFP_STAT_FUNC, argv4: &argv4, |
607 | ACPI_TYPE_INTEGER); |
608 | if (!obj) |
609 | return -ENODEV; |
610 | |
611 | *sfp_prsnt = obj->integer.value; |
612 | |
613 | ACPI_FREE(obj); |
614 | |
615 | return 0; |
616 | } |
617 | |
618 | /** |
619 | * hns_mac_config_sds_loopback - set loop back for serdes |
620 | * @mac_cb: mac control block |
621 | * @en: enable or disable |
622 | * return 0 == success |
623 | */ |
624 | static int hns_mac_config_sds_loopback(struct hns_mac_cb *mac_cb, bool en) |
625 | { |
626 | const u8 lane_id[] = { |
627 | 0, /* mac 0 -> lane 0 */ |
628 | 1, /* mac 1 -> lane 1 */ |
629 | 2, /* mac 2 -> lane 2 */ |
630 | 3, /* mac 3 -> lane 3 */ |
631 | 2, /* mac 4 -> lane 2 */ |
632 | 3, /* mac 5 -> lane 3 */ |
633 | 0, /* mac 6 -> lane 0 */ |
634 | 1 /* mac 7 -> lane 1 */ |
635 | }; |
636 | #define RX_CSR(lane, reg) ((0x4080 + (reg) * 0x0002 + (lane) * 0x0200) * 2) |
637 | u64 reg_offset = RX_CSR(lane_id[mac_cb->mac_id], 0); |
638 | |
639 | int sfp_prsnt = 0; |
640 | int ret = hns_mac_get_sfp_prsnt(mac_cb, sfp_prsnt: &sfp_prsnt); |
641 | |
642 | if (!mac_cb->phy_dev) { |
643 | if (ret) |
644 | pr_info("please confirm sfp is present or not\n" ); |
645 | else |
646 | if (!sfp_prsnt) |
647 | pr_info("no sfp in this eth\n" ); |
648 | } |
649 | |
650 | if (mac_cb->serdes_ctrl) { |
651 | u32 origin = 0; |
652 | |
653 | if (!AE_IS_VER1(mac_cb->dsaf_dev->dsaf_ver)) { |
654 | #define HILINK_ACCESS_SEL_CFG 0x40008 |
655 | /* hilink4 & hilink3 use the same xge training and |
656 | * xge u adaptor. There is a hilink access sel cfg |
657 | * register to select which one to be configed |
658 | */ |
659 | if ((!HNS_DSAF_IS_DEBUG(mac_cb->dsaf_dev)) && |
660 | (mac_cb->mac_id <= 3)) |
661 | dsaf_write_syscon(base: mac_cb->serdes_ctrl, |
662 | HILINK_ACCESS_SEL_CFG, value: 0); |
663 | else |
664 | dsaf_write_syscon(base: mac_cb->serdes_ctrl, |
665 | HILINK_ACCESS_SEL_CFG, value: 3); |
666 | } |
667 | |
668 | ret = dsaf_read_syscon(base: mac_cb->serdes_ctrl, reg: reg_offset, |
669 | val: &origin); |
670 | if (ret) |
671 | return ret; |
672 | |
673 | dsaf_set_field(origin, 1ull << 10, 10, en); |
674 | dsaf_write_syscon(base: mac_cb->serdes_ctrl, reg: reg_offset, value: origin); |
675 | } else { |
676 | u8 __iomem *base_addr = mac_cb->serdes_vaddr + |
677 | (mac_cb->mac_id <= 3 ? 0x00280000 : 0x00200000); |
678 | dsaf_set_reg_field(base: base_addr, reg: reg_offset, mask: 1ull << 10, shift: 10, val: en); |
679 | } |
680 | |
681 | return 0; |
682 | } |
683 | |
684 | static int |
685 | hns_mac_config_sds_loopback_acpi(struct hns_mac_cb *mac_cb, bool en) |
686 | { |
687 | union acpi_object *obj; |
688 | union acpi_object obj_args[3], argv4; |
689 | |
690 | obj_args[0].integer.type = ACPI_TYPE_INTEGER; |
691 | obj_args[0].integer.value = mac_cb->mac_id; |
692 | obj_args[1].integer.type = ACPI_TYPE_INTEGER; |
693 | obj_args[1].integer.value = en; |
694 | |
695 | argv4.type = ACPI_TYPE_PACKAGE; |
696 | argv4.package.count = 2; |
697 | argv4.package.elements = obj_args; |
698 | |
699 | obj = acpi_evaluate_dsm(ACPI_HANDLE(mac_cb->dsaf_dev->dev), |
700 | guid: &hns_dsaf_acpi_dsm_guid, rev: 0, |
701 | func: HNS_OP_SERDES_LP_FUNC, argv4: &argv4); |
702 | if (!obj) { |
703 | dev_warn(mac_cb->dsaf_dev->dev, "set port%d serdes lp fail!" , |
704 | mac_cb->mac_id); |
705 | |
706 | return -ENOTSUPP; |
707 | } |
708 | |
709 | ACPI_FREE(obj); |
710 | |
711 | return 0; |
712 | } |
713 | |
714 | struct dsaf_misc_op *hns_misc_op_get(struct dsaf_device *dsaf_dev) |
715 | { |
716 | struct dsaf_misc_op *misc_op; |
717 | |
718 | misc_op = devm_kzalloc(dev: dsaf_dev->dev, size: sizeof(*misc_op), GFP_KERNEL); |
719 | if (!misc_op) |
720 | return NULL; |
721 | |
722 | if (dev_of_node(dev: dsaf_dev->dev)) { |
723 | misc_op->cpld_set_led = hns_cpld_set_led; |
724 | misc_op->cpld_reset_led = cpld_led_reset; |
725 | misc_op->cpld_set_led_id = cpld_set_led_id; |
726 | |
727 | misc_op->dsaf_reset = hns_dsaf_rst; |
728 | misc_op->xge_srst = hns_dsaf_xge_srst_by_port; |
729 | misc_op->ge_srst = hns_dsaf_ge_srst_by_port; |
730 | misc_op->ppe_srst = hns_ppe_srst_by_port; |
731 | misc_op->ppe_comm_srst = hns_ppe_com_srst; |
732 | misc_op->hns_dsaf_srst_chns = hns_dsaf_srst_chns; |
733 | misc_op->hns_dsaf_roce_srst = hns_dsaf_roce_srst; |
734 | |
735 | misc_op->get_phy_if = hns_mac_get_phy_if; |
736 | misc_op->get_sfp_prsnt = hns_mac_get_sfp_prsnt; |
737 | |
738 | misc_op->cfg_serdes_loopback = hns_mac_config_sds_loopback; |
739 | } else if (is_acpi_node(fwnode: dsaf_dev->dev->fwnode)) { |
740 | misc_op->cpld_set_led = hns_cpld_set_led_acpi; |
741 | misc_op->cpld_reset_led = cpld_led_reset_acpi; |
742 | misc_op->cpld_set_led_id = cpld_set_led_id_acpi; |
743 | |
744 | misc_op->dsaf_reset = hns_dsaf_rst_acpi; |
745 | misc_op->xge_srst = hns_dsaf_xge_srst_by_port_acpi; |
746 | misc_op->ge_srst = hns_dsaf_ge_srst_by_port_acpi; |
747 | misc_op->ppe_srst = hns_ppe_srst_by_port_acpi; |
748 | misc_op->ppe_comm_srst = hns_ppe_com_srst; |
749 | misc_op->hns_dsaf_srst_chns = hns_dsaf_srst_chns_acpi; |
750 | misc_op->hns_dsaf_roce_srst = hns_dsaf_roce_srst_acpi; |
751 | |
752 | misc_op->get_phy_if = hns_mac_get_phy_if_acpi; |
753 | misc_op->get_sfp_prsnt = hns_mac_get_sfp_prsnt_acpi; |
754 | |
755 | misc_op->cfg_serdes_loopback = hns_mac_config_sds_loopback_acpi; |
756 | } else { |
757 | devm_kfree(dev: dsaf_dev->dev, p: (void *)misc_op); |
758 | misc_op = NULL; |
759 | } |
760 | |
761 | return (void *)misc_op; |
762 | } |
763 | |
764 | struct |
765 | platform_device *hns_dsaf_find_platform_device(struct fwnode_handle *fwnode) |
766 | { |
767 | struct device *dev; |
768 | |
769 | dev = bus_find_device_by_fwnode(bus: &platform_bus_type, fwnode); |
770 | return dev ? to_platform_device(dev) : NULL; |
771 | } |
772 | |