phy-gmii-sel.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Texas Instruments CPSW Port's PHY Interface Mode selection Driver
  4. *
  5. * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/
  6. *
  7. * Based on cpsw-phy-sel.c driver created by Mugunthan V N <mugunthanvnm@ti.com>
  8. */
  9. #include <linux/platform_device.h>
  10. #include <linux/module.h>
  11. #include <linux/mfd/syscon.h>
  12. #include <linux/of.h>
  13. #include <linux/of_address.h>
  14. #include <linux/of_net.h>
  15. #include <linux/phy.h>
  16. #include <linux/phy/phy.h>
  17. #include <linux/regmap.h>
  18. /* AM33xx SoC specific definitions for the CONTROL port */
  19. #define AM33XX_GMII_SEL_MODE_MII 0
  20. #define AM33XX_GMII_SEL_MODE_RMII 1
  21. #define AM33XX_GMII_SEL_MODE_RGMII 2
  22. /* J72xx SoC specific definitions for the CONTROL port */
  23. #define J72XX_GMII_SEL_MODE_SGMII 3
  24. #define J72XX_GMII_SEL_MODE_QSGMII 4
  25. #define J72XX_GMII_SEL_MODE_USXGMII 5
  26. #define J72XX_GMII_SEL_MODE_QSGMII_SUB 6
  27. #define PHY_GMII_PORT(n) BIT((n) - 1)
  28. enum {
  29. PHY_GMII_SEL_PORT_MODE = 0,
  30. PHY_GMII_SEL_RGMII_ID_MODE,
  31. PHY_GMII_SEL_RMII_IO_CLK_EN,
  32. PHY_GMII_SEL_FIXED_TX_DELAY,
  33. PHY_GMII_SEL_LAST,
  34. };
  35. struct phy_gmii_sel_phy_priv {
  36. struct phy_gmii_sel_priv *priv;
  37. u32 id;
  38. struct phy *if_phy;
  39. int rmii_clock_external;
  40. int phy_if_mode;
  41. struct regmap_field *fields[PHY_GMII_SEL_LAST];
  42. };
  43. struct phy_gmii_sel_soc_data {
  44. u32 num_ports;
  45. u32 features;
  46. const struct reg_field (*regfields)[PHY_GMII_SEL_LAST];
  47. bool use_of_data;
  48. u64 extra_modes;
  49. u32 num_qsgmii_main_ports;
  50. };
  51. struct phy_gmii_sel_priv {
  52. struct device *dev;
  53. const struct phy_gmii_sel_soc_data *soc_data;
  54. struct regmap *regmap;
  55. struct phy_provider *phy_provider;
  56. struct phy_gmii_sel_phy_priv *if_phys;
  57. u32 num_ports;
  58. u32 reg_offset;
  59. u32 qsgmii_main_ports;
  60. bool no_offset;
  61. };
  62. static int phy_gmii_sel_mode(struct phy *phy, enum phy_mode mode, int submode)
  63. {
  64. struct phy_gmii_sel_phy_priv *if_phy = phy_get_drvdata(phy);
  65. const struct phy_gmii_sel_soc_data *soc_data = if_phy->priv->soc_data;
  66. struct device *dev = if_phy->priv->dev;
  67. struct regmap_field *regfield;
  68. int ret, rgmii_id = 0;
  69. u32 gmii_sel_mode = 0;
  70. if (mode != PHY_MODE_ETHERNET)
  71. return -EINVAL;
  72. switch (submode) {
  73. case PHY_INTERFACE_MODE_RMII:
  74. gmii_sel_mode = AM33XX_GMII_SEL_MODE_RMII;
  75. break;
  76. case PHY_INTERFACE_MODE_RGMII:
  77. case PHY_INTERFACE_MODE_RGMII_RXID:
  78. gmii_sel_mode = AM33XX_GMII_SEL_MODE_RGMII;
  79. break;
  80. case PHY_INTERFACE_MODE_RGMII_ID:
  81. case PHY_INTERFACE_MODE_RGMII_TXID:
  82. gmii_sel_mode = AM33XX_GMII_SEL_MODE_RGMII;
  83. rgmii_id = 1;
  84. break;
  85. case PHY_INTERFACE_MODE_MII:
  86. case PHY_INTERFACE_MODE_GMII:
  87. gmii_sel_mode = AM33XX_GMII_SEL_MODE_MII;
  88. break;
  89. case PHY_INTERFACE_MODE_QSGMII:
  90. if (!(soc_data->extra_modes & BIT(PHY_INTERFACE_MODE_QSGMII)))
  91. goto unsupported;
  92. if (if_phy->priv->qsgmii_main_ports & BIT(if_phy->id - 1))
  93. gmii_sel_mode = J72XX_GMII_SEL_MODE_QSGMII;
  94. else
  95. gmii_sel_mode = J72XX_GMII_SEL_MODE_QSGMII_SUB;
  96. break;
  97. case PHY_INTERFACE_MODE_SGMII:
  98. if (!(soc_data->extra_modes & BIT(PHY_INTERFACE_MODE_SGMII)))
  99. goto unsupported;
  100. else
  101. gmii_sel_mode = J72XX_GMII_SEL_MODE_SGMII;
  102. break;
  103. case PHY_INTERFACE_MODE_USXGMII:
  104. if (!(soc_data->extra_modes & BIT(PHY_INTERFACE_MODE_USXGMII)))
  105. goto unsupported;
  106. else
  107. gmii_sel_mode = J72XX_GMII_SEL_MODE_USXGMII;
  108. break;
  109. default:
  110. goto unsupported;
  111. }
  112. /* With a fixed delay, some modes are not supported at all. */
  113. if (soc_data->features & BIT(PHY_GMII_SEL_FIXED_TX_DELAY) &&
  114. rgmii_id != 0)
  115. return -EINVAL;
  116. if_phy->phy_if_mode = submode;
  117. dev_dbg(dev, "%s id:%u mode:%u rgmii_id:%d rmii_clk_ext:%d\n",
  118. __func__, if_phy->id, submode, rgmii_id,
  119. if_phy->rmii_clock_external);
  120. regfield = if_phy->fields[PHY_GMII_SEL_PORT_MODE];
  121. ret = regmap_field_write(regfield, gmii_sel_mode);
  122. if (ret) {
  123. dev_err(dev, "port%u: set mode fail %d", if_phy->id, ret);
  124. return ret;
  125. }
  126. if (soc_data->features & BIT(PHY_GMII_SEL_RGMII_ID_MODE) &&
  127. if_phy->fields[PHY_GMII_SEL_RGMII_ID_MODE]) {
  128. regfield = if_phy->fields[PHY_GMII_SEL_RGMII_ID_MODE];
  129. ret = regmap_field_write(regfield, rgmii_id);
  130. if (ret)
  131. return ret;
  132. }
  133. if (soc_data->features & BIT(PHY_GMII_SEL_RMII_IO_CLK_EN) &&
  134. if_phy->fields[PHY_GMII_SEL_RMII_IO_CLK_EN]) {
  135. regfield = if_phy->fields[PHY_GMII_SEL_RMII_IO_CLK_EN];
  136. ret = regmap_field_write(regfield,
  137. if_phy->rmii_clock_external);
  138. }
  139. return 0;
  140. unsupported:
  141. dev_warn(dev, "port%u: unsupported mode: \"%s\"\n",
  142. if_phy->id, phy_modes(submode));
  143. return -EINVAL;
  144. }
  145. static const
  146. struct reg_field phy_gmii_sel_fields_am33xx[][PHY_GMII_SEL_LAST] = {
  147. {
  148. [PHY_GMII_SEL_PORT_MODE] = REG_FIELD(0x650, 0, 1),
  149. [PHY_GMII_SEL_RGMII_ID_MODE] = REG_FIELD(0x650, 4, 4),
  150. [PHY_GMII_SEL_RMII_IO_CLK_EN] = REG_FIELD(0x650, 6, 6),
  151. },
  152. {
  153. [PHY_GMII_SEL_PORT_MODE] = REG_FIELD(0x650, 2, 3),
  154. [PHY_GMII_SEL_RGMII_ID_MODE] = REG_FIELD(0x650, 5, 5),
  155. [PHY_GMII_SEL_RMII_IO_CLK_EN] = REG_FIELD(0x650, 7, 7),
  156. },
  157. };
  158. static const
  159. struct phy_gmii_sel_soc_data phy_gmii_sel_soc_am33xx = {
  160. .num_ports = 2,
  161. .features = BIT(PHY_GMII_SEL_RGMII_ID_MODE) |
  162. BIT(PHY_GMII_SEL_RMII_IO_CLK_EN),
  163. .regfields = phy_gmii_sel_fields_am33xx,
  164. };
  165. static const
  166. struct reg_field phy_gmii_sel_fields_dra7[][PHY_GMII_SEL_LAST] = {
  167. {
  168. [PHY_GMII_SEL_PORT_MODE] = REG_FIELD(0x554, 0, 1),
  169. },
  170. {
  171. [PHY_GMII_SEL_PORT_MODE] = REG_FIELD(0x554, 4, 5),
  172. },
  173. };
  174. static const
  175. struct phy_gmii_sel_soc_data phy_gmii_sel_soc_dra7 = {
  176. .num_ports = 2,
  177. .regfields = phy_gmii_sel_fields_dra7,
  178. };
  179. static const
  180. struct phy_gmii_sel_soc_data phy_gmii_sel_soc_dm814 = {
  181. .num_ports = 2,
  182. .features = BIT(PHY_GMII_SEL_RGMII_ID_MODE),
  183. .regfields = phy_gmii_sel_fields_am33xx,
  184. };
  185. static const
  186. struct reg_field phy_gmii_sel_fields_am654[][PHY_GMII_SEL_LAST] = {
  187. {
  188. [PHY_GMII_SEL_PORT_MODE] = REG_FIELD(0x0, 0, 2),
  189. [PHY_GMII_SEL_RGMII_ID_MODE] = REG_FIELD(0x0, 4, 4),
  190. }, {
  191. [PHY_GMII_SEL_PORT_MODE] = REG_FIELD(0x4, 0, 2),
  192. [PHY_GMII_SEL_RGMII_ID_MODE] = REG_FIELD(0x4, 4, 4),
  193. }, {
  194. [PHY_GMII_SEL_PORT_MODE] = REG_FIELD(0x8, 0, 2),
  195. [PHY_GMII_SEL_RGMII_ID_MODE] = REG_FIELD(0x8, 4, 4),
  196. }, {
  197. [PHY_GMII_SEL_PORT_MODE] = REG_FIELD(0xC, 0, 2),
  198. [PHY_GMII_SEL_RGMII_ID_MODE] = REG_FIELD(0xC, 4, 4),
  199. }, {
  200. [PHY_GMII_SEL_PORT_MODE] = REG_FIELD(0x10, 0, 2),
  201. [PHY_GMII_SEL_RGMII_ID_MODE] = REG_FIELD(0x10, 4, 4),
  202. }, {
  203. [PHY_GMII_SEL_PORT_MODE] = REG_FIELD(0x14, 0, 2),
  204. [PHY_GMII_SEL_RGMII_ID_MODE] = REG_FIELD(0x14, 4, 4),
  205. }, {
  206. [PHY_GMII_SEL_PORT_MODE] = REG_FIELD(0x18, 0, 2),
  207. [PHY_GMII_SEL_RGMII_ID_MODE] = REG_FIELD(0x18, 4, 4),
  208. }, {
  209. [PHY_GMII_SEL_PORT_MODE] = REG_FIELD(0x1C, 0, 2),
  210. [PHY_GMII_SEL_RGMII_ID_MODE] = REG_FIELD(0x1C, 4, 4),
  211. },
  212. };
  213. static const
  214. struct phy_gmii_sel_soc_data phy_gmii_sel_soc_am654 = {
  215. .use_of_data = true,
  216. .features = BIT(PHY_GMII_SEL_RGMII_ID_MODE) |
  217. BIT(PHY_GMII_SEL_FIXED_TX_DELAY),
  218. .regfields = phy_gmii_sel_fields_am654,
  219. };
  220. static const
  221. struct phy_gmii_sel_soc_data phy_gmii_sel_cpsw5g_soc_j7200 = {
  222. .use_of_data = true,
  223. .features = BIT(PHY_GMII_SEL_RGMII_ID_MODE) |
  224. BIT(PHY_GMII_SEL_FIXED_TX_DELAY),
  225. .regfields = phy_gmii_sel_fields_am654,
  226. .extra_modes = BIT(PHY_INTERFACE_MODE_QSGMII) | BIT(PHY_INTERFACE_MODE_SGMII) |
  227. BIT(PHY_INTERFACE_MODE_USXGMII),
  228. .num_ports = 4,
  229. .num_qsgmii_main_ports = 1,
  230. };
  231. static const
  232. struct phy_gmii_sel_soc_data phy_gmii_sel_cpsw9g_soc_j721e = {
  233. .use_of_data = true,
  234. .features = BIT(PHY_GMII_SEL_RGMII_ID_MODE) |
  235. BIT(PHY_GMII_SEL_FIXED_TX_DELAY),
  236. .regfields = phy_gmii_sel_fields_am654,
  237. .extra_modes = BIT(PHY_INTERFACE_MODE_QSGMII) | BIT(PHY_INTERFACE_MODE_SGMII),
  238. .num_ports = 8,
  239. .num_qsgmii_main_ports = 2,
  240. };
  241. static const
  242. struct phy_gmii_sel_soc_data phy_gmii_sel_cpsw9g_soc_j784s4 = {
  243. .use_of_data = true,
  244. .features = BIT(PHY_GMII_SEL_RGMII_ID_MODE) |
  245. BIT(PHY_GMII_SEL_FIXED_TX_DELAY),
  246. .regfields = phy_gmii_sel_fields_am654,
  247. .extra_modes = BIT(PHY_INTERFACE_MODE_QSGMII) | BIT(PHY_INTERFACE_MODE_SGMII) |
  248. BIT(PHY_INTERFACE_MODE_USXGMII),
  249. .num_ports = 8,
  250. .num_qsgmii_main_ports = 2,
  251. };
  252. static const struct of_device_id phy_gmii_sel_id_table[] = {
  253. {
  254. .compatible = "ti,am3352-phy-gmii-sel",
  255. .data = &phy_gmii_sel_soc_am33xx,
  256. },
  257. {
  258. .compatible = "ti,dra7xx-phy-gmii-sel",
  259. .data = &phy_gmii_sel_soc_dra7,
  260. },
  261. {
  262. .compatible = "ti,am43xx-phy-gmii-sel",
  263. .data = &phy_gmii_sel_soc_am33xx,
  264. },
  265. {
  266. .compatible = "ti,dm814-phy-gmii-sel",
  267. .data = &phy_gmii_sel_soc_dm814,
  268. },
  269. {
  270. .compatible = "ti,am654-phy-gmii-sel",
  271. .data = &phy_gmii_sel_soc_am654,
  272. },
  273. {
  274. .compatible = "ti,j7200-cpsw5g-phy-gmii-sel",
  275. .data = &phy_gmii_sel_cpsw5g_soc_j7200,
  276. },
  277. {
  278. .compatible = "ti,j721e-cpsw9g-phy-gmii-sel",
  279. .data = &phy_gmii_sel_cpsw9g_soc_j721e,
  280. },
  281. {
  282. .compatible = "ti,j784s4-cpsw9g-phy-gmii-sel",
  283. .data = &phy_gmii_sel_cpsw9g_soc_j784s4,
  284. },
  285. {}
  286. };
  287. MODULE_DEVICE_TABLE(of, phy_gmii_sel_id_table);
  288. static const struct phy_ops phy_gmii_sel_ops = {
  289. .set_mode = phy_gmii_sel_mode,
  290. .owner = THIS_MODULE,
  291. };
  292. static struct phy *phy_gmii_sel_of_xlate(struct device *dev,
  293. const struct of_phandle_args *args)
  294. {
  295. struct phy_gmii_sel_priv *priv = dev_get_drvdata(dev);
  296. int phy_id = args->args[0];
  297. if (args->args_count < 1)
  298. return ERR_PTR(-EINVAL);
  299. if (!priv || !priv->if_phys)
  300. return ERR_PTR(-ENODEV);
  301. if (priv->soc_data->features & BIT(PHY_GMII_SEL_RMII_IO_CLK_EN) &&
  302. args->args_count < 2)
  303. return ERR_PTR(-EINVAL);
  304. if (phy_id < 1 || phy_id > priv->num_ports)
  305. return ERR_PTR(-EINVAL);
  306. if (phy_id != priv->if_phys[phy_id - 1].id)
  307. return ERR_PTR(-EINVAL);
  308. phy_id--;
  309. if (priv->soc_data->features & BIT(PHY_GMII_SEL_RMII_IO_CLK_EN))
  310. priv->if_phys[phy_id].rmii_clock_external = args->args[1];
  311. dev_dbg(dev, "%s id:%u ext:%d\n", __func__,
  312. priv->if_phys[phy_id].id, args->args[1]);
  313. return priv->if_phys[phy_id].if_phy;
  314. }
  315. static int phy_gmii_init_phy(struct phy_gmii_sel_priv *priv, int port,
  316. struct phy_gmii_sel_phy_priv *if_phy)
  317. {
  318. const struct phy_gmii_sel_soc_data *soc_data = priv->soc_data;
  319. struct device *dev = priv->dev;
  320. const struct reg_field *fields;
  321. struct regmap_field *regfield;
  322. struct reg_field field;
  323. int ret;
  324. if_phy->id = port;
  325. if_phy->priv = priv;
  326. fields = soc_data->regfields[port - 1];
  327. field = *fields++;
  328. field.reg += priv->reg_offset;
  329. dev_dbg(dev, "%s field %x %d %d\n", __func__,
  330. field.reg, field.msb, field.lsb);
  331. regfield = devm_regmap_field_alloc(dev, priv->regmap, field);
  332. if (IS_ERR(regfield))
  333. return PTR_ERR(regfield);
  334. if_phy->fields[PHY_GMII_SEL_PORT_MODE] = regfield;
  335. field = *fields++;
  336. field.reg += priv->reg_offset;
  337. if (soc_data->features & BIT(PHY_GMII_SEL_RGMII_ID_MODE)) {
  338. regfield = devm_regmap_field_alloc(dev,
  339. priv->regmap,
  340. field);
  341. if (IS_ERR(regfield))
  342. return PTR_ERR(regfield);
  343. if_phy->fields[PHY_GMII_SEL_RGMII_ID_MODE] = regfield;
  344. dev_dbg(dev, "%s field %x %d %d\n", __func__,
  345. field.reg, field.msb, field.lsb);
  346. }
  347. field = *fields;
  348. field.reg += priv->reg_offset;
  349. if (soc_data->features & BIT(PHY_GMII_SEL_RMII_IO_CLK_EN)) {
  350. regfield = devm_regmap_field_alloc(dev,
  351. priv->regmap,
  352. field);
  353. if (IS_ERR(regfield))
  354. return PTR_ERR(regfield);
  355. if_phy->fields[PHY_GMII_SEL_RMII_IO_CLK_EN] = regfield;
  356. dev_dbg(dev, "%s field %x %d %d\n", __func__,
  357. field.reg, field.msb, field.lsb);
  358. }
  359. if_phy->if_phy = devm_phy_create(dev,
  360. priv->dev->of_node,
  361. &phy_gmii_sel_ops);
  362. if (IS_ERR(if_phy->if_phy)) {
  363. ret = PTR_ERR(if_phy->if_phy);
  364. dev_err(dev, "Failed to create phy%d %d\n", port, ret);
  365. return ret;
  366. }
  367. phy_set_drvdata(if_phy->if_phy, if_phy);
  368. return 0;
  369. }
  370. static int phy_gmii_sel_init_ports(struct phy_gmii_sel_priv *priv)
  371. {
  372. const struct phy_gmii_sel_soc_data *soc_data = priv->soc_data;
  373. struct phy_gmii_sel_phy_priv *if_phys;
  374. struct device *dev = priv->dev;
  375. int i, ret;
  376. if (soc_data->use_of_data) {
  377. const __be32 *offset;
  378. u64 size;
  379. offset = of_get_address(dev->of_node, 0, &size, NULL);
  380. if (!offset)
  381. return -EINVAL;
  382. priv->num_ports = size / sizeof(u32);
  383. if (!priv->num_ports)
  384. return -EINVAL;
  385. if (!priv->no_offset)
  386. priv->reg_offset = __be32_to_cpu(*offset);
  387. }
  388. if_phys = devm_kcalloc(dev, priv->num_ports,
  389. sizeof(*if_phys), GFP_KERNEL);
  390. if (!if_phys)
  391. return -ENOMEM;
  392. dev_dbg(dev, "%s %d\n", __func__, priv->num_ports);
  393. for (i = 0; i < priv->num_ports; i++) {
  394. ret = phy_gmii_init_phy(priv, i + 1, &if_phys[i]);
  395. if (ret)
  396. return ret;
  397. }
  398. priv->if_phys = if_phys;
  399. return 0;
  400. }
  401. static const struct regmap_config phy_gmii_sel_regmap_cfg = {
  402. .reg_bits = 32,
  403. .val_bits = 32,
  404. .reg_stride = 4,
  405. };
  406. static int phy_gmii_sel_probe(struct platform_device *pdev)
  407. {
  408. struct device *dev = &pdev->dev;
  409. const struct phy_gmii_sel_soc_data *soc_data;
  410. struct device_node *node = dev->of_node;
  411. const struct of_device_id *of_id;
  412. struct phy_gmii_sel_priv *priv;
  413. u32 main_ports = 1;
  414. int ret;
  415. u32 i;
  416. of_id = of_match_node(phy_gmii_sel_id_table, pdev->dev.of_node);
  417. if (!of_id)
  418. return -EINVAL;
  419. priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
  420. if (!priv)
  421. return -ENOMEM;
  422. priv->dev = &pdev->dev;
  423. priv->soc_data = of_id->data;
  424. soc_data = priv->soc_data;
  425. priv->num_ports = priv->soc_data->num_ports;
  426. priv->qsgmii_main_ports = 0;
  427. /*
  428. * Based on the compatible, try to read the appropriate number of
  429. * QSGMII main ports from the "ti,qsgmii-main-ports" property from
  430. * the device-tree node.
  431. */
  432. for (i = 0; i < soc_data->num_qsgmii_main_ports; i++) {
  433. of_property_read_u32_index(node, "ti,qsgmii-main-ports", i, &main_ports);
  434. /*
  435. * Ensure that main_ports is within bounds.
  436. */
  437. if (main_ports < 1 || main_ports > soc_data->num_ports) {
  438. dev_err(dev, "Invalid qsgmii main port provided\n");
  439. return -EINVAL;
  440. }
  441. priv->qsgmii_main_ports |= PHY_GMII_PORT(main_ports);
  442. }
  443. priv->regmap = syscon_node_to_regmap(node->parent);
  444. if (IS_ERR(priv->regmap)) {
  445. void __iomem *base;
  446. base = devm_platform_ioremap_resource(pdev, 0);
  447. if (IS_ERR(base))
  448. return dev_err_probe(dev, PTR_ERR(base),
  449. "failed to get base memory resource\n");
  450. priv->regmap = devm_regmap_init_mmio(dev, base, &phy_gmii_sel_regmap_cfg);
  451. if (IS_ERR(priv->regmap))
  452. return dev_err_probe(dev, PTR_ERR(priv->regmap),
  453. "Failed to get syscon\n");
  454. priv->no_offset = true;
  455. }
  456. ret = phy_gmii_sel_init_ports(priv);
  457. if (ret)
  458. return ret;
  459. dev_set_drvdata(&pdev->dev, priv);
  460. priv->phy_provider =
  461. devm_of_phy_provider_register(dev,
  462. phy_gmii_sel_of_xlate);
  463. if (IS_ERR(priv->phy_provider))
  464. return dev_err_probe(dev, PTR_ERR(priv->phy_provider),
  465. "Failed to create phy provider\n");
  466. return 0;
  467. }
  468. static int phy_gmii_sel_resume_noirq(struct device *dev)
  469. {
  470. struct phy_gmii_sel_priv *priv = dev_get_drvdata(dev);
  471. struct phy_gmii_sel_phy_priv *if_phys = priv->if_phys;
  472. int ret, i;
  473. for (i = 0; i < priv->num_ports; i++) {
  474. if (if_phys[i].phy_if_mode) {
  475. ret = phy_gmii_sel_mode(if_phys[i].if_phy,
  476. PHY_MODE_ETHERNET, if_phys[i].phy_if_mode);
  477. if (ret) {
  478. dev_err(dev, "port%u: restore mode fail %d\n",
  479. if_phys[i].if_phy->id, ret);
  480. return ret;
  481. }
  482. }
  483. }
  484. return 0;
  485. }
  486. static DEFINE_NOIRQ_DEV_PM_OPS(phy_gmii_sel_pm_ops, NULL, phy_gmii_sel_resume_noirq);
  487. static struct platform_driver phy_gmii_sel_driver = {
  488. .probe = phy_gmii_sel_probe,
  489. .driver = {
  490. .name = "phy-gmii-sel",
  491. .of_match_table = phy_gmii_sel_id_table,
  492. .pm = pm_sleep_ptr(&phy_gmii_sel_pm_ops),
  493. },
  494. };
  495. module_platform_driver(phy_gmii_sel_driver);
  496. MODULE_LICENSE("GPL v2");
  497. MODULE_AUTHOR("Grygorii Strashko <grygorii.strashko@ti.com>");
  498. MODULE_DESCRIPTION("TI CPSW Port's PHY Interface Mode selection Driver");