clk/samsung updates for 4.13
- conversion to the clk_hw API - definitions and fixes of exynos5420 SoC audio subsystem related clocks -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAABCAAGBQJZOpzhAAoJEE1bIKeAnHqLPFsP/jh9z5A1eq+rlB3ivWW8OByi 4iANs6Gd9Tnw7MNF46XV6qPHmj+9cEe1ntT/6lVs9Hlz67HwEnWuMc8dgtU6YU7d A7Vzx+fMpE/UwFISLhqMjn5Djh13KP4wuPYiHaJKS+00JNEfT/IsvL6kZPS5I2bZ teoeWzD1vOnn8QXxSnJeCCkmS91zVq5Sxyrge9Lui0gLMN+5wVxY1VTiw7erL9hi jDL6qSRvcJfG1lruGD9No5MkI0kBXiVgqMHi1b2mTYnUS2NUQeAhCfGsvkO71ZU7 YjDSAOHYTccIdWHs6X4aIvzeVLjuHMVsnnXErDjI388POOQ3BCQ0JE2FDkp68UrM DNGQFaKE528mxOL819aH71JQ5qj1kB9Upq7NUSC6roPbahiPv1tdx9dzX2vgGslM pW+lXR6ysnsEYsE8HsCsOti4jpVSG6iWYyffI6GMGHVqRiDUY9d6cxHgj/Qx3YFR 9a7QmehnmSSzJK9sC1acD6e/U1YhcZYKMmb4ygtjFP/w2N2pwNXTgEw74UmXS/Mg /ydVbcwJh6spaN85wXKer5lrZNio+gHDj4B+Vwnfo8yB2GW2akHYGW5cNkGeGac6 7ysI0wp7l9AuofzmovtiPw0pvz0p41rJO2LvIOvvsGeo6i5OOZBke7aAxe7lfg8G hoXF2gS+r0wg/C3ljj4z =2bgV -----END PGP SIGNATURE----- Merge tag 'clk-v4.13-samsung' of git://git.kernel.org/pub/scm/linux/kernel/git/snawrocki/clk into clk-next Pull samsung clk driver updates from Sylwester Nawrocki - conversion to the clk_hw API - definitions and fixes of exynos5420 SoC audio subsystem related clocks * tag 'clk-v4.13-samsung' of git://git.kernel.org/pub/scm/linux/kernel/git/snawrocki/clk: clk: samsung: exynos542x: Add EPLL rate table clk: samsung: Add missing exynos5420 audio related clocks clk: samsung: Add enable/disable operation for PLL36XX clocks clk: samsung: s5pv210-audss: Convert to the new clk_hw API clk: samsung: exynos-clkout: Convert to the new clk_hw API clk: samsung: exynos-audss: Convert to the new clk_hw API clk: samsung: Convert common drivers to the new clk_hw API clk: samsung: Add local variable to match its purpose clk: samsung: Remove dead code
This commit is contained in:
commit
7f274d54bb
|
@ -410,7 +410,7 @@ int __init exynos_register_cpu_clock(struct samsung_clk_provider *ctx,
|
|||
{
|
||||
struct exynos_cpuclk *cpuclk;
|
||||
struct clk_init_data init;
|
||||
struct clk *clk;
|
||||
struct clk *parent_clk;
|
||||
int ret = 0;
|
||||
|
||||
cpuclk = kzalloc(sizeof(*cpuclk), GFP_KERNEL);
|
||||
|
@ -440,15 +440,15 @@ int __init exynos_register_cpu_clock(struct samsung_clk_provider *ctx,
|
|||
goto free_cpuclk;
|
||||
}
|
||||
|
||||
clk = __clk_lookup(parent);
|
||||
if (!clk) {
|
||||
parent_clk = __clk_lookup(parent);
|
||||
if (!parent_clk) {
|
||||
pr_err("%s: could not lookup parent clock %s\n",
|
||||
__func__, parent);
|
||||
ret = -EINVAL;
|
||||
goto free_cpuclk;
|
||||
}
|
||||
|
||||
ret = clk_notifier_register(clk, &cpuclk->clk_nb);
|
||||
ret = clk_notifier_register(parent_clk, &cpuclk->clk_nb);
|
||||
if (ret) {
|
||||
pr_err("%s: failed to register clock notifier for %s\n",
|
||||
__func__, name);
|
||||
|
@ -463,20 +463,19 @@ int __init exynos_register_cpu_clock(struct samsung_clk_provider *ctx,
|
|||
goto unregister_clk_nb;
|
||||
}
|
||||
|
||||
clk = clk_register(NULL, &cpuclk->hw);
|
||||
if (IS_ERR(clk)) {
|
||||
ret = clk_hw_register(NULL, &cpuclk->hw);
|
||||
if (ret) {
|
||||
pr_err("%s: could not register cpuclk %s\n", __func__, name);
|
||||
ret = PTR_ERR(clk);
|
||||
goto free_cpuclk_data;
|
||||
}
|
||||
|
||||
samsung_clk_add_lookup(ctx, clk, lookup_id);
|
||||
samsung_clk_add_lookup(ctx, &cpuclk->hw, lookup_id);
|
||||
return 0;
|
||||
|
||||
free_cpuclk_data:
|
||||
kfree(cpuclk->cfg);
|
||||
unregister_clk_nb:
|
||||
clk_notifier_unregister(__clk_lookup(parent), &cpuclk->clk_nb);
|
||||
clk_notifier_unregister(parent_clk, &cpuclk->clk_nb);
|
||||
free_cpuclk:
|
||||
kfree(cpuclk);
|
||||
return ret;
|
||||
|
|
|
@ -22,9 +22,8 @@
|
|||
#include <dt-bindings/clock/exynos-audss-clk.h>
|
||||
|
||||
static DEFINE_SPINLOCK(lock);
|
||||
static struct clk **clk_table;
|
||||
static void __iomem *reg_base;
|
||||
static struct clk_onecell_data clk_data;
|
||||
static struct clk_hw_onecell_data *clk_data;
|
||||
/*
|
||||
* On Exynos5420 this will be a clock which has to be enabled before any
|
||||
* access to audss registers. Typically a child of EPLL.
|
||||
|
@ -110,18 +109,18 @@ static void exynos_audss_clk_teardown(void)
|
|||
int i;
|
||||
|
||||
for (i = EXYNOS_MOUT_AUDSS; i < EXYNOS_DOUT_SRP; i++) {
|
||||
if (!IS_ERR(clk_table[i]))
|
||||
clk_unregister_mux(clk_table[i]);
|
||||
if (!IS_ERR(clk_data->hws[i]))
|
||||
clk_hw_unregister_mux(clk_data->hws[i]);
|
||||
}
|
||||
|
||||
for (; i < EXYNOS_SRP_CLK; i++) {
|
||||
if (!IS_ERR(clk_table[i]))
|
||||
clk_unregister_divider(clk_table[i]);
|
||||
if (!IS_ERR(clk_data->hws[i]))
|
||||
clk_hw_unregister_divider(clk_data->hws[i]);
|
||||
}
|
||||
|
||||
for (; i < clk_data.clk_num; i++) {
|
||||
if (!IS_ERR(clk_table[i]))
|
||||
clk_unregister_gate(clk_table[i]);
|
||||
for (; i < clk_data->num; i++) {
|
||||
if (!IS_ERR(clk_data->hws[i]))
|
||||
clk_hw_unregister_gate(clk_data->hws[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -133,6 +132,7 @@ static int exynos_audss_clk_probe(struct platform_device *pdev)
|
|||
const char *sclk_pcm_p = "sclk_pcm0";
|
||||
struct clk *pll_ref, *pll_in, *cdclk, *sclk_audio, *sclk_pcm_in;
|
||||
const struct exynos_audss_clk_drvdata *variant;
|
||||
struct clk_hw **clk_table;
|
||||
struct resource *res;
|
||||
int i, ret = 0;
|
||||
|
||||
|
@ -149,14 +149,15 @@ static int exynos_audss_clk_probe(struct platform_device *pdev)
|
|||
|
||||
epll = ERR_PTR(-ENODEV);
|
||||
|
||||
clk_table = devm_kzalloc(&pdev->dev,
|
||||
sizeof(struct clk *) * EXYNOS_AUDSS_MAX_CLKS,
|
||||
clk_data = devm_kzalloc(&pdev->dev,
|
||||
sizeof(*clk_data) +
|
||||
sizeof(*clk_data->hws) * EXYNOS_AUDSS_MAX_CLKS,
|
||||
GFP_KERNEL);
|
||||
if (!clk_table)
|
||||
if (!clk_data)
|
||||
return -ENOMEM;
|
||||
|
||||
clk_data.clks = clk_table;
|
||||
clk_data.clk_num = variant->num_clks;
|
||||
clk_data->num = variant->num_clks;
|
||||
clk_table = clk_data->hws;
|
||||
|
||||
pll_ref = devm_clk_get(&pdev->dev, "pll_ref");
|
||||
pll_in = devm_clk_get(&pdev->dev, "pll_in");
|
||||
|
@ -176,7 +177,7 @@ static int exynos_audss_clk_probe(struct platform_device *pdev)
|
|||
}
|
||||
}
|
||||
}
|
||||
clk_table[EXYNOS_MOUT_AUDSS] = clk_register_mux(NULL, "mout_audss",
|
||||
clk_table[EXYNOS_MOUT_AUDSS] = clk_hw_register_mux(NULL, "mout_audss",
|
||||
mout_audss_p, ARRAY_SIZE(mout_audss_p),
|
||||
CLK_SET_RATE_NO_REPARENT,
|
||||
reg_base + ASS_CLK_SRC, 0, 1, 0, &lock);
|
||||
|
@ -187,53 +188,53 @@ static int exynos_audss_clk_probe(struct platform_device *pdev)
|
|||
mout_i2s_p[1] = __clk_get_name(cdclk);
|
||||
if (!IS_ERR(sclk_audio))
|
||||
mout_i2s_p[2] = __clk_get_name(sclk_audio);
|
||||
clk_table[EXYNOS_MOUT_I2S] = clk_register_mux(NULL, "mout_i2s",
|
||||
clk_table[EXYNOS_MOUT_I2S] = clk_hw_register_mux(NULL, "mout_i2s",
|
||||
mout_i2s_p, ARRAY_SIZE(mout_i2s_p),
|
||||
CLK_SET_RATE_NO_REPARENT,
|
||||
reg_base + ASS_CLK_SRC, 2, 2, 0, &lock);
|
||||
|
||||
clk_table[EXYNOS_DOUT_SRP] = clk_register_divider(NULL, "dout_srp",
|
||||
clk_table[EXYNOS_DOUT_SRP] = clk_hw_register_divider(NULL, "dout_srp",
|
||||
"mout_audss", 0, reg_base + ASS_CLK_DIV, 0, 4,
|
||||
0, &lock);
|
||||
|
||||
clk_table[EXYNOS_DOUT_AUD_BUS] = clk_register_divider(NULL,
|
||||
clk_table[EXYNOS_DOUT_AUD_BUS] = clk_hw_register_divider(NULL,
|
||||
"dout_aud_bus", "dout_srp", 0,
|
||||
reg_base + ASS_CLK_DIV, 4, 4, 0, &lock);
|
||||
|
||||
clk_table[EXYNOS_DOUT_I2S] = clk_register_divider(NULL, "dout_i2s",
|
||||
clk_table[EXYNOS_DOUT_I2S] = clk_hw_register_divider(NULL, "dout_i2s",
|
||||
"mout_i2s", 0, reg_base + ASS_CLK_DIV, 8, 4, 0,
|
||||
&lock);
|
||||
|
||||
clk_table[EXYNOS_SRP_CLK] = clk_register_gate(NULL, "srp_clk",
|
||||
clk_table[EXYNOS_SRP_CLK] = clk_hw_register_gate(NULL, "srp_clk",
|
||||
"dout_srp", CLK_SET_RATE_PARENT,
|
||||
reg_base + ASS_CLK_GATE, 0, 0, &lock);
|
||||
|
||||
clk_table[EXYNOS_I2S_BUS] = clk_register_gate(NULL, "i2s_bus",
|
||||
clk_table[EXYNOS_I2S_BUS] = clk_hw_register_gate(NULL, "i2s_bus",
|
||||
"dout_aud_bus", CLK_SET_RATE_PARENT,
|
||||
reg_base + ASS_CLK_GATE, 2, 0, &lock);
|
||||
|
||||
clk_table[EXYNOS_SCLK_I2S] = clk_register_gate(NULL, "sclk_i2s",
|
||||
clk_table[EXYNOS_SCLK_I2S] = clk_hw_register_gate(NULL, "sclk_i2s",
|
||||
"dout_i2s", CLK_SET_RATE_PARENT,
|
||||
reg_base + ASS_CLK_GATE, 3, 0, &lock);
|
||||
|
||||
clk_table[EXYNOS_PCM_BUS] = clk_register_gate(NULL, "pcm_bus",
|
||||
clk_table[EXYNOS_PCM_BUS] = clk_hw_register_gate(NULL, "pcm_bus",
|
||||
"sclk_pcm", CLK_SET_RATE_PARENT,
|
||||
reg_base + ASS_CLK_GATE, 4, 0, &lock);
|
||||
|
||||
sclk_pcm_in = devm_clk_get(&pdev->dev, "sclk_pcm_in");
|
||||
if (!IS_ERR(sclk_pcm_in))
|
||||
sclk_pcm_p = __clk_get_name(sclk_pcm_in);
|
||||
clk_table[EXYNOS_SCLK_PCM] = clk_register_gate(NULL, "sclk_pcm",
|
||||
clk_table[EXYNOS_SCLK_PCM] = clk_hw_register_gate(NULL, "sclk_pcm",
|
||||
sclk_pcm_p, CLK_SET_RATE_PARENT,
|
||||
reg_base + ASS_CLK_GATE, 5, 0, &lock);
|
||||
|
||||
if (variant->has_adma_clk) {
|
||||
clk_table[EXYNOS_ADMA] = clk_register_gate(NULL, "adma",
|
||||
clk_table[EXYNOS_ADMA] = clk_hw_register_gate(NULL, "adma",
|
||||
"dout_srp", CLK_SET_RATE_PARENT,
|
||||
reg_base + ASS_CLK_GATE, 9, 0, &lock);
|
||||
}
|
||||
|
||||
for (i = 0; i < clk_data.clk_num; i++) {
|
||||
for (i = 0; i < clk_data->num; i++) {
|
||||
if (IS_ERR(clk_table[i])) {
|
||||
dev_err(&pdev->dev, "failed to register clock %d\n", i);
|
||||
ret = PTR_ERR(clk_table[i]);
|
||||
|
@ -241,8 +242,8 @@ static int exynos_audss_clk_probe(struct platform_device *pdev)
|
|||
}
|
||||
}
|
||||
|
||||
ret = of_clk_add_provider(pdev->dev.of_node, of_clk_src_onecell_get,
|
||||
&clk_data);
|
||||
ret = of_clk_add_hw_provider(pdev->dev.of_node, of_clk_hw_onecell_get,
|
||||
clk_data);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "failed to add clock provider\n");
|
||||
goto unregister;
|
||||
|
|
|
@ -29,10 +29,9 @@ struct exynos_clkout {
|
|||
struct clk_gate gate;
|
||||
struct clk_mux mux;
|
||||
spinlock_t slock;
|
||||
struct clk_onecell_data data;
|
||||
struct clk *clk_table[EXYNOS_CLKOUT_NR_CLKS];
|
||||
void __iomem *reg;
|
||||
u32 pmu_debug_save;
|
||||
struct clk_hw_onecell_data data;
|
||||
};
|
||||
|
||||
static struct exynos_clkout *clkout;
|
||||
|
@ -62,7 +61,9 @@ static void __init exynos_clkout_init(struct device_node *node, u32 mux_mask)
|
|||
int ret;
|
||||
int i;
|
||||
|
||||
clkout = kzalloc(sizeof(*clkout), GFP_KERNEL);
|
||||
clkout = kzalloc(sizeof(*clkout) +
|
||||
sizeof(*clkout->data.hws) * EXYNOS_CLKOUT_NR_CLKS,
|
||||
GFP_KERNEL);
|
||||
if (!clkout)
|
||||
return;
|
||||
|
||||
|
@ -100,17 +101,16 @@ static void __init exynos_clkout_init(struct device_node *node, u32 mux_mask)
|
|||
clkout->mux.shift = EXYNOS_CLKOUT_MUX_SHIFT;
|
||||
clkout->mux.lock = &clkout->slock;
|
||||
|
||||
clkout->clk_table[0] = clk_register_composite(NULL, "clkout",
|
||||
clkout->data.hws[0] = clk_hw_register_composite(NULL, "clkout",
|
||||
parent_names, parent_count, &clkout->mux.hw,
|
||||
&clk_mux_ops, NULL, NULL, &clkout->gate.hw,
|
||||
&clk_gate_ops, CLK_SET_RATE_PARENT
|
||||
| CLK_SET_RATE_NO_REPARENT);
|
||||
if (IS_ERR(clkout->clk_table[0]))
|
||||
if (IS_ERR(clkout->data.hws[0]))
|
||||
goto err_unmap;
|
||||
|
||||
clkout->data.clks = clkout->clk_table;
|
||||
clkout->data.clk_num = EXYNOS_CLKOUT_NR_CLKS;
|
||||
ret = of_clk_add_provider(node, of_clk_src_onecell_get, &clkout->data);
|
||||
clkout->data.num = EXYNOS_CLKOUT_NR_CLKS;
|
||||
ret = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, &clkout->data);
|
||||
if (ret)
|
||||
goto err_clk_unreg;
|
||||
|
||||
|
@ -119,7 +119,7 @@ static void __init exynos_clkout_init(struct device_node *node, u32 mux_mask)
|
|||
return;
|
||||
|
||||
err_clk_unreg:
|
||||
clk_unregister(clkout->clk_table[0]);
|
||||
clk_hw_unregister(clkout->data.hws[0]);
|
||||
err_unmap:
|
||||
iounmap(clkout->reg);
|
||||
clks_put:
|
||||
|
|
|
@ -487,6 +487,7 @@ PNAME(mout_group12_5800_p) = { "dout_aclkfl1_550_cam", "dout_sclk_sw" };
|
|||
PNAME(mout_group13_5800_p) = { "dout_osc_div", "mout_sw_aclkfl1_550_cam" };
|
||||
PNAME(mout_group14_5800_p) = { "dout_aclk550_cam", "dout_sclk_sw" };
|
||||
PNAME(mout_group15_5800_p) = { "dout_osc_div", "mout_sw_aclk550_cam" };
|
||||
PNAME(mout_group16_5800_p) = { "dout_osc_div", "mout_mau_epll_clk" };
|
||||
|
||||
/* fixed rate clocks generated outside the soc */
|
||||
static struct samsung_fixed_rate_clock
|
||||
|
@ -536,8 +537,8 @@ static const struct samsung_mux_clock exynos5800_mux_clks[] __initconst = {
|
|||
|
||||
MUX(CLK_MOUT_MX_MSPLL_CCORE, "mout_mx_mspll_ccore",
|
||||
mout_mx_mspll_ccore_p, SRC_TOP7, 16, 2),
|
||||
MUX(0, "mout_mau_epll_clk", mout_mau_epll_clk_5800_p, SRC_TOP7,
|
||||
20, 2),
|
||||
MUX(CLK_MOUT_MAU_EPLL, "mout_mau_epll_clk", mout_mau_epll_clk_5800_p,
|
||||
SRC_TOP7, 20, 2),
|
||||
MUX(0, "sclk_bpll", mout_bpll_p, SRC_TOP7, 24, 1),
|
||||
MUX(0, "mout_epll2", mout_epll2_5800_p, SRC_TOP7, 28, 1),
|
||||
|
||||
|
@ -546,6 +547,8 @@ static const struct samsung_mux_clock exynos5800_mux_clks[] __initconst = {
|
|||
MUX(0, "mout_aclk432_cam", mout_group6_5800_p, SRC_TOP8, 24, 2),
|
||||
MUX(0, "mout_aclk432_scaler", mout_group6_5800_p, SRC_TOP8, 28, 2),
|
||||
|
||||
MUX(CLK_MOUT_USER_MAU_EPLL, "mout_user_mau_epll", mout_group16_5800_p,
|
||||
SRC_TOP9, 8, 1),
|
||||
MUX(0, "mout_user_aclk550_cam", mout_group15_5800_p,
|
||||
SRC_TOP9, 16, 1),
|
||||
MUX(0, "mout_user_aclkfl1_550_cam", mout_group13_5800_p,
|
||||
|
@ -703,7 +706,7 @@ static const struct samsung_mux_clock exynos5x_mux_clks[] __initconst = {
|
|||
MUX(0, "mout_sclk_spll", mout_spll_p, SRC_TOP6, 8, 1),
|
||||
MUX(0, "mout_sclk_ipll", mout_ipll_p, SRC_TOP6, 12, 1),
|
||||
MUX(0, "mout_sclk_rpll", mout_rpll_p, SRC_TOP6, 16, 1),
|
||||
MUX(0, "mout_sclk_epll", mout_epll_p, SRC_TOP6, 20, 1),
|
||||
MUX(CLK_MOUT_EPLL, "mout_sclk_epll", mout_epll_p, SRC_TOP6, 20, 1),
|
||||
MUX(0, "mout_sclk_dpll", mout_dpll_p, SRC_TOP6, 24, 1),
|
||||
MUX(0, "mout_sclk_cpll", mout_cpll_p, SRC_TOP6, 28, 1),
|
||||
|
||||
|
@ -1277,6 +1280,21 @@ static const struct samsung_pll_rate_table exynos5420_pll2550x_24mhz_tbl[] __ini
|
|||
PLL_35XX_RATE(200000000, 200, 3, 3),
|
||||
};
|
||||
|
||||
static const struct samsung_pll_rate_table exynos5420_epll_24mhz_tbl[] = {
|
||||
PLL_36XX_RATE(600000000U, 100, 2, 1, 0),
|
||||
PLL_36XX_RATE(400000000U, 200, 3, 2, 0),
|
||||
PLL_36XX_RATE(393216000U, 197, 3, 2, 25690),
|
||||
PLL_36XX_RATE(361267200U, 301, 5, 2, 3671),
|
||||
PLL_36XX_RATE(200000000U, 200, 3, 3, 0),
|
||||
PLL_36XX_RATE(196608000U, 197, 3, 3, -25690),
|
||||
PLL_36XX_RATE(180633600U, 301, 5, 3, 3671),
|
||||
PLL_36XX_RATE(131072000U, 131, 3, 3, 4719),
|
||||
PLL_36XX_RATE(100000000U, 200, 3, 4, 0),
|
||||
PLL_36XX_RATE(65536000U, 131, 3, 4, 4719),
|
||||
PLL_36XX_RATE(49152000U, 197, 3, 5, 25690),
|
||||
PLL_36XX_RATE(32768000U, 131, 3, 5, 4719),
|
||||
};
|
||||
|
||||
static struct samsung_pll_clock exynos5x_plls[nr_plls] __initdata = {
|
||||
[apll] = PLL(pll_2550, CLK_FOUT_APLL, "fout_apll", "fin_pll", APLL_LOCK,
|
||||
APLL_CON0, NULL),
|
||||
|
@ -1284,7 +1302,7 @@ static struct samsung_pll_clock exynos5x_plls[nr_plls] __initdata = {
|
|||
CPLL_CON0, NULL),
|
||||
[dpll] = PLL(pll_2550, CLK_FOUT_DPLL, "fout_dpll", "fin_pll", DPLL_LOCK,
|
||||
DPLL_CON0, NULL),
|
||||
[epll] = PLL(pll_2650, CLK_FOUT_EPLL, "fout_epll", "fin_pll", EPLL_LOCK,
|
||||
[epll] = PLL(pll_36xx, CLK_FOUT_EPLL, "fout_epll", "fin_pll", EPLL_LOCK,
|
||||
EPLL_CON0, NULL),
|
||||
[rpll] = PLL(pll_2650, CLK_FOUT_RPLL, "fout_rpll", "fin_pll", RPLL_LOCK,
|
||||
RPLL_CON0, NULL),
|
||||
|
@ -1399,6 +1417,7 @@ static void __init exynos5x_clk_init(struct device_node *np,
|
|||
|
||||
if (_get_rate("fin_pll") == 24 * MHZ) {
|
||||
exynos5x_plls[apll].rate_table = exynos5420_pll2550x_24mhz_tbl;
|
||||
exynos5x_plls[epll].rate_table = exynos5420_epll_24mhz_tbl;
|
||||
exynos5x_plls[kpll].rate_table = exynos5420_pll2550x_24mhz_tbl;
|
||||
exynos5x_plls[bpll].rate_table = exynos5420_pll2550x_24mhz_tbl;
|
||||
}
|
||||
|
|
|
@ -23,6 +23,10 @@ struct samsung_clk_pll {
|
|||
struct clk_hw hw;
|
||||
void __iomem *lock_reg;
|
||||
void __iomem *con_reg;
|
||||
/* PLL enable control bit offset in @con_reg register */
|
||||
unsigned short enable_offs;
|
||||
/* PLL lock status bit offset in @con_reg register */
|
||||
unsigned short lock_offs;
|
||||
enum samsung_pll_type type;
|
||||
unsigned int rate_count;
|
||||
const struct samsung_pll_rate_table *rate_table;
|
||||
|
@ -61,6 +65,34 @@ static long samsung_pll_round_rate(struct clk_hw *hw,
|
|||
return rate_table[i - 1].rate;
|
||||
}
|
||||
|
||||
static int samsung_pll3xxx_enable(struct clk_hw *hw)
|
||||
{
|
||||
struct samsung_clk_pll *pll = to_clk_pll(hw);
|
||||
u32 tmp;
|
||||
|
||||
tmp = readl_relaxed(pll->con_reg);
|
||||
tmp |= BIT(pll->enable_offs);
|
||||
writel_relaxed(tmp, pll->con_reg);
|
||||
|
||||
/* wait lock time */
|
||||
do {
|
||||
cpu_relax();
|
||||
tmp = readl_relaxed(pll->con_reg);
|
||||
} while (!(tmp & BIT(pll->lock_offs)));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void samsung_pll3xxx_disable(struct clk_hw *hw)
|
||||
{
|
||||
struct samsung_clk_pll *pll = to_clk_pll(hw);
|
||||
u32 tmp;
|
||||
|
||||
tmp = readl_relaxed(pll->con_reg);
|
||||
tmp &= ~BIT(pll->enable_offs);
|
||||
writel_relaxed(tmp, pll->con_reg);
|
||||
}
|
||||
|
||||
/*
|
||||
* PLL2126 Clock Type
|
||||
*/
|
||||
|
@ -142,34 +174,6 @@ static const struct clk_ops samsung_pll3000_clk_ops = {
|
|||
#define PLL35XX_LOCK_STAT_SHIFT (29)
|
||||
#define PLL35XX_ENABLE_SHIFT (31)
|
||||
|
||||
static int samsung_pll35xx_enable(struct clk_hw *hw)
|
||||
{
|
||||
struct samsung_clk_pll *pll = to_clk_pll(hw);
|
||||
u32 tmp;
|
||||
|
||||
tmp = readl_relaxed(pll->con_reg);
|
||||
tmp |= BIT(PLL35XX_ENABLE_SHIFT);
|
||||
writel_relaxed(tmp, pll->con_reg);
|
||||
|
||||
/* wait_lock_time */
|
||||
do {
|
||||
cpu_relax();
|
||||
tmp = readl_relaxed(pll->con_reg);
|
||||
} while (!(tmp & BIT(PLL35XX_LOCK_STAT_SHIFT)));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void samsung_pll35xx_disable(struct clk_hw *hw)
|
||||
{
|
||||
struct samsung_clk_pll *pll = to_clk_pll(hw);
|
||||
u32 tmp;
|
||||
|
||||
tmp = readl_relaxed(pll->con_reg);
|
||||
tmp &= ~BIT(PLL35XX_ENABLE_SHIFT);
|
||||
writel_relaxed(tmp, pll->con_reg);
|
||||
}
|
||||
|
||||
static unsigned long samsung_pll35xx_recalc_rate(struct clk_hw *hw,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
|
@ -238,12 +242,12 @@ static int samsung_pll35xx_set_rate(struct clk_hw *hw, unsigned long drate,
|
|||
(rate->sdiv << PLL35XX_SDIV_SHIFT);
|
||||
writel_relaxed(tmp, pll->con_reg);
|
||||
|
||||
/* wait_lock_time if enabled */
|
||||
if (tmp & BIT(PLL35XX_ENABLE_SHIFT)) {
|
||||
/* Wait until the PLL is locked if it is enabled. */
|
||||
if (tmp & BIT(pll->enable_offs)) {
|
||||
do {
|
||||
cpu_relax();
|
||||
tmp = readl_relaxed(pll->con_reg);
|
||||
} while (!(tmp & BIT(PLL35XX_LOCK_STAT_SHIFT)));
|
||||
} while (!(tmp & BIT(pll->lock_offs)));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -252,8 +256,8 @@ static const struct clk_ops samsung_pll35xx_clk_ops = {
|
|||
.recalc_rate = samsung_pll35xx_recalc_rate,
|
||||
.round_rate = samsung_pll_round_rate,
|
||||
.set_rate = samsung_pll35xx_set_rate,
|
||||
.enable = samsung_pll35xx_enable,
|
||||
.disable = samsung_pll35xx_disable,
|
||||
.enable = samsung_pll3xxx_enable,
|
||||
.disable = samsung_pll3xxx_disable,
|
||||
};
|
||||
|
||||
static const struct clk_ops samsung_pll35xx_clk_min_ops = {
|
||||
|
@ -275,6 +279,7 @@ static const struct clk_ops samsung_pll35xx_clk_min_ops = {
|
|||
#define PLL36XX_SDIV_SHIFT (0)
|
||||
#define PLL36XX_KDIV_SHIFT (0)
|
||||
#define PLL36XX_LOCK_STAT_SHIFT (29)
|
||||
#define PLL36XX_ENABLE_SHIFT (31)
|
||||
|
||||
static unsigned long samsung_pll36xx_recalc_rate(struct clk_hw *hw,
|
||||
unsigned long parent_rate)
|
||||
|
@ -354,10 +359,12 @@ static int samsung_pll36xx_set_rate(struct clk_hw *hw, unsigned long drate,
|
|||
writel_relaxed(pll_con1, pll->con_reg + 4);
|
||||
|
||||
/* wait_lock_time */
|
||||
do {
|
||||
cpu_relax();
|
||||
tmp = readl_relaxed(pll->con_reg);
|
||||
} while (!(tmp & (1 << PLL36XX_LOCK_STAT_SHIFT)));
|
||||
if (pll_con0 & BIT(pll->enable_offs)) {
|
||||
do {
|
||||
cpu_relax();
|
||||
tmp = readl_relaxed(pll->con_reg);
|
||||
} while (!(tmp & BIT(pll->lock_offs)));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -366,6 +373,8 @@ static const struct clk_ops samsung_pll36xx_clk_ops = {
|
|||
.recalc_rate = samsung_pll36xx_recalc_rate,
|
||||
.set_rate = samsung_pll36xx_set_rate,
|
||||
.round_rate = samsung_pll_round_rate,
|
||||
.enable = samsung_pll3xxx_enable,
|
||||
.disable = samsung_pll3xxx_disable,
|
||||
};
|
||||
|
||||
static const struct clk_ops samsung_pll36xx_clk_min_ops = {
|
||||
|
@ -1244,7 +1253,6 @@ static void __init _samsung_clk_register_pll(struct samsung_clk_provider *ctx,
|
|||
void __iomem *base)
|
||||
{
|
||||
struct samsung_clk_pll *pll;
|
||||
struct clk *clk;
|
||||
struct clk_init_data init;
|
||||
int ret, len;
|
||||
|
||||
|
@ -1288,6 +1296,8 @@ static void __init _samsung_clk_register_pll(struct samsung_clk_provider *ctx,
|
|||
case pll_1450x:
|
||||
case pll_1451x:
|
||||
case pll_1452x:
|
||||
pll->enable_offs = PLL35XX_ENABLE_SHIFT;
|
||||
pll->lock_offs = PLL35XX_LOCK_STAT_SHIFT;
|
||||
if (!pll->rate_table)
|
||||
init.ops = &samsung_pll35xx_clk_min_ops;
|
||||
else
|
||||
|
@ -1306,6 +1316,8 @@ static void __init _samsung_clk_register_pll(struct samsung_clk_provider *ctx,
|
|||
/* clk_ops for 36xx and 2650 are similar */
|
||||
case pll_36xx:
|
||||
case pll_2650:
|
||||
pll->enable_offs = PLL36XX_ENABLE_SHIFT;
|
||||
pll->lock_offs = PLL36XX_LOCK_STAT_SHIFT;
|
||||
if (!pll->rate_table)
|
||||
init.ops = &samsung_pll36xx_clk_min_ops;
|
||||
else
|
||||
|
@ -1376,20 +1388,21 @@ static void __init _samsung_clk_register_pll(struct samsung_clk_provider *ctx,
|
|||
pll->lock_reg = base + pll_clk->lock_offset;
|
||||
pll->con_reg = base + pll_clk->con_offset;
|
||||
|
||||
clk = clk_register(NULL, &pll->hw);
|
||||
if (IS_ERR(clk)) {
|
||||
pr_err("%s: failed to register pll clock %s : %ld\n",
|
||||
__func__, pll_clk->name, PTR_ERR(clk));
|
||||
ret = clk_hw_register(NULL, &pll->hw);
|
||||
if (ret) {
|
||||
pr_err("%s: failed to register pll clock %s : %d\n",
|
||||
__func__, pll_clk->name, ret);
|
||||
kfree(pll);
|
||||
return;
|
||||
}
|
||||
|
||||
samsung_clk_add_lookup(ctx, clk, pll_clk->id);
|
||||
samsung_clk_add_lookup(ctx, &pll->hw, pll_clk->id);
|
||||
|
||||
if (!pll_clk->alias)
|
||||
return;
|
||||
|
||||
ret = clk_register_clkdev(clk, pll_clk->alias, pll_clk->dev_name);
|
||||
ret = clk_hw_register_clkdev(&pll->hw, pll_clk->alias,
|
||||
pll_clk->dev_name);
|
||||
if (ret)
|
||||
pr_err("%s: failed to register lookup for %s : %d",
|
||||
__func__, pll_clk->name, ret);
|
||||
|
|
|
@ -103,8 +103,4 @@ struct samsung_pll_rate_table {
|
|||
unsigned int vsel;
|
||||
};
|
||||
|
||||
extern struct clk * __init samsung_clk_register_pll2550x(const char *name,
|
||||
const char *pname, const void __iomem *reg_base,
|
||||
const unsigned long offset);
|
||||
|
||||
#endif /* __SAMSUNG_CLK_PLL_H */
|
||||
|
|
|
@ -90,13 +90,13 @@ static const struct clk_ops s3c24xx_clkout_ops = {
|
|||
.determine_rate = __clk_mux_determine_rate,
|
||||
};
|
||||
|
||||
static struct clk *s3c24xx_register_clkout(struct device *dev, const char *name,
|
||||
const char **parent_names, u8 num_parents,
|
||||
static struct clk_hw *s3c24xx_register_clkout(struct device *dev,
|
||||
const char *name, const char **parent_names, u8 num_parents,
|
||||
u8 shift, u32 mask)
|
||||
{
|
||||
struct s3c24xx_clkout *clkout;
|
||||
struct clk *clk;
|
||||
struct clk_init_data init;
|
||||
int ret;
|
||||
|
||||
/* allocate the clkout */
|
||||
clkout = kzalloc(sizeof(*clkout), GFP_KERNEL);
|
||||
|
@ -113,9 +113,11 @@ static struct clk *s3c24xx_register_clkout(struct device *dev, const char *name,
|
|||
clkout->mask = mask;
|
||||
clkout->hw.init = &init;
|
||||
|
||||
clk = clk_register(dev, &clkout->hw);
|
||||
ret = clk_hw_register(dev, &clkout->hw);
|
||||
if (ret)
|
||||
return ERR_PTR(ret);
|
||||
|
||||
return clk;
|
||||
return &clkout->hw;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -125,11 +127,12 @@ static struct clk *s3c24xx_register_clkout(struct device *dev, const char *name,
|
|||
struct s3c24xx_dclk {
|
||||
struct device *dev;
|
||||
void __iomem *base;
|
||||
struct clk_onecell_data clk_data;
|
||||
struct notifier_block dclk0_div_change_nb;
|
||||
struct notifier_block dclk1_div_change_nb;
|
||||
spinlock_t dclk_lock;
|
||||
unsigned long reg_save;
|
||||
/* clk_data must be the last entry in the structure */
|
||||
struct clk_hw_onecell_data clk_data;
|
||||
};
|
||||
|
||||
#define to_s3c24xx_dclk0(x) \
|
||||
|
@ -240,28 +243,23 @@ static int s3c24xx_dclk_probe(struct platform_device *pdev)
|
|||
{
|
||||
struct s3c24xx_dclk *s3c24xx_dclk;
|
||||
struct resource *mem;
|
||||
struct clk **clk_table;
|
||||
struct s3c24xx_dclk_drv_data *dclk_variant;
|
||||
struct clk_hw **clk_table;
|
||||
int ret, i;
|
||||
|
||||
s3c24xx_dclk = devm_kzalloc(&pdev->dev, sizeof(*s3c24xx_dclk),
|
||||
GFP_KERNEL);
|
||||
s3c24xx_dclk = devm_kzalloc(&pdev->dev, sizeof(*s3c24xx_dclk) +
|
||||
sizeof(*s3c24xx_dclk->clk_data.hws) * DCLK_MAX_CLKS,
|
||||
GFP_KERNEL);
|
||||
if (!s3c24xx_dclk)
|
||||
return -ENOMEM;
|
||||
|
||||
clk_table = s3c24xx_dclk->clk_data.hws;
|
||||
|
||||
s3c24xx_dclk->dev = &pdev->dev;
|
||||
s3c24xx_dclk->clk_data.num = DCLK_MAX_CLKS;
|
||||
platform_set_drvdata(pdev, s3c24xx_dclk);
|
||||
spin_lock_init(&s3c24xx_dclk->dclk_lock);
|
||||
|
||||
clk_table = devm_kzalloc(&pdev->dev,
|
||||
sizeof(struct clk *) * DCLK_MAX_CLKS,
|
||||
GFP_KERNEL);
|
||||
if (!clk_table)
|
||||
return -ENOMEM;
|
||||
|
||||
s3c24xx_dclk->clk_data.clks = clk_table;
|
||||
s3c24xx_dclk->clk_data.clk_num = DCLK_MAX_CLKS;
|
||||
|
||||
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
s3c24xx_dclk->base = devm_ioremap_resource(&pdev->dev, mem);
|
||||
if (IS_ERR(s3c24xx_dclk->base))
|
||||
|
@ -271,29 +269,29 @@ static int s3c24xx_dclk_probe(struct platform_device *pdev)
|
|||
platform_get_device_id(pdev)->driver_data;
|
||||
|
||||
|
||||
clk_table[MUX_DCLK0] = clk_register_mux(&pdev->dev, "mux_dclk0",
|
||||
clk_table[MUX_DCLK0] = clk_hw_register_mux(&pdev->dev, "mux_dclk0",
|
||||
dclk_variant->mux_parent_names,
|
||||
dclk_variant->mux_num_parents, 0,
|
||||
s3c24xx_dclk->base, 1, 1, 0,
|
||||
&s3c24xx_dclk->dclk_lock);
|
||||
clk_table[MUX_DCLK1] = clk_register_mux(&pdev->dev, "mux_dclk1",
|
||||
clk_table[MUX_DCLK1] = clk_hw_register_mux(&pdev->dev, "mux_dclk1",
|
||||
dclk_variant->mux_parent_names,
|
||||
dclk_variant->mux_num_parents, 0,
|
||||
s3c24xx_dclk->base, 17, 1, 0,
|
||||
&s3c24xx_dclk->dclk_lock);
|
||||
|
||||
clk_table[DIV_DCLK0] = clk_register_divider(&pdev->dev, "div_dclk0",
|
||||
clk_table[DIV_DCLK0] = clk_hw_register_divider(&pdev->dev, "div_dclk0",
|
||||
"mux_dclk0", 0, s3c24xx_dclk->base,
|
||||
4, 4, 0, &s3c24xx_dclk->dclk_lock);
|
||||
clk_table[DIV_DCLK1] = clk_register_divider(&pdev->dev, "div_dclk1",
|
||||
clk_table[DIV_DCLK1] = clk_hw_register_divider(&pdev->dev, "div_dclk1",
|
||||
"mux_dclk1", 0, s3c24xx_dclk->base,
|
||||
20, 4, 0, &s3c24xx_dclk->dclk_lock);
|
||||
|
||||
clk_table[GATE_DCLK0] = clk_register_gate(&pdev->dev, "gate_dclk0",
|
||||
clk_table[GATE_DCLK0] = clk_hw_register_gate(&pdev->dev, "gate_dclk0",
|
||||
"div_dclk0", CLK_SET_RATE_PARENT,
|
||||
s3c24xx_dclk->base, 0, 0,
|
||||
&s3c24xx_dclk->dclk_lock);
|
||||
clk_table[GATE_DCLK1] = clk_register_gate(&pdev->dev, "gate_dclk1",
|
||||
clk_table[GATE_DCLK1] = clk_hw_register_gate(&pdev->dev, "gate_dclk1",
|
||||
"div_dclk1", CLK_SET_RATE_PARENT,
|
||||
s3c24xx_dclk->base, 16, 0,
|
||||
&s3c24xx_dclk->dclk_lock);
|
||||
|
@ -312,15 +310,16 @@ static int s3c24xx_dclk_probe(struct platform_device *pdev)
|
|||
goto err_clk_register;
|
||||
}
|
||||
|
||||
ret = clk_register_clkdev(clk_table[MUX_DCLK0], "dclk0", NULL);
|
||||
ret = clk_hw_register_clkdev(clk_table[MUX_DCLK0], "dclk0", NULL);
|
||||
if (!ret)
|
||||
ret = clk_register_clkdev(clk_table[MUX_DCLK1], "dclk1", NULL);
|
||||
ret = clk_hw_register_clkdev(clk_table[MUX_DCLK1], "dclk1",
|
||||
NULL);
|
||||
if (!ret)
|
||||
ret = clk_register_clkdev(clk_table[MUX_CLKOUT0],
|
||||
"clkout0", NULL);
|
||||
ret = clk_hw_register_clkdev(clk_table[MUX_CLKOUT0],
|
||||
"clkout0", NULL);
|
||||
if (!ret)
|
||||
ret = clk_register_clkdev(clk_table[MUX_CLKOUT1],
|
||||
"clkout1", NULL);
|
||||
ret = clk_hw_register_clkdev(clk_table[MUX_CLKOUT1],
|
||||
"clkout1", NULL);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "failed to register aliases, %d\n", ret);
|
||||
goto err_clk_register;
|
||||
|
@ -332,12 +331,12 @@ static int s3c24xx_dclk_probe(struct platform_device *pdev)
|
|||
s3c24xx_dclk->dclk1_div_change_nb.notifier_call =
|
||||
s3c24xx_dclk1_div_notify;
|
||||
|
||||
ret = clk_notifier_register(clk_table[DIV_DCLK0],
|
||||
ret = clk_notifier_register(clk_table[DIV_DCLK0]->clk,
|
||||
&s3c24xx_dclk->dclk0_div_change_nb);
|
||||
if (ret)
|
||||
goto err_clk_register;
|
||||
|
||||
ret = clk_notifier_register(clk_table[DIV_DCLK1],
|
||||
ret = clk_notifier_register(clk_table[DIV_DCLK1]->clk,
|
||||
&s3c24xx_dclk->dclk1_div_change_nb);
|
||||
if (ret)
|
||||
goto err_dclk_notify;
|
||||
|
@ -345,12 +344,12 @@ static int s3c24xx_dclk_probe(struct platform_device *pdev)
|
|||
return 0;
|
||||
|
||||
err_dclk_notify:
|
||||
clk_notifier_unregister(clk_table[DIV_DCLK0],
|
||||
clk_notifier_unregister(clk_table[DIV_DCLK0]->clk,
|
||||
&s3c24xx_dclk->dclk0_div_change_nb);
|
||||
err_clk_register:
|
||||
for (i = 0; i < DCLK_MAX_CLKS; i++)
|
||||
if (clk_table[i] && !IS_ERR(clk_table[i]))
|
||||
clk_unregister(clk_table[i]);
|
||||
clk_hw_unregister(clk_table[i]);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -358,16 +357,16 @@ err_clk_register:
|
|||
static int s3c24xx_dclk_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct s3c24xx_dclk *s3c24xx_dclk = platform_get_drvdata(pdev);
|
||||
struct clk **clk_table = s3c24xx_dclk->clk_data.clks;
|
||||
struct clk_hw **clk_table = s3c24xx_dclk->clk_data.hws;
|
||||
int i;
|
||||
|
||||
clk_notifier_unregister(clk_table[DIV_DCLK1],
|
||||
clk_notifier_unregister(clk_table[DIV_DCLK1]->clk,
|
||||
&s3c24xx_dclk->dclk1_div_change_nb);
|
||||
clk_notifier_unregister(clk_table[DIV_DCLK0],
|
||||
clk_notifier_unregister(clk_table[DIV_DCLK0]->clk,
|
||||
&s3c24xx_dclk->dclk0_div_change_nb);
|
||||
|
||||
for (i = 0; i < DCLK_MAX_CLKS; i++)
|
||||
clk_unregister(clk_table[i]);
|
||||
clk_hw_unregister(clk_table[i]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -24,9 +24,8 @@
|
|||
#include <dt-bindings/clock/s5pv210-audss.h>
|
||||
|
||||
static DEFINE_SPINLOCK(lock);
|
||||
static struct clk **clk_table;
|
||||
static void __iomem *reg_base;
|
||||
static struct clk_onecell_data clk_data;
|
||||
static struct clk_hw_onecell_data *clk_data;
|
||||
|
||||
#define ASS_CLK_SRC 0x0
|
||||
#define ASS_CLK_DIV 0x4
|
||||
|
@ -71,6 +70,7 @@ static int s5pv210_audss_clk_probe(struct platform_device *pdev)
|
|||
const char *mout_audss_p[2];
|
||||
const char *mout_i2s_p[3];
|
||||
const char *hclk_p;
|
||||
struct clk_hw **clk_table;
|
||||
struct clk *hclk, *pll_ref, *pll_in, *cdclk, *sclk_audio;
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
|
@ -80,14 +80,16 @@ static int s5pv210_audss_clk_probe(struct platform_device *pdev)
|
|||
return PTR_ERR(reg_base);
|
||||
}
|
||||
|
||||
clk_table = devm_kzalloc(&pdev->dev,
|
||||
sizeof(struct clk *) * AUDSS_MAX_CLKS,
|
||||
clk_data = devm_kzalloc(&pdev->dev,
|
||||
sizeof(*clk_data) +
|
||||
sizeof(*clk_data->hws) * AUDSS_MAX_CLKS,
|
||||
GFP_KERNEL);
|
||||
if (!clk_table)
|
||||
|
||||
if (!clk_data)
|
||||
return -ENOMEM;
|
||||
|
||||
clk_data.clks = clk_table;
|
||||
clk_data.clk_num = AUDSS_MAX_CLKS;
|
||||
clk_data->num = AUDSS_MAX_CLKS;
|
||||
clk_table = clk_data->hws;
|
||||
|
||||
hclk = devm_clk_get(&pdev->dev, "hclk");
|
||||
if (IS_ERR(hclk)) {
|
||||
|
@ -116,7 +118,7 @@ static int s5pv210_audss_clk_probe(struct platform_device *pdev)
|
|||
else
|
||||
mout_audss_p[0] = "xxti";
|
||||
mout_audss_p[1] = __clk_get_name(pll_in);
|
||||
clk_table[CLK_MOUT_AUDSS] = clk_register_mux(NULL, "mout_audss",
|
||||
clk_table[CLK_MOUT_AUDSS] = clk_hw_register_mux(NULL, "mout_audss",
|
||||
mout_audss_p, ARRAY_SIZE(mout_audss_p),
|
||||
CLK_SET_RATE_NO_REPARENT,
|
||||
reg_base + ASS_CLK_SRC, 0, 1, 0, &lock);
|
||||
|
@ -127,44 +129,44 @@ static int s5pv210_audss_clk_probe(struct platform_device *pdev)
|
|||
else
|
||||
mout_i2s_p[1] = "iiscdclk0";
|
||||
mout_i2s_p[2] = __clk_get_name(sclk_audio);
|
||||
clk_table[CLK_MOUT_I2S_A] = clk_register_mux(NULL, "mout_i2s_audss",
|
||||
clk_table[CLK_MOUT_I2S_A] = clk_hw_register_mux(NULL, "mout_i2s_audss",
|
||||
mout_i2s_p, ARRAY_SIZE(mout_i2s_p),
|
||||
CLK_SET_RATE_NO_REPARENT,
|
||||
reg_base + ASS_CLK_SRC, 2, 2, 0, &lock);
|
||||
|
||||
clk_table[CLK_DOUT_AUD_BUS] = clk_register_divider(NULL,
|
||||
clk_table[CLK_DOUT_AUD_BUS] = clk_hw_register_divider(NULL,
|
||||
"dout_aud_bus", "mout_audss", 0,
|
||||
reg_base + ASS_CLK_DIV, 0, 4, 0, &lock);
|
||||
clk_table[CLK_DOUT_I2S_A] = clk_register_divider(NULL, "dout_i2s_audss",
|
||||
"mout_i2s_audss", 0, reg_base + ASS_CLK_DIV,
|
||||
4, 4, 0, &lock);
|
||||
clk_table[CLK_DOUT_I2S_A] = clk_hw_register_divider(NULL,
|
||||
"dout_i2s_audss", "mout_i2s_audss", 0,
|
||||
reg_base + ASS_CLK_DIV, 4, 4, 0, &lock);
|
||||
|
||||
clk_table[CLK_I2S] = clk_register_gate(NULL, "i2s_audss",
|
||||
clk_table[CLK_I2S] = clk_hw_register_gate(NULL, "i2s_audss",
|
||||
"dout_i2s_audss", CLK_SET_RATE_PARENT,
|
||||
reg_base + ASS_CLK_GATE, 6, 0, &lock);
|
||||
|
||||
hclk_p = __clk_get_name(hclk);
|
||||
|
||||
clk_table[CLK_HCLK_I2S] = clk_register_gate(NULL, "hclk_i2s_audss",
|
||||
clk_table[CLK_HCLK_I2S] = clk_hw_register_gate(NULL, "hclk_i2s_audss",
|
||||
hclk_p, CLK_IGNORE_UNUSED,
|
||||
reg_base + ASS_CLK_GATE, 5, 0, &lock);
|
||||
clk_table[CLK_HCLK_UART] = clk_register_gate(NULL, "hclk_uart_audss",
|
||||
clk_table[CLK_HCLK_UART] = clk_hw_register_gate(NULL, "hclk_uart_audss",
|
||||
hclk_p, CLK_IGNORE_UNUSED,
|
||||
reg_base + ASS_CLK_GATE, 4, 0, &lock);
|
||||
clk_table[CLK_HCLK_HWA] = clk_register_gate(NULL, "hclk_hwa_audss",
|
||||
clk_table[CLK_HCLK_HWA] = clk_hw_register_gate(NULL, "hclk_hwa_audss",
|
||||
hclk_p, CLK_IGNORE_UNUSED,
|
||||
reg_base + ASS_CLK_GATE, 3, 0, &lock);
|
||||
clk_table[CLK_HCLK_DMA] = clk_register_gate(NULL, "hclk_dma_audss",
|
||||
clk_table[CLK_HCLK_DMA] = clk_hw_register_gate(NULL, "hclk_dma_audss",
|
||||
hclk_p, CLK_IGNORE_UNUSED,
|
||||
reg_base + ASS_CLK_GATE, 2, 0, &lock);
|
||||
clk_table[CLK_HCLK_BUF] = clk_register_gate(NULL, "hclk_buf_audss",
|
||||
clk_table[CLK_HCLK_BUF] = clk_hw_register_gate(NULL, "hclk_buf_audss",
|
||||
hclk_p, CLK_IGNORE_UNUSED,
|
||||
reg_base + ASS_CLK_GATE, 1, 0, &lock);
|
||||
clk_table[CLK_HCLK_RP] = clk_register_gate(NULL, "hclk_rp_audss",
|
||||
clk_table[CLK_HCLK_RP] = clk_hw_register_gate(NULL, "hclk_rp_audss",
|
||||
hclk_p, CLK_IGNORE_UNUSED,
|
||||
reg_base + ASS_CLK_GATE, 0, 0, &lock);
|
||||
|
||||
for (i = 0; i < clk_data.clk_num; i++) {
|
||||
for (i = 0; i < clk_data->num; i++) {
|
||||
if (IS_ERR(clk_table[i])) {
|
||||
dev_err(&pdev->dev, "failed to register clock %d\n", i);
|
||||
ret = PTR_ERR(clk_table[i]);
|
||||
|
@ -172,8 +174,8 @@ static int s5pv210_audss_clk_probe(struct platform_device *pdev)
|
|||
}
|
||||
}
|
||||
|
||||
ret = of_clk_add_provider(pdev->dev.of_node, of_clk_src_onecell_get,
|
||||
&clk_data);
|
||||
ret = of_clk_add_hw_provider(pdev->dev.of_node, of_clk_hw_onecell_get,
|
||||
clk_data);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "failed to add clock provider\n");
|
||||
goto unregister;
|
||||
|
@ -186,9 +188,9 @@ static int s5pv210_audss_clk_probe(struct platform_device *pdev)
|
|||
return 0;
|
||||
|
||||
unregister:
|
||||
for (i = 0; i < clk_data.clk_num; i++) {
|
||||
for (i = 0; i < clk_data->num; i++) {
|
||||
if (!IS_ERR(clk_table[i]))
|
||||
clk_unregister(clk_table[i]);
|
||||
clk_hw_unregister(clk_table[i]);
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
|
|
@ -60,23 +60,18 @@ struct samsung_clk_provider *__init samsung_clk_init(struct device_node *np,
|
|||
void __iomem *base, unsigned long nr_clks)
|
||||
{
|
||||
struct samsung_clk_provider *ctx;
|
||||
struct clk **clk_table;
|
||||
int i;
|
||||
|
||||
ctx = kzalloc(sizeof(struct samsung_clk_provider), GFP_KERNEL);
|
||||
ctx = kzalloc(sizeof(struct samsung_clk_provider) +
|
||||
sizeof(*ctx->clk_data.hws) * nr_clks, GFP_KERNEL);
|
||||
if (!ctx)
|
||||
panic("could not allocate clock provider context.\n");
|
||||
|
||||
clk_table = kcalloc(nr_clks, sizeof(struct clk *), GFP_KERNEL);
|
||||
if (!clk_table)
|
||||
panic("could not allocate clock lookup table\n");
|
||||
|
||||
for (i = 0; i < nr_clks; ++i)
|
||||
clk_table[i] = ERR_PTR(-ENOENT);
|
||||
ctx->clk_data.hws[i] = ERR_PTR(-ENOENT);
|
||||
|
||||
ctx->reg_base = base;
|
||||
ctx->clk_data.clks = clk_table;
|
||||
ctx->clk_data.clk_num = nr_clks;
|
||||
ctx->clk_data.num = nr_clks;
|
||||
spin_lock_init(&ctx->lock);
|
||||
|
||||
return ctx;
|
||||
|
@ -86,18 +81,18 @@ void __init samsung_clk_of_add_provider(struct device_node *np,
|
|||
struct samsung_clk_provider *ctx)
|
||||
{
|
||||
if (np) {
|
||||
if (of_clk_add_provider(np, of_clk_src_onecell_get,
|
||||
if (of_clk_add_hw_provider(np, of_clk_hw_onecell_get,
|
||||
&ctx->clk_data))
|
||||
panic("could not register clk provider\n");
|
||||
}
|
||||
}
|
||||
|
||||
/* add a clock instance to the clock lookup table used for dt based lookup */
|
||||
void samsung_clk_add_lookup(struct samsung_clk_provider *ctx, struct clk *clk,
|
||||
unsigned int id)
|
||||
void samsung_clk_add_lookup(struct samsung_clk_provider *ctx,
|
||||
struct clk_hw *clk_hw, unsigned int id)
|
||||
{
|
||||
if (ctx->clk_data.clks && id)
|
||||
ctx->clk_data.clks[id] = clk;
|
||||
if (id)
|
||||
ctx->clk_data.hws[id] = clk_hw;
|
||||
}
|
||||
|
||||
/* register a list of aliases */
|
||||
|
@ -105,14 +100,9 @@ void __init samsung_clk_register_alias(struct samsung_clk_provider *ctx,
|
|||
const struct samsung_clock_alias *list,
|
||||
unsigned int nr_clk)
|
||||
{
|
||||
struct clk *clk;
|
||||
struct clk_hw *clk_hw;
|
||||
unsigned int idx, ret;
|
||||
|
||||
if (!ctx->clk_data.clks) {
|
||||
pr_err("%s: clock table missing\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
for (idx = 0; idx < nr_clk; idx++, list++) {
|
||||
if (!list->id) {
|
||||
pr_err("%s: clock id missing for index %d\n", __func__,
|
||||
|
@ -120,14 +110,15 @@ void __init samsung_clk_register_alias(struct samsung_clk_provider *ctx,
|
|||
continue;
|
||||
}
|
||||
|
||||
clk = ctx->clk_data.clks[list->id];
|
||||
if (!clk) {
|
||||
clk_hw = ctx->clk_data.hws[list->id];
|
||||
if (!clk_hw) {
|
||||
pr_err("%s: failed to find clock %d\n", __func__,
|
||||
list->id);
|
||||
continue;
|
||||
}
|
||||
|
||||
ret = clk_register_clkdev(clk, list->alias, list->dev_name);
|
||||
ret = clk_hw_register_clkdev(clk_hw, list->alias,
|
||||
list->dev_name);
|
||||
if (ret)
|
||||
pr_err("%s: failed to register lookup %s\n",
|
||||
__func__, list->alias);
|
||||
|
@ -139,25 +130,25 @@ void __init samsung_clk_register_fixed_rate(struct samsung_clk_provider *ctx,
|
|||
const struct samsung_fixed_rate_clock *list,
|
||||
unsigned int nr_clk)
|
||||
{
|
||||
struct clk *clk;
|
||||
struct clk_hw *clk_hw;
|
||||
unsigned int idx, ret;
|
||||
|
||||
for (idx = 0; idx < nr_clk; idx++, list++) {
|
||||
clk = clk_register_fixed_rate(NULL, list->name,
|
||||
clk_hw = clk_hw_register_fixed_rate(NULL, list->name,
|
||||
list->parent_name, list->flags, list->fixed_rate);
|
||||
if (IS_ERR(clk)) {
|
||||
if (IS_ERR(clk_hw)) {
|
||||
pr_err("%s: failed to register clock %s\n", __func__,
|
||||
list->name);
|
||||
continue;
|
||||
}
|
||||
|
||||
samsung_clk_add_lookup(ctx, clk, list->id);
|
||||
samsung_clk_add_lookup(ctx, clk_hw, list->id);
|
||||
|
||||
/*
|
||||
* Unconditionally add a clock lookup for the fixed rate clocks.
|
||||
* There are not many of these on any of Samsung platforms.
|
||||
*/
|
||||
ret = clk_register_clkdev(clk, list->name, NULL);
|
||||
ret = clk_hw_register_clkdev(clk_hw, list->name, NULL);
|
||||
if (ret)
|
||||
pr_err("%s: failed to register clock lookup for %s",
|
||||
__func__, list->name);
|
||||
|
@ -168,19 +159,19 @@ void __init samsung_clk_register_fixed_rate(struct samsung_clk_provider *ctx,
|
|||
void __init samsung_clk_register_fixed_factor(struct samsung_clk_provider *ctx,
|
||||
const struct samsung_fixed_factor_clock *list, unsigned int nr_clk)
|
||||
{
|
||||
struct clk *clk;
|
||||
struct clk_hw *clk_hw;
|
||||
unsigned int idx;
|
||||
|
||||
for (idx = 0; idx < nr_clk; idx++, list++) {
|
||||
clk = clk_register_fixed_factor(NULL, list->name,
|
||||
clk_hw = clk_hw_register_fixed_factor(NULL, list->name,
|
||||
list->parent_name, list->flags, list->mult, list->div);
|
||||
if (IS_ERR(clk)) {
|
||||
if (IS_ERR(clk_hw)) {
|
||||
pr_err("%s: failed to register clock %s\n", __func__,
|
||||
list->name);
|
||||
continue;
|
||||
}
|
||||
|
||||
samsung_clk_add_lookup(ctx, clk, list->id);
|
||||
samsung_clk_add_lookup(ctx, clk_hw, list->id);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -189,25 +180,25 @@ void __init samsung_clk_register_mux(struct samsung_clk_provider *ctx,
|
|||
const struct samsung_mux_clock *list,
|
||||
unsigned int nr_clk)
|
||||
{
|
||||
struct clk *clk;
|
||||
struct clk_hw *clk_hw;
|
||||
unsigned int idx, ret;
|
||||
|
||||
for (idx = 0; idx < nr_clk; idx++, list++) {
|
||||
clk = clk_register_mux(NULL, list->name, list->parent_names,
|
||||
list->num_parents, list->flags,
|
||||
clk_hw = clk_hw_register_mux(NULL, list->name,
|
||||
list->parent_names, list->num_parents, list->flags,
|
||||
ctx->reg_base + list->offset,
|
||||
list->shift, list->width, list->mux_flags, &ctx->lock);
|
||||
if (IS_ERR(clk)) {
|
||||
if (IS_ERR(clk_hw)) {
|
||||
pr_err("%s: failed to register clock %s\n", __func__,
|
||||
list->name);
|
||||
continue;
|
||||
}
|
||||
|
||||
samsung_clk_add_lookup(ctx, clk, list->id);
|
||||
samsung_clk_add_lookup(ctx, clk_hw, list->id);
|
||||
|
||||
/* register a clock lookup only if a clock alias is specified */
|
||||
if (list->alias) {
|
||||
ret = clk_register_clkdev(clk, list->alias,
|
||||
ret = clk_hw_register_clkdev(clk_hw, list->alias,
|
||||
list->dev_name);
|
||||
if (ret)
|
||||
pr_err("%s: failed to register lookup %s\n",
|
||||
|
@ -221,32 +212,32 @@ void __init samsung_clk_register_div(struct samsung_clk_provider *ctx,
|
|||
const struct samsung_div_clock *list,
|
||||
unsigned int nr_clk)
|
||||
{
|
||||
struct clk *clk;
|
||||
struct clk_hw *clk_hw;
|
||||
unsigned int idx, ret;
|
||||
|
||||
for (idx = 0; idx < nr_clk; idx++, list++) {
|
||||
if (list->table)
|
||||
clk = clk_register_divider_table(NULL, list->name,
|
||||
list->parent_name, list->flags,
|
||||
clk_hw = clk_hw_register_divider_table(NULL,
|
||||
list->name, list->parent_name, list->flags,
|
||||
ctx->reg_base + list->offset,
|
||||
list->shift, list->width, list->div_flags,
|
||||
list->table, &ctx->lock);
|
||||
else
|
||||
clk = clk_register_divider(NULL, list->name,
|
||||
clk_hw = clk_hw_register_divider(NULL, list->name,
|
||||
list->parent_name, list->flags,
|
||||
ctx->reg_base + list->offset, list->shift,
|
||||
list->width, list->div_flags, &ctx->lock);
|
||||
if (IS_ERR(clk)) {
|
||||
if (IS_ERR(clk_hw)) {
|
||||
pr_err("%s: failed to register clock %s\n", __func__,
|
||||
list->name);
|
||||
continue;
|
||||
}
|
||||
|
||||
samsung_clk_add_lookup(ctx, clk, list->id);
|
||||
samsung_clk_add_lookup(ctx, clk_hw, list->id);
|
||||
|
||||
/* register a clock lookup only if a clock alias is specified */
|
||||
if (list->alias) {
|
||||
ret = clk_register_clkdev(clk, list->alias,
|
||||
ret = clk_hw_register_clkdev(clk_hw, list->alias,
|
||||
list->dev_name);
|
||||
if (ret)
|
||||
pr_err("%s: failed to register lookup %s\n",
|
||||
|
@ -260,14 +251,14 @@ void __init samsung_clk_register_gate(struct samsung_clk_provider *ctx,
|
|||
const struct samsung_gate_clock *list,
|
||||
unsigned int nr_clk)
|
||||
{
|
||||
struct clk *clk;
|
||||
struct clk_hw *clk_hw;
|
||||
unsigned int idx, ret;
|
||||
|
||||
for (idx = 0; idx < nr_clk; idx++, list++) {
|
||||
clk = clk_register_gate(NULL, list->name, list->parent_name,
|
||||
clk_hw = clk_hw_register_gate(NULL, list->name, list->parent_name,
|
||||
list->flags, ctx->reg_base + list->offset,
|
||||
list->bit_idx, list->gate_flags, &ctx->lock);
|
||||
if (IS_ERR(clk)) {
|
||||
if (IS_ERR(clk_hw)) {
|
||||
pr_err("%s: failed to register clock %s\n", __func__,
|
||||
list->name);
|
||||
continue;
|
||||
|
@ -275,14 +266,14 @@ void __init samsung_clk_register_gate(struct samsung_clk_provider *ctx,
|
|||
|
||||
/* register a clock lookup only if a clock alias is specified */
|
||||
if (list->alias) {
|
||||
ret = clk_register_clkdev(clk, list->alias,
|
||||
ret = clk_hw_register_clkdev(clk_hw, list->alias,
|
||||
list->dev_name);
|
||||
if (ret)
|
||||
pr_err("%s: failed to register lookup %s\n",
|
||||
__func__, list->alias);
|
||||
}
|
||||
|
||||
samsung_clk_add_lookup(ctx, clk, list->id);
|
||||
samsung_clk_add_lookup(ctx, clk_hw, list->id);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -16,18 +16,17 @@
|
|||
#include <linux/clk-provider.h>
|
||||
#include "clk-pll.h"
|
||||
|
||||
struct clk;
|
||||
|
||||
/**
|
||||
* struct samsung_clk_provider: information about clock provider
|
||||
* @reg_base: virtual address for the register base.
|
||||
* @clk_data: holds clock related data like clk* and number of clocks.
|
||||
* @lock: maintains exclusion between callbacks for a given clock-provider.
|
||||
* @clk_data: holds clock related data like clk_hw* and number of clocks.
|
||||
*/
|
||||
struct samsung_clk_provider {
|
||||
void __iomem *reg_base;
|
||||
struct clk_onecell_data clk_data;
|
||||
spinlock_t lock;
|
||||
/* clk_data must be the last entry due to variable lenght 'hws' array */
|
||||
struct clk_hw_onecell_data clk_data;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -367,7 +366,7 @@ extern void __init samsung_clk_of_register_fixed_ext(
|
|||
const struct of_device_id *clk_matches);
|
||||
|
||||
extern void samsung_clk_add_lookup(struct samsung_clk_provider *ctx,
|
||||
struct clk *clk, unsigned int id);
|
||||
struct clk_hw *clk_hw, unsigned int id);
|
||||
|
||||
extern void __init samsung_clk_register_alias(struct samsung_clk_provider *ctx,
|
||||
const struct samsung_clock_alias *list,
|
||||
|
|
|
@ -217,6 +217,9 @@
|
|||
#define CLK_MOUT_MCLK_CDREX 654
|
||||
#define CLK_MOUT_BPLL 655
|
||||
#define CLK_MOUT_MX_MSPLL_CCORE 656
|
||||
#define CLK_MOUT_EPLL 657
|
||||
#define CLK_MOUT_MAU_EPLL 658
|
||||
#define CLK_MOUT_USER_MAU_EPLL 659
|
||||
|
||||
/* divider clocks */
|
||||
#define CLK_DOUT_PIXEL 768
|
||||
|
|
Loading…
Reference in New Issue