kernel/modules/other/mlxreg: add new package
[openwrt/openwrt.git] / package / boot / uboot-mediatek / patches / 160-net-phy-add-support-for-Airoha-ethernet-PHY-driver.patch
1 From 70157a6148ad47734f1dc646b4157ca83cc5df9f Mon Sep 17 00:00:00 2001
2 From: Weijie Gao <weijie.gao@mediatek.com>
3 Date: Thu, 13 Jul 2023 16:34:48 +0800
4 Subject: [PATCH] net: phy: add support for Airoha ethernet PHY driver
5
6 This patch adds support for Airoha ethernet PHY driver.
7
8 If GMAC2 of your board connects to Airoha EN8801S, please change the eth
9 node as follow:
10
11 &eth {
12 status = "okay";
13 mediatek,gmac-id = <1>;
14 mediatek,sgmiisys = <&sgmiisys1>;
15 phy-mode = "sgmii";
16 phy-handle = <&phy5>;
17
18 phy5: eth-phy@5 {
19 reg = <24>;
20 };
21 };
22
23 If GMAC2 of your board connects to Airoha EN8811H, please change the eth
24 node as follow:
25
26 &eth {
27 status = "okay";
28 mediatek,gmac-id = <1>;
29 mediatek,sgmiisys = <&sgmiisys1>;
30 phy-mode = "2500base-x";
31 phy-handle = <&phy5>;
32
33 fixed-link {
34 speed = <2500>;
35 full-duplex;
36 };
37
38 phy5: eth-phy@5 {
39 reg = <15>;
40 };
41 };
42
43 Signed-off-by: Weijie Gao <weijie.gao@mediatek.com>
44 ---
45 .../drivers/net/phy/Kconfig | 15 +
46 .../drivers/net/phy/Makefile | 2 +
47 .../drivers/net/phy/air_en8801s.c | 633 ++
48 .../drivers/net/phy/air_en8801s.h | 267 +
49 .../drivers/net/phy/air_en8811h.c | 649 ++
50 .../drivers/net/phy/air_en8811h.h | 160 +
51 .../drivers/net/phy/air_en8811h_fw.h | 9227 +++++++++++++++++
52 7 files changed, 10953 insertions(+)
53 create mode 100644 drivers/net/phy/air_en8801s.c
54 create mode 100644 drivers/net/phy/air_en8801s.h
55 create mode 100644 drivers/net/phy/air_en8811h.c
56 create mode 100644 drivers/net/phy/air_en8811h.h
57 create mode 100644 drivers/net/phy/air_en8811h_fw.h
58
59 --- a/drivers/net/phy/Kconfig
60 +++ b/drivers/net/phy/Kconfig
61 @@ -77,6 +77,37 @@ config PHY_ADIN
62 help
63 Add support for configuring RGMII on Analog Devices ADIN PHYs.
64
65 +menuconfig PHY_AIROHA
66 + bool "Airoha Ethernet PHYs support"
67 +
68 +config PHY_AIROHA_EN8801S
69 + bool "Airoha Ethernet EN8801S support"
70 + depends on PHY_AIROHA
71 + help
72 + AIROHA EN8801S supported.
73 +
74 +config PHY_AIROHA_EN8811H
75 + bool "Airoha Ethernet EN8811H support"
76 + depends on PHY_AIROHA
77 + help
78 + AIROHA EN8811H supported.
79 +
80 +choice
81 + prompt "Location of the Airoha PHY firmware"
82 + default PHY_AIROHA_FW_IN_UBI
83 + depends on PHY_AIROHA_EN8811H
84 +
85 +config PHY_AIROHA_FW_IN_MMC
86 + bool "Airoha firmware in MMC boot1 partition"
87 +
88 +config PHY_AIROHA_FW_IN_UBI
89 + bool "Airoha firmware in UBI volume en8811h-fw on NAND flash"
90 +
91 +config PHY_AIROHA_FW_IN_MTD
92 + bool "Airoha firmware in MTD partition on raw flash"
93 +
94 +endchoice
95 +
96 menuconfig PHY_AQUANTIA
97 bool "Aquantia Ethernet PHYs support"
98 select PHY_GIGE
99 --- a/drivers/net/phy/Makefile
100 +++ b/drivers/net/phy/Makefile
101 @@ -11,6 +11,8 @@ obj-$(CONFIG_MV88E6352_SWITCH) += mv88e6
102 obj-$(CONFIG_PHYLIB) += phy.o
103 obj-$(CONFIG_PHYLIB_10G) += generic_10g.o
104 obj-$(CONFIG_PHY_ADIN) += adin.o
105 +obj-$(CONFIG_PHY_AIROHA_EN8801S) += air_en8801s.o
106 +obj-$(CONFIG_PHY_AIROHA_EN8811H) += air_en8811h.o
107 obj-$(CONFIG_PHY_AQUANTIA) += aquantia.o
108 obj-$(CONFIG_PHY_ATHEROS) += atheros.o
109 obj-$(CONFIG_PHY_BROADCOM) += broadcom.o
110 --- /dev/null
111 +++ b/drivers/net/phy/air_en8801s.c
112 @@ -0,0 +1,633 @@
113 +// SPDX-License-Identifier: GPL-2.0
114 +/*************************************************
115 + * FILE NAME: air_en8801s.c
116 + * PURPOSE:
117 + * EN8801S PHY Driver for Uboot
118 + * NOTES:
119 + *
120 + * Copyright (C) 2023 Airoha Technology Corp.
121 + *************************************************/
122 +
123 +/* INCLUDE FILE DECLARATIONS
124 + */
125 +#include <common.h>
126 +#include <phy.h>
127 +#include <errno.h>
128 +#include <version.h>
129 +#include "air_en8801s.h"
130 +
131 +#if AIR_UBOOT_REVISION > 0x202004
132 +#include <linux/delay.h>
133 +#endif
134 +
135 +static struct phy_device *s_phydev = 0;
136 +/******************************************************
137 + * The following led_cfg example is for reference only.
138 + * LED5 1000M/LINK/ACT (GPIO5) <-> BASE_T_LED0,
139 + * LED6 10/100M/LINK/ACT (GPIO9) <-> BASE_T_LED1,
140 + * LED4 100M/LINK/ACT (GPIO8) <-> BASE_T_LED2,
141 + ******************************************************/
142 +/* User-defined.B */
143 +#define AIR_LED_SUPPORT
144 +#ifdef AIR_LED_SUPPORT
145 +static const AIR_BASE_T_LED_CFG_T led_cfg[4] =
146 +{
147 + /*
148 + * LED Enable, GPIO, LED Polarity, LED ON, LED Blink
149 + */
150 + {LED_ENABLE, 5, AIR_ACTIVE_LOW, BASE_T_LED0_ON_CFG, BASE_T_LED0_BLK_CFG}, /* BASE-T LED0 */
151 + {LED_ENABLE, 9, AIR_ACTIVE_LOW, BASE_T_LED1_ON_CFG, BASE_T_LED1_BLK_CFG}, /* BASE-T LED1 */
152 + {LED_ENABLE, 8, AIR_ACTIVE_LOW, BASE_T_LED2_ON_CFG, BASE_T_LED2_BLK_CFG}, /* BASE-T LED2 */
153 + {LED_DISABLE, 1, AIR_ACTIVE_LOW, BASE_T_LED3_ON_CFG, BASE_T_LED3_BLK_CFG} /* BASE-T LED3 */
154 +};
155 +static const u16 led_dur = UNIT_LED_BLINK_DURATION << AIR_LED_BLK_DUR_64M;
156 +#endif
157 +/* User-defined.E */
158 +/************************************************************************
159 + * F U N C T I O N S
160 + ************************************************************************/
161 +/* Airoha MII read function */
162 +static int airoha_cl22_read(struct mii_dev *bus, int phy_addr, int phy_register)
163 +{
164 + int read_data = bus->read(bus, phy_addr, MDIO_DEVAD_NONE, phy_register);
165 +
166 + if (read_data < 0)
167 + return -EIO;
168 + return read_data;
169 +}
170 +
171 +/* Airoha MII write function */
172 +static int airoha_cl22_write(struct mii_dev *bus, int phy_addr, int phy_register, int write_data)
173 +{
174 + int ret = bus->write(bus, phy_addr, MDIO_DEVAD_NONE, phy_register, write_data);
175 +
176 + return ret;
177 +}
178 +
179 +static int airoha_cl45_write(struct phy_device *phydev, int devad, int reg, int val)
180 +{
181 + int ret = 0;
182 +
183 + ret = phy_write(phydev, MDIO_DEVAD_NONE, MII_MMD_ACC_CTL_REG, devad);
184 + AIR_RTN_ERR(ret);
185 + ret = phy_write(phydev, MDIO_DEVAD_NONE, MII_MMD_ADDR_DATA_REG, reg);
186 + AIR_RTN_ERR(ret);
187 + ret = phy_write(phydev, MDIO_DEVAD_NONE, MII_MMD_ACC_CTL_REG, MMD_OP_MODE_DATA | devad);
188 + AIR_RTN_ERR(ret);
189 + ret = phy_write(phydev, MDIO_DEVAD_NONE, MII_MMD_ADDR_DATA_REG, val);
190 + AIR_RTN_ERR(ret);
191 + return ret;
192 +}
193 +
194 +static int airoha_cl45_read(struct phy_device *phydev, int devad, int reg)
195 +{
196 + int read_data, ret;
197 +
198 + ret = phy_write(phydev, MDIO_DEVAD_NONE, MII_MMD_ACC_CTL_REG, devad);
199 + AIR_RTN_ERR(ret);
200 + ret = phy_write(phydev, MDIO_DEVAD_NONE, MII_MMD_ADDR_DATA_REG, reg);
201 + AIR_RTN_ERR(ret);
202 + ret = phy_write(phydev, MDIO_DEVAD_NONE, MII_MMD_ACC_CTL_REG, MMD_OP_MODE_DATA | devad);
203 + AIR_RTN_ERR(ret);
204 + read_data = phy_read(phydev, MDIO_DEVAD_NONE, MII_MMD_ADDR_DATA_REG);
205 + if (read_data < 0)
206 + return -EIO;
207 + return read_data;
208 +}
209 +
210 +/* EN8801 PBUS write function */
211 +int airoha_pbus_write(struct mii_dev *bus, int pbus_addr, int pbus_reg, unsigned long pbus_data)
212 +{
213 + int ret = 0;
214 +
215 + ret = airoha_cl22_write(bus, pbus_addr, 0x1F, (pbus_reg >> 6));
216 + AIR_RTN_ERR(ret);
217 + ret = airoha_cl22_write(bus, pbus_addr, ((pbus_reg >> 2) & 0xf), (pbus_data & 0xFFFF));
218 + AIR_RTN_ERR(ret);
219 + ret = airoha_cl22_write(bus, pbus_addr, 0x10, (pbus_data >> 16));
220 + AIR_RTN_ERR(ret);
221 + return ret;
222 +}
223 +
224 +/* EN8801 PBUS read function */
225 +unsigned long airoha_pbus_read(struct mii_dev *bus, int pbus_addr, int pbus_reg)
226 +{
227 + unsigned long pbus_data;
228 + unsigned int pbus_data_low, pbus_data_high;
229 +
230 + airoha_cl22_write(bus, pbus_addr, 0x1F, (pbus_reg >> 6));
231 + pbus_data_low = airoha_cl22_read(bus, pbus_addr, ((pbus_reg >> 2) & 0xf));
232 + pbus_data_high = airoha_cl22_read(bus, pbus_addr, 0x10);
233 + pbus_data = (pbus_data_high << 16) + pbus_data_low;
234 + return pbus_data;
235 +}
236 +
237 +/* Airoha Token Ring Write function */
238 +static int airoha_tr_reg_write(struct phy_device *phydev, unsigned long tr_address, unsigned long tr_data)
239 +{
240 + int ret;
241 +
242 + ret = phy_write(phydev, MDIO_DEVAD_NONE, 0x1F, 0x52b5); /* page select */
243 + AIR_RTN_ERR(ret);
244 + ret = phy_write(phydev, MDIO_DEVAD_NONE, 0x11, (int)(tr_data & 0xffff));
245 + AIR_RTN_ERR(ret);
246 + ret = phy_write(phydev, MDIO_DEVAD_NONE, 0x12, (int)(tr_data >> 16));
247 + AIR_RTN_ERR(ret);
248 + ret = phy_write(phydev, MDIO_DEVAD_NONE, 0x10, (int)(tr_address | TrReg_WR));
249 + AIR_RTN_ERR(ret);
250 + ret = phy_write(phydev, MDIO_DEVAD_NONE, 0x1F, 0x0); /* page resetore */
251 + AIR_RTN_ERR(ret);
252 + return ret;
253 +}
254 +
255 +int airoha_phy_process(void)
256 +{
257 + int ret = 0, pbus_addr = EN8801S_PBUS_PHY_ID;
258 + unsigned long pbus_data;
259 + struct mii_dev *mbus;
260 +
261 + mbus = s_phydev->bus;
262 + pbus_data = airoha_pbus_read(mbus, pbus_addr, 0x19e0);
263 + pbus_data |= BIT(0);
264 + ret = airoha_pbus_write(mbus, pbus_addr, 0x19e0, pbus_data);
265 + if(ret)
266 + printf("error: airoha_pbus_write fail ret: %d\n", ret);
267 + pbus_data = airoha_pbus_read(mbus, pbus_addr, 0x19e0);
268 + pbus_data &= ~BIT(0);
269 + ret = airoha_pbus_write(mbus, pbus_addr, 0x19e0, pbus_data);
270 + if(ret)
271 + printf("error: airoha_pbus_write fail ret: %d\n", ret);
272 +
273 + if(ret)
274 + printf("error: FCM regs reset fail, ret: %d\n", ret);
275 + else
276 + debug("FCM regs reset successful\n");
277 + return ret;
278 +}
279 +
280 +#ifdef AIR_LED_SUPPORT
281 +static int airoha_led_set_usr_def(struct phy_device *phydev, u8 entity, int polar,
282 + u16 on_evt, u16 blk_evt)
283 +{
284 + int ret = 0;
285 +
286 + if (AIR_ACTIVE_HIGH == polar) {
287 + on_evt |= LED_ON_POL;
288 + } else {
289 + on_evt &= ~LED_ON_POL;
290 + }
291 + ret = airoha_cl45_write(phydev, 0x1f, LED_ON_CTRL(entity), on_evt | LED_ON_EN);
292 + AIR_RTN_ERR(ret);
293 + ret = airoha_cl45_write(phydev, 0x1f, LED_BLK_CTRL(entity), blk_evt);
294 + AIR_RTN_ERR(ret);
295 + return 0;
296 +}
297 +
298 +static int airoha_led_set_mode(struct phy_device *phydev, u8 mode)
299 +{
300 + u16 cl45_data;
301 + int err = 0;
302 +
303 + cl45_data = airoha_cl45_read(phydev, 0x1f, LED_BCR);
304 + switch (mode) {
305 + case AIR_LED_MODE_DISABLE:
306 + cl45_data &= ~LED_BCR_EXT_CTRL;
307 + cl45_data &= ~LED_BCR_MODE_MASK;
308 + cl45_data |= LED_BCR_MODE_DISABLE;
309 + break;
310 + case AIR_LED_MODE_USER_DEFINE:
311 + cl45_data |= LED_BCR_EXT_CTRL;
312 + cl45_data |= LED_BCR_CLK_EN;
313 + break;
314 + default:
315 + printf("LED mode%d is not supported!\n", mode);
316 + return -EINVAL;
317 + }
318 + err = airoha_cl45_write(phydev, 0x1f, LED_BCR, cl45_data);
319 + AIR_RTN_ERR(err);
320 + return 0;
321 +}
322 +
323 +static int airoha_led_set_state(struct phy_device *phydev, u8 entity, u8 state)
324 +{
325 + u16 cl45_data;
326 + int err;
327 +
328 + cl45_data = airoha_cl45_read(phydev, 0x1f, LED_ON_CTRL(entity));
329 + if (LED_ENABLE == state) {
330 + cl45_data |= LED_ON_EN;
331 + } else {
332 + cl45_data &= ~LED_ON_EN;
333 + }
334 +
335 + err = airoha_cl45_write(phydev, 0x1f, LED_ON_CTRL(entity), cl45_data);
336 + AIR_RTN_ERR(err);
337 + return 0;
338 +}
339 +
340 +static int en8801s_led_init(struct phy_device *phydev)
341 +{
342 +
343 + unsigned long led_gpio = 0, reg_value = 0;
344 + int ret = 0, led_id;
345 + struct mii_dev *mbus = phydev->bus;
346 + int gpio_led_rg[3] = {0x1870, 0x1874, 0x1878};
347 + u16 cl45_data = led_dur;
348 +
349 + ret = airoha_cl45_write(phydev, 0x1f, LED_BLK_DUR, cl45_data);
350 + AIR_RTN_ERR(ret);
351 + cl45_data >>= 1;
352 + ret = airoha_cl45_write(phydev, 0x1f, LED_ON_DUR, cl45_data);
353 + AIR_RTN_ERR(ret);
354 + ret = airoha_led_set_mode(phydev, AIR_LED_MODE_USER_DEFINE);
355 + if (ret != 0) {
356 + printf("LED fail to set mode, ret %d !\n", ret);
357 + return ret;
358 + }
359 + for(led_id = 0; led_id < EN8801S_LED_COUNT; led_id++) {
360 + reg_value = 0;
361 + ret = airoha_led_set_state(phydev, led_id, led_cfg[led_id].en);
362 + if (ret != 0) {
363 + printf("LED fail to set state, ret %d !\n", ret);
364 + return ret;
365 + }
366 + if (LED_ENABLE == led_cfg[led_id].en) {
367 + if ( (led_cfg[led_id].gpio < 0) || led_cfg[led_id].gpio > 9) {
368 + printf("GPIO%d is out of range!! GPIO number is 0~9.\n", led_cfg[led_id].gpio);
369 + return -EIO;
370 + }
371 + led_gpio |= BIT(led_cfg[led_id].gpio);
372 + reg_value = airoha_pbus_read(mbus, EN8801S_PBUS_PHY_ID, gpio_led_rg[led_cfg[led_id].gpio / 4]);
373 + LED_SET_GPIO_SEL(led_cfg[led_id].gpio, led_id, reg_value);
374 + debug("[Airoha] gpio%d, reg_value 0x%lx\n", led_cfg[led_id].gpio, reg_value);
375 + ret = airoha_pbus_write(mbus, EN8801S_PBUS_PHY_ID, gpio_led_rg[led_cfg[led_id].gpio / 4], reg_value);
376 + AIR_RTN_ERR(ret);
377 + ret = airoha_led_set_usr_def(phydev, led_id, led_cfg[led_id].pol, led_cfg[led_id].on_cfg, led_cfg[led_id].blk_cfg);
378 + if (ret != 0) {
379 + printf("LED fail to set usr def, ret %d !\n", ret);
380 + return ret;
381 + }
382 + }
383 + }
384 + reg_value = (airoha_pbus_read(mbus, EN8801S_PBUS_PHY_ID, 0x1880) & ~led_gpio);
385 + ret = airoha_pbus_write(mbus, EN8801S_PBUS_PHY_ID, 0x1880, reg_value);
386 + AIR_RTN_ERR(ret);
387 + ret = airoha_pbus_write(mbus, EN8801S_PBUS_PHY_ID, 0x186c, led_gpio);
388 + AIR_RTN_ERR(ret);
389 +
390 + printf("LED initialize OK !\n");
391 + return 0;
392 +}
393 +#endif /* AIR_LED_SUPPORT */
394 +
395 +static int en8801s_config(struct phy_device *phydev)
396 +{
397 + int reg_value = 0, ret = 0;
398 + struct mii_dev *mbus = phydev->bus;
399 + int retry, pbus_addr = EN8801S_PBUS_DEFAULT_ID;
400 + int phy_addr = EN8801S_MDIO_PHY_ID;
401 + unsigned long pbus_data = 0;
402 + gephy_all_REG_LpiReg1Ch GPHY_RG_LPI_1C;
403 + gephy_all_REG_dev1Eh_reg324h GPHY_RG_1E_324;
404 + gephy_all_REG_dev1Eh_reg012h GPHY_RG_1E_012;
405 + gephy_all_REG_dev1Eh_reg017h GPHY_RG_1E_017;
406 +
407 + s_phydev = phydev;
408 + retry = MAX_OUI_CHECK;
409 + while (1) {
410 + /* PHY OUI */
411 + pbus_data = airoha_pbus_read(mbus, pbus_addr, EN8801S_RG_ETHER_PHY_OUI);
412 + if (EN8801S_PBUS_OUI == pbus_data) {
413 + printf("PBUS addr 0x%x: Start initialized.\n", pbus_addr);
414 + ret = airoha_pbus_write(mbus, pbus_addr, EN8801S_RG_BUCK_CTL, 0x03);
415 + AIR_RTN_ERR(ret);
416 + break;
417 + } else
418 + pbus_addr = EN8801S_PBUS_PHY_ID;
419 +
420 + if (0 == --retry) {
421 + printf("EN8801S Probe fail !\n");
422 + return 0;
423 + }
424 + }
425 +
426 + /* SMI ADDR */
427 + pbus_data = airoha_pbus_read(mbus, pbus_addr, EN8801S_RG_SMI_ADDR);
428 + pbus_data = (pbus_data & 0xffff0000) | (unsigned long)(pbus_addr << 8) | (unsigned long)(EN8801S_MDIO_DEFAULT_ID);
429 + ret = airoha_pbus_write(mbus, pbus_addr, EN8801S_RG_SMI_ADDR, pbus_data);
430 + AIR_RTN_ERR(ret);
431 + mdelay(10);
432 +
433 + pbus_data = (airoha_pbus_read(mbus, pbus_addr, EN8801S_RG_LTR_CTL) & (~0x3)) | BIT(2) ;
434 + ret = airoha_pbus_write(mbus, pbus_addr, EN8801S_RG_LTR_CTL, pbus_data);
435 + AIR_RTN_ERR(ret);
436 + mdelay(500);
437 + pbus_data = (pbus_data & ~BIT(2)) | EN8801S_RX_POLARITY_NORMAL | EN8801S_TX_POLARITY_NORMAL;
438 + ret = airoha_pbus_write(mbus, pbus_addr, EN8801S_RG_LTR_CTL, pbus_data);
439 + AIR_RTN_ERR(ret);
440 + mdelay(500);
441 + /* SMI ADDR */
442 + pbus_data = airoha_pbus_read(mbus, pbus_addr, EN8801S_RG_SMI_ADDR);
443 + pbus_data = (pbus_data & 0xffff0000) | (unsigned long)(EN8801S_PBUS_PHY_ID << 8) | (unsigned long)(EN8801S_MDIO_PHY_ID);
444 + ret = airoha_pbus_write(mbus, pbus_addr, EN8801S_RG_SMI_ADDR, pbus_data);
445 + pbus_addr = EN8801S_PBUS_PHY_ID;
446 + AIR_RTN_ERR(ret);
447 + mdelay(10);
448 +
449 + /* Optimze 10M IoT */
450 + pbus_data = airoha_pbus_read(mbus, pbus_addr, 0x1690);
451 + pbus_data |= (1 << 31);
452 + ret = airoha_pbus_write(mbus, pbus_addr, 0x1690, pbus_data);
453 + AIR_RTN_ERR(ret);
454 + /* set SGMII Base Page */
455 + ret = airoha_pbus_write(mbus, pbus_addr, 0x0600, 0x0c000c00);
456 + AIR_RTN_ERR(ret);
457 + ret = airoha_pbus_write(mbus, pbus_addr, 0x10, 0xD801);
458 + AIR_RTN_ERR(ret);
459 + ret = airoha_pbus_write(mbus, pbus_addr, 0x0, 0x9140);
460 + AIR_RTN_ERR(ret);
461 + ret = airoha_pbus_write(mbus, pbus_addr, 0x0A14, 0x0003);
462 + AIR_RTN_ERR(ret);
463 + ret = airoha_pbus_write(mbus, pbus_addr, 0x0600, 0x0c000c00);
464 + AIR_RTN_ERR(ret);
465 + /* Set FCM control */
466 + ret = airoha_pbus_write(mbus, pbus_addr, 0x1404, 0x004b);
467 + AIR_RTN_ERR(ret);
468 + ret = airoha_pbus_write(mbus, pbus_addr, 0x140c, 0x0007);
469 + AIR_RTN_ERR(ret);
470 +
471 + ret = airoha_pbus_write(mbus, pbus_addr, 0x142c, 0x05050505);
472 + AIR_RTN_ERR(ret);
473 + pbus_data = airoha_pbus_read(mbus, pbus_addr, 0x1440);
474 + ret = airoha_pbus_write(mbus, pbus_addr, 0x1440, pbus_data & ~BIT(11));
475 + AIR_RTN_ERR(ret);
476 +
477 + pbus_data = airoha_pbus_read(mbus, pbus_addr, 0x1408);
478 + ret = airoha_pbus_write(mbus, pbus_addr, 0x1408, pbus_data | BIT(5));
479 + AIR_RTN_ERR(ret);
480 +
481 + /* Set GPHY Perfomance*/
482 + /* Token Ring */
483 + ret = airoha_tr_reg_write(phydev, RgAddr_R1000DEC_15h, 0x0055A0);
484 + AIR_RTN_ERR(ret);
485 + ret = airoha_tr_reg_write(phydev, RgAddr_R1000DEC_17h, 0x07FF3F);
486 + AIR_RTN_ERR(ret);
487 + ret = airoha_tr_reg_write(phydev, RgAddr_PMA_00h, 0x00001E);
488 + AIR_RTN_ERR(ret);
489 + ret = airoha_tr_reg_write(phydev, RgAddr_PMA_01h, 0x6FB90A);
490 + AIR_RTN_ERR(ret);
491 + ret = airoha_tr_reg_write(phydev, RgAddr_PMA_17h, 0x060671);
492 + AIR_RTN_ERR(ret);
493 + ret = airoha_tr_reg_write(phydev, RgAddr_PMA_18h, 0x0E2F00);
494 + AIR_RTN_ERR(ret);
495 + ret = airoha_tr_reg_write(phydev, RgAddr_TR_26h, 0x444444);
496 + AIR_RTN_ERR(ret);
497 + ret = airoha_tr_reg_write(phydev, RgAddr_DSPF_03h, 0x000000);
498 + AIR_RTN_ERR(ret);
499 + ret = airoha_tr_reg_write(phydev, RgAddr_DSPF_06h, 0x2EBAEF);
500 + AIR_RTN_ERR(ret);
501 + ret = airoha_tr_reg_write(phydev, RgAddr_DSPF_08h, 0x00000B);
502 + AIR_RTN_ERR(ret);
503 + ret = airoha_tr_reg_write(phydev, RgAddr_DSPF_0Ch, 0x00504D);
504 + AIR_RTN_ERR(ret);
505 + ret = airoha_tr_reg_write(phydev, RgAddr_DSPF_0Dh, 0x02314F);
506 + AIR_RTN_ERR(ret);
507 + ret = airoha_tr_reg_write(phydev, RgAddr_DSPF_0Fh, 0x003028);
508 + AIR_RTN_ERR(ret);
509 + ret = airoha_tr_reg_write(phydev, RgAddr_DSPF_10h, 0x005010);
510 + AIR_RTN_ERR(ret);
511 + ret = airoha_tr_reg_write(phydev, RgAddr_DSPF_11h, 0x040001);
512 + AIR_RTN_ERR(ret);
513 + ret = airoha_tr_reg_write(phydev, RgAddr_DSPF_13h, 0x018670);
514 + AIR_RTN_ERR(ret);
515 + ret = airoha_tr_reg_write(phydev, RgAddr_DSPF_14h, 0x00024A);
516 + AIR_RTN_ERR(ret);
517 + ret = airoha_tr_reg_write(phydev, RgAddr_DSPF_1Bh, 0x000072);
518 + AIR_RTN_ERR(ret);
519 + ret = airoha_tr_reg_write(phydev, RgAddr_DSPF_1Ch, 0x003210);
520 + AIR_RTN_ERR(ret);
521 + /* CL22 & CL45 */
522 + ret = airoha_cl22_write(mbus, phy_addr, 0x1f, 0x03);
523 + AIR_RTN_ERR(ret);
524 + GPHY_RG_LPI_1C.DATA = airoha_cl22_read(mbus, phy_addr, RgAddr_LPI_1Ch);
525 + if (GPHY_RG_LPI_1C.DATA < 0)
526 + return -EIO;
527 + GPHY_RG_LPI_1C.DataBitField.smi_deton_th = 0x0C;
528 + ret = airoha_cl22_write(mbus, phy_addr, RgAddr_LPI_1Ch, GPHY_RG_LPI_1C.DATA);
529 + AIR_RTN_ERR(ret);
530 + ret = airoha_cl22_write(mbus, phy_addr, RgAddr_LPI_1Ch, 0xC92);
531 + AIR_RTN_ERR(ret);
532 + ret = airoha_cl22_write(mbus, phy_addr, RgAddr_AUXILIARY_1Dh, 0x1);
533 + AIR_RTN_ERR(ret);
534 + ret = airoha_cl22_write(mbus, phy_addr, 0x1f, 0x0);
535 + AIR_RTN_ERR(ret);
536 + ret = airoha_cl45_write(phydev, 0x1E, 0x120, 0x8014);
537 + AIR_RTN_ERR(ret);
538 + ret = airoha_cl45_write(phydev, 0x1E, 0x122, 0xffff);
539 + AIR_RTN_ERR(ret);
540 + ret = airoha_cl45_write(phydev, 0x1E, 0x123, 0xffff);
541 + AIR_RTN_ERR(ret);
542 + ret = airoha_cl45_write(phydev, 0x1E, 0x144, 0x0200);
543 + AIR_RTN_ERR(ret);
544 + ret = airoha_cl45_write(phydev, 0x1E, 0x14A, 0xEE20);
545 + AIR_RTN_ERR(ret);
546 + ret = airoha_cl45_write(phydev, 0x1E, 0x189, 0x0110);
547 + AIR_RTN_ERR(ret);
548 + ret = airoha_cl45_write(phydev, 0x1E, 0x19B, 0x0111);
549 + AIR_RTN_ERR(ret);
550 + ret = airoha_cl45_write(phydev, 0x1E, 0x234, 0x0181);
551 + AIR_RTN_ERR(ret);
552 + ret = airoha_cl45_write(phydev, 0x1E, 0x238, 0x0120);
553 + AIR_RTN_ERR(ret);
554 + ret = airoha_cl45_write(phydev, 0x1E, 0x239, 0x0117);
555 + AIR_RTN_ERR(ret);
556 + ret = airoha_cl45_write(phydev, 0x1E, 0x268, 0x07F4);
557 + AIR_RTN_ERR(ret);
558 + ret = airoha_cl45_write(phydev, 0x1E, 0x2D1, 0x0733);
559 + AIR_RTN_ERR(ret);
560 + ret = airoha_cl45_write(phydev, 0x1E, 0x323, 0x0011);
561 + AIR_RTN_ERR(ret);
562 + ret = airoha_cl45_write(phydev, 0x1E, 0x324, 0x013F);
563 + AIR_RTN_ERR(ret);
564 + ret = airoha_cl45_write(phydev, 0x1E, 0x326, 0x0037);
565 + AIR_RTN_ERR(ret);
566 +
567 + reg_value = airoha_cl45_read(phydev, 0x1E, 0x324);
568 + if (reg_value < 0)
569 + return -EIO;
570 + GPHY_RG_1E_324.DATA = (int)reg_value;
571 + GPHY_RG_1E_324.DataBitField.smi_det_deglitch_off = 0;
572 + ret = airoha_cl45_write(phydev, 0x1E, 0x324, GPHY_RG_1E_324.DATA);
573 + AIR_RTN_ERR(ret);
574 + ret = airoha_cl45_write(phydev, 0x1E, 0x19E, 0xC2);
575 + AIR_RTN_ERR(ret);
576 + ret = airoha_cl45_write(phydev, 0x1E, 0x013, 0x0);
577 + AIR_RTN_ERR(ret);
578 +
579 + /* EFUSE */
580 + airoha_pbus_write(mbus, pbus_addr, 0x1C08, 0x40000040);
581 + retry = MAX_RETRY;
582 + while (0 != retry) {
583 + mdelay(1);
584 + pbus_data = airoha_pbus_read(mbus, pbus_addr, 0x1C08);
585 + if ((pbus_data & (1 << 30)) == 0) {
586 + break;
587 + }
588 + retry--;
589 + }
590 + pbus_data = airoha_pbus_read(mbus, pbus_addr, 0x1C38); /* RAW#2 */
591 + reg_value = airoha_cl45_read(phydev, 0x1E, 0x12);
592 + if (reg_value < 0)
593 + return -EIO;
594 + GPHY_RG_1E_012.DATA = reg_value;
595 + GPHY_RG_1E_012.DataBitField.da_tx_i2mpb_a_tbt = pbus_data & 0x03f;
596 + ret = airoha_cl45_write(phydev, 0x1E, 0x12, GPHY_RG_1E_012.DATA);
597 + AIR_RTN_ERR(ret);
598 + reg_value = airoha_cl45_read(phydev, 0x1E, 0x17);
599 + if (reg_value < 0)
600 + return -EIO;
601 + GPHY_RG_1E_017.DataBitField.da_tx_i2mpb_b_tbt = (reg_value >> 8) & 0x03f;
602 + ret = airoha_cl45_write(phydev, 0x1E, 0x17, GPHY_RG_1E_017.DATA);
603 + AIR_RTN_ERR(ret);
604 +
605 + ret = airoha_pbus_write(mbus, pbus_addr, 0x1C08, 0x40400040);
606 + AIR_RTN_ERR(ret);
607 + retry = MAX_RETRY;
608 + while (0 != retry) {
609 + mdelay(1);
610 + reg_value = airoha_pbus_read(mbus, pbus_addr, 0x1C08);
611 + if ((reg_value & (1 << 30)) == 0) {
612 + break;
613 + }
614 + retry--;
615 + }
616 + pbus_data = airoha_pbus_read(mbus, pbus_addr, 0x1C30); /* RAW#16 */
617 + GPHY_RG_1E_324.DataBitField.smi_det_deglitch_off = (pbus_data >> 12) & 0x01;
618 + ret = airoha_cl45_write(phydev, 0x1E, 0x324, GPHY_RG_1E_324.DATA);
619 + AIR_RTN_ERR(ret);
620 +#ifdef AIR_LED_SUPPORT
621 + ret = en8801s_led_init(phydev);
622 + if (ret != 0){
623 + printf("en8801s_led_init fail (ret:%d) !\n", ret);
624 + }
625 +#endif
626 + printf("EN8801S initialize OK ! (%s)\n", EN8801S_DRIVER_VERSION);
627 + return 0;
628 +}
629 +
630 +int en8801s_read_status(struct phy_device *phydev)
631 +{
632 + int ret, pbus_addr = EN8801S_PBUS_PHY_ID;
633 + struct mii_dev *mbus;
634 + unsigned long pbus_data;
635 +
636 + mbus = phydev->bus;
637 + if (SPEED_10 == phydev->speed) {
638 + /* set the bit for Optimze 10M IoT */
639 + debug("[Airoha] SPEED_10 0x1694\n");
640 + pbus_data = airoha_pbus_read(mbus, pbus_addr, 0x1694);
641 + pbus_data |= (1 << 31);
642 + ret = airoha_pbus_write(mbus, pbus_addr, 0x1694, pbus_data);
643 + AIR_RTN_ERR(ret);
644 + } else {
645 + debug("[Airoha] SPEED_1000/100 0x1694\n");
646 + /* clear the bit for other speeds */
647 + pbus_data = airoha_pbus_read(mbus, pbus_addr, 0x1694);
648 + pbus_data &= ~(1 << 31);
649 + ret = airoha_pbus_write(mbus, pbus_addr, 0x1694, pbus_data);
650 + AIR_RTN_ERR(ret);
651 + }
652 +
653 + airoha_pbus_write(mbus, pbus_addr, 0x0600, 0x0c000c00);
654 + if(SPEED_1000 == phydev->speed) {
655 + debug("[Airoha] SPEED_1000\n");
656 + ret = airoha_pbus_write(mbus, pbus_addr, 0x10, 0xD801);
657 + AIR_RTN_ERR(ret);
658 + ret = airoha_pbus_write(mbus, pbus_addr, 0x0, 0x9140);
659 + AIR_RTN_ERR(ret);
660 +
661 + ret = airoha_pbus_write(mbus, pbus_addr, 0x0A14, 0x0003);
662 + AIR_RTN_ERR(ret);
663 + ret = airoha_pbus_write(mbus, pbus_addr, 0x0600, 0x0c000c00);
664 + AIR_RTN_ERR(ret);
665 + mdelay(2); /* delay 2 ms */
666 + ret = airoha_pbus_write(mbus, pbus_addr, 0x1404, 0x004b);
667 + AIR_RTN_ERR(ret);
668 + ret = airoha_pbus_write(mbus, pbus_addr, 0x140c, 0x0007);
669 + AIR_RTN_ERR(ret);
670 + }
671 + else if (SPEED_100 == phydev->speed) {
672 + debug("[Airoha] SPEED_100\n");
673 + ret = airoha_pbus_write(mbus, pbus_addr, 0x10, 0xD401);
674 + AIR_RTN_ERR(ret);
675 + ret = airoha_pbus_write(mbus, pbus_addr, 0x0, 0x9140);
676 + AIR_RTN_ERR(ret);
677 + ret = airoha_pbus_write(mbus, pbus_addr, 0x0A14, 0x0007);
678 + AIR_RTN_ERR(ret);
679 + ret = airoha_pbus_write(mbus, pbus_addr, 0x0600, 0x0c11);
680 + AIR_RTN_ERR(ret);
681 + mdelay(2); /* delay 2 ms */
682 + ret = airoha_pbus_write(mbus, pbus_addr, 0x1404, 0x0027);
683 + AIR_RTN_ERR(ret);
684 + ret = airoha_pbus_write(mbus, pbus_addr, 0x140c, 0x0007);
685 + AIR_RTN_ERR(ret);
686 + }
687 + else {
688 + debug("[Airoha] SPEED_10\n");
689 + ret = airoha_pbus_write(mbus, pbus_addr, 0x10, 0xD001);
690 + AIR_RTN_ERR(ret);
691 + ret = airoha_pbus_write(mbus, pbus_addr, 0x0, 0x9140);
692 + AIR_RTN_ERR(ret);
693 +
694 + ret = airoha_pbus_write(mbus, pbus_addr, 0x0A14, 0x000b);
695 + AIR_RTN_ERR(ret);
696 + ret = airoha_pbus_write(mbus, pbus_addr, 0x0600, 0x0c11);
697 + AIR_RTN_ERR(ret);
698 + mdelay(2); /* delay 2 ms */
699 + ret = airoha_pbus_write(mbus, pbus_addr, 0x1404, 0x0047);
700 + AIR_RTN_ERR(ret);
701 + ret = airoha_pbus_write(mbus, pbus_addr, 0x140c, 0x0007);
702 + AIR_RTN_ERR(ret);
703 + }
704 + return 0;
705 +}
706 +
707 +static int en8801s_startup(struct phy_device *phydev)
708 +{
709 + int ret;
710 +
711 + ret = genphy_update_link(phydev);
712 + if (ret)
713 + return ret;
714 + ret = genphy_parse_link(phydev);
715 + if (ret)
716 + return ret;
717 + return en8801s_read_status(phydev);
718 +}
719 +#if AIR_UBOOT_REVISION > 0x202303
720 +U_BOOT_PHY_DRIVER(en8801s) = {
721 + .name = "Airoha EN8801S",
722 + .uid = EN8801S_PHY_ID,
723 + .mask = 0x0ffffff0,
724 + .features = PHY_GBIT_FEATURES,
725 + .config = &en8801s_config,
726 + .startup = &en8801s_startup,
727 + .shutdown = &genphy_shutdown,
728 +};
729 +#else
730 +static struct phy_driver AIR_EN8801S_driver = {
731 + .name = "Airoha EN8801S",
732 + .uid = EN8801S_PHY_ID,
733 + .mask = 0x0ffffff0,
734 + .features = PHY_GBIT_FEATURES,
735 + .config = &en8801s_config,
736 + .startup = &en8801s_startup,
737 + .shutdown = &genphy_shutdown,
738 +};
739 +
740 +int phy_air_en8801s_init(void)
741 +{
742 + phy_register(&AIR_EN8801S_driver);
743 + return 0;
744 +}
745 +#endif
746 --- /dev/null
747 +++ b/drivers/net/phy/air_en8801s.h
748 @@ -0,0 +1,267 @@
749 +/* SPDX-License-Identifier: GPL-2.0 */
750 +/*************************************************
751 + * FILE NAME: air_en8801s.h
752 + * PURPOSE:
753 + * EN8801S PHY Driver for Uboot
754 + * NOTES:
755 + *
756 + * Copyright (C) 2023 Airoha Technology Corp.
757 + *************************************************/
758 +
759 +#ifndef __EN8801S_H
760 +#define __EN8801S_H
761 +
762 +/************************************************************************
763 +* D E F I N E S
764 +************************************************************************/
765 +#define AIR_UBOOT_REVISION ((((U_BOOT_VERSION_NUM / 1000) % 10) << 20) | \
766 + (((U_BOOT_VERSION_NUM / 100) % 10) << 16) | \
767 + (((U_BOOT_VERSION_NUM / 10) % 10) << 12) | \
768 + ((U_BOOT_VERSION_NUM % 10) << 8) | \
769 + (((U_BOOT_VERSION_NUM_PATCH / 10) % 10) << 4) | \
770 + ((U_BOOT_VERSION_NUM_PATCH % 10) << 0))
771 +
772 +#define EN8801S_MDIO_DEFAULT_ID 0x1d
773 +#define EN8801S_PBUS_DEFAULT_ID (EN8801S_MDIO_DEFAULT_ID + 1)
774 +#define EN8801S_MDIO_PHY_ID 0x18 /* Range PHY_ADDRESS_RANGE .. 0x1e */
775 +#define EN8801S_PBUS_PHY_ID (EN8801S_MDIO_PHY_ID + 1)
776 +#define EN8801S_DRIVER_VERSION "v1.1.3"
777 +
778 +#define EN8801S_RG_ETHER_PHY_OUI 0x19a4
779 +#define EN8801S_RG_SMI_ADDR 0x19a8
780 +#define EN8801S_PBUS_OUI 0x17a5
781 +#define EN8801S_RG_BUCK_CTL 0x1a20
782 +#define EN8801S_RG_LTR_CTL 0x0cf8
783 +
784 +#define EN8801S_PHY_ID1 0x03a2
785 +#define EN8801S_PHY_ID2 0x9461
786 +#define EN8801S_PHY_ID (unsigned long)((EN8801S_PHY_ID1 << 16) | EN8801S_PHY_ID2)
787 +
788 +/*
789 +SFP Sample for verification
790 +Tx Reverse, Rx Reverse
791 +*/
792 +#define EN8801S_TX_POLARITY_NORMAL 0x0
793 +#define EN8801S_TX_POLARITY_REVERSE 0x1
794 +
795 +#define EN8801S_RX_POLARITY_NORMAL (0x1 << 1)
796 +#define EN8801S_RX_POLARITY_REVERSE (0x0 << 1)
797 +
798 +#ifndef BIT
799 +#define BIT(nr) (1UL << (nr))
800 +#endif
801 +
802 +#define MAX_RETRY 5
803 +#define MAX_OUI_CHECK 2
804 +
805 +/* CL45 MDIO control */
806 +#define MII_MMD_ACC_CTL_REG 0x0d
807 +#define MII_MMD_ADDR_DATA_REG 0x0e
808 +#define MMD_OP_MODE_DATA BIT(14)
809 +
810 +#define MAX_TRG_COUNTER 5
811 +
812 +/* TokenRing Reg Access */
813 +#define TrReg_PKT_XMT_STA 0x8000
814 +#define TrReg_WR 0x8000
815 +#define TrReg_RD 0xA000
816 +
817 +#define RgAddr_LPI_1Ch 0x1c
818 +#define RgAddr_AUXILIARY_1Dh 0x1d
819 +#define RgAddr_PMA_00h 0x0f80
820 +#define RgAddr_PMA_01h 0x0f82
821 +#define RgAddr_PMA_17h 0x0fae
822 +#define RgAddr_PMA_18h 0x0fb0
823 +#define RgAddr_DSPF_03h 0x1686
824 +#define RgAddr_DSPF_06h 0x168c
825 +#define RgAddr_DSPF_08h 0x1690
826 +#define RgAddr_DSPF_0Ch 0x1698
827 +#define RgAddr_DSPF_0Dh 0x169a
828 +#define RgAddr_DSPF_0Fh 0x169e
829 +#define RgAddr_DSPF_10h 0x16a0
830 +#define RgAddr_DSPF_11h 0x16a2
831 +#define RgAddr_DSPF_13h 0x16a6
832 +#define RgAddr_DSPF_14h 0x16a8
833 +#define RgAddr_DSPF_1Bh 0x16b6
834 +#define RgAddr_DSPF_1Ch 0x16b8
835 +#define RgAddr_TR_26h 0x0ecc
836 +#define RgAddr_R1000DEC_15h 0x03aa
837 +#define RgAddr_R1000DEC_17h 0x03ae
838 +
839 +/*
840 +The following led_cfg example is for reference only.
841 +LED5 1000M/LINK/ACT (GPIO5) <-> BASE_T_LED0,
842 +LED6 10/100M/LINK/ACT(GPIO9) <-> BASE_T_LED1,
843 +LED4 100M/LINK/ACT (GPIO8) <-> BASE_T_LED2,
844 +*/
845 +/* User-defined.B */
846 +#define BASE_T_LED0_ON_CFG (LED_ON_EVT_LINK_1000M)
847 +#define BASE_T_LED0_BLK_CFG (LED_BLK_EVT_1000M_TX_ACT | LED_BLK_EVT_1000M_RX_ACT)
848 +#define BASE_T_LED1_ON_CFG (LED_ON_EVT_LINK_100M | LED_ON_EVT_LINK_10M)
849 +#define BASE_T_LED1_BLK_CFG (LED_BLK_EVT_100M_TX_ACT | LED_BLK_EVT_100M_RX_ACT | \
850 + LED_BLK_EVT_10M_TX_ACT | LED_BLK_EVT_10M_RX_ACT )
851 +#define BASE_T_LED2_ON_CFG (LED_ON_EVT_LINK_100M)
852 +#define BASE_T_LED2_BLK_CFG (LED_BLK_EVT_100M_TX_ACT | LED_BLK_EVT_100M_RX_ACT)
853 +#define BASE_T_LED3_ON_CFG (0x0)
854 +#define BASE_T_LED3_BLK_CFG (0x0)
855 +/* User-defined.E */
856 +
857 +#define EN8801S_LED_COUNT 4
858 +
859 +#define LED_BCR (0x021)
860 +#define LED_BCR_EXT_CTRL (1 << 15)
861 +#define LED_BCR_CLK_EN (1 << 3)
862 +#define LED_BCR_TIME_TEST (1 << 2)
863 +#define LED_BCR_MODE_MASK (3)
864 +#define LED_BCR_MODE_DISABLE (0)
865 +#define LED_ON_CTRL(i) (0x024 + ((i)*2))
866 +#define LED_ON_EN (1 << 15)
867 +#define LED_ON_POL (1 << 14)
868 +#define LED_ON_EVT_MASK (0x7f)
869 +/* LED ON Event Option.B */
870 +#define LED_ON_EVT_FORCE (1 << 6)
871 +#define LED_ON_EVT_LINK_DOWN (1 << 3)
872 +#define LED_ON_EVT_LINK_10M (1 << 2)
873 +#define LED_ON_EVT_LINK_100M (1 << 1)
874 +#define LED_ON_EVT_LINK_1000M (1 << 0)
875 +/* LED ON Event Option.E */
876 +#define LED_BLK_CTRL(i) (0x025 + ((i)*2))
877 +#define LED_BLK_EVT_MASK (0x3ff)
878 +/* LED Blinking Event Option.B*/
879 +#define LED_BLK_EVT_FORCE (1 << 9)
880 +#define LED_BLK_EVT_10M_RX_ACT (1 << 5)
881 +#define LED_BLK_EVT_10M_TX_ACT (1 << 4)
882 +#define LED_BLK_EVT_100M_RX_ACT (1 << 3)
883 +#define LED_BLK_EVT_100M_TX_ACT (1 << 2)
884 +#define LED_BLK_EVT_1000M_RX_ACT (1 << 1)
885 +#define LED_BLK_EVT_1000M_TX_ACT (1 << 0)
886 +/* LED Blinking Event Option.E*/
887 +#define LED_ON_DUR (0x022)
888 +#define LED_ON_DUR_MASK (0xffff)
889 +#define LED_BLK_DUR (0x023)
890 +#define LED_BLK_DUR_MASK (0xffff)
891 +
892 +#define LED_ENABLE 1
893 +#define LED_DISABLE 0
894 +
895 +#define UNIT_LED_BLINK_DURATION 1024
896 +
897 +#define AIR_RTN_ON_ERR(cond, err) \
898 + do { if ((cond)) return (err); } while(0)
899 +
900 +#define AIR_RTN_ERR(err) AIR_RTN_ON_ERR(err < 0, err)
901 +
902 +#define LED_SET_EVT(reg, cod, result, bit) do \
903 + { \
904 + if(reg & cod) { \
905 + result |= bit; \
906 + } \
907 + } while(0)
908 +
909 +#define LED_SET_GPIO_SEL(gpio, led, val) do \
910 + { \
911 + val |= (led << (8 * (gpio % 4))); \
912 + } while(0)
913 +
914 +/* DATA TYPE DECLARATIONS
915 + */
916 +typedef struct
917 +{
918 + int DATA_Lo;
919 + int DATA_Hi;
920 +}TR_DATA_T;
921 +
922 +typedef union
923 +{
924 + struct
925 + {
926 + /* b[15:00] */
927 + int smi_deton_wt : 3;
928 + int smi_det_mdi_inv : 1;
929 + int smi_detoff_wt : 3;
930 + int smi_sigdet_debouncing_en : 1;
931 + int smi_deton_th : 6;
932 + int rsv_14 : 2;
933 + } DataBitField;
934 + int DATA;
935 +} gephy_all_REG_LpiReg1Ch, *Pgephy_all_REG_LpiReg1Ch;
936 +
937 +typedef union
938 +{
939 + struct
940 + {
941 + /* b[15:00] */
942 + int rg_smi_detcnt_max : 6;
943 + int rsv_6 : 2;
944 + int rg_smi_det_max_en : 1;
945 + int smi_det_deglitch_off : 1;
946 + int rsv_10 : 6;
947 + } DataBitField;
948 + int DATA;
949 +} gephy_all_REG_dev1Eh_reg324h, *Pgephy_all_REG_dev1Eh_reg324h;
950 +
951 +typedef union
952 +{
953 + struct
954 + {
955 + /* b[15:00] */
956 + int da_tx_i2mpb_a_tbt : 6;
957 + int rsv_6 : 4;
958 + int da_tx_i2mpb_a_gbe : 6;
959 + } DataBitField;
960 + int DATA;
961 +} gephy_all_REG_dev1Eh_reg012h, *Pgephy_all_REG_dev1Eh_reg012h;
962 +
963 +typedef union
964 +{
965 + struct
966 + {
967 + /* b[15:00] */
968 + int da_tx_i2mpb_b_tbt : 6;
969 + int rsv_6 : 2;
970 + int da_tx_i2mpb_b_gbe : 6;
971 + int rsv_14 : 2;
972 + } DataBitField;
973 + int DATA;
974 +} gephy_all_REG_dev1Eh_reg017h, *Pgephy_all_REG_dev1Eh_reg017h;
975 +
976 +typedef struct AIR_BASE_T_LED_CFG_S
977 +{
978 + u16 en;
979 + u16 gpio;
980 + u16 pol;
981 + u16 on_cfg;
982 + u16 blk_cfg;
983 +}AIR_BASE_T_LED_CFG_T;
984 +
985 +typedef enum
986 +{
987 + AIR_LED_BLK_DUR_32M,
988 + AIR_LED_BLK_DUR_64M,
989 + AIR_LED_BLK_DUR_128M,
990 + AIR_LED_BLK_DUR_256M,
991 + AIR_LED_BLK_DUR_512M,
992 + AIR_LED_BLK_DUR_1024M,
993 + AIR_LED_BLK_DUR_LAST
994 +} AIR_LED_BLK_DUT_T;
995 +
996 +typedef enum
997 +{
998 + AIR_ACTIVE_LOW,
999 + AIR_ACTIVE_HIGH,
1000 +} AIR_LED_POLARITY;
1001 +typedef enum
1002 +{
1003 + AIR_LED_MODE_DISABLE,
1004 + AIR_LED_MODE_USER_DEFINE,
1005 + AIR_LED_MODE_LAST
1006 +} AIR_LED_MODE_T;
1007 +
1008 +/************************************************************************
1009 +* F U N C T I O N P R O T O T Y P E S
1010 +************************************************************************/
1011 +
1012 +unsigned long airoha_pbus_read(struct mii_dev *bus, int pbus_addr, int pbus_reg);
1013 +int airoha_pbus_write(struct mii_dev *bus, int pbus_addr, int pbus_reg, unsigned long pbus_data);
1014 +int airoha_phy_process(void);
1015 +#endif /* __EN8801S_H */
1016 --- /dev/null
1017 +++ b/drivers/net/phy/air_en8811h.c
1018 @@ -0,0 +1,725 @@
1019 +// SPDX-License-Identifier: GPL-2.0
1020 +/*************************************************
1021 + * FILE NAME: air_en8811h.c
1022 + * PURPOSE:
1023 + * EN8811H PHY Driver for Uboot
1024 + * NOTES:
1025 + *
1026 + * Copyright (C) 2023 Airoha Technology Corp.
1027 + *************************************************/
1028 +
1029 +/* INCLUDE FILE DECLARATIONS
1030 +*/
1031 +#include <common.h>
1032 +#include <eth_phy.h>
1033 +#include <phy.h>
1034 +#include <errno.h>
1035 +#include <malloc.h>
1036 +#include <version.h>
1037 +#include "air_en8811h.h"
1038 +
1039 +#ifdef CONFIG_PHY_AIROHA_FW_IN_UBI
1040 +#include <ubi_uboot.h>
1041 +#endif
1042 +
1043 +#ifdef CONFIG_PHY_AIROHA_FW_IN_MMC
1044 +#include <mmc.h>
1045 +#endif
1046 +
1047 +#ifdef CONFIG_PHY_AIROHA_FW_IN_MTD
1048 +#include <mtd.h>
1049 +#endif
1050 +
1051 +#if AIR_UBOOT_REVISION > 0x202004
1052 +#include <linux/delay.h>
1053 +#endif
1054 +
1055 +/**************************
1056 + * GPIO5 <-> BASE_T_LED0,
1057 + * GPIO4 <-> BASE_T_LED1,
1058 + * GPIO3 <-> BASE_T_LED2,
1059 + **************************/
1060 +/* User-defined.B */
1061 +#define AIR_LED_SUPPORT
1062 +#ifdef AIR_LED_SUPPORT
1063 +static const struct air_base_t_led_cfg_s led_cfg[3] = {
1064 +/*********************************************************************
1065 + *Enable, GPIO, LED Polarity, LED ON, LED Blink
1066 +**********************************************************************/
1067 + {1, AIR_LED0_GPIO5, AIR_ACTIVE_HIGH, AIR_LED0_ON, AIR_LED0_BLK},
1068 + {1, AIR_LED1_GPIO4, AIR_ACTIVE_HIGH, AIR_LED1_ON, AIR_LED1_BLK},
1069 + {1, AIR_LED2_GPIO3, AIR_ACTIVE_HIGH, AIR_LED2_ON, AIR_LED2_BLK},
1070 +};
1071 +static const u16 led_dur = UNIT_LED_BLINK_DURATION << AIR_LED_BLK_DUR_64M;
1072 +#endif
1073 +/* User-defined.E */
1074 +/*************************************************************
1075 + * F U N C T I O N S
1076 + **************************************************************/
1077 +/* Airoha MII read function */
1078 +static int air_mii_cl22_read(struct mii_dev *bus, int phy_addr, int phy_register)
1079 +{
1080 + int read_data = bus->read(bus, phy_addr, MDIO_DEVAD_NONE, phy_register);
1081 +
1082 + if (read_data < 0)
1083 + return -EIO;
1084 + return read_data;
1085 +}
1086 +
1087 +/* Airoha MII write function */
1088 +static int air_mii_cl22_write(struct mii_dev *bus, int phy_addr, int phy_register, int write_data)
1089 +{
1090 + int ret = 0;
1091 +
1092 + ret = bus->write(bus, phy_addr, MDIO_DEVAD_NONE, phy_register, write_data);
1093 + if (ret < 0) {
1094 + printf("bus->write, ret: %d\n", ret);
1095 + return ret;
1096 + }
1097 + return ret;
1098 +}
1099 +
1100 +static int air_mii_cl45_read(struct phy_device *phydev, int devad, u16 reg)
1101 +{
1102 + int ret = 0;
1103 + int data;
1104 +
1105 + ret = phy_write(phydev, MDIO_DEVAD_NONE, MII_MMD_ACC_CTL_REG, devad);
1106 + if (ret < 0) {
1107 + printf("phy_write, ret: %d\n", ret);
1108 + return INVALID_DATA;
1109 + }
1110 + ret = phy_write(phydev, MDIO_DEVAD_NONE, MII_MMD_ADDR_DATA_REG, reg);
1111 + if (ret < 0) {
1112 + printf("phy_write, ret: %d\n", ret);
1113 + return INVALID_DATA;
1114 + }
1115 + ret = phy_write(phydev, MDIO_DEVAD_NONE, MII_MMD_ACC_CTL_REG, MMD_OP_MODE_DATA | devad);
1116 + if (ret < 0) {
1117 + printf("phy_write, ret: %d\n", ret);
1118 + return INVALID_DATA;
1119 + }
1120 + data = phy_read(phydev, MDIO_DEVAD_NONE, MII_MMD_ADDR_DATA_REG);
1121 + return data;
1122 +}
1123 +
1124 +static int air_mii_cl45_write(struct phy_device *phydev, int devad, u16 reg, u16 write_data)
1125 +{
1126 + int ret = 0;
1127 +
1128 + ret = phy_write(phydev, MDIO_DEVAD_NONE, MII_MMD_ACC_CTL_REG, devad);
1129 + if (ret < 0) {
1130 + printf("phy_write, ret: %d\n", ret);
1131 + return ret;
1132 + }
1133 + ret = phy_write(phydev, MDIO_DEVAD_NONE, MII_MMD_ADDR_DATA_REG, reg);
1134 + if (ret < 0) {
1135 + printf("phy_write, ret: %d\n", ret);
1136 + return ret;
1137 + }
1138 + ret = phy_write(phydev, MDIO_DEVAD_NONE, MII_MMD_ACC_CTL_REG, MMD_OP_MODE_DATA | devad);
1139 + if (ret < 0) {
1140 + printf("phy_write, ret: %d\n", ret);
1141 + return ret;
1142 + }
1143 + ret = phy_write(phydev, MDIO_DEVAD_NONE, MII_MMD_ADDR_DATA_REG, write_data);
1144 + if (ret < 0) {
1145 + printf("phy_write, ret: %d\n", ret);
1146 + return ret;
1147 + }
1148 + return 0;
1149 +}
1150 +/* Use default PBUS_PHY_ID */
1151 +/* EN8811H PBUS write function */
1152 +static int air_pbus_reg_write(struct phy_device *phydev, unsigned long pbus_address, unsigned long pbus_data)
1153 +{
1154 + int ret = 0;
1155 + struct mii_dev *mbus = phydev->bus;
1156 +
1157 + ret = air_mii_cl22_write(mbus, ((phydev->addr) + 8), 0x1F, (unsigned int)(pbus_address >> 6));
1158 + if (ret < 0)
1159 + return ret;
1160 + ret = air_mii_cl22_write(mbus, ((phydev->addr) + 8), (unsigned int)((pbus_address >> 2) & 0xf), (unsigned int)(pbus_data & 0xFFFF));
1161 + if (ret < 0)
1162 + return ret;
1163 + ret = air_mii_cl22_write(mbus, ((phydev->addr) + 8), 0x10, (unsigned int)(pbus_data >> 16));
1164 + if (ret < 0)
1165 + return ret;
1166 + return 0;
1167 +}
1168 +
1169 +/* EN8811H BUCK write function */
1170 +static int air_buckpbus_reg_write(struct phy_device *phydev, unsigned long pbus_address, unsigned int pbus_data)
1171 +{
1172 + int ret = 0;
1173 +
1174 + /* page 4 */
1175 + ret = phy_write(phydev, MDIO_DEVAD_NONE, 0x1F, (unsigned int)4);
1176 + if (ret < 0) {
1177 + printf("phy_write, ret: %d\n", ret);
1178 + return ret;
1179 + }
1180 + ret = phy_write(phydev, MDIO_DEVAD_NONE, 0x10, (unsigned int)0);
1181 + if (ret < 0) {
1182 + printf("phy_write, ret: %d\n", ret);
1183 + return ret;
1184 + }
1185 + ret = phy_write(phydev, MDIO_DEVAD_NONE, 0x11, (unsigned int)((pbus_address >> 16) & 0xffff));
1186 + if (ret < 0) {
1187 + printf("phy_write, ret: %d\n", ret);
1188 + return ret;
1189 + }
1190 + ret = phy_write(phydev, MDIO_DEVAD_NONE, 0x12, (unsigned int)(pbus_address & 0xffff));
1191 + if (ret < 0) {
1192 + printf("phy_write, ret: %d\n", ret);
1193 + return ret;
1194 + }
1195 + ret = phy_write(phydev, MDIO_DEVAD_NONE, 0x13, (unsigned int)((pbus_data >> 16) & 0xffff));
1196 + if (ret < 0) {
1197 + printf("phy_write, ret: %d\n", ret);
1198 + return ret;
1199 + }
1200 + ret = phy_write(phydev, MDIO_DEVAD_NONE, 0x14, (unsigned int)(pbus_data & 0xffff));
1201 + if (ret < 0) {
1202 + printf("phy_write, ret: %d\n", ret);
1203 + return ret;
1204 + }
1205 + return 0;
1206 +}
1207 +
1208 +/* EN8811H BUCK read function */
1209 +static unsigned int air_buckpbus_reg_read(struct phy_device *phydev, unsigned long pbus_address)
1210 +{
1211 + unsigned int pbus_data = 0, pbus_data_low, pbus_data_high;
1212 + int ret = 0;
1213 +
1214 + ret = phy_write(phydev, MDIO_DEVAD_NONE, 0x1F, (unsigned int)4); /* page 4 */
1215 + if (ret < 0) {
1216 + printf("phy_write, ret: %d\n", ret);
1217 + return PBUS_INVALID_DATA;
1218 + }
1219 + ret = phy_write(phydev, MDIO_DEVAD_NONE, 0x10, (unsigned int)0);
1220 + if (ret < 0) {
1221 + printf("phy_write, ret: %d\n", ret);
1222 + return PBUS_INVALID_DATA;
1223 + }
1224 + ret = phy_write(phydev, MDIO_DEVAD_NONE, 0x15, (unsigned int)((pbus_address >> 16) & 0xffff));
1225 + if (ret < 0) {
1226 + printf("phy_write, ret: %d\n", ret);
1227 + return PBUS_INVALID_DATA;
1228 + }
1229 + ret = phy_write(phydev, MDIO_DEVAD_NONE, 0x16, (unsigned int)(pbus_address & 0xffff));
1230 + if (ret < 0) {
1231 + printf("phy_write, ret: %d\n", ret);
1232 + return PBUS_INVALID_DATA;
1233 + }
1234 +
1235 + pbus_data_high = phy_read(phydev, MDIO_DEVAD_NONE, 0x17);
1236 + pbus_data_low = phy_read(phydev, MDIO_DEVAD_NONE, 0x18);
1237 + pbus_data = (pbus_data_high << 16) + pbus_data_low;
1238 + ret = phy_write(phydev, MDIO_DEVAD_NONE, 0x1F, (unsigned int)0);
1239 + if (ret < 0) {
1240 + printf("phy_write, ret: %d\n", ret);
1241 + return ret;
1242 + }
1243 + return pbus_data;
1244 +}
1245 +
1246 +static int MDIOWriteBuf(struct phy_device *phydev, unsigned long address, unsigned long array_size, const unsigned char *buffer)
1247 +{
1248 + unsigned int write_data, offset ;
1249 + int ret = 0;
1250 +
1251 + /* page 4 */
1252 + ret = phy_write(phydev, MDIO_DEVAD_NONE, 0x1F, (unsigned int)4);
1253 + if (ret < 0) {
1254 + printf("phy_write, ret: %d\n", ret);
1255 + return ret;
1256 + }
1257 + /* address increment*/
1258 + ret = phy_write(phydev, MDIO_DEVAD_NONE, 0x10, (unsigned int)0x8000);
1259 + if (ret < 0) {
1260 + printf("phy_write, ret: %d\n", ret);
1261 + return ret;
1262 + }
1263 + ret = phy_write(phydev, MDIO_DEVAD_NONE, 0x11, (unsigned int)((address >> 16) & 0xffff));
1264 + if (ret < 0) {
1265 + printf("phy_write, ret: %d\n", ret);
1266 + return ret;
1267 + }
1268 + ret = phy_write(phydev, MDIO_DEVAD_NONE, 0x12, (unsigned int)(address & 0xffff));
1269 + if (ret < 0) {
1270 + printf("phy_write, ret: %d\n", ret);
1271 + return ret;
1272 + }
1273 +
1274 + for (offset = 0; offset < array_size; offset += 4) {
1275 + write_data = (buffer[offset + 3] << 8) | buffer[offset + 2];
1276 + ret = phy_write(phydev, MDIO_DEVAD_NONE, 0x13, write_data);
1277 + if (ret < 0) {
1278 + printf("phy_write, ret: %d\n", ret);
1279 + return ret;
1280 + }
1281 + write_data = (buffer[offset + 1] << 8) | buffer[offset];
1282 + ret = phy_write(phydev, MDIO_DEVAD_NONE, 0x14, write_data);
1283 + if (ret < 0) {
1284 + printf("phy_write, ret: %d\n", ret);
1285 + return ret;
1286 + }
1287 + }
1288 + ret = phy_write(phydev, MDIO_DEVAD_NONE, 0x1F, (unsigned int)0);
1289 + if (ret < 0) {
1290 + printf("phy_write, ret: %d\n", ret);
1291 + return ret;
1292 + }
1293 + return 0;
1294 +}
1295 +
1296 +#ifdef AIR_LED_SUPPORT
1297 +static int airoha_led_set_usr_def(struct phy_device *phydev, u8 entity, int polar,
1298 + u16 on_evt, u16 blk_evt)
1299 +{
1300 + int ret = 0;
1301 +
1302 + if (AIR_ACTIVE_HIGH == polar)
1303 + on_evt |= LED_ON_POL;
1304 + else
1305 + on_evt &= ~LED_ON_POL;
1306 +
1307 + ret = air_mii_cl45_write(phydev, 0x1f, LED_ON_CTRL(entity), on_evt | LED_ON_EN);
1308 + if (ret < 0)
1309 + return ret;
1310 + ret = air_mii_cl45_write(phydev, 0x1f, LED_BLK_CTRL(entity), blk_evt);
1311 + if (ret < 0)
1312 + return ret;
1313 + return 0;
1314 +}
1315 +
1316 +static int airoha_led_set_mode(struct phy_device *phydev, u8 mode)
1317 +{
1318 + u16 cl45_data;
1319 + int err = 0;
1320 +
1321 + cl45_data = air_mii_cl45_read(phydev, 0x1f, LED_BCR);
1322 + switch (mode) {
1323 + case AIR_LED_MODE_DISABLE:
1324 + cl45_data &= ~LED_BCR_EXT_CTRL;
1325 + cl45_data &= ~LED_BCR_MODE_MASK;
1326 + cl45_data |= LED_BCR_MODE_DISABLE;
1327 + break;
1328 + case AIR_LED_MODE_USER_DEFINE:
1329 + cl45_data |= LED_BCR_EXT_CTRL;
1330 + cl45_data |= LED_BCR_CLK_EN;
1331 + break;
1332 + default:
1333 + printf("LED mode%d is not supported!\n", mode);
1334 + return -EINVAL;
1335 + }
1336 + err = air_mii_cl45_write(phydev, 0x1f, LED_BCR, cl45_data);
1337 + if (err < 0)
1338 + return err;
1339 + return 0;
1340 +}
1341 +
1342 +static int airoha_led_set_state(struct phy_device *phydev, u8 entity, u8 state)
1343 +{
1344 + u16 cl45_data;
1345 + int err;
1346 +
1347 + cl45_data = air_mii_cl45_read(phydev, 0x1f, LED_ON_CTRL(entity));
1348 + if (LED_ENABLE == state)
1349 + cl45_data |= LED_ON_EN;
1350 + else
1351 + cl45_data &= ~LED_ON_EN;
1352 +
1353 + err = air_mii_cl45_write(phydev, 0x1f, LED_ON_CTRL(entity), cl45_data);
1354 + if (err < 0)
1355 + return err;
1356 + return 0;
1357 +}
1358 +
1359 +static int en8811h_led_init(struct phy_device *phydev)
1360 +{
1361 + unsigned int led_gpio = 0, reg_value = 0;
1362 + u16 cl45_data = led_dur;
1363 + int ret, led_id;
1364 +
1365 + cl45_data = UNIT_LED_BLINK_DURATION << AIR_LED_BLK_DUR_64M;
1366 + ret = air_mii_cl45_write(phydev, 0x1f, LED_BLK_DUR, cl45_data);
1367 + if (ret < 0)
1368 + return ret;
1369 + cl45_data >>= 1;
1370 + ret = air_mii_cl45_write(phydev, 0x1f, LED_ON_DUR, cl45_data);
1371 + if (ret < 0)
1372 + return ret;
1373 +
1374 + ret = airoha_led_set_mode(phydev, AIR_LED_MODE_USER_DEFINE);
1375 + if (ret != 0) {
1376 + printf("LED fail to set mode, ret %d !\n", ret);
1377 + return ret;
1378 + }
1379 + for(led_id = 0; led_id < EN8811H_LED_COUNT; led_id++)
1380 + {
1381 + /* LED0 <-> GPIO5, LED1 <-> GPIO4, LED0 <-> GPIO3 */
1382 + if ( led_cfg[led_id].gpio != (led_id + (AIR_LED0_GPIO5 - (2 * led_id)))) {
1383 + printf("LED%d uses incorrect GPIO%d !\n", led_id, led_cfg[led_id].gpio);
1384 + return -EINVAL;
1385 + }
1386 + reg_value = 0;
1387 + if (led_cfg[led_id].en == LED_ENABLE)
1388 + {
1389 + led_gpio |= BIT(led_cfg[led_id].gpio);
1390 + ret = airoha_led_set_state(phydev, led_id, led_cfg[led_id].en);
1391 + if (ret != 0) {
1392 + printf("LED fail to set state, ret %d !\n", ret);
1393 + return ret;
1394 + }
1395 + ret = airoha_led_set_usr_def(phydev, led_id, led_cfg[led_id].pol, led_cfg[led_id].on_cfg, led_cfg[led_id].blk_cfg);
1396 + if (ret != 0) {
1397 + printf("LED fail to set default, ret %d !\n", ret);
1398 + return ret;
1399 + }
1400 + }
1401 + }
1402 + ret = air_buckpbus_reg_write(phydev, 0xcf8b8, led_gpio);
1403 + if (ret < 0)
1404 + return ret;
1405 + printf("LED initialize OK !\n");
1406 + return 0;
1407 +}
1408 +#endif /* AIR_LED_SUPPORT */
1409 +
1410 +static char *firmware_buf;
1411 +static int en8811h_load_firmware(struct phy_device *phydev)
1412 +{
1413 + u32 pbus_value;
1414 + int ret = 0;
1415 +
1416 + if (!firmware_buf) {
1417 + firmware_buf = malloc(EN8811H_MD32_DM_SIZE + EN8811H_MD32_DSP_SIZE);
1418 + if (!firmware_buf) {
1419 + printf("[Airoha] cannot allocated buffer for firmware.\n");
1420 + return -ENOMEM;
1421 + }
1422 +
1423 +#ifdef CONFIG_PHY_AIROHA_FW_IN_UBI
1424 + ret = ubi_volume_read("en8811h-fw", firmware_buf, EN8811H_MD32_DM_SIZE + EN8811H_MD32_DSP_SIZE);
1425 + if (ret) {
1426 + printf("[Airoha] read firmware from UBI failed.\n");
1427 + free(firmware_buf);
1428 + firmware_buf = NULL;
1429 + return ret;
1430 + }
1431 +#elif defined(CONFIG_PHY_AIROHA_FW_IN_MMC)
1432 + struct mmc *mmc = find_mmc_device(0);
1433 + if (!mmc) {
1434 + printf("[Airoha] opening MMC device failed.\n");
1435 + free(firmware_buf);
1436 + firmware_buf = NULL;
1437 + return -ENODEV;
1438 + }
1439 + if (mmc_init(mmc)) {
1440 + printf("[Airoha] initializing MMC device failed.\n");
1441 + free(firmware_buf);
1442 + firmware_buf = NULL;
1443 + return -ENODEV;
1444 + }
1445 + if (IS_SD(mmc)) {
1446 + printf("[Airoha] SD card is not supported.\n");
1447 + free(firmware_buf);
1448 + firmware_buf = NULL;
1449 + return -EINVAL;
1450 + }
1451 + ret = mmc_set_part_conf(mmc, 1, 2, 2);
1452 + if (ret) {
1453 + printf("[Airoha] cannot access eMMC boot1 hw partition.\n");
1454 + free(firmware_buf);
1455 + firmware_buf = NULL;
1456 + return ret;
1457 + }
1458 + ret = blk_dread(mmc_get_blk_desc(mmc), 0, 0x120, firmware_buf);
1459 + mmc_set_part_conf(mmc, 1, 1, 0);
1460 + if (ret != 0x120) {
1461 + printf("[Airoha] cannot read firmware from eMMC.\n");
1462 + free(firmware_buf);
1463 + firmware_buf = NULL;
1464 + return -EIO;
1465 + }
1466 +#else
1467 +#warning EN8811H firmware loading not implemented
1468 + free(firmware_buf);
1469 + firmware_buf = NULL;
1470 + return -EOPNOTSUPP;
1471 +#endif
1472 + }
1473 +
1474 + ret = air_buckpbus_reg_write(phydev, 0x0f0018, 0x0);
1475 + if (ret < 0)
1476 + return ret;
1477 + pbus_value = air_buckpbus_reg_read(phydev, 0x800000);
1478 + pbus_value |= BIT(11);
1479 + ret = air_buckpbus_reg_write(phydev, 0x800000, pbus_value);
1480 + if (ret < 0)
1481 + return ret;
1482 + /* Download DM */
1483 + ret = MDIOWriteBuf(phydev, 0x00000000, EN8811H_MD32_DM_SIZE, firmware_buf);
1484 + if (ret < 0) {
1485 + printf("[Airoha] MDIOWriteBuf 0x00000000 fail.\n");
1486 + return ret;
1487 + }
1488 + /* Download PM */
1489 + ret = MDIOWriteBuf(phydev, 0x00100000, EN8811H_MD32_DSP_SIZE, firmware_buf + EN8811H_MD32_DM_SIZE);
1490 + if (ret < 0) {
1491 + printf("[Airoha] MDIOWriteBuf 0x00100000 fail.\n");
1492 + return ret;
1493 + }
1494 + pbus_value = air_buckpbus_reg_read(phydev, 0x800000);
1495 + pbus_value &= ~BIT(11);
1496 + ret = air_buckpbus_reg_write(phydev, 0x800000, pbus_value);
1497 + if (ret < 0)
1498 + return ret;
1499 + ret = air_buckpbus_reg_write(phydev, 0x0f0018, 0x01);
1500 + if (ret < 0)
1501 + return ret;
1502 + return 0;
1503 +}
1504 +
1505 +static int en8811h_config(struct phy_device *phydev)
1506 +{
1507 + int ret = 0;
1508 + int pid1 = 0, pid2 = 0;
1509 +
1510 + ret = air_pbus_reg_write(phydev, 0xcf928 , 0x0);
1511 + if (ret < 0)
1512 + return ret;
1513 +
1514 + pid1 = phy_read(phydev, MDIO_DEVAD_NONE, MII_PHYSID1);
1515 + pid2 = phy_read(phydev, MDIO_DEVAD_NONE, MII_PHYSID2);
1516 + if ((EN8811H_PHY_ID1 != pid1) || (EN8811H_PHY_ID2 != pid2)) {
1517 + printf("EN8811H does not exist !\n");
1518 + return -ENODEV;
1519 + }
1520 +
1521 + return 0;
1522 +}
1523 +
1524 +static int en8811h_get_autonego(struct phy_device *phydev, int *an)
1525 +{
1526 + int reg;
1527 + reg = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMCR);
1528 + if (reg < 0)
1529 + return -EINVAL;
1530 + if (reg & BMCR_ANENABLE)
1531 + *an = AUTONEG_ENABLE;
1532 + else
1533 + *an = AUTONEG_DISABLE;
1534 + return 0;
1535 +}
1536 +
1537 +static int en8811h_startup(struct phy_device *phydev)
1538 +{
1539 + ofnode node = phy_get_ofnode(phydev);
1540 + int ret = 0, lpagb = 0, lpa = 0, common_adv_gb = 0, common_adv = 0, advgb = 0, adv = 0, reg = 0, an = AUTONEG_DISABLE, bmcr = 0, reg_value;
1541 + int old_link = phydev->link;
1542 + u32 pbus_value = 0, retry;
1543 +
1544 + eth_phy_reset(phydev->dev, 1);
1545 + mdelay(10);
1546 + eth_phy_reset(phydev->dev, 0);
1547 + mdelay(1);
1548 +
1549 + ret = en8811h_load_firmware(phydev);
1550 + if (ret) {
1551 + printf("EN8811H load firmware fail.\n");
1552 + return ret;
1553 + }
1554 + retry = MAX_RETRY;
1555 + do {
1556 + mdelay(300);
1557 + reg_value = air_mii_cl45_read(phydev, 0x1e, 0x8009);
1558 + if (EN8811H_PHY_READY == reg_value) {
1559 + printf("EN8811H PHY ready!\n");
1560 + break;
1561 + }
1562 + retry--;
1563 + } while (retry);
1564 + if (0 == retry) {
1565 + printf("EN8811H PHY is not ready. (MD32 FW Status reg: 0x%x)\n", reg_value);
1566 + pbus_value = air_buckpbus_reg_read(phydev, 0x3b3c);
1567 + printf("Check MD32 FW Version(0x3b3c) : %08x\n", pbus_value);
1568 + printf("EN8811H initialize fail!\n");
1569 + return 0;
1570 + }
1571 + /* Mode selection*/
1572 + printf("EN8811H Mode 1 !\n");
1573 + ret = air_mii_cl45_write(phydev, 0x1e, 0x800c, 0x0);
1574 + if (ret < 0)
1575 + return ret;
1576 + ret = air_mii_cl45_write(phydev, 0x1e, 0x800d, 0x0);
1577 + if (ret < 0)
1578 + return ret;
1579 + ret = air_mii_cl45_write(phydev, 0x1e, 0x800e, 0x1101);
1580 + if (ret < 0)
1581 + return ret;
1582 + ret = air_mii_cl45_write(phydev, 0x1e, 0x800f, 0x0002);
1583 + if (ret < 0)
1584 + return ret;
1585 +
1586 + /* Serdes polarity */
1587 + pbus_value = air_buckpbus_reg_read(phydev, 0xca0f8);
1588 + pbus_value &= 0xfffffffc;
1589 + pbus_value |= ofnode_read_bool(node, "airoha,rx-pol-reverse") ?
1590 + EN8811H_RX_POLARITY_REVERSE : EN8811H_RX_POLARITY_NORMAL;
1591 + pbus_value |= ofnode_read_bool(node, "airoha,tx-pol-reverse") ?
1592 + EN8811H_TX_POLARITY_REVERSE : EN8811H_TX_POLARITY_NORMAL;
1593 + ret = air_buckpbus_reg_write(phydev, 0xca0f8, pbus_value);
1594 + if (ret < 0)
1595 + return ret;
1596 + pbus_value = air_buckpbus_reg_read(phydev, 0xca0f8);
1597 + printf("Tx, Rx Polarity(0xca0f8): %08x\n", pbus_value);
1598 + pbus_value = air_buckpbus_reg_read(phydev, 0x3b3c);
1599 + printf("MD32 FW Version(0x3b3c) : %08x\n", pbus_value);
1600 +#if defined(AIR_LED_SUPPORT)
1601 + ret = en8811h_led_init(phydev);
1602 + if (ret < 0) {
1603 + printf("en8811h_led_init fail\n");
1604 + }
1605 +#endif
1606 + printf("EN8811H initialize OK ! (%s)\n", EN8811H_DRIVER_VERSION);
1607 +
1608 + ret = genphy_update_link(phydev);
1609 + if (ret)
1610 + {
1611 + printf("ret %d!\n", ret);
1612 + return ret;
1613 + }
1614 +
1615 + ret = genphy_parse_link(phydev);
1616 + if (ret)
1617 + {
1618 + printf("ret %d!\n", ret);
1619 + return ret;
1620 + }
1621 +
1622 + if (old_link && phydev->link)
1623 + return 0;
1624 +
1625 + phydev->speed = SPEED_100;
1626 + phydev->duplex = DUPLEX_FULL;
1627 + phydev->pause = 0;
1628 + phydev->asym_pause = 0;
1629 +
1630 + reg = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMSR);
1631 + if (reg < 0)
1632 + {
1633 + printf("MII_BMSR reg %d!\n", reg);
1634 + return reg;
1635 + }
1636 + reg = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMSR);
1637 + if (reg < 0)
1638 + {
1639 + printf("MII_BMSR reg %d!\n", reg);
1640 + return reg;
1641 + }
1642 + if(reg & BMSR_LSTATUS)
1643 + {
1644 + pbus_value = air_buckpbus_reg_read(phydev, 0x109D4);
1645 + if (0x10 & pbus_value) {
1646 + phydev->speed = SPEED_2500;
1647 + phydev->duplex = DUPLEX_FULL;
1648 + }
1649 + else
1650 + {
1651 + ret = en8811h_get_autonego(phydev, &an);
1652 + if ((AUTONEG_ENABLE == an) && (0 == ret))
1653 + {
1654 + printf("AN mode!\n");
1655 + printf("SPEED 1000/100!\n");
1656 + lpagb = phy_read(phydev, MDIO_DEVAD_NONE, MII_STAT1000);
1657 + if (lpagb < 0 )
1658 + return lpagb;
1659 + advgb = phy_read(phydev, MDIO_DEVAD_NONE, MII_CTRL1000);
1660 + if (adv < 0 )
1661 + return adv;
1662 + common_adv_gb = (lpagb & (advgb << 2));
1663 +
1664 + lpa = phy_read(phydev, MDIO_DEVAD_NONE, MII_LPA);
1665 + if (lpa < 0 )
1666 + return lpa;
1667 + adv = phy_read(phydev, MDIO_DEVAD_NONE, MII_ADVERTISE);
1668 + if (adv < 0 )
1669 + return adv;
1670 + common_adv = (lpa & adv);
1671 +
1672 + phydev->speed = SPEED_10;
1673 + phydev->duplex = DUPLEX_HALF;
1674 + if (common_adv_gb & (LPA_1000FULL | LPA_1000HALF))
1675 + {
1676 + phydev->speed = SPEED_1000;
1677 + if (common_adv_gb & LPA_1000FULL)
1678 +
1679 + phydev->duplex = DUPLEX_FULL;
1680 + }
1681 + else if (common_adv & (LPA_100FULL | LPA_100HALF))
1682 + {
1683 + phydev->speed = SPEED_100;
1684 + if (common_adv & LPA_100FULL)
1685 + phydev->duplex = DUPLEX_FULL;
1686 + }
1687 + else
1688 + {
1689 + if (common_adv & LPA_10FULL)
1690 + phydev->duplex = DUPLEX_FULL;
1691 + }
1692 + }
1693 + else
1694 + {
1695 + printf("Force mode!\n");
1696 + bmcr = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMCR);
1697 +
1698 + if (bmcr < 0)
1699 + return bmcr;
1700 +
1701 + if (bmcr & BMCR_FULLDPLX)
1702 + phydev->duplex = DUPLEX_FULL;
1703 + else
1704 + phydev->duplex = DUPLEX_HALF;
1705 +
1706 + if (bmcr & BMCR_SPEED1000)
1707 + phydev->speed = SPEED_1000;
1708 + else if (bmcr & BMCR_SPEED100)
1709 + phydev->speed = SPEED_100;
1710 + else
1711 + phydev->speed = SPEED_100;
1712 + }
1713 + }
1714 + }
1715 +
1716 + return ret;
1717 +}
1718 +
1719 +#if AIR_UBOOT_REVISION > 0x202303
1720 +U_BOOT_PHY_DRIVER(en8811h) = {
1721 + .name = "Airoha EN8811H",
1722 + .uid = EN8811H_PHY_ID,
1723 + .mask = 0x0ffffff0,
1724 + .config = &en8811h_config,
1725 + .startup = &en8811h_startup,
1726 + .shutdown = &genphy_shutdown,
1727 +};
1728 +#else
1729 +static struct phy_driver AIR_EN8811H_driver = {
1730 + .name = "Airoha EN8811H",
1731 + .uid = EN8811H_PHY_ID,
1732 + .mask = 0x0ffffff0,
1733 + .config = &en8811h_config,
1734 + .startup = &en8811h_startup,
1735 + .shutdown = &genphy_shutdown,
1736 +};
1737 +
1738 +int phy_air_en8811h_init(void)
1739 +{
1740 + phy_register(&AIR_EN8811H_driver);
1741 + return 0;
1742 +}
1743 +#endif
1744 --- /dev/null
1745 +++ b/drivers/net/phy/air_en8811h.h
1746 @@ -0,0 +1,163 @@
1747 +/* SPDX-License-Identifier: GPL-2.0 */
1748 +/*************************************************
1749 + * FILE NAME: air_en8811h.h
1750 + * PURPOSE:
1751 + * EN8811H PHY Driver for Uboot
1752 + * NOTES:
1753 + *
1754 + * Copyright (C) 2023 Airoha Technology Corp.
1755 + *************************************************/
1756 +
1757 +#ifndef __EN8811H_H
1758 +#define __EN8811H_H
1759 +
1760 +#define AIR_UBOOT_REVISION ((((U_BOOT_VERSION_NUM / 1000) % 10) << 20) | \
1761 + (((U_BOOT_VERSION_NUM / 100) % 10) << 16) | \
1762 + (((U_BOOT_VERSION_NUM / 10) % 10) << 12) | \
1763 + ((U_BOOT_VERSION_NUM % 10) << 8) | \
1764 + (((U_BOOT_VERSION_NUM_PATCH / 10) % 10) << 4) | \
1765 + ((U_BOOT_VERSION_NUM_PATCH % 10) << 0))
1766 +
1767 +#define EN8811H_PHY_ID1 0x03a2
1768 +#define EN8811H_PHY_ID2 0xa411
1769 +#define EN8811H_PHY_ID ((EN8811H_PHY_ID1 << 16) | EN8811H_PHY_ID2)
1770 +#define EN8811H_SPEED_2500 0x03
1771 +#define EN8811H_PHY_READY 0x02
1772 +#define MAX_RETRY 5
1773 +
1774 +#define EN8811H_MD32_DM_SIZE 0x4000
1775 +#define EN8811H_MD32_DSP_SIZE 0x20000
1776 +
1777 +#define EN8811H_TX_POLARITY_NORMAL 0x1
1778 +#define EN8811H_TX_POLARITY_REVERSE 0x0
1779 +
1780 +#define EN8811H_RX_POLARITY_NORMAL (0x0 << 1)
1781 +#define EN8811H_RX_POLARITY_REVERSE (0x1 << 1)
1782 +
1783 +#ifndef BIT
1784 +#define BIT(nr) (1UL << (nr))
1785 +#endif
1786 +
1787 +/* CL45 MDIO control */
1788 +#define MII_MMD_ACC_CTL_REG 0x0d
1789 +#define MII_MMD_ADDR_DATA_REG 0x0e
1790 +#define MMD_OP_MODE_DATA BIT(14)
1791 +/* MultiGBASE-T AN register */
1792 +#define MULTIG_ANAR_2500M (0x0080)
1793 +#define MULTIG_LPAR_2500M (0x0020)
1794 +
1795 +#define EN8811H_DRIVER_VERSION "v1.0.4"
1796 +
1797 +/************************************************************
1798 + * For reference only
1799 + * LED0 Link 2500/Blink 2500 TxRx (GPIO5) <-> BASE_T_LED0,
1800 + * LED1 Link 1000/Blink 1000 TxRx (GPIO4) <-> BASE_T_LED1,
1801 + * LED2 Link 100/Blink 100 TxRx (GPIO3) <-> BASE_T_LED2,
1802 + ************************************************************/
1803 +/* User-defined.B */
1804 +#define AIR_LED0_ON (LED_ON_EVT_LINK_2500M)
1805 +#define AIR_LED0_BLK (LED_BLK_EVT_2500M_TX_ACT | LED_BLK_EVT_2500M_RX_ACT)
1806 +#define AIR_LED1_ON (LED_ON_EVT_LINK_1000M)
1807 +#define AIR_LED1_BLK (LED_BLK_EVT_1000M_TX_ACT | LED_BLK_EVT_1000M_RX_ACT)
1808 +#define AIR_LED2_ON (LED_ON_EVT_LINK_100M)
1809 +#define AIR_LED2_BLK (LED_BLK_EVT_100M_TX_ACT | LED_BLK_EVT_100M_RX_ACT)
1810 +/* User-defined.E */
1811 +
1812 +#define LED_ON_CTRL(i) (0x024 + ((i)*2))
1813 +#define LED_ON_EN (1 << 15)
1814 +#define LED_ON_POL (1 << 14)
1815 +#define LED_ON_EVT_MASK (0x1ff)
1816 +/* LED ON Event Option.B */
1817 +#define LED_ON_EVT_LINK_2500M (1 << 8)
1818 +#define LED_ON_EVT_FORCE (1 << 6)
1819 +#define LED_ON_EVT_HDX (1 << 5)
1820 +#define LED_ON_EVT_FDX (1 << 4)
1821 +#define LED_ON_EVT_LINK_DOWN (1 << 3)
1822 +#define LED_ON_EVT_LINK_100M (1 << 1)
1823 +#define LED_ON_EVT_LINK_1000M (1 << 0)
1824 +/* LED ON Event Option.E */
1825 +
1826 +#define LED_BLK_CTRL(i) (0x025 + ((i)*2))
1827 +#define LED_BLK_EVT_MASK (0xfff)
1828 +/* LED Blinking Event Option.B*/
1829 +#define LED_BLK_EVT_2500M_RX_ACT (1 << 11)
1830 +#define LED_BLK_EVT_2500M_TX_ACT (1 << 10)
1831 +#define LED_BLK_EVT_FORCE (1 << 9)
1832 +#define LED_BLK_EVT_100M_RX_ACT (1 << 3)
1833 +#define LED_BLK_EVT_100M_TX_ACT (1 << 2)
1834 +#define LED_BLK_EVT_1000M_RX_ACT (1 << 1)
1835 +#define LED_BLK_EVT_1000M_TX_ACT (1 << 0)
1836 +/* LED Blinking Event Option.E*/
1837 +#define LED_ENABLE 1
1838 +#define LED_DISABLE 0
1839 +
1840 +#define EN8811H_LED_COUNT 3
1841 +
1842 +#define LED_BCR (0x021)
1843 +#define LED_BCR_EXT_CTRL (1 << 15)
1844 +#define LED_BCR_CLK_EN (1 << 3)
1845 +#define LED_BCR_TIME_TEST (1 << 2)
1846 +#define LED_BCR_MODE_MASK (3)
1847 +#define LED_BCR_MODE_DISABLE (0)
1848 +#define LED_BCR_MODE_2LED (1)
1849 +#define LED_BCR_MODE_3LED_1 (2)
1850 +#define LED_BCR_MODE_3LED_2 (3)
1851 +
1852 +#define LED_ON_DUR (0x022)
1853 +#define LED_ON_DUR_MASK (0xffff)
1854 +
1855 +#define LED_BLK_DUR (0x023)
1856 +#define LED_BLK_DUR_MASK (0xffff)
1857 +
1858 +#define LED_GPIO_SEL_MASK 0x7FFFFFF
1859 +
1860 +#define UNIT_LED_BLINK_DURATION 1024
1861 +
1862 +#define INVALID_DATA 0xffff
1863 +#define PBUS_INVALID_DATA 0xffffffff
1864 +
1865 +struct air_base_t_led_cfg_s {
1866 + u16 en;
1867 + u16 gpio;
1868 + u16 pol;
1869 + u16 on_cfg;
1870 + u16 blk_cfg;
1871 +};
1872 +
1873 +enum {
1874 + AIR_LED2_GPIO3 = 3,
1875 + AIR_LED1_GPIO4,
1876 + AIR_LED0_GPIO5,
1877 + AIR_LED_LAST
1878 +};
1879 +
1880 +enum {
1881 + AIR_BASE_T_LED0,
1882 + AIR_BASE_T_LED1,
1883 + AIR_BASE_T_LED2,
1884 + AIR_BASE_T_LED3
1885 +};
1886 +
1887 +enum {
1888 + AIR_LED_BLK_DUR_32M,
1889 + AIR_LED_BLK_DUR_64M,
1890 + AIR_LED_BLK_DUR_128M,
1891 + AIR_LED_BLK_DUR_256M,
1892 + AIR_LED_BLK_DUR_512M,
1893 + AIR_LED_BLK_DUR_1024M,
1894 + AIR_LED_BLK_DUR_LAST
1895 +};
1896 +
1897 +enum {
1898 + AIR_ACTIVE_LOW,
1899 + AIR_ACTIVE_HIGH,
1900 +};
1901 +
1902 +enum {
1903 + AIR_LED_MODE_DISABLE,
1904 + AIR_LED_MODE_USER_DEFINE,
1905 + AIR_LED_MODE_LAST
1906 +};
1907 +
1908 +#endif /* End of __EN8811H_MD32_H */
1909 +
1910 --- a/drivers/net/eth-phy-uclass.c
1911 +++ b/drivers/net/eth-phy-uclass.c
1912 @@ -155,7 +155,7 @@ static int eth_phy_of_to_plat(struct ude
1913 return 0;
1914 }
1915
1916 -static void eth_phy_reset(struct udevice *dev, int value)
1917 +void eth_phy_reset(struct udevice *dev, int value)
1918 {
1919 struct eth_phy_device_priv *uc_priv = dev_get_uclass_priv(dev);
1920 u32 delay;
1921 --- a/include/eth_phy.h
1922 +++ b/include/eth_phy.h
1923 @@ -14,5 +14,6 @@ int eth_phy_binds_nodes(struct udevice *
1924 int eth_phy_set_mdio_bus(struct udevice *eth_dev, struct mii_dev *mdio_bus);
1925 struct mii_dev *eth_phy_get_mdio_bus(struct udevice *eth_dev);
1926 int eth_phy_get_addr(struct udevice *dev);
1927 +void eth_phy_reset(struct udevice *dev, int value);
1928
1929 #endif