1
0

0001-net-macb-improve-big-endian-CPU-support.patch 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282
  1. From f2ce8a9e48385f444389e75cfe293637c3eb5410 Mon Sep 17 00:00:00 2001
  2. From: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
  3. Date: Fri, 24 Jul 2015 21:23:59 +0300
  4. Subject: [PATCH] net/macb: improve big endian CPU support
  5. The commit a50dad355a53 (net: macb: Add big endian CPU support) converted I/O
  6. accessors to readl_relaxed() and writel_relaxed() and consequentially broke
  7. MACB driver on AVR32 platforms such as ATNGW100.
  8. This patch improves I/O access by checking endiannes first and use the
  9. corresponding methods.
  10. Fixes: a50dad355a53 (net: macb: Add big endian CPU support)
  11. Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
  12. Signed-off-by: David S. Miller <davem@davemloft.net>
  13. Signed-off-by: Waldemar Brodkorb <wbx@openadk.org>
  14. ---
  15. drivers/net/ethernet/cadence/macb.c | 103 ++++++++++++++++++++++++++---------
  16. drivers/net/ethernet/cadence/macb.h | 28 ++++------
  17. 2 files changed, 87 insertions(+), 44 deletions(-)
  18. diff --git a/drivers/net/ethernet/cadence/macb.c b/drivers/net/ethernet/cadence/macb.c
  19. index caeb395..9d06e3d 100644
  20. --- a/drivers/net/ethernet/cadence/macb.c
  21. +++ b/drivers/net/ethernet/cadence/macb.c
  22. @@ -104,6 +104,57 @@ static void *macb_rx_buffer(struct macb *bp, unsigned int index)
  23. return bp->rx_buffers + bp->rx_buffer_size * macb_rx_ring_wrap(index);
  24. }
  25. +/* I/O accessors */
  26. +static u32 hw_readl_native(struct macb *bp, int offset)
  27. +{
  28. + return __raw_readl(bp->regs + offset);
  29. +}
  30. +
  31. +static void hw_writel_native(struct macb *bp, int offset, u32 value)
  32. +{
  33. + __raw_writel(value, bp->regs + offset);
  34. +}
  35. +
  36. +static u32 hw_readl(struct macb *bp, int offset)
  37. +{
  38. + return readl_relaxed(bp->regs + offset);
  39. +}
  40. +
  41. +static void hw_writel(struct macb *bp, int offset, u32 value)
  42. +{
  43. + writel_relaxed(value, bp->regs + offset);
  44. +}
  45. +
  46. +/*
  47. + * Find the CPU endianness by using the loopback bit of NCR register. When the
  48. + * CPU is in big endian we need to program swaped mode for management
  49. + * descriptor access.
  50. + */
  51. +static bool hw_is_native_io(void __iomem *addr)
  52. +{
  53. + u32 value = MACB_BIT(LLB);
  54. +
  55. + __raw_writel(value, addr + MACB_NCR);
  56. + value = __raw_readl(addr + MACB_NCR);
  57. +
  58. + /* Write 0 back to disable everything */
  59. + __raw_writel(0, addr + MACB_NCR);
  60. +
  61. + return value == MACB_BIT(LLB);
  62. +}
  63. +
  64. +static bool hw_is_gem(void __iomem *addr, bool native_io)
  65. +{
  66. + u32 id;
  67. +
  68. + if (native_io)
  69. + id = __raw_readl(addr + MACB_MID);
  70. + else
  71. + id = readl_relaxed(addr + MACB_MID);
  72. +
  73. + return MACB_BFEXT(IDNUM, id) >= 0x2;
  74. +}
  75. +
  76. static void macb_set_hwaddr(struct macb *bp)
  77. {
  78. u32 bottom;
  79. @@ -449,14 +500,14 @@ err_out:
  80. static void macb_update_stats(struct macb *bp)
  81. {
  82. - u32 __iomem *reg = bp->regs + MACB_PFR;
  83. u32 *p = &bp->hw_stats.macb.rx_pause_frames;
  84. u32 *end = &bp->hw_stats.macb.tx_pause_frames + 1;
  85. + int offset = MACB_PFR;
  86. WARN_ON((unsigned long)(end - p - 1) != (MACB_TPF - MACB_PFR) / 4);
  87. - for(; p < end; p++, reg++)
  88. - *p += readl_relaxed(reg);
  89. + for(; p < end; p++, offset += 4)
  90. + *p += bp->readl(bp, offset);
  91. }
  92. static int macb_halt_tx(struct macb *bp)
  93. @@ -1603,7 +1654,6 @@ static u32 macb_dbw(struct macb *bp)
  94. static void macb_configure_dma(struct macb *bp)
  95. {
  96. u32 dmacfg;
  97. - u32 tmp, ncr;
  98. if (macb_is_gem(bp)) {
  99. dmacfg = gem_readl(bp, DMACFG) & ~GEM_BF(RXBS, -1L);
  100. @@ -1613,22 +1663,11 @@ static void macb_configure_dma(struct macb *bp)
  101. dmacfg |= GEM_BIT(TXPBMS) | GEM_BF(RXBMS, -1L);
  102. dmacfg &= ~GEM_BIT(ENDIA_PKT);
  103. - /* Find the CPU endianness by using the loopback bit of net_ctrl
  104. - * register. save it first. When the CPU is in big endian we
  105. - * need to program swaped mode for management descriptor access.
  106. - */
  107. - ncr = macb_readl(bp, NCR);
  108. - __raw_writel(MACB_BIT(LLB), bp->regs + MACB_NCR);
  109. - tmp = __raw_readl(bp->regs + MACB_NCR);
  110. -
  111. - if (tmp == MACB_BIT(LLB))
  112. + if (bp->native_io)
  113. dmacfg &= ~GEM_BIT(ENDIA_DESC);
  114. else
  115. dmacfg |= GEM_BIT(ENDIA_DESC); /* CPU in big endian */
  116. - /* Restore net_ctrl */
  117. - macb_writel(bp, NCR, ncr);
  118. -
  119. if (bp->dev->features & NETIF_F_HW_CSUM)
  120. dmacfg |= GEM_BIT(TXCOEN);
  121. else
  122. @@ -1902,14 +1941,14 @@ static void gem_update_stats(struct macb *bp)
  123. for (i = 0; i < GEM_STATS_LEN; ++i, ++p) {
  124. u32 offset = gem_statistics[i].offset;
  125. - u64 val = readl_relaxed(bp->regs + offset);
  126. + u64 val = bp->readl(bp, offset);
  127. bp->ethtool_stats[i] += val;
  128. *p += val;
  129. if (offset == GEM_OCTTXL || offset == GEM_OCTRXL) {
  130. /* Add GEM_OCTTXH, GEM_OCTRXH */
  131. - val = readl_relaxed(bp->regs + offset + 4);
  132. + val = bp->readl(bp, offset + 4);
  133. bp->ethtool_stats[i] += ((u64)val) << 32;
  134. *(++p) += val;
  135. }
  136. @@ -2190,7 +2229,7 @@ static void macb_configure_caps(struct macb *bp, const struct macb_config *dt_co
  137. if (dt_conf)
  138. bp->caps = dt_conf->caps;
  139. - if (macb_is_gem_hw(bp->regs)) {
  140. + if (hw_is_gem(bp->regs, bp->native_io)) {
  141. bp->caps |= MACB_CAPS_MACB_IS_GEM;
  142. dcfg = gem_readl(bp, DCFG1);
  143. @@ -2205,6 +2244,7 @@ static void macb_configure_caps(struct macb *bp, const struct macb_config *dt_co
  144. }
  145. static void macb_probe_queues(void __iomem *mem,
  146. + bool native_io,
  147. unsigned int *queue_mask,
  148. unsigned int *num_queues)
  149. {
  150. @@ -2219,7 +2259,7 @@ static void macb_probe_queues(void __iomem *mem,
  151. * we are early in the probe process and don't have the
  152. * MACB_CAPS_MACB_IS_GEM flag positioned
  153. */
  154. - if (!macb_is_gem_hw(mem))
  155. + if (!hw_is_gem(mem, native_io))
  156. return;
  157. /* bit 0 is never set but queue 0 always exists */
  158. @@ -2786,6 +2826,7 @@ static int macb_probe(struct platform_device *pdev)
  159. struct clk *pclk, *hclk, *tx_clk;
  160. unsigned int queue_mask, num_queues;
  161. struct macb_platform_data *pdata;
  162. + bool native_io;
  163. struct phy_device *phydev;
  164. struct net_device *dev;
  165. struct resource *regs;
  166. @@ -2794,6 +2835,11 @@ static int macb_probe(struct platform_device *pdev)
  167. struct macb *bp;
  168. int err;
  169. + regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  170. + mem = devm_ioremap_resource(&pdev->dev, regs);
  171. + if (IS_ERR(mem))
  172. + return PTR_ERR(mem);
  173. +
  174. if (np) {
  175. const struct of_device_id *match;
  176. @@ -2809,14 +2855,9 @@ static int macb_probe(struct platform_device *pdev)
  177. if (err)
  178. return err;
  179. - regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  180. - mem = devm_ioremap_resource(&pdev->dev, regs);
  181. - if (IS_ERR(mem)) {
  182. - err = PTR_ERR(mem);
  183. - goto err_disable_clocks;
  184. - }
  185. + native_io = hw_is_native_io(mem);
  186. - macb_probe_queues(mem, &queue_mask, &num_queues);
  187. + macb_probe_queues(mem, native_io, &queue_mask, &num_queues);
  188. dev = alloc_etherdev_mq(sizeof(*bp), num_queues);
  189. if (!dev) {
  190. err = -ENOMEM;
  191. @@ -2831,6 +2872,14 @@ static int macb_probe(struct platform_device *pdev)
  192. bp->pdev = pdev;
  193. bp->dev = dev;
  194. bp->regs = mem;
  195. + bp->native_io = native_io;
  196. + if (native_io) {
  197. + bp->readl = hw_readl_native;
  198. + bp->writel = hw_writel_native;
  199. + } else {
  200. + bp->readl = hw_readl;
  201. + bp->writel = hw_writel;
  202. + }
  203. bp->num_queues = num_queues;
  204. bp->queue_mask = queue_mask;
  205. if (macb_config)
  206. diff --git a/drivers/net/ethernet/cadence/macb.h b/drivers/net/ethernet/cadence/macb.h
  207. index d746559..f245340 100644
  208. --- a/drivers/net/ethernet/cadence/macb.h
  209. +++ b/drivers/net/ethernet/cadence/macb.h
  210. @@ -429,18 +429,12 @@
  211. | GEM_BF(name, value))
  212. /* Register access macros */
  213. -#define macb_readl(port,reg) \
  214. - readl_relaxed((port)->regs + MACB_##reg)
  215. -#define macb_writel(port,reg,value) \
  216. - writel_relaxed((value), (port)->regs + MACB_##reg)
  217. -#define gem_readl(port, reg) \
  218. - readl_relaxed((port)->regs + GEM_##reg)
  219. -#define gem_writel(port, reg, value) \
  220. - writel_relaxed((value), (port)->regs + GEM_##reg)
  221. -#define queue_readl(queue, reg) \
  222. - readl_relaxed((queue)->bp->regs + (queue)->reg)
  223. -#define queue_writel(queue, reg, value) \
  224. - writel_relaxed((value), (queue)->bp->regs + (queue)->reg)
  225. +#define macb_readl(port, reg) (port)->readl((port), MACB_##reg)
  226. +#define macb_writel(port, reg, value) (port)->writel((port), MACB_##reg, (value))
  227. +#define gem_readl(port, reg) (port)->readl((port), GEM_##reg)
  228. +#define gem_writel(port, reg, value) (port)->writel((port), GEM_##reg, (value))
  229. +#define queue_readl(queue, reg) (queue)->bp->readl((queue)->bp, (queue)->reg)
  230. +#define queue_writel(queue, reg, value) (queue)->bp->writel((queue)->bp, (queue)->reg, (value))
  231. /* Conditional GEM/MACB macros. These perform the operation to the correct
  232. * register dependent on whether the device is a GEM or a MACB. For registers
  233. @@ -785,6 +779,11 @@ struct macb_queue {
  234. struct macb {
  235. void __iomem *regs;
  236. + bool native_io;
  237. +
  238. + /* hardware IO accessors */
  239. + u32 (*readl)(struct macb *bp, int offset);
  240. + void (*writel)(struct macb *bp, int offset, u32 value);
  241. unsigned int rx_tail;
  242. unsigned int rx_prepared_head;
  243. @@ -843,9 +842,4 @@ static inline bool macb_is_gem(struct macb *bp)
  244. return !!(bp->caps & MACB_CAPS_MACB_IS_GEM);
  245. }
  246. -static inline bool macb_is_gem_hw(void __iomem *addr)
  247. -{
  248. - return !!(MACB_BFEXT(IDNUM, readl_relaxed(addr + MACB_MID)) >= 0x2);
  249. -}
  250. -
  251. #endif /* _MACB_H */
  252. --
  253. 1.7.10.4