diff --git a/drivers/i3c/master/dw-i3c-master.c b/drivers/i3c/master/dw-i3c-master.c index a6d3fa548144..e2ab9f199eb3 100644 --- a/drivers/i3c/master/dw-i3c-master.c +++ b/drivers/i3c/master/dw-i3c-master.c @@ -242,6 +242,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; @@ -556,13 +557,28 @@ 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->core_clk) + return clk_get_rate(master->core_clk); + + if (device_property_read_u32(master->dev, "clock-frequency", &core_rate_prop)) { + dev_err(master->dev, "missing clock-frequency property\n"); + 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; @@ -615,7 +631,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; @@ -1602,14 +1618,28 @@ int dw_i3c_common_probe(struct dw_i3c_master *master, master->dev = &pdev->dev; + 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; + master->regs = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(master->regs)) return PTR_ERR(master->regs); - master->core_clk = devm_clk_get_enabled(&pdev->dev, NULL); + master->core_clk = devm_clk_get_optional_enabled(&pdev->dev, NULL); if (IS_ERR(master->core_clk)) return PTR_ERR(master->core_clk); + if (!master->core_clk && !(master->quirks & DW_I3C_ACPI_SKIP_CLK_RST)) { + dev_err(&pdev->dev, "missing core clock\n"); + return -EINVAL; + } + master->pclk = devm_clk_get_optional_enabled(&pdev->dev, "pclk"); if (IS_ERR(master->pclk)) return PTR_ERR(master->pclk); @@ -1665,15 +1695,6 @@ int dw_i3c_common_probe(struct dw_i3c_master *master, master->has_ibi_data = true; writel(thld_ctrl, master->regs + QUEUE_THLD_CTRL); - 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);