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
This commit is contained in:
@@ -37,6 +37,7 @@ properties:
|
||||
- samsung,exynos850-cmu-cmgp
|
||||
- samsung,exynos850-cmu-core
|
||||
- samsung,exynos850-cmu-dpu
|
||||
- samsung,exynos850-cmu-g3d
|
||||
- samsung,exynos850-cmu-hsi
|
||||
- samsung,exynos850-cmu-is
|
||||
- samsung,exynos850-cmu-mfcmscl
|
||||
@@ -169,6 +170,24 @@ allOf:
|
||||
- const: oscclk
|
||||
- const: dout_dpu
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
const: samsung,exynos850-cmu-g3d
|
||||
|
||||
then:
|
||||
properties:
|
||||
clocks:
|
||||
items:
|
||||
- description: External reference clock (26 MHz)
|
||||
- description: G3D clock (from CMU_TOP)
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: oscclk
|
||||
- const: dout_g3d_switch
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
|
@@ -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)
|
||||
@@ -56,6 +72,83 @@ static void __init exynos_arm64_init_clocks(struct device_node *np,
|
||||
iounmap(reg_base);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
@@ -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;
|
||||
int err;
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
|
@@ -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 */
|
||||
|
@@ -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);
|
||||
|
@@ -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);
|
||||
|
||||
|
@@ -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,
|
||||
|
@@ -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);
|
||||
|
||||
|
@@ -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,
|
||||
|
@@ -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,
|
||||
|
@@ -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)
|
||||
|
@@ -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),
|
||||
@@ -1700,6 +1836,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,
|
||||
|
@@ -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]);
|
||||
}
|
||||
|
@@ -34,6 +34,7 @@ enum samsung_pll_type {
|
||||
pll_1451x,
|
||||
pll_1452x,
|
||||
pll_1460x,
|
||||
pll_0818x,
|
||||
pll_0822x,
|
||||
pll_0831x,
|
||||
pll_142xx,
|
||||
|
@@ -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,
|
||||
|
@@ -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,
|
||||
|
@@ -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);
|
||||
|
||||
|
@@ -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 *);
|
||||
|
@@ -85,7 +85,10 @@
|
||||
#define CLK_DOUT_MFCMSCL_M2M 73
|
||||
#define CLK_DOUT_MFCMSCL_MCSC 74
|
||||
#define CLK_DOUT_MFCMSCL_JPEG 75
|
||||
#define TOP_NR_CLK 76
|
||||
#define CLK_MOUT_G3D_SWITCH 76
|
||||
#define CLK_GOUT_G3D_SWITCH 77
|
||||
#define CLK_DOUT_G3D_SWITCH 78
|
||||
#define TOP_NR_CLK 79
|
||||
|
||||
/* CMU_APM */
|
||||
#define CLK_RCO_I3C_PMIC 1
|
||||
@@ -175,7 +178,8 @@
|
||||
#define IOCLK_AUDIOCDCLK5 58
|
||||
#define IOCLK_AUDIOCDCLK6 59
|
||||
#define TICK_USB 60
|
||||
#define AUD_NR_CLK 61
|
||||
#define CLK_GOUT_AUD_CMU_AUD_PCLK 61
|
||||
#define AUD_NR_CLK 62
|
||||
|
||||
/* CMU_CMGP */
|
||||
#define CLK_RCO_CMGP 1
|
||||
@@ -195,6 +199,21 @@
|
||||
#define CLK_GOUT_SYSREG_CMGP_PCLK 15
|
||||
#define CMGP_NR_CLK 16
|
||||
|
||||
/* CMU_G3D */
|
||||
#define CLK_FOUT_G3D_PLL 1
|
||||
#define CLK_MOUT_G3D_PLL 2
|
||||
#define CLK_MOUT_G3D_SWITCH_USER 3
|
||||
#define CLK_MOUT_G3D_BUSD 4
|
||||
#define CLK_DOUT_G3D_BUSP 5
|
||||
#define CLK_GOUT_G3D_CMU_G3D_PCLK 6
|
||||
#define CLK_GOUT_G3D_GPU_CLK 7
|
||||
#define CLK_GOUT_G3D_TZPC_PCLK 8
|
||||
#define CLK_GOUT_G3D_GRAY2BIN_CLK 9
|
||||
#define CLK_GOUT_G3D_BUSD_CLK 10
|
||||
#define CLK_GOUT_G3D_BUSP_CLK 11
|
||||
#define CLK_GOUT_G3D_SYSREG_PCLK 12
|
||||
#define G3D_NR_CLK 13
|
||||
|
||||
/* CMU_HSI */
|
||||
#define CLK_MOUT_HSI_BUS_USER 1
|
||||
#define CLK_MOUT_HSI_MMC_CARD_USER 2
|
||||
@@ -209,7 +228,10 @@
|
||||
#define CLK_GOUT_MMC_CARD_ACLK 11
|
||||
#define CLK_GOUT_MMC_CARD_SDCLKIN 12
|
||||
#define CLK_GOUT_SYSREG_HSI_PCLK 13
|
||||
#define HSI_NR_CLK 14
|
||||
#define CLK_GOUT_HSI_PPMU_ACLK 14
|
||||
#define CLK_GOUT_HSI_PPMU_PCLK 15
|
||||
#define CLK_GOUT_HSI_CMU_HSI_PCLK 16
|
||||
#define HSI_NR_CLK 17
|
||||
|
||||
/* CMU_IS */
|
||||
#define CLK_MOUT_IS_BUS_USER 1
|
||||
|
Reference in New Issue
Block a user