diff --git a/board/tbs/tbs2910/MAINTAINERS b/board/tbs/tbs2910/MAINTAINERS index a3ad2f712a254b26dab7e51b2f88cc4e89daedfa..1e3c0d0ece897eeadfa4a012ea3732d6efe674f9 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/cmd/net.c b/cmd/net.c index 25390b0474f4c9032cea1c678a1053e9d195a3f5..9bbcdbcfe0762f50d1c39c1554def117e8ccdfed 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/configs/am65x_evm_a53_defconfig b/configs/am65x_evm_a53_defconfig index d74a2d09309bf6c0cb8da4556d2b58ac592262f1..c5ca4da73a8c547799844a6e1c7bddbf2a5af1f6 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 117953817d820e1fdc2dc1ff0fe2d6dd39973441..644873d67c74192c149b8590c7da6318454a7b38 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 e4547d9dcc8c3960ade7d5721f6a8d25ba331dda..73ac3b319b59ea5fa74ff383f8abf94bf43c4240 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 c08bcce903813e1e2faaaf6483b597c91359bae2..40dc554e8071dcb260b1387aef43c0bd57506206 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 879c2b650be3da549a4011db0b1c9096580c5887..babd7029c0e2decb8419ec9c074b245ebc161d7a 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 4deb4e219fe77bedf9e0ca6eaded74a0b4545980..91a05722870babb008860b73636210a39485ccfe 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 ae540a26a4015758a7af50eff68f0035fe665d2b..9aa3113642c96d98470672266e37db24cbfd2553 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 5bc7f7f8656ebacac80b22f94063901a1bca9475..0379021c14cb93c45c6ab9bafefdb5acfa24d97c 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/tbs2910_defconfig b/configs/tbs2910_defconfig index 2ff0e160f7379004b6e6617ef6c92fd60001fd19..fbd2293add15cf70e3711c4b83a12de58f1702b2 100644 --- a/configs/tbs2910_defconfig +++ b/configs/tbs2910_defconfig @@ -9,11 +9,15 @@ 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 || 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 @@ -28,6 +32,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 @@ -39,6 +45,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 @@ -86,5 +93,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 diff --git a/configs/xilinx_versal_virt_defconfig b/configs/xilinx_versal_virt_defconfig index 4ed14f7030cca33a9e18059b299555f0821a4257..b3e21ea90371f41cffea33b31de4532122d149ef 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 7886d5a38f29e0017e48cfc855ca43df735114eb..2b4a0244fa9858b597486e2b65dfe5fda47fc8c2 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/doc/board/index.rst b/doc/board/index.rst index 01b233f737288cd6b85e756515ffd3ebcf7b6598..bb4473152a87db6e4e746b402733383d907a8897 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 0000000000000000000000000000000000000000..b677bc624fd6ec3a0283a6e19000459fdb0c30d0 --- /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 0000000000000000000000000000000000000000..e97f2b6e61353da9b547d0d6461ac5535700fbb6 --- /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. diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig index d1f049e62ab7c702bddd02106abe197a448cb822..b0bd762ac397557f476070fc46e04928e93e4f15 100644 --- a/drivers/net/phy/Kconfig +++ b/drivers/net/phy/Kconfig @@ -243,6 +243,21 @@ 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_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/Makefile b/drivers/net/phy/Makefile index 1d81516ecd1d3221074bf678fe27daeace85801f..6e722331f1bf2029282534a6745ca2195ae66899 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 d435cc1e6c549d76502cb71abd9958bed6f4d386..eada4541c9c336c786ec2d0c7d5bfe5e77edaa23 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/micrel_ksz8xxx.c b/drivers/net/phy/micrel_ksz8xxx.c index 98a0c83e68b13b63ba217b222c60852bcb99584b..60d42fe9840a746dcb842005ef4e4fb38c6b487c 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); diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c index cce09c47f9dc18e30a701b1c55c9f327226ec9d4..67789897c2569aa969fe21af1adc98a120ef69fd 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) diff --git a/drivers/net/phy/ti_phy_init.c b/drivers/net/phy/ti_phy_init.c new file mode 100644 index 0000000000000000000000000000000000000000..50eff77692f1573a6b3fad125874f0828ca730d0 --- /dev/null +++ b/drivers/net/phy/ti_phy_init.c @@ -0,0 +1,101 @@ +// 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 +#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; +} diff --git a/drivers/net/phy/ti_phy_init.h b/drivers/net/phy/ti_phy_init.h new file mode 100644 index 0000000000000000000000000000000000000000..6c7f6c640a7992f4213045a7e86d8b5dff9dcf72 --- /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 */ diff --git a/drivers/net/rtl8139.c b/drivers/net/rtl8139.c index 0daeefa489b1ae154bf82f652001464415cea720..8a6f305893bc6ca5a302d5ec9fdee4a48096fcca 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 */ -#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) +#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. */ @@ -191,8 +197,19 @@ #define RTL_STS_RXBADALIGN BIT(1) #define RTL_STS_RXSTATUSOK BIT(0) -static unsigned int cur_rx, cur_tx; -static int ioaddr; +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; + 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); @@ -214,51 +231,52 @@ 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(unsigned int location, unsigned int addr_len) +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 = ioaddr + 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(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(ioaddr); + rtl8139_eeprom_delay(priv); outb(EE_ENB | dataval | EE_SHIFT_CLK, ee_addr); - rtl8139_eeprom_delay(ioaddr); + rtl8139_eeprom_delay(priv); } outb(EE_ENB, ee_addr); - rtl8139_eeprom_delay(ioaddr); + rtl8139_eeprom_delay(priv); for (i = 16; i > 0; i--) { outb(EE_ENB | EE_SHIFT_CLK, ee_addr); - rtl8139_eeprom_delay(ioaddr); + rtl8139_eeprom_delay(priv); retval <<= 1; retval |= inb(ee_addr) & EE_DATA_READ; outb(EE_ENB, ee_addr); - rtl8139_eeprom_delay(ioaddr); + rtl8139_eeprom_delay(priv); } /* Terminate the EEPROM access. */ outb(~EE_CS, ee_addr); - rtl8139_eeprom_delay(ioaddr); + rtl8139_eeprom_delay(priv); return retval; } @@ -268,29 +286,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, ioaddr + RTL_REG_RXCONFIG); + outl(rtl8139_rx_config | rx_mode, priv->ioaddr + RTL_REG_RXCONFIG); - outl(0xffffffff, ioaddr + RTL_REG_MAR0 + 0); - outl(0xffffffff, ioaddr + 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, ioaddr + 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(ioaddr + RTL_REG_CHIPCMD); + reg = inb(priv->ioaddr + RTL_REG_CHIPCMD); if (!(reg & RTL_REG_CHIPCMD_CMDRESET)) break; @@ -298,25 +316,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], ioaddr + 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, - ioaddr + RTL_REG_CHIPCMD); + priv->ioaddr + RTL_REG_CHIPCMD); /* accept no frames yet! */ - outl(rtl8139_rx_config, ioaddr + RTL_REG_RXCONFIG); - outl((TX_DMA_BURST << 8) | 0x03000000, ioaddr + RTL_REG_TXCONFIG); + 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 +349,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(priv->devno, (int)rx_ring), priv->ioaddr + RTL_REG_RXBUF); /* * If we add multicast support, the RTL_REG_MAR0 register would have @@ -340,28 +358,27 @@ static void rtl8139_reset(struct eth_device *dev) * unicast. */ outb(RTL_REG_CHIPCMD_CMDRXENB | RTL_REG_CHIPCMD_CMDTXENB, - ioaddr + RTL_REG_CHIPCMD); + priv->ioaddr + RTL_REG_CHIPCMD); - outl(rtl8139_rx_config, ioaddr + RTL_REG_RXCONFIG); + outl(rtl8139_rx_config, priv->ioaddr + RTL_REG_RXCONFIG); /* Start the chip's Tx and Rx process. */ - outl(0, ioaddr + 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, ioaddr + RTL_REG_INTRMASK); + 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) { unsigned int len = length; unsigned long txstatus; unsigned int status; int i = 0; - ioaddr = dev->iobase; - memcpy(tx_buffer, packet, length); debug_cond(DEBUG_TX, "sending %d bytes\n", len); @@ -374,13 +391,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((unsigned long)tx_buffer), - ioaddr + 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, - ioaddr + RTL_REG_TXSTATUS0 + cur_tx * 4); + priv->ioaddr + RTL_REG_TXSTATUS0 + priv->cur_tx * 4); do { - status = inw(ioaddr + RTL_REG_INTRSTATUS); + status = inw(priv->ioaddr + RTL_REG_INTRSTATUS); /* * Only acknlowledge interrupt sources we can properly * handle here - the RTL_REG_INTRSTATUS_RXOVERFLOW/ @@ -389,26 +406,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, ioaddr + RTL_REG_INTRSTATUS); + outw(status, priv->ioaddr + RTL_REG_INTRSTATUS); if (status) break; udelay(10); } while (i++ < RTL_TIMEOUT); - txstatus = inl(ioaddr + 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,28 +433,26 @@ 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) { 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; - ioaddr = dev->iobase; - - if (inb(ioaddr + RTL_REG_CHIPCMD) & RTL_REG_CHIPCMD_RXBUFEMPTY) + if (inb(priv->ioaddr + RTL_REG_CHIPCMD) & RTL_REG_CHIPCMD_RXBUFEMPTY) return 0; - status = inw(ioaddr + RTL_REG_INTRSTATUS); + priv->rxstatus = inw(priv->ioaddr + RTL_REG_INTRSTATUS); /* See below for the rest of the interrupt acknowledges. */ - outw(status & ~rxstat, 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 = 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; @@ -450,59 +465,61 @@ 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; } /* 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); - cur_rx = ROUND(cur_rx + rx_size + 4, 4); - outw(cur_rx - 16, ioaddr + 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, 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) { - unsigned short *ap = (unsigned short *)dev->enetaddr; - int addr_len, i; u8 reg; - ioaddr = dev->iobase; - /* Bring the chip out of low-power mode. */ - outb(0x00, ioaddr + RTL_REG_CONFIG1); + outb(0x00, priv->ioaddr + RTL_REG_CONFIG1); - addr_len = rtl8139_read_eeprom(0, 8) == 0x8129 ? 8 : 6; - for (i = 0; i < 3; i++) - *ap++ = le16_to_cpu(rtl8139_read_eeprom(i + 7, addr_len)); - - rtl8139_reset(dev); + rtl8139_reset(priv); - reg = inb(ioaddr + 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; @@ -511,27 +528,82 @@ 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) { - ioaddr = dev->iobase; + rtl8139_hw_reset(priv); +} - rtl8139_hw_reset(dev); +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 int rtl8139_bcast_addr(struct eth_device *dev, const u8 *bcast_mac, - int join) +static void rtl8139_name(char *str, int card_number) { - return 0; + 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 }, + { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, PCI_DEVICE_ID_REALTEK_8139) }, + { PCI_DEVICE(PCI_VENDOR_ID_DLINK, PCI_DEVICE_ID_DLINK_8139) }, { } }; +#ifndef CONFIG_DM_ETH +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; struct eth_device *dev; int card_number = 0; pci_dev_t devno; @@ -549,23 +621,31 @@ int rtl8139_initialize(bd_t *bis) debug("rtl8139: REALTEK RTL8139 @0x%x\n", iobase); - dev = (struct eth_device *)malloc(sizeof(*dev)); - if (!dev) { + priv = calloc(1, sizeof(*priv)); + if (!priv) { printf("Can not allocate memory of rtl8139\n"); break; } - memset(dev, 0, sizeof(*dev)); - sprintf(dev->name, "RTL8139#%d", card_number); + 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 = (int)bus_to_phys(iobase); + dev->iobase = priv->ioaddr; /* Non-DM compatibility */ dev->init = rtl8139_init; dev->halt = rtl8139_stop; dev->send = rtl8139_send; 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++; @@ -577,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 diff --git a/drivers/net/rtl8169.c b/drivers/net/rtl8169.c index 75058fdadc00ea73bfd0e41951e29690cf06b480..fb4fae20e5386f7c462b9ee25bb3e36e750824bd 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; } diff --git a/examples/standalone/Makefile b/examples/standalone/Makefile index 4a34813804f634741c7f9896b8c6572de8a69750..d4be0c7350dcf7b8d8a09c31cf68fd6713510778 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 9bd9a6efa30c55518bca310eff6ed8f6f30036df..0000000000000000000000000000000000000000 --- 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; - } - } -} diff --git a/include/configs/tbs2910.h b/include/configs/tbs2910.h index 7376b91f550a8a30143ef456515956101f0c0bae..17de122852f350217c87def9e5469de6bb8485d5 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,12 +108,14 @@ "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" +/* 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 * */ diff --git a/include/net.h b/include/net.h index 00a8ec0c78a3de8ea19604d694865d019cf2e4a6..1bf9867f8cf8efaf70528d1e4e892034701e9857 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/include/phy.h b/include/phy.h index b5de14cbfc293d7b5fb1b67ff2cbf22e2ba91bef..fedd14609192130f68447748cbe16c8e535d94b8 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) { @@ -257,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; @@ -275,26 +368,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 @@ -304,7 +394,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); @@ -320,7 +410,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 @@ -332,7 +421,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, @@ -356,7 +445,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 @@ -368,7 +456,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, @@ -428,7 +516,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); @@ -436,6 +524,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) { @@ -447,6 +536,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) { diff --git a/net/dns.c b/net/dns.c index e35c4dca7c5030dc4e316eb315f8a56013b6fba1..5b1fe5b0103747a0fe91c5c17bc69a8f2801dfb9 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 37932919d049a7a834bb999e83f593f9b5d47a29..1e7f633cb69c903f3d8d183f6aa13ef2fc686892 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; @@ -1562,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); diff --git a/net/tftp.c b/net/tftp.c index 180140e495b15482f9ac2c0fef87a0b87f6cf8da..c05b7b5532b9c5454cebc5a85417f84ff87caaad 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 @@ -233,9 +235,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 +251,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 +288,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 */ @@ -315,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 @@ -385,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: @@ -396,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 @@ -421,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; @@ -477,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; /* @@ -487,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", @@ -504,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++; @@ -518,10 +566,8 @@ 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"); + debug("Server did not acknowledge any options!\n"); if (tftp_state == STATE_SEND_RRQ || tftp_state == STATE_OACK || tftp_state == STATE_RECV_WRQ) { @@ -545,6 +591,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);