1 // SPDX-License-Identifier: GPL-2.0
3 #include <linux/bitfield.h>
5 #include <linux/firmware.h>
6 #include <linux/crc-itu-t.h>
7 #include <linux/nvmem-consumer.h>
9 #include <linux/unaligned.h>
13 #define UP_RESET_SLEEP 100
15 /* addresses of memory segments in the phy */
16 #define DRAM_BASE_ADDR 0x3FFE0000
17 #define IRAM_BASE_ADDR 0x40000000
19 /* firmware image format constants */
20 #define VERSION_STRING_SIZE 0x40
21 #define VERSION_STRING_OFFSET 0x0200
22 /* primary offset is written at an offset from the start of the fw blob */
23 #define PRIMARY_OFFSET_OFFSET 0x8
24 /* primary offset needs to be then added to a base offset */
25 #define PRIMARY_OFFSET_SHIFT 12
26 #define PRIMARY_OFFSET(x) ((x) << PRIMARY_OFFSET_SHIFT)
27 #define HEADER_OFFSET 0x300
29 struct aqr_fw_header
{
42 static const char * const aqr_fw_src_string
[] = {
43 [AQR_FW_SRC_NVMEM
] = "NVMEM",
44 [AQR_FW_SRC_FS
] = "FS",
47 /* AQR firmware doesn't have fixed offsets for iram and dram section
48 * but instead provide an header with the offset to use on reading
49 * and parsing the firmware.
51 * AQR firmware can't be trusted and each offset is validated to be
52 * not negative and be in the size of the firmware itself.
54 static bool aqr_fw_validate_get(size_t size
, size_t offset
, size_t get_size
)
56 return offset
+ get_size
<= size
;
59 static int aqr_fw_get_be16(const u8
*data
, size_t offset
, size_t size
, u16
*value
)
61 if (!aqr_fw_validate_get(size
, offset
, sizeof(u16
)))
64 *value
= get_unaligned_be16(data
+ offset
);
69 static int aqr_fw_get_le16(const u8
*data
, size_t offset
, size_t size
, u16
*value
)
71 if (!aqr_fw_validate_get(size
, offset
, sizeof(u16
)))
74 *value
= get_unaligned_le16(data
+ offset
);
79 static int aqr_fw_get_le24(const u8
*data
, size_t offset
, size_t size
, u32
*value
)
81 if (!aqr_fw_validate_get(size
, offset
, sizeof(u8
) * 3))
84 *value
= get_unaligned_le24(data
+ offset
);
89 /* load data into the phy's memory */
90 static int aqr_fw_load_memory(struct phy_device
*phydev
, u32 addr
,
91 const u8
*data
, size_t len
)
96 phy_write_mmd(phydev
, MDIO_MMD_VEND1
,
97 VEND1_GLOBAL_MAILBOX_INTERFACE1
,
98 VEND1_GLOBAL_MAILBOX_INTERFACE1_CRC_RESET
);
99 phy_write_mmd(phydev
, MDIO_MMD_VEND1
,
100 VEND1_GLOBAL_MAILBOX_INTERFACE3
,
101 VEND1_GLOBAL_MAILBOX_INTERFACE3_MSW_ADDR(addr
));
102 phy_write_mmd(phydev
, MDIO_MMD_VEND1
,
103 VEND1_GLOBAL_MAILBOX_INTERFACE4
,
104 VEND1_GLOBAL_MAILBOX_INTERFACE4_LSW_ADDR(addr
));
106 /* We assume and enforce the size to be word aligned.
107 * If a firmware that is not word aligned is found, please report upstream.
109 for (pos
= 0; pos
< len
; pos
+= sizeof(u32
)) {
113 /* FW data is always stored in little-endian */
114 word
= get_unaligned_le32((const u32
*)(data
+ pos
));
116 phy_write_mmd(phydev
, MDIO_MMD_VEND1
, VEND1_GLOBAL_MAILBOX_INTERFACE5
,
117 VEND1_GLOBAL_MAILBOX_INTERFACE5_MSW_DATA(word
));
118 phy_write_mmd(phydev
, MDIO_MMD_VEND1
, VEND1_GLOBAL_MAILBOX_INTERFACE6
,
119 VEND1_GLOBAL_MAILBOX_INTERFACE6_LSW_DATA(word
));
121 phy_write_mmd(phydev
, MDIO_MMD_VEND1
, VEND1_GLOBAL_MAILBOX_INTERFACE1
,
122 VEND1_GLOBAL_MAILBOX_INTERFACE1_EXECUTE
|
123 VEND1_GLOBAL_MAILBOX_INTERFACE1_WRITE
);
125 /* Word is swapped internally and MAILBOX CRC is calculated
126 * using big-endian order. Mimic what the PHY does to have a
129 crc_data
[0] = word
>> 24;
130 crc_data
[1] = word
>> 16;
131 crc_data
[2] = word
>> 8;
134 /* ...calculate CRC as we load data... */
135 crc
= crc_itu_t(crc
, crc_data
, sizeof(crc_data
));
137 /* ...gets CRC from MAILBOX after we have loaded the entire section... */
138 up_crc
= phy_read_mmd(phydev
, MDIO_MMD_VEND1
, VEND1_GLOBAL_MAILBOX_INTERFACE2
);
139 /* ...and make sure it does match our calculated CRC */
141 phydev_err(phydev
, "CRC mismatch: calculated 0x%04x PHY 0x%04x\n",
149 static int aqr_fw_boot(struct phy_device
*phydev
, const u8
*data
, size_t size
,
150 enum aqr_fw_src fw_src
)
152 u16 calculated_crc
, read_crc
, read_primary_offset
;
153 u32 iram_offset
= 0, iram_size
= 0;
154 u32 dram_offset
= 0, dram_size
= 0;
155 char version
[VERSION_STRING_SIZE
];
156 u32 primary_offset
= 0;
159 /* extract saved CRC at the end of the fw
160 * CRC is saved in big-endian as PHY is BE
162 ret
= aqr_fw_get_be16(data
, size
- sizeof(u16
), size
, &read_crc
);
164 phydev_err(phydev
, "bad firmware CRC in firmware\n");
167 calculated_crc
= crc_itu_t(0, data
, size
- sizeof(u16
));
168 if (read_crc
!= calculated_crc
) {
169 phydev_err(phydev
, "bad firmware CRC: file 0x%04x calculated 0x%04x\n",
170 read_crc
, calculated_crc
);
174 /* Get the primary offset to extract DRAM and IRAM sections. */
175 ret
= aqr_fw_get_le16(data
, PRIMARY_OFFSET_OFFSET
, size
, &read_primary_offset
);
177 phydev_err(phydev
, "bad primary offset in firmware\n");
180 primary_offset
= PRIMARY_OFFSET(read_primary_offset
);
182 /* Find the DRAM and IRAM sections within the firmware file.
183 * Make sure the fw_header is correctly in the firmware.
185 if (!aqr_fw_validate_get(size
, primary_offset
+ HEADER_OFFSET
,
186 sizeof(struct aqr_fw_header
))) {
187 phydev_err(phydev
, "bad fw_header in firmware\n");
191 /* offset are in LE and values needs to be converted to cpu endian */
192 ret
= aqr_fw_get_le24(data
, primary_offset
+ HEADER_OFFSET
+
193 offsetof(struct aqr_fw_header
, iram_offset
),
196 phydev_err(phydev
, "bad iram offset in firmware\n");
199 ret
= aqr_fw_get_le24(data
, primary_offset
+ HEADER_OFFSET
+
200 offsetof(struct aqr_fw_header
, iram_size
),
203 phydev_err(phydev
, "invalid iram size in firmware\n");
206 ret
= aqr_fw_get_le24(data
, primary_offset
+ HEADER_OFFSET
+
207 offsetof(struct aqr_fw_header
, dram_offset
),
210 phydev_err(phydev
, "bad dram offset in firmware\n");
213 ret
= aqr_fw_get_le24(data
, primary_offset
+ HEADER_OFFSET
+
214 offsetof(struct aqr_fw_header
, dram_size
),
217 phydev_err(phydev
, "invalid dram size in firmware\n");
221 /* Increment the offset with the primary offset.
222 * Validate iram/dram offset and size.
224 iram_offset
+= primary_offset
;
225 if (iram_size
% sizeof(u32
)) {
226 phydev_err(phydev
, "iram size if not aligned to word size. Please report this upstream!\n");
229 if (!aqr_fw_validate_get(size
, iram_offset
, iram_size
)) {
230 phydev_err(phydev
, "invalid iram offset for iram size\n");
234 dram_offset
+= primary_offset
;
235 if (dram_size
% sizeof(u32
)) {
236 phydev_err(phydev
, "dram size if not aligned to word size. Please report this upstream!\n");
239 if (!aqr_fw_validate_get(size
, dram_offset
, dram_size
)) {
240 phydev_err(phydev
, "invalid iram offset for iram size\n");
244 phydev_dbg(phydev
, "primary %d IRAM offset=%d size=%d DRAM offset=%d size=%d\n",
245 primary_offset
, iram_offset
, iram_size
, dram_offset
, dram_size
);
247 if (!aqr_fw_validate_get(size
, dram_offset
+ VERSION_STRING_OFFSET
,
248 VERSION_STRING_SIZE
)) {
249 phydev_err(phydev
, "invalid version in firmware\n");
252 strscpy(version
, (char *)data
+ dram_offset
+ VERSION_STRING_OFFSET
,
253 VERSION_STRING_SIZE
);
254 if (version
[0] == '\0') {
255 phydev_err(phydev
, "invalid version in firmware\n");
258 phydev_info(phydev
, "loading firmware version '%s' from '%s'\n", version
,
259 aqr_fw_src_string
[fw_src
]);
261 /* stall the microcprocessor */
262 phy_write_mmd(phydev
, MDIO_MMD_VEND1
, VEND1_GLOBAL_CONTROL2
,
263 VEND1_GLOBAL_CONTROL2_UP_RUN_STALL
| VEND1_GLOBAL_CONTROL2_UP_RUN_STALL_OVD
);
265 phydev_dbg(phydev
, "loading DRAM 0x%08x from offset=%d size=%d\n",
266 DRAM_BASE_ADDR
, dram_offset
, dram_size
);
267 ret
= aqr_fw_load_memory(phydev
, DRAM_BASE_ADDR
, data
+ dram_offset
,
272 phydev_dbg(phydev
, "loading IRAM 0x%08x from offset=%d size=%d\n",
273 IRAM_BASE_ADDR
, iram_offset
, iram_size
);
274 ret
= aqr_fw_load_memory(phydev
, IRAM_BASE_ADDR
, data
+ iram_offset
,
279 /* make sure soft reset and low power mode are clear */
280 phy_clear_bits_mmd(phydev
, MDIO_MMD_VEND1
, VEND1_GLOBAL_SC
,
281 VEND1_GLOBAL_SC_SOFT_RESET
| VEND1_GLOBAL_SC_LOW_POWER
);
283 /* Release the microprocessor. UP_RESET must be held for 100 usec. */
284 phy_write_mmd(phydev
, MDIO_MMD_VEND1
, VEND1_GLOBAL_CONTROL2
,
285 VEND1_GLOBAL_CONTROL2_UP_RUN_STALL
|
286 VEND1_GLOBAL_CONTROL2_UP_RUN_STALL_OVD
|
287 VEND1_GLOBAL_CONTROL2_UP_RUN_STALL_RST
);
288 usleep_range(UP_RESET_SLEEP
, UP_RESET_SLEEP
* 2);
290 phy_write_mmd(phydev
, MDIO_MMD_VEND1
, VEND1_GLOBAL_CONTROL2
,
291 VEND1_GLOBAL_CONTROL2_UP_RUN_STALL_OVD
);
296 static int aqr_firmware_load_nvmem(struct phy_device
*phydev
)
298 struct nvmem_cell
*cell
;
303 cell
= nvmem_cell_get(&phydev
->mdio
.dev
, "firmware");
305 return PTR_ERR(cell
);
307 buf
= nvmem_cell_read(cell
, &size
);
313 ret
= aqr_fw_boot(phydev
, buf
, size
, AQR_FW_SRC_NVMEM
);
315 phydev_err(phydev
, "firmware loading failed: %d\n", ret
);
319 nvmem_cell_put(cell
);
324 static int aqr_firmware_load_fs(struct phy_device
*phydev
)
326 struct device
*dev
= &phydev
->mdio
.dev
;
327 const struct firmware
*fw
;
331 ret
= of_property_read_string(dev
->of_node
, "firmware-name",
336 ret
= request_firmware(&fw
, fw_name
, dev
);
338 phydev_err(phydev
, "failed to find FW file %s (%d)\n",
343 ret
= aqr_fw_boot(phydev
, fw
->data
, fw
->size
, AQR_FW_SRC_FS
);
345 phydev_err(phydev
, "firmware loading failed: %d\n", ret
);
347 release_firmware(fw
);
352 int aqr_firmware_load(struct phy_device
*phydev
)
356 /* Check if the firmware is not already loaded by polling
357 * the current version returned by the PHY.
359 ret
= aqr_wait_reset_complete(phydev
);
362 /* Some firmware is loaded => do nothing */
365 /* VEND1_GLOBAL_FW_ID still reads 0 after 2 seconds of polling.
366 * We don't have full confidence that no firmware is loaded (in
367 * theory it might just not have loaded yet), but we will
368 * assume that, and load a new image.
370 ret
= aqr_firmware_load_nvmem(phydev
);
374 ret
= aqr_firmware_load_fs(phydev
);
379 /* PHY read error, propagate it to the caller */