mscc.c 54 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586
  1. // SPDX-License-Identifier: MIT
  2. /*
  3. * Microsemi PHY drivers
  4. *
  5. *
  6. * Copyright (c) 2016 Microsemi Corporation
  7. *
  8. * Author: John Haechten
  9. *
  10. */
  11. #include <log.h>
  12. #include <miiphy.h>
  13. #include <bitfield.h>
  14. #include <time.h>
  15. #include <linux/bitops.h>
  16. #include <linux/delay.h>
  17. /* Microsemi PHY ID's */
  18. #define PHY_ID_VSC8530 0x00070560
  19. #define PHY_ID_VSC8531 0x00070570
  20. #define PHY_ID_VSC8540 0x00070760
  21. #define PHY_ID_VSC8541 0x00070770
  22. #define PHY_ID_VSC8574 0x000704a0
  23. #define PHY_ID_VSC8584 0x000707c0
  24. /* Microsemi VSC85xx PHY Register Pages */
  25. #define MSCC_EXT_PAGE_ACCESS 31 /* Page Access Register */
  26. #define MSCC_PHY_PAGE_STD 0x0000 /* Standard registers */
  27. #define MSCC_PHY_PAGE_EXT1 0x0001 /* Extended registers - page 1 */
  28. #define MSCC_PHY_PAGE_EXT2 0x0002 /* Extended registers - page 2 */
  29. #define MSCC_PHY_PAGE_EXT3 0x0003 /* Extended registers - page 3 */
  30. #define MSCC_PHY_PAGE_EXT4 0x0004 /* Extended registers - page 4 */
  31. #define MSCC_PHY_PAGE_GPIO 0x0010 /* GPIO registers */
  32. #define MSCC_PHY_PAGE_TEST 0x2A30 /* TEST Page registers */
  33. #define MSCC_PHY_PAGE_TR 0x52B5 /* Token Ring Page registers */
  34. /* Std Page Register 18 */
  35. #define MSCC_PHY_BYPASS_CONTROL 18
  36. #define PARALLEL_DET_IGNORE_ADVERTISED BIT(3)
  37. /* Std Page Register 22 */
  38. #define MSCC_PHY_EXT_CNTL_STATUS 22
  39. #define SMI_BROADCAST_WR_EN BIT(0)
  40. /* Std Page Register 24 */
  41. #define MSCC_PHY_EXT_PHY_CNTL_2 24
  42. /* Std Page Register 28 - PHY AUX Control/Status */
  43. #define MIIM_AUX_CNTRL_STAT_REG 28
  44. #define MIIM_AUX_CNTRL_STAT_ACTIPHY_TO (0x0004)
  45. #define MIIM_AUX_CNTRL_STAT_F_DUPLEX (0x0020)
  46. #define MIIM_AUX_CNTRL_STAT_SPEED_MASK (0x0018)
  47. #define MIIM_AUX_CNTRL_STAT_SPEED_POS (3)
  48. #define MIIM_AUX_CNTRL_STAT_SPEED_10M (0x0)
  49. #define MIIM_AUX_CNTRL_STAT_SPEED_100M (0x1)
  50. #define MIIM_AUX_CNTRL_STAT_SPEED_1000M (0x2)
  51. /* Std Page Register 23 - Extended PHY CTRL_1 */
  52. #define MSCC_PHY_EXT_PHY_CNTL_1_REG 23
  53. #define MAC_IF_SELECTION_MASK (0x1800)
  54. #define MAC_IF_SELECTION_GMII (0)
  55. #define MAC_IF_SELECTION_RMII (1)
  56. #define MAC_IF_SELECTION_RGMII (2)
  57. #define MAC_IF_SELECTION_POS (11)
  58. #define MAC_IF_SELECTION_WIDTH (2)
  59. #define VSC8584_MAC_IF_SELECTION_MASK BIT(12)
  60. #define VSC8584_MAC_IF_SELECTION_SGMII 0
  61. #define VSC8584_MAC_IF_SELECTION_1000BASEX 1
  62. #define VSC8584_MAC_IF_SELECTION_POS 12
  63. #define MEDIA_OP_MODE_MASK GENMASK(10, 8)
  64. #define MEDIA_OP_MODE_COPPER 0
  65. #define MEDIA_OP_MODE_SERDES 1
  66. #define MEDIA_OP_MODE_1000BASEX 2
  67. #define MEDIA_OP_MODE_100BASEFX 3
  68. #define MEDIA_OP_MODE_AMS_COPPER_SERDES 5
  69. #define MEDIA_OP_MODE_AMS_COPPER_1000BASEX 6
  70. #define MEDIA_OP_MODE_AMS_COPPER_100BASEFX 7
  71. #define MEDIA_OP_MODE_POS 8
  72. /* Extended Page 1 Register 20E1 */
  73. #define MSCC_PHY_ACTIPHY_CNTL 20
  74. #define PHY_ADDR_REVERSED BIT(9)
  75. /* Extended Page 1 Register 23E1 */
  76. #define MSCC_PHY_EXT_PHY_CNTL_4 23
  77. #define PHY_CNTL_4_ADDR_POS 11
  78. /* Extended Page 1 Register 25E1 */
  79. #define MSCC_PHY_VERIPHY_CNTL_2 25
  80. /* Extended Page 1 Register 26E1 */
  81. #define MSCC_PHY_VERIPHY_CNTL_3 26
  82. /* Extended Page 2 Register 16E2 */
  83. #define MSCC_PHY_CU_PMD_TX_CNTL 16
  84. /* Extended Page 2 Register 20E2 */
  85. #define MSCC_PHY_RGMII_CNTL_REG 20
  86. #define VSC_FAST_LINK_FAIL2_ENA_MASK (0x8000)
  87. #define RX_CLK_OUT_MASK (0x0800)
  88. #define RX_CLK_OUT_POS (11)
  89. #define RX_CLK_OUT_WIDTH (1)
  90. #define RX_CLK_OUT_NORMAL (0)
  91. #define RX_CLK_OUT_DISABLE (1)
  92. #define RGMII_RX_CLK_DELAY_POS (4)
  93. #define RGMII_RX_CLK_DELAY_WIDTH (3)
  94. #define RGMII_RX_CLK_DELAY_MASK (0x0070)
  95. #define RGMII_TX_CLK_DELAY_POS (0)
  96. #define RGMII_TX_CLK_DELAY_WIDTH (3)
  97. #define RGMII_TX_CLK_DELAY_MASK (0x0007)
  98. /* Extended Page 2 Register 27E2 */
  99. #define MSCC_PHY_WOL_MAC_CONTROL 27
  100. #define EDGE_RATE_CNTL_POS (5)
  101. #define EDGE_RATE_CNTL_WIDTH (3)
  102. #define EDGE_RATE_CNTL_MASK (0x00E0)
  103. #define RMII_CLK_OUT_ENABLE_POS (4)
  104. #define RMII_CLK_OUT_ENABLE_WIDTH (1)
  105. #define RMII_CLK_OUT_ENABLE_MASK (0x10)
  106. /* Extended Page 3 Register 22E3 */
  107. #define MSCC_PHY_SERDES_TX_CRC_ERR_CNT 22
  108. /* Extended page GPIO register 00G */
  109. #define MSCC_DW8051_CNTL_STATUS 0
  110. #define MICRO_NSOFT_RESET BIT(15)
  111. #define RUN_FROM_INT_ROM BIT(14)
  112. #define AUTOINC_ADDR BIT(13)
  113. #define PATCH_RAM_CLK BIT(12)
  114. #define MICRO_PATCH_EN BIT(7)
  115. #define DW8051_CLK_EN BIT(4)
  116. #define MICRO_CLK_EN BIT(3)
  117. #define MICRO_CLK_DIVIDE(x) ((x) >> 1)
  118. #define MSCC_DW8051_VLD_MASK 0xf1ff
  119. /* Extended page GPIO register 09G */
  120. #define MSCC_TRAP_ROM_ADDR(x) ((x) * 2 + 1)
  121. #define MSCC_TRAP_ROM_ADDR_SERDES_INIT 0x3eb7
  122. /* Extended page GPIO register 10G */
  123. #define MSCC_PATCH_RAM_ADDR(x) (((x) + 1) * 2)
  124. #define MSCC_PATCH_RAM_ADDR_SERDES_INIT 0x4012
  125. /* Extended page GPIO register 11G */
  126. #define MSCC_INT_MEM_ADDR 11
  127. /* Extended page GPIO register 12G */
  128. #define MSCC_INT_MEM_CNTL 12
  129. #define READ_SFR (BIT(14) | BIT(13))
  130. #define READ_PRAM BIT(14)
  131. #define READ_ROM BIT(13)
  132. #define READ_RAM (0x00 << 13)
  133. #define INT_MEM_WRITE_EN BIT(12)
  134. #define EN_PATCH_RAM_TRAP_ADDR(x) BIT((x) + 7)
  135. #define INT_MEM_DATA_M GENMASK(7, 0)
  136. #define INT_MEM_DATA(x) (INT_MEM_DATA_M & (x))
  137. /* Extended page GPIO register 13G */
  138. #define MSCC_CLKOUT_CNTL 13
  139. #define CLKOUT_ENABLE BIT(15)
  140. #define CLKOUT_FREQ_MASK GENMASK(14, 13)
  141. #define CLKOUT_FREQ_25M (0x0 << 13)
  142. #define CLKOUT_FREQ_50M (0x1 << 13)
  143. #define CLKOUT_FREQ_125M (0x2 << 13)
  144. /* Extended page GPIO register 18G */
  145. #define MSCC_PHY_PROC_CMD 18
  146. #define PROC_CMD_NCOMPLETED BIT(15)
  147. #define PROC_CMD_FAILED BIT(14)
  148. #define PROC_CMD_SGMII_PORT(x) ((x) << 8)
  149. #define PROC_CMD_FIBER_PORT(x) BIT(8 + (x) % 4)
  150. #define PROC_CMD_QSGMII_PORT (BIT(11) | BIT(10))
  151. #define PROC_CMD_RST_CONF_PORT BIT(7)
  152. #define PROC_CMD_RECONF_PORT (0 << 7)
  153. #define PROC_CMD_READ_MOD_WRITE_PORT BIT(6)
  154. #define PROC_CMD_WRITE BIT(6)
  155. #define PROC_CMD_READ (0 << 6)
  156. #define PROC_CMD_FIBER_DISABLE BIT(5)
  157. #define PROC_CMD_FIBER_100BASE_FX BIT(4)
  158. #define PROC_CMD_FIBER_1000BASE_X (0 << 4)
  159. #define PROC_CMD_SGMII_MAC (BIT(5) | BIT(4))
  160. #define PROC_CMD_QSGMII_MAC BIT(5)
  161. #define PROC_CMD_NO_MAC_CONF (0x00 << 4)
  162. #define PROC_CMD_1588_DEFAULT_INIT BIT(4)
  163. #define PROC_CMD_NOP GENMASK(3, 0)
  164. #define PROC_CMD_PHY_INIT (BIT(3) | BIT(1))
  165. #define PROC_CMD_CRC16 BIT(3)
  166. #define PROC_CMD_FIBER_MEDIA_CONF BIT(0)
  167. #define PROC_CMD_MCB_ACCESS_MAC_CONF (0x0000 << 0)
  168. #define PROC_CMD_NCOMPLETED_TIMEOUT_MS 500
  169. /* Extended page GPIO register 19G */
  170. #define MSCC_PHY_MAC_CFG_FASTLINK 19
  171. #define MAC_CFG_MASK GENMASK(15, 14)
  172. #define MAC_CFG_SGMII (0x00 << 14)
  173. #define MAC_CFG_QSGMII BIT(14)
  174. /* Test Registers */
  175. #define MSCC_PHY_TEST_PAGE_5 5
  176. #define MSCC_PHY_TEST_PAGE_8 8
  177. #define TR_CLK_DISABLE BIT(15)
  178. #define MSCC_PHY_TEST_PAGE_9 9
  179. #define MSCC_PHY_TEST_PAGE_20 20
  180. #define MSCC_PHY_TEST_PAGE_24 24
  181. /* Token Ring Page 0x52B5 Registers */
  182. #define MSCC_PHY_REG_TR_ADDR_16 16
  183. #define MSCC_PHY_REG_TR_DATA_17 17
  184. #define MSCC_PHY_REG_TR_DATA_18 18
  185. /* Token Ring - Read Value in */
  186. #define MSCC_PHY_TR_16_READ (0xA000)
  187. /* Token Ring - Write Value out */
  188. #define MSCC_PHY_TR_16_WRITE (0x8000)
  189. /* Token Ring Registers */
  190. #define MSCC_PHY_TR_LINKDETCTRL_POS (3)
  191. #define MSCC_PHY_TR_LINKDETCTRL_WIDTH (2)
  192. #define MSCC_PHY_TR_LINKDETCTRL_VAL (3)
  193. #define MSCC_PHY_TR_LINKDETCTRL_MASK (0x0018)
  194. #define MSCC_PHY_TR_LINKDETCTRL_ADDR (0x07F8)
  195. #define MSCC_PHY_TR_VGATHRESH100_POS (0)
  196. #define MSCC_PHY_TR_VGATHRESH100_WIDTH (7)
  197. #define MSCC_PHY_TR_VGATHRESH100_VAL (0x0018)
  198. #define MSCC_PHY_TR_VGATHRESH100_MASK (0x007f)
  199. #define MSCC_PHY_TR_VGATHRESH100_ADDR (0x0FA4)
  200. #define MSCC_PHY_TR_VGAGAIN10_U_POS (0)
  201. #define MSCC_PHY_TR_VGAGAIN10_U_WIDTH (1)
  202. #define MSCC_PHY_TR_VGAGAIN10_U_MASK (0x0001)
  203. #define MSCC_PHY_TR_VGAGAIN10_U_VAL (0)
  204. #define MSCC_PHY_TR_VGAGAIN10_L_POS (12)
  205. #define MSCC_PHY_TR_VGAGAIN10_L_WIDTH (4)
  206. #define MSCC_PHY_TR_VGAGAIN10_L_MASK (0xf000)
  207. #define MSCC_PHY_TR_VGAGAIN10_L_VAL (0x0001)
  208. #define MSCC_PHY_TR_VGAGAIN10_ADDR (0x0F92)
  209. /* General Timeout Values */
  210. #define MSCC_PHY_RESET_TIMEOUT (100)
  211. #define MSCC_PHY_MICRO_TIMEOUT (500)
  212. #define VSC8584_REVB 0x0001
  213. #define MSCC_DEV_REV_MASK GENMASK(3, 0)
  214. #define MSCC_VSC8574_REVB_INT8051_FW_START_ADDR 0x4000
  215. #define MSCC_VSC8574_REVB_INT8051_FW_CRC 0x29e8
  216. #define MSCC_VSC8584_REVB_INT8051_FW_START_ADDR 0xe800
  217. #define MSCC_VSC8584_REVB_INT8051_FW_CRC 0xfb48
  218. /* RGMII/GMII Clock Delay (Skew) Options */ enum vsc_phy_rgmii_skew {
  219. VSC_PHY_RGMII_DELAY_200_PS,
  220. VSC_PHY_RGMII_DELAY_800_PS,
  221. VSC_PHY_RGMII_DELAY_1100_PS,
  222. VSC_PHY_RGMII_DELAY_1700_PS,
  223. VSC_PHY_RGMII_DELAY_2000_PS,
  224. VSC_PHY_RGMII_DELAY_2300_PS,
  225. VSC_PHY_RGMII_DELAY_2600_PS,
  226. VSC_PHY_RGMII_DELAY_3400_PS,
  227. };
  228. /* MAC i/f Clock Edge Rage Control (Slew), See Reg27E2 */ enum
  229. vsc_phy_clk_slew {
  230. VSC_PHY_CLK_SLEW_RATE_0,
  231. VSC_PHY_CLK_SLEW_RATE_1,
  232. VSC_PHY_CLK_SLEW_RATE_2,
  233. VSC_PHY_CLK_SLEW_RATE_3,
  234. VSC_PHY_CLK_SLEW_RATE_4,
  235. VSC_PHY_CLK_SLEW_RATE_5,
  236. VSC_PHY_CLK_SLEW_RATE_6,
  237. VSC_PHY_CLK_SLEW_RATE_7,
  238. };
  239. struct vsc85xx_priv {
  240. int (*config_pre)(struct phy_device *phydev);
  241. };
  242. static void vsc8584_csr_write(struct mii_dev *bus, int phy0, u16 addr, u32 val)
  243. {
  244. bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_18,
  245. val >> 16);
  246. bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_17,
  247. val & GENMASK(15, 0));
  248. bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_ADDR_16,
  249. MSCC_PHY_TR_16_WRITE | addr);
  250. }
  251. static int vsc8584_cmd(struct mii_dev *bus, int phy, u16 val)
  252. {
  253. unsigned long deadline;
  254. u16 reg_val;
  255. bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
  256. MSCC_PHY_PAGE_GPIO);
  257. bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_PHY_PROC_CMD,
  258. PROC_CMD_NCOMPLETED | val);
  259. deadline = timer_get_us() + PROC_CMD_NCOMPLETED_TIMEOUT_MS * 1000;
  260. do {
  261. reg_val = bus->read(bus, phy, MDIO_DEVAD_NONE,
  262. MSCC_PHY_PROC_CMD);
  263. } while (timer_get_us() <= deadline &&
  264. (reg_val & PROC_CMD_NCOMPLETED) &&
  265. !(reg_val & PROC_CMD_FAILED));
  266. bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
  267. MSCC_PHY_PAGE_STD);
  268. if (reg_val & PROC_CMD_FAILED)
  269. return -EIO;
  270. if (reg_val & PROC_CMD_NCOMPLETED)
  271. return -ETIMEDOUT;
  272. return 0;
  273. }
  274. static int vsc8584_micro_deassert_reset(struct mii_dev *bus, int phy,
  275. bool patch_en)
  276. {
  277. u32 enable, release;
  278. bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
  279. MSCC_PHY_PAGE_GPIO);
  280. enable = RUN_FROM_INT_ROM | MICRO_CLK_EN | DW8051_CLK_EN;
  281. release = MICRO_NSOFT_RESET | RUN_FROM_INT_ROM | DW8051_CLK_EN |
  282. MICRO_CLK_EN;
  283. if (patch_en) {
  284. enable |= MICRO_PATCH_EN;
  285. release |= MICRO_PATCH_EN;
  286. /* Clear all patches */
  287. bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_INT_MEM_CNTL,
  288. READ_RAM);
  289. }
  290. /*
  291. * Enable 8051 Micro clock; CLEAR/SET patch present; disable PRAM clock
  292. * override and addr. auto-incr; operate at 125 MHz
  293. */
  294. bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_DW8051_CNTL_STATUS, enable);
  295. /* Release 8051 Micro SW reset */
  296. bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_DW8051_CNTL_STATUS, release);
  297. bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
  298. MSCC_PHY_PAGE_STD);
  299. return 0;
  300. }
  301. static int vsc8584_micro_assert_reset(struct mii_dev *bus, int phy)
  302. {
  303. int ret;
  304. u16 reg;
  305. ret = vsc8584_cmd(bus, phy, PROC_CMD_NOP);
  306. if (ret)
  307. return ret;
  308. bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
  309. MSCC_PHY_PAGE_GPIO);
  310. reg = bus->read(bus, phy, MDIO_DEVAD_NONE, MSCC_INT_MEM_CNTL);
  311. reg &= ~EN_PATCH_RAM_TRAP_ADDR(4);
  312. bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_INT_MEM_CNTL, reg);
  313. bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_TRAP_ROM_ADDR(4), 0x005b);
  314. bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_PATCH_RAM_ADDR(4), 0x005b);
  315. reg = bus->read(bus, phy, MDIO_DEVAD_NONE, MSCC_INT_MEM_CNTL);
  316. reg |= EN_PATCH_RAM_TRAP_ADDR(4);
  317. bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_INT_MEM_CNTL, reg);
  318. bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_PHY_PROC_CMD, PROC_CMD_NOP);
  319. reg = bus->read(bus, phy, MDIO_DEVAD_NONE, MSCC_DW8051_CNTL_STATUS);
  320. reg &= ~MICRO_NSOFT_RESET;
  321. bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_DW8051_CNTL_STATUS, reg);
  322. bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_PHY_PROC_CMD,
  323. PROC_CMD_MCB_ACCESS_MAC_CONF | PROC_CMD_SGMII_PORT(0) |
  324. PROC_CMD_NO_MAC_CONF | PROC_CMD_READ);
  325. reg = bus->read(bus, phy, MDIO_DEVAD_NONE, MSCC_INT_MEM_CNTL);
  326. reg &= ~EN_PATCH_RAM_TRAP_ADDR(4);
  327. bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_INT_MEM_CNTL, reg);
  328. bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
  329. MSCC_PHY_PAGE_STD);
  330. return 0;
  331. }
  332. static const u8 fw_patch_vsc8574[] = {
  333. 0x46, 0x4a, 0x02, 0x43, 0x37, 0x02, 0x46, 0x26, 0x02, 0x46, 0x77, 0x02,
  334. 0x45, 0x60, 0x02, 0x45, 0xaf, 0xed, 0xff, 0xe5, 0xfc, 0x54, 0x38, 0x64,
  335. 0x20, 0x70, 0x08, 0x65, 0xff, 0x70, 0x04, 0xed, 0x44, 0x80, 0xff, 0x22,
  336. 0x8f, 0x19, 0x7b, 0xbb, 0x7d, 0x0e, 0x7f, 0x04, 0x12, 0x3d, 0xd7, 0xef,
  337. 0x4e, 0x60, 0x03, 0x02, 0x41, 0xf9, 0xe4, 0xf5, 0x1a, 0x74, 0x01, 0x7e,
  338. 0x00, 0xa8, 0x1a, 0x08, 0x80, 0x05, 0xc3, 0x33, 0xce, 0x33, 0xce, 0xd8,
  339. 0xf9, 0xff, 0xef, 0x55, 0x19, 0x70, 0x03, 0x02, 0x41, 0xed, 0x85, 0x1a,
  340. 0xfb, 0x7b, 0xbb, 0xe4, 0xfd, 0xff, 0x12, 0x3d, 0xd7, 0xef, 0x4e, 0x60,
  341. 0x03, 0x02, 0x41, 0xed, 0xe5, 0x1a, 0x54, 0x02, 0x75, 0x1d, 0x00, 0x25,
  342. 0xe0, 0x25, 0xe0, 0xf5, 0x1c, 0xe4, 0x78, 0xc5, 0xf6, 0xd2, 0x0a, 0x12,
  343. 0x41, 0xfa, 0x7b, 0xff, 0x7d, 0x12, 0x7f, 0x07, 0x12, 0x3d, 0xd7, 0xef,
  344. 0x4e, 0x60, 0x03, 0x02, 0x41, 0xe7, 0xc2, 0x0a, 0x74, 0xc7, 0x25, 0x1a,
  345. 0xf9, 0x74, 0xe7, 0x25, 0x1a, 0xf8, 0xe6, 0x27, 0xf5, 0x1b, 0xe5, 0x1d,
  346. 0x24, 0x5b, 0x12, 0x45, 0xea, 0x12, 0x3e, 0xda, 0x7b, 0xfc, 0x7d, 0x11,
  347. 0x7f, 0x07, 0x12, 0x3d, 0xd7, 0x78, 0xcc, 0xef, 0xf6, 0x78, 0xc1, 0xe6,
  348. 0xfe, 0xef, 0xd3, 0x9e, 0x40, 0x06, 0x78, 0xcc, 0xe6, 0x78, 0xc1, 0xf6,
  349. 0x12, 0x41, 0xfa, 0x7b, 0xec, 0x7d, 0x12, 0x7f, 0x07, 0x12, 0x3d, 0xd7,
  350. 0x78, 0xcb, 0xef, 0xf6, 0xbf, 0x07, 0x06, 0x78, 0xc3, 0x76, 0x1a, 0x80,
  351. 0x1f, 0x78, 0xc5, 0xe6, 0xff, 0x60, 0x0f, 0xc3, 0xe5, 0x1b, 0x9f, 0xff,
  352. 0x78, 0xcb, 0xe6, 0x85, 0x1b, 0xf0, 0xa4, 0x2f, 0x80, 0x07, 0x78, 0xcb,
  353. 0xe6, 0x85, 0x1b, 0xf0, 0xa4, 0x78, 0xc3, 0xf6, 0xe4, 0x78, 0xc2, 0xf6,
  354. 0x78, 0xc2, 0xe6, 0xff, 0xc3, 0x08, 0x96, 0x40, 0x03, 0x02, 0x41, 0xd1,
  355. 0xef, 0x54, 0x03, 0x60, 0x33, 0x14, 0x60, 0x46, 0x24, 0xfe, 0x60, 0x42,
  356. 0x04, 0x70, 0x4b, 0xef, 0x24, 0x02, 0xff, 0xe4, 0x33, 0xfe, 0xef, 0x78,
  357. 0x02, 0xce, 0xa2, 0xe7, 0x13, 0xce, 0x13, 0xd8, 0xf8, 0xff, 0xe5, 0x1d,
  358. 0x24, 0x5c, 0xcd, 0xe5, 0x1c, 0x34, 0xf0, 0xcd, 0x2f, 0xff, 0xed, 0x3e,
  359. 0xfe, 0x12, 0x46, 0x0d, 0x7d, 0x11, 0x80, 0x0b, 0x78, 0xc2, 0xe6, 0x70,
  360. 0x04, 0x7d, 0x11, 0x80, 0x02, 0x7d, 0x12, 0x7f, 0x07, 0x12, 0x3e, 0x9a,
  361. 0x8e, 0x1e, 0x8f, 0x1f, 0x80, 0x03, 0xe5, 0x1e, 0xff, 0x78, 0xc5, 0xe6,
  362. 0x06, 0x24, 0xcd, 0xf8, 0xa6, 0x07, 0x78, 0xc2, 0x06, 0xe6, 0xb4, 0x1a,
  363. 0x0a, 0xe5, 0x1d, 0x24, 0x5c, 0x12, 0x45, 0xea, 0x12, 0x3e, 0xda, 0x78,
  364. 0xc5, 0xe6, 0x65, 0x1b, 0x70, 0x82, 0x75, 0xdb, 0x20, 0x75, 0xdb, 0x28,
  365. 0x12, 0x46, 0x02, 0x12, 0x46, 0x02, 0xe5, 0x1a, 0x12, 0x45, 0xf5, 0xe5,
  366. 0x1a, 0xc3, 0x13, 0x12, 0x45, 0xf5, 0x78, 0xc5, 0x16, 0xe6, 0x24, 0xcd,
  367. 0xf8, 0xe6, 0xff, 0x7e, 0x08, 0x1e, 0xef, 0xa8, 0x06, 0x08, 0x80, 0x02,
  368. 0xc3, 0x13, 0xd8, 0xfc, 0xfd, 0xc4, 0x33, 0x54, 0xe0, 0xf5, 0xdb, 0xef,
  369. 0xa8, 0x06, 0x08, 0x80, 0x02, 0xc3, 0x13, 0xd8, 0xfc, 0xfd, 0xc4, 0x33,
  370. 0x54, 0xe0, 0x44, 0x08, 0xf5, 0xdb, 0xee, 0x70, 0xd8, 0x78, 0xc5, 0xe6,
  371. 0x70, 0xc8, 0x75, 0xdb, 0x10, 0x02, 0x40, 0xfd, 0x78, 0xc2, 0xe6, 0xc3,
  372. 0x94, 0x17, 0x50, 0x0e, 0xe5, 0x1d, 0x24, 0x62, 0x12, 0x42, 0x08, 0xe5,
  373. 0x1d, 0x24, 0x5c, 0x12, 0x42, 0x08, 0x20, 0x0a, 0x03, 0x02, 0x40, 0x76,
  374. 0x05, 0x1a, 0xe5, 0x1a, 0xc3, 0x94, 0x04, 0x50, 0x03, 0x02, 0x40, 0x3a,
  375. 0x22, 0xe5, 0x1d, 0x24, 0x5c, 0xff, 0xe5, 0x1c, 0x34, 0xf0, 0xfe, 0x12,
  376. 0x46, 0x0d, 0x22, 0xff, 0xe5, 0x1c, 0x34, 0xf0, 0xfe, 0x12, 0x46, 0x0d,
  377. 0x22, 0xe4, 0xf5, 0x19, 0x12, 0x46, 0x43, 0x20, 0xe7, 0x1e, 0x7b, 0xfe,
  378. 0x12, 0x42, 0xf9, 0xef, 0xc4, 0x33, 0x33, 0x54, 0xc0, 0xff, 0xc0, 0x07,
  379. 0x7b, 0x54, 0x12, 0x42, 0xf9, 0xd0, 0xe0, 0x4f, 0xff, 0x74, 0x2a, 0x25,
  380. 0x19, 0xf8, 0xa6, 0x07, 0x12, 0x46, 0x43, 0x20, 0xe7, 0x03, 0x02, 0x42,
  381. 0xdf, 0x54, 0x03, 0x64, 0x03, 0x70, 0x03, 0x02, 0x42, 0xcf, 0x7b, 0xcb,
  382. 0x12, 0x43, 0x2c, 0x8f, 0xfb, 0x7b, 0x30, 0x7d, 0x03, 0xe4, 0xff, 0x12,
  383. 0x3d, 0xd7, 0xc3, 0xef, 0x94, 0x02, 0xee, 0x94, 0x00, 0x50, 0x2a, 0x12,
  384. 0x42, 0xec, 0xef, 0x4e, 0x70, 0x23, 0x12, 0x43, 0x04, 0x60, 0x0a, 0x12,
  385. 0x43, 0x12, 0x70, 0x0c, 0x12, 0x43, 0x1f, 0x70, 0x07, 0x12, 0x46, 0x39,
  386. 0x7b, 0x03, 0x80, 0x07, 0x12, 0x46, 0x39, 0x12, 0x46, 0x43, 0xfb, 0x7a,
  387. 0x00, 0x7d, 0x54, 0x80, 0x3e, 0x12, 0x42, 0xec, 0xef, 0x4e, 0x70, 0x24,
  388. 0x12, 0x43, 0x04, 0x60, 0x0a, 0x12, 0x43, 0x12, 0x70, 0x0f, 0x12, 0x43,
  389. 0x1f, 0x70, 0x0a, 0x12, 0x46, 0x39, 0xe4, 0xfb, 0xfa, 0x7d, 0xee, 0x80,
  390. 0x1e, 0x12, 0x46, 0x39, 0x7b, 0x01, 0x7a, 0x00, 0x7d, 0xee, 0x80, 0x13,
  391. 0x12, 0x46, 0x39, 0x12, 0x46, 0x43, 0x54, 0x40, 0xfe, 0xc4, 0x13, 0x13,
  392. 0x54, 0x03, 0xfb, 0x7a, 0x00, 0x7d, 0xee, 0x12, 0x38, 0xbd, 0x7b, 0xff,
  393. 0x12, 0x43, 0x2c, 0xef, 0x4e, 0x70, 0x07, 0x74, 0x2a, 0x25, 0x19, 0xf8,
  394. 0xe4, 0xf6, 0x05, 0x19, 0xe5, 0x19, 0xc3, 0x94, 0x02, 0x50, 0x03, 0x02,
  395. 0x42, 0x15, 0x22, 0xe5, 0x19, 0x24, 0x17, 0xfd, 0x7b, 0x20, 0x7f, 0x04,
  396. 0x12, 0x3d, 0xd7, 0x22, 0xe5, 0x19, 0x24, 0x17, 0xfd, 0x7f, 0x04, 0x12,
  397. 0x3d, 0xd7, 0x22, 0x7b, 0x22, 0x7d, 0x18, 0x7f, 0x06, 0x12, 0x3d, 0xd7,
  398. 0xef, 0x64, 0x01, 0x4e, 0x22, 0x7d, 0x1c, 0xe4, 0xff, 0x12, 0x3e, 0x9a,
  399. 0xef, 0x54, 0x1b, 0x64, 0x0a, 0x22, 0x7b, 0xcc, 0x7d, 0x10, 0xff, 0x12,
  400. 0x3d, 0xd7, 0xef, 0x64, 0x01, 0x4e, 0x22, 0xe5, 0x19, 0x24, 0x17, 0xfd,
  401. 0x7f, 0x04, 0x12, 0x3d, 0xd7, 0x22, 0xd2, 0x08, 0x75, 0xfb, 0x03, 0xab,
  402. 0x7e, 0xaa, 0x7d, 0x7d, 0x19, 0x7f, 0x03, 0x12, 0x3e, 0xda, 0xe5, 0x7e,
  403. 0x54, 0x0f, 0x24, 0xf3, 0x60, 0x03, 0x02, 0x43, 0xe9, 0x12, 0x46, 0x5a,
  404. 0x12, 0x46, 0x61, 0xd8, 0xfb, 0xff, 0x20, 0xe2, 0x35, 0x13, 0x92, 0x0c,
  405. 0xef, 0xa2, 0xe1, 0x92, 0x0b, 0x30, 0x0c, 0x2a, 0xe4, 0xf5, 0x10, 0x7b,
  406. 0xfe, 0x12, 0x43, 0xff, 0xef, 0xc4, 0x33, 0x33, 0x54, 0xc0, 0xff, 0xc0,
  407. 0x07, 0x7b, 0x54, 0x12, 0x43, 0xff, 0xd0, 0xe0, 0x4f, 0xff, 0x74, 0x2a,
  408. 0x25, 0x10, 0xf8, 0xa6, 0x07, 0x05, 0x10, 0xe5, 0x10, 0xc3, 0x94, 0x02,
  409. 0x40, 0xd9, 0x12, 0x46, 0x5a, 0x12, 0x46, 0x61, 0xd8, 0xfb, 0x54, 0x05,
  410. 0x64, 0x04, 0x70, 0x27, 0x78, 0xc4, 0xe6, 0x78, 0xc6, 0xf6, 0xe5, 0x7d,
  411. 0xff, 0x33, 0x95, 0xe0, 0xef, 0x54, 0x0f, 0x78, 0xc4, 0xf6, 0x12, 0x44,
  412. 0x0a, 0x20, 0x0c, 0x0c, 0x12, 0x46, 0x5a, 0x12, 0x46, 0x61, 0xd8, 0xfb,
  413. 0x13, 0x92, 0x0d, 0x22, 0xc2, 0x0d, 0x22, 0x12, 0x46, 0x5a, 0x12, 0x46,
  414. 0x61, 0xd8, 0xfb, 0x54, 0x05, 0x64, 0x05, 0x70, 0x1e, 0x78, 0xc4, 0x7d,
  415. 0xb8, 0x12, 0x43, 0xf5, 0x78, 0xc1, 0x7d, 0x74, 0x12, 0x43, 0xf5, 0xe4,
  416. 0x78, 0xc1, 0xf6, 0x22, 0x7b, 0x01, 0x7a, 0x00, 0x7d, 0xee, 0x7f, 0x92,
  417. 0x12, 0x38, 0xbd, 0x22, 0xe6, 0xfb, 0x7a, 0x00, 0x7f, 0x92, 0x12, 0x38,
  418. 0xbd, 0x22, 0xe5, 0x10, 0x24, 0x17, 0xfd, 0x7f, 0x04, 0x12, 0x3d, 0xd7,
  419. 0x22, 0x78, 0xc1, 0xe6, 0xfb, 0x7a, 0x00, 0x7d, 0x74, 0x7f, 0x92, 0x12,
  420. 0x38, 0xbd, 0xe4, 0x78, 0xc1, 0xf6, 0xf5, 0x11, 0x74, 0x01, 0x7e, 0x00,
  421. 0xa8, 0x11, 0x08, 0x80, 0x05, 0xc3, 0x33, 0xce, 0x33, 0xce, 0xd8, 0xf9,
  422. 0xff, 0x78, 0xc4, 0xe6, 0xfd, 0xef, 0x5d, 0x60, 0x44, 0x85, 0x11, 0xfb,
  423. 0xe5, 0x11, 0x54, 0x02, 0x25, 0xe0, 0x25, 0xe0, 0xfe, 0xe4, 0x24, 0x5b,
  424. 0xfb, 0xee, 0x12, 0x45, 0xed, 0x12, 0x3e, 0xda, 0x7b, 0x40, 0x7d, 0x11,
  425. 0x7f, 0x07, 0x12, 0x3d, 0xd7, 0x74, 0xc7, 0x25, 0x11, 0xf8, 0xa6, 0x07,
  426. 0x7b, 0x11, 0x7d, 0x12, 0x7f, 0x07, 0x12, 0x3d, 0xd7, 0xef, 0x4e, 0x60,
  427. 0x09, 0x74, 0xe7, 0x25, 0x11, 0xf8, 0x76, 0x04, 0x80, 0x07, 0x74, 0xe7,
  428. 0x25, 0x11, 0xf8, 0x76, 0x0a, 0x05, 0x11, 0xe5, 0x11, 0xc3, 0x94, 0x04,
  429. 0x40, 0x9a, 0x78, 0xc6, 0xe6, 0x70, 0x15, 0x78, 0xc4, 0xe6, 0x60, 0x10,
  430. 0x75, 0xd9, 0x38, 0x75, 0xdb, 0x10, 0x7d, 0xfe, 0x12, 0x44, 0xb8, 0x7d,
  431. 0x76, 0x12, 0x44, 0xb8, 0x79, 0xc6, 0xe7, 0x78, 0xc4, 0x66, 0xff, 0x60,
  432. 0x03, 0x12, 0x40, 0x25, 0x78, 0xc4, 0xe6, 0x70, 0x09, 0xfb, 0xfa, 0x7d,
  433. 0xfe, 0x7f, 0x8e, 0x12, 0x38, 0xbd, 0x22, 0x7b, 0x01, 0x7a, 0x00, 0x7f,
  434. 0x8e, 0x12, 0x38, 0xbd, 0x22, 0xe4, 0xf5, 0xfb, 0x7d, 0x1c, 0xe4, 0xff,
  435. 0x12, 0x3e, 0x9a, 0xad, 0x07, 0xac, 0x06, 0xec, 0x54, 0xc0, 0xff, 0xed,
  436. 0x54, 0x3f, 0x4f, 0xf5, 0x20, 0x30, 0x06, 0x2c, 0x30, 0x01, 0x08, 0xa2,
  437. 0x04, 0x72, 0x03, 0x92, 0x07, 0x80, 0x21, 0x30, 0x04, 0x06, 0x7b, 0xcc,
  438. 0x7d, 0x11, 0x80, 0x0d, 0x30, 0x03, 0x06, 0x7b, 0xcc, 0x7d, 0x10, 0x80,
  439. 0x04, 0x7b, 0x66, 0x7d, 0x16, 0xe4, 0xff, 0x12, 0x3d, 0xd7, 0xee, 0x4f,
  440. 0x24, 0xff, 0x92, 0x07, 0xaf, 0xfb, 0x74, 0x26, 0x2f, 0xf8, 0xe6, 0xff,
  441. 0xa6, 0x20, 0x20, 0x07, 0x39, 0x8f, 0x20, 0x30, 0x07, 0x34, 0x30, 0x00,
  442. 0x31, 0x20, 0x04, 0x2e, 0x20, 0x03, 0x2b, 0xe4, 0xf5, 0xff, 0x75, 0xfc,
  443. 0xc2, 0xe5, 0xfc, 0x30, 0xe0, 0xfb, 0xaf, 0xfe, 0xef, 0x20, 0xe3, 0x1a,
  444. 0xae, 0xfd, 0x44, 0x08, 0xf5, 0xfe, 0x75, 0xfc, 0x80, 0xe5, 0xfc, 0x30,
  445. 0xe0, 0xfb, 0x8f, 0xfe, 0x8e, 0xfd, 0x75, 0xfc, 0x80, 0xe5, 0xfc, 0x30,
  446. 0xe0, 0xfb, 0x05, 0xfb, 0xaf, 0xfb, 0xef, 0xc3, 0x94, 0x04, 0x50, 0x03,
  447. 0x02, 0x44, 0xc5, 0xe4, 0xf5, 0xfb, 0x22, 0xe5, 0x7e, 0x54, 0x0f, 0x64,
  448. 0x01, 0x70, 0x23, 0xe5, 0x7e, 0x30, 0xe4, 0x1e, 0x90, 0x47, 0xd0, 0xe0,
  449. 0x44, 0x02, 0xf0, 0x54, 0xfb, 0xf0, 0x90, 0x47, 0xd4, 0xe0, 0x44, 0x04,
  450. 0xf0, 0x7b, 0x03, 0x7d, 0x5b, 0x7f, 0x5d, 0x12, 0x36, 0x29, 0x7b, 0x0e,
  451. 0x80, 0x1c, 0x90, 0x47, 0xd0, 0xe0, 0x54, 0xfd, 0xf0, 0x44, 0x04, 0xf0,
  452. 0x90, 0x47, 0xd4, 0xe0, 0x54, 0xfb, 0xf0, 0x7b, 0x02, 0x7d, 0x5b, 0x7f,
  453. 0x5d, 0x12, 0x36, 0x29, 0x7b, 0x06, 0x7d, 0x60, 0x7f, 0x63, 0x12, 0x36,
  454. 0x29, 0x22, 0xe5, 0x7e, 0x30, 0xe5, 0x35, 0x30, 0xe4, 0x0b, 0x7b, 0x02,
  455. 0x7d, 0x33, 0x7f, 0x35, 0x12, 0x36, 0x29, 0x80, 0x10, 0x7b, 0x01, 0x7d,
  456. 0x33, 0x7f, 0x35, 0x12, 0x36, 0x29, 0x90, 0x47, 0xd2, 0xe0, 0x44, 0x04,
  457. 0xf0, 0x90, 0x47, 0xd2, 0xe0, 0x54, 0xf7, 0xf0, 0x90, 0x47, 0xd1, 0xe0,
  458. 0x44, 0x10, 0xf0, 0x7b, 0x05, 0x7d, 0x84, 0x7f, 0x86, 0x12, 0x36, 0x29,
  459. 0x22, 0xfb, 0xe5, 0x1c, 0x34, 0xf0, 0xfa, 0x7d, 0x10, 0x7f, 0x07, 0x22,
  460. 0x54, 0x01, 0xc4, 0x33, 0x54, 0xe0, 0xf5, 0xdb, 0x44, 0x08, 0xf5, 0xdb,
  461. 0x22, 0xf5, 0xdb, 0x75, 0xdb, 0x08, 0xf5, 0xdb, 0x75, 0xdb, 0x08, 0x22,
  462. 0xab, 0x07, 0xaa, 0x06, 0x7d, 0x10, 0x7f, 0x07, 0x12, 0x3e, 0xda, 0x7b,
  463. 0xff, 0x7d, 0x10, 0x7f, 0x07, 0x12, 0x3d, 0xd7, 0xef, 0x4e, 0x60, 0xf3,
  464. 0x22, 0x12, 0x44, 0xc2, 0x30, 0x0c, 0x03, 0x12, 0x42, 0x12, 0x78, 0xc4,
  465. 0xe6, 0xff, 0x60, 0x03, 0x12, 0x40, 0x25, 0x22, 0xe5, 0x19, 0x24, 0x17,
  466. 0x54, 0x1f, 0x44, 0x80, 0xff, 0x22, 0x74, 0x2a, 0x25, 0x19, 0xf8, 0xe6,
  467. 0x22, 0x12, 0x46, 0x72, 0x12, 0x46, 0x68, 0x90, 0x47, 0xfa, 0xe0, 0x54,
  468. 0xf8, 0x44, 0x02, 0xf0, 0x22, 0xe5, 0x7e, 0xae, 0x7d, 0x78, 0x04, 0x22,
  469. 0xce, 0xa2, 0xe7, 0x13, 0xce, 0x13, 0x22, 0xe4, 0x78, 0xc4, 0xf6, 0xc2,
  470. 0x0d, 0x78, 0xc1, 0xf6, 0x22, 0xc2, 0x0c, 0xc2, 0x0b, 0x22, 0x22,
  471. };
  472. static const u8 fw_patch_vsc8584[] = {
  473. 0xe8, 0x59, 0x02, 0xe8, 0x12, 0x02, 0xe8, 0x42, 0x02, 0xe8, 0x5a, 0x02,
  474. 0xe8, 0x5b, 0x02, 0xe8, 0x5c, 0xe5, 0x69, 0x54, 0x0f, 0x24, 0xf7, 0x60,
  475. 0x27, 0x24, 0xfc, 0x60, 0x23, 0x24, 0x08, 0x70, 0x14, 0xe5, 0x69, 0xae,
  476. 0x68, 0x78, 0x04, 0xce, 0xa2, 0xe7, 0x13, 0xce, 0x13, 0xd8, 0xf8, 0x7e,
  477. 0x00, 0x54, 0x0f, 0x80, 0x00, 0x7b, 0x01, 0x7a, 0x00, 0x7d, 0xee, 0x7f,
  478. 0x92, 0x12, 0x50, 0xee, 0x22, 0xe4, 0xf5, 0x10, 0x85, 0x10, 0xfb, 0x7d,
  479. 0x1c, 0xe4, 0xff, 0x12, 0x59, 0xea, 0x05, 0x10, 0xe5, 0x10, 0xc3, 0x94,
  480. 0x04, 0x40, 0xed, 0x22, 0x22, 0x22, 0x22, 0x22,
  481. };
  482. static int vsc8584_get_fw_crc(struct mii_dev *bus, int phy, u16 start,
  483. u16 *crc, const u8 *fw_patch, int fw_size)
  484. {
  485. int ret;
  486. bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
  487. MSCC_PHY_PAGE_EXT1);
  488. bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_PHY_VERIPHY_CNTL_2, start);
  489. /* Add one byte to size for the one added by the patch_fw function */
  490. bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_PHY_VERIPHY_CNTL_3,
  491. fw_size + 1);
  492. ret = vsc8584_cmd(bus, phy, PROC_CMD_CRC16);
  493. if (ret)
  494. goto out;
  495. bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
  496. MSCC_PHY_PAGE_EXT1);
  497. *crc = bus->read(bus, phy, MDIO_DEVAD_NONE, MSCC_PHY_VERIPHY_CNTL_2);
  498. out:
  499. bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
  500. MSCC_PHY_PAGE_STD);
  501. return ret;
  502. }
  503. static int vsc8584_patch_fw(struct mii_dev *bus, int phy, const u8 *fw_patch,
  504. int fw_size)
  505. {
  506. int i, ret;
  507. ret = vsc8584_micro_assert_reset(bus, phy);
  508. if (ret) {
  509. pr_err("%s: failed to assert reset of micro\n", __func__);
  510. return ret;
  511. }
  512. bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
  513. MSCC_PHY_PAGE_GPIO);
  514. /*
  515. * Hold 8051 Micro in SW Reset, Enable auto incr address and patch clock
  516. * Disable the 8051 Micro clock
  517. */
  518. bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_DW8051_CNTL_STATUS,
  519. RUN_FROM_INT_ROM | AUTOINC_ADDR | PATCH_RAM_CLK |
  520. MICRO_CLK_EN | MICRO_CLK_DIVIDE(2));
  521. bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_INT_MEM_CNTL, READ_PRAM |
  522. INT_MEM_WRITE_EN | INT_MEM_DATA(2));
  523. bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_INT_MEM_ADDR, 0x0000);
  524. for (i = 0; i < fw_size; i++)
  525. bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_INT_MEM_CNTL,
  526. READ_PRAM | INT_MEM_WRITE_EN | fw_patch[i]);
  527. /* Clear internal memory access */
  528. bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_INT_MEM_CNTL, READ_RAM);
  529. bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
  530. MSCC_PHY_PAGE_STD);
  531. return 0;
  532. }
  533. static bool vsc8574_is_serdes_init(struct mii_dev *bus, int phy)
  534. {
  535. u16 reg;
  536. bool ret;
  537. bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
  538. MSCC_PHY_PAGE_GPIO);
  539. reg = bus->read(bus, phy, MDIO_DEVAD_NONE, MSCC_TRAP_ROM_ADDR(1));
  540. if (reg != MSCC_TRAP_ROM_ADDR_SERDES_INIT) {
  541. ret = false;
  542. goto out;
  543. }
  544. reg = bus->read(bus, phy, MDIO_DEVAD_NONE, MSCC_PATCH_RAM_ADDR(1));
  545. if (reg != MSCC_PATCH_RAM_ADDR_SERDES_INIT) {
  546. ret = false;
  547. goto out;
  548. }
  549. reg = bus->read(bus, phy, MDIO_DEVAD_NONE, MSCC_INT_MEM_CNTL);
  550. if (reg != EN_PATCH_RAM_TRAP_ADDR(1)) {
  551. ret = false;
  552. goto out;
  553. }
  554. reg = bus->read(bus, phy, MDIO_DEVAD_NONE, MSCC_DW8051_CNTL_STATUS);
  555. if ((MICRO_NSOFT_RESET | RUN_FROM_INT_ROM | DW8051_CLK_EN |
  556. MICRO_CLK_EN) != (reg & MSCC_DW8051_VLD_MASK)) {
  557. ret = false;
  558. goto out;
  559. }
  560. ret = true;
  561. out:
  562. bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
  563. MSCC_PHY_PAGE_GPIO);
  564. return ret;
  565. }
  566. static int vsc8574_config_pre_init(struct phy_device *phydev)
  567. {
  568. struct mii_dev *bus = phydev->bus;
  569. u16 crc, reg, phy0, addr;
  570. bool serdes_init;
  571. int ret;
  572. phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
  573. MSCC_PHY_PAGE_EXT1);
  574. addr = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_EXT_PHY_CNTL_4);
  575. addr >>= PHY_CNTL_4_ADDR_POS;
  576. reg = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_ACTIPHY_CNTL);
  577. if (reg & PHY_ADDR_REVERSED)
  578. phy0 = phydev->addr + addr;
  579. else
  580. phy0 = phydev->addr - addr;
  581. bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
  582. MSCC_PHY_PAGE_STD);
  583. /* all writes below are broadcasted to all PHYs in the same package */
  584. reg = bus->read(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_EXT_CNTL_STATUS);
  585. reg |= SMI_BROADCAST_WR_EN;
  586. bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_EXT_CNTL_STATUS, reg);
  587. /*
  588. * The below register writes are tweaking analog and electrical
  589. * configuration that were determined through characterization by PHY
  590. * engineers. These don't mean anything more than "these are the best
  591. * values".
  592. */
  593. bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_EXT_PHY_CNTL_2, 0x0040);
  594. bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
  595. MSCC_PHY_PAGE_TEST);
  596. bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_TEST_PAGE_20, 0x4320);
  597. bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_TEST_PAGE_24, 0x0c00);
  598. bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_TEST_PAGE_9, 0x18ca);
  599. bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_TEST_PAGE_5, 0x1b20);
  600. reg = bus->read(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_TEST_PAGE_8);
  601. reg |= TR_CLK_DISABLE;
  602. bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_TEST_PAGE_8, reg);
  603. bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
  604. MSCC_PHY_PAGE_TR);
  605. vsc8584_csr_write(bus, phy0, 0x0fae, 0x000401bd);
  606. vsc8584_csr_write(bus, phy0, 0x0fac, 0x000f000f);
  607. vsc8584_csr_write(bus, phy0, 0x17a0, 0x00a0f147);
  608. vsc8584_csr_write(bus, phy0, 0x0fe4, 0x00052f54);
  609. vsc8584_csr_write(bus, phy0, 0x1792, 0x0027303d);
  610. vsc8584_csr_write(bus, phy0, 0x07fe, 0x00000704);
  611. vsc8584_csr_write(bus, phy0, 0x0fe0, 0x00060150);
  612. vsc8584_csr_write(bus, phy0, 0x0f82, 0x0012b00a);
  613. vsc8584_csr_write(bus, phy0, 0x0f80, 0x00000d74);
  614. vsc8584_csr_write(bus, phy0, 0x02e0, 0x00000012);
  615. vsc8584_csr_write(bus, phy0, 0x03a2, 0x00050208);
  616. vsc8584_csr_write(bus, phy0, 0x03b2, 0x00009186);
  617. vsc8584_csr_write(bus, phy0, 0x0fb0, 0x000e3700);
  618. vsc8584_csr_write(bus, phy0, 0x1688, 0x00049f81);
  619. vsc8584_csr_write(bus, phy0, 0x0fd2, 0x0000ffff);
  620. vsc8584_csr_write(bus, phy0, 0x168a, 0x00039fa2);
  621. vsc8584_csr_write(bus, phy0, 0x1690, 0x0020640b);
  622. vsc8584_csr_write(bus, phy0, 0x0258, 0x00002220);
  623. vsc8584_csr_write(bus, phy0, 0x025a, 0x00002a20);
  624. vsc8584_csr_write(bus, phy0, 0x025c, 0x00003060);
  625. vsc8584_csr_write(bus, phy0, 0x025e, 0x00003fa0);
  626. vsc8584_csr_write(bus, phy0, 0x03a6, 0x0000e0f0);
  627. vsc8584_csr_write(bus, phy0, 0x0f92, 0x00001489);
  628. vsc8584_csr_write(bus, phy0, 0x16a2, 0x00007000);
  629. vsc8584_csr_write(bus, phy0, 0x16a6, 0x00071448);
  630. vsc8584_csr_write(bus, phy0, 0x16a0, 0x00eeffdd);
  631. vsc8584_csr_write(bus, phy0, 0x0fe8, 0x0091b06c);
  632. vsc8584_csr_write(bus, phy0, 0x0fea, 0x00041600);
  633. vsc8584_csr_write(bus, phy0, 0x16b0, 0x00eeff00);
  634. vsc8584_csr_write(bus, phy0, 0x16b2, 0x00007000);
  635. vsc8584_csr_write(bus, phy0, 0x16b4, 0x00000814);
  636. vsc8584_csr_write(bus, phy0, 0x0f90, 0x00688980);
  637. vsc8584_csr_write(bus, phy0, 0x03a4, 0x0000d8f0);
  638. vsc8584_csr_write(bus, phy0, 0x0fc0, 0x00000400);
  639. vsc8584_csr_write(bus, phy0, 0x07fa, 0x0050100f);
  640. vsc8584_csr_write(bus, phy0, 0x0796, 0x00000003);
  641. vsc8584_csr_write(bus, phy0, 0x07f8, 0x00c3ff98);
  642. vsc8584_csr_write(bus, phy0, 0x0fa4, 0x0018292a);
  643. vsc8584_csr_write(bus, phy0, 0x168c, 0x00d2c46f);
  644. vsc8584_csr_write(bus, phy0, 0x17a2, 0x00000620);
  645. vsc8584_csr_write(bus, phy0, 0x16a4, 0x0013132f);
  646. vsc8584_csr_write(bus, phy0, 0x16a8, 0x00000000);
  647. vsc8584_csr_write(bus, phy0, 0x0ffc, 0x00c0a028);
  648. vsc8584_csr_write(bus, phy0, 0x0fec, 0x00901c09);
  649. vsc8584_csr_write(bus, phy0, 0x0fee, 0x0004a6a1);
  650. vsc8584_csr_write(bus, phy0, 0x0ffe, 0x00b01807);
  651. bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
  652. MSCC_PHY_PAGE_EXT2);
  653. bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_CU_PMD_TX_CNTL, 0x028e);
  654. bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
  655. MSCC_PHY_PAGE_TR);
  656. vsc8584_csr_write(bus, phy0, 0x0486, 0x0008a518);
  657. vsc8584_csr_write(bus, phy0, 0x0488, 0x006dc696);
  658. vsc8584_csr_write(bus, phy0, 0x048a, 0x00000912);
  659. vsc8584_csr_write(bus, phy0, 0x048e, 0x00000db6);
  660. vsc8584_csr_write(bus, phy0, 0x049c, 0x00596596);
  661. vsc8584_csr_write(bus, phy0, 0x049e, 0x00000514);
  662. vsc8584_csr_write(bus, phy0, 0x04a2, 0x00410280);
  663. vsc8584_csr_write(bus, phy0, 0x04a4, 0x00000000);
  664. vsc8584_csr_write(bus, phy0, 0x04a6, 0x00000000);
  665. vsc8584_csr_write(bus, phy0, 0x04a8, 0x00000000);
  666. vsc8584_csr_write(bus, phy0, 0x04aa, 0x00000000);
  667. vsc8584_csr_write(bus, phy0, 0x04ae, 0x007df7dd);
  668. vsc8584_csr_write(bus, phy0, 0x04b0, 0x006d95d4);
  669. vsc8584_csr_write(bus, phy0, 0x04b2, 0x00492410);
  670. bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
  671. MSCC_PHY_PAGE_TEST);
  672. reg = bus->read(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_TEST_PAGE_8);
  673. reg &= ~TR_CLK_DISABLE;
  674. bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_TEST_PAGE_8, reg);
  675. bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
  676. MSCC_PHY_PAGE_STD);
  677. /* end of write broadcasting */
  678. reg = bus->read(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_EXT_CNTL_STATUS);
  679. reg &= ~SMI_BROADCAST_WR_EN;
  680. bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_EXT_CNTL_STATUS, reg);
  681. ret = vsc8584_get_fw_crc(bus, phy0,
  682. MSCC_VSC8574_REVB_INT8051_FW_START_ADDR, &crc,
  683. fw_patch_vsc8574,
  684. ARRAY_SIZE(fw_patch_vsc8574));
  685. if (ret)
  686. goto out;
  687. if (crc == MSCC_VSC8574_REVB_INT8051_FW_CRC) {
  688. serdes_init = vsc8574_is_serdes_init(bus, phy0);
  689. if (!serdes_init) {
  690. ret = vsc8584_micro_assert_reset(bus, phy0);
  691. if (ret) {
  692. pr_err("failed to assert reset of micro\n");
  693. return ret;
  694. }
  695. }
  696. } else {
  697. pr_debug("FW CRC is not the expected one, patching FW\n");
  698. serdes_init = false;
  699. if (vsc8584_patch_fw(bus, phy0, fw_patch_vsc8574,
  700. ARRAY_SIZE(fw_patch_vsc8574)))
  701. pr_warn("failed to patch FW, expect non-optimal device\n");
  702. }
  703. if (!serdes_init) {
  704. bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
  705. MSCC_PHY_PAGE_GPIO);
  706. bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_TRAP_ROM_ADDR(1),
  707. MSCC_TRAP_ROM_ADDR_SERDES_INIT);
  708. bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PATCH_RAM_ADDR(1),
  709. MSCC_PATCH_RAM_ADDR_SERDES_INIT);
  710. bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_INT_MEM_CNTL,
  711. EN_PATCH_RAM_TRAP_ADDR(1));
  712. vsc8584_micro_deassert_reset(bus, phy0, false);
  713. ret = vsc8584_get_fw_crc(bus, phy0,
  714. MSCC_VSC8574_REVB_INT8051_FW_START_ADDR,
  715. &crc, fw_patch_vsc8574,
  716. ARRAY_SIZE(fw_patch_vsc8574));
  717. if (ret)
  718. goto out;
  719. if (crc != MSCC_VSC8574_REVB_INT8051_FW_CRC)
  720. pr_warn("FW CRC after patching is not the expected one, expect non-optimal device\n");
  721. }
  722. bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
  723. MSCC_PHY_PAGE_GPIO);
  724. ret = vsc8584_cmd(bus, phy0, PROC_CMD_1588_DEFAULT_INIT |
  725. PROC_CMD_PHY_INIT);
  726. out:
  727. bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
  728. MSCC_PHY_PAGE_STD);
  729. return ret;
  730. }
  731. static int vsc8584_config_pre_init(struct phy_device *phydev)
  732. {
  733. struct mii_dev *bus = phydev->bus;
  734. u16 reg, crc, phy0, addr;
  735. int ret;
  736. if ((phydev->phy_id & MSCC_DEV_REV_MASK) != VSC8584_REVB) {
  737. pr_warn("VSC8584 revA not officially supported, skipping firmware patching. Use at your own risk.\n");
  738. return 0;
  739. }
  740. phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
  741. MSCC_PHY_PAGE_EXT1);
  742. addr = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_EXT_PHY_CNTL_4);
  743. addr >>= PHY_CNTL_4_ADDR_POS;
  744. reg = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_ACTIPHY_CNTL);
  745. if (reg & PHY_ADDR_REVERSED)
  746. phy0 = phydev->addr + addr;
  747. else
  748. phy0 = phydev->addr - addr;
  749. bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
  750. MSCC_PHY_PAGE_STD);
  751. /* all writes below are broadcasted to all PHYs in the same package */
  752. reg = bus->read(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_EXT_CNTL_STATUS);
  753. reg |= SMI_BROADCAST_WR_EN;
  754. bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_EXT_CNTL_STATUS, reg);
  755. /*
  756. * The below register writes are tweaking analog and electrical
  757. * configuration that were determined through characterization by PHY
  758. * engineers. These don't mean anything more than "these are the best
  759. * values".
  760. */
  761. reg = bus->read(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_BYPASS_CONTROL);
  762. reg |= PARALLEL_DET_IGNORE_ADVERTISED;
  763. bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_BYPASS_CONTROL, reg);
  764. bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
  765. MSCC_PHY_PAGE_EXT3);
  766. bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_SERDES_TX_CRC_ERR_CNT,
  767. 0x2000);
  768. bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
  769. MSCC_PHY_PAGE_TEST);
  770. bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_TEST_PAGE_5, 0x1f20);
  771. reg = bus->read(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_TEST_PAGE_8);
  772. reg |= TR_CLK_DISABLE;
  773. bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_TEST_PAGE_8, reg);
  774. bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
  775. MSCC_PHY_PAGE_TR);
  776. bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_ADDR_16, 0xafa4);
  777. reg = bus->read(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_18);
  778. reg &= ~0x007f;
  779. reg |= 0x0019;
  780. bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_18, reg);
  781. bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_ADDR_16, 0x8fa4);
  782. vsc8584_csr_write(bus, phy0, 0x07fa, 0x0050100f);
  783. vsc8584_csr_write(bus, phy0, 0x1688, 0x00049f81);
  784. vsc8584_csr_write(bus, phy0, 0x0f90, 0x00688980);
  785. vsc8584_csr_write(bus, phy0, 0x03a4, 0x0000d8f0);
  786. vsc8584_csr_write(bus, phy0, 0x0fc0, 0x00000400);
  787. vsc8584_csr_write(bus, phy0, 0x0f82, 0x0012b002);
  788. vsc8584_csr_write(bus, phy0, 0x1686, 0x00000004);
  789. vsc8584_csr_write(bus, phy0, 0x168c, 0x00d2c46f);
  790. vsc8584_csr_write(bus, phy0, 0x17a2, 0x00000620);
  791. vsc8584_csr_write(bus, phy0, 0x16a0, 0x00eeffdd);
  792. vsc8584_csr_write(bus, phy0, 0x16a6, 0x00071448);
  793. vsc8584_csr_write(bus, phy0, 0x16a4, 0x0013132f);
  794. vsc8584_csr_write(bus, phy0, 0x16a8, 0x00000000);
  795. vsc8584_csr_write(bus, phy0, 0x0ffc, 0x00c0a028);
  796. vsc8584_csr_write(bus, phy0, 0x0fe8, 0x0091b06c);
  797. vsc8584_csr_write(bus, phy0, 0x0fea, 0x00041600);
  798. vsc8584_csr_write(bus, phy0, 0x0f80, 0x00fffaff);
  799. vsc8584_csr_write(bus, phy0, 0x0fec, 0x00901809);
  800. vsc8584_csr_write(bus, phy0, 0x0ffe, 0x00b01007);
  801. vsc8584_csr_write(bus, phy0, 0x16b0, 0x00eeff00);
  802. vsc8584_csr_write(bus, phy0, 0x16b2, 0x00007000);
  803. vsc8584_csr_write(bus, phy0, 0x16b4, 0x00000814);
  804. bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
  805. MSCC_PHY_PAGE_EXT2);
  806. bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_CU_PMD_TX_CNTL, 0x028e);
  807. bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
  808. MSCC_PHY_PAGE_TR);
  809. vsc8584_csr_write(bus, phy0, 0x0486, 0x0008a518);
  810. vsc8584_csr_write(bus, phy0, 0x0488, 0x006dc696);
  811. vsc8584_csr_write(bus, phy0, 0x048a, 0x00000912);
  812. bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
  813. MSCC_PHY_PAGE_TEST);
  814. reg = bus->read(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_TEST_PAGE_8);
  815. reg &= ~TR_CLK_DISABLE;
  816. bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_TEST_PAGE_8, reg);
  817. bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
  818. MSCC_PHY_PAGE_STD);
  819. /* end of write broadcasting */
  820. reg = bus->read(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_EXT_CNTL_STATUS);
  821. reg &= ~SMI_BROADCAST_WR_EN;
  822. bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_EXT_CNTL_STATUS, reg);
  823. ret = vsc8584_get_fw_crc(bus, phy0,
  824. MSCC_VSC8584_REVB_INT8051_FW_START_ADDR, &crc,
  825. fw_patch_vsc8584,
  826. ARRAY_SIZE(fw_patch_vsc8584));
  827. if (ret)
  828. goto out;
  829. if (crc != MSCC_VSC8584_REVB_INT8051_FW_CRC) {
  830. debug("FW CRC is not the expected one, patching FW...\n");
  831. if (vsc8584_patch_fw(bus, phy0, fw_patch_vsc8584,
  832. ARRAY_SIZE(fw_patch_vsc8584)))
  833. pr_warn("failed to patch FW, expect non-optimal device\n");
  834. }
  835. vsc8584_micro_deassert_reset(bus, phy0, false);
  836. ret = vsc8584_get_fw_crc(bus, phy0,
  837. MSCC_VSC8584_REVB_INT8051_FW_START_ADDR, &crc,
  838. fw_patch_vsc8584,
  839. ARRAY_SIZE(fw_patch_vsc8584));
  840. if (ret)
  841. goto out;
  842. if (crc != MSCC_VSC8584_REVB_INT8051_FW_CRC)
  843. pr_warn("FW CRC after patching is not the expected one, expect non-optimal device\n");
  844. ret = vsc8584_micro_assert_reset(bus, phy0);
  845. if (ret)
  846. goto out;
  847. vsc8584_micro_deassert_reset(bus, phy0, true);
  848. out:
  849. bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
  850. MSCC_PHY_PAGE_STD);
  851. return ret;
  852. }
  853. static int mscc_vsc8531_vsc8541_init_scripts(struct phy_device *phydev)
  854. {
  855. u16 reg_val;
  856. /* Set to Access Token Ring Registers */
  857. phy_write(phydev, MDIO_DEVAD_NONE,
  858. MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_TR);
  859. /* Update LinkDetectCtrl default to optimized values */
  860. /* Determined during Silicon Validation Testing */
  861. phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_ADDR_16,
  862. (MSCC_PHY_TR_LINKDETCTRL_ADDR | MSCC_PHY_TR_16_READ));
  863. reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_17);
  864. reg_val = bitfield_replace(reg_val, MSCC_PHY_TR_LINKDETCTRL_POS,
  865. MSCC_PHY_TR_LINKDETCTRL_WIDTH,
  866. MSCC_PHY_TR_LINKDETCTRL_VAL);
  867. phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_17, reg_val);
  868. phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_ADDR_16,
  869. (MSCC_PHY_TR_LINKDETCTRL_ADDR | MSCC_PHY_TR_16_WRITE));
  870. /* Update VgaThresh100 defaults to optimized values */
  871. /* Determined during Silicon Validation Testing */
  872. phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_ADDR_16,
  873. (MSCC_PHY_TR_VGATHRESH100_ADDR | MSCC_PHY_TR_16_READ));
  874. reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_18);
  875. reg_val = bitfield_replace(reg_val, MSCC_PHY_TR_VGATHRESH100_POS,
  876. MSCC_PHY_TR_VGATHRESH100_WIDTH,
  877. MSCC_PHY_TR_VGATHRESH100_VAL);
  878. phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_18, reg_val);
  879. phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_ADDR_16,
  880. (MSCC_PHY_TR_VGATHRESH100_ADDR | MSCC_PHY_TR_16_WRITE));
  881. /* Update VgaGain10 defaults to optimized values */
  882. /* Determined during Silicon Validation Testing */
  883. phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_ADDR_16,
  884. (MSCC_PHY_TR_VGAGAIN10_ADDR | MSCC_PHY_TR_16_READ));
  885. reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_18);
  886. reg_val = bitfield_replace(reg_val, MSCC_PHY_TR_VGAGAIN10_U_POS,
  887. MSCC_PHY_TR_VGAGAIN10_U_WIDTH,
  888. MSCC_PHY_TR_VGAGAIN10_U_VAL);
  889. phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_18, reg_val);
  890. reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_17);
  891. reg_val = bitfield_replace(reg_val, MSCC_PHY_TR_VGAGAIN10_L_POS,
  892. MSCC_PHY_TR_VGAGAIN10_L_WIDTH,
  893. MSCC_PHY_TR_VGAGAIN10_L_VAL);
  894. phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_17, reg_val);
  895. phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_ADDR_16,
  896. (MSCC_PHY_TR_VGAGAIN10_ADDR | MSCC_PHY_TR_16_WRITE));
  897. /* Set back to Access Standard Page Registers */
  898. phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
  899. MSCC_PHY_PAGE_STD);
  900. return 0;
  901. }
  902. static int mscc_parse_status(struct phy_device *phydev)
  903. {
  904. u16 speed;
  905. u16 mii_reg;
  906. mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_AUX_CNTRL_STAT_REG);
  907. if (mii_reg & MIIM_AUX_CNTRL_STAT_F_DUPLEX)
  908. phydev->duplex = DUPLEX_FULL;
  909. else
  910. phydev->duplex = DUPLEX_HALF;
  911. speed = mii_reg & MIIM_AUX_CNTRL_STAT_SPEED_MASK;
  912. speed = speed >> MIIM_AUX_CNTRL_STAT_SPEED_POS;
  913. switch (speed) {
  914. case MIIM_AUX_CNTRL_STAT_SPEED_1000M:
  915. phydev->speed = SPEED_1000;
  916. break;
  917. case MIIM_AUX_CNTRL_STAT_SPEED_100M:
  918. phydev->speed = SPEED_100;
  919. break;
  920. case MIIM_AUX_CNTRL_STAT_SPEED_10M:
  921. phydev->speed = SPEED_10;
  922. break;
  923. default:
  924. phydev->speed = SPEED_10;
  925. break;
  926. }
  927. return 0;
  928. }
  929. static int mscc_startup(struct phy_device *phydev)
  930. {
  931. int retval;
  932. retval = genphy_update_link(phydev);
  933. if (retval)
  934. return retval;
  935. return mscc_parse_status(phydev);
  936. }
  937. static int mscc_phy_soft_reset(struct phy_device *phydev)
  938. {
  939. int retval = 0;
  940. u16 timeout = MSCC_PHY_RESET_TIMEOUT;
  941. u16 reg_val = 0;
  942. phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
  943. MSCC_PHY_PAGE_STD);
  944. reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMCR);
  945. phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, (reg_val | BMCR_RESET));
  946. reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMCR);
  947. while ((reg_val & BMCR_RESET) && (timeout > 0)) {
  948. reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMCR);
  949. timeout--;
  950. udelay(1000); /* 1 ms */
  951. }
  952. if (timeout == 0) {
  953. printf("MSCC PHY Soft_Reset Error: mac i/f = 0x%x\n",
  954. phydev->interface);
  955. retval = -ETIME;
  956. }
  957. return retval;
  958. }
  959. static int vsc8531_vsc8541_mac_config(struct phy_device *phydev)
  960. {
  961. u16 reg_val = 0;
  962. u16 mac_if = 0;
  963. u16 rx_clk_out = 0;
  964. /* For VSC8530/31 the only MAC modes are RMII/RGMII. */
  965. /* For VSC8540/41 the only MAC modes are (G)MII and RMII/RGMII. */
  966. /* Setup MAC Configuration */
  967. switch (phydev->interface) {
  968. case PHY_INTERFACE_MODE_MII:
  969. case PHY_INTERFACE_MODE_GMII:
  970. /* Set Reg23.12:11=0 */
  971. mac_if = MAC_IF_SELECTION_GMII;
  972. /* Set Reg20E2.11=1 */
  973. rx_clk_out = RX_CLK_OUT_DISABLE;
  974. break;
  975. case PHY_INTERFACE_MODE_RMII:
  976. /* Set Reg23.12:11=1 */
  977. mac_if = MAC_IF_SELECTION_RMII;
  978. /* Set Reg20E2.11=0 */
  979. rx_clk_out = RX_CLK_OUT_NORMAL;
  980. break;
  981. case PHY_INTERFACE_MODE_RGMII_TXID:
  982. case PHY_INTERFACE_MODE_RGMII_RXID:
  983. case PHY_INTERFACE_MODE_RGMII_ID:
  984. case PHY_INTERFACE_MODE_RGMII:
  985. /* Set Reg23.12:11=2 */
  986. mac_if = MAC_IF_SELECTION_RGMII;
  987. /* Set Reg20E2.11=0 */
  988. rx_clk_out = RX_CLK_OUT_NORMAL;
  989. break;
  990. default:
  991. printf("MSCC PHY - INVALID MAC i/f Config: mac i/f = 0x%x\n",
  992. phydev->interface);
  993. return -EINVAL;
  994. }
  995. phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
  996. MSCC_PHY_PAGE_STD);
  997. reg_val = phy_read(phydev, MDIO_DEVAD_NONE,
  998. MSCC_PHY_EXT_PHY_CNTL_1_REG);
  999. /* Set MAC i/f bits Reg23.12:11 */
  1000. reg_val = bitfield_replace(reg_val, MAC_IF_SELECTION_POS,
  1001. MAC_IF_SELECTION_WIDTH, mac_if);
  1002. /* Update Reg23.12:11 */
  1003. phy_write(phydev, MDIO_DEVAD_NONE,
  1004. MSCC_PHY_EXT_PHY_CNTL_1_REG, reg_val);
  1005. /* Setup ExtPg_2 Register Access */
  1006. phy_write(phydev, MDIO_DEVAD_NONE,
  1007. MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_EXT2);
  1008. /* Read Reg20E2 */
  1009. reg_val = phy_read(phydev, MDIO_DEVAD_NONE,
  1010. MSCC_PHY_RGMII_CNTL_REG);
  1011. reg_val = bitfield_replace(reg_val, RX_CLK_OUT_POS,
  1012. RX_CLK_OUT_WIDTH, rx_clk_out);
  1013. /* Update Reg20E2.11 */
  1014. phy_write(phydev, MDIO_DEVAD_NONE,
  1015. MSCC_PHY_RGMII_CNTL_REG, reg_val);
  1016. /* Before leaving - Change back to Std Page Register Access */
  1017. phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
  1018. MSCC_PHY_PAGE_STD);
  1019. return 0;
  1020. }
  1021. static int vsc8531_vsc8541_clkout_config(struct phy_device *phydev)
  1022. {
  1023. struct ofnode_phandle_args phandle_args;
  1024. u32 clkout_rate = 0;
  1025. u16 reg_val;
  1026. int retval;
  1027. retval = dev_read_phandle_with_args(phydev->dev, "phy-handle", NULL,
  1028. 0, 0, &phandle_args);
  1029. if (!retval)
  1030. clkout_rate = ofnode_read_u32_default(phandle_args.node,
  1031. "vsc8531,clk-out-frequency", 0);
  1032. switch (clkout_rate) {
  1033. case 0:
  1034. reg_val = 0;
  1035. break;
  1036. case 25000000:
  1037. reg_val = CLKOUT_FREQ_25M | CLKOUT_ENABLE;
  1038. break;
  1039. case 50000000:
  1040. reg_val = CLKOUT_FREQ_50M | CLKOUT_ENABLE;
  1041. break;
  1042. case 125000000:
  1043. reg_val = CLKOUT_FREQ_125M | CLKOUT_ENABLE;
  1044. break;
  1045. default:
  1046. printf("PHY 8530/31 invalid clkout rate %u\n",
  1047. clkout_rate);
  1048. return -EINVAL;
  1049. }
  1050. phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
  1051. MSCC_PHY_PAGE_GPIO);
  1052. phy_write(phydev, MDIO_DEVAD_NONE, MSCC_CLKOUT_CNTL, reg_val);
  1053. phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
  1054. MSCC_PHY_PAGE_STD);
  1055. return 0;
  1056. }
  1057. static int vsc8531_vsc8541_clk_skew_config(struct phy_device *phydev)
  1058. {
  1059. enum vsc_phy_rgmii_skew rx_clk_skew = VSC_PHY_RGMII_DELAY_200_PS;
  1060. enum vsc_phy_rgmii_skew tx_clk_skew = VSC_PHY_RGMII_DELAY_200_PS;
  1061. u16 reg_val;
  1062. if (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID ||
  1063. phydev->interface == PHY_INTERFACE_MODE_RGMII_ID)
  1064. rx_clk_skew = VSC_PHY_RGMII_DELAY_2000_PS;
  1065. if (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID ||
  1066. phydev->interface == PHY_INTERFACE_MODE_RGMII_ID)
  1067. tx_clk_skew = VSC_PHY_RGMII_DELAY_2000_PS;
  1068. phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
  1069. MSCC_PHY_PAGE_EXT2);
  1070. reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_RGMII_CNTL_REG);
  1071. /* Reg20E2 - Update RGMII RX_Clk Skews. */
  1072. reg_val = bitfield_replace(reg_val, RGMII_RX_CLK_DELAY_POS,
  1073. RGMII_RX_CLK_DELAY_WIDTH, rx_clk_skew);
  1074. /* Reg20E2 - Update RGMII TX_Clk Skews. */
  1075. reg_val = bitfield_replace(reg_val, RGMII_TX_CLK_DELAY_POS,
  1076. RGMII_TX_CLK_DELAY_WIDTH, tx_clk_skew);
  1077. phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_RGMII_CNTL_REG, reg_val);
  1078. phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
  1079. MSCC_PHY_PAGE_STD);
  1080. return 0;
  1081. }
  1082. static int vsc8531_config(struct phy_device *phydev)
  1083. {
  1084. int retval = -EINVAL;
  1085. u16 reg_val;
  1086. u16 rmii_clk_out;
  1087. enum vsc_phy_clk_slew edge_rate = VSC_PHY_CLK_SLEW_RATE_4;
  1088. /* For VSC8530/31 and VSC8540/41 the init scripts are the same */
  1089. mscc_vsc8531_vsc8541_init_scripts(phydev);
  1090. /* For VSC8530/31 the only MAC modes are RMII/RGMII. */
  1091. switch (phydev->interface) {
  1092. case PHY_INTERFACE_MODE_RMII:
  1093. case PHY_INTERFACE_MODE_RGMII:
  1094. case PHY_INTERFACE_MODE_RGMII_TXID:
  1095. case PHY_INTERFACE_MODE_RGMII_RXID:
  1096. case PHY_INTERFACE_MODE_RGMII_ID:
  1097. retval = vsc8531_vsc8541_mac_config(phydev);
  1098. if (retval != 0)
  1099. return retval;
  1100. retval = mscc_phy_soft_reset(phydev);
  1101. if (retval != 0)
  1102. return retval;
  1103. break;
  1104. default:
  1105. printf("PHY 8530/31 MAC i/f Config Error: mac i/f = 0x%x\n",
  1106. phydev->interface);
  1107. return -EINVAL;
  1108. }
  1109. /* Default RMII Clk Output to 0=OFF/1=ON */
  1110. rmii_clk_out = 0;
  1111. retval = vsc8531_vsc8541_clk_skew_config(phydev);
  1112. if (retval != 0)
  1113. return retval;
  1114. phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
  1115. MSCC_PHY_PAGE_EXT2);
  1116. reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_WOL_MAC_CONTROL);
  1117. /* Reg27E2 - Update Clk Slew Rate. */
  1118. reg_val = bitfield_replace(reg_val, EDGE_RATE_CNTL_POS,
  1119. EDGE_RATE_CNTL_WIDTH, edge_rate);
  1120. /* Reg27E2 - Update RMII Clk Out. */
  1121. reg_val = bitfield_replace(reg_val, RMII_CLK_OUT_ENABLE_POS,
  1122. RMII_CLK_OUT_ENABLE_WIDTH, rmii_clk_out);
  1123. /* Update Reg27E2 */
  1124. phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_WOL_MAC_CONTROL, reg_val);
  1125. phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
  1126. MSCC_PHY_PAGE_STD);
  1127. /* Configure the clk output */
  1128. retval = vsc8531_vsc8541_clkout_config(phydev);
  1129. if (retval != 0)
  1130. return retval;
  1131. return genphy_config_aneg(phydev);
  1132. }
  1133. static int vsc8541_config(struct phy_device *phydev)
  1134. {
  1135. int retval = -EINVAL;
  1136. u16 reg_val;
  1137. u16 rmii_clk_out;
  1138. enum vsc_phy_clk_slew edge_rate = VSC_PHY_CLK_SLEW_RATE_4;
  1139. /* For VSC8530/31 and VSC8540/41 the init scripts are the same */
  1140. mscc_vsc8531_vsc8541_init_scripts(phydev);
  1141. /* For VSC8540/41 the only MAC modes are (G)MII and RMII/RGMII. */
  1142. switch (phydev->interface) {
  1143. case PHY_INTERFACE_MODE_MII:
  1144. case PHY_INTERFACE_MODE_GMII:
  1145. case PHY_INTERFACE_MODE_RMII:
  1146. case PHY_INTERFACE_MODE_RGMII:
  1147. retval = vsc8531_vsc8541_mac_config(phydev);
  1148. if (retval != 0)
  1149. return retval;
  1150. retval = mscc_phy_soft_reset(phydev);
  1151. if (retval != 0)
  1152. return retval;
  1153. break;
  1154. default:
  1155. printf("PHY 8541 MAC i/f config Error: mac i/f = 0x%x\n",
  1156. phydev->interface);
  1157. return -EINVAL;
  1158. }
  1159. /* Default RMII Clk Output to 0=OFF/1=ON */
  1160. rmii_clk_out = 0;
  1161. retval = vsc8531_vsc8541_clk_skew_config(phydev);
  1162. if (retval != 0)
  1163. return retval;
  1164. phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
  1165. MSCC_PHY_PAGE_EXT2);
  1166. reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_WOL_MAC_CONTROL);
  1167. /* Reg27E2 - Update Clk Slew Rate. */
  1168. reg_val = bitfield_replace(reg_val, EDGE_RATE_CNTL_POS,
  1169. EDGE_RATE_CNTL_WIDTH, edge_rate);
  1170. /* Reg27E2 - Update RMII Clk Out. */
  1171. reg_val = bitfield_replace(reg_val, RMII_CLK_OUT_ENABLE_POS,
  1172. RMII_CLK_OUT_ENABLE_WIDTH, rmii_clk_out);
  1173. /* Update Reg27E2 */
  1174. phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_WOL_MAC_CONTROL, reg_val);
  1175. phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
  1176. MSCC_PHY_PAGE_STD);
  1177. /* Configure the clk output */
  1178. retval = vsc8531_vsc8541_clkout_config(phydev);
  1179. if (retval != 0)
  1180. return retval;
  1181. return genphy_config_aneg(phydev);
  1182. }
  1183. static int vsc8584_config_init(struct phy_device *phydev)
  1184. {
  1185. struct vsc85xx_priv *priv = phydev->priv;
  1186. int ret;
  1187. u16 addr;
  1188. u16 reg_val;
  1189. u16 val;
  1190. phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
  1191. MSCC_PHY_PAGE_EXT1);
  1192. addr = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_EXT_PHY_CNTL_4);
  1193. addr >>= PHY_CNTL_4_ADDR_POS;
  1194. ret = priv->config_pre(phydev);
  1195. if (ret)
  1196. return ret;
  1197. phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
  1198. MSCC_PHY_PAGE_GPIO);
  1199. if (phydev->interface == PHY_INTERFACE_MODE_QSGMII)
  1200. val = MAC_CFG_QSGMII;
  1201. else
  1202. val = MAC_CFG_SGMII;
  1203. reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_MAC_CFG_FASTLINK);
  1204. reg_val &= ~MAC_CFG_MASK;
  1205. reg_val |= val;
  1206. ret = phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_MAC_CFG_FASTLINK,
  1207. reg_val);
  1208. if (ret)
  1209. return ret;
  1210. reg_val = PROC_CMD_MCB_ACCESS_MAC_CONF | PROC_CMD_RST_CONF_PORT |
  1211. PROC_CMD_READ_MOD_WRITE_PORT;
  1212. if (phydev->interface == PHY_INTERFACE_MODE_QSGMII)
  1213. reg_val |= PROC_CMD_QSGMII_MAC;
  1214. else
  1215. reg_val |= PROC_CMD_SGMII_MAC;
  1216. ret = vsc8584_cmd(phydev->bus, phydev->addr, reg_val);
  1217. if (ret)
  1218. return ret;
  1219. mdelay(10);
  1220. /* Disable SerDes for 100Base-FX */
  1221. ret = vsc8584_cmd(phydev->bus, phydev->addr, PROC_CMD_FIBER_MEDIA_CONF |
  1222. PROC_CMD_FIBER_PORT(addr) | PROC_CMD_FIBER_DISABLE |
  1223. PROC_CMD_READ_MOD_WRITE_PORT |
  1224. PROC_CMD_RST_CONF_PORT | PROC_CMD_FIBER_100BASE_FX);
  1225. if (ret)
  1226. return ret;
  1227. /* Disable SerDes for 1000Base-X */
  1228. ret = vsc8584_cmd(phydev->bus, phydev->addr, PROC_CMD_FIBER_MEDIA_CONF |
  1229. PROC_CMD_FIBER_PORT(addr) | PROC_CMD_FIBER_DISABLE |
  1230. PROC_CMD_READ_MOD_WRITE_PORT |
  1231. PROC_CMD_RST_CONF_PORT | PROC_CMD_FIBER_1000BASE_X);
  1232. if (ret)
  1233. return ret;
  1234. phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
  1235. MSCC_PHY_PAGE_STD);
  1236. reg_val = phy_read(phydev, MDIO_DEVAD_NONE,
  1237. MSCC_PHY_EXT_PHY_CNTL_1_REG);
  1238. reg_val &= ~(MEDIA_OP_MODE_MASK | VSC8584_MAC_IF_SELECTION_MASK);
  1239. reg_val |= MEDIA_OP_MODE_COPPER |
  1240. (VSC8584_MAC_IF_SELECTION_SGMII <<
  1241. VSC8584_MAC_IF_SELECTION_POS);
  1242. ret = phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_EXT_PHY_CNTL_1_REG,
  1243. reg_val);
  1244. ret = mscc_phy_soft_reset(phydev);
  1245. if (ret != 0)
  1246. return ret;
  1247. return genphy_config(phydev);
  1248. }
  1249. static struct vsc85xx_priv vsc8574_priv = {
  1250. .config_pre = vsc8574_config_pre_init,
  1251. };
  1252. static int vsc8574_config(struct phy_device *phydev)
  1253. {
  1254. phydev->priv = &vsc8574_priv;
  1255. return vsc8584_config_init(phydev);
  1256. }
  1257. static struct vsc85xx_priv vsc8584_priv = {
  1258. .config_pre = vsc8584_config_pre_init,
  1259. };
  1260. static int vsc8584_config(struct phy_device *phydev)
  1261. {
  1262. phydev->priv = &vsc8584_priv;
  1263. return vsc8584_config_init(phydev);
  1264. }
  1265. static struct phy_driver VSC8530_driver = {
  1266. .name = "Microsemi VSC8530",
  1267. .uid = PHY_ID_VSC8530,
  1268. .mask = 0x000ffff0,
  1269. .features = PHY_BASIC_FEATURES,
  1270. .config = &vsc8531_config,
  1271. .startup = &mscc_startup,
  1272. .shutdown = &genphy_shutdown,
  1273. };
  1274. static struct phy_driver VSC8531_driver = {
  1275. .name = "Microsemi VSC8531",
  1276. .uid = PHY_ID_VSC8531,
  1277. .mask = 0x000ffff0,
  1278. .features = PHY_GBIT_FEATURES,
  1279. .config = &vsc8531_config,
  1280. .startup = &mscc_startup,
  1281. .shutdown = &genphy_shutdown,
  1282. };
  1283. static struct phy_driver VSC8540_driver = {
  1284. .name = "Microsemi VSC8540",
  1285. .uid = PHY_ID_VSC8540,
  1286. .mask = 0x000ffff0,
  1287. .features = PHY_BASIC_FEATURES,
  1288. .config = &vsc8541_config,
  1289. .startup = &mscc_startup,
  1290. .shutdown = &genphy_shutdown,
  1291. };
  1292. static struct phy_driver VSC8541_driver = {
  1293. .name = "Microsemi VSC8541",
  1294. .uid = PHY_ID_VSC8541,
  1295. .mask = 0x000ffff0,
  1296. .features = PHY_GBIT_FEATURES,
  1297. .config = &vsc8541_config,
  1298. .startup = &mscc_startup,
  1299. .shutdown = &genphy_shutdown,
  1300. };
  1301. static struct phy_driver VSC8574_driver = {
  1302. .name = "Microsemi VSC8574",
  1303. .uid = PHY_ID_VSC8574,
  1304. .mask = 0x000ffff0,
  1305. .features = PHY_GBIT_FEATURES,
  1306. .config = &vsc8574_config,
  1307. .startup = &mscc_startup,
  1308. .shutdown = &genphy_shutdown,
  1309. };
  1310. static struct phy_driver VSC8584_driver = {
  1311. .name = "Microsemi VSC8584",
  1312. .uid = PHY_ID_VSC8584,
  1313. .mask = 0x000ffff0,
  1314. .features = PHY_GBIT_FEATURES,
  1315. .config = &vsc8584_config,
  1316. .startup = &mscc_startup,
  1317. .shutdown = &genphy_shutdown,
  1318. };
  1319. int phy_mscc_init(void)
  1320. {
  1321. phy_register(&VSC8530_driver);
  1322. phy_register(&VSC8531_driver);
  1323. phy_register(&VSC8540_driver);
  1324. phy_register(&VSC8541_driver);
  1325. phy_register(&VSC8574_driver);
  1326. phy_register(&VSC8584_driver);
  1327. return 0;
  1328. }