Merge branch 'master' of git://git.denx.de/u-boot-net

- Basic bug fixes and minor features for 2019.07.
This commit is contained in:
Tom Rini 2019-06-02 08:33:10 -04:00
commit 55cae6458d
8 changed files with 228 additions and 6 deletions

View File

@ -0,0 +1,66 @@
The following properties are common to the Ethernet controllers:
NOTE: All 'phy*' properties documented below are Ethernet specific. For the
generic PHY 'phys' property, see
Documentation/devicetree/bindings/phy/phy-bindings.txt.
- local-mac-address: array of 6 bytes, specifies the MAC address that was
assigned to the network device;
- mac-address: array of 6 bytes, specifies the MAC address that was last used by
the boot program; should be used in cases where the MAC address assigned to
the device by the boot program is different from the "local-mac-address"
property;
- nvmem-cells: phandle, reference to an nvmem node for the MAC address;
- nvmem-cell-names: string, should be "mac-address" if nvmem is to be used;
- max-speed: number, specifies maximum speed in Mbit/s supported by the device;
- max-frame-size: number, maximum transfer unit (IEEE defined MTU), rather than
the maximum frame size (there's contradiction in the Devicetree
Specification).
- phy-mode: string, operation mode of the PHY interface. This is now a de-facto
standard property; supported values are:
* "internal"
* "mii"
* "gmii"
* "sgmii"
* "qsgmii"
* "tbi"
* "rev-mii"
* "rmii"
* "rgmii" (RX and TX delays are added by the MAC when required)
* "rgmii-id" (RGMII with internal RX and TX delays provided by the PHY, the
MAC should not add the RX or TX delays in this case)
* "rgmii-rxid" (RGMII with internal RX delay provided by the PHY, the MAC
should not add an RX delay in this case)
* "rgmii-txid" (RGMII with internal TX delay provided by the PHY, the MAC
should not add an TX delay in this case)
* "rtbi"
* "smii"
* "xgmii"
* "trgmii"
* "2000base-x",
* "2500base-x",
* "rxaui"
* "xaui"
* "10gbase-kr" (10GBASE-KR, XFI, SFI)
- phy-connection-type: the same as "phy-mode" property but described in the
Devicetree Specification;
- phy-handle: phandle, specifies a reference to a node representing a PHY
device; this property is described in the Devicetree Specification and so
preferred;
- phy: the same as "phy-handle" property, not recommended for new bindings.
- phy-device: the same as "phy-handle" property, not recommended for new
bindings.
- rx-fifo-depth: the size of the controller's receive fifo in bytes. This
is used for components that can have configurable receive fifo sizes,
and is useful for determining certain configuration settings such as
flow control thresholds.
- tx-fifo-depth: the size of the controller's transmit fifo in bytes. This
is used for components that can have configurable fifo sizes.
- managed: string, specifies the PHY management type. Supported values are:
"auto", "in-band-status". "auto" is the default, it usess MDIO for
management if fixed-link is not specified.
Child nodes of the Ethernet controller are typically the individual PHY devices
connected via the MDIO bus (sometimes the MDIO bus controller is separate).
They are described in the phy.txt file in this same directory.
For non-MDIO PHY management see fixed-link.txt.

View File

@ -28,6 +28,7 @@ config BOARD_SPECIFIC_OPTIONS # dummy
imply CMD_PING
imply CLK_SIFIVE
imply CLK_SIFIVE_FU540_PRCI
imply CLK_SIFIVE_GEMGXL_MGMT
imply DOS_PARTITION
imply EFI_PARTITION
imply IP_DYN

View File

