[U-Boot] [PATCH 06/18] dm: eth: Add driver-model support to the rtl8169 driver

Simon Glass sjg at chromium.org
Tue Jul 7 00:47:45 CEST 2015


This driver is used by the Intel Minnowmax board. Convert it to driver model
so it can use the new Ethernet implementation.

Signed-off-by: Simon Glass <sjg at chromium.org>
---

 drivers/net/rtl8169.c | 236 +++++++++++++++++++++++++++++++++++++++-----------
 1 file changed, 187 insertions(+), 49 deletions(-)

diff --git a/drivers/net/rtl8169.c b/drivers/net/rtl8169.c
index 958488c..7b6e20f 100644
--- a/drivers/net/rtl8169.c
+++ b/drivers/net/rtl8169.c
@@ -41,10 +41,13 @@
  * Modified to use le32_to_cpu and cpu_to_le32 properly
  */
 #include <common.h>
+#include <dm.h>
 #include <errno.h>
 #include <malloc.h>
 #include <net.h>
+#ifndef CONFIG_DM_ETH
 #include <netdev.h>
+#endif
 #include <asm/io.h>
 #include <pci.h>
 
@@ -281,6 +284,8 @@ struct RxDesc {
 	u32 buf_Haddr;
 };
 
+static unsigned char rxdata[RX_BUF_LEN];
+
 #define RTL8169_DESC_SIZE 16
 
 #if ARCH_DMA_MINALIGN > 256
@@ -299,7 +304,8 @@ struct RxDesc {
  * the driver to allocate descriptors from a pool of non-cached memory.
  */
 #if RTL8169_DESC_SIZE < ARCH_DMA_MINALIGN
-#if !defined(CONFIG_SYS_NONCACHED_MEMORY) && !defined(CONFIG_SYS_DCACHE_OFF)
+#if !defined(CONFIG_SYS_NONCACHED_MEMORY) && \
+	!defined(CONFIG_SYS_DCACHE_OFF) && !defined(CONFIG_X86)
 #warning cache-line size is larger than descriptor size
 #endif
 #endif
@@ -317,6 +323,7 @@ DEFINE_ALIGN_BUFFER(u8, txb, NUM_TX_DESC * RX_BUF_SIZE, RTL8169_ALIGN);
 DEFINE_ALIGN_BUFFER(u8, rxb, NUM_RX_DESC * RX_BUF_SIZE, RTL8169_ALIGN);
 
 struct rtl8169_private {
+	ulong iobase;
 	void *mmio_addr;	/* memory map physical address */
 	int chipset;
 	unsigned long cur_rx;	/* Index into the Rx descriptor buffer of next Rx pkt. */
@@ -338,9 +345,9 @@ static const unsigned int rtl8169_rx_config =
     (RX_FIFO_THRESH << RxCfgFIFOShift) | (RX_DMA_BURST << RxCfgDMAShift);
 
 static struct pci_device_id supported[] = {
-	{PCI_VENDOR_ID_REALTEK, 0x8167},
-	{PCI_VENDOR_ID_REALTEK, 0x8168},
-	{PCI_VENDOR_ID_REALTEK, 0x8169},
+	{ PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8167) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8168) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8169) },
 	{}
 };
 
@@ -380,7 +387,7 @@ int mdio_read(int RegAddr)
 	return value;
 }
 
-static int rtl8169_init_board(struct eth_device *dev)
+static int rtl8169_init_board(unsigned long dev_iobase, const char *name)
 {
 	int i;
 	u32 tmp;
@@ -388,7 +395,7 @@ static int rtl8169_init_board(struct eth_device *dev)
 #ifdef DEBUG_RTL8169
 	printf ("%s\n", __FUNCTION__);
 #endif
-	ioaddr = dev->iobase;
+	ioaddr = dev_iobase;
 
 	/* Soft reset the chip. */
 	RTL_W8(ChipCmd, CmdReset);
@@ -412,7 +419,8 @@ static int rtl8169_init_board(struct eth_device *dev)
 	}
 
 	/* if unknown chip, assume array element #0, original RTL-8169 in this case */
