blob: 170b84147351c3680b89d7092380bd49b1735e93 [file] [log] [blame]
developer5d148cb2023-06-02 13:08:11 +08001From 2fd17c806f5ad23f9958c358cdc26f618f05d5df Mon Sep 17 00:00:00 2001
2From: Sam Shih <sam.shih@mediatek.com>
3Date: Fri, 2 Jun 2023 13:06:32 +0800
4Subject: [PATCH]
5 [networking][999-2719-net-phy-aquantia-add-firmware-download.patch]
6
7---
8 drivers/net/phy/Kconfig | 33 +-
9 drivers/net/phy/Makefile | 3 +
10 drivers/net/phy/aquantia.h | 64 ++
11 drivers/net/phy/aquantia_firmware.c | 1090 +++++++++++++++++++++++++++
12 drivers/net/phy/aquantia_main.c | 92 ++-
13 5 files changed, 1241 insertions(+), 41 deletions(-)
14 create mode 100644 drivers/net/phy/aquantia_firmware.c
15
developer122ffbb2022-11-14 12:07:10 +080016diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
developer5d148cb2023-06-02 13:08:11 +080017index c0e09c99d..d467834eb 100644
developer122ffbb2022-11-14 12:07:10 +080018--- a/drivers/net/phy/Kconfig
19+++ b/drivers/net/phy/Kconfig
developer301205c2023-05-24 15:39:32 +080020@@ -372,7 +372,38 @@ config AMD_PHY
developer122ffbb2022-11-14 12:07:10 +080021 config AQUANTIA_PHY
22 tristate "Aquantia PHYs"
23 ---help---
24- Currently supports the Aquantia AQ1202, AQ2104, AQR105, AQR405
25+ Currently supports the Aquantia AQ1202, AQ2104, AQR105, AQR405, AQR113C
26+
27+config AQUANTIA_PHY_FW_DOWNLOAD
28+ tristate "Firmware Download Enable"
29+ depends on AQUANTIA_PHY
30+ ---help---
31+ Currently supports the Aquantia AQR113C
32+
33+choice
34+ prompt "Download mode"
35+ default AQUANTIA_PHY_FW_DOWNLOAD_GANG
36+ depends on AQUANTIA_PHY_FW_DOWNLOAD
37+
38+ config AQUANTIA_PHY_FW_DOWNLOAD_SINGLE
39+ bool "Single"
40+ ---help---
41+ If you would like to download firmware in sequential way,
42+ please select this option.
43+
44+ config AQUANTIA_PHY_FW_DOWNLOAD_GANG
45+ bool "Gang"
46+ ---help---
47+ If you would like to download firmware in parallel way,
48+ please select this option.
49+endchoice
50+
51+config AQUANTIA_PHY_FW_FILE
52+ string "FW File"
53+ depends on AQUANTIA_PHY
54+ default "Rhe-05.06-Candidate7-AQR_Mediatek_23B_StartOff_ID45623_VER36657.cld"
55+ ---help---
56+ Currently supports the Aquantia AQR113c
57
58 config AX88796B_PHY
59 tristate "Asix PHYs"
60diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
developer5d148cb2023-06-02 13:08:11 +080061index 8b57d6105..e9653de36 100644
developer122ffbb2022-11-14 12:07:10 +080062--- a/drivers/net/phy/Makefile
63+++ b/drivers/net/phy/Makefile
developer5d148cb2023-06-02 13:08:11 +080064@@ -68,6 +68,9 @@ aquantia-objs += aquantia_main.o
developer122ffbb2022-11-14 12:07:10 +080065 ifdef CONFIG_HWMON
66 aquantia-objs += aquantia_hwmon.o
67 endif
68+ifdef CONFIG_AQUANTIA_PHY_FW_DOWNLOAD
69+aquantia-objs += aquantia_firmware.o
70+endif
developer122ffbb2022-11-14 12:07:10 +080071 obj-$(CONFIG_AIROHA_EN8801SC_PHY) += en8801sc.o
developer5d148cb2023-06-02 13:08:11 +080072 obj-$(CONFIG_AIROHA_EN8811H_PHY) += air_en8811h.o
developer122ffbb2022-11-14 12:07:10 +080073 obj-$(CONFIG_AQUANTIA_PHY) += aquantia.o
74diff --git a/drivers/net/phy/aquantia.h b/drivers/net/phy/aquantia.h
developer5d148cb2023-06-02 13:08:11 +080075index 5a16caab7..ab1c241d3 100644
developer122ffbb2022-11-14 12:07:10 +080076--- a/drivers/net/phy/aquantia.h
77+++ b/drivers/net/phy/aquantia.h
developer08abacf2023-05-18 15:52:22 +080078@@ -9,8 +9,72 @@
developer122ffbb2022-11-14 12:07:10 +080079 #include <linux/device.h>
80 #include <linux/phy.h>
81
developer08abacf2023-05-18 15:52:22 +080082+#define MDIO_AN_VEND_PROV_DOWNSHIFT_DFLT 4
83+
developer94316402022-11-21 08:58:41 +080084+#define PMAPMD_RSVD_VEND_PROV 0xe400
85+#define PMAPMD_RSVD_VEND_PROV_MDI_CONF BIT(0)
86+
developer122ffbb2022-11-14 12:07:10 +080087+/* MDIO_MMD_C22EXT */
88+#define MDIO_C22EXT_STAT_SGMII_RX_GOOD_FRAMES 0xd292
89+#define MDIO_C22EXT_STAT_SGMII_RX_BAD_FRAMES 0xd294
90+#define MDIO_C22EXT_STAT_SGMII_RX_FALSE_CARRIER 0xd297
91+#define MDIO_C22EXT_STAT_SGMII_TX_GOOD_FRAMES 0xd313
92+#define MDIO_C22EXT_STAT_SGMII_TX_BAD_FRAMES 0xd315
93+#define MDIO_C22EXT_STAT_SGMII_TX_FALSE_CARRIER 0xd317
94+#define MDIO_C22EXT_STAT_SGMII_TX_COLLISIONS 0xd318
95+#define MDIO_C22EXT_STAT_SGMII_TX_LINE_COLLISIONS 0xd319
96+#define MDIO_C22EXT_STAT_SGMII_TX_FRAME_ALIGN_ERR 0xd31a
97+#define MDIO_C22EXT_STAT_SGMII_TX_RUNT_FRAMES 0xd31b
98+
99+struct aqr107_hw_stat {
100+ const char *name;
101+ int reg;
102+ int size;
103+};
104+
105+#define SGMII_STAT(n, r, s) { n, MDIO_C22EXT_STAT_SGMII_ ## r, s }
106+static const struct aqr107_hw_stat aqr107_hw_stats[] = {
107+ SGMII_STAT("sgmii_rx_good_frames", RX_GOOD_FRAMES, 26),
108+ SGMII_STAT("sgmii_rx_bad_frames", RX_BAD_FRAMES, 26),
109+ SGMII_STAT("sgmii_rx_false_carrier_events", RX_FALSE_CARRIER, 8),
110+ SGMII_STAT("sgmii_tx_good_frames", TX_GOOD_FRAMES, 26),
111+ SGMII_STAT("sgmii_tx_bad_frames", TX_BAD_FRAMES, 26),
112+ SGMII_STAT("sgmii_tx_false_carrier_events", TX_FALSE_CARRIER, 8),
113+ SGMII_STAT("sgmii_tx_collisions", TX_COLLISIONS, 8),
114+ SGMII_STAT("sgmii_tx_line_collisions", TX_LINE_COLLISIONS, 8),
115+ SGMII_STAT("sgmii_tx_frame_alignment_err", TX_FRAME_ALIGN_ERR, 16),
116+ SGMII_STAT("sgmii_tx_runt_frames", TX_RUNT_FRAMES, 22),
117+};
118+#define AQR107_SGMII_STAT_SZ ARRAY_SIZE(aqr107_hw_stats)
119+
120+struct aqr107_priv {
121+ u64 sgmii_stats[AQR107_SGMII_STAT_SZ];
122+#ifdef CONFIG_AQUANTIA_PHY_FW_DOWNLOAD
123+ struct phy_device *phydevs[1];
developer7ddeff02023-03-22 15:28:46 +0800124+ struct task_struct *heartbeat_thread;
developer08abacf2023-05-18 15:52:22 +0800125+ spinlock_t lock;
developer122ffbb2022-11-14 12:07:10 +0800126+ bool fw_initialized;
developer093e9b32022-12-13 16:08:34 +0800127+ int fw_dl_mode;
developer7ddeff02023-03-22 15:28:46 +0800128+ u16 heartbeat;
developer122ffbb2022-11-14 12:07:10 +0800129+#endif
130+};
131+
developer08abacf2023-05-18 15:52:22 +0800132+int aqr107_set_downshift(struct phy_device *phydev, u8 cnt);
133+void aqr107_chip_info(struct phy_device *phydev);
developer94316402022-11-21 08:58:41 +0800134+int aqr107_config_mdi(struct phy_device *phydev);
135+
developer122ffbb2022-11-14 12:07:10 +0800136 #if IS_REACHABLE(CONFIG_HWMON)
137 int aqr_hwmon_probe(struct phy_device *phydev);
138 #else
139 static inline int aqr_hwmon_probe(struct phy_device *phydev) { return 0; }
140 #endif
141+
142+#ifdef CONFIG_AQUANTIA_PHY_FW_DOWNLOAD
developer093e9b32022-12-13 16:08:34 +0800143+enum {
144+ FW_DL_SINGLE = 0,
145+ FW_DL_GNAGLOAD,
146+};
147+
developer08abacf2023-05-18 15:52:22 +0800148+int aqr_firmware_heartbeat_thread(void *data);
developer122ffbb2022-11-14 12:07:10 +0800149+int aqr_firmware_download(struct phy_device *phydev);
150+#endif
151diff --git a/drivers/net/phy/aquantia_firmware.c b/drivers/net/phy/aquantia_firmware.c
152new file mode 100644
developer5d148cb2023-06-02 13:08:11 +0800153index 000000000..d2828aad4
developer122ffbb2022-11-14 12:07:10 +0800154--- /dev/null
155+++ b/drivers/net/phy/aquantia_firmware.c
developer9451bcd2023-07-18 09:34:05 +0800156@@ -0,0 +1,1100 @@
developer122ffbb2022-11-14 12:07:10 +0800157+// SPDX-License-Identifier: GPL-2.0
158+/* FW download driver for Aquantia PHY
159+ */
160+
161+#include <linux/phy.h>
162+#include <linux/of.h>
163+#include <linux/device.h>
164+#include <linux/firmware.h>
165+#include <linux/kthread.h>
166+
167+#include "aquantia.h"
168+
169+#undef AQ_VERBOSE
170+
171+#ifdef CONFIG_AQUANTIA_PHY_FW_DOWNLOAD_SINGLE
172+#define MAX_GANGLOAD_DEVICES 1
173+#elif CONFIG_AQUANTIA_PHY_FW_DOWNLOAD_GANG
174+#define MAX_GANGLOAD_DEVICES 2
175+#endif
176+
177+#define AQR_FIRMWARE CONFIG_AQUANTIA_PHY_FW_FILE
178+
179+/* Vendor specific 1, MDIO_MMD_VEND1 */
180+#define VEND1_STD_CONTROL1 0x0000
181+#define VEND1_STD_CONTROL1_SOFT_RESET BIT(15)
182+
183+#define VEND1_MAILBOX_INTERFACE1 0x0200
184+#define VEND1_MAILBOX_INTERFACE1_START BIT(15)
185+#define VEND1_MAILBOX_INTERFACE1_WRITE FIELD_PREP(BIT(14), 1)
186+#define VEND1_MAILBOX_INTERFACE1_READ FIELD_PREP(BIT(14), 0)
187+#define VEND1_MAILBOX_INTERFACE1_RESET_CRC BIT(12)
188+
189+#define VEND1_MAILBOX_INTERFACE2 0x0201
190+#define VEND1_MAILBOX_INTERFACE2_CRC GENMASK(15, 0)
191+
192+#define VEND1_MAILBOX_INTERFACE3 0x0202
193+#define VEND1_MAILBOX_INTERFACE3_ADDR_MSW GENMASK(15, 0)
194+
195+#define VEND1_MAILBOX_INTERFACE4 0x0203
196+#define VEND1_MAILBOX_INTERFACE4_ADDR_LSW GENMASK(15, 2)
197+
198+#define VEND1_MAILBOX_INTERFACE5 0x0204
199+#define VEND1_MAILBOX_INTERFACE5_DATA_MSW GENMASK(15, 0)
200+
201+#define VEND1_MAILBOX_INTERFACE6 0x0205
202+#define VEND1_MAILBOX_INTERFACE6_DATA_LSW GENMASK(15, 0)
203+
204+#define VEND1_CONTROL2 0xc001
205+#define VEND1_CONTROL2_UP_RESET BIT(15)
206+#define VEND1_CONTROL2_UP_RUNSTALL_OVERRIDE BIT(6)
207+#define VEND1_CONTROL2_UP_RUNSTALL BIT(0)
208+
209+#define VEND1_RESET_CONTROL 0xc006
210+#define VEND1_RESET_CONTROL_MMD_RESET_DISABLE BIT(14)
211+
212+#define VEND1_GENERAL_PROV2 0xc441
213+#define VEND1_GENERAL_PROV2_MDIO_BROADCAST_ENABLE BIT(14)
214+
215+#define VEND1_GENERAL_PROV8 0xc447
216+#define VEND1_GENERAL_PROV8_MDIO_BROADCAST_ADDRESS GENMASK(4, 0)
217+
218+#define VEND1_NVR_PROV3 0xc452
219+#define VEND1_NVR_PROV3_DAISYCHAIN_DISABLE BIT(0)
220+
221+#define VEND1_RSVD_PROV2 0xc471
222+#define VEND1_RSVD_PROV2_DAISYCHAIN_HOPCOUNT GENMASK(5, 0)
223+#define VEND1_RSVD_PROV2_DAISYCHAIN_HOPCOUNT_OVERRIDE BIT(6)
224+
developeraafac652023-01-18 09:41:27 +0800225+#define VEND1_GLOBAL_RSVD_STAT2 0xc886
226+
developer122ffbb2022-11-14 12:07:10 +0800227+/*! The byte address, in processor memory, of the start of the IRAM segment. */
228+#define AQ_IRAM_BASE_ADDRESS 0x40000000
229+
230+/*! The byte address, in processor memory, of the start of the DRAM segment. */
231+#define AQ_DRAM_BASE_ADDRESS 0x3FFE0000
232+
233+/*! The byte offset from the top of the PHY image to the header content (HHD & EUR devices). */
234+#define AQ_PHY_IMAGE_HEADER_CONTENT_OFFSET_HHD 0x300
235+
236+/*! The offset, from the start of DRAM, where the provisioning block begins. */
237+#define AQ_PHY_IMAGE_PROVTABLE_OFFSET 0x680
238+
239+/*! The offset, from the start of DRAM, where the provisioning block's ending address is recorded. */
240+#define AQ_PHY_IMAGE_PROVTABLE_TERM_OFFSET 0x028C
241+
242+/*! The size of the space alloted within the PHY image for the provisioning table. */
243+#define AQ_PHY_IMAGE_PROVTABLE_MAXSIZE 0x800
244+
245+/*! The maximum number of ports that can be MDIO bootloaded at once. */
246+#define AQ_MAX_NUM_PHY_IDS 48
247+
248+/*! This enumeration is used to describe the different types of
249+ Aquantia PHY.*/
250+typedef enum
251+{
252+ /*! 1/2/4-port package, 40nm architechture.*/
253+ AQ_DEVICE_APPIA,
254+ /*! 1/2/4-port package, first-generation 28nm architechture.*/
255+ AQ_DEVICE_HHD,
256+ /*! 1/2/4-port package, second-generation 28nm architechture.*/
257+ AQ_DEVICE_EUR,
258+ /*! 1/2/4-port package, third-generation 28nm architechture.*/
259+ AQ_DEVICE_CAL,
260+ /*! 1/2/4/8-port package, forth-generation 14nm architechture.*/
261+ AQ_DEVICE_RHEA,
262+ /*! 8-port package, fifth-generation 14nm architechture.*/
263+ AQ_DEVICE_DIONE
264+} AQ_API_Device;
265+
266+/*! The table used to compute CRC's within the PHY. */
267+const uint16_t AQ_CRC16Table[256] = {0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
268+ 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
269+ 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
270+ 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
271+ 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
272+ 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
273+ 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
274+ 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
275+ 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
276+ 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
277+ 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
278+ 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
279+ 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
280+ 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
281+ 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
282+ 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
283+ 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
284+ 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
285+ 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
286+ 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
287+ 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
288+ 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
289+ 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
290+ 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
291+ 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
292+ 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
293+ 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
294+ 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
295+ 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
296+ 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
297+ 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
298+ 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0};
299+
300+struct task_struct *gangload_kthread = NULL;
301+struct phy_device *gangload_phydevs[MAX_GANGLOAD_DEVICES];
developer9451bcd2023-07-18 09:34:05 +0800302+static unsigned long gangload_timeout = 0;
developer122ffbb2022-11-14 12:07:10 +0800303+static int gangload = 0;
304+
developeraafac652023-01-18 09:41:27 +0800305+static int aqr_firmware_download_single(struct phy_device *phydev);
306+
developer122ffbb2022-11-14 12:07:10 +0800307+void AQ_API_EnableMDIO_BootLoadMode
308+(
309+ /*! The target PHY port.*/
310+ struct phy_device *phydev,
311+ /*! The provisioning address to use when the FW starts and applies the
312+ * bootloaded image's provisioned values. */
313+ unsigned int provisioningAddress
314+)
315+{
316+ uint16_t globalNvrProvisioning;
317+ uint16_t globalReservedProvisioning;
318+
319+ /* disable the daisy-chain */
320+ globalNvrProvisioning = phy_read_mmd(phydev, MDIO_MMD_VEND1, VEND1_NVR_PROV3);
321+ globalNvrProvisioning |= VEND1_NVR_PROV3_DAISYCHAIN_DISABLE;
322+ phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_NVR_PROV3, globalNvrProvisioning);
323+
324+ /* override the hop-count */
325+ globalReservedProvisioning = phy_read_mmd(phydev, MDIO_MMD_VEND1, VEND1_RSVD_PROV2);
326+ globalReservedProvisioning &= ~VEND1_RSVD_PROV2_DAISYCHAIN_HOPCOUNT;
327+ globalReservedProvisioning |= FIELD_PREP(VEND1_RSVD_PROV2_DAISYCHAIN_HOPCOUNT,
328+ provisioningAddress);
329+ globalReservedProvisioning |= VEND1_RSVD_PROV2_DAISYCHAIN_HOPCOUNT_OVERRIDE;
330+ phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_RSVD_PROV2, globalReservedProvisioning);
331+
332+ return;
333+}
334+
335+/*! Prepare the specified port for MDIO bootloading, and set the temporary MDIO
336+ * address to be used during the bootload process. Disables the daisy-chain,
337+ * and explicitly sets the port's provisioningAddress. */
338+void AQ_API_EnableGangLoadMode
339+(
340+ /*! The target PHY port.*/
341+ struct phy_device *phydev,
342+ /*! The PHY's MDIO address will be changed to this value during the
343+ * bootload process. */
344+ unsigned int gangLoadAddress
345+)
346+{
347+ uint16_t globalGeneralProvisioning;
348+
349+ /* Enable gangload mode. After doing this, the PHY will be
350+ * addressable at the MDIO address indicated by gangLoadAddress.
351+ * Now that the PHY is in gangload mode, MDIO reads are prohibited
352+ * until AQ_API_DisableGangLoadMode is called. */
353+ globalGeneralProvisioning = phy_read_mmd(phydev, MDIO_MMD_VEND1, VEND1_GENERAL_PROV8);
354+ globalGeneralProvisioning &= ~VEND1_GENERAL_PROV8_MDIO_BROADCAST_ADDRESS;
355+ globalGeneralProvisioning |= FIELD_PREP(VEND1_GENERAL_PROV8_MDIO_BROADCAST_ADDRESS,
356+ gangLoadAddress);
357+ phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_GENERAL_PROV8, globalGeneralProvisioning);
358+
359+ globalGeneralProvisioning = phy_read_mmd(phydev, MDIO_MMD_VEND1, VEND1_GENERAL_PROV2);
360+ globalGeneralProvisioning |= VEND1_GENERAL_PROV2_MDIO_BROADCAST_ENABLE;
361+ phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_GENERAL_PROV2, globalGeneralProvisioning);
362+
363+ return;
364+}
365+
366+/*! Restore the PHY's MDIO address to the pin-specified value. Should be
367+ * called when MDIO bootloading is complete, to return to normal MDIO
368+ * addressing.
369+ * <b>This is a gang-load function, hence write-only!</b> */
370+void AQ_API_DisableGangLoadMode
371+(
372+ /*! The target PHY port.*/
373+ struct phy_device *phydev,
374+ /*! The value to write to of AQ_GlobalGeneralProvisioning.u1.word_1. */
375+ uint16_t origVal_GGP1
376+)
377+{
378+ uint16_t globalGeneralProvisioning;
379+
380+ /* Restore the original value of globalGeneralProvisioning.u1, and set
381+ * the MDIO address reset bit. This will cause the MDIO address to be
382+ * reset to the value indicated by the pins. */
383+ globalGeneralProvisioning = origVal_GGP1;
384+ globalGeneralProvisioning &= ~VEND1_GENERAL_PROV2_MDIO_BROADCAST_ENABLE;
385+ phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_GENERAL_PROV2, globalGeneralProvisioning);
386+
387+ /* The PHY has now exited gang-load mode. */
388+ return;
389+}
390+
391+/* Common implementation of MDIO bootload routine, for the entry points:
392+ * AQ_API_WriteBootLoadImage
393+ * AQ_API_WriteBootLoadImageWithProvTable
394+ * AQ_API_WriteBootLoadImageDRAMOnly
395+ * AQ_API_WriteBootLoadImageWithProvTableDRAMOnly */
396+static int AQ_API_WriteBootLoadImage_impl
397+(
398+ struct phy_device **phydevs,
399+ int num_phydevs,
400+ struct phy_device *gandload_phydev,
401+ int *result,
402+ const uint32_t* imageSizePointer,
403+ const uint8_t* image,
404+ const uint32_t* provTableSizePointer,
405+ const uint8_t* provTableImage,
406+ bool dramOnly
407+)
408+{
409+ uint32_t primaryHeaderPtr = 0x00000000;
410+ uint32_t primaryIramPtr = 0x00000000;
411+ uint32_t primaryDramPtr = 0x00000000;
412+ uint32_t primaryIramSize = 0x00000000;
413+ uint32_t primaryDramSize = 0x00000000;
414+ uint32_t terminatorPtr = 0x00000000;
415+ uint32_t phyImageHeaderContentOffset = 0x00000000;
416+ uint32_t i, j;
417+ uint32_t imageSize;
418+ uint32_t provTableImageSize = 0;
419+ uint32_t bytePointer;
420+ uint32_t byteSize;
421+ uint32_t dWordSize;
422+#ifdef AQ_PHY_SUPPORTS_BLOCK_READ_WRITE
423+ uint32_t countPendingOps; /* A count of block MDIO operation pending... necessary to keep a count
424+ in order to ensure we don't exceed the maximum pending operations. */
425+#endif
426+ uint16_t globalControl;
427+ uint16_t msw;
428+ uint16_t lsw;
429+ uint16_t crc16Calculated;
430+ uint16_t provTableCrc16Calculated;
431+ uint16_t fileCRC;
432+ uint16_t provTableFileCRC;
433+ uint16_t mailboxCRC;
434+ uint16_t mailboxWrite;
435+ uint16_t recordedGGP1Values[AQ_MAX_NUM_PHY_IDS]; /* When entering/exiting gangload mode, we record and restore
436+ the AQ_GlobalGeneralProvisioning.u1 register values. */
437+
438+ /* store the CRC-16 for the image, which is the last two bytes */
439+ imageSize = *imageSizePointer;
440+
441+ /*
442+ * If the imageSize is less than 2, we don't do anything
443+ */
444+ if (imageSize < 2) {
445+ result[0] = -EINVAL;
446+ return -EINVAL;
447+ }
448+
449+ fileCRC = image[imageSize-2] << 8 | image[imageSize-1];
450+
451+ /*------------------------------------- Check the image integrity ------------------------------------------------*/
452+ crc16Calculated = 0x0000;
453+ for (i = 0; i < imageSize-2; i++)
454+ {
455+ crc16Calculated = ((crc16Calculated & 0xFF) << 8) ^ AQ_CRC16Table[(crc16Calculated >> 8) ^ image[i]];
456+ }
457+
458+ if (crc16Calculated != fileCRC)
459+ {
460+ phydev_err(phydevs[0], "CRC check failed on image file (expected 0x%X, found 0x%X)\n",
461+ fileCRC, crc16Calculated);
462+ result[0] = -EINVAL;
463+ return -EINVAL;
464+ }
465+ else
466+ {
467+ phydev_info(phydevs[0], "CRC check good on image file (0x%04X)\n", crc16Calculated);
468+ }
469+
470+ /*-------------------------------- Check the provisioning table image integrity ----------------------------------*/
471+ if (provTableSizePointer != NULL && provTableImage != NULL)
472+ {
473+ provTableImageSize = (*provTableSizePointer) - 2;
474+ provTableFileCRC = provTableImage[provTableImageSize + 1] << 8 |
475+ provTableImage[provTableImageSize];
476+
477+ provTableCrc16Calculated = 0x0000;
478+ for (i = 0; i < provTableImageSize; i++)
479+ {
480+ provTableCrc16Calculated = ((provTableCrc16Calculated & 0xFF) << 8) ^
481+ AQ_CRC16Table[(provTableCrc16Calculated >> 8) ^ provTableImage[i]];
482+ }
483+
484+ if (provTableCrc16Calculated != provTableFileCRC)
485+ {
486+ phydev_err(phydevs[0], "CRC check failed on provisioning table file (expected 0x%X, found 0x%X)\n",
487+ provTableFileCRC, provTableCrc16Calculated);
488+ result[0] = -EINVAL;
489+ return -EINVAL;
490+ }
491+ else
492+ {
493+ phydev_info(phydevs[0], "CRC check good on provisioning table file (0x%04X)\n",
494+ provTableCrc16Calculated);
495+ }
496+ }
497+
498+ /*--------------------------- Store 1E.C441 values for later use. Enforce uniformity. ---------------------------*/
499+ for (j = 0; j < num_phydevs; j++)
500+ {
501+ /* Record the original value of AQ_GlobalGeneralProvisioning.u1.word_1,
502+ * so that we can restore it later after exiting gangload mode. */
503+ recordedGGP1Values[j] = phy_read_mmd(phydevs[j], MDIO_MMD_VEND1, VEND1_GENERAL_PROV2);
504+
505+ /* If any of the PHYs' GGP1 values don't match the others, set the appropriate
506+ * error code and return. */
507+ if (j > 0 && recordedGGP1Values[j] != recordedGGP1Values[0])
508+ {
509+ phydev_err(phydevs[j], "Non-uniform value of 1E.C441 found (expected 0x%X, found 0x%X)\n",
510+ recordedGGP1Values[0], recordedGGP1Values[j]);
511+ result[j] = -EINVAL;
512+ return -EINVAL;
513+ }
514+ }
515+
516+ /*--------------------------- Put each PHY into gangload mode at the specified address ---------------------------*/
517+ for (j = 0; j < num_phydevs; j++) {
518+ AQ_API_EnableMDIO_BootLoadMode(phydevs[j], 0);
519+ AQ_API_EnableGangLoadMode(phydevs[j], gandload_phydev->mdio.addr);
520+ }
521+
522+ /*------------------------------------- Stall the uP ------------------------------------------------------------*/
523+ globalControl = 0x0000;
524+ globalControl |= VEND1_CONTROL2_UP_RUNSTALL_OVERRIDE;
525+ globalControl |= VEND1_CONTROL2_UP_RUNSTALL;
526+ phy_write_mmd(gandload_phydev, MDIO_MMD_VEND1, VEND1_CONTROL2, globalControl);
527+
528+ /*------------------------------------- Initialize the mailbox write command -------------------------------------*/
529+ mailboxWrite = 0x0000;
530+ mailboxWrite |= VEND1_MAILBOX_INTERFACE1_WRITE;
531+ mailboxWrite |= VEND1_MAILBOX_INTERFACE1_START;
532+
533+ /*------------------------------------- Read the segment addresses and sizes -------------------------------------*/
534+ primaryHeaderPtr = (((image[0x9] & 0x0F) << 8) | image[0x8]) << 12;
535+
536+ /* setup image header content offset for HHD/EUR/CAL/RHEA */
537+ phyImageHeaderContentOffset = AQ_PHY_IMAGE_HEADER_CONTENT_OFFSET_HHD;
538+
539+ primaryIramPtr = (image[primaryHeaderPtr + phyImageHeaderContentOffset + 0x4 + 2] << 16) |
540+ (image[primaryHeaderPtr + phyImageHeaderContentOffset + 0x4 + 1] << 8) |
541+ image[primaryHeaderPtr + phyImageHeaderContentOffset + 0x4];
542+ primaryIramSize = (image[primaryHeaderPtr + phyImageHeaderContentOffset + 0x7 + 2] << 16) |
543+ (image[primaryHeaderPtr + phyImageHeaderContentOffset + 0x7 + 1] << 8) |
544+ image[primaryHeaderPtr + phyImageHeaderContentOffset + 0x7];
545+ primaryDramPtr = (image[primaryHeaderPtr + phyImageHeaderContentOffset + 0xA + 2] << 16) |
546+ (image[primaryHeaderPtr + phyImageHeaderContentOffset + 0xA + 1] << 8) |
547+ image[primaryHeaderPtr + phyImageHeaderContentOffset + 0xA];
548+ primaryDramSize = (image[primaryHeaderPtr + phyImageHeaderContentOffset + 0xD + 2] << 16) |
549+ (image[primaryHeaderPtr + phyImageHeaderContentOffset + 0xD + 1] << 8) |
550+ image[primaryHeaderPtr + phyImageHeaderContentOffset + 0xD];
551+
552+ /* setup primary image pointer for HHD/EUR/CAL/RHEA */
553+ primaryIramPtr += primaryHeaderPtr;
554+ primaryDramPtr += primaryHeaderPtr;
555+
556+ phydev_info(gandload_phydev, "Segment Addresses and Sizes as read from the PHY ROM image header:\n");
557+ phydev_info(gandload_phydev, "Primary Iram Address: 0x%x\n", primaryIramPtr);
558+ phydev_info(gandload_phydev, "Primary Iram Size: 0x%x\n", primaryIramSize);
559+ phydev_info(gandload_phydev, "Primary Dram Address: 0x%x\n", primaryDramPtr);
560+ phydev_info(gandload_phydev, "Primary Dram Size: 0x%x\n", primaryDramSize);
561+
562+ /*------------------ Prepare to merge the provisioning table into the main image ---------------------------------*/
563+ if (provTableSizePointer != NULL && provTableImage != NULL)
564+ {
565+ /* Locate the terminator of the built-in provisioning table */
566+ terminatorPtr = primaryDramPtr +
567+ ((image[primaryDramPtr + AQ_PHY_IMAGE_PROVTABLE_TERM_OFFSET + 1] << 8) |
568+ image[primaryDramPtr + AQ_PHY_IMAGE_PROVTABLE_TERM_OFFSET]);
569+
570+ phydev_info(gandload_phydev, "Supplied Provisioning Table At Address: 0x%x\n\n", terminatorPtr);
571+
572+ /* Check that the supplied provisioning table will fit within the alloted
573+ * space. */
574+ if (terminatorPtr - (primaryDramPtr + AQ_PHY_IMAGE_PROVTABLE_OFFSET) +
575+ provTableImageSize > AQ_PHY_IMAGE_PROVTABLE_MAXSIZE)
576+ {
577+ result[0] = -EINVAL;
578+ return -EINVAL;
579+ }
580+ }
581+
582+ /*------------------------------------- Load IRAM and DRAM -------------------------------------------------------*/
583+ /* clear the mailbox CRC */
584+ phy_write_mmd(gandload_phydev, MDIO_MMD_VEND1, VEND1_MAILBOX_INTERFACE1, VEND1_MAILBOX_INTERFACE1_RESET_CRC);
585+ phy_write_mmd(gandload_phydev, MDIO_MMD_VEND1, VEND1_MAILBOX_INTERFACE1, 0x0000);
586+
587+ crc16Calculated = 0; /* This is to calculate what was written through the mailbox */
588+
589+ if (!dramOnly)
590+ {
591+ /* load the IRAM */
592+ phydev_info(gandload_phydev, "Loading IRAM:\n");
593+
594+ /* dWord align the address: note the image addressing is byte based, but is properly aligned on dWord
595+ boundaries, so the 2 LSbits of the block start are always zero. */
596+ msw = (uint16_t) (AQ_IRAM_BASE_ADDRESS >> 16);
597+ lsw = (AQ_IRAM_BASE_ADDRESS & 0xFFFF) >> 2;
598+ phy_write_mmd(gandload_phydev, MDIO_MMD_VEND1, VEND1_MAILBOX_INTERFACE3, msw);
599+ phy_write_mmd(gandload_phydev, MDIO_MMD_VEND1, VEND1_MAILBOX_INTERFACE4, lsw);
600+
601+ /* set block size so that there are from 0-3 bytes remaining */
602+ byteSize = primaryIramSize;
603+ dWordSize = byteSize >> 2;
604+
605+ bytePointer = primaryIramPtr;
606+ #ifdef AQ_PHY_SUPPORTS_BLOCK_READ_WRITE
607+ countPendingOps = 0;
608+ #endif
609+ for (i = 0; i < dWordSize; i++)
610+ {
611+ /* write 4 bytes of data */
612+ if (terminatorPtr && (bytePointer >= terminatorPtr) && (bytePointer < terminatorPtr + provTableImageSize))
613+ lsw = provTableImage[bytePointer - terminatorPtr];
614+ else
615+ lsw = image[bytePointer];
616+
617+ if (terminatorPtr && ((bytePointer+1) >= terminatorPtr) && ((bytePointer+1) < terminatorPtr + provTableImageSize))
618+ lsw |= provTableImage[bytePointer + 1 - terminatorPtr] << 8;
619+ else
620+ lsw |= image[bytePointer+1] << 8;
621+
622+ bytePointer += 2;
623+
624+ if (terminatorPtr && (bytePointer >= terminatorPtr) && (bytePointer < terminatorPtr + provTableImageSize))
625+ msw = provTableImage[bytePointer - terminatorPtr];
626+ else
627+ msw = image[bytePointer];
628+
629+ if (terminatorPtr && ((bytePointer+1) >= terminatorPtr) && ((bytePointer+1) < terminatorPtr + provTableImageSize))
630+ msw |= provTableImage[bytePointer + 1 - terminatorPtr] << 8;
631+ else
632+ msw |= image[bytePointer+1] << 8;
633+
634+ bytePointer += 2;
635+
636+ #ifdef AQ_PHY_SUPPORTS_BLOCK_READ_WRITE
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+
641+ countPendingOps += 3;
642+ /* Check if we've filled our output buffer, and if so, flush. */
643+ #ifdef AQ_EXTRA_FLAGS
644+ if (countPendingOps >= AQ_API_MDIO_MaxBlockOperations(0) - 3)
645+ #else
646+ if (countPendingOps >= AQ_API_MDIO_MaxBlockOperations() - 3)
647+ #endif
648+ {
649+ AQ_API_MDIO_BlockOperationExecute(gandload_phydev);
650+ countPendingOps = 0;
651+ }
652+ #else
653+ phy_write_mmd(gandload_phydev, MDIO_MMD_VEND1, VEND1_MAILBOX_INTERFACE5, msw);
654+ phy_write_mmd(gandload_phydev, MDIO_MMD_VEND1, VEND1_MAILBOX_INTERFACE6, lsw);
655+ phy_write_mmd(gandload_phydev, MDIO_MMD_VEND1, VEND1_MAILBOX_INTERFACE1, mailboxWrite);
656+ #endif
657+
658+ /* update the calculated CRC */
659+ crc16Calculated = ((crc16Calculated & 0xFF) << 8) ^ AQ_CRC16Table[(crc16Calculated >> 8) ^ (msw >> 8)];
660+ crc16Calculated = ((crc16Calculated & 0xFF) << 8) ^ AQ_CRC16Table[(crc16Calculated >> 8) ^ (msw & 0xFF)];
661+ crc16Calculated = ((crc16Calculated & 0xFF) << 8) ^ AQ_CRC16Table[(crc16Calculated >> 8) ^ (lsw >> 8)];
662+ crc16Calculated = ((crc16Calculated & 0xFF) << 8) ^ AQ_CRC16Table[(crc16Calculated >> 8) ^ (lsw & 0xFF)];
663+
664+ #ifdef AQ_VERBOSE
665+ if (i && ((i % 512) == 0)) phydev_info(gandload_phydev, " Byte: %X:\n", i << 2);
666+ #endif
667+ }
668+
669+ #ifdef AQ_PHY_SUPPORTS_BLOCK_READ_WRITE
670+ /* flush the output buffer one last time. */
671+ AQ_API_MDIO_BlockOperationExecute(gandload_phydev);
672+ countPendingOps = 0;
673+ #endif
674+
675+ /* Note: this final write right-justifies non-dWord data in the final dWord */
676+ switch (byteSize & 0x3)
677+ {
678+ case 0x1:
679+ /* write 1 byte of data */
680+ if (terminatorPtr && (bytePointer >= terminatorPtr) && (bytePointer < terminatorPtr + provTableImageSize))
681+ lsw = provTableImage[bytePointer - terminatorPtr];
682+ else
683+ lsw = image[bytePointer];
684+
685+ bytePointer += 1;
686+
687+ msw = 0x0000;
688+
689+ phy_write_mmd(gandload_phydev, MDIO_MMD_VEND1, VEND1_MAILBOX_INTERFACE5, msw);
690+ phy_write_mmd(gandload_phydev, MDIO_MMD_VEND1, VEND1_MAILBOX_INTERFACE6, lsw);
691+
692+ /* no polling */
693+ phy_write_mmd(gandload_phydev, MDIO_MMD_VEND1, VEND1_MAILBOX_INTERFACE1, mailboxWrite);
694+ break;
695+
696+ case 0x2:
697+ /* write 2 bytes of data */
698+ if (terminatorPtr && (bytePointer >= terminatorPtr) && (bytePointer < terminatorPtr + provTableImageSize))
699+ lsw = provTableImage[bytePointer - terminatorPtr];
700+ else
701+ lsw = image[bytePointer];
702+
703+ if (terminatorPtr && ((bytePointer+1) >= terminatorPtr) && ((bytePointer+1) < terminatorPtr + provTableImageSize))
704+ lsw |= provTableImage[bytePointer + 1 - terminatorPtr] << 8;
705+ else
706+ lsw |= image[bytePointer+1] << 8;
707+
708+ bytePointer += 2;
709+
710+ msw = 0x0000;
711+
712+ phy_write_mmd(gandload_phydev, MDIO_MMD_VEND1, VEND1_MAILBOX_INTERFACE5, msw);
713+ phy_write_mmd(gandload_phydev, MDIO_MMD_VEND1, VEND1_MAILBOX_INTERFACE6, lsw);
714+
715+ /* no polling */
716+ phy_write_mmd(gandload_phydev, MDIO_MMD_VEND1, VEND1_MAILBOX_INTERFACE1, mailboxWrite);
717+ break;
718+
719+ case 0x3:
720+ /* write 3 bytes of data */
721+ if (terminatorPtr && (bytePointer >= terminatorPtr) && (bytePointer < terminatorPtr + provTableImageSize))
722+ lsw = provTableImage[bytePointer - terminatorPtr];
723+ else
724+ lsw = image[bytePointer];
725+
726+ if (terminatorPtr && ((bytePointer+1) >= terminatorPtr) && ((bytePointer+1) < terminatorPtr + provTableImageSize))
727+ lsw |= provTableImage[bytePointer + 1 - terminatorPtr] << 8;
728+ else
729+ lsw |= image[bytePointer+1] << 8;
730+
731+ bytePointer += 2;
732+
733+ if (terminatorPtr && (bytePointer >= terminatorPtr) && (bytePointer < terminatorPtr + provTableImageSize))
734+ msw = provTableImage[bytePointer - terminatorPtr];
735+ else
736+ msw = image[bytePointer];
737+
738+ bytePointer += 1;
739+
740+ phy_write_mmd(gandload_phydev, MDIO_MMD_VEND1, VEND1_MAILBOX_INTERFACE5, msw);
741+ phy_write_mmd(gandload_phydev, MDIO_MMD_VEND1, VEND1_MAILBOX_INTERFACE6, lsw);
742+
743+ /* no polling */
744+ phy_write_mmd(gandload_phydev, MDIO_MMD_VEND1, VEND1_MAILBOX_INTERFACE1, mailboxWrite);
745+ break;
746+ }
747+
748+ if (byteSize & 0x3)
749+ {
750+ /* update the calculated CRC */
751+ crc16Calculated = ((crc16Calculated & 0xFF) << 8) ^ AQ_CRC16Table[(crc16Calculated >> 8) ^ (msw >> 8)];
752+ crc16Calculated = ((crc16Calculated & 0xFF) << 8) ^ AQ_CRC16Table[(crc16Calculated >> 8) ^ (msw & 0xFF)];
753+ crc16Calculated = ((crc16Calculated & 0xFF) << 8) ^ AQ_CRC16Table[(crc16Calculated >> 8) ^ (lsw >> 8)];
754+ crc16Calculated = ((crc16Calculated & 0xFF) << 8) ^ AQ_CRC16Table[(crc16Calculated >> 8) ^ (lsw & 0xFF)];
755+ }
756+
757+ phydev_info(gandload_phydev, "CRC-16 after loading IRAM: 0x%X\n", crc16Calculated);
758+ }
759+
760+ /* load the DRAM */
761+ phydev_info(gandload_phydev, "Loading DRAM:\n");
762+
763+ /* dWord align the address: note the image addressing is byte based, but is properly aligned on dWord
764+ boundaries, so the 2 LSbits of the block start are always zero. */
765+ msw = (uint16_t) (AQ_DRAM_BASE_ADDRESS >> 16);
766+ lsw = (AQ_DRAM_BASE_ADDRESS & 0xFFFF) >> 2;
767+ phy_write_mmd(gandload_phydev, MDIO_MMD_VEND1, VEND1_MAILBOX_INTERFACE3, msw);
768+ phy_write_mmd(gandload_phydev, MDIO_MMD_VEND1, VEND1_MAILBOX_INTERFACE4, lsw);
769+
770+ /* set block size so that there are from 0-3 bytes remaining */
771+ byteSize = primaryDramSize;
772+ dWordSize = byteSize >> 2;
773+
774+ bytePointer = primaryDramPtr;
775+#ifdef AQ_PHY_SUPPORTS_BLOCK_READ_WRITE
776+ countPendingOps = 0;
777+#endif
778+ for (i = 0; i < dWordSize; i++)
779+ {
780+ /* write 4 bytes of data */
781+ if (terminatorPtr && (bytePointer >= terminatorPtr) && (bytePointer < terminatorPtr + provTableImageSize))
782+ lsw = provTableImage[bytePointer - terminatorPtr];
783+ else
784+ lsw = image[bytePointer];
785+
786+ if (terminatorPtr && ((bytePointer+1) >= terminatorPtr) && ((bytePointer+1) < terminatorPtr + provTableImageSize))
787+ lsw |= provTableImage[bytePointer + 1 - terminatorPtr] << 8;
788+ else
789+ lsw |= image[bytePointer+1] << 8;
790+
791+ bytePointer += 2;
792+
793+ if (terminatorPtr && (bytePointer >= terminatorPtr) && (bytePointer < terminatorPtr + provTableImageSize))
794+ msw = provTableImage[bytePointer - terminatorPtr];
795+ else
796+ msw = image[bytePointer];
797+
798+ if (terminatorPtr && ((bytePointer+1) >= terminatorPtr) && ((bytePointer+1) < terminatorPtr + provTableImageSize))
799+ msw |= provTableImage[bytePointer + 1 - terminatorPtr] << 8;
800+ else
801+ msw |= image[bytePointer+1] << 8;
802+
803+ bytePointer += 2;
804+
805+ #ifdef AQ_PHY_SUPPORTS_BLOCK_READ_WRITE
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+
810+ countPendingOps += 3;
811+ /* Check if we've filled our output buffer, and if so, flush. */
812+ #ifdef AQ_EXTRA_FLAGS
813+ if (countPendingOps >= AQ_API_MDIO_MaxBlockOperations(0) - 3)
814+ #else
815+ if (countPendingOps >= AQ_API_MDIO_MaxBlockOperations() - 3)
816+ #endif
817+ {
818+ AQ_API_MDIO_BlockOperationExecute(gandload_phydev);
819+ countPendingOps = 0;
820+ }
821+ #else
822+ phy_write_mmd(gandload_phydev, MDIO_MMD_VEND1, VEND1_MAILBOX_INTERFACE5, msw);
823+ phy_write_mmd(gandload_phydev, MDIO_MMD_VEND1, VEND1_MAILBOX_INTERFACE6, lsw);
824+ phy_write_mmd(gandload_phydev, MDIO_MMD_VEND1, VEND1_MAILBOX_INTERFACE1, mailboxWrite);
825+ #endif
826+
827+ /* update the calculated CRC */
828+ crc16Calculated = ((crc16Calculated & 0xFF) << 8) ^ AQ_CRC16Table[(crc16Calculated >> 8) ^ (msw >> 8)];
829+ crc16Calculated = ((crc16Calculated & 0xFF) << 8) ^ AQ_CRC16Table[(crc16Calculated >> 8) ^ (msw & 0xFF)];
830+ crc16Calculated = ((crc16Calculated & 0xFF) << 8) ^ AQ_CRC16Table[(crc16Calculated >> 8) ^ (lsw >> 8)];
831+ crc16Calculated = ((crc16Calculated & 0xFF) << 8) ^ AQ_CRC16Table[(crc16Calculated >> 8) ^ (lsw & 0xFF)];
832+
833+ #ifdef AQ_VERBOSE
834+ if (i && ((i % 512) == 0)) phydev_info(gandload_phydev, " Byte: %X:\n", i << 2);
835+ #endif
836+ }
837+
838+ #ifdef AQ_PHY_SUPPORTS_BLOCK_READ_WRITE
839+ /* flush the output buffer one last time. */
840+ AQ_API_MDIO_BlockOperationExecute(gandload_phydev);
841+ countPendingOps = 0;
842+ #endif
843+
844+ /* Note: this final write right-justifies non-dWord data in the final dWord */
845+ switch (byteSize & 0x3)
846+ {
847+ case 0x1:
848+ /* write 1 byte of data */
849+ if (terminatorPtr && (bytePointer >= terminatorPtr) && (bytePointer < terminatorPtr + provTableImageSize))
850+ lsw = provTableImage[bytePointer - terminatorPtr];
851+ else
852+ lsw = image[bytePointer];
853+
854+ bytePointer += 1;
855+
856+ msw = 0x0000;
857+
858+ phy_write_mmd(gandload_phydev, MDIO_MMD_VEND1, VEND1_MAILBOX_INTERFACE5, msw);
859+ phy_write_mmd(gandload_phydev, MDIO_MMD_VEND1, VEND1_MAILBOX_INTERFACE6, lsw);
860+
861+ /* no polling */
862+ phy_write_mmd(gandload_phydev, MDIO_MMD_VEND1, VEND1_MAILBOX_INTERFACE1, mailboxWrite);
863+ break;
864+
865+ case 0x2:
866+ /* write 2 bytes of data */
867+ if (terminatorPtr && (bytePointer >= terminatorPtr) && (bytePointer < terminatorPtr + provTableImageSize))
868+ lsw = provTableImage[bytePointer - terminatorPtr];
869+ else
870+ lsw = image[bytePointer];
871+
872+ if (terminatorPtr && ((bytePointer+1) >= terminatorPtr) && ((bytePointer+1) < terminatorPtr + provTableImageSize))
873+ lsw |= provTableImage[bytePointer + 1 - terminatorPtr] << 8;
874+ else
875+ lsw |= image[bytePointer+1] << 8;
876+
877+ bytePointer += 2;
878+
879+ msw = 0x0000;
880+
881+ phy_write_mmd(gandload_phydev, MDIO_MMD_VEND1, VEND1_MAILBOX_INTERFACE5, msw);
882+ phy_write_mmd(gandload_phydev, MDIO_MMD_VEND1, VEND1_MAILBOX_INTERFACE6, lsw);
883+
884+ /* no polling */
885+ phy_write_mmd(gandload_phydev, MDIO_MMD_VEND1, VEND1_MAILBOX_INTERFACE1, mailboxWrite);
886+ break;
887+
888+ case 0x3:
889+ /* write 3 bytes of data */
890+ if (terminatorPtr && (bytePointer >= terminatorPtr) && (bytePointer < terminatorPtr + provTableImageSize))
891+ lsw = provTableImage[bytePointer - terminatorPtr];
892+ else
893+ lsw = image[bytePointer];
894+
895+ if (terminatorPtr && ((bytePointer+1) >= terminatorPtr) && ((bytePointer+1) < terminatorPtr + provTableImageSize))
896+ lsw |= provTableImage[bytePointer + 1 - terminatorPtr] << 8;
897+ else
898+ lsw |= image[bytePointer+1] << 8;
899+
900+ bytePointer += 2;
901+
902+ msw = image[bytePointer];
903+ bytePointer += 1;
904+
905+ phy_write_mmd(gandload_phydev, MDIO_MMD_VEND1, VEND1_MAILBOX_INTERFACE5, msw);
906+ phy_write_mmd(gandload_phydev, MDIO_MMD_VEND1, VEND1_MAILBOX_INTERFACE6, lsw);
907+
908+ /* no polling */
909+ phy_write_mmd(gandload_phydev, MDIO_MMD_VEND1, VEND1_MAILBOX_INTERFACE1, mailboxWrite);
910+ break;
911+ }
912+
913+ if (byteSize & 0x3)
914+ {
915+ /* update the calculated CRC */
916+ crc16Calculated = ((crc16Calculated & 0xFF) << 8) ^ AQ_CRC16Table[(crc16Calculated >> 8) ^ (msw >> 8)];
917+ crc16Calculated = ((crc16Calculated & 0xFF) << 8) ^ AQ_CRC16Table[(crc16Calculated >> 8) ^ (msw & 0xFF)];
918+ crc16Calculated = ((crc16Calculated & 0xFF) << 8) ^ AQ_CRC16Table[(crc16Calculated >> 8) ^ (lsw >> 8)];
919+ crc16Calculated = ((crc16Calculated & 0xFF) << 8) ^ AQ_CRC16Table[(crc16Calculated >> 8) ^ (lsw & 0xFF)];
920+ }
921+
922+ /*------------------------------------- Exit gangload mode -------------------------------------------------------*/
923+ AQ_API_DisableGangLoadMode(gandload_phydev, recordedGGP1Values[0]);
924+
925+ /*------------------------------------- Check mailbox CRCs -------------------------------------------------------*/
926+ /* check to make sure the mailbox CRC matches the calculated CRC */
927+ for (j = 0; j < num_phydevs; j++) {
928+ mailboxCRC = phy_read_mmd(phydevs[j], MDIO_MMD_VEND1, VEND1_MAILBOX_INTERFACE2);
929+ if (mailboxCRC != crc16Calculated)
930+ {
931+ phydev_err(phydevs[j], "%uth port: Mailbox CRC-16 (0x%X) does not match calculated CRC-16 (0x%X)\n",
932+ j, mailboxCRC, crc16Calculated);
933+ result[j] = -EIO;
934+ }
935+ else
936+ {
937+ phydev_info(phydevs[j], "%uth port: Image load good - mailbox CRC-16 matches (0x%X)\n",
938+ j, mailboxCRC);
939+ }
940+ }
941+
942+ /*------------------------------------- Clear any resets ---------------------------------------------------------*/
943+ for (j = 0; j < num_phydevs; j++) {
944+ phy_write_mmd(phydevs[j], MDIO_MMD_VEND1, VEND1_STD_CONTROL1, 0x0000);
945+ }
946+
947+ /*------------------------------------- Release the uP -----------------------------------------------------------*/
948+ globalControl = 0x0000;
949+ globalControl |= VEND1_CONTROL2_UP_RUNSTALL_OVERRIDE;
950+ globalControl |= VEND1_CONTROL2_UP_RUNSTALL;
951+ for (j = 0; j < num_phydevs; j++) {
952+ globalControl &= ~VEND1_CONTROL2_UP_RESET;
953+ phy_write_mmd(phydevs[j], MDIO_MMD_VEND1, VEND1_CONTROL2, globalControl);
954+ globalControl |= VEND1_CONTROL2_UP_RESET;
955+ phy_write_mmd(phydevs[j], MDIO_MMD_VEND1, VEND1_CONTROL2, globalControl);
956+ }
957+
958+ /* Need to wait at least 100us. */
959+ udelay(100);
960+
961+ globalControl &= ~VEND1_CONTROL2_UP_RESET;
962+ globalControl &= ~VEND1_CONTROL2_UP_RUNSTALL;
963+ /* For post-APPIA devices, always set the uP stall override bit to
964+ * smooth over any packaging differences WRT the boot load pin. */
965+ /* REGDOC: Assign to local representation of bitfield (HHD/APPIA/EUR/CAL/RHEA: 1E.C001.6) */
966+ globalControl |= VEND1_CONTROL2_UP_RUNSTALL_OVERRIDE;
967+
968+ for (j = 0; j < num_phydevs; j++) {
969+ phy_write_mmd(phydevs[j], MDIO_MMD_VEND1, VEND1_CONTROL2, globalControl);
970+ }
971+
972+ /* NOTE!!! We can't re-enable the daisy-chain here, as this will overwrite the IRAM and DRAM with the FLASH contents*/
973+
974+ /* If any of the ports was not bootloaded successfully, return AQ_RET_ERROR */
975+ for (j = 0; j < num_phydevs; j++) {
976+ if (result[j] != 0)
977+ return -EIO;
978+ }
979+
980+ /* All ports were bootloaded successfully. */
981+ return 0;
982+}
983+
984+static int AQ_API_WriteBootLoadImage(
985+ struct phy_device **phydevs,
986+ int num_phydevs,
987+ struct phy_device *gandload_phydev,
988+ int *result,
989+ const uint8_t* data,
990+ size_t size)
991+{
992+ unsigned int val;
993+ int j;
994+
995+ for (j = 0; j < num_phydevs; j++) {
developer3c737eb2022-12-09 09:44:16 +0800996+ /* stall the uP */
997+ val = phy_read_mmd(phydevs[j], MDIO_MMD_VEND1, VEND1_CONTROL2);
998+ val |= VEND1_CONTROL2_UP_RUNSTALL_OVERRIDE;
999+ val |= VEND1_CONTROL2_UP_RUNSTALL;
1000+ phy_write_mmd(phydevs[j], MDIO_MMD_VEND1, VEND1_CONTROL2, val);
1001+
developer122ffbb2022-11-14 12:07:10 +08001002+ /* disable the S/W reset to the Global MMD registers */
1003+ val = phy_read_mmd(phydevs[j], MDIO_MMD_VEND1, VEND1_RESET_CONTROL);
1004+ val |= VEND1_RESET_CONTROL_MMD_RESET_DISABLE;
1005+ phy_write_mmd(phydevs[j], MDIO_MMD_VEND1, VEND1_RESET_CONTROL, val);
1006+
developer3c737eb2022-12-09 09:44:16 +08001007+ /* de-assert Global S/W reset */
1008+ val = phy_read_mmd(phydevs[j], MDIO_MMD_VEND1, VEND1_STD_CONTROL1);
1009+ val &= ~VEND1_STD_CONTROL1_SOFT_RESET;
1010+ phy_write_mmd(phydevs[j], MDIO_MMD_VEND1, VEND1_STD_CONTROL1, val);
1011+
developer122ffbb2022-11-14 12:07:10 +08001012+ /* assert Global S/W reset */
1013+ val = phy_read_mmd(phydevs[j], MDIO_MMD_VEND1, VEND1_STD_CONTROL1);
1014+ val |= VEND1_STD_CONTROL1_SOFT_RESET;
1015+ phy_write_mmd(phydevs[j], MDIO_MMD_VEND1, VEND1_STD_CONTROL1, val);
1016+
1017+ /* de-assert Global S/W reset */
1018+ val = phy_read_mmd(phydevs[j], MDIO_MMD_VEND1, VEND1_STD_CONTROL1);
1019+ val &= ~VEND1_STD_CONTROL1_SOFT_RESET;
1020+ phy_write_mmd(phydevs[j], MDIO_MMD_VEND1, VEND1_STD_CONTROL1, val);
1021+
1022+ /* wait 100ms */
1023+ mdelay(100);
1024+
1025+ /* enable the S/W reset to the Global MMD registers */
1026+ val = phy_read_mmd(phydevs[j], MDIO_MMD_VEND1, VEND1_RESET_CONTROL);
1027+ val &= ~VEND1_RESET_CONTROL_MMD_RESET_DISABLE;
1028+ phy_write_mmd(phydevs[j], MDIO_MMD_VEND1, VEND1_RESET_CONTROL, val);
1029+ }
1030+
1031+ return AQ_API_WriteBootLoadImage_impl(phydevs, num_phydevs, gandload_phydev,
1032+ result, (const uint32_t *)&size, data,
1033+ NULL, NULL, 0);
1034+}
1035+
developeraafac652023-01-18 09:41:27 +08001036+static int aqr_firmware_check_heartbeat(struct phy_device *phydev)
1037+{
developer7ddeff02023-03-22 15:28:46 +08001038+ struct aqr107_priv *priv = phydev->priv;
1039+ int stopped = 0, ret;
developeraafac652023-01-18 09:41:27 +08001040+
1041+ ret = phy_read_mmd(phydev, MDIO_MMD_VEND1, VEND1_GLOBAL_RSVD_STAT2);
1042+ if (ret < 0)
1043+ return ret;
1044+
developer08abacf2023-05-18 15:52:22 +08001045+ /* heartbeat stopped if the current heartbeat is equal to the previous */
developer7ddeff02023-03-22 15:28:46 +08001046+ if (priv->heartbeat == ret)
1047+ stopped = 1;
developeraafac652023-01-18 09:41:27 +08001048+
developer08abacf2023-05-18 15:52:22 +08001049+ /* update heartbeat to the private data */
developer7ddeff02023-03-22 15:28:46 +08001050+ priv->heartbeat = ret;
developeraafac652023-01-18 09:41:27 +08001051+
developer7ddeff02023-03-22 15:28:46 +08001052+ return stopped;
developeraafac652023-01-18 09:41:27 +08001053+}
1054+
developer08abacf2023-05-18 15:52:22 +08001055+int aqr_firmware_heartbeat_thread(void *data)
developeraafac652023-01-18 09:41:27 +08001056+{
1057+ struct phy_device *phydev = data;
1058+ struct aqr107_priv *priv = phydev->priv;
developer7ddeff02023-03-22 15:28:46 +08001059+ struct device *dev;
developeraafac652023-01-18 09:41:27 +08001060+ int ret = 0;
1061+
developer7ddeff02023-03-22 15:28:46 +08001062+ dev = &phydev->mdio.dev;
1063+
developeraafac652023-01-18 09:41:27 +08001064+ for (;;) {
1065+ if (kthread_should_stop())
1066+ break;
1067+
developer08abacf2023-05-18 15:52:22 +08001068+ if (priv->fw_initialized == true &&
developera3617672023-01-31 10:46:41 +08001069+ aqr_firmware_check_heartbeat(phydev) == 1) {
developer7ddeff02023-03-22 15:28:46 +08001070+ dev_err(dev, "Detect heartbeat stopped, start to realod firmware...\n");
developeraafac652023-01-18 09:41:27 +08001071+ priv->fw_initialized = false;
developer08abacf2023-05-18 15:52:22 +08001072+ priv->fw_dl_mode = FW_DL_SINGLE;
developeraafac652023-01-18 09:41:27 +08001073+ aqr_firmware_download_single(phydev);
1074+ }
1075+
1076+ set_current_state(TASK_INTERRUPTIBLE);
developer05838f02023-03-23 15:54:37 +08001077+ schedule_timeout(2 * HZ);
developeraafac652023-01-18 09:41:27 +08001078+ }
1079+
1080+ return ret;
1081+}
1082+
developer122ffbb2022-11-14 12:07:10 +08001083+static void aqr_firmware_download_cb(const struct firmware *fw, void *context)
1084+{
1085+ struct phy_device **phydevs = context;
1086+ struct phy_device *gandload_phydev = phydevs[0];
developer08abacf2023-05-18 15:52:22 +08001087+ struct device *dev = &phydevs[0]->mdio.dev;
developer093e9b32022-12-13 16:08:34 +08001088+ struct aqr107_priv *priv = phydevs[0]->priv;
developer122ffbb2022-11-14 12:07:10 +08001089+ int result[MAX_GANGLOAD_DEVICES];
developer093e9b32022-12-13 16:08:34 +08001090+ int i, num_phydevs = 0, ret = 0;
developer122ffbb2022-11-14 12:07:10 +08001091+
developer94316402022-11-21 08:58:41 +08001092+ if (!fw)
1093+ return;
1094+
developer093e9b32022-12-13 16:08:34 +08001095+ num_phydevs = priv->fw_dl_mode == FW_DL_GNAGLOAD ?
developer9451bcd2023-07-18 09:34:05 +08001096+ gangload : 1;
developer3c737eb2022-12-09 09:44:16 +08001097+
developer122ffbb2022-11-14 12:07:10 +08001098+retry:
developer7ddeff02023-03-22 15:28:46 +08001099+ if (gandload_phydev->state == PHY_HALTED) {
developer7ddeff02023-03-22 15:28:46 +08001100+ dev_info(dev, "Detect PHY power down, stop to reload firmware...\n");
1101+ goto out;
1102+ }
1103+
developer122ffbb2022-11-14 12:07:10 +08001104+ memset(result, 0, sizeof(result));
1105+
developer093e9b32022-12-13 16:08:34 +08001106+ ret = AQ_API_WriteBootLoadImage(phydevs, num_phydevs, gandload_phydev,
developer122ffbb2022-11-14 12:07:10 +08001107+ result, fw->data, fw->size);
1108+ if (ret) {
developer093e9b32022-12-13 16:08:34 +08001109+ for (i = 0; i < num_phydevs; i++) {
developer94316402022-11-21 08:58:41 +08001110+ if (result[i] == 0)
developer122ffbb2022-11-14 12:07:10 +08001111+ continue;
developer122ffbb2022-11-14 12:07:10 +08001112+
1113+ dev = &phydevs[i]->mdio.dev;
1114+ dev_err(dev, "failed to download firmware %s, ret: %d\n",
1115+ AQR_FIRMWARE, ret);
1116+ goto retry;
1117+ }
1118+ }
1119+
developer55398292022-12-14 19:03:08 +08001120+ /* wait firmware initialization completed */
developer94316402022-11-21 08:58:41 +08001121+ mdelay(250);
developer55398292022-12-14 19:03:08 +08001122+
developer093e9b32022-12-13 16:08:34 +08001123+ for (i = 0; i < num_phydevs; i++) {
developer94316402022-11-21 08:58:41 +08001124+ if (result[i] == 0) {
developer08abacf2023-05-18 15:52:22 +08001125+ dev = &phydevs[i]->mdio.dev;
developer94316402022-11-21 08:58:41 +08001126+ priv = phydevs[i]->priv;
1127+ priv->fw_initialized = true;
developer3c737eb2022-12-09 09:44:16 +08001128+
developer08abacf2023-05-18 15:52:22 +08001129+ aqr107_chip_info(phydevs[i]);
1130+
developer94316402022-11-21 08:58:41 +08001131+ aqr107_config_mdi(phydevs[i]);
developer3c737eb2022-12-09 09:44:16 +08001132+
developer08abacf2023-05-18 15:52:22 +08001133+ aqr107_set_downshift(phydevs[i],
1134+ MDIO_AN_VEND_PROV_DOWNSHIFT_DFLT);
1135+
1136+ if (phy_is_started(phydevs[i])) {
developer093e9b32022-12-13 16:08:34 +08001137+ phydevs[i]->state = PHY_UP;
1138+ phy_queue_state_machine(phydevs[i], 0);
1139+ }
developer94316402022-11-21 08:58:41 +08001140+ }
1141+ }
developer7ddeff02023-03-22 15:28:46 +08001142+out:
developer122ffbb2022-11-14 12:07:10 +08001143+ release_firmware(fw);
1144+}
1145+
developeraafac652023-01-18 09:41:27 +08001146+static int aqr_firmware_download_single(struct phy_device *phydev)
developer122ffbb2022-11-14 12:07:10 +08001147+{
1148+ struct aqr107_priv *priv = phydev->priv;
1149+ struct device *dev = &phydev->mdio.dev;
developer093e9b32022-12-13 16:08:34 +08001150+ const struct firmware *fw;
developer122ffbb2022-11-14 12:07:10 +08001151+ int ret = 0;
1152+
1153+ if (priv->fw_initialized == true)
1154+ return 0;
1155+
developer08abacf2023-05-18 15:52:22 +08001156+ spin_lock_init(&priv->lock);
developer093e9b32022-12-13 16:08:34 +08001157+ priv->fw_dl_mode = FW_DL_SINGLE;
developer122ffbb2022-11-14 12:07:10 +08001158+ priv->phydevs[0] = phydev;
developer7ddeff02023-03-22 15:28:46 +08001159+ priv->heartbeat = -1;
developer122ffbb2022-11-14 12:07:10 +08001160+
developer093e9b32022-12-13 16:08:34 +08001161+ ret = request_firmware(&fw, AQR_FIRMWARE, dev);
developer122ffbb2022-11-14 12:07:10 +08001162+ if (ret) {
developer08abacf2023-05-18 15:52:22 +08001163+ dev_err(dev, "failed to request firmware %s, ret: %d\n",
developer122ffbb2022-11-14 12:07:10 +08001164+ AQR_FIRMWARE, ret);
1165+ }
1166+
developer093e9b32022-12-13 16:08:34 +08001167+ aqr_firmware_download_cb(fw, priv->phydevs);
1168+
developer122ffbb2022-11-14 12:07:10 +08001169+ return ret;
1170+}
1171+
1172+static int aqr_firmware_gandload_thread(void *data)
1173+{
1174+ struct phy_device **phydevs = data;
1175+ struct device *dev = &phydevs[0]->mdio.dev;
1176+ int ret = 0;
1177+
1178+ for (;;) {
1179+ if (kthread_should_stop())
1180+ break;
1181+
developer9451bcd2023-07-18 09:34:05 +08001182+ /* either maximum gangload phy devices or timeout is reached */
1183+ if (gangload == MAX_GANGLOAD_DEVICES ||
1184+ time_after(jiffies, gangload_timeout)) {
developer122ffbb2022-11-14 12:07:10 +08001185+ ret = request_firmware_nowait(THIS_MODULE, true, AQR_FIRMWARE, dev,
1186+ GFP_KERNEL, phydevs, aqr_firmware_download_cb);
1187+ if (ret) {
developer08abacf2023-05-18 15:52:22 +08001188+ dev_err(dev, "failed to request firmware %s, ret: %d\n",
developer122ffbb2022-11-14 12:07:10 +08001189+ AQR_FIRMWARE, ret);
1190+ }
1191+ break;
1192+ }
1193+
1194+ set_current_state(TASK_INTERRUPTIBLE);
1195+ msleep(1);
1196+ }
1197+
1198+ return ret;
1199+}
1200+
1201+static int aqr_firmware_download_gang(struct phy_device *phydev)
1202+{
1203+ struct aqr107_priv *priv = phydev->priv;
1204+ struct device *dev = &phydev->mdio.dev;
developer3c737eb2022-12-09 09:44:16 +08001205+ int i;
developer122ffbb2022-11-14 12:07:10 +08001206+
1207+ if (priv->fw_initialized == true)
1208+ return 0;
1209+
1210+ if (!gangload_kthread) {
developer9451bcd2023-07-18 09:34:05 +08001211+ /* setup a maximum wait time limit for gangload mode */
1212+ gangload_timeout = jiffies + 5 * HZ;
1213+
developer122ffbb2022-11-14 12:07:10 +08001214+ /* create a thread for monitor gangload devices */
1215+ gangload_kthread = kthread_create(aqr_firmware_gandload_thread,
1216+ gangload_phydevs,
1217+ "aqr_firmware_gandload_thread");
1218+ if (IS_ERR(gangload_kthread)) {
1219+ dev_err(dev,
developerf3048b62023-06-05 18:00:04 +08001220+ "failed to create aqr_firmware_gandload_thread(%ld)\n",
1221+ PTR_ERR(gangload_kthread));
developer122ffbb2022-11-14 12:07:10 +08001222+ return PTR_ERR(gangload_kthread);
1223+ }
1224+ wake_up_process(gangload_kthread);
1225+ }
1226+
developer9451bcd2023-07-18 09:34:05 +08001227+ /* fall back to single mode if timeout is reached */
1228+ if (time_after(jiffies, gangload_timeout))
1229+ return aqr_firmware_download_single(phydev);
1230+
developer3c737eb2022-12-09 09:44:16 +08001231+ for (i = 0; i < gangload; i++) {
1232+ if (gangload_phydevs[i] == phydev) {
developer08abacf2023-05-18 15:52:22 +08001233+ dev_warn(dev, "Detect duplicate gangload phydev\n");
developer3c737eb2022-12-09 09:44:16 +08001234+ return -EINVAL;
1235+ }
1236+ }
1237+
developer08abacf2023-05-18 15:52:22 +08001238+ spin_lock_init(&priv->lock);
developer093e9b32022-12-13 16:08:34 +08001239+ priv->fw_dl_mode = FW_DL_GNAGLOAD;
developer7ddeff02023-03-22 15:28:46 +08001240+ priv->heartbeat = -1;
developer122ffbb2022-11-14 12:07:10 +08001241+ gangload_phydevs[gangload] = phydev;
1242+ gangload++;
1243+
1244+ return 0;
1245+}
1246+
1247+int aqr_firmware_download(struct phy_device *phydev)
1248+{
1249+ int ret = 0;
1250+#ifdef CONFIG_AQUANTIA_PHY_FW_DOWNLOAD_SINGLE
1251+ ret = aqr_firmware_download_single(phydev);
1252+#elif CONFIG_AQUANTIA_PHY_FW_DOWNLOAD_GANG
1253+ ret = aqr_firmware_download_gang(phydev);
1254+#endif
1255+ return ret;
1256+}
1257diff --git a/drivers/net/phy/aquantia_main.c b/drivers/net/phy/aquantia_main.c
developer5d148cb2023-06-02 13:08:11 +08001258index e7495c9a7..36f1aac4f 100644
developer122ffbb2022-11-14 12:07:10 +08001259--- a/drivers/net/phy/aquantia_main.c
1260+++ b/drivers/net/phy/aquantia_main.c
developer301205c2023-05-24 15:39:32 +08001261@@ -8,10 +8,12 @@
developeraafac652023-01-18 09:41:27 +08001262 */
developer08abacf2023-05-18 15:52:22 +08001263
developeraafac652023-01-18 09:41:27 +08001264 #include <linux/kernel.h>
1265+#include <linux/kthread.h>
1266 #include <linux/module.h>
1267 #include <linux/delay.h>
1268 #include <linux/bitfield.h>
developer301205c2023-05-24 15:39:32 +08001269 #include <linux/phy.h>
1270+#include <linux/of.h>
1271
1272 #include "aquantia.h"
1273
developer5d148cb2023-06-02 13:08:11 +08001274@@ -39,7 +41,6 @@
developer08abacf2023-05-18 15:52:22 +08001275 #define MDIO_AN_VEND_PROV_2500BASET_FULL BIT(10)
1276 #define MDIO_AN_VEND_PROV_DOWNSHIFT_EN BIT(4)
1277 #define MDIO_AN_VEND_PROV_DOWNSHIFT_MASK GENMASK(3, 0)
1278-#define MDIO_AN_VEND_PROV_DOWNSHIFT_DFLT 4
1279
1280 #define MDIO_AN_TX_VEND_STATUS1 0xc800
1281 #define MDIO_AN_TX_VEND_STATUS1_RATE_MASK GENMASK(3, 1)
developer5d148cb2023-06-02 13:08:11 +08001282@@ -73,18 +74,6 @@
developer122ffbb2022-11-14 12:07:10 +08001283 #define MDIO_AN_RX_VEND_STAT3 0xe832
1284 #define MDIO_AN_RX_VEND_STAT3_AFR BIT(0)
1285
1286-/* MDIO_MMD_C22EXT */
1287-#define MDIO_C22EXT_STAT_SGMII_RX_GOOD_FRAMES 0xd292
1288-#define MDIO_C22EXT_STAT_SGMII_RX_BAD_FRAMES 0xd294
1289-#define MDIO_C22EXT_STAT_SGMII_RX_FALSE_CARRIER 0xd297
1290-#define MDIO_C22EXT_STAT_SGMII_TX_GOOD_FRAMES 0xd313
1291-#define MDIO_C22EXT_STAT_SGMII_TX_BAD_FRAMES 0xd315
1292-#define MDIO_C22EXT_STAT_SGMII_TX_FALSE_CARRIER 0xd317
1293-#define MDIO_C22EXT_STAT_SGMII_TX_COLLISIONS 0xd318
1294-#define MDIO_C22EXT_STAT_SGMII_TX_LINE_COLLISIONS 0xd319
1295-#define MDIO_C22EXT_STAT_SGMII_TX_FRAME_ALIGN_ERR 0xd31a
1296-#define MDIO_C22EXT_STAT_SGMII_TX_RUNT_FRAMES 0xd31b
1297-
1298 /* Vendor specific 1, MDIO_MMD_VEND1 */
1299 #define VEND1_GLOBAL_FW_ID 0x0020
1300 #define VEND1_GLOBAL_FW_ID_MAJOR GENMASK(15, 8)
developer5d148cb2023-06-02 13:08:11 +08001301@@ -124,31 +113,6 @@
developer122ffbb2022-11-14 12:07:10 +08001302 #define VEND1_GLOBAL_INT_VEND_MASK_GLOBAL2 BIT(1)
1303 #define VEND1_GLOBAL_INT_VEND_MASK_GLOBAL3 BIT(0)
1304
1305-struct aqr107_hw_stat {
1306- const char *name;
1307- int reg;
1308- int size;
1309-};
1310-
1311-#define SGMII_STAT(n, r, s) { n, MDIO_C22EXT_STAT_SGMII_ ## r, s }
1312-static const struct aqr107_hw_stat aqr107_hw_stats[] = {
1313- SGMII_STAT("sgmii_rx_good_frames", RX_GOOD_FRAMES, 26),
1314- SGMII_STAT("sgmii_rx_bad_frames", RX_BAD_FRAMES, 26),
1315- SGMII_STAT("sgmii_rx_false_carrier_events", RX_FALSE_CARRIER, 8),
1316- SGMII_STAT("sgmii_tx_good_frames", TX_GOOD_FRAMES, 26),
1317- SGMII_STAT("sgmii_tx_bad_frames", TX_BAD_FRAMES, 26),
1318- SGMII_STAT("sgmii_tx_false_carrier_events", TX_FALSE_CARRIER, 8),
1319- SGMII_STAT("sgmii_tx_collisions", TX_COLLISIONS, 8),
1320- SGMII_STAT("sgmii_tx_line_collisions", TX_LINE_COLLISIONS, 8),
1321- SGMII_STAT("sgmii_tx_frame_alignment_err", TX_FRAME_ALIGN_ERR, 16),
1322- SGMII_STAT("sgmii_tx_runt_frames", TX_RUNT_FRAMES, 22),
1323-};
1324-#define AQR107_SGMII_STAT_SZ ARRAY_SIZE(aqr107_hw_stats)
1325-
1326-struct aqr107_priv {
1327- u64 sgmii_stats[AQR107_SGMII_STAT_SZ];
1328-};
1329-
1330 static int aqr107_get_sset_count(struct phy_device *phydev)
1331 {
1332 return AQR107_SGMII_STAT_SZ;
developer5d148cb2023-06-02 13:08:11 +08001333@@ -398,7 +362,7 @@ static int aqr107_get_downshift(struct phy_device *phydev, u8 *data)
developer08abacf2023-05-18 15:52:22 +08001334 return 0;
1335 }
1336
1337-static int aqr107_set_downshift(struct phy_device *phydev, u8 cnt)
1338+int aqr107_set_downshift(struct phy_device *phydev, u8 cnt)
1339 {
1340 int val = 0;
1341
developer5d148cb2023-06-02 13:08:11 +08001342@@ -458,7 +422,7 @@ static int aqr107_wait_reset_complete(struct phy_device *phydev)
developer08abacf2023-05-18 15:52:22 +08001343 return val ? 0 : -ETIMEDOUT;
1344 }
1345
1346-static void aqr107_chip_info(struct phy_device *phydev)
1347+void aqr107_chip_info(struct phy_device *phydev)
1348 {
1349 u8 fw_major, fw_minor, build_id, prov_id;
1350 int val;
developer5d148cb2023-06-02 13:08:11 +08001351@@ -481,6 +445,21 @@ static void aqr107_chip_info(struct phy_device *phydev)
developer94316402022-11-21 08:58:41 +08001352 fw_major, fw_minor, build_id, prov_id);
1353 }
1354
1355+int aqr107_config_mdi(struct phy_device *phydev)
1356+{
developer301205c2023-05-24 15:39:32 +08001357+ struct device_node *np = phydev->mdio.dev.of_node;
1358+ u16 val;
1359+
1360+ if (of_property_read_u16(np, "mdi-reversal", &val))
1361+ return -ENOENT;
1362+
1363+ if (!FIELD_FIT(PMAPMD_RSVD_VEND_PROV_MDI_CONF, val))
1364+ return -E2BIG;
1365+
developer94316402022-11-21 08:58:41 +08001366+ return phy_modify_mmd(phydev, MDIO_MMD_PMAPMD, PMAPMD_RSVD_VEND_PROV,
developer301205c2023-05-24 15:39:32 +08001367+ PMAPMD_RSVD_VEND_PROV_MDI_CONF, val);
developer94316402022-11-21 08:58:41 +08001368+}
1369+
1370 static int aqr107_config_init(struct phy_device *phydev)
1371 {
1372 int ret;
developer5d148cb2023-06-02 13:08:11 +08001373@@ -499,6 +478,12 @@ static int aqr107_config_init(struct phy_device *phydev)
developer08abacf2023-05-18 15:52:22 +08001374 ret = aqr107_wait_reset_complete(phydev);
developer122ffbb2022-11-14 12:07:10 +08001375 if (!ret)
1376 aqr107_chip_info(phydev);
developer122ffbb2022-11-14 12:07:10 +08001377+#ifdef CONFIG_AQUANTIA_PHY_FW_DOWNLOAD
developer08abacf2023-05-18 15:52:22 +08001378+ else
1379+ return aqr_firmware_download(phydev);
developer122ffbb2022-11-14 12:07:10 +08001380+#endif
1381+
developer08abacf2023-05-18 15:52:22 +08001382+ aqr107_config_mdi(phydev);
developer08abacf2023-05-18 15:52:22 +08001383
developerd7641da2023-02-24 13:56:03 +08001384 return aqr107_set_downshift(phydev, MDIO_AN_VEND_PROV_DOWNSHIFT_DFLT);
1385 }
developerf3048b62023-06-05 18:00:04 +08001386@@ -574,12 +559,41 @@ static void aqr107_link_change_notify(struct phy_device *phydev)
developer122ffbb2022-11-14 12:07:10 +08001387
developer08abacf2023-05-18 15:52:22 +08001388 static int aqr107_suspend(struct phy_device *phydev)
1389 {
developeraafac652023-01-18 09:41:27 +08001390+#ifdef CONFIG_AQUANTIA_PHY_FW_DOWNLOAD
1391+ struct aqr107_priv *priv = phydev->priv;
1392+
developer08abacf2023-05-18 15:52:22 +08001393+ spin_lock(&priv->lock);
1394+ if (priv->heartbeat_thread) {
1395+ kthread_stop(priv->heartbeat_thread);
1396+ priv->heartbeat_thread = NULL;
1397+ priv->heartbeat = -1;
1398+ }
1399+ spin_unlock(&priv->lock);
developeraafac652023-01-18 09:41:27 +08001400+#endif
developer08abacf2023-05-18 15:52:22 +08001401 return phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, MDIO_CTRL1,
1402 MDIO_CTRL1_LPOWER);
1403 }
developeraafac652023-01-18 09:41:27 +08001404
developer08abacf2023-05-18 15:52:22 +08001405 static int aqr107_resume(struct phy_device *phydev)
1406 {
1407+#ifdef CONFIG_AQUANTIA_PHY_FW_DOWNLOAD
1408+ struct aqr107_priv *priv = phydev->priv;
1409+
1410+ spin_lock(&priv->lock);
1411+ if (!priv->heartbeat_thread) {
1412+ priv->heartbeat_thread = kthread_create(aqr_firmware_heartbeat_thread,
1413+ phydev,
1414+ "aqr_firmware_heartbeat_thread");
1415+ if (IS_ERR(priv->heartbeat_thread)) {
1416+ phydev_err(phydev,
developerf3048b62023-06-05 18:00:04 +08001417+ "Failed to create aqr_firmware_heartbeat_thread(%ld)\n",
1418+ PTR_ERR(priv->heartbeat_thread));
1419+ priv->heartbeat_thread = NULL;
1420+ } else
1421+ wake_up_process(priv->heartbeat_thread);
developer08abacf2023-05-18 15:52:22 +08001422+ }
1423+ spin_unlock(&priv->lock);
1424+#endif
1425 return phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, MDIO_CTRL1,
1426 MDIO_CTRL1_LPOWER);
1427 }
developer5d148cb2023-06-02 13:08:11 +08001428--
14292.34.1
1430