mirror of
https://github.com/AsahiLinux/u-boot
synced 2025-02-17 22:49:02 +00:00
Merge branch '2020-09-30-assorted-network-improvements' into next
- Generic UDP framework - TFTP fixes - dwc_eth_qos, smc911x, smc911x and mscc phy fixes
This commit is contained in:
commit
26acc6395f
22 changed files with 494 additions and 72 deletions
|
@ -1645,6 +1645,7 @@ config CMD_CDP
|
|||
|
||||
config CMD_SNTP
|
||||
bool "sntp"
|
||||
select PROT_UDP
|
||||
help
|
||||
Synchronize RTC via network
|
||||
|
||||
|
|
10
cmd/net.c
10
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;
|
||||
|
|
|
@ -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
|
||||
|
|
35
doc/README.udp
Normal file
35
doc/README.udp
Normal file
|
@ -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);
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
177
drivers/phy/phy-bcm-sr-pcie.c
Normal file
177
drivers/phy/phy-bcm-sr-pcie.c
Normal file
|
@ -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),
|
||||
};
|
|
@ -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 */
|
||||
|
|
|
@ -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__ */
|
41
include/net/udp.h
Normal file
41
include/net/udp.h
Normal file
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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');
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
44
net/net.c
44
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 */
|
||||
|
|
29
net/sntp.c
29
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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
46
net/udp.c
Normal file
46
net/udp.c
Normal file
|
@ -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;
|
||||
}
|
Loading…
Add table
Reference in a new issue