-	printf("PCI device %s: unknown chip version, assuming RTL-8169\n", dev->name);
+	printf("PCI device %s: unknown chip version, assuming RTL-8169\n",
+	       name);
 	printf("PCI device: TxConfig = 0x%lX\n", (unsigned long) RTL_R32(TxConfig));
 	tpc->chipset = 0;
 
@@ -504,7 +512,8 @@ static void rtl_flush_buffer(void *buf, size_t size)
 /**************************************************************************
 RECV - Receive a frame
 ***************************************************************************/
-static int rtl_recv(struct eth_device *dev)
+static int rtl_recv_common(pci_dev_t bdf, unsigned long dev_iobase,
+			   uchar **packetp)
 {
 	/* return true if there's an ethernet packet ready to read */
 	/* nic->packet should contain data on return */
@@ -515,7 +524,7 @@ static int rtl_recv(struct eth_device *dev)
 #ifdef DEBUG_RTL8169_RX
 	printf ("%s\n", __FUNCTION__);
 #endif
-	ioaddr = dev->iobase;
+	ioaddr = dev_iobase;
 
 	cur_rx = tpc->cur_rx;
 
@@ -523,7 +532,6 @@ static int rtl_recv(struct eth_device *dev)
 
 	if ((le32_to_cpu(tpc->RxDescArray[cur_rx].status) & OWNbit) == 0) {
 		if (!(le32_to_cpu(tpc->RxDescArray[cur_rx].status) & RxRES)) {
-			unsigned char rxdata[RX_BUF_LEN];
 			length = (int) (le32_to_cpu(tpc->RxDescArray[cur_rx].
 						status) & 0x00001FFF) - 4;
 
@@ -536,17 +544,22 @@ static int rtl_recv(struct eth_device *dev)
 			else
 				tpc->RxDescArray[cur_rx].status =
 					cpu_to_le32(OWNbit + RX_BUF_SIZE);
-			tpc->RxDescArray[cur_rx].buf_addr =
-				cpu_to_le32(bus_to_phys(tpc->RxBufferRing[cur_rx]));
+			tpc->RxDescArray[cur_rx].buf_addr = cpu_to_le32(
+				pci_mem_to_phys(bdf, (pci_addr_t)(unsigned long)
+				tpc->RxBufferRing[cur_rx]));
 			rtl_flush_rx_desc(&tpc->RxDescArray[cur_rx]);
-
+#ifdef CONFIG_DM_ETH
+			*packetp = rxdata;
+#else
 			net_process_received_packet(rxdata, length);
+#endif
 		} else {
 			puts("Error Rx");
+			length = -EIO;
 		}
 		cur_rx = (cur_rx + 1) % NUM_RX_DESC;
 		tpc->cur_rx = cur_rx;
-		return 1;
+		return length;
 
 	} else {
 		ushort sts = RTL_R8(IntrStatus);
@@ -557,11 +570,26 @@ static int rtl_recv(struct eth_device *dev)
 	return (0);		/* initially as this is called to flush the input */
 }
 
+#ifdef CONFIG_DM_ETH
+int rtl8169_eth_recv(struct udevice *dev, int flags, uchar **packetp)
+{
+	struct rtl8169_private *priv = dev_get_priv(dev);
+
+	return rtl_recv_common(pci_get_bdf(dev), priv->iobase, packetp);
+}
+#else
+static int rtl_recv(struct eth_device *dev)
+{
+	return rtl_recv_common((pci_dev_t)dev->priv, dev->iobase, NULL);
+}
+#endif /* nCONFIG_DM_ETH */
+
 #define HZ 1000
 /**************************************************************************
 SEND - Transmit a frame
 ***************************************************************************/
-static int rtl_send(struct eth_device *dev, void *packet, int length)
+static int rtl_send_common(pci_dev_t bdf, unsigned long dev_iobase,
+			   void *packet, int length)
 {
 	/* send the packet to destination */
 
@@ -577,7 +605,7 @@ static int rtl_send(struct eth_device *dev, void *packet, int length)
 	printf("sending %d bytes\n", len);
 #endif
 
-	ioaddr = dev->iobase;
+	ioaddr = dev_iobase;
 
 	/* point to the current txb incase multiple tx_rings are used */
 	ptxb = tpc->Tx_skbuff[entry * MAX_ETH_FRAME_SIZE];
@@ -588,7 +616,8 @@ static int rtl_send(struct eth_device *dev, void *packet, int length)
 		ptxb[len++] = '\0';
 
 	tpc->TxDescArray[entry].buf_Haddr = 0;
-	tpc->TxDescArray[entry].buf_addr = cpu_to_le32(bus_to_phys(ptxb));
+	tpc->TxDescArray[entry].buf_addr = cpu_to_le32(
+		pci_mem_to_phys(bdf, (pci_addr_t)(unsigned long)ptxb));
 	if (entry != (NUM_TX_DESC - 1)) {
 		tpc->TxDescArray[entry].status =
 			cpu_to_le32((OWNbit | FSbit | LSbit) |
@@ -625,7 +654,23 @@ static int rtl_send(struct eth_device *dev, void *packet, int length)
 	return ret;
 }
 
-static void rtl8169_set_rx_mode(struct eth_device *dev)
+#ifdef CONFIG_DM_ETH
+int rtl8169_eth_send(struct udevice *dev, void *packet, int length)
+{
+	struct rtl8169_private *priv = dev_get_priv(dev);
+
+	return rtl_send_common(pci_get_bdf(dev), priv->iobase, packet, length);
+}
+
+#else
+static int rtl_send(struct eth_device *dev, void *packet, int length)
+{
+	return rtl_send_common((pci_dev_t)dev->priv, dev->iobase, packet,
+			       length);
+}
+#endif
+
+static void rtl8169_set_rx_mode(void)
 {
 	u32 mc_filter[2];	/* Multicast hash filter */
 	int rx_mode;
@@ -648,7 +693,7 @@ static void rtl8169_set_rx_mode(struct eth_device *dev)
 	RTL_W32(MAR0 + 4, mc_filter[1]);
 }
 
-static void rtl8169_hw_start(struct eth_device *dev)
+static void rtl8169_hw_start(pci_dev_t bdf)
 {
 	u32 i;
 
@@ -693,9 +738,11 @@ static void rtl8169_hw_start(struct eth_device *dev)
 
 	tpc->cur_rx = 0;
 
-	RTL_W32(TxDescStartAddrLow, bus_to_phys(tpc->TxDescArray));
+	RTL_W32(TxDescStartAddrLow, pci_mem_to_phys(bdf,
+			(pci_addr_t)(unsigned long)tpc->TxDescArray));
 	RTL_W32(TxDescStartAddrHigh, (unsigned long)0);
-	RTL_W32(RxDescStartAddrLow, bus_to_phys(tpc->RxDescArray));
+	RTL_W32(RxDescStartAddrLow, pci_mem_to_phys(
+			bdf, (pci_addr_t)(unsigned long)tpc->RxDescArray));
 	RTL_W32(RxDescStartAddrHigh, (unsigned long)0);
 
 	/* RTL-8169sc/8110sc or later version */
@@ -707,7 +754,7 @@ static void rtl8169_hw_start(struct eth_device *dev)
 
 	RTL_W32(RxMissed, 0);
 
-	rtl8169_set_rx_mode(dev);
+	rtl8169_set_rx_mode();
 
 	/* no early-rx interrupts */
 	RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xF000);
@@ -717,7 +764,7 @@ static void rtl8169_hw_start(struct eth_device *dev)
 #endif
 }
 
-static void rtl8169_init_ring(struct eth_device *dev)
+static void rtl8169_init_ring(pci_dev_t bdf)
 {
 	int i;
 
@@ -745,8 +792,8 @@ static void rtl8169_init_ring(struct eth_device *dev)
 				cpu_to_le32(OWNbit + RX_BUF_SIZE);
 
 		tpc->RxBufferRing[i] = &rxb[i * RX_BUF_SIZE];
-		tpc->RxDescArray[i].buf_addr =
-			cpu_to_le32(bus_to_phys(tpc->RxBufferRing[i]));
+		tpc->RxDescArray[i].buf_addr = cpu_to_le32(pci_mem_to_phys(
+			bdf, (pci_addr_t)(unsigned long)tpc->RxBufferRing[i]));
 		rtl_flush_rx_desc(&tpc->RxDescArray[i]);
 	}
 
@@ -755,10 +802,7 @@ static void rtl8169_init_ring(struct eth_device *dev)
 #endif
 }
 
-/**************************************************************************
-RESET - Finish setting up the ethernet interface
-***************************************************************************/
-static int rtl_reset(struct eth_device *dev, bd_t *bis)
+static void rtl8169_common_start(pci_dev_t bdf, unsigned char *enetaddr)
 {
 	int i;
 
@@ -767,30 +811,47 @@ static int rtl_reset(struct eth_device *dev, bd_t *bis)
 	printf ("%s\n", __FUNCTION__);
 #endif
 
-	rtl8169_init_ring(dev);
-	rtl8169_hw_start(dev);
+	rtl8169_init_ring(bdf);
+	rtl8169_hw_start(bdf);
 	/* Construct a perfect filter frame with the mac address as first match
 	 * and broadcast for all others */
 	for (i = 0; i < 192; i++)
 		txb[i] = 0xFF;
 
-	txb[0] = dev->enetaddr[0];
-	txb[1] = dev->enetaddr[1];
-	txb[2] = dev->enetaddr[2];
-	txb[3] = dev->enetaddr[3];
-	txb[4] = dev->enetaddr[4];
-	txb[5] = dev->enetaddr[5];
+	txb[0] = enetaddr[0];
+	txb[1] = enetaddr[1];
+	txb[2] = enetaddr[2];
+	txb[3] = enetaddr[3];
+	txb[4] = enetaddr[4];
+	txb[5] = enetaddr[5];
 
 #ifdef DEBUG_RTL8169
 	printf("%s elapsed time : %lu\n", __func__, currticks()-stime);
 #endif
-	return 0;
 }
 
+#ifdef CONFIG_DM_ETH
+static int rtl8169_eth_start(struct udevice *dev)
+{
+	struct eth_pdata *plat = dev_get_platdata(dev);
+
+	rtl8169_common_start(pci_get_bdf(dev), plat->enetaddr);
+
+	return 0;
+}
+#else
 /**************************************************************************
-HALT - Turn off ethernet interface
+RESET - Finish setting up the ethernet interface
 ***************************************************************************/
-static void rtl_halt(struct eth_device *dev)
+static int rtl_reset(struct eth_device *dev, bd_t *bis)
+{
+	rtl8169_common_start((pci_dev_t)dev->priv, dev->enetaddr);
+
+	return 0;
+}
+#endif /* nCONFIG_DM_ETH */
+
+static void rtl_halt_common(unsigned long dev_iobase)
 {
 	int i;
 
@@ -798,7 +859,7 @@ static void rtl_halt(struct eth_device *dev)
 	printf ("%s\n", __FUNCTION__);
 #endif
 
-	ioaddr = dev->iobase;
+	ioaddr = dev_iobase;
 
 	/* Stop the chip's Tx and Rx DMA processes. */
 	RTL_W8(ChipCmd, 0x00);
@@ -813,13 +874,31 @@ static void rtl_halt(struct eth_device *dev)
 	}
 }
 
