Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * This file is subject to the terms and conditions of the GNU General Public
0003  * License.  See the file "COPYING" in the main directory of this archive
0004  * for more details.
0005  *
0006  * Copyright (C) 2008 Maxime Bizon <mbizon@freebox.fr>
0007  */
0008 
0009 #include <linux/init.h>
0010 #include <linux/kernel.h>
0011 #include <linux/platform_device.h>
0012 #include <linux/export.h>
0013 #include <bcm63xx_dev_enet.h>
0014 #include <bcm63xx_io.h>
0015 #include <bcm63xx_regs.h>
0016 
0017 static const unsigned long bcm6348_regs_enetdmac[] = {
0018     [ENETDMAC_CHANCFG]  = ENETDMAC_CHANCFG_REG,
0019     [ENETDMAC_IR]       = ENETDMAC_IR_REG,
0020     [ENETDMAC_IRMASK]   = ENETDMAC_IRMASK_REG,
0021     [ENETDMAC_MAXBURST] = ENETDMAC_MAXBURST_REG,
0022 };
0023 
0024 static const unsigned long bcm6345_regs_enetdmac[] = {
0025     [ENETDMAC_CHANCFG]  = ENETDMA_6345_CHANCFG_REG,
0026     [ENETDMAC_IR]       = ENETDMA_6345_IR_REG,
0027     [ENETDMAC_IRMASK]   = ENETDMA_6345_IRMASK_REG,
0028     [ENETDMAC_MAXBURST] = ENETDMA_6345_MAXBURST_REG,
0029     [ENETDMAC_BUFALLOC] = ENETDMA_6345_BUFALLOC_REG,
0030     [ENETDMAC_RSTART]   = ENETDMA_6345_RSTART_REG,
0031     [ENETDMAC_FC]       = ENETDMA_6345_FC_REG,
0032     [ENETDMAC_LEN]      = ENETDMA_6345_LEN_REG,
0033 };
0034 
0035 const unsigned long *bcm63xx_regs_enetdmac;
0036 EXPORT_SYMBOL(bcm63xx_regs_enetdmac);
0037 
0038 static __init void bcm63xx_enetdmac_regs_init(void)
0039 {
0040     if (BCMCPU_IS_6345())
0041         bcm63xx_regs_enetdmac = bcm6345_regs_enetdmac;
0042     else
0043         bcm63xx_regs_enetdmac = bcm6348_regs_enetdmac;
0044 }
0045 
0046 static struct resource shared_res[] = {
0047     {
0048         .start      = -1, /* filled at runtime */
0049         .end        = -1, /* filled at runtime */
0050         .flags      = IORESOURCE_MEM,
0051     },
0052     {
0053         .start      = -1, /* filled at runtime */
0054         .end        = -1, /* filled at runtime */
0055         .flags      = IORESOURCE_MEM,
0056     },
0057     {
0058         .start      = -1, /* filled at runtime */
0059         .end        = -1, /* filled at runtime */
0060         .flags      = IORESOURCE_MEM,
0061     },
0062 };
0063 
0064 static struct platform_device bcm63xx_enet_shared_device = {
0065     .name       = "bcm63xx_enet_shared",
0066     .id     = 0,
0067     .num_resources  = ARRAY_SIZE(shared_res),
0068     .resource   = shared_res,
0069 };
0070 
0071 static int shared_device_registered;
0072 
0073 static u64 enet_dmamask = DMA_BIT_MASK(32);
0074 
0075 static struct resource enet0_res[] = {
0076     {
0077         .start      = -1, /* filled at runtime */
0078         .end        = -1, /* filled at runtime */
0079         .flags      = IORESOURCE_MEM,
0080     },
0081     {
0082         .start      = -1, /* filled at runtime */
0083         .flags      = IORESOURCE_IRQ,
0084     },
0085     {
0086         .start      = -1, /* filled at runtime */
0087         .flags      = IORESOURCE_IRQ,
0088     },
0089     {
0090         .start      = -1, /* filled at runtime */
0091         .flags      = IORESOURCE_IRQ,
0092     },
0093 };
0094 
0095 static struct bcm63xx_enet_platform_data enet0_pd;
0096 
0097 static struct platform_device bcm63xx_enet0_device = {
0098     .name       = "bcm63xx_enet",
0099     .id     = 0,
0100     .num_resources  = ARRAY_SIZE(enet0_res),
0101     .resource   = enet0_res,
0102     .dev        = {
0103         .platform_data = &enet0_pd,
0104         .dma_mask = &enet_dmamask,
0105         .coherent_dma_mask = DMA_BIT_MASK(32),
0106     },
0107 };
0108 
0109 static struct resource enet1_res[] = {
0110     {
0111         .start      = -1, /* filled at runtime */
0112         .end        = -1, /* filled at runtime */
0113         .flags      = IORESOURCE_MEM,
0114     },
0115     {
0116         .start      = -1, /* filled at runtime */
0117         .flags      = IORESOURCE_IRQ,
0118     },
0119     {
0120         .start      = -1, /* filled at runtime */
0121         .flags      = IORESOURCE_IRQ,
0122     },
0123     {
0124         .start      = -1, /* filled at runtime */
0125         .flags      = IORESOURCE_IRQ,
0126     },
0127 };
0128 
0129 static struct bcm63xx_enet_platform_data enet1_pd;
0130 
0131 static struct platform_device bcm63xx_enet1_device = {
0132     .name       = "bcm63xx_enet",
0133     .id     = 1,
0134     .num_resources  = ARRAY_SIZE(enet1_res),
0135     .resource   = enet1_res,
0136     .dev        = {
0137         .platform_data = &enet1_pd,
0138         .dma_mask = &enet_dmamask,
0139         .coherent_dma_mask = DMA_BIT_MASK(32),
0140     },
0141 };
0142 
0143 static struct resource enetsw_res[] = {
0144     {
0145         /* start & end filled at runtime */
0146         .flags      = IORESOURCE_MEM,
0147     },
0148     {
0149         /* start filled at runtime */
0150         .flags      = IORESOURCE_IRQ,
0151     },
0152     {
0153         /* start filled at runtime */
0154         .flags      = IORESOURCE_IRQ,
0155     },
0156 };
0157 
0158 static struct bcm63xx_enetsw_platform_data enetsw_pd;
0159 
0160 static struct platform_device bcm63xx_enetsw_device = {
0161     .name       = "bcm63xx_enetsw",
0162     .num_resources  = ARRAY_SIZE(enetsw_res),
0163     .resource   = enetsw_res,
0164     .dev        = {
0165         .platform_data = &enetsw_pd,
0166         .dma_mask = &enet_dmamask,
0167         .coherent_dma_mask = DMA_BIT_MASK(32),
0168     },
0169 };
0170 
0171 static int __init register_shared(void)
0172 {
0173     int ret, chan_count;
0174 
0175     if (shared_device_registered)
0176         return 0;
0177 
0178     bcm63xx_enetdmac_regs_init();
0179 
0180     shared_res[0].start = bcm63xx_regset_address(RSET_ENETDMA);
0181     shared_res[0].end = shared_res[0].start;
0182     if (BCMCPU_IS_6345())
0183         shared_res[0].end += (RSET_6345_ENETDMA_SIZE) - 1;
0184     else
0185         shared_res[0].end += (RSET_ENETDMA_SIZE)  - 1;
0186 
0187     if (BCMCPU_IS_6328() || BCMCPU_IS_6362() || BCMCPU_IS_6368())
0188         chan_count = 32;
0189     else if (BCMCPU_IS_6345())
0190         chan_count = 8;
0191     else
0192         chan_count = 16;
0193 
0194     shared_res[1].start = bcm63xx_regset_address(RSET_ENETDMAC);
0195     shared_res[1].end = shared_res[1].start;
0196     shared_res[1].end += RSET_ENETDMAC_SIZE(chan_count)  - 1;
0197 
0198     shared_res[2].start = bcm63xx_regset_address(RSET_ENETDMAS);
0199     shared_res[2].end = shared_res[2].start;
0200     shared_res[2].end += RSET_ENETDMAS_SIZE(chan_count)  - 1;
0201 
0202     ret = platform_device_register(&bcm63xx_enet_shared_device);
0203     if (ret)
0204         return ret;
0205     shared_device_registered = 1;
0206 
0207     return 0;
0208 }
0209 
0210 int __init bcm63xx_enet_register(int unit,
0211                  const struct bcm63xx_enet_platform_data *pd)
0212 {
0213     struct platform_device *pdev;
0214     struct bcm63xx_enet_platform_data *dpd;
0215     int ret;
0216 
0217     if (unit > 1)
0218         return -ENODEV;
0219 
0220     if (unit == 1 && (BCMCPU_IS_6338() || BCMCPU_IS_6345()))
0221         return -ENODEV;
0222 
0223     ret = register_shared();
0224     if (ret)
0225         return ret;
0226 
0227     if (unit == 0) {
0228         enet0_res[0].start = bcm63xx_regset_address(RSET_ENET0);
0229         enet0_res[0].end = enet0_res[0].start;
0230         enet0_res[0].end += RSET_ENET_SIZE - 1;
0231         enet0_res[1].start = bcm63xx_get_irq_number(IRQ_ENET0);
0232         enet0_res[2].start = bcm63xx_get_irq_number(IRQ_ENET0_RXDMA);
0233         enet0_res[3].start = bcm63xx_get_irq_number(IRQ_ENET0_TXDMA);
0234         pdev = &bcm63xx_enet0_device;
0235     } else {
0236         enet1_res[0].start = bcm63xx_regset_address(RSET_ENET1);
0237         enet1_res[0].end = enet1_res[0].start;
0238         enet1_res[0].end += RSET_ENET_SIZE - 1;
0239         enet1_res[1].start = bcm63xx_get_irq_number(IRQ_ENET1);
0240         enet1_res[2].start = bcm63xx_get_irq_number(IRQ_ENET1_RXDMA);
0241         enet1_res[3].start = bcm63xx_get_irq_number(IRQ_ENET1_TXDMA);
0242         pdev = &bcm63xx_enet1_device;
0243     }
0244 
0245     /* copy given platform data */
0246     dpd = pdev->dev.platform_data;
0247     memcpy(dpd, pd, sizeof(*pd));
0248 
0249     /* adjust them in case internal phy is used */
0250     if (dpd->use_internal_phy) {
0251 
0252         /* internal phy only exists for enet0 */
0253         if (unit == 1)
0254             return -ENODEV;
0255 
0256         dpd->phy_id = 1;
0257         dpd->has_phy_interrupt = 1;
0258         dpd->phy_interrupt = bcm63xx_get_irq_number(IRQ_ENET_PHY);
0259     }
0260 
0261     dpd->dma_chan_en_mask = ENETDMAC_CHANCFG_EN_MASK;
0262     dpd->dma_chan_int_mask = ENETDMAC_IR_PKTDONE_MASK;
0263     if (BCMCPU_IS_6345()) {
0264         dpd->dma_chan_en_mask |= ENETDMAC_CHANCFG_CHAINING_MASK;
0265         dpd->dma_chan_en_mask |= ENETDMAC_CHANCFG_WRAP_EN_MASK;
0266         dpd->dma_chan_en_mask |= ENETDMAC_CHANCFG_FLOWC_EN_MASK;
0267         dpd->dma_chan_int_mask |= ENETDMA_IR_BUFDONE_MASK;
0268         dpd->dma_chan_int_mask |= ENETDMA_IR_NOTOWNER_MASK;
0269         dpd->dma_chan_width = ENETDMA_6345_CHAN_WIDTH;
0270         dpd->dma_desc_shift = ENETDMA_6345_DESC_SHIFT;
0271     } else {
0272         dpd->dma_has_sram = true;
0273         dpd->dma_chan_width = ENETDMA_CHAN_WIDTH;
0274     }
0275 
0276     if (unit == 0) {
0277         dpd->rx_chan = 0;
0278         dpd->tx_chan = 1;
0279     } else {
0280         dpd->rx_chan = 2;
0281         dpd->tx_chan = 3;
0282     }
0283 
0284     ret = platform_device_register(pdev);
0285     if (ret)
0286         return ret;
0287     return 0;
0288 }
0289 
0290 int __init
0291 bcm63xx_enetsw_register(const struct bcm63xx_enetsw_platform_data *pd)
0292 {
0293     int ret;
0294 
0295     if (!BCMCPU_IS_6328() && !BCMCPU_IS_6362() && !BCMCPU_IS_6368())
0296         return -ENODEV;
0297 
0298     ret = register_shared();
0299     if (ret)
0300         return ret;
0301 
0302     enetsw_res[0].start = bcm63xx_regset_address(RSET_ENETSW);
0303     enetsw_res[0].end = enetsw_res[0].start;
0304     enetsw_res[0].end += RSET_ENETSW_SIZE - 1;
0305     enetsw_res[1].start = bcm63xx_get_irq_number(IRQ_ENETSW_RXDMA0);
0306     enetsw_res[2].start = bcm63xx_get_irq_number(IRQ_ENETSW_TXDMA0);
0307     if (!enetsw_res[2].start)
0308         enetsw_res[2].start = -1;
0309 
0310     memcpy(bcm63xx_enetsw_device.dev.platform_data, pd, sizeof(*pd));
0311 
0312     if (BCMCPU_IS_6328())
0313         enetsw_pd.num_ports = ENETSW_PORTS_6328;
0314     else if (BCMCPU_IS_6362() || BCMCPU_IS_6368())
0315         enetsw_pd.num_ports = ENETSW_PORTS_6368;
0316 
0317     enetsw_pd.dma_has_sram = true;
0318     enetsw_pd.dma_chan_width = ENETDMA_CHAN_WIDTH;
0319     enetsw_pd.dma_chan_en_mask = ENETDMAC_CHANCFG_EN_MASK;
0320     enetsw_pd.dma_chan_int_mask = ENETDMAC_IR_PKTDONE_MASK;
0321 
0322     ret = platform_device_register(&bcm63xx_enetsw_device);
0323     if (ret)
0324         return ret;
0325 
0326     return 0;
0327 }