blob: 5e3c619a1915b62203e06f2baa4b44dc2e656496 [file] [log] [blame]
developer5d148cb2023-06-02 13:08:11 +08001From b5aa08e6dd4e06ffd3fb4de2ffc6af1e3da0bce4 Mon Sep 17 00:00:00 2001
2From: Sam Shih <sam.shih@mediatek.com>
3Date: Fri, 2 Jun 2023 13:06:00 +0800
4Subject: [PATCH]
5 [backport-networking-drivers][999-1703-en8811h-2p5gphy-support.patch]
6
7---
8 drivers/net/phy/Kconfig | 5 +
9 drivers/net/phy/Makefile | 1 +
10 drivers/net/phy/air_en8811h.c | 702 ++++++++++++++++++++++++++++++++++
11 drivers/net/phy/air_en8811h.h | 151 ++++++++
12 4 files changed, 859 insertions(+)
13 create mode 100644 drivers/net/phy/air_en8811h.c
14 create mode 100644 drivers/net/phy/air_en8811h.h
15
developera29111c2023-01-12 10:20:04 +080016diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
developer5d148cb2023-06-02 13:08:11 +080017index 170dd00cd..5eeccfee2 100644
developera29111c2023-01-12 10:20:04 +080018--- a/drivers/net/phy/Kconfig
19+++ b/drivers/net/phy/Kconfig
developer5d148cb2023-06-02 13:08:11 +080020@@ -345,6 +345,11 @@ config SFP
21 depends on HWMON || HWMON=n
22 select MDIO_I2C
developera29111c2023-01-12 10:20:04 +080023
24+config AIROHA_EN8811H_PHY
25+ tristate "Drivers for Airoha EN8811H 2.5G Gigabit PHY"
26+ ---help---
27+ Currently supports the Airoha EN8811H PHY.
28+
29 config ADIN_PHY
30 tristate "Analog Devices Industrial Ethernet PHYs"
31 help
32diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
developer5d148cb2023-06-02 13:08:11 +080033index 2368c1d19..8ea612a85 100644
developera29111c2023-01-12 10:20:04 +080034--- a/drivers/net/phy/Makefile
35+++ b/drivers/net/phy/Makefile
developer5d148cb2023-06-02 13:08:11 +080036@@ -67,6 +67,7 @@ aquantia-objs += aquantia_main.o
developera29111c2023-01-12 10:20:04 +080037 ifdef CONFIG_HWMON
38 aquantia-objs += aquantia_hwmon.o
39 endif
40+obj-$(CONFIG_AIROHA_EN8811H_PHY) += air_en8811h.o
41 obj-$(CONFIG_AQUANTIA_PHY) += aquantia.o
42 obj-$(CONFIG_AX88796B_PHY) += ax88796b.o
43 obj-$(CONFIG_AT803X_PHY) += at803x.o
44diff --git a/drivers/net/phy/air_en8811h.c b/drivers/net/phy/air_en8811h.c
45new file mode 100644
developer5d148cb2023-06-02 13:08:11 +080046index 000000000..cf564fc04
developera29111c2023-01-12 10:20:04 +080047--- /dev/null
48+++ b/drivers/net/phy/air_en8811h.c
49@@ -0,0 +1,702 @@
50+// SPDX-License-Identifier: GPL-2.0+
51+
52+/* FILE NAME: air_en8811h.c
53+ * PURPOSE:
54+ * EN8811H phy driver for Linux
55+ * NOTES:
56+ *
57+ */
58+
59+/* INCLUDE FILE DECLARATIONS
60+ */
61+#include <linux/kernel.h>
62+#include <linux/errno.h>
63+#include <linux/init.h>
64+#include <linux/module.h>
65+#include <linux/mii.h>
66+#include <linux/phy.h>
67+#include <linux/delay.h>
68+#include <linux/ethtool.h>
69+#include <linux/delay.h>
70+#include <linux/version.h>
71+#include <linux/firmware.h>
72+#include <linux/crc32.h>
73+
74+#include "air_en8811h.h"
75+
76+#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 5, 0))
77+#define phydev_mdio_bus(_dev) (_dev->bus)
78+#define phydev_addr(_dev) (_dev->addr)
79+#define phydev_dev(_dev) (&_dev->dev)
80+#else
81+#define phydev_mdio_bus(_dev) (_dev->mdio.bus)
82+#define phydev_addr(_dev) (_dev->mdio.addr)
83+#define phydev_dev(_dev) (&_dev->mdio.dev)
84+#endif
85+
86+MODULE_DESCRIPTION("Airoha EN8811H PHY drivers");
87+MODULE_AUTHOR("Airoha");
88+MODULE_LICENSE("GPL");
89+
90+/*
91+GPIO5 <-> BASE_T_LED0,
92+GPIO4 <-> BASE_T_LED1,
93+GPIO3 <-> BASE_T_LED2,
94+*/
95+/* User-defined.B */
96+#define AIR_LED_SUPPORT
97+#ifdef AIR_LED_SUPPORT
98+static const AIR_BASE_T_LED_CFG_T led_cfg[3] =
99+{
100+ /*
101+ * LED Enable, GPIO, LED Polarity, LED ON, LED Blink
102+ */
103+ {LED_ENABLE, AIR_LED0_GPIO5, AIR_ACTIVE_HIGH, BASE_T_LED0_ON_CFG, BASE_T_LED0_BLK_CFG}, /* BASE-T LED0 */
104+ {LED_ENABLE, AIR_LED1_GPIO4, AIR_ACTIVE_HIGH, BASE_T_LED1_ON_CFG, BASE_T_LED1_BLK_CFG}, /* BASE-T LED1 */
105+ {LED_ENABLE, AIR_LED2_GPIO3, AIR_ACTIVE_HIGH, BASE_T_LED2_ON_CFG, BASE_T_LED2_BLK_CFG}, /* BASE-T LED2 */
106+};
107+static const u16 led_dur = UNIT_LED_BLINK_DURATION << AIR_LED_BLK_DUR_64M;
108+#endif
109+/* User-defined.E */
110+
111+/************************************************************************
112+* F U N C T I O N S
113+************************************************************************/
114+#if 0
115+/* Airoha MII read function */
116+static int air_mii_cl22_read(struct mii_bus *ebus, unsigned int phy_addr,unsigned int phy_register)
117+{
118+ int read_data;
119+ read_data = mdiobus_read(ebus, phy_addr, phy_register);
120+ return read_data;
121+}
122+#endif
123+/* Airoha MII write function */
124+static int air_mii_cl22_write(struct mii_bus *ebus, unsigned int phy_addr, unsigned int phy_register,unsigned int write_data)
125+{
126+ int ret = 0;
127+ ret = mdiobus_write(ebus, phy_addr, phy_register, write_data);
128+ return ret;
129+}
130+
131+static int air_mii_cl45_read(struct phy_device *phydev, int devad, u16 reg)
132+{
133+ int ret = 0;
134+ int data;
135+ struct device *dev = phydev_dev(phydev);
136+ ret = phy_write(phydev, MII_MMD_ACC_CTL_REG, devad);
137+ if (ret < 0) {
138+ dev_err(dev, "phy_write, ret: %d\n", ret);
139+ return INVALID_DATA;
140+ }
141+ ret = phy_write(phydev, MII_MMD_ADDR_DATA_REG, reg);
142+ if (ret < 0) {
143+ dev_err(dev, "phy_write, ret: %d\n", ret);
144+ return INVALID_DATA;
145+ }
146+ ret = phy_write(phydev, MII_MMD_ACC_CTL_REG, MMD_OP_MODE_DATA | devad);
147+ if (ret < 0) {
148+ dev_err(dev, "phy_write, ret: %d\n", ret);
149+ return INVALID_DATA;
150+ }
151+ data = phy_read(phydev, MII_MMD_ADDR_DATA_REG);
152+ return data;
153+}
154+
155+static int air_mii_cl45_write(struct phy_device *phydev, int devad, u16 reg, u16 write_data)
156+{
157+ int ret = 0;
158+ struct device *dev = phydev_dev(phydev);
159+ ret = phy_write(phydev, MII_MMD_ACC_CTL_REG, devad);
160+ if (ret < 0) {
161+ dev_err(dev, "phy_write, ret: %d\n", ret);
162+ return ret;
163+ }
164+ ret = phy_write(phydev, MII_MMD_ADDR_DATA_REG, reg);
165+ if (ret < 0) {
166+ dev_err(dev, "phy_write, ret: %d\n", ret);
167+ return ret;
168+ }
169+ ret = phy_write(phydev, MII_MMD_ACC_CTL_REG, MMD_OP_MODE_DATA | devad);
170+ if (ret < 0) {
171+ dev_err(dev, "phy_write, ret: %d\n", ret);
172+ return ret;
173+ }
174+ ret = phy_write(phydev, MII_MMD_ADDR_DATA_REG, write_data);
175+ if (ret < 0) {
176+ dev_err(dev, "phy_write, ret: %d\n", ret);
177+ return ret;
178+ }
179+ return 0;
180+}
181+/* Use default PBUS_PHY_ID */
182+/* EN8811H PBUS write function */
183+static int air_pbus_reg_write(struct phy_device *phydev, unsigned long pbus_address, unsigned long pbus_data)
184+{
185+ struct mii_bus *mbus = phydev_mdio_bus(phydev);
186+ int addr = phydev_addr(phydev);
187+ int ret = 0;
188+ ret = air_mii_cl22_write(mbus, (addr + 8), 0x1F, (unsigned int)(pbus_address >> 6));
189+ AIR_RTN_ERR(ret);
190+ ret = air_mii_cl22_write(mbus, (addr + 8), (unsigned int)((pbus_address >> 2) & 0xf), (unsigned int)(pbus_data & 0xFFFF));
191+ AIR_RTN_ERR(ret);
192+ ret = air_mii_cl22_write(mbus, (addr + 8), 0x10, (unsigned int)(pbus_data >> 16));
193+ AIR_RTN_ERR(ret);
194+ return 0;
195+}
196+
197+/* EN8811H BUCK write function */
198+static int air_buckpbus_reg_write(struct phy_device *phydev, unsigned long pbus_address, unsigned int pbus_data)
199+{
200+ int ret = 0;
201+ struct device *dev = phydev_dev(phydev);
202+ ret = phy_write(phydev, 0x1F, (unsigned int)4); /* page 4 */
203+ if (ret < 0) {
204+ dev_err(dev, "phy_write, ret: %d\n", ret);
205+ return ret;
206+ }
207+ ret = phy_write(phydev, 0x10, (unsigned int)0);
208+ if (ret < 0) {
209+ dev_err(dev, "phy_write, ret: %d\n", ret);
210+ return ret;
211+ }
212+ ret = phy_write(phydev, 0x11, (unsigned int)((pbus_address >> 16) & 0xffff));
213+ if (ret < 0) {
214+ dev_err(dev, "phy_write, ret: %d\n", ret);
215+ return ret;
216+ }
217+ ret = phy_write(phydev, 0x12, (unsigned int)(pbus_address & 0xffff));
218+ if (ret < 0) {
219+ dev_err(dev, "phy_write, ret: %d\n", ret);
220+ return ret;
221+ }
222+ ret = phy_write(phydev, 0x13, (unsigned int)((pbus_data >> 16) & 0xffff));
223+ if (ret < 0) {
224+ dev_err(dev, "phy_write, ret: %d\n", ret);
225+ return ret;
226+ }
227+ ret = phy_write(phydev, 0x14, (unsigned int)(pbus_data & 0xffff));
228+ if (ret < 0) {
229+ dev_err(dev, "phy_write, ret: %d\n", ret);
230+ return ret;
231+ }
232+ ret = phy_write(phydev, 0x1F, 0);
233+ if (ret < 0) {
234+ dev_err(dev, "phy_write, ret: %d\n", ret);
235+ return ret;
236+ }
237+ return 0;
238+}
239+
240+/* EN8811H BUCK read function */
241+static unsigned int air_buckpbus_reg_read(struct phy_device *phydev, unsigned long pbus_address)
242+{
243+ unsigned int pbus_data = 0, pbus_data_low, pbus_data_high;
244+ int ret = 0;
245+ struct device *dev = phydev_dev(phydev);
246+ ret = phy_write(phydev, 0x1F, (unsigned int)4); /* page 4 */
247+ if (ret < 0) {
248+ dev_err(dev, "phy_write, ret: %d\n", ret);
249+ return PBUS_INVALID_DATA;
250+ }
251+ ret = phy_write(phydev, 0x10, (unsigned int)0);
252+ if (ret < 0) {
253+ dev_err(dev, "phy_write, ret: %d\n", ret);
254+ return PBUS_INVALID_DATA;
255+ }
256+ ret = phy_write(phydev, 0x15, (unsigned int)((pbus_address >> 16) & 0xffff));
257+ if (ret < 0) {
258+ dev_err(dev, "phy_write, ret: %d\n", ret);
259+ return PBUS_INVALID_DATA;
260+ }
261+ ret = phy_write(phydev, 0x16, (unsigned int)(pbus_address & 0xffff));
262+ if (ret < 0) {
263+ dev_err(dev, "phy_write, ret: %d\n", ret);
264+ return PBUS_INVALID_DATA;
265+ }
266+
267+ pbus_data_high = phy_read(phydev, 0x17);
268+ pbus_data_low = phy_read(phydev, 0x18);
269+ pbus_data = (pbus_data_high << 16) + pbus_data_low;
270+ ret = phy_write(phydev, 0x1F, 0);
271+ if (ret < 0) {
272+ dev_err(dev, "phy_write, ret: %d\n", ret);
273+ return ret;
274+ }
275+ return pbus_data;
276+}
277+
278+static int MDIOWriteBuf(struct phy_device *phydev, unsigned long address, const struct firmware *fw)
279+{
280+ unsigned int write_data, offset ;
281+ int ret = 0;
282+ struct device *dev = phydev_dev(phydev);
283+ ret = phy_write(phydev, 0x1F, (unsigned int)4); /* page 4 */
284+ if (ret < 0) {
285+ dev_err(dev, "phy_write, ret: %d\n", ret);
286+ return ret;
287+ }
288+ ret = phy_write(phydev, 0x10, (unsigned int)0x8000); /* address increment*/
289+ if (ret < 0) {
290+ dev_err(dev, "phy_write, ret: %d\n", ret);
291+ return ret;
292+ }
293+ ret = phy_write(phydev, 0x11, (unsigned int)((address >> 16) & 0xffff));
294+ if (ret < 0) {
295+ dev_err(dev, "phy_write, ret: %d\n", ret);
296+ return ret;
297+ }
298+ ret = phy_write(phydev, 0x12, (unsigned int)(address & 0xffff));
299+ if (ret < 0) {
300+ dev_err(dev, "phy_write, ret: %d\n", ret);
301+ return ret;
302+ }
303+
304+ for (offset = 0; offset < fw->size; offset += 4)
305+ {
306+ write_data = (fw->data[offset + 3] << 8) | fw->data[offset + 2];
307+ ret = phy_write(phydev, 0x13, write_data);
308+ if (ret < 0) {
309+ dev_err(dev, "phy_write, ret: %d\n", ret);
310+ return ret;
311+ }
312+ write_data = (fw->data[offset + 1] << 8) | fw->data[offset];
313+ ret = phy_write(phydev, 0x14, write_data);
314+ if (ret < 0) {
315+ dev_err(dev, "phy_write, ret: %d\n", ret);
316+ return ret;
317+ }
318+ }
319+ ret = phy_write(phydev, 0x1F, (unsigned int)0);
320+ if (ret < 0) {
321+ dev_err(dev, "phy_write, ret: %d\n", ret);
322+ return ret;
323+ }
324+ return 0;
325+}
326+
327+static int en8811h_load_firmware(struct phy_device *phydev)
328+{
329+ struct device *dev = phydev_dev(phydev);
330+ const struct firmware *fw;
331+ const char *firmware;
332+ int ret = 0;
333+ unsigned int crc32;
334+ u32 pbus_value = 0;
335+
336+ ret = air_buckpbus_reg_write(phydev, 0x0f0018, 0x0);
337+ AIR_RTN_ERR(ret);
338+ pbus_value = air_buckpbus_reg_read(phydev, 0x800000);
339+ pbus_value |= BIT(11);
340+ ret = air_buckpbus_reg_write(phydev, 0x800000, pbus_value);
341+ AIR_RTN_ERR(ret);
342+ firmware = EN8811H_MD32_DM;
343+ ret = request_firmware_direct(&fw, firmware, dev);
344+ if (ret < 0) {
345+ dev_info(dev, "failed to load firmware %s, ret: %d\n", firmware, ret);
346+ return ret;
347+ }
348+ crc32 = ~crc32(~0, fw->data, fw->size);
349+ dev_info(dev, "%s: crc32=0x%x\n", firmware, crc32);
350+ /* Download DM */
351+ ret = MDIOWriteBuf(phydev, 0x00000000, fw);
352+ if (ret < 0) {
353+ dev_info(dev, "MDIOWriteBuf 0x00000000 fail, ret: %d\n", ret);
354+ return ret;
355+ }
356+ release_firmware(fw);
357+
358+ firmware = EN8811H_MD32_DSP;
359+ ret = request_firmware_direct(&fw, firmware, dev);
360+ if (ret < 0) {
361+ dev_info(dev, "failed to load firmware %s, ret: %d\n", firmware, ret);
362+ return ret;
363+ }
364+ crc32 = ~crc32(~0, fw->data, fw->size);
365+ dev_info(dev, "%s: crc32=0x%x\n", firmware, crc32);
366+ /* Download PM */
367+ ret = MDIOWriteBuf(phydev, 0x00100000, fw);
368+ if (ret < 0) {
369+ dev_info(dev, "MDIOWriteBuf 0x00100000 fail , ret: %d\n", ret);
370+ return ret;
371+ }
372+ release_firmware(fw);
373+
374+ pbus_value = air_buckpbus_reg_read(phydev, 0x800000);
375+ pbus_value &= ~BIT(11);
376+ ret = air_buckpbus_reg_write(phydev, 0x800000, pbus_value);
377+ AIR_RTN_ERR(ret);
378+ ret = air_buckpbus_reg_write(phydev, 0x0f0018, 0x01);
379+ AIR_RTN_ERR(ret);
380+ return 0;
381+}
382+
383+#ifdef AIR_LED_SUPPORT
384+static int airoha_led_set_usr_def(struct phy_device *phydev, u8 entity, int polar,
385+ u16 on_evt, u16 blk_evt)
386+{
387+ int ret = 0;
388+ if (AIR_ACTIVE_HIGH == polar) {
389+ on_evt |= LED_ON_POL;
390+ } else {
391+ on_evt &= ~LED_ON_POL ;
392+ }
393+ ret = air_mii_cl45_write(phydev, 0x1f, LED_ON_CTRL(entity), on_evt | LED_ON_EN);
394+ AIR_RTN_ERR(ret);
395+ ret = air_mii_cl45_write(phydev, 0x1f, LED_BLK_CTRL(entity), blk_evt);
396+ AIR_RTN_ERR(ret);
397+ return 0;
398+}
399+
400+static int airoha_led_set_mode(struct phy_device *phydev, u8 mode)
401+{
402+ u16 cl45_data;
403+ int err = 0;
404+ struct device *dev = phydev_dev(phydev);
405+ cl45_data = air_mii_cl45_read(phydev, 0x1f, LED_BCR);
406+ switch (mode) {
407+ case AIR_LED_MODE_DISABLE:
408+ cl45_data &= ~LED_BCR_EXT_CTRL;
409+ cl45_data &= ~LED_BCR_MODE_MASK;
410+ cl45_data |= LED_BCR_MODE_DISABLE;
411+ break;
412+ case AIR_LED_MODE_USER_DEFINE:
413+ cl45_data |= LED_BCR_EXT_CTRL;
414+ cl45_data |= LED_BCR_CLK_EN;
415+ break;
416+ default:
417+ dev_err(dev, "LED mode%d is not supported!\n", mode);
418+ return -EINVAL;
419+ }
420+ err = air_mii_cl45_write(phydev, 0x1f, LED_BCR, cl45_data);
421+ AIR_RTN_ERR(err);
422+ return 0;
423+}
424+
425+static int airoha_led_set_state(struct phy_device *phydev, u8 entity, u8 state)
426+{
427+ u16 cl45_data = 0;
428+ int err;
429+
430+ cl45_data = air_mii_cl45_read(phydev, 0x1f, LED_ON_CTRL(entity));
431+ if (LED_ENABLE == state) {
432+ cl45_data |= LED_ON_EN;
433+ } else {
434+ cl45_data &= ~LED_ON_EN;
435+ }
436+
437+ err = air_mii_cl45_write(phydev, 0x1f, LED_ON_CTRL(entity), cl45_data);
438+ AIR_RTN_ERR(err);
439+ return 0;
440+}
441+
442+static int en8811h_led_init(struct phy_device *phydev)
443+{
444+
445+ unsigned long led_gpio = 0, reg_value = 0;
446+ u16 cl45_data = led_dur;
447+ int ret = 0, led_id;
448+ struct device *dev = phydev_dev(phydev);
449+ ret = air_mii_cl45_write(phydev, 0x1f, LED_BLK_DUR, cl45_data);
450+ AIR_RTN_ERR(ret);
451+ cl45_data >>= 1;
452+ ret = air_mii_cl45_write(phydev, 0x1f, LED_ON_DUR, cl45_data);
453+ AIR_RTN_ERR(ret);
454+ ret = airoha_led_set_mode(phydev, AIR_LED_MODE_USER_DEFINE);
455+ if (ret != 0) {
456+ dev_err(dev, "LED fail to set mode, ret %d !\n", ret);
457+ return ret;
458+ }
459+ for(led_id = 0; led_id < EN8811H_LED_COUNT; led_id++)
460+ {
461+ /* LED0 <-> GPIO5, LED1 <-> GPIO4, LED0 <-> GPIO3 */
462+ if (led_cfg[led_id].gpio != (led_id + (AIR_LED0_GPIO5 - (2 * led_id))))
463+ {
464+ dev_err(dev, "LED%d uses incorrect GPIO%d !\n", led_id, led_cfg[led_id].gpio);
465+ return -EINVAL;
466+ }
467+ ret = airoha_led_set_state(phydev, led_id, led_cfg[led_id].en);
468+ if (ret != 0)
469+ {
470+ dev_err(dev, "LED fail to set state, ret %d !\n", ret);
471+ return ret;
472+ }
473+ if (LED_ENABLE == led_cfg[led_id].en)
474+ {
475+ led_gpio |= BIT(led_cfg[led_id].gpio);
476+ 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);
477+ if (ret != 0)
478+ {
479+ dev_err(dev, "LED fail to set default, ret %d !\n", ret);
480+ return ret;
481+ }
482+ }
483+ }
484+ reg_value = air_buckpbus_reg_read(phydev, 0xcf8b8) | led_gpio;
485+ ret = air_buckpbus_reg_write(phydev, 0xcf8b8, reg_value);
486+ AIR_RTN_ERR(ret);
487+
488+ dev_info(dev, "LED initialize OK !\n");
489+ return 0;
490+}
491+#endif /* AIR_LED_SUPPORT */
492+#if (LINUX_VERSION_CODE > KERNEL_VERSION(4, 5, 0))
493+static int en8811h_get_features(struct phy_device *phydev)
494+{
495+ int ret;
496+ struct device *dev = phydev_dev(phydev);
497+ dev_info(dev, "%s()\n", __func__);
498+ ret = air_pbus_reg_write(phydev, 0xcf928 , 0x0);
499+ AIR_RTN_ERR(ret);
500+ ret = genphy_read_abilities(phydev);
501+ if (ret)
502+ return ret;
503+
504+ /* EN8811H supports 100M/1G/2.5G speed. */
505+ linkmode_clear_bit(ETHTOOL_LINK_MODE_10baseT_Half_BIT,
506+ phydev->supported);
507+ linkmode_clear_bit(ETHTOOL_LINK_MODE_10baseT_Full_BIT,
508+ phydev->supported);
509+ linkmode_set_bit(ETHTOOL_LINK_MODE_100baseT_Half_BIT,
510+ phydev->supported);
511+ linkmode_set_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT,
512+ phydev->supported);
513+ linkmode_set_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT,
514+ phydev->supported);
515+ linkmode_set_bit(ETHTOOL_LINK_MODE_2500baseX_Full_BIT,
516+ phydev->supported);
517+ return 0;
518+}
519+#endif
520+static int en8811h_phy_probe(struct phy_device *phydev)
521+{
522+ int ret = 0;
523+ int reg_value, pid1 = 0, pid2 = 0;
524+ u32 pbus_value = 0, retry;
525+ struct device *dev = phydev_dev(phydev);
526+ ret = air_pbus_reg_write(phydev, 0xcf928 , 0x0);
527+ AIR_RTN_ERR(ret);
528+ pid1 = phy_read(phydev, MII_PHYSID1);
529+ if (pid1 < 0)
530+ return pid1;
531+ pid2 = phy_read(phydev, MII_PHYSID2);
532+ if (pid2 < 0)
533+ return pid2;
534+ dev_info(dev, "PHY = %x - %x\n", pid1, pid2);
535+ if ((EN8811H_PHY_ID1 != pid1) || (EN8811H_PHY_ID2 != pid2))
536+ {
537+ dev_err(dev, "EN8811H dose not exist !\n");
538+ return -ENODEV;
539+ }
540+ ret = en8811h_load_firmware(phydev);
541+ if (ret)
542+ {
543+ dev_err(dev,"EN8811H load firmware fail.\n");
544+ return ret;
545+ }
546+ retry = MAX_RETRY;
547+ do {
548+ mdelay(300);
549+ reg_value = air_mii_cl45_read(phydev, 0x1e, 0x8009);
550+ if (EN8811H_PHY_READY == reg_value)
551+ {
552+ dev_info(dev, "EN8811H PHY ready!\n");
553+ break;
554+ }
555+ retry--;
556+ } while (retry);
557+ if (0 == retry)
558+ {
559+ dev_err(dev, "EN8811H initialize fail ! reg: 0x%x\n", reg_value);
560+ return -EIO;
561+ }
562+ /* Mode selection*/
563+ dev_info(dev, "EN8811H Mode 1 !\n");
564+ ret = air_mii_cl45_write(phydev, 0x1e, 0x800c, 0x0);
565+ AIR_RTN_ERR(ret);
566+ ret = air_mii_cl45_write(phydev, 0x1e, 0x800d, 0x0);
567+ AIR_RTN_ERR(ret);
568+ ret = air_mii_cl45_write(phydev, 0x1e, 0x800e, 0x1101);
569+ AIR_RTN_ERR(ret);
570+ ret = air_mii_cl45_write(phydev, 0x1e, 0x800f, 0x0002);
571+ AIR_RTN_ERR(ret);
572+
573+ /* Serdes polarity */
574+ pbus_value = air_buckpbus_reg_read(phydev, 0xca0f8);
575+ pbus_value = (pbus_value & 0xfffffffc) | EN8811H_RX_POLARITY_NORMAL | EN8811H_TX_POLARITY_NORMAL;
576+ ret = air_buckpbus_reg_write(phydev, 0xca0f8, pbus_value);
577+ AIR_RTN_ERR(ret);
578+ pbus_value = air_buckpbus_reg_read(phydev, 0xca0f8);
579+ dev_info(dev, "0xca0f8= 0x%x\n", pbus_value);
580+ pbus_value = air_buckpbus_reg_read(phydev, 0x3b3c);
581+ dev_info(dev, "Version(0x3b3c)= %x\n", pbus_value);
582+#if defined(AIR_LED_SUPPORT)
583+ ret = en8811h_led_init(phydev);
584+ if (ret < 0)
585+ {
586+ dev_err(dev, "en8811h_led_init fail. (ret=%d)\n", ret);
587+ return ret;
588+ }
589+#endif
590+ dev_info(dev, "EN8811H initialize OK ! (%s)\n", EN8811H_FW_VERSION);
591+ return 0;
592+}
593+
594+static int en8811h_get_autonego(struct phy_device *phydev, int *an)
595+{
596+ int reg;
597+ reg = phy_read(phydev, MII_BMCR);
598+ if (reg < 0)
599+ return -EINVAL;
600+ if (reg & BMCR_ANENABLE)
601+ *an = AUTONEG_ENABLE;
602+ else
603+ *an = AUTONEG_DISABLE;
604+ return 0;
605+}
606+
607+static int en8811h_read_status(struct phy_device *phydev)
608+{
609+ 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;
610+ int old_link = phydev->link;
611+ u32 pbus_value = 0;
612+ struct device *dev = phydev_dev(phydev);
613+ ret = genphy_update_link(phydev);
614+ if (ret)
615+ {
616+ dev_err(dev, "ret %d!\n", ret);
617+ return ret;
618+ }
619+
620+ if (old_link && phydev->link)
621+ return 0;
622+
623+ phydev->speed = SPEED_UNKNOWN;
624+ phydev->duplex = DUPLEX_UNKNOWN;
625+ phydev->pause = 0;
626+ phydev->asym_pause = 0;
627+
628+ reg = phy_read(phydev, MII_BMSR);
629+ if (reg < 0)
630+ {
631+ dev_err(dev, "MII_BMSR reg %d!\n", reg);
632+ return reg;
633+ }
634+ reg = phy_read(phydev, MII_BMSR);
635+ if (reg < 0)
636+ {
637+ dev_err(dev, "MII_BMSR reg %d!\n", reg);
638+ return reg;
639+ }
640+ if(reg & BMSR_LSTATUS)
641+ {
642+ pbus_value = air_buckpbus_reg_read(phydev, 0x109D4);
643+ if (0x10 & pbus_value) {
644+ phydev->speed = SPEED_2500;
645+ phydev->duplex = DUPLEX_FULL;
646+ }
647+ else
648+ {
649+ ret = en8811h_get_autonego(phydev, &an);
650+ if ((AUTONEG_ENABLE == an) && (0 == ret))
651+ {
652+ dev_dbg(dev, "AN mode!\n");
653+ dev_dbg(dev, "SPEED 1000/100!\n");
654+ lpagb = phy_read(phydev, MII_STAT1000);
655+ if (lpagb < 0 )
656+ return lpagb;
657+ advgb = phy_read(phydev, MII_CTRL1000);
658+ if (adv < 0 )
659+ return adv;
660+ common_adv_gb = (lpagb & (advgb << 2));
661+
662+ lpa = phy_read(phydev, MII_LPA);
663+ if (lpa < 0 )
664+ return lpa;
665+ adv = phy_read(phydev, MII_ADVERTISE);
666+ if (adv < 0 )
667+ return adv;
668+ common_adv = (lpa & adv);
669+
670+ phydev->speed = SPEED_10;
671+ phydev->duplex = DUPLEX_HALF;
672+ if (common_adv_gb & (LPA_1000FULL | LPA_1000HALF))
673+ {
674+ phydev->speed = SPEED_1000;
675+ if (common_adv_gb & LPA_1000FULL)
676+
677+ phydev->duplex = DUPLEX_FULL;
678+ }
679+ else if (common_adv & (LPA_100FULL | LPA_100HALF))
680+ {
681+ phydev->speed = SPEED_100;
682+ if (common_adv & LPA_100FULL)
683+ phydev->duplex = DUPLEX_FULL;
684+ }
685+ else
686+ {
687+ if (common_adv & LPA_10FULL)
688+ phydev->duplex = DUPLEX_FULL;
689+ }
690+ }
691+ else
692+ {
693+ dev_dbg(dev, "Force mode!\n");
694+ bmcr = phy_read(phydev, MII_BMCR);
695+
696+ if (bmcr < 0)
697+ return bmcr;
698+
699+ if (bmcr & BMCR_FULLDPLX)
700+ phydev->duplex = DUPLEX_FULL;
701+ else
702+ phydev->duplex = DUPLEX_HALF;
703+
704+ if (bmcr & BMCR_SPEED1000)
705+ phydev->speed = SPEED_1000;
706+ else if (bmcr & BMCR_SPEED100)
707+ phydev->speed = SPEED_100;
708+ else
709+ phydev->speed = SPEED_UNKNOWN;
710+ }
711+ }
712+ }
713+
714+ return ret;
715+}
716+static struct phy_driver en8811h_driver[] = {
717+{
718+ .phy_id = EN8811H_PHY_ID,
719+ .name = "Airoha EN8811H",
720+ .phy_id_mask = 0x0ffffff0,
721+ .probe = en8811h_phy_probe,
722+ .read_status = en8811h_read_status,
723+#if (LINUX_VERSION_CODE > KERNEL_VERSION(4, 5, 0))
724+ .get_features = en8811h_get_features,
725+ .read_mmd = air_mii_cl45_read,
726+ .write_mmd = air_mii_cl45_write,
727+#endif
728+} };
729+
730+int __init en8811h_phy_driver_register(void)
731+{
732+ int ret;
733+#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 5, 0))
734+ ret = phy_driver_register(en8811h_driver);
735+#else
736+ ret = phy_driver_register(en8811h_driver, THIS_MODULE);
737+#endif
738+ if (!ret)
739+ return 0;
740+
741+ phy_driver_unregister(en8811h_driver);
742+ return ret;
743+}
744+
745+void __exit en8811h_phy_driver_unregister(void)
746+{
747+ phy_driver_unregister(en8811h_driver);
748+}
749+
750+module_init(en8811h_phy_driver_register);
751+module_exit(en8811h_phy_driver_unregister);
752diff --git a/drivers/net/phy/air_en8811h.h b/drivers/net/phy/air_en8811h.h
753new file mode 100644
developer5d148cb2023-06-02 13:08:11 +0800754index 000000000..1c9162795
developera29111c2023-01-12 10:20:04 +0800755--- /dev/null
756+++ b/drivers/net/phy/air_en8811h.h
757@@ -0,0 +1,151 @@
758+#ifndef __EN8811H_H
759+#define __EN8811H_H
760+
761+#define EN8811H_MD32_DM "EthMD32.dm.bin"
762+#define EN8811H_MD32_DSP "EthMD32.DSP.bin"
763+
764+#define EN8811H_PHY_ID1 0x03a2
765+#define EN8811H_PHY_ID2 0xa411
766+#define EN8811H_PHY_ID ((EN8811H_PHY_ID1 << 16) | EN8811H_PHY_ID2)
767+#define EN8811H_PHY_READY 0x02
768+#define MAX_RETRY 5
769+
770+#define EN8811H_TX_POLARITY_NORMAL 0x1
771+#define EN8811H_TX_POLARITY_REVERSE 0x0
772+
773+#define EN8811H_RX_POLARITY_REVERSE (0x1 << 1)
774+#define EN8811H_RX_POLARITY_NORMAL (0x0 << 1)
775+
776+
777+/*
778+The following led_cfg example is for reference only.
779+LED0 Link 2500/Blink 2500 TxRx (GPIO5) <-> BASE_T_LED0,
780+LED1 Link 1000/Blink 1000 TxRx (GPIO4) <-> BASE_T_LED1,
781+LED2 Link 100 /Blink 100 TxRx (GPIO3) <-> BASE_T_LED2,
782+*/
783+/* User-defined.B */
784+#define BASE_T_LED0_ON_CFG (LED_ON_EVT_LINK_2500M)
785+#define BASE_T_LED0_BLK_CFG (LED_BLK_EVT_2500M_TX_ACT | LED_BLK_EVT_2500M_RX_ACT)
786+#define BASE_T_LED1_ON_CFG (LED_ON_EVT_LINK_1000M)
787+#define BASE_T_LED1_BLK_CFG (LED_BLK_EVT_1000M_TX_ACT | LED_BLK_EVT_1000M_RX_ACT)
788+#define BASE_T_LED2_ON_CFG (LED_ON_EVT_LINK_100M)
789+#define BASE_T_LED2_BLK_CFG (LED_BLK_EVT_100M_TX_ACT | LED_BLK_EVT_100M_RX_ACT)
790+/* User-defined.E */
791+
792+/* CL45 MDIO control */
793+#define MII_MMD_ACC_CTL_REG 0x0d
794+#define MII_MMD_ADDR_DATA_REG 0x0e
795+#define MMD_OP_MODE_DATA BIT(14)
796+
797+#define EN8811H_FW_VERSION "1.1.3"
798+
799+#define LED_ON_CTRL(i) (0x024 + ((i)*2))
800+#define LED_ON_EN (1 << 15)
801+#define LED_ON_POL (1 << 14)
802+#define LED_ON_EVT_MASK (0x1ff)
803+/* LED ON Event Option.B */
804+#define LED_ON_EVT_LINK_2500M (1 << 8)
805+#define LED_ON_EVT_FORCE (1 << 6)
806+#define LED_ON_EVT_LINK_DOWN (1 << 3)
807+#define LED_ON_EVT_LINK_100M (1 << 1)
808+#define LED_ON_EVT_LINK_1000M (1 << 0)
809+/* LED ON Event Option.E */
810+
811+#define LED_BLK_CTRL(i) (0x025 + ((i)*2))
812+#define LED_BLK_EVT_MASK (0xfff)
813+/* LED Blinking Event Option.B*/
814+#define LED_BLK_EVT_2500M_RX_ACT (1 << 11)
815+#define LED_BLK_EVT_2500M_TX_ACT (1 << 10)
816+#define LED_BLK_EVT_FORCE (1 << 9)
817+#define LED_BLK_EVT_100M_RX_ACT (1 << 3)
818+#define LED_BLK_EVT_100M_TX_ACT (1 << 2)
819+#define LED_BLK_EVT_1000M_RX_ACT (1 << 1)
820+#define LED_BLK_EVT_1000M_TX_ACT (1 << 0)
821+/* LED Blinking Event Option.E*/
822+#define LED_ENABLE 1
823+#define LED_DISABLE 0
824+
825+#define EN8811H_LED_COUNT 3
826+
827+#define LED_BCR (0x021)
828+#define LED_BCR_EXT_CTRL (1 << 15)
829+#define LED_BCR_CLK_EN (1 << 3)
830+#define LED_BCR_TIME_TEST (1 << 2)
831+#define LED_BCR_MODE_MASK (3)
832+#define LED_BCR_MODE_DISABLE (0)
833+
834+#define LED_ON_DUR (0x022)
835+#define LED_ON_DUR_MASK (0xffff)
836+
837+#define LED_BLK_DUR (0x023)
838+#define LED_BLK_DUR_MASK (0xffff)
839+
840+#define UNIT_LED_BLINK_DURATION 1024
841+
842+#define AIR_RTN_ON_ERR(cond, err) \
843+ do { if ((cond)) return (err); } while(0)
844+
845+#define AIR_RTN_ERR(err) AIR_RTN_ON_ERR(err < 0, err)
846+
847+#define LED_SET_EVT(reg, cod, result, bit) do \
848+ { \
849+ if(reg & cod) { \
850+ result |= bit; \
851+ } \
852+ } while(0)
853+
854+#define LED_SET_GPIO_SEL(gpio, led, val) do \
855+ { \
856+ val |= (led << (8 * (gpio % 4))); \
857+ } while(0)
858+
859+#define INVALID_DATA 0xffff
860+#define PBUS_INVALID_DATA 0xffffffff
861+
862+typedef struct AIR_BASE_T_LED_CFG_S
863+{
864+ u16 en;
865+ u16 gpio;
866+ u16 pol;
867+ u16 on_cfg;
868+ u16 blk_cfg;
869+}AIR_BASE_T_LED_CFG_T;
870+typedef enum
871+{
872+ AIR_LED2_GPIO3 = 3,
873+ AIR_LED1_GPIO4,
874+ AIR_LED0_GPIO5,
875+ AIR_LED_LAST
876+} AIR_LED_GPIO;
877+
878+typedef enum {
879+ AIR_BASE_T_LED0,
880+ AIR_BASE_T_LED1,
881+ AIR_BASE_T_LED2,
882+ AIR_BASE_T_LED3
883+}AIR_BASE_T_LED;
884+
885+typedef enum
886+{
887+ AIR_LED_BLK_DUR_32M,
888+ AIR_LED_BLK_DUR_64M,
889+ AIR_LED_BLK_DUR_128M,
890+ AIR_LED_BLK_DUR_256M,
891+ AIR_LED_BLK_DUR_512M,
892+ AIR_LED_BLK_DUR_1024M,
893+ AIR_LED_BLK_DUR_LAST
894+} AIR_LED_BLK_DUT_T;
895+
896+typedef enum
897+{
898+ AIR_ACTIVE_LOW,
899+ AIR_ACTIVE_HIGH,
900+} AIR_LED_POLARITY;
901+typedef enum
902+{
903+ AIR_LED_MODE_DISABLE,
904+ AIR_LED_MODE_USER_DEFINE,
905+ AIR_LED_MODE_LAST
906+} AIR_LED_MODE_T;
907+
908+#endif /* End of __EN8811H_MD32_H */
developer5d148cb2023-06-02 13:08:11 +0800909--
9102.34.1
911