mirror of
https://github.com/Fishwaldo/u-boot.git
synced 2025-03-18 13:11:31 +00:00
Merge branch '2020-06-12-next-net' into next
- Merge tbs2910 distro boot support and associated clean-ups and size reduction. - Assorted networking corrections / bugfixes. - Drop smc911x standalone API example as it was likely non-functional for a long time. - Enhanced support for TI PHYs - rtl8139 DM conversion
This commit is contained in:
commit
8a1292ce3e
33 changed files with 892 additions and 693 deletions
|
@ -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
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -18,5 +18,6 @@ Board-specific doc
|
|||
rockchip/index
|
||||
sifive/index
|
||||
st/index
|
||||
tbs/index
|
||||
toradex/index
|
||||
xilinx/index
|
||||
|
|
9
doc/board/tbs/index.rst
Normal file
9
doc/board/tbs/index.rst
Normal file
|
@ -0,0 +1,9 @@
|
|||
.. SPDX-License-Identifier: GPL-2.0+
|
||||
|
||||
TBS
|
||||
===
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
tbs2910
|
191
doc/board/tbs/tbs2910.rst
Normal file
191
doc/board/tbs/tbs2910.rst
Normal file
|
@ -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.
|
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include <dm.h>
|
||||
#include <dt-bindings/net/ti-dp83867.h>
|
||||
|
||||
#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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
101
drivers/net/phy/ti_phy_init.c
Normal file
101
drivers/net/phy/ti_phy_init.c
Normal file
|
@ -0,0 +1,101 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* TI Generic PHY Init to register any TI Ethernet PHYs
|
||||
*
|
||||
* Author: Dan Murphy <dmurphy@ti.com>
|
||||
*
|
||||
* Copyright (C) 2019-20 Texas Instruments Inc.
|
||||
*/
|
||||
|
||||
#include <phy.h>
|
||||
#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;
|
||||
}
|
15
drivers/net/phy/ti_phy_init.h
Normal file
15
drivers/net/phy/ti_phy_init.h
Normal file
|
@ -0,0 +1,15 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/*
|
||||
* TI Generic Ethernet PHY
|
||||
*
|
||||
* Author: Dan Murphy <dmurphy@ti.com>
|
||||
*
|
||||
* 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 */
|
|
@ -70,6 +70,7 @@
|
|||
|
||||
#include <common.h>
|
||||
#include <cpu_func.h>
|
||||
#include <dm.h>
|
||||
#include <log.h>
|
||||
#include <malloc.h>
|
||||
#include <net.h>
|
||||
|
@ -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(priv);
|
||||
|
||||
rtl8139_reset(dev);
|
||||
|
||||
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(dev);
|
||||
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);
|
||||
}
|
||||
|
||||
static struct pci_device_id supported[] = {
|
||||
{ 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 struct pci_device_id supported[] = {
|
||||
{ PCI_VENDOR_ID_REALTEK, PCI_DEVICE_ID_REALTEK_8139 },
|
||||
{ PCI_VENDOR_ID_DLINK, PCI_DEVICE_ID_DLINK_8139 },
|
||||
{ }
|
||||
};
|
||||
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 = (void *)devno;
|
||||
dev->iobase = (int)bus_to_phys(iobase);
|
||||
dev = &priv->dev;
|
||||
|
||||
rtl8139_name(dev->name, card_number);
|
||||
|
||||
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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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 <common.h>
|
||||
#include <console.h>
|
||||
#include <exports.h>
|
||||
#include <net.h>
|
||||
#include <linux/ctype.h>
|
||||
#include <linux/types.h>
|
||||
#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 <E|M> <register> <value>\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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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 <config_distro_bootcmd.h>
|
||||
|
||||
#endif /* __TBS2910_CONFIG_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)
|
||||
*
|
||||
|
|
112
include/phy.h
112
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)
|
||||
{
|
||||
|
|
10
net/dns.c
10
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;
|
||||
|
|
20
net/net.c
20
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);
|
||||
|
|
75
net/tftp.c
75
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);
|
||||
|
|
Loading…
Add table
Reference in a new issue