764-07-v5.17-net-next-net-dsa-qca8k-initial-conversion-to-regmap-heper.patch 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  1. From 8b5f3f29a81a71934d004e21a1292c1148b05926 Mon Sep 17 00:00:00 2001
  2. From: Ansuel Smith <[email protected]>
  3. Date: Mon, 22 Nov 2021 16:23:44 +0100
  4. Subject: net: dsa: qca8k: initial conversion to regmap helper
  5. Convert any qca8k set/clear/pool to regmap helper and add
  6. missing config to regmap_config struct.
  7. Read/write/rmw operation are reworked to use the regmap helper
  8. internally to keep the delta of this patch low. These additional
  9. function will then be dropped when the code split will be proposed.
  10. Ipq40xx SoC have the internal switch based on the qca8k regmap but use
  11. mmio for read/write/rmw operation instead of mdio.
  12. In preparation for the support of this internal switch, convert the
  13. driver to regmap API to later split the driver to common and specific
  14. code. The overhead introduced by the use of regamp API is marginal as the
  15. internal mdio will bypass it by using its direct access and regmap will be
  16. used only by configuration functions or fdb access.
  17. Signed-off-by: Ansuel Smith <[email protected]>
  18. Signed-off-by: David S. Miller <[email protected]>
  19. ---
  20. drivers/net/dsa/qca8k.c | 107 +++++++++++++++++++++---------------------------
  21. 1 file changed, 47 insertions(+), 60 deletions(-)
  22. --- a/drivers/net/dsa/qca8k.c
  23. +++ b/drivers/net/dsa/qca8k.c
  24. @@ -10,6 +10,7 @@
  25. #include <linux/phy.h>
  26. #include <linux/netdevice.h>
  27. #include <linux/bitfield.h>
  28. +#include <linux/regmap.h>
  29. #include <net/dsa.h>
  30. #include <linux/of_net.h>
  31. #include <linux/of_mdio.h>
  32. @@ -152,6 +153,25 @@ qca8k_set_page(struct mii_bus *bus, u16
  33. static int
  34. qca8k_read(struct qca8k_priv *priv, u32 reg, u32 *val)
  35. {
  36. + return regmap_read(priv->regmap, reg, val);
  37. +}
  38. +
  39. +static int
  40. +qca8k_write(struct qca8k_priv *priv, u32 reg, u32 val)
  41. +{
  42. + return regmap_write(priv->regmap, reg, val);
  43. +}
  44. +
  45. +static int
  46. +qca8k_rmw(struct qca8k_priv *priv, u32 reg, u32 mask, u32 write_val)
  47. +{
  48. + return regmap_update_bits(priv->regmap, reg, mask, write_val);
  49. +}
  50. +
  51. +static int
  52. +qca8k_regmap_read(void *ctx, uint32_t reg, uint32_t *val)
  53. +{
  54. + struct qca8k_priv *priv = (struct qca8k_priv *)ctx;
  55. struct mii_bus *bus = priv->bus;
  56. u16 r1, r2, page;
  57. int ret;
  58. @@ -172,8 +192,9 @@ exit:
  59. }
  60. static int
  61. -qca8k_write(struct qca8k_priv *priv, u32 reg, u32 val)
  62. +qca8k_regmap_write(void *ctx, uint32_t reg, uint32_t val)
  63. {
  64. + struct qca8k_priv *priv = (struct qca8k_priv *)ctx;
  65. struct mii_bus *bus = priv->bus;
  66. u16 r1, r2, page;
  67. int ret;
  68. @@ -194,8 +215,9 @@ exit:
  69. }
  70. static int
  71. -qca8k_rmw(struct qca8k_priv *priv, u32 reg, u32 mask, u32 write_val)
  72. +qca8k_regmap_update_bits(void *ctx, uint32_t reg, uint32_t mask, uint32_t write_val)
  73. {
  74. + struct qca8k_priv *priv = (struct qca8k_priv *)ctx;
  75. struct mii_bus *bus = priv->bus;
  76. u16 r1, r2, page;
  77. u32 val;
  78. @@ -223,34 +245,6 @@ exit:
  79. return ret;
  80. }
  81. -static int
  82. -qca8k_reg_set(struct qca8k_priv *priv, u32 reg, u32 val)
  83. -{
  84. - return qca8k_rmw(priv, reg, 0, val);
  85. -}
  86. -
  87. -static int
  88. -qca8k_reg_clear(struct qca8k_priv *priv, u32 reg, u32 val)
  89. -{
  90. - return qca8k_rmw(priv, reg, val, 0);
  91. -}
  92. -
  93. -static int
  94. -qca8k_regmap_read(void *ctx, uint32_t reg, uint32_t *val)
  95. -{
  96. - struct qca8k_priv *priv = (struct qca8k_priv *)ctx;
  97. -
  98. - return qca8k_read(priv, reg, val);
  99. -}
  100. -
  101. -static int
  102. -qca8k_regmap_write(void *ctx, uint32_t reg, uint32_t val)
  103. -{
  104. - struct qca8k_priv *priv = (struct qca8k_priv *)ctx;
  105. -
  106. - return qca8k_write(priv, reg, val);
  107. -}
  108. -
  109. static const struct regmap_range qca8k_readable_ranges[] = {
  110. regmap_reg_range(0x0000, 0x00e4), /* Global control */
  111. regmap_reg_range(0x0100, 0x0168), /* EEE control */
  112. @@ -282,26 +276,19 @@ static struct regmap_config qca8k_regmap
  113. .max_register = 0x16ac, /* end MIB - Port6 range */
  114. .reg_read = qca8k_regmap_read,
  115. .reg_write = qca8k_regmap_write,
  116. + .reg_update_bits = qca8k_regmap_update_bits,
  117. .rd_table = &qca8k_readable_table,
  118. + .disable_locking = true, /* Locking is handled by qca8k read/write */
  119. + .cache_type = REGCACHE_NONE, /* Explicitly disable CACHE */
  120. };
  121. static int
  122. qca8k_busy_wait(struct qca8k_priv *priv, u32 reg, u32 mask)
  123. {
  124. - int ret, ret1;
  125. u32 val;
  126. - ret = read_poll_timeout(qca8k_read, ret1, !(val & mask),
  127. - 0, QCA8K_BUSY_WAIT_TIMEOUT * USEC_PER_MSEC, false,
  128. - priv, reg, &val);
  129. -
  130. - /* Check if qca8k_read has failed for a different reason
  131. - * before returning -ETIMEDOUT
  132. - */
  133. - if (ret < 0 && ret1 < 0)
  134. - return ret1;
  135. -
  136. - return ret;
  137. + return regmap_read_poll_timeout(priv->regmap, reg, val, !(val & mask), 0,
  138. + QCA8K_BUSY_WAIT_TIMEOUT * USEC_PER_MSEC);
  139. }
  140. static int
  141. @@ -568,7 +555,7 @@ qca8k_mib_init(struct qca8k_priv *priv)
  142. int ret;
  143. mutex_lock(&priv->reg_mutex);
  144. - ret = qca8k_reg_set(priv, QCA8K_REG_MIB, QCA8K_MIB_FLUSH | QCA8K_MIB_BUSY);
  145. + ret = regmap_set_bits(priv->regmap, QCA8K_REG_MIB, QCA8K_MIB_FLUSH | QCA8K_MIB_BUSY);
  146. if (ret)
  147. goto exit;
  148. @@ -576,7 +563,7 @@ qca8k_mib_init(struct qca8k_priv *priv)
  149. if (ret)
  150. goto exit;
  151. - ret = qca8k_reg_set(priv, QCA8K_REG_MIB, QCA8K_MIB_CPU_KEEP);
  152. + ret = regmap_set_bits(priv->regmap, QCA8K_REG_MIB, QCA8K_MIB_CPU_KEEP);
  153. if (ret)
  154. goto exit;
  155. @@ -597,9 +584,9 @@ qca8k_port_set_status(struct qca8k_priv
  156. mask |= QCA8K_PORT_STATUS_LINK_AUTO;
  157. if (enable)
  158. - qca8k_reg_set(priv, QCA8K_REG_PORT_STATUS(port), mask);
  159. + regmap_set_bits(priv->regmap, QCA8K_REG_PORT_STATUS(port), mask);
  160. else
  161. - qca8k_reg_clear(priv, QCA8K_REG_PORT_STATUS(port), mask);
  162. + regmap_clear_bits(priv->regmap, QCA8K_REG_PORT_STATUS(port), mask);
  163. }
  164. static u32
  165. @@ -861,8 +848,8 @@ qca8k_setup_mdio_bus(struct qca8k_priv *
  166. * a dt-overlay and driver reload changed the configuration
  167. */
  168. - return qca8k_reg_clear(priv, QCA8K_MDIO_MASTER_CTRL,
  169. - QCA8K_MDIO_MASTER_EN);
  170. + return regmap_clear_bits(priv->regmap, QCA8K_MDIO_MASTER_CTRL,
  171. + QCA8K_MDIO_MASTER_EN);
  172. }
  173. /* Check if the devicetree declare the port:phy mapping */
  174. @@ -1099,16 +1086,16 @@ qca8k_setup(struct dsa_switch *ds)
  175. return ret;
  176. /* Make sure MAC06 is disabled */
  177. - ret = qca8k_reg_clear(priv, QCA8K_REG_PORT0_PAD_CTRL,
  178. - QCA8K_PORT0_PAD_MAC06_EXCHANGE_EN);
  179. + ret = regmap_clear_bits(priv->regmap, QCA8K_REG_PORT0_PAD_CTRL,
  180. + QCA8K_PORT0_PAD_MAC06_EXCHANGE_EN);
  181. if (ret) {
  182. dev_err(priv->dev, "failed disabling MAC06 exchange");
  183. return ret;
  184. }
  185. /* Enable CPU Port */
  186. - ret = qca8k_reg_set(priv, QCA8K_REG_GLOBAL_FW_CTRL0,
  187. - QCA8K_GLOBAL_FW_CTRL0_CPU_PORT_EN);
  188. + ret = regmap_set_bits(priv->regmap, QCA8K_REG_GLOBAL_FW_CTRL0,
  189. + QCA8K_GLOBAL_FW_CTRL0_CPU_PORT_EN);
  190. if (ret) {
  191. dev_err(priv->dev, "failed enabling CPU port");
  192. return ret;
  193. @@ -1176,8 +1163,8 @@ qca8k_setup(struct dsa_switch *ds)
  194. return ret;
  195. /* Enable ARP Auto-learning by default */
  196. - ret = qca8k_reg_set(priv, QCA8K_PORT_LOOKUP_CTRL(i),
  197. - QCA8K_PORT_LOOKUP_LEARN);
  198. + ret = regmap_set_bits(priv->regmap, QCA8K_PORT_LOOKUP_CTRL(i),
  199. + QCA8K_PORT_LOOKUP_LEARN);
  200. if (ret)
  201. return ret;
  202. @@ -1745,9 +1732,9 @@ qca8k_port_bridge_join(struct dsa_switch
  203. /* Add this port to the portvlan mask of the other ports
  204. * in the bridge
  205. */
  206. - ret = qca8k_reg_set(priv,
  207. - QCA8K_PORT_LOOKUP_CTRL(i),
  208. - BIT(port));
  209. + ret = regmap_set_bits(priv->regmap,
  210. + QCA8K_PORT_LOOKUP_CTRL(i),
  211. + BIT(port));
  212. if (ret)
  213. return ret;
  214. if (i != port)
  215. @@ -1777,9 +1764,9 @@ qca8k_port_bridge_leave(struct dsa_switc
  216. /* Remove this port to the portvlan mask of the other ports
  217. * in the bridge
  218. */
  219. - qca8k_reg_clear(priv,
  220. - QCA8K_PORT_LOOKUP_CTRL(i),
  221. - BIT(port));
  222. + regmap_clear_bits(priv->regmap,
  223. + QCA8K_PORT_LOOKUP_CTRL(i),
  224. + BIT(port));
  225. }
  226. /* Set the cpu port to be the only one in the portvlan mask of