TIAM335X 网卡驱动解析

 

1.CPSW驱动及设备的初始化;

(1)首先驱动注册,会自动进入cpsw_probe执行;

1 static struct platform_driver cpsw_driver = {
2     .driver = {
3         .name     = "cpsw",
4         .owner     = THIS_MODULE,
5         .pm     = &cpsw_pm_ops,
6     },
7     .probe = cpsw_probe,
8     .remove = __devexit_p(cpsw_remove),
9 };

 

进入CPSW后,主要干活是:

  • 创建 cpsw_priv *priv,入参pedv->dev.platform_data的参数,都赋值到priv里,后续主要使用的结构;
  • 创建netdev结构,这个是网卡的默认数据结构,和上层协议栈通讯,注意注册都是用的name,后续作为匹配的,name应该来自入参;
  • 初始化priv_sl2(网卡2),调用cpsw_init_slave_emac()函数,大部分是直接使用网卡1的priv数据直接复制过去;
  • cpsw_netdev_ops内open,xmit等函数赋值到netdev的ndev->netdev_ops,协议栈使用会最终调用这些函数;

数据结构关系:

platform_device *pdev   :  .dev                           ,   指向创建 netdev  *ndev,            在netdev结构体后面定义一个 cpsw_priv *priv, 

                                           .dev.platform_data     ,  改名重定义指向到data , 

