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); |
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 | } |