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