This commit is contained in:
Tom Rini 2021-07-06 12:22:10 -04:00
commit efc0088f06
24 changed files with 614 additions and 59 deletions

View File

@ -922,6 +922,11 @@ F: cmd/nvme.c
F: include/nvme.h F: include/nvme.h
F: doc/develop/driver-model/nvme.rst F: doc/develop/driver-model/nvme.rst
NXP C45 TJA11XX PHY DRIVER
M: Radu Pirea <radu-nicolae.pirea@oss.nxp.com>
S: Maintained
F: drivers/net/phy/nxp-c45-tja11xx.c
ONENAND ONENAND
#M: Lukasz Majewski <l.majewski@majess.pl> #M: Lukasz Majewski <l.majewski@majess.pl>
S: Orphaned (Since 2017-01) S: Orphaned (Since 2017-01)

View File

@ -1,2 +1,9 @@
// SPDX-License-Identifier: GPL-2.0+ // SPDX-License-Identifier: GPL-2.0+
#include "fsl-ls1028a-kontron-sl28-u-boot.dtsi" #include "fsl-ls1028a-kontron-sl28-u-boot.dtsi"
/ {
aliases {
ethernet0 = &mscc_felix_port0;
ethernet1 = &mscc_felix_port1;
};
};

View File

@ -22,4 +22,44 @@
/delete-property/ phy-handle; /delete-property/ phy-handle;
}; };
&enetc2 {
status = "okay";
};
&mscc_felix {
status = "okay";
};
&mscc_felix_port0 {
label = "gbe0";
phy-handle = <&phy0>;
phy-mode = "sgmii";
status = "okay";
};
&mscc_felix_port1 {
label = "gbe1";
phy-handle = <&phy1>;
phy-mode = "sgmii";
status = "okay";
};
&mscc_felix_port4 {
ethernet = <&enetc2>;
status = "okay";
};
/delete-node/ &phy0; /delete-node/ &phy0;
&mdio0 {
phy0: ethernet-phy@5 {
reg = <0x5>;
eee-broken-1000t;
eee-broken-100tx;
};
phy1: ethernet-phy@4 {
reg = <0x4>;
eee-broken-1000t;
eee-broken-100tx;
};
};

View File

@ -20,6 +20,10 @@
#include "fsl-sch-30841.dtsi" #include "fsl-sch-30841.dtsi"
}; };
&enetc2 {
status = "okay";
};
&mscc_felix { &mscc_felix {
status = "okay"; status = "okay";
}; };
@ -47,3 +51,8 @@
phy-mode = "sgmii-2500"; phy-mode = "sgmii-2500";
phy-handle = <&{/i2c@2000000/fpga@66/mux-mdio@54/mdio@40/phy@03}>; phy-handle = <&{/i2c@2000000/fpga@66/mux-mdio@54/mdio@40/phy@03}>;
}; };
&mscc_felix_port4 {
ethernet = <&enetc2>;
status = "okay";
};

View File

@ -9,6 +9,10 @@
#include "fsl-sch-30841.dtsi" #include "fsl-sch-30841.dtsi"
}; };
&enetc2 {
status = "okay";
};
&mscc_felix { &mscc_felix {
status = "okay"; status = "okay";
}; };
@ -24,3 +28,8 @@
phy-mode = "sgmii-2500"; phy-mode = "sgmii-2500";
phy-handle = <&{/i2c@2000000/fpga@66/mux-mdio@54/mdio@40/phy@03}>; phy-handle = <&{/i2c@2000000/fpga@66/mux-mdio@54/mdio@40/phy@03}>;
}; };
&mscc_felix_port4 {
ethernet = <&enetc2>;
status = "okay";
};

View File

@ -34,6 +34,10 @@
#include "fsl-sch-24801.dtsi" #include "fsl-sch-24801.dtsi"
}; };
&enetc2 {
status = "okay";
};
&mscc_felix { &mscc_felix {
status = "okay"; status = "okay";
}; };
@ -61,3 +65,8 @@
phy-mode = "sgmii"; phy-mode = "sgmii";
phy-handle = <&{/i2c@2000000/fpga@66/mux-mdio@54/mdio@40/phy@1f}>; phy-handle = <&{/i2c@2000000/fpga@66/mux-mdio@54/mdio@40/phy@1f}>;
}; };
&mscc_felix_port4 {
ethernet = <&enetc2>;
status = "okay";
};

View File

@ -19,6 +19,10 @@
#include "fsl-sch-24801.dtsi" #include "fsl-sch-24801.dtsi"
}; };
&enetc2 {
status = "okay";
};
&mscc_felix { &mscc_felix {
status = "okay"; status = "okay";
}; };
@ -46,3 +50,8 @@
phy-mode = "sgmii"; phy-mode = "sgmii";
phy-handle = <&{/i2c@2000000/fpga@66/mux-mdio@54/mdio@40/phy@1f}>; phy-handle = <&{/i2c@2000000/fpga@66/mux-mdio@54/mdio@40/phy@1f}>;
}; };
&mscc_felix_port4 {
ethernet = <&enetc2>;
status = "okay";
};

View File

@ -19,6 +19,10 @@
#include "fsl-sch-30841.dtsi" #include "fsl-sch-30841.dtsi"
}; };
&enetc2 {
status = "okay";
};
&mscc_felix { &mscc_felix {
status = "okay"; status = "okay";
}; };
@ -46,3 +50,8 @@
phy-mode = "usxgmii"; phy-mode = "usxgmii";
phy-handle = <&{/i2c@2000000/fpga@66/mux-mdio@54/mdio@50/phy@03}>; phy-handle = <&{/i2c@2000000/fpga@66/mux-mdio@54/mdio@50/phy@03}>;
}; };
&mscc_felix_port4 {
ethernet = <&enetc2>;
status = "okay";
};

View File

@ -13,6 +13,10 @@
#include "fsl-sch-28021.dtsi" #include "fsl-sch-28021.dtsi"
}; };
&enetc2 {
status = "okay";
};
&mscc_felix { &mscc_felix {
status = "okay"; status = "okay";
}; };
@ -40,3 +44,8 @@
phy-mode = "qsgmii"; phy-mode = "qsgmii";
phy-handle = <&{/i2c@2000000/fpga@66/mux-mdio@54/mdio@50/phy@0b}>; phy-handle = <&{/i2c@2000000/fpga@66/mux-mdio@54/mdio@50/phy@0b}>;
}; };
&mscc_felix_port4 {
ethernet = <&enetc2>;
status = "okay";
};

View File

@ -9,6 +9,10 @@
#include "fsl-sch-30842.dtsi" #include "fsl-sch-30842.dtsi"
}; };
&enetc2 {
status = "okay";
};
&mscc_felix { &mscc_felix {
status = "okay"; status = "okay";
}; };
@ -18,3 +22,8 @@
phy-mode = "sgmii-2500"; phy-mode = "sgmii-2500";
phy-handle = <&{/i2c@2000000/fpga@66/mux-mdio@54/mdio@50/phy@02}>; phy-handle = <&{/i2c@2000000/fpga@66/mux-mdio@54/mdio@50/phy@02}>;
}; };
&mscc_felix_port4 {
ethernet = <&enetc2>;
status = "okay";
};

View File

@ -9,6 +9,10 @@
#include "fsl-sch-30842.dtsi" #include "fsl-sch-30842.dtsi"
}; };
&enetc2 {
status = "okay";
};
&mscc_felix { &mscc_felix {
status = "okay"; status = "okay";
}; };
@ -18,3 +22,8 @@
phy-mode = "sgmii-2500"; phy-mode = "sgmii-2500";
phy-handle = <&{/i2c@2000000/fpga@66/mux-mdio@54/mdio@60/phy@02}>; phy-handle = <&{/i2c@2000000/fpga@66/mux-mdio@54/mdio@60/phy@02}>;
}; };
&mscc_felix_port4 {
ethernet = <&enetc2>;
status = "okay";
};

View File

@ -251,7 +251,7 @@
&enetc1 { &enetc1 {
status = "okay"; status = "okay";
phy-mode = "rgmii"; phy-mode = "rgmii-id";
phy-handle = <&qds_phy0>; phy-handle = <&qds_phy0>;
}; };

View File

@ -142,14 +142,24 @@
}; };
enetc2: pci@0,2 { enetc2: pci@0,2 {
reg = <0x000200 0 0 0 0>; reg = <0x000200 0 0 0 0>;
status = "okay"; status = "disabled";
phy-mode = "internal"; phy-mode = "internal";
fixed-link {
speed = <2500>;
full-duplex;
};
}; };
mdio0: pci@0,3 { mdio0: pci@0,3 {
#address-cells=<0>; #address-cells=<0>;
#size-cells=<1>; #size-cells=<1>;
reg = <0x000300 0 0 0 0>; reg = <0x000300 0 0 0 0>;
status = "disabled"; status = "disabled";
fixed-link {
speed = <1000>;
full-duplex;
};
}; };
mscc_felix: pci@0,5 { mscc_felix: pci@0,5 {

View File

@ -10,6 +10,7 @@
#include <common.h> #include <common.h>
#include <bootstage.h> #include <bootstage.h>
#include <command.h> #include <command.h>
#include <dm.h>
#include <env.h> #include <env.h>
#include <image.h> #include <image.h>
#include <net.h> #include <net.h>
@ -480,3 +481,48 @@ U_BOOT_CMD(
); );
#endif /* CONFIG_CMD_LINK_LOCAL */ #endif /* CONFIG_CMD_LINK_LOCAL */
#ifdef CONFIG_DM_ETH
static int do_net_list(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
{
const struct udevice *current = eth_get_dev();
unsigned char env_enetaddr[ARP_HLEN];
const struct udevice *dev;
struct uclass *uc;
uclass_id_foreach_dev(UCLASS_ETH, dev, uc) {
eth_env_get_enetaddr_by_index("eth", dev_seq(dev), env_enetaddr);
printf("eth%d : %s %pM %s\n", dev_seq(dev), dev->name, env_enetaddr,
current == dev ? "active" : "");
}
return CMD_RET_SUCCESS;
}
static struct cmd_tbl cmd_net[] = {
U_BOOT_CMD_MKENT(list, 1, 0, do_net_list, "", ""),
};
static int do_net(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
{
struct cmd_tbl *cp;
cp = find_cmd_tbl(argv[1], cmd_net, ARRAY_SIZE(cmd_net));
/* Drop the net command */
argc--;
argv++;
if (!cp || argc > cp->maxargs)
return CMD_RET_USAGE;
if (flag == CMD_FLAG_REPEAT && !cmd_is_repeatable(cp))
return CMD_RET_SUCCESS;
return cp->cmd(cmdtp, flag, argc, argv);
}
U_BOOT_CMD(
net, 2, 1, do_net,
"NET sub-system",
"list - list available devices\n"
);
#endif // CONFIG_DM_ETH

View File

@ -548,21 +548,14 @@ config SMC911X_BASE
of the device (I/O space) of the device (I/O space)
endif #DM_ETH endif #DM_ETH
choice
prompt "SMC911X bus width"
default SMC911X_16_BIT
config SMC911X_32_BIT config SMC911X_32_BIT
bool "Enable 32-bit interface" bool "Enable SMC911X 32-bit interface"
default n
config SMC911X_16_BIT
bool "Enable 16-bit interface"
help help
Define this if data bus is 16 bits. If your processor Define this if data bus is 32 bits. If your processor use a
automatically converts one 32 bit word to two 16 bit narrower 16 bit bus or cannot convert one 32 bit word to two 16 bit
words you may also try CONFIG_SMC911X_32_BIT. words, leave this to "n".
endchoice
endif #SMC911X endif #SMC911X
config SUN7I_GMAC config SUN7I_GMAC

View File

@ -238,8 +238,6 @@ struct eqos_tegra186_regs {
#define EQOS_AUTO_CAL_STATUS_ACTIVE BIT(31) #define EQOS_AUTO_CAL_STATUS_ACTIVE BIT(31)
/* Descriptors */ /* Descriptors */
/* We assume ARCH_DMA_MINALIGN >= 16; 16 is the EQOS HW minimum */
#define EQOS_DESCRIPTOR_ALIGN ARCH_DMA_MINALIGN
#define EQOS_DESCRIPTORS_TX 4 #define EQOS_DESCRIPTORS_TX 4
#define EQOS_DESCRIPTORS_RX 4 #define EQOS_DESCRIPTORS_RX 4
#define EQOS_DESCRIPTORS_NUM (EQOS_DESCRIPTORS_TX + EQOS_DESCRIPTORS_RX) #define EQOS_DESCRIPTORS_NUM (EQOS_DESCRIPTORS_TX + EQOS_DESCRIPTORS_RX)

View File

@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0+ // SPDX-License-Identifier: GPL-2.0+
/* /*
* ENETC ethernet controller driver * ENETC ethernet controller driver
* Copyright 2017-2019 NXP * Copyright 2017-2021 NXP
*/ */
#include <common.h> #include <common.h>
@ -178,21 +178,43 @@ static int enetc_init_sgmii(struct udevice *dev)
} }
/* set up MAC for RGMII */ /* set up MAC for RGMII */
static int enetc_init_rgmii(struct udevice *dev) static void enetc_init_rgmii(struct udevice *dev, struct phy_device *phydev)
{ {
struct enetc_priv *priv = dev_get_priv(dev); struct enetc_priv *priv = dev_get_priv(dev);
u32 if_mode; u32 old_val, val;
/* enable RGMII AN */ old_val = val = enetc_read_port(priv, ENETC_PM_IF_MODE);
if_mode = enetc_read_port(priv, ENETC_PM_IF_MODE);
if_mode |= ENETC_PM_IF_MODE_AN_ENA;
enetc_write_port(priv, ENETC_PM_IF_MODE, if_mode);
return 0; /* disable unreliable RGMII in-band signaling and force the MAC into
* the speed negotiated by the PHY.
*/
val &= ~ENETC_PM_IF_MODE_AN_ENA;
if (phydev->speed == SPEED_1000) {
val &= ~ENETC_PM_IFM_SSP_MASK;
val |= ENETC_PM_IFM_SSP_1000;
} else if (phydev->speed == SPEED_100) {
val &= ~ENETC_PM_IFM_SSP_MASK;
val |= ENETC_PM_IFM_SSP_100;
} else if (phydev->speed == SPEED_10) {
val &= ~ENETC_PM_IFM_SSP_MASK;
val |= ENETC_PM_IFM_SSP_10;
}
if (phydev->duplex == DUPLEX_FULL)
val |= ENETC_PM_IFM_FULL_DPX;
else
val &= ~ENETC_PM_IFM_FULL_DPX;
if (val == old_val)
return;
enetc_write_port(priv, ENETC_PM_IF_MODE, val);
} }
/* set up MAC configuration for the given interface type */ /* set up MAC configuration for the given interface type */
static void enetc_setup_mac_iface(struct udevice *dev) static void enetc_setup_mac_iface(struct udevice *dev,
struct phy_device *phydev)
{ {
struct enetc_priv *priv = dev_get_priv(dev); struct enetc_priv *priv = dev_get_priv(dev);
u32 if_mode; u32 if_mode;
@ -202,7 +224,7 @@ static void enetc_setup_mac_iface(struct udevice *dev)
case PHY_INTERFACE_MODE_RGMII_ID: case PHY_INTERFACE_MODE_RGMII_ID:
case PHY_INTERFACE_MODE_RGMII_RXID: case PHY_INTERFACE_MODE_RGMII_RXID:
case PHY_INTERFACE_MODE_RGMII_TXID: case PHY_INTERFACE_MODE_RGMII_TXID:
enetc_init_rgmii(dev); enetc_init_rgmii(dev, phydev);
break; break;
case PHY_INTERFACE_MODE_XGMII: case PHY_INTERFACE_MODE_XGMII:
case PHY_INTERFACE_MODE_USXGMII: case PHY_INTERFACE_MODE_USXGMII:
@ -281,21 +303,20 @@ static void enetc_start_pcs(struct udevice *dev)
} }
/* Configure the actual/external ethernet PHY, if one is found */ /* Configure the actual/external ethernet PHY, if one is found */
static void enetc_config_phy(struct udevice *dev) static int enetc_config_phy(struct udevice *dev)
{ {
struct enetc_priv *priv = dev_get_priv(dev); struct enetc_priv *priv = dev_get_priv(dev);
int supported; int supported;
priv->phy = dm_eth_phy_connect(dev); priv->phy = dm_eth_phy_connect(dev);
if (!priv->phy) if (!priv->phy)
return; return -ENODEV;
supported = PHY_GBIT_FEATURES | SUPPORTED_2500baseX_Full; supported = PHY_GBIT_FEATURES | SUPPORTED_2500baseX_Full;
priv->phy->supported &= supported; priv->phy->supported &= supported;
priv->phy->advertising &= supported; priv->phy->advertising &= supported;
phy_config(priv->phy); return phy_config(priv->phy);
} }
/* /*
@ -335,9 +356,8 @@ static int enetc_probe(struct udevice *dev)
dm_pci_clrset_config16(dev, PCI_COMMAND, 0, PCI_COMMAND_MEMORY); dm_pci_clrset_config16(dev, PCI_COMMAND, 0, PCI_COMMAND_MEMORY);
enetc_start_pcs(dev); enetc_start_pcs(dev);
enetc_config_phy(dev);
return 0; return enetc_config_phy(dev);
} }
/* /*
@ -548,12 +568,9 @@ static int enetc_start(struct udevice *dev)
enetc_setup_tx_bdr(dev); enetc_setup_tx_bdr(dev);
enetc_setup_rx_bdr(dev); enetc_setup_rx_bdr(dev);
enetc_setup_mac_iface(dev); enetc_setup_mac_iface(dev, priv->phy);
if (priv->phy) return phy_startup(priv->phy);
phy_startup(priv->phy);
return 0;
} }
/* /*

View File

@ -1,7 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0+ */ /* SPDX-License-Identifier: GPL-2.0+ */
/* /*
* ENETC ethernet controller driver * ENETC ethernet controller driver
* Copyright 2017-2019 NXP * Copyright 2017-2021 NXP
*/ */
#ifndef _ENETC_H #ifndef _ENETC_H
@ -77,6 +77,11 @@ enum enetc_bdr_type {TX, RX};
#define ENETC_PM_IF_MODE 0x8300 #define ENETC_PM_IF_MODE 0x8300
#define ENETC_PM_IF_MODE_RG BIT(2) #define ENETC_PM_IF_MODE_RG BIT(2)
#define ENETC_PM_IF_MODE_AN_ENA BIT(15) #define ENETC_PM_IF_MODE_AN_ENA BIT(15)
#define ENETC_PM_IFM_SSP_MASK GENMASK(14, 13)
#define ENETC_PM_IFM_SSP_1000 (2 << 13)
#define ENETC_PM_IFM_SSP_100 (0 << 13)
#define ENETC_PM_IFM_SSP_10 (1 << 13)
#define ENETC_PM_IFM_FULL_DPX BIT(12)
#define ENETC_PM_IF_IFMODE_MASK GENMASK(1, 0) #define ENETC_PM_IF_IFMODE_MASK GENMASK(1, 0)
/* buffer descriptors count must be multiple of 8 and aligned to 128 bytes */ /* buffer descriptors count must be multiple of 8 and aligned to 128 bytes */

View File

@ -197,6 +197,12 @@ config PHY_MSCC
config PHY_NATSEMI config PHY_NATSEMI
bool "National Semiconductor Ethernet PHYs support" bool "National Semiconductor Ethernet PHYs support"
config PHY_NXP_C45_TJA11XX
tristate "NXP C45 TJA11XX PHYs"
help
Enable support for NXP C45 TJA11XX PHYs.
Currently supports only the TJA1103 PHY.
config PHY_REALTEK config PHY_REALTEK
bool "Realtek Ethernet PHYs support" bool "Realtek Ethernet PHYs support"

View File

@ -23,6 +23,7 @@ obj-$(CONFIG_PHY_MICREL_KSZ8XXX) += micrel_ksz8xxx.o
obj-$(CONFIG_PHY_MICREL_KSZ90X1) += micrel_ksz90x1.o obj-$(CONFIG_PHY_MICREL_KSZ90X1) += micrel_ksz90x1.o
obj-$(CONFIG_PHY_MESON_GXL) += meson-gxl.o obj-$(CONFIG_PHY_MESON_GXL) += meson-gxl.o
obj-$(CONFIG_PHY_NATSEMI) += natsemi.o obj-$(CONFIG_PHY_NATSEMI) += natsemi.o
obj-$(CONFIG_PHY_NXP_C45_TJA11XX) += nxp-c45-tja11xx.o
obj-$(CONFIG_PHY_REALTEK) += realtek.o obj-$(CONFIG_PHY_REALTEK) += realtek.o
obj-$(CONFIG_PHY_SMSC) += smsc.o obj-$(CONFIG_PHY_SMSC) += smsc.o
obj-$(CONFIG_PHY_TERANETICS) += teranetics.o obj-$(CONFIG_PHY_TERANETICS) += teranetics.o

View File

@ -0,0 +1,348 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* NXP C45 PHY driver
*
* Copyright 2021 NXP
* Author: Radu Pirea <radu-nicolae.pirea@oss.nxp.com>
*/
#include <common.h>
#include <dm.h>
#include <dm/devres.h>
#include <linux/delay.h>
#include <linux/math64.h>
#include <linux/mdio.h>
#include <phy.h>
#define PHY_ID_TJA_1103 0x001BB010
#define VEND1_DEVICE_CONTROL 0x0040
#define DEVICE_CONTROL_RESET BIT(15)
#define DEVICE_CONTROL_CONFIG_GLOBAL_EN BIT(14)
#define DEVICE_CONTROL_CONFIG_ALL_EN BIT(13)
#define VEND1_PORT_CONTROL 0x8040
#define PORT_CONTROL_EN BIT(14)
#define VEND1_PHY_CONTROL 0x8100
#define PHY_CONFIG_EN BIT(14)
#define PHY_START_OP BIT(0)
#define VEND1_PHY_CONFIG 0x8108
#define PHY_CONFIG_AUTO BIT(0)
#define VEND1_PORT_INFRA_CONTROL 0xAC00
#define PORT_INFRA_CONTROL_EN BIT(14)
#define VEND1_RXID 0xAFCC
#define VEND1_TXID 0xAFCD
#define ID_ENABLE BIT(15)
#define VEND1_ABILITIES 0xAFC4
#define RGMII_ID_ABILITY BIT(15)
#define RGMII_ABILITY BIT(14)
#define RMII_ABILITY BIT(10)
#define REVMII_ABILITY BIT(9)
#define MII_ABILITY BIT(8)
#define SGMII_ABILITY BIT(0)
#define VEND1_MII_BASIC_CONFIG 0xAFC6
#define MII_BASIC_CONFIG_REV BIT(8)
#define MII_BASIC_CONFIG_SGMII 0x9
#define MII_BASIC_CONFIG_RGMII 0x7
#define MII_BASIC_CONFIG_RMII 0x5
#define MII_BASIC_CONFIG_MII 0x4
#define RGMII_PERIOD_PS 8000U
#define PS_PER_DEGREE div_u64(RGMII_PERIOD_PS, 360)
#define MIN_ID_PS 1644U
#define MAX_ID_PS 2260U
#define DEFAULT_ID_PS 2000U
#define RESET_DELAY_MS 25
#define CONF_EN_DELAY_US 450
struct nxp_c45_phy {
u32 tx_delay;
u32 rx_delay;
};
static int nxp_c45_soft_reset(struct phy_device *phydev)
{
int tries = 10, ret;
ret = phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_DEVICE_CONTROL,
DEVICE_CONTROL_RESET);
if (ret)
return ret;
do {
ret = phy_read_mmd(phydev, MDIO_MMD_VEND1,
VEND1_DEVICE_CONTROL);
if (!(ret & DEVICE_CONTROL_RESET))
return 0;
mdelay(RESET_DELAY_MS);
} while (tries--);
return -EIO;
}
static int nxp_c45_start_op(struct phy_device *phydev)
{
return phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_PHY_CONTROL,
PHY_START_OP);
}
static int nxp_c45_config_enable(struct phy_device *phydev)
{
phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_DEVICE_CONTROL,
DEVICE_CONTROL_CONFIG_GLOBAL_EN |
DEVICE_CONTROL_CONFIG_ALL_EN);
udelay(CONF_EN_DELAY_US);
phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_PORT_CONTROL,
PORT_CONTROL_EN);
phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_PHY_CONTROL,
PHY_CONFIG_EN);
phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_PORT_INFRA_CONTROL,
PORT_INFRA_CONTROL_EN);
return 0;
}
static u64 nxp_c45_get_phase_shift(u64 phase_offset_raw)
{
/* The delay in degree phase is 73.8 + phase_offset_raw * 0.9.
* To avoid floating point operations we'll multiply by 10
* and get 1 decimal point precision.
*/
phase_offset_raw *= 10;
phase_offset_raw -= 738;
return div_u64(phase_offset_raw, 9);
}
static void nxp_c45_disable_delays(struct phy_device *phydev)
{
phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_TXID, 0);
phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_RXID, 0);
}
static int nxp_c45_check_delay(struct phy_device *phydev, u32 delay)
{
if (delay < MIN_ID_PS) {
pr_err("%s: delay value smaller than %u\n",
phydev->drv->name, MIN_ID_PS);
return -EINVAL;
}
if (delay > MAX_ID_PS) {
pr_err("%s: delay value higher than %u\n",
phydev->drv->name, MAX_ID_PS);
return -EINVAL;
}
return 0;
}
static int nxp_c45_get_delays(struct phy_device *phydev)
{
struct nxp_c45_phy *priv = phydev->priv;
int ret;
if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID ||
phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID) {
ret = dev_read_u32(phydev->dev, "tx-internal-delay-ps",
&priv->tx_delay);
if (ret)
priv->tx_delay = DEFAULT_ID_PS;
ret = nxp_c45_check_delay(phydev, priv->tx_delay);
if (ret) {
pr_err("%s: tx-internal-delay-ps invalid value\n",
phydev->drv->name);
return ret;
}
}
if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID ||
phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) {
ret = dev_read_u32(phydev->dev, "rx-internal-delay-ps",
&priv->rx_delay);
if (ret)
priv->rx_delay = DEFAULT_ID_PS;
ret = nxp_c45_check_delay(phydev, priv->rx_delay);
if (ret) {
pr_err("%s: rx-internal-delay-ps invalid value\n",
phydev->drv->name);
return ret;
}
}
return 0;
}
static void nxp_c45_set_delays(struct phy_device *phydev)
{
struct nxp_c45_phy *priv = phydev->priv;
u64 tx_delay = priv->tx_delay;
u64 rx_delay = priv->rx_delay;
u64 degree;
if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID ||
phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID) {
degree = div_u64(tx_delay, PS_PER_DEGREE);
phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_TXID,
ID_ENABLE | nxp_c45_get_phase_shift(degree));
} else {
phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_TXID, 0);
}
if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID ||
phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) {
degree = div_u64(rx_delay, PS_PER_DEGREE);
phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_RXID,
ID_ENABLE | nxp_c45_get_phase_shift(degree));
} else {
phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_RXID, 0);
}
}
static int nxp_c45_set_phy_mode(struct phy_device *phydev)
{
int ret;
ret = phy_read_mmd(phydev, MDIO_MMD_VEND1, VEND1_ABILITIES);
pr_debug("%s: Clause 45 managed PHY abilities 0x%x\n",
phydev->drv->name, ret);
switch (phydev->interface) {
case PHY_INTERFACE_MODE_RGMII:
if (!(ret & RGMII_ABILITY)) {
pr_err("%s: rgmii mode not supported\n",
phydev->drv->name);
return -EINVAL;
}
phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_MII_BASIC_CONFIG,
MII_BASIC_CONFIG_RGMII);
nxp_c45_disable_delays(phydev);
break;
case PHY_INTERFACE_MODE_RGMII_ID:
case PHY_INTERFACE_MODE_RGMII_TXID:
case PHY_INTERFACE_MODE_RGMII_RXID:
if (!(ret & RGMII_ID_ABILITY)) {
pr_err("%s: rgmii-id, rgmii-txid, rgmii-rxid modes are not supported\n",
phydev->drv->name);
return -EINVAL;
}
phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_MII_BASIC_CONFIG,
MII_BASIC_CONFIG_RGMII);
ret = nxp_c45_get_delays(phydev);
if (ret)
return ret;
nxp_c45_set_delays(phydev);
break;
case PHY_INTERFACE_MODE_MII:
if (!(ret & MII_ABILITY)) {
pr_err("%s: mii mode not supported\n",
phydev->drv->name);
return -EINVAL;
}
phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_MII_BASIC_CONFIG,
MII_BASIC_CONFIG_MII);
break;
case PHY_INTERFACE_MODE_RMII:
if (!(ret & RMII_ABILITY)) {
pr_err("%s: rmii mode not supported\n",
phydev->drv->name);
return -EINVAL;
}
phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_MII_BASIC_CONFIG,
MII_BASIC_CONFIG_RMII);
break;
case PHY_INTERFACE_MODE_SGMII:
if (!(ret & SGMII_ABILITY)) {
pr_err("%s: sgmii mode not supported\n",
phydev->drv->name);
return -EINVAL;
}
phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_MII_BASIC_CONFIG,
MII_BASIC_CONFIG_SGMII);
break;
case PHY_INTERFACE_MODE_INTERNAL:
break;
default:
return -EINVAL;
}
return 0;
}
static int nxp_c45_config(struct phy_device *phydev)
{
int ret;
ret = nxp_c45_soft_reset(phydev);
if (ret)
return ret;
ret = nxp_c45_config_enable(phydev);
if (ret) {
pr_err("%s: Failed to enable config\n", phydev->drv->name);
return ret;
}
phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_PHY_CONFIG,
PHY_CONFIG_AUTO);
ret = nxp_c45_set_phy_mode(phydev);
if (ret) {
pr_err("%s: Failed to set phy mode\n", phydev->drv->name);
return ret;
}
phydev->autoneg = AUTONEG_DISABLE;
return nxp_c45_start_op(phydev);
}
static int nxp_c45_startup(struct phy_device *phydev)
{
u32 reg;
reg = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_STAT1);
phydev->link = !!(reg & MDIO_STAT1_LSTATUS);
phydev->speed = SPEED_100;
phydev->duplex = DUPLEX_FULL;
return 0;
}
static int nxp_c45_probe(struct phy_device *phydev)
{
struct nxp_c45_phy *priv;
priv = devm_kzalloc(phydev->priv, sizeof(*priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;
phydev->priv = priv;
return 0;
}
static struct phy_driver nxp_tja11xx = {
.name = "NXP C45 TJA1103",
.uid = PHY_ID_TJA_1103,
.mask = 0xfffff0,
.features = PHY_100BT1_FEATURES,
.probe = &nxp_c45_probe,
.config = &nxp_c45_config,
.startup = &nxp_c45_startup,
.shutdown = &genphy_shutdown,
};
int phy_nxp_tja11xx_init(void)
{
phy_register(&nxp_tja11xx);
return 0;
}

View File

@ -529,6 +529,9 @@ int phy_init(void)
#ifdef CONFIG_PHY_NATSEMI #ifdef CONFIG_PHY_NATSEMI
phy_natsemi_init(); phy_natsemi_init();
#endif #endif
#ifdef CONFIG_NXP_C45_TJA11XX_PHY
phy_nxp_tja11xx_init();
#endif
#ifdef CONFIG_PHY_REALTEK #ifdef CONFIG_PHY_REALTEK
phy_realtek_init(); phy_realtek_init();
#endif #endif

View File

@ -28,6 +28,7 @@ struct smc911x_priv {
phys_addr_t iobase; phys_addr_t iobase;
const struct chip_id *chipid; const struct chip_id *chipid;
unsigned char enetaddr[6]; unsigned char enetaddr[6];
bool use_32_bit_io;
}; };
static const struct chip_id chip_ids[] = { static const struct chip_id chip_ids[] = {
@ -48,36 +49,24 @@ static const struct chip_id chip_ids[] = {
#define DRIVERNAME "smc911x" #define DRIVERNAME "smc911x"
#if defined (CONFIG_SMC911X_32_BIT) && \
defined (CONFIG_SMC911X_16_BIT)
#error "SMC911X: Only one of CONFIG_SMC911X_32_BIT and \
CONFIG_SMC911X_16_BIT shall be set"
#endif
#if defined (CONFIG_SMC911X_32_BIT)
static u32 smc911x_reg_read(struct smc911x_priv *priv, u32 offset) static u32 smc911x_reg_read(struct smc911x_priv *priv, u32 offset)
{ {
return readl(priv->iobase + offset); if (priv->use_32_bit_io)
} return readl(priv->iobase + offset);
static void smc911x_reg_write(struct smc911x_priv *priv, u32 offset, u32 val)
{
writel(val, priv->iobase + offset);
}
#elif defined (CONFIG_SMC911X_16_BIT)
static u32 smc911x_reg_read(struct smc911x_priv *priv, u32 offset)
{
return (readw(priv->iobase + offset) & 0xffff) | return (readw(priv->iobase + offset) & 0xffff) |
(readw(priv->iobase + offset + 2) << 16); (readw(priv->iobase + offset + 2) << 16);
} }
static void smc911x_reg_write(struct smc911x_priv *priv, u32 offset, u32 val) static void smc911x_reg_write(struct smc911x_priv *priv, u32 offset, u32 val)
{ {
writew(val & 0xffff, priv->iobase + offset); if (priv->use_32_bit_io) {
writew(val >> 16, priv->iobase + offset + 2); writel(val, priv->iobase + offset);
} else {
writew(val & 0xffff, priv->iobase + offset);
writew(val >> 16, priv->iobase + offset + 2);
}
} }
#else
#error "SMC911X: undefined bus width"
#endif /* CONFIG_SMC911X_16_BIT */
static u32 smc911x_get_mac_csr(struct smc911x_priv *priv, u8 reg) static u32 smc911x_get_mac_csr(struct smc911x_priv *priv, u8 reg)
{ {
@ -501,6 +490,8 @@ int smc911x_initialize(u8 dev_num, int base_addr)
priv->iobase = base_addr; priv->iobase = base_addr;
priv->dev.iobase = base_addr; priv->dev.iobase = base_addr;
priv->use_32_bit_io = CONFIG_IS_ENABLED(SMC911X_32_BIT);
/* Try to detect chip. Will fail if not present. */ /* Try to detect chip. Will fail if not present. */
ret = smc911x_detect_chip(priv); ret = smc911x_detect_chip(priv);
if (ret) { if (ret) {
@ -611,10 +602,18 @@ static int smc911x_of_to_plat(struct udevice *dev)
{ {
struct smc911x_priv *priv = dev_get_priv(dev); struct smc911x_priv *priv = dev_get_priv(dev);
struct eth_pdata *pdata = dev_get_plat(dev); struct eth_pdata *pdata = dev_get_plat(dev);
u32 io_width;
int ret;
pdata->iobase = dev_read_addr(dev); pdata->iobase = dev_read_addr(dev);
priv->iobase = pdata->iobase; priv->iobase = pdata->iobase;
ret = dev_read_u32(dev, "reg-io-width", &io_width);
if (!ret)
priv->use_32_bit_io = (io_width == 4);
else
priv->use_32_bit_io = CONFIG_IS_ENABLED(SMC911X_32_BIT);
return 0; return 0;
} }

View File

@ -51,6 +51,10 @@ struct udevice;
PHY_100BT_FEATURES | \ PHY_100BT_FEATURES | \
PHY_DEFAULT_FEATURES) PHY_DEFAULT_FEATURES)
#define PHY_100BT1_FEATURES (SUPPORTED_TP | \
SUPPORTED_MII | \
SUPPORTED_100baseT_Full)
#define PHY_GBIT_FEATURES (PHY_BASIC_FEATURES | \ #define PHY_GBIT_FEATURES (PHY_BASIC_FEATURES | \
PHY_1000BT_FEATURES) PHY_1000BT_FEATURES)
@ -523,6 +527,7 @@ int phy_micrel_ksz8xxx_init(void);
int phy_micrel_ksz90x1_init(void); int phy_micrel_ksz90x1_init(void);
int phy_meson_gxl_init(void); int phy_meson_gxl_init(void);
int phy_natsemi_init(void); int phy_natsemi_init(void);
int phy_nxp_tja11xx_init(void);
int phy_realtek_init(void); int phy_realtek_init(void);
int phy_smsc_init(void); int phy_smsc_init(void);
int phy_teranetics_init(void); int phy_teranetics_init(void);