blob: f40c3b0d488738cc1d696edccb2716ea552784e6 [file] [log] [blame]
developer122ffbb2022-11-14 12:07:10 +08001diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
2index 7b49c94..5a79af2 100644
3--- a/drivers/net/phy/Kconfig
4+++ b/drivers/net/phy/Kconfig
5@@ -372,7 +372,38 @@ config AMD_PHY
6 config AQUANTIA_PHY
7 tristate "Aquantia PHYs"
8 ---help---
9- Currently supports the Aquantia AQ1202, AQ2104, AQR105, AQR405
10+ Currently supports the Aquantia AQ1202, AQ2104, AQR105, AQR405, AQR113C
11+
12+config AQUANTIA_PHY_FW_DOWNLOAD
13+ tristate "Firmware Download Enable"
14+ depends on AQUANTIA_PHY
15+ ---help---
16+ Currently supports the Aquantia AQR113C
17+
18+choice
19+ prompt "Download mode"
20+ default AQUANTIA_PHY_FW_DOWNLOAD_GANG
21+ depends on AQUANTIA_PHY_FW_DOWNLOAD
22+
23+ config AQUANTIA_PHY_FW_DOWNLOAD_SINGLE
24+ bool "Single"
25+ ---help---
26+ If you would like to download firmware in sequential way,
27+ please select this option.
28+
29+ config AQUANTIA_PHY_FW_DOWNLOAD_GANG
30+ bool "Gang"
31+ ---help---
32+ If you would like to download firmware in parallel way,
33+ please select this option.
34+endchoice
35+
36+config AQUANTIA_PHY_FW_FILE
37+ string "FW File"
38+ depends on AQUANTIA_PHY
39+ default "Rhe-05.06-Candidate7-AQR_Mediatek_23B_StartOff_ID45623_VER36657.cld"
40+ ---help---
41+ Currently supports the Aquantia AQR113c
42
43 config AX88796B_PHY
44 tristate "Asix PHYs"
45diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
46index 043a697..4f67110 100644
47--- a/drivers/net/phy/Makefile
48+++ b/drivers/net/phy/Makefile
49@@ -67,6 +67,9 @@ aquantia-objs += aquantia_main.o
50 ifdef CONFIG_HWMON
51 aquantia-objs += aquantia_hwmon.o
52 endif
53+ifdef CONFIG_AQUANTIA_PHY_FW_DOWNLOAD
54+aquantia-objs += aquantia_firmware.o
55+endif
56 obj-$(CONFIG_AIROHA_EN8801S_PHY) += en8801s.o
57 obj-$(CONFIG_AIROHA_EN8801SC_PHY) += en8801sc.o
58 obj-$(CONFIG_AQUANTIA_PHY) += aquantia.o
59diff --git a/drivers/net/phy/aquantia.h b/drivers/net/phy/aquantia.h
60index 5a16caa..912bbe6 100644
61--- a/drivers/net/phy/aquantia.h
62+++ b/drivers/net/phy/aquantia.h
63@@ -9,8 +9,53 @@
64 #include <linux/device.h>
65 #include <linux/phy.h>
66
67+/* MDIO_MMD_C22EXT */
68+#define MDIO_C22EXT_STAT_SGMII_RX_GOOD_FRAMES 0xd292
69+#define MDIO_C22EXT_STAT_SGMII_RX_BAD_FRAMES 0xd294
70+#define MDIO_C22EXT_STAT_SGMII_RX_FALSE_CARRIER 0xd297
71+#define MDIO_C22EXT_STAT_SGMII_TX_GOOD_FRAMES 0xd313
72+#define MDIO_C22EXT_STAT_SGMII_TX_BAD_FRAMES 0xd315
73+#define MDIO_C22EXT_STAT_SGMII_TX_FALSE_CARRIER 0xd317
74+#define MDIO_C22EXT_STAT_SGMII_TX_COLLISIONS 0xd318
75+#define MDIO_C22EXT_STAT_SGMII_TX_LINE_COLLISIONS 0xd319
76+#define MDIO_C22EXT_STAT_SGMII_TX_FRAME_ALIGN_ERR 0xd31a
77+#define MDIO_C22EXT_STAT_SGMII_TX_RUNT_FRAMES 0xd31b
78+
79+struct aqr107_hw_stat {
80+ const char *name;
81+ int reg;
82+ int size;
83+};
84+
85+#define SGMII_STAT(n, r, s) { n, MDIO_C22EXT_STAT_SGMII_ ## r, s }
86+static const struct aqr107_hw_stat aqr107_hw_stats[] = {
87+ SGMII_STAT("sgmii_rx_good_frames", RX_GOOD_FRAMES, 26),
88+ SGMII_STAT("sgmii_rx_bad_frames", RX_BAD_FRAMES, 26),
89+ SGMII_STAT("sgmii_rx_false_carrier_events", RX_FALSE_CARRIER, 8),
90+ SGMII_STAT("sgmii_tx_good_frames", TX_GOOD_FRAMES, 26),
91+ SGMII_STAT("sgmii_tx_bad_frames", TX_BAD_FRAMES, 26),
92+ SGMII_STAT("sgmii_tx_false_carrier_events", TX_FALSE_CARRIER, 8),
93+ SGMII_STAT("sgmii_tx_collisions", TX_COLLISIONS, 8),
94+ SGMII_STAT("sgmii_tx_line_collisions", TX_LINE_COLLISIONS, 8),
95+ SGMII_STAT("sgmii_tx_frame_alignment_err", TX_FRAME_ALIGN_ERR, 16),
96+ SGMII_STAT("sgmii_tx_runt_frames", TX_RUNT_FRAMES, 22),
97+};
98+#define AQR107_SGMII_STAT_SZ ARRAY_SIZE(aqr107_hw_stats)
99+
100+struct aqr107_priv {
101+ u64 sgmii_stats[AQR107_SGMII_STAT_SZ];
102+#ifdef CONFIG_AQUANTIA_PHY_FW_DOWNLOAD
103+ struct phy_device *phydevs[1];
104+ bool fw_initialized;
105+#endif
106+};
107+
108 #if IS_REACHABLE(CONFIG_HWMON)
109 int aqr_hwmon_probe(struct phy_device *phydev);
110 #else
111 static inline int aqr_hwmon_probe(struct phy_device *phydev) { return 0; }
112 #endif
113+
114+#ifdef CONFIG_AQUANTIA_PHY_FW_DOWNLOAD
115+int aqr_firmware_download(struct phy_device *phydev);
116+#endif
117diff --git a/drivers/net/phy/aquantia_firmware.c b/drivers/net/phy/aquantia_firmware.c
118new file mode 100644
119index 0000000..7aeec86
120--- /dev/null
121+++ b/drivers/net/phy/aquantia_firmware.c
122@@ -0,0 +1,982 @@
123+// SPDX-License-Identifier: GPL-2.0
124+/* FW download driver for Aquantia PHY
125+ */
126+
127+#include <linux/phy.h>
128+#include <linux/of.h>
129+#include <linux/device.h>
130+#include <linux/firmware.h>
131+#include <linux/kthread.h>
132+
133+#include "aquantia.h"
134+
135+#undef AQ_VERBOSE
136+
137+#ifdef CONFIG_AQUANTIA_PHY_FW_DOWNLOAD_SINGLE
138+#define MAX_GANGLOAD_DEVICES 1
139+#elif CONFIG_AQUANTIA_PHY_FW_DOWNLOAD_GANG
140+#define MAX_GANGLOAD_DEVICES 2
141+#endif
142+
143+#define AQR_FIRMWARE CONFIG_AQUANTIA_PHY_FW_FILE
144+
145+/* Vendor specific 1, MDIO_MMD_VEND1 */
146+#define VEND1_STD_CONTROL1 0x0000
147+#define VEND1_STD_CONTROL1_SOFT_RESET BIT(15)
148+
149+#define VEND1_MAILBOX_INTERFACE1 0x0200
150+#define VEND1_MAILBOX_INTERFACE1_START BIT(15)
151+#define VEND1_MAILBOX_INTERFACE1_WRITE FIELD_PREP(BIT(14), 1)
152+#define VEND1_MAILBOX_INTERFACE1_READ FIELD_PREP(BIT(14), 0)
153+#define VEND1_MAILBOX_INTERFACE1_RESET_CRC BIT(12)
154+
155+#define VEND1_MAILBOX_INTERFACE2 0x0201
156+#define VEND1_MAILBOX_INTERFACE2_CRC GENMASK(15, 0)
157+
158+#define VEND1_MAILBOX_INTERFACE3 0x0202
159+#define VEND1_MAILBOX_INTERFACE3_ADDR_MSW GENMASK(15, 0)
160+
161+#define VEND1_MAILBOX_INTERFACE4 0x0203
162+#define VEND1_MAILBOX_INTERFACE4_ADDR_LSW GENMASK(15, 2)
163+
164+#define VEND1_MAILBOX_INTERFACE5 0x0204
165+#define VEND1_MAILBOX_INTERFACE5_DATA_MSW GENMASK(15, 0)
166+
167+#define VEND1_MAILBOX_INTERFACE6 0x0205
168+#define VEND1_MAILBOX_INTERFACE6_DATA_LSW GENMASK(15, 0)
169+
170+#define VEND1_CONTROL2 0xc001
171+#define VEND1_CONTROL2_UP_RESET BIT(15)
172+#define VEND1_CONTROL2_UP_RUNSTALL_OVERRIDE BIT(6)
173+#define VEND1_CONTROL2_UP_RUNSTALL BIT(0)
174+
175+#define VEND1_RESET_CONTROL 0xc006
176+#define VEND1_RESET_CONTROL_MMD_RESET_DISABLE BIT(14)
177+
178+#define VEND1_GENERAL_PROV2 0xc441
179+#define VEND1_GENERAL_PROV2_MDIO_BROADCAST_ENABLE BIT(14)
180+
181+#define VEND1_GENERAL_PROV8 0xc447
182+#define VEND1_GENERAL_PROV8_MDIO_BROADCAST_ADDRESS GENMASK(4, 0)
183+
184+#define VEND1_NVR_PROV3 0xc452
185+#define VEND1_NVR_PROV3_DAISYCHAIN_DISABLE BIT(0)
186+
187+#define VEND1_RSVD_PROV2 0xc471
188+#define VEND1_RSVD_PROV2_DAISYCHAIN_HOPCOUNT GENMASK(5, 0)
189+#define VEND1_RSVD_PROV2_DAISYCHAIN_HOPCOUNT_OVERRIDE BIT(6)
190+
191+/*! The byte address, in processor memory, of the start of the IRAM segment. */
192+#define AQ_IRAM_BASE_ADDRESS 0x40000000
193+
194+/*! The byte address, in processor memory, of the start of the DRAM segment. */
195+#define AQ_DRAM_BASE_ADDRESS 0x3FFE0000
196+
197+/*! The byte offset from the top of the PHY image to the header content (HHD & EUR devices). */
198+#define AQ_PHY_IMAGE_HEADER_CONTENT_OFFSET_HHD 0x300
199+
200+/*! The offset, from the start of DRAM, where the provisioning block begins. */
201+#define AQ_PHY_IMAGE_PROVTABLE_OFFSET 0x680
202+
203+/*! The offset, from the start of DRAM, where the provisioning block's ending address is recorded. */
204+#define AQ_PHY_IMAGE_PROVTABLE_TERM_OFFSET 0x028C
205+
206+/*! The size of the space alloted within the PHY image for the provisioning table. */
207+#define AQ_PHY_IMAGE_PROVTABLE_MAXSIZE 0x800
208+
209+/*! The maximum number of ports that can be MDIO bootloaded at once. */
210+#define AQ_MAX_NUM_PHY_IDS 48
211+
212+/*! This enumeration is used to describe the different types of
213+ Aquantia PHY.*/
214+typedef enum
215+{
216+ /*! 1/2/4-port package, 40nm architechture.*/
217+ AQ_DEVICE_APPIA,
218+ /*! 1/2/4-port package, first-generation 28nm architechture.*/
219+ AQ_DEVICE_HHD,
220+ /*! 1/2/4-port package, second-generation 28nm architechture.*/
221+ AQ_DEVICE_EUR,
222+ /*! 1/2/4-port package, third-generation 28nm architechture.*/
223+ AQ_DEVICE_CAL,
224+ /*! 1/2/4/8-port package, forth-generation 14nm architechture.*/
225+ AQ_DEVICE_RHEA,
226+ /*! 8-port package, fifth-generation 14nm architechture.*/
227+ AQ_DEVICE_DIONE
228+} AQ_API_Device;
229+
230+/*! The table used to compute CRC's within the PHY. */
231+const uint16_t AQ_CRC16Table[256] = {0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
232+ 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
233+ 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
234+ 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
235+ 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
236+ 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
237+ 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
238+ 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
239+ 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
240+ 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
241+ 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
242+ 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
243+ 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
244+ 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
245+ 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
246+ 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
247+ 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
248+ 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
249+ 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
250+ 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
251+ 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
252+ 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
253+ 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
254+ 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
255+ 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
256+ 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
257+ 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
258+ 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
259+ 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
260+ 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
261+ 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
262+ 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0};
263+
264+struct task_struct *gangload_kthread = NULL;
265+struct phy_device *gangload_phydevs[MAX_GANGLOAD_DEVICES];
266+static int gangload = 0;
267+
268+void AQ_API_EnableMDIO_BootLoadMode
269+(
270+ /*! The target PHY port.*/
271+ struct phy_device *phydev,
272+ /*! The provisioning address to use when the FW starts and applies the
273+ * bootloaded image's provisioned values. */
274+ unsigned int provisioningAddress
275+)
276+{
277+ uint16_t globalNvrProvisioning;
278+ uint16_t globalReservedProvisioning;
279+
280+ /* disable the daisy-chain */
281+ globalNvrProvisioning = phy_read_mmd(phydev, MDIO_MMD_VEND1, VEND1_NVR_PROV3);
282+ globalNvrProvisioning |= VEND1_NVR_PROV3_DAISYCHAIN_DISABLE;
283+ phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_NVR_PROV3, globalNvrProvisioning);
284+
285+ /* override the hop-count */
286+ globalReservedProvisioning = phy_read_mmd(phydev, MDIO_MMD_VEND1, VEND1_RSVD_PROV2);
287+ globalReservedProvisioning &= ~VEND1_RSVD_PROV2_DAISYCHAIN_HOPCOUNT;
288+ globalReservedProvisioning |= FIELD_PREP(VEND1_RSVD_PROV2_DAISYCHAIN_HOPCOUNT,
289+ provisioningAddress);
290+ globalReservedProvisioning |= VEND1_RSVD_PROV2_DAISYCHAIN_HOPCOUNT_OVERRIDE;
291+ phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_RSVD_PROV2, globalReservedProvisioning);
292+
293+ return;
294+}
295+
296+/*! Prepare the specified port for MDIO bootloading, and set the temporary MDIO
297+ * address to be used during the bootload process. Disables the daisy-chain,
298+ * and explicitly sets the port's provisioningAddress. */
299+void AQ_API_EnableGangLoadMode
300+(
301+ /*! The target PHY port.*/
302+ struct phy_device *phydev,
303+ /*! The PHY's MDIO address will be changed to this value during the
304+ * bootload process. */
305+ unsigned int gangLoadAddress
306+)
307+{
308+ uint16_t globalGeneralProvisioning;
309+
310+ /* Enable gangload mode. After doing this, the PHY will be
311+ * addressable at the MDIO address indicated by gangLoadAddress.
312+ * Now that the PHY is in gangload mode, MDIO reads are prohibited
313+ * until AQ_API_DisableGangLoadMode is called. */
314+ globalGeneralProvisioning = phy_read_mmd(phydev, MDIO_MMD_VEND1, VEND1_GENERAL_PROV8);
315+ globalGeneralProvisioning &= ~VEND1_GENERAL_PROV8_MDIO_BROADCAST_ADDRESS;
316+ globalGeneralProvisioning |= FIELD_PREP(VEND1_GENERAL_PROV8_MDIO_BROADCAST_ADDRESS,
317+ gangLoadAddress);
318+ phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_GENERAL_PROV8, globalGeneralProvisioning);
319+
320+ globalGeneralProvisioning = phy_read_mmd(phydev, MDIO_MMD_VEND1, VEND1_GENERAL_PROV2);
321+ globalGeneralProvisioning |= VEND1_GENERAL_PROV2_MDIO_BROADCAST_ENABLE;
322+ phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_GENERAL_PROV2, globalGeneralProvisioning);
323+
324+ return;
325+}
326+
327+/*! Restore the PHY's MDIO address to the pin-specified value. Should be
328+ * called when MDIO bootloading is complete, to return to normal MDIO
329+ * addressing.
330+ * <b>This is a gang-load function, hence write-only!</b> */
331+void AQ_API_DisableGangLoadMode
332+(
333+ /*! The target PHY port.*/
334+ struct phy_device *phydev,
335+ /*! The value to write to of AQ_GlobalGeneralProvisioning.u1.word_1. */
336+ uint16_t origVal_GGP1
337+)
338+{
339+ uint16_t globalGeneralProvisioning;
340+
341+ /* Restore the original value of globalGeneralProvisioning.u1, and set
342+ * the MDIO address reset bit. This will cause the MDIO address to be
343+ * reset to the value indicated by the pins. */
344+ globalGeneralProvisioning = origVal_GGP1;
345+ globalGeneralProvisioning &= ~VEND1_GENERAL_PROV2_MDIO_BROADCAST_ENABLE;
346+ phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_GENERAL_PROV2, globalGeneralProvisioning);
347+
348+ /* The PHY has now exited gang-load mode. */
349+ return;
350+}
351+
352+/* Common implementation of MDIO bootload routine, for the entry points:
353+ * AQ_API_WriteBootLoadImage
354+ * AQ_API_WriteBootLoadImageWithProvTable
355+ * AQ_API_WriteBootLoadImageDRAMOnly
356+ * AQ_API_WriteBootLoadImageWithProvTableDRAMOnly */
357+static int AQ_API_WriteBootLoadImage_impl
358+(
359+ struct phy_device **phydevs,
360+ int num_phydevs,
361+ struct phy_device *gandload_phydev,
362+ int *result,
363+ const uint32_t* imageSizePointer,
364+ const uint8_t* image,
365+ const uint32_t* provTableSizePointer,
366+ const uint8_t* provTableImage,
367+ bool dramOnly
368+)
369+{
370+ uint32_t primaryHeaderPtr = 0x00000000;
371+ uint32_t primaryIramPtr = 0x00000000;
372+ uint32_t primaryDramPtr = 0x00000000;
373+ uint32_t primaryIramSize = 0x00000000;
374+ uint32_t primaryDramSize = 0x00000000;
375+ uint32_t terminatorPtr = 0x00000000;
376+ uint32_t phyImageHeaderContentOffset = 0x00000000;
377+ uint32_t i, j;
378+ uint32_t imageSize;
379+ uint32_t provTableImageSize = 0;
380+ uint32_t bytePointer;
381+ uint32_t byteSize;
382+ uint32_t dWordSize;
383+#ifdef AQ_PHY_SUPPORTS_BLOCK_READ_WRITE
384+ uint32_t countPendingOps; /* A count of block MDIO operation pending... necessary to keep a count
385+ in order to ensure we don't exceed the maximum pending operations. */
386+#endif
387+ uint16_t globalControl;
388+ uint16_t msw;
389+ uint16_t lsw;
390+ uint16_t crc16Calculated;
391+ uint16_t provTableCrc16Calculated;
392+ uint16_t fileCRC;
393+ uint16_t provTableFileCRC;
394+ uint16_t mailboxCRC;
395+ uint16_t mailboxWrite;
396+ uint16_t recordedGGP1Values[AQ_MAX_NUM_PHY_IDS]; /* When entering/exiting gangload mode, we record and restore
397+ the AQ_GlobalGeneralProvisioning.u1 register values. */
398+
399+ /* store the CRC-16 for the image, which is the last two bytes */
400+ imageSize = *imageSizePointer;
401+
402+ /*
403+ * If the imageSize is less than 2, we don't do anything
404+ */
405+ if (imageSize < 2) {
406+ result[0] = -EINVAL;
407+ return -EINVAL;
408+ }
409+
410+ fileCRC = image[imageSize-2] << 8 | image[imageSize-1];
411+
412+ /*------------------------------------- Check the image integrity ------------------------------------------------*/
413+ crc16Calculated = 0x0000;
414+ for (i = 0; i < imageSize-2; i++)
415+ {
416+ crc16Calculated = ((crc16Calculated & 0xFF) << 8) ^ AQ_CRC16Table[(crc16Calculated >> 8) ^ image[i]];
417+ }
418+
419+ if (crc16Calculated != fileCRC)
420+ {
421+ phydev_err(phydevs[0], "CRC check failed on image file (expected 0x%X, found 0x%X)\n",
422+ fileCRC, crc16Calculated);
423+ result[0] = -EINVAL;
424+ return -EINVAL;
425+ }
426+ else
427+ {
428+ phydev_info(phydevs[0], "CRC check good on image file (0x%04X)\n", crc16Calculated);
429+ }
430+
431+ /*-------------------------------- Check the provisioning table image integrity ----------------------------------*/
432+ if (provTableSizePointer != NULL && provTableImage != NULL)
433+ {
434+ provTableImageSize = (*provTableSizePointer) - 2;
435+ provTableFileCRC = provTableImage[provTableImageSize + 1] << 8 |
436+ provTableImage[provTableImageSize];
437+
438+ provTableCrc16Calculated = 0x0000;
439+ for (i = 0; i < provTableImageSize; i++)
440+ {
441+ provTableCrc16Calculated = ((provTableCrc16Calculated & 0xFF) << 8) ^
442+ AQ_CRC16Table[(provTableCrc16Calculated >> 8) ^ provTableImage[i]];
443+ }
444+
445+ if (provTableCrc16Calculated != provTableFileCRC)
446+ {
447+ phydev_err(phydevs[0], "CRC check failed on provisioning table file (expected 0x%X, found 0x%X)\n",
448+ provTableFileCRC, provTableCrc16Calculated);
449+ result[0] = -EINVAL;
450+ return -EINVAL;
451+ }
452+ else
453+ {
454+ phydev_info(phydevs[0], "CRC check good on provisioning table file (0x%04X)\n",
455+ provTableCrc16Calculated);
456+ }
457+ }
458+
459+ /*--------------------------- Store 1E.C441 values for later use. Enforce uniformity. ---------------------------*/
460+ for (j = 0; j < num_phydevs; j++)
461+ {
462+ /* Record the original value of AQ_GlobalGeneralProvisioning.u1.word_1,
463+ * so that we can restore it later after exiting gangload mode. */
464+ recordedGGP1Values[j] = phy_read_mmd(phydevs[j], MDIO_MMD_VEND1, VEND1_GENERAL_PROV2);
465+
466+ /* If any of the PHYs' GGP1 values don't match the others, set the appropriate
467+ * error code and return. */
468+ if (j > 0 && recordedGGP1Values[j] != recordedGGP1Values[0])
469+ {
470+ phydev_err(phydevs[j], "Non-uniform value of 1E.C441 found (expected 0x%X, found 0x%X)\n",
471+ recordedGGP1Values[0], recordedGGP1Values[j]);
472+ result[j] = -EINVAL;
473+ return -EINVAL;
474+ }
475+ }
476+
477+ /*--------------------------- Put each PHY into gangload mode at the specified address ---------------------------*/
478+ for (j = 0; j < num_phydevs; j++) {
479+ AQ_API_EnableMDIO_BootLoadMode(phydevs[j], 0);
480+ AQ_API_EnableGangLoadMode(phydevs[j], gandload_phydev->mdio.addr);
481+ }
482+
483+ /*------------------------------------- Stall the uP ------------------------------------------------------------*/
484+ globalControl = 0x0000;
485+ globalControl |= VEND1_CONTROL2_UP_RUNSTALL_OVERRIDE;
486+ globalControl |= VEND1_CONTROL2_UP_RUNSTALL;
487+ phy_write_mmd(gandload_phydev, MDIO_MMD_VEND1, VEND1_CONTROL2, globalControl);
488+
489+ /*------------------------------------- Initialize the mailbox write command -------------------------------------*/
490+ mailboxWrite = 0x0000;
491+ mailboxWrite |= VEND1_MAILBOX_INTERFACE1_WRITE;
492+ mailboxWrite |= VEND1_MAILBOX_INTERFACE1_START;
493+
494+ /*------------------------------------- Read the segment addresses and sizes -------------------------------------*/
495+ primaryHeaderPtr = (((image[0x9] & 0x0F) << 8) | image[0x8]) << 12;
496+
497+ /* setup image header content offset for HHD/EUR/CAL/RHEA */
498+ phyImageHeaderContentOffset = AQ_PHY_IMAGE_HEADER_CONTENT_OFFSET_HHD;
499+
500+ primaryIramPtr = (image[primaryHeaderPtr + phyImageHeaderContentOffset + 0x4 + 2] << 16) |
501+ (image[primaryHeaderPtr + phyImageHeaderContentOffset + 0x4 + 1] << 8) |
502+ image[primaryHeaderPtr + phyImageHeaderContentOffset + 0x4];
503+ primaryIramSize = (image[primaryHeaderPtr + phyImageHeaderContentOffset + 0x7 + 2] << 16) |
504+ (image[primaryHeaderPtr + phyImageHeaderContentOffset + 0x7 + 1] << 8) |
505+ image[primaryHeaderPtr + phyImageHeaderContentOffset + 0x7];
506+ primaryDramPtr = (image[primaryHeaderPtr + phyImageHeaderContentOffset + 0xA + 2] << 16) |
507+ (image[primaryHeaderPtr + phyImageHeaderContentOffset + 0xA + 1] << 8) |
508+ image[primaryHeaderPtr + phyImageHeaderContentOffset + 0xA];
509+ primaryDramSize = (image[primaryHeaderPtr + phyImageHeaderContentOffset + 0xD + 2] << 16) |
510+ (image[primaryHeaderPtr + phyImageHeaderContentOffset + 0xD + 1] << 8) |
511+ image[primaryHeaderPtr + phyImageHeaderContentOffset + 0xD];
512+
513+ /* setup primary image pointer for HHD/EUR/CAL/RHEA */
514+ primaryIramPtr += primaryHeaderPtr;
515+ primaryDramPtr += primaryHeaderPtr;
516+
517+ phydev_info(gandload_phydev, "Segment Addresses and Sizes as read from the PHY ROM image header:\n");
518+ phydev_info(gandload_phydev, "Primary Iram Address: 0x%x\n", primaryIramPtr);
519+ phydev_info(gandload_phydev, "Primary Iram Size: 0x%x\n", primaryIramSize);
520+ phydev_info(gandload_phydev, "Primary Dram Address: 0x%x\n", primaryDramPtr);
521+ phydev_info(gandload_phydev, "Primary Dram Size: 0x%x\n", primaryDramSize);
522+
523+ /*------------------ Prepare to merge the provisioning table into the main image ---------------------------------*/
524+ if (provTableSizePointer != NULL && provTableImage != NULL)
525+ {
526+ /* Locate the terminator of the built-in provisioning table */
527+ terminatorPtr = primaryDramPtr +
528+ ((image[primaryDramPtr + AQ_PHY_IMAGE_PROVTABLE_TERM_OFFSET + 1] << 8) |
529+ image[primaryDramPtr + AQ_PHY_IMAGE_PROVTABLE_TERM_OFFSET]);
530+
531+ phydev_info(gandload_phydev, "Supplied Provisioning Table At Address: 0x%x\n\n", terminatorPtr);
532+
533+ /* Check that the supplied provisioning table will fit within the alloted
534+ * space. */
535+ if (terminatorPtr - (primaryDramPtr + AQ_PHY_IMAGE_PROVTABLE_OFFSET) +
536+ provTableImageSize > AQ_PHY_IMAGE_PROVTABLE_MAXSIZE)
537+ {
538+ result[0] = -EINVAL;
539+ return -EINVAL;
540+ }
541+ }
542+
543+ /*------------------------------------- Load IRAM and DRAM -------------------------------------------------------*/
544+ /* clear the mailbox CRC */
545+ phy_write_mmd(gandload_phydev, MDIO_MMD_VEND1, VEND1_MAILBOX_INTERFACE1, VEND1_MAILBOX_INTERFACE1_RESET_CRC);
546+ phy_write_mmd(gandload_phydev, MDIO_MMD_VEND1, VEND1_MAILBOX_INTERFACE1, 0x0000);
547+
548+ crc16Calculated = 0; /* This is to calculate what was written through the mailbox */
549+
550+ if (!dramOnly)
551+ {
552+ /* load the IRAM */
553+ phydev_info(gandload_phydev, "Loading IRAM:\n");
554+
555+ /* dWord align the address: note the image addressing is byte based, but is properly aligned on dWord
556+ boundaries, so the 2 LSbits of the block start are always zero. */
557+ msw = (uint16_t) (AQ_IRAM_BASE_ADDRESS >> 16);
558+ lsw = (AQ_IRAM_BASE_ADDRESS & 0xFFFF) >> 2;
559+ phy_write_mmd(gandload_phydev, MDIO_MMD_VEND1, VEND1_MAILBOX_INTERFACE3, msw);
560+ phy_write_mmd(gandload_phydev, MDIO_MMD_VEND1, VEND1_MAILBOX_INTERFACE4, lsw);
561+
562+ /* set block size so that there are from 0-3 bytes remaining */
563+ byteSize = primaryIramSize;
564+ dWordSize = byteSize >> 2;
565+
566+ bytePointer = primaryIramPtr;
567+ #ifdef AQ_PHY_SUPPORTS_BLOCK_READ_WRITE
568+ countPendingOps = 0;
569+ #endif
570+ for (i = 0; i < dWordSize; i++)
571+ {
572+ /* write 4 bytes of data */
573+ if (terminatorPtr && (bytePointer >= terminatorPtr) && (bytePointer < terminatorPtr + provTableImageSize))
574+ lsw = provTableImage[bytePointer - terminatorPtr];
575+ else
576+ lsw = image[bytePointer];
577+
578+ if (terminatorPtr && ((bytePointer+1) >= terminatorPtr) && ((bytePointer+1) < terminatorPtr + provTableImageSize))
579+ lsw |= provTableImage[bytePointer + 1 - terminatorPtr] << 8;
580+ else
581+ lsw |= image[bytePointer+1] << 8;
582+
583+ bytePointer += 2;
584+
585+ if (terminatorPtr && (bytePointer >= terminatorPtr) && (bytePointer < terminatorPtr + provTableImageSize))
586+ msw = provTableImage[bytePointer - terminatorPtr];
587+ else
588+ msw = image[bytePointer];
589+
590+ if (terminatorPtr && ((bytePointer+1) >= terminatorPtr) && ((bytePointer+1) < terminatorPtr + provTableImageSize))
591+ msw |= provTableImage[bytePointer + 1 - terminatorPtr] << 8;
592+ else
593+ msw |= image[bytePointer+1] << 8;
594+
595+ bytePointer += 2;
596+
597+ #ifdef AQ_PHY_SUPPORTS_BLOCK_READ_WRITE
598+ phy_write_mmd(gandload_phydev, MDIO_MMD_VEND1, VEND1_MAILBOX_INTERFACE5, msw);
599+ phy_write_mmd(gandload_phydev, MDIO_MMD_VEND1, VEND1_MAILBOX_INTERFACE6, lsw);
600+ phy_write_mmd(gandload_phydev, MDIO_MMD_VEND1, VEND1_MAILBOX_INTERFACE1, mailboxWrite);
601+
602+ countPendingOps += 3;
603+ /* Check if we've filled our output buffer, and if so, flush. */
604+ #ifdef AQ_EXTRA_FLAGS
605+ if (countPendingOps >= AQ_API_MDIO_MaxBlockOperations(0) - 3)
606+ #else
607+ if (countPendingOps >= AQ_API_MDIO_MaxBlockOperations() - 3)
608+ #endif
609+ {
610+ AQ_API_MDIO_BlockOperationExecute(gandload_phydev);
611+ countPendingOps = 0;
612+ }
613+ #else
614+ phy_write_mmd(gandload_phydev, MDIO_MMD_VEND1, VEND1_MAILBOX_INTERFACE5, msw);
615+ phy_write_mmd(gandload_phydev, MDIO_MMD_VEND1, VEND1_MAILBOX_INTERFACE6, lsw);
616+ phy_write_mmd(gandload_phydev, MDIO_MMD_VEND1, VEND1_MAILBOX_INTERFACE1, mailboxWrite);
617+ #endif
618+
619+ /* update the calculated CRC */
620+ crc16Calculated = ((crc16Calculated & 0xFF) << 8) ^ AQ_CRC16Table[(crc16Calculated >> 8) ^ (msw >> 8)];
621+ crc16Calculated = ((crc16Calculated & 0xFF) << 8) ^ AQ_CRC16Table[(crc16Calculated >> 8) ^ (msw & 0xFF)];
622+ crc16Calculated = ((crc16Calculated & 0xFF) << 8) ^ AQ_CRC16Table[(crc16Calculated >> 8) ^ (lsw >> 8)];
623+ crc16Calculated = ((crc16Calculated & 0xFF) << 8) ^ AQ_CRC16Table[(crc16Calculated >> 8) ^ (lsw & 0xFF)];
624+
625+ #ifdef AQ_VERBOSE
626+ if (i && ((i % 512) == 0)) phydev_info(gandload_phydev, " Byte: %X:\n", i << 2);
627+ #endif
628+ }
629+
630+ #ifdef AQ_PHY_SUPPORTS_BLOCK_READ_WRITE
631+ /* flush the output buffer one last time. */
632+ AQ_API_MDIO_BlockOperationExecute(gandload_phydev);
633+ countPendingOps = 0;
634+ #endif
635+
636+ /* Note: this final write right-justifies non-dWord data in the final dWord */
637+ switch (byteSize & 0x3)
638+ {
639+ case 0x1:
640+ /* write 1 byte of data */
641+ if (terminatorPtr && (bytePointer >= terminatorPtr) && (bytePointer < terminatorPtr + provTableImageSize))
642+ lsw = provTableImage[bytePointer - terminatorPtr];
643+ else
644+ lsw = image[bytePointer];
645+
646+ bytePointer += 1;
647+
648+ msw = 0x0000;
649+
650+ phy_write_mmd(gandload_phydev, MDIO_MMD_VEND1, VEND1_MAILBOX_INTERFACE5, msw);
651+ phy_write_mmd(gandload_phydev, MDIO_MMD_VEND1, VEND1_MAILBOX_INTERFACE6, lsw);
652+
653+ /* no polling */
654+ phy_write_mmd(gandload_phydev, MDIO_MMD_VEND1, VEND1_MAILBOX_INTERFACE1, mailboxWrite);
655+ break;
656+
657+ case 0x2:
658+ /* write 2 bytes of data */
659+ if (terminatorPtr && (bytePointer >= terminatorPtr) && (bytePointer < terminatorPtr + provTableImageSize))
660+ lsw = provTableImage[bytePointer - terminatorPtr];
661+ else
662+ lsw = image[bytePointer];
663+
664+ if (terminatorPtr && ((bytePointer+1) >= terminatorPtr) && ((bytePointer+1) < terminatorPtr + provTableImageSize))
665+ lsw |= provTableImage[bytePointer + 1 - terminatorPtr] << 8;
666+ else
667+ lsw |= image[bytePointer+1] << 8;
668+
669+ bytePointer += 2;
670+
671+ msw = 0x0000;
672+
673+ phy_write_mmd(gandload_phydev, MDIO_MMD_VEND1, VEND1_MAILBOX_INTERFACE5, msw);
674+ phy_write_mmd(gandload_phydev, MDIO_MMD_VEND1, VEND1_MAILBOX_INTERFACE6, lsw);
675+
676+ /* no polling */
677+ phy_write_mmd(gandload_phydev, MDIO_MMD_VEND1, VEND1_MAILBOX_INTERFACE1, mailboxWrite);
678+ break;
679+
680+ case 0x3:
681+ /* write 3 bytes of data */
682+ if (terminatorPtr && (bytePointer >= terminatorPtr) && (bytePointer < terminatorPtr + provTableImageSize))
683+ lsw = provTableImage[bytePointer - terminatorPtr];
684+ else
685+ lsw = image[bytePointer];
686+
687+ if (terminatorPtr && ((bytePointer+1) >= terminatorPtr) && ((bytePointer+1) < terminatorPtr + provTableImageSize))
688+ lsw |= provTableImage[bytePointer + 1 - terminatorPtr] << 8;
689+ else
690+ lsw |= image[bytePointer+1] << 8;
691+
692+ bytePointer += 2;
693+
694+ if (terminatorPtr && (bytePointer >= terminatorPtr) && (bytePointer < terminatorPtr + provTableImageSize))
695+ msw = provTableImage[bytePointer - terminatorPtr];
696+ else
697+ msw = image[bytePointer];
698+
699+ bytePointer += 1;
700+
701+ phy_write_mmd(gandload_phydev, MDIO_MMD_VEND1, VEND1_MAILBOX_INTERFACE5, msw);
702+ phy_write_mmd(gandload_phydev, MDIO_MMD_VEND1, VEND1_MAILBOX_INTERFACE6, lsw);
703+
704+ /* no polling */
705+ phy_write_mmd(gandload_phydev, MDIO_MMD_VEND1, VEND1_MAILBOX_INTERFACE1, mailboxWrite);
706+ break;
707+ }
708+
709+ if (byteSize & 0x3)
710+ {
711+ /* update the calculated CRC */
712+ crc16Calculated = ((crc16Calculated & 0xFF) << 8) ^ AQ_CRC16Table[(crc16Calculated >> 8) ^ (msw >> 8)];
713+ crc16Calculated = ((crc16Calculated & 0xFF) << 8) ^ AQ_CRC16Table[(crc16Calculated >> 8) ^ (msw & 0xFF)];
714+ crc16Calculated = ((crc16Calculated & 0xFF) << 8) ^ AQ_CRC16Table[(crc16Calculated >> 8) ^ (lsw >> 8)];
715+ crc16Calculated = ((crc16Calculated & 0xFF) << 8) ^ AQ_CRC16Table[(crc16Calculated >> 8) ^ (lsw & 0xFF)];
716+ }
717+
718+ phydev_info(gandload_phydev, "CRC-16 after loading IRAM: 0x%X\n", crc16Calculated);
719+ }
720+
721+ /* load the DRAM */
722+ phydev_info(gandload_phydev, "Loading DRAM:\n");
723+
724+ /* dWord align the address: note the image addressing is byte based, but is properly aligned on dWord
725+ boundaries, so the 2 LSbits of the block start are always zero. */
726+ msw = (uint16_t) (AQ_DRAM_BASE_ADDRESS >> 16);
727+ lsw = (AQ_DRAM_BASE_ADDRESS & 0xFFFF) >> 2;
728+ phy_write_mmd(gandload_phydev, MDIO_MMD_VEND1, VEND1_MAILBOX_INTERFACE3, msw);
729+ phy_write_mmd(gandload_phydev, MDIO_MMD_VEND1, VEND1_MAILBOX_INTERFACE4, lsw);
730+
731+ /* set block size so that there are from 0-3 bytes remaining */
732+ byteSize = primaryDramSize;
733+ dWordSize = byteSize >> 2;
734+
735+ bytePointer = primaryDramPtr;
736+#ifdef AQ_PHY_SUPPORTS_BLOCK_READ_WRITE
737+ countPendingOps = 0;
738+#endif
739+ for (i = 0; i < dWordSize; i++)
740+ {
741+ /* write 4 bytes of data */
742+ if (terminatorPtr && (bytePointer >= terminatorPtr) && (bytePointer < terminatorPtr + provTableImageSize))
743+ lsw = provTableImage[bytePointer - terminatorPtr];
744+ else
745+ lsw = image[bytePointer];
746+
747+ if (terminatorPtr && ((bytePointer+1) >= terminatorPtr) && ((bytePointer+1) < terminatorPtr + provTableImageSize))
748+ lsw |= provTableImage[bytePointer + 1 - terminatorPtr] << 8;
749+ else
750+ lsw |= image[bytePointer+1] << 8;
751+
752+ bytePointer += 2;
753+
754+ if (terminatorPtr && (bytePointer >= terminatorPtr) && (bytePointer < terminatorPtr + provTableImageSize))
755+ msw = provTableImage[bytePointer - terminatorPtr];
756+ else
757+ msw = image[bytePointer];
758+
759+ if (terminatorPtr && ((bytePointer+1) >= terminatorPtr) && ((bytePointer+1) < terminatorPtr + provTableImageSize))
760+ msw |= provTableImage[bytePointer + 1 - terminatorPtr] << 8;
761+ else
762+ msw |= image[bytePointer+1] << 8;
763+
764+ bytePointer += 2;
765+
766+ #ifdef AQ_PHY_SUPPORTS_BLOCK_READ_WRITE
767+ phy_write_mmd(gandload_phydev, MDIO_MMD_VEND1, VEND1_MAILBOX_INTERFACE5, msw);
768+ phy_write_mmd(gandload_phydev, MDIO_MMD_VEND1, VEND1_MAILBOX_INTERFACE6, lsw);
769+ phy_write_mmd(gandload_phydev, MDIO_MMD_VEND1, VEND1_MAILBOX_INTERFACE1, mailboxWrite);
770+
771+ countPendingOps += 3;
772+ /* Check if we've filled our output buffer, and if so, flush. */
773+ #ifdef AQ_EXTRA_FLAGS
774+ if (countPendingOps >= AQ_API_MDIO_MaxBlockOperations(0) - 3)
775+ #else
776+ if (countPendingOps >= AQ_API_MDIO_MaxBlockOperations() - 3)
777+ #endif
778+ {
779+ AQ_API_MDIO_BlockOperationExecute(gandload_phydev);
780+ countPendingOps = 0;
781+ }
782+ #else
783+ phy_write_mmd(gandload_phydev, MDIO_MMD_VEND1, VEND1_MAILBOX_INTERFACE5, msw);
784+ phy_write_mmd(gandload_phydev, MDIO_MMD_VEND1, VEND1_MAILBOX_INTERFACE6, lsw);
785+ phy_write_mmd(gandload_phydev, MDIO_MMD_VEND1, VEND1_MAILBOX_INTERFACE1, mailboxWrite);
786+ #endif
787+
788+ /* update the calculated CRC */
789+ crc16Calculated = ((crc16Calculated & 0xFF) << 8) ^ AQ_CRC16Table[(crc16Calculated >> 8) ^ (msw >> 8)];
790+ crc16Calculated = ((crc16Calculated & 0xFF) << 8) ^ AQ_CRC16Table[(crc16Calculated >> 8) ^ (msw & 0xFF)];
791+ crc16Calculated = ((crc16Calculated & 0xFF) << 8) ^ AQ_CRC16Table[(crc16Calculated >> 8) ^ (lsw >> 8)];
792+ crc16Calculated = ((crc16Calculated & 0xFF) << 8) ^ AQ_CRC16Table[(crc16Calculated >> 8) ^ (lsw & 0xFF)];
793+
794+ #ifdef AQ_VERBOSE
795+ if (i && ((i % 512) == 0)) phydev_info(gandload_phydev, " Byte: %X:\n", i << 2);
796+ #endif
797+ }
798+
799+ #ifdef AQ_PHY_SUPPORTS_BLOCK_READ_WRITE
800+ /* flush the output buffer one last time. */
801+ AQ_API_MDIO_BlockOperationExecute(gandload_phydev);
802+ countPendingOps = 0;
803+ #endif
804+
805+ /* Note: this final write right-justifies non-dWord data in the final dWord */
806+ switch (byteSize & 0x3)
807+ {
808+ case 0x1:
809+ /* write 1 byte of data */
810+ if (terminatorPtr && (bytePointer >= terminatorPtr) && (bytePointer < terminatorPtr + provTableImageSize))
811+ lsw = provTableImage[bytePointer - terminatorPtr];
812+ else
813+ lsw = image[bytePointer];
814+
815+ bytePointer += 1;
816+
817+ msw = 0x0000;
818+
819+ phy_write_mmd(gandload_phydev, MDIO_MMD_VEND1, VEND1_MAILBOX_INTERFACE5, msw);
820+ phy_write_mmd(gandload_phydev, MDIO_MMD_VEND1, VEND1_MAILBOX_INTERFACE6, lsw);
821+
822+ /* no polling */
823+ phy_write_mmd(gandload_phydev, MDIO_MMD_VEND1, VEND1_MAILBOX_INTERFACE1, mailboxWrite);
824+ break;
825+
826+ case 0x2:
827+ /* write 2 bytes of data */
828+ if (terminatorPtr && (bytePointer >= terminatorPtr) && (bytePointer < terminatorPtr + provTableImageSize))
829+ lsw = provTableImage[bytePointer - terminatorPtr];
830+ else
831+ lsw = image[bytePointer];
832+
833+ if (terminatorPtr && ((bytePointer+1) >= terminatorPtr) && ((bytePointer+1) < terminatorPtr + provTableImageSize))
834+ lsw |= provTableImage[bytePointer + 1 - terminatorPtr] << 8;
835+ else
836+ lsw |= image[bytePointer+1] << 8;
837+
838+ bytePointer += 2;
839+
840+ msw = 0x0000;
841+
842+ phy_write_mmd(gandload_phydev, MDIO_MMD_VEND1, VEND1_MAILBOX_INTERFACE5, msw);
843+ phy_write_mmd(gandload_phydev, MDIO_MMD_VEND1, VEND1_MAILBOX_INTERFACE6, lsw);
844+
845+ /* no polling */
846+ phy_write_mmd(gandload_phydev, MDIO_MMD_VEND1, VEND1_MAILBOX_INTERFACE1, mailboxWrite);
847+ break;
848+
849+ case 0x3:
850+ /* write 3 bytes of data */
851+ if (terminatorPtr && (bytePointer >= terminatorPtr) && (bytePointer < terminatorPtr + provTableImageSize))
852+ lsw = provTableImage[bytePointer - terminatorPtr];
853+ else
854+ lsw = image[bytePointer];
855+
856+ if (terminatorPtr && ((bytePointer+1) >= terminatorPtr) && ((bytePointer+1) < terminatorPtr + provTableImageSize))
857+ lsw |= provTableImage[bytePointer + 1 - terminatorPtr] << 8;
858+ else
859+ lsw |= image[bytePointer+1] << 8;
860+
861+ bytePointer += 2;
862+
863+ msw = image[bytePointer];
864+ bytePointer += 1;
865+
866+ phy_write_mmd(gandload_phydev, MDIO_MMD_VEND1, VEND1_MAILBOX_INTERFACE5, msw);
867+ phy_write_mmd(gandload_phydev, MDIO_MMD_VEND1, VEND1_MAILBOX_INTERFACE6, lsw);
868+
869+ /* no polling */
870+ phy_write_mmd(gandload_phydev, MDIO_MMD_VEND1, VEND1_MAILBOX_INTERFACE1, mailboxWrite);
871+ break;
872+ }
873+
874+ if (byteSize & 0x3)
875+ {
876+ /* update the calculated CRC */
877+ crc16Calculated = ((crc16Calculated & 0xFF) << 8) ^ AQ_CRC16Table[(crc16Calculated >> 8) ^ (msw >> 8)];
878+ crc16Calculated = ((crc16Calculated & 0xFF) << 8) ^ AQ_CRC16Table[(crc16Calculated >> 8) ^ (msw & 0xFF)];
879+ crc16Calculated = ((crc16Calculated & 0xFF) << 8) ^ AQ_CRC16Table[(crc16Calculated >> 8) ^ (lsw >> 8)];
880+ crc16Calculated = ((crc16Calculated & 0xFF) << 8) ^ AQ_CRC16Table[(crc16Calculated >> 8) ^ (lsw & 0xFF)];
881+ }
882+
883+ /*------------------------------------- Exit gangload mode -------------------------------------------------------*/
884+ AQ_API_DisableGangLoadMode(gandload_phydev, recordedGGP1Values[0]);
885+
886+ /*------------------------------------- Check mailbox CRCs -------------------------------------------------------*/
887+ /* check to make sure the mailbox CRC matches the calculated CRC */
888+ for (j = 0; j < num_phydevs; j++) {
889+ mailboxCRC = phy_read_mmd(phydevs[j], MDIO_MMD_VEND1, VEND1_MAILBOX_INTERFACE2);
890+ if (mailboxCRC != crc16Calculated)
891+ {
892+ phydev_err(phydevs[j], "%uth port: Mailbox CRC-16 (0x%X) does not match calculated CRC-16 (0x%X)\n",
893+ j, mailboxCRC, crc16Calculated);
894+ result[j] = -EIO;
895+ }
896+ else
897+ {
898+ phydev_info(phydevs[j], "%uth port: Image load good - mailbox CRC-16 matches (0x%X)\n",
899+ j, mailboxCRC);
900+ }
901+ }
902+
903+ /*------------------------------------- Clear any resets ---------------------------------------------------------*/
904+ for (j = 0; j < num_phydevs; j++) {
905+ phy_write_mmd(phydevs[j], MDIO_MMD_VEND1, VEND1_STD_CONTROL1, 0x0000);
906+ }
907+
908+ /*------------------------------------- Release the uP -----------------------------------------------------------*/
909+ globalControl = 0x0000;
910+ globalControl |= VEND1_CONTROL2_UP_RUNSTALL_OVERRIDE;
911+ globalControl |= VEND1_CONTROL2_UP_RUNSTALL;
912+ for (j = 0; j < num_phydevs; j++) {
913+ globalControl &= ~VEND1_CONTROL2_UP_RESET;
914+ phy_write_mmd(phydevs[j], MDIO_MMD_VEND1, VEND1_CONTROL2, globalControl);
915+ globalControl |= VEND1_CONTROL2_UP_RESET;
916+ phy_write_mmd(phydevs[j], MDIO_MMD_VEND1, VEND1_CONTROL2, globalControl);
917+ }
918+
919+ /* Need to wait at least 100us. */
920+ udelay(100);
921+
922+ globalControl &= ~VEND1_CONTROL2_UP_RESET;
923+ globalControl &= ~VEND1_CONTROL2_UP_RUNSTALL;
924+ /* For post-APPIA devices, always set the uP stall override bit to
925+ * smooth over any packaging differences WRT the boot load pin. */
926+ /* REGDOC: Assign to local representation of bitfield (HHD/APPIA/EUR/CAL/RHEA: 1E.C001.6) */
927+ globalControl |= VEND1_CONTROL2_UP_RUNSTALL_OVERRIDE;
928+
929+ for (j = 0; j < num_phydevs; j++) {
930+ phy_write_mmd(phydevs[j], MDIO_MMD_VEND1, VEND1_CONTROL2, globalControl);
931+ }
932+
933+ /* NOTE!!! We can't re-enable the daisy-chain here, as this will overwrite the IRAM and DRAM with the FLASH contents*/
934+
935+ /* If any of the ports was not bootloaded successfully, return AQ_RET_ERROR */
936+ for (j = 0; j < num_phydevs; j++) {
937+ if (result[j] != 0)
938+ return -EIO;
939+ }
940+
941+ /* All ports were bootloaded successfully. */
942+ return 0;
943+}
944+
945+static int AQ_API_WriteBootLoadImage(
946+ struct phy_device **phydevs,
947+ int num_phydevs,
948+ struct phy_device *gandload_phydev,
949+ int *result,
950+ const uint8_t* data,
951+ size_t size)
952+{
953+ unsigned int val;
954+ int j;
955+
956+ for (j = 0; j < num_phydevs; j++) {
957+ /* disable the S/W reset to the Global MMD registers */
958+ val = phy_read_mmd(phydevs[j], MDIO_MMD_VEND1, VEND1_RESET_CONTROL);
959+ val |= VEND1_RESET_CONTROL_MMD_RESET_DISABLE;
960+ phy_write_mmd(phydevs[j], MDIO_MMD_VEND1, VEND1_RESET_CONTROL, val);
961+
962+ /* assert Global S/W reset */
963+ val = phy_read_mmd(phydevs[j], MDIO_MMD_VEND1, VEND1_STD_CONTROL1);
964+ val |= VEND1_STD_CONTROL1_SOFT_RESET;
965+ phy_write_mmd(phydevs[j], MDIO_MMD_VEND1, VEND1_STD_CONTROL1, val);
966+
967+ /* de-assert Global S/W reset */
968+ val = phy_read_mmd(phydevs[j], MDIO_MMD_VEND1, VEND1_STD_CONTROL1);
969+ val &= ~VEND1_STD_CONTROL1_SOFT_RESET;
970+ phy_write_mmd(phydevs[j], MDIO_MMD_VEND1, VEND1_STD_CONTROL1, val);
971+
972+ /* wait 100ms */
973+ mdelay(100);
974+
975+ /* enable the S/W reset to the Global MMD registers */
976+ val = phy_read_mmd(phydevs[j], MDIO_MMD_VEND1, VEND1_RESET_CONTROL);
977+ val &= ~VEND1_RESET_CONTROL_MMD_RESET_DISABLE;
978+ phy_write_mmd(phydevs[j], MDIO_MMD_VEND1, VEND1_RESET_CONTROL, val);
979+ }
980+
981+ return AQ_API_WriteBootLoadImage_impl(phydevs, num_phydevs, gandload_phydev,
982+ result, (const uint32_t *)&size, data,
983+ NULL, NULL, 0);
984+}
985+
986+static void aqr_firmware_download_cb(const struct firmware *fw, void *context)
987+{
988+ struct phy_device **phydevs = context;
989+ struct phy_device *gandload_phydev = phydevs[0];
990+ struct device *dev;
991+ struct aqr107_priv *priv;
992+ int result[MAX_GANGLOAD_DEVICES];
993+ int i, ret = 0;
994+
995+retry:
996+ memset(result, 0, sizeof(result));
997+
998+ ret = AQ_API_WriteBootLoadImage(phydevs, MAX_GANGLOAD_DEVICES, gandload_phydev,
999+ result, fw->data, fw->size);
1000+ if (ret) {
1001+ for (i = 0; i < MAX_GANGLOAD_DEVICES; i++) {
1002+ if (result[i] == 0) {
1003+ priv = phydevs[i]->priv;
1004+ priv->fw_initialized = true;
1005+ continue;
1006+ }
1007+
1008+ dev = &phydevs[i]->mdio.dev;
1009+ dev_err(dev, "failed to download firmware %s, ret: %d\n",
1010+ AQR_FIRMWARE, ret);
1011+ goto retry;
1012+ }
1013+ }
1014+
1015+ release_firmware(fw);
1016+}
1017+
1018+int aqr_firmware_download_single(struct phy_device *phydev)
1019+{
1020+ struct aqr107_priv *priv = phydev->priv;
1021+ struct device *dev = &phydev->mdio.dev;
1022+ int ret = 0;
1023+
1024+ if (priv->fw_initialized == true)
1025+ return 0;
1026+
1027+ priv->phydevs[0] = phydev;
1028+
1029+ ret = request_firmware_nowait(THIS_MODULE, true, AQR_FIRMWARE, dev,
1030+ GFP_KERNEL, priv->phydevs, aqr_firmware_download_cb);
1031+ if (ret) {
1032+ dev_err(dev, "failed to load firmware %s, ret: %d\n",
1033+ AQR_FIRMWARE, ret);
1034+ }
1035+
1036+ return ret;
1037+}
1038+
1039+static int aqr_firmware_gandload_thread(void *data)
1040+{
1041+ struct phy_device **phydevs = data;
1042+ struct device *dev = &phydevs[0]->mdio.dev;
1043+ int ret = 0;
1044+
1045+ for (;;) {
1046+ if (kthread_should_stop())
1047+ break;
1048+
1049+ /* reach maximum gangload phy devices */
1050+ if (gangload == MAX_GANGLOAD_DEVICES) {
1051+ ret = request_firmware_nowait(THIS_MODULE, true, AQR_FIRMWARE, dev,
1052+ GFP_KERNEL, phydevs, aqr_firmware_download_cb);
1053+ if (ret) {
1054+ dev_err(dev, "failed to load firmware %s, ret: %d\n",
1055+ AQR_FIRMWARE, ret);
1056+ }
1057+ break;
1058+ }
1059+
1060+ set_current_state(TASK_INTERRUPTIBLE);
1061+ msleep(1);
1062+ }
1063+
1064+ return ret;
1065+}
1066+
1067+static int aqr_firmware_download_gang(struct phy_device *phydev)
1068+{
1069+ struct aqr107_priv *priv = phydev->priv;
1070+ struct device *dev = &phydev->mdio.dev;
1071+
1072+ if (priv->fw_initialized == true)
1073+ return 0;
1074+
1075+ if (!gangload_kthread) {
1076+ /* create a thread for monitor gangload devices */
1077+ gangload_kthread = kthread_create(aqr_firmware_gandload_thread,
1078+ gangload_phydevs,
1079+ "aqr_firmware_gandload_thread");
1080+ if (IS_ERR(gangload_kthread)) {
1081+ dev_err(dev,
1082+ "%s Failed to create thread for aqr_firmware_gandload_thread\n",
1083+ __func__);
1084+ return PTR_ERR(gangload_kthread);
1085+ }
1086+ wake_up_process(gangload_kthread);
1087+ }
1088+
1089+ gangload_phydevs[gangload] = phydev;
1090+ gangload++;
1091+
1092+ return 0;
1093+}
1094+
1095+int aqr_firmware_download(struct phy_device *phydev)
1096+{
1097+ int ret = 0;
1098+#ifdef CONFIG_AQUANTIA_PHY_FW_DOWNLOAD_SINGLE
1099+ ret = aqr_firmware_download_single(phydev);
1100+#elif CONFIG_AQUANTIA_PHY_FW_DOWNLOAD_GANG
1101+ ret = aqr_firmware_download_gang(phydev);
1102+#endif
1103+ return ret;
1104+}
1105diff --git a/drivers/net/phy/aquantia_main.c b/drivers/net/phy/aquantia_main.c
1106index ac8dd8e..421cdd3 100644
1107--- a/drivers/net/phy/aquantia_main.c
1108+++ b/drivers/net/phy/aquantia_main.c
1109@@ -73,18 +73,6 @@
1110 #define MDIO_AN_RX_VEND_STAT3 0xe832
1111 #define MDIO_AN_RX_VEND_STAT3_AFR BIT(0)
1112
1113-/* MDIO_MMD_C22EXT */
1114-#define MDIO_C22EXT_STAT_SGMII_RX_GOOD_FRAMES 0xd292
1115-#define MDIO_C22EXT_STAT_SGMII_RX_BAD_FRAMES 0xd294
1116-#define MDIO_C22EXT_STAT_SGMII_RX_FALSE_CARRIER 0xd297
1117-#define MDIO_C22EXT_STAT_SGMII_TX_GOOD_FRAMES 0xd313
1118-#define MDIO_C22EXT_STAT_SGMII_TX_BAD_FRAMES 0xd315
1119-#define MDIO_C22EXT_STAT_SGMII_TX_FALSE_CARRIER 0xd317
1120-#define MDIO_C22EXT_STAT_SGMII_TX_COLLISIONS 0xd318
1121-#define MDIO_C22EXT_STAT_SGMII_TX_LINE_COLLISIONS 0xd319
1122-#define MDIO_C22EXT_STAT_SGMII_TX_FRAME_ALIGN_ERR 0xd31a
1123-#define MDIO_C22EXT_STAT_SGMII_TX_RUNT_FRAMES 0xd31b
1124-
1125 /* Vendor specific 1, MDIO_MMD_VEND1 */
1126 #define VEND1_GLOBAL_FW_ID 0x0020
1127 #define VEND1_GLOBAL_FW_ID_MAJOR GENMASK(15, 8)
1128@@ -124,31 +112,6 @@
1129 #define VEND1_GLOBAL_INT_VEND_MASK_GLOBAL2 BIT(1)
1130 #define VEND1_GLOBAL_INT_VEND_MASK_GLOBAL3 BIT(0)
1131
1132-struct aqr107_hw_stat {
1133- const char *name;
1134- int reg;
1135- int size;
1136-};
1137-
1138-#define SGMII_STAT(n, r, s) { n, MDIO_C22EXT_STAT_SGMII_ ## r, s }
1139-static const struct aqr107_hw_stat aqr107_hw_stats[] = {
1140- SGMII_STAT("sgmii_rx_good_frames", RX_GOOD_FRAMES, 26),
1141- SGMII_STAT("sgmii_rx_bad_frames", RX_BAD_FRAMES, 26),
1142- SGMII_STAT("sgmii_rx_false_carrier_events", RX_FALSE_CARRIER, 8),
1143- SGMII_STAT("sgmii_tx_good_frames", TX_GOOD_FRAMES, 26),
1144- SGMII_STAT("sgmii_tx_bad_frames", TX_BAD_FRAMES, 26),
1145- SGMII_STAT("sgmii_tx_false_carrier_events", TX_FALSE_CARRIER, 8),
1146- SGMII_STAT("sgmii_tx_collisions", TX_COLLISIONS, 8),
1147- SGMII_STAT("sgmii_tx_line_collisions", TX_LINE_COLLISIONS, 8),
1148- SGMII_STAT("sgmii_tx_frame_alignment_err", TX_FRAME_ALIGN_ERR, 16),
1149- SGMII_STAT("sgmii_tx_runt_frames", TX_RUNT_FRAMES, 22),
1150-};
1151-#define AQR107_SGMII_STAT_SZ ARRAY_SIZE(aqr107_hw_stats)
1152-
1153-struct aqr107_priv {
1154- u64 sgmii_stats[AQR107_SGMII_STAT_SZ];
1155-};
1156-
1157 static int aqr107_get_sset_count(struct phy_device *phydev)
1158 {
1159 return AQR107_SGMII_STAT_SZ;
1160@@ -517,6 +480,10 @@ static int aqr107_config_init(struct phy_device *phydev)
1161 if (!ret)
1162 aqr107_chip_info(phydev);
1163
1164+#ifdef CONFIG_AQUANTIA_PHY_FW_DOWNLOAD
1165+ aqr_firmware_download(phydev);
1166+#endif
1167+
1168 /* ensure that a latched downshift event is cleared */
1169 aqr107_read_downshift_event(phydev);
1170