[PATCH v2] serial: pl01x: set baudrate when probing

2024-02-28 Thread Yang Xiwen via B4 Relay
From: Yang Xiwen 

It is found that when DM is enabled, only generic init function is
called in .probe(). Baudrate is never honored. Add a function call
to .setbrg() when probing so that we can update the baudrate of the
serial device.

Signed-off-by: Yang Xiwen 
---
Changes in v2:
- reverse if statement (Dan Carpenter)
- Link to v1: 
https://lore.kernel.org/r/20240123-b4-pl011-v1-1-fb576d0a7...@outlook.com
---
 drivers/serial/serial_pl01x.c | 11 ---
 1 file changed, 8 insertions(+), 3 deletions(-)

diff --git a/drivers/serial/serial_pl01x.c b/drivers/serial/serial_pl01x.c
index 428a4d210de5..f04c21e08264 100644
--- a/drivers/serial/serial_pl01x.c
+++ b/drivers/serial/serial_pl01x.c
@@ -290,6 +290,7 @@ int pl01x_serial_probe(struct udevice *dev)
 {
struct pl01x_serial_plat *plat = dev_get_plat(dev);
struct pl01x_priv *priv = dev_get_priv(dev);
+   int ret;
 
 #if CONFIG_IS_ENABLED(OF_PLATDATA)
struct dtd_serial_pl01x *dtplat = >dtplat;
@@ -301,10 +302,14 @@ int pl01x_serial_probe(struct udevice *dev)
 #endif
priv->type = plat->type;
 
-   if (!plat->skip_init)
-   return pl01x_generic_serial_init(priv->regs, priv->type);
-   else
+   if (!plat->skip_init) {
+   ret = pl01x_generic_serial_init(priv->regs, priv->type);
+   if (ret)
+   return ret;
+   return pl01x_serial_setbrg(dev, gd->baudrate);
+   } else {
return 0;
+   }
 }
 
 int pl01x_serial_getc(struct udevice *dev)

---
base-commit: f7cca7ccc5117eaafcc2bde91ad1bed6fee7cfc3
change-id: 20240123-b4-pl011-ee9575ff2a38

Best regards,
-- 
Yang Xiwen 



[PATCH RESEND] serial: pl01x: set baudrate when probing

2024-02-24 Thread Yang Xiwen via B4 Relay
From: Yang Xiwen 

It is found that when DM is enabled, only generic init function is
called in .probe(). Baudrate is never honored. Add a function call
to .setbrg() when probing so that we can update the baudrate of the
serial device.

Signed-off-by: Yang Xiwen 
---
 drivers/serial/serial_pl01x.c | 11 ---
 1 file changed, 8 insertions(+), 3 deletions(-)

diff --git a/drivers/serial/serial_pl01x.c b/drivers/serial/serial_pl01x.c
index 428a4d210de5..57bbcaf3b619 100644
--- a/drivers/serial/serial_pl01x.c
+++ b/drivers/serial/serial_pl01x.c
@@ -290,6 +290,7 @@ int pl01x_serial_probe(struct udevice *dev)
 {
struct pl01x_serial_plat *plat = dev_get_plat(dev);
struct pl01x_priv *priv = dev_get_priv(dev);
+   int ret;
 
 #if CONFIG_IS_ENABLED(OF_PLATDATA)
struct dtd_serial_pl01x *dtplat = >dtplat;
@@ -301,10 +302,14 @@ int pl01x_serial_probe(struct udevice *dev)
 #endif
priv->type = plat->type;
 
-   if (!plat->skip_init)
-   return pl01x_generic_serial_init(priv->regs, priv->type);
-   else
+   if (!plat->skip_init) {
+   ret = pl01x_generic_serial_init(priv->regs, priv->type);
+   if (!ret)
+   return ret;
+   return pl01x_serial_setbrg(dev, gd->baudrate);
+   } else {
return 0;
+   }
 }
 
 int pl01x_serial_getc(struct udevice *dev)

---
base-commit: f7cca7ccc5117eaafcc2bde91ad1bed6fee7cfc3
change-id: 20240123-b4-pl011-ee9575ff2a38

Best regards,
-- 
Yang Xiwen 



[PATCH RFC] pinctrl: add support for HiSilicon HiSTB SoCs

2024-02-12 Thread Yang Xiwen via B4 Relay
From: Yang Xiwen 

The first supported SoC is Hi3798MV200.

Signed-off-by: Yang Xiwen 
---
This patchset adds support for HiSTB ioconfig module. The module is used
to set pins config(e.g. pull-up, pull-down, drive-strength etc..) and
pinmux.

The first supported chip is Hi3798MV200. Adding support for Hi3798CV200
should be also easy.

Below is an example of the dts node:

```dts
ioconfig: pinctrl@8a21000 {
compatible = "hisilicon,hi3798mv200-ioconfig";
reg = <0x8a21000 0x180>;
#pinctrl-cells = <1>;

emmc_default: emmc-default-state {
cdata-pins {
// CDATA0-7
pins = "W20", "V20", "U20", "V19", "Y21", "W21", "V21", 
"U21";
bias-pullup;
slew-rate = <1>;

drive-strength = <8>;
function = "emmc_cdata";
};

cclk-pin {
pins = "T18";

bias-pullup;
slew-rate = <1>;

drive-strength = <8>;
function = "emmc_cclk";
};

ccmd-pin {
pins = "T20";

bias-pullup;
slew-rate = <1>;

drive-strength = <6>;
function = "emmc_ccmd";
};

reset-pin {
pins = "R20";

bias-disable;
slew-rate = <1>;

drive-strength = <1>;
function = "emmc_rst";
};

datastrobe-pin {
pins = "R21";

bias-pullup;
slew-rate;

drive-strength = <1>;
function = "emmc_datastrobe";
};
};
};
```
---
 drivers/pinctrl/Kconfig|   1 +
 drivers/pinctrl/Makefile   |   1 +
 drivers/pinctrl/hisilicon/Kconfig  |  21 ++
 drivers/pinctrl/hisilicon/Makefile |   6 +
 drivers/pinctrl/hisilicon/pinctrl-hi3798mv2x.c | 319 +
 drivers/pinctrl/hisilicon/pinctrl-histb.c  | 276 +
 drivers/pinctrl/hisilicon/pinctrl-histb.h  | 132 ++
 7 files changed, 756 insertions(+)

diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
index a1d53cfbdb..d600a30492 100644
--- a/drivers/pinctrl/Kconfig
+++ b/drivers/pinctrl/Kconfig
@@ -346,6 +346,7 @@ endif
 
 source "drivers/pinctrl/broadcom/Kconfig"
 source "drivers/pinctrl/exynos/Kconfig"
+source "drivers/pinctrl/hisilicon/Kconfig"
 source "drivers/pinctrl/intel/Kconfig"
 source "drivers/pinctrl/mediatek/Kconfig"
 source "drivers/pinctrl/meson/Kconfig"
diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile
index 0e929d8ca0..79fb800faf 100644
--- a/drivers/pinctrl/Makefile
+++ b/drivers/pinctrl/Makefile
@@ -36,3 +36,4 @@ obj-$(CONFIG_$(SPL_)PINCTRL_STMFX)+= pinctrl-stmfx.o
 obj-y  += broadcom/
 obj-$(CONFIG_PINCTRL_ZYNQMP)   += pinctrl-zynqmp.o
 obj-$(CONFIG_PINCTRL_STARFIVE) += starfive/
