dev-enet.c 3.8 KB

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