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