+#ifdef CONFIG_DM_ETH
+void rtl8169_eth_stop(struct udevice *dev)
+{
+	struct rtl8169_private *priv = dev_get_priv(dev);
+
+	rtl_halt_common(priv->iobase);
+}
+#else
+/**************************************************************************
+HALT - Turn off ethernet interface
+***************************************************************************/
+static void rtl_halt(struct eth_device *dev)
+{
+	rtl_halt_common(dev->iobase);
+}
+#endif
+
 /**************************************************************************
 INIT - Look for an adapter, this routine's visible to the outside
 ***************************************************************************/
 
 #define board_found 1
 #define valid_link 0
-static int rtl_init(struct eth_device *dev, bd_t *bis)
+static int rtl_init(unsigned long dev_ioaddr, const char *name,
+		    unsigned char *enetaddr)
 {
 	static int board_idx = -1;
 	int i, rc;
@@ -828,33 +907,32 @@ static int rtl_init(struct eth_device *dev, bd_t *bis)
 #ifdef DEBUG_RTL8169
 	printf ("%s\n", __FUNCTION__);
 #endif
-
-	ioaddr = dev->iobase;
+	ioaddr = dev_ioaddr;
 
 	board_idx++;
 
 	/* point to private storage */
 	tpc = &tpx;
 
-	rc = rtl8169_init_board(dev);
+	rc = rtl8169_init_board(ioaddr, name);
 	if (rc)
 		return rc;
 
 	/* Get MAC address.  FIXME: read EEPROM */
 	for (i = 0; i < MAC_ADDR_LEN; i++)
-		dev->enetaddr[i] = RTL_R8(MAC0 + i);
+		enetaddr[i] = RTL_R8(MAC0 + i);
 
 #ifdef DEBUG_RTL8169
 	printf("chipset = %d\n", tpc->chipset);
 	printf("MAC Address");
 	for (i = 0; i < MAC_ADDR_LEN; i++)
-		printf(":%02x", dev->enetaddr[i]);
+		printf(":%02x", enetaddr[i]);
 	putc('\n');
 #endif
 
 #ifdef DEBUG_RTL8169
 	/* Print out some hardware info */
-	printf("%s: at ioaddr 0x%lx\n", dev->name, ioaddr);
+	printf("%s: at ioaddr 0x%lx\n", name, ioaddr);
 #endif
 
 	/* if TBI is not endbled */
@@ -964,6 +1042,7 @@ static int rtl_init(struct eth_device *dev, bd_t *bis)
 	return 0;
 }
 
+#ifndef CONFIG_DM_ETH
 int rtl8169_initialize(bd_t *bis)
 {
 	pci_dev_t devno;
@@ -1014,7 +1093,7 @@ int rtl8169_initialize(bd_t *bis)
 		dev->send = rtl_send;
 		dev->recv = rtl_recv;
 
-		err = rtl_init(dev, bis);
+		err = rtl_init(dev->iobase, dev->name, dev->enetaddr);
 		if (err < 0) {
 			printf(pr_fmt("failed to initialize card: %d\n"), err);
 			free(dev);
@@ -1027,3 +1106,62 @@ int rtl8169_initialize(bd_t *bis)
 	}
 	return card_number;
 }
+#endif
+
+#ifdef CONFIG_DM_ETH
+static int rtl8169_eth_probe(struct udevice *dev)
+{
+	struct pci_child_platdata *pplat = dev_get_parent_platdata(dev);
+	struct rtl8169_private *priv = dev_get_priv(dev);
+	struct eth_pdata *plat = dev_get_platdata(dev);
+	u32 iobase;
+	int region;
+	int ret;
+
+	debug("rtl8169: REALTEK RTL8169 @0x%x\n", iobase);
+	switch (pplat->device) {
+	case 0x8168:
+		region = 2;
+		break;
+	default:
+		region = 1;
+		break;
+	}
+	pci_read_config32(pci_get_bdf(dev), PCI_BASE_ADDRESS_0 + region * 4,
+			  &iobase);
+	iobase &= ~0xf;
+	priv->iobase = (int)pci_mem_to_phys(pci_get_bdf(dev), iobase);
+
+	ret = rtl_init(priv->iobase, dev->name, plat->enetaddr);
+	if (ret < 0) {
+		printf(pr_fmt("failed to initialize card: %d\n"), ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static const struct eth_ops rtl8169_eth_ops = {
+	.start	= rtl8169_eth_start,
+	.send	= rtl8169_eth_send,
+	.recv	= rtl8169_eth_recv,
+	.stop	= rtl8169_eth_stop,
+};
+
+static const struct udevice_id rtl8169_eth_ids[] = {
+	{ .compatible = "realtek,rtl8169" },
+	{ }
+};
+
+U_BOOT_DRIVER(eth_rtl8169) = {
+	.name	= "eth_rtl8169",
+	.id	= UCLASS_ETH,
+	.of_match = rtl8169_eth_ids,
+	.probe	= rtl8169_eth_probe,
+	.ops	= &rtl8169_eth_ops,
+	.priv_auto_alloc_size = sizeof(struct rtl8169_private),
+	.platdata_auto_alloc_size = sizeof(struct eth_pdata),
+};
+
+U_BOOT_PCI_DEVICE(eth_rtl8169, supported);
+#endif
-- 
2.4.3.573.g4eafbef



More information about the U-Boot mailing list