mirror of
https://github.com/brain-hackers/u-boot-brain
synced 2024-06-09 23:36:03 +09:00
Merge branch 'master' of https://gitlab.denx.de/u-boot/custodians/u-boot-net
This commit is contained in:
commit
ac1ca99926
|
@ -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";
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -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>;
|
||||
};
|
||||
|
||||
|
|
|
@ -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";
|
||||
};
|
||||
};
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
16
cmd/Kconfig
16
cmd/Kconfig
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
|
||||
#include "pxe_utils.h"
|
||||
|
||||
#define MAX_TFTP_PATH_LEN 127
|
||||
#define MAX_TFTP_PATH_LEN 512
|
||||
|
||||
bool is_pxe;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
25
doc/device-tree-bindings/net/aquantia-phy.txt
Normal file
25
doc/device-tree-bindings/net/aquantia-phy.txt
Normal 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>;
|
||||
};
|
24
doc/device-tree-bindings/net/phy.txt
Normal file
24
doc/device-tree-bindings/net/phy.txt
Normal 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>;
|
||||
};
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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" },
|
||||
{ }
|
||||
};
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -154,6 +154,7 @@ struct enetc_priv {
|
|||
|
||||
int if_type;
|
||||
struct mii_dev imdio;
|
||||
struct phy_device *phy;
|
||||
};
|
||||
|
||||
/* register accessors */
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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,
|
|
@ -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,
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,},
|
||||
|
|
|
@ -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" },
|
||||
{ }
|
||||
};
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 */
|
||||
|
||||
/*
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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__ */
|
||||
|
|
|
@ -115,6 +115,9 @@ struct phy_driver {
|
|||
u16 val);
|
||||
|
||||
struct list_head list;
|
||||
|
||||
/* driver private data */
|
||||
ulong data;
|
||||
};
|
||||
|
||||
struct phy_device {
|
||||
|
|
|
@ -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] = "",
|
||||
};
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -31,7 +31,7 @@ config IP_DEFRAG
|
|||
|
||||
config TFTP_BLOCKSIZE
|
||||
int "TFTP block size"
|
||||
default 512
|
||||
default 1468
|
||||
help
|
||||
Default TFTP block size.
|
||||
|
||||
|
|
|
@ -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');
|
||||
}
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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) = {
|
||||
|
|
36
net/net.c
36
net/net.c
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue
Block a user