mscc_main.c 82 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003
  1. // SPDX-License-Identifier: (GPL-2.0 OR MIT)
  2. /*
  3. * Driver for Microsemi VSC85xx PHYs
  4. *
  5. * Author: Nagaraju Lakkaraju
  6. * License: Dual MIT/GPL
  7. * Copyright (c) 2016 Microsemi Corporation
  8. */
  9. #include <linux/firmware.h>
  10. #include <linux/jiffies.h>
  11. #include <linux/kernel.h>
  12. #include <linux/module.h>
  13. #include <linux/mdio.h>
  14. #include <linux/mii.h>
  15. #include <linux/phy.h>
  16. #include <linux/of.h>
  17. #include <linux/netdevice.h>
  18. #include <dt-bindings/net/mscc-phy-vsc8531.h>
  19. #include "../phylib.h"
  20. #include "mscc_serdes.h"
  21. #include "mscc.h"
  22. struct vsc85xx_probe_config {
  23. const struct vsc85xx_hw_stat *hw_stats;
  24. size_t shared_size;
  25. size_t nstats;
  26. u16 supp_led_modes;
  27. u8 nleds;
  28. bool check_rate_magic;
  29. bool use_package;
  30. bool has_ptp;
  31. };
  32. static const u32 vsc85xx_default_led_modes_4[] = {
  33. VSC8531_LINK_1000_ACTIVITY,
  34. VSC8531_LINK_100_ACTIVITY,
  35. VSC8531_LINK_ACTIVITY,
  36. VSC8531_DUPLEX_COLLISION
  37. };
  38. static const struct vsc85xx_hw_stat vsc85xx_hw_stats[] = {
  39. {
  40. .string = "phy_receive_errors",
  41. .reg = MSCC_PHY_ERR_RX_CNT,
  42. .page = MSCC_PHY_PAGE_STANDARD,
  43. .mask = ERR_CNT_MASK,
  44. }, {
  45. .string = "phy_false_carrier",
  46. .reg = MSCC_PHY_ERR_FALSE_CARRIER_CNT,
  47. .page = MSCC_PHY_PAGE_STANDARD,
  48. .mask = ERR_CNT_MASK,
  49. }, {
  50. .string = "phy_cu_media_link_disconnect",
  51. .reg = MSCC_PHY_ERR_LINK_DISCONNECT_CNT,
  52. .page = MSCC_PHY_PAGE_STANDARD,
  53. .mask = ERR_CNT_MASK,
  54. }, {
  55. .string = "phy_cu_media_crc_good_count",
  56. .reg = MSCC_PHY_CU_MEDIA_CRC_VALID_CNT,
  57. .page = MSCC_PHY_PAGE_EXTENDED,
  58. .mask = VALID_CRC_CNT_CRC_MASK,
  59. }, {
  60. .string = "phy_cu_media_crc_error_count",
  61. .reg = MSCC_PHY_EXT_PHY_CNTL_4,
  62. .page = MSCC_PHY_PAGE_EXTENDED,
  63. .mask = ERR_CNT_MASK,
  64. },
  65. };
  66. static const struct vsc85xx_hw_stat vsc8584_hw_stats[] = {
  67. {
  68. .string = "phy_receive_errors",
  69. .reg = MSCC_PHY_ERR_RX_CNT,
  70. .page = MSCC_PHY_PAGE_STANDARD,
  71. .mask = ERR_CNT_MASK,
  72. }, {
  73. .string = "phy_false_carrier",
  74. .reg = MSCC_PHY_ERR_FALSE_CARRIER_CNT,
  75. .page = MSCC_PHY_PAGE_STANDARD,
  76. .mask = ERR_CNT_MASK,
  77. }, {
  78. .string = "phy_cu_media_link_disconnect",
  79. .reg = MSCC_PHY_ERR_LINK_DISCONNECT_CNT,
  80. .page = MSCC_PHY_PAGE_STANDARD,
  81. .mask = ERR_CNT_MASK,
  82. }, {
  83. .string = "phy_cu_media_crc_good_count",
  84. .reg = MSCC_PHY_CU_MEDIA_CRC_VALID_CNT,
  85. .page = MSCC_PHY_PAGE_EXTENDED,
  86. .mask = VALID_CRC_CNT_CRC_MASK,
  87. }, {
  88. .string = "phy_cu_media_crc_error_count",
  89. .reg = MSCC_PHY_EXT_PHY_CNTL_4,
  90. .page = MSCC_PHY_PAGE_EXTENDED,
  91. .mask = ERR_CNT_MASK,
  92. }, {
  93. .string = "phy_serdes_tx_good_pkt_count",
  94. .reg = MSCC_PHY_SERDES_TX_VALID_CNT,
  95. .page = MSCC_PHY_PAGE_EXTENDED_3,
  96. .mask = VALID_CRC_CNT_CRC_MASK,
  97. }, {
  98. .string = "phy_serdes_tx_bad_crc_count",
  99. .reg = MSCC_PHY_SERDES_TX_CRC_ERR_CNT,
  100. .page = MSCC_PHY_PAGE_EXTENDED_3,
  101. .mask = ERR_CNT_MASK,
  102. }, {
  103. .string = "phy_serdes_rx_good_pkt_count",
  104. .reg = MSCC_PHY_SERDES_RX_VALID_CNT,
  105. .page = MSCC_PHY_PAGE_EXTENDED_3,
  106. .mask = VALID_CRC_CNT_CRC_MASK,
  107. }, {
  108. .string = "phy_serdes_rx_bad_crc_count",
  109. .reg = MSCC_PHY_SERDES_RX_CRC_ERR_CNT,
  110. .page = MSCC_PHY_PAGE_EXTENDED_3,
  111. .mask = ERR_CNT_MASK,
  112. },
  113. };
  114. #if IS_ENABLED(CONFIG_OF_MDIO)
  115. static const struct vsc8531_edge_rate_table edge_table[] = {
  116. {MSCC_VDDMAC_3300, { 0, 2, 4, 7, 10, 17, 29, 53} },
  117. {MSCC_VDDMAC_2500, { 0, 3, 6, 10, 14, 23, 37, 63} },
  118. {MSCC_VDDMAC_1800, { 0, 5, 9, 16, 23, 35, 52, 76} },
  119. {MSCC_VDDMAC_1500, { 0, 6, 14, 21, 29, 42, 58, 77} },
  120. };
  121. #endif
  122. static const int vsc85xx_internal_delay[] = {200, 800, 1100, 1700, 2000, 2300,
  123. 2600, 3400};
  124. static int vsc85xx_phy_read_page(struct phy_device *phydev)
  125. {
  126. return __phy_read(phydev, MSCC_EXT_PAGE_ACCESS);
  127. }
  128. static int vsc85xx_phy_write_page(struct phy_device *phydev, int page)
  129. {
  130. return __phy_write(phydev, MSCC_EXT_PAGE_ACCESS, page);
  131. }
  132. static int vsc85xx_get_sset_count(struct phy_device *phydev)
  133. {
  134. struct vsc8531_private *priv = phydev->priv;
  135. if (!priv)
  136. return 0;
  137. return priv->nstats;
  138. }
  139. static void vsc85xx_get_strings(struct phy_device *phydev, u8 *data)
  140. {
  141. struct vsc8531_private *priv = phydev->priv;
  142. int i;
  143. if (!priv)
  144. return;
  145. for (i = 0; i < priv->nstats; i++)
  146. ethtool_puts(&data, priv->hw_stats[i].string);
  147. }
  148. static u64 vsc85xx_get_stat(struct phy_device *phydev, int i)
  149. {
  150. struct vsc8531_private *priv = phydev->priv;
  151. int val;
  152. val = phy_read_paged(phydev, priv->hw_stats[i].page,
  153. priv->hw_stats[i].reg);
  154. if (val < 0)
  155. return U64_MAX;
  156. val = val & priv->hw_stats[i].mask;
  157. priv->stats[i] += val;
  158. return priv->stats[i];
  159. }
  160. static void vsc85xx_get_stats(struct phy_device *phydev,
  161. struct ethtool_stats *stats, u64 *data)
  162. {
  163. struct vsc8531_private *priv = phydev->priv;
  164. int i;
  165. if (!priv)
  166. return;
  167. for (i = 0; i < priv->nstats; i++)
  168. data[i] = vsc85xx_get_stat(phydev, i);
  169. }
  170. static int vsc85xx_led_cntl_set(struct phy_device *phydev,
  171. u8 led_num,
  172. u8 mode)
  173. {
  174. u16 mask = LED_MODE_SEL_MASK(led_num);
  175. u16 val = LED_MODE_SEL(led_num, mode);
  176. return phy_modify(phydev, MSCC_PHY_LED_MODE_SEL, mask, val);
  177. }
  178. static int vsc85xx_led_combine_disable_set(struct phy_device *phydev,
  179. u8 led_num, bool combine_disable)
  180. {
  181. u16 val = LED_COMBINE_DIS(led_num, combine_disable);
  182. u16 mask = LED_COMBINE_DIS_MASK(led_num);
  183. return phy_modify(phydev, MSCC_PHY_LED_BEHAVIOR, mask, val);
  184. }
  185. static int vsc85xx_mdix_get(struct phy_device *phydev, u8 *mdix)
  186. {
  187. u16 reg_val;
  188. reg_val = phy_read(phydev, MSCC_PHY_DEV_AUX_CNTL);
  189. if (reg_val & HP_AUTO_MDIX_X_OVER_IND_MASK)
  190. *mdix = ETH_TP_MDI_X;
  191. else
  192. *mdix = ETH_TP_MDI;
  193. return 0;
  194. }
  195. static int vsc85xx_mdix_set(struct phy_device *phydev, u8 mdix)
  196. {
  197. int rc;
  198. u16 reg_val;
  199. reg_val = phy_read(phydev, MSCC_PHY_BYPASS_CONTROL);
  200. if (mdix == ETH_TP_MDI || mdix == ETH_TP_MDI_X) {
  201. reg_val |= (DISABLE_PAIR_SWAP_CORR_MASK |
  202. DISABLE_POLARITY_CORR_MASK |
  203. DISABLE_HP_AUTO_MDIX_MASK);
  204. } else {
  205. reg_val &= ~(DISABLE_PAIR_SWAP_CORR_MASK |
  206. DISABLE_POLARITY_CORR_MASK |
  207. DISABLE_HP_AUTO_MDIX_MASK);
  208. }
  209. rc = phy_write(phydev, MSCC_PHY_BYPASS_CONTROL, reg_val);
  210. if (rc)
  211. return rc;
  212. reg_val = 0;
  213. if (mdix == ETH_TP_MDI)
  214. reg_val = FORCE_MDI_CROSSOVER_MDI;
  215. else if (mdix == ETH_TP_MDI_X)
  216. reg_val = FORCE_MDI_CROSSOVER_MDIX;
  217. rc = phy_modify_paged(phydev, MSCC_PHY_PAGE_EXTENDED,
  218. MSCC_PHY_EXT_MODE_CNTL, FORCE_MDI_CROSSOVER_MASK,
  219. reg_val);
  220. if (rc < 0)
  221. return rc;
  222. return genphy_restart_aneg(phydev);
  223. }
  224. static int vsc85xx_downshift_get(struct phy_device *phydev, u8 *count)
  225. {
  226. int reg_val;
  227. reg_val = phy_read_paged(phydev, MSCC_PHY_PAGE_EXTENDED,
  228. MSCC_PHY_ACTIPHY_CNTL);
  229. if (reg_val < 0)
  230. return reg_val;
  231. reg_val &= DOWNSHIFT_CNTL_MASK;
  232. if (!(reg_val & DOWNSHIFT_EN))
  233. *count = DOWNSHIFT_DEV_DISABLE;
  234. else
  235. *count = ((reg_val & ~DOWNSHIFT_EN) >> DOWNSHIFT_CNTL_POS) + 2;
  236. return 0;
  237. }
  238. static int vsc85xx_downshift_set(struct phy_device *phydev, u8 count)
  239. {
  240. if (count == DOWNSHIFT_DEV_DEFAULT_COUNT) {
  241. /* Default downshift count 3 (i.e. Bit3:2 = 0b01) */
  242. count = ((1 << DOWNSHIFT_CNTL_POS) | DOWNSHIFT_EN);
  243. } else if (count > DOWNSHIFT_COUNT_MAX || count == 1) {
  244. phydev_err(phydev, "Downshift count should be 2,3,4 or 5\n");
  245. return -ERANGE;
  246. } else if (count) {
  247. /* Downshift count is either 2,3,4 or 5 */
  248. count = (((count - 2) << DOWNSHIFT_CNTL_POS) | DOWNSHIFT_EN);
  249. }
  250. return phy_modify_paged(phydev, MSCC_PHY_PAGE_EXTENDED,
  251. MSCC_PHY_ACTIPHY_CNTL, DOWNSHIFT_CNTL_MASK,
  252. count);
  253. }
  254. static int vsc85xx_wol_set(struct phy_device *phydev,
  255. struct ethtool_wolinfo *wol)
  256. {
  257. const u8 *mac_addr = phydev->attached_dev->dev_addr;
  258. int rc;
  259. u16 reg_val;
  260. u8 i;
  261. u16 pwd[3] = {0, 0, 0};
  262. struct ethtool_wolinfo *wol_conf = wol;
  263. rc = phy_select_page(phydev, MSCC_PHY_PAGE_EXTENDED_2);
  264. if (rc < 0)
  265. return phy_restore_page(phydev, rc, rc);
  266. if (wol->wolopts & WAKE_MAGIC) {
  267. /* Store the device address for the magic packet */
  268. for (i = 0; i < ARRAY_SIZE(pwd); i++)
  269. pwd[i] = mac_addr[5 - (i * 2 + 1)] << 8 |
  270. mac_addr[5 - i * 2];
  271. __phy_write(phydev, MSCC_PHY_WOL_LOWER_MAC_ADDR, pwd[0]);
  272. __phy_write(phydev, MSCC_PHY_WOL_MID_MAC_ADDR, pwd[1]);
  273. __phy_write(phydev, MSCC_PHY_WOL_UPPER_MAC_ADDR, pwd[2]);
  274. } else {
  275. __phy_write(phydev, MSCC_PHY_WOL_LOWER_MAC_ADDR, 0);
  276. __phy_write(phydev, MSCC_PHY_WOL_MID_MAC_ADDR, 0);
  277. __phy_write(phydev, MSCC_PHY_WOL_UPPER_MAC_ADDR, 0);
  278. }
  279. if (wol_conf->wolopts & WAKE_MAGICSECURE) {
  280. for (i = 0; i < ARRAY_SIZE(pwd); i++)
  281. pwd[i] = wol_conf->sopass[5 - (i * 2 + 1)] << 8 |
  282. wol_conf->sopass[5 - i * 2];
  283. __phy_write(phydev, MSCC_PHY_WOL_LOWER_PASSWD, pwd[0]);
  284. __phy_write(phydev, MSCC_PHY_WOL_MID_PASSWD, pwd[1]);
  285. __phy_write(phydev, MSCC_PHY_WOL_UPPER_PASSWD, pwd[2]);
  286. } else {
  287. __phy_write(phydev, MSCC_PHY_WOL_LOWER_PASSWD, 0);
  288. __phy_write(phydev, MSCC_PHY_WOL_MID_PASSWD, 0);
  289. __phy_write(phydev, MSCC_PHY_WOL_UPPER_PASSWD, 0);
  290. }
  291. reg_val = __phy_read(phydev, MSCC_PHY_WOL_MAC_CONTROL);
  292. if (wol_conf->wolopts & WAKE_MAGICSECURE)
  293. reg_val |= SECURE_ON_ENABLE;
  294. else
  295. reg_val &= ~SECURE_ON_ENABLE;
  296. __phy_write(phydev, MSCC_PHY_WOL_MAC_CONTROL, reg_val);
  297. rc = phy_restore_page(phydev, rc, rc > 0 ? 0 : rc);
  298. if (rc < 0)
  299. return rc;
  300. if (wol->wolopts & WAKE_MAGIC) {
  301. /* Enable the WOL interrupt */
  302. reg_val = phy_read(phydev, MII_VSC85XX_INT_MASK);
  303. reg_val |= MII_VSC85XX_INT_MASK_WOL;
  304. rc = phy_write(phydev, MII_VSC85XX_INT_MASK, reg_val);
  305. if (rc)
  306. return rc;
  307. } else {
  308. /* Disable the WOL interrupt */
  309. reg_val = phy_read(phydev, MII_VSC85XX_INT_MASK);
  310. reg_val &= (~MII_VSC85XX_INT_MASK_WOL);
  311. rc = phy_write(phydev, MII_VSC85XX_INT_MASK, reg_val);
  312. if (rc)
  313. return rc;
  314. }
  315. /* Clear WOL iterrupt status */
  316. reg_val = phy_read(phydev, MII_VSC85XX_INT_STATUS);
  317. return 0;
  318. }
  319. static void vsc85xx_wol_get(struct phy_device *phydev,
  320. struct ethtool_wolinfo *wol)
  321. {
  322. int rc;
  323. u16 reg_val;
  324. u8 i;
  325. u16 pwd[3] = {0, 0, 0};
  326. struct ethtool_wolinfo *wol_conf = wol;
  327. rc = phy_select_page(phydev, MSCC_PHY_PAGE_EXTENDED_2);
  328. if (rc < 0)
  329. goto out_restore_page;
  330. reg_val = __phy_read(phydev, MSCC_PHY_WOL_MAC_CONTROL);
  331. if (reg_val & SECURE_ON_ENABLE)
  332. wol_conf->wolopts |= WAKE_MAGICSECURE;
  333. if (wol_conf->wolopts & WAKE_MAGICSECURE) {
  334. pwd[0] = __phy_read(phydev, MSCC_PHY_WOL_LOWER_PASSWD);
  335. pwd[1] = __phy_read(phydev, MSCC_PHY_WOL_MID_PASSWD);
  336. pwd[2] = __phy_read(phydev, MSCC_PHY_WOL_UPPER_PASSWD);
  337. for (i = 0; i < ARRAY_SIZE(pwd); i++) {
  338. wol_conf->sopass[5 - i * 2] = pwd[i] & 0x00ff;
  339. wol_conf->sopass[5 - (i * 2 + 1)] = (pwd[i] & 0xff00)
  340. >> 8;
  341. }
  342. }
  343. out_restore_page:
  344. phy_restore_page(phydev, rc, rc > 0 ? 0 : rc);
  345. }
  346. #if IS_ENABLED(CONFIG_OF_MDIO)
  347. static int vsc85xx_edge_rate_magic_get(struct phy_device *phydev)
  348. {
  349. u32 vdd, sd;
  350. int i, j;
  351. struct device *dev = &phydev->mdio.dev;
  352. struct device_node *of_node = dev->of_node;
  353. u8 sd_array_size = ARRAY_SIZE(edge_table[0].slowdown);
  354. if (!of_node)
  355. return -ENODEV;
  356. if (of_property_read_u32(of_node, "vsc8531,vddmac", &vdd))
  357. vdd = MSCC_VDDMAC_3300;
  358. if (of_property_read_u32(of_node, "vsc8531,edge-slowdown", &sd))
  359. sd = 0;
  360. for (i = 0; i < ARRAY_SIZE(edge_table); i++)
  361. if (edge_table[i].vddmac == vdd)
  362. for (j = 0; j < sd_array_size; j++)
  363. if (edge_table[i].slowdown[j] == sd)
  364. return (sd_array_size - j - 1);
  365. return -EINVAL;
  366. }
  367. static int vsc85xx_dt_led_mode_get(struct phy_device *phydev,
  368. char *led,
  369. u32 default_mode)
  370. {
  371. struct vsc8531_private *priv = phydev->priv;
  372. struct device *dev = &phydev->mdio.dev;
  373. struct device_node *of_node = dev->of_node;
  374. u32 led_mode;
  375. int err;
  376. if (!of_node)
  377. return -ENODEV;
  378. led_mode = default_mode;
  379. err = of_property_read_u32(of_node, led, &led_mode);
  380. if (!err && !(BIT(led_mode) & priv->supp_led_modes)) {
  381. phydev_err(phydev, "DT %s invalid\n", led);
  382. return -EINVAL;
  383. }
  384. return led_mode;
  385. }
  386. #else
  387. static int vsc85xx_edge_rate_magic_get(struct phy_device *phydev)
  388. {
  389. return 0;
  390. }
  391. static int vsc85xx_dt_led_mode_get(struct phy_device *phydev,
  392. char *led,
  393. u8 default_mode)
  394. {
  395. return default_mode;
  396. }
  397. #endif /* CONFIG_OF_MDIO */
  398. static int vsc85xx_dt_led_modes_get(struct phy_device *phydev,
  399. const u32 *default_mode)
  400. {
  401. struct vsc8531_private *priv = phydev->priv;
  402. char led_dt_prop[28];
  403. int i, ret;
  404. for (i = 0; i < priv->nleds; i++) {
  405. ret = sprintf(led_dt_prop, "vsc8531,led-%d-mode", i);
  406. if (ret < 0)
  407. return ret;
  408. ret = vsc85xx_dt_led_mode_get(phydev, led_dt_prop,
  409. default_mode[i]);
  410. if (ret < 0)
  411. return ret;
  412. priv->leds_mode[i] = ret;
  413. }
  414. return 0;
  415. }
  416. static int vsc85xx_edge_rate_cntl_set(struct phy_device *phydev, u8 edge_rate)
  417. {
  418. int rc;
  419. mutex_lock(&phydev->lock);
  420. rc = phy_modify_paged(phydev, MSCC_PHY_PAGE_EXTENDED_2,
  421. MSCC_PHY_WOL_MAC_CONTROL, EDGE_RATE_CNTL_MASK,
  422. edge_rate << EDGE_RATE_CNTL_POS);
  423. mutex_unlock(&phydev->lock);
  424. return rc;
  425. }
  426. static int vsc85xx_mac_if_set(struct phy_device *phydev,
  427. phy_interface_t interface)
  428. {
  429. int rc;
  430. u16 reg_val;
  431. mutex_lock(&phydev->lock);
  432. reg_val = phy_read(phydev, MSCC_PHY_EXT_PHY_CNTL_1);
  433. reg_val &= ~(MAC_IF_SELECTION_MASK);
  434. switch (interface) {
  435. case PHY_INTERFACE_MODE_RGMII_TXID:
  436. case PHY_INTERFACE_MODE_RGMII_RXID:
  437. case PHY_INTERFACE_MODE_RGMII_ID:
  438. case PHY_INTERFACE_MODE_RGMII:
  439. reg_val |= (MAC_IF_SELECTION_RGMII << MAC_IF_SELECTION_POS);
  440. break;
  441. case PHY_INTERFACE_MODE_RMII:
  442. reg_val |= (MAC_IF_SELECTION_RMII << MAC_IF_SELECTION_POS);
  443. break;
  444. case PHY_INTERFACE_MODE_MII:
  445. case PHY_INTERFACE_MODE_GMII:
  446. reg_val |= (MAC_IF_SELECTION_GMII << MAC_IF_SELECTION_POS);
  447. break;
  448. default:
  449. rc = -EINVAL;
  450. goto out_unlock;
  451. }
  452. rc = phy_write(phydev, MSCC_PHY_EXT_PHY_CNTL_1, reg_val);
  453. if (rc)
  454. goto out_unlock;
  455. rc = genphy_soft_reset(phydev);
  456. out_unlock:
  457. mutex_unlock(&phydev->lock);
  458. return rc;
  459. }
  460. /* Set the RGMII RX and TX clock skews individually, according to the PHY
  461. * interface type, to:
  462. * * 0.2 ns (their default, and lowest, hardware value) if delays should
  463. * not be enabled
  464. * * 2.0 ns (which causes the data to be sampled at exactly half way between
  465. * clock transitions at 1000 Mbps) if delays should be enabled
  466. */
  467. static int vsc85xx_update_rgmii_cntl(struct phy_device *phydev, u32 rgmii_cntl,
  468. u16 rgmii_rx_delay_mask,
  469. u16 rgmii_tx_delay_mask)
  470. {
  471. u16 rgmii_rx_delay_pos = ffs(rgmii_rx_delay_mask) - 1;
  472. u16 rgmii_tx_delay_pos = ffs(rgmii_tx_delay_mask) - 1;
  473. int delay_size = ARRAY_SIZE(vsc85xx_internal_delay);
  474. u16 reg_val = 0;
  475. u16 mask = 0;
  476. s32 rx_delay;
  477. s32 tx_delay;
  478. int rc = 0;
  479. /* For traffic to pass, the VSC8502 family needs the RX_CLK disable bit
  480. * to be unset for all PHY modes, so do that as part of the paged
  481. * register modification.
  482. * For some family members (like VSC8530/31/40/41) this bit is reserved
  483. * and read-only, and the RX clock is enabled by default.
  484. */
  485. if (rgmii_cntl == VSC8502_RGMII_CNTL)
  486. mask |= VSC8502_RGMII_RX_CLK_DISABLE;
  487. if (phy_interface_is_rgmii(phydev))
  488. mask |= rgmii_rx_delay_mask | rgmii_tx_delay_mask;
  489. rx_delay = phy_get_internal_delay(phydev, vsc85xx_internal_delay,
  490. delay_size, true);
  491. if (rx_delay < 0) {
  492. if (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID ||
  493. phydev->interface == PHY_INTERFACE_MODE_RGMII_ID)
  494. rx_delay = RGMII_CLK_DELAY_2_0_NS;
  495. else
  496. rx_delay = RGMII_CLK_DELAY_0_2_NS;
  497. }
  498. tx_delay = phy_get_internal_delay(phydev, vsc85xx_internal_delay,
  499. delay_size, false);
  500. if (tx_delay < 0) {
  501. if (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID ||
  502. phydev->interface == PHY_INTERFACE_MODE_RGMII_ID)
  503. tx_delay = RGMII_CLK_DELAY_2_0_NS;
  504. else
  505. tx_delay = RGMII_CLK_DELAY_0_2_NS;
  506. }
  507. reg_val |= rx_delay << rgmii_rx_delay_pos;
  508. reg_val |= tx_delay << rgmii_tx_delay_pos;
  509. if (mask)
  510. rc = phy_modify_paged(phydev, MSCC_PHY_PAGE_EXTENDED_2,
  511. rgmii_cntl, mask, reg_val);
  512. return rc;
  513. }
  514. static int vsc85xx_default_config(struct phy_device *phydev)
  515. {
  516. phydev->mdix_ctrl = ETH_TP_MDI_AUTO;
  517. return vsc85xx_update_rgmii_cntl(phydev, VSC8502_RGMII_CNTL,
  518. VSC8502_RGMII_RX_DELAY_MASK,
  519. VSC8502_RGMII_TX_DELAY_MASK);
  520. }
  521. static int vsc85xx_get_tunable(struct phy_device *phydev,
  522. struct ethtool_tunable *tuna, void *data)
  523. {
  524. switch (tuna->id) {
  525. case ETHTOOL_PHY_DOWNSHIFT:
  526. return vsc85xx_downshift_get(phydev, (u8 *)data);
  527. default:
  528. return -EINVAL;
  529. }
  530. }
  531. static int vsc85xx_set_tunable(struct phy_device *phydev,
  532. struct ethtool_tunable *tuna,
  533. const void *data)
  534. {
  535. switch (tuna->id) {
  536. case ETHTOOL_PHY_DOWNSHIFT:
  537. return vsc85xx_downshift_set(phydev, *(u8 *)data);
  538. default:
  539. return -EINVAL;
  540. }
  541. }
  542. /* mdiobus lock should be locked when using this function */
  543. static void vsc85xx_tr_write(struct phy_device *phydev, u16 addr, u32 val)
  544. {
  545. __phy_write(phydev, MSCC_PHY_TR_MSB, val >> 16);
  546. __phy_write(phydev, MSCC_PHY_TR_LSB, val & GENMASK(15, 0));
  547. __phy_write(phydev, MSCC_PHY_TR_CNTL, TR_WRITE | TR_ADDR(addr));
  548. }
  549. static int vsc8531_pre_init_seq_set(struct phy_device *phydev)
  550. {
  551. int rc;
  552. static const struct reg_val init_seq[] = {
  553. {0x0f90, 0x00688980},
  554. {0x0696, 0x00000003},
  555. {0x07fa, 0x0050100f},
  556. {0x1686, 0x00000004},
  557. };
  558. unsigned int i;
  559. int oldpage;
  560. rc = phy_modify_paged(phydev, MSCC_PHY_PAGE_STANDARD,
  561. MSCC_PHY_EXT_CNTL_STATUS, SMI_BROADCAST_WR_EN,
  562. SMI_BROADCAST_WR_EN);
  563. if (rc < 0)
  564. return rc;
  565. rc = phy_modify_paged(phydev, MSCC_PHY_PAGE_TEST,
  566. MSCC_PHY_TEST_PAGE_24, 0, 0x0400);
  567. if (rc < 0)
  568. return rc;
  569. rc = phy_modify_paged(phydev, MSCC_PHY_PAGE_TEST,
  570. MSCC_PHY_TEST_PAGE_5, 0x0a00, 0x0e00);
  571. if (rc < 0)
  572. return rc;
  573. rc = phy_modify_paged(phydev, MSCC_PHY_PAGE_TEST,
  574. MSCC_PHY_TEST_PAGE_8, TR_CLK_DISABLE, TR_CLK_DISABLE);
  575. if (rc < 0)
  576. return rc;
  577. mutex_lock(&phydev->lock);
  578. oldpage = phy_select_page(phydev, MSCC_PHY_PAGE_TR);
  579. if (oldpage < 0)
  580. goto out_unlock;
  581. for (i = 0; i < ARRAY_SIZE(init_seq); i++)
  582. vsc85xx_tr_write(phydev, init_seq[i].reg, init_seq[i].val);
  583. out_unlock:
  584. oldpage = phy_restore_page(phydev, oldpage, oldpage);
  585. mutex_unlock(&phydev->lock);
  586. return oldpage;
  587. }
  588. static int vsc85xx_eee_init_seq_set(struct phy_device *phydev)
  589. {
  590. static const struct reg_val init_eee[] = {
  591. {0x0f82, 0x0012b00a},
  592. {0x1686, 0x00000004},
  593. {0x168c, 0x00d2c46f},
  594. {0x17a2, 0x00000620},
  595. {0x16a0, 0x00eeffdd},
  596. {0x16a6, 0x00071448},
  597. {0x16a4, 0x0013132f},
  598. {0x16a8, 0x00000000},
  599. {0x0ffc, 0x00c0a028},
  600. {0x0fe8, 0x0091b06c},
  601. {0x0fea, 0x00041600},
  602. {0x0f80, 0x00000af4},
  603. {0x0fec, 0x00901809},
  604. {0x0fee, 0x0000a6a1},
  605. {0x0ffe, 0x00b01007},
  606. {0x16b0, 0x00eeff00},
  607. {0x16b2, 0x00007000},
  608. {0x16b4, 0x00000814},
  609. };
  610. unsigned int i;
  611. int oldpage;
  612. mutex_lock(&phydev->lock);
  613. oldpage = phy_select_page(phydev, MSCC_PHY_PAGE_TR);
  614. if (oldpage < 0)
  615. goto out_unlock;
  616. for (i = 0; i < ARRAY_SIZE(init_eee); i++)
  617. vsc85xx_tr_write(phydev, init_eee[i].reg, init_eee[i].val);
  618. out_unlock:
  619. oldpage = phy_restore_page(phydev, oldpage, oldpage);
  620. mutex_unlock(&phydev->lock);
  621. return oldpage;
  622. }
  623. /* phydev->bus->mdio_lock should be locked when using this function */
  624. int phy_base_write(struct phy_device *phydev, u32 regnum, u16 val)
  625. {
  626. if (unlikely(!mutex_is_locked(&phydev->mdio.bus->mdio_lock))) {
  627. dev_err(&phydev->mdio.dev, "MDIO bus lock not held!\n");
  628. dump_stack();
  629. }
  630. return __phy_package_write(phydev, VSC88XX_BASE_ADDR, regnum, val);
  631. }
  632. /* phydev->bus->mdio_lock should be locked when using this function */
  633. int phy_base_read(struct phy_device *phydev, u32 regnum)
  634. {
  635. if (unlikely(!mutex_is_locked(&phydev->mdio.bus->mdio_lock))) {
  636. dev_err(&phydev->mdio.dev, "MDIO bus lock not held!\n");
  637. dump_stack();
  638. }
  639. return __phy_package_read(phydev, VSC88XX_BASE_ADDR, regnum);
  640. }
  641. u32 vsc85xx_csr_read(struct phy_device *phydev,
  642. enum csr_target target, u32 reg)
  643. {
  644. unsigned long deadline;
  645. u32 val, val_l, val_h;
  646. phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_CSR_CNTL);
  647. /* CSR registers are grouped under different Target IDs.
  648. * 6-bit Target_ID is split between MSCC_EXT_PAGE_CSR_CNTL_20 and
  649. * MSCC_EXT_PAGE_CSR_CNTL_19 registers.
  650. * Target_ID[5:2] maps to bits[3:0] of MSCC_EXT_PAGE_CSR_CNTL_20
  651. * and Target_ID[1:0] maps to bits[13:12] of MSCC_EXT_PAGE_CSR_CNTL_19.
  652. */
  653. /* Setup the Target ID */
  654. phy_base_write(phydev, MSCC_EXT_PAGE_CSR_CNTL_20,
  655. MSCC_PHY_CSR_CNTL_20_TARGET(target >> 2));
  656. if ((target >> 2 == 0x1) || (target >> 2 == 0x3))
  657. /* non-MACsec access */
  658. target &= 0x3;
  659. else
  660. target = 0;
  661. /* Trigger CSR Action - Read into the CSR's */
  662. phy_base_write(phydev, MSCC_EXT_PAGE_CSR_CNTL_19,
  663. MSCC_PHY_CSR_CNTL_19_CMD | MSCC_PHY_CSR_CNTL_19_READ |
  664. MSCC_PHY_CSR_CNTL_19_REG_ADDR(reg) |
  665. MSCC_PHY_CSR_CNTL_19_TARGET(target));
  666. /* Wait for register access*/
  667. deadline = jiffies + msecs_to_jiffies(PROC_CMD_NCOMPLETED_TIMEOUT_MS);
  668. do {
  669. usleep_range(500, 1000);
  670. val = phy_base_read(phydev, MSCC_EXT_PAGE_CSR_CNTL_19);
  671. } while (time_before(jiffies, deadline) &&
  672. !(val & MSCC_PHY_CSR_CNTL_19_CMD));
  673. if (!(val & MSCC_PHY_CSR_CNTL_19_CMD))
  674. return 0xffffffff;
  675. /* Read the Least Significant Word (LSW) (17) */
  676. val_l = phy_base_read(phydev, MSCC_EXT_PAGE_CSR_CNTL_17);
  677. /* Read the Most Significant Word (MSW) (18) */
  678. val_h = phy_base_read(phydev, MSCC_EXT_PAGE_CSR_CNTL_18);
  679. phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS,
  680. MSCC_PHY_PAGE_STANDARD);
  681. return (val_h << 16) | val_l;
  682. }
  683. int vsc85xx_csr_write(struct phy_device *phydev,
  684. enum csr_target target, u32 reg, u32 val)
  685. {
  686. unsigned long deadline;
  687. phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_CSR_CNTL);
  688. /* CSR registers are grouped under different Target IDs.
  689. * 6-bit Target_ID is split between MSCC_EXT_PAGE_CSR_CNTL_20 and
  690. * MSCC_EXT_PAGE_CSR_CNTL_19 registers.
  691. * Target_ID[5:2] maps to bits[3:0] of MSCC_EXT_PAGE_CSR_CNTL_20
  692. * and Target_ID[1:0] maps to bits[13:12] of MSCC_EXT_PAGE_CSR_CNTL_19.
  693. */
  694. /* Setup the Target ID */
  695. phy_base_write(phydev, MSCC_EXT_PAGE_CSR_CNTL_20,
  696. MSCC_PHY_CSR_CNTL_20_TARGET(target >> 2));
  697. /* Write the Least Significant Word (LSW) (17) */
  698. phy_base_write(phydev, MSCC_EXT_PAGE_CSR_CNTL_17, (u16)val);
  699. /* Write the Most Significant Word (MSW) (18) */
  700. phy_base_write(phydev, MSCC_EXT_PAGE_CSR_CNTL_18, (u16)(val >> 16));
  701. if ((target >> 2 == 0x1) || (target >> 2 == 0x3))
  702. /* non-MACsec access */
  703. target &= 0x3;
  704. else
  705. target = 0;
  706. /* Trigger CSR Action - Write into the CSR's */
  707. phy_base_write(phydev, MSCC_EXT_PAGE_CSR_CNTL_19,
  708. MSCC_PHY_CSR_CNTL_19_CMD |
  709. MSCC_PHY_CSR_CNTL_19_REG_ADDR(reg) |
  710. MSCC_PHY_CSR_CNTL_19_TARGET(target));
  711. /* Wait for register access */
  712. deadline = jiffies + msecs_to_jiffies(PROC_CMD_NCOMPLETED_TIMEOUT_MS);
  713. do {
  714. usleep_range(500, 1000);
  715. val = phy_base_read(phydev, MSCC_EXT_PAGE_CSR_CNTL_19);
  716. } while (time_before(jiffies, deadline) &&
  717. !(val & MSCC_PHY_CSR_CNTL_19_CMD));
  718. if (!(val & MSCC_PHY_CSR_CNTL_19_CMD))
  719. return -ETIMEDOUT;
  720. phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS,
  721. MSCC_PHY_PAGE_STANDARD);
  722. return 0;
  723. }
  724. /* bus->mdio_lock should be locked when using this function */
  725. static void vsc8584_csr_write(struct phy_device *phydev, u16 addr, u32 val)
  726. {
  727. phy_base_write(phydev, MSCC_PHY_TR_MSB, val >> 16);
  728. phy_base_write(phydev, MSCC_PHY_TR_LSB, val & GENMASK(15, 0));
  729. phy_base_write(phydev, MSCC_PHY_TR_CNTL, TR_WRITE | TR_ADDR(addr));
  730. }
  731. /* bus->mdio_lock should be locked when using this function */
  732. int vsc8584_cmd(struct phy_device *phydev, u16 val)
  733. {
  734. unsigned long deadline;
  735. u16 reg_val;
  736. phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS,
  737. MSCC_PHY_PAGE_EXTENDED_GPIO);
  738. phy_base_write(phydev, MSCC_PHY_PROC_CMD, PROC_CMD_NCOMPLETED | val);
  739. deadline = jiffies + msecs_to_jiffies(PROC_CMD_NCOMPLETED_TIMEOUT_MS);
  740. do {
  741. reg_val = phy_base_read(phydev, MSCC_PHY_PROC_CMD);
  742. } while (time_before(jiffies, deadline) &&
  743. (reg_val & PROC_CMD_NCOMPLETED) &&
  744. !(reg_val & PROC_CMD_FAILED));
  745. phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_STANDARD);
  746. if (reg_val & PROC_CMD_FAILED)
  747. return -EIO;
  748. if (reg_val & PROC_CMD_NCOMPLETED)
  749. return -ETIMEDOUT;
  750. return 0;
  751. }
  752. /* bus->mdio_lock should be locked when using this function */
  753. static int vsc8584_micro_deassert_reset(struct phy_device *phydev,
  754. bool patch_en)
  755. {
  756. u32 enable, release;
  757. phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS,
  758. MSCC_PHY_PAGE_EXTENDED_GPIO);
  759. enable = RUN_FROM_INT_ROM | MICRO_CLK_EN | DW8051_CLK_EN;
  760. release = MICRO_NSOFT_RESET | RUN_FROM_INT_ROM | DW8051_CLK_EN |
  761. MICRO_CLK_EN;
  762. if (patch_en) {
  763. enable |= MICRO_PATCH_EN;
  764. release |= MICRO_PATCH_EN;
  765. /* Clear all patches */
  766. phy_base_write(phydev, MSCC_INT_MEM_CNTL, READ_RAM);
  767. }
  768. /* Enable 8051 Micro clock; CLEAR/SET patch present; disable PRAM clock
  769. * override and addr. auto-incr; operate at 125 MHz
  770. */
  771. phy_base_write(phydev, MSCC_DW8051_CNTL_STATUS, enable);
  772. /* Release 8051 Micro SW reset */
  773. phy_base_write(phydev, MSCC_DW8051_CNTL_STATUS, release);
  774. phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_STANDARD);
  775. return 0;
  776. }
  777. /* bus->mdio_lock should be locked when using this function */
  778. static int vsc8584_micro_assert_reset(struct phy_device *phydev)
  779. {
  780. int ret;
  781. u16 reg;
  782. ret = vsc8584_cmd(phydev, PROC_CMD_NOP);
  783. if (ret)
  784. return ret;
  785. phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS,
  786. MSCC_PHY_PAGE_EXTENDED_GPIO);
  787. reg = phy_base_read(phydev, MSCC_INT_MEM_CNTL);
  788. reg &= ~EN_PATCH_RAM_TRAP_ADDR(4);
  789. phy_base_write(phydev, MSCC_INT_MEM_CNTL, reg);
  790. phy_base_write(phydev, MSCC_TRAP_ROM_ADDR(4), 0x005b);
  791. phy_base_write(phydev, MSCC_PATCH_RAM_ADDR(4), 0x005b);
  792. reg = phy_base_read(phydev, MSCC_INT_MEM_CNTL);
  793. reg |= EN_PATCH_RAM_TRAP_ADDR(4);
  794. phy_base_write(phydev, MSCC_INT_MEM_CNTL, reg);
  795. phy_base_write(phydev, MSCC_PHY_PROC_CMD, PROC_CMD_NOP);
  796. reg = phy_base_read(phydev, MSCC_DW8051_CNTL_STATUS);
  797. reg &= ~MICRO_NSOFT_RESET;
  798. phy_base_write(phydev, MSCC_DW8051_CNTL_STATUS, reg);
  799. phy_base_write(phydev, MSCC_PHY_PROC_CMD, PROC_CMD_MCB_ACCESS_MAC_CONF |
  800. PROC_CMD_SGMII_PORT(0) | PROC_CMD_NO_MAC_CONF |
  801. PROC_CMD_READ);
  802. reg = phy_base_read(phydev, MSCC_INT_MEM_CNTL);
  803. reg &= ~EN_PATCH_RAM_TRAP_ADDR(4);
  804. phy_base_write(phydev, MSCC_INT_MEM_CNTL, reg);
  805. phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_STANDARD);
  806. return 0;
  807. }
  808. /* bus->mdio_lock should be locked when using this function */
  809. static int vsc8584_get_fw_crc(struct phy_device *phydev, u16 start, u16 size,
  810. u16 *crc)
  811. {
  812. int ret;
  813. phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_EXTENDED);
  814. phy_base_write(phydev, MSCC_PHY_VERIPHY_CNTL_2, start);
  815. phy_base_write(phydev, MSCC_PHY_VERIPHY_CNTL_3, size);
  816. /* Start Micro command */
  817. ret = vsc8584_cmd(phydev, PROC_CMD_CRC16);
  818. if (ret)
  819. goto out;
  820. phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_EXTENDED);
  821. *crc = phy_base_read(phydev, MSCC_PHY_VERIPHY_CNTL_2);
  822. out:
  823. phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_STANDARD);
  824. return ret;
  825. }
  826. /* bus->mdio_lock should be locked when using this function */
  827. static int vsc8584_patch_fw(struct phy_device *phydev,
  828. const struct firmware *fw)
  829. {
  830. int i, ret;
  831. ret = vsc8584_micro_assert_reset(phydev);
  832. if (ret) {
  833. dev_err(&phydev->mdio.dev,
  834. "%s: failed to assert reset of micro\n", __func__);
  835. return ret;
  836. }
  837. phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS,
  838. MSCC_PHY_PAGE_EXTENDED_GPIO);
  839. /* Hold 8051 Micro in SW Reset, Enable auto incr address and patch clock
  840. * Disable the 8051 Micro clock
  841. */
  842. phy_base_write(phydev, MSCC_DW8051_CNTL_STATUS, RUN_FROM_INT_ROM |
  843. AUTOINC_ADDR | PATCH_RAM_CLK | MICRO_CLK_EN |
  844. MICRO_CLK_DIVIDE(2));
  845. phy_base_write(phydev, MSCC_INT_MEM_CNTL, READ_PRAM | INT_MEM_WRITE_EN |
  846. INT_MEM_DATA(2));
  847. phy_base_write(phydev, MSCC_INT_MEM_ADDR, 0x0000);
  848. for (i = 0; i < fw->size; i++)
  849. phy_base_write(phydev, MSCC_INT_MEM_CNTL, READ_PRAM |
  850. INT_MEM_WRITE_EN | fw->data[i]);
  851. /* Clear internal memory access */
  852. phy_base_write(phydev, MSCC_INT_MEM_CNTL, READ_RAM);
  853. phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_STANDARD);
  854. return 0;
  855. }
  856. /* bus->mdio_lock should be locked when using this function */
  857. static bool vsc8574_is_serdes_init(struct phy_device *phydev)
  858. {
  859. u16 reg;
  860. bool ret;
  861. phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS,
  862. MSCC_PHY_PAGE_EXTENDED_GPIO);
  863. reg = phy_base_read(phydev, MSCC_TRAP_ROM_ADDR(1));
  864. if (reg != 0x3eb7) {
  865. ret = false;
  866. goto out;
  867. }
  868. reg = phy_base_read(phydev, MSCC_PATCH_RAM_ADDR(1));
  869. if (reg != 0x4012) {
  870. ret = false;
  871. goto out;
  872. }
  873. reg = phy_base_read(phydev, MSCC_INT_MEM_CNTL);
  874. if (reg != EN_PATCH_RAM_TRAP_ADDR(1)) {
  875. ret = false;
  876. goto out;
  877. }
  878. reg = phy_base_read(phydev, MSCC_DW8051_CNTL_STATUS);
  879. if ((MICRO_NSOFT_RESET | RUN_FROM_INT_ROM | DW8051_CLK_EN |
  880. MICRO_CLK_EN) != (reg & MSCC_DW8051_VLD_MASK)) {
  881. ret = false;
  882. goto out;
  883. }
  884. ret = true;
  885. out:
  886. phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_STANDARD);
  887. return ret;
  888. }
  889. /* bus->mdio_lock should be locked when using this function */
  890. static int vsc8574_config_pre_init(struct phy_device *phydev)
  891. {
  892. static const struct reg_val pre_init1[] = {
  893. {0x0fae, 0x000401bd},
  894. {0x0fac, 0x000f000f},
  895. {0x17a0, 0x00a0f147},
  896. {0x0fe4, 0x00052f54},
  897. {0x1792, 0x0027303d},
  898. {0x07fe, 0x00000704},
  899. {0x0fe0, 0x00060150},
  900. {0x0f82, 0x0012b00a},
  901. {0x0f80, 0x00000d74},
  902. {0x02e0, 0x00000012},
  903. {0x03a2, 0x00050208},
  904. {0x03b2, 0x00009186},
  905. {0x0fb0, 0x000e3700},
  906. {0x1688, 0x00049f81},
  907. {0x0fd2, 0x0000ffff},
  908. {0x168a, 0x00039fa2},
  909. {0x1690, 0x0020640b},
  910. {0x0258, 0x00002220},
  911. {0x025a, 0x00002a20},
  912. {0x025c, 0x00003060},
  913. {0x025e, 0x00003fa0},
  914. {0x03a6, 0x0000e0f0},
  915. {0x0f92, 0x00001489},
  916. {0x16a2, 0x00007000},
  917. {0x16a6, 0x00071448},
  918. {0x16a0, 0x00eeffdd},
  919. {0x0fe8, 0x0091b06c},
  920. {0x0fea, 0x00041600},
  921. {0x16b0, 0x00eeff00},
  922. {0x16b2, 0x00007000},
  923. {0x16b4, 0x00000814},
  924. {0x0f90, 0x00688980},
  925. {0x03a4, 0x0000d8f0},
  926. {0x0fc0, 0x00000400},
  927. {0x07fa, 0x0050100f},
  928. {0x0796, 0x00000003},
  929. {0x07f8, 0x00c3ff98},
  930. {0x0fa4, 0x0018292a},
  931. {0x168c, 0x00d2c46f},
  932. {0x17a2, 0x00000620},
  933. {0x16a4, 0x0013132f},
  934. {0x16a8, 0x00000000},
  935. {0x0ffc, 0x00c0a028},
  936. {0x0fec, 0x00901c09},
  937. {0x0fee, 0x0004a6a1},
  938. {0x0ffe, 0x00b01807},
  939. };
  940. static const struct reg_val pre_init2[] = {
  941. {0x0486, 0x0008a518},
  942. {0x0488, 0x006dc696},
  943. {0x048a, 0x00000912},
  944. {0x048e, 0x00000db6},
  945. {0x049c, 0x00596596},
  946. {0x049e, 0x00000514},
  947. {0x04a2, 0x00410280},
  948. {0x04a4, 0x00000000},
  949. {0x04a6, 0x00000000},
  950. {0x04a8, 0x00000000},
  951. {0x04aa, 0x00000000},
  952. {0x04ae, 0x007df7dd},
  953. {0x04b0, 0x006d95d4},
  954. {0x04b2, 0x00492410},
  955. };
  956. struct device *dev = &phydev->mdio.dev;
  957. const struct firmware *fw;
  958. unsigned int i;
  959. u16 crc, reg;
  960. bool serdes_init;
  961. int ret;
  962. phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_STANDARD);
  963. /* all writes below are broadcasted to all PHYs in the same package */
  964. reg = phy_base_read(phydev, MSCC_PHY_EXT_CNTL_STATUS);
  965. reg |= SMI_BROADCAST_WR_EN;
  966. phy_base_write(phydev, MSCC_PHY_EXT_CNTL_STATUS, reg);
  967. phy_base_write(phydev, MII_VSC85XX_INT_MASK, 0);
  968. /* The below register writes are tweaking analog and electrical
  969. * configuration that were determined through characterization by PHY
  970. * engineers. These don't mean anything more than "these are the best
  971. * values".
  972. */
  973. phy_base_write(phydev, MSCC_PHY_EXT_PHY_CNTL_2, 0x0040);
  974. phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_TEST);
  975. phy_base_write(phydev, MSCC_PHY_TEST_PAGE_20, 0x4320);
  976. phy_base_write(phydev, MSCC_PHY_TEST_PAGE_24, 0x0c00);
  977. phy_base_write(phydev, MSCC_PHY_TEST_PAGE_9, 0x18ca);
  978. phy_base_write(phydev, MSCC_PHY_TEST_PAGE_5, 0x1b20);
  979. reg = phy_base_read(phydev, MSCC_PHY_TEST_PAGE_8);
  980. reg |= TR_CLK_DISABLE;
  981. phy_base_write(phydev, MSCC_PHY_TEST_PAGE_8, reg);
  982. phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_TR);
  983. for (i = 0; i < ARRAY_SIZE(pre_init1); i++)
  984. vsc8584_csr_write(phydev, pre_init1[i].reg, pre_init1[i].val);
  985. phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_EXTENDED_2);
  986. phy_base_write(phydev, MSCC_PHY_CU_PMD_TX_CNTL, 0x028e);
  987. phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_TR);
  988. for (i = 0; i < ARRAY_SIZE(pre_init2); i++)
  989. vsc8584_csr_write(phydev, pre_init2[i].reg, pre_init2[i].val);
  990. phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_TEST);
  991. reg = phy_base_read(phydev, MSCC_PHY_TEST_PAGE_8);
  992. reg &= ~TR_CLK_DISABLE;
  993. phy_base_write(phydev, MSCC_PHY_TEST_PAGE_8, reg);
  994. phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_STANDARD);
  995. /* end of write broadcasting */
  996. reg = phy_base_read(phydev, MSCC_PHY_EXT_CNTL_STATUS);
  997. reg &= ~SMI_BROADCAST_WR_EN;
  998. phy_base_write(phydev, MSCC_PHY_EXT_CNTL_STATUS, reg);
  999. ret = request_firmware(&fw, MSCC_VSC8574_REVB_INT8051_FW, dev);
  1000. if (ret) {
  1001. dev_err(dev, "failed to load firmware %s, ret: %d\n",
  1002. MSCC_VSC8574_REVB_INT8051_FW, ret);
  1003. return ret;
  1004. }
  1005. /* Add one byte to size for the one added by the patch_fw function */
  1006. ret = vsc8584_get_fw_crc(phydev,
  1007. MSCC_VSC8574_REVB_INT8051_FW_START_ADDR,
  1008. fw->size + 1, &crc);
  1009. if (ret)
  1010. goto out;
  1011. if (crc == MSCC_VSC8574_REVB_INT8051_FW_CRC) {
  1012. serdes_init = vsc8574_is_serdes_init(phydev);
  1013. if (!serdes_init) {
  1014. ret = vsc8584_micro_assert_reset(phydev);
  1015. if (ret) {
  1016. dev_err(dev,
  1017. "%s: failed to assert reset of micro\n",
  1018. __func__);
  1019. goto out;
  1020. }
  1021. }
  1022. } else {
  1023. dev_dbg(dev, "FW CRC is not the expected one, patching FW\n");
  1024. serdes_init = false;
  1025. if (vsc8584_patch_fw(phydev, fw))
  1026. dev_warn(dev,
  1027. "failed to patch FW, expect non-optimal device\n");
  1028. }
  1029. if (!serdes_init) {
  1030. phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS,
  1031. MSCC_PHY_PAGE_EXTENDED_GPIO);
  1032. phy_base_write(phydev, MSCC_TRAP_ROM_ADDR(1), 0x3eb7);
  1033. phy_base_write(phydev, MSCC_PATCH_RAM_ADDR(1), 0x4012);
  1034. phy_base_write(phydev, MSCC_INT_MEM_CNTL,
  1035. EN_PATCH_RAM_TRAP_ADDR(1));
  1036. vsc8584_micro_deassert_reset(phydev, false);
  1037. /* Add one byte to size for the one added by the patch_fw
  1038. * function
  1039. */
  1040. ret = vsc8584_get_fw_crc(phydev,
  1041. MSCC_VSC8574_REVB_INT8051_FW_START_ADDR,
  1042. fw->size + 1, &crc);
  1043. if (ret)
  1044. goto out;
  1045. if (crc != MSCC_VSC8574_REVB_INT8051_FW_CRC)
  1046. dev_warn(dev,
  1047. "FW CRC after patching is not the expected one, expect non-optimal device\n");
  1048. }
  1049. phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS,
  1050. MSCC_PHY_PAGE_EXTENDED_GPIO);
  1051. ret = vsc8584_cmd(phydev, PROC_CMD_1588_DEFAULT_INIT |
  1052. PROC_CMD_PHY_INIT);
  1053. out:
  1054. phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_STANDARD);
  1055. release_firmware(fw);
  1056. return ret;
  1057. }
  1058. /* Access LCPLL Cfg_2 */
  1059. static void vsc8584_pll5g_cfg2_wr(struct phy_device *phydev,
  1060. bool disable_fsm)
  1061. {
  1062. u32 rd_dat;
  1063. rd_dat = vsc85xx_csr_read(phydev, MACRO_CTRL, PHY_S6G_PLL5G_CFG2);
  1064. rd_dat &= ~BIT(PHY_S6G_CFG2_FSM_DIS);
  1065. rd_dat |= (disable_fsm << PHY_S6G_CFG2_FSM_DIS);
  1066. vsc85xx_csr_write(phydev, MACRO_CTRL, PHY_S6G_PLL5G_CFG2, rd_dat);
  1067. }
  1068. /* trigger a read to the spcified MCB */
  1069. static int vsc8584_mcb_rd_trig(struct phy_device *phydev,
  1070. u32 mcb_reg_addr, u8 mcb_slave_num)
  1071. {
  1072. u32 rd_dat = 0;
  1073. /* read MCB */
  1074. vsc85xx_csr_write(phydev, MACRO_CTRL, mcb_reg_addr,
  1075. (0x40000000 | (1L << mcb_slave_num)));
  1076. return read_poll_timeout(vsc85xx_csr_read, rd_dat,
  1077. !(rd_dat & 0x40000000),
  1078. 4000, 200000, 0,
  1079. phydev, MACRO_CTRL, mcb_reg_addr);
  1080. }
  1081. /* trigger a write to the spcified MCB */
  1082. static int vsc8584_mcb_wr_trig(struct phy_device *phydev,
  1083. u32 mcb_reg_addr,
  1084. u8 mcb_slave_num)
  1085. {
  1086. u32 rd_dat = 0;
  1087. /* write back MCB */
  1088. vsc85xx_csr_write(phydev, MACRO_CTRL, mcb_reg_addr,
  1089. (0x80000000 | (1L << mcb_slave_num)));
  1090. return read_poll_timeout(vsc85xx_csr_read, rd_dat,
  1091. !(rd_dat & 0x80000000),
  1092. 4000, 200000, 0,
  1093. phydev, MACRO_CTRL, mcb_reg_addr);
  1094. }
  1095. /* Sequence to Reset LCPLL for the VIPER and ELISE PHY */
  1096. static int vsc8584_pll5g_reset(struct phy_device *phydev)
  1097. {
  1098. bool dis_fsm;
  1099. int ret = 0;
  1100. ret = vsc8584_mcb_rd_trig(phydev, 0x11, 0);
  1101. if (ret < 0)
  1102. goto done;
  1103. dis_fsm = 1;
  1104. /* Reset LCPLL */
  1105. vsc8584_pll5g_cfg2_wr(phydev, dis_fsm);
  1106. /* write back LCPLL MCB */
  1107. ret = vsc8584_mcb_wr_trig(phydev, 0x11, 0);
  1108. if (ret < 0)
  1109. goto done;
  1110. /* 10 mSec sleep while LCPLL is hold in reset */
  1111. usleep_range(10000, 20000);
  1112. /* read LCPLL MCB into CSRs */
  1113. ret = vsc8584_mcb_rd_trig(phydev, 0x11, 0);
  1114. if (ret < 0)
  1115. goto done;
  1116. dis_fsm = 0;
  1117. /* Release the Reset of LCPLL */
  1118. vsc8584_pll5g_cfg2_wr(phydev, dis_fsm);
  1119. /* write back LCPLL MCB */
  1120. ret = vsc8584_mcb_wr_trig(phydev, 0x11, 0);
  1121. if (ret < 0)
  1122. goto done;
  1123. usleep_range(110000, 200000);
  1124. done:
  1125. return ret;
  1126. }
  1127. /* bus->mdio_lock should be locked when using this function */
  1128. static int vsc8584_config_pre_init(struct phy_device *phydev)
  1129. {
  1130. static const struct reg_val pre_init1[] = {
  1131. {0x07fa, 0x0050100f},
  1132. {0x1688, 0x00049f81},
  1133. {0x0f90, 0x00688980},
  1134. {0x03a4, 0x0000d8f0},
  1135. {0x0fc0, 0x00000400},
  1136. {0x0f82, 0x0012b002},
  1137. {0x1686, 0x00000004},
  1138. {0x168c, 0x00d2c46f},
  1139. {0x17a2, 0x00000620},
  1140. {0x16a0, 0x00eeffdd},
  1141. {0x16a6, 0x00071448},
  1142. {0x16a4, 0x0013132f},
  1143. {0x16a8, 0x00000000},
  1144. {0x0ffc, 0x00c0a028},
  1145. {0x0fe8, 0x0091b06c},
  1146. {0x0fea, 0x00041600},
  1147. {0x0f80, 0x00fffaff},
  1148. {0x0fec, 0x00901809},
  1149. {0x0ffe, 0x00b01007},
  1150. {0x16b0, 0x00eeff00},
  1151. {0x16b2, 0x00007000},
  1152. {0x16b4, 0x00000814},
  1153. };
  1154. static const struct reg_val pre_init2[] = {
  1155. {0x0486, 0x0008a518},
  1156. {0x0488, 0x006dc696},
  1157. {0x048a, 0x00000912},
  1158. };
  1159. const struct firmware *fw;
  1160. struct device *dev = &phydev->mdio.dev;
  1161. unsigned int i;
  1162. u16 crc, reg;
  1163. int ret;
  1164. ret = vsc8584_pll5g_reset(phydev);
  1165. if (ret < 0) {
  1166. dev_err(dev, "failed LCPLL reset, ret: %d\n", ret);
  1167. return ret;
  1168. }
  1169. phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_STANDARD);
  1170. /* all writes below are broadcasted to all PHYs in the same package */
  1171. reg = phy_base_read(phydev, MSCC_PHY_EXT_CNTL_STATUS);
  1172. reg |= SMI_BROADCAST_WR_EN;
  1173. phy_base_write(phydev, MSCC_PHY_EXT_CNTL_STATUS, reg);
  1174. phy_base_write(phydev, MII_VSC85XX_INT_MASK, 0);
  1175. reg = phy_base_read(phydev, MSCC_PHY_BYPASS_CONTROL);
  1176. reg |= PARALLEL_DET_IGNORE_ADVERTISED;
  1177. phy_base_write(phydev, MSCC_PHY_BYPASS_CONTROL, reg);
  1178. /* The below register writes are tweaking analog and electrical
  1179. * configuration that were determined through characterization by PHY
  1180. * engineers. These don't mean anything more than "these are the best
  1181. * values".
  1182. */
  1183. phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_EXTENDED_3);
  1184. phy_base_write(phydev, MSCC_PHY_SERDES_TX_CRC_ERR_CNT, 0x2000);
  1185. phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_TEST);
  1186. phy_base_write(phydev, MSCC_PHY_TEST_PAGE_5, 0x1f20);
  1187. reg = phy_base_read(phydev, MSCC_PHY_TEST_PAGE_8);
  1188. reg |= TR_CLK_DISABLE;
  1189. phy_base_write(phydev, MSCC_PHY_TEST_PAGE_8, reg);
  1190. phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_TR);
  1191. phy_base_write(phydev, MSCC_PHY_TR_CNTL, TR_WRITE | TR_ADDR(0x2fa4));
  1192. reg = phy_base_read(phydev, MSCC_PHY_TR_MSB);
  1193. reg &= ~0x007f;
  1194. reg |= 0x0019;
  1195. phy_base_write(phydev, MSCC_PHY_TR_MSB, reg);
  1196. phy_base_write(phydev, MSCC_PHY_TR_CNTL, TR_WRITE | TR_ADDR(0x0fa4));
  1197. for (i = 0; i < ARRAY_SIZE(pre_init1); i++)
  1198. vsc8584_csr_write(phydev, pre_init1[i].reg, pre_init1[i].val);
  1199. phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_EXTENDED_2);
  1200. phy_base_write(phydev, MSCC_PHY_CU_PMD_TX_CNTL, 0x028e);
  1201. phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_TR);
  1202. for (i = 0; i < ARRAY_SIZE(pre_init2); i++)
  1203. vsc8584_csr_write(phydev, pre_init2[i].reg, pre_init2[i].val);
  1204. phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_TEST);
  1205. reg = phy_base_read(phydev, MSCC_PHY_TEST_PAGE_8);
  1206. reg &= ~TR_CLK_DISABLE;
  1207. phy_base_write(phydev, MSCC_PHY_TEST_PAGE_8, reg);
  1208. phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_STANDARD);
  1209. /* end of write broadcasting */
  1210. reg = phy_base_read(phydev, MSCC_PHY_EXT_CNTL_STATUS);
  1211. reg &= ~SMI_BROADCAST_WR_EN;
  1212. phy_base_write(phydev, MSCC_PHY_EXT_CNTL_STATUS, reg);
  1213. ret = request_firmware(&fw, MSCC_VSC8584_REVB_INT8051_FW, dev);
  1214. if (ret) {
  1215. dev_err(dev, "failed to load firmware %s, ret: %d\n",
  1216. MSCC_VSC8584_REVB_INT8051_FW, ret);
  1217. return ret;
  1218. }
  1219. /* Add one byte to size for the one added by the patch_fw function */
  1220. ret = vsc8584_get_fw_crc(phydev,
  1221. MSCC_VSC8584_REVB_INT8051_FW_START_ADDR,
  1222. fw->size + 1, &crc);
  1223. if (ret)
  1224. goto out;
  1225. if (crc != MSCC_VSC8584_REVB_INT8051_FW_CRC) {
  1226. dev_dbg(dev, "FW CRC is not the expected one, patching FW\n");
  1227. if (vsc8584_patch_fw(phydev, fw))
  1228. dev_warn(dev,
  1229. "failed to patch FW, expect non-optimal device\n");
  1230. }
  1231. vsc8584_micro_deassert_reset(phydev, false);
  1232. /* Add one byte to size for the one added by the patch_fw function */
  1233. ret = vsc8584_get_fw_crc(phydev,
  1234. MSCC_VSC8584_REVB_INT8051_FW_START_ADDR,
  1235. fw->size + 1, &crc);
  1236. if (ret)
  1237. goto out;
  1238. if (crc != MSCC_VSC8584_REVB_INT8051_FW_CRC)
  1239. dev_warn(dev,
  1240. "FW CRC after patching is not the expected one, expect non-optimal device\n");
  1241. ret = vsc8584_micro_assert_reset(phydev);
  1242. if (ret)
  1243. goto out;
  1244. /* Write patch vector 0, to skip IB cal polling */
  1245. phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_EXTENDED_GPIO);
  1246. reg = MSCC_ROM_TRAP_SERDES_6G_CFG; /* ROM address to trap, for patch vector 0 */
  1247. ret = phy_base_write(phydev, MSCC_TRAP_ROM_ADDR(1), reg);
  1248. if (ret)
  1249. goto out;
  1250. reg = MSCC_RAM_TRAP_SERDES_6G_CFG; /* RAM address to jump to, when patch vector 0 enabled */
  1251. ret = phy_base_write(phydev, MSCC_PATCH_RAM_ADDR(1), reg);
  1252. if (ret)
  1253. goto out;
  1254. reg = phy_base_read(phydev, MSCC_INT_MEM_CNTL);
  1255. reg |= PATCH_VEC_ZERO_EN; /* bit 8, enable patch vector 0 */
  1256. ret = phy_base_write(phydev, MSCC_INT_MEM_CNTL, reg);
  1257. if (ret)
  1258. goto out;
  1259. vsc8584_micro_deassert_reset(phydev, true);
  1260. out:
  1261. phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_STANDARD);
  1262. release_firmware(fw);
  1263. return ret;
  1264. }
  1265. static void vsc8584_get_base_addr(struct phy_device *phydev)
  1266. {
  1267. struct vsc8531_private *vsc8531 = phydev->priv;
  1268. u16 val, addr;
  1269. phy_lock_mdio_bus(phydev);
  1270. __phy_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_EXTENDED);
  1271. addr = __phy_read(phydev, MSCC_PHY_EXT_PHY_CNTL_4);
  1272. addr >>= PHY_CNTL_4_ADDR_POS;
  1273. val = __phy_read(phydev, MSCC_PHY_ACTIPHY_CNTL);
  1274. __phy_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_STANDARD);
  1275. phy_unlock_mdio_bus(phydev);
  1276. /* In the package, there are two pairs of PHYs (PHY0 + PHY2 and
  1277. * PHY1 + PHY3). The first PHY of each pair (PHY0 and PHY1) is
  1278. * the base PHY for timestamping operations.
  1279. */
  1280. vsc8531->ts_base_addr = phydev->mdio.addr;
  1281. vsc8531->ts_base_phy = addr;
  1282. if (val & PHY_ADDR_REVERSED) {
  1283. vsc8531->base_addr = phydev->mdio.addr + addr;
  1284. if (addr > 1) {
  1285. vsc8531->ts_base_addr += 2;
  1286. vsc8531->ts_base_phy += 2;
  1287. }
  1288. } else {
  1289. vsc8531->base_addr = phydev->mdio.addr - addr;
  1290. if (addr > 1) {
  1291. vsc8531->ts_base_addr -= 2;
  1292. vsc8531->ts_base_phy -= 2;
  1293. }
  1294. }
  1295. vsc8531->addr = addr;
  1296. }
  1297. static void vsc85xx_coma_mode_release(struct phy_device *phydev)
  1298. {
  1299. /* The coma mode (pin or reg) provides an optional feature that
  1300. * may be used to control when the PHYs become active.
  1301. * Alternatively the COMA_MODE pin may be connected low
  1302. * so that the PHYs are fully active once out of reset.
  1303. */
  1304. /* Enable output (mode=0) and write zero to it */
  1305. vsc85xx_phy_write_page(phydev, MSCC_PHY_PAGE_EXTENDED_GPIO);
  1306. __phy_modify(phydev, MSCC_PHY_GPIO_CONTROL_2,
  1307. MSCC_PHY_COMA_MODE | MSCC_PHY_COMA_OUTPUT, 0);
  1308. vsc85xx_phy_write_page(phydev, MSCC_PHY_PAGE_STANDARD);
  1309. }
  1310. static int vsc8584_config_host_serdes(struct phy_device *phydev)
  1311. {
  1312. struct vsc8531_private *vsc8531 = phydev->priv;
  1313. int ret;
  1314. u16 val;
  1315. ret = phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS,
  1316. MSCC_PHY_PAGE_EXTENDED_GPIO);
  1317. if (ret)
  1318. return ret;
  1319. val = phy_base_read(phydev, MSCC_PHY_MAC_CFG_FASTLINK);
  1320. val &= ~MAC_CFG_MASK;
  1321. if (phydev->interface == PHY_INTERFACE_MODE_QSGMII) {
  1322. val |= MAC_CFG_QSGMII;
  1323. } else if (phydev->interface == PHY_INTERFACE_MODE_SGMII) {
  1324. val |= MAC_CFG_SGMII;
  1325. } else {
  1326. ret = -EINVAL;
  1327. return ret;
  1328. }
  1329. ret = phy_base_write(phydev, MSCC_PHY_MAC_CFG_FASTLINK, val);
  1330. if (ret)
  1331. return ret;
  1332. ret = phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS,
  1333. MSCC_PHY_PAGE_STANDARD);
  1334. if (ret)
  1335. return ret;
  1336. val = PROC_CMD_MCB_ACCESS_MAC_CONF | PROC_CMD_RST_CONF_PORT |
  1337. PROC_CMD_READ_MOD_WRITE_PORT;
  1338. if (phydev->interface == PHY_INTERFACE_MODE_QSGMII)
  1339. val |= PROC_CMD_QSGMII_MAC;
  1340. else
  1341. val |= PROC_CMD_SGMII_MAC;
  1342. ret = vsc8584_cmd(phydev, val);
  1343. if (ret)
  1344. return ret;
  1345. usleep_range(10000, 20000);
  1346. /* Disable SerDes for 100Base-FX */
  1347. ret = vsc8584_cmd(phydev, PROC_CMD_FIBER_MEDIA_CONF |
  1348. PROC_CMD_FIBER_PORT(vsc8531->addr) |
  1349. PROC_CMD_FIBER_DISABLE |
  1350. PROC_CMD_READ_MOD_WRITE_PORT |
  1351. PROC_CMD_RST_CONF_PORT | PROC_CMD_FIBER_100BASE_FX);
  1352. if (ret)
  1353. return ret;
  1354. /* Disable SerDes for 1000Base-X */
  1355. ret = vsc8584_cmd(phydev, PROC_CMD_FIBER_MEDIA_CONF |
  1356. PROC_CMD_FIBER_PORT(vsc8531->addr) |
  1357. PROC_CMD_FIBER_DISABLE |
  1358. PROC_CMD_READ_MOD_WRITE_PORT |
  1359. PROC_CMD_RST_CONF_PORT | PROC_CMD_FIBER_1000BASE_X);
  1360. if (ret)
  1361. return ret;
  1362. return vsc85xx_sd6g_config_v2(phydev);
  1363. }
  1364. static int vsc8574_config_host_serdes(struct phy_device *phydev)
  1365. {
  1366. struct vsc8531_private *vsc8531 = phydev->priv;
  1367. int ret;
  1368. u16 val;
  1369. ret = phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS,
  1370. MSCC_PHY_PAGE_EXTENDED_GPIO);
  1371. if (ret)
  1372. return ret;
  1373. val = phy_base_read(phydev, MSCC_PHY_MAC_CFG_FASTLINK);
  1374. val &= ~MAC_CFG_MASK;
  1375. if (phydev->interface == PHY_INTERFACE_MODE_QSGMII) {
  1376. val |= MAC_CFG_QSGMII;
  1377. } else if (phydev->interface == PHY_INTERFACE_MODE_SGMII) {
  1378. val |= MAC_CFG_SGMII;
  1379. } else if (phy_interface_is_rgmii(phydev)) {
  1380. val |= MAC_CFG_RGMII;
  1381. } else {
  1382. ret = -EINVAL;
  1383. return ret;
  1384. }
  1385. ret = phy_base_write(phydev, MSCC_PHY_MAC_CFG_FASTLINK, val);
  1386. if (ret)
  1387. return ret;
  1388. ret = phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS,
  1389. MSCC_PHY_PAGE_STANDARD);
  1390. if (ret)
  1391. return ret;
  1392. if (!phy_interface_is_rgmii(phydev)) {
  1393. val = PROC_CMD_MCB_ACCESS_MAC_CONF | PROC_CMD_RST_CONF_PORT |
  1394. PROC_CMD_READ_MOD_WRITE_PORT;
  1395. if (phydev->interface == PHY_INTERFACE_MODE_QSGMII)
  1396. val |= PROC_CMD_QSGMII_MAC;
  1397. else
  1398. val |= PROC_CMD_SGMII_MAC;
  1399. ret = vsc8584_cmd(phydev, val);
  1400. if (ret)
  1401. return ret;
  1402. usleep_range(10000, 20000);
  1403. }
  1404. /* Disable SerDes for 100Base-FX */
  1405. ret = vsc8584_cmd(phydev, PROC_CMD_FIBER_MEDIA_CONF |
  1406. PROC_CMD_FIBER_PORT(vsc8531->addr) |
  1407. PROC_CMD_FIBER_DISABLE |
  1408. PROC_CMD_READ_MOD_WRITE_PORT |
  1409. PROC_CMD_RST_CONF_PORT | PROC_CMD_FIBER_100BASE_FX);
  1410. if (ret)
  1411. return ret;
  1412. /* Disable SerDes for 1000Base-X */
  1413. return vsc8584_cmd(phydev, PROC_CMD_FIBER_MEDIA_CONF |
  1414. PROC_CMD_FIBER_PORT(vsc8531->addr) |
  1415. PROC_CMD_FIBER_DISABLE |
  1416. PROC_CMD_READ_MOD_WRITE_PORT |
  1417. PROC_CMD_RST_CONF_PORT | PROC_CMD_FIBER_1000BASE_X);
  1418. }
  1419. static int vsc8584_config_init(struct phy_device *phydev)
  1420. {
  1421. struct vsc8531_private *vsc8531 = phydev->priv;
  1422. int ret, i;
  1423. u16 val;
  1424. phydev->mdix_ctrl = ETH_TP_MDI_AUTO;
  1425. phy_lock_mdio_bus(phydev);
  1426. /* Some parts of the init sequence are identical for every PHY in the
  1427. * package. Some parts are modifying the GPIO register bank which is a
  1428. * set of registers that are affecting all PHYs, a few resetting the
  1429. * microprocessor common to all PHYs. The CRC check responsible of the
  1430. * checking the firmware within the 8051 microprocessor can only be
  1431. * accessed via the PHY whose internal address in the package is 0.
  1432. * All PHYs' interrupts mask register has to be zeroed before enabling
  1433. * any PHY's interrupt in this register.
  1434. * For all these reasons, we need to do the init sequence once and only
  1435. * once whatever is the first PHY in the package that is initialized and
  1436. * do the correct init sequence for all PHYs that are package-critical
  1437. * in this pre-init function.
  1438. */
  1439. if (phy_package_init_once(phydev)) {
  1440. switch (phydev->phy_id & phydev->drv->phy_id_mask) {
  1441. case PHY_ID_VSC8504:
  1442. case PHY_ID_VSC8552:
  1443. case PHY_ID_VSC8572:
  1444. case PHY_ID_VSC8574:
  1445. ret = vsc8574_config_pre_init(phydev);
  1446. if (ret)
  1447. goto err;
  1448. ret = vsc8574_config_host_serdes(phydev);
  1449. if (ret)
  1450. goto err;
  1451. break;
  1452. case PHY_ID_VSC856X:
  1453. case PHY_ID_VSC8575:
  1454. case PHY_ID_VSC8582:
  1455. case PHY_ID_VSC8584:
  1456. ret = vsc8584_config_pre_init(phydev);
  1457. if (ret)
  1458. goto err;
  1459. ret = vsc8584_config_host_serdes(phydev);
  1460. if (ret)
  1461. goto err;
  1462. vsc85xx_coma_mode_release(phydev);
  1463. break;
  1464. default:
  1465. ret = -EINVAL;
  1466. break;
  1467. }
  1468. if (ret)
  1469. goto err;
  1470. }
  1471. phy_unlock_mdio_bus(phydev);
  1472. ret = vsc8584_macsec_init(phydev);
  1473. if (ret)
  1474. return ret;
  1475. ret = vsc8584_ptp_init(phydev);
  1476. if (ret)
  1477. return ret;
  1478. val = phy_read(phydev, MSCC_PHY_EXT_PHY_CNTL_1);
  1479. val &= ~(MEDIA_OP_MODE_MASK | VSC8584_MAC_IF_SELECTION_MASK);
  1480. val |= (MEDIA_OP_MODE_COPPER << MEDIA_OP_MODE_POS) |
  1481. (VSC8584_MAC_IF_SELECTION_SGMII << VSC8584_MAC_IF_SELECTION_POS);
  1482. ret = phy_write(phydev, MSCC_PHY_EXT_PHY_CNTL_1, val);
  1483. if (ret)
  1484. return ret;
  1485. ret = vsc85xx_update_rgmii_cntl(phydev, VSC8572_RGMII_CNTL,
  1486. VSC8572_RGMII_RX_DELAY_MASK,
  1487. VSC8572_RGMII_TX_DELAY_MASK);
  1488. if (ret)
  1489. return ret;
  1490. ret = genphy_soft_reset(phydev);
  1491. if (ret)
  1492. return ret;
  1493. for (i = 0; i < vsc8531->nleds; i++) {
  1494. ret = vsc85xx_led_cntl_set(phydev, i, vsc8531->leds_mode[i]);
  1495. if (ret)
  1496. return ret;
  1497. }
  1498. return 0;
  1499. err:
  1500. phy_unlock_mdio_bus(phydev);
  1501. return ret;
  1502. }
  1503. static irqreturn_t vsc8584_handle_interrupt(struct phy_device *phydev)
  1504. {
  1505. irqreturn_t ret;
  1506. int irq_status;
  1507. irq_status = phy_read(phydev, MII_VSC85XX_INT_STATUS);
  1508. if (irq_status < 0)
  1509. return IRQ_NONE;
  1510. /* Timestamping IRQ does not set a bit in the global INT_STATUS, so
  1511. * irq_status would be 0.
  1512. */
  1513. ret = vsc8584_handle_ts_interrupt(phydev);
  1514. if (!(irq_status & MII_VSC85XX_INT_MASK_MASK))
  1515. return ret;
  1516. if (irq_status & MII_VSC85XX_INT_MASK_EXT)
  1517. vsc8584_handle_macsec_interrupt(phydev);
  1518. if (irq_status & MII_VSC85XX_INT_MASK_LINK_CHG)
  1519. phy_trigger_machine(phydev);
  1520. return IRQ_HANDLED;
  1521. }
  1522. static int vsc85xx_config_init(struct phy_device *phydev)
  1523. {
  1524. int rc, i, phy_id;
  1525. struct vsc8531_private *vsc8531 = phydev->priv;
  1526. rc = vsc85xx_default_config(phydev);
  1527. if (rc)
  1528. return rc;
  1529. rc = vsc85xx_mac_if_set(phydev, phydev->interface);
  1530. if (rc)
  1531. return rc;
  1532. rc = vsc85xx_edge_rate_cntl_set(phydev, vsc8531->rate_magic);
  1533. if (rc)
  1534. return rc;
  1535. phy_id = phydev->drv->phy_id & phydev->drv->phy_id_mask;
  1536. if (PHY_ID_VSC8531 == phy_id || PHY_ID_VSC8541 == phy_id ||
  1537. PHY_ID_VSC8530 == phy_id || PHY_ID_VSC8540 == phy_id) {
  1538. rc = vsc8531_pre_init_seq_set(phydev);
  1539. if (rc)
  1540. return rc;
  1541. }
  1542. rc = vsc85xx_eee_init_seq_set(phydev);
  1543. if (rc)
  1544. return rc;
  1545. for (i = 0; i < vsc8531->nleds; i++) {
  1546. rc = vsc85xx_led_cntl_set(phydev, i, vsc8531->leds_mode[i]);
  1547. if (rc)
  1548. return rc;
  1549. }
  1550. return 0;
  1551. }
  1552. static int __phy_write_mcb_s6g(struct phy_device *phydev, u32 reg, u8 mcb,
  1553. u32 op)
  1554. {
  1555. unsigned long deadline;
  1556. u32 val;
  1557. int ret;
  1558. ret = vsc85xx_csr_write(phydev, PHY_MCB_TARGET, reg,
  1559. op | (1 << mcb));
  1560. if (ret)
  1561. return -EINVAL;
  1562. deadline = jiffies + msecs_to_jiffies(PROC_CMD_NCOMPLETED_TIMEOUT_MS);
  1563. do {
  1564. usleep_range(500, 1000);
  1565. val = vsc85xx_csr_read(phydev, PHY_MCB_TARGET, reg);
  1566. if (val == 0xffffffff)
  1567. return -EIO;
  1568. } while (time_before(jiffies, deadline) && (val & op));
  1569. if (val & op)
  1570. return -ETIMEDOUT;
  1571. return 0;
  1572. }
  1573. /* Trigger a read to the specified MCB */
  1574. int phy_update_mcb_s6g(struct phy_device *phydev, u32 reg, u8 mcb)
  1575. {
  1576. return __phy_write_mcb_s6g(phydev, reg, mcb, PHY_MCB_S6G_READ);
  1577. }
  1578. /* Trigger a write to the specified MCB */
  1579. int phy_commit_mcb_s6g(struct phy_device *phydev, u32 reg, u8 mcb)
  1580. {
  1581. return __phy_write_mcb_s6g(phydev, reg, mcb, PHY_MCB_S6G_WRITE);
  1582. }
  1583. static int vsc8514_config_host_serdes(struct phy_device *phydev)
  1584. {
  1585. int ret;
  1586. u16 val;
  1587. ret = phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS,
  1588. MSCC_PHY_PAGE_EXTENDED_GPIO);
  1589. if (ret)
  1590. return ret;
  1591. val = phy_base_read(phydev, MSCC_PHY_MAC_CFG_FASTLINK);
  1592. val &= ~MAC_CFG_MASK;
  1593. val |= MAC_CFG_QSGMII;
  1594. ret = phy_base_write(phydev, MSCC_PHY_MAC_CFG_FASTLINK, val);
  1595. if (ret)
  1596. return ret;
  1597. ret = phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS,
  1598. MSCC_PHY_PAGE_STANDARD);
  1599. if (ret)
  1600. return ret;
  1601. ret = vsc8584_cmd(phydev, PROC_CMD_NOP);
  1602. if (ret)
  1603. return ret;
  1604. ret = vsc8584_cmd(phydev,
  1605. PROC_CMD_MCB_ACCESS_MAC_CONF |
  1606. PROC_CMD_RST_CONF_PORT |
  1607. PROC_CMD_READ_MOD_WRITE_PORT | PROC_CMD_QSGMII_MAC);
  1608. if (ret) {
  1609. dev_err(&phydev->mdio.dev, "%s: QSGMII error: %d\n",
  1610. __func__, ret);
  1611. return ret;
  1612. }
  1613. /* Apply 6G SerDes FOJI Algorithm
  1614. * Initial condition requirement:
  1615. * 1. hold 8051 in reset
  1616. * 2. disable patch vector 0, in order to allow IB cal poll during FoJi
  1617. * 3. deassert 8051 reset after change patch vector status
  1618. * 4. proceed with FoJi (vsc85xx_sd6g_config_v2)
  1619. */
  1620. vsc8584_micro_assert_reset(phydev);
  1621. val = phy_base_read(phydev, MSCC_INT_MEM_CNTL);
  1622. /* clear bit 8, to disable patch vector 0 */
  1623. val &= ~PATCH_VEC_ZERO_EN;
  1624. ret = phy_base_write(phydev, MSCC_INT_MEM_CNTL, val);
  1625. /* Enable 8051 clock, don't set patch present, disable PRAM clock override */
  1626. vsc8584_micro_deassert_reset(phydev, false);
  1627. return vsc85xx_sd6g_config_v2(phydev);
  1628. }
  1629. static int vsc8514_config_pre_init(struct phy_device *phydev)
  1630. {
  1631. /* These are the settings to override the silicon default
  1632. * values to handle hardware performance of PHY. They
  1633. * are set at Power-On state and remain until PHY Reset.
  1634. */
  1635. static const struct reg_val pre_init1[] = {
  1636. {0x0f90, 0x00688980},
  1637. {0x0786, 0x00000003},
  1638. {0x07fa, 0x0050100f},
  1639. {0x0f82, 0x0012b002},
  1640. {0x1686, 0x00000004},
  1641. {0x168c, 0x00d2c46f},
  1642. {0x17a2, 0x00000620},
  1643. {0x16a0, 0x00eeffdd},
  1644. {0x16a6, 0x00071448},
  1645. {0x16a4, 0x0013132f},
  1646. {0x16a8, 0x00000000},
  1647. {0x0ffc, 0x00c0a028},
  1648. {0x0fe8, 0x0091b06c},
  1649. {0x0fea, 0x00041600},
  1650. {0x0f80, 0x00fffaff},
  1651. {0x0fec, 0x00901809},
  1652. {0x0ffe, 0x00b01007},
  1653. {0x16b0, 0x00eeff00},
  1654. {0x16b2, 0x00007000},
  1655. {0x16b4, 0x00000814},
  1656. };
  1657. struct device *dev = &phydev->mdio.dev;
  1658. unsigned int i;
  1659. u16 reg;
  1660. int ret;
  1661. ret = vsc8584_pll5g_reset(phydev);
  1662. if (ret < 0) {
  1663. dev_err(dev, "failed LCPLL reset, ret: %d\n", ret);
  1664. return ret;
  1665. }
  1666. phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_STANDARD);
  1667. /* all writes below are broadcasted to all PHYs in the same package */
  1668. reg = phy_base_read(phydev, MSCC_PHY_EXT_CNTL_STATUS);
  1669. reg |= SMI_BROADCAST_WR_EN;
  1670. phy_base_write(phydev, MSCC_PHY_EXT_CNTL_STATUS, reg);
  1671. phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_TEST);
  1672. reg = phy_base_read(phydev, MSCC_PHY_TEST_PAGE_8);
  1673. reg |= BIT(15);
  1674. phy_base_write(phydev, MSCC_PHY_TEST_PAGE_8, reg);
  1675. phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_TR);
  1676. for (i = 0; i < ARRAY_SIZE(pre_init1); i++)
  1677. vsc8584_csr_write(phydev, pre_init1[i].reg, pre_init1[i].val);
  1678. phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_TEST);
  1679. reg = phy_base_read(phydev, MSCC_PHY_TEST_PAGE_8);
  1680. reg &= ~BIT(15);
  1681. phy_base_write(phydev, MSCC_PHY_TEST_PAGE_8, reg);
  1682. phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_STANDARD);
  1683. reg = phy_base_read(phydev, MSCC_PHY_EXT_CNTL_STATUS);
  1684. reg &= ~SMI_BROADCAST_WR_EN;
  1685. phy_base_write(phydev, MSCC_PHY_EXT_CNTL_STATUS, reg);
  1686. /* Add pre-patching commands to:
  1687. * 1. enable 8051 clock, operate 8051 clock at 125 MHz
  1688. * instead of HW default 62.5MHz
  1689. * 2. write patch vector 0, to skip IB cal polling executed
  1690. * as part of the 0x80E0 ROM command
  1691. */
  1692. vsc8584_micro_deassert_reset(phydev, false);
  1693. vsc8584_micro_assert_reset(phydev);
  1694. phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS,
  1695. MSCC_PHY_PAGE_EXTENDED_GPIO);
  1696. /* ROM address to trap, for patch vector 0 */
  1697. reg = MSCC_ROM_TRAP_SERDES_6G_CFG;
  1698. ret = phy_base_write(phydev, MSCC_TRAP_ROM_ADDR(1), reg);
  1699. if (ret)
  1700. goto err;
  1701. /* RAM address to jump to, when patch vector 0 enabled */
  1702. reg = MSCC_RAM_TRAP_SERDES_6G_CFG;
  1703. ret = phy_base_write(phydev, MSCC_PATCH_RAM_ADDR(1), reg);
  1704. if (ret)
  1705. goto err;
  1706. reg = phy_base_read(phydev, MSCC_INT_MEM_CNTL);
  1707. reg |= PATCH_VEC_ZERO_EN; /* bit 8, enable patch vector 0 */
  1708. ret = phy_base_write(phydev, MSCC_INT_MEM_CNTL, reg);
  1709. if (ret)
  1710. goto err;
  1711. /* Enable 8051 clock, don't set patch present
  1712. * yet, disable PRAM clock override
  1713. */
  1714. vsc8584_micro_deassert_reset(phydev, false);
  1715. return ret;
  1716. err:
  1717. /* restore 8051 and bail w error */
  1718. vsc8584_micro_deassert_reset(phydev, false);
  1719. return ret;
  1720. }
  1721. static int vsc8514_config_init(struct phy_device *phydev)
  1722. {
  1723. struct vsc8531_private *vsc8531 = phydev->priv;
  1724. int ret, i;
  1725. phydev->mdix_ctrl = ETH_TP_MDI_AUTO;
  1726. phy_lock_mdio_bus(phydev);
  1727. /* Some parts of the init sequence are identical for every PHY in the
  1728. * package. Some parts are modifying the GPIO register bank which is a
  1729. * set of registers that are affecting all PHYs, a few resetting the
  1730. * microprocessor common to all PHYs.
  1731. * All PHYs' interrupts mask register has to be zeroed before enabling
  1732. * any PHY's interrupt in this register.
  1733. * For all these reasons, we need to do the init sequence once and only
  1734. * once whatever is the first PHY in the package that is initialized and
  1735. * do the correct init sequence for all PHYs that are package-critical
  1736. * in this pre-init function.
  1737. */
  1738. if (phy_package_init_once(phydev)) {
  1739. ret = vsc8514_config_pre_init(phydev);
  1740. if (ret)
  1741. goto err;
  1742. ret = vsc8514_config_host_serdes(phydev);
  1743. if (ret)
  1744. goto err;
  1745. vsc85xx_coma_mode_release(phydev);
  1746. }
  1747. phy_unlock_mdio_bus(phydev);
  1748. ret = phy_modify(phydev, MSCC_PHY_EXT_PHY_CNTL_1, MEDIA_OP_MODE_MASK,
  1749. MEDIA_OP_MODE_COPPER << MEDIA_OP_MODE_POS);
  1750. if (ret)
  1751. return ret;
  1752. ret = genphy_soft_reset(phydev);
  1753. if (ret)
  1754. return ret;
  1755. for (i = 0; i < vsc8531->nleds; i++) {
  1756. ret = vsc85xx_led_cntl_set(phydev, i, vsc8531->leds_mode[i]);
  1757. if (ret)
  1758. return ret;
  1759. }
  1760. return ret;
  1761. err:
  1762. phy_unlock_mdio_bus(phydev);
  1763. return ret;
  1764. }
  1765. static int vsc85xx_ack_interrupt(struct phy_device *phydev)
  1766. {
  1767. int rc = 0;
  1768. if (phydev->interrupts == PHY_INTERRUPT_ENABLED)
  1769. rc = phy_read(phydev, MII_VSC85XX_INT_STATUS);
  1770. return (rc < 0) ? rc : 0;
  1771. }
  1772. static int vsc85xx_config_intr(struct phy_device *phydev)
  1773. {
  1774. int rc;
  1775. if (phydev->interrupts == PHY_INTERRUPT_ENABLED) {
  1776. rc = vsc85xx_ack_interrupt(phydev);
  1777. if (rc)
  1778. return rc;
  1779. vsc8584_config_macsec_intr(phydev);
  1780. vsc8584_config_ts_intr(phydev);
  1781. rc = phy_write(phydev, MII_VSC85XX_INT_MASK,
  1782. MII_VSC85XX_INT_MASK_MASK);
  1783. } else {
  1784. rc = phy_write(phydev, MII_VSC85XX_INT_MASK, 0);
  1785. if (rc < 0)
  1786. return rc;
  1787. rc = phy_read(phydev, MII_VSC85XX_INT_STATUS);
  1788. if (rc < 0)
  1789. return rc;
  1790. rc = vsc85xx_ack_interrupt(phydev);
  1791. }
  1792. return rc;
  1793. }
  1794. static irqreturn_t vsc85xx_handle_interrupt(struct phy_device *phydev)
  1795. {
  1796. int irq_status;
  1797. irq_status = phy_read(phydev, MII_VSC85XX_INT_STATUS);
  1798. if (irq_status < 0) {
  1799. phy_error(phydev);
  1800. return IRQ_NONE;
  1801. }
  1802. if (!(irq_status & MII_VSC85XX_INT_MASK_MASK))
  1803. return IRQ_NONE;
  1804. phy_trigger_machine(phydev);
  1805. return IRQ_HANDLED;
  1806. }
  1807. static int vsc85xx_config_aneg(struct phy_device *phydev)
  1808. {
  1809. int rc;
  1810. rc = vsc85xx_mdix_set(phydev, phydev->mdix_ctrl);
  1811. if (rc < 0)
  1812. return rc;
  1813. return genphy_config_aneg(phydev);
  1814. }
  1815. static int vsc85xx_read_status(struct phy_device *phydev)
  1816. {
  1817. int rc;
  1818. rc = vsc85xx_mdix_get(phydev, &phydev->mdix);
  1819. if (rc < 0)
  1820. return rc;
  1821. return genphy_read_status(phydev);
  1822. }
  1823. static unsigned int vsc85xx_inband_caps(struct phy_device *phydev,
  1824. phy_interface_t interface)
  1825. {
  1826. if (interface != PHY_INTERFACE_MODE_SGMII &&
  1827. interface != PHY_INTERFACE_MODE_QSGMII)
  1828. return 0;
  1829. return LINK_INBAND_DISABLE | LINK_INBAND_ENABLE;
  1830. }
  1831. static int vsc85xx_config_inband(struct phy_device *phydev, unsigned int modes)
  1832. {
  1833. u16 reg_val = 0;
  1834. if (modes == LINK_INBAND_ENABLE)
  1835. reg_val = MSCC_PHY_SERDES_ANEG;
  1836. return phy_modify_paged(phydev, MSCC_PHY_PAGE_EXTENDED_3,
  1837. MSCC_PHY_SERDES_PCS_CTRL, MSCC_PHY_SERDES_ANEG,
  1838. reg_val);
  1839. }
  1840. static int vsc85xx_probe_common(struct phy_device *phydev,
  1841. const struct vsc85xx_probe_config *cfg,
  1842. const u32 *default_led_mode)
  1843. {
  1844. struct vsc8531_private *vsc8531;
  1845. struct device_node *np;
  1846. int ret;
  1847. vsc8531 = devm_kzalloc(&phydev->mdio.dev, sizeof(*vsc8531), GFP_KERNEL);
  1848. if (!vsc8531)
  1849. return -ENOMEM;
  1850. phydev->priv = vsc8531;
  1851. /* Check rate magic if needed (only for non-package PHYs) */
  1852. if (cfg->check_rate_magic) {
  1853. ret = vsc85xx_edge_rate_magic_get(phydev);
  1854. if (ret < 0)
  1855. return ret;
  1856. vsc8531->rate_magic = ret;
  1857. }
  1858. /* Set up package if needed */
  1859. if (cfg->use_package) {
  1860. vsc8584_get_base_addr(phydev);
  1861. ret = devm_phy_package_join(&phydev->mdio.dev, phydev,
  1862. vsc8531->base_addr,
  1863. cfg->shared_size);
  1864. if (ret)
  1865. return ret;
  1866. }
  1867. /* Configure LED settings */
  1868. vsc8531->nleds = cfg->nleds;
  1869. vsc8531->supp_led_modes = cfg->supp_led_modes;
  1870. /* Configure hardware stats */
  1871. vsc8531->hw_stats = cfg->hw_stats;
  1872. vsc8531->nstats = cfg->nstats;
  1873. vsc8531->stats = devm_kcalloc(&phydev->mdio.dev, vsc8531->nstats,
  1874. sizeof(u64), GFP_KERNEL);
  1875. if (!vsc8531->stats)
  1876. return -ENOMEM;
  1877. /* PTP setup for VSC8584 */
  1878. if (cfg->has_ptp) {
  1879. if (phy_package_probe_once(phydev)) {
  1880. ret = vsc8584_ptp_probe_once(phydev);
  1881. if (ret)
  1882. return ret;
  1883. }
  1884. ret = vsc8584_ptp_probe(phydev);
  1885. if (ret)
  1886. return ret;
  1887. }
  1888. /*
  1889. * Check for LED configuration in device tree if available
  1890. * or fall back to default `vsc8531,led-x-mode` DT properties.
  1891. */
  1892. np = of_get_child_by_name(phydev->mdio.dev.of_node, "leds");
  1893. if (np) {
  1894. of_node_put(np);
  1895. /* Force to defaults */
  1896. for (unsigned int i = 0; i < vsc8531->nleds; i++)
  1897. vsc8531->leds_mode[i] = default_led_mode[i];
  1898. return 0;
  1899. }
  1900. /* Parse LED modes from device tree */
  1901. return vsc85xx_dt_led_modes_get(phydev, default_led_mode);
  1902. }
  1903. static int vsc85xx_led_brightness_set(struct phy_device *phydev,
  1904. u8 index, enum led_brightness value)
  1905. {
  1906. struct vsc8531_private *vsc8531 = phydev->priv;
  1907. if (index >= vsc8531->nleds)
  1908. return -EINVAL;
  1909. return vsc85xx_led_cntl_set(phydev, index, value == LED_OFF ?
  1910. VSC8531_FORCE_LED_OFF : VSC8531_FORCE_LED_ON);
  1911. }
  1912. static int vsc85xx_led_hw_is_supported(struct phy_device *phydev, u8 index,
  1913. unsigned long rules)
  1914. {
  1915. static const unsigned long supported = BIT(TRIGGER_NETDEV_LINK_1000) |
  1916. BIT(TRIGGER_NETDEV_LINK_100) |
  1917. BIT(TRIGGER_NETDEV_LINK_10) |
  1918. BIT(TRIGGER_NETDEV_LINK) |
  1919. BIT(TRIGGER_NETDEV_RX) |
  1920. BIT(TRIGGER_NETDEV_TX);
  1921. struct vsc8531_private *vsc8531 = phydev->priv;
  1922. if (index >= vsc8531->nleds)
  1923. return -EINVAL;
  1924. if (rules & ~supported)
  1925. return -EOPNOTSUPP;
  1926. return 0;
  1927. }
  1928. static int vsc85xx_led_hw_control_get(struct phy_device *phydev, u8 index,
  1929. unsigned long *rules)
  1930. {
  1931. struct vsc8531_private *vsc8531 = phydev->priv;
  1932. u8 mode, behavior;
  1933. int rc;
  1934. if (index >= vsc8531->nleds)
  1935. return -EINVAL;
  1936. rc = phy_read(phydev, MSCC_PHY_LED_MODE_SEL);
  1937. if (rc < 0)
  1938. return rc;
  1939. mode = (rc & LED_MODE_SEL_MASK(index)) >> LED_MODE_SEL_POS(index);
  1940. rc = phy_read(phydev, MSCC_PHY_LED_BEHAVIOR);
  1941. if (rc < 0)
  1942. return rc;
  1943. behavior = (rc & LED_COMBINE_DIS_MASK(index)) >> index;
  1944. switch (mode) {
  1945. case VSC8531_LINK_ACTIVITY:
  1946. case VSC8531_ACTIVITY:
  1947. *rules = BIT(TRIGGER_NETDEV_LINK);
  1948. break;
  1949. case VSC8531_LINK_1000_ACTIVITY:
  1950. *rules = BIT(TRIGGER_NETDEV_LINK_1000) |
  1951. BIT(TRIGGER_NETDEV_LINK);
  1952. break;
  1953. case VSC8531_LINK_100_ACTIVITY:
  1954. *rules = BIT(TRIGGER_NETDEV_LINK_100) |
  1955. BIT(TRIGGER_NETDEV_LINK);
  1956. break;
  1957. case VSC8531_LINK_10_ACTIVITY:
  1958. *rules = BIT(TRIGGER_NETDEV_LINK_10) |
  1959. BIT(TRIGGER_NETDEV_LINK);
  1960. break;
  1961. case VSC8531_LINK_100_1000_ACTIVITY:
  1962. *rules = BIT(TRIGGER_NETDEV_LINK_1000) |
  1963. BIT(TRIGGER_NETDEV_LINK_100) |
  1964. BIT(TRIGGER_NETDEV_LINK);
  1965. break;
  1966. case VSC8531_LINK_10_1000_ACTIVITY:
  1967. *rules = BIT(TRIGGER_NETDEV_LINK_1000) |
  1968. BIT(TRIGGER_NETDEV_LINK_10) |
  1969. BIT(TRIGGER_NETDEV_LINK);
  1970. break;
  1971. case VSC8531_LINK_10_100_ACTIVITY:
  1972. *rules = BIT(TRIGGER_NETDEV_LINK_100) |
  1973. BIT(TRIGGER_NETDEV_LINK_10) |
  1974. BIT(TRIGGER_NETDEV_LINK);
  1975. break;
  1976. default:
  1977. *rules = 0;
  1978. break;
  1979. }
  1980. if (!behavior && *rules)
  1981. *rules |= BIT(TRIGGER_NETDEV_RX) | BIT(TRIGGER_NETDEV_TX);
  1982. return 0;
  1983. }
  1984. static int vsc85xx_led_hw_control_set(struct phy_device *phydev, u8 index,
  1985. unsigned long rules)
  1986. {
  1987. struct vsc8531_private *vsc8531 = phydev->priv;
  1988. u8 mode = VSC8531_FORCE_LED_ON;
  1989. bool combine_disable = false;
  1990. bool has_rx, has_tx;
  1991. int ret;
  1992. if (index >= vsc8531->nleds)
  1993. return -EINVAL;
  1994. if (rules & BIT(TRIGGER_NETDEV_LINK))
  1995. mode = VSC8531_LINK_ACTIVITY;
  1996. if (rules & BIT(TRIGGER_NETDEV_LINK_10))
  1997. mode = VSC8531_LINK_10_ACTIVITY;
  1998. if (rules & BIT(TRIGGER_NETDEV_LINK_100))
  1999. mode = VSC8531_LINK_100_ACTIVITY;
  2000. if (rules & BIT(TRIGGER_NETDEV_LINK_1000))
  2001. mode = VSC8531_LINK_1000_ACTIVITY;
  2002. if (rules & BIT(TRIGGER_NETDEV_LINK_100) &&
  2003. rules & BIT(TRIGGER_NETDEV_LINK_1000))
  2004. mode = VSC8531_LINK_100_1000_ACTIVITY;
  2005. if (rules & BIT(TRIGGER_NETDEV_LINK_10) &&
  2006. rules & BIT(TRIGGER_NETDEV_LINK_1000))
  2007. mode = VSC8531_LINK_10_1000_ACTIVITY;
  2008. if (rules & BIT(TRIGGER_NETDEV_LINK_10) &&
  2009. rules & BIT(TRIGGER_NETDEV_LINK_100))
  2010. mode = VSC8531_LINK_10_100_ACTIVITY;
  2011. /*
  2012. * The VSC85xx PHYs provides an option to control LED behavior. By
  2013. * default, the LEDx combine function is enabled, meaning the LED
  2014. * will be on when there is link/activity or duplex/collision. If
  2015. * the combine function is disabled, the LED will be on only for
  2016. * link or duplex.
  2017. *
  2018. * To control this behavior, we check the selected rules. If both
  2019. * RX and TX activity are not selected, the LED combine function
  2020. * is disabled; otherwise, it remains enabled.
  2021. */
  2022. has_rx = !!(rules & BIT(TRIGGER_NETDEV_RX));
  2023. has_tx = !!(rules & BIT(TRIGGER_NETDEV_TX));
  2024. if (!has_rx && !has_tx)
  2025. combine_disable = true;
  2026. ret = vsc85xx_led_combine_disable_set(phydev, index, combine_disable);
  2027. if (ret < 0)
  2028. return ret;
  2029. return vsc85xx_led_cntl_set(phydev, index, mode);
  2030. }
  2031. static int vsc8514_probe(struct phy_device *phydev)
  2032. {
  2033. static const struct vsc85xx_probe_config vsc8514_cfg = {
  2034. .nleds = 4,
  2035. .supp_led_modes = VSC85XX_SUPP_LED_MODES,
  2036. .hw_stats = vsc85xx_hw_stats,
  2037. .nstats = ARRAY_SIZE(vsc85xx_hw_stats),
  2038. .use_package = true,
  2039. .shared_size = 0,
  2040. .has_ptp = false,
  2041. .check_rate_magic = false,
  2042. };
  2043. return vsc85xx_probe_common(phydev, &vsc8514_cfg, vsc85xx_default_led_modes_4);
  2044. }
  2045. static int vsc8574_probe(struct phy_device *phydev)
  2046. {
  2047. static const struct vsc85xx_probe_config vsc8574_cfg = {
  2048. .nleds = 4,
  2049. .supp_led_modes = VSC8584_SUPP_LED_MODES,
  2050. .hw_stats = vsc8584_hw_stats,
  2051. .nstats = ARRAY_SIZE(vsc8584_hw_stats),
  2052. .use_package = true,
  2053. .shared_size = 0,
  2054. .has_ptp = false,
  2055. .check_rate_magic = false,
  2056. };
  2057. return vsc85xx_probe_common(phydev, &vsc8574_cfg, vsc85xx_default_led_modes_4);
  2058. }
  2059. static int vsc8584_probe(struct phy_device *phydev)
  2060. {
  2061. static const struct vsc85xx_probe_config vsc8584_cfg = {
  2062. .nleds = 4,
  2063. .supp_led_modes = VSC8584_SUPP_LED_MODES,
  2064. .hw_stats = vsc8584_hw_stats,
  2065. .nstats = ARRAY_SIZE(vsc8584_hw_stats),
  2066. .use_package = true,
  2067. .shared_size = sizeof(struct vsc85xx_shared_private),
  2068. .has_ptp = true,
  2069. .check_rate_magic = false,
  2070. };
  2071. return vsc85xx_probe_common(phydev, &vsc8584_cfg, vsc85xx_default_led_modes_4);
  2072. }
  2073. static int vsc85xx_probe(struct phy_device *phydev)
  2074. {
  2075. static const struct vsc85xx_probe_config vsc85xx_cfg = {
  2076. .nleds = 2,
  2077. .supp_led_modes = VSC85XX_SUPP_LED_MODES,
  2078. .hw_stats = vsc85xx_hw_stats,
  2079. .nstats = ARRAY_SIZE(vsc85xx_hw_stats),
  2080. .use_package = false,
  2081. .has_ptp = false,
  2082. .check_rate_magic = true,
  2083. };
  2084. return vsc85xx_probe_common(phydev, &vsc85xx_cfg, vsc85xx_default_led_modes_4);
  2085. }
  2086. static void vsc85xx_remove(struct phy_device *phydev)
  2087. {
  2088. vsc8584_ptp_deinit(phydev);
  2089. }
  2090. /* Microsemi VSC85xx PHYs */
  2091. static struct phy_driver vsc85xx_driver[] = {
  2092. {
  2093. .phy_id = PHY_ID_VSC8501,
  2094. .name = "Microsemi GE VSC8501 SyncE",
  2095. .phy_id_mask = 0xfffffff0,
  2096. /* PHY_BASIC_FEATURES */
  2097. .soft_reset = &genphy_soft_reset,
  2098. .config_init = &vsc85xx_config_init,
  2099. .config_aneg = &vsc85xx_config_aneg,
  2100. .read_status = &vsc85xx_read_status,
  2101. .handle_interrupt = vsc85xx_handle_interrupt,
  2102. .config_intr = &vsc85xx_config_intr,
  2103. .suspend = &genphy_suspend,
  2104. .resume = &genphy_resume,
  2105. .probe = &vsc85xx_probe,
  2106. .set_wol = &vsc85xx_wol_set,
  2107. .get_wol = &vsc85xx_wol_get,
  2108. .get_tunable = &vsc85xx_get_tunable,
  2109. .set_tunable = &vsc85xx_set_tunable,
  2110. .read_page = &vsc85xx_phy_read_page,
  2111. .write_page = &vsc85xx_phy_write_page,
  2112. .get_sset_count = &vsc85xx_get_sset_count,
  2113. .get_strings = &vsc85xx_get_strings,
  2114. .get_stats = &vsc85xx_get_stats,
  2115. .led_brightness_set = vsc85xx_led_brightness_set,
  2116. .led_hw_is_supported = vsc85xx_led_hw_is_supported,
  2117. .led_hw_control_get = vsc85xx_led_hw_control_get,
  2118. .led_hw_control_set = vsc85xx_led_hw_control_set,
  2119. },
  2120. {
  2121. .phy_id = PHY_ID_VSC8502,
  2122. .name = "Microsemi GE VSC8502 SyncE",
  2123. .phy_id_mask = 0xfffffff0,
  2124. /* PHY_BASIC_FEATURES */
  2125. .soft_reset = &genphy_soft_reset,
  2126. .config_init = &vsc85xx_config_init,
  2127. .config_aneg = &vsc85xx_config_aneg,
  2128. .read_status = &vsc85xx_read_status,
  2129. .handle_interrupt = vsc85xx_handle_interrupt,
  2130. .config_intr = &vsc85xx_config_intr,
  2131. .suspend = &genphy_suspend,
  2132. .resume = &genphy_resume,
  2133. .probe = &vsc85xx_probe,
  2134. .set_wol = &vsc85xx_wol_set,
  2135. .get_wol = &vsc85xx_wol_get,
  2136. .get_tunable = &vsc85xx_get_tunable,
  2137. .set_tunable = &vsc85xx_set_tunable,
  2138. .read_page = &vsc85xx_phy_read_page,
  2139. .write_page = &vsc85xx_phy_write_page,
  2140. .get_sset_count = &vsc85xx_get_sset_count,
  2141. .get_strings = &vsc85xx_get_strings,
  2142. .get_stats = &vsc85xx_get_stats,
  2143. .led_brightness_set = vsc85xx_led_brightness_set,
  2144. .led_hw_is_supported = vsc85xx_led_hw_is_supported,
  2145. .led_hw_control_get = vsc85xx_led_hw_control_get,
  2146. .led_hw_control_set = vsc85xx_led_hw_control_set,
  2147. },
  2148. {
  2149. .phy_id = PHY_ID_VSC8504,
  2150. .name = "Microsemi GE VSC8504 SyncE",
  2151. .phy_id_mask = 0xfffffff0,
  2152. /* PHY_GBIT_FEATURES */
  2153. .soft_reset = &genphy_soft_reset,
  2154. .config_init = &vsc8584_config_init,
  2155. .config_aneg = &vsc85xx_config_aneg,
  2156. .aneg_done = &genphy_aneg_done,
  2157. .read_status = &vsc85xx_read_status,
  2158. .handle_interrupt = vsc85xx_handle_interrupt,
  2159. .config_intr = &vsc85xx_config_intr,
  2160. .suspend = &genphy_suspend,
  2161. .resume = &genphy_resume,
  2162. .probe = &vsc8574_probe,
  2163. .set_wol = &vsc85xx_wol_set,
  2164. .get_wol = &vsc85xx_wol_get,
  2165. .get_tunable = &vsc85xx_get_tunable,
  2166. .set_tunable = &vsc85xx_set_tunable,
  2167. .read_page = &vsc85xx_phy_read_page,
  2168. .write_page = &vsc85xx_phy_write_page,
  2169. .get_sset_count = &vsc85xx_get_sset_count,
  2170. .get_strings = &vsc85xx_get_strings,
  2171. .get_stats = &vsc85xx_get_stats,
  2172. .inband_caps = vsc85xx_inband_caps,
  2173. .config_inband = vsc85xx_config_inband,
  2174. .led_brightness_set = vsc85xx_led_brightness_set,
  2175. .led_hw_is_supported = vsc85xx_led_hw_is_supported,
  2176. .led_hw_control_get = vsc85xx_led_hw_control_get,
  2177. .led_hw_control_set = vsc85xx_led_hw_control_set,
  2178. },
  2179. {
  2180. .phy_id = PHY_ID_VSC8514,
  2181. .name = "Microsemi GE VSC8514 SyncE",
  2182. .phy_id_mask = 0xfffffff0,
  2183. .soft_reset = &genphy_soft_reset,
  2184. .config_init = &vsc8514_config_init,
  2185. .config_aneg = &vsc85xx_config_aneg,
  2186. .read_status = &vsc85xx_read_status,
  2187. .handle_interrupt = vsc85xx_handle_interrupt,
  2188. .config_intr = &vsc85xx_config_intr,
  2189. .suspend = &genphy_suspend,
  2190. .resume = &genphy_resume,
  2191. .probe = &vsc8514_probe,
  2192. .set_wol = &vsc85xx_wol_set,
  2193. .get_wol = &vsc85xx_wol_get,
  2194. .get_tunable = &vsc85xx_get_tunable,
  2195. .set_tunable = &vsc85xx_set_tunable,
  2196. .read_page = &vsc85xx_phy_read_page,
  2197. .write_page = &vsc85xx_phy_write_page,
  2198. .get_sset_count = &vsc85xx_get_sset_count,
  2199. .get_strings = &vsc85xx_get_strings,
  2200. .get_stats = &vsc85xx_get_stats,
  2201. .inband_caps = vsc85xx_inband_caps,
  2202. .config_inband = vsc85xx_config_inband,
  2203. .led_brightness_set = vsc85xx_led_brightness_set,
  2204. .led_hw_is_supported = vsc85xx_led_hw_is_supported,
  2205. .led_hw_control_get = vsc85xx_led_hw_control_get,
  2206. .led_hw_control_set = vsc85xx_led_hw_control_set,
  2207. },
  2208. {
  2209. .phy_id = PHY_ID_VSC8530,
  2210. .name = "Microsemi FE VSC8530",
  2211. .phy_id_mask = 0xfffffff0,
  2212. /* PHY_BASIC_FEATURES */
  2213. .soft_reset = &genphy_soft_reset,
  2214. .config_init = &vsc85xx_config_init,
  2215. .config_aneg = &vsc85xx_config_aneg,
  2216. .read_status = &vsc85xx_read_status,
  2217. .handle_interrupt = vsc85xx_handle_interrupt,
  2218. .config_intr = &vsc85xx_config_intr,
  2219. .suspend = &genphy_suspend,
  2220. .resume = &genphy_resume,
  2221. .probe = &vsc85xx_probe,
  2222. .set_wol = &vsc85xx_wol_set,
  2223. .get_wol = &vsc85xx_wol_get,
  2224. .get_tunable = &vsc85xx_get_tunable,
  2225. .set_tunable = &vsc85xx_set_tunable,
  2226. .read_page = &vsc85xx_phy_read_page,
  2227. .write_page = &vsc85xx_phy_write_page,
  2228. .get_sset_count = &vsc85xx_get_sset_count,
  2229. .get_strings = &vsc85xx_get_strings,
  2230. .get_stats = &vsc85xx_get_stats,
  2231. .led_brightness_set = vsc85xx_led_brightness_set,
  2232. .led_hw_is_supported = vsc85xx_led_hw_is_supported,
  2233. .led_hw_control_get = vsc85xx_led_hw_control_get,
  2234. .led_hw_control_set = vsc85xx_led_hw_control_set,
  2235. },
  2236. {
  2237. .phy_id = PHY_ID_VSC8531,
  2238. .name = "Microsemi VSC8531",
  2239. .phy_id_mask = 0xfffffff0,
  2240. /* PHY_GBIT_FEATURES */
  2241. .soft_reset = &genphy_soft_reset,
  2242. .config_init = &vsc85xx_config_init,
  2243. .config_aneg = &vsc85xx_config_aneg,
  2244. .read_status = &vsc85xx_read_status,
  2245. .handle_interrupt = vsc85xx_handle_interrupt,
  2246. .config_intr = &vsc85xx_config_intr,
  2247. .suspend = &genphy_suspend,
  2248. .resume = &genphy_resume,
  2249. .probe = &vsc85xx_probe,
  2250. .set_wol = &vsc85xx_wol_set,
  2251. .get_wol = &vsc85xx_wol_get,
  2252. .get_tunable = &vsc85xx_get_tunable,
  2253. .set_tunable = &vsc85xx_set_tunable,
  2254. .read_page = &vsc85xx_phy_read_page,
  2255. .write_page = &vsc85xx_phy_write_page,
  2256. .get_sset_count = &vsc85xx_get_sset_count,
  2257. .get_strings = &vsc85xx_get_strings,
  2258. .get_stats = &vsc85xx_get_stats,
  2259. .led_brightness_set = vsc85xx_led_brightness_set,
  2260. .led_hw_is_supported = vsc85xx_led_hw_is_supported,
  2261. .led_hw_control_get = vsc85xx_led_hw_control_get,
  2262. .led_hw_control_set = vsc85xx_led_hw_control_set,
  2263. },
  2264. {
  2265. .phy_id = PHY_ID_VSC8540,
  2266. .name = "Microsemi FE VSC8540 SyncE",
  2267. .phy_id_mask = 0xfffffff0,
  2268. /* PHY_BASIC_FEATURES */
  2269. .soft_reset = &genphy_soft_reset,
  2270. .config_init = &vsc85xx_config_init,
  2271. .config_aneg = &vsc85xx_config_aneg,
  2272. .read_status = &vsc85xx_read_status,
  2273. .handle_interrupt = vsc85xx_handle_interrupt,
  2274. .config_intr = &vsc85xx_config_intr,
  2275. .suspend = &genphy_suspend,
  2276. .resume = &genphy_resume,
  2277. .probe = &vsc85xx_probe,
  2278. .set_wol = &vsc85xx_wol_set,
  2279. .get_wol = &vsc85xx_wol_get,
  2280. .get_tunable = &vsc85xx_get_tunable,
  2281. .set_tunable = &vsc85xx_set_tunable,
  2282. .read_page = &vsc85xx_phy_read_page,
  2283. .write_page = &vsc85xx_phy_write_page,
  2284. .get_sset_count = &vsc85xx_get_sset_count,
  2285. .get_strings = &vsc85xx_get_strings,
  2286. .get_stats = &vsc85xx_get_stats,
  2287. .led_brightness_set = vsc85xx_led_brightness_set,
  2288. .led_hw_is_supported = vsc85xx_led_hw_is_supported,
  2289. .led_hw_control_get = vsc85xx_led_hw_control_get,
  2290. .led_hw_control_set = vsc85xx_led_hw_control_set,
  2291. },
  2292. {
  2293. .phy_id = PHY_ID_VSC8541,
  2294. .name = "Microsemi VSC8541 SyncE",
  2295. .phy_id_mask = 0xfffffff0,
  2296. /* PHY_GBIT_FEATURES */
  2297. .soft_reset = &genphy_soft_reset,
  2298. .config_init = &vsc85xx_config_init,
  2299. .config_aneg = &vsc85xx_config_aneg,
  2300. .read_status = &vsc85xx_read_status,
  2301. .handle_interrupt = vsc85xx_handle_interrupt,
  2302. .config_intr = &vsc85xx_config_intr,
  2303. .suspend = &genphy_suspend,
  2304. .resume = &genphy_resume,
  2305. .probe = &vsc85xx_probe,
  2306. .set_wol = &vsc85xx_wol_set,
  2307. .get_wol = &vsc85xx_wol_get,
  2308. .get_tunable = &vsc85xx_get_tunable,
  2309. .set_tunable = &vsc85xx_set_tunable,
  2310. .read_page = &vsc85xx_phy_read_page,
  2311. .write_page = &vsc85xx_phy_write_page,
  2312. .get_sset_count = &vsc85xx_get_sset_count,
  2313. .get_strings = &vsc85xx_get_strings,
  2314. .get_stats = &vsc85xx_get_stats,
  2315. .led_brightness_set = vsc85xx_led_brightness_set,
  2316. .led_hw_is_supported = vsc85xx_led_hw_is_supported,
  2317. .led_hw_control_get = vsc85xx_led_hw_control_get,
  2318. .led_hw_control_set = vsc85xx_led_hw_control_set,
  2319. },
  2320. {
  2321. .phy_id = PHY_ID_VSC8552,
  2322. .name = "Microsemi GE VSC8552 SyncE",
  2323. .phy_id_mask = 0xfffffff0,
  2324. /* PHY_GBIT_FEATURES */
  2325. .soft_reset = &genphy_soft_reset,
  2326. .config_init = &vsc8584_config_init,
  2327. .config_aneg = &vsc85xx_config_aneg,
  2328. .read_status = &vsc85xx_read_status,
  2329. .handle_interrupt = vsc85xx_handle_interrupt,
  2330. .config_intr = &vsc85xx_config_intr,
  2331. .suspend = &genphy_suspend,
  2332. .resume = &genphy_resume,
  2333. .probe = &vsc8574_probe,
  2334. .set_wol = &vsc85xx_wol_set,
  2335. .get_wol = &vsc85xx_wol_get,
  2336. .get_tunable = &vsc85xx_get_tunable,
  2337. .set_tunable = &vsc85xx_set_tunable,
  2338. .read_page = &vsc85xx_phy_read_page,
  2339. .write_page = &vsc85xx_phy_write_page,
  2340. .get_sset_count = &vsc85xx_get_sset_count,
  2341. .get_strings = &vsc85xx_get_strings,
  2342. .get_stats = &vsc85xx_get_stats,
  2343. .inband_caps = vsc85xx_inband_caps,
  2344. .config_inband = vsc85xx_config_inband,
  2345. .led_brightness_set = vsc85xx_led_brightness_set,
  2346. .led_hw_is_supported = vsc85xx_led_hw_is_supported,
  2347. .led_hw_control_get = vsc85xx_led_hw_control_get,
  2348. .led_hw_control_set = vsc85xx_led_hw_control_set,
  2349. },
  2350. {
  2351. PHY_ID_MATCH_EXACT(PHY_ID_VSC856X),
  2352. .name = "Microsemi GE VSC856X SyncE",
  2353. /* PHY_GBIT_FEATURES */
  2354. .soft_reset = &genphy_soft_reset,
  2355. .config_init = &vsc8584_config_init,
  2356. .config_aneg = &vsc85xx_config_aneg,
  2357. .read_status = &vsc85xx_read_status,
  2358. .handle_interrupt = vsc85xx_handle_interrupt,
  2359. .config_intr = &vsc85xx_config_intr,
  2360. .suspend = &genphy_suspend,
  2361. .resume = &genphy_resume,
  2362. .probe = &vsc8584_probe,
  2363. .get_tunable = &vsc85xx_get_tunable,
  2364. .set_tunable = &vsc85xx_set_tunable,
  2365. .read_page = &vsc85xx_phy_read_page,
  2366. .write_page = &vsc85xx_phy_write_page,
  2367. .get_sset_count = &vsc85xx_get_sset_count,
  2368. .get_strings = &vsc85xx_get_strings,
  2369. .get_stats = &vsc85xx_get_stats,
  2370. .inband_caps = vsc85xx_inband_caps,
  2371. .config_inband = vsc85xx_config_inband,
  2372. .led_brightness_set = vsc85xx_led_brightness_set,
  2373. .led_hw_is_supported = vsc85xx_led_hw_is_supported,
  2374. .led_hw_control_get = vsc85xx_led_hw_control_get,
  2375. .led_hw_control_set = vsc85xx_led_hw_control_set,
  2376. },
  2377. {
  2378. .phy_id = PHY_ID_VSC8572,
  2379. .name = "Microsemi GE VSC8572 SyncE",
  2380. .phy_id_mask = 0xfffffff0,
  2381. /* PHY_GBIT_FEATURES */
  2382. .soft_reset = &genphy_soft_reset,
  2383. .config_init = &vsc8584_config_init,
  2384. .config_aneg = &vsc85xx_config_aneg,
  2385. .aneg_done = &genphy_aneg_done,
  2386. .read_status = &vsc85xx_read_status,
  2387. .handle_interrupt = &vsc8584_handle_interrupt,
  2388. .config_intr = &vsc85xx_config_intr,
  2389. .suspend = &genphy_suspend,
  2390. .resume = &genphy_resume,
  2391. .remove = &vsc85xx_remove,
  2392. .probe = &vsc8584_probe,
  2393. .set_wol = &vsc85xx_wol_set,
  2394. .get_wol = &vsc85xx_wol_get,
  2395. .get_tunable = &vsc85xx_get_tunable,
  2396. .set_tunable = &vsc85xx_set_tunable,
  2397. .read_page = &vsc85xx_phy_read_page,
  2398. .write_page = &vsc85xx_phy_write_page,
  2399. .get_sset_count = &vsc85xx_get_sset_count,
  2400. .get_strings = &vsc85xx_get_strings,
  2401. .get_stats = &vsc85xx_get_stats,
  2402. .inband_caps = vsc85xx_inband_caps,
  2403. .config_inband = vsc85xx_config_inband,
  2404. .led_brightness_set = vsc85xx_led_brightness_set,
  2405. .led_hw_is_supported = vsc85xx_led_hw_is_supported,
  2406. .led_hw_control_get = vsc85xx_led_hw_control_get,
  2407. .led_hw_control_set = vsc85xx_led_hw_control_set,
  2408. },
  2409. {
  2410. .phy_id = PHY_ID_VSC8574,
  2411. .name = "Microsemi GE VSC8574 SyncE",
  2412. .phy_id_mask = 0xfffffff0,
  2413. /* PHY_GBIT_FEATURES */
  2414. .soft_reset = &genphy_soft_reset,
  2415. .config_init = &vsc8584_config_init,
  2416. .config_aneg = &vsc85xx_config_aneg,
  2417. .aneg_done = &genphy_aneg_done,
  2418. .read_status = &vsc85xx_read_status,
  2419. .handle_interrupt = vsc8584_handle_interrupt,
  2420. .config_intr = &vsc85xx_config_intr,
  2421. .suspend = &genphy_suspend,
  2422. .resume = &genphy_resume,
  2423. .remove = &vsc85xx_remove,
  2424. .probe = &vsc8584_probe,
  2425. .set_wol = &vsc85xx_wol_set,
  2426. .get_wol = &vsc85xx_wol_get,
  2427. .get_tunable = &vsc85xx_get_tunable,
  2428. .set_tunable = &vsc85xx_set_tunable,
  2429. .read_page = &vsc85xx_phy_read_page,
  2430. .write_page = &vsc85xx_phy_write_page,
  2431. .get_sset_count = &vsc85xx_get_sset_count,
  2432. .get_strings = &vsc85xx_get_strings,
  2433. .get_stats = &vsc85xx_get_stats,
  2434. .inband_caps = vsc85xx_inband_caps,
  2435. .config_inband = vsc85xx_config_inband,
  2436. .led_brightness_set = vsc85xx_led_brightness_set,
  2437. .led_hw_is_supported = vsc85xx_led_hw_is_supported,
  2438. .led_hw_control_get = vsc85xx_led_hw_control_get,
  2439. .led_hw_control_set = vsc85xx_led_hw_control_set,
  2440. },
  2441. {
  2442. PHY_ID_MATCH_EXACT(PHY_ID_VSC8575),
  2443. .name = "Microsemi GE VSC8575 SyncE",
  2444. /* PHY_GBIT_FEATURES */
  2445. .soft_reset = &genphy_soft_reset,
  2446. .config_init = &vsc8584_config_init,
  2447. .config_aneg = &vsc85xx_config_aneg,
  2448. .aneg_done = &genphy_aneg_done,
  2449. .read_status = &vsc85xx_read_status,
  2450. .handle_interrupt = &vsc8584_handle_interrupt,
  2451. .config_intr = &vsc85xx_config_intr,
  2452. .suspend = &genphy_suspend,
  2453. .resume = &genphy_resume,
  2454. .remove = &vsc85xx_remove,
  2455. .probe = &vsc8584_probe,
  2456. .get_tunable = &vsc85xx_get_tunable,
  2457. .set_tunable = &vsc85xx_set_tunable,
  2458. .read_page = &vsc85xx_phy_read_page,
  2459. .write_page = &vsc85xx_phy_write_page,
  2460. .get_sset_count = &vsc85xx_get_sset_count,
  2461. .get_strings = &vsc85xx_get_strings,
  2462. .get_stats = &vsc85xx_get_stats,
  2463. .inband_caps = vsc85xx_inband_caps,
  2464. .config_inband = vsc85xx_config_inband,
  2465. .led_brightness_set = vsc85xx_led_brightness_set,
  2466. .led_hw_is_supported = vsc85xx_led_hw_is_supported,
  2467. .led_hw_control_get = vsc85xx_led_hw_control_get,
  2468. .led_hw_control_set = vsc85xx_led_hw_control_set,
  2469. },
  2470. {
  2471. PHY_ID_MATCH_EXACT(PHY_ID_VSC8582),
  2472. .name = "Microsemi GE VSC8582 SyncE",
  2473. /* PHY_GBIT_FEATURES */
  2474. .soft_reset = &genphy_soft_reset,
  2475. .config_init = &vsc8584_config_init,
  2476. .config_aneg = &vsc85xx_config_aneg,
  2477. .aneg_done = &genphy_aneg_done,
  2478. .read_status = &vsc85xx_read_status,
  2479. .handle_interrupt = &vsc8584_handle_interrupt,
  2480. .config_intr = &vsc85xx_config_intr,
  2481. .suspend = &genphy_suspend,
  2482. .resume = &genphy_resume,
  2483. .remove = &vsc85xx_remove,
  2484. .probe = &vsc8584_probe,
  2485. .get_tunable = &vsc85xx_get_tunable,
  2486. .set_tunable = &vsc85xx_set_tunable,
  2487. .read_page = &vsc85xx_phy_read_page,
  2488. .write_page = &vsc85xx_phy_write_page,
  2489. .get_sset_count = &vsc85xx_get_sset_count,
  2490. .get_strings = &vsc85xx_get_strings,
  2491. .get_stats = &vsc85xx_get_stats,
  2492. .inband_caps = vsc85xx_inband_caps,
  2493. .config_inband = vsc85xx_config_inband,
  2494. .led_brightness_set = vsc85xx_led_brightness_set,
  2495. .led_hw_is_supported = vsc85xx_led_hw_is_supported,
  2496. .led_hw_control_get = vsc85xx_led_hw_control_get,
  2497. .led_hw_control_set = vsc85xx_led_hw_control_set,
  2498. },
  2499. {
  2500. PHY_ID_MATCH_EXACT(PHY_ID_VSC8584),
  2501. .name = "Microsemi GE VSC8584 SyncE",
  2502. /* PHY_GBIT_FEATURES */
  2503. .soft_reset = &genphy_soft_reset,
  2504. .config_init = &vsc8584_config_init,
  2505. .config_aneg = &vsc85xx_config_aneg,
  2506. .aneg_done = &genphy_aneg_done,
  2507. .read_status = &vsc85xx_read_status,
  2508. .handle_interrupt = &vsc8584_handle_interrupt,
  2509. .config_intr = &vsc85xx_config_intr,
  2510. .suspend = &genphy_suspend,
  2511. .resume = &genphy_resume,
  2512. .remove = &vsc85xx_remove,
  2513. .probe = &vsc8584_probe,
  2514. .get_tunable = &vsc85xx_get_tunable,
  2515. .set_tunable = &vsc85xx_set_tunable,
  2516. .read_page = &vsc85xx_phy_read_page,
  2517. .write_page = &vsc85xx_phy_write_page,
  2518. .get_sset_count = &vsc85xx_get_sset_count,
  2519. .get_strings = &vsc85xx_get_strings,
  2520. .get_stats = &vsc85xx_get_stats,
  2521. .link_change_notify = &vsc85xx_link_change_notify,
  2522. .inband_caps = vsc85xx_inband_caps,
  2523. .config_inband = vsc85xx_config_inband,
  2524. .led_brightness_set = vsc85xx_led_brightness_set,
  2525. .led_hw_is_supported = vsc85xx_led_hw_is_supported,
  2526. .led_hw_control_get = vsc85xx_led_hw_control_get,
  2527. .led_hw_control_set = vsc85xx_led_hw_control_set,
  2528. }
  2529. };
  2530. module_phy_driver(vsc85xx_driver);
  2531. static const struct mdio_device_id __maybe_unused vsc85xx_tbl[] = {
  2532. { PHY_ID_MATCH_VENDOR(PHY_VENDOR_MSCC) },
  2533. { }
  2534. };
  2535. MODULE_DEVICE_TABLE(mdio, vsc85xx_tbl);
  2536. MODULE_DESCRIPTION("Microsemi VSC85xx PHY driver");
  2537. MODULE_AUTHOR("Nagaraju Lakkaraju");
  2538. MODULE_LICENSE("Dual MIT/GPL");
  2539. MODULE_FIRMWARE(MSCC_VSC8584_REVB_INT8051_FW);
  2540. MODULE_FIRMWARE(MSCC_VSC8574_REVB_INT8051_FW);