703-phy-support-layerscape.patch 46 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763
  1. From 8949ebc0c5b982eab7ca493dad7b86c30befa6ec Mon Sep 17 00:00:00 2001
  2. From: Yangbo Lu <[email protected]>
  3. Date: Wed, 17 Jan 2018 15:01:30 +0800
  4. Subject: [PATCH 09/30] phy: support layerscape
  5. This is an integrated patch for layerscape mdio-phy support.
  6. Signed-off-by: Bogdan Purcareata <[email protected]>
  7. Signed-off-by: Zhang Ying-22455 <[email protected]>
  8. Signed-off-by: costi <[email protected]>
  9. Signed-off-by: Madalin Bucur <[email protected]>
  10. Signed-off-by: Shaohui Xie <[email protected]>
  11. Signed-off-by: Florian Fainelli <[email protected]>
  12. Signed-off-by: Yangbo Lu <[email protected]>
  13. ---
  14. drivers/net/phy/Kconfig | 11 +
  15. drivers/net/phy/Makefile | 2 +
  16. drivers/net/phy/aquantia.c | 28 +
  17. drivers/net/phy/cortina.c | 118 ++++
  18. drivers/net/phy/fsl_backplane.c | 1358 +++++++++++++++++++++++++++++++++++++++
  19. drivers/net/phy/marvell.c | 2 +-
  20. drivers/net/phy/phy.c | 23 +-
  21. drivers/net/phy/phy_device.c | 6 +-
  22. drivers/net/phy/swphy.c | 1 +
  23. include/linux/phy.h | 6 +
  24. 10 files changed, 1547 insertions(+), 8 deletions(-)
  25. create mode 100644 drivers/net/phy/cortina.c
  26. create mode 100644 drivers/net/phy/fsl_backplane.c
  27. --- a/drivers/net/phy/Kconfig
  28. +++ b/drivers/net/phy/Kconfig
  29. @@ -89,6 +89,12 @@ config MDIO_BUS_MUX_MMIOREG
  30. config MDIO_CAVIUM
  31. tristate
  32. +config MDIO_FSL_BACKPLANE
  33. + tristate "Support for backplane on Freescale XFI interface"
  34. + depends on OF_MDIO
  35. + help
  36. + This module provides a driver for Freescale XFI's backplane.
  37. +
  38. config MDIO_GPIO
  39. tristate "GPIO lib-based bitbanged MDIO buses"
  40. depends on MDIO_BITBANG && GPIOLIB
  41. @@ -298,6 +304,11 @@ config CICADA_PHY
  42. ---help---
  43. Currently supports the cis8204
  44. +config CORTINA_PHY
  45. + tristate "Cortina EDC CDR 10G Ethernet PHY"
  46. + ---help---
  47. + Currently supports the CS4340 phy.
  48. +
  49. config DAVICOM_PHY
  50. tristate "Davicom PHYs"
  51. ---help---
  52. --- a/drivers/net/phy/Makefile
  53. +++ b/drivers/net/phy/Makefile
  54. @@ -30,6 +30,7 @@ obj-$(CONFIG_MDIO_BUS_MUX_BCM_IPROC) +=
  55. obj-$(CONFIG_MDIO_BUS_MUX_GPIO) += mdio-mux-gpio.o
  56. obj-$(CONFIG_MDIO_BUS_MUX_MMIOREG) += mdio-mux-mmioreg.o
  57. obj-$(CONFIG_MDIO_CAVIUM) += mdio-cavium.o
  58. +obj-$(CONFIG_MDIO_FSL_BACKPLANE) += fsl_backplane.o
  59. obj-$(CONFIG_MDIO_GPIO) += mdio-gpio.o
  60. obj-$(CONFIG_MDIO_HISI_FEMAC) += mdio-hisi-femac.o
  61. obj-$(CONFIG_MDIO_MOXART) += mdio-moxart.o
  62. @@ -48,6 +49,7 @@ obj-$(CONFIG_BCM_CYGNUS_PHY) += bcm-cygn
  63. obj-$(CONFIG_BCM_NET_PHYLIB) += bcm-phy-lib.o
  64. obj-$(CONFIG_BROADCOM_PHY) += broadcom.o
  65. obj-$(CONFIG_CICADA_PHY) += cicada.o
  66. +obj-$(CONFIG_CORTINA_PHY) += cortina.o
  67. obj-$(CONFIG_DAVICOM_PHY) += davicom.o
  68. obj-$(CONFIG_DP83640_PHY) += dp83640.o
  69. obj-$(CONFIG_DP83848_PHY) += dp83848.o
  70. --- a/drivers/net/phy/aquantia.c
  71. +++ b/drivers/net/phy/aquantia.c
  72. @@ -21,6 +21,8 @@
  73. #define PHY_ID_AQ1202 0x03a1b445
  74. #define PHY_ID_AQ2104 0x03a1b460
  75. #define PHY_ID_AQR105 0x03a1b4a2
  76. +#define PHY_ID_AQR106 0x03a1b4d0
  77. +#define PHY_ID_AQR107 0x03a1b4e0
  78. #define PHY_ID_AQR405 0x03a1b4b0
  79. #define PHY_AQUANTIA_FEATURES (SUPPORTED_10000baseT_Full | \
  80. @@ -154,6 +156,30 @@ static struct phy_driver aquantia_driver
  81. .read_status = aquantia_read_status,
  82. },
  83. {
  84. + .phy_id = PHY_ID_AQR106,
  85. + .phy_id_mask = 0xfffffff0,
  86. + .name = "Aquantia AQR106",
  87. + .features = PHY_AQUANTIA_FEATURES,
  88. + .flags = PHY_HAS_INTERRUPT,
  89. + .aneg_done = aquantia_aneg_done,
  90. + .config_aneg = aquantia_config_aneg,
  91. + .config_intr = aquantia_config_intr,
  92. + .ack_interrupt = aquantia_ack_interrupt,
  93. + .read_status = aquantia_read_status,
  94. +},
  95. +{
  96. + .phy_id = PHY_ID_AQR107,
  97. + .phy_id_mask = 0xfffffff0,
  98. + .name = "Aquantia AQR107",
  99. + .features = PHY_AQUANTIA_FEATURES,
  100. + .flags = PHY_HAS_INTERRUPT,
  101. + .aneg_done = aquantia_aneg_done,
  102. + .config_aneg = aquantia_config_aneg,
  103. + .config_intr = aquantia_config_intr,
  104. + .ack_interrupt = aquantia_ack_interrupt,
  105. + .read_status = aquantia_read_status,
  106. +},
  107. +{
  108. .phy_id = PHY_ID_AQR405,
  109. .phy_id_mask = 0xfffffff0,
  110. .name = "Aquantia AQR405",
  111. @@ -173,6 +199,8 @@ static struct mdio_device_id __maybe_unu
  112. { PHY_ID_AQ1202, 0xfffffff0 },
  113. { PHY_ID_AQ2104, 0xfffffff0 },
  114. { PHY_ID_AQR105, 0xfffffff0 },
  115. + { PHY_ID_AQR106, 0xfffffff0 },
  116. + { PHY_ID_AQR107, 0xfffffff0 },
  117. { PHY_ID_AQR405, 0xfffffff0 },
  118. { }
  119. };
  120. --- /dev/null
  121. +++ b/drivers/net/phy/cortina.c
  122. @@ -0,0 +1,118 @@
  123. +/*
  124. + * Copyright 2017 NXP
  125. + *
  126. + * This program is free software; you can redistribute it and/or modify
  127. + * it under the terms of the GNU General Public License as published by
  128. + * the Free Software Foundation; either version 2 of the License, or
  129. + * (at your option) any later version.
  130. + *
  131. + * This program is distributed in the hope that it will be useful,
  132. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  133. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  134. + * GNU General Public License for more details.
  135. + *
  136. + * CORTINA is a registered trademark of Cortina Systems, Inc.
  137. + *
  138. + */
  139. +#include <linux/module.h>
  140. +#include <linux/phy.h>
  141. +
  142. +#define PHY_ID_CS4340 0x13e51002
  143. +
  144. +#define VILLA_GLOBAL_CHIP_ID_LSB 0x0
  145. +#define VILLA_GLOBAL_CHIP_ID_MSB 0x1
  146. +
  147. +#define VILLA_GLOBAL_GPIO_1_INTS 0x017
  148. +
  149. +static int cortina_read_reg(struct phy_device *phydev, u16 regnum)
  150. +{
  151. + return mdiobus_read(phydev->mdio.bus, phydev->mdio.addr,
  152. + MII_ADDR_C45 | regnum);
  153. +}
  154. +
  155. +static int cortina_config_aneg(struct phy_device *phydev)
  156. +{
  157. + phydev->supported = SUPPORTED_10000baseT_Full;
  158. + phydev->advertising = SUPPORTED_10000baseT_Full;
  159. +
  160. + return 0;
  161. +}
  162. +
  163. +static int cortina_read_status(struct phy_device *phydev)
  164. +{
  165. + int gpio_int_status, ret = 0;
  166. +
  167. + gpio_int_status = cortina_read_reg(phydev, VILLA_GLOBAL_GPIO_1_INTS);
  168. + if (gpio_int_status < 0) {
  169. + ret = gpio_int_status;
  170. + goto err;
  171. + }
  172. +
  173. + if (gpio_int_status & 0x8) {
  174. + /* up when edc_convergedS set */
  175. + phydev->speed = SPEED_10000;
  176. + phydev->duplex = DUPLEX_FULL;
  177. + phydev->link = 1;
  178. + } else {
  179. + phydev->link = 0;
  180. + }
  181. +
  182. +err:
  183. + return ret;
  184. +}
  185. +
  186. +static int cortina_soft_reset(struct phy_device *phydev)
  187. +{
  188. + return 0;
  189. +}
  190. +
  191. +static int cortina_probe(struct phy_device *phydev)
  192. +{
  193. + u32 phy_id = 0;
  194. + int id_lsb = 0, id_msb = 0;
  195. +
  196. + /* Read device id from phy registers. */
  197. + id_lsb = cortina_read_reg(phydev, VILLA_GLOBAL_CHIP_ID_LSB);
  198. + if (id_lsb < 0)
  199. + return -ENXIO;
  200. +
  201. + phy_id = id_lsb << 16;
  202. +
  203. + id_msb = cortina_read_reg(phydev, VILLA_GLOBAL_CHIP_ID_MSB);
  204. + if (id_msb < 0)
  205. + return -ENXIO;
  206. +
  207. + phy_id |= id_msb;
  208. +
  209. + /* Make sure the device tree binding matched the driver with the
  210. + * right device.
  211. + */
  212. + if (phy_id != phydev->drv->phy_id) {
  213. + phydev_err(phydev, "Error matching phy with %s driver\n",
  214. + phydev->drv->name);
  215. + return -ENODEV;
  216. + }
  217. +
  218. + return 0;
  219. +}
  220. +
  221. +static struct phy_driver cortina_driver[] = {
  222. +{
  223. + .phy_id = PHY_ID_CS4340,
  224. + .phy_id_mask = 0xffffffff,
  225. + .name = "Cortina CS4340",
  226. + .config_aneg = cortina_config_aneg,
  227. + .read_status = cortina_read_status,
  228. + .soft_reset = cortina_soft_reset,
  229. + .probe = cortina_probe,
  230. +},
  231. +};
  232. +
  233. +module_phy_driver(cortina_driver);
  234. +
  235. +static struct mdio_device_id __maybe_unused cortina_tbl[] = {
  236. + { PHY_ID_CS4340, 0xffffffff},
  237. + {},
  238. +};
  239. +
  240. +MODULE_DEVICE_TABLE(mdio, cortina_tbl);
  241. --- /dev/null
  242. +++ b/drivers/net/phy/fsl_backplane.c
  243. @@ -0,0 +1,1358 @@
  244. +/* Freescale backplane driver.
  245. + * Author: Shaohui Xie <[email protected]>
  246. + *
  247. + * Copyright 2015 Freescale Semiconductor, Inc.
  248. + *
  249. + * Licensed under the GPL-2 or later.
  250. + */
  251. +
  252. +#include <linux/kernel.h>
  253. +#include <linux/module.h>
  254. +#include <linux/mii.h>
  255. +#include <linux/mdio.h>
  256. +#include <linux/ethtool.h>
  257. +#include <linux/phy.h>
  258. +#include <linux/io.h>
  259. +#include <linux/of.h>
  260. +#include <linux/of_net.h>
  261. +#include <linux/of_address.h>
  262. +#include <linux/of_platform.h>
  263. +#include <linux/timer.h>
  264. +#include <linux/delay.h>
  265. +#include <linux/workqueue.h>
  266. +
  267. +/* XFI PCS Device Identifier */
  268. +#define FSL_PCS_PHY_ID 0x0083e400
  269. +
  270. +/* Freescale KR PMD registers */
  271. +#define FSL_KR_PMD_CTRL 0x96
  272. +#define FSL_KR_PMD_STATUS 0x97
  273. +#define FSL_KR_LP_CU 0x98
  274. +#define FSL_KR_LP_STATUS 0x99
  275. +#define FSL_KR_LD_CU 0x9a
  276. +#define FSL_KR_LD_STATUS 0x9b
  277. +
  278. +/* Freescale KR PMD defines */
  279. +#define PMD_RESET 0x1
  280. +#define PMD_STATUS_SUP_STAT 0x4
  281. +#define PMD_STATUS_FRAME_LOCK 0x2
  282. +#define TRAIN_EN 0x3
  283. +#define TRAIN_DISABLE 0x1
  284. +#define RX_STAT 0x1
  285. +
  286. +#define FSL_KR_RX_LINK_STAT_MASK 0x1000
  287. +#define FSL_XFI_PCS_10GR_SR1 0x20
  288. +
  289. +/* Freescale KX PCS mode register */
  290. +#define FSL_PCS_IF_MODE 0x8014
  291. +
  292. +/* Freescale KX PCS mode register init value */
  293. +#define IF_MODE_INIT 0x8
  294. +
  295. +/* Freescale KX/KR AN registers */
  296. +#define FSL_AN_AD1 0x11
  297. +#define FSL_AN_BP_STAT 0x30
  298. +
  299. +/* Freescale KX/KR AN registers defines */
  300. +#define AN_CTRL_INIT 0x1200
  301. +#define KX_AN_AD1_INIT 0x25
  302. +#define KR_AN_AD1_INIT 0x85
  303. +#define AN_LNK_UP_MASK 0x4
  304. +#define KR_AN_MASK 0x8
  305. +#define TRAIN_FAIL 0x8
  306. +
  307. +/* C(-1) */
  308. +#define BIN_M1 0
  309. +/* C(1) */
  310. +#define BIN_LONG 1
  311. +#define BIN_M1_SEL 6
  312. +#define BIN_Long_SEL 7
  313. +#define CDR_SEL_MASK 0x00070000
  314. +#define BIN_SNAPSHOT_NUM 5
  315. +#define BIN_M1_THRESHOLD 3
  316. +#define BIN_LONG_THRESHOLD 2
  317. +
  318. +#define PRE_COE_SHIFT 22
  319. +#define POST_COE_SHIFT 16
  320. +#define ZERO_COE_SHIFT 8
  321. +
  322. +#define PRE_COE_MAX 0x0
  323. +#define PRE_COE_MIN 0x8
  324. +#define POST_COE_MAX 0x0
  325. +#define POST_COE_MIN 0x10
  326. +#define ZERO_COE_MAX 0x30
  327. +#define ZERO_COE_MIN 0x0
  328. +
  329. +#define TECR0_INIT 0x24200000
  330. +#define RATIO_PREQ 0x3
  331. +#define RATIO_PST1Q 0xd
  332. +#define RATIO_EQ 0x20
  333. +
  334. +#define GCR0_RESET_MASK 0x600000
  335. +#define GCR1_SNP_START_MASK 0x00000040
  336. +#define GCR1_CTL_SNP_START_MASK 0x00002000
  337. +#define GCR1_REIDL_TH_MASK 0x00700000
  338. +#define GCR1_REIDL_EX_SEL_MASK 0x000c0000
  339. +#define GCR1_REIDL_ET_MAS_MASK 0x00004000
  340. +#define TECR0_AMP_RED_MASK 0x0000003f
  341. +
  342. +#define RECR1_CTL_SNP_DONE_MASK 0x00000002
  343. +#define RECR1_SNP_DONE_MASK 0x00000004
  344. +#define TCSR1_SNP_DATA_MASK 0x0000ffc0
  345. +#define TCSR1_SNP_DATA_SHIFT 6
  346. +#define TCSR1_EQ_SNPBIN_SIGN_MASK 0x100
  347. +
  348. +#define RECR1_GAINK2_MASK 0x0f000000
  349. +#define RECR1_GAINK2_SHIFT 24
  350. +#define RECR1_GAINK3_MASK 0x000f0000
  351. +#define RECR1_GAINK3_SHIFT 16
  352. +#define RECR1_OFFSET_MASK 0x00003f80
  353. +#define RECR1_OFFSET_SHIFT 7
  354. +#define RECR1_BLW_MASK 0x00000f80
  355. +#define RECR1_BLW_SHIFT 7
  356. +#define EYE_CTRL_SHIFT 12
  357. +#define BASE_WAND_SHIFT 10
  358. +
  359. +#define XGKR_TIMEOUT 1050
  360. +
  361. +#define INCREMENT 1
  362. +#define DECREMENT 2
  363. +#define TIMEOUT_LONG 3
  364. +#define TIMEOUT_M1 3
  365. +
  366. +#define RX_READY_MASK 0x8000
  367. +#define PRESET_MASK 0x2000
  368. +#define INIT_MASK 0x1000
  369. +#define COP1_MASK 0x30
  370. +#define COP1_SHIFT 4
  371. +#define COZ_MASK 0xc
  372. +#define COZ_SHIFT 2
  373. +#define COM1_MASK 0x3
  374. +#define COM1_SHIFT 0
  375. +#define REQUEST_MASK 0x3f
  376. +#define LD_ALL_MASK (PRESET_MASK | INIT_MASK | \
  377. + COP1_MASK | COZ_MASK | COM1_MASK)
  378. +
  379. +#define NEW_ALGORITHM_TRAIN_TX
  380. +#ifdef NEW_ALGORITHM_TRAIN_TX
  381. +#define FORCE_INC_COP1_NUMBER 0
  382. +#define FORCE_INC_COM1_NUMBER 1
  383. +#endif
  384. +
  385. +#define VAL_INVALID 0xff
  386. +
  387. +static const u32 preq_table[] = {0x0, 0x1, 0x3, 0x5,
  388. + 0x7, 0x9, 0xb, 0xc, VAL_INVALID};
  389. +static const u32 pst1q_table[] = {0x0, 0x1, 0x3, 0x5, 0x7,
  390. + 0x9, 0xb, 0xd, 0xf, 0x10, VAL_INVALID};
  391. +
  392. +enum backplane_mode {
  393. + PHY_BACKPLANE_1000BASE_KX,
  394. + PHY_BACKPLANE_10GBASE_KR,
  395. + PHY_BACKPLANE_INVAL
  396. +};
  397. +
  398. +enum coe_filed {
  399. + COE_COP1,
  400. + COE_COZ,
  401. + COE_COM
  402. +};
  403. +
  404. +enum coe_update {
  405. + COE_NOTUPDATED,
  406. + COE_UPDATED,
  407. + COE_MIN,
  408. + COE_MAX,
  409. + COE_INV
  410. +};
  411. +
  412. +enum train_state {
  413. + DETECTING_LP,
  414. + TRAINED,
  415. +};
  416. +
  417. +struct per_lane_ctrl_status {
  418. + __be32 gcr0; /* 0x.000 - General Control Register 0 */
  419. + __be32 gcr1; /* 0x.004 - General Control Register 1 */
  420. + __be32 gcr2; /* 0x.008 - General Control Register 2 */
  421. + __be32 resv1; /* 0x.00C - Reserved */
  422. + __be32 recr0; /* 0x.010 - Receive Equalization Control Register 0 */
  423. + __be32 recr1; /* 0x.014 - Receive Equalization Control Register 1 */
  424. + __be32 tecr0; /* 0x.018 - Transmit Equalization Control Register 0 */
  425. + __be32 resv2; /* 0x.01C - Reserved */
  426. + __be32 tlcr0; /* 0x.020 - TTL Control Register 0 */
  427. + __be32 tlcr1; /* 0x.024 - TTL Control Register 1 */
  428. + __be32 tlcr2; /* 0x.028 - TTL Control Register 2 */
  429. + __be32 tlcr3; /* 0x.02C - TTL Control Register 3 */
  430. + __be32 tcsr0; /* 0x.030 - Test Control/Status Register 0 */
  431. + __be32 tcsr1; /* 0x.034 - Test Control/Status Register 1 */
  432. + __be32 tcsr2; /* 0x.038 - Test Control/Status Register 2 */
  433. + __be32 tcsr3; /* 0x.03C - Test Control/Status Register 3 */
  434. +};
  435. +
  436. +struct tx_condition {
  437. + bool bin_m1_late_early;
  438. + bool bin_long_late_early;
  439. + bool bin_m1_stop;
  440. + bool bin_long_stop;
  441. + bool tx_complete;
  442. + bool sent_init;
  443. + int m1_min_max_cnt;
  444. + int long_min_max_cnt;
  445. +#ifdef NEW_ALGORITHM_TRAIN_TX
  446. + int pre_inc;
  447. + int post_inc;
  448. +#endif
  449. +};
  450. +
  451. +struct fsl_xgkr_inst {
  452. + void *reg_base;
  453. + struct phy_device *phydev;
  454. + struct tx_condition tx_c;
  455. + struct delayed_work xgkr_wk;
  456. + enum train_state state;
  457. + u32 ld_update;
  458. + u32 ld_status;
  459. + u32 ratio_preq;
  460. + u32 ratio_pst1q;
  461. + u32 adpt_eq;
  462. +};
  463. +
  464. +static void tx_condition_init(struct tx_condition *tx_c)
  465. +{
  466. + tx_c->bin_m1_late_early = true;
  467. + tx_c->bin_long_late_early = false;
  468. + tx_c->bin_m1_stop = false;
  469. + tx_c->bin_long_stop = false;
  470. + tx_c->tx_complete = false;
  471. + tx_c->sent_init = false;
  472. + tx_c->m1_min_max_cnt = 0;
  473. + tx_c->long_min_max_cnt = 0;
  474. +#ifdef NEW_ALGORITHM_TRAIN_TX
  475. + tx_c->pre_inc = FORCE_INC_COM1_NUMBER;
  476. + tx_c->post_inc = FORCE_INC_COP1_NUMBER;
  477. +#endif
  478. +}
  479. +
  480. +void tune_tecr0(struct fsl_xgkr_inst *inst)
  481. +{
  482. + struct per_lane_ctrl_status *reg_base = inst->reg_base;
  483. + u32 val;
  484. +
  485. + val = TECR0_INIT |
  486. + inst->adpt_eq << ZERO_COE_SHIFT |
  487. + inst->ratio_preq << PRE_COE_SHIFT |
  488. + inst->ratio_pst1q << POST_COE_SHIFT;
  489. +
  490. + /* reset the lane */
  491. + iowrite32(ioread32(&reg_base->gcr0) & ~GCR0_RESET_MASK,
  492. + &reg_base->gcr0);
  493. + udelay(1);
  494. + iowrite32(val, &reg_base->tecr0);
  495. + udelay(1);
  496. + /* unreset the lane */
  497. + iowrite32(ioread32(&reg_base->gcr0) | GCR0_RESET_MASK,
  498. + &reg_base->gcr0);
  499. + udelay(1);
  500. +}
  501. +
  502. +static void start_lt(struct phy_device *phydev)
  503. +{
  504. + phy_write_mmd(phydev, MDIO_MMD_PMAPMD, FSL_KR_PMD_CTRL, TRAIN_EN);
  505. +}
  506. +
  507. +static void stop_lt(struct phy_device *phydev)
  508. +{
  509. + phy_write_mmd(phydev, MDIO_MMD_PMAPMD, FSL_KR_PMD_CTRL, TRAIN_DISABLE);
  510. +}
  511. +
  512. +static void reset_gcr0(struct fsl_xgkr_inst *inst)
  513. +{
  514. + struct per_lane_ctrl_status *reg_base = inst->reg_base;
  515. +
  516. + iowrite32(ioread32(&reg_base->gcr0) & ~GCR0_RESET_MASK,
  517. + &reg_base->gcr0);
  518. + udelay(1);
  519. + iowrite32(ioread32(&reg_base->gcr0) | GCR0_RESET_MASK,
  520. + &reg_base->gcr0);
  521. + udelay(1);
  522. +}
  523. +
  524. +void lane_set_1gkx(void *reg)
  525. +{
  526. + struct per_lane_ctrl_status *reg_base = reg;
  527. + u32 val;
  528. +
  529. + /* reset the lane */
  530. + iowrite32(ioread32(&reg_base->gcr0) & ~GCR0_RESET_MASK,
  531. + &reg_base->gcr0);
  532. + udelay(1);
  533. +
  534. + /* set gcr1 for 1GKX */
  535. + val = ioread32(&reg_base->gcr1);
  536. + val &= ~(GCR1_REIDL_TH_MASK | GCR1_REIDL_EX_SEL_MASK |
  537. + GCR1_REIDL_ET_MAS_MASK);
  538. + iowrite32(val, &reg_base->gcr1);
  539. + udelay(1);
  540. +
  541. + /* set tecr0 for 1GKX */
  542. + val = ioread32(&reg_base->tecr0);
  543. + val &= ~TECR0_AMP_RED_MASK;
  544. + iowrite32(val, &reg_base->tecr0);
  545. + udelay(1);
  546. +
  547. + /* unreset the lane */
  548. + iowrite32(ioread32(&reg_base->gcr0) | GCR0_RESET_MASK,
  549. + &reg_base->gcr0);
  550. + udelay(1);
  551. +}
  552. +
  553. +static void reset_lt(struct phy_device *phydev)
  554. +{
  555. + phy_write_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_CTRL1, PMD_RESET);
  556. + phy_write_mmd(phydev, MDIO_MMD_PMAPMD, FSL_KR_PMD_CTRL, TRAIN_DISABLE);
  557. + phy_write_mmd(phydev, MDIO_MMD_PMAPMD, FSL_KR_LD_CU, 0);
  558. + phy_write_mmd(phydev, MDIO_MMD_PMAPMD, FSL_KR_LD_STATUS, 0);
  559. + phy_write_mmd(phydev, MDIO_MMD_PMAPMD, FSL_KR_PMD_STATUS, 0);
  560. + phy_write_mmd(phydev, MDIO_MMD_PMAPMD, FSL_KR_LP_CU, 0);
  561. + phy_write_mmd(phydev, MDIO_MMD_PMAPMD, FSL_KR_LP_STATUS, 0);
  562. +}
  563. +
  564. +static void start_xgkr_state_machine(struct delayed_work *work)
  565. +{
  566. + queue_delayed_work(system_power_efficient_wq, work,
  567. + msecs_to_jiffies(XGKR_TIMEOUT));
  568. +}
  569. +
  570. +static void start_xgkr_an(struct phy_device *phydev)
  571. +{
  572. + struct fsl_xgkr_inst *inst;
  573. +
  574. + reset_lt(phydev);
  575. + phy_write_mmd(phydev, MDIO_MMD_AN, FSL_AN_AD1, KR_AN_AD1_INIT);
  576. + phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_CTRL1, AN_CTRL_INIT);
  577. +
  578. + inst = phydev->priv;
  579. +
  580. + /* start state machine*/
  581. + start_xgkr_state_machine(&inst->xgkr_wk);
  582. +}
  583. +
  584. +static void start_1gkx_an(struct phy_device *phydev)
  585. +{
  586. + phy_write_mmd(phydev, MDIO_MMD_PCS, FSL_PCS_IF_MODE, IF_MODE_INIT);
  587. + phy_write_mmd(phydev, MDIO_MMD_AN, FSL_AN_AD1, KX_AN_AD1_INIT);
  588. + phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_STAT1);
  589. + phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_CTRL1, AN_CTRL_INIT);
  590. +}
  591. +
  592. +static void ld_coe_status(struct fsl_xgkr_inst *inst)
  593. +{
  594. + phy_write_mmd(inst->phydev, MDIO_MMD_PMAPMD,
  595. + FSL_KR_LD_STATUS, inst->ld_status);
  596. +}
  597. +
  598. +static void ld_coe_update(struct fsl_xgkr_inst *inst)
  599. +{
  600. + dev_dbg(&inst->phydev->mdio.dev, "sending request: %x\n", inst->ld_update);
  601. + phy_write_mmd(inst->phydev, MDIO_MMD_PMAPMD,
  602. + FSL_KR_LD_CU, inst->ld_update);
  603. +}
  604. +
  605. +static void init_inst(struct fsl_xgkr_inst *inst, int reset)
  606. +{
  607. + if (reset) {
  608. + inst->ratio_preq = RATIO_PREQ;
  609. + inst->ratio_pst1q = RATIO_PST1Q;
  610. + inst->adpt_eq = RATIO_EQ;
  611. + tune_tecr0(inst);
  612. + }
  613. +
  614. + tx_condition_init(&inst->tx_c);
  615. + inst->state = DETECTING_LP;
  616. + inst->ld_status &= RX_READY_MASK;
  617. + ld_coe_status(inst);
  618. + inst->ld_update = 0;
  619. + inst->ld_status &= ~RX_READY_MASK;
  620. + ld_coe_status(inst);
  621. +}
  622. +
  623. +#ifdef NEW_ALGORITHM_TRAIN_TX
  624. +static int get_median_gaink2(u32 *reg)
  625. +{
  626. + int gaink2_snap_shot[BIN_SNAPSHOT_NUM];
  627. + u32 rx_eq_snp;
  628. + struct per_lane_ctrl_status *reg_base;
  629. + int timeout;
  630. + int i, j, tmp, pos;
  631. +
  632. + reg_base = (struct per_lane_ctrl_status *)reg;
  633. +
  634. + for (i = 0; i < BIN_SNAPSHOT_NUM; i++) {
  635. + /* wait RECR1_CTL_SNP_DONE_MASK has cleared */
  636. + timeout = 100;
  637. + while (ioread32(&reg_base->recr1) &
  638. + RECR1_CTL_SNP_DONE_MASK) {
  639. + udelay(1);
  640. + timeout--;
  641. + if (timeout == 0)
  642. + break;
  643. + }
  644. +
  645. + /* start snap shot */
  646. + iowrite32((ioread32(&reg_base->gcr1) |
  647. + GCR1_CTL_SNP_START_MASK),
  648. + &reg_base->gcr1);
  649. +
  650. + /* wait for SNP done */
  651. + timeout = 100;
  652. + while (!(ioread32(&reg_base->recr1) &
  653. + RECR1_CTL_SNP_DONE_MASK)) {
  654. + udelay(1);
  655. + timeout--;
  656. + if (timeout == 0)
  657. + break;
  658. + }
  659. +
  660. + /* read and save the snap shot */
  661. + rx_eq_snp = ioread32(&reg_base->recr1);
  662. + gaink2_snap_shot[i] = (rx_eq_snp & RECR1_GAINK2_MASK) >>
  663. + RECR1_GAINK2_SHIFT;
  664. +
  665. + /* terminate the snap shot by setting GCR1[REQ_CTL_SNP] */
  666. + iowrite32((ioread32(&reg_base->gcr1) &
  667. + ~GCR1_CTL_SNP_START_MASK),
  668. + &reg_base->gcr1);
  669. + }
  670. +
  671. + /* get median of the 5 snap shot */
  672. + for (i = 0; i < BIN_SNAPSHOT_NUM - 1; i++) {
  673. + tmp = gaink2_snap_shot[i];
  674. + pos = i;
  675. + for (j = i + 1; j < BIN_SNAPSHOT_NUM; j++) {
  676. + if (gaink2_snap_shot[j] < tmp) {
  677. + tmp = gaink2_snap_shot[j];
  678. + pos = j;
  679. + }
  680. + }
  681. +
  682. + gaink2_snap_shot[pos] = gaink2_snap_shot[i];
  683. + gaink2_snap_shot[i] = tmp;
  684. + }
  685. +
  686. + return gaink2_snap_shot[2];
  687. +}
  688. +#endif
  689. +
  690. +static bool is_bin_early(int bin_sel, void *reg)
  691. +{
  692. + bool early = false;
  693. + int bin_snap_shot[BIN_SNAPSHOT_NUM];
  694. + int i, negative_count = 0;
  695. + struct per_lane_ctrl_status *reg_base = reg;
  696. + int timeout;
  697. +
  698. + for (i = 0; i < BIN_SNAPSHOT_NUM; i++) {
  699. + /* wait RECR1_SNP_DONE_MASK has cleared */
  700. + timeout = 100;
  701. + while ((ioread32(&reg_base->recr1) & RECR1_SNP_DONE_MASK)) {
  702. + udelay(1);
  703. + timeout--;
  704. + if (timeout == 0)
  705. + break;
  706. + }
  707. +
  708. + /* set TCSR1[CDR_SEL] to BinM1/BinLong */
  709. + if (bin_sel == BIN_M1) {
  710. + iowrite32((ioread32(&reg_base->tcsr1) &
  711. + ~CDR_SEL_MASK) | BIN_M1_SEL,
  712. + &reg_base->tcsr1);
  713. + } else {
  714. + iowrite32((ioread32(&reg_base->tcsr1) &
  715. + ~CDR_SEL_MASK) | BIN_Long_SEL,
  716. + &reg_base->tcsr1);
  717. + }
  718. +
  719. + /* start snap shot */
  720. + iowrite32(ioread32(&reg_base->gcr1) | GCR1_SNP_START_MASK,
  721. + &reg_base->gcr1);
  722. +
  723. + /* wait for SNP done */
  724. + timeout = 100;
  725. + while (!(ioread32(&reg_base->recr1) & RECR1_SNP_DONE_MASK)) {
  726. + udelay(1);
  727. + timeout--;
  728. + if (timeout == 0)
  729. + break;
  730. + }
  731. +
  732. + /* read and save the snap shot */
  733. + bin_snap_shot[i] = (ioread32(&reg_base->tcsr1) &
  734. + TCSR1_SNP_DATA_MASK) >> TCSR1_SNP_DATA_SHIFT;
  735. + if (bin_snap_shot[i] & TCSR1_EQ_SNPBIN_SIGN_MASK)
  736. + negative_count++;
  737. +
  738. + /* terminate the snap shot by setting GCR1[REQ_CTL_SNP] */
  739. + iowrite32(ioread32(&reg_base->gcr1) & ~GCR1_SNP_START_MASK,
  740. + &reg_base->gcr1);
  741. + }
  742. +
  743. + if (((bin_sel == BIN_M1) && (negative_count > BIN_M1_THRESHOLD)) ||
  744. + ((bin_sel == BIN_LONG && (negative_count > BIN_LONG_THRESHOLD)))) {
  745. + early = true;
  746. + }
  747. +
  748. + return early;
  749. +}
  750. +
  751. +static void train_tx(struct fsl_xgkr_inst *inst)
  752. +{
  753. + struct phy_device *phydev = inst->phydev;
  754. + struct tx_condition *tx_c = &inst->tx_c;
  755. + bool bin_m1_early, bin_long_early;
  756. + u32 lp_status, old_ld_update;
  757. + u32 status_cop1, status_coz, status_com1;
  758. + u32 req_cop1, req_coz, req_com1, req_preset, req_init;
  759. + u32 temp;
  760. +#ifdef NEW_ALGORITHM_TRAIN_TX
  761. + u32 median_gaink2;
  762. +#endif
  763. +
  764. +recheck:
  765. + if (tx_c->bin_long_stop && tx_c->bin_m1_stop) {
  766. + tx_c->tx_complete = true;
  767. + inst->ld_status |= RX_READY_MASK;
  768. + ld_coe_status(inst);
  769. + /* tell LP we are ready */
  770. + phy_write_mmd(phydev, MDIO_MMD_PMAPMD,
  771. + FSL_KR_PMD_STATUS, RX_STAT);
  772. + return;
  773. + }
  774. +
  775. + /* We start by checking the current LP status. If we got any responses,
  776. + * we can clear up the appropriate update request so that the
  777. + * subsequent code may easily issue new update requests if needed.
  778. + */
  779. + lp_status = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, FSL_KR_LP_STATUS) &
  780. + REQUEST_MASK;
  781. + status_cop1 = (lp_status & COP1_MASK) >> COP1_SHIFT;
  782. + status_coz = (lp_status & COZ_MASK) >> COZ_SHIFT;
  783. + status_com1 = (lp_status & COM1_MASK) >> COM1_SHIFT;
  784. +
  785. + old_ld_update = inst->ld_update;
  786. + req_cop1 = (old_ld_update & COP1_MASK) >> COP1_SHIFT;
  787. + req_coz = (old_ld_update & COZ_MASK) >> COZ_SHIFT;
  788. + req_com1 = (old_ld_update & COM1_MASK) >> COM1_SHIFT;
  789. + req_preset = old_ld_update & PRESET_MASK;
  790. + req_init = old_ld_update & INIT_MASK;
  791. +
  792. + /* IEEE802.3-2008, 72.6.10.2.3.1
  793. + * We may clear PRESET when all coefficients show UPDATED or MAX.
  794. + */
  795. + if (req_preset) {
  796. + if ((status_cop1 == COE_UPDATED || status_cop1 == COE_MAX) &&
  797. + (status_coz == COE_UPDATED || status_coz == COE_MAX) &&
  798. + (status_com1 == COE_UPDATED || status_com1 == COE_MAX)) {
  799. + inst->ld_update &= ~PRESET_MASK;
  800. + }
  801. + }
  802. +
  803. + /* IEEE802.3-2008, 72.6.10.2.3.2
  804. + * We may clear INITIALIZE when no coefficients show NOT UPDATED.
  805. + */
  806. + if (req_init) {
  807. + if (status_cop1 != COE_NOTUPDATED &&
  808. + status_coz != COE_NOTUPDATED &&
  809. + status_com1 != COE_NOTUPDATED) {
  810. + inst->ld_update &= ~INIT_MASK;
  811. + }
  812. + }
  813. +
  814. + /* IEEE802.3-2008, 72.6.10.2.3.2
  815. + * we send initialize to the other side to ensure default settings
  816. + * for the LP. Naturally, we should do this only once.
  817. + */
  818. + if (!tx_c->sent_init) {
  819. + if (!lp_status && !(old_ld_update & (LD_ALL_MASK))) {
  820. + inst->ld_update = INIT_MASK;
  821. + tx_c->sent_init = true;
  822. + }
  823. + }
  824. +
  825. + /* IEEE802.3-2008, 72.6.10.2.3.3
  826. + * We set coefficient requests to HOLD when we get the information
  827. + * about any updates On clearing our prior response, we also update
  828. + * our internal status.
  829. + */
  830. + if (status_cop1 != COE_NOTUPDATED) {
  831. + if (req_cop1) {
  832. + inst->ld_update &= ~COP1_MASK;
  833. +#ifdef NEW_ALGORITHM_TRAIN_TX
  834. + if (tx_c->post_inc) {
  835. + if (req_cop1 == INCREMENT &&
  836. + status_cop1 == COE_MAX) {
  837. + tx_c->post_inc = 0;
  838. + tx_c->bin_long_stop = true;
  839. + tx_c->bin_m1_stop = true;
  840. + } else {
  841. + tx_c->post_inc -= 1;
  842. + }
  843. +
  844. + ld_coe_update(inst);
  845. + goto recheck;
  846. + }
  847. +#endif
  848. + if ((req_cop1 == DECREMENT && status_cop1 == COE_MIN) ||
  849. + (req_cop1 == INCREMENT && status_cop1 == COE_MAX)) {
  850. + dev_dbg(&inst->phydev->mdio.dev, "COP1 hit limit %s",
  851. + (status_cop1 == COE_MIN) ?
  852. + "DEC MIN" : "INC MAX");
  853. + tx_c->long_min_max_cnt++;
  854. + if (tx_c->long_min_max_cnt >= TIMEOUT_LONG) {
  855. + tx_c->bin_long_stop = true;
  856. + ld_coe_update(inst);
  857. + goto recheck;
  858. + }
  859. + }
  860. + }
  861. + }
  862. +
  863. + if (status_coz != COE_NOTUPDATED) {
  864. + if (req_coz)
  865. + inst->ld_update &= ~COZ_MASK;
  866. + }
  867. +
  868. + if (status_com1 != COE_NOTUPDATED) {
  869. + if (req_com1) {
  870. + inst->ld_update &= ~COM1_MASK;
  871. +#ifdef NEW_ALGORITHM_TRAIN_TX
  872. + if (tx_c->pre_inc) {
  873. + if (req_com1 == INCREMENT &&
  874. + status_com1 == COE_MAX)
  875. + tx_c->pre_inc = 0;
  876. + else
  877. + tx_c->pre_inc -= 1;
  878. +
  879. + ld_coe_update(inst);
  880. + goto recheck;
  881. + }
  882. +#endif
  883. + /* Stop If we have reached the limit for a parameter. */
  884. + if ((req_com1 == DECREMENT && status_com1 == COE_MIN) ||
  885. + (req_com1 == INCREMENT && status_com1 == COE_MAX)) {
  886. + dev_dbg(&inst->phydev->mdio.dev, "COM1 hit limit %s",
  887. + (status_com1 == COE_MIN) ?
  888. + "DEC MIN" : "INC MAX");
  889. + tx_c->m1_min_max_cnt++;
  890. + if (tx_c->m1_min_max_cnt >= TIMEOUT_M1) {
  891. + tx_c->bin_m1_stop = true;
  892. + ld_coe_update(inst);
  893. + goto recheck;
  894. + }
  895. + }
  896. + }
  897. + }
  898. +
  899. + if (old_ld_update != inst->ld_update) {
  900. + ld_coe_update(inst);
  901. + /* Redo these status checks and updates until we have no more
  902. + * changes, to speed up the overall process.
  903. + */
  904. + goto recheck;
  905. + }
  906. +
  907. + /* Do nothing if we have pending request. */
  908. + if ((req_coz || req_com1 || req_cop1))
  909. + return;
  910. + else if (lp_status)
  911. + /* No pending request but LP status was not reverted to
  912. + * not updated.
  913. + */
  914. + return;
  915. +
  916. +#ifdef NEW_ALGORITHM_TRAIN_TX
  917. + if (!(inst->ld_update & (PRESET_MASK | INIT_MASK))) {
  918. + if (tx_c->pre_inc) {
  919. + inst->ld_update = INCREMENT << COM1_SHIFT;
  920. + ld_coe_update(inst);
  921. + return;
  922. + }
  923. +
  924. + if (status_cop1 != COE_MAX) {
  925. + median_gaink2 = get_median_gaink2(inst->reg_base);
  926. + if (median_gaink2 == 0xf) {
  927. + tx_c->post_inc = 1;
  928. + } else {
  929. + /* Gaink2 median lower than "F" */
  930. + tx_c->bin_m1_stop = true;
  931. + tx_c->bin_long_stop = true;
  932. + goto recheck;
  933. + }
  934. + } else {
  935. + /* C1 MAX */
  936. + tx_c->bin_m1_stop = true;
  937. + tx_c->bin_long_stop = true;
  938. + goto recheck;
  939. + }
  940. +
  941. + if (tx_c->post_inc) {
  942. + inst->ld_update = INCREMENT << COP1_SHIFT;
  943. + ld_coe_update(inst);
  944. + return;
  945. + }
  946. + }
  947. +#endif
  948. +
  949. + /* snapshot and select bin */
  950. + bin_m1_early = is_bin_early(BIN_M1, inst->reg_base);
  951. + bin_long_early = is_bin_early(BIN_LONG, inst->reg_base);
  952. +
  953. + if (!tx_c->bin_m1_stop && !tx_c->bin_m1_late_early && bin_m1_early) {
  954. + tx_c->bin_m1_stop = true;
  955. + goto recheck;
  956. + }
  957. +
  958. + if (!tx_c->bin_long_stop &&
  959. + tx_c->bin_long_late_early && !bin_long_early) {
  960. + tx_c->bin_long_stop = true;
  961. + goto recheck;
  962. + }
  963. +
  964. + /* IEEE802.3-2008, 72.6.10.2.3.3
  965. + * We only request coefficient updates when no PRESET/INITIALIZE is
  966. + * pending. We also only request coefficient updates when the
  967. + * corresponding status is NOT UPDATED and nothing is pending.
  968. + */
  969. + if (!(inst->ld_update & (PRESET_MASK | INIT_MASK))) {
  970. + if (!tx_c->bin_long_stop) {
  971. + /* BinM1 correction means changing COM1 */
  972. + if (!status_com1 && !(inst->ld_update & COM1_MASK)) {
  973. + /* Avoid BinM1Late by requesting an
  974. + * immediate decrement.
  975. + */
  976. + if (!bin_m1_early) {
  977. + /* request decrement c(-1) */
  978. + temp = DECREMENT << COM1_SHIFT;
  979. + inst->ld_update = temp;
  980. + ld_coe_update(inst);
  981. + tx_c->bin_m1_late_early = bin_m1_early;
  982. + return;
  983. + }
  984. + }
  985. +
  986. + /* BinLong correction means changing COP1 */
  987. + if (!status_cop1 && !(inst->ld_update & COP1_MASK)) {
  988. + /* Locate BinLong transition point (if any)
  989. + * while avoiding BinM1Late.
  990. + */
  991. + if (bin_long_early) {
  992. + /* request increment c(1) */
  993. + temp = INCREMENT << COP1_SHIFT;
  994. + inst->ld_update = temp;
  995. + } else {
  996. + /* request decrement c(1) */
  997. + temp = DECREMENT << COP1_SHIFT;
  998. + inst->ld_update = temp;
  999. + }
  1000. +
  1001. + ld_coe_update(inst);
  1002. + tx_c->bin_long_late_early = bin_long_early;
  1003. + }
  1004. + /* We try to finish BinLong before we do BinM1 */
  1005. + return;
  1006. + }
  1007. +
  1008. + if (!tx_c->bin_m1_stop) {
  1009. + /* BinM1 correction means changing COM1 */
  1010. + if (!status_com1 && !(inst->ld_update & COM1_MASK)) {
  1011. + /* Locate BinM1 transition point (if any) */
  1012. + if (bin_m1_early) {
  1013. + /* request increment c(-1) */
  1014. + temp = INCREMENT << COM1_SHIFT;
  1015. + inst->ld_update = temp;
  1016. + } else {
  1017. + /* request decrement c(-1) */
  1018. + temp = DECREMENT << COM1_SHIFT;
  1019. + inst->ld_update = temp;
  1020. + }
  1021. +
  1022. + ld_coe_update(inst);
  1023. + tx_c->bin_m1_late_early = bin_m1_early;
  1024. + }
  1025. + }
  1026. + }
  1027. +}
  1028. +
  1029. +static int is_link_up(struct phy_device *phydev)
  1030. +{
  1031. + int val;
  1032. +
  1033. + phy_read_mmd(phydev, MDIO_MMD_PCS, FSL_XFI_PCS_10GR_SR1);
  1034. + val = phy_read_mmd(phydev, MDIO_MMD_PCS, FSL_XFI_PCS_10GR_SR1);
  1035. +
  1036. + return (val & FSL_KR_RX_LINK_STAT_MASK) ? 1 : 0;
  1037. +}
  1038. +
  1039. +static int is_link_training_fail(struct phy_device *phydev)
  1040. +{
  1041. + int val;
  1042. + int timeout = 100;
  1043. +
  1044. + val = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, FSL_KR_PMD_STATUS);
  1045. + if (!(val & TRAIN_FAIL) && (val & RX_STAT)) {
  1046. + /* check LNK_STAT for sure */
  1047. + while (timeout--) {
  1048. + if (is_link_up(phydev))
  1049. + return 0;
  1050. +
  1051. + usleep_range(100, 500);
  1052. + }
  1053. + }
  1054. +
  1055. + return 1;
  1056. +}
  1057. +
  1058. +static int check_rx(struct phy_device *phydev)
  1059. +{
  1060. + return phy_read_mmd(phydev, MDIO_MMD_PMAPMD, FSL_KR_LP_STATUS) &
  1061. + RX_READY_MASK;
  1062. +}
  1063. +
  1064. +/* Coefficient values have hardware restrictions */
  1065. +static int is_ld_valid(struct fsl_xgkr_inst *inst)
  1066. +{
  1067. + u32 ratio_pst1q = inst->ratio_pst1q;
  1068. + u32 adpt_eq = inst->adpt_eq;
  1069. + u32 ratio_preq = inst->ratio_preq;
  1070. +
  1071. + if ((ratio_pst1q + adpt_eq + ratio_preq) > 48)
  1072. + return 0;
  1073. +
  1074. + if (((ratio_pst1q + adpt_eq + ratio_preq) * 4) >=
  1075. + ((adpt_eq - ratio_pst1q - ratio_preq) * 17))
  1076. + return 0;
  1077. +
  1078. + if (ratio_preq > ratio_pst1q)
  1079. + return 0;
  1080. +
  1081. + if (ratio_preq > 8)
  1082. + return 0;
  1083. +
  1084. + if (adpt_eq < 26)
  1085. + return 0;
  1086. +
  1087. + if (ratio_pst1q > 16)
  1088. + return 0;
  1089. +
  1090. + return 1;
  1091. +}
  1092. +
  1093. +static int is_value_allowed(const u32 *val_table, u32 val)
  1094. +{
  1095. + int i;
  1096. +
  1097. + for (i = 0;; i++) {
  1098. + if (*(val_table + i) == VAL_INVALID)
  1099. + return 0;
  1100. + if (*(val_table + i) == val)
  1101. + return 1;
  1102. + }
  1103. +}
  1104. +
  1105. +static int inc_dec(struct fsl_xgkr_inst *inst, int field, int request)
  1106. +{
  1107. + u32 ld_limit[3], ld_coe[3], step[3];
  1108. +
  1109. + ld_coe[0] = inst->ratio_pst1q;
  1110. + ld_coe[1] = inst->adpt_eq;
  1111. + ld_coe[2] = inst->ratio_preq;
  1112. +
  1113. + /* Information specific to the Freescale SerDes for 10GBase-KR:
  1114. + * Incrementing C(+1) means *decrementing* RATIO_PST1Q
  1115. + * Incrementing C(0) means incrementing ADPT_EQ
  1116. + * Incrementing C(-1) means *decrementing* RATIO_PREQ
  1117. + */
  1118. + step[0] = -1;
  1119. + step[1] = 1;
  1120. + step[2] = -1;
  1121. +
  1122. + switch (request) {
  1123. + case INCREMENT:
  1124. + ld_limit[0] = POST_COE_MAX;
  1125. + ld_limit[1] = ZERO_COE_MAX;
  1126. + ld_limit[2] = PRE_COE_MAX;
  1127. + if (ld_coe[field] != ld_limit[field])
  1128. + ld_coe[field] += step[field];
  1129. + else
  1130. + /* MAX */
  1131. + return 2;
  1132. + break;
  1133. + case DECREMENT:
  1134. + ld_limit[0] = POST_COE_MIN;
  1135. + ld_limit[1] = ZERO_COE_MIN;
  1136. + ld_limit[2] = PRE_COE_MIN;
  1137. + if (ld_coe[field] != ld_limit[field])
  1138. + ld_coe[field] -= step[field];
  1139. + else
  1140. + /* MIN */
  1141. + return 1;
  1142. + break;
  1143. + default:
  1144. + break;
  1145. + }
  1146. +
  1147. + if (is_ld_valid(inst)) {
  1148. + /* accept new ld */
  1149. + inst->ratio_pst1q = ld_coe[0];
  1150. + inst->adpt_eq = ld_coe[1];
  1151. + inst->ratio_preq = ld_coe[2];
  1152. + /* only some values for preq and pst1q can be used.
  1153. + * for preq: 0x0, 0x1, 0x3, 0x5, 0x7, 0x9, 0xb, 0xc.
  1154. + * for pst1q: 0x0, 0x1, 0x3, 0x5, 0x7, 0x9, 0xb, 0xd, 0xf, 0x10.
  1155. + */
  1156. + if (!is_value_allowed((const u32 *)&preq_table, ld_coe[2])) {
  1157. + dev_dbg(&inst->phydev->mdio.dev,
  1158. + "preq skipped value: %d\n", ld_coe[2]);
  1159. + return 0;
  1160. + }
  1161. +
  1162. + if (!is_value_allowed((const u32 *)&pst1q_table, ld_coe[0])) {
  1163. + dev_dbg(&inst->phydev->mdio.dev,
  1164. + "pst1q skipped value: %d\n", ld_coe[0]);
  1165. + return 0;
  1166. + }
  1167. +
  1168. + tune_tecr0(inst);
  1169. + } else {
  1170. + if (request == DECREMENT)
  1171. + /* MIN */
  1172. + return 1;
  1173. + if (request == INCREMENT)
  1174. + /* MAX */
  1175. + return 2;
  1176. + }
  1177. +
  1178. + return 0;
  1179. +}
  1180. +
  1181. +static void min_max_updated(struct fsl_xgkr_inst *inst, int field, int new_ld)
  1182. +{
  1183. + u32 ld_coe[] = {COE_UPDATED, COE_MIN, COE_MAX};
  1184. + u32 mask, val;
  1185. +
  1186. + switch (field) {
  1187. + case COE_COP1:
  1188. + mask = COP1_MASK;
  1189. + val = ld_coe[new_ld] << COP1_SHIFT;
  1190. + break;
  1191. + case COE_COZ:
  1192. + mask = COZ_MASK;
  1193. + val = ld_coe[new_ld] << COZ_SHIFT;
  1194. + break;
  1195. + case COE_COM:
  1196. + mask = COM1_MASK;
  1197. + val = ld_coe[new_ld] << COM1_SHIFT;
  1198. + break;
  1199. + default:
  1200. + return;
  1201. + }
  1202. +
  1203. + inst->ld_status &= ~mask;
  1204. + inst->ld_status |= val;
  1205. +}
  1206. +
  1207. +static void check_request(struct fsl_xgkr_inst *inst, int request)
  1208. +{
  1209. + int cop1_req, coz_req, com_req;
  1210. + int old_status, new_ld_sta;
  1211. +
  1212. + cop1_req = (request & COP1_MASK) >> COP1_SHIFT;
  1213. + coz_req = (request & COZ_MASK) >> COZ_SHIFT;
  1214. + com_req = (request & COM1_MASK) >> COM1_SHIFT;
  1215. +
  1216. + /* IEEE802.3-2008, 72.6.10.2.5
  1217. + * Ensure we only act on INCREMENT/DECREMENT when we are in NOT UPDATED
  1218. + */
  1219. + old_status = inst->ld_status;
  1220. +
  1221. + if (cop1_req && !(inst->ld_status & COP1_MASK)) {
  1222. + new_ld_sta = inc_dec(inst, COE_COP1, cop1_req);
  1223. + min_max_updated(inst, COE_COP1, new_ld_sta);
  1224. + }
  1225. +
  1226. + if (coz_req && !(inst->ld_status & COZ_MASK)) {
  1227. + new_ld_sta = inc_dec(inst, COE_COZ, coz_req);
  1228. + min_max_updated(inst, COE_COZ, new_ld_sta);
  1229. + }
  1230. +
  1231. + if (com_req && !(inst->ld_status & COM1_MASK)) {
  1232. + new_ld_sta = inc_dec(inst, COE_COM, com_req);
  1233. + min_max_updated(inst, COE_COM, new_ld_sta);
  1234. + }
  1235. +
  1236. + if (old_status != inst->ld_status)
  1237. + ld_coe_status(inst);
  1238. +}
  1239. +
  1240. +static void preset(struct fsl_xgkr_inst *inst)
  1241. +{
  1242. + /* These are all MAX values from the IEEE802.3 perspective. */
  1243. + inst->ratio_pst1q = POST_COE_MAX;
  1244. + inst->adpt_eq = ZERO_COE_MAX;
  1245. + inst->ratio_preq = PRE_COE_MAX;
  1246. +
  1247. + tune_tecr0(inst);
  1248. + inst->ld_status &= ~(COP1_MASK | COZ_MASK | COM1_MASK);
  1249. + inst->ld_status |= COE_MAX << COP1_SHIFT |
  1250. + COE_MAX << COZ_SHIFT |
  1251. + COE_MAX << COM1_SHIFT;
  1252. + ld_coe_status(inst);
  1253. +}
  1254. +
  1255. +static void initialize(struct fsl_xgkr_inst *inst)
  1256. +{
  1257. + inst->ratio_preq = RATIO_PREQ;
  1258. + inst->ratio_pst1q = RATIO_PST1Q;
  1259. + inst->adpt_eq = RATIO_EQ;
  1260. +
  1261. + tune_tecr0(inst);
  1262. + inst->ld_status &= ~(COP1_MASK | COZ_MASK | COM1_MASK);
  1263. + inst->ld_status |= COE_UPDATED << COP1_SHIFT |
  1264. + COE_UPDATED << COZ_SHIFT |
  1265. + COE_UPDATED << COM1_SHIFT;
  1266. + ld_coe_status(inst);
  1267. +}
  1268. +
  1269. +static void train_rx(struct fsl_xgkr_inst *inst)
  1270. +{
  1271. + struct phy_device *phydev = inst->phydev;
  1272. + int request, old_ld_status;
  1273. +
  1274. + /* get request from LP */
  1275. + request = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, FSL_KR_LP_CU) &
  1276. + (LD_ALL_MASK);
  1277. + old_ld_status = inst->ld_status;
  1278. +
  1279. + /* IEEE802.3-2008, 72.6.10.2.5
  1280. + * Ensure we always go to NOT UDPATED for status reporting in
  1281. + * response to HOLD requests.
  1282. + * IEEE802.3-2008, 72.6.10.2.3.1/2
  1283. + * ... but only if PRESET/INITIALIZE are not active to ensure
  1284. + * we keep status until they are released.
  1285. + */
  1286. + if (!(request & (PRESET_MASK | INIT_MASK))) {
  1287. + if (!(request & COP1_MASK))
  1288. + inst->ld_status &= ~COP1_MASK;
  1289. +
  1290. + if (!(request & COZ_MASK))
  1291. + inst->ld_status &= ~COZ_MASK;
  1292. +
  1293. + if (!(request & COM1_MASK))
  1294. + inst->ld_status &= ~COM1_MASK;
  1295. +
  1296. + if (old_ld_status != inst->ld_status)
  1297. + ld_coe_status(inst);
  1298. + }
  1299. +
  1300. + /* As soon as the LP shows ready, no need to do any more updates. */
  1301. + if (check_rx(phydev)) {
  1302. + /* LP receiver is ready */
  1303. + if (inst->ld_status & (COP1_MASK | COZ_MASK | COM1_MASK)) {
  1304. + inst->ld_status &= ~(COP1_MASK | COZ_MASK | COM1_MASK);
  1305. + ld_coe_status(inst);
  1306. + }
  1307. + } else {
  1308. + /* IEEE802.3-2008, 72.6.10.2.3.1/2
  1309. + * only act on PRESET/INITIALIZE if all status is NOT UPDATED.
  1310. + */
  1311. + if (request & (PRESET_MASK | INIT_MASK)) {
  1312. + if (!(inst->ld_status &
  1313. + (COP1_MASK | COZ_MASK | COM1_MASK))) {
  1314. + if (request & PRESET_MASK)
  1315. + preset(inst);
  1316. +
  1317. + if (request & INIT_MASK)
  1318. + initialize(inst);
  1319. + }
  1320. + }
  1321. +
  1322. + /* LP Coefficient are not in HOLD */
  1323. + if (request & REQUEST_MASK)
  1324. + check_request(inst, request & REQUEST_MASK);
  1325. + }
  1326. +}
  1327. +
  1328. +static void xgkr_start_train(struct phy_device *phydev)
  1329. +{
  1330. + struct fsl_xgkr_inst *inst = phydev->priv;
  1331. + struct tx_condition *tx_c = &inst->tx_c;
  1332. + int val = 0, i;
  1333. + int lt_state;
  1334. + unsigned long dead_line;
  1335. + int rx_ok, tx_ok;
  1336. +
  1337. + init_inst(inst, 0);
  1338. + start_lt(phydev);
  1339. +
  1340. + for (i = 0; i < 2;) {
  1341. + dead_line = jiffies + msecs_to_jiffies(500);
  1342. + while (time_before(jiffies, dead_line)) {
  1343. + val = phy_read_mmd(phydev, MDIO_MMD_PMAPMD,
  1344. + FSL_KR_PMD_STATUS);
  1345. + if (val & TRAIN_FAIL) {
  1346. + /* LT failed already, reset lane to avoid
  1347. + * it run into hanging, then start LT again.
  1348. + */
  1349. + reset_gcr0(inst);
  1350. + start_lt(phydev);
  1351. + } else if ((val & PMD_STATUS_SUP_STAT) &&
  1352. + (val & PMD_STATUS_FRAME_LOCK))
  1353. + break;
  1354. + usleep_range(100, 500);
  1355. + }
  1356. +
  1357. + if (!((val & PMD_STATUS_FRAME_LOCK) &&
  1358. + (val & PMD_STATUS_SUP_STAT))) {
  1359. + i++;
  1360. + continue;
  1361. + }
  1362. +
  1363. + /* init process */
  1364. + rx_ok = false;
  1365. + tx_ok = false;
  1366. + /* the LT should be finished in 500ms, failed or OK. */
  1367. + dead_line = jiffies + msecs_to_jiffies(500);
  1368. +
  1369. + while (time_before(jiffies, dead_line)) {
  1370. + /* check if the LT is already failed */
  1371. + lt_state = phy_read_mmd(phydev, MDIO_MMD_PMAPMD,
  1372. + FSL_KR_PMD_STATUS);
  1373. + if (lt_state & TRAIN_FAIL) {
  1374. + reset_gcr0(inst);
  1375. + break;
  1376. + }
  1377. +
  1378. + rx_ok = check_rx(phydev);
  1379. + tx_ok = tx_c->tx_complete;
  1380. +
  1381. + if (rx_ok && tx_ok)
  1382. + break;
  1383. +
  1384. + if (!rx_ok)
  1385. + train_rx(inst);
  1386. +
  1387. + if (!tx_ok)
  1388. + train_tx(inst);
  1389. +
  1390. + usleep_range(100, 500);
  1391. + }
  1392. +
  1393. + i++;
  1394. + /* check LT result */
  1395. + if (is_link_training_fail(phydev)) {
  1396. + init_inst(inst, 0);
  1397. + continue;
  1398. + } else {
  1399. + stop_lt(phydev);
  1400. + inst->state = TRAINED;
  1401. + break;
  1402. + }
  1403. + }
  1404. +}
  1405. +
  1406. +static void xgkr_state_machine(struct work_struct *work)
  1407. +{
  1408. + struct delayed_work *dwork = to_delayed_work(work);
  1409. + struct fsl_xgkr_inst *inst = container_of(dwork,
  1410. + struct fsl_xgkr_inst,
  1411. + xgkr_wk);
  1412. + struct phy_device *phydev = inst->phydev;
  1413. + int an_state;
  1414. + bool needs_train = false;
  1415. +
  1416. + mutex_lock(&phydev->lock);
  1417. +
  1418. + switch (inst->state) {
  1419. + case DETECTING_LP:
  1420. + phy_read_mmd(phydev, MDIO_MMD_AN, FSL_AN_BP_STAT);
  1421. + an_state = phy_read_mmd(phydev, MDIO_MMD_AN, FSL_AN_BP_STAT);
  1422. + if ((an_state & KR_AN_MASK))
  1423. + needs_train = true;
  1424. + break;
  1425. + case TRAINED:
  1426. + if (!is_link_up(phydev)) {
  1427. + dev_info(&phydev->mdio.dev,
  1428. + "Detect hotplug, restart training\n");
  1429. + init_inst(inst, 1);
  1430. + start_xgkr_an(phydev);
  1431. + inst->state = DETECTING_LP;
  1432. + }
  1433. + break;
  1434. + }
  1435. +
  1436. + if (needs_train)
  1437. + xgkr_start_train(phydev);
  1438. +
  1439. + mutex_unlock(&phydev->lock);
  1440. + queue_delayed_work(system_power_efficient_wq, &inst->xgkr_wk,
  1441. + msecs_to_jiffies(XGKR_TIMEOUT));
  1442. +}
  1443. +
  1444. +static int fsl_backplane_probe(struct phy_device *phydev)
  1445. +{
  1446. + struct fsl_xgkr_inst *xgkr_inst;
  1447. + struct device_node *phy_node, *lane_node;
  1448. + struct resource res_lane;
  1449. + const char *bm;
  1450. + int ret;
  1451. + int bp_mode;
  1452. + u32 lane[2];
  1453. +
  1454. + phy_node = phydev->mdio.dev.of_node;
  1455. + bp_mode = of_property_read_string(phy_node, "backplane-mode", &bm);
  1456. + if (bp_mode < 0)
  1457. + return 0;
  1458. +
  1459. + if (!strcasecmp(bm, "1000base-kx")) {
  1460. + bp_mode = PHY_BACKPLANE_1000BASE_KX;
  1461. + } else if (!strcasecmp(bm, "10gbase-kr")) {
  1462. + bp_mode = PHY_BACKPLANE_10GBASE_KR;
  1463. + } else {
  1464. + dev_err(&phydev->mdio.dev, "Unknown backplane-mode\n");
  1465. + return -EINVAL;
  1466. + }
  1467. +
  1468. + lane_node = of_parse_phandle(phy_node, "fsl,lane-handle", 0);
  1469. + if (!lane_node) {
  1470. + dev_err(&phydev->mdio.dev, "parse fsl,lane-handle failed\n");
  1471. + return -EINVAL;
  1472. + }
  1473. +
  1474. + ret = of_address_to_resource(lane_node, 0, &res_lane);
  1475. + if (ret) {
  1476. + dev_err(&phydev->mdio.dev, "could not obtain memory map\n");
  1477. + return ret;
  1478. + }
  1479. +
  1480. + of_node_put(lane_node);
  1481. + ret = of_property_read_u32_array(phy_node, "fsl,lane-reg",
  1482. + (u32 *)&lane, 2);
  1483. + if (ret) {
  1484. + dev_err(&phydev->mdio.dev, "could not get fsl,lane-reg\n");
  1485. + return -EINVAL;
  1486. + }
  1487. +
  1488. + phydev->priv = devm_ioremap_nocache(&phydev->mdio.dev,
  1489. + res_lane.start + lane[0],
  1490. + lane[1]);
  1491. + if (!phydev->priv) {
  1492. + dev_err(&phydev->mdio.dev, "ioremap_nocache failed\n");
  1493. + return -ENOMEM;
  1494. + }
  1495. +
  1496. + if (bp_mode == PHY_BACKPLANE_1000BASE_KX) {
  1497. + phydev->speed = SPEED_1000;
  1498. + /* configure the lane for 1000BASE-KX */
  1499. + lane_set_1gkx(phydev->priv);
  1500. + return 0;
  1501. + }
  1502. +
  1503. + xgkr_inst = devm_kzalloc(&phydev->mdio.dev,
  1504. + sizeof(*xgkr_inst), GFP_KERNEL);
  1505. + if (!xgkr_inst)
  1506. + return -ENOMEM;
  1507. +
  1508. + xgkr_inst->reg_base = phydev->priv;
  1509. + xgkr_inst->phydev = phydev;
  1510. + phydev->priv = xgkr_inst;
  1511. +
  1512. + if (bp_mode == PHY_BACKPLANE_10GBASE_KR) {
  1513. + phydev->speed = SPEED_10000;
  1514. + INIT_DELAYED_WORK(&xgkr_inst->xgkr_wk, xgkr_state_machine);
  1515. + }
  1516. +
  1517. + return 0;
  1518. +}
  1519. +
  1520. +static int fsl_backplane_aneg_done(struct phy_device *phydev)
  1521. +{
  1522. + return 1;
  1523. +}
  1524. +
  1525. +static int fsl_backplane_config_aneg(struct phy_device *phydev)
  1526. +{
  1527. + if (phydev->speed == SPEED_10000) {
  1528. + phydev->supported |= SUPPORTED_10000baseKR_Full;
  1529. + start_xgkr_an(phydev);
  1530. + } else if (phydev->speed == SPEED_1000) {
  1531. + phydev->supported |= SUPPORTED_1000baseKX_Full;
  1532. + start_1gkx_an(phydev);
  1533. + }
  1534. +
  1535. + phydev->advertising = phydev->supported;
  1536. + phydev->duplex = 1;
  1537. +
  1538. + return 0;
  1539. +}
  1540. +
  1541. +static int fsl_backplane_suspend(struct phy_device *phydev)
  1542. +{
  1543. + if (phydev->speed == SPEED_10000) {
  1544. + struct fsl_xgkr_inst *xgkr_inst = phydev->priv;
  1545. +
  1546. + cancel_delayed_work_sync(&xgkr_inst->xgkr_wk);
  1547. + }
  1548. + return 0;
  1549. +}
  1550. +
  1551. +static int fsl_backplane_resume(struct phy_device *phydev)
  1552. +{
  1553. + if (phydev->speed == SPEED_10000) {
  1554. + struct fsl_xgkr_inst *xgkr_inst = phydev->priv;
  1555. +
  1556. + init_inst(xgkr_inst, 1);
  1557. + queue_delayed_work(system_power_efficient_wq,
  1558. + &xgkr_inst->xgkr_wk,
  1559. + msecs_to_jiffies(XGKR_TIMEOUT));
  1560. + }
  1561. + return 0;
  1562. +}
  1563. +
  1564. +static int fsl_backplane_read_status(struct phy_device *phydev)
  1565. +{
  1566. + if (is_link_up(phydev))
  1567. + phydev->link = 1;
  1568. + else
  1569. + phydev->link = 0;
  1570. +
  1571. + return 0;
  1572. +}
  1573. +
  1574. +static struct phy_driver fsl_backplane_driver[] = {
  1575. + {
  1576. + .phy_id = FSL_PCS_PHY_ID,
  1577. + .name = "Freescale Backplane",
  1578. + .phy_id_mask = 0xffffffff,
  1579. + .features = SUPPORTED_Backplane | SUPPORTED_Autoneg |
  1580. + SUPPORTED_MII,
  1581. + .probe = fsl_backplane_probe,
  1582. + .aneg_done = fsl_backplane_aneg_done,
  1583. + .config_aneg = fsl_backplane_config_aneg,
  1584. + .read_status = fsl_backplane_read_status,
  1585. + .suspend = fsl_backplane_suspend,
  1586. + .resume = fsl_backplane_resume,
  1587. + },
  1588. +};
  1589. +
  1590. +module_phy_driver(fsl_backplane_driver);
  1591. +
  1592. +static struct mdio_device_id __maybe_unused freescale_tbl[] = {
  1593. + { FSL_PCS_PHY_ID, 0xffffffff },
  1594. + { }
  1595. +};
  1596. +
  1597. +MODULE_DEVICE_TABLE(mdio, freescale_tbl);
  1598. +
  1599. +MODULE_DESCRIPTION("Freescale Backplane driver");
  1600. +MODULE_AUTHOR("Shaohui Xie <[email protected]>");
  1601. +MODULE_LICENSE("GPL v2");
  1602. --- a/drivers/net/phy/phy.c
  1603. +++ b/drivers/net/phy/phy.c
  1604. @@ -591,7 +591,7 @@ int phy_mii_ioctl(struct phy_device *phy
  1605. return 0;
  1606. case SIOCSHWTSTAMP:
  1607. - if (phydev->drv->hwtstamp)
  1608. + if (phydev->drv && phydev->drv->hwtstamp)
  1609. return phydev->drv->hwtstamp(phydev, ifr);
  1610. /* fall through */
  1611. @@ -616,6 +616,9 @@ static int phy_start_aneg_priv(struct ph
  1612. bool trigger = 0;
  1613. int err;
  1614. + if (!phydev->drv)
  1615. + return -EIO;
  1616. +
  1617. mutex_lock(&phydev->lock);
  1618. if (AUTONEG_DISABLE == phydev->autoneg)
  1619. @@ -1015,7 +1018,7 @@ void phy_state_machine(struct work_struc
  1620. old_state = phydev->state;
  1621. - if (phydev->drv->link_change_notify)
  1622. + if (phydev->drv && phydev->drv->link_change_notify)
  1623. phydev->drv->link_change_notify(phydev);
  1624. switch (phydev->state) {
  1625. @@ -1317,6 +1320,9 @@ EXPORT_SYMBOL(phy_write_mmd_indirect);
  1626. */
  1627. int phy_init_eee(struct phy_device *phydev, bool clk_stop_enable)
  1628. {
  1629. + if (!phydev->drv)
  1630. + return -EIO;
  1631. +
  1632. /* According to 802.3az,the EEE is supported only in full duplex-mode.
  1633. * Also EEE feature is active when core is operating with MII, GMII
  1634. * or RGMII (all kinds). Internal PHYs are also allowed to proceed and
  1635. @@ -1394,6 +1400,9 @@ EXPORT_SYMBOL(phy_init_eee);
  1636. */
  1637. int phy_get_eee_err(struct phy_device *phydev)
  1638. {
  1639. + if (!phydev->drv)
  1640. + return -EIO;
  1641. +
  1642. return phy_read_mmd_indirect(phydev, MDIO_PCS_EEE_WK_ERR, MDIO_MMD_PCS);
  1643. }
  1644. EXPORT_SYMBOL(phy_get_eee_err);
  1645. @@ -1410,6 +1419,9 @@ int phy_ethtool_get_eee(struct phy_devic
  1646. {
  1647. int val;
  1648. + if (!phydev->drv)
  1649. + return -EIO;
  1650. +
  1651. /* Get Supported EEE */
  1652. val = phy_read_mmd_indirect(phydev, MDIO_PCS_EEE_ABLE, MDIO_MMD_PCS);
  1653. if (val < 0)
  1654. @@ -1443,6 +1455,9 @@ int phy_ethtool_set_eee(struct phy_devic
  1655. {
  1656. int val = ethtool_adv_to_mmd_eee_adv_t(data->advertised);
  1657. + if (!phydev->drv)
  1658. + return -EIO;
  1659. +
  1660. /* Mask prohibited EEE modes */
  1661. val &= ~phydev->eee_broken_modes;
  1662. @@ -1454,7 +1469,7 @@ EXPORT_SYMBOL(phy_ethtool_set_eee);
  1663. int phy_ethtool_set_wol(struct phy_device *phydev, struct ethtool_wolinfo *wol)
  1664. {
  1665. - if (phydev->drv->set_wol)
  1666. + if (phydev->drv && phydev->drv->set_wol)
  1667. return phydev->drv->set_wol(phydev, wol);
  1668. return -EOPNOTSUPP;
  1669. @@ -1463,7 +1478,7 @@ EXPORT_SYMBOL(phy_ethtool_set_wol);
  1670. void phy_ethtool_get_wol(struct phy_device *phydev, struct ethtool_wolinfo *wol)
  1671. {
  1672. - if (phydev->drv->get_wol)
  1673. + if (phydev->drv && phydev->drv->get_wol)
  1674. phydev->drv->get_wol(phydev, wol);
  1675. }
  1676. EXPORT_SYMBOL(phy_ethtool_get_wol);
  1677. --- a/drivers/net/phy/phy_device.c
  1678. +++ b/drivers/net/phy/phy_device.c
  1679. @@ -1046,7 +1046,7 @@ int phy_suspend(struct phy_device *phyde
  1680. if (wol.wolopts)
  1681. return -EBUSY;
  1682. - if (phydrv->suspend)
  1683. + if (phydev->drv && phydrv->suspend)
  1684. ret = phydrv->suspend(phydev);
  1685. if (ret)
  1686. @@ -1063,7 +1063,7 @@ int phy_resume(struct phy_device *phydev
  1687. struct phy_driver *phydrv = to_phy_driver(phydev->mdio.dev.driver);
  1688. int ret = 0;
  1689. - if (phydrv->resume)
  1690. + if (phydev->drv && phydrv->resume)
  1691. ret = phydrv->resume(phydev);
  1692. if (ret)
  1693. @@ -1720,7 +1720,7 @@ static int phy_remove(struct device *dev
  1694. phydev->state = PHY_DOWN;
  1695. mutex_unlock(&phydev->lock);
  1696. - if (phydev->drv->remove)
  1697. + if (phydev->drv && phydev->drv->remove)
  1698. phydev->drv->remove(phydev);
  1699. phydev->drv = NULL;
  1700. --- a/drivers/net/phy/swphy.c
  1701. +++ b/drivers/net/phy/swphy.c
  1702. @@ -77,6 +77,7 @@ static const struct swmii_regs duplex[]
  1703. static int swphy_decode_speed(int speed)
  1704. {
  1705. switch (speed) {
  1706. + case 10000:
  1707. case 1000:
  1708. return SWMII_SPEED_1000;
  1709. case 100:
  1710. --- a/include/linux/phy.h
  1711. +++ b/include/linux/phy.h
  1712. @@ -81,6 +81,7 @@ typedef enum {
  1713. PHY_INTERFACE_MODE_MOCA,
  1714. PHY_INTERFACE_MODE_QSGMII,
  1715. PHY_INTERFACE_MODE_TRGMII,
  1716. + PHY_INTERFACE_MODE_2500SGMII,
  1717. PHY_INTERFACE_MODE_MAX,
  1718. } phy_interface_t;
  1719. @@ -126,6 +127,8 @@ static inline const char *phy_modes(phy_
  1720. return "qsgmii";
  1721. case PHY_INTERFACE_MODE_TRGMII:
  1722. return "trgmii";
  1723. + case PHY_INTERFACE_MODE_2500SGMII:
  1724. + return "sgmii-2500";
  1725. default:
  1726. return "unknown";
  1727. }
  1728. @@ -791,6 +794,9 @@ int phy_stop_interrupts(struct phy_devic
  1729. static inline int phy_read_status(struct phy_device *phydev)
  1730. {
  1731. + if (!phydev->drv)
  1732. + return -EIO;
  1733. +
  1734. return phydev->drv->read_status(phydev);
  1735. }