summaryrefslogtreecommitdiff
path: root/drivers/clk
diff options
context:
space:
mode:
authorStephen Boyd <sboyd@kernel.org>2023-04-03 12:05:23 -0700
committerStephen Boyd <sboyd@kernel.org>2023-04-03 12:05:23 -0700
commitef382228d25a93aa9dcb8be6e82322c272831cda (patch)
tree68b9cb532582420283b472d8061447ddda362ca4 /drivers/clk
parentfe15c26ee26efa11741a7b632e9f23b01aca4cc6 (diff)
parentbabb3e6a8a8e5a61a65d4463610108808139b23e (diff)
downloadlwn-ef382228d25a93aa9dcb8be6e82322c272831cda.tar.gz
lwn-ef382228d25a93aa9dcb8be6e82322c272831cda.zip
Merge tag 'samsung-clk-6.4' of https://git.kernel.org/pub/scm/linux/kernel/git/krzk/linux into clk-samsung
Pull Samsung SoC clk drivers updates from Krzysztof Kozlowski: - Exynos850: Add CMU_G3D clock controller for the Mali GPU. This brings new PLLs and few cleanups/simplifications in core Exynos clock controller code, so they can be easier re-used in Exynos850 clock controller driver. New CMU_G3D clock controller needs Devicetree bindings header changes with clock indices which are pulled from Samsung SoC repository. - Extract Exynos5433 (ARM64) clock controller power management code to common driver parts, so later it can be re-used by other Exynos clock controller drivers. This only prepares for such re-usage, which is expected to come later for Exynos850. - Exynos850: make PMU_ALIVE_PCLK clock critical, because it is needed for core block - Power Management Unit. - Cleanup: remove() callback returns void. * tag 'samsung-clk-6.4' of https://git.kernel.org/pub/scm/linux/kernel/git/krzk/linux: clk: samsung: exynos850: Make PMU_ALIVE_PCLK critical clk: samsung: Convert to platform remove callback returning void clk: samsung: exynos5433: Extract PM support to common ARM64 layer clk: samsung: Extract parent clock enabling to common function clk: samsung: Extract clocks registration to common function clk: samsung: exynos850: Add AUD and HSI main gate clocks clk: samsung: exynos850: Implement CMU_G3D domain clk: samsung: clk-pll: Implement pll0818x PLL type clk: samsung: Set dev in samsung_clk_init() clk: samsung: Don't pass reg_base to samsung_clk_register_pll() clk: samsung: Remove np argument from samsung_clk_init() dt-bindings: clock: exynos850: Add AUD and HSI main gate clocks dt-bindings: clock: exynos850: Add Exynos850 CMU_G3D
Diffstat (limited to 'drivers/clk')
-rw-r--r--drivers/clk/samsung/clk-exynos-arm64.c229
-rw-r--r--drivers/clk/samsung/clk-exynos-arm64.h3
-rw-r--r--drivers/clk/samsung/clk-exynos-audss.c6
-rw-r--r--drivers/clk/samsung/clk-exynos-clkout.c6
-rw-r--r--drivers/clk/samsung/clk-exynos4.c6
-rw-r--r--drivers/clk/samsung/clk-exynos4412-isp.c3
-rw-r--r--drivers/clk/samsung/clk-exynos5250.c5
-rw-r--r--drivers/clk/samsung/clk-exynos5420.c5
-rw-r--r--drivers/clk/samsung/clk-exynos5433.c157
-rw-r--r--drivers/clk/samsung/clk-exynos850.c141
-rw-r--r--drivers/clk/samsung/clk-pll.c12
-rw-r--r--drivers/clk/samsung/clk-pll.h1
-rw-r--r--drivers/clk/samsung/clk-s3c64xx.c4
-rw-r--r--drivers/clk/samsung/clk-s5pv210.c6
-rw-r--r--drivers/clk/samsung/clk.c64
-rw-r--r--drivers/clk/samsung/clk.h10
16 files changed, 431 insertions, 227 deletions
diff --git a/drivers/clk/samsung/clk-exynos-arm64.c b/drivers/clk/samsung/clk-exynos-arm64.c
index b921b9a1134a..7d8937caf22a 100644
--- a/drivers/clk/samsung/clk-exynos-arm64.c
+++ b/drivers/clk/samsung/clk-exynos-arm64.c
@@ -10,6 +10,9 @@
*/
#include <linux/clk.h>
#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/slab.h>
#include "clk-exynos-arm64.h"
@@ -21,6 +24,19 @@
#define GATE_OFF_START 0x2000
#define GATE_OFF_END 0x2fff
+struct exynos_arm64_cmu_data {
+ struct samsung_clk_reg_dump *clk_save;
+ unsigned int nr_clk_save;
+ const struct samsung_clk_reg_dump *clk_suspend;
+ unsigned int nr_clk_suspend;
+
+ struct clk *clk;
+ struct clk **pclks;
+ int nr_pclks;
+
+ struct samsung_clk_provider *ctx;
+};
+
/**
* exynos_arm64_init_clocks - Set clocks initial configuration
* @np: CMU device tree node with "reg" property (CMU addr)
@@ -57,6 +73,83 @@ static void __init exynos_arm64_init_clocks(struct device_node *np,
}
/**
+ * exynos_arm64_enable_bus_clk - Enable parent clock of specified CMU
+ *
+ * @dev: Device object; may be NULL if this function is not being
+ * called from platform driver probe function
+ * @np: CMU device tree node
+ * @cmu: CMU data
+ *
+ * Keep CMU parent clock running (needed for CMU registers access).
+ *
+ * Return: 0 on success or a negative error code on failure.
+ */
+static int __init exynos_arm64_enable_bus_clk(struct device *dev,
+ struct device_node *np, const struct samsung_cmu_info *cmu)
+{
+ struct clk *parent_clk;
+
+ if (!cmu->clk_name)
+ return 0;
+
+ if (dev) {
+ struct exynos_arm64_cmu_data *data;
+
+ parent_clk = clk_get(dev, cmu->clk_name);
+ data = dev_get_drvdata(dev);
+ if (data)
+ data->clk = parent_clk;
+ } else {
+ parent_clk = of_clk_get_by_name(np, cmu->clk_name);
+ }
+
+ if (IS_ERR(parent_clk))
+ return PTR_ERR(parent_clk);
+
+ return clk_prepare_enable(parent_clk);
+}
+
+static int __init exynos_arm64_cmu_prepare_pm(struct device *dev,
+ const struct samsung_cmu_info *cmu)
+{
+ struct exynos_arm64_cmu_data *data = dev_get_drvdata(dev);
+ int i;
+
+ data->clk_save = samsung_clk_alloc_reg_dump(cmu->clk_regs,
+ cmu->nr_clk_regs);
+ if (!data->clk_save)
+ return -ENOMEM;
+
+ data->nr_clk_save = cmu->nr_clk_regs;
+ data->clk_suspend = cmu->suspend_regs;
+ data->nr_clk_suspend = cmu->nr_suspend_regs;
+ data->nr_pclks = of_clk_get_parent_count(dev->of_node);
+ if (!data->nr_pclks)
+ return 0;
+
+ data->pclks = devm_kcalloc(dev, sizeof(struct clk *), data->nr_pclks,
+ GFP_KERNEL);
+ if (!data->pclks) {
+ kfree(data->clk_save);
+ return -ENOMEM;
+ }
+
+ for (i = 0; i < data->nr_pclks; i++) {
+ struct clk *clk = of_clk_get(dev->of_node, i);
+
+ if (IS_ERR(clk)) {
+ kfree(data->clk_save);
+ while (--i >= 0)
+ clk_put(data->pclks[i]);
+ return PTR_ERR(clk);
+ }
+ data->pclks[i] = clk;
+ }
+
+ return 0;
+}
+
+/**
* exynos_arm64_register_cmu - Register specified Exynos CMU domain
* @dev: Device object; may be NULL if this function is not being
* called from platform driver probe function
@@ -72,23 +165,127 @@ static void __init exynos_arm64_init_clocks(struct device_node *np,
void __init exynos_arm64_register_cmu(struct device *dev,
struct device_node *np, const struct samsung_cmu_info *cmu)
{
- /* Keep CMU parent clock running (needed for CMU registers access) */
- if (cmu->clk_name) {
- struct clk *parent_clk;
-
- if (dev)
- parent_clk = clk_get(dev, cmu->clk_name);
- else
- parent_clk = of_clk_get_by_name(np, cmu->clk_name);
-
- if (IS_ERR(parent_clk)) {
- pr_err("%s: could not find bus clock %s; err = %ld\n",
- __func__, cmu->clk_name, PTR_ERR(parent_clk));
- } else {
- clk_prepare_enable(parent_clk);
- }
- }
+ int err;
+
+ /*
+ * Try to boot even if the parent clock enablement fails, as it might be
+ * already enabled by bootloader.
+ */
+ err = exynos_arm64_enable_bus_clk(dev, np, cmu);
+ if (err)
+ pr_err("%s: could not enable bus clock %s; err = %d\n",
+ __func__, cmu->clk_name, err);
exynos_arm64_init_clocks(np, cmu->clk_regs, cmu->nr_clk_regs);
samsung_cmu_register_one(np, cmu);
}
+
+/**
+ * exynos_arm64_register_cmu_pm - Register Exynos CMU domain with PM support
+ *
+ * @pdev: Platform device object
+ * @set_manual: If true, set gate clocks to manual mode
+ *
+ * It's a version of exynos_arm64_register_cmu() with PM support. Should be
+ * called from probe function of platform driver.
+ *
+ * Return: 0 on success, or negative error code on error.
+ */
+int __init exynos_arm64_register_cmu_pm(struct platform_device *pdev,
+ bool set_manual)
+{
+ const struct samsung_cmu_info *cmu;
+ struct device *dev = &pdev->dev;
+ struct device_node *np = dev->of_node;
+ struct exynos_arm64_cmu_data *data;
+ void __iomem *reg_base;
+ int ret;
+
+ cmu = of_device_get_match_data(dev);
+
+ data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ platform_set_drvdata(pdev, data);
+
+ ret = exynos_arm64_cmu_prepare_pm(dev, cmu);
+ if (ret)
+ return ret;
+
+ /*
+ * Try to boot even if the parent clock enablement fails, as it might be
+ * already enabled by bootloader.
+ */
+ ret = exynos_arm64_enable_bus_clk(dev, NULL, cmu);
+ if (ret)
+ dev_err(dev, "%s: could not enable bus clock %s; err = %d\n",
+ __func__, cmu->clk_name, ret);
+
+ if (set_manual)
+ exynos_arm64_init_clocks(np, cmu->clk_regs, cmu->nr_clk_regs);
+
+ reg_base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(reg_base))
+ return PTR_ERR(reg_base);
+
+ data->ctx = samsung_clk_init(dev, reg_base, cmu->nr_clk_ids);
+
+ /*
+ * Enable runtime PM here to allow the clock core using runtime PM
+ * for the registered clocks. Additionally, we increase the runtime
+ * PM usage count before registering the clocks, to prevent the
+ * clock core from runtime suspending the device.
+ */
+ pm_runtime_get_noresume(dev);
+ pm_runtime_set_active(dev);
+ pm_runtime_enable(dev);
+
+ samsung_cmu_register_clocks(data->ctx, cmu);
+ samsung_clk_of_add_provider(dev->of_node, data->ctx);
+ pm_runtime_put_sync(dev);
+
+ return 0;
+}
+
+int exynos_arm64_cmu_suspend(struct device *dev)
+{
+ struct exynos_arm64_cmu_data *data = dev_get_drvdata(dev);
+ int i;
+
+ samsung_clk_save(data->ctx->reg_base, data->clk_save,
+ data->nr_clk_save);
+
+ for (i = 0; i < data->nr_pclks; i++)
+ clk_prepare_enable(data->pclks[i]);
+
+ /* For suspend some registers have to be set to certain values */
+ samsung_clk_restore(data->ctx->reg_base, data->clk_suspend,
+ data->nr_clk_suspend);
+
+ for (i = 0; i < data->nr_pclks; i++)
+ clk_disable_unprepare(data->pclks[i]);
+
+ clk_disable_unprepare(data->clk);
+
+ return 0;
+}
+
+int exynos_arm64_cmu_resume(struct device *dev)
+{
+ struct exynos_arm64_cmu_data *data = dev_get_drvdata(dev);
+ int i;
+
+ clk_prepare_enable(data->clk);
+
+ for (i = 0; i < data->nr_pclks; i++)
+ clk_prepare_enable(data->pclks[i]);
+
+ samsung_clk_restore(data->ctx->reg_base, data->clk_save,
+ data->nr_clk_save);
+
+ for (i = 0; i < data->nr_pclks; i++)
+ clk_disable_unprepare(data->pclks[i]);
+
+ return 0;
+}
diff --git a/drivers/clk/samsung/clk-exynos-arm64.h b/drivers/clk/samsung/clk-exynos-arm64.h
index 0dd174693935..969979e714bc 100644
--- a/drivers/clk/samsung/clk-exynos-arm64.h
+++ b/drivers/clk/samsung/clk-exynos-arm64.h
@@ -16,5 +16,8 @@
void exynos_arm64_register_cmu(struct device *dev,
struct device_node *np, const struct samsung_cmu_info *cmu);
+int exynos_arm64_register_cmu_pm(struct platform_device *pdev, bool set_manual);
+int exynos_arm64_cmu_suspend(struct device *dev);
+int exynos_arm64_cmu_resume(struct device *dev);
#endif /* __CLK_EXYNOS_ARM64_H */
diff --git a/drivers/clk/samsung/clk-exynos-audss.c b/drivers/clk/samsung/clk-exynos-audss.c
index 9cc127a162ad..7626dff41f6f 100644
--- a/drivers/clk/samsung/clk-exynos-audss.c
+++ b/drivers/clk/samsung/clk-exynos-audss.c
@@ -268,7 +268,7 @@ unregister:
return ret;
}
-static int exynos_audss_clk_remove(struct platform_device *pdev)
+static void exynos_audss_clk_remove(struct platform_device *pdev)
{
of_clk_del_provider(pdev->dev.of_node);
@@ -277,8 +277,6 @@ static int exynos_audss_clk_remove(struct platform_device *pdev)
if (!IS_ERR(epll))
clk_disable_unprepare(epll);
-
- return 0;
}
static const struct dev_pm_ops exynos_audss_clk_pm_ops = {
@@ -295,7 +293,7 @@ static struct platform_driver exynos_audss_clk_driver = {
.pm = &exynos_audss_clk_pm_ops,
},
.probe = exynos_audss_clk_probe,
- .remove = exynos_audss_clk_remove,
+ .remove_new = exynos_audss_clk_remove,
};
module_platform_driver(exynos_audss_clk_driver);
diff --git a/drivers/clk/samsung/clk-exynos-clkout.c b/drivers/clk/samsung/clk-exynos-clkout.c
index e6d6cbf8c4e6..0cff1c94c35e 100644
--- a/drivers/clk/samsung/clk-exynos-clkout.c
+++ b/drivers/clk/samsung/clk-exynos-clkout.c
@@ -196,15 +196,13 @@ clks_put:
return ret;
}
-static int exynos_clkout_remove(struct platform_device *pdev)
+static void exynos_clkout_remove(struct platform_device *pdev)
{
struct exynos_clkout *clkout = platform_get_drvdata(pdev);
of_clk_del_provider(clkout->np);
clk_hw_unregister(clkout->data.hws[0]);
iounmap(clkout->reg);
-
- return 0;
}
static int __maybe_unused exynos_clkout_suspend(struct device *dev)
@@ -235,7 +233,7 @@ static struct platform_driver exynos_clkout_driver = {
.pm = &exynos_clkout_pm_ops,
},
.probe = exynos_clkout_probe,
- .remove = exynos_clkout_remove,
+ .remove_new = exynos_clkout_remove,
};
module_platform_driver(exynos_clkout_driver);
diff --git a/drivers/clk/samsung/clk-exynos4.c b/drivers/clk/samsung/clk-exynos4.c
index 22009cb53428..d7dbb3858347 100644
--- a/drivers/clk/samsung/clk-exynos4.c
+++ b/drivers/clk/samsung/clk-exynos4.c
@@ -1251,7 +1251,7 @@ static void __init exynos4_clk_init(struct device_node *np,
if (!reg_base)
panic("%s: failed to map registers\n", __func__);
- ctx = samsung_clk_init(np, reg_base, CLK_NR_CLKS);
+ ctx = samsung_clk_init(NULL, reg_base, CLK_NR_CLKS);
hws = ctx->clk_data.hws;
samsung_clk_of_register_fixed_ext(ctx, exynos4_fixed_rate_ext_clks,
@@ -1276,7 +1276,7 @@ static void __init exynos4_clk_init(struct device_node *np,
exynos4210_vpll_rates;
samsung_clk_register_pll(ctx, exynos4210_plls,
- ARRAY_SIZE(exynos4210_plls), reg_base);
+ ARRAY_SIZE(exynos4210_plls));
} else {
if (clk_hw_get_rate(hws[CLK_FIN_PLL]) == 24000000) {
exynos4x12_plls[apll].rate_table =
@@ -1288,7 +1288,7 @@ static void __init exynos4_clk_init(struct device_node *np,
}
samsung_clk_register_pll(ctx, exynos4x12_plls,
- ARRAY_SIZE(exynos4x12_plls), reg_base);
+ ARRAY_SIZE(exynos4x12_plls));
}
samsung_clk_register_fixed_rate(ctx, exynos4_fixed_rate_clks,
diff --git a/drivers/clk/samsung/clk-exynos4412-isp.c b/drivers/clk/samsung/clk-exynos4412-isp.c
index 471a6fb82670..1470c15e95da 100644
--- a/drivers/clk/samsung/clk-exynos4412-isp.c
+++ b/drivers/clk/samsung/clk-exynos4412-isp.c
@@ -121,8 +121,7 @@ static int __init exynos4x12_isp_clk_probe(struct platform_device *pdev)
if (!exynos4x12_save_isp)
return -ENOMEM;
- ctx = samsung_clk_init(np, reg_base, CLK_NR_ISP_CLKS);
- ctx->dev = dev;
+ ctx = samsung_clk_init(dev, reg_base, CLK_NR_ISP_CLKS);
platform_set_drvdata(pdev, ctx);
diff --git a/drivers/clk/samsung/clk-exynos5250.c b/drivers/clk/samsung/clk-exynos5250.c
index 113df773ee44..92fb09922f28 100644
--- a/drivers/clk/samsung/clk-exynos5250.c
+++ b/drivers/clk/samsung/clk-exynos5250.c
@@ -797,7 +797,7 @@ static void __init exynos5250_clk_init(struct device_node *np)
panic("%s: unable to determine soc\n", __func__);
}
- ctx = samsung_clk_init(np, reg_base, CLK_NR_CLKS);
+ ctx = samsung_clk_init(NULL, reg_base, CLK_NR_CLKS);
hws = ctx->clk_data.hws;
samsung_clk_of_register_fixed_ext(ctx, exynos5250_fixed_rate_ext_clks,
@@ -815,8 +815,7 @@ static void __init exynos5250_clk_init(struct device_node *np)
exynos5250_plls[vpll].rate_table = vpll_24mhz_tbl;
samsung_clk_register_pll(ctx, exynos5250_plls,
- ARRAY_SIZE(exynos5250_plls),
- reg_base);
+ ARRAY_SIZE(exynos5250_plls));
samsung_clk_register_fixed_rate(ctx, exynos5250_fixed_rate_clks,
ARRAY_SIZE(exynos5250_fixed_rate_clks));
samsung_clk_register_fixed_factor(ctx, exynos5250_fixed_factor_clks,
diff --git a/drivers/clk/samsung/clk-exynos5420.c b/drivers/clk/samsung/clk-exynos5420.c
index caad74dee297..1e0cbf762408 100644
--- a/drivers/clk/samsung/clk-exynos5420.c
+++ b/drivers/clk/samsung/clk-exynos5420.c
@@ -1587,7 +1587,7 @@ static void __init exynos5x_clk_init(struct device_node *np,
exynos5x_soc = soc;
- ctx = samsung_clk_init(np, reg_base, CLK_NR_CLKS);
+ ctx = samsung_clk_init(NULL, reg_base, CLK_NR_CLKS);
hws = ctx->clk_data.hws;
samsung_clk_of_register_fixed_ext(ctx, exynos5x_fixed_rate_ext_clks,
@@ -1606,8 +1606,7 @@ static void __init exynos5x_clk_init(struct device_node *np,
else
exynos5x_plls[bpll].rate_table = exynos5422_bpll_rate_table;
- samsung_clk_register_pll(ctx, exynos5x_plls, ARRAY_SIZE(exynos5x_plls),
- reg_base);
+ samsung_clk_register_pll(ctx, exynos5x_plls, ARRAY_SIZE(exynos5x_plls));
samsung_clk_register_fixed_rate(ctx, exynos5x_fixed_rate_clks,
ARRAY_SIZE(exynos5x_fixed_rate_clks));
samsung_clk_register_fixed_factor(ctx, exynos5x_fixed_factor_clks,
diff --git a/drivers/clk/samsung/clk-exynos5433.c b/drivers/clk/samsung/clk-exynos5433.c
index f9daae20f393..ed43233649ae 100644
--- a/drivers/clk/samsung/clk-exynos5433.c
+++ b/drivers/clk/samsung/clk-exynos5433.c
@@ -10,7 +10,6 @@
#include <linux/clk-provider.h>
#include <linux/of.h>
#include <linux/of_address.h>
-#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/slab.h>
@@ -19,6 +18,7 @@
#include "clk.h"
#include "clk-cpu.h"
+#include "clk-exynos-arm64.h"
#include "clk-pll.h"
/*
@@ -5478,160 +5478,9 @@ static const struct samsung_cmu_info imem_cmu_info __initconst = {
.clk_name = "aclk_imem_200",
};
-struct exynos5433_cmu_data {
- struct samsung_clk_reg_dump *clk_save;
- unsigned int nr_clk_save;
- const struct samsung_clk_reg_dump *clk_suspend;
- unsigned int nr_clk_suspend;
-
- struct clk *clk;
- struct clk **pclks;
- int nr_pclks;
-
- /* must be the last entry */
- struct samsung_clk_provider ctx;
-};
-
-static int __maybe_unused exynos5433_cmu_suspend(struct device *dev)
-{
- struct exynos5433_cmu_data *data = dev_get_drvdata(dev);
- int i;
-
- samsung_clk_save(data->ctx.reg_base, data->clk_save,
- data->nr_clk_save);
-
- for (i = 0; i < data->nr_pclks; i++)
- clk_prepare_enable(data->pclks[i]);
-
- /* for suspend some registers have to be set to certain values */
- samsung_clk_restore(data->ctx.reg_base, data->clk_suspend,
- data->nr_clk_suspend);
-
- for (i = 0; i < data->nr_pclks; i++)
- clk_disable_unprepare(data->pclks[i]);
-
- clk_disable_unprepare(data->clk);
-
- return 0;
-}
-
-static int __maybe_unused exynos5433_cmu_resume(struct device *dev)
-{
- struct exynos5433_cmu_data *data = dev_get_drvdata(dev);
- int i;
-
- clk_prepare_enable(data->clk);
-
- for (i = 0; i < data->nr_pclks; i++)
- clk_prepare_enable(data->pclks[i]);
-
- samsung_clk_restore(data->ctx.reg_base, data->clk_save,
- data->nr_clk_save);
-
- for (i = 0; i < data->nr_pclks; i++)
- clk_disable_unprepare(data->pclks[i]);
-
- return 0;
-}
-
static int __init exynos5433_cmu_probe(struct platform_device *pdev)
{
- const struct samsung_cmu_info *info;
- struct exynos5433_cmu_data *data;
- struct samsung_clk_provider *ctx;
- struct device *dev = &pdev->dev;
- void __iomem *reg_base;
- int i;
-
- info = of_device_get_match_data(dev);
-
- data = devm_kzalloc(dev,
- struct_size(data, ctx.clk_data.hws, info->nr_clk_ids),
- GFP_KERNEL);
- if (!data)
- return -ENOMEM;
- ctx = &data->ctx;
-
- reg_base = devm_platform_ioremap_resource(pdev, 0);
- if (IS_ERR(reg_base))
- return PTR_ERR(reg_base);
-
- for (i = 0; i < info->nr_clk_ids; ++i)
- ctx->clk_data.hws[i] = ERR_PTR(-ENOENT);
-
- ctx->clk_data.num = info->nr_clk_ids;
- ctx->reg_base = reg_base;
- ctx->dev = dev;
- spin_lock_init(&ctx->lock);
-
- data->clk_save = samsung_clk_alloc_reg_dump(info->clk_regs,
- info->nr_clk_regs);
- if (!data->clk_save)
- return -ENOMEM;
- data->nr_clk_save = info->nr_clk_regs;
- data->clk_suspend = info->suspend_regs;
- data->nr_clk_suspend = info->nr_suspend_regs;
- data->nr_pclks = of_clk_get_parent_count(dev->of_node);
-
- if (data->nr_pclks > 0) {
- data->pclks = devm_kcalloc(dev, sizeof(struct clk *),
- data->nr_pclks, GFP_KERNEL);
- if (!data->pclks) {
- kfree(data->clk_save);
- return -ENOMEM;
- }
- for (i = 0; i < data->nr_pclks; i++) {
- struct clk *clk = of_clk_get(dev->of_node, i);
-
- if (IS_ERR(clk)) {
- kfree(data->clk_save);
- while (--i >= 0)
- clk_put(data->pclks[i]);
- return PTR_ERR(clk);
- }
- data->pclks[i] = clk;
- }
- }
-
- if (info->clk_name)
- data->clk = clk_get(dev, info->clk_name);
- clk_prepare_enable(data->clk);
-
- platform_set_drvdata(pdev, data);
-
- /*
- * Enable runtime PM here to allow the clock core using runtime PM
- * for the registered clocks. Additionally, we increase the runtime
- * PM usage count before registering the clocks, to prevent the
- * clock core from runtime suspending the device.
- */
- pm_runtime_get_noresume(dev);
- pm_runtime_set_active(dev);
- pm_runtime_enable(dev);
-
- if (info->pll_clks)
- samsung_clk_register_pll(ctx, info->pll_clks, info->nr_pll_clks,
- reg_base);
- if (info->mux_clks)
- samsung_clk_register_mux(ctx, info->mux_clks,
- info->nr_mux_clks);
- if (info->div_clks)
- samsung_clk_register_div(ctx, info->div_clks,
- info->nr_div_clks);
- if (info->gate_clks)
- samsung_clk_register_gate(ctx, info->gate_clks,
- info->nr_gate_clks);
- if (info->fixed_clks)
- samsung_clk_register_fixed_rate(ctx, info->fixed_clks,
- info->nr_fixed_clks);
- if (info->fixed_factor_clks)
- samsung_clk_register_fixed_factor(ctx, info->fixed_factor_clks,
- info->nr_fixed_factor_clks);
-
- samsung_clk_of_add_provider(dev->of_node, ctx);
- pm_runtime_put_sync(dev);
-
- return 0;
+ return exynos_arm64_register_cmu_pm(pdev, false);
}
static const struct of_device_id exynos5433_cmu_of_match[] = {
@@ -5679,7 +5528,7 @@ static const struct of_device_id exynos5433_cmu_of_match[] = {
};
static const struct dev_pm_ops exynos5433_cmu_pm_ops = {
- SET_RUNTIME_PM_OPS(exynos5433_cmu_suspend, exynos5433_cmu_resume,
+ SET_RUNTIME_PM_OPS(exynos_arm64_cmu_suspend, exynos_arm64_cmu_resume,
NULL)
SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
pm_runtime_force_resume)
diff --git a/drivers/clk/samsung/clk-exynos850.c b/drivers/clk/samsung/clk-exynos850.c
index 541761e96aeb..98b23af7324d 100644
--- a/drivers/clk/samsung/clk-exynos850.c
+++ b/drivers/clk/samsung/clk-exynos850.c
@@ -36,6 +36,7 @@
#define CLK_CON_MUX_MUX_CLKCMU_CORE_MMC_EMBD 0x101c
#define CLK_CON_MUX_MUX_CLKCMU_CORE_SSS 0x1020
#define CLK_CON_MUX_MUX_CLKCMU_DPU 0x1034
+#define CLK_CON_MUX_MUX_CLKCMU_G3D_SWITCH 0x1038
#define CLK_CON_MUX_MUX_CLKCMU_HSI_BUS 0x103c
#define CLK_CON_MUX_MUX_CLKCMU_HSI_MMC_CARD 0x1040
#define CLK_CON_MUX_MUX_CLKCMU_HSI_USB20DRD 0x1044
@@ -57,6 +58,7 @@
#define CLK_CON_DIV_CLKCMU_CORE_MMC_EMBD 0x1828
#define CLK_CON_DIV_CLKCMU_CORE_SSS 0x182c
#define CLK_CON_DIV_CLKCMU_DPU 0x1840
+#define CLK_CON_DIV_CLKCMU_G3D_SWITCH 0x1844
#define CLK_CON_DIV_CLKCMU_HSI_BUS 0x1848
#define CLK_CON_DIV_CLKCMU_HSI_MMC_CARD 0x184c
#define CLK_CON_DIV_CLKCMU_HSI_USB20DRD 0x1850
@@ -84,6 +86,7 @@
#define CLK_CON_GAT_GATE_CLKCMU_CORE_MMC_EMBD 0x2024
#define CLK_CON_GAT_GATE_CLKCMU_CORE_SSS 0x2028
#define CLK_CON_GAT_GATE_CLKCMU_DPU 0x203c
+#define CLK_CON_GAT_GATE_CLKCMU_G3D_SWITCH 0x2040
#define CLK_CON_GAT_GATE_CLKCMU_HSI_BUS 0x2044
#define CLK_CON_GAT_GATE_CLKCMU_HSI_MMC_CARD 0x2048
#define CLK_CON_GAT_GATE_CLKCMU_HSI_USB20DRD 0x204c
@@ -116,6 +119,7 @@ static const unsigned long top_clk_regs[] __initconst = {
CLK_CON_MUX_MUX_CLKCMU_CORE_MMC_EMBD,
CLK_CON_MUX_MUX_CLKCMU_CORE_SSS,
CLK_CON_MUX_MUX_CLKCMU_DPU,
+ CLK_CON_MUX_MUX_CLKCMU_G3D_SWITCH,
CLK_CON_MUX_MUX_CLKCMU_HSI_BUS,
CLK_CON_MUX_MUX_CLKCMU_HSI_MMC_CARD,
CLK_CON_MUX_MUX_CLKCMU_HSI_USB20DRD,
@@ -137,6 +141,7 @@ static const unsigned long top_clk_regs[] __initconst = {
CLK_CON_DIV_CLKCMU_CORE_MMC_EMBD,
CLK_CON_DIV_CLKCMU_CORE_SSS,
CLK_CON_DIV_CLKCMU_DPU,
+ CLK_CON_DIV_CLKCMU_G3D_SWITCH,
CLK_CON_DIV_CLKCMU_HSI_BUS,
CLK_CON_DIV_CLKCMU_HSI_MMC_CARD,
CLK_CON_DIV_CLKCMU_HSI_USB20DRD,
@@ -164,6 +169,7 @@ static const unsigned long top_clk_regs[] __initconst = {
CLK_CON_GAT_GATE_CLKCMU_CORE_MMC_EMBD,
CLK_CON_GAT_GATE_CLKCMU_CORE_SSS,
CLK_CON_GAT_GATE_CLKCMU_DPU,
+ CLK_CON_GAT_GATE_CLKCMU_G3D_SWITCH,
CLK_CON_GAT_GATE_CLKCMU_HSI_BUS,
CLK_CON_GAT_GATE_CLKCMU_HSI_MMC_CARD,
CLK_CON_GAT_GATE_CLKCMU_HSI_USB20DRD,
@@ -216,6 +222,9 @@ PNAME(mout_core_mmc_embd_p) = { "oscclk", "dout_shared0_div2",
"oscclk", "oscclk" };
PNAME(mout_core_sss_p) = { "dout_shared0_div3", "dout_shared1_div3",
"dout_shared0_div4", "dout_shared1_div4" };
+/* List of parent clocks for Muxes in CMU_TOP: for CMU_G3D */
+PNAME(mout_g3d_switch_p) = { "dout_shared0_div2", "dout_shared1_div2",
+ "dout_shared0_div3", "dout_shared1_div3" };
/* List of parent clocks for Muxes in CMU_TOP: for CMU_HSI */
PNAME(mout_hsi_bus_p) = { "dout_shared0_div2", "dout_shared1_div2" };
PNAME(mout_hsi_mmc_card_p) = { "oscclk", "dout_shared0_div2",
@@ -283,6 +292,10 @@ static const struct samsung_mux_clock top_mux_clks[] __initconst = {
MUX(CLK_MOUT_DPU, "mout_dpu", mout_dpu_p,
CLK_CON_MUX_MUX_CLKCMU_DPU, 0, 2),
+ /* G3D */
+ MUX(CLK_MOUT_G3D_SWITCH, "mout_g3d_switch", mout_g3d_switch_p,
+ CLK_CON_MUX_MUX_CLKCMU_G3D_SWITCH, 0, 2),
+
/* HSI */
MUX(CLK_MOUT_HSI_BUS, "mout_hsi_bus", mout_hsi_bus_p,
CLK_CON_MUX_MUX_CLKCMU_HSI_BUS, 0, 1),
@@ -357,6 +370,10 @@ static const struct samsung_div_clock top_div_clks[] __initconst = {
DIV(CLK_DOUT_DPU, "dout_dpu", "gout_dpu",
CLK_CON_DIV_CLKCMU_DPU, 0, 4),
+ /* G3D */
+ DIV(CLK_DOUT_G3D_SWITCH, "dout_g3d_switch", "gout_g3d_switch",
+ CLK_CON_DIV_CLKCMU_G3D_SWITCH, 0, 3),
+
/* HSI */
DIV(CLK_DOUT_HSI_BUS, "dout_hsi_bus", "gout_hsi_bus",
CLK_CON_DIV_CLKCMU_HSI_BUS, 0, 4),
@@ -417,6 +434,10 @@ static const struct samsung_gate_clock top_gate_clks[] __initconst = {
GATE(CLK_GOUT_DPU, "gout_dpu", "mout_dpu",
CLK_CON_GAT_GATE_CLKCMU_DPU, 21, 0, 0),
+ /* G3D */
+ GATE(CLK_GOUT_G3D_SWITCH, "gout_g3d_switch", "mout_g3d_switch",
+ CLK_CON_GAT_GATE_CLKCMU_G3D_SWITCH, 21, 0, 0),
+
/* HSI */
GATE(CLK_GOUT_HSI_BUS, "gout_hsi_bus", "mout_hsi_bus",
CLK_CON_GAT_GATE_CLKCMU_HSI_BUS, 21, 0, 0),
@@ -591,7 +612,7 @@ static const struct samsung_gate_clock apm_gate_clks[] __initconst = {
CLK_CON_GAT_GOUT_APM_APBIF_GPIO_ALIVE_PCLK, 21, CLK_IGNORE_UNUSED,
0),
GATE(CLK_GOUT_PMU_ALIVE_PCLK, "gout_pmu_alive_pclk", "dout_apm_bus",
- CLK_CON_GAT_GOUT_APM_APBIF_PMU_ALIVE_PCLK, 21, 0, 0),
+ CLK_CON_GAT_GOUT_APM_APBIF_PMU_ALIVE_PCLK, 21, CLK_IS_CRITICAL, 0),
GATE(CLK_GOUT_SYSREG_APM_PCLK, "gout_sysreg_apm_pclk", "dout_apm_bus",
CLK_CON_GAT_GOUT_APM_SYSREG_APM_PCLK, 21, 0, 0),
};
@@ -653,6 +674,7 @@ static const struct samsung_cmu_info apm_cmu_info __initconst = {
#define CLK_CON_GAT_GOUT_AUD_ABOX_BCLK_UAIF4 0x2014
#define CLK_CON_GAT_GOUT_AUD_ABOX_BCLK_UAIF5 0x2018
#define CLK_CON_GAT_GOUT_AUD_ABOX_BCLK_UAIF6 0x201c
+#define CLK_CON_GAT_CLK_AUD_CMU_AUD_PCLK 0x2020
#define CLK_CON_GAT_GOUT_AUD_ABOX_ACLK 0x2048
#define CLK_CON_GAT_GOUT_AUD_ABOX_BCLK_SPDY 0x204c
#define CLK_CON_GAT_GOUT_AUD_ABOX_CCLK_ASB 0x2050
@@ -708,6 +730,7 @@ static const unsigned long aud_clk_regs[] __initconst = {
CLK_CON_GAT_GOUT_AUD_ABOX_BCLK_UAIF4,
CLK_CON_GAT_GOUT_AUD_ABOX_BCLK_UAIF5,
CLK_CON_GAT_GOUT_AUD_ABOX_BCLK_UAIF6,
+ CLK_CON_GAT_CLK_AUD_CMU_AUD_PCLK,
CLK_CON_GAT_GOUT_AUD_ABOX_ACLK,
CLK_CON_GAT_GOUT_AUD_ABOX_BCLK_SPDY,
CLK_CON_GAT_GOUT_AUD_ABOX_CCLK_ASB,
@@ -827,6 +850,9 @@ static const struct samsung_div_clock aud_div_clks[] __initconst = {
};
static const struct samsung_gate_clock aud_gate_clks[] __initconst = {
+ GATE(CLK_GOUT_AUD_CMU_AUD_PCLK, "gout_aud_cmu_aud_pclk",
+ "dout_aud_busd",
+ CLK_CON_GAT_CLK_AUD_CMU_AUD_PCLK, 21, CLK_IGNORE_UNUSED, 0),
GATE(CLK_GOUT_AUD_CA32_CCLK, "gout_aud_ca32_cclk", "mout_aud_cpu_hch",
CLK_CON_GAT_GOUT_AUD_ABOX_CCLK_CA32, 21, 0, 0),
GATE(CLK_GOUT_AUD_ASB_CCLK, "gout_aud_asb_cclk", "dout_aud_cpu_aclk",
@@ -992,6 +1018,102 @@ static const struct samsung_cmu_info cmgp_cmu_info __initconst = {
.clk_name = "gout_clkcmu_cmgp_bus",
};
+/* ---- CMU_G3D ------------------------------------------------------------- */
+
+/* Register Offset definitions for CMU_G3D (0x11400000) */
+#define PLL_LOCKTIME_PLL_G3D 0x0000
+#define PLL_CON0_PLL_G3D 0x0100
+#define PLL_CON3_PLL_G3D 0x010c
+#define PLL_CON0_MUX_CLKCMU_G3D_SWITCH_USER 0x0600
+#define CLK_CON_MUX_MUX_CLK_G3D_BUSD 0x1000
+#define CLK_CON_DIV_DIV_CLK_G3D_BUSP 0x1804
+#define CLK_CON_GAT_CLK_G3D_CMU_G3D_PCLK 0x2000
+#define CLK_CON_GAT_CLK_G3D_GPU_CLK 0x2004
+#define CLK_CON_GAT_GOUT_G3D_TZPC_PCLK 0x200c
+#define CLK_CON_GAT_GOUT_G3D_GRAY2BIN_CLK 0x2010
+#define CLK_CON_GAT_GOUT_G3D_BUSD_CLK 0x2024
+#define CLK_CON_GAT_GOUT_G3D_BUSP_CLK 0x2028
+#define CLK_CON_GAT_GOUT_G3D_SYSREG_PCLK 0x202c
+
+static const unsigned long g3d_clk_regs[] __initconst = {
+ PLL_LOCKTIME_PLL_G3D,
+ PLL_CON0_PLL_G3D,
+ PLL_CON3_PLL_G3D,
+ PLL_CON0_MUX_CLKCMU_G3D_SWITCH_USER,
+ CLK_CON_MUX_MUX_CLK_G3D_BUSD,
+ CLK_CON_DIV_DIV_CLK_G3D_BUSP,
+ CLK_CON_GAT_CLK_G3D_CMU_G3D_PCLK,
+ CLK_CON_GAT_CLK_G3D_GPU_CLK,
+ CLK_CON_GAT_GOUT_G3D_TZPC_PCLK,
+ CLK_CON_GAT_GOUT_G3D_GRAY2BIN_CLK,
+ CLK_CON_GAT_GOUT_G3D_BUSD_CLK,
+ CLK_CON_GAT_GOUT_G3D_BUSP_CLK,
+ CLK_CON_GAT_GOUT_G3D_SYSREG_PCLK,
+};
+
+/* List of parent clocks for Muxes in CMU_G3D */
+PNAME(mout_g3d_pll_p) = { "oscclk", "fout_g3d_pll" };
+PNAME(mout_g3d_switch_user_p) = { "oscclk", "dout_g3d_switch" };
+PNAME(mout_g3d_busd_p) = { "mout_g3d_pll", "mout_g3d_switch_user" };
+
+/*
+ * Do not provide PLL table to PLL_G3D, as MANUAL_PLL_CTRL bit is not set
+ * for that PLL by default, so set_rate operation would fail.
+ */
+static const struct samsung_pll_clock g3d_pll_clks[] __initconst = {
+ PLL(pll_0818x, CLK_FOUT_G3D_PLL, "fout_g3d_pll", "oscclk",
+ PLL_LOCKTIME_PLL_G3D, PLL_CON3_PLL_G3D, NULL),
+};
+
+static const struct samsung_mux_clock g3d_mux_clks[] __initconst = {
+ MUX(CLK_MOUT_G3D_PLL, "mout_g3d_pll", mout_g3d_pll_p,
+ PLL_CON0_PLL_G3D, 4, 1),
+ MUX(CLK_MOUT_G3D_SWITCH_USER, "mout_g3d_switch_user",
+ mout_g3d_switch_user_p,
+ PLL_CON0_MUX_CLKCMU_G3D_SWITCH_USER, 4, 1),
+ MUX(CLK_MOUT_G3D_BUSD, "mout_g3d_busd", mout_g3d_busd_p,
+ CLK_CON_MUX_MUX_CLK_G3D_BUSD, 0, 1),
+};
+
+static const struct samsung_div_clock g3d_div_clks[] __initconst = {
+ DIV(CLK_DOUT_G3D_BUSP, "dout_g3d_busp", "mout_g3d_busd",
+ CLK_CON_DIV_DIV_CLK_G3D_BUSP, 0, 3),
+};
+
+static const struct samsung_gate_clock g3d_gate_clks[] __initconst = {
+ GATE(CLK_GOUT_G3D_CMU_G3D_PCLK, "gout_g3d_cmu_g3d_pclk",
+ "dout_g3d_busp",
+ CLK_CON_GAT_CLK_G3D_CMU_G3D_PCLK, 21, CLK_IGNORE_UNUSED, 0),
+ GATE(CLK_GOUT_G3D_GPU_CLK, "gout_g3d_gpu_clk", "mout_g3d_busd",
+ CLK_CON_GAT_CLK_G3D_GPU_CLK, 21, 0, 0),
+ GATE(CLK_GOUT_G3D_TZPC_PCLK, "gout_g3d_tzpc_pclk", "dout_g3d_busp",
+ CLK_CON_GAT_GOUT_G3D_TZPC_PCLK, 21, 0, 0),
+ GATE(CLK_GOUT_G3D_GRAY2BIN_CLK, "gout_g3d_gray2bin_clk",
+ "mout_g3d_busd",
+ CLK_CON_GAT_GOUT_G3D_GRAY2BIN_CLK, 21, 0, 0),
+ GATE(CLK_GOUT_G3D_BUSD_CLK, "gout_g3d_busd_clk", "mout_g3d_busd",
+ CLK_CON_GAT_GOUT_G3D_BUSD_CLK, 21, 0, 0),
+ GATE(CLK_GOUT_G3D_BUSP_CLK, "gout_g3d_busp_clk", "dout_g3d_busp",
+ CLK_CON_GAT_GOUT_G3D_BUSP_CLK, 21, 0, 0),
+ GATE(CLK_GOUT_G3D_SYSREG_PCLK, "gout_g3d_sysreg_pclk", "dout_g3d_busp",
+ CLK_CON_GAT_GOUT_G3D_SYSREG_PCLK, 21, 0, 0),
+};
+
+static const struct samsung_cmu_info g3d_cmu_info __initconst = {
+ .pll_clks = g3d_pll_clks,
+ .nr_pll_clks = ARRAY_SIZE(g3d_pll_clks),
+ .mux_clks = g3d_mux_clks,
+ .nr_mux_clks = ARRAY_SIZE(g3d_mux_clks),
+ .div_clks = g3d_div_clks,
+ .nr_div_clks = ARRAY_SIZE(g3d_div_clks),
+ .gate_clks = g3d_gate_clks,
+ .nr_gate_clks = ARRAY_SIZE(g3d_gate_clks),
+ .nr_clk_ids = G3D_NR_CLK,
+ .clk_regs = g3d_clk_regs,
+ .nr_clk_regs = ARRAY_SIZE(g3d_clk_regs),
+ .clk_name = "dout_g3d_switch",
+};
+
/* ---- CMU_HSI ------------------------------------------------------------- */
/* Register Offset definitions for CMU_HSI (0x13400000) */
@@ -999,12 +1121,15 @@ static const struct samsung_cmu_info cmgp_cmu_info __initconst = {
#define PLL_CON0_MUX_CLKCMU_HSI_MMC_CARD_USER 0x0610
#define PLL_CON0_MUX_CLKCMU_HSI_USB20DRD_USER 0x0620
#define CLK_CON_MUX_MUX_CLK_HSI_RTC 0x1000
+#define CLK_CON_GAT_CLK_HSI_CMU_HSI_PCLK 0x2000
#define CLK_CON_GAT_HSI_USB20DRD_TOP_I_RTC_CLK__ALV 0x2008
#define CLK_CON_GAT_HSI_USB20DRD_TOP_I_REF_CLK_50 0x200c
#define CLK_CON_GAT_HSI_USB20DRD_TOP_I_PHY_REFCLK_26 0x2010
#define CLK_CON_GAT_GOUT_HSI_GPIO_HSI_PCLK 0x2018
#define CLK_CON_GAT_GOUT_HSI_MMC_CARD_I_ACLK 0x2024
#define CLK_CON_GAT_GOUT_HSI_MMC_CARD_SDCLKIN 0x2028
+#define CLK_CON_GAT_GOUT_HSI_PPMU_ACLK 0x202c
+#define CLK_CON_GAT_GOUT_HSI_PPMU_PCLK 0x2030
#define CLK_CON_GAT_GOUT_HSI_SYSREG_HSI_PCLK 0x2038
#define CLK_CON_GAT_GOUT_HSI_USB20DRD_TOP_ACLK_PHYCTRL_20 0x203c
#define CLK_CON_GAT_GOUT_HSI_USB20DRD_TOP_BUS_CLK_EARLY 0x2040
@@ -1014,12 +1139,15 @@ static const unsigned long hsi_clk_regs[] __initconst = {
PLL_CON0_MUX_CLKCMU_HSI_MMC_CARD_USER,
PLL_CON0_MUX_CLKCMU_HSI_USB20DRD_USER,
CLK_CON_MUX_MUX_CLK_HSI_RTC,
+ CLK_CON_GAT_CLK_HSI_CMU_HSI_PCLK,
CLK_CON_GAT_HSI_USB20DRD_TOP_I_RTC_CLK__ALV,
CLK_CON_GAT_HSI_USB20DRD_TOP_I_REF_CLK_50,
CLK_CON_GAT_HSI_USB20DRD_TOP_I_PHY_REFCLK_26,
CLK_CON_GAT_GOUT_HSI_GPIO_HSI_PCLK,
CLK_CON_GAT_GOUT_HSI_MMC_CARD_I_ACLK,
CLK_CON_GAT_GOUT_HSI_MMC_CARD_SDCLKIN,
+ CLK_CON_GAT_GOUT_HSI_PPMU_ACLK,
+ CLK_CON_GAT_GOUT_HSI_PPMU_PCLK,
CLK_CON_GAT_GOUT_HSI_SYSREG_HSI_PCLK,
CLK_CON_GAT_GOUT_HSI_USB20DRD_TOP_ACLK_PHYCTRL_20,
CLK_CON_GAT_GOUT_HSI_USB20DRD_TOP_BUS_CLK_EARLY,
@@ -1045,6 +1173,10 @@ static const struct samsung_mux_clock hsi_mux_clks[] __initconst = {
};
static const struct samsung_gate_clock hsi_gate_clks[] __initconst = {
+ /* TODO: Should be enabled in corresponding driver */
+ GATE(CLK_GOUT_HSI_CMU_HSI_PCLK, "gout_hsi_cmu_hsi_pclk",
+ "mout_hsi_bus_user",
+ CLK_CON_GAT_CLK_HSI_CMU_HSI_PCLK, 21, CLK_IGNORE_UNUSED, 0),
GATE(CLK_GOUT_USB_RTC_CLK, "gout_usb_rtc", "mout_hsi_rtc",
CLK_CON_GAT_HSI_USB20DRD_TOP_I_RTC_CLK__ALV, 21, 0, 0),
GATE(CLK_GOUT_USB_REF_CLK, "gout_usb_ref", "mout_hsi_usb20drd_user",
@@ -1059,6 +1191,10 @@ static const struct samsung_gate_clock hsi_gate_clks[] __initconst = {
GATE(CLK_GOUT_MMC_CARD_SDCLKIN, "gout_mmc_card_sdclkin",
"mout_hsi_mmc_card_user",
CLK_CON_GAT_GOUT_HSI_MMC_CARD_SDCLKIN, 21, CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_GOUT_HSI_PPMU_ACLK, "gout_hsi_ppmu_aclk", "mout_hsi_bus_user",
+ CLK_CON_GAT_GOUT_HSI_PPMU_ACLK, 21, 0, 0),
+ GATE(CLK_GOUT_HSI_PPMU_PCLK, "gout_hsi_ppmu_pclk", "mout_hsi_bus_user",
+ CLK_CON_GAT_GOUT_HSI_PPMU_PCLK, 21, 0, 0),
GATE(CLK_GOUT_SYSREG_HSI_PCLK, "gout_sysreg_hsi_pclk",
"mout_hsi_bus_user",
CLK_CON_GAT_GOUT_HSI_SYSREG_HSI_PCLK, 21, 0, 0),
@@ -1701,6 +1837,9 @@ static const struct of_device_id exynos850_cmu_of_match[] = {
.compatible = "samsung,exynos850-cmu-cmgp",
.data = &cmgp_cmu_info,
}, {
+ .compatible = "samsung,exynos850-cmu-g3d",
+ .data = &g3d_cmu_info,
+ }, {
.compatible = "samsung,exynos850-cmu-hsi",
.data = &hsi_cmu_info,
}, {
diff --git a/drivers/clk/samsung/clk-pll.c b/drivers/clk/samsung/clk-pll.c
index df7812371d70..74934c6182ce 100644
--- a/drivers/clk/samsung/clk-pll.c
+++ b/drivers/clk/samsung/clk-pll.c
@@ -1259,8 +1259,7 @@ static const struct clk_ops samsung_pll2650xx_clk_min_ops = {
};
static void __init _samsung_clk_register_pll(struct samsung_clk_provider *ctx,
- const struct samsung_pll_clock *pll_clk,
- void __iomem *base)
+ const struct samsung_pll_clock *pll_clk)
{
struct samsung_clk_pll *pll;
struct clk_init_data init;
@@ -1315,6 +1314,7 @@ static void __init _samsung_clk_register_pll(struct samsung_clk_provider *ctx,
init.ops = &samsung_pll35xx_clk_ops;
break;
case pll_1417x:
+ case pll_0818x:
case pll_0822x:
pll->enable_offs = PLL0822X_ENABLE_SHIFT;
pll->lock_offs = PLL0822X_LOCK_STAT_SHIFT;
@@ -1395,8 +1395,8 @@ static void __init _samsung_clk_register_pll(struct samsung_clk_provider *ctx,
pll->hw.init = &init;
pll->type = pll_clk->type;
- pll->lock_reg = base + pll_clk->lock_offset;
- pll->con_reg = base + pll_clk->con_offset;
+ pll->lock_reg = ctx->reg_base + pll_clk->lock_offset;
+ pll->con_reg = ctx->reg_base + pll_clk->con_offset;
ret = clk_hw_register(ctx->dev, &pll->hw);
if (ret) {
@@ -1412,10 +1412,10 @@ static void __init _samsung_clk_register_pll(struct samsung_clk_provider *ctx,
void __init samsung_clk_register_pll(struct samsung_clk_provider *ctx,
const struct samsung_pll_clock *pll_list,
- unsigned int nr_pll, void __iomem *base)
+ unsigned int nr_pll)
{
int cnt;
for (cnt = 0; cnt < nr_pll; cnt++)
- _samsung_clk_register_pll(ctx, &pll_list[cnt], base);
+ _samsung_clk_register_pll(ctx, &pll_list[cnt]);
}
diff --git a/drivers/clk/samsung/clk-pll.h b/drivers/clk/samsung/clk-pll.h
index 5d5a58d40e7e..0725d485c6ee 100644
--- a/drivers/clk/samsung/clk-pll.h
+++ b/drivers/clk/samsung/clk-pll.h
@@ -34,6 +34,7 @@ enum samsung_pll_type {
pll_1451x,
pll_1452x,
pll_1460x,
+ pll_0818x,
pll_0822x,
pll_0831x,
pll_142xx,
diff --git a/drivers/clk/samsung/clk-s3c64xx.c b/drivers/clk/samsung/clk-s3c64xx.c
index d6b432a26d63..d27a1f73f077 100644
--- a/drivers/clk/samsung/clk-s3c64xx.c
+++ b/drivers/clk/samsung/clk-s3c64xx.c
@@ -405,7 +405,7 @@ void __init s3c64xx_clk_init(struct device_node *np, unsigned long xtal_f,
panic("%s: failed to map registers\n", __func__);
}
- ctx = samsung_clk_init(np, reg_base, NR_CLKS);
+ ctx = samsung_clk_init(NULL, reg_base, NR_CLKS);
hws = ctx->clk_data.hws;
/* Register external clocks. */
@@ -414,7 +414,7 @@ void __init s3c64xx_clk_init(struct device_node *np, unsigned long xtal_f,
/* Register PLLs. */
samsung_clk_register_pll(ctx, s3c64xx_pll_clks,
- ARRAY_SIZE(s3c64xx_pll_clks), reg_base);
+ ARRAY_SIZE(s3c64xx_pll_clks));
/* Register common internal clocks. */
samsung_clk_register_fixed_rate(ctx, s3c64xx_fixed_rate_clks,
diff --git a/drivers/clk/samsung/clk-s5pv210.c b/drivers/clk/samsung/clk-s5pv210.c
index 4425186bdcab..cd85342e4ddb 100644
--- a/drivers/clk/samsung/clk-s5pv210.c
+++ b/drivers/clk/samsung/clk-s5pv210.c
@@ -743,7 +743,7 @@ static void __init __s5pv210_clk_init(struct device_node *np,
struct samsung_clk_provider *ctx;
struct clk_hw **hws;
- ctx = samsung_clk_init(np, reg_base, NR_CLKS);
+ ctx = samsung_clk_init(NULL, reg_base, NR_CLKS);
hws = ctx->clk_data.hws;
samsung_clk_register_mux(ctx, early_mux_clks,
@@ -753,7 +753,7 @@ static void __init __s5pv210_clk_init(struct device_node *np,
samsung_clk_register_fixed_rate(ctx, s5p6442_frate_clks,
ARRAY_SIZE(s5p6442_frate_clks));
samsung_clk_register_pll(ctx, s5p6442_pll_clks,
- ARRAY_SIZE(s5p6442_pll_clks), reg_base);
+ ARRAY_SIZE(s5p6442_pll_clks));
samsung_clk_register_mux(ctx, s5p6442_mux_clks,
ARRAY_SIZE(s5p6442_mux_clks));
samsung_clk_register_div(ctx, s5p6442_div_clks,
@@ -764,7 +764,7 @@ static void __init __s5pv210_clk_init(struct device_node *np,
samsung_clk_register_fixed_rate(ctx, s5pv210_frate_clks,
ARRAY_SIZE(s5pv210_frate_clks));
samsung_clk_register_pll(ctx, s5pv210_pll_clks,
- ARRAY_SIZE(s5pv210_pll_clks), reg_base);
+ ARRAY_SIZE(s5pv210_pll_clks));
samsung_clk_register_mux(ctx, s5pv210_mux_clks,
ARRAY_SIZE(s5pv210_mux_clks));
samsung_clk_register_div(ctx, s5pv210_div_clks,
diff --git a/drivers/clk/samsung/clk.c b/drivers/clk/samsung/clk.c
index bca4731b14ea..b6701905f254 100644
--- a/drivers/clk/samsung/clk.c
+++ b/drivers/clk/samsung/clk.c
@@ -53,8 +53,18 @@ struct samsung_clk_reg_dump *samsung_clk_alloc_reg_dump(
return rd;
}
-/* setup the essentials required to support clock lookup using ccf */
-struct samsung_clk_provider *__init samsung_clk_init(struct device_node *np,
+/**
+ * samsung_clk_init() - Create and initialize a clock provider object
+ * @dev: CMU device to enable runtime PM, or NULL if RPM is not needed
+ * @base: Start address (mapped) of CMU registers
+ * @nr_clks: Total clock count to allocate in clock provider object
+ *
+ * Setup the essentials required to support clock lookup using Common Clock
+ * Framework.
+ *
+ * Return: Allocated and initialized clock provider object.
+ */
+struct samsung_clk_provider * __init samsung_clk_init(struct device *dev,
void __iomem *base, unsigned long nr_clks)
{
struct samsung_clk_provider *ctx;
@@ -67,6 +77,7 @@ struct samsung_clk_provider *__init samsung_clk_init(struct device_node *np,
for (i = 0; i < nr_clks; ++i)
ctx->clk_data.hws[i] = ERR_PTR(-ENOENT);
+ ctx->dev = dev;
ctx->reg_base = base;
ctx->clk_data.num = nr_clks;
spin_lock_init(&ctx->lock);
@@ -324,6 +335,33 @@ void samsung_clk_extended_sleep_init(void __iomem *reg_base,
}
#endif
+/**
+ * samsung_cmu_register_clocks() - Register all clocks provided in CMU object
+ * @ctx: Clock provider object
+ * @cmu: CMU object with clocks to register
+ */
+void __init samsung_cmu_register_clocks(struct samsung_clk_provider *ctx,
+ const struct samsung_cmu_info *cmu)
+{
+ if (cmu->pll_clks)
+ samsung_clk_register_pll(ctx, cmu->pll_clks, cmu->nr_pll_clks);
+ if (cmu->mux_clks)
+ samsung_clk_register_mux(ctx, cmu->mux_clks, cmu->nr_mux_clks);
+ if (cmu->div_clks)
+ samsung_clk_register_div(ctx, cmu->div_clks, cmu->nr_div_clks);
+ if (cmu->gate_clks)
+ samsung_clk_register_gate(ctx, cmu->gate_clks,
+ cmu->nr_gate_clks);
+ if (cmu->fixed_clks)
+ samsung_clk_register_fixed_rate(ctx, cmu->fixed_clks,
+ cmu->nr_fixed_clks);
+ if (cmu->fixed_factor_clks)
+ samsung_clk_register_fixed_factor(ctx, cmu->fixed_factor_clks,
+ cmu->nr_fixed_factor_clks);
+ if (cmu->cpu_clks)
+ samsung_clk_register_cpu(ctx, cmu->cpu_clks, cmu->nr_cpu_clks);
+}
+
/*
* Common function which registers plls, muxes, dividers and gates
* for each CMU. It also add CMU register list to register cache.
@@ -341,31 +379,13 @@ struct samsung_clk_provider * __init samsung_cmu_register_one(
return NULL;
}
- ctx = samsung_clk_init(np, reg_base, cmu->nr_clk_ids);
+ ctx = samsung_clk_init(NULL, reg_base, cmu->nr_clk_ids);
+ samsung_cmu_register_clocks(ctx, cmu);
- if (cmu->pll_clks)
- samsung_clk_register_pll(ctx, cmu->pll_clks, cmu->nr_pll_clks,
- reg_base);
- if (cmu->mux_clks)
- samsung_clk_register_mux(ctx, cmu->mux_clks,
- cmu->nr_mux_clks);
- if (cmu->div_clks)
- samsung_clk_register_div(ctx, cmu->div_clks, cmu->nr_div_clks);
- if (cmu->gate_clks)
- samsung_clk_register_gate(ctx, cmu->gate_clks,
- cmu->nr_gate_clks);
- if (cmu->fixed_clks)
- samsung_clk_register_fixed_rate(ctx, cmu->fixed_clks,
- cmu->nr_fixed_clks);
- if (cmu->fixed_factor_clks)
- samsung_clk_register_fixed_factor(ctx, cmu->fixed_factor_clks,
- cmu->nr_fixed_factor_clks);
if (cmu->clk_regs)
samsung_clk_extended_sleep_init(reg_base,
cmu->clk_regs, cmu->nr_clk_regs,
cmu->suspend_regs, cmu->nr_suspend_regs);
- if (cmu->cpu_clks)
- samsung_clk_register_cpu(ctx, cmu->cpu_clks, cmu->nr_cpu_clks);
samsung_clk_of_add_provider(np, ctx);
diff --git a/drivers/clk/samsung/clk.h b/drivers/clk/samsung/clk.h
index b46e83a2581f..ab9c3d7a25b3 100644
--- a/drivers/clk/samsung/clk.h
+++ b/drivers/clk/samsung/clk.h
@@ -16,6 +16,7 @@
/**
* struct samsung_clk_provider: information about clock provider
* @reg_base: virtual address for the register base.
+ * @dev: clock provider device needed for runtime PM.
* @lock: maintains exclusion between callbacks for a given clock-provider.
* @clk_data: holds clock related data like clk_hw* and number of clocks.
*/
@@ -337,9 +338,8 @@ struct samsung_cmu_info {
const char *clk_name;
};
-struct samsung_clk_provider * samsung_clk_init(
- struct device_node *np, void __iomem *base,
- unsigned long nr_clks);
+struct samsung_clk_provider *samsung_clk_init(struct device *dev,
+ void __iomem *base, unsigned long nr_clks);
void samsung_clk_of_add_provider(struct device_node *np,
struct samsung_clk_provider *ctx);
void samsung_clk_of_register_fixed_ext(
@@ -373,10 +373,12 @@ void samsung_clk_register_gate(struct samsung_clk_provider *ctx,
unsigned int nr_clk);
void samsung_clk_register_pll(struct samsung_clk_provider *ctx,
const struct samsung_pll_clock *pll_list,
- unsigned int nr_clk, void __iomem *base);
+ unsigned int nr_clk);
void samsung_clk_register_cpu(struct samsung_clk_provider *ctx,
const struct samsung_cpu_clock *list, unsigned int nr_clk);
+void samsung_cmu_register_clocks(struct samsung_clk_provider *ctx,
+ const struct samsung_cmu_info *cmu);
struct samsung_clk_provider *samsung_cmu_register_one(
struct device_node *,
const struct samsung_cmu_info *);