* [PATCH v3 2/6] phy: realtek: usb2: introduce read and write functions to driver data
From: Rustam Adilov @ 2026-04-02 15:44 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Stanley Chang, linux-phy, devicetree, linux-kernel
Cc: Rustam Adilov, Michael Zavertkin
In-Reply-To: <20260402154414.196012-1-adilov@disroot.org>
RTL9607C is a big endian SoC but has little endian USB host controller and
thus, reads and writes to the reg_gusb2phyacc0 should go through
le32_to_cpu and cpu_to_le32 functions respectively. This doesn't apply to
vstatus register though.
To handle this situation, introduce read and write functions to the driver
data and create 2 variations of reads and write function with le32 function
in it and without.
Adjust all instances of utmi_wait_register function to now include the read
function as one of its arguments.
Assign the existing phy configuration for RTD SoCs to the default read
and write functions.
Co-developed-by: Michael Zavertkin <misha.zavertkin@mail.ru>
Signed-off-by: Michael Zavertkin <misha.zavertkin@mail.ru>
Signed-off-by: Rustam Adilov <adilov@disroot.org>
---
drivers/phy/realtek/phy-rtk-usb2.c | 75 ++++++++++++++++++++++++------
1 file changed, 62 insertions(+), 13 deletions(-)
diff --git a/drivers/phy/realtek/phy-rtk-usb2.c b/drivers/phy/realtek/phy-rtk-usb2.c
index f5d2f0c3376a..f6670ac6346d 100644
--- a/drivers/phy/realtek/phy-rtk-usb2.c
+++ b/drivers/phy/realtek/phy-rtk-usb2.c
@@ -67,6 +67,9 @@ struct phy_reg {
int vstatus_offset;
int vstatus_busy;
int new_reg_req;
+
+ u32 (*read)(void __iomem *reg);
+ void (*write)(u32 val, void __iomem *reg);
};
struct phy_data {
@@ -102,6 +105,9 @@ struct phy_cfg {
int vstatus_offset;
int vstatus_busy;
int new_reg_req;
+
+ u32 (*read)(void __iomem *reg);
+ void (*write)(u32 val, void __iomem *reg);
};
struct phy_parameter {
@@ -128,6 +134,28 @@ struct rtk_phy {
struct dentry *debug_dir;
};
+static u32 rtk_usb2phy_read(void __iomem *reg)
+{
+ return readl(reg);
+}
+
+static u32 rtk_usb2phy_read_le(void __iomem *reg)
+{
+ return le32_to_cpu(readl(reg));
+}
+
+static void rtk_usb2phy_write(u32 val, void __iomem *reg)
+{
+ writel(val, reg);
+}
+
+static void rtk_usb2phy_write_le(u32 val, void __iomem *reg)
+{
+ u32 tmp = cpu_to_le32(val);
+
+ writel(tmp, reg);
+}
+
/* mapping 0xE0 to 0 ... 0xE7 to 7, 0xF0 to 8 ,,, 0xF7 to 15 */
static inline int page_addr_to_array_index(u8 addr)
{
@@ -144,12 +172,13 @@ static inline u8 array_index_to_page_addr(int index)
#define PHY_IO_TIMEOUT_USEC (50000)
#define PHY_IO_DELAY_US (100)
-static inline int utmi_wait_register(void __iomem *reg, u32 mask, u32 result)
+static inline int utmi_wait_register(u32 (*read)(void __iomem *reg), void __iomem *reg, u32 mask,
+ u32 result)
{
int ret;
unsigned int val;
- ret = read_poll_timeout(readl, val, ((val & mask) == result),
+ ret = read_poll_timeout(read, val, ((val & mask) == result),
PHY_IO_DELAY_US, PHY_IO_TIMEOUT_USEC, false, reg);
if (ret) {
pr_err("%s can't program USB phy\n", __func__);
@@ -168,25 +197,25 @@ static char rtk_phy_read(struct phy_reg *phy_reg, char addr)
addr -= OFFEST_PHY_READ;
/* polling until VBusy == 0 */
- ret = utmi_wait_register(reg_gusb2phyacc0, phy_reg->vstatus_busy, 0);
+ ret = utmi_wait_register(phy_reg->read, reg_gusb2phyacc0, phy_reg->vstatus_busy, 0);
if (ret)
return (char)ret;
/* VCtrl = low nibble of addr, and set PHY_NEW_REG_REQ */
val = phy_reg->new_reg_req | (GET_LOW_NIBBLE(addr) << PHY_VCTRL_SHIFT);
- writel(val, reg_gusb2phyacc0);
- ret = utmi_wait_register(reg_gusb2phyacc0, phy_reg->vstatus_busy, 0);
+ phy_reg->write(val, reg_gusb2phyacc0);
+ ret = utmi_wait_register(phy_reg->read, reg_gusb2phyacc0, phy_reg->vstatus_busy, 0);
if (ret)
return (char)ret;
/* VCtrl = high nibble of addr, and set PHY_NEW_REG_REQ */
val = phy_reg->new_reg_req | (GET_HIGH_NIBBLE(addr) << PHY_VCTRL_SHIFT);
- writel(val, reg_gusb2phyacc0);
- ret = utmi_wait_register(reg_gusb2phyacc0, phy_reg->vstatus_busy, 0);
+ phy_reg->write(val, reg_gusb2phyacc0);
+ ret = utmi_wait_register(phy_reg->read, reg_gusb2phyacc0, phy_reg->vstatus_busy, 0);
if (ret)
return (char)ret;
- val = readl(reg_gusb2phyacc0);
+ val = phy_reg->read(reg_gusb2phyacc0);
return (char)(val & PHY_REG_DATA_MASK);
}
@@ -202,23 +231,23 @@ static int rtk_phy_write(struct phy_reg *phy_reg, char addr, char data)
/* write data to VStatusOut2 (data output to phy) */
writel((u32)data << shift_bits, reg_wrap_vstatus + phy_reg->vstatus_offset);
- ret = utmi_wait_register(reg_gusb2phyacc0, phy_reg->vstatus_busy, 0);
+ ret = utmi_wait_register(phy_reg->read, reg_gusb2phyacc0, phy_reg->vstatus_busy, 0);
if (ret)
return ret;
/* VCtrl = low nibble of addr, set PHY_NEW_REG_REQ */
val = phy_reg->new_reg_req | (GET_LOW_NIBBLE(addr) << PHY_VCTRL_SHIFT);
- writel(val, reg_gusb2phyacc0);
- ret = utmi_wait_register(reg_gusb2phyacc0, phy_reg->vstatus_busy, 0);
+ phy_reg->write(val, reg_gusb2phyacc0);
+ ret = utmi_wait_register(phy_reg->read, reg_gusb2phyacc0, phy_reg->vstatus_busy, 0);
if (ret)
return ret;
/* VCtrl = high nibble of addr, set PHY_NEW_REG_REQ */
val = phy_reg->new_reg_req | (GET_HIGH_NIBBLE(addr) << PHY_VCTRL_SHIFT);
- writel(val, reg_gusb2phyacc0);
- ret = utmi_wait_register(reg_gusb2phyacc0, phy_reg->vstatus_busy, 0);
+ phy_reg->write(val, reg_gusb2phyacc0);
+ ret = utmi_wait_register(phy_reg->read, reg_gusb2phyacc0, phy_reg->vstatus_busy, 0);
if (ret)
return ret;
@@ -984,6 +1013,8 @@ static int parse_phy_data(struct rtk_phy *rtk_phy)
phy_parameter->phy_reg.vstatus_offset = phy_cfg->vstatus_offset;
phy_parameter->phy_reg.vstatus_busy = phy_cfg->vstatus_busy;
phy_parameter->phy_reg.new_reg_req = phy_cfg->new_reg_req;
+ phy_parameter->phy_reg.read = phy_cfg->read;
+ phy_parameter->phy_reg.write = phy_cfg->write;
if (of_property_read_bool(np, "realtek,inverse-hstx-sync-clock"))
phy_parameter->inverse_hstx_sync_clock = true;
@@ -1098,6 +1129,8 @@ static const struct phy_cfg rtd1295_phy_cfg = {
.vstatus_offset = 0,
.vstatus_busy = PHY_VSTS_BUSY,
.new_reg_req = PHY_NEW_REG_REQ,
+ .read = rtk_usb2phy_read,
+ .write = rtk_usb2phy_write,
};
static const struct phy_cfg rtd1395_phy_cfg = {
@@ -1125,6 +1158,8 @@ static const struct phy_cfg rtd1395_phy_cfg = {
.vstatus_offset = 0,
.vstatus_busy = PHY_VSTS_BUSY,
.new_reg_req = PHY_NEW_REG_REQ,
+ .read = rtk_usb2phy_read,
+ .write = rtk_usb2phy_write,
};
static const struct phy_cfg rtd1395_phy_cfg_2port = {
@@ -1152,6 +1187,8 @@ static const struct phy_cfg rtd1395_phy_cfg_2port = {
.vstatus_offset = 0,
.vstatus_busy = PHY_VSTS_BUSY,
.new_reg_req = PHY_NEW_REG_REQ,
+ .read = rtk_usb2phy_read,
+ .write = rtk_usb2phy_write,
};
static const struct phy_cfg rtd1619_phy_cfg = {
@@ -1177,6 +1214,8 @@ static const struct phy_cfg rtd1619_phy_cfg = {
.vstatus_offset = 0,
.vstatus_busy = PHY_VSTS_BUSY,
.new_reg_req = PHY_NEW_REG_REQ,
+ .read = rtk_usb2phy_read,
+ .write = rtk_usb2phy_write,
};
static const struct phy_cfg rtd1319_phy_cfg = {
@@ -1206,6 +1245,8 @@ static const struct phy_cfg rtd1319_phy_cfg = {
.vstatus_offset = 0,
.vstatus_busy = PHY_VSTS_BUSY,
.new_reg_req = PHY_NEW_REG_REQ,
+ .read = rtk_usb2phy_read,
+ .write = rtk_usb2phy_write,
};
static const struct phy_cfg rtd1312c_phy_cfg = {
@@ -1234,6 +1275,8 @@ static const struct phy_cfg rtd1312c_phy_cfg = {
.vstatus_offset = 0,
.vstatus_busy = PHY_VSTS_BUSY,
.new_reg_req = PHY_NEW_REG_REQ,
+ .read = rtk_usb2phy_read,
+ .write = rtk_usb2phy_write,
};
static const struct phy_cfg rtd1619b_phy_cfg = {
@@ -1262,6 +1305,8 @@ static const struct phy_cfg rtd1619b_phy_cfg = {
.vstatus_offset = 0,
.vstatus_busy = PHY_VSTS_BUSY,
.new_reg_req = PHY_NEW_REG_REQ,
+ .read = rtk_usb2phy_read,
+ .write = rtk_usb2phy_write,
};
static const struct phy_cfg rtd1319d_phy_cfg = {
@@ -1290,6 +1335,8 @@ static const struct phy_cfg rtd1319d_phy_cfg = {
.vstatus_offset = 0,
.vstatus_busy = PHY_VSTS_BUSY,
.new_reg_req = PHY_NEW_REG_REQ,
+ .read = rtk_usb2phy_read,
+ .write = rtk_usb2phy_write,
};
static const struct phy_cfg rtd1315e_phy_cfg = {
@@ -1319,6 +1366,8 @@ static const struct phy_cfg rtd1315e_phy_cfg = {
.vstatus_offset = 0,
.vstatus_busy = PHY_VSTS_BUSY,
.new_reg_req = PHY_NEW_REG_REQ,
+ .read = rtk_usb2phy_read,
+ .write = rtk_usb2phy_write,
};
static const struct of_device_id usbphy_rtk_dt_match[] = {
--
2.53.0
^ permalink raw reply related
* [PATCH v3 1/6] phy: realtek: usb2: introduce vstatus/new_reg_req variables to driver data
From: Rustam Adilov @ 2026-04-02 15:44 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Stanley Chang, linux-phy, devicetree, linux-kernel
Cc: Rustam Adilov, Michael Zavertkin
In-Reply-To: <20260402154414.196012-1-adilov@disroot.org>
In RTL9607C SoC, the vstatus register is located at a certain offset from
the base and so introduce the vstatus_offset to handle it.
Busy bit of the vstatus and new_reg_req bit are also different and so
introduce these variables to the driver data as well.
Add these variables to the pre-existing phy cfg structs for RTD SoCs and
assign them the default values.
Co-developed-by: Michael Zavertkin <misha.zavertkin@mail.ru>
Signed-off-by: Michael Zavertkin <misha.zavertkin@mail.ru>
Signed-off-by: Rustam Adilov <adilov@disroot.org>
---
drivers/phy/realtek/phy-rtk-usb2.c | 59 ++++++++++++++++++++++++------
1 file changed, 48 insertions(+), 11 deletions(-)
diff --git a/drivers/phy/realtek/phy-rtk-usb2.c b/drivers/phy/realtek/phy-rtk-usb2.c
index 248550ef98ca..f5d2f0c3376a 100644
--- a/drivers/phy/realtek/phy-rtk-usb2.c
+++ b/drivers/phy/realtek/phy-rtk-usb2.c
@@ -64,6 +64,9 @@ struct phy_reg {
void __iomem *reg_wrap_vstatus;
void __iomem *reg_gusb2phyacc0;
int vstatus_index;
+ int vstatus_offset;
+ int vstatus_busy;
+ int new_reg_req;
};
struct phy_data {
@@ -96,6 +99,9 @@ struct phy_cfg {
bool do_toggle_driving;
bool use_default_parameter;
bool is_double_sensitivity_mode;
+ int vstatus_offset;
+ int vstatus_busy;
+ int new_reg_req;
};
struct phy_parameter {
@@ -162,21 +168,21 @@ static char rtk_phy_read(struct phy_reg *phy_reg, char addr)
addr -= OFFEST_PHY_READ;
/* polling until VBusy == 0 */
- ret = utmi_wait_register(reg_gusb2phyacc0, PHY_VSTS_BUSY, 0);
+ ret = utmi_wait_register(reg_gusb2phyacc0, phy_reg->vstatus_busy, 0);
if (ret)
return (char)ret;
/* VCtrl = low nibble of addr, and set PHY_NEW_REG_REQ */
- val = PHY_NEW_REG_REQ | (GET_LOW_NIBBLE(addr) << PHY_VCTRL_SHIFT);
+ val = phy_reg->new_reg_req | (GET_LOW_NIBBLE(addr) << PHY_VCTRL_SHIFT);
writel(val, reg_gusb2phyacc0);
- ret = utmi_wait_register(reg_gusb2phyacc0, PHY_VSTS_BUSY, 0);
+ ret = utmi_wait_register(reg_gusb2phyacc0, phy_reg->vstatus_busy, 0);
if (ret)
return (char)ret;
/* VCtrl = high nibble of addr, and set PHY_NEW_REG_REQ */
- val = PHY_NEW_REG_REQ | (GET_HIGH_NIBBLE(addr) << PHY_VCTRL_SHIFT);
+ val = phy_reg->new_reg_req | (GET_HIGH_NIBBLE(addr) << PHY_VCTRL_SHIFT);
writel(val, reg_gusb2phyacc0);
- ret = utmi_wait_register(reg_gusb2phyacc0, PHY_VSTS_BUSY, 0);
+ ret = utmi_wait_register(reg_gusb2phyacc0, phy_reg->vstatus_busy, 0);
if (ret)
return (char)ret;
@@ -194,25 +200,25 @@ static int rtk_phy_write(struct phy_reg *phy_reg, char addr, char data)
int ret = 0;
/* write data to VStatusOut2 (data output to phy) */
- writel((u32)data << shift_bits, reg_wrap_vstatus);
+ writel((u32)data << shift_bits, reg_wrap_vstatus + phy_reg->vstatus_offset);
- ret = utmi_wait_register(reg_gusb2phyacc0, PHY_VSTS_BUSY, 0);
+ ret = utmi_wait_register(reg_gusb2phyacc0, phy_reg->vstatus_busy, 0);
if (ret)
return ret;
/* VCtrl = low nibble of addr, set PHY_NEW_REG_REQ */
- val = PHY_NEW_REG_REQ | (GET_LOW_NIBBLE(addr) << PHY_VCTRL_SHIFT);
+ val = phy_reg->new_reg_req | (GET_LOW_NIBBLE(addr) << PHY_VCTRL_SHIFT);
writel(val, reg_gusb2phyacc0);
- ret = utmi_wait_register(reg_gusb2phyacc0, PHY_VSTS_BUSY, 0);
+ ret = utmi_wait_register(reg_gusb2phyacc0, phy_reg->vstatus_busy, 0);
if (ret)
return ret;
/* VCtrl = high nibble of addr, set PHY_NEW_REG_REQ */
- val = PHY_NEW_REG_REQ | (GET_HIGH_NIBBLE(addr) << PHY_VCTRL_SHIFT);
+ val = phy_reg->new_reg_req | (GET_HIGH_NIBBLE(addr) << PHY_VCTRL_SHIFT);
writel(val, reg_gusb2phyacc0);
- ret = utmi_wait_register(reg_gusb2phyacc0, PHY_VSTS_BUSY, 0);
+ ret = utmi_wait_register(reg_gusb2phyacc0, phy_reg->vstatus_busy, 0);
if (ret)
return ret;
@@ -957,6 +963,7 @@ static int get_phy_data_by_efuse(struct rtk_phy *rtk_phy,
static int parse_phy_data(struct rtk_phy *rtk_phy)
{
+ struct phy_cfg *phy_cfg = rtk_phy->phy_cfg;
struct device *dev = rtk_phy->dev;
struct device_node *np = dev->of_node;
struct phy_parameter *phy_parameter;
@@ -974,6 +981,9 @@ static int parse_phy_data(struct rtk_phy *rtk_phy)
phy_parameter->phy_reg.reg_wrap_vstatus = of_iomap(np, 0);
phy_parameter->phy_reg.reg_gusb2phyacc0 = of_iomap(np, 1) + index;
phy_parameter->phy_reg.vstatus_index = index;
+ phy_parameter->phy_reg.vstatus_offset = phy_cfg->vstatus_offset;
+ phy_parameter->phy_reg.vstatus_busy = phy_cfg->vstatus_busy;
+ phy_parameter->phy_reg.new_reg_req = phy_cfg->new_reg_req;
if (of_property_read_bool(np, "realtek,inverse-hstx-sync-clock"))
phy_parameter->inverse_hstx_sync_clock = true;
@@ -1085,6 +1095,9 @@ static const struct phy_cfg rtd1295_phy_cfg = {
.driving_updated_for_dev_dis = 0xf,
.use_default_parameter = false,
.is_double_sensitivity_mode = false,
+ .vstatus_offset = 0,
+ .vstatus_busy = PHY_VSTS_BUSY,
+ .new_reg_req = PHY_NEW_REG_REQ,
};
static const struct phy_cfg rtd1395_phy_cfg = {
@@ -1109,6 +1122,9 @@ static const struct phy_cfg rtd1395_phy_cfg = {
.driving_updated_for_dev_dis = 0xf,
.use_default_parameter = false,
.is_double_sensitivity_mode = false,
+ .vstatus_offset = 0,
+ .vstatus_busy = PHY_VSTS_BUSY,
+ .new_reg_req = PHY_NEW_REG_REQ,
};
static const struct phy_cfg rtd1395_phy_cfg_2port = {
@@ -1133,6 +1149,9 @@ static const struct phy_cfg rtd1395_phy_cfg_2port = {
.driving_updated_for_dev_dis = 0xf,
.use_default_parameter = false,
.is_double_sensitivity_mode = false,
+ .vstatus_offset = 0,
+ .vstatus_busy = PHY_VSTS_BUSY,
+ .new_reg_req = PHY_NEW_REG_REQ,
};
static const struct phy_cfg rtd1619_phy_cfg = {
@@ -1155,6 +1174,9 @@ static const struct phy_cfg rtd1619_phy_cfg = {
.driving_updated_for_dev_dis = 0xf,
.use_default_parameter = false,
.is_double_sensitivity_mode = false,
+ .vstatus_offset = 0,
+ .vstatus_busy = PHY_VSTS_BUSY,
+ .new_reg_req = PHY_NEW_REG_REQ,
};
static const struct phy_cfg rtd1319_phy_cfg = {
@@ -1181,6 +1203,9 @@ static const struct phy_cfg rtd1319_phy_cfg = {
.driving_updated_for_dev_dis = 0xf,
.use_default_parameter = false,
.is_double_sensitivity_mode = true,
+ .vstatus_offset = 0,
+ .vstatus_busy = PHY_VSTS_BUSY,
+ .new_reg_req = PHY_NEW_REG_REQ,
};
static const struct phy_cfg rtd1312c_phy_cfg = {
@@ -1206,6 +1231,9 @@ static const struct phy_cfg rtd1312c_phy_cfg = {
.driving_updated_for_dev_dis = 0xf,
.use_default_parameter = false,
.is_double_sensitivity_mode = true,
+ .vstatus_offset = 0,
+ .vstatus_busy = PHY_VSTS_BUSY,
+ .new_reg_req = PHY_NEW_REG_REQ,
};
static const struct phy_cfg rtd1619b_phy_cfg = {
@@ -1231,6 +1259,9 @@ static const struct phy_cfg rtd1619b_phy_cfg = {
.driving_updated_for_dev_dis = 0x8,
.use_default_parameter = false,
.is_double_sensitivity_mode = true,
+ .vstatus_offset = 0,
+ .vstatus_busy = PHY_VSTS_BUSY,
+ .new_reg_req = PHY_NEW_REG_REQ,
};
static const struct phy_cfg rtd1319d_phy_cfg = {
@@ -1256,6 +1287,9 @@ static const struct phy_cfg rtd1319d_phy_cfg = {
.driving_updated_for_dev_dis = 0x8,
.use_default_parameter = false,
.is_double_sensitivity_mode = true,
+ .vstatus_offset = 0,
+ .vstatus_busy = PHY_VSTS_BUSY,
+ .new_reg_req = PHY_NEW_REG_REQ,
};
static const struct phy_cfg rtd1315e_phy_cfg = {
@@ -1282,6 +1316,9 @@ static const struct phy_cfg rtd1315e_phy_cfg = {
.driving_updated_for_dev_dis = 0x8,
.use_default_parameter = false,
.is_double_sensitivity_mode = true,
+ .vstatus_offset = 0,
+ .vstatus_busy = PHY_VSTS_BUSY,
+ .new_reg_req = PHY_NEW_REG_REQ,
};
static const struct of_device_id usbphy_rtk_dt_match[] = {
--
2.53.0
^ permalink raw reply related
* [PATCH v3 0/6] phy: realtek: usb2: support for RTL9607C USB2 PHY
From: Rustam Adilov @ 2026-04-02 15:44 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Stanley Chang, linux-phy, devicetree, linux-kernel
Cc: Rustam Adilov
This patch series for Realtek USB2 PHY driver adds support for RTL9607C
USB2 PHY.
RTL9607C is a big endian MIPS CPU which is quite far from RTD series SoCs
supported by realtek usb2 phy driver, but the phy initilization is found
to be very indentical in most areas.
Most of the code was based on the Realtek's usb driver from the GPL tarball
in [1] and adjusted to fit into the realtek usb2 phy driver code format.
The patch series was split into smaller patches that add/change something
in the driver that are not exactly related to RTL9607C and that also
helps for easier review. That also means, patch 5 depends on all the prior
patches that come before it.
USB2 PHY on RTL9607C is primarly used for its internal OHCI/EHCI controllers.
[1] - https://github.com/jameywine/GPL-for-GP3000/blob/main/linux-5.10.x/arch/mips/rtl9607c/usb.c
---
Changelog in v3:
- Patch 2
- renamed phy read and functions to "rtk_usb2phy" to not collide with networking API functions
- fixed the sparse warnings by creating intermidiate "tmp" variable and then pass it to writel
- sligtly adjusted commit message to instead use "default read" not "default phy_read"
- Patch 4
- added the check for reset_control_deassert() just in case
- changed mdelay(5) to msleep(5)
- changed dev_err and return combo with one dev_err_probe for phy_rst
- Patch 5
- changed mdelay(10) under force_host_disconnect to msleep(10)
- removed struct fields with false like force_host_disconnect and more in rtl9607_phy_cfg
- Patch 6
- updated the #endif commend to now include MACH_REALTEK_RTL to reflect if on top
- Link to v2: https://lore.kernel.org/linux-phy/20260327160638.15134-1-adilov@disroot.org/
Changelog in v2:
- Patch 5
- removed the line about OHCI/EHCI controllers from description.
- set the resets to false for RTD SoC devices and changed the
commit message to reflect that.
- Link to v1: https://lore.kernel.org/linux-phy/20260326193419.48419-1-adilov@disroot.org/
Rustam Adilov (6):
phy: realtek: usb2: introduce vstatus/new_reg_req variables to driver
data
phy: realtek: usb2: introduce read and write functions to driver data
dt-bindings: phy: realtek,usb2phy.yaml: extend for resets and RTL9607C
support
phy: realtek: usb2: introduce reset controller struct
phy: realtek: usb2: add support for RTL9607C USB2 PHY
phy: realtek: Make configs available for MACH_REALTEK_RTL
.../bindings/phy/realtek,usb2phy.yaml | 25 ++-
drivers/phy/realtek/Kconfig | 4 +-
drivers/phy/realtek/phy-rtk-usb2.c | 183 ++++++++++++++++--
3 files changed, 191 insertions(+), 21 deletions(-)
--
2.53.0
^ permalink raw reply
* Re: [PATCH 5/8] thermal: khadas-mcu-fan: Add fan config from platform data Add regulator support
From: Neil Armstrong @ 2026-04-02 15:39 UTC (permalink / raw)
To: Ronald Claveau, Lee Jones, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Andi Shyti, Kevin Hilman, Jerome Brunet,
Martin Blumenstingl, Beniamino Galvani, Rafael J. Wysocki,
Daniel Lezcano, Zhang Rui, Lukasz Luba, Liam Girdwood, Mark Brown
Cc: linux-amlogic, devicetree, linux-kernel, linux-i2c,
linux-arm-kernel, linux-pm
In-Reply-To: <20260402-add-mcu-fan-khadas-vim4-v1-5-2b12eb4ac7b0@aliel.fr>
On 4/2/26 16:27, Ronald Claveau wrote:
> Replace the hardcoded MAX_LEVEL constant and fan register
> with values read from platform_data (fan_reg, max_level),
> as new MCUs need different values.
>
> Optionally acquire and enable a "fan" regulator supply
> at probe time and on resume,
> so boards that gate fan power through a regulator are handled.
>
> Signed-off-by: Ronald Claveau <linux-kernel-dev@aliel.fr>
> ---
> drivers/thermal/khadas_mcu_fan.c | 43 ++++++++++++++++++++++++++++++++++------
> 1 file changed, 37 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/thermal/khadas_mcu_fan.c b/drivers/thermal/khadas_mcu_fan.c
> index d35e5313bea41..55b496625e3bd 100644
> --- a/drivers/thermal/khadas_mcu_fan.c
> +++ b/drivers/thermal/khadas_mcu_fan.c
> @@ -13,13 +13,15 @@
> #include <linux/regmap.h>
> #include <linux/sysfs.h>
> #include <linux/thermal.h>
> -
> -#define MAX_LEVEL 3
> +#include <linux/regulator/consumer.h>
>
> struct khadas_mcu_fan_ctx {
> struct khadas_mcu *mcu;
> + unsigned int fan_reg;
> unsigned int level;
> + unsigned int max_level;
> struct thermal_cooling_device *cdev;
> + struct regulator *power;
> };
>
> static int khadas_mcu_fan_set_level(struct khadas_mcu_fan_ctx *ctx,
> @@ -27,8 +29,7 @@ static int khadas_mcu_fan_set_level(struct khadas_mcu_fan_ctx *ctx,
> {
> int ret;
>
> - ret = regmap_write(ctx->mcu->regmap, KHADAS_MCU_CMD_FAN_STATUS_CTRL_REG,
> - level);
> + ret = regmap_write(ctx->mcu->regmap, ctx->fan_reg, level);
> if (ret)
> return ret;
>
> @@ -40,7 +41,9 @@ static int khadas_mcu_fan_set_level(struct khadas_mcu_fan_ctx *ctx,
> static int khadas_mcu_fan_get_max_state(struct thermal_cooling_device *cdev,
> unsigned long *state)
> {
> - *state = MAX_LEVEL;
> + struct khadas_mcu_fan_ctx *ctx = cdev->devdata;
> +
> + *state = ctx->max_level;
>
> return 0;
> }
> @@ -61,7 +64,7 @@ khadas_mcu_fan_set_cur_state(struct thermal_cooling_device *cdev,
> {
> struct khadas_mcu_fan_ctx *ctx = cdev->devdata;
>
> - if (state > MAX_LEVEL)
> + if (state > ctx->max_level)
> return -EINVAL;
>
> if (state == ctx->level)
> @@ -83,11 +86,32 @@ static int khadas_mcu_fan_probe(struct platform_device *pdev)
> struct device *dev = &pdev->dev;
> struct khadas_mcu_fan_ctx *ctx;
> int ret;
> + const struct khadas_mcu_fan_pdata *pdata = dev_get_platdata(&pdev->dev);
>
> ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
> if (!ctx)
> return -ENOMEM;
> +
> ctx->mcu = mcu;
> + ctx->fan_reg = pdata->fan_reg;
> + ctx->max_level = pdata->max_level;
> +
> + ctx->power = devm_regulator_get_optional(dev->parent, "fan");
> + if (IS_ERR(ctx->power)) {
> + if (PTR_ERR(ctx->power) == -ENODEV)
> + ctx->power = NULL;
> + else
> + return PTR_ERR(ctx->power);
> + }
> +
> + if (ctx->power) {
> + ret = regulator_enable(ctx->power);
> + if (ret) {
> + dev_err(dev, "Failed to enable fan power supply: %d\n", ret);
> + return ret;
> + }
> + }
> +
> platform_set_drvdata(pdev, ctx);
>
> cdev = devm_thermal_of_cooling_device_register(dev->parent,
> @@ -130,6 +154,13 @@ static int khadas_mcu_fan_suspend(struct device *dev)
> static int khadas_mcu_fan_resume(struct device *dev)
> {
> struct khadas_mcu_fan_ctx *ctx = dev_get_drvdata(dev);
> + int ret;
> +
> + if (ctx->power) {
> + ret = regulator_enable(ctx->power);
Seems you're missing a regulator_disable() on suspend.
Neil
> + if (ret)
> + return ret;
> + }
>
> return khadas_mcu_fan_set_level(ctx, ctx->level);
> }
>
^ permalink raw reply
* Re: [PATCH v20 2/6] pwm: driver for qualcomm ipq6018 pwm block
From: Uwe Kleine-König @ 2026-04-02 15:35 UTC (permalink / raw)
To: george.moussalem
Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Baruch Siach,
Bjorn Andersson, Konrad Dybcio, linux-arm-msm, linux-pwm,
devicetree, linux-kernel, Devi Priya, Baruch Siach
In-Reply-To: <20260204-ipq-pwm-v20-2-91733011a3d1@outlook.com>
[-- Attachment #1: Type: text/plain, Size: 2582 bytes --]
Hello,
I applied the patch and reviewed it in my editor. Here is the resulting
diff:
diff --git a/drivers/pwm/pwm-ipq.c b/drivers/pwm/pwm-ipq.c
index b944ecb456d5..4818d0170d53 100644
--- a/drivers/pwm/pwm-ipq.c
+++ b/drivers/pwm/pwm-ipq.c
@@ -97,9 +97,10 @@ static int ipq_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
if (state->polarity != PWM_POLARITY_NORMAL)
return -EINVAL;
- if (!ipq_chip->clk_rate)
- return -EINVAL;
-
+ /*
+ * XXX Why? A comment please. (Is this already covered by the checks
+ * below?)
+ */
if (state->period < DIV64_U64_ROUND_UP(NSEC_PER_SEC,
ipq_chip->clk_rate))
return -ERANGE;
@@ -107,18 +108,29 @@ static int ipq_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
period_ns = min(state->period, IPQ_PWM_MAX_PERIOD_NS);
duty_ns = min(state->duty_cycle, period_ns);
+ /*
+ * Pick the maximal value for PWM_DIV that still allows a
+ * 100% relative duty cycle. This allows a fine grained
+ * selection of duty cycles.
+ */
pwm_div = IPQ_PWM_MAX_DIV - 1;
+
+ /*
+ * XXX mul_u64_u64_div_u64 returns an u64, this might overflow the
+ * unsigned int pre_div.
+ */
pre_div = mul_u64_u64_div_u64(period_ns, ipq_chip->clk_rate,
(u64)NSEC_PER_SEC * (pwm_div + 1));
- pre_div = (pre_div > 0) ? pre_div - 1 : 0;
+
+ if (!pre_div)
+ return -ERANGE;
+
+ pre_div -= 1;
if (pre_div > IPQ_PWM_MAX_DIV)
pre_div = IPQ_PWM_MAX_DIV;
- /*
- * high duration = pwm duty * (pwm div + 1)
- * pwm duty = duty_ns / period_ns
- */
+ /* pwm duty = HI_DUR * (PRE_DIV + 1) / clk_rate */
hi_dur = mul_u64_u64_div_u64(duty_ns, ipq_chip->clk_rate,
(u64)(pre_div + 1) * NSEC_PER_SEC);
@@ -161,6 +173,10 @@ static int ipq_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
pre_div = FIELD_GET(IPQ_PWM_REG1_PRE_DIV, reg1);
effective_div = (u64)(pre_div + 1) * (pwm_div + 1);
+
+ /*
+ * effective_div <= 0x100000000, so the multiplication doesn't overflow.
+ */
state->period = DIV64_U64_ROUND_UP(effective_div * NSEC_PER_SEC,
ipq_chip->clk_rate);
@@ -210,6 +226,8 @@ static int ipq_pwm_probe(struct platform_device *pdev)
return dev_err_probe(dev, ret, "Failed to lock clock rate\n");
pwm->clk_rate = clk_get_rate(clk);
+ if (!pwm->clk_rate)
+ return dev_err_probe(dev, -EINVAL, "Failed due to clock rate being zero\n");
chip->ops = &ipq_pwm_ops;
Comments with XXX need more code adaptions (or a comment why my concern
isn't justified).
Best regards
Uwe
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply related
* RE: [PATCH v2 00/24] ASoC: rsnd: Add audio support for the Renesas RZ/G3E SoC
From: John Madieu @ 2026-04-02 15:30 UTC (permalink / raw)
To: Mark Brown
Cc: Geert Uytterhoeven, Kuninori Morimoto, Vinod Koul, Rob Herring,
Krzysztof Kozlowski, Michael Turquette, Stephen Boyd,
Conor Dooley, Frank Li, Liam Girdwood, magnus.damm,
Thomas Gleixner, Jaroslav Kysela, Takashi Iwai, Philipp Zabel,
Claudiu.Beznea, Biju Das, Fabrizio Castro, Prabhakar Mahadev Lad,
John Madieu, linux-renesas-soc@vger.kernel.org,
linux-clk@vger.kernel.org, devicetree@vger.kernel.org,
linux-kernel@vger.kernel.org, dmaengine@vger.kernel.org,
linux-sound@vger.kernel.org
In-Reply-To: <0c5afdbd-1348-4c61-b036-89adafeb5109@sirena.org.uk>
Hi Mark,
Thanks for the feedback.
> -----Original Message-----
> From: Mark Brown <broonie@kernel.org>
> Sent: Thursday, April 2, 2026 1:55 PM
> To: John Madieu <john.madieu.xa@bp.renesas.com>
> Subject: Re: [PATCH v2 00/24] ASoC: rsnd: Add audio support for the
> Renesas RZ/G3E SoC
>
> On Thu, Apr 02, 2026 at 11:04:59AM +0200, John Madieu wrote:
>
> > This series adds audio support for the Renesas RZ/G3E SoC and enables
> > it on the SMARC EVK board with the Dialog DA7212 codec.
>
> > The RZ/G3E audio subsystem is based on R-Car Sound IP but has several
> > differences requiring dedicated handling:
> > - SSI operates exclusively in BUSIF mode (no PIO)
> > - 2 BUSIF channels per SSI instead of 4/8 on R-Car
> > - Different register offsets for SCU, ADG, SSIU, and SSI
> > - Per-SSI ADG and SSIF supply clocks
> > - DMA ACK signal routing through ICU
> >
> > This series includes:
> > - Clock driver support for audio clocks and resets
> > - DT bindings update for DMA ACK signal field
> > - IRQ chip extension for DMA ACK signal routing
> > - RZ-DMAC driver updates for ACK signal support
> > - R-Car Sound driver updates for RZ/G3E support
> > - System suspend/resume support
> > - Device tree nodes for RZ/G3E SMARC EVK
>
> You said you were going to separate out the serieses:
>
> https://lore.kernel.org/all/TY6PR01MB173779BDE4BE11739D3B7DAACFF4FA@TY6PR0
> 1MB17377.jpnprd01.prod.outlook.com/
My bad. Sorry for not taking care of it. I'll split into
subsystem-specific serieses and send the v3.
Regards,
John
^ permalink raw reply
* RE: [PATCH 0/2] Add Renesas RZ/G3L RSPI support
From: Biju Das @ 2026-04-02 15:17 UTC (permalink / raw)
To: Mark Brown
Cc: Krzysztof Kozlowski, biju.das.au, Fabrizio Castro, Rob Herring,
Conor Dooley, Geert Uytterhoeven, magnus.damm,
linux-spi@vger.kernel.org, linux-renesas-soc@vger.kernel.org,
devicetree@vger.kernel.org, linux-kernel@vger.kernel.org,
Prabhakar Mahadev Lad
In-Reply-To: <fb4a0a18-5fde-43a7-8b2f-3b79656e78eb@sirena.org.uk>
Hi Mark,
Thanks for the feedback.
> -----Original Message-----
> From: Mark Brown <broonie@kernel.org>
> Sent: 02 April 2026 15:52
> Subject: Re: [PATCH 0/2] Add Renesas RZ/G3L RSPI support
>
> On Thu, Apr 02, 2026 at 01:32:29PM +0000, Biju Das wrote:
> > > -----Original Message-----
> > > From: Mark Brown <broonie@kernel.org>
> > > Sent: 02 April 2026 14:20
> > > Subject: Re: [PATCH 0/2] Add Renesas RZ/G3L RSPI support
> > >
> > > On Thu, Apr 02, 2026 at 01:00:28PM +0000, Biju Das wrote:
>
> > > > Gentle ping.
>
> > > There's strongly negative feedback from Krzysztof...
>
> > I believe Krzysztof is complaining about patch [1] and his comments
> > were addressed in [2].
>
> That's really not at all clear from the discussion.
>
> Please include human readable descriptions of things like commits and issues being discussed in e-mail
> in your mails, this makes them much easier for humans to read especially when they have no internet
> access.
> I do frequently catch up on my mail on flights or while otherwise travelling so this is even more
> pressing for me than just being about making things a bit easier to read.
Agreed.
>
> > > Please don't send content free pings and please allow a reasonable
> > > time for review. People get busy, go on holiday, attend conferences
> > > and so on so unless there is some reason for urgency (like critical
> > > bug fixes) please allow at least a couple of weeks for review. If there have been review comments
> then people may be waiting for those to be addressed.
>
> > > Sending content free pings adds to the mail volume (if they are seen
> > > at
> > > all) which is often the problem and since they can't be reviewed
> > > directly if something has gone wrong you'll have to resend the
> > > patches anyway, so sending again is generally a better approach
> > > though there are some other maintainers who like them - if in doubt look at how patches for the
> subsystem are normally handled.
>
> > There is no pending points, everything addressed in [2]. that is the
> > reason for sending gentle reminder.
>
> There's more there than just "make sure you've addressed review comments".
The issues related to flexible DMA names for multiple DMAs are addressed by the
commit c2edd7841f58 ("spi: dt-bindings: renesas,rzv2h-rspi: Document dmas property").
It looks like Krzysztof wants strict ordering in bindings for DMA names, if it is
a single DMA.
I will wait for his feedback.
Cheers,
Biju
^ permalink raw reply
* Re: Re: Re: Re: Re: [PATCH 1/2] dt-bindings: gpu: mali-valhall-csf: Document i.MX952 support
From: Liviu Dudau @ 2026-04-02 15:14 UTC (permalink / raw)
To: Guangliu Ding
Cc: Daniel Baluta (OSS), Daniel Almeida, Alice Ryhl, Boris Brezillon,
Steven Price, David Airlie, Simona Vetter, Maarten Lankhorst,
Maxime Ripard, Thomas Zimmermann, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Frank Li, Sascha Hauer,
Pengutronix Kernel Team, Fabio Estevam,
dri-devel@lists.freedesktop.org, devicetree@vger.kernel.org,
linux-kernel@vger.kernel.org, imx@lists.linux.dev,
linux-arm-kernel@lists.infradead.org, Jiyu Yang
In-Reply-To: <AM0PR04MB470716BD5A538CFBB6685C87F350A@AM0PR04MB4707.eurprd04.prod.outlook.com>
On Wed, Apr 01, 2026 at 06:03:28PM +0000, Guangliu Ding wrote:
> Hi Liviu
>
> Thanks a lot for your sharing.
>
> > On Wed, Apr 01, 2026 at 03:59:23PM +0000, Guangliu Ding wrote:
> > > Hi Liviu
> > >
> > > > On Wed, Apr 01, 2026 at 10:31:01AM +0000, Guangliu Ding wrote:
> > > > > Hi Liviu
> > > > >
> > > > > > On Wed, Apr 01, 2026 at 09:43:12AM +0000, Guangliu Ding wrote:
> > > > > > > Hi Daniel
> > > > > > >
> > > > > > > > On 4/1/26 11:48, Guangliu Ding wrote:
> > > > > > > > > [You don't often get email from guangliu.ding@nxp.com.
> > > > > > > > > Learn why this is important at
> > > > > > > > > https://aka.ms/LearnAboutSenderIdentification
> > > > > > > > > ]
> > > > > > > > >
> > > > > > > > > Hi Liviu
> > > > > > > > >
> > > > > > > > > Thanks for your review. Please refer to my comments below:
> > > > > > > > >
> > > > > > > > >> On Tue, Mar 31, 2026 at 06:12:38PM +0800, Guangliu Ding
> > wrote:
> > > > > > > > >>> Add compatible string of Mali G310 GPU on i.MX952 board.
> > > > > > > > >>>
> > > > > > > > >>> Signed-off-by: Guangliu Ding <guangliu.ding@nxp.com>
> > > > > > > > >>> Reviewed-by: Jiyu Yang <jiyu.yang@nxp.com>
> > > > > > > > >>> ---
> > > > > > > > >>>
> > > > > > > > >>> Documentation/devicetree/bindings/gpu/arm,mali-valhall-c
> > > > > > > > >>> sf.y
> > > > > > > > >>> aml
> > > > > > > > >>> | 1
> > > > > > > > >>> +
> > > > > > > > >>> 1 file changed, 1 insertion(+)
> > > > > > > > >>>
> > > > > > > > >>> diff --git
> > > > > > > > >>> a/Documentation/devicetree/bindings/gpu/arm,mali-valhall
> > > > > > > > >>> -csf
> > > > > > > > >>> .yam
> > > > > > > > >>> l
> > > > > > > > >> b/Documentation/devicetree/bindings/gpu/arm,mali-valhall-csf.
> > > > > > > > >> yaml
> > > > > > > > >>> index 8eccd4338a2b..6a10843a26e2 100644
> > > > > > > > >>> ---
> > > > > > > > >>> a/Documentation/devicetree/bindings/gpu/arm,mali-valhall
> > > > > > > > >>> -csf
> > > > > > > > >>> .yam
> > > > > > > > >>> l
> > > > > > > > >>> +++ b/Documentation/devicetree/bindings/gpu/arm,mali-val
> > > > > > > > >>> +++ hall
> > > > > > > > >>> +++ -csf
> > > > > > > > >>> +++ .yam
> > > > > > > > >>> +++ l
> > > > > > > > >>> @@ -20,6 +20,7 @@ properties:
> > > > > > > > >>> - enum:
> > > > > > > > >>> - mediatek,mt8196-mali
> > > > > > > > >>> - nxp,imx95-mali # G310
> > > > > > > > >>> + - nxp,imx952-mali # G310
> > > > > > > > >> Can you explain why this is needed? Can it not be covered
> > > > > > > > >> by the existing compatible?
> > > > > > > > > There are functional differences in GPU module (GPUMIX)
> > > > > > > > > between
> > > > > > > > > i.MX95 and i.MX952. So they cannot be fully covered by a
> > > > > > > > > single existing
> > > > > > compatible.
> > > > > > > > > On i.MX952, The GPU clock is controlled by hardware GPU
> > > > > > > > > auto clock-gating mechanism, while the GPU clock is
> > > > > > > > > managed explicitly by the
> > > > > > > > driver on i.MX95.
> > > > > > > > > Because of these behavioral differences, separate
> > > > > > > > > compatible strings "nxp,imx95-mali" and "nxp,imx952-mali"
> > > > > > > > > are needed to allow the driver to handle the two variants
> > > > > > > > > independently and to keep room for future
> > > > > > > > divergence.
> > > > > > > >
> > > > > > > >
> > > > > > > > This information should be added in the commit message
> > > > > > > > explaining why
> > > > > > > >
> > > > > > > > the change is needed.
> > > > > > > >
> > > > > > > >
> > > > > > > > But then where is the driver code taking care of these diferences?
> > > > > > > >
> > > > > > >
> > > > > > > Yes. Currently the driver does not require "nxp,imx952-mali" string.
> > > > > > > However, when GPU ipa_counters are enabled to calculate the
> > > > > > > GPU busy_time/idle_time for GPU DVFS feature, they will
> > > > > > > conflict with the hardware GPU auto clock‑gating mechanism,
> > > > > > > causing GPU clock to remain
> > > > > > always on.
> > > > > > > In such cases, ipa_counters need to be disabled so that the
> > > > > > > GPU auto clock‑gating mechanism can operate normally, using
> > > > "nxp,imx952-mali"
> > > > > > string.
> > > > > >
> > > > > > OK, I understand that you're following guidance from some other
> > > > > > senior people on how to upstream patches so you've tried to
> > > > > > create the smallest patchset to ensure that it gets reviewed and
> > > > > > accepted, but in this case we need to see the other patches as
> > > > > > well to decide if your approach is the right one and we do need
> > > > > > a separate compatible
> > > > string.
> > > > > >
> > > > > > If enabling GPU ipa_counters causes the clocks to get stuck
> > > > > > active, that feels like a hardware bug, so figuring out how to
> > > > > > handle that is more important than adding a compatible string.
> > > > > >
> > > > > > Either add the patch(es) that use the compatible to this series
> > > > > > in v2, or put a comment in the commit message on where we can
> > > > > > see the
> > > > driver changes.
> > > > > >
> > > > >
> > > > > According to discussions with the GPU vendor, this is a hardware
> > > > > limitation of Mali-G310 rather than a hardware bug, and it has
> > > > > been addressed in newer Mali GPU families.
> > > >
> > > > I represent the said GPU vendor and I think I know what you're
> > > > talking about, but you're taking the wrong approach. All G310s have
> > > > a problem where in order to enable access to the ipa_counters the
> > > > automatic clock gating gets disabled. So the solution that needs to
> > > > be implemented when we add support for IPA_COUNTERs will apply to all
> > GPUs, not just MX952.
> > >
> > > Yes. We have bring-up G310 (V2) GPU on both i.MX95 and i.MX952. And
> > > auto clock gating mechanism is firstly introduced in i.MX952 (not supported
> > on i.MX95).
> > > According to your update, solution needs to be implemented to all GPUs
> > > which support auto clock gating mechanism after IPA_COUNTERs are
> > supported in the driver, right?
> >
> > A solution is needed, yes.
> >
> > > What's your suggestions for 952 gpu dtb node?
> >
> > There is no IPA_COUNTER use in Panthor at the moment. Unless your DVFS
> > controller uses that, I would suggest that we don't introduce a compatible for
> > 952 until the time we add support for reading the counters.
> >
> > It helps if you think in terms of what is already in upstream, rather than mixing
> > with the tests that uses kbase code. Does your hardware need extra code in
> > upstream in order to function? If so, where is that code? If not, then let's not
> > introduce the compatible until we are absolutely sure we need it because we
> > have code specific to that SoC. For everything else we will implement an
> > architecture fix if needed.
> >
>
> Got it. The following compatible string is the correct choice since the GPU on
> i.MX952 is fully compatible with the GPU on i.MX95 now.
> compatible = "nxp,imx95-mali", "arm,mali-valhall-csf";
>
> I will not mix tests with kbase code in the following upstream patches for panthor driver.
OK. I think if you drop patch 2/3 from your series you can send a v3.
Best regards,
Liviu
--
====================
| I would like to |
| fix the world, |
| but they're not |
| giving me the |
\ source code! /
---------------
¯\_(ツ)_/¯
^ permalink raw reply
* Re: [PATCH] dt-bindings: arm: arm,vexpress-scc: convert to DT schema
From: Liviu Dudau @ 2026-04-02 15:11 UTC (permalink / raw)
To: Khushal Chitturi
Cc: robh, krzk+dt, conor+dt, sudeep.holla, lpieralisi, pawel.moll,
devicetree, linux-arm-kernel, linux-kernel
In-Reply-To: <20260331172959.35745-1-khushalchitturi@gmail.com>
Hello,
Thanks for your patch, I have some suggestions to improve it.
On Tue, Mar 31, 2026 at 10:59:59PM +0530, Khushal Chitturi wrote:
> Convert the ARM Versatile Express Serial Configuration Controller
> bindings to DT schema.
>
> Signed-off-by: Khushal Chitturi <khushalchitturi@gmail.com>
> ---
> Note:
> * This patch is part of the GSoC2026 application process for device tree bindings conversions
> * https://github.com/LinuxFoundationGSoC/ProjectIdeas/wiki/GSoC-2026-Device-Tree-Bindings
>
> .../bindings/arm/arm,vexpress-scc.yaml | 51 +++++++++++++++++++
> .../devicetree/bindings/arm/vexpress-scc.txt | 33 ------------
> 2 files changed, 51 insertions(+), 33 deletions(-)
> create mode 100644 Documentation/devicetree/bindings/arm/arm,vexpress-scc.yaml
> delete mode 100644 Documentation/devicetree/bindings/arm/vexpress-scc.txt
>
> diff --git a/Documentation/devicetree/bindings/arm/arm,vexpress-scc.yaml b/Documentation/devicetree/bindings/arm/arm,vexpress-scc.yaml
> new file mode 100644
> index 000000000000..7870410211a0
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/arm/arm,vexpress-scc.yaml
> @@ -0,0 +1,51 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/arm/arm,vexpress-scc.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: ARM Versatile Express Serial Configuration Controller
> +
> +maintainers:
> + - Pawel Moll <pawel.moll@arm.com>
I'm not sure Pawel wants to be maintainer for this file, maybe add me and Sudeep
instead. I'd also wait until Pawel replies.
> +
> +description: |
> + Test chips for ARM Versatile Express platform implement SCC (Serial
> + Configuration Controller) interface, used to set initial conditions
> + for the test chip.
> +
> + In some cases its registers are also mapped in normal address space
> + and can be used to obtain runtime information about the chip internals
> + (like silicon temperature sensors) and as interface to other subsystems
> + like platform configuration control and power management.
> +
> +properties:
> + compatible:
> + items:
> + - pattern: "^arm,vexpress-scc,[a-z0-9_-]+$"
This is way too generic. I suggest you have a look at bindings/arm/arm,vexpress-juno.yaml
and see how we defined the possible values for the compatible string there. For the initial
conversion I would suggest you only define as valid the "arm,vexpress-scc,v2p-ca15_a7" value
but in a way similar to Juno's file so that it can be extended in the future.
Best regards,
Liviu
> + - const: arm,vexpress-scc
> +
> + reg:
> + maxItems: 1
> +
> + interrupts:
> + maxItems: 1
> +
> +required:
> + - compatible
> +
> +additionalProperties: false
> +
> +examples:
> + - |
> + bus {
> + #address-cells = <2>;
> + #size-cells = <2>;
> +
> + scc@7fff0000 {
> + compatible = "arm,vexpress-scc,v2p-ca15_a7", "arm,vexpress-scc";
> + reg = <0 0x7fff0000 0 0x1000>;
> + interrupts = <0 95 4>;
> + };
> + };
> +...
> diff --git a/Documentation/devicetree/bindings/arm/vexpress-scc.txt b/Documentation/devicetree/bindings/arm/vexpress-scc.txt
> deleted file mode 100644
> index ae5043e42e5d..000000000000
> --- a/Documentation/devicetree/bindings/arm/vexpress-scc.txt
> +++ /dev/null
> @@ -1,33 +0,0 @@
> -ARM Versatile Express Serial Configuration Controller
> ------------------------------------------------------
> -
> -Test chips for ARM Versatile Express platform implement SCC (Serial
> -Configuration Controller) interface, used to set initial conditions
> -for the test chip.
> -
> -In some cases its registers are also mapped in normal address space
> -and can be used to obtain runtime information about the chip internals
> -(like silicon temperature sensors) and as interface to other subsystems
> -like platform configuration control and power management.
> -
> -Required properties:
> -
> -- compatible value: "arm,vexpress-scc,<model>", "arm,vexpress-scc";
> - where <model> is the full tile model name (as used
> - in the tile's Technical Reference Manual),
> - eg. for Coretile Express A15x2 A7x3 (V2P-CA15_A7):
> - compatible = "arm,vexpress-scc,v2p-ca15_a7", "arm,vexpress-scc";
> -
> -Optional properties:
> -
> -- reg: when the SCC is memory mapped, physical address and size of the
> - registers window
> -- interrupts: when the SCC can generate a system-level interrupt
> -
> -Example:
> -
> - scc@7fff0000 {
> - compatible = "arm,vexpress-scc,v2p-ca15_a7", "arm,vexpress-scc";
> - reg = <0 0x7fff0000 0 0x1000>;
> - interrupts = <0 95 4>;
> - };
> --
> 2.53.0
>
--
====================
| I would like to |
| fix the world, |
| but they're not |
| giving me the |
\ source code! /
---------------
¯\_(ツ)_/¯
^ permalink raw reply
* Re: [RFC PATCH] dt-bindings: incomplete-devices: allow additional properties
From: Wolfram Sang @ 2026-04-02 14:52 UTC (permalink / raw)
To: Krzysztof Kozlowski
Cc: linux-renesas-soc, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
devicetree
In-Reply-To: <c2095c20-834d-4f52-aa82-07f0cd6fb228@kernel.org>
[-- Attachment #1: Type: text/plain, Size: 147 bytes --]
> This solves nothing - the entire point is to have warning for
> 'broken-usage-of-incorrect-compatible'.
Ok, this answers my question. Thanks!
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply
* Re: [PATCH 0/2] Add Renesas RZ/G3L RSPI support
From: Mark Brown @ 2026-04-02 14:51 UTC (permalink / raw)
To: Biju Das
Cc: Krzysztof Kozlowski, biju.das.au, Fabrizio Castro, Rob Herring,
Conor Dooley, Geert Uytterhoeven, magnus.damm,
linux-spi@vger.kernel.org, linux-renesas-soc@vger.kernel.org,
devicetree@vger.kernel.org, linux-kernel@vger.kernel.org,
Prabhakar Mahadev Lad
In-Reply-To: <TY3PR01MB11346472F87787030828ACFFE8651A@TY3PR01MB11346.jpnprd01.prod.outlook.com>
[-- Attachment #1: Type: text/plain, Size: 1913 bytes --]
On Thu, Apr 02, 2026 at 01:32:29PM +0000, Biju Das wrote:
> > -----Original Message-----
> > From: Mark Brown <broonie@kernel.org>
> > Sent: 02 April 2026 14:20
> > Subject: Re: [PATCH 0/2] Add Renesas RZ/G3L RSPI support
> >
> > On Thu, Apr 02, 2026 at 01:00:28PM +0000, Biju Das wrote:
> > > Gentle ping.
> > There's strongly negative feedback from Krzysztof...
> I believe Krzysztof is complaining about patch [1] and his
> comments were addressed in [2].
That's really not at all clear from the discussion.
Please include human readable descriptions of things like commits and
issues being discussed in e-mail in your mails, this makes them much
easier for humans to read especially when they have no internet access.
I do frequently catch up on my mail on flights or while otherwise
travelling so this is even more pressing for me than just being about
making things a bit easier to read.
> > Please don't send content free pings and please allow a reasonable time for review. People get busy,
> > go on holiday, attend conferences and so on so unless there is some reason for urgency (like critical
> > bug fixes) please allow at least a couple of weeks for review. If there have been review comments then
> > people may be waiting for those to be addressed.
> > Sending content free pings adds to the mail volume (if they are seen at
> > all) which is often the problem and since they can't be reviewed directly if something has gone wrong
> > you'll have to resend the patches anyway, so sending again is generally a better approach though there
> > are some other maintainers who like them - if in doubt look at how patches for the subsystem are
> > normally handled.
> There is no pending points, everything addressed in [2]. that is the reason for
> sending gentle reminder.
There's more there than just "make sure you've addressed review
comments".
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply
* Re: [PATCH v10 6/6] usb: typec: tcpm/tcpci_maxim: deprecate WAR for setting charger mode
From: Heikki Krogerus @ 2026-04-02 14:33 UTC (permalink / raw)
To: amitsd
Cc: André Draszik, Lee Jones, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Greg Kroah-Hartman, Jagan Sridharan, Mark Brown,
Matti Vaittinen, Andrew Morton, Sebastian Reichel, Peter Griffin,
Tudor Ambarus, Alim Akhtar, linux-kernel, devicetree, linux-usb,
linux-pm, linux-arm-kernel, linux-samsung-soc, RD Babiera,
Kyle Tso
In-Reply-To: <20260331-max77759-charger-v10-6-76f59233c369@google.com>
Hi Amit,
> +static int get_vbus_regulator_handle(struct max_tcpci_chip *chip)
> +{
> + if (IS_ERR_OR_NULL(chip->vbus_reg)) {
> + chip->vbus_reg = devm_regulator_get_exclusive(chip->dev,
> + "vbus");
Sorry to go back to this, but why can't you just get the regulator in
max_tcpci_probe()?
thanks,
> + if (IS_ERR_OR_NULL(chip->vbus_reg)) {
> + dev_err(chip->dev,
> + "Failed to get vbus regulator handle\n");
> + return -ENODEV;
> + }
> + }
> +
> + return 0;
> +}
--
heikki
^ permalink raw reply
* Re: [PATCH 6/6] arm64: dts: qcom: milos: Add Adreno 810 GPU and GMU nodes
From: Alexander Koskovich @ 2026-04-02 14:28 UTC (permalink / raw)
To: Krzysztof Kozlowski
Cc: Rob Clark, Dmitry Baryshkov, Abhinav Kumar, Jessica Zhang,
Sean Paul, Marijn Suijten, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, David Airlie, Simona Vetter, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Konrad Dybcio, Akhil P Oommen,
Bjorn Andersson, Luca Weiss, linux-arm-msm, dri-devel, freedreno,
devicetree, linux-kernel
In-Reply-To: <20260402-military-arrogant-woodpecker-4ab9b5@quoll>
On Thursday, April 2nd, 2026 at 4:19 AM, Krzysztof Kozlowski <krzk@kernel.org> wrote:
> On Wed, Apr 01, 2026 at 02:17:44AM +0000, Alexander Koskovich wrote:
> > Add GPU and GMU devicetree nodes for the Adreno 810 GPU found on
> > Qualcomm SM7635 (Milos) based devices.
> >
> > Signed-off-by: Alexander Koskovich <akoskovich@pm.me>
> > ---
> > arch/arm64/boot/dts/qcom/milos.dtsi | 148 ++++++++++++++++++++++++++++++++++++
> > 1 file changed, 148 insertions(+)
> >
> > diff --git a/arch/arm64/boot/dts/qcom/milos.dtsi b/arch/arm64/boot/dts/qcom/milos.dtsi
> > index 621f05820826..a8feb0339804 100644
> > --- a/arch/arm64/boot/dts/qcom/milos.dtsi
> > +++ b/arch/arm64/boot/dts/qcom/milos.dtsi
> > @@ -7,6 +7,7 @@
> > #include <dt-bindings/clock/qcom,milos-dispcc.h>
> > #include <dt-bindings/clock/qcom,milos-gcc.h>
> > #include <dt-bindings/clock/qcom,milos-gpucc.h>
> > +#include <dt-bindings/clock/qcom,kaanapali-gxclkctl.h>
>
> Why? My next from 27th Match does not have Milos in that binding. Was it
> added? It's worth mentioning in commit msg.
They use the same driver and the GX_CLKCTL_GX_GDSC definition would be
identical, so the header can be reused. I'll mention it in the commit
msg for v2.
>
> Also, please keep alphabetical sort of the includes, k < m.
Fixed in v2.
>
> Best regards,
> Krzysztof
>
>
^ permalink raw reply
* [PATCH v4 4/4] arm64: tegra: Add PCI controllers on Tegra264
From: Thierry Reding @ 2026-04-02 14:27 UTC (permalink / raw)
To: Bjorn Helgaas, Lorenzo Pieralisi, Krzysztof Wilczyński,
Manivannan Sadhasivam, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Thierry Reding, Jonathan Hunter, Karthikeyan Mitran,
Hou Zhiqiang, Thomas Petazzoni, Pali Rohár, Michal Simek,
Kevin Xie
Cc: linux-pci, devicetree, linux-tegra, linux-kernel,
linux-arm-kernel, Thierry Reding
In-Reply-To: <20260402-tegra264-pcie-v4-0-21e2e19987e8@nvidia.com>
From: Thierry Reding <treding@nvidia.com>
A total of six PCIe controllers can be found on Tegra264. One of them is
used internally for the integrated GPU while the other five can go to a
variety of connectors like full PCIe slots or M.2.
Signed-off-by: Thierry Reding <treding@nvidia.com>
---
Changes in v4:
- revert ECAM "reg" entry order
Changes in v2:
- order ECAM "reg" entry before others
---
arch/arm64/boot/dts/nvidia/tegra264.dtsi | 248 +++++++++++++++++++++++++++----
1 file changed, 221 insertions(+), 27 deletions(-)
diff --git a/arch/arm64/boot/dts/nvidia/tegra264.dtsi b/arch/arm64/boot/dts/nvidia/tegra264.dtsi
index 7644a41d5f72..1bf5a2368afe 100644
--- a/arch/arm64/boot/dts/nvidia/tegra264.dtsi
+++ b/arch/arm64/boot/dts/nvidia/tegra264.dtsi
@@ -32,7 +32,7 @@ bus@0 {
#address-cells = <2>;
#size-cells = <2>;
- ranges = <0x00 0x00000000 0x00 0x00000000 0x01 0x00000000>;
+ ranges = <0x00 0x00000000 0x00 0x00000000 0x00 0x20000000>; /* MMIO (512 MiB) */
misc@100000 {
compatible = "nvidia,tegra234-misc";
@@ -3356,9 +3356,10 @@ bus@8100000000 {
#address-cells = <2>;
#size-cells = <2>;
- ranges = <0x00 0x00000000 0x81 0x00000000 0x01 0x00000000>, /* MMIO */
- <0x01 0x00000000 0x00 0x20000000 0x00 0x40000000>, /* non-prefetchable memory (32-bit) */
- <0x02 0x00000000 0xd0 0x00000000 0x08 0x80000000>; /* ECAM, prefetchable memory, I/O */
+ ranges = <0x00 0x00000000 0x81 0x00000000 0x00 0x20000000>, /* MMIO (512 MiB) */
+ <0x00 0x20000000 0x00 0x20000000 0x00 0x20000000>, /* non-prefetchable memory (32-bit, 512 MiB) */
+ <0x00 0x40000000 0x81 0x40000000 0x00 0x20000000>, /* MMIO (512 MiB) */
+ <0xa8 0x80000000 0xa8 0x80000000 0x57 0x80000000>; /* I/O, ECAM, prefetchable memory (64-bit) */
smmu1: iommu@5000000 {
compatible = "nvidia,tegra264-smmu", "arm,smmu-v3";
@@ -3402,23 +3403,23 @@ cmdqv2: cmdqv@6200000 {
mc: memory-controller@8020000 {
compatible = "nvidia,tegra264-mc";
- reg = <0x00 0x8020000 0x0 0x20000>, /* MC broadcast */
- <0x00 0x8040000 0x0 0x20000>, /* MC 0 */
- <0x00 0x8060000 0x0 0x20000>, /* MC 1 */
- <0x00 0x8080000 0x0 0x20000>, /* MC 2 */
- <0x00 0x80a0000 0x0 0x20000>, /* MC 3 */
- <0x00 0x80c0000 0x0 0x20000>, /* MC 4 */
- <0x00 0x80e0000 0x0 0x20000>, /* MC 5 */
- <0x00 0x8100000 0x0 0x20000>, /* MC 6 */
- <0x00 0x8120000 0x0 0x20000>, /* MC 7 */
- <0x00 0x8140000 0x0 0x20000>, /* MC 8 */
- <0x00 0x8160000 0x0 0x20000>, /* MC 9 */
- <0x00 0x8180000 0x0 0x20000>, /* MC 10 */
- <0x00 0x81a0000 0x0 0x20000>, /* MC 11 */
- <0x00 0x81c0000 0x0 0x20000>, /* MC 12 */
- <0x00 0x81e0000 0x0 0x20000>, /* MC 13 */
- <0x00 0x8200000 0x0 0x20000>, /* MC 14 */
- <0x00 0x8220000 0x0 0x20000>; /* MC 15 */
+ reg = <0x000 0x8020000 0x0 0x20000>, /* MC broadcast */
+ <0x000 0x8040000 0x0 0x20000>, /* MC 0 */
+ <0x000 0x8060000 0x0 0x20000>, /* MC 1 */
+ <0x000 0x8080000 0x0 0x20000>, /* MC 2 */
+ <0x000 0x80a0000 0x0 0x20000>, /* MC 3 */
+ <0x000 0x80c0000 0x0 0x20000>, /* MC 4 */
+ <0x000 0x80e0000 0x0 0x20000>, /* MC 5 */
+ <0x000 0x8100000 0x0 0x20000>, /* MC 6 */
+ <0x000 0x8120000 0x0 0x20000>, /* MC 7 */
+ <0x000 0x8140000 0x0 0x20000>, /* MC 8 */
+ <0x000 0x8160000 0x0 0x20000>, /* MC 9 */
+ <0x000 0x8180000 0x0 0x20000>, /* MC 10 */
+ <0x000 0x81a0000 0x0 0x20000>, /* MC 11 */
+ <0x000 0x81c0000 0x0 0x20000>, /* MC 12 */
+ <0x000 0x81e0000 0x0 0x20000>, /* MC 13 */
+ <0x000 0x8200000 0x0 0x20000>, /* MC 14 */
+ <0x000 0x8220000 0x0 0x20000>; /* MC 15 */
reg-names = "broadcast", "ch0", "ch1", "ch2", "ch3",
"ch4", "ch5", "ch6", "ch7", "ch8", "ch9",
"ch10", "ch11", "ch12", "ch13", "ch14",
@@ -3437,12 +3438,12 @@ mc: memory-controller@8020000 {
#size-cells = <2>;
/* limit the DMA range for memory clients to [39:0] */
- dma-ranges = <0x0 0x0 0x0 0x0 0x100 0x0>;
+ dma-ranges = <0x000 0x0 0x000 0x0 0x100 0x0>;
emc: external-memory-controller@8800000 {
compatible = "nvidia,tegra264-emc";
- reg = <0x00 0x8800000 0x0 0x20000>,
- <0x00 0x8890000 0x0 0x20000>;
+ reg = <0x000 0x8800000 0x0 0x20000>,
+ <0x000 0x8890000 0x0 0x20000>;
interrupts = <GIC_SPI 141 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&bpmp TEGRA264_CLK_EMC>,
<&bpmp TEGRA264_CLK_DBB_UPHY0>;
@@ -3493,6 +3494,38 @@ cmdqv4: cmdqv@b200000 {
status = "disabled";
};
+ pci@c000000 {
+ compatible = "nvidia,tegra264-pcie";
+ reg = <0x00 0x0c000000 0x0 0x00004000>,
+ <0x00 0x0c004000 0x0 0x00001000>,
+ <0x00 0x0c005000 0x0 0x00001000>,
+ <0xd0 0xb0000000 0x0 0x10000000>;
+ reg-names = "xal", "xtl", "xtl-pri", "ecam";
+ #address-cells = <3>;
+ #size-cells = <2>;
+ device_type = "pci";
+ linux,pci-domain = <0x00>;
+ #interrupt-cells = <0x1>;
+
+ interrupt-map-mask = <0x0 0x0 0x0 0x7>;
+ interrupt-map = <0x0 0x0 0x0 0x1 &gic 0x0 0x0 0x0 155 IRQ_TYPE_LEVEL_HIGH>,
+ <0x0 0x0 0x0 0x2 &gic 0x0 0x0 0x0 156 IRQ_TYPE_LEVEL_HIGH>,
+ <0x0 0x0 0x0 0x3 &gic 0x0 0x0 0x0 157 IRQ_TYPE_LEVEL_HIGH>,
+ <0x0 0x0 0x0 0x4 &gic 0x0 0x0 0x0 158 IRQ_TYPE_LEVEL_HIGH>;
+
+ iommu-map = <0x0 &smmu2 0x10000 0x10000>;
+ msi-map = <0x0 &its 0x210000 0x10000>;
+ dma-coherent;
+
+ ranges = <0x81000000 0x00 0x84000000 0xd0 0x84000000 0x00 0x00200000>, /* I/O */
+ <0x82000000 0x00 0x20000000 0x00 0x20000000 0x00 0x08000000>, /* non-prefetchable memory (128 MiB) */
+ <0xc3000000 0xd0 0xc0000000 0xd0 0xc0000000 0x07 0xc0000000>; /* prefetchable memory */
+ bus-range = <0x0 0xff>;
+
+ nvidia,bpmp = <&bpmp 0>;
+ status = "disabled";
+ };
+
i2c14: i2c@c410000 {
compatible = "nvidia,tegra264-i2c";
reg = <0x00 0x0c410000 0x0 0x10000>;
@@ -3720,7 +3753,7 @@ bus@8800000000 {
#address-cells = <2>;
#size-cells = <2>;
- ranges = <0x00 0x00000000 0x88 0x00000000 0x01 0x00000000>;
+ ranges = <0x00 0x00000000 0x88 0x00000000 0x00 0x20000000>; /* MMIO (512 MiB) */
smmu3: iommu@6000000 {
compatible = "nvidia,tegra264-smmu", "arm,smmu-v3";
@@ -3765,8 +3798,169 @@ bus@a800000000 {
#address-cells = <2>;
#size-cells = <2>;
- ranges = <0x00 0x00000000 0xa8 0x00000000 0x40 0x00000000>, /* MMIO, ECAM, prefetchable memory, I/O */
- <0x80 0x00000000 0x00 0x20000000 0x00 0x40000000>; /* non-prefetchable memory (32-bit) */
+ ranges = <0x00 0x00000000 0xa8 0x00000000 0x00 0x20000000>, /* MMIO (512 MiB) */
+ <0x00 0x20000000 0x00 0x20000000 0x00 0x60000000>, /* non-prefetchable memory (32-bit, 1536 GiB) */
+ <0xa8 0x80000000 0xa8 0x80000000 0x57 0x80000000>; /* I/O, ECAM, prefetchable memory (64-bit) */
+
+ pci@8400000 {
+ compatible = "nvidia,tegra264-pcie";
+ reg = <0x00 0x08400000 0x0 0x00004000>,
+ <0x00 0x08404000 0x0 0x00001000>,
+ <0x00 0x08405000 0x0 0x00001000>,
+ <0x00 0x08410000 0x0 0x00010000>,
+ <0xa8 0xb0000000 0x0 0x10000000>;
+ reg-names = "xal", "xtl", "xtl-pri", "xpl", "ecam";
+ #address-cells = <3>;
+ #size-cells = <2>;
+ device_type = "pci";
+ linux,pci-domain = <0x01>;
+ #interrupt-cells = <1>;
+ interrupt-map-mask = <0x0 0x0 0x0 0x7>;
+ interrupt-map = <0x0 0x0 0x0 0x1 &gic 0x0 0x0 0x0 908 IRQ_TYPE_LEVEL_HIGH>, /* INTA */
+ <0x0 0x0 0x0 0x2 &gic 0x0 0x0 0x0 909 IRQ_TYPE_LEVEL_HIGH>, /* INTB */
+ <0x0 0x0 0x0 0x3 &gic 0x0 0x0 0x0 910 IRQ_TYPE_LEVEL_HIGH>, /* INTC */
+ <0x0 0x0 0x0 0x4 &gic 0x0 0x0 0x0 911 IRQ_TYPE_LEVEL_HIGH>; /* INTD */
+
+ iommu-map = <0x0 &smmu1 0x10000 0x10000>;
+ msi-map = <0x0 &its 0x110000 0x10000>;
+ dma-coherent;
+
+ ranges = <0x81000000 0x00 0x84000000 0xa8 0x84000000 0x00 0x00200000>, /* I/O */
+ <0x82000000 0x00 0x28000000 0x00 0x28000000 0x00 0x08000000>, /* non-prefetchable memory */
+ <0xc3000000 0xa8 0xc0000000 0xa8 0xc0000000 0x07 0xc0000000>; /* prefetchable memory */
+ bus-range = <0x00 0xff>;
+
+ nvidia,bpmp = <&bpmp 1>;
+ status = "disabled";
+ };
+
+ pci@8420000 {
+ compatible = "nvidia,tegra264-pcie";
+ reg = <0x00 0x08420000 0x0 0x00004000>,
+ <0x00 0x08424000 0x0 0x00001000>,
+ <0x00 0x08425000 0x0 0x00001000>,
+ <0x00 0x08430000 0x0 0x00010000>,
+ <0xb0 0xb0000000 0x0 0x10000000>;
+ reg-names = "xal", "xtl", "xtl-pri", "xpl", "ecam";
+ #address-cells = <3>;
+ #size-cells = <2>;
+ device_type = "pci";
+ linux,pci-domain = <0x02>;
+ #interrupt-cells = <1>;
+ interrupt-map-mask = <0x0 0x0 0x0 0x7>;
+ interrupt-map = <0x0 0x0 0x0 0x1 &gic 0x0 0x0 0x0 917 IRQ_TYPE_LEVEL_HIGH>, /* INTA */
+ <0x0 0x0 0x0 0x2 &gic 0x0 0x0 0x0 918 IRQ_TYPE_LEVEL_HIGH>, /* INTB */
+ <0x0 0x0 0x0 0x3 &gic 0x0 0x0 0x0 919 IRQ_TYPE_LEVEL_HIGH>, /* INTC */
+ <0x0 0x0 0x0 0x4 &gic 0x0 0x0 0x0 920 IRQ_TYPE_LEVEL_HIGH>; /* INTD */
+
+ iommu-map = <0x0 &smmu1 0x20000 0x10000>;
+ msi-map = <0x0 &its 0x120000 0x10000>;
+ dma-coherent;
+
+ ranges = <0x81000000 0x00 0x84000000 0xb0 0x84000000 0x00 0x00200000>, /* I/O */
+ <0x82000000 0x00 0x30000000 0x00 0x30000000 0x00 0x08000000>, /* non-prefetchable memory */
+ <0xc3000000 0xb0 0xc0000000 0xb0 0xc0000000 0x07 0xc0000000>; /* prefetchable memory */
+ bus-range = <0x00 0xff>;
+
+ nvidia,bpmp = <&bpmp 2>;
+ status = "disabled";
+ };
+
+ pci@8440000 {
+ compatible = "nvidia,tegra264-pcie";
+ reg = <0x00 0x08440000 0x0 0x00004000>,
+ <0x00 0x08444000 0x0 0x00001000>,
+ <0x00 0x08445000 0x0 0x00001000>,
+ <0x00 0x08450000 0x0 0x00010000>,
+ <0xb8 0xb0000000 0x0 0x10000000>;
+ reg-names = "xal", "xtl", "xtl-pri", "xpl", "ecam";
+ #address-cells = <3>;
+ #size-cells = <2>;
+ device_type = "pci";
+ linux,pci-domain = <0x03>;
+ #interrupt-cells = <1>;
+ interrupt-map-mask = <0x0 0x0 0x0 0x7>;
+ interrupt-map = <0x0 0x0 0x0 0x1 &gic 0x0 0x0 0x0 926 IRQ_TYPE_LEVEL_HIGH>, /* INTA */
+ <0x0 0x0 0x0 0x2 &gic 0x0 0x0 0x0 927 IRQ_TYPE_LEVEL_HIGH>, /* INTB */
+ <0x0 0x0 0x0 0x3 &gic 0x0 0x0 0x0 928 IRQ_TYPE_LEVEL_HIGH>, /* INTC */
+ <0x0 0x0 0x0 0x4 &gic 0x0 0x0 0x0 929 IRQ_TYPE_LEVEL_HIGH>; /* INTD */
+
+ iommu-map = <0x0 &smmu1 0x30000 0x10000>;
+ msi-map = <0x0 &its 0x130000 0x10000>;
+ dma-coherent;
+
+ ranges = <0x81000000 0x00 0x84000000 0xb8 0x84000000 0x00 0x00200000>, /* I/O */
+ <0x82000000 0x00 0x38000000 0x00 0x38000000 0x00 0x08000000>, /* non-prefetchable memory */
+ <0xc3000000 0xb8 0xc0000000 0xb8 0xc0000000 0x07 0xc0000000>; /* prefetchable memory */
+ bus-range = <0x00 0xff>;
+
+ nvidia,bpmp = <&bpmp 3>;
+ status = "disabled";
+ };
+
+ pci@8460000 {
+ compatible = "nvidia,tegra264-pcie";
+ reg = <0x00 0x08460000 0x0 0x00004000>,
+ <0x00 0x08464000 0x0 0x00001000>,
+ <0x00 0x08465000 0x0 0x00001000>,
+ <0x00 0x08470000 0x0 0x00010000>,
+ <0xc0 0xb0000000 0x0 0x10000000>;
+ reg-names = "xal", "xtl", "xtl-pri", "xpl", "ecam";
+ #address-cells = <3>;
+ #size-cells = <2>;
+ device_type = "pci";
+ linux,pci-domain = <0x04>;
+ #interrupt-cells = <1>;
+ interrupt-map-mask = <0x0 0x0 0x0 0x7>;
+ interrupt-map = <0x0 0x0 0x0 0x1 &gic 0x0 0x0 0x0 935 IRQ_TYPE_LEVEL_HIGH>, /* INTA */
+ <0x0 0x0 0x0 0x2 &gic 0x0 0x0 0x0 936 IRQ_TYPE_LEVEL_HIGH>, /* INTB */
+ <0x0 0x0 0x0 0x3 &gic 0x0 0x0 0x0 937 IRQ_TYPE_LEVEL_HIGH>, /* INTC */
+ <0x0 0x0 0x0 0x4 &gic 0x0 0x0 0x0 938 IRQ_TYPE_LEVEL_HIGH>; /* INTD */
+
+ iommu-map = <0x0 &smmu1 0x40000 0x10000>;
+ msi-map = <0x0 &its 0x140000 0x10000>;
+ dma-coherent;
+
+ ranges = <0x81000000 0x00 0x84000000 0xc0 0x84000000 0x00 0x00200000>, /* I/O */
+ <0x82000000 0x00 0x40000000 0x00 0x40000000 0x00 0x08000000>, /* non-prefetchable memory */
+ <0xc3000000 0xc0 0xc0000000 0xc0 0xc0000000 0x07 0xc0000000>; /* prefetchable memory */
+ bus-range = <0x00 0xff>;
+
+ nvidia,bpmp = <&bpmp 4>;
+ status = "disabled";
+ };
+
+ pci@8480000 {
+ compatible = "nvidia,tegra264-pcie";
+ reg = <0x00 0x08480000 0x0 0x00004000>,
+ <0x00 0x08484000 0x0 0x00001000>,
+ <0x00 0x08485000 0x0 0x00001000>,
+ <0x00 0x08490000 0x0 0x00010000>,
+ <0xc8 0xb0000000 0x0 0x10000000>;
+ reg-names = "xal", "xtl", "xtl-pri", "xpl", "ecam";
+ #address-cells = <3>;
+ #size-cells = <2>;
+ device_type = "pci";
+ linux,pci-domain = <0x05>;
+ #interrupt-cells = <1>;
+ interrupt-map-mask = <0x0 0x0 0x0 0x7>;
+ interrupt-map = <0x0 0x0 0x0 0x1 &gic 0x0 0x0 0x0 944 IRQ_TYPE_LEVEL_HIGH>, /* INTA */
+ <0x0 0x0 0x0 0x2 &gic 0x0 0x0 0x0 945 IRQ_TYPE_LEVEL_HIGH>, /* INTB */
+ <0x0 0x0 0x0 0x3 &gic 0x0 0x0 0x0 946 IRQ_TYPE_LEVEL_HIGH>, /* INTC */
+ <0x0 0x0 0x0 0x4 &gic 0x0 0x0 0x0 947 IRQ_TYPE_LEVEL_HIGH>; /* INTD */
+
+ iommu-map = <0x0 &smmu1 0x50000 0x10000>;
+ msi-map = <0x0 &its 0x150000 0x10000>;
+ dma-coherent;
+
+ ranges = <0x81000000 0x00 0x84000000 0xc8 0x84000000 0x00 0x00200000>, /* I/O */
+ <0x82000000 0x00 0x48000000 0x00 0x48000000 0x00 0x08000000>, /* non-prefetchable memory */
+ <0xc3000000 0xc8 0xc0000000 0xc8 0xc0000000 0x07 0xc0000000>; /* prefetchable memory */
+ bus-range = <0x00 0xff>;
+
+ nvidia,bpmp = <&bpmp 5>;
+ status = "disabled";
+ };
};
cpus {
--
2.52.0
^ permalink raw reply related
* [PATCH v4 3/4] PCI: tegra: Add Tegra264 support
From: Thierry Reding @ 2026-04-02 14:27 UTC (permalink / raw)
To: Bjorn Helgaas, Lorenzo Pieralisi, Krzysztof Wilczyński,
Manivannan Sadhasivam, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Thierry Reding, Jonathan Hunter, Karthikeyan Mitran,
Hou Zhiqiang, Thomas Petazzoni, Pali Rohár, Michal Simek,
Kevin Xie
Cc: linux-pci, devicetree, linux-tegra, linux-kernel,
linux-arm-kernel, Thierry Reding, Manikanta Maddireddy
In-Reply-To: <20260402-tegra264-pcie-v4-0-21e2e19987e8@nvidia.com>
From: Thierry Reding <treding@nvidia.com>
Add a driver for the PCIe controller found on NVIDIA Tegra264 SoCs. The
driver is very small, with its main purpose being to set up the address
translation registers and then creating a standard PCI host using ECAM.
Signed-off-by: Manikanta Maddireddy <mmaddireddy@nvidia.com>
Signed-off-by: Thierry Reding <treding@nvidia.com>
---
Changes in v2:
- specify generations applicable for PCI_TEGRA driver to avoid confusion
- drop SPDX-FileCopyrightText tag
- rename link_state to link_up to clarify meaning
- replace memset() by an empty initializer
- sanity-check only enable BAR regions
- bring PCI link out of reset in case firmware didn't
- use common wait times instead of defining our own
- use core helpers to parse and print PCI link speed
- fix multi-line comment
- use dev_err_probe() more ubiquitously
- fix probe sequence and error cleanup
- use DEFINE_NOIRQ_DEV_PM_OPS() to avoid warnings for !PM_SUSPEND
- reuse more standard registers and remove unused register definitions
- use %pe and ERR_PTR() to print symbolic errors
- add signed-off-by from Manikanta as the original author
- add myself as author after significantly modifying the driver
---
drivers/pci/controller/Kconfig | 10 +-
drivers/pci/controller/Makefile | 1 +
drivers/pci/controller/pcie-tegra264.c | 527 +++++++++++++++++++++++++++++++++
3 files changed, 537 insertions(+), 1 deletion(-)
diff --git a/drivers/pci/controller/Kconfig b/drivers/pci/controller/Kconfig
index 5aaed8ac6e44..6ead04f7bd6e 100644
--- a/drivers/pci/controller/Kconfig
+++ b/drivers/pci/controller/Kconfig
@@ -254,7 +254,15 @@ config PCI_TEGRA
select IRQ_MSI_LIB
help
Say Y here if you want support for the PCIe host controller found
- on NVIDIA Tegra SoCs.
+ on NVIDIA Tegra SoCs (Tegra20 through Tegra186).
+
+config PCIE_TEGRA264
+ bool "NVIDIA Tegra264 PCIe controller"
+ depends on ARCH_TEGRA || COMPILE_TEST
+ depends on PCI_MSI
+ help
+ Say Y here if you want support for the PCIe host controller found
+ on NVIDIA Tegra264 SoCs.
config PCIE_RCAR_HOST
bool "Renesas R-Car PCIe controller (host mode)"
diff --git a/drivers/pci/controller/Makefile b/drivers/pci/controller/Makefile
index ac8db283f0fe..d478743b5142 100644
--- a/drivers/pci/controller/Makefile
+++ b/drivers/pci/controller/Makefile
@@ -7,6 +7,7 @@ obj-$(CONFIG_PCI_HYPERV_INTERFACE) += pci-hyperv-intf.o
obj-$(CONFIG_PCI_MVEBU) += pci-mvebu.o
obj-$(CONFIG_PCI_AARDVARK) += pci-aardvark.o
obj-$(CONFIG_PCI_TEGRA) += pci-tegra.o
+obj-$(CONFIG_PCIE_TEGRA264) += pcie-tegra264.o
obj-$(CONFIG_PCI_RCAR_GEN2) += pci-rcar-gen2.o
obj-$(CONFIG_PCIE_RCAR_HOST) += pcie-rcar.o pcie-rcar-host.o
obj-$(CONFIG_PCIE_RCAR_EP) += pcie-rcar.o pcie-rcar-ep.o
diff --git a/drivers/pci/controller/pcie-tegra264.c b/drivers/pci/controller/pcie-tegra264.c
new file mode 100644
index 000000000000..3ce1ad971bdb
--- /dev/null
+++ b/drivers/pci/controller/pcie-tegra264.c
@@ -0,0 +1,527 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * PCIe host controller driver for Tegra264 SoC
+ *
+ * Copyright (c) 2022-2026, NVIDIA CORPORATION. All rights reserved.
+ */
+
+#include <linux/delay.h>
+#include <linux/gpio/consumer.h>
+#include <linux/init.h>
+#include <linux/interconnect.h>
+#include <linux/interrupt.h>
+#include <linux/iopoll.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/of.h>
+#include <linux/of_pci.h>
+#include <linux/of_platform.h>
+#include <linux/pci-ecam.h>
+#include <linux/pci.h>
+#include <linux/pinctrl/consumer.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+
+#include <soc/tegra/bpmp.h>
+#include <soc/tegra/bpmp-abi.h>
+#include <soc/tegra/fuse.h>
+
+#include "../pci.h"
+
+/* XAL registers */
+#define XAL_RC_ECAM_BASE_HI 0x00
+#define XAL_RC_ECAM_BASE_LO 0x04
+#define XAL_RC_ECAM_BUSMASK 0x08
+#define XAL_RC_IO_BASE_HI 0x0c
+#define XAL_RC_IO_BASE_LO 0x10
+#define XAL_RC_IO_LIMIT_HI 0x14
+#define XAL_RC_IO_LIMIT_LO 0x18
+#define XAL_RC_MEM_32BIT_BASE_HI 0x1c
+#define XAL_RC_MEM_32BIT_BASE_LO 0x20
+#define XAL_RC_MEM_32BIT_LIMIT_HI 0x24
+#define XAL_RC_MEM_32BIT_LIMIT_LO 0x28
+#define XAL_RC_MEM_64BIT_BASE_HI 0x2c
+#define XAL_RC_MEM_64BIT_BASE_LO 0x30
+#define XAL_RC_MEM_64BIT_LIMIT_HI 0x34
+#define XAL_RC_MEM_64BIT_LIMIT_LO 0x38
+#define XAL_RC_BAR_CNTL_STANDARD 0x40
+#define XAL_RC_BAR_CNTL_STANDARD_IOBAR_EN BIT(0)
+#define XAL_RC_BAR_CNTL_STANDARD_32B_BAR_EN BIT(1)
+#define XAL_RC_BAR_CNTL_STANDARD_64B_BAR_EN BIT(2)
+
+/* XTL registers */
+#define XTL_RC_PCIE_CFG_LINK_STATUS 0x5a
+
+#define XTL_RC_MGMT_PERST_CONTROL 0x218
+#define XTL_RC_MGMT_PERST_CONTROL_PERST_O_N BIT(0)
+
+#define XTL_RC_MGMT_CLOCK_CONTROL 0x47c
+#define XTL_RC_MGMT_CLOCK_CONTROL_PEX_CLKREQ_I_N_PIN_USE_CONV_TO_PRSNT BIT(9)
+
+struct tegra264_pcie {
+ struct device *dev;
+ bool link_up;
+
+ /* I/O memory */
+ void __iomem *xal;
+ void __iomem *xtl;
+ void __iomem *ecam;
+
+ /* bridge configuration */
+ struct pci_config_window *cfg;
+ struct pci_host_bridge *bridge;
+
+ /* wake IRQ */
+ struct gpio_desc *wake_gpio;
+ unsigned int wake_irq;
+
+ /* BPMP and bandwidth management */
+ struct icc_path *icc_path;
+ struct tegra_bpmp *bpmp;
+ u32 ctl_id;
+};
+
+static int tegra264_pcie_parse_dt(struct tegra264_pcie *pcie)
+{
+ int err;
+
+ pcie->wake_gpio = devm_gpiod_get_optional(pcie->dev, "nvidia,pex-wake",
+ GPIOD_IN);
+ if (IS_ERR(pcie->wake_gpio))
+ return PTR_ERR(pcie->wake_gpio);
+
+ if (pcie->wake_gpio) {
+ device_init_wakeup(pcie->dev, true);
+
+ err = gpiod_to_irq(pcie->wake_gpio);
+ if (err < 0) {
+ dev_err(pcie->dev, "failed to get wake IRQ: %pe\n",
+ ERR_PTR(err));
+ return err;
+ }
+
+ pcie->wake_irq = (unsigned int)err;
+ }
+
+ return 0;
+}
+
+static void tegra264_pcie_bpmp_set_rp_state(struct tegra264_pcie *pcie)
+{
+ struct tegra_bpmp_message msg = {};
+ struct mrq_pcie_request req = {};
+ int err;
+
+ req.cmd = CMD_PCIE_RP_CONTROLLER_OFF;
+ req.rp_ctrlr_off.rp_controller = pcie->ctl_id;
+
+ msg.mrq = MRQ_PCIE;
+ msg.tx.data = &req;
+ msg.tx.size = sizeof(req);
+
+ err = tegra_bpmp_transfer(pcie->bpmp, &msg);
+ if (err)
+ dev_info(pcie->dev, "failed to turn off PCIe #%u: %pe\n",
+ pcie->ctl_id, ERR_PTR(err));
+
+ if (msg.rx.ret)
+ dev_info(pcie->dev, "failed to turn off PCIe #%u: %d\n",
+ pcie->ctl_id, msg.rx.ret);
+}
+
+static void tegra264_pcie_icc_set(struct tegra264_pcie *pcie)
+{
+ u32 value, speed, width, bw;
+ int err;
+
+ value = readw(pcie->ecam + XTL_RC_PCIE_CFG_LINK_STATUS);
+ speed = FIELD_GET(PCI_EXP_LNKSTA_CLS, value);
+ width = FIELD_GET(PCI_EXP_LNKSTA_NLW, value);
+
+ bw = width * (PCIE_SPEED2MBS_ENC(speed) / BITS_PER_BYTE);
+ value = MBps_to_icc(bw);
+
+ err = icc_set_bw(pcie->icc_path, bw, bw);
+ if (err < 0)
+ dev_err(pcie->dev,
+ "failed to request bandwidth (%u MBps): %pe\n",
+ bw, ERR_PTR(err));
+}
+
+/*
+ * The various memory regions used by the controller (I/O, memory, ECAM) are
+ * set up during early boot and have hardware-level protections in place. If
+ * the DT ranges don't match what's been setup, the controller won't be able
+ * to write the address endpoints properly, so make sure to validate that DT
+ * and firmware programming agree on these ranges.
+ */
+static bool tegra264_pcie_check_ranges(struct platform_device *pdev)
+{
+ struct tegra264_pcie *pcie = platform_get_drvdata(pdev);
+ struct device_node *np = pcie->dev->of_node;
+ struct of_pci_range_parser parser;
+ phys_addr_t phys, limit, hi, lo;
+ struct of_pci_range range;
+ struct resource *res;
+ bool status = true;
+ u32 value;
+ int err;
+
+ err = of_pci_range_parser_init(&parser, np);
+ if (err < 0)
+ return false;
+
+ for_each_of_pci_range(&parser, &range) {
+ unsigned int addr_hi, addr_lo, limit_hi, limit_lo, enable;
+ unsigned long type = range.flags & IORESOURCE_TYPE_BITS;
+ phys_addr_t start, end, mask;
+ const char *region = NULL;
+
+ end = range.cpu_addr + range.size - 1;
+ start = range.cpu_addr;
+
+ switch (type) {
+ case IORESOURCE_IO:
+ addr_hi = XAL_RC_IO_BASE_HI;
+ addr_lo = XAL_RC_IO_BASE_LO;
+ limit_hi = XAL_RC_IO_LIMIT_HI;
+ limit_lo = XAL_RC_IO_LIMIT_LO;
+ enable = XAL_RC_BAR_CNTL_STANDARD_IOBAR_EN;
+ mask = SZ_64K - 1;
+ region = "I/O";
+ break;
+
+ case IORESOURCE_MEM:
+ if (range.flags & IORESOURCE_PREFETCH) {
+ addr_hi = XAL_RC_MEM_64BIT_BASE_HI;
+ addr_lo = XAL_RC_MEM_64BIT_BASE_LO;
+ limit_hi = XAL_RC_MEM_64BIT_LIMIT_HI;
+ limit_lo = XAL_RC_MEM_64BIT_LIMIT_LO;
+ enable = XAL_RC_BAR_CNTL_STANDARD_64B_BAR_EN;
+ region = "prefetchable memory";
+ } else {
+ addr_hi = XAL_RC_MEM_32BIT_BASE_HI;
+ addr_lo = XAL_RC_MEM_32BIT_BASE_LO;
+ limit_hi = XAL_RC_MEM_32BIT_LIMIT_HI;
+ limit_lo = XAL_RC_MEM_32BIT_LIMIT_LO;
+ enable = XAL_RC_BAR_CNTL_STANDARD_32B_BAR_EN;
+ region = "memory";
+ }
+
+ mask = SZ_1M - 1;
+ break;
+ }
+
+ /* not interested in anything that's not I/O or memory */
+ if (!region)
+ continue;
+
+ /* don't check regions that haven't been enabled */
+ value = readl(pcie->xal + XAL_RC_BAR_CNTL_STANDARD);
+ if ((value & enable) == 0)
+ continue;
+
+ hi = readl(pcie->xal + addr_hi);
+ lo = readl(pcie->xal + addr_lo);
+ phys = hi << 32 | lo;
+
+ hi = readl(pcie->xal + limit_hi);
+ lo = readl(pcie->xal + limit_lo);
+ limit = hi << 32 | lo | mask;
+
+ if (phys != start || limit != end) {
+ dev_err(pcie->dev,
+ "%s region mismatch: %pap-%pap -> %pap-%pap\n",
+ region, &phys, &limit, &start, &end);
+ status = false;
+ }
+ }
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ecam");
+ if (!res)
+ return false;
+
+ hi = readl(pcie->xal + XAL_RC_ECAM_BASE_HI);
+ lo = readl(pcie->xal + XAL_RC_ECAM_BASE_LO);
+ phys = hi << 32 | lo;
+
+ value = readl(pcie->xal + XAL_RC_ECAM_BUSMASK);
+ limit = phys + ((value + 1) << 20) - 1;
+
+ if (phys != res->start || limit != res->end) {
+ dev_err(pcie->dev,
+ "ECAM region mismatch: %pap-%pap -> %pap-%pap\n",
+ &phys, &limit, &res->start, &res->end);
+ status = false;
+ }
+
+ return status;
+}
+
+static bool tegra264_pcie_link_up(struct tegra264_pcie *pcie,
+ enum pci_bus_speed *speed)
+{
+ u16 value = readw(pcie->ecam + XTL_RC_PCIE_CFG_LINK_STATUS);
+
+ if (value & PCI_EXP_LNKSTA_DLLLA) {
+ if (speed)
+ *speed = pcie_link_speed[FIELD_GET(PCI_EXP_LNKSTA_CLS,
+ value)];
+
+ return true;
+ }
+
+ return false;
+}
+
+static void tegra264_pcie_init(struct tegra264_pcie *pcie)
+{
+ enum pci_bus_speed speed;
+ unsigned int i;
+ u32 value;
+
+ /* bring the link out of reset */
+ value = readl(pcie->xtl + XTL_RC_MGMT_PERST_CONTROL);
+ value |= XTL_RC_MGMT_PERST_CONTROL_PERST_O_N;
+ writel(value, pcie->xtl + XTL_RC_MGMT_PERST_CONTROL);
+
+ if (!tegra_is_silicon()) {
+ dev_info(pcie->dev,
+ "skipping link state for PCIe #%u in simulation\n",
+ pcie->ctl_id);
+ pcie->link_up = true;
+ return;
+ }
+
+ for (i = 0; i < PCIE_LINK_WAIT_MAX_RETRIES; i++) {
+ if (tegra264_pcie_link_up(pcie, NULL))
+ break;
+
+ usleep_range(PCIE_LINK_WAIT_US_MIN, PCIE_LINK_WAIT_US_MAX);
+ }
+
+ if (tegra264_pcie_link_up(pcie, &speed)) {
+ /* Per PCIe r5.0, 6.6.1 wait for 100ms after DLL up */
+ msleep(PCIE_RESET_CONFIG_WAIT_MS);
+
+ dev_info(pcie->dev, "PCIe #%u link is up (speed: %s)\n",
+ pcie->ctl_id, pci_speed_string(speed));
+ tegra264_pcie_icc_set(pcie);
+ pcie->link_up = true;
+ } else {
+ dev_info(pcie->dev, "PCIe #%u link is down\n", pcie->ctl_id);
+
+ value = readl(pcie->xtl + XTL_RC_MGMT_CLOCK_CONTROL);
+
+ /*
+ * Set link state only when link fails and no hot-plug feature
+ * is present.
+ */
+ if ((value & XTL_RC_MGMT_CLOCK_CONTROL_PEX_CLKREQ_I_N_PIN_USE_CONV_TO_PRSNT) == 0) {
+ dev_info(pcie->dev,
+ "PCIe #%u link is down and not hotplug-capable, turning off\n",
+ pcie->ctl_id);
+ tegra264_pcie_bpmp_set_rp_state(pcie);
+ pcie->link_up = false;
+ } else {
+ pcie->link_up = true;
+ }
+ }
+}
+
+static int tegra264_pcie_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct pci_host_bridge *bridge;
+ struct tegra264_pcie *pcie;
+ struct resource_entry *bus;
+ struct resource *res;
+ int err;
+
+ bridge = devm_pci_alloc_host_bridge(dev, sizeof(struct tegra264_pcie));
+ if (!bridge)
+ return dev_err_probe(dev, -ENOMEM,
+ "failed to allocate host bridge\n");
+
+ pcie = pci_host_bridge_priv(bridge);
+ platform_set_drvdata(pdev, pcie);
+ pcie->bridge = bridge;
+ pcie->dev = dev;
+
+ err = pinctrl_pm_select_default_state(dev);
+ if (err < 0)
+ return dev_err_probe(dev, err,
+ "failed to configure sideband pins\n");
+
+ err = tegra264_pcie_parse_dt(pcie);
+ if (err < 0)
+ return dev_err_probe(dev, err, "failed to parse device tree");
+
+ pcie->xal = devm_platform_ioremap_resource_byname(pdev, "xal");
+ if (IS_ERR(pcie->xal))
+ return dev_err_probe(dev, PTR_ERR(pcie->xal),
+ "failed to map XAL memory\n");
+
+ pcie->xtl = devm_platform_ioremap_resource_byname(pdev, "xtl-pri");
+ if (IS_ERR(pcie->xtl))
+ return dev_err_probe(dev, PTR_ERR(pcie->xtl),
+ "failed to map XTL-PRI memory\n");
+
+ bus = resource_list_first_type(&bridge->windows, IORESOURCE_BUS);
+ if (!bus)
+ return dev_err_probe(dev, -ENODEV,
+ "failed to get bus resources\n");
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ecam");
+ if (!res)
+ return dev_err_probe(dev, -ENXIO,
+ "failed to get ECAM resource\n");
+
+ pcie->icc_path = devm_of_icc_get(&pdev->dev, "write");
+ if (IS_ERR(pcie->icc_path))
+ return dev_err_probe(&pdev->dev, PTR_ERR(pcie->icc_path),
+ "failed to get ICC");
+
+ /*
+ * Parse BPMP property only for silicon, as interaction with BPMP is
+ * not needed for other platforms.
+ */
+ if (tegra_is_silicon()) {
+ pcie->bpmp = tegra_bpmp_get_with_id(dev, &pcie->ctl_id);
+ if (IS_ERR(pcie->bpmp))
+ return dev_err_probe(dev, PTR_ERR(pcie->bpmp),
+ "failed to get BPMP\n");
+ }
+
+ pm_runtime_enable(dev);
+ pm_runtime_get_sync(dev);
+
+ /* sanity check that programmed ranges match what's in DT */
+ if (!tegra264_pcie_check_ranges(pdev)) {
+ err = -EINVAL;
+ goto put_pm;
+ }
+
+ pcie->cfg = pci_ecam_create(dev, res, bus->res, &pci_generic_ecam_ops);
+ if (IS_ERR(pcie->cfg)) {
+ err = dev_err_probe(dev, PTR_ERR(pcie->cfg),
+ "failed to create ECAM\n");
+ goto put_pm;
+ }
+
+ bridge->ops = (struct pci_ops *)&pci_generic_ecam_ops.pci_ops;
+ bridge->sysdata = pcie->cfg;
+ pcie->ecam = pcie->cfg->win;
+
+ tegra264_pcie_init(pcie);
+
+ if (!pcie->link_up)
+ goto free;
+
+ err = pci_host_probe(bridge);
+ if (err < 0) {
+ dev_err(dev, "failed to register host: %pe\n", ERR_PTR(err));
+ goto free;
+ }
+
+ return err;
+
+free:
+ pci_ecam_free(pcie->cfg);
+put_pm:
+ pm_runtime_put_sync(dev);
+ pm_runtime_disable(dev);
+
+ if (tegra_is_silicon())
+ tegra_bpmp_put(pcie->bpmp);
+
+ return err;
+}
+
+static void tegra264_pcie_remove(struct platform_device *pdev)
+{
+ struct tegra264_pcie *pcie = platform_get_drvdata(pdev);
+
+ /*
+ * If we undo tegra264_pcie_init() then link goes down and need
+ * controller reset to bring up the link again. Remove intention is
+ * to clean up the root bridge and re-enumerate during bind.
+ */
+ pci_lock_rescan_remove();
+ pci_stop_root_bus(pcie->bridge->bus);
+ pci_remove_root_bus(pcie->bridge->bus);
+ pci_unlock_rescan_remove();
+
+ pm_runtime_put_sync(&pdev->dev);
+ pm_runtime_disable(&pdev->dev);
+
+ if (tegra_is_silicon())
+ tegra_bpmp_put(pcie->bpmp);
+
+ pci_ecam_free(pcie->cfg);
+}
+
+static int tegra264_pcie_suspend_noirq(struct device *dev)
+{
+ struct tegra264_pcie *pcie = dev_get_drvdata(dev);
+ int err;
+
+ if (pcie->wake_gpio && device_may_wakeup(dev)) {
+ err = enable_irq_wake(pcie->wake_irq);
+ if (err < 0)
+ dev_err(dev, "failed to enable wake IRQ: %pe\n",
+ ERR_PTR(err));
+ }
+
+ return 0;
+}
+
+static int tegra264_pcie_resume_noirq(struct device *dev)
+{
+ struct tegra264_pcie *pcie = dev_get_drvdata(dev);
+ int err;
+
+ if (pcie->wake_gpio && device_may_wakeup(dev)) {
+ err = disable_irq_wake(pcie->wake_irq);
+ if (err < 0)
+ dev_err(dev, "failed to disable wake IRQ: %pe\n",
+ ERR_PTR(err));
+ }
+
+ if (pcie->link_up == false)
+ return 0;
+
+ tegra264_pcie_init(pcie);
+
+ return 0;
+}
+
+static DEFINE_NOIRQ_DEV_PM_OPS(tegra264_pcie_pm_ops,
+ tegra264_pcie_suspend_noirq,
+ tegra264_pcie_resume_noirq);
+
+static const struct of_device_id tegra264_pcie_of_match[] = {
+ {
+ .compatible = "nvidia,tegra264-pcie",
+ },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, tegra264_pcie_of_match);
+
+static struct platform_driver tegra264_pcie_driver = {
+ .probe = tegra264_pcie_probe,
+ .remove = tegra264_pcie_remove,
+ .driver = {
+ .name = "tegra264-pcie",
+ .pm = &tegra264_pcie_pm_ops,
+ .of_match_table = tegra264_pcie_of_match,
+ },
+};
+module_platform_driver(tegra264_pcie_driver);
+
+MODULE_AUTHOR("Manikanta Maddireddy <mmaddireddy@nvidia.com>");
+MODULE_AUTHOR("Thierry Reding <treding@nvidia.com>");
+MODULE_DESCRIPTION("NVIDIA Tegra264 PCIe host controller driver");
+MODULE_LICENSE("GPL");
--
2.52.0
^ permalink raw reply related
* [PATCH v4 2/4] PCI: Use standard wait times for PCIe link monitoring
From: Thierry Reding @ 2026-04-02 14:27 UTC (permalink / raw)
To: Bjorn Helgaas, Lorenzo Pieralisi, Krzysztof Wilczyński,
Manivannan Sadhasivam, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Thierry Reding, Jonathan Hunter, Karthikeyan Mitran,
Hou Zhiqiang, Thomas Petazzoni, Pali Rohár, Michal Simek,
Kevin Xie
Cc: linux-pci, devicetree, linux-tegra, linux-kernel,
linux-arm-kernel, Thierry Reding
In-Reply-To: <20260402-tegra264-pcie-v4-0-21e2e19987e8@nvidia.com>
From: Thierry Reding <treding@nvidia.com>
Instead of defining the wait values for each driver, use common values
defined in the core pci.h header file. Note that most drivers don't use
the millisecond waits, but rather usleep_range(), so add these commonly
used values to the header so that all drivers can use them.
Signed-off-by: Thierry Reding <treding@nvidia.com>
---
Changes in v2:
- fix build for Cadence
---
drivers/pci/controller/cadence/pcie-cadence-host-common.c | 6 ++++--
drivers/pci/controller/cadence/pcie-cadence-lga-regs.h | 5 -----
drivers/pci/controller/mobiveil/pcie-mobiveil.c | 4 ++--
drivers/pci/controller/mobiveil/pcie-mobiveil.h | 5 -----
drivers/pci/controller/pci-aardvark.c | 7 ++-----
drivers/pci/controller/pcie-xilinx-nwl.c | 9 ++-------
drivers/pci/controller/plda/pcie-starfive.c | 9 ++-------
drivers/pci/pci.h | 2 ++
8 files changed, 14 insertions(+), 33 deletions(-)
diff --git a/drivers/pci/controller/cadence/pcie-cadence-host-common.c b/drivers/pci/controller/cadence/pcie-cadence-host-common.c
index 2b0211870f02..72b36c70f389 100644
--- a/drivers/pci/controller/cadence/pcie-cadence-host-common.c
+++ b/drivers/pci/controller/cadence/pcie-cadence-host-common.c
@@ -15,6 +15,8 @@
#include "pcie-cadence.h"
#include "pcie-cadence-host-common.h"
+#include "../../pci.h"
+
#define LINK_RETRAIN_TIMEOUT HZ
u64 bar_max_size[] = {
@@ -53,12 +55,12 @@ int cdns_pcie_host_wait_for_link(struct cdns_pcie *pcie,
int retries;
/* Check if the link is up or not */
- for (retries = 0; retries < LINK_WAIT_MAX_RETRIES; retries++) {
+ for (retries = 0; retries < PCIE_LINK_WAIT_MAX_RETRIES; retries++) {
if (pcie_link_up(pcie)) {
dev_info(dev, "Link up\n");
return 0;
}
- usleep_range(LINK_WAIT_USLEEP_MIN, LINK_WAIT_USLEEP_MAX);
+ usleep_range(PCIE_LINK_WAIT_US_MIN, PCIE_LINK_WAIT_US_MAX);
}
return -ETIMEDOUT;
diff --git a/drivers/pci/controller/cadence/pcie-cadence-lga-regs.h b/drivers/pci/controller/cadence/pcie-cadence-lga-regs.h
index 857b2140c5d2..15dc4fcaf45d 100644
--- a/drivers/pci/controller/cadence/pcie-cadence-lga-regs.h
+++ b/drivers/pci/controller/cadence/pcie-cadence-lga-regs.h
@@ -10,11 +10,6 @@
#include <linux/bitfield.h>
-/* Parameters for the waiting for link up routine */
-#define LINK_WAIT_MAX_RETRIES 10
-#define LINK_WAIT_USLEEP_MIN 90000
-#define LINK_WAIT_USLEEP_MAX 100000
-
/* Local Management Registers */
#define CDNS_PCIE_LM_BASE 0x00100000
diff --git a/drivers/pci/controller/mobiveil/pcie-mobiveil.c b/drivers/pci/controller/mobiveil/pcie-mobiveil.c
index 62ecbaeb0a60..cc102032c1e6 100644
--- a/drivers/pci/controller/mobiveil/pcie-mobiveil.c
+++ b/drivers/pci/controller/mobiveil/pcie-mobiveil.c
@@ -218,11 +218,11 @@ int mobiveil_bringup_link(struct mobiveil_pcie *pcie)
int retries;
/* check if the link is up or not */
- for (retries = 0; retries < LINK_WAIT_MAX_RETRIES; retries++) {
+ for (retries = 0; retries < PCIE_LINK_WAIT_MAX_RETRIES; retries++) {
if (mobiveil_pcie_link_up(pcie))
return 0;
- usleep_range(LINK_WAIT_MIN, LINK_WAIT_MAX);
+ usleep_range(PCIE_LINK_WAIT_US_MIN, PCIE_LINK_WAIT_US_MAX);
}
dev_err(&pcie->pdev->dev, "link never came up\n");
diff --git a/drivers/pci/controller/mobiveil/pcie-mobiveil.h b/drivers/pci/controller/mobiveil/pcie-mobiveil.h
index 7246de6a7176..11010a99e27c 100644
--- a/drivers/pci/controller/mobiveil/pcie-mobiveil.h
+++ b/drivers/pci/controller/mobiveil/pcie-mobiveil.h
@@ -122,11 +122,6 @@
#define IB_WIN_SIZE ((u64)256 * 1024 * 1024 * 1024)
#define MAX_PIO_WINDOWS 8
-/* Parameters for the waiting for link up routine */
-#define LINK_WAIT_MAX_RETRIES 10
-#define LINK_WAIT_MIN 90000
-#define LINK_WAIT_MAX 100000
-
#define PAGED_ADDR_BNDRY 0xc00
#define OFFSET_TO_PAGE_ADDR(off) \
((off & PAGE_LO_MASK) | PAGED_ADDR_BNDRY)
diff --git a/drivers/pci/controller/pci-aardvark.c b/drivers/pci/controller/pci-aardvark.c
index e34bea1ff0ac..506323a6c72b 100644
--- a/drivers/pci/controller/pci-aardvark.c
+++ b/drivers/pci/controller/pci-aardvark.c
@@ -255,9 +255,6 @@ enum {
#define PIO_RETRY_CNT 750000 /* 1.5 s */
#define PIO_RETRY_DELAY 2 /* 2 us*/
-#define LINK_WAIT_MAX_RETRIES 10
-#define LINK_WAIT_USLEEP_MIN 90000
-#define LINK_WAIT_USLEEP_MAX 100000
#define RETRAIN_WAIT_MAX_RETRIES 10
#define RETRAIN_WAIT_USLEEP_US 2000
@@ -349,11 +346,11 @@ static int advk_pcie_wait_for_link(struct advk_pcie *pcie)
int retries;
/* check if the link is up or not */
- for (retries = 0; retries < LINK_WAIT_MAX_RETRIES; retries++) {
+ for (retries = 0; retries < PCIE_LINK_WAIT_MAX_RETRIES; retries++) {
if (advk_pcie_link_up(pcie))
return 0;
- usleep_range(LINK_WAIT_USLEEP_MIN, LINK_WAIT_USLEEP_MAX);
+ usleep_range(PCIE_LINK_WAIT_US_MIN, PCIE_LINK_WAIT_US_MAX);
}
return -ETIMEDOUT;
diff --git a/drivers/pci/controller/pcie-xilinx-nwl.c b/drivers/pci/controller/pcie-xilinx-nwl.c
index 7db2c96c6cec..fc65e9fdddb3 100644
--- a/drivers/pci/controller/pcie-xilinx-nwl.c
+++ b/drivers/pci/controller/pcie-xilinx-nwl.c
@@ -140,11 +140,6 @@
#define PCIE_PHY_LINKUP_BIT BIT(0)
#define PHY_RDY_LINKUP_BIT BIT(1)
-/* Parameters for the waiting for link up routine */
-#define LINK_WAIT_MAX_RETRIES 10
-#define LINK_WAIT_USLEEP_MIN 90000
-#define LINK_WAIT_USLEEP_MAX 100000
-
struct nwl_msi { /* MSI information */
DECLARE_BITMAP(bitmap, INT_PCI_MSI_NR);
struct irq_domain *dev_domain;
@@ -203,10 +198,10 @@ static int nwl_wait_for_link(struct nwl_pcie *pcie)
int retries;
/* check if the link is up or not */
- for (retries = 0; retries < LINK_WAIT_MAX_RETRIES; retries++) {
+ for (retries = 0; retries < PCIE_LINK_WAIT_MAX_RETRIES; retries++) {
if (nwl_phy_link_up(pcie))
return 0;
- usleep_range(LINK_WAIT_USLEEP_MIN, LINK_WAIT_USLEEP_MAX);
+ usleep_range(PCIE_LINK_WAIT_US_MIN, PCIE_LINK_WAIT_US_MAX);
}
dev_err(dev, "PHY link never came up\n");
diff --git a/drivers/pci/controller/plda/pcie-starfive.c b/drivers/pci/controller/plda/pcie-starfive.c
index 298036c3e7f9..542a751b6f4d 100644
--- a/drivers/pci/controller/plda/pcie-starfive.c
+++ b/drivers/pci/controller/plda/pcie-starfive.c
@@ -45,11 +45,6 @@
#define STG_SYSCON_LNKSTA_OFFSET 0x170
#define DATA_LINK_ACTIVE BIT(5)
-/* Parameters for the waiting for link up routine */
-#define LINK_WAIT_MAX_RETRIES 10
-#define LINK_WAIT_USLEEP_MIN 90000
-#define LINK_WAIT_USLEEP_MAX 100000
-
struct starfive_jh7110_pcie {
struct plda_pcie_rp plda;
struct reset_control *resets;
@@ -217,12 +212,12 @@ static int starfive_pcie_host_wait_for_link(struct starfive_jh7110_pcie *pcie)
int retries;
/* Check if the link is up or not */
- for (retries = 0; retries < LINK_WAIT_MAX_RETRIES; retries++) {
+ for (retries = 0; retries < PCIE_LINK_WAIT_MAX_RETRIES; retries++) {
if (starfive_pcie_link_up(&pcie->plda)) {
dev_info(pcie->plda.dev, "port link up\n");
return 0;
}
- usleep_range(LINK_WAIT_USLEEP_MIN, LINK_WAIT_USLEEP_MAX);
+ usleep_range(PCIE_LINK_WAIT_US_MIN, PCIE_LINK_WAIT_US_MAX);
}
return -ETIMEDOUT;
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
index 13d998fbacce..f47ed96d8ef2 100644
--- a/drivers/pci/pci.h
+++ b/drivers/pci/pci.h
@@ -63,6 +63,8 @@ struct pcie_tlp_log;
/* Parameters for the waiting for link up routine */
#define PCIE_LINK_WAIT_MAX_RETRIES 10
#define PCIE_LINK_WAIT_SLEEP_MS 90
+#define PCIE_LINK_WAIT_US_MIN 90000
+#define PCIE_LINK_WAIT_US_MAX 100000
/* Format of TLP; PCIe r7.0, sec 2.2.1 */
#define PCIE_TLP_FMT_3DW_NO_DATA 0x00 /* 3DW header, no data */
--
2.52.0
^ permalink raw reply related
* [PATCH v4 1/4] dt-bindings: pci: Document the NVIDIA Tegra264 PCIe controller
From: Thierry Reding @ 2026-04-02 14:27 UTC (permalink / raw)
To: Bjorn Helgaas, Lorenzo Pieralisi, Krzysztof Wilczyński,
Manivannan Sadhasivam, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Thierry Reding, Jonathan Hunter, Karthikeyan Mitran,
Hou Zhiqiang, Thomas Petazzoni, Pali Rohár, Michal Simek,
Kevin Xie
Cc: linux-pci, devicetree, linux-tegra, linux-kernel,
linux-arm-kernel, Thierry Reding
In-Reply-To: <20260402-tegra264-pcie-v4-0-21e2e19987e8@nvidia.com>
From: Thierry Reding <treding@nvidia.com>
The six PCIe controllers found on Tegra264 are of two types: one is used
for the internal GPU and therefore is not connected to a UPHY and the
remaining five controllers are typically routed to a PCI slot and have
additional controls for the physical link.
While these controllers can be switched into endpoint mode, this binding
describes the root complex mode only.
Signed-off-by: Thierry Reding <treding@nvidia.com>
---
Changes in v4:
- ECAM is outside of the controller's region, so it cannot be the first
reg entry, otherwise we get warnings because it doesn't match the
unit-address, so revert back to oneOf construct
Changes in v2:
- move ECAM region first and unify C0 vs. C1-C5
- move unevaluatedProperties to right before the examples
- add description to clarify the two types of controllers
- add examples for C0 and C1-C5
---
.../bindings/pci/nvidia,tegra264-pcie.yaml | 174 +++++++++++++++++++++
1 file changed, 174 insertions(+)
diff --git a/Documentation/devicetree/bindings/pci/nvidia,tegra264-pcie.yaml b/Documentation/devicetree/bindings/pci/nvidia,tegra264-pcie.yaml
new file mode 100644
index 000000000000..acb677d477fb
--- /dev/null
+++ b/Documentation/devicetree/bindings/pci/nvidia,tegra264-pcie.yaml
@@ -0,0 +1,174 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/pci/nvidia,tegra264-pcie.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: NVIDIA Tegra264 PCIe controller
+
+maintainers:
+ - Thierry Reding <thierry.reding@gmail.com>
+ - Jon Hunter <jonathanh@nvidia.com>
+
+description: |
+ Of the six PCIe controllers found on Tegra264, one (C0) is used for the
+ internal GPU and the other five (C1-C5) are routed to connectors such as
+ PCI or M.2 slots. Therefore the UPHY registers (XPL) exist only for C1
+ through C5, but not for C0.
+
+properties:
+ compatible:
+ const: nvidia,tegra264-pcie
+
+ reg:
+ minItems: 4
+ maxItems: 5
+
+ reg-names:
+ minItems: 4
+ maxItems: 5
+
+ interrupts:
+ minItems: 1
+ maxItems: 4
+
+ dma-coherent: true
+
+ nvidia,bpmp:
+ $ref: /schemas/types.yaml#/definitions/phandle-array
+ description: |
+ Must contain a pair of phandle (to the BPMP controller node) and
+ controller ID. The following are the controller IDs for each controller:
+
+ 0: C0
+ 1: C1
+ 2: C2
+ 3: C3
+ 4: C4
+ 5: C5
+ items:
+ - items:
+ - description: phandle to the BPMP controller node
+ - description: PCIe controller ID
+ maximum: 5
+
+required:
+ - interrupt-map
+ - interrupt-map-mask
+ - iommu-map
+ - msi-map
+ - nvidia,bpmp
+
+allOf:
+ - $ref: /schemas/pci/pci-host-bridge.yaml#
+ - oneOf:
+ - description: C0 controller (no UPHY)
+ properties:
+ reg:
+ items:
+ - description: application layer registers
+ - description: transaction layer registers
+ - description: privileged transaction layer registers
+ - description: ECAM compatible configuration space
+
+ reg-names:
+ items:
+ - const: xal
+ - const: xtl
+ - const: xtl-pri
+ - const: ecam
+
+ - description: C1-C5 controllers (with UPHY)
+ properties:
+ reg:
+ items:
+ - description: application layer registers
+ - description: transaction layer registers
+ - description: privileged transaction layer registers
+ - description: data link/physical layer registers
+ - description: ECAM compatible configuration space
+
+ reg-names:
+ items:
+ - const: xal
+ - const: xtl
+ - const: xtl-pri
+ - const: xpl
+ - const: ecam
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ bus {
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ pci@c000000 {
+ compatible = "nvidia,tegra264-pcie";
+ reg = <0x00 0x0c000000 0x0 0x00004000>,
+ <0x00 0x0c004000 0x0 0x00001000>,
+ <0x00 0x0c005000 0x0 0x00001000>,
+ <0xd0 0xb0000000 0x0 0x10000000>;
+ reg-names = "xal", "xtl", "xtl-pri", "ecam";
+ #address-cells = <3>;
+ #size-cells = <2>;
+ device_type = "pci";
+ linux,pci-domain = <0x00>;
+ #interrupt-cells = <0x1>;
+
+ interrupt-map-mask = <0x0 0x0 0x0 0x7>;
+ interrupt-map = <0x0 0x0 0x0 0x1 &gic 0x0 0x0 0x0 155 4>,
+ <0x0 0x0 0x0 0x2 &gic 0x0 0x0 0x0 156 4>,
+ <0x0 0x0 0x0 0x3 &gic 0x0 0x0 0x0 157 4>,
+ <0x0 0x0 0x0 0x4 &gic 0x0 0x0 0x0 158 4>;
+
+ iommu-map = <0x0 &smmu2 0x10000 0x10000>;
+ msi-map = <0x0 &its 0x210000 0x10000>;
+ dma-coherent;
+
+ ranges = <0x81000000 0x00 0x84000000 0xd0 0x84000000 0x00 0x00200000>,
+ <0x82000000 0x00 0x20000000 0x00 0x20000000 0x00 0x08000000>,
+ <0xc3000000 0xd0 0xc0000000 0xd0 0xc0000000 0x07 0xc0000000>;
+ bus-range = <0x0 0xff>;
+
+ nvidia,bpmp = <&bpmp 0>;
+ };
+ };
+
+ - |
+ bus {
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ pci@8400000 {
+ compatible = "nvidia,tegra264-pcie";
+ reg = <0x00 0x08400000 0x0 0x00004000>,
+ <0x00 0x08404000 0x0 0x00001000>,
+ <0x00 0x08405000 0x0 0x00001000>,
+ <0x00 0x08410000 0x0 0x00010000>,
+ <0xa8 0xb0000000 0x0 0x10000000>;
+ reg-names = "xal", "xtl", "xtl-pri", "xpl", "ecam";
+ #address-cells = <3>;
+ #size-cells = <2>;
+ device_type = "pci";
+ linux,pci-domain = <0x01>;
+ #interrupt-cells = <1>;
+ interrupt-map-mask = <0x0 0x0 0x0 0x7>;
+ interrupt-map = <0x0 0x0 0x0 0x1 &gic 0x0 0x0 0x0 908 4>,
+ <0x0 0x0 0x0 0x2 &gic 0x0 0x0 0x0 909 4>,
+ <0x0 0x0 0x0 0x3 &gic 0x0 0x0 0x0 910 4>,
+ <0x0 0x0 0x0 0x4 &gic 0x0 0x0 0x0 911 4>;
+
+ iommu-map = <0x0 &smmu1 0x10000 0x10000>;
+ msi-map = <0x0 &its 0x110000 0x10000>;
+ dma-coherent;
+
+ ranges = <0x81000000 0x00 0x84000000 0xa8 0x84000000 0x00 0x00200000>,
+ <0x82000000 0x00 0x28000000 0x00 0x28000000 0x00 0x08000000>,
+ <0xc3000000 0xa8 0xc0000000 0xa8 0xc0000000 0x07 0xc0000000>;
+ bus-range = <0x00 0xff>;
+
+ nvidia,bpmp = <&bpmp 1>;
+ };
+ };
--
2.52.0
^ permalink raw reply related
* [PATCH v4 0/4] PCI: tegra: Add Tegra264 support
From: Thierry Reding @ 2026-04-02 14:27 UTC (permalink / raw)
To: Bjorn Helgaas, Lorenzo Pieralisi, Krzysztof Wilczyński,
Manivannan Sadhasivam, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Thierry Reding, Jonathan Hunter, Karthikeyan Mitran,
Hou Zhiqiang, Thomas Petazzoni, Pali Rohár, Michal Simek,
Kevin Xie
Cc: linux-pci, devicetree, linux-tegra, linux-kernel,
linux-arm-kernel, Thierry Reding, Manikanta Maddireddy
Hi,
this series adds support for the PCIe controllers found on the Tegra264
SoC. There are six instances, one of which is for internal purposes only
and the other five are general purpose.
The first two patches in the series add the BPMP support needed to power
up/down the PCI link. Patch 3 contains the device tree bindings for the
PCIe controller. Before adding the driver in patch 5, patch 4 introduces
some new common wait times for PCIe and unifies the way that drivers use
them. Finally, patch 6 adds DT nodes for the controllers found on the
Tegra264 SoC.
Note that this cannot be applied for v7.1-rc1 because there's a build
dependency that's going through the Tegra tree. If you'd like to merge
this, please let me know and I can provide a branch with the
dependencies resolved.
Changes in v4:
- strip out dependencies that are going in through the ARM SoC tree
- revert bindings to oneOf construct so that we don't produce new DTC
warnings
- Link to v3: https://patch.msgid.link/20260326135855.2795149-1-thierry.reding@kernel.org
Changes in v3:
- integrate PCI standard wait times patch into the series to maintain
bisectability
- fix review comments from Mikko
- Link to v2: https://patch.msgid.link/20260320225443.2571920-1-thierry.reding@kernel.org
Changes in v2:
- fix an issue with sanity-checking disabled BARs
- address review comments
- Link to v1: https://patch.msgid.link/20260319160110.2131954-1-thierry.reding@kernel.org
Thanks,
Thierry
---
Thierry Reding (4):
dt-bindings: pci: Document the NVIDIA Tegra264 PCIe controller
PCI: Use standard wait times for PCIe link monitoring
PCI: tegra: Add Tegra264 support
arm64: tegra: Add PCI controllers on Tegra264
.../bindings/pci/nvidia,tegra264-pcie.yaml | 174 +++++++
arch/arm64/boot/dts/nvidia/tegra264.dtsi | 248 ++++++++--
drivers/pci/controller/Kconfig | 10 +-
drivers/pci/controller/Makefile | 1 +
.../controller/cadence/pcie-cadence-host-common.c | 6 +-
.../pci/controller/cadence/pcie-cadence-lga-regs.h | 5 -
drivers/pci/controller/mobiveil/pcie-mobiveil.c | 4 +-
drivers/pci/controller/mobiveil/pcie-mobiveil.h | 5 -
drivers/pci/controller/pci-aardvark.c | 7 +-
drivers/pci/controller/pcie-tegra264.c | 527 +++++++++++++++++++++
drivers/pci/controller/pcie-xilinx-nwl.c | 9 +-
drivers/pci/controller/plda/pcie-starfive.c | 9 +-
drivers/pci/pci.h | 2 +
13 files changed, 946 insertions(+), 61 deletions(-)
---
base-commit: bfbb8533d7293235b71e4096cc0bc9a5c0c20b20
change-id: 20260402-tegra264-pcie-e30abe23da07
Best regards,
--
Thierry Reding <treding@nvidia.com>
^ permalink raw reply
* [PATCH 8/8] arm64: dts: amlogic: t7: khadas-vim4: Add i2c MCU fan node
From: Ronald Claveau @ 2026-04-02 14:27 UTC (permalink / raw)
To: Neil Armstrong, Lee Jones, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Andi Shyti, Kevin Hilman, Jerome Brunet,
Martin Blumenstingl, Beniamino Galvani, Rafael J. Wysocki,
Daniel Lezcano, Zhang Rui, Lukasz Luba, Liam Girdwood, Mark Brown
Cc: linux-amlogic, devicetree, linux-kernel, linux-i2c,
linux-arm-kernel, linux-pm, Ronald Claveau
In-Reply-To: <20260402-add-mcu-fan-khadas-vim4-v1-0-2b12eb4ac7b0@aliel.fr>
Enable and configure i2c MCU node to get fan working on Khadas VIM4.
Signed-off-by: Ronald Claveau <linux-kernel-dev@aliel.fr>
---
.../boot/dts/amlogic/amlogic-t7-a311d2-khadas-vim4.dts | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/arch/arm64/boot/dts/amlogic/amlogic-t7-a311d2-khadas-vim4.dts b/arch/arm64/boot/dts/amlogic/amlogic-t7-a311d2-khadas-vim4.dts
index 69d6118ba57e7..5d7f5390f3a66 100644
--- a/arch/arm64/boot/dts/amlogic/amlogic-t7-a311d2-khadas-vim4.dts
+++ b/arch/arm64/boot/dts/amlogic/amlogic-t7-a311d2-khadas-vim4.dts
@@ -157,6 +157,19 @@ wifi32k: wifi32k {
};
};
+&i2c_m_ao_a {
+ status = "okay";
+ pinctrl-0 = <&i2c0_ao_d_pins>;
+ pinctrl-names = "default";
+
+ khadas_mcu: system-controller@18 {
+ compatible = "khadas,vim4-mcu";
+ reg = <0x18>;
+ fan-supply = <&vcc5v>;
+ #cooling-cells = <2>;
+ };
+};
+
&pwm_ab {
status = "okay";
pinctrl-0 = <&pwm_a_pins>;
--
2.49.0
^ permalink raw reply related
* [PATCH 4/8] mfd: khadas-mcu: Add support for VIM4 MCU variant
From: Ronald Claveau @ 2026-04-02 14:27 UTC (permalink / raw)
To: Neil Armstrong, Lee Jones, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Andi Shyti, Kevin Hilman, Jerome Brunet,
Martin Blumenstingl, Beniamino Galvani, Rafael J. Wysocki,
Daniel Lezcano, Zhang Rui, Lukasz Luba, Liam Girdwood, Mark Brown
Cc: linux-amlogic, devicetree, linux-kernel, linux-i2c,
linux-arm-kernel, linux-pm, Ronald Claveau
In-Reply-To: <20260402-add-mcu-fan-khadas-vim4-v1-0-2b12eb4ac7b0@aliel.fr>
Refactor probe() to use per-variant khadas_mcu_data
instead of hardcoded globals.
Add dedicated regmap configuration and device data for the VIM4 MCU,
with its own volatile/writeable registers.
Add the fan control register
(0–100 levels vs 0–3 for previous supported boards).
Add a new compatible string "khadas,vim4-mcu".
Signed-off-by: Ronald Claveau <linux-kernel-dev@aliel.fr>
---
drivers/mfd/khadas-mcu.c | 106 ++++++++++++++++++++++++++++++++++++++++++-----
1 file changed, 95 insertions(+), 11 deletions(-)
diff --git a/drivers/mfd/khadas-mcu.c b/drivers/mfd/khadas-mcu.c
index ba981a7886921..b36b3b3ab73c0 100644
--- a/drivers/mfd/khadas-mcu.c
+++ b/drivers/mfd/khadas-mcu.c
@@ -75,15 +75,91 @@ static const struct regmap_config khadas_mcu_regmap_config = {
.cache_type = REGCACHE_MAPLE,
};
+static const struct khadas_mcu_fan_pdata khadas_mcu_fan_pdata = {
+ .fan_reg = KHADAS_MCU_CMD_FAN_STATUS_CTRL_REG,
+ .max_level = 3,
+};
+
static struct mfd_cell khadas_mcu_fan_cells[] = {
/* VIM1/2 Rev13+ and VIM3 only */
- { .name = "khadas-mcu-fan-ctrl", },
+ {
+ .name = "khadas-mcu-fan-ctrl",
+ .platform_data = &khadas_mcu_fan_pdata,
+ .pdata_size = sizeof(khadas_mcu_fan_pdata),
+ },
};
static struct mfd_cell khadas_mcu_cells[] = {
{ .name = "khadas-mcu-user-mem", },
};
+static const struct khadas_mcu_data khadas_mcu_data = {
+ .regmap_config = &khadas_mcu_regmap_config,
+ .cells = khadas_mcu_cells,
+ .ncells = ARRAY_SIZE(khadas_mcu_cells),
+ .fan_cells = khadas_mcu_fan_cells,
+ .nfan_cells = ARRAY_SIZE(khadas_mcu_fan_cells),
+};
+
+static bool khadas_mcu_vim4_reg_volatile(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case KHADAS_MCU_PWR_OFF_CMD_REG:
+ case KHADAS_MCU_VIM4_REST_CONF_REG:
+ case KHADAS_MCU_WOL_INIT_START_REG:
+ case KHADAS_MCU_VIM4_LED_ON_RAM_REG:
+ case KHADAS_MCU_VIM4_FAN_CTRL_REG:
+ case KHADAS_MCU_VIM4_WDT_EN_REG:
+ case KHADAS_MCU_VIM4_SYS_RST_REG:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static bool khadas_mcu_vim4_reg_writeable(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case KHADAS_MCU_VERSION_0_REG:
+ case KHADAS_MCU_VERSION_1_REG:
+ case KHADAS_MCU_SHUTDOWN_NORMAL_STATUS_REG:
+ return false;
+ default:
+ return true;
+ }
+}
+
+static const struct regmap_config khadas_mcu_vim4_regmap_config = {
+ .reg_bits = 8,
+ .reg_stride = 1,
+ .val_bits = 8,
+ .max_register = KHADAS_MCU_VIM4_SYS_RST_REG,
+ .volatile_reg = khadas_mcu_vim4_reg_volatile,
+ .writeable_reg = khadas_mcu_vim4_reg_writeable,
+ .cache_type = REGCACHE_MAPLE,
+};
+
+static const struct khadas_mcu_fan_pdata khadas_vim4_fan_pdata = {
+ .fan_reg = KHADAS_MCU_VIM4_FAN_CTRL_REG,
+ .max_level = 0x64,
+};
+
+static const struct mfd_cell khadas_mcu_vim4_cells[] = {
+ {
+ .name = "khadas-mcu-fan-ctrl",
+ .platform_data = &khadas_vim4_fan_pdata,
+ .pdata_size = sizeof(khadas_vim4_fan_pdata),
+ },
+};
+
+static const struct khadas_mcu_data khadas_vim4_mcu_data = {
+ .regmap_config = &khadas_mcu_vim4_regmap_config,
+ .cells = NULL,
+ .ncells = 0,
+ .fan_cells = khadas_mcu_vim4_cells,
+ .nfan_cells = ARRAY_SIZE(khadas_mcu_vim4_cells),
+};
+
static int khadas_mcu_probe(struct i2c_client *client)
{
struct device *dev = &client->dev;
@@ -94,28 +170,35 @@ static int khadas_mcu_probe(struct i2c_client *client)
if (!ddata)
return -ENOMEM;
+ ddata->data = i2c_get_match_data(client);
+ if (!ddata->data)
+ return -EINVAL;
+
i2c_set_clientdata(client, ddata);
ddata->dev = dev;
- ddata->regmap = devm_regmap_init_i2c(client, &khadas_mcu_regmap_config);
+ ddata->regmap = devm_regmap_init_i2c(client,
+ ddata->data->regmap_config);
if (IS_ERR(ddata->regmap)) {
ret = PTR_ERR(ddata->regmap);
dev_err(dev, "Failed to allocate register map: %d\n", ret);
return ret;
}
- ret = devm_mfd_add_devices(dev, PLATFORM_DEVID_NONE,
- khadas_mcu_cells,
- ARRAY_SIZE(khadas_mcu_cells),
- NULL, 0, NULL);
- if (ret)
- return ret;
+ if (ddata->data->cells && ddata->data->ncells) {
+ ret = devm_mfd_add_devices(dev, PLATFORM_DEVID_NONE,
+ ddata->data->cells,
+ ddata->data->ncells,
+ NULL, 0, NULL);
+ if (ret)
+ return ret;
+ }
if (of_property_present(dev->of_node, "#cooling-cells"))
return devm_mfd_add_devices(dev, PLATFORM_DEVID_NONE,
- khadas_mcu_fan_cells,
- ARRAY_SIZE(khadas_mcu_fan_cells),
+ ddata->data->fan_cells,
+ ddata->data->nfan_cells,
NULL, 0, NULL);
return 0;
@@ -123,7 +206,8 @@ static int khadas_mcu_probe(struct i2c_client *client)
#ifdef CONFIG_OF
static const struct of_device_id khadas_mcu_of_match[] = {
- { .compatible = "khadas,mcu", },
+ { .compatible = "khadas,mcu", .data = &khadas_mcu_data },
+ { .compatible = "khadas,vim4-mcu", .data = &khadas_vim4_mcu_data },
{},
};
MODULE_DEVICE_TABLE(of, khadas_mcu_of_match);
--
2.49.0
^ permalink raw reply related
* [PATCH 6/8] arm64: dts: amlogic: t7: Add i2c pinctrl node
From: Ronald Claveau @ 2026-04-02 14:27 UTC (permalink / raw)
To: Neil Armstrong, Lee Jones, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Andi Shyti, Kevin Hilman, Jerome Brunet,
Martin Blumenstingl, Beniamino Galvani, Rafael J. Wysocki,
Daniel Lezcano, Zhang Rui, Lukasz Luba, Liam Girdwood, Mark Brown
Cc: linux-amlogic, devicetree, linux-kernel, linux-i2c,
linux-arm-kernel, linux-pm, Ronald Claveau
In-Reply-To: <20260402-add-mcu-fan-khadas-vim4-v1-0-2b12eb4ac7b0@aliel.fr>
Add the T7 pinctrl used by the Khadas VIM4 for MCU communication.
Signed-off-by: Ronald Claveau <linux-kernel-dev@aliel.fr>
---
arch/arm64/boot/dts/amlogic/amlogic-t7.dtsi | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/arch/arm64/boot/dts/amlogic/amlogic-t7.dtsi b/arch/arm64/boot/dts/amlogic/amlogic-t7.dtsi
index 7fe72c94ed623..e96fe10b251a0 100644
--- a/arch/arm64/boot/dts/amlogic/amlogic-t7.dtsi
+++ b/arch/arm64/boot/dts/amlogic/amlogic-t7.dtsi
@@ -376,6 +376,16 @@ mux {
};
};
+ i2c0_ao_d_pins: i2c0-ao-d {
+ mux {
+ groups = "i2c0_ao_sck_d",
+ "i2c0_ao_sda_d";
+ function = "i2c0_ao";
+ bias-disable;
+ drive-strength-microamp = <3000>;
+ };
+ };
+
pwm_a_pins: pwm-a {
mux {
groups = "pwm_a";
--
2.49.0
^ permalink raw reply related
* [PATCH 5/8] thermal: khadas-mcu-fan: Add fan config from platform data Add regulator support
From: Ronald Claveau @ 2026-04-02 14:27 UTC (permalink / raw)
To: Neil Armstrong, Lee Jones, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Andi Shyti, Kevin Hilman, Jerome Brunet,
Martin Blumenstingl, Beniamino Galvani, Rafael J. Wysocki,
Daniel Lezcano, Zhang Rui, Lukasz Luba, Liam Girdwood, Mark Brown
Cc: linux-amlogic, devicetree, linux-kernel, linux-i2c,
linux-arm-kernel, linux-pm, Ronald Claveau
In-Reply-To: <20260402-add-mcu-fan-khadas-vim4-v1-0-2b12eb4ac7b0@aliel.fr>
Replace the hardcoded MAX_LEVEL constant and fan register
with values read from platform_data (fan_reg, max_level),
as new MCUs need different values.
Optionally acquire and enable a "fan" regulator supply
at probe time and on resume,
so boards that gate fan power through a regulator are handled.
Signed-off-by: Ronald Claveau <linux-kernel-dev@aliel.fr>
---
drivers/thermal/khadas_mcu_fan.c | 43 ++++++++++++++++++++++++++++++++++------
1 file changed, 37 insertions(+), 6 deletions(-)
diff --git a/drivers/thermal/khadas_mcu_fan.c b/drivers/thermal/khadas_mcu_fan.c
index d35e5313bea41..55b496625e3bd 100644
--- a/drivers/thermal/khadas_mcu_fan.c
+++ b/drivers/thermal/khadas_mcu_fan.c
@@ -13,13 +13,15 @@
#include <linux/regmap.h>
#include <linux/sysfs.h>
#include <linux/thermal.h>
-
-#define MAX_LEVEL 3
+#include <linux/regulator/consumer.h>
struct khadas_mcu_fan_ctx {
struct khadas_mcu *mcu;
+ unsigned int fan_reg;
unsigned int level;
+ unsigned int max_level;
struct thermal_cooling_device *cdev;
+ struct regulator *power;
};
static int khadas_mcu_fan_set_level(struct khadas_mcu_fan_ctx *ctx,
@@ -27,8 +29,7 @@ static int khadas_mcu_fan_set_level(struct khadas_mcu_fan_ctx *ctx,
{
int ret;
- ret = regmap_write(ctx->mcu->regmap, KHADAS_MCU_CMD_FAN_STATUS_CTRL_REG,
- level);
+ ret = regmap_write(ctx->mcu->regmap, ctx->fan_reg, level);
if (ret)
return ret;
@@ -40,7 +41,9 @@ static int khadas_mcu_fan_set_level(struct khadas_mcu_fan_ctx *ctx,
static int khadas_mcu_fan_get_max_state(struct thermal_cooling_device *cdev,
unsigned long *state)
{
- *state = MAX_LEVEL;
+ struct khadas_mcu_fan_ctx *ctx = cdev->devdata;
+
+ *state = ctx->max_level;
return 0;
}
@@ -61,7 +64,7 @@ khadas_mcu_fan_set_cur_state(struct thermal_cooling_device *cdev,
{
struct khadas_mcu_fan_ctx *ctx = cdev->devdata;
- if (state > MAX_LEVEL)
+ if (state > ctx->max_level)
return -EINVAL;
if (state == ctx->level)
@@ -83,11 +86,32 @@ static int khadas_mcu_fan_probe(struct platform_device *pdev)
struct device *dev = &pdev->dev;
struct khadas_mcu_fan_ctx *ctx;
int ret;
+ const struct khadas_mcu_fan_pdata *pdata = dev_get_platdata(&pdev->dev);
ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
if (!ctx)
return -ENOMEM;
+
ctx->mcu = mcu;
+ ctx->fan_reg = pdata->fan_reg;
+ ctx->max_level = pdata->max_level;
+
+ ctx->power = devm_regulator_get_optional(dev->parent, "fan");
+ if (IS_ERR(ctx->power)) {
+ if (PTR_ERR(ctx->power) == -ENODEV)
+ ctx->power = NULL;
+ else
+ return PTR_ERR(ctx->power);
+ }
+
+ if (ctx->power) {
+ ret = regulator_enable(ctx->power);
+ if (ret) {
+ dev_err(dev, "Failed to enable fan power supply: %d\n", ret);
+ return ret;
+ }
+ }
+
platform_set_drvdata(pdev, ctx);
cdev = devm_thermal_of_cooling_device_register(dev->parent,
@@ -130,6 +154,13 @@ static int khadas_mcu_fan_suspend(struct device *dev)
static int khadas_mcu_fan_resume(struct device *dev)
{
struct khadas_mcu_fan_ctx *ctx = dev_get_drvdata(dev);
+ int ret;
+
+ if (ctx->power) {
+ ret = regulator_enable(ctx->power);
+ if (ret)
+ return ret;
+ }
return khadas_mcu_fan_set_level(ctx, ctx->level);
}
--
2.49.0
^ permalink raw reply related
* [PATCH 7/8] arm64: dts: amlogic: t7: Add i2c controller node
From: Ronald Claveau @ 2026-04-02 14:27 UTC (permalink / raw)
To: Neil Armstrong, Lee Jones, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Andi Shyti, Kevin Hilman, Jerome Brunet,
Martin Blumenstingl, Beniamino Galvani, Rafael J. Wysocki,
Daniel Lezcano, Zhang Rui, Lukasz Luba, Liam Girdwood, Mark Brown
Cc: linux-amlogic, devicetree, linux-kernel, linux-i2c,
linux-arm-kernel, linux-pm, Ronald Claveau
In-Reply-To: <20260402-add-mcu-fan-khadas-vim4-v1-0-2b12eb4ac7b0@aliel.fr>
Add the T7 i2c controller node used by the Khadas VIM4
for MCU communication.
Use amlogic,meson-axg-i2c as fallback compatible.
Signed-off-by: Ronald Claveau <linux-kernel-dev@aliel.fr>
---
arch/arm64/boot/dts/amlogic/amlogic-t7.dtsi | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/arch/arm64/boot/dts/amlogic/amlogic-t7.dtsi b/arch/arm64/boot/dts/amlogic/amlogic-t7.dtsi
index e96fe10b251a0..560c9dce35266 100644
--- a/arch/arm64/boot/dts/amlogic/amlogic-t7.dtsi
+++ b/arch/arm64/boot/dts/amlogic/amlogic-t7.dtsi
@@ -711,6 +711,16 @@ pwm_ao_cd: pwm@60000 {
status = "disabled";
};
+ i2c_m_ao_a: i2c@76000 {
+ compatible = "amlogic,t7-i2c", "amlogic,meson-axg-i2c";
+ reg = <0x0 0x76000 0x0 0x48>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ interrupts = <GIC_SPI 330 IRQ_TYPE_EDGE_RISING>;
+ clocks = <&clkc_periphs CLKID_SYS_I2C_AO_A>;
+ status = "disabled";
+ };
+
sd_emmc_a: mmc@88000 {
compatible = "amlogic,t7-mmc", "amlogic,meson-axg-mmc";
reg = <0x0 0x88000 0x0 0x800>;
--
2.49.0
^ permalink raw reply related
* [PATCH 3/8] mfd: khadas-mcu: Add per-variant configuration infrastructure and VIM4 support
From: Ronald Claveau @ 2026-04-02 14:27 UTC (permalink / raw)
To: Neil Armstrong, Lee Jones, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Andi Shyti, Kevin Hilman, Jerome Brunet,
Martin Blumenstingl, Beniamino Galvani, Rafael J. Wysocki,
Daniel Lezcano, Zhang Rui, Lukasz Luba, Liam Girdwood, Mark Brown
Cc: linux-amlogic, devicetree, linux-kernel, linux-i2c,
linux-arm-kernel, linux-pm, Ronald Claveau
In-Reply-To: <20260402-add-mcu-fan-khadas-vim4-v1-0-2b12eb4ac7b0@aliel.fr>
Introduce a per-variant configuration structure (khadas_mcu_data)
holding the regmap config and MFD cells,
selected at probe time via the of_device_id match data.
This makes adding other variants straightforward.
Also introduce khadas_mcu_fan_pdata to pass fan register address and
maximum level to the fan sub-driver, removing the hardcoded constants.
Signed-off-by: Ronald Claveau <linux-kernel-dev@aliel.fr>
---
include/linux/mfd/khadas-mcu.h | 39 +++++++++++++++++++++++++++++++++++++--
1 file changed, 37 insertions(+), 2 deletions(-)
diff --git a/include/linux/mfd/khadas-mcu.h b/include/linux/mfd/khadas-mcu.h
index a99ba2ed0e4e0..75e275d3fa8d9 100644
--- a/include/linux/mfd/khadas-mcu.h
+++ b/include/linux/mfd/khadas-mcu.h
@@ -70,6 +70,13 @@
#define KHADAS_MCU_WOL_INIT_START_REG 0x87 /* WO */
#define KHADAS_MCU_CMD_FAN_STATUS_CTRL_REG 0x88 /* WO */
+/* VIM4 specific registers */
+#define KHADAS_MCU_VIM4_REST_CONF_REG 0x2c /* WO - reset EEPROM */
+#define KHADAS_MCU_VIM4_LED_ON_RAM_REG 0x89 /* WO - LED volatile */
+#define KHADAS_MCU_VIM4_FAN_CTRL_REG 0x8a /* WO */
+#define KHADAS_MCU_VIM4_WDT_EN_REG 0x8b /* WO */
+#define KHADAS_MCU_VIM4_SYS_RST_REG 0x91 /* WO */
+
enum {
KHADAS_BOARD_VIM1 = 0x1,
KHADAS_BOARD_VIM2,
@@ -82,10 +89,38 @@ enum {
* struct khadas_mcu - Khadas MCU structure
* @device: device reference used for logs
* @regmap: register map
+ * @data: pointer to variant-specific config
*/
struct khadas_mcu {
- struct device *dev;
- struct regmap *regmap;
+ struct device *dev;
+ struct regmap *regmap;
+ const struct khadas_mcu_data *data;
+};
+
+/**
+ * struct khadas_mcu_data - per-variant configuration
+ * @regmap_config: regmap configuration
+ * @cells: MFD sub-devices
+ * @ncells: number of sub-devices
+ * @fan_cells: MFD fan sub-devices
+ * @nfan_cells: number of fan sub-devices
+ */
+struct khadas_mcu_data {
+ const struct regmap_config *regmap_config;
+ const struct mfd_cell *cells;
+ int ncells;
+ const struct mfd_cell *fan_cells;
+ int nfan_cells;
+};
+
+/**
+ * struct khadas_mcu_fan_pdata - fan sub-driver configuration
+ * @fan_reg: register address to write the fan level
+ * @max_level: maximum fan level
+ */
+struct khadas_mcu_fan_pdata {
+ unsigned int fan_reg;
+ unsigned int max_level;
};
#endif /* MFD_KHADAS_MCU_H */
--
2.49.0
^ permalink raw reply related
* [PATCH 2/8] dt-bindings: i2c: amlogic: Add compatible for T7 SOC
From: Ronald Claveau @ 2026-04-02 14:27 UTC (permalink / raw)
To: Neil Armstrong, Lee Jones, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Andi Shyti, Kevin Hilman, Jerome Brunet,
Martin Blumenstingl, Beniamino Galvani, Rafael J. Wysocki,
Daniel Lezcano, Zhang Rui, Lukasz Luba, Liam Girdwood, Mark Brown
Cc: linux-amlogic, devicetree, linux-kernel, linux-i2c,
linux-arm-kernel, linux-pm, Ronald Claveau
In-Reply-To: <20260402-add-mcu-fan-khadas-vim4-v1-0-2b12eb4ac7b0@aliel.fr>
Add the T7 SOC compatible which fallback to AXG compatible.
Signed-off-by: Ronald Claveau <linux-kernel-dev@aliel.fr>
---
.../devicetree/bindings/i2c/amlogic,meson6-i2c.yaml | 13 +++++++++----
1 file changed, 9 insertions(+), 4 deletions(-)
diff --git a/Documentation/devicetree/bindings/i2c/amlogic,meson6-i2c.yaml b/Documentation/devicetree/bindings/i2c/amlogic,meson6-i2c.yaml
index c4cc8af182807..7b59b60b62e5b 100644
--- a/Documentation/devicetree/bindings/i2c/amlogic,meson6-i2c.yaml
+++ b/Documentation/devicetree/bindings/i2c/amlogic,meson6-i2c.yaml
@@ -16,10 +16,15 @@ allOf:
properties:
compatible:
- enum:
- - amlogic,meson6-i2c # Meson6, Meson8 and compatible SoCs
- - amlogic,meson-gxbb-i2c # GXBB and compatible SoCs
- - amlogic,meson-axg-i2c # AXG and compatible SoCs
+ oneOf:
+ - items:
+ - enum:
+ - amlogic,t7-i2c
+ - const: amlogic,meson-axg-i2c
+ - enum:
+ - amlogic,meson6-i2c # Meson6, Meson8 and compatible SoCs
+ - amlogic,meson-gxbb-i2c # GXBB and compatible SoCs
+ - amlogic,meson-axg-i2c # AXG and compatible SoCs
reg:
maxItems: 1
--
2.49.0
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox