This commit is contained in:
Tom Rini 2019-12-09 13:48:22 -05:00
commit ac1ca99926
52 changed files with 1316 additions and 528 deletions

View File

@ -99,6 +99,15 @@
device-name = "cpm-mdio";
};
cpm_xmdio: mdio@12a600 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "marvell,xmdio";
reg = <0x12a600 0x16>;
status = "disabled";
device-name = "cpm-xmdio";
};
cpm_syscon0: system-controller@440000 {
compatible = "marvell,cp110-system-controller0",
"syscon";

View File

@ -99,6 +99,15 @@
device-name = "cps-mdio";
};
cps_xmdio: mdio@12a600 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "marvell,xmdio";
reg = <0x12a600 0x16>;
status = "disabled";
device-name = "cps-xmdio";
};
cps_syscon0: system-controller@440000 {
compatible = "marvell,cp110-system-controller0",
"syscon";

View File

@ -336,13 +336,12 @@
reg = <0>;
/* TODO: phy reset: TCA9555RTWR(i2c:0x21)[p04].GPIO_MCU_RGMII_RSTN */
ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_00_NS>;
ti,tx-internal-delay = <DP83867_RGMIIDCTL_2_00_NS>;
ti,fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_4_B_NIB>;
};
};
&cpsw_port1 {
phy-mode = "rgmii-id";
phy-mode = "rgmii-rxid";
phy-handle = <&phy0>;
};

View File

@ -3,11 +3,18 @@
* Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/
*/
#include <dt-bindings/dma/k3-udma.h>
#include <dt-bindings/net/ti-dp83867.h>
/ {
chosen {
stdout-path = "serial2:115200n8";
tick-timer = &timer1;
};
aliases {
ethernet0 = &cpsw_port1;
};
};
&cbass_main{
@ -24,6 +31,184 @@
clock-frequency = <25000000>;
u-boot,dm-spl;
};
mcu_conf: scm_conf@40f00000 {
compatible = "syscon", "simple-mfd";
reg = <0x0 0x40f00000 0x0 0x20000>;
#address-cells = <1>;
#size-cells = <1>;
ranges = <0x0 0x0 0x40f00000 0x20000>;
phy_sel: cpsw-phy-sel@4040 {
compatible = "ti,am654-cpsw-phy-sel";
reg = <0x4040 0x4>;
reg-names = "gmii-sel";
};
};
cbass_mcu_navss: mcu_navss {
compatible = "simple-bus";
#address-cells = <2>;
#size-cells = <2>;
dma-coherent;
dma-ranges;
ranges;
ti,sci-dev-id = <232>;
u-boot,dm-spl;
mcu_ringacc: ringacc@2b800000 {
compatible = "ti,am654-navss-ringacc";
reg = <0x0 0x2b800000 0x0 0x400000>,
<0x0 0x2b000000 0x0 0x400000>,
<0x0 0x28590000 0x0 0x100>,
<0x0 0x2a500000 0x0 0x40000>;
reg-names = "rt", "fifos", "proxy_gcfg", "proxy_target";
ti,num-rings = <286>;
ti,sci-rm-range-gp-rings = <0x1>; /* GP ring range */
ti,sci = <&dmsc>;
ti,sci-dev-id = <235>;
u-boot,dm-spl;
};
mcu_udmap: udmap@31150000 {
compatible = "ti,j721e-navss-mcu-udmap";
reg = <0x0 0x285c0000 0x0 0x100>,
<0x0 0x2a800000 0x0 0x40000>,
<0x0 0x2aa00000 0x0 0x40000>;
reg-names = "gcfg", "rchanrt", "tchanrt";
#dma-cells = <3>;
ti,ringacc = <&mcu_ringacc>;
ti,psil-base = <0x6000>;
ti,sci = <&dmsc>;
ti,sci-dev-id = <236>;
ti,sci-rm-range-tchan = <0x0d>, /* TX_CHAN */
<0x0f>; /* TX_HCHAN */
ti,sci-rm-range-rchan = <0x0a>, /* RX_CHAN */
<0x0b>; /* RX_HCHAN */
ti,sci-rm-range-rflow = <0x00>; /* GP RFLOW */
u-boot,dm-spl;
};
};
mcu_cpsw: ethernet@046000000 {
compatible = "ti,j721e-cpsw-nuss";
#address-cells = <2>;
#size-cells = <2>;
reg = <0x0 0x46000000 0x0 0x200000>;
reg-names = "cpsw_nuss";
ranges;
dma-coherent;
clocks = <&k3_clks 18 22>;
clock-names = "fck";
power-domains = <&k3_pds 18 TI_SCI_PD_EXCLUSIVE>;
ti,psil-base = <0x7000>;
cpsw-phy-sel = <&phy_sel>;
dmas = <&mcu_udmap &mcu_cpsw 0 UDMA_DIR_TX>,
<&mcu_udmap &mcu_cpsw 1 UDMA_DIR_TX>,
<&mcu_udmap &mcu_cpsw 2 UDMA_DIR_TX>,
<&mcu_udmap &mcu_cpsw 3 UDMA_DIR_TX>,
<&mcu_udmap &mcu_cpsw 4 UDMA_DIR_TX>,
<&mcu_udmap &mcu_cpsw 5 UDMA_DIR_TX>,
<&mcu_udmap &mcu_cpsw 6 UDMA_DIR_TX>,
<&mcu_udmap &mcu_cpsw 7 UDMA_DIR_TX>,
<&mcu_udmap &mcu_cpsw 0 UDMA_DIR_RX>;
dma-names = "tx0", "tx1", "tx2", "tx3",
"tx4", "tx5", "tx6", "tx7",
"rx";
ports {
#address-cells = <1>;
#size-cells = <0>;
host: host@0 {
reg = <0>;
ti,label = "host";
};
cpsw_port1: port@1 {
reg = <1>;
ti,mac-only;
ti,label = "port1";
ti,syscon-efuse = <&mcu_conf 0x200>;
};
};
davinci_mdio: mdio {
#address-cells = <1>;
#size-cells = <0>;
bus_freq = <1000000>;
};
cpts {
clocks = <&k3_clks 18 2>;
clock-names = "cpts";
interrupts-extended = <&gic500 GIC_SPI 858 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "cpts";
ti,cpts-ext-ts-inputs = <4>;
ti,cpts-periodic-outputs = <2>;
};
ti,psil-config0 {
linux,udma-mode = <UDMA_PKT_MODE>;
statictr-type = <PSIL_STATIC_TR_NONE>;
ti,needs-epib;
ti,psd-size = <16>;
};
ti,psil-config1 {
linux,udma-mode = <UDMA_PKT_MODE>;
statictr-type = <PSIL_STATIC_TR_NONE>;
ti,needs-epib;
ti,psd-size = <16>;
};
ti,psil-config2 {
linux,udma-mode = <UDMA_PKT_MODE>;
statictr-type = <PSIL_STATIC_TR_NONE>;
ti,needs-epib;
ti,psd-size = <16>;
};
ti,psil-config3 {
linux,udma-mode = <UDMA_PKT_MODE>;
statictr-type = <PSIL_STATIC_TR_NONE>;
ti,needs-epib;
ti,psd-size = <16>;
};
ti,psil-config4 {
linux,udma-mode = <UDMA_PKT_MODE>;
statictr-type = <PSIL_STATIC_TR_NONE>;
ti,needs-epib;
ti,psd-size = <16>;
};
ti,psil-config5 {
linux,udma-mode = <UDMA_PKT_MODE>;
statictr-type = <PSIL_STATIC_TR_NONE>;
ti,needs-epib;
ti,psd-size = <16>;
};
ti,psil-config6 {
linux,udma-mode = <UDMA_PKT_MODE>;
statictr-type = <PSIL_STATIC_TR_NONE>;
ti,needs-epib;
ti,psd-size = <16>;
};
ti,psil-config7 {
linux,udma-mode = <UDMA_PKT_MODE>;
statictr-type = <PSIL_STATIC_TR_NONE>;
ti,needs-epib;
ti,psd-size = <16>;
};
};
};
&secure_proxy_main {
@ -52,6 +237,29 @@
&wkup_pmx0 {
u-boot,dm-spl;
mcu_cpsw_pins_default: mcu_cpsw_pins_default {
pinctrl-single,pins = <
J721E_WKUP_IOPAD(0x0058, PIN_OUTPUT, 0) /* (N4) MCU_RGMII1_TX_CTL */
J721E_WKUP_IOPAD(0x005c, PIN_INPUT, 0) /* (N5) MCU_RGMII1_RX_CTL */
J721E_WKUP_IOPAD(0x0060, PIN_OUTPUT, 0) /* (M2) MCU_RGMII1_TD3 */
J721E_WKUP_IOPAD(0x0064, PIN_OUTPUT, 0) /* (M3) MCU_RGMII1_TD2 */
J721E_WKUP_IOPAD(0x0068, PIN_OUTPUT, 0) /* (M4) MCU_RGMII1_TD1 */
J721E_WKUP_IOPAD(0x006c, PIN_OUTPUT, 0) /* (M5) MCU_RGMII1_TD0 */
J721E_WKUP_IOPAD(0x0078, PIN_INPUT, 0) /* (L2) MCU_RGMII1_RD3 */
J721E_WKUP_IOPAD(0x007c, PIN_INPUT, 0) /* (L5) MCU_RGMII1_RD2 */
J721E_WKUP_IOPAD(0x0080, PIN_INPUT, 0) /* (M6) MCU_RGMII1_RD1 */
J721E_WKUP_IOPAD(0x0084, PIN_INPUT, 0) /* (L6) MCU_RGMII1_RD0 */
J721E_WKUP_IOPAD(0x0070, PIN_INPUT, 0) /* (N1) MCU_RGMII1_TXC */
J721E_WKUP_IOPAD(0x0074, PIN_INPUT, 0) /* (M1) MCU_RGMII1_RXC */
>;
};
mcu_mdio_pins_default: mcu_mdio1_pins_default {
pinctrl-single,pins = <
J721E_WKUP_IOPAD(0x008c, PIN_OUTPUT, 0) /* (L1) MCU_MDIO0_MDC */
J721E_WKUP_IOPAD(0x0088, PIN_INPUT, 0) /* (L4) MCU_MDIO0_MDIO */
>;
};
};
&main_pmx0 {
@ -73,3 +281,33 @@
&main_sdhci1 {
u-boot,dm-spl;
};
&mcu_cpsw {
pinctrl-names = "default";
pinctrl-0 = <&mcu_cpsw_pins_default &mcu_mdio_pins_default>;
};
&davinci_mdio {
phy0: ethernet-phy@0 {
reg = <0>;
ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_00_NS>;
ti,fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_4_B_NIB>;
};
};
&cpsw_port1 {
phy-mode = "rgmii-rxid";
phy-handle = <&phy0>;
};
&mcu_cpsw {
reg = <0x0 0x46000000 0x0 0x200000>,
<0x0 0x40f00200 0x0 0x2>;
reg-names = "cpsw_nuss", "mac_efuse";
cpsw-phy-sel@40f04040 {
compatible = "ti,am654-cpsw-phy-sel";
reg= <0x0 0x40f04040 0x0 0x4>;
reg-names = "gmii-sel";
};
};

View File

@ -495,7 +495,7 @@ static int cboot_get_ethaddr_legacy(const void *fdt, uint8_t mac[ETH_ALEN])
return -ENOENT;
}
eth_parse_enetaddr(prop, mac);
string_to_enetaddr(prop, mac);
if (!is_valid_ethaddr(mac)) {
printf("Invalid MAC address: %s\n", prop);

View File

@ -94,7 +94,7 @@ static void set_mac_to_sh_giga_eth_register(int channel, char *mac_string)
unsigned char mac[6];
unsigned long val;
eth_parse_enetaddr(mac_string, mac);
string_to_enetaddr(mac_string, mac);
if (!channel)
ether = GETHER0_MAC_BASE;

View File

@ -101,7 +101,7 @@ static void set_mac_to_sh_giga_eth_register(int channel, char *mac_string)
unsigned char mac[6];
unsigned long val;
eth_parse_enetaddr(mac_string, mac);
string_to_enetaddr(mac_string, mac);
if (!channel)
ether = GETHER0_MAC_BASE;

View File

@ -141,7 +141,7 @@ static void set_mac_to_sh_eth_register(int channel, char *mac_string)
unsigned char mac[6];
unsigned long val;
eth_parse_enetaddr(mac_string, mac);
string_to_enetaddr(mac_string, mac);
if (!channel)
ether = ETHER0_MAC_BASE;
@ -160,7 +160,7 @@ static void set_mac_to_sh_giga_eth_register(int channel, char *mac_string)
unsigned char mac[6];
unsigned long val;
eth_parse_enetaddr(mac_string, mac);
string_to_enetaddr(mac_string, mac);
if (!channel)
ether = GETHER0_MAC_BASE;

View File

@ -1473,8 +1473,22 @@ config CMD_NFS
config CMD_MII
bool "mii"
imply CMD_MDIO
help
Enable MII utility commands.
If set, allows 802.3(clause 22) MII Management functions interface access
The management interface specified in Clause 22 provides
a simple, two signal, serial interface to connect a
Station Management entity and a managed PHY for providing access
to management parameters and services.
The interface is referred to as the MII management interface.
config CMD_MDIO
bool "mdio"
depends on PHYLIB
help
If set, allows Enable 802.3(clause 45) MDIO interface registers access
The MDIO interface is orthogonal to the MII interface and extends
it by adding access to more registers through indirect addressing.
config CMD_PING
bool "ping"

View File

@ -89,9 +89,7 @@ obj-$(CONFIG_CMD_MEMORY) += mem.o
obj-$(CONFIG_CMD_IO) += io.o
obj-$(CONFIG_CMD_MFSL) += mfsl.o
obj-$(CONFIG_CMD_MII) += mii.o
ifdef CONFIG_PHYLIB
obj-$(CONFIG_CMD_MII) += mdio.o
endif
obj-$(CONFIG_CMD_MDIO) += mdio.o
obj-$(CONFIG_CMD_MISC) += misc.o
obj-$(CONFIG_CMD_MMC) += mmc.o
obj-$(CONFIG_MP) += mp.o

View File

@ -864,7 +864,7 @@ static int keyword_match_mac_addr(enum ethsw_keyword_id key_id, int argc,
return 0;
}
eth_parse_enetaddr(argv[*argc_nr + 1], parsed_cmd->ethaddr);
string_to_enetaddr(argv[*argc_nr + 1], parsed_cmd->ethaddr);
if (is_broadcast_ethaddr(parsed_cmd->ethaddr)) {
memset(parsed_cmd->ethaddr, 0xFF, sizeof(parsed_cmd->ethaddr));

View File

@ -361,7 +361,7 @@ ulong env_get_hex(const char *varname, ulong default_val)
int eth_env_get_enetaddr(const char *name, uint8_t *enetaddr)
{
eth_parse_enetaddr(env_get(name), enetaddr);
string_to_enetaddr(env_get(name), enetaddr);
return is_valid_ethaddr(enetaddr);
}

View File

@ -22,7 +22,7 @@
#include "pxe_utils.h"
#define MAX_TFTP_PATH_LEN 127
#define MAX_TFTP_PATH_LEN 512
bool is_pxe;

View File

@ -51,6 +51,7 @@ CONFIG_DEFAULT_DEVICE_TREE="k3-j721e-common-proc-board"
CONFIG_SPL_MULTI_DTB_FIT=y
CONFIG_SPL_MULTI_DTB_FIT_NO_COMPRESSION=y
CONFIG_SYS_RELOC_GD_ENV_ADDR=y
CONFIG_NET_RANDOM_ETHADDR=y
CONFIG_DM=y
CONFIG_SPL_DM=y
CONFIG_SPL_DM_SEQ_ALIAS=y
@ -61,6 +62,8 @@ CONFIG_SPL_OF_TRANSLATE=y
CONFIG_CLK=y
CONFIG_SPL_CLK=y
CONFIG_CLK_TI_SCI=y
CONFIG_DMA_CHANNELS=y
CONFIG_TI_K3_NAVSS_UDMA=y
CONFIG_TI_SCI_PROTOCOL=y
CONFIG_DM_MAILBOX=y
CONFIG_K3_SEC_PROXY=y
@ -79,6 +82,10 @@ CONFIG_SYS_FLASH_CFI=y
CONFIG_HBMC_AM654=y
CONFIG_DM_SPI_FLASH=y
CONFIG_SPI_FLASH_STMICRO=y
CONFIG_PHY_TI=y
CONFIG_PHY_FIXED=y
CONFIG_DM_ETH=y
CONFIG_TI_AM65_CPSW_NUSS=y
CONFIG_PINCTRL=y
# CONFIG_PINCTRL_GENERIC is not set
CONFIG_SPL_PINCTRL=y
@ -93,6 +100,7 @@ CONFIG_RESET_TI_SCI=y
CONFIG_SCSI=y
CONFIG_DM_SCSI=y
CONFIG_DM_SERIAL=y
CONFIG_SOC_TI=y
CONFIG_SPI=y
CONFIG_DM_SPI=y
CONFIG_CADENCE_QSPI=y

View File

@ -76,12 +76,12 @@ To assist in the management of these layers, a few helper functions exist. You
should use these rather than attempt to do any kind of parsing/manipulation
yourself as many common errors have arisen in the past.
* void eth_parse_enetaddr(const char *addr, uchar *enetaddr);
* void string_to_enetaddr(const char *addr, uchar *enetaddr);
Convert a string representation of a MAC address to the binary version.
char *addr = "00:11:22:33:44:55";
uchar enetaddr[6];
eth_parse_enetaddr(addr, enetaddr);
string_to_enetaddr(addr, enetaddr);
/* enetaddr now equals { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55 } */
* int eth_env_get_enetaddr(char *name, uchar *enetaddr);

View File

@ -0,0 +1,25 @@
PHY nodes for Aquantia devices.
This text describes properties that are applicable to Aquantia PHY nodes in
addition to the bindings in phy.txt.
Aquantia PHYs allow some flexibility in the way they are wired in a system,
they allow MDI pins to be reversed, LEDs linked up in different weays, have an
I2C slave interface that can be used for debug. Normally the configuration
corresponding to these is driven by the PHY firmware with the downside that
a custom firmware is needed for each integration of a PHY.
Several optional bindings are defined that allow these configuration points to
be driven by the PHY driver and reduce dependency on specific FW versions.
Optional properties:
mdi-reversal: 0 or 1 indicating that reversal must be disabled/enabled.
Firmware default is used if the property is missing.
smb-addr: I2C/SMBus address to use, firmware default is used if the property
is missing.
Example node:
phy@00 {
reg = <0x00>;
mdi-reversal = <1>;
smb-addr = <0x25>;
};

View File

@ -0,0 +1,24 @@
PHY nodes
If the device tree is used to describe networking interfaces, U-Boot expects a
node for each PHY. Parent node for such a PHY node is expected to correspond to
a MDIO bus and the bus is used to access the PHY.
Required properties:
- reg : The ID number for the phy, usually a small integer
Example:
ethernet-phy@0 {
compatible = "ethernet-phy-id0141.0e90", "ethernet-phy-ieee802.3-c22";
interrupt-parent = <&PIC>;
interrupts = <35 IRQ_TYPE_EDGE_RISING>;
reg = <0>;
resets = <&rst 8>;
reset-names = "phy";
reset-gpios = <&gpio1 4 GPIO_ACTIVE_LOW>;
reset-assert-us = <1000>;
reset-deassert-us = <2000>;
};

View File

@ -12,8 +12,10 @@ Required properties:
compensate for the board being designed with the lanes swapped.
- enet-phy-no-lane-swap - Indicates that PHY will disable swap of the
TX/RX lanes.
- ti,clk-output-sel - Clock output select - see dt-bindings/net/ti-dp83867.h
for applicable values
- ti,clk-output-sel - Muxing option for CLK_OUT pin. See dt-bindings/net/ti-dp83867.h
for applicable values. The CLK_OUT pin can also
be disabled by this property. When omitted, the
PHY's default will be left as is.
Default child nodes are standard Ethernet PHY device
nodes as described in doc/devicetree/bindings/net/ethernet.txt

View File

@ -187,6 +187,18 @@ int dma_send(struct dma *dma, void *src, size_t len, void *metadata)
return ops->send(dma, src, len, metadata);
}
int dma_get_cfg(struct dma *dma, u32 cfg_id, void **cfg_data)
{
struct dma_ops *ops = dma_dev_ops(dma->dev);
debug("%s(dma=%p)\n", __func__, dma);
if (!ops->get_cfg)
return -ENOSYS;
return ops->get_cfg(dma, cfg_id, cfg_data);
}
#endif /* CONFIG_DMA_CHANNELS */
int dma_get_device(u32 transfer_type, struct udevice **devp)

View File

@ -104,6 +104,8 @@ struct udma_chan {
struct udma_rchan *rchan;
struct udma_rflow *rflow;
struct ti_udma_drv_chan_cfg_data cfg_data;
u32 bcnt; /* number of bytes completed since the start of the channel */
bool pkt_mode; /* TR or packet */
@ -1407,6 +1409,11 @@ static int udma_request(struct dma *dma)
uc->desc_rx_cur = 0;
uc->num_rx_bufs = 0;
if (uc->dir == DMA_DEV_TO_MEM) {
uc->cfg_data.flow_id_base = uc->rflow->id;
uc->cfg_data.flow_id_cnt = 1;
}
return 0;
}
@ -1689,6 +1696,26 @@ int udma_prepare_rcv_buf(struct dma *dma, void *dst, size_t size)
return 0;
}
static int udma_get_cfg(struct dma *dma, u32 id, void **data)
{
struct udma_dev *ud = dev_get_priv(dma->dev);
struct udma_chan *uc;
if (dma->id >= (ud->rchan_cnt + ud->tchan_cnt)) {
dev_err(dma->dev, "invalid dma ch_id %lu\n", dma->id);
return -EINVAL;
}
switch (id) {
case TI_UDMA_CHAN_PRIV_INFO:
uc = &ud->channels[dma->id];
*data = &uc->cfg_data;
return 0;
}
return -EINVAL;
}
static const struct dma_ops udma_ops = {
.transfer = udma_transfer,
.of_xlate = udma_of_xlate,
@ -1699,10 +1726,12 @@ static const struct dma_ops udma_ops = {
.send = udma_send,
.receive = udma_receive,
.prepare_rcv_buf = udma_prepare_rcv_buf,
.get_cfg = udma_get_cfg,
};
static const struct udevice_id udma_ids[] = {
{ .compatible = "ti,k3-navss-udmap" },
{ .compatible = "ti,j721e-navss-mcu-udmap" },
{ }
};

View File

@ -298,6 +298,8 @@ config MVPP2
bool "Marvell Armada 375/7K/8K network interface support"
depends on ARMADA_375 || ARMADA_8K
select PHYLIB
select MVMDIO
select DM_MDIO
help
This driver supports the network interface units in the
Marvell ARMADA 375, 7K and 8K SoCs.

View File

@ -156,19 +156,14 @@ static void enetc_start_pcs(struct udevice *dev)
priv->if_type = PHY_INTERFACE_MODE_NONE;
/* check internal mdio capability, not all ports need it */
/* register internal MDIO for debug purposes */
if (enetc_read_port(priv, ENETC_PCAPR0) & ENETC_PCAPRO_MDIO) {
/*
* set up internal MDIO, this is part of ETH PCI function and is
* used to access serdes / internal SoC PHYs.
* We don't currently register it as a MDIO bus as it goes away
* when the interface is removed, so it can't practically be
* used in the console.
*/
priv->imdio.read = enetc_mdio_read;
priv->imdio.write = enetc_mdio_write;
priv->imdio.priv = priv->port_regs + ENETC_PM_IMDIO_BASE;
strncpy(priv->imdio.name, dev->name, MDIO_NAME_LEN);
if (!miiphy_get_dev_by_name(priv->imdio.name))
mdio_register(&priv->imdio);
}
if (!ofnode_valid(dev->node)) {
@ -190,70 +185,30 @@ static void enetc_start_pcs(struct udevice *dev)
case PHY_INTERFACE_MODE_SGMII_2500:
enetc_init_sgmii(dev);
break;
case PHY_INTERFACE_MODE_RGMII:
case PHY_INTERFACE_MODE_RGMII_ID:
case PHY_INTERFACE_MODE_RGMII_RXID:
case PHY_INTERFACE_MODE_RGMII_TXID:
enetc_init_rgmii(dev);
break;
case PHY_INTERFACE_MODE_XGMII:
case PHY_INTERFACE_MODE_USXGMII:
case PHY_INTERFACE_MODE_XFI:
enetc_init_sxgmii(dev);
break;
};
}
/* Configure the actual/external ethernet PHY, if one is found */
static void enetc_start_phy(struct udevice *dev)
static void enetc_config_phy(struct udevice *dev)
{
struct enetc_priv *priv = dev_get_priv(dev);
struct udevice *miidev;
struct phy_device *phy;
u32 phandle, phy_id;
ofnode phy_node;
int supported;
if (!ofnode_valid(dev->node)) {
enetc_dbg(dev, "no enetc ofnode found, skipping PHY set-up\n");
return;
}
priv->phy = dm_eth_phy_connect(dev);
if (ofnode_read_u32(dev->node, "phy-handle", &phandle)) {
enetc_dbg(dev, "phy-handle not found, skipping PHY set-up\n");
if (!priv->phy)
return;
}
phy_node = ofnode_get_by_phandle(phandle);
if (!ofnode_valid(phy_node)) {
enetc_dbg(dev, "invalid phy node, skipping PHY set-up\n");
return;
}
enetc_dbg(dev, "phy node: %s\n", ofnode_get_name(phy_node));
supported = PHY_GBIT_FEATURES | SUPPORTED_2500baseX_Full;
priv->phy->supported &= supported;
priv->phy->advertising &= supported;
if (ofnode_read_u32(phy_node, "reg", &phy_id)) {
enetc_dbg(dev,
"missing reg in PHY node, skipping PHY set-up\n");
return;
}
if (uclass_get_device_by_ofnode(UCLASS_MDIO,
ofnode_get_parent(phy_node),
&miidev)) {
enetc_dbg(dev, "can't find MDIO bus for node %s\n",
ofnode_get_name(ofnode_get_parent(phy_node)));
return;
}
phy = dm_mdio_phy_connect(miidev, phy_id, dev, priv->if_type);
if (!phy) {
enetc_dbg(dev, "dm_mdio_phy_connect returned null\n");
return;
}
supported = GENMASK(6, 0); /* speeds up to 1G & AN */
phy->advertising = phy->supported & supported;
phy->node = phy_node;
phy_config(phy);
phy_startup(phy);
phy_config(priv->phy);
}
/*
@ -292,6 +247,9 @@ static int enetc_probe(struct udevice *dev)
dm_pci_clrset_config16(dev, PCI_COMMAND, 0, PCI_COMMAND_MEMORY);
enetc_start_pcs(dev);
enetc_config_phy(dev);
return 0;
}
@ -467,8 +425,14 @@ static int enetc_start(struct udevice *dev)
enetc_setup_tx_bdr(dev);
enetc_setup_rx_bdr(dev);
enetc_start_pcs(dev);
enetc_start_phy(dev);
if (priv->if_type == PHY_INTERFACE_MODE_RGMII ||
priv->if_type == PHY_INTERFACE_MODE_RGMII_ID ||
priv->if_type == PHY_INTERFACE_MODE_RGMII_RXID ||
priv->if_type == PHY_INTERFACE_MODE_RGMII_TXID)
enetc_init_rgmii(dev);
if (priv->phy)
phy_startup(priv->phy);
return 0;
}
@ -482,6 +446,10 @@ static void enetc_stop(struct udevice *dev)
{
/* FLR is sufficient to quiesce the device */
dm_pci_flr(dev);
/* leave the BARs accessible after we stop, this is needed to use
* internal MDIO in command line.
*/
dm_pci_clrset_config16(dev, PCI_COMMAND, 0, PCI_COMMAND_MEMORY);
}
/*

View File

@ -154,6 +154,7 @@ struct enetc_priv {
int if_type;
struct mii_dev imdio;
struct phy_device *phy;
};
/* register accessors */

