dev-enet.c 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327
  1. /*
  2. * This file is subject to the terms and conditions of the GNU General Public
  3. * License. See the file "COPYING" in the main directory of this archive
  4. * for more details.
  5. *
  6. * Copyright (C) 2008 Maxime Bizon <[email protected]>
  7. */
  8. #include <linux/init.h>
  9. #include <linux/kernel.h>
  10. #include <linux/platform_device.h>
  11. #include <linux/export.h>
  12. #include <bcm63xx_dev_enet.h>
  13. #include <bcm63xx_io.h>
  14. #include <bcm63xx_regs.h>
  15. static const unsigned long bcm6348_regs_enetdmac[] = {
  16. [ENETDMAC_CHANCFG] = ENETDMAC_CHANCFG_REG,
  17. [ENETDMAC_IR] = ENETDMAC_IR_REG,
  18. [ENETDMAC_IRMASK] = ENETDMAC_IRMASK_REG,
  19. [ENETDMAC_MAXBURST] = ENETDMAC_MAXBURST_REG,
  20. };
  21. static const unsigned long bcm6345_regs_enetdmac[] = {
  22. [ENETDMAC_CHANCFG] = ENETDMA_6345_CHANCFG_REG,
  23. [ENETDMAC_IR] = ENETDMA_6345_IR_REG,
  24. [ENETDMAC_IRMASK] = ENETDMA_6345_IRMASK_REG,
  25. [ENETDMAC_MAXBURST] = ENETDMA_6345_MAXBURST_REG,
  26. [ENETDMAC_BUFALLOC] = ENETDMA_6345_BUFALLOC_REG,
  27. [ENETDMAC_RSTART] = ENETDMA_6345_RSTART_REG,
  28. [ENETDMAC_FC] = ENETDMA_6345_FC_REG,
  29. [ENETDMAC_LEN] = ENETDMA_6345_LEN_REG,
  30. };
  31. const unsigned long *bcm63xx_regs_enetdmac;
  32. EXPORT_SYMBOL(bcm63xx_regs_enetdmac);
  33. static __init void bcm63xx_enetdmac_regs_init(void)
  34. {
  35. if (BCMCPU_IS_6345())
  36. bcm63xx_regs_enetdmac = bcm6345_regs_enetdmac;
  37. else
  38. bcm63xx_regs_enetdmac = bcm6348_regs_enetdmac;
  39. }
  40. static struct resource shared_res[] = {
  41. {
  42. .start = -1, /* filled at runtime */
  43. .end = -1, /* filled at runtime */
  44. .flags = IORESOURCE_MEM,
  45. },
  46. {
  47. .start = -1, /* filled at runtime */
  48. .end = -1, /* filled at runtime */
  49. .flags = IORESOURCE_MEM,
  50. },
  51. {
  52. .start = -1, /* filled at runtime */
  53. .end = -1, /* filled at runtime */
  54. .flags = IORESOURCE_MEM,
  55. },
  56. };
  57. static struct platform_device bcm63xx_enet_shared_device = {
  58. .name = "bcm63xx_enet_shared",
  59. .id = 0,
  60. .num_resources = ARRAY_SIZE(shared_res),
  61. .resource = shared_res,
  62. };
  63. static int shared_device_registered;
  64. static u64 enet_dmamask = DMA_BIT_MASK(32);
  65. static struct resource enet0_res[] = {
  66. {
  67. .start = -1, /* filled at runtime */
  68. .end = -1, /* filled at runtime */
  69. .flags = IORESOURCE_MEM,
  70. },
  71. {
  72. .start = -1, /* filled at runtime */
  73. .flags = IORESOURCE_IRQ,
  74. },
  75. {
  76. .start = -1, /* filled at runtime */
  77. .flags = IORESOURCE_IRQ,
  78. },
  79. {
  80. .start = -1, /* filled at runtime */
  81. .flags = IORESOURCE_IRQ,
  82. },
  83. };
  84. static struct bcm63xx_enet_platform_data enet0_pd;
  85. static struct platform_device bcm63xx_enet0_device = {
  86. .name = "bcm63xx_enet",
  87. .id = 0,
  88. .num_resources = ARRAY_SIZE(enet0_res),
  89. .resource = enet0_res,
  90. .dev = {
  91. .platform_data = &enet0_pd,
  92. .dma_mask = &enet_dmamask,
  93. .coherent_dma_mask = DMA_BIT_MASK(32),
  94. },
  95. };
  96. static struct resource enet1_res[] = {
  97. {
  98. .start = -1, /* filled at runtime */
  99. .end = -1, /* filled at runtime */
  100. .flags = IORESOURCE_MEM,
  101. },
  102. {
  103. .start = -1, /* filled at runtime */
  104. .flags = IORESOURCE_IRQ,
  105. },
  106. {
  107. .start = -1, /* filled at runtime */
  108. .flags = IORESOURCE_IRQ,
  109. },
  110. {
  111. .start = -1, /* filled at runtime */
  112. .flags = IORESOURCE_IRQ,
  113. },
  114. };
  115. static struct bcm63xx_enet_platform_data enet1_pd;
  116. static struct platform_device bcm63xx_enet1_device = {
  117. .name = "bcm63xx_enet",
  118. .id = 1,
  119. .num_resources = ARRAY_SIZE(enet1_res),
  120. .resource = enet1_res,
  121. .dev = {
  122. .platform_data = &enet1_pd,
  123. .dma_mask = &enet_dmamask,
  124. .coherent_dma_mask = DMA_BIT_MASK(32),
  125. },
  126. };
  127. static struct resource enetsw_res[] = {
  128. {
  129. /* start & end filled at runtime */
  130. .flags = IORESOURCE_MEM,
  131. },
  132. {
  133. /* start filled at runtime */
  134. .flags = IORESOURCE_IRQ,
  135. },
  136. {
  137. /* start filled at runtime */
  138. .flags = IORESOURCE_IRQ,
  139. },
  140. };
  141. static struct bcm63xx_enetsw_platform_data enetsw_pd;
  142. static struct platform_device bcm63xx_enetsw_device = {
  143. .name = "bcm63xx_enetsw",
  144. .num_resources = ARRAY_SIZE(enetsw_res),
  145. .resource = enetsw_res,
  146. .dev = {
  147. .platform_data = &enetsw_pd,
  148. .dma_mask = &enet_dmamask,
  149. .coherent_dma_mask = DMA_BIT_MASK(32),
  150. },
  151. };
  152. static int __init register_shared(void)
  153. {
  154. int ret, chan_count;
  155. if (shared_device_registered)
  156. return 0;
  157. bcm63xx_enetdmac_regs_init();
  158. shared_res[0].start = bcm63xx_regset_address(RSET_ENETDMA);
  159. shared_res[0].end = shared_res[0].start;
  160. if (BCMCPU_IS_6345())
  161. shared_res[0].end += (RSET_6345_ENETDMA_SIZE) - 1;
  162. else
  163. shared_res[0].end += (RSET_ENETDMA_SIZE) - 1;
  164. if (BCMCPU_IS_6328() || BCMCPU_IS_6362() || BCMCPU_IS_6368())
  165. chan_count = 32;
  166. else if (BCMCPU_IS_6345())
  167. chan_count = 8;
  168. else
  169. chan_count = 16;
  170. shared_res[1].start = bcm63xx_regset_address(RSET_ENETDMAC);
  171. shared_res[1].end = shared_res[1].start;
  172. shared_res[1].end += RSET_ENETDMAC_SIZE(chan_count) - 1;
  173. shared_res[2].start = bcm63xx_regset_address(RSET_ENETDMAS);
  174. shared_res[2].end = shared_res[2].start;
  175. shared_res[2].end += RSET_ENETDMAS_SIZE(chan_count) - 1;
  176. ret = platform_device_register(&bcm63xx_enet_shared_device);
  177. if (ret)
  178. return ret;
  179. shared_device_registered = 1;
  180. return 0;
  181. }
  182. int __init bcm63xx_enet_register(int unit,
  183. const struct bcm63xx_enet_platform_data *pd)
  184. {
  185. struct platform_device *pdev;
  186. struct bcm63xx_enet_platform_data *dpd;
  187. int ret;
  188. if (unit > 1)
  189. return -ENODEV;
  190. if (unit == 1 && (BCMCPU_IS_6338() || BCMCPU_IS_6345()))
  191. return -ENODEV;
  192. ret = register_shared();
  193. if (ret)
  194. return ret;
  195. if (unit == 0) {
  196. enet0_res[0].start = bcm63xx_regset_address(RSET_ENET0);
  197. enet0_res[0].end = enet0_res[0].start;
  198. enet0_res[0].end += RSET_ENET_SIZE - 1;
  199. enet0_res[1].start = bcm63xx_get_irq_number(IRQ_ENET0);
  200. enet0_res[2].start = bcm63xx_get_irq_number(IRQ_ENET0_RXDMA);
  201. enet0_res[3].start = bcm63xx_get_irq_number(IRQ_ENET0_TXDMA);
  202. pdev = &bcm63xx_enet0_device;
  203. } else {
  204. enet1_res[0].start = bcm63xx_regset_address(RSET_ENET1);
  205. enet1_res[0].end = enet1_res[0].start;
  206. enet1_res[0].end += RSET_ENET_SIZE - 1;
  207. enet1_res[1].start = bcm63xx_get_irq_number(IRQ_ENET1);
  208. enet1_res[2].start = bcm63xx_get_irq_number(IRQ_ENET1_RXDMA);
  209. enet1_res[3].start = bcm63xx_get_irq_number(IRQ_ENET1_TXDMA);
  210. pdev = &bcm63xx_enet1_device;
  211. }
  212. /* copy given platform data */
  213. dpd = pdev->dev.platform_data;
  214. memcpy(dpd, pd, sizeof(*pd));
  215. /* adjust them in case internal phy is used */
  216. if (dpd->use_internal_phy) {
  217. /* internal phy only exists for enet0 */
  218. if (unit == 1)
  219. return -ENODEV;
  220. dpd->phy_id = 1;
  221. dpd->has_phy_interrupt = 1;
  222. dpd->phy_interrupt = bcm63xx_get_irq_number(IRQ_ENET_PHY);
  223. }
  224. dpd->dma_chan_en_mask = ENETDMAC_CHANCFG_EN_MASK;
  225. dpd->dma_chan_int_mask = ENETDMAC_IR_PKTDONE_MASK;
  226. if (BCMCPU_IS_6345()) {
  227. dpd->dma_chan_en_mask |= ENETDMAC_CHANCFG_CHAINING_MASK;
  228. dpd->dma_chan_en_mask |= ENETDMAC_CHANCFG_WRAP_EN_MASK;
  229. dpd->dma_chan_en_mask |= ENETDMAC_CHANCFG_FLOWC_EN_MASK;
  230. dpd->dma_chan_int_mask |= ENETDMA_IR_BUFDONE_MASK;
  231. dpd->dma_chan_int_mask |= ENETDMA_IR_NOTOWNER_MASK;
  232. dpd->dma_chan_width = ENETDMA_6345_CHAN_WIDTH;
  233. dpd->dma_desc_shift = ENETDMA_6345_DESC_SHIFT;
  234. } else {
  235. dpd->dma_has_sram = true;
  236. dpd->dma_chan_width = ENETDMA_CHAN_WIDTH;
  237. }
  238. if (unit == 0) {
  239. dpd->rx_chan = 0;
  240. dpd->tx_chan = 1;
  241. } else {
  242. dpd->rx_chan = 2;
  243. dpd->tx_chan = 3;
  244. }
  245. ret = platform_device_register(pdev);
  246. if (ret)
  247. return ret;
  248. return 0;
  249. }
  250. int __init
  251. bcm63xx_enetsw_register(const struct bcm63xx_enetsw_platform_data *pd)
  252. {
  253. int ret;
  254. if (!BCMCPU_IS_6328() && !BCMCPU_IS_6362() && !BCMCPU_IS_6368())
  255. return -ENODEV;
  256. ret = register_shared();
  257. if (ret)
  258. return ret;
  259. enetsw_res[0].start = bcm63xx_regset_address(RSET_ENETSW);
  260. enetsw_res[0].end = enetsw_res[0].start;
  261. enetsw_res[0].end += RSET_ENETSW_SIZE - 1;
  262. enetsw_res[1].start = bcm63xx_get_irq_number(IRQ_ENETSW_RXDMA0);
  263. enetsw_res[2].start = bcm63xx_get_irq_number(IRQ_ENETSW_TXDMA0);
  264. if (!enetsw_res[2].start)
  265. enetsw_res[2].start = -1;
  266. memcpy(bcm63xx_enetsw_device.dev.platform_data, pd, sizeof(*pd));
  267. if (BCMCPU_IS_6328())
  268. enetsw_pd.num_ports = ENETSW_PORTS_6328;
  269. else if (BCMCPU_IS_6362() || BCMCPU_IS_6368())
  270. enetsw_pd.num_ports = ENETSW_PORTS_6368;
  271. enetsw_pd.dma_has_sram = true;
  272. enetsw_pd.dma_chan_width = ENETDMA_CHAN_WIDTH;
  273. enetsw_pd.dma_chan_en_mask = ENETDMAC_CHANCFG_EN_MASK;
  274. enetsw_pd.dma_chan_int_mask = ENETDMAC_IR_PKTDONE_MASK;
  275. ret = platform_device_register(&bcm63xx_enetsw_device);
  276. if (ret)
  277. return ret;
  278. return 0;
  279. }