hns_mdio.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581
  1. /*
  2. * Copyright (c) 2014-2015 Hisilicon Limited.
  3. *
  4. * This program is free software; you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation; either version 2 of the License, or
  7. * (at your option) any later version.
  8. */
  9. #include <linux/acpi.h>
  10. #include <linux/errno.h>
  11. #include <linux/etherdevice.h>
  12. #include <linux/init.h>
  13. #include <linux/kernel.h>
  14. #include <linux/mfd/syscon.h>
  15. #include <linux/module.h>
  16. #include <linux/mutex.h>
  17. #include <linux/netdevice.h>
  18. #include <linux/of_address.h>
  19. #include <linux/of.h>
  20. #include <linux/of_mdio.h>
  21. #include <linux/of_platform.h>
  22. #include <linux/phy.h>
  23. #include <linux/platform_device.h>
  24. #include <linux/regmap.h>
  25. #define MDIO_DRV_NAME "Hi-HNS_MDIO"
  26. #define MDIO_BUS_NAME "Hisilicon MII Bus"
  27. #define MDIO_TIMEOUT 1000000
  28. struct hns_mdio_sc_reg {
  29. u16 mdio_clk_en;
  30. u16 mdio_clk_dis;
  31. u16 mdio_reset_req;
  32. u16 mdio_reset_dreq;
  33. u16 mdio_clk_st;
  34. u16 mdio_reset_st;
  35. };
  36. struct hns_mdio_device {
  37. void *vbase; /* mdio reg base address */
  38. struct regmap *subctrl_vbase;
  39. struct hns_mdio_sc_reg sc_reg;
  40. };
  41. /* mdio reg */
  42. #define MDIO_COMMAND_REG 0x0
  43. #define MDIO_ADDR_REG 0x4
  44. #define MDIO_WDATA_REG 0x8
  45. #define MDIO_RDATA_REG 0xc
  46. #define MDIO_STA_REG 0x10
  47. /* cfg phy bit map */
  48. #define MDIO_CMD_DEVAD_M 0x1f
  49. #define MDIO_CMD_DEVAD_S 0
  50. #define MDIO_CMD_PRTAD_M 0x1f
  51. #define MDIO_CMD_PRTAD_S 5
  52. #define MDIO_CMD_OP_S 10
  53. #define MDIO_CMD_ST_S 12
  54. #define MDIO_CMD_START_B 14
  55. #define MDIO_ADDR_DATA_M 0xffff
  56. #define MDIO_ADDR_DATA_S 0
  57. #define MDIO_WDATA_DATA_M 0xffff
  58. #define MDIO_WDATA_DATA_S 0
  59. #define MDIO_RDATA_DATA_M 0xffff
  60. #define MDIO_RDATA_DATA_S 0
  61. #define MDIO_STATE_STA_B 0
  62. enum mdio_st_clause {
  63. MDIO_ST_CLAUSE_45 = 0,
  64. MDIO_ST_CLAUSE_22
  65. };
  66. enum mdio_c22_op_seq {
  67. MDIO_C22_WRITE = 1,
  68. MDIO_C22_READ = 2
  69. };
  70. enum mdio_c45_op_seq {
  71. MDIO_C45_WRITE_ADDR = 0,
  72. MDIO_C45_WRITE_DATA,
  73. MDIO_C45_READ_INCREMENT,
  74. MDIO_C45_READ
  75. };
  76. /* peri subctrl reg */
  77. #define MDIO_SC_CLK_EN 0x338
  78. #define MDIO_SC_CLK_DIS 0x33C
  79. #define MDIO_SC_RESET_REQ 0xA38
  80. #define MDIO_SC_RESET_DREQ 0xA3C
  81. #define MDIO_SC_CLK_ST 0x531C
  82. #define MDIO_SC_RESET_ST 0x5A1C
  83. static void mdio_write_reg(void *base, u32 reg, u32 value)
  84. {
  85. u8 __iomem *reg_addr = (u8 __iomem *)base;
  86. writel_relaxed(value, reg_addr + reg);
  87. }
  88. #define MDIO_WRITE_REG(a, reg, value) \
  89. mdio_write_reg((a)->vbase, (reg), (value))
  90. static u32 mdio_read_reg(void *base, u32 reg)
  91. {
  92. u8 __iomem *reg_addr = (u8 __iomem *)base;
  93. return readl_relaxed(reg_addr + reg);
  94. }
  95. #define mdio_set_field(origin, mask, shift, val) \
  96. do { \
  97. (origin) &= (~((mask) << (shift))); \
  98. (origin) |= (((val) & (mask)) << (shift)); \
  99. } while (0)
  100. #define mdio_get_field(origin, mask, shift) (((origin) >> (shift)) & (mask))
  101. static void mdio_set_reg_field(void *base, u32 reg, u32 mask, u32 shift,
  102. u32 val)
  103. {
  104. u32 origin = mdio_read_reg(base, reg);
  105. mdio_set_field(origin, mask, shift, val);
  106. mdio_write_reg(base, reg, origin);
  107. }
  108. #define MDIO_SET_REG_FIELD(dev, reg, mask, shift, val) \
  109. mdio_set_reg_field((dev)->vbase, (reg), (mask), (shift), (val))
  110. static u32 mdio_get_reg_field(void *base, u32 reg, u32 mask, u32 shift)
  111. {
  112. u32 origin;
  113. origin = mdio_read_reg(base, reg);
  114. return mdio_get_field(origin, mask, shift);
  115. }
  116. #define MDIO_GET_REG_FIELD(dev, reg, mask, shift) \
  117. mdio_get_reg_field((dev)->vbase, (reg), (mask), (shift))
  118. #define MDIO_GET_REG_BIT(dev, reg, bit) \
  119. mdio_get_reg_field((dev)->vbase, (reg), 0x1ull, (bit))
  120. #define MDIO_CHECK_SET_ST 1
  121. #define MDIO_CHECK_CLR_ST 0
  122. static int mdio_sc_cfg_reg_write(struct hns_mdio_device *mdio_dev,
  123. u32 cfg_reg, u32 set_val,
  124. u32 st_reg, u32 st_msk, u8 check_st)
  125. {
  126. u32 time_cnt;
  127. u32 reg_value;
  128. regmap_write(mdio_dev->subctrl_vbase, cfg_reg, set_val);
  129. for (time_cnt = MDIO_TIMEOUT; time_cnt; time_cnt--) {
  130. regmap_read(mdio_dev->subctrl_vbase, st_reg, &reg_value);
  131. reg_value &= st_msk;
  132. if ((!!check_st) == (!!reg_value))
  133. break;
  134. }
  135. if ((!!check_st) != (!!reg_value))
  136. return -EBUSY;
  137. return 0;
  138. }
  139. static int hns_mdio_wait_ready(struct mii_bus *bus)
  140. {
  141. struct hns_mdio_device *mdio_dev = bus->priv;
  142. u32 cmd_reg_value;
  143. int i;
  144. /* waitting for MDIO_COMMAND_REG 's mdio_start==0 */
  145. /* after that can do read or write*/
  146. for (i = 0; i < MDIO_TIMEOUT; i++) {
  147. cmd_reg_value = MDIO_GET_REG_BIT(mdio_dev,
  148. MDIO_COMMAND_REG,
  149. MDIO_CMD_START_B);
  150. if (!cmd_reg_value)
  151. break;
  152. }
  153. if ((i == MDIO_TIMEOUT) && cmd_reg_value)
  154. return -ETIMEDOUT;
  155. return 0;
  156. }
  157. static void hns_mdio_cmd_write(struct hns_mdio_device *mdio_dev,
  158. u8 is_c45, u8 op, u8 phy_id, u16 cmd)
  159. {
  160. u32 cmd_reg_value;
  161. u8 st = is_c45 ? MDIO_ST_CLAUSE_45 : MDIO_ST_CLAUSE_22;
  162. cmd_reg_value = st << MDIO_CMD_ST_S;
  163. cmd_reg_value |= op << MDIO_CMD_OP_S;
  164. cmd_reg_value |=
  165. (phy_id & MDIO_CMD_PRTAD_M) << MDIO_CMD_PRTAD_S;
  166. cmd_reg_value |= (cmd & MDIO_CMD_DEVAD_M) << MDIO_CMD_DEVAD_S;
  167. cmd_reg_value |= 1 << MDIO_CMD_START_B;
  168. MDIO_WRITE_REG(mdio_dev, MDIO_COMMAND_REG, cmd_reg_value);
  169. }
  170. /**
  171. * hns_mdio_write - access phy register
  172. * @bus: mdio bus
  173. * @phy_id: phy id
  174. * @regnum: register num
  175. * @value: register value
  176. *
  177. * Return 0 on success, negative on failure
  178. */
  179. static int hns_mdio_write(struct mii_bus *bus,
  180. int phy_id, int regnum, u16 data)
  181. {
  182. int ret;
  183. struct hns_mdio_device *mdio_dev = (struct hns_mdio_device *)bus->priv;
  184. u8 devad = ((regnum >> 16) & 0x1f);
  185. u8 is_c45 = !!(regnum & MII_ADDR_C45);
  186. u16 reg = (u16)(regnum & 0xffff);
  187. u8 op;
  188. u16 cmd_reg_cfg;
  189. dev_dbg(&bus->dev, "mdio write %s,base is %p\n",
  190. bus->id, mdio_dev->vbase);
  191. dev_dbg(&bus->dev, "phy id=%d, is_c45=%d, devad=%d, reg=%#x, write data=%d\n",
  192. phy_id, is_c45, devad, reg, data);
  193. /* wait for ready */
  194. ret = hns_mdio_wait_ready(bus);
  195. if (ret) {
  196. dev_err(&bus->dev, "MDIO bus is busy\n");
  197. return ret;
  198. }
  199. if (!is_c45) {
  200. cmd_reg_cfg = reg;
  201. op = MDIO_C22_WRITE;
  202. } else {
  203. /* config the cmd-reg to write addr*/
  204. MDIO_SET_REG_FIELD(mdio_dev, MDIO_ADDR_REG, MDIO_ADDR_DATA_M,
  205. MDIO_ADDR_DATA_S, reg);
  206. hns_mdio_cmd_write(mdio_dev, is_c45,
  207. MDIO_C45_WRITE_ADDR, phy_id, devad);
  208. /* check for read or write opt is finished */
  209. ret = hns_mdio_wait_ready(bus);
  210. if (ret) {
  211. dev_err(&bus->dev, "MDIO bus is busy\n");
  212. return ret;
  213. }
  214. /* config the data needed writing */
  215. cmd_reg_cfg = devad;
  216. op = MDIO_C45_WRITE_ADDR;
  217. }
  218. MDIO_SET_REG_FIELD(mdio_dev, MDIO_WDATA_REG, MDIO_WDATA_DATA_M,
  219. MDIO_WDATA_DATA_S, data);
  220. hns_mdio_cmd_write(mdio_dev, is_c45, op, phy_id, cmd_reg_cfg);
  221. return 0;
  222. }
  223. /**
  224. * hns_mdio_read - access phy register
  225. * @bus: mdio bus
  226. * @phy_id: phy id
  227. * @regnum: register num
  228. * @value: register value
  229. *
  230. * Return phy register value
  231. */
  232. static int hns_mdio_read(struct mii_bus *bus, int phy_id, int regnum)
  233. {
  234. int ret;
  235. u16 reg_val = 0;
  236. u8 devad = ((regnum >> 16) & 0x1f);
  237. u8 is_c45 = !!(regnum & MII_ADDR_C45);
  238. u16 reg = (u16)(regnum & 0xffff);
  239. struct hns_mdio_device *mdio_dev = (struct hns_mdio_device *)bus->priv;
  240. dev_dbg(&bus->dev, "mdio read %s,base is %p\n",
  241. bus->id, mdio_dev->vbase);
  242. dev_dbg(&bus->dev, "phy id=%d, is_c45=%d, devad=%d, reg=%#x!\n",
  243. phy_id, is_c45, devad, reg);
  244. /* Step 1: wait for ready */
  245. ret = hns_mdio_wait_ready(bus);
  246. if (ret) {
  247. dev_err(&bus->dev, "MDIO bus is busy\n");
  248. return ret;
  249. }
  250. if (!is_c45) {
  251. hns_mdio_cmd_write(mdio_dev, is_c45,
  252. MDIO_C22_READ, phy_id, reg);
  253. } else {
  254. MDIO_SET_REG_FIELD(mdio_dev, MDIO_ADDR_REG, MDIO_ADDR_DATA_M,
  255. MDIO_ADDR_DATA_S, reg);
  256. /* Step 2; config the cmd-reg to write addr*/
  257. hns_mdio_cmd_write(mdio_dev, is_c45,
  258. MDIO_C45_WRITE_ADDR, phy_id, devad);
  259. /* Step 3: check for read or write opt is finished */
  260. ret = hns_mdio_wait_ready(bus);
  261. if (ret) {
  262. dev_err(&bus->dev, "MDIO bus is busy\n");
  263. return ret;
  264. }
  265. hns_mdio_cmd_write(mdio_dev, is_c45,
  266. MDIO_C45_WRITE_ADDR, phy_id, devad);
  267. }
  268. /* Step 5: waitting for MDIO_COMMAND_REG 's mdio_start==0,*/
  269. /* check for read or write opt is finished */
  270. ret = hns_mdio_wait_ready(bus);
  271. if (ret) {
  272. dev_err(&bus->dev, "MDIO bus is busy\n");
  273. return ret;
  274. }
  275. reg_val = MDIO_GET_REG_BIT(mdio_dev, MDIO_STA_REG, MDIO_STATE_STA_B);
  276. if (reg_val) {
  277. dev_err(&bus->dev, " ERROR! MDIO Read failed!\n");
  278. return -EBUSY;
  279. }
  280. /* Step 6; get out data*/
  281. reg_val = (u16)MDIO_GET_REG_FIELD(mdio_dev, MDIO_RDATA_REG,
  282. MDIO_RDATA_DATA_M, MDIO_RDATA_DATA_S);
  283. return reg_val;
  284. }
  285. /**
  286. * hns_mdio_reset - reset mdio bus
  287. * @bus: mdio bus
  288. *
  289. * Return 0 on success, negative on failure
  290. */
  291. static int hns_mdio_reset(struct mii_bus *bus)
  292. {
  293. struct hns_mdio_device *mdio_dev = (struct hns_mdio_device *)bus->priv;
  294. const struct hns_mdio_sc_reg *sc_reg;
  295. int ret;
  296. if (dev_of_node(bus->parent)) {
  297. if (!mdio_dev->subctrl_vbase) {
  298. dev_err(&bus->dev, "mdio sys ctl reg has not maped\n");
  299. return -ENODEV;
  300. }
  301. sc_reg = &mdio_dev->sc_reg;
  302. /* 1. reset req, and read reset st check */
  303. ret = mdio_sc_cfg_reg_write(mdio_dev, sc_reg->mdio_reset_req,
  304. 0x1, sc_reg->mdio_reset_st, 0x1,
  305. MDIO_CHECK_SET_ST);
  306. if (ret) {
  307. dev_err(&bus->dev, "MDIO reset fail\n");
  308. return ret;
  309. }
  310. /* 2. dis clk, and read clk st check */
  311. ret = mdio_sc_cfg_reg_write(mdio_dev, sc_reg->mdio_clk_dis,
  312. 0x1, sc_reg->mdio_clk_st, 0x1,
  313. MDIO_CHECK_CLR_ST);
  314. if (ret) {
  315. dev_err(&bus->dev, "MDIO dis clk fail\n");
  316. return ret;
  317. }
  318. /* 3. reset dreq, and read reset st check */
  319. ret = mdio_sc_cfg_reg_write(mdio_dev, sc_reg->mdio_reset_dreq,
  320. 0x1, sc_reg->mdio_reset_st, 0x1,
  321. MDIO_CHECK_CLR_ST);
  322. if (ret) {
  323. dev_err(&bus->dev, "MDIO dis clk fail\n");
  324. return ret;
  325. }
  326. /* 4. en clk, and read clk st check */
  327. ret = mdio_sc_cfg_reg_write(mdio_dev, sc_reg->mdio_clk_en,
  328. 0x1, sc_reg->mdio_clk_st, 0x1,
  329. MDIO_CHECK_SET_ST);
  330. if (ret)
  331. dev_err(&bus->dev, "MDIO en clk fail\n");
  332. } else if (is_acpi_node(bus->parent->fwnode)) {
  333. acpi_status s;
  334. s = acpi_evaluate_object(ACPI_HANDLE(bus->parent),
  335. "_RST", NULL, NULL);
  336. if (ACPI_FAILURE(s)) {
  337. dev_err(&bus->dev, "Reset failed, return:%#x\n", s);
  338. ret = -EBUSY;
  339. } else {
  340. ret = 0;
  341. }
  342. } else {
  343. dev_err(&bus->dev, "Can not get cfg data from DT or ACPI\n");
  344. ret = -ENXIO;
  345. }
  346. return ret;
  347. }
  348. /**
  349. * hns_mdio_probe - probe mdio device
  350. * @pdev: mdio platform device
  351. *
  352. * Return 0 on success, negative on failure
  353. */
  354. static int hns_mdio_probe(struct platform_device *pdev)
  355. {
  356. struct hns_mdio_device *mdio_dev;
  357. struct mii_bus *new_bus;
  358. struct resource *res;
  359. int ret = -ENODEV;
  360. if (!pdev) {
  361. dev_err(NULL, "pdev is NULL!\r\n");
  362. return -ENODEV;
  363. }
  364. mdio_dev = devm_kzalloc(&pdev->dev, sizeof(*mdio_dev), GFP_KERNEL);
  365. if (!mdio_dev)
  366. return -ENOMEM;
  367. new_bus = devm_mdiobus_alloc(&pdev->dev);
  368. if (!new_bus) {
  369. dev_err(&pdev->dev, "mdiobus_alloc fail!\n");
  370. return -ENOMEM;
  371. }
  372. new_bus->name = MDIO_BUS_NAME;
  373. new_bus->read = hns_mdio_read;
  374. new_bus->write = hns_mdio_write;
  375. new_bus->reset = hns_mdio_reset;
  376. new_bus->priv = mdio_dev;
  377. new_bus->parent = &pdev->dev;
  378. res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  379. mdio_dev->vbase = devm_ioremap_resource(&pdev->dev, res);
  380. if (IS_ERR(mdio_dev->vbase)) {
  381. ret = PTR_ERR(mdio_dev->vbase);
  382. return ret;
  383. }
  384. platform_set_drvdata(pdev, new_bus);
  385. snprintf(new_bus->id, MII_BUS_ID_SIZE, "%s-%s", "Mii",
  386. dev_name(&pdev->dev));
  387. if (dev_of_node(&pdev->dev)) {
  388. struct of_phandle_args reg_args;
  389. ret = of_parse_phandle_with_fixed_args(pdev->dev.of_node,
  390. "subctrl-vbase",
  391. 4,
  392. 0,
  393. &reg_args);
  394. if (!ret) {
  395. mdio_dev->subctrl_vbase =
  396. syscon_node_to_regmap(reg_args.np);
  397. if (IS_ERR(mdio_dev->subctrl_vbase)) {
  398. dev_warn(&pdev->dev, "syscon_node_to_regmap error\n");
  399. mdio_dev->subctrl_vbase = NULL;
  400. } else {
  401. if (reg_args.args_count == 4) {
  402. mdio_dev->sc_reg.mdio_clk_en =
  403. (u16)reg_args.args[0];
  404. mdio_dev->sc_reg.mdio_clk_dis =
  405. (u16)reg_args.args[0] + 4;
  406. mdio_dev->sc_reg.mdio_reset_req =
  407. (u16)reg_args.args[1];
  408. mdio_dev->sc_reg.mdio_reset_dreq =
  409. (u16)reg_args.args[1] + 4;
  410. mdio_dev->sc_reg.mdio_clk_st =
  411. (u16)reg_args.args[2];
  412. mdio_dev->sc_reg.mdio_reset_st =
  413. (u16)reg_args.args[3];
  414. } else {
  415. /* for compatible */
  416. mdio_dev->sc_reg.mdio_clk_en =
  417. MDIO_SC_CLK_EN;
  418. mdio_dev->sc_reg.mdio_clk_dis =
  419. MDIO_SC_CLK_DIS;
  420. mdio_dev->sc_reg.mdio_reset_req =
  421. MDIO_SC_RESET_REQ;
  422. mdio_dev->sc_reg.mdio_reset_dreq =
  423. MDIO_SC_RESET_DREQ;
  424. mdio_dev->sc_reg.mdio_clk_st =
  425. MDIO_SC_CLK_ST;
  426. mdio_dev->sc_reg.mdio_reset_st =
  427. MDIO_SC_RESET_ST;
  428. }
  429. }
  430. } else {
  431. dev_warn(&pdev->dev, "find syscon ret = %#x\n", ret);
  432. mdio_dev->subctrl_vbase = NULL;
  433. }
  434. ret = of_mdiobus_register(new_bus, pdev->dev.of_node);
  435. } else if (is_acpi_node(pdev->dev.fwnode)) {
  436. /* Clear all the IRQ properties */
  437. memset(new_bus->irq, PHY_POLL, 4 * PHY_MAX_ADDR);
  438. /* Mask out all PHYs from auto probing. */
  439. new_bus->phy_mask = ~0;
  440. /* Register the MDIO bus */
  441. ret = mdiobus_register(new_bus);
  442. } else {
  443. dev_err(&pdev->dev, "Can not get cfg data from DT or ACPI\n");
  444. ret = -ENXIO;
  445. }
  446. if (ret) {
  447. dev_err(&pdev->dev, "Cannot register as MDIO bus!\n");
  448. platform_set_drvdata(pdev, NULL);
  449. return ret;
  450. }
  451. return 0;
  452. }
  453. /**
  454. * hns_mdio_remove - remove mdio device
  455. * @pdev: mdio platform device
  456. *
  457. * Return 0 on success, negative on failure
  458. */
  459. static int hns_mdio_remove(struct platform_device *pdev)
  460. {
  461. struct mii_bus *bus;
  462. bus = platform_get_drvdata(pdev);
  463. mdiobus_unregister(bus);
  464. platform_set_drvdata(pdev, NULL);
  465. return 0;
  466. }
  467. static const struct of_device_id hns_mdio_match[] = {
  468. {.compatible = "hisilicon,mdio"},
  469. {.compatible = "hisilicon,hns-mdio"},
  470. {}
  471. };
  472. MODULE_DEVICE_TABLE(of, hns_mdio_match);
  473. static const struct acpi_device_id hns_mdio_acpi_match[] = {
  474. { "HISI0141", 0 },
  475. { },
  476. };
  477. MODULE_DEVICE_TABLE(acpi, hns_mdio_acpi_match);
  478. static struct platform_driver hns_mdio_driver = {
  479. .probe = hns_mdio_probe,
  480. .remove = hns_mdio_remove,
  481. .driver = {
  482. .name = MDIO_DRV_NAME,
  483. .of_match_table = hns_mdio_match,
  484. .acpi_match_table = ACPI_PTR(hns_mdio_acpi_match),
  485. },
  486. };
  487. module_platform_driver(hns_mdio_driver);
  488. MODULE_LICENSE("GPL");
  489. MODULE_AUTHOR("Huawei Tech. Co., Ltd.");
  490. MODULE_DESCRIPTION("Hisilicon HNS MDIO driver");
  491. MODULE_ALIAS("platform:" MDIO_DRV_NAME);