View File

@ -17,8 +17,13 @@
static void enetc_mdio_wait_bsy(struct enetc_mdio_priv *priv)
{
while (enetc_read(priv, ENETC_MDIO_CFG) & ENETC_EMDIO_CFG_BSY)
int to = 10000;
while ((enetc_read(priv, ENETC_MDIO_CFG) & ENETC_EMDIO_CFG_BSY) &&
--to)
cpu_relax();
if (!to)
printf("T");
}
int enetc_mdio_read_priv(struct enetc_mdio_priv *priv, int addr, int devad,

View File

@ -72,8 +72,8 @@ enum ftgmac100_model {
struct ftgmac100_data {
struct ftgmac100 *iobase;
struct ftgmac100_txdes txdes[PKTBUFSTX];
struct ftgmac100_rxdes rxdes[PKTBUFSRX];
struct ftgmac100_txdes txdes[PKTBUFSTX] __aligned(ARCH_DMA_MINALIGN);
struct ftgmac100_rxdes rxdes[PKTBUFSRX] __aligned(ARCH_DMA_MINALIGN);
int tx_index;
int rx_index;
@ -310,7 +310,7 @@ static int ftgmac100_start(struct udevice *dev)
}
priv->txdes[PKTBUFSTX - 1].txdes0 = priv->txdes0_edotr_mask;
start = (ulong)&priv->txdes[0];
start = ((ulong)&priv->txdes[0]) & ~(ARCH_DMA_MINALIGN - 1);
end = start + roundup(sizeof(priv->txdes), ARCH_DMA_MINALIGN);
flush_dcache_range(start, end);
@ -320,7 +320,7 @@ static int ftgmac100_start(struct udevice *dev)
}
priv->rxdes[PKTBUFSRX - 1].rxdes0 = priv->rxdes0_edorr_mask;
start = (ulong)&priv->rxdes[0];
start = ((ulong)&priv->rxdes[0]) & ~(ARCH_DMA_MINALIGN - 1);
end = start + roundup(sizeof(priv->rxdes), ARCH_DMA_MINALIGN);
flush_dcache_range(start, end);
@ -370,7 +370,7 @@ static int ftgmac100_free_pkt(struct udevice *dev, uchar *packet, int length)
{
struct ftgmac100_data *priv = dev_get_priv(dev);
struct ftgmac100_rxdes *curr_des = &priv->rxdes[priv->rx_index];
ulong des_start = (ulong)curr_des;
ulong des_start = ((ulong)curr_des) & ~(ARCH_DMA_MINALIGN - 1);
ulong des_end = des_start +
roundup(sizeof(*curr_des), ARCH_DMA_MINALIGN);
@ -392,7 +392,7 @@ static int ftgmac100_recv(struct udevice *dev, int flags, uchar **packetp)
struct ftgmac100_data *priv = dev_get_priv(dev);
struct ftgmac100_rxdes *curr_des = &priv->rxdes[priv->rx_index];
unsigned short rxlen;
ulong des_start = (ulong)curr_des;
ulong des_start = ((ulong)curr_des) & ~(ARCH_DMA_MINALIGN - 1);
ulong des_end = des_start +
roundup(sizeof(*curr_des), ARCH_DMA_MINALIGN);
ulong data_start = curr_des->rxdes3;
@ -427,7 +427,7 @@ static int ftgmac100_recv(struct udevice *dev, int flags, uchar **packetp)
static u32 ftgmac100_read_txdesc(const void *desc)
{
const struct ftgmac100_txdes *txdes = desc;
ulong des_start = (ulong)txdes;
ulong des_start = ((ulong)txdes) & ~(ARCH_DMA_MINALIGN - 1);
ulong des_end = des_start + roundup(sizeof(*txdes), ARCH_DMA_MINALIGN);
invalidate_dcache_range(des_start, des_end);
@ -445,7 +445,7 @@ static int ftgmac100_send(struct udevice *dev, void *packet, int length)
struct ftgmac100_data *priv = dev_get_priv(dev);
struct ftgmac100 *ftgmac100 = priv->iobase;
struct ftgmac100_txdes *curr_des = &priv->txdes[priv->tx_index];
ulong des_start = (ulong)curr_des;
ulong des_start = ((ulong)curr_des) & ~(ARCH_DMA_MINALIGN - 1);
ulong des_end = des_start +
roundup(sizeof(*curr_des), ARCH_DMA_MINALIGN);
ulong data_start;

View File

@ -165,7 +165,8 @@ static int gem_is_gigabit_capable(struct macb_device *macb)
return macb_is_gem(macb) && !cpu_is_sama5d2() && !cpu_is_sama5d4();
}
static void macb_mdio_write(struct macb_device *macb, u8 reg, u16 value)
static void macb_mdio_write(struct macb_device *macb, u8 phy_adr, u8 reg,
u16 value)
{
unsigned long netctl;
unsigned long netstat;
@ -177,7 +178,7 @@ static void macb_mdio_write(struct macb_device *macb, u8 reg, u16 value)
frame = (MACB_BF(SOF, 1)
| MACB_BF(RW, 1)
| MACB_BF(PHYA, macb->phy_addr)
| MACB_BF(PHYA, phy_adr)
| MACB_BF(REGA, reg)
| MACB_BF(CODE, 2)
| MACB_BF(DATA, value));
@ -192,7 +193,7 @@ static void macb_mdio_write(struct macb_device *macb, u8 reg, u16 value)
macb_writel(macb, NCR, netctl);
}
static u16 macb_mdio_read(struct macb_device *macb, u8 reg)
static u16 macb_mdio_read(struct macb_device *macb, u8 phy_adr, u8 reg)
{
unsigned long netctl;
unsigned long netstat;
@ -204,7 +205,7 @@ static u16 macb_mdio_read(struct macb_device *macb, u8 reg)
frame = (MACB_BF(SOF, 1)
| MACB_BF(RW, 2)
| MACB_BF(PHYA, macb->phy_addr)
| MACB_BF(PHYA, phy_adr)
| MACB_BF(REGA, reg)
| MACB_BF(CODE, 2));
macb_writel(macb, MAN, frame);
@ -240,11 +241,8 @@ int macb_miiphy_read(struct mii_dev *bus, int phy_adr, int devad, int reg)
struct macb_device *macb = to_macb(dev);
#endif
if (macb->phy_addr != phy_adr)
return -1;
arch_get_mdio_control(bus->name);
value = macb_mdio_read(macb, reg);
value = macb_mdio_read(macb, phy_adr, reg);
return value;
}
@ -260,11 +258,8 @@ int macb_miiphy_write(struct mii_dev *bus, int phy_adr, int devad, int reg,
struct macb_device *macb = to_macb(dev);
#endif
if (macb->phy_addr != phy_adr)
return -1;
arch_get_mdio_control(bus->name);
macb_mdio_write(macb, reg, value);
macb_mdio_write(macb, phy_adr, reg, value);
return 0;
}
@ -451,13 +446,13 @@ static void macb_phy_reset(struct macb_device *macb, const char *name)
u16 status, adv;
adv = ADVERTISE_CSMA | ADVERTISE_ALL;
macb_mdio_write(macb, MII_ADVERTISE, adv);
macb_mdio_write(macb, macb->phy_addr, MII_ADVERTISE, adv);
printf("%s: Starting autonegotiation...\n", name);
macb_mdio_write(macb, MII_BMCR, (BMCR_ANENABLE
macb_mdio_write(macb, macb->phy_addr, MII_BMCR, (BMCR_ANENABLE
| BMCR_ANRESTART));
for (i = 0; i < MACB_AUTONEG_TIMEOUT / 100; i++) {
status = macb_mdio_read(macb, MII_BMSR);
status = macb_mdio_read(macb, macb->phy_addr, MII_BMSR);
if (status & BMSR_ANEGCOMPLETE)
break;
udelay(100);
@ -478,7 +473,7 @@ static int macb_phy_find(struct macb_device *macb, const char *name)
/* Search for PHY... */
for (i = 0; i < 32; i++) {
macb->phy_addr = i;
phy_id = macb_mdio_read(macb, MII_PHYSID1);
phy_id = macb_mdio_read(macb, macb->phy_addr, MII_PHYSID1);
if (phy_id != 0xffff) {
printf("%s: PHY present at %d\n", name, i);
return 0;
@ -596,7 +591,7 @@ static int macb_phy_init(struct macb_device *macb, const char *name)
return ret;
/* Check if the PHY is up to snuff... */
phy_id = macb_mdio_read(macb, MII_PHYSID1);
phy_id = macb_mdio_read(macb, macb->phy_addr, MII_PHYSID1);
if (phy_id == 0xffff) {
printf("%s: No PHY present\n", name);
return -ENODEV;
@ -619,13 +614,13 @@ static int macb_phy_init(struct macb_device *macb, const char *name)
phy_config(macb->phydev);
#endif
status = macb_mdio_read(macb, MII_BMSR);
status = macb_mdio_read(macb, macb->phy_addr, MII_BMSR);
if (!(status & BMSR_LSTATUS)) {
/* Try to re-negotiate if we don't have link already. */
macb_phy_reset(macb, name);
for (i = 0; i < MACB_AUTONEG_TIMEOUT / 100; i++) {
status = macb_mdio_read(macb, MII_BMSR);
status = macb_mdio_read(macb, macb->phy_addr, MII_BMSR);
if (status & BMSR_LSTATUS) {
/*
* Delay a bit after the link is established,
@ -646,7 +641,7 @@ static int macb_phy_init(struct macb_device *macb, const char *name)
/* First check for GMAC and that it is GiB capable */
if (gem_is_gigabit_capable(macb)) {
lpa = macb_mdio_read(macb, MII_STAT1000);
lpa = macb_mdio_read(macb, macb->phy_addr, MII_STAT1000);
if (lpa & (LPA_1000FULL | LPA_1000HALF | LPA_1000XFULL |
LPA_1000XHALF)) {
@ -680,8 +675,8 @@ static int macb_phy_init(struct macb_device *macb, const char *name)
}
/* fall back for EMAC checking */
adv = macb_mdio_read(macb, MII_ADVERTISE);
lpa = macb_mdio_read(macb, MII_LPA);
adv = macb_mdio_read(macb, macb->phy_addr, MII_ADVERTISE);
lpa = macb_mdio_read(macb, macb->phy_addr, MII_LPA);
media = mii_nway_result(lpa & adv);
speed = (media & (ADVERTISE_100FULL | ADVERTISE_100HALF)
? 1 : 0);

View File

@ -33,6 +33,7 @@
#include <linux/mbus.h>
#include <asm-generic/gpio.h>
#include <fdt_support.h>
#include <linux/mdio.h>
DECLARE_GLOBAL_DATA_PTR;
@ -63,8 +64,6 @@ do { \
#define MTU 1500
#define RX_BUFFER_SIZE (ALIGN(MTU + WRAP, ARCH_DMA_MINALIGN))
#define MVPP2_SMI_TIMEOUT 10000
/* RX Fifo Registers */
#define MVPP2_RX_DATA_FIFO_SIZE_REG(port) (0x00 + 4 * (port))
#define MVPP2_RX_ATTR_FIFO_SIZE_REG(port) (0x20 + 4 * (port))
@ -491,23 +490,8 @@ do { \
#define MVPP2_QUEUE_NEXT_DESC(q, index) \
(((index) < (q)->last_desc) ? ((index) + 1) : 0)
/* SMI: 0xc0054 -> offset 0x54 to lms_base */
#define MVPP21_SMI 0x0054
/* PP2.2: SMI: 0x12a200 -> offset 0x1200 to iface_base */
#define MVPP22_SMI 0x1200
#define MVPP2_PHY_REG_MASK 0x1f
/* SMI register fields */
#define MVPP2_SMI_DATA_OFFS 0 /* Data */
#define MVPP2_SMI_DATA_MASK (0xffff << MVPP2_SMI_DATA_OFFS)
#define MVPP2_SMI_DEV_ADDR_OFFS 16 /* PHY device address */
#define MVPP2_SMI_REG_ADDR_OFFS 21 /* PHY device reg addr*/
#define MVPP2_SMI_OPCODE_OFFS 26 /* Write/Read opcode */
#define MVPP2_SMI_OPCODE_READ (1 << MVPP2_SMI_OPCODE_OFFS)
#define MVPP2_SMI_READ_VALID (1 << 27) /* Read Valid */
#define MVPP2_SMI_BUSY (1 << 28) /* Busy */
#define MVPP2_PHY_ADDR_MASK 0x1f
#define MVPP2_PHY_REG_MASK 0x1f
/* Additional PPv2.2 offsets */
#define MVPP22_MPCS 0x007000
@ -953,7 +937,6 @@ struct mvpp2_port {
/* Per-port registers' base address */
void __iomem *base;
void __iomem *mdio_base;
struct mvpp2_rx_queue **rxqs;
struct mvpp2_tx_queue **txqs;
@ -974,9 +957,8 @@ struct mvpp2_port {
struct phy_device *phy_dev;
phy_interface_t phy_interface;
int phy_node;
int phyaddr;
struct mii_dev *bus;
struct udevice *mdio_dev;
#ifdef CONFIG_DM_GPIO
struct gpio_desc phy_reset_gpio;
struct gpio_desc phy_tx_disable_gpio;
@ -4495,17 +4477,40 @@ static void mvpp2_stop_dev(struct mvpp2_port *port)
gop_port_enable(port, 0);
}
static int mvpp2_phy_connect(struct udevice *dev, struct mvpp2_port *port)
static void mvpp2_phy_connect(struct udevice *dev, struct mvpp2_port *port)
{
struct phy_device *phy_dev;
if (!port->init || port->link == 0) {
phy_dev = phy_connect(port->bus, port->phyaddr, dev,
port->phy_interface);
phy_dev = dm_mdio_phy_connect(port->mdio_dev, port->phyaddr,
dev, port->phy_interface);
/*
* If the phy doesn't match with any existing u-boot drivers the
* phy framework will connect it to generic one which
* uid == 0xffffffff. In this case act as if the phy wouldn't be
* declared in dts. Otherwise in case of 3310 (for which the
* driver doesn't exist) the link will not be correctly
* detected. Removing phy entry from dts in case of 3310 is not
* an option because it is required for the phy_fw_down
* procedure.
*/
if (phy_dev &&
phy_dev->drv->uid == 0xffffffff) {/* Generic phy */
netdev_warn(port->dev,
"Marking phy as invalid, link will not be checked\n");
/* set phy_addr to invalid value */
port->phyaddr = PHY_MAX_ADDR;
mvpp2_egress_enable(port);
mvpp2_ingress_enable(port);
return;
}
port->phy_dev = phy_dev;
if (!phy_dev) {
netdev_err(port->dev, "cannot connect to phy\n");
return -ENODEV;
return;
}
phy_dev->supported &= PHY_GBIT_FEATURES;
phy_dev->advertising = phy_dev->supported;
@ -4517,18 +4522,14 @@ static int mvpp2_phy_connect(struct udevice *dev, struct mvpp2_port *port)
phy_config(phy_dev);
phy_startup(phy_dev);
if (!phy_dev->link) {
if (!phy_dev->link)
printf("%s: No link\n", phy_dev->dev->name);
return -1;
}
port->init = 1;
else
port->init = 1;
} else {
mvpp2_egress_enable(port);
mvpp2_ingress_enable(port);
}
return 0;
}
static int mvpp2_open(struct udevice *dev, struct mvpp2_port *port)
@ -4567,11 +4568,8 @@ static int mvpp2_open(struct udevice *dev, struct mvpp2_port *port)
return err;
}
if (port->phy_node) {
err = mvpp2_phy_connect(dev, port);
if (err < 0)
return err;
if (port->phyaddr < PHY_MAX_ADDR) {
mvpp2_phy_connect(dev, port);
mvpp2_link_event(port);
} else {
mvpp2_egress_enable(port);
@ -4709,35 +4707,25 @@ static int phy_info_parse(struct udevice *dev, struct mvpp2_port *port)
u32 id;
u32 phyaddr = 0;
int phy_mode = -1;
/* Default mdio_base from the same eth base */
if (port->priv->hw_version == MVPP21)
port->mdio_base = port->priv->lms_base + MVPP21_SMI;
else
port->mdio_base = port->priv->iface_base + MVPP22_SMI;
int ret;
phy_node = fdtdec_lookup_phandle(gd->fdt_blob, port_node, "phy");
if (phy_node > 0) {
ofnode phy_ofnode;
fdt_addr_t phy_base;
int parent;
phyaddr = fdtdec_get_int(gd->fdt_blob, phy_node, "reg", 0);
if (phyaddr < 0) {
dev_err(&pdev->dev, "could not find phy address\n");
return -1;
}
phy_ofnode = ofnode_get_parent(offset_to_ofnode(phy_node));
phy_base = ofnode_get_addr(phy_ofnode);
port->mdio_base = (void *)phy_base;
if (port->mdio_base < 0) {
dev_err(&pdev->dev, "could not find mdio base address\n");
return -1;
}
parent = fdt_parent_offset(gd->fdt_blob, phy_node);
ret = uclass_get_device_by_of_offset(UCLASS_MDIO, parent,
&port->mdio_dev);
if (ret)
return ret;
} else {
phy_node = 0;
/* phy_addr is set to invalid value */
phyaddr = PHY_MAX_ADDR;
}
phy_mode_str = fdt_getprop(gd->fdt_blob, port_node, "phy-mode", NULL);
@ -4775,7 +4763,6 @@ static int phy_info_parse(struct udevice *dev, struct mvpp2_port *port)
port->first_rxq = port->id * rxq_number;
else
port->first_rxq = port->id * port->priv->max_port_rxqs;
port->phy_node = phy_node;
port->phy_interface = phy_mode;
port->phyaddr = phyaddr;
@ -5052,118 +5039,6 @@ static int mvpp2_init(struct udevice *dev, struct mvpp2 *priv)
return 0;
}
/* SMI / MDIO functions */
static int smi_wait_ready(struct mvpp2_port *priv)
{
u32 timeout = MVPP2_SMI_TIMEOUT;
u32 smi_reg;
/* wait till the SMI is not busy */
do {
/* read smi register */
smi_reg = readl(priv->mdio_base);
if (timeout-- == 0) {
printf("Error: SMI busy timeout\n");
return -EFAULT;
}
} while (smi_reg & MVPP2_SMI_BUSY);
return 0;
}
/*
* mpp2_mdio_read - miiphy_read callback function.
*
* Returns 16bit phy register value, or 0xffff on error
*/
static int mpp2_mdio_read(struct mii_dev *bus, int addr, int devad, int reg)
{
struct mvpp2_port *priv = bus->priv;
u32 smi_reg;
u32 timeout;
/* check parameters */
if (addr > MVPP2_PHY_ADDR_MASK) {
printf("Error: Invalid PHY address %d\n", addr);
return -EFAULT;
}
if (reg > MVPP2_PHY_REG_MASK) {
printf("Err: Invalid register offset %d\n", reg);
return -EFAULT;
}
/* wait till the SMI is not busy */
if (smi_wait_ready(priv) < 0)
return -EFAULT;
/* fill the phy address and regiser offset and read opcode */
smi_reg = (addr << MVPP2_SMI_DEV_ADDR_OFFS)
| (reg << MVPP2_SMI_REG_ADDR_OFFS)
| MVPP2_SMI_OPCODE_READ;
/* write the smi register */
writel(smi_reg, priv->mdio_base);
/* wait till read value is ready */
timeout = MVPP2_SMI_TIMEOUT;
do {
/* read smi register */
smi_reg = readl(priv->mdio_base);
if (timeout-- == 0) {
printf("Err: SMI read ready timeout\n");
return -EFAULT;
}
} while (!(smi_reg & MVPP2_SMI_READ_VALID));
/* Wait for the data to update in the SMI register */
for (timeout = 0; timeout < MVPP2_SMI_TIMEOUT; timeout++)
;
return readl(priv->mdio_base) & MVPP2_SMI_DATA_MASK;
}
/*
* mpp2_mdio_write - miiphy_write callback function.
*
* Returns 0 if write succeed, -EINVAL on bad parameters
* -ETIME on timeout
*/
static int mpp2_mdio_write(struct mii_dev *bus, int addr, int devad, int reg,
u16 value)
{
struct mvpp2_port *priv = bus->priv;
u32 smi_reg;
/* check parameters */
if (addr > MVPP2_PHY_ADDR_MASK) {
printf("Error: Invalid PHY address %d\n", addr);
return -EFAULT;
}
if (reg > MVPP2_PHY_REG_MASK) {
printf("Err: Invalid register offset %d\n", reg);
return -EFAULT;
}
/* wait till the SMI is not busy */
if (smi_wait_ready(priv) < 0)
return -EFAULT;
/* fill the phy addr and reg offset and write opcode and data */
smi_reg = value << MVPP2_SMI_DATA_OFFS;
smi_reg |= (addr << MVPP2_SMI_DEV_ADDR_OFFS)
| (reg << MVPP2_SMI_REG_ADDR_OFFS);
smi_reg &= ~MVPP2_SMI_OPCODE_READ;
/* write the smi register */
writel(smi_reg, priv->mdio_base);
return 0;
}
static int mvpp2_recv(struct udevice *dev, int flags, uchar **packetp)
{
struct mvpp2_port *port = dev_get_priv(dev);
@ -5176,6 +5051,10 @@ static int mvpp2_recv(struct udevice *dev, int flags, uchar **packetp)
struct mvpp2_rx_queue *rxq;
u8 *data;
if (port->phyaddr < PHY_MAX_ADDR)
if (!port->phy_dev->link)
return 0;
/* Process RX packets */
rxq = port->rxqs[0];
@ -5241,6 +5120,10 @@ static int mvpp2_send(struct udevice *dev, void *packet, int length)
int tx_done;
int timeout;
if (port->phyaddr < PHY_MAX_ADDR)
if (!port->phy_dev->link)
return 0;
txq = port->txqs[0];
aggr_txq = &port->priv->aggr_txqs[smp_processor_id()];
@ -5421,31 +5304,13 @@ static int mvpp2_probe(struct udevice *dev)
{
struct mvpp2_port *port = dev_get_priv(dev);
struct mvpp2 *priv = dev_get_priv(dev->parent);
struct mii_dev *bus;
int err;
/* Only call the probe function for the parent once */
if (!priv->probe_done)
err = mvpp2_base_probe(dev->parent);
port->priv = dev_get_priv(dev->parent);
/* Create and register the MDIO bus driver */
bus = mdio_alloc();
if (!bus) {
printf("Failed to allocate MDIO bus\n");
return -ENOMEM;
}
bus->read = mpp2_mdio_read;
bus->write = mpp2_mdio_write;
snprintf(bus->name, sizeof(bus->name), dev->name);
bus->priv = (void *)port;
port->bus = bus;
err = mdio_register(bus);
if (err)
return err;
port->priv = priv;
err = phy_info_parse(dev, port);
if (err)
@ -5474,7 +5339,7 @@ static int mvpp2_probe(struct udevice *dev)
port->gop_id * MVPP22_PORT_OFFSET;
/* Set phy address of the port */
if(port->phy_node)
if (port->phyaddr < PHY_MAX_ADDR)
mvpp22_smi_phy_addr_cfg(port);
/* GoP Init */

View File

@ -46,7 +46,7 @@ config B53_PHY_PORTS
endif # B53_SWITCH
config MV88E61XX_SWITCH
bool "Marvel MV88E61xx Ethernet switch PHY support."
bool "Marvell MV88E61xx Ethernet switch PHY support."
if MV88E61XX_SWITCH

View File

@ -25,7 +25,7 @@ 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) += ti.o
obj-$(CONFIG_PHY_TI) += dp83867.o
obj-$(CONFIG_PHY_XILINX) += xilinx_phy.o
obj-$(CONFIG_PHY_XILINX_GMII2RGMII) += xilinx_gmii2rgmii.o
obj-$(CONFIG_PHY_VITESSE) += vitesse.o

View File

@ -21,6 +21,7 @@
#define AQUNTIA_SPEED_MSB_MASK 0x40
#define AQUANTIA_SYSTEM_INTERFACE_SR 0xe812
#define AQUANTIA_SYSTEM_INTERFACE_SR_READY BIT(0)
#define AQUANTIA_VENDOR_PROVISIONING_REG 0xC441
#define AQUANTIA_FIRMWARE_ID 0x20
#define AQUANTIA_RESERVED_STATUS 0xc885
@ -33,10 +34,16 @@
#define AQUANTIA_SI_USXGMII 0x0018
/* registers in MDIO_MMD_VEND1 region */
#define AQUANTIA_VND1_GLOBAL_SC 0x000
#define AQUANTIA_VND1_GLOBAL_SC_LP BIT(0xb)
#define GLOBAL_FIRMWARE_ID 0x20
#define GLOBAL_FAULT 0xc850
#define GLOBAL_RSTATUS_1 0xc885
#define GLOBAL_ALARM_1 0xcc00
#define SYSTEM_READY_BIT 0x40
#define GLOBAL_STANDARD_CONTROL 0x0
#define SOFT_RESET BIT(15)
#define LOW_POWER BIT(11)
@ -60,6 +67,36 @@
#define UP_RUN_STALL_OVERRIDE BIT(6)
#define UP_RUN_STALL BIT(0)
#define AQUANTIA_PMA_RX_VENDOR_P1 0xe400
#define AQUANTIA_PMA_RX_VENDOR_P1_MDI_MSK GENMASK(1, 0)
/* MDI reversal configured through registers */
#define AQUANTIA_PMA_RX_VENDOR_P1_MDI_CFG BIT(1)
/* MDI reversal enabled */
#define AQUANTIA_PMA_RX_VENDOR_P1_MDI_REV BIT(0)
/*
* global start rate, the protocol associated with this speed is used by default
* on SI.
*/
#define AQUANTIA_VND1_GSTART_RATE 0x31a
#define AQUANTIA_VND1_GSTART_RATE_OFF 0
#define AQUANTIA_VND1_GSTART_RATE_100M 1
#define AQUANTIA_VND1_GSTART_RATE_1G 2
#define AQUANTIA_VND1_GSTART_RATE_10G 3
#define AQUANTIA_VND1_GSTART_RATE_2_5G 4
#define AQUANTIA_VND1_GSTART_RATE_5G 5
/* SYSCFG registers for 100M, 1G, 2.5G, 5G, 10G */
#define AQUANTIA_VND1_GSYSCFG_BASE 0x31b
#define AQUANTIA_VND1_GSYSCFG_100M 0
#define AQUANTIA_VND1_GSYSCFG_1G 1
#define AQUANTIA_VND1_GSYSCFG_2_5G 2
#define AQUANTIA_VND1_GSYSCFG_5G 3
#define AQUANTIA_VND1_GSYSCFG_10G 4
#define AQUANTIA_VND1_SMBUS0 0xc485
#define AQUANTIA_VND1_SMBUS1 0xc495
/* addresses of memory segments in the phy */
#define DRAM_BASE_ADDR 0x3FFE0000
#define IRAM_BASE_ADDR 0x40000000
@ -69,6 +106,12 @@
#define VERSION_STRING_OFFSET 0x0200
#define HEADER_OFFSET 0x300
/* driver private data */
#define AQUANTIA_NA 0
#define AQUANTIA_GEN1 1
#define AQUANTIA_GEN2 2
#define AQUANTIA_GEN3 3
#pragma pack(1)
struct fw_header {
u8 padding[4];
@ -254,10 +297,128 @@ static int aquantia_upload_firmware(struct phy_device *phydev)
}
#endif
struct {
u16 syscfg;
int cnt;
u16 start_rate;
} aquantia_syscfg[PHY_INTERFACE_MODE_COUNT] = {
[PHY_INTERFACE_MODE_SGMII] = {0x04b, AQUANTIA_VND1_GSYSCFG_1G,
AQUANTIA_VND1_GSTART_RATE_1G},
[PHY_INTERFACE_MODE_SGMII_2500] = {0x144, AQUANTIA_VND1_GSYSCFG_2_5G,
AQUANTIA_VND1_GSTART_RATE_2_5G},
[PHY_INTERFACE_MODE_XGMII] = {0x100, AQUANTIA_VND1_GSYSCFG_10G,
AQUANTIA_VND1_GSTART_RATE_10G},
[PHY_INTERFACE_MODE_XFI] = {0x100, AQUANTIA_VND1_GSYSCFG_10G,
AQUANTIA_VND1_GSTART_RATE_10G},
[PHY_INTERFACE_MODE_USXGMII] = {0x080, AQUANTIA_VND1_GSYSCFG_10G,
AQUANTIA_VND1_GSTART_RATE_10G},
};
static int aquantia_set_proto(struct phy_device *phydev)
{
int i;
if (!aquantia_syscfg[phydev->interface].cnt)
return 0;
/* set the default rate to enable the SI link */
phy_write(phydev, MDIO_MMD_VEND1, AQUANTIA_VND1_GSTART_RATE,
aquantia_syscfg[phydev->interface].start_rate);
/* set selected protocol for all relevant line side link speeds */
for (i = 0; i <= aquantia_syscfg[phydev->interface].cnt; i++)
phy_write(phydev, MDIO_MMD_VEND1,
AQUANTIA_VND1_GSYSCFG_BASE + i,
aquantia_syscfg[phydev->interface].syscfg);
return 0;
}
static int aquantia_dts_config(struct phy_device *phydev)
{
#ifdef CONFIG_DM_ETH
ofnode node = phydev->node;
u32 prop;
u16 reg;
/* this code only works on gen2 and gen3 PHYs */
if (phydev->drv->data != AQUANTIA_GEN2 &&
phydev->drv->data != AQUANTIA_GEN3)
return -ENOTSUPP;
if (!ofnode_valid(node))
return 0;
if (!ofnode_read_u32(node, "mdi-reversal", &prop)) {
debug("mdi-reversal = %d\n", (int)prop);
reg = phy_read(phydev, MDIO_MMD_PMAPMD,
AQUANTIA_PMA_RX_VENDOR_P1);
reg &= ~AQUANTIA_PMA_RX_VENDOR_P1_MDI_MSK;
reg |= AQUANTIA_PMA_RX_VENDOR_P1_MDI_CFG;
reg |= prop ? AQUANTIA_PMA_RX_VENDOR_P1_MDI_REV : 0;
phy_write(phydev, MDIO_MMD_PMAPMD, AQUANTIA_PMA_RX_VENDOR_P1,
reg);
}
if (!ofnode_read_u32(node, "smb-addr", &prop)) {
debug("smb-addr = %x\n", (int)prop);
/*
* there are two addresses here, normally just one bus would
* be in use so we're setting both regs using the same DT
* property.
*/
phy_write(phydev, MDIO_MMD_VEND1, AQUANTIA_VND1_SMBUS0,
(u16)(prop << 1));
phy_write(phydev, MDIO_MMD_VEND1, AQUANTIA_VND1_SMBUS1,
(u16)(prop << 1));
}
#endif
return 0;
}
static bool aquantia_link_is_up(struct phy_device *phydev)
{
u16 reg, regmask;
int devad, regnum;
/*
* On Gen 2 and 3 we have a bit that indicates that both system and
* line side are ready for data, use that if possible.
*/
if (phydev->drv->data == AQUANTIA_GEN2 ||
phydev->drv->data == AQUANTIA_GEN3) {
devad = MDIO_MMD_PHYXS;
regnum = AQUANTIA_SYSTEM_INTERFACE_SR;
regmask = AQUANTIA_SYSTEM_INTERFACE_SR_READY;
} else {
devad = MDIO_MMD_AN;
regnum = MDIO_STAT1;
regmask = MDIO_AN_STAT1_COMPLETE;
}
/* the register should be latched, do a double read */
phy_read(phydev, devad, regnum);
reg = phy_read(phydev, devad, regnum);
return !!(reg & regmask);
}
int aquantia_config(struct phy_device *phydev)
{
int interface = phydev->interface;
u32 val, id, rstatus, fault;
u32 reg_val1 = 0;
int num_retries = 5;
int usx_an = 0;
/*
* check if the system is out of reset and init sequence completed.
* chip-wide reset for gen1 quad phys takes longer
*/
while (--num_retries) {
rstatus = phy_read(phydev, MDIO_MMD_VEND1, GLOBAL_ALARM_1);
if (rstatus & SYSTEM_READY_BIT)
break;
mdelay(10);
}
id = phy_read(phydev, MDIO_MMD_VEND1, GLOBAL_FIRMWARE_ID);
rstatus = phy_read(phydev, MDIO_MMD_VEND1, GLOBAL_RSTATUS_1);
@ -278,17 +439,57 @@ int aquantia_config(struct phy_device *phydev)
if (ret != 0)
return ret;
}
/*
* for backward compatibility convert XGMII into either XFI or USX based
* on FW config
*/
if (interface == PHY_INTERFACE_MODE_XGMII) {
reg_val1 = phy_read(phydev, MDIO_MMD_PHYXS,
AQUANTIA_SYSTEM_INTERFACE_SR);
if ((reg_val1 & AQUANTIA_SI_IN_USE_MASK) == AQUANTIA_SI_USXGMII)
interface = PHY_INTERFACE_MODE_USXGMII;
else
interface = PHY_INTERFACE_MODE_XFI;
}
/*
* if link is up already we can just use it, otherwise configure
* the protocols in the PHY. If link is down set the system
* interface protocol to use based on phydev->interface
*/
if (!aquantia_link_is_up(phydev) &&
(phydev->drv->data == AQUANTIA_GEN2 ||
phydev->drv->data == AQUANTIA_GEN3)) {
/* set PHY in low power mode so we can configure protocols */
phy_write(phydev, MDIO_MMD_VEND1, AQUANTIA_VND1_GLOBAL_SC,
AQUANTIA_VND1_GLOBAL_SC_LP);
mdelay(10);
/* configure protocol based on phydev->interface */
aquantia_set_proto(phydev);
/* apply custom configuration based on DT */
aquantia_dts_config(phydev);
/* wake PHY back up */
phy_write(phydev, MDIO_MMD_VEND1, AQUANTIA_VND1_GLOBAL_SC, 0);
mdelay(10);
}
val = phy_read(phydev, MDIO_MMD_PMAPMD, MII_BMCR);
if (phydev->interface == PHY_INTERFACE_MODE_SGMII) {
switch (interface) {
case PHY_INTERFACE_MODE_SGMII:
/* 1000BASE-T mode */
phydev->advertising = SUPPORTED_1000baseT_Full;
phydev->supported = phydev->advertising;
val = (val & ~AQUNTIA_SPEED_LSB_MASK) | AQUNTIA_SPEED_MSB_MASK;
phy_write(phydev, MDIO_MMD_PMAPMD, MII_BMCR, val);
} else if (phydev->interface == PHY_INTERFACE_MODE_XGMII) {
break;
case PHY_INTERFACE_MODE_USXGMII:
usx_an = 1;
/* FALLTHROUGH */
case PHY_INTERFACE_MODE_XFI:
/* 10GBASE-T mode */
phydev->advertising = SUPPORTED_10000baseT_Full;
phydev->supported = phydev->advertising;
@ -299,40 +500,40 @@ int aquantia_config(struct phy_device *phydev)
AQUNTIA_SPEED_LSB_MASK |
AQUNTIA_SPEED_MSB_MASK);
val = phy_read(phydev, MDIO_MMD_PHYXS,
AQUANTIA_SYSTEM_INTERFACE_SR);
/* If SI is USXGMII then start USXGMII autoneg */
if ((val & AQUANTIA_SI_IN_USE_MASK) == AQUANTIA_SI_USXGMII) {
reg_val1 = phy_read(phydev, MDIO_MMD_PHYXS,
AQUANTIA_VENDOR_PROVISIONING_REG);
reg_val1 = phy_read(phydev, MDIO_MMD_PHYXS,
AQUANTIA_VENDOR_PROVISIONING_REG);
if (usx_an) {
reg_val1 |= AQUANTIA_USX_AUTONEG_CONTROL_ENA;
phy_write(phydev, MDIO_MMD_PHYXS,
AQUANTIA_VENDOR_PROVISIONING_REG,
reg_val1);
printf("%s: system interface USXGMII\n",
phydev->dev->name);
} else {
reg_val1 &= ~AQUANTIA_USX_AUTONEG_CONTROL_ENA;
printf("%s: system interface XFI\n",
phydev->dev->name);
}
} else if (phydev->interface == PHY_INTERFACE_MODE_SGMII_2500) {
phy_write(phydev, MDIO_MMD_PHYXS,
AQUANTIA_VENDOR_PROVISIONING_REG, reg_val1);
break;
case PHY_INTERFACE_MODE_SGMII_2500:
/* 2.5GBASE-T mode */
phydev->advertising = SUPPORTED_1000baseT_Full;
phydev->supported = phydev->advertising;
phy_write(phydev, MDIO_MMD_AN, AQUNTIA_10G_CTL, 1);
phy_write(phydev, MDIO_MMD_AN, AQUNTIA_VENDOR_P1, 0x9440);
} else if (phydev->interface == PHY_INTERFACE_MODE_MII) {
break;
case PHY_INTERFACE_MODE_MII:
/* 100BASE-TX mode */
phydev->advertising = SUPPORTED_100baseT_Full;
phydev->supported = phydev->advertising;
val = (val & ~AQUNTIA_SPEED_MSB_MASK) | AQUNTIA_SPEED_LSB_MASK;
phy_write(phydev, MDIO_MMD_PMAPMD, MII_BMCR, val);
}
break;
};
val = phy_read(phydev, MDIO_MMD_VEND1, AQUANTIA_RESERVED_STATUS);
reg_val1 = phy_read(phydev, MDIO_MMD_VEND1, AQUANTIA_FIRMWARE_ID);
@ -354,17 +555,14 @@ int aquantia_startup(struct phy_device *phydev)
phydev->duplex = DUPLEX_FULL;
/* if the AN is still in progress, wait till timeout. */
phy_read(phydev, MDIO_MMD_AN, MDIO_STAT1);
reg = phy_read(phydev, MDIO_MMD_AN, MDIO_STAT1);
if (!(reg & MDIO_AN_STAT1_COMPLETE)) {
if (!aquantia_link_is_up(phydev)) {
printf("%s Waiting for PHY auto negotiation to complete",
phydev->dev->name);
do {
udelay(1000);
reg = phy_read(phydev, MDIO_MMD_AN, MDIO_STAT1);
if ((i++ % 500) == 0)
printf(".");
} while (!(reg & MDIO_AN_STAT1_COMPLETE) &&
} while (!aquantia_link_is_up(phydev) &&
i < (4 * PHY_ANEG_TIMEOUT));
if (i > PHY_ANEG_TIMEOUT)
@ -433,6 +631,7 @@ struct phy_driver aqr105_driver = {
.config = &aquantia_config,
.startup = &aquantia_startup,
.shutdown = &gen10g_shutdown,
.data = AQUANTIA_GEN1,
};
struct phy_driver aqr106_driver = {
@ -459,6 +658,7 @@ struct phy_driver aqr107_driver = {
.config = &aquantia_config,
.startup = &aquantia_startup,
.shutdown = &gen10g_shutdown,
.data = AQUANTIA_GEN2,
};
struct phy_driver aqr112_driver = {
@ -472,6 +672,7 @@ struct phy_driver aqr112_driver = {
.config = &aquantia_config,
.startup = &aquantia_startup,
.shutdown = &gen10g_shutdown,
.data = AQUANTIA_GEN3,
};
struct phy_driver aqr405_driver = {
@ -485,6 +686,7 @@ struct phy_driver aqr405_driver = {
.config = &aquantia_config,
.startup = &aquantia_startup,
.shutdown = &gen10g_shutdown,
.data = AQUANTIA_GEN1,
};
struct phy_driver aqr412_driver = {
@ -498,6 +700,7 @@ struct phy_driver aqr412_driver = {
.config = &aquantia_config,
.startup = &aquantia_startup,
.shutdown = &gen10g_shutdown,
.data = AQUANTIA_GEN3,
};
int phy_aquantia_init(void)

View File

@ -25,6 +25,7 @@
#define DP83867_CFG4 0x0031
#define DP83867_RGMIICTL 0x0032
#define DP83867_STRAP_STS1 0x006E
#define DP83867_STRAP_STS2 0x006f
#define DP83867_RGMIIDCTL 0x0086
#define DP83867_IO_MUX_CFG 0x0170
@ -52,18 +53,27 @@
/* STRAP_STS1 bits */
#define DP83867_STRAP_STS1_RESERVED BIT(11)
/* STRAP_STS2 bits */
#define DP83867_STRAP_STS2_CLK_SKEW_TX_MASK GENMASK(6, 4)
#define DP83867_STRAP_STS2_CLK_SKEW_TX_SHIFT 4
#define DP83867_STRAP_STS2_CLK_SKEW_RX_MASK GENMASK(2, 0)
#define DP83867_STRAP_STS2_CLK_SKEW_RX_SHIFT 0
#define DP83867_STRAP_STS2_CLK_SKEW_NONE BIT(2)
/* PHY CTRL bits */
#define DP83867_PHYCR_FIFO_DEPTH_SHIFT 14
#define DP83867_PHYCR_FIFO_DEPTH_MASK GENMASK(15, 14)
#define DP83867_PHYCR_RESERVED_MASK BIT(11)
#define DP83867_MDI_CROSSOVER 5
#define DP83867_MDI_CROSSOVER_AUTO 2
#define DP83867_MDI_CROSSOVER_MDIX 2
#define DP83867_PHYCTRL_SGMIIEN 0x0800
#define DP83867_PHYCTRL_RXFIFO_SHIFT 12
#define DP83867_PHYCTRL_TXFIFO_SHIFT 14
/* RGMIIDCTL bits */
#define DP83867_RGMII_TX_CLK_DELAY_MAX 0xf
#define DP83867_RGMII_TX_CLK_DELAY_SHIFT 4
#define DP83867_RGMII_RX_CLK_DELAY_MAX 0xf
/* CFG2 bits */
#define MII_DP83867_CFG2_SPEEDOPT_10EN 0x0040
@ -74,8 +84,6 @@
#define MII_DP83867_CFG2_MASK 0x003F
/* User setting - can be taken from DTS */
#define DEFAULT_RX_ID_DELAY DP83867_RGMIIDCTL_2_25_NS
#define DEFAULT_TX_ID_DELAY DP83867_RGMIIDCTL_2_75_NS
#define DEFAULT_FIFO_DEPTH DP83867_PHYCR_FIFO_DEPTH_4_B_NIB
/* IO_MUX_CFG bits */
@ -83,6 +91,7 @@
#define DP83867_IO_MUX_CFG_IO_IMPEDANCE_MAX 0x0
#define DP83867_IO_MUX_CFG_IO_IMPEDANCE_MIN 0x1f
#define DP83867_IO_MUX_CFG_CLK_O_DISABLE BIT(6)
#define DP83867_IO_MUX_CFG_CLK_O_SEL_SHIFT 8
#define DP83867_IO_MUX_CFG_CLK_O_SEL_MASK \
GENMASK(0x1f, DP83867_IO_MUX_CFG_CLK_O_SEL_SHIFT)
@ -97,12 +106,13 @@ enum {
};
struct dp83867_private {
int rx_id_delay;
int tx_id_delay;
u32 rx_id_delay;
u32 tx_id_delay;
int fifo_depth;
int io_impedance;
bool rxctrl_strap_quirk;
int port_mirroring;
bool set_clk_output;
unsigned int clk_output_sel;
};
@ -134,16 +144,28 @@ static int dp83867_of_init(struct phy_device *phydev)
{
struct dp83867_private *dp83867 = phydev->priv;
ofnode node;
u16 val;
int ret;
node = phy_get_ofnode(phydev);
if (!ofnode_valid(node))
return -EINVAL;
/* Keep the default value if ti,clk-output-sel is not set */
dp83867->clk_output_sel =
ofnode_read_u32_default(node, "ti,clk-output-sel",
DP83867_CLK_O_SEL_REF_CLK);
/* Optional configuration */
ret = ofnode_read_u32(node, "ti,clk-output-sel",
&dp83867->clk_output_sel);
/* If not set, keep default */
if (!ret) {
dp83867->set_clk_output = true;
/* Valid values are 0 to DP83867_CLK_O_SEL_REF_CLK or
* DP83867_CLK_O_SEL_OFF.
*/
if (dp83867->clk_output_sel > DP83867_CLK_O_SEL_REF_CLK &&
dp83867->clk_output_sel != DP83867_CLK_O_SEL_OFF) {
pr_debug("ti,clk-output-sel value %u out of range\n",
dp83867->clk_output_sel);
return -EINVAL;
}
}
if (ofnode_read_bool(node, "ti,max-output-impedance"))
dp83867->io_impedance = DP83867_IO_MUX_CFG_IO_IMPEDANCE_MAX;
@ -154,13 +176,55 @@ static int dp83867_of_init(struct phy_device *phydev)
if (ofnode_read_bool(node, "ti,dp83867-rxctrl-strap-quirk"))
dp83867->rxctrl_strap_quirk = true;
dp83867->rx_id_delay = ofnode_read_u32_default(node,
"ti,rx-internal-delay",
DEFAULT_RX_ID_DELAY);
dp83867->tx_id_delay = ofnode_read_u32_default(node,
"ti,tx-internal-delay",
DEFAULT_TX_ID_DELAY);
/* Existing behavior was to use default pin strapping delay in rgmii
* mode, but rgmii should have meant no delay. Warn existing users.
*/
if (phydev->interface == PHY_INTERFACE_MODE_RGMII) {
u16 val = phy_read_mmd(phydev, DP83867_DEVADDR,
DP83867_STRAP_STS2);
u16 txskew = (val & DP83867_STRAP_STS2_CLK_SKEW_TX_MASK) >>
DP83867_STRAP_STS2_CLK_SKEW_TX_SHIFT;
u16 rxskew = (val & DP83867_STRAP_STS2_CLK_SKEW_RX_MASK) >>
DP83867_STRAP_STS2_CLK_SKEW_RX_SHIFT;
if (txskew != DP83867_STRAP_STS2_CLK_SKEW_NONE ||
rxskew != DP83867_STRAP_STS2_CLK_SKEW_NONE)
pr_warn("PHY has delays via pin strapping, but phy-mode = 'rgmii'\n"
"Should be 'rgmii-id' to use internal delays\n");
}
/* RX delay *must* be specified if internal delay of RX is used. */
if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID ||
phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) {
ret = ofnode_read_u32(node, "ti,rx-internal-delay",
&dp83867->rx_id_delay);
if (ret) {
pr_debug("ti,rx-internal-delay must be specified\n");
return ret;
}
if (dp83867->rx_id_delay > DP83867_RGMII_RX_CLK_DELAY_MAX) {
pr_debug("ti,rx-internal-delay value of %u out of range\n",
dp83867->rx_id_delay);
return -EINVAL;
}
}
/* TX delay *must* be specified if internal delay of RX is used. */
if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID ||
phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID) {
ret = ofnode_read_u32(node, "ti,tx-internal-delay",
&dp83867->tx_id_delay);
if (ret) {
debug("ti,tx-internal-delay must be specified\n");
return ret;
}
if (dp83867->tx_id_delay > DP83867_RGMII_TX_CLK_DELAY_MAX) {
pr_debug("ti,tx-internal-delay value of %u out of range\n",
dp83867->tx_id_delay);
return -EINVAL;
}
}
dp83867->fifo_depth = ofnode_read_u32_default(node, "ti,fifo-depth",
DEFAULT_FIFO_DEPTH);
@ -170,18 +234,6 @@ static int dp83867_of_init(struct phy_device *phydev)
if (ofnode_read_bool(node, "enet-phy-lane-no-swap"))
dp83867->port_mirroring = DP83867_PORT_MIRRORING_DIS;
/* Clock output selection if muxing property is set */
if (dp83867->clk_output_sel != DP83867_CLK_O_SEL_REF_CLK) {
val = phy_read_mmd(phydev, DP83867_DEVADDR,
DP83867_IO_MUX_CFG);
val &= ~DP83867_IO_MUX_CFG_CLK_O_SEL_MASK;
val |= (dp83867->clk_output_sel <<
DP83867_IO_MUX_CFG_CLK_O_SEL_SHIFT);
phy_write_mmd(phydev, DP83867_DEVADDR,
DP83867_IO_MUX_CFG, val);
}
return 0;
}
#else
@ -189,8 +241,8 @@ static int dp83867_of_init(struct phy_device *phydev)
{
struct dp83867_private *dp83867 = phydev->priv;
dp83867->rx_id_delay = DEFAULT_RX_ID_DELAY;
dp83867->tx_id_delay = DEFAULT_TX_ID_DELAY;
dp83867->rx_id_delay = DP83867_RGMIIDCTL_2_25_NS;
dp83867->tx_id_delay = DP83867_RGMIIDCTL_2_75_NS;
dp83867->fifo_depth = DEFAULT_FIFO_DEPTH;
dp83867->io_impedance = -EINVAL;
@ -204,18 +256,11 @@ static int dp83867_config(struct phy_device *phydev)
unsigned int val, delay, cfg2;
int ret, bs;
if (!phydev->priv) {
dp83867 = kzalloc(sizeof(*dp83867), GFP_KERNEL);
if (!dp83867)
return -ENOMEM;
dp83867 = (struct dp83867_private *)phydev->priv;
phydev->priv = dp83867;
ret = dp83867_of_init(phydev);
if (ret)
goto err_out;
} else {
dp83867 = (struct dp83867_private *)phydev->priv;
}
ret = dp83867_of_init(phydev);
if (ret)
return ret;
/* Restart the PHY. */
val = phy_read(phydev, MDIO_DEVAD_NONE, DP83867_CTRL);
@ -232,11 +277,11 @@ static int dp83867_config(struct phy_device *phydev)
}
if (phy_interface_is_rgmii(phydev)) {
ret = phy_write(phydev, MDIO_DEVAD_NONE, MII_DP83867_PHYCTRL,
(DP83867_MDI_CROSSOVER_AUTO << DP83867_MDI_CROSSOVER) |
(dp83867->fifo_depth << DP83867_PHYCR_FIFO_DEPTH_SHIFT));
if (ret)
val = phy_read(phydev, MDIO_DEVAD_NONE, MII_DP83867_PHYCTRL);
if (val < 0)
goto err_out;
val &= ~DP83867_PHYCR_FIFO_DEPTH_MASK;
val |= (dp83867->fifo_depth << DP83867_PHYCR_FIFO_DEPTH_SHIFT);
/* The code below checks if "port mirroring" N/A MODE4 has been
* enabled during power on bootstrap.
@ -248,16 +293,39 @@ static int dp83867_config(struct phy_device *phydev)
* register's bit 11 (marked as RESERVED).
*/
bs = phy_read_mmd(phydev, DP83867_DEVADDR,
DP83867_STRAP_STS1);
val = phy_read(phydev, MDIO_DEVAD_NONE, MII_DP83867_PHYCTRL);
if (bs & DP83867_STRAP_STS1_RESERVED) {
bs = phy_read_mmd(phydev, DP83867_DEVADDR, DP83867_STRAP_STS1);
if (bs & DP83867_STRAP_STS1_RESERVED)
val &= ~DP83867_PHYCR_RESERVED_MASK;
phy_write(phydev, MDIO_DEVAD_NONE, MII_DP83867_PHYCTRL,
val);
}
} else if (phy_interface_is_sgmii(phydev)) {
ret = phy_write(phydev, MDIO_DEVAD_NONE,
MII_DP83867_PHYCTRL, val);
val = phy_read_mmd(phydev, DP83867_DEVADDR,
DP83867_RGMIICTL);
val &= ~(DP83867_RGMII_TX_CLK_DELAY_EN |
DP83867_RGMII_RX_CLK_DELAY_EN);
if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID)
val |= (DP83867_RGMII_TX_CLK_DELAY_EN |
DP83867_RGMII_RX_CLK_DELAY_EN);
if (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID)
val |= DP83867_RGMII_TX_CLK_DELAY_EN;
if (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID)
val |= DP83867_RGMII_RX_CLK_DELAY_EN;
phy_write_mmd(phydev, DP83867_DEVADDR, DP83867_RGMIICTL, val);
delay = (dp83867->rx_id_delay |
(dp83867->tx_id_delay <<
DP83867_RGMII_TX_CLK_DELAY_SHIFT));
phy_write_mmd(phydev, DP83867_DEVADDR,
DP83867_RGMIIDCTL, delay);
}
if (phy_interface_is_sgmii(phydev)) {
phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR,
(BMCR_ANENABLE | BMCR_FULLDPLX | BMCR_SPEED1000));
@ -282,57 +350,62 @@ static int dp83867_config(struct phy_device *phydev)
phy_write(phydev, MDIO_DEVAD_NONE, MII_DP83867_BISCR, 0x0);
}
if (phy_interface_is_rgmii(phydev)) {
val = phy_read_mmd(phydev, DP83867_DEVADDR,
DP83867_RGMIICTL);
if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID)
val |= (DP83867_RGMII_TX_CLK_DELAY_EN |
DP83867_RGMII_RX_CLK_DELAY_EN);
if (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID)
val |= DP83867_RGMII_TX_CLK_DELAY_EN;
if (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID)
val |= DP83867_RGMII_RX_CLK_DELAY_EN;
if (dp83867->io_impedance >= 0) {
val = phy_read_mmd(phydev,
DP83867_DEVADDR,
DP83867_IO_MUX_CFG);
val &= ~DP83867_IO_MUX_CFG_IO_IMPEDANCE_CTRL;
val |= dp83867->io_impedance &
DP83867_IO_MUX_CFG_IO_IMPEDANCE_CTRL;
phy_write_mmd(phydev, DP83867_DEVADDR,
DP83867_RGMIICTL, val);
delay = (dp83867->rx_id_delay |
(dp83867->tx_id_delay << DP83867_RGMII_TX_CLK_DELAY_SHIFT));
phy_write_mmd(phydev, DP83867_DEVADDR,
DP83867_RGMIIDCTL, delay);
if (dp83867->io_impedance >= 0) {
val = phy_read_mmd(phydev,
DP83867_DEVADDR,
DP83867_IO_MUX_CFG);
val &= ~DP83867_IO_MUX_CFG_IO_IMPEDANCE_CTRL;
val |= dp83867->io_impedance &
DP83867_IO_MUX_CFG_IO_IMPEDANCE_CTRL;
phy_write_mmd(phydev, DP83867_DEVADDR,
DP83867_IO_MUX_CFG, val);
}
DP83867_IO_MUX_CFG, val);
}
if (dp83867->port_mirroring != DP83867_PORT_MIRRORING_KEEP)
dp83867_config_port_mirroring(phydev);
/* Clock output selection if muxing property is set */
if (dp83867->set_clk_output) {
val = phy_read_mmd(phydev, DP83867_DEVADDR,
DP83867_IO_MUX_CFG);
if (dp83867->clk_output_sel == DP83867_CLK_O_SEL_OFF) {
val |= DP83867_IO_MUX_CFG_CLK_O_DISABLE;
} else {
val &= ~(DP83867_IO_MUX_CFG_CLK_O_SEL_MASK |
DP83867_IO_MUX_CFG_CLK_O_DISABLE);
val |= dp83867->clk_output_sel <<
DP83867_IO_MUX_CFG_CLK_O_SEL_SHIFT;
}
phy_write_mmd(phydev, DP83867_DEVADDR,
DP83867_IO_MUX_CFG, val);
}
genphy_config_aneg(phydev);
return 0;
err_out:
kfree(dp83867);
return ret;
}
static int dp83867_probe(struct phy_device *phydev)
{
struct dp83867_private *dp83867;
dp83867 = kzalloc(sizeof(*dp83867), GFP_KERNEL);
if (!dp83867)
return -ENOMEM;
phydev->priv = dp83867;
return 0;
}
static struct phy_driver DP83867_driver = {
.name = "TI DP83867",
.uid = 0x2000a231,
.mask = 0xfffffff0,
.features = PHY_GBIT_FEATURES,
.probe = dp83867_probe,
.config = &dp83867_config,
.startup = &genphy_startup,
.shutdown = &genphy_shutdown,

View File

@ -24,6 +24,7 @@ static struct phy_driver KSZ804_driver = {
};
#define MII_KSZPHY_OMSO 0x16
#define KSZPHY_OMSO_FACTORY_TEST BIT(15)
#define KSZPHY_OMSO_B_CAST_OFF (1 << 9)
static int ksz_genconfig_bcastoff(struct phy_device *phydev)
@ -80,12 +81,30 @@ static struct phy_driver KSZ8051_driver = {
.shutdown = &genphy_shutdown,
};
static int ksz8081_config(struct phy_device *phydev)
{
int ret;
ret = phy_read(phydev, MDIO_DEVAD_NONE, MII_KSZPHY_OMSO);
if (ret < 0)
return ret;
ret &= ~KSZPHY_OMSO_FACTORY_TEST;
ret = phy_write(phydev, MDIO_DEVAD_NONE, MII_KSZPHY_OMSO,
ret | KSZPHY_OMSO_B_CAST_OFF);
if (ret < 0)
return ret;
return genphy_config(phydev);
}
static struct phy_driver KSZ8081_driver = {
.name = "Micrel KSZ8081",
.uid = 0x221560,
.mask = 0xfffff0,
.features = PHY_BASIC_FEATURES,
.config = &ksz_genconfig_bcastoff,
.config = &ksz8081_config,
.startup = &genphy_startup,
.shutdown = &genphy_shutdown,
};

View File

@ -39,15 +39,11 @@
#define PHY_AUTONEGOTIATE_TIMEOUT 5000
#define PORT_COUNT 11
#define PORT_MASK ((1 << PORT_COUNT) - 1)
#define PORT_MASK(port_count) ((1 << (port_count)) - 1)
/* Device addresses */
#define DEVADDR_PHY(p) (p)
#define DEVADDR_PORT(p) (0x10 + (p))
#define DEVADDR_SERDES 0x0F
#define DEVADDR_GLOBAL_1 0x1B
#define DEVADDR_GLOBAL_2 0x1C
/* SMI indirection registers for multichip addressing mode */
#define SMI_CMD_REG 0x00
@ -88,11 +84,7 @@
#define GLOBAL1_MON_CTRL_CPUDEST_SHIFT 4
#define GLOBAL1_MON_CTRL_CPUDEST_WIDTH 4
#define PORT_REG_STATUS_LINK BIT(11)
#define PORT_REG_STATUS_DUPLEX BIT(10)
#define PORT_REG_STATUS_SPEED_SHIFT 8
#define PORT_REG_STATUS_SPEED_WIDTH 2
#define PORT_REG_STATUS_SPEED_10 0
#define PORT_REG_STATUS_SPEED_100 1
#define PORT_REG_STATUS_SPEED_1000 2
@ -111,6 +103,7 @@
#define PORT_REG_PHYS_CTRL_DUPLEX_VALUE BIT(3)
#define PORT_REG_PHYS_CTRL_DUPLEX_FORCE BIT(2)
#define PORT_REG_PHYS_CTRL_SPD1000 BIT(1)
#define PORT_REG_PHYS_CTRL_SPD100 BIT(0)
#define PORT_REG_PHYS_CTRL_SPD_MASK (BIT(1) | BIT(0))
#define PORT_REG_CTRL_PSTATE_SHIFT 0
@ -124,14 +117,12 @@
#define SERDES_REG_CTRL_1_FORCE_LINK BIT(10)
#define PHY_REG_CTRL1_ENERGY_DET_SHIFT 8
#define PHY_REG_CTRL1_ENERGY_DET_WIDTH 2
/* Field values */
#define PORT_REG_CTRL_PSTATE_DISABLED 0
#define PORT_REG_CTRL_PSTATE_FORWARD 3
#define PHY_REG_CTRL1_ENERGY_DET_OFF 0
#define PHY_REG_CTRL1_ENERGY_DET_SENSE_PULSE 1
#define PHY_REG_CTRL1_ENERGY_DET_SENSE_ONLY 2
#define PHY_REG_CTRL1_ENERGY_DET_SENSE_XMIT 3
@ -182,17 +173,32 @@
#endif
/* ID register values for different switch models */
#define PORT_SWITCH_ID_6020 0x0200
#define PORT_SWITCH_ID_6070 0x0700
#define PORT_SWITCH_ID_6071 0x0710
#define PORT_SWITCH_ID_6096 0x0980
#define PORT_SWITCH_ID_6097 0x0990
#define PORT_SWITCH_ID_6172 0x1720
#define PORT_SWITCH_ID_6176 0x1760
#define PORT_SWITCH_ID_6220 0x2200
#define PORT_SWITCH_ID_6240 0x2400
#define PORT_SWITCH_ID_6250 0x2500
#define PORT_SWITCH_ID_6352 0x3520
struct mv88e61xx_phy_priv {
struct mii_dev *mdio_bus;
int smi_addr;
int id;
int port_count; /* Number of switch ports */
int port_reg_base; /* Base of the switch port registers */
u16 port_stat_link_mask;/* Bitmask for port link status bits */
u16 port_stat_dup_mask; /* Bitmask for port duplex status bits */
u8 port_stat_speed_width;/* Width of speed status bitfield */
u8 global1; /* Offset of Switch Global 1 registers */
u8 global2; /* Offset of Switch Global 2 registers */
u8 phy_ctrl1_en_det_shift; /* 'EDet' bit field offset */
u8 phy_ctrl1_en_det_width; /* Width of 'EDet' bit field */
u8 phy_ctrl1_en_det_ctrl; /* 'EDet' control value */
};
static inline int smi_cmd(int cmd, int addr, int reg)
@ -329,11 +335,12 @@ static int mv88e61xx_reg_write(struct phy_device *phydev, int dev, int reg,
static int mv88e61xx_phy_wait(struct phy_device *phydev)
{
struct mv88e61xx_phy_priv *priv = phydev->priv;
int val;
u32 timeout = 100;
do {
val = mv88e61xx_reg_read(phydev, DEVADDR_GLOBAL_2,
val = mv88e61xx_reg_read(phydev, priv->global2,
GLOBAL2_REG_PHY_CMD);
if (val >= 0 && (val & SMI_BUSY) == 0)
return 0;
@ -347,13 +354,15 @@ static int mv88e61xx_phy_wait(struct phy_device *phydev)
static int mv88e61xx_phy_read_indirect(struct mii_dev *smi_wrapper, int dev,
int devad, int reg)
{
struct mv88e61xx_phy_priv *priv;
struct phy_device *phydev;
int res;
phydev = (struct phy_device *)smi_wrapper->priv;
priv = phydev->priv;
/* Issue command to read */
res = mv88e61xx_reg_write(phydev, DEVADDR_GLOBAL_2,
res = mv88e61xx_reg_write(phydev, priv->global2,
GLOBAL2_REG_PHY_CMD,
smi_cmd_read(dev, reg));
@ -363,25 +372,27 @@ static int mv88e61xx_phy_read_indirect(struct mii_dev *smi_wrapper, int dev,
return res;
/* Read retrieved data */
return mv88e61xx_reg_read(phydev, DEVADDR_GLOBAL_2,
return mv88e61xx_reg_read(phydev, priv->global2,
GLOBAL2_REG_PHY_DATA);
}
static int mv88e61xx_phy_write_indirect(struct mii_dev *smi_wrapper, int dev,
int devad, int reg, u16 data)
{
struct mv88e61xx_phy_priv *priv;
struct phy_device *phydev;
int res;
phydev = (struct phy_device *)smi_wrapper->priv;
priv = phydev->priv;
/* Set the data to write */
res = mv88e61xx_reg_write(phydev, DEVADDR_GLOBAL_2,
res = mv88e61xx_reg_write(phydev, priv->global2,
GLOBAL2_REG_PHY_DATA, data);
if (res < 0)
return res;
/* Issue the write command */
res = mv88e61xx_reg_write(phydev, DEVADDR_GLOBAL_2,
res = mv88e61xx_reg_write(phydev, priv->global2,
GLOBAL2_REG_PHY_CMD,
smi_cmd_write(dev, reg));
if (res < 0)
@ -408,13 +419,18 @@ static int mv88e61xx_phy_write(struct phy_device *phydev, int phy,
static int mv88e61xx_port_read(struct phy_device *phydev, u8 port, u8 reg)
{
return mv88e61xx_reg_read(phydev, DEVADDR_PORT(port), reg);
struct mv88e61xx_phy_priv *priv = phydev->priv;
return mv88e61xx_reg_read(phydev, priv->port_reg_base + port, reg);
}
static int mv88e61xx_port_write(struct phy_device *phydev, u8 port, u8 reg,
u16 val)
{
return mv88e61xx_reg_write(phydev, DEVADDR_PORT(port), reg, val);
struct mv88e61xx_phy_priv *priv = phydev->priv;
return mv88e61xx_reg_write(phydev, priv->port_reg_base + port,
reg, val);
}
static int mv88e61xx_set_page(struct phy_device *phydev, u8 phy, u8 page)
@ -515,12 +531,13 @@ static int mv88e61xx_parse_status(struct phy_device *phydev)
static int mv88e61xx_switch_reset(struct phy_device *phydev)
{
struct mv88e61xx_phy_priv *priv = phydev->priv;
int time;
int val;
u8 port;
/* Disable all ports */
for (port = 0; port < PORT_COUNT; port++) {
for (port = 0; port < priv->port_count; port++) {
val = mv88e61xx_port_read(phydev, port, PORT_REG_CTRL);
if (val < 0)
return val;
@ -536,19 +553,19 @@ static int mv88e61xx_switch_reset(struct phy_device *phydev)
udelay(2000);
/* Reset switch */
val = mv88e61xx_reg_read(phydev, DEVADDR_GLOBAL_1, GLOBAL1_CTRL);
val = mv88e61xx_reg_read(phydev, priv->global1, GLOBAL1_CTRL);
if (val < 0)
return val;
val |= GLOBAL1_CTRL_SWRESET;
val = mv88e61xx_reg_write(phydev, DEVADDR_GLOBAL_1,
GLOBAL1_CTRL, val);
val = mv88e61xx_reg_write(phydev, priv->global1,
GLOBAL1_CTRL, val);
if (val < 0)
return val;
/* Wait up to 1 second for switch reset complete */
for (time = 1000; time; time--) {
val = mv88e61xx_reg_read(phydev, DEVADDR_GLOBAL_1,
GLOBAL1_CTRL);
val = mv88e61xx_reg_read(phydev, priv->global1,
GLOBAL1_CTRL);
if (val >= 0 && ((val & GLOBAL1_CTRL_SWRESET) == 0))
break;
udelay(1000);
@ -628,6 +645,7 @@ static int mv88e61xx_port_set_vlan(struct phy_device *phydev, u8 port,
static int mv88e61xx_read_port_config(struct phy_device *phydev, u8 port)
{
struct mv88e61xx_phy_priv *priv = phydev->priv;
int res;
int val;
bool forced = false;
@ -635,7 +653,7 @@ static int mv88e61xx_read_port_config(struct phy_device *phydev, u8 port)
val = mv88e61xx_port_read(phydev, port, PORT_REG_STATUS);
if (val < 0)
return val;
if (!(val & PORT_REG_STATUS_LINK)) {
if (!(val & priv->port_stat_link_mask)) {
/* Temporarily force link to read port configuration */
u32 timeout = 100;
forced = true;
@ -658,7 +676,7 @@ static int mv88e61xx_read_port_config(struct phy_device *phydev, u8 port)
res = -EIO;
goto unforce;
}
if (val & PORT_REG_STATUS_LINK)
if (val & priv->port_stat_link_mask)
break;
} while (--timeout);
@ -668,13 +686,13 @@ static int mv88e61xx_read_port_config(struct phy_device *phydev, u8 port)
}
}
if (val & PORT_REG_STATUS_DUPLEX)
if (val & priv->port_stat_dup_mask)
phydev->duplex = DUPLEX_FULL;
else
phydev->duplex = DUPLEX_HALF;
val = bitfield_extract(val, PORT_REG_STATUS_SPEED_SHIFT,
PORT_REG_STATUS_SPEED_WIDTH);
priv->port_stat_speed_width);
switch (val) {
case PORT_REG_STATUS_SPEED_1000:
phydev->speed = SPEED_1000;
@ -707,6 +725,7 @@ unforce:
static int mv88e61xx_fixed_port_setup(struct phy_device *phydev, u8 port)
{
struct mv88e61xx_phy_priv *priv = phydev->priv;
int val;
val = mv88e61xx_port_read(phydev, port, PORT_REG_PHYS_CTRL);
@ -714,13 +733,19 @@ static int mv88e61xx_fixed_port_setup(struct phy_device *phydev, u8 port)
return val;
val &= ~(PORT_REG_PHYS_CTRL_SPD_MASK |
PORT_REG_PHYS_CTRL_FC_VALUE);
val |= PORT_REG_PHYS_CTRL_PCS_AN_EN |
PORT_REG_PHYS_CTRL_PCS_AN_RST |
PORT_REG_PHYS_CTRL_FC_FORCE |
PORT_REG_PHYS_CTRL_FC_VALUE |
PORT_REG_PHYS_CTRL_FC_FORCE);
val |= PORT_REG_PHYS_CTRL_FC_FORCE |
PORT_REG_PHYS_CTRL_DUPLEX_VALUE |
PORT_REG_PHYS_CTRL_DUPLEX_FORCE |
PORT_REG_PHYS_CTRL_SPD1000;
PORT_REG_PHYS_CTRL_DUPLEX_FORCE;
if (priv->id == PORT_SWITCH_ID_6071) {
val |= PORT_REG_PHYS_CTRL_SPD100;
} else {
val |= PORT_REG_PHYS_CTRL_PCS_AN_EN |
PORT_REG_PHYS_CTRL_PCS_AN_RST |
PORT_REG_PHYS_CTRL_SPD1000;
}
if (port == CONFIG_MV88E61XX_CPU_PORT)
val |= PORT_REG_PHYS_CTRL_LINK_VALUE |
@ -732,22 +757,23 @@ static int mv88e61xx_fixed_port_setup(struct phy_device *phydev, u8 port)
static int mv88e61xx_set_cpu_port(struct phy_device *phydev)
{
struct mv88e61xx_phy_priv *priv = phydev->priv;
int val;
/* Set CPUDest */
val = mv88e61xx_reg_read(phydev, DEVADDR_GLOBAL_1, GLOBAL1_MON_CTRL);
val = mv88e61xx_reg_read(phydev, priv->global1, GLOBAL1_MON_CTRL);
if (val < 0)
return val;
val = bitfield_replace(val, GLOBAL1_MON_CTRL_CPUDEST_SHIFT,
GLOBAL1_MON_CTRL_CPUDEST_WIDTH,
CONFIG_MV88E61XX_CPU_PORT);
val = mv88e61xx_reg_write(phydev, DEVADDR_GLOBAL_1,
GLOBAL1_MON_CTRL, val);
val = mv88e61xx_reg_write(phydev, priv->global1,
GLOBAL1_MON_CTRL, val);
if (val < 0)
return val;
/* Allow CPU to route to any port */
val = PORT_MASK & ~(1 << CONFIG_MV88E61XX_CPU_PORT);
val = PORT_MASK(priv->port_count) & ~(1 << CONFIG_MV88E61XX_CPU_PORT);
val = mv88e61xx_port_set_vlan(phydev, CONFIG_MV88E61XX_CPU_PORT, val);
if (val < 0)
return val;
@ -821,6 +847,7 @@ static int mv88e61xx_phy_enable(struct phy_device *phydev, u8 phy)
static int mv88e61xx_phy_setup(struct phy_device *phydev, u8 phy)
{
struct mv88e61xx_phy_priv *priv = phydev->priv;
int val;
/*
@ -830,9 +857,9 @@ static int mv88e61xx_phy_setup(struct phy_device *phydev, u8 phy)
val = mv88e61xx_phy_read(phydev, phy, PHY_REG_CTRL1);
if (val < 0)
return val;
val = bitfield_replace(val, PHY_REG_CTRL1_ENERGY_DET_SHIFT,
PHY_REG_CTRL1_ENERGY_DET_WIDTH,
PHY_REG_CTRL1_ENERGY_DET_SENSE_XMIT);
val = bitfield_replace(val, priv->phy_ctrl1_en_det_shift,
priv->phy_ctrl1_en_det_width,
priv->phy_ctrl1_en_det_ctrl);
val = mv88e61xx_phy_write(phydev, phy, PHY_REG_CTRL1, val);
if (val < 0)
return val;
@ -856,6 +883,48 @@ static int mv88e61xx_phy_config_port(struct phy_device *phydev, u8 phy)
return 0;
}
/*
* This function is used to pre-configure the required register
* offsets, so that the indirect register access to the PHY registers
* is possible. This is necessary to be able to read the PHY ID
* while driver probing or in get_phy_id(). The globalN register
* offsets must be initialized correctly for a detected switch,
* otherwise detection of the PHY ID won't work!
*/
static int mv88e61xx_priv_reg_offs_pre_init(struct phy_device *phydev)
{
struct mv88e61xx_phy_priv *priv = phydev->priv;
/*
* Initial 'port_reg_base' value must be an offset of existing
* port register, then reading the ID should succeed. First, try
* to read via port registers with device address 0x10 (88E6096
* and compatible switches).
*/
priv->port_reg_base = 0x10;
priv->id = mv88e61xx_get_switch_id(phydev);
if (priv->id != 0xfff0) {
priv->global1 = 0x1B;
priv->global2 = 0x1C;
return 0;
}
/*
* Now try via port registers with device address 0x08
* (88E6020 and compatible switches).
*/
priv->port_reg_base = 0x08;
priv->id = mv88e61xx_get_switch_id(phydev);
if (priv->id != 0xfff0) {
priv->global1 = 0x0F;
priv->global2 = 0x07;
return 0;
}
debug("%s Unknown ID 0x%x\n", __func__, priv->id);
return -ENODEV;
}
static int mv88e61xx_probe(struct phy_device *phydev)
{
struct mii_dev *smi_wrapper;
@ -910,13 +979,57 @@ static int mv88e61xx_probe(struct phy_device *phydev)
phydev->priv = priv;
priv->id = mv88e61xx_get_switch_id(phydev);
res = mv88e61xx_priv_reg_offs_pre_init(phydev);
if (res < 0)
return res;
debug("%s ID 0x%x\n", __func__, priv->id);
switch (priv->id) {
case PORT_SWITCH_ID_6096:
case PORT_SWITCH_ID_6097:
case PORT_SWITCH_ID_6172:
case PORT_SWITCH_ID_6176:
case PORT_SWITCH_ID_6240:
case PORT_SWITCH_ID_6352:
priv->port_count = 11;
priv->port_stat_link_mask = BIT(11);
priv->port_stat_dup_mask = BIT(10);
priv->port_stat_speed_width = 2;
priv->phy_ctrl1_en_det_shift = 8;
priv->phy_ctrl1_en_det_width = 2;
priv->phy_ctrl1_en_det_ctrl =
PHY_REG_CTRL1_ENERGY_DET_SENSE_XMIT;
break;
case PORT_SWITCH_ID_6020:
case PORT_SWITCH_ID_6070:
case PORT_SWITCH_ID_6071:
case PORT_SWITCH_ID_6220:
case PORT_SWITCH_ID_6250:
priv->port_count = 7;
priv->port_stat_link_mask = BIT(12);
priv->port_stat_dup_mask = BIT(9);
priv->port_stat_speed_width = 1;
priv->phy_ctrl1_en_det_shift = 14;
priv->phy_ctrl1_en_det_width = 1;
priv->phy_ctrl1_en_det_ctrl =
PHY_REG_CTRL1_ENERGY_DET_SENSE_PULSE;
break;
default:
free(priv);
return -ENODEV;
}
res = mdio_register(smi_wrapper);
if (res)
printf("Failed to register SMI bus\n");
return 0;
}
static int mv88e61xx_phy_config(struct phy_device *phydev)
{
struct mv88e61xx_phy_priv *priv = phydev->priv;
int res;
int i;
int ret = -1;
@ -925,7 +1038,7 @@ static int mv88e61xx_phy_config(struct phy_device *phydev)
if (res < 0)
return res;
for (i = 0; i < PORT_COUNT; i++) {
for (i = 0; i < priv->port_count; i++) {
if ((1 << i) & CONFIG_MV88E61XX_PHY_PORTS) {
phydev->addr = i;
@ -988,13 +1101,14 @@ static int mv88e61xx_phy_is_connected(struct phy_device *phydev)
static int mv88e61xx_phy_startup(struct phy_device *phydev)
{
struct mv88e61xx_phy_priv *priv = phydev->priv;
int i;
int link = 0;
int res;
int speed = phydev->speed;
int duplex = phydev->duplex;
for (i = 0; i < PORT_COUNT; i++) {
for (i = 0; i < priv->port_count; i++) {
if ((1 << i) & CONFIG_MV88E61XX_PHY_PORTS) {
phydev->addr = i;
if (!mv88e61xx_phy_is_connected(phydev))
@ -1040,10 +1154,22 @@ static struct phy_driver mv88e609x_driver = {
.shutdown = &genphy_shutdown,
};
static struct phy_driver mv88e6071_driver = {
.name = "Marvell MV88E6071",
.uid = 0x1410db0,
.mask = 0xfffffff0,
.features = PHY_BASIC_FEATURES | SUPPORTED_MII,
.probe = mv88e61xx_probe,
.config = mv88e61xx_phy_config,
.startup = mv88e61xx_phy_startup,
.shutdown = &genphy_shutdown,
};
int phy_mv88e61xx_init(void)
{
phy_register(&mv88e61xx_driver);
phy_register(&mv88e609x_driver);
phy_register(&mv88e6071_driver);
return 0;
}
@ -1068,6 +1194,16 @@ int get_phy_id(struct mii_dev *bus, int smi_addr, int devad, u32 *phy_id)
temp_phy.priv = &temp_priv;
temp_mii.priv = &temp_phy;
/*
* get_phy_id() can be called by framework before mv88e61xx driver
* probing, in this case the global register offsets are not
* initialized yet. Do this initialization here before indirect
* PHY register access.
*/
val = mv88e61xx_priv_reg_offs_pre_init(&temp_phy);
if (val < 0)
return val;
val = mv88e61xx_phy_read_indirect(&temp_mii, 0, devad, MII_PHYSID1);
if (val < 0)
return -EIO;

View File

@ -256,11 +256,11 @@ int genphy_update_link(struct phy_device *phydev)
return -EINTR;
}
if ((i++ % 500) == 0)
if ((i++ % 10) == 0)
printf(".");
udelay(1000); /* 1 ms */
mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMSR);
mdelay(50); /* 50 ms */
}
printf(" done\n");
phydev->link = 1;
@ -997,7 +997,7 @@ struct phy_device *phy_connect(struct mii_dev *bus, int addr,
#endif
{
struct phy_device *phydev = NULL;
uint mask = (addr > 0) ? (1 << addr) : 0xffffffff;
uint mask = (addr >= 0) ? (1 << addr) : 0xffffffff;
#ifdef CONFIG_PHY_FIXED
phydev = phy_connect_fixed(bus, dev, interface);

View File

@ -253,6 +253,7 @@ static struct {
{"RTL-8169sc/8110sc", 0x18, 0xff7e1880,},
{"RTL-8168b/8111sb", 0x30, 0xff7e1880,},
{"RTL-8168b/8111sb", 0x38, 0xff7e1880,},
{"RTL-8168c/8111c", 0x3c, 0xff7e1880,},
{"RTL-8168d/8111d", 0x28, 0xff7e1880,},
{"RTL-8168evl/8111evl", 0x2e, 0xff7e1880,},
{"RTL-8168/8111g", 0x4c, 0xff7e1880,},

View File

@ -99,7 +99,6 @@ struct am65_cpsw_common {
u32 port_num;
struct am65_cpsw_port ports[AM65_CPSW_CPSWNU_MAX_PORTS];
u32 rflow_id_base;
struct mii_dev *bus;
u32 bus_freq;
@ -276,6 +275,7 @@ static int am65_cpsw_start(struct udevice *dev)
struct am65_cpsw_common *common = priv->cpsw_common;
struct am65_cpsw_port *port = &common->ports[priv->port_id];
struct am65_cpsw_port *port0 = &common->ports[0];
struct ti_udma_drv_chan_cfg_data *dma_rx_cfg_data;
int ret, i;
ret = power_domain_on(&common->pwrdmn);
@ -341,8 +341,11 @@ static int am65_cpsw_start(struct udevice *dev)
writel(PKTSIZE_ALIGN, port0->port_base + AM65_CPSW_PN_RX_MAXLEN_REG);
/* set base flow_id */
writel(common->rflow_id_base,
dma_get_cfg(&common->dma_rx, 0, (void **)&dma_rx_cfg_data);
writel(dma_rx_cfg_data->flow_id_base,
port0->port_base + AM65_CPSW_P0_FLOW_ID_REG);
dev_info(dev, "K3 CPSW: rflow_id_base: %u\n",
dma_rx_cfg_data->flow_id_base);
/* Reset and enable the ALE */
writel(AM65_CPSW_ALE_CTL_REG_ENABLE | AM65_CPSW_ALE_CTL_REG_RESET_TBL |
@ -669,11 +672,6 @@ static int am65_cpsw_probe_cpsw(struct udevice *dev)
AM65_CPSW_CPSW_NU_ALE_BASE;
cpsw_common->mdio_base = cpsw_common->ss_base + AM65_CPSW_MDIO_BASE;
cpsw_common->rflow_id_base = 0;
cpsw_common->rflow_id_base =
dev_read_u32_default(dev, "ti,rx-flow-id-base",
cpsw_common->rflow_id_base);
ports_np = dev_read_subnode(dev, "ports");
if (!ofnode_valid(ports_np)) {
ret = -ENOENT;
@ -761,12 +759,11 @@ static int am65_cpsw_probe_cpsw(struct udevice *dev)
if (ret)
goto out;
dev_info(dev, "K3 CPSW: nuss_ver: 0x%08X cpsw_ver: 0x%08X ale_ver: 0x%08X Ports:%u rflow_id_base:%u mdio_freq:%u\n",
dev_info(dev, "K3 CPSW: nuss_ver: 0x%08X cpsw_ver: 0x%08X ale_ver: 0x%08X Ports:%u mdio_freq:%u\n",
readl(cpsw_common->ss_base),
readl(cpsw_common->cpsw_base),
readl(cpsw_common->ale_base),
cpsw_common->port_num,
cpsw_common->rflow_id_base,
cpsw_common->bus_freq);
out:
@ -777,6 +774,7 @@ out:
static const struct udevice_id am65_cpsw_nuss_ids[] = {
{ .compatible = "ti,am654-cpsw-nuss" },
{ .compatible = "ti,j721e-cpsw-nuss" },
{ }
};

View File

@ -108,6 +108,17 @@ struct dma_ops {
* @return zero on success, or -ve error code.
*/
int (*send)(struct dma *dma, void *src, size_t len, void *metadata);
/**
* get_cfg() - Get DMA channel configuration for client's use
*
* @dma: The DMA Channel to manipulate
* @cfg_id: DMA provider specific ID to identify what
* configuration data client needs
* @data: Pointer to store pointer to DMA driver specific
* configuration data for the given cfg_id (output param)
* @return zero on success, or -ve error code.
*/
int (*get_cfg)(struct dma *dma, u32 cfg_id, void **data);
#endif /* CONFIG_DMA_CHANNELS */
/**
* transfer() - Issue a DMA transfer. The implementation must

View File

@ -290,6 +290,18 @@ int dma_receive(struct dma *dma, void **dst, void *metadata);
* @return zero on success, or -ve error code.
*/
int dma_send(struct dma *dma, void *src, size_t len, void *metadata);
/**
* dma_get_cfg() - Get DMA channel configuration for client's use
*
* @dma: The DMA Channel to manipulate
* @cfg_id: DMA provider specific ID to identify what
* configuration data client needs
* @cfg_data: Pointer to store pointer to DMA driver specific
* configuration data for the given cfg_id (output param)
* @return zero on success, or -ve error code.
*/
int dma_get_cfg(struct dma *dma, u32 cfg_id, void **cfg_data);
#endif /* CONFIG_DMA_CHANNELS */
/*

View File

@ -45,5 +45,6 @@
#define DP83867_CLK_O_SEL_CHN_C_TCLK 0xA
#define DP83867_CLK_O_SEL_CHN_D_TCLK 0xB
#define DP83867_CLK_O_SEL_REF_CLK 0xC
/* Special flag to indicate clock should be off */
#define DP83867_CLK_O_SEL_OFF 0xFFFFFFFF
#endif

View File

@ -21,4 +21,23 @@ struct ti_udma_drv_packet_data {
u32 dest_tag;
};
/**
* struct ti_udma_drv_chan_cfg_data - TI UDMA per channel specific
* configuration data
*
* @flow_id_base: Start index of flow ID allocated to this channel
* @flow_id_cnt: Number of flows allocated for this channel starting at
* flow_id_base
*
* TI UDMA channel specific data returned as part of dma_get_cfg() call
* from the DMA client driver.
*/
struct ti_udma_drv_chan_cfg_data {
u32 flow_id_base;
u32 flow_id_cnt;
};
/* TI UDMA specific flag IDs for dma_get_cfg() call */
#define TI_UDMA_CHAN_PRIV_INFO 0
#endif /* __TI_UDMA_H */

View File

@ -154,17 +154,29 @@ void dm_mdio_probe_devices(void);
/**
* dm_mdio_phy_connect - Wrapper over phy_connect for DM MDIO
*
* @dev: mdio dev
* @addr: PHY address on MDIO bus
* @mdiodev: mdio device the PHY is accesible on
* @phyaddr: PHY address on MDIO bus
* @ethdev: ethernet device to connect to the PHY
* @interface: MAC-PHY protocol
*
* @return pointer to phy_device, or 0 on error
*/
struct phy_device *dm_mdio_phy_connect(struct udevice *dev, int addr,
struct phy_device *dm_mdio_phy_connect(struct udevice *mdiodev, int phyaddr,
struct udevice *ethdev,
phy_interface_t interface);
/**
* dm_eth_phy_connect - Connect an Eth device to a PHY based on device tree
*
* Picks up the DT phy-handle and phy-mode from ethernet device node and
* connects the ethernet device to the linked PHY.
*
* @ethdev: ethernet device
*
* @return pointer to phy_device, or 0 on error
*/
struct phy_device *dm_eth_phy_connect(struct udevice *ethdev);
#endif
#ifdef CONFIG_DM_MDIO_MUX

View File

@ -826,15 +826,29 @@ static inline void net_random_ethaddr(uchar *addr)
addr[0] |= 0x02; /* set local assignment bit (IEEE802) */
}
/**
* string_to_enetaddr() - Parse a MAC address
*
* Convert a string MAC address
*
* Implemented in lib/net_utils.c (built unconditionally)
*
* @addr: MAC address in aa:bb:cc:dd:ee:ff format, where each part is a 2-digit
* hex value
* @enetaddr: Place to put MAC address (6 bytes)
*/
void string_to_enetaddr(const char *addr, uint8_t *enetaddr);
/* Convert an IP address to a string */
void ip_to_string(struct in_addr x, char *s);
/**
* string_to_ip() - Convert a string to ip address
*
* @s: String to conver, in the format format a.b.c.d, where each value is a
* decimal number from 0 to 255
* @return IP address, or 0 if invalid
* Implemented in lib/net_utils.c (built unconditionally)
*
* @s: Input string to parse
* @return: in_addr struct containing the parsed IP address
*/
struct in_addr string_to_ip(const char *s);
@ -880,19 +894,6 @@ unsigned int random_port(void);
*/
int update_tftp(ulong addr, char *interface, char *devstring);
/**********************************************************************/
/**
* eth_parse_enetaddr() - Parse a MAC address
*
* Convert a string MAC address
*
* @addr: MAC address in aa:bb:cc:dd:ee:ff format, where each part is a 2-digit
* hex value
* @enetaddr: Place to put MAC address (6 bytes)
*/
void eth_parse_enetaddr(const char *addr, uint8_t *enetaddr);
/**
* env_get_ip() - Convert an environment value to to an ip address
*
@ -905,5 +906,4 @@ static inline struct in_addr env_get_ip(char *var)
{
return string_to_ip(env_get(var));
}
#endif /* __NET_H__ */

View File

@ -115,6 +115,9 @@ struct phy_driver {
u16 val);
struct list_head list;
/* driver private data */
ulong data;
};
struct phy_device {

View File

@ -31,6 +31,8 @@ typedef enum {
PHY_INTERFACE_MODE_XLAUI,
PHY_INTERFACE_MODE_CAUI2,
PHY_INTERFACE_MODE_CAUI4,
PHY_INTERFACE_MODE_XFI,
PHY_INTERFACE_MODE_USXGMII,
PHY_INTERFACE_MODE_NONE, /* Must be last */
PHY_INTERFACE_MODE_COUNT,
@ -58,6 +60,8 @@ static const char * const phy_interface_strings[] = {
[PHY_INTERFACE_MODE_XLAUI] = "xlaui4",
[PHY_INTERFACE_MODE_CAUI2] = "caui2",
[PHY_INTERFACE_MODE_CAUI4] = "caui4",
[PHY_INTERFACE_MODE_XFI] = "xfi",
[PHY_INTERFACE_MODE_USXGMII] = "usxgmii",
[PHY_INTERFACE_MODE_NONE] = "",
};

View File

@ -41,3 +41,18 @@ struct in_addr string_to_ip(const char *s)
addr.s_addr = htonl(addr.s_addr);
return addr;
}
void string_to_enetaddr(const char *addr, uint8_t *enetaddr)
{
char *end;
int i;
if (!enetaddr)
return;
for (i = 0; i < 6; ++i) {
enetaddr[i] = addr ? simple_strtoul(addr, &end, 16) : 0;
if (addr)
addr = (*end) ? end + 1 : end;
}
}

View File

@ -320,7 +320,6 @@ static char *device_path_string(char *buf, char *end, void *dp, int field_width,
#endif
#endif
#ifdef CONFIG_CMD_NET
static char *mac_address_string(char *buf, char *end, u8 *addr, int field_width,
int precision, int flags)
{
@ -382,7 +381,6 @@ static char *ip4_addr_string(char *buf, char *end, u8 *addr, int field_width,
return string(buf, end, ip4_addr, field_width, precision,
flags & ~SPECIAL);
}
#endif
#ifdef CONFIG_LIB_UUID
/*
@ -474,7 +472,6 @@ static char *pointer(const char *fmt, char *buf, char *end, void *ptr,
break;
}
break;
#ifdef CONFIG_CMD_NET
case 'm':
flags |= SPECIAL;
/* Fallthrough */
@ -493,7 +490,6 @@ static char *pointer(const char *fmt, char *buf, char *end, void *ptr,
precision, flags);
flags &= ~SPECIAL;
break;
#endif
#ifdef CONFIG_LIB_UUID
case 'U':
return uuid_string(buf, end, ptr, field_width, precision,

View File

@ -31,7 +31,7 @@ config IP_DEFRAG
config TFTP_BLOCKSIZE
int "TFTP block size"
default 512
default 1468
help
Default TFTP block size.

View File

@ -227,7 +227,7 @@ static int on_ethaddr(const char *name, const char *value, enum env_op op,
switch (op) {
case env_op_create:
case env_op_overwrite:
eth_parse_enetaddr(value, pdata->enetaddr);
string_to_enetaddr(value, pdata->enetaddr);
eth_write_hwaddr(dev);
break;
case env_op_delete:
@ -420,20 +420,25 @@ int eth_initialize(void)
bootstage_mark(BOOTSTAGE_ID_NET_ETH_INIT);
do {
if (num_devices)
printf(", ");
if (dev->seq != -1) {
if (num_devices)
printf(", ");
printf("eth%d: %s", dev->seq, dev->name);
printf("eth%d: %s", dev->seq, dev->name);
if (ethprime && dev == prime_dev)
printf(" [PRIME]");
if (ethprime && dev == prime_dev)
printf(" [PRIME]");
}
eth_write_hwaddr(dev);
if (dev->seq != -1)
num_devices++;
uclass_next_device_check(&dev);
num_devices++;
} while (dev);
if (!num_devices)
printf("No ethernet found.\n");
putc('\n');
}

View File

@ -117,7 +117,7 @@ static int on_ethaddr(const char *name, const char *value, enum env_op op,
switch (op) {
case env_op_create:
case env_op_overwrite:
eth_parse_enetaddr(value, dev->enetaddr);
string_to_enetaddr(value, dev->enetaddr);
eth_write_hwaddr(dev, "eth", dev->index);
break;
case env_op_delete:

View File

@ -10,6 +10,16 @@
#include <dm/device-internal.h>
#include <dm/uclass-internal.h>
/* DT node properties for MAC-PHY interface */
#define PHY_MODE_STR_CNT 2
static const char *phy_mode_str[PHY_MODE_STR_CNT] = { "phy-mode",
"phy-connection-type" };
/* DT node properties that reference a PHY node */
#define PHY_HANDLE_STR_CNT 3
const char *phy_handle_str[PHY_HANDLE_STR_CNT] = { "phy-handle",
"phy",
"phy-device" };
void dm_mdio_probe_devices(void)
{
struct udevice *it;
@ -104,16 +114,96 @@ static int dm_mdio_pre_remove(struct udevice *dev)
return 0;
}
struct phy_device *dm_mdio_phy_connect(struct udevice *dev, int addr,
struct phy_device *dm_mdio_phy_connect(struct udevice *mdiodev, int phyaddr,
struct udevice *ethdev,
phy_interface_t interface)
{
struct mdio_perdev_priv *pdata = dev_get_uclass_priv(dev);
struct mdio_perdev_priv *pdata = dev_get_uclass_priv(mdiodev);
if (device_probe(dev))
return 0;
if (device_probe(mdiodev))
return NULL;
return phy_connect(pdata->mii_bus, addr, ethdev, interface);
return phy_connect(pdata->mii_bus, phyaddr, ethdev, interface);
}
static struct phy_device *dm_eth_connect_phy_handle(struct udevice *ethdev,
phy_interface_t interface)
{
u32 phy_addr;
struct udevice *mdiodev;
struct phy_device *phy;
struct ofnode_phandle_args phandle = {.node = ofnode_null()};
int i;
for (i = 0; i < PHY_HANDLE_STR_CNT; i++)
if (!dev_read_phandle_with_args(ethdev, phy_handle_str[i], NULL,
0, 0, &phandle))
break;
if (!ofnode_valid(phandle.node)) {
dev_dbg(dev, "can't find PHY node\n");
return NULL;
}
/*
* reading 'reg' directly should be fine. This is a PHY node, the
* address is always size 1 and requires no translation
*/
if (ofnode_read_u32(phandle.node, "reg", &phy_addr)) {
dev_dbg(ethdev, "missing reg property in phy node\n");
return NULL;
}
if (uclass_get_device_by_ofnode(UCLASS_MDIO,
ofnode_get_parent(phandle.node),
&mdiodev)) {
dev_dbg(dev, "can't find MDIO bus for node %s\n",
ofnode_get_name(ofnode_get_parent(phandle.node)));
return NULL;
}
phy = dm_mdio_phy_connect(mdiodev, phy_addr, ethdev, interface);
if (phy)
phy->node = phandle.node;
return phy;
}
/* Connect to a PHY linked in eth DT node */
struct phy_device *dm_eth_phy_connect(struct udevice *ethdev)
{
const char *if_str;
phy_interface_t interface;
struct phy_device *phy;
int i;
if (!ofnode_valid(ethdev->node)) {
debug("%s: supplied eth dev has no DT node!\n", ethdev->name);
return NULL;
}
interface = PHY_INTERFACE_MODE_NONE;
for (i = 0; i < PHY_MODE_STR_CNT; i++) {
if_str = ofnode_read_string(ethdev->node, phy_mode_str[i]);
if (if_str) {
interface = phy_get_interface_by_name(if_str);
break;
}
}
if (interface < 0)
interface = PHY_INTERFACE_MODE_NONE;
if (interface == PHY_INTERFACE_MODE_NONE)
dev_dbg(ethdev, "can't find interface mode, default to NONE\n");
phy = dm_eth_connect_phy_handle(ethdev, interface);
if (!phy)
return NULL;
phy->interface = interface;
return phy;
}
UCLASS_DRIVER(mdio) = {

View File

@ -308,7 +308,7 @@ U_BOOT_ENV_CALLBACK(dnsip, on_dnsip);
*/
void net_auto_load(void)
{
#if defined(CONFIG_CMD_NFS)
#if defined(CONFIG_CMD_NFS) && !defined(CONFIG_SPL_BUILD)
const char *s = env_get("autoload");
if (s != NULL && strcmp(s, "NFS") == 0) {
@ -496,7 +496,7 @@ restart:
ping_start();
break;
#endif
#if defined(CONFIG_CMD_NFS)
#if defined(CONFIG_CMD_NFS) && !defined(CONFIG_SPL_BUILD)
case NFS:
nfs_start();
break;
@ -1271,7 +1271,7 @@ void net_process_received_packet(uchar *in_packet, int len)
#ifdef CONFIG_UDP_CHECKSUM
if (ip->udp_xsum != 0) {
ulong xsum;
ushort *sumptr;
u8 *sumptr;
ushort sumlen;
xsum = ip->ip_p;
@ -1282,22 +1282,16 @@ void net_process_received_packet(uchar *in_packet, int len)
xsum += (ntohl(ip->ip_dst.s_addr) >> 0) & 0x0000ffff;
sumlen = ntohs(ip->udp_len);
sumptr = (ushort *)&(ip->udp_src);
sumptr = (u8 *)&ip->udp_src;
while (sumlen > 1) {
ushort sumdata;
sumdata = *sumptr++;
xsum += ntohs(sumdata);
/* inlined ntohs() to avoid alignment errors */
xsum += (sumptr[0] << 8) + sumptr[1];
sumptr += 2;
sumlen -= 2;
}
if (sumlen > 0) {
ushort sumdata;
sumdata = *(unsigned char *)sumptr;
sumdata = (sumdata << 8) & 0xff00;
xsum += sumdata;
}
if (sumlen > 0)
xsum += (sumptr[0] << 8) + sumptr[0];
while ((xsum >> 16) != 0) {
xsum = (xsum & 0x0000ffff) +
((xsum >> 16) & 0x0000ffff);
@ -1625,15 +1619,3 @@ ushort env_get_vlan(char *var)
{
return string_to_vlan(env_get(var));
}
void eth_parse_enetaddr(const char *addr, uint8_t *enetaddr)
{
char *end;
int i;
for (i = 0; i < 6; ++i) {
enetaddr[i] = addr ? simple_strtoul(addr, &end, 16) : 0;
if (addr)
addr = (*end) ? end + 1 : end;
}
}

View File

@ -171,8 +171,13 @@ static inline int store_block(int block, uchar *src, unsigned int len)
void *ptr;
#ifdef CONFIG_LMB
ulong end_addr = tftp_load_addr + tftp_load_size;
if (!end_addr)
end_addr = ULONG_MAX;
if (store_addr < tftp_load_addr ||
store_addr + len > tftp_load_addr + tftp_load_size) {
store_addr + len > end_addr) {
puts("\nTFTP error: ");
puts("trying to overwrite reserved memory...\n");
return -1;