data: DMA DMA中断                 ---->               cpsw_priv *priv, 这个结构也是后面主要用的;

    reg    寄存器信息

            ALE  模块

            MAC  配置

            clk     时钟

   

 

 

  1 static int __devinit cpsw_probe(struct platform_device *pdev)
  2 {
  3     struct cpsw_platform_data    *data = pdev->dev.platform_data;
  4     struct net_device        *ndev;
  5     struct cpsw_priv        *priv;
  6     struct cpdma_params        dma_params;
  7     struct cpsw_ale_params        ale_params;
  8     void __iomem            *regs; 15           ..............
 16     ndev = alloc_etherdev(sizeof(struct cpsw_priv));
 17     if (!ndev) {
 18         pr_err("cpsw: error allocating net_device\n");
 19         return -ENOMEM;
 20     }
 21 
 22     platform_set_drvdata(pdev, ndev);
 23     priv = netdev_priv(ndev);
 24     spin_lock_init(&priv->lock);
 25     priv->data = *data;
 26     priv->pdev = pdev;
 27     priv->ndev = ndev;
 28     priv->dev  = &ndev->dev;
 29     priv->msg_enable = netif_msg_init(debug_level, CPSW_DEBUG);
 30     priv->rx_packet_max = max(rx_packet_max, 128);
 31     priv->cpts = devm_kzalloc(&pdev->dev, sizeof(struct cpts), GFP_KERNEL);
 32 
 33     if (is_valid_ether_addr(data->mac_addr)) {
 34         memcpy(priv->mac_addr, data->mac_addr, ETH_ALEN);
 35         printk(KERN_INFO"Detected MACID=%x:%x:%x:%x:%x:%x\n",
 36             priv->mac_addr[0], priv->mac_addr[1],
 37             priv->mac_addr[2], priv->mac_addr[3],
 38             priv->mac_addr[4], priv->mac_addr[5]);
 39     } else {
 40         random_ether_addr(priv->mac_addr);
 41         printk(KERN_INFO"Random MACID=%x:%x:%x:%x:%x:%x\n",
 42             priv->mac_addr[0], priv->mac_addr[1],
 43             priv->mac_addr[2], priv->mac_addr[3],
 44             priv->mac_addr[4], priv->mac_addr[5]);
 45     }
 46 
 47     memcpy(ndev->dev_addr, priv->mac_addr, ETH_ALEN);
 48 
 49     priv->slaves = kzalloc(sizeof(struct cpsw_slave) * data->slaves,
 50                    GFP_KERNEL);
 51     if (!priv->slaves) {
 52         dev_err(priv->dev, "failed to allocate slave ports\n");
 53         ret = -EBUSY;
 54         goto clean_ndev_ret;
 55     }
 56     for (i = 0; i < data->slaves; i++)
 57         priv->slaves[i].slave_num = i;
 58 
 59     priv->slaves[0].ndev = ndev;
 60     priv->emac_port = 0;
 61 
 62     pm_runtime_enable(&pdev->dev);
 63     pm_runtime_get_sync(&pdev->dev);
 64     priv->clk = clk_get(&pdev->dev, "fck");
 65     if (IS_ERR(priv->clk)) {
 66         dev_err(&pdev->dev, "fck is not found\n");
 67         ret = -ENODEV;
 68         goto clean_slave_ret;
 69     }
 70 
 71     priv->coal_intvl = 0;
 72     priv->bus_freq_mhz = clk_get_rate(priv->clk) / 1000000;
 73 
 74     priv->cpsw_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 75     if (!priv->cpsw_res) {
 76         dev_err(priv->dev, "error getting i/o resource\n");
 77         ret = -ENOENT;
 78         goto clean_clk_ret;
 79     }
 80 
 81     if (!request_mem_region(priv->cpsw_res->start,
 82         resource_size(priv->cpsw_res), ndev->name)) {
 83         dev_err(priv->dev, "failed request i/o region\n");
 84         ret = -ENXIO;
 85         goto clean_clk_ret;
 86     }
 87 
 88     regs = ioremap(priv->cpsw_res->start, resource_size(priv->cpsw_res));
 89     if (!regs) {
 90         dev_err(priv->dev, "unable to map i/o region\n");
 91         goto clean_cpsw_iores_ret;
 92     }
 93     priv->regs = regs;
 94     priv->host_port = data->host_port_num;
 95     priv->host_port_regs = regs + data->host_port_reg_ofs;
 96     priv->hw_stats = regs + data->hw_stats_reg_ofs;
 97     priv->cpts->reg = regs + data->cpts_reg_ofs;
 98 
 99     priv->cpsw_ss_res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
100     if (!priv->cpsw_ss_res) {
101         dev_err(priv->dev, "error getting i/o resource\n");
102         ret = -ENOENT;
103         goto clean_clk_ret;
104     }
105 
106     if (!request_mem_region(priv->cpsw_ss_res->start,
107         resource_size(priv->cpsw_ss_res), ndev->name)) {
108         dev_err(priv->dev, "failed request i/o region\n");
109         ret = -ENXIO;
110         goto clean_clk_ret;
111     }
112 
113     regs = ioremap(priv->cpsw_ss_res->start,
114             resource_size(priv->cpsw_ss_res));
115     if (!regs) {
116         dev_err(priv->dev, "unable to map i/o region\n");
117         goto clean_cpsw_ss_iores_ret;
118     }
119     priv->wr_regs = regs;
120 
121     for_each_slave(priv, cpsw_slave_init, priv);
122 
123     omap_ctrl_writel(CPSW_TIMER_MASK, CPSW_TIMER_CAP_REG);
124 
125     dmtimer_rx = omap_dm_timer_request_specific(CPSW_RX_TIMER_REQ);
126     if (!dmtimer_rx) {
127         dev_err(priv->dev, "Error getting Rx Timer resource\n");
128         ret = -ENODEV;
129         goto clean_iomap_ret;
130     }
131     dmtimer_tx = omap_dm_timer_request_specific(CPSW_TX_TIMER_REQ);
132     if (!dmtimer_tx) {
133         dev_err(priv->dev, "Error getting Tx Timer resource\n");
134         ret = -ENODEV;
135         goto clean_timer_rx_ret;
136     }
137 
138     memset(&dma_params, 0, sizeof(dma_params));
139     dma_params.dev            = &pdev->dev;
140     dma_params.dmaregs        = (void __iomem *)(((u32)priv->regs) +
141                         data->cpdma_reg_ofs);
142     dma_params.rxthresh        = (void __iomem *)(((u32)priv->regs) +
143                     data->cpdma_reg_ofs + CPDMA_RXTHRESH);
144     dma_params.rxfree        = (void __iomem *)(((u32)priv->regs) +
145                     data->cpdma_reg_ofs + CPDMA_RXFREE);
146 
147     if (data->version == CPSW_VERSION_2) {
148         dma_params.txhdp    = (void __iomem *)(((u32)priv->regs) +
149                     data->cpdma_reg_ofs + CPDMA_TXHDP_VER2);
150         dma_params.rxhdp    = (void __iomem *)(((u32)priv->regs) +
151                     data->cpdma_reg_ofs + CPDMA_RXHDP_VER2);
152         dma_params.txcp        = (void __iomem *)(((u32)priv->regs) +
153                     data->cpdma_reg_ofs + CPDMA_TXCP_VER2);
154         dma_params.rxcp        = (void __iomem *)(((u32)priv->regs) +
155                     data->cpdma_reg_ofs + CPDMA_RXCP_VER2);
156     } else {
157         dma_params.txhdp    = (void __iomem *)(((u32)priv->regs) +
158                     data->cpdma_reg_ofs + CPDMA_TXHDP_VER1);
159         dma_params.rxhdp    = (void __iomem *)(((u32)priv->regs) +
160                     data->cpdma_reg_ofs + CPDMA_RXHDP_VER1);
161         dma_params.txcp        = (void __iomem *)(((u32)priv->regs) +
162                     data->cpdma_reg_ofs + CPDMA_TXCP_VER1);
163         dma_params.rxcp        = (void __iomem *)(((u32)priv->regs) +
164                     data->cpdma_reg_ofs + CPDMA_RXCP_VER1);
165     }
166 
167     dma_params.num_chan        = data->channels;
168     dma_params.has_soft_reset    = true;
169     dma_params.min_packet_size    = CPSW_MIN_PACKET_SIZE;
170     dma_params.desc_mem_size    = data->bd_ram_size;
171     dma_params.desc_align        = 16;
172     dma_params.has_ext_regs        = true;
173     dma_params.desc_mem_phys    = data->no_bd_ram ? 0 :
174             (u32 __force)priv->cpsw_res->start + data->bd_ram_ofs;
175     dma_params.desc_hw_addr        = data->hw_ram_addr ?
176                 data->hw_ram_addr : dma_params.desc_mem_phys ;
177 
178     priv->dma = cpdma_ctlr_create(&dma_params);
179     if (!priv->dma) {
180         dev_err(priv->dev, "error initializing dma\n");
181         ret = -ENOMEM;
182         goto clean_timer_ret;
183     }
184 
185     priv->txch = cpdma_chan_create(priv->dma, tx_chan_num(0),
186                        cpsw_tx_handler);
187     priv->rxch = cpdma_chan_create(priv->dma, rx_chan_num(0),
188                        cpsw_rx_handler);
189 
190     if (WARN_ON(!priv->txch || !priv->rxch)) {
191         dev_err(priv->dev, "error initializing dma channels\n");
192         ret = -ENOMEM;
193         goto clean_dma_ret;
194     }
195 
196     memset(&ale_params, 0, sizeof(ale_params));
197     ale_params.dev        = &ndev->dev;
198     ale_params.ale_regs    = (void *)((u32)priv->regs) +
199                     ((u32)data->ale_reg_ofs);
200     ale_params.ale_ageout    = ale_ageout;
201     ale_params.ale_entries    = data->ale_entries;
202     ale_params.ale_ports    = data->slaves;
203 
204     priv->ale = cpsw_ale_create(&ale_params);
205     if (!priv->ale) {
206         dev_err(priv->dev, "error initializing ale engine\n");
207         ret = -ENODEV;
208         goto clean_dma_ret;
209     }
210 
211     while ((i = platform_get_irq(pdev, k)) >= 0) {
212         if (request_irq(i, cpsw_interrupt, IRQF_DISABLED,
213                 dev_name(&pdev->dev), priv)) {
214             dev_err(priv->dev, "error attaching irq\n");
215             goto clean_ale_ret;
216         }
217         priv->irqs_table[k] = i;
218         priv->num_irqs = ++k;
219     }
220 
221 #ifdef VLAN_SUPPORT
222     ndev->features |= NETIF_F_HW_VLAN_FILTER;
223 #endif
224 
225     ndev->flags |= IFF_ALLMULTI;    /* see cpsw_ndo_change_rx_flags() */
226 
227     ndev->netdev_ops = &cpsw_netdev_ops;
228     SET_ETHTOOL_OPS(ndev, &cpsw_ethtool_ops);
229     netif_napi_add(ndev, &priv->napi, cpsw_poll, CPSW_POLL_WEIGHT);
230 
231     /* register the network device */
232     SET_NETDEV_DEV(ndev, &pdev->dev);
233     ret = register_netdev(ndev);
234     if (ret) {
235         dev_err(priv->dev, "error registering net device\n");
236         ret = -ENODEV;
237         goto clean_irq_ret;
238     }
239 
240     msg(notice, probe, "initialized device (regs %x, irq %d)\n",
241         priv->cpsw_res->start, ndev->irq);
242 
243     ret = cpsw_init_slave_emac(pdev, priv);
244     if (ret) {
245         dev_err(priv->dev, "error probe slave 2 emac interface\n");
246         goto clean_irq_ret;
247     }
248 
249     return 0;
250 ................280 }

 

上一篇:中断与DMA


下一篇:录音机调试第四天