+obj-$(CONFIG_PINCTRL_HISILICON)+= hisilicon/
diff --git a/drivers/pinctrl/hisilicon/Kconfig 
b/drivers/pinctrl/hisilicon/Kconfig
new file mode 100644
index 00..33c3048940
--- /dev/null
+++ b/drivers/pinctrl/hisilicon/Kconfig
@@ -0,0 +1,21 @@
+config PINCTRL_HISILICON
+   bool
+
+config PINCTRL_HISTB
+   bool "HiSilicon HiSTB pinctrl framework"
+   depends on PINCTRL
+   select PINCTRL_HISILICON
+   imply PINCONF
+   help
+ Support HiSTB SoCs IOCONFIG module
+
+menu "HiSTB pinctrl drivers"
+   depends on PINCTRL_HISTB
+
+config PINCTRL_HI3798MV2X
+   bool "HiSilicon Hi3798MV2X pinctrl driver"
+   depends on ARCH_HI3798MV2X
+   help
+ Support IOCONFIG on Hi3798MV2X SoCs
+
+endmenu
diff --git a/drivers/pinctrl/hisilicon/Makefile 
b/drivers/pinctrl/hisilicon/Makefile
new file mode 100644
index 00..5afb64d4b6
--- /dev/null
+++ b/drivers/pinctrl/hisilicon/Makefile
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+#
+# Copyright 2024 (r) Yang Xiwen 
+
+obj-$(CONFIG_PINCTRL_HISTB)+= pinctrl-histb.o
+obj-$(CONFIG_PINCTRL_HI3798MV2X)   += pinctrl-hi3798mv2x.o
diff --git a/drivers/pinctrl/hisilicon/pinctrl-hi3798mv2x.c 
b/drivers/pinctrl/hisilicon/pinctrl-hi3798mv2x.c
new file mode 100644
index 00..1e0a89675a
--- /dev/null
+++ b/drivers/pinctrl/hisilicon/pinctrl-hi3798mv2x.c
@@ -0,0 +1,319 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * IOCONFIG driver for Hi3798MV2x SoCs
+ *
+ * Copyright 2024 (r) Yang Xiwen 
+ */
+
+#include 
+
+#include "pinctrl-histb.h"
+
+// The sequence is important!
+enum hi3798mv2x_ioconfig_pins {
+   HI3798MV2X_Y19,
+   HI3798MV2X_W19,
+   

[PATCH v2 3/3] usb: ehci: Make usage of generic_{setup,shutdown}_phy_bulk() helpers

2024-02-07 Thread Yang Xiwen via B4 Relay
From: Yang Xiwen 

Replace generic_setup_phy() and generic_shutdown_phy() by respectively
generic_setup_phy_bulk() and generic_shutdown_phy_bulk().

Signed-off-by: Yang Xiwen 
---
 drivers/usb/host/ehci-generic.c | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/usb/host/ehci-generic.c b/drivers/usb/host/ehci-generic.c
index 936e30438d..e109d84d73 100644
--- a/drivers/usb/host/ehci-generic.c
+++ b/drivers/usb/host/ehci-generic.c
@@ -25,7 +25,7 @@ struct generic_ehci {
struct ehci_ctrl ctrl;
struct clk_bulk clocks;
struct reset_ctl_bulk resets;
-   struct phy phy;
+   struct phy_bulk phys;
struct udevice *vbus_supply;
 };
 
@@ -95,7 +95,7 @@ static int ehci_usb_probe(struct udevice *dev)
if (err)
goto reset_err;
 
-   err = generic_setup_phy(dev, >phy, 0);
+   err = generic_setup_phy_bulk(dev, >phys);
if (err)
goto regulator_err;
 
@@ -110,7 +110,7 @@ static int ehci_usb_probe(struct udevice *dev)
return 0;
 
 phy_err:
-   ret = generic_shutdown_phy(>phy);
+   ret = generic_shutdown_phy_bulk(>phys);
if (ret)
dev_err(dev, "failed to shutdown usb phy (ret=%d)\n", ret);
 
@@ -140,7 +140,7 @@ static int ehci_usb_remove(struct udevice *dev)
if (ret)
return ret;
 
-   ret = generic_shutdown_phy(>phy);
+   ret = generic_shutdown_phy_bulk(>phys);
if (ret)
return ret;
 

-- 
2.43.0



[PATCH v2 0/3] usb: ehci-generic: setup a bulk of phy when possible

2024-02-07 Thread Yang Xiwen via B4 Relay
one USB controller can have multiple ports specified in dts, all of them
should be setup to make use of all possible ports.

Signed-off-by: Yang Xiwen 
---
Changes in v2:
- Rewrite generic_phy_setup_bulk(): Actually v1 is doing things
  completely wrong. This series should work and it's tested on a real
  machine.
- Link to v1: 
https://lore.kernel.org/r/20240201-ehci-v1-0-bb506cb0f...@outlook.com

---
Yang Xiwen (3):
  phy: add generic_setup(shutdown)_phy_bulk()
  test: phy: test generic_setup(shutdown)_phy_bulk()
  usb: ehci: Make usage of generic_{setup,shutdown}_phy_bulk() helpers

 drivers/phy/phy-uclass.c| 41 +
 drivers/usb/host/ehci-generic.c |  8 
 include/generic-phy.h   | 29 +
 test/dm/phy.c   |  4 
 4 files changed, 78 insertions(+), 4 deletions(-)
---
base-commit: b6d8969bcb94321dfed1399f2eaa8768ba42caaa
change-id: 20240201-ehci-6c3aa7d97932

Best regards,
-- 
Yang Xiwen 



[PATCH v2 2/3] test: phy: test generic_setup(shutdown)_phy_bulk()

2024-02-07 Thread Yang Xiwen via B4 Relay
From: Yang Xiwen 

add unittests for the newly introduced helper functions.

Signed-off-by: Yang Xiwen 
---
 test/dm/phy.c | 4 
 1 file changed, 4 insertions(+)

diff --git a/test/dm/phy.c b/test/dm/phy.c
index 0cf3689fde..cb16844a0a 100644
--- a/test/dm/phy.c
+++ b/test/dm/phy.c
@@ -159,6 +159,8 @@ static int dm_test_phy_bulk(struct unit_test_state *uts)
ut_asserteq(0, generic_phy_power_on_bulk());
ut_asserteq(0, generic_phy_power_off_bulk());
ut_asserteq(0, generic_phy_exit_bulk());
+   ut_asserteq(0, generic_setup_phy_bulk(parent, ));
+   ut_asserteq(0, generic_shutdown_phy_bulk());
 
/* has a known problem phy */
ut_assertok(uclass_get_device_by_name(UCLASS_SIMPLE_BUS,
@@ -171,6 +173,8 @@ static int dm_test_phy_bulk(struct unit_test_state *uts)
ut_asserteq(-EIO, generic_phy_power_on_bulk());
ut_asserteq(-EIO, generic_phy_power_off_bulk());
ut_asserteq(0, generic_phy_exit_bulk());
+   ut_asserteq(-EIO, generic_setup_phy_bulk(parent, ));
+   ut_asserteq(-EIO, generic_shutdown_phy_bulk());
 
return 0;
 }

-- 
2.43.0



[PATCH v2 1/3] phy: add generic_setup(shutdown)_phy_bulk()

2024-02-07 Thread Yang Xiwen via B4 Relay
From: Yang Xiwen 

They are the bulk version of generic_setup(shutdown)_phy().

Signed-off-by: Yang Xiwen 
---
 drivers/phy/phy-uclass.c | 41 +
 include/generic-phy.h| 29 +
 2 files changed, 70 insertions(+)

diff --git a/drivers/phy/phy-uclass.c b/drivers/phy/phy-uclass.c
index 0dcfe258bc..1a6bb54290 100644
--- a/drivers/phy/phy-uclass.c
+++ b/drivers/phy/phy-uclass.c
@@ -528,6 +528,36 @@ int generic_setup_phy(struct udevice *dev, struct phy 
*phy, int index)
return ret;
 }
 
+int generic_setup_phy_bulk(struct udevice *dev, struct phy_bulk *bulk)
+{
+   int ret;
+
+   ret = generic_phy_get_bulk(dev, bulk);
+   if (ret) {
+   pr_err("Can't get PHY bulk: %d\n", ret);
+   goto phys_get_err;
+   }
+
+   ret = generic_phy_init_bulk(bulk);
+   if (ret) {
+   pr_err("Can't init PHY bulk: %d\n", ret);
+   goto phys_get_err;
+   }
+
+   ret = generic_phy_power_on_bulk(bulk);
+   if (ret) {
+   generic_phy_exit_bulk(bulk);
+   goto phys_setup_err;
+   }
+
+   return 0;
+
+phys_setup_err:
+   generic_phy_exit_bulk(bulk);
+phys_get_err:
+   return ret;
+}
+
 int generic_shutdown_phy(struct phy *phy)
 {
int ret;
@@ -542,6 +572,17 @@ int generic_shutdown_phy(struct phy *phy)
return generic_phy_exit(phy);
 }
 
+int generic_shutdown_phy_bulk(struct phy_bulk *bulk)
+{
+   struct phy *phys = bulk->phys;
+   int i, ret = 0;
+
+   for (i = 0; i < bulk->count; i++)
+   ret |= generic_shutdown_phy([i]);
+
+   return ret;
+}
+
 UCLASS_DRIVER(phy) = {
.id = UCLASS_PHY,
.name   = "phy",
diff --git a/include/generic-phy.h b/include/generic-phy.h
index eaab749166..2d1bf7c1ea 100644
--- a/include/generic-phy.h
+++ b/include/generic-phy.h
@@ -420,6 +420,16 @@ int generic_phy_power_off_bulk(struct phy_bulk *bulk);
  */
 int generic_setup_phy(struct udevice *dev, struct phy *phy, int index);
 
+/**
+ * generic_setup_phy() - Get, initialize and power on all phys in a phy bulk.
+ *
+ * @dev:   The consumer device.
+ * @bulk:  A pointer to the PHY bulk
+ *
+ * Return: 0 if OK, or negative error code.
+ */
+int generic_setup_phy_bulk(struct udevice *dev, struct phy_bulk *bulk);
+
 /**
  * generic_shutdown_phy() - Power off and de-initialize phy.
  *
@@ -429,6 +439,15 @@ int generic_setup_phy(struct udevice *dev, struct phy 
*phy, int index);
  */
 int generic_shutdown_phy(struct phy *phy);
 
+/**
+ * generic_shutdown_phy_bulk() - Power off and de-initialize all phys in a phy 
bulk.
+ *
+ * @bulk:  A pointer to the PHY bulk.
+ *
+ * Return: 0 if OK, or negative error code.
+ */
+int generic_shutdown_phy_bulk(struct phy_bulk *bulk);
+
 #else /* CONFIG_PHY */
 
 static inline int generic_phy_init(struct phy *phy)
@@ -514,11 +533,21 @@ static inline int generic_setup_phy(struct udevice *dev, 
struct phy *phy, int in
return 0;
 }
 
+static inline int generic_setup_phy_bulk(struct udevice *dev, struct phy_bulk 
*bulk)
+{
+   return 0;
+}
+
 static inline int generic_shutdown_phy(struct phy *phy)
 {
return 0;
 }
 
+static inline int generic_shutdown_phy_bulk(struct phy_bulk *bulk)
+{
+   return 0;
+}
+
 #endif /* CONFIG_PHY */
 
 /**

-- 
2.43.0



[PATCH 2/3] usb: dwc3: replace argument mode with child ofnode

2024-02-02 Thread Yang Xiwen via B4 Relay
From: Yang Xiwen 

child ofnode is more useful and can be used to query a lot of other
props of child device. dr_mode can be also queried from it.

Signed-off-by: Yang Xiwen 
---
 drivers/usb/dwc3/dwc3-generic.c | 12 
 drivers/usb/dwc3/dwc3-generic.h |  3 +--
 2 files changed, 5 insertions(+), 10 deletions(-)

diff --git a/drivers/usb/dwc3/dwc3-generic.c b/drivers/usb/dwc3/dwc3-generic.c
index 6fb2de8a5a..d892042b91 100644
--- a/drivers/usb/dwc3/dwc3-generic.c
+++ b/drivers/usb/dwc3/dwc3-generic.c
@@ -272,8 +272,7 @@ U_BOOT_DRIVER(dwc3_generic_host) = {
 };
 #endif
 
-void dwc3_imx8mp_glue_configure(struct udevice *dev, int index,
-   enum usb_dr_mode mode)
+void dwc3_imx8mp_glue_configure(struct udevice *dev, ofnode child, int index)
 {
 /* USB glue registers */
 #define USB_CTRL0  0x00
@@ -323,8 +322,7 @@ struct dwc3_glue_ops imx8mp_ops = {
.glue_configure = dwc3_imx8mp_glue_configure,
 };
 
-void dwc3_ti_glue_configure(struct udevice *dev, int index,
-   enum usb_dr_mode mode)
+void dwc3_ti_glue_configure(struct udevice *dev, ofnode child, int index)
 {
 #define USBOTGSS_UTMI_OTG_STATUS   0x0084
 #define USBOTGSS_UTMI_OTG_OFFSET   0x0480
@@ -348,6 +346,7 @@ enum dwc3_omap_utmi_mode {
u32 reg;
u32 utmi_mode;
u32 utmi_status_offset = USBOTGSS_UTMI_OTG_STATUS;
+   enum usb_dr_mode mode = usb_get_dr_mode(child);
 
struct dwc3_glue_data *glue = dev_get_plat(dev);
void *base = map_physmem(glue->regs, 0x1, MAP_NOCACHE);
@@ -577,12 +576,9 @@ int dwc3_glue_probe(struct udevice *dev)
}
 
while (child) {
-   enum usb_dr_mode dr_mode;
-
-   dr_mode = usb_get_dr_mode(dev_ofnode(child));
device_find_next_child();
if (ops && ops->glue_configure)
-   ops->glue_configure(dev, index, dr_mode);
+   ops->glue_configure(dev, dev_ofnode(child), index);
index++;
}
 
diff --git a/drivers/usb/dwc3/dwc3-generic.h b/drivers/usb/dwc3/dwc3-generic.h
index 40902c8923..46c14a338b 100644
--- a/drivers/usb/dwc3/dwc3-generic.h
+++ b/drivers/usb/dwc3/dwc3-generic.h
@@ -22,8 +22,7 @@ struct dwc3_glue_data {
 
 struct dwc3_glue_ops {
int (*glue_get_ctrl_dev)(struct udevice *parent, ofnode *node);
-   void (*glue_configure)(struct udevice *dev, int index,
-  enum usb_dr_mode mode);
+   void (*glue_configure)(struct udevice *parent, ofnode node, int index);
 };
 
 int dwc3_glue_bind(struct udevice *parent);

-- 
2.43.0



[PATCH 3/3] usb: dwc3: add glue driver for Hi3798MV200

2024-02-02 Thread Yang Xiwen via B4 Relay
From: Yang Xiwen 

It needs some platform-specific operations before generic initialization
code.

If nano PHY is not initialized properly, it must be disabled. Or else
 USB host will complain unable to reset port.

USB2 is always supported, so it's never disabled.

Signed-off-by: Yang Xiwen 
---
 drivers/usb/dwc3/dwc3-generic.c | 40 
 1 file changed, 40 insertions(+)

diff --git a/drivers/usb/dwc3/dwc3-generic.c b/drivers/usb/dwc3/dwc3-generic.c
index d892042b91..a3200ff1ab 100644
--- a/drivers/usb/dwc3/dwc3-generic.c
+++ b/drivers/usb/dwc3/dwc3-generic.c
@@ -419,6 +419,45 @@ struct dwc3_glue_ops rk_ops = {
.glue_get_ctrl_dev = dwc3_rk_glue_get_ctrl_dev,
 };
 
+static void dwc3_hi3798mv200_glue_configure(struct udevice *dev, ofnode child, 
int index)
+{
+#define HI3798MV200_PERI_CTRL_ADDR 0xf8a2
+#define HI3798MV200_PERI_USB5  0x134
+#define USB3_U3_PORT_DISABLE   BIT(5)
+#define USB3_U2_PORT_DISABLE   BIT(4)
+
+   // Disable super-speed port if maximum speed is high-speed
+   void __iomem *peri_base = map_physmem(HI3798MV200_PERI_CTRL_ADDR, 
0x1000, MAP_NOCACHE);
+   enum usb_device_speed speed = usb_get_maximum_speed(child);
+   u32 reg;
+
+   reg = readl(peri_base + HI3798MV200_PERI_USB5);
+   reg &= ~(USB3_U3_PORT_DISABLE | USB3_U2_PORT_DISABLE);
+
+   switch (speed) {
+   case USB_SPEED_LOW:
+   case USB_SPEED_FULL:
+   case USB_SPEED_HIGH:
+   // disable super-speed port
+   reg |= USB3_U3_PORT_DISABLE;
+   pr_info("%s: super-speed port disabled.\n", __func__);
+   break;
+
+   case USB_SPEED_SUPER:
+   break;
+
+   default:
+   pr_warn("%s: unknown speed class %d.\n", __func__, speed);
+   }
+
+   writel(reg, peri_base + HI3798MV200_PERI_USB5);
+   unmap_physmem(peri_base, MAP_NOCACHE);
+}
+
+const struct dwc3_glue_ops hi3798mv200_ops = {
+   .glue_configure = dwc3_hi3798mv200_glue_configure,
+};
+
 static int dwc3_glue_bind_common(struct udevice *parent, ofnode node)
 {
const char *name = ofnode_get_name(node);
@@ -611,6 +650,7 @@ static const struct udevice_id dwc3_glue_ids[] = {
{ .compatible = "fsl,imx8mp-dwc3", .data = (ulong)_ops },
{ .compatible = "fsl,imx8mq-dwc3" },
{ .compatible = "intel,tangier-dwc3" },
+   { .compatible = "hisilicon,hi3798mv200-dwc3", .data = 
(ulong)_ops },
{ }
 };
 

-- 
2.43.0



[PATCH 0/3] usb: dwv3: add glue driver for hi3798mv200

2024-02-02 Thread Yang Xiwen via B4 Relay
Also edit the prototype of .glue_configure to fulfill our needs.

Signed-off-by: Yang Xiwen 
---
Yang Xiwen (3):
  usb: dwc3: handle return value of clk_get_rate() correctly
  usb: dwc3: replace argument mode with child ofnode
  usb: dwc3: add glue driver for Hi3798MV200

 drivers/usb/dwc3/core.c |  2 +-
 drivers/usb/dwc3/dwc3-generic.c | 52 ++---
 drivers/usb/dwc3/dwc3-generic.h |  3 +--
 3 files changed, 46 insertions(+), 11 deletions(-)
---
base-commit: 050a9b981d6a835133521b599be3ae189ce70f41
change-id: 20240203-hisi-dwc3-3c47f734cd20

Best regards,
-- 
Yang Xiwen 



[PATCH 1/3] usb: dwc3: handle return value of clk_get_rate() correctly

2024-02-02 Thread Yang Xiwen via B4 Relay
From: Yang Xiwen 

clk_get_rate() return -ve on error, not 0. Fix it by replacing judging
NULL with IS_ERR_VALUE().

Fixes: 6bae0eb5b8bd("usb: dwc3: Calculate REFCLKPER based on reference clock")
Signed-off-by: Yang Xiwen 
---
 drivers/usb/dwc3/core.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
index 4b4fcd8a22..06ff68105e 100644
--- a/drivers/usb/dwc3/core.c
+++ b/drivers/usb/dwc3/core.c
@@ -137,7 +137,7 @@ static void dwc3_ref_clk_period(struct dwc3 *dwc)
 
if (dwc->ref_clk) {
rate = clk_get_rate(dwc->ref_clk);
-   if (!rate)
+   if (IS_ERR_VALUE(rate))
return;
period = NSEC_PER_SEC / rate;
} else {

-- 
2.43.0



[PATCH v2 1/3] mmc: hi6220-dwmmc: handle clocks and resets if CONFIG_CLK and CONFIG_DM_RESET enabled

2024-02-01 Thread Yang Xiwen via B4 Relay
From: Yang Xiwen 

This can avoid hardcoding a clock rate in driver. Also can enable the
clocks and deassert the resets if the pre-bootloader does not do this
for us.

Currently only enabled for Hi3798MV200.

Signed-off-by: Yang Xiwen 
---
 drivers/mmc/hi6220_dw_mmc.c | 61 -
 1 file changed, 60 insertions(+), 1 deletion(-)

diff --git a/drivers/mmc/hi6220_dw_mmc.c b/drivers/mmc/hi6220_dw_mmc.c
index 71962cd47e..a4b8072976 100644
--- a/drivers/mmc/hi6220_dw_mmc.c
+++ b/drivers/mmc/hi6220_dw_mmc.c
@@ -5,15 +5,24 @@
  */
 
 #include 
+#include 
 #include 
 #include 
 #include 
 #include 
 #include 
+#include 
 #include 
+#include 
 
 DECLARE_GLOBAL_DATA_PTR;
 
+enum hi6220_dwmmc_clk_type {
+   HI6220_DWMMC_CLK_BIU,
+   HI6220_DWMMC_CLK_CIU,
+   HI6220_DWMMC_CLK_CNT,
+};
+
 struct hi6220_dwmmc_plat {
struct mmc_config cfg;
struct mmc mmc;
@@ -21,6 +30,8 @@ struct hi6220_dwmmc_plat {
 
 struct hi6220_dwmmc_priv_data {
struct dwmci_host host;
+   struct clk *clks[HI6220_DWMMC_CLK_CNT];
+   struct reset_ctl_bulk rsts;
 };
 
 struct hisi_mmc_data {
@@ -32,7 +43,29 @@ static int hi6220_dwmmc_of_to_plat(struct udevice *dev)
 {
struct hi6220_dwmmc_priv_data *priv = dev_get_priv(dev);
struct dwmci_host *host = >host;
+   int ret;
 
+   if (CONFIG_IS_ENABLED(CLK) && CONFIG_IS_ENABLED(DM_RESET)) {
+   priv->clks[HI6220_DWMMC_CLK_BIU] = devm_clk_get(dev, "biu");
+   if (IS_ERR(priv->clks[HI6220_DWMMC_CLK_BIU])) {
+   ret = PTR_ERR(priv->clks[HI6220_DWMMC_CLK_BIU]);
+   dev_err(dev, "Failed to get BIU clock(ret = %d).\n", 
ret);
+   return log_msg_ret("clk", ret);
+   }
+
+   priv->clks[HI6220_DWMMC_CLK_CIU] = devm_clk_get(dev, "ciu");
+   if (IS_ERR(priv->clks[HI6220_DWMMC_CLK_CIU])) {
+   ret = PTR_ERR(priv->clks[HI6220_DWMMC_CLK_CIU]);
+   dev_err(dev, "Failed to get CIU clock(ret = %d).\n", 
ret);
+   return log_msg_ret("clk", ret);
+   }
+
+   ret = reset_get_bulk(dev, >rsts);
+   if (ret) {
+   dev_err(dev, "Failed to get resets(ret = %d)", ret);
+   return log_msg_ret("rst", ret);
+   }
+   }
host->name = dev->name;
host->ioaddr = dev_read_addr_ptr(dev);
host->buswidth = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev),
@@ -56,11 +89,37 @@ static int hi6220_dwmmc_probe(struct udevice *dev)
struct hi6220_dwmmc_priv_data *priv = dev_get_priv(dev);
struct dwmci_host *host = >host;
struct hisi_mmc_data *mmc_data;
+   int ret;
 
mmc_data = (struct hisi_mmc_data *)dev_get_driver_data(dev);
 
-   /* Use default bus speed due to absence of clk driver */
host->bus_hz = mmc_data->clock;
+   if (CONFIG_IS_ENABLED(CLK) && CONFIG_IS_ENABLED(DM_RESET)) {
+   ret = clk_prepare_enable(priv->clks[HI6220_DWMMC_CLK_BIU]);
+   if (ret) {
+   dev_err(dev, "Failed to enable biu clock(ret = %d).\n", 
ret);
+   return log_msg_ret("clk", ret);
+   }
+
+   ret = clk_prepare_enable(priv->clks[HI6220_DWMMC_CLK_CIU]);
+   if (ret) {
+   dev_err(dev, "Failed to enable ciu clock(ret = %d).\n", 
ret);
+   return log_msg_ret("clk", ret);
+   }
+
+   ret = reset_deassert_bulk(>rsts);
+   if (ret) {
+   dev_err(dev, "Failed to deassert resets(ret = %d).\n", 
ret);
+   return log_msg_ret("rst", ret);
+   }
+
+   host->bus_hz = clk_get_rate(priv->clks[HI6220_DWMMC_CLK_CIU]);
+   if (host->bus_hz <= 0) {
+   dev_err(dev, "Failed to get ciu clock rate(ret = 
%d).\n", ret);
+   return log_msg_ret("clk", ret);
+   }
+   }
+   dev_dbg(dev, "bus clock rate: %d.\n", host->bus_hz);
 
dwmci_setup_cfg(>cfg, host, host->bus_hz, 40);
host->mmc = >mmc;

-- 
2.43.0



[PATCH v2 3/3] mmc: hi6220_dw_mmc: add fifoth_val to private data and set it in .probe

2024-02-01 Thread Yang Xiwen via B4 Relay
From: Yang Xiwen 

The value defaults to 0 and is ignored by dw_mmc code, so the other
users are not affected.

Setting this explicitly fixes some weird reading error found on Hi3798MV200.

Fixes: 8a5dc8140e62 ("mmc: hi6220_dw_mmc: add compatible for HC2910 support")

Signed-off-by: Yang Xiwen 
---
 drivers/mmc/hi6220_dw_mmc.c | 11 ++-
 1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/drivers/mmc/hi6220_dw_mmc.c b/drivers/mmc/hi6220_dw_mmc.c
index a4b8072976..dc0210402b 100644
--- a/drivers/mmc/hi6220_dw_mmc.c
+++ b/drivers/mmc/hi6220_dw_mmc.c
@@ -37,6 +37,7 @@ struct hi6220_dwmmc_priv_data {
 struct hisi_mmc_data {
unsigned int clock;
bool use_fifo;
+   u32 fifoth_val;
 };
 
 static int hi6220_dwmmc_of_to_plat(struct udevice *dev)
@@ -125,6 +126,7 @@ static int hi6220_dwmmc_probe(struct udevice *dev)
host->mmc = >mmc;
 
host->fifo_mode = mmc_data->use_fifo;
+   host->fifoth_val = mmc_data->fifoth_val;
host->mmc->priv = >host;
upriv->mmc = host->mmc;
host->mmc->dev = dev;
@@ -154,13 +156,20 @@ static const struct hisi_mmc_data hi6220_mmc_data = {
.use_fifo = false,
 };
 
+static const struct hisi_mmc_data hi3798mv2x_mmc_data = {
+   .clock = 5000,
+   .use_fifo = false,
+   // FIFO depth is 256
+   .fifoth_val = MSIZE(4) | RX_WMARK(0x7f) | TX_WMARK(0x80),
+};
+
 static const struct udevice_id hi6220_dwmmc_ids[] = {
{ .compatible = "hisilicon,hi6220-dw-mshc",
  .data = (ulong)_mmc_data },
{ .compatible = "hisilicon,hi3798cv200-dw-mshc",
  .data = (ulong)_mmc_data },
{ .compatible = "hisilicon,hi3798mv200-dw-mshc",
- .data = (ulong)_mmc_data },
+ .data = (ulong)_mmc_data },
{ .compatible = "hisilicon,hi3660-dw-mshc",
  .data = (ulong)_mmc_data },
{ }

-- 
2.43.0



[PATCH v2 2/3] mmc: dw_mmc: Don't return error if data busy timeout

2024-02-01 Thread Yang Xiwen via B4 Relay
From: Yang Xiwen 

As described in [1], some poor hardware or cards would fail to release
the bus and keep driving data lines low. Ignore it and send the next cmd
directly seems okay for most cases.

[1]: 
https://patchwork.kernel.org/project/linux-mmc/patch/1424458179-5456-1-git-send-email-diand...@chromium.org/

Signed-off-by: Yang Xiwen 
---
 drivers/mmc/dw_mmc.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/mmc/dw_mmc.c b/drivers/mmc/dw_mmc.c
index 400066fa99..e103664145 100644
--- a/drivers/mmc/dw_mmc.c
+++ b/drivers/mmc/dw_mmc.c
@@ -262,8 +262,8 @@ static int dwmci_send_cmd(struct mmc *mmc, struct mmc_cmd 
*cmd,
 
while (dwmci_readl(host, DWMCI_STATUS) & DWMCI_BUSY) {
if (get_timer(start) > timeout) {
-   debug("%s: Timeout on data busy\n", __func__);
-   return -ETIMEDOUT;
+   debug("%s: Timeout on data busy, continue anyway\n", 
__func__);
+   break;
}
}
 

-- 
2.43.0



[PATCH v2 0/3] mmc: hi6220-dwmmc: handle resets and clocks

2024-02-01 Thread Yang Xiwen via B4 Relay
Also allow setup fifoth_val in driver

Signed-off-by: Yang Xiwen 
---
Changes in v2:
- dw-mmc: proceed if data busy found
- hi6220-dw-mmc: add fifoth_val setup, separate hi3798mv200 data
- Link to v1: 
https://lore.kernel.org/r/20240119-mmc-v1-1-aee6b2cf6...@outlook.com

---
Yang Xiwen (3):
  mmc: hi6220-dwmmc: handle clocks and resets if CONFIG_CLK and 
CONFIG_DM_RESET enabled
  mmc: dw_mmc: Don't return error if data busy timeout
  mmc: hi6220_dw_mmc: add fifoth_val to private data and set it in .probe

 drivers/mmc/dw_mmc.c|  4 +--
 drivers/mmc/hi6220_dw_mmc.c | 72 +++--
 2 files changed, 72 insertions(+), 4 deletions(-)
---
base-commit: f7cca7ccc5117eaafcc2bde91ad1bed6fee7cfc3
change-id: 20240119-mmc-9cf7f3455cb4

Best regards,
-- 
Yang Xiwen 



[PATCH 2/3] test: phy: test generic_setup(shutdown)_phy_bulk()

2024-02-01 Thread Yang Xiwen via B4 Relay
From: Yang Xiwen 

add unittests for the newly introduced helper functions.

Signed-off-by: Yang Xiwen 
---
 test/dm/phy.c | 4 
 1 file changed, 4 insertions(+)

diff --git a/test/dm/phy.c b/test/dm/phy.c
index 0cf3689fde..cb16844a0a 100644
--- a/test/dm/phy.c
+++ b/test/dm/phy.c
@@ -159,6 +159,8 @@ static int dm_test_phy_bulk(struct unit_test_state *uts)
ut_asserteq(0, generic_phy_power_on_bulk());
ut_asserteq(0, generic_phy_power_off_bulk());
ut_asserteq(0, generic_phy_exit_bulk());
+   ut_asserteq(0, generic_setup_phy_bulk(parent, ));
+   ut_asserteq(0, generic_shutdown_phy_bulk());
 
/* has a known problem phy */
ut_assertok(uclass_get_device_by_name(UCLASS_SIMPLE_BUS,
@@ -171,6 +173,8 @@ static int dm_test_phy_bulk(struct unit_test_state *uts)
ut_asserteq(-EIO, generic_phy_power_on_bulk());
ut_asserteq(-EIO, generic_phy_power_off_bulk());
ut_asserteq(0, generic_phy_exit_bulk());
+   ut_asserteq(-EIO, generic_setup_phy_bulk(parent, ));
+   ut_asserteq(-EIO, generic_shutdown_phy_bulk());
 
return 0;
 }

-- 
2.43.0



[PATCH 3/3] usb: ehci: Make usage of generic_{setup,shutdown}_phy_bulk() helpers

2024-02-01 Thread Yang Xiwen via B4 Relay
From: Yang Xiwen 

Replace generic_setup_phy() and generic_shutdown_phy() by respectively
generic_setup_phy_bulk() and generic_shutdown_phy_bulk().

Signed-off-by: Yang Xiwen 
---
 drivers/usb/host/ehci-generic.c | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/usb/host/ehci-generic.c b/drivers/usb/host/ehci-generic.c
index 936e30438d..e109d84d73 100644
--- a/drivers/usb/host/ehci-generic.c
+++ b/drivers/usb/host/ehci-generic.c
@@ -25,7 +25,7 @@ struct generic_ehci {
struct ehci_ctrl ctrl;
struct clk_bulk clocks;
struct reset_ctl_bulk resets;
-   struct phy phy;
+   struct phy_bulk phys;
struct udevice *vbus_supply;
 };
 
@@ -95,7 +95,7 @@ static int ehci_usb_probe(struct udevice *dev)
if (err)
goto reset_err;
 
-   err = generic_setup_phy(dev, >phy, 0);
+   err = generic_setup_phy_bulk(dev, >phys);
if (err)
goto regulator_err;
 
@@ -110,7 +110,7 @@ static int ehci_usb_probe(struct udevice *dev)
return 0;
 
 phy_err:
-   ret = generic_shutdown_phy(>phy);
+   ret = generic_shutdown_phy_bulk(>phys);
if (ret)
dev_err(dev, "failed to shutdown usb phy (ret=%d)\n", ret);
 
@@ -140,7 +140,7 @@ static int ehci_usb_remove(struct udevice *dev)
if (ret)
return ret;
 
-   ret = generic_shutdown_phy(>phy);
+   ret = generic_shutdown_phy_bulk(>phys);
if (ret)
return ret;
 

-- 
2.43.0



[PATCH 1/3] phy: add generic_setup(shutdown)_phy_bulk()

2024-02-01 Thread Yang Xiwen via B4 Relay
From: Yang Xiwen 

They are the bulk version of generic_setup(shutdown)_phy().

Signed-off-by: Yang Xiwen 
---
 drivers/phy/phy-uclass.c | 33 +
 include/generic-phy.h| 29 +
 2 files changed, 62 insertions(+)

diff --git a/drivers/phy/phy-uclass.c b/drivers/phy/phy-uclass.c
index 0dcfe258bc..d50ebbe3a0 100644
--- a/drivers/phy/phy-uclass.c
+++ b/drivers/phy/phy-uclass.c
@@ -528,6 +528,28 @@ int generic_setup_phy(struct udevice *dev, struct phy 
*phy, int index)
return ret;
 }
 
+int generic_setup_phy_bulk(struct udevice *dev, struct phy_bulk *bulk)
+{
+   struct phy *phys = bulk->phys;
+   int i, ret;
+
+   for (i = 0; i < bulk->count; i++) {
+   ret = generic_setup_phy(dev, [i], i);
+   if (ret) {
+   pr_err("Can't setup PHY%d\n", i);
+   goto phys_setup_err;
+   }
+   }
+
+   return 0;
+
+phys_setup_err:
+   for (; i > 0; i--)
+   generic_shutdown_phy([i - 1]);
+
+   return ret;
+}
+
 int generic_shutdown_phy(struct phy *phy)
 {
int ret;
@@ -542,6 +564,17 @@ int generic_shutdown_phy(struct phy *phy)
return generic_phy_exit(phy);
 }
 
+int generic_shutdown_phy_bulk(struct phy_bulk *bulk)
+{
+   struct phy *phys = bulk->phys;
+   int i, ret = 0;
+
+   for (i = 0; i < bulk->count; i++)
+   ret |= generic_shutdown_phy([i]);
+
+   return ret;
+}
+
 UCLASS_DRIVER(phy) = {
.id = UCLASS_PHY,
.name   = "phy",
diff --git a/include/generic-phy.h b/include/generic-phy.h
index eaab749166..2d1bf7c1ea 100644
--- a/include/generic-phy.h
+++ b/include/generic-phy.h
@@ -420,6 +420,16 @@ int generic_phy_power_off_bulk(struct phy_bulk *bulk);
  */
 int generic_setup_phy(struct udevice *dev, struct phy *phy, int index);
 
+/**
+ * generic_setup_phy() - Get, initialize and power on all phys in a phy bulk.
+ *
+ * @dev:   The consumer device.
+ * @bulk:  A pointer to the PHY bulk
+ *
+ * Return: 0 if OK, or negative error code.
+ */
+int generic_setup_phy_bulk(struct udevice *dev, struct phy_bulk *bulk);
+
 /**
  * generic_shutdown_phy() - Power off and de-initialize phy.
  *
@@ -429,6 +439,15 @@ int generic_setup_phy(struct udevice *dev, struct phy 
*phy, int index);
  */
 int generic_shutdown_phy(struct phy *phy);
 
+/**
+ * generic_shutdown_phy_bulk() - Power off and de-initialize all phys in a phy 
bulk.
+ *
+ * @bulk:  A pointer to the PHY bulk.
+ *
+ * Return: 0 if OK, or negative error code.
+ */
+int generic_shutdown_phy_bulk(struct phy_bulk *bulk);
+
 #else /* CONFIG_PHY */
 
 static inline int generic_phy_init(struct phy *phy)
@@ -514,11 +533,21 @@ static inline int generic_setup_phy(struct udevice *dev, 
struct phy *phy, int in
return 0;
 }
 
+static inline int generic_setup_phy_bulk(struct udevice *dev, struct phy_bulk 
*bulk)
+{
+   return 0;
+}
+
 static inline int generic_shutdown_phy(struct phy *phy)
 {
return 0;
 }
 
+static inline int generic_shutdown_phy_bulk(struct phy_bulk *bulk)
+{
+   return 0;
+}
+
 #endif /* CONFIG_PHY */
 
 /**

-- 
2.43.0



[PATCH 0/3] usb: ehci-generic: setup a bulk of phy when possible

2024-02-01 Thread Yang Xiwen via B4 Relay
one USB controller can have multiple ports specified in dts, all of them
should be setup to make use of all possible ports.

Signed-off-by: Yang Xiwen 
---
Yang Xiwen (3):
  phy: add generic_setup(shutdown)_phy_bulk()
  test: phy: test generic_setup(shutdown)_phy_bulk()
  usb: ehci: Make usage of generic_{setup,shutdown}_phy_bulk() helpers

 drivers/phy/phy-uclass.c| 33 +
 drivers/usb/host/ehci-generic.c |  8 
 include/generic-phy.h   | 29 +
 test/dm/phy.c   |  4 
 4 files changed, 70 insertions(+), 4 deletions(-)
---
base-commit: b6d8969bcb94321dfed1399f2eaa8768ba42caaa
change-id: 20240201-ehci-6c3aa7d97932

Best regards,
-- 
Yang Xiwen 



[PATCH] serial: pl01x: set baudrate when probing

2024-01-22 Thread Yang Xiwen via B4 Relay
From: Yang Xiwen 

It is found that when DM is enabled, only generic init function is
called in .probe(). Baudrate is never honored. Add a function call
to .setbrg() when probing so that we can update the baudrate of the
serial device.

Signed-off-by: Yang Xiwen 
---
 drivers/serial/serial_pl01x.c | 11 ---
 1 file changed, 8 insertions(+), 3 deletions(-)

diff --git a/drivers/serial/serial_pl01x.c b/drivers/serial/serial_pl01x.c
index 428a4d210d..57bbcaf3b6 100644
--- a/drivers/serial/serial_pl01x.c
+++ b/drivers/serial/serial_pl01x.c
@@ -290,6 +290,7 @@ int pl01x_serial_probe(struct udevice *dev)
 {
struct pl01x_serial_plat *plat = dev_get_plat(dev);
struct pl01x_priv *priv = dev_get_priv(dev);
+   int ret;
 
 #if CONFIG_IS_ENABLED(OF_PLATDATA)
struct dtd_serial_pl01x *dtplat = >dtplat;
@@ -301,10 +302,14 @@ int pl01x_serial_probe(struct udevice *dev)
 #endif
priv->type = plat->type;
 
-   if (!plat->skip_init)
-   return pl01x_generic_serial_init(priv->regs, priv->type);
-   else
+   if (!plat->skip_init) {
+   ret = pl01x_generic_serial_init(priv->regs, priv->type);
+   if (!ret)
+   return ret;
+   return pl01x_serial_setbrg(dev, gd->baudrate);
+   } else {
return 0;
+   }
 }
 
 int pl01x_serial_getc(struct udevice *dev)

---
base-commit: f7cca7ccc5117eaafcc2bde91ad1bed6fee7cfc3
change-id: 20240123-b4-pl011-ee9575ff2a38

Best regards,
-- 
Yang Xiwen 



[PATCH v3 4/5] net: hifemac: implement `net stats` needed ops

2024-01-22 Thread Yang Xiwen via B4 Relay
From: Yang Xiwen 

3 operations needed by `net stats` are implemented. New `net stats`
output some useful info.

Signed-off-by: Yang Xiwen 
---
 drivers/net/hifemac.c | 87 +++
 1 file changed, 87 insertions(+)

diff --git a/drivers/net/hifemac.c b/drivers/net/hifemac.c
index 39c0233b62..d24023eefd 100644
--- a/drivers/net/hifemac.c
+++ b/drivers/net/hifemac.c
@@ -16,6 +16,8 @@
 #include 
 #include 
 #include 
+#include 
+#include 
 #include 
 #include 
 
@@ -125,6 +127,57 @@ struct hisi_femac_priv {
u32 link_status;
 };
 
+struct hisi_femac_stat_entry {
+   const char *name;
+   u32 offset;
+   u32 mask;
+};
+
+/* please refer to the datasheet for the description of these entries */
+static const struct hisi_femac_stat_entry hisi_femac_stats_table[] = {
+   { "rxsof_cnt",  0x584,  GENMASK(31, 28) },
+   { "rxeof_cnt",  0x584,  GENMASK(27, 24) },
+   { "rxcrcok_cnt",0x584,  GENMASK(23, 20) },
+   { "rxcrcbad_cnt",   0x584,  GENMASK(19, 16) },
+   { "txsof_cnt",  0x584,  GENMASK(15, 12) },
+   { "txeof_cnt",  0x584,  GENMASK(11, 8) },
+   { "txcrcok_cnt",0x584,  GENMASK(7, 4) },
+   { "txcrcbad_cnt",   0x584,  GENMASK(3, 0) },
+   { "pkts_cpu",   0x5a0,  GENMASK(15, 0) },
+   { "addr_cpu",   0x5a4,  GENMASK(15, 0) },
+   { "pkts_port",  0x5a8,  GENMASK(15, 0) },
+   { "pkts_cpu2tx",0x5ac,  GENMASK(15, 0) },
+   { "rxdvrise",   0x600,  GENMASK(31, 0) },
+   { "ifinoctets", 0x604,  GENMASK(31, 0) },
+   { "octets_rx",  0x608,  GENMASK(31, 0) },
+   { "local_mac_match",0x60c,  GENMASK(31, 0) },
+   { "pkts",   0x610,  GENMASK(31, 0) },
+   { "broadcastpkts",  0x614,  GENMASK(31, 0) },
+   { "multicastpkts",  0x618,  GENMASK(31, 0) },
+   { "ifinucastpkts",  0x61c,  GENMASK(31, 0) },
+   { "ifinerrors", 0x620,  GENMASK(31, 0) },
+   { "crcerr", 0x624,  GENMASK(31, 0) },
+   { "abnormalsizepkts",   0x628,  GENMASK(31, 0) },
+   { "dot3alignmenterr",   0x62c,  GENMASK(31, 0) },
+   { "dot3pause",  0x630,  GENMASK(31, 0) },
+   { "dropevents", 0x634,  GENMASK(31, 0) },
+   { "flux_frame_cnt", 0x638,  GENMASK(31, 0) },
+   { "flux_drop_cnt",  0x63c,  GENMASK(31, 0) },
+   { "mac_not2cpu_pkts",   0x64c,  GENMASK(31, 0) },
+   { "pkts_tx",0x780,  GENMASK(31, 0) },
+   { "broadcastpkts_tx",   0x784,  GENMASK(31, 0) },
+   { "multicastpkts_tx",   0x788,  GENMASK(31, 0) },
+   { "ifoutucastpkts_tx",  0x78c,  GENMASK(31, 0) },
+   { "octets_tx",  0x790,  GENMASK(31, 0) },
+   { "dot3pause",  0x794,  GENMASK(31, 0) },
+   { "retry_times_tx", 0x798,  GENMASK(31, 0) },
+   { "collisions", 0x79c,  GENMASK(31, 0) },
+   { "dot3latecol",0x7a0,  GENMASK(31, 0) },
+   { "dot3colok",  0x7a4,  GENMASK(31, 0) },
+   { "dot3excessivecol",   0x7a8,  GENMASK(31, 0) },
+   { "dot3colcnt", 0x7ac,  GENMASK(31, 0) },
+};
+
 static void hisi_femac_irq_enable(struct hisi_femac_priv *priv, int irqs)
 {
u32 val;
@@ -334,6 +387,37 @@ static void hisi_femac_stop(struct udevice *dev)
writel(SOFT_RESET_ALL, priv->glb_base + GLB_SOFT_RESET);
 }
 
+static int hisi_femac_get_sset_count(struct udevice *dev)
+{
+   return ARRAY_SIZE(hisi_femac_stats_table);
+}
+
+static void hisi_femac_get_strings(struct udevice *dev, u8 *data)
+{
+   int i;
+
+   for (i = 0; i < ARRAY_SIZE(hisi_femac_stats_table); i++)
+   strcpy(data + i * ETH_GSTRING_LEN, 
hisi_femac_stats_table[i].name);
+}
+
+/* Non-constant mask variant of FIELD_GET/FIELD_PREP */
+#define field_get(_mask, _reg) (((_reg) & (_mask)) >> (ffs(_mask) - 1))
+
+static void hisi_femac_get_stats(struct udevice *dev, u64 *data)
+{
+   int i;
+   u32 mask, reg;
+   struct hisi_femac_priv *priv = dev_get_priv(dev);
+   void __iomem *port_base = priv->port_base;
+
+   for (i = 0; i < ARRAY_SIZE(hisi_femac_stats_table); i++) {
+   mask = hisi_femac_stats_table[i].mask;
+   reg = readl(port_base + hisi_femac_stats_table[i].offset);
+
+   data[i] = field_get(mask, reg);
+   }
+}
+
 int hisi_femac_of_to_plat(struct udevice *dev)
 {
int ret, i;
@@ -523,6 +607,9 @@ static const struct eth_ops hisi_femac_ops = {
.free_pkt   = hisi_femac_free_pkt,
.stop   = hisi_femac_stop,
.write_hwaddr   = hisi_femac_set_hw_mac_addr,
+   .get_sset_count = hisi_femac_get_sset_count,
+   .get_strings= hisi_femac_get_strings,
+   .get_stats  = hisi_femac_get_stats,
 };
 
 static const struct udevice_id hisi_femac_ids[] = {

-- 
2.43.0



[PATCH v3 1/5] net: hifemac_mdio: use log_msg_ret() correctly, report error by dev_err()

2024-01-22 Thread Yang Xiwen via B4 Relay
From: Yang Xiwen 

The initial commit used log_msg_ret() wrongly. Fix that by moving error
report to a separate dev_err() call and shrink the first argument of
log_msg_ret() to no more than 4 chars.

Fixes: 6b5c8d98e204 ("net: add hifemac_mdio MDIO bus driver for HiSilicon 
platform")

Signed-off-by: Yang Xiwen 
---
 drivers/net/hifemac_mdio.c | 11 ---
 1 file changed, 8 insertions(+), 3 deletions(-)

diff --git a/drivers/net/hifemac_mdio.c b/drivers/net/hifemac_mdio.c
index 343c5f3a38..0b59d06091 100644
--- a/drivers/net/hifemac_mdio.c
+++ b/drivers/net/hifemac_mdio.c
@@ -8,6 +8,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 
@@ -74,7 +75,8 @@ static int hisi_femac_mdio_of_to_plat(struct udevice *dev)
data->membase = dev_remap_addr(dev);
if (IS_ERR(data->membase)) {
ret = PTR_ERR(data->membase);
-   return log_msg_ret("Failed to remap base addr", ret);
+   dev_err(dev, "Failed to remap base addr %d\n", ret);
+   return log_msg_ret("mdio", ret);
}
 
// clk is optional
@@ -89,8 +91,10 @@ static int hisi_femac_mdio_probe(struct udevice *dev)
int ret;
 
ret = clk_prepare_enable(data->clk);
-   if (ret)
-   return log_msg_ret("Failed to enable clk", ret);
+   if (ret) {
+   dev_err(dev, "Failed to enable clock: %d\n", ret);
+   return log_msg_ret("clk", ret);
+   }
 
return 0;
 }
@@ -112,5 +116,6 @@ U_BOOT_DRIVER(hisi_femac_mdio_driver) = {
.of_to_plat = hisi_femac_mdio_of_to_plat,
.probe = hisi_femac_mdio_probe,
.ops = _femac_mdio_ops,
+   .plat_auto = sizeof(struct mdio_perdev_priv),
.priv_auto = sizeof(struct hisi_femac_mdio_data),
 };

-- 
2.43.0



[PATCH v3 3/5] net: hifemac: register MDIO bus device for subnode

2024-01-22 Thread Yang Xiwen via B4 Relay
From: Yang Xiwen 

register internal MDIO bus device if it is a subnode.

Signed-off-by: Yang Xiwen 
---
 drivers/net/hifemac.c | 28 
 1 file changed, 28 insertions(+)

diff --git a/drivers/net/hifemac.c b/drivers/net/hifemac.c
index 1088f3eca3..39c0233b62 100644
--- a/drivers/net/hifemac.c
+++ b/drivers/net/hifemac.c
@@ -15,6 +15,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 
@@ -337,6 +338,8 @@ int hisi_femac_of_to_plat(struct udevice *dev)
 {
int ret, i;
struct hisi_femac_priv *priv = dev_get_priv(dev);
+   ofnode mdio_node;
+   bool mdio_registered = false;
static const char * const clk_strs[] = {
[CLK_MAC] = "mac",
[CLK_BUS] = "bus",
@@ -388,6 +391,31 @@ int hisi_femac_of_to_plat(struct udevice *dev)
 MAC_RESET_DELAY_PROPERTY,
 MAC_RESET_ASSERT_PERIOD);
 
+   /* Create MDIO bus */
+   ofnode_for_each_subnode(mdio_node, dev_ofnode(dev)) {
+   const char *subnode_name = ofnode_get_name(mdio_node);
+   struct udevice *mdiodev;
+
+   // Skip subnodes not starting with "mdio"
+   if (strncmp(subnode_name, "mdio", 4))
+   continue;
+
+   ret = device_bind_driver_to_node(dev, "hisi-femac-mdio",
+subnode_name, mdio_node, 
);
+   if (ret) {
+   dev_err(dev, "Failed to register MDIO bus device %d\n", 
ret);
+   return log_msg_ret("net", ret);
+   }
+
+   mdio_registered = true;
+   break;
+   }
+
+   if (!mdio_registered) {
+   dev_err(dev, "No MDIO subnode is found!\n");
+   return log_msg_ret("mdio", -ENODATA);
+   }
+
return 0;
 }
 

-- 
2.43.0



[PATCH v3 2/5] net: hifemac: fix log reporting

2024-01-22 Thread Yang Xiwen via B4 Relay
From: Yang Xiwen 

shrink the first argument of log_msg_ret(), add dev_xxx() functions for
error reporting.

Fixes: 9d8f78a2a79f7 ("net: add hifemac Ethernet driver for HiSilicon platform")

Signed-off-by: Yang Xiwen 
---
 drivers/net/hifemac.c | 110 +-
 1 file changed, 73 insertions(+), 37 deletions(-)

diff --git a/drivers/net/hifemac.c b/drivers/net/hifemac.c
index b61a29e636..1088f3eca3 100644
--- a/drivers/net/hifemac.c
+++ b/drivers/net/hifemac.c
@@ -245,8 +245,10 @@ static int hisi_femac_start(struct udevice *dev)
hisi_femac_rx_refill(priv);
 
ret = phy_startup(priv->phy);
-   if (ret)
-   return log_msg_ret("Failed to startup phy", ret);
+   if (ret) {
+   dev_err(dev, "Failed to startup phy: %d\n", ret);
+   return log_msg_ret("phy", ret);
+   }
 
if (!priv->phy->link) {
debug("%s: link down\n", __func__);
@@ -281,8 +283,10 @@ static int hisi_femac_send(struct udevice *dev, void 
*packet, int length)
 
// wait until FIFO is empty
ret = wait_for_bit_le32(priv->glb_base + GLB_IRQ_RAW, 
IRQ_INT_TX_PER_PACKET, true, 50, false);
-   if (ret == -ETIMEDOUT)
-   return log_msg_ret("FIFO timeout", ret);
+   if (ret == -ETIMEDOUT) {
+   dev_err(dev, "FIFO timeout\n");
+   return log_msg_ret("net", ret);
+   }
 
return 0;
 }
@@ -340,35 +344,45 @@ int hisi_femac_of_to_plat(struct udevice *dev)
};
 
priv->port_base = dev_remap_addr_name(dev, "port");
-   if (IS_ERR(priv->port_base))
-   return log_msg_ret("Failed to remap port address space", 
PTR_ERR(priv->port_base));
+   if (!priv->port_base) {
+   dev_err(dev, "Failed to remap port address space\n");
+   return log_msg_ret("net", -EINVAL);
+   }
 
priv->glb_base = dev_remap_addr_name(dev, "glb");
-   if (IS_ERR(priv->glb_base))
-   return log_msg_ret("Failed to remap global address space", 
PTR_ERR(priv->glb_base));
+   if (IS_ERR(priv->glb_base)) {
+   dev_err(dev, "Failed to remap global address space\n");
+   return log_msg_ret("net", -EINVAL);
+   }
 
for (i = 0; i < ARRAY_SIZE(clk_strs); i++) {
priv->clks[i] = devm_clk_get(dev, clk_strs[i]);
if (IS_ERR(priv->clks[i])) {
dev_err(dev, "Error getting clock %s\n", clk_strs[i]);
-   return log_msg_ret("Failed to get clocks", 
PTR_ERR(priv->clks[i]));
+   return log_msg_ret("clk", PTR_ERR(priv->clks[i]));
}
}
 
priv->mac_rst = devm_reset_control_get(dev, "mac");
-   if (IS_ERR(priv->mac_rst))
-   return log_msg_ret("Failed to get MAC reset", 
PTR_ERR(priv->mac_rst));
+   if (IS_ERR(priv->mac_rst)) {
+   dev_err(dev, "Failed to get MAC reset %ld\n", 
PTR_ERR(priv->mac_rst));
+   return log_msg_ret("rst", PTR_ERR(priv->mac_rst));
+   }
 
priv->phy_rst = devm_reset_control_get(dev, "phy");
-   if (IS_ERR(priv->phy_rst))
-   return log_msg_ret("Failed to get PHY reset", 
PTR_ERR(priv->phy_rst));
+   if (IS_ERR(priv->phy_rst)) {
+   dev_err(dev, "Failed to get PHY reset %ld\n", 
PTR_ERR(priv->phy_rst));
+   return log_msg_ret("rst", PTR_ERR(priv->phy_rst));
+   }
 
ret = dev_read_u32_array(dev,
 PHY_RESET_DELAYS_PROPERTY,
 priv->phy_reset_delays,
 DELAYS_NUM);
-   if (ret < 0)
-   return log_msg_ret("Failed to get PHY reset delays", ret);
+   if (ret < 0) {
+   dev_err(dev, "Failed to get PHY reset delays %d\n", ret);
+   return log_msg_ret("rst", ret);
+   }
 
priv->mac_reset_delay = dev_read_u32_default(dev,
 MAC_RESET_DELAY_PROPERTY,
@@ -385,32 +399,44 @@ static int hisi_femac_phy_reset(struct hisi_femac_priv 
*priv)
 
// Disable MAC clk before phy reset
ret = clk_disable(priv->clks[CLK_MAC]);
-   if (ret < 0)
-   return log_msg_ret("Failed to disable MAC clock", ret);
+   if (ret < 0) {
+   pr_err("%s: Failed to disable MAC clock %d\n", __func__, ret);
+   return log_msg_ret("clk", ret);
+   }
ret = clk_disable(priv->clks[CLK_BUS]);
-   if (ret < 0)
-   return log_msg_ret("Failed to disable bus clock", ret);
+   if (ret < 0) {
+   pr_err("%s: Failed to disable bus clock %d\n", __func__, ret);
+   return log_msg_ret("clk", ret);
+   }
 
udelay(delays[PRE_DELAY]);
 
ret = reset_assert(rst);
-   if (ret < 0)
-   return log_msg_ret("Failed to assert reset", ret);
+   if (ret < 0) {
+   

[PATCH v3 0/5] net: hifemac: a few cleanups

2024-01-22 Thread Yang Xiwen via B4 Relay
- Fix the use of log_msg_ret() and add dev_xxx() for error reporting.
- Register mdio subnode as a mdio bus device for hifemac.
- Implement ops needed by `net stats`
- Make functions static.

Signed-off-by: Yang Xiwen 
---
Changes in v3:
- hisi-femac: add missing `static` to avoid polluting global namespace.
- Link to v2: 
https://lore.kernel.org/r/20240122-net-v2-0-78a368896...@outlook.com

Changes in v2:
- hisi-femac: add statistics related operations
- Link to v1: 
https://lore.kernel.org/r/20240119-net-v1-0-d1feb8e16...@outlook.com

---
Yang Xiwen (5):
  net: hifemac_mdio: use log_msg_ret() correctly, report error by dev_err()
  net: hifemac: fix log reporting
  net: hifemac: register MDIO bus device for subnode
  net: hifemac: implement `net stats` needed ops
  net: hifemac: make some functions static

 drivers/net/hifemac.c  | 229 +
 drivers/net/hifemac_mdio.c |  11 ++-
 2 files changed, 198 insertions(+), 42 deletions(-)
---
base-commit: f7cca7ccc5117eaafcc2bde91ad1bed6fee7cfc3
change-id: 20240119-net-72a32675eeb4

Best regards,
-- 
Yang Xiwen 



[PATCH v3 5/5] net: hifemac: make some functions static

2024-01-22 Thread Yang Xiwen via B4 Relay
From: Yang Xiwen 

They are not required to be global, make them static.

Signed-off-by: Yang Xiwen 
---
 drivers/net/hifemac.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/net/hifemac.c b/drivers/net/hifemac.c
index d24023eefd..90cc247b3b 100644
--- a/drivers/net/hifemac.c
+++ b/drivers/net/hifemac.c
@@ -418,7 +418,7 @@ static void hisi_femac_get_stats(struct udevice *dev, u64 
*data)
}
 }
 
-int hisi_femac_of_to_plat(struct udevice *dev)
+static int hisi_femac_of_to_plat(struct udevice *dev)
 {
int ret, i;
struct hisi_femac_priv *priv = dev_get_priv(dev);
@@ -553,7 +553,7 @@ static int hisi_femac_phy_reset(struct hisi_femac_priv 
*priv)
return 0;
 }
 
-int hisi_femac_probe(struct udevice *dev)
+static int hisi_femac_probe(struct udevice *dev)
 {
struct hisi_femac_priv *priv = dev_get_priv(dev);
int ret, i;

-- 
2.43.0



[PATCH v2 0/4] net: hifemac: a few cleanups

2024-01-21 Thread Yang Xiwen via B4 Relay
Fix the use of log_msg_ret() and add dev_xxx() for error reporting.

Register mdio subnode as a mdio bus device for hifemac.

Implement ops needed by `net stats`

Signed-off-by: Yang Xiwen 
---
Changes in v2:
- hisi-femac: add statistics related operations
- Link to v1: 
https://lore.kernel.org/r/20240119-net-v1-0-d1feb8e16...@outlook.com

---
Yang Xiwen (4):
  net: hifemac_mdio: use log_msg_ret() correctly, report error by dev_err()
  net: hifemac: fix log reporting
  net: hifemac: register MDIO bus device for subnode
  net: hifemac: implement `net stats` needed ops

 drivers/net/hifemac.c  | 225 +
 drivers/net/hifemac_mdio.c |  11 ++-
 2 files changed, 196 insertions(+), 40 deletions(-)
---
base-commit: f7cca7ccc5117eaafcc2bde91ad1bed6fee7cfc3
change-id: 20240119-net-72a32675eeb4

Best regards,
-- 
Yang Xiwen 



[PATCH v2 4/4] net: hifemac: implement `net stats` needed ops

2024-01-21 Thread Yang Xiwen via B4 Relay
From: Yang Xiwen 

3 operations needed by `net stats` are implemented. New `net stats`
output some useful info.

Signed-off-by: Yang Xiwen 
---
 drivers/net/hifemac.c | 87 +++
 1 file changed, 87 insertions(+)

diff --git a/drivers/net/hifemac.c b/drivers/net/hifemac.c
index 39c0233b62..24108bee4b 100644
--- a/drivers/net/hifemac.c
+++ b/drivers/net/hifemac.c
@@ -16,6 +16,8 @@
 #include 
 #include 
 #include 
+#include 
+#include 
 #include 
 #include 
 
@@ -125,6 +127,57 @@ struct hisi_femac_priv {
u32 link_status;
 };
 
+struct hisi_femac_stat_entry {
+   const char *name;
+   u32 offset;
+   u32 mask;
+};
+
+/* please refer to the datasheet for the description of these entries */
+const struct hisi_femac_stat_entry hisi_femac_stats_table[] = {
+   { "rxsof_cnt",  0x584,  GENMASK(31, 28) },
+   { "rxeof_cnt",  0x584,  GENMASK(27, 24) },
+   { "rxcrcok_cnt",0x584,  GENMASK(23, 20) },
+   { "rxcrcbad_cnt",   0x584,  GENMASK(19, 16) },
+   { "txsof_cnt",  0x584,  GENMASK(15, 12) },
+   { "txeof_cnt",  0x584,  GENMASK(11, 8) },
+   { "txcrcok_cnt",0x584,  GENMASK(7, 4) },
+   { "txcrcbad_cnt",   0x584,  GENMASK(3, 0) },
+   { "pkts_cpu",   0x5a0,  GENMASK(15, 0) },
+   { "addr_cpu",   0x5a4,  GENMASK(15, 0) },
+   { "pkts_port",  0x5a8,  GENMASK(15, 0) },
+   { "pkts_cpu2tx",0x5ac,  GENMASK(15, 0) },
+   { "rxdvrise",   0x600,  GENMASK(31, 0) },
+   { "ifinoctets", 0x604,  GENMASK(31, 0) },
+   { "octets_rx",  0x608,  GENMASK(31, 0) },
+   { "local_mac_match",0x60c,  GENMASK(31, 0) },
+   { "pkts",   0x610,  GENMASK(31, 0) },
+   { "broadcastpkts",  0x614,  GENMASK(31, 0) },
+   { "multicastpkts",  0x618,  GENMASK(31, 0) },
+   { "ifinucastpkts",  0x61c,  GENMASK(31, 0) },
+   { "ifinerrors", 0x620,  GENMASK(31, 0) },
+   { "crcerr", 0x624,  GENMASK(31, 0) },
+   { "abnormalsizepkts",   0x628,  GENMASK(31, 0) },
+   { "dot3alignmenterr",   0x62c,  GENMASK(31, 0) },
+   { "dot3pause",  0x630,  GENMASK(31, 0) },
+   { "dropevents", 0x634,  GENMASK(31, 0) },
+   { "flux_frame_cnt", 0x638,  GENMASK(31, 0) },
+   { "flux_drop_cnt",  0x63c,  GENMASK(31, 0) },
+   { "mac_not2cpu_pkts",   0x64c,  GENMASK(31, 0) },
+   { "pkts_tx",0x780,  GENMASK(31, 0) },
+   { "broadcastpkts_tx",   0x784,  GENMASK(31, 0) },
+   { "multicastpkts_tx",   0x788,  GENMASK(31, 0) },
+   { "ifoutucastpkts_tx",  0x78c,  GENMASK(31, 0) },
+   { "octets_tx",  0x790,  GENMASK(31, 0) },
+   { "dot3pause",  0x794,  GENMASK(31, 0) },
+   { "retry_times_tx", 0x798,  GENMASK(31, 0) },
+   { "collisions", 0x79c,  GENMASK(31, 0) },
+   { "dot3latecol",0x7a0,  GENMASK(31, 0) },
+   { "dot3colok",  0x7a4,  GENMASK(31, 0) },
+   { "dot3excessivecol",   0x7a8,  GENMASK(31, 0) },
+   { "dot3colcnt", 0x7ac,  GENMASK(31, 0) },
+};
+
 static void hisi_femac_irq_enable(struct hisi_femac_priv *priv, int irqs)
 {
u32 val;
@@ -334,6 +387,37 @@ static void hisi_femac_stop(struct udevice *dev)
writel(SOFT_RESET_ALL, priv->glb_base + GLB_SOFT_RESET);
 }
 
+static int hisi_femac_get_sset_count(struct udevice *dev)
+{
+   return ARRAY_SIZE(hisi_femac_stats_table);
+}
+
+static void hisi_femac_get_strings(struct udevice *dev, u8 *data)
+{
+   int i;
+
+   for (i = 0; i < ARRAY_SIZE(hisi_femac_stats_table); i++)
+   strcpy(data + i * ETH_GSTRING_LEN, 
hisi_femac_stats_table[i].name);
+}
+
+/* Non-constant mask variant of FIELD_GET/FIELD_PREP */
+#define field_get(_mask, _reg) (((_reg) & (_mask)) >> (ffs(_mask) - 1))
+
+static void hisi_femac_get_stats(struct udevice *dev, u64 *data)
+{
+   int i;
+   u32 mask, reg;
+   struct hisi_femac_priv *priv = dev_get_priv(dev);
+   void __iomem *port_base = priv->port_base;
+
+   for (i = 0; i < ARRAY_SIZE(hisi_femac_stats_table); i++) {
+   mask = hisi_femac_stats_table[i].mask;
+   reg = readl(port_base + hisi_femac_stats_table[i].offset);
+
+   data[i] = field_get(mask, reg);
+   }
+}
+
 int hisi_femac_of_to_plat(struct udevice *dev)
 {
int ret, i;
@@ -523,6 +607,9 @@ static const struct eth_ops hisi_femac_ops = {
.free_pkt   = hisi_femac_free_pkt,
.stop   = hisi_femac_stop,
.write_hwaddr   = hisi_femac_set_hw_mac_addr,
+   .get_sset_count = hisi_femac_get_sset_count,
+   .get_strings= hisi_femac_get_strings,
+   .get_stats  = hisi_femac_get_stats,
 };
 
 static const struct udevice_id hisi_femac_ids[] = {

-- 
2.43.0



[PATCH v2 3/4] net: hifemac: register MDIO bus device for subnode

2024-01-21 Thread Yang Xiwen via B4 Relay
From: Yang Xiwen 

register internal MDIO bus device if it is a subnode.

Signed-off-by: Yang Xiwen 
---
 drivers/net/hifemac.c | 28 
 1 file changed, 28 insertions(+)

diff --git a/drivers/net/hifemac.c b/drivers/net/hifemac.c
index 1088f3eca3..39c0233b62 100644
--- a/drivers/net/hifemac.c
+++ b/drivers/net/hifemac.c
@@ -15,6 +15,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 
@@ -337,6 +338,8 @@ int hisi_femac_of_to_plat(struct udevice *dev)
 {
int ret, i;
struct hisi_femac_priv *priv = dev_get_priv(dev);
+   ofnode mdio_node;
+   bool mdio_registered = false;
static const char * const clk_strs[] = {
[CLK_MAC] = "mac",
[CLK_BUS] = "bus",
@@ -388,6 +391,31 @@ int hisi_femac_of_to_plat(struct udevice *dev)
 MAC_RESET_DELAY_PROPERTY,
 MAC_RESET_ASSERT_PERIOD);
 
+   /* Create MDIO bus */
+   ofnode_for_each_subnode(mdio_node, dev_ofnode(dev)) {
+   const char *subnode_name = ofnode_get_name(mdio_node);
+   struct udevice *mdiodev;
+
+   // Skip subnodes not starting with "mdio"
+   if (strncmp(subnode_name, "mdio", 4))
+   continue;
+
+   ret = device_bind_driver_to_node(dev, "hisi-femac-mdio",
+subnode_name, mdio_node, 
);
+   if (ret) {
+   dev_err(dev, "Failed to register MDIO bus device %d\n", 
ret);
+   return log_msg_ret("net", ret);
+   }
+
+   mdio_registered = true;
+   break;
+   }
+
+   if (!mdio_registered) {
+   dev_err(dev, "No MDIO subnode is found!\n");
+   return log_msg_ret("mdio", -ENODATA);
+   }
+
return 0;
 }
 

-- 
2.43.0



[PATCH v2 2/4] net: hifemac: fix log reporting

2024-01-21 Thread Yang Xiwen via B4 Relay
From: Yang Xiwen 

shrink the first argument of log_msg_ret(), add dev_xxx() functions for
error reporting.

Fixes: 9d8f78a2a79f7 ("net: add hifemac Ethernet driver for HiSilicon platform")

Signed-off-by: Yang Xiwen 
---
 drivers/net/hifemac.c | 110 +-
 1 file changed, 73 insertions(+), 37 deletions(-)

diff --git a/drivers/net/hifemac.c b/drivers/net/hifemac.c
index b61a29e636..1088f3eca3 100644
--- a/drivers/net/hifemac.c
+++ b/drivers/net/hifemac.c
@@ -245,8 +245,10 @@ static int hisi_femac_start(struct udevice *dev)
hisi_femac_rx_refill(priv);
 
ret = phy_startup(priv->phy);
-   if (ret)
-   return log_msg_ret("Failed to startup phy", ret);
+   if (ret) {
+   dev_err(dev, "Failed to startup phy: %d\n", ret);
+   return log_msg_ret("phy", ret);
+   }
 
if (!priv->phy->link) {
debug("%s: link down\n", __func__);
@@ -281,8 +283,10 @@ static int hisi_femac_send(struct udevice *dev, void 
*packet, int length)
 
// wait until FIFO is empty
ret = wait_for_bit_le32(priv->glb_base + GLB_IRQ_RAW, 
IRQ_INT_TX_PER_PACKET, true, 50, false);
-   if (ret == -ETIMEDOUT)
-   return log_msg_ret("FIFO timeout", ret);
+   if (ret == -ETIMEDOUT) {
+   dev_err(dev, "FIFO timeout\n");
+   return log_msg_ret("net", ret);
+   }
 
return 0;
 }
@@ -340,35 +344,45 @@ int hisi_femac_of_to_plat(struct udevice *dev)
};
 
priv->port_base = dev_remap_addr_name(dev, "port");
-   if (IS_ERR(priv->port_base))
-   return log_msg_ret("Failed to remap port address space", 
PTR_ERR(priv->port_base));
+   if (!priv->port_base) {
+   dev_err(dev, "Failed to remap port address space\n");
+   return log_msg_ret("net", -EINVAL);
+   }
 
priv->glb_base = dev_remap_addr_name(dev, "glb");
-   if (IS_ERR(priv->glb_base))
-   return log_msg_ret("Failed to remap global address space", 
PTR_ERR(priv->glb_base));
+   if (IS_ERR(priv->glb_base)) {
+   dev_err(dev, "Failed to remap global address space\n");
+   return log_msg_ret("net", -EINVAL);
+   }
 
for (i = 0; i < ARRAY_SIZE(clk_strs); i++) {
priv->clks[i] = devm_clk_get(dev, clk_strs[i]);
if (IS_ERR(priv->clks[i])) {
dev_err(dev, "Error getting clock %s\n", clk_strs[i]);
-   return log_msg_ret("Failed to get clocks", 
PTR_ERR(priv->clks[i]));
+   return log_msg_ret("clk", PTR_ERR(priv->clks[i]));
}
}
 
priv->mac_rst = devm_reset_control_get(dev, "mac");
-   if (IS_ERR(priv->mac_rst))
-   return log_msg_ret("Failed to get MAC reset", 
PTR_ERR(priv->mac_rst));
+   if (IS_ERR(priv->mac_rst)) {
+   dev_err(dev, "Failed to get MAC reset %ld\n", 
PTR_ERR(priv->mac_rst));
+   return log_msg_ret("rst", PTR_ERR(priv->mac_rst));
+   }
 
priv->phy_rst = devm_reset_control_get(dev, "phy");
-   if (IS_ERR(priv->phy_rst))
-   return log_msg_ret("Failed to get PHY reset", 
PTR_ERR(priv->phy_rst));
+   if (IS_ERR(priv->phy_rst)) {
+   dev_err(dev, "Failed to get PHY reset %ld\n", 
PTR_ERR(priv->phy_rst));
+   return log_msg_ret("rst", PTR_ERR(priv->phy_rst));
+   }
 
ret = dev_read_u32_array(dev,
 PHY_RESET_DELAYS_PROPERTY,
 priv->phy_reset_delays,
 DELAYS_NUM);
-   if (ret < 0)
-   return log_msg_ret("Failed to get PHY reset delays", ret);
+   if (ret < 0) {
+   dev_err(dev, "Failed to get PHY reset delays %d\n", ret);
+   return log_msg_ret("rst", ret);
+   }
 
priv->mac_reset_delay = dev_read_u32_default(dev,
 MAC_RESET_DELAY_PROPERTY,
@@ -385,32 +399,44 @@ static int hisi_femac_phy_reset(struct hisi_femac_priv 
*priv)
 
// Disable MAC clk before phy reset
ret = clk_disable(priv->clks[CLK_MAC]);
-   if (ret < 0)
-   return log_msg_ret("Failed to disable MAC clock", ret);
+   if (ret < 0) {
+   pr_err("%s: Failed to disable MAC clock %d\n", __func__, ret);
+   return log_msg_ret("clk", ret);
+   }
ret = clk_disable(priv->clks[CLK_BUS]);
-   if (ret < 0)
-   return log_msg_ret("Failed to disable bus clock", ret);
+   if (ret < 0) {
+   pr_err("%s: Failed to disable bus clock %d\n", __func__, ret);
+   return log_msg_ret("clk", ret);
+   }
 
udelay(delays[PRE_DELAY]);
 
ret = reset_assert(rst);
-   if (ret < 0)
-   return log_msg_ret("Failed to assert reset", ret);
+   if (ret < 0) {
+   

[PATCH v2 1/4] net: hifemac_mdio: use log_msg_ret() correctly, report error by dev_err()

2024-01-21 Thread Yang Xiwen via B4 Relay
From: Yang Xiwen 

The initial commit used log_msg_ret() wrongly. Fix that by moving error
report to a separate dev_err() call and shrink the first argument of
log_msg_ret() to no more than 4 chars.

Fixes: 6b5c8d98e204 ("net: add hifemac_mdio MDIO bus driver for HiSilicon 
platform")

Signed-off-by: Yang Xiwen 
---
 drivers/net/hifemac_mdio.c | 11 ---
 1 file changed, 8 insertions(+), 3 deletions(-)

diff --git a/drivers/net/hifemac_mdio.c b/drivers/net/hifemac_mdio.c
index 343c5f3a38..0b59d06091 100644
--- a/drivers/net/hifemac_mdio.c
+++ b/drivers/net/hifemac_mdio.c
@@ -8,6 +8,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 
@@ -74,7 +75,8 @@ static int hisi_femac_mdio_of_to_plat(struct udevice *dev)
data->membase = dev_remap_addr(dev);
if (IS_ERR(data->membase)) {
ret = PTR_ERR(data->membase);
-   return log_msg_ret("Failed to remap base addr", ret);
+   dev_err(dev, "Failed to remap base addr %d\n", ret);
+   return log_msg_ret("mdio", ret);
}
 
// clk is optional
@@ -89,8 +91,10 @@ static int hisi_femac_mdio_probe(struct udevice *dev)
int ret;
 
ret = clk_prepare_enable(data->clk);
-   if (ret)
-   return log_msg_ret("Failed to enable clk", ret);
+   if (ret) {
+   dev_err(dev, "Failed to enable clock: %d\n", ret);
+   return log_msg_ret("clk", ret);
+   }
 
return 0;
 }
@@ -112,5 +116,6 @@ U_BOOT_DRIVER(hisi_femac_mdio_driver) = {
.of_to_plat = hisi_femac_mdio_of_to_plat,
.probe = hisi_femac_mdio_probe,
.ops = _femac_mdio_ops,
+   .plat_auto = sizeof(struct mdio_perdev_priv),
.priv_auto = sizeof(struct hisi_femac_mdio_data),
 };

-- 
2.43.0



[PATCH RFC 2/2] clk: add clock framework for HiSilicon SoCs

2024-01-19 Thread Yang Xiwen via B4 Relay
From: Yang Xiwen 

Hi3798 Series SoCs have a CRG (Clock Reset Generator) module which
manages all clocks and resets of the SoC.

The first supported chip is Hi3798MV200.  The unused clocks are not
registered to save space and time. Only necessary clocks are
implemented right now.

Signed-off-by: Yang Xiwen 
---
 drivers/clk/Kconfig |   7 ++
 drivers/clk/Makefile|   1 +
 drivers/clk/hisilicon/Kconfig   |  14 +++
 drivers/clk/hisilicon/Makefile  |   8 ++
 drivers/clk/hisilicon/clk-hi3798mv200.c | 213 
 drivers/clk/hisilicon/clk.c | 102 +++
 drivers/clk/hisilicon/clk.h |  55 +
 include/dt-bindings/clock/histb-clock.h |   4 +
 8 files changed, 404 insertions(+)

diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index 017dd260a5..4c5ac46b26 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -127,6 +127,12 @@ config CLK_ICS8N3QV01
  Crystal Oscillator). The output frequency can be programmed via an
  I2C interface.
 
+config CLK_HISI
+   bool "Enable Hisilicon Clock Framework"
+   depends on CLK && CLK_CCF
+   help
+ Support for Hisilicon Clock Framework.
+
 config CLK_INTEL
bool "Enable clock driver for Intel x86"
depends on CLK && X86
@@ -249,6 +255,7 @@ config CLK_ZYNQMP
 source "drivers/clk/analogbits/Kconfig"
 source "drivers/clk/at91/Kconfig"
 source "drivers/clk/exynos/Kconfig"
+source "drivers/clk/hisilicon/Kconfig"
 source "drivers/clk/imx/Kconfig"
 source "drivers/clk/meson/Kconfig"
 source "drivers/clk/microchip/Kconfig"
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index 638ad04bae..90e7e1b5f4 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -32,6 +32,7 @@ obj-$(CONFIG_CLK_BCM6345) += clk_bcm6345.o
 obj-$(CONFIG_CLK_BOSTON) += clk_boston.o
 obj-$(CONFIG_CLK_CDCE9XX) += clk-cdce9xx.o
 obj-$(CONFIG_CLK_EXYNOS) += exynos/
+obj-$(CONFIG_CLK_HISI) += hisilicon/
 obj-$(CONFIG_CLK_HSDK) += clk-hsdk-cgu.o
 obj-$(CONFIG_CLK_K210) += clk_k210.o
 obj-$(CONFIG_CLK_MPC83XX) += mpc83xx_clk.o
diff --git a/drivers/clk/hisilicon/Kconfig b/drivers/clk/hisilicon/Kconfig
new file mode 100644
index 00..caa51b7831
--- /dev/null
+++ b/drivers/clk/hisilicon/Kconfig
@@ -0,0 +1,14 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
+if CLK_HISI
+menu "HiSilicon CRG Driver"
+
+config COMMON_CLK_HI3798MV200
+   tristate "Hi3798MV200 CRG Driver"
+   select RESET_HISILICON
+   depends on ARCH_HISTB
+   help
+ Build the CRG driver for Hi3798MV200.
+
+endmenu
+endif
diff --git a/drivers/clk/hisilicon/Makefile b/drivers/clk/hisilicon/Makefile
new file mode 100644
index 00..85a0ffb4a1
--- /dev/null
+++ b/drivers/clk/hisilicon/Makefile
@@ -0,0 +1,8 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# Hisilicon Clock specific Makefile
+#
+
+obj-y  += clk.o
+
+obj-$(CONFIG_COMMON_CLK_HI3798MV200)   += clk-hi3798mv200.o
diff --git a/drivers/clk/hisilicon/clk-hi3798mv200.c 
b/drivers/clk/hisilicon/clk-hi3798mv200.c
new file mode 100644
index 00..01bb20d940
--- /dev/null
+++ b/drivers/clk/hisilicon/clk-hi3798mv200.c
@@ -0,0 +1,213 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Hi3798MV200 Clock and Reset Generator Driver.
+ * Adapted from clk-hi3798cv200.c.
+ *
+ * Copyright (c) 2024 Yang Xiwen 
+ * Copyright (c) 2016 HiSilicon Technologies Co., Ltd.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "clk.h"
+
+/* hi3798MV200 core CRG */
+#define HI3798MV200_INNER_CLK_OFFSET   64
+#define HI3798MV200_FIXED_12M  65
+#define HI3798MV200_FIXED_24M  66
+#define HI3798MV200_FIXED_25M  67
+#define HI3798MV200_FIXED_27M  68
+#define HI3798MV200_FIXED_48M  69
+#define HI3798MV200_FIXED_50M  70
+#define HI3798MV200_FIXED_54M  71
+#define HI3798MV200_FIXED_60M  72
+#define HI3798MV200_FIXED_75M  73
+#define HI3798MV200_FIXED_100M 74
+#define HI3798MV200_FIXED_150M 75
+#define HI3798MV200_FIXED_166P5M   76
+#define HI3798MV200_FIXED_200M 77
+#define HI3798MV200_FIXED_250M 78
+#define HI3798MV200_FIXED_300M 79
+#define HI3798MV200_FIXED_400M 80
+#define HI3798MV200_MMC_MUX81
+#define HI3798MV200_COMBPHY1_MUX   82
+#define HI3798MV200_SDIO0_MUX  83
+#define HI3798MV200_COMBPHY0_MUX   84
+#define HI3798MV200_SDIO1_MUX  85
+#define HI3798MV200_ETH_MUX86
+
+static const struct hisi_fixed_rate_clock hi3798mv200_fixed_rate_clks[] = {
+   { HISTB_OSC_CLK, "clk_osc", 2400, },
+   { HISTB_APB_CLK, "clk_apb", 1, },
+   { HISTB_AHB_CLK, "clk_ahb", 2, },
+   { HI3798MV200_FIXED_12M, "12m", 

[PATCH RFC 0/2] clk: add HiSilicon CLK framework

2024-01-19 Thread Yang Xiwen via B4 Relay
The first supported chip is Hi3798MV200.

Signed-off-by: Yang Xiwen 
---
Yang Xiwen (2):
  clk: ccf: Export clk_register_mux_table() in linux/clk-provider.h
  clk: add clock framework for HiSilicon SoCs

 drivers/clk/Kconfig |   7 ++
 drivers/clk/Makefile|   1 +
 drivers/clk/hisilicon/Kconfig   |  14 +++
 drivers/clk/hisilicon/Makefile  |   8 ++
 drivers/clk/hisilicon/clk-hi3798mv200.c | 213 
 drivers/clk/hisilicon/clk.c | 102 +++
 drivers/clk/hisilicon/clk.h |  55 +
 include/dt-bindings/clock/histb-clock.h |   4 +
 include/linux/clk-provider.h|   6 +
 9 files changed, 410 insertions(+)
---
base-commit: f7cca7ccc5117eaafcc2bde91ad1bed6fee7cfc3
change-id: 20240119-b4-hisi-clk-88075b46c359

Best regards,
-- 
Yang Xiwen 



[PATCH RFC 1/2] clk: ccf: Export clk_register_mux_table() in linux/clk-provider.h

2024-01-19 Thread Yang Xiwen via B4 Relay
From: Yang Xiwen 

This function is used by HiSilicon Clock Framework.

Signed-off-by: Yang Xiwen 
---
 include/linux/clk-provider.h | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index b8acacd49e..952439ad39 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -247,6 +247,12 @@ struct clk *clk_register_mux(struct device *dev, const 
char *name,
void __iomem *reg, u8 shift, u8 width,
u8 clk_mux_flags);
 
+struct clk *clk_register_mux_table(struct device *dev, const char *name,
+   const char * const *parent_names, u8 num_parents,
+   unsigned long flags,
+   void __iomem *reg, u8 shift, u32 mask,
+   u8 clk_mux_flags, u32 *table);
+
 struct clk *clk_register_fixed_rate(struct device *dev, const char *name,
ulong rate);
 

-- 
2.43.0



[PATCH RFC 2/2] clk: add clock framework for HiSilicon SoCs

2024-01-19 Thread Yang Xiwen via B4 Relay
From: Yang Xiwen 

Hi3798 Series SoCs have a CRG (Clock Reset Generator) module which
manages all clocks and resets of the SoC.

The first supported chip is Hi3798MV200.  The unused clocks are not
registered to save space and time. Only necessary clocks are
implemented right now.

Signed-off-by: Yang Xiwen 
---
 drivers/clk/Kconfig |   7 ++
 drivers/clk/Makefile|   1 +
 drivers/clk/hisilicon/Kconfig   |  14 +++
 drivers/clk/hisilicon/Makefile  |   8 ++
 drivers/clk/hisilicon/clk-hi3798mv200.c | 213 
 drivers/clk/hisilicon/clk.c | 102 +++
 drivers/clk/hisilicon/clk.h |  55 +
 include/dt-bindings/clock/histb-clock.h |   4 +
 8 files changed, 404 insertions(+)

diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index 017dd260a5..4c5ac46b26 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -127,6 +127,12 @@ config CLK_ICS8N3QV01
  Crystal Oscillator). The output frequency can be programmed via an
  I2C interface.
 
+config CLK_HISI
+   bool "Enable Hisilicon Clock Framework"
+   depends on CLK && CLK_CCF
+   help
+ Support for Hisilicon Clock Framework.
+
 config CLK_INTEL
bool "Enable clock driver for Intel x86"
depends on CLK && X86
@@ -249,6 +255,7 @@ config CLK_ZYNQMP
 source "drivers/clk/analogbits/Kconfig"
 source "drivers/clk/at91/Kconfig"
 source "drivers/clk/exynos/Kconfig"
+source "drivers/clk/hisilicon/Kconfig"
 source "drivers/clk/imx/Kconfig"
 source "drivers/clk/meson/Kconfig"
 source "drivers/clk/microchip/Kconfig"
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index 638ad04bae..90e7e1b5f4 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -32,6 +32,7 @@ obj-$(CONFIG_CLK_BCM6345) += clk_bcm6345.o
 obj-$(CONFIG_CLK_BOSTON) += clk_boston.o
 obj-$(CONFIG_CLK_CDCE9XX) += clk-cdce9xx.o
 obj-$(CONFIG_CLK_EXYNOS) += exynos/
+obj-$(CONFIG_CLK_HISI) += hisilicon/
 obj-$(CONFIG_CLK_HSDK) += clk-hsdk-cgu.o
 obj-$(CONFIG_CLK_K210) += clk_k210.o
 obj-$(CONFIG_CLK_MPC83XX) += mpc83xx_clk.o
diff --git a/drivers/clk/hisilicon/Kconfig b/drivers/clk/hisilicon/Kconfig
new file mode 100644
index 00..caa51b7831
--- /dev/null
+++ b/drivers/clk/hisilicon/Kconfig
@@ -0,0 +1,14 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
+if CLK_HISI
+menu "HiSilicon CRG Driver"
+
+config COMMON_CLK_HI3798MV200
+   tristate "Hi3798MV200 CRG Driver"
+   select RESET_HISILICON
+   depends on ARCH_HISTB
+   help
+ Build the CRG driver for Hi3798MV200.
+
+endmenu
+endif
diff --git a/drivers/clk/hisilicon/Makefile b/drivers/clk/hisilicon/Makefile
new file mode 100644
index 00..85a0ffb4a1
--- /dev/null
+++ b/drivers/clk/hisilicon/Makefile
@@ -0,0 +1,8 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# Hisilicon Clock specific Makefile
+#
+
+obj-y  += clk.o
+
+obj-$(CONFIG_COMMON_CLK_HI3798MV200)   += clk-hi3798mv200.o
diff --git a/drivers/clk/hisilicon/clk-hi3798mv200.c 
b/drivers/clk/hisilicon/clk-hi3798mv200.c
new file mode 100644
index 00..01bb20d940
--- /dev/null
+++ b/drivers/clk/hisilicon/clk-hi3798mv200.c
@@ -0,0 +1,213 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Hi3798MV200 Clock and Reset Generator Driver.
+ * Adapted from clk-hi3798cv200.c.
+ *
+ * Copyright (c) 2024 Yang Xiwen 
+ * Copyright (c) 2016 HiSilicon Technologies Co., Ltd.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "clk.h"
+
+/* hi3798MV200 core CRG */
+#define HI3798MV200_INNER_CLK_OFFSET   64
+#define HI3798MV200_FIXED_12M  65
+#define HI3798MV200_FIXED_24M  66
+#define HI3798MV200_FIXED_25M  67
+#define HI3798MV200_FIXED_27M  68
+#define HI3798MV200_FIXED_48M  69
+#define HI3798MV200_FIXED_50M  70
+#define HI3798MV200_FIXED_54M  71
+#define HI3798MV200_FIXED_60M  72
+#define HI3798MV200_FIXED_75M  73
+#define HI3798MV200_FIXED_100M 74
+#define HI3798MV200_FIXED_150M 75
+#define HI3798MV200_FIXED_166P5M   76
+#define HI3798MV200_FIXED_200M 77
+#define HI3798MV200_FIXED_250M 78
+#define HI3798MV200_FIXED_300M 79
+#define HI3798MV200_FIXED_400M 80
+#define HI3798MV200_MMC_MUX81
+#define HI3798MV200_COMBPHY1_MUX   82
+#define HI3798MV200_SDIO0_MUX  83
+#define HI3798MV200_COMBPHY0_MUX   84
+#define HI3798MV200_SDIO1_MUX  85
+#define HI3798MV200_ETH_MUX86
+
+static const struct hisi_fixed_rate_clock hi3798mv200_fixed_rate_clks[] = {
+   { HISTB_OSC_CLK, "clk_osc", 2400, },
+   { HISTB_APB_CLK, "clk_apb", 1, },
+   { HISTB_AHB_CLK, "clk_ahb", 2, },
+   { HI3798MV200_FIXED_12M, "12m", 

[PATCH RFC 0/2] clk: add HiSilicon CLK framework

2024-01-19 Thread Yang Xiwen via B4 Relay
The first supported chip is Hi3798MV200.

Signed-off-by: Yang Xiwen 
---
Yang Xiwen (2):
  clk: ccf: Export clk_register_mux_table() in linux/clk-provider.h
  clk: add clock framework for HiSilicon SoCs

 drivers/clk/Kconfig |   7 ++
 drivers/clk/Makefile|   1 +
 drivers/clk/hisilicon/Kconfig   |  14 +++
 drivers/clk/hisilicon/Makefile  |   8 ++
 drivers/clk/hisilicon/clk-hi3798mv200.c | 213 
 drivers/clk/hisilicon/clk.c | 102 +++
 drivers/clk/hisilicon/clk.h |  55 +
 include/dt-bindings/clock/histb-clock.h |   4 +
 include/linux/clk-provider.h|   6 +
 9 files changed, 410 insertions(+)
---
base-commit: f7cca7ccc5117eaafcc2bde91ad1bed6fee7cfc3
change-id: 20240119-b4-hisi-clk-88075b46c359

Best regards,
-- 
Yang Xiwen 



[PATCH RFC 1/2] clk: ccf: Export clk_register_mux_table() in linux/clk-provider.h

2024-01-19 Thread Yang Xiwen via B4 Relay
From: Yang Xiwen 

This function is used by HiSilicon Clock Framework.

Signed-off-by: Yang Xiwen 
---
 include/linux/clk-provider.h | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index b8acacd49e..952439ad39 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -247,6 +247,12 @@ struct clk *clk_register_mux(struct device *dev, const 
char *name,
void __iomem *reg, u8 shift, u8 width,
u8 clk_mux_flags);
 
+struct clk *clk_register_mux_table(struct device *dev, const char *name,
+   const char * const *parent_names, u8 num_parents,
+   unsigned long flags,
+   void __iomem *reg, u8 shift, u32 mask,
+   u8 clk_mux_flags, u32 *table);
+
 struct clk *clk_register_fixed_rate(struct device *dev, const char *name,
ulong rate);
 

-- 
2.43.0



[PATCH] reset: reset-hisilicon: also handle #reset-cells = <2>

2024-01-19 Thread Yang Xiwen via B4 Relay
From: Yang Xiwen 

It's also valid to have #reset-cells = <2> while the third arg defaults
to ASSERT_SET.

Signed-off-by: Yang Xiwen 
---
 drivers/reset/reset-hisilicon.c | 15 +--
 1 file changed, 13 insertions(+), 2 deletions(-)

diff --git a/drivers/reset/reset-hisilicon.c b/drivers/reset/reset-hisilicon.c
index 8152cec227..85e02b296b 100644
--- a/drivers/reset/reset-hisilicon.c
+++ b/drivers/reset/reset-hisilicon.c
@@ -49,7 +49,18 @@ static int hisi_reset_assert(struct reset_ctl *rst)
 static int hisi_reset_of_xlate(struct reset_ctl *rst,
   struct ofnode_phandle_args *args)
 {
-   if (args->args_count != 3) {
+   unsigned long polarity;
+
+   switch (args->args_count) {
+   case 2:
+   polarity = ASSERT_SET;
+   break;
+
+   case 3:
+   polarity = args->args[2];
+   break;
+
+   default:
debug("Invalid args_count: %d\n", args->args_count);
return -EINVAL;
}
@@ -57,7 +68,7 @@ static int hisi_reset_of_xlate(struct reset_ctl *rst,
/* Use .data field as register offset and .id field as bit shift */
rst->data = args->args[0];
rst->id = args->args[1];
-   rst->polarity = args->args[2];
+   rst->polarity = polarity;
 
return 0;
 }

---
base-commit: f7cca7ccc5117eaafcc2bde91ad1bed6fee7cfc3
change-id: 20240119-rst-0bc8097b847a

Best regards,
-- 
Yang Xiwen 



[PATCH 0/3] net: hifemac: a few cleanups

2024-01-19 Thread Yang Xiwen via B4 Relay
Fix the use of log_msg_ret() and add dev_xxx() for error reporting.

Register mdio subnode as a mdio bus device for hifemac.

Signed-off-by: Yang Xiwen 
---
Yang Xiwen (3):
  net: hifemac_mdio: use log_msg_ret() correctly, report error by dev_err()
  net: hifemac: fix log reporting
  net: hifemac: register MDIO bus device for subnode

 drivers/net/hifemac.c  | 138 +
 drivers/net/hifemac_mdio.c |  11 +++-
 2 files changed, 109 insertions(+), 40 deletions(-)
---
base-commit: f7cca7ccc5117eaafcc2bde91ad1bed6fee7cfc3
change-id: 20240119-net-72a32675eeb4

Best regards,
-- 
Yang Xiwen 



[PATCH 3/3] net: hifemac: register MDIO bus device for subnode

2024-01-19 Thread Yang Xiwen via B4 Relay
From: Yang Xiwen 

register internal MDIO bus device if it is a subnode.

Signed-off-by: Yang Xiwen 
---
 drivers/net/hifemac.c | 28 
 1 file changed, 28 insertions(+)

diff --git a/drivers/net/hifemac.c b/drivers/net/hifemac.c
index 1088f3eca3..39c0233b62 100644
--- a/drivers/net/hifemac.c
+++ b/drivers/net/hifemac.c
@@ -15,6 +15,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 
@@ -337,6 +338,8 @@ int hisi_femac_of_to_plat(struct udevice *dev)
 {
int ret, i;
struct hisi_femac_priv *priv = dev_get_priv(dev);
+   ofnode mdio_node;
+   bool mdio_registered = false;
static const char * const clk_strs[] = {
[CLK_MAC] = "mac",
[CLK_BUS] = "bus",
@@ -388,6 +391,31 @@ int hisi_femac_of_to_plat(struct udevice *dev)
 MAC_RESET_DELAY_PROPERTY,
 MAC_RESET_ASSERT_PERIOD);
 
+   /* Create MDIO bus */
+   ofnode_for_each_subnode(mdio_node, dev_ofnode(dev)) {
+   const char *subnode_name = ofnode_get_name(mdio_node);
+   struct udevice *mdiodev;
+
+   // Skip subnodes not starting with "mdio"
+   if (strncmp(subnode_name, "mdio", 4))
+   continue;
+
+   ret = device_bind_driver_to_node(dev, "hisi-femac-mdio",
+subnode_name, mdio_node, 
);
+   if (ret) {
+   dev_err(dev, "Failed to register MDIO bus device %d\n", 
ret);
+   return log_msg_ret("net", ret);
+   }
+
+   mdio_registered = true;
+   break;
+   }
+
+   if (!mdio_registered) {
+   dev_err(dev, "No MDIO subnode is found!\n");
+   return log_msg_ret("mdio", -ENODATA);
+   }
+
return 0;
 }
 

-- 
2.43.0



[PATCH 2/3] net: hifemac: fix log reporting

2024-01-19 Thread Yang Xiwen via B4 Relay
From: Yang Xiwen 

shrink the first argument of log_msg_ret(), add dev_xxx() functions for
error reporting.

Fixes: 9d8f78a2a79f7 ("net: add hifemac Ethernet driver for HiSilicon platform")

Signed-off-by: Yang Xiwen 
---
 drivers/net/hifemac.c | 110 +-
 1 file changed, 73 insertions(+), 37 deletions(-)

diff --git a/drivers/net/hifemac.c b/drivers/net/hifemac.c
index b61a29e636..1088f3eca3 100644
--- a/drivers/net/hifemac.c
+++ b/drivers/net/hifemac.c
@@ -245,8 +245,10 @@ static int hisi_femac_start(struct udevice *dev)
hisi_femac_rx_refill(priv);
 
ret = phy_startup(priv->phy);
-   if (ret)
-   return log_msg_ret("Failed to startup phy", ret);
+   if (ret) {
+   dev_err(dev, "Failed to startup phy: %d\n", ret);
+   return log_msg_ret("phy", ret);
+   }
 
if (!priv->phy->link) {
debug("%s: link down\n", __func__);
@@ -281,8 +283,10 @@ static int hisi_femac_send(struct udevice *dev, void 
*packet, int length)
 
// wait until FIFO is empty
ret = wait_for_bit_le32(priv->glb_base + GLB_IRQ_RAW, 
IRQ_INT_TX_PER_PACKET, true, 50, false);
-   if (ret == -ETIMEDOUT)
-   return log_msg_ret("FIFO timeout", ret);
+   if (ret == -ETIMEDOUT) {
+   dev_err(dev, "FIFO timeout\n");
+   return log_msg_ret("net", ret);
+   }
 
return 0;
 }
@@ -340,35 +344,45 @@ int hisi_femac_of_to_plat(struct udevice *dev)
};
 
priv->port_base = dev_remap_addr_name(dev, "port");
-   if (IS_ERR(priv->port_base))
-   return log_msg_ret("Failed to remap port address space", 
PTR_ERR(priv->port_base));
+   if (!priv->port_base) {
+   dev_err(dev, "Failed to remap port address space\n");
+   return log_msg_ret("net", -EINVAL);
+   }
 
priv->glb_base = dev_remap_addr_name(dev, "glb");
-   if (IS_ERR(priv->glb_base))
-   return log_msg_ret("Failed to remap global address space", 
PTR_ERR(priv->glb_base));
+   if (IS_ERR(priv->glb_base)) {
+   dev_err(dev, "Failed to remap global address space\n");
+   return log_msg_ret("net", -EINVAL);
+   }
 
for (i = 0; i < ARRAY_SIZE(clk_strs); i++) {
priv->clks[i] = devm_clk_get(dev, clk_strs[i]);
if (IS_ERR(priv->clks[i])) {
dev_err(dev, "Error getting clock %s\n", clk_strs[i]);
-   return log_msg_ret("Failed to get clocks", 
PTR_ERR(priv->clks[i]));
+   return log_msg_ret("clk", PTR_ERR(priv->clks[i]));
}
}
 
priv->mac_rst = devm_reset_control_get(dev, "mac");
-   if (IS_ERR(priv->mac_rst))
-   return log_msg_ret("Failed to get MAC reset", 
PTR_ERR(priv->mac_rst));
+   if (IS_ERR(priv->mac_rst)) {
+   dev_err(dev, "Failed to get MAC reset %ld\n", 
PTR_ERR(priv->mac_rst));
+   return log_msg_ret("rst", PTR_ERR(priv->mac_rst));
+   }
 
priv->phy_rst = devm_reset_control_get(dev, "phy");
-   if (IS_ERR(priv->phy_rst))
-   return log_msg_ret("Failed to get PHY reset", 
PTR_ERR(priv->phy_rst));
+   if (IS_ERR(priv->phy_rst)) {
+   dev_err(dev, "Failed to get PHY reset %ld\n", 
PTR_ERR(priv->phy_rst));
+   return log_msg_ret("rst", PTR_ERR(priv->phy_rst));
+   }
 
ret = dev_read_u32_array(dev,
 PHY_RESET_DELAYS_PROPERTY,
 priv->phy_reset_delays,
 DELAYS_NUM);
-   if (ret < 0)
-   return log_msg_ret("Failed to get PHY reset delays", ret);
+   if (ret < 0) {
+   dev_err(dev, "Failed to get PHY reset delays %d\n", ret);
+   return log_msg_ret("rst", ret);
+   }
 
priv->mac_reset_delay = dev_read_u32_default(dev,
 MAC_RESET_DELAY_PROPERTY,
@@ -385,32 +399,44 @@ static int hisi_femac_phy_reset(struct hisi_femac_priv 
*priv)
 
// Disable MAC clk before phy reset
ret = clk_disable(priv->clks[CLK_MAC]);
-   if (ret < 0)
-   return log_msg_ret("Failed to disable MAC clock", ret);
+   if (ret < 0) {
+   pr_err("%s: Failed to disable MAC clock %d\n", __func__, ret);
+   return log_msg_ret("clk", ret);
+   }
ret = clk_disable(priv->clks[CLK_BUS]);
-   if (ret < 0)
-   return log_msg_ret("Failed to disable bus clock", ret);
+   if (ret < 0) {
+   pr_err("%s: Failed to disable bus clock %d\n", __func__, ret);
+   return log_msg_ret("clk", ret);
+   }
 
udelay(delays[PRE_DELAY]);
 
ret = reset_assert(rst);
-   if (ret < 0)
-   return log_msg_ret("Failed to assert reset", ret);
+   if (ret < 0) {
+   

[PATCH 1/3] net: hifemac_mdio: use log_msg_ret() correctly, report error by dev_err()

2024-01-19 Thread Yang Xiwen via B4 Relay
From: Yang Xiwen 

The initial commit used log_msg_ret() wrongly. Fix that by moving error
report to a separate dev_err() call and shrink the first argument of
log_msg_ret() to no more than 4 chars.

Fixes: 6b5c8d98e204 ("net: add hifemac_mdio MDIO bus driver for HiSilicon 
platform")

Signed-off-by: Yang Xiwen 
---
 drivers/net/hifemac_mdio.c | 11 ---
 1 file changed, 8 insertions(+), 3 deletions(-)

diff --git a/drivers/net/hifemac_mdio.c b/drivers/net/hifemac_mdio.c
index 343c5f3a38..0b59d06091 100644
--- a/drivers/net/hifemac_mdio.c
+++ b/drivers/net/hifemac_mdio.c
@@ -8,6 +8,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 
@@ -74,7 +75,8 @@ static int hisi_femac_mdio_of_to_plat(struct udevice *dev)
data->membase = dev_remap_addr(dev);
if (IS_ERR(data->membase)) {
ret = PTR_ERR(data->membase);
-   return log_msg_ret("Failed to remap base addr", ret);
+   dev_err(dev, "Failed to remap base addr %d\n", ret);
+   return log_msg_ret("mdio", ret);
}
 
// clk is optional
@@ -89,8 +91,10 @@ static int hisi_femac_mdio_probe(struct udevice *dev)
int ret;
 
ret = clk_prepare_enable(data->clk);
-   if (ret)
-   return log_msg_ret("Failed to enable clk", ret);
+   if (ret) {
+   dev_err(dev, "Failed to enable clock: %d\n", ret);
+   return log_msg_ret("clk", ret);
+   }
 
return 0;
 }
@@ -112,5 +116,6 @@ U_BOOT_DRIVER(hisi_femac_mdio_driver) = {
.of_to_plat = hisi_femac_mdio_of_to_plat,
.probe = hisi_femac_mdio_probe,
.ops = _femac_mdio_ops,
+   .plat_auto = sizeof(struct mdio_perdev_priv),
.priv_auto = sizeof(struct hisi_femac_mdio_data),
 };

-- 
2.43.0



[PATCH] mmc: hi6220-dwmmc: handle clocks and resets if CONFIG_CLK and CONFIG_DM_RESET enabled

2024-01-19 Thread Yang Xiwen via B4 Relay
From: Yang Xiwen 

This can avoid hardcoding a clock rate in driver. Also can enable the
clocks and deassert the resets if the pre-bootloader does not do this
for us.

Currently only enabled for Hi3798MV200.

Signed-off-by: Yang Xiwen 
---
 drivers/mmc/hi6220_dw_mmc.c | 61 -
 1 file changed, 60 insertions(+), 1 deletion(-)

diff --git a/drivers/mmc/hi6220_dw_mmc.c b/drivers/mmc/hi6220_dw_mmc.c
index 71962cd47e..a4b8072976 100644
--- a/drivers/mmc/hi6220_dw_mmc.c
+++ b/drivers/mmc/hi6220_dw_mmc.c
@@ -5,15 +5,24 @@
  */
 
 #include 
+#include 
 #include 
 #include 
 #include 
 #include 
 #include 
+#include 
 #include 
+#include 
 
 DECLARE_GLOBAL_DATA_PTR;
 
+enum hi6220_dwmmc_clk_type {
+   HI6220_DWMMC_CLK_BIU,
+   HI6220_DWMMC_CLK_CIU,
+   HI6220_DWMMC_CLK_CNT,
+};
+
 struct hi6220_dwmmc_plat {
struct mmc_config cfg;
struct mmc mmc;
@@ -21,6 +30,8 @@ struct hi6220_dwmmc_plat {
 
 struct hi6220_dwmmc_priv_data {
struct dwmci_host host;
+   struct clk *clks[HI6220_DWMMC_CLK_CNT];
+   struct reset_ctl_bulk rsts;
 };
 
 struct hisi_mmc_data {
@@ -32,7 +43,29 @@ static int hi6220_dwmmc_of_to_plat(struct udevice *dev)
 {
struct hi6220_dwmmc_priv_data *priv = dev_get_priv(dev);
struct dwmci_host *host = >host;
+   int ret;
 
+   if (CONFIG_IS_ENABLED(CLK) && CONFIG_IS_ENABLED(DM_RESET)) {
+   priv->clks[HI6220_DWMMC_CLK_BIU] = devm_clk_get(dev, "biu");
+   if (IS_ERR(priv->clks[HI6220_DWMMC_CLK_BIU])) {
+   ret = PTR_ERR(priv->clks[HI6220_DWMMC_CLK_BIU]);
+   dev_err(dev, "Failed to get BIU clock(ret = %d).\n", 
ret);
+   return log_msg_ret("clk", ret);
+   }
+
+   priv->clks[HI6220_DWMMC_CLK_CIU] = devm_clk_get(dev, "ciu");
+   if (IS_ERR(priv->clks[HI6220_DWMMC_CLK_CIU])) {
+   ret = PTR_ERR(priv->clks[HI6220_DWMMC_CLK_CIU]);
+   dev_err(dev, "Failed to get CIU clock(ret = %d).\n", 
ret);
+   return log_msg_ret("clk", ret);
+   }
+
+   ret = reset_get_bulk(dev, >rsts);
+   if (ret) {
+   dev_err(dev, "Failed to get resets(ret = %d)", ret);
+   return log_msg_ret("rst", ret);
+   }
+   }
host->name = dev->name;
host->ioaddr = dev_read_addr_ptr(dev);
host->buswidth = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev),
@@ -56,11 +89,37 @@ static int hi6220_dwmmc_probe(struct udevice *dev)
struct hi6220_dwmmc_priv_data *priv = dev_get_priv(dev);
struct dwmci_host *host = >host;
struct hisi_mmc_data *mmc_data;
+   int ret;
 
mmc_data = (struct hisi_mmc_data *)dev_get_driver_data(dev);
 
-   /* Use default bus speed due to absence of clk driver */
host->bus_hz = mmc_data->clock;
+   if (CONFIG_IS_ENABLED(CLK) && CONFIG_IS_ENABLED(DM_RESET)) {
+   ret = clk_prepare_enable(priv->clks[HI6220_DWMMC_CLK_BIU]);
+   if (ret) {
+   dev_err(dev, "Failed to enable biu clock(ret = %d).\n", 
ret);
+   return log_msg_ret("clk", ret);
+   }
+
+   ret = clk_prepare_enable(priv->clks[HI6220_DWMMC_CLK_CIU]);
+   if (ret) {
+   dev_err(dev, "Failed to enable ciu clock(ret = %d).\n", 
ret);
+   return log_msg_ret("clk", ret);
+   }
+
+   ret = reset_deassert_bulk(>rsts);
+   if (ret) {
+   dev_err(dev, "Failed to deassert resets(ret = %d).\n", 
ret);
+   return log_msg_ret("rst", ret);
+   }
+
+   host->bus_hz = clk_get_rate(priv->clks[HI6220_DWMMC_CLK_CIU]);
+   if (host->bus_hz <= 0) {
+   dev_err(dev, "Failed to get ciu clock rate(ret = 
%d).\n", ret);
+   return log_msg_ret("clk", ret);
+   }
+   }
+   dev_dbg(dev, "bus clock rate: %d.\n", host->bus_hz);
 
dwmci_setup_cfg(>cfg, host, host->bus_hz, 40);
host->mmc = >mmc;

---
base-commit: f7cca7ccc5117eaafcc2bde91ad1bed6fee7cfc3
change-id: 20240119-mmc-9cf7f3455cb4

Best regards,
-- 
Yang Xiwen 



[PATCH] wdt: add HiSilicon watchdog driver support

2024-01-18 Thread Yang Xiwen via B4 Relay
From: Yang Xiwen 

This watchdog core is found on many HiSilicon SoCs. Add support for it.

Signed-off-by: Yang Xiwen 
---
 drivers/watchdog/Kconfig|  10 +++
 drivers/watchdog/Makefile   |   1 +
 drivers/watchdog/hisi_wdt.c | 196 
 3 files changed, 207 insertions(+)

diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index 569726119c..ddf44f63d2 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -32,6 +32,7 @@ config WATCHDOG_TIMEOUT_MSECS
default 16000 if ARCH_SUNXI
default 5376 if ULP_WATCHDOG
default 15000 if ARCH_BCM283X
+   range 500 18 if ARCH_HISI
default 6
help
  Watchdog timeout in msec
@@ -171,6 +172,15 @@ config WDT_GPIO
  doc/device-tree-bindings/watchdog/gpio-wdt.txt for
  information on how to describe the watchdog in device tree.
 
+config WDT_HISI
+   bool "HiSilicon watchdog timer support"
+   depends on WDT
+   depends on CLK && DM_RESET
+   imply WATCHDOG
+   help
+ Select this to enable HiSilicon watchdog timer.
+ Currently supports Hi3798MV200 only.
+
 config WDT_MAX6370
bool "MAX6370 watchdog timer support"
depends on WDT
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
index 5520d3d9ae..3436aa6389 100644
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -30,6 +30,7 @@ obj-$(CONFIG_WDT_ORION) += orion_wdt.o
 obj-$(CONFIG_WDT_CDNS) += cdns_wdt.o
 obj-$(CONFIG_WDT_FTWDT010) += ftwdt010_wdt.o
 obj-$(CONFIG_WDT_GPIO) += gpio_wdt.o
+obj-$(CONFIG_WDT_HISI) += hisi_wdt.o
 obj-$(CONFIG_WDT_MAX6370) += max6370_wdt.o
 obj-$(CONFIG_WDT_MCF) += mcf_wdt.o
 obj-$(CONFIG_WDT_MESON_GXBB) += meson_gxbb_wdt.o
diff --git a/drivers/watchdog/hisi_wdt.c b/drivers/watchdog/hisi_wdt.c
new file mode 100644
index 00..5be9e90865
--- /dev/null
+++ b/drivers/watchdog/hisi_wdt.c
@@ -0,0 +1,196 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Watchdog driver for HiSilicon SoCs
+ *
+ * Copyright 2024 (r) Yang Xiwen 
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+/* CONTROL register definitions */
+#define HISI_WDG_RES_ENBIT(1)
+#define HISI_WDG_INT_ENBIT(0)
+
+/* RIS(Raw Interrupt Status) register definitions */
+#define HISI_WDG_RIS   BIT(0)
+
+/* MIS(Masked Interrupt Status) register definitions*/
+#define HISI_WDG_MIS   BIT(0)
+
+/* LOCK register magic */
+// Write this value to unlock watchdog
+#define HISI_WDG_LOCK_MAGIC0x1ACCE551
+// Read values
+#define HISI_WDG_LOCK_WA   0x0
+#define HISI_WDG_LOCK_RO   0x1
+
+struct hisi_wdg_reg {
+   u32 load; // 0x
+   u32 value; // 0x0004
+   u32 control; // 0x0008
+   u32 intclr; // 0x000c
+   u32 ris; // 0x0010
+   u32 mis; // 0x0014
+   u32 reserved[762]; // 0x0018
+   u32 lock; // 0x0c00
+};
+
+struct hisi_wdt_priv {
+   struct hisi_wdg_reg __iomem *reg;
+   struct clk *clk;
+   struct reset_ctl *rst;
+};
+
+static inline void hisi_wdt_unlock(struct hisi_wdg_reg __iomem *reg)
+{
+   reg->lock = HISI_WDG_LOCK_MAGIC;
+}
+
+static inline void hisi_wdt_lock(struct hisi_wdg_reg __iomem *reg)
+{
+   // Any value other than HISI_WDG_LOCK_MAGIC would lock the registers
+   reg->lock = 0;
+}
+
+static int hisi_wdt_start(struct udevice *dev, u64 timeout_ms, ulong flags)
+{
+   struct hisi_wdt_priv *priv = dev_get_priv(dev);
+   u64 rate;
+   u64 val;
+
+   rate = clk_get_rate(priv->clk);
+
+   /* This may overflow */
+   val = mul_u64_u32_div(timeout_ms, rate, 1000);
+   if (val > UINT32_MAX) {
+   dev_warn(dev, "timeout_ms too large, using maximum.\n");
+   val = UINT32_MAX;
+   }
+
+   hisi_wdt_unlock(priv->reg);
+
+   priv->reg->load = (u32) val;
+   priv->reg->control |= (HISI_WDG_RES_EN | HISI_WDG_INT_EN);
+
+   hisi_wdt_lock(priv->reg);
+
+   return 0;
+}
+
+static int hisi_wdt_stop(struct udevice *dev)
+{
+   struct hisi_wdt_priv *priv = dev_get_priv(dev);
+
+   hisi_wdt_unlock(priv->reg);
+   // disabling interrupt also disables counting
+   priv->reg->control &= ~HISI_WDG_INT_EN;
+
+   hisi_wdt_lock(priv->reg);
+
+   return 0;
+}
+
+static int hisi_wdt_reset(struct udevice *dev)
+{
+   struct hisi_wdt_priv *priv = dev_get_priv(dev);
+
+   hisi_wdt_unlock(priv->reg);
+
+   // any value written to INTCLR would result a counter reload
+   priv->reg->intclr = 0;
+
+   hisi_wdt_lock(priv->reg);
+
+   return 0;
+}
+
+static int hisi_wdt_expire_now(struct udevice *dev, ulong flags)
+{
+   return hisi_wdt_start(dev, 1, flags);
+}
+
+static const struct wdt_ops hisi_wdt_ops = {
+   .start  = hisi_wdt_start,
+   .stop   = hisi_wdt_stop,
+   .reset  = hisi_wdt_reset,
+   

[PATCH] test: dm: clk_ccf: fix building error

2023-12-15 Thread Yang Xiwen via B4 Relay
From: Yang Xiwen 

Fix unused variable error produced by building tests

Fixes: d3061824 (test: dm: clk_ccf: test ccf_clk_ops)
Signed-off-by: Yang Xiwen 
---
it's detected by u-boot gitlab CI.
---
 test/dm/clk_ccf.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/test/dm/clk_ccf.c b/test/dm/clk_ccf.c
index b8be6d6572..5a3c58c6b5 100644
--- a/test/dm/clk_ccf.c
+++ b/test/dm/clk_ccf.c
@@ -18,11 +18,12 @@
 /* Tests for Common Clock Framework driver */
 static int dm_test_clk_ccf(struct unit_test_state *uts)
 {
-   struct clk *clk, *pclk, clk_ccf;
+   struct clk *clk, *pclk;
struct udevice *dev, *test_dev;
long long rate;
int ret;
 #if CONFIG_IS_ENABLED(CLK_CCF)
+   struct clk clk_ccf;
const char *clkname;
int clkid, i;
 #endif

---
base-commit: c9945276f77921feb8df7be75cced3338d08e8d4
change-id: 20231216-b4-fix_build-d05f2b26c8a7

Best regards,
-- 
Yang Xiwen 



[PATCH v3 0/2] clk: ccf: fix enable_count mismatch

2023-12-15 Thread Yang Xiwen via B4 Relay
As described in [1], enable_count is incremented by 2 when
ccf_clk_enable() is called. This series of patch fixed this issue and
added a testcase for that.

[1]: 
https://lore.kernel.org/all/sezpr06mb695927a6deeef8489a06897396...@sezpr06mb6959.apcprd06.prod.outlook.com/

Signed-off-by: Yang Xiwen 
---
Changes in v3:
- move i2v_root in front of devm clocks. So that clk_test driver needs a
  minimum modification
- squash patch 1, 3 and 4. -- Suggested by Sean
- rewrite commit log for clarity.
- Link to v2: 
https://lore.kernel.org/r/2023-enable_count-v2-0-20e372860...@outlook.com

Changes in v2:
- add missing SoB in patch 1/4, no functional change
- Link to v1: 
https://lore.kernel.org/r/2023-enable_count-v1-0-509f400a9...@outlook.com

---
Yang Xiwen (2):
  clk: get correct ops for clk_enable() and clk_disable()
  test: dm: clk_ccf: test ccf_clk_ops

 arch/sandbox/dts/test.dts  |  4 +++-
 arch/sandbox/include/asm/clk.h |  1 +
 drivers/clk/clk-uclass.c   |  2 ++
 drivers/clk/clk_sandbox_ccf.c  |  1 +
 drivers/clk/clk_sandbox_test.c |  1 +
 test/dm/clk_ccf.c  | 14 +++---
 6 files changed, 19 insertions(+), 4 deletions(-)
---
base-commit: 3b913c148249a2b9d12ff25517ec311646e83bee
change-id: 2023-enable_count-ad5001326815

Best regards,
-- 
Yang Xiwen 



[PATCH v3 1/2] clk: get correct ops for clk_enable() and clk_disable()

2023-12-15 Thread Yang Xiwen via B4 Relay
From: Yang Xiwen 

assign clk_dev_ops(clkp->dev) to ops to ensure correct clk operations
are called on clocks.

This fixes the incorrect enable_count issue as described in [1].

[1]: 
https://lore.kernel.org/all/sezpr06mb695927a6deeef8489a06897396...@sezpr06mb6959.apcprd06.prod.outlook.com/

Reviewed-by: Sean Anderson 
Signed-off-by: Yang Xiwen 
---
 drivers/clk/clk-uclass.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/clk/clk-uclass.c b/drivers/clk/clk-uclass.c
index 3b5e3f9c86..3e9d68feb3 100644
--- a/drivers/clk/clk-uclass.c
+++ b/drivers/clk/clk-uclass.c
@@ -640,6 +640,7 @@ int clk_enable(struct clk *clk)
if (CONFIG_IS_ENABLED(CLK_CCF)) {
/* Take id 0 as a non-valid clk, such as dummy */
if (clk->id && !clk_get_by_id(clk->id, )) {
+   ops = clk_dev_ops(clkp->dev);
if (clkp->enable_count) {
clkp->enable_count++;
return 0;
@@ -699,6 +700,7 @@ int clk_disable(struct clk *clk)
 
if (CONFIG_IS_ENABLED(CLK_CCF)) {
if (clk->id && !clk_get_by_id(clk->id, )) {
+   ops = clk_dev_ops(clkp->dev);
if (clkp->flags & CLK_IS_CRITICAL)
return 0;
 

-- 
2.39.2



[PATCH v3 2/2] test: dm: clk_ccf: test ccf_clk_ops

2023-12-15 Thread Yang Xiwen via B4 Relay
From: Yang Xiwen 

Assign ccf_clk_ops to .ops of clk_ccf driver so that it can act as an
clk provider. Also add "#clock-cells=<1>" to its device tree node.

Add "i2c_root" to clk_test in the device tree and driver for testing.

Get "i2c_root" clock in CCF unit tests and add tests for it.

Signed-off-by: Yang Xiwen 
---
 arch/sandbox/dts/test.dts  |  4 +++-
 arch/sandbox/include/asm/clk.h |  1 +
 drivers/clk/clk_sandbox_ccf.c  |  1 +
 drivers/clk/clk_sandbox_test.c |  1 +
 test/dm/clk_ccf.c  | 14 +++---
 5 files changed, 17 insertions(+), 4 deletions(-)

diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
index c7197795ef..a3a865d65c 100644
--- a/arch/sandbox/dts/test.dts
+++ b/arch/sandbox/dts/test.dts
@@ -631,9 +631,10 @@
clocks = <_fixed>,
 <_sandbox 1>,
 <_sandbox 0>,
+< 11>,
 <_sandbox 3>,
 <_sandbox 2>;
-   clock-names = "fixed", "i2c", "spi", "uart2", "uart1";
+   clock-names = "fixed", "i2c", "spi", "i2c_root", "uart2", 
"uart1";
};
 
clk-test2 {
@@ -654,6 +655,7 @@
 
ccf: clk-ccf {
compatible = "sandbox,clk-ccf";
+   #clock-cells = <1>;
};
 
efi-media {
diff --git a/arch/sandbox/include/asm/clk.h b/arch/sandbox/include/asm/clk.h
index df7156fe31..1daf2e7ac7 100644
--- a/arch/sandbox/include/asm/clk.h
+++ b/arch/sandbox/include/asm/clk.h
@@ -39,6 +39,7 @@ enum sandbox_clk_test_id {
SANDBOX_CLK_TEST_ID_FIXED,
SANDBOX_CLK_TEST_ID_SPI,
SANDBOX_CLK_TEST_ID_I2C,
+   SANDBOX_CLK_TEST_ID_I2C_ROOT,
SANDBOX_CLK_TEST_ID_DEVM1,
SANDBOX_CLK_TEST_ID_DEVM2,
SANDBOX_CLK_TEST_ID_DEVM_NULL,
diff --git a/drivers/clk/clk_sandbox_ccf.c b/drivers/clk/clk_sandbox_ccf.c
index fedcdd4044..38184e27aa 100644
--- a/drivers/clk/clk_sandbox_ccf.c
+++ b/drivers/clk/clk_sandbox_ccf.c
@@ -284,6 +284,7 @@ static int sandbox_clk_ccf_probe(struct udevice *dev)
 U_BOOT_DRIVER(sandbox_clk_ccf) = {
.name = "sandbox_clk_ccf",
.id = UCLASS_CLK,
+   .ops = _clk_ops,
.probe = sandbox_clk_ccf_probe,
.of_match = sandbox_clk_ccf_test_ids,
 };
diff --git a/drivers/clk/clk_sandbox_test.c b/drivers/clk/clk_sandbox_test.c
index 5807a454f3..c695b69321 100644
--- a/drivers/clk/clk_sandbox_test.c
+++ b/drivers/clk/clk_sandbox_test.c
@@ -15,6 +15,7 @@ static const char * const sandbox_clk_test_names[] = {
[SANDBOX_CLK_TEST_ID_FIXED] = "fixed",
[SANDBOX_CLK_TEST_ID_SPI] = "spi",
[SANDBOX_CLK_TEST_ID_I2C] = "i2c",
+   [SANDBOX_CLK_TEST_ID_I2C_ROOT] = "i2c_root",
 };
 
 int sandbox_clk_test_get(struct udevice *dev)
diff --git a/test/dm/clk_ccf.c b/test/dm/clk_ccf.c
index e4ebb93cda..b8be6d6572 100644
--- a/test/dm/clk_ccf.c
+++ b/test/dm/clk_ccf.c
@@ -18,8 +18,8 @@
 /* Tests for Common Clock Framework driver */
 static int dm_test_clk_ccf(struct unit_test_state *uts)
 {
-   struct clk *clk, *pclk;
-   struct udevice *dev;
+   struct clk *clk, *pclk, clk_ccf;
+   struct udevice *dev, *test_dev;
long long rate;
int ret;
 #if CONFIG_IS_ENABLED(CLK_CCF)
@@ -29,6 +29,7 @@ static int dm_test_clk_ccf(struct unit_test_state *uts)
 
/* Get the device using the clk device */
ut_assertok(uclass_get_device_by_name(UCLASS_CLK, "clk-ccf", ));
+   ut_assertok(uclass_get_device_by_name(UCLASS_MISC, "clk-test", 
_dev));
 
/* Test for clk_get_by_id() */
ret = clk_get_by_id(SANDBOX_CLK_ECSPI_ROOT, );
@@ -110,11 +111,18 @@ static int dm_test_clk_ccf(struct unit_test_state *uts)
 
 #if CONFIG_IS_ENABLED(CLK_CCF)
/* Test clk tree enable/disable */
+
+   ret = clk_get_by_index(test_dev, SANDBOX_CLK_TEST_ID_I2C_ROOT, 
_ccf);
+   ut_assertok(ret);
+   ut_asserteq_str("clk-ccf", clk_ccf.dev->name);
+   ut_asserteq(clk_ccf.id, SANDBOX_CLK_I2C_ROOT);
+
ret = clk_get_by_id(SANDBOX_CLK_I2C_ROOT, );
ut_assertok(ret);
ut_asserteq_str("i2c_root", clk->dev->name);
+   ut_asserteq(clk->id, SANDBOX_CLK_I2C_ROOT);
 
-   ret = clk_enable(clk);
+   ret = clk_enable(_ccf);
ut_assertok(ret);
 
ret = sandbox_clk_enable_count(clk);

-- 
2.39.2



[PATCH v2 2/4] clk: get correct ops for clk_enable() and clk_disable()

2023-11-18 Thread Yang Xiwen via B4 Relay
From: Yang Xiwen 

assign clk_dev_ops(clkp->dev) to ops to ensure correct clk operations
are called on clocks.

This fixes the incorrect enable_count issue as described in [1].

[1]: 
https://lore.kernel.org/all/sezpr06mb695927a6deeef8489a06897396...@sezpr06mb6959.apcprd06.prod.outlook.com/

Signed-off-by: Yang Xiwen 
---
 drivers/clk/clk-uclass.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/clk/clk-uclass.c b/drivers/clk/clk-uclass.c
index 3b5e3f9c86..3e9d68feb3 100644
--- a/drivers/clk/clk-uclass.c
+++ b/drivers/clk/clk-uclass.c
@@ -640,6 +640,7 @@ int clk_enable(struct clk *clk)
if (CONFIG_IS_ENABLED(CLK_CCF)) {
/* Take id 0 as a non-valid clk, such as dummy */
if (clk->id && !clk_get_by_id(clk->id, )) {
+   ops = clk_dev_ops(clkp->dev);
if (clkp->enable_count) {
clkp->enable_count++;
return 0;
@@ -699,6 +700,7 @@ int clk_disable(struct clk *clk)
 
if (CONFIG_IS_ENABLED(CLK_CCF)) {
if (clk->id && !clk_get_by_id(clk->id, )) {
+   ops = clk_dev_ops(clkp->dev);
if (clkp->flags & CLK_IS_CRITICAL)
return 0;
 

-- 
2.39.2



[PATCH v2 1/4] clk: clk_sandbox_ccf: assign ccf_clk_ops to .ops of the driver

2023-11-18 Thread Yang Xiwen via B4 Relay
From: Yang Xiwen 

It can now act as an clk provider on which ccf_clk_ops can be tested.
Also add "#clock-cells=<1>" to test.dts.

Signed-off-by: Yang Xiwen 
---
 arch/sandbox/dts/test.dts | 1 +
 drivers/clk/clk_sandbox_ccf.c | 1 +
 2 files changed, 2 insertions(+)

diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
index c7197795ef..b1773f1bc2 100644
--- a/arch/sandbox/dts/test.dts
+++ b/arch/sandbox/dts/test.dts
@@ -654,6 +654,7 @@
 
ccf: clk-ccf {
compatible = "sandbox,clk-ccf";
+   #clock-cells = <1>;
};
 
efi-media {
diff --git a/drivers/clk/clk_sandbox_ccf.c b/drivers/clk/clk_sandbox_ccf.c
index fedcdd4044..38184e27aa 100644
--- a/drivers/clk/clk_sandbox_ccf.c
+++ b/drivers/clk/clk_sandbox_ccf.c
@@ -284,6 +284,7 @@ static int sandbox_clk_ccf_probe(struct udevice *dev)
 U_BOOT_DRIVER(sandbox_clk_ccf) = {
.name = "sandbox_clk_ccf",
.id = UCLASS_CLK,
+   .ops = _clk_ops,
.probe = sandbox_clk_ccf_probe,
.of_match = sandbox_clk_ccf_test_ids,
 };

-- 
2.39.2



[PATCH v2 3/4] clk: clk_sandbox: get devm clock i2c_root

2023-11-18 Thread Yang Xiwen via B4 Relay
From: Yang Xiwen 

This clock is added to dts. Get it in the devm group in the driver or
the testcases will fail.

Signed-off-by: Yang Xiwen 
---
 arch/sandbox/dts/test.dts  | 5 +++--
 arch/sandbox/include/asm/clk.h | 1 +
 drivers/clk/clk_sandbox_test.c | 5 +
 3 files changed, 9 insertions(+), 2 deletions(-)

diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
index b1773f1bc2..f99397c528 100644
--- a/arch/sandbox/dts/test.dts
+++ b/arch/sandbox/dts/test.dts
@@ -632,8 +632,9 @@
 <_sandbox 1>,
 <_sandbox 0>,
 <_sandbox 3>,
-<_sandbox 2>;
-   clock-names = "fixed", "i2c", "spi", "uart2", "uart1";
+<_sandbox 2>,
+< 11>;
+   clock-names = "fixed", "i2c", "spi", "uart2", "uart1", 
"i2c_root";
};
 
clk-test2 {
diff --git a/arch/sandbox/include/asm/clk.h b/arch/sandbox/include/asm/clk.h
index df7156fe31..597bc528dc 100644
--- a/arch/sandbox/include/asm/clk.h
+++ b/arch/sandbox/include/asm/clk.h
@@ -41,6 +41,7 @@ enum sandbox_clk_test_id {
SANDBOX_CLK_TEST_ID_I2C,
SANDBOX_CLK_TEST_ID_DEVM1,
SANDBOX_CLK_TEST_ID_DEVM2,
+   SANDBOX_CLK_TEST_ID_I2C_ROOT,
SANDBOX_CLK_TEST_ID_DEVM_NULL,
 
SANDBOX_CLK_TEST_ID_COUNT,
diff --git a/drivers/clk/clk_sandbox_test.c b/drivers/clk/clk_sandbox_test.c
index 5807a454f3..c0623dee10 100644
--- a/drivers/clk/clk_sandbox_test.c
+++ b/drivers/clk/clk_sandbox_test.c
@@ -53,6 +53,11 @@ int sandbox_clk_test_devm_get(struct udevice *dev)
return PTR_ERR(clk);
sbct->clkps[SANDBOX_CLK_TEST_ID_DEVM2] = clk;
 
+   clk = devm_clk_get_optional(dev, "i2c_root");
+   if (IS_ERR(clk))
+   return PTR_ERR(clk);
+   sbct->clkps[SANDBOX_CLK_TEST_ID_I2C_ROOT] = clk;
+
sbct->clkps[SANDBOX_CLK_TEST_ID_DEVM_NULL] = NULL;
clk = devm_clk_get_optional(dev, "not_an_existing_clock");
if (IS_ERR(clk))

-- 
2.39.2



[PATCH v2 0/4] clk: ccf: fix enable_count mismatch

2023-11-18 Thread Yang Xiwen via B4 Relay
As described in [1], enable_count is incremented by 2 when
ccf_clk_enable() is called. This series of patch fixed this issue and
added a testcase for that.

[1]: 
https://lore.kernel.org/all/sezpr06mb695927a6deeef8489a06897396...@sezpr06mb6959.apcprd06.prod.outlook.com/

Signed-off-by: Yang Xiwen 
---
Changes in v2:
- add missing SoB in patch 1/4, no functional change
- Link to v1: 
https://lore.kernel.org/r/2023-enable_count-v1-0-509f400a9...@outlook.com

---
Yang Xiwen (4):
  clk: clk_sandbox_ccf: assign ccf_clk_ops to .ops of the driver
  clk: get correct ops for clk_enable() and clk_disable()
  clk: clk_sandbox: get devm clock i2c_root
  test: dm: clk_ccf: get "i2c_root" clock from _ccf

 arch/sandbox/dts/test.dts  |  6 --
 arch/sandbox/include/asm/clk.h |  1 +
 drivers/clk/clk-uclass.c   |  2 ++
 drivers/clk/clk_sandbox_ccf.c  |  1 +
 drivers/clk/clk_sandbox_test.c |  5 +
 test/dm/clk_ccf.c  | 14 +++---
 6 files changed, 24 insertions(+), 5 deletions(-)
---
base-commit: 3b913c148249a2b9d12ff25517ec311646e83bee
change-id: 2023-enable_count-ad5001326815

Best regards,
-- 
Yang Xiwen 



[PATCH v2 4/4] test: dm: clk_ccf: get "i2c_root" clock from _ccf

2023-11-18 Thread Yang Xiwen via B4 Relay
From: Yang Xiwen 

get i2c_root clock from device tree. In this way we get an CCF clock and
also test ccf_clk_ops.

Signed-off-by: Yang Xiwen 
---
 test/dm/clk_ccf.c | 14 +++---
 1 file changed, 11 insertions(+), 3 deletions(-)

diff --git a/test/dm/clk_ccf.c b/test/dm/clk_ccf.c
index e4ebb93cda..b8be6d6572 100644
--- a/test/dm/clk_ccf.c
+++ b/test/dm/clk_ccf.c
@@ -18,8 +18,8 @@
 /* Tests for Common Clock Framework driver */
 static int dm_test_clk_ccf(struct unit_test_state *uts)
 {
-   struct clk *clk, *pclk;
-   struct udevice *dev;
+   struct clk *clk, *pclk, clk_ccf;
+   struct udevice *dev, *test_dev;
long long rate;
int ret;
 #if CONFIG_IS_ENABLED(CLK_CCF)
@@ -29,6 +29,7 @@ static int dm_test_clk_ccf(struct unit_test_state *uts)
 
/* Get the device using the clk device */
ut_assertok(uclass_get_device_by_name(UCLASS_CLK, "clk-ccf", ));
+   ut_assertok(uclass_get_device_by_name(UCLASS_MISC, "clk-test", 
_dev));
 
/* Test for clk_get_by_id() */
ret = clk_get_by_id(SANDBOX_CLK_ECSPI_ROOT, );
@@ -110,11 +111,18 @@ static int dm_test_clk_ccf(struct unit_test_state *uts)
 
 #if CONFIG_IS_ENABLED(CLK_CCF)
/* Test clk tree enable/disable */
+
+   ret = clk_get_by_index(test_dev, SANDBOX_CLK_TEST_ID_I2C_ROOT, 
_ccf);
+   ut_assertok(ret);
+   ut_asserteq_str("clk-ccf", clk_ccf.dev->name);
+   ut_asserteq(clk_ccf.id, SANDBOX_CLK_I2C_ROOT);
+
ret = clk_get_by_id(SANDBOX_CLK_I2C_ROOT, );
ut_assertok(ret);
ut_asserteq_str("i2c_root", clk->dev->name);
+   ut_asserteq(clk->id, SANDBOX_CLK_I2C_ROOT);
 
-   ret = clk_enable(clk);
+   ret = clk_enable(_ccf);
ut_assertok(ret);
 
ret = sandbox_clk_enable_count(clk);

-- 
2.39.2



[PATCH 1/4] clk: clk_sandbox_ccf: assign ccf_clk_ops to .ops of the driver

2023-11-18 Thread Yang Xiwen via B4 Relay
From: Yang Xiwen 

It can now act as an clk provider on which ccf_clk_ops can be tested.
Also add "#clock-cells=<1>" to test.dts.
---
 arch/sandbox/dts/test.dts | 1 +
 drivers/clk/clk_sandbox_ccf.c | 1 +
 2 files changed, 2 insertions(+)

diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
index c7197795ef..b1773f1bc2 100644
--- a/arch/sandbox/dts/test.dts
+++ b/arch/sandbox/dts/test.dts
@@ -654,6 +654,7 @@
 
ccf: clk-ccf {
compatible = "sandbox,clk-ccf";
+   #clock-cells = <1>;
};
 
efi-media {
diff --git a/drivers/clk/clk_sandbox_ccf.c b/drivers/clk/clk_sandbox_ccf.c
index fedcdd4044..38184e27aa 100644
--- a/drivers/clk/clk_sandbox_ccf.c
+++ b/drivers/clk/clk_sandbox_ccf.c
@@ -284,6 +284,7 @@ static int sandbox_clk_ccf_probe(struct udevice *dev)
 U_BOOT_DRIVER(sandbox_clk_ccf) = {
.name = "sandbox_clk_ccf",
.id = UCLASS_CLK,
+   .ops = _clk_ops,
.probe = sandbox_clk_ccf_probe,
.of_match = sandbox_clk_ccf_test_ids,
 };

-- 
2.39.2



[PATCH 4/4] test: dm: clk_ccf: get "i2c_root" clock from _ccf

2023-11-18 Thread Yang Xiwen via B4 Relay
From: Yang Xiwen 

get i2c_root clock from device tree. In this way we get an CCF clock and
also test ccf_clk_ops.

Signed-off-by: Yang Xiwen 
---
 test/dm/clk_ccf.c | 14 +++---
 1 file changed, 11 insertions(+), 3 deletions(-)

diff --git a/test/dm/clk_ccf.c b/test/dm/clk_ccf.c
index e4ebb93cda..b8be6d6572 100644
--- a/test/dm/clk_ccf.c
+++ b/test/dm/clk_ccf.c
@@ -18,8 +18,8 @@
 /* Tests for Common Clock Framework driver */
 static int dm_test_clk_ccf(struct unit_test_state *uts)
 {
-   struct clk *clk, *pclk;
-   struct udevice *dev;
+   struct clk *clk, *pclk, clk_ccf;
+   struct udevice *dev, *test_dev;
long long rate;
int ret;
 #if CONFIG_IS_ENABLED(CLK_CCF)
@@ -29,6 +29,7 @@ static int dm_test_clk_ccf(struct unit_test_state *uts)
 
/* Get the device using the clk device */
ut_assertok(uclass_get_device_by_name(UCLASS_CLK, "clk-ccf", ));
+   ut_assertok(uclass_get_device_by_name(UCLASS_MISC, "clk-test", 
_dev));
 
/* Test for clk_get_by_id() */
ret = clk_get_by_id(SANDBOX_CLK_ECSPI_ROOT, );
@@ -110,11 +111,18 @@ static int dm_test_clk_ccf(struct unit_test_state *uts)
 
 #if CONFIG_IS_ENABLED(CLK_CCF)
/* Test clk tree enable/disable */
+
+   ret = clk_get_by_index(test_dev, SANDBOX_CLK_TEST_ID_I2C_ROOT, 
_ccf);
+   ut_assertok(ret);
+   ut_asserteq_str("clk-ccf", clk_ccf.dev->name);
+   ut_asserteq(clk_ccf.id, SANDBOX_CLK_I2C_ROOT);
+
ret = clk_get_by_id(SANDBOX_CLK_I2C_ROOT, );
ut_assertok(ret);
ut_asserteq_str("i2c_root", clk->dev->name);
+   ut_asserteq(clk->id, SANDBOX_CLK_I2C_ROOT);
 
-   ret = clk_enable(clk);
+   ret = clk_enable(_ccf);
ut_assertok(ret);
 
ret = sandbox_clk_enable_count(clk);

-- 
2.39.2



[PATCH 0/4] clk: ccf: fix enable_count mismatch

2023-11-18 Thread Yang Xiwen via B4 Relay
As described in [1], enable_count is incremented by 2 when
ccf_clk_enable() is called. This series of patch fixed this issue and
added a testcase for that.

[1]: 
https://lore.kernel.org/all/sezpr06mb695927a6deeef8489a06897396...@sezpr06mb6959.apcprd06.prod.outlook.com/

Signed-off-by: Yang Xiwen 
---
Yang Xiwen (4):
  clk: clk_sandbox_ccf: assign ccf_clk_ops to .ops of the driver
  clk: get correct ops for clk_enable() and clk_disable()
  clk: clk_sandbox: get devm clock i2c_root
  test: dm: clk_ccf: get "i2c_root" clock from _ccf

 arch/sandbox/dts/test.dts  |  6 --
 arch/sandbox/include/asm/clk.h |  1 +
 drivers/clk/clk-uclass.c   |  2 ++
 drivers/clk/clk_sandbox_ccf.c  |  1 +
 drivers/clk/clk_sandbox_test.c |  5 +
 test/dm/clk_ccf.c  | 14 +++---
 6 files changed, 24 insertions(+), 5 deletions(-)
---
base-commit: 3b913c148249a2b9d12ff25517ec311646e83bee
change-id: 2023-enable_count-ad5001326815

Best regards,
-- 
Yang Xiwen 



[PATCH 2/4] clk: get correct ops for clk_enable() and clk_disable()

2023-11-18 Thread Yang Xiwen via B4 Relay
From: Yang Xiwen 

assign clk_dev_ops(clkp->dev) to ops to ensure correct clk operations
are called on clocks.

This fixes the incorrect enable_count issue as described in [1].

[1]: 
https://lore.kernel.org/all/sezpr06mb695927a6deeef8489a06897396...@sezpr06mb6959.apcprd06.prod.outlook.com/

Signed-off-by: Yang Xiwen 
---
 drivers/clk/clk-uclass.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/clk/clk-uclass.c b/drivers/clk/clk-uclass.c
index 3b5e3f9c86..3e9d68feb3 100644
--- a/drivers/clk/clk-uclass.c
+++ b/drivers/clk/clk-uclass.c
@@ -640,6 +640,7 @@ int clk_enable(struct clk *clk)
if (CONFIG_IS_ENABLED(CLK_CCF)) {
/* Take id 0 as a non-valid clk, such as dummy */
if (clk->id && !clk_get_by_id(clk->id, )) {
+   ops = clk_dev_ops(clkp->dev);
if (clkp->enable_count) {
clkp->enable_count++;
return 0;
@@ -699,6 +700,7 @@ int clk_disable(struct clk *clk)
 
if (CONFIG_IS_ENABLED(CLK_CCF)) {
if (clk->id && !clk_get_by_id(clk->id, )) {
+   ops = clk_dev_ops(clkp->dev);
if (clkp->flags & CLK_IS_CRITICAL)
return 0;
 

-- 
2.39.2



[PATCH 3/4] clk: clk_sandbox: get devm clock i2c_root

2023-11-18 Thread Yang Xiwen via B4 Relay
From: Yang Xiwen 

This clock is added to dts. Get it in the devm group in the driver or
the testcases will fail.

Signed-off-by: Yang Xiwen 
---
 arch/sandbox/dts/test.dts  | 5 +++--
 arch/sandbox/include/asm/clk.h | 1 +
 drivers/clk/clk_sandbox_test.c | 5 +
 3 files changed, 9 insertions(+), 2 deletions(-)

diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
index b1773f1bc2..f99397c528 100644
--- a/arch/sandbox/dts/test.dts
+++ b/arch/sandbox/dts/test.dts
@@ -632,8 +632,9 @@
 <_sandbox 1>,
 <_sandbox 0>,
 <_sandbox 3>,
-<_sandbox 2>;
-   clock-names = "fixed", "i2c", "spi", "uart2", "uart1";
+<_sandbox 2>,
+< 11>;
+   clock-names = "fixed", "i2c", "spi", "uart2", "uart1", 
"i2c_root";
};
 
clk-test2 {
diff --git a/arch/sandbox/include/asm/clk.h b/arch/sandbox/include/asm/clk.h
index df7156fe31..597bc528dc 100644
--- a/arch/sandbox/include/asm/clk.h
+++ b/arch/sandbox/include/asm/clk.h
@@ -41,6 +41,7 @@ enum sandbox_clk_test_id {
SANDBOX_CLK_TEST_ID_I2C,
SANDBOX_CLK_TEST_ID_DEVM1,
SANDBOX_CLK_TEST_ID_DEVM2,
+   SANDBOX_CLK_TEST_ID_I2C_ROOT,
SANDBOX_CLK_TEST_ID_DEVM_NULL,
 
SANDBOX_CLK_TEST_ID_COUNT,
diff --git a/drivers/clk/clk_sandbox_test.c b/drivers/clk/clk_sandbox_test.c
index 5807a454f3..c0623dee10 100644
--- a/drivers/clk/clk_sandbox_test.c
+++ b/drivers/clk/clk_sandbox_test.c
@@ -53,6 +53,11 @@ int sandbox_clk_test_devm_get(struct udevice *dev)
return PTR_ERR(clk);
sbct->clkps[SANDBOX_CLK_TEST_ID_DEVM2] = clk;
 
+   clk = devm_clk_get_optional(dev, "i2c_root");
+   if (IS_ERR(clk))
+   return PTR_ERR(clk);
+   sbct->clkps[SANDBOX_CLK_TEST_ID_I2C_ROOT] = clk;
+
sbct->clkps[SANDBOX_CLK_TEST_ID_DEVM_NULL] = NULL;
clk = devm_clk_get_optional(dev, "not_an_existing_clock");
if (IS_ERR(clk))

-- 
2.39.2



[PATCH v2] clk: check parent_name in clk_register to avoid confusing log_error() output

2023-11-10 Thread Yang Xiwen via B4 Relay
From: Yang Xiwen 

For some gate clocks and fixed clocks without a parent, calling
clk_register will print an useless error message indicating that parent
is missing. Fix that by gaurding log_xxx() with an if-statement.

Signed-off-by: Yang Xiwen 
Suggested-by: Sean Anderson 
---
It's found during my development for HiSilicon clock driver.
---
Changes in v2:
- drop the commit which exports clk_mux_register.
- drop the commit which is already merged
- drop ccf enable_count fix as it'll be in another patchset
- use Anderson's patch for clk_register()
- Link to v1: 
https://lore.kernel.org/r/20230809-clk-fix-v1-0-808dbae54...@outlook.com
---
 drivers/clk/clk.c | 18 ++
 1 file changed, 10 insertions(+), 8 deletions(-)

diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index a5a3461b66..6ede1b4d4d 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -18,17 +18,19 @@
 int clk_register(struct clk *clk, const char *drv_name,
 const char *name, const char *parent_name)
 {
-   struct udevice *parent;
+   struct udevice *parent = NULL;
struct driver *drv;
int ret;
 
-   ret = uclass_get_device_by_name(UCLASS_CLK, parent_name, );
-   if (ret) {
-   log_err("%s: failed to get %s device (parent of %s)\n",
-   __func__, parent_name, name);
-   } else {
-   log_debug("%s: name: %s parent: %s [0x%p]\n", __func__, name,
- parent->name, parent);
+   if (parent_name) {
+   ret = uclass_get_device_by_name(UCLASS_CLK, parent_name, 
);
+   if (ret) {
+   log_err("%s: failed to get %s device (parent of %s)\n",
+   __func__, parent_name, name);
+   } else {
+   log_debug("%s: name: %s parent: %s [0x%p]\n", __func__, 
name,
+ parent->name, parent);
+   }
}
 
drv = lists_driver_lookup_name(drv_name);

---
base-commit: 580eb31199be8a822e62f20965854a242f895d03
change-id: 20230807-clk-fix-17e895f79817

Best regards,
-- 
Yang Xiwen 



[PATCH RESEND v2 0/2] net: add support for HiSilicon Fast Ethernet Controller driver

2023-08-22 Thread Yang Xiwen via B4 Relay
This core is found on many HiSilicon chips. This patchset adds support
for it and the integrated MDIO bus.

The driver code comes from linux kernel driver, downstream u-boot driver
and the datasheet. It's already tested on a Hi3798MV200 based STB.

Note that currently this driver can't be used for Hi3798MV200 since the
clock driver is missing. I will implement and submit the clock driver
and the framework in a later patchset.

Signed-off-by: Yang Xiwen 
---
Changes in v2:
- hisi_femac: clear previous irq before sending
- Link to v1: 
https://lore.kernel.org/r/20230725-wip-hisi_femac-trunk-v1-0-88469a170...@outlook.com

---
Yang Xiwen (2):
  net: add hifemac Ethernet driver for HiSilicon platform
  net: add hifemac_mdio MDIO bus driver for HiSilicon platform

 drivers/net/Kconfig|  17 ++
 drivers/net/Makefile   |   2 +
 drivers/net/hifemac.c  | 481 +
 drivers/net/hifemac_mdio.c | 116 +++
 4 files changed, 616 insertions(+)
---
base-commit: 580eb31199be8a822e62f20965854a242f895d03
change-id: 20230724-wip-hisi_femac-trunk-1f57f0986f0c

Best regards,
-- 
Yang Xiwen 



[PATCH RESEND v2 1/2] net: add hifemac Ethernet driver for HiSilicon platform

2023-08-22 Thread Yang Xiwen via B4 Relay
From: Yang Xiwen 

It adds the driver for HIFEMAC Ethernet controller found on HiSilicon
SoCs like Hi3798MV200.  It's based on the mainstream linux driver, but
quite a lot of code gets rewritten and cleaned up to adopt u-boot driver
model.

Signed-off-by: Yang Xiwen 
---
 drivers/net/Kconfig   |   9 +
 drivers/net/Makefile  |   1 +
 drivers/net/hifemac.c | 481 ++
 3 files changed, 491 insertions(+)

diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 39eee98ca7..bc1d6e3905 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -886,6 +886,15 @@ config MEDIATEK_ETH
  This Driver support MediaTek Ethernet GMAC
  Say Y to enable support for the MediaTek Ethernet GMAC.
 
+config HIFEMAC_ETH
+   bool "HiSilicon Fast Ethernet Controller"
+   select DM_CLK
+   select DM_RESET
+   select PHYLIB
+   help
+ This driver supports HIFEMAC Ethernet controller found on
+ HiSilicon SoCs.
+
 config HIGMACV300_ETH
bool "HiSilicon Gigabit Ethernet Controller"
select DM_RESET
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index 46a40e2ed9..de6bf1d014 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -45,6 +45,7 @@ obj-$(CONFIG_FSL_PFE) += pfe_eth/
 obj-$(CONFIG_FTGMAC100) += ftgmac100.o
 obj-$(CONFIG_FTMAC100) += ftmac100.o
 obj-$(CONFIG_GMAC_ROCKCHIP) += gmac_rockchip.o
+obj-$(CONFIG_HIFEMAC_ETH) += hifemac.o
 obj-$(CONFIG_HIGMACV300_ETH) += higmacv300.o
 obj-$(CONFIG_KS8851_MLL) += ks8851_mll.o
 obj-$(CONFIG_KSZ9477) += ksz9477.o
diff --git a/drivers/net/hifemac.c b/drivers/net/hifemac.c
new file mode 100644
index 00..b61a29e636
--- /dev/null
+++ b/drivers/net/hifemac.c
@@ -0,0 +1,481 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Hisilicon Fast Ethernet MAC Driver
+ * Adapted from linux
+ *
+ * Copyright (c) 2016 HiSilicon Technologies Co., Ltd.
+ * Copyright (c) 2023 Yang Xiwen 
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+/* MAC control register list */
+#define MAC_PORTSEL0x0200
+#define MAC_PORTSEL_STAT_CPU   BIT(0)
+#define MAC_PORTSEL_RMII   BIT(1)
+#define MAC_PORTSET0x0208
+#define MAC_PORTSET_DUPLEX_FULLBIT(0)
+#define MAC_PORTSET_LINKED BIT(1)
+#define MAC_PORTSET_SPEED_100M BIT(2)
+#define MAC_SET0x0210
+#define MAX_FRAME_SIZE 1600
+#define MAX_FRAME_SIZE_MASKGENMASK(10, 0)
+#define BIT_PAUSE_EN   BIT(18)
+#define RX_COALESCE_SET0x0340
+#define RX_COALESCED_FRAME_OFFSET  24
+#define RX_COALESCED_FRAMES8
+#define RX_COALESCED_TIMER 0x74
+#define QLEN_SET   0x0344
+#define RX_DEPTH_OFFSET8
+#define MAX_HW_FIFO_DEPTH  64
+#define HW_TX_FIFO_DEPTH   1
+#define MAX_HW_RX_FIFO_DEPTH   (MAX_HW_FIFO_DEPTH - HW_TX_FIFO_DEPTH)
+#define HW_RX_FIFO_DEPTH   min(PKTBUFSRX, MAX_HW_RX_FIFO_DEPTH)
+#define IQFRM_DES  0x0354
+#define RX_FRAME_LEN_MASK  GENMASK(11, 0)
+#define RX_FRAME_IN_INDEX_MASK GENMASK(17, 12)
+#define IQ_ADDR0x0358
+#define EQ_ADDR0x0360
+#define EQFRM_LEN  0x0364
+#define ADDRQ_STAT 0x036C
+#define TX_CNT_INUSE_MASK  GENMASK(5, 0)
+#define BIT_TX_READY   BIT(24)
+#define BIT_RX_READY   BIT(25)
+/* global control register list */
+#define GLB_HOSTMAC_L320x
+#define GLB_HOSTMAC_H160x0004
+#define GLB_SOFT_RESET 0x0008
+#define SOFT_RESET_ALL BIT(0)
+#define GLB_FWCTRL 0x0010
+#define FWCTRL_VLAN_ENABLE BIT(0)
+#define FWCTRL_FW2CPU_ENA  BIT(5)
+#define FWCTRL_FWALL2CPU   BIT(7)
+#define GLB_MACTCTRL   0x0014
+#define MACTCTRL_UNI2CPU   BIT(1)
+#define MACTCTRL_MULTI2CPU BIT(3)
+#define MACTCTRL_BROAD2CPU BIT(5)
+#define MACTCTRL_MACT_ENA  BIT(7)
+#define GLB_IRQ_STAT   0x0030
+#define GLB_IRQ_ENA0x0034
+#define IRQ_ENA_PORT0_MASK GENMASK(7, 0)
+#define IRQ_ENA_PORT0  BIT(18)
+#define IRQ_ENA_ALLBIT(19)
+#define GLB_IRQ_RAW0x0038
+#define IRQ_INT_RX_RDY BIT(0)
+#define IRQ_INT_TX_PER_PACKET  BIT(1)
+#define IRQ_INT_TX_FIFO_EMPTY  BIT(6)
+#define IRQ_INT_MULTI_RXRDYBIT(7)
+#define DEF_INT_MASK   (IRQ_INT_MULTI_RXRDY | \
+   IRQ_INT_TX_PER_PACKET | \
+  

[PATCH RESEND v2 2/2] net: add hifemac_mdio MDIO bus driver for HiSilicon platform

2023-08-22 Thread Yang Xiwen via B4 Relay
From: Yang Xiwen 

It adds the driver for the internal MDIO bus of HIFEMAC Ethernet
controller.  It's based on the mainstream linux driver.

Signed-off-by: Yang Xiwen 
---
 drivers/net/Kconfig|   8 
 drivers/net/Makefile   |   1 +
 drivers/net/hifemac_mdio.c | 116 +
 3 files changed, 125 insertions(+)

diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index bc1d6e3905..5c5bfb1263 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -895,6 +895,14 @@ config HIFEMAC_ETH
  This driver supports HIFEMAC Ethernet controller found on
  HiSilicon SoCs.
 
+config HIFEMAC_MDIO
+   bool "HiSilicon Fast Ethernet Controller MDIO interface"
+   depends on DM_MDIO
+   select DM_CLK
+   help
+ This driver supports the internal MDIO interface of HIFEMAC
+ Ethernet controller.
+
 config HIGMACV300_ETH
bool "HiSilicon Gigabit Ethernet Controller"
select DM_RESET
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index de6bf1d014..b2d3da6934 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -46,6 +46,7 @@ obj-$(CONFIG_FTGMAC100) += ftgmac100.o
 obj-$(CONFIG_FTMAC100) += ftmac100.o
 obj-$(CONFIG_GMAC_ROCKCHIP) += gmac_rockchip.o
 obj-$(CONFIG_HIFEMAC_ETH) += hifemac.o
+obj-$(CONFIG_HIFEMAC_MDIO) += hifemac_mdio.o
 obj-$(CONFIG_HIGMACV300_ETH) += higmacv300.o
 obj-$(CONFIG_KS8851_MLL) += ks8851_mll.o
 obj-$(CONFIG_KSZ9477) += ksz9477.o
diff --git a/drivers/net/hifemac_mdio.c b/drivers/net/hifemac_mdio.c
new file mode 100644
index 00..343c5f3a38
--- /dev/null
+++ b/drivers/net/hifemac_mdio.c
@@ -0,0 +1,116 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Hisilicon Fast Ethernet MDIO Bus Driver
+ *
+ * Copyright (c) 2016 HiSilicon Technologies Co., Ltd.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define MDIO_RWCTRL0x00
+#define MDIO_RO_DATA   0x04
+#define MDIO_WRITE BIT(13)
+#define MDIO_RW_FINISH BIT(15)
+#define BIT_PHY_ADDR_OFFSET8
+#define BIT_WR_DATA_OFFSET 16
+
+struct hisi_femac_mdio_data {
+   struct clk *clk;
+   void __iomem *membase;
+};
+
+static int hisi_femac_mdio_wait_ready(struct hisi_femac_mdio_data *data)
+{
+   u32 val;
+
+   return readl_poll_timeout(data->membase + MDIO_RWCTRL,
+ val, val & MDIO_RW_FINISH, 1);
+}
+
+static int hisi_femac_mdio_read(struct udevice *dev, int addr, int devad, int 
reg)
+{
+   struct hisi_femac_mdio_data *data = dev_get_priv(dev);
+   int ret;
+
+   ret = hisi_femac_mdio_wait_ready(data);
+   if (ret)
+   return ret;
+
+   writel((addr << BIT_PHY_ADDR_OFFSET) | reg,
+  data->membase + MDIO_RWCTRL);
+
+   ret = hisi_femac_mdio_wait_ready(data);
+   if (ret)
+   return ret;
+
+   return readl(data->membase + MDIO_RO_DATA) & 0x;
+}
+
+static int hisi_femac_mdio_write(struct udevice *dev, int addr, int devad, int 
reg, u16 val)
+{
+   struct hisi_femac_mdio_data *data = dev_get_priv(dev);
+   int ret;
+
+   ret = hisi_femac_mdio_wait_ready(data);
+   if (ret)
+   return ret;
+
+   writel(MDIO_WRITE | (val << BIT_WR_DATA_OFFSET) |
+  (addr << BIT_PHY_ADDR_OFFSET) | reg,
+  data->membase + MDIO_RWCTRL);
+
+   return hisi_femac_mdio_wait_ready(data);
+}
+
+static int hisi_femac_mdio_of_to_plat(struct udevice *dev)
+{
+   struct hisi_femac_mdio_data *data = dev_get_priv(dev);
+   int ret;
+
+   data->membase = dev_remap_addr(dev);
+   if (IS_ERR(data->membase)) {
+   ret = PTR_ERR(data->membase);
+   return log_msg_ret("Failed to remap base addr", ret);
+   }
+
+   // clk is optional
+   data->clk = devm_clk_get_optional(dev, NULL);
+
+   return 0;
+}
+
+static int hisi_femac_mdio_probe(struct udevice *dev)
+{
+   struct hisi_femac_mdio_data *data = dev_get_priv(dev);
+   int ret;
+
+   ret = clk_prepare_enable(data->clk);
+   if (ret)
+   return log_msg_ret("Failed to enable clk", ret);
+
+   return 0;
+}
+
+static const struct mdio_ops hisi_femac_mdio_ops = {
+   .read = hisi_femac_mdio_read,
+   .write = hisi_femac_mdio_write,
+};
+
+static const struct udevice_id hisi_femac_mdio_dt_ids[] = {
+   { .compatible = "hisilicon,hisi-femac-mdio" },
+   { }
+};
+
+U_BOOT_DRIVER(hisi_femac_mdio_driver) = {
+   .name = "hisi-femac-mdio",
+   .id = UCLASS_MDIO,
+   .of_match = hisi_femac_mdio_dt_ids,
+   .of_to_plat = hisi_femac_mdio_of_to_plat,
+   .probe = hisi_femac_mdio_probe,
+   .ops = _femac_mdio_ops,
+   .priv_auto = sizeof(struct hisi_femac_mdio_data),
+};

-- 
2.34.1



[PATCH RESEND 5/5] clk: ccf: call clock provided ops directly for endisable()

2023-08-17 Thread Yang Xiwen via B4 Relay
From: Yang Xiwen 

Calling into CCF framework will cause a clock being enabled twice
instead of once (clk->enable_count becomes 2 rather than 1), thus making
it hard to disable (needs to call clk_disable() twice).
Fix that by calling clock provided ops directly.

Signed-off-by: Yang Xiwen 
---
 drivers/clk/clk.c | 12 +++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index a38daaac0c..00d082c46f 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -14,6 +14,7 @@
 #include 
 #include 
 #include 
+#include 
 
 int clk_register(struct clk *clk, const char *drv_name,
 const char *name, const char *parent_name)
@@ -115,11 +116,20 @@ int ccf_clk_set_parent(struct clk *clk, struct clk 
*parent)
 static int ccf_clk_endisable(struct clk *clk, bool enable)
 {
struct clk *c;
+   const struct clk_ops *ops;
int err = clk_get_by_id(clk->id, );
 
if (err)
return err;
-   return enable ? clk_enable(c) : clk_disable(c);
+   else
+   ops = clk_dev_ops(c->dev);
+
+   if (enable && ops->enable)
+   return ops->enable(c);
+   else if (!enable && ops->disable)
+   return ops->disable(c);
+
+   return -ENOSYS;
 }
 
 int ccf_clk_enable(struct clk *clk)

-- 
2.34.1



[PATCH RESEND 2/5] clk: call log_debug() instead to avoid console log printing

2023-08-17 Thread Yang Xiwen via B4 Relay
From: Yang Xiwen 

it's a very common case to register a clock without a parent, such as
clk_register_fixed_rate(). Replace log_error() with log_debug() to avoid
useless console log if not debugging.

Signed-off-by: Yang Xiwen 
---
 drivers/clk/clk.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index a5a3461b66..a38daaac0c 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -24,8 +24,8 @@ int clk_register(struct clk *clk, const char *drv_name,
 
ret = uclass_get_device_by_name(UCLASS_CLK, parent_name, );
if (ret) {
-   log_err("%s: failed to get %s device (parent of %s)\n",
-   __func__, parent_name, name);
+   log_debug("%s: failed to get %s device (parent of %s)\n",
+ __func__, parent_name, name);
} else {
log_debug("%s: name: %s parent: %s [0x%p]\n", __func__, name,
  parent->name, parent);

-- 
2.34.1



[PATCH RESEND 4/5] clk: promote clk_dev_ops to linux/clk-provider.h

2023-08-17 Thread Yang Xiwen via B4 Relay
From: Yang Xiwen 

So that it can be used by others.

Signed-off-by: Yang Xiwen 
---
 drivers/clk/clk-uclass.c | 5 -
 include/linux/clk-provider.h | 5 +
 2 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/drivers/clk/clk-uclass.c b/drivers/clk/clk-uclass.c
index dc3e9d6a26..5cc80e5e39 100644
--- a/drivers/clk/clk-uclass.c
+++ b/drivers/clk/clk-uclass.c
@@ -25,11 +25,6 @@
 #include 
 #include 
 
-static inline const struct clk_ops *clk_dev_ops(struct udevice *dev)
-{
-   return (const struct clk_ops *)dev->driver->ops;
-}
-
 struct clk *dev_get_clk_ptr(struct udevice *dev)
 {
return (struct clk *)dev_get_uclass_priv(dev);
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index 801404480b..dfafb4cc9d 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -21,6 +21,11 @@ static inline void clk_dm(ulong id, struct clk *clk)
clk->id = id;
 }
 
+static inline const struct clk_ops *clk_dev_ops(struct udevice *dev)
+{
+   return (const struct clk_ops *)dev->driver->ops;
+}
+
 /*
  * flags used across common struct clk.  these flags should only affect the
  * top-level framework.  custom flags for dealing with hardware specifics

-- 
2.34.1



[PATCH RESEND 3/5] clk: also handle ENOENT in *_optional functions

2023-08-17 Thread Yang Xiwen via B4 Relay
From: Yang Xiwen 

If the device does not specify any clocks in device tree, these
functions will return PTR_ERR(-ENOENT). This is not the intended
behavior and does not comply with linux kernel CCF. Fix that by
returning NULL under such circumstances instead.

Signed-off-by: Yang Xiwen 
---
 include/clk.h | 8 +---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/include/clk.h b/include/clk.h
index d91285235f..f95da0838d 100644
--- a/include/clk.h
+++ b/include/clk.h
@@ -223,9 +223,11 @@ struct clk *devm_clk_get(struct udevice *dev, const char 
*id);
 static inline struct clk *devm_clk_get_optional(struct udevice *dev,
const char *id)
 {
+   int ret;
struct clk *clk = devm_clk_get(dev, id);
 
-   if (PTR_ERR(clk) == -ENODATA)
+   ret = PTR_ERR(clk);
+   if (ret == -ENODATA || ret == -ENOENT)
return NULL;
 
return clk;
@@ -335,7 +337,7 @@ static inline int clk_get_by_name_optional(struct udevice 
*dev,
int ret;
 
ret = clk_get_by_name(dev, name, clk);
-   if (ret == -ENODATA)
+   if (ret == -ENODATA || ret == -ENOENT)
return 0;
 
return ret;
@@ -359,7 +361,7 @@ static inline int clk_get_by_name_nodev_optional(ofnode 
node, const char *name,
int ret;
 
ret = clk_get_by_name_nodev(node, name, clk);
-   if (ret == -ENODATA)
+   if (ret == -ENODATA || ret == -ENOENT)
return 0;
 
return ret;

-- 
2.34.1



[PATCH RESEND 1/5] clk: export clk_register_mux_table()

2023-08-17 Thread Yang Xiwen via B4 Relay
From: Yang Xiwen 

It's already implemented in clk-mux.c, export it in the header file.

Signed-off-by: Yang Xiwen 
---
 include/linux/clk-provider.h | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index b8acacd49e..801404480b 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -247,6 +247,12 @@ struct clk *clk_register_mux(struct device *dev, const 
char *name,
void __iomem *reg, u8 shift, u8 width,
u8 clk_mux_flags);
 
+struct clk *clk_register_mux_table(struct device *dev, const char *name,
+  const char * const *parent_names, u8 
num_parents,
+  unsigned long flags,
+  void __iomem *reg, u8 shift, u32 mask,
+  u8 clk_mux_flags, u32 *table);
+
 struct clk *clk_register_fixed_rate(struct device *dev, const char *name,
ulong rate);
 

-- 
2.34.1



[PATCH RESEND 0/5] clk: A few bugfixes/enhancements for CCF

2023-08-17 Thread Yang Xiwen via B4 Relay
They are found during my development for HiSilicon clock driver. Details
are in commit logs.

Signed-off-by: Yang Xiwen 
---
Yang Xiwen (5):
  clk: export clk_register_mux_table()
  clk: call log_debug() instead to avoid console log printing
  clk: also handle ENOENT in *_optional functions
  clk: promote clk_dev_ops to linux/clk-provider.h
  clk: ccf: call clock provided ops directly for endisable()

 drivers/clk/clk-uclass.c |  5 -
 drivers/clk/clk.c| 16 +---
 include/clk.h|  8 +---
 include/linux/clk-provider.h | 11 +++
 4 files changed, 29 insertions(+), 11 deletions(-)
---
base-commit: 580eb31199be8a822e62f20965854a242f895d03
change-id: 20230807-clk-fix-17e895f79817

Best regards,
-- 
Yang Xiwen 



[PATCH v2 1/2] net: add hifemac Ethernet driver for HiSilicon platform

2023-08-13 Thread Yang Xiwen via B4 Relay
From: Yang Xiwen 

It adds the driver for HIFEMAC Ethernet controller found on HiSilicon
SoCs like Hi3798MV200.  It's based on the mainstream linux driver, but
quite a lot of code gets rewritten and cleaned up to adopt u-boot driver
model.

Signed-off-by: Yang Xiwen 
---
 drivers/net/Kconfig   |   9 +
 drivers/net/Makefile  |   1 +
 drivers/net/hifemac.c | 481 ++
 3 files changed, 491 insertions(+)

diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 39eee98ca7..bc1d6e3905 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -886,6 +886,15 @@ config MEDIATEK_ETH
  This Driver support MediaTek Ethernet GMAC
  Say Y to enable support for the MediaTek Ethernet GMAC.
 
+config HIFEMAC_ETH
+   bool "HiSilicon Fast Ethernet Controller"
+   select DM_CLK
+   select DM_RESET
+   select PHYLIB
+   help
+ This driver supports HIFEMAC Ethernet controller found on
+ HiSilicon SoCs.
+
 config HIGMACV300_ETH
bool "HiSilicon Gigabit Ethernet Controller"
select DM_RESET
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index 46a40e2ed9..de6bf1d014 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -45,6 +45,7 @@ obj-$(CONFIG_FSL_PFE) += pfe_eth/
 obj-$(CONFIG_FTGMAC100) += ftgmac100.o
 obj-$(CONFIG_FTMAC100) += ftmac100.o
 obj-$(CONFIG_GMAC_ROCKCHIP) += gmac_rockchip.o
+obj-$(CONFIG_HIFEMAC_ETH) += hifemac.o
 obj-$(CONFIG_HIGMACV300_ETH) += higmacv300.o
 obj-$(CONFIG_KS8851_MLL) += ks8851_mll.o
 obj-$(CONFIG_KSZ9477) += ksz9477.o
diff --git a/drivers/net/hifemac.c b/drivers/net/hifemac.c
new file mode 100644
index 00..b61a29e636
--- /dev/null
+++ b/drivers/net/hifemac.c
@@ -0,0 +1,481 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Hisilicon Fast Ethernet MAC Driver
+ * Adapted from linux
+ *
+ * Copyright (c) 2016 HiSilicon Technologies Co., Ltd.
+ * Copyright (c) 2023 Yang Xiwen 
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+/* MAC control register list */
+#define MAC_PORTSEL0x0200
+#define MAC_PORTSEL_STAT_CPU   BIT(0)
+#define MAC_PORTSEL_RMII   BIT(1)
+#define MAC_PORTSET0x0208
+#define MAC_PORTSET_DUPLEX_FULLBIT(0)
+#define MAC_PORTSET_LINKED BIT(1)
+#define MAC_PORTSET_SPEED_100M BIT(2)
+#define MAC_SET0x0210
+#define MAX_FRAME_SIZE 1600
+#define MAX_FRAME_SIZE_MASKGENMASK(10, 0)
+#define BIT_PAUSE_EN   BIT(18)
+#define RX_COALESCE_SET0x0340
+#define RX_COALESCED_FRAME_OFFSET  24
+#define RX_COALESCED_FRAMES8
+#define RX_COALESCED_TIMER 0x74
+#define QLEN_SET   0x0344
+#define RX_DEPTH_OFFSET8
+#define MAX_HW_FIFO_DEPTH  64
+#define HW_TX_FIFO_DEPTH   1
+#define MAX_HW_RX_FIFO_DEPTH   (MAX_HW_FIFO_DEPTH - HW_TX_FIFO_DEPTH)
+#define HW_RX_FIFO_DEPTH   min(PKTBUFSRX, MAX_HW_RX_FIFO_DEPTH)
+#define IQFRM_DES  0x0354
+#define RX_FRAME_LEN_MASK  GENMASK(11, 0)
+#define RX_FRAME_IN_INDEX_MASK GENMASK(17, 12)
+#define IQ_ADDR0x0358
+#define EQ_ADDR0x0360
+#define EQFRM_LEN  0x0364
+#define ADDRQ_STAT 0x036C
+#define TX_CNT_INUSE_MASK  GENMASK(5, 0)
+#define BIT_TX_READY   BIT(24)
+#define BIT_RX_READY   BIT(25)
+/* global control register list */
+#define GLB_HOSTMAC_L320x
+#define GLB_HOSTMAC_H160x0004
+#define GLB_SOFT_RESET 0x0008
+#define SOFT_RESET_ALL BIT(0)
+#define GLB_FWCTRL 0x0010
+#define FWCTRL_VLAN_ENABLE BIT(0)
+#define FWCTRL_FW2CPU_ENA  BIT(5)
+#define FWCTRL_FWALL2CPU   BIT(7)
+#define GLB_MACTCTRL   0x0014
+#define MACTCTRL_UNI2CPU   BIT(1)
+#define MACTCTRL_MULTI2CPU BIT(3)
+#define MACTCTRL_BROAD2CPU BIT(5)
+#define MACTCTRL_MACT_ENA  BIT(7)
+#define GLB_IRQ_STAT   0x0030
+#define GLB_IRQ_ENA0x0034
+#define IRQ_ENA_PORT0_MASK GENMASK(7, 0)
+#define IRQ_ENA_PORT0  BIT(18)
+#define IRQ_ENA_ALLBIT(19)
+#define GLB_IRQ_RAW0x0038
+#define IRQ_INT_RX_RDY BIT(0)
+#define IRQ_INT_TX_PER_PACKET  BIT(1)
+#define IRQ_INT_TX_FIFO_EMPTY  BIT(6)
+#define IRQ_INT_MULTI_RXRDYBIT(7)
+#define DEF_INT_MASK   (IRQ_INT_MULTI_RXRDY | \
+   IRQ_INT_TX_PER_PACKET | \
+  

[PATCH v2 0/2] net: add support for HiSilicon Fast Ethernet Controller driver

2023-08-13 Thread Yang Xiwen via B4 Relay
This core is found on many HiSilicon chips. This patchset adds support
for it and the integrated MDIO bus.

The driver code comes from linux kernel driver, downstream u-boot driver
and the datasheet. It's already tested on a Hi3798MV200 based STB.

Note that currently this driver can't be used for Hi3798MV200 since the
clock driver is missing. I will implement and submit the clock driver
and the framework in a later patchset.

Signed-off-by: Yang Xiwen 
---
Changes in v2:
- hisi_femac: clear previous irq before sending
- Link to v1: 
https://lore.kernel.org/r/20230725-wip-hisi_femac-trunk-v1-0-88469a170...@outlook.com

---
Yang Xiwen (2):
  net: add hifemac Ethernet driver for HiSilicon platform
  net: add hifemac_mdio MDIO bus driver for HiSilicon platform

 drivers/net/Kconfig|  17 ++
 drivers/net/Makefile   |   2 +
 drivers/net/hifemac.c  | 481 +
 drivers/net/hifemac_mdio.c | 116 +++
 4 files changed, 616 insertions(+)
---
base-commit: 580eb31199be8a822e62f20965854a242f895d03
change-id: 20230724-wip-hisi_femac-trunk-1f57f0986f0c

Best regards,
-- 
Yang Xiwen 



[PATCH v2 2/2] net: add hifemac_mdio MDIO bus driver for HiSilicon platform

2023-08-13 Thread Yang Xiwen via B4 Relay
From: Yang Xiwen 

It adds the driver for the internal MDIO bus of HIFEMAC Ethernet
controller.  It's based on the mainstream linux driver.

Signed-off-by: Yang Xiwen 
---
 drivers/net/Kconfig|   8 
 drivers/net/Makefile   |   1 +
 drivers/net/hifemac_mdio.c | 116 +
 3 files changed, 125 insertions(+)

diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index bc1d6e3905..5c5bfb1263 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -895,6 +895,14 @@ config HIFEMAC_ETH
  This driver supports HIFEMAC Ethernet controller found on
  HiSilicon SoCs.
 
+config HIFEMAC_MDIO
+   bool "HiSilicon Fast Ethernet Controller MDIO interface"
+   depends on DM_MDIO
+   select DM_CLK
+   help
+ This driver supports the internal MDIO interface of HIFEMAC
+ Ethernet controller.
+
 config HIGMACV300_ETH
bool "HiSilicon Gigabit Ethernet Controller"
select DM_RESET
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index de6bf1d014..b2d3da6934 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -46,6 +46,7 @@ obj-$(CONFIG_FTGMAC100) += ftgmac100.o
 obj-$(CONFIG_FTMAC100) += ftmac100.o
 obj-$(CONFIG_GMAC_ROCKCHIP) += gmac_rockchip.o
 obj-$(CONFIG_HIFEMAC_ETH) += hifemac.o
+obj-$(CONFIG_HIFEMAC_MDIO) += hifemac_mdio.o
 obj-$(CONFIG_HIGMACV300_ETH) += higmacv300.o
 obj-$(CONFIG_KS8851_MLL) += ks8851_mll.o
 obj-$(CONFIG_KSZ9477) += ksz9477.o
diff --git a/drivers/net/hifemac_mdio.c b/drivers/net/hifemac_mdio.c
new file mode 100644
index 00..343c5f3a38
--- /dev/null
+++ b/drivers/net/hifemac_mdio.c
@@ -0,0 +1,116 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Hisilicon Fast Ethernet MDIO Bus Driver
+ *
+ * Copyright (c) 2016 HiSilicon Technologies Co., Ltd.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define MDIO_RWCTRL0x00
+#define MDIO_RO_DATA   0x04
+#define MDIO_WRITE BIT(13)
+#define MDIO_RW_FINISH BIT(15)
+#define BIT_PHY_ADDR_OFFSET8
+#define BIT_WR_DATA_OFFSET 16
+
+struct hisi_femac_mdio_data {
+   struct clk *clk;
+   void __iomem *membase;
+};
+
+static int hisi_femac_mdio_wait_ready(struct hisi_femac_mdio_data *data)
+{
+   u32 val;
+
+   return readl_poll_timeout(data->membase + MDIO_RWCTRL,
+ val, val & MDIO_RW_FINISH, 1);
+}
+
+static int hisi_femac_mdio_read(struct udevice *dev, int addr, int devad, int 
reg)
+{
+   struct hisi_femac_mdio_data *data = dev_get_priv(dev);
+   int ret;
+
+   ret = hisi_femac_mdio_wait_ready(data);
+   if (ret)
+   return ret;
+
+   writel((addr << BIT_PHY_ADDR_OFFSET) | reg,
+  data->membase + MDIO_RWCTRL);
+
+   ret = hisi_femac_mdio_wait_ready(data);
+   if (ret)
+   return ret;
+
+   return readl(data->membase + MDIO_RO_DATA) & 0x;
+}
+
+static int hisi_femac_mdio_write(struct udevice *dev, int addr, int devad, int 
reg, u16 val)
+{
+   struct hisi_femac_mdio_data *data = dev_get_priv(dev);
+   int ret;
+
+   ret = hisi_femac_mdio_wait_ready(data);
+   if (ret)
+   return ret;
+
+   writel(MDIO_WRITE | (val << BIT_WR_DATA_OFFSET) |
+  (addr << BIT_PHY_ADDR_OFFSET) | reg,
+  data->membase + MDIO_RWCTRL);
+
+   return hisi_femac_mdio_wait_ready(data);
+}
+
+static int hisi_femac_mdio_of_to_plat(struct udevice *dev)
+{
+   struct hisi_femac_mdio_data *data = dev_get_priv(dev);
+   int ret;
+
+   data->membase = dev_remap_addr(dev);
+   if (IS_ERR(data->membase)) {
+   ret = PTR_ERR(data->membase);
+   return log_msg_ret("Failed to remap base addr", ret);
+   }
+
+   // clk is optional
+   data->clk = devm_clk_get_optional(dev, NULL);
+
+   return 0;
+}
+
+static int hisi_femac_mdio_probe(struct udevice *dev)
+{
+   struct hisi_femac_mdio_data *data = dev_get_priv(dev);
+   int ret;
+
+   ret = clk_prepare_enable(data->clk);
+   if (ret)
+   return log_msg_ret("Failed to enable clk", ret);
+
+   return 0;
+}
+
+static const struct mdio_ops hisi_femac_mdio_ops = {
+   .read = hisi_femac_mdio_read,
+   .write = hisi_femac_mdio_write,
+};
+
+static const struct udevice_id hisi_femac_mdio_dt_ids[] = {
+   { .compatible = "hisilicon,hisi-femac-mdio" },
+   { }
+};
+
+U_BOOT_DRIVER(hisi_femac_mdio_driver) = {
+   .name = "hisi-femac-mdio",
+   .id = UCLASS_MDIO,
+   .of_match = hisi_femac_mdio_dt_ids,
+   .of_to_plat = hisi_femac_mdio_of_to_plat,
+   .probe = hisi_femac_mdio_probe,
+   .ops = _femac_mdio_ops,
+   .priv_auto = sizeof(struct hisi_femac_mdio_data),
+};

-- 
2.34.1



[PATCH 4/5] clk: promote clk_dev_ops to linux/clk-provider.h

2023-08-08 Thread Yang Xiwen via B4 Relay
From: Yang Xiwen 

So that it can be used by others.

Signed-off-by: Yang Xiwen 
---
 drivers/clk/clk-uclass.c | 5 -
 include/linux/clk-provider.h | 5 +
 2 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/drivers/clk/clk-uclass.c b/drivers/clk/clk-uclass.c
index dc3e9d6a26..5cc80e5e39 100644
--- a/drivers/clk/clk-uclass.c
+++ b/drivers/clk/clk-uclass.c
@@ -25,11 +25,6 @@
 #include 
 #include 
 
-static inline const struct clk_ops *clk_dev_ops(struct udevice *dev)
-{
-   return (const struct clk_ops *)dev->driver->ops;
-}
-
 struct clk *dev_get_clk_ptr(struct udevice *dev)
 {
return (struct clk *)dev_get_uclass_priv(dev);
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index 801404480b..dfafb4cc9d 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -21,6 +21,11 @@ static inline void clk_dm(ulong id, struct clk *clk)
clk->id = id;
 }
 
+static inline const struct clk_ops *clk_dev_ops(struct udevice *dev)
+{
+   return (const struct clk_ops *)dev->driver->ops;
+}
+
 /*
  * flags used across common struct clk.  these flags should only affect the
  * top-level framework.  custom flags for dealing with hardware specifics

-- 
2.34.1



[PATCH 5/5] clk: ccf: call clock provided ops directly for endisable()

2023-08-08 Thread Yang Xiwen via B4 Relay
From: Yang Xiwen 

Calling into CCF framework will cause a clock being enabled twice
instead of once (clk->enable_count becomes 2 rather than 1), thus making
it hard to disable (needs to call clk_disable() twice).
Fix that by calling clock provided ops directly.

Signed-off-by: Yang Xiwen 
---
 drivers/clk/clk.c | 12 +++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index a38daaac0c..00d082c46f 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -14,6 +14,7 @@
 #include 
 #include 
 #include 
+#include 
 
 int clk_register(struct clk *clk, const char *drv_name,
 const char *name, const char *parent_name)
@@ -115,11 +116,20 @@ int ccf_clk_set_parent(struct clk *clk, struct clk 
*parent)
 static int ccf_clk_endisable(struct clk *clk, bool enable)
 {
struct clk *c;
+   const struct clk_ops *ops;
int err = clk_get_by_id(clk->id, );
 
if (err)
return err;
-   return enable ? clk_enable(c) : clk_disable(c);
+   else
+   ops = clk_dev_ops(c->dev);
+
+   if (enable && ops->enable)
+   return ops->enable(c);
+   else if (!enable && ops->disable)
+   return ops->disable(c);
+
+   return -ENOSYS;
 }
 
 int ccf_clk_enable(struct clk *clk)

-- 
2.34.1



[PATCH 2/5] clk: call log_debug() instead to avoid console log printing

2023-08-08 Thread Yang Xiwen via B4 Relay
From: Yang Xiwen 

it's a very common case to register a clock without a parent, such as
clk_register_fixed_rate(). Replace log_error() with log_debug() to avoid
useless console log if not debugging.

Signed-off-by: Yang Xiwen 
---
 drivers/clk/clk.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index a5a3461b66..a38daaac0c 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -24,8 +24,8 @@ int clk_register(struct clk *clk, const char *drv_name,
 
ret = uclass_get_device_by_name(UCLASS_CLK, parent_name, );
if (ret) {
-   log_err("%s: failed to get %s device (parent of %s)\n",
-   __func__, parent_name, name);
+   log_debug("%s: failed to get %s device (parent of %s)\n",
+ __func__, parent_name, name);
} else {
log_debug("%s: name: %s parent: %s [0x%p]\n", __func__, name,
  parent->name, parent);

-- 
2.34.1



[PATCH 3/5] clk: also handle ENOENT in *_optional functions

2023-08-08 Thread Yang Xiwen via B4 Relay
From: Yang Xiwen 

If the device does not specify any clocks in device tree, these
functions will return PTR_ERR(-ENOENT). This is not the intended
behavior and does not comply with linux kernel CCF. Fix that by
returning NULL under such circumstances instead.

Signed-off-by: Yang Xiwen 
---
 include/clk.h | 8 +---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/include/clk.h b/include/clk.h
index d91285235f..f95da0838d 100644
--- a/include/clk.h
+++ b/include/clk.h
@@ -223,9 +223,11 @@ struct clk *devm_clk_get(struct udevice *dev, const char 
*id);
 static inline struct clk *devm_clk_get_optional(struct udevice *dev,
const char *id)
 {
+   int ret;
struct clk *clk = devm_clk_get(dev, id);
 
-   if (PTR_ERR(clk) == -ENODATA)
+   ret = PTR_ERR(clk);
+   if (ret == -ENODATA || ret == -ENOENT)
return NULL;
 
return clk;
@@ -335,7 +337,7 @@ static inline int clk_get_by_name_optional(struct udevice 
*dev,
int ret;
 
ret = clk_get_by_name(dev, name, clk);
-   if (ret == -ENODATA)
+   if (ret == -ENODATA || ret == -ENOENT)
return 0;
 
return ret;
@@ -359,7 +361,7 @@ static inline int clk_get_by_name_nodev_optional(ofnode 
node, const char *name,
int ret;
 
ret = clk_get_by_name_nodev(node, name, clk);
-   if (ret == -ENODATA)
+   if (ret == -ENODATA || ret == -ENOENT)
return 0;
 
return ret;

-- 
2.34.1



[PATCH 0/5] clk: A few bugfixes/enhancements for CCF

2023-08-08 Thread Yang Xiwen via B4 Relay
They are found during my development for HiSilicon clock driver. Details
are in commit logs.

Signed-off-by: Yang Xiwen 
---
Yang Xiwen (5):
  clk: export clk_register_mux_table()
  clk: call log_debug() instead to avoid console log printing
  clk: also handle ENOENT in *_optional functions
  clk: promote clk_dev_ops to linux/clk-provider.h
  clk: ccf: call clock provided ops directly for endisable()

 drivers/clk/clk-uclass.c |  5 -
 drivers/clk/clk.c| 16 +---
 include/clk.h|  8 +---
 include/linux/clk-provider.h | 11 +++
 4 files changed, 29 insertions(+), 11 deletions(-)
---
base-commit: 580eb31199be8a822e62f20965854a242f895d03
change-id: 20230807-clk-fix-17e895f79817

Best regards,
-- 
Yang Xiwen 



[PATCH 1/5] clk: export clk_register_mux_table()

2023-08-08 Thread Yang Xiwen via B4 Relay
From: Yang Xiwen 

It's already implemented in clk-mux.c, export it in the header file.

Signed-off-by: Yang Xiwen 
---
 include/linux/clk-provider.h | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index b8acacd49e..801404480b 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -247,6 +247,12 @@ struct clk *clk_register_mux(struct device *dev, const 
char *name,
void __iomem *reg, u8 shift, u8 width,
u8 clk_mux_flags);
 
+struct clk *clk_register_mux_table(struct device *dev, const char *name,
+  const char * const *parent_names, u8 
num_parents,
+  unsigned long flags,
+  void __iomem *reg, u8 shift, u32 mask,
+  u8 clk_mux_flags, u32 *table);
+
 struct clk *clk_register_fixed_rate(struct device *dev, const char *name,
ulong rate);
 

-- 
2.34.1



[PATCH] clk: also return NULL for -ENOENT in devm_clk_get_optional functions

2023-07-24 Thread Yang Xiwen via B4 Relay
From: Yang Xiwen 

As described by the doc.

Signed-off-by: Yang Xiwen 
---
Handle both ENODATA and ENOENT.
---
 include/clk.h | 7 ---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/include/clk.h b/include/clk.h
index d91285235f..c9aa2360e1 100644
--- a/include/clk.h
+++ b/include/clk.h
@@ -224,8 +224,9 @@ static inline struct clk *devm_clk_get_optional(struct 
udevice *dev,
const char *id)
 {
struct clk *clk = devm_clk_get(dev, id);
+   int ret = PTR_ERR(clk);
 
-   if (PTR_ERR(clk) == -ENODATA)
+   if (ret == -ENODATA || ret == -ENOENT)
return NULL;
 
return clk;
@@ -335,7 +336,7 @@ static inline int clk_get_by_name_optional(struct udevice 
*dev,
int ret;
 
ret = clk_get_by_name(dev, name, clk);
-   if (ret == -ENODATA)
+   if (ret == -ENODATA || ret == -ENOENT)
return 0;
 
return ret;
@@ -359,7 +360,7 @@ static inline int clk_get_by_name_nodev_optional(ofnode 
node, const char *name,
int ret;
 
ret = clk_get_by_name_nodev(node, name, clk);
-   if (ret == -ENODATA)
+   if (ret == -ENODATA || ret == -ENOENT)
return 0;
 
return ret;

---
base-commit: 580eb31199be8a822e62f20965854a242f895d03
change-id: 20230725-clk-fix-inc-903aa0540739

Best regards,
-- 
Yang Xiwen 



[PATCH 1/2] net: add hifemac Ethernet driver for HiSilicon platform

2023-07-24 Thread Yang Xiwen via B4 Relay
From: Yang Xiwen 

It adds the driver for HIFEMAC Ethernet controller found on HiSilicon
SoCs like Hi3798MV200.  It's based on the mainstream linux driver, but
quite a lot of code gets rewritten and cleaned up to adopt u-boot driver
model.

Signed-off-by: Yang Xiwen 
---
 drivers/net/Kconfig   |   9 +
 drivers/net/Makefile  |   1 +
 drivers/net/hifemac.c | 478 ++
 3 files changed, 488 insertions(+)

diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 39eee98ca7..bc1d6e3905 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -886,6 +886,15 @@ config MEDIATEK_ETH
  This Driver support MediaTek Ethernet GMAC
  Say Y to enable support for the MediaTek Ethernet GMAC.
 
+config HIFEMAC_ETH
+   bool "HiSilicon Fast Ethernet Controller"
+   select DM_CLK
+   select DM_RESET
+   select PHYLIB
+   help
+ This driver supports HIFEMAC Ethernet controller found on
+ HiSilicon SoCs.
+
 config HIGMACV300_ETH
bool "HiSilicon Gigabit Ethernet Controller"
select DM_RESET
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index 46a40e2ed9..de6bf1d014 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -45,6 +45,7 @@ obj-$(CONFIG_FSL_PFE) += pfe_eth/
 obj-$(CONFIG_FTGMAC100) += ftgmac100.o
 obj-$(CONFIG_FTMAC100) += ftmac100.o
 obj-$(CONFIG_GMAC_ROCKCHIP) += gmac_rockchip.o
+obj-$(CONFIG_HIFEMAC_ETH) += hifemac.o
 obj-$(CONFIG_HIGMACV300_ETH) += higmacv300.o
 obj-$(CONFIG_KS8851_MLL) += ks8851_mll.o
 obj-$(CONFIG_KSZ9477) += ksz9477.o
diff --git a/drivers/net/hifemac.c b/drivers/net/hifemac.c
new file mode 100644
index 00..bd0e3c5c5f
--- /dev/null
+++ b/drivers/net/hifemac.c
@@ -0,0 +1,478 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Hisilicon Fast Ethernet MAC Driver
+ * Adapted from linux
+ *
+ * Copyright (c) 2016 HiSilicon Technologies Co., Ltd.
+ * Copyright (c) 2023 Yang Xiwen 
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+/* MAC control register list */
+#define MAC_PORTSEL0x0200
+#define MAC_PORTSEL_STAT_CPU   BIT(0)
+#define MAC_PORTSEL_RMII   BIT(1)
+#define MAC_PORTSET0x0208
+#define MAC_PORTSET_DUPLEX_FULLBIT(0)
+#define MAC_PORTSET_LINKED BIT(1)
+#define MAC_PORTSET_SPEED_100M BIT(2)
+#define MAC_SET0x0210
+#define MAX_FRAME_SIZE 1600
+#define MAX_FRAME_SIZE_MASKGENMASK(10, 0)
+#define BIT_PAUSE_EN   BIT(18)
+#define RX_COALESCE_SET0x0340
+#define RX_COALESCED_FRAME_OFFSET  24
+#define RX_COALESCED_FRAMES8
+#define RX_COALESCED_TIMER 0x74
+#define QLEN_SET   0x0344
+#define RX_DEPTH_OFFSET8
+#define MAX_HW_FIFO_DEPTH  64
+#define HW_TX_FIFO_DEPTH   1
+#define MAX_HW_RX_FIFO_DEPTH   (MAX_HW_FIFO_DEPTH - HW_TX_FIFO_DEPTH)
+#define HW_RX_FIFO_DEPTH   min(PKTBUFSRX, MAX_HW_RX_FIFO_DEPTH)
+#define IQFRM_DES  0x0354
+#define RX_FRAME_LEN_MASK  GENMASK(11, 0)
+#define RX_FRAME_IN_INDEX_MASK GENMASK(17, 12)
+#define IQ_ADDR0x0358
+#define EQ_ADDR0x0360
+#define EQFRM_LEN  0x0364
+#define ADDRQ_STAT 0x036C
+#define TX_CNT_INUSE_MASK  GENMASK(5, 0)
+#define BIT_TX_READY   BIT(24)
+#define BIT_RX_READY   BIT(25)
+/* global control register list */
+#define GLB_HOSTMAC_L320x
+#define GLB_HOSTMAC_H160x0004
+#define GLB_SOFT_RESET 0x0008
+#define SOFT_RESET_ALL BIT(0)
+#define GLB_FWCTRL 0x0010
+#define FWCTRL_VLAN_ENABLE BIT(0)
+#define FWCTRL_FW2CPU_ENA  BIT(5)
+#define FWCTRL_FWALL2CPU   BIT(7)
+#define GLB_MACTCTRL   0x0014
+#define MACTCTRL_UNI2CPU   BIT(1)
+#define MACTCTRL_MULTI2CPU BIT(3)
+#define MACTCTRL_BROAD2CPU BIT(5)
+#define MACTCTRL_MACT_ENA  BIT(7)
+#define GLB_IRQ_STAT   0x0030
+#define GLB_IRQ_ENA0x0034
+#define IRQ_ENA_PORT0_MASK GENMASK(7, 0)
+#define IRQ_ENA_PORT0  BIT(18)
+#define IRQ_ENA_ALLBIT(19)
+#define GLB_IRQ_RAW0x0038
+#define IRQ_INT_RX_RDY BIT(0)
+#define IRQ_INT_TX_PER_PACKET  BIT(1)
+#define IRQ_INT_TX_FIFO_EMPTY  BIT(6)
+#define IRQ_INT_MULTI_RXRDYBIT(7)
+#define DEF_INT_MASK   (IRQ_INT_MULTI_RXRDY | \
+   IRQ_INT_TX_PER_PACKET | \
+  

[PATCH 0/2] net: add support for HiSilicon Fast Ethernet Controller driver

2023-07-24 Thread Yang Xiwen via B4 Relay
This core is found on many HiSilicon chips. This patchset adds support
for it and the integrated MDIO bus.

The driver code comes from linux kernel driver, downstream u-boot driver
and the datasheet. It's already tested on a Hi3798MV200 based STB.

Note that currently this driver can't be used for Hi3798MV200 since the
clock driver is missing. I will implement and submit the clock driver
and the framework in a later patchset.

Signed-off-by: Yang Xiwen 
---
Yang Xiwen (2):
  net: add hifemac Ethernet driver for HiSilicon platform
  net: add hifemac_mdio MDIO bus driver for HiSilicon platform

 drivers/net/Kconfig|  17 ++
 drivers/net/Makefile   |   2 +
 drivers/net/hifemac.c  | 478 +
 drivers/net/hifemac_mdio.c | 116 +++
 4 files changed, 613 insertions(+)
---
base-commit: 580eb31199be8a822e62f20965854a242f895d03
change-id: 20230724-wip-hisi_femac-trunk-1f57f0986f0c

Best regards,
-- 
Yang Xiwen 



[PATCH 2/2] net: add hifemac_mdio MDIO bus driver for HiSilicon platform

2023-07-24 Thread Yang Xiwen via B4 Relay
From: Yang Xiwen 

It adds the driver for the internal MDIO bus of HIFEMAC Ethernet
controller.  It's based on the mainstream linux driver.

Signed-off-by: Yang Xiwen 
---
 drivers/net/Kconfig|   8 
 drivers/net/Makefile   |   1 +
 drivers/net/hifemac_mdio.c | 116 +
 3 files changed, 125 insertions(+)

diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index bc1d6e3905..5c5bfb1263 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -895,6 +895,14 @@ config HIFEMAC_ETH
  This driver supports HIFEMAC Ethernet controller found on
  HiSilicon SoCs.
 
+config HIFEMAC_MDIO
+   bool "HiSilicon Fast Ethernet Controller MDIO interface"
+   depends on DM_MDIO
+   select DM_CLK
+   help
+ This driver supports the internal MDIO interface of HIFEMAC
+ Ethernet controller.
+
 config HIGMACV300_ETH
bool "HiSilicon Gigabit Ethernet Controller"
select DM_RESET
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index de6bf1d014..b2d3da6934 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -46,6 +46,7 @@ obj-$(CONFIG_FTGMAC100) += ftgmac100.o
 obj-$(CONFIG_FTMAC100) += ftmac100.o
 obj-$(CONFIG_GMAC_ROCKCHIP) += gmac_rockchip.o
 obj-$(CONFIG_HIFEMAC_ETH) += hifemac.o
+obj-$(CONFIG_HIFEMAC_MDIO) += hifemac_mdio.o
 obj-$(CONFIG_HIGMACV300_ETH) += higmacv300.o
 obj-$(CONFIG_KS8851_MLL) += ks8851_mll.o
 obj-$(CONFIG_KSZ9477) += ksz9477.o
diff --git a/drivers/net/hifemac_mdio.c b/drivers/net/hifemac_mdio.c
new file mode 100644
index 00..343c5f3a38
--- /dev/null
+++ b/drivers/net/hifemac_mdio.c
@@ -0,0 +1,116 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Hisilicon Fast Ethernet MDIO Bus Driver
+ *
+ * Copyright (c) 2016 HiSilicon Technologies Co., Ltd.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define MDIO_RWCTRL0x00
+#define MDIO_RO_DATA   0x04
+#define MDIO_WRITE BIT(13)
+#define MDIO_RW_FINISH BIT(15)
+#define BIT_PHY_ADDR_OFFSET8
+#define BIT_WR_DATA_OFFSET 16
+
+struct hisi_femac_mdio_data {
+   struct clk *clk;
+   void __iomem *membase;
+};
+
+static int hisi_femac_mdio_wait_ready(struct hisi_femac_mdio_data *data)
+{
+   u32 val;
+
+   return readl_poll_timeout(data->membase + MDIO_RWCTRL,
+ val, val & MDIO_RW_FINISH, 1);
+}
+
+static int hisi_femac_mdio_read(struct udevice *dev, int addr, int devad, int 
reg)
+{
+   struct hisi_femac_mdio_data *data = dev_get_priv(dev);
+   int ret;
+
+   ret = hisi_femac_mdio_wait_ready(data);
+   if (ret)
+   return ret;
+
+   writel((addr << BIT_PHY_ADDR_OFFSET) | reg,
+  data->membase + MDIO_RWCTRL);
+
+   ret = hisi_femac_mdio_wait_ready(data);
+   if (ret)
+   return ret;
+
+   return readl(data->membase + MDIO_RO_DATA) & 0x;
+}
+
+static int hisi_femac_mdio_write(struct udevice *dev, int addr, int devad, int 
reg, u16 val)
+{
+   struct hisi_femac_mdio_data *data = dev_get_priv(dev);
+   int ret;
+
+   ret = hisi_femac_mdio_wait_ready(data);
+   if (ret)
+   return ret;
+
+   writel(MDIO_WRITE | (val << BIT_WR_DATA_OFFSET) |
+  (addr << BIT_PHY_ADDR_OFFSET) | reg,
+  data->membase + MDIO_RWCTRL);
+
+   return hisi_femac_mdio_wait_ready(data);
+}
+
+static int hisi_femac_mdio_of_to_plat(struct udevice *dev)
+{
+   struct hisi_femac_mdio_data *data = dev_get_priv(dev);
+   int ret;
+
+   data->membase = dev_remap_addr(dev);
+   if (IS_ERR(data->membase)) {
+   ret = PTR_ERR(data->membase);
+   return log_msg_ret("Failed to remap base addr", ret);
+   }
+
+   // clk is optional
+   data->clk = devm_clk_get_optional(dev, NULL);
+
+   return 0;
+}
+
+static int hisi_femac_mdio_probe(struct udevice *dev)
+{
+   struct hisi_femac_mdio_data *data = dev_get_priv(dev);
+   int ret;
+
+   ret = clk_prepare_enable(data->clk);
+   if (ret)
+   return log_msg_ret("Failed to enable clk", ret);
+
+   return 0;
+}
+
+static const struct mdio_ops hisi_femac_mdio_ops = {
+   .read = hisi_femac_mdio_read,
+   .write = hisi_femac_mdio_write,
+};
+
+static const struct udevice_id hisi_femac_mdio_dt_ids[] = {
+   { .compatible = "hisilicon,hisi-femac-mdio" },
+   { }
+};
+
+U_BOOT_DRIVER(hisi_femac_mdio_driver) = {
+   .name = "hisi-femac-mdio",
+   .id = UCLASS_MDIO,
+   .of_match = hisi_femac_mdio_dt_ids,
+   .of_to_plat = hisi_femac_mdio_of_to_plat,
+   .probe = hisi_femac_mdio_probe,
+   .ops = _femac_mdio_ops,
+   .priv_auto = sizeof(struct hisi_femac_mdio_data),
+};

-- 
2.34.1



[PATCH 1/2] clk: move clk_get_ops() to a common header

2023-07-23 Thread Yang Xiwen via B4 Relay
From: Yang Xiwen 

This allows it to be used by other source files.

Signed-off-by: Yang Xiwen 
---
 drivers/clk/clk-uclass.c |  5 -
 include/clk.h| 17 +
 2 files changed, 17 insertions(+), 5 deletions(-)

diff --git a/drivers/clk/clk-uclass.c b/drivers/clk/clk-uclass.c
index dc3e9d6a26..5cc80e5e39 100644
--- a/drivers/clk/clk-uclass.c
+++ b/drivers/clk/clk-uclass.c
@@ -25,11 +25,6 @@
 #include 
 #include 
 
-static inline const struct clk_ops *clk_dev_ops(struct udevice *dev)
-{
-   return (const struct clk_ops *)dev->driver->ops;
-}
-
 struct clk *dev_get_clk_ptr(struct udevice *dev)
 {
return (struct clk *)dev_get_uclass_priv(dev);
diff --git a/include/clk.h b/include/clk.h
index d91285235f..bd3617e1e0 100644
--- a/include/clk.h
+++ b/include/clk.h
@@ -8,6 +8,7 @@
 #ifndef _CLK_H_
 #define _CLK_H_
 
+#include 
 #include 
 #include 
 #include 
@@ -258,6 +259,17 @@ int clk_release_all(struct clk *clk, int count);
  */
 void devm_clk_put(struct udevice *dev, struct clk *clk);
 
+/**
+ * clk_dev_ops - get ops of a clock
+ * @dev: clock device
+ *
+ * Return: ops of the clk
+ */
+static inline const struct clk_ops *clk_dev_ops(struct udevice *dev)
+{
+   return (const struct clk_ops *)dev->driver->ops;
+}
+
 #else
 
 static inline int clk_get_by_phandle(struct udevice *dev, const
@@ -315,6 +327,11 @@ static inline int clk_release_all(struct clk *clk, int 
count)
 static inline void devm_clk_put(struct udevice *dev, struct clk *clk)
 {
 }
+
+static inline const struct clk_ops *clk_dev_ops(struct udevice *dev)
+{
+   return ERR_PTR(-ENOSYS);
+}
 #endif
 
 /**

-- 
2.34.1



[PATCH 2/2] clk: ccf: invoke ops provided by clk directly

2023-07-23 Thread Yang Xiwen via B4 Relay
From: Yang Xiwen 

Invoking clk_enable() or clk_disable() in clk->ops context causes a
recursion, results in a clock being enabled twice.

Signed-off-by: Yang Xiwen 
---
 drivers/clk/clk.c | 10 --
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index a5a3461b66..bd455e44a4 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -10,7 +10,6 @@
 #include 
 #include 
 #include 
-#include 
 #include 
 #include 
 #include 
@@ -115,11 +114,18 @@ int ccf_clk_set_parent(struct clk *clk, struct clk 
*parent)
 static int ccf_clk_endisable(struct clk *clk, bool enable)
 {
struct clk *c;
+   const struct clk_ops *ops = clk_dev_ops(clk->dev);
int err = clk_get_by_id(clk->id, );
 
if (err)
return err;
-   return enable ? clk_enable(c) : clk_disable(c);
+
+   if (enable && ops->enable)
+   return ops->enable(c);
+   else if (!enable && ops->disable)
+   return ops->disable(c);
+
+   return 0;
 }
 
 int ccf_clk_enable(struct clk *clk)

-- 
2.34.1



[PATCH 0/2] clk: fix a bug in CCF which results in a clock being enabled twice.

2023-07-23 Thread Yang Xiwen via B4 Relay
Currently, ccf_clk_endisable() calls clk_enable() / clk_disable()
directly depending on the request. However, this function is also
referenced in clk->ops, which is also called in clk_enable() /
clk_disable().

This caused a recursion and made the clock enabled twice if clk_enable()
is invoked. So we have to call clk_disable() twice to disable the clock.
It can be easily reproduced with few extra lines of debug code.

Fix that by calling clk->ops->enable/disable directly in
ccf_clk_endisable() rather than using the framework functions.

Signed-off-by: Yang Xiwen 
---
Yang Xiwen (2):
  clk: move clk_get_ops() to a common header
  clk: ccf: invoke ops provided by clk directly

 drivers/clk/clk-uclass.c |  5 -
 drivers/clk/clk.c| 10 --
 include/clk.h| 17 +
 3 files changed, 25 insertions(+), 7 deletions(-)
---
base-commit: 580eb31199be8a822e62f20965854a242f895d03
change-id: 20230724-clk_fix-1b7265d663a8

Best regards,
-- 
Yang Xiwen