rk3399 stmmac驱动解析
时间: 2023-07-22 20:36:49 浏览: 213
RK3399是一款由Rockchip公司生产的64位六核处理器,它集成了双千兆以太网MAC控制器。在RK3399的Linux内核中,提供了对该以太网控制器的stmmac驱动程序支持。以下是对RK3399 stmmac驱动程序的解析:
1. 设备树绑定
RK3399的设备树文件中需要进行stmmac驱动程序的绑定。在设备树中需要指定MAC地址、PHY地址、中断控制器、中断号等信息。以下是设备树中stmmac驱动程序的绑定示例:
```
&mac {
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&mac_rgmii_pins>, <&mac_clk_rx_pins>, <&mac_clk_tx_pins>;
phy-mode = "rgmii";
phy-handle = <&phy0>;
phy0: ethernet-phy@0 {
reg = <0>;
compatible = "ethernet-phy-ieee802.3-c22";
};
interrupts = <GIC_SPI 123 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "macirq";
local-mac-address = [XX XX XX XX XX XX];
};
```
2. 驱动程序初始化
在驱动程序初始化时,需要进行一些基本的设置,如设置MAC地址、中断处理程序、DMA通道等。以下是RK3399 stmmac驱动程序初始化的代码示例:
```
static int rk3399_stmmac_probe(struct platform_device *pdev)
{
struct rk_priv_data *bsp_priv;
struct stmmac_resources stmmac_res;
int ret;
/* Allocate bsp_priv */
bsp_priv = devm_kzalloc(&pdev->dev, sizeof(struct rk_priv_data), GFP_KERNEL);
if (!bsp_priv)
return -ENOMEM;
/* Get GPIO reset pin */
bsp_priv->reset_gpio = of_get_named_gpio(pdev->dev.of_node, "reset-gpios", 0);
if (gpio_is_valid(bsp_priv->reset_gpio)) {
ret = devm_gpio_request_one(&pdev->dev, bsp_priv->reset_gpio, GPIOF_OUT_INIT_LOW, "stmmac_reset");
if (ret) {
dev_err(&pdev->dev, "Failed to request GPIO reset pin %d: %d\n",
bsp_priv->reset_gpio, ret);
goto err_out;
}
}
/* Set MAC address */
stmmac_res.mac_addr = bsp_priv->mac_addr;
/* Set IRQ handler */
stmmac_res.irq = platform_get_irq(pdev, 0);
stmmac_res.irqflags = IRQF_TRIGGER_LOW;
stmmac_res.irqhandler = rk3399_stmmac_isr;
/* Set DMA channel */
stmmac_res.dma_rx_channel = dma_request_slave_channel(&pdev->dev, "rx");
stmmac_res.dma_tx_channel = dma_request_slave_channel(&pdev->dev, "tx");
/* Initialize stmmac */
ret = stmmac_dvr_probe(&pdev->dev, &stmmac_res, &rk3399_pdata, &bsp_priv->plat_dat);
if (ret)
goto err_out;
return 0;
err_out:
return ret;
}
```
3. DMA传输
RK3399 stmmac驱动程序使用DMA引擎来实现高速数据传输。在DMA传输开始前,需要配置DMA通道和缓冲区。以下是RK3399 stmmac驱动程序DMA传输的代码示例:
```
static int rk3399_stmmac_start_xmit(struct sk_buff *skb, struct net_device *ndev)
{
struct rk_priv_data *bsp_priv = netdev_priv(ndev);
struct stmmac_xgmac_dma_ops *dma_ops = &bsp_priv->plat_dat->dma_ops;
struct stmmac_packet_attrs attrs;
dma_addr_t dma_addr;
int ret;
/* Configure DMA buffer */
skb->ip_summed = CHECKSUM_NONE;
skb_push(skb, 2);
skb->data[0] = 0;
skb->data[1] = 0;
/* Configure DMA attributes */
attrs.tci = 0;
attrs.proto = 0;
attrs.dma_desc = NULL;
attrs.tx_csum = 0;
attrs.tx_timestamp = 0;
attrs.tx_vlan = 0;
attrs.tx_vlan_cfi = 0;
/* Map DMA buffer */
dma_addr = dma_map_single(&pdev->dev, skb->data, skb->len, DMA_TO_DEVICE);
if (dma_mapping_error(&pdev->dev, dma_addr)) {
dev_err(&pdev->dev, "Failed to map DMA buffer\n");
goto err_out;
}
/* Configure DMA descriptor */
dma_ops->tx_dma_desc_init(ndev, &attrs, dma_addr, skb->len, 0);
/* Start DMA transfer */
ret = dma_ops->tx_dma(ndev, &attrs);
if (ret) {
dev_err(&pdev->dev, "Failed to start DMA transfer\n");
dma_unmap_single(&pdev->dev, dma_addr, skb->len, DMA_TO_DEVICE);
goto err_out;
}
return NETDEV_TX_OK;
err_out:
dev_kfree_skb(skb);
return NETDEV_TX_OK;
}
```
总的来说,RK3399 stmmac驱动程序是一个功能完善、性能优越的以太网驱动程序,它使用了DMA引擎来实现高速数据传输。通过对设备树进行绑定和执行初始化,可以使该驱动程序在RK3399平台上正常工作。
阅读全文