U-Boot
Threads by month
- ----- 2025 -----
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2004 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2003 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2002 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2001 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2000 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
March 2023
- 199 participants
- 606 discussions

[PATCH] Revert 9f62a472dfb2 ("video: Remove duplicate cursor-positioning function")
by Tom Rini 02 Apr '23
by Tom Rini 02 Apr '23
02 Apr '23
This reverts commit 9f62a472dfb26ec14408a27938ddd2a25700009d.
The changes here aren't quite right, and on platforms such as Raspberry
Pi where we can have both serial and video output, the change above
causes output to change. This can be seen as the hush tests we have now
fail.
Signed-off-by: Tom Rini <trini(a)konsulko.com>
---
Cc: Simon Glass <sjg(a)chromium.org>
Some other issues in my lab meant I thought I had tested this platform
when I took the PR in originally, but hadn't. So I'd like to grab this
ASAP.
---
drivers/video/vidconsole-uclass.c | 44 ++++++++++++++++++++++++-------
1 file changed, 34 insertions(+), 10 deletions(-)
diff --git a/drivers/video/vidconsole-uclass.c b/drivers/video/vidconsole-uclass.c
index 61f4216750f2..1225de233325 100644
--- a/drivers/video/vidconsole-uclass.c
+++ b/drivers/video/vidconsole-uclass.c
@@ -126,14 +126,26 @@ void vidconsole_set_cursor_pos(struct udevice *dev, int x, int y)
priv->ycur = y;
}
-void vidconsole_position_cursor(struct udevice *dev, uint col, uint row)
+/**
+ * set_cursor_position() - set cursor position
+ *
+ * @priv: private data of the video console
+ * @row: new row
+ * @col: new column
+ */
+static void set_cursor_position(struct vidconsole_priv *priv, int row, int col)
{
- struct vidconsole_priv *priv = dev_get_uclass_priv(dev);
- short x, y;
-
- x = min_t(short, col, priv->cols - 1) * priv->x_charsize;
- y = min_t(short, row, priv->rows - 1) * priv->y_charsize;
- vidconsole_set_cursor_pos(dev, x, y);
+ /*
+ * Ensure we stay in the bounds of the screen.
+ */
+ if (row >= priv->rows)
+ row = priv->rows - 1;
+ if (col >= priv->cols)
+ col = priv->cols - 1;
+
+ priv->ycur = row * priv->y_charsize;
+ priv->xcur_frac = priv->xstart_frac +
+ VID_TO_POS(col * priv->x_charsize);
}
/**
@@ -180,7 +192,7 @@ static void vidconsole_escape_char(struct udevice *dev, char ch)
int row = priv->row_saved;
int col = priv->col_saved;
- vidconsole_position_cursor(dev, col, row);
+ set_cursor_position(priv, row, col);
priv->escape = 0;
return;
}
@@ -242,7 +254,7 @@ static void vidconsole_escape_char(struct udevice *dev, char ch)
if (row < 0)
row = 0;
/* Right and bottom overflows are handled in the callee. */
- vidconsole_position_cursor(dev, col, row);
+ set_cursor_position(priv, row, col);
break;
}
case 'H':
@@ -266,7 +278,7 @@ static void vidconsole_escape_char(struct udevice *dev, char ch)
if (col)
--col;
- vidconsole_position_cursor(dev, col, row);
+ set_cursor_position(priv, row, col);
break;
}
@@ -655,3 +667,15 @@ int vidconsole_clear_and_reset(struct udevice *dev)
return 0;
}
+
+void vidconsole_position_cursor(struct udevice *dev, unsigned col, unsigned row)
+{
+ struct vidconsole_priv *priv = dev_get_uclass_priv(dev);
+ struct udevice *vid_dev = dev->parent;
+ struct video_priv *vid_priv = dev_get_uclass_priv(vid_dev);
+ short x, y;
+
+ x = min_t(short, col * priv->x_charsize, vid_priv->xsize - 1);
+ y = min_t(short, row * priv->y_charsize, vid_priv->ysize - 1);
+ vidconsole_set_cursor_pos(dev, x, y);
+}
--
2.34.1
2
4
From: Jianqun Xu <jay.xu(a)rock-chips.com>
Add support for Rockchip rk3588 variant of pinctrl.
The driver is adapted from the Linux driver.
Signed-off-by: Jianqun Xu <jay.xu(a)rock-chips.com>
[eugen.hristev(a)collabora.com:
port to latest U-boot, bring more changes from Linux
use translated pull values table]
Signed-off-by: Eugen Hristev <eugen.hristev(a)collabora.com>
---
Changes in v4:
- After checking with what happens in Linux, it appears that the gpio4
D0-D5 also work using VCCIO2, just that the value written by Uboot
appears to be wrongly computed. Linux and other drivers like rk3568
use a translated pull value. Adapt also the r3588 to use this translated
value. Now the arrays are identical with Linux
Changes in v3:
- change assert(i) to assert (i >= 0) because i==0 is a valid number it's
the first entry in the array. Otherwise it would assert wrongly when setting
gpio 0 A2 e.g.
Changes in v2:
- change the way the reg is computed to align with Linux
- For the gpio4 bank D0-8, as the downstream uboot uses VCCIO6 instead of
VCCIO2, change accordingly, otherwise D0-D5 pins won't work to set PUP/PDOWN,
DS, etc. It appears gpio4D has the registers just after gpio4A,gpio4B,gpio4C
in the same VCCIO6, and not in VCCIO2.
drivers/pinctrl/rockchip/Makefile | 1 +
drivers/pinctrl/rockchip/pinctrl-rk3588.c | 353 ++++++++++++++++++++
drivers/pinctrl/rockchip/pinctrl-rockchip.h | 187 +++++++++++
3 files changed, 541 insertions(+)
create mode 100644 drivers/pinctrl/rockchip/pinctrl-rk3588.c
diff --git a/drivers/pinctrl/rockchip/Makefile b/drivers/pinctrl/rockchip/Makefile
index 90461ae8819a..c91f650b0434 100644
--- a/drivers/pinctrl/rockchip/Makefile
+++ b/drivers/pinctrl/rockchip/Makefile
@@ -15,5 +15,6 @@ obj-$(CONFIG_ROCKCHIP_RK3328) += pinctrl-rk3328.o
obj-$(CONFIG_ROCKCHIP_RK3368) += pinctrl-rk3368.o
obj-$(CONFIG_ROCKCHIP_RK3399) += pinctrl-rk3399.o
obj-$(CONFIG_ROCKCHIP_RK3568) += pinctrl-rk3568.o
+obj-$(CONFIG_ROCKCHIP_RK3588) += pinctrl-rk3588.o
obj-$(CONFIG_ROCKCHIP_RV1108) += pinctrl-rv1108.o
obj-$(CONFIG_ROCKCHIP_RV1126) += pinctrl-rv1126.o
diff --git a/drivers/pinctrl/rockchip/pinctrl-rk3588.c b/drivers/pinctrl/rockchip/pinctrl-rk3588.c
new file mode 100644
index 000000000000..548cf09bcca4
--- /dev/null
+++ b/drivers/pinctrl/rockchip/pinctrl-rk3588.c
@@ -0,0 +1,353 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2021 Rockchip Electronics Co., Ltd
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <dm/pinctrl.h>
+#include <regmap.h>
+#include <syscon.h>
+
+#include "pinctrl-rockchip.h"
+#include <dt-bindings/pinctrl/rockchip.h>
+
+static int rk3588_set_mux(struct rockchip_pin_bank *bank, int pin, int mux)
+{
+ struct rockchip_pinctrl_priv *priv = bank->priv;
+ struct regmap *regmap;
+ int iomux_num = (pin / 8);
+ int reg, ret, mask;
+ u8 bit;
+ u32 data;
+
+ debug("setting mux of GPIO%d-%d to %d\n", bank->bank_num, pin, mux);
+
+ regmap = priv->regmap_base;
+ reg = bank->iomux[iomux_num].offset;
+ if ((pin % 8) >= 4)
+ reg += 0x4;
+ bit = (pin % 4) * 4;
+ mask = 0xf;
+
+ if (bank->bank_num == 0) {
+ if (pin >= RK_PB4 && pin <= RK_PD7) {
+ if (mux < 8) {
+ reg += 0x4000 - 0xC; /* PMU2_IOC_BASE */
+ data = (mask << (bit + 16));
+ data |= (mux & mask) << bit;
+ ret = regmap_write(regmap, reg, data);
+ } else {
+ u32 reg0 = 0;
+
+ reg0 = reg + 0x4000 - 0xC; /* PMU2_IOC_BASE */
+ data = (mask << (bit + 16));
+ data |= 8 << bit;
+ ret = regmap_write(regmap, reg0, data);
+
+ reg0 = reg + 0x8000; /* BUS_IOC_BASE */
+ data = (mask << (bit + 16));
+ data |= mux << bit;
+ regmap = priv->regmap_base;
+ regmap_write(regmap, reg0, data);
+ }
+ } else {
+ data = (mask << (bit + 16));
+ data |= (mux & mask) << bit;
+ ret = regmap_write(regmap, reg, data);
+ }
+ return ret;
+ } else if (bank->bank_num > 0) {
+ reg += 0x8000; /* BUS_IOC_BASE */
+ }
+
+ data = (mask << (bit + 16));
+ data |= (mux & mask) << bit;
+
+ return regmap_write(regmap, reg, data);
+}
+
+#define RK3588_PMU1_IOC_REG (0x0000)
+#define RK3588_PMU2_IOC_REG (0x4000)
+#define RK3588_BUS_IOC_REG (0x8000)
+#define RK3588_VCCIO1_4_IOC_REG (0x9000)
+#define RK3588_VCCIO3_5_IOC_REG (0xA000)
+#define RK3588_VCCIO2_IOC_REG (0xB000)
+#define RK3588_VCCIO6_IOC_REG (0xC000)
+#define RK3588_EMMC_IOC_REG (0xD000)
+
+static const u32 rk3588_ds_regs[][2] = {
+ {RK_GPIO0_A0, RK3588_PMU1_IOC_REG + 0x0010},
+ {RK_GPIO0_A4, RK3588_PMU1_IOC_REG + 0x0014},
+ {RK_GPIO0_B0, RK3588_PMU1_IOC_REG + 0x0018},
+ {RK_GPIO0_B4, RK3588_PMU2_IOC_REG + 0x0014},
+ {RK_GPIO0_C0, RK3588_PMU2_IOC_REG + 0x0018},
+ {RK_GPIO0_C4, RK3588_PMU2_IOC_REG + 0x001C},
+ {RK_GPIO0_D0, RK3588_PMU2_IOC_REG + 0x0020},
+ {RK_GPIO0_D4, RK3588_PMU2_IOC_REG + 0x0024},
+ {RK_GPIO1_A0, RK3588_VCCIO1_4_IOC_REG + 0x0020},
+ {RK_GPIO1_A4, RK3588_VCCIO1_4_IOC_REG + 0x0024},
+ {RK_GPIO1_B0, RK3588_VCCIO1_4_IOC_REG + 0x0028},
+ {RK_GPIO1_B4, RK3588_VCCIO1_4_IOC_REG + 0x002C},
+ {RK_GPIO1_C0, RK3588_VCCIO1_4_IOC_REG + 0x0030},
+ {RK_GPIO1_C4, RK3588_VCCIO1_4_IOC_REG + 0x0034},
+ {RK_GPIO1_D0, RK3588_VCCIO1_4_IOC_REG + 0x0038},
+ {RK_GPIO1_D4, RK3588_VCCIO1_4_IOC_REG + 0x003C},
+ {RK_GPIO2_A0, RK3588_EMMC_IOC_REG + 0x0040},
+ {RK_GPIO2_A4, RK3588_VCCIO3_5_IOC_REG + 0x0044},
+ {RK_GPIO2_B0, RK3588_VCCIO3_5_IOC_REG + 0x0048},
+ {RK_GPIO2_B4, RK3588_VCCIO3_5_IOC_REG + 0x004C},
+ {RK_GPIO2_C0, RK3588_VCCIO3_5_IOC_REG + 0x0050},
+ {RK_GPIO2_C4, RK3588_VCCIO3_5_IOC_REG + 0x0054},
+ {RK_GPIO2_D0, RK3588_EMMC_IOC_REG + 0x0058},
+ {RK_GPIO2_D4, RK3588_EMMC_IOC_REG + 0x005C},
+ {RK_GPIO3_A0, RK3588_VCCIO3_5_IOC_REG + 0x0060},
+ {RK_GPIO3_A4, RK3588_VCCIO3_5_IOC_REG + 0x0064},
+ {RK_GPIO3_B0, RK3588_VCCIO3_5_IOC_REG + 0x0068},
+ {RK_GPIO3_B4, RK3588_VCCIO3_5_IOC_REG + 0x006C},
+ {RK_GPIO3_C0, RK3588_VCCIO3_5_IOC_REG + 0x0070},
+ {RK_GPIO3_C4, RK3588_VCCIO3_5_IOC_REG + 0x0074},
+ {RK_GPIO3_D0, RK3588_VCCIO3_5_IOC_REG + 0x0078},
+ {RK_GPIO3_D4, RK3588_VCCIO3_5_IOC_REG + 0x007C},
+ {RK_GPIO4_A0, RK3588_VCCIO6_IOC_REG + 0x0080},
+ {RK_GPIO4_A4, RK3588_VCCIO6_IOC_REG + 0x0084},
+ {RK_GPIO4_B0, RK3588_VCCIO6_IOC_REG + 0x0088},
+ {RK_GPIO4_B4, RK3588_VCCIO6_IOC_REG + 0x008C},
+ {RK_GPIO4_C0, RK3588_VCCIO6_IOC_REG + 0x0090},
+ {RK_GPIO4_C2, RK3588_VCCIO3_5_IOC_REG + 0x0090},
+ {RK_GPIO4_C4, RK3588_VCCIO3_5_IOC_REG + 0x0094},
+ {RK_GPIO4_D0, RK3588_VCCIO2_IOC_REG + 0x0098},
+ {RK_GPIO4_D4, RK3588_VCCIO2_IOC_REG + 0x009C},
+};
+
+static const u32 rk3588_p_regs[][2] = {
+ {RK_GPIO0_A0, RK3588_PMU1_IOC_REG + 0x0020},
+ {RK_GPIO0_B0, RK3588_PMU1_IOC_REG + 0x0024},
+ {RK_GPIO0_B5, RK3588_PMU2_IOC_REG + 0x0028},
+ {RK_GPIO0_C0, RK3588_PMU2_IOC_REG + 0x002C},
+ {RK_GPIO0_D0, RK3588_PMU2_IOC_REG + 0x0030},
+ {RK_GPIO1_A0, RK3588_VCCIO1_4_IOC_REG + 0x0110},
+ {RK_GPIO1_B0, RK3588_VCCIO1_4_IOC_REG + 0x0114},
+ {RK_GPIO1_C0, RK3588_VCCIO1_4_IOC_REG + 0x0118},
+ {RK_GPIO1_D0, RK3588_VCCIO1_4_IOC_REG + 0x011C},
+ {RK_GPIO2_A0, RK3588_EMMC_IOC_REG + 0x0120},
+ {RK_GPIO2_A6, RK3588_VCCIO3_5_IOC_REG + 0x0120},
+ {RK_GPIO2_B0, RK3588_VCCIO3_5_IOC_REG + 0x0124},
+ {RK_GPIO2_C0, RK3588_VCCIO3_5_IOC_REG + 0x0128},
+ {RK_GPIO2_D0, RK3588_EMMC_IOC_REG + 0x012C},
+ {RK_GPIO3_A0, RK3588_VCCIO3_5_IOC_REG + 0x0130},
+ {RK_GPIO3_B0, RK3588_VCCIO3_5_IOC_REG + 0x0134},
+ {RK_GPIO3_C0, RK3588_VCCIO3_5_IOC_REG + 0x0138},
+ {RK_GPIO3_D0, RK3588_VCCIO3_5_IOC_REG + 0x013C},
+ {RK_GPIO4_A0, RK3588_VCCIO6_IOC_REG + 0x0140},
+ {RK_GPIO4_B0, RK3588_VCCIO6_IOC_REG + 0x0144},
+ {RK_GPIO4_C0, RK3588_VCCIO6_IOC_REG + 0x0148},
+ {RK_GPIO4_C2, RK3588_VCCIO3_5_IOC_REG + 0x0148},
+ {RK_GPIO4_D0, RK3588_VCCIO2_IOC_REG + 0x014C},
+};
+
+static const u32 rk3588_smt_regs[][2] = {
+ {RK_GPIO0_A0, RK3588_PMU1_IOC_REG + 0x0030},
+ {RK_GPIO0_B0, RK3588_PMU1_IOC_REG + 0x0034},
+ {RK_GPIO0_B5, RK3588_PMU2_IOC_REG + 0x0040},
+ {RK_GPIO0_C0, RK3588_PMU2_IOC_REG + 0x0044},
+ {RK_GPIO0_D0, RK3588_PMU2_IOC_REG + 0x0048},
+ {RK_GPIO1_A0, RK3588_VCCIO1_4_IOC_REG + 0x0210},
+ {RK_GPIO1_B0, RK3588_VCCIO1_4_IOC_REG + 0x0214},
+ {RK_GPIO1_C0, RK3588_VCCIO1_4_IOC_REG + 0x0218},
+ {RK_GPIO1_D0, RK3588_VCCIO1_4_IOC_REG + 0x021C},
+ {RK_GPIO2_A0, RK3588_EMMC_IOC_REG + 0x0220},
+ {RK_GPIO2_A6, RK3588_VCCIO3_5_IOC_REG + 0x0220},
+ {RK_GPIO2_B0, RK3588_VCCIO3_5_IOC_REG + 0x0224},
+ {RK_GPIO2_C0, RK3588_VCCIO3_5_IOC_REG + 0x0228},
+ {RK_GPIO2_D0, RK3588_EMMC_IOC_REG + 0x022C},
+ {RK_GPIO3_A0, RK3588_VCCIO3_5_IOC_REG + 0x0230},
+ {RK_GPIO3_B0, RK3588_VCCIO3_5_IOC_REG + 0x0234},
+ {RK_GPIO3_C0, RK3588_VCCIO3_5_IOC_REG + 0x0238},
+ {RK_GPIO3_D0, RK3588_VCCIO3_5_IOC_REG + 0x023C},
+ {RK_GPIO4_A0, RK3588_VCCIO6_IOC_REG + 0x0240},
+ {RK_GPIO4_B0, RK3588_VCCIO6_IOC_REG + 0x0244},
+ {RK_GPIO4_C0, RK3588_VCCIO6_IOC_REG + 0x0248},
+ {RK_GPIO4_C2, RK3588_VCCIO3_5_IOC_REG + 0x0248},
+ {RK_GPIO4_D0, RK3588_VCCIO2_IOC_REG + 0x024C},
+};
+
+#define RK3588_PULL_BITS_PER_PIN 2
+#define RK3588_PULL_PINS_PER_REG 8
+
+static void rk3588_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank,
+ int pin_num, struct regmap **regmap,
+ int *reg, u8 *bit)
+{
+ struct rockchip_pinctrl_priv *info = bank->priv;
+ u8 bank_num = bank->bank_num;
+ u32 pin = bank_num * 32 + pin_num;
+ int i;
+
+ for (i = ARRAY_SIZE(rk3588_p_regs) - 1; i >= 0; i--) {
+ if (pin >= rk3588_p_regs[i][0]) {
+ *reg = rk3588_p_regs[i][1];
+ break;
+ }
+ }
+
+ assert(i >= 0);
+
+ *regmap = info->regmap_base;
+ *bit = pin_num % RK3588_PULL_PINS_PER_REG;
+ *bit *= RK3588_PULL_BITS_PER_PIN;
+}
+
+#define RK3588_DRV_BITS_PER_PIN 4
+#define RK3588_DRV_PINS_PER_REG 4
+
+static void rk3588_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank,
+ int pin_num, struct regmap **regmap,
+ int *reg, u8 *bit)
+{
+ struct rockchip_pinctrl_priv *info = bank->priv;
+ u8 bank_num = bank->bank_num;
+ u32 pin = bank_num * 32 + pin_num;
+ int i;
+
+ for (i = ARRAY_SIZE(rk3588_ds_regs) - 1; i >= 0; i--) {
+ if (pin >= rk3588_ds_regs[i][0]) {
+ *reg = rk3588_ds_regs[i][1];
+ break;
+ }
+ }
+
+ assert(i >= 0);
+
+ *regmap = info->regmap_base;
+ *bit = pin_num % RK3588_DRV_PINS_PER_REG;
+ *bit *= RK3588_DRV_BITS_PER_PIN;
+}
+
+#define RK3588_SMT_BITS_PER_PIN 1
+#define RK3588_SMT_PINS_PER_REG 8
+
+static int rk3588_calc_schmitt_reg_and_bit(struct rockchip_pin_bank *bank,
+ int pin_num, struct regmap **regmap,
+ int *reg, u8 *bit)
+{
+ struct rockchip_pinctrl_priv *info = bank->priv;
+ u8 bank_num = bank->bank_num;
+ u32 pin = bank_num * 32 + pin_num;
+ int i;
+
+ for (i = ARRAY_SIZE(rk3588_smt_regs) - 1; i >= 0; i--) {
+ if (pin >= rk3588_smt_regs[i][0]) {
+ *reg = rk3588_smt_regs[i][1];
+ break;
+ }
+ }
+
+ assert(i >= 0);
+
+ *regmap = info->regmap_base;
+ *bit = pin_num % RK3588_SMT_PINS_PER_REG;
+ *bit *= RK3588_SMT_BITS_PER_PIN;
+
+ return 0;
+}
+
+static int rk3588_set_pull(struct rockchip_pin_bank *bank,
+ int pin_num, int pull)
+{
+ struct regmap *regmap;
+ int reg, translated_pull;
+ u8 bit, type;
+ u32 data;
+
+ rk3588_calc_pull_reg_and_bit(bank, pin_num, ®map, ®, &bit);
+ type = bank->pull_type[pin_num / 8];
+ translated_pull = rockchip_translate_pull_value(type, pull);
+ if (translated_pull < 0) {
+ debug("unsupported pull setting %d\n", pull);
+ return -EINVAL;
+ }
+
+ /* enable the write to the equivalent lower bits */
+ data = ((1 << ROCKCHIP_PULL_BITS_PER_PIN) - 1) << (bit + 16);
+ data |= (translated_pull << bit);
+
+ return regmap_write(regmap, reg, data);
+}
+
+static int rk3588_set_drive(struct rockchip_pin_bank *bank,
+ int pin_num, int strength)
+{
+ struct regmap *regmap;
+ int reg;
+ u32 data;
+ u8 bit;
+
+ rk3588_calc_drv_reg_and_bit(bank, pin_num, ®map, ®, &bit);
+
+ /* enable the write to the equivalent lower bits */
+ data = ((1 << RK3588_DRV_BITS_PER_PIN) - 1) << (bit + 16);
+ data |= (strength << bit);
+
+ return regmap_write(regmap, reg, data);
+}
+
+static int rk3588_set_schmitt(struct rockchip_pin_bank *bank,
+ int pin_num, int enable)
+{
+ struct regmap *regmap;
+ int reg;
+ u32 data;
+ u8 bit;
+
+ rk3588_calc_schmitt_reg_and_bit(bank, pin_num, ®map, ®, &bit);
+
+ /* enable the write to the equivalent lower bits */
+ data = ((1 << RK3588_SMT_BITS_PER_PIN) - 1) << (bit + 16);
+ data |= (enable << bit);
+
+ return regmap_write(regmap, reg, data);
+}
+
+static struct rockchip_pin_bank rk3588_pin_banks[] = {
+ RK3588_PIN_BANK_FLAGS(0, 32, "gpio0",
+ IOMUX_WIDTH_4BIT, PULL_TYPE_IO_1V8_ONLY),
+ RK3588_PIN_BANK_FLAGS(1, 32, "gpio1",
+ IOMUX_WIDTH_4BIT, PULL_TYPE_IO_1V8_ONLY),
+ RK3588_PIN_BANK_FLAGS(2, 32, "gpio2",
+ IOMUX_WIDTH_4BIT, PULL_TYPE_IO_1V8_ONLY),
+ RK3588_PIN_BANK_FLAGS(3, 32, "gpio3",
+ IOMUX_WIDTH_4BIT, PULL_TYPE_IO_1V8_ONLY),
+ RK3588_PIN_BANK_FLAGS(4, 32, "gpio4",
+ IOMUX_WIDTH_4BIT, PULL_TYPE_IO_1V8_ONLY),
+};
+
+static const struct rockchip_pin_ctrl rk3588_pin_ctrl = {
+ .pin_banks = rk3588_pin_banks,
+ .nr_banks = ARRAY_SIZE(rk3588_pin_banks),
+ .nr_pins = 160,
+ .set_mux = rk3588_set_mux,
+ .set_pull = rk3588_set_pull,
+ .set_drive = rk3588_set_drive,
+ .set_schmitt = rk3588_set_schmitt,
+};
+
+static const struct udevice_id rk3588_pinctrl_ids[] = {
+ {
+ .compatible = "rockchip,rk3588-pinctrl",
+ .data = (ulong)&rk3588_pin_ctrl
+ },
+ { }
+};
+
+U_BOOT_DRIVER(pinctrl_rk3588) = {
+ .name = "rockchip_rk3588_pinctrl",
+ .id = UCLASS_PINCTRL,
+ .of_match = rk3588_pinctrl_ids,
+ .priv_auto = sizeof(struct rockchip_pinctrl_priv),
+ .ops = &rockchip_pinctrl_ops,
+#if CONFIG_IS_ENABLED(OF_REAL)
+ .bind = dm_scan_fdt_dev,
+#endif
+ .probe = rockchip_pinctrl_probe,
+};
diff --git a/drivers/pinctrl/rockchip/pinctrl-rockchip.h b/drivers/pinctrl/rockchip/pinctrl-rockchip.h
index 8dfaba5c74d2..df7bc684d29f 100644
--- a/drivers/pinctrl/rockchip/pinctrl-rockchip.h
+++ b/drivers/pinctrl/rockchip/pinctrl-rockchip.h
@@ -9,6 +9,171 @@
#include <linux/bitops.h>
#include <linux/types.h>
+#define RK_GPIO0_A0 0
+#define RK_GPIO0_A1 1
+#define RK_GPIO0_A2 2
+#define RK_GPIO0_A3 3
+#define RK_GPIO0_A4 4
+#define RK_GPIO0_A5 5
+#define RK_GPIO0_A6 6
+#define RK_GPIO0_A7 7
+#define RK_GPIO0_B0 8
+#define RK_GPIO0_B1 9
+#define RK_GPIO0_B2 10
+#define RK_GPIO0_B3 11
+#define RK_GPIO0_B4 12
+#define RK_GPIO0_B5 13
+#define RK_GPIO0_B6 14
+#define RK_GPIO0_B7 15
+#define RK_GPIO0_C0 16
+#define RK_GPIO0_C1 17
+#define RK_GPIO0_C2 18
+#define RK_GPIO0_C3 19
+#define RK_GPIO0_C4 20
+#define RK_GPIO0_C5 21
+#define RK_GPIO0_C6 22
+#define RK_GPIO0_C7 23
+#define RK_GPIO0_D0 24
+#define RK_GPIO0_D1 25
+#define RK_GPIO0_D2 26
+#define RK_GPIO0_D3 27
+#define RK_GPIO0_D4 28
+#define RK_GPIO0_D5 29
+#define RK_GPIO0_D6 30
+#define RK_GPIO0_D7 31
+
+#define RK_GPIO1_A0 32
+#define RK_GPIO1_A1 33
+#define RK_GPIO1_A2 34
+#define RK_GPIO1_A3 35
+#define RK_GPIO1_A4 36
+#define RK_GPIO1_A5 37
+#define RK_GPIO1_A6 38
+#define RK_GPIO1_A7 39
+#define RK_GPIO1_B0 40
+#define RK_GPIO1_B1 41
+#define RK_GPIO1_B2 42
+#define RK_GPIO1_B3 43
+#define RK_GPIO1_B4 44
+#define RK_GPIO1_B5 45
+#define RK_GPIO1_B6 46
+#define RK_GPIO1_B7 47
+#define RK_GPIO1_C0 48
+#define RK_GPIO1_C1 49
+#define RK_GPIO1_C2 50
+#define RK_GPIO1_C3 51
+#define RK_GPIO1_C4 52
+#define RK_GPIO1_C5 53
+#define RK_GPIO1_C6 54
+#define RK_GPIO1_C7 55
+#define RK_GPIO1_D0 56
+#define RK_GPIO1_D1 57
+#define RK_GPIO1_D2 58
+#define RK_GPIO1_D3 59
+#define RK_GPIO1_D4 60
+#define RK_GPIO1_D5 61
+#define RK_GPIO1_D6 62
+#define RK_GPIO1_D7 63
+
+#define RK_GPIO2_A0 64
+#define RK_GPIO2_A1 65
+#define RK_GPIO2_A2 66
+#define RK_GPIO2_A3 67
+#define RK_GPIO2_A4 68
+#define RK_GPIO2_A5 69
+#define RK_GPIO2_A6 70
+#define RK_GPIO2_A7 71
+#define RK_GPIO2_B0 72
+#define RK_GPIO2_B1 73
+#define RK_GPIO2_B2 74
+#define RK_GPIO2_B3 75
+#define RK_GPIO2_B4 76
+#define RK_GPIO2_B5 77
+#define RK_GPIO2_B6 78
+#define RK_GPIO2_B7 79
+#define RK_GPIO2_C0 80
+#define RK_GPIO2_C1 81
+#define RK_GPIO2_C2 82
+#define RK_GPIO2_C3 83
+#define RK_GPIO2_C4 84
+#define RK_GPIO2_C5 85
+#define RK_GPIO2_C6 86
+#define RK_GPIO2_C7 87
+#define RK_GPIO2_D0 88
+#define RK_GPIO2_D1 89
+#define RK_GPIO2_D2 90
+#define RK_GPIO2_D3 91
+#define RK_GPIO2_D4 92
+#define RK_GPIO2_D5 93
+#define RK_GPIO2_D6 94
+#define RK_GPIO2_D7 95
+
+#define RK_GPIO3_A0 96
+#define RK_GPIO3_A1 97
+#define RK_GPIO3_A2 98
+#define RK_GPIO3_A3 99
+#define RK_GPIO3_A4 100
+#define RK_GPIO3_A5 101
+#define RK_GPIO3_A6 102
+#define RK_GPIO3_A7 103
+#define RK_GPIO3_B0 104
+#define RK_GPIO3_B1 105
+#define RK_GPIO3_B2 106
+#define RK_GPIO3_B3 107
+#define RK_GPIO3_B4 108
+#define RK_GPIO3_B5 109
+#define RK_GPIO3_B6 110
+#define RK_GPIO3_B7 111
+#define RK_GPIO3_C0 112
+#define RK_GPIO3_C1 113
+#define RK_GPIO3_C2 114
+#define RK_GPIO3_C3 115
+#define RK_GPIO3_C4 116
+#define RK_GPIO3_C5 117
+#define RK_GPIO3_C6 118
+#define RK_GPIO3_C7 119
+#define RK_GPIO3_D0 120
+#define RK_GPIO3_D1 121
+#define RK_GPIO3_D2 122
+#define RK_GPIO3_D3 123
+#define RK_GPIO3_D4 124
+#define RK_GPIO3_D5 125
+#define RK_GPIO3_D6 126
+#define RK_GPIO3_D7 127
+
+#define RK_GPIO4_A0 128
+#define RK_GPIO4_A1 129
+#define RK_GPIO4_A2 130
+#define RK_GPIO4_A3 131
+#define RK_GPIO4_A4 132
+#define RK_GPIO4_A5 133
+#define RK_GPIO4_A6 134
+#define RK_GPIO4_A7 135
+#define RK_GPIO4_B0 136
+#define RK_GPIO4_B1 137
+#define RK_GPIO4_B2 138
+#define RK_GPIO4_B3 139
+#define RK_GPIO4_B4 140
+#define RK_GPIO4_B5 141
+#define RK_GPIO4_B6 142
+#define RK_GPIO4_B7 143
+#define RK_GPIO4_C0 144
+#define RK_GPIO4_C1 145
+#define RK_GPIO4_C2 146
+#define RK_GPIO4_C3 147
+#define RK_GPIO4_C4 148
+#define RK_GPIO4_C5 149
+#define RK_GPIO4_C6 150
+#define RK_GPIO4_C7 151
+#define RK_GPIO4_D0 152
+#define RK_GPIO4_D1 153
+#define RK_GPIO4_D2 154
+#define RK_GPIO4_D3 155
+#define RK_GPIO4_D4 156
+#define RK_GPIO4_D5 157
+#define RK_GPIO4_D6 158
+#define RK_GPIO4_D7 159
+
#define RK_GENMASK_VAL(h, l, v) \
(GENMASK(((h) + 16), ((l) + 16)) | (((v) << (l)) & GENMASK((h), (l))))
@@ -180,6 +345,25 @@ struct rockchip_pin_bank {
}, \
}
+#define PIN_BANK_IOMUX_FLAGS_PULL_FLAGS(id, pins, label, iom0, iom1, \
+ iom2, iom3, pull0, pull1, \
+ pull2, pull3) \
+ { \
+ .bank_num = id, \
+ .nr_pins = pins, \
+ .name = label, \
+ .iomux = { \
+ { .type = iom0, .offset = -1 }, \
+ { .type = iom1, .offset = -1 }, \
+ { .type = iom2, .offset = -1 }, \
+ { .type = iom3, .offset = -1 }, \
+ }, \
+ .pull_type[0] = pull0, \
+ .pull_type[1] = pull1, \
+ .pull_type[2] = pull2, \
+ .pull_type[3] = pull3, \
+ }
+
#define PIN_BANK_DRV_FLAGS_PULL_FLAGS(id, pins, label, drv0, drv1, \
drv2, drv3, pull0, pull1, \
pull2, pull3) \
@@ -274,6 +458,9 @@ struct rockchip_pin_bank {
#define MR_PMUGRF(ID, PIN, FUNC, REG, VAL) \
PIN_BANK_MUX_ROUTE_FLAGS(ID, PIN, FUNC, REG, VAL, ROUTE_TYPE_PMUGRF)
+#define RK3588_PIN_BANK_FLAGS(ID, PIN, LABEL, M, P) \
+ PIN_BANK_IOMUX_FLAGS_PULL_FLAGS(ID, PIN, LABEL, M, M, M, M, P, P, P, P)
+
/**
* struct rockchip_mux_recalced_data: recalculate a pin iomux data.
* @num: bank number.
--
2.34.1
3
2
From: Ziyuan Xu <xzy.xu(a)rock-chips.com>
Per dw_mmc databook, it's recommended to reset the host controller if
some data-related error occurred.
Implement a reset mechanism.
Signed-off-by: Ziyuan Xu <xzy.xu(a)rock-chips.com>
Co-developed-by: Jason Zhu <jason.zhu(a)rock-chips.com>
Signed-off-by: Jason Zhu <jason.zhu(a)rock-chips.com>
[eugen.hristev(a)collabora.com: modified a bit the variables initialization]
Signed-off-by: Eugen Hristev <eugen.hristev(a)collabora.com>
---
drivers/mmc/dw_mmc.c | 20 +++++++++++++++++++-
1 file changed, 19 insertions(+), 1 deletion(-)
diff --git a/drivers/mmc/dw_mmc.c b/drivers/mmc/dw_mmc.c
index 5085a3b491da..7c302ee614f4 100644
--- a/drivers/mmc/dw_mmc.c
+++ b/drivers/mmc/dw_mmc.c
@@ -138,7 +138,7 @@ static int dwmci_data_transfer(struct dwmci_host *host, struct mmc_data *data)
{
struct mmc *mmc = host->mmc;
int ret = 0;
- u32 timeout, mask, size, i, len = 0;
+ u32 timeout, reset_timeout = 100, status, ctrl, mask, size, i, len = 0;
u32 *buf = NULL;
ulong start = get_timer(0);
u32 fifo_depth = (((host->fifoth_val & RX_WMARK_MASK) >>
@@ -159,6 +159,24 @@ static int dwmci_data_transfer(struct dwmci_host *host, struct mmc_data *data)
/* Error during data transfer. */
if (mask & (DWMCI_DATA_ERR | DWMCI_DATA_TOUT)) {
debug("%s: DATA ERROR!\n", __func__);
+
+ dwmci_wait_reset(host, DWMCI_RESET_ALL);
+ dwmci_writel(host, DWMCI_CMD, DWMCI_CMD_PRV_DAT_WAIT |
+ DWMCI_CMD_UPD_CLK | DWMCI_CMD_START);
+
+ do {
+ status = dwmci_readl(host, DWMCI_CMD);
+ if (!reset_timeout)
+ break;
+ udelay(100);
+ } while (status & DWMCI_CMD_START);
+
+ if (!host->fifo_mode) {
+ ctrl = dwmci_readl(host, DWMCI_BMOD);
+ ctrl |= DWMCI_BMOD_IDMAC_RESET;
+ dwmci_writel(host, DWMCI_BMOD, ctrl);
+ }
+
ret = -EINVAL;
break;
}
--
2.34.1
3
2
From: Mikhail Lappo <mikhail.lappo(a)esrlabs.com>
Calling old U-Boot API doesn't allow to use fixed PHY.
Searching by mask is the part of new function, after
scanning FDT for a fixed PHY definition
Fixes: e821a7bdb13 ("net: ravb: Detect PHY correctly")
Reviewed-by: Marek Vasut <marek.vasut+renesas(a)mailbox.org>
Signed-off-by: Mikhail Lappo <mikhail.lappo(a)esrlabs.com>
Signed-off-by: Hai Pham <hai.pham.ud(a)renesas.com>
[Hai Pham: Drop phy_connect_dev since it's called in phy_connect]
Signed-off-by: Marek Vasut <marek.vasut+renesas(a)mailbox.org>
[Marek: Use mask -1 instead of 0 to reinstate the search behavior
over all PHY addresses. Add Fixes tag, sort the tag list.]
---
Cc: Joe Hershberger <joe.hershberger(a)ni.com>
Cc: Ramon Fried <rfried.dev(a)gmail.com>
---
drivers/net/ravb.c | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/drivers/net/ravb.c b/drivers/net/ravb.c
index 5a835cc06ff..0bc50dc7335 100644
--- a/drivers/net/ravb.c
+++ b/drivers/net/ravb.c
@@ -310,7 +310,7 @@ static int ravb_phy_config(struct udevice *dev)
struct ravb_priv *eth = dev_get_priv(dev);
struct eth_pdata *pdata = dev_get_plat(dev);
struct phy_device *phydev;
- int mask = 0xffffffff, reg;
+ int reg;
if (dm_gpio_is_valid(ð->reset_gpio)) {
dm_gpio_set_value(ð->reset_gpio, 1);
@@ -319,12 +319,10 @@ static int ravb_phy_config(struct udevice *dev)
mdelay(1);
}
- phydev = phy_find_by_mask(eth->bus, mask);
+ phydev = phy_connect(eth->bus, -1, dev, pdata->phy_interface);
if (!phydev)
return -ENODEV;
- phy_connect_dev(phydev, dev, pdata->phy_interface);
-
eth->phydev = phydev;
phydev->supported &= SUPPORTED_100baseT_Full |
--
2.39.2
2
1
This series adds ethernet support for the StarFive JH7110 RISC-V SoC.
The series includes PHY and MAC drivers. The PHY model is
YT8531 (from Motorcomm Inc), and the MAC version is dwmac-5.20
(from Synopsys DesignWare).
The implementation of the phy driver is ported from linux, but it
has been adjusted for the u-boot framework.
The PHY and MAC driver has been tested on the StarFive VisionFive 2 1.2A
and 1.3B boards and works normally.
For more information and support,you can visit RVspace wiki[1].
This patchset should be applied after the patchset [2].
[1] https://wiki.rvspace.org/
[2] https://patchwork.ozlabs.org/project/uboot/cover/20230329034224.26545-1-yanâŠ
v2:
- Reworded the phy driver. Added platform private data struct to save the
configuration data read from dts.
- Reworded the MAC driver. Added platform private data struct to save the
configuration data read from dts.
Previous versions:
v1 - https://patchwork.ozlabs.org/project/uboot/cover/20230317010536.17860-1-yanâŠ
Yanhong Wang (5):
net: phy: Add driver for Motorcomm yt8531 gigabit ethernet phy
net: dwc_eth_qos: Add StarFive ethernet driver glue layer
riscv: dts: jh7110: Add ethernet device tree nodes
riscv: dts: starfive: Add phy clock delay configuration for StarFive
VisionFive2 board
configs: starfive: Enable ethernet configuration for StarFive
VisionFive 2
.../jh7110-starfive-visionfive-2-v1.2a.dts | 13 +
.../jh7110-starfive-visionfive-2-v1.3b.dts | 27 ++
.../dts/jh7110-starfive-visionfive-2.dtsi | 34 ++
arch/riscv/dts/jh7110.dtsi | 69 +++
configs/starfive_visionfive2_12a_defconfig | 12 +-
configs/starfive_visionfive2_13b_defconfig | 12 +-
drivers/net/Kconfig | 7 +
drivers/net/Makefile | 1 +
drivers/net/dwc_eth_qos.c | 6 +
drivers/net/dwc_eth_qos.h | 1 +
drivers/net/dwc_eth_qos_starfive.c | 249 ++++++++++
drivers/net/phy/Kconfig | 6 +
drivers/net/phy/Makefile | 1 +
drivers/net/phy/motorcomm.c | 450 ++++++++++++++++++
drivers/net/phy/phy.c | 4 +-
include/phy.h | 1 +
16 files changed, 890 insertions(+), 3 deletions(-)
create mode 100644 drivers/net/dwc_eth_qos_starfive.c
create mode 100644 drivers/net/phy/motorcomm.c
base-commit: d7c2e87a0b8025314ae7dd62a8add292b7524e0b
--
2.17.1
4
8
Hi.
During 2021 summer, Sean Anderson wrote a contribution to add a new shell, based
on LIL, to U-Boot [1, 2].
While one of the goals of this contribution was to address the fact actual
U-Boot shell, which is based on Busybox hush, is old there was a discussion
about adding a new shell versus updating the actual one [3, 4].
So, in this series, with Harald Seiler, we updated the actual U-Boot shell to
reflect what is currently in Busybox source code.
Basically, this contribution is about taking a snapshot of Busybox shell/hush.c
file (as it exists in commit 37460f5da) and adapt it to suit U-Boot needs.
This contribution was written to be as backward-compatible as possible to avoid
breaking the existing.
So, the 2021 hush flavor offers the same as the actual, that is to say:
1. Variable expansion.
2. Instruction lists (;, && and ||).
3. If, then and else.
4. Loops (for, while and until).
No new features offered by Busybox hush were implemented (e.g. functions).
It is possible to change the parser at runtime using the "parser" command:
=> parser print
old
=> parser set 2021
=> parser print
2021
=> parser set old
The default parser is the old one.
Note that to use both parser, you would need to set both CONFIG_HUSH_2021_PARSER
and CONFIG_HUSH_OLD_PARSER.
In terms of testing, new unit tests were added to ut to ensure the new behavior
is the same as the old one and it does not add regression.
Nonetheless, if old behavior was buggy and fixed upstream, the fix is then added
to U-Boot [5].
In sandbox, all of these tests pass smoothly:
=> printenv board
board=sandbox
=> ut hush
Running 20 hush tests
...
Failures: 0
=> parser set 2021
=> ut hush
Running 20 hush tests
...
Failures: 0
Thanks to the effort of Harald Seiler, I was successful booting a board:
=> printenv fdtfile
fdtfile=amlogic/meson-gxl-s905x-libretech-cc.dtb
=> parser get
old
=> boot
...
root@lepotato:~#
root@lepotato:~# reboot
...
=> parser set 2021
=> parser get
2021
=> printenv fdtfile
fdtfile=amlogic/meson-gxl-s905x-libretech-cc.dtb
=> boot
...
root@lepotato:~#
I was able to have the CI passes but I had to not use CONFIG_HUSH_2021_PARSER
for the keymile board.
Indeed, the keymile board family is the only set of boards to call
get_local_var(), set_local_var() and unset_local_var().
Sadly, these functions are static in this contribution.
I could have change all of them to introduce code like this:
*_local_var(/*...*/)
{
if (gd->flags & GD_FLG_HUSH_OLD_PARSER)
return *_local_var_old(/*...*/);
if (gd->flags & GD_FLG_HUSH_2021_PARSER)
return *_local_var_2021(/*...*/);
}
But this would have mean renaming all old hush functions calls and I did not
want to change the old hush particularly to avoid breaking things.
Instead, I change the keymile board to use environment variable instead of local
ones.
I think this particularities can be addressed in future works.
I also had to enable CONFIG_LTO for kirkwoord sheevaplug and phytec bk4r1, so
they do not hit their limits.
For all these reasons, I marked this contribution as RFC to indeed collect your
opinions.
My goal is not to change suddenly actual shell to this one, we clearly need a
transition period to think about it.
I think it is better to see this contribution as a proof of concept which shows
it is possible to update the actual shell.
If you want to review it - your review will really be appreciated - here are
some information regarding the commits:
* commits marked as "test:" deal with unit tests.
* commit "cli: Add Busybox upstream hush.c file." copies Busybox shell/hush.c
into U-Boot tree, this explain why this commit contains around 12000 additions.
* commit "cli: Port Busybox 2021 hush to U-Boot." modifies previously added file
to permit us to use this as new shell.
The really good idea of #include'ing Busybox code into a wrapper file to define
some particular functions while minimizing modifications to upstream code comes
from Harald Seiler.
* commit "cmd: Add new parser command" adds a new command which permits
selecting parser at runtime.
I am not really satisfied with the fact it calls cli_init() and cli_loop() each
time the parser is set, so your reviews would be welcomed.
* Other commits focus on enabling features we need (e.g. if).
Changes since:
v2:
* Added a small fix to compile sandbox with NO_SDL=1.
* Added a command to change parser at runtime.
* Added 2021 parser function to all run_command*().
v3:
* Various bug fixes pointed by the CI.
* Added upstream busybox hush commits until 6th February 2022.
v4:
* Various cleaning.
* Modified python test to accept failure output when the test are designed to
fail.
* Bumped upstream busybox hush commits until 24h March 2022.
v5:
* Bumped upstream busybox hush commits until 30th January 2023.
* Fix how hush interprets '<' and '>', indeed we needed to escape them but I
removed this behavior as tests are handled by test command and not hush
itself. This permitted to have the ut fdt to pass.
* Fix a problem with how exit was handled. This was reported by the ut exit
test.
Francis Laniel (23):
test: Add framework to test hush behavior
test: hush: Test hush if/else
test/py: hush_if_test: Remove the test file
test: hush: Test hush variable expansion
test: hush: Test hush commands list
test: hush: Test hush loops
cli: Add Busybox upstream hush.c file
cli: Port Busybox 2021 hush to U-Boot
cli: Add menu for hush parser
global_data.h: add GD_FLG_HUSH_OLD_PARSER flag
cmd: Add new parser command
cli: Enables using hush 2021 parser as command line parser
cli: hush_2021: Enable variables expansion for hush 2021
cli: hush_2021: Add functions to be called from run_command()
cli: add hush 2021 as parser for run_command*()
test: hush: Fix instructions list tests for hush 2021
test: hush: Fix variable expansion tests for hush 2021
cli: hush_2021: Enable using < and > as string compare operators
cli: hush_2021: Enable if keyword
cli: hush_2021: Enable loops
test: hush: Fix loop tests for hush 2021
cli: hush_2021: Add upstream commits up to 30th January 2023.
DO NOT MERGE: only to make CI happy
arch/arm/lib/lib1funcs.S | 17 +
cmd/Kconfig | 22 +
cmd/Makefile | 2 +
cmd/parser.c | 125 +
common/Makefile | 3 +-
common/cli.c | 82 +-
common/cli_hush_2021.c | 306 +
common/cli_hush_upstream.c | 12969 +++++++++++++++++++++++++++
configs/bk4r1_defconfig | 1 +
configs/sheevaplug_defconfig | 1 +
include/asm-generic/global_data.h | 8 +
include/cli_hush.h | 51 +-
include/test/hush.h | 15 +
include/test/suites.h | 1 +
test/Makefile | 3 +
test/cmd_ut.c | 6 +
test/hush/Makefile | 10 +
test/hush/cmd_ut_hush.c | 20 +
test/hush/dollar.c | 226 +
test/hush/if.c | 308 +
test/hush/list.c | 140 +
test/hush/loop.c | 91 +
test/py/tests/test_hush_if_test.py | 184 -
test/py/tests/test_ut.py | 8 +-
24 files changed, 14400 insertions(+), 199 deletions(-)
create mode 100644 cmd/parser.c
create mode 100644 common/cli_hush_2021.c
create mode 100644 common/cli_hush_upstream.c
create mode 100644 include/test/hush.h
create mode 100644 test/hush/Makefile
create mode 100644 test/hush/cmd_ut_hush.c
create mode 100644 test/hush/dollar.c
create mode 100644 test/hush/if.c
create mode 100644 test/hush/list.c
create mode 100644 test/hush/loop.c
delete mode 100644 test/py/tests/test_hush_if_test.py
Best regards and thank you in advance.
--
2.34.1
3
36
These struct phy_driver ... instances are local to this source code
file, staticize them. No functional change.
Signed-off-by: Marek Vasut <marek.vasut+renesas(a)mailbox.org>
---
Cc: "Ariel D'Alessandro" <ariel.dalessandro(a)collabora.com>
Cc: "Cédric Le Goater" <clg(a)kaod.org>
Cc: "Marek BehĂșn" <kabel(a)kernel.org>
Cc: Alex Nemirovsky <alex.nemirovsky(a)cortina-access.com>
Cc: Haolin Li <li.haolin(a)qq.com>
Cc: Heinrich Schuchardt <xypron.glpk(a)gmx.de>
Cc: Joe Hershberger <joe.hershberger(a)ni.com>
Cc: Joel Stanley <joel(a)jms.id.au>
Cc: Josua Mayer <josua(a)solid-run.com>
Cc: Marek Vasut <marek.vasut+renesas(a)mailbox.org>
Cc: Michael Trimarchi <michael(a)amarulasolutions.com>
Cc: Michal Simek <michal.simek(a)amd.com>
Cc: Nate Drude <nate.d(a)variscite.com>
Cc: Neil Armstrong <neil.armstrong(a)linaro.org>
Cc: Radu Pirea <radu-nicolae.pirea(a)oss.nxp.com>
Cc: Ramon Fried <rfried.dev(a)gmail.com>
Cc: Samuel Mendoza-Jonas <sam(a)mendozajonas.com>
Cc: Stefan Roese <sr(a)denx.de>
Cc: T Karthik Reddy <t.karthik.reddy(a)xilinx.com>
Cc: Tim Harvey <tharvey(a)gateworks.com>
Cc: Vladimir Oltean <vladimir.oltean(a)nxp.com>
Cc: u-boot-amlogic(a)groups.io
---
drivers/net/phy/aquantia.c | 18 +++++++++---------
1 file changed, 9 insertions(+), 9 deletions(-)
diff --git a/drivers/net/phy/aquantia.c b/drivers/net/phy/aquantia.c
index 8eb6024829d..fa887ade0c2 100644
--- a/drivers/net/phy/aquantia.c
+++ b/drivers/net/phy/aquantia.c
@@ -598,7 +598,7 @@ int aquantia_startup(struct phy_device *phydev)
return 0;
}
-struct phy_driver aq1202_driver = {
+static struct phy_driver aq1202_driver = {
.name = "Aquantia AQ1202",
.uid = 0x3a1b445,
.mask = 0xfffffff0,
@@ -611,7 +611,7 @@ struct phy_driver aq1202_driver = {
.shutdown = &gen10g_shutdown,
};
-struct phy_driver aq2104_driver = {
+static struct phy_driver aq2104_driver = {
.name = "Aquantia AQ2104",
.uid = 0x3a1b460,
.mask = 0xfffffff0,
@@ -624,7 +624,7 @@ struct phy_driver aq2104_driver = {
.shutdown = &gen10g_shutdown,
};
-struct phy_driver aqr105_driver = {
+static struct phy_driver aqr105_driver = {
.name = "Aquantia AQR105",
.uid = 0x3a1b4a2,
.mask = 0xfffffff0,
@@ -638,7 +638,7 @@ struct phy_driver aqr105_driver = {
.data = AQUANTIA_GEN1,
};
-struct phy_driver aqr106_driver = {
+static struct phy_driver aqr106_driver = {
.name = "Aquantia AQR106",
.uid = 0x3a1b4d0,
.mask = 0xfffffff0,
@@ -651,7 +651,7 @@ struct phy_driver aqr106_driver = {
.shutdown = &gen10g_shutdown,
};
-struct phy_driver aqr107_driver = {
+static struct phy_driver aqr107_driver = {
.name = "Aquantia AQR107",
.uid = 0x3a1b4e0,
.mask = 0xfffffff0,
@@ -665,7 +665,7 @@ struct phy_driver aqr107_driver = {
.data = AQUANTIA_GEN2,
};
-struct phy_driver aqr112_driver = {
+static struct phy_driver aqr112_driver = {
.name = "Aquantia AQR112",
.uid = 0x3a1b660,
.mask = 0xfffffff0,
@@ -679,7 +679,7 @@ struct phy_driver aqr112_driver = {
.data = AQUANTIA_GEN3,
};
-struct phy_driver aqr113c_driver = {
+static struct phy_driver aqr113c_driver = {
.name = "Aquantia AQR113C",
.uid = 0x31c31c12,
.mask = 0xfffffff0,
@@ -693,7 +693,7 @@ struct phy_driver aqr113c_driver = {
.data = AQUANTIA_GEN3,
};
-struct phy_driver aqr405_driver = {
+static struct phy_driver aqr405_driver = {
.name = "Aquantia AQR405",
.uid = 0x3a1b4b2,
.mask = 0xfffffff0,
@@ -707,7 +707,7 @@ struct phy_driver aqr405_driver = {
.data = AQUANTIA_GEN1,
};
-struct phy_driver aqr412_driver = {
+static struct phy_driver aqr412_driver = {
.name = "Aquantia AQR412",
.uid = 0x3a1b710,
.mask = 0xfffffff0,
--
2.39.2
4
55

01 Apr '23
This mode does not seem to be well defined and used anywhere, remove support for it.
Based on discussion:
- 1000baseX does c37 AN of duplex+pause
- SGMII does AN of duplex+pause+speed, at lower speed bytes are repeated 10x/100x
- 2500baseX does not do AN, or does very different c73 AN
- SGMII 2500 behavior is unclear
Signed-off-by: Marek Vasut <marek.vasut+renesas(a)mailbox.org>
---
Cc: "Ariel D'Alessandro" <ariel.dalessandro(a)collabora.com>
Cc: "Marek BehĂșn" <kabel(a)kernel.org>
Cc: Joe Hershberger <joe.hershberger(a)ni.com>
Cc: Marek Vasut <marek.vasut+renesas(a)mailbox.org>
Cc: Ramon Fried <rfried.dev(a)gmail.com>
Cc: Stefan Roese <sr(a)denx.de>
Cc: Tim Harvey <tharvey(a)gateworks.com>
Cc: Vladimir Oltean <vladimir.oltean(a)nxp.com>
---
V2: Drop SGMII 2500 support, if it becomes required and/or standardized,
this patch can be reverted
---
drivers/net/mvpp2.c | 53 ---------------------------------------------
1 file changed, 53 deletions(-)
diff --git a/drivers/net/mvpp2.c b/drivers/net/mvpp2.c
index 1bad50d344c..c99d52c85d7 100644
--- a/drivers/net/mvpp2.c
+++ b/drivers/net/mvpp2.c
@@ -2871,7 +2871,6 @@ static void mvpp2_port_mii_set(struct mvpp2_port *port)
switch (port->phy_interface) {
case PHY_INTERFACE_MODE_SGMII:
- case PHY_INTERFACE_MODE_SGMII_2500:
val |= MVPP2_GMAC_INBAND_AN_MASK;
break;
case PHY_INTERFACE_MODE_1000BASEX:
@@ -2939,7 +2938,6 @@ static void mvpp2_port_loopback_set(struct mvpp2_port *port)
val &= ~MVPP2_GMAC_GMII_LB_EN_MASK;
if (port->phy_interface == PHY_INTERFACE_MODE_SGMII ||
- port->phy_interface == PHY_INTERFACE_MODE_SGMII_2500 ||
port->phy_interface == PHY_INTERFACE_MODE_1000BASEX ||
port->phy_interface == PHY_INTERFACE_MODE_2500BASEX)
val |= MVPP2_GMAC_PCS_LB_EN_MASK;
@@ -3027,48 +3025,6 @@ static int gop_bypass_clk_cfg(struct mvpp2_port *port, int en)
return 0;
}
-static void gop_gmac_sgmii2_5_cfg(struct mvpp2_port *port)
-{
- u32 val, thresh;
-
- /*
- * Configure minimal level of the Tx FIFO before the lower part
- * starts to read a packet
- */
- thresh = MVPP2_SGMII2_5_TX_FIFO_MIN_TH;
- val = readl(port->base + MVPP2_GMAC_PORT_FIFO_CFG_1_REG);
- val &= ~MVPP2_GMAC_TX_FIFO_MIN_TH_ALL_MASK;
- val |= MVPP2_GMAC_TX_FIFO_MIN_TH_MASK(thresh);
- writel(val, port->base + MVPP2_GMAC_PORT_FIFO_CFG_1_REG);
-
- /* Disable bypass of sync module */
- val = readl(port->base + MVPP2_GMAC_CTRL_4_REG);
- val |= MVPP2_GMAC_CTRL4_SYNC_BYPASS_MASK;
- /* configure DP clock select according to mode */
- val |= MVPP2_GMAC_CTRL4_DP_CLK_SEL_MASK;
- /* configure QSGMII bypass according to mode */
- val |= MVPP2_GMAC_CTRL4_QSGMII_BYPASS_ACTIVE_MASK;
- writel(val, port->base + MVPP2_GMAC_CTRL_4_REG);
-
- val = readl(port->base + MVPP2_GMAC_CTRL_0_REG);
- /*
- * Configure GIG MAC to SGMII mode connected to a fiber
- * transceiver
- */
- val &= ~MVPP2_GMAC_PORT_TYPE_MASK;
- writel(val, port->base + MVPP2_GMAC_CTRL_0_REG);
-
- /* configure AN 0x9268 */
- val = MVPP2_GMAC_EN_PCS_AN |
- MVPP2_GMAC_AN_BYPASS_EN |
- MVPP2_GMAC_CONFIG_MII_SPEED |
- MVPP2_GMAC_CONFIG_GMII_SPEED |
- MVPP2_GMAC_FC_ADV_EN |
- MVPP2_GMAC_CONFIG_FULL_DUPLEX |
- MVPP2_GMAC_CHOOSE_SAMPLE_TX_CONFIG;
- writel(val, port->base + MVPP2_GMAC_AUTONEG_CONFIG);
-}
-
static void gop_gmac_sgmii_cfg(struct mvpp2_port *port)
{
u32 val, thresh;
@@ -3239,9 +3195,6 @@ static int gop_gmac_mode_cfg(struct mvpp2_port *port)
case PHY_INTERFACE_MODE_SGMII:
gop_gmac_sgmii_cfg(port);
break;
- case PHY_INTERFACE_MODE_SGMII_2500:
- gop_gmac_sgmii2_5_cfg(port);
- break;
case PHY_INTERFACE_MODE_1000BASEX:
gop_gmac_1000basex_cfg(port);
break;
@@ -3422,7 +3375,6 @@ static int gop_port_init(struct mvpp2_port *port)
break;
case PHY_INTERFACE_MODE_SGMII:
- case PHY_INTERFACE_MODE_SGMII_2500:
case PHY_INTERFACE_MODE_1000BASEX:
case PHY_INTERFACE_MODE_2500BASEX:
/* configure PCS */
@@ -3482,7 +3434,6 @@ static void gop_port_enable(struct mvpp2_port *port, int enable)
case PHY_INTERFACE_MODE_RGMII:
case PHY_INTERFACE_MODE_RGMII_ID:
case PHY_INTERFACE_MODE_SGMII:
- case PHY_INTERFACE_MODE_SGMII_2500:
case PHY_INTERFACE_MODE_1000BASEX:
case PHY_INTERFACE_MODE_2500BASEX:
if (enable)
@@ -3519,7 +3470,6 @@ static u32 mvpp2_netc_cfg_create(int gop_id, phy_interface_t phy_type)
if (gop_id == 2) {
if (phy_type == PHY_INTERFACE_MODE_SGMII ||
- phy_type == PHY_INTERFACE_MODE_SGMII_2500 ||
phy_type == PHY_INTERFACE_MODE_1000BASEX ||
phy_type == PHY_INTERFACE_MODE_2500BASEX)
val |= MV_NETC_GE_MAC2_SGMII;
@@ -3530,7 +3480,6 @@ static u32 mvpp2_netc_cfg_create(int gop_id, phy_interface_t phy_type)
if (gop_id == 3) {
if (phy_type == PHY_INTERFACE_MODE_SGMII ||
- phy_type == PHY_INTERFACE_MODE_SGMII_2500 ||
phy_type == PHY_INTERFACE_MODE_1000BASEX ||
phy_type == PHY_INTERFACE_MODE_2500BASEX)
val |= MV_NETC_GE_MAC3_SGMII;
@@ -4529,7 +4478,6 @@ static void mvpp2_start_dev(struct mvpp2_port *port)
case PHY_INTERFACE_MODE_RGMII:
case PHY_INTERFACE_MODE_RGMII_ID:
case PHY_INTERFACE_MODE_SGMII:
- case PHY_INTERFACE_MODE_SGMII_2500:
case PHY_INTERFACE_MODE_1000BASEX:
case PHY_INTERFACE_MODE_2500BASEX:
mvpp2_gmac_max_rx_size_set(port);
@@ -5263,7 +5211,6 @@ static int mvpp2_start(struct udevice *dev)
case PHY_INTERFACE_MODE_RGMII:
case PHY_INTERFACE_MODE_RGMII_ID:
case PHY_INTERFACE_MODE_SGMII:
- case PHY_INTERFACE_MODE_SGMII_2500:
case PHY_INTERFACE_MODE_1000BASEX:
case PHY_INTERFACE_MODE_2500BASEX:
mvpp2_port_power_up(port);
--
2.39.2
2
5
From: Phong Hoang <phong.hoang.wz(a)renesas.com>
This patch adds Ethernet Switch support that found on R-Car S4
(r8a779f0) SoC. This is extracted from multiple patches from
downstream BSP, with additional rework of the network device
registration.
Signed-off-by: Hai Pham <hai.pham.ud(a)renesas.com>
Signed-off-by: Marek Vasut <marek.vasut+renesas(a)mailbox.org>
Signed-off-by: Phong Hoang <phong.hoang.wz(a)renesas.com>
Signed-off-by: Takeshi Kihara <takeshi.kihara.df(a)renesas.com>
[Marek: Rework the driver to support all ports via subdrivers.
Split the driver up, add generic PHY framework support.
Generic code clean ups.]
---
Cc: Hai Pham <hai.pham.ud(a)renesas.com>
Cc: Joe Hershberger <joe.hershberger(a)ni.com>
Cc: Marek Vasut <marek.vasut+renesas(a)mailbox.org>
Cc: Peng Fan <peng.fan(a)nxp.com>
Cc: Ramon Fried <rfried.dev(a)gmail.com>
Cc: Simon Glass <sjg(a)chromium.org>
---
drivers/net/Kconfig | 8 +
drivers/net/Makefile | 1 +
drivers/net/rswitch.c | 1139 +++++++++++++++++++++++++++++++++++++++++
3 files changed, 1148 insertions(+)
create mode 100644 drivers/net/rswitch.c
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 5c29e63d0be..09039a283eb 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -752,6 +752,14 @@ config GMAC_ROCKCHIP
This driver provides Rockchip SoCs network support based on the
Synopsys Designware driver.
+config RENESAS_ETHER_SWITCH
+ bool "Renesas Ethernet Switch support"
+ depends on DM_ETH && R8A779F0
+ select PHYLIB
+ help
+ This driver implements support for the Renesas Ethernet Switch
+ which is available on R-Car S4 SoC (r8a779f0).
+
config RENESAS_RAVB
bool "Renesas Ethernet AVB MAC"
depends on RCAR_64
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index 75daa5e694c..46a40e2ed9f 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -76,6 +76,7 @@ obj-$(CONFIG_OCTEONTX_SMI) += octeontx/smi.o
obj-$(CONFIG_PCH_GBE) += pch_gbe.o
obj-$(CONFIG_PCNET) += pcnet.o
obj-$(CONFIG_PIC32_ETH) += pic32_mdio.o pic32_eth.o
+obj-$(CONFIG_RENESAS_ETHER_SWITCH) += rswitch.o
obj-$(CONFIG_RENESAS_RAVB) += ravb.o
obj-$(CONFIG_RTL8139) += rtl8139.o
obj-$(CONFIG_RTL8169) += rtl8169.o
diff --git a/drivers/net/rswitch.c b/drivers/net/rswitch.c
new file mode 100644
index 00000000000..5a69ca1a0f9
--- /dev/null
+++ b/drivers/net/rswitch.c
@@ -0,0 +1,1139 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Driver for Renesas Ethernet RSwitch2 (Ethernet-TSN).
+ *
+ * Copyright (C) 2021 Renesas Electronics Corporation
+ *
+ * Based on the Renesas Ethernet AVB driver.
+ */
+
+#include <asm/io.h>
+#include <clk.h>
+#include <common.h>
+#include <dm.h>
+#include <dm/device-internal.h>
+#include <dm/device_compat.h>
+#include <dm/lists.h>
+#include <errno.h>
+#include <generic-phy.h>
+#include <linux/bitops.h>
+#include <linux/delay.h>
+#include <linux/iopoll.h>
+#include <linux/mii.h>
+#include <eth_phy.h>
+#include <log.h>
+#include <malloc.h>
+#include <miiphy.h>
+
+#define RSWITCH_SLEEP_US 1000
+#define RSWITCH_TIMEOUT_US 1000000
+
+#define RSWITCH_NUM_HW 5
+
+#define ETHA_TO_GWCA(i) ((i) % 2)
+#define GWCA_TO_HW_INDEX(i) ((i) + 3)
+#define HW_INDEX_TO_GWCA(i) ((i) - 3)
+
+#define RSWITCH_MAX_CTAG_PCP 7
+
+/* Registers */
+#define RSWITCH_COMA_OFFSET 0x00009000
+#define RSWITCH_ETHA_OFFSET 0x0000a000 /* with RMAC */
+#define RSWITCH_ETHA_SIZE 0x00002000 /* with RMAC */
+#define RSWITCH_GWCA_OFFSET 0x00010000
+#define RSWITCH_GWCA_SIZE 0x00002000
+
+#define FWRO 0
+#define CARO RSWITCH_COMA_OFFSET
+#define GWRO 0
+#define TARO 0
+#define RMRO 0x1000
+
+enum rswitch_reg {
+ EAMC = TARO + 0x0000,
+ EAMS = TARO + 0x0004,
+ EATDQDC = TARO + 0x0060,
+ EATTFC = TARO + 0x0138,
+ EATASRIRM = TARO + 0x03E4,
+
+ GWMC = GWRO + 0x0000,
+ GWMS = GWRO + 0x0004,
+ GWMTIRM = GWRO + 0x0100,
+ GWVCC = GWRO + 0x0130,
+ GWTTFC = GWRO + 0x0138,
+ GWDCBAC0 = GWRO + 0x0194,
+ GWDCBAC1 = GWRO + 0x0198,
+ GWTRC = GWRO + 0x0200,
+ GWARIRM = GWRO + 0x0380,
+ GWDCC = GWRO + 0x0400,
+
+ RRC = CARO + 0x0004,
+ RCEC = CARO + 0x0008,
+ RCDC = CARO + 0x000C,
+ CABPIRM = CARO + 0x0140,
+
+ FWPC0 = FWRO + 0x0100,
+ FWPBFC = FWRO + 0x4A00,
+ FWPBFCSDC = FWRO + 0x4A04,
+
+ MPSM = RMRO + 0x0000,
+ MPIC = RMRO + 0x0004,
+ MRMAC0 = RMRO + 0x0084,
+ MRMAC1 = RMRO + 0x0088,
+ MRAFC = RMRO + 0x008C,
+ MRSCE = RMRO + 0x0090,
+ MRSCP = RMRO + 0x0094,
+ MLVC = RMRO + 0x0180,
+ MLBC = RMRO + 0x0188,
+ MXGMIIC = RMRO + 0x0190,
+ MPCH = RMRO + 0x0194,
+ MANM = RMRO + 0x019C,
+ MMIS0 = RMRO + 0x0210,
+ MMIS1 = RMRO + 0x0220,
+};
+
+/* COMA */
+#define RRC_RR BIT(0)
+#define RCEC_RCE BIT(16)
+
+#define CABPIRM_BPIOG BIT(0)
+#define CABPIRM_BPR BIT(1)
+
+/* MFWD */
+#define FWPC0(i) (FWPC0 + (i) * 0x10)
+#define FWPC0_LTHTA BIT(0)
+#define FWPC0_IP4UE BIT(3)
+#define FWPC0_IP4TE BIT(4)
+#define FWPC0_IP4OE BIT(5)
+#define FWPC0_L2SE BIT(9)
+#define FWPC0_IP4EA BIT(10)
+#define FWPC0_IPDSA BIT(12)
+#define FWPC0_IPHLA BIT(18)
+#define FWPC0_MACSDA BIT(20)
+#define FWPC0_MACHLA BIT(26)
+#define FWPC0_MACHMA BIT(27)
+#define FWPC0_VLANSA BIT(28)
+
+#define FWPC0_DEFAULT (FWPC0_LTHTA | FWPC0_IP4UE | FWPC0_IP4TE | \
+ FWPC0_IP4OE | FWPC0_L2SE | FWPC0_IP4EA | \
+ FWPC0_IPDSA | FWPC0_IPHLA | FWPC0_MACSDA | \
+ FWPC0_MACHLA | FWPC0_MACHMA | FWPC0_VLANSA)
+
+#define FWPBFC(i) (FWPBFC + (i) * 0x10)
+#define FWPBFCSDC(j, i) (FWPBFCSDC + (i) * 0x10 + (j) * 0x04)
+
+/* ETHA */
+#define EATASRIRM_TASRIOG BIT(0)
+#define EATASRIRM_TASRR BIT(1)
+#define EATDQDC(q) (EATDQDC + (q) * 0x04)
+#define EATDQDC_DQD (0xff)
+
+/* RMAC */
+#define MPIC_PIS_GMII 0x02
+#define MPIC_LSC_MASK (0x07 << 3)
+#define MPIC_LSC_100 (0x01 << 3)
+#define MPIC_LSC_1000 (0x02 << 3)
+#define MPIC_LSC_2500 (0x03 << 3)
+#define MLVC_PLV BIT(16)
+#define MLVC_LVT 0x09
+#define MMIS0_LVSS 0x02
+
+#define MPIC_PSMCS_MASK (0x7f << 16)
+#define MPIC_PSMHT_MASK (0x06 << 24)
+#define MPIC_MDC_CLK_SET (0x06050000)
+
+#define MPSM_MFF_C45 BIT(2)
+#define MPSM_MFF_C22 0x0
+#define MPSM_PSME BIT(0)
+
+#define MDIO_READ_C45 0x03
+#define MDIO_WRITE_C45 0x01
+#define MDIO_ADDR_C45 0x00
+
+#define MDIO_READ_C22 0x02
+#define MDIO_WRITE_C22 0x01
+
+#define MPSM_POP_MASK (0x03 << 13)
+#define MPSM_PRA_MASK (0x1f << 8)
+#define MPSM_PDA_MASK (0x1f << 3)
+#define MPSM_PRD_MASK (0xffff << 16)
+
+/* Completion flags */
+#define MMIS1_PAACS BIT(2) /* Address */
+#define MMIS1_PWACS BIT(1) /* Write */
+#define MMIS1_PRACS BIT(0) /* Read */
+#define MMIS1_CLEAR_FLAGS 0xf
+
+/* ETHA */
+enum rswitch_etha_mode {
+ EAMC_OPC_RESET,
+ EAMC_OPC_DISABLE,
+ EAMC_OPC_CONFIG,
+ EAMC_OPC_OPERATION,
+};
+
+#define EAMS_OPS_MASK EAMC_OPC_OPERATION
+
+/* GWCA */
+enum rswitch_gwca_mode {
+ GWMC_OPC_RESET,
+ GWMC_OPC_DISABLE,
+ GWMC_OPC_CONFIG,
+ GWMC_OPC_OPERATION,
+};
+
+#define GWMS_OPS_MASK GWMC_OPC_OPERATION
+
+#define GWMTIRM_MTIOG BIT(0)
+#define GWMTIRM_MTR BIT(1)
+#define GWARIRM_ARIOG BIT(0)
+#define GWARIRM_ARR BIT(1)
+#define GWVCC_VEM_SC_TAG (0x3 << 16)
+#define GWDCBAC0_DCBAUP (0xff)
+#define GWTRC(i) (GWTRC + (i) * 0x04)
+#define GWDCC(i) (GWDCC + (i) * 0x04)
+#define GWDCC_DQT BIT(11)
+#define GWDCC_BALR BIT(24)
+
+struct rswitch_etha {
+ int index;
+ void __iomem *addr;
+ struct phy_device *phydev;
+ struct mii_dev *bus;
+ unsigned char *enetaddr;
+};
+
+struct rswitch_gwca {
+ int index;
+ void __iomem *addr;
+ int num_chain;
+};
+
+/* Setting value */
+#define LINK_SPEED_100 100
+#define LINK_SPEED_1000 1000
+#define LINK_SPEED_2500 2500
+
+/* Decriptor */
+#define RSWITCH_NUM_BASE_DESC 2
+#define RSWITCH_TX_CHAIN_INDEX 0
+#define RSWITCH_RX_CHAIN_INDEX 1
+#define RSWITCH_NUM_TX_DESC 8
+#define RSWITCH_NUM_RX_DESC 8
+
+enum RX_DS_CC_BIT {
+ RX_DS = 0x0fff, /* Data size */
+ RX_TR = 0x1000, /* Truncation indication */
+ RX_EI = 0x2000, /* Error indication */
+ RX_PS = 0xc000, /* Padding selection */
+};
+
+enum DIE_DT {
+ /* Frame data */
+ DT_FSINGLE = 0x80,
+ DT_FSTART = 0x90,
+ DT_FMID = 0xa0,
+ DT_FEND = 0xb8,
+
+ /* Chain control */
+ DT_LEMPTY = 0xc0,
+ DT_EEMPTY = 0xd0,
+ DT_LINKFIX = 0x00,
+ DT_LINK = 0xe0,
+ DT_EOS = 0xf0,
+ /* HW/SW arbitration */
+ DT_FEMPTY = 0x40,
+ DT_FEMPTY_IS = 0x10,
+ DT_FEMPTY_IC = 0x20,
+ DT_FEMPTY_ND = 0x38,
+ DT_FEMPTY_START = 0x50,
+ DT_FEMPTY_MID = 0x60,
+ DT_FEMPTY_END = 0x70,
+
+ DT_MASK = 0xf0,
+ DIE = 0x08, /* Descriptor Interrupt Enable */
+};
+
+struct rswitch_desc {
+ __le16 info_ds; /* Descriptor size */
+ u8 die_dt; /* Descriptor interrupt enable and type */
+ __u8 dptrh; /* Descriptor pointer MSB */
+ __le32 dptrl; /* Descriptor pointer LSW */
+} __packed;
+
+struct rswitch_rxdesc {
+ struct rswitch_desc data;
+ struct rswitch_desc link;
+ u8 __pad[48];
+ u8 packet[PKTSIZE_ALIGN];
+} __packed;
+
+struct rswitch_port_priv {
+ void __iomem *addr;
+ struct phy serdes;
+ struct rswitch_etha etha;
+ struct rswitch_gwca gwca;
+ struct rswitch_desc bat_desc[RSWITCH_NUM_BASE_DESC];
+ struct rswitch_desc tx_desc[RSWITCH_NUM_TX_DESC];
+ struct rswitch_rxdesc rx_desc[RSWITCH_NUM_RX_DESC];
+ u32 rx_desc_index;
+ u32 tx_desc_index;
+};
+
+struct rswitch_priv {
+ void __iomem *addr;
+ struct clk *rsw_clk;
+};
+
+static inline void rswitch_flush_dcache(u32 addr, u32 len)
+{
+ flush_dcache_range(addr, addr + len);
+}
+
+static inline void rswitch_invalidate_dcache(u32 addr, u32 len)
+{
+ u32 start = addr & ~((uintptr_t)ARCH_DMA_MINALIGN - 1);
+ u32 end = roundup(addr + len, ARCH_DMA_MINALIGN);
+
+ invalidate_dcache_range(start, end);
+}
+
+static void rswitch_agent_clock_ctrl(struct rswitch_port_priv *priv, int port, int enable)
+{
+ u32 val;
+
+ if (enable) {
+ val = readl(priv->addr + RCEC);
+ if ((val & (RCEC_RCE | BIT(port))) != (RCEC_RCE | BIT(port)))
+ writel(val | RCEC_RCE | BIT(port), priv->addr + RCEC);
+ } else {
+ setbits_le32(priv->addr + RCDC, BIT(port));
+ }
+}
+
+static int rswitch_etha_change_mode(struct rswitch_port_priv *priv,
+ enum rswitch_etha_mode mode)
+{
+ struct rswitch_etha *etha = &priv->etha;
+ u32 pval;
+ int ret;
+
+ /* Enable clock */
+ rswitch_agent_clock_ctrl(priv, etha->index, 1);
+
+ writel(mode, etha->addr + EAMC);
+
+ ret = readl_poll_sleep_timeout(etha->addr + EAMS, pval,
+ (pval & EAMS_OPS_MASK) == mode,
+ RSWITCH_SLEEP_US, RSWITCH_TIMEOUT_US);
+
+ /* Disable clock */
+ if (mode == EAMC_OPC_DISABLE)
+ rswitch_agent_clock_ctrl(priv, etha->index, 0);
+
+ return ret;
+}
+
+static int rswitch_gwca_change_mode(struct rswitch_port_priv *priv,
+ enum rswitch_gwca_mode mode)
+{
+ struct rswitch_gwca *gwca = &priv->gwca;
+ u32 pval;
+ int ret;
+
+ /* Enable clock */
+ rswitch_agent_clock_ctrl(priv, gwca->index, 1);
+
+ writel(mode, gwca->addr + GWMC);
+
+ ret = readl_poll_sleep_timeout(gwca->addr + GWMS, pval,
+ (pval & GWMS_OPS_MASK) == mode,
+ RSWITCH_SLEEP_US, RSWITCH_TIMEOUT_US);
+
+ /* Disable clock */
+ if (mode == GWMC_OPC_DISABLE)
+ rswitch_agent_clock_ctrl(priv, gwca->index, 0);
+
+ return ret;
+}
+
+static int rswitch_mii_access_c45(struct rswitch_etha *etha, bool read,
+ int phyad, int devad, int regad, int data)
+{
+ u32 pval, val;
+ int ret;
+
+ /* No match device */
+ if (devad == 0xffffffff)
+ return 0;
+
+ /* Clear completion flags */
+ writel(MMIS1_CLEAR_FLAGS, etha->addr + MMIS1);
+
+ /* Submit address to PHY (MDIO_ADDR_C45 << 13) */
+ val = MPSM_PSME | MPSM_MFF_C45 | (devad << 8) | (phyad << 3);
+ writel((regad << 16) | val, etha->addr + MPSM);
+
+ ret = readl_poll_sleep_timeout(etha->addr + MMIS1, pval,
+ pval & MMIS1_PAACS,
+ RSWITCH_SLEEP_US, RSWITCH_TIMEOUT_US);
+ if (ret)
+ return ret;
+
+ /* Clear address completion flag */
+ setbits_le32(etha->addr + MMIS1, MMIS1_PAACS);
+
+ /* Read/Write PHY register */
+ if (read) {
+ val |= MDIO_READ_C45 << 13;
+ writel(val, etha->addr + MPSM);
+
+ ret = readl_poll_sleep_timeout(etha->addr + MMIS1, pval,
+ pval & MMIS1_PRACS,
+ RSWITCH_SLEEP_US,
+ RSWITCH_TIMEOUT_US);
+ if (ret)
+ return ret;
+
+ /* Read data */
+ ret = (readl(etha->addr + MPSM) & MPSM_PRD_MASK) >> 16;
+
+ /* Clear read completion flag */
+ setbits_le32(etha->addr + MMIS1, MMIS1_PRACS);
+ } else {
+ val |= MDIO_WRITE_C45 << 13;
+ val |= data << 16;
+ writel(val, etha->addr + MPSM);
+
+ ret = readl_poll_sleep_timeout(etha->addr + MMIS1, pval,
+ pval & MMIS1_PWACS,
+ RSWITCH_SLEEP_US,
+ RSWITCH_TIMEOUT_US);
+ }
+
+ return ret;
+}
+
+static int rswitch_mii_read_c45(struct mii_dev *miidev, int phyad, int devad, int regad)
+{
+ struct rswitch_port_priv *priv = miidev->priv;
+ struct rswitch_etha *etha = &priv->etha;
+ int val;
+ int reg;
+
+ /* Change to disable mode */
+ rswitch_etha_change_mode(priv, EAMC_OPC_DISABLE);
+
+ /* Change to config mode */
+ rswitch_etha_change_mode(priv, EAMC_OPC_CONFIG);
+
+ /* Enable Station Management clock */
+ reg = readl(etha->addr + MPIC);
+ reg &= ~MPIC_PSMCS_MASK & ~MPIC_PSMHT_MASK;
+ writel(reg | MPIC_MDC_CLK_SET, etha->addr + MPIC);
+
+ /* Set Station Management Mode : Clause 45 */
+ setbits_le32(etha->addr + MPSM, MPSM_MFF_C45);
+
+ /* Access PHY register */
+ val = rswitch_mii_access_c45(etha, true, phyad, devad, regad, 0);
+
+ /* Disable Station Management Clock */
+ clrbits_le32(etha->addr + MPIC, MPIC_PSMCS_MASK);
+
+ /* Change to disable mode */
+ rswitch_etha_change_mode(priv, EAMC_OPC_DISABLE);
+
+ return val;
+}
+
+int rswitch_mii_write_c45(struct mii_dev *miidev, int phyad, int devad, int regad, u16 data)
+{
+ struct rswitch_port_priv *priv = miidev->priv;
+ struct rswitch_etha *etha = &priv->etha;
+ int reg;
+
+ /* Change to disable mode */
+ rswitch_etha_change_mode(priv, EAMC_OPC_DISABLE);
+
+ /* Change to config mode */
+ rswitch_etha_change_mode(priv, EAMC_OPC_CONFIG);
+
+ /* Enable Station Management clock */
+ reg = readl(etha->addr + MPIC);
+ reg &= ~MPIC_PSMCS_MASK & ~MPIC_PSMHT_MASK;
+ writel(reg | MPIC_MDC_CLK_SET, etha->addr + MPIC);
+
+ /* Set Station Management Mode : Clause 45 */
+ setbits_le32(etha->addr + MPSM, MPSM_MFF_C45);
+
+ /* Access PHY register */
+ rswitch_mii_access_c45(etha, false, phyad, devad, regad, data);
+
+ /* Disable Station Management Clock */
+ clrbits_le32(etha->addr + MPIC, MPIC_PSMCS_MASK);
+
+ /* Change to disable mode */
+ rswitch_etha_change_mode(priv, EAMC_OPC_DISABLE);
+
+ return 0;
+}
+
+static int rswitch_check_link(struct rswitch_etha *etha)
+{
+ u32 pval;
+ int ret;
+
+ /* Request Link Verification */
+ writel(MLVC_PLV, etha->addr + MLVC);
+
+ /* Complete Link Verification */
+ ret = readl_poll_sleep_timeout(etha->addr + MLVC, pval,
+ !(pval & MLVC_PLV),
+ RSWITCH_SLEEP_US, RSWITCH_TIMEOUT_US);
+ if (ret) {
+ debug("\n%s: Link verification timeout!", __func__);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int rswitch_reset(struct rswitch_port_priv *priv)
+{
+ int ret;
+
+ setbits_le32(priv->addr + RRC, RRC_RR);
+ clrbits_le32(priv->addr + RRC, RRC_RR);
+
+ ret = rswitch_gwca_change_mode(priv, GWMC_OPC_DISABLE);
+ if (ret)
+ return ret;
+
+ ret = rswitch_etha_change_mode(priv, EAMC_OPC_DISABLE);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static void rswitch_bat_desc_init(struct rswitch_port_priv *priv)
+{
+ const u32 desc_size = RSWITCH_NUM_BASE_DESC * sizeof(struct rswitch_desc);
+ int i;
+
+ /* Initialize all descriptors */
+ memset(priv->bat_desc, 0x0, desc_size);
+
+ for (i = 0; i < RSWITCH_NUM_BASE_DESC; i++)
+ priv->bat_desc[i].die_dt = DT_EOS;
+
+ rswitch_flush_dcache((uintptr_t)priv->bat_desc, desc_size);
+}
+
+static void rswitch_tx_desc_init(struct rswitch_port_priv *priv)
+{
+ const u32 desc_size = RSWITCH_NUM_TX_DESC * sizeof(struct rswitch_desc);
+ u64 tx_desc_addr;
+ int i;
+
+ /* Initialize all descriptor */
+ memset(priv->tx_desc, 0x0, desc_size);
+ priv->tx_desc_index = 0;
+
+ for (i = 0; i < RSWITCH_NUM_TX_DESC; i++)
+ priv->tx_desc[i].die_dt = DT_EEMPTY;
+
+ /* Mark the end of the descriptors */
+ priv->tx_desc[RSWITCH_NUM_TX_DESC - 1].die_dt = DT_LINKFIX;
+ tx_desc_addr = (uintptr_t)priv->tx_desc;
+ priv->tx_desc[RSWITCH_NUM_TX_DESC - 1].dptrl = lower_32_bits(tx_desc_addr);
+ priv->tx_desc[RSWITCH_NUM_TX_DESC - 1].dptrh = upper_32_bits(tx_desc_addr);
+ rswitch_flush_dcache(tx_desc_addr, desc_size);
+
+ /* Point the controller to the TX descriptor list */
+ priv->bat_desc[RSWITCH_TX_CHAIN_INDEX].die_dt = DT_LINKFIX;
+ priv->bat_desc[RSWITCH_TX_CHAIN_INDEX].dptrl = lower_32_bits(tx_desc_addr);
+ priv->bat_desc[RSWITCH_TX_CHAIN_INDEX].dptrh = upper_32_bits(tx_desc_addr);
+ rswitch_flush_dcache((uintptr_t)&priv->bat_desc[RSWITCH_TX_CHAIN_INDEX],
+ sizeof(struct rswitch_desc));
+}
+
+static void rswitch_rx_desc_init(struct rswitch_port_priv *priv)
+{
+ const u32 desc_size = RSWITCH_NUM_RX_DESC * sizeof(struct rswitch_rxdesc);
+ int i;
+ u64 packet_addr;
+ u64 next_rx_desc_addr;
+ u64 rx_desc_addr;
+
+ /* Initialize all descriptor */
+ memset(priv->rx_desc, 0x0, desc_size);
+ priv->rx_desc_index = 0;
+
+ for (i = 0; i < RSWITCH_NUM_RX_DESC; i++) {
+ priv->rx_desc[i].data.die_dt = DT_EEMPTY;
+ priv->rx_desc[i].data.info_ds = PKTSIZE_ALIGN;
+ packet_addr = (uintptr_t)priv->rx_desc[i].packet;
+ priv->rx_desc[i].data.dptrl = lower_32_bits(packet_addr);
+ priv->rx_desc[i].data.dptrh = upper_32_bits(packet_addr);
+
+ priv->rx_desc[i].link.die_dt = DT_LINKFIX;
+ next_rx_desc_addr = (uintptr_t)&priv->rx_desc[i + 1];
+ priv->rx_desc[i].link.dptrl = lower_32_bits(next_rx_desc_addr);
+ priv->rx_desc[i].link.dptrh = upper_32_bits(next_rx_desc_addr);
+ }
+
+ /* Mark the end of the descriptors */
+ priv->rx_desc[RSWITCH_NUM_RX_DESC - 1].link.die_dt = DT_LINKFIX;
+ rx_desc_addr = (uintptr_t)priv->rx_desc;
+ priv->rx_desc[RSWITCH_NUM_RX_DESC - 1].link.dptrl = lower_32_bits(rx_desc_addr);
+ priv->rx_desc[RSWITCH_NUM_RX_DESC - 1].link.dptrh = upper_32_bits(rx_desc_addr);
+ rswitch_flush_dcache(rx_desc_addr, desc_size);
+
+ /* Point the controller to the rx descriptor list */
+ priv->bat_desc[RSWITCH_RX_CHAIN_INDEX].die_dt = DT_LINKFIX;
+ priv->bat_desc[RSWITCH_RX_CHAIN_INDEX].dptrl = lower_32_bits(rx_desc_addr);
+ priv->bat_desc[RSWITCH_RX_CHAIN_INDEX].dptrh = upper_32_bits(rx_desc_addr);
+ rswitch_flush_dcache((uintptr_t)&priv->bat_desc[RSWITCH_RX_CHAIN_INDEX],
+ sizeof(struct rswitch_desc));
+}
+
+static void rswitch_clock_enable(struct rswitch_port_priv *priv)
+{
+ struct rswitch_etha *etha = &priv->etha;
+ struct rswitch_gwca *gwca = &priv->gwca;
+
+ setbits_le32(priv->addr + RCEC, BIT(etha->index) | BIT(gwca->index) | RCEC_RCE);
+}
+
+static int rswitch_bpool_init(struct rswitch_port_priv *priv)
+{
+ u32 pval;
+
+ writel(CABPIRM_BPIOG, priv->addr + CABPIRM);
+
+ return readl_poll_sleep_timeout(priv->addr + CABPIRM, pval,
+ pval & CABPIRM_BPR,
+ RSWITCH_SLEEP_US, RSWITCH_TIMEOUT_US);
+}
+
+static void rswitch_mfwd_init(struct rswitch_port_priv *priv)
+{
+ struct rswitch_etha *etha = &priv->etha;
+ struct rswitch_gwca *gwca = &priv->gwca;
+
+ writel(FWPC0_DEFAULT, priv->addr + FWPC0(etha->index));
+ writel(FWPC0_DEFAULT, priv->addr + FWPC0(gwca->index));
+
+ writel(RSWITCH_RX_CHAIN_INDEX,
+ priv->addr + FWPBFCSDC(HW_INDEX_TO_GWCA(gwca->index), etha->index));
+
+ writel(BIT(gwca->index),
+ priv->addr + FWPBFC(etha->index));
+
+ writel(BIT(etha->index),
+ priv->addr + FWPBFC(gwca->index));
+}
+
+static void rswitch_rmac_init(struct rswitch_etha *etha)
+{
+ unsigned char *mac = etha->enetaddr;
+
+ /* Set MAC address */
+ writel((mac[2] << 24) | (mac[3] << 16) | (mac[4] << 8) | mac[5],
+ etha->addr + MRMAC1);
+
+ writel((mac[0] << 8) | mac[1], etha->addr + MRMAC0);
+
+ /* Set MIIx */
+ writel(MPIC_PIS_GMII | MPIC_LSC_1000, etha->addr + MPIC);
+
+ writel(0x07E707E7, etha->addr + MRAFC);
+}
+
+static int rswitch_gwca_mcast_table_reset(struct rswitch_gwca *gwca)
+{
+ u32 pval;
+
+ writel(GWMTIRM_MTIOG, gwca->addr + GWMTIRM);
+
+ return readl_poll_sleep_timeout(gwca->addr + GWMTIRM, pval,
+ pval & GWMTIRM_MTR,
+ RSWITCH_SLEEP_US, RSWITCH_TIMEOUT_US);
+}
+
+static int rswitch_gwca_axi_ram_reset(struct rswitch_gwca *gwca)
+{
+ u32 pval;
+
+ writel(GWARIRM_ARIOG, gwca->addr + GWARIRM);
+
+ return readl_poll_sleep_timeout(gwca->addr + GWARIRM, pval,
+ pval & GWARIRM_ARR,
+ RSWITCH_SLEEP_US, RSWITCH_TIMEOUT_US);
+}
+
+static int rswitch_gwca_init(struct rswitch_port_priv *priv)
+{
+ struct rswitch_gwca *gwca = &priv->gwca;
+ int ret;
+
+ ret = rswitch_gwca_change_mode(priv, GWMC_OPC_DISABLE);
+ if (ret)
+ return ret;
+
+ ret = rswitch_gwca_change_mode(priv, GWMC_OPC_CONFIG);
+ if (ret)
+ return ret;
+
+ ret = rswitch_gwca_mcast_table_reset(gwca);
+ if (ret)
+ return ret;
+
+ ret = rswitch_gwca_axi_ram_reset(gwca);
+ if (ret)
+ return ret;
+
+ /* Setting flow */
+ writel(GWVCC_VEM_SC_TAG, gwca->addr + GWVCC);
+ writel(0, gwca->addr + GWTTFC);
+ writel(upper_32_bits((uintptr_t)priv->bat_desc) & GWDCBAC0_DCBAUP, gwca->addr + GWDCBAC0);
+ writel(lower_32_bits((uintptr_t)priv->bat_desc), gwca->addr + GWDCBAC1);
+ writel(GWDCC_DQT | GWDCC_BALR, gwca->addr + GWDCC(RSWITCH_TX_CHAIN_INDEX));
+ writel(GWDCC_BALR, gwca->addr + GWDCC(RSWITCH_RX_CHAIN_INDEX));
+
+ ret = rswitch_gwca_change_mode(priv, GWMC_OPC_DISABLE);
+ if (ret)
+ return ret;
+
+ ret = rswitch_gwca_change_mode(priv, GWMC_OPC_OPERATION);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static int rswitch_etha_tas_ram_reset(struct rswitch_etha *etha)
+{
+ u32 pval;
+
+ writel(EATASRIRM_TASRIOG, etha->addr + EATASRIRM);
+
+ return readl_poll_sleep_timeout(etha->addr + EATASRIRM, pval,
+ pval & EATASRIRM_TASRR,
+ RSWITCH_SLEEP_US, RSWITCH_TIMEOUT_US);
+}
+
+static int rswitch_etha_init(struct rswitch_port_priv *priv)
+{
+ struct rswitch_etha *etha = &priv->etha;
+ int ret;
+ u32 prio;
+
+ ret = rswitch_etha_change_mode(priv, EAMC_OPC_DISABLE);
+ if (ret)
+ return ret;
+
+ ret = rswitch_etha_change_mode(priv, EAMC_OPC_CONFIG);
+ if (ret)
+ return ret;
+
+ ret = rswitch_etha_tas_ram_reset(etha);
+ if (ret)
+ return ret;
+
+ /* Setting flow */
+ writel(0, etha->addr + EATTFC);
+
+ for (prio = 0; prio < RSWITCH_MAX_CTAG_PCP; prio++)
+ writel(EATDQDC_DQD, etha->addr + EATDQDC(prio));
+
+ rswitch_rmac_init(etha);
+
+ ret = rswitch_etha_change_mode(priv, EAMC_OPC_OPERATION);
+ if (ret)
+ return ret;
+
+ /* Link Verification */
+ ret = rswitch_check_link(etha);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static int rswitch_init(struct rswitch_port_priv *priv)
+{
+ struct rswitch_etha *etha = &priv->etha;
+ int ret;
+
+ ret = rswitch_reset(priv);
+ if (ret)
+ return ret;
+
+ ret = generic_phy_set_mode(&priv->serdes, PHY_MODE_ETHERNET,
+ etha->phydev->interface);
+ if (ret)
+ return ret;
+
+ ret = generic_phy_set_speed(&priv->serdes, etha->phydev->speed);
+ if (ret)
+ return ret;
+
+ ret = generic_phy_init(&priv->serdes);
+ if (ret)
+ return ret;
+
+ ret = generic_phy_power_on(&priv->serdes);
+ if (ret)
+ return ret;
+
+ ret = phy_startup(etha->phydev);
+ if (ret)
+ return ret;
+
+ rswitch_bat_desc_init(priv);
+ rswitch_tx_desc_init(priv);
+ rswitch_rx_desc_init(priv);
+
+ rswitch_clock_enable(priv);
+
+ ret = rswitch_bpool_init(priv);
+ if (ret)
+ return ret;
+
+ rswitch_mfwd_init(priv);
+
+ ret = rswitch_gwca_init(priv);
+ if (ret)
+ return ret;
+
+ ret = rswitch_etha_init(priv);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static int rswitch_start(struct udevice *dev)
+{
+ struct rswitch_port_priv *priv = dev_get_priv(dev);
+ int ret;
+
+ ret = rswitch_init(priv);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+#define RSWITCH_TX_TIMEOUT_MS 1000
+static int rswitch_send(struct udevice *dev, void *packet, int len)
+{
+ struct rswitch_port_priv *priv = dev_get_priv(dev);
+ struct rswitch_desc *desc = &priv->tx_desc[priv->tx_desc_index];
+ struct rswitch_gwca *gwca = &priv->gwca;
+ u32 gwtrc_index, start;
+
+ /* Update TX descriptor */
+ rswitch_flush_dcache((uintptr_t)packet, len);
+ memset(desc, 0x0, sizeof(*desc));
+ desc->die_dt = DT_FSINGLE;
+ desc->info_ds = len;
+ desc->dptrl = lower_32_bits((uintptr_t)packet);
+ desc->dptrh = upper_32_bits((uintptr_t)packet);
+ rswitch_flush_dcache((uintptr_t)desc, sizeof(*desc));
+
+ /* Start transmission */
+ gwtrc_index = RSWITCH_TX_CHAIN_INDEX / 32;
+ setbits_le32(gwca->addr + GWTRC(gwtrc_index), BIT(RSWITCH_TX_CHAIN_INDEX));
+
+ /* Wait until packet is transmitted */
+ start = get_timer(0);
+ while (get_timer(start) < RSWITCH_TX_TIMEOUT_MS) {
+ rswitch_invalidate_dcache((uintptr_t)desc, sizeof(*desc));
+ if ((desc->die_dt & DT_MASK) != DT_FSINGLE)
+ break;
+ udelay(10);
+ }
+
+ if (get_timer(start) >= RSWITCH_TX_TIMEOUT_MS) {
+ dev_dbg(dev, "\n%s: Timeout", __func__);
+ return -ETIMEDOUT;
+ }
+
+ priv->tx_desc_index = (priv->tx_desc_index + 1) % (RSWITCH_NUM_TX_DESC - 1);
+
+ return 0;
+}
+
+static int rswitch_recv(struct udevice *dev, int flags, uchar **packetp)
+{
+ struct rswitch_port_priv *priv = dev_get_priv(dev);
+ struct rswitch_rxdesc *desc = &priv->rx_desc[priv->rx_desc_index];
+ u8 *packet;
+ int len;
+
+ /* Check if the rx descriptor is ready */
+ rswitch_invalidate_dcache((uintptr_t)desc, sizeof(*desc));
+ if ((desc->data.die_dt & DT_MASK) == DT_FEMPTY)
+ return -EAGAIN;
+
+ len = desc->data.info_ds & RX_DS;
+ packet = (u8 *)(((uintptr_t)(desc->data.dptrh) << 32) | (uintptr_t)desc->data.dptrl);
+ rswitch_invalidate_dcache((uintptr_t)packet, len);
+
+ *packetp = packet;
+
+ return len;
+}
+
+static int rswitch_free_pkt(struct udevice *dev, uchar *packet, int length)
+{
+ struct rswitch_port_priv *priv = dev_get_priv(dev);
+ struct rswitch_rxdesc *desc = &priv->rx_desc[priv->rx_desc_index];
+
+ /* Make current descritor available again */
+ desc->data.die_dt = DT_FEMPTY;
+ desc->data.info_ds = PKTSIZE_ALIGN;
+ rswitch_flush_dcache((uintptr_t)desc, sizeof(*desc));
+
+ /* Point to the next descriptor */
+ priv->rx_desc_index = (priv->rx_desc_index + 1) % RSWITCH_NUM_RX_DESC;
+ desc = &priv->rx_desc[priv->rx_desc_index];
+ rswitch_invalidate_dcache((uintptr_t)desc, sizeof(*desc));
+
+ return 0;
+}
+
+static void rswitch_stop(struct udevice *dev)
+{
+ struct rswitch_port_priv *priv = dev_get_priv(dev);
+
+ phy_shutdown(priv->etha.phydev);
+
+ generic_phy_power_off(&priv->serdes);
+}
+
+static int rswitch_write_hwaddr(struct udevice *dev)
+{
+ struct rswitch_port_priv *priv = dev_get_priv(dev);
+ struct rswitch_etha *etha = &priv->etha;
+ struct eth_pdata *pdata = dev_get_plat(dev);
+ unsigned char *mac = pdata->enetaddr;
+
+ writel((mac[2] << 24) | (mac[3] << 16) | (mac[4] << 8) | mac[5],
+ etha->addr + MRMAC1);
+
+ writel((mac[0] << 8) | mac[1], etha->addr + MRMAC0);
+
+ return 0;
+}
+
+static int rswitch_phy_config(struct udevice *dev)
+{
+ struct rswitch_port_priv *priv = dev_get_priv(dev);
+ struct rswitch_etha *etha = &priv->etha;
+ struct eth_pdata *pdata = dev_get_plat(dev);
+ struct phy_device *phydev;
+ int phy_addr;
+
+ phy_addr = eth_phy_get_addr(dev);
+ if (phy_addr < 0)
+ return phy_addr;
+
+ phydev = phy_connect(etha->bus, phy_addr, dev, pdata->phy_interface);
+ if (!phydev)
+ return -ENODEV;
+
+ etha->phydev = phydev;
+ phydev->speed = SPEED_1000;
+
+ phy_config(phydev);
+
+ return 0;
+}
+
+static int rswitch_port_probe(struct udevice *dev)
+{
+ struct rswitch_priv *rpriv =
+ (struct rswitch_priv *)dev_get_driver_data(dev);
+ struct eth_pdata *pdata = dev_get_plat(dev);
+ struct rswitch_port_priv *priv = dev_get_priv(dev);
+ struct rswitch_etha *etha = &priv->etha;
+ struct rswitch_gwca *gwca = &priv->gwca;
+ struct mii_dev *mdiodev;
+ int ret;
+
+ priv->addr = rpriv->addr;
+
+ etha->enetaddr = pdata->enetaddr;
+
+ etha->index = dev_read_u32_default(dev, "reg", 0);
+ etha->addr = priv->addr + RSWITCH_ETHA_OFFSET + etha->index * RSWITCH_ETHA_SIZE;
+
+ gwca->index = 1;
+ gwca->addr = priv->addr + RSWITCH_GWCA_OFFSET + gwca->index * RSWITCH_GWCA_SIZE;
+ gwca->index = GWCA_TO_HW_INDEX(gwca->index);
+
+ ret = generic_phy_get_by_index(dev, 0, &priv->serdes);
+ if (ret)
+ return ret;
+
+ /* Toggle the reset so we can access the PHYs */
+ ret = rswitch_reset(priv);
+ if (ret)
+ return ret;
+
+ mdiodev = mdio_alloc();
+ if (!mdiodev)
+ return -ENOMEM;
+
+ mdiodev->priv = priv;
+ mdiodev->read = rswitch_mii_read_c45;
+ mdiodev->write = rswitch_mii_write_c45;
+ snprintf(mdiodev->name, sizeof(mdiodev->name), dev->name);
+
+ ret = mdio_register(mdiodev);
+ if (ret)
+ goto err_mdio_register;
+
+ priv->etha.bus = miiphy_get_dev_by_name(dev->name);
+
+ ret = rswitch_phy_config(dev);
+ if (ret)
+ goto err_mdio_register;
+
+ return 0;
+
+err_mdio_register:
+ mdio_free(mdiodev);
+ return ret;
+}
+
+static int rswitch_port_remove(struct udevice *dev)
+{
+ struct rswitch_port_priv *priv = dev_get_priv(dev);
+
+ mdio_unregister(priv->etha.bus);
+ free(priv->etha.phydev);
+
+ return 0;
+}
+
+int rswitch_ofdata_to_platdata(struct udevice *dev)
+{
+ struct eth_pdata *pdata = dev_get_plat(dev);
+
+ pdata->phy_interface = dev_read_phy_mode(dev);
+ if (pdata->phy_interface == PHY_INTERFACE_MODE_NA)
+ return -EINVAL;
+
+ pdata->max_speed = dev_read_u32_default(dev, "max-speed", 1000);
+
+ return 0;
+}
+
+static const struct eth_ops rswitch_port_ops = {
+ .start = rswitch_start,
+ .send = rswitch_send,
+ .recv = rswitch_recv,
+ .free_pkt = rswitch_free_pkt,
+ .stop = rswitch_stop,
+ .write_hwaddr = rswitch_write_hwaddr,
+};
+
+U_BOOT_DRIVER(rswitch_port) = {
+ .name = "rswitch-port",
+ .id = UCLASS_ETH,
+ .of_to_plat = rswitch_ofdata_to_platdata,
+ .probe = rswitch_port_probe,
+ .remove = rswitch_port_remove,
+ .ops = &rswitch_port_ops,
+ .priv_auto = sizeof(struct rswitch_port_priv),
+ .plat_auto = sizeof(struct eth_pdata),
+ .flags = DM_FLAG_ALLOC_PRIV_DMA | DM_FLAG_OS_PREPARE,
+};
+
+static int rswitch_probe(struct udevice *dev)
+{
+ struct rswitch_priv *priv = dev_get_plat(dev);
+ fdt_addr_t secure_base;
+ fdt_size_t size;
+ int ret;
+
+ secure_base = dev_read_addr_size_name(dev, "secure_base", &size);
+ if (!secure_base)
+ return -EINVAL;
+
+ priv->addr = map_physmem(secure_base, size, MAP_NOCACHE);
+ if (!priv->addr)
+ return -EINVAL;
+
+ priv->rsw_clk = devm_clk_get(dev, NULL);
+ if (ret)
+ goto err_map;
+
+ ret = clk_prepare_enable(priv->rsw_clk);
+ if (ret)
+ goto err_map;
+
+ return 0;
+
+err_map:
+ unmap_physmem(priv->addr, MAP_NOCACHE);
+ return ret;
+}
+
+static int rswitch_remove(struct udevice *dev)
+{
+ struct rswitch_priv *priv = dev_get_plat(dev);
+
+ clk_disable_unprepare(priv->rsw_clk);
+ unmap_physmem(priv->addr, MAP_NOCACHE);
+
+ return 0;
+}
+
+static int rswitch_bind(struct udevice *parent)
+{
+ struct rswitch_port_priv *priv = dev_get_plat(parent);
+ ofnode ports_np, node;
+ struct udevice *dev;
+ struct driver *drv;
+ int ret;
+
+ drv = lists_driver_lookup_name("rswitch-port");
+ if (!drv)
+ return -ENOENT;
+
+ ports_np = dev_read_subnode(parent, "ethernet-ports");
+ if (!ofnode_valid(ports_np))
+ return -ENOENT;
+
+ ofnode_for_each_subnode(node, ports_np) {
+ ret = device_bind_with_driver_data(parent, drv,
+ ofnode_get_name(node),
+ (ulong)priv, node, &dev);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static const struct udevice_id rswitch_ids[] = {
+ { .compatible = "renesas,r8a779f0-ether-switch" },
+ { }
+};
+
+U_BOOT_DRIVER(rswitch) = {
+ .name = "rswitch",
+ .id = UCLASS_NOP,
+ .of_match = rswitch_ids,
+ .bind = rswitch_bind,
+ .probe = rswitch_probe,
+ .remove = rswitch_remove,
+ .plat_auto = sizeof(struct rswitch_priv),
+};
--
2.39.2
2
1

01 Apr '23
Import marvell_phy.h from Linux 5.14.y as of commit
a5de4be0aaaa6 ("net: phy: marvell10g: fix differentiation of 88X3310 from 88X3340")
and use it in marvell PHY driver instead of current ad-hoc macros.
Two of the PHY IDs are unknown to Linux, 88E1149S and 88E1680, for
those two, only sync the length of the hexadecimal number to 8 digits.
No functional change.
Signed-off-by: Marek Vasut <marek.vasut+renesas(a)mailbox.org>
---
Cc: "Ariel D'Alessandro" <ariel.dalessandro(a)collabora.com>
Cc: "Marek BehĂșn" <kabel(a)kernel.org>
Cc: Joe Hershberger <joe.hershberger(a)ni.com>
Cc: Marek Vasut <marek.vasut+renesas(a)mailbox.org>
Cc: Michael Trimarchi <michael(a)amarulasolutions.com>
Cc: Nate Drude <nate.d(a)variscite.com>
Cc: Ramon Fried <rfried.dev(a)gmail.com>
Cc: Simon Glass <sjg(a)chromium.org>
Cc: Stefan Roese <sr(a)denx.de>
Cc: Tim Harvey <tharvey(a)gateworks.com>
Cc: Vladimir Oltean <vladimir.oltean(a)nxp.com>
---
drivers/net/phy/marvell.c | 45 +++++++++++++++++++------------------
include/marvell_phy.h | 47 +++++++++++++++++++++++++++++++++++++++
2 files changed, 70 insertions(+), 22 deletions(-)
create mode 100644 include/marvell_phy.h
diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c
index 8992be6e89e..0a90f710dfe 100644
--- a/drivers/net/phy/marvell.c
+++ b/drivers/net/phy/marvell.c
@@ -7,6 +7,7 @@
*/
#include <common.h>
#include <errno.h>
+#include <marvell_phy.h>
#include <phy.h>
#include <linux/bitops.h>
#include <linux/delay.h>
@@ -695,8 +696,8 @@ static int m88e1680_config(struct phy_device *phydev)
U_BOOT_PHY_DRIVER(m88e1011s) = {
.name = "Marvell 88E1011S",
- .uid = 0x1410c60,
- .mask = 0xffffff0,
+ .uid = MARVELL_PHY_ID_88E1101,
+ .mask = MARVELL_PHY_ID_MASK,
.features = PHY_GBIT_FEATURES,
.config = &m88e1011s_config,
.startup = &m88e1011s_startup,
@@ -705,8 +706,8 @@ U_BOOT_PHY_DRIVER(m88e1011s) = {
U_BOOT_PHY_DRIVER(m88e1111s) = {
.name = "Marvell 88E1111S",
- .uid = 0x1410cc0,
- .mask = 0xffffff0,
+ .uid = MARVELL_PHY_ID_88E1111,
+ .mask = MARVELL_PHY_ID_MASK,
.features = PHY_GBIT_FEATURES,
.config = &m88e1111s_config,
.startup = &m88e1011s_startup,
@@ -715,8 +716,8 @@ U_BOOT_PHY_DRIVER(m88e1111s) = {
U_BOOT_PHY_DRIVER(m88e1118) = {
.name = "Marvell 88E1118",
- .uid = 0x1410e10,
- .mask = 0xffffff0,
+ .uid = MARVELL_PHY_ID_88E1118,
+ .mask = MARVELL_PHY_ID_MASK,
.features = PHY_GBIT_FEATURES,
.config = &m88e1118_config,
.startup = &m88e1118_startup,
@@ -725,8 +726,8 @@ U_BOOT_PHY_DRIVER(m88e1118) = {
U_BOOT_PHY_DRIVER(m88e1118r) = {
.name = "Marvell 88E1118R",
- .uid = 0x1410e40,
- .mask = 0xffffff0,
+ .uid = MARVELL_PHY_ID_88E1116R,
+ .mask = MARVELL_PHY_ID_MASK,
.features = PHY_GBIT_FEATURES,
.config = &m88e1118_config,
.startup = &m88e1118_startup,
@@ -735,8 +736,8 @@ U_BOOT_PHY_DRIVER(m88e1118r) = {
U_BOOT_PHY_DRIVER(m88e1121r) = {
.name = "Marvell 88E1121R",
- .uid = 0x1410cb0,
- .mask = 0xffffff0,
+ .uid = MARVELL_PHY_ID_88E1121R,
+ .mask = MARVELL_PHY_ID_MASK,
.features = PHY_GBIT_FEATURES,
.config = &m88e1121_config,
.startup = &genphy_startup,
@@ -745,8 +746,8 @@ U_BOOT_PHY_DRIVER(m88e1121r) = {
U_BOOT_PHY_DRIVER(m88e1145) = {
.name = "Marvell 88E1145",
- .uid = 0x1410cd0,
- .mask = 0xffffff0,
+ .uid = MARVELL_PHY_ID_88E1145,
+ .mask = MARVELL_PHY_ID_MASK,
.features = PHY_GBIT_FEATURES,
.config = &m88e1145_config,
.startup = &m88e1145_startup,
@@ -755,8 +756,8 @@ U_BOOT_PHY_DRIVER(m88e1145) = {
U_BOOT_PHY_DRIVER(m88e1149s) = {
.name = "Marvell 88E1149S",
- .uid = 0x1410ca0,
- .mask = 0xffffff0,
+ .uid = 0x01410ca0,
+ .mask = MARVELL_PHY_ID_MASK,
.features = PHY_GBIT_FEATURES,
.config = &m88e1149_config,
.startup = &m88e1011s_startup,
@@ -765,8 +766,8 @@ U_BOOT_PHY_DRIVER(m88e1149s) = {
U_BOOT_PHY_DRIVER(m88e1240) = {
.name = "Marvell 88E1240",
- .uid = 0x1410e30,
- .mask = 0xffffff0,
+ .uid = MARVELL_PHY_ID_88E1240,
+ .mask = MARVELL_PHY_ID_MASK,
.features = PHY_GBIT_FEATURES,
.config = &m88e1240_config,
.startup = &m88e1011s_startup,
@@ -775,8 +776,8 @@ U_BOOT_PHY_DRIVER(m88e1240) = {
U_BOOT_PHY_DRIVER(m88e151x) = {
.name = "Marvell 88E151x",
- .uid = 0x1410dd0,
- .mask = 0xffffff0,
+ .uid = MARVELL_PHY_ID_88E1510,
+ .mask = MARVELL_PHY_ID_MASK,
.features = PHY_GBIT_FEATURES,
.config = &m88e151x_config,
.startup = &m88e1011s_startup,
@@ -787,8 +788,8 @@ U_BOOT_PHY_DRIVER(m88e151x) = {
U_BOOT_PHY_DRIVER(m88e1310) = {
.name = "Marvell 88E1310",
- .uid = 0x01410e90,
- .mask = 0xffffff0,
+ .uid = MARVELL_PHY_ID_88E1318S,
+ .mask = MARVELL_PHY_ID_MASK,
.features = PHY_GBIT_FEATURES,
.config = &m88e1310_config,
.startup = &m88e1011s_startup,
@@ -797,8 +798,8 @@ U_BOOT_PHY_DRIVER(m88e1310) = {
U_BOOT_PHY_DRIVER(m88e1680) = {
.name = "Marvell 88E1680",
- .uid = 0x1410ed0,
- .mask = 0xffffff0,
+ .uid = 0x01410ed0,
+ .mask = MARVELL_PHY_ID_MASK,
.features = PHY_GBIT_FEATURES,
.config = &m88e1680_config,
.startup = &genphy_startup,
diff --git a/include/marvell_phy.h b/include/marvell_phy.h
new file mode 100644
index 00000000000..0f06c2287b5
--- /dev/null
+++ b/include/marvell_phy.h
@@ -0,0 +1,47 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _MARVELL_PHY_H
+#define _MARVELL_PHY_H
+
+/* Mask used for ID comparisons */
+#define MARVELL_PHY_ID_MASK 0xfffffff0
+
+/* Known PHY IDs */
+#define MARVELL_PHY_ID_88E1101 0x01410c60
+#define MARVELL_PHY_ID_88E1112 0x01410c90
+#define MARVELL_PHY_ID_88E1111 0x01410cc0
+#define MARVELL_PHY_ID_88E1118 0x01410e10
+#define MARVELL_PHY_ID_88E1121R 0x01410cb0
+#define MARVELL_PHY_ID_88E1145 0x01410cd0
+#define MARVELL_PHY_ID_88E1149R 0x01410e50
+#define MARVELL_PHY_ID_88E1240 0x01410e30
+#define MARVELL_PHY_ID_88E1318S 0x01410e90
+#define MARVELL_PHY_ID_88E1340S 0x01410dc0
+#define MARVELL_PHY_ID_88E1116R 0x01410e40
+#define MARVELL_PHY_ID_88E1510 0x01410dd0
+#define MARVELL_PHY_ID_88E1540 0x01410eb0
+#define MARVELL_PHY_ID_88E1545 0x01410ea0
+#define MARVELL_PHY_ID_88E1548P 0x01410ec0
+#define MARVELL_PHY_ID_88E3016 0x01410e60
+#define MARVELL_PHY_ID_88X3310 0x002b09a0
+#define MARVELL_PHY_ID_88E2110 0x002b09b0
+#define MARVELL_PHY_ID_88X2222 0x01410f10
+
+/* Marvel 88E1111 in Finisar SFP module with modified PHY ID */
+#define MARVELL_PHY_ID_88E1111_FINISAR 0x01ff0cc0
+
+/* These Ethernet switch families contain embedded PHYs, but they do
+ * not have a model ID. So the switch driver traps reads to the ID2
+ * register and returns the switch family ID
+ */
+#define MARVELL_PHY_ID_88E6341_FAMILY 0x01410f41
+#define MARVELL_PHY_ID_88E6390_FAMILY 0x01410f90
+#define MARVELL_PHY_ID_88E6393_FAMILY 0x002b0b9b
+
+#define MARVELL_PHY_FAMILY_ID(id) ((id) >> 4)
+
+/* struct phy_device dev_flags definitions */
+#define MARVELL_PHY_M1145_FLAGS_RESISTANCE 0x00000001
+#define MARVELL_PHY_M1118_DNS323_LEDS 0x00000002
+#define MARVELL_PHY_LED0_LINK_LED1_ACTIVE 0x00000004
+
+#endif /* _MARVELL_PHY_H */
--
2.39.2
2
9