summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Rini <trini@konsulko.com>2023-07-27 16:45:50 -0400
committerTom Rini <trini@konsulko.com>2023-07-27 16:45:50 -0400
commit67957176a258d4288740acd2a18097d5b4ecf080 (patch)
treec6e3a7ca859163001529829eab3697518ebe3678
parentc98c401dfb485b39c7453a4147b17cd4b8d10c67 (diff)
parente8b4a8d7f0583268a9ecfb4910558e10aa7a473b (diff)
downloadu-boot-67957176a258d4288740acd2a18097d5b4ecf080.tar.gz
u-boot-67957176a258d4288740acd2a18097d5b4ecf080.tar.bz2
u-boot-67957176a258d4288740acd2a18097d5b4ecf080.zip
Merge branch '2023-07-27-assorted-network-updates'
- Merge a few network updates
-rw-r--r--drivers/net/ksz9477.c103
-rw-r--r--drivers/net/phy/adin.c14
-rw-r--r--include/net6.h2
-rw-r--r--net/ndisc.c2
4 files changed, 106 insertions, 15 deletions
diff --git a/drivers/net/ksz9477.c b/drivers/net/ksz9477.c
index 6b59b5fcd2..43baa69961 100644
--- a/drivers/net/ksz9477.c
+++ b/drivers/net/ksz9477.c
@@ -16,6 +16,10 @@
#include <asm-generic/gpio.h>
+/* Used with variable features to indicate capabilities. */
+#define NEW_XMII BIT(1)
+#define IS_9893 BIT(2)
+
/* Global registers */
/* Chip ID */
@@ -41,6 +45,13 @@
#define PORT_RMII_SEL 0x1
#define PORT_GMII_SEL 0x2
#define PORT_MII_SEL 0x3
+/* S1 */
+#define PORT_MII_1000MBIT_S1 BIT(6)
+/* S1 */
+#define PORT_MII_SEL_S1 0x0
+#define PORT_RMII_SEL_S1 0x1
+#define PORT_GMII_SEL_S1 0x2
+#define PORT_RGMII_SEL_S1 0x3
/* Port MSTP State Register */
#define REG_PORT_MSTP_STATE 0x0b04
@@ -62,6 +73,8 @@
struct ksz_dsa_priv {
struct udevice *dev;
+
+ u32 features; /* chip specific features */
};
static inline int ksz_read8(struct udevice *dev, u32 reg, u8 *val)
@@ -284,6 +297,60 @@ U_BOOT_DRIVER(ksz_mdio) = {
.plat_auto = sizeof(struct mdio_perdev_priv),
};
+static void ksz9477_set_gbit(struct ksz_dsa_priv *priv, bool gbit, u8 *data)
+{
+ if (priv->features & NEW_XMII) {
+ if (gbit)
+ *data &= ~PORT_MII_NOT_1GBIT;
+ else
+ *data |= PORT_MII_NOT_1GBIT;
+ } else {
+ if (gbit)
+ *data |= PORT_MII_1000MBIT_S1;
+ else
+ *data &= ~PORT_MII_1000MBIT_S1;
+ }
+}
+
+static void ksz9477_set_xmii(struct ksz_dsa_priv *priv, int mode, u8 *data)
+{
+ u8 xmii;
+
+ if (priv->features & NEW_XMII) {
+ switch (mode) {
+ case 0:
+ xmii = PORT_MII_SEL;
+ break;
+ case 1:
+ xmii = PORT_RMII_SEL;
+ break;
+ case 2:
+ xmii = PORT_GMII_SEL;
+ break;
+ default:
+ xmii = PORT_RGMII_SEL;
+ break;
+ }
+ } else {
+ switch (mode) {
+ case 0:
+ xmii = PORT_MII_SEL_S1;
+ break;
+ case 1:
+ xmii = PORT_RMII_SEL_S1;
+ break;
+ case 2:
+ xmii = PORT_GMII_SEL_S1;
+ break;
+ default:
+ xmii = PORT_RGMII_SEL_S1;
+ break;
+ }
+ }
+ *data &= ~PORT_MII_SEL_M;
+ *data |= xmii;
+}
+
static int ksz_port_setup(struct udevice *dev, int port,
phy_interface_t interface)
{
@@ -293,9 +360,11 @@ static int ksz_port_setup(struct udevice *dev, int port,
dev_dbg(dev, "%s P%d %s\n", __func__, port + 1,
(port == pdata->cpu_port) ? "cpu" : "");
+ struct ksz_dsa_priv *priv = dev_get_priv(dev);
if (port != pdata->cpu_port) {
- /* phy port: config errata and leds */
- ksz_phy_errata_setup(dev, port);
+ if (priv->features & NEW_XMII)
+ /* phy port: config errata and leds */
+ ksz_phy_errata_setup(dev, port);
} else {
/* cpu port: configure MAC interface mode */
ksz_pread8(dev, port, REG_PORT_XMII_CTRL_1, &data8);
@@ -303,24 +372,20 @@ static int ksz_port_setup(struct udevice *dev, int port,
phy_string_for_interface(interface));
switch (interface) {
case PHY_INTERFACE_MODE_MII:
- data8 &= ~PORT_MII_SEL_M;
- data8 |= PORT_MII_SEL;
- data8 |= PORT_MII_NOT_1GBIT;
+ ksz9477_set_xmii(priv, 0, &data8);
+ ksz9477_set_gbit(priv, false, &data8);
break;
case PHY_INTERFACE_MODE_RMII:
- data8 &= ~PORT_MII_SEL_M;
- data8 |= PORT_RMII_SEL;
- data8 |= PORT_MII_NOT_1GBIT;
+ ksz9477_set_xmii(priv, 1, &data8);
+ ksz9477_set_gbit(priv, false, &data8);
break;
case PHY_INTERFACE_MODE_GMII:
- data8 &= ~PORT_MII_SEL_M;
- data8 |= PORT_GMII_SEL;
- data8 &= ~PORT_MII_NOT_1GBIT;
+ ksz9477_set_xmii(priv, 2, &data8);
+ ksz9477_set_gbit(priv, true, &data8);
break;
default:
- data8 &= ~PORT_MII_SEL_M;
- data8 |= PORT_RGMII_SEL;
- data8 &= ~PORT_MII_NOT_1GBIT;
+ ksz9477_set_xmii(priv, 3, &data8);
+ ksz9477_set_gbit(priv, true, &data8);
data8 &= ~PORT_RGMII_ID_IG_ENABLE;
data8 &= ~PORT_RGMII_ID_EG_ENABLE;
if (interface == PHY_INTERFACE_MODE_RGMII_ID ||
@@ -329,6 +394,8 @@ static int ksz_port_setup(struct udevice *dev, int port,
if (interface == PHY_INTERFACE_MODE_RGMII_ID ||
interface == PHY_INTERFACE_MODE_RGMII_TXID)
data8 |= PORT_RGMII_ID_EG_ENABLE;
+ if (priv->features & IS_9893)
+ data8 &= ~PORT_MII_MAC_MODE;
break;
}
ksz_write8(dev, PORT_CTRL_ADDR(port, REG_PORT_XMII_CTRL_1), data8);
@@ -479,10 +546,17 @@ static int ksz_i2c_probe(struct udevice *dev)
case 0x00989700:
puts("KSZ9897S: ");
break;
+ case 0x00989300:
+ puts("KSZ9893R: ");
+ break;
default:
dev_err(dev, "invalid chip id: 0x%08x\n", id);
return -EINVAL;
}
+ if ((id & 0xf00) == 0x300)
+ priv->features |= IS_9893;
+ else
+ priv->features |= NEW_XMII;
/* probe mdio bus */
ret = ksz_probe_mdio(dev);
@@ -503,6 +577,7 @@ static const struct udevice_id ksz_i2c_ids[] = {
{ .compatible = "microchip,ksz9897" },
{ .compatible = "microchip,ksz9477" },
{ .compatible = "microchip,ksz9567" },
+ { .compatible = "microchip,ksz9893" },
{ }
};
diff --git a/drivers/net/phy/adin.c b/drivers/net/phy/adin.c
index fb9f1e4c70..0970449d0f 100644
--- a/drivers/net/phy/adin.c
+++ b/drivers/net/phy/adin.c
@@ -155,6 +155,18 @@ static int adin_ext_write(struct phy_device *phydev, const u32 regnum, const u16
return phy_write(phydev, MDIO_DEVAD_NONE, ADIN1300_EXT_REG_DATA, val);
}
+static int adin_extread(struct phy_device *phydev, int addr, int devaddr,
+ int regnum)
+{
+ return adin_ext_read(phydev, regnum);
+}
+
+static int adin_extwrite(struct phy_device *phydev, int addr,
+ int devaddr, int regnum, u16 val)
+{
+ return adin_ext_write(phydev, regnum, val);
+}
+
static int adin_config_clk_out(struct phy_device *phydev)
{
ofnode node = phy_get_ofnode(phydev);
@@ -260,4 +272,6 @@ U_BOOT_PHY_DRIVER(ADIN1300) = {
.config = adin1300_config,
.startup = genphy_startup,
.shutdown = genphy_shutdown,
+ .readext = adin_extread,
+ .writeext = adin_extwrite,
};
diff --git a/include/net6.h b/include/net6.h
index beafc05338..1e766aa720 100644
--- a/include/net6.h
+++ b/include/net6.h
@@ -204,7 +204,7 @@ struct icmp6_ra_prefix_info {
* be initialized to zero by the sender and ignored by the receiver.
*/
struct in6_addr prefix;
-};
+} __packed;
extern struct in6_addr const net_null_addr_ip6; /* NULL IPv6 address */
extern struct in6_addr net_gateway6; /* Our gateways IPv6 address */
diff --git a/net/ndisc.c b/net/ndisc.c
index 0b27779ce5..d1cec0601c 100644
--- a/net/ndisc.c
+++ b/net/ndisc.c
@@ -382,6 +382,8 @@ int process_ra(struct ip6_hdr *ip6, int len)
unsigned char type = 0;
struct icmp6_ra_prefix_info *prefix = NULL;
+ if (len > ETH_MAX_MTU)
+ return -EMSGSIZE;
/* Ignore the packet if router lifetime is 0. */
if (!icmp->icmp6_rt_lifetime)
return -EOPNOTSUPP;