dev-enet.c 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  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 <mbizon@freebox.fr>
  7. */
  8. #include <linux/init.h>
  9. #include <linux/kernel.h>
  10. #include <linux/platform_device.h>
  11. #include <bcm63xx_dev_enet.h>
  12. #include <bcm63xx_io.h>
  13. #include <bcm63xx_regs.h>
  14. static struct resource shared_res[] = {
  15. {
  16. .start = -1, /* filled at runtime */
  17. .end = -1, /* filled at runtime */
  18. .flags = IORESOURCE_MEM,
  19. },
  20. {
  21. .start = -1, /* filled at runtime */
  22. .end = -1, /* filled at runtime */
  23. .flags = IORESOURCE_MEM,
  24. },
  25. {
  26. .start = -1, /* filled at runtime */
  27. .end = -1, /* filled at runtime */
  28. .flags = IORESOURCE_MEM,
  29. },
  30. };
  31. static struct platform_device bcm63xx_enet_shared_device = {
  32. .name = "bcm63xx_enet_shared",
  33. .id = 0,
  34. .num_resources = ARRAY_SIZE(shared_res),
  35. .resource = shared_res,
  36. };
  37. static int shared_device_registered;
  38. static struct resource enet0_res[] = {
  39. {
  40. .start = -1, /* filled at runtime */
  41. .end = -1, /* filled at runtime */
  42. .flags = IORESOURCE_MEM,
  43. },
  44. {
  45. .start = -1, /* filled at runtime */
  46. .flags = IORESOURCE_IRQ,
  47. },
  48. {
  49. .start = -1, /* filled at runtime */
  50. .flags = IORESOURCE_IRQ,
  51. },
  52. {
  53. .start = -1, /* filled at runtime */
  54. .flags = IORESOURCE_IRQ,
  55. },
  56. };
  57. static struct bcm63xx_enet_platform_data enet0_pd;
  58. static struct platform_device bcm63xx_enet0_device = {
  59. .name = "bcm63xx_enet",
  60. .id = 0,
  61. .num_resources = ARRAY_SIZE(enet0_res),
  62. .resource = enet0_res,
  63. .dev = {
  64. .platform_data = &enet0_pd,
  65. },
  66. };
  67. static struct resource enet1_res[] = {
  68. {
  69. .start = -1, /* filled at runtime */
  70. .end = -1, /* filled at runtime */
  71. .flags = IORESOURCE_MEM,
  72. },
  73. {
  74. .start = -1, /* filled at runtime */
  75. .flags = IORESOURCE_IRQ,
  76. },
  77. {
  78. .start = -1, /* filled at runtime */
  79. .flags = IORESOURCE_IRQ,
  80. },
  81. {
  82. .start = -1, /* filled at runtime */
  83. .flags = IORESOURCE_IRQ,
  84. },
  85. };
  86. static struct bcm63xx_enet_platform_data enet1_pd;
  87. static struct platform_device bcm63xx_enet1_device = {
  88. .name = "bcm63xx_enet",
  89. .id = 1,
  90. .num_resources = ARRAY_SIZE(enet1_res),
  91. .resource = enet1_res,
  92. .dev = {
  93. .platform_data = &enet1_pd,
  94. },
  95. };
  96. int __init bcm63xx_enet_register(int unit,
  97. const struct bcm63xx_enet_platform_data *pd)
  98. {
  99. struct platform_device *pdev;
  100. struct bcm63xx_enet_platform_data *dpd;
  101. int ret;
  102. if (unit > 1)
  103. return -ENODEV;
  104. if (unit == 1 && BCMCPU_IS_6338())
  105. return -ENODEV;
  106. if (!shared_device_registered) {
  107. shared_res[0].start = bcm63xx_regset_address(RSET_ENETDMA);
  108. shared_res[0].end = shared_res[0].start;
  109. shared_res[0].end += (RSET_ENETDMA_SIZE) - 1;
  110. shared_res[1].start = bcm63xx_regset_address(RSET_ENETDMAC);
  111. shared_res[1].end = shared_res[1].start;
  112. shared_res[1].end += RSET_ENETDMAC_SIZE(16) - 1;
  113. shared_res[2].start = bcm63xx_regset_address(RSET_ENETDMAS);
  114. shared_res[2].end = shared_res[2].start;
  115. shared_res[2].end += RSET_ENETDMAS_SIZE(16) - 1;
  116. ret = platform_device_register(&bcm63xx_enet_shared_device);
  117. if (ret)
  118. return ret;
  119. shared_device_registered = 1;
  120. }
  121. if (unit == 0) {
  122. enet0_res[0].start = bcm63xx_regset_address(RSET_ENET0);
  123. enet0_res[0].end = enet0_res[0].start;
  124. enet0_res[0].end += RSET_ENET_SIZE - 1;
  125. enet0_res[1].start = bcm63xx_get_irq_number(IRQ_ENET0);
  126. enet0_res[2].start = bcm63xx_get_irq_number(IRQ_ENET0_RXDMA);
  127. enet0_res[3].start = bcm63xx_get_irq_number(IRQ_ENET0_TXDMA);
  128. pdev = &bcm63xx_enet0_device;
  129. } else {
  130. enet1_res[0].start = bcm63xx_regset_address(RSET_ENET1);
  131. enet1_res[0].end = enet1_res[0].start;
  132. enet1_res[0].end += RSET_ENET_SIZE - 1;
  133. enet1_res[1].start = bcm63xx_get_irq_number(IRQ_ENET1);
  134. enet1_res[2].start = bcm63xx_get_irq_number(IRQ_ENET1_RXDMA);
  135. enet1_res[3].start = bcm63xx_get_irq_number(IRQ_ENET1_TXDMA);
  136. pdev = &bcm63xx_enet1_device;
  137. }
  138. /* copy given platform data */
  139. dpd = pdev->dev.platform_data;
  140. memcpy(dpd, pd, sizeof(*pd));
  141. /* adjust them in case internal phy is used */
  142. if (dpd->use_internal_phy) {
  143. /* internal phy only exists for enet0 */
  144. if (unit == 1)
  145. return -ENODEV;
  146. dpd->phy_id = 1;
  147. dpd->has_phy_interrupt = 1;
  148. dpd->phy_interrupt = bcm63xx_get_irq_number(IRQ_ENET_PHY);
  149. }
  150. ret = platform_device_register(pdev);
  151. if (ret)
  152. return ret;
  153. return 0;
  154. }