160-net-phy-add-support-for-Airoha-ethernet-PHY-driver.patch 63 KB

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