@ -54,7 +54,10 @@ static int mdio_write_ranges(struct mii_dev *bus,
for (devad = devadlo; devad <= devadhi; devad++) {
for (reg = reglo; reg <= reghi; reg++) {
if (!extended)
if (!phydev)
err = bus->write(bus, addr, devad,
reg, data);
else if (!extended)
err = phy_write_mmd(phydev, devad,
reg, data);
else
@ -88,7 +91,9 @@ static int mdio_read_ranges(struct mii_dev *bus,
for (reg = reglo; reg <= reghi; reg++) {
int val;
if (!extended)
if (!phydev)
val = bus->read(bus, addr, devad, reg);
else if (!extended)
val = phy_read_mmd(phydev, devad, reg);
else
val = phydev->drv->readext(phydev, addr,

View File

@ -17,3 +17,10 @@ config CLK_SIFIVE_FU540_PRCI
Supports the Power Reset Clock interface (PRCI) IP block found in
FU540 SoCs. If this kernel is meant to run on a SiFive FU540 SoC,
enable this driver.
config CLK_SIFIVE_GEMGXL_MGMT
bool "GEMGXL management for SiFive FU540 SoCs"
depends on CLK_SIFIVE
help
Supports the GEMGXL management IP block found in FU540 SoCs to
control GEM TX clock operation mode for 10/100/1000 Mbps.

View File

@ -3,3 +3,5 @@
obj-$(CONFIG_CLK_ANALOGBITS_WRPLL_CLN28HPC) += wrpll-cln28hpc.o
obj-$(CONFIG_CLK_SIFIVE_FU540_PRCI) += fu540-prci.o
obj-$(CONFIG_CLK_SIFIVE_GEMGXL_MGMT) += gemgxl-mgmt.o

View File

@ -0,0 +1,60 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2019, Bin Meng <bmeng.cn@gmail.com>
*/
#include <common.h>
#include <clk-uclass.h>
#include <dm.h>
#include <asm/io.h>
struct gemgxl_mgmt_regs {
__u32 tx_clk_sel;
};
struct gemgxl_mgmt_platdata {
struct gemgxl_mgmt_regs *regs;
};
static int gemgxl_mgmt_ofdata_to_platdata(struct udevice *dev)
{
struct gemgxl_mgmt_platdata *plat = dev_get_platdata(dev);
plat->regs = (struct gemgxl_mgmt_regs *)dev_read_addr(dev);
return 0;
}
static ulong gemgxl_mgmt_set_rate(struct clk *clk, ulong rate)
{
struct gemgxl_mgmt_platdata *plat = dev_get_platdata(clk->dev);
/*
* GEMGXL TX clock operation mode:
*
* 0 = GMII mode. Use 125 MHz gemgxlclk from PRCI in TX logic
* and output clock on GMII output signal GTX_CLK
* 1 = MII mode. Use MII input signal TX_CLK in TX logic
*/
writel(rate != 125000000, &plat->regs->tx_clk_sel);
return 0;
}
const struct clk_ops gemgxl_mgmt_ops = {
.set_rate = gemgxl_mgmt_set_rate,
};
static const struct udevice_id gemgxl_mgmt_match[] = {
{ .compatible = "sifive,cadencegemgxlmgmt0", },
{ /* sentinel */ }
};
U_BOOT_DRIVER(sifive_gemgxl_mgmt) = {
.name = "sifive-gemgxl-mgmt",
.id = UCLASS_CLK,
.of_match = gemgxl_mgmt_match,
.ofdata_to_platdata = gemgxl_mgmt_ofdata_to_platdata,
.platdata_auto_alloc_size = sizeof(struct gemgxl_mgmt_platdata),
.ops = &gemgxl_mgmt_ops,
};

View File

@ -488,15 +488,58 @@ static int macb_phy_find(struct macb_device *macb, const char *name)
/**
* macb_linkspd_cb - Linkspeed change callback function
* @regs: Base Register of MACB devices
* @dev/@regs: MACB udevice (DM version) or
* Base Register of MACB devices (non-DM version)
* @speed: Linkspeed
* Returns 0 when operation success and negative errno number
* when operation failed.
*/
#ifdef CONFIG_DM_ETH
int __weak macb_linkspd_cb(struct udevice *dev, unsigned int speed)
{
#ifdef CONFIG_CLK
struct clk tx_clk;
ulong rate;
int ret;
/*
* "tx_clk" is an optional clock source for MACB.
* Ignore if it does not exist in DT.
*/
ret = clk_get_by_name(dev, "tx_clk", &tx_clk);
if (ret)
return 0;
switch (speed) {
case _10BASET:
rate = 2500000; /* 2.5 MHz */
break;
case _100BASET:
rate = 25000000; /* 25 MHz */
break;
case _1000BASET:
rate = 125000000; /* 125 MHz */
break;
default:
/* does not change anything */
return 0;
}
if (tx_clk.dev) {
ret = clk_set_rate(&tx_clk, rate);
if (ret)
return ret;
}
#endif
return 0;
}
#else
int __weak macb_linkspd_cb(void *regs, unsigned int speed)
{
return 0;
}
#endif
#ifdef CONFIG_DM_ETH
static int macb_phy_init(struct udevice *dev, const char *name)
@ -589,7 +632,11 @@ static int macb_phy_init(struct macb_device *macb, const char *name)
macb_writel(macb, NCFGR, ncfgr);
#ifdef CONFIG_DM_ETH
ret = macb_linkspd_cb(dev, _1000BASET);
#else
ret = macb_linkspd_cb(macb->regs, _1000BASET);
#endif
if (ret)
return ret;
@ -614,9 +661,17 @@ static int macb_phy_init(struct macb_device *macb, const char *name)
ncfgr &= ~(MACB_BIT(SPD) | MACB_BIT(FD) | GEM_BIT(GBE));
if (speed) {
ncfgr |= MACB_BIT(SPD);
#ifdef CONFIG_DM_ETH
ret = macb_linkspd_cb(dev, _100BASET);
#else
ret = macb_linkspd_cb(macb->regs, _100BASET);
#endif
} else {
#ifdef CONFIG_DM_ETH
ret = macb_linkspd_cb(dev, _10BASET);
#else
ret = macb_linkspd_cb(macb->regs, _10BASET);
#endif
}
if (ret)

View File

@ -455,6 +455,26 @@ static int eth_pre_unbind(struct udevice *dev)
return 0;
}
static bool eth_dev_get_mac_address(struct udevice *dev, u8 mac[ARP_HLEN])
{
#if IS_ENABLED(CONFIG_OF_CONTROL)
const uint8_t *p;
p = dev_read_u8_array_ptr(dev, "mac-address", ARP_HLEN);
if (!p)
p = dev_read_u8_array_ptr(dev, "local-mac-address", ARP_HLEN);
if (!p)
return false;
memcpy(mac, p, ARP_HLEN);
return true;
#else
return false;
#endif
}
static int eth_post_probe(struct udevice *dev)
{
struct eth_device_priv *priv = dev->uclass_priv;
@ -489,9 +509,13 @@ static int eth_post_probe(struct udevice *dev)
priv->state = ETH_STATE_INIT;
/* Check if the device has a MAC address in ROM */
if (eth_get_ops(dev)->read_rom_hwaddr)
eth_get_ops(dev)->read_rom_hwaddr(dev);
/* Check if the device has a valid MAC address in device tree */
if (!eth_dev_get_mac_address(dev, pdata->enetaddr) ||
!is_valid_ethaddr(pdata->enetaddr)) {
/* Check if the device has a MAC address in ROM */
if (eth_get_ops(dev)->read_rom_hwaddr)
eth_get_ops(dev)->read_rom_hwaddr(dev);
}
eth_env_get_enetaddr_by_index("eth", dev->seq, env_enetaddr);
if (!is_zero_ethaddr(env_enetaddr)) {
@ -524,6 +548,8 @@ static int eth_post_probe(struct udevice *dev)
#endif
}
eth_write_hwaddr(dev);
return 0;
}