hns_mdio.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521
  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/errno.h>
  10. #include <linux/etherdevice.h>
  11. #include <linux/init.h>
  12. #include <linux/kernel.h>
  13. #include <linux/mfd/syscon.h>
  14. #include <linux/module.h>
  15. #include <linux/mutex.h>
  16. #include <linux/netdevice.h>
  17. #include <linux/of_address.h>
  18. #include <linux/of.h>
  19. #include <linux/of_mdio.h>
  20. #include <linux/of_platform.h>
  21. #include <linux/phy.h>
  22. #include <linux/platform_device.h>
  23. #include <linux/regmap.h>
  24. #include <linux/spinlock_types.h>
  25. #define MDIO_DRV_NAME "Hi-HNS_MDIO"
  26. #define MDIO_BUS_NAME "Hisilicon MII Bus"
  27. #define MDIO_DRV_VERSION "1.3.0"
  28. #define MDIO_COPYRIGHT "Copyright(c) 2015 Huawei Corporation."
  29. #define MDIO_DRV_STRING MDIO_BUS_NAME
  30. #define MDIO_DEFAULT_DEVICE_DESCR MDIO_BUS_NAME
  31. #define MDIO_CTL_DEV_ADDR(x) (x & 0x1f)
  32. #define MDIO_CTL_PORT_ADDR(x) ((x & 0x1f) << 5)
  33. #define MDIO_TIMEOUT 1000000
  34. struct hns_mdio_device {
  35. void *vbase; /* mdio reg base address */
  36. struct regmap *subctrl_vbase;
  37. };
  38. /* mdio reg */
  39. #define MDIO_COMMAND_REG 0x0
  40. #define MDIO_ADDR_REG 0x4
  41. #define MDIO_WDATA_REG 0x8
  42. #define MDIO_RDATA_REG 0xc
  43. #define MDIO_STA_REG 0x10
  44. /* cfg phy bit map */
  45. #define MDIO_CMD_DEVAD_M 0x1f
  46. #define MDIO_CMD_DEVAD_S 0
  47. #define MDIO_CMD_PRTAD_M 0x1f
  48. #define MDIO_CMD_PRTAD_S 5
  49. #define MDIO_CMD_OP_M 0x3
  50. #define MDIO_CMD_OP_S 10
  51. #define MDIO_CMD_ST_M 0x3
  52. #define MDIO_CMD_ST_S 12
  53. #define MDIO_CMD_START_B 14
  54. #define MDIO_ADDR_DATA_M 0xffff
  55. #define MDIO_ADDR_DATA_S 0
  56. #define MDIO_WDATA_DATA_M 0xffff
  57. #define MDIO_WDATA_DATA_S 0
  58. #define MDIO_RDATA_DATA_M 0xffff
  59. #define MDIO_RDATA_DATA_S 0
  60. #define MDIO_STATE_STA_B 0
  61. enum mdio_st_clause {
  62. MDIO_ST_CLAUSE_45 = 0,
  63. MDIO_ST_CLAUSE_22
  64. };
  65. enum mdio_c22_op_seq {
  66. MDIO_C22_WRITE = 1,
  67. MDIO_C22_READ = 2
  68. };
  69. enum mdio_c45_op_seq {
  70. MDIO_C45_WRITE_ADDR = 0,
  71. MDIO_C45_WRITE_DATA,
  72. MDIO_C45_READ_INCREMENT,
  73. MDIO_C45_READ
  74. };
  75. /* peri subctrl reg */
  76. #define MDIO_SC_CLK_EN 0x338
  77. #define MDIO_SC_CLK_DIS 0x33C
  78. #define MDIO_SC_RESET_REQ 0xA38
  79. #define MDIO_SC_RESET_DREQ 0xA3C
  80. #define MDIO_SC_CTRL 0x2010
  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. int i;
  143. u32 cmd_reg_value = 1;
  144. /* waitting for MDIO_COMMAND_REG 's mdio_start==0 */
  145. /* after that can do read or write*/
  146. for (i = 0; cmd_reg_value; i++) {
  147. cmd_reg_value = MDIO_GET_REG_BIT(mdio_dev,
  148. MDIO_COMMAND_REG,
  149. MDIO_CMD_START_B);
  150. if (i == MDIO_TIMEOUT)
  151. return -ETIMEDOUT;
  152. }
  153. return 0;
  154. }
  155. static void hns_mdio_cmd_write(struct hns_mdio_device *mdio_dev,
  156. u8 is_c45, u8 op, u8 phy_id, u16 cmd)
  157. {
  158. u32 cmd_reg_value;
  159. u8 st = is_c45 ? MDIO_ST_CLAUSE_45 : MDIO_ST_CLAUSE_22;
  160. cmd_reg_value = st << MDIO_CMD_ST_S;
  161. cmd_reg_value |= op << MDIO_CMD_OP_S;
  162. cmd_reg_value |=
  163. (phy_id & MDIO_CMD_PRTAD_M) << MDIO_CMD_PRTAD_S;
  164. cmd_reg_value |= (cmd & MDIO_CMD_DEVAD_M) << MDIO_CMD_DEVAD_S;
  165. cmd_reg_value |= 1 << MDIO_CMD_START_B;
  166. MDIO_WRITE_REG(mdio_dev, MDIO_COMMAND_REG, cmd_reg_value);
  167. }
  168. /**
  169. * hns_mdio_write - access phy register
  170. * @bus: mdio bus
  171. * @phy_id: phy id
  172. * @regnum: register num
  173. * @value: register value
  174. *
  175. * Return 0 on success, negative on failure
  176. */
  177. static int hns_mdio_write(struct mii_bus *bus,
  178. int phy_id, int regnum, u16 data)
  179. {
  180. int ret;
  181. struct hns_mdio_device *mdio_dev = (struct hns_mdio_device *)bus->priv;
  182. u8 devad = ((regnum >> 16) & 0x1f);
  183. u8 is_c45 = !!(regnum & MII_ADDR_C45);
  184. u16 reg = (u16)(regnum & 0xffff);
  185. u8 op;
  186. u16 cmd_reg_cfg;
  187. dev_dbg(&bus->dev, "mdio write %s,base is %p\n",
  188. bus->id, mdio_dev->vbase);
  189. dev_dbg(&bus->dev, "phy id=%d, is_c45=%d, devad=%d, reg=%#x, write data=%d\n",
  190. phy_id, is_c45, devad, reg, data);
  191. /* wait for ready */
  192. ret = hns_mdio_wait_ready(bus);
  193. if (ret) {
  194. dev_err(&bus->dev, "MDIO bus is busy\n");
  195. return ret;
  196. }
  197. if (!is_c45) {
  198. cmd_reg_cfg = reg;
  199. op = MDIO_C22_WRITE;
  200. } else {
  201. /* config the cmd-reg to write addr*/
  202. MDIO_SET_REG_FIELD(mdio_dev, MDIO_ADDR_REG, MDIO_ADDR_DATA_M,
  203. MDIO_ADDR_DATA_S, reg);
  204. hns_mdio_cmd_write(mdio_dev, is_c45,
  205. MDIO_C45_WRITE_ADDR, phy_id, devad);
  206. /* check for read or write opt is finished */
  207. ret = hns_mdio_wait_ready(bus);
  208. if (ret) {
  209. dev_err(&bus->dev, "MDIO bus is busy\n");
  210. return ret;
  211. }
  212. /* config the data needed writing */
  213. cmd_reg_cfg = devad;
  214. op = MDIO_C45_WRITE_ADDR;
  215. }
  216. MDIO_SET_REG_FIELD(mdio_dev, MDIO_WDATA_REG, MDIO_WDATA_DATA_M,
  217. MDIO_WDATA_DATA_S, data);
  218. hns_mdio_cmd_write(mdio_dev, is_c45, op, phy_id, cmd_reg_cfg);
  219. return 0;
  220. }
  221. /**
  222. * hns_mdio_read - access phy register
  223. * @bus: mdio bus
  224. * @phy_id: phy id
  225. * @regnum: register num
  226. * @value: register value
  227. *
  228. * Return phy register value
  229. */
  230. static int hns_mdio_read(struct mii_bus *bus, int phy_id, int regnum)
  231. {
  232. int ret;
  233. u16 reg_val = 0;
  234. u8 devad = ((regnum >> 16) & 0x1f);
  235. u8 is_c45 = !!(regnum & MII_ADDR_C45);
  236. u16 reg = (u16)(regnum & 0xffff);
  237. struct hns_mdio_device *mdio_dev = (struct hns_mdio_device *)bus->priv;
  238. dev_dbg(&bus->dev, "mdio read %s,base is %p\n",
  239. bus->id, mdio_dev->vbase);
  240. dev_dbg(&bus->dev, "phy id=%d, is_c45=%d, devad=%d, reg=%#x!\n",
  241. phy_id, is_c45, devad, reg);
  242. /* Step 1: wait for ready */
  243. ret = hns_mdio_wait_ready(bus);
  244. if (ret) {
  245. dev_err(&bus->dev, "MDIO bus is busy\n");
  246. return ret;
  247. }
  248. if (!is_c45) {
  249. hns_mdio_cmd_write(mdio_dev, is_c45,
  250. MDIO_C22_READ, phy_id, reg);
  251. } else {
  252. MDIO_SET_REG_FIELD(mdio_dev, MDIO_ADDR_REG, MDIO_ADDR_DATA_M,
  253. MDIO_ADDR_DATA_S, reg);
  254. /* Step 2; config the cmd-reg to write addr*/
  255. hns_mdio_cmd_write(mdio_dev, is_c45,
  256. MDIO_C45_WRITE_ADDR, phy_id, devad);
  257. /* Step 3: check for read or write opt is finished */
  258. ret = hns_mdio_wait_ready(bus);
  259. if (ret) {
  260. dev_err(&bus->dev, "MDIO bus is busy\n");
  261. return ret;
  262. }
  263. hns_mdio_cmd_write(mdio_dev, is_c45,
  264. MDIO_C45_READ, phy_id, devad);
  265. }
  266. /* Step 5: waitting for MDIO_COMMAND_REG 's mdio_start==0,*/
  267. /* check for read or write opt is finished */
  268. ret = hns_mdio_wait_ready(bus);
  269. if (ret) {
  270. dev_err(&bus->dev, "MDIO bus is busy\n");
  271. return ret;
  272. }
  273. reg_val = MDIO_GET_REG_BIT(mdio_dev, MDIO_STA_REG, MDIO_STATE_STA_B);
  274. if (reg_val) {
  275. dev_err(&bus->dev, " ERROR! MDIO Read failed!\n");
  276. return -EBUSY;
  277. }
  278. /* Step 6; get out data*/
  279. reg_val = (u16)MDIO_GET_REG_FIELD(mdio_dev, MDIO_RDATA_REG,
  280. MDIO_RDATA_DATA_M, MDIO_RDATA_DATA_S);
  281. return reg_val;
  282. }
  283. /**
  284. * hns_mdio_reset - reset mdio bus
  285. * @bus: mdio bus
  286. *
  287. * Return 0 on success, negative on failure
  288. */
  289. static int hns_mdio_reset(struct mii_bus *bus)
  290. {
  291. struct hns_mdio_device *mdio_dev = (struct hns_mdio_device *)bus->priv;
  292. int ret;
  293. if (!mdio_dev->subctrl_vbase) {
  294. dev_err(&bus->dev, "mdio sys ctl reg has not maped\n");
  295. return -ENODEV;
  296. }
  297. /*1. reset req, and read reset st check*/
  298. ret = mdio_sc_cfg_reg_write(mdio_dev, MDIO_SC_RESET_REQ, 0x1,
  299. MDIO_SC_RESET_ST, 0x1,
  300. MDIO_CHECK_SET_ST);
  301. if (ret) {
  302. dev_err(&bus->dev, "MDIO reset fail\n");
  303. return ret;
  304. }
  305. /*2. dis clk, and read clk st check*/
  306. ret = mdio_sc_cfg_reg_write(mdio_dev, MDIO_SC_CLK_DIS,
  307. 0x1, MDIO_SC_CLK_ST, 0x1,
  308. MDIO_CHECK_CLR_ST);
  309. if (ret) {
  310. dev_err(&bus->dev, "MDIO dis clk fail\n");
  311. return ret;
  312. }
  313. /*3. reset dreq, and read reset st check*/
  314. ret = mdio_sc_cfg_reg_write(mdio_dev, MDIO_SC_RESET_DREQ, 0x1,
  315. MDIO_SC_RESET_ST, 0x1,
  316. MDIO_CHECK_CLR_ST);
  317. if (ret) {
  318. dev_err(&bus->dev, "MDIO dis clk fail\n");
  319. return ret;
  320. }
  321. /*4. en clk, and read clk st check*/
  322. ret = mdio_sc_cfg_reg_write(mdio_dev, MDIO_SC_CLK_EN,
  323. 0x1, MDIO_SC_CLK_ST, 0x1,
  324. MDIO_CHECK_SET_ST);
  325. if (ret)
  326. dev_err(&bus->dev, "MDIO en clk fail\n");
  327. return ret;
  328. }
  329. /**
  330. * hns_mdio_bus_name - get mdio bus name
  331. * @name: mdio bus name
  332. * @np: mdio device node pointer
  333. */
  334. static void hns_mdio_bus_name(char *name, struct device_node *np)
  335. {
  336. const u32 *addr;
  337. u64 taddr = OF_BAD_ADDR;
  338. addr = of_get_address(np, 0, NULL, NULL);
  339. if (addr)
  340. taddr = of_translate_address(np, addr);
  341. snprintf(name, MII_BUS_ID_SIZE, "%s@%llx", np->name,
  342. (unsigned long long)taddr);
  343. }
  344. /**
  345. * hns_mdio_probe - probe mdio device
  346. * @pdev: mdio platform device
  347. *
  348. * Return 0 on success, negative on failure
  349. */
  350. static int hns_mdio_probe(struct platform_device *pdev)
  351. {
  352. struct device_node *np;
  353. struct hns_mdio_device *mdio_dev;
  354. struct mii_bus *new_bus;
  355. struct resource *res;
  356. int ret;
  357. if (!pdev) {
  358. dev_err(NULL, "pdev is NULL!\r\n");
  359. return -ENODEV;
  360. }
  361. np = pdev->dev.of_node;
  362. mdio_dev = devm_kzalloc(&pdev->dev, sizeof(*mdio_dev), GFP_KERNEL);
  363. if (!mdio_dev)
  364. return -ENOMEM;
  365. new_bus = devm_mdiobus_alloc(&pdev->dev);
  366. if (!new_bus) {
  367. dev_err(&pdev->dev, "mdiobus_alloc fail!\n");
  368. return -ENOMEM;
  369. }
  370. new_bus->name = MDIO_BUS_NAME;
  371. new_bus->read = hns_mdio_read;
  372. new_bus->write = hns_mdio_write;
  373. new_bus->reset = hns_mdio_reset;
  374. new_bus->priv = mdio_dev;
  375. hns_mdio_bus_name(new_bus->id, np);
  376. res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  377. mdio_dev->vbase = devm_ioremap_resource(&pdev->dev, res);
  378. if (IS_ERR(mdio_dev->vbase)) {
  379. ret = PTR_ERR(mdio_dev->vbase);
  380. return ret;
  381. }
  382. mdio_dev->subctrl_vbase =
  383. syscon_node_to_regmap(of_parse_phandle(np, "subctrl_vbase", 0));
  384. if (IS_ERR(mdio_dev->subctrl_vbase)) {
  385. dev_warn(&pdev->dev, "no syscon hisilicon,peri-c-subctrl\n");
  386. mdio_dev->subctrl_vbase = NULL;
  387. }
  388. new_bus->irq = devm_kcalloc(&pdev->dev, PHY_MAX_ADDR,
  389. sizeof(int), GFP_KERNEL);
  390. if (!new_bus->irq)
  391. return -ENOMEM;
  392. new_bus->parent = &pdev->dev;
  393. platform_set_drvdata(pdev, new_bus);
  394. ret = of_mdiobus_register(new_bus, np);
  395. if (ret) {
  396. dev_err(&pdev->dev, "Cannot register as MDIO bus!\n");
  397. platform_set_drvdata(pdev, NULL);
  398. return ret;
  399. }
  400. return 0;
  401. }
  402. /**
  403. * hns_mdio_remove - remove mdio device
  404. * @pdev: mdio platform device
  405. *
  406. * Return 0 on success, negative on failure
  407. */
  408. static int hns_mdio_remove(struct platform_device *pdev)
  409. {
  410. struct mii_bus *bus;
  411. bus = platform_get_drvdata(pdev);
  412. mdiobus_unregister(bus);
  413. platform_set_drvdata(pdev, NULL);
  414. return 0;
  415. }
  416. static const struct of_device_id hns_mdio_match[] = {
  417. {.compatible = "hisilicon,mdio"},
  418. {.compatible = "hisilicon,hns-mdio"},
  419. {}
  420. };
  421. static struct platform_driver hns_mdio_driver = {
  422. .probe = hns_mdio_probe,
  423. .remove = hns_mdio_remove,
  424. .driver = {
  425. .name = MDIO_DRV_NAME,
  426. .of_match_table = hns_mdio_match,
  427. },
  428. };
  429. module_platform_driver(hns_mdio_driver);
  430. MODULE_LICENSE("GPL");
  431. MODULE_AUTHOR("Huawei Tech. Co., Ltd.");
  432. MODULE_DESCRIPTION("Hisilicon HNS MDIO driver");
  433. MODULE_ALIAS("platform:" MDIO_DRV_NAME);