From 9fd573c8fb080b9f729015705b489d856904445b Mon Sep 17 00:00:00 2001 From: Denis 'GNUtoo' Carikli Date: Sat, 30 May 2020 05:24:19 +0200 Subject: [PATCH 01/29] board: tbs2910: disable loadb and loads commands The loadb and loads commands are not needed for booting. There are also more reliable and faster alternatives to loadb and loads that can be used with the current configuration. As that the resulting image is already very close to the size limit, removing the loadb and loads commands shouldn't hurt. With arm-linux-gnueabi-gcc 9.2.0-1 from the Parabola GNU/Linux distribution we have the following size reduction: - text: 6733 bytes - data: 116 bytes - bss: 1172 bytes - total: 8021 bytes Signed-off-by: Denis 'GNUtoo' Carikli Acked-by: Soeren Moch --- configs/tbs2910_defconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/configs/tbs2910_defconfig b/configs/tbs2910_defconfig index 2ff0e160f7..2623eb73cd 100644 --- a/configs/tbs2910_defconfig +++ b/configs/tbs2910_defconfig @@ -28,6 +28,8 @@ CONFIG_SYS_MEMTEST_START=0x10000000 CONFIG_SYS_MEMTEST_END=0x2f400000 CONFIG_CMD_GPIO=y CONFIG_CMD_I2C=y +# CONFIG_CMD_LOADB is not set +# CONFIG_CMD_LOADS is not set CONFIG_CMD_MMC=y CONFIG_CMD_PART=y CONFIG_CMD_PCI=y From b3e5d2937972a4385ff665366253244b25f0c0a2 Mon Sep 17 00:00:00 2001 From: Denis 'GNUtoo' Carikli Date: Sat, 30 May 2020 05:24:20 +0200 Subject: [PATCH 02/29] board: tbs2910: disable CONFIG_GZIP As that the resulting image is already very close to the size limit, and that CONFIG_GZIP is not strictly required, removing it shouldn't hurt. With arm-linux-gnueabi-gcc 9.2.0-1 from the Parabola GNU/Linux distribution we have the following size reduction: - text: 9752 - data: 0 - bss: 16 - total: 9768 Signed-off-by: Denis 'GNUtoo' Carikli Acked-by: Soeren Moch --- configs/tbs2910_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/configs/tbs2910_defconfig b/configs/tbs2910_defconfig index 2623eb73cd..cc459e6de6 100644 --- a/configs/tbs2910_defconfig +++ b/configs/tbs2910_defconfig @@ -88,5 +88,6 @@ CONFIG_USB_GADGET_DOWNLOAD=y CONFIG_I2C_EDID=y CONFIG_VIDEO_IPUV3=y CONFIG_VIDEO=y +# CONFIG_GZIP is not set CONFIG_OF_LIBFDT_ASSUME_MASK=0xff # CONFIG_EFI_LOADER is not set From 0c7550f03a67d9fd2b67e4c299f6d8908e2c7d5b Mon Sep 17 00:00:00 2001 From: Denis 'GNUtoo' Carikli Date: Sat, 30 May 2020 05:24:21 +0200 Subject: [PATCH 03/29] board: tbs2910: move CONFIG_BOOTCOMMAND from header to defconfig This doesn't affect the size of the image: with arm-linux-gnueabi-gcc 9.2.0-1 from the Parabola GNU/Linux distribution, the text, data, bss and total sizes remain unchanged. Signed-off-by: Denis 'GNUtoo' Carikli Reviewed-by: Soeren Moch --- configs/tbs2910_defconfig | 2 ++ include/configs/tbs2910.h | 8 -------- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/configs/tbs2910_defconfig b/configs/tbs2910_defconfig index cc459e6de6..d14ff45615 100644 --- a/configs/tbs2910_defconfig +++ b/configs/tbs2910_defconfig @@ -10,6 +10,8 @@ CONFIG_PRE_CON_BUF_ADDR=0x7c000000 CONFIG_CMD_HDMIDETECT=y CONFIG_AHCI=y CONFIG_BOOTDELAY=3 +CONFIG_USE_BOOTCOMMAND=y +CONFIG_BOOTCOMMAND="mmc rescan; if run bootcmd_up1; then run bootcmd_up2; else run bootcmd_mmc; fi" CONFIG_USE_PREBOOT=y CONFIG_PREBOOT="echo PCI:; pci enum; pci 1; usb start; if hdmidet; then run set_con_hdmi; else run set_con_serial; fi" CONFIG_PRE_CONSOLE_BUFFER=y diff --git a/include/configs/tbs2910.h b/include/configs/tbs2910.h index 7376b91f55..a230111251 100644 --- a/include/configs/tbs2910.h +++ b/include/configs/tbs2910.h @@ -100,12 +100,4 @@ "stdin=serial,usbkbd\0" \ "stdout=serial,vga\0" -#define CONFIG_BOOTCOMMAND \ - "mmc rescan; " \ - "if run bootcmd_up1; then " \ - "run bootcmd_up2; " \ - "else " \ - "run bootcmd_mmc; " \ - "fi" - #endif /* __TBS2910_CONFIG_H * */ From e63ab4527ea4ee23de7ee3335d14ee597667b457 Mon Sep 17 00:00:00 2001 From: Denis 'GNUtoo' Carikli Date: Sat, 30 May 2020 05:24:22 +0200 Subject: [PATCH 04/29] board: tbs2910_defconfig: Add support for booting general purpose distributions This is needed to enable distro_boot support later on. Adding the necessary configuration to enable booting general purpose distributions is typically done by enabling CONFIG_DISTRO_DEFAULTS. However the resulting image size is is already very close to the size limit and PXE isn't strictly needed, so instead we made sure that all the configuration selected by CONFIG_DISTRO_DEFAULTS were selected, with the exception of PXE related configuration (CONFIG_BOOTP_PXE and CONFIG_CMD_PXE) that are both disabled. With arm-linux-gnueabi-gcc 9.3.0-1 from the Parabola GNU/Linux distribution, we have the following size differences: - text: +7526 bytes - data: +28 bytes - bss: -12 bytes - total: +7542 bytes Signed-off-by: Denis 'GNUtoo' Carikli Reviewed-by: Soeren Moch --- configs/tbs2910_defconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/configs/tbs2910_defconfig b/configs/tbs2910_defconfig index d14ff45615..fc9095c859 100644 --- a/configs/tbs2910_defconfig +++ b/configs/tbs2910_defconfig @@ -9,6 +9,7 @@ CONFIG_NR_DRAM_BANKS=1 CONFIG_PRE_CON_BUF_ADDR=0x7c000000 CONFIG_CMD_HDMIDETECT=y CONFIG_AHCI=y +CONFIG_ENV_VARS_UBOOT_CONFIG=y CONFIG_BOOTDELAY=3 CONFIG_USE_BOOTCOMMAND=y CONFIG_BOOTCOMMAND="mmc rescan; if run bootcmd_up1; then run bootcmd_up2; else run bootcmd_mmc; fi" @@ -43,6 +44,7 @@ CONFIG_CMD_MII=y CONFIG_CMD_PING=y CONFIG_CMD_CACHE=y CONFIG_CMD_TIME=y +CONFIG_CMD_SYSBOOT=y CONFIG_CMD_EXT2=y CONFIG_CMD_EXT4=y CONFIG_CMD_EXT4_WRITE=y From 9658884f3d923ab266903fd18ee7ff6ecf4ff096 Mon Sep 17 00:00:00 2001 From: Denis 'GNUtoo' Carikli Date: Sat, 30 May 2020 05:24:24 +0200 Subject: [PATCH 05/29] board: tbs2910: Enable distro_boot support. This keeps the compatibility with the old bootcmd. The fdtfile environment variable also needed to be set to imx6q-tbs2910.dtb to enable booting mainline kernels otherwise with extlinux.conf it tries to load mx6-tbs2910.dtb instead. With arm-linux-gnueabi-gcc 9.2.0-1 from the Parabola GNU/Linux distribution, we have the following size differences: - text: +2041 bytes - data: 0 bytes - bss: 0 bytes - total: +2041 bytes Signed-off-by: Denis 'GNUtoo' Carikli Reviewed-by: Soeren Moch --- configs/tbs2910_defconfig | 3 ++- include/configs/tbs2910.h | 18 ++++++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/configs/tbs2910_defconfig b/configs/tbs2910_defconfig index fc9095c859..fbd2293add 100644 --- a/configs/tbs2910_defconfig +++ b/configs/tbs2910_defconfig @@ -12,11 +12,12 @@ CONFIG_AHCI=y CONFIG_ENV_VARS_UBOOT_CONFIG=y CONFIG_BOOTDELAY=3 CONFIG_USE_BOOTCOMMAND=y -CONFIG_BOOTCOMMAND="mmc rescan; if run bootcmd_up1; then run bootcmd_up2; else run bootcmd_mmc; fi" +CONFIG_BOOTCOMMAND="mmc rescan; if run bootcmd_up1; then run bootcmd_up2; else run bootcmd_mmc || run distro_bootcmd; fi" CONFIG_USE_PREBOOT=y CONFIG_PREBOOT="echo PCI:; pci enum; pci 1; usb start; if hdmidet; then run set_con_hdmi; else run set_con_serial; fi" CONFIG_PRE_CONSOLE_BUFFER=y CONFIG_SUPPORT_RAW_INITRD=y +CONFIG_DEFAULT_FDT_FILE="imx6q-tbs2910.dtb" CONFIG_BOUNCE_BUFFER=y CONFIG_BOARD_EARLY_INIT_F=y CONFIG_HUSH_PARSER=y diff --git a/include/configs/tbs2910.h b/include/configs/tbs2910.h index a230111251..17de122852 100644 --- a/include/configs/tbs2910.h +++ b/include/configs/tbs2910.h @@ -76,6 +76,7 @@ #define CONFIG_BOARD_SIZE_LIMIT 392192 /* (CONFIG_ENV_OFFSET - 1024) */ #define CONFIG_EXTRA_ENV_SETTINGS \ + BOOTENV \ "bootargs_mmc1=console=ttymxc0,115200 di0_primary console=tty1\0" \ "bootargs_mmc2=video=mxcfb0:dev=hdmi,1920x1080M@60 " \ "video=mxcfb1:off video=mxcfb2:off fbmem=28M\0" \ @@ -92,6 +93,13 @@ "bootm 0x10800000 0x10d00000\0" \ "console=ttymxc0\0" \ "fan=gpio set 92\0" \ + "fdt_addr=0x13000000\0" \ + "fdt_addr_r=0x13000000\0" \ + "fdtfile=" CONFIG_DEFAULT_FDT_FILE "\0" \ + "kernel_addr_r=0x10008000\0" \ + "pxefile_addr_r=0x10008000\0" \ + "ramdisk_addr_r=0x18000000\0" \ + "scriptaddr=0x14000000\0" \ "set_con_serial=setenv stdout serial; " \ "setenv stderr serial\0" \ "set_con_hdmi=setenv stdout serial,vga; " \ @@ -100,4 +108,14 @@ "stdin=serial,usbkbd\0" \ "stdout=serial,vga\0" +/* Enable distro boot */ +#define BOOT_TARGET_DEVICES(func) \ + func(MMC, mmc, 0) \ + func(MMC, mmc, 1) \ + func(MMC, mmc, 2) \ + func(SATA, sata, 0) \ + func(USB, usb, 0) + +#include + #endif /* __TBS2910_CONFIG_H * */ From f3767bcb31d0ce5c6381d5f6c33a951774ee6d41 Mon Sep 17 00:00:00 2001 From: Denis 'GNUtoo' Carikli Date: Sat, 30 May 2020 05:24:25 +0200 Subject: [PATCH 06/29] board: tbs2910: add documentation This documents the u-boot installation procedure and the hardware in order to get started. Signed-off-by: Denis 'GNUtoo' Carikli [trini: Add MAINTAINERS entry for doc file per Soeren's request] --- board/tbs/tbs2910/MAINTAINERS | 1 + doc/board/index.rst | 1 + doc/board/tbs/index.rst | 9 ++ doc/board/tbs/tbs2910.rst | 191 ++++++++++++++++++++++++++++++++++ 4 files changed, 202 insertions(+) create mode 100644 doc/board/tbs/index.rst create mode 100644 doc/board/tbs/tbs2910.rst diff --git a/board/tbs/tbs2910/MAINTAINERS b/board/tbs/tbs2910/MAINTAINERS index a3ad2f712a..1e3c0d0ece 100644 --- a/board/tbs/tbs2910/MAINTAINERS +++ b/board/tbs/tbs2910/MAINTAINERS @@ -4,4 +4,5 @@ S: Maintained F: arch/arm/dts/imx6q-tbs2910.dts F: board/tbs/tbs2910/ F: configs/tbs2910_defconfig +F: doc/board/tbs/ F: include/configs/tbs2910.h diff --git a/doc/board/index.rst b/doc/board/index.rst index 01b233f737..bb4473152a 100644 --- a/doc/board/index.rst +++ b/doc/board/index.rst @@ -18,5 +18,6 @@ Board-specific doc rockchip/index sifive/index st/index + tbs/index toradex/index xilinx/index diff --git a/doc/board/tbs/index.rst b/doc/board/tbs/index.rst new file mode 100644 index 0000000000..b677bc624f --- /dev/null +++ b/doc/board/tbs/index.rst @@ -0,0 +1,9 @@ +.. SPDX-License-Identifier: GPL-2.0+ + +TBS +=== + +.. toctree:: + :maxdepth: 2 + + tbs2910 diff --git a/doc/board/tbs/tbs2910.rst b/doc/board/tbs/tbs2910.rst new file mode 100644 index 0000000000..e97f2b6e61 --- /dev/null +++ b/doc/board/tbs/tbs2910.rst @@ -0,0 +1,191 @@ +TBS2910 Matrix ARM miniPC +========================= + +Building +-------- +To build u-boot for the TBS2910 Matrix ARM miniPC, you can use the following +procedure: + +First add the ARM toolchain to your PATH + +Then setup the ARCH and cross compilation environment variables. + +When this is done you can then build u-boot for the TBS2910 Matrix ARM miniPC +with the following commands: + +.. code-block:: none + + make mrproper + make tbs2910_defconfig + make + +Once the build is complete, you can find the resulting image as u-boot.imx in +the current directory. + +UART +---- +The UART voltage is at 3.3V and its settings are 115200bps 8N1 + +BOOT/UPDATE boot switch: +------------------------ +The BOOT/UPDATE switch (SW11) is connected to the BOOT_MODE0 and +BOOT_MODE1 SoC pins. It has "BOOT" and "UPDATE" markings both on +the PCB and on the plastic case. + +When set to the "UPDATE" position, the SoC will use the "Boot From Fuses" +configuration, and since BT_FUSE_SEL is 0, this makes the SOC jump to serial +downloader. + +When set in the "BOOT" position, the SoC will use the "Internal boot" +configuration, and since BT_FUSE_SEL is 0, it will then use the GPIO pins +for the boot configuration. + +SW6 binary DIP switch array on the PCB revision 2.1: +---------------------------------------------------- +On that PCB revision, SW6 has 8 positions. + +Switching a position to ON sets the corresponding +register to 1. + +See the following table for a correspondence between the switch positions and +registers: + +=============== ============ +Switch position Register +=============== ============ +1 BOOT_CFG2[3] +2 BOOT_CFG2[4] +3 BOOT_CFG2[5] +4 BOOT_CFG2[6] +5 BOOT_CFG1[4] +6 BOOT_CFG1[5] +7 BOOT_CFG1[6] +8 BOOT_CFG1[7] +=============== ============ + +For example: + + - To boot from the eMMC: 1:ON , 2:ON, 3:ON, 4:OFF, 5:OFF, 6:ON, 7:ON, 8:OFF + - To boot from the microSD slot: 1: ON, 2: OFF, 3: OFF, 4: OFF, 5:OFF, 6:OFF, + 7:ON, 8:OFF + - To boot from the SD slot: 1: OFF, 2: ON, 3: OFF, 4: OFF, 5:OFF, 6:OFF, 7:ON, + 8:OFF + - To boot from SATA: 1: OFF, 2: OFF, 3: OFF, 4: OFF, 5:OFF, 6:ON, 7:OFF, 8:OFF + +You can refer to the BOOT_CFG registers in the I.MX6Q reference manual for +additional details. + +SW6 binary DIP switch array on the PCB revision 2.3: +---------------------------------------------------- +On that PCB revision, SW6 has only 4 positions. + +Switching a position to ON sets the corresponding +register to 1. + +See the following table for a correspondence between the switch positions and +registers: + +=============== ============ +Switch position Register +=============== ============ +1 BOOT_CFG2[3] +2 BOOT_CFG2[4] +3 BOOT_CFG2[5] +4 BOOT_CFG1[5] +=============== ============ + +For example: + +- To boot from the eMMC: 1:ON, 2:ON, 3:ON, 4:ON +- To boot from the microSD slot: 1:ON, 2:OFF, 3:OFF, 4:OFF +- To boot from the SD slot: 1:OFF, 2:ON, 3:OFF, 4:OFF + +You can refer to the BOOT_CFG registers in the I.MX6Q reference manual for +additional details. + +Loading u-boot from USB: +------------------------ +If you need to load u-boot from USB, you can use the following instructions: + +First build imx_usb_loader, as we will need it to load u-boot from USB. This +can be done with the following commands: + +.. code-block:: none + + git clone git://github.com/boundarydevices/imx_usb_loader.git + cd imx_usb_loader + make + +This will create the resulting imx_usb binary. + +When this is done, you can copy the u-boot.imx image that you built earlier +in in the imx_usb_loader directory. + +You will then need to power off the TBS2910 Matrix ARM miniPC and make sure that +the boot switch is set to "UPDATE" + +Once this is done you can connect an USB cable between the computer that will +run imx_usb and the TBS2910 Matrix ARM miniPC. + +If you also need to access the u-boot console, you will also need to connect an +UART cable between the computer running imx_usb and the TBS2910 Matrix ARM +miniPC. + +Once everything is connected you can finally power on the TBS2910 Matrix ARM +miniPC. The SoC will then jump to the serial download and wait for you. + +Finlay, you can load u-boot through USB with with the following command: + +.. code-block:: none + + sudo ./imx_usb -v u-boot.imx + +The u-boot boot messages will then appear in the serial console. + +Install u-boot on the eMMC: +--------------------------- +To install u-boot on the eMMC, you first need to boot the TBS2910 Matrix ARM +miniPC. + +Once booted, you can flash u-boot.imx to mmcblk0boot0 with the +following commands: + +.. code-block:: none + + sudo echo 0 >/sys/block/mmcblk0boot0/force_ro + sudo dd if=u-boot.imx of=/dev/mmcblk0boot0 bs=1k seek=1; sync + +Note that the eMMC card node may vary, so adjust this as needed. + +Once the new u-boot version is installed, to boot on it you then need to power +off the TBS2910 Matrix ARM miniPC. + +Once it is off, you need make sure that the boot switch is set to "BOOT" and +that the SW6 switch is set to boot on the eMMC as described in the previous +sections. + +If you also need to access the u-boot console, you will also need to connect an +UART cable between the computer running imx_usb and the TBS2910 Matrix ARM +miniPC. + +You can then power up the TBS2910 Matrix ARM miniPC and U-Boot messages will +appear in the serial console. + +Booting a distribution: +----------------------- +When booting on the TBS2910 Matrix ARM miniPC, by default U-Boot will first try +to boot from hardcoded offsets from the start of the eMMC. This is for +compatibility with the stock GNU/Linux distribution. + +If that fails it will then try to boot from several interfaces using +'distro_bootcmd': It will first try to boot from the microSD slot, then the +SD slot, then the internal eMMC, then the SATA interface and finally the USB +interface. For more information on how to configure your distribution to boot, +see 'README.distro'. + +Links: +------ + - https://www.tbsdtv.com/download/document/tbs2910/TBS2910-Matrix-ARM-mini-PC-SCH_rev2.1.pdf + - The schematics for the revision 2.1 of the TBS2910 Matrix ARM miniPC. + - https://cache.freescale.com/files/32bit/doc/ref_manual/IMX6DQRM.pdf - The + SoC reference manual for additional details on the BOOT_CFG registers. From 808f13d8fc38959dc90de7243029141e758a5c0a Mon Sep 17 00:00:00 2001 From: "Krebs, Olaf" Date: Mon, 9 Mar 2020 14:27:55 +0000 Subject: [PATCH 07/29] net: Fix error if some network features are disabled If 'CONFIG_CMD_TFTPBOOT' or 'CONFIG_CMD_BOOTP' are disabled, the usage must be disabled, too! Signed-off-by: Olaf Krebs CC: Joe Hershberger --- cmd/net.c | 6 ++++++ net/net.c | 6 ++++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/cmd/net.c b/cmd/net.c index 25390b0474..9bbcdbcfe0 100644 --- a/cmd/net.c +++ b/cmd/net.c @@ -135,11 +135,15 @@ static void netboot_update_env(void) env_set("netmask", tmp); } +#ifdef CONFIG_CMD_BOOTP if (net_hostname[0]) env_set("hostname", net_hostname); +#endif +#ifdef CONFIG_CMD_BOOTP if (net_root_path[0]) env_set("rootpath", net_root_path); +#endif if (net_ip.s_addr) { ip_to_string(net_ip, tmp); @@ -165,8 +169,10 @@ static void netboot_update_env(void) env_set("dnsip2", tmp); } #endif +#ifdef CONFIG_CMD_BOOTP if (net_nis_domain[0]) env_set("domain", net_nis_domain); +#endif #if defined(CONFIG_CMD_SNTP) && defined(CONFIG_BOOTP_TIMEOFFSET) if (net_ntp_time_offset) { diff --git a/net/net.c b/net/net.c index 37932919d0..11683dd6d0 100644 --- a/net/net.c +++ b/net/net.c @@ -456,6 +456,7 @@ restart: net_dev_exists = 1; net_boot_file_size = 0; switch (protocol) { +#ifdef CONFIG_CMD_TFTPBOOT case TFTPGET: #ifdef CONFIG_CMD_TFTPPUT case TFTPPUT: @@ -463,6 +464,7 @@ restart: /* always use ARP to get server ethernet address */ tftp_start(protocol); break; +#endif #ifdef CONFIG_CMD_TFTPSRV case TFTPSRV: tftp_start_server(); @@ -480,13 +482,13 @@ restart: dhcp_request(); /* Basically same as BOOTP */ break; #endif - +#if defined(CONFIG_CMD_BOOTP) case BOOTP: bootp_reset(); net_ip.s_addr = 0; bootp_request(); break; - +#endif #if defined(CONFIG_CMD_RARP) case RARP: rarp_try = 0; From 73d7aec0b1fdbd0681008b226e861127cd8e9ae6 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sun, 15 Mar 2020 00:18:57 +0100 Subject: [PATCH 08/29] net: smc911x: Drop the standalone EEPROM example Drop the example, for two reasons. First, it is tapping directly into the IO accessors of the SMC911x, while it should instead go through the net device API. Second, this makes conversion of the SMC911x driver to DM real hard. Signed-off-by: Marek Vasut Cc: Joe Hershberger Cc: Tom Rini Acked-by: Joe Hershberger --- examples/standalone/Makefile | 4 - examples/standalone/smc911x_eeprom.c | 530 --------------------------- 2 files changed, 534 deletions(-) delete mode 100644 examples/standalone/smc911x_eeprom.c diff --git a/examples/standalone/Makefile b/examples/standalone/Makefile index 4a34813804..d4be0c7350 100644 --- a/examples/standalone/Makefile +++ b/examples/standalone/Makefile @@ -8,10 +8,6 @@ extra-$(CONFIG_SMC91111) += smc91111_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. diff --git a/examples/standalone/smc911x_eeprom.c b/examples/standalone/smc911x_eeprom.c deleted file mode 100644 index 9bd9a6efa3..0000000000 --- a/examples/standalone/smc911x_eeprom.c +++ /dev/null @@ -1,530 +0,0 @@ -/* - * smc911x_eeprom.c - EEPROM interface to SMC911x parts. - * Only tested on SMSC9118 though ... - * - * Copyright 2004-2009 Analog Devices Inc. - * - * Licensed under the GPL-2 or later. - * - * Based on smc91111_eeprom.c which: - * Heavily borrowed from the following peoples GPL'ed software: - * - Wolfgang Denk, DENX Software Engineering, wd@denx.de - * Das U-Boot - * - Ladislav Michl ladis@linux-mips.org - * A rejected patch on the U-Boot mailing list - */ - -#include -#include -#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 u32 smc911x_reg_read(struct eth_device *dev, u32 offset) -{ - return *(volatile u32*)(dev->iobase + offset); -} - -static void smc911x_reg_write(struct eth_device *dev, u32 offset, u32 val) -{ - *(volatile u32*)(dev->iobase + offset) = val; -} -#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); -} -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); -} -#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!?) - */ -static int smsc_ctrlc(void) -{ - return (tstc() && getc() == 0x03); -} - -/** - * usage - dump usage information - */ -static void usage(void) -{ - puts( - "MAC/EEPROM Commands:\n" - " P : Print the MAC addresses\n" - " D : Dump the EEPROM contents\n" - " M : Dump the MAC contents\n" - " C : Copy the MAC address from the EEPROM to the MAC\n" - " W : Write a register in the EEPROM or in the MAC\n" - " Q : Quit\n" - "\n" - "Some commands take arguments:\n" - " W \n" - " E: EEPROM M: MAC\n" - ); -} - -/** - * dump_regs - dump the MAC registers - * - * Registers 0x00 - 0x50 are FIFOs. The 0x50+ are the control registers - * and they're all 32bits long. 0xB8+ are reserved, so don't bother. - */ -static void dump_regs(struct eth_device *dev) -{ - u8 i, j = 0; - for (i = 0x50; i < 0xB8; i += sizeof(u32)) - printf("%02x: 0x%08x %c", i, - smc911x_reg_read(dev, i), - (j++ % 2 ? '\n' : ' ')); -} - -/** - * do_eeprom_cmd - handle eeprom communication - */ -static int do_eeprom_cmd(struct eth_device *dev, int cmd, u8 reg) -{ - if (smc911x_reg_read(dev, E2P_CMD) & E2P_CMD_EPC_BUSY) { - printf("eeprom_cmd: busy at start (E2P_CMD = 0x%08x)\n", - smc911x_reg_read(dev, E2P_CMD)); - return -1; - } - - smc911x_reg_write(dev, E2P_CMD, E2P_CMD_EPC_BUSY | cmd | reg); - - while (smc911x_reg_read(dev, E2P_CMD) & E2P_CMD_EPC_BUSY) - if (smsc_ctrlc()) { - printf("eeprom_cmd: timeout (E2P_CMD = 0x%08x)\n", - smc911x_reg_read(dev, E2P_CMD)); - return -1; - } - - return 0; -} - -/** - * read_eeprom_reg - read specified register in EEPROM - */ -static u8 read_eeprom_reg(struct eth_device *dev, u8 reg) -{ - int ret = do_eeprom_cmd(dev, E2P_CMD_EPC_CMD_READ, reg); - return (ret ? : smc911x_reg_read(dev, E2P_DATA)); -} - -/** - * write_eeprom_reg - write specified value into specified register in EEPROM - */ -static int write_eeprom_reg(struct eth_device *dev, u8 value, u8 reg) -{ - int ret; - - /* enable erasing/writing */ - ret = do_eeprom_cmd(dev, E2P_CMD_EPC_CMD_EWEN, reg); - if (ret) - goto done; - - /* erase the eeprom reg */ - ret = do_eeprom_cmd(dev, E2P_CMD_EPC_CMD_ERASE, reg); - if (ret) - goto done; - - /* write the eeprom reg */ - smc911x_reg_write(dev, E2P_DATA, value); - ret = do_eeprom_cmd(dev, E2P_CMD_EPC_CMD_WRITE, reg); - if (ret) - goto done; - - /* disable erasing/writing */ - ret = do_eeprom_cmd(dev, E2P_CMD_EPC_CMD_EWDS, reg); - - done: - return ret; -} - -/** - * skip_space - find first non-whitespace in given pointer - */ -static char *skip_space(char *buf) -{ - while (isblank(buf[0])) - ++buf; - return buf; -} - -/** - * write_stuff - handle writing of MAC registers / eeprom - */ -static void write_stuff(struct eth_device *dev, char *line) -{ - char dest; - char *endp; - u8 reg; - u32 value; - - /* Skip over the "W " part of the command */ - line = skip_space(line + 1); - - /* Figure out destination */ - switch (line[0]) { - case 'E': - case 'M': - dest = line[0]; - break; - default: - invalid_usage: - printf("ERROR: Invalid write usage\n"); - usage(); - return; - } - - /* Get the register to write */ - line = skip_space(line + 1); - reg = simple_strtoul(line, &endp, 16); - if (line == endp) - goto invalid_usage; - - /* Get the value to write */ - line = skip_space(endp); - value = simple_strtoul(line, &endp, 16); - if (line == endp) - goto invalid_usage; - - /* Check for trailing cruft */ - line = skip_space(endp); - if (line[0]) - goto invalid_usage; - - /* Finally, execute the command */ - if (dest == 'E') { - printf("Writing EEPROM register %02x with %02x\n", reg, value); - write_eeprom_reg(dev, value, reg); - } else { - printf("Writing MAC register %02x with %08x\n", reg, value); - smc911x_reg_write(dev, reg, value); - } -} - -/** - * copy_from_eeprom - copy MAC address in eeprom to address registers - */ -static void copy_from_eeprom(struct eth_device *dev) -{ - ulong addrl = - read_eeprom_reg(dev, 0x01) | - read_eeprom_reg(dev, 0x02) << 8 | - read_eeprom_reg(dev, 0x03) << 16 | - read_eeprom_reg(dev, 0x04) << 24; - ulong addrh = - read_eeprom_reg(dev, 0x05) | - read_eeprom_reg(dev, 0x06) << 8; - smc911x_set_mac_csr(dev, ADDRL, addrl); - smc911x_set_mac_csr(dev, ADDRH, addrh); - puts("EEPROM contents copied to MAC\n"); -} - -/** - * print_macaddr - print MAC address registers and MAC address in eeprom - */ -static void print_macaddr(struct eth_device *dev) -{ - puts("Current MAC Address in MAC: "); - ulong addrl = smc911x_get_mac_csr(dev, ADDRL); - ulong addrh = smc911x_get_mac_csr(dev, ADDRH); - printf("%02x:%02x:%02x:%02x:%02x:%02x\n", - (u8)(addrl), (u8)(addrl >> 8), (u8)(addrl >> 16), - (u8)(addrl >> 24), (u8)(addrh), (u8)(addrh >> 8)); - - puts("Current MAC Address in EEPROM: "); - int i; - for (i = 1; i < 6; ++i) - printf("%02x:", read_eeprom_reg(dev, i)); - printf("%02x\n", read_eeprom_reg(dev, i)); -} - -/** - * dump_eeprom - dump the whole content of the EEPROM - */ -static void dump_eeprom(struct eth_device *dev) -{ - int i; - puts("EEPROM:\n"); - for (i = 0; i < 7; ++i) - printf("%02x: 0x%02x\n", i, read_eeprom_reg(dev, i)); -} - -/** - * smc911x_init - get the MAC/EEPROM up and ready for use - */ -static int smc911x_init(struct eth_device *dev) -{ - /* See if there is anything there */ - if (smc911x_detect_chip(dev)) - return 1; - - smc911x_reset(dev); - - /* Make sure we set EEDIO/EECLK to the EEPROM */ - if (smc911x_reg_read(dev, GPIO_CFG) & GPIO_CFG_EEPR_EN) { - while (smc911x_reg_read(dev, E2P_CMD) & E2P_CMD_EPC_BUSY) - if (smsc_ctrlc()) { - printf("init: timeout (E2P_CMD = 0x%08x)\n", - smc911x_reg_read(dev, E2P_CMD)); - return 1; - } - smc911x_reg_write(dev, GPIO_CFG, - smc911x_reg_read(dev, GPIO_CFG) & ~GPIO_CFG_EEPR_EN); - } - - return 0; -} - -/** - * getline - consume a line of input and handle some escape sequences - */ -static char *getline(void) -{ - static char buffer[100]; - char c; - size_t i; - - i = 0; - while (1) { - buffer[i] = '\0'; - while (!tstc()) - continue; - - c = getc(); - /* Convert to uppercase */ - if (c >= 'a' && c <= 'z') - c -= ('a' - 'A'); - - switch (c) { - case '\r': /* Enter/Return key */ - case '\n': - puts("\n"); - return buffer; - - case 0x03: /* ^C - break */ - return NULL; - - case 0x5F: - case 0x08: /* ^H - backspace */ - case 0x7F: /* DEL - backspace */ - if (i) { - puts("\b \b"); - i--; - } - break; - - default: - /* Ignore control characters */ - if (c < 0x20) - break; - /* Queue up all other characters */ - buffer[i++] = c; - printf("%c", c); - break; - } - } -} - -/** - * smc911x_eeprom - our application's main() function - */ -int smc911x_eeprom(int argc, char *const argv[]) -{ - /* Avoid initializing on stack as gcc likes to call memset() */ - struct eth_device dev; - dev.iobase = CONFIG_SMC911X_BASE; - - /* Print the ABI version */ - app_startup(argv); - if (XF_VERSION != get_version()) { - printf("Expects ABI version %d\n", XF_VERSION); - printf("Actual U-Boot ABI version %lu\n", get_version()); - printf("Can't run\n\n"); - return 1; - } - - /* Initialize the MAC/EEPROM somewhat */ - puts("\n"); - if (smc911x_init(&dev)) - return 1; - - /* Dump helpful usage information */ - puts("\n"); - usage(); - puts("\n"); - - while (1) { - char *line; - - /* Send the prompt and wait for a line */ - puts("eeprom> "); - line = getline(); - - /* Got a ctrl+c */ - if (!line) - return 0; - - /* Eat leading space */ - line = skip_space(line); - - /* Empty line, try again */ - if (!line[0]) - continue; - - /* Only accept 1 letter commands */ - if (line[0] && line[1] && !isblank(line[1])) - goto unknown_cmd; - - /* Now parse the command */ - switch (line[0]) { - case 'W': write_stuff(&dev, line); break; - case 'D': dump_eeprom(&dev); break; - case 'M': dump_regs(&dev); break; - case 'C': copy_from_eeprom(&dev); break; - case 'P': print_macaddr(&dev); break; - unknown_cmd: - default: puts("ERROR: Unknown command!\n\n"); - case '?': - case 'H': usage(); break; - case 'Q': return 0; - } - } -} From baafd99d13931312ff3e2c1c75922d8a46222f7f Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Thu, 26 Mar 2020 03:54:01 +0000 Subject: [PATCH 09/29] net: phy: micrel: ksz8061 implement errata 80000688A fix Linux commit 232ba3a51cc2 ('net: phy: Micrel KSZ8061: link failure after cable connect') implements a fix for the above errata. This patch replicates that errata fix in an ksz8061 specific init routine. Signed-off-by: Bryan O'Donoghue Acked-by: Joe Hershberger --- drivers/net/phy/micrel_ksz8xxx.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/drivers/net/phy/micrel_ksz8xxx.c b/drivers/net/phy/micrel_ksz8xxx.c index 98a0c83e68..60d42fe984 100644 --- a/drivers/net/phy/micrel_ksz8xxx.c +++ b/drivers/net/phy/micrel_ksz8xxx.c @@ -82,6 +82,21 @@ static struct phy_driver KSZ8051_driver = { .shutdown = &genphy_shutdown, }; +static int ksz8061_config(struct phy_device *phydev) +{ + return phy_write(phydev, MDIO_MMD_PMAPMD, MDIO_DEVID1, 0xB61A); +} + +static struct phy_driver KSZ8061_driver = { + .name = "Micrel KSZ8061", + .uid = 0x00221570, + .mask = 0xfffff0, + .features = PHY_BASIC_FEATURES, + .config = &ksz8061_config, + .startup = &genphy_startup, + .shutdown = &genphy_shutdown, +}; + static int ksz8081_config(struct phy_device *phydev) { int ret; @@ -210,6 +225,7 @@ int phy_micrel_ksz8xxx_init(void) phy_register(&KSZ804_driver); phy_register(&KSZ8031_driver); phy_register(&KSZ8051_driver); + phy_register(&KSZ8061_driver); phy_register(&KSZ8081_driver); phy_register(&KS8721_driver); phy_register(&ksz8895_driver); From a7a435e7d41db6a611427b4cc5fd506a18fb2c2f Mon Sep 17 00:00:00 2001 From: Tom Warren Date: Thu, 26 Mar 2020 15:59:13 -0700 Subject: [PATCH 10/29] net: rt8169: WAR for DHCP not getting IP after kernel boot/reboot This is a WAR for DHCP failure after rebooting from the L4T kernel. The r8169.c kernel driver is setting bit 19 of the rt816x HW register 0xF0, which goes by FuncEvent and MISC in various driver source/datasheets. That bit is called RxDv_Gated_En in the r8169.c kernel driver. Clear it here at the end of probe to ensure that U-Boot can get an IP assigned via DHCP. Signed-off-by: Tom Warren --- drivers/net/rtl8169.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/drivers/net/rtl8169.c b/drivers/net/rtl8169.c index 75058fdadc..fb4fae20e5 100644 --- a/drivers/net/rtl8169.c +++ b/drivers/net/rtl8169.c @@ -240,6 +240,9 @@ enum RTL8169_register_content { /*_TBICSRBit*/ TBILinkOK = 0x02000000, + + /* FuncEvent/Misc */ + RxDv_Gated_En = 0x80000, }; static struct { @@ -1210,6 +1213,19 @@ static int rtl8169_eth_probe(struct udevice *dev) return ret; } + /* + * WAR for DHCP failure after rebooting from kernel. + * Clear RxDv_Gated_En bit which was set by kernel driver. + * Without this, U-Boot can't get an IP via DHCP. + * Register (FuncEvent, aka MISC) and RXDV_GATED_EN bit are from + * the r8169.c kernel driver. + */ + + u32 val = RTL_R32(FuncEvent); + debug("%s: FuncEvent/Misc (0xF0) = 0x%08X\n", __func__, val); + val &= ~RxDv_Gated_En; + RTL_W32(FuncEvent, val); + return 0; } From 9c6de508a6362a3ddd4067e90f07ae613f312aa4 Mon Sep 17 00:00:00 2001 From: Florin Chiculita Date: Wed, 29 Apr 2020 14:25:48 +0300 Subject: [PATCH 11/29] net: phy: add phyid search in vendor specific space There are devices accesible through mdio clause-45, such as retimers, that do not have PMA or PCS blocks. This patch adds MDIO_MMD_VEND1 on the list of device addresses where phyid is searched. Previous order of devices was kept. Signed-off-by: Florin Chiculita Reviewed-by: Madalin Bucur --- drivers/net/phy/phy.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c index cce09c47f9..67789897c2 100644 --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c @@ -786,17 +786,27 @@ static struct phy_device *get_phy_device_by_mask(struct mii_dev *bus, uint phy_mask, phy_interface_t interface) { - int i; struct phy_device *phydev; + int devad[] = { + /* Clause-22 */ + MDIO_DEVAD_NONE, + /* Clause-45 */ + MDIO_MMD_PMAPMD, + MDIO_MMD_WIS, + MDIO_MMD_PCS, + MDIO_MMD_PHYXS, + MDIO_MMD_VEND1, + }; + int i, devad_cnt; + devad_cnt = sizeof(devad)/sizeof(int); phydev = search_for_existing_phy(bus, phy_mask, interface); if (phydev) return phydev; - /* Try Standard (ie Clause 22) access */ - /* Otherwise we have to try Clause 45 */ - for (i = 0; i < 5; i++) { + /* try different access clauses */ + for (i = 0; i < devad_cnt; i++) { phydev = create_phy_by_mask(bus, phy_mask, - i ? i : MDIO_DEVAD_NONE, interface); + devad[i], interface); if (IS_ERR(phydev)) return NULL; if (phydev) From 6325c8bc484e3c123c95854bbe52543eecc7127d Mon Sep 17 00:00:00 2001 From: Dan Murphy Date: Mon, 4 May 2020 16:14:36 -0500 Subject: [PATCH 12/29] net: phy: Add missing kernel doc to phy functions Add kernel doc to the phy_read/write utility functions in phy.h Acked-by: Michal Simek Signed-off-by: Dan Murphy --- include/phy.h | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/include/phy.h b/include/phy.h index b5de14cbfc..c1f6509e42 100644 --- a/include/phy.h +++ b/include/phy.h @@ -170,6 +170,13 @@ struct fixed_link { int asym_pause; }; +/** + * phy_read - Convenience function for reading a given PHY register + * @phydev: the phy_device struct + * @devad: The MMD to read from + * @regnum: register number to read + * @return: value for success or negative errno for failure + */ static inline int phy_read(struct phy_device *phydev, int devad, int regnum) { struct mii_dev *bus = phydev->bus; @@ -182,6 +189,14 @@ static inline int phy_read(struct phy_device *phydev, int devad, int regnum) return bus->read(bus, phydev->addr, devad, regnum); } +/** + * phy_write - Convenience function for writing a given PHY register + * @phydev: the phy_device struct + * @devad: The MMD to read from + * @regnum: register number to write + * @val: value to write to @regnum + * @return: 0 for success or negative errno for failure + */ static inline int phy_write(struct phy_device *phydev, int devad, int regnum, u16 val) { @@ -195,6 +210,13 @@ static inline int phy_write(struct phy_device *phydev, int devad, int regnum, return bus->write(bus, phydev->addr, devad, regnum, val); } +/** + * phy_mmd_start_indirect - Convenience function for writing MMD registers + * @phydev: the phy_device struct + * @devad: The MMD to read from + * @regnum: register number to write + * @return: None + */ static inline void phy_mmd_start_indirect(struct phy_device *phydev, int devad, int regnum) { @@ -209,6 +231,14 @@ static inline void phy_mmd_start_indirect(struct phy_device *phydev, int devad, (devad | MII_MMD_CTRL_NOINCR)); } +/** + * phy_read_mmd - Convenience function for reading a register + * from an MMD on a given PHY. + * @phydev: The phy_device struct + * @devad: The MMD to read from + * @regnum: The register on the MMD to read + * @return: Value for success or negative errno for failure + */ static inline int phy_read_mmd(struct phy_device *phydev, int devad, int regnum) { @@ -233,6 +263,15 @@ static inline int phy_read_mmd(struct phy_device *phydev, int devad, return phy_read(phydev, MDIO_DEVAD_NONE, MII_MMD_DATA); } +/** + * phy_write_mmd - Convenience function for writing a register + * on an MMD on a given PHY. + * @phydev: The phy_device struct + * @devad: The MMD to read from + * @regnum: The register on the MMD to read + * @val: value to write to @regnum + * @return: 0 for success or negative errno for failure + */ static inline int phy_write_mmd(struct phy_device *phydev, int devad, int regnum, u16 val) { From ea756fb8b71f5399c10f4a8f7e4325ced90d7c9f Mon Sep 17 00:00:00 2001 From: Dan Murphy Date: Mon, 4 May 2020 16:14:37 -0500 Subject: [PATCH 13/29] net: phy: Fix kernel doc issues in phy.h Fix kernel doc warnings in phy.h. Mostly the warnings were due to the return missing the semi-colon. Acked-by: Michal Simek Signed-off-by: Dan Murphy --- include/phy.h | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/include/phy.h b/include/phy.h index c1f6509e42..34c2af719b 100644 --- a/include/phy.h +++ b/include/phy.h @@ -314,26 +314,23 @@ static inline int is_10g_interface(phy_interface_t interface) /** * phy_init() - Initializes the PHY drivers - * * This function registers all available PHY drivers * - * @return 0 if OK, -ve on error + * @return: 0 if OK, -ve on error */ int phy_init(void); /** * phy_reset() - Resets the specified PHY - * * Issues a reset of the PHY and waits for it to complete * * @phydev: PHY to reset - * @return 0 if OK, -ve on error + * @return: 0 if OK, -ve on error */ int phy_reset(struct phy_device *phydev); /** * phy_find_by_mask() - Searches for a PHY on the specified MDIO bus - * * The function checks the PHY addresses flagged in phy_mask and returns a * phy_device pointer if it detects a PHY. * This function should only be called if just one PHY is expected to be present @@ -343,7 +340,7 @@ int phy_reset(struct phy_device *phydev); * @bus: MII/MDIO bus to scan * @phy_mask: bitmap of PYH addresses to scan * @interface: type of MAC-PHY interface - * @return pointer to phy_device if a PHY is found, or NULL otherwise + * @return: pointer to phy_device if a PHY is found, or NULL otherwise */ struct phy_device *phy_find_by_mask(struct mii_dev *bus, unsigned phy_mask, phy_interface_t interface); @@ -359,7 +356,6 @@ void phy_connect_dev(struct phy_device *phydev, struct udevice *dev); /** * phy_connect() - Creates a PHY device for the Ethernet interface - * * Creates a PHY device for the PHY at the given address, if one doesn't exist * already, and associates it with the Ethernet device. * The function may be called with addr <= 0, in this case addr value is ignored @@ -371,7 +367,7 @@ void phy_connect_dev(struct phy_device *phydev, struct udevice *dev); * @addr: PHY address on MDIO bus * @dev: Ethernet device to associate to the PHY * @interface: type of MAC-PHY interface - * @return pointer to phy_device if a PHY is found, or NULL otherwise + * @return: pointer to phy_device if a PHY is found, or NULL otherwise */ struct phy_device *phy_connect(struct mii_dev *bus, int addr, struct udevice *dev, @@ -395,7 +391,6 @@ void phy_connect_dev(struct phy_device *phydev, struct eth_device *dev); /** * phy_connect() - Creates a PHY device for the Ethernet interface - * * Creates a PHY device for the PHY at the given address, if one doesn't exist * already, and associates it with the Ethernet device. * The function may be called with addr <= 0, in this case addr value is ignored @@ -407,7 +402,7 @@ void phy_connect_dev(struct phy_device *phydev, struct eth_device *dev); * @addr: PHY address on MDIO bus * @dev: Ethernet device to associate to the PHY * @interface: type of MAC-PHY interface - * @return pointer to phy_device if a PHY is found, or NULL otherwise + * @return: pointer to phy_device if a PHY is found, or NULL otherwise */ struct phy_device *phy_connect(struct mii_dev *bus, int addr, struct eth_device *dev, @@ -467,7 +462,7 @@ int get_phy_id(struct mii_dev *bus, int addr, int devad, u32 *phy_id); * phy_get_interface_by_name() - Look up a PHY interface name * * @str: PHY interface name, e.g. "mii" - * @return PHY_INTERFACE_MODE_... value, or -1 if not found + * @return: PHY_INTERFACE_MODE_... value, or -1 if not found */ int phy_get_interface_by_name(const char *str); @@ -475,6 +470,7 @@ int phy_get_interface_by_name(const char *str); * phy_interface_is_rgmii - Convenience function for testing if a PHY interface * is RGMII (all variants) * @phydev: the phy_device struct + * @return: true if MII bus is RGMII or false if it is not */ static inline bool phy_interface_is_rgmii(struct phy_device *phydev) { @@ -486,6 +482,7 @@ static inline bool phy_interface_is_rgmii(struct phy_device *phydev) * phy_interface_is_sgmii - Convenience function for testing if a PHY interface * is SGMII (all variants) * @phydev: the phy_device struct + * @return: true if MII bus is SGMII or false if it is not */ static inline bool phy_interface_is_sgmii(struct phy_device *phydev) { From 535247a9e455a165943efcdbb7e144e816d6e904 Mon Sep 17 00:00:00 2001 From: Dan Murphy Date: Mon, 4 May 2020 16:14:38 -0500 Subject: [PATCH 14/29] net: phy: Add helper routines to set and clear bits Add phy_set/clear_bit helper routines so that ported drivers from the kernel can use these functions. Acked-by: Michal Simek Signed-off-by: Dan Murphy --- include/phy.h | 54 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/include/phy.h b/include/phy.h index 34c2af719b..fedd146091 100644 --- a/include/phy.h +++ b/include/phy.h @@ -296,6 +296,60 @@ static inline int phy_write_mmd(struct phy_device *phydev, int devad, return phy_write(phydev, MDIO_DEVAD_NONE, MII_MMD_DATA, val); } +/** + * phy_set_bits_mmd - Convenience function for setting bits in a register + * on MMD + * @phydev: the phy_device struct + * @devad: the MMD containing register to modify + * @regnum: register number to modify + * @val: bits to set + * @return: 0 for success or negative errno for failure + */ +static inline int phy_set_bits_mmd(struct phy_device *phydev, int devad, + u32 regnum, u16 val) +{ + int value, ret; + + value = phy_read_mmd(phydev, devad, regnum); + if (value < 0) + return value; + + value |= val; + + ret = phy_write_mmd(phydev, devad, regnum, value); + if (ret < 0) + return ret; + + return 0; +} + +/** + * phy_clear_bits_mmd - Convenience function for clearing bits in a register + * on MMD + * @phydev: the phy_device struct + * @devad: the MMD containing register to modify + * @regnum: register number to modify + * @val: bits to clear + * @return: 0 for success or negative errno for failure + */ +static inline int phy_clear_bits_mmd(struct phy_device *phydev, int devad, + u32 regnum, u16 val) +{ + int value, ret; + + value = phy_read_mmd(phydev, devad, regnum); + if (value < 0) + return value; + + value &= ~val; + + ret = phy_write_mmd(phydev, devad, regnum, value); + if (ret < 0) + return ret; + + return 0; +} + #ifdef CONFIG_PHYLIB_10G extern struct phy_driver gen10g_driver; From bc0e578f903d24b5291d34959ad534138ced0780 Mon Sep 17 00:00:00 2001 From: Dan Murphy Date: Mon, 4 May 2020 16:14:39 -0500 Subject: [PATCH 15/29] net: phy: Add support for TI PHY init ti_phy_init function was allocated to the DP83867 PHY. This function name is to generic for a specific PHY. The function can be moved to a TI specific file that can register all TI PHYs that are defined in the defconfig. The ti_phy_init file will contain all TI PHYs initialization so that only phy_ti_init can be called from the framework. In addition to the above the config flag for the DP83867 needs to be changed in the Kconfig and dependent defconfig files. The config flag that was used for the DP83867 was also generic in nature so a more specific config flag for the DP83867 was created. Acked-by: Michal Simek Signed-off-by: Dan Murphy --- configs/am65x_evm_a53_defconfig | 2 +- configs/am65x_hs_evm_a53_defconfig | 2 +- configs/dra7xx_evm_defconfig | 2 +- configs/dra7xx_hs_evm_defconfig | 2 +- configs/dra7xx_hs_evm_usb_defconfig | 2 +- configs/j721e_evm_a72_defconfig | 2 +- configs/j721e_hs_evm_a72_defconfig | 2 +- configs/k2g_evm_defconfig | 2 +- configs/xilinx_versal_virt_defconfig | 2 +- configs/xilinx_zynqmp_virt_defconfig | 2 +- drivers/net/phy/Kconfig | 8 ++++++++ drivers/net/phy/Makefile | 3 ++- drivers/net/phy/dp83867.c | 3 ++- drivers/net/phy/ti_phy_init.c | 18 ++++++++++++++++++ drivers/net/phy/ti_phy_init.h | 15 +++++++++++++++ 15 files changed, 55 insertions(+), 12 deletions(-) create mode 100644 drivers/net/phy/ti_phy_init.c create mode 100644 drivers/net/phy/ti_phy_init.h diff --git a/configs/am65x_evm_a53_defconfig b/configs/am65x_evm_a53_defconfig index d74a2d0930..c5ca4da73a 100644 --- a/configs/am65x_evm_a53_defconfig +++ b/configs/am65x_evm_a53_defconfig @@ -99,7 +99,7 @@ CONFIG_SPI_FLASH_SFDP_SUPPORT=y CONFIG_SPI_FLASH_STMICRO=y # CONFIG_SPI_FLASH_USE_4K_SECTORS is not set CONFIG_SPI_FLASH_MTD=y -CONFIG_PHY_TI=y +CONFIG_PHY_TI_DP83867=y CONFIG_PHY_FIXED=y CONFIG_DM_ETH=y CONFIG_E1000=y diff --git a/configs/am65x_hs_evm_a53_defconfig b/configs/am65x_hs_evm_a53_defconfig index 117953817d..644873d67c 100644 --- a/configs/am65x_hs_evm_a53_defconfig +++ b/configs/am65x_hs_evm_a53_defconfig @@ -101,7 +101,7 @@ CONFIG_SPI_FLASH_SFDP_SUPPORT=y CONFIG_SPI_FLASH_STMICRO=y # CONFIG_SPI_FLASH_USE_4K_SECTORS is not set CONFIG_SPI_FLASH_MTD=y -CONFIG_PHY_TI=y +CONFIG_PHY_TI_DP83867=y CONFIG_PHY_FIXED=y CONFIG_DM_ETH=y CONFIG_E1000=y diff --git a/configs/dra7xx_evm_defconfig b/configs/dra7xx_evm_defconfig index e4547d9dcc..73ac3b319b 100644 --- a/configs/dra7xx_evm_defconfig +++ b/configs/dra7xx_evm_defconfig @@ -86,7 +86,7 @@ CONFIG_DM_SPI_FLASH=y CONFIG_SF_DEFAULT_MODE=0 CONFIG_SF_DEFAULT_SPEED=76800000 CONFIG_SPI_FLASH_SPANSION=y -CONFIG_PHY_TI=y +CONFIG_PHY_TI_DP83867=y CONFIG_DM_ETH=y CONFIG_PHY_GIGE=y CONFIG_MII=y diff --git a/configs/dra7xx_hs_evm_defconfig b/configs/dra7xx_hs_evm_defconfig index c08bcce903..40dc554e80 100644 --- a/configs/dra7xx_hs_evm_defconfig +++ b/configs/dra7xx_hs_evm_defconfig @@ -89,7 +89,7 @@ CONFIG_DM_SPI_FLASH=y CONFIG_SF_DEFAULT_MODE=0 CONFIG_SF_DEFAULT_SPEED=76800000 CONFIG_SPI_FLASH_SPANSION=y -CONFIG_PHY_TI=y +CONFIG_PHY_TI_DP83867=y CONFIG_DM_ETH=y CONFIG_PHY_GIGE=y CONFIG_MII=y diff --git a/configs/dra7xx_hs_evm_usb_defconfig b/configs/dra7xx_hs_evm_usb_defconfig index 879c2b650b..babd7029c0 100644 --- a/configs/dra7xx_hs_evm_usb_defconfig +++ b/configs/dra7xx_hs_evm_usb_defconfig @@ -87,7 +87,7 @@ CONFIG_SF_DEFAULT_MODE=0 CONFIG_SF_DEFAULT_SPEED=76800000 CONFIG_SPI_FLASH_BAR=y CONFIG_SPI_FLASH_SPANSION=y -CONFIG_PHY_TI=y +CONFIG_PHY_TI_DP83867=y CONFIG_DM_ETH=y CONFIG_PHY_GIGE=y CONFIG_MII=y diff --git a/configs/j721e_evm_a72_defconfig b/configs/j721e_evm_a72_defconfig index 4deb4e219f..91a0572287 100644 --- a/configs/j721e_evm_a72_defconfig +++ b/configs/j721e_evm_a72_defconfig @@ -123,7 +123,7 @@ CONFIG_DM_SPI_FLASH=y CONFIG_SPI_FLASH_STMICRO=y # CONFIG_SPI_FLASH_USE_4K_SECTORS is not set CONFIG_SPI_FLASH_MTD=y -CONFIG_PHY_TI=y +CONFIG_PHY_TI_DP83867=y CONFIG_PHY_FIXED=y CONFIG_DM_ETH=y CONFIG_TI_AM65_CPSW_NUSS=y diff --git a/configs/j721e_hs_evm_a72_defconfig b/configs/j721e_hs_evm_a72_defconfig index ae540a26a4..9aa3113642 100644 --- a/configs/j721e_hs_evm_a72_defconfig +++ b/configs/j721e_hs_evm_a72_defconfig @@ -113,7 +113,7 @@ CONFIG_DM_SPI_FLASH=y CONFIG_SPI_FLASH_STMICRO=y # CONFIG_SPI_FLASH_USE_4K_SECTORS is not set CONFIG_SPI_FLASH_MTD=y -CONFIG_PHY_TI=y +CONFIG_PHY_TI_DP83867=y CONFIG_PHY_FIXED=y CONFIG_DM_ETH=y CONFIG_TI_AM65_CPSW_NUSS=y diff --git a/configs/k2g_evm_defconfig b/configs/k2g_evm_defconfig index 5bc7f7f865..0379021c14 100644 --- a/configs/k2g_evm_defconfig +++ b/configs/k2g_evm_defconfig @@ -58,7 +58,7 @@ CONFIG_PHYLIB=y CONFIG_PHY_MARVELL=y CONFIG_PHY_MICREL=y CONFIG_PHY_MICREL_KSZ8XXX=y -CONFIG_PHY_TI=y +CONFIG_PHY_TI_DP83867=y CONFIG_DM_ETH=y CONFIG_MII=y CONFIG_DRIVER_TI_KEYSTONE_NET=y diff --git a/configs/xilinx_versal_virt_defconfig b/configs/xilinx_versal_virt_defconfig index 4ed14f7030..b3e21ea903 100644 --- a/configs/xilinx_versal_virt_defconfig +++ b/configs/xilinx_versal_virt_defconfig @@ -63,7 +63,7 @@ CONFIG_SPI_FLASH_WINBOND=y CONFIG_PHY_MARVELL=y CONFIG_PHY_NATSEMI=y CONFIG_PHY_REALTEK=y -CONFIG_PHY_TI=y +CONFIG_PHY_TI_DP83867=y CONFIG_PHY_VITESSE=y CONFIG_PHY_FIXED=y CONFIG_PHY_GIGE=y diff --git a/configs/xilinx_zynqmp_virt_defconfig b/configs/xilinx_zynqmp_virt_defconfig index 7886d5a38f..2b4a0244fa 100644 --- a/configs/xilinx_zynqmp_virt_defconfig +++ b/configs/xilinx_zynqmp_virt_defconfig @@ -108,7 +108,7 @@ CONFIG_PHY_MICREL=y CONFIG_PHY_MICREL_KSZ90X1=y CONFIG_PHY_NATSEMI=y CONFIG_PHY_REALTEK=y -CONFIG_PHY_TI=y +CONFIG_PHY_TI_DP83867=y CONFIG_PHY_VITESSE=y CONFIG_PHY_XILINX_GMII2RGMII=y CONFIG_PHY_FIXED=y diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig index d1f049e62a..a5a1ff257f 100644 --- a/drivers/net/phy/Kconfig +++ b/drivers/net/phy/Kconfig @@ -243,6 +243,14 @@ config PHY_TERANETICS config PHY_TI bool "Texas Instruments Ethernet PHYs support" + ---help--- + Adds PHY registration support for TI PHYs. + +config PHY_TI_DP83867 + select PHY_TI + bool "Texas Instruments Ethernet DP83867 PHY support" + ---help--- + Adds support for the TI DP83867 1Gbit PHY. config PHY_VITESSE bool "Vitesse Ethernet PHYs support" diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile index 1d81516ecd..6e722331f1 100644 --- a/drivers/net/phy/Makefile +++ b/drivers/net/phy/Makefile @@ -25,7 +25,8 @@ obj-$(CONFIG_PHY_NATSEMI) += natsemi.o obj-$(CONFIG_PHY_REALTEK) += realtek.o obj-$(CONFIG_PHY_SMSC) += smsc.o obj-$(CONFIG_PHY_TERANETICS) += teranetics.o -obj-$(CONFIG_PHY_TI) += dp83867.o +obj-$(CONFIG_PHY_TI) += ti_phy_init.o +obj-$(CONFIG_PHY_TI_DP83867) += dp83867.o obj-$(CONFIG_PHY_XILINX) += xilinx_phy.o obj-$(CONFIG_PHY_XILINX_GMII2RGMII) += xilinx_gmii2rgmii.o obj-$(CONFIG_PHY_VITESSE) += vitesse.o diff --git a/drivers/net/phy/dp83867.c b/drivers/net/phy/dp83867.c index d435cc1e6c..eada4541c9 100644 --- a/drivers/net/phy/dp83867.c +++ b/drivers/net/phy/dp83867.c @@ -14,6 +14,7 @@ #include #include +#include "ti_phy_init.h" /* TI DP83867 */ #define DP83867_DEVADDR 0x1f @@ -430,7 +431,7 @@ static struct phy_driver DP83867_driver = { .shutdown = &genphy_shutdown, }; -int phy_ti_init(void) +int phy_dp83867_init(void) { phy_register(&DP83867_driver); return 0; diff --git a/drivers/net/phy/ti_phy_init.c b/drivers/net/phy/ti_phy_init.c new file mode 100644 index 0000000000..277b29a263 --- /dev/null +++ b/drivers/net/phy/ti_phy_init.c @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * TI Generic PHY Init to register any TI Ethernet PHYs + * + * Author: Dan Murphy + * + * Copyright (C) 2019-20 Texas Instruments Inc. + */ + +#include "ti_phy_init.h" + +int phy_ti_init(void) +{ +#ifdef CONFIG_PHY_TI_DP83867 + phy_dp83867_init(); +#endif + return 0; +} diff --git a/drivers/net/phy/ti_phy_init.h b/drivers/net/phy/ti_phy_init.h new file mode 100644 index 0000000000..6c7f6c640a --- /dev/null +++ b/drivers/net/phy/ti_phy_init.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * TI Generic Ethernet PHY + * + * Author: Dan Murphy + * + * Copyright (C) 2019-20 Texas Instruments Inc. + */ + +#ifndef _TI_GEN_PHY_H +#define _TI_GEN_PHY_H + +int phy_dp83867_init(void); + +#endif /* _TI_GEN_PHY_H */ From 8882238cc4c1276629c989ea1fe71b15358a5040 Mon Sep 17 00:00:00 2001 From: Dan Murphy Date: Mon, 4 May 2020 16:14:40 -0500 Subject: [PATCH 16/29] net: phy: Add DP8382x phy registration to TI PHY init Add the DP8382X generic PHY registration to the TI PHY init file. Acked-by: Michal Simek Signed-off-by: Dan Murphy --- drivers/net/phy/Kconfig | 7 +++ drivers/net/phy/ti_phy_init.c | 83 +++++++++++++++++++++++++++++++++++ 2 files changed, 90 insertions(+) diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig index a5a1ff257f..b0bd762ac3 100644 --- a/drivers/net/phy/Kconfig +++ b/drivers/net/phy/Kconfig @@ -252,6 +252,13 @@ config PHY_TI_DP83867 ---help--- Adds support for the TI DP83867 1Gbit PHY. +config PHY_TI_GENERIC + select PHY_TI + bool "Texas Instruments Generic Ethernet PHYs support" + ---help--- + Adds support for Generic TI PHYs that don't need special handling but + the PHY name is associated with a PHY ID. + config PHY_VITESSE bool "Vitesse Ethernet PHYs support" diff --git a/drivers/net/phy/ti_phy_init.c b/drivers/net/phy/ti_phy_init.c index 277b29a263..50eff77692 100644 --- a/drivers/net/phy/ti_phy_init.c +++ b/drivers/net/phy/ti_phy_init.c @@ -7,12 +7,95 @@ * Copyright (C) 2019-20 Texas Instruments Inc. */ +#include #include "ti_phy_init.h" +#ifdef CONFIG_PHY_TI_GENERIC +static struct phy_driver dp83822_driver = { + .name = "TI DP83822", + .uid = 0x2000a240, + .mask = 0xfffffff0, + .features = PHY_BASIC_FEATURES, + .config = &genphy_config_aneg, + .startup = &genphy_startup, + .shutdown = &genphy_shutdown, +}; + +static struct phy_driver dp83826nc_driver = { + .name = "TI DP83826NC", + .uid = 0x2000a110, + .mask = 0xfffffff0, + .features = PHY_BASIC_FEATURES, + .config = &genphy_config_aneg, + .startup = &genphy_startup, + .shutdown = &genphy_shutdown, +}; + +static struct phy_driver dp83826c_driver = { + .name = "TI DP83826C", + .uid = 0x2000a130, + .mask = 0xfffffff0, + .features = PHY_BASIC_FEATURES, + .config = &genphy_config_aneg, + .startup = &genphy_startup, + .shutdown = &genphy_shutdown, +}; + +static struct phy_driver dp83825s_driver = { + .name = "TI DP83825S", + .uid = 0x2000a140, + .mask = 0xfffffff0, + .features = PHY_BASIC_FEATURES, + .config = &genphy_config_aneg, + .startup = &genphy_startup, + .shutdown = &genphy_shutdown, +}; + +static struct phy_driver dp83825i_driver = { + .name = "TI DP83825I", + .uid = 0x2000a150, + .mask = 0xfffffff0, + .features = PHY_BASIC_FEATURES, + .config = &genphy_config_aneg, + .startup = &genphy_startup, + .shutdown = &genphy_shutdown, +}; + +static struct phy_driver dp83825m_driver = { + .name = "TI DP83825M", + .uid = 0x2000a160, + .mask = 0xfffffff0, + .features = PHY_BASIC_FEATURES, + .config = &genphy_config_aneg, + .startup = &genphy_startup, + .shutdown = &genphy_shutdown, +}; + +static struct phy_driver dp83825cs_driver = { + .name = "TI DP83825CS", + .uid = 0x2000a170, + .mask = 0xfffffff0, + .features = PHY_BASIC_FEATURES, + .config = &genphy_config_aneg, + .startup = &genphy_startup, + .shutdown = &genphy_shutdown, +}; +#endif /* CONFIG_PHY_TI_GENERIC */ + int phy_ti_init(void) { #ifdef CONFIG_PHY_TI_DP83867 phy_dp83867_init(); #endif + +#ifdef CONFIG_PHY_TI_GENERIC + phy_register(&dp83822_driver); + phy_register(&dp83825s_driver); + phy_register(&dp83825i_driver); + phy_register(&dp83825m_driver); + phy_register(&dp83825cs_driver); + phy_register(&dp83826c_driver); + phy_register(&dp83826nc_driver); +#endif return 0; } From de5468e660742c4d2c2cbfc39e106fc647570110 Mon Sep 17 00:00:00 2001 From: Ravik Hasija Date: Thu, 7 May 2020 14:55:32 -0700 Subject: [PATCH 17/29] net: tftp: fix progress marker for file transfer During packet sequence number wraparound the show_block_marker() API was not called, as a result the progress marker doesn't stay within column boundary. Use position in file instead of sequence number to align the marker. Signed-off-by: Ravik Hasija Reviewed-By: Ramon Fried --- net/tftp.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/net/tftp.c b/net/tftp.c index 180140e495..bbede9c0f2 100644 --- a/net/tftp.c +++ b/net/tftp.c @@ -233,9 +233,11 @@ static void tftp_timeout_handler(void); static void show_block_marker(void) { + ulong pos; + #ifdef CONFIG_TFTP_TSIZE if (tftp_tsize) { - ulong pos = tftp_cur_block * tftp_block_size + + pos = tftp_cur_block * tftp_block_size + tftp_block_wrap_offset; if (pos > tftp_tsize) pos = tftp_tsize; @@ -247,9 +249,11 @@ static void show_block_marker(void) } else #endif { - if (((tftp_cur_block - 1) % 10) == 0) + pos = (tftp_cur_block - 1) + + (tftp_block_wrap * TFTP_SEQUENCE_SIZE); + if ((pos % 10) == 0) putc('#'); - else if ((tftp_cur_block % (10 * HASHES_PER_LINE)) == 0) + else if (((pos + 1) % (10 * HASHES_PER_LINE)) == 0) puts("\n\t "); } } @@ -282,9 +286,8 @@ static void update_block_number(void) tftp_block_wrap++; tftp_block_wrap_offset += tftp_block_size * TFTP_SEQUENCE_SIZE; timeout_count = 0; /* we've done well, reset the timeout */ - } else { - show_block_marker(); } + show_block_marker(); } /* The TFTP get or put is complete */ @@ -518,8 +521,6 @@ static void tftp_handler(uchar *pkt, unsigned dest, struct in_addr sip, len -= 2; tftp_cur_block = ntohs(*(__be16 *)pkt); - update_block_number(); - if (tftp_state == STATE_SEND_RRQ) debug("Server did not acknowledge timeout option!\n"); @@ -545,6 +546,7 @@ static void tftp_handler(uchar *pkt, unsigned dest, struct in_addr sip, break; } + update_block_number(); tftp_prev_block = tftp_cur_block; timeout_count_max = tftp_timeout_count_max; net_set_timeout_handler(timeout_ms, tftp_timeout_handler); From 9962dd25b1e228c5c8f0b33ef89c48093ca2a311 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sat, 9 May 2020 22:34:35 +0200 Subject: [PATCH 18/29] net: rtl8139: Factor out device name assignment Pull the device name setting into a separate function, as this will be shared between DM/non-DM variants. Signed-off-by: Marek Vasut Cc: Joe Hershberger --- drivers/net/rtl8139.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/net/rtl8139.c b/drivers/net/rtl8139.c index 0daeefa489..cc7fcdfea4 100644 --- a/drivers/net/rtl8139.c +++ b/drivers/net/rtl8139.c @@ -524,6 +524,11 @@ static int rtl8139_bcast_addr(struct eth_device *dev, const u8 *bcast_mac, return 0; } +static void rtl8139_name(char *str, int card_number) +{ + sprintf(str, "RTL8139#%u", card_number); +} + static struct pci_device_id supported[] = { { PCI_VENDOR_ID_REALTEK, PCI_DEVICE_ID_REALTEK_8139 }, { PCI_VENDOR_ID_DLINK, PCI_DEVICE_ID_DLINK_8139 }, @@ -556,7 +561,7 @@ int rtl8139_initialize(bd_t *bis) } memset(dev, 0, sizeof(*dev)); - sprintf(dev->name, "RTL8139#%d", card_number); + rtl8139_name(dev->name, card_number); dev->priv = (void *)devno; dev->iobase = (int)bus_to_phys(iobase); From 1ba8d9844562c74f0d80423d5dac658291d6d2f1 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sat, 9 May 2020 22:34:36 +0200 Subject: [PATCH 19/29] net: rtl8139: Switch from malloc()+memset() to calloc() Replace malloc()+memset() combination with calloc(), no functional change. Signed-off-by: Marek Vasut Cc: Joe Hershberger --- drivers/net/rtl8139.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/net/rtl8139.c b/drivers/net/rtl8139.c index cc7fcdfea4..4874c1aa4f 100644 --- a/drivers/net/rtl8139.c +++ b/drivers/net/rtl8139.c @@ -554,12 +554,11 @@ int rtl8139_initialize(bd_t *bis) debug("rtl8139: REALTEK RTL8139 @0x%x\n", iobase); - dev = (struct eth_device *)malloc(sizeof(*dev)); + dev = calloc(1, sizeof(*dev)); if (!dev) { printf("Can not allocate memory of rtl8139\n"); break; } - memset(dev, 0, sizeof(*dev)); rtl8139_name(dev->name, card_number); From f4385539f1a6b4def6bf74091a2bc11f574d3bd1 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sat, 9 May 2020 22:34:37 +0200 Subject: [PATCH 20/29] net: rtl8139: Use dev->iobase instead of custom ioaddr Replace the use of custom static ioaddr variable with common dev->iobase, no functional change. Signed-off-by: Marek Vasut Cc: Joe Hershberger --- drivers/net/rtl8139.c | 84 ++++++++++++++++++++----------------------- 1 file changed, 38 insertions(+), 46 deletions(-) diff --git a/drivers/net/rtl8139.c b/drivers/net/rtl8139.c index 4874c1aa4f..f829e52521 100644 --- a/drivers/net/rtl8139.c +++ b/drivers/net/rtl8139.c @@ -192,7 +192,6 @@ #define RTL_STS_RXSTATUSOK BIT(0) 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); @@ -223,42 +222,43 @@ static void rtl8139_eeprom_delay(uintptr_t regbase) inl(regbase + RTL_REG_CFG9346); } -static int rtl8139_read_eeprom(unsigned int location, unsigned int addr_len) +static int rtl8139_read_eeprom(struct eth_device *dev, + unsigned int location, unsigned int addr_len) { unsigned int read_cmd = location | (EE_READ_CMD << addr_len); - uintptr_t ee_addr = ioaddr + RTL_REG_CFG9346; + uintptr_t ee_addr = dev->iobase + RTL_REG_CFG9346; unsigned int retval = 0; u8 dataval; int i; outb(EE_ENB & ~EE_CS, ee_addr); outb(EE_ENB, ee_addr); - rtl8139_eeprom_delay(ioaddr); + rtl8139_eeprom_delay(dev->iobase); /* Shift the read command bits out. */ for (i = 4 + addr_len; i >= 0; i--) { dataval = (read_cmd & BIT(i)) ? EE_DATA_WRITE : 0; outb(EE_ENB | dataval, ee_addr); - rtl8139_eeprom_delay(ioaddr); + rtl8139_eeprom_delay(dev->iobase); outb(EE_ENB | dataval | EE_SHIFT_CLK, ee_addr); - rtl8139_eeprom_delay(ioaddr); + rtl8139_eeprom_delay(dev->iobase); } outb(EE_ENB, ee_addr); - rtl8139_eeprom_delay(ioaddr); + rtl8139_eeprom_delay(dev->iobase); for (i = 16; i > 0; i--) { outb(EE_ENB | EE_SHIFT_CLK, ee_addr); - rtl8139_eeprom_delay(ioaddr); + rtl8139_eeprom_delay(dev->iobase); retval <<= 1; retval |= inb(ee_addr) & EE_DATA_READ; outb(EE_ENB, ee_addr); - rtl8139_eeprom_delay(ioaddr); + rtl8139_eeprom_delay(dev->iobase); } /* Terminate the EEPROM access. */ outb(~EE_CS, ee_addr); - rtl8139_eeprom_delay(ioaddr); + rtl8139_eeprom_delay(dev->iobase); return retval; } @@ -275,10 +275,10 @@ static void rtl8139_set_rx_mode(struct eth_device *dev) RTL_REG_RXCONFIG_ACCEPTMULTICAST | RTL_REG_RXCONFIG_ACCEPTMYPHYS; - outl(rtl8139_rx_config | rx_mode, ioaddr + RTL_REG_RXCONFIG); + outl(rtl8139_rx_config | rx_mode, dev->iobase + RTL_REG_RXCONFIG); - outl(0xffffffff, ioaddr + RTL_REG_MAR0 + 0); - outl(0xffffffff, ioaddr + RTL_REG_MAR0 + 4); + outl(0xffffffff, dev->iobase + RTL_REG_MAR0 + 0); + outl(0xffffffff, dev->iobase + RTL_REG_MAR0 + 4); } static void rtl8139_hw_reset(struct eth_device *dev) @@ -286,11 +286,11 @@ static void rtl8139_hw_reset(struct eth_device *dev) u8 reg; int i; - outb(RTL_REG_CHIPCMD_CMDRESET, ioaddr + RTL_REG_CHIPCMD); + outb(RTL_REG_CHIPCMD_CMDRESET, dev->iobase + RTL_REG_CHIPCMD); /* Give the chip 10ms to finish the reset. */ for (i = 0; i < 100; i++) { - reg = inb(ioaddr + RTL_REG_CHIPCMD); + reg = inb(dev->iobase + RTL_REG_CHIPCMD); if (!(reg & RTL_REG_CHIPCMD_CMDRESET)) break; @@ -308,15 +308,15 @@ static void rtl8139_reset(struct eth_device *dev) rtl8139_hw_reset(dev); for (i = 0; i < ETH_ALEN; i++) - outb(dev->enetaddr[i], ioaddr + RTL_REG_MAC0 + i); + outb(dev->enetaddr[i], dev->iobase + RTL_REG_MAC0 + i); /* Must enable Tx/Rx before setting transfer thresholds! */ outb(RTL_REG_CHIPCMD_CMDRXENB | RTL_REG_CHIPCMD_CMDTXENB, - ioaddr + RTL_REG_CHIPCMD); + dev->iobase + 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); + outl(rtl8139_rx_config, dev->iobase + RTL_REG_RXCONFIG); + outl((TX_DMA_BURST << 8) | 0x03000000, dev->iobase + RTL_REG_TXCONFIG); /* * The Linux driver changes RTL_REG_CONFIG1 here to use a different @@ -331,7 +331,7 @@ static void rtl8139_reset(struct eth_device *dev) 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); + outl(phys_to_bus((int)rx_ring), dev->iobase + RTL_REG_RXBUF); /* * If we add multicast support, the RTL_REG_MAR0 register would have @@ -340,17 +340,17 @@ static void rtl8139_reset(struct eth_device *dev) * unicast. */ outb(RTL_REG_CHIPCMD_CMDRXENB | RTL_REG_CHIPCMD_CMDTXENB, - ioaddr + RTL_REG_CHIPCMD); + dev->iobase + RTL_REG_CHIPCMD); - outl(rtl8139_rx_config, ioaddr + RTL_REG_RXCONFIG); + outl(rtl8139_rx_config, dev->iobase + RTL_REG_RXCONFIG); /* Start the chip's Tx and Rx process. */ - outl(0, ioaddr + RTL_REG_RXMISSED); + outl(0, dev->iobase + RTL_REG_RXMISSED); rtl8139_set_rx_mode(dev); /* Disable all known interrupts by setting the interrupt mask. */ - outw(0, ioaddr + RTL_REG_INTRMASK); + outw(0, dev->iobase + RTL_REG_INTRMASK); } static int rtl8139_send(struct eth_device *dev, void *packet, int length) @@ -360,8 +360,6 @@ static int rtl8139_send(struct eth_device *dev, void *packet, int length) unsigned int status; int i = 0; - ioaddr = dev->iobase; - memcpy(tx_buffer, packet, length); debug_cond(DEBUG_TX, "sending %d bytes\n", len); @@ -375,12 +373,12 @@ static int rtl8139_send(struct eth_device *dev, void *packet, int length) flush_cache((unsigned long)tx_buffer, length); outl(phys_to_bus((unsigned long)tx_buffer), - ioaddr + RTL_REG_TXADDR0 + cur_tx * 4); + dev->iobase + RTL_REG_TXADDR0 + cur_tx * 4); outl(((TX_FIFO_THRESH << 11) & 0x003f0000) | len, - ioaddr + RTL_REG_TXSTATUS0 + cur_tx * 4); + dev->iobase + RTL_REG_TXSTATUS0 + cur_tx * 4); do { - status = inw(ioaddr + RTL_REG_INTRSTATUS); + status = inw(dev->iobase + RTL_REG_INTRSTATUS); /* * Only acknlowledge interrupt sources we can properly * handle here - the RTL_REG_INTRSTATUS_RXOVERFLOW/ @@ -389,14 +387,14 @@ static int rtl8139_send(struct eth_device *dev, void *packet, int length) */ status &= RTL_REG_INTRSTATUS_TXOK | RTL_REG_INTRSTATUS_TXERR | RTL_REG_INTRSTATUS_PCIERR; - outw(status, ioaddr + RTL_REG_INTRSTATUS); + outw(status, dev->iobase + RTL_REG_INTRSTATUS); if (status) break; udelay(10); } while (i++ < RTL_TIMEOUT); - txstatus = inl(ioaddr + RTL_REG_TXSTATUS0 + cur_tx * 4); + txstatus = inl(dev->iobase + RTL_REG_TXSTATUS0 + cur_tx * 4); if (!(status & RTL_REG_INTRSTATUS_TXOK)) { debug_cond(DEBUG_TX, @@ -426,14 +424,12 @@ static int rtl8139_recv(struct eth_device *dev) unsigned int status; int length = 0; - ioaddr = dev->iobase; - - if (inb(ioaddr + RTL_REG_CHIPCMD) & RTL_REG_CHIPCMD_RXBUFEMPTY) + if (inb(dev->iobase + RTL_REG_CHIPCMD) & RTL_REG_CHIPCMD_RXBUFEMPTY) return 0; - status = inw(ioaddr + RTL_REG_INTRSTATUS); + status = inw(dev->iobase + RTL_REG_INTRSTATUS); /* See below for the rest of the interrupt acknowledges. */ - outw(status & ~rxstat, ioaddr + RTL_REG_INTRSTATUS); + outw(status & ~rxstat, dev->iobase + RTL_REG_INTRSTATUS); debug_cond(DEBUG_RX, "%s: int %hX ", __func__, status); @@ -474,13 +470,13 @@ static int rtl8139_recv(struct eth_device *dev) flush_cache((unsigned long)rx_ring, RX_BUF_LEN); cur_rx = ROUND(cur_rx + rx_size + 4, 4); - outw(cur_rx - 16, ioaddr + RTL_REG_RXBUFPTR); + outw(cur_rx - 16, dev->iobase + 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 & rxstat, ioaddr + RTL_REG_INTRSTATUS); + outw(status & rxstat, dev->iobase + RTL_REG_INTRSTATUS); return length; } @@ -491,18 +487,16 @@ static int rtl8139_init(struct eth_device *dev, bd_t *bis) int addr_len, i; u8 reg; - ioaddr = dev->iobase; - /* Bring the chip out of low-power mode. */ - outb(0x00, ioaddr + RTL_REG_CONFIG1); + outb(0x00, dev->iobase + RTL_REG_CONFIG1); - addr_len = rtl8139_read_eeprom(0, 8) == 0x8129 ? 8 : 6; + addr_len = rtl8139_read_eeprom(dev, 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(dev, i + 7, addr_len)); rtl8139_reset(dev); - reg = inb(ioaddr + RTL_REG_MEDIASTATUS); + reg = inb(dev->iobase + RTL_REG_MEDIASTATUS); if (reg & RTL_REG_MEDIASTATUS_MSRLINKFAIL) { printf("Cable not connected or other link failure\n"); return -1; @@ -513,8 +507,6 @@ static int rtl8139_init(struct eth_device *dev, bd_t *bis) static void rtl8139_stop(struct eth_device *dev) { - ioaddr = dev->iobase; - rtl8139_hw_reset(dev); } From 8ff1d4a9c8e629253e43d9d04eccbfa773f81e83 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sat, 9 May 2020 22:34:38 +0200 Subject: [PATCH 21/29] net: rtl8139: Clean up bus_to_phys()/phys_to_bus() macros These macros depended on the dev variable being declared wherever they were used. This is wrong and will not work with DM anyway, so pass only the PCI BFD into these macros, which fixes the dependency and prepares them for DM support as well. Signed-off-by: Marek Vasut Cc: Joe Hershberger --- drivers/net/rtl8139.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/net/rtl8139.c b/drivers/net/rtl8139.c index f829e52521..aa13740542 100644 --- a/drivers/net/rtl8139.c +++ b/drivers/net/rtl8139.c @@ -96,8 +96,8 @@ #define DEBUG_TX 0 /* set to 1 to enable debug code */ #define DEBUG_RX 0 /* set to 1 to enable debug code */ -#define bus_to_phys(a) pci_mem_to_phys((pci_dev_t)dev->priv, a) -#define phys_to_bus(a) pci_phys_to_mem((pci_dev_t)dev->priv, a) +#define bus_to_phys(devno, a) pci_mem_to_phys((pci_dev_t)(devno), (a)) +#define phys_to_bus(devno, a) pci_phys_to_mem((pci_dev_t)(devno), (a)) /* Symbolic offsets to registers. */ /* Ethernet hardware address. */ @@ -331,7 +331,7 @@ static void rtl8139_reset(struct eth_device *dev) 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), dev->iobase + RTL_REG_RXBUF); + outl(phys_to_bus(dev->priv, (int)rx_ring), dev->iobase + RTL_REG_RXBUF); /* * If we add multicast support, the RTL_REG_MAR0 register would have @@ -372,7 +372,7 @@ static int rtl8139_send(struct eth_device *dev, void *packet, int length) tx_buffer[len++] = '\0'; flush_cache((unsigned long)tx_buffer, length); - outl(phys_to_bus((unsigned long)tx_buffer), + outl(phys_to_bus(dev->priv, (unsigned long)tx_buffer), dev->iobase + RTL_REG_TXADDR0 + cur_tx * 4); outl(((TX_FIFO_THRESH << 11) & 0x003f0000) | len, dev->iobase + RTL_REG_TXSTATUS0 + cur_tx * 4); @@ -555,7 +555,7 @@ int rtl8139_initialize(bd_t *bis) rtl8139_name(dev->name, card_number); dev->priv = (void *)devno; - dev->iobase = (int)bus_to_phys(iobase); + dev->iobase = (unsigned long)bus_to_phys(devno, iobase); dev->init = rtl8139_init; dev->halt = rtl8139_stop; dev->send = rtl8139_send; From 3feb6f7ff6856e1e903e5a62f6252d37731b6592 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sat, 9 May 2020 22:34:39 +0200 Subject: [PATCH 22/29] net: rtl8139: Introduce device private data Introduce rtl8139_pdata, which is a super-structure around eth_device and tracks per-device state, here the device IO address, PCI BDF, RX and TX ring position. Pass this structure around instead of the old non-DM eth_device in preparation for DM conversion. Signed-off-by: Marek Vasut Cc: Joe Hershberger --- drivers/net/rtl8139.c | 136 ++++++++++++++++++++++++------------------ 1 file changed, 78 insertions(+), 58 deletions(-) diff --git a/drivers/net/rtl8139.c b/drivers/net/rtl8139.c index aa13740542..dff77de06e 100644 --- a/drivers/net/rtl8139.c +++ b/drivers/net/rtl8139.c @@ -191,7 +191,14 @@ #define RTL_STS_RXBADALIGN BIT(1) #define RTL_STS_RXSTATUSOK BIT(0) -static unsigned int cur_rx, cur_tx; +struct rtl8139_priv { + struct eth_device dev; + unsigned int cur_rx; + unsigned int cur_tx; + unsigned long ioaddr; + pci_dev_t devno; + unsigned char enetaddr[6]; +}; /* The RTL8139 can only transmit from a contiguous, aligned memory block. */ static unsigned char tx_buffer[TX_BUF_SIZE] __aligned(4); @@ -222,43 +229,43 @@ static void rtl8139_eeprom_delay(uintptr_t regbase) inl(regbase + RTL_REG_CFG9346); } -static int rtl8139_read_eeprom(struct eth_device *dev, +static int rtl8139_read_eeprom(struct rtl8139_priv *priv, unsigned int location, unsigned int addr_len) { unsigned int read_cmd = location | (EE_READ_CMD << addr_len); - uintptr_t ee_addr = dev->iobase + RTL_REG_CFG9346; + uintptr_t ee_addr = priv->ioaddr + RTL_REG_CFG9346; unsigned int retval = 0; u8 dataval; int i; outb(EE_ENB & ~EE_CS, ee_addr); outb(EE_ENB, ee_addr); - rtl8139_eeprom_delay(dev->iobase); + rtl8139_eeprom_delay(priv->ioaddr); /* Shift the read command bits out. */ for (i = 4 + addr_len; i >= 0; i--) { dataval = (read_cmd & BIT(i)) ? EE_DATA_WRITE : 0; outb(EE_ENB | dataval, ee_addr); - rtl8139_eeprom_delay(dev->iobase); + rtl8139_eeprom_delay(priv->ioaddr); outb(EE_ENB | dataval | EE_SHIFT_CLK, ee_addr); - rtl8139_eeprom_delay(dev->iobase); + rtl8139_eeprom_delay(priv->ioaddr); } outb(EE_ENB, ee_addr); - rtl8139_eeprom_delay(dev->iobase); + rtl8139_eeprom_delay(priv->ioaddr); for (i = 16; i > 0; i--) { outb(EE_ENB | EE_SHIFT_CLK, ee_addr); - rtl8139_eeprom_delay(dev->iobase); + rtl8139_eeprom_delay(priv->ioaddr); retval <<= 1; retval |= inb(ee_addr) & EE_DATA_READ; outb(EE_ENB, ee_addr); - rtl8139_eeprom_delay(dev->iobase); + rtl8139_eeprom_delay(priv->ioaddr); } /* Terminate the EEPROM access. */ outb(~EE_CS, ee_addr); - rtl8139_eeprom_delay(dev->iobase); + rtl8139_eeprom_delay(priv->ioaddr); return retval; } @@ -268,29 +275,29 @@ static const unsigned int rtl8139_rx_config = (RX_FIFO_THRESH << 13) | (RX_DMA_BURST << 8); -static void rtl8139_set_rx_mode(struct eth_device *dev) +static void rtl8139_set_rx_mode(struct rtl8139_priv *priv) { /* !IFF_PROMISC */ unsigned int rx_mode = RTL_REG_RXCONFIG_ACCEPTBROADCAST | RTL_REG_RXCONFIG_ACCEPTMULTICAST | RTL_REG_RXCONFIG_ACCEPTMYPHYS; - outl(rtl8139_rx_config | rx_mode, dev->iobase + RTL_REG_RXCONFIG); + outl(rtl8139_rx_config | rx_mode, priv->ioaddr + RTL_REG_RXCONFIG); - outl(0xffffffff, dev->iobase + RTL_REG_MAR0 + 0); - outl(0xffffffff, dev->iobase + RTL_REG_MAR0 + 4); + outl(0xffffffff, priv->ioaddr + RTL_REG_MAR0 + 0); + outl(0xffffffff, priv->ioaddr + RTL_REG_MAR0 + 4); } -static void rtl8139_hw_reset(struct eth_device *dev) +static void rtl8139_hw_reset(struct rtl8139_priv *priv) { u8 reg; int i; - outb(RTL_REG_CHIPCMD_CMDRESET, dev->iobase + RTL_REG_CHIPCMD); + outb(RTL_REG_CHIPCMD_CMDRESET, priv->ioaddr + RTL_REG_CHIPCMD); /* Give the chip 10ms to finish the reset. */ for (i = 0; i < 100; i++) { - reg = inb(dev->iobase + RTL_REG_CHIPCMD); + reg = inb(priv->ioaddr + RTL_REG_CHIPCMD); if (!(reg & RTL_REG_CHIPCMD_CMDRESET)) break; @@ -298,25 +305,25 @@ static void rtl8139_hw_reset(struct eth_device *dev) } } -static void rtl8139_reset(struct eth_device *dev) +static void rtl8139_reset(struct rtl8139_priv *priv) { int i; - cur_rx = 0; - cur_tx = 0; + priv->cur_rx = 0; + priv->cur_tx = 0; - rtl8139_hw_reset(dev); + rtl8139_hw_reset(priv); for (i = 0; i < ETH_ALEN; i++) - outb(dev->enetaddr[i], dev->iobase + RTL_REG_MAC0 + i); + outb(priv->enetaddr[i], priv->ioaddr + RTL_REG_MAC0 + i); /* Must enable Tx/Rx before setting transfer thresholds! */ outb(RTL_REG_CHIPCMD_CMDRXENB | RTL_REG_CHIPCMD_CMDTXENB, - dev->iobase + RTL_REG_CHIPCMD); + priv->ioaddr + RTL_REG_CHIPCMD); /* accept no frames yet! */ - outl(rtl8139_rx_config, dev->iobase + RTL_REG_RXCONFIG); - outl((TX_DMA_BURST << 8) | 0x03000000, dev->iobase + RTL_REG_TXCONFIG); + outl(rtl8139_rx_config, priv->ioaddr + RTL_REG_RXCONFIG); + outl((TX_DMA_BURST << 8) | 0x03000000, priv->ioaddr + RTL_REG_TXCONFIG); /* * The Linux driver changes RTL_REG_CONFIG1 here to use a different @@ -331,7 +338,7 @@ static void rtl8139_reset(struct eth_device *dev) 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(dev->priv, (int)rx_ring), dev->iobase + RTL_REG_RXBUF); + outl(phys_to_bus(priv->devno, (int)rx_ring), priv->ioaddr + RTL_REG_RXBUF); /* * If we add multicast support, the RTL_REG_MAR0 register would have @@ -340,21 +347,22 @@ static void rtl8139_reset(struct eth_device *dev) * unicast. */ outb(RTL_REG_CHIPCMD_CMDRXENB | RTL_REG_CHIPCMD_CMDTXENB, - dev->iobase + RTL_REG_CHIPCMD); + priv->ioaddr + RTL_REG_CHIPCMD); - outl(rtl8139_rx_config, dev->iobase + RTL_REG_RXCONFIG); + outl(rtl8139_rx_config, priv->ioaddr + RTL_REG_RXCONFIG); /* Start the chip's Tx and Rx process. */ - outl(0, dev->iobase + RTL_REG_RXMISSED); + outl(0, priv->ioaddr + RTL_REG_RXMISSED); - rtl8139_set_rx_mode(dev); + rtl8139_set_rx_mode(priv); /* Disable all known interrupts by setting the interrupt mask. */ - outw(0, dev->iobase + RTL_REG_INTRMASK); + outw(0, priv->ioaddr + RTL_REG_INTRMASK); } static int rtl8139_send(struct eth_device *dev, void *packet, int length) { + struct rtl8139_priv *priv = container_of(dev, struct rtl8139_priv, dev); unsigned int len = length; unsigned long txstatus; unsigned int status; @@ -372,13 +380,13 @@ static int rtl8139_send(struct eth_device *dev, void *packet, int length) tx_buffer[len++] = '\0'; flush_cache((unsigned long)tx_buffer, length); - outl(phys_to_bus(dev->priv, (unsigned long)tx_buffer), - dev->iobase + RTL_REG_TXADDR0 + cur_tx * 4); + outl(phys_to_bus(priv->devno, (unsigned long)tx_buffer), + priv->ioaddr + RTL_REG_TXADDR0 + priv->cur_tx * 4); outl(((TX_FIFO_THRESH << 11) & 0x003f0000) | len, - dev->iobase + RTL_REG_TXSTATUS0 + cur_tx * 4); + priv->ioaddr + RTL_REG_TXSTATUS0 + priv->cur_tx * 4); do { - status = inw(dev->iobase + RTL_REG_INTRSTATUS); + status = inw(priv->ioaddr + RTL_REG_INTRSTATUS); /* * Only acknlowledge interrupt sources we can properly * handle here - the RTL_REG_INTRSTATUS_RXOVERFLOW/ @@ -387,26 +395,26 @@ static int rtl8139_send(struct eth_device *dev, void *packet, int length) */ status &= RTL_REG_INTRSTATUS_TXOK | RTL_REG_INTRSTATUS_TXERR | RTL_REG_INTRSTATUS_PCIERR; - outw(status, dev->iobase + RTL_REG_INTRSTATUS); + outw(status, priv->ioaddr + RTL_REG_INTRSTATUS); if (status) break; udelay(10); } while (i++ < RTL_TIMEOUT); - txstatus = inl(dev->iobase + RTL_REG_TXSTATUS0 + cur_tx * 4); + txstatus = inl(priv->ioaddr + RTL_REG_TXSTATUS0 + priv->cur_tx * 4); if (!(status & RTL_REG_INTRSTATUS_TXOK)) { debug_cond(DEBUG_TX, "tx timeout/error (%d usecs), status %hX txstatus %lX\n", 10 * i, status, txstatus); - rtl8139_reset(dev); + rtl8139_reset(priv); return 0; } - cur_tx = (cur_tx + 1) % NUM_TX_DESC; + priv->cur_tx = (priv->cur_tx + 1) % NUM_TX_DESC; debug_cond(DEBUG_TX, "tx done, status %hX txstatus %lX\n", status, txstatus); @@ -416,6 +424,7 @@ static int rtl8139_send(struct eth_device *dev, void *packet, int length) static int rtl8139_recv(struct eth_device *dev) { + struct rtl8139_priv *priv = container_of(dev, struct rtl8139_priv, dev); const unsigned int rxstat = RTL_REG_INTRSTATUS_RXFIFOOVER | RTL_REG_INTRSTATUS_RXOVERFLOW | RTL_REG_INTRSTATUS_RXOK; @@ -424,16 +433,16 @@ static int rtl8139_recv(struct eth_device *dev) unsigned int status; int length = 0; - if (inb(dev->iobase + RTL_REG_CHIPCMD) & RTL_REG_CHIPCMD_RXBUFEMPTY) + if (inb(priv->ioaddr + RTL_REG_CHIPCMD) & RTL_REG_CHIPCMD_RXBUFEMPTY) return 0; - status = inw(dev->iobase + RTL_REG_INTRSTATUS); + status = inw(priv->ioaddr + RTL_REG_INTRSTATUS); /* See below for the rest of the interrupt acknowledges. */ - outw(status & ~rxstat, dev->iobase + RTL_REG_INTRSTATUS); + outw(status & ~rxstat, priv->ioaddr + RTL_REG_INTRSTATUS); debug_cond(DEBUG_RX, "%s: int %hX ", __func__, status); - ring_offs = cur_rx % RX_BUF_LEN; + ring_offs = priv->cur_rx % RX_BUF_LEN; /* ring_offs is guaranteed being 4-byte aligned */ rx_status = le32_to_cpu(*(unsigned int *)(rx_ring + ring_offs)); rx_size = rx_status >> 16; @@ -446,7 +455,7 @@ static int rtl8139_recv(struct eth_device *dev) (rx_size > ETH_FRAME_LEN + 4)) { printf("rx error %hX\n", rx_status); /* this clears all interrupts still pending */ - rtl8139_reset(dev); + rtl8139_reset(priv); return 0; } @@ -469,45 +478,51 @@ static int rtl8139_recv(struct eth_device *dev) } flush_cache((unsigned long)rx_ring, RX_BUF_LEN); - cur_rx = ROUND(cur_rx + rx_size + 4, 4); - outw(cur_rx - 16, dev->iobase + RTL_REG_RXBUFPTR); + priv->cur_rx = ROUND(priv->cur_rx + rx_size + 4, 4); + outw(priv->cur_rx - 16, priv->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 & rxstat, dev->iobase + RTL_REG_INTRSTATUS); + outw(status & rxstat, priv->ioaddr + RTL_REG_INTRSTATUS); return length; } static int rtl8139_init(struct eth_device *dev, bd_t *bis) { - unsigned short *ap = (unsigned short *)dev->enetaddr; + struct rtl8139_priv *priv = container_of(dev, struct rtl8139_priv, dev); + unsigned short *ap = (unsigned short *)priv->enetaddr; int addr_len, i; u8 reg; /* Bring the chip out of low-power mode. */ - outb(0x00, dev->iobase + RTL_REG_CONFIG1); + outb(0x00, priv->ioaddr + RTL_REG_CONFIG1); - addr_len = rtl8139_read_eeprom(dev, 0, 8) == 0x8129 ? 8 : 6; + addr_len = rtl8139_read_eeprom(priv, 0, 8) == 0x8129 ? 8 : 6; for (i = 0; i < 3; i++) - *ap++ = le16_to_cpu(rtl8139_read_eeprom(dev, i + 7, addr_len)); + *ap++ = le16_to_cpu(rtl8139_read_eeprom(priv, i + 7, addr_len)); - rtl8139_reset(dev); + rtl8139_reset(priv); - reg = inb(dev->iobase + RTL_REG_MEDIASTATUS); + reg = inb(priv->ioaddr + RTL_REG_MEDIASTATUS); if (reg & RTL_REG_MEDIASTATUS_MSRLINKFAIL) { printf("Cable not connected or other link failure\n"); return -1; } + /* Non-DM compatibility */ + memcpy(priv->dev.enetaddr, priv->enetaddr, 6); + return 0; } static void rtl8139_stop(struct eth_device *dev) { - rtl8139_hw_reset(dev); + struct rtl8139_priv *priv = container_of(dev, struct rtl8139_priv, dev); + + rtl8139_hw_reset(priv); } static int rtl8139_bcast_addr(struct eth_device *dev, const u8 *bcast_mac, @@ -529,6 +544,7 @@ static struct pci_device_id supported[] = { int rtl8139_initialize(bd_t *bis) { + struct rtl8139_priv *priv; struct eth_device *dev; int card_number = 0; pci_dev_t devno; @@ -546,16 +562,20 @@ int rtl8139_initialize(bd_t *bis) debug("rtl8139: REALTEK RTL8139 @0x%x\n", iobase); - dev = calloc(1, sizeof(*dev)); - if (!dev) { + priv = calloc(1, sizeof(*priv)); + if (!priv) { printf("Can not allocate memory of rtl8139\n"); break; } + priv->devno = devno; + priv->ioaddr = (unsigned long)bus_to_phys(devno, iobase); + + dev = &priv->dev; + rtl8139_name(dev->name, card_number); - dev->priv = (void *)devno; - dev->iobase = (unsigned long)bus_to_phys(devno, iobase); + dev->iobase = priv->ioaddr; /* Non-DM compatibility */ dev->init = rtl8139_init; dev->halt = rtl8139_stop; dev->send = rtl8139_send; From 26f59c28bdea91617b3acfd132d5affc55e1ef4a Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sat, 9 May 2020 22:34:40 +0200 Subject: [PATCH 23/29] net: rtl8139: Pass private data into rtl8139_eeprom_delay() Instead of always calling rtl8139_eeprom_delay() with priv->ioaddr, call it with priv and let the function access priv->ioaddr. This reduces code duplication and has no impact, since the compiler will inline this as needed anyway. Signed-off-by: Marek Vasut Cc: Joe Hershberger --- drivers/net/rtl8139.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/net/rtl8139.c b/drivers/net/rtl8139.c index dff77de06e..ae5d1251ae 100644 --- a/drivers/net/rtl8139.c +++ b/drivers/net/rtl8139.c @@ -220,13 +220,13 @@ static unsigned char rx_ring[RX_BUF_LEN + 16] __aligned(4); #define EE_READ_CMD 6 #define EE_ERASE_CMD 7 -static void rtl8139_eeprom_delay(uintptr_t regbase) +static void rtl8139_eeprom_delay(struct rtl8139_priv *priv) { /* * Delay between EEPROM clock transitions. * No extra delay is needed with 33MHz PCI, but 66MHz may change this. */ - inl(regbase + RTL_REG_CFG9346); + inl(priv->ioaddr + RTL_REG_CFG9346); } static int rtl8139_read_eeprom(struct rtl8139_priv *priv, @@ -240,32 +240,32 @@ static int rtl8139_read_eeprom(struct rtl8139_priv *priv, outb(EE_ENB & ~EE_CS, ee_addr); outb(EE_ENB, ee_addr); - rtl8139_eeprom_delay(priv->ioaddr); + rtl8139_eeprom_delay(priv); /* Shift the read command bits out. */ for (i = 4 + addr_len; i >= 0; i--) { dataval = (read_cmd & BIT(i)) ? EE_DATA_WRITE : 0; outb(EE_ENB | dataval, ee_addr); - rtl8139_eeprom_delay(priv->ioaddr); + rtl8139_eeprom_delay(priv); outb(EE_ENB | dataval | EE_SHIFT_CLK, ee_addr); - rtl8139_eeprom_delay(priv->ioaddr); + rtl8139_eeprom_delay(priv); } outb(EE_ENB, ee_addr); - rtl8139_eeprom_delay(priv->ioaddr); + rtl8139_eeprom_delay(priv); for (i = 16; i > 0; i--) { outb(EE_ENB | EE_SHIFT_CLK, ee_addr); - rtl8139_eeprom_delay(priv->ioaddr); + rtl8139_eeprom_delay(priv); retval <<= 1; retval |= inb(ee_addr) & EE_DATA_READ; outb(EE_ENB, ee_addr); - rtl8139_eeprom_delay(priv->ioaddr); + rtl8139_eeprom_delay(priv); } /* Terminate the EEPROM access. */ outb(~EE_CS, ee_addr); - rtl8139_eeprom_delay(priv->ioaddr); + rtl8139_eeprom_delay(priv); return retval; } From 6a4a5c194df8af25390f4ba30250a76fc0256643 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sat, 9 May 2020 22:34:41 +0200 Subject: [PATCH 24/29] net: rtl8139: Split out common and non-DM functions Split the driver into common and non-DM functionality, so that the DM support can later re-use the common code, while we retain the non-DM code until all the platforms are converted. Signed-off-by: Marek Vasut Cc: Joe Hershberger --- drivers/net/rtl8139.c | 92 ++++++++++++++++++++++++++++++++----------- 1 file changed, 68 insertions(+), 24 deletions(-) diff --git a/drivers/net/rtl8139.c b/drivers/net/rtl8139.c index ae5d1251ae..70b09fb2d2 100644 --- a/drivers/net/rtl8139.c +++ b/drivers/net/rtl8139.c @@ -193,6 +193,7 @@ struct rtl8139_priv { struct eth_device dev; + unsigned int rxstatus; unsigned int cur_rx; unsigned int cur_tx; unsigned long ioaddr; @@ -360,9 +361,9 @@ static void rtl8139_reset(struct rtl8139_priv *priv) outw(0, priv->ioaddr + RTL_REG_INTRMASK); } -static int rtl8139_send(struct eth_device *dev, void *packet, int length) +static int rtl8139_send_common(struct rtl8139_priv *priv, + void *packet, int length) { - struct rtl8139_priv *priv = container_of(dev, struct rtl8139_priv, dev); unsigned int len = length; unsigned long txstatus; unsigned int status; @@ -422,25 +423,24 @@ static int rtl8139_send(struct eth_device *dev, void *packet, int length) return length; } -static int rtl8139_recv(struct eth_device *dev) +static int rtl8139_recv_common(struct rtl8139_priv *priv, unsigned char *rxdata, + uchar **packetp) { - struct rtl8139_priv *priv = container_of(dev, struct rtl8139_priv, dev); const unsigned int rxstat = RTL_REG_INTRSTATUS_RXFIFOOVER | RTL_REG_INTRSTATUS_RXOVERFLOW | RTL_REG_INTRSTATUS_RXOK; unsigned int rx_size, rx_status; unsigned int ring_offs; - unsigned int status; int length = 0; if (inb(priv->ioaddr + RTL_REG_CHIPCMD) & RTL_REG_CHIPCMD_RXBUFEMPTY) return 0; - status = inw(priv->ioaddr + RTL_REG_INTRSTATUS); + priv->rxstatus = inw(priv->ioaddr + RTL_REG_INTRSTATUS); /* See below for the rest of the interrupt acknowledges. */ - outw(status & ~rxstat, priv->ioaddr + RTL_REG_INTRSTATUS); + outw(priv->rxstatus & ~rxstat, priv->ioaddr + RTL_REG_INTRSTATUS); - debug_cond(DEBUG_RX, "%s: int %hX ", __func__, status); + debug_cond(DEBUG_RX, "%s: int %hX ", __func__, priv->rxstatus); ring_offs = priv->cur_rx % RX_BUF_LEN; /* ring_offs is guaranteed being 4-byte aligned */ @@ -462,20 +462,30 @@ static int rtl8139_recv(struct eth_device *dev) /* Received a good packet */ length = rx_size - 4; /* no one cares about the FCS */ 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); - net_process_received_packet(rxdata, length); + *packetp = rxdata; debug_cond(DEBUG_RX, "rx packet %d+%d bytes", semi_count, rx_size - 4 - semi_count); } else { - net_process_received_packet(rx_ring + ring_offs + 4, length); + *packetp = rx_ring + ring_offs + 4; debug_cond(DEBUG_RX, "rx packet %d bytes", rx_size - 4); } + + return length; +} + +static int rtl8139_free_pkt_common(struct rtl8139_priv *priv, unsigned int len) +{ + const unsigned int rxstat = RTL_REG_INTRSTATUS_RXFIFOOVER | + RTL_REG_INTRSTATUS_RXOVERFLOW | + RTL_REG_INTRSTATUS_RXOK; + unsigned int rx_size = len + 4; + flush_cache((unsigned long)rx_ring, RX_BUF_LEN); priv->cur_rx = ROUND(priv->cur_rx + rx_size + 4, 4); @@ -485,14 +495,13 @@ static int rtl8139_recv(struct eth_device *dev) * Rx overflow situations. The document itself contains basically * no usable information, except for a few exception handling rules. */ - outw(status & rxstat, priv->ioaddr + RTL_REG_INTRSTATUS); + outw(priv->rxstatus & rxstat, priv->ioaddr + RTL_REG_INTRSTATUS); - return length; + return 0; } -static int rtl8139_init(struct eth_device *dev, bd_t *bis) +static int rtl8139_init_common(struct rtl8139_priv *priv) { - struct rtl8139_priv *priv = container_of(dev, struct rtl8139_priv, dev); unsigned short *ap = (unsigned short *)priv->enetaddr; int addr_len, i; u8 reg; @@ -518,19 +527,11 @@ static int rtl8139_init(struct eth_device *dev, bd_t *bis) return 0; } -static void rtl8139_stop(struct eth_device *dev) +static void rtl8139_stop_common(struct rtl8139_priv *priv) { - struct rtl8139_priv *priv = container_of(dev, struct rtl8139_priv, dev); - rtl8139_hw_reset(priv); } -static int rtl8139_bcast_addr(struct eth_device *dev, const u8 *bcast_mac, - int join) -{ - return 0; -} - static void rtl8139_name(char *str, int card_number) { sprintf(str, "RTL8139#%u", card_number); @@ -542,6 +543,49 @@ static struct pci_device_id supported[] = { { } }; +static int rtl8139_bcast_addr(struct eth_device *dev, const u8 *bcast_mac, + int join) +{ + return 0; +} + +static int rtl8139_init(struct eth_device *dev, bd_t *bis) +{ + struct rtl8139_priv *priv = container_of(dev, struct rtl8139_priv, dev); + + return rtl8139_init_common(priv); +} + +static void rtl8139_stop(struct eth_device *dev) +{ + struct rtl8139_priv *priv = container_of(dev, struct rtl8139_priv, dev); + + return rtl8139_stop_common(priv); +} + +static int rtl8139_send(struct eth_device *dev, void *packet, int length) +{ + struct rtl8139_priv *priv = container_of(dev, struct rtl8139_priv, dev); + + return rtl8139_send_common(priv, packet, length); +} + +static int rtl8139_recv(struct eth_device *dev) +{ + struct rtl8139_priv *priv = container_of(dev, struct rtl8139_priv, dev); + unsigned char rxdata[RX_BUF_LEN]; + uchar *packet; + int ret; + + ret = rtl8139_recv_common(priv, rxdata, &packet); + if (ret) { + net_process_received_packet(packet, ret); + rtl8139_free_pkt_common(priv, ret); + } + + return ret; +} + int rtl8139_initialize(bd_t *bis) { struct rtl8139_priv *priv; From 2df3a51510758dc6208ecf36f5e4b929d01f2dd1 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sat, 9 May 2020 22:34:42 +0200 Subject: [PATCH 25/29] net: rtl8139: Use PCI_DEVICE() to define PCI device compat list Use this macro to fully fill the PCI device ID table. This is mandatory for the DM PCI support, which checks all the fields. Signed-off-by: Marek Vasut Cc: Joe Hershberger --- drivers/net/rtl8139.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/rtl8139.c b/drivers/net/rtl8139.c index 70b09fb2d2..f3190170d3 100644 --- a/drivers/net/rtl8139.c +++ b/drivers/net/rtl8139.c @@ -538,8 +538,8 @@ static void rtl8139_name(char *str, int card_number) } 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_DEVICE(PCI_VENDOR_ID_REALTEK, PCI_DEVICE_ID_REALTEK_8139) }, + { PCI_DEVICE(PCI_VENDOR_ID_DLINK, PCI_DEVICE_ID_DLINK_8139) }, { } }; From d8afb8b28efb5af640d693e7f848732141482cfb Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sat, 9 May 2020 22:34:43 +0200 Subject: [PATCH 26/29] net: rtl8139: Read HW address from EEPROM only on probe Do not re-read the HW address from the EEPROM on every start of transfer, otherwise the user will not be able to adjust ethaddr as needed. Read the address only once, when the card is detected. Signed-off-by: Marek Vasut Cc: Joe Hershberger --- drivers/net/rtl8139.c | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/drivers/net/rtl8139.c b/drivers/net/rtl8139.c index f3190170d3..d7fabdbcf4 100644 --- a/drivers/net/rtl8139.c +++ b/drivers/net/rtl8139.c @@ -502,17 +502,11 @@ static int rtl8139_free_pkt_common(struct rtl8139_priv *priv, unsigned int len) static int rtl8139_init_common(struct rtl8139_priv *priv) { - unsigned short *ap = (unsigned short *)priv->enetaddr; - int addr_len, i; u8 reg; /* Bring the chip out of low-power mode. */ outb(0x00, priv->ioaddr + RTL_REG_CONFIG1); - addr_len = rtl8139_read_eeprom(priv, 0, 8) == 0x8129 ? 8 : 6; - for (i = 0; i < 3; i++) - *ap++ = le16_to_cpu(rtl8139_read_eeprom(priv, i + 7, addr_len)); - rtl8139_reset(priv); reg = inb(priv->ioaddr + RTL_REG_MEDIASTATUS); @@ -521,9 +515,6 @@ static int rtl8139_init_common(struct rtl8139_priv *priv) return -1; } - /* Non-DM compatibility */ - memcpy(priv->dev.enetaddr, priv->enetaddr, 6); - return 0; } @@ -532,6 +523,19 @@ static void rtl8139_stop_common(struct rtl8139_priv *priv) rtl8139_hw_reset(priv); } +static void rtl8139_get_hwaddr(struct rtl8139_priv *priv) +{ + unsigned short *ap = (unsigned short *)priv->enetaddr; + int i, addr_len; + + /* Bring the chip out of low-power mode. */ + outb(0x00, priv->ioaddr + RTL_REG_CONFIG1); + + addr_len = rtl8139_read_eeprom(priv, 0, 8) == 0x8129 ? 8 : 6; + for (i = 0; i < 3; i++) + *ap++ = le16_to_cpu(rtl8139_read_eeprom(priv, i + 7, addr_len)); +} + static void rtl8139_name(char *str, int card_number) { sprintf(str, "RTL8139#%u", card_number); @@ -626,6 +630,11 @@ int rtl8139_initialize(bd_t *bis) dev->recv = rtl8139_recv; dev->mcast = rtl8139_bcast_addr; + rtl8139_get_hwaddr(priv); + + /* Non-DM compatibility */ + memcpy(priv->dev.enetaddr, priv->enetaddr, 6); + eth_register(dev); card_number++; From 46c8b18734d273619174006eef498639c06000d3 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sat, 9 May 2020 22:34:44 +0200 Subject: [PATCH 27/29] net: rtl8139: Add DM support Add support for driver model to the driver. Signed-off-by: Marek Vasut Cc: Joe Hershberger --- drivers/net/rtl8139.c | 133 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 132 insertions(+), 1 deletion(-) diff --git a/drivers/net/rtl8139.c b/drivers/net/rtl8139.c index d7fabdbcf4..8a6f305893 100644 --- a/drivers/net/rtl8139.c +++ b/drivers/net/rtl8139.c @@ -70,6 +70,7 @@ #include #include +#include #include #include #include @@ -96,8 +97,13 @@ #define DEBUG_TX 0 /* set to 1 to enable debug code */ #define DEBUG_RX 0 /* set to 1 to enable debug code */ +#ifdef CONFIG_DM_ETH +#define bus_to_phys(devno, a) dm_pci_mem_to_phys((devno), (a)) +#define phys_to_bus(devno, a) dm_pci_phys_to_mem((devno), (a)) +#else #define bus_to_phys(devno, a) pci_mem_to_phys((pci_dev_t)(devno), (a)) #define phys_to_bus(devno, a) pci_phys_to_mem((pci_dev_t)(devno), (a)) +#endif /* Symbolic offsets to registers. */ /* Ethernet hardware address. */ @@ -192,12 +198,16 @@ #define RTL_STS_RXSTATUSOK BIT(0) struct rtl8139_priv { +#ifndef CONFIG_DM_ETH struct eth_device dev; + pci_dev_t devno; +#else + struct udevice *devno; +#endif unsigned int rxstatus; unsigned int cur_rx; unsigned int cur_tx; unsigned long ioaddr; - pci_dev_t devno; unsigned char enetaddr[6]; }; @@ -547,6 +557,7 @@ static struct pci_device_id supported[] = { { } }; +#ifndef CONFIG_DM_ETH static int rtl8139_bcast_addr(struct eth_device *dev, const u8 *bcast_mac, int join) { @@ -646,3 +657,123 @@ int rtl8139_initialize(bd_t *bis) return card_number; } +#else /* DM_ETH */ +static int rtl8139_start(struct udevice *dev) +{ + struct eth_pdata *plat = dev_get_platdata(dev); + struct rtl8139_priv *priv = dev_get_priv(dev); + + memcpy(priv->enetaddr, plat->enetaddr, sizeof(plat->enetaddr)); + + return rtl8139_init_common(priv); +} + +static void rtl8139_stop(struct udevice *dev) +{ + struct rtl8139_priv *priv = dev_get_priv(dev); + + rtl8139_stop_common(priv); +} + +static int rtl8139_send(struct udevice *dev, void *packet, int length) +{ + struct rtl8139_priv *priv = dev_get_priv(dev); + int ret; + + ret = rtl8139_send_common(priv, packet, length); + + return ret ? 0 : -ETIMEDOUT; +} + +static int rtl8139_recv(struct udevice *dev, int flags, uchar **packetp) +{ + struct rtl8139_priv *priv = dev_get_priv(dev); + static unsigned char rxdata[RX_BUF_LEN]; + + return rtl8139_recv_common(priv, rxdata, packetp); +} + +static int rtl8139_free_pkt(struct udevice *dev, uchar *packet, int length) +{ + struct rtl8139_priv *priv = dev_get_priv(dev); + + rtl8139_free_pkt_common(priv, length); + + return 0; +} + +static int rtl8139_write_hwaddr(struct udevice *dev) +{ + struct eth_pdata *plat = dev_get_platdata(dev); + struct rtl8139_priv *priv = dev_get_priv(dev); + + memcpy(priv->enetaddr, plat->enetaddr, sizeof(plat->enetaddr)); + + rtl8139_reset(priv); + + return 0; +} + +static int rtl8139_read_rom_hwaddr(struct udevice *dev) +{ + struct rtl8139_priv *priv = dev_get_priv(dev); + + rtl8139_get_hwaddr(priv); + + return 0; +} + +static int rtl8139_bind(struct udevice *dev) +{ + static int card_number; + char name[16]; + + rtl8139_name(name, card_number++); + + return device_set_name(dev, name); +} + +static int rtl8139_probe(struct udevice *dev) +{ + struct eth_pdata *plat = dev_get_platdata(dev); + struct rtl8139_priv *priv = dev_get_priv(dev); + u32 iobase; + + dm_pci_read_config32(dev, PCI_BASE_ADDRESS_1, &iobase); + iobase &= ~0xf; + + debug("rtl8139: REALTEK RTL8139 @0x%x\n", iobase); + + priv->devno = dev; + priv->ioaddr = (unsigned long)bus_to_phys(dev, iobase); + + rtl8139_get_hwaddr(priv); + memcpy(plat->enetaddr, priv->enetaddr, sizeof(priv->enetaddr)); + + dm_pci_write_config8(dev, PCI_LATENCY_TIMER, 0x20); + + return 0; +} + +static const struct eth_ops rtl8139_ops = { + .start = rtl8139_start, + .send = rtl8139_send, + .recv = rtl8139_recv, + .stop = rtl8139_stop, + .free_pkt = rtl8139_free_pkt, + .write_hwaddr = rtl8139_write_hwaddr, + .read_rom_hwaddr = rtl8139_read_rom_hwaddr, +}; + +U_BOOT_DRIVER(eth_rtl8139) = { + .name = "eth_rtl8139", + .id = UCLASS_ETH, + .bind = rtl8139_bind, + .probe = rtl8139_probe, + .ops = &rtl8139_ops, + .priv_auto_alloc_size = sizeof(struct rtl8139_priv), + .platdata_auto_alloc_size = sizeof(struct eth_pdata), +}; + +U_BOOT_PCI_DEVICE(eth_rtl8139, supported); +#endif From 0813921042c363a9c591454144226e67ed21a223 Mon Sep 17 00:00:00 2001 From: Ravik Hasija Date: Mon, 18 May 2020 21:35:43 -0700 Subject: [PATCH 28/29] net: tftp: fix option validation as per RFCs RFC2348, RFC2349: - Option string is case in-sensitive. - Client must generate ERR pkt in case option value mismatch in server OACK - Fix debug print for options Signed-off-by: Ravik Hasija Reviewed-By: Ramon Fried --- net/tftp.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 52 insertions(+), 7 deletions(-) diff --git a/net/tftp.c b/net/tftp.c index bbede9c0f2..c05b7b5532 100644 --- a/net/tftp.c +++ b/net/tftp.c @@ -70,6 +70,7 @@ enum { TFTP_ERR_UNEXPECTED_OPCODE = 4, TFTP_ERR_UNKNOWN_TRANSFER_ID = 5, TFTP_ERR_FILE_ALREADY_EXISTS = 6, + TFTP_ERR_OPTION_NEGOTIATION = 8, }; static struct in_addr tftp_remote_ip; @@ -113,6 +114,7 @@ static int tftp_put_final_block_sent; #define STATE_OACK 5 #define STATE_RECV_WRQ 6 #define STATE_SEND_WRQ 7 +#define STATE_INVALID_OPTION 8 /* default TFTP block size */ #define TFTP_BLOCK_SIZE 512 @@ -318,6 +320,7 @@ static void tftp_send(void) uchar *xp; int len = 0; ushort *s; + bool err_pkt = false; /* * We will always be sending some sort of packet, so @@ -388,6 +391,7 @@ static void tftp_send(void) strcpy((char *)pkt, "File too large"); pkt += 14 /*strlen("File too large")*/ + 1; len = pkt - xp; + err_pkt = true; break; case STATE_BAD_MAGIC: @@ -399,11 +403,28 @@ static void tftp_send(void) strcpy((char *)pkt, "File has bad magic"); pkt += 18 /*strlen("File has bad magic")*/ + 1; len = pkt - xp; + err_pkt = true; + break; + + case STATE_INVALID_OPTION: + xp = pkt; + s = (ushort *)pkt; + *s++ = htons(TFTP_ERROR); + *s++ = htons(TFTP_ERR_OPTION_NEGOTIATION); + pkt = (uchar *)s; + strcpy((char *)pkt, "Option Negotiation Failed"); + /* strlen("Option Negotiation Failed") + NULL*/ + pkt += 25 + 1; + len = pkt - xp; + err_pkt = true; break; } net_send_udp_packet(net_server_ethaddr, tftp_remote_ip, tftp_remote_port, tftp_our_port, len); + + if (err_pkt) + net_set_state(NETLOOP_FAIL); } #ifdef CONFIG_CMD_TFTPPUT @@ -424,6 +445,7 @@ static void tftp_handler(uchar *pkt, unsigned dest, struct in_addr sip, __be16 proto; __be16 *s; int i; + u16 timeout_val_rcvd; if (dest != tftp_our_port) { return; @@ -480,8 +502,14 @@ static void tftp_handler(uchar *pkt, unsigned dest, struct in_addr sip, #endif case TFTP_OACK: - debug("Got OACK: %s %s\n", - pkt, pkt + strlen((char *)pkt) + 1); + debug("Got OACK: "); + for (i = 0; i < len; i++) { + if (pkt[i] == '\0') + debug(" "); + else + debug("%c", pkt[i]); + } + debug("\n"); tftp_state = STATE_OACK; tftp_remote_port = src; /* @@ -490,15 +518,32 @@ static void tftp_handler(uchar *pkt, unsigned dest, struct in_addr sip, * something like "len-8" may give a *huge* number */ for (i = 0; i+8 < len; i++) { - if (strcmp((char *)pkt + i, "blksize") == 0) { + if (strcasecmp((char *)pkt + i, "blksize") == 0) { tftp_block_size = (unsigned short) simple_strtoul((char *)pkt + i + 8, NULL, 10); - debug("Blocksize ack: %s, %d\n", + debug("Blocksize oack: %s, %d\n", (char *)pkt + i + 8, tftp_block_size); + if (tftp_block_size > tftp_block_size_option) { + printf("Invalid blk size(=%d)\n", + tftp_block_size); + tftp_state = STATE_INVALID_OPTION; + } + } + if (strcasecmp((char *)pkt + i, "timeout") == 0) { + timeout_val_rcvd = (unsigned short) + simple_strtoul((char *)pkt + i + 8, + NULL, 10); + debug("Timeout oack: %s, %d\n", + (char *)pkt + i + 8, timeout_val_rcvd); + if (timeout_val_rcvd != (timeout_ms / 1000)) { + printf("Invalid timeout val(=%d s)\n", + timeout_val_rcvd); + tftp_state = STATE_INVALID_OPTION; + } } #ifdef CONFIG_TFTP_TSIZE - if (strcmp((char *)pkt+i, "tsize") == 0) { + if (strcasecmp((char *)pkt + i, "tsize") == 0) { tftp_tsize = simple_strtoul((char *)pkt + i + 6, NULL, 10); debug("size = %s, %d\n", @@ -507,7 +552,7 @@ static void tftp_handler(uchar *pkt, unsigned dest, struct in_addr sip, #endif } #ifdef CONFIG_CMD_TFTPPUT - if (tftp_put_active) { + if (tftp_put_active && tftp_state == STATE_OACK) { /* Get ready to send the first block */ tftp_state = STATE_DATA; tftp_cur_block++; @@ -522,7 +567,7 @@ static void tftp_handler(uchar *pkt, unsigned dest, struct in_addr sip, tftp_cur_block = ntohs(*(__be16 *)pkt); if (tftp_state == STATE_SEND_RRQ) - debug("Server did not acknowledge timeout option!\n"); + debug("Server did not acknowledge any options!\n"); if (tftp_state == STATE_SEND_RRQ || tftp_state == STATE_OACK || tftp_state == STATE_RECV_WRQ) { From f1d925d9c39628d346b3809408695cd5c8b8faa2 Mon Sep 17 00:00:00 2001 From: Baruch Siach Date: Wed, 20 May 2020 13:31:41 +0300 Subject: [PATCH 29/29] net: move random_port() to dns The random_port() routine is not used anywhere else. Make it local to dns.c to reduce code clutter, and shrink generated code a little. Signed-off-by: Baruch Siach --- include/net.h | 3 --- net/dns.c | 10 ++++++++++ net/net.c | 14 -------------- 3 files changed, 10 insertions(+), 17 deletions(-) diff --git a/include/net.h b/include/net.h index 00a8ec0c78..1bf9867f8c 100644 --- a/include/net.h +++ b/include/net.h @@ -897,9 +897,6 @@ int is_serverip_in_cmd(void); */ int net_parse_bootfile(struct in_addr *ipaddr, char *filename, int max_len); -/* get a random source port */ -unsigned int random_port(void); - /** * update_tftp - Update firmware over TFTP (via DFU) * diff --git a/net/dns.c b/net/dns.c index e35c4dca7c..5b1fe5b010 100644 --- a/net/dns.c +++ b/net/dns.c @@ -36,6 +36,16 @@ char *net_dns_env_var; /* The envvar to store the answer in */ static int dns_our_port; +/* + * make port a little random (1024-17407) + * This keeps the math somewhat trivial to compute, and seems to work with + * all supported protocols/clients/servers + */ +static unsigned int random_port(void) +{ + return 1024 + (get_timer(0) % 0x4000); +} + static void dns_send(void) { struct header *header; diff --git a/net/net.c b/net/net.c index 11683dd6d0..1e7f633cb6 100644 --- a/net/net.c +++ b/net/net.c @@ -1564,20 +1564,6 @@ int net_parse_bootfile(struct in_addr *ipaddr, char *filename, int max_len) return 1; } -#if defined(CONFIG_CMD_NFS) || \ - defined(CONFIG_CMD_SNTP) || \ - defined(CONFIG_CMD_DNS) -/* - * make port a little random (1024-17407) - * This keeps the math somewhat trivial to compute, and seems to work with - * all supported protocols/clients/servers - */ -unsigned int random_port(void) -{ - return 1024 + (get_timer(0) % 0x4000); -} -#endif - void ip_to_string(struct in_addr x, char *s) { x.s_addr = ntohl(x.s_addr);