* [PATCH 1/3] of: add of_property_read_variable_uxx_array()
@ 2024-04-03 8:07 Sascha Hauer
2024-04-03 8:07 ` [PATCH 2/3] phy: rockchip: add pcie3 phy driver Sascha Hauer
` (2 more replies)
0 siblings, 3 replies; 6+ messages in thread
From: Sascha Hauer @ 2024-04-03 8:07 UTC (permalink / raw)
To: Barebox List
This adds of_property_read_variable_uxx_array() which allow to read
arrays from properties with min/max size boundaries. Code is directly
taken from Linux.
We already had of_property_read_variable_u64_array(), but without
min/max arguments. This one is updated to match the Kernel code.
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
drivers/of/base.c | 197 ++++++++++++++++++++++++++++++++++++++++++----
include/of.h | 40 +++++++++-
2 files changed, 218 insertions(+), 19 deletions(-)
diff --git a/drivers/of/base.c b/drivers/of/base.c
index b22959dabe..20cfa0274c 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -773,22 +773,24 @@ int of_match(struct device *dev, struct driver *drv)
return 0;
}
EXPORT_SYMBOL(of_match);
-
/**
* of_find_property_value_of_size
*
* @np: device node from which the property value is to be read.
* @propname: name of the property to be searched.
- * @len: requested length of property value
+ * @min: minimum allowed length of property value
+ * @max: maximum allowed length of property value (0 means unlimited)
+ * @len: if !=NULL, actual length is written to here
*
* Search for a property in a device node and valid the requested size.
- * Returns the property value on success, -EINVAL if the property does not
- * exist, -ENODATA if property does not have a value, and -EOVERFLOW if the
- * property data isn't large enough.
+ *
+ * Return: The property value on success, -EINVAL if the property does not
+ * exist, -ENODATA if property does not have a value, and -EOVERFLOW if the
+ * property data is too small or too large.
*
*/
static const void *of_find_property_value_of_size(const struct device_node *np,
- const char *propname, u32 len)
+ const char *propname, u32 min, u32 max, size_t *len)
{
struct property *prop = of_find_property(np, propname, NULL);
const void *value;
@@ -798,8 +800,13 @@ static const void *of_find_property_value_of_size(const struct device_node *np,
value = of_property_get_value(prop);
if (!value)
return ERR_PTR(-ENODATA);
- if (len > prop->length)
+ if (prop->length < min)
return ERR_PTR(-EOVERFLOW);
+ if (max && prop->length > max)
+ return ERR_PTR(-EOVERFLOW);
+
+ if (len)
+ *len = prop->length;
return value;
}
@@ -824,7 +831,8 @@ int of_property_read_u32_index(const struct device_node *np,
u32 index, u32 *out_value)
{
const u32 *val = of_find_property_value_of_size(np, propname,
- ((index + 1) * sizeof(*out_value)));
+ ((index + 1) * sizeof(*out_value)),
+ 0, NULL);
if (IS_ERR(val))
return PTR_ERR(val);
@@ -888,7 +896,8 @@ int of_property_read_u8_array(const struct device_node *np,
const char *propname, u8 *out_values, size_t sz)
{
const u8 *val = of_find_property_value_of_size(np, propname,
- (sz * sizeof(*out_values)));
+ (sz * sizeof(*out_values)),
+ 0, NULL);
if (IS_ERR(val))
return PTR_ERR(val);
@@ -921,7 +930,8 @@ int of_property_read_u16_array(const struct device_node *np,
const char *propname, u16 *out_values, size_t sz)
{
const __be16 *val = of_find_property_value_of_size(np, propname,
- (sz * sizeof(*out_values)));
+ (sz * sizeof(*out_values)),
+ 0, NULL);
if (IS_ERR(val))
return PTR_ERR(val);
@@ -953,7 +963,8 @@ int of_property_read_u32_array(const struct device_node *np,
size_t sz)
{
const __be32 *val = of_find_property_value_of_size(np, propname,
- (sz * sizeof(*out_values)));
+ (sz * sizeof(*out_values)),
+ 0, NULL);
if (IS_ERR(val))
return PTR_ERR(val);
@@ -981,7 +992,7 @@ int of_property_read_u64(const struct device_node *np, const char *propname,
u64 *out_value)
{
const __be32 *val = of_find_property_value_of_size(np, propname,
- sizeof(*out_value));
+ sizeof(*out_value), 0, NULL);
if (IS_ERR(val))
return PTR_ERR(val);
@@ -992,7 +1003,154 @@ int of_property_read_u64(const struct device_node *np, const char *propname,
EXPORT_SYMBOL_GPL(of_property_read_u64);
/**
- * of_property_read_u64_array - Find and read an array of 64 bit integers
+ * of_property_read_variable_u8_array - Find and read an array of u8 from a
+ * property, with bounds on the minimum and maximum array size.
+ *
+ * @np: device node from which the property value is to be read.
+ * @propname: name of the property to be searched.
+ * @out_values: pointer to found values.
+ * @sz_min: minimum number of array elements to read
+ * @sz_max: maximum number of array elements to read, if zero there is no
+ * upper limit on the number of elements in the dts entry but only
+ * sz_min will be read.
+ *
+ * Search for a property in a device node and read 8-bit value(s) from
+ * it.
+ *
+ * dts entry of array should be like:
+ * ``property = /bits/ 8 <0x50 0x60 0x70>;``
+ *
+ * Return: The number of elements read on success, -EINVAL if the property
+ * does not exist, -ENODATA if property does not have a value, and -EOVERFLOW
+ * if the property data is smaller than sz_min or longer than sz_max.
+ *
+ * The out_values is modified only if a valid u8 value can be decoded.
+ */
+int of_property_read_variable_u8_array(const struct device_node *np,
+ const char *propname, u8 *out_values,
+ size_t sz_min, size_t sz_max)
+{
+ size_t sz, count;
+ const u8 *val = of_find_property_value_of_size(np, propname,
+ (sz_min * sizeof(*out_values)),
+ (sz_max * sizeof(*out_values)),
+ &sz);
+
+ if (IS_ERR(val))
+ return PTR_ERR(val);
+
+ if (!sz_max)
+ sz = sz_min;
+ else
+ sz /= sizeof(*out_values);
+
+ count = sz;
+ while (count--)
+ *out_values++ = *val++;
+
+ return sz;
+}
+EXPORT_SYMBOL_GPL(of_property_read_variable_u8_array);
+
+/**
+ * of_property_read_variable_u16_array - Find and read an array of u16 from a
+ * property, with bounds on the minimum and maximum array size.
+ *
+ * @np: device node from which the property value is to be read.
+ * @propname: name of the property to be searched.
+ * @out_values: pointer to found values.
+ * @sz_min: minimum number of array elements to read
+ * @sz_max: maximum number of array elements to read, if zero there is no
+ * upper limit on the number of elements in the dts entry but only
+ * sz_min will be read.
+ *
+ * Search for a property in a device node and read 16-bit value(s) from
+ * it.
+ *
+ * dts entry of array should be like:
+ * ``property = /bits/ 16 <0x5000 0x6000 0x7000>;``
+ *
+ * Return: The number of elements read on success, -EINVAL if the property
+ * does not exist, -ENODATA if property does not have a value, and -EOVERFLOW
+ * if the property data is smaller than sz_min or longer than sz_max.
+ *
+ * The out_values is modified only if a valid u16 value can be decoded.
+ */
+int of_property_read_variable_u16_array(const struct device_node *np,
+ const char *propname, u16 *out_values,
+ size_t sz_min, size_t sz_max)
+{
+ size_t sz, count;
+ const __be16 *val = of_find_property_value_of_size(np, propname,
+ (sz_min * sizeof(*out_values)),
+ (sz_max * sizeof(*out_values)),
+ &sz);
+
+ if (IS_ERR(val))
+ return PTR_ERR(val);
+
+ if (!sz_max)
+ sz = sz_min;
+ else
+ sz /= sizeof(*out_values);
+
+ count = sz;
+ while (count--)
+ *out_values++ = be16_to_cpup(val++);
+
+ return sz;
+}
+EXPORT_SYMBOL_GPL(of_property_read_variable_u16_array);
+
+/**
+ * of_property_read_variable_u32_array - Find and read an array of 32 bit
+ * integers from a property, with bounds on the minimum and maximum array size.
+ *
+ * @np: device node from which the property value is to be read.
+ * @propname: name of the property to be searched.
+ * @out_values: pointer to return found values.
+ * @sz_min: minimum number of array elements to read
+ * @sz_max: maximum number of array elements to read, if zero there is no
+ * upper limit on the number of elements in the dts entry but only
+ * sz_min will be read.
+ *
+ * Search for a property in a device node and read 32-bit value(s) from
+ * it.
+ *
+ * Return: The number of elements read on success, -EINVAL if the property
+ * does not exist, -ENODATA if property does not have a value, and -EOVERFLOW
+ * if the property data is smaller than sz_min or longer than sz_max.
+ *
+ * The out_values is modified only if a valid u32 value can be decoded.
+ */
+int of_property_read_variable_u32_array(const struct device_node *np,
+ const char *propname, u32 *out_values,
+ size_t sz_min, size_t sz_max)
+{
+ size_t sz, count;
+ const __be32 *val = of_find_property_value_of_size(np, propname,
+ (sz_min * sizeof(*out_values)),
+ (sz_max * sizeof(*out_values)),
+ &sz);
+
+ if (IS_ERR(val))
+ return PTR_ERR(val);
+
+ if (!sz_max)
+ sz = sz_min;
+ else
+ sz /= sizeof(*out_values);
+
+ count = sz;
+ while (count--)
+ *out_values++ = be32_to_cpup(val++);
+
+ return sz;
+}
+EXPORT_SYMBOL_GPL(of_property_read_variable_u32_array);
+
+/**
+ * of_property_read_variable_u64_array - Find and read an array of 64 bit integers
* from a property.
*
* @np: device node from which the property value is to be read.
@@ -1009,15 +1167,22 @@ EXPORT_SYMBOL_GPL(of_property_read_u64);
*/
int of_property_read_variable_u64_array(const struct device_node *np,
const char *propname, u64 *out_values,
- size_t sz)
+ size_t sz_min, size_t sz_max)
{
- size_t count;
+ size_t sz, count;
const __be32 *val = of_find_property_value_of_size(np, propname,
- (sz * sizeof(*out_values)));
+ (sz_min * sizeof(*out_values)),
+ (sz_max * sizeof(*out_values)),
+ &sz);
if (IS_ERR(val))
return PTR_ERR(val);
+ if (!sz_max)
+ sz = sz_min;
+ else
+ sz /= sizeof(*out_values);
+
count = sz;
while (count--) {
*out_values++ = of_read_number(val, 2);
diff --git a/include/of.h b/include/of.h
index 9eef6d7f13..dbdc4a524a 100644
--- a/include/of.h
+++ b/include/of.h
@@ -240,11 +240,22 @@ extern int of_property_read_u32_array(const struct device_node *np,
size_t sz);
extern int of_property_read_u64(const struct device_node *np,
const char *propname, u64 *out_value);
-
+extern int of_property_read_variable_u8_array(const struct device_node *np,
+ const char *propname, u8 *out_values,
+ size_t sz_min, size_t sz_max);
+extern int of_property_read_variable_u16_array(const struct device_node *np,
+ const char *propname, u16 *out_values,
+ size_t sz_min, size_t sz_max);
+extern int of_property_read_variable_u32_array(const struct device_node *np,
+ const char *propname,
+ u32 *out_values,
+ size_t sz_min,
+ size_t sz_max);
extern int of_property_read_variable_u64_array(const struct device_node *np,
const char *propname,
u64 *out_values,
- size_t sz);
+ size_t sz_min,
+ size_t sz_max);
extern int of_property_read_string(struct device_node *np,
const char *propname,
@@ -669,6 +680,29 @@ static inline int of_property_read_u64(const struct device_node *np,
return -ENOSYS;
}
+static inline int of_property_read_variable_u8_array(const struct device_node *np,
+ const char *propname, u8 *out_values,
+ size_t sz_min, size_t sz_max)
+{
+ return -ENOSYS;
+}
+
+static inline int of_property_read_variable_u16_array(const struct device_node *np,
+ const char *propname, u16 *out_values,
+ size_t sz_min, size_t sz_max)
+{
+ return -ENOSYS;
+}
+
+static inline int of_property_read_variable_u32_array(const struct device_node *np,
+ const char *propname,
+ u32 *out_values,
+ size_t sz_min,
+ size_t sz_max)
+{
+ return -ENOSYS;
+}
+
static inline int of_property_read_variable_u64_array(const struct device_node *np,
const char *propname,
u64 *out_values,
@@ -1166,7 +1200,7 @@ static inline int of_property_read_u64_array(const struct device_node *np,
u64 *out_values, size_t sz)
{
int ret = of_property_read_variable_u64_array(np, propname, out_values,
- sz);
+ sz, 0);
if (ret >= 0)
return 0;
else
--
2.39.2
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH 2/3] phy: rockchip: add pcie3 phy driver
2024-04-03 8:07 [PATCH 1/3] of: add of_property_read_variable_uxx_array() Sascha Hauer
@ 2024-04-03 8:07 ` Sascha Hauer
2024-04-03 8:26 ` Ahmad Fatoum
2024-04-03 8:07 ` [PATCH 3/3] pci: ignore BAR when it doesn't fit into bus resource Sascha Hauer
2024-04-04 6:36 ` [PATCH 1/3] of: add of_property_read_variable_uxx_array() Sascha Hauer
2 siblings, 1 reply; 6+ messages in thread
From: Sascha Hauer @ 2024-04-03 8:07 UTC (permalink / raw)
To: Barebox List
This adds support for the Rockchip PCIe3 phy found on RK35x8 SoCs. The
code is taken from Linux as of Linux-6.9-rc2.
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
drivers/phy/rockchip/Kconfig | 5 +
drivers/phy/rockchip/Makefile | 1 +
.../phy/rockchip/phy-rockchip-snps-pcie3.c | 317 ++++++++++++++++++
3 files changed, 323 insertions(+)
create mode 100644 drivers/phy/rockchip/phy-rockchip-snps-pcie3.c
diff --git a/drivers/phy/rockchip/Kconfig b/drivers/phy/rockchip/Kconfig
index e6cee372e7..8a10190f8e 100644
--- a/drivers/phy/rockchip/Kconfig
+++ b/drivers/phy/rockchip/Kconfig
@@ -13,3 +13,8 @@ config PHY_ROCKCHIP_NANENG_COMBO_PHY
Enable this to support the Rockchip PCIe/USB3.0/SATA/QSGMII
combo PHY with NaNeng IP block.
+config PHY_ROCKCHIP_SNPS_PCIE3
+ bool "Rockchip Snps PCIe3 PHY Driver"
+ depends on ARCH_ROCKCHIP || COMPILE_TEST
+ help
+ Enable this to support the Rockchip snps PCIe3 PHY.
diff --git a/drivers/phy/rockchip/Makefile b/drivers/phy/rockchip/Makefile
index 51ebf06aa1..1eaee4cbee 100644
--- a/drivers/phy/rockchip/Makefile
+++ b/drivers/phy/rockchip/Makefile
@@ -1,3 +1,4 @@
# SPDX-License-Identifier: GPL-2.0-only
obj-$(CONFIG_PHY_ROCKCHIP_INNO_USB2) += phy-rockchip-inno-usb2.o
obj-$(CONFIG_PHY_ROCKCHIP_NANENG_COMBO_PHY) += phy-rockchip-naneng-combphy.o
+obj-$(CONFIG_PHY_ROCKCHIP_SNPS_PCIE3) += phy-rockchip-snps-pcie3.o
diff --git a/drivers/phy/rockchip/phy-rockchip-snps-pcie3.c b/drivers/phy/rockchip/phy-rockchip-snps-pcie3.c
new file mode 100644
index 0000000000..7f39b261ca
--- /dev/null
+++ b/drivers/phy/rockchip/phy-rockchip-snps-pcie3.c
@@ -0,0 +1,317 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Rockchip PCIE3.0 phy driver
+ *
+ * Copyright (C) 2022 Rockchip Electronics Co., Ltd.
+ */
+
+#include <of.h>
+#include <common.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/iopoll.h>
+#include <linux/kernel.h>
+//#include <linux/phy/pcie.h>
+#include <mfd/syscon.h>
+#include <linux/phy/phy.h>
+#include <linux/regmap.h>
+#include <linux/reset.h>
+
+/* Register for RK3568 */
+#define GRF_PCIE30PHY_CON1 0x4
+#define GRF_PCIE30PHY_CON6 0x18
+#define GRF_PCIE30PHY_CON9 0x24
+#define GRF_PCIE30PHY_DA_OCM (BIT(15) | BIT(31))
+#define GRF_PCIE30PHY_STATUS0 0x80
+#define GRF_PCIE30PHY_WR_EN (0xf << 16)
+#define SRAM_INIT_DONE(reg) (reg & BIT(14))
+
+#define RK3568_BIFURCATION_LANE_0_1 BIT(0)
+
+/* Register for RK3588 */
+#define PHP_GRF_PCIESEL_CON 0x100
+#define RK3588_PCIE3PHY_GRF_CMN_CON0 0x0
+#define RK3588_PCIE3PHY_GRF_PHY0_STATUS1 0x904
+#define RK3588_PCIE3PHY_GRF_PHY1_STATUS1 0xa04
+#define RK3588_SRAM_INIT_DONE(reg) (reg & BIT(0))
+
+#define RK3588_BIFURCATION_LANE_0_1 BIT(0)
+#define RK3588_BIFURCATION_LANE_2_3 BIT(1)
+#define RK3588_LANE_AGGREGATION BIT(2)
+
+struct rockchip_p3phy_ops;
+
+struct rockchip_p3phy_priv {
+ const struct rockchip_p3phy_ops *ops;
+ void __iomem *mmio;
+ /* mode: RC, EP */
+ int mode;
+ /* pcie30_phymode: Aggregation, Bifurcation */
+ int pcie30_phymode;
+ struct regmap *phy_grf;
+ struct regmap *pipe_grf;
+ struct reset_control *p30phy;
+ struct phy *phy;
+ struct clk_bulk_data *clks;
+ int num_clks;
+ int num_lanes;
+ u32 lanes[4];
+};
+
+struct rockchip_p3phy_ops {
+ int (*phy_init)(struct rockchip_p3phy_priv *priv);
+};
+
+static int rockchip_p3phy_set_mode(struct phy *phy, enum phy_mode mode, int submode)
+{
+ return 0;
+}
+
+static int rockchip_p3phy_rk3568_init(struct rockchip_p3phy_priv *priv)
+{
+ struct phy *phy = priv->phy;
+ bool bifurcation = false;
+ int ret;
+ u32 reg;
+
+ /* Deassert PCIe PMA output clamp mode */
+ regmap_write(priv->phy_grf, GRF_PCIE30PHY_CON9, GRF_PCIE30PHY_DA_OCM);
+
+ for (int i = 0; i < priv->num_lanes; i++) {
+ dev_info(&phy->dev, "lane number %d, val %d\n", i, priv->lanes[i]);
+ if (priv->lanes[i] > 1)
+ bifurcation = true;
+ }
+
+ /* Set bifurcation if needed, and it doesn't care RC/EP */
+ if (bifurcation) {
+ dev_info(&phy->dev, "bifurcation enabled\n");
+ regmap_write(priv->phy_grf, GRF_PCIE30PHY_CON6,
+ GRF_PCIE30PHY_WR_EN | RK3568_BIFURCATION_LANE_0_1);
+ regmap_write(priv->phy_grf, GRF_PCIE30PHY_CON1,
+ GRF_PCIE30PHY_DA_OCM);
+ } else {
+ dev_dbg(&phy->dev, "bifurcation disabled\n");
+ regmap_write(priv->phy_grf, GRF_PCIE30PHY_CON6,
+ GRF_PCIE30PHY_WR_EN & ~RK3568_BIFURCATION_LANE_0_1);
+ }
+
+ reset_control_deassert(priv->p30phy);
+
+ ret = regmap_read_poll_timeout(priv->phy_grf,
+ GRF_PCIE30PHY_STATUS0,
+ reg, SRAM_INIT_DONE(reg),
+ 500);
+ if (ret)
+ dev_err(&priv->phy->dev, "%s: lock failed 0x%x, check input refclk and power supply\n",
+ __func__, reg);
+ return ret;
+}
+
+static const struct rockchip_p3phy_ops rk3568_ops = {
+ .phy_init = rockchip_p3phy_rk3568_init,
+};
+
+static int rockchip_p3phy_rk3588_init(struct rockchip_p3phy_priv *priv)
+{
+ u32 reg = 0;
+ u8 mode = 0;
+ int ret;
+
+ /* Deassert PCIe PMA output clamp mode */
+ regmap_write(priv->phy_grf, RK3588_PCIE3PHY_GRF_CMN_CON0, BIT(8) | BIT(24));
+
+ /* Set bifurcation if needed */
+ for (int i = 0; i < priv->num_lanes; i++) {
+ if (!priv->lanes[i])
+ mode |= (BIT(i) << 3);
+
+ if (priv->lanes[i] > 1)
+ mode |= (BIT(i) >> 1);
+ }
+
+ if (!mode)
+ reg = RK3588_LANE_AGGREGATION;
+ else {
+ if (mode & (BIT(0) | BIT(1)))
+ reg |= RK3588_BIFURCATION_LANE_0_1;
+
+ if (mode & (BIT(2) | BIT(3)))
+ reg |= RK3588_BIFURCATION_LANE_2_3;
+ }
+
+ regmap_write(priv->phy_grf, RK3588_PCIE3PHY_GRF_CMN_CON0, (0x7<<16) | reg);
+
+ /* Set pcie1ln_sel in PHP_GRF_PCIESEL_CON */
+ if (!IS_ERR(priv->pipe_grf)) {
+ reg = (mode & (BIT(6) | BIT(7))) >> 6;
+ if (reg)
+ regmap_write(priv->pipe_grf, PHP_GRF_PCIESEL_CON,
+ (reg << 16) | reg);
+ }
+
+ reset_control_deassert(priv->p30phy);
+
+ ret = regmap_read_poll_timeout(priv->phy_grf,
+ RK3588_PCIE3PHY_GRF_PHY0_STATUS1,
+ reg, RK3588_SRAM_INIT_DONE(reg),
+ 500);
+ ret |= regmap_read_poll_timeout(priv->phy_grf,
+ RK3588_PCIE3PHY_GRF_PHY1_STATUS1,
+ reg, RK3588_SRAM_INIT_DONE(reg),
+ 500);
+ if (ret)
+ dev_err(&priv->phy->dev, "lock failed 0x%x, check input refclk and power supply\n",
+ reg);
+ return ret;
+}
+
+static const struct rockchip_p3phy_ops rk3588_ops = {
+ .phy_init = rockchip_p3phy_rk3588_init,
+};
+
+static int rochchip_p3phy_init(struct phy *phy)
+{
+ struct rockchip_p3phy_priv *priv = phy_get_drvdata(phy);
+ int ret;
+
+ ret = clk_bulk_prepare_enable(priv->num_clks, priv->clks);
+ if (ret) {
+ dev_err(&priv->phy->dev, "failed to enable PCIe bulk clks %d\n", ret);
+ return ret;
+ }
+
+ reset_control_assert(priv->p30phy);
+ udelay(1);
+
+ if (priv->ops->phy_init) {
+ ret = priv->ops->phy_init(priv);
+ if (ret)
+ clk_bulk_disable_unprepare(priv->num_clks, priv->clks);
+ }
+
+ return ret;
+}
+
+static int rochchip_p3phy_exit(struct phy *phy)
+{
+ struct rockchip_p3phy_priv *priv = phy_get_drvdata(phy);
+
+ clk_bulk_disable_unprepare(priv->num_clks, priv->clks);
+ reset_control_assert(priv->p30phy);
+ return 0;
+}
+
+static const struct phy_ops rochchip_p3phy_ops = {
+ .init = rochchip_p3phy_init,
+ .exit = rochchip_p3phy_exit,
+ .set_mode = rockchip_p3phy_set_mode,
+};
+
+static struct phy *rockchip_p3phy_xlate(struct device *dev,
+ struct of_phandle_args *args)
+{
+ struct rockchip_p3phy_priv *priv = dev->priv;
+
+ return priv->phy;
+}
+
+static int rockchip_p3phy_probe(struct device *dev)
+{
+ struct phy_provider *phy_provider;
+ struct rockchip_p3phy_priv *priv;
+ struct device_node *np = dev->of_node;
+ struct resource *res;
+ int ret;
+
+ priv = xzalloc(sizeof(*priv));
+
+ res = dev_request_mem_resource(dev, 0);
+ if (IS_ERR(res)) {
+ ret = PTR_ERR(res);
+ return ret;
+ }
+
+ priv->mmio = IOMEM(res->start);
+ if (IS_ERR(priv->mmio)) {
+ ret = PTR_ERR(priv->mmio);
+ return ret;
+ }
+
+ priv->ops = device_get_match_data(dev);
+ if (!priv->ops) {
+ dev_err(dev, "no of match data provided\n");
+ return -EINVAL;
+ }
+
+ priv->phy_grf = syscon_regmap_lookup_by_phandle(np, "rockchip,phy-grf");
+ if (IS_ERR(priv->phy_grf)) {
+ dev_err(dev, "failed to find rockchip,phy_grf regmap\n");
+ return PTR_ERR(priv->phy_grf);
+ }
+
+ if (of_device_is_compatible(np, "rockchip,rk3588-pcie3-phy")) {
+ priv->pipe_grf =
+ syscon_regmap_lookup_by_phandle(dev->of_node,
+ "rockchip,pipe-grf");
+ if (IS_ERR(priv->pipe_grf))
+ dev_info(dev, "failed to find rockchip,pipe_grf regmap\n");
+ } else {
+ priv->pipe_grf = NULL;
+ }
+
+ priv->num_lanes = of_property_read_variable_u32_array(dev->of_node, "data-lanes",
+ priv->lanes, 2,
+ ARRAY_SIZE(priv->lanes));
+
+ /* if no data-lanes assume aggregation */
+ if (priv->num_lanes == -EINVAL) {
+ dev_dbg(dev, "no data-lanes property found\n");
+ priv->num_lanes = 1;
+ priv->lanes[0] = 1;
+ } else if (priv->num_lanes < 0) {
+ dev_err(dev, "failed to read data-lanes property %d\n", priv->num_lanes);
+ return priv->num_lanes;
+ }
+
+ priv->phy = phy_create(dev, NULL, &rochchip_p3phy_ops);
+ if (IS_ERR(priv->phy)) {
+ dev_err(dev, "failed to create combphy\n");
+ return PTR_ERR(priv->phy);
+ }
+
+ priv->p30phy = reset_control_get_optional(dev, "phy");
+ if (IS_ERR(priv->p30phy)) {
+ return dev_err_probe(dev, PTR_ERR(priv->p30phy),
+ "failed to get phy reset control\n");
+ }
+ if (!priv->p30phy)
+ dev_info(dev, "no phy reset control specified\n");
+
+ priv->num_clks = clk_bulk_get_all(dev, &priv->clks);
+ if (priv->num_clks < 1)
+ return -ENODEV;
+
+ dev->priv = priv;
+ phy_set_drvdata(priv->phy, priv);
+ phy_provider = of_phy_provider_register(dev, rockchip_p3phy_xlate);
+
+ return PTR_ERR_OR_ZERO(phy_provider);
+}
+
+static const struct of_device_id rockchip_p3phy_of_match[] = {
+ { .compatible = "rockchip,rk3568-pcie3-phy", .data = &rk3568_ops },
+ { .compatible = "rockchip,rk3588-pcie3-phy", .data = &rk3588_ops },
+ { },
+};
+MODULE_DEVICE_TABLE(of, rockchip_p3phy_of_match);
+
+static struct driver rockchip_p3phy_driver = {
+ .probe = rockchip_p3phy_probe,
+ .name = "rockchip-snps-pcie3-phy",
+ .of_compatible = rockchip_p3phy_of_match,
+};
+coredevice_platform_driver(rockchip_p3phy_driver);
+
+MODULE_DESCRIPTION("Rockchip Synopsys PCIe 3.0 PHY driver");
+MODULE_LICENSE("GPL");
--
2.39.2
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH 2/3] phy: rockchip: add pcie3 phy driver
2024-04-03 8:07 ` [PATCH 2/3] phy: rockchip: add pcie3 phy driver Sascha Hauer
@ 2024-04-03 8:26 ` Ahmad Fatoum
2024-04-03 12:15 ` Sascha Hauer
0 siblings, 1 reply; 6+ messages in thread
From: Ahmad Fatoum @ 2024-04-03 8:26 UTC (permalink / raw)
To: Sascha Hauer, Barebox List
Hello Sascha,
On 03.04.24 10:07, Sascha Hauer wrote:
> This adds support for the Rockchip PCIe3 phy found on RK35x8 SoCs. The
> code is taken from Linux as of Linux-6.9-rc2.
>
> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Should we update the defconfigs?
Cheers,
Ahmad
> ---
> drivers/phy/rockchip/Kconfig | 5 +
> drivers/phy/rockchip/Makefile | 1 +
> .../phy/rockchip/phy-rockchip-snps-pcie3.c | 317 ++++++++++++++++++
> 3 files changed, 323 insertions(+)
> create mode 100644 drivers/phy/rockchip/phy-rockchip-snps-pcie3.c
>
> diff --git a/drivers/phy/rockchip/Kconfig b/drivers/phy/rockchip/Kconfig
> index e6cee372e7..8a10190f8e 100644
> --- a/drivers/phy/rockchip/Kconfig
> +++ b/drivers/phy/rockchip/Kconfig
> @@ -13,3 +13,8 @@ config PHY_ROCKCHIP_NANENG_COMBO_PHY
> Enable this to support the Rockchip PCIe/USB3.0/SATA/QSGMII
> combo PHY with NaNeng IP block.
>
> +config PHY_ROCKCHIP_SNPS_PCIE3
> + bool "Rockchip Snps PCIe3 PHY Driver"
> + depends on ARCH_ROCKCHIP || COMPILE_TEST
> + help
> + Enable this to support the Rockchip snps PCIe3 PHY.
> diff --git a/drivers/phy/rockchip/Makefile b/drivers/phy/rockchip/Makefile
> index 51ebf06aa1..1eaee4cbee 100644
> --- a/drivers/phy/rockchip/Makefile
> +++ b/drivers/phy/rockchip/Makefile
> @@ -1,3 +1,4 @@
> # SPDX-License-Identifier: GPL-2.0-only
> obj-$(CONFIG_PHY_ROCKCHIP_INNO_USB2) += phy-rockchip-inno-usb2.o
> obj-$(CONFIG_PHY_ROCKCHIP_NANENG_COMBO_PHY) += phy-rockchip-naneng-combphy.o
> +obj-$(CONFIG_PHY_ROCKCHIP_SNPS_PCIE3) += phy-rockchip-snps-pcie3.o
> diff --git a/drivers/phy/rockchip/phy-rockchip-snps-pcie3.c b/drivers/phy/rockchip/phy-rockchip-snps-pcie3.c
> new file mode 100644
> index 0000000000..7f39b261ca
> --- /dev/null
> +++ b/drivers/phy/rockchip/phy-rockchip-snps-pcie3.c
> @@ -0,0 +1,317 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Rockchip PCIE3.0 phy driver
> + *
> + * Copyright (C) 2022 Rockchip Electronics Co., Ltd.
> + */
> +
> +#include <of.h>
> +#include <common.h>
> +#include <linux/clk.h>
> +#include <linux/io.h>
> +#include <linux/iopoll.h>
> +#include <linux/kernel.h>
> +//#include <linux/phy/pcie.h>
> +#include <mfd/syscon.h>
> +#include <linux/phy/phy.h>
> +#include <linux/regmap.h>
> +#include <linux/reset.h>
> +
> +/* Register for RK3568 */
> +#define GRF_PCIE30PHY_CON1 0x4
> +#define GRF_PCIE30PHY_CON6 0x18
> +#define GRF_PCIE30PHY_CON9 0x24
> +#define GRF_PCIE30PHY_DA_OCM (BIT(15) | BIT(31))
> +#define GRF_PCIE30PHY_STATUS0 0x80
> +#define GRF_PCIE30PHY_WR_EN (0xf << 16)
> +#define SRAM_INIT_DONE(reg) (reg & BIT(14))
> +
> +#define RK3568_BIFURCATION_LANE_0_1 BIT(0)
> +
> +/* Register for RK3588 */
> +#define PHP_GRF_PCIESEL_CON 0x100
> +#define RK3588_PCIE3PHY_GRF_CMN_CON0 0x0
> +#define RK3588_PCIE3PHY_GRF_PHY0_STATUS1 0x904
> +#define RK3588_PCIE3PHY_GRF_PHY1_STATUS1 0xa04
> +#define RK3588_SRAM_INIT_DONE(reg) (reg & BIT(0))
> +
> +#define RK3588_BIFURCATION_LANE_0_1 BIT(0)
> +#define RK3588_BIFURCATION_LANE_2_3 BIT(1)
> +#define RK3588_LANE_AGGREGATION BIT(2)
> +
> +struct rockchip_p3phy_ops;
> +
> +struct rockchip_p3phy_priv {
> + const struct rockchip_p3phy_ops *ops;
> + void __iomem *mmio;
> + /* mode: RC, EP */
> + int mode;
> + /* pcie30_phymode: Aggregation, Bifurcation */
> + int pcie30_phymode;
> + struct regmap *phy_grf;
> + struct regmap *pipe_grf;
> + struct reset_control *p30phy;
> + struct phy *phy;
> + struct clk_bulk_data *clks;
> + int num_clks;
> + int num_lanes;
> + u32 lanes[4];
> +};
> +
> +struct rockchip_p3phy_ops {
> + int (*phy_init)(struct rockchip_p3phy_priv *priv);
> +};
> +
> +static int rockchip_p3phy_set_mode(struct phy *phy, enum phy_mode mode, int submode)
> +{
> + return 0;
> +}
> +
> +static int rockchip_p3phy_rk3568_init(struct rockchip_p3phy_priv *priv)
> +{
> + struct phy *phy = priv->phy;
> + bool bifurcation = false;
> + int ret;
> + u32 reg;
> +
> + /* Deassert PCIe PMA output clamp mode */
> + regmap_write(priv->phy_grf, GRF_PCIE30PHY_CON9, GRF_PCIE30PHY_DA_OCM);
> +
> + for (int i = 0; i < priv->num_lanes; i++) {
> + dev_info(&phy->dev, "lane number %d, val %d\n", i, priv->lanes[i]);
> + if (priv->lanes[i] > 1)
> + bifurcation = true;
> + }
> +
> + /* Set bifurcation if needed, and it doesn't care RC/EP */
> + if (bifurcation) {
> + dev_info(&phy->dev, "bifurcation enabled\n");
> + regmap_write(priv->phy_grf, GRF_PCIE30PHY_CON6,
> + GRF_PCIE30PHY_WR_EN | RK3568_BIFURCATION_LANE_0_1);
> + regmap_write(priv->phy_grf, GRF_PCIE30PHY_CON1,
> + GRF_PCIE30PHY_DA_OCM);
> + } else {
> + dev_dbg(&phy->dev, "bifurcation disabled\n");
> + regmap_write(priv->phy_grf, GRF_PCIE30PHY_CON6,
> + GRF_PCIE30PHY_WR_EN & ~RK3568_BIFURCATION_LANE_0_1);
> + }
> +
> + reset_control_deassert(priv->p30phy);
> +
> + ret = regmap_read_poll_timeout(priv->phy_grf,
> + GRF_PCIE30PHY_STATUS0,
> + reg, SRAM_INIT_DONE(reg),
> + 500);
> + if (ret)
> + dev_err(&priv->phy->dev, "%s: lock failed 0x%x, check input refclk and power supply\n",
> + __func__, reg);
> + return ret;
> +}
> +
> +static const struct rockchip_p3phy_ops rk3568_ops = {
> + .phy_init = rockchip_p3phy_rk3568_init,
> +};
> +
> +static int rockchip_p3phy_rk3588_init(struct rockchip_p3phy_priv *priv)
> +{
> + u32 reg = 0;
> + u8 mode = 0;
> + int ret;
> +
> + /* Deassert PCIe PMA output clamp mode */
> + regmap_write(priv->phy_grf, RK3588_PCIE3PHY_GRF_CMN_CON0, BIT(8) | BIT(24));
> +
> + /* Set bifurcation if needed */
> + for (int i = 0; i < priv->num_lanes; i++) {
> + if (!priv->lanes[i])
> + mode |= (BIT(i) << 3);
> +
> + if (priv->lanes[i] > 1)
> + mode |= (BIT(i) >> 1);
> + }
> +
> + if (!mode)
> + reg = RK3588_LANE_AGGREGATION;
> + else {
> + if (mode & (BIT(0) | BIT(1)))
> + reg |= RK3588_BIFURCATION_LANE_0_1;
> +
> + if (mode & (BIT(2) | BIT(3)))
> + reg |= RK3588_BIFURCATION_LANE_2_3;
> + }
> +
> + regmap_write(priv->phy_grf, RK3588_PCIE3PHY_GRF_CMN_CON0, (0x7<<16) | reg);
> +
> + /* Set pcie1ln_sel in PHP_GRF_PCIESEL_CON */
> + if (!IS_ERR(priv->pipe_grf)) {
> + reg = (mode & (BIT(6) | BIT(7))) >> 6;
> + if (reg)
> + regmap_write(priv->pipe_grf, PHP_GRF_PCIESEL_CON,
> + (reg << 16) | reg);
> + }
> +
> + reset_control_deassert(priv->p30phy);
> +
> + ret = regmap_read_poll_timeout(priv->phy_grf,
> + RK3588_PCIE3PHY_GRF_PHY0_STATUS1,
> + reg, RK3588_SRAM_INIT_DONE(reg),
> + 500);
> + ret |= regmap_read_poll_timeout(priv->phy_grf,
> + RK3588_PCIE3PHY_GRF_PHY1_STATUS1,
> + reg, RK3588_SRAM_INIT_DONE(reg),
> + 500);
> + if (ret)
> + dev_err(&priv->phy->dev, "lock failed 0x%x, check input refclk and power supply\n",
> + reg);
> + return ret;
> +}
> +
> +static const struct rockchip_p3phy_ops rk3588_ops = {
> + .phy_init = rockchip_p3phy_rk3588_init,
> +};
> +
> +static int rochchip_p3phy_init(struct phy *phy)
> +{
> + struct rockchip_p3phy_priv *priv = phy_get_drvdata(phy);
> + int ret;
> +
> + ret = clk_bulk_prepare_enable(priv->num_clks, priv->clks);
> + if (ret) {
> + dev_err(&priv->phy->dev, "failed to enable PCIe bulk clks %d\n", ret);
> + return ret;
> + }
> +
> + reset_control_assert(priv->p30phy);
> + udelay(1);
> +
> + if (priv->ops->phy_init) {
> + ret = priv->ops->phy_init(priv);
> + if (ret)
> + clk_bulk_disable_unprepare(priv->num_clks, priv->clks);
> + }
> +
> + return ret;
> +}
> +
> +static int rochchip_p3phy_exit(struct phy *phy)
> +{
> + struct rockchip_p3phy_priv *priv = phy_get_drvdata(phy);
> +
> + clk_bulk_disable_unprepare(priv->num_clks, priv->clks);
> + reset_control_assert(priv->p30phy);
> + return 0;
> +}
> +
> +static const struct phy_ops rochchip_p3phy_ops = {
> + .init = rochchip_p3phy_init,
> + .exit = rochchip_p3phy_exit,
> + .set_mode = rockchip_p3phy_set_mode,
> +};
> +
> +static struct phy *rockchip_p3phy_xlate(struct device *dev,
> + struct of_phandle_args *args)
> +{
> + struct rockchip_p3phy_priv *priv = dev->priv;
> +
> + return priv->phy;
> +}
> +
> +static int rockchip_p3phy_probe(struct device *dev)
> +{
> + struct phy_provider *phy_provider;
> + struct rockchip_p3phy_priv *priv;
> + struct device_node *np = dev->of_node;
> + struct resource *res;
> + int ret;
> +
> + priv = xzalloc(sizeof(*priv));
> +
> + res = dev_request_mem_resource(dev, 0);
> + if (IS_ERR(res)) {
> + ret = PTR_ERR(res);
> + return ret;
> + }
> +
> + priv->mmio = IOMEM(res->start);
> + if (IS_ERR(priv->mmio)) {
> + ret = PTR_ERR(priv->mmio);
> + return ret;
> + }
> +
> + priv->ops = device_get_match_data(dev);
> + if (!priv->ops) {
> + dev_err(dev, "no of match data provided\n");
> + return -EINVAL;
> + }
> +
> + priv->phy_grf = syscon_regmap_lookup_by_phandle(np, "rockchip,phy-grf");
> + if (IS_ERR(priv->phy_grf)) {
> + dev_err(dev, "failed to find rockchip,phy_grf regmap\n");
> + return PTR_ERR(priv->phy_grf);
> + }
> +
> + if (of_device_is_compatible(np, "rockchip,rk3588-pcie3-phy")) {
> + priv->pipe_grf =
> + syscon_regmap_lookup_by_phandle(dev->of_node,
> + "rockchip,pipe-grf");
> + if (IS_ERR(priv->pipe_grf))
> + dev_info(dev, "failed to find rockchip,pipe_grf regmap\n");
> + } else {
> + priv->pipe_grf = NULL;
> + }
> +
> + priv->num_lanes = of_property_read_variable_u32_array(dev->of_node, "data-lanes",
> + priv->lanes, 2,
> + ARRAY_SIZE(priv->lanes));
> +
> + /* if no data-lanes assume aggregation */
> + if (priv->num_lanes == -EINVAL) {
> + dev_dbg(dev, "no data-lanes property found\n");
> + priv->num_lanes = 1;
> + priv->lanes[0] = 1;
> + } else if (priv->num_lanes < 0) {
> + dev_err(dev, "failed to read data-lanes property %d\n", priv->num_lanes);
> + return priv->num_lanes;
> + }
> +
> + priv->phy = phy_create(dev, NULL, &rochchip_p3phy_ops);
> + if (IS_ERR(priv->phy)) {
> + dev_err(dev, "failed to create combphy\n");
> + return PTR_ERR(priv->phy);
> + }
> +
> + priv->p30phy = reset_control_get_optional(dev, "phy");
> + if (IS_ERR(priv->p30phy)) {
> + return dev_err_probe(dev, PTR_ERR(priv->p30phy),
> + "failed to get phy reset control\n");
> + }
> + if (!priv->p30phy)
> + dev_info(dev, "no phy reset control specified\n");
> +
> + priv->num_clks = clk_bulk_get_all(dev, &priv->clks);
> + if (priv->num_clks < 1)
> + return -ENODEV;
> +
> + dev->priv = priv;
> + phy_set_drvdata(priv->phy, priv);
> + phy_provider = of_phy_provider_register(dev, rockchip_p3phy_xlate);
> +
> + return PTR_ERR_OR_ZERO(phy_provider);
> +}
> +
> +static const struct of_device_id rockchip_p3phy_of_match[] = {
> + { .compatible = "rockchip,rk3568-pcie3-phy", .data = &rk3568_ops },
> + { .compatible = "rockchip,rk3588-pcie3-phy", .data = &rk3588_ops },
> + { },
> +};
> +MODULE_DEVICE_TABLE(of, rockchip_p3phy_of_match);
> +
> +static struct driver rockchip_p3phy_driver = {
> + .probe = rockchip_p3phy_probe,
> + .name = "rockchip-snps-pcie3-phy",
> + .of_compatible = rockchip_p3phy_of_match,
> +};
> +coredevice_platform_driver(rockchip_p3phy_driver);
> +
> +MODULE_DESCRIPTION("Rockchip Synopsys PCIe 3.0 PHY driver");
> +MODULE_LICENSE("GPL");
--
Pengutronix e.K. | |
Steuerwalder Str. 21 | http://www.pengutronix.de/ |
31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH 2/3] phy: rockchip: add pcie3 phy driver
2024-04-03 8:26 ` Ahmad Fatoum
@ 2024-04-03 12:15 ` Sascha Hauer
0 siblings, 0 replies; 6+ messages in thread
From: Sascha Hauer @ 2024-04-03 12:15 UTC (permalink / raw)
To: Ahmad Fatoum; +Cc: Barebox List
On Wed, Apr 03, 2024 at 10:26:48AM +0200, Ahmad Fatoum wrote:
> Hello Sascha,
>
> On 03.04.24 10:07, Sascha Hauer wrote:
> > This adds support for the Rockchip PCIe3 phy found on RK35x8 SoCs. The
> > code is taken from Linux as of Linux-6.9-rc2.
> >
> > Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
>
> Should we update the defconfigs?
Yes, but this is done as part of the MECSBC board support already, so
should be fine.
Sascha
--
Pengutronix e.K. | |
Steuerwalder Str. 21 | http://www.pengutronix.de/ |
31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH 3/3] pci: ignore BAR when it doesn't fit into bus resource
2024-04-03 8:07 [PATCH 1/3] of: add of_property_read_variable_uxx_array() Sascha Hauer
2024-04-03 8:07 ` [PATCH 2/3] phy: rockchip: add pcie3 phy driver Sascha Hauer
@ 2024-04-03 8:07 ` Sascha Hauer
2024-04-04 6:36 ` [PATCH 1/3] of: add of_property_read_variable_uxx_array() Sascha Hauer
2 siblings, 0 replies; 6+ messages in thread
From: Sascha Hauer @ 2024-04-03 8:07 UTC (permalink / raw)
To: Barebox List
It can happen that a BAR doesn't fit into the bus resource. In this case
just ignore the BAR instead of failing the device. This is what Linux
does as well.
This helps me on the Protonic MECSBC where a NVME drive offers a 1GiB
BAR which doesn't seem to be needed to make the driver work.
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
drivers/pci/pci.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index bc083270d9..e6370b5c7f 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -406,7 +406,7 @@ static void setup_device(struct pci_dev *dev, int max_bar)
if (ALIGN(*last_addr, size) + size > busres->end) {
pr_debug("BAR does not fit within bus %s res\n", kind);
- return;
+ continue;
}
*last_addr = ALIGN(*last_addr, size);
--
2.39.2
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH 1/3] of: add of_property_read_variable_uxx_array()
2024-04-03 8:07 [PATCH 1/3] of: add of_property_read_variable_uxx_array() Sascha Hauer
2024-04-03 8:07 ` [PATCH 2/3] phy: rockchip: add pcie3 phy driver Sascha Hauer
2024-04-03 8:07 ` [PATCH 3/3] pci: ignore BAR when it doesn't fit into bus resource Sascha Hauer
@ 2024-04-04 6:36 ` Sascha Hauer
2 siblings, 0 replies; 6+ messages in thread
From: Sascha Hauer @ 2024-04-04 6:36 UTC (permalink / raw)
To: Barebox List, Sascha Hauer
On Wed, 03 Apr 2024 10:07:01 +0200, Sascha Hauer wrote:
> This adds of_property_read_variable_uxx_array() which allow to read
> arrays from properties with min/max size boundaries. Code is directly
> taken from Linux.
> We already had of_property_read_variable_u64_array(), but without
> min/max arguments. This one is updated to match the Kernel code.
>
>
> [...]
Applied, thanks!
[1/3] of: add of_property_read_variable_uxx_array()
https://git.pengutronix.de/cgit/barebox/commit/?id=0c6d2f4ded18 (link may not be stable)
[2/3] phy: rockchip: add pcie3 phy driver
https://git.pengutronix.de/cgit/barebox/commit/?id=2d85618a2eb4 (link may not be stable)
[3/3] pci: ignore BAR when it doesn't fit into bus resource
https://git.pengutronix.de/cgit/barebox/commit/?id=0d21f12e2aee (link may not be stable)
Best regards,
--
Sascha Hauer <s.hauer@pengutronix.de>
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2024-04-04 6:37 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-04-03 8:07 [PATCH 1/3] of: add of_property_read_variable_uxx_array() Sascha Hauer
2024-04-03 8:07 ` [PATCH 2/3] phy: rockchip: add pcie3 phy driver Sascha Hauer
2024-04-03 8:26 ` Ahmad Fatoum
2024-04-03 12:15 ` Sascha Hauer
2024-04-03 8:07 ` [PATCH 3/3] pci: ignore BAR when it doesn't fit into bus resource Sascha Hauer
2024-04-04 6:36 ` [PATCH 1/3] of: add of_property_read_variable_uxx_array() Sascha Hauer
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox