From 635a76b703f3bd5b20e28bfc86caee9889f536c2 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sat, 18 Apr 2020 01:44:12 +0200 Subject: net: pcnet: Remove CONFIG_PCNET_79C97x These macros guard one switch-case statement, which grows mips malta by some 20 bytes if debug is enabled, and even less if it is not. To make the code simpler, just support all the NICs and be done with it. Signed-off-by: Marek Vasut Cc: Joe Hershberger --- drivers/net/pcnet.c | 8 -------- 1 file changed, 8 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/pcnet.c b/drivers/net/pcnet.c index b4ad11d3fa5..59241c95bcd 100644 --- a/drivers/net/pcnet.c +++ b/drivers/net/pcnet.c @@ -21,10 +21,6 @@ #define PCNET_DEBUG2(fmt,args...) \ debug_cond(PCNET_DEBUG_LEVEL > 1, fmt ,##args) -#if !defined(CONF_PCNET_79C973) && defined(CONF_PCNET_79C975) -#error "Macro for PCnet chip version is not defined!" -#endif - /* * Set the number of Tx and Rx buffers, using Log_2(# buffers). * Reasonable default values are 4 Tx buffers, and 16 Rx buffers. @@ -254,16 +250,12 @@ static int pcnet_probe(struct eth_device *dev, bd_t *bis, int dev_nr) case 0x2621: chipname = "PCnet/PCI II 79C970A"; /* PCI */ break; -#ifdef CONFIG_PCNET_79C973 case 0x2625: chipname = "PCnet/FAST III 79C973"; /* PCI */ break; -#endif -#ifdef CONFIG_PCNET_79C975 case 0x2627: chipname = "PCnet/FAST III 79C975"; /* PCI */ break; -#endif default: printf("%s: PCnet version %#x not supported\n", dev->name, chip_version); -- cgit v1.3.1 From 171f5e580e3388090d589aa4c0f123576948ab52 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sat, 18 Apr 2020 01:56:51 +0200 Subject: net: tulip: Remove CONFIG_TULIP_* These macros are not used by any board, remove them to simplify the driver. The EEPROM accessors are still retained however, as those might still be useful. Signed-off-by: Marek Vasut Cc: Joe Hershberger --- README | 2 - drivers/net/dc2114x.c | 88 +++----------------------------------------- scripts/config_whitelist.txt | 3 -- 3 files changed, 5 insertions(+), 88 deletions(-) (limited to 'drivers/net') diff --git a/README b/README index 08348506765..2e8ad3bc0cb 100644 --- a/README +++ b/README @@ -896,8 +896,6 @@ The following options need to be configured: CONFIG_TULIP Support for Digital 2114x chips. - Optional CONFIG_TULIP_SELECT_MEDIA for board specific - modem chip initialisation (KS8761/QS6611). CONFIG_NATSEMI Support for National dp83815 chips. diff --git a/drivers/net/dc2114x.c b/drivers/net/dc2114x.c index 43c2253f10d..40bfc5281b2 100644 --- a/drivers/net/dc2114x.c +++ b/drivers/net/dc2114x.c @@ -77,15 +77,6 @@ #define POLL_DEMAND 1 -#ifdef CONFIG_TULIP_FIX_DAVICOM -#define RESET_DM9102(dev) {\ - unsigned long i;\ - i=INL(dev, 0x0);\ - udelay(1000);\ - OUTL(dev, i | BMR_SWR, DE4X5_BMR);\ - udelay(1000);\ -} -#else #define RESET_DE4X5(dev) {\ int i;\ i=INL(dev, DE4X5_BMR);\ @@ -97,7 +88,6 @@ for (i=0;i<5;i++) {INL(dev, DE4X5_BMR); udelay(10000);}\ udelay(1000);\ } -#endif #define START_DE4X5(dev) {\ s32 omr; \ @@ -114,11 +104,7 @@ } #define NUM_RX_DESC PKTBUFSRX -#ifndef CONFIG_TULIP_FIX_DAVICOM - #define NUM_TX_DESC 1 /* Number of TX descriptors */ -#else - #define NUM_TX_DESC 4 -#endif +#define NUM_TX_DESC 1 /* Number of TX descriptors */ #define RX_BUFF_SZ PKTSIZE_ALIGN #define TOUT_LOOP 1000000 @@ -140,29 +126,22 @@ static int tx_new; /* TX descriptor ring pointer */ static char rxRingSize; static char txRingSize; -#if defined(UPDATE_SROM) || !defined(CONFIG_TULIP_FIX_DAVICOM) static void sendto_srom(struct eth_device* dev, u_int command, u_long addr); static int getfrom_srom(struct eth_device* dev, u_long addr); static int do_eeprom_cmd(struct eth_device *dev, u_long ioaddr,int cmd,int cmd_len); static int do_read_eeprom(struct eth_device *dev,u_long ioaddr,int location,int addr_len); -#endif /* UPDATE_SROM || !CONFIG_TULIP_FIX_DAVICOM */ #ifdef UPDATE_SROM static int write_srom(struct eth_device *dev, u_long ioaddr, int index, int new_value); static void update_srom(struct eth_device *dev, bd_t *bis); #endif -#ifndef CONFIG_TULIP_FIX_DAVICOM static int read_srom(struct eth_device *dev, u_long ioaddr, int index); static void read_hw_addr(struct eth_device* dev, bd_t * bis); -#endif /* CONFIG_TULIP_FIX_DAVICOM */ static void send_setup_frame(struct eth_device* dev, bd_t * bis); static int dc21x4x_init(struct eth_device* dev, bd_t* bis); static int dc21x4x_send(struct eth_device *dev, void *packet, int length); static int dc21x4x_recv(struct eth_device* dev); static void dc21x4x_halt(struct eth_device* dev); -#ifdef CONFIG_TULIP_SELECT_MEDIA -extern void dc21x4x_select_media(struct eth_device* dev); -#endif #if defined(CONFIG_E500) #define phys_to_bus(a) (a) @@ -183,9 +162,6 @@ static void OUTL(struct eth_device* dev, int command, u_long addr) static struct pci_device_id supported[] = { { PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_TULIP_FAST }, { PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_21142 }, -#ifdef CONFIG_TULIP_FIX_DAVICOM - { PCI_VENDOR_ID_DAVICOM, PCI_DEVICE_ID_DAVICOM_DM9102A }, -#endif { } }; @@ -209,35 +185,22 @@ int dc21x4x_initialize(bd_t *bis) /* Get the chip configuration revision register. */ pci_read_config_dword(devbusfn, PCI_REVISION_ID, &cfrv); -#ifndef CONFIG_TULIP_FIX_DAVICOM if ((cfrv & CFRV_RN) < DC2114x_BRK ) { printf("Error: The chip is not DC21143.\n"); continue; } -#endif pci_read_config_word(devbusfn, PCI_COMMAND, &status); status |= -#ifdef CONFIG_TULIP_USE_IO - PCI_COMMAND_IO | -#else PCI_COMMAND_MEMORY | -#endif PCI_COMMAND_MASTER; pci_write_config_word(devbusfn, PCI_COMMAND, status); pci_read_config_word(devbusfn, PCI_COMMAND, &status); -#ifdef CONFIG_TULIP_USE_IO - if (!(status & PCI_COMMAND_IO)) { - printf("Error: Can not enable I/O access.\n"); - continue; - } -#else if (!(status & PCI_COMMAND_MEMORY)) { printf("Error: Can not enable MEMORY access.\n"); continue; } -#endif if (!(status & PCI_COMMAND_MASTER)) { printf("Error: Can not enable Bus Mastering.\n"); @@ -251,15 +214,9 @@ int dc21x4x_initialize(bd_t *bis) pci_write_config_byte(devbusfn, PCI_LATENCY_TIMER, 0x60); } -#ifdef CONFIG_TULIP_USE_IO - /* read BAR for memory space access */ - pci_read_config_dword(devbusfn, PCI_BASE_ADDRESS_0, &iobase); - iobase &= PCI_BASE_ADDRESS_IO_MASK; -#else /* read BAR for memory space access */ pci_read_config_dword(devbusfn, PCI_BASE_ADDRESS_1, &iobase); iobase &= PCI_BASE_ADDRESS_MEM_MASK; -#endif debug ("dc21x4x: DEC 21142 PCI Device @0x%x\n", iobase); dev = (struct eth_device*) malloc(sizeof *dev); @@ -270,17 +227,9 @@ int dc21x4x_initialize(bd_t *bis) } memset(dev, 0, sizeof(*dev)); -#ifdef CONFIG_TULIP_FIX_DAVICOM - sprintf(dev->name, "Davicom#%d", card_number); -#else sprintf(dev->name, "dc21x4x#%d", card_number); -#endif -#ifdef CONFIG_TULIP_USE_IO - dev->iobase = pci_io_to_phys(devbusfn, iobase); -#else dev->iobase = pci_mem_to_phys(devbusfn, iobase); -#endif dev->priv = (void*) devbusfn; dev->init = dc21x4x_init; dev->halt = dc21x4x_halt; @@ -292,9 +241,8 @@ int dc21x4x_initialize(bd_t *bis) udelay(10 * 1000); -#ifndef CONFIG_TULIP_FIX_DAVICOM read_hw_addr(dev, bis); -#endif + eth_register(dev); card_number++; @@ -311,46 +259,28 @@ static int dc21x4x_init(struct eth_device* dev, bd_t* bis) /* Ensure we're not sleeping. */ pci_write_config_byte(devbusfn, PCI_CFDA_PSM, WAKEUP); -#ifdef CONFIG_TULIP_FIX_DAVICOM - RESET_DM9102(dev); -#else RESET_DE4X5(dev); -#endif if ((INL(dev, DE4X5_STS) & (STS_TS | STS_RS)) != 0) { printf("Error: Cannot reset ethernet controller.\n"); return -1; } -#ifdef CONFIG_TULIP_SELECT_MEDIA - dc21x4x_select_media(dev); -#else OUTL(dev, OMR_SDP | OMR_PS | OMR_PM, DE4X5_OMR); -#endif for (i = 0; i < NUM_RX_DESC; i++) { rx_ring[i].status = cpu_to_le32(R_OWN); rx_ring[i].des1 = cpu_to_le32(RX_BUFF_SZ); rx_ring[i].buf = cpu_to_le32( phys_to_bus((u32)net_rx_packets[i])); -#ifdef CONFIG_TULIP_FIX_DAVICOM - rx_ring[i].next = cpu_to_le32( - phys_to_bus((u32)&rx_ring[(i + 1) % NUM_RX_DESC])); -#else rx_ring[i].next = 0; -#endif } for (i=0; i < NUM_TX_DESC; i++) { tx_ring[i].status = 0; tx_ring[i].des1 = 0; tx_ring[i].buf = 0; - -#ifdef CONFIG_TULIP_FIX_DAVICOM - tx_ring[i].next = cpu_to_le32(phys_to_bus((u32) &tx_ring[(i+1) % NUM_TX_DESC])); -#else tx_ring[i].next = 0; -#endif } rxRingSize = NUM_RX_DESC; @@ -520,9 +450,7 @@ Done: return; } -#if defined(UPDATE_SROM) || !defined(CONFIG_TULIP_FIX_DAVICOM) -/* SROM Read and write routines. - */ +/* SROM Read and write routines. */ static void sendto_srom(struct eth_device* dev, u_int command, u_long addr) { @@ -594,13 +522,12 @@ static int do_read_eeprom(struct eth_device *dev, u_long ioaddr, int location, i return retval; } -#endif /* UPDATE_SROM || !CONFIG_TULIP_FIX_DAVICOM */ -/* This executes a generic EEPROM command, typically a write or write +/* + * This executes a generic EEPROM command, typically a write or write * enable. It returns the data output from the EEPROM, and thus may * also be used for reads. */ -#if defined(UPDATE_SROM) || !defined(CONFIG_TULIP_FIX_DAVICOM) static int do_eeprom_cmd(struct eth_device *dev, u_long ioaddr, int cmd, int cmd_len) { unsigned retval = 0; @@ -636,9 +563,7 @@ static int do_eeprom_cmd(struct eth_device *dev, u_long ioaddr, int cmd, int cmd return retval; } -#endif /* UPDATE_SROM || !CONFIG_TULIP_FIX_DAVICOM */ -#ifndef CONFIG_TULIP_FIX_DAVICOM static int read_srom(struct eth_device *dev, u_long ioaddr, int index) { int ee_addr_size = do_read_eeprom(dev, ioaddr, 0xff, 8) & 0x40000 ? 8 : 6; @@ -647,7 +572,6 @@ static int read_srom(struct eth_device *dev, u_long ioaddr, int index) (((SROM_READ_CMD << ee_addr_size) | index) << 16) | 0xffff, 3 + ee_addr_size + 16); } -#endif /* CONFIG_TULIP_FIX_DAVICOM */ #ifdef UPDATE_SROM static int write_srom(struct eth_device *dev, u_long ioaddr, int index, int new_value) @@ -695,7 +619,6 @@ static int write_srom(struct eth_device *dev, u_long ioaddr, int index, int new_ } #endif -#ifndef CONFIG_TULIP_FIX_DAVICOM static void read_hw_addr(struct eth_device *dev, bd_t *bis) { u_short tmp, *p = (u_short *)(&dev->enetaddr[0]); @@ -721,7 +644,6 @@ Done: #endif return; } -#endif /* CONFIG_TULIP_FIX_DAVICOM */ #ifdef UPDATE_SROM static void update_srom(struct eth_device *dev, bd_t *bis) diff --git a/scripts/config_whitelist.txt b/scripts/config_whitelist.txt index 27125d7b8af..9b9f7df8c42 100644 --- a/scripts/config_whitelist.txt +++ b/scripts/config_whitelist.txt @@ -4076,9 +4076,6 @@ CONFIG_TSECV2_1 CONFIG_TSEC_TBI CONFIG_TSEC_TBICR_SETTINGS CONFIG_TULIP -CONFIG_TULIP_FIX_DAVICOM -CONFIG_TULIP_SELECT_MEDIA -CONFIG_TULIP_USE_IO CONFIG_TWL6030_INPUT CONFIG_TWL6030_POWER CONFIG_TWR -- cgit v1.3.1 From 3c0bcb97d6d7ed7f9b4c46eb2a6dd0e910214faf Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sat, 18 Apr 2020 02:32:19 +0200 Subject: net: pcnet: Replace mips-specific accessors Replace mips-specific UNCACHED_SDRAM() macro with standard map_physmem(), which permits the driver to work on other systems than mips. Signed-off-by: Marek Vasut Cc: Daniel Schwierzeck Cc: Joe Hershberger --- drivers/net/pcnet.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/pcnet.c b/drivers/net/pcnet.c index 59241c95bcd..e7d6c8d714c 100644 --- a/drivers/net/pcnet.c +++ b/drivers/net/pcnet.c @@ -332,7 +332,9 @@ static int pcnet_init(struct eth_device *dev, bd_t *bis) addr = (unsigned long)memalign(ARCH_DMA_MINALIGN, sizeof(*lp->uc)); flush_dcache_range(addr, addr + sizeof(*lp->uc)); - addr = UNCACHED_SDRAM(addr); + addr = (unsigned long)map_physmem(addr, + roundup(sizeof(*lp->uc), ARCH_DMA_MINALIGN), + MAP_NOCACHE); lp->uc = (struct pcnet_uncached_priv *)addr; addr = (unsigned long)memalign(ARCH_DMA_MINALIGN, -- cgit v1.3.1 From 69529c912059ed4585f648cc6cde1a2fbd5b722b Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sat, 18 Apr 2020 05:11:05 +0200 Subject: net: pcnet: Switch to PCI memory access Replace the PCI IO access with PCI memory access, the card supports both, but the former does not work with QEMU SH4. Signed-off-by: Marek Vasut Cc: Daniel Schwierzeck Cc: Joe Hershberger --- drivers/net/pcnet.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/pcnet.c b/drivers/net/pcnet.c index e7d6c8d714c..34a5a16cfe8 100644 --- a/drivers/net/pcnet.c +++ b/drivers/net/pcnet.c @@ -179,14 +179,14 @@ int pcnet_initialize(bd_t *bis) /* * Setup the PCI device. */ - pci_read_config_dword(devbusfn, PCI_BASE_ADDRESS_0, &bar); - dev->iobase = pci_io_to_phys(devbusfn, bar); + pci_read_config_dword(devbusfn, PCI_BASE_ADDRESS_1, &bar); + dev->iobase = pci_mem_to_phys(devbusfn, bar); dev->iobase &= ~0xf; PCNET_DEBUG1("%s: devbusfn=0x%x iobase=0x%lx: ", dev->name, devbusfn, (unsigned long)dev->iobase); - command = PCI_COMMAND_IO | PCI_COMMAND_MASTER; + command = PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER; pci_write_config_word(devbusfn, PCI_COMMAND, command); pci_read_config_word(devbusfn, PCI_COMMAND, &status); if ((status & command) != command) { -- cgit v1.3.1 From ca5cb04b7fef31d66461cb58872d9ea32a24628b Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sun, 19 Apr 2020 03:09:47 +0200 Subject: net: dc2114x: Clean up init code Clean up the driver init code to bring it up to standards with U-Boot coding style, no functional change. Signed-off-by: Marek Vasut Cc: Joe Hershberger --- drivers/net/dc2114x.c | 66 +++++++++++++++++++++++++-------------------------- 1 file changed, 32 insertions(+), 34 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/dc2114x.c b/drivers/net/dc2114x.c index 40bfc5281b2..d302d0362a9 100644 --- a/drivers/net/dc2114x.c +++ b/drivers/net/dc2114x.c @@ -167,33 +167,30 @@ static struct pci_device_id supported[] = { int dc21x4x_initialize(bd_t *bis) { - int idx=0; - int card_number = 0; - unsigned int cfrv; - unsigned char timer; - pci_dev_t devbusfn; - unsigned int iobase; - unsigned short status; - struct eth_device* dev; - - while(1) { - devbusfn = pci_find_devices(supported, idx++); - if (devbusfn == -1) { + struct eth_device *dev; + unsigned short status; + unsigned char timer; + unsigned int iobase; + int card_number = 0; + pci_dev_t devbusfn; + unsigned int cfrv; + int idx = 0; + + while (1) { + devbusfn = pci_find_devices(supported, idx++); + if (devbusfn == -1) break; - } /* Get the chip configuration revision register. */ pci_read_config_dword(devbusfn, PCI_REVISION_ID, &cfrv); - if ((cfrv & CFRV_RN) < DC2114x_BRK ) { + if ((cfrv & CFRV_RN) < DC2114x_BRK) { printf("Error: The chip is not DC21143.\n"); continue; } pci_read_config_word(devbusfn, PCI_COMMAND, &status); - status |= - PCI_COMMAND_MEMORY | - PCI_COMMAND_MASTER; + status |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER; pci_write_config_word(devbusfn, PCI_COMMAND, status); pci_read_config_word(devbusfn, PCI_COMMAND, &status); @@ -211,30 +208,31 @@ int dc21x4x_initialize(bd_t *bis) pci_read_config_byte(devbusfn, PCI_LATENCY_TIMER, &timer); if (timer < 0x60) { - pci_write_config_byte(devbusfn, PCI_LATENCY_TIMER, 0x60); + pci_write_config_byte(devbusfn, PCI_LATENCY_TIMER, + 0x60); } /* read BAR for memory space access */ pci_read_config_dword(devbusfn, PCI_BASE_ADDRESS_1, &iobase); iobase &= PCI_BASE_ADDRESS_MEM_MASK; - debug ("dc21x4x: DEC 21142 PCI Device @0x%x\n", iobase); - - dev = (struct eth_device*) malloc(sizeof *dev); + debug("dc21x4x: DEC 21142 PCI Device @0x%x\n", iobase); + dev = (struct eth_device *)malloc(sizeof(*dev)); if (!dev) { printf("Can not allocalte memory of dc21x4x\n"); break; } + memset(dev, 0, sizeof(*dev)); sprintf(dev->name, "dc21x4x#%d", card_number); dev->iobase = pci_mem_to_phys(devbusfn, iobase); - dev->priv = (void*) devbusfn; - dev->init = dc21x4x_init; - dev->halt = dc21x4x_halt; - dev->send = dc21x4x_send; - dev->recv = dc21x4x_recv; + dev->priv = (void *)devbusfn; + dev->init = dc21x4x_init; + dev->halt = dc21x4x_halt; + dev->send = dc21x4x_send; + dev->recv = dc21x4x_recv; /* Ensure we're not sleeping. */ pci_write_config_byte(devbusfn, PCI_CFDA_PSM, WAKEUP); @@ -251,10 +249,10 @@ int dc21x4x_initialize(bd_t *bis) return card_number; } -static int dc21x4x_init(struct eth_device* dev, bd_t* bis) +static int dc21x4x_init(struct eth_device *dev, bd_t *bis) { - int i; - int devbusfn = (int) dev->priv; + int i; + int devbusfn = (int)dev->priv; /* Ensure we're not sleeping. */ pci_write_config_byte(devbusfn, PCI_CFDA_PSM, WAKEUP); @@ -271,12 +269,12 @@ static int dc21x4x_init(struct eth_device* dev, bd_t* bis) for (i = 0; i < NUM_RX_DESC; i++) { rx_ring[i].status = cpu_to_le32(R_OWN); rx_ring[i].des1 = cpu_to_le32(RX_BUFF_SZ); - rx_ring[i].buf = cpu_to_le32( - phys_to_bus((u32)net_rx_packets[i])); + rx_ring[i].buf = + cpu_to_le32(phys_to_bus((u32)net_rx_packets[i])); rx_ring[i].next = 0; } - for (i=0; i < NUM_TX_DESC; i++) { + for (i = 0; i < NUM_TX_DESC; i++) { tx_ring[i].status = 0; tx_ring[i].des1 = 0; tx_ring[i].buf = 0; @@ -291,8 +289,8 @@ static int dc21x4x_init(struct eth_device* dev, bd_t* bis) tx_ring[txRingSize - 1].des1 |= cpu_to_le32(TD_TER); /* Tell the adapter where the TX/RX rings are located. */ - OUTL(dev, phys_to_bus((u32) &rx_ring), DE4X5_RRBA); - OUTL(dev, phys_to_bus((u32) &tx_ring), DE4X5_TRBA); + OUTL(dev, phys_to_bus((u32)&rx_ring), DE4X5_RRBA); + OUTL(dev, phys_to_bus((u32)&tx_ring), DE4X5_TRBA); START_DE4X5(dev); -- cgit v1.3.1 From 7c53e3364e4dc7dc4752a75f18a3d72548098365 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sun, 19 Apr 2020 03:10:14 +0200 Subject: net: dc2114x: Clean up dc21x4x_send() Clean up the driver send code to bring it up to standards with U-Boot coding style, invert the loops where applicable to cut down the level of indent. No functional change. Signed-off-by: Marek Vasut Cc: Joe Hershberger --- drivers/net/dc2114x.c | 42 ++++++++++++++++++++---------------------- 1 file changed, 20 insertions(+), 22 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/dc2114x.c b/drivers/net/dc2114x.c index d302d0362a9..11ebea9c1a6 100644 --- a/drivers/net/dc2114x.c +++ b/drivers/net/dc2114x.c @@ -304,47 +304,45 @@ static int dc21x4x_init(struct eth_device *dev, bd_t *bis) static int dc21x4x_send(struct eth_device *dev, void *packet, int length) { - int status = -1; - int i; + int status = -1; + int i; if (length <= 0) { printf("%s: bad packet size: %d\n", dev->name, length); - goto Done; + goto done; } - for(i = 0; tx_ring[tx_new].status & cpu_to_le32(T_OWN); i++) { - if (i >= TOUT_LOOP) { - printf("%s: tx error buffer not ready\n", dev->name); - goto Done; - } + for (i = 0; tx_ring[tx_new].status & cpu_to_le32(T_OWN); i++) { + if (i < TOUT_LOOP) + continue; + + printf("%s: tx error buffer not ready\n", dev->name); + goto done; } - tx_ring[tx_new].buf = cpu_to_le32(phys_to_bus((u32) packet)); - tx_ring[tx_new].des1 = cpu_to_le32(TD_TER | TD_LS | TD_FS | length); + tx_ring[tx_new].buf = cpu_to_le32(phys_to_bus((u32)packet)); + tx_ring[tx_new].des1 = cpu_to_le32(TD_TER | TD_LS | TD_FS | length); tx_ring[tx_new].status = cpu_to_le32(T_OWN); OUTL(dev, POLL_DEMAND, DE4X5_TPD); - for(i = 0; tx_ring[tx_new].status & cpu_to_le32(T_OWN); i++) { - if (i >= TOUT_LOOP) { - printf(".%s: tx buffer not ready\n", dev->name); - goto Done; - } + for (i = 0; tx_ring[tx_new].status & cpu_to_le32(T_OWN); i++) { + if (i < TOUT_LOOP) + continue; + + printf(".%s: tx buffer not ready\n", dev->name); + goto done; } if (le32_to_cpu(tx_ring[tx_new].status) & TD_ES) { -#if 0 /* test-only */ - printf("TX error status = 0x%08X\n", - le32_to_cpu(tx_ring[tx_new].status)); -#endif tx_ring[tx_new].status = 0x0; - goto Done; + goto done; } status = length; - Done: - tx_new = (tx_new+1) % NUM_TX_DESC; +done: + tx_new = (tx_new + 1) % NUM_TX_DESC; return status; } -- cgit v1.3.1 From 9308df81a206e73687a8ba7a1f1b3753e2f2fd79 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sun, 19 Apr 2020 03:10:25 +0200 Subject: net: dc2114x: Clean up dc21x4x_recv() Clean up the driver recv code to bring it up to standards with U-Boot coding style. No functional change. Signed-off-by: Marek Vasut Cc: Joe Hershberger --- drivers/net/dc2114x.c | 44 +++++++++++++++++++------------------------- 1 file changed, 19 insertions(+), 25 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/dc2114x.c b/drivers/net/dc2114x.c index 11ebea9c1a6..4d2e11672e1 100644 --- a/drivers/net/dc2114x.c +++ b/drivers/net/dc2114x.c @@ -346,46 +346,40 @@ done: return status; } -static int dc21x4x_recv(struct eth_device* dev) +static int dc21x4x_recv(struct eth_device *dev) { - s32 status; - int length = 0; + int length = 0; + u32 status; - for ( ; ; ) { - status = (s32)le32_to_cpu(rx_ring[rx_new].status); + while (true) { + status = le32_to_cpu(rx_ring[rx_new].status); - if (status & R_OWN) { + if (status & R_OWN) break; - } if (status & RD_LS) { - /* Valid frame status. - */ + /* Valid frame status. */ if (status & RD_ES) { - - /* There was an error. - */ + /* There was an error. */ printf("RX error status = 0x%08X\n", status); } else { - /* A valid frame received. - */ - length = (le32_to_cpu(rx_ring[rx_new].status) >> 16); - - /* Pass the packet up to the protocol - * layers. - */ - net_process_received_packet( - net_rx_packets[rx_new], length - 4); + /* A valid frame received. */ + length = (le32_to_cpu(rx_ring[rx_new].status) + >> 16); + + /* Pass the packet up to the protocol layers */ + net_process_received_packet + (net_rx_packets[rx_new], length - 4); } - /* Change buffer ownership for this frame, back - * to the adapter. + /* + * Change buffer ownership for this frame, + * back to the adapter. */ rx_ring[rx_new].status = cpu_to_le32(R_OWN); } - /* Update entry information. - */ + /* Update entry information. */ rx_new = (rx_new + 1) % rxRingSize; } -- cgit v1.3.1 From 5b4e7dfb879c4b127f27bd92bac68e114d5e0b70 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sun, 19 Apr 2020 03:10:30 +0200 Subject: net: dc2114x: Clean up dc21x4x_halt() Clean up the driver halt code to bring it up to standards with U-Boot coding style. No functional change. Signed-off-by: Marek Vasut Cc: Joe Hershberger --- drivers/net/dc2114x.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/dc2114x.c b/drivers/net/dc2114x.c index 4d2e11672e1..6fe05113cae 100644 --- a/drivers/net/dc2114x.c +++ b/drivers/net/dc2114x.c @@ -386,9 +386,9 @@ static int dc21x4x_recv(struct eth_device *dev) return length; } -static void dc21x4x_halt(struct eth_device* dev) +static void dc21x4x_halt(struct eth_device *dev) { - int devbusfn = (int) dev->priv; + int devbusfn = (int)dev->priv; STOP_DE4X5(dev); OUTL(dev, 0, DE4X5_SICR); -- cgit v1.3.1 From 5a0c332a8a6fee7deadda5c8439782aa5f7b9ca2 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sun, 19 Apr 2020 03:10:50 +0200 Subject: net: dc2114x: Clean up send_setup_frame() Clean up the send_setup_frame() to bring it up to standards with U-Boot coding style, invert the loops where applicable to cut down the level of indent. No functional change. Signed-off-by: Marek Vasut Cc: Joe Hershberger --- drivers/net/dc2114x.c | 44 ++++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 22 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/dc2114x.c b/drivers/net/dc2114x.c index 6fe05113cae..bd64c75af4c 100644 --- a/drivers/net/dc2114x.c +++ b/drivers/net/dc2114x.c @@ -396,48 +396,48 @@ static void dc21x4x_halt(struct eth_device *dev) pci_write_config_byte(devbusfn, PCI_CFDA_PSM, SLEEP); } -static void send_setup_frame(struct eth_device* dev, bd_t *bis) +static void send_setup_frame(struct eth_device *dev, bd_t *bis) { - int i; - char setup_frame[SETUP_FRAME_LEN]; - char *pa = &setup_frame[0]; + char setup_frame[SETUP_FRAME_LEN]; + char *pa = &setup_frame[0]; + int i; memset(pa, 0xff, SETUP_FRAME_LEN); for (i = 0; i < ETH_ALEN; i++) { *(pa + (i & 1)) = dev->enetaddr[i]; - if (i & 0x01) { + if (i & 0x01) pa += 4; - } } - for(i = 0; tx_ring[tx_new].status & cpu_to_le32(T_OWN); i++) { - if (i >= TOUT_LOOP) { - printf("%s: tx error buffer not ready\n", dev->name); - goto Done; - } + for (i = 0; tx_ring[tx_new].status & cpu_to_le32(T_OWN); i++) { + if (i < TOUT_LOOP) + continue; + + printf("%s: tx error buffer not ready\n", dev->name); + return; } - tx_ring[tx_new].buf = cpu_to_le32(phys_to_bus((u32) &setup_frame[0])); - tx_ring[tx_new].des1 = cpu_to_le32(TD_TER | TD_SET| SETUP_FRAME_LEN); + tx_ring[tx_new].buf = cpu_to_le32(phys_to_bus((u32)&setup_frame[0])); + tx_ring[tx_new].des1 = cpu_to_le32(TD_TER | TD_SET | SETUP_FRAME_LEN); tx_ring[tx_new].status = cpu_to_le32(T_OWN); OUTL(dev, POLL_DEMAND, DE4X5_TPD); - for(i = 0; tx_ring[tx_new].status & cpu_to_le32(T_OWN); i++) { - if (i >= TOUT_LOOP) { - printf("%s: tx buffer not ready\n", dev->name); - goto Done; - } + for (i = 0; tx_ring[tx_new].status & cpu_to_le32(T_OWN); i++) { + if (i < TOUT_LOOP) + continue; + + printf("%s: tx buffer not ready\n", dev->name); + return; } if (le32_to_cpu(tx_ring[tx_new].status) != 0x7FFFFFFF) { - printf("TX error status2 = 0x%08X\n", le32_to_cpu(tx_ring[tx_new].status)); + printf("TX error status2 = 0x%08X\n", + le32_to_cpu(tx_ring[tx_new].status)); } - tx_new = (tx_new+1) % NUM_TX_DESC; -Done: - return; + tx_new = (tx_new + 1) % NUM_TX_DESC; } /* SROM Read and write routines. */ -- cgit v1.3.1 From 2e5c2a103edeed19bfbf393e8550a7bd77e62dfa Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sun, 19 Apr 2020 03:11:06 +0200 Subject: net: dc2114x: Clean up SROM operations Clean up the SROM accessors to bring them up to standards with U-Boot coding style. Sort variable into reverse xmas tree. No functional change. Signed-off-by: Marek Vasut Cc: Joe Hershberger --- drivers/net/dc2114x.c | 117 +++++++++++++++++++++++++++----------------------- 1 file changed, 63 insertions(+), 54 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/dc2114x.c b/drivers/net/dc2114x.c index bd64c75af4c..b375906e27d 100644 --- a/drivers/net/dc2114x.c +++ b/drivers/net/dc2114x.c @@ -441,30 +441,27 @@ static void send_setup_frame(struct eth_device *dev, bd_t *bis) } /* SROM Read and write routines. */ -static void -sendto_srom(struct eth_device* dev, u_int command, u_long addr) +static void sendto_srom(struct eth_device *dev, u_int command, u_long addr) { OUTL(dev, command, addr); udelay(1); } -static int -getfrom_srom(struct eth_device* dev, u_long addr) +static int getfrom_srom(struct eth_device *dev, u_long addr) { - s32 tmp; + s32 tmp = INL(dev, addr); - tmp = INL(dev, addr); udelay(1); - return tmp; } /* Note: this routine returns extra data bits for size detection. */ -static int do_read_eeprom(struct eth_device *dev, u_long ioaddr, int location, int addr_len) +static int do_read_eeprom(struct eth_device *dev, u_long ioaddr, int location, + int addr_len) { - int i; - unsigned retval = 0; int read_cmd = location | (SROM_READ_CMD << addr_len); + unsigned int retval = 0; + int i; sendto_srom(dev, SROM_RD | SROM_SR, ioaddr); sendto_srom(dev, SROM_RD | SROM_SR | DT_CS, ioaddr); @@ -476,14 +473,18 @@ static int do_read_eeprom(struct eth_device *dev, u_long ioaddr, int location, i /* Shift the read command bits out. */ for (i = 4 + addr_len; i >= 0; i--) { short dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0; - sendto_srom(dev, SROM_RD | SROM_SR | DT_CS | dataval, ioaddr); + + sendto_srom(dev, SROM_RD | SROM_SR | DT_CS | dataval, + ioaddr); udelay(10); - sendto_srom(dev, SROM_RD | SROM_SR | DT_CS | dataval | DT_CLK, ioaddr); + sendto_srom(dev, SROM_RD | SROM_SR | DT_CS | dataval | DT_CLK, + ioaddr); udelay(10); #ifdef DEBUG_SROM2 printf("%X", getfrom_srom(dev, ioaddr) & 15); #endif - retval = (retval << 1) | ((getfrom_srom(dev, ioaddr) & EE_DATA_READ) ? 1 : 0); + retval = (retval << 1) | + !!(getfrom_srom(dev, ioaddr) & EE_DATA_READ); } sendto_srom(dev, SROM_RD | SROM_SR | DT_CS, ioaddr); @@ -498,7 +499,8 @@ static int do_read_eeprom(struct eth_device *dev, u_long ioaddr, int location, i #ifdef DEBUG_SROM2 printf("%X", getfrom_srom(dev, ioaddr) & 15); #endif - retval = (retval << 1) | ((getfrom_srom(dev, ioaddr) & EE_DATA_READ) ? 1 : 0); + retval = (retval << 1) | + !!(getfrom_srom(dev, ioaddr) & EE_DATA_READ); sendto_srom(dev, SROM_RD | SROM_SR | DT_CS, ioaddr); udelay(10); } @@ -518,34 +520,38 @@ static int do_read_eeprom(struct eth_device *dev, u_long ioaddr, int location, i * enable. It returns the data output from the EEPROM, and thus may * also be used for reads. */ -static int do_eeprom_cmd(struct eth_device *dev, u_long ioaddr, int cmd, int cmd_len) +static int do_eeprom_cmd(struct eth_device *dev, u_long ioaddr, int cmd, + int cmd_len) { - unsigned retval = 0; + unsigned int retval = 0; #ifdef DEBUG_SROM printf(" EEPROM op 0x%x: ", cmd); #endif - sendto_srom(dev,SROM_RD | SROM_SR | DT_CS | DT_CLK, ioaddr); + sendto_srom(dev, SROM_RD | SROM_SR | DT_CS | DT_CLK, ioaddr); /* Shift the command bits out. */ do { - short dataval = (cmd & (1 << cmd_len)) ? EE_WRITE_1 : EE_WRITE_0; - sendto_srom(dev,dataval, ioaddr); + short dataval = (cmd & BIT(cmd_len)) ? EE_WRITE_1 : EE_WRITE_0; + + sendto_srom(dev, dataval, ioaddr); udelay(10); #ifdef DEBUG_SROM2 - printf("%X", getfrom_srom(dev,ioaddr) & 15); + printf("%X", getfrom_srom(dev, ioaddr) & 15); #endif - sendto_srom(dev,dataval | DT_CLK, ioaddr); + sendto_srom(dev, dataval | DT_CLK, ioaddr); udelay(10); - retval = (retval << 1) | ((getfrom_srom(dev,ioaddr) & EE_DATA_READ) ? 1 : 0); + retval = (retval << 1) | + !!(getfrom_srom(dev, ioaddr) & EE_DATA_READ); } while (--cmd_len >= 0); - sendto_srom(dev,SROM_RD | SROM_SR | DT_CS, ioaddr); + + sendto_srom(dev, SROM_RD | SROM_SR | DT_CS, ioaddr); /* Terminate the EEPROM access. */ - sendto_srom(dev,SROM_RD | SROM_SR, ioaddr); + sendto_srom(dev, SROM_RD | SROM_SR, ioaddr); #ifdef DEBUG_SROM printf(" EEPROM result is 0x%5.5x.\n", retval); @@ -556,21 +562,26 @@ static int do_eeprom_cmd(struct eth_device *dev, u_long ioaddr, int cmd, int cmd static int read_srom(struct eth_device *dev, u_long ioaddr, int index) { - int ee_addr_size = do_read_eeprom(dev, ioaddr, 0xff, 8) & 0x40000 ? 8 : 6; + int ee_addr_size; - return do_eeprom_cmd(dev, ioaddr, - (((SROM_READ_CMD << ee_addr_size) | index) << 16) - | 0xffff, 3 + ee_addr_size + 16); + ee_addr_size = (do_read_eeprom(dev, ioaddr, 0xff, 8) & BIT(18)) ? 8 : 6; + + return do_eeprom_cmd(dev, ioaddr, 0xffff | + (((SROM_READ_CMD << ee_addr_size) | index) << 16), + 3 + ee_addr_size + 16); } #ifdef UPDATE_SROM -static int write_srom(struct eth_device *dev, u_long ioaddr, int index, int new_value) +static int write_srom(struct eth_device *dev, u_long ioaddr, int index, + int new_value) { - int ee_addr_size = do_read_eeprom(dev, ioaddr, 0xff, 8) & 0x40000 ? 8 : 6; - int i; unsigned short newval; + int ee_addr_size; + int i; - udelay(10*1000); /* test-only */ + ee_addr_size = (do_read_eeprom(dev, ioaddr, 0xff, 8) & BIT(18)) ? 8 : 6; + + udelay(10 * 1000); /* test-only */ #ifdef DEBUG_SROM printf("ee_addr_size=%d.\n", ee_addr_size); @@ -578,33 +589,37 @@ static int write_srom(struct eth_device *dev, u_long ioaddr, int index, int new_ #endif /* Enable programming modes. */ - do_eeprom_cmd(dev, ioaddr, (0x4f << (ee_addr_size-4)), 3+ee_addr_size); + do_eeprom_cmd(dev, ioaddr, 0x4f << (ee_addr_size - 4), + 3 + ee_addr_size); /* Do the actual write. */ - do_eeprom_cmd(dev, ioaddr, - (((SROM_WRITE_CMD<> 1); i++) { - tmp = read_srom(dev, DE4X5_APROM, ((SROM_HWADD >> 1) + i)); + tmp = read_srom(dev, DE4X5_APROM, (SROM_HWADD >> 1) + i); *p = le16_to_cpu(tmp); j += *p++; } - if ((j == 0) || (j == 0x2fffd)) { - memset (dev->enetaddr, 0, ETH_ALEN); - debug ("Warning: can't read HW address from SROM.\n"); - goto Done; - } - - return; - -Done: + if (!j || j == 0x2fffd) { + memset(dev->enetaddr, 0, ETH_ALEN); + debug("Warning: can't read HW address from SROM.\n"); #ifdef UPDATE_SROM - update_srom(dev, bis); + update_srom(dev, bis); #endif - return; + } } #ifdef UPDATE_SROM static void update_srom(struct eth_device *dev, bd_t *bis) { - int i; static unsigned short eeprom[0x40] = { 0x140b, 0x6610, 0x0000, 0x0000, /* 00 */ 0x0000, 0x0000, 0x0000, 0x0000, /* 04 */ @@ -658,16 +666,17 @@ static void update_srom(struct eth_device *dev, bd_t *bis) 0x0000, 0x0000, 0x0000, 0x4e07, /* 3c */ }; uchar enetaddr[6]; + int i; /* Ethernet Addr... */ if (!eth_env_get_enetaddr("ethaddr", enetaddr)) return; + eeprom[0x0a] = (enetaddr[1] << 8) | enetaddr[0]; eeprom[0x0b] = (enetaddr[3] << 8) | enetaddr[2]; eeprom[0x0c] = (enetaddr[5] << 8) | enetaddr[4]; - for (i=0; i<0x40; i++) { + for (i = 0; i < 0x40; i++) write_srom(dev, DE4X5_APROM, i, eeprom[i]); - } } -#endif /* UPDATE_SROM */ +#endif /* UPDATE_SROM */ -- cgit v1.3.1 From eb216f1e0005ea1b3e125efeb32d72d1691eea2d Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sun, 19 Apr 2020 03:09:26 +0200 Subject: net: dc2114x: Clean up remaining driver code Clean up the remaining driver code, macro space alignment, function declaration indent, replace __attribute__((aligned(32))) with plain __aligned(32). No functional change. Signed-off-by: Marek Vasut Cc: Joe Hershberger --- drivers/net/dc2114x.c | 86 +++++++++++++++++++++++++-------------------------- 1 file changed, 43 insertions(+), 43 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/dc2114x.c b/drivers/net/dc2114x.c index b375906e27d..007e4cecb69 100644 --- a/drivers/net/dc2114x.c +++ b/drivers/net/dc2114x.c @@ -12,19 +12,17 @@ #undef UPDATE_SROM -/* PCI Registers. - */ -#define PCI_CFDA_PSM 0x43 +/* PCI Registers. */ +#define PCI_CFDA_PSM 0x43 #define CFRV_RN 0x000000f0 /* Revision Number */ #define WAKEUP 0x00 /* Power Saving Wakeup */ #define SLEEP 0x80 /* Power Saving Sleep Mode */ -#define DC2114x_BRK 0x0020 /* CFRV break between DC21142 & DC21143 */ +#define DC2114x_BRK 0x0020 /* CFRV break between DC21142 & DC21143 */ -/* Ethernet chip registers. - */ +/* Ethernet chip registers. */ #define DE4X5_BMR 0x000 /* Bus Mode Register */ #define DE4X5_TPD 0x008 /* Transmit Poll Demand Reg */ #define DE4X5_RRBA 0x018 /* RX Ring Base Address Reg */ @@ -34,8 +32,7 @@ #define DE4X5_SICR 0x068 /* SIA Connectivity Register */ #define DE4X5_APROM 0x048 /* Ethernet Address PROM */ -/* Register bits. - */ +/* Register bits. */ #define BMR_SWR 0x00000001 /* Software Reset */ #define STS_TS 0x00700000 /* Transmit Process State */ #define STS_RS 0x000e0000 /* Receive Process State */ @@ -45,8 +42,7 @@ #define OMR_SDP 0x02000000 /* SD Polarity - MUST BE ASSERTED */ #define OMR_PM 0x00000080 /* Pass All Multicast */ -/* Descriptor bits. - */ +/* Descriptor bits. */ #define R_OWN 0x80000000 /* Own Bit */ #define RD_RER 0x02000000 /* Receive End Of Ring */ #define RD_LS 0x00000100 /* Last Descriptor */ @@ -63,12 +59,12 @@ #define SROM_READ_CMD 6 #define SROM_ERASE_CMD 7 -#define SROM_HWADD 0x0014 /* Hardware Address offset in SROM */ +#define SROM_HWADD 0x0014 /* Hardware Address offset in SROM */ #define SROM_RD 0x00004000 /* Read from Boot ROM */ -#define EE_DATA_WRITE 0x04 /* EEPROM chip data in. */ -#define EE_WRITE_0 0x4801 -#define EE_WRITE_1 0x4805 -#define EE_DATA_READ 0x08 /* EEPROM chip data out. */ +#define EE_DATA_WRITE 0x04 /* EEPROM chip data in. */ +#define EE_WRITE_0 0x4801 +#define EE_WRITE_1 0x4805 +#define EE_DATA_READ 0x08 /* EEPROM chip data out. */ #define SROM_SR 0x00000800 /* Select Serial ROM when set */ #define DT_IN 0x00000004 /* Serial Data In */ @@ -79,13 +75,13 @@ #define RESET_DE4X5(dev) {\ int i;\ - i=INL(dev, DE4X5_BMR);\ + i = INL(dev, DE4X5_BMR);\ udelay(1000);\ OUTL(dev, i | BMR_SWR, DE4X5_BMR);\ udelay(1000);\ OUTL(dev, i, DE4X5_BMR);\ udelay(1000);\ - for (i=0;i<5;i++) {INL(dev, DE4X5_BMR); udelay(10000);}\ + for (i = 0; i < 5; i++) {INL(dev, DE4X5_BMR); udelay(10000); } \ udelay(1000);\ } @@ -99,7 +95,7 @@ #define STOP_DE4X5(dev) {\ s32 omr; \ omr = INL(dev, DE4X5_OMR);\ - omr &= ~(OMR_ST|OMR_SR);\ + omr &= ~(OMR_ST | OMR_SR);\ OUTL(dev, omr, DE4X5_OMR); /* Disable the TX and/or RX */ \ } @@ -118,30 +114,34 @@ struct de4x5_desc { u32 next; }; -static struct de4x5_desc rx_ring[NUM_RX_DESC] __attribute__ ((aligned(32))); /* RX descriptor ring */ -static struct de4x5_desc tx_ring[NUM_TX_DESC] __attribute__ ((aligned(32))); /* TX descriptor ring */ -static int rx_new; /* RX descriptor ring pointer */ -static int tx_new; /* TX descriptor ring pointer */ - -static char rxRingSize; -static char txRingSize; - -static void sendto_srom(struct eth_device* dev, u_int command, u_long addr); -static int getfrom_srom(struct eth_device* dev, u_long addr); -static int do_eeprom_cmd(struct eth_device *dev, u_long ioaddr,int cmd,int cmd_len); -static int do_read_eeprom(struct eth_device *dev,u_long ioaddr,int location,int addr_len); +/* RX and TX descriptor ring */ +static struct de4x5_desc rx_ring[NUM_RX_DESC] __aligned(32); +static struct de4x5_desc tx_ring[NUM_TX_DESC] __aligned(32); +static int rx_new; /* RX descriptor ring pointer */ +static int tx_new; /* TX descriptor ring pointer */ + +static char rx_ring_size; +static char tx_ring_size; + +static void sendto_srom(struct eth_device *dev, u_int command, u_long addr); +static int getfrom_srom(struct eth_device *dev, u_long addr); +static int do_eeprom_cmd(struct eth_device *dev, u_long ioaddr, + int cmd, int cmd_len); +static int do_read_eeprom(struct eth_device *dev, u_long ioaddr, + int location, int addr_len); #ifdef UPDATE_SROM -static int write_srom(struct eth_device *dev, u_long ioaddr, int index, int new_value); +static int write_srom(struct eth_device *dev, u_long ioaddr, + int index, int new_value); static void update_srom(struct eth_device *dev, bd_t *bis); #endif static int read_srom(struct eth_device *dev, u_long ioaddr, int index); -static void read_hw_addr(struct eth_device* dev, bd_t * bis); -static void send_setup_frame(struct eth_device* dev, bd_t * bis); +static void read_hw_addr(struct eth_device *dev, bd_t *bis); +static void send_setup_frame(struct eth_device *dev, bd_t *bis); -static int dc21x4x_init(struct eth_device* dev, bd_t* bis); +static int dc21x4x_init(struct eth_device *dev, bd_t *bis); static int dc21x4x_send(struct eth_device *dev, void *packet, int length); -static int dc21x4x_recv(struct eth_device* dev); -static void dc21x4x_halt(struct eth_device* dev); +static int dc21x4x_recv(struct eth_device *dev); +static void dc21x4x_halt(struct eth_device *dev); #if defined(CONFIG_E500) #define phys_to_bus(a) (a) @@ -149,12 +149,12 @@ static void dc21x4x_halt(struct eth_device* dev); #define phys_to_bus(a) pci_phys_to_mem((pci_dev_t)dev->priv, a) #endif -static int INL(struct eth_device* dev, u_long addr) +static int INL(struct eth_device *dev, u_long addr) { return le32_to_cpu(*(volatile u_long *)(addr + dev->iobase)); } -static void OUTL(struct eth_device* dev, int command, u_long addr) +static void OUTL(struct eth_device *dev, int command, u_long addr) { *(volatile u_long *)(addr + dev->iobase) = cpu_to_le32(command); } @@ -281,12 +281,12 @@ static int dc21x4x_init(struct eth_device *dev, bd_t *bis) tx_ring[i].next = 0; } - rxRingSize = NUM_RX_DESC; - txRingSize = NUM_TX_DESC; + rx_ring_size = NUM_RX_DESC; + tx_ring_size = NUM_TX_DESC; /* Write the end of list marker to the descriptor lists. */ - rx_ring[rxRingSize - 1].des1 |= cpu_to_le32(RD_RER); - tx_ring[txRingSize - 1].des1 |= cpu_to_le32(TD_TER); + rx_ring[rx_ring_size - 1].des1 |= cpu_to_le32(RD_RER); + tx_ring[tx_ring_size - 1].des1 |= cpu_to_le32(TD_TER); /* Tell the adapter where the TX/RX rings are located. */ OUTL(dev, phys_to_bus((u32)&rx_ring), DE4X5_RRBA); @@ -380,7 +380,7 @@ static int dc21x4x_recv(struct eth_device *dev) } /* Update entry information. */ - rx_new = (rx_new + 1) % rxRingSize; + rx_new = (rx_new + 1) % rx_ring_size; } return length; -- cgit v1.3.1 From 04da06120909729bc9d0d3974d06dc2ef758e821 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sun, 19 Apr 2020 03:36:46 +0200 Subject: net: dc2114x: Clean up DE4X5 macros Replace these macros with static functions to permit the compiler to do type checking on the functions. The INL()/OUTL() functions have to be moved in this patch as well, as those DE4X5 macros are using them. No functional change. Signed-off-by: Marek Vasut Cc: Joe Hershberger --- drivers/net/dc2114x.c | 89 +++++++++++++++++++++++++++++---------------------- 1 file changed, 50 insertions(+), 39 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/dc2114x.c b/drivers/net/dc2114x.c index 007e4cecb69..a85fb76d53c 100644 --- a/drivers/net/dc2114x.c +++ b/drivers/net/dc2114x.c @@ -73,30 +73,57 @@ #define POLL_DEMAND 1 -#define RESET_DE4X5(dev) {\ - int i;\ - i = INL(dev, DE4X5_BMR);\ - udelay(1000);\ - OUTL(dev, i | BMR_SWR, DE4X5_BMR);\ - udelay(1000);\ - OUTL(dev, i, DE4X5_BMR);\ - udelay(1000);\ - for (i = 0; i < 5; i++) {INL(dev, DE4X5_BMR); udelay(10000); } \ - udelay(1000);\ +#if defined(CONFIG_E500) +#define phys_to_bus(a) (a) +#else +#define phys_to_bus(a) pci_phys_to_mem((pci_dev_t)dev->priv, a) +#endif + +static int INL(struct eth_device *dev, u_long addr) +{ + return le32_to_cpu(*(volatile u_long *)(addr + dev->iobase)); +} + +static void OUTL(struct eth_device *dev, int command, u_long addr) +{ + *(volatile u_long *)(addr + dev->iobase) = cpu_to_le32(command); +} + +static void reset_de4x5(struct eth_device *dev) +{ + int i; + + i = INL(dev, DE4X5_BMR); + mdelay(1); + OUTL(dev, i | BMR_SWR, DE4X5_BMR); + mdelay(1); + OUTL(dev, i, DE4X5_BMR); + mdelay(1); + + for (i = 0; i < 5; i++) { + INL(dev, DE4X5_BMR); + mdelay(10); + } + + mdelay(1); } -#define START_DE4X5(dev) {\ - s32 omr; \ - omr = INL(dev, DE4X5_OMR);\ - omr |= OMR_ST | OMR_SR;\ - OUTL(dev, omr, DE4X5_OMR); /* Enable the TX and/or RX */\ +static void start_de4x5(struct eth_device *dev) +{ + s32 omr; + + omr = INL(dev, DE4X5_OMR); + omr |= OMR_ST | OMR_SR; + OUTL(dev, omr, DE4X5_OMR); /* Enable the TX and/or RX */ } -#define STOP_DE4X5(dev) {\ - s32 omr; \ - omr = INL(dev, DE4X5_OMR);\ - omr &= ~(OMR_ST | OMR_SR);\ - OUTL(dev, omr, DE4X5_OMR); /* Disable the TX and/or RX */ \ +static void stop_de4x5(struct eth_device *dev) +{ + s32 omr; + + omr = INL(dev, DE4X5_OMR); + omr &= ~(OMR_ST | OMR_SR); + OUTL(dev, omr, DE4X5_OMR); /* Disable the TX and/or RX */ } #define NUM_RX_DESC PKTBUFSRX @@ -143,22 +170,6 @@ static int dc21x4x_send(struct eth_device *dev, void *packet, int length); static int dc21x4x_recv(struct eth_device *dev); static void dc21x4x_halt(struct eth_device *dev); -#if defined(CONFIG_E500) -#define phys_to_bus(a) (a) -#else -#define phys_to_bus(a) pci_phys_to_mem((pci_dev_t)dev->priv, a) -#endif - -static int INL(struct eth_device *dev, u_long addr) -{ - return le32_to_cpu(*(volatile u_long *)(addr + dev->iobase)); -} - -static void OUTL(struct eth_device *dev, int command, u_long addr) -{ - *(volatile u_long *)(addr + dev->iobase) = cpu_to_le32(command); -} - static struct pci_device_id supported[] = { { PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_TULIP_FAST }, { PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_21142 }, @@ -257,7 +268,7 @@ static int dc21x4x_init(struct eth_device *dev, bd_t *bis) /* Ensure we're not sleeping. */ pci_write_config_byte(devbusfn, PCI_CFDA_PSM, WAKEUP); - RESET_DE4X5(dev); + reset_de4x5(dev); if ((INL(dev, DE4X5_STS) & (STS_TS | STS_RS)) != 0) { printf("Error: Cannot reset ethernet controller.\n"); @@ -292,7 +303,7 @@ static int dc21x4x_init(struct eth_device *dev, bd_t *bis) OUTL(dev, phys_to_bus((u32)&rx_ring), DE4X5_RRBA); OUTL(dev, phys_to_bus((u32)&tx_ring), DE4X5_TRBA); - START_DE4X5(dev); + start_de4x5(dev); tx_new = 0; rx_new = 0; @@ -390,7 +401,7 @@ static void dc21x4x_halt(struct eth_device *dev) { int devbusfn = (int)dev->priv; - STOP_DE4X5(dev); + stop_de4x5(dev); OUTL(dev, 0, DE4X5_SICR); pci_write_config_byte(devbusfn, PCI_CFDA_PSM, SLEEP); -- cgit v1.3.1 From 3b7b9e2e71e7334198d696a03f3552bbc812ce9b Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sun, 19 Apr 2020 03:40:03 +0200 Subject: net: dc2114x: Clean up INL/OUTL functions Rename these functions to dc2114x_{inl,outl}(), use u32 values in them instead of plain signed integers as all those values are in fact register values and the driver code does bitwise operations on them. No functional change intended. Signed-off-by: Marek Vasut Cc: Joe Hershberger --- drivers/net/dc2114x.c | 48 ++++++++++++++++++++++++------------------------ 1 file changed, 24 insertions(+), 24 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/dc2114x.c b/drivers/net/dc2114x.c index a85fb76d53c..2bbe4e5d602 100644 --- a/drivers/net/dc2114x.c +++ b/drivers/net/dc2114x.c @@ -79,29 +79,29 @@ #define phys_to_bus(a) pci_phys_to_mem((pci_dev_t)dev->priv, a) #endif -static int INL(struct eth_device *dev, u_long addr) +static u32 dc2114x_inl(struct eth_device *dev, u32 addr) { - return le32_to_cpu(*(volatile u_long *)(addr + dev->iobase)); + return le32_to_cpu(*(volatile u32 *)(addr + dev->iobase)); } -static void OUTL(struct eth_device *dev, int command, u_long addr) +static void dc2114x_outl(struct eth_device *dev, u32 command, u32 addr) { - *(volatile u_long *)(addr + dev->iobase) = cpu_to_le32(command); + *(volatile u32 *)(addr + dev->iobase) = cpu_to_le32(command); } static void reset_de4x5(struct eth_device *dev) { - int i; + u32 i; - i = INL(dev, DE4X5_BMR); + i = dc2114x_inl(dev, DE4X5_BMR); mdelay(1); - OUTL(dev, i | BMR_SWR, DE4X5_BMR); + dc2114x_outl(dev, i | BMR_SWR, DE4X5_BMR); mdelay(1); - OUTL(dev, i, DE4X5_BMR); + dc2114x_outl(dev, i, DE4X5_BMR); mdelay(1); for (i = 0; i < 5; i++) { - INL(dev, DE4X5_BMR); + dc2114x_inl(dev, DE4X5_BMR); mdelay(10); } @@ -110,20 +110,20 @@ static void reset_de4x5(struct eth_device *dev) static void start_de4x5(struct eth_device *dev) { - s32 omr; + u32 omr; - omr = INL(dev, DE4X5_OMR); + omr = dc2114x_inl(dev, DE4X5_OMR); omr |= OMR_ST | OMR_SR; - OUTL(dev, omr, DE4X5_OMR); /* Enable the TX and/or RX */ + dc2114x_outl(dev, omr, DE4X5_OMR); /* Enable the TX and/or RX */ } static void stop_de4x5(struct eth_device *dev) { - s32 omr; + u32 omr; - omr = INL(dev, DE4X5_OMR); + omr = dc2114x_inl(dev, DE4X5_OMR); omr &= ~(OMR_ST | OMR_SR); - OUTL(dev, omr, DE4X5_OMR); /* Disable the TX and/or RX */ + dc2114x_outl(dev, omr, DE4X5_OMR); /* Disable the TX and/or RX */ } #define NUM_RX_DESC PKTBUFSRX @@ -270,12 +270,12 @@ static int dc21x4x_init(struct eth_device *dev, bd_t *bis) reset_de4x5(dev); - if ((INL(dev, DE4X5_STS) & (STS_TS | STS_RS)) != 0) { + if (dc2114x_inl(dev, DE4X5_STS) & (STS_TS | STS_RS)) { printf("Error: Cannot reset ethernet controller.\n"); return -1; } - OUTL(dev, OMR_SDP | OMR_PS | OMR_PM, DE4X5_OMR); + dc2114x_outl(dev, OMR_SDP | OMR_PS | OMR_PM, DE4X5_OMR); for (i = 0; i < NUM_RX_DESC; i++) { rx_ring[i].status = cpu_to_le32(R_OWN); @@ -300,8 +300,8 @@ static int dc21x4x_init(struct eth_device *dev, bd_t *bis) tx_ring[tx_ring_size - 1].des1 |= cpu_to_le32(TD_TER); /* Tell the adapter where the TX/RX rings are located. */ - OUTL(dev, phys_to_bus((u32)&rx_ring), DE4X5_RRBA); - OUTL(dev, phys_to_bus((u32)&tx_ring), DE4X5_TRBA); + dc2114x_outl(dev, phys_to_bus((u32)&rx_ring), DE4X5_RRBA); + dc2114x_outl(dev, phys_to_bus((u32)&tx_ring), DE4X5_TRBA); start_de4x5(dev); @@ -335,7 +335,7 @@ static int dc21x4x_send(struct eth_device *dev, void *packet, int length) tx_ring[tx_new].des1 = cpu_to_le32(TD_TER | TD_LS | TD_FS | length); tx_ring[tx_new].status = cpu_to_le32(T_OWN); - OUTL(dev, POLL_DEMAND, DE4X5_TPD); + dc2114x_outl(dev, POLL_DEMAND, DE4X5_TPD); for (i = 0; tx_ring[tx_new].status & cpu_to_le32(T_OWN); i++) { if (i < TOUT_LOOP) @@ -402,7 +402,7 @@ static void dc21x4x_halt(struct eth_device *dev) int devbusfn = (int)dev->priv; stop_de4x5(dev); - OUTL(dev, 0, DE4X5_SICR); + dc2114x_outl(dev, 0, DE4X5_SICR); pci_write_config_byte(devbusfn, PCI_CFDA_PSM, SLEEP); } @@ -433,7 +433,7 @@ static void send_setup_frame(struct eth_device *dev, bd_t *bis) tx_ring[tx_new].des1 = cpu_to_le32(TD_TER | TD_SET | SETUP_FRAME_LEN); tx_ring[tx_new].status = cpu_to_le32(T_OWN); - OUTL(dev, POLL_DEMAND, DE4X5_TPD); + dc2114x_outl(dev, POLL_DEMAND, DE4X5_TPD); for (i = 0; tx_ring[tx_new].status & cpu_to_le32(T_OWN); i++) { if (i < TOUT_LOOP) @@ -454,13 +454,13 @@ static void send_setup_frame(struct eth_device *dev, bd_t *bis) /* SROM Read and write routines. */ static void sendto_srom(struct eth_device *dev, u_int command, u_long addr) { - OUTL(dev, command, addr); + dc2114x_outl(dev, command, addr); udelay(1); } static int getfrom_srom(struct eth_device *dev, u_long addr) { - s32 tmp = INL(dev, addr); + u32 tmp = dc2114x_inl(dev, addr); udelay(1); return tmp; -- cgit v1.3.1 From dbe9c0c1457dad8446f1d9aac5f4cbd4ee6db060 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sun, 19 Apr 2020 04:00:49 +0200 Subject: net: dc2114x: Reorganize driver Move the functions in the driver around to better fit future DM conversion, drop function forward declarations. No functional change. Signed-off-by: Marek Vasut Cc: Joe Hershberger --- drivers/net/dc2114x.c | 736 ++++++++++++++++++++++++-------------------------- 1 file changed, 357 insertions(+), 379 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/dc2114x.c b/drivers/net/dc2114x.c index 2bbe4e5d602..9de9634cd51 100644 --- a/drivers/net/dc2114x.c +++ b/drivers/net/dc2114x.c @@ -79,6 +79,30 @@ #define phys_to_bus(a) pci_phys_to_mem((pci_dev_t)dev->priv, a) #endif +#define NUM_RX_DESC PKTBUFSRX +#define NUM_TX_DESC 1 /* Number of TX descriptors */ +#define RX_BUFF_SZ PKTSIZE_ALIGN + +#define TOUT_LOOP 1000000 + +#define SETUP_FRAME_LEN 192 + +struct de4x5_desc { + volatile s32 status; + u32 des1; + u32 buf; + u32 next; +}; + +/* RX and TX descriptor ring */ +static struct de4x5_desc rx_ring[NUM_RX_DESC] __aligned(32); +static struct de4x5_desc tx_ring[NUM_TX_DESC] __aligned(32); +static int rx_new; /* RX descriptor ring pointer */ +static int tx_new; /* TX descriptor ring pointer */ + +static char rx_ring_size; +static char tx_ring_size; + static u32 dc2114x_inl(struct eth_device *dev, u32 addr) { return le32_to_cpu(*(volatile u32 *)(addr + dev->iobase)); @@ -126,191 +150,267 @@ static void stop_de4x5(struct eth_device *dev) dc2114x_outl(dev, omr, DE4X5_OMR); /* Disable the TX and/or RX */ } -#define NUM_RX_DESC PKTBUFSRX -#define NUM_TX_DESC 1 /* Number of TX descriptors */ -#define RX_BUFF_SZ PKTSIZE_ALIGN - -#define TOUT_LOOP 1000000 +/* SROM Read and write routines. */ +static void sendto_srom(struct eth_device *dev, u_int command, u_long addr) +{ + dc2114x_outl(dev, command, addr); + udelay(1); +} -#define SETUP_FRAME_LEN 192 +static int getfrom_srom(struct eth_device *dev, u_long addr) +{ + u32 tmp = dc2114x_inl(dev, addr); -struct de4x5_desc { - volatile s32 status; - u32 des1; - u32 buf; - u32 next; -}; + udelay(1); + return tmp; +} -/* RX and TX descriptor ring */ -static struct de4x5_desc rx_ring[NUM_RX_DESC] __aligned(32); -static struct de4x5_desc tx_ring[NUM_TX_DESC] __aligned(32); -static int rx_new; /* RX descriptor ring pointer */ -static int tx_new; /* TX descriptor ring pointer */ +/* Note: this routine returns extra data bits for size detection. */ +static int do_read_eeprom(struct eth_device *dev, u_long ioaddr, int location, + int addr_len) +{ + int read_cmd = location | (SROM_READ_CMD << addr_len); + unsigned int retval = 0; + int i; -static char rx_ring_size; -static char tx_ring_size; + sendto_srom(dev, SROM_RD | SROM_SR, ioaddr); + sendto_srom(dev, SROM_RD | SROM_SR | DT_CS, ioaddr); -static void sendto_srom(struct eth_device *dev, u_int command, u_long addr); -static int getfrom_srom(struct eth_device *dev, u_long addr); -static int do_eeprom_cmd(struct eth_device *dev, u_long ioaddr, - int cmd, int cmd_len); -static int do_read_eeprom(struct eth_device *dev, u_long ioaddr, - int location, int addr_len); -#ifdef UPDATE_SROM -static int write_srom(struct eth_device *dev, u_long ioaddr, - int index, int new_value); -static void update_srom(struct eth_device *dev, bd_t *bis); +#ifdef DEBUG_SROM + printf(" EEPROM read at %d ", location); #endif -static int read_srom(struct eth_device *dev, u_long ioaddr, int index); -static void read_hw_addr(struct eth_device *dev, bd_t *bis); -static void send_setup_frame(struct eth_device *dev, bd_t *bis); -static int dc21x4x_init(struct eth_device *dev, bd_t *bis); -static int dc21x4x_send(struct eth_device *dev, void *packet, int length); -static int dc21x4x_recv(struct eth_device *dev); -static void dc21x4x_halt(struct eth_device *dev); + /* Shift the read command bits out. */ + for (i = 4 + addr_len; i >= 0; i--) { + short dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0; -static struct pci_device_id supported[] = { - { PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_TULIP_FAST }, - { PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_21142 }, - { } -}; + sendto_srom(dev, SROM_RD | SROM_SR | DT_CS | dataval, + ioaddr); + udelay(10); + sendto_srom(dev, SROM_RD | SROM_SR | DT_CS | dataval | DT_CLK, + ioaddr); + udelay(10); +#ifdef DEBUG_SROM2 + printf("%X", getfrom_srom(dev, ioaddr) & 15); +#endif + retval = (retval << 1) | + !!(getfrom_srom(dev, ioaddr) & EE_DATA_READ); + } -int dc21x4x_initialize(bd_t *bis) -{ - struct eth_device *dev; - unsigned short status; - unsigned char timer; - unsigned int iobase; - int card_number = 0; - pci_dev_t devbusfn; - unsigned int cfrv; - int idx = 0; + sendto_srom(dev, SROM_RD | SROM_SR | DT_CS, ioaddr); - while (1) { - devbusfn = pci_find_devices(supported, idx++); - if (devbusfn == -1) - break; +#ifdef DEBUG_SROM2 + printf(" :%X:", getfrom_srom(dev, ioaddr) & 15); +#endif - /* Get the chip configuration revision register. */ - pci_read_config_dword(devbusfn, PCI_REVISION_ID, &cfrv); + for (i = 16; i > 0; i--) { + sendto_srom(dev, SROM_RD | SROM_SR | DT_CS | DT_CLK, ioaddr); + udelay(10); +#ifdef DEBUG_SROM2 + printf("%X", getfrom_srom(dev, ioaddr) & 15); +#endif + retval = (retval << 1) | + !!(getfrom_srom(dev, ioaddr) & EE_DATA_READ); + sendto_srom(dev, SROM_RD | SROM_SR | DT_CS, ioaddr); + udelay(10); + } - if ((cfrv & CFRV_RN) < DC2114x_BRK) { - printf("Error: The chip is not DC21143.\n"); - continue; - } + /* Terminate the EEPROM access. */ + sendto_srom(dev, SROM_RD | SROM_SR, ioaddr); - pci_read_config_word(devbusfn, PCI_COMMAND, &status); - status |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER; - pci_write_config_word(devbusfn, PCI_COMMAND, status); +#ifdef DEBUG_SROM2 + printf(" EEPROM value at %d is %5.5x.\n", location, retval); +#endif - pci_read_config_word(devbusfn, PCI_COMMAND, &status); - if (!(status & PCI_COMMAND_MEMORY)) { - printf("Error: Can not enable MEMORY access.\n"); - continue; - } + return retval; +} - if (!(status & PCI_COMMAND_MASTER)) { - printf("Error: Can not enable Bus Mastering.\n"); - continue; - } +/* + * This executes a generic EEPROM command, typically a write or write + * enable. It returns the data output from the EEPROM, and thus may + * also be used for reads. + */ +static int do_eeprom_cmd(struct eth_device *dev, u_long ioaddr, int cmd, + int cmd_len) +{ + unsigned int retval = 0; - /* Check the latency timer for values >= 0x60. */ - pci_read_config_byte(devbusfn, PCI_LATENCY_TIMER, &timer); +#ifdef DEBUG_SROM + printf(" EEPROM op 0x%x: ", cmd); +#endif - if (timer < 0x60) { - pci_write_config_byte(devbusfn, PCI_LATENCY_TIMER, - 0x60); - } + sendto_srom(dev, SROM_RD | SROM_SR | DT_CS | DT_CLK, ioaddr); - /* read BAR for memory space access */ - pci_read_config_dword(devbusfn, PCI_BASE_ADDRESS_1, &iobase); - iobase &= PCI_BASE_ADDRESS_MEM_MASK; - debug("dc21x4x: DEC 21142 PCI Device @0x%x\n", iobase); + /* Shift the command bits out. */ + do { + short dataval = (cmd & BIT(cmd_len)) ? EE_WRITE_1 : EE_WRITE_0; - dev = (struct eth_device *)malloc(sizeof(*dev)); - if (!dev) { - printf("Can not allocalte memory of dc21x4x\n"); - break; - } + sendto_srom(dev, dataval, ioaddr); + udelay(10); - memset(dev, 0, sizeof(*dev)); +#ifdef DEBUG_SROM2 + printf("%X", getfrom_srom(dev, ioaddr) & 15); +#endif - sprintf(dev->name, "dc21x4x#%d", card_number); + sendto_srom(dev, dataval | DT_CLK, ioaddr); + udelay(10); + retval = (retval << 1) | + !!(getfrom_srom(dev, ioaddr) & EE_DATA_READ); + } while (--cmd_len >= 0); - dev->iobase = pci_mem_to_phys(devbusfn, iobase); - dev->priv = (void *)devbusfn; - dev->init = dc21x4x_init; - dev->halt = dc21x4x_halt; - dev->send = dc21x4x_send; - dev->recv = dc21x4x_recv; + sendto_srom(dev, SROM_RD | SROM_SR | DT_CS, ioaddr); - /* Ensure we're not sleeping. */ - pci_write_config_byte(devbusfn, PCI_CFDA_PSM, WAKEUP); + /* Terminate the EEPROM access. */ + sendto_srom(dev, SROM_RD | SROM_SR, ioaddr); - udelay(10 * 1000); +#ifdef DEBUG_SROM + printf(" EEPROM result is 0x%5.5x.\n", retval); +#endif - read_hw_addr(dev, bis); + return retval; +} - eth_register(dev); +static int read_srom(struct eth_device *dev, u_long ioaddr, int index) +{ + int ee_addr_size; - card_number++; - } + ee_addr_size = (do_read_eeprom(dev, ioaddr, 0xff, 8) & BIT(18)) ? 8 : 6; - return card_number; + return do_eeprom_cmd(dev, ioaddr, 0xffff | + (((SROM_READ_CMD << ee_addr_size) | index) << 16), + 3 + ee_addr_size + 16); } -static int dc21x4x_init(struct eth_device *dev, bd_t *bis) +#ifdef UPDATE_SROM +static int write_srom(struct eth_device *dev, u_long ioaddr, int index, + int new_value) { + unsigned short newval; + int ee_addr_size; int i; - int devbusfn = (int)dev->priv; - /* Ensure we're not sleeping. */ - pci_write_config_byte(devbusfn, PCI_CFDA_PSM, WAKEUP); + ee_addr_size = (do_read_eeprom(dev, ioaddr, 0xff, 8) & BIT(18)) ? 8 : 6; - reset_de4x5(dev); + udelay(10 * 1000); /* test-only */ - if (dc2114x_inl(dev, DE4X5_STS) & (STS_TS | STS_RS)) { - printf("Error: Cannot reset ethernet controller.\n"); - return -1; - } +#ifdef DEBUG_SROM + printf("ee_addr_size=%d.\n", ee_addr_size); + printf("Writing new entry 0x%4.4x to offset %d.\n", new_value, index); +#endif - dc2114x_outl(dev, OMR_SDP | OMR_PS | OMR_PM, DE4X5_OMR); + /* Enable programming modes. */ + do_eeprom_cmd(dev, ioaddr, 0x4f << (ee_addr_size - 4), + 3 + ee_addr_size); - for (i = 0; i < NUM_RX_DESC; i++) { - rx_ring[i].status = cpu_to_le32(R_OWN); - rx_ring[i].des1 = cpu_to_le32(RX_BUFF_SZ); - rx_ring[i].buf = - cpu_to_le32(phys_to_bus((u32)net_rx_packets[i])); - rx_ring[i].next = 0; + /* Do the actual write. */ + do_eeprom_cmd(dev, ioaddr, new_value | + (((SROM_WRITE_CMD << ee_addr_size) | index) << 16), + 3 + ee_addr_size + 16); + + /* Poll for write finished. */ + sendto_srom(dev, SROM_RD | SROM_SR | DT_CS, ioaddr); + for (i = 0; i < 10000; i++) { /* Typical 2000 ticks */ + if (getfrom_srom(dev, ioaddr) & EE_DATA_READ) + break; } - for (i = 0; i < NUM_TX_DESC; i++) { - tx_ring[i].status = 0; - tx_ring[i].des1 = 0; - tx_ring[i].buf = 0; - tx_ring[i].next = 0; +#ifdef DEBUG_SROM + printf(" Write finished after %d ticks.\n", i); +#endif + + /* Disable programming. */ + do_eeprom_cmd(dev, ioaddr, (0x40 << (ee_addr_size - 4)), + 3 + ee_addr_size); + + /* And read the result. */ + newval = do_eeprom_cmd(dev, ioaddr, + (((SROM_READ_CMD << ee_addr_size) | index) << 16) + | 0xffff, 3 + ee_addr_size + 16); +#ifdef DEBUG_SROM + printf(" New value at offset %d is %4.4x.\n", index, newval); +#endif + + return 1; +} + +static void update_srom(struct eth_device *dev, bd_t *bis) +{ + static unsigned short eeprom[0x40] = { + 0x140b, 0x6610, 0x0000, 0x0000, /* 00 */ + 0x0000, 0x0000, 0x0000, 0x0000, /* 04 */ + 0x00a3, 0x0103, 0x0000, 0x0000, /* 08 */ + 0x0000, 0x1f00, 0x0000, 0x0000, /* 0c */ + 0x0108, 0x038d, 0x0000, 0x0000, /* 10 */ + 0xe078, 0x0001, 0x0040, 0x0018, /* 14 */ + 0x0000, 0x0000, 0x0000, 0x0000, /* 18 */ + 0x0000, 0x0000, 0x0000, 0x0000, /* 1c */ + 0x0000, 0x0000, 0x0000, 0x0000, /* 20 */ + 0x0000, 0x0000, 0x0000, 0x0000, /* 24 */ + 0x0000, 0x0000, 0x0000, 0x0000, /* 28 */ + 0x0000, 0x0000, 0x0000, 0x0000, /* 2c */ + 0x0000, 0x0000, 0x0000, 0x0000, /* 30 */ + 0x0000, 0x0000, 0x0000, 0x0000, /* 34 */ + 0x0000, 0x0000, 0x0000, 0x0000, /* 38 */ + 0x0000, 0x0000, 0x0000, 0x4e07, /* 3c */ + }; + uchar enetaddr[6]; + int i; + + /* Ethernet Addr... */ + if (!eth_env_get_enetaddr("ethaddr", enetaddr)) + return; + + eeprom[0x0a] = (enetaddr[1] << 8) | enetaddr[0]; + eeprom[0x0b] = (enetaddr[3] << 8) | enetaddr[2]; + eeprom[0x0c] = (enetaddr[5] << 8) | enetaddr[4]; + + for (i = 0; i < 0x40; i++) + write_srom(dev, DE4X5_APROM, i, eeprom[i]); +} +#endif /* UPDATE_SROM */ + +static void send_setup_frame(struct eth_device *dev, bd_t *bis) +{ + char setup_frame[SETUP_FRAME_LEN]; + char *pa = &setup_frame[0]; + int i; + + memset(pa, 0xff, SETUP_FRAME_LEN); + + for (i = 0; i < ETH_ALEN; i++) { + *(pa + (i & 1)) = dev->enetaddr[i]; + if (i & 0x01) + pa += 4; } - rx_ring_size = NUM_RX_DESC; - tx_ring_size = NUM_TX_DESC; + for (i = 0; tx_ring[tx_new].status & cpu_to_le32(T_OWN); i++) { + if (i < TOUT_LOOP) + continue; - /* Write the end of list marker to the descriptor lists. */ - rx_ring[rx_ring_size - 1].des1 |= cpu_to_le32(RD_RER); - tx_ring[tx_ring_size - 1].des1 |= cpu_to_le32(TD_TER); + printf("%s: tx error buffer not ready\n", dev->name); + return; + } - /* Tell the adapter where the TX/RX rings are located. */ - dc2114x_outl(dev, phys_to_bus((u32)&rx_ring), DE4X5_RRBA); - dc2114x_outl(dev, phys_to_bus((u32)&tx_ring), DE4X5_TRBA); + tx_ring[tx_new].buf = cpu_to_le32(phys_to_bus((u32)&setup_frame[0])); + tx_ring[tx_new].des1 = cpu_to_le32(TD_TER | TD_SET | SETUP_FRAME_LEN); + tx_ring[tx_new].status = cpu_to_le32(T_OWN); - start_de4x5(dev); + dc2114x_outl(dev, POLL_DEMAND, DE4X5_TPD); - tx_new = 0; - rx_new = 0; + for (i = 0; tx_ring[tx_new].status & cpu_to_le32(T_OWN); i++) { + if (i < TOUT_LOOP) + continue; - send_setup_frame(dev, bis); + printf("%s: tx buffer not ready\n", dev->name); + return; + } - return 0; + if (le32_to_cpu(tx_ring[tx_new].status) != 0x7FFFFFFF) { + printf("TX error status2 = 0x%08X\n", + le32_to_cpu(tx_ring[tx_new].status)); + } + + tx_new = (tx_new + 1) % NUM_TX_DESC; } static int dc21x4x_send(struct eth_device *dev, void *packet, int length) @@ -397,297 +497,175 @@ static int dc21x4x_recv(struct eth_device *dev) return length; } -static void dc21x4x_halt(struct eth_device *dev) +static int dc21x4x_init(struct eth_device *dev, bd_t *bis) { + int i; int devbusfn = (int)dev->priv; - stop_de4x5(dev); - dc2114x_outl(dev, 0, DE4X5_SICR); + /* Ensure we're not sleeping. */ + pci_write_config_byte(devbusfn, PCI_CFDA_PSM, WAKEUP); - pci_write_config_byte(devbusfn, PCI_CFDA_PSM, SLEEP); -} + reset_de4x5(dev); -static void send_setup_frame(struct eth_device *dev, bd_t *bis) -{ - char setup_frame[SETUP_FRAME_LEN]; - char *pa = &setup_frame[0]; - int i; + if (dc2114x_inl(dev, DE4X5_STS) & (STS_TS | STS_RS)) { + printf("Error: Cannot reset ethernet controller.\n"); + return -1; + } - memset(pa, 0xff, SETUP_FRAME_LEN); + dc2114x_outl(dev, OMR_SDP | OMR_PS | OMR_PM, DE4X5_OMR); - for (i = 0; i < ETH_ALEN; i++) { - *(pa + (i & 1)) = dev->enetaddr[i]; - if (i & 0x01) - pa += 4; + for (i = 0; i < NUM_RX_DESC; i++) { + rx_ring[i].status = cpu_to_le32(R_OWN); + rx_ring[i].des1 = cpu_to_le32(RX_BUFF_SZ); + rx_ring[i].buf = + cpu_to_le32(phys_to_bus((u32)net_rx_packets[i])); + rx_ring[i].next = 0; } - for (i = 0; tx_ring[tx_new].status & cpu_to_le32(T_OWN); i++) { - if (i < TOUT_LOOP) - continue; - - printf("%s: tx error buffer not ready\n", dev->name); - return; + for (i = 0; i < NUM_TX_DESC; i++) { + tx_ring[i].status = 0; + tx_ring[i].des1 = 0; + tx_ring[i].buf = 0; + tx_ring[i].next = 0; } - tx_ring[tx_new].buf = cpu_to_le32(phys_to_bus((u32)&setup_frame[0])); - tx_ring[tx_new].des1 = cpu_to_le32(TD_TER | TD_SET | SETUP_FRAME_LEN); - tx_ring[tx_new].status = cpu_to_le32(T_OWN); + rx_ring_size = NUM_RX_DESC; + tx_ring_size = NUM_TX_DESC; - dc2114x_outl(dev, POLL_DEMAND, DE4X5_TPD); + /* Write the end of list marker to the descriptor lists. */ + rx_ring[rx_ring_size - 1].des1 |= cpu_to_le32(RD_RER); + tx_ring[tx_ring_size - 1].des1 |= cpu_to_le32(TD_TER); - for (i = 0; tx_ring[tx_new].status & cpu_to_le32(T_OWN); i++) { - if (i < TOUT_LOOP) - continue; + /* Tell the adapter where the TX/RX rings are located. */ + dc2114x_outl(dev, phys_to_bus((u32)&rx_ring), DE4X5_RRBA); + dc2114x_outl(dev, phys_to_bus((u32)&tx_ring), DE4X5_TRBA); - printf("%s: tx buffer not ready\n", dev->name); - return; - } + start_de4x5(dev); - if (le32_to_cpu(tx_ring[tx_new].status) != 0x7FFFFFFF) { - printf("TX error status2 = 0x%08X\n", - le32_to_cpu(tx_ring[tx_new].status)); - } + tx_new = 0; + rx_new = 0; - tx_new = (tx_new + 1) % NUM_TX_DESC; -} + send_setup_frame(dev, bis); -/* SROM Read and write routines. */ -static void sendto_srom(struct eth_device *dev, u_int command, u_long addr) -{ - dc2114x_outl(dev, command, addr); - udelay(1); + return 0; } -static int getfrom_srom(struct eth_device *dev, u_long addr) +static void dc21x4x_halt(struct eth_device *dev) { - u32 tmp = dc2114x_inl(dev, addr); + int devbusfn = (int)dev->priv; - udelay(1); - return tmp; + stop_de4x5(dev); + dc2114x_outl(dev, 0, DE4X5_SICR); + + pci_write_config_byte(devbusfn, PCI_CFDA_PSM, SLEEP); } -/* Note: this routine returns extra data bits for size detection. */ -static int do_read_eeprom(struct eth_device *dev, u_long ioaddr, int location, - int addr_len) +static void read_hw_addr(struct eth_device *dev, bd_t *bis) { - int read_cmd = location | (SROM_READ_CMD << addr_len); - unsigned int retval = 0; - int i; - - sendto_srom(dev, SROM_RD | SROM_SR, ioaddr); - sendto_srom(dev, SROM_RD | SROM_SR | DT_CS, ioaddr); - -#ifdef DEBUG_SROM - printf(" EEPROM read at %d ", location); -#endif - - /* Shift the read command bits out. */ - for (i = 4 + addr_len; i >= 0; i--) { - short dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0; + u_short tmp, *p = (u_short *)(&dev->enetaddr[0]); + int i, j = 0; - sendto_srom(dev, SROM_RD | SROM_SR | DT_CS | dataval, - ioaddr); - udelay(10); - sendto_srom(dev, SROM_RD | SROM_SR | DT_CS | dataval | DT_CLK, - ioaddr); - udelay(10); -#ifdef DEBUG_SROM2 - printf("%X", getfrom_srom(dev, ioaddr) & 15); -#endif - retval = (retval << 1) | - !!(getfrom_srom(dev, ioaddr) & EE_DATA_READ); + for (i = 0; i < (ETH_ALEN >> 1); i++) { + tmp = read_srom(dev, DE4X5_APROM, (SROM_HWADD >> 1) + i); + *p = le16_to_cpu(tmp); + j += *p++; } - sendto_srom(dev, SROM_RD | SROM_SR | DT_CS, ioaddr); - -#ifdef DEBUG_SROM2 - printf(" :%X:", getfrom_srom(dev, ioaddr) & 15); -#endif - - for (i = 16; i > 0; i--) { - sendto_srom(dev, SROM_RD | SROM_SR | DT_CS | DT_CLK, ioaddr); - udelay(10); -#ifdef DEBUG_SROM2 - printf("%X", getfrom_srom(dev, ioaddr) & 15); + if (!j || j == 0x2fffd) { + memset(dev->enetaddr, 0, ETH_ALEN); + debug("Warning: can't read HW address from SROM.\n"); +#ifdef UPDATE_SROM + update_srom(dev, bis); #endif - retval = (retval << 1) | - !!(getfrom_srom(dev, ioaddr) & EE_DATA_READ); - sendto_srom(dev, SROM_RD | SROM_SR | DT_CS, ioaddr); - udelay(10); } - - /* Terminate the EEPROM access. */ - sendto_srom(dev, SROM_RD | SROM_SR, ioaddr); - -#ifdef DEBUG_SROM2 - printf(" EEPROM value at %d is %5.5x.\n", location, retval); -#endif - - return retval; } -/* - * This executes a generic EEPROM command, typically a write or write - * enable. It returns the data output from the EEPROM, and thus may - * also be used for reads. - */ -static int do_eeprom_cmd(struct eth_device *dev, u_long ioaddr, int cmd, - int cmd_len) -{ - unsigned int retval = 0; - -#ifdef DEBUG_SROM - printf(" EEPROM op 0x%x: ", cmd); -#endif - - sendto_srom(dev, SROM_RD | SROM_SR | DT_CS | DT_CLK, ioaddr); - - /* Shift the command bits out. */ - do { - short dataval = (cmd & BIT(cmd_len)) ? EE_WRITE_1 : EE_WRITE_0; - - sendto_srom(dev, dataval, ioaddr); - udelay(10); - -#ifdef DEBUG_SROM2 - printf("%X", getfrom_srom(dev, ioaddr) & 15); -#endif - - sendto_srom(dev, dataval | DT_CLK, ioaddr); - udelay(10); - retval = (retval << 1) | - !!(getfrom_srom(dev, ioaddr) & EE_DATA_READ); - } while (--cmd_len >= 0); - - sendto_srom(dev, SROM_RD | SROM_SR | DT_CS, ioaddr); - - /* Terminate the EEPROM access. */ - sendto_srom(dev, SROM_RD | SROM_SR, ioaddr); - -#ifdef DEBUG_SROM - printf(" EEPROM result is 0x%5.5x.\n", retval); -#endif - - return retval; -} +static struct pci_device_id supported[] = { + { PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_TULIP_FAST }, + { PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_21142 }, + { } +}; -static int read_srom(struct eth_device *dev, u_long ioaddr, int index) +int dc21x4x_initialize(bd_t *bis) { - int ee_addr_size; - - ee_addr_size = (do_read_eeprom(dev, ioaddr, 0xff, 8) & BIT(18)) ? 8 : 6; + struct eth_device *dev; + unsigned short status; + unsigned char timer; + unsigned int iobase; + int card_number = 0; + pci_dev_t devbusfn; + unsigned int cfrv; + int idx = 0; - return do_eeprom_cmd(dev, ioaddr, 0xffff | - (((SROM_READ_CMD << ee_addr_size) | index) << 16), - 3 + ee_addr_size + 16); -} + while (1) { + devbusfn = pci_find_devices(supported, idx++); + if (devbusfn == -1) + break; -#ifdef UPDATE_SROM -static int write_srom(struct eth_device *dev, u_long ioaddr, int index, - int new_value) -{ - unsigned short newval; - int ee_addr_size; - int i; + /* Get the chip configuration revision register. */ + pci_read_config_dword(devbusfn, PCI_REVISION_ID, &cfrv); - ee_addr_size = (do_read_eeprom(dev, ioaddr, 0xff, 8) & BIT(18)) ? 8 : 6; + if ((cfrv & CFRV_RN) < DC2114x_BRK) { + printf("Error: The chip is not DC21143.\n"); + continue; + } - udelay(10 * 1000); /* test-only */ + pci_read_config_word(devbusfn, PCI_COMMAND, &status); + status |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER; + pci_write_config_word(devbusfn, PCI_COMMAND, status); -#ifdef DEBUG_SROM - printf("ee_addr_size=%d.\n", ee_addr_size); - printf("Writing new entry 0x%4.4x to offset %d.\n", new_value, index); -#endif + pci_read_config_word(devbusfn, PCI_COMMAND, &status); + if (!(status & PCI_COMMAND_MEMORY)) { + printf("Error: Can not enable MEMORY access.\n"); + continue; + } - /* Enable programming modes. */ - do_eeprom_cmd(dev, ioaddr, 0x4f << (ee_addr_size - 4), - 3 + ee_addr_size); + if (!(status & PCI_COMMAND_MASTER)) { + printf("Error: Can not enable Bus Mastering.\n"); + continue; + } - /* Do the actual write. */ - do_eeprom_cmd(dev, ioaddr, new_value | - (((SROM_WRITE_CMD << ee_addr_size) | index) << 16), - 3 + ee_addr_size + 16); + /* Check the latency timer for values >= 0x60. */ + pci_read_config_byte(devbusfn, PCI_LATENCY_TIMER, &timer); - /* Poll for write finished. */ - sendto_srom(dev, SROM_RD | SROM_SR | DT_CS, ioaddr); - for (i = 0; i < 10000; i++) { /* Typical 2000 ticks */ - if (getfrom_srom(dev, ioaddr) & EE_DATA_READ) - break; - } + if (timer < 0x60) { + pci_write_config_byte(devbusfn, PCI_LATENCY_TIMER, + 0x60); + } -#ifdef DEBUG_SROM - printf(" Write finished after %d ticks.\n", i); -#endif + /* read BAR for memory space access */ + pci_read_config_dword(devbusfn, PCI_BASE_ADDRESS_1, &iobase); + iobase &= PCI_BASE_ADDRESS_MEM_MASK; + debug("dc21x4x: DEC 21142 PCI Device @0x%x\n", iobase); - /* Disable programming. */ - do_eeprom_cmd(dev, ioaddr, (0x40 << (ee_addr_size - 4)), - 3 + ee_addr_size); + dev = (struct eth_device *)malloc(sizeof(*dev)); + if (!dev) { + printf("Can not allocalte memory of dc21x4x\n"); + break; + } - /* And read the result. */ - newval = do_eeprom_cmd(dev, ioaddr, - (((SROM_READ_CMD << ee_addr_size) | index) << 16) - | 0xffff, 3 + ee_addr_size + 16); -#ifdef DEBUG_SROM - printf(" New value at offset %d is %4.4x.\n", index, newval); -#endif + memset(dev, 0, sizeof(*dev)); - return 1; -} -#endif + sprintf(dev->name, "dc21x4x#%d", card_number); -static void read_hw_addr(struct eth_device *dev, bd_t *bis) -{ - u_short tmp, *p = (u_short *)(&dev->enetaddr[0]); - int i, j = 0; + dev->iobase = pci_mem_to_phys(devbusfn, iobase); + dev->priv = (void *)devbusfn; + dev->init = dc21x4x_init; + dev->halt = dc21x4x_halt; + dev->send = dc21x4x_send; + dev->recv = dc21x4x_recv; - for (i = 0; i < (ETH_ALEN >> 1); i++) { - tmp = read_srom(dev, DE4X5_APROM, (SROM_HWADD >> 1) + i); - *p = le16_to_cpu(tmp); - j += *p++; - } + /* Ensure we're not sleeping. */ + pci_write_config_byte(devbusfn, PCI_CFDA_PSM, WAKEUP); - if (!j || j == 0x2fffd) { - memset(dev->enetaddr, 0, ETH_ALEN); - debug("Warning: can't read HW address from SROM.\n"); -#ifdef UPDATE_SROM - update_srom(dev, bis); -#endif - } -} + udelay(10 * 1000); -#ifdef UPDATE_SROM -static void update_srom(struct eth_device *dev, bd_t *bis) -{ - static unsigned short eeprom[0x40] = { - 0x140b, 0x6610, 0x0000, 0x0000, /* 00 */ - 0x0000, 0x0000, 0x0000, 0x0000, /* 04 */ - 0x00a3, 0x0103, 0x0000, 0x0000, /* 08 */ - 0x0000, 0x1f00, 0x0000, 0x0000, /* 0c */ - 0x0108, 0x038d, 0x0000, 0x0000, /* 10 */ - 0xe078, 0x0001, 0x0040, 0x0018, /* 14 */ - 0x0000, 0x0000, 0x0000, 0x0000, /* 18 */ - 0x0000, 0x0000, 0x0000, 0x0000, /* 1c */ - 0x0000, 0x0000, 0x0000, 0x0000, /* 20 */ - 0x0000, 0x0000, 0x0000, 0x0000, /* 24 */ - 0x0000, 0x0000, 0x0000, 0x0000, /* 28 */ - 0x0000, 0x0000, 0x0000, 0x0000, /* 2c */ - 0x0000, 0x0000, 0x0000, 0x0000, /* 30 */ - 0x0000, 0x0000, 0x0000, 0x0000, /* 34 */ - 0x0000, 0x0000, 0x0000, 0x0000, /* 38 */ - 0x0000, 0x0000, 0x0000, 0x4e07, /* 3c */ - }; - uchar enetaddr[6]; - int i; + read_hw_addr(dev, bis); - /* Ethernet Addr... */ - if (!eth_env_get_enetaddr("ethaddr", enetaddr)) - return; + eth_register(dev); - eeprom[0x0a] = (enetaddr[1] << 8) | enetaddr[0]; - eeprom[0x0b] = (enetaddr[3] << 8) | enetaddr[2]; - eeprom[0x0c] = (enetaddr[5] << 8) | enetaddr[4]; + card_number++; + } - for (i = 0; i < 0x40; i++) - write_srom(dev, DE4X5_APROM, i, eeprom[i]); + return card_number; } -#endif /* UPDATE_SROM */ -- cgit v1.3.1 From c2abfca9be3a62a98c1a1b77a11cd01092c0160f Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sun, 19 Apr 2020 04:05:44 +0200 Subject: net: dc2114x: Switch DEBUG_SROM{,2} to debug_cond() Replace the adhoc debugging ifdeffery with debug_cond() and an internal SROM_DEBUG macro to select the debug level. Signed-off-by: Marek Vasut Cc: Joe Hershberger --- drivers/net/dc2114x.c | 57 +++++++++++++++++++-------------------------------- 1 file changed, 21 insertions(+), 36 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/dc2114x.c b/drivers/net/dc2114x.c index 9de9634cd51..d008696b0ff 100644 --- a/drivers/net/dc2114x.c +++ b/drivers/net/dc2114x.c @@ -7,8 +7,7 @@ #include #include -#undef DEBUG_SROM -#undef DEBUG_SROM2 +#define SROM_DLEVEL 0 #undef UPDATE_SROM @@ -176,9 +175,7 @@ static int do_read_eeprom(struct eth_device *dev, u_long ioaddr, int location, sendto_srom(dev, SROM_RD | SROM_SR, ioaddr); sendto_srom(dev, SROM_RD | SROM_SR | DT_CS, ioaddr); -#ifdef DEBUG_SROM - printf(" EEPROM read at %d ", location); -#endif + debug_cond(SROM_DLEVEL >= 1, " EEPROM read at %d ", location); /* Shift the read command bits out. */ for (i = 4 + addr_len; i >= 0; i--) { @@ -190,25 +187,21 @@ static int do_read_eeprom(struct eth_device *dev, u_long ioaddr, int location, sendto_srom(dev, SROM_RD | SROM_SR | DT_CS | dataval | DT_CLK, ioaddr); udelay(10); -#ifdef DEBUG_SROM2 - printf("%X", getfrom_srom(dev, ioaddr) & 15); -#endif + debug_cond(SROM_DLEVEL >= 2, "%X", + getfrom_srom(dev, ioaddr) & 15); retval = (retval << 1) | !!(getfrom_srom(dev, ioaddr) & EE_DATA_READ); } sendto_srom(dev, SROM_RD | SROM_SR | DT_CS, ioaddr); -#ifdef DEBUG_SROM2 - printf(" :%X:", getfrom_srom(dev, ioaddr) & 15); -#endif + debug_cond(SROM_DLEVEL >= 2, " :%X:", getfrom_srom(dev, ioaddr) & 15); for (i = 16; i > 0; i--) { sendto_srom(dev, SROM_RD | SROM_SR | DT_CS | DT_CLK, ioaddr); udelay(10); -#ifdef DEBUG_SROM2 - printf("%X", getfrom_srom(dev, ioaddr) & 15); -#endif + debug_cond(SROM_DLEVEL >= 2, "%X", + getfrom_srom(dev, ioaddr) & 15); retval = (retval << 1) | !!(getfrom_srom(dev, ioaddr) & EE_DATA_READ); sendto_srom(dev, SROM_RD | SROM_SR | DT_CS, ioaddr); @@ -218,9 +211,8 @@ static int do_read_eeprom(struct eth_device *dev, u_long ioaddr, int location, /* Terminate the EEPROM access. */ sendto_srom(dev, SROM_RD | SROM_SR, ioaddr); -#ifdef DEBUG_SROM2 - printf(" EEPROM value at %d is %5.5x.\n", location, retval); -#endif + debug_cond(SROM_DLEVEL >= 2, " EEPROM value at %d is %5.5x.\n", + location, retval); return retval; } @@ -235,9 +227,7 @@ static int do_eeprom_cmd(struct eth_device *dev, u_long ioaddr, int cmd, { unsigned int retval = 0; -#ifdef DEBUG_SROM - printf(" EEPROM op 0x%x: ", cmd); -#endif + debug_cond(SROM_DLEVEL >= 1, " EEPROM op 0x%x: ", cmd); sendto_srom(dev, SROM_RD | SROM_SR | DT_CS | DT_CLK, ioaddr); @@ -248,9 +238,8 @@ static int do_eeprom_cmd(struct eth_device *dev, u_long ioaddr, int cmd, sendto_srom(dev, dataval, ioaddr); udelay(10); -#ifdef DEBUG_SROM2 - printf("%X", getfrom_srom(dev, ioaddr) & 15); -#endif + debug_cond(SROM_DLEVEL >= 2, "%X", + getfrom_srom(dev, ioaddr) & 15); sendto_srom(dev, dataval | DT_CLK, ioaddr); udelay(10); @@ -263,9 +252,7 @@ static int do_eeprom_cmd(struct eth_device *dev, u_long ioaddr, int cmd, /* Terminate the EEPROM access. */ sendto_srom(dev, SROM_RD | SROM_SR, ioaddr); -#ifdef DEBUG_SROM - printf(" EEPROM result is 0x%5.5x.\n", retval); -#endif + debug_cond(SROM_DLEVEL >= 1, " EEPROM result is 0x%5.5x.\n", retval); return retval; } @@ -293,10 +280,10 @@ static int write_srom(struct eth_device *dev, u_long ioaddr, int index, udelay(10 * 1000); /* test-only */ -#ifdef DEBUG_SROM - printf("ee_addr_size=%d.\n", ee_addr_size); - printf("Writing new entry 0x%4.4x to offset %d.\n", new_value, index); -#endif + debug_cond(SROM_DLEVEL >= 1, "ee_addr_size=%d.\n", ee_addr_size); + debug_cond(SROM_DLEVEL >= 1, + "Writing new entry 0x%4.4x to offset %d.\n", + new_value, index); /* Enable programming modes. */ do_eeprom_cmd(dev, ioaddr, 0x4f << (ee_addr_size - 4), @@ -314,9 +301,7 @@ static int write_srom(struct eth_device *dev, u_long ioaddr, int index, break; } -#ifdef DEBUG_SROM - printf(" Write finished after %d ticks.\n", i); -#endif + debug_cond(SROM_DLEVEL >= 1, " Write finished after %d ticks.\n", i); /* Disable programming. */ do_eeprom_cmd(dev, ioaddr, (0x40 << (ee_addr_size - 4)), @@ -326,9 +311,9 @@ static int write_srom(struct eth_device *dev, u_long ioaddr, int index, newval = do_eeprom_cmd(dev, ioaddr, (((SROM_READ_CMD << ee_addr_size) | index) << 16) | 0xffff, 3 + ee_addr_size + 16); -#ifdef DEBUG_SROM - printf(" New value at offset %d is %4.4x.\n", index, newval); -#endif + + debug_cond(SROM_DLEVEL >= 1, " New value at offset %d is %4.4x.\n", + index, newval); return 1; } -- cgit v1.3.1 From 4332d8061785b697ae7bdf3945adb55ba4da696b Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Mon, 23 Mar 2020 02:02:57 +0100 Subject: net: dwc_eth_qos: Fully rewrite RX descriptor field 3 The RX descriptor field 3 should contain only OWN and BUF1V bits before being used for receiving data by the DMA engine. However, right now, if the descriptor was already used for receiving data and is being cleared, the field 3 is only modified and the aforementioned two bits are ORRed into the field. This could lead to a residual dirty bits being left in the field 3 from previous transfer, and it generally does. Fully set the field 3 instead to clear those residual dirty bits. Reviewed-by: Patrick Delaunay Signed-off-by: Marek Vasut Cc: Joe Hershberger Cc: Patrice Chotard Cc: Patrick Delaunay Cc: Ramon Fried Cc: Stephen Warren --- drivers/net/dwc_eth_qos.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/dwc_eth_qos.c b/drivers/net/dwc_eth_qos.c index 63f2086dece..4f245206910 100644 --- a/drivers/net/dwc_eth_qos.c +++ b/drivers/net/dwc_eth_qos.c @@ -1288,7 +1288,7 @@ static int eqos_start(struct udevice *dev) struct eqos_desc *rx_desc = &(eqos->rx_descs[i]); rx_desc->des0 = (u32)(ulong)(eqos->rx_dma_buf + (i * EQOS_MAX_PACKET_SIZE)); - rx_desc->des3 |= EQOS_DESC3_OWN | EQOS_DESC3_BUF1V; + rx_desc->des3 = EQOS_DESC3_OWN | EQOS_DESC3_BUF1V; } eqos->config->ops->eqos_flush_desc(eqos->descs); @@ -1482,7 +1482,7 @@ static int eqos_free_pkt(struct udevice *dev, uchar *packet, int length) * writes to the rest of the descriptor too. */ mb(); - rx_desc->des3 |= EQOS_DESC3_OWN | EQOS_DESC3_BUF1V; + rx_desc->des3 = EQOS_DESC3_OWN | EQOS_DESC3_BUF1V; eqos->config->ops->eqos_flush_desc(rx_desc); writel((ulong)rx_desc, &eqos->dma_regs->ch0_rxdesc_tail_pointer); -- cgit v1.3.1 From 83858d87954627af7a576ccc7c93034b055faa7b Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Mon, 23 Mar 2020 02:03:50 +0100 Subject: net: dwc_eth_qos: Correctly wrap around TX descriptor tail pointer This code programs the next descriptor in the TX descriptor ring into the hardware as the last valid TX descriptor. The problem is that if the currenty descriptor is the last one in the array, the code will not wrap around correctly and use TX descriptor 0 again, but instead will use TX descriptor at address right past the TX descriptor ring, which is the first descriptor in the RX ring. Fix this by adding the necessary wrap-around. Reviewed-by: Patrick Delaunay Signed-off-by: Marek Vasut Cc: Joe Hershberger Cc: Patrice Chotard Cc: Patrick Delaunay Cc: Ramon Fried Cc: Stephen Warren --- drivers/net/dwc_eth_qos.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/dwc_eth_qos.c b/drivers/net/dwc_eth_qos.c index 4f245206910..e2fb690a1c2 100644 --- a/drivers/net/dwc_eth_qos.c +++ b/drivers/net/dwc_eth_qos.c @@ -1419,7 +1419,8 @@ static int eqos_send(struct udevice *dev, void *packet, int length) tx_desc->des3 = EQOS_DESC3_OWN | EQOS_DESC3_FD | EQOS_DESC3_LD | length; eqos->config->ops->eqos_flush_desc(tx_desc); - writel((ulong)(tx_desc + 1), &eqos->dma_regs->ch0_txdesc_tail_pointer); + writel((ulong)(&(eqos->tx_descs[eqos->tx_desc_idx])), + &eqos->dma_regs->ch0_txdesc_tail_pointer); for (i = 0; i < 1000000; i++) { eqos->config->ops->eqos_inval_desc(tx_desc); -- cgit v1.3.1 From dd90c2e1ea0a7abdfa501e604523c23d6f77ffdd Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Mon, 23 Mar 2020 02:09:01 +0100 Subject: net: dwc_eth_qos: Flush the RX descriptors on init Currently the code only flushes the first RX descriptor, not every entry in the RX descriptor ring. Fix this, to make sure the DMA engine can pick the RX descriptors correctly. Reviewed-by: Patrick Delaunay Signed-off-by: Marek Vasut Cc: Joe Hershberger Cc: Patrice Chotard Cc: Patrick Delaunay Cc: Ramon Fried Cc: Stephen Warren --- drivers/net/dwc_eth_qos.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/dwc_eth_qos.c b/drivers/net/dwc_eth_qos.c index e2fb690a1c2..e33f3045fea 100644 --- a/drivers/net/dwc_eth_qos.c +++ b/drivers/net/dwc_eth_qos.c @@ -1289,8 +1289,8 @@ static int eqos_start(struct udevice *dev) rx_desc->des0 = (u32)(ulong)(eqos->rx_dma_buf + (i * EQOS_MAX_PACKET_SIZE)); rx_desc->des3 = EQOS_DESC3_OWN | EQOS_DESC3_BUF1V; + eqos->config->ops->eqos_flush_desc(rx_desc); } - eqos->config->ops->eqos_flush_desc(eqos->descs); writel(0, &eqos->dma_regs->ch0_txdesc_list_haddress); writel((ulong)eqos->tx_descs, &eqos->dma_regs->ch0_txdesc_list_address); -- cgit v1.3.1 From 738ee270fe17ea9e48fee8823eb356ed03656e7c Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Mon, 23 Mar 2020 02:09:21 +0100 Subject: net: dwc_eth_qos: Invalidate RX descriptor before reading The current code polls the RX desciptor ring for new packets by reading the RX descriptor status. This works by accident, as the RX descriptors are often in non-cacheable memory. However, the driver does support use of RX descriptors in cacheable memory. This patch adds a missing RX descriptor invalidation, which assures the CPU will read a fresh copy of the RX descriptor instead of a cached one. Reviewed-by: Patrick Delaunay Signed-off-by: Marek Vasut Cc: Joe Hershberger Cc: Patrice Chotard Cc: Patrick Delaunay Cc: Ramon Fried Cc: Stephen Warren --- drivers/net/dwc_eth_qos.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/net') diff --git a/drivers/net/dwc_eth_qos.c b/drivers/net/dwc_eth_qos.c index e33f3045fea..2b37cc3cded 100644 --- a/drivers/net/dwc_eth_qos.c +++ b/drivers/net/dwc_eth_qos.c @@ -1443,6 +1443,7 @@ static int eqos_recv(struct udevice *dev, int flags, uchar **packetp) debug("%s(dev=%p, flags=%x):\n", __func__, dev, flags); rx_desc = &(eqos->rx_descs[eqos->rx_desc_idx]); + eqos->config->ops->eqos_inval_desc(rx_desc); if (rx_desc->des3 & EQOS_DESC3_OWN) { debug("%s: RX packet not available\n", __func__); return -EAGAIN; -- cgit v1.3.1 From a83ca0c280dd41dda576d6a8f15a8534a84b782c Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Mon, 23 Mar 2020 02:09:55 +0100 Subject: net: dwc_eth_qos: Invalidate RX packet DMA buffer This patch prevents an issue where the RX packet might have been accessed by the CPU, which now has cached data from the packet in the caches and possibly various write buffers, and these data may be evicted from the caches into the DRAM while the buffer is also written by the DMA. By invalidating the buffer after the CPU accessed it and before the DMA populates the buffer, it is assured that the buffer will not be corrupted. Reviewed-by: Patrick Delaunay Signed-off-by: Marek Vasut Cc: Joe Hershberger Cc: Patrice Chotard Cc: Patrick Delaunay Cc: Ramon Fried Cc: Stephen Warren --- drivers/net/dwc_eth_qos.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/dwc_eth_qos.c b/drivers/net/dwc_eth_qos.c index 2b37cc3cded..a195fe5c275 100644 --- a/drivers/net/dwc_eth_qos.c +++ b/drivers/net/dwc_eth_qos.c @@ -1476,6 +1476,9 @@ static int eqos_free_pkt(struct udevice *dev, uchar *packet, int length) } rx_desc = &(eqos->rx_descs[eqos->rx_desc_idx]); + + eqos->config->ops->eqos_inval_buffer(packet, length); + rx_desc->des0 = (u32)(ulong)packet; rx_desc->des1 = 0; rx_desc->des2 = 0; @@ -1538,6 +1541,9 @@ static int eqos_probe_resources_core(struct udevice *dev) } debug("%s: rx_pkt=%p\n", __func__, eqos->rx_pkt); + eqos->config->ops->eqos_inval_buffer(eqos->rx_dma_buf, + EQOS_MAX_PACKET_SIZE * EQOS_DESCRIPTORS_RX); + debug("%s: OK\n", __func__); return 0; -- cgit v1.3.1 From 24891dd8d40d71c034023d2a037c97df1714393b Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Mon, 23 Mar 2020 02:11:46 +0100 Subject: net: dwc_eth_qos: Prevent DMA from writing updated RX DMA descriptor The DMA may attempt to write a DMA descriptor in the ring while it is being updated. By writing the DMA descriptor buffer address to 0, it is assured the DMA will not use such a buffer and the buffer can be updated without any interference. Reviewed-by: Patrick Delaunay Signed-off-by: Marek Vasut Cc: Joe Hershberger Cc: Patrice Chotard Cc: Patrick Delaunay Cc: Ramon Fried Cc: Stephen Warren --- drivers/net/dwc_eth_qos.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/dwc_eth_qos.c b/drivers/net/dwc_eth_qos.c index a195fe5c275..60dfd17a74d 100644 --- a/drivers/net/dwc_eth_qos.c +++ b/drivers/net/dwc_eth_qos.c @@ -1477,8 +1477,10 @@ static int eqos_free_pkt(struct udevice *dev, uchar *packet, int length) rx_desc = &(eqos->rx_descs[eqos->rx_desc_idx]); + rx_desc->des0 = 0; + mb(); + eqos->config->ops->eqos_flush_desc(rx_desc); eqos->config->ops->eqos_inval_buffer(packet, length); - rx_desc->des0 = (u32)(ulong)packet; rx_desc->des1 = 0; rx_desc->des2 = 0; -- cgit v1.3.1 From a5e66e515b0e6615d6e6fed91e20361d9a476831 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sun, 12 Apr 2020 20:47:26 +0200 Subject: net: rtl8139: Register macro cleanup Clean up the horrible register definitions in the RTL8139 driver. This does create a couple of checkpatch errors, but the driver is full of them anyway, and those will be cleaned up later. No functional change. Signed-off-by: Marek Vasut Cc: Joe Hershberger --- drivers/net/rtl8139.c | 263 +++++++++++++++++++++++++++++--------------------- 1 file changed, 152 insertions(+), 111 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/rtl8139.c b/drivers/net/rtl8139.c index bb59629f81c..9898f20c391 100644 --- a/drivers/net/rtl8139.c +++ b/drivers/net/rtl8139.c @@ -99,77 +99,96 @@ #define phys_to_bus(a) pci_phys_to_mem((pci_dev_t)dev->priv, a) /* Symbolic offsets to registers. */ -enum RTL8139_registers { - MAC0=0, /* Ethernet hardware address. */ - MAR0=8, /* Multicast filter. */ - TxStatus0=0x10, /* Transmit status (four 32bit registers). */ - TxAddr0=0x20, /* Tx descriptors (also four 32bit). */ - RxBuf=0x30, RxEarlyCnt=0x34, RxEarlyStatus=0x36, - ChipCmd=0x37, RxBufPtr=0x38, RxBufAddr=0x3A, - IntrMask=0x3C, IntrStatus=0x3E, - TxConfig=0x40, RxConfig=0x44, - Timer=0x48, /* general-purpose counter. */ - RxMissed=0x4C, /* 24 bits valid, write clears. */ - Cfg9346=0x50, Config0=0x51, Config1=0x52, - TimerIntrReg=0x54, /* intr if gp counter reaches this value */ - MediaStatus=0x58, - Config3=0x59, - MultiIntr=0x5C, - RevisionID=0x5E, /* revision of the RTL8139 chip */ - TxSummary=0x60, - MII_BMCR=0x62, MII_BMSR=0x64, NWayAdvert=0x66, NWayLPAR=0x68, - NWayExpansion=0x6A, - DisconnectCnt=0x6C, FalseCarrierCnt=0x6E, - NWayTestReg=0x70, - RxCnt=0x72, /* packet received counter */ - CSCR=0x74, /* chip status and configuration register */ - PhyParm1=0x78,TwisterParm=0x7c,PhyParm2=0x80, /* undocumented */ - /* from 0x84 onwards are a number of power management/wakeup frame - * definitions we will probably never need to know about. */ -}; - -enum ChipCmdBits { - CmdReset=0x10, CmdRxEnb=0x08, CmdTxEnb=0x04, RxBufEmpty=0x01, }; - -/* Interrupt register bits, using my own meaningful names. */ -enum IntrStatusBits { - PCIErr=0x8000, PCSTimeout=0x4000, CableLenChange= 0x2000, - RxFIFOOver=0x40, RxUnderrun=0x20, RxOverflow=0x10, - TxErr=0x08, TxOK=0x04, RxErr=0x02, RxOK=0x01, -}; -enum TxStatusBits { - TxHostOwns=0x2000, TxUnderrun=0x4000, TxStatOK=0x8000, - TxOutOfWindow=0x20000000, TxAborted=0x40000000, - TxCarrierLost=0x80000000, -}; -enum RxStatusBits { - RxMulticast=0x8000, RxPhysical=0x4000, RxBroadcast=0x2000, - RxBadSymbol=0x0020, RxRunt=0x0010, RxTooLong=0x0008, RxCRCErr=0x0004, - RxBadAlign=0x0002, RxStatusOK=0x0001, -}; - -enum MediaStatusBits { - MSRTxFlowEnable=0x80, MSRRxFlowEnable=0x40, MSRSpeed10=0x08, - MSRLinkFail=0x04, MSRRxPauseFlag=0x02, MSRTxPauseFlag=0x01, -}; - -enum MIIBMCRBits { - BMCRReset=0x8000, BMCRSpeed100=0x2000, BMCRNWayEnable=0x1000, - BMCRRestartNWay=0x0200, BMCRDuplex=0x0100, -}; - -enum CSCRBits { - CSCR_LinkOKBit=0x0400, CSCR_LinkChangeBit=0x0800, - CSCR_LinkStatusBits=0x0f000, CSCR_LinkDownOffCmd=0x003c0, - CSCR_LinkDownCmd=0x0f3c0, -}; +/* Ethernet hardware address. */ +#define RTL_REG_MAC0 0x00 +/* Multicast filter. */ +#define RTL_REG_MAR0 0x08 +/* Transmit status (four 32bit registers). */ +#define RTL_REG_TXSTATUS0 0x10 +/* Tx descriptors (also four 32bit). */ +#define RTL_REG_TXADDR0 0x20 +#define RTL_REG_RXBUF 0x30 +#define RTL_REG_RXEARLYCNT 0x34 +#define RTL_REG_RXEARLYSTATUS 0x36 +#define RTL_REG_CHIPCMD 0x37 +#define RTL_REG_CHIPCMD_CMDRESET BIT(4) +#define RTL_REG_CHIPCMD_CMDRXENB BIT(3) +#define RTL_REG_CHIPCMD_CMDTXENB BIT(2) +#define RTL_REG_CHIPCMD_RXBUFEMPTY BIT(0) +#define RTL_REG_RXBUFPTR 0x38 +#define RTL_REG_RXBUFADDR 0x3A +#define RTL_REG_INTRMASK 0x3C +#define RTL_REG_INTRSTATUS 0x3E +#define RTL_REG_INTRSTATUS_PCIERR BIT(15) +#define RTL_REG_INTRSTATUS_PCSTIMEOUT BIT(14) +#define RTL_REG_INTRSTATUS_CABLELENCHANGE BIT(13) +#define RTL_REG_INTRSTATUS_RXFIFOOVER BIT(6) +#define RTL_REG_INTRSTATUS_RXUNDERRUN BIT(5) +#define RTL_REG_INTRSTATUS_RXOVERFLOW BIT(4) +#define RTL_REG_INTRSTATUS_TXERR BIT(3) +#define RTL_REG_INTRSTATUS_TXOK BIT(2) +#define RTL_REG_INTRSTATUS_RXERR BIT(1) +#define RTL_REG_INTRSTATUS_RXOK BIT(0) +#define RTL_REG_TXCONFIG 0x40 +#define RTL_REG_RXCONFIG 0x44 +#define RTL_REG_RXCONFIG_RXCFGWRAP BIT(7) +#define RTL_REG_RXCONFIG_ACCEPTERR BIT(5) +#define RTL_REG_RXCONFIG_ACCEPTRUNT BIT(4) +#define RTL_REG_RXCONFIG_ACCEPTBROADCAST BIT(3) +#define RTL_REG_RXCONFIG_ACCEPTMULTICAST BIT(2) +#define RTL_REG_RXCONFIG_ACCEPTMYPHYS BIT(1) +#define RTL_REG_RXCONFIG_ACCEPTALLPHYS BIT(0) +/* general-purpose counter. */ +#define RTL_REG_TIMER 0x48 +/* 24 bits valid, write clears. */ +#define RTL_REG_RXMISSED 0x4C +#define RTL_REG_CFG9346 0x50 +#define RTL_REG_CONFIG0 0x51 +#define RTL_REG_CONFIG1 0x52 +/* intr if gp counter reaches this value */ +#define RTL_REG_TIMERINTRREG 0x54 +#define RTL_REG_MEDIASTATUS 0x58 +#define RTL_REG_MEDIASTATUS_MSRTXFLOWENABLE BIT(7) +#define RTL_REG_MEDIASTATUS_MSRRXFLOWENABLE BIT(6) +#define RTL_REG_MEDIASTATUS_MSRSPEED10 BIT(3) +#define RTL_REG_MEDIASTATUS_MSRLINKFAIL BIT(2) +#define RTL_REG_MEDIASTATUS_MSRRXPAUSEFLAG BIT(1) +#define RTL_REG_MEDIASTATUS_MSRTXPAUSEFLAG BIT(0) +#define RTL_REG_CONFIG3 0x59 +#define RTL_REG_MULTIINTR 0x5C +/* revision of the RTL8139 chip */ +#define RTL_REG_REVISIONID 0x5E +#define RTL_REG_TXSUMMARY 0x60 +#define RTL_REG_MII_BMCR 0x62 +#define RTL_REG_MII_BMSR 0x64 +#define RTL_REG_NWAYADVERT 0x66 +#define RTL_REG_NWAYLPAR 0x68 +#define RTL_REG_NWAYEXPANSION 0x6A +#define RTL_REG_DISCONNECTCNT 0x6C +#define RTL_REG_FALSECARRIERCNT 0x6E +#define RTL_REG_NWAYTESTREG 0x70 +/* packet received counter */ +#define RTL_REG_RXCNT 0x72 +/* chip status and configuration register */ +#define RTL_REG_CSCR 0x74 +#define RTL_REG_PHYPARM1 0x78 +#define RTL_REG_TWISTERPARM 0x7c +/* undocumented */ +#define RTL_REG_PHYPARM2 0x80 +/* + * from 0x84 onwards are a number of power management/wakeup frame + * definitions we will probably never need to know about. + */ -/* Bits in RxConfig. */ -enum rx_mode_bits { - RxCfgWrap=0x80, - AcceptErr=0x20, AcceptRunt=0x10, AcceptBroadcast=0x08, - AcceptMulticast=0x04, AcceptMyPhys=0x02, AcceptAllPhys=0x01, -}; +#define RTL_STS_RXMULTICAST BIT(15) +#define RTL_STS_RXPHYSICAL BIT(14) +#define RTL_STS_RXBROADCAST BIT(13) +#define RTL_STS_RXBADSYMBOL BIT(5) +#define RTL_STS_RXRUNT BIT(4) +#define RTL_STS_RXTOOLONG BIT(3) +#define RTL_STS_RXCRCERR BIT(2) +#define RTL_STS_RXBADALIGN BIT(1) +#define RTL_STS_RXSTATUSOK BIT(0) static int ioaddr; static unsigned int cur_rx,cur_tx; @@ -251,7 +270,7 @@ static int rtl8139_probe(struct eth_device *dev, bd_t *bis) ioaddr = dev->iobase; /* Bring the chip out of low-power mode. */ - outb(0x00, ioaddr + Config1); + outb(0x00, ioaddr + RTL_REG_CONFIG1); addr_len = read_eeprom(0,8) == 0x8129 ? 8 : 6; for (i = 0; i < 3; i++) @@ -259,7 +278,7 @@ static int rtl8139_probe(struct eth_device *dev, bd_t *bis) rtl_reset(dev); - if (inb(ioaddr + MediaStatus) & MSRLinkFail) { + if (inb(ioaddr + RTL_REG_MEDIASTATUS) & RTL_REG_MEDIASTATUS_MSRLINKFAIL) { printf("Cable not connected or other link failure\n"); return -1 ; } @@ -286,15 +305,15 @@ static int rtl8139_probe(struct eth_device *dev, bd_t *bis) #define eeprom_delay() inl(ee_addr) /* The EEPROM commands include the alway-set leading bit. */ -#define EE_WRITE_CMD (5) -#define EE_READ_CMD (6) -#define EE_ERASE_CMD (7) +#define EE_WRITE_CMD 5 +#define EE_READ_CMD 6 +#define EE_ERASE_CMD 7 static int read_eeprom(int location, int addr_len) { int i; unsigned int retval = 0; - long ee_addr = ioaddr + Cfg9346; + long ee_addr = ioaddr + RTL_REG_CFG9346; int read_cmd = location | (EE_READ_CMD << addr_len); outb(EE_ENB & ~EE_CS, ee_addr); @@ -335,41 +354,46 @@ static void set_rx_mode(struct eth_device *dev) { unsigned int mc_filter[2]; int rx_mode; /* !IFF_PROMISC */ - rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys; + rx_mode = RTL_REG_RXCONFIG_ACCEPTBROADCAST | + RTL_REG_RXCONFIG_ACCEPTMULTICAST | + RTL_REG_RXCONFIG_ACCEPTMYPHYS; mc_filter[1] = mc_filter[0] = 0xffffffff; - outl(rtl8139_rx_config | rx_mode, ioaddr + RxConfig); + outl(rtl8139_rx_config | rx_mode, ioaddr + RTL_REG_RXCONFIG); - outl(mc_filter[0], ioaddr + MAR0 + 0); - outl(mc_filter[1], ioaddr + MAR0 + 4); + outl(mc_filter[0], ioaddr + RTL_REG_MAR0 + 0); + outl(mc_filter[1], ioaddr + RTL_REG_MAR0 + 4); } static void rtl_reset(struct eth_device *dev) { int i; - outb(CmdReset, ioaddr + ChipCmd); + outb(RTL_REG_CHIPCMD_CMDRESET, ioaddr + RTL_REG_CHIPCMD); cur_rx = 0; cur_tx = 0; /* Give the chip 10ms to finish the reset. */ for (i=0; i<100; ++i){ - if ((inb(ioaddr + ChipCmd) & CmdReset) == 0) break; + if ((inb(ioaddr + RTL_REG_CHIPCMD) & + RTL_REG_CHIPCMD_CMDRESET) == 0) + break; udelay (100); /* wait 100us */ } for (i = 0; i < ETH_ALEN; i++) - outb(dev->enetaddr[i], ioaddr + MAC0 + i); + outb(dev->enetaddr[i], ioaddr + RTL_REG_MAC0 + i); /* Must enable Tx/Rx before setting transfer thresholds! */ - outb(CmdRxEnb | CmdTxEnb, ioaddr + ChipCmd); + outb(RTL_REG_CHIPCMD_CMDRXENB | RTL_REG_CHIPCMD_CMDTXENB, + ioaddr + RTL_REG_CHIPCMD); outl((RX_FIFO_THRESH<<13) | (RX_BUF_LEN_IDX<<11) | (RX_DMA_BURST<<8), - ioaddr + RxConfig); /* accept no frames yet! */ - outl((TX_DMA_BURST<<8)|0x03000000, ioaddr + TxConfig); + ioaddr + RTL_REG_RXCONFIG); /* accept no frames yet! */ + outl((TX_DMA_BURST<<8)|0x03000000, ioaddr + RTL_REG_TXCONFIG); - /* The Linux driver changes Config1 here to use a different LED pattern + /* The Linux driver changes RTL_REG_CONFIG1 here to use a different LED pattern * for half duplex or full/autodetect duplex (for full/autodetect, the * outputs are TX/RX, Link10/100, FULL, while for half duplex it uses * TX/RX, Link100, Link10). This is messy, because it doesn't match @@ -380,24 +404,25 @@ static void rtl_reset(struct eth_device *dev) debug_cond(DEBUG_RX, "rx ring address is %lX\n",(unsigned long)rx_ring); flush_cache((unsigned long)rx_ring, RX_BUF_LEN); - outl(phys_to_bus((int)rx_ring), ioaddr + RxBuf); + outl(phys_to_bus((int)rx_ring), ioaddr + RTL_REG_RXBUF); - /* If we add multicast support, the MAR0 register would have to be + /* If we add multicast support, the RTL_REG_MAR0 register would have to be * initialized to 0xffffffffffffffff (two 32 bit accesses). Etherboot * only needs broadcast (for ARP/RARP/BOOTP/DHCP) and unicast. */ - outb(CmdRxEnb | CmdTxEnb, ioaddr + ChipCmd); + outb(RTL_REG_CHIPCMD_CMDRXENB | RTL_REG_CHIPCMD_CMDTXENB, + ioaddr + RTL_REG_CHIPCMD); - outl(rtl8139_rx_config, ioaddr + RxConfig); + outl(rtl8139_rx_config, ioaddr + RTL_REG_RXCONFIG); /* Start the chip's Tx and Rx process. */ - outl(0, ioaddr + RxMissed); + outl(0, ioaddr + RTL_REG_RXMISSED); /* set_rx_mode */ set_rx_mode(dev); /* Disable all known interrupts by setting the interrupt mask. */ - outw(0, ioaddr + IntrMask); + outw(0, ioaddr + RTL_REG_INTRMASK); } static int rtl_transmit(struct eth_device *dev, void *packet, int length) @@ -420,23 +445,32 @@ static int rtl_transmit(struct eth_device *dev, void *packet, int length) } flush_cache((unsigned long)tx_buffer, length); - outl(phys_to_bus((int)tx_buffer), ioaddr + TxAddr0 + cur_tx*4); + outl(phys_to_bus((int)tx_buffer), ioaddr + RTL_REG_TXADDR0 + cur_tx*4); outl(((TX_FIFO_THRESH<<11) & 0x003f0000) | len, - ioaddr + TxStatus0 + cur_tx*4); + ioaddr + RTL_REG_TXSTATUS0 + cur_tx*4); do { - status = inw(ioaddr + IntrStatus); - /* Only acknlowledge interrupt sources we can properly handle - * here - the RxOverflow/RxFIFOOver MUST be handled in the - * rtl_poll() function. */ - outw(status & (TxOK | TxErr | PCIErr), ioaddr + IntrStatus); - if ((status & (TxOK | TxErr | PCIErr)) != 0) break; + status = inw(ioaddr + RTL_REG_INTRSTATUS); + /* + * Only acknlowledge interrupt sources we can properly + * handle here - the RTL_REG_INTRSTATUS_RXOVERFLOW/ + * RTL_REG_INTRSTATUS_RXFIFOOVER MUST be handled in the + * rtl_poll() function. + */ + outw(status & (RTL_REG_INTRSTATUS_TXOK | + RTL_REG_INTRSTATUS_TXERR | + RTL_REG_INTRSTATUS_PCIERR), + ioaddr + RTL_REG_INTRSTATUS); + if ((status & (RTL_REG_INTRSTATUS_TXOK | + RTL_REG_INTRSTATUS_TXERR | + RTL_REG_INTRSTATUS_PCIERR)) != 0) + break; udelay(10); } while (i++ < RTL_TIMEOUT); - txstatus = inl(ioaddr + TxStatus0 + cur_tx*4); + txstatus = inl(ioaddr + RTL_REG_TXSTATUS0 + cur_tx*4); - if (status & TxOK) { + if (status & RTL_REG_INTRSTATUS_TXOK) { cur_tx = (cur_tx + 1) % NUM_TX_DESC; debug_cond(DEBUG_TX, @@ -465,13 +499,16 @@ static int rtl_poll(struct eth_device *dev) ioaddr = dev->iobase; - if (inb(ioaddr + ChipCmd) & RxBufEmpty) { + if (inb(ioaddr + RTL_REG_CHIPCMD) & RTL_REG_CHIPCMD_RXBUFEMPTY) { return 0; } - status = inw(ioaddr + IntrStatus); + status = inw(ioaddr + RTL_REG_INTRSTATUS); /* See below for the rest of the interrupt acknowledges. */ - outw(status & ~(RxFIFOOver | RxOverflow | RxOK), ioaddr + IntrStatus); + outw(status & ~(RTL_REG_INTRSTATUS_RXFIFOOVER | + RTL_REG_INTRSTATUS_RXOVERFLOW | + RTL_REG_INTRSTATUS_RXOK), + ioaddr + RTL_REG_INTRSTATUS); debug_cond(DEBUG_RX, "rtl_poll: int %hX ", status); @@ -481,7 +518,9 @@ static int rtl_poll(struct eth_device *dev) rx_size = rx_status >> 16; rx_status &= 0xffff; - if ((rx_status & (RxBadSymbol|RxRunt|RxTooLong|RxCRCErr|RxBadAlign)) || + if ((rx_status & (RTL_STS_RXBADSYMBOL | RTL_STS_RXRUNT | + RTL_STS_RXTOOLONG | RTL_STS_RXCRCERR | + RTL_STS_RXBADALIGN)) || (rx_size < ETH_ZLEN) || (rx_size > ETH_FRAME_LEN + 4)) { printf("rx error %hX\n", rx_status); rtl_reset(dev); /* this clears all interrupts still pending */ @@ -507,11 +546,13 @@ static int rtl_poll(struct eth_device *dev) flush_cache((unsigned long)rx_ring, RX_BUF_LEN); cur_rx = (cur_rx + rx_size + 4 + 3) & ~3; - outw(cur_rx - 16, ioaddr + RxBufPtr); + outw(cur_rx - 16, ioaddr + RTL_REG_RXBUFPTR); /* See RTL8139 Programming Guide V0.1 for the official handling of * Rx overflow situations. The document itself contains basically no * usable information, except for a few exception handling rules. */ - outw(status & (RxFIFOOver | RxOverflow | RxOK), ioaddr + IntrStatus); + outw(status & (RTL_REG_INTRSTATUS_RXFIFOOVER | + RTL_REG_INTRSTATUS_RXOVERFLOW | + RTL_REG_INTRSTATUS_RXOK), ioaddr + RTL_REG_INTRSTATUS); return length; } @@ -522,11 +563,11 @@ static void rtl_disable(struct eth_device *dev) ioaddr = dev->iobase; /* reset the chip */ - outb(CmdReset, ioaddr + ChipCmd); + outb(RTL_REG_CHIPCMD_CMDRESET, ioaddr + RTL_REG_CHIPCMD); /* Give the chip 10ms to finish the reset. */ for (i=0; i<100; ++i){ - if ((inb(ioaddr + ChipCmd) & CmdReset) == 0) break; + if ((inb(ioaddr + RTL_REG_CHIPCMD) & RTL_REG_CHIPCMD_CMDRESET) == 0) break; udelay (100); /* wait 100us */ } } -- cgit v1.3.1 From f80f4e4d729252eb6124e1afb5dde9f74c35c994 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sun, 12 Apr 2020 21:20:31 +0200 Subject: net: rtl8139: Rework eeprom_delay() macro The macro assumes ee_addr variable to be present when it's being used. Rework the macro into a function instead and pass it an argument specifying the register base address, to make it future proof for DM conversion. Signed-off-by: Marek Vasut Cc: Joe Hershberger --- drivers/net/rtl8139.c | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/rtl8139.c b/drivers/net/rtl8139.c index 9898f20c391..ff014ade88b 100644 --- a/drivers/net/rtl8139.c +++ b/drivers/net/rtl8139.c @@ -73,6 +73,7 @@ #include #include +#include #include #include #include @@ -297,18 +298,20 @@ static int rtl8139_probe(struct eth_device *dev, bd_t *bis) #define EE_DATA_READ 0x01 /* EEPROM chip data out. */ #define EE_ENB (0x80 | EE_CS) -/* - Delay between EEPROM clock transitions. - No extra delay is needed with 33MHz PCI, but 66MHz may change this. -*/ - -#define eeprom_delay() inl(ee_addr) - /* The EEPROM commands include the alway-set leading bit. */ #define EE_WRITE_CMD 5 #define EE_READ_CMD 6 #define EE_ERASE_CMD 7 +static void rtl8139_eeprom_delay(uintptr_t regbase) +{ + /* + * Delay between EEPROM clock transitions. + * No extra delay is needed with 33MHz PCI, but 66MHz may change this. + */ + inl(regbase + RTL_REG_CFG9346); +} + static int read_eeprom(int location, int addr_len) { int i; @@ -318,30 +321,30 @@ static int read_eeprom(int location, int addr_len) outb(EE_ENB & ~EE_CS, ee_addr); outb(EE_ENB, ee_addr); - eeprom_delay(); + rtl8139_eeprom_delay(ioaddr); /* Shift the read command bits out. */ for (i = 4 + addr_len; i >= 0; i--) { int dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0; outb(EE_ENB | dataval, ee_addr); - eeprom_delay(); + rtl8139_eeprom_delay(ioaddr); outb(EE_ENB | dataval | EE_SHIFT_CLK, ee_addr); - eeprom_delay(); + rtl8139_eeprom_delay(ioaddr); } outb(EE_ENB, ee_addr); - eeprom_delay(); + rtl8139_eeprom_delay(ioaddr); for (i = 16; i > 0; i--) { outb(EE_ENB | EE_SHIFT_CLK, ee_addr); - eeprom_delay(); + rtl8139_eeprom_delay(ioaddr); retval = (retval << 1) | ((inb(ee_addr) & EE_DATA_READ) ? 1 : 0); outb(EE_ENB, ee_addr); - eeprom_delay(); + rtl8139_eeprom_delay(ioaddr); } /* Terminate the EEPROM access. */ outb(~EE_CS, ee_addr); - eeprom_delay(); + rtl8139_eeprom_delay(ioaddr); return retval; } -- cgit v1.3.1 From 17dc95e5277cdbad1281b6b5605b1eef74729463 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sun, 12 Apr 2020 21:28:30 +0200 Subject: net: rtl8139: Minor cleanup of read_eeprom() Rename the function to rtl8139_read_eeprom() to keep the naming consistent, keep the variables sorted in reverse xmas tree. No functional change. Signed-off-by: Marek Vasut Cc: Joe Hershberger --- drivers/net/rtl8139.c | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/rtl8139.c b/drivers/net/rtl8139.c index ff014ade88b..90e9f1272c3 100644 --- a/drivers/net/rtl8139.c +++ b/drivers/net/rtl8139.c @@ -199,7 +199,7 @@ static unsigned char tx_buffer[TX_BUF_SIZE] __attribute__((aligned(4))); static unsigned char rx_ring[RX_BUF_LEN+16] __attribute__((aligned(4))); static int rtl8139_probe(struct eth_device *dev, bd_t *bis); -static int read_eeprom(int location, int addr_len); +static int rtl8139_read_eeprom(unsigned int location, unsigned int addr_len); static void rtl_reset(struct eth_device *dev); static int rtl_transmit(struct eth_device *dev, void *packet, int length); static int rtl_poll(struct eth_device *dev); @@ -273,9 +273,9 @@ static int rtl8139_probe(struct eth_device *dev, bd_t *bis) /* Bring the chip out of low-power mode. */ outb(0x00, ioaddr + RTL_REG_CONFIG1); - addr_len = read_eeprom(0,8) == 0x8129 ? 8 : 6; + addr_len = rtl8139_read_eeprom(0,8) == 0x8129 ? 8 : 6; for (i = 0; i < 3; i++) - *ap++ = le16_to_cpu (read_eeprom(i + 7, addr_len)); + *ap++ = le16_to_cpu (rtl8139_read_eeprom(i + 7, addr_len)); rtl_reset(dev); @@ -312,12 +312,13 @@ static void rtl8139_eeprom_delay(uintptr_t regbase) inl(regbase + RTL_REG_CFG9346); } -static int read_eeprom(int location, int addr_len) +static int rtl8139_read_eeprom(unsigned int location, unsigned int addr_len) { - int i; + unsigned int read_cmd = location | (EE_READ_CMD << addr_len); + uintptr_t ee_addr = ioaddr + RTL_REG_CFG9346; unsigned int retval = 0; - long ee_addr = ioaddr + RTL_REG_CFG9346; - int read_cmd = location | (EE_READ_CMD << addr_len); + u8 dataval; + int i; outb(EE_ENB & ~EE_CS, ee_addr); outb(EE_ENB, ee_addr); @@ -325,19 +326,21 @@ static int read_eeprom(int location, int addr_len) /* Shift the read command bits out. */ for (i = 4 + addr_len; i >= 0; i--) { - int dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0; + dataval = (read_cmd & BIT(i)) ? EE_DATA_WRITE : 0; outb(EE_ENB | dataval, ee_addr); rtl8139_eeprom_delay(ioaddr); outb(EE_ENB | dataval | EE_SHIFT_CLK, ee_addr); rtl8139_eeprom_delay(ioaddr); } + outb(EE_ENB, ee_addr); rtl8139_eeprom_delay(ioaddr); for (i = 16; i > 0; i--) { outb(EE_ENB | EE_SHIFT_CLK, ee_addr); rtl8139_eeprom_delay(ioaddr); - retval = (retval << 1) | ((inb(ee_addr) & EE_DATA_READ) ? 1 : 0); + retval <<= 1; + retval |= inb(ee_addr) & EE_DATA_READ; outb(EE_ENB, ee_addr); rtl8139_eeprom_delay(ioaddr); } @@ -345,6 +348,7 @@ static int read_eeprom(int location, int addr_len) /* Terminate the EEPROM access. */ outb(~EE_CS, ee_addr); rtl8139_eeprom_delay(ioaddr); + return retval; } -- cgit v1.3.1 From 198e6b571b58de54803a92743970c8f5dea77782 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sun, 12 Apr 2020 21:30:38 +0200 Subject: net: rtl8139: Consistently use rtl8139_rx_config This string of macros is exactly the same thing as rtl8139_rx_config, so just use rtl8139_rx_config. No functional change. Signed-off-by: Marek Vasut Cc: Joe Hershberger --- drivers/net/rtl8139.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/rtl8139.c b/drivers/net/rtl8139.c index 90e9f1272c3..7a2829a1633 100644 --- a/drivers/net/rtl8139.c +++ b/drivers/net/rtl8139.c @@ -396,8 +396,8 @@ static void rtl_reset(struct eth_device *dev) /* Must enable Tx/Rx before setting transfer thresholds! */ outb(RTL_REG_CHIPCMD_CMDRXENB | RTL_REG_CHIPCMD_CMDTXENB, ioaddr + RTL_REG_CHIPCMD); - outl((RX_FIFO_THRESH<<13) | (RX_BUF_LEN_IDX<<11) | (RX_DMA_BURST<<8), - ioaddr + RTL_REG_RXCONFIG); /* accept no frames yet! */ + /* accept no frames yet! */ + outl(rtl8139_rx_config, ioaddr + RTL_REG_RXCONFIG); outl((TX_DMA_BURST<<8)|0x03000000, ioaddr + RTL_REG_TXCONFIG); /* The Linux driver changes RTL_REG_CONFIG1 here to use a different LED pattern -- cgit v1.3.1 From 89f3facffb8b35f45d405716dce63f6bc944a082 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sun, 12 Apr 2020 21:35:12 +0200 Subject: net: rtl8139: Minor cleanup of set_rx_mode() Rename the function to rtl8139_set_rx_mode(), use unsigned variables where applicable and inline mc_filter[] values. No functional chanage. Signed-off-by: Marek Vasut Cc: Joe Hershberger --- drivers/net/rtl8139.c | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/rtl8139.c b/drivers/net/rtl8139.c index 7a2829a1633..4dfb709fa9a 100644 --- a/drivers/net/rtl8139.c +++ b/drivers/net/rtl8139.c @@ -357,19 +357,17 @@ static const unsigned int rtl8139_rx_config = (RX_FIFO_THRESH << 13) | (RX_DMA_BURST << 8); -static void set_rx_mode(struct eth_device *dev) { - unsigned int mc_filter[2]; - int rx_mode; +static void rtl8139_set_rx_mode(struct eth_device *dev) +{ /* !IFF_PROMISC */ - rx_mode = RTL_REG_RXCONFIG_ACCEPTBROADCAST | - RTL_REG_RXCONFIG_ACCEPTMULTICAST | - RTL_REG_RXCONFIG_ACCEPTMYPHYS; - mc_filter[1] = mc_filter[0] = 0xffffffff; + unsigned int rx_mode = RTL_REG_RXCONFIG_ACCEPTBROADCAST | + RTL_REG_RXCONFIG_ACCEPTMULTICAST | + RTL_REG_RXCONFIG_ACCEPTMYPHYS; outl(rtl8139_rx_config | rx_mode, ioaddr + RTL_REG_RXCONFIG); - outl(mc_filter[0], ioaddr + RTL_REG_MAR0 + 0); - outl(mc_filter[1], ioaddr + RTL_REG_MAR0 + 4); + outl(0xffffffff, ioaddr + RTL_REG_MAR0 + 0); + outl(0xffffffff, ioaddr + RTL_REG_MAR0 + 4); } static void rtl_reset(struct eth_device *dev) @@ -425,8 +423,7 @@ static void rtl_reset(struct eth_device *dev) /* Start the chip's Tx and Rx process. */ outl(0, ioaddr + RTL_REG_RXMISSED); - /* set_rx_mode */ - set_rx_mode(dev); + rtl8139_set_rx_mode(dev); /* Disable all known interrupts by setting the interrupt mask. */ outw(0, ioaddr + RTL_REG_INTRMASK); -- cgit v1.3.1 From c7a3e35d768ddc6b6d3a9a0e061bba0741deaa52 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sun, 12 Apr 2020 21:41:56 +0200 Subject: net: rtl8139: Minor cleanup of rtl_reset() Rename the function to rtl8139_reset(), clean up the reset polling and various line-over-80 problems. No functional change. Signed-off-by: Marek Vasut Cc: Joe Hershberger --- drivers/net/rtl8139.c | 61 ++++++++++++++++++++++++++++----------------------- 1 file changed, 34 insertions(+), 27 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/rtl8139.c b/drivers/net/rtl8139.c index 4dfb709fa9a..d9d8aae7a94 100644 --- a/drivers/net/rtl8139.c +++ b/drivers/net/rtl8139.c @@ -200,7 +200,7 @@ static unsigned char rx_ring[RX_BUF_LEN+16] __attribute__((aligned(4))); static int rtl8139_probe(struct eth_device *dev, bd_t *bis); static int rtl8139_read_eeprom(unsigned int location, unsigned int addr_len); -static void rtl_reset(struct eth_device *dev); +static void rtl8139_reset(struct eth_device *dev); static int rtl_transmit(struct eth_device *dev, void *packet, int length); static int rtl_poll(struct eth_device *dev); static void rtl_disable(struct eth_device *dev); @@ -277,7 +277,7 @@ static int rtl8139_probe(struct eth_device *dev, bd_t *bis) for (i = 0; i < 3; i++) *ap++ = le16_to_cpu (rtl8139_read_eeprom(i + 7, addr_len)); - rtl_reset(dev); + rtl8139_reset(dev); if (inb(ioaddr + RTL_REG_MEDIASTATUS) & RTL_REG_MEDIASTATUS_MSRLINKFAIL) { printf("Cable not connected or other link failure\n"); @@ -370,8 +370,9 @@ static void rtl8139_set_rx_mode(struct eth_device *dev) outl(0xffffffff, ioaddr + RTL_REG_MAR0 + 4); } -static void rtl_reset(struct eth_device *dev) +static void rtl8139_reset(struct eth_device *dev) { + u8 reg; int i; outb(RTL_REG_CHIPCMD_CMDRESET, ioaddr + RTL_REG_CHIPCMD); @@ -380,11 +381,12 @@ static void rtl_reset(struct eth_device *dev) cur_tx = 0; /* Give the chip 10ms to finish the reset. */ - for (i=0; i<100; ++i){ - if ((inb(ioaddr + RTL_REG_CHIPCMD) & - RTL_REG_CHIPCMD_CMDRESET) == 0) + for (i = 0; i < 100; i++) { + reg = inb(ioaddr + RTL_REG_CHIPCMD); + if (!(reg & RTL_REG_CHIPCMD_CMDRESET)) break; - udelay (100); /* wait 100us */ + + udelay(100); } @@ -393,30 +395,35 @@ static void rtl_reset(struct eth_device *dev) /* Must enable Tx/Rx before setting transfer thresholds! */ outb(RTL_REG_CHIPCMD_CMDRXENB | RTL_REG_CHIPCMD_CMDTXENB, - ioaddr + RTL_REG_CHIPCMD); + ioaddr + RTL_REG_CHIPCMD); + /* accept no frames yet! */ outl(rtl8139_rx_config, ioaddr + RTL_REG_RXCONFIG); - outl((TX_DMA_BURST<<8)|0x03000000, ioaddr + RTL_REG_TXCONFIG); - - /* The Linux driver changes RTL_REG_CONFIG1 here to use a different LED pattern - * for half duplex or full/autodetect duplex (for full/autodetect, the - * outputs are TX/RX, Link10/100, FULL, while for half duplex it uses - * TX/RX, Link100, Link10). This is messy, because it doesn't match - * the inscription on the mounting bracket. It should not be changed - * from the configuration EEPROM default, because the card manufacturer - * should have set that to match the card. */ - - debug_cond(DEBUG_RX, - "rx ring address is %lX\n",(unsigned long)rx_ring); + outl((TX_DMA_BURST << 8) | 0x03000000, ioaddr + RTL_REG_TXCONFIG); + + /* + * The Linux driver changes RTL_REG_CONFIG1 here to use a different + * LED pattern for half duplex or full/autodetect duplex (for + * full/autodetect, the outputs are TX/RX, Link10/100, FULL, while + * for half duplex it uses TX/RX, Link100, Link10). This is messy, + * because it doesn't match the inscription on the mounting bracket. + * It should not be changed from the configuration EEPROM default, + * because the card manufacturer should have set that to match the + * card. + */ + debug_cond(DEBUG_RX, "rx ring address is %p\n", rx_ring); + flush_cache((unsigned long)rx_ring, RX_BUF_LEN); outl(phys_to_bus((int)rx_ring), ioaddr + RTL_REG_RXBUF); - /* If we add multicast support, the RTL_REG_MAR0 register would have to be - * initialized to 0xffffffffffffffff (two 32 bit accesses). Etherboot - * only needs broadcast (for ARP/RARP/BOOTP/DHCP) and unicast. */ - + /* + * If we add multicast support, the RTL_REG_MAR0 register would have + * to be initialized to 0xffffffffffffffff (two 32 bit accesses). + * Etherboot only needs broadcast (for ARP/RARP/BOOTP/DHCP) and + * unicast. + */ outb(RTL_REG_CHIPCMD_CMDRXENB | RTL_REG_CHIPCMD_CMDTXENB, - ioaddr + RTL_REG_CHIPCMD); + ioaddr + RTL_REG_CHIPCMD); outl(rtl8139_rx_config, ioaddr + RTL_REG_RXCONFIG); @@ -488,7 +495,7 @@ static int rtl_transmit(struct eth_device *dev, void *packet, int length) "tx timeout/error (%d usecs), status %hX txstatus %lX\n", 10*i, status, txstatus); - rtl_reset(dev); + rtl8139_reset(dev); return 0; } @@ -527,7 +534,7 @@ static int rtl_poll(struct eth_device *dev) RTL_STS_RXBADALIGN)) || (rx_size < ETH_ZLEN) || (rx_size > ETH_FRAME_LEN + 4)) { printf("rx error %hX\n", rx_status); - rtl_reset(dev); /* this clears all interrupts still pending */ + rtl8139_reset(dev); /* this clears all interrupts still pending */ return 0; } -- cgit v1.3.1 From 67fdbc06be27728e41aa9682d6aaf5618d959765 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sun, 12 Apr 2020 22:40:45 +0200 Subject: net: rtl8139: Minor cleanup of rtl_transmit() Rename the function to rtl8139_send(), clean up the TX polling, the TX OK condition at the end, overuse of typecasts, and various line-over-80 problems. No functional change. Signed-off-by: Marek Vasut Cc: Joe Hershberger --- drivers/net/rtl8139.c | 64 +++++++++++++++++++++++++-------------------------- 1 file changed, 31 insertions(+), 33 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/rtl8139.c b/drivers/net/rtl8139.c index d9d8aae7a94..cb1166ead2d 100644 --- a/drivers/net/rtl8139.c +++ b/drivers/net/rtl8139.c @@ -201,7 +201,7 @@ static unsigned char rx_ring[RX_BUF_LEN+16] __attribute__((aligned(4))); static int rtl8139_probe(struct eth_device *dev, bd_t *bis); static int rtl8139_read_eeprom(unsigned int location, unsigned int addr_len); static void rtl8139_reset(struct eth_device *dev); -static int rtl_transmit(struct eth_device *dev, void *packet, int length); +static int rtl8139_send(struct eth_device *dev, void *packet, int length); static int rtl_poll(struct eth_device *dev); static void rtl_disable(struct eth_device *dev); static int rtl_bcast_addr(struct eth_device *dev, const u8 *bcast_mac, int join) @@ -246,7 +246,7 @@ int rtl8139_initialize(bd_t *bis) dev->iobase = (int)bus_to_phys(iobase); dev->init = rtl8139_probe; dev->halt = rtl_disable; - dev->send = rtl_transmit; + dev->send = rtl8139_send; dev->recv = rtl_poll; dev->mcast = rtl_bcast_addr; @@ -436,29 +436,31 @@ static void rtl8139_reset(struct eth_device *dev) outw(0, ioaddr + RTL_REG_INTRMASK); } -static int rtl_transmit(struct eth_device *dev, void *packet, int length) +static int rtl8139_send(struct eth_device *dev, void *packet, int length) { - unsigned int status; - unsigned long txstatus; unsigned int len = length; + unsigned long txstatus; + unsigned int status; int i = 0; ioaddr = dev->iobase; - memcpy((char *)tx_buffer, (char *)packet, (int)length); + memcpy(tx_buffer, packet, length); debug_cond(DEBUG_TX, "sending %d bytes\n", len); - /* Note: RTL8139 doesn't auto-pad, send minimum payload (another 4 - * bytes are sent automatically for the FCS, totalling to 64 bytes). */ - while (len < ETH_ZLEN) { + /* + * Note: RTL8139 doesn't auto-pad, send minimum payload (another 4 + * bytes are sent automatically for the FCS, totalling to 64 bytes). + */ + while (len < ETH_ZLEN) tx_buffer[len++] = '\0'; - } flush_cache((unsigned long)tx_buffer, length); - outl(phys_to_bus((int)tx_buffer), ioaddr + RTL_REG_TXADDR0 + cur_tx*4); - outl(((TX_FIFO_THRESH<<11) & 0x003f0000) | len, - ioaddr + RTL_REG_TXSTATUS0 + cur_tx*4); + outl(phys_to_bus((unsigned long)tx_buffer), + ioaddr + RTL_REG_TXADDR0 + cur_tx * 4); + outl(((TX_FIFO_THRESH << 11) & 0x003f0000) | len, + ioaddr + RTL_REG_TXSTATUS0 + cur_tx * 4); do { status = inw(ioaddr + RTL_REG_INTRSTATUS); @@ -468,37 +470,33 @@ static int rtl_transmit(struct eth_device *dev, void *packet, int length) * RTL_REG_INTRSTATUS_RXFIFOOVER MUST be handled in the * rtl_poll() function. */ - outw(status & (RTL_REG_INTRSTATUS_TXOK | - RTL_REG_INTRSTATUS_TXERR | - RTL_REG_INTRSTATUS_PCIERR), - ioaddr + RTL_REG_INTRSTATUS); - if ((status & (RTL_REG_INTRSTATUS_TXOK | - RTL_REG_INTRSTATUS_TXERR | - RTL_REG_INTRSTATUS_PCIERR)) != 0) + status &= RTL_REG_INTRSTATUS_TXOK | RTL_REG_INTRSTATUS_TXERR | + RTL_REG_INTRSTATUS_PCIERR; + outw(status, ioaddr + RTL_REG_INTRSTATUS); + if (status) break; + udelay(10); } while (i++ < RTL_TIMEOUT); - txstatus = inl(ioaddr + RTL_REG_TXSTATUS0 + cur_tx*4); - - if (status & RTL_REG_INTRSTATUS_TXOK) { - cur_tx = (cur_tx + 1) % NUM_TX_DESC; + txstatus = inl(ioaddr + RTL_REG_TXSTATUS0 + cur_tx * 4); + if (!(status & RTL_REG_INTRSTATUS_TXOK)) { debug_cond(DEBUG_TX, - "tx done, status %hX txstatus %lX\n", - status, txstatus); - - return length; - } else { - - debug_cond(DEBUG_TX, - "tx timeout/error (%d usecs), status %hX txstatus %lX\n", - 10*i, status, txstatus); + "tx timeout/error (%d usecs), status %hX txstatus %lX\n", + 10 * i, status, txstatus); rtl8139_reset(dev); return 0; } + + cur_tx = (cur_tx + 1) % NUM_TX_DESC; + + debug_cond(DEBUG_TX, "tx done, status %hX txstatus %lX\n", + status, txstatus); + + return length; } static int rtl_poll(struct eth_device *dev) -- cgit v1.3.1 From 468fd955626b650ebb7975d061d415682c91f041 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sun, 12 Apr 2020 22:43:16 +0200 Subject: net: rtl8139: Minor cleanup of rtl_poll() Rename the function to rtl8139_recv(), clean up various checkpatch errors, line-over-80 conditions, and malformed comments. No functional change. Signed-off-by: Marek Vasut Cc: Joe Hershberger --- drivers/net/rtl8139.c | 63 +++++++++++++++++++++++++++------------------------ 1 file changed, 33 insertions(+), 30 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/rtl8139.c b/drivers/net/rtl8139.c index cb1166ead2d..d942ccf6273 100644 --- a/drivers/net/rtl8139.c +++ b/drivers/net/rtl8139.c @@ -44,7 +44,7 @@ which reserves the ranges 0x00000-0x10000 and 0x98000-0xA0000. My interpretation of this "reserved" is that Etherboot may do whatever it likes, as long as its environment is kept intact (like the BIOS - variables). Hopefully fixed rtl_poll() once and for all. The symptoms + variables). Hopefully fixed rtl8139_recv() once and for all. The symptoms were that if Etherboot was left at the boot menu for several minutes, the first eth_poll failed. Seems like I am the only person who does this. First of all I fixed the debugging code and then set out for a long bug @@ -65,7 +65,7 @@ corruption because of exceeding 32K during runtime. 28 Jul 1999 (Matthias Meixner - meixner@rbg.informatik.tu-darmstadt.de) - rtl_poll was quite broken: it used the RxOK interrupt flag instead + rtl8139_recv was quite broken: it used the RxOK interrupt flag instead of the RxBufferEmpty flag which often resulted in very bad transmission performace - below 1kBytes/s. @@ -202,7 +202,7 @@ static int rtl8139_probe(struct eth_device *dev, bd_t *bis); static int rtl8139_read_eeprom(unsigned int location, unsigned int addr_len); static void rtl8139_reset(struct eth_device *dev); static int rtl8139_send(struct eth_device *dev, void *packet, int length); -static int rtl_poll(struct eth_device *dev); +static int rtl8139_recv(struct eth_device *dev); static void rtl_disable(struct eth_device *dev); static int rtl_bcast_addr(struct eth_device *dev, const u8 *bcast_mac, int join) { @@ -247,7 +247,7 @@ int rtl8139_initialize(bd_t *bis) dev->init = rtl8139_probe; dev->halt = rtl_disable; dev->send = rtl8139_send; - dev->recv = rtl_poll; + dev->recv = rtl8139_recv; dev->mcast = rtl_bcast_addr; eth_register (dev); @@ -468,7 +468,7 @@ static int rtl8139_send(struct eth_device *dev, void *packet, int length) * Only acknlowledge interrupt sources we can properly * handle here - the RTL_REG_INTRSTATUS_RXOVERFLOW/ * RTL_REG_INTRSTATUS_RXFIFOOVER MUST be handled in the - * rtl_poll() function. + * rtl8139_recv() function. */ status &= RTL_REG_INTRSTATUS_TXOK | RTL_REG_INTRSTATUS_TXERR | RTL_REG_INTRSTATUS_PCIERR; @@ -499,27 +499,26 @@ static int rtl8139_send(struct eth_device *dev, void *packet, int length) return length; } -static int rtl_poll(struct eth_device *dev) +static int rtl8139_recv(struct eth_device *dev) { - unsigned int status; - unsigned int ring_offs; + const unsigned int rxstat = RTL_REG_INTRSTATUS_RXFIFOOVER | + RTL_REG_INTRSTATUS_RXOVERFLOW | + RTL_REG_INTRSTATUS_RXOK; unsigned int rx_size, rx_status; - int length=0; + unsigned int ring_offs; + unsigned int status; + int length = 0; ioaddr = dev->iobase; - if (inb(ioaddr + RTL_REG_CHIPCMD) & RTL_REG_CHIPCMD_RXBUFEMPTY) { + if (inb(ioaddr + RTL_REG_CHIPCMD) & RTL_REG_CHIPCMD_RXBUFEMPTY) return 0; - } status = inw(ioaddr + RTL_REG_INTRSTATUS); /* See below for the rest of the interrupt acknowledges. */ - outw(status & ~(RTL_REG_INTRSTATUS_RXFIFOOVER | - RTL_REG_INTRSTATUS_RXOVERFLOW | - RTL_REG_INTRSTATUS_RXOK), - ioaddr + RTL_REG_INTRSTATUS); + outw(status & ~rxstat, ioaddr + RTL_REG_INTRSTATUS); - debug_cond(DEBUG_RX, "rtl_poll: int %hX ", status); + debug_cond(DEBUG_RX, "%s: int %hX ", __func__, status); ring_offs = cur_rx % RX_BUF_LEN; /* ring_offs is guaranteed being 4-byte aligned */ @@ -530,38 +529,42 @@ static int rtl_poll(struct eth_device *dev) if ((rx_status & (RTL_STS_RXBADSYMBOL | RTL_STS_RXRUNT | RTL_STS_RXTOOLONG | RTL_STS_RXCRCERR | RTL_STS_RXBADALIGN)) || - (rx_size < ETH_ZLEN) || (rx_size > ETH_FRAME_LEN + 4)) { + (rx_size < ETH_ZLEN) || + (rx_size > ETH_FRAME_LEN + 4)) { printf("rx error %hX\n", rx_status); - rtl8139_reset(dev); /* this clears all interrupts still pending */ + /* this clears all interrupts still pending */ + rtl8139_reset(dev); return 0; } /* Received a good packet */ length = rx_size - 4; /* no one cares about the FCS */ - if (ring_offs+4+rx_size-4 > RX_BUF_LEN) { - int semi_count = RX_BUF_LEN - ring_offs - 4; + if (ring_offs + 4 + rx_size - 4 > RX_BUF_LEN) { unsigned char rxdata[RX_BUF_LEN]; + int semi_count = RX_BUF_LEN - ring_offs - 4; memcpy(rxdata, rx_ring + ring_offs + 4, semi_count); - memcpy(&(rxdata[semi_count]), rx_ring, rx_size-4-semi_count); + memcpy(&rxdata[semi_count], rx_ring, + rx_size - 4 - semi_count); net_process_received_packet(rxdata, length); debug_cond(DEBUG_RX, "rx packet %d+%d bytes", - semi_count, rx_size-4-semi_count); + semi_count, rx_size - 4 - semi_count); } else { net_process_received_packet(rx_ring + ring_offs + 4, length); - debug_cond(DEBUG_RX, "rx packet %d bytes", rx_size-4); + debug_cond(DEBUG_RX, "rx packet %d bytes", rx_size - 4); } flush_cache((unsigned long)rx_ring, RX_BUF_LEN); - cur_rx = (cur_rx + rx_size + 4 + 3) & ~3; + cur_rx = ROUND(cur_rx + rx_size + 4, 4); outw(cur_rx - 16, ioaddr + RTL_REG_RXBUFPTR); - /* See RTL8139 Programming Guide V0.1 for the official handling of - * Rx overflow situations. The document itself contains basically no - * usable information, except for a few exception handling rules. */ - outw(status & (RTL_REG_INTRSTATUS_RXFIFOOVER | - RTL_REG_INTRSTATUS_RXOVERFLOW | - RTL_REG_INTRSTATUS_RXOK), ioaddr + RTL_REG_INTRSTATUS); + /* + * See RTL8139 Programming Guide V0.1 for the official handling of + * Rx overflow situations. The document itself contains basically + * no usable information, except for a few exception handling rules. + */ + outw(status & rxstat, ioaddr + RTL_REG_INTRSTATUS); + return length; } -- cgit v1.3.1 From 661479ffc1a0b7ea159dae1ca34d61d009896870 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sun, 12 Apr 2020 22:55:40 +0200 Subject: net: rtl8139: Minor cleanup of rtl_disable() Rename the function to rtl8139_stop(), clean up checkpatch errors in the stop polling function. No functional change. Signed-off-by: Marek Vasut Cc: Joe Hershberger --- drivers/net/rtl8139.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/rtl8139.c b/drivers/net/rtl8139.c index d942ccf6273..6aed7bd8957 100644 --- a/drivers/net/rtl8139.c +++ b/drivers/net/rtl8139.c @@ -203,7 +203,7 @@ static int rtl8139_read_eeprom(unsigned int location, unsigned int addr_len); static void rtl8139_reset(struct eth_device *dev); static int rtl8139_send(struct eth_device *dev, void *packet, int length); static int rtl8139_recv(struct eth_device *dev); -static void rtl_disable(struct eth_device *dev); +static void rtl8139_stop(struct eth_device *dev); static int rtl_bcast_addr(struct eth_device *dev, const u8 *bcast_mac, int join) { return (0); @@ -245,7 +245,7 @@ int rtl8139_initialize(bd_t *bis) dev->priv = (void *) devno; dev->iobase = (int)bus_to_phys(iobase); dev->init = rtl8139_probe; - dev->halt = rtl_disable; + dev->halt = rtl8139_stop; dev->send = rtl8139_send; dev->recv = rtl8139_recv; dev->mcast = rtl_bcast_addr; @@ -568,8 +568,9 @@ static int rtl8139_recv(struct eth_device *dev) return length; } -static void rtl_disable(struct eth_device *dev) +static void rtl8139_stop(struct eth_device *dev) { + u8 reg; int i; ioaddr = dev->iobase; @@ -578,8 +579,10 @@ static void rtl_disable(struct eth_device *dev) outb(RTL_REG_CHIPCMD_CMDRESET, ioaddr + RTL_REG_CHIPCMD); /* Give the chip 10ms to finish the reset. */ - for (i=0; i<100; ++i){ - if ((inb(ioaddr + RTL_REG_CHIPCMD) & RTL_REG_CHIPCMD_CMDRESET) == 0) break; + for (i = 0; i < 100; i++) { + reg = inb(ioaddr + RTL_REG_CHIPCMD); + if (!(reg & RTL_REG_CHIPCMD_CMDRESET)) + break; udelay (100); /* wait 100us */ } } -- cgit v1.3.1 From 38b306db2334a6565b326874eb4ff536e28654ba Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sun, 12 Apr 2020 22:58:27 +0200 Subject: net: rtl8139: Factor out hardware reset This hardware reset and reset-wait implementation was twice in the driver, factor it out into a separate function. This really should use wait_for_bit() eventually and return -ETIMEDOUT, but thus far, handling of any of this is missing from the driver. This must be added later. Thus far, no functional change. Signed-off-by: Marek Vasut Cc: Joe Hershberger --- drivers/net/rtl8139.c | 28 +++++++++++----------------- 1 file changed, 11 insertions(+), 17 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/rtl8139.c b/drivers/net/rtl8139.c index 6aed7bd8957..68ef9eea250 100644 --- a/drivers/net/rtl8139.c +++ b/drivers/net/rtl8139.c @@ -370,16 +370,13 @@ static void rtl8139_set_rx_mode(struct eth_device *dev) outl(0xffffffff, ioaddr + RTL_REG_MAR0 + 4); } -static void rtl8139_reset(struct eth_device *dev) +static void rtl8139_hw_reset(struct eth_device *dev) { u8 reg; int i; outb(RTL_REG_CHIPCMD_CMDRESET, ioaddr + RTL_REG_CHIPCMD); - cur_rx = 0; - cur_tx = 0; - /* Give the chip 10ms to finish the reset. */ for (i = 0; i < 100; i++) { reg = inb(ioaddr + RTL_REG_CHIPCMD); @@ -388,7 +385,16 @@ static void rtl8139_reset(struct eth_device *dev) udelay(100); } +} + +static void rtl8139_reset(struct eth_device *dev) +{ + int i; + + cur_rx = 0; + cur_tx = 0; + rtl8139_hw_reset(dev); for (i = 0; i < ETH_ALEN; i++) outb(dev->enetaddr[i], ioaddr + RTL_REG_MAC0 + i); @@ -570,19 +576,7 @@ static int rtl8139_recv(struct eth_device *dev) static void rtl8139_stop(struct eth_device *dev) { - u8 reg; - int i; - ioaddr = dev->iobase; - /* reset the chip */ - outb(RTL_REG_CHIPCMD_CMDRESET, ioaddr + RTL_REG_CHIPCMD); - - /* Give the chip 10ms to finish the reset. */ - for (i = 0; i < 100; i++) { - reg = inb(ioaddr + RTL_REG_CHIPCMD); - if (!(reg & RTL_REG_CHIPCMD_CMDRESET)) - break; - udelay (100); /* wait 100us */ - } + rtl8139_hw_reset(dev); } -- cgit v1.3.1 From 0e5a4117a58b8d47b502d7e5536ca6b36d568806 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sun, 12 Apr 2020 23:01:45 +0200 Subject: net: rtl8139: Finish cleanup Finish the checkpatch cleanup of the driver, fix the remaining issues in probe and init function and in global variables, rename the probe function to rtl8139_init(), no functional change. Signed-off-by: Marek Vasut Cc: Joe Hershberger --- drivers/net/rtl8139.c | 173 +++++++++++++++++++++++++------------------------- 1 file changed, 87 insertions(+), 86 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/rtl8139.c b/drivers/net/rtl8139.c index 68ef9eea250..b901e3a79b7 100644 --- a/drivers/net/rtl8139.c +++ b/drivers/net/rtl8139.c @@ -8,68 +8,67 @@ */ /* rtl8139.c - etherboot driver for the Realtek 8139 chipset - - ported from the linux driver written by Donald Becker - by Rainer Bawidamann (Rainer.Bawidamann@informatik.uni-ulm.de) 1999 - - This software may be used and distributed according to the terms - of the GNU Public License, incorporated herein by reference. - - changes to the original driver: - - removed support for interrupts, switching to polling mode (yuck!) - - removed support for the 8129 chip (external MII) - -*/ + * + * ported from the linux driver written by Donald Becker + * by Rainer Bawidamann (Rainer.Bawidamann@informatik.uni-ulm.de) 1999 + * + * This software may be used and distributed according to the terms + * of the GNU Public License, incorporated herein by reference. + * + * changes to the original driver: + * - removed support for interrupts, switching to polling mode (yuck!) + * - removed support for the 8129 chip (external MII) + */ /*********************************************************************/ /* Revision History */ /*********************************************************************/ /* - 28 Dec 2002 ken_yap@users.sourceforge.net (Ken Yap) - Put in virt_to_bus calls to allow Etherboot relocation. - - 06 Apr 2001 ken_yap@users.sourceforge.net (Ken Yap) - Following email from Hyun-Joon Cha, added a disable routine, otherwise - NIC remains live and can crash the kernel later. - - 4 Feb 2000 espenlaub@informatik.uni-ulm.de (Klaus Espenlaub) - Shuffled things around, removed the leftovers from the 8129 support - that was in the Linux driver and added a bit more 8139 definitions. - Moved the 8K receive buffer to a fixed, available address outside the - 0x98000-0x9ffff range. This is a bit of a hack, but currently the only - way to make room for the Etherboot features that need substantial amounts - of code like the ANSI console support. Currently the buffer is just below - 0x10000, so this even conforms to the tagged boot image specification, - which reserves the ranges 0x00000-0x10000 and 0x98000-0xA0000. My - interpretation of this "reserved" is that Etherboot may do whatever it - likes, as long as its environment is kept intact (like the BIOS - variables). Hopefully fixed rtl8139_recv() once and for all. The symptoms - were that if Etherboot was left at the boot menu for several minutes, the - first eth_poll failed. Seems like I am the only person who does this. - First of all I fixed the debugging code and then set out for a long bug - hunting session. It took me about a week full time work - poking around - various places in the driver, reading Don Becker's and Jeff Garzik's Linux - driver and even the FreeBSD driver (what a piece of crap!) - and - eventually spotted the nasty thing: the transmit routine was acknowledging - each and every interrupt pending, including the RxOverrun and RxFIFIOver - interrupts. This confused the RTL8139 thoroughly. It destroyed the - Rx ring contents by dumping the 2K FIFO contents right where we wanted to - get the next packet. Oh well, what fun. - - 18 Jan 2000 mdc@thinguin.org (Marty Connor) - Drastically simplified error handling. Basically, if any error - in transmission or reception occurs, the card is reset. - Also, pointed all transmit descriptors to the same buffer to - save buffer space. This should decrease driver size and avoid - corruption because of exceeding 32K during runtime. - - 28 Jul 1999 (Matthias Meixner - meixner@rbg.informatik.tu-darmstadt.de) - rtl8139_recv was quite broken: it used the RxOK interrupt flag instead - of the RxBufferEmpty flag which often resulted in very bad - transmission performace - below 1kBytes/s. - -*/ + * 28 Dec 2002 ken_yap@users.sourceforge.net (Ken Yap) + * Put in virt_to_bus calls to allow Etherboot relocation. + * + * 06 Apr 2001 ken_yap@users.sourceforge.net (Ken Yap) + * Following email from Hyun-Joon Cha, added a disable routine, otherwise + * NIC remains live and can crash the kernel later. + * + * 4 Feb 2000 espenlaub@informatik.uni-ulm.de (Klaus Espenlaub) + * Shuffled things around, removed the leftovers from the 8129 support + * that was in the Linux driver and added a bit more 8139 definitions. + * Moved the 8K receive buffer to a fixed, available address outside the + * 0x98000-0x9ffff range. This is a bit of a hack, but currently the only + * way to make room for the Etherboot features that need substantial amounts + * of code like the ANSI console support. Currently the buffer is just below + * 0x10000, so this even conforms to the tagged boot image specification, + * which reserves the ranges 0x00000-0x10000 and 0x98000-0xA0000. My + * interpretation of this "reserved" is that Etherboot may do whatever it + * likes, as long as its environment is kept intact (like the BIOS + * variables). Hopefully fixed rtl8139_recv() once and for all. The symptoms + * were that if Etherboot was left at the boot menu for several minutes, the + * first eth_poll failed. Seems like I am the only person who does this. + * First of all I fixed the debugging code and then set out for a long bug + * hunting session. It took me about a week full time work - poking around + * various places in the driver, reading Don Becker's and Jeff Garzik's Linux + * driver and even the FreeBSD driver (what a piece of crap!) - and + * eventually spotted the nasty thing: the transmit routine was acknowledging + * each and every interrupt pending, including the RxOverrun and RxFIFIOver + * interrupts. This confused the RTL8139 thoroughly. It destroyed the + * Rx ring contents by dumping the 2K FIFO contents right where we wanted to + * get the next packet. Oh well, what fun. + * + * 18 Jan 2000 mdc@thinguin.org (Marty Connor) + * Drastically simplified error handling. Basically, if any error + * in transmission or reception occurs, the card is reset. + * Also, pointed all transmit descriptors to the same buffer to + * save buffer space. This should decrease driver size and avoid + * corruption because of exceeding 32K during runtime. + * + * 28 Jul 1999 (Matthias Meixner - meixner@rbg.informatik.tu-darmstadt.de) + * rtl8139_recv was quite broken: it used the RxOK interrupt flag instead + * of the RxBufferEmpty flag which often resulted in very bad + * transmission performace - below 1kBytes/s. + * + */ #include #include @@ -82,8 +81,8 @@ #define RTL_TIMEOUT 100000 -/* PCI Tuning Parameters - Threshold is bytes transferred to chip before transmission starts. */ +/* PCI Tuning Parameters */ +/* Threshold is bytes transferred to chip before transmission starts. */ #define TX_FIFO_THRESH 256 /* In bytes, rounded down to 32 byte units. */ #define RX_FIFO_THRESH 4 /* Rx buffer level before first PCI xfer. */ #define RX_DMA_BURST 4 /* Maximum PCI burst, '4' is 256 bytes */ @@ -192,13 +191,13 @@ #define RTL_STS_RXSTATUSOK BIT(0) static int ioaddr; -static unsigned int cur_rx,cur_tx; +static unsigned int cur_rx, cur_tx; /* The RTL8139 can only transmit from a contiguous, aligned memory block. */ -static unsigned char tx_buffer[TX_BUF_SIZE] __attribute__((aligned(4))); -static unsigned char rx_ring[RX_BUF_LEN+16] __attribute__((aligned(4))); +static unsigned char tx_buffer[TX_BUF_SIZE] __aligned(4); +static unsigned char rx_ring[RX_BUF_LEN + 16] __aligned(4); -static int rtl8139_probe(struct eth_device *dev, bd_t *bis); +static int rtl8139_init(struct eth_device *dev, bd_t *bis); static int rtl8139_read_eeprom(unsigned int location, unsigned int addr_len); static void rtl8139_reset(struct eth_device *dev); static int rtl8139_send(struct eth_device *dev, void *packet, int length); @@ -206,82 +205,84 @@ static int rtl8139_recv(struct eth_device *dev); static void rtl8139_stop(struct eth_device *dev); static int rtl_bcast_addr(struct eth_device *dev, const u8 *bcast_mac, int join) { - return (0); + return 0; } static struct pci_device_id supported[] = { - {PCI_VENDOR_ID_REALTEK, PCI_DEVICE_ID_REALTEK_8139}, - {PCI_VENDOR_ID_DLINK, PCI_DEVICE_ID_DLINK_8139}, - {} + { PCI_VENDOR_ID_REALTEK, PCI_DEVICE_ID_REALTEK_8139 }, + { PCI_VENDOR_ID_DLINK, PCI_DEVICE_ID_DLINK_8139 }, + { } }; int rtl8139_initialize(bd_t *bis) { - pci_dev_t devno; - int card_number = 0; struct eth_device *dev; + int card_number = 0; + pci_dev_t devno; + int idx = 0; u32 iobase; - int idx=0; - while(1){ + while (1) { /* Find RTL8139 */ - if ((devno = pci_find_devices(supported, idx++)) < 0) + devno = pci_find_devices(supported, idx++); + if (devno < 0) break; pci_read_config_dword(devno, PCI_BASE_ADDRESS_1, &iobase); iobase &= ~0xf; - debug ("rtl8139: REALTEK RTL8139 @0x%x\n", iobase); + debug("rtl8139: REALTEK RTL8139 @0x%x\n", iobase); - dev = (struct eth_device *)malloc(sizeof *dev); + dev = (struct eth_device *)malloc(sizeof(*dev)); if (!dev) { printf("Can not allocate memory of rtl8139\n"); break; } memset(dev, 0, sizeof(*dev)); - sprintf (dev->name, "RTL8139#%d", card_number); + sprintf(dev->name, "RTL8139#%d", card_number); - dev->priv = (void *) devno; + dev->priv = (void *)devno; dev->iobase = (int)bus_to_phys(iobase); - dev->init = rtl8139_probe; + dev->init = rtl8139_init; dev->halt = rtl8139_stop; dev->send = rtl8139_send; dev->recv = rtl8139_recv; dev->mcast = rtl_bcast_addr; - eth_register (dev); + eth_register(dev); card_number++; - pci_write_config_byte (devno, PCI_LATENCY_TIMER, 0x20); + pci_write_config_byte(devno, PCI_LATENCY_TIMER, 0x20); - udelay (10 * 1000); + udelay(10 * 1000); } return card_number; } -static int rtl8139_probe(struct eth_device *dev, bd_t *bis) +static int rtl8139_init(struct eth_device *dev, bd_t *bis) { - int i; - int addr_len; unsigned short *ap = (unsigned short *)dev->enetaddr; + int addr_len, i; + u8 reg; ioaddr = dev->iobase; /* Bring the chip out of low-power mode. */ outb(0x00, ioaddr + RTL_REG_CONFIG1); - addr_len = rtl8139_read_eeprom(0,8) == 0x8129 ? 8 : 6; + addr_len = rtl8139_read_eeprom(0, 8) == 0x8129 ? 8 : 6; for (i = 0; i < 3; i++) - *ap++ = le16_to_cpu (rtl8139_read_eeprom(i + 7, addr_len)); + *ap++ = le16_to_cpu(rtl8139_read_eeprom(i + 7, addr_len)); rtl8139_reset(dev); - if (inb(ioaddr + RTL_REG_MEDIASTATUS) & RTL_REG_MEDIASTATUS_MSRLINKFAIL) { + reg = inb(ioaddr + RTL_REG_MEDIASTATUS); + if (reg & RTL_REG_MEDIASTATUS_MSRLINKFAIL) { printf("Cable not connected or other link failure\n"); - return -1 ; + return -1; } return 0; -- cgit v1.3.1 From 6ee6caaf035063dc376eeb3385f7f08f87549b1e Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sun, 12 Apr 2020 23:12:11 +0200 Subject: net: rtl8139: Move functions around Just move functions around in preparation for easy DM conversion, rename rtl_bcast_addr() to rtl8139_bcast_addr(), no functional change. Signed-off-by: Marek Vasut Cc: Joe Hershberger --- drivers/net/rtl8139.c | 179 ++++++++++++++++++++++++-------------------------- 1 file changed, 87 insertions(+), 92 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/rtl8139.c b/drivers/net/rtl8139.c index b901e3a79b7..66591d03cec 100644 --- a/drivers/net/rtl8139.c +++ b/drivers/net/rtl8139.c @@ -190,104 +190,13 @@ #define RTL_STS_RXBADALIGN BIT(1) #define RTL_STS_RXSTATUSOK BIT(0) -static int ioaddr; static unsigned int cur_rx, cur_tx; +static int ioaddr; /* The RTL8139 can only transmit from a contiguous, aligned memory block. */ static unsigned char tx_buffer[TX_BUF_SIZE] __aligned(4); static unsigned char rx_ring[RX_BUF_LEN + 16] __aligned(4); -static int rtl8139_init(struct eth_device *dev, bd_t *bis); -static int rtl8139_read_eeprom(unsigned int location, unsigned int addr_len); -static void rtl8139_reset(struct eth_device *dev); -static int rtl8139_send(struct eth_device *dev, void *packet, int length); -static int rtl8139_recv(struct eth_device *dev); -static void rtl8139_stop(struct eth_device *dev); -static int rtl_bcast_addr(struct eth_device *dev, const u8 *bcast_mac, int join) -{ - return 0; -} - -static struct pci_device_id supported[] = { - { PCI_VENDOR_ID_REALTEK, PCI_DEVICE_ID_REALTEK_8139 }, - { PCI_VENDOR_ID_DLINK, PCI_DEVICE_ID_DLINK_8139 }, - { } -}; - -int rtl8139_initialize(bd_t *bis) -{ - struct eth_device *dev; - int card_number = 0; - pci_dev_t devno; - int idx = 0; - u32 iobase; - - while (1) { - /* Find RTL8139 */ - devno = pci_find_devices(supported, idx++); - if (devno < 0) - break; - - pci_read_config_dword(devno, PCI_BASE_ADDRESS_1, &iobase); - iobase &= ~0xf; - - debug("rtl8139: REALTEK RTL8139 @0x%x\n", iobase); - - dev = (struct eth_device *)malloc(sizeof(*dev)); - if (!dev) { - printf("Can not allocate memory of rtl8139\n"); - break; - } - memset(dev, 0, sizeof(*dev)); - - sprintf(dev->name, "RTL8139#%d", card_number); - - dev->priv = (void *)devno; - dev->iobase = (int)bus_to_phys(iobase); - dev->init = rtl8139_init; - dev->halt = rtl8139_stop; - dev->send = rtl8139_send; - dev->recv = rtl8139_recv; - dev->mcast = rtl_bcast_addr; - - eth_register(dev); - - card_number++; - - pci_write_config_byte(devno, PCI_LATENCY_TIMER, 0x20); - - udelay(10 * 1000); - } - - return card_number; -} - -static int rtl8139_init(struct eth_device *dev, bd_t *bis) -{ - unsigned short *ap = (unsigned short *)dev->enetaddr; - int addr_len, i; - u8 reg; - - ioaddr = dev->iobase; - - /* Bring the chip out of low-power mode. */ - outb(0x00, ioaddr + RTL_REG_CONFIG1); - - addr_len = rtl8139_read_eeprom(0, 8) == 0x8129 ? 8 : 6; - for (i = 0; i < 3; i++) - *ap++ = le16_to_cpu(rtl8139_read_eeprom(i + 7, addr_len)); - - rtl8139_reset(dev); - - reg = inb(ioaddr + RTL_REG_MEDIASTATUS); - if (reg & RTL_REG_MEDIASTATUS_MSRLINKFAIL) { - printf("Cable not connected or other link failure\n"); - return -1; - } - - return 0; -} - /* Serial EEPROM section. */ /* EEPROM_Ctrl bits. */ @@ -575,9 +484,95 @@ static int rtl8139_recv(struct eth_device *dev) return length; } +static int rtl8139_init(struct eth_device *dev, bd_t *bis) +{ + unsigned short *ap = (unsigned short *)dev->enetaddr; + int addr_len, i; + u8 reg; + + ioaddr = dev->iobase; + + /* Bring the chip out of low-power mode. */ + outb(0x00, ioaddr + RTL_REG_CONFIG1); + + addr_len = rtl8139_read_eeprom(0, 8) == 0x8129 ? 8 : 6; + for (i = 0; i < 3; i++) + *ap++ = le16_to_cpu(rtl8139_read_eeprom(i + 7, addr_len)); + + rtl8139_reset(dev); + + reg = inb(ioaddr + RTL_REG_MEDIASTATUS); + if (reg & RTL_REG_MEDIASTATUS_MSRLINKFAIL) { + printf("Cable not connected or other link failure\n"); + return -1; + } + + return 0; +} + static void rtl8139_stop(struct eth_device *dev) { ioaddr = dev->iobase; rtl8139_hw_reset(dev); } + +static int rtl8139_bcast_addr(struct eth_device *dev, const u8 *bcast_mac, + int join) +{ + return 0; +} + +static struct pci_device_id supported[] = { + { PCI_VENDOR_ID_REALTEK, PCI_DEVICE_ID_REALTEK_8139 }, + { PCI_VENDOR_ID_DLINK, PCI_DEVICE_ID_DLINK_8139 }, + { } +}; + +int rtl8139_initialize(bd_t *bis) +{ + struct eth_device *dev; + int card_number = 0; + pci_dev_t devno; + int idx = 0; + u32 iobase; + + while (1) { + /* Find RTL8139 */ + devno = pci_find_devices(supported, idx++); + if (devno < 0) + break; + + pci_read_config_dword(devno, PCI_BASE_ADDRESS_1, &iobase); + iobase &= ~0xf; + + debug("rtl8139: REALTEK RTL8139 @0x%x\n", iobase); + + dev = (struct eth_device *)malloc(sizeof(*dev)); + if (!dev) { + printf("Can not allocate memory of rtl8139\n"); + break; + } + memset(dev, 0, sizeof(*dev)); + + sprintf(dev->name, "RTL8139#%d", card_number); + + dev->priv = (void *)devno; + dev->iobase = (int)bus_to_phys(iobase); + dev->init = rtl8139_init; + dev->halt = rtl8139_stop; + dev->send = rtl8139_send; + dev->recv = rtl8139_recv; + dev->mcast = rtl8139_bcast_addr; + + eth_register(dev); + + card_number++; + + pci_write_config_byte(devno, PCI_LATENCY_TIMER, 0x20); + + udelay(10 * 1000); + } + + return card_number; +} -- cgit v1.3.1 From e7ab86d9b2f24c92552be62b0447abab4f8644a2 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sun, 12 Apr 2020 23:49:25 +0200 Subject: net: rtl8139: Fill in SPDX tag The rtl8139 driver is derived from Etherboot driver, which is in turn derived from Linux 8139too driver added in Linux 2.2.18pre14. An undocumented change in Linux 2.4.10.2 added a new field to the driver, MODULE_LICENSE("GPL"); . According to current Linux kernel licensing rules, Documentation/process/license-rules.rst, quote: "GPL" Module is licensed under GPL version 2. This does not express any distinction between GPL-2.0-only or GPL-2.0-or-later. The exact license information can only be determined via the license information in the corresponding source files. And since the code does not contain any "future" clause, the tag is therefore GPL-2.0 only. Signed-off-by: Marek Vasut Cc: Joe Hershberger --- drivers/net/rtl8139.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/rtl8139.c b/drivers/net/rtl8139.c index 66591d03cec..1f083972917 100644 --- a/drivers/net/rtl8139.c +++ b/drivers/net/rtl8139.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 /* * rtl8139.c : U-Boot driver for the RealTek RTL8139 * @@ -12,9 +13,6 @@ * ported from the linux driver written by Donald Becker * by Rainer Bawidamann (Rainer.Bawidamann@informatik.uni-ulm.de) 1999 * - * This software may be used and distributed according to the terms - * of the GNU Public License, incorporated herein by reference. - * * changes to the original driver: * - removed support for interrupts, switching to polling mode (yuck!) * - removed support for the 8129 chip (external MII) -- cgit v1.3.1 From 9c211e3b055ce809ac81ea4f849594ffb6f77df4 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sun, 15 Mar 2020 00:08:31 +0100 Subject: net: smc911x: Remove pkt_data_{push,pull} These functions are never used and are likely a pre-DM remnant from times long past, just remove them. Signed-off-by: Marek Vasut Cc: Joe Hershberger Cc: Masahiro Yamada --- drivers/net/smc911x.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/smc911x.c b/drivers/net/smc911x.c index 257b0385c2a..24b4eaeb3fd 100644 --- a/drivers/net/smc911x.c +++ b/drivers/net/smc911x.c @@ -13,11 +13,6 @@ #include "smc911x.h" -u32 pkt_data_pull(struct eth_device *dev, u32 addr) \ - __attribute__ ((weak, alias ("smc911x_reg_read"))); -void pkt_data_push(struct eth_device *dev, u32 addr, u32 val) \ - __attribute__ ((weak, alias ("smc911x_reg_write"))); - static void smc911x_handle_mac_address(struct eth_device *dev) { unsigned long addrh, addrl; @@ -157,7 +152,7 @@ static int smc911x_send(struct eth_device *dev, void *packet, int length) tmplen = (length + 3) / 4; while (tmplen--) - pkt_data_push(dev, TX_DATA_FIFO, *data++); + smc911x_reg_write(dev, TX_DATA_FIFO, *data++); /* wait for transmission */ while (!((smc911x_reg_read(dev, TX_FIFO_INF) & @@ -203,7 +198,7 @@ static int smc911x_rx(struct eth_device *dev) tmplen = (pktlen + 3) / 4; while (tmplen--) - *data++ = pkt_data_pull(dev, RX_DATA_FIFO); + *data++ = smc911x_reg_read(dev, RX_DATA_FIFO); if (status & RX_STS_ES) printf(DRIVERNAME -- cgit v1.3.1 From 882d5f6983ff23b6f09899bb43d6dfd90ed7492f Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sun, 15 Mar 2020 15:14:18 +0100 Subject: net: smc911x: Replace malloc()+memset() with calloc() Replace combination of malloc()+memset() with calloc() as the behavior is exactly the same and the amount of code is reduced. Signed-off-by: Marek Vasut Cc: Joe Hershberger Cc: Masahiro Yamada --- drivers/net/smc911x.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/smc911x.c b/drivers/net/smc911x.c index 24b4eaeb3fd..2c72e3469d5 100644 --- a/drivers/net/smc911x.c +++ b/drivers/net/smc911x.c @@ -242,11 +242,9 @@ int smc911x_initialize(u8 dev_num, int base_addr) unsigned long addrl, addrh; struct eth_device *dev; - dev = malloc(sizeof(*dev)); - if (!dev) { - return -1; - } - memset(dev, 0, sizeof(*dev)); + dev = calloc(1, sizeof(*dev)); + if (!dev) + return -ENOMEM; dev->iobase = base_addr; -- cgit v1.3.1 From 49af0cb5a61c821d416ef069c6950d82523db585 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sun, 15 Mar 2020 15:40:15 +0100 Subject: net: smc911x: Rename smc911x_rx() to smc911x_recv() Rename the function to keep the naming scheme consistent, no functional change. Signed-off-by: Marek Vasut Cc: Joe Hershberger Cc: Masahiro Yamada --- drivers/net/smc911x.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/smc911x.c b/drivers/net/smc911x.c index 2c72e3469d5..6da6c895469 100644 --- a/drivers/net/smc911x.c +++ b/drivers/net/smc911x.c @@ -184,7 +184,7 @@ static void smc911x_halt(struct eth_device *dev) smc911x_handle_mac_address(dev); } -static int smc911x_rx(struct eth_device *dev) +static int smc911x_recv(struct eth_device *dev) { u32 *data = (u32 *)net_rx_packets[0]; u32 pktlen, tmplen; @@ -269,7 +269,7 @@ int smc911x_initialize(u8 dev_num, int base_addr) dev->init = smc911x_init; dev->halt = smc911x_halt; dev->send = smc911x_send; - dev->recv = smc911x_rx; + dev->recv = smc911x_recv; sprintf(dev->name, "%s-%hu", DRIVERNAME, dev_num); eth_register(dev); -- cgit v1.3.1 From 6f6cf0083f466c49c97c175b0169a0cd31c35d63 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sun, 15 Mar 2020 15:43:20 +0100 Subject: net: smc911x: Invert the logic in smc911x_miiphy_{read,write}() Invert the logic in the aforementioned functions to reduce indent, no functional change. Signed-off-by: Marek Vasut Cc: Joe Hershberger Cc: Masahiro Yamada --- drivers/net/smc911x.c | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/smc911x.c b/drivers/net/smc911x.c index 6da6c895469..ceb4f812152 100644 --- a/drivers/net/smc911x.c +++ b/drivers/net/smc911x.c @@ -216,24 +216,29 @@ static int smc911x_recv(struct eth_device *dev) static int smc911x_miiphy_read(struct mii_dev *bus, int phy, int devad, int reg) { - u16 val = 0; struct eth_device *dev = eth_get_dev_by_name(bus->name); - if (dev) { - int retval = smc911x_eth_phy_read(dev, phy, reg, &val); - if (retval < 0) - return retval; - return val; - } - return -ENODEV; + u16 val = 0; + int ret; + + if (!dev) + return -ENODEV; + + ret = smc911x_eth_phy_read(dev, phy, reg, &val); + if (ret < 0) + return ret; + + return val; } /* wrapper for smc911x_eth_phy_write */ static int smc911x_miiphy_write(struct mii_dev *bus, int phy, int devad, int reg, u16 val) { struct eth_device *dev = eth_get_dev_by_name(bus->name); - if (dev) - return smc911x_eth_phy_write(dev, phy, reg, val); - return -ENODEV; + + if (!dev) + return -ENODEV; + + return smc911x_eth_phy_write(dev, phy, reg, val); } #endif -- cgit v1.3.1 From 9741795408d2fb907256899cd9403dd57b917358 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sun, 15 Mar 2020 15:57:14 +0100 Subject: net: smc911x: Fix potential memleak() in init fail path Fix memleak in the init fail path, where if allocation or registration of MDIO bus fails, then ethernet interface is not unregistered and the private data are not freed, yet the probe function reports a failure. Signed-off-by: Marek Vasut Cc: Joe Hershberger Cc: Masahiro Yamada --- drivers/net/smc911x.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/smc911x.c b/drivers/net/smc911x.c index ceb4f812152..4459da5945d 100644 --- a/drivers/net/smc911x.c +++ b/drivers/net/smc911x.c @@ -282,15 +282,23 @@ int smc911x_initialize(u8 dev_num, int base_addr) #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) int retval; struct mii_dev *mdiodev = mdio_alloc(); - if (!mdiodev) + if (!mdiodev) { + eth_unregister(dev); + free(dev); return -ENOMEM; + } + strncpy(mdiodev->name, dev->name, MDIO_NAME_LEN); mdiodev->read = smc911x_miiphy_read; mdiodev->write = smc911x_miiphy_write; retval = mdio_register(mdiodev); - if (retval < 0) + if (retval < 0) { + mdio_free(mdiodev); + eth_unregister(dev); + free(dev); return retval; + } #endif return 1; -- cgit v1.3.1 From f51a2f84969a1c88fb96414835a3b04883f3d8eb Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sat, 21 Mar 2020 17:25:41 +0100 Subject: net: smc911x: Pull MII registration into separate function Pull the MII interface registration into separate function to avoid the ifdeffery in smc911x_initialize(). Moreover, adjust the fail path such that we use goto labels. Signed-off-by: Marek Vasut Cc: Joe Hershberger Cc: Masahiro Yamada --- drivers/net/smc911x.c | 64 ++++++++++++++++++++++++++++++++------------------- 1 file changed, 40 insertions(+), 24 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/smc911x.c b/drivers/net/smc911x.c index 4459da5945d..65c25f3bfd3 100644 --- a/drivers/net/smc911x.c +++ b/drivers/net/smc911x.c @@ -240,12 +240,39 @@ static int smc911x_miiphy_write(struct mii_dev *bus, int phy, int devad, return smc911x_eth_phy_write(dev, phy, reg, val); } + +static int smc911x_initialize_mii(struct eth_device *dev) +{ + struct mii_dev *mdiodev = mdio_alloc(); + int ret; + + if (!mdiodev) + return -ENOMEM; + + strncpy(mdiodev->name, dev->name, MDIO_NAME_LEN); + mdiodev->read = smc911x_miiphy_read; + mdiodev->write = smc911x_miiphy_write; + + ret = mdio_register(mdiodev); + if (ret < 0) { + mdio_free(mdiodev); + return ret; + } + + return 0; +} +#else +static int smc911x_initialize_mii(struct eth_device *dev) +{ + return 0; +} #endif int smc911x_initialize(u8 dev_num, int base_addr) { unsigned long addrl, addrh; struct eth_device *dev; + int ret; dev = calloc(1, sizeof(*dev)); if (!dev) @@ -254,9 +281,10 @@ int smc911x_initialize(u8 dev_num, int base_addr) dev->iobase = base_addr; /* Try to detect chip. Will fail if not present. */ - if (smc911x_detect_chip(dev)) { - free(dev); - return 0; + ret = smc911x_detect_chip(dev); + if (ret) { + ret = 0; /* Card not detected is not an error */ + goto err_detect; } addrh = smc911x_get_mac_csr(dev, ADDRH); @@ -279,27 +307,15 @@ int smc911x_initialize(u8 dev_num, int base_addr) eth_register(dev); -#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) - int retval; - struct mii_dev *mdiodev = mdio_alloc(); - if (!mdiodev) { - eth_unregister(dev); - free(dev); - return -ENOMEM; - } - - strncpy(mdiodev->name, dev->name, MDIO_NAME_LEN); - mdiodev->read = smc911x_miiphy_read; - mdiodev->write = smc911x_miiphy_write; - - retval = mdio_register(mdiodev); - if (retval < 0) { - mdio_free(mdiodev); - eth_unregister(dev); - free(dev); - return retval; - } -#endif + ret = smc911x_initialize_mii(dev); + if (ret) + goto err_mii; return 1; + +err_mii: + eth_unregister(dev); +err_detect: + free(dev); + return ret; } -- cgit v1.3.1 From eb46efa381d6dedb03af77d74b896ff40f1591b8 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sun, 15 Mar 2020 15:03:07 +0100 Subject: net: smc911x: Inline all functions from header file Inline all the functions from the header file, as they are not used outside of the driver or the standalone EEPROM example. Note that this does introduce considerable amount of duplication in the standalone EEPROM example, however that one has to be rewritten anyway, roughly such that the SMC911x driver would expose DM EEPROM interface and the standalone example would use that. Signed-off-by: Marek Vasut Cc: Joe Hershberger Cc: Masahiro Yamada --- drivers/net/smc911x.c | 157 ++++++++++++++++++++++++++++++++++- drivers/net/smc911x.h | 157 ----------------------------------- examples/standalone/smc911x_eeprom.c | 156 ++++++++++++++++++++++++++++++++++ 3 files changed, 312 insertions(+), 158 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/smc911x.c b/drivers/net/smc911x.c index 65c25f3bfd3..ff285f14b4b 100644 --- a/drivers/net/smc911x.c +++ b/drivers/net/smc911x.c @@ -10,9 +10,165 @@ #include #include #include +#include #include "smc911x.h" +struct chip_id { + u16 id; + char *name; +}; + +static const struct chip_id chip_ids[] = { + { CHIP_89218, "LAN89218" }, + { CHIP_9115, "LAN9115" }, + { CHIP_9116, "LAN9116" }, + { CHIP_9117, "LAN9117" }, + { CHIP_9118, "LAN9118" }, + { CHIP_9211, "LAN9211" }, + { CHIP_9215, "LAN9215" }, + { CHIP_9216, "LAN9216" }, + { CHIP_9217, "LAN9217" }, + { CHIP_9218, "LAN9218" }, + { CHIP_9220, "LAN9220" }, + { CHIP_9221, "LAN9221" }, + { 0, NULL }, +}; + +#define DRIVERNAME "smc911x" + +#if defined (CONFIG_SMC911X_32_BIT) && \ + defined (CONFIG_SMC911X_16_BIT) +#error "SMC911X: Only one of CONFIG_SMC911X_32_BIT and \ + CONFIG_SMC911X_16_BIT shall be set" +#endif + +#if defined (CONFIG_SMC911X_32_BIT) +static inline u32 __smc911x_reg_read(struct eth_device *dev, u32 offset) +{ + return *(volatile u32*)(dev->iobase + offset); +} +u32 smc911x_reg_read(struct eth_device *dev, u32 offset) + __attribute__((weak, alias("__smc911x_reg_read"))); + +static inline void __smc911x_reg_write(struct eth_device *dev, + u32 offset, u32 val) +{ + *(volatile u32*)(dev->iobase + offset) = val; +} +void smc911x_reg_write(struct eth_device *dev, u32 offset, u32 val) + __attribute__((weak, alias("__smc911x_reg_write"))); +#elif defined (CONFIG_SMC911X_16_BIT) +static inline u32 smc911x_reg_read(struct eth_device *dev, u32 offset) +{ + volatile u16 *addr_16 = (u16 *)(dev->iobase + offset); + return ((*addr_16 & 0x0000ffff) | (*(addr_16 + 1) << 16)); +} +static inline void smc911x_reg_write(struct eth_device *dev, + u32 offset, u32 val) +{ + *(volatile u16 *)(dev->iobase + offset) = (u16)val; + *(volatile u16 *)(dev->iobase + offset + 2) = (u16)(val >> 16); +} +#else +#error "SMC911X: undefined bus width" +#endif /* CONFIG_SMC911X_16_BIT */ + +static u32 smc911x_get_mac_csr(struct eth_device *dev, u8 reg) +{ + while (smc911x_reg_read(dev, MAC_CSR_CMD) & MAC_CSR_CMD_CSR_BUSY) + ; + smc911x_reg_write(dev, MAC_CSR_CMD, + MAC_CSR_CMD_CSR_BUSY | MAC_CSR_CMD_R_NOT_W | reg); + while (smc911x_reg_read(dev, MAC_CSR_CMD) & MAC_CSR_CMD_CSR_BUSY) + ; + + return smc911x_reg_read(dev, MAC_CSR_DATA); +} + +static void smc911x_set_mac_csr(struct eth_device *dev, u8 reg, u32 data) +{ + while (smc911x_reg_read(dev, MAC_CSR_CMD) & MAC_CSR_CMD_CSR_BUSY) + ; + smc911x_reg_write(dev, MAC_CSR_DATA, data); + smc911x_reg_write(dev, MAC_CSR_CMD, MAC_CSR_CMD_CSR_BUSY | reg); + while (smc911x_reg_read(dev, MAC_CSR_CMD) & MAC_CSR_CMD_CSR_BUSY) + ; +} + +static int smc911x_detect_chip(struct eth_device *dev) +{ + unsigned long val, i; + + val = smc911x_reg_read(dev, BYTE_TEST); + if (val == 0xffffffff) { + /* Special case -- no chip present */ + return -1; + } else if (val != 0x87654321) { + printf(DRIVERNAME ": Invalid chip endian 0x%08lx\n", val); + return -1; + } + + val = smc911x_reg_read(dev, ID_REV) >> 16; + for (i = 0; chip_ids[i].id != 0; i++) { + if (chip_ids[i].id == val) break; + } + if (!chip_ids[i].id) { + printf(DRIVERNAME ": Unknown chip ID %04lx\n", val); + return -1; + } + + dev->priv = (void *)&chip_ids[i]; + + return 0; +} + +static void smc911x_reset(struct eth_device *dev) +{ + int timeout; + + /* + * Take out of PM setting first + * Device is already wake up if PMT_CTRL_READY bit is set + */ + if ((smc911x_reg_read(dev, PMT_CTRL) & PMT_CTRL_READY) == 0) { + /* Write to the bytetest will take out of powerdown */ + smc911x_reg_write(dev, BYTE_TEST, 0x0); + + timeout = 10; + + while (timeout-- && + !(smc911x_reg_read(dev, PMT_CTRL) & PMT_CTRL_READY)) + udelay(10); + if (timeout < 0) { + printf(DRIVERNAME + ": timeout waiting for PM restore\n"); + return; + } + } + + /* Disable interrupts */ + smc911x_reg_write(dev, INT_EN, 0); + + smc911x_reg_write(dev, HW_CFG, HW_CFG_SRST); + + timeout = 1000; + while (timeout-- && smc911x_reg_read(dev, E2P_CMD) & E2P_CMD_EPC_BUSY) + udelay(10); + + if (timeout < 0) { + printf(DRIVERNAME ": reset timeout\n"); + return; + } + + /* Reset the FIFO level and flow control settings */ + smc911x_set_mac_csr(dev, FLOW, FLOW_FCPT | FLOW_FCEN); + smc911x_reg_write(dev, AFC_CFG, 0x0050287F); + + /* Set to LED outputs */ + smc911x_reg_write(dev, GPIO_CFG, 0x70070000); +} + static void smc911x_handle_mac_address(struct eth_device *dev) { unsigned long addrh, addrl; @@ -117,7 +273,6 @@ static void smc911x_enable(struct eth_device *dev) smc911x_set_mac_csr(dev, MAC_CR, MAC_CR_TXEN | MAC_CR_RXEN | MAC_CR_HBDIS); - } static int smc911x_init(struct eth_device *dev, bd_t * bd) diff --git a/drivers/net/smc911x.h b/drivers/net/smc911x.h index 3145fbde2bd..ce66900f4cf 100644 --- a/drivers/net/smc911x.h +++ b/drivers/net/smc911x.h @@ -8,47 +8,6 @@ #ifndef _SMC911X_H_ #define _SMC911X_H_ -#include - -#define DRIVERNAME "smc911x" - -#if defined (CONFIG_SMC911X_32_BIT) && \ - defined (CONFIG_SMC911X_16_BIT) -#error "SMC911X: Only one of CONFIG_SMC911X_32_BIT and \ - CONFIG_SMC911X_16_BIT shall be set" -#endif - -#if defined (CONFIG_SMC911X_32_BIT) -static inline u32 __smc911x_reg_read(struct eth_device *dev, u32 offset) -{ - return *(volatile u32*)(dev->iobase + offset); -} -u32 smc911x_reg_read(struct eth_device *dev, u32 offset) - __attribute__((weak, alias("__smc911x_reg_read"))); - -static inline void __smc911x_reg_write(struct eth_device *dev, - u32 offset, u32 val) -{ - *(volatile u32*)(dev->iobase + offset) = val; -} -void smc911x_reg_write(struct eth_device *dev, u32 offset, u32 val) - __attribute__((weak, alias("__smc911x_reg_write"))); -#elif defined (CONFIG_SMC911X_16_BIT) -static inline u32 smc911x_reg_read(struct eth_device *dev, u32 offset) -{ - volatile u16 *addr_16 = (u16 *)(dev->iobase + offset); - return ((*addr_16 & 0x0000ffff) | (*(addr_16 + 1) << 16)); -} -static inline void smc911x_reg_write(struct eth_device *dev, - u32 offset, u32 val) -{ - *(volatile u16 *)(dev->iobase + offset) = (u16)val; - *(volatile u16 *)(dev->iobase + offset + 2) = (u16)(val >> 16); -} -#else -#error "SMC911X: undefined bus width" -#endif /* CONFIG_SMC911X_16_BIT */ - /* Below are the register offsets and bit definitions * of the Lan911x memory space */ @@ -380,120 +339,4 @@ static inline void smc911x_reg_write(struct eth_device *dev, #define CHIP_9220 0x9220 #define CHIP_9221 0x9221 -struct chip_id { - u16 id; - char *name; -}; - -static const struct chip_id chip_ids[] = { - { CHIP_89218, "LAN89218" }, - { CHIP_9115, "LAN9115" }, - { CHIP_9116, "LAN9116" }, - { CHIP_9117, "LAN9117" }, - { CHIP_9118, "LAN9118" }, - { CHIP_9211, "LAN9211" }, - { CHIP_9215, "LAN9215" }, - { CHIP_9216, "LAN9216" }, - { CHIP_9217, "LAN9217" }, - { CHIP_9218, "LAN9218" }, - { CHIP_9220, "LAN9220" }, - { CHIP_9221, "LAN9221" }, - { 0, NULL }, -}; - -static u32 smc911x_get_mac_csr(struct eth_device *dev, u8 reg) -{ - while (smc911x_reg_read(dev, MAC_CSR_CMD) & MAC_CSR_CMD_CSR_BUSY) - ; - smc911x_reg_write(dev, MAC_CSR_CMD, - MAC_CSR_CMD_CSR_BUSY | MAC_CSR_CMD_R_NOT_W | reg); - while (smc911x_reg_read(dev, MAC_CSR_CMD) & MAC_CSR_CMD_CSR_BUSY) - ; - - return smc911x_reg_read(dev, MAC_CSR_DATA); -} - -static void smc911x_set_mac_csr(struct eth_device *dev, u8 reg, u32 data) -{ - while (smc911x_reg_read(dev, MAC_CSR_CMD) & MAC_CSR_CMD_CSR_BUSY) - ; - smc911x_reg_write(dev, MAC_CSR_DATA, data); - smc911x_reg_write(dev, MAC_CSR_CMD, MAC_CSR_CMD_CSR_BUSY | reg); - while (smc911x_reg_read(dev, MAC_CSR_CMD) & MAC_CSR_CMD_CSR_BUSY) - ; -} - -static int smc911x_detect_chip(struct eth_device *dev) -{ - unsigned long val, i; - - val = smc911x_reg_read(dev, BYTE_TEST); - if (val == 0xffffffff) { - /* Special case -- no chip present */ - return -1; - } else if (val != 0x87654321) { - printf(DRIVERNAME ": Invalid chip endian 0x%08lx\n", val); - return -1; - } - - val = smc911x_reg_read(dev, ID_REV) >> 16; - for (i = 0; chip_ids[i].id != 0; i++) { - if (chip_ids[i].id == val) break; - } - if (!chip_ids[i].id) { - printf(DRIVERNAME ": Unknown chip ID %04lx\n", val); - return -1; - } - - dev->priv = (void *)&chip_ids[i]; - - return 0; -} - -static void smc911x_reset(struct eth_device *dev) -{ - int timeout; - - /* - * Take out of PM setting first - * Device is already wake up if PMT_CTRL_READY bit is set - */ - if ((smc911x_reg_read(dev, PMT_CTRL) & PMT_CTRL_READY) == 0) { - /* Write to the bytetest will take out of powerdown */ - smc911x_reg_write(dev, BYTE_TEST, 0x0); - - timeout = 10; - - while (timeout-- && - !(smc911x_reg_read(dev, PMT_CTRL) & PMT_CTRL_READY)) - udelay(10); - if (timeout < 0) { - printf(DRIVERNAME - ": timeout waiting for PM restore\n"); - return; - } - } - - /* Disable interrupts */ - smc911x_reg_write(dev, INT_EN, 0); - - smc911x_reg_write(dev, HW_CFG, HW_CFG_SRST); - - timeout = 1000; - while (timeout-- && smc911x_reg_read(dev, E2P_CMD) & E2P_CMD_EPC_BUSY) - udelay(10); - - if (timeout < 0) { - printf(DRIVERNAME ": reset timeout\n"); - return; - } - - /* Reset the FIFO level and flow control settings */ - smc911x_set_mac_csr(dev, FLOW, FLOW_FCPT | FLOW_FCEN); - smc911x_reg_write(dev, AFC_CFG, 0x0050287F); - - /* Set to LED outputs */ - smc911x_reg_write(dev, GPIO_CFG, 0x70070000); -} - #endif diff --git a/examples/standalone/smc911x_eeprom.c b/examples/standalone/smc911x_eeprom.c index 2c05ed902d0..19ad9e6297c 100644 --- a/examples/standalone/smc911x_eeprom.c +++ b/examples/standalone/smc911x_eeprom.c @@ -18,8 +18,164 @@ #include #include #include +#include #include "../drivers/net/smc911x.h" +#define DRIVERNAME "smc911x" + +#if defined (CONFIG_SMC911X_32_BIT) && \ + defined (CONFIG_SMC911X_16_BIT) +#error "SMC911X: Only one of CONFIG_SMC911X_32_BIT and \ + CONFIG_SMC911X_16_BIT shall be set" +#endif + +struct chip_id { + u16 id; + char *name; +}; + +static const struct chip_id chip_ids[] = { + { CHIP_89218, "LAN89218" }, + { CHIP_9115, "LAN9115" }, + { CHIP_9116, "LAN9116" }, + { CHIP_9117, "LAN9117" }, + { CHIP_9118, "LAN9118" }, + { CHIP_9211, "LAN9211" }, + { CHIP_9215, "LAN9215" }, + { CHIP_9216, "LAN9216" }, + { CHIP_9217, "LAN9217" }, + { CHIP_9218, "LAN9218" }, + { CHIP_9220, "LAN9220" }, + { CHIP_9221, "LAN9221" }, + { 0, NULL }, +}; + +#if defined (CONFIG_SMC911X_32_BIT) +static inline u32 __smc911x_reg_read(struct eth_device *dev, u32 offset) +{ + return *(volatile u32*)(dev->iobase + offset); +} +u32 smc911x_reg_read(struct eth_device *dev, u32 offset) + __attribute__((weak, alias("__smc911x_reg_read"))); + +static inline void __smc911x_reg_write(struct eth_device *dev, + u32 offset, u32 val) +{ + *(volatile u32*)(dev->iobase + offset) = val; +} +void smc911x_reg_write(struct eth_device *dev, u32 offset, u32 val) + __attribute__((weak, alias("__smc911x_reg_write"))); +#elif defined (CONFIG_SMC911X_16_BIT) +static inline u32 smc911x_reg_read(struct eth_device *dev, u32 offset) +{ + volatile u16 *addr_16 = (u16 *)(dev->iobase + offset); + return ((*addr_16 & 0x0000ffff) | (*(addr_16 + 1) << 16)); +} +static inline void smc911x_reg_write(struct eth_device *dev, + u32 offset, u32 val) +{ + *(volatile u16 *)(dev->iobase + offset) = (u16)val; + *(volatile u16 *)(dev->iobase + offset + 2) = (u16)(val >> 16); +} +#else +#error "SMC911X: undefined bus width" +#endif /* CONFIG_SMC911X_16_BIT */ + +static u32 smc911x_get_mac_csr(struct eth_device *dev, u8 reg) +{ + while (smc911x_reg_read(dev, MAC_CSR_CMD) & MAC_CSR_CMD_CSR_BUSY) + ; + smc911x_reg_write(dev, MAC_CSR_CMD, + MAC_CSR_CMD_CSR_BUSY | MAC_CSR_CMD_R_NOT_W | reg); + while (smc911x_reg_read(dev, MAC_CSR_CMD) & MAC_CSR_CMD_CSR_BUSY) + ; + + return smc911x_reg_read(dev, MAC_CSR_DATA); +} + +static void smc911x_set_mac_csr(struct eth_device *dev, u8 reg, u32 data) +{ + while (smc911x_reg_read(dev, MAC_CSR_CMD) & MAC_CSR_CMD_CSR_BUSY) + ; + smc911x_reg_write(dev, MAC_CSR_DATA, data); + smc911x_reg_write(dev, MAC_CSR_CMD, MAC_CSR_CMD_CSR_BUSY | reg); + while (smc911x_reg_read(dev, MAC_CSR_CMD) & MAC_CSR_CMD_CSR_BUSY) + ; +} + +static int smc911x_detect_chip(struct eth_device *dev) +{ + unsigned long val, i; + + val = smc911x_reg_read(dev, BYTE_TEST); + if (val == 0xffffffff) { + /* Special case -- no chip present */ + return -1; + } else if (val != 0x87654321) { + printf(DRIVERNAME ": Invalid chip endian 0x%08lx\n", val); + return -1; + } + + val = smc911x_reg_read(dev, ID_REV) >> 16; + for (i = 0; chip_ids[i].id != 0; i++) { + if (chip_ids[i].id == val) break; + } + if (!chip_ids[i].id) { + printf(DRIVERNAME ": Unknown chip ID %04lx\n", val); + return -1; + } + + dev->priv = (void *)&chip_ids[i]; + + return 0; +} + +static void smc911x_reset(struct eth_device *dev) +{ + int timeout; + + /* + * Take out of PM setting first + * Device is already wake up if PMT_CTRL_READY bit is set + */ + if ((smc911x_reg_read(dev, PMT_CTRL) & PMT_CTRL_READY) == 0) { + /* Write to the bytetest will take out of powerdown */ + smc911x_reg_write(dev, BYTE_TEST, 0x0); + + timeout = 10; + + while (timeout-- && + !(smc911x_reg_read(dev, PMT_CTRL) & PMT_CTRL_READY)) + udelay(10); + if (timeout < 0) { + printf(DRIVERNAME + ": timeout waiting for PM restore\n"); + return; + } + } + + /* Disable interrupts */ + smc911x_reg_write(dev, INT_EN, 0); + + smc911x_reg_write(dev, HW_CFG, HW_CFG_SRST); + + timeout = 1000; + while (timeout-- && smc911x_reg_read(dev, E2P_CMD) & E2P_CMD_EPC_BUSY) + udelay(10); + + if (timeout < 0) { + printf(DRIVERNAME ": reset timeout\n"); + return; + } + + /* Reset the FIFO level and flow control settings */ + smc911x_set_mac_csr(dev, FLOW, FLOW_FCPT | FLOW_FCEN); + smc911x_reg_write(dev, AFC_CFG, 0x0050287F); + + /* Set to LED outputs */ + smc911x_reg_write(dev, GPIO_CFG, 0x70070000); +} + /** * smsc_ctrlc - detect press of CTRL+C (common ctrlc() isnt exported!?) */ -- cgit v1.3.1 From f0d73f5cd0ec0967fffcdf130a8c016262a216c4 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sun, 15 Mar 2020 14:38:59 +0100 Subject: net: smc911x: Drop weak alias from 32bit accessors These accessors are not overridden by any board, and even if they were, this is something which should be handled via DM now, so remove the weak alias option. Moreover, drop the inline keyword, as the compiler can decide better. Signed-off-by: Marek Vasut Cc: Joe Hershberger Cc: Masahiro Yamada --- drivers/net/smc911x.c | 14 ++++---------- examples/standalone/smc911x_eeprom.c | 16 +++++----------- 2 files changed, 9 insertions(+), 21 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/smc911x.c b/drivers/net/smc911x.c index ff285f14b4b..effee5367ca 100644 --- a/drivers/net/smc911x.c +++ b/drivers/net/smc911x.c @@ -44,28 +44,22 @@ static const struct chip_id chip_ids[] = { #endif #if defined (CONFIG_SMC911X_32_BIT) -static inline u32 __smc911x_reg_read(struct eth_device *dev, u32 offset) +static u32 smc911x_reg_read(struct eth_device *dev, u32 offset) { return *(volatile u32*)(dev->iobase + offset); } -u32 smc911x_reg_read(struct eth_device *dev, u32 offset) - __attribute__((weak, alias("__smc911x_reg_read"))); -static inline void __smc911x_reg_write(struct eth_device *dev, - u32 offset, u32 val) +static void smc911x_reg_write(struct eth_device *dev, u32 offset, u32 val) { *(volatile u32*)(dev->iobase + offset) = val; } -void smc911x_reg_write(struct eth_device *dev, u32 offset, u32 val) - __attribute__((weak, alias("__smc911x_reg_write"))); #elif defined (CONFIG_SMC911X_16_BIT) -static inline u32 smc911x_reg_read(struct eth_device *dev, u32 offset) +static u32 smc911x_reg_read(struct eth_device *dev, u32 offset) { volatile u16 *addr_16 = (u16 *)(dev->iobase + offset); return ((*addr_16 & 0x0000ffff) | (*(addr_16 + 1) << 16)); } -static inline void smc911x_reg_write(struct eth_device *dev, - u32 offset, u32 val) +static void smc911x_reg_write(struct eth_device *dev, u32 offset, u32 val) { *(volatile u16 *)(dev->iobase + offset) = (u16)val; *(volatile u16 *)(dev->iobase + offset + 2) = (u16)(val >> 16); diff --git a/examples/standalone/smc911x_eeprom.c b/examples/standalone/smc911x_eeprom.c index 19ad9e6297c..270588bcf5e 100644 --- a/examples/standalone/smc911x_eeprom.c +++ b/examples/standalone/smc911x_eeprom.c @@ -51,28 +51,22 @@ static const struct chip_id chip_ids[] = { }; #if defined (CONFIG_SMC911X_32_BIT) -static inline u32 __smc911x_reg_read(struct eth_device *dev, u32 offset) +static u32 smc911x_reg_read(struct eth_device *dev, u32 offset) { return *(volatile u32*)(dev->iobase + offset); } -u32 smc911x_reg_read(struct eth_device *dev, u32 offset) - __attribute__((weak, alias("__smc911x_reg_read"))); -static inline void __smc911x_reg_write(struct eth_device *dev, - u32 offset, u32 val) +static void smc911x_reg_write(struct eth_device *dev, u32 offset, u32 val) { *(volatile u32*)(dev->iobase + offset) = val; } -void smc911x_reg_write(struct eth_device *dev, u32 offset, u32 val) - __attribute__((weak, alias("__smc911x_reg_write"))); #elif defined (CONFIG_SMC911X_16_BIT) -static inline u32 smc911x_reg_read(struct eth_device *dev, u32 offset) +static u32 smc911x_reg_read(struct eth_device *dev, u32 offset) { volatile u16 *addr_16 = (u16 *)(dev->iobase + offset); - return ((*addr_16 & 0x0000ffff) | (*(addr_16 + 1) << 16)); + return (*addr_16 & 0x0000ffff) | (*(addr_16 + 1) << 16); } -static inline void smc911x_reg_write(struct eth_device *dev, - u32 offset, u32 val) +static void smc911x_reg_write(struct eth_device *dev, u32 offset, u32 val) { *(volatile u16 *)(dev->iobase + offset) = (u16)val; *(volatile u16 *)(dev->iobase + offset + 2) = (u16)(val >> 16); -- cgit v1.3.1 From ba267c781da73ab0df4a7a57c05ef21c19aee609 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sun, 15 Mar 2020 14:42:23 +0100 Subject: net: smc911x: Convert IO accessors to {read,write}{w,l}() Convert the IO accessors to standard ones instead of using volatile void pointers, as those do not cover all the bus access details. Signed-off-by: Marek Vasut Cc: Joe Hershberger Cc: Masahiro Yamada --- drivers/net/smc911x.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/smc911x.c b/drivers/net/smc911x.c index effee5367ca..364f8c5da8d 100644 --- a/drivers/net/smc911x.c +++ b/drivers/net/smc911x.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include "smc911x.h" @@ -46,23 +47,23 @@ static const struct chip_id chip_ids[] = { #if defined (CONFIG_SMC911X_32_BIT) static u32 smc911x_reg_read(struct eth_device *dev, u32 offset) { - return *(volatile u32*)(dev->iobase + offset); + return readl(dev->iobase + offset); } static void smc911x_reg_write(struct eth_device *dev, u32 offset, u32 val) { - *(volatile u32*)(dev->iobase + offset) = val; + writel(val, dev->iobase + offset); } #elif defined (CONFIG_SMC911X_16_BIT) static u32 smc911x_reg_read(struct eth_device *dev, u32 offset) { - volatile u16 *addr_16 = (u16 *)(dev->iobase + offset); - return ((*addr_16 & 0x0000ffff) | (*(addr_16 + 1) << 16)); + return (readw(dev->iobase + offset) & 0xffff) | + (readw(dev->iobase + offset + 2) << 16); } static void smc911x_reg_write(struct eth_device *dev, u32 offset, u32 val) { - *(volatile u16 *)(dev->iobase + offset) = (u16)val; - *(volatile u16 *)(dev->iobase + offset + 2) = (u16)(val >> 16); + writew(val & 0xffff, dev->iobase + offset); + writew(val >> 16, dev->iobase + offset + 2); } #else #error "SMC911X: undefined bus width" -- cgit v1.3.1 From 3dbab926031fe77d794670c05d6c7badcfa77291 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sun, 15 Mar 2020 15:36:09 +0100 Subject: net: smc911x: Pass around driver private data Introduce a private data structure for this driver with embedded struct eth_device and pass it around. This prepares the driver to work with both DM and non-DM systems. Signed-off-by: Marek Vasut Cc: Joe Hershberger Cc: Masahiro Yamada --- drivers/net/smc911x.c | 232 +++++++++++++++++++++++++++----------------------- 1 file changed, 124 insertions(+), 108 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/smc911x.c b/drivers/net/smc911x.c index 364f8c5da8d..07066ce1083 100644 --- a/drivers/net/smc911x.c +++ b/drivers/net/smc911x.c @@ -20,6 +20,13 @@ struct chip_id { char *name; }; +struct smc911x_priv { + struct eth_device dev; + phys_addr_t iobase; + const struct chip_id *chipid; + unsigned char enetaddr[6]; +}; + static const struct chip_id chip_ids[] = { { CHIP_89218, "LAN89218" }, { CHIP_9115, "LAN9115" }, @@ -45,57 +52,57 @@ static const struct chip_id chip_ids[] = { #endif #if defined (CONFIG_SMC911X_32_BIT) -static u32 smc911x_reg_read(struct eth_device *dev, u32 offset) +static u32 smc911x_reg_read(struct smc911x_priv *priv, u32 offset) { - return readl(dev->iobase + offset); + return readl(priv->iobase + offset); } -static void smc911x_reg_write(struct eth_device *dev, u32 offset, u32 val) +static void smc911x_reg_write(struct smc911x_priv *priv, u32 offset, u32 val) { - writel(val, dev->iobase + offset); + writel(val, priv->iobase + offset); } #elif defined (CONFIG_SMC911X_16_BIT) -static u32 smc911x_reg_read(struct eth_device *dev, u32 offset) +static u32 smc911x_reg_read(struct smc911x_priv *priv, u32 offset) { - return (readw(dev->iobase + offset) & 0xffff) | - (readw(dev->iobase + offset + 2) << 16); + return (readw(priv->iobase + offset) & 0xffff) | + (readw(priv->iobase + offset + 2) << 16); } -static void smc911x_reg_write(struct eth_device *dev, u32 offset, u32 val) +static void smc911x_reg_write(struct smc911x_priv *priv, u32 offset, u32 val) { - writew(val & 0xffff, dev->iobase + offset); - writew(val >> 16, dev->iobase + offset + 2); + writew(val & 0xffff, priv->iobase + offset); + writew(val >> 16, priv->iobase + offset + 2); } #else #error "SMC911X: undefined bus width" #endif /* CONFIG_SMC911X_16_BIT */ -static u32 smc911x_get_mac_csr(struct eth_device *dev, u8 reg) +static u32 smc911x_get_mac_csr(struct smc911x_priv *priv, u8 reg) { - while (smc911x_reg_read(dev, MAC_CSR_CMD) & MAC_CSR_CMD_CSR_BUSY) + while (smc911x_reg_read(priv, MAC_CSR_CMD) & MAC_CSR_CMD_CSR_BUSY) ; - smc911x_reg_write(dev, MAC_CSR_CMD, + smc911x_reg_write(priv, MAC_CSR_CMD, MAC_CSR_CMD_CSR_BUSY | MAC_CSR_CMD_R_NOT_W | reg); - while (smc911x_reg_read(dev, MAC_CSR_CMD) & MAC_CSR_CMD_CSR_BUSY) + while (smc911x_reg_read(priv, MAC_CSR_CMD) & MAC_CSR_CMD_CSR_BUSY) ; - return smc911x_reg_read(dev, MAC_CSR_DATA); + return smc911x_reg_read(priv, MAC_CSR_DATA); } -static void smc911x_set_mac_csr(struct eth_device *dev, u8 reg, u32 data) +static void smc911x_set_mac_csr(struct smc911x_priv *priv, u8 reg, u32 data) { - while (smc911x_reg_read(dev, MAC_CSR_CMD) & MAC_CSR_CMD_CSR_BUSY) + while (smc911x_reg_read(priv, MAC_CSR_CMD) & MAC_CSR_CMD_CSR_BUSY) ; - smc911x_reg_write(dev, MAC_CSR_DATA, data); - smc911x_reg_write(dev, MAC_CSR_CMD, MAC_CSR_CMD_CSR_BUSY | reg); - while (smc911x_reg_read(dev, MAC_CSR_CMD) & MAC_CSR_CMD_CSR_BUSY) + smc911x_reg_write(priv, MAC_CSR_DATA, data); + smc911x_reg_write(priv, MAC_CSR_CMD, MAC_CSR_CMD_CSR_BUSY | reg); + while (smc911x_reg_read(priv, MAC_CSR_CMD) & MAC_CSR_CMD_CSR_BUSY) ; } -static int smc911x_detect_chip(struct eth_device *dev) +static int smc911x_detect_chip(struct smc911x_priv *priv) { unsigned long val, i; - val = smc911x_reg_read(dev, BYTE_TEST); + val = smc911x_reg_read(priv, BYTE_TEST); if (val == 0xffffffff) { /* Special case -- no chip present */ return -1; @@ -104,7 +111,7 @@ static int smc911x_detect_chip(struct eth_device *dev) return -1; } - val = smc911x_reg_read(dev, ID_REV) >> 16; + val = smc911x_reg_read(priv, ID_REV) >> 16; for (i = 0; chip_ids[i].id != 0; i++) { if (chip_ids[i].id == val) break; } @@ -113,12 +120,12 @@ static int smc911x_detect_chip(struct eth_device *dev) return -1; } - dev->priv = (void *)&chip_ids[i]; + priv->chipid = &chip_ids[i]; return 0; } -static void smc911x_reset(struct eth_device *dev) +static void smc911x_reset(struct smc911x_priv *priv) { int timeout; @@ -126,14 +133,14 @@ static void smc911x_reset(struct eth_device *dev) * Take out of PM setting first * Device is already wake up if PMT_CTRL_READY bit is set */ - if ((smc911x_reg_read(dev, PMT_CTRL) & PMT_CTRL_READY) == 0) { + if ((smc911x_reg_read(priv, PMT_CTRL) & PMT_CTRL_READY) == 0) { /* Write to the bytetest will take out of powerdown */ - smc911x_reg_write(dev, BYTE_TEST, 0x0); + smc911x_reg_write(priv, BYTE_TEST, 0x0); timeout = 10; while (timeout-- && - !(smc911x_reg_read(dev, PMT_CTRL) & PMT_CTRL_READY)) + !(smc911x_reg_read(priv, PMT_CTRL) & PMT_CTRL_READY)) udelay(10); if (timeout < 0) { printf(DRIVERNAME @@ -143,12 +150,12 @@ static void smc911x_reset(struct eth_device *dev) } /* Disable interrupts */ - smc911x_reg_write(dev, INT_EN, 0); + smc911x_reg_write(priv, INT_EN, 0); - smc911x_reg_write(dev, HW_CFG, HW_CFG_SRST); + smc911x_reg_write(priv, HW_CFG, HW_CFG_SRST); timeout = 1000; - while (timeout-- && smc911x_reg_read(dev, E2P_CMD) & E2P_CMD_EPC_BUSY) + while (timeout-- && smc911x_reg_read(priv, E2P_CMD) & E2P_CMD_EPC_BUSY) udelay(10); if (timeout < 0) { @@ -157,83 +164,83 @@ static void smc911x_reset(struct eth_device *dev) } /* Reset the FIFO level and flow control settings */ - smc911x_set_mac_csr(dev, FLOW, FLOW_FCPT | FLOW_FCEN); - smc911x_reg_write(dev, AFC_CFG, 0x0050287F); + smc911x_set_mac_csr(priv, FLOW, FLOW_FCPT | FLOW_FCEN); + smc911x_reg_write(priv, AFC_CFG, 0x0050287F); /* Set to LED outputs */ - smc911x_reg_write(dev, GPIO_CFG, 0x70070000); + smc911x_reg_write(priv, GPIO_CFG, 0x70070000); } -static void smc911x_handle_mac_address(struct eth_device *dev) +static void smc911x_handle_mac_address(struct smc911x_priv *priv) { unsigned long addrh, addrl; - uchar *m = dev->enetaddr; + unsigned char *m = priv->enetaddr; addrl = m[0] | (m[1] << 8) | (m[2] << 16) | (m[3] << 24); addrh = m[4] | (m[5] << 8); - smc911x_set_mac_csr(dev, ADDRL, addrl); - smc911x_set_mac_csr(dev, ADDRH, addrh); + smc911x_set_mac_csr(priv, ADDRL, addrl); + smc911x_set_mac_csr(priv, ADDRH, addrh); printf(DRIVERNAME ": MAC %pM\n", m); } -static int smc911x_eth_phy_read(struct eth_device *dev, +static int smc911x_eth_phy_read(struct smc911x_priv *priv, u8 phy, u8 reg, u16 *val) { - while (smc911x_get_mac_csr(dev, MII_ACC) & MII_ACC_MII_BUSY) + while (smc911x_get_mac_csr(priv, MII_ACC) & MII_ACC_MII_BUSY) ; - smc911x_set_mac_csr(dev, MII_ACC, phy << 11 | reg << 6 | + smc911x_set_mac_csr(priv, MII_ACC, phy << 11 | reg << 6 | MII_ACC_MII_BUSY); - while (smc911x_get_mac_csr(dev, MII_ACC) & MII_ACC_MII_BUSY) + while (smc911x_get_mac_csr(priv, MII_ACC) & MII_ACC_MII_BUSY) ; - *val = smc911x_get_mac_csr(dev, MII_DATA); + *val = smc911x_get_mac_csr(priv, MII_DATA); return 0; } -static int smc911x_eth_phy_write(struct eth_device *dev, +static int smc911x_eth_phy_write(struct smc911x_priv *priv, u8 phy, u8 reg, u16 val) { - while (smc911x_get_mac_csr(dev, MII_ACC) & MII_ACC_MII_BUSY) + while (smc911x_get_mac_csr(priv, MII_ACC) & MII_ACC_MII_BUSY) ; - smc911x_set_mac_csr(dev, MII_DATA, val); - smc911x_set_mac_csr(dev, MII_ACC, + smc911x_set_mac_csr(priv, MII_DATA, val); + smc911x_set_mac_csr(priv, MII_ACC, phy << 11 | reg << 6 | MII_ACC_MII_BUSY | MII_ACC_MII_WRITE); - while (smc911x_get_mac_csr(dev, MII_ACC) & MII_ACC_MII_BUSY) + while (smc911x_get_mac_csr(priv, MII_ACC) & MII_ACC_MII_BUSY) ; return 0; } -static int smc911x_phy_reset(struct eth_device *dev) +static int smc911x_phy_reset(struct smc911x_priv *priv) { u32 reg; - reg = smc911x_reg_read(dev, PMT_CTRL); + reg = smc911x_reg_read(priv, PMT_CTRL); reg &= ~0xfffff030; reg |= PMT_CTRL_PHY_RST; - smc911x_reg_write(dev, PMT_CTRL, reg); + smc911x_reg_write(priv, PMT_CTRL, reg); mdelay(100); return 0; } -static void smc911x_phy_configure(struct eth_device *dev) +static void smc911x_phy_configure(struct smc911x_priv *priv) { int timeout; u16 status; - smc911x_phy_reset(dev); + smc911x_phy_reset(priv); - smc911x_eth_phy_write(dev, 1, MII_BMCR, BMCR_RESET); + smc911x_eth_phy_write(priv, 1, MII_BMCR, BMCR_RESET); mdelay(1); - smc911x_eth_phy_write(dev, 1, MII_ADVERTISE, 0x01e1); - smc911x_eth_phy_write(dev, 1, MII_BMCR, BMCR_ANENABLE | + smc911x_eth_phy_write(priv, 1, MII_ADVERTISE, 0x01e1); + smc911x_eth_phy_write(priv, 1, MII_BMCR, BMCR_ANENABLE | BMCR_ANRESTART); timeout = 5000; @@ -242,7 +249,7 @@ static void smc911x_phy_configure(struct eth_device *dev) if ((timeout--) == 0) goto err_out; - if (smc911x_eth_phy_read(dev, 1, MII_BMSR, &status) != 0) + if (smc911x_eth_phy_read(priv, 1, MII_BMSR, &status) != 0) goto err_out; } while (!(status & BMSR_LSTATUS)); @@ -254,64 +261,66 @@ err_out: printf(DRIVERNAME ": autonegotiation timed out\n"); } -static void smc911x_enable(struct eth_device *dev) +static void smc911x_enable(struct smc911x_priv *priv) { /* Enable TX */ - smc911x_reg_write(dev, HW_CFG, 8 << 16 | HW_CFG_SF); + smc911x_reg_write(priv, HW_CFG, 8 << 16 | HW_CFG_SF); - smc911x_reg_write(dev, GPT_CFG, GPT_CFG_TIMER_EN | 10000); + smc911x_reg_write(priv, GPT_CFG, GPT_CFG_TIMER_EN | 10000); - smc911x_reg_write(dev, TX_CFG, TX_CFG_TX_ON); + smc911x_reg_write(priv, TX_CFG, TX_CFG_TX_ON); /* no padding to start of packets */ - smc911x_reg_write(dev, RX_CFG, 0); + smc911x_reg_write(priv, RX_CFG, 0); - smc911x_set_mac_csr(dev, MAC_CR, MAC_CR_TXEN | MAC_CR_RXEN | + smc911x_set_mac_csr(priv, MAC_CR, MAC_CR_TXEN | MAC_CR_RXEN | MAC_CR_HBDIS); } static int smc911x_init(struct eth_device *dev, bd_t * bd) { - struct chip_id *id = dev->priv; + struct smc911x_priv *priv = container_of(dev, struct smc911x_priv, dev); + const struct chip_id *id = priv->chipid; printf(DRIVERNAME ": detected %s controller\n", id->name); - smc911x_reset(dev); + smc911x_reset(priv); /* Configure the PHY, initialize the link state */ - smc911x_phy_configure(dev); + smc911x_phy_configure(priv); - smc911x_handle_mac_address(dev); + smc911x_handle_mac_address(priv); /* Turn on Tx + Rx */ - smc911x_enable(dev); + smc911x_enable(priv); return 0; } static int smc911x_send(struct eth_device *dev, void *packet, int length) { + struct smc911x_priv *priv = container_of(dev, struct smc911x_priv, dev); u32 *data = (u32*)packet; u32 tmplen; u32 status; - smc911x_reg_write(dev, TX_DATA_FIFO, TX_CMD_A_INT_FIRST_SEG | + smc911x_reg_write(priv, TX_DATA_FIFO, TX_CMD_A_INT_FIRST_SEG | TX_CMD_A_INT_LAST_SEG | length); - smc911x_reg_write(dev, TX_DATA_FIFO, length); + smc911x_reg_write(priv, TX_DATA_FIFO, length); tmplen = (length + 3) / 4; while (tmplen--) - smc911x_reg_write(dev, TX_DATA_FIFO, *data++); + smc911x_reg_write(priv, TX_DATA_FIFO, *data++); /* wait for transmission */ - while (!((smc911x_reg_read(dev, TX_FIFO_INF) & + while (!((smc911x_reg_read(priv, TX_FIFO_INF) & TX_FIFO_INF_TSUSED) >> 16)); /* get status. Ignore 'no carrier' error, it has no meaning for * full duplex operation */ - status = smc911x_reg_read(dev, TX_STATUS_FIFO) & + status = smc911x_reg_read(priv, TX_STATUS_FIFO) & (TX_STS_LOC | TX_STS_LATE_COLL | TX_STS_MANY_COLL | TX_STS_MANY_DEFER | TX_STS_UNDERRUN); @@ -330,25 +339,28 @@ static int smc911x_send(struct eth_device *dev, void *packet, int length) static void smc911x_halt(struct eth_device *dev) { - smc911x_reset(dev); - smc911x_handle_mac_address(dev); + struct smc911x_priv *priv = container_of(dev, struct smc911x_priv, dev); + + smc911x_reset(priv); + smc911x_handle_mac_address(priv); } static int smc911x_recv(struct eth_device *dev) { + struct smc911x_priv *priv = container_of(dev, struct smc911x_priv, dev); u32 *data = (u32 *)net_rx_packets[0]; u32 pktlen, tmplen; u32 status; - if ((smc911x_reg_read(dev, RX_FIFO_INF) & RX_FIFO_INF_RXSUSED) >> 16) { - status = smc911x_reg_read(dev, RX_STATUS_FIFO); + if ((smc911x_reg_read(priv, RX_FIFO_INF) & RX_FIFO_INF_RXSUSED) >> 16) { + status = smc911x_reg_read(priv, RX_STATUS_FIFO); pktlen = (status & RX_STS_PKT_LEN) >> 16; - smc911x_reg_write(dev, RX_CFG, 0); + smc911x_reg_write(priv, RX_CFG, 0); tmplen = (pktlen + 3) / 4; while (tmplen--) - *data++ = smc911x_reg_read(dev, RX_DATA_FIFO); + *data++ = smc911x_reg_read(priv, RX_DATA_FIFO); if (status & RX_STS_ES) printf(DRIVERNAME @@ -367,31 +379,34 @@ static int smc911x_miiphy_read(struct mii_dev *bus, int phy, int devad, int reg) { struct eth_device *dev = eth_get_dev_by_name(bus->name); + struct smc911x_priv *priv = container_of(dev, struct smc911x_priv, dev); u16 val = 0; int ret; - if (!dev) + if (!dev || !priv) return -ENODEV; - ret = smc911x_eth_phy_read(dev, phy, reg, &val); + ret = smc911x_eth_phy_read(priv, phy, reg, &val); if (ret < 0) return ret; return val; } + /* wrapper for smc911x_eth_phy_write */ static int smc911x_miiphy_write(struct mii_dev *bus, int phy, int devad, int reg, u16 val) { struct eth_device *dev = eth_get_dev_by_name(bus->name); + struct smc911x_priv *priv = container_of(dev, struct smc911x_priv, dev); - if (!dev) + if (!dev || !priv) return -ENODEV; - return smc911x_eth_phy_write(dev, phy, reg, val); + return smc911x_eth_phy_write(priv, phy, reg, val); } -static int smc911x_initialize_mii(struct eth_device *dev) +static int smc911x_initialize_mii(struct smc911x_priv *priv) { struct mii_dev *mdiodev = mdio_alloc(); int ret; @@ -399,7 +414,7 @@ static int smc911x_initialize_mii(struct eth_device *dev) if (!mdiodev) return -ENOMEM; - strncpy(mdiodev->name, dev->name, MDIO_NAME_LEN); + strncpy(mdiodev->name, priv->dev.name, MDIO_NAME_LEN); mdiodev->read = smc911x_miiphy_read; mdiodev->write = smc911x_miiphy_write; @@ -412,7 +427,7 @@ static int smc911x_initialize_mii(struct eth_device *dev) return 0; } #else -static int smc911x_initialize_mii(struct eth_device *dev) +static int smc911x_initialize_mii(struct smc911x_priv *priv) { return 0; } @@ -421,51 +436,52 @@ static int smc911x_initialize_mii(struct eth_device *dev) int smc911x_initialize(u8 dev_num, int base_addr) { unsigned long addrl, addrh; - struct eth_device *dev; + struct smc911x_priv *priv; int ret; - dev = calloc(1, sizeof(*dev)); - if (!dev) + priv = calloc(1, sizeof(*priv)); + if (!priv) return -ENOMEM; - dev->iobase = base_addr; + priv->iobase = base_addr; + priv->dev.iobase = base_addr; /* Try to detect chip. Will fail if not present. */ - ret = smc911x_detect_chip(dev); + ret = smc911x_detect_chip(priv); if (ret) { ret = 0; /* Card not detected is not an error */ goto err_detect; } - addrh = smc911x_get_mac_csr(dev, ADDRH); - addrl = smc911x_get_mac_csr(dev, ADDRL); + addrh = smc911x_get_mac_csr(priv, ADDRH); + addrl = smc911x_get_mac_csr(priv, ADDRL); if (!(addrl == 0xffffffff && addrh == 0x0000ffff)) { /* address is obtained from optional eeprom */ - dev->enetaddr[0] = addrl; - dev->enetaddr[1] = addrl >> 8; - dev->enetaddr[2] = addrl >> 16; - dev->enetaddr[3] = addrl >> 24; - dev->enetaddr[4] = addrh; - dev->enetaddr[5] = addrh >> 8; + priv->enetaddr[0] = addrl; + priv->enetaddr[1] = addrl >> 8; + priv->enetaddr[2] = addrl >> 16; + priv->enetaddr[3] = addrl >> 24; + priv->enetaddr[4] = addrh; + priv->enetaddr[5] = addrh >> 8; } - dev->init = smc911x_init; - dev->halt = smc911x_halt; - dev->send = smc911x_send; - dev->recv = smc911x_recv; - sprintf(dev->name, "%s-%hu", DRIVERNAME, dev_num); + priv->dev.init = smc911x_init; + priv->dev.halt = smc911x_halt; + priv->dev.send = smc911x_send; + priv->dev.recv = smc911x_recv; + sprintf(priv->dev.name, "%s-%hu", DRIVERNAME, dev_num); - eth_register(dev); + eth_register(&priv->dev); - ret = smc911x_initialize_mii(dev); + ret = smc911x_initialize_mii(priv); if (ret) goto err_mii; return 1; err_mii: - eth_unregister(dev); + eth_unregister(&priv->dev); err_detect: - free(dev); + free(priv); return ret; } -- cgit v1.3.1 From b11c8bbfafa998e90fe93ab4e9b08c1a4959bd65 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sun, 15 Mar 2020 17:02:05 +0100 Subject: net: smc911x: Clean up the status handling in smc911x_recv() Invert the status handling logic in smc911x_recv(), to make the function easier to read, no functional change. Signed-off-by: Marek Vasut Cc: Joe Hershberger Cc: Masahiro Yamada --- drivers/net/smc911x.c | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/smc911x.c b/drivers/net/smc911x.c index 07066ce1083..2d1a9e0f5a9 100644 --- a/drivers/net/smc911x.c +++ b/drivers/net/smc911x.c @@ -352,23 +352,25 @@ static int smc911x_recv(struct eth_device *dev) u32 pktlen, tmplen; u32 status; - if ((smc911x_reg_read(priv, RX_FIFO_INF) & RX_FIFO_INF_RXSUSED) >> 16) { - status = smc911x_reg_read(priv, RX_STATUS_FIFO); - pktlen = (status & RX_STS_PKT_LEN) >> 16; + status = smc911x_reg_read(priv, RX_FIFO_INF); + if (!(status & RX_FIFO_INF_RXSUSED)) + return 0; - smc911x_reg_write(priv, RX_CFG, 0); + status = smc911x_reg_read(priv, RX_STATUS_FIFO); + pktlen = (status & RX_STS_PKT_LEN) >> 16; - tmplen = (pktlen + 3) / 4; - while (tmplen--) - *data++ = smc911x_reg_read(priv, RX_DATA_FIFO); + smc911x_reg_write(priv, RX_CFG, 0); - if (status & RX_STS_ES) - printf(DRIVERNAME - ": dropped bad packet. Status: 0x%08x\n", - status); - else - net_process_received_packet(net_rx_packets[0], pktlen); - } + tmplen = (pktlen + 3) / 4; + while (tmplen--) + *data++ = smc911x_reg_read(priv, RX_DATA_FIFO); + + if (status & RX_STS_ES) + printf(DRIVERNAME + ": dropped bad packet. Status: 0x%08x\n", + status); + else + net_process_received_packet(net_rx_packets[0], pktlen); return 0; } -- cgit v1.3.1 From 8eb4fef11b5420020518486ef0305aada0a02467 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sun, 15 Mar 2020 17:25:27 +0100 Subject: net: smc911x: Split non-DM specific bits from common code Split network handling functions into non-DM specific parts and common code in preparation for conversion to DM. Signed-off-by: Marek Vasut Cc: Joe Hershberger Cc: Masahiro Yamada Acked-by: Joe Hershberger --- drivers/net/smc911x.c | 57 ++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 43 insertions(+), 14 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/smc911x.c b/drivers/net/smc911x.c index 2d1a9e0f5a9..95f955f6d8a 100644 --- a/drivers/net/smc911x.c +++ b/drivers/net/smc911x.c @@ -277,9 +277,8 @@ static void smc911x_enable(struct smc911x_priv *priv) MAC_CR_HBDIS); } -static int smc911x_init(struct eth_device *dev, bd_t * bd) +static int smc911x_init_common(struct smc911x_priv *priv) { - struct smc911x_priv *priv = container_of(dev, struct smc911x_priv, dev); const struct chip_id *id = priv->chipid; printf(DRIVERNAME ": detected %s controller\n", id->name); @@ -297,9 +296,9 @@ static int smc911x_init(struct eth_device *dev, bd_t * bd) return 0; } -static int smc911x_send(struct eth_device *dev, void *packet, int length) +static int smc911x_send_common(struct smc911x_priv *priv, + void *packet, int length) { - struct smc911x_priv *priv = container_of(dev, struct smc911x_priv, dev); u32 *data = (u32*)packet; u32 tmplen; u32 status; @@ -337,18 +336,14 @@ static int smc911x_send(struct eth_device *dev, void *packet, int length) return -1; } -static void smc911x_halt(struct eth_device *dev) +static void smc911x_halt_common(struct smc911x_priv *priv) { - struct smc911x_priv *priv = container_of(dev, struct smc911x_priv, dev); - smc911x_reset(priv); smc911x_handle_mac_address(priv); } -static int smc911x_recv(struct eth_device *dev) +static int smc911x_recv_common(struct smc911x_priv *priv, u32 *data) { - struct smc911x_priv *priv = container_of(dev, struct smc911x_priv, dev); - u32 *data = (u32 *)net_rx_packets[0]; u32 pktlen, tmplen; u32 status; @@ -365,14 +360,14 @@ static int smc911x_recv(struct eth_device *dev) while (tmplen--) *data++ = smc911x_reg_read(priv, RX_DATA_FIFO); - if (status & RX_STS_ES) + if (status & RX_STS_ES) { printf(DRIVERNAME ": dropped bad packet. Status: 0x%08x\n", status); - else - net_process_received_packet(net_rx_packets[0], pktlen); + return 0; + } - return 0; + return pktlen; } #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) @@ -435,6 +430,40 @@ static int smc911x_initialize_mii(struct smc911x_priv *priv) } #endif +static int smc911x_init(struct eth_device *dev, bd_t *bd) +{ + struct smc911x_priv *priv = container_of(dev, struct smc911x_priv, dev); + + return smc911x_init_common(priv); +} + +static void smc911x_halt(struct eth_device *dev) +{ + struct smc911x_priv *priv = container_of(dev, struct smc911x_priv, dev); + + smc911x_halt_common(priv); +} + +static int smc911x_send(struct eth_device *dev, void *packet, int length) +{ + struct smc911x_priv *priv = container_of(dev, struct smc911x_priv, dev); + + return smc911x_send_common(priv, packet, length); +} + +static int smc911x_recv(struct eth_device *dev) +{ + struct smc911x_priv *priv = container_of(dev, struct smc911x_priv, dev); + u32 *data = (u32 *)net_rx_packets[0]; + int ret; + + ret = smc911x_recv_common(priv, data); + if (ret) + net_process_received_packet(net_rx_packets[0], ret); + + return ret; +} + int smc911x_initialize(u8 dev_num, int base_addr) { unsigned long addrl, addrh; -- cgit v1.3.1 From 8148693b988fb36463dbc12cef4b7947acae9846 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sun, 15 Mar 2020 17:39:01 +0100 Subject: net: smc911x: Add DM support Add support for U-Boot DM and DT probing. Furthermore, build the SMC911x standalone EEPROM example only for the non-DM case, as it is not converted yet. Signed-off-by: Marek Vasut Cc: Joe Hershberger Cc: Masahiro Yamada --- drivers/net/Kconfig | 2 + drivers/net/smc911x.c | 115 +++++++++++++++++++++++++++++++++++++++++++ examples/standalone/Makefile | 5 +- 3 files changed, 121 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index bc518f218da..a2587a29e16 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -388,11 +388,13 @@ config SMC911X if SMC911X +if !DM_ETH config SMC911X_BASE hex "SMC911X Base Address" help Define this to hold the physical address of the device (I/O space) +endif #DM_ETH choice prompt "SMC911X bus width" diff --git a/drivers/net/smc911x.c b/drivers/net/smc911x.c index 95f955f6d8a..45ecd6a2633 100644 --- a/drivers/net/smc911x.c +++ b/drivers/net/smc911x.c @@ -21,7 +21,9 @@ struct chip_id { }; struct smc911x_priv { +#ifndef CONFIG_DM_ETH struct eth_device dev; +#endif phys_addr_t iobase; const struct chip_id *chipid; unsigned char enetaddr[6]; @@ -370,6 +372,8 @@ static int smc911x_recv_common(struct smc911x_priv *priv, u32 *data) return pktlen; } +#ifndef CONFIG_DM_ETH + #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) /* wrapper for smc911x_eth_phy_read */ static int smc911x_miiphy_read(struct mii_dev *bus, int phy, int devad, @@ -494,6 +498,7 @@ int smc911x_initialize(u8 dev_num, int base_addr) priv->enetaddr[3] = addrl >> 24; priv->enetaddr[4] = addrh; priv->enetaddr[5] = addrh >> 8; + memcpy(priv->dev.enetaddr, priv->enetaddr, 6); } priv->dev.init = smc911x_init; @@ -516,3 +521,113 @@ err_detect: free(priv); return ret; } + +#else /* ifdef CONFIG_DM_ETH */ + +static int smc911x_start(struct udevice *dev) +{ + struct eth_pdata *plat = dev_get_platdata(dev); + struct smc911x_priv *priv = dev_get_priv(dev); + + memcpy(priv->enetaddr, plat->enetaddr, sizeof(plat->enetaddr)); + + return smc911x_init_common(priv); +} + +static void smc911x_stop(struct udevice *dev) +{ + struct smc911x_priv *priv = dev_get_priv(dev); + + smc911x_halt_common(priv); +} + +static int smc911x_send(struct udevice *dev, void *packet, int length) +{ + struct smc911x_priv *priv = dev_get_priv(dev); + int ret; + + ret = smc911x_send_common(priv, packet, length); + + return ret ? 0 : -ETIMEDOUT; +} + +static int smc911x_recv(struct udevice *dev, int flags, uchar **packetp) +{ + struct smc911x_priv *priv = dev_get_priv(dev); + u32 *data = (u32 *)net_rx_packets[0]; + int ret; + + ret = smc911x_recv_common(priv, data); + if (ret) + *packetp = (void *)data; + + return ret ? ret : -EAGAIN; +} + +static int smc911x_bind(struct udevice *dev) +{ + return device_set_name(dev, dev->name); +} + +static int smc911x_probe(struct udevice *dev) +{ + struct smc911x_priv *priv = dev_get_priv(dev); + unsigned long addrh, addrl; + int ret; + + /* Try to detect chip. Will fail if not present. */ + ret = smc911x_detect_chip(priv); + if (ret) + return ret; + + addrh = smc911x_get_mac_csr(priv, ADDRH); + addrl = smc911x_get_mac_csr(priv, ADDRL); + if (!(addrl == 0xffffffff && addrh == 0x0000ffff)) { + /* address is obtained from optional eeprom */ + priv->enetaddr[0] = addrl; + priv->enetaddr[1] = addrl >> 8; + priv->enetaddr[2] = addrl >> 16; + priv->enetaddr[3] = addrl >> 24; + priv->enetaddr[4] = addrh; + priv->enetaddr[5] = addrh >> 8; + } + + return 0; +} + +static int smc911x_ofdata_to_platdata(struct udevice *dev) +{ + struct smc911x_priv *priv = dev_get_priv(dev); + struct eth_pdata *pdata = dev_get_platdata(dev); + + pdata->iobase = devfdt_get_addr(dev); + priv->iobase = pdata->iobase; + + return 0; +} + +static const struct eth_ops smc911x_ops = { + .start = smc911x_start, + .send = smc911x_send, + .recv = smc911x_recv, + .stop = smc911x_stop, +}; + +static const struct udevice_id smc911x_ids[] = { + { .compatible = "smsc,lan9115" }, + { } +}; + +U_BOOT_DRIVER(smc911x) = { + .name = "eth_smc911x", + .id = UCLASS_ETH, + .of_match = smc911x_ids, + .bind = smc911x_bind, + .ofdata_to_platdata = smc911x_ofdata_to_platdata, + .probe = smc911x_probe, + .ops = &smc911x_ops, + .priv_auto_alloc_size = sizeof(struct smc911x_priv), + .platdata_auto_alloc_size = sizeof(struct eth_pdata), + .flags = DM_FLAG_ALLOC_PRIV_DMA, +}; +#endif diff --git a/examples/standalone/Makefile b/examples/standalone/Makefile index 779e2528b77..4a34813804f 100644 --- a/examples/standalone/Makefile +++ b/examples/standalone/Makefile @@ -5,10 +5,13 @@ extra-y := hello_world extra-$(CONFIG_SMC91111) += smc91111_eeprom -extra-$(CONFIG_SMC911X) += smc911x_eeprom extra-$(CONFIG_SPI_FLASH_ATMEL) += atmel_df_pow2 extra-$(CONFIG_PPC) += sched +ifndef CONFIG_DM_ETH +extra-$(CONFIG_SMC911X) += smc911x_eeprom +endif + # # Some versions of make do not handle trailing white spaces properly; # leading to build failures. The problem was found with GNU Make 3.80. -- cgit v1.3.1 From 8510580f2e85a8687b40fe5fc3d8c060e5278505 Mon Sep 17 00:00:00 2001 From: Daniel Schwierzeck Date: Sun, 3 May 2020 19:43:32 +0200 Subject: net: pcnet: fix I/O primitives for memory access Commit 69529c912059 ("net: pcnet: Switch to PCI memory access") switched from PCI IO access to PCI memory access without updating the I/O primitives. Contrary to SH, the primitives for memory access and IO access are implemented differently. Thus doing memory access with IO port primitives breaks the driver on MIPS Malta board. Signed-off-by: Daniel Schwierzeck --- drivers/net/pcnet.c | 34 +++++++++++++++++++++++----------- 1 file changed, 23 insertions(+), 11 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/pcnet.c b/drivers/net/pcnet.c index 34a5a16cfe8..f97e7f8c6a3 100644 --- a/drivers/net/pcnet.c +++ b/drivers/net/pcnet.c @@ -91,37 +91,49 @@ static pcnet_priv_t *lp; static u16 pcnet_read_csr(struct eth_device *dev, int index) { - outw(index, dev->iobase + PCNET_RAP); - return inw(dev->iobase + PCNET_RDP); + void __iomem *base = (void __iomem *)dev->iobase; + + writew(index, base + PCNET_RAP); + return readw(base + PCNET_RDP); } static void pcnet_write_csr(struct eth_device *dev, int index, u16 val) { - outw(index, dev->iobase + PCNET_RAP); - outw(val, dev->iobase + PCNET_RDP); + void __iomem *base = (void __iomem *)dev->iobase; + + writew(index, base + PCNET_RAP); + writew(val, base + PCNET_RDP); } static u16 pcnet_read_bcr(struct eth_device *dev, int index) { - outw(index, dev->iobase + PCNET_RAP); - return inw(dev->iobase + PCNET_BDP); + void __iomem *base = (void __iomem *)dev->iobase; + + writew(index, base + PCNET_RAP); + return readw(base + PCNET_BDP); } static void pcnet_write_bcr(struct eth_device *dev, int index, u16 val) { - outw(index, dev->iobase + PCNET_RAP); - outw(val, dev->iobase + PCNET_BDP); + void __iomem *base = (void __iomem *)dev->iobase; + + writew(index, base + PCNET_RAP); + writew(val, base + PCNET_BDP); } static void pcnet_reset(struct eth_device *dev) { - inw(dev->iobase + PCNET_RESET); + void __iomem *base = (void __iomem *)dev->iobase; + + readw(base + PCNET_RESET); } static int pcnet_check(struct eth_device *dev) { - outw(88, dev->iobase + PCNET_RAP); - return inw(dev->iobase + PCNET_RAP) == 88; + void __iomem *base = (void __iomem *)dev->iobase; + + writew(88, base + PCNET_RAP); + return readw(base + PCNET_RAP) == 88; } static int pcnet_init (struct eth_device *dev, bd_t * bis); -- cgit v1.3.1 From 4346df3392c0e795ce458bc86e9e8ed24a3afa0f Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Thu, 7 May 2020 00:11:48 +0200 Subject: phy: atheros: Make RGMII Tx delays actually configurable for AR8035 Delete the extraneous write to debug reg 5 that enables Tx delay When the driver was originally introduced in commit "6027384a phylib: Add Atheros AR8035 GETH PHY support", the Tx delay was being unconditionally enabled. Then during "2ec4d10b phy: atheros: add support for RGMII_ID, RGMII_TXID and RGMII_RXID", the author did not notice that code for enabling Tx delay code was already. Therefore, the if condition for Tx delay has always been useless for this PHY since this commit introduced it. Prior to this patch, every AR8035 PHY in U-boot had Tx delay enabled. After this patch, only those who define the interface as RGMII_TXID or RGMII_ID will. This is to be expected, but will nonetheless break the setups of those who didn't know they rely on Tx delay implicitly. Signed-off-by: Vladimir Oltean Acked-by: Joe Hershberger --- drivers/net/phy/atheros.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/phy/atheros.c b/drivers/net/phy/atheros.c index 3783d155e79..537c1a91251 100644 --- a/drivers/net/phy/atheros.c +++ b/drivers/net/phy/atheros.c @@ -63,10 +63,6 @@ static int ar8035_config(struct phy_device *phydev) regval = phy_read(phydev, MDIO_DEVAD_NONE, 0xe); phy_write(phydev, MDIO_DEVAD_NONE, 0xe, (regval|0x0018)); - phy_write(phydev, MDIO_DEVAD_NONE, 0x1d, 0x05); - regval = phy_read(phydev, MDIO_DEVAD_NONE, 0x1e); - phy_write(phydev, MDIO_DEVAD_NONE, 0x1e, (regval|0x0100)); - if ((phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) || (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID)) { /* select debug reg 5 */ -- cgit v1.3.1 From 29602f9c4b8efd9afcb2212eda0e13483ca6ec5d Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Thu, 7 May 2020 00:11:49 +0200 Subject: phy: atheros: Use common functions for RGMII internal delays Signed-off-by: Vladimir Oltean Acked-by: Joe Hershberger --- drivers/net/phy/atheros.c | 69 ++++++++++++++++++++++++++++------------------- 1 file changed, 41 insertions(+), 28 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/phy/atheros.c b/drivers/net/phy/atheros.c index 537c1a91251..c0c2b4db396 100644 --- a/drivers/net/phy/atheros.c +++ b/drivers/net/phy/atheros.c @@ -12,16 +12,45 @@ #define AR803x_PHY_DEBUG_DATA_REG 0x1e #define AR803x_DEBUG_REG_5 0x5 -#define AR803x_RGMII_TX_CLK_DLY 0x100 +#define AR803x_RGMII_TX_CLK_DLY BIT(8) #define AR803x_DEBUG_REG_0 0x0 -#define AR803x_RGMII_RX_CLK_DLY 0x8000 +#define AR803x_RGMII_RX_CLK_DLY BIT(15) + +static void ar803x_enable_rx_delay(struct phy_device *phydev, bool on) +{ + int regval; + + phy_write(phydev, MDIO_DEVAD_NONE, AR803x_PHY_DEBUG_ADDR_REG, + AR803x_DEBUG_REG_0); + regval = phy_read(phydev, MDIO_DEVAD_NONE, AR803x_PHY_DEBUG_DATA_REG); + if (on) + regval |= AR803x_RGMII_RX_CLK_DLY; + else + regval &= ~AR803x_RGMII_RX_CLK_DLY; + phy_write(phydev, MDIO_DEVAD_NONE, AR803x_PHY_DEBUG_DATA_REG, regval); +} + +static void ar803x_enable_tx_delay(struct phy_device *phydev, bool on) +{ + int regval; + + phy_write(phydev, MDIO_DEVAD_NONE, AR803x_PHY_DEBUG_ADDR_REG, + AR803x_DEBUG_REG_5); + regval = phy_read(phydev, MDIO_DEVAD_NONE, AR803x_PHY_DEBUG_DATA_REG); + if (on) + regval |= AR803x_RGMII_TX_CLK_DLY; + else + regval &= ~AR803x_RGMII_TX_CLK_DLY; + phy_write(phydev, MDIO_DEVAD_NONE, AR803x_PHY_DEBUG_DATA_REG, regval); +} static int ar8021_config(struct phy_device *phydev) { phy_write(phydev, MDIO_DEVAD_NONE, 0x00, 0x1200); - phy_write(phydev, MDIO_DEVAD_NONE, 0x1d, 0x05); - phy_write(phydev, MDIO_DEVAD_NONE, 0x1e, 0x3D47); + phy_write(phydev, MDIO_DEVAD_NONE, AR803x_PHY_DEBUG_ADDR_REG, + AR803x_DEBUG_REG_5); + phy_write(phydev, MDIO_DEVAD_NONE, AR803x_PHY_DEBUG_DATA_REG, 0x3D47); phydev->supported = phydev->drv->features; return 0; @@ -30,20 +59,12 @@ static int ar8021_config(struct phy_device *phydev) static int ar8031_config(struct phy_device *phydev) { if (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID || - phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) { - phy_write(phydev, MDIO_DEVAD_NONE, AR803x_PHY_DEBUG_ADDR_REG, - AR803x_DEBUG_REG_5); - phy_write(phydev, MDIO_DEVAD_NONE, AR803x_PHY_DEBUG_DATA_REG, - AR803x_RGMII_TX_CLK_DLY); - } + phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) + ar803x_enable_tx_delay(phydev, true); if (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID || - phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) { - phy_write(phydev, MDIO_DEVAD_NONE, AR803x_PHY_DEBUG_ADDR_REG, - AR803x_DEBUG_REG_0); - phy_write(phydev, MDIO_DEVAD_NONE, AR803x_PHY_DEBUG_DATA_REG, - AR803x_RGMII_RX_CLK_DLY); - } + phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) + ar803x_enable_rx_delay(phydev, true); phydev->supported = phydev->drv->features; @@ -64,20 +85,12 @@ static int ar8035_config(struct phy_device *phydev) phy_write(phydev, MDIO_DEVAD_NONE, 0xe, (regval|0x0018)); if ((phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) || - (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID)) { - /* select debug reg 5 */ - phy_write(phydev, MDIO_DEVAD_NONE, 0x1D, 0x5); - /* enable tx delay */ - phy_write(phydev, MDIO_DEVAD_NONE, 0x1E, 0x0100); - } + (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID)) + ar803x_enable_tx_delay(phydev, true); if ((phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) || - (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID)) { - /* select debug reg 0 */ - phy_write(phydev, MDIO_DEVAD_NONE, 0x1D, 0x0); - /* enable rx delay */ - phy_write(phydev, MDIO_DEVAD_NONE, 0x1E, 0x8000); - } + (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID)) + ar803x_enable_rx_delay(phydev, true); phydev->supported = phydev->drv->features; -- cgit v1.3.1 From a234ae863a413d371a0abc36f9e0aa9c1726e331 Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Thu, 7 May 2020 00:11:50 +0200 Subject: phy: atheros: Clarify the configuration of the CLK_25M output pin Also take the opportunity to use the phy_read_mmd and phy_write_mmd convenience functions. Signed-off-by: Vladimir Oltean Acked-by: Joe Hershberger --- drivers/net/phy/atheros.c | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/phy/atheros.c b/drivers/net/phy/atheros.c index c0c2b4db396..1da18eb5d45 100644 --- a/drivers/net/phy/atheros.c +++ b/drivers/net/phy/atheros.c @@ -17,6 +17,15 @@ #define AR803x_DEBUG_REG_0 0x0 #define AR803x_RGMII_RX_CLK_DLY BIT(15) +/* CLK_25M register is at MMD 7, address 0x8016 */ +#define AR803x_CLK_25M_SEL_REG 0x8016 +/* AR8035: Select frequency on CLK_25M pin through bits 4:3 */ +#define AR8035_CLK_25M_FREQ_25M (0 | 0) +#define AR8035_CLK_25M_FREQ_50M (0 | BIT(3)) +#define AR8035_CLK_25M_FREQ_62M (BIT(4) | 0) +#define AR8035_CLK_25M_FREQ_125M (BIT(4) | BIT(3)) +#define AR8035_CLK_25M_MASK GENMASK(4, 3) + static void ar803x_enable_rx_delay(struct phy_device *phydev, bool on) { int regval; @@ -78,11 +87,11 @@ static int ar8035_config(struct phy_device *phydev) { int regval; - phy_write(phydev, MDIO_DEVAD_NONE, 0xd, 0x0007); - phy_write(phydev, MDIO_DEVAD_NONE, 0xe, 0x8016); - phy_write(phydev, MDIO_DEVAD_NONE, 0xd, 0x4007); - regval = phy_read(phydev, MDIO_DEVAD_NONE, 0xe); - phy_write(phydev, MDIO_DEVAD_NONE, 0xe, (regval|0x0018)); + /* Configure CLK_25M output clock at 125 MHz */ + regval = phy_read_mmd(phydev, MDIO_MMD_AN, AR803x_CLK_25M_SEL_REG); + regval &= ~AR8035_CLK_25M_MASK; /* No surprises */ + regval |= AR8035_CLK_25M_FREQ_125M; + phy_write_mmd(phydev, MDIO_MMD_AN, AR803x_CLK_25M_SEL_REG, regval); if ((phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) || (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID)) -- cgit v1.3.1 From 13114f38e2ccea9386726d8b9831dfc310589548 Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Thu, 7 May 2020 00:11:51 +0200 Subject: phy: atheros: Explicitly disable RGMII delays To eliminate any doubts about the out-of-reset value of the PHY, that the driver previously relied on. If bisecting shows that this commit breaks your board you probably have a wrong PHY interface mode. You probably want the PHY_INTERFACE_MODE_RGMII_RXID or PHY_INTERFACE_MODE_RGMII_ID mode. Signed-off-by: Vladimir Oltean Acked-by: Joe Hershberger --- drivers/net/phy/atheros.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/phy/atheros.c b/drivers/net/phy/atheros.c index 1da18eb5d45..3e59c3f3915 100644 --- a/drivers/net/phy/atheros.c +++ b/drivers/net/phy/atheros.c @@ -70,10 +70,14 @@ static int ar8031_config(struct phy_device *phydev) if (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID || phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) ar803x_enable_tx_delay(phydev, true); + else + ar803x_enable_tx_delay(phydev, false); if (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID || phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) ar803x_enable_rx_delay(phydev, true); + else + ar803x_enable_rx_delay(phydev, false); phydev->supported = phydev->drv->features; @@ -96,10 +100,14 @@ static int ar8035_config(struct phy_device *phydev) if ((phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) || (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID)) ar803x_enable_tx_delay(phydev, true); + else + ar803x_enable_tx_delay(phydev, false); if ((phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) || (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID)) ar803x_enable_rx_delay(phydev, true); + else + ar803x_enable_rx_delay(phydev, false); phydev->supported = phydev->drv->features; -- cgit v1.3.1 From 4d4e4cf7798276bcb047b65cf80fde63fd347903 Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Thu, 7 May 2020 00:11:52 +0200 Subject: phy: atheros: Clarify the intention of ar8021_config Debug register 5 contains TX_CLK DELAY at bit 8 and reserved values at the other bit positions, just like the other PHYs in the family do. Therefore, it is not necessary to hardcode the reserved values, but instead simply follow the read-modify-write procedure from the common function. Signed-off-by: Vladimir Oltean Acked-by: Joe Hershberger --- drivers/net/phy/atheros.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/phy/atheros.c b/drivers/net/phy/atheros.c index 3e59c3f3915..3cc162828ca 100644 --- a/drivers/net/phy/atheros.c +++ b/drivers/net/phy/atheros.c @@ -56,10 +56,10 @@ static void ar803x_enable_tx_delay(struct phy_device *phydev, bool on) static int ar8021_config(struct phy_device *phydev) { - phy_write(phydev, MDIO_DEVAD_NONE, 0x00, 0x1200); - phy_write(phydev, MDIO_DEVAD_NONE, AR803x_PHY_DEBUG_ADDR_REG, - AR803x_DEBUG_REG_5); - phy_write(phydev, MDIO_DEVAD_NONE, AR803x_PHY_DEBUG_DATA_REG, 0x3D47); + phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, + BMCR_ANENABLE | BMCR_ANRESTART); + + ar803x_enable_tx_delay(phydev, true); phydev->supported = phydev->drv->features; return 0; -- cgit v1.3.1 From f4d48f43b29756dac0f306eec3ca7ddf2821dd4e Mon Sep 17 00:00:00 2001 From: Michael Walle Date: Thu, 7 May 2020 00:11:53 +0200 Subject: phy: atheros: fix AR8021 PHY ID mask The upper bits are all the OUI. Signed-off-by: Michael Walle Acked-by: Joe Hershberger --- drivers/net/phy/atheros.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/phy/atheros.c b/drivers/net/phy/atheros.c index 3cc162828ca..01953a13902 100644 --- a/drivers/net/phy/atheros.c +++ b/drivers/net/phy/atheros.c @@ -120,7 +120,7 @@ static int ar8035_config(struct phy_device *phydev) static struct phy_driver AR8021_driver = { .name = "AR8021", .uid = 0x4dd040, - .mask = 0x4ffff0, + .mask = 0xfffffff0, .features = PHY_GBIT_FEATURES, .config = ar8021_config, .startup = genphy_startup, -- cgit v1.3.1 From 30e3193128f95d7276311b50f4215f9a8625c3ba Mon Sep 17 00:00:00 2001 From: Michael Walle Date: Thu, 7 May 2020 00:11:54 +0200 Subject: phy: atheros: use defines for PHY IDs Signed-off-by: Michael Walle Acked-by: Joe Hershberger --- drivers/net/phy/atheros.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/phy/atheros.c b/drivers/net/phy/atheros.c index 01953a13902..5ff5875d3df 100644 --- a/drivers/net/phy/atheros.c +++ b/drivers/net/phy/atheros.c @@ -26,6 +26,10 @@ #define AR8035_CLK_25M_FREQ_125M (BIT(4) | BIT(3)) #define AR8035_CLK_25M_MASK GENMASK(4, 3) +#define AR8021_PHY_ID 0x004dd040 +#define AR8031_PHY_ID 0x004dd074 +#define AR8035_PHY_ID 0x004dd072 + static void ar803x_enable_rx_delay(struct phy_device *phydev, bool on) { int regval; @@ -119,7 +123,7 @@ static int ar8035_config(struct phy_device *phydev) static struct phy_driver AR8021_driver = { .name = "AR8021", - .uid = 0x4dd040, + .uid = AR8021_PHY_ID, .mask = 0xfffffff0, .features = PHY_GBIT_FEATURES, .config = ar8021_config, @@ -129,7 +133,7 @@ static struct phy_driver AR8021_driver = { static struct phy_driver AR8031_driver = { .name = "AR8031/AR8033", - .uid = 0x4dd074, + .uid = AR8031_PHY_ID, .mask = 0xffffffef, .features = PHY_GBIT_FEATURES, .config = ar8031_config, @@ -139,7 +143,7 @@ static struct phy_driver AR8031_driver = { static struct phy_driver AR8035_driver = { .name = "AR8035", - .uid = 0x4dd072, + .uid = AR8035_PHY_ID, .mask = 0xffffffef, .features = PHY_GBIT_FEATURES, .config = ar8035_config, -- cgit v1.3.1 From f6ae47be1ac5f3b16ac2b702ffa89e5709711ce5 Mon Sep 17 00:00:00 2001 From: Michael Walle Date: Thu, 7 May 2020 00:11:55 +0200 Subject: phy: atheros: introduce debug read and write functions Provide functions to read and write the Atheros debug registers. Signed-off-by: Michael Walle Acked-by: Joe Hershberger --- drivers/net/phy/atheros.c | 57 ++++++++++++++++++++++++++++++++++------------- 1 file changed, 41 insertions(+), 16 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/phy/atheros.c b/drivers/net/phy/atheros.c index 5ff5875d3df..660dcd9491d 100644 --- a/drivers/net/phy/atheros.c +++ b/drivers/net/phy/atheros.c @@ -30,32 +30,57 @@ #define AR8031_PHY_ID 0x004dd074 #define AR8035_PHY_ID 0x004dd072 -static void ar803x_enable_rx_delay(struct phy_device *phydev, bool on) +static int ar803x_debug_reg_read(struct phy_device *phydev, u16 reg) { - int regval; + int ret; + + ret = phy_write(phydev, MDIO_DEVAD_NONE, AR803x_PHY_DEBUG_ADDR_REG, + reg); + if (ret < 0) + return ret; + + return phy_read(phydev, MDIO_DEVAD_NONE, AR803x_PHY_DEBUG_DATA_REG); +} + +static int ar803x_debug_reg_mask(struct phy_device *phydev, u16 reg, + u16 clear, u16 set) +{ + int val; + + val = ar803x_debug_reg_read(phydev, reg); + if (val < 0) + return val; + + val &= 0xffff; + val &= ~clear; + val |= set; + + return phy_write(phydev, MDIO_DEVAD_NONE, AR803x_PHY_DEBUG_DATA_REG, + val); +} + +static int ar803x_enable_rx_delay(struct phy_device *phydev, bool on) +{ + u16 clear = 0, set = 0; - phy_write(phydev, MDIO_DEVAD_NONE, AR803x_PHY_DEBUG_ADDR_REG, - AR803x_DEBUG_REG_0); - regval = phy_read(phydev, MDIO_DEVAD_NONE, AR803x_PHY_DEBUG_DATA_REG); if (on) - regval |= AR803x_RGMII_RX_CLK_DLY; + set = AR803x_RGMII_RX_CLK_DLY; else - regval &= ~AR803x_RGMII_RX_CLK_DLY; - phy_write(phydev, MDIO_DEVAD_NONE, AR803x_PHY_DEBUG_DATA_REG, regval); + clear = AR803x_RGMII_RX_CLK_DLY; + + return ar803x_debug_reg_mask(phydev, AR803x_DEBUG_REG_0, clear, set); } -static void ar803x_enable_tx_delay(struct phy_device *phydev, bool on) +static int ar803x_enable_tx_delay(struct phy_device *phydev, bool on) { - int regval; + u16 clear = 0, set = 0; - phy_write(phydev, MDIO_DEVAD_NONE, AR803x_PHY_DEBUG_ADDR_REG, - AR803x_DEBUG_REG_5); - regval = phy_read(phydev, MDIO_DEVAD_NONE, AR803x_PHY_DEBUG_DATA_REG); if (on) - regval |= AR803x_RGMII_TX_CLK_DLY; + set = AR803x_RGMII_TX_CLK_DLY; else - regval &= ~AR803x_RGMII_TX_CLK_DLY; - phy_write(phydev, MDIO_DEVAD_NONE, AR803x_PHY_DEBUG_DATA_REG, regval); + clear = AR803x_RGMII_TX_CLK_DLY; + + return ar803x_debug_reg_mask(phydev, AR803x_DEBUG_REG_5, clear, set); } static int ar8021_config(struct phy_device *phydev) -- cgit v1.3.1 From 2b7721552a4cb4046a365a665fba3a3a848eb966 Mon Sep 17 00:00:00 2001 From: Michael Walle Date: Thu, 7 May 2020 00:11:56 +0200 Subject: phy: atheros: move delay config to common function Signed-off-by: Michael Walle Acked-by: Joe Hershberger --- drivers/net/phy/atheros.c | 38 ++++++++++++++++++++++---------------- 1 file changed, 22 insertions(+), 16 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/phy/atheros.c b/drivers/net/phy/atheros.c index 660dcd9491d..22035c2496d 100644 --- a/drivers/net/phy/atheros.c +++ b/drivers/net/phy/atheros.c @@ -94,19 +94,32 @@ static int ar8021_config(struct phy_device *phydev) return 0; } -static int ar8031_config(struct phy_device *phydev) +static int ar803x_delay_config(struct phy_device *phydev) { + int ret; + if (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID || phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) - ar803x_enable_tx_delay(phydev, true); + ret = ar803x_enable_tx_delay(phydev, true); else - ar803x_enable_tx_delay(phydev, false); + ret = ar803x_enable_tx_delay(phydev, false); if (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID || phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) - ar803x_enable_rx_delay(phydev, true); + ret = ar803x_enable_rx_delay(phydev, true); else - ar803x_enable_rx_delay(phydev, false); + ret = ar803x_enable_rx_delay(phydev, false); + + return ret; +} + +static int ar8031_config(struct phy_device *phydev) +{ + int ret; + + ret = ar803x_delay_config(phydev); + if (ret < 0) + return ret; phydev->supported = phydev->drv->features; @@ -118,6 +131,7 @@ static int ar8031_config(struct phy_device *phydev) static int ar8035_config(struct phy_device *phydev) { + int ret; int regval; /* Configure CLK_25M output clock at 125 MHz */ @@ -126,17 +140,9 @@ static int ar8035_config(struct phy_device *phydev) regval |= AR8035_CLK_25M_FREQ_125M; phy_write_mmd(phydev, MDIO_MMD_AN, AR803x_CLK_25M_SEL_REG, regval); - if ((phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) || - (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID)) - ar803x_enable_tx_delay(phydev, true); - else - ar803x_enable_tx_delay(phydev, false); - - if ((phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) || - (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID)) - ar803x_enable_rx_delay(phydev, true); - else - ar803x_enable_rx_delay(phydev, false); + ret = ar803x_delay_config(phydev); + if (ret < 0) + return ret; phydev->supported = phydev->drv->features; -- cgit v1.3.1 From fe6293a8095998affd5e46e7968485fcc332e0fa Mon Sep 17 00:00:00 2001 From: Michael Walle Date: Thu, 7 May 2020 00:11:57 +0200 Subject: phy: atheros: add device tree bindings and config Add support for configuring the CLK_25M pin as well as the RGMII I/O voltage by the device tree. By default the AT803x PHYs outputs the 25MHz clock of the XTAL input. But this output can also be changed by software to other frequencies. This commit introduces a generic way to configure this output. Also the PHY supports different RGMII I/O voltages: 1.5V, 1.8V and 2.5V. An internal LDO is able to provide 1.5V (default) and 1.8V. The 2.5V option needs an external supply voltage. This commit adds support to switch the internal LDO to 1.8V. Signed-off-by: Michael Walle Acked-by: Joe Hershberger --- doc/device-tree-bindings/net/phy/atheros.txt | 35 +++++ drivers/net/phy/atheros.c | 224 ++++++++++++++++++++++++++- include/dt-bindings/net/qca-ar803x.h | 13 ++ 3 files changed, 270 insertions(+), 2 deletions(-) create mode 100644 doc/device-tree-bindings/net/phy/atheros.txt create mode 100644 include/dt-bindings/net/qca-ar803x.h (limited to 'drivers/net') diff --git a/doc/device-tree-bindings/net/phy/atheros.txt b/doc/device-tree-bindings/net/phy/atheros.txt new file mode 100644 index 00000000000..97e97b8c13d --- /dev/null +++ b/doc/device-tree-bindings/net/phy/atheros.txt @@ -0,0 +1,35 @@ +* Qualcomm Atheros PHY Device Tree binding + +Required properties: +- reg: PHY address + +Optional properties: +- qca,clk-out-frequency: Clock frequency of the CLK_25M pin in Hz. + Either 25000000, 50000000, 62500000 or 125000000. +- qca,clk-out-strength: Clock output buffer driver strength. + Supported values are defined in dt-bindings/net/qca-ar803x.h +- qca,keep-pll-enabled: Keep the PLL running if no link is present. + Don't go into hibernation mode. + Only supported on the AR8031/AR8033. +- vddio-supply: RGMII I/O voltage regulator + Only supported on the AR8031/AR8033. + +Optional subnodes: +- vddio-regulator: Initial data for the VDDIO regulator, as covered + doc/device-tree-bindings/regulator/regulator.txt + +Example: + #include + + ethernet-phy@0 { + reg = <0>; + qca-clk-out-frequency = <125000000>; + qca,keep-pll-enabled; + + vddio-supply = <&vddio>; + + vddio: vddio-regulator { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + }; + }; diff --git a/drivers/net/phy/atheros.c b/drivers/net/phy/atheros.c index 22035c2496d..3cd301c50ed 100644 --- a/drivers/net/phy/atheros.c +++ b/drivers/net/phy/atheros.c @@ -4,21 +4,41 @@ * * Copyright 2011, 2013 Freescale Semiconductor, Inc. * author Andy Fleming + * Copyright (c) 2019 Michael Walle */ #include #include +#include +#include +#include #define AR803x_PHY_DEBUG_ADDR_REG 0x1d #define AR803x_PHY_DEBUG_DATA_REG 0x1e +/* Debug registers */ +#define AR803x_DEBUG_REG_0 0x0 +#define AR803x_RGMII_RX_CLK_DLY BIT(15) + #define AR803x_DEBUG_REG_5 0x5 #define AR803x_RGMII_TX_CLK_DLY BIT(8) -#define AR803x_DEBUG_REG_0 0x0 -#define AR803x_RGMII_RX_CLK_DLY BIT(15) +#define AR803x_DEBUG_REG_1F 0x1f +#define AR803x_PLL_ON BIT(2) +#define AR803x_RGMII_1V8 BIT(3) /* CLK_25M register is at MMD 7, address 0x8016 */ #define AR803x_CLK_25M_SEL_REG 0x8016 + +#define AR803x_CLK_25M_MASK GENMASK(4, 2) +#define AR803x_CLK_25M_25MHZ_XTAL 0 +#define AR803x_CLK_25M_25MHZ_DSP 1 +#define AR803x_CLK_25M_50MHZ_PLL 2 +#define AR803x_CLK_25M_50MHZ_DSP 3 +#define AR803x_CLK_25M_62_5MHZ_PLL 4 +#define AR803x_CLK_25M_62_5MHZ_DSP 5 +#define AR803x_CLK_25M_125MHZ_PLL 6 +#define AR803x_CLK_25M_125MHZ_DSP 7 + /* AR8035: Select frequency on CLK_25M pin through bits 4:3 */ #define AR8035_CLK_25M_FREQ_25M (0 | 0) #define AR8035_CLK_25M_FREQ_50M (0 | BIT(3)) @@ -26,10 +46,23 @@ #define AR8035_CLK_25M_FREQ_125M (BIT(4) | BIT(3)) #define AR8035_CLK_25M_MASK GENMASK(4, 3) +#define AR803x_CLK_25M_DR_MASK GENMASK(8, 7) +#define AR803x_CLK_25M_DR_FULL 0 +#define AR803x_CLK_25M_DR_HALF 1 +#define AR803x_CLK_25M_DR_QUARTER 2 + #define AR8021_PHY_ID 0x004dd040 #define AR8031_PHY_ID 0x004dd074 #define AR8035_PHY_ID 0x004dd072 +struct ar803x_priv { + int flags; +#define AR803x_FLAG_KEEP_PLL_ENABLED BIT(0) /* don't turn off internal PLL */ +#define AR803x_FLAG_RGMII_1V8 BIT(1) /* use 1.8V RGMII I/O voltage */ + u16 clk_25m_reg; + u16 clk_25m_mask; +}; + static int ar803x_debug_reg_read(struct phy_device *phydev, u16 reg) { int ret; @@ -113,14 +146,193 @@ static int ar803x_delay_config(struct phy_device *phydev) return ret; } +static int ar803x_regs_config(struct phy_device *phydev) +{ + struct ar803x_priv *priv = phydev->priv; + u16 set = 0, clear = 0; + int val; + int ret; + + /* no configuration available */ + if (!priv) + return 0; + + /* + * Only supported on the AR8031, AR8035 has strappings for the PLL mode + * as well as the RGMII voltage. + */ + if (phydev->drv->uid == AR8031_PHY_ID) { + if (priv->flags & AR803x_FLAG_KEEP_PLL_ENABLED) + set |= AR803x_PLL_ON; + else + clear |= AR803x_PLL_ON; + + if (priv->flags & AR803x_FLAG_RGMII_1V8) + set |= AR803x_RGMII_1V8; + else + clear |= AR803x_RGMII_1V8; + + ret = ar803x_debug_reg_mask(phydev, AR803x_DEBUG_REG_1F, clear, + set); + if (ret < 0) + return ret; + } + + /* save the write access if the mask is empty */ + if (priv->clk_25m_mask) { + val = phy_read_mmd(phydev, MDIO_MMD_AN, AR803x_CLK_25M_SEL_REG); + if (val < 0) + return val; + val &= ~priv->clk_25m_mask; + val |= priv->clk_25m_reg; + ret = phy_write_mmd(phydev, MDIO_MMD_AN, + AR803x_CLK_25M_SEL_REG, val); + if (ret < 0) + return ret; + } + + return 0; +} + +static int ar803x_of_init(struct phy_device *phydev) +{ +#if defined(CONFIG_DM_ETH) + struct ar803x_priv *priv; + ofnode node, vddio_reg_node; + u32 strength, freq, min_uV, max_uV; + int sel; + + node = phy_get_ofnode(phydev); + if (!ofnode_valid(node)) + return -EINVAL; + + priv = malloc(sizeof(*priv)); + if (!priv) + return -ENOMEM; + memset(priv, 0, sizeof(*priv)); + + phydev->priv = priv; + + debug("%s: found PHY node: %s\n", __func__, ofnode_get_name(node)); + + if (ofnode_read_bool(node, "qca,keep-pll-enabled")) + priv->flags |= AR803x_FLAG_KEEP_PLL_ENABLED; + + /* + * We can't use the regulator framework because the regulator is + * a subnode of the PHY. So just read the two properties we are + * interested in. + */ + vddio_reg_node = ofnode_find_subnode(node, "vddio-regulator"); + if (ofnode_valid(vddio_reg_node)) { + min_uV = ofnode_read_u32_default(vddio_reg_node, + "regulator-min-microvolt", 0); + max_uV = ofnode_read_u32_default(vddio_reg_node, + "regulator-max-microvolt", 0); + + if (min_uV != max_uV) { + free(priv); + return -EINVAL; + } + + switch (min_uV) { + case 1500000: + break; + case 1800000: + priv->flags |= AR803x_FLAG_RGMII_1V8; + break; + default: + free(priv); + return -EINVAL; + } + } + + /* + * Get the CLK_25M frequency from the device tree. Only XTAL and PLL + * sources are supported right now. There is also the possibilty to use + * the DSP as frequency reference, this is used for synchronous + * ethernet. + */ + if (!ofnode_read_u32(node, "qca,clk-out-frequency", &freq)) { + switch (freq) { + case 25000000: + sel = AR803x_CLK_25M_25MHZ_XTAL; + break; + case 50000000: + sel = AR803x_CLK_25M_50MHZ_PLL; + break; + case 62500000: + sel = AR803x_CLK_25M_62_5MHZ_PLL; + break; + case 125000000: + sel = AR803x_CLK_25M_125MHZ_PLL; + break; + default: + dev_err(phydev->dev, + "invalid qca,clk-out-frequency\n"); + free(priv); + return -EINVAL; + } + + priv->clk_25m_mask |= AR803x_CLK_25M_MASK; + priv->clk_25m_reg |= FIELD_PREP(AR803x_CLK_25M_MASK, sel); + /* + * Fixup for the AR8035 which only has two bits. The two + * remaining bits map to the same frequencies. + */ + if (phydev->drv->uid == AR8035_PHY_ID) { + u16 clear = AR803x_CLK_25M_MASK & AR8035_CLK_25M_MASK; + + priv->clk_25m_mask &= ~clear; + priv->clk_25m_reg &= ~clear; + } + } + + if (phydev->drv->uid == AR8031_PHY_ID && + !ofnode_read_u32(node, "qca,clk-out-strength", &strength)) { + switch (strength) { + case AR803X_STRENGTH_FULL: + sel = AR803x_CLK_25M_DR_FULL; + break; + case AR803X_STRENGTH_HALF: + sel = AR803x_CLK_25M_DR_HALF; + break; + case AR803X_STRENGTH_QUARTER: + sel = AR803x_CLK_25M_DR_QUARTER; + break; + default: + dev_err(phydev->dev, + "invalid qca,clk-out-strength\n"); + free(priv); + return -EINVAL; + } + priv->clk_25m_mask |= AR803x_CLK_25M_DR_MASK; + priv->clk_25m_reg |= FIELD_PREP(AR803x_CLK_25M_DR_MASK, sel); + } + + debug("%s: flags=%x clk_25m_reg=%04x clk_25m_mask=%04x\n", __func__, + priv->flags, priv->clk_25m_reg, priv->clk_25m_mask); +#endif + + return 0; +} + static int ar8031_config(struct phy_device *phydev) { int ret; + ret = ar803x_of_init(phydev); + if (ret < 0) + return ret; + ret = ar803x_delay_config(phydev); if (ret < 0) return ret; + ret = ar803x_regs_config(phydev); + if (ret < 0) + return ret; + phydev->supported = phydev->drv->features; genphy_config_aneg(phydev); @@ -134,6 +346,10 @@ static int ar8035_config(struct phy_device *phydev) int ret; int regval; + ret = ar803x_of_init(phydev); + if (ret < 0) + return ret; + /* Configure CLK_25M output clock at 125 MHz */ regval = phy_read_mmd(phydev, MDIO_MMD_AN, AR803x_CLK_25M_SEL_REG); regval &= ~AR8035_CLK_25M_MASK; /* No surprises */ @@ -144,6 +360,10 @@ static int ar8035_config(struct phy_device *phydev) if (ret < 0) return ret; + ret = ar803x_regs_config(phydev); + if (ret < 0) + return ret; + phydev->supported = phydev->drv->features; genphy_config_aneg(phydev); diff --git a/include/dt-bindings/net/qca-ar803x.h b/include/dt-bindings/net/qca-ar803x.h new file mode 100644 index 00000000000..9c046c7242e --- /dev/null +++ b/include/dt-bindings/net/qca-ar803x.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Device Tree constants for the Qualcomm Atheros AR803x PHYs + */ + +#ifndef _DT_BINDINGS_QCA_AR803X_H +#define _DT_BINDINGS_QCA_AR803X_H + +#define AR803X_STRENGTH_FULL 0 +#define AR803X_STRENGTH_HALF 1 +#define AR803X_STRENGTH_QUARTER 2 + +#endif -- cgit v1.3.1 From 6333cbb3817ed551cd7d4e92f7359c73ccc567fc Mon Sep 17 00:00:00 2001 From: Michael Walle Date: Thu, 7 May 2020 00:11:58 +0200 Subject: phy: atheros: ar8035: remove static clock config We can configure the clock output in the device tree. Disable the hardcoded one in here. This is highly board-specific and should have never been enabled in the PHY driver. If bisecting shows that this commit breaks your board it probably depends on the clock output of your Atheros AR8035 PHY. Please have a look at doc/device-tree-bindings/net/phy/atheros.txt. You need to set "clk-out-frequency = <125000000>" because that value was the hardcoded value until this commit. Signed-off-by: Michael Walle Acked-by: Joe Hershberger --- drivers/net/phy/atheros.c | 13 ------------- 1 file changed, 13 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/phy/atheros.c b/drivers/net/phy/atheros.c index 3cd301c50ed..31427331052 100644 --- a/drivers/net/phy/atheros.c +++ b/drivers/net/phy/atheros.c @@ -38,12 +38,6 @@ #define AR803x_CLK_25M_62_5MHZ_DSP 5 #define AR803x_CLK_25M_125MHZ_PLL 6 #define AR803x_CLK_25M_125MHZ_DSP 7 - -/* AR8035: Select frequency on CLK_25M pin through bits 4:3 */ -#define AR8035_CLK_25M_FREQ_25M (0 | 0) -#define AR8035_CLK_25M_FREQ_50M (0 | BIT(3)) -#define AR8035_CLK_25M_FREQ_62M (BIT(4) | 0) -#define AR8035_CLK_25M_FREQ_125M (BIT(4) | BIT(3)) #define AR8035_CLK_25M_MASK GENMASK(4, 3) #define AR803x_CLK_25M_DR_MASK GENMASK(8, 7) @@ -344,18 +338,11 @@ static int ar8031_config(struct phy_device *phydev) static int ar8035_config(struct phy_device *phydev) { int ret; - int regval; ret = ar803x_of_init(phydev); if (ret < 0) return ret; - /* Configure CLK_25M output clock at 125 MHz */ - regval = phy_read_mmd(phydev, MDIO_MMD_AN, AR803x_CLK_25M_SEL_REG); - regval &= ~AR8035_CLK_25M_MASK; /* No surprises */ - regval |= AR8035_CLK_25M_FREQ_125M; - phy_write_mmd(phydev, MDIO_MMD_AN, AR803x_CLK_25M_SEL_REG, regval); - ret = ar803x_delay_config(phydev); if (ret < 0) return ret; -- cgit v1.3.1 From 8737c65fe4e315af923efde05e5f30041944be08 Mon Sep 17 00:00:00 2001 From: Michael Walle Date: Thu, 7 May 2020 00:11:59 +0200 Subject: phy: atheros: consolidate {ar8031|ar8035}_config() The two functions are now exactly the same, remove one of them. Signed-off-by: Michael Walle Acked-by: Joe Hershberger --- drivers/net/phy/atheros.c | 30 +++--------------------------- 1 file changed, 3 insertions(+), 27 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/phy/atheros.c b/drivers/net/phy/atheros.c index 31427331052..47ff9f8d44c 100644 --- a/drivers/net/phy/atheros.c +++ b/drivers/net/phy/atheros.c @@ -311,31 +311,7 @@ static int ar803x_of_init(struct phy_device *phydev) return 0; } -static int ar8031_config(struct phy_device *phydev) -{ - int ret; - - ret = ar803x_of_init(phydev); - if (ret < 0) - return ret; - - ret = ar803x_delay_config(phydev); - if (ret < 0) - return ret; - - ret = ar803x_regs_config(phydev); - if (ret < 0) - return ret; - - phydev->supported = phydev->drv->features; - - genphy_config_aneg(phydev); - genphy_restart_aneg(phydev); - - return 0; -} - -static int ar8035_config(struct phy_device *phydev) +static int ar803x_config(struct phy_device *phydev) { int ret; @@ -374,7 +350,7 @@ static struct phy_driver AR8031_driver = { .uid = AR8031_PHY_ID, .mask = 0xffffffef, .features = PHY_GBIT_FEATURES, - .config = ar8031_config, + .config = ar803x_config, .startup = genphy_startup, .shutdown = genphy_shutdown, }; @@ -384,7 +360,7 @@ static struct phy_driver AR8035_driver = { .uid = AR8035_PHY_ID, .mask = 0xffffffef, .features = PHY_GBIT_FEATURES, - .config = ar8035_config, + .config = ar803x_config, .startup = genphy_startup, .shutdown = genphy_shutdown, }; -- cgit v1.3.1