summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorTom Rini <[email protected]>2020-10-01 09:46:10 -0400
committerTom Rini <[email protected]>2020-10-01 09:46:10 -0400
commit26acc6395fee680cea72e51348bd59e206eb0464 (patch)
tree14a2a97d03c4c0cf7b0c531fbdcf9ebec7cfdd13 /drivers
parent097bbf1ba97b8ece930deca663f05ea444e99e45 (diff)
parent912ece4c3dd486bcd62f0d0dfee760b9f01caac6 (diff)
Merge branch '2020-09-30-assorted-network-improvements' into next
- Generic UDP framework - TFTP fixes - dwc_eth_qos, smc911x, smc911x and mscc phy fixes
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/dwc_eth_qos.c7
-rw-r--r--drivers/net/ftgmac100.c4
-rw-r--r--drivers/net/phy/mscc.c129
-rw-r--r--drivers/net/smc911x.c3
-rw-r--r--drivers/phy/Kconfig7
-rw-r--r--drivers/phy/Makefile1
-rw-r--r--drivers/phy/phy-bcm-sr-pcie.c177
7 files changed, 300 insertions, 28 deletions
diff --git a/drivers/net/dwc_eth_qos.c b/drivers/net/dwc_eth_qos.c
index 810a2b95b19..db1102562f6 100644
--- a/drivers/net/dwc_eth_qos.c
+++ b/drivers/net/dwc_eth_qos.c
@@ -26,6 +26,7 @@
* supports a single RGMII PHY. This configuration also has SW control over
* all clock and reset signals to the HW block.
*/
+
#include <common.h>
#include <clk.h>
#include <cpu_func.h>
@@ -1893,8 +1894,7 @@ static phy_interface_t eqos_get_interface_stm32(struct udevice *dev)
debug("%s(dev=%p):\n", __func__, dev);
- phy_mode = fdt_getprop(gd->fdt_blob, dev_of_offset(dev), "phy-mode",
- NULL);
+ phy_mode = dev_read_prop(dev, "phy-mode", NULL);
if (phy_mode)
interface = phy_get_interface_by_name(phy_mode);
@@ -1931,8 +1931,7 @@ static phy_interface_t eqos_get_interface_imx(struct udevice *dev)
debug("%s(dev=%p):\n", __func__, dev);
- phy_mode = fdt_getprop(gd->fdt_blob, dev_of_offset(dev), "phy-mode",
- NULL);
+ phy_mode = dev_read_prop(dev, "phy-mode", NULL);
if (phy_mode)
interface = phy_get_interface_by_name(phy_mode);
diff --git a/drivers/net/ftgmac100.c b/drivers/net/ftgmac100.c
index 5676a5b3ba9..00bda24f1fd 100644
--- a/drivers/net/ftgmac100.c
+++ b/drivers/net/ftgmac100.c
@@ -551,6 +551,10 @@ static int ftgmac100_probe(struct udevice *dev)
priv->max_speed = pdata->max_speed;
priv->phy_addr = 0;
+#ifdef CONFIG_PHY_ADDR
+ priv->phy_addr = CONFIG_PHY_ADDR;
+#endif
+
ret = clk_enable_bulk(&priv->clks);
if (ret)
goto out;
diff --git a/drivers/net/phy/mscc.c b/drivers/net/phy/mscc.c
index 709979f48c9..d1a643cf5a0 100644
--- a/drivers/net/phy/mscc.c
+++ b/drivers/net/phy/mscc.c
@@ -157,6 +157,14 @@
#define INT_MEM_DATA_M GENMASK(7, 0)
#define INT_MEM_DATA(x) (INT_MEM_DATA_M & (x))
+/* Extended page GPIO register 13G */
+#define MSCC_CLKOUT_CNTL 13
+#define CLKOUT_ENABLE BIT(15)
+#define CLKOUT_FREQ_MASK GENMASK(14, 13)
+#define CLKOUT_FREQ_25M (0x0 << 13)
+#define CLKOUT_FREQ_50M (0x1 << 13)
+#define CLKOUT_FREQ_125M (0x2 << 13)
+
/* Extended page GPIO register 18G */
#define MSCC_PHY_PROC_CMD 18
#define PROC_CMD_NCOMPLETED BIT(15)
@@ -1168,6 +1176,9 @@ static int vsc8531_vsc8541_mac_config(struct phy_device *phydev)
rx_clk_out = RX_CLK_OUT_NORMAL;
break;
+ case PHY_INTERFACE_MODE_RGMII_TXID:
+ case PHY_INTERFACE_MODE_RGMII_RXID:
+ case PHY_INTERFACE_MODE_RGMII_ID:
case PHY_INTERFACE_MODE_RGMII:
/* Set Reg23.12:11=2 */
mac_if = MAC_IF_SELECTION_RGMII;
@@ -1210,13 +1221,84 @@ static int vsc8531_vsc8541_mac_config(struct phy_device *phydev)
return 0;
}
+static int vsc8531_vsc8541_clkout_config(struct phy_device *phydev)
+{
+ struct ofnode_phandle_args phandle_args;
+ u32 clkout_rate = 0;
+ u16 reg_val;
+ int retval;
+
+ retval = dev_read_phandle_with_args(phydev->dev, "phy-handle", NULL,
+ 0, 0, &phandle_args);
+ if (!retval)
+ clkout_rate = ofnode_read_u32_default(phandle_args.node,
+ "vsc8531,clk-out-frequency", 0);
+
+ switch (clkout_rate) {
+ case 0:
+ reg_val = 0;
+ break;
+ case 25000000:
+ reg_val = CLKOUT_FREQ_25M | CLKOUT_ENABLE;
+ break;
+ case 50000000:
+ reg_val = CLKOUT_FREQ_50M | CLKOUT_ENABLE;
+ break;
+ case 125000000:
+ reg_val = CLKOUT_FREQ_125M | CLKOUT_ENABLE;
+ break;
+ default:
+ printf("PHY 8530/31 invalid clkout rate %u\n",
+ clkout_rate);
+ return -EINVAL;
+ }
+
+ phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
+ MSCC_PHY_PAGE_GPIO);
+ phy_write(phydev, MDIO_DEVAD_NONE, MSCC_CLKOUT_CNTL, reg_val);
+ phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
+ MSCC_PHY_PAGE_STD);
+
+ return 0;
+}
+
+static int vsc8531_vsc8541_clk_skew_config(struct phy_device *phydev)
+{
+ enum vsc_phy_rgmii_skew rx_clk_skew = VSC_PHY_RGMII_DELAY_200_PS;
+ enum vsc_phy_rgmii_skew tx_clk_skew = VSC_PHY_RGMII_DELAY_200_PS;
+ u16 reg_val;
+
+ if (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID ||
+ phydev->interface == PHY_INTERFACE_MODE_RGMII_ID)
+ rx_clk_skew = VSC_PHY_RGMII_DELAY_2000_PS;
+
+ if (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID ||
+ phydev->interface == PHY_INTERFACE_MODE_RGMII_ID)
+ tx_clk_skew = VSC_PHY_RGMII_DELAY_2000_PS;
+
+ phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
+ MSCC_PHY_PAGE_EXT2);
+ reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_RGMII_CNTL_REG);
+
+ /* Reg20E2 - Update RGMII RX_Clk Skews. */
+ reg_val = bitfield_replace(reg_val, RGMII_RX_CLK_DELAY_POS,
+ RGMII_RX_CLK_DELAY_WIDTH, rx_clk_skew);
+ /* Reg20E2 - Update RGMII TX_Clk Skews. */
+ reg_val = bitfield_replace(reg_val, RGMII_TX_CLK_DELAY_POS,
+ RGMII_TX_CLK_DELAY_WIDTH, tx_clk_skew);
+
+ phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_RGMII_CNTL_REG, reg_val);
+ phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
+ MSCC_PHY_PAGE_STD);
+
+ return 0;
+}
+
static int vsc8531_config(struct phy_device *phydev)
{
int retval = -EINVAL;
u16 reg_val;
u16 rmii_clk_out;
- enum vsc_phy_rgmii_skew rx_clk_skew = VSC_PHY_RGMII_DELAY_1700_PS;
- enum vsc_phy_rgmii_skew tx_clk_skew = VSC_PHY_RGMII_DELAY_800_PS;
enum vsc_phy_clk_slew edge_rate = VSC_PHY_CLK_SLEW_RATE_4;
/* For VSC8530/31 and VSC8540/41 the init scripts are the same */
@@ -1226,6 +1308,9 @@ static int vsc8531_config(struct phy_device *phydev)
switch (phydev->interface) {
case PHY_INTERFACE_MODE_RMII:
case PHY_INTERFACE_MODE_RGMII:
+ case PHY_INTERFACE_MODE_RGMII_TXID:
+ case PHY_INTERFACE_MODE_RGMII_RXID:
+ case PHY_INTERFACE_MODE_RGMII_ID:
retval = vsc8531_vsc8541_mac_config(phydev);
if (retval != 0)
return retval;
@@ -1242,19 +1327,12 @@ static int vsc8531_config(struct phy_device *phydev)
/* Default RMII Clk Output to 0=OFF/1=ON */
rmii_clk_out = 0;
+ retval = vsc8531_vsc8541_clk_skew_config(phydev);
+ if (retval != 0)
+ return retval;
+
phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
MSCC_PHY_PAGE_EXT2);
- reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_RGMII_CNTL_REG);
-
- /* Reg20E2 - Update RGMII RX_Clk Skews. */
- reg_val = bitfield_replace(reg_val, RGMII_RX_CLK_DELAY_POS,
- RGMII_RX_CLK_DELAY_WIDTH, rx_clk_skew);
- /* Reg20E2 - Update RGMII TX_Clk Skews. */
- reg_val = bitfield_replace(reg_val, RGMII_TX_CLK_DELAY_POS,
- RGMII_TX_CLK_DELAY_WIDTH, tx_clk_skew);
-
- phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_RGMII_CNTL_REG, reg_val);
-
reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_WOL_MAC_CONTROL);
/* Reg27E2 - Update Clk Slew Rate. */
reg_val = bitfield_replace(reg_val, EDGE_RATE_CNTL_POS,
@@ -1267,6 +1345,11 @@ static int vsc8531_config(struct phy_device *phydev)
phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
MSCC_PHY_PAGE_STD);
+ /* Configure the clk output */
+ retval = vsc8531_vsc8541_clkout_config(phydev);
+ if (retval != 0)
+ return retval;
+
return genphy_config_aneg(phydev);
}
@@ -1275,8 +1358,6 @@ static int vsc8541_config(struct phy_device *phydev)
int retval = -EINVAL;
u16 reg_val;
u16 rmii_clk_out;
- enum vsc_phy_rgmii_skew rx_clk_skew = VSC_PHY_RGMII_DELAY_1700_PS;
- enum vsc_phy_rgmii_skew tx_clk_skew = VSC_PHY_RGMII_DELAY_800_PS;
enum vsc_phy_clk_slew edge_rate = VSC_PHY_CLK_SLEW_RATE_4;
/* For VSC8530/31 and VSC8540/41 the init scripts are the same */
@@ -1304,17 +1385,12 @@ static int vsc8541_config(struct phy_device *phydev)
/* Default RMII Clk Output to 0=OFF/1=ON */
rmii_clk_out = 0;
+ retval = vsc8531_vsc8541_clk_skew_config(phydev);
+ if (retval != 0)
+ return retval;
+
phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
MSCC_PHY_PAGE_EXT2);
- reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_RGMII_CNTL_REG);
- /* Reg20E2 - Update RGMII RX_Clk Skews. */
- reg_val = bitfield_replace(reg_val, RGMII_RX_CLK_DELAY_POS,
- RGMII_RX_CLK_DELAY_WIDTH, rx_clk_skew);
- /* Reg20E2 - Update RGMII TX_Clk Skews. */
- reg_val = bitfield_replace(reg_val, RGMII_TX_CLK_DELAY_POS,
- RGMII_TX_CLK_DELAY_WIDTH, tx_clk_skew);
- phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_RGMII_CNTL_REG, reg_val);
-
reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_WOL_MAC_CONTROL);
/* Reg27E2 - Update Clk Slew Rate. */
reg_val = bitfield_replace(reg_val, EDGE_RATE_CNTL_POS,
@@ -1327,6 +1403,11 @@ static int vsc8541_config(struct phy_device *phydev)
phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
MSCC_PHY_PAGE_STD);
+ /* Configure the clk output */
+ retval = vsc8531_vsc8541_clkout_config(phydev);
+ if (retval != 0)
+ return retval;
+
return genphy_config_aneg(phydev);
}
diff --git a/drivers/net/smc911x.c b/drivers/net/smc911x.c
index 09372d7f6ba..1fa3667b77c 100644
--- a/drivers/net/smc911x.c
+++ b/drivers/net/smc911x.c
@@ -6,6 +6,7 @@
*/
#include <common.h>
+#include <env.h>
#include <command.h>
#include <malloc.h>
#include <net.h>
@@ -185,6 +186,8 @@ static void smc911x_handle_mac_address(struct smc911x_priv *priv)
smc911x_set_mac_csr(priv, ADDRH, addrh);
printf(DRIVERNAME ": MAC %pM\n", m);
+ if (!env_get("ethaddr"))
+ env_set("ethaddr", (const char *)m);
}
static bool smc911x_read_mac_address(struct smc911x_priv *priv)
diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
index 8da00a259d7..d66aa073927 100644
--- a/drivers/phy/Kconfig
+++ b/drivers/phy/Kconfig
@@ -84,6 +84,13 @@ config BCM6368_USBH_PHY
help
Support for the Broadcom MIPS BCM6368 USBH PHY.
+config BCM_SR_PCIE_PHY
+ bool "Broadcom Stingray PCIe PHY driver"
+ depends on PHY
+ help
+ Enable this to support the Broadcom Stingray PCIe PHY
+ If unsure, say N.
+
config PHY_DA8XX_USB
tristate "TI DA8xx USB PHY Driver"
depends on PHY && ARCH_DAVINCI
diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile
index 009f353baf4..8dabefd776a 100644
--- a/drivers/phy/Makefile
+++ b/drivers/phy/Makefile
@@ -9,6 +9,7 @@ obj-$(CONFIG_BCM6318_USBH_PHY) += bcm6318-usbh-phy.o
obj-$(CONFIG_BCM6348_USBH_PHY) += bcm6348-usbh-phy.o
obj-$(CONFIG_BCM6358_USBH_PHY) += bcm6358-usbh-phy.o
obj-$(CONFIG_BCM6368_USBH_PHY) += bcm6368-usbh-phy.o
+obj-$(CONFIG_BCM_SR_PCIE_PHY) += phy-bcm-sr-pcie.o
obj-$(CONFIG_PHY_SANDBOX) += sandbox-phy.o
obj-$(CONFIG_$(SPL_)PIPE3_PHY) += ti-pipe3-phy.o
obj-$(CONFIG_AM654_PHY) += phy-ti-am654.o
diff --git a/drivers/phy/phy-bcm-sr-pcie.c b/drivers/phy/phy-bcm-sr-pcie.c
new file mode 100644
index 00000000000..36c77c4b639
--- /dev/null
+++ b/drivers/phy/phy-bcm-sr-pcie.c
@@ -0,0 +1,177 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2019 Broadcom
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <generic-phy.h>
+#include <asm/io.h>
+#include <linux/bitops.h>
+
+/* we have up to 8 PAXB based RC. The 9th one is always PAXC */
+#define SR_NR_PCIE_PHYS 8
+
+#define PCIE_PIPEMUX_CFG_OFFSET 0x10c
+#define PCIE_PIPEMUX_SELECT_STRAP GENMASK(3, 0)
+
+#define CDRU_STRAP_DATA_LSW_OFFSET 0x5c
+#define PCIE_PIPEMUX_SHIFT 19
+#define PCIE_PIPEMUX_MASK GENMASK(3, 0)
+
+/**
+ * struct sr_pcie_phy_core - Stingray PCIe PHY core control
+ *
+ * @dev: pointer to device
+ * @base: base register of PCIe SS
+ * @cdru: CDRU base address
+ * @pipemux: pipemuex strap
+ */
+struct sr_pcie_phy_core {
+ struct udevice *dev;
+ void __iomem *base;
+ void __iomem *cdru;
+ u32 pipemux;
+};
+
+/*
+ * PCIe PIPEMUX lookup table
+ *
+ * Each array index represents a PIPEMUX strap setting
+ * The array element represents a bitmap where a set bit means the PCIe
+ * core and associated serdes has been enabled as RC and is available for use
+ */
+static const u8 pipemux_table[] = {
+ /* PIPEMUX = 0, EP 1x16 */
+ 0x00,
+ /* PIPEMUX = 1, EP 1x8 + RC 1x8, core 7 */
+ 0x80,
+ /* PIPEMUX = 2, EP 4x4 */
+ 0x00,
+ /* PIPEMUX = 3, RC 2x8, cores 0, 7 */
+ 0x81,
+ /* PIPEMUX = 4, RC 4x4, cores 0, 1, 6, 7 */
+ 0xc3,
+ /* PIPEMUX = 5, RC 8x2, all 8 cores */
+ 0xff,
+ /* PIPEMUX = 6, RC 3x4 + 2x2, cores 0, 2, 3, 6, 7 */
+ 0xcd,
+ /* PIPEMUX = 7, RC 1x4 + 6x2, cores 0, 2, 3, 4, 5, 6, 7 */
+ 0xfd,
+ /* PIPEMUX = 8, EP 1x8 + RC 4x2, cores 4, 5, 6, 7 */
+ 0xf0,
+ /* PIPEMUX = 9, EP 1x8 + RC 2x4, cores 6, 7 */
+ 0xc0,
+ /* PIPEMUX = 10, EP 2x4 + RC 2x4, cores 1, 6 */
+ 0x42,
+ /* PIPEMUX = 11, EP 2x4 + RC 4x2, cores 2, 3, 4, 5 */
+ 0x3c,
+ /* PIPEMUX = 12, EP 1x4 + RC 6x2, cores 2, 3, 4, 5, 6, 7 */
+ 0xfc,
+ /* PIPEMUX = 13, RC 2x4 + RC 1x4 + 2x2, cores 2, 3, 6 */
+ 0x4c,
+};
+
+/*
+ * Return true if the strap setting is valid
+ */
+static bool pipemux_strap_is_valid(u32 pipemux)
+{
+ return !!(pipemux < ARRAY_SIZE(pipemux_table));
+}
+
+/*
+ * Read the PCIe PIPEMUX from strap
+ */
+static u32 pipemux_strap_read(struct sr_pcie_phy_core *core)
+{
+ u32 pipemux;
+
+ /*
+ * Read PIPEMUX configuration register to determine the pipemux setting
+ *
+ * In the case when the value indicates using HW strap, fall back to
+ * use HW strap
+ */
+ pipemux = readl(core->base + PCIE_PIPEMUX_CFG_OFFSET);
+ pipemux &= PCIE_PIPEMUX_MASK;
+ if (pipemux == PCIE_PIPEMUX_SELECT_STRAP) {
+ pipemux = readl(core->cdru + CDRU_STRAP_DATA_LSW_OFFSET);
+ pipemux >>= PCIE_PIPEMUX_SHIFT;
+ pipemux &= PCIE_PIPEMUX_MASK;
+ }
+
+ return pipemux;
+}
+
+static int sr_pcie_phy_init(struct phy *phy)
+{
+ struct sr_pcie_phy_core *core = dev_get_priv(phy->dev);
+ unsigned int core_idx = phy->id;
+
+ debug("%s %lx\n", __func__, phy->id);
+ /*
+ * Check whether this PHY is for root complex or not. If yes, return
+ * zero so the host driver can proceed to enumeration. If not, return
+ * an error and that will force the host driver to bail out
+ */
+ if (!!((pipemux_table[core->pipemux] >> core_idx) & 0x1))
+ return 0;
+
+ return -ENODEV;
+}
+
+static int sr_pcie_phy_xlate(struct phy *phy, struct ofnode_phandle_args *args)
+{
+ debug("%s %d\n", __func__, args->args[0]);
+ if (args->args_count && args->args[0] < SR_NR_PCIE_PHYS)
+ phy->id = args->args[0];
+ else
+ return -ENODEV;
+
+ return 0;
+}
+
+static const struct phy_ops sr_pcie_phy_ops = {
+ .of_xlate = sr_pcie_phy_xlate,
+ .init = sr_pcie_phy_init,
+};
+
+static int sr_pcie_phy_probe(struct udevice *dev)
+{
+ struct sr_pcie_phy_core *core = dev_get_priv(dev);
+
+ core->dev = dev;
+
+ core->base = (void __iomem *)devfdt_get_addr_name(dev, "reg_base");
+ core->cdru = (void __iomem *)devfdt_get_addr_name(dev, "cdru_base");
+ debug("ip base %p\n", core->base);
+ debug("cdru base %p\n", core->cdru);
+
+ /* read the PCIe PIPEMUX strap setting */
+ core->pipemux = pipemux_strap_read(core);
+ if (!pipemux_strap_is_valid(core->pipemux)) {
+ pr_err("invalid PCIe PIPEMUX strap %u\n", core->pipemux);
+ return -EIO;
+ }
+ debug("%s %#x\n", __func__, core->pipemux);
+
+ pr_info("Stingray PCIe PHY driver initialized\n");
+
+ return 0;
+}
+
+static const struct udevice_id sr_pcie_phy_match_table[] = {
+ { .compatible = "brcm,sr-pcie-phy" },
+ { }
+};
+
+U_BOOT_DRIVER(sr_pcie_phy) = {
+ .name = "sr-pcie-phy",
+ .id = UCLASS_PHY,
+ .probe = sr_pcie_phy_probe,
+ .of_match = sr_pcie_phy_match_table,
+ .ops = &sr_pcie_phy_ops,
+ .platdata_auto_alloc_size = sizeof(struct sr_pcie_phy_core),
+ .priv_auto_alloc_size = sizeof(struct sr_pcie_phy_core),
+};