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