pcs-rzn1-miic.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Copyright (C) 2022 Schneider Electric
  4. *
  5. * Clément Léger <clement.leger@bootlin.com>
  6. */
  7. #include <linux/clk.h>
  8. #include <linux/device.h>
  9. #include <linux/mdio.h>
  10. #include <linux/of.h>
  11. #include <linux/of_platform.h>
  12. #include <linux/pcs-rzn1-miic.h>
  13. #include <linux/phylink.h>
  14. #include <linux/platform_device.h>
  15. #include <linux/pm_runtime.h>
  16. #include <dt-bindings/net/pcs-rzn1-miic.h>
  17. #define MIIC_PRCMD 0x0
  18. #define MIIC_ESID_CODE 0x4
  19. #define MIIC_MODCTRL 0x8
  20. #define MIIC_MODCTRL_SW_MODE GENMASK(4, 0)
  21. #define MIIC_CONVCTRL(port) (0x100 + (port) * 4)
  22. #define MIIC_CONVCTRL_CONV_SPEED GENMASK(1, 0)
  23. #define CONV_MODE_10MBPS 0
  24. #define CONV_MODE_100MBPS 1
  25. #define CONV_MODE_1000MBPS 2
  26. #define MIIC_CONVCTRL_CONV_MODE GENMASK(3, 2)
  27. #define CONV_MODE_MII 0
  28. #define CONV_MODE_RMII 1
  29. #define CONV_MODE_RGMII 2
  30. #define MIIC_CONVCTRL_FULLD BIT(8)
  31. #define MIIC_CONVCTRL_RGMII_LINK BIT(12)
  32. #define MIIC_CONVCTRL_RGMII_DUPLEX BIT(13)
  33. #define MIIC_CONVCTRL_RGMII_SPEED GENMASK(15, 14)
  34. #define MIIC_CONVRST 0x114
  35. #define MIIC_CONVRST_PHYIF_RST(port) BIT(port)
  36. #define MIIC_CONVRST_PHYIF_RST_MASK GENMASK(4, 0)
  37. #define MIIC_SWCTRL 0x304
  38. #define MIIC_SWDUPC 0x308
  39. #define MIIC_MAX_NR_PORTS 5
  40. #define MIIC_MODCTRL_CONF_CONV_NUM 6
  41. #define MIIC_MODCTRL_CONF_NONE -1
  42. /**
  43. * struct modctrl_match - Matching table entry for convctrl configuration
  44. * See section 8.2.1 of manual.
  45. * @mode_cfg: Configuration value for convctrl
  46. * @conv: Configuration of ethernet port muxes. First index is SWITCH_PORTIN,
  47. * then index 1 - 5 are CONV1 - CONV5.
  48. */
  49. struct modctrl_match {
  50. u32 mode_cfg;
  51. u8 conv[MIIC_MODCTRL_CONF_CONV_NUM];
  52. };
  53. static struct modctrl_match modctrl_match_table[] = {
  54. {0x0, {MIIC_RTOS_PORT, MIIC_GMAC1_PORT, MIIC_SWITCH_PORTD,
  55. MIIC_SWITCH_PORTC, MIIC_SERCOS_PORTB, MIIC_SERCOS_PORTA}},
  56. {0x1, {MIIC_RTOS_PORT, MIIC_GMAC1_PORT, MIIC_SWITCH_PORTD,
  57. MIIC_SWITCH_PORTC, MIIC_ETHERCAT_PORTB, MIIC_ETHERCAT_PORTA}},
  58. {0x2, {MIIC_RTOS_PORT, MIIC_GMAC1_PORT, MIIC_SWITCH_PORTD,
  59. MIIC_ETHERCAT_PORTC, MIIC_ETHERCAT_PORTB, MIIC_ETHERCAT_PORTA}},
  60. {0x3, {MIIC_RTOS_PORT, MIIC_GMAC1_PORT, MIIC_SWITCH_PORTD,
  61. MIIC_SWITCH_PORTC, MIIC_SWITCH_PORTB, MIIC_SWITCH_PORTA}},
  62. {0x8, {MIIC_RTOS_PORT, MIIC_GMAC1_PORT, MIIC_SWITCH_PORTD,
  63. MIIC_SWITCH_PORTC, MIIC_SERCOS_PORTB, MIIC_SERCOS_PORTA}},
  64. {0x9, {MIIC_RTOS_PORT, MIIC_GMAC1_PORT, MIIC_SWITCH_PORTD,
  65. MIIC_SWITCH_PORTC, MIIC_ETHERCAT_PORTB, MIIC_ETHERCAT_PORTA}},
  66. {0xA, {MIIC_RTOS_PORT, MIIC_GMAC1_PORT, MIIC_SWITCH_PORTD,
  67. MIIC_ETHERCAT_PORTC, MIIC_ETHERCAT_PORTB, MIIC_ETHERCAT_PORTA}},
  68. {0xB, {MIIC_RTOS_PORT, MIIC_GMAC1_PORT, MIIC_SWITCH_PORTD,
  69. MIIC_SWITCH_PORTC, MIIC_SWITCH_PORTB, MIIC_SWITCH_PORTA}},
  70. {0x10, {MIIC_GMAC2_PORT, MIIC_GMAC1_PORT, MIIC_SWITCH_PORTD,
  71. MIIC_SWITCH_PORTC, MIIC_SERCOS_PORTB, MIIC_SERCOS_PORTA}},
  72. {0x11, {MIIC_GMAC2_PORT, MIIC_GMAC1_PORT, MIIC_SWITCH_PORTD,
  73. MIIC_SWITCH_PORTC, MIIC_ETHERCAT_PORTB, MIIC_ETHERCAT_PORTA}},
  74. {0x12, {MIIC_GMAC2_PORT, MIIC_GMAC1_PORT, MIIC_SWITCH_PORTD,
  75. MIIC_ETHERCAT_PORTC, MIIC_ETHERCAT_PORTB, MIIC_ETHERCAT_PORTA}},
  76. {0x13, {MIIC_GMAC2_PORT, MIIC_GMAC1_PORT, MIIC_SWITCH_PORTD,
  77. MIIC_SWITCH_PORTC, MIIC_SWITCH_PORTB, MIIC_SWITCH_PORTA}}
  78. };
  79. static const char * const conf_to_string[] = {
  80. [MIIC_GMAC1_PORT] = "GMAC1_PORT",
  81. [MIIC_GMAC2_PORT] = "GMAC2_PORT",
  82. [MIIC_RTOS_PORT] = "RTOS_PORT",
  83. [MIIC_SERCOS_PORTA] = "SERCOS_PORTA",
  84. [MIIC_SERCOS_PORTB] = "SERCOS_PORTB",
  85. [MIIC_ETHERCAT_PORTA] = "ETHERCAT_PORTA",
  86. [MIIC_ETHERCAT_PORTB] = "ETHERCAT_PORTB",
  87. [MIIC_ETHERCAT_PORTC] = "ETHERCAT_PORTC",
  88. [MIIC_SWITCH_PORTA] = "SWITCH_PORTA",
  89. [MIIC_SWITCH_PORTB] = "SWITCH_PORTB",
  90. [MIIC_SWITCH_PORTC] = "SWITCH_PORTC",
  91. [MIIC_SWITCH_PORTD] = "SWITCH_PORTD",
  92. [MIIC_HSR_PORTA] = "HSR_PORTA",
  93. [MIIC_HSR_PORTB] = "HSR_PORTB",
  94. };
  95. static const char *index_to_string[MIIC_MODCTRL_CONF_CONV_NUM] = {
  96. "SWITCH_PORTIN",
  97. "CONV1",
  98. "CONV2",
  99. "CONV3",
  100. "CONV4",
  101. "CONV5",
  102. };
  103. /**
  104. * struct miic - MII converter structure
  105. * @base: base address of the MII converter
  106. * @dev: Device associated to the MII converter
  107. * @lock: Lock used for read-modify-write access
  108. */
  109. struct miic {
  110. void __iomem *base;
  111. struct device *dev;
  112. spinlock_t lock;
  113. };
  114. /**
  115. * struct miic_port - Per port MII converter struct
  116. * @miic: backiling to MII converter structure
  117. * @pcs: PCS structure associated to the port
  118. * @port: port number
  119. * @interface: interface mode of the port
  120. */
  121. struct miic_port {
  122. struct miic *miic;
  123. struct phylink_pcs pcs;
  124. int port;
  125. phy_interface_t interface;
  126. };
  127. static struct miic_port *phylink_pcs_to_miic_port(struct phylink_pcs *pcs)
  128. {
  129. return container_of(pcs, struct miic_port, pcs);
  130. }
  131. static void miic_reg_writel(struct miic *miic, int offset, u32 value)
  132. {
  133. writel(value, miic->base + offset);
  134. }
  135. static u32 miic_reg_readl(struct miic *miic, int offset)
  136. {
  137. return readl(miic->base + offset);
  138. }
  139. static void miic_reg_rmw(struct miic *miic, int offset, u32 mask, u32 val)
  140. {
  141. u32 reg;
  142. spin_lock(&miic->lock);
  143. reg = miic_reg_readl(miic, offset);
  144. reg &= ~mask;
  145. reg |= val;
  146. miic_reg_writel(miic, offset, reg);
  147. spin_unlock(&miic->lock);
  148. }
  149. static void miic_converter_enable(struct miic *miic, int port, int enable)
  150. {
  151. u32 val = 0;
  152. if (enable)
  153. val = MIIC_CONVRST_PHYIF_RST(port);
  154. miic_reg_rmw(miic, MIIC_CONVRST, MIIC_CONVRST_PHYIF_RST(port), val);
  155. }
  156. static int miic_config(struct phylink_pcs *pcs, unsigned int neg_mode,
  157. phy_interface_t interface,
  158. const unsigned long *advertising, bool permit)
  159. {
  160. struct miic_port *miic_port = phylink_pcs_to_miic_port(pcs);
  161. struct miic *miic = miic_port->miic;
  162. u32 speed, conv_mode, val, mask;
  163. int port = miic_port->port;
  164. switch (interface) {
  165. case PHY_INTERFACE_MODE_RMII:
  166. conv_mode = CONV_MODE_RMII;
  167. speed = CONV_MODE_100MBPS;
  168. break;
  169. case PHY_INTERFACE_MODE_RGMII:
  170. case PHY_INTERFACE_MODE_RGMII_ID:
  171. case PHY_INTERFACE_MODE_RGMII_TXID:
  172. case PHY_INTERFACE_MODE_RGMII_RXID:
  173. conv_mode = CONV_MODE_RGMII;
  174. speed = CONV_MODE_1000MBPS;
  175. break;
  176. case PHY_INTERFACE_MODE_MII:
  177. conv_mode = CONV_MODE_MII;
  178. /* When in MII mode, speed should be set to 0 (which is actually
  179. * CONV_MODE_10MBPS)
  180. */
  181. speed = CONV_MODE_10MBPS;
  182. break;
  183. default:
  184. return -EOPNOTSUPP;
  185. }
  186. val = FIELD_PREP(MIIC_CONVCTRL_CONV_MODE, conv_mode);
  187. mask = MIIC_CONVCTRL_CONV_MODE;
  188. /* Update speed only if we are going to change the interface because
  189. * the link might already be up and it would break it if the speed is
  190. * changed.
  191. */
  192. if (interface != miic_port->interface) {
  193. val |= FIELD_PREP(MIIC_CONVCTRL_CONV_SPEED, speed);
  194. mask |= MIIC_CONVCTRL_CONV_SPEED;
  195. miic_port->interface = interface;
  196. }
  197. miic_reg_rmw(miic, MIIC_CONVCTRL(port), mask, val);
  198. miic_converter_enable(miic, miic_port->port, 1);
  199. return 0;
  200. }
  201. static void miic_link_up(struct phylink_pcs *pcs, unsigned int neg_mode,
  202. phy_interface_t interface, int speed, int duplex)
  203. {
  204. struct miic_port *miic_port = phylink_pcs_to_miic_port(pcs);
  205. struct miic *miic = miic_port->miic;
  206. u32 conv_speed = 0, val = 0;
  207. int port = miic_port->port;
  208. if (duplex == DUPLEX_FULL)
  209. val |= MIIC_CONVCTRL_FULLD;
  210. /* No speed in MII through-mode */
  211. if (interface != PHY_INTERFACE_MODE_MII) {
  212. switch (speed) {
  213. case SPEED_1000:
  214. conv_speed = CONV_MODE_1000MBPS;
  215. break;
  216. case SPEED_100:
  217. conv_speed = CONV_MODE_100MBPS;
  218. break;
  219. case SPEED_10:
  220. conv_speed = CONV_MODE_10MBPS;
  221. break;
  222. default:
  223. return;
  224. }
  225. }
  226. val |= FIELD_PREP(MIIC_CONVCTRL_CONV_SPEED, conv_speed);
  227. miic_reg_rmw(miic, MIIC_CONVCTRL(port),
  228. (MIIC_CONVCTRL_CONV_SPEED | MIIC_CONVCTRL_FULLD), val);
  229. }
  230. static int miic_validate(struct phylink_pcs *pcs, unsigned long *supported,
  231. const struct phylink_link_state *state)
  232. {
  233. if (phy_interface_mode_is_rgmii(state->interface) ||
  234. state->interface == PHY_INTERFACE_MODE_RMII ||
  235. state->interface == PHY_INTERFACE_MODE_MII)
  236. return 1;
  237. return -EINVAL;
  238. }
  239. static int miic_pre_init(struct phylink_pcs *pcs)
  240. {
  241. struct miic_port *miic_port = phylink_pcs_to_miic_port(pcs);
  242. struct miic *miic = miic_port->miic;
  243. u32 val, mask;
  244. /* Start RX clock if required */
  245. if (pcs->rxc_always_on) {
  246. /* In MII through mode, the clock signals will be driven by the
  247. * external PHY, which might not be initialized yet. Set RMII
  248. * as default mode to ensure that a reference clock signal is
  249. * generated.
  250. */
  251. miic_port->interface = PHY_INTERFACE_MODE_RMII;
  252. val = FIELD_PREP(MIIC_CONVCTRL_CONV_MODE, CONV_MODE_RMII) |
  253. FIELD_PREP(MIIC_CONVCTRL_CONV_SPEED, CONV_MODE_100MBPS);
  254. mask = MIIC_CONVCTRL_CONV_MODE | MIIC_CONVCTRL_CONV_SPEED;
  255. miic_reg_rmw(miic, MIIC_CONVCTRL(miic_port->port), mask, val);
  256. miic_converter_enable(miic, miic_port->port, 1);
  257. }
  258. return 0;
  259. }
  260. static const struct phylink_pcs_ops miic_phylink_ops = {
  261. .pcs_validate = miic_validate,
  262. .pcs_config = miic_config,
  263. .pcs_link_up = miic_link_up,
  264. .pcs_pre_init = miic_pre_init,
  265. };
  266. struct phylink_pcs *miic_create(struct device *dev, struct device_node *np)
  267. {
  268. struct platform_device *pdev;
  269. struct miic_port *miic_port;
  270. struct device_node *pcs_np;
  271. struct miic *miic;
  272. u32 port;
  273. if (!of_device_is_available(np))
  274. return ERR_PTR(-ENODEV);
  275. if (of_property_read_u32(np, "reg", &port))
  276. return ERR_PTR(-EINVAL);
  277. if (port > MIIC_MAX_NR_PORTS || port < 1)
  278. return ERR_PTR(-EINVAL);
  279. /* The PCS pdev is attached to the parent node */
  280. pcs_np = of_get_parent(np);
  281. if (!pcs_np)
  282. return ERR_PTR(-ENODEV);
  283. if (!of_device_is_available(pcs_np)) {
  284. of_node_put(pcs_np);
  285. return ERR_PTR(-ENODEV);
  286. }
  287. pdev = of_find_device_by_node(pcs_np);
  288. of_node_put(pcs_np);
  289. if (!pdev || !platform_get_drvdata(pdev)) {
  290. if (pdev)
  291. put_device(&pdev->dev);
  292. return ERR_PTR(-EPROBE_DEFER);
  293. }
  294. miic_port = kzalloc(sizeof(*miic_port), GFP_KERNEL);
  295. if (!miic_port) {
  296. put_device(&pdev->dev);
  297. return ERR_PTR(-ENOMEM);
  298. }
  299. miic = platform_get_drvdata(pdev);
  300. device_link_add(dev, miic->dev, DL_FLAG_AUTOREMOVE_CONSUMER);
  301. put_device(&pdev->dev);
  302. miic_port->miic = miic;
  303. miic_port->port = port - 1;
  304. miic_port->pcs.ops = &miic_phylink_ops;
  305. miic_port->pcs.neg_mode = true;
  306. return &miic_port->pcs;
  307. }
  308. EXPORT_SYMBOL(miic_create);
  309. void miic_destroy(struct phylink_pcs *pcs)
  310. {
  311. struct miic_port *miic_port = phylink_pcs_to_miic_port(pcs);
  312. miic_converter_enable(miic_port->miic, miic_port->port, 0);
  313. kfree(miic_port);
  314. }
  315. EXPORT_SYMBOL(miic_destroy);
  316. static int miic_init_hw(struct miic *miic, u32 cfg_mode)
  317. {
  318. int port;
  319. /* Unlock write access to accessory registers (cf datasheet). If this
  320. * is going to be used in conjunction with the Cortex-M3, this sequence
  321. * will have to be moved in register write
  322. */
  323. miic_reg_writel(miic, MIIC_PRCMD, 0x00A5);
  324. miic_reg_writel(miic, MIIC_PRCMD, 0x0001);
  325. miic_reg_writel(miic, MIIC_PRCMD, 0xFFFE);
  326. miic_reg_writel(miic, MIIC_PRCMD, 0x0001);
  327. miic_reg_writel(miic, MIIC_MODCTRL,
  328. FIELD_PREP(MIIC_MODCTRL_SW_MODE, cfg_mode));
  329. for (port = 0; port < MIIC_MAX_NR_PORTS; port++) {
  330. miic_converter_enable(miic, port, 0);
  331. /* Disable speed/duplex control from these registers, datasheet
  332. * says switch registers should be used to setup switch port
  333. * speed and duplex.
  334. */
  335. miic_reg_writel(miic, MIIC_SWCTRL, 0x0);
  336. miic_reg_writel(miic, MIIC_SWDUPC, 0x0);
  337. }
  338. return 0;
  339. }
  340. static bool miic_modctrl_match(s8 table_val[MIIC_MODCTRL_CONF_CONV_NUM],
  341. s8 dt_val[MIIC_MODCTRL_CONF_CONV_NUM])
  342. {
  343. int i;
  344. for (i = 0; i < MIIC_MODCTRL_CONF_CONV_NUM; i++) {
  345. if (dt_val[i] == MIIC_MODCTRL_CONF_NONE)
  346. continue;
  347. if (dt_val[i] != table_val[i])
  348. return false;
  349. }
  350. return true;
  351. }
  352. static void miic_dump_conf(struct device *dev,
  353. s8 conf[MIIC_MODCTRL_CONF_CONV_NUM])
  354. {
  355. const char *conf_name;
  356. int i;
  357. for (i = 0; i < MIIC_MODCTRL_CONF_CONV_NUM; i++) {
  358. if (conf[i] != MIIC_MODCTRL_CONF_NONE)
  359. conf_name = conf_to_string[conf[i]];
  360. else
  361. conf_name = "NONE";
  362. dev_err(dev, "%s: %s\n", index_to_string[i], conf_name);
  363. }
  364. }
  365. static int miic_match_dt_conf(struct device *dev,
  366. s8 dt_val[MIIC_MODCTRL_CONF_CONV_NUM],
  367. u32 *mode_cfg)
  368. {
  369. struct modctrl_match *table_entry;
  370. int i;
  371. for (i = 0; i < ARRAY_SIZE(modctrl_match_table); i++) {
  372. table_entry = &modctrl_match_table[i];
  373. if (miic_modctrl_match(table_entry->conv, dt_val)) {
  374. *mode_cfg = table_entry->mode_cfg;
  375. return 0;
  376. }
  377. }
  378. dev_err(dev, "Failed to apply requested configuration\n");
  379. miic_dump_conf(dev, dt_val);
  380. return -EINVAL;
  381. }
  382. static int miic_parse_dt(struct device *dev, u32 *mode_cfg)
  383. {
  384. s8 dt_val[MIIC_MODCTRL_CONF_CONV_NUM];
  385. struct device_node *np = dev->of_node;
  386. struct device_node *conv;
  387. u32 conf;
  388. int port;
  389. memset(dt_val, MIIC_MODCTRL_CONF_NONE, sizeof(dt_val));
  390. if (of_property_read_u32(np, "renesas,miic-switch-portin", &conf) == 0)
  391. dt_val[0] = conf;
  392. for_each_child_of_node(np, conv) {
  393. if (of_property_read_u32(conv, "reg", &port))
  394. continue;
  395. if (!of_device_is_available(conv))
  396. continue;
  397. if (of_property_read_u32(conv, "renesas,miic-input", &conf) == 0)
  398. dt_val[port] = conf;
  399. }
  400. return miic_match_dt_conf(dev, dt_val, mode_cfg);
  401. }
  402. static int miic_probe(struct platform_device *pdev)
  403. {
  404. struct device *dev = &pdev->dev;
  405. struct miic *miic;
  406. u32 mode_cfg;
  407. int ret;
  408. ret = miic_parse_dt(dev, &mode_cfg);
  409. if (ret < 0)
  410. return ret;
  411. miic = devm_kzalloc(dev, sizeof(*miic), GFP_KERNEL);
  412. if (!miic)
  413. return -ENOMEM;
  414. spin_lock_init(&miic->lock);
  415. miic->dev = dev;
  416. miic->base = devm_platform_ioremap_resource(pdev, 0);
  417. if (IS_ERR(miic->base))
  418. return PTR_ERR(miic->base);
  419. ret = devm_pm_runtime_enable(dev);
  420. if (ret < 0)
  421. return ret;
  422. ret = pm_runtime_resume_and_get(dev);
  423. if (ret < 0)
  424. return ret;
  425. ret = miic_init_hw(miic, mode_cfg);
  426. if (ret)
  427. goto disable_runtime_pm;
  428. /* miic_create() relies on that fact that data are attached to the
  429. * platform device to determine if the driver is ready so this needs to
  430. * be the last thing to be done after everything is initialized
  431. * properly.
  432. */
  433. platform_set_drvdata(pdev, miic);
  434. return 0;
  435. disable_runtime_pm:
  436. pm_runtime_put(dev);
  437. return ret;
  438. }
  439. static void miic_remove(struct platform_device *pdev)
  440. {
  441. pm_runtime_put(&pdev->dev);
  442. }
  443. static const struct of_device_id miic_of_mtable[] = {
  444. { .compatible = "renesas,rzn1-miic" },
  445. { /* sentinel */ },
  446. };
  447. MODULE_DEVICE_TABLE(of, miic_of_mtable);
  448. static struct platform_driver miic_driver = {
  449. .driver = {
  450. .name = "rzn1_miic",
  451. .suppress_bind_attrs = true,
  452. .of_match_table = miic_of_mtable,
  453. },
  454. .probe = miic_probe,
  455. .remove_new = miic_remove,
  456. };
  457. module_platform_driver(miic_driver);
  458. MODULE_LICENSE("GPL");
  459. MODULE_DESCRIPTION("Renesas MII converter PCS driver");
  460. MODULE_AUTHOR("Clément Léger <clement.leger@bootlin.com>");