[PATCH v2 09/13] i3c: dw-i3c-master: Add a quirk to skip clock and reset
Akhil R <[email protected]>
| Newsgroups | dev.linux.lists.acpica-devel,org.infradead.lists.linux-i3c,org.kernel.vger.linux-acpi,org.kernel.vger.linux-devicetree,org.kernel.vger.linux-hwmon,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <[email protected]> |
Some ACPI-enumerated devices like Tegra410 do not have clock and reset resources exposed via the clk/reset frameworks. Add a match data for such devices to skip acquiring clock and reset controls during probe. Move match data parsing before clock/reset acquisition so the quirk is available early enough. When the quirk is set, fall back to reading the clock rate from the "clock-frequency" device property instead. Signed-off-by: Akhil R <[email protected]> --- drivers/i3c/master/dw-i3c-master.c | 60 +++++++++++++++++++----------- 1 file changed, 39 insertions(+), 21 deletions(-) diff --git a/drivers/i3c/master/dw-i3c-master.c b/drivers/i3c/master/dw-i3c-master.c index 05ccdf177b6d..a62eec6d2ac0 100644 --- a/drivers/i3c/master/dw-i3c-master.c +++ b/drivers/i3c/master/dw-i3c-master.c @@ -241,6 +241,7 @@ /* List of quirks */ #define AMD_I3C_OD_PP_TIMING BIT(1) #define DW_I3C_DISABLE_RUNTIME_PM_QUIRK BIT(2) +#define DW_I3C_ACPI_SKIP_CLK_RST BIT(3) struct dw_i3c_cmd { u32 cmd_lo; @@ -560,13 +561,26 @@ static void dw_i3c_master_set_intr_regs(struct dw_i3c_master *master) writel(IBI_REQ_REJECT_ALL, master->regs + IBI_MR_REQ_REJECT); } +static unsigned long dw_i3c_master_get_core_rate(struct dw_i3c_master *master) +{ + unsigned int core_rate_prop; + + if (!(master->quirks & DW_I3C_ACPI_SKIP_CLK_RST)) + return clk_get_rate(master->core_clk); + + if (device_property_read_u32(master->dev, "clock-frequency", &core_rate_prop)) + return 0; + + return core_rate_prop; +} + static int dw_i3c_clk_cfg(struct dw_i3c_master *master) { unsigned long core_rate, core_period; u32 scl_timing; u8 hcnt, lcnt; - core_rate = clk_get_rate(master->core_clk); + core_rate = dw_i3c_master_get_core_rate(master); if (!core_rate) return -EINVAL; @@ -619,7 +633,7 @@ static int dw_i2c_clk_cfg(struct dw_i3c_master *master) u16 hcnt, lcnt; u32 scl_timing; - core_rate = clk_get_rate(master->core_clk); + core_rate = dw_i3c_master_get_core_rate(master); if (!core_rate) return -EINVAL; @@ -1600,21 +1614,34 @@ int dw_i3c_common_probe(struct dw_i3c_master *master, if (IS_ERR(master->regs)) return PTR_ERR(master->regs); - master->core_clk = devm_clk_get_enabled(&pdev->dev, NULL); - if (IS_ERR(master->core_clk)) - return PTR_ERR(master->core_clk); + if (has_acpi_companion(&pdev->dev)) { + quirks = (unsigned long)device_get_match_data(&pdev->dev); + } else if (pdev->dev.of_node) { + drvdata = device_get_match_data(&pdev->dev); + if (drvdata) + quirks = drvdata->flags; + } + master->quirks = quirks; + + if (master->quirks & DW_I3C_ACPI_SKIP_CLK_RST) { + master->core_clk = NULL; + master->core_rst = NULL; + } else { + master->core_clk = devm_clk_get_enabled(&pdev->dev, NULL); + if (IS_ERR(master->core_clk)) + return PTR_ERR(master->core_clk); + + master->core_rst = devm_reset_control_get_optional_exclusive(&pdev->dev, + "core_rst"); + if (IS_ERR(master->core_rst)) + return PTR_ERR(master->core_rst); + reset_control_deassert(master->core_rst); + } master->pclk = devm_clk_get_optional_enabled(&pdev->dev, "pclk"); if (IS_ERR(master->pclk)) return PTR_ERR(master->pclk); - master->core_rst = devm_reset_control_get_optional_exclusive(&pdev->dev, - "core_rst"); - if (IS_ERR(master->core_rst)) - return PTR_ERR(master->core_rst); - - reset_control_deassert(master->core_rst); - spin_lock_init(&master->xferqueue.lock); INIT_LIST_HEAD(&master->xferqueue.list); @@ -1647,15 +1674,6 @@ int dw_i3c_common_probe(struct dw_i3c_master *master, master->maxdevs = ret >> 16; master->free_pos = GENMASK(master->maxdevs - 1, 0); - if (has_acpi_companion(&pdev->dev)) { - quirks = (unsigned long)device_get_match_data(&pdev->dev); - } else if (pdev->dev.of_node) { - drvdata = device_get_match_data(&pdev->dev); - if (drvdata) - quirks = drvdata->flags; - } - master->quirks = quirks; - /* Keep controller enabled by preventing runtime suspend */ if (master->quirks & DW_I3C_DISABLE_RUNTIME_PM_QUIRK) pm_runtime_get_noresume(&pdev->dev); -- 2.50.1