ksz8863_smi.c 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Microchip KSZ8863 series register access through SMI
  4. *
  5. * Copyright (C) 2019 Pengutronix, Michael Grzeschik <[email protected]>
  6. */
  7. #include "ksz8.h"
  8. #include "ksz_common.h"
  9. /* Serial Management Interface (SMI) uses the following frame format:
  10. *
  11. * preamble|start|Read/Write| PHY | REG |TA| Data bits | Idle
  12. * |frame| OP code |address |address| | |
  13. * read | 32x1´s | 01 | 00 | 1xRRR | RRRRR |Z0| 00000000DDDDDDDD | Z
  14. * write| 32x1´s | 01 | 00 | 0xRRR | RRRRR |10| xxxxxxxxDDDDDDDD | Z
  15. *
  16. */
  17. #define SMI_KSZ88XX_READ_PHY BIT(4)
  18. static int ksz8863_mdio_read(void *ctx, const void *reg_buf, size_t reg_len,
  19. void *val_buf, size_t val_len)
  20. {
  21. struct ksz_device *dev = ctx;
  22. struct mdio_device *mdev;
  23. u8 reg = *(u8 *)reg_buf;
  24. u8 *val = val_buf;
  25. int i, ret = 0;
  26. mdev = dev->priv;
  27. mutex_lock_nested(&mdev->bus->mdio_lock, MDIO_MUTEX_NESTED);
  28. for (i = 0; i < val_len; i++) {
  29. int tmp = reg + i;
  30. ret = __mdiobus_read(mdev->bus, ((tmp & 0xE0) >> 5) |
  31. SMI_KSZ88XX_READ_PHY, tmp);
  32. if (ret < 0)
  33. goto out;
  34. val[i] = ret;
  35. }
  36. ret = 0;
  37. out:
  38. mutex_unlock(&mdev->bus->mdio_lock);
  39. return ret;
  40. }
  41. static int ksz8863_mdio_write(void *ctx, const void *data, size_t count)
  42. {
  43. struct ksz_device *dev = ctx;
  44. struct mdio_device *mdev;
  45. int i, ret = 0;
  46. u32 reg;
  47. u8 *val;
  48. mdev = dev->priv;
  49. val = (u8 *)(data + 4);
  50. reg = *(u32 *)data;
  51. mutex_lock_nested(&mdev->bus->mdio_lock, MDIO_MUTEX_NESTED);
  52. for (i = 0; i < (count - 4); i++) {
  53. int tmp = reg + i;
  54. ret = __mdiobus_write(mdev->bus, ((tmp & 0xE0) >> 5),
  55. tmp, val[i]);
  56. if (ret < 0)
  57. goto out;
  58. }
  59. out:
  60. mutex_unlock(&mdev->bus->mdio_lock);
  61. return ret;
  62. }
  63. static const struct regmap_bus regmap_smi[] = {
  64. {
  65. .read = ksz8863_mdio_read,
  66. .write = ksz8863_mdio_write,
  67. },
  68. {
  69. .read = ksz8863_mdio_read,
  70. .write = ksz8863_mdio_write,
  71. .val_format_endian_default = REGMAP_ENDIAN_BIG,
  72. },
  73. {
  74. .read = ksz8863_mdio_read,
  75. .write = ksz8863_mdio_write,
  76. .val_format_endian_default = REGMAP_ENDIAN_BIG,
  77. }
  78. };
  79. static const struct regmap_config ksz8863_regmap_config[] = {
  80. {
  81. .name = "#8",
  82. .reg_bits = 8,
  83. .pad_bits = 24,
  84. .val_bits = 8,
  85. .cache_type = REGCACHE_NONE,
  86. .lock = ksz_regmap_lock,
  87. .unlock = ksz_regmap_unlock,
  88. },
  89. {
  90. .name = "#16",
  91. .reg_bits = 8,
  92. .pad_bits = 24,
  93. .val_bits = 16,
  94. .cache_type = REGCACHE_NONE,
  95. .lock = ksz_regmap_lock,
  96. .unlock = ksz_regmap_unlock,
  97. },
  98. {
  99. .name = "#32",
  100. .reg_bits = 8,
  101. .pad_bits = 24,
  102. .val_bits = 32,
  103. .cache_type = REGCACHE_NONE,
  104. .lock = ksz_regmap_lock,
  105. .unlock = ksz_regmap_unlock,
  106. }
  107. };
  108. static int ksz8863_smi_probe(struct mdio_device *mdiodev)
  109. {
  110. struct regmap_config rc;
  111. struct ksz_device *dev;
  112. int ret;
  113. int i;
  114. dev = ksz_switch_alloc(&mdiodev->dev, mdiodev);
  115. if (!dev)
  116. return -ENOMEM;
  117. for (i = 0; i < ARRAY_SIZE(ksz8863_regmap_config); i++) {
  118. rc = ksz8863_regmap_config[i];
  119. rc.lock_arg = &dev->regmap_mutex;
  120. dev->regmap[i] = devm_regmap_init(&mdiodev->dev,
  121. &regmap_smi[i], dev,
  122. &rc);
  123. if (IS_ERR(dev->regmap[i])) {
  124. ret = PTR_ERR(dev->regmap[i]);
  125. dev_err(&mdiodev->dev,
  126. "Failed to initialize regmap%i: %d\n",
  127. ksz8863_regmap_config[i].val_bits, ret);
  128. return ret;
  129. }
  130. }
  131. if (mdiodev->dev.platform_data)
  132. dev->pdata = mdiodev->dev.platform_data;
  133. ret = ksz_switch_register(dev);
  134. /* Main DSA driver may not be started yet. */
  135. if (ret)
  136. return ret;
  137. dev_set_drvdata(&mdiodev->dev, dev);
  138. return 0;
  139. }
  140. static void ksz8863_smi_remove(struct mdio_device *mdiodev)
  141. {
  142. struct ksz_device *dev = dev_get_drvdata(&mdiodev->dev);
  143. if (dev)
  144. ksz_switch_remove(dev);
  145. }
  146. static void ksz8863_smi_shutdown(struct mdio_device *mdiodev)
  147. {
  148. struct ksz_device *dev = dev_get_drvdata(&mdiodev->dev);
  149. if (dev)
  150. dsa_switch_shutdown(dev->ds);
  151. dev_set_drvdata(&mdiodev->dev, NULL);
  152. }
  153. static const struct of_device_id ksz8863_dt_ids[] = {
  154. {
  155. .compatible = "microchip,ksz8863",
  156. .data = &ksz_switch_chips[KSZ8830]
  157. },
  158. {
  159. .compatible = "microchip,ksz8873",
  160. .data = &ksz_switch_chips[KSZ8830]
  161. },
  162. { },
  163. };
  164. MODULE_DEVICE_TABLE(of, ksz8863_dt_ids);
  165. static struct mdio_driver ksz8863_driver = {
  166. .probe = ksz8863_smi_probe,
  167. .remove = ksz8863_smi_remove,
  168. .shutdown = ksz8863_smi_shutdown,
  169. .mdiodrv.driver = {
  170. .name = "ksz8863-switch",
  171. .of_match_table = ksz8863_dt_ids,
  172. },
  173. };
  174. mdio_module_driver(ksz8863_driver);
  175. MODULE_AUTHOR("Michael Grzeschik <[email protected]>");
  176. MODULE_DESCRIPTION("Microchip KSZ8863 SMI Switch driver");
  177. MODULE_LICENSE("GPL v2");