summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cmd/Kconfig1
-rw-r--r--cmd/net.c10
-rw-r--r--configs/sandbox_defconfig1
-rw-r--r--doc/README.udp35
-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
-rw-r--r--include/net.h2
-rw-r--r--include/net/sntp.h (renamed from net/sntp.h)3
-rw-r--r--include/net/udp.h41
-rw-r--r--net/Kconfig6
-rw-r--r--net/Makefile1
-rw-r--r--net/eth-uclass.c6
-rw-r--r--net/eth_legacy.c4
-rw-r--r--net/net.c44
-rw-r--r--net/sntp.c29
-rw-r--r--net/tftp.c9
-rw-r--r--net/udp.c46
22 files changed, 494 insertions, 72 deletions
diff --git a/cmd/Kconfig b/cmd/Kconfig
index 30c358d7e74..999b6cf239a 100644
--- a/cmd/Kconfig
+++ b/cmd/Kconfig
@@ -1645,6 +1645,7 @@ config CMD_CDP
config CMD_SNTP
bool "sntp"
+ select PROT_UDP
help
Synchronize RTC via network
diff --git a/cmd/net.c b/cmd/net.c
index 9bbcdbcfe07..beb2877dfd5 100644
--- a/cmd/net.c
+++ b/cmd/net.c
@@ -13,6 +13,8 @@
#include <env.h>
#include <image.h>
#include <net.h>
+#include <net/udp.h>
+#include <net/sntp.h>
static int netboot_common(enum proto_t, struct cmd_tbl *, int, char * const []);
@@ -356,6 +358,12 @@ U_BOOT_CMD(
#endif
#if defined(CONFIG_CMD_SNTP)
+static struct udp_ops sntp_ops = {
+ .prereq = sntp_prereq,
+ .start = sntp_start,
+ .data = NULL,
+};
+
int do_sntp(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
{
char *toff;
@@ -380,7 +388,7 @@ int do_sntp(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
else
net_ntp_time_offset = simple_strtol(toff, NULL, 10);
- if (net_loop(SNTP) < 0) {
+ if (udp_loop(&sntp_ops) < 0) {
printf("SNTP failed: host %pI4 not responding\n",
&net_ntp_server);
return CMD_RET_FAILURE;
diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig
index a2ebb3c971d..c72e0e29005 100644
--- a/configs/sandbox_defconfig
+++ b/configs/sandbox_defconfig
@@ -102,6 +102,7 @@ CONFIG_ENV_IS_NOWHERE=y
CONFIG_ENV_IS_IN_EXT4=y
CONFIG_ENV_EXT4_INTERFACE="host"
CONFIG_ENV_EXT4_DEVICE_AND_PART="0:0"
+CONFIG_PROT_UDP=y
CONFIG_BOOTP_SEND_HOSTNAME=y
CONFIG_NETCONSOLE=y
CONFIG_IP_DEFRAG=y
diff --git a/doc/README.udp b/doc/README.udp
new file mode 100644
index 00000000000..da0725719dc
--- /dev/null
+++ b/doc/README.udp
@@ -0,0 +1,35 @@
+Udp framework
+
+The udp framework is build on top of network framework and is designed
+to define new protocol or new command based on udp without modifying
+the network framework.
+
+The udp framework define a function udp_loop that take as argument
+a structure udp_ops (defined in include/net/udp.h) :
+
+struct udp_ops {
+ int (*prereq)(void *data);
+ int (*start)(void *data);
+ void *data;
+};
+
+The callback prereq define if all the requirements are
+valid before running the network/udp loop.
+
+The callback start define the first step in the network/udp loop,
+and it may also be used to configure a timemout and udp handler.
+
+The pointer data is used to store private data that
+could be used by both callback.
+
+A simple example to use this framework:
+
+static struct udp_ops udp_ops = {
+ .prereq = wmp_prereq,
+ .start = wmp_start,
+ .data = NULL,
+};
+
+...
+
+err = udp_loop(&udp_ops);
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),
+};
diff --git a/include/net.h b/include/net.h
index 1bf9867f8cf..219107194f7 100644
--- a/include/net.h
+++ b/include/net.h
@@ -551,7 +551,7 @@ extern int net_restart_wrap; /* Tried all network devices */
enum proto_t {
BOOTP, RARP, ARP, TFTPGET, DHCP, PING, DNS, NFS, CDP, NETCONS, SNTP,
- TFTPSRV, TFTPPUT, LINKLOCAL, FASTBOOT, WOL
+ TFTPSRV, TFTPPUT, LINKLOCAL, FASTBOOT, WOL, UDP
};
extern char net_boot_file_name[1024];/* Boot File name */
diff --git a/net/sntp.h b/include/net/sntp.h
index d3cbfbc69a6..30b44d1c066 100644
--- a/net/sntp.h
+++ b/include/net/sntp.h
@@ -52,6 +52,7 @@ struct sntp_pkt_t {
unsigned long long transmit_timestamp;
} __attribute__((packed));
-void sntp_start(void); /* Begin SNTP */
+int sntp_prereq(void *data);
+int sntp_start(void *data); /* Begin SNTP */
#endif /* __SNTP_H__ */
diff --git a/include/net/udp.h b/include/net/udp.h
new file mode 100644
index 00000000000..2ae56e84477
--- /dev/null
+++ b/include/net/udp.h
@@ -0,0 +1,41 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2020 Philippe Reynes <philippe.reynes@softathome.com>
+ */
+
+#ifndef __UDP
+#define __UDP
+
+/**
+ * struct udp_ops - function to handle udp packet
+ *
+ * This structure provides the function to handle udp packet in
+ * the network loop.
+ *
+ * @prereq: callback called to check the requirement
+ * @start: callback called to start the protocol/feature
+ * @data: pointer to store private data (used by prereq and start)
+ */
+struct udp_ops {
+ int (*prereq)(void *data);
+ int (*start)(void *data);
+ void *data;
+};
+
+int udp_prereq(void);
+
+int udp_start(void);
+
+/**
+ * udp_loop() - network loop for udp protocol
+ *
+ * Launch a network loop for udp protocol and use callbacks
+ * provided in parameter @ops to initialize the loop, and then
+ * to handle udp packet.
+ *
+ * @ops: udp callback
+ * @return: 0 if success, otherwise < 0 on error
+ */
+int udp_loop(struct udp_ops *ops);
+
+#endif
diff --git a/net/Kconfig b/net/Kconfig
index 6874b55aacb..1b3e420d0d1 100644
--- a/net/Kconfig
+++ b/net/Kconfig
@@ -8,6 +8,12 @@ menuconfig NET
if NET
+config PROT_UDP
+ bool "Enable generic udp framework"
+ help
+ Enable a generic udp framework that allows defining a custom
+ handler for udp protocol.
+
config BOOTP_SEND_HOSTNAME
bool "Send hostname to DNS server"
help
diff --git a/net/Makefile b/net/Makefile
index fef71b940a0..76527f704c4 100644
--- a/net/Makefile
+++ b/net/Makefile
@@ -27,6 +27,7 @@ obj-$(CONFIG_CMD_SNTP) += sntp.o
obj-$(CONFIG_CMD_TFTPBOOT) += tftp.o
obj-$(CONFIG_UDP_FUNCTION_FASTBOOT) += fastboot.o
obj-$(CONFIG_CMD_WOL) += wol.o
+obj-$(CONFIG_PROT_UDP) += udp.o
# Disable this warning as it is triggered by:
# sprintf(buf, index ? "foo%d" : "foo", index)
diff --git a/net/eth-uclass.c b/net/eth-uclass.c
index 0d9b75a9a20..396418eb390 100644
--- a/net/eth-uclass.c
+++ b/net/eth-uclass.c
@@ -273,7 +273,7 @@ int eth_init(void)
if (!current) {
current = eth_get_dev();
if (!current) {
- printf("No ethernet found.\n");
+ log_err("No ethernet found.\n");
return -ENODEV;
}
}
@@ -414,7 +414,7 @@ int eth_initialize(void)
*/
uclass_first_device_check(UCLASS_ETH, &dev);
if (!dev) {
- printf("No ethernet found.\n");
+ log_err("No ethernet found.\n");
bootstage_error(BOOTSTAGE_ID_NET_ETH_START);
} else {
char *ethprime = env_get("ethprime");
@@ -449,7 +449,7 @@ int eth_initialize(void)
} while (dev);
if (!num_devices)
- printf("No ethernet found.\n");
+ log_err("No ethernet found.\n");
putc('\n');
}
diff --git a/net/eth_legacy.c b/net/eth_legacy.c
index 992d1880bf3..6e0c0587616 100644
--- a/net/eth_legacy.c
+++ b/net/eth_legacy.c
@@ -261,7 +261,7 @@ int eth_initialize(void)
}
if (!eth_devices) {
- puts("No ethernet found.\n");
+ log_err("No ethernet found.\n");
bootstage_error(BOOTSTAGE_ID_NET_ETH_START);
} else {
struct eth_device *dev = eth_devices;
@@ -319,7 +319,7 @@ int eth_init(void)
struct eth_device *old_current;
if (!eth_current) {
- puts("No ethernet found.\n");
+ log_err("No ethernet found.\n");
return -ENODEV;
}
diff --git a/net/net.c b/net/net.c
index 28d9eebf9dd..197fde3568d 100644
--- a/net/net.c
+++ b/net/net.c
@@ -72,12 +72,6 @@
* We want: - load the boot file
* Next step: none
*
- * SNTP:
- *
- * Prerequisites: - own ethernet address
- * - own IP address
- * We want: - network time
- * Next step: none
*
* WOL:
*
@@ -102,6 +96,7 @@
#if defined(CONFIG_CMD_PCAP)
#include <net/pcap.h>
#endif
+#include <net/udp.h>
#if defined(CONFIG_LED_STATUS)
#include <miiphy.h>
#include <status_led.h>
@@ -118,9 +113,6 @@
#include "nfs.h"
#include "ping.h"
#include "rarp.h"
-#if defined(CONFIG_CMD_SNTP)
-#include "sntp.h"
-#endif
#if defined(CONFIG_CMD_WOL)
#include "wol.h"
#endif
@@ -184,13 +176,6 @@ u32 net_boot_file_size;
/* Boot file size in blocks as reported by the DHCP server */
u32 net_boot_file_expected_size_in_blocks;
-#if defined(CONFIG_CMD_SNTP)
-/* NTP server IP address */
-struct in_addr net_ntp_server;
-/* offset time from UTC */
-int net_ntp_time_offset;
-#endif
-
static uchar net_pkt_buf[(PKTBUFSRX+1) * PKTSIZE_ALIGN + PKTALIGN];
/* Receive packets */
uchar *net_rx_packets[PKTBUFSRX];
@@ -520,11 +505,6 @@ restart:
nc_start();
break;
#endif
-#if defined(CONFIG_CMD_SNTP)
- case SNTP:
- sntp_start();
- break;
-#endif
#if defined(CONFIG_CMD_DNS)
case DNS:
dns_start();
@@ -544,6 +524,9 @@ restart:
break;
}
+ if (IS_ENABLED(CONFIG_PROT_UDP) && protocol == UDP)
+ udp_start();
+
break;
}
@@ -1348,14 +1331,6 @@ static int net_check_prereq(enum proto_t protocol)
}
goto common;
#endif
-#if defined(CONFIG_CMD_SNTP)
- case SNTP:
- if (net_ntp_server.s_addr == 0) {
- puts("*** ERROR: NTP server address not given\n");
- return 1;
- }
- goto common;
-#endif
#if defined(CONFIG_CMD_DNS)
case DNS:
if (net_dns_server.s_addr == 0) {
@@ -1364,6 +1339,13 @@ static int net_check_prereq(enum proto_t protocol)
}
goto common;
#endif
+#if defined(CONFIG_PROT_UDP)
+ case UDP:
+ if (udp_prereq())
+ return 1;
+ goto common;
+#endif
+
#if defined(CONFIG_CMD_NFS)
case NFS:
#endif
@@ -1374,8 +1356,8 @@ static int net_check_prereq(enum proto_t protocol)
puts("*** ERROR: `serverip' not set\n");
return 1;
}
-#if defined(CONFIG_CMD_PING) || defined(CONFIG_CMD_SNTP) || \
- defined(CONFIG_CMD_DNS)
+#if defined(CONFIG_CMD_PING) || \
+ defined(CONFIG_CMD_DNS) || defined(CONFIG_PROT_UDP)
common:
#endif
/* Fall through */
diff --git a/net/sntp.c b/net/sntp.c
index 39d7664a224..d5d56719331 100644
--- a/net/sntp.c
+++ b/net/sntp.c
@@ -12,12 +12,17 @@
#include <net.h>
#include <rtc.h>
-#include "sntp.h"
+#include <net/sntp.h>
#define SNTP_TIMEOUT 10000UL
static int sntp_our_port;
+/* NTP server IP address */
+struct in_addr net_ntp_server;
+/* offset time from UTC */
+int net_ntp_time_offset;
+
static void sntp_send(void)
{
struct sntp_pkt_t pkt;
@@ -93,7 +98,25 @@ static void sntp_handler(uchar *pkt, unsigned dest, struct in_addr sip,
net_set_state(NETLOOP_SUCCESS);
}
-void sntp_start(void)
+/*
+ * SNTP:
+ *
+ * Prerequisites: - own ethernet address
+ * - own IP address
+ * We want: - network time
+ * Next step: none
+ */
+int sntp_prereq(void *data)
+{
+ if (net_ntp_server.s_addr == 0) {
+ puts("*** ERROR: NTP server address not given\n");
+ return 1;
+ }
+
+ return 0;
+}
+
+int sntp_start(void *data)
{
debug("%s\n", __func__);
@@ -102,4 +125,6 @@ void sntp_start(void)
memset(net_server_ethaddr, 0, sizeof(net_server_ethaddr));
sntp_send();
+
+ return 0;
}
diff --git a/net/tftp.c b/net/tftp.c
index 84e970bec13..6fdb1a821a8 100644
--- a/net/tftp.c
+++ b/net/tftp.c
@@ -159,7 +159,8 @@ static unsigned short tftp_window_size_option = TFTP_WINDOWSIZE;
static inline int store_block(int block, uchar *src, unsigned int len)
{
- ulong offset = block * tftp_block_size + tftp_block_wrap_offset;
+ ulong offset = block * tftp_block_size + tftp_block_wrap_offset -
+ tftp_block_size;
ulong newsize = offset + len;
ulong store_addr = tftp_load_addr + offset;
#ifdef CONFIG_SYS_DIRECT_FLASH_TFTP
@@ -233,7 +234,8 @@ static void new_transfer(void)
static int load_block(unsigned block, uchar *dst, unsigned len)
{
/* We may want to get the final block from the previous set */
- ulong offset = ((int)block - 1) * len + tftp_block_wrap_offset;
+ ulong offset = block * tftp_block_size + tftp_block_wrap_offset -
+ tftp_block_size;
ulong tosend = len;
tosend = min(net_boot_file_size - offset, tosend);
@@ -502,6 +504,7 @@ static void tftp_handler(uchar *pkt, unsigned dest, struct in_addr sip,
int block = ntohs(*s);
int ack_ok = (tftp_cur_block == block);
+ tftp_prev_block = tftp_cur_block;
tftp_cur_block = (unsigned short)(block + 1);
update_block_number();
if (ack_ok)
@@ -651,7 +654,7 @@ static void tftp_handler(uchar *pkt, unsigned dest, struct in_addr sip,
timeout_count_max = tftp_timeout_count_max;
net_set_timeout_handler(timeout_ms, tftp_timeout_handler);
- if (store_block(tftp_cur_block - 1, pkt + 2, len)) {
+ if (store_block(tftp_cur_block, pkt + 2, len)) {
eth_halt();
net_set_state(NETLOOP_FAIL);
break;
diff --git a/net/udp.c b/net/udp.c
new file mode 100644
index 00000000000..a93822f511c
--- /dev/null
+++ b/net/udp.c
@@ -0,0 +1,46 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2020 Philippe Reynes <philippe.reynes@softathome.com>
+ */
+
+#include <common.h>
+#include <net.h>
+#include <net/udp.h>
+
+static struct udp_ops *udp_ops;
+
+int udp_prereq(void)
+{
+ int ret = 0;
+
+ if (udp_ops->prereq)
+ ret = udp_ops->prereq(udp_ops->data);
+
+ return ret;
+}
+
+int udp_start(void)
+{
+ return udp_ops->start(udp_ops->data);
+}
+
+int udp_loop(struct udp_ops *ops)
+{
+ int ret = -1;
+
+ if (!ops) {
+ printf("%s: ops should not be null\n", __func__);
+ goto out;
+ }
+
+ if (!ops->start) {
+ printf("%s: no start function defined\n", __func__);
+ goto out;
+ }
+
+ udp_ops = ops;
+ ret = net_loop(UDP);
+
+ out:
+ return ret;
+}