net/ngbe: fix external PHY power down
[dpdk.git] / drivers / net / ngbe / base / ngbe_mng.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2018-2021 Beijing WangXun Technology Co., Ltd.
3  * Copyright(c) 2010-2017 Intel Corporation
4  */
5
6 #include "ngbe_type.h"
7 #include "ngbe_mng.h"
8
9 /**
10  *  ngbe_hic_unlocked - Issue command to manageability block unlocked
11  *  @hw: pointer to the HW structure
12  *  @buffer: command to write and where the return status will be placed
13  *  @length: length of buffer, must be multiple of 4 bytes
14  *  @timeout: time in ms to wait for command completion
15  *
16  *  Communicates with the manageability block. On success return 0
17  *  else returns semaphore error when encountering an error acquiring
18  *  semaphore or NGBE_ERR_HOST_INTERFACE_COMMAND when command fails.
19  *
20  *  This function assumes that the NGBE_MNGSEM_SWMBX semaphore is held
21  *  by the caller.
22  **/
23 static s32
24 ngbe_hic_unlocked(struct ngbe_hw *hw, u32 *buffer, u32 length, u32 timeout)
25 {
26         u32 value, loop;
27         u16 i, dword_len;
28
29         if (!length || length > NGBE_PMMBX_BSIZE) {
30                 DEBUGOUT("Buffer length failure buffersize=%d.", length);
31                 return NGBE_ERR_HOST_INTERFACE_COMMAND;
32         }
33
34         /* Calculate length in DWORDs. We must be DWORD aligned */
35         if (length % sizeof(u32)) {
36                 DEBUGOUT("Buffer length failure, not aligned to dword");
37                 return NGBE_ERR_INVALID_ARGUMENT;
38         }
39
40         dword_len = length >> 2;
41
42         /* The device driver writes the relevant command block
43          * into the ram area.
44          */
45         for (i = 0; i < dword_len; i++) {
46                 wr32a(hw, NGBE_MNGMBX, i, cpu_to_le32(buffer[i]));
47                 buffer[i] = rd32a(hw, NGBE_MNGMBX, i);
48         }
49         ngbe_flush(hw);
50
51         /* Setting this bit tells the ARC that a new command is pending. */
52         wr32m(hw, NGBE_MNGMBXCTL,
53               NGBE_MNGMBXCTL_SWRDY, NGBE_MNGMBXCTL_SWRDY);
54
55         /* Check command completion */
56         loop = po32m(hw, NGBE_MNGMBXCTL,
57                 NGBE_MNGMBXCTL_FWRDY, NGBE_MNGMBXCTL_FWRDY,
58                 &value, timeout, 1000);
59         if (!loop || !(value & NGBE_MNGMBXCTL_FWACK)) {
60                 DEBUGOUT("Command has failed with no status valid.");
61                 return NGBE_ERR_HOST_INTERFACE_COMMAND;
62         }
63
64         return 0;
65 }
66
67 /**
68  *  ngbe_host_interface_command - Issue command to manageability block
69  *  @hw: pointer to the HW structure
70  *  @buffer: contains the command to write and where the return status will
71  *   be placed
72  *  @length: length of buffer, must be multiple of 4 bytes
73  *  @timeout: time in ms to wait for command completion
74  *  @return_data: read and return data from the buffer (true) or not (false)
75  *   Needed because FW structures are big endian and decoding of
76  *   these fields can be 8 bit or 16 bit based on command. Decoding
77  *   is not easily understood without making a table of commands.
78  *   So we will leave this up to the caller to read back the data
79  *   in these cases.
80  *
81  *  Communicates with the manageability block. On success return 0
82  *  else returns semaphore error when encountering an error acquiring
83  *  semaphore or NGBE_ERR_HOST_INTERFACE_COMMAND when command fails.
84  **/
85 static s32
86 ngbe_host_interface_command(struct ngbe_hw *hw, u32 *buffer,
87                                  u32 length, u32 timeout, bool return_data)
88 {
89         u32 hdr_size = sizeof(struct ngbe_hic_hdr);
90         struct ngbe_hic_hdr *resp = (struct ngbe_hic_hdr *)buffer;
91         u16 buf_len;
92         s32 err;
93         u32 bi;
94         u32 dword_len;
95
96         if (length == 0 || length > NGBE_PMMBX_BSIZE) {
97                 DEBUGOUT("Buffer length failure buffersize=%d.", length);
98                 return NGBE_ERR_HOST_INTERFACE_COMMAND;
99         }
100
101         /* Take management host interface semaphore */
102         err = hw->mac.acquire_swfw_sync(hw, NGBE_MNGSEM_SWMBX);
103         if (err)
104                 return err;
105
106         err = ngbe_hic_unlocked(hw, buffer, length, timeout);
107         if (err)
108                 goto rel_out;
109
110         if (!return_data)
111                 goto rel_out;
112
113         /* Calculate length in DWORDs */
114         dword_len = hdr_size >> 2;
115
116         /* first pull in the header so we know the buffer length */
117         for (bi = 0; bi < dword_len; bi++)
118                 buffer[bi] = rd32a(hw, NGBE_MNGMBX, bi);
119
120         /*
121          * If there is any thing in data position pull it in
122          * Read Flash command requires reading buffer length from
123          * two byes instead of one byte
124          */
125         if (resp->cmd == 0x30) {
126                 for (; bi < dword_len + 2; bi++)
127                         buffer[bi] = rd32a(hw, NGBE_MNGMBX, bi);
128
129                 buf_len = (((u16)(resp->cmd_or_resp.ret_status) << 3)
130                                   & 0xF00) | resp->buf_len;
131                 hdr_size += (2 << 2);
132         } else {
133                 buf_len = resp->buf_len;
134         }
135         if (!buf_len)
136                 goto rel_out;
137
138         if (length < buf_len + hdr_size) {
139                 DEBUGOUT("Buffer not large enough for reply message.");
140                 err = NGBE_ERR_HOST_INTERFACE_COMMAND;
141                 goto rel_out;
142         }
143
144         /* Calculate length in DWORDs, add 3 for odd lengths */
145         dword_len = (buf_len + 3) >> 2;
146
147         /* Pull in the rest of the buffer (bi is where we left off) */
148         for (; bi <= dword_len; bi++)
149                 buffer[bi] = rd32a(hw, NGBE_MNGMBX, bi);
150
151 rel_out:
152         hw->mac.release_swfw_sync(hw, NGBE_MNGSEM_SWMBX);
153
154         return err;
155 }
156
157 /**
158  *  ngbe_hic_sr_read - Read EEPROM word using a host interface cmd
159  *  assuming that the semaphore is already obtained.
160  *  @hw: pointer to hardware structure
161  *  @offset: offset of  word in the EEPROM to read
162  *  @data: word read from the EEPROM
163  *
164  *  Reads a 16 bit word from the EEPROM using the hostif.
165  **/
166 s32 ngbe_hic_sr_read(struct ngbe_hw *hw, u32 addr, u8 *buf, int len)
167 {
168         struct ngbe_hic_read_shadow_ram command;
169         u32 value;
170         int err, i = 0, j = 0;
171
172         if (len > NGBE_PMMBX_DATA_SIZE)
173                 return NGBE_ERR_HOST_INTERFACE_COMMAND;
174
175         memset(&command, 0, sizeof(command));
176         command.hdr.req.cmd = FW_READ_SHADOW_RAM_CMD;
177         command.hdr.req.buf_lenh = 0;
178         command.hdr.req.buf_lenl = FW_READ_SHADOW_RAM_LEN;
179         command.hdr.req.checksum = FW_DEFAULT_CHECKSUM;
180         command.address = cpu_to_be32(addr);
181         command.length = cpu_to_be16(len);
182
183         err = ngbe_hic_unlocked(hw, (u32 *)&command,
184                         sizeof(command), NGBE_HI_COMMAND_TIMEOUT);
185         if (err)
186                 return err;
187
188         while (i < (len >> 2)) {
189                 value = rd32a(hw, NGBE_MNGMBX, FW_NVM_DATA_OFFSET + i);
190                 ((u32 *)buf)[i] = value;
191                 i++;
192         }
193
194         value = rd32a(hw, NGBE_MNGMBX, FW_NVM_DATA_OFFSET + i);
195         for (i <<= 2; i < len; i++)
196                 ((u8 *)buf)[i] = ((u8 *)&value)[j++];
197
198         return 0;
199 }
200
201 /**
202  *  ngbe_hic_sr_write - Write EEPROM word using hostif
203  *  @hw: pointer to hardware structure
204  *  @offset: offset of  word in the EEPROM to write
205  *  @data: word write to the EEPROM
206  *
207  *  Write a 16 bit word to the EEPROM using the hostif.
208  **/
209 s32 ngbe_hic_sr_write(struct ngbe_hw *hw, u32 addr, u8 *buf, int len)
210 {
211         struct ngbe_hic_write_shadow_ram command;
212         u32 value;
213         int err = 0, i = 0, j = 0;
214
215         if (len > NGBE_PMMBX_DATA_SIZE)
216                 return NGBE_ERR_HOST_INTERFACE_COMMAND;
217
218         memset(&command, 0, sizeof(command));
219         command.hdr.req.cmd = FW_WRITE_SHADOW_RAM_CMD;
220         command.hdr.req.buf_lenh = 0;
221         command.hdr.req.buf_lenl = FW_WRITE_SHADOW_RAM_LEN;
222         command.hdr.req.checksum = FW_DEFAULT_CHECKSUM;
223         command.address = cpu_to_be32(addr);
224         command.length = cpu_to_be16(len);
225
226         while (i < (len >> 2)) {
227                 value = ((u32 *)buf)[i];
228                 wr32a(hw, NGBE_MNGMBX, FW_NVM_DATA_OFFSET + i, value);
229                 i++;
230         }
231
232         for (i <<= 2; i < len; i++)
233                 ((u8 *)&value)[j++] = ((u8 *)buf)[i];
234
235         wr32a(hw, NGBE_MNGMBX, FW_NVM_DATA_OFFSET + (i >> 2), value);
236
237         UNREFERENCED_PARAMETER(&command);
238
239         return err;
240 }
241
242 s32 ngbe_hic_pcie_read(struct ngbe_hw *hw, u16 addr, u32 *buf, int len)
243 {
244         struct ngbe_hic_read_pcie command;
245         u32 value = 0;
246         int err, i = 0;
247
248         if (len > NGBE_PMMBX_DATA_SIZE)
249                 return NGBE_ERR_HOST_INTERFACE_COMMAND;
250
251         memset(&command, 0, sizeof(command));
252         command.hdr.cmd = FW_PCIE_READ_CMD;
253         command.hdr.buf_len = sizeof(command) - sizeof(command.hdr);
254         command.hdr.checksum = FW_DEFAULT_CHECKSUM;
255         command.lan_id = hw->bus.lan_id;
256         command.addr = addr;
257
258         err = ngbe_host_interface_command(hw, (u32 *)&command,
259                         sizeof(command), NGBE_HI_COMMAND_TIMEOUT, false);
260         if (err)
261                 return err;
262
263         while (i < (len >> 2)) {
264                 value = rd32a(hw, NGBE_MNGMBX, FW_PCIE_BUSMASTER_OFFSET + i);
265                 ((u32 *)buf)[i] = value;
266                 i++;
267         }
268
269         return 0;
270 }
271
272 s32 ngbe_hic_pcie_write(struct ngbe_hw *hw, u16 addr, u32 *buf, int len)
273 {
274         struct ngbe_hic_write_pcie command;
275         u32 value = 0;
276         int err, i = 0;
277
278         while (i < (len >> 2)) {
279                 value = ((u32 *)buf)[i];
280                 i++;
281         }
282
283         memset(&command, 0, sizeof(command));
284         command.hdr.cmd = FW_PCIE_WRITE_CMD;
285         command.hdr.buf_len = sizeof(command) - sizeof(command.hdr);
286         command.hdr.checksum = FW_DEFAULT_CHECKSUM;
287         command.lan_id = hw->bus.lan_id;
288         command.addr = addr;
289         command.data = value;
290
291         err = ngbe_host_interface_command(hw, (u32 *)&command,
292                         sizeof(command), NGBE_HI_COMMAND_TIMEOUT, false);
293         if (err)
294                 return err;
295
296         return 0;
297 }
298
299 s32 ngbe_hic_check_cap(struct ngbe_hw *hw)
300 {
301         struct ngbe_hic_read_shadow_ram command;
302         s32 err;
303         int i;
304
305         command.hdr.req.cmd = FW_EEPROM_CHECK_STATUS;
306         command.hdr.req.buf_lenh = 0;
307         command.hdr.req.buf_lenl = 0;
308         command.hdr.req.checksum = FW_DEFAULT_CHECKSUM;
309
310         /* convert offset from words to bytes */
311         command.address = 0;
312         /* one word */
313         command.length = 0;
314
315         for (i = 0; i <= FW_CEM_MAX_RETRIES; i++) {
316                 err = ngbe_host_interface_command(hw, (u32 *)&command,
317                                 sizeof(command),
318                                 NGBE_HI_COMMAND_TIMEOUT, true);
319                 if (err)
320                         continue;
321
322                 command.hdr.rsp.ret_status &= 0x1F;
323                 if (command.hdr.rsp.ret_status !=
324                         FW_CEM_RESP_STATUS_SUCCESS)
325                         err = NGBE_ERR_HOST_INTERFACE_COMMAND;
326
327                 break;
328         }
329
330         if (!err && command.address != FW_CHECKSUM_CAP_ST_PASS)
331                 err = NGBE_ERR_EEPROM_CHECKSUM;
332
333         return err;
334 }
335
336 s32 ngbe_phy_led_oem_chk(struct ngbe_hw *hw, u32 *data)
337 {
338         struct ngbe_hic_read_shadow_ram command;
339         s32 err;
340         int i;
341
342         command.hdr.req.cmd = FW_PHY_LED_CONF;
343         command.hdr.req.buf_lenh = 0;
344         command.hdr.req.buf_lenl = 0;
345         command.hdr.req.checksum = FW_DEFAULT_CHECKSUM;
346
347         /* convert offset from words to bytes */
348         command.address = 0;
349         /* one word */
350         command.length = 0;
351
352         for (i = 0; i <= FW_CEM_MAX_RETRIES; i++) {
353                 err = ngbe_host_interface_command(hw, (u32 *)&command,
354                                 sizeof(command),
355                                 NGBE_HI_COMMAND_TIMEOUT, true);
356                 if (err)
357                         continue;
358
359                 command.hdr.rsp.ret_status &= 0x1F;
360                 if (command.hdr.rsp.ret_status !=
361                         FW_CEM_RESP_STATUS_SUCCESS)
362                         err = NGBE_ERR_HOST_INTERFACE_COMMAND;
363
364                 break;
365         }
366
367         if (err)
368                 return err;
369
370         if (command.address == FW_CHECKSUM_CAP_ST_PASS) {
371                 *data = ((u32 *)&command)[2];
372                 err = 0;
373         } else if (command.address == FW_CHECKSUM_CAP_ST_FAIL) {
374                 *data = FW_CHECKSUM_CAP_ST_FAIL;
375                 err = -1;
376         } else {
377                 err = NGBE_ERR_EEPROM_CHECKSUM;
378         }
379
380         return err;
381 }