Fixed MTP to work with TWRP

This commit is contained in:
awab228 2018-06-19 23:16:04 +02:00
commit f6dfaef42e
50820 changed files with 20846062 additions and 0 deletions

View file

@ -0,0 +1,26 @@
config COMMON_CLK_SAMSUNG
bool
select COMMON_CLK
config S3C2410_COMMON_CLK
bool
select COMMON_CLK_SAMSUNG
help
Build the s3c2410 clock driver based on the common clock framework.
config S3C2410_COMMON_DCLK
bool
select COMMON_CLK_SAMSUNG
select REGMAP_MMIO
help
Temporary symbol to build the dclk driver based on the common clock
framework.
config S3C2412_COMMON_CLK
bool
select COMMON_CLK_SAMSUNG
config S3C2443_COMMON_CLK
bool
select COMMON_CLK_SAMSUNG

View file

@ -0,0 +1,34 @@
#
# Samsung Clock specific Makefile
#
obj-$(CONFIG_SOC_EXYNOS3250) += clk-exynos3250.o
obj-$(CONFIG_ARCH_EXYNOS4) += clk-exynos4.o
obj-$(CONFIG_SOC_EXYNOS5250) += clk-exynos5250.o
obj-$(CONFIG_SOC_EXYNOS5260) += clk-exynos5260.o
obj-$(CONFIG_SOC_EXYNOS5410) += clk-exynos5410.o
obj-$(CONFIG_SOC_EXYNOS5420) += clk-exynos5420.o
obj-$(CONFIG_SOC_EXYNOS5440) += clk-exynos5440.o
obj-$(CONFIG_SOC_EXYNOS7570) += clk-exynos7570.o
obj-$(CONFIG_SOC_EXYNOS7870) += clk-exynos7870.o
ifeq ($(CONFIG_SOC_EXYNOS8890), y)
ifeq ($(CONFIG_SOC_EXYNOS8890_EVT1), y)
obj-y += clk-exynos8890.o
else
obj-y += clk-exynos8890_evt0.o
endif
endif
ifeq ($(CONFIG_ARM64), y)
obj-y += composite.o
else
obj-$(CONFIG_COMMON_CLK) += clk.o clk-pll.o
endif
obj-$(CONFIG_ARCH_EXYNOS) += clk-exynos-audss.o
obj-$(CONFIG_ARCH_EXYNOS) += clk-exynos-clkout.o
obj-$(CONFIG_S3C2410_COMMON_CLK)+= clk-s3c2410.o
obj-$(CONFIG_S3C2410_COMMON_DCLK)+= clk-s3c2410-dclk.o
obj-$(CONFIG_S3C2412_COMMON_CLK)+= clk-s3c2412.o
obj-$(CONFIG_S3C2443_COMMON_CLK)+= clk-s3c2443.o
obj-$(CONFIG_ARCH_S3C64XX) += clk-s3c64xx.o
obj-$(CONFIG_ARCH_S5PV210) += clk-s5pv210.o clk-s5pv210-audss.o
obj-$(CONFIG_PWM_SAMSUNG) += clk-exynos-pwm.o

View file

@ -0,0 +1,252 @@
/*
* Copyright (c) 2013 Samsung Electronics Co., Ltd.
* Author: Padmavathi Venna <padma.v@samsung.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Common Clock Framework support for Audio Subsystem Clock Controller.
*/
#include <linux/clkdev.h>
#include <linux/io.h>
#include <linux/clk-provider.h>
#include <linux/of_address.h>
#include <linux/syscore_ops.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <dt-bindings/clock/exynos-audss-clk.h>
enum exynos_audss_clk_type {
TYPE_EXYNOS4210,
TYPE_EXYNOS5250,
TYPE_EXYNOS5420,
};
static DEFINE_SPINLOCK(lock);
static struct clk **clk_table;
static void __iomem *reg_base;
static struct clk_onecell_data clk_data;
#define ASS_CLK_SRC 0x0
#define ASS_CLK_DIV 0x4
#define ASS_CLK_GATE 0x8
#ifdef CONFIG_PM_SLEEP
static unsigned long reg_save[][2] = {
{ASS_CLK_SRC, 0},
{ASS_CLK_DIV, 0},
{ASS_CLK_GATE, 0},
};
static int exynos_audss_clk_suspend(void)
{
int i;
for (i = 0; i < ARRAY_SIZE(reg_save); i++)
reg_save[i][1] = readl(reg_base + reg_save[i][0]);
return 0;
}
static void exynos_audss_clk_resume(void)
{
int i;
for (i = 0; i < ARRAY_SIZE(reg_save); i++)
writel(reg_save[i][1], reg_base + reg_save[i][0]);
}
static struct syscore_ops exynos_audss_clk_syscore_ops = {
.suspend = exynos_audss_clk_suspend,
.resume = exynos_audss_clk_resume,
};
#endif /* CONFIG_PM_SLEEP */
static const struct of_device_id exynos_audss_clk_of_match[] = {
{ .compatible = "samsung,exynos4210-audss-clock",
.data = (void *)TYPE_EXYNOS4210, },
{ .compatible = "samsung,exynos5250-audss-clock",
.data = (void *)TYPE_EXYNOS5250, },
{ .compatible = "samsung,exynos5420-audss-clock",
.data = (void *)TYPE_EXYNOS5420, },
{},
};
/* register exynos_audss clocks */
static int exynos_audss_clk_probe(struct platform_device *pdev)
{
int i, ret = 0;
struct resource *res;
const char *mout_audss_p[] = {"fin_pll", "fout_epll"};
const char *mout_i2s_p[] = {"mout_audss", "cdclk0", "sclk_audio0"};
const char *sclk_pcm_p = "sclk_pcm0";
struct clk *pll_ref, *pll_in, *cdclk, *sclk_audio, *sclk_pcm_in;
const struct of_device_id *match;
enum exynos_audss_clk_type variant;
match = of_match_node(exynos_audss_clk_of_match, pdev->dev.of_node);
if (!match)
return -EINVAL;
variant = (enum exynos_audss_clk_type)match->data;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
reg_base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(reg_base)) {
dev_err(&pdev->dev, "failed to map audss registers\n");
return PTR_ERR(reg_base);
}
clk_table = devm_kzalloc(&pdev->dev,
sizeof(struct clk *) * EXYNOS_AUDSS_MAX_CLKS,
GFP_KERNEL);
if (!clk_table)
return -ENOMEM;
clk_data.clks = clk_table;
if (variant == TYPE_EXYNOS5420)
clk_data.clk_num = EXYNOS_AUDSS_MAX_CLKS;
else
clk_data.clk_num = EXYNOS_AUDSS_MAX_CLKS - 1;
pll_ref = devm_clk_get(&pdev->dev, "pll_ref");
pll_in = devm_clk_get(&pdev->dev, "pll_in");
if (!IS_ERR(pll_ref))
mout_audss_p[0] = __clk_get_name(pll_ref);
if (!IS_ERR(pll_in))
mout_audss_p[1] = __clk_get_name(pll_in);
clk_table[EXYNOS_MOUT_AUDSS] = clk_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);
cdclk = devm_clk_get(&pdev->dev, "cdclk");
sclk_audio = devm_clk_get(&pdev->dev, "sclk_audio");
if (!IS_ERR(cdclk))
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",
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",
"mout_audss", 0, reg_base + ASS_CLK_DIV, 0, 4,
0, &lock);
clk_table[EXYNOS_DOUT_AUD_BUS] = clk_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",
"mout_i2s", 0, reg_base + ASS_CLK_DIV, 8, 4, 0,
&lock);
clk_table[EXYNOS_SRP_CLK] = clk_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",
"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",
"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",
"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",
sclk_pcm_p, CLK_SET_RATE_PARENT,
reg_base + ASS_CLK_GATE, 5, 0, &lock);
if (variant == TYPE_EXYNOS5420) {
clk_table[EXYNOS_ADMA] = clk_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++) {
if (IS_ERR(clk_table[i])) {
dev_err(&pdev->dev, "failed to register clock %d\n", i);
ret = PTR_ERR(clk_table[i]);
goto unregister;
}
}
ret = of_clk_add_provider(pdev->dev.of_node, of_clk_src_onecell_get,
&clk_data);
if (ret) {
dev_err(&pdev->dev, "failed to add clock provider\n");
goto unregister;
}
#ifdef CONFIG_PM_SLEEP
register_syscore_ops(&exynos_audss_clk_syscore_ops);
#endif
dev_info(&pdev->dev, "setup completed\n");
return 0;
unregister:
for (i = 0; i < clk_data.clk_num; i++) {
if (!IS_ERR(clk_table[i]))
clk_unregister(clk_table[i]);
}
return ret;
}
static int exynos_audss_clk_remove(struct platform_device *pdev)
{
int i;
#ifdef CONFIG_PM_SLEEP
unregister_syscore_ops(&exynos_audss_clk_syscore_ops);
#endif
of_clk_del_provider(pdev->dev.of_node);
for (i = 0; i < clk_data.clk_num; i++) {
if (!IS_ERR(clk_table[i]))
clk_unregister(clk_table[i]);
}
return 0;
}
static struct platform_driver exynos_audss_clk_driver = {
.driver = {
.name = "exynos-audss-clk",
.owner = THIS_MODULE,
.of_match_table = exynos_audss_clk_of_match,
},
.probe = exynos_audss_clk_probe,
.remove = exynos_audss_clk_remove,
};
static int __init exynos_audss_clk_init(void)
{
return platform_driver_register(&exynos_audss_clk_driver);
}
core_initcall(exynos_audss_clk_init);
static void __exit exynos_audss_clk_exit(void)
{
platform_driver_unregister(&exynos_audss_clk_driver);
}
module_exit(exynos_audss_clk_exit);
MODULE_AUTHOR("Padmavathi Venna <padma.v@samsung.com>");
MODULE_DESCRIPTION("Exynos Audio Subsystem Clock Controller");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS("platform:exynos-audss-clk");

View file

@ -0,0 +1,153 @@
/*
* Copyright (c) 2014 Samsung Electronics Co., Ltd.
* Author: Tomasz Figa <t.figa@samsung.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Clock driver for Exynos clock output
*/
#include <linux/clk.h>
#include <linux/clkdev.h>
#include <linux/clk-provider.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/syscore_ops.h>
#define EXYNOS_CLKOUT_NR_CLKS 1
#define EXYNOS_CLKOUT_PARENTS 32
#define EXYNOS_PMU_DEBUG_REG 0xa00
#define EXYNOS_CLKOUT_DISABLE_SHIFT 0
#define EXYNOS_CLKOUT_MUX_SHIFT 8
#define EXYNOS4_CLKOUT_MUX_MASK 0xf
#define EXYNOS5_CLKOUT_MUX_MASK 0x1f
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;
};
static struct exynos_clkout *clkout;
static int exynos_clkout_suspend(void)
{
clkout->pmu_debug_save = readl(clkout->reg + EXYNOS_PMU_DEBUG_REG);
return 0;
}
static void exynos_clkout_resume(void)
{
writel(clkout->pmu_debug_save, clkout->reg + EXYNOS_PMU_DEBUG_REG);
}
static struct syscore_ops exynos_clkout_syscore_ops = {
.suspend = exynos_clkout_suspend,
.resume = exynos_clkout_resume,
};
static void __init exynos_clkout_init(struct device_node *node, u32 mux_mask)
{
const char *parent_names[EXYNOS_CLKOUT_PARENTS];
struct clk *parents[EXYNOS_CLKOUT_PARENTS];
int parent_count;
int ret;
int i;
clkout = kzalloc(sizeof(*clkout), GFP_KERNEL);
if (!clkout)
return;
spin_lock_init(&clkout->slock);
parent_count = 0;
for (i = 0; i < EXYNOS_CLKOUT_PARENTS; ++i) {
char name[] = "clkoutXX";
snprintf(name, sizeof(name), "clkout%d", i);
parents[i] = of_clk_get_by_name(node, name);
if (IS_ERR(parents[i])) {
parent_names[i] = "none";
continue;
}
parent_names[i] = __clk_get_name(parents[i]);
parent_count = i + 1;
}
if (!parent_count)
goto free_clkout;
clkout->reg = of_iomap(node, 0);
if (!clkout->reg)
goto clks_put;
clkout->gate.reg = clkout->reg + EXYNOS_PMU_DEBUG_REG;
clkout->gate.bit_idx = EXYNOS_CLKOUT_DISABLE_SHIFT;
clkout->gate.flags = CLK_GATE_SET_TO_DISABLE;
clkout->gate.lock = &clkout->slock;
clkout->mux.reg = clkout->reg + EXYNOS_PMU_DEBUG_REG;
clkout->mux.mask = mux_mask;
clkout->mux.shift = EXYNOS_CLKOUT_MUX_SHIFT;
clkout->mux.lock = &clkout->slock;
clkout->clk_table[0] = clk_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]))
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);
if (ret)
goto err_clk_unreg;
register_syscore_ops(&exynos_clkout_syscore_ops);
return;
err_clk_unreg:
clk_unregister(clkout->clk_table[0]);
err_unmap:
iounmap(clkout->reg);
clks_put:
for (i = 0; i < EXYNOS_CLKOUT_PARENTS; ++i)
if (!IS_ERR(parents[i]))
clk_put(parents[i]);
free_clkout:
kfree(clkout);
pr_err("%s: failed to register clkout clock\n", __func__);
}
static void __init exynos4_clkout_init(struct device_node *node)
{
exynos_clkout_init(node, EXYNOS4_CLKOUT_MUX_MASK);
}
CLK_OF_DECLARE(exynos4210_clkout, "samsung,exynos4210-pmu",
exynos4_clkout_init);
CLK_OF_DECLARE(exynos4212_clkout, "samsung,exynos4212-pmu",
exynos4_clkout_init);
CLK_OF_DECLARE(exynos4412_clkout, "samsung,exynos4412-pmu",
exynos4_clkout_init);
static void __init exynos5_clkout_init(struct device_node *node)
{
exynos_clkout_init(node, EXYNOS5_CLKOUT_MUX_MASK);
}
CLK_OF_DECLARE(exynos5250_clkout, "samsung,exynos5250-pmu",
exynos5_clkout_init);
CLK_OF_DECLARE(exynos5420_clkout, "samsung,exynos5420-pmu",
exynos5_clkout_init);

View file

@ -0,0 +1,190 @@
/*
* Copyright (c) 2013 Samsung Electronics Co., Ltd.
* Author: Hyunki Koo <hyunki00.koo@samsung.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Common Clock Framework support for pwm timer Clock Controller.
*/
#include <linux/clkdev.h>
#include <linux/io.h>
#include <linux/clk-provider.h>
#include <linux/of_address.h>
#include "clk.h"
/* Each of the timers 0 through 5 go through the following
* clock tree, with the inputs depending on the timers.
*
* pclk ---- [ prescaler 0 ] -+---> timer 0
* +---> timer 1
*
* pclk ---- [ prescaler 1 ] -+---> timer 2
* +---> timer 3
* \---> timer 4
*
* Which are fed into the timers as so:
*
* prescaled 0 ---- [ div 2,4,8,16 ] ---\
* [mux] -> timer 0 (tin)
* tclk 0 ------------------------------/
*
* prescaled 0 ---- [ div 2,4,8,16 ] ---\
* [mux] -> timer 1 (tin)
* tclk 0 ------------------------------/
*
*
* prescaled 1 ---- [ div 2,4,8,16 ] ---\
* [mux] -> timer 2 (tin)
* tclk 1 ------------------------------/
*
* prescaled 1 ---- [ div 2,4,8,16 ] ---\
* [mux] -> timer 3 (tin)
* tclk 1 ------------------------------/
*
* prescaled 1 ---- [ div 2,4,8, 16 ] --\
* [mux] -> timer 4 (tin)
* tclk 1 ------------------------------/
*
* Since the mux and the divider are tied together in the
* same register space, it is impossible to set the parent
* and the rate at the same time. To avoid this, we add an
* intermediate 'prescaled-and-divided' clock to select
* as the parent for the timer input clock called tdiv.
*
* prescaled clk --> pwm-tdiv ---\
* [ mux ] --> timer X
* tclk -------------------------/
*
* tclk is deprecated in exynos
*
*/
static DEFINE_SPINLOCK(lock);
static struct clk **clk_table;
static struct clk_onecell_data clk_data;
#define REG_TCFG0 0x00
#define REG_TCFG1 0x04
#define REG_TCON 0x08
#define REG_TINT_CSTAT 0x44
#define MASK_TCFG0_PRESCALE0 0x00FF
#define MASK_TCFG0_PRESCALE1 0xFF00
enum exynos_pwm_clks {
pwm_clock = 0,
pwm_scaler0,
pwm_scaler1,
pwm_tclk0,
pwm_tclk1,
pwm_tdiv0 = 5,
pwm_tdiv1,
pwm_tdiv2,
pwm_tdiv3,
pwm_tdiv4,
pwm_tin0 = 10,
pwm_tin1,
pwm_tin2,
pwm_tin3,
pwm_tin4,
exynos_pwm_max_clks,
};
static const char *pwm_tin0_p[] = { "pwm-tdiv0", "pwm-tclk" };
static const char *pwm_tin1_p[] = { "pwm-tdiv1", "pwm-tclk" };
static const char *pwm_tin2_p[] = { "pwm-tdiv2", "pwm-tclk" };
static const char *pwm_tin3_p[] = { "pwm-tdiv3", "pwm-tclk" };
static const char *pwm_tin4_p[] = { "pwm-tdiv4", "pwm-tclk" };
static const struct clk_div_table pwm_div_table[5] = {
/* { val, div } */
{ 0, 1 },
{ 1, 2 },
{ 2, 4 },
{ 3, 8 },
{ 4, 16 },
};
/* register exynos_pwm clocks */
void __init exynos_pwm_clk_init(struct device_node *np)
{
static void __iomem *reg_base;
unsigned int reg_tcfg0;
reg_base = of_iomap(np, 0);
if (!reg_base) {
pr_err("%s: failed to map pwm registers\n", __func__);
return;
}
clk_table = kzalloc(sizeof(struct clk *) * exynos_pwm_max_clks,
GFP_KERNEL);
if (!clk_table) {
pr_err("%s: could not allocate clk lookup table\n", __func__);
return;
}
clk_data.clks = clk_table;
clk_data.clk_num = exynos_pwm_max_clks;
of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
reg_tcfg0 = __raw_readl(reg_base + REG_TCFG0);
reg_tcfg0 &= ~(MASK_TCFG0_PRESCALE0 | MASK_TCFG0_PRESCALE1);
__raw_writel(reg_tcfg0, reg_base + REG_TCFG0);
__raw_writel(0, reg_base + REG_TCFG1);
clk_table[pwm_scaler0] = clk_register_divider(NULL, "pwm-scaler0",
"pwm-clock", 0, reg_base + REG_TCFG0, 0, 8,
CLK_DIVIDER_ALLOW_ZERO, &lock);
clk_table[pwm_scaler1] = clk_register_divider(NULL, "pwm-scaler1",
"pwm-clock", 0, reg_base + REG_TCFG0, 8, 8,
CLK_DIVIDER_ALLOW_ZERO, &lock);
clk_table[pwm_tdiv0] = clk_register_divider_table(NULL, "pwm-tdiv0",
"pwm-scaler0", 0, reg_base + REG_TCFG1, 0, 4,
CLK_DIVIDER_ALLOW_ZERO, pwm_div_table, &lock);
clk_table[pwm_tdiv1] = clk_register_divider_table(NULL, "pwm-tdiv1",
"pwm-scaler0", 0, reg_base + REG_TCFG1, 4, 4,
CLK_DIVIDER_ALLOW_ZERO, pwm_div_table, &lock);
clk_table[pwm_tdiv2] = clk_register_divider_table(NULL, "pwm-tdiv2",
"pwm-scaler1", 0, reg_base + REG_TCFG1, 8, 4,
CLK_DIVIDER_ALLOW_ZERO, pwm_div_table, &lock);
clk_table[pwm_tdiv3] = clk_register_divider_table(NULL, "pwm-tdiv3",
"pwm-scaler1", 0, reg_base + REG_TCFG1, 12, 4,
CLK_DIVIDER_ALLOW_ZERO, pwm_div_table, &lock);
clk_table[pwm_tdiv4] = clk_register_divider_table(NULL, "pwm-tdiv4",
"pwm-scaler1", 0, reg_base + REG_TCFG1, 16, 4,
CLK_DIVIDER_ALLOW_ZERO, pwm_div_table, &lock);
clk_table[pwm_tin0] = clk_register_mux(NULL, "pwm-tin0",
pwm_tin0_p, ARRAY_SIZE(pwm_tin0_p), 0,
reg_base + REG_TCFG1, 3, 0, 0, &lock);
clk_table[pwm_tin1] = clk_register_mux(NULL, "pwm-tin1",
pwm_tin1_p, ARRAY_SIZE(pwm_tin1_p), 0,
reg_base + REG_TCFG1, 7, 0, 0, &lock);
clk_table[pwm_tin2] = clk_register_mux(NULL, "pwm-tin2",
pwm_tin2_p, ARRAY_SIZE(pwm_tin2_p), 0,
reg_base + REG_TCFG1, 11, 0, 0, &lock);
clk_table[pwm_tin3] = clk_register_mux(NULL, "pwm-tin3",
pwm_tin3_p, ARRAY_SIZE(pwm_tin3_p), 0,
reg_base + REG_TCFG1, 15, 0, 0, &lock);
clk_table[pwm_tin4] = clk_register_mux(NULL, "pwm-tin4",
pwm_tin4_p, ARRAY_SIZE(pwm_tin4_p), 0,
reg_base + REG_TCFG1, 19, 0, 0, &lock);
pr_info("Exynos: pwm: clock setup completed\n");
}
CLK_OF_DECLARE(exynos_pwm_clk, "samsung,exynos-pwm-clock",
exynos_pwm_clk_init);

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,828 @@
/*
* Copyright (c) 2013 Samsung Electronics Co., Ltd.
* Copyright (c) 2013 Linaro Ltd.
* Author: Thomas Abraham <thomas.ab@samsung.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Common Clock Framework support for Exynos5250 SoC.
*/
#include <dt-bindings/clock/exynos5250.h>
#include <linux/clk.h>
#include <linux/clkdev.h>
#include <linux/clk-provider.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/syscore_ops.h>
#include "clk.h"
#define APLL_LOCK 0x0
#define APLL_CON0 0x100
#define SRC_CPU 0x200
#define DIV_CPU0 0x500
#define PWR_CTRL1 0x1020
#define PWR_CTRL2 0x1024
#define MPLL_LOCK 0x4000
#define MPLL_CON0 0x4100
#define SRC_CORE1 0x4204
#define GATE_IP_ACP 0x8800
#define GATE_IP_ISP0 0xc800
#define GATE_IP_ISP1 0xc804
#define CPLL_LOCK 0x10020
#define EPLL_LOCK 0x10030
#define VPLL_LOCK 0x10040
#define GPLL_LOCK 0x10050
#define CPLL_CON0 0x10120
#define EPLL_CON0 0x10130
#define VPLL_CON0 0x10140
#define GPLL_CON0 0x10150
#define SRC_TOP0 0x10210
#define SRC_TOP1 0x10214
#define SRC_TOP2 0x10218
#define SRC_TOP3 0x1021c
#define SRC_GSCL 0x10220
#define SRC_DISP1_0 0x1022c
#define SRC_MAU 0x10240
#define SRC_FSYS 0x10244
#define SRC_GEN 0x10248
#define SRC_PERIC0 0x10250
#define SRC_PERIC1 0x10254
#define SRC_MASK_GSCL 0x10320
#define SRC_MASK_DISP1_0 0x1032c
#define SRC_MASK_MAU 0x10334
#define SRC_MASK_FSYS 0x10340
#define SRC_MASK_GEN 0x10344
#define SRC_MASK_PERIC0 0x10350
#define SRC_MASK_PERIC1 0x10354
#define DIV_TOP0 0x10510
#define DIV_TOP1 0x10514
#define DIV_GSCL 0x10520
#define DIV_DISP1_0 0x1052c
#define DIV_GEN 0x1053c
#define DIV_MAU 0x10544
#define DIV_FSYS0 0x10548
#define DIV_FSYS1 0x1054c
#define DIV_FSYS2 0x10550
#define DIV_PERIC0 0x10558
#define DIV_PERIC1 0x1055c
#define DIV_PERIC2 0x10560
#define DIV_PERIC3 0x10564
#define DIV_PERIC4 0x10568
#define DIV_PERIC5 0x1056c
#define GATE_IP_GSCL 0x10920
#define GATE_IP_DISP1 0x10928
#define GATE_IP_MFC 0x1092c
#define GATE_IP_G3D 0x10930
#define GATE_IP_GEN 0x10934
#define GATE_IP_FSYS 0x10944
#define GATE_IP_PERIC 0x10950
#define GATE_IP_PERIS 0x10960
#define BPLL_LOCK 0x20010
#define BPLL_CON0 0x20110
#define SRC_CDREX 0x20200
#define PLL_DIV2_SEL 0x20a24
/*Below definitions are used for PWR_CTRL settings*/
#define PWR_CTRL1_CORE2_DOWN_RATIO (7 << 28)
#define PWR_CTRL1_CORE1_DOWN_RATIO (7 << 16)
#define PWR_CTRL1_DIV2_DOWN_EN (1 << 9)
#define PWR_CTRL1_DIV1_DOWN_EN (1 << 8)
#define PWR_CTRL1_USE_CORE1_WFE (1 << 5)
#define PWR_CTRL1_USE_CORE0_WFE (1 << 4)
#define PWR_CTRL1_USE_CORE1_WFI (1 << 1)
#define PWR_CTRL1_USE_CORE0_WFI (1 << 0)
#define PWR_CTRL2_DIV2_UP_EN (1 << 25)
#define PWR_CTRL2_DIV1_UP_EN (1 << 24)
#define PWR_CTRL2_DUR_STANDBY2_VAL (1 << 16)
#define PWR_CTRL2_DUR_STANDBY1_VAL (1 << 8)
#define PWR_CTRL2_CORE2_UP_RATIO (1 << 4)
#define PWR_CTRL2_CORE1_UP_RATIO (1 << 0)
/* list of PLLs to be registered */
enum exynos5250_plls {
apll, mpll, cpll, epll, vpll, gpll, bpll,
nr_plls /* number of PLLs */
};
static void __iomem *reg_base;
#ifdef CONFIG_PM_SLEEP
static struct samsung_clk_reg_dump *exynos5250_save;
/*
* list of controller registers to be saved and restored during a
* suspend/resume cycle.
*/
static unsigned long exynos5250_clk_regs[] __initdata = {
SRC_CPU,
DIV_CPU0,
PWR_CTRL1,
PWR_CTRL2,
SRC_CORE1,
SRC_TOP0,
SRC_TOP1,
SRC_TOP2,
SRC_TOP3,
SRC_GSCL,
SRC_DISP1_0,
SRC_MAU,
SRC_FSYS,
SRC_GEN,
SRC_PERIC0,
SRC_PERIC1,
SRC_MASK_GSCL,
SRC_MASK_DISP1_0,
SRC_MASK_MAU,
SRC_MASK_FSYS,
SRC_MASK_GEN,
SRC_MASK_PERIC0,
SRC_MASK_PERIC1,
DIV_TOP0,
DIV_TOP1,
DIV_GSCL,
DIV_DISP1_0,
DIV_GEN,
DIV_MAU,
DIV_FSYS0,
DIV_FSYS1,
DIV_FSYS2,
DIV_PERIC0,
DIV_PERIC1,
DIV_PERIC2,
DIV_PERIC3,
DIV_PERIC4,
DIV_PERIC5,
GATE_IP_GSCL,
GATE_IP_MFC,
GATE_IP_G3D,
GATE_IP_GEN,
GATE_IP_FSYS,
GATE_IP_PERIC,
GATE_IP_PERIS,
SRC_CDREX,
PLL_DIV2_SEL,
GATE_IP_DISP1,
GATE_IP_ACP,
GATE_IP_ISP0,
GATE_IP_ISP1,
};
static int exynos5250_clk_suspend(void)
{
samsung_clk_save(reg_base, exynos5250_save,
ARRAY_SIZE(exynos5250_clk_regs));
return 0;
}
static void exynos5250_clk_resume(void)
{
samsung_clk_restore(reg_base, exynos5250_save,
ARRAY_SIZE(exynos5250_clk_regs));
}
static struct syscore_ops exynos5250_clk_syscore_ops = {
.suspend = exynos5250_clk_suspend,
.resume = exynos5250_clk_resume,
};
static void exynos5250_clk_sleep_init(void)
{
exynos5250_save = samsung_clk_alloc_reg_dump(exynos5250_clk_regs,
ARRAY_SIZE(exynos5250_clk_regs));
if (!exynos5250_save) {
pr_warn("%s: failed to allocate sleep save data, no sleep support!\n",
__func__);
return;
}
register_syscore_ops(&exynos5250_clk_syscore_ops);
}
#else
static void exynos5250_clk_sleep_init(void) {}
#endif
/* list of all parent clock list */
PNAME(mout_apll_p) = { "fin_pll", "fout_apll", };
PNAME(mout_cpu_p) = { "mout_apll", "mout_mpll", };
PNAME(mout_mpll_fout_p) = { "fout_mplldiv2", "fout_mpll" };
PNAME(mout_mpll_p) = { "fin_pll", "mout_mpll_fout" };
PNAME(mout_bpll_fout_p) = { "fout_bplldiv2", "fout_bpll" };
PNAME(mout_bpll_p) = { "fin_pll", "mout_bpll_fout" };
PNAME(mout_vpllsrc_p) = { "fin_pll", "sclk_hdmi27m" };
PNAME(mout_vpll_p) = { "mout_vpllsrc", "fout_vpll" };
PNAME(mout_cpll_p) = { "fin_pll", "fout_cpll" };
PNAME(mout_epll_p) = { "fin_pll", "fout_epll" };
PNAME(mout_gpll_p) = { "fin_pll", "fout_gpll" };
PNAME(mout_mpll_user_p) = { "fin_pll", "mout_mpll" };
PNAME(mout_bpll_user_p) = { "fin_pll", "mout_bpll" };
PNAME(mout_aclk166_p) = { "mout_cpll", "mout_mpll_user" };
PNAME(mout_aclk200_p) = { "mout_mpll_user", "mout_bpll_user" };
PNAME(mout_aclk400_p) = { "mout_aclk400_g3d_mid", "mout_gpll" };
PNAME(mout_aclk200_sub_p) = { "fin_pll", "div_aclk200" };
PNAME(mout_aclk266_sub_p) = { "fin_pll", "div_aclk266" };
PNAME(mout_aclk333_sub_p) = { "fin_pll", "div_aclk333" };
PNAME(mout_aclk400_isp_sub_p) = { "fin_pll", "div_aclk400_isp" };
PNAME(mout_hdmi_p) = { "div_hdmi_pixel", "sclk_hdmiphy" };
PNAME(mout_usb3_p) = { "mout_mpll_user", "mout_cpll" };
PNAME(mout_group1_p) = { "fin_pll", "fin_pll", "sclk_hdmi27m",
"sclk_dptxphy", "sclk_uhostphy", "sclk_hdmiphy",
"mout_mpll_user", "mout_epll", "mout_vpll",
"mout_cpll", "none", "none",
"none", "none", "none",
"none" };
PNAME(mout_audio0_p) = { "cdclk0", "fin_pll", "sclk_hdmi27m", "sclk_dptxphy",
"sclk_uhostphy", "fin_pll",
"mout_mpll_user", "mout_epll", "mout_vpll",
"mout_cpll", "none", "none",
"none", "none", "none",
"none" };
PNAME(mout_audio1_p) = { "cdclk1", "fin_pll", "sclk_hdmi27m", "sclk_dptxphy",
"sclk_uhostphy", "fin_pll",
"mout_mpll_user", "mout_epll", "mout_vpll",
"mout_cpll", "none", "none",
"none", "none", "none",
"none" };
PNAME(mout_audio2_p) = { "cdclk2", "fin_pll", "sclk_hdmi27m", "sclk_dptxphy",
"sclk_uhostphy", "fin_pll",
"mout_mpll_user", "mout_epll", "mout_vpll",
"mout_cpll", "none", "none",
"none", "none", "none",
"none" };
PNAME(mout_spdif_p) = { "sclk_audio0", "sclk_audio1", "sclk_audio2",
"spdif_extclk" };
/* fixed rate clocks generated outside the soc */
static struct samsung_fixed_rate_clock exynos5250_fixed_rate_ext_clks[] __initdata = {
FRATE(CLK_FIN_PLL, "fin_pll", NULL, CLK_IS_ROOT, 0),
};
/* fixed rate clocks generated inside the soc */
static struct samsung_fixed_rate_clock exynos5250_fixed_rate_clks[] __initdata = {
FRATE(CLK_SCLK_HDMIPHY, "sclk_hdmiphy", NULL, CLK_IS_ROOT, 24000000),
FRATE(0, "sclk_hdmi27m", NULL, CLK_IS_ROOT, 27000000),
FRATE(0, "sclk_dptxphy", NULL, CLK_IS_ROOT, 24000000),
FRATE(0, "sclk_uhostphy", NULL, CLK_IS_ROOT, 48000000),
};
static struct samsung_fixed_factor_clock exynos5250_fixed_factor_clks[] __initdata = {
FFACTOR(0, "fout_mplldiv2", "fout_mpll", 1, 2, 0),
FFACTOR(0, "fout_bplldiv2", "fout_bpll", 1, 2, 0),
};
static struct samsung_mux_clock exynos5250_pll_pmux_clks[] __initdata = {
MUX(0, "mout_vpllsrc", mout_vpllsrc_p, SRC_TOP2, 0, 1),
};
static struct samsung_mux_clock exynos5250_mux_clks[] __initdata = {
/*
* NOTE: Following table is sorted by (clock domain, register address,
* bitfield shift) triplet in ascending order. When adding new entries,
* please make sure that the order is kept, to avoid merge conflicts
* and make further work with defined data easier.
*/
/*
* CMU_CPU
*/
MUX_FA(0, "mout_apll", mout_apll_p, SRC_CPU, 0, 1,
CLK_SET_RATE_PARENT, 0, "mout_apll"),
MUX_A(0, "mout_cpu", mout_cpu_p, SRC_CPU, 16, 1, "mout_cpu"),
/*
* CMU_CORE
*/
MUX_A(0, "mout_mpll", mout_mpll_p, SRC_CORE1, 8, 1, "mout_mpll"),
/*
* CMU_TOP
*/
MUX(0, "mout_aclk166", mout_aclk166_p, SRC_TOP0, 8, 1),
MUX(0, "mout_aclk200", mout_aclk200_p, SRC_TOP0, 12, 1),
MUX(0, "mout_aclk333", mout_aclk166_p, SRC_TOP0, 16, 1),
MUX(0, "mout_aclk400_g3d_mid", mout_aclk200_p, SRC_TOP0, 20, 1),
MUX(0, "mout_aclk400_isp", mout_aclk200_p, SRC_TOP1, 24, 1),
MUX(0, "mout_aclk400_g3d", mout_aclk400_p, SRC_TOP1, 28, 1),
MUX(0, "mout_cpll", mout_cpll_p, SRC_TOP2, 8, 1),
MUX(0, "mout_epll", mout_epll_p, SRC_TOP2, 12, 1),
MUX(0, "mout_vpll", mout_vpll_p, SRC_TOP2, 16, 1),
MUX(0, "mout_mpll_user", mout_mpll_user_p, SRC_TOP2, 20, 1),
MUX(0, "mout_bpll_user", mout_bpll_user_p, SRC_TOP2, 24, 1),
MUX(CLK_MOUT_GPLL, "mout_gpll", mout_gpll_p, SRC_TOP2, 28, 1),
MUX(0, "mout_aclk200_disp1_sub", mout_aclk200_sub_p, SRC_TOP3, 4, 1),
MUX(0, "mout_aclk266_gscl_sub", mout_aclk266_sub_p, SRC_TOP3, 8, 1),
MUX(0, "mout_aclk_266_isp_sub", mout_aclk266_sub_p, SRC_TOP3, 16, 1),
MUX(0, "mout_aclk_400_isp_sub", mout_aclk400_isp_sub_p,
SRC_TOP3, 20, 1),
MUX(0, "mout_aclk333_sub", mout_aclk333_sub_p, SRC_TOP3, 24, 1),
MUX(0, "mout_cam_bayer", mout_group1_p, SRC_GSCL, 12, 4),
MUX(0, "mout_cam0", mout_group1_p, SRC_GSCL, 16, 4),
MUX(0, "mout_cam1", mout_group1_p, SRC_GSCL, 20, 4),
MUX(0, "mout_gscl_wa", mout_group1_p, SRC_GSCL, 24, 4),
MUX(0, "mout_gscl_wb", mout_group1_p, SRC_GSCL, 28, 4),
MUX(0, "mout_fimd1", mout_group1_p, SRC_DISP1_0, 0, 4),
MUX(0, "mout_mipi1", mout_group1_p, SRC_DISP1_0, 12, 4),
MUX(0, "mout_dp", mout_group1_p, SRC_DISP1_0, 16, 4),
MUX(CLK_MOUT_HDMI, "mout_hdmi", mout_hdmi_p, SRC_DISP1_0, 20, 1),
MUX(0, "mout_audio0", mout_audio0_p, SRC_MAU, 0, 4),
MUX(0, "mout_mmc0", mout_group1_p, SRC_FSYS, 0, 4),
MUX(0, "mout_mmc1", mout_group1_p, SRC_FSYS, 4, 4),
MUX(0, "mout_mmc2", mout_group1_p, SRC_FSYS, 8, 4),
MUX(0, "mout_mmc3", mout_group1_p, SRC_FSYS, 12, 4),
MUX(0, "mout_sata", mout_aclk200_p, SRC_FSYS, 24, 1),
MUX(0, "mout_usb3", mout_usb3_p, SRC_FSYS, 28, 1),
MUX(0, "mout_jpeg", mout_group1_p, SRC_GEN, 0, 4),
MUX(0, "mout_uart0", mout_group1_p, SRC_PERIC0, 0, 4),
MUX(0, "mout_uart1", mout_group1_p, SRC_PERIC0, 4, 4),
MUX(0, "mout_uart2", mout_group1_p, SRC_PERIC0, 8, 4),
MUX(0, "mout_uart3", mout_group1_p, SRC_PERIC0, 12, 4),
MUX(0, "mout_pwm", mout_group1_p, SRC_PERIC0, 24, 4),
MUX(0, "mout_audio1", mout_audio1_p, SRC_PERIC1, 0, 4),
MUX(0, "mout_audio2", mout_audio2_p, SRC_PERIC1, 4, 4),
MUX(0, "mout_spdif", mout_spdif_p, SRC_PERIC1, 8, 2),
MUX(0, "mout_spi0", mout_group1_p, SRC_PERIC1, 16, 4),
MUX(0, "mout_spi1", mout_group1_p, SRC_PERIC1, 20, 4),
MUX(0, "mout_spi2", mout_group1_p, SRC_PERIC1, 24, 4),
/*
* CMU_CDREX
*/
MUX(0, "mout_bpll", mout_bpll_p, SRC_CDREX, 0, 1),
MUX(0, "mout_mpll_fout", mout_mpll_fout_p, PLL_DIV2_SEL, 4, 1),
MUX(0, "mout_bpll_fout", mout_bpll_fout_p, PLL_DIV2_SEL, 0, 1),
};
static struct samsung_div_clock exynos5250_div_clks[] __initdata = {
/*
* NOTE: Following table is sorted by (clock domain, register address,
* bitfield shift) triplet in ascending order. When adding new entries,
* please make sure that the order is kept, to avoid merge conflicts
* and make further work with defined data easier.
*/
/*
* CMU_CPU
*/
DIV(0, "div_arm", "mout_cpu", DIV_CPU0, 0, 3),
DIV(0, "div_apll", "mout_apll", DIV_CPU0, 24, 3),
DIV_A(0, "div_arm2", "div_arm", DIV_CPU0, 28, 3, "armclk"),
/*
* CMU_TOP
*/
DIV(0, "div_aclk66", "div_aclk66_pre", DIV_TOP0, 0, 3),
DIV(0, "div_aclk166", "mout_aclk166", DIV_TOP0, 8, 3),
DIV(0, "div_aclk200", "mout_aclk200", DIV_TOP0, 12, 3),
DIV(0, "div_aclk266", "mout_mpll_user", DIV_TOP0, 16, 3),
DIV(0, "div_aclk333", "mout_aclk333", DIV_TOP0, 20, 3),
DIV(0, "div_aclk400_g3d", "mout_aclk400_g3d", DIV_TOP0,
24, 3),
DIV(0, "div_aclk400_isp", "mout_aclk400_isp", DIV_TOP1, 20, 3),
DIV(0, "div_aclk66_pre", "mout_mpll_user", DIV_TOP1, 24, 3),
DIV(0, "div_cam_bayer", "mout_cam_bayer", DIV_GSCL, 12, 4),
DIV(0, "div_cam0", "mout_cam0", DIV_GSCL, 16, 4),
DIV(0, "div_cam1", "mout_cam1", DIV_GSCL, 20, 4),
DIV(0, "div_gscl_wa", "mout_gscl_wa", DIV_GSCL, 24, 4),
DIV(0, "div_gscl_wb", "mout_gscl_wb", DIV_GSCL, 28, 4),
DIV(0, "div_fimd1", "mout_fimd1", DIV_DISP1_0, 0, 4),
DIV(0, "div_mipi1", "mout_mipi1", DIV_DISP1_0, 16, 4),
DIV_F(0, "div_mipi1_pre", "div_mipi1",
DIV_DISP1_0, 20, 4, CLK_SET_RATE_PARENT, 0),
DIV(0, "div_dp", "mout_dp", DIV_DISP1_0, 24, 4),
DIV(CLK_SCLK_PIXEL, "div_hdmi_pixel", "mout_vpll", DIV_DISP1_0, 28, 4),
DIV(0, "div_jpeg", "mout_jpeg", DIV_GEN, 4, 4),
DIV(0, "div_audio0", "mout_audio0", DIV_MAU, 0, 4),
DIV(CLK_DIV_PCM0, "div_pcm0", "sclk_audio0", DIV_MAU, 4, 8),
DIV(0, "div_sata", "mout_sata", DIV_FSYS0, 20, 4),
DIV(0, "div_usb3", "mout_usb3", DIV_FSYS0, 24, 4),
DIV(0, "div_mmc0", "mout_mmc0", DIV_FSYS1, 0, 4),
DIV_F(0, "div_mmc_pre0", "div_mmc0",
DIV_FSYS1, 8, 8, CLK_SET_RATE_PARENT, 0),
DIV(0, "div_mmc1", "mout_mmc1", DIV_FSYS1, 16, 4),
DIV_F(0, "div_mmc_pre1", "div_mmc1",
DIV_FSYS1, 24, 8, CLK_SET_RATE_PARENT, 0),
DIV(0, "div_mmc2", "mout_mmc2", DIV_FSYS2, 0, 4),
DIV_F(0, "div_mmc_pre2", "div_mmc2",
DIV_FSYS2, 8, 8, CLK_SET_RATE_PARENT, 0),
DIV(0, "div_mmc3", "mout_mmc3", DIV_FSYS2, 16, 4),
DIV_F(0, "div_mmc_pre3", "div_mmc3",
DIV_FSYS2, 24, 8, CLK_SET_RATE_PARENT, 0),
DIV(0, "div_uart0", "mout_uart0", DIV_PERIC0, 0, 4),
DIV(0, "div_uart1", "mout_uart1", DIV_PERIC0, 4, 4),
DIV(0, "div_uart2", "mout_uart2", DIV_PERIC0, 8, 4),
DIV(0, "div_uart3", "mout_uart3", DIV_PERIC0, 12, 4),
DIV(0, "div_spi0", "mout_spi0", DIV_PERIC1, 0, 4),
DIV_F(0, "div_spi_pre0", "div_spi0",
DIV_PERIC1, 8, 8, CLK_SET_RATE_PARENT, 0),
DIV(0, "div_spi1", "mout_spi1", DIV_PERIC1, 16, 4),
DIV_F(0, "div_spi_pre1", "div_spi1",
DIV_PERIC1, 24, 8, CLK_SET_RATE_PARENT, 0),
DIV(0, "div_spi2", "mout_spi2", DIV_PERIC2, 0, 4),
DIV_F(0, "div_spi_pre2", "div_spi2",
DIV_PERIC2, 8, 8, CLK_SET_RATE_PARENT, 0),
DIV(0, "div_pwm", "mout_pwm", DIV_PERIC3, 0, 4),
DIV(0, "div_audio1", "mout_audio1", DIV_PERIC4, 0, 4),
DIV(0, "div_pcm1", "sclk_audio1", DIV_PERIC4, 4, 8),
DIV(0, "div_audio2", "mout_audio2", DIV_PERIC4, 16, 4),
DIV(0, "div_pcm2", "sclk_audio2", DIV_PERIC4, 20, 8),
DIV(CLK_DIV_I2S1, "div_i2s1", "sclk_audio1", DIV_PERIC5, 0, 6),
DIV(CLK_DIV_I2S2, "div_i2s2", "sclk_audio2", DIV_PERIC5, 8, 6),
};
static struct samsung_gate_clock exynos5250_gate_clks[] __initdata = {
/*
* NOTE: Following table is sorted by (clock domain, register address,
* bitfield shift) triplet in ascending order. When adding new entries,
* please make sure that the order is kept, to avoid merge conflicts
* and make further work with defined data easier.
*/
/*
* CMU_ACP
*/
GATE(CLK_MDMA0, "mdma0", "div_aclk266", GATE_IP_ACP, 1, 0, 0),
GATE(CLK_SSS, "sss", "div_aclk266", GATE_IP_ACP, 2, 0, 0),
GATE(CLK_G2D, "g2d", "div_aclk200", GATE_IP_ACP, 3, 0, 0),
GATE(CLK_SMMU_MDMA0, "smmu_mdma0", "div_aclk266", GATE_IP_ACP, 5, 0, 0),
/*
* CMU_TOP
*/
GATE(CLK_SCLK_CAM_BAYER, "sclk_cam_bayer", "div_cam_bayer",
SRC_MASK_GSCL, 12, CLK_SET_RATE_PARENT, 0),
GATE(CLK_SCLK_CAM0, "sclk_cam0", "div_cam0",
SRC_MASK_GSCL, 16, CLK_SET_RATE_PARENT, 0),
GATE(CLK_SCLK_CAM1, "sclk_cam1", "div_cam1",
SRC_MASK_GSCL, 20, CLK_SET_RATE_PARENT, 0),
GATE(CLK_SCLK_GSCL_WA, "sclk_gscl_wa", "div_gscl_wa",
SRC_MASK_GSCL, 24, CLK_SET_RATE_PARENT, 0),
GATE(CLK_SCLK_GSCL_WB, "sclk_gscl_wb", "div_gscl_wb",
SRC_MASK_GSCL, 28, CLK_SET_RATE_PARENT, 0),
GATE(CLK_SCLK_FIMD1, "sclk_fimd1", "div_fimd1",
SRC_MASK_DISP1_0, 0, CLK_SET_RATE_PARENT, 0),
GATE(CLK_SCLK_MIPI1, "sclk_mipi1", "div_mipi1",
SRC_MASK_DISP1_0, 12, CLK_SET_RATE_PARENT, 0),
GATE(CLK_SCLK_DP, "sclk_dp", "div_dp",
SRC_MASK_DISP1_0, 16, CLK_SET_RATE_PARENT, 0),
GATE(CLK_SCLK_HDMI, "sclk_hdmi", "mout_hdmi",
SRC_MASK_DISP1_0, 20, 0, 0),
GATE(CLK_SCLK_AUDIO0, "sclk_audio0", "div_audio0",
SRC_MASK_MAU, 0, CLK_SET_RATE_PARENT, 0),
GATE(CLK_SCLK_MMC0, "sclk_mmc0", "div_mmc_pre0",
SRC_MASK_FSYS, 0, CLK_SET_RATE_PARENT, 0),
GATE(CLK_SCLK_MMC1, "sclk_mmc1", "div_mmc_pre1",
SRC_MASK_FSYS, 4, CLK_SET_RATE_PARENT, 0),
GATE(CLK_SCLK_MMC2, "sclk_mmc2", "div_mmc_pre2",
SRC_MASK_FSYS, 8, CLK_SET_RATE_PARENT, 0),
GATE(CLK_SCLK_MMC3, "sclk_mmc3", "div_mmc_pre3",
SRC_MASK_FSYS, 12, CLK_SET_RATE_PARENT, 0),
GATE(CLK_SCLK_SATA, "sclk_sata", "div_sata",
SRC_MASK_FSYS, 24, CLK_SET_RATE_PARENT, 0),
GATE(CLK_SCLK_USB3, "sclk_usb3", "div_usb3",
SRC_MASK_FSYS, 28, CLK_SET_RATE_PARENT, 0),
GATE(CLK_SCLK_JPEG, "sclk_jpeg", "div_jpeg",
SRC_MASK_GEN, 0, CLK_SET_RATE_PARENT, 0),
GATE(CLK_SCLK_UART0, "sclk_uart0", "div_uart0",
SRC_MASK_PERIC0, 0, CLK_SET_RATE_PARENT, 0),
GATE(CLK_SCLK_UART1, "sclk_uart1", "div_uart1",
SRC_MASK_PERIC0, 4, CLK_SET_RATE_PARENT, 0),
GATE(CLK_SCLK_UART2, "sclk_uart2", "div_uart2",
SRC_MASK_PERIC0, 8, CLK_SET_RATE_PARENT, 0),
GATE(CLK_SCLK_UART3, "sclk_uart3", "div_uart3",
SRC_MASK_PERIC0, 12, CLK_SET_RATE_PARENT, 0),
GATE(CLK_SCLK_PWM, "sclk_pwm", "div_pwm",
SRC_MASK_PERIC0, 24, CLK_SET_RATE_PARENT, 0),
GATE(CLK_SCLK_AUDIO1, "sclk_audio1", "div_audio1",
SRC_MASK_PERIC1, 0, CLK_SET_RATE_PARENT, 0),
GATE(CLK_SCLK_AUDIO2, "sclk_audio2", "div_audio2",
SRC_MASK_PERIC1, 4, CLK_SET_RATE_PARENT, 0),
GATE(CLK_SCLK_SPDIF, "sclk_spdif", "mout_spdif",
SRC_MASK_PERIC1, 4, 0, 0),
GATE(CLK_SCLK_SPI0, "sclk_spi0", "div_spi_pre0",
SRC_MASK_PERIC1, 16, CLK_SET_RATE_PARENT, 0),
GATE(CLK_SCLK_SPI1, "sclk_spi1", "div_spi_pre1",
SRC_MASK_PERIC1, 20, CLK_SET_RATE_PARENT, 0),
GATE(CLK_SCLK_SPI2, "sclk_spi2", "div_spi_pre2",
SRC_MASK_PERIC1, 24, CLK_SET_RATE_PARENT, 0),
GATE(CLK_GSCL0, "gscl0", "mout_aclk266_gscl_sub", GATE_IP_GSCL, 0, 0,
0),
GATE(CLK_GSCL1, "gscl1", "mout_aclk266_gscl_sub", GATE_IP_GSCL, 1, 0,
0),
GATE(CLK_GSCL2, "gscl2", "mout_aclk266_gscl_sub", GATE_IP_GSCL, 2, 0,
0),
GATE(CLK_GSCL3, "gscl3", "mout_aclk266_gscl_sub", GATE_IP_GSCL, 3, 0,
0),
GATE(CLK_GSCL_WA, "gscl_wa", "div_gscl_wa", GATE_IP_GSCL, 5, 0, 0),
GATE(CLK_GSCL_WB, "gscl_wb", "div_gscl_wb", GATE_IP_GSCL, 6, 0, 0),
GATE(CLK_SMMU_GSCL0, "smmu_gscl0", "mout_aclk266_gscl_sub",
GATE_IP_GSCL, 7, 0, 0),
GATE(CLK_SMMU_GSCL1, "smmu_gscl1", "mout_aclk266_gscl_sub",
GATE_IP_GSCL, 8, 0, 0),
GATE(CLK_SMMU_GSCL2, "smmu_gscl2", "mout_aclk266_gscl_sub",
GATE_IP_GSCL, 9, 0, 0),
GATE(CLK_SMMU_GSCL3, "smmu_gscl3", "mout_aclk266_gscl_sub",
GATE_IP_GSCL, 10, 0, 0),
GATE(CLK_FIMD1, "fimd1", "mout_aclk200_disp1_sub", GATE_IP_DISP1, 0, 0,
0),
GATE(CLK_MIE1, "mie1", "mout_aclk200_disp1_sub", GATE_IP_DISP1, 1, 0,
0),
GATE(CLK_DSIM0, "dsim0", "mout_aclk200_disp1_sub", GATE_IP_DISP1, 3, 0,
0),
GATE(CLK_DP, "dp", "mout_aclk200_disp1_sub", GATE_IP_DISP1, 4, 0, 0),
GATE(CLK_MIXER, "mixer", "mout_aclk200_disp1_sub", GATE_IP_DISP1, 5, 0,
0),
GATE(CLK_HDMI, "hdmi", "mout_aclk200_disp1_sub", GATE_IP_DISP1, 6, 0,
0),
GATE(CLK_MFC, "mfc", "mout_aclk333_sub", GATE_IP_MFC, 0, 0, 0),
GATE(CLK_SMMU_MFCR, "smmu_mfcr", "mout_aclk333_sub", GATE_IP_MFC, 1, 0,
0),
GATE(CLK_SMMU_MFCL, "smmu_mfcl", "mout_aclk333_sub", GATE_IP_MFC, 2, 0,
0),
GATE(CLK_G3D, "g3d", "div_aclk400_g3d", GATE_IP_G3D, 0,
CLK_SET_RATE_PARENT, 0),
GATE(CLK_ROTATOR, "rotator", "div_aclk266", GATE_IP_GEN, 1, 0, 0),
GATE(CLK_JPEG, "jpeg", "div_aclk166", GATE_IP_GEN, 2, 0, 0),
GATE(CLK_MDMA1, "mdma1", "div_aclk266", GATE_IP_GEN, 4, 0, 0),
GATE(CLK_SMMU_ROTATOR, "smmu_rotator", "div_aclk266", GATE_IP_GEN, 6, 0,
0),
GATE(CLK_SMMU_JPEG, "smmu_jpeg", "div_aclk166", GATE_IP_GEN, 7, 0, 0),
GATE(CLK_SMMU_MDMA1, "smmu_mdma1", "div_aclk266", GATE_IP_GEN, 9, 0, 0),
GATE(CLK_PDMA0, "pdma0", "div_aclk200", GATE_IP_FSYS, 1, 0, 0),
GATE(CLK_PDMA1, "pdma1", "div_aclk200", GATE_IP_FSYS, 2, 0, 0),
GATE(CLK_SATA, "sata", "div_aclk200", GATE_IP_FSYS, 6, 0, 0),
GATE(CLK_USBOTG, "usbotg", "div_aclk200", GATE_IP_FSYS, 7, 0, 0),
GATE(CLK_MIPI_HSI, "mipi_hsi", "div_aclk200", GATE_IP_FSYS, 8, 0, 0),
GATE(CLK_SDMMC0, "sdmmc0", "div_aclk200", GATE_IP_FSYS, 12, 0, 0),
GATE(CLK_SDMMC1, "sdmmc1", "div_aclk200", GATE_IP_FSYS, 13, 0, 0),
GATE(CLK_SDMMC2, "sdmmc2", "div_aclk200", GATE_IP_FSYS, 14, 0, 0),
GATE(CLK_SDMMC3, "sdmmc3", "div_aclk200", GATE_IP_FSYS, 15, 0, 0),
GATE(CLK_SROMC, "sromc", "div_aclk200", GATE_IP_FSYS, 17, 0, 0),
GATE(CLK_USB2, "usb2", "div_aclk200", GATE_IP_FSYS, 18, 0, 0),
GATE(CLK_USB3, "usb3", "div_aclk200", GATE_IP_FSYS, 19, 0, 0),
GATE(CLK_SATA_PHYCTRL, "sata_phyctrl", "div_aclk200",
GATE_IP_FSYS, 24, 0, 0),
GATE(CLK_SATA_PHYI2C, "sata_phyi2c", "div_aclk200", GATE_IP_FSYS, 25, 0,
0),
GATE(CLK_UART0, "uart0", "div_aclk66", GATE_IP_PERIC, 0, 0, 0),
GATE(CLK_UART1, "uart1", "div_aclk66", GATE_IP_PERIC, 1, 0, 0),
GATE(CLK_UART2, "uart2", "div_aclk66", GATE_IP_PERIC, 2, 0, 0),
GATE(CLK_UART3, "uart3", "div_aclk66", GATE_IP_PERIC, 3, 0, 0),
GATE(CLK_UART4, "uart4", "div_aclk66", GATE_IP_PERIC, 4, 0, 0),
GATE(CLK_I2C0, "i2c0", "div_aclk66", GATE_IP_PERIC, 6, 0, 0),
GATE(CLK_I2C1, "i2c1", "div_aclk66", GATE_IP_PERIC, 7, 0, 0),
GATE(CLK_I2C2, "i2c2", "div_aclk66", GATE_IP_PERIC, 8, 0, 0),
GATE(CLK_I2C3, "i2c3", "div_aclk66", GATE_IP_PERIC, 9, 0, 0),
GATE(CLK_I2C4, "i2c4", "div_aclk66", GATE_IP_PERIC, 10, 0, 0),
GATE(CLK_I2C5, "i2c5", "div_aclk66", GATE_IP_PERIC, 11, 0, 0),
GATE(CLK_I2C6, "i2c6", "div_aclk66", GATE_IP_PERIC, 12, 0, 0),
GATE(CLK_I2C7, "i2c7", "div_aclk66", GATE_IP_PERIC, 13, 0, 0),
GATE(CLK_I2C_HDMI, "i2c_hdmi", "div_aclk66", GATE_IP_PERIC, 14, 0, 0),
GATE(CLK_ADC, "adc", "div_aclk66", GATE_IP_PERIC, 15, 0, 0),
GATE(CLK_SPI0, "spi0", "div_aclk66", GATE_IP_PERIC, 16, 0, 0),
GATE(CLK_SPI1, "spi1", "div_aclk66", GATE_IP_PERIC, 17, 0, 0),
GATE(CLK_SPI2, "spi2", "div_aclk66", GATE_IP_PERIC, 18, 0, 0),
GATE(CLK_I2S1, "i2s1", "div_aclk66", GATE_IP_PERIC, 20, 0, 0),
GATE(CLK_I2S2, "i2s2", "div_aclk66", GATE_IP_PERIC, 21, 0, 0),
GATE(CLK_PCM1, "pcm1", "div_aclk66", GATE_IP_PERIC, 22, 0, 0),
GATE(CLK_PCM2, "pcm2", "div_aclk66", GATE_IP_PERIC, 23, 0, 0),
GATE(CLK_PWM, "pwm", "div_aclk66", GATE_IP_PERIC, 24, 0, 0),
GATE(CLK_SPDIF, "spdif", "div_aclk66", GATE_IP_PERIC, 26, 0, 0),
GATE(CLK_AC97, "ac97", "div_aclk66", GATE_IP_PERIC, 27, 0, 0),
GATE(CLK_HSI2C0, "hsi2c0", "div_aclk66", GATE_IP_PERIC, 28, 0, 0),
GATE(CLK_HSI2C1, "hsi2c1", "div_aclk66", GATE_IP_PERIC, 29, 0, 0),
GATE(CLK_HSI2C2, "hsi2c2", "div_aclk66", GATE_IP_PERIC, 30, 0, 0),
GATE(CLK_HSI2C3, "hsi2c3", "div_aclk66", GATE_IP_PERIC, 31, 0, 0),
GATE(CLK_CHIPID, "chipid", "div_aclk66", GATE_IP_PERIS, 0, 0, 0),
GATE(CLK_SYSREG, "sysreg", "div_aclk66",
GATE_IP_PERIS, 1, CLK_IGNORE_UNUSED, 0),
GATE(CLK_PMU, "pmu", "div_aclk66", GATE_IP_PERIS, 2, CLK_IGNORE_UNUSED,
0),
GATE(CLK_CMU_TOP, "cmu_top", "div_aclk66",
GATE_IP_PERIS, 3, CLK_IGNORE_UNUSED, 0),
GATE(CLK_CMU_CORE, "cmu_core", "div_aclk66",
GATE_IP_PERIS, 4, CLK_IGNORE_UNUSED, 0),
GATE(CLK_CMU_MEM, "cmu_mem", "div_aclk66",
GATE_IP_PERIS, 5, CLK_IGNORE_UNUSED, 0),
GATE(CLK_TZPC0, "tzpc0", "div_aclk66", GATE_IP_PERIS, 6, 0, 0),
GATE(CLK_TZPC1, "tzpc1", "div_aclk66", GATE_IP_PERIS, 7, 0, 0),
GATE(CLK_TZPC2, "tzpc2", "div_aclk66", GATE_IP_PERIS, 8, 0, 0),
GATE(CLK_TZPC3, "tzpc3", "div_aclk66", GATE_IP_PERIS, 9, 0, 0),
GATE(CLK_TZPC4, "tzpc4", "div_aclk66", GATE_IP_PERIS, 10, 0, 0),
GATE(CLK_TZPC5, "tzpc5", "div_aclk66", GATE_IP_PERIS, 11, 0, 0),
GATE(CLK_TZPC6, "tzpc6", "div_aclk66", GATE_IP_PERIS, 12, 0, 0),
GATE(CLK_TZPC7, "tzpc7", "div_aclk66", GATE_IP_PERIS, 13, 0, 0),
GATE(CLK_TZPC8, "tzpc8", "div_aclk66", GATE_IP_PERIS, 14, 0, 0),
GATE(CLK_TZPC9, "tzpc9", "div_aclk66", GATE_IP_PERIS, 15, 0, 0),
GATE(CLK_HDMI_CEC, "hdmi_cec", "div_aclk66", GATE_IP_PERIS, 16, 0, 0),
GATE(CLK_MCT, "mct", "div_aclk66", GATE_IP_PERIS, 18, 0, 0),
GATE(CLK_WDT, "wdt", "div_aclk66", GATE_IP_PERIS, 19, 0, 0),
GATE(CLK_RTC, "rtc", "div_aclk66", GATE_IP_PERIS, 20, 0, 0),
GATE(CLK_TMU, "tmu", "div_aclk66", GATE_IP_PERIS, 21, 0, 0),
GATE(CLK_SMMU_TV, "smmu_tv", "mout_aclk200_disp1_sub",
GATE_IP_DISP1, 9, 0, 0),
GATE(CLK_SMMU_FIMD1, "smmu_fimd1", "mout_aclk200_disp1_sub",
GATE_IP_DISP1, 8, 0, 0),
GATE(CLK_SMMU_2D, "smmu_2d", "div_aclk200", GATE_IP_ACP, 7, 0, 0),
GATE(CLK_SMMU_FIMC_ISP, "smmu_fimc_isp", "mout_aclk_266_isp_sub",
GATE_IP_ISP0, 8, 0, 0),
GATE(CLK_SMMU_FIMC_DRC, "smmu_fimc_drc", "mout_aclk_266_isp_sub",
GATE_IP_ISP0, 9, 0, 0),
GATE(CLK_SMMU_FIMC_FD, "smmu_fimc_fd", "mout_aclk_266_isp_sub",
GATE_IP_ISP0, 10, 0, 0),
GATE(CLK_SMMU_FIMC_SCC, "smmu_fimc_scc", "mout_aclk_266_isp_sub",
GATE_IP_ISP0, 11, 0, 0),
GATE(CLK_SMMU_FIMC_SCP, "smmu_fimc_scp", "mout_aclk_266_isp_sub",
GATE_IP_ISP0, 12, 0, 0),
GATE(CLK_SMMU_FIMC_MCU, "smmu_fimc_mcu", "mout_aclk_400_isp_sub",
GATE_IP_ISP0, 13, 0, 0),
GATE(CLK_SMMU_FIMC_ODC, "smmu_fimc_odc", "mout_aclk_266_isp_sub",
GATE_IP_ISP1, 4, 0, 0),
GATE(CLK_SMMU_FIMC_DIS0, "smmu_fimc_dis0", "mout_aclk_266_isp_sub",
GATE_IP_ISP1, 5, 0, 0),
GATE(CLK_SMMU_FIMC_DIS1, "smmu_fimc_dis1", "mout_aclk_266_isp_sub",
GATE_IP_ISP1, 6, 0, 0),
GATE(CLK_SMMU_FIMC_3DNR, "smmu_fimc_3dnr", "mout_aclk_266_isp_sub",
GATE_IP_ISP1, 7, 0, 0),
};
static struct samsung_pll_rate_table vpll_24mhz_tbl[] __initdata = {
/* sorted in descending order */
/* PLL_36XX_RATE(rate, m, p, s, k) */
PLL_36XX_RATE(266000000, 266, 3, 3, 0),
/* Not in UM, but need for eDP on snow */
PLL_36XX_RATE(70500000, 94, 2, 4, 0),
{ },
};
static struct samsung_pll_rate_table epll_24mhz_tbl[] __initdata = {
/* sorted in descending order */
/* PLL_36XX_RATE(rate, m, p, s, k) */
PLL_36XX_RATE(192000000, 64, 2, 2, 0),
PLL_36XX_RATE(180633600, 90, 3, 2, 20762),
PLL_36XX_RATE(180000000, 90, 3, 2, 0),
PLL_36XX_RATE(73728000, 98, 2, 4, 19923),
PLL_36XX_RATE(67737600, 90, 2, 4, 20762),
PLL_36XX_RATE(49152000, 98, 3, 4, 19923),
PLL_36XX_RATE(45158400, 90, 3, 4, 20762),
PLL_36XX_RATE(32768000, 131, 3, 5, 4719),
{ },
};
static struct samsung_pll_rate_table apll_24mhz_tbl[] __initdata = {
/* sorted in descending order */
/* PLL_35XX_RATE(rate, m, p, s) */
PLL_35XX_RATE(1700000000, 425, 6, 0),
PLL_35XX_RATE(1600000000, 200, 3, 0),
PLL_35XX_RATE(1500000000, 250, 4, 0),
PLL_35XX_RATE(1400000000, 175, 3, 0),
PLL_35XX_RATE(1300000000, 325, 6, 0),
PLL_35XX_RATE(1200000000, 200, 4, 0),
PLL_35XX_RATE(1100000000, 275, 6, 0),
PLL_35XX_RATE(1000000000, 125, 3, 0),
PLL_35XX_RATE(900000000, 150, 4, 0),
PLL_35XX_RATE(800000000, 100, 3, 0),
PLL_35XX_RATE(700000000, 175, 3, 1),
PLL_35XX_RATE(600000000, 200, 4, 1),
PLL_35XX_RATE(500000000, 125, 3, 1),
PLL_35XX_RATE(400000000, 100, 3, 1),
PLL_35XX_RATE(300000000, 200, 4, 2),
PLL_35XX_RATE(200000000, 100, 3, 2),
};
static struct samsung_pll_clock exynos5250_plls[nr_plls] __initdata = {
[apll] = PLL_A(pll_35xx, CLK_FOUT_APLL, "fout_apll", "fin_pll",
APLL_LOCK, APLL_CON0, "fout_apll", NULL),
[mpll] = PLL_A(pll_35xx, CLK_FOUT_MPLL, "fout_mpll", "fin_pll",
MPLL_LOCK, MPLL_CON0, "fout_mpll", NULL),
[bpll] = PLL(pll_35xx, CLK_FOUT_BPLL, "fout_bpll", "fin_pll", BPLL_LOCK,
BPLL_CON0, NULL),
[gpll] = PLL(pll_35xx, CLK_FOUT_GPLL, "fout_gpll", "fin_pll", GPLL_LOCK,
GPLL_CON0, NULL),
[cpll] = PLL(pll_35xx, CLK_FOUT_CPLL, "fout_cpll", "fin_pll", CPLL_LOCK,
CPLL_CON0, NULL),
[epll] = PLL(pll_36xx, CLK_FOUT_EPLL, "fout_epll", "fin_pll", EPLL_LOCK,
EPLL_CON0, NULL),
[vpll] = PLL(pll_36xx, CLK_FOUT_VPLL, "fout_vpll", "mout_vpllsrc",
VPLL_LOCK, VPLL_CON0, NULL),
};
static const struct of_device_id ext_clk_match[] __initconst = {
{ .compatible = "samsung,clock-xxti", .data = (void *)0, },
{ },
};
/* register exynox5250 clocks */
static void __init exynos5250_clk_init(struct device_node *np)
{
struct samsung_clk_provider *ctx;
unsigned int tmp;
if (np) {
reg_base = of_iomap(np, 0);
if (!reg_base)
panic("%s: failed to map registers\n", __func__);
} else {
panic("%s: unable to determine soc\n", __func__);
}
ctx = samsung_clk_init(np, reg_base, CLK_NR_CLKS);
if (!ctx)
panic("%s: unable to allocate context.\n", __func__);
samsung_clk_of_register_fixed_ext(ctx, exynos5250_fixed_rate_ext_clks,
ARRAY_SIZE(exynos5250_fixed_rate_ext_clks),
ext_clk_match);
samsung_clk_register_mux(ctx, exynos5250_pll_pmux_clks,
ARRAY_SIZE(exynos5250_pll_pmux_clks));
if (_get_rate("fin_pll") == 24 * MHZ) {
exynos5250_plls[epll].rate_table = epll_24mhz_tbl;
exynos5250_plls[apll].rate_table = apll_24mhz_tbl;
}
if (_get_rate("mout_vpllsrc") == 24 * MHZ)
exynos5250_plls[vpll].rate_table = vpll_24mhz_tbl;
samsung_clk_register_pll(ctx, exynos5250_plls,
ARRAY_SIZE(exynos5250_plls),
reg_base);
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,
ARRAY_SIZE(exynos5250_fixed_factor_clks));
samsung_clk_register_mux(ctx, exynos5250_mux_clks,
ARRAY_SIZE(exynos5250_mux_clks));
samsung_clk_register_div(ctx, exynos5250_div_clks,
ARRAY_SIZE(exynos5250_div_clks));
samsung_clk_register_gate(ctx, exynos5250_gate_clks,
ARRAY_SIZE(exynos5250_gate_clks));
/*
* Enable arm clock down (in idle) and set arm divider
* ratios in WFI/WFE state.
*/
tmp = (PWR_CTRL1_CORE2_DOWN_RATIO | PWR_CTRL1_CORE1_DOWN_RATIO |
PWR_CTRL1_DIV2_DOWN_EN | PWR_CTRL1_DIV1_DOWN_EN |
PWR_CTRL1_USE_CORE1_WFE | PWR_CTRL1_USE_CORE0_WFE |
PWR_CTRL1_USE_CORE1_WFI | PWR_CTRL1_USE_CORE0_WFI);
__raw_writel(tmp, reg_base + PWR_CTRL1);
/*
* Enable arm clock up (on exiting idle). Set arm divider
* ratios when not in idle along with the standby duration
* ratios.
*/
tmp = (PWR_CTRL2_DIV2_UP_EN | PWR_CTRL2_DIV1_UP_EN |
PWR_CTRL2_DUR_STANDBY2_VAL | PWR_CTRL2_DUR_STANDBY1_VAL |
PWR_CTRL2_CORE2_UP_RATIO | PWR_CTRL2_CORE1_UP_RATIO);
__raw_writel(tmp, reg_base + PWR_CTRL2);
exynos5250_clk_sleep_init();
samsung_clk_of_add_provider(np, ctx);
pr_info("Exynos5250: clock setup completed, armclk=%ld\n",
_get_rate("div_arm2"));
}
CLK_OF_DECLARE(exynos5250_clk, "samsung,exynos5250-clock", exynos5250_clk_init);

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,459 @@
/*
* Copyright (c) 2014 Samsung Electronics Co., Ltd.
* Author: Rahul Sharma <rahul.sharma@samsung.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Common Clock Framework support for Exynos5260 SoC.
*/
#ifndef __CLK_EXYNOS5260_H
#define __CLK_EXYNOS5260_H
/*
*Registers for CMU_AUD
*/
#define MUX_SEL_AUD 0x0200
#define MUX_ENABLE_AUD 0x0300
#define MUX_STAT_AUD 0x0400
#define MUX_IGNORE_AUD 0x0500
#define DIV_AUD0 0x0600
#define DIV_AUD1 0x0604
#define DIV_STAT_AUD0 0x0700
#define DIV_STAT_AUD1 0x0704
#define EN_ACLK_AUD 0x0800
#define EN_PCLK_AUD 0x0900
#define EN_SCLK_AUD 0x0a00
#define EN_IP_AUD 0x0b00
/*
*Registers for CMU_DISP
*/
#define MUX_SEL_DISP0 0x0200
#define MUX_SEL_DISP1 0x0204
#define MUX_SEL_DISP2 0x0208
#define MUX_SEL_DISP3 0x020C
#define MUX_SEL_DISP4 0x0210
#define MUX_ENABLE_DISP0 0x0300
#define MUX_ENABLE_DISP1 0x0304
#define MUX_ENABLE_DISP2 0x0308
#define MUX_ENABLE_DISP3 0x030c
#define MUX_ENABLE_DISP4 0x0310
#define MUX_STAT_DISP0 0x0400
#define MUX_STAT_DISP1 0x0404
#define MUX_STAT_DISP2 0x0408
#define MUX_STAT_DISP3 0x040c
#define MUX_STAT_DISP4 0x0410
#define MUX_IGNORE_DISP0 0x0500
#define MUX_IGNORE_DISP1 0x0504
#define MUX_IGNORE_DISP2 0x0508
#define MUX_IGNORE_DISP3 0x050c
#define MUX_IGNORE_DISP4 0x0510
#define DIV_DISP 0x0600
#define DIV_STAT_DISP 0x0700
#define EN_ACLK_DISP 0x0800
#define EN_PCLK_DISP 0x0900
#define EN_SCLK_DISP0 0x0a00
#define EN_SCLK_DISP1 0x0a04
#define EN_IP_DISP 0x0b00
#define EN_IP_DISP_BUS 0x0b04
/*
*Registers for CMU_EGL
*/
#define EGL_PLL_LOCK 0x0000
#define EGL_DPLL_LOCK 0x0004
#define EGL_PLL_CON0 0x0100
#define EGL_PLL_CON1 0x0104
#define EGL_PLL_FREQ_DET 0x010c
#define EGL_DPLL_CON0 0x0110
#define EGL_DPLL_CON1 0x0114
#define EGL_DPLL_FREQ_DET 0x011c
#define MUX_SEL_EGL 0x0200
#define MUX_ENABLE_EGL 0x0300
#define MUX_STAT_EGL 0x0400
#define DIV_EGL 0x0600
#define DIV_EGL_PLL_FDET 0x0604
#define DIV_STAT_EGL 0x0700
#define DIV_STAT_EGL_PLL_FDET 0x0704
#define EN_ACLK_EGL 0x0800
#define EN_PCLK_EGL 0x0900
#define EN_SCLK_EGL 0x0a00
#define EN_IP_EGL 0x0b00
#define CLKOUT_CMU_EGL 0x0c00
#define CLKOUT_CMU_EGL_DIV_STAT 0x0c04
#define ARMCLK_STOPCTRL 0x1000
#define EAGLE_EMA_CTRL 0x1008
#define EAGLE_EMA_STATUS 0x100c
#define PWR_CTRL 0x1020
#define PWR_CTRL2 0x1024
#define CLKSTOP_CTRL 0x1028
#define INTR_SPREAD_EN 0x1080
#define INTR_SPREAD_USE_STANDBYWFI 0x1084
#define INTR_SPREAD_BLOCKING_DURATION 0x1088
#define CMU_EGL_SPARE0 0x2000
#define CMU_EGL_SPARE1 0x2004
#define CMU_EGL_SPARE2 0x2008
#define CMU_EGL_SPARE3 0x200c
#define CMU_EGL_SPARE4 0x2010
/*
*Registers for CMU_FSYS
*/
#define MUX_SEL_FSYS0 0x0200
#define MUX_SEL_FSYS1 0x0204
#define MUX_ENABLE_FSYS0 0x0300
#define MUX_ENABLE_FSYS1 0x0304
#define MUX_STAT_FSYS0 0x0400
#define MUX_STAT_FSYS1 0x0404
#define MUX_IGNORE_FSYS0 0x0500
#define MUX_IGNORE_FSYS1 0x0504
#define EN_ACLK_FSYS 0x0800
#define EN_ACLK_FSYS_SECURE_RTIC 0x0804
#define EN_ACLK_FSYS_SECURE_SMMU_RTIC 0x0808
#define EN_PCLK_FSYS 0x0900
#define EN_SCLK_FSYS 0x0a00
#define EN_IP_FSYS 0x0b00
#define EN_IP_FSYS_SECURE_RTIC 0x0b04
#define EN_IP_FSYS_SECURE_SMMU_RTIC 0x0b08
/*
*Registers for CMU_G2D
*/
#define MUX_SEL_G2D 0x0200
#define MUX_ENABLE_G2D 0x0300
#define MUX_STAT_G2D 0x0400
#define DIV_G2D 0x0600
#define DIV_STAT_G2D 0x0700
#define EN_ACLK_G2D 0x0800
#define EN_ACLK_G2D_SECURE_SSS 0x0804
#define EN_ACLK_G2D_SECURE_SLIM_SSS 0x0808
#define EN_ACLK_G2D_SECURE_SMMU_SLIM_SSS 0x080c
#define EN_ACLK_G2D_SECURE_SMMU_SSS 0x0810
#define EN_ACLK_G2D_SECURE_SMMU_MDMA 0x0814
#define EN_ACLK_G2D_SECURE_SMMU_G2D 0x0818
#define EN_PCLK_G2D 0x0900
#define EN_PCLK_G2D_SECURE_SMMU_SLIM_SSS 0x0904
#define EN_PCLK_G2D_SECURE_SMMU_SSS 0x0908
#define EN_PCLK_G2D_SECURE_SMMU_MDMA 0x090c
#define EN_PCLK_G2D_SECURE_SMMU_G2D 0x0910
#define EN_IP_G2D 0x0b00
#define EN_IP_G2D_SECURE_SSS 0x0b04
#define EN_IP_G2D_SECURE_SLIM_SSS 0x0b08
#define EN_IP_G2D_SECURE_SMMU_SLIM_SSS 0x0b0c
#define EN_IP_G2D_SECURE_SMMU_SSS 0x0b10
#define EN_IP_G2D_SECURE_SMMU_MDMA 0x0b14
#define EN_IP_G2D_SECURE_SMMU_G2D 0x0b18
/*
*Registers for CMU_G3D
*/
#define G3D_PLL_LOCK 0x0000
#define G3D_PLL_CON0 0x0100
#define G3D_PLL_CON1 0x0104
#define G3D_PLL_FDET 0x010c
#define MUX_SEL_G3D 0x0200
#define MUX_EN_G3D 0x0300
#define MUX_STAT_G3D 0x0400
#define MUX_IGNORE_G3D 0x0500
#define DIV_G3D 0x0600
#define DIV_G3D_PLL_FDET 0x0604
#define DIV_STAT_G3D 0x0700
#define DIV_STAT_G3D_PLL_FDET 0x0704
#define EN_ACLK_G3D 0x0800
#define EN_PCLK_G3D 0x0900
#define EN_SCLK_G3D 0x0a00
#define EN_IP_G3D 0x0b00
#define CLKOUT_CMU_G3D 0x0c00
#define CLKOUT_CMU_G3D_DIV_STAT 0x0c04
#define G3DCLK_STOPCTRL 0x1000
#define G3D_EMA_CTRL 0x1008
#define G3D_EMA_STATUS 0x100c
/*
*Registers for CMU_GSCL
*/
#define MUX_SEL_GSCL 0x0200
#define MUX_EN_GSCL 0x0300
#define MUX_STAT_GSCL 0x0400
#define MUX_IGNORE_GSCL 0x0500
#define DIV_GSCL 0x0600
#define DIV_STAT_GSCL 0x0700
#define EN_ACLK_GSCL 0x0800
#define EN_ACLK_GSCL_FIMC 0x0804
#define EN_ACLK_GSCL_SECURE_SMMU_GSCL0 0x0808
#define EN_ACLK_GSCL_SECURE_SMMU_GSCL1 0x080c
#define EN_ACLK_GSCL_SECURE_SMMU_MSCL0 0x0810
#define EN_ACLK_GSCL_SECURE_SMMU_MSCL1 0x0814
#define EN_PCLK_GSCL 0x0900
#define EN_PCLK_GSCL_FIMC 0x0904
#define EN_PCLK_GSCL_SECURE_SMMU_GSCL0 0x0908
#define EN_PCLK_GSCL_SECURE_SMMU_GSCL1 0x090c
#define EN_PCLK_GSCL_SECURE_SMMU_MSCL0 0x0910
#define EN_PCLK_GSCL_SECURE_SMMU_MSCL1 0x0914
#define EN_SCLK_GSCL 0x0a00
#define EN_SCLK_GSCL_FIMC 0x0a04
#define EN_IP_GSCL 0x0b00
#define EN_IP_GSCL_FIMC 0x0b04
#define EN_IP_GSCL_SECURE_SMMU_GSCL0 0x0b08
#define EN_IP_GSCL_SECURE_SMMU_GSCL1 0x0b0c
#define EN_IP_GSCL_SECURE_SMMU_MSCL0 0x0b10
#define EN_IP_GSCL_SECURE_SMMU_MSCL1 0x0b14
/*
*Registers for CMU_ISP
*/
#define MUX_SEL_ISP0 0x0200
#define MUX_SEL_ISP1 0x0204
#define MUX_ENABLE_ISP0 0x0300
#define MUX_ENABLE_ISP1 0x0304
#define MUX_STAT_ISP0 0x0400
#define MUX_STAT_ISP1 0x0404
#define MUX_IGNORE_ISP0 0x0500
#define MUX_IGNORE_ISP1 0x0504
#define DIV_ISP 0x0600
#define DIV_STAT_ISP 0x0700
#define EN_ACLK_ISP0 0x0800
#define EN_ACLK_ISP1 0x0804
#define EN_PCLK_ISP0 0x0900
#define EN_PCLK_ISP1 0x0904
#define EN_SCLK_ISP 0x0a00
#define EN_IP_ISP0 0x0b00
#define EN_IP_ISP1 0x0b04
/*
*Registers for CMU_KFC
*/
#define KFC_PLL_LOCK 0x0000
#define KFC_PLL_CON0 0x0100
#define KFC_PLL_CON1 0x0104
#define KFC_PLL_FDET 0x010c
#define MUX_SEL_KFC0 0x0200
#define MUX_SEL_KFC2 0x0208
#define MUX_ENABLE_KFC0 0x0300
#define MUX_ENABLE_KFC2 0x0308
#define MUX_STAT_KFC0 0x0400
#define MUX_STAT_KFC2 0x0408
#define DIV_KFC 0x0600
#define DIV_KFC_PLL_FDET 0x0604
#define DIV_STAT_KFC 0x0700
#define DIV_STAT_KFC_PLL_FDET 0x0704
#define EN_ACLK_KFC 0x0800
#define EN_PCLK_KFC 0x0900
#define EN_SCLK_KFC 0x0a00
#define EN_IP_KFC 0x0b00
#define CLKOUT_CMU_KFC 0x0c00
#define CLKOUT_CMU_KFC_DIV_STAT 0x0c04
#define ARMCLK_STOPCTRL_KFC 0x1000
#define ARM_EMA_CTRL 0x1008
#define ARM_EMA_STATUS 0x100c
#define PWR_CTRL_KFC 0x1020
#define PWR_CTRL2_KFC 0x1024
#define CLKSTOP_CTRL_KFC 0x1028
#define INTR_SPREAD_ENABLE_KFC 0x1080
#define INTR_SPREAD_USE_STANDBYWFI_KFC 0x1084
#define INTR_SPREAD_BLOCKING_DURATION_KFC 0x1088
#define CMU_KFC_SPARE0 0x2000
#define CMU_KFC_SPARE1 0x2004
#define CMU_KFC_SPARE2 0x2008
#define CMU_KFC_SPARE3 0x200c
#define CMU_KFC_SPARE4 0x2010
/*
*Registers for CMU_MFC
*/
#define MUX_SEL_MFC 0x0200
#define MUX_ENABLE_MFC 0x0300
#define MUX_STAT_MFC 0x0400
#define DIV_MFC 0x0600
#define DIV_STAT_MFC 0x0700
#define EN_ACLK_MFC 0x0800
#define EN_ACLK_SECURE_SMMU2_MFC 0x0804
#define EN_PCLK_MFC 0x0900
#define EN_PCLK_SECURE_SMMU2_MFC 0x0904
#define EN_IP_MFC 0x0b00
#define EN_IP_MFC_SECURE_SMMU2_MFC 0x0b04
/*
*Registers for CMU_MIF
*/
#define MEM_PLL_LOCK 0x0000
#define BUS_PLL_LOCK 0x0004
#define MEDIA_PLL_LOCK 0x0008
#define MEM_PLL_CON0 0x0100
#define MEM_PLL_CON1 0x0104
#define MEM_PLL_FDET 0x010c
#define BUS_PLL_CON0 0x0110
#define BUS_PLL_CON1 0x0114
#define BUS_PLL_FDET 0x011c
#define MEDIA_PLL_CON0 0x0120
#define MEDIA_PLL_CON1 0x0124
#define MEDIA_PLL_FDET 0x012c
#define MUX_SEL_MIF 0x0200
#define MUX_ENABLE_MIF 0x0300
#define MUX_STAT_MIF 0x0400
#define MUX_IGNORE_MIF 0x0500
#define DIV_MIF 0x0600
#define DIV_MIF_PLL_FDET 0x0604
#define DIV_STAT_MIF 0x0700
#define DIV_STAT_MIF_PLL_FDET 0x0704
#define EN_ACLK_MIF 0x0800
#define EN_ACLK_MIF_SECURE_DREX1_TZ 0x0804
#define EN_ACLK_MIF_SECURE_DREX0_TZ 0x0808
#define EN_ACLK_MIF_SECURE_INTMEM 0x080c
#define EN_PCLK_MIF 0x0900
#define EN_PCLK_MIF_SECURE_MONOCNT 0x0904
#define EN_PCLK_MIF_SECURE_RTC_APBIF 0x0908
#define EN_PCLK_MIF_SECURE_DREX1_TZ 0x090c
#define EN_PCLK_MIF_SECURE_DREX0_TZ 0x0910
#define EN_SCLK_MIF 0x0a00
#define EN_IP_MIF 0x0b00
#define EN_IP_MIF_SECURE_MONOCNT 0x0b04
#define EN_IP_MIF_SECURE_RTC_APBIF 0x0b08
#define EN_IP_MIF_SECURE_DREX1_TZ 0x0b0c
#define EN_IP_MIF_SECURE_DREX0_TZ 0x0b10
#define EN_IP_MIF_SECURE_INTEMEM 0x0b14
#define CLKOUT_CMU_MIF_DIV_STAT 0x0c04
#define DREX_FREQ_CTRL 0x1000
#define PAUSE 0x1004
#define DDRPHY_LOCK_CTRL 0x1008
#define CLKOUT_CMU_MIF 0xcb00
/*
*Registers for CMU_PERI
*/
#define MUX_SEL_PERI 0x0200
#define MUX_SEL_PERI1 0x0204
#define MUX_ENABLE_PERI 0x0300
#define MUX_ENABLE_PERI1 0x0304
#define MUX_STAT_PERI 0x0400
#define MUX_STAT_PERI1 0x0404
#define MUX_IGNORE_PERI 0x0500
#define MUX_IGNORE_PERI1 0x0504
#define DIV_PERI 0x0600
#define DIV_STAT_PERI 0x0700
#define EN_PCLK_PERI0 0x0800
#define EN_PCLK_PERI1 0x0804
#define EN_PCLK_PERI2 0x0808
#define EN_PCLK_PERI3 0x080c
#define EN_PCLK_PERI_SECURE_CHIPID 0x0810
#define EN_PCLK_PERI_SECURE_PROVKEY0 0x0814
#define EN_PCLK_PERI_SECURE_PROVKEY1 0x0818
#define EN_PCLK_PERI_SECURE_SECKEY 0x081c
#define EN_PCLK_PERI_SECURE_ANTIRBKCNT 0x0820
#define EN_PCLK_PERI_SECURE_TOP_RTC 0x0824
#define EN_PCLK_PERI_SECURE_TZPC 0x0828
#define EN_SCLK_PERI 0x0a00
#define EN_SCLK_PERI_SECURE_TOP_RTC 0x0a04
#define EN_IP_PERI0 0x0b00
#define EN_IP_PERI1 0x0b04
#define EN_IP_PERI2 0x0b08
#define EN_IP_PERI_SECURE_CHIPID 0x0b0c
#define EN_IP_PERI_SECURE_PROVKEY0 0x0b10
#define EN_IP_PERI_SECURE_PROVKEY1 0x0b14
#define EN_IP_PERI_SECURE_SECKEY 0x0b18
#define EN_IP_PERI_SECURE_ANTIRBKCNT 0x0b1c
#define EN_IP_PERI_SECURE_TOP_RTC 0x0b20
#define EN_IP_PERI_SECURE_TZPC 0x0b24
/*
*Registers for CMU_TOP
*/
#define DISP_PLL_LOCK 0x0000
#define AUD_PLL_LOCK 0x0004
#define DISP_PLL_CON0 0x0100
#define DISP_PLL_CON1 0x0104
#define DISP_PLL_FDET 0x0108
#define AUD_PLL_CON0 0x0110
#define AUD_PLL_CON1 0x0114
#define AUD_PLL_CON2 0x0118
#define AUD_PLL_FDET 0x011c
#define MUX_SEL_TOP_PLL0 0x0200
#define MUX_SEL_TOP_MFC 0x0204
#define MUX_SEL_TOP_G2D 0x0208
#define MUX_SEL_TOP_GSCL 0x020c
#define MUX_SEL_TOP_ISP10 0x0214
#define MUX_SEL_TOP_ISP11 0x0218
#define MUX_SEL_TOP_DISP0 0x021c
#define MUX_SEL_TOP_DISP1 0x0220
#define MUX_SEL_TOP_BUS 0x0224
#define MUX_SEL_TOP_PERI0 0x0228
#define MUX_SEL_TOP_PERI1 0x022c
#define MUX_SEL_TOP_FSYS 0x0230
#define MUX_ENABLE_TOP_PLL0 0x0300
#define MUX_ENABLE_TOP_MFC 0x0304
#define MUX_ENABLE_TOP_G2D 0x0308
#define MUX_ENABLE_TOP_GSCL 0x030c
#define MUX_ENABLE_TOP_ISP10 0x0314
#define MUX_ENABLE_TOP_ISP11 0x0318
#define MUX_ENABLE_TOP_DISP0 0x031c
#define MUX_ENABLE_TOP_DISP1 0x0320
#define MUX_ENABLE_TOP_BUS 0x0324
#define MUX_ENABLE_TOP_PERI0 0x0328
#define MUX_ENABLE_TOP_PERI1 0x032c
#define MUX_ENABLE_TOP_FSYS 0x0330
#define MUX_STAT_TOP_PLL0 0x0400
#define MUX_STAT_TOP_MFC 0x0404
#define MUX_STAT_TOP_G2D 0x0408
#define MUX_STAT_TOP_GSCL 0x040c
#define MUX_STAT_TOP_ISP10 0x0414
#define MUX_STAT_TOP_ISP11 0x0418
#define MUX_STAT_TOP_DISP0 0x041c
#define MUX_STAT_TOP_DISP1 0x0420
#define MUX_STAT_TOP_BUS 0x0424
#define MUX_STAT_TOP_PERI0 0x0428
#define MUX_STAT_TOP_PERI1 0x042c
#define MUX_STAT_TOP_FSYS 0x0430
#define MUX_IGNORE_TOP_PLL0 0x0500
#define MUX_IGNORE_TOP_MFC 0x0504
#define MUX_IGNORE_TOP_G2D 0x0508
#define MUX_IGNORE_TOP_GSCL 0x050c
#define MUX_IGNORE_TOP_ISP10 0x0514
#define MUX_IGNORE_TOP_ISP11 0x0518
#define MUX_IGNORE_TOP_DISP0 0x051c
#define MUX_IGNORE_TOP_DISP1 0x0520
#define MUX_IGNORE_TOP_BUS 0x0524
#define MUX_IGNORE_TOP_PERI0 0x0528
#define MUX_IGNORE_TOP_PERI1 0x052c
#define MUX_IGNORE_TOP_FSYS 0x0530
#define DIV_TOP_G2D_MFC 0x0600
#define DIV_TOP_GSCL_ISP0 0x0604
#define DIV_TOP_ISP10 0x0608
#define DIV_TOP_ISP11 0x060c
#define DIV_TOP_DISP 0x0610
#define DIV_TOP_BUS 0x0614
#define DIV_TOP_PERI0 0x0618
#define DIV_TOP_PERI1 0x061c
#define DIV_TOP_PERI2 0x0620
#define DIV_TOP_FSYS0 0x0624
#define DIV_TOP_FSYS1 0x0628
#define DIV_TOP_HPM 0x062c
#define DIV_TOP_PLL_FDET 0x0630
#define DIV_STAT_TOP_G2D_MFC 0x0700
#define DIV_STAT_TOP_GSCL_ISP0 0x0704
#define DIV_STAT_TOP_ISP10 0x0708
#define DIV_STAT_TOP_ISP11 0x070c
#define DIV_STAT_TOP_DISP 0x0710
#define DIV_STAT_TOP_BUS 0x0714
#define DIV_STAT_TOP_PERI0 0x0718
#define DIV_STAT_TOP_PERI1 0x071c
#define DIV_STAT_TOP_PERI2 0x0720
#define DIV_STAT_TOP_FSYS0 0x0724
#define DIV_STAT_TOP_FSYS1 0x0728
#define DIV_STAT_TOP_HPM 0x072c
#define DIV_STAT_TOP_PLL_FDET 0x0730
#define EN_ACLK_TOP 0x0800
#define EN_SCLK_TOP 0x0a00
#define EN_IP_TOP 0x0b00
#define CLKOUT_CMU_TOP 0x0c00
#define CLKOUT_CMU_TOP_DIV_STAT 0x0c04
#endif /*__CLK_EXYNOS5260_H */

View file

@ -0,0 +1,211 @@
/*
* Copyright (c) 2013 Samsung Electronics Co., Ltd.
* Author: Tarek Dakhran <t.dakhran@samsung.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Common Clock Framework support for Exynos5410 SoC.
*/
#include <dt-bindings/clock/exynos5410.h>
#include <linux/clk.h>
#include <linux/clkdev.h>
#include <linux/clk-provider.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include "clk.h"
#define APLL_LOCK 0x0
#define APLL_CON0 0x100
#define CPLL_LOCK 0x10020
#define CPLL_CON0 0x10120
#define MPLL_LOCK 0x4000
#define MPLL_CON0 0x4100
#define BPLL_LOCK 0x20010
#define BPLL_CON0 0x20110
#define KPLL_LOCK 0x28000
#define KPLL_CON0 0x28100
#define SRC_CPU 0x200
#define DIV_CPU0 0x500
#define SRC_CPERI1 0x4204
#define DIV_TOP0 0x10510
#define DIV_TOP1 0x10514
#define DIV_FSYS1 0x1054c
#define DIV_FSYS2 0x10550
#define DIV_PERIC0 0x10558
#define SRC_TOP0 0x10210
#define SRC_TOP1 0x10214
#define SRC_TOP2 0x10218
#define SRC_FSYS 0x10244
#define SRC_PERIC0 0x10250
#define SRC_MASK_FSYS 0x10340
#define SRC_MASK_PERIC0 0x10350
#define GATE_BUS_FSYS0 0x10740
#define GATE_IP_FSYS 0x10944
#define GATE_IP_PERIC 0x10950
#define GATE_IP_PERIS 0x10960
#define SRC_CDREX 0x20200
#define SRC_KFC 0x28200
#define DIV_KFC0 0x28500
/* list of PLLs */
enum exynos5410_plls {
apll, cpll, mpll,
bpll, kpll,
nr_plls /* number of PLLs */
};
/* list of all parent clocks */
PNAME(apll_p) = { "fin_pll", "fout_apll", };
PNAME(bpll_p) = { "fin_pll", "fout_bpll", };
PNAME(cpll_p) = { "fin_pll", "fout_cpll" };
PNAME(mpll_p) = { "fin_pll", "fout_mpll", };
PNAME(kpll_p) = { "fin_pll", "fout_kpll", };
PNAME(mout_cpu_p) = { "mout_apll", "sclk_mpll", };
PNAME(mout_kfc_p) = { "mout_kpll", "sclk_mpll", };
PNAME(mpll_user_p) = { "fin_pll", "sclk_mpll", };
PNAME(bpll_user_p) = { "fin_pll", "sclk_bpll", };
PNAME(mpll_bpll_p) = { "sclk_mpll_muxed", "sclk_bpll_muxed", };
PNAME(group2_p) = { "fin_pll", "fin_pll", "none", "none",
"none", "none", "sclk_mpll_bpll",
"none", "none", "sclk_cpll" };
static struct samsung_mux_clock exynos5410_mux_clks[] __initdata = {
MUX(0, "mout_apll", apll_p, SRC_CPU, 0, 1),
MUX(0, "mout_cpu", mout_cpu_p, SRC_CPU, 16, 1),
MUX(0, "mout_kpll", kpll_p, SRC_KFC, 0, 1),
MUX(0, "mout_kfc", mout_kfc_p, SRC_KFC, 16, 1),
MUX(0, "sclk_mpll", mpll_p, SRC_CPERI1, 8, 1),
MUX(0, "sclk_mpll_muxed", mpll_user_p, SRC_TOP2, 20, 1),
MUX(0, "sclk_bpll", bpll_p, SRC_CDREX, 0, 1),
MUX(0, "sclk_bpll_muxed", bpll_user_p, SRC_TOP2, 24, 1),
MUX(0, "sclk_cpll", cpll_p, SRC_TOP2, 8, 1),
MUX(0, "sclk_mpll_bpll", mpll_bpll_p, SRC_TOP1, 20, 1),
MUX(0, "mout_mmc0", group2_p, SRC_FSYS, 0, 4),
MUX(0, "mout_mmc1", group2_p, SRC_FSYS, 4, 4),
MUX(0, "mout_mmc2", group2_p, SRC_FSYS, 8, 4),
MUX(0, "mout_uart0", group2_p, SRC_PERIC0, 0, 4),
MUX(0, "mout_uart1", group2_p, SRC_PERIC0, 4, 4),
MUX(0, "mout_uart2", group2_p, SRC_PERIC0, 8, 4),
MUX(0, "mout_aclk200", mpll_bpll_p, SRC_TOP0, 12, 1),
MUX(0, "mout_aclk400", mpll_bpll_p, SRC_TOP0, 20, 1),
};
static struct samsung_div_clock exynos5410_div_clks[] __initdata = {
DIV(0, "div_arm", "mout_cpu", DIV_CPU0, 0, 3),
DIV(0, "div_arm2", "div_arm", DIV_CPU0, 28, 3),
DIV(0, "div_acp", "div_arm2", DIV_CPU0, 8, 3),
DIV(0, "div_cpud", "div_arm2", DIV_CPU0, 4, 3),
DIV(0, "div_atb", "div_arm2", DIV_CPU0, 16, 3),
DIV(0, "pclk_dbg", "div_arm2", DIV_CPU0, 20, 3),
DIV(0, "div_kfc", "mout_kfc", DIV_KFC0, 0, 3),
DIV(0, "div_aclk", "div_kfc", DIV_KFC0, 4, 3),
DIV(0, "div_pclk", "div_kfc", DIV_KFC0, 20, 3),
DIV(0, "aclk66_pre", "sclk_mpll_muxed", DIV_TOP1, 24, 3),
DIV(0, "aclk66", "aclk66_pre", DIV_TOP0, 0, 3),
DIV(0, "div_mmc0", "mout_mmc0", DIV_FSYS1, 0, 4),
DIV(0, "div_mmc1", "mout_mmc1", DIV_FSYS1, 16, 4),
DIV(0, "div_mmc2", "mout_mmc2", DIV_FSYS2, 0, 4),
DIV_F(0, "div_mmc_pre0", "div_mmc0",
DIV_FSYS1, 8, 8, CLK_SET_RATE_PARENT, 0),
DIV_F(0, "div_mmc_pre1", "div_mmc1",
DIV_FSYS1, 24, 8, CLK_SET_RATE_PARENT, 0),
DIV_F(0, "div_mmc_pre2", "div_mmc2",
DIV_FSYS2, 8, 8, CLK_SET_RATE_PARENT, 0),
DIV(0, "div_uart0", "mout_uart0", DIV_PERIC0, 0, 4),
DIV(0, "div_uart1", "mout_uart1", DIV_PERIC0, 4, 4),
DIV(0, "div_uart2", "mout_uart2", DIV_PERIC0, 8, 4),
DIV(0, "div_uart3", "mout_uart3", DIV_PERIC0, 12, 4),
DIV(0, "aclk200", "mout_aclk200", DIV_TOP0, 12, 3),
DIV(0, "aclk400", "mout_aclk400", DIV_TOP0, 24, 3),
};
static struct samsung_gate_clock exynos5410_gate_clks[] __initdata = {
GATE(CLK_MCT, "mct", "aclk66", GATE_IP_PERIS, 18, 0, 0),
GATE(CLK_SCLK_MMC0, "sclk_mmc0", "div_mmc_pre0",
SRC_MASK_FSYS, 0, CLK_SET_RATE_PARENT, 0),
GATE(CLK_SCLK_MMC1, "sclk_mmc1", "div_mmc_pre1",
SRC_MASK_FSYS, 4, CLK_SET_RATE_PARENT, 0),
GATE(CLK_SCLK_MMC2, "sclk_mmc2", "div_mmc_pre2",
SRC_MASK_FSYS, 8, CLK_SET_RATE_PARENT, 0),
GATE(CLK_MMC0, "sdmmc0", "aclk200", GATE_BUS_FSYS0, 12, 0, 0),
GATE(CLK_MMC1, "sdmmc1", "aclk200", GATE_BUS_FSYS0, 13, 0, 0),
GATE(CLK_MMC2, "sdmmc2", "aclk200", GATE_BUS_FSYS0, 14, 0, 0),
GATE(CLK_UART0, "uart0", "aclk66", GATE_IP_PERIC, 0, 0, 0),
GATE(CLK_UART1, "uart1", "aclk66", GATE_IP_PERIC, 1, 0, 0),
GATE(CLK_UART2, "uart2", "aclk66", GATE_IP_PERIC, 2, 0, 0),
GATE(CLK_SCLK_UART0, "sclk_uart0", "div_uart0",
SRC_MASK_PERIC0, 0, CLK_SET_RATE_PARENT, 0),
GATE(CLK_SCLK_UART1, "sclk_uart1", "div_uart1",
SRC_MASK_PERIC0, 4, CLK_SET_RATE_PARENT, 0),
GATE(CLK_SCLK_UART2, "sclk_uart2", "div_uart2",
SRC_MASK_PERIC0, 8, CLK_SET_RATE_PARENT, 0),
};
static struct samsung_pll_clock exynos5410_plls[nr_plls] __initdata = {
[apll] = PLL(pll_35xx, CLK_FOUT_APLL, "fout_apll", "fin_pll", APLL_LOCK,
APLL_CON0, NULL),
[cpll] = PLL(pll_35xx, CLK_FOUT_CPLL, "fout_cpll", "fin_pll", CPLL_LOCK,
CPLL_CON0, NULL),
[mpll] = PLL(pll_35xx, CLK_FOUT_MPLL, "fout_mpll", "fin_pll", MPLL_LOCK,
MPLL_CON0, NULL),
[bpll] = PLL(pll_35xx, CLK_FOUT_BPLL, "fout_bpll", "fin_pll", BPLL_LOCK,
BPLL_CON0, NULL),
[kpll] = PLL(pll_35xx, CLK_FOUT_KPLL, "fout_kpll", "fin_pll", KPLL_LOCK,
KPLL_CON0, NULL),
};
/* register exynos5410 clocks */
static void __init exynos5410_clk_init(struct device_node *np)
{
struct samsung_clk_provider *ctx;
void __iomem *reg_base;
reg_base = of_iomap(np, 0);
if (!reg_base)
panic("%s: failed to map registers\n", __func__);
ctx = samsung_clk_init(np, reg_base, CLK_NR_CLKS);
samsung_clk_register_pll(ctx, exynos5410_plls,
ARRAY_SIZE(exynos5410_plls), reg_base);
samsung_clk_register_mux(ctx, exynos5410_mux_clks,
ARRAY_SIZE(exynos5410_mux_clks));
samsung_clk_register_div(ctx, exynos5410_div_clks,
ARRAY_SIZE(exynos5410_div_clks));
samsung_clk_register_gate(ctx, exynos5410_gate_clks,
ARRAY_SIZE(exynos5410_gate_clks));
samsung_clk_of_add_provider(np, ctx);
pr_debug("Exynos5410: clock setup completed.\n");
}
CLK_OF_DECLARE(exynos5410_clk, "samsung,exynos5410-clock", exynos5410_clk_init);

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,131 @@
/*
* Copyright (c) 2013 Samsung Electronics Co., Ltd.
* Author: Thomas Abraham <thomas.ab@samsung.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Common Clock Framework support for Exynos5440 SoC.
*/
#include <dt-bindings/clock/exynos5440.h>
#include <linux/clk.h>
#include <linux/clkdev.h>
#include <linux/clk-provider.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include "clk.h"
#include "clk-pll.h"
#define CLKEN_OV_VAL 0xf8
#define CPU_CLK_STATUS 0xfc
#define MISC_DOUT1 0x558
/* parent clock name list */
PNAME(mout_armclk_p) = { "cplla", "cpllb" };
PNAME(mout_spi_p) = { "div125", "div200" };
/* fixed rate clocks generated outside the soc */
static struct samsung_fixed_rate_clock exynos5440_fixed_rate_ext_clks[] __initdata = {
FRATE(0, "xtal", NULL, CLK_IS_ROOT, 0),
};
/* fixed rate clocks */
static struct samsung_fixed_rate_clock exynos5440_fixed_rate_clks[] __initdata = {
FRATE(0, "ppll", NULL, CLK_IS_ROOT, 1000000000),
FRATE(0, "usb_phy0", NULL, CLK_IS_ROOT, 60000000),
FRATE(0, "usb_phy1", NULL, CLK_IS_ROOT, 60000000),
FRATE(0, "usb_ohci12", NULL, CLK_IS_ROOT, 12000000),
FRATE(0, "usb_ohci48", NULL, CLK_IS_ROOT, 48000000),
};
/* fixed factor clocks */
static struct samsung_fixed_factor_clock exynos5440_fixed_factor_clks[] __initdata = {
FFACTOR(0, "div250", "ppll", 1, 4, 0),
FFACTOR(0, "div200", "ppll", 1, 5, 0),
FFACTOR(0, "div125", "div250", 1, 2, 0),
};
/* mux clocks */
static struct samsung_mux_clock exynos5440_mux_clks[] __initdata = {
MUX(0, "mout_spi", mout_spi_p, MISC_DOUT1, 5, 1),
MUX_A(CLK_ARM_CLK, "arm_clk", mout_armclk_p,
CPU_CLK_STATUS, 0, 1, "armclk"),
};
/* divider clocks */
static struct samsung_div_clock exynos5440_div_clks[] __initdata = {
DIV(CLK_SPI_BAUD, "div_spi", "mout_spi", MISC_DOUT1, 3, 2),
};
/* gate clocks */
static struct samsung_gate_clock exynos5440_gate_clks[] __initdata = {
GATE(CLK_PB0_250, "pb0_250", "div250", CLKEN_OV_VAL, 3, 0, 0),
GATE(CLK_PR0_250, "pr0_250", "div250", CLKEN_OV_VAL, 4, 0, 0),
GATE(CLK_PR1_250, "pr1_250", "div250", CLKEN_OV_VAL, 5, 0, 0),
GATE(CLK_B_250, "b_250", "div250", CLKEN_OV_VAL, 9, 0, 0),
GATE(CLK_B_125, "b_125", "div125", CLKEN_OV_VAL, 10, 0, 0),
GATE(CLK_B_200, "b_200", "div200", CLKEN_OV_VAL, 11, 0, 0),
GATE(CLK_SATA, "sata", "div200", CLKEN_OV_VAL, 12, 0, 0),
GATE(CLK_USB, "usb", "div200", CLKEN_OV_VAL, 13, 0, 0),
GATE(CLK_GMAC0, "gmac0", "div200", CLKEN_OV_VAL, 14, 0, 0),
GATE(CLK_CS250, "cs250", "div250", CLKEN_OV_VAL, 19, 0, 0),
GATE(CLK_PB0_250_O, "pb0_250_o", "pb0_250", CLKEN_OV_VAL, 3, 0, 0),
GATE(CLK_PR0_250_O, "pr0_250_o", "pr0_250", CLKEN_OV_VAL, 4, 0, 0),
GATE(CLK_PR1_250_O, "pr1_250_o", "pr1_250", CLKEN_OV_VAL, 5, 0, 0),
GATE(CLK_B_250_O, "b_250_o", "b_250", CLKEN_OV_VAL, 9, 0, 0),
GATE(CLK_B_125_O, "b_125_o", "b_125", CLKEN_OV_VAL, 10, 0, 0),
GATE(CLK_B_200_O, "b_200_o", "b_200", CLKEN_OV_VAL, 11, 0, 0),
GATE(CLK_SATA_O, "sata_o", "sata", CLKEN_OV_VAL, 12, 0, 0),
GATE(CLK_USB_O, "usb_o", "usb", CLKEN_OV_VAL, 13, 0, 0),
GATE(CLK_GMAC0_O, "gmac0_o", "gmac", CLKEN_OV_VAL, 14, 0, 0),
GATE(CLK_CS250_O, "cs250_o", "cs250", CLKEN_OV_VAL, 19, 0, 0),
};
static const struct of_device_id ext_clk_match[] __initconst = {
{ .compatible = "samsung,clock-xtal", .data = (void *)0, },
{},
};
/* register exynos5440 clocks */
static void __init exynos5440_clk_init(struct device_node *np)
{
void __iomem *reg_base;
struct samsung_clk_provider *ctx;
reg_base = of_iomap(np, 0);
if (!reg_base) {
pr_err("%s: failed to map clock controller registers,"
" aborting clock initialization\n", __func__);
return;
}
ctx = samsung_clk_init(np, reg_base, CLK_NR_CLKS);
if (!ctx)
panic("%s: unable to allocate context.\n", __func__);
samsung_clk_of_register_fixed_ext(ctx, exynos5440_fixed_rate_ext_clks,
ARRAY_SIZE(exynos5440_fixed_rate_ext_clks), ext_clk_match);
samsung_clk_register_pll2550x("cplla", "xtal", reg_base + 0x1c, 0x10);
samsung_clk_register_pll2550x("cpllb", "xtal", reg_base + 0x20, 0x10);
samsung_clk_register_fixed_rate(ctx, exynos5440_fixed_rate_clks,
ARRAY_SIZE(exynos5440_fixed_rate_clks));
samsung_clk_register_fixed_factor(ctx, exynos5440_fixed_factor_clks,
ARRAY_SIZE(exynos5440_fixed_factor_clks));
samsung_clk_register_mux(ctx, exynos5440_mux_clks,
ARRAY_SIZE(exynos5440_mux_clks));
samsung_clk_register_div(ctx, exynos5440_div_clks,
ARRAY_SIZE(exynos5440_div_clks));
samsung_clk_register_gate(ctx, exynos5440_gate_clks,
ARRAY_SIZE(exynos5440_gate_clks));
samsung_clk_of_add_provider(np, ctx);
pr_info("Exynos5440: arm_clk = %ldHz\n", _get_rate("arm_clk"));
pr_info("exynos5440 clock initialization complete\n");
}
CLK_OF_DECLARE(exynos5440_clk, "samsung,exynos5440-clock", exynos5440_clk_init);

View file

@ -0,0 +1,288 @@
/*
* Copyright (c) 2013 Samsung Electronics Co., Ltd.
* Authors: Thomas Abraham <thomas.ab@samsung.com>
* Chander Kashyap <k.chander@samsung.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Common Clock Framework support for Exynos7570 SoC.
*/
#include <linux/clk.h>
#include <linux/clkdev.h>
#include <linux/clk-provider.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <soc/samsung/ect_parser.h>
#include <dt-bindings/clock/exynos7570.h>
#include "../../soc/samsung/pwrcal/S5E7570/S5E7570-vclk.h"
#include "composite.h"
enum exynos7570_clks {
none,
oscclk = 1,
/* mif group */
mif_adcif = 10, mif_speedy,
mif_uart_debug = 20, mif_uart_sensor, mif_spi_rearfrom, mif_spi_ese,
mif_mmc0 = 30, mif_mmc2, mif_usb20drd_refclk,
mif_usi0 = 40, mif_usi1, mif_apm, mif_isp_sensor0,
mif_pdma0 = 50,
/* cpucl0 group */
cpucl0_bcm = 100, cpucl0_bts,
/* g3d group */
g3d_sysmmu = 200, g3d_bcm, g3d_bts, gate_g3d,
/* peri group */
peri_i2c_sensor1 = 300, peri_i2c_sensor2, peri_i2c_tsp,
peri_i2c_fuelgauge = 310, peri_i2c_nfc, peri_i2c_muic,
peri_hsi2c_frontsensor = 320, peri_hsi2c_rearsensor, peri_hsi2c_rearaf,
peri_pwm_motor = 330, peri_sclk_pwm_motor, peri_hsi2c_maincam, peri_hsi2c_frontcam,
peri_gpio_touch = 340, peri_gpio_top, peri_gpio_nfc, peri_gpio_ese,
peri_gpio_alive = 350, peri_usi0, peri_usi1, peri_otp_con_top,
peri_uart_debug = 360, peri_uart_sensor, peri_spi_ese, peri_spi_rearfrom,
peri_mct = 370, peri_wdt_cpucl0, peri_tmu_cpucl0, peri_chipid, peri_rtc_alive, peri_rtc_top,
/* fsys group */
fsys_sysmmu = 500, fsys_bcm, fsys_bts,
fsys_sss = 510, fsys_rtic, fsys_usb20drd, fsys_mmc0, fsys_mmc2, fsys_sclk_mmc0, fsys_sclk_mmc2,
fsys_usb20drd_phyclock_user = 520,
wpll_usb = 530,
/* mfcmscl group */
mfcmscl_bcm = 601, mfcmscl_bts,
gate_mscl = 610, gate_jpeg, gate_mfc,
/* dispaud group */
dispaud_bcm = 701, dispaud_bts, dispaud_decon, dispaud_dsim0,
dispaud_mixer = 710, dispaud_mi2s_aud, dispaud_mi2s_amp,
dispaud_mipiphy_txbyteclkhs_user = 720,
dispaud_mipiphy_rxclkesc0_user,
decon_vclk = 730, decon_vclk_local,
aud_pll = 740, mi2s_div, mixer_div, oscclk_fm_52m_div,
/* isp group */
isp_bcm = 801, isp_bts, isp_cam, isp_vra,
isp_s_rxbyteclkhs0_s4_user = 810,
/* apm group */
gate_apm = 900,
/* number of dfs driver starts from 1000 */
dfs_mif = 1000, dfs_mif_sw, dfs_int, dfs_cam, dfs_disp,
/* number for clkout port starts from 1050 */
oscclk_aud = 1050,
/* clk id for sysmmu: 1100 ~ 1149
* NOTE: clock IDs of sysmmus are defined in
* include/dt-bindings/clock/exynos8890.h
*/
sysmmu_last = 1149,
nr_clks,
};
/* fixed rate clocks generated outside the soc */
static struct samsung_fixed_rate exynos7570_fixed_rate_ext_clks[] __initdata = {
FRATE(oscclk, "fin_pll", NULL, CLK_IS_ROOT, 26000000),
};
static struct init_vclk exynos7570_mif_vclks[] __initdata = {
VCLK(mif_adcif, gate_mif_adcif, "gate_mif_adcif", 0, 0, NULL),
VCLK(mif_speedy, gate_mif_speedy, "gate_mif_speedy", 0, 0, NULL),
VCLK(mif_pdma0, gate_mif_pdma, "gate_mif_pdma", 0, 0, NULL),
/* sclk */
VCLK(mif_uart_debug, sclk_uart_debug, "sclk_uart_debug", 0, 0, NULL),
VCLK(mif_uart_sensor, sclk_uart_sensor, "sclk_uart_sensor", 0, 0, NULL),
VCLK(mif_spi_rearfrom, sclk_spi_rearfrom, "sclk_spi_rearfrom", 0, 0, NULL),
#ifdef CONFIG_SENSORS_FINGERPRINT
VCLK(mif_spi_ese, sclk_spi_ese, "sclk_spi_ese", 0, 0, "fp-spi-sclk"),
#else
VCLK(mif_spi_ese, sclk_spi_ese, "sclk_spi_ese", 0, 0, NULL),
#endif
VCLK(mif_mmc0, sclk_mmc0, "sclk_mmc0", 0, 0, NULL),
VCLK(mif_mmc2, sclk_mmc2, "sclk_mmc2", 0, 0, NULL),
VCLK(mif_usb20drd_refclk, sclk_usb20drd_refclk, "sclk_usb20drd_refclk", 0, 0, NULL),
VCLK(mif_usi0, sclk_usi0, "sclk_usi0", 0, 0, NULL),
VCLK(mif_usi1, sclk_usi1, "sclk_usi1", 0, 0, NULL),
VCLK(mif_apm, sclk_apm, "sclk_apm", 0, 0, NULL),
VCLK(mif_isp_sensor0, sclk_isp_sensor0, "sclk_isp_sensor0", 0, 0, NULL),
};
static struct init_vclk exynos7570_g3d_vclks[] __initdata = {
VCLK(g3d_sysmmu, gate_g3d_sysmmu, "gate_g3d_sysmmu", 0, 0, NULL),
VCLK(g3d_bcm, gate_g3d_bcm, "gate_g3d_bcm", 0, 0, "gate_g3d_bcm"),
VCLK(g3d_bts, gate_g3d_bts, "gate_g3d_bts", 0, 0, NULL),
VCLK(gate_g3d, gate_g3d_g3d, "gate_g3d_g3d", 0, 0, NULL),
};
static struct init_vclk exynos7570_peri_vclks[] __initdata = {
VCLK(peri_i2c_sensor1, gate_peri_i2c_sensor1, "gate_peri_i2c_sensor1", 0, 0, NULL),
VCLK(peri_i2c_sensor2, gate_peri_i2c_sensor2, "gate_peri_i2c_sensor2", 0, 0, NULL),
VCLK(peri_i2c_tsp, gate_peri_i2c_tsp, "gate_peri_i2c_tsp", 0, 0, NULL),
VCLK(peri_i2c_fuelgauge, gate_peri_i2c_fuelgauge, "gate_peri_i2c_fuelgauge", 0, 0, NULL),
VCLK(peri_i2c_nfc, gate_peri_i2c_nfc, "gate_peri_i2c_nfc", 0, 0, NULL),
VCLK(peri_i2c_muic, gate_peri_i2c_muic, "gate_peri_i2c_muic", 0, 0, NULL),
VCLK(peri_hsi2c_frontsensor, gate_peri_hsi2c_frontsensor, "gate_peri_hsi2c_frontsensor", 0, 0, NULL),
VCLK(peri_hsi2c_rearsensor, gate_peri_hsi2c_rearsensor, "gate_peri_hsi2c_rearsensor", 0, 0, NULL),
VCLK(peri_hsi2c_rearaf, gate_peri_hsi2c_rearaf, "gate_peri_hsi2c_rearaf", 0, 0, NULL),
VCLK(peri_pwm_motor, gate_peri_pwm_motor, "gate_peri_pwm_motor", 0, 0, NULL),
VCLK(peri_sclk_pwm_motor, gate_peri_sclk_pwm_motor, "gate_peri_sclk_pwm_motor", 0, 0, NULL),
VCLK(peri_hsi2c_maincam, gate_peri_hsi2c_maincam, "gate_peri_hsi2c_maincam", 0, 0, NULL),
VCLK(peri_hsi2c_frontcam, gate_peri_hsi2c_frontcam, "gate_peri_hsi2c_frontcam", 0, 0, NULL),
VCLK(peri_gpio_touch, gate_peri_gpio_touch, "gate_peri_gpio_touch", 0, 0, NULL),
VCLK(peri_gpio_top, gate_peri_gpio_top, "gate_peri_gpio_top", 0, 0, NULL),
VCLK(peri_gpio_nfc, gate_peri_gpio_nfc, "gate_peri_gpio_nfc", 0, 0, NULL),
VCLK(peri_gpio_ese, gate_peri_gpio_ese, "gate_peri_gpio_ese", 0, 0, NULL),
VCLK(peri_gpio_alive, gate_peri_gpio_alive, "gate_peri_gpio_alive", 0, 0, NULL),
VCLK(peri_usi0, gate_peri_usi0, "gate_peri_usi0", 0, 0, NULL),
VCLK(peri_usi1, gate_peri_usi1, "gate_peri_usi1", 0, 0, NULL),
VCLK(peri_otp_con_top, gate_peri_otp_con_top, "gate_peri_otp_con_top", 0, 0, NULL),
VCLK(peri_uart_debug, gate_peri_uart_debug, "gate_peri_uart_debug", 0, 0, NULL),
VCLK(peri_uart_sensor, gate_peri_uart_sensor, "gate_peri_uart_sensor", 0, 0, NULL),
#ifdef CONFIG_SENSORS_FINGERPRINT
VCLK(peri_spi_ese, gate_peri_spi_ese, "gate_peri_spi_ese", 0, 0, "fp-spi-pclk"),
#else
VCLK(peri_spi_ese, gate_peri_spi_ese, "gate_peri_spi_ese", 0, 0, NULL),
#endif
VCLK(peri_spi_rearfrom, gate_peri_spi_rearfrom, "gate_peri_spi_rearfrom", 0, 0, NULL),
VCLK(peri_mct, gate_peri_mct, "gate_peri_mct", 0, 0, NULL),
VCLK(peri_wdt_cpucl0, gate_peri_wdt_cpucl0, "gate_peri_wdt_cpucl0", 0, 0, NULL),
VCLK(peri_tmu_cpucl0, gate_peri_tmu_cpucl0, "gate_peri_tmu_cpucl0", 0, 0, NULL),
VCLK(peri_chipid, gate_peri_chipid, "gate_peri_chipid", 0, 0, NULL),
VCLK(peri_rtc_alive, gate_peri_rtc_alive, "gate_peri_rtc_alive", 0, 0, NULL),
VCLK(peri_rtc_top, gate_peri_rtc_top, "gate_peri_rtc_top", 0, 0, NULL),
};
static struct init_vclk exynos7570_fsys_vclks[] __initdata = {
VCLK(fsys_sysmmu, gate_fsys_sysmmu, "gate_fsys_sysmmu", 0, 0, NULL),
VCLK(fsys_bcm, gate_fsys_bcm, "gate_fsys_bcm", 0, 0, "gate_fsys_bcm"),
VCLK(fsys_bts, gate_fsys_bts, "gate_fsys_bts", 0, 0, NULL),
VCLK(fsys_sss, gate_fsys_sss, "gate_fsys_sss", 0, 0, NULL),
VCLK(fsys_rtic, gate_fsys_rtic, "gate_fsys_rtic", 0, 0, NULL),
VCLK(fsys_usb20drd, gate_fsys_usb20drd, "gate_fsys_usb20drd", 0, 0, NULL),
VCLK(fsys_mmc0, gate_fsys_mmc0, "gate_fsys_mmc0", 0, 0, NULL),
VCLK(fsys_mmc2, gate_fsys_mmc2, "gate_fsys_mmc2", 0, 0, NULL),
VCLK(fsys_sclk_mmc0, gate_fsys_sclk_mmc0, "gate_fsys_sclk_mmc0", 0, 0, NULL),
VCLK(fsys_sclk_mmc2, gate_fsys_sclk_mmc2, "gate_fsys_sclk_mmc2", 0, 0, NULL),
VCLK(fsys_usb20drd_phyclock_user, umux_fsys_clkphy_fsys_usb20drd_phyclock_user, \
"umux_fsys_clkphy_fsys_usb20drd_phyclock_user", 0, 0, NULL),
VCLK(wpll_usb, p1_wpll_usb_pll, "p1_wpll_usb_pll", 0, 0, NULL),
};
static struct init_vclk exynos7570_mfcmscl_vclks[] __initdata = {
VCLK(CLK_VCLK_SYSMMU_MFC_MSCL, gate_mfcmscl_sysmmu, "gate_mfcmscl_sysmmu", 0, 0, NULL),
VCLK(mfcmscl_bcm, gate_mfcmscl_bcm, "gate_mfcmscl_bcm", 0, 0, "gate_mfcmscl_bcm"),
VCLK(mfcmscl_bts, gate_mfcmscl_bts, "gate_mfcmscl_bts", 0, 0, NULL),
VCLK(gate_mscl, gate_mfcmscl_mscl, "gate_mfcmscl_mscl", 0, 0, NULL),
VCLK(gate_jpeg, gate_mfcmscl_jpeg, "gate_mfcmscl_jpeg", 0, 0, NULL),
VCLK(gate_mfc, gate_mfcmscl_mfc, "gate_mfcmscl_mfc", 0, 0, NULL),
};
static struct init_vclk exynos7570_dispaud_vclks[] __initdata = {
VCLK(CLK_VCLK_SYSMMU_DISP_AUD, gate_dispaud_sysmmu, "gate_dispaud_sysmmu", 0, 0, NULL),
VCLK(dispaud_bcm, gate_dispaud_bcm, "gate_dispaud_bcm", 0, 0, "gate_dispaud_bcm"),
VCLK(dispaud_bts, gate_dispaud_bts, "gate_dispaud_bts", 0, 0, NULL),
VCLK(dispaud_decon, gate_dispaud_decon, "gate_dispaud_decon", 0, 0, NULL),
VCLK(dispaud_dsim0, gate_dispaud_dsim0, "gate_dispaud_dsim0", 0, 0, NULL),
VCLK(dispaud_mixer, gate_dispaud_mixer, "gate_dispaud_mixer", 0, 0, NULL),
VCLK(dispaud_mi2s_aud, gate_dispaud_mi2s_aud, "gate_dispaud_mi2s_aud", 0, 0, NULL),
VCLK(dispaud_mi2s_amp, gate_dispaud_mi2s_amp, "gate_dispaud_mi2s_amp", 0, 0, NULL),
VCLK(dispaud_mipiphy_txbyteclkhs_user, umux_dispaud_clkphy_dispaud_mipiphy_txbyteclkhs_user, \
"umux_dispaud_clkphy_dispaud_mipiphy_txbyteclkhs_user", 0, 0, NULL),
VCLK(dispaud_mipiphy_rxclkesc0_user, umux_dispaud_clkphy_dispaud_mipiphy_rxclkesc0_user, \
"umux_dispaud_clkphy_dispaud_mipiphy_rxclkesc0_user", 0, 0, NULL),
/* sclk */
VCLK(decon_vclk, sclk_decon_vclk, "sclk_decon_vclk", 0, 0, NULL),
VCLK(decon_vclk_local, sclk_decon_vclk_local, "sclk_decon_vclk_local", 0, 0, NULL),
VCLK(aud_pll, p1_aud_pll, "p1_aud_pll", 0, 0, NULL),
VCLK(mi2s_div, d1_dispaud_mi2s, "d1_dispaud_mi2s", 0, 0, NULL),
VCLK(mixer_div, d1_dispaud_mixer, "d1_dispaud_mixer", 0, 0, NULL),
VCLK(oscclk_fm_52m_div, d1_dispaud_oscclk_fm_52m, "d1_dispaud_oscclk_fm_52m", 0, 0, NULL),
};
static struct init_vclk exynos7570_isp_vclks[] __initdata = {
VCLK(CLK_VCLK_SYSMMU_ISP, gate_isp_sysmmu, "gate_isp_sysmmu", 0, 0, NULL),
VCLK(isp_bcm, gate_isp_bcm, "gate_isp_bcm", 0, 0, "gate_isp_bcm"),
VCLK(isp_bts, gate_isp_bts, "gate_isp_bts", 0, 0, NULL),
VCLK(isp_cam, gate_isp_cam, "gate_isp_cam", 0, 0, NULL),
VCLK(isp_vra, gate_isp_vra, "gate_isp_vra", 0, 0, NULL),
VCLK(isp_s_rxbyteclkhs0_s4_user, umux_isp_clkphy_isp_s_rxbyteclkhs0_s4_user, \
"umux_isp_clkphy_isp_s_rxbyteclkhs0_s4_user", 0, 0, NULL),
};
static struct init_vclk exynos7570_apm_vclks[] __initdata = {
VCLK(gate_apm, gate_apm_apm, "gate_apm_apm", 0, 0, NULL),
};
static struct of_device_id ext_clk_match[] __initdata = {
{ .compatible = "samsung,exynos7570-oscclk", .data = (void *)0, },
};
static struct init_vclk exynos7570_dfs_vclks[] __initdata = {
/* DFS */
VCLK(dfs_mif, dvfs_mif, "dvfs_mif", 0, VCLK_DFS, NULL),
VCLK(dfs_mif_sw, dvfs_mif, "dvfs_mif_sw", 0, VCLK_DFS_SWITCH, NULL),
VCLK(dfs_int, dvfs_int, "dvfs_int", 0, VCLK_DFS, NULL),
VCLK(dfs_cam, dvfs_cam, "dvfs_cam", 0, VCLK_DFS, NULL),
VCLK(dfs_disp, dvfs_disp, "dvfs_disp", 0, VCLK_DFS, NULL),
};
static struct init_vclk exynos7570_clkout_vclks[] __initdata = {
VCLK(oscclk_aud, pxmxdx_oscclk_aud, "pxmxdx_oscclk_aud", 0, 0, NULL),
};
/* register exynos7570 clocks */
void __init exynos7570_clk_init(struct device_node *np)
{
struct samsung_clk_provider *ctx;
void __iomem *reg_base;
if (np) {
reg_base = of_iomap(np, 0);
if (!reg_base)
panic("%s: failed to map registers\n", __func__);
} else {
panic("%s: unable to determine soc\n", __func__);
}
ect_parse_binary_header();
if (cal_init())
pr_err("%s: unable to initialize power cal\n", __func__);
else
pr_info("%s: Exynos power cal initialized\n", __func__);
ctx = samsung_clk_init(np, reg_base, nr_clks);
if (!ctx)
panic("%s: unable to allocate context.\n", __func__);
samsung_register_of_fixed_ext(ctx, exynos7570_fixed_rate_ext_clks,
ARRAY_SIZE(exynos7570_fixed_rate_ext_clks), ext_clk_match);
samsung_register_vclk(ctx, exynos7570_mif_vclks, ARRAY_SIZE(exynos7570_mif_vclks));
samsung_register_vclk(ctx, exynos7570_g3d_vclks, ARRAY_SIZE(exynos7570_g3d_vclks));
samsung_register_vclk(ctx, exynos7570_peri_vclks, ARRAY_SIZE(exynos7570_peri_vclks));
samsung_register_vclk(ctx, exynos7570_fsys_vclks, ARRAY_SIZE(exynos7570_fsys_vclks));
samsung_register_vclk(ctx, exynos7570_mfcmscl_vclks, ARRAY_SIZE(exynos7570_mfcmscl_vclks));
samsung_register_vclk(ctx, exynos7570_dispaud_vclks, ARRAY_SIZE(exynos7570_dispaud_vclks));
samsung_register_vclk(ctx, exynos7570_isp_vclks, ARRAY_SIZE(exynos7570_isp_vclks));
samsung_register_vclk(ctx, exynos7570_apm_vclks, ARRAY_SIZE(exynos7570_apm_vclks));
samsung_register_vclk(ctx, exynos7570_dfs_vclks, ARRAY_SIZE(exynos7570_dfs_vclks));
samsung_register_vclk(ctx, exynos7570_clkout_vclks, ARRAY_SIZE(exynos7570_clkout_vclks));
samsung_clk_of_add_provider(np, ctx);
clk_register_fixed_factor(NULL, "pwm-clock", "gate_peri_sclk_pwm_motor",CLK_SET_RATE_PARENT, 1, 1);
pr_info("Exynos clock initialized\n");
}
CLK_OF_DECLARE(exynos7570_clk, "samsung,exynos7570-clock", exynos7570_clk_init);

View file

@ -0,0 +1,332 @@
/*
* Copyright (c) 2015 Samsung Electronics Co., Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This file contains clocks of Exynos7870.
*/
#include <linux/clk.h>
#include <linux/clkdev.h>
#include <linux/clk-provider.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <dt-bindings/clock/exynos7870.h>
#include "../../soc/samsung/pwrcal/S5E7870/S5E7870-vclk.h"
#include "composite.h"
#if defined(CONFIG_ECT)
#include <soc/samsung/ect_parser.h>
#endif
enum exynos7870_clks {
none,
oscclk = 1,
/* The group of clocks in mfcmscl */
mscl_sysmmu = 10, mfc_sysmmu, mfcmscl_ppmu, mfcmscl_bts, gate_mscl_bi, gate_mscl_poly, gate_jpeg, gate_mfc,
/* The group of clocks in g3d */
g3d_sysmmu = 50, g3d_ppmu, g3d_bts, gate_g3d,
/* The group of clocks related with pwm and mct in peri */
peri_pwm_motor = 100, peri_sclk_pwm_motor, peri_mct,
/* The group of clocks related with i2c in peri */
i2c_sensor1 = 110, i2c_sensor2, i2c_tsp, i2c_touchkey, i2c_fuelgauge, i2c_spkamp, i2c_nfc, i2c_muic, i2c_ifpmic,
/* The group of clocks related with hsi2c in peri */
hsi2c_frontcam = 130, hsi2c_maincam, hsi2c_depthcam, hsi2c_frontsensor, hsi2c_rearaf, hsi2c_rearsensor,
/* The group of clocks related with gpio in peri */
gpio_touch = 150, gpio_top, gpio_nfc, gpio_ese, gpio_alive,
/* The group of clocks related with wdt in peri */
wdt_cpucl0 = 160, wdt_cpucl1,
/* The group of clocks related with uart in peri */
uart_debug = 170, uart_btwififm, uart_sensor,
/* The group of clocks related with tmu in peri */
peri_tmu_g3d = 180, peri_tmu_cpucl1, peri_tmu_cpucl0,
/* The group of clocks related with spi in peri */
peri_spi_sensorhub = 190, peri_spi_voiceprocessor, peri_spi_ese, peri_spi_rearfrom, peri_spi_frontfrom,
/* The group of clocks related with rtc in peri */
peri_rtc_alive = 210, peri_rtc_top,
/* The group of etc clocks in peri */
peri_chipid = 220, peri_otp_con_top,
/* The group of clocks in fsys */
fsys_sysmmu = 300, fsys_ppmu, fsys_bts,
fsys_mmc0 = 310, fsys_mmc1, fsys_mmc2, fsys_sclk_mmc0, fsys_sclk_mmc1, fsys_sclk_mmc2,
fsys_sss = 330, fsys_rtic, fsys_pdma0, fsys_pdma1, fsys_sromc, fsys_usb20drd, fsys_usb20drd_phyclock,
usb_pll = 350,
/* The group of clocks in dispaud */
dispaud_sysmmu = 400, dispaud_ppmu, dispaud_bts,
dispaud_decon = 410, dispaud_dsim0, dispaud_mixer, dispaud_mi2s_aud, dispaud_mi2s_amp,
dispaud_bus = 430, dispaud_decon_int_vclk, dispaud_decon_int_eclk, dispaud_mipiphy_txbyteclkhs, dispaud_mipiphy_rxclkesc0,
decon_vclk = 450, decon_vclk_local, decon_eclk, decon_eclk_local,
disp_pll = 460, aud_pll, d1_i2s, d1_mixer,
/* The group of clocks in isp */
isp_sysmmu = 500, isp_ppmu, isp_bts,
isp_cam = 510, isp_isp, isp_vra, pxmxdx_vra, pxmxdx_cam, pxmxdx_isp,
isp_s_rxbyteclkhs0_s4 = 520, isp_s_rxbyteclkhs0_s4s,
isp_pll = 530,
/* The group of clocks in mif */
mif_adcif = 600, mif_hsi2c_mif, mmc0_sclk, mmc1_sclk, mmc2_sclk,
ufsunipro_sclk = 610, ufsunipro_cfg_sclk, usb20drd_sclk,
uart_sensor_sclk = 620, uart_btwififm_sclk, uart_debug_sclk,
spi_frontfrom_sclk = 630, spi_rearfrom_sclk, spi_ese_sclk, spi_voiceprocessor_sclk, spi_sensorhub_sclk,
isp_sensor0_sclk = 640, isp_sensor1_sclk, isp_sensor2_sclk,
/* number of dfs driver starts from 2000 */
dfs_mif = 2000, dfs_mif_sw, dfs_int, dfs_cam, dfs_disp,
nr_clks,
};
/* fixed rate clocks generated outside the soc */
static struct samsung_fixed_rate exynos7870_fixed_rate_ext_clks[] __initdata = {
FRATE(oscclk, "fin_pll", NULL, CLK_IS_ROOT, 26000000),
};
static struct of_device_id ext_clk_match[] __initdata = {
{ .compatible = "samsung,exynos7870-oscclk", .data = (void *)0, },
};
static struct init_vclk exynos7870_mfcmscl_vclks[] __initdata = {
/* MFC & MSCL ACLK */
VCLK(mscl_sysmmu, gate_mfcmscl_sysmmu_mscl, "gate_mfcmscl_sysmmu_mscl", 0, 0, NULL),
VCLK(mfc_sysmmu, gate_mfcmscl_sysmmu_mfc, "gate_mfcmscl_sysmmu_mfc", 0, 0, NULL),
VCLK(mfcmscl_ppmu, gate_mfcmscl_ppmu, "gate_mfcmscl_ppmu", 0, 0, NULL),
VCLK(mfcmscl_bts, gate_mfcmscl_bts, "gate_mfcmscl_bts", 0, 0, NULL),
VCLK(gate_mscl_bi, gate_mfcmscl_mscl_bi, "gate_mfcmscl_mscl_bi", 0, 0, NULL),
VCLK(gate_mscl_poly, gate_mfcmscl_mscl_poly, "gate_mfcmscl_mscl_poly", 0, 0, NULL),
VCLK(gate_jpeg, gate_mfcmscl_jpeg, "gate_mfcmscl_jpeg", 0, 0, NULL),
VCLK(gate_mfc, gate_mfcmscl_mfc, "gate_mfcmscl_mfc", 0, 0, NULL),
};
static struct init_vclk exynos7870_g3d_vclks[] __initdata = {
/* G3D ACLK */
VCLK(g3d_sysmmu, gate_g3d_sysmmu, "gate_g3d_sysmmu", 0, 0, NULL),
VCLK(g3d_ppmu, gate_g3d_ppmu, "gate_g3d_ppmu", 0, 0, NULL),
VCLK(g3d_bts, gate_g3d_bts, "gate_g3d_bts", 0, 0, "gate_g3d_bts_alias"),
VCLK(gate_g3d, gate_g3d_g3d, "gate_g3d_g3d", 0, 0, "vclk_g3d"),
};
static struct init_vclk exynos7870_peri_vclks[] __initdata = {
/* PERI PWM ACLK & SCLK */
VCLK(peri_pwm_motor, gate_peri_pwm_motor, "gate_peri_pwm_motor", 0, 0, NULL),
VCLK(peri_sclk_pwm_motor, gate_peri_sclk_pwm_motor, "gate_peri_sclk_pwm_motor", 0, 0, NULL),
/* PERI MCT ACLK */
VCLK(peri_mct, gate_peri_mct, "gate_peri_mct", 0, 0, NULL),
/* PERI I2C ACLK */
VCLK(i2c_sensor1, gate_peri_i2c_sensor1, "gate_peri_i2c_sensor1", 0, 0, NULL),
VCLK(i2c_sensor2, gate_peri_i2c_sensor2, "gate_peri_i2c_sensor2", 0, 0, NULL),
VCLK(i2c_tsp, gate_peri_i2c_tsp, "gate_peri_i2c_tsp", 0, 0, NULL),
VCLK(i2c_touchkey, gate_peri_i2c_touchkey, "gate_peri_i2c_touchkey", 0, 0, NULL),
VCLK(i2c_fuelgauge, gate_peri_i2c_fuelgauge, "gate_peri_i2c_fuelgauge", 0, 0, NULL),
VCLK(i2c_spkamp, gate_peri_i2c_spkamp, "gate_peri_i2c_spkamp", 0, 0, NULL),
VCLK(i2c_nfc, gate_peri_i2c_nfc, "gate_peri_i2c_nfc", 0, 0, NULL),
VCLK(i2c_muic, gate_peri_i2c_muic, "gate_peri_i2c_muic", 0, 0, NULL),
VCLK(i2c_ifpmic, gate_peri_i2c_ifpmic, "gate_peri_i2c_ifpmic", 0, 0, NULL),
/* PERI HSI2C ACLK */
VCLK(hsi2c_frontcam, gate_peri_hsi2c_frontcam, "gate_peri_hsi2c_frontcam", 0, 0, NULL),
VCLK(hsi2c_maincam, gate_peri_hsi2c_maincam, "gate_peri_hsi2c_maincam", 0, 0, NULL),
VCLK(hsi2c_depthcam, gate_peri_hsi2c_depthcam, "gate_peri_hsi2c_depthcam", 0, 0, NULL),
VCLK(hsi2c_frontsensor, gate_peri_hsi2c_frontsensor, "gate_peri_hsi2c_frontsensor", 0, 0, NULL),
VCLK(hsi2c_rearaf,gate_peri_hsi2c_rearaf, "gate_peri_hsi2c_rearaf", 0, 0, NULL),
VCLK(hsi2c_rearsensor, gate_peri_hsi2c_rearsensor, "gate_peri_hsi2c_rearsensor", 0, 0, NULL),
/* PERI GPIO ACLK */
VCLK(gpio_touch, gate_peri_gpio_touch, "gate_peri_gpio_touch", 0, 0, NULL),
VCLK(gpio_top, gate_peri_gpio_top, "gate_peri_gpio_top", 0, 0, NULL),
VCLK(gpio_nfc, gate_peri_gpio_nfc, "gate_peri_gpio_nfc", 0, 0, NULL),
VCLK(gpio_ese, gate_peri_gpio_ese, "gate_peri_gpio_ese", 0, 0, NULL),
VCLK(gpio_alive, gate_peri_gpio_alive, "gate_peri_gpio_alive", 0, 0, NULL),
/* PERI WDT ACLK */
VCLK(wdt_cpucl0, gate_peri_wdt_cpucl0, "gate_peri_wdt_cpucl0", 0, 0, NULL),
VCLK(wdt_cpucl1, gate_peri_wdt_cpucl1, "gate_peri_wdt_cpucl1", 0, 0, NULL),
/* PERI UART ACLK */
VCLK(uart_debug, gate_peri_uart_debug, "gate_peri_uart_debug", 0, 0, "console-pclk0"),
VCLK(uart_btwififm, gate_peri_uart_btwififm, "gate_peri_uart_btwififm", 0, 0, NULL),
VCLK(uart_sensor, gate_peri_uart_sensor, "gate_peri_uart_sensor", 0, 0, NULL),
/* PERI TMU ACLK */
VCLK(peri_tmu_g3d, gate_peri_tmu_g3d, "gate_peri_tmu_g3d", 0, 0, NULL),
VCLK(peri_tmu_cpucl1, gate_peri_tmu_cpucl1, "gate_peri_tmu_cpucl1", 0, 0, NULL),
VCLK(peri_tmu_cpucl0, gate_peri_tmu_cpucl0, "gate_peri_tmu_cpucl0", 0, 0, NULL),
/* PERI SPI ACLK */
VCLK(peri_spi_sensorhub, gate_peri_spi_sensorhub, "gate_peri_spi_sensorhub", 0, 0, NULL),
VCLK(peri_spi_voiceprocessor, gate_peri_spi_voiceprocessor, "gate_peri_spi_voiceprocessor", 0, 0, NULL),
VCLK(peri_spi_ese, gate_peri_spi_ese, "gate_peri_spi_ese", 0, 0, NULL),
VCLK(peri_spi_rearfrom, gate_peri_spi_rearfrom, "gate_peri_spi_rearfrom", 0, 0, NULL),
VCLK(peri_spi_frontfrom, gate_peri_spi_frontfrom, "gate_peri_spi_frontfrom", 0, 0, NULL),
/* PERI RTC ACLK */
VCLK(peri_rtc_alive, gate_peri_rtc_alive, "gate_peri_rtc_alive", 0, 0, NULL),
VCLK(peri_rtc_top, gate_peri_rtc_top, "gate_peri_rtc_top", 0, 0, NULL),
/* PERI ETC ACLK */
VCLK(peri_chipid, gate_peri_chipid, "gate_peri_chipid", 0, 0, NULL),
VCLK(peri_otp_con_top, gate_peri_otp_con_top, "gate_peri_otp_con_top", 0, 0, NULL),
};
static struct init_vclk exynos7870_fsys_vclks[] __initdata = {
/* FSYS COMMON*/
VCLK(fsys_sysmmu, gate_fsys_sysmmu, "gate_fsys_sysmmu", 0, 0, NULL),
VCLK(fsys_ppmu, gate_fsys_ppmu, "gate_fsys_ppmu", 0, 0, NULL),
VCLK(fsys_bts, gate_fsys_bts, "gate_fsys_bts", 0, 0, NULL),
VCLK(fsys_usb20drd, gate_fsys_usb20drd, "gate_fsys_usb20drd", 0, 0, NULL),
VCLK(fsys_mmc0, gate_fsys_mmc0, "gate_fsys_mmc0", 0, 0, NULL),
VCLK(fsys_mmc1, gate_fsys_mmc1, "gate_fsys_mmc1", 0, 0, NULL),
VCLK(fsys_mmc2, gate_fsys_mmc2, "gate_fsys_mmc2", 0, 0, NULL),
VCLK(fsys_sclk_mmc0, gate_fsys_sclk_mmc0, "gate_fsys_sclk_mmc0", 0, 0, NULL),
VCLK(fsys_sclk_mmc1, gate_fsys_sclk_mmc1, "gate_fsys_sclk_mmc1", 0, 0, NULL),
VCLK(fsys_sclk_mmc2, gate_fsys_sclk_mmc2, "gate_fsys_sclk_mmc2", 0, 0, NULL),
VCLK(fsys_sss, gate_fsys_sss, "gate_fsys_sss", 0, 0, NULL),
VCLK(fsys_rtic, gate_fsys_rtic, "gate_fsys_rtic", 0, 0, NULL),
VCLK(fsys_pdma0, gate_fsys_pdma0, "gate_fsys_pdma0", 0, 0, NULL),
VCLK(fsys_pdma1, gate_fsys_pdma1, "gate_fsys_pdma1", 0, 0, NULL),
VCLK(fsys_sromc, gate_fsys_sromc, "gate_fsys_sromc", 0, 0, NULL),
VCLK(fsys_usb20drd_phyclock, umux_fsys_clkphy_fsys_usb20drd_phyclock_user, "umux_fsys_clkphy_fsys_usb20drd_phyclock_user", 0, 0, NULL),
VCLK(usb_pll, p1_usb_pll, "p1_usb_pll", 0, 0, NULL),
};
static struct init_vclk exynos7870_dispaud_vclks[] __initdata = {
/* DISPAUD ACLK */
VCLK(dispaud_sysmmu, gate_dispaud_sysmmu, "gate_dispaud_sysmmu", 0, 0, NULL),
VCLK(dispaud_ppmu, gate_dispaud_ppmu, "gate_dispaud_ppmu", 0, 0, NULL),
VCLK(dispaud_bts, gate_dispaud_bts, "gate_dispaud_bts", 0, 0, NULL),
VCLK(dispaud_decon, gate_dispaud_decon, "gate_dispaud_decon", 0, 0, NULL),
VCLK(dispaud_dsim0, gate_dispaud_dsim0, "gate_dispaud_dsim0", 0, 0, NULL),
VCLK(dispaud_mixer, gate_dispaud_mixer, "gate_dispaud_mixer", 0, 0, NULL),
VCLK(dispaud_mi2s_aud, gate_dispaud_mi2s_aud, "gate_dispaud_mi2s_aud", 0, 0, NULL),
VCLK(dispaud_mi2s_amp, gate_dispaud_mi2s_amp, "gate_dispaud_mi2s_amp", 0, 0, NULL),
/*
VCLK(dispaud_bus, umux_dispaud_clkcmu_dispaud_bus_user, "umux_dispaud_clkcmu_dispaud_bus_user", 0, 0, NULL),
VCLK(dispaud_decon_int_vclk, umux_dispaud_clkcmu_dispaud_decon_int_vclk_user, "umux_dispaud_clkcmu_dispaud_decon_int_vclk_user", 0, 0, NULL),
VCLK(dispaud_decon_int_eclk, umux_dispaud_clkcmu_dispaud_decon_int_eclk_user, "umux_dispaud_clkcmu_dispaud_decon_int_eclk_user", 0, 0, NULL),
*/
VCLK(dispaud_mipiphy_txbyteclkhs, umux_dispaud_clkphy_dispaud_mipiphy_txbyteclkhs_user, "umux_dispaud_clkphy_dispaud_mipiphy_txbyteclkhs_user", 0, 0, NULL),
VCLK(dispaud_mipiphy_rxclkesc0, umux_dispaud_clkphy_dispaud_mipiphy_rxclkesc0_user, "umux_dispaud_clkphy_dispaud_mipiphy_rxclkesc0_user", 0, 0, NULL),
/* DISPAUD SCLK */
VCLK(decon_vclk, sclk_decon_vclk, "sclk_decon_vclk", 0, 0, NULL),
VCLK(decon_vclk_local, sclk_decon_vclk_local, "sclk_decon_vclk_local", 0, 0, NULL),
VCLK(decon_eclk, sclk_decon_eclk, "sclk_decon_eclk", 0, 0, NULL),
VCLK(decon_eclk_local, sclk_decon_eclk_local, "sclk_decon_eclk_local", 0, 0, NULL),
/* DISPAUD PLL */
VCLK(disp_pll, p1_disp_pll, "p1_disp_pll", 0, 0, NULL),
VCLK(aud_pll, p1_aud_pll, "p1_aud_pll", 0, 0, NULL),
VCLK(d1_i2s, d1_dispaud_mi2s, "d1_dispaud_mi2s", 0, 0, NULL),
VCLK(d1_mixer, d1_dispaud_mixer, "d1_dispaud_mixer", 0, 0, NULL),
};
static struct init_vclk exynos7870_isp_vclks[] __initdata = {
VCLK(isp_sysmmu, gate_isp_sysmmu, "gate_isp_sysmmu", 0, 0, NULL),
VCLK(isp_ppmu, gate_isp_ppmu, "gate_isp_ppmu", 0, 0, NULL),
VCLK(isp_bts, gate_isp_bts, "gate_isp_bts", 0, 0, NULL),
VCLK(isp_cam, gate_isp_cam, "gate_isp_cam", 0, 0, NULL),
VCLK(isp_isp, gate_isp_isp, "gate_isp_isp", 0, 0, NULL),
VCLK(isp_vra, gate_isp_vra, "gate_isp_vra", 0, 0, NULL),
VCLK(pxmxdx_vra, pxmxdx_isp_vra, "pxmxdx_isp_vra", 0, 0, NULL),
VCLK(pxmxdx_cam, pxmxdx_isp_cam, "pxmxdx_isp_cam", 0, 0, NULL),
VCLK(pxmxdx_isp, pxmxdx_isp_isp, "pxmxdx_isp_isp", 0, 0, NULL),
VCLK(isp_s_rxbyteclkhs0_s4, umux_isp_clkphy_isp_s_rxbyteclkhs0_s4_user, "umux_isp_clkphy_isp_s_rxbyteclkhs0_s4_user", 0, 0, NULL),
VCLK(isp_s_rxbyteclkhs0_s4s, umux_isp_clkphy_isp_s_rxbyteclkhs0_s4s_user, "umux_isp_clkphy_isp_s_rxbyteclkhs0_s4s_user", 0, 0, NULL),
VCLK(isp_pll, p1_isp_pll, "p1_isp_pll", 0, 0, NULL),
};
static struct init_vclk exynos7870_mif_vclks[] __initdata = {
VCLK(mif_adcif, gate_mif_adcif, "gate_mif_adcif", 0, 0, NULL),
VCLK(mif_hsi2c_mif, gate_mif_hsi2c_mif, "gate_mif_hsi2c_mif", 0, 0, NULL),
VCLK(mmc0_sclk, sclk_mmc0, "sclk_mmc0", 0, 0, NULL),
VCLK(mmc1_sclk, sclk_mmc1, "sclk_mmc1", 0, 0, NULL),
VCLK(mmc2_sclk, sclk_mmc2, "sclk_mmc2", 0, 0, NULL),
/*
VCLK(ufsunipro_sclk, sclk_ufsunipro, "sclk_ufsunipro", 0, 0, NULL),
VCLK(ufsunipro_cfg_sclk, sclk_ufsunipro_cfg, "sclk_ufsunipro_cfg", 0, 0, NULL),
*/
VCLK(usb20drd_sclk, sclk_usb20drd, "sclk_usb20drd" , 0, 0, NULL),
VCLK(uart_sensor_sclk, sclk_uart_sensor, "sclk_uart_sensor", 0, 0, "console-sclk0"),
VCLK(uart_btwififm_sclk, sclk_uart_btwififm, "sclk_uart_btwififm", 0, 0, NULL),
VCLK(uart_debug_sclk, sclk_uart_debug, "sclk_uart_debug", 0, 0, NULL),
VCLK(spi_frontfrom_sclk, sclk_spi_frontfrom, "sclk_spi_frontfrom", 0, 0, NULL),
VCLK(spi_rearfrom_sclk, sclk_spi_rearfrom, "sclk_spi_rearfrom", 0, 0, NULL),
VCLK(spi_ese_sclk, sclk_spi_ese, "sclk_spi_ese", 0, 0, NULL),
VCLK(spi_voiceprocessor_sclk, sclk_spi_voiceprocessor, "sclk_spi_voiceprocessor", 0, 0, NULL),
VCLK(spi_sensorhub_sclk, sclk_spi_sensorhub, "sclk_spi_sensorhub", 0, 0, NULL),
VCLK(isp_sensor0_sclk, sclk_isp_sensor0, "sclk_isp_sensor0", 0, 0, NULL),
VCLK(isp_sensor1_sclk, sclk_isp_sensor1, "sclk_isp_sensor1", 0, 0, NULL),
VCLK(isp_sensor2_sclk, sclk_isp_sensor2, "sclk_isp_sensor2", 0, 0, NULL),
};
static struct init_vclk exynos7870_dfs_vclks[] __initdata = {
/* DFS */
VCLK(dfs_mif, dvfs_mif, "dvfs_mif", 0, VCLK_DFS, NULL),
VCLK(dfs_mif_sw, dvfs_mif, "dvfs_mif_sw", 0, VCLK_DFS_SWITCH, NULL),
VCLK(dfs_int, dvfs_int, "dvfs_int", 0, VCLK_DFS, NULL),
VCLK(dfs_cam, dvfs_cam, "dvfs_cam", 0, VCLK_DFS, NULL),
VCLK(dfs_disp, dvfs_disp, "dvfs_disp", 0, VCLK_DFS, NULL),
};
/* register exynos7870 clocks */
void __init exynos7870_clk_init(struct device_node *np)
{
struct samsung_clk_provider *ctx;
void __iomem *reg_base;
int ret;
if (np) {
reg_base = of_iomap(np, 0);
if (!reg_base)
panic("%s: failed to map registers\n", __func__);
} else {
panic("%s: unable to determine soc\n", __func__);
}
#if defined(CONFIG_ECT)
ect_parse_binary_header();
#endif
ret = cal_init();
if (ret)
pr_err("%s: unable to initialize power cal\n", __func__);
ctx = samsung_clk_init(np, reg_base, nr_clks);
if (!ctx)
panic("%s: unable to allocate context.\n", __func__);
samsung_register_of_fixed_ext(ctx, exynos7870_fixed_rate_ext_clks,
ARRAY_SIZE(exynos7870_fixed_rate_ext_clks), ext_clk_match);
/* Regist clock local IP */
samsung_register_vclk(ctx, exynos7870_mfcmscl_vclks, ARRAY_SIZE(exynos7870_mfcmscl_vclks));
samsung_register_vclk(ctx, exynos7870_g3d_vclks, ARRAY_SIZE(exynos7870_g3d_vclks));
samsung_register_vclk(ctx, exynos7870_peri_vclks, ARRAY_SIZE(exynos7870_peri_vclks));
samsung_register_vclk(ctx, exynos7870_fsys_vclks, ARRAY_SIZE(exynos7870_fsys_vclks));
samsung_register_vclk(ctx, exynos7870_dispaud_vclks, ARRAY_SIZE(exynos7870_dispaud_vclks));
samsung_register_vclk(ctx, exynos7870_isp_vclks, ARRAY_SIZE(exynos7870_isp_vclks));
samsung_register_vclk(ctx, exynos7870_mif_vclks, ARRAY_SIZE(exynos7870_mif_vclks));
samsung_register_vclk(ctx, exynos7870_dfs_vclks, ARRAY_SIZE(exynos7870_dfs_vclks));
samsung_clk_of_add_provider(np, ctx);
clk_register_fixed_factor(NULL, "pwm-clock", "gate_peri_sclk_pwm_motor", CLK_SET_RATE_PARENT, 1, 1);
pr_info("EXYNOS7870: Clock setup completed\n");
}
CLK_OF_DECLARE(exynos7870_clks, "samsung,exynos7870-clock", exynos7870_clk_init);

View file

@ -0,0 +1,544 @@
/*
* Copyright (c) 2015 Samsung Electronics Co., Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This file contains clocks of Exynos8890.
*/
#include <linux/clk.h>
#include <linux/clkdev.h>
#include <linux/clk-provider.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <dt-bindings/clock/exynos8890.h>
#include "../../soc/samsung/pwrcal/S5E8890/S5E8890-vclk.h"
#include "composite.h"
#if defined(CONFIG_ECT)
#include <soc/samsung/ect_parser.h>
#endif
enum exynos8890_clks {
none,
oscclk = 1,
/* number for mfc driver starts from 10 */
mfc_hpm = 10, mfc_mfc, mfc_ppmu,
/* number for mscl driver starts from 50 */
mscl_mscl0 = 50, mscl_jpeg, mscl_mscl1, mscl_g2d, mscl_ppmu, mscl_bts,
/* number for imem driver starts from 100 */
gate_apm = 100, gate_sss, gate_gic400, gate_rtic, gate_mc, gate_intmem, gate_alv, gate_ppmu,
/* number for peris driver starts from 150 */
peris_sfr = 150, peris_hpm, peris_mct, wdt_mngs, wdt_apollo, sysreg_peris, monocnt_apbif, rtc_apbif, top_rtc, otp_con_top, peris_chipid, peris_tmu, peris_sysreg, peris_monocnt,
/* number for peric0 driver starts from 200 */
gate_hsi2c0 = 200, gate_hsi2c1, gate_hsi2c4, gate_hsi2c5, gate_hsi2c9, gate_hsi2c10, gate_hsi2c11, puart0, suart0, gate_adcif, gate_pwm, gate_sclk_pwm,
/* number for peric1 driver starts from 250 */
gate_hsi2c2 = 250, gate_hsi2c3, gate_hsi2c6, gate_hsi2c7, gate_hsi2c8, gate_hsi2c12, gate_hsi2c13, gate_hsi2c14,
gate_uart1, gate_uart2, gate_uart3, gate_uart4, gate_uart5, suart1, suart2, suart3, suart4, suart5,
gate_spi0, gate_spi1, gate_spi2, gate_spi3, gate_spi4, gate_spi5, gate_spi6, gate_spi7,
sclk_peric1_spi0, sclk_peric1_spi1, sclk_peric1_spi2, sclk_peric1_spi3, sclk_peric1_spi4, sclk_peric1_spi5, sclk_peric1_spi6, sclk_peric1_spi7,
gate_gpio_nfc, gate_gpio_touch, gate_gpio_fp, gate_gpio_ese, promise_int, promise_disp, ap2cp_mif_pll_out, gate_i2s1, gate_pcm1, gate_spdif,
/* number for isp0 driver starts from 400 */
gate_fimc_isp0 = 400, gate_fimc_tpu, isp0, isp0_tpu, isp0_trex, isp0_ppmu, isp0_bts,
/* number for isp1 driver starts from 450 */
gate_fimc_isp1 = 450, isp1, isp1_ppmu, isp1_bts,
/* number for isp sensor driver starts from 500 */
isp_sensor0 = 500, isp_sensor1, isp_sensor2, isp_sensor3,
/* number for cam0 driver starts from 550 */
gate_csis0 = 550, gate_csis1, gate_fimc_bns, fimc_3aa0, fimc_3aa1, cam0_hpm, pxmxdx_csis0, pxmxdx_csis1, pxmxdx_csis2, pxmxdx_csis3,
pxmxdx_3aa0, pxmxdx_3aa1, pxmxdx_trex, hs0_csis0_rx_byte, hs1_csis0_rx_byte, hs2_csis0_rx_byte, hs3_csis0_rx_byte, hs0_csis1_rx_byte, hs1_csis1_rx_byte, cam0_ppmu, cam0_bts,
/* number for cam1 driver starts from 600 */
gate_isp_cpu = 600, gate_csis2, gate_csis3, gate_fimc_vra, gate_mc_scaler, gate_i2c0_isp, gate_i2c1_isp, gate_i2c2_isp, gate_i2c3_isp, gate_wdt_isp,
gate_mcuctl_isp, gate_uart_isp, gate_pdma_isp, gate_pwm_isp, gate_spi0_isp, gate_spi1_isp, isp_spi0, isp_spi1, isp_uart, gate_sclk_pwm_isp,
gate_sclk_uart_isp, cam1_arm, cam1_vra, cam1_trex, cam1_bus, cam1_peri, cam1_csis2, cam1_csis3, cam1_scl, cam1_phy0_csis2, cam1_phy1_csis2,
cam1_phy2_csis2, cam1_phy3_csis2, cam1_phy0_csis3, cam1_ppmu, cam1_bts,
/* number for audio driver starts from 650 */
gate_mi2s = 650, gate_pcm, gate_slimbus, gate_sclk_mi2s, d1_sclk_i2s, gate_sclk_pcm, d1_sclk_pcm, gate_sclk_slimbus, sclk_slimbus, sclk_cp_i2s,
sclk_asrc, aud_pll, aud_cp, aud_lpass, aud_dma, aud_ppmu, aud_bts,
/* number for fsys0 driver starts from 700 */
gate_usbdrd30 = 700, gate_usbhost20, usbdrd30 = 703, sclk_fsys0_mmc0, ufsunipro20, phy24m, ufsunipro_cfg, gate_udrd30_phyclock, gate_udrd30_pipe, gate_ufs_tx0,
gate_ufs_rx0, usbhost20_phyclock, usbhost20phy_ref = 715, fsys_200 = 719, fsys0_etr_usb, gate_mmc, gate_pdma0, gate_pdmas, gate_ufs_linkemedded,
/* number for fsys1 driver starts from 750 */
gate_ufs20_sdcard = 750, fsys1_hpm, fsys1_sclk_mmc2, ufsunipro20_sdcard, pcie_phy, sclk_ufsunipro_sdcard, ufs_link_sdcard_tx0, ufs_link_sdcard_rx0,
pcie_wifi0_tx0, pcie_wifi0_rx0, pcie_wifi1_tx0, pcie_wifi1_rx0, wifi0_dig_refclk, wifi1_dig_refclk, gate_mmc2 =767, gate_sromc, gate_pciewifi0,
gate_pciewifi1, fsys1_ppmu, fsys1_bts,
/* number for g3d driver starts from 800 */
gate_g3d = 800, gate_g3d_iram, g3d_bts, g3d_ppmu,
/* number for disp0 driver starts from 850 */
gate_decon0 = 850, gate_dsim0, gate_dsim1, gate_dsim2, gate_hdmi, gate_dp, gate_hpm_apbif_disp0, decon0_eclk0, decon0_vclk0, decon0_vclk1,
decon0_eclk0_local, decon0_vclk0_local, decon0_vclk1_local, hdmi_audio, disp_pll,
mipidphy0_rxclkesc0, mipidphy0_bitclkdiv8, mipidphy1_rxclkesc0, mipidphy1_bitclkdiv8, mipidphy2_rxclkesc0, mipidphy2_bitclkdiv8,
dpphy_ch0_txd, dpphy_ch1_txd, dpphy_ch2_txd, dpphy_ch3_txd, dptx_phy_i_ref_clk_24m,
mipi_dphy_m1s0, mipi_dphy_m4s0, mipi_dphy_m4s4, phyclk_hdmiphy_tmds_20b, phyclk_hdmiphy_pixel, mipidphy0_bitclkdiv2_user,
mipidphy1_bitclkdiv2_user, mipidphy2_bitclkdiv2_user,
/* number for disp1 driver starts from 900 */
gate_decon1 = 900, gate_hpmdisp1, decon1_eclk0, decon1_eclk1, decon1_eclk0_local, decon1_eclk1_local,
disp1_phyclk_mipidphy0_bitclkdiv2_user, disp1_phyclk_mipidphy1_bitclkdiv2_user,
disp1_phyclk_mipidphy2_bitclkdiv2_user, disp1_phyclk_disp1_hdmiphy_pixel_clko_user, disp1_ppmu, disp1_bts,
/* number for ccore driver starts from 950 */
ccore_i2c = 950,
/* number for clkout port starts from 1000 */
oscclk_nfc = 1000, oscclk_aud,
/* clk id for sysmmu: 1100 ~ 1149
* NOTE: clock IDs of sysmmus are defined in
* include/dt-bindings/clock/exynos8890.h
*/
sysmmu_last = 1149,
nr_clks,
};
static struct samsung_fixed_rate exynos8890_fixed_rate_ext_clks[] __initdata = {
FRATE(oscclk, "fin_pll", NULL, CLK_IS_ROOT, 0),
};
static struct of_device_id ext_clk_match[] __initdata = {
{ .compatible = "samsung,exynos8890-oscclk", .data = (void *)0, },
};
static struct init_vclk exynos8890_clkout_vclks[] __initdata = {
VCLK(oscclk_nfc, pxmxdx_oscclk_nfc, "pxmxdx_oscclk_nfc", 0, 0, NULL),
VCLK(oscclk_aud, pxmxdx_oscclk_aud, "pxmxdx_oscclk_aud", 0, 0, NULL),
};
static struct init_vclk exynos8890_ccore_vclks[] __initdata = {
VCLK(ccore_i2c, gate_ccore_i2c, "gate_ccore_i2c", 0, 0, NULL),
};
static struct init_vclk exynos8890_mfc_vclks[] __initdata = {
/* MFC */
VCLK(mfc_hpm, gate_mfc_hpm, "mfc_hpm", 0, 0, NULL),
VCLK(mfc_mfc, gate_mfc_mfc, "mfc_mfc", 0, 0, NULL),
VCLK(CLK_VCLK_SYSMMU_MFC, gate_mfc_sysmmu, "mfc_sysmmu", 0, 0, NULL),
VCLK(mfc_ppmu, gate_mfc_ppmu, "mfc_ppmu", 0, 0, NULL),
};
static struct init_vclk exynos8890_mscl_vclks[] __initdata = {
/* MSCL */
VCLK(mscl_mscl0, gate_mscl_mscl0, "gate_mscl_mscl0", 0, 0, NULL),
VCLK(mscl_jpeg, gate_mscl_jpeg, "gate_mscl_jpeg", 0, 0, NULL),
VCLK(mscl_mscl1, gate_mscl_mscl1, "gate_mscl_mscl1", 0, 0, NULL),
VCLK(mscl_g2d, gate_mscl_g2d, "gate_mscl_g2d", 0, 0, NULL),
VCLK(CLK_VCLK_SYSMMU_MSCL, gate_mscl_sysmmu, "gate_mscl_sysmmu", 0, 0, NULL),
VCLK(mscl_ppmu, gate_mscl_ppmu, "gate_mscl_ppmu", 0, 0, NULL),
VCLK(mscl_bts, gate_mscl_bts, "gate_mscl_bts", 0, 0, NULL),
};
static struct init_vclk exynos8890_imem_vclks[] __initdata = {
/* IMEM */
VCLK(gate_apm, gate_imem_apm, "gate_imem_apm", 0, 0, NULL),
VCLK(gate_sss, gate_imem_sss, "gate_imem_sss", 0, 0, NULL),
VCLK(gate_gic400, gate_imem_gic400, "gate_imem_gic400", 0, 0, NULL),
VCLK(gate_rtic, gate_imem_rtic, "gate_imem_rtic", 0, 0, NULL),
VCLK(gate_mc, gate_imem_mc, "gate_imem_mc", 0, 0, NULL),
VCLK(gate_intmem, gate_imem_intmem, "gate_imem_intmem", 0, 0, NULL),
VCLK(gate_alv, gate_imem_intmem_alv, "gate_imem_intmem_alv", 0, 0, NULL),
VCLK(gate_ppmu, gate_imem_ppmu, "gate_imem_ppmu", 0, 0, NULL),
};
static struct init_vclk exynos8890_peris_vclks[] __initdata = {
/* PERIS */
VCLK(peris_sfr, gate_peris_sfr_apbif_hdmi_cec, "gate_peris_sfr_apbif_hdmi_cec", 0, 0, NULL),
VCLK(peris_hpm, gate_peris_hpm, "gate_peris_hpm", 0, 0, NULL),
VCLK(peris_mct, gate_peris_mct, "gate_peris_mct", 0, 0, NULL),
VCLK(wdt_mngs, gate_peris_wdt_mngs, "gate_peris_wdt_mngs", 0, 0, NULL),
VCLK(wdt_apollo, gate_peris_wdt_apollo, "gate_peris_wdt_apollo", 0, 0, NULL),
VCLK(rtc_apbif, gate_peris_rtc_apbif, "gate_peris_rtc_apbif", 0, 0, NULL),
VCLK(top_rtc, gate_peris_top_rtc, "gate_peris_top_rtc", 0, 0, NULL),
VCLK(otp_con_top, gate_peris_otp_con_top, "gate_peris_otp_con_top", 0, 0, NULL),
VCLK(peris_chipid, gate_peris_chipid, "gate_peris_chipid", 0, 0, NULL),
VCLK(peris_tmu, gate_peris_tmu, "gate_peris_tmu", 0, 0, NULL),
VCLK(peris_sysreg, gate_peris_sysreg_peris, "gate_peris_sysreg_peris", 0, 0, NULL),
VCLK(peris_monocnt, gate_peris_monocnt_apbif, "gate_peris_monocnt_apbif", 0, 0, NULL),
};
static struct init_vclk exynos8890_peric0_vclks[] __initdata = {
/* PERIC0 */
VCLK(gate_hsi2c0, gate_peric0_hsi2c0, "gate_peric0_hsi2c0", 0, 0, NULL),
VCLK(gate_hsi2c1, gate_peric0_hsi2c1, "gate_peric0_hsi2c1", 0, 0, NULL),
VCLK(gate_hsi2c4, gate_peric0_hsi2c4, "gate_peric0_hsi2c4", 0, 0, NULL),
VCLK(gate_hsi2c5, gate_peric0_hsi2c5, "gate_peric0_hsi2c5", 0, 0, NULL),
VCLK(gate_hsi2c9, gate_peric0_hsi2c9, "gate_peric0_hsi2c9", 0, 0, NULL),
VCLK(gate_hsi2c10, gate_peric0_hsi2c10, "gate_peric0_hsi2c10", 0, 0, NULL),
VCLK(gate_hsi2c11, gate_peric0_hsi2c11, "gate_peric0_hsi2c11", 0, 0, NULL),
VCLK(puart0, gate_peric0_uart0, "gate_peric0_uart0", 0, 0, "console-pclk0"),
VCLK(suart0, sclk_uart0, "sclk_uart0", 0, 0, "console-sclk0"),
VCLK(gate_adcif, gate_peric0_adcif, "gate_peric0_adcif", 0, 0, NULL),
VCLK(gate_pwm, gate_peric0_pwm, "gate_peric0_pwm", 0, 0, NULL),
VCLK(gate_sclk_pwm, gate_peric0_sclk_pwm, "gate_peric0_sclk_pwm", 0, 0, NULL),
};
static struct init_vclk exynos8890_peric1_vclks[] __initdata = {
/* PERIC1 HSI2C */
VCLK(gate_hsi2c2, gate_peric1_hsi2c2, "gate_hsi2c2", 0, 0, NULL),
VCLK(gate_hsi2c3, gate_peric1_hsi2c3, "gate_hsi2c3", 0, 0, NULL),
VCLK(gate_hsi2c6, gate_peric1_hsi2c6, "gate_hsi2c6", 0, 0, NULL),
VCLK(gate_hsi2c7, gate_peric1_hsi2c7, "gate_hsi2c7", 0, 0, NULL),
VCLK(gate_hsi2c8, gate_peric1_hsi2c8, "gate_hsi2c8", 0, 0, NULL),
VCLK(gate_hsi2c12, gate_peric1_hsi2c12, "gate_hsi2c12", 0, 0, NULL),
VCLK(gate_hsi2c13, gate_peric1_hsi2c13, "gate_hsi2c13", 0, 0, NULL),
VCLK(gate_hsi2c14, gate_peric1_hsi2c14, "gate_hsi2c14", 0, 0, NULL),
/* PERIC1 UART0~5 */
VCLK(gate_uart1, gate_peric1_uart1, "gate_uart1", 0, 0, "console-pclk1"),
VCLK(gate_uart2, gate_peric1_uart2, "gate_uart2", 0, 0, "console-pclk2"),
VCLK(gate_uart3, gate_peric1_uart3, "gate_uart3", 0, 0, "console-pclk3"),
VCLK(gate_uart4, gate_peric1_uart4, "gate_uart4", 0, 0, "console-pclk4"),
VCLK(gate_uart5, gate_peric1_uart5, "gate_uart5", 0, 0, "console-pclk5"),
VCLK(suart1, sclk_uart1, "sclk_uart1", 0, 0, "console-sclk1"),
VCLK(suart2, sclk_uart2, "sclk_uart2", 0, 0, "console-sclk2"),
VCLK(suart3, sclk_uart3, "sclk_uart3", 0, 0, "console-sclk3"),
VCLK(suart4, sclk_uart4, "sclk_uart4", 0, 0, "console-sclk4"),
VCLK(suart5, sclk_uart5, "sclk_uart5", 0, 0, "console-sclk5"),
/* PERIC1 SPI0~7 */
VCLK(gate_spi0, gate_peric1_spi0, "gate_spi0", 0, 0, NULL),
VCLK(gate_spi1, gate_peric1_spi1, "gate_spi1", 0, 0, NULL),
VCLK(gate_spi2, gate_peric1_spi2, "gate_spi2", 0, 0, NULL),
VCLK(gate_spi3, gate_peric1_spi3, "gate_spi3", 0, 0, NULL),
VCLK(gate_spi4, gate_peric1_spi4, "gate_spi4", 0, 0, NULL),
VCLK(gate_spi5, gate_peric1_spi5, "gate_spi5", 0, 0, NULL),
VCLK(gate_spi6, gate_peric1_spi6, "gate_spi6", 0, 0, NULL),
VCLK(gate_spi7, gate_peric1_spi7, "gate_spi7", 0, 0, NULL),
VCLK(sclk_peric1_spi0, sclk_spi0, "sclk_spi0", 0, 0, NULL),
VCLK(sclk_peric1_spi1, sclk_spi1, "sclk_spi1", 0, 0, NULL),
VCLK(sclk_peric1_spi2, sclk_spi2, "sclk_spi2", 0, 0, NULL),
VCLK(sclk_peric1_spi3, sclk_spi3, "sclk_spi3", 0, 0, NULL),
VCLK(sclk_peric1_spi4, sclk_spi4, "sclk_spi4", 0, 0, NULL),
VCLK(sclk_peric1_spi5, sclk_spi5, "sclk_spi5", 0, 0, NULL),
VCLK(sclk_peric1_spi6, sclk_spi6, "sclk_spi6", 0, 0, NULL),
VCLK(sclk_peric1_spi7, sclk_spi7, "sclk_spi7", 0, 0, NULL),
/* PERIC1 GPIO */
VCLK(gate_gpio_nfc, gate_peric1_gpio_nfc, "gate_gpio_nfc", 0, 0, NULL),
VCLK(gate_gpio_touch, gate_peric1_gpio_touch, "gate_gpio_touch", 0, 0, NULL),
VCLK(gate_gpio_fp, gate_peric1_gpio_fp, "gate_gpio_fp", 0, 0, NULL),
VCLK(gate_gpio_ese, gate_peric1_gpio_ese, "gate_gpio_ese", 0, 0, NULL),
/* PERIC1 promise */
VCLK(promise_int, sclk_promise_int, "sclk_promise_int", 0, 0, NULL),
VCLK(promise_disp, sclk_promise_disp, "sclk_promise_disp", 0, 0, NULL),
VCLK(ap2cp_mif_pll_out, sclk_ap2cp_mif_pll_out, "sclk_ap2cp_mif_pll_out", 0, 0, NULL),
VCLK(gate_i2s1, gate_peric1_i2s1, "gate_peric1_i2s1", 0, 0, NULL),
VCLK(gate_pcm1, gate_peric1_pcm1, "gate_peric1_pcm1", 0, 0, NULL),
VCLK(gate_spdif, gate_peric1_spdif, "gate_peric1_spdif", 0, 0, NULL),
};
static struct init_vclk exynos8890_isp0_vclks[] __initdata = {
/* ISP0 */
VCLK(gate_fimc_isp0, gate_isp0_fimc_isp0, "gate_fimc_isp0", 0, 0, NULL),
VCLK(gate_fimc_tpu, gate_isp0_fimc_tpu, "gate_isp0_fimc_tpu", 0, 0, NULL),
VCLK(isp0, pxmxdx_isp0_isp0, "clk_isp0", 0, 0, NULL),
VCLK(isp0_tpu, pxmxdx_isp0_tpu, "clk_isp0_tpu", 0, 0, NULL),
VCLK(isp0_trex, pxmxdx_isp0_trex, "clk_isp0_trex", 0, 0, NULL),
VCLK(CLK_VCLK_SYSMMU_ISP0, gate_isp0_sysmmu, "gate_isp0_sysmmu", 0, 0, NULL),
VCLK(isp0_ppmu, gate_isp0_ppmu, "gate_isp0_ppmu", 0, 0, NULL),
VCLK(isp0_bts, gate_isp0_bts, "gate_isp0_bts", 0, 0, NULL),
};
static struct init_vclk exynos8890_isp1_vclks[] __initdata = {
/* ISP1 */
VCLK(gate_fimc_isp1, gate_isp1_fimc_isp1, "gate_isp1_fimc_isp1", 0, 0, NULL),
VCLK(isp1, pxmxdx_isp1_isp1, "clk_isp1", 0, 0, NULL),
VCLK(isp1_ppmu, gate_isp1_ppmu, "gate_isp1_ppmu", 0, 0, NULL),
VCLK(isp1_bts, gate_isp1_bts, "gate_isp1_bts", 0, 0, NULL),
};
static struct init_vclk exynos8890_isp_sensor_vclks[] __initdata = {
/* ISP1 */
VCLK(isp_sensor0, sclk_isp_sensor0, "sclk_isp_sensor0", 0, 0, NULL),
VCLK(isp_sensor1, sclk_isp_sensor1, "sclk_isp_sensor1", 0, 0, NULL),
VCLK(isp_sensor2, sclk_isp_sensor2, "sclk_isp_sensor2", 0, 0, NULL),
VCLK(isp_sensor3, sclk_isp_sensor3, "sclk_isp_sensor3", 0, 0, NULL),
};
static struct init_vclk exynos8890_cam0_vclks[] __initdata = {
/* CAM0 */
VCLK(gate_csis0, gate_cam0_csis0, "gate_cam0_csis0", 0, 0, NULL),
VCLK(gate_csis1, gate_cam0_csis1, "gate_cam0_csis1", 0, 0, NULL),
VCLK(gate_fimc_bns, gate_cam0_fimc_bns, "gate_cam0_fimc_bns", 0, 0, NULL),
VCLK(fimc_3aa0, gate_cam0_fimc_3aa0, "gate_cam0_fimc_3aa0", 0, 0, NULL),
VCLK(fimc_3aa1, gate_cam0_fimc_3aa1, "gate_cam0_fimc_3aa1", 0, 0, NULL),
VCLK(cam0_hpm, gate_cam0_hpm, "gate_cam0_hpm", 0, 0, NULL),
VCLK(pxmxdx_csis0, pxmxdx_cam0_csis0, "gate_pxmxdx_cam0_csis0", 0, 0, NULL),
VCLK(pxmxdx_csis1, pxmxdx_cam0_csis1, "gate_pxmxdx_cam0_csis1", 0, 0, NULL),
VCLK(pxmxdx_csis2, pxmxdx_cam0_csis2, "gate_pxmxdx_cam0_csis2", 0, 0, NULL),
VCLK(pxmxdx_csis3, pxmxdx_cam0_csis3, "gate_pxmxdx_cam0_csis3", 0, 0, NULL),
VCLK(pxmxdx_3aa0, pxmxdx_cam0_3aa0, "gate_pxmxdx_cam0_3aa0", 0, 0, NULL),
VCLK(pxmxdx_3aa1, pxmxdx_cam0_3aa1, "gate_pxmxdx_cam0_3aa1", 0, 0, NULL),
VCLK(pxmxdx_trex, pxmxdx_cam0_trex, "gate_pxmxdx_cam0_trex", 0, 0, NULL),
VCLK(hs0_csis0_rx_byte, umux_cam0_phyclk_rxbyteclkhs0_csis0_user, "umux_cam0_phyclk_rxbyteclkhs0_csis0_user", 0, 0, NULL),
VCLK(hs1_csis0_rx_byte, umux_cam0_phyclk_rxbyteclkhs1_csis0_user, "umux_cam0_phyclk_rxbyteclkhs1_csis0_user", 0, 0, NULL),
VCLK(hs2_csis0_rx_byte, umux_cam0_phyclk_rxbyteclkhs2_csis0_user, "umux_cam0_phyclk_rxbyteclkhs2_csis0_user", 0, 0, NULL),
VCLK(hs3_csis0_rx_byte, umux_cam0_phyclk_rxbyteclkhs3_csis0_user, "umux_cam0_phyclk_rxbyteclkhs3_csis0_user", 0, 0, NULL),
VCLK(hs0_csis1_rx_byte, umux_cam0_phyclk_rxbyteclkhs0_csis1_user, "umux_cam0_phyclk_rxbyteclkhs0_csis1_user", 0, 0, NULL),
VCLK(hs1_csis1_rx_byte, umux_cam0_phyclk_rxbyteclkhs1_csis1_user, "umux_cam0_phyclk_rxbyteclkhs1_csis1_user", 0, 0, NULL),
VCLK(CLK_VCLK_SYSMMU_CAM0, gate_cam0_sysmmu, "gate_cam0_sysmmu", 0, 0, NULL),
VCLK(cam0_ppmu, gate_cam0_ppmu, "gate_cam0_ppmu", 0, 0, NULL),
VCLK(cam0_bts, gate_cam0_bts, "gate_cam0_bts", 0, 0, NULL),
};
static struct init_vclk exynos8890_cam1_vclks[] __initdata = {
/* CAM1 */
VCLK(gate_isp_cpu, gate_cam1_isp_cpu, "gate_cam1_isp_cpu", 0, 0, NULL),
VCLK(gate_csis2, gate_cam1_csis2, "gate_cam1_csis2", 0, 0, NULL),
VCLK(gate_csis3, gate_cam1_csis3, "gate_cam1_csis3", 0, 0, NULL),
VCLK(gate_fimc_vra, gate_cam1_fimc_vra, "gate_cam1_fimc_vra", 0, 0, NULL),
VCLK(gate_mc_scaler, gate_cam1_mc_scaler, "gate_cam1_mc_scaler", 0, 0, NULL),
VCLK(gate_i2c0_isp, gate_cam1_i2c0_isp, "gate_cam1_i2c0_isp", 0, 0, NULL),
VCLK(gate_i2c1_isp, gate_cam1_i2c1_isp, "gate_cam1_i2c1_isp", 0, 0, NULL),
VCLK(gate_i2c2_isp, gate_cam1_i2c2_isp, "gate_cam1_i2c2_isp", 0, 0, NULL),
VCLK(gate_i2c3_isp, gate_cam1_i2c3_isp, "gate_cam1_i2c3_isp", 0, 0, NULL),
VCLK(gate_wdt_isp, gate_cam1_wdt_isp, "gate_cam1_wdt_isp", 0, 0, NULL),
VCLK(gate_mcuctl_isp, gate_cam1_mcuctl_isp, "gate_cam1_mcuctl_isp", 0, 0, NULL),
VCLK(gate_uart_isp, gate_cam1_uart_isp, "gate_cam1_uart_isp", 0, 0, NULL),
VCLK(gate_pdma_isp, gate_cam1_pdma_isp, "gate_cam1_pdma_isp", 0, 0, NULL),
VCLK(gate_pwm_isp, gate_cam1_pwm_isp, "gate_cam1_pwm_isp", 0, 0, NULL),
VCLK(gate_spi0_isp, gate_cam1_spi0_isp, "gate_cam1_spi0_isp", 0, 0, NULL),
VCLK(gate_spi1_isp, gate_cam1_spi1_isp, "gate_cam1_spi1_isp", 0, 0, NULL),
/* rate clock source */
VCLK(isp_spi0, sclk_isp_spi0, "sclk_isp_spi0", 0, 0, NULL),
VCLK(isp_spi1, sclk_isp_spi1, "sclk_isp_spi1", 0, 0, NULL),
VCLK(isp_uart, sclk_isp_uart, "sclk_isp_uart", 0, 0, NULL),
VCLK(gate_sclk_pwm_isp, gate_cam1_sclk_pwm_isp, "gate_cam1_sclk_pwm_isp", 0, 0, NULL),
VCLK(gate_sclk_uart_isp, gate_cam1_sclk_uart_isp, "gate_cam1_sclk_uart_isp", 0, 0, NULL),
/* rate clock source */
VCLK(cam1_arm, pxmxdx_cam1_arm, "pxmxdx_cam1_arm", 0, 0, NULL),
VCLK(cam1_vra, pxmxdx_cam1_vra, "pxmxdx_cam1_vra", 0, 0, NULL),
VCLK(cam1_trex, pxmxdx_cam1_trex, "pxmxdx_cam1_trex", 0, 0, NULL),
VCLK(cam1_bus, pxmxdx_cam1_bus, "pxmxdx_cam1_bus", 0, 0, NULL),
VCLK(cam1_peri, pxmxdx_cam1_peri, "pxmxdx_cam1_peri", 0, 0, NULL),
VCLK(cam1_csis2, pxmxdx_cam1_csis2, "pxmxdx_cam1_csis2", 0, 0, NULL),
VCLK(cam1_csis3, pxmxdx_cam1_csis3, "pxmxdx_cam1_csis3", 0, 0, NULL),
VCLK(cam1_scl, pxmxdx_cam1_scl, "pxmxdx_cam1_scl", 0, 0, NULL),
/* usermux */
VCLK(cam1_phy0_csis2, umux_cam1_phyclk_rxbyteclkhs0_csis2_user, "phyclk_rxbyteclkhs0_csis2_user", 0, 0, NULL),
VCLK(cam1_phy1_csis2, umux_cam1_phyclk_rxbyteclkhs1_csis2_user, "phyclk_rxbyteclkhs1_csis2_user", 0, 0, NULL),
VCLK(cam1_phy2_csis2, umux_cam1_phyclk_rxbyteclkhs2_csis2_user, "phyclk_rxbyteclkhs2_csis2_user", 0, 0, NULL),
VCLK(cam1_phy3_csis2, umux_cam1_phyclk_rxbyteclkhs3_csis2_user, "phyclk_rxbyteclkhs3_csis2_user", 0, 0, NULL),
VCLK(cam1_phy0_csis3, umux_cam1_phyclk_rxbyteclkhs0_csis3_user, "phyclk_rxbyteclkhs0_csis3_user", 0, 0, NULL),
VCLK(CLK_VCLK_SYSMMU_CAM1, gate_cam1_sysmmu, "gate_cam1_sysmmu", 0, 0, NULL),
VCLK(cam1_ppmu, gate_cam1_ppmu, "gate_cam1_ppmu", 0, 0, NULL),
VCLK(cam1_bts, gate_cam1_bts, "gate_cam1_bts", 0, 0, NULL),
};
static struct init_vclk exynos8890_audio_vclks[] __initdata = {
/* AUDIO */
VCLK(gate_mi2s, gate_aud_mi2s, "gate_aud_mi2s", 0, 0, NULL),
VCLK(gate_pcm, gate_aud_pcm, "gate_aud_pcm", 0, 0, NULL),
VCLK(gate_slimbus, gate_aud_slimbus, "gate_aud_slimbus", 0, 0, NULL),
VCLK(gate_sclk_mi2s, gate_aud_sclk_mi2s, "gate_aud_sclk_mi2s", 0, 0, NULL),
VCLK(d1_sclk_i2s, d1_sclk_i2s_local, "dout_sclk_i2s_local", 0, 0, NULL),
VCLK(gate_sclk_pcm, gate_aud_sclk_pcm, "gate_aud_sclk_pcm", 0, 0, NULL),
VCLK(d1_sclk_pcm, d1_sclk_pcm_local, "dout_sclk_pcm_local", 0, 0, NULL),
VCLK(gate_sclk_slimbus, gate_aud_sclk_slimbus, "gate_aud_sclk_slimbus", 0, 0, NULL),
VCLK(sclk_slimbus, d1_sclk_slimbus, "dout_sclk_slimbus", 0, 0, NULL),
VCLK(sclk_cp_i2s, d1_sclk_cp_i2s, "dout_sclk_cp_i2s", 0, 0, NULL),
VCLK(sclk_asrc, d1_sclk_asrc, "dout_sclk_asrc", 0, 0, NULL),
VCLK(aud_pll, p1_aud_pll, "sclk_aud_pll", 0, 0, NULL),
VCLK(aud_cp, pxmxdx_aud_cp, "gate_aud_cp", 0, 0, NULL),
VCLK(aud_lpass, gate_aud_lpass, "gate_aud_lpass", 0, 0, NULL),
VCLK(aud_dma, gate_aud_dma, "gate_aud_dma", 0, 0, NULL),
VCLK(CLK_VCLK_SYSMMU_AUD, gate_aud_sysmmu, "gate_aud_sysmmu", 0, 0, NULL),
VCLK(aud_ppmu, gate_aud_ppmu, "gate_aud_ppmu", 0, 0, NULL),
VCLK(aud_bts, gate_aud_bts, "gate_aud_bts", 0, 0, NULL),
};
static struct init_vclk exynos8890_fsys0_vclks[] __initdata = {
/* FSYS0 */
VCLK(gate_usbdrd30, gate_fsys0_usbdrd30, "gate_fsys0_usbdrd30", 0, 0, NULL),
VCLK(gate_usbhost20, gate_fsys0_usbhost20, "gate_fsys0_usbhost20", 0, 0, NULL),
VCLK(usbdrd30, sclk_usbdrd30, "sclk_usbdrd30", 0, 0, NULL),
VCLK(sclk_fsys0_mmc0, sclk_mmc0, "sclk_mmc0", 0, 0, NULL),
VCLK(ufsunipro20, sclk_ufsunipro20, "sclk_ufsunipro20", 0, 0, NULL),
VCLK(phy24m, sclk_phy24m, "sclk_phy24m", 0, 0, NULL),
VCLK(ufsunipro_cfg, sclk_ufsunipro_cfg, "sclk_ufsunipro_cfg", 0, 0, NULL),
/* UMUX GATE related clock sources */
VCLK(gate_udrd30_phyclock, umux_fsys0_phyclk_usbdrd30_udrd30_phyclock_user, "umux_fsys0_phyclk_usbdrd30_udrd30_phyclock_user", 0, 0, NULL),
VCLK(gate_udrd30_pipe, umux_fsys0_phyclk_usbdrd30_udrd30_pipe_pclk_user, "umux_fsys0_phyclk_usbdrd30_udrd30_pipe_pclk_user", 0, 0, NULL),
VCLK(gate_ufs_tx0, umux_fsys0_phyclk_ufs_tx0_symbol_user, "umux_fsys0_phyclk_ufs_tx0_symbol_user", 0, 0, NULL),
VCLK(gate_ufs_rx0, umux_fsys0_phyclk_ufs_rx0_symbol_user, "umux_fsys0_phyclk_ufs_rx0_symbol_user", 0, 0, NULL),
VCLK(usbhost20_phyclock, umux_fsys0_phyclk_usbhost20_phyclock_user, "umux_fsys0_phyclk_usbhost20_phyclock_user", 0, 0, NULL),
VCLK(usbhost20phy_ref, umux_fsys0_phyclk_usbhost20phy_ref_clk, "umux_fsys0_phyclk_usbhost20phy_ref_clk", 0, 0, NULL),
VCLK(fsys_200, pxmxdx_fsys0, "aclk_ufs", 0, 0, NULL),
VCLK(fsys0_etr_usb, gate_fsys0_etr_usb, "gate_fsys0_etr_usb", 0, 0, "etr_clk"),
VCLK(gate_mmc, gate_fsys0_mmc0, "gate_fsys0_mmc0", 0, 0, NULL),
VCLK(gate_pdma0, gate_fsys0_pdma0, "gate_fsys0_pdma0", 0, 0, NULL),
VCLK(gate_pdmas, gate_fsys0_pdmas, "gate_fsys0_pdmas", 0, 0, NULL),
VCLK(gate_ufs_linkemedded, gate_fsys0_ufs_linkemedded, "gate_fsys0_ufs_linkemedded", 0, 0, NULL),
};
static struct init_vclk exynos8890_fsys1_vclks[] __initdata = {
/* FSYS1 */
VCLK(fsys1_hpm, gate_fsys1_hpm, "gate_fsys1_hpm", 0, 0, NULL),
VCLK(fsys1_sclk_mmc2, sclk_mmc2, "sclk_mmc2", 0, 0, NULL),
VCLK(ufsunipro20_sdcard, sclk_ufsunipro20_sdcard, "sclk_ufsunipro20_sdcard", 0, 0, NULL),
VCLK(pcie_phy, sclk_pcie_phy, "sclk_pcie_phy", 0, 0, NULL),
VCLK(sclk_ufsunipro_sdcard, sclk_ufsunipro_sdcard_cfg, "sclk_ufsunipro_sdcard_cfg", 0, 0, NULL),
/* UMUX GATE related clock sources */
VCLK(ufs_link_sdcard_tx0, umux_fsys1_phyclk_ufs_link_sdcard_tx0_symbol_user, "umux_fsys1_phyclk_ufs_link_sdcard_tx0_symbol_user", 0, 0, NULL),
VCLK(ufs_link_sdcard_rx0, umux_fsys1_phyclk_ufs_link_sdcard_rx0_symbol_user, "umux_fsys1_phyclk_ufs_link_sdcard_rx0_symbol_user", 0, 0, NULL),
VCLK(pcie_wifi0_tx0, umux_fsys1_phyclk_pcie_wifi0_tx0_user, "umux_fsys1_phyclk_pcie_wifi0_tx0_user", 0, 0, NULL),
VCLK(pcie_wifi0_rx0, umux_fsys1_phyclk_pcie_wifi0_rx0_user, "umux_fsys1_phyclk_pcie_wifi0_rx0_user", 0, 0, NULL),
VCLK(pcie_wifi1_tx0, umux_fsys1_phyclk_pcie_wifi1_tx0_user, "umux_fsys1_phyclk_pcie_wifi1_tx0_user", 0, 0, NULL),
VCLK(pcie_wifi1_rx0, umux_fsys1_phyclk_pcie_wifi1_rx0_user, "umux_fsys1_phyclk_pcie_wifi1_rx0_user", 0, 0, NULL),
VCLK(wifi0_dig_refclk, umux_fsys1_phyclk_pcie_wifi0_dig_refclk_user, "umux_fsys1_phyclk_pcie_wifi0_dig_refclk_user", 0, 0, NULL),
VCLK(wifi1_dig_refclk, umux_fsys1_phyclk_pcie_wifi1_dig_refclk_user, "umux_fsys1_phyclk_pcie_wifi1_dig_refclk_user", 0, 0, NULL),
VCLK(gate_mmc2, gate_fsys1_mmc2, "gate_fsys1_mmc2", 0, 0, NULL),
VCLK(gate_ufs20_sdcard, gate_fsys1_ufs20_sdcard, "gate_fsys1_ufs20_sdcard", 0, 0, NULL),
VCLK(gate_sromc, gate_fsys1_sromc, "gate_fsys1_sromc", 0, 0, NULL),
VCLK(gate_pciewifi0, gate_fsys1_pciewifi0, "gate_fsys1_pciewifi0", 0, 0, NULL),
VCLK(gate_pciewifi1, gate_fsys1_pciewifi1, "gate_fsys1_pciewifi1", 0, 0, NULL),
VCLK(fsys1_ppmu, gate_fsys1_ppmu, "gate_fsys1_ppmu", 0, 0, NULL),
VCLK(fsys1_bts, gate_fsys1_bts, "gate_fsys1_bts", 0, 0, NULL),
};
static struct init_vclk exynos8890_g3d_vclks[] __initdata = {
/* G3D */
VCLK(gate_g3d, gate_g3d_g3d, "gate_g3d_g3d", 0, 0, "vclk_g3d"),
VCLK(gate_g3d_iram, gate_g3d_iram_path_test, "g3d_iram_path", 0, 0, NULL),
VCLK(g3d_bts, gate_g3d_bts, "gate_g3d_bts", 0, 0, NULL),
VCLK(g3d_ppmu, gate_g3d_ppmu, "gate_g3d_ppmu", 0, 0, NULL),
};
static struct init_vclk exynos8890_disp0_vclks[] __initdata = {
/* DISP0 */
VCLK(gate_decon0, gate_disp0_decon0, "gate_disp0_decon0", 0, 0, NULL),
VCLK(gate_dsim0, gate_disp0_dsim0, "gate_disp0_dsim0", 0, 0, NULL),
VCLK(gate_dsim1, gate_disp0_dsim1, "gate_disp0_dsim1", 0, 0, NULL),
VCLK(gate_dsim2, gate_disp0_dsim2, "gate_disp0_dsim2", 0, 0, NULL),
VCLK(gate_hdmi, gate_disp0_hdmi, "gate_disp0_hdmi", 0, 0, NULL),
VCLK(gate_dp, gate_disp0_dp, "gate_disp0_dp", 0, 0, NULL),
VCLK(gate_hpm_apbif_disp0, gate_disp0_hpm_apbif_disp0, "gate_disp0_hpm_apbif_disp0", 0, 0, NULL),
/* special clock - sclk */
VCLK(decon0_eclk0, sclk_decon0_eclk0, "sclk_decon0_eclk0", 0, 0, NULL),
VCLK(decon0_vclk0, sclk_decon0_vclk0, "sclk_decon0_vclk0", 0, 0, NULL),
VCLK(decon0_vclk1, sclk_decon0_vclk1, "sclk_decon0_vclk1", 0, 0, NULL),
VCLK(decon0_eclk0_local, sclk_decon0_eclk0_local, "sclk_decon0_eclk0_local", 0, 0, NULL),
VCLK(decon0_vclk0_local, sclk_decon0_vclk0_local, "sclk_decon0_vclk0_local", 0, 0, NULL),
VCLK(decon0_vclk1_local, sclk_decon0_vclk1_local, "sclk_decon0_vclk1_local", 0, 0, NULL),
VCLK(hdmi_audio, sclk_hdmi_audio, "sclk_hdmi_audio", 0, 0, NULL),
/* PLL clock source */
VCLK(disp_pll, p1_disp_pll, "p1_disp_pll", 0, 0, "disp_pll"),
/* USERMUX related clock source */
VCLK(mipidphy0_rxclkesc0, umux_disp0_phyclk_mipidphy0_rxclkesc0_user, "umux_disp0_phyclk_mipidphy0_rxclkesc0_user", 0, 0, NULL),
VCLK(mipidphy0_bitclkdiv8, umux_disp0_phyclk_mipidphy0_bitclkdiv8_user, "umux_disp0_phyclk_mipidphy0_bitclkdiv8_user", 0, 0, NULL),
VCLK(mipidphy1_rxclkesc0, umux_disp0_phyclk_mipidphy1_rxclkesc0_user, "umux_disp0_phyclk_mipidphy1_rxclkesc0_user", 0, 0, NULL),
VCLK(mipidphy1_bitclkdiv8, umux_disp0_phyclk_mipidphy1_bitclkdiv8_user, "umux_disp0_phyclk_mipidphy1_bitclkdiv8_user", 0, 0, NULL),
VCLK(mipidphy2_rxclkesc0, umux_disp0_phyclk_mipidphy2_rxclkesc0_user, "umux_disp0_phyclk_mipidphy2_rxclkesc0_user", 0, 0, NULL),
VCLK(mipidphy2_bitclkdiv8, umux_disp0_phyclk_mipidphy2_bitclkdiv8_user, "umux_disp0_phyclk_mipidphy2_bitclkdiv8_user", 0, 0, NULL),
VCLK(dpphy_ch0_txd, umux_disp0_phyclk_dpphy_ch0_txd_clk_user, "umux_disp0_phyclk_dpphy_ch0_txd_clk_user", 0, 0, NULL),
VCLK(dpphy_ch1_txd, umux_disp0_phyclk_dpphy_ch1_txd_clk_user, "umux_disp0_phyclk_dpphy_ch1_txd_clk_user", 0, 0, NULL),
VCLK(dpphy_ch2_txd, umux_disp0_phyclk_dpphy_ch2_txd_clk_user, "umux_disp0_phyclk_dpphy_ch2_txd_clk_user", 0, 0, NULL),
VCLK(dpphy_ch3_txd, umux_disp0_phyclk_dpphy_ch3_txd_clk_user, "umux_disp0_phyclk_dpphy_ch3_txd_clk_user", 0, 0, NULL),
VCLK(dptx_phy_i_ref_clk_24m, gate_disp0_oscclk_i_dptx_phy_i_ref_clk_24m, "gate_disp0_oscclk_i_dptx_phy_i_ref_clk_24m", 0, 0, NULL),
VCLK(mipi_dphy_m1s0, gate_disp0_oscclk_i_mipi_dphy_m1s0_m_xi, "gate_disp0_oscclk_i_mipi_dphy_m1s0_m_xi", 0, 0, NULL),
VCLK(mipi_dphy_m4s0, gate_disp0_oscclk_i_mipi_dphy_m4s0_m_xi, "gate_disp0_oscclk_i_mipi_dphy_m4s0_m_xi", 0, 0, NULL),
VCLK(mipi_dphy_m4s4, gate_disp0_oscclk_i_mipi_dphy_m4s4_m_xi, "gate_disp0_oscclk_i_mipi_dphy_m4s4_m_xi", 0, 0, NULL),
VCLK(phyclk_hdmiphy_tmds_20b, umux_disp0_phyclk_hdmiphy_tmds_clko_user, "umux_disp0_phyclk_hdmiphy_tmds_clko_user", 0, 0, NULL),
VCLK(phyclk_hdmiphy_pixel, umux_disp0_phyclk_hdmiphy_pixel_clko_user, "umux_disp0_phyclk_hdmiphy_pixel_clko_user", 0, 0, NULL),
VCLK(mipidphy0_bitclkdiv2_user, umux_disp0_phyclk_mipidphy0_bitclkdiv2_user, "umux_disp0_phyclk_mipidphy0_bitclkdiv2_user", 0, 0, NULL),
VCLK(mipidphy1_bitclkdiv2_user, umux_disp0_phyclk_mipidphy1_bitclkdiv2_user, "umux_disp0_phyclk_mipidphy1_bitclkdiv2_user", 0, 0, NULL),
VCLK(mipidphy2_bitclkdiv2_user, umux_disp0_phyclk_mipidphy2_bitclkdiv2_user, "umux_disp0_phyclk_mipidphy2_bitclkdiv2_user", 0, 0, NULL),
VCLK(CLK_VCLK_SYSMMU_DISP0, gate_disp0_sysmmu, "gate_disp0_sysmmu", 0, 0, NULL),
};
static struct init_vclk exynos8890_disp1_vclks[] __initdata = {
/* DISP1 */
VCLK(gate_decon1, gate_disp1_decon1, "gate_disp1_decon1", 0, 0, NULL),
VCLK(gate_hpmdisp1, gate_disp1_hpmdisp1, "gate_disp1_hpmdisp1", 0, 0, NULL),
/* special clock - sclk */
VCLK(decon1_eclk0, sclk_decon1_eclk0, "sclk_decon1_eclk0", 0, 0, NULL),
VCLK(decon1_eclk1, sclk_decon1_eclk1, "sclk_decon1_eclk1", 0, 0, NULL),
VCLK(decon1_eclk0_local, sclk_decon1_eclk0_local, "sclk_decon1_eclk0_local", 0, 0, NULL),
VCLK(decon1_eclk1_local, sclk_decon1_eclk1_local, "sclk_decon1_eclk1_local", 0, 0, NULL),
/* USERMUX related clock source */
VCLK(disp1_phyclk_mipidphy0_bitclkdiv2_user, umux_disp1_phyclk_mipidphy0_bitclkdiv2_user, "umux_disp1_phyclk_mipidphy0_bitclkdiv2_user", 0, 0, NULL),
VCLK(disp1_phyclk_mipidphy1_bitclkdiv2_user, umux_disp1_phyclk_mipidphy1_bitclkdiv2_user, "umux_disp1_phyclk_mipidphy1_bitclkdiv2_user", 0, 0, NULL),
VCLK(disp1_phyclk_mipidphy2_bitclkdiv2_user, umux_disp1_phyclk_mipidphy2_bitclkdiv2_user, "umux_disp1_phyclk_mipidphy2_bitclkdiv2_user", 0, 0, NULL),
VCLK(disp1_phyclk_disp1_hdmiphy_pixel_clko_user, umux_disp1_phyclk_disp1_hdmiphy_pixel_clko_user, "umux_disp1_phyclk_disp1_hdmiphy_pixel_clko_user", 0, 0, NULL),
VCLK(CLK_VCLK_SYSMMU_DISP1, gate_disp1_sysmmu, "gate_disp1_sysmmu", 0, 0, NULL),
VCLK(disp1_ppmu, gate_disp1_ppmu, "gate_disp1_ppmu", 0, 0, NULL),
VCLK(disp1_bts, gate_disp1_bts, "gate_disp1_bts", 0, 0, NULL),
};
void __init exynos8890_clk_init(struct device_node *np)
{
struct samsung_clk_provider *ctx;
void __iomem *reg_base;
int ret;
BUILD_BUG_ON(mscl_jpeg != CLK_GATE_SMFC);
if (np) {
reg_base = of_iomap(np, 0);
if (!reg_base)
panic("%s: failed to map registers\n", __func__);
} else {
panic("%s: unable to determine soc\n", __func__);
}
#if defined(CONFIG_ECT)
ect_parse_binary_header();
#endif
ret = cal_init();
if (ret)
pr_err("%s: unable to initialize power cal\n", __func__);
ctx = samsung_clk_init(np, reg_base, nr_clks);
if (!ctx)
panic("%s: unable to allocate context.\n", __func__);
samsung_register_of_fixed_ext(ctx, exynos8890_fixed_rate_ext_clks,
ARRAY_SIZE(exynos8890_fixed_rate_ext_clks),
ext_clk_match);
/* Regist clock local IP */
samsung_register_vclk(ctx, exynos8890_audio_vclks, ARRAY_SIZE(exynos8890_audio_vclks));
samsung_register_vclk(ctx, exynos8890_cam0_vclks, ARRAY_SIZE(exynos8890_cam0_vclks));
samsung_register_vclk(ctx, exynos8890_cam1_vclks, ARRAY_SIZE(exynos8890_cam1_vclks));
samsung_register_vclk(ctx, exynos8890_disp0_vclks, ARRAY_SIZE(exynos8890_disp0_vclks));
samsung_register_vclk(ctx, exynos8890_disp1_vclks, ARRAY_SIZE(exynos8890_disp1_vclks));
samsung_register_vclk(ctx, exynos8890_fsys0_vclks, ARRAY_SIZE(exynos8890_fsys0_vclks));
samsung_register_vclk(ctx, exynos8890_fsys1_vclks, ARRAY_SIZE(exynos8890_fsys1_vclks));
samsung_register_vclk(ctx, exynos8890_g3d_vclks, ARRAY_SIZE(exynos8890_g3d_vclks));
samsung_register_vclk(ctx, exynos8890_imem_vclks, ARRAY_SIZE(exynos8890_imem_vclks));
samsung_register_vclk(ctx, exynos8890_isp0_vclks, ARRAY_SIZE(exynos8890_isp0_vclks));
samsung_register_vclk(ctx, exynos8890_isp1_vclks, ARRAY_SIZE(exynos8890_isp1_vclks));
samsung_register_vclk(ctx, exynos8890_isp_sensor_vclks, ARRAY_SIZE(exynos8890_isp1_vclks));
samsung_register_vclk(ctx, exynos8890_mfc_vclks, ARRAY_SIZE(exynos8890_mfc_vclks));
samsung_register_vclk(ctx, exynos8890_mscl_vclks, ARRAY_SIZE(exynos8890_mscl_vclks));
samsung_register_vclk(ctx, exynos8890_peric0_vclks, ARRAY_SIZE(exynos8890_peric0_vclks));
samsung_register_vclk(ctx, exynos8890_peric1_vclks, ARRAY_SIZE(exynos8890_peric1_vclks));
samsung_register_vclk(ctx, exynos8890_peris_vclks, ARRAY_SIZE(exynos8890_peris_vclks));
samsung_register_vclk(ctx, exynos8890_ccore_vclks, ARRAY_SIZE(exynos8890_ccore_vclks));
samsung_register_vclk(ctx, exynos8890_clkout_vclks, ARRAY_SIZE(exynos8890_clkout_vclks));
samsung_clk_of_add_provider(np, ctx);
clk_register_fixed_factor(NULL, "pwm-clock", "gate_peric0_pwm",CLK_SET_RATE_PARENT, 1, 1);
pr_info("EXYNOS8890: Clock setup completed\n");
}
CLK_OF_DECLARE(exynos8890_clks, "samsung,exynos8890-clock", exynos8890_clk_init);

View file

@ -0,0 +1,552 @@
/*
* Copyright (c) 2015 Samsung Electronics Co., Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This file contains clocks of Exynos8890.
*/
#include <linux/clk.h>
#include <linux/clkdev.h>
#include <linux/clk-provider.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <dt-bindings/clock/exynos8890.h>
#include "../../soc/samsung/pwrcal/S5E8890/S5E8890-vclk.h"
#include "composite.h"
#if defined(CONFIG_ECT)
#include <soc/samsung/ect_parser.h>
#endif
enum exynos8890_clks {
none,
oscclk = 1,
/* number for mfc driver starts from 10 */
mfc_hpm = 10, mfc_mfc, mfc_ppmu,
/* number for mscl driver starts from 50 */
mscl_mscl0 = 50, mscl_jpeg, mscl_mscl1, mscl_g2d, mscl_ppmu, mscl_bts,
/* number for imem driver starts from 100 */
gate_apm = 100, gate_sss, gate_gic400, gate_rtic, gate_mc, gate_intmem, gate_alv, gate_ppmu,
/* number for peris driver starts from 150 */
peris_sfr = 150, peris_hpm, peris_mct, wdt_mngs, wdt_apollo, sysreg_peris, monocnt_apbif, rtc_apbif, top_rtc, otp_con_top, peris_chipid, peris_tmu, peris_sysreg, peris_monocnt,
/* number for peric0 driver starts from 200 */
gate_hsi2c0 = 200, gate_hsi2c1, gate_hsi2c4, gate_hsi2c5, gate_hsi2c9, gate_hsi2c10, gate_hsi2c11, puart0, suart0, gate_adcif, gate_pwm, gate_sclk_pwm,
/* number for peric1 driver starts from 250 */
gate_hsi2c2 = 250, gate_hsi2c3, gate_hsi2c6, gate_hsi2c7, gate_hsi2c8, gate_hsi2c12, gate_hsi2c13, gate_hsi2c14,
gate_uart1, gate_uart2, gate_uart3, gate_uart4, gate_uart5, suart1, suart2, suart3, suart4, suart5,
gate_spi0, gate_spi1, gate_spi2, gate_spi3, gate_spi4, gate_spi5, gate_spi6, gate_spi7,
sclk_peric1_spi0, sclk_peric1_spi1, sclk_peric1_spi2, sclk_peric1_spi3, sclk_peric1_spi4, sclk_peric1_spi5, sclk_peric1_spi6, sclk_peric1_spi7,
gate_gpio_nfc, gate_gpio_touch, gate_gpio_fp, gate_gpio_ese, promise_int, promise_disp, ap2cp_mif_pll_out, gate_i2s1, gate_pcm1, gate_spdif,
/* number for isp0 driver starts from 400 */
gate_fimc_isp0 = 400, gate_fimc_tpu, isp0, isp0_tpu, isp0_trex, isp0_ppmu, isp0_bts,
/* number for isp1 driver starts from 450 */
gate_fimc_isp1 = 450, isp1, isp1_ppmu, isp1_bts,
/* number for isp sensor driver starts from 500 */
isp_sensor0 = 500, isp_sensor1, isp_sensor2, isp_sensor3,
/* number for cam0 driver starts from 550 */
gate_csis0 = 550, gate_csis1, gate_fimc_bns, fimc_3aa0, fimc_3aa1, cam0_hpm, pxmxdx_csis0, pxmxdx_csis1, pxmxdx_csis2, pxmxdx_csis3,
pxmxdx_3aa0, pxmxdx_3aa1, pxmxdx_trex, hs0_csis0_rx_byte, hs1_csis0_rx_byte, hs2_csis0_rx_byte, hs3_csis0_rx_byte, hs0_csis1_rx_byte, hs1_csis1_rx_byte, cam0_ppmu, cam0_bts,
/* number for cam1 driver starts from 600 */
gate_isp_cpu = 600, gate_csis2, gate_csis3, gate_fimc_vra, gate_mc_scaler, gate_i2c0_isp, gate_i2c1_isp, gate_i2c2_isp, gate_i2c3_isp, gate_wdt_isp,
gate_mcuctl_isp, gate_uart_isp, gate_pdma_isp, gate_pwm_isp, gate_spi0_isp, gate_spi1_isp, isp_spi0, isp_spi1, isp_uart, gate_sclk_pwm_isp,
gate_sclk_uart_isp, cam1_arm, cam1_vra, cam1_trex, cam1_bus, cam1_peri, cam1_csis2, cam1_csis3, cam1_scl, cam1_phy0_csis2, cam1_phy1_csis2,
cam1_phy2_csis2, cam1_phy3_csis2, cam1_phy0_csis3, cam1_ppmu, cam1_bts,
/* number for audio driver starts from 650 */
gate_mi2s = 650, gate_pcm, gate_slimbus, gate_sclk_mi2s, d1_sclk_i2s, gate_sclk_pcm, d1_sclk_pcm, gate_sclk_slimbus, sclk_slimbus, sclk_cp_i2s,
sclk_asrc, aud_pll, aud_cp, aud_lpass, aud_dma, aud_ppmu, aud_bts,
/* number for fsys0 driver starts from 700 */
gate_usbdrd30 = 700, gate_usbhost20, usbdrd30 = 703, sclk_fsys0_mmc0, ufsunipro20, phy24m, ufsunipro_cfg, gate_udrd30_phyclock, gate_udrd30_pipe, gate_ufs_tx0,
gate_ufs_rx0, usbhost20_phyclock, usbhost20_freeclk, usbhost20_clk48, usbhost20phy_ref, ufs_rx_pwm, ufs_tx_pwm, ufs_refclk_out, fsys_200, fsys0_etr_usb, gate_mmc, gate_pdma0, gate_pdmas, gate_ufs_linkemedded,
/* number for fsys1 driver starts from 750 */
gate_ufs20_sdcard = 750, fsys1_hpm, fsys1_sclk_mmc2, ufsunipro20_sdcard, pcie_phy, sclk_ufsunipro_sdcard, ufs_link_sdcard_tx0, ufs_link_sdcard_rx0,
pcie_wifi0_tx0, pcie_wifi0_rx0, pcie_wifi1_tx0, pcie_wifi1_rx0, wifi0_dig_refclk, wifi1_dig_refclk, sdcard_rx_pwm, sdcard_tx_pwm, sdcard_refclk, gate_mmc2,
gate_sromc, gate_pciewifi0, gate_pciewifi1, fsys1_ppmu, fsys1_bts,
/* number for g3d driver starts from 800 */
gate_g3d = 800, gate_g3d_iram, g3d_bts, g3d_ppmu,
/* number for disp0 driver starts from 850 */
gate_decon0 = 850, gate_dsim0, gate_dsim1, gate_dsim2, gate_hdmi, gate_dp, gate_hpm_apbif_disp0, decon0_eclk0, decon0_vclk0, decon0_vclk1,
decon0_eclk0_local, decon0_vclk0_local, decon0_vclk1_local, hdmi_audio, disp_pll,
mipidphy0_rxclkesc0, mipidphy0_bitclkdiv8, mipidphy1_rxclkesc0, mipidphy1_bitclkdiv8, mipidphy2_rxclkesc0, mipidphy2_bitclkdiv8,
dpphy_ch0_txd, dpphy_ch1_txd, dpphy_ch2_txd, dpphy_ch3_txd, dptx_phy_i_ref_clk_24m,
mipi_dphy_m1s0, mipi_dphy_m4s0, mipi_dphy_m4s4, phyclk_hdmiphy_tmds_20b, phyclk_hdmiphy_pixel, mipidphy0_bitclkdiv2_user,
mipidphy1_bitclkdiv2_user, mipidphy2_bitclkdiv2_user,
/* number for disp1 driver starts from 900 */
gate_decon1 = 900, gate_hpmdisp1, decon1_eclk0, decon1_eclk1, decon1_eclk0_local, decon1_eclk1_local,
disp1_phyclk_mipidphy0_bitclkdiv2_user, disp1_phyclk_mipidphy1_bitclkdiv2_user,
disp1_phyclk_mipidphy2_bitclkdiv2_user, disp1_phyclk_disp1_hdmiphy_pixel_clko_user, disp1_ppmu, disp1_bts,
/* number for ccore driver starts from 950 */
ccore_i2c = 950,
/* number for clkout port starts from 1000 */
oscclk_nfc = 1000, oscclk_aud,
/* clk id for sysmmu: 1100 ~ 1149
* NOTE: clock IDs of sysmmus are defined in
* include/dt-bindings/clock/exynos8890.h
*/
sysmmu_last = 1149,
nr_clks,
};
static struct samsung_fixed_rate exynos8890_fixed_rate_ext_clks[] __initdata = {
FRATE(oscclk, "fin_pll", NULL, CLK_IS_ROOT, 0),
};
static struct of_device_id ext_clk_match[] __initdata = {
{ .compatible = "samsung,exynos8890-oscclk", .data = (void *)0, },
};
static struct init_vclk exynos8890_clkout_vclks[] __initdata = {
VCLK(oscclk_nfc, pxmxdx_oscclk_nfc, "pxmxdx_oscclk_nfc", 0, 0, NULL),
VCLK(oscclk_aud, pxmxdx_oscclk_aud, "pxmxdx_oscclk_aud", 0, 0, NULL),
};
static struct init_vclk exynos8890_ccore_vclks[] __initdata = {
VCLK(ccore_i2c, gate_ccore_i2c, "gate_ccore_i2c", 0, 0, NULL),
};
static struct init_vclk exynos8890_mfc_vclks[] __initdata = {
/* MFC */
VCLK(mfc_hpm, gate_mfc_hpm, "mfc_hpm", 0, 0, NULL),
VCLK(mfc_mfc, gate_mfc_mfc, "mfc_mfc", 0, 0, NULL),
VCLK(CLK_VCLK_SYSMMU_MFC, gate_mfc_sysmmu, "mfc_sysmmu", 0, 0, NULL),
VCLK(mfc_ppmu, gate_mfc_ppmu, "mfc_ppmu", 0, 0, NULL),
};
static struct init_vclk exynos8890_mscl_vclks[] __initdata = {
/* MSCL */
VCLK(mscl_mscl0, gate_mscl_mscl0, "gate_mscl_mscl0", 0, 0, NULL),
VCLK(mscl_jpeg, gate_mscl_jpeg, "gate_mscl_jpeg", 0, 0, NULL),
VCLK(mscl_mscl1, gate_mscl_mscl1, "gate_mscl_mscl1", 0, 0, NULL),
VCLK(mscl_g2d, gate_mscl_g2d, "gate_mscl_g2d", 0, 0, NULL),
VCLK(CLK_VCLK_SYSMMU_MSCL, gate_mscl_sysmmu, "gate_mscl_sysmmu", 0, 0, NULL),
VCLK(mscl_ppmu, gate_mscl_ppmu, "gate_mscl_ppmu", 0, 0, NULL),
VCLK(mscl_bts, gate_mscl_bts, "gate_mscl_bts", 0, 0, NULL),
};
static struct init_vclk exynos8890_imem_vclks[] __initdata = {
/* IMEM */
VCLK(gate_apm, gate_imem_apm, "gate_imem_apm", 0, 0, NULL),
VCLK(gate_sss, gate_imem_sss, "gate_imem_sss", 0, 0, NULL),
VCLK(gate_gic400, gate_imem_gic400, "gate_imem_gic400", 0, 0, NULL),
VCLK(gate_rtic, gate_imem_rtic, "gate_imem_rtic", 0, 0, NULL),
VCLK(gate_mc, gate_imem_mc, "gate_imem_mc", 0, 0, NULL),
VCLK(gate_intmem, gate_imem_intmem, "gate_imem_intmem", 0, 0, NULL),
VCLK(gate_alv, gate_imem_intmem_alv, "gate_imem_intmem_alv", 0, 0, NULL),
VCLK(gate_ppmu, gate_imem_ppmu, "gate_imem_ppmu", 0, 0, NULL),
};
static struct init_vclk exynos8890_peris_vclks[] __initdata = {
/* PERIS */
VCLK(peris_sfr, gate_peris_sfr_apbif_hdmi_cec, "gate_peris_sfr_apbif_hdmi_cec", 0, 0, NULL),
VCLK(peris_hpm, gate_peris_hpm, "gate_peris_hpm", 0, 0, NULL),
VCLK(peris_mct, gate_peris_mct, "gate_peris_mct", 0, 0, NULL),
VCLK(wdt_mngs, gate_peris_wdt_mngs, "gate_peris_wdt_mngs", 0, 0, NULL),
VCLK(wdt_apollo, gate_peris_wdt_apollo, "gate_peris_wdt_apollo", 0, 0, NULL),
VCLK(rtc_apbif, gate_peris_rtc_apbif, "gate_peris_rtc_apbif", 0, 0, NULL),
VCLK(top_rtc, gate_peris_top_rtc, "gate_peris_top_rtc", 0, 0, NULL),
VCLK(otp_con_top, gate_peris_otp_con_top, "gate_peris_otp_con_top", 0, 0, NULL),
VCLK(peris_chipid, gate_peris_chipid, "gate_peris_chipid", 0, 0, NULL),
VCLK(peris_tmu, gate_peris_tmu, "gate_peris_tmu", 0, 0, NULL),
VCLK(peris_sysreg, gate_peris_sysreg_peris, "gate_peris_sysreg_peris", 0, 0, NULL),
VCLK(peris_monocnt, gate_peris_monocnt_apbif, "gate_peris_monocnt_apbif", 0, 0, NULL),
};
static struct init_vclk exynos8890_peric0_vclks[] __initdata = {
/* PERIC0 */
VCLK(gate_hsi2c0, gate_peric0_hsi2c0, "gate_peric0_hsi2c0", 0, 0, NULL),
VCLK(gate_hsi2c1, gate_peric0_hsi2c1, "gate_peric0_hsi2c1", 0, 0, NULL),
VCLK(gate_hsi2c4, gate_peric0_hsi2c4, "gate_peric0_hsi2c4", 0, 0, NULL),
VCLK(gate_hsi2c5, gate_peric0_hsi2c5, "gate_peric0_hsi2c5", 0, 0, NULL),
VCLK(gate_hsi2c9, gate_peric0_hsi2c9, "gate_peric0_hsi2c9", 0, 0, NULL),
VCLK(gate_hsi2c10, gate_peric0_hsi2c10, "gate_peric0_hsi2c10", 0, 0, NULL),
VCLK(gate_hsi2c11, gate_peric0_hsi2c11, "gate_peric0_hsi2c11", 0, 0, NULL),
VCLK(puart0, gate_peric0_uart0, "gate_peric0_uart0", 0, 0, "console-pclk0"),
VCLK(suart0, sclk_uart0, "sclk_uart0", 0, 0, "console-sclk0"),
VCLK(gate_adcif, gate_peric0_adcif, "gate_peric0_adcif", 0, 0, NULL),
VCLK(gate_pwm, gate_peric0_pwm, "gate_peric0_pwm", 0, 0, NULL),
VCLK(gate_sclk_pwm, gate_peric0_sclk_pwm, "gate_peric0_sclk_pwm", 0, 0, NULL),
};
static struct init_vclk exynos8890_peric1_vclks[] __initdata = {
/* PERIC1 HSI2C */
VCLK(gate_hsi2c2, gate_peric1_hsi2c2, "gate_hsi2c2", 0, 0, NULL),
VCLK(gate_hsi2c3, gate_peric1_hsi2c3, "gate_hsi2c3", 0, 0, NULL),
VCLK(gate_hsi2c6, gate_peric1_hsi2c6, "gate_hsi2c6", 0, 0, NULL),
VCLK(gate_hsi2c7, gate_peric1_hsi2c7, "gate_hsi2c7", 0, 0, NULL),
VCLK(gate_hsi2c8, gate_peric1_hsi2c8, "gate_hsi2c8", 0, 0, NULL),
VCLK(gate_hsi2c12, gate_peric1_hsi2c12, "gate_hsi2c12", 0, 0, NULL),
VCLK(gate_hsi2c13, gate_peric1_hsi2c13, "gate_hsi2c13", 0, 0, NULL),
VCLK(gate_hsi2c14, gate_peric1_hsi2c14, "gate_hsi2c14", 0, 0, NULL),
/* PERIC1 UART0~5 */
VCLK(gate_uart1, gate_peric1_uart1, "gate_uart1", 0, 0, "console-pclk1"),
VCLK(gate_uart2, gate_peric1_uart2, "gate_uart2", 0, 0, "console-pclk2"),
VCLK(gate_uart3, gate_peric1_uart3, "gate_uart3", 0, 0, "console-pclk3"),
VCLK(gate_uart4, gate_peric1_uart4, "gate_uart4", 0, 0, "console-pclk4"),
VCLK(gate_uart5, gate_peric1_uart5, "gate_uart5", 0, 0, "console-pclk5"),
VCLK(suart1, sclk_uart1, "sclk_uart1", 0, 0, "console-sclk1"),
VCLK(suart2, sclk_uart2, "sclk_uart2", 0, 0, "console-sclk2"),
VCLK(suart3, sclk_uart3, "sclk_uart3", 0, 0, "console-sclk3"),
VCLK(suart4, sclk_uart4, "sclk_uart4", 0, 0, "console-sclk4"),
VCLK(suart5, sclk_uart5, "sclk_uart5", 0, 0, "console-sclk5"),
/* PERIC1 SPI0~7 */
VCLK(gate_spi0, gate_peric1_spi0, "gate_spi0", 0, 0, NULL),
VCLK(gate_spi1, gate_peric1_spi1, "gate_spi1", 0, 0, NULL),
VCLK(gate_spi2, gate_peric1_spi2, "gate_spi2", 0, 0, NULL),
VCLK(gate_spi3, gate_peric1_spi3, "gate_spi3", 0, 0, NULL),
VCLK(gate_spi4, gate_peric1_spi4, "gate_spi4", 0, 0, NULL),
VCLK(gate_spi5, gate_peric1_spi5, "gate_spi5", 0, 0, NULL),
VCLK(gate_spi6, gate_peric1_spi6, "gate_spi6", 0, 0, NULL),
VCLK(gate_spi7, gate_peric1_spi7, "gate_spi7", 0, 0, NULL),
VCLK(sclk_peric1_spi0, sclk_spi0, "sclk_spi0", 0, 0, NULL),
VCLK(sclk_peric1_spi1, sclk_spi1, "sclk_spi1", 0, 0, NULL),
VCLK(sclk_peric1_spi2, sclk_spi2, "sclk_spi2", 0, 0, NULL),
VCLK(sclk_peric1_spi3, sclk_spi3, "sclk_spi3", 0, 0, NULL),
VCLK(sclk_peric1_spi4, sclk_spi4, "sclk_spi4", 0, 0, NULL),
VCLK(sclk_peric1_spi5, sclk_spi5, "sclk_spi5", 0, 0, NULL),
VCLK(sclk_peric1_spi6, sclk_spi6, "sclk_spi6", 0, 0, NULL),
VCLK(sclk_peric1_spi7, sclk_spi7, "sclk_spi7", 0, 0, NULL),
/* PERIC1 GPIO */
VCLK(gate_gpio_nfc, gate_peric1_gpio_nfc, "gate_gpio_nfc", 0, 0, NULL),
VCLK(gate_gpio_touch, gate_peric1_gpio_touch, "gate_gpio_touch", 0, 0, NULL),
VCLK(gate_gpio_fp, gate_peric1_gpio_fp, "gate_gpio_fp", 0, 0, NULL),
VCLK(gate_gpio_ese, gate_peric1_gpio_ese, "gate_gpio_ese", 0, 0, NULL),
/* PERIC1 promise */
VCLK(promise_int, sclk_promise_int, "sclk_promise_int", 0, 0, NULL),
VCLK(promise_disp, sclk_promise_disp, "sclk_promise_disp", 0, 0, NULL),
VCLK(ap2cp_mif_pll_out, sclk_ap2cp_mif_pll_out, "sclk_ap2cp_mif_pll_out", 0, 0, NULL),
VCLK(gate_i2s1, gate_peric1_i2s1, "gate_peric1_i2s1", 0, 0, NULL),
VCLK(gate_pcm1, gate_peric1_pcm1, "gate_peric1_pcm1", 0, 0, NULL),
VCLK(gate_spdif, gate_peric1_spdif, "gate_peric1_spdif", 0, 0, NULL),
};
static struct init_vclk exynos8890_isp0_vclks[] __initdata = {
/* ISP0 */
VCLK(gate_fimc_isp0, gate_isp0_fimc_isp0, "gate_fimc_isp0", 0, 0, NULL),
VCLK(gate_fimc_tpu, gate_isp0_fimc_tpu, "gate_isp0_fimc_tpu", 0, 0, NULL),
VCLK(isp0, pxmxdx_isp0_isp0, "clk_isp0", 0, 0, NULL),
VCLK(isp0_tpu, pxmxdx_isp0_tpu, "clk_isp0_tpu", 0, 0, NULL),
VCLK(isp0_trex, pxmxdx_isp0_trex, "clk_isp0_trex", 0, 0, NULL),
VCLK(CLK_VCLK_SYSMMU_ISP0, gate_isp0_sysmmu, "gate_isp0_sysmmu", 0, 0, NULL),
VCLK(isp0_ppmu, gate_isp0_ppmu, "gate_isp0_ppmu", 0, 0, NULL),
VCLK(isp0_bts, gate_isp0_bts, "gate_isp0_bts", 0, 0, NULL),
};
static struct init_vclk exynos8890_isp1_vclks[] __initdata = {
/* ISP1 */
VCLK(gate_fimc_isp1, gate_isp1_fimc_isp1, "gate_isp1_fimc_isp1", 0, 0, NULL),
VCLK(isp1, pxmxdx_isp1_isp1, "clk_isp1", 0, 0, NULL),
VCLK(isp1_ppmu, gate_isp1_ppmu, "gate_isp1_ppmu", 0, 0, NULL),
VCLK(isp1_bts, gate_isp1_bts, "gate_isp1_bts", 0, 0, NULL),
};
static struct init_vclk exynos8890_isp_sensor_vclks[] __initdata = {
/* ISP1 */
VCLK(isp_sensor0, sclk_isp_sensor0, "sclk_isp_sensor0", 0, 0, NULL),
VCLK(isp_sensor1, sclk_isp_sensor1, "sclk_isp_sensor1", 0, 0, NULL),
VCLK(isp_sensor2, sclk_isp_sensor2, "sclk_isp_sensor2", 0, 0, NULL),
VCLK(isp_sensor3, sclk_isp_sensor3, "sclk_isp_sensor3", 0, 0, NULL),
};
static struct init_vclk exynos8890_cam0_vclks[] __initdata = {
/* CAM0 */
VCLK(gate_csis0, gate_cam0_csis0, "gate_cam0_csis0", 0, 0, NULL),
VCLK(gate_csis1, gate_cam0_csis1, "gate_cam0_csis1", 0, 0, NULL),
VCLK(gate_fimc_bns, gate_cam0_fimc_bns, "gate_cam0_fimc_bns", 0, 0, NULL),
VCLK(fimc_3aa0, gate_cam0_fimc_3aa0, "gate_cam0_fimc_3aa0", 0, 0, NULL),
VCLK(fimc_3aa1, gate_cam0_fimc_3aa1, "gate_cam0_fimc_3aa1", 0, 0, NULL),
VCLK(cam0_hpm, gate_cam0_hpm, "gate_cam0_hpm", 0, 0, NULL),
VCLK(pxmxdx_csis0, pxmxdx_cam0_csis0, "gate_pxmxdx_cam0_csis0", 0, 0, NULL),
VCLK(pxmxdx_csis1, pxmxdx_cam0_csis1, "gate_pxmxdx_cam0_csis1", 0, 0, NULL),
VCLK(pxmxdx_csis2, pxmxdx_cam0_csis2, "gate_pxmxdx_cam0_csis2", 0, 0, NULL),
VCLK(pxmxdx_csis3, pxmxdx_cam0_csis3, "gate_pxmxdx_cam0_csis3", 0, 0, NULL),
VCLK(pxmxdx_3aa0, pxmxdx_cam0_3aa0, "gate_pxmxdx_cam0_3aa0", 0, 0, NULL),
VCLK(pxmxdx_3aa1, pxmxdx_cam0_3aa1, "gate_pxmxdx_cam0_3aa1", 0, 0, NULL),
VCLK(pxmxdx_trex, pxmxdx_cam0_trex, "gate_pxmxdx_cam0_trex", 0, 0, NULL),
VCLK(hs0_csis0_rx_byte, umux_cam0_phyclk_rxbyteclkhs0_csis0_user, "umux_cam0_phyclk_rxbyteclkhs0_csis0_user", 0, 0, NULL),
VCLK(hs1_csis0_rx_byte, umux_cam0_phyclk_rxbyteclkhs1_csis0_user, "umux_cam0_phyclk_rxbyteclkhs1_csis0_user", 0, 0, NULL),
VCLK(hs2_csis0_rx_byte, umux_cam0_phyclk_rxbyteclkhs2_csis0_user, "umux_cam0_phyclk_rxbyteclkhs2_csis0_user", 0, 0, NULL),
VCLK(hs3_csis0_rx_byte, umux_cam0_phyclk_rxbyteclkhs3_csis0_user, "umux_cam0_phyclk_rxbyteclkhs3_csis0_user", 0, 0, NULL),
VCLK(hs0_csis1_rx_byte, umux_cam0_phyclk_rxbyteclkhs0_csis1_user, "umux_cam0_phyclk_rxbyteclkhs0_csis1_user", 0, 0, NULL),
VCLK(hs1_csis1_rx_byte, umux_cam0_phyclk_rxbyteclkhs1_csis1_user, "umux_cam0_phyclk_rxbyteclkhs1_csis1_user", 0, 0, NULL),
VCLK(CLK_VCLK_SYSMMU_CAM0, gate_cam0_sysmmu, "gate_cam0_sysmmu", 0, 0, NULL),
VCLK(cam0_ppmu, gate_cam0_ppmu, "gate_cam0_ppmu", 0, 0, NULL),
VCLK(cam0_bts, gate_cam0_bts, "gate_cam0_bts", 0, 0, NULL),
};
static struct init_vclk exynos8890_cam1_vclks[] __initdata = {
/* CAM1 */
VCLK(gate_isp_cpu, gate_cam1_isp_cpu, "gate_cam1_isp_cpu", 0, 0, NULL),
VCLK(gate_csis2, gate_cam1_csis2, "gate_cam1_csis2", 0, 0, NULL),
VCLK(gate_csis3, gate_cam1_csis3, "gate_cam1_csis3", 0, 0, NULL),
VCLK(gate_fimc_vra, gate_cam1_fimc_vra, "gate_cam1_fimc_vra", 0, 0, NULL),
VCLK(gate_mc_scaler, gate_cam1_mc_scaler, "gate_cam1_mc_scaler", 0, 0, NULL),
VCLK(gate_i2c0_isp, gate_cam1_i2c0_isp, "gate_cam1_i2c0_isp", 0, 0, NULL),
VCLK(gate_i2c1_isp, gate_cam1_i2c1_isp, "gate_cam1_i2c1_isp", 0, 0, NULL),
VCLK(gate_i2c2_isp, gate_cam1_i2c2_isp, "gate_cam1_i2c2_isp", 0, 0, NULL),
VCLK(gate_i2c3_isp, gate_cam1_i2c3_isp, "gate_cam1_i2c3_isp", 0, 0, NULL),
VCLK(gate_wdt_isp, gate_cam1_wdt_isp, "gate_cam1_wdt_isp", 0, 0, NULL),
VCLK(gate_mcuctl_isp, gate_cam1_mcuctl_isp, "gate_cam1_mcuctl_isp", 0, 0, NULL),
VCLK(gate_uart_isp, gate_cam1_uart_isp, "gate_cam1_uart_isp", 0, 0, NULL),
VCLK(gate_pdma_isp, gate_cam1_pdma_isp, "gate_cam1_pdma_isp", 0, 0, NULL),
VCLK(gate_pwm_isp, gate_cam1_pwm_isp, "gate_cam1_pwm_isp", 0, 0, NULL),
VCLK(gate_spi0_isp, gate_cam1_spi0_isp, "gate_cam1_spi0_isp", 0, 0, NULL),
VCLK(gate_spi1_isp, gate_cam1_spi1_isp, "gate_cam1_spi1_isp", 0, 0, NULL),
/* rate clock source */
VCLK(isp_spi0, sclk_isp_spi0, "sclk_isp_spi0", 0, 0, NULL),
VCLK(isp_spi1, sclk_isp_spi1, "sclk_isp_spi1", 0, 0, NULL),
VCLK(isp_uart, sclk_isp_uart, "sclk_isp_uart", 0, 0, NULL),
VCLK(gate_sclk_pwm_isp, gate_cam1_sclk_pwm_isp, "gate_cam1_sclk_pwm_isp", 0, 0, NULL),
VCLK(gate_sclk_uart_isp, gate_cam1_sclk_uart_isp, "gate_cam1_sclk_uart_isp", 0, 0, NULL),
/* rate clock source */
VCLK(cam1_arm, pxmxdx_cam1_arm, "pxmxdx_cam1_arm", 0, 0, NULL),
VCLK(cam1_vra, pxmxdx_cam1_vra, "pxmxdx_cam1_vra", 0, 0, NULL),
VCLK(cam1_trex, pxmxdx_cam1_trex, "pxmxdx_cam1_trex", 0, 0, NULL),
VCLK(cam1_bus, pxmxdx_cam1_bus, "pxmxdx_cam1_bus", 0, 0, NULL),
VCLK(cam1_peri, pxmxdx_cam1_peri, "pxmxdx_cam1_peri", 0, 0, NULL),
VCLK(cam1_csis2, pxmxdx_cam1_csis2, "pxmxdx_cam1_csis2", 0, 0, NULL),
VCLK(cam1_csis3, pxmxdx_cam1_csis3, "pxmxdx_cam1_csis3", 0, 0, NULL),
VCLK(cam1_scl, pxmxdx_cam1_scl, "pxmxdx_cam1_scl", 0, 0, NULL),
/* usermux */
VCLK(cam1_phy0_csis2, umux_cam1_phyclk_rxbyteclkhs0_csis2_user, "phyclk_rxbyteclkhs0_csis2_user", 0, 0, NULL),
VCLK(cam1_phy1_csis2, umux_cam1_phyclk_rxbyteclkhs1_csis2_user, "phyclk_rxbyteclkhs1_csis2_user", 0, 0, NULL),
VCLK(cam1_phy2_csis2, umux_cam1_phyclk_rxbyteclkhs2_csis2_user, "phyclk_rxbyteclkhs2_csis2_user", 0, 0, NULL),
VCLK(cam1_phy3_csis2, umux_cam1_phyclk_rxbyteclkhs3_csis2_user, "phyclk_rxbyteclkhs3_csis2_user", 0, 0, NULL),
VCLK(cam1_phy0_csis3, umux_cam1_phyclk_rxbyteclkhs0_csis3_user, "phyclk_rxbyteclkhs0_csis3_user", 0, 0, NULL),
VCLK(CLK_VCLK_SYSMMU_CAM1, gate_cam1_sysmmu, "gate_cam1_sysmmu", 0, 0, NULL),
VCLK(cam1_ppmu, gate_cam1_ppmu, "gate_cam1_ppmu", 0, 0, NULL),
VCLK(cam1_bts, gate_cam1_bts, "gate_cam1_bts", 0, 0, NULL),
};
static struct init_vclk exynos8890_audio_vclks[] __initdata = {
/* AUDIO */
VCLK(gate_mi2s, gate_aud_mi2s, "gate_aud_mi2s", 0, 0, NULL),
VCLK(gate_pcm, gate_aud_pcm, "gate_aud_pcm", 0, 0, NULL),
VCLK(gate_slimbus, gate_aud_slimbus, "gate_aud_slimbus", 0, 0, NULL),
VCLK(gate_sclk_mi2s, gate_aud_sclk_mi2s, "gate_aud_sclk_mi2s", 0, 0, NULL),
VCLK(d1_sclk_i2s, d1_sclk_i2s_local, "dout_sclk_i2s_local", 0, 0, NULL),
VCLK(gate_sclk_pcm, gate_aud_sclk_pcm, "gate_aud_sclk_pcm", 0, 0, NULL),
VCLK(d1_sclk_pcm, d1_sclk_pcm_local, "dout_sclk_pcm_local", 0, 0, NULL),
VCLK(gate_sclk_slimbus, gate_aud_sclk_slimbus, "gate_aud_sclk_slimbus", 0, 0, NULL),
VCLK(sclk_slimbus, d1_sclk_slimbus, "dout_sclk_slimbus", 0, 0, NULL),
VCLK(sclk_cp_i2s, d1_sclk_cp_i2s, "dout_sclk_cp_i2s", 0, 0, NULL),
VCLK(sclk_asrc, d1_sclk_asrc, "dout_sclk_asrc", 0, 0, NULL),
VCLK(aud_pll, p1_aud_pll, "sclk_aud_pll", 0, 0, NULL),
VCLK(aud_cp, pxmxdx_aud_cp, "gate_aud_cp", 0, 0, NULL),
VCLK(aud_lpass, gate_aud_lpass, "gate_aud_lpass", 0, 0, NULL),
VCLK(aud_dma, gate_aud_dma, "gate_aud_dma", 0, 0, NULL),
VCLK(CLK_VCLK_SYSMMU_AUD, gate_aud_sysmmu, "gate_aud_sysmmu", 0, 0, NULL),
VCLK(aud_ppmu, gate_aud_ppmu, "gate_aud_ppmu", 0, 0, NULL),
VCLK(aud_bts, gate_aud_bts, "gate_aud_bts", 0, 0, NULL),
};
static struct init_vclk exynos8890_fsys0_vclks[] __initdata = {
/* FSYS0 */
VCLK(gate_usbdrd30, gate_fsys0_usbdrd30, "gate_fsys0_usbdrd30", 0, 0, NULL),
VCLK(gate_usbhost20, gate_fsys0_usbhost20, "gate_fsys0_usbhost20", 0, 0, NULL),
VCLK(usbdrd30, sclk_usbdrd30, "sclk_usbdrd30", 0, 0, NULL),
VCLK(sclk_fsys0_mmc0, sclk_mmc0, "sclk_mmc0", 0, 0, NULL),
VCLK(ufsunipro20, sclk_ufsunipro20, "sclk_ufsunipro20", 0, 0, NULL),
VCLK(phy24m, sclk_phy24m, "sclk_phy24m", 0, 0, NULL),
VCLK(ufsunipro_cfg, sclk_ufsunipro_cfg, "sclk_ufsunipro_cfg", 0, 0, NULL),
/* UMUX GATE related clock sources */
VCLK(gate_udrd30_phyclock, umux_fsys0_phyclk_usbdrd30_udrd30_phyclock_user, "umux_fsys0_phyclk_usbdrd30_udrd30_phyclock_user", 0, 0, NULL),
VCLK(gate_udrd30_pipe, umux_fsys0_phyclk_usbdrd30_udrd30_pipe_pclk_user, "umux_fsys0_phyclk_usbdrd30_udrd30_pipe_pclk_user", 0, 0, NULL),
VCLK(gate_ufs_tx0, umux_fsys0_phyclk_ufs_tx0_symbol_user, "umux_fsys0_phyclk_ufs_tx0_symbol_user", 0, 0, NULL),
VCLK(gate_ufs_rx0, umux_fsys0_phyclk_ufs_rx0_symbol_user, "umux_fsys0_phyclk_ufs_rx0_symbol_user", 0, 0, NULL),
VCLK(usbhost20_phyclock, umux_fsys0_phyclk_usbhost20_phyclock_user, "umux_fsys0_phyclk_usbhost20_phyclock_user", 0, 0, NULL),
VCLK(usbhost20_freeclk, umux_fsys0_phyclk_usbhost20_freeclk_user, "umux_fsys0_phyclk_usbhost20_freeclk_user", 0, 0, NULL),
VCLK(usbhost20_clk48, umux_fsys0_phyclk_usbhost20_clk48mohci_user, "umux_fsys0_phyclk_usbhost20_clk48mohci_user", 0, 0, NULL),
VCLK(usbhost20phy_ref, umux_fsys0_phyclk_usbhost20phy_ref_clk, "umux_fsys0_phyclk_usbhost20phy_ref_clk", 0, 0, NULL),
VCLK(ufs_rx_pwm, umux_fsys0_phyclk_ufs_rx_pwm_clk_user, "umux_fsys0_phyclk_ufs_rx_pwm_clk_user", 0, 0, NULL),
VCLK(ufs_tx_pwm, umux_fsys0_phyclk_ufs_tx_pwm_clk_user, "umux_fsys0_phyclk_ufs_tx_pwm_clk_user", 0, 0, NULL),
VCLK(ufs_refclk_out, umux_fsys0_phyclk_ufs_refclk_out_soc_user, "umux_fsys0_phyclk_ufs_refclk_out_soc_user", 0, 0, NULL),
VCLK(fsys_200, pxmxdx_fsys0, "aclk_ufs", 0, 0, NULL),
VCLK(fsys0_etr_usb, gate_fsys0_etr_usb, "gate_fsys0_etr_usb", 0, 0, "etr_clk"),
VCLK(gate_mmc, gate_fsys0_mmc0, "gate_fsys0_mmc0", 0, 0, NULL),
VCLK(gate_pdma0, gate_fsys0_pdma0, "gate_fsys0_pdma0", 0, 0, NULL),
VCLK(gate_pdmas, gate_fsys0_pdmas, "gate_fsys0_pdmas", 0, 0, NULL),
VCLK(gate_ufs_linkemedded, gate_fsys0_ufs_linkemedded, "gate_fsys0_ufs_linkemedded", 0, 0, NULL),
};
static struct init_vclk exynos8890_fsys1_vclks[] __initdata = {
/* FSYS1 */
VCLK(fsys1_hpm, gate_fsys1_hpm, "gate_fsys1_hpm", 0, 0, NULL),
VCLK(fsys1_sclk_mmc2, sclk_mmc2, "sclk_mmc2", 0, 0, NULL),
VCLK(ufsunipro20_sdcard, sclk_ufsunipro20_sdcard, "sclk_ufsunipro20_sdcard", 0, 0, NULL),
VCLK(pcie_phy, sclk_pcie_phy, "sclk_pcie_phy", 0, 0, NULL),
VCLK(sclk_ufsunipro_sdcard, sclk_ufsunipro_sdcard_cfg, "sclk_ufsunipro_sdcard_cfg", 0, 0, NULL),
/* UMUX GATE related clock sources */
VCLK(ufs_link_sdcard_tx0, umux_fsys1_phyclk_ufs_link_sdcard_tx0_symbol_user, "umux_fsys1_phyclk_ufs_link_sdcard_tx0_symbol_user", 0, 0, NULL),
VCLK(ufs_link_sdcard_rx0, umux_fsys1_phyclk_ufs_link_sdcard_rx0_symbol_user, "umux_fsys1_phyclk_ufs_link_sdcard_rx0_symbol_user", 0, 0, NULL),
VCLK(pcie_wifi0_tx0, umux_fsys1_phyclk_pcie_wifi0_tx0_user, "umux_fsys1_phyclk_pcie_wifi0_tx0_user", 0, 0, NULL),
VCLK(pcie_wifi0_rx0, umux_fsys1_phyclk_pcie_wifi0_rx0_user, "umux_fsys1_phyclk_pcie_wifi0_rx0_user", 0, 0, NULL),
VCLK(pcie_wifi1_tx0, umux_fsys1_phyclk_pcie_wifi1_tx0_user, "umux_fsys1_phyclk_pcie_wifi1_tx0_user", 0, 0, NULL),
VCLK(pcie_wifi1_rx0, umux_fsys1_phyclk_pcie_wifi1_rx0_user, "umux_fsys1_phyclk_pcie_wifi1_rx0_user", 0, 0, NULL),
VCLK(wifi0_dig_refclk, umux_fsys1_phyclk_pcie_wifi0_dig_refclk_user, "umux_fsys1_phyclk_pcie_wifi0_dig_refclk_user", 0, 0, NULL),
VCLK(wifi1_dig_refclk, umux_fsys1_phyclk_pcie_wifi1_dig_refclk_user, "umux_fsys1_phyclk_pcie_wifi1_dig_refclk_user", 0, 0, NULL),
VCLK(sdcard_rx_pwm, umux_fsys1_phyclk_ufs_link_sdcard_rx_pwm_clk_user, "umux_fsys1_phyclk_ufs_link_sdcard_rx_pwm_clk_user", 0, 0, NULL),
VCLK(sdcard_tx_pwm, umux_fsys1_phyclk_ufs_link_sdcard_tx_pwm_clk_user, "umux_fsys1_phyclk_ufs_link_sdcard_tx_pwm_clk_user", 0, 0, NULL),
VCLK(sdcard_refclk, umux_fsys1_phyclk_ufs_link_sdcard_refclk_out_soc_user, "umux_fsys1_phyclk_ufs_link_sdcard_refclk_out_soc_user", 0, 0, NULL),
VCLK(gate_mmc2, gate_fsys1_mmc2, "gate_fsys1_mmc2", 0, 0, NULL),
VCLK(gate_ufs20_sdcard, gate_fsys1_ufs20_sdcard, "gate_fsys1_ufs20_sdcard", 0, 0, NULL),
VCLK(gate_sromc, gate_fsys1_sromc, "gate_fsys1_sromc", 0, 0, NULL),
VCLK(gate_pciewifi0, gate_fsys1_pciewifi0, "gate_fsys1_pciewifi0", 0, 0, NULL),
VCLK(gate_pciewifi1, gate_fsys1_pciewifi1, "gate_fsys1_pciewifi1", 0, 0, NULL),
VCLK(fsys1_ppmu, gate_fsys1_ppmu, "gate_fsys1_ppmu", 0, 0, NULL),
VCLK(fsys1_bts, gate_fsys1_bts, "gate_fsys1_bts", 0, 0, NULL),
};
static struct init_vclk exynos8890_g3d_vclks[] __initdata = {
/* G3D */
VCLK(gate_g3d, gate_g3d_g3d, "gate_g3d_g3d", 0, 0, "vclk_g3d"),
VCLK(gate_g3d_iram, gate_g3d_iram_path_test, "g3d_iram_path", 0, 0, NULL),
VCLK(g3d_bts, gate_g3d_bts, "gate_g3d_bts", 0, 0, NULL),
VCLK(g3d_ppmu, gate_g3d_ppmu, "gate_g3d_ppmu", 0, 0, NULL),
};
static struct init_vclk exynos8890_disp0_vclks[] __initdata = {
/* DISP0 */
VCLK(gate_decon0, gate_disp0_decon0, "gate_disp0_decon0", 0, 0, NULL),
VCLK(gate_dsim0, gate_disp0_dsim0, "gate_disp0_dsim0", 0, 0, NULL),
VCLK(gate_dsim1, gate_disp0_dsim1, "gate_disp0_dsim1", 0, 0, NULL),
VCLK(gate_dsim2, gate_disp0_dsim2, "gate_disp0_dsim2", 0, 0, NULL),
VCLK(gate_hdmi, gate_disp0_hdmi, "gate_disp0_hdmi", 0, 0, NULL),
VCLK(gate_dp, gate_disp0_dp, "gate_disp0_dp", 0, 0, NULL),
VCLK(gate_hpm_apbif_disp0, gate_disp0_hpm_apbif_disp0, "gate_disp0_hpm_apbif_disp0", 0, 0, NULL),
/* special clock - sclk */
VCLK(decon0_eclk0, sclk_decon0_eclk0, "sclk_decon0_eclk0", 0, 0, NULL),
VCLK(decon0_vclk0, sclk_decon0_vclk0, "sclk_decon0_vclk0", 0, 0, NULL),
VCLK(decon0_vclk1, sclk_decon0_vclk1, "sclk_decon0_vclk1", 0, 0, NULL),
VCLK(decon0_eclk0_local, sclk_decon0_eclk0_local, "sclk_decon0_eclk0_local", 0, 0, NULL),
VCLK(decon0_vclk0_local, sclk_decon0_vclk0_local, "sclk_decon0_vclk0_local", 0, 0, NULL),
VCLK(decon0_vclk1_local, sclk_decon0_vclk1_local, "sclk_decon0_vclk1_local", 0, 0, NULL),
VCLK(hdmi_audio, sclk_hdmi_audio, "sclk_hdmi_audio", 0, 0, NULL),
/* PLL clock source */
VCLK(disp_pll, p1_disp_pll, "p1_disp_pll", 0, 0, "disp_pll"),
/* USERMUX related clock source */
VCLK(mipidphy0_rxclkesc0, umux_disp0_phyclk_mipidphy0_rxclkesc0_user, "umux_disp0_phyclk_mipidphy0_rxclkesc0_user", 0, 0, NULL),
VCLK(mipidphy0_bitclkdiv8, umux_disp0_phyclk_mipidphy0_bitclkdiv8_user, "umux_disp0_phyclk_mipidphy0_bitclkdiv8_user", 0, 0, NULL),
VCLK(mipidphy1_rxclkesc0, umux_disp0_phyclk_mipidphy1_rxclkesc0_user, "umux_disp0_phyclk_mipidphy1_rxclkesc0_user", 0, 0, NULL),
VCLK(mipidphy1_bitclkdiv8, umux_disp0_phyclk_mipidphy1_bitclkdiv8_user, "umux_disp0_phyclk_mipidphy1_bitclkdiv8_user", 0, 0, NULL),
VCLK(mipidphy2_rxclkesc0, umux_disp0_phyclk_mipidphy2_rxclkesc0_user, "umux_disp0_phyclk_mipidphy2_rxclkesc0_user", 0, 0, NULL),
VCLK(mipidphy2_bitclkdiv8, umux_disp0_phyclk_mipidphy2_bitclkdiv8_user, "umux_disp0_phyclk_mipidphy2_bitclkdiv8_user", 0, 0, NULL),
VCLK(dpphy_ch0_txd, umux_disp0_phyclk_dpphy_ch0_txd_clk_user, "umux_disp0_phyclk_dpphy_ch0_txd_clk_user", 0, 0, NULL),
VCLK(dpphy_ch1_txd, umux_disp0_phyclk_dpphy_ch1_txd_clk_user, "umux_disp0_phyclk_dpphy_ch1_txd_clk_user", 0, 0, NULL),
VCLK(dpphy_ch2_txd, umux_disp0_phyclk_dpphy_ch2_txd_clk_user, "umux_disp0_phyclk_dpphy_ch2_txd_clk_user", 0, 0, NULL),
VCLK(dpphy_ch3_txd, umux_disp0_phyclk_dpphy_ch3_txd_clk_user, "umux_disp0_phyclk_dpphy_ch3_txd_clk_user", 0, 0, NULL),
VCLK(dptx_phy_i_ref_clk_24m, gate_disp0_oscclk_i_dptx_phy_i_ref_clk_24m, "gate_disp0_oscclk_i_dptx_phy_i_ref_clk_24m", 0, 0, NULL),
VCLK(mipi_dphy_m1s0, gate_disp0_oscclk_i_mipi_dphy_m1s0_m_xi, "gate_disp0_oscclk_i_mipi_dphy_m1s0_m_xi", 0, 0, NULL),
VCLK(mipi_dphy_m4s0, gate_disp0_oscclk_i_mipi_dphy_m4s0_m_xi, "gate_disp0_oscclk_i_mipi_dphy_m4s0_m_xi", 0, 0, NULL),
VCLK(mipi_dphy_m4s4, gate_disp0_oscclk_i_mipi_dphy_m4s4_m_xi, "gate_disp0_oscclk_i_mipi_dphy_m4s4_m_xi", 0, 0, NULL),
VCLK(phyclk_hdmiphy_tmds_20b, umux_disp0_phyclk_hdmiphy_tmds_clko_user, "umux_disp0_phyclk_hdmiphy_tmds_clko_user", 0, 0, NULL),
VCLK(phyclk_hdmiphy_pixel, umux_disp0_phyclk_hdmiphy_pixel_clko_user, "umux_disp0_phyclk_hdmiphy_pixel_clko_user", 0, 0, NULL),
VCLK(mipidphy0_bitclkdiv2_user, umux_disp0_phyclk_mipidphy0_bitclkdiv2_user, "umux_disp0_phyclk_mipidphy0_bitclkdiv2_user", 0, 0, NULL),
VCLK(mipidphy1_bitclkdiv2_user, umux_disp0_phyclk_mipidphy1_bitclkdiv2_user, "umux_disp0_phyclk_mipidphy1_bitclkdiv2_user", 0, 0, NULL),
VCLK(mipidphy2_bitclkdiv2_user, umux_disp0_phyclk_mipidphy2_bitclkdiv2_user, "umux_disp0_phyclk_mipidphy2_bitclkdiv2_user", 0, 0, NULL),
VCLK(CLK_VCLK_SYSMMU_DISP0, gate_disp0_sysmmu, "gate_disp0_sysmmu", 0, 0, NULL),
};
static struct init_vclk exynos8890_disp1_vclks[] __initdata = {
/* DISP1 */
VCLK(gate_decon1, gate_disp1_decon1, "gate_disp1_decon1", 0, 0, NULL),
VCLK(gate_hpmdisp1, gate_disp1_hpmdisp1, "gate_disp1_hpmdisp1", 0, 0, NULL),
/* special clock - sclk */
VCLK(decon1_eclk0, sclk_decon1_eclk0, "sclk_decon1_eclk0", 0, 0, NULL),
VCLK(decon1_eclk1, sclk_decon1_eclk1, "sclk_decon1_eclk1", 0, 0, NULL),
VCLK(decon1_eclk0_local, sclk_decon1_eclk0_local, "sclk_decon1_eclk0_local", 0, 0, NULL),
VCLK(decon1_eclk1_local, sclk_decon1_eclk1_local, "sclk_decon1_eclk1_local", 0, 0, NULL),
/* USERMUX related clock source */
VCLK(disp1_phyclk_mipidphy0_bitclkdiv2_user, umux_disp1_phyclk_mipidphy0_bitclkdiv2_user, "umux_disp1_phyclk_mipidphy0_bitclkdiv2_user", 0, 0, NULL),
VCLK(disp1_phyclk_mipidphy1_bitclkdiv2_user, umux_disp1_phyclk_mipidphy1_bitclkdiv2_user, "umux_disp1_phyclk_mipidphy1_bitclkdiv2_user", 0, 0, NULL),
VCLK(disp1_phyclk_mipidphy2_bitclkdiv2_user, umux_disp1_phyclk_mipidphy2_bitclkdiv2_user, "umux_disp1_phyclk_mipidphy2_bitclkdiv2_user", 0, 0, NULL),
VCLK(disp1_phyclk_disp1_hdmiphy_pixel_clko_user, umux_disp1_phyclk_disp1_hdmiphy_pixel_clko_user, "umux_disp1_phyclk_disp1_hdmiphy_pixel_clko_user", 0, 0, NULL),
VCLK(CLK_VCLK_SYSMMU_DISP1, gate_disp1_sysmmu, "gate_disp1_sysmmu", 0, 0, NULL),
VCLK(disp1_ppmu, gate_disp1_ppmu, "gate_disp1_ppmu", 0, 0, NULL),
VCLK(disp1_bts, gate_disp1_bts, "gate_disp1_bts", 0, 0, NULL),
};
void __init exynos8890_clk_init(struct device_node *np)
{
struct samsung_clk_provider *ctx;
void __iomem *reg_base;
int ret;
BUILD_BUG_ON(mscl_jpeg != CLK_GATE_SMFC);
if (np) {
reg_base = of_iomap(np, 0);
if (!reg_base)
panic("%s: failed to map registers\n", __func__);
} else {
panic("%s: unable to determine soc\n", __func__);
}
#if defined(CONFIG_ECT)
ect_parse_binary_header();
#endif
ret = cal_init();
if (ret)
pr_err("%s: unable to initialize power cal\n", __func__);
ctx = samsung_clk_init(np, reg_base, nr_clks);
if (!ctx)
panic("%s: unable to allocate context.\n", __func__);
samsung_register_of_fixed_ext(ctx, exynos8890_fixed_rate_ext_clks,
ARRAY_SIZE(exynos8890_fixed_rate_ext_clks),
ext_clk_match);
/* Regist clock local IP */
samsung_register_vclk(ctx, exynos8890_audio_vclks, ARRAY_SIZE(exynos8890_audio_vclks));
samsung_register_vclk(ctx, exynos8890_cam0_vclks, ARRAY_SIZE(exynos8890_cam0_vclks));
samsung_register_vclk(ctx, exynos8890_cam1_vclks, ARRAY_SIZE(exynos8890_cam1_vclks));
samsung_register_vclk(ctx, exynos8890_disp0_vclks, ARRAY_SIZE(exynos8890_disp0_vclks));
samsung_register_vclk(ctx, exynos8890_disp1_vclks, ARRAY_SIZE(exynos8890_disp1_vclks));
samsung_register_vclk(ctx, exynos8890_fsys0_vclks, ARRAY_SIZE(exynos8890_fsys0_vclks));
samsung_register_vclk(ctx, exynos8890_fsys1_vclks, ARRAY_SIZE(exynos8890_fsys1_vclks));
samsung_register_vclk(ctx, exynos8890_g3d_vclks, ARRAY_SIZE(exynos8890_g3d_vclks));
samsung_register_vclk(ctx, exynos8890_imem_vclks, ARRAY_SIZE(exynos8890_imem_vclks));
samsung_register_vclk(ctx, exynos8890_isp0_vclks, ARRAY_SIZE(exynos8890_isp0_vclks));
samsung_register_vclk(ctx, exynos8890_isp1_vclks, ARRAY_SIZE(exynos8890_isp1_vclks));
samsung_register_vclk(ctx, exynos8890_isp_sensor_vclks, ARRAY_SIZE(exynos8890_isp1_vclks));
samsung_register_vclk(ctx, exynos8890_mfc_vclks, ARRAY_SIZE(exynos8890_mfc_vclks));
samsung_register_vclk(ctx, exynos8890_mscl_vclks, ARRAY_SIZE(exynos8890_mscl_vclks));
samsung_register_vclk(ctx, exynos8890_peric0_vclks, ARRAY_SIZE(exynos8890_peric0_vclks));
samsung_register_vclk(ctx, exynos8890_peric1_vclks, ARRAY_SIZE(exynos8890_peric1_vclks));
samsung_register_vclk(ctx, exynos8890_peris_vclks, ARRAY_SIZE(exynos8890_peris_vclks));
samsung_register_vclk(ctx, exynos8890_ccore_vclks, ARRAY_SIZE(exynos8890_ccore_vclks));
samsung_register_vclk(ctx, exynos8890_clkout_vclks, ARRAY_SIZE(exynos8890_clkout_vclks));
samsung_clk_of_add_provider(np, ctx);
clk_register_fixed_factor(NULL, "pwm-clock", "gate_peric0_pwm",CLK_SET_RATE_PARENT, 1, 1);
pr_info("EXYNOS8890: Clock setup completed\n");
}
CLK_OF_DECLARE(exynos8890_clks, "samsung,exynos8890-clock", exynos8890_clk_init);

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,104 @@
/*
* Copyright (c) 2013 Samsung Electronics Co., Ltd.
* Copyright (c) 2013 Linaro Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Common Clock Framework support for all PLL's in Samsung platforms
*/
#ifndef __SAMSUNG_CLK_PLL_H
#define __SAMSUNG_CLK_PLL_H
enum samsung_pll_type {
pll_2126,
pll_3000,
pll_35xx,
pll_36xx,
pll_2550,
pll_2650,
pll_4500,
pll_4502,
pll_4508,
pll_4600,
pll_4650,
pll_4650c,
pll_6552,
pll_6552_s3c2416,
pll_6553,
pll_s3c2410_mpll,
pll_s3c2410_upll,
pll_s3c2440_mpll,
pll_2550xx,
pll_2650xx,
};
#define PLL_35XX_RATE(_rate, _m, _p, _s) \
{ \
.rate = (_rate), \
.mdiv = (_m), \
.pdiv = (_p), \
.sdiv = (_s), \
}
#define PLL_36XX_RATE(_rate, _m, _p, _s, _k) \
{ \
.rate = (_rate), \
.mdiv = (_m), \
.pdiv = (_p), \
.sdiv = (_s), \
.kdiv = (_k), \
}
#define PLL_45XX_RATE(_rate, _m, _p, _s, _afc) \
{ \
.rate = (_rate), \
.mdiv = (_m), \
.pdiv = (_p), \
.sdiv = (_s), \
.afc = (_afc), \
}
#define PLL_4600_RATE(_rate, _m, _p, _s, _k, _vsel) \
{ \
.rate = (_rate), \
.mdiv = (_m), \
.pdiv = (_p), \
.sdiv = (_s), \
.kdiv = (_k), \
.vsel = (_vsel), \
}
#define PLL_4650_RATE(_rate, _m, _p, _s, _k, _mfr, _mrr, _vsel) \
{ \
.rate = (_rate), \
.mdiv = (_m), \
.pdiv = (_p), \
.sdiv = (_s), \
.kdiv = (_k), \
.mfr = (_mfr), \
.mrr = (_mrr), \
.vsel = (_vsel), \
}
/* NOTE: Rate table should be kept sorted in descending order. */
struct samsung_pll_rate_table {
unsigned int rate;
unsigned int pdiv;
unsigned int mdiv;
unsigned int sdiv;
unsigned int kdiv;
unsigned int afc;
unsigned int mfr;
unsigned int mrr;
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 */

View file

@ -0,0 +1,439 @@
/*
* Copyright (c) 2013 Heiko Stuebner <heiko@sntech.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Common Clock Framework support for s3c24xx external clock output.
*/
#include <linux/platform_device.h>
#include <linux/module.h>
#include "clk.h"
/* legacy access to misccr, until dt conversion is finished */
#include <mach/hardware.h>
#include <mach/regs-gpio.h>
#define MUX_DCLK0 0
#define MUX_DCLK1 1
#define DIV_DCLK0 2
#define DIV_DCLK1 3
#define GATE_DCLK0 4
#define GATE_DCLK1 5
#define MUX_CLKOUT0 6
#define MUX_CLKOUT1 7
#define DCLK_MAX_CLKS (MUX_CLKOUT1 + 1)
enum supported_socs {
S3C2410,
S3C2412,
S3C2440,
S3C2443,
};
struct s3c24xx_dclk_drv_data {
const char **clkout0_parent_names;
int clkout0_num_parents;
const char **clkout1_parent_names;
int clkout1_num_parents;
const char **mux_parent_names;
int mux_num_parents;
};
/*
* Clock for output-parent selection in misccr
*/
struct s3c24xx_clkout {
struct clk_hw hw;
u32 mask;
u8 shift;
};
#define to_s3c24xx_clkout(_hw) container_of(_hw, struct s3c24xx_clkout, hw)
static u8 s3c24xx_clkout_get_parent(struct clk_hw *hw)
{
struct s3c24xx_clkout *clkout = to_s3c24xx_clkout(hw);
int num_parents = __clk_get_num_parents(hw->clk);
u32 val;
val = readl_relaxed(S3C24XX_MISCCR) >> clkout->shift;
val >>= clkout->shift;
val &= clkout->mask;
if (val >= num_parents)
return -EINVAL;
return val;
}
static int s3c24xx_clkout_set_parent(struct clk_hw *hw, u8 index)
{
struct s3c24xx_clkout *clkout = to_s3c24xx_clkout(hw);
int ret = 0;
s3c2410_modify_misccr((clkout->mask << clkout->shift),
(index << clkout->shift));
return ret;
}
const struct clk_ops s3c24xx_clkout_ops = {
.get_parent = s3c24xx_clkout_get_parent,
.set_parent = s3c24xx_clkout_set_parent,
.determine_rate = __clk_mux_determine_rate,
};
struct clk *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;
/* allocate the clkout */
clkout = kzalloc(sizeof(*clkout), GFP_KERNEL);
if (!clkout)
return ERR_PTR(-ENOMEM);
init.name = name;
init.ops = &s3c24xx_clkout_ops;
init.flags = CLK_IS_BASIC;
init.parent_names = parent_names;
init.num_parents = num_parents;
clkout->shift = shift;
clkout->mask = mask;
clkout->hw.init = &init;
clk = clk_register(dev, &clkout->hw);
return clk;
}
/*
* dclk and clkout init
*/
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;
};
#define to_s3c24xx_dclk0(x) \
container_of(x, struct s3c24xx_dclk, dclk0_div_change_nb)
#define to_s3c24xx_dclk1(x) \
container_of(x, struct s3c24xx_dclk, dclk1_div_change_nb)
static const char *dclk_s3c2410_p[] = { "pclk", "uclk" };
static const char *clkout0_s3c2410_p[] = { "mpll", "upll", "fclk", "hclk", "pclk",
"gate_dclk0" };
static const char *clkout1_s3c2410_p[] = { "mpll", "upll", "fclk", "hclk", "pclk",
"gate_dclk1" };
static const char *clkout0_s3c2412_p[] = { "mpll", "upll", "rtc_clkout",
"hclk", "pclk", "gate_dclk0" };
static const char *clkout1_s3c2412_p[] = { "xti", "upll", "fclk", "hclk", "pclk",
"gate_dclk1" };
static const char *clkout0_s3c2440_p[] = { "xti", "upll", "fclk", "hclk", "pclk",
"gate_dclk0" };
static const char *clkout1_s3c2440_p[] = { "mpll", "upll", "rtc_clkout",
"hclk", "pclk", "gate_dclk1" };
static const char *dclk_s3c2443_p[] = { "pclk", "epll" };
static const char *clkout0_s3c2443_p[] = { "xti", "epll", "armclk", "hclk", "pclk",
"gate_dclk0" };
static const char *clkout1_s3c2443_p[] = { "dummy", "epll", "rtc_clkout",
"hclk", "pclk", "gate_dclk1" };
#define DCLKCON_DCLK_DIV_MASK 0xf
#define DCLKCON_DCLK0_DIV_SHIFT 4
#define DCLKCON_DCLK0_CMP_SHIFT 8
#define DCLKCON_DCLK1_DIV_SHIFT 20
#define DCLKCON_DCLK1_CMP_SHIFT 24
static void s3c24xx_dclk_update_cmp(struct s3c24xx_dclk *s3c24xx_dclk,
int div_shift, int cmp_shift)
{
unsigned long flags = 0;
u32 dclk_con, div, cmp;
spin_lock_irqsave(&s3c24xx_dclk->dclk_lock, flags);
dclk_con = readl_relaxed(s3c24xx_dclk->base);
div = ((dclk_con >> div_shift) & DCLKCON_DCLK_DIV_MASK) + 1;
cmp = ((div + 1) / 2) - 1;
dclk_con &= ~(DCLKCON_DCLK_DIV_MASK << cmp_shift);
dclk_con |= (cmp << cmp_shift);
writel_relaxed(dclk_con, s3c24xx_dclk->base);
spin_unlock_irqrestore(&s3c24xx_dclk->dclk_lock, flags);
}
static int s3c24xx_dclk0_div_notify(struct notifier_block *nb,
unsigned long event, void *data)
{
struct s3c24xx_dclk *s3c24xx_dclk = to_s3c24xx_dclk0(nb);
if (event == POST_RATE_CHANGE) {
s3c24xx_dclk_update_cmp(s3c24xx_dclk,
DCLKCON_DCLK0_DIV_SHIFT, DCLKCON_DCLK0_CMP_SHIFT);
}
return NOTIFY_DONE;
}
static int s3c24xx_dclk1_div_notify(struct notifier_block *nb,
unsigned long event, void *data)
{
struct s3c24xx_dclk *s3c24xx_dclk = to_s3c24xx_dclk1(nb);
if (event == POST_RATE_CHANGE) {
s3c24xx_dclk_update_cmp(s3c24xx_dclk,
DCLKCON_DCLK1_DIV_SHIFT, DCLKCON_DCLK1_CMP_SHIFT);
}
return NOTIFY_DONE;
}
#ifdef CONFIG_PM_SLEEP
static int s3c24xx_dclk_suspend(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct s3c24xx_dclk *s3c24xx_dclk = platform_get_drvdata(pdev);
s3c24xx_dclk->reg_save = readl_relaxed(s3c24xx_dclk->base);
return 0;
}
static int s3c24xx_dclk_resume(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct s3c24xx_dclk *s3c24xx_dclk = platform_get_drvdata(pdev);
writel_relaxed(s3c24xx_dclk->reg_save, s3c24xx_dclk->base);
return 0;
}
#endif
static SIMPLE_DEV_PM_OPS(s3c24xx_dclk_pm_ops,
s3c24xx_dclk_suspend, s3c24xx_dclk_resume);
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;
int ret, i;
s3c24xx_dclk = devm_kzalloc(&pdev->dev, sizeof(*s3c24xx_dclk),
GFP_KERNEL);
if (!s3c24xx_dclk)
return -ENOMEM;
s3c24xx_dclk->dev = &pdev->dev;
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))
return PTR_ERR(s3c24xx_dclk->base);
dclk_variant = (struct s3c24xx_dclk_drv_data *)
platform_get_device_id(pdev)->driver_data;
clk_table[MUX_DCLK0] = clk_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",
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",
"mux_dclk0", 0, s3c24xx_dclk->base,
4, 4, 0, &s3c24xx_dclk->dclk_lock);
clk_table[DIV_DCLK1] = clk_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",
"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",
"div_dclk1", CLK_SET_RATE_PARENT,
s3c24xx_dclk->base, 16, 0,
&s3c24xx_dclk->dclk_lock);
clk_table[MUX_CLKOUT0] = s3c24xx_register_clkout(&pdev->dev,
"clkout0", dclk_variant->clkout0_parent_names,
dclk_variant->clkout0_num_parents, 4, 7);
clk_table[MUX_CLKOUT1] = s3c24xx_register_clkout(&pdev->dev,
"clkout1", dclk_variant->clkout1_parent_names,
dclk_variant->clkout1_num_parents, 8, 7);
for (i = 0; i < DCLK_MAX_CLKS; i++)
if (IS_ERR(clk_table[i])) {
dev_err(&pdev->dev, "clock %d failed to register\n", i);
ret = PTR_ERR(clk_table[i]);
goto err_clk_register;
}
ret = clk_register_clkdev(clk_table[MUX_DCLK0], "dclk0", NULL);
if (!ret)
ret = clk_register_clkdev(clk_table[MUX_DCLK1], "dclk1", NULL);
if (!ret)
ret = clk_register_clkdev(clk_table[MUX_CLKOUT0],
"clkout0", NULL);
if (!ret)
ret = clk_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;
}
s3c24xx_dclk->dclk0_div_change_nb.notifier_call =
s3c24xx_dclk0_div_notify;
s3c24xx_dclk->dclk1_div_change_nb.notifier_call =
s3c24xx_dclk1_div_notify;
ret = clk_notifier_register(clk_table[DIV_DCLK0],
&s3c24xx_dclk->dclk0_div_change_nb);
if (ret)
goto err_clk_register;
ret = clk_notifier_register(clk_table[DIV_DCLK1],
&s3c24xx_dclk->dclk1_div_change_nb);
if (ret)
goto err_dclk_notify;
return 0;
err_dclk_notify:
clk_notifier_unregister(clk_table[DIV_DCLK0],
&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]);
return ret;
}
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;
int i;
clk_notifier_unregister(clk_table[DIV_DCLK1],
&s3c24xx_dclk->dclk1_div_change_nb);
clk_notifier_unregister(clk_table[DIV_DCLK0],
&s3c24xx_dclk->dclk0_div_change_nb);
for (i = 0; i < DCLK_MAX_CLKS; i++)
clk_unregister(clk_table[i]);
return 0;
}
static struct s3c24xx_dclk_drv_data dclk_variants[] = {
[S3C2410] = {
.clkout0_parent_names = clkout0_s3c2410_p,
.clkout0_num_parents = ARRAY_SIZE(clkout0_s3c2410_p),
.clkout1_parent_names = clkout1_s3c2410_p,
.clkout1_num_parents = ARRAY_SIZE(clkout1_s3c2410_p),
.mux_parent_names = dclk_s3c2410_p,
.mux_num_parents = ARRAY_SIZE(dclk_s3c2410_p),
},
[S3C2412] = {
.clkout0_parent_names = clkout0_s3c2412_p,
.clkout0_num_parents = ARRAY_SIZE(clkout0_s3c2412_p),
.clkout1_parent_names = clkout1_s3c2412_p,
.clkout1_num_parents = ARRAY_SIZE(clkout1_s3c2412_p),
.mux_parent_names = dclk_s3c2410_p,
.mux_num_parents = ARRAY_SIZE(dclk_s3c2410_p),
},
[S3C2440] = {
.clkout0_parent_names = clkout0_s3c2440_p,
.clkout0_num_parents = ARRAY_SIZE(clkout0_s3c2440_p),
.clkout1_parent_names = clkout1_s3c2440_p,
.clkout1_num_parents = ARRAY_SIZE(clkout1_s3c2440_p),
.mux_parent_names = dclk_s3c2410_p,
.mux_num_parents = ARRAY_SIZE(dclk_s3c2410_p),
},
[S3C2443] = {
.clkout0_parent_names = clkout0_s3c2443_p,
.clkout0_num_parents = ARRAY_SIZE(clkout0_s3c2443_p),
.clkout1_parent_names = clkout1_s3c2443_p,
.clkout1_num_parents = ARRAY_SIZE(clkout1_s3c2443_p),
.mux_parent_names = dclk_s3c2443_p,
.mux_num_parents = ARRAY_SIZE(dclk_s3c2443_p),
},
};
static struct platform_device_id s3c24xx_dclk_driver_ids[] = {
{
.name = "s3c2410-dclk",
.driver_data = (kernel_ulong_t)&dclk_variants[S3C2410],
}, {
.name = "s3c2412-dclk",
.driver_data = (kernel_ulong_t)&dclk_variants[S3C2412],
}, {
.name = "s3c2440-dclk",
.driver_data = (kernel_ulong_t)&dclk_variants[S3C2440],
}, {
.name = "s3c2443-dclk",
.driver_data = (kernel_ulong_t)&dclk_variants[S3C2443],
},
{ }
};
MODULE_DEVICE_TABLE(platform, s3c24xx_dclk_driver_ids);
static struct platform_driver s3c24xx_dclk_driver = {
.driver = {
.name = "s3c24xx-dclk",
.pm = &s3c24xx_dclk_pm_ops,
},
.probe = s3c24xx_dclk_probe,
.remove = s3c24xx_dclk_remove,
.id_table = s3c24xx_dclk_driver_ids,
};
module_platform_driver(s3c24xx_dclk_driver);
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("Heiko Stuebner <heiko@sntech.de>");
MODULE_DESCRIPTION("Driver for the S3C24XX external clock outputs");

View file

@ -0,0 +1,489 @@
/*
* Copyright (c) 2013 Heiko Stuebner <heiko@sntech.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Common Clock Framework support for S3C2410 and following SoCs.
*/
#include <linux/clk.h>
#include <linux/clkdev.h>
#include <linux/clk-provider.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/syscore_ops.h>
#include <dt-bindings/clock/s3c2410.h>
#include "clk.h"
#include "clk-pll.h"
#define LOCKTIME 0x00
#define MPLLCON 0x04
#define UPLLCON 0x08
#define CLKCON 0x0c
#define CLKSLOW 0x10
#define CLKDIVN 0x14
#define CAMDIVN 0x18
/* the soc types */
enum supported_socs {
S3C2410,
S3C2440,
S3C2442,
};
/* list of PLLs to be registered */
enum s3c2410_plls {
mpll, upll,
};
static void __iomem *reg_base;
#ifdef CONFIG_PM_SLEEP
static struct samsung_clk_reg_dump *s3c2410_save;
/*
* list of controller registers to be saved and restored during a
* suspend/resume cycle.
*/
static unsigned long s3c2410_clk_regs[] __initdata = {
LOCKTIME,
MPLLCON,
UPLLCON,
CLKCON,
CLKSLOW,
CLKDIVN,
CAMDIVN,
};
static int s3c2410_clk_suspend(void)
{
samsung_clk_save(reg_base, s3c2410_save,
ARRAY_SIZE(s3c2410_clk_regs));
return 0;
}
static void s3c2410_clk_resume(void)
{
samsung_clk_restore(reg_base, s3c2410_save,
ARRAY_SIZE(s3c2410_clk_regs));
}
static struct syscore_ops s3c2410_clk_syscore_ops = {
.suspend = s3c2410_clk_suspend,
.resume = s3c2410_clk_resume,
};
static void s3c2410_clk_sleep_init(void)
{
s3c2410_save = samsung_clk_alloc_reg_dump(s3c2410_clk_regs,
ARRAY_SIZE(s3c2410_clk_regs));
if (!s3c2410_save) {
pr_warn("%s: failed to allocate sleep save data, no sleep support!\n",
__func__);
return;
}
register_syscore_ops(&s3c2410_clk_syscore_ops);
return;
}
#else
static void s3c2410_clk_sleep_init(void) {}
#endif
PNAME(fclk_p) = { "mpll", "div_slow" };
struct samsung_mux_clock s3c2410_common_muxes[] __initdata = {
MUX(FCLK, "fclk", fclk_p, CLKSLOW, 4, 1),
};
static struct clk_div_table divslow_d[] = {
{ .val = 0, .div = 1 },
{ .val = 1, .div = 2 },
{ .val = 2, .div = 4 },
{ .val = 3, .div = 6 },
{ .val = 4, .div = 8 },
{ .val = 5, .div = 10 },
{ .val = 6, .div = 12 },
{ .val = 7, .div = 14 },
{ /* sentinel */ },
};
struct samsung_div_clock s3c2410_common_dividers[] __initdata = {
DIV_T(0, "div_slow", "xti", CLKSLOW, 0, 3, divslow_d),
DIV(PCLK, "pclk", "hclk", CLKDIVN, 0, 1),
};
struct samsung_gate_clock s3c2410_common_gates[] __initdata = {
GATE(PCLK_SPI, "spi", "pclk", CLKCON, 18, 0, 0),
GATE(PCLK_I2S, "i2s", "pclk", CLKCON, 17, 0, 0),
GATE(PCLK_I2C, "i2c", "pclk", CLKCON, 16, 0, 0),
GATE(PCLK_ADC, "adc", "pclk", CLKCON, 15, 0, 0),
GATE(PCLK_RTC, "rtc", "pclk", CLKCON, 14, 0, 0),
GATE(PCLK_GPIO, "gpio", "pclk", CLKCON, 13, CLK_IGNORE_UNUSED, 0),
GATE(PCLK_UART2, "uart2", "pclk", CLKCON, 12, 0, 0),
GATE(PCLK_UART1, "uart1", "pclk", CLKCON, 11, 0, 0),
GATE(PCLK_UART0, "uart0", "pclk", CLKCON, 10, 0, 0),
GATE(PCLK_SDI, "sdi", "pclk", CLKCON, 9, 0, 0),
GATE(PCLK_PWM, "pwm", "pclk", CLKCON, 8, 0, 0),
GATE(HCLK_USBD, "usb-device", "hclk", CLKCON, 7, 0, 0),
GATE(HCLK_USBH, "usb-host", "hclk", CLKCON, 6, 0, 0),
GATE(HCLK_LCD, "lcd", "hclk", CLKCON, 5, 0, 0),
GATE(HCLK_NAND, "nand", "hclk", CLKCON, 4, 0, 0),
};
/* should be added _after_ the soc-specific clocks are created */
struct samsung_clock_alias s3c2410_common_aliases[] __initdata = {
ALIAS(PCLK_I2C, "s3c2410-i2c.0", "i2c"),
ALIAS(PCLK_ADC, NULL, "adc"),
ALIAS(PCLK_RTC, NULL, "rtc"),
ALIAS(PCLK_PWM, NULL, "timers"),
ALIAS(HCLK_LCD, NULL, "lcd"),
ALIAS(HCLK_USBD, NULL, "usb-device"),
ALIAS(HCLK_USBH, NULL, "usb-host"),
ALIAS(UCLK, NULL, "usb-bus-host"),
ALIAS(UCLK, NULL, "usb-bus-gadget"),
ALIAS(ARMCLK, NULL, "armclk"),
ALIAS(UCLK, NULL, "uclk"),
ALIAS(HCLK, NULL, "hclk"),
ALIAS(MPLL, NULL, "mpll"),
ALIAS(FCLK, NULL, "fclk"),
ALIAS(PCLK, NULL, "watchdog"),
ALIAS(PCLK_SDI, NULL, "sdi"),
ALIAS(HCLK_NAND, NULL, "nand"),
ALIAS(PCLK_I2S, NULL, "iis"),
ALIAS(PCLK_I2C, NULL, "i2c"),
};
/* S3C2410 specific clocks */
static struct samsung_pll_rate_table pll_s3c2410_12mhz_tbl[] __initdata = {
/* sorted in descending order */
/* 2410A extras */
PLL_35XX_RATE(270000000, 127, 1, 1),
PLL_35XX_RATE(268000000, 126, 1, 1),
PLL_35XX_RATE(266000000, 125, 1, 1),
PLL_35XX_RATE(226000000, 105, 1, 1),
PLL_35XX_RATE(210000000, 132, 2, 1),
/* 2410 common */
PLL_35XX_RATE(203000000, 161, 3, 1),
PLL_35XX_RATE(192000000, 88, 1, 1),
PLL_35XX_RATE(186000000, 85, 1, 1),
PLL_35XX_RATE(180000000, 82, 1, 1),
PLL_35XX_RATE(170000000, 77, 1, 1),
PLL_35XX_RATE(158000000, 71, 1, 1),
PLL_35XX_RATE(152000000, 68, 1, 1),
PLL_35XX_RATE(147000000, 90, 2, 1),
PLL_35XX_RATE(135000000, 82, 2, 1),
PLL_35XX_RATE(124000000, 116, 1, 2),
PLL_35XX_RATE(118000000, 150, 2, 2),
PLL_35XX_RATE(113000000, 105, 1, 2),
PLL_35XX_RATE(101000000, 127, 2, 2),
PLL_35XX_RATE(90000000, 112, 2, 2),
PLL_35XX_RATE(85000000, 105, 2, 2),
PLL_35XX_RATE(79000000, 71, 1, 2),
PLL_35XX_RATE(68000000, 82, 2, 2),
PLL_35XX_RATE(56000000, 142, 2, 3),
PLL_35XX_RATE(48000000, 120, 2, 3),
PLL_35XX_RATE(51000000, 161, 3, 3),
PLL_35XX_RATE(45000000, 82, 1, 3),
PLL_35XX_RATE(34000000, 82, 2, 3),
{ /* sentinel */ },
};
static struct samsung_pll_clock s3c2410_plls[] __initdata = {
[mpll] = PLL(pll_s3c2410_mpll, MPLL, "mpll", "xti",
LOCKTIME, MPLLCON, NULL),
[upll] = PLL(pll_s3c2410_upll, UPLL, "upll", "xti",
LOCKTIME, UPLLCON, NULL),
};
struct samsung_div_clock s3c2410_dividers[] __initdata = {
DIV(HCLK, "hclk", "mpll", CLKDIVN, 1, 1),
};
struct samsung_fixed_factor_clock s3c2410_ffactor[] __initdata = {
/*
* armclk is directly supplied by the fclk, without
* switching possibility like on the s3c244x below.
*/
FFACTOR(ARMCLK, "armclk", "fclk", 1, 1, 0),
/* uclk is fed from the unmodified upll */
FFACTOR(UCLK, "uclk", "upll", 1, 1, 0),
};
struct samsung_clock_alias s3c2410_aliases[] __initdata = {
ALIAS(PCLK_UART0, "s3c2410-uart.0", "uart"),
ALIAS(PCLK_UART1, "s3c2410-uart.1", "uart"),
ALIAS(PCLK_UART2, "s3c2410-uart.2", "uart"),
ALIAS(PCLK_UART0, "s3c2410-uart.0", "clk_uart_baud0"),
ALIAS(PCLK_UART1, "s3c2410-uart.1", "clk_uart_baud0"),
ALIAS(PCLK_UART2, "s3c2410-uart.2", "clk_uart_baud0"),
ALIAS(UCLK, NULL, "clk_uart_baud1"),
};
/* S3C244x specific clocks */
static struct samsung_pll_rate_table pll_s3c244x_12mhz_tbl[] __initdata = {
/* sorted in descending order */
PLL_35XX_RATE(400000000, 0x5c, 1, 1),
PLL_35XX_RATE(390000000, 0x7a, 2, 1),
PLL_35XX_RATE(380000000, 0x57, 1, 1),
PLL_35XX_RATE(370000000, 0xb1, 4, 1),
PLL_35XX_RATE(360000000, 0x70, 2, 1),
PLL_35XX_RATE(350000000, 0xa7, 4, 1),
PLL_35XX_RATE(340000000, 0x4d, 1, 1),
PLL_35XX_RATE(330000000, 0x66, 2, 1),
PLL_35XX_RATE(320000000, 0x98, 4, 1),
PLL_35XX_RATE(310000000, 0x93, 4, 1),
PLL_35XX_RATE(300000000, 0x75, 3, 1),
PLL_35XX_RATE(240000000, 0x70, 1, 2),
PLL_35XX_RATE(230000000, 0x6b, 1, 2),
PLL_35XX_RATE(220000000, 0x66, 1, 2),
PLL_35XX_RATE(210000000, 0x84, 2, 2),
PLL_35XX_RATE(200000000, 0x5c, 1, 2),
PLL_35XX_RATE(190000000, 0x57, 1, 2),
PLL_35XX_RATE(180000000, 0x70, 2, 2),
PLL_35XX_RATE(170000000, 0x4d, 1, 2),
PLL_35XX_RATE(160000000, 0x98, 4, 2),
PLL_35XX_RATE(150000000, 0x75, 3, 2),
PLL_35XX_RATE(120000000, 0x70, 1, 3),
PLL_35XX_RATE(110000000, 0x66, 1, 3),
PLL_35XX_RATE(100000000, 0x5c, 1, 3),
PLL_35XX_RATE(90000000, 0x70, 2, 3),
PLL_35XX_RATE(80000000, 0x98, 4, 3),
PLL_35XX_RATE(75000000, 0x75, 3, 3),
{ /* sentinel */ },
};
static struct samsung_pll_clock s3c244x_common_plls[] __initdata = {
[mpll] = PLL(pll_s3c2440_mpll, MPLL, "mpll", "xti",
LOCKTIME, MPLLCON, NULL),
[upll] = PLL(pll_s3c2410_upll, UPLL, "upll", "xti",
LOCKTIME, UPLLCON, NULL),
};
PNAME(hclk_p) = { "fclk", "div_hclk_2", "div_hclk_4", "div_hclk_3" };
PNAME(armclk_p) = { "fclk", "hclk" };
struct samsung_mux_clock s3c244x_common_muxes[] __initdata = {
MUX(HCLK, "hclk", hclk_p, CLKDIVN, 1, 2),
MUX(ARMCLK, "armclk", armclk_p, CAMDIVN, 12, 1),
};
struct samsung_fixed_factor_clock s3c244x_common_ffactor[] __initdata = {
FFACTOR(0, "div_hclk_2", "fclk", 1, 2, 0),
FFACTOR(0, "ff_cam", "div_cam", 2, 1, CLK_SET_RATE_PARENT),
};
static struct clk_div_table div_hclk_4_d[] = {
{ .val = 0, .div = 4 },
{ .val = 1, .div = 8 },
{ /* sentinel */ },
};
static struct clk_div_table div_hclk_3_d[] = {
{ .val = 0, .div = 3 },
{ .val = 1, .div = 6 },
{ /* sentinel */ },
};
struct samsung_div_clock s3c244x_common_dividers[] __initdata = {
DIV(UCLK, "uclk", "upll", CLKDIVN, 3, 1),
DIV(0, "div_hclk", "fclk", CLKDIVN, 1, 1),
DIV_T(0, "div_hclk_4", "fclk", CAMDIVN, 9, 1, div_hclk_4_d),
DIV_T(0, "div_hclk_3", "fclk", CAMDIVN, 8, 1, div_hclk_3_d),
DIV(0, "div_cam", "upll", CAMDIVN, 0, 3),
};
struct samsung_gate_clock s3c244x_common_gates[] __initdata = {
GATE(HCLK_CAM, "cam", "hclk", CLKCON, 19, 0, 0),
};
struct samsung_clock_alias s3c244x_common_aliases[] __initdata = {
ALIAS(PCLK_UART0, "s3c2440-uart.0", "uart"),
ALIAS(PCLK_UART1, "s3c2440-uart.1", "uart"),
ALIAS(PCLK_UART2, "s3c2440-uart.2", "uart"),
ALIAS(PCLK_UART0, "s3c2440-uart.0", "clk_uart_baud2"),
ALIAS(PCLK_UART1, "s3c2440-uart.1", "clk_uart_baud2"),
ALIAS(PCLK_UART2, "s3c2440-uart.2", "clk_uart_baud2"),
ALIAS(HCLK_CAM, NULL, "camif"),
ALIAS(CAMIF, NULL, "camif-upll"),
};
/* S3C2440 specific clocks */
PNAME(s3c2440_camif_p) = { "upll", "ff_cam" };
struct samsung_mux_clock s3c2440_muxes[] __initdata = {
MUX(CAMIF, "camif", s3c2440_camif_p, CAMDIVN, 4, 1),
};
struct samsung_gate_clock s3c2440_gates[] __initdata = {
GATE(PCLK_AC97, "ac97", "pclk", CLKCON, 20, 0, 0),
};
/* S3C2442 specific clocks */
struct samsung_fixed_factor_clock s3c2442_ffactor[] __initdata = {
FFACTOR(0, "upll_3", "upll", 1, 3, 0),
};
PNAME(s3c2442_camif_p) = { "upll", "ff_cam", "upll", "upll_3" };
struct samsung_mux_clock s3c2442_muxes[] __initdata = {
MUX(CAMIF, "camif", s3c2442_camif_p, CAMDIVN, 4, 2),
};
/*
* fixed rate clocks generated outside the soc
* Only necessary until the devicetree-move is complete
*/
#define XTI 1
struct samsung_fixed_rate_clock s3c2410_common_frate_clks[] __initdata = {
FRATE(XTI, "xti", NULL, CLK_IS_ROOT, 0),
};
static void __init s3c2410_common_clk_register_fixed_ext(
struct samsung_clk_provider *ctx,
unsigned long xti_f)
{
struct samsung_clock_alias xti_alias = ALIAS(XTI, NULL, "xtal");
s3c2410_common_frate_clks[0].fixed_rate = xti_f;
samsung_clk_register_fixed_rate(ctx, s3c2410_common_frate_clks,
ARRAY_SIZE(s3c2410_common_frate_clks));
samsung_clk_register_alias(ctx, &xti_alias, 1);
}
void __init s3c2410_common_clk_init(struct device_node *np, unsigned long xti_f,
int current_soc,
void __iomem *base)
{
struct samsung_clk_provider *ctx;
reg_base = base;
if (np) {
reg_base = of_iomap(np, 0);
if (!reg_base)
panic("%s: failed to map registers\n", __func__);
}
ctx = samsung_clk_init(np, reg_base, NR_CLKS);
if (!ctx)
panic("%s: unable to allocate context.\n", __func__);
/* Register external clocks only in non-dt cases */
if (!np)
s3c2410_common_clk_register_fixed_ext(ctx, xti_f);
if (current_soc == S3C2410) {
if (_get_rate("xti") == 12 * MHZ) {
s3c2410_plls[mpll].rate_table = pll_s3c2410_12mhz_tbl;
s3c2410_plls[upll].rate_table = pll_s3c2410_12mhz_tbl;
}
/* Register PLLs. */
samsung_clk_register_pll(ctx, s3c2410_plls,
ARRAY_SIZE(s3c2410_plls), reg_base);
} else { /* S3C2440, S3C2442 */
if (_get_rate("xti") == 12 * MHZ) {
/*
* plls follow different calculation schemes, with the
* upll following the same scheme as the s3c2410 plls
*/
s3c244x_common_plls[mpll].rate_table =
pll_s3c244x_12mhz_tbl;
s3c244x_common_plls[upll].rate_table =
pll_s3c2410_12mhz_tbl;
}
/* Register PLLs. */
samsung_clk_register_pll(ctx, s3c244x_common_plls,
ARRAY_SIZE(s3c244x_common_plls), reg_base);
}
/* Register common internal clocks. */
samsung_clk_register_mux(ctx, s3c2410_common_muxes,
ARRAY_SIZE(s3c2410_common_muxes));
samsung_clk_register_div(ctx, s3c2410_common_dividers,
ARRAY_SIZE(s3c2410_common_dividers));
samsung_clk_register_gate(ctx, s3c2410_common_gates,
ARRAY_SIZE(s3c2410_common_gates));
if (current_soc == S3C2440 || current_soc == S3C2442) {
samsung_clk_register_div(ctx, s3c244x_common_dividers,
ARRAY_SIZE(s3c244x_common_dividers));
samsung_clk_register_gate(ctx, s3c244x_common_gates,
ARRAY_SIZE(s3c244x_common_gates));
samsung_clk_register_mux(ctx, s3c244x_common_muxes,
ARRAY_SIZE(s3c244x_common_muxes));
samsung_clk_register_fixed_factor(ctx, s3c244x_common_ffactor,
ARRAY_SIZE(s3c244x_common_ffactor));
}
/* Register SoC-specific clocks. */
switch (current_soc) {
case S3C2410:
samsung_clk_register_div(ctx, s3c2410_dividers,
ARRAY_SIZE(s3c2410_dividers));
samsung_clk_register_fixed_factor(ctx, s3c2410_ffactor,
ARRAY_SIZE(s3c2410_ffactor));
samsung_clk_register_alias(ctx, s3c2410_aliases,
ARRAY_SIZE(s3c2410_aliases));
break;
case S3C2440:
samsung_clk_register_mux(ctx, s3c2440_muxes,
ARRAY_SIZE(s3c2440_muxes));
samsung_clk_register_gate(ctx, s3c2440_gates,
ARRAY_SIZE(s3c2440_gates));
break;
case S3C2442:
samsung_clk_register_mux(ctx, s3c2442_muxes,
ARRAY_SIZE(s3c2442_muxes));
samsung_clk_register_fixed_factor(ctx, s3c2442_ffactor,
ARRAY_SIZE(s3c2442_ffactor));
break;
}
/*
* Register common aliases at the end, as some of the aliased clocks
* are SoC specific.
*/
samsung_clk_register_alias(ctx, s3c2410_common_aliases,
ARRAY_SIZE(s3c2410_common_aliases));
if (current_soc == S3C2440 || current_soc == S3C2442) {
samsung_clk_register_alias(ctx, s3c244x_common_aliases,
ARRAY_SIZE(s3c244x_common_aliases));
}
s3c2410_clk_sleep_init();
samsung_clk_of_add_provider(np, ctx);
}
static void __init s3c2410_clk_init(struct device_node *np)
{
s3c2410_common_clk_init(np, 0, S3C2410, 0);
}
CLK_OF_DECLARE(s3c2410_clk, "samsung,s3c2410-clock", s3c2410_clk_init);
static void __init s3c2440_clk_init(struct device_node *np)
{
s3c2410_common_clk_init(np, 0, S3C2440, 0);
}
CLK_OF_DECLARE(s3c2440_clk, "samsung,s3c2440-clock", s3c2440_clk_init);
static void __init s3c2442_clk_init(struct device_node *np)
{
s3c2410_common_clk_init(np, 0, S3C2442, 0);
}
CLK_OF_DECLARE(s3c2442_clk, "samsung,s3c2442-clock", s3c2442_clk_init);

View file

@ -0,0 +1,305 @@
/*
* Copyright (c) 2013 Heiko Stuebner <heiko@sntech.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Common Clock Framework support for S3C2412 and S3C2413.
*/
#include <linux/clk.h>
#include <linux/clkdev.h>
#include <linux/clk-provider.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/syscore_ops.h>
#include <linux/reboot.h>
#include <dt-bindings/clock/s3c2412.h>
#include "clk.h"
#include "clk-pll.h"
#define LOCKTIME 0x00
#define MPLLCON 0x04
#define UPLLCON 0x08
#define CLKCON 0x0c
#define CLKDIVN 0x14
#define CLKSRC 0x1c
#define SWRST 0x30
/* list of PLLs to be registered */
enum s3c2412_plls {
mpll, upll,
};
static void __iomem *reg_base;
#ifdef CONFIG_PM_SLEEP
static struct samsung_clk_reg_dump *s3c2412_save;
/*
* list of controller registers to be saved and restored during a
* suspend/resume cycle.
*/
static unsigned long s3c2412_clk_regs[] __initdata = {
LOCKTIME,
MPLLCON,
UPLLCON,
CLKCON,
CLKDIVN,
CLKSRC,
};
static int s3c2412_clk_suspend(void)
{
samsung_clk_save(reg_base, s3c2412_save,
ARRAY_SIZE(s3c2412_clk_regs));
return 0;
}
static void s3c2412_clk_resume(void)
{
samsung_clk_restore(reg_base, s3c2412_save,
ARRAY_SIZE(s3c2412_clk_regs));
}
static struct syscore_ops s3c2412_clk_syscore_ops = {
.suspend = s3c2412_clk_suspend,
.resume = s3c2412_clk_resume,
};
static void s3c2412_clk_sleep_init(void)
{
s3c2412_save = samsung_clk_alloc_reg_dump(s3c2412_clk_regs,
ARRAY_SIZE(s3c2412_clk_regs));
if (!s3c2412_save) {
pr_warn("%s: failed to allocate sleep save data, no sleep support!\n",
__func__);
return;
}
register_syscore_ops(&s3c2412_clk_syscore_ops);
return;
}
#else
static void s3c2412_clk_sleep_init(void) {}
#endif
static struct clk_div_table divxti_d[] = {
{ .val = 0, .div = 1 },
{ .val = 1, .div = 2 },
{ .val = 2, .div = 4 },
{ .val = 3, .div = 6 },
{ .val = 4, .div = 8 },
{ .val = 5, .div = 10 },
{ .val = 6, .div = 12 },
{ .val = 7, .div = 14 },
{ /* sentinel */ },
};
struct samsung_div_clock s3c2412_dividers[] __initdata = {
DIV_T(0, "div_xti", "xti", CLKSRC, 0, 3, divxti_d),
DIV(0, "div_cam", "mux_cam", CLKDIVN, 16, 4),
DIV(0, "div_i2s", "mux_i2s", CLKDIVN, 12, 4),
DIV(0, "div_uart", "mux_uart", CLKDIVN, 8, 4),
DIV(0, "div_usb", "mux_usb", CLKDIVN, 6, 1),
DIV(0, "div_hclk_half", "hclk", CLKDIVN, 5, 1),
DIV(ARMDIV, "armdiv", "msysclk", CLKDIVN, 3, 1),
DIV(PCLK, "pclk", "hclk", CLKDIVN, 2, 1),
DIV(HCLK, "hclk", "armdiv", CLKDIVN, 0, 2),
};
struct samsung_fixed_factor_clock s3c2412_ffactor[] __initdata = {
FFACTOR(0, "ff_hclk", "hclk", 2, 1, CLK_SET_RATE_PARENT),
};
/*
* The first two use the OM[4] setting, which is not readable from
* software, so assume it is set to xti.
*/
PNAME(erefclk_p) = { "xti", "xti", "xti", "ext" };
PNAME(urefclk_p) = { "xti", "xti", "xti", "ext" };
PNAME(camclk_p) = { "usysclk", "hclk" };
PNAME(usbclk_p) = { "usysclk", "hclk" };
PNAME(i2sclk_p) = { "erefclk", "mpll" };
PNAME(uartclk_p) = { "erefclk", "mpll" };
PNAME(usysclk_p) = { "urefclk", "upll" };
PNAME(msysclk_p) = { "mdivclk", "mpll" };
PNAME(mdivclk_p) = { "xti", "div_xti" };
PNAME(armclk_p) = { "armdiv", "hclk" };
struct samsung_mux_clock s3c2412_muxes[] __initdata = {
MUX(0, "erefclk", erefclk_p, CLKSRC, 14, 2),
MUX(0, "urefclk", urefclk_p, CLKSRC, 12, 2),
MUX(0, "mux_cam", camclk_p, CLKSRC, 11, 1),
MUX(0, "mux_usb", usbclk_p, CLKSRC, 10, 1),
MUX(0, "mux_i2s", i2sclk_p, CLKSRC, 9, 1),
MUX(0, "mux_uart", uartclk_p, CLKSRC, 8, 1),
MUX(USYSCLK, "usysclk", usysclk_p, CLKSRC, 5, 1),
MUX(MSYSCLK, "msysclk", msysclk_p, CLKSRC, 4, 1),
MUX(MDIVCLK, "mdivclk", mdivclk_p, CLKSRC, 3, 1),
MUX(ARMCLK, "armclk", armclk_p, CLKDIVN, 4, 1),
};
static struct samsung_pll_clock s3c2412_plls[] __initdata = {
[mpll] = PLL(pll_s3c2440_mpll, MPLL, "mpll", "xti",
LOCKTIME, MPLLCON, NULL),
[upll] = PLL(pll_s3c2410_upll, UPLL, "upll", "urefclk",
LOCKTIME, UPLLCON, NULL),
};
struct samsung_gate_clock s3c2412_gates[] __initdata = {
GATE(PCLK_WDT, "wdt", "pclk", CLKCON, 28, 0, 0),
GATE(PCLK_SPI, "spi", "pclk", CLKCON, 27, 0, 0),
GATE(PCLK_I2S, "i2s", "pclk", CLKCON, 26, 0, 0),
GATE(PCLK_I2C, "i2c", "pclk", CLKCON, 25, 0, 0),
GATE(PCLK_ADC, "adc", "pclk", CLKCON, 24, 0, 0),
GATE(PCLK_RTC, "rtc", "pclk", CLKCON, 23, 0, 0),
GATE(PCLK_GPIO, "gpio", "pclk", CLKCON, 22, CLK_IGNORE_UNUSED, 0),
GATE(PCLK_UART2, "uart2", "pclk", CLKCON, 21, 0, 0),
GATE(PCLK_UART1, "uart1", "pclk", CLKCON, 20, 0, 0),
GATE(PCLK_UART0, "uart0", "pclk", CLKCON, 19, 0, 0),
GATE(PCLK_SDI, "sdi", "pclk", CLKCON, 18, 0, 0),
GATE(PCLK_PWM, "pwm", "pclk", CLKCON, 17, 0, 0),
GATE(PCLK_USBD, "usb-device", "pclk", CLKCON, 16, 0, 0),
GATE(SCLK_CAM, "sclk_cam", "div_cam", CLKCON, 15, 0, 0),
GATE(SCLK_UART, "sclk_uart", "div_uart", CLKCON, 14, 0, 0),
GATE(SCLK_I2S, "sclk_i2s", "div_i2s", CLKCON, 13, 0, 0),
GATE(SCLK_USBH, "sclk_usbh", "div_usb", CLKCON, 12, 0, 0),
GATE(SCLK_USBD, "sclk_usbd", "div_usb", CLKCON, 11, 0, 0),
GATE(HCLK_HALF, "hclk_half", "div_hclk_half", CLKCON, 10, CLK_IGNORE_UNUSED, 0),
GATE(HCLK_X2, "hclkx2", "ff_hclk", CLKCON, 9, CLK_IGNORE_UNUSED, 0),
GATE(HCLK_SDRAM, "sdram", "hclk", CLKCON, 8, CLK_IGNORE_UNUSED, 0),
GATE(HCLK_USBH, "usb-host", "hclk", CLKCON, 6, 0, 0),
GATE(HCLK_LCD, "lcd", "hclk", CLKCON, 5, 0, 0),
GATE(HCLK_NAND, "nand", "hclk", CLKCON, 4, 0, 0),
GATE(HCLK_DMA3, "dma3", "hclk", CLKCON, 3, CLK_IGNORE_UNUSED, 0),
GATE(HCLK_DMA2, "dma2", "hclk", CLKCON, 2, CLK_IGNORE_UNUSED, 0),
GATE(HCLK_DMA1, "dma1", "hclk", CLKCON, 1, CLK_IGNORE_UNUSED, 0),
GATE(HCLK_DMA0, "dma0", "hclk", CLKCON, 0, CLK_IGNORE_UNUSED, 0),
};
struct samsung_clock_alias s3c2412_aliases[] __initdata = {
ALIAS(PCLK_UART0, "s3c2412-uart.0", "uart"),
ALIAS(PCLK_UART1, "s3c2412-uart.1", "uart"),
ALIAS(PCLK_UART2, "s3c2412-uart.2", "uart"),
ALIAS(PCLK_UART0, "s3c2412-uart.0", "clk_uart_baud2"),
ALIAS(PCLK_UART1, "s3c2412-uart.1", "clk_uart_baud2"),
ALIAS(PCLK_UART2, "s3c2412-uart.2", "clk_uart_baud2"),
ALIAS(SCLK_UART, NULL, "clk_uart_baud3"),
ALIAS(PCLK_I2C, "s3c2410-i2c.0", "i2c"),
ALIAS(PCLK_ADC, NULL, "adc"),
ALIAS(PCLK_RTC, NULL, "rtc"),
ALIAS(PCLK_PWM, NULL, "timers"),
ALIAS(HCLK_LCD, NULL, "lcd"),
ALIAS(PCLK_USBD, NULL, "usb-device"),
ALIAS(SCLK_USBD, NULL, "usb-bus-gadget"),
ALIAS(HCLK_USBH, NULL, "usb-host"),
ALIAS(SCLK_USBH, NULL, "usb-bus-host"),
ALIAS(ARMCLK, NULL, "armclk"),
ALIAS(HCLK, NULL, "hclk"),
ALIAS(MPLL, NULL, "mpll"),
ALIAS(MSYSCLK, NULL, "fclk"),
};
static int s3c2412_restart(struct notifier_block *this,
unsigned long mode, void *cmd)
{
/* errata "Watch-dog/Software Reset Problem" specifies that
* this reset must be done with the SYSCLK sourced from
* EXTCLK instead of FOUT to avoid a glitch in the reset
* mechanism.
*
* See the watchdog section of the S3C2412 manual for more
* information on this fix.
*/
__raw_writel(0x00, reg_base + CLKSRC);
__raw_writel(0x533C2412, reg_base + SWRST);
return NOTIFY_DONE;
}
static struct notifier_block s3c2412_restart_handler = {
.notifier_call = s3c2412_restart,
.priority = 129,
};
/*
* fixed rate clocks generated outside the soc
* Only necessary until the devicetree-move is complete
*/
#define XTI 1
struct samsung_fixed_rate_clock s3c2412_common_frate_clks[] __initdata = {
FRATE(XTI, "xti", NULL, CLK_IS_ROOT, 0),
FRATE(0, "ext", NULL, CLK_IS_ROOT, 0),
};
static void __init s3c2412_common_clk_register_fixed_ext(
struct samsung_clk_provider *ctx,
unsigned long xti_f, unsigned long ext_f)
{
/* xtal alias is necessary for the current cpufreq driver */
struct samsung_clock_alias xti_alias = ALIAS(XTI, NULL, "xtal");
s3c2412_common_frate_clks[0].fixed_rate = xti_f;
s3c2412_common_frate_clks[1].fixed_rate = ext_f;
samsung_clk_register_fixed_rate(ctx, s3c2412_common_frate_clks,
ARRAY_SIZE(s3c2412_common_frate_clks));
samsung_clk_register_alias(ctx, &xti_alias, 1);
}
void __init s3c2412_common_clk_init(struct device_node *np, unsigned long xti_f,
unsigned long ext_f, void __iomem *base)
{
struct samsung_clk_provider *ctx;
int ret;
reg_base = base;
if (np) {
reg_base = of_iomap(np, 0);
if (!reg_base)
panic("%s: failed to map registers\n", __func__);
}
ctx = samsung_clk_init(np, reg_base, NR_CLKS);
if (!ctx)
panic("%s: unable to allocate context.\n", __func__);
/* Register external clocks only in non-dt cases */
if (!np)
s3c2412_common_clk_register_fixed_ext(ctx, xti_f, ext_f);
/* Register PLLs. */
samsung_clk_register_pll(ctx, s3c2412_plls, ARRAY_SIZE(s3c2412_plls),
reg_base);
/* Register common internal clocks. */
samsung_clk_register_mux(ctx, s3c2412_muxes, ARRAY_SIZE(s3c2412_muxes));
samsung_clk_register_div(ctx, s3c2412_dividers,
ARRAY_SIZE(s3c2412_dividers));
samsung_clk_register_gate(ctx, s3c2412_gates,
ARRAY_SIZE(s3c2412_gates));
samsung_clk_register_fixed_factor(ctx, s3c2412_ffactor,
ARRAY_SIZE(s3c2412_ffactor));
samsung_clk_register_alias(ctx, s3c2412_aliases,
ARRAY_SIZE(s3c2412_aliases));
s3c2412_clk_sleep_init();
samsung_clk_of_add_provider(np, ctx);
ret = register_restart_handler(&s3c2412_restart_handler);
if (ret)
pr_warn("cannot register restart handler, %d\n", ret);
}
static void __init s3c2412_clk_init(struct device_node *np)
{
s3c2412_common_clk_init(np, 0, 0, 0);
}
CLK_OF_DECLARE(s3c2412_clk, "samsung,s3c2412-clock", s3c2412_clk_init);

View file

@ -0,0 +1,487 @@
/*
* Copyright (c) 2013 Heiko Stuebner <heiko@sntech.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Common Clock Framework support for S3C2443 and following SoCs.
*/
#include <linux/clk.h>
#include <linux/clkdev.h>
#include <linux/clk-provider.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/syscore_ops.h>
#include <linux/reboot.h>
#include <dt-bindings/clock/s3c2443.h>
#include "clk.h"
#include "clk-pll.h"
/* S3C2416 clock controller register offsets */
#define LOCKCON0 0x00
#define LOCKCON1 0x04
#define MPLLCON 0x10
#define EPLLCON 0x18
#define EPLLCON_K 0x1C
#define CLKSRC 0x20
#define CLKDIV0 0x24
#define CLKDIV1 0x28
#define CLKDIV2 0x2C
#define HCLKCON 0x30
#define PCLKCON 0x34
#define SCLKCON 0x38
#define SWRST 0x44
/* the soc types */
enum supported_socs {
S3C2416,
S3C2443,
S3C2450,
};
/* list of PLLs to be registered */
enum s3c2443_plls {
mpll, epll,
};
static void __iomem *reg_base;
#ifdef CONFIG_PM_SLEEP
static struct samsung_clk_reg_dump *s3c2443_save;
/*
* list of controller registers to be saved and restored during a
* suspend/resume cycle.
*/
static unsigned long s3c2443_clk_regs[] __initdata = {
LOCKCON0,
LOCKCON1,
MPLLCON,
EPLLCON,
EPLLCON_K,
CLKSRC,
CLKDIV0,
CLKDIV1,
CLKDIV2,
PCLKCON,
HCLKCON,
SCLKCON,
};
static int s3c2443_clk_suspend(void)
{
samsung_clk_save(reg_base, s3c2443_save,
ARRAY_SIZE(s3c2443_clk_regs));
return 0;
}
static void s3c2443_clk_resume(void)
{
samsung_clk_restore(reg_base, s3c2443_save,
ARRAY_SIZE(s3c2443_clk_regs));
}
static struct syscore_ops s3c2443_clk_syscore_ops = {
.suspend = s3c2443_clk_suspend,
.resume = s3c2443_clk_resume,
};
static void s3c2443_clk_sleep_init(void)
{
s3c2443_save = samsung_clk_alloc_reg_dump(s3c2443_clk_regs,
ARRAY_SIZE(s3c2443_clk_regs));
if (!s3c2443_save) {
pr_warn("%s: failed to allocate sleep save data, no sleep support!\n",
__func__);
return;
}
register_syscore_ops(&s3c2443_clk_syscore_ops);
return;
}
#else
static void s3c2443_clk_sleep_init(void) {}
#endif
PNAME(epllref_p) = { "mpllref", "mpllref", "xti", "ext" };
PNAME(esysclk_p) = { "epllref", "epll" };
PNAME(mpllref_p) = { "xti", "mdivclk" };
PNAME(msysclk_p) = { "mpllref", "mpll" };
PNAME(armclk_p) = { "armdiv" , "hclk" };
PNAME(i2s0_p) = { "div_i2s0", "ext_i2s", "epllref", "epllref" };
struct samsung_mux_clock s3c2443_common_muxes[] __initdata = {
MUX(0, "epllref", epllref_p, CLKSRC, 7, 2),
MUX(ESYSCLK, "esysclk", esysclk_p, CLKSRC, 6, 1),
MUX(0, "mpllref", mpllref_p, CLKSRC, 3, 1),
MUX_A(MSYSCLK, "msysclk", msysclk_p, CLKSRC, 4, 1, "msysclk"),
MUX_A(ARMCLK, "armclk", armclk_p, CLKDIV0, 13, 1, "armclk"),
MUX(0, "mux_i2s0", i2s0_p, CLKSRC, 14, 2),
};
static struct clk_div_table hclk_d[] = {
{ .val = 0, .div = 1 },
{ .val = 1, .div = 2 },
{ .val = 3, .div = 4 },
{ /* sentinel */ },
};
static struct clk_div_table mdivclk_d[] = {
{ .val = 0, .div = 1 },
{ .val = 1, .div = 3 },
{ .val = 2, .div = 5 },
{ .val = 3, .div = 7 },
{ .val = 4, .div = 9 },
{ .val = 5, .div = 11 },
{ .val = 6, .div = 13 },
{ .val = 7, .div = 15 },
{ /* sentinel */ },
};
struct samsung_div_clock s3c2443_common_dividers[] __initdata = {
DIV_T(0, "mdivclk", "xti", CLKDIV0, 6, 3, mdivclk_d),
DIV(0, "prediv", "msysclk", CLKDIV0, 4, 2),
DIV_T(HCLK, "hclk", "prediv", CLKDIV0, 0, 2, hclk_d),
DIV(PCLK, "pclk", "hclk", CLKDIV0, 2, 1),
DIV(0, "div_hsspi0_epll", "esysclk", CLKDIV1, 24, 2),
DIV(0, "div_fimd", "esysclk", CLKDIV1, 16, 8),
DIV(0, "div_i2s0", "esysclk", CLKDIV1, 12, 4),
DIV(0, "div_uart", "esysclk", CLKDIV1, 8, 4),
DIV(0, "div_hsmmc1", "esysclk", CLKDIV1, 6, 2),
DIV(0, "div_usbhost", "esysclk", CLKDIV1, 4, 2),
};
struct samsung_gate_clock s3c2443_common_gates[] __initdata = {
GATE(SCLK_HSMMC_EXT, "sclk_hsmmcext", "ext", SCLKCON, 13, 0, 0),
GATE(SCLK_HSMMC1, "sclk_hsmmc1", "div_hsmmc1", SCLKCON, 12, 0, 0),
GATE(SCLK_FIMD, "sclk_fimd", "div_fimd", SCLKCON, 10, 0, 0),
GATE(SCLK_I2S0, "sclk_i2s0", "mux_i2s0", SCLKCON, 9, 0, 0),
GATE(SCLK_UART, "sclk_uart", "div_uart", SCLKCON, 8, 0, 0),
GATE(SCLK_USBH, "sclk_usbhost", "div_usbhost", SCLKCON, 1, 0, 0),
GATE(HCLK_DRAM, "dram", "hclk", HCLKCON, 19, CLK_IGNORE_UNUSED, 0),
GATE(HCLK_SSMC, "ssmc", "hclk", HCLKCON, 18, CLK_IGNORE_UNUSED, 0),
GATE(HCLK_HSMMC1, "hsmmc1", "hclk", HCLKCON, 16, 0, 0),
GATE(HCLK_USBD, "usb-device", "hclk", HCLKCON, 12, 0, 0),
GATE(HCLK_USBH, "usb-host", "hclk", HCLKCON, 11, 0, 0),
GATE(HCLK_LCD, "lcd", "hclk", HCLKCON, 9, 0, 0),
GATE(HCLK_DMA5, "dma5", "hclk", HCLKCON, 5, CLK_IGNORE_UNUSED, 0),
GATE(HCLK_DMA4, "dma4", "hclk", HCLKCON, 4, CLK_IGNORE_UNUSED, 0),
GATE(HCLK_DMA3, "dma3", "hclk", HCLKCON, 3, CLK_IGNORE_UNUSED, 0),
GATE(HCLK_DMA2, "dma2", "hclk", HCLKCON, 2, CLK_IGNORE_UNUSED, 0),
GATE(HCLK_DMA1, "dma1", "hclk", HCLKCON, 1, CLK_IGNORE_UNUSED, 0),
GATE(HCLK_DMA0, "dma0", "hclk", HCLKCON, 0, CLK_IGNORE_UNUSED, 0),
GATE(PCLK_GPIO, "gpio", "pclk", PCLKCON, 13, CLK_IGNORE_UNUSED, 0),
GATE(PCLK_RTC, "rtc", "pclk", PCLKCON, 12, 0, 0),
GATE(PCLK_WDT, "wdt", "pclk", PCLKCON, 11, 0, 0),
GATE(PCLK_PWM, "pwm", "pclk", PCLKCON, 10, 0, 0),
GATE(PCLK_I2S0, "i2s0", "pclk", PCLKCON, 9, 0, 0),
GATE(PCLK_AC97, "ac97", "pclk", PCLKCON, 8, 0, 0),
GATE(PCLK_ADC, "adc", "pclk", PCLKCON, 7, 0, 0),
GATE(PCLK_SPI0, "spi0", "pclk", PCLKCON, 6, 0, 0),
GATE(PCLK_I2C0, "i2c0", "pclk", PCLKCON, 4, 0, 0),
GATE(PCLK_UART3, "uart3", "pclk", PCLKCON, 3, 0, 0),
GATE(PCLK_UART2, "uart2", "pclk", PCLKCON, 2, 0, 0),
GATE(PCLK_UART1, "uart1", "pclk", PCLKCON, 1, 0, 0),
GATE(PCLK_UART0, "uart0", "pclk", PCLKCON, 0, 0, 0),
};
struct samsung_clock_alias s3c2443_common_aliases[] __initdata = {
ALIAS(HCLK, NULL, "hclk"),
ALIAS(HCLK_SSMC, NULL, "nand"),
ALIAS(PCLK_UART0, "s3c2440-uart.0", "uart"),
ALIAS(PCLK_UART1, "s3c2440-uart.1", "uart"),
ALIAS(PCLK_UART2, "s3c2440-uart.2", "uart"),
ALIAS(PCLK_UART3, "s3c2440-uart.3", "uart"),
ALIAS(PCLK_UART0, "s3c2440-uart.0", "clk_uart_baud2"),
ALIAS(PCLK_UART1, "s3c2440-uart.1", "clk_uart_baud2"),
ALIAS(PCLK_UART2, "s3c2440-uart.2", "clk_uart_baud2"),
ALIAS(PCLK_UART3, "s3c2440-uart.3", "clk_uart_baud2"),
ALIAS(SCLK_UART, NULL, "clk_uart_baud3"),
ALIAS(PCLK_PWM, NULL, "timers"),
ALIAS(PCLK_RTC, NULL, "rtc"),
ALIAS(PCLK_WDT, NULL, "watchdog"),
ALIAS(PCLK_ADC, NULL, "adc"),
ALIAS(PCLK_I2C0, "s3c2410-i2c.0", "i2c"),
ALIAS(HCLK_USBD, NULL, "usb-device"),
ALIAS(HCLK_USBH, NULL, "usb-host"),
ALIAS(SCLK_USBH, NULL, "usb-bus-host"),
ALIAS(PCLK_SPI0, "s3c2443-spi.0", "spi"),
ALIAS(PCLK_SPI0, "s3c2443-spi.0", "spi_busclk0"),
ALIAS(HCLK_HSMMC1, "s3c-sdhci.1", "hsmmc"),
ALIAS(HCLK_HSMMC1, "s3c-sdhci.1", "mmc_busclk.0"),
ALIAS(PCLK_I2S0, "samsung-i2s.0", "iis"),
ALIAS(SCLK_I2S0, NULL, "i2s-if"),
ALIAS(HCLK_LCD, NULL, "lcd"),
ALIAS(SCLK_FIMD, NULL, "sclk_fimd"),
};
/* S3C2416 specific clocks */
static struct samsung_pll_clock s3c2416_pll_clks[] __initdata = {
[mpll] = PLL(pll_6552_s3c2416, 0, "mpll", "mpllref",
LOCKCON0, MPLLCON, NULL),
[epll] = PLL(pll_6553, 0, "epll", "epllref",
LOCKCON1, EPLLCON, NULL),
};
PNAME(s3c2416_hsmmc0_p) = { "sclk_hsmmc0", "sclk_hsmmcext" };
PNAME(s3c2416_hsmmc1_p) = { "sclk_hsmmc1", "sclk_hsmmcext" };
PNAME(s3c2416_hsspi0_p) = { "hsspi0_epll", "hsspi0_mpll" };
static struct clk_div_table armdiv_s3c2416_d[] = {
{ .val = 0, .div = 1 },
{ .val = 1, .div = 2 },
{ .val = 2, .div = 3 },
{ .val = 3, .div = 4 },
{ .val = 5, .div = 6 },
{ .val = 7, .div = 8 },
{ /* sentinel */ },
};
struct samsung_div_clock s3c2416_dividers[] __initdata = {
DIV_T(ARMDIV, "armdiv", "msysclk", CLKDIV0, 9, 3, armdiv_s3c2416_d),
DIV(0, "div_hsspi0_mpll", "msysclk", CLKDIV2, 0, 4),
DIV(0, "div_hsmmc0", "esysclk", CLKDIV2, 6, 2),
};
struct samsung_mux_clock s3c2416_muxes[] __initdata = {
MUX(MUX_HSMMC0, "mux_hsmmc0", s3c2416_hsmmc0_p, CLKSRC, 16, 1),
MUX(MUX_HSMMC1, "mux_hsmmc1", s3c2416_hsmmc1_p, CLKSRC, 17, 1),
MUX(MUX_HSSPI0, "mux_hsspi0", s3c2416_hsspi0_p, CLKSRC, 18, 1),
};
struct samsung_gate_clock s3c2416_gates[] __initdata = {
GATE(0, "hsspi0_mpll", "div_hsspi0_mpll", SCLKCON, 19, 0, 0),
GATE(0, "hsspi0_epll", "div_hsspi0_epll", SCLKCON, 14, 0, 0),
GATE(0, "sclk_hsmmc0", "div_hsmmc0", SCLKCON, 6, 0, 0),
GATE(HCLK_2D, "2d", "hclk", HCLKCON, 20, 0, 0),
GATE(HCLK_HSMMC0, "hsmmc0", "hclk", HCLKCON, 15, 0, 0),
GATE(HCLK_IROM, "irom", "hclk", HCLKCON, 13, CLK_IGNORE_UNUSED, 0),
GATE(PCLK_PCM, "pcm", "pclk", PCLKCON, 19, 0, 0),
};
struct samsung_clock_alias s3c2416_aliases[] __initdata = {
ALIAS(HCLK_HSMMC0, "s3c-sdhci.0", "hsmmc"),
ALIAS(HCLK_HSMMC0, "s3c-sdhci.0", "mmc_busclk.0"),
ALIAS(MUX_HSMMC0, "s3c-sdhci.0", "mmc_busclk.2"),
ALIAS(MUX_HSMMC1, "s3c-sdhci.1", "mmc_busclk.2"),
ALIAS(MUX_HSSPI0, "s3c2443-spi.0", "spi_busclk2"),
ALIAS(ARMDIV, NULL, "armdiv"),
};
/* S3C2443 specific clocks */
static struct samsung_pll_clock s3c2443_pll_clks[] __initdata = {
[mpll] = PLL(pll_3000, 0, "mpll", "mpllref",
LOCKCON0, MPLLCON, NULL),
[epll] = PLL(pll_2126, 0, "epll", "epllref",
LOCKCON1, EPLLCON, NULL),
};
static struct clk_div_table armdiv_s3c2443_d[] = {
{ .val = 0, .div = 1 },
{ .val = 8, .div = 2 },
{ .val = 2, .div = 3 },
{ .val = 9, .div = 4 },
{ .val = 10, .div = 6 },
{ .val = 11, .div = 8 },
{ .val = 13, .div = 12 },
{ .val = 15, .div = 16 },
{ /* sentinel */ },
};
struct samsung_div_clock s3c2443_dividers[] __initdata = {
DIV_T(ARMDIV, "armdiv", "msysclk", CLKDIV0, 9, 4, armdiv_s3c2443_d),
DIV(0, "div_cam", "esysclk", CLKDIV1, 26, 4),
};
struct samsung_gate_clock s3c2443_gates[] __initdata = {
GATE(SCLK_HSSPI0, "sclk_hsspi0", "div_hsspi0_epll", SCLKCON, 14, 0, 0),
GATE(SCLK_CAM, "sclk_cam", "div_cam", SCLKCON, 11, 0, 0),
GATE(HCLK_CFC, "cfc", "hclk", HCLKCON, 17, CLK_IGNORE_UNUSED, 0),
GATE(HCLK_CAM, "cam", "hclk", HCLKCON, 8, 0, 0),
GATE(PCLK_SPI1, "spi1", "pclk", PCLKCON, 15, 0, 0),
GATE(PCLK_SDI, "sdi", "pclk", PCLKCON, 5, 0, 0),
};
struct samsung_clock_alias s3c2443_aliases[] __initdata = {
ALIAS(SCLK_HSSPI0, "s3c2443-spi.0", "spi_busclk2"),
ALIAS(SCLK_HSMMC1, "s3c-sdhci.1", "mmc_busclk.2"),
ALIAS(SCLK_CAM, NULL, "camif-upll"),
ALIAS(PCLK_SPI1, "s3c2410-spi.0", "spi"),
ALIAS(PCLK_SDI, NULL, "sdi"),
ALIAS(HCLK_CFC, NULL, "cfc"),
ALIAS(ARMDIV, NULL, "armdiv"),
};
/* S3C2450 specific clocks */
PNAME(s3c2450_cam_p) = { "div_cam", "hclk" };
PNAME(s3c2450_hsspi1_p) = { "hsspi1_epll", "hsspi1_mpll" };
PNAME(i2s1_p) = { "div_i2s1", "ext_i2s", "epllref", "epllref" };
struct samsung_div_clock s3c2450_dividers[] __initdata = {
DIV(0, "div_cam", "esysclk", CLKDIV1, 26, 4),
DIV(0, "div_hsspi1_epll", "esysclk", CLKDIV2, 24, 2),
DIV(0, "div_hsspi1_mpll", "msysclk", CLKDIV2, 16, 4),
DIV(0, "div_i2s1", "esysclk", CLKDIV2, 12, 4),
};
struct samsung_mux_clock s3c2450_muxes[] __initdata = {
MUX(0, "mux_cam", s3c2450_cam_p, CLKSRC, 20, 1),
MUX(MUX_HSSPI1, "mux_hsspi1", s3c2450_hsspi1_p, CLKSRC, 19, 1),
MUX(0, "mux_i2s1", i2s1_p, CLKSRC, 12, 2),
};
struct samsung_gate_clock s3c2450_gates[] __initdata = {
GATE(SCLK_I2S1, "sclk_i2s1", "div_i2s1", SCLKCON, 5, 0, 0),
GATE(HCLK_CFC, "cfc", "hclk", HCLKCON, 17, 0, 0),
GATE(HCLK_CAM, "cam", "hclk", HCLKCON, 8, 0, 0),
GATE(HCLK_DMA7, "dma7", "hclk", HCLKCON, 7, CLK_IGNORE_UNUSED, 0),
GATE(HCLK_DMA6, "dma6", "hclk", HCLKCON, 6, CLK_IGNORE_UNUSED, 0),
GATE(PCLK_I2S1, "i2s1", "pclk", PCLKCON, 17, 0, 0),
GATE(PCLK_I2C1, "i2c1", "pclk", PCLKCON, 16, 0, 0),
GATE(PCLK_SPI1, "spi1", "pclk", PCLKCON, 14, 0, 0),
};
struct samsung_clock_alias s3c2450_aliases[] __initdata = {
ALIAS(PCLK_SPI1, "s3c2443-spi.1", "spi"),
ALIAS(PCLK_SPI1, "s3c2443-spi.1", "spi_busclk0"),
ALIAS(MUX_HSSPI1, "s3c2443-spi.1", "spi_busclk2"),
ALIAS(PCLK_I2C1, "s3c2410-i2c.1", "i2c"),
};
static int s3c2443_restart(struct notifier_block *this,
unsigned long mode, void *cmd)
{
__raw_writel(0x533c2443, reg_base + SWRST);
return NOTIFY_DONE;
}
static struct notifier_block s3c2443_restart_handler = {
.notifier_call = s3c2443_restart,
.priority = 129,
};
/*
* fixed rate clocks generated outside the soc
* Only necessary until the devicetree-move is complete
*/
struct samsung_fixed_rate_clock s3c2443_common_frate_clks[] __initdata = {
FRATE(0, "xti", NULL, CLK_IS_ROOT, 0),
FRATE(0, "ext", NULL, CLK_IS_ROOT, 0),
FRATE(0, "ext_i2s", NULL, CLK_IS_ROOT, 0),
FRATE(0, "ext_uart", NULL, CLK_IS_ROOT, 0),
};
static void __init s3c2443_common_clk_register_fixed_ext(
struct samsung_clk_provider *ctx, unsigned long xti_f)
{
s3c2443_common_frate_clks[0].fixed_rate = xti_f;
samsung_clk_register_fixed_rate(ctx, s3c2443_common_frate_clks,
ARRAY_SIZE(s3c2443_common_frate_clks));
}
void __init s3c2443_common_clk_init(struct device_node *np, unsigned long xti_f,
int current_soc,
void __iomem *base)
{
struct samsung_clk_provider *ctx;
int ret;
reg_base = base;
if (np) {
reg_base = of_iomap(np, 0);
if (!reg_base)
panic("%s: failed to map registers\n", __func__);
}
ctx = samsung_clk_init(np, reg_base, NR_CLKS);
if (!ctx)
panic("%s: unable to allocate context.\n", __func__);
/* Register external clocks only in non-dt cases */
if (!np)
s3c2443_common_clk_register_fixed_ext(ctx, xti_f);
/* Register PLLs. */
if (current_soc == S3C2416 || current_soc == S3C2450)
samsung_clk_register_pll(ctx, s3c2416_pll_clks,
ARRAY_SIZE(s3c2416_pll_clks), reg_base);
else
samsung_clk_register_pll(ctx, s3c2443_pll_clks,
ARRAY_SIZE(s3c2443_pll_clks), reg_base);
/* Register common internal clocks. */
samsung_clk_register_mux(ctx, s3c2443_common_muxes,
ARRAY_SIZE(s3c2443_common_muxes));
samsung_clk_register_div(ctx, s3c2443_common_dividers,
ARRAY_SIZE(s3c2443_common_dividers));
samsung_clk_register_gate(ctx, s3c2443_common_gates,
ARRAY_SIZE(s3c2443_common_gates));
samsung_clk_register_alias(ctx, s3c2443_common_aliases,
ARRAY_SIZE(s3c2443_common_aliases));
/* Register SoC-specific clocks. */
switch (current_soc) {
case S3C2450:
samsung_clk_register_div(ctx, s3c2450_dividers,
ARRAY_SIZE(s3c2450_dividers));
samsung_clk_register_mux(ctx, s3c2450_muxes,
ARRAY_SIZE(s3c2450_muxes));
samsung_clk_register_gate(ctx, s3c2450_gates,
ARRAY_SIZE(s3c2450_gates));
samsung_clk_register_alias(ctx, s3c2450_aliases,
ARRAY_SIZE(s3c2450_aliases));
/* fall through, as s3c2450 extends the s3c2416 clocks */
case S3C2416:
samsung_clk_register_div(ctx, s3c2416_dividers,
ARRAY_SIZE(s3c2416_dividers));
samsung_clk_register_mux(ctx, s3c2416_muxes,
ARRAY_SIZE(s3c2416_muxes));
samsung_clk_register_gate(ctx, s3c2416_gates,
ARRAY_SIZE(s3c2416_gates));
samsung_clk_register_alias(ctx, s3c2416_aliases,
ARRAY_SIZE(s3c2416_aliases));
break;
case S3C2443:
samsung_clk_register_div(ctx, s3c2443_dividers,
ARRAY_SIZE(s3c2443_dividers));
samsung_clk_register_gate(ctx, s3c2443_gates,
ARRAY_SIZE(s3c2443_gates));
samsung_clk_register_alias(ctx, s3c2443_aliases,
ARRAY_SIZE(s3c2443_aliases));
break;
}
s3c2443_clk_sleep_init();
samsung_clk_of_add_provider(np, ctx);
ret = register_restart_handler(&s3c2443_restart_handler);
if (ret)
pr_warn("cannot register restart handler, %d\n", ret);
}
static void __init s3c2416_clk_init(struct device_node *np)
{
s3c2443_common_clk_init(np, 0, S3C2416, 0);
}
CLK_OF_DECLARE(s3c2416_clk, "samsung,s3c2416-clock", s3c2416_clk_init);
static void __init s3c2443_clk_init(struct device_node *np)
{
s3c2443_common_clk_init(np, 0, S3C2443, 0);
}
CLK_OF_DECLARE(s3c2443_clk, "samsung,s3c2443-clock", s3c2443_clk_init);
static void __init s3c2450_clk_init(struct device_node *np)
{
s3c2443_common_clk_init(np, 0, S3C2450, 0);
}
CLK_OF_DECLARE(s3c2450_clk, "samsung,s3c2450-clock", s3c2450_clk_init);

View file

@ -0,0 +1,540 @@
/*
* Copyright (c) 2013 Tomasz Figa <tomasz.figa at gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Common Clock Framework support for all S3C64xx SoCs.
*/
#include <linux/clk.h>
#include <linux/clkdev.h>
#include <linux/clk-provider.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/syscore_ops.h>
#include <dt-bindings/clock/samsung,s3c64xx-clock.h>
#include "clk.h"
#include "clk-pll.h"
/* S3C64xx clock controller register offsets. */
#define APLL_LOCK 0x000
#define MPLL_LOCK 0x004
#define EPLL_LOCK 0x008
#define APLL_CON 0x00c
#define MPLL_CON 0x010
#define EPLL_CON0 0x014
#define EPLL_CON1 0x018
#define CLK_SRC 0x01c
#define CLK_DIV0 0x020
#define CLK_DIV1 0x024
#define CLK_DIV2 0x028
#define HCLK_GATE 0x030
#define PCLK_GATE 0x034
#define SCLK_GATE 0x038
#define MEM0_GATE 0x03c
#define CLK_SRC2 0x10c
#define OTHERS 0x900
/* Helper macros to define clock arrays. */
#define FIXED_RATE_CLOCKS(name) \
static struct samsung_fixed_rate_clock name[]
#define MUX_CLOCKS(name) \
static struct samsung_mux_clock name[]
#define DIV_CLOCKS(name) \
static struct samsung_div_clock name[]
#define GATE_CLOCKS(name) \
static struct samsung_gate_clock name[]
/* Helper macros for gate types present on S3C64xx. */
#define GATE_BUS(_id, cname, pname, o, b) \
GATE(_id, cname, pname, o, b, 0, 0)
#define GATE_SCLK(_id, cname, pname, o, b) \
GATE(_id, cname, pname, o, b, CLK_SET_RATE_PARENT, 0)
#define GATE_ON(_id, cname, pname, o, b) \
GATE(_id, cname, pname, o, b, CLK_IGNORE_UNUSED, 0)
/* list of PLLs to be registered */
enum s3c64xx_plls {
apll, mpll, epll,
};
static void __iomem *reg_base;
static bool is_s3c6400;
#ifdef CONFIG_PM_SLEEP
static struct samsung_clk_reg_dump *s3c64xx_save_common;
static struct samsung_clk_reg_dump *s3c64xx_save_soc;
/*
* List of controller registers to be saved and restored during
* a suspend/resume cycle.
*/
static unsigned long s3c64xx_clk_regs[] __initdata = {
APLL_LOCK,
MPLL_LOCK,
EPLL_LOCK,
APLL_CON,
MPLL_CON,
EPLL_CON0,
EPLL_CON1,
CLK_SRC,
CLK_DIV0,
CLK_DIV1,
CLK_DIV2,
HCLK_GATE,
PCLK_GATE,
SCLK_GATE,
};
static unsigned long s3c6410_clk_regs[] __initdata = {
CLK_SRC2,
MEM0_GATE,
};
static int s3c64xx_clk_suspend(void)
{
samsung_clk_save(reg_base, s3c64xx_save_common,
ARRAY_SIZE(s3c64xx_clk_regs));
if (!is_s3c6400)
samsung_clk_save(reg_base, s3c64xx_save_soc,
ARRAY_SIZE(s3c6410_clk_regs));
return 0;
}
static void s3c64xx_clk_resume(void)
{
samsung_clk_restore(reg_base, s3c64xx_save_common,
ARRAY_SIZE(s3c64xx_clk_regs));
if (!is_s3c6400)
samsung_clk_restore(reg_base, s3c64xx_save_soc,
ARRAY_SIZE(s3c6410_clk_regs));
}
static struct syscore_ops s3c64xx_clk_syscore_ops = {
.suspend = s3c64xx_clk_suspend,
.resume = s3c64xx_clk_resume,
};
static void s3c64xx_clk_sleep_init(void)
{
s3c64xx_save_common = samsung_clk_alloc_reg_dump(s3c64xx_clk_regs,
ARRAY_SIZE(s3c64xx_clk_regs));
if (!s3c64xx_save_common)
goto err_warn;
if (!is_s3c6400) {
s3c64xx_save_soc = samsung_clk_alloc_reg_dump(s3c6410_clk_regs,
ARRAY_SIZE(s3c6410_clk_regs));
if (!s3c64xx_save_soc)
goto err_soc;
}
register_syscore_ops(&s3c64xx_clk_syscore_ops);
return;
err_soc:
kfree(s3c64xx_save_common);
err_warn:
pr_warn("%s: failed to allocate sleep save data, no sleep support!\n",
__func__);
}
#else
static void s3c64xx_clk_sleep_init(void) {}
#endif
/* List of parent clocks common for all S3C64xx SoCs. */
PNAME(spi_mmc_p) = { "mout_epll", "dout_mpll", "fin_pll", "clk27m" };
PNAME(uart_p) = { "mout_epll", "dout_mpll" };
PNAME(audio0_p) = { "mout_epll", "dout_mpll", "fin_pll", "iiscdclk0",
"pcmcdclk0", "none", "none", "none" };
PNAME(audio1_p) = { "mout_epll", "dout_mpll", "fin_pll", "iiscdclk1",
"pcmcdclk0", "none", "none", "none" };
PNAME(mfc_p) = { "hclkx2", "mout_epll" };
PNAME(apll_p) = { "fin_pll", "fout_apll" };
PNAME(mpll_p) = { "fin_pll", "fout_mpll" };
PNAME(epll_p) = { "fin_pll", "fout_epll" };
PNAME(hclkx2_p) = { "mout_mpll", "mout_apll" };
/* S3C6400-specific parent clocks. */
PNAME(scaler_lcd_p6400) = { "mout_epll", "dout_mpll", "none", "none" };
PNAME(irda_p6400) = { "mout_epll", "dout_mpll", "none", "clk48m" };
PNAME(uhost_p6400) = { "clk48m", "mout_epll", "dout_mpll", "none" };
/* S3C6410-specific parent clocks. */
PNAME(clk27_p6410) = { "clk27m", "fin_pll" };
PNAME(scaler_lcd_p6410) = { "mout_epll", "dout_mpll", "fin_pll", "none" };
PNAME(irda_p6410) = { "mout_epll", "dout_mpll", "fin_pll", "clk48m" };
PNAME(uhost_p6410) = { "clk48m", "mout_epll", "dout_mpll", "fin_pll" };
PNAME(audio2_p6410) = { "mout_epll", "dout_mpll", "fin_pll", "iiscdclk2",
"pcmcdclk1", "none", "none", "none" };
/* Fixed rate clocks generated outside the SoC. */
FIXED_RATE_CLOCKS(s3c64xx_fixed_rate_ext_clks) __initdata = {
FRATE(0, "fin_pll", NULL, CLK_IS_ROOT, 0),
FRATE(0, "xusbxti", NULL, CLK_IS_ROOT, 0),
};
/* Fixed rate clocks generated inside the SoC. */
FIXED_RATE_CLOCKS(s3c64xx_fixed_rate_clks) __initdata = {
FRATE(CLK27M, "clk27m", NULL, CLK_IS_ROOT, 27000000),
FRATE(CLK48M, "clk48m", NULL, CLK_IS_ROOT, 48000000),
};
/* List of clock muxes present on all S3C64xx SoCs. */
MUX_CLOCKS(s3c64xx_mux_clks) __initdata = {
MUX_F(0, "mout_syncmux", hclkx2_p, OTHERS, 6, 1, 0, CLK_MUX_READ_ONLY),
MUX(MOUT_APLL, "mout_apll", apll_p, CLK_SRC, 0, 1),
MUX(MOUT_MPLL, "mout_mpll", mpll_p, CLK_SRC, 1, 1),
MUX(MOUT_EPLL, "mout_epll", epll_p, CLK_SRC, 2, 1),
MUX(MOUT_MFC, "mout_mfc", mfc_p, CLK_SRC, 4, 1),
MUX(MOUT_AUDIO0, "mout_audio0", audio0_p, CLK_SRC, 7, 3),
MUX(MOUT_AUDIO1, "mout_audio1", audio1_p, CLK_SRC, 10, 3),
MUX(MOUT_UART, "mout_uart", uart_p, CLK_SRC, 13, 1),
MUX(MOUT_SPI0, "mout_spi0", spi_mmc_p, CLK_SRC, 14, 2),
MUX(MOUT_SPI1, "mout_spi1", spi_mmc_p, CLK_SRC, 16, 2),
MUX(MOUT_MMC0, "mout_mmc0", spi_mmc_p, CLK_SRC, 18, 2),
MUX(MOUT_MMC1, "mout_mmc1", spi_mmc_p, CLK_SRC, 20, 2),
MUX(MOUT_MMC2, "mout_mmc2", spi_mmc_p, CLK_SRC, 22, 2),
};
/* List of clock muxes present on S3C6400. */
MUX_CLOCKS(s3c6400_mux_clks) __initdata = {
MUX(MOUT_UHOST, "mout_uhost", uhost_p6400, CLK_SRC, 5, 2),
MUX(MOUT_IRDA, "mout_irda", irda_p6400, CLK_SRC, 24, 2),
MUX(MOUT_LCD, "mout_lcd", scaler_lcd_p6400, CLK_SRC, 26, 2),
MUX(MOUT_SCALER, "mout_scaler", scaler_lcd_p6400, CLK_SRC, 28, 2),
};
/* List of clock muxes present on S3C6410. */
MUX_CLOCKS(s3c6410_mux_clks) __initdata = {
MUX(MOUT_UHOST, "mout_uhost", uhost_p6410, CLK_SRC, 5, 2),
MUX(MOUT_IRDA, "mout_irda", irda_p6410, CLK_SRC, 24, 2),
MUX(MOUT_LCD, "mout_lcd", scaler_lcd_p6410, CLK_SRC, 26, 2),
MUX(MOUT_SCALER, "mout_scaler", scaler_lcd_p6410, CLK_SRC, 28, 2),
MUX(MOUT_DAC27, "mout_dac27", clk27_p6410, CLK_SRC, 30, 1),
MUX(MOUT_TV27, "mout_tv27", clk27_p6410, CLK_SRC, 31, 1),
MUX(MOUT_AUDIO2, "mout_audio2", audio2_p6410, CLK_SRC2, 0, 3),
};
/* List of clock dividers present on all S3C64xx SoCs. */
DIV_CLOCKS(s3c64xx_div_clks) __initdata = {
DIV(DOUT_MPLL, "dout_mpll", "mout_mpll", CLK_DIV0, 4, 1),
DIV(HCLKX2, "hclkx2", "mout_syncmux", CLK_DIV0, 9, 3),
DIV(HCLK, "hclk", "hclkx2", CLK_DIV0, 8, 1),
DIV(PCLK, "pclk", "hclkx2", CLK_DIV0, 12, 4),
DIV(DOUT_SECUR, "dout_secur", "hclkx2", CLK_DIV0, 18, 2),
DIV(DOUT_CAM, "dout_cam", "hclkx2", CLK_DIV0, 20, 4),
DIV(DOUT_JPEG, "dout_jpeg", "hclkx2", CLK_DIV0, 24, 4),
DIV(DOUT_MFC, "dout_mfc", "mout_mfc", CLK_DIV0, 28, 4),
DIV(DOUT_MMC0, "dout_mmc0", "mout_mmc0", CLK_DIV1, 0, 4),
DIV(DOUT_MMC1, "dout_mmc1", "mout_mmc1", CLK_DIV1, 4, 4),
DIV(DOUT_MMC2, "dout_mmc2", "mout_mmc2", CLK_DIV1, 8, 4),
DIV(DOUT_LCD, "dout_lcd", "mout_lcd", CLK_DIV1, 12, 4),
DIV(DOUT_SCALER, "dout_scaler", "mout_scaler", CLK_DIV1, 16, 4),
DIV(DOUT_UHOST, "dout_uhost", "mout_uhost", CLK_DIV1, 20, 4),
DIV(DOUT_SPI0, "dout_spi0", "mout_spi0", CLK_DIV2, 0, 4),
DIV(DOUT_SPI1, "dout_spi1", "mout_spi1", CLK_DIV2, 4, 4),
DIV(DOUT_AUDIO0, "dout_audio0", "mout_audio0", CLK_DIV2, 8, 4),
DIV(DOUT_AUDIO1, "dout_audio1", "mout_audio1", CLK_DIV2, 12, 4),
DIV(DOUT_UART, "dout_uart", "mout_uart", CLK_DIV2, 16, 4),
DIV(DOUT_IRDA, "dout_irda", "mout_irda", CLK_DIV2, 20, 4),
};
/* List of clock dividers present on S3C6400. */
DIV_CLOCKS(s3c6400_div_clks) __initdata = {
DIV(ARMCLK, "armclk", "mout_apll", CLK_DIV0, 0, 3),
};
/* List of clock dividers present on S3C6410. */
DIV_CLOCKS(s3c6410_div_clks) __initdata = {
DIV(ARMCLK, "armclk", "mout_apll", CLK_DIV0, 0, 4),
DIV(DOUT_FIMC, "dout_fimc", "hclk", CLK_DIV1, 24, 4),
DIV(DOUT_AUDIO2, "dout_audio2", "mout_audio2", CLK_DIV2, 24, 4),
};
/* List of clock gates present on all S3C64xx SoCs. */
GATE_CLOCKS(s3c64xx_gate_clks) __initdata = {
GATE_BUS(HCLK_UHOST, "hclk_uhost", "hclk", HCLK_GATE, 29),
GATE_BUS(HCLK_SECUR, "hclk_secur", "hclk", HCLK_GATE, 28),
GATE_BUS(HCLK_SDMA1, "hclk_sdma1", "hclk", HCLK_GATE, 27),
GATE_BUS(HCLK_SDMA0, "hclk_sdma0", "hclk", HCLK_GATE, 26),
GATE_ON(HCLK_DDR1, "hclk_ddr1", "hclk", HCLK_GATE, 24),
GATE_BUS(HCLK_USB, "hclk_usb", "hclk", HCLK_GATE, 20),
GATE_BUS(HCLK_HSMMC2, "hclk_hsmmc2", "hclk", HCLK_GATE, 19),
GATE_BUS(HCLK_HSMMC1, "hclk_hsmmc1", "hclk", HCLK_GATE, 18),
GATE_BUS(HCLK_HSMMC0, "hclk_hsmmc0", "hclk", HCLK_GATE, 17),
GATE_BUS(HCLK_MDP, "hclk_mdp", "hclk", HCLK_GATE, 16),
GATE_BUS(HCLK_DHOST, "hclk_dhost", "hclk", HCLK_GATE, 15),
GATE_BUS(HCLK_IHOST, "hclk_ihost", "hclk", HCLK_GATE, 14),
GATE_BUS(HCLK_DMA1, "hclk_dma1", "hclk", HCLK_GATE, 13),
GATE_BUS(HCLK_DMA0, "hclk_dma0", "hclk", HCLK_GATE, 12),
GATE_BUS(HCLK_JPEG, "hclk_jpeg", "hclk", HCLK_GATE, 11),
GATE_BUS(HCLK_CAMIF, "hclk_camif", "hclk", HCLK_GATE, 10),
GATE_BUS(HCLK_SCALER, "hclk_scaler", "hclk", HCLK_GATE, 9),
GATE_BUS(HCLK_2D, "hclk_2d", "hclk", HCLK_GATE, 8),
GATE_BUS(HCLK_TV, "hclk_tv", "hclk", HCLK_GATE, 7),
GATE_BUS(HCLK_POST0, "hclk_post0", "hclk", HCLK_GATE, 5),
GATE_BUS(HCLK_ROT, "hclk_rot", "hclk", HCLK_GATE, 4),
GATE_BUS(HCLK_LCD, "hclk_lcd", "hclk", HCLK_GATE, 3),
GATE_BUS(HCLK_TZIC, "hclk_tzic", "hclk", HCLK_GATE, 2),
GATE_ON(HCLK_INTC, "hclk_intc", "hclk", HCLK_GATE, 1),
GATE_ON(PCLK_SKEY, "pclk_skey", "pclk", PCLK_GATE, 24),
GATE_ON(PCLK_CHIPID, "pclk_chipid", "pclk", PCLK_GATE, 23),
GATE_BUS(PCLK_SPI1, "pclk_spi1", "pclk", PCLK_GATE, 22),
GATE_BUS(PCLK_SPI0, "pclk_spi0", "pclk", PCLK_GATE, 21),
GATE_BUS(PCLK_HSIRX, "pclk_hsirx", "pclk", PCLK_GATE, 20),
GATE_BUS(PCLK_HSITX, "pclk_hsitx", "pclk", PCLK_GATE, 19),
GATE_ON(PCLK_GPIO, "pclk_gpio", "pclk", PCLK_GATE, 18),
GATE_BUS(PCLK_IIC0, "pclk_iic0", "pclk", PCLK_GATE, 17),
GATE_BUS(PCLK_IIS1, "pclk_iis1", "pclk", PCLK_GATE, 16),
GATE_BUS(PCLK_IIS0, "pclk_iis0", "pclk", PCLK_GATE, 15),
GATE_BUS(PCLK_AC97, "pclk_ac97", "pclk", PCLK_GATE, 14),
GATE_BUS(PCLK_TZPC, "pclk_tzpc", "pclk", PCLK_GATE, 13),
GATE_BUS(PCLK_TSADC, "pclk_tsadc", "pclk", PCLK_GATE, 12),
GATE_BUS(PCLK_KEYPAD, "pclk_keypad", "pclk", PCLK_GATE, 11),
GATE_BUS(PCLK_IRDA, "pclk_irda", "pclk", PCLK_GATE, 10),
GATE_BUS(PCLK_PCM1, "pclk_pcm1", "pclk", PCLK_GATE, 9),
GATE_BUS(PCLK_PCM0, "pclk_pcm0", "pclk", PCLK_GATE, 8),
GATE_BUS(PCLK_PWM, "pclk_pwm", "pclk", PCLK_GATE, 7),
GATE_BUS(PCLK_RTC, "pclk_rtc", "pclk", PCLK_GATE, 6),
GATE_BUS(PCLK_WDT, "pclk_wdt", "pclk", PCLK_GATE, 5),
GATE_BUS(PCLK_UART3, "pclk_uart3", "pclk", PCLK_GATE, 4),
GATE_BUS(PCLK_UART2, "pclk_uart2", "pclk", PCLK_GATE, 3),
GATE_BUS(PCLK_UART1, "pclk_uart1", "pclk", PCLK_GATE, 2),
GATE_BUS(PCLK_UART0, "pclk_uart0", "pclk", PCLK_GATE, 1),
GATE_BUS(PCLK_MFC, "pclk_mfc", "pclk", PCLK_GATE, 0),
GATE_SCLK(SCLK_UHOST, "sclk_uhost", "dout_uhost", SCLK_GATE, 30),
GATE_SCLK(SCLK_MMC2_48, "sclk_mmc2_48", "clk48m", SCLK_GATE, 29),
GATE_SCLK(SCLK_MMC1_48, "sclk_mmc1_48", "clk48m", SCLK_GATE, 28),
GATE_SCLK(SCLK_MMC0_48, "sclk_mmc0_48", "clk48m", SCLK_GATE, 27),
GATE_SCLK(SCLK_MMC2, "sclk_mmc2", "dout_mmc2", SCLK_GATE, 26),
GATE_SCLK(SCLK_MMC1, "sclk_mmc1", "dout_mmc1", SCLK_GATE, 25),
GATE_SCLK(SCLK_MMC0, "sclk_mmc0", "dout_mmc0", SCLK_GATE, 24),
GATE_SCLK(SCLK_SPI1_48, "sclk_spi1_48", "clk48m", SCLK_GATE, 23),
GATE_SCLK(SCLK_SPI0_48, "sclk_spi0_48", "clk48m", SCLK_GATE, 22),
GATE_SCLK(SCLK_SPI1, "sclk_spi1", "dout_spi1", SCLK_GATE, 21),
GATE_SCLK(SCLK_SPI0, "sclk_spi0", "dout_spi0", SCLK_GATE, 20),
GATE_SCLK(SCLK_DAC27, "sclk_dac27", "mout_dac27", SCLK_GATE, 19),
GATE_SCLK(SCLK_TV27, "sclk_tv27", "mout_tv27", SCLK_GATE, 18),
GATE_SCLK(SCLK_SCALER27, "sclk_scaler27", "clk27m", SCLK_GATE, 17),
GATE_SCLK(SCLK_SCALER, "sclk_scaler", "dout_scaler", SCLK_GATE, 16),
GATE_SCLK(SCLK_LCD27, "sclk_lcd27", "clk27m", SCLK_GATE, 15),
GATE_SCLK(SCLK_LCD, "sclk_lcd", "dout_lcd", SCLK_GATE, 14),
GATE_SCLK(SCLK_POST0_27, "sclk_post0_27", "clk27m", SCLK_GATE, 12),
GATE_SCLK(SCLK_POST0, "sclk_post0", "dout_lcd", SCLK_GATE, 10),
GATE_SCLK(SCLK_AUDIO1, "sclk_audio1", "dout_audio1", SCLK_GATE, 9),
GATE_SCLK(SCLK_AUDIO0, "sclk_audio0", "dout_audio0", SCLK_GATE, 8),
GATE_SCLK(SCLK_SECUR, "sclk_secur", "dout_secur", SCLK_GATE, 7),
GATE_SCLK(SCLK_IRDA, "sclk_irda", "dout_irda", SCLK_GATE, 6),
GATE_SCLK(SCLK_UART, "sclk_uart", "dout_uart", SCLK_GATE, 5),
GATE_SCLK(SCLK_MFC, "sclk_mfc", "dout_mfc", SCLK_GATE, 3),
GATE_SCLK(SCLK_CAM, "sclk_cam", "dout_cam", SCLK_GATE, 2),
GATE_SCLK(SCLK_JPEG, "sclk_jpeg", "dout_jpeg", SCLK_GATE, 1),
};
/* List of clock gates present on S3C6400. */
GATE_CLOCKS(s3c6400_gate_clks) __initdata = {
GATE_ON(HCLK_DDR0, "hclk_ddr0", "hclk", HCLK_GATE, 23),
GATE_SCLK(SCLK_ONENAND, "sclk_onenand", "parent", SCLK_GATE, 4),
};
/* List of clock gates present on S3C6410. */
GATE_CLOCKS(s3c6410_gate_clks) __initdata = {
GATE_BUS(HCLK_3DSE, "hclk_3dse", "hclk", HCLK_GATE, 31),
GATE_ON(HCLK_IROM, "hclk_irom", "hclk", HCLK_GATE, 25),
GATE_ON(HCLK_MEM1, "hclk_mem1", "hclk", HCLK_GATE, 22),
GATE_ON(HCLK_MEM0, "hclk_mem0", "hclk", HCLK_GATE, 21),
GATE_BUS(HCLK_MFC, "hclk_mfc", "hclk", HCLK_GATE, 0),
GATE_BUS(PCLK_IIC1, "pclk_iic1", "pclk", PCLK_GATE, 27),
GATE_BUS(PCLK_IIS2, "pclk_iis2", "pclk", PCLK_GATE, 26),
GATE_SCLK(SCLK_FIMC, "sclk_fimc", "dout_fimc", SCLK_GATE, 13),
GATE_SCLK(SCLK_AUDIO2, "sclk_audio2", "dout_audio2", SCLK_GATE, 11),
GATE_BUS(MEM0_CFCON, "mem0_cfcon", "hclk_mem0", MEM0_GATE, 5),
GATE_BUS(MEM0_ONENAND1, "mem0_onenand1", "hclk_mem0", MEM0_GATE, 4),
GATE_BUS(MEM0_ONENAND0, "mem0_onenand0", "hclk_mem0", MEM0_GATE, 3),
GATE_BUS(MEM0_NFCON, "mem0_nfcon", "hclk_mem0", MEM0_GATE, 2),
GATE_ON(MEM0_SROM, "mem0_srom", "hclk_mem0", MEM0_GATE, 1),
};
/* List of PLL clocks. */
static struct samsung_pll_clock s3c64xx_pll_clks[] __initdata = {
[apll] = PLL(pll_6552, FOUT_APLL, "fout_apll", "fin_pll",
APLL_LOCK, APLL_CON, NULL),
[mpll] = PLL(pll_6552, FOUT_MPLL, "fout_mpll", "fin_pll",
MPLL_LOCK, MPLL_CON, NULL),
[epll] = PLL(pll_6553, FOUT_EPLL, "fout_epll", "fin_pll",
EPLL_LOCK, EPLL_CON0, NULL),
};
/* Aliases for common s3c64xx clocks. */
static struct samsung_clock_alias s3c64xx_clock_aliases[] = {
ALIAS(FOUT_APLL, NULL, "fout_apll"),
ALIAS(FOUT_MPLL, NULL, "fout_mpll"),
ALIAS(FOUT_EPLL, NULL, "fout_epll"),
ALIAS(MOUT_EPLL, NULL, "mout_epll"),
ALIAS(DOUT_MPLL, NULL, "dout_mpll"),
ALIAS(HCLKX2, NULL, "hclk2"),
ALIAS(HCLK, NULL, "hclk"),
ALIAS(PCLK, NULL, "pclk"),
ALIAS(PCLK, NULL, "clk_uart_baud2"),
ALIAS(ARMCLK, NULL, "armclk"),
ALIAS(HCLK_UHOST, "s3c2410-ohci", "usb-host"),
ALIAS(HCLK_USB, "s3c-hsotg", "otg"),
ALIAS(HCLK_HSMMC2, "s3c-sdhci.2", "hsmmc"),
ALIAS(HCLK_HSMMC2, "s3c-sdhci.2", "mmc_busclk.0"),
ALIAS(HCLK_HSMMC1, "s3c-sdhci.1", "hsmmc"),
ALIAS(HCLK_HSMMC1, "s3c-sdhci.1", "mmc_busclk.0"),
ALIAS(HCLK_HSMMC0, "s3c-sdhci.0", "hsmmc"),
ALIAS(HCLK_HSMMC0, "s3c-sdhci.0", "mmc_busclk.0"),
ALIAS(HCLK_DMA1, "dma-pl080s.1", "apb_pclk"),
ALIAS(HCLK_DMA0, "dma-pl080s.0", "apb_pclk"),
ALIAS(HCLK_CAMIF, "s3c-camif", "camif"),
ALIAS(HCLK_LCD, "s3c-fb", "lcd"),
ALIAS(PCLK_SPI1, "s3c6410-spi.1", "spi"),
ALIAS(PCLK_SPI0, "s3c6410-spi.0", "spi"),
ALIAS(PCLK_IIC0, "s3c2440-i2c.0", "i2c"),
ALIAS(PCLK_IIS1, "samsung-i2s.1", "iis"),
ALIAS(PCLK_IIS0, "samsung-i2s.0", "iis"),
ALIAS(PCLK_AC97, "samsung-ac97", "ac97"),
ALIAS(PCLK_TSADC, "s3c64xx-adc", "adc"),
ALIAS(PCLK_KEYPAD, "samsung-keypad", "keypad"),
ALIAS(PCLK_PCM1, "samsung-pcm.1", "pcm"),
ALIAS(PCLK_PCM0, "samsung-pcm.0", "pcm"),
ALIAS(PCLK_PWM, NULL, "timers"),
ALIAS(PCLK_RTC, "s3c64xx-rtc", "rtc"),
ALIAS(PCLK_WDT, NULL, "watchdog"),
ALIAS(PCLK_UART3, "s3c6400-uart.3", "uart"),
ALIAS(PCLK_UART2, "s3c6400-uart.2", "uart"),
ALIAS(PCLK_UART1, "s3c6400-uart.1", "uart"),
ALIAS(PCLK_UART0, "s3c6400-uart.0", "uart"),
ALIAS(SCLK_UHOST, "s3c2410-ohci", "usb-bus-host"),
ALIAS(SCLK_MMC2, "s3c-sdhci.2", "mmc_busclk.2"),
ALIAS(SCLK_MMC1, "s3c-sdhci.1", "mmc_busclk.2"),
ALIAS(SCLK_MMC0, "s3c-sdhci.0", "mmc_busclk.2"),
ALIAS(PCLK_SPI1, "s3c6410-spi.1", "spi_busclk0"),
ALIAS(SCLK_SPI1, "s3c6410-spi.1", "spi_busclk2"),
ALIAS(PCLK_SPI0, "s3c6410-spi.0", "spi_busclk0"),
ALIAS(SCLK_SPI0, "s3c6410-spi.0", "spi_busclk2"),
ALIAS(SCLK_AUDIO1, "samsung-pcm.1", "audio-bus"),
ALIAS(SCLK_AUDIO1, "samsung-i2s.1", "audio-bus"),
ALIAS(SCLK_AUDIO0, "samsung-pcm.0", "audio-bus"),
ALIAS(SCLK_AUDIO0, "samsung-i2s.0", "audio-bus"),
ALIAS(SCLK_UART, NULL, "clk_uart_baud3"),
ALIAS(SCLK_CAM, "s3c-camif", "camera"),
};
/* Aliases for s3c6400-specific clocks. */
static struct samsung_clock_alias s3c6400_clock_aliases[] = {
/* Nothing to place here yet. */
};
/* Aliases for s3c6410-specific clocks. */
static struct samsung_clock_alias s3c6410_clock_aliases[] = {
ALIAS(PCLK_IIC1, "s3c2440-i2c.1", "i2c"),
ALIAS(PCLK_IIS2, "samsung-i2s.2", "iis"),
ALIAS(SCLK_FIMC, "s3c-camif", "fimc"),
ALIAS(SCLK_AUDIO2, "samsung-i2s.2", "audio-bus"),
ALIAS(MEM0_SROM, NULL, "srom"),
};
static void __init s3c64xx_clk_register_fixed_ext(
struct samsung_clk_provider *ctx,
unsigned long fin_pll_f,
unsigned long xusbxti_f)
{
s3c64xx_fixed_rate_ext_clks[0].fixed_rate = fin_pll_f;
s3c64xx_fixed_rate_ext_clks[1].fixed_rate = xusbxti_f;
samsung_clk_register_fixed_rate(ctx, s3c64xx_fixed_rate_ext_clks,
ARRAY_SIZE(s3c64xx_fixed_rate_ext_clks));
}
/* Register s3c64xx clocks. */
void __init s3c64xx_clk_init(struct device_node *np, unsigned long xtal_f,
unsigned long xusbxti_f, bool s3c6400,
void __iomem *base)
{
struct samsung_clk_provider *ctx;
reg_base = base;
is_s3c6400 = s3c6400;
if (np) {
reg_base = of_iomap(np, 0);
if (!reg_base)
panic("%s: failed to map registers\n", __func__);
}
ctx = samsung_clk_init(np, reg_base, NR_CLKS);
if (!ctx)
panic("%s: unable to allocate context.\n", __func__);
/* Register external clocks. */
if (!np)
s3c64xx_clk_register_fixed_ext(ctx, xtal_f, xusbxti_f);
/* Register PLLs. */
samsung_clk_register_pll(ctx, s3c64xx_pll_clks,
ARRAY_SIZE(s3c64xx_pll_clks), reg_base);
/* Register common internal clocks. */
samsung_clk_register_fixed_rate(ctx, s3c64xx_fixed_rate_clks,
ARRAY_SIZE(s3c64xx_fixed_rate_clks));
samsung_clk_register_mux(ctx, s3c64xx_mux_clks,
ARRAY_SIZE(s3c64xx_mux_clks));
samsung_clk_register_div(ctx, s3c64xx_div_clks,
ARRAY_SIZE(s3c64xx_div_clks));
samsung_clk_register_gate(ctx, s3c64xx_gate_clks,
ARRAY_SIZE(s3c64xx_gate_clks));
/* Register SoC-specific clocks. */
if (is_s3c6400) {
samsung_clk_register_mux(ctx, s3c6400_mux_clks,
ARRAY_SIZE(s3c6400_mux_clks));
samsung_clk_register_div(ctx, s3c6400_div_clks,
ARRAY_SIZE(s3c6400_div_clks));
samsung_clk_register_gate(ctx, s3c6400_gate_clks,
ARRAY_SIZE(s3c6400_gate_clks));
samsung_clk_register_alias(ctx, s3c6400_clock_aliases,
ARRAY_SIZE(s3c6400_clock_aliases));
} else {
samsung_clk_register_mux(ctx, s3c6410_mux_clks,
ARRAY_SIZE(s3c6410_mux_clks));
samsung_clk_register_div(ctx, s3c6410_div_clks,
ARRAY_SIZE(s3c6410_div_clks));
samsung_clk_register_gate(ctx, s3c6410_gate_clks,
ARRAY_SIZE(s3c6410_gate_clks));
samsung_clk_register_alias(ctx, s3c6410_clock_aliases,
ARRAY_SIZE(s3c6410_clock_aliases));
}
samsung_clk_register_alias(ctx, s3c64xx_clock_aliases,
ARRAY_SIZE(s3c64xx_clock_aliases));
s3c64xx_clk_sleep_init();
samsung_clk_of_add_provider(np, ctx);
pr_info("%s clocks: apll = %lu, mpll = %lu\n"
"\tepll = %lu, arm_clk = %lu\n",
is_s3c6400 ? "S3C6400" : "S3C6410",
_get_rate("fout_apll"), _get_rate("fout_mpll"),
_get_rate("fout_epll"), _get_rate("armclk"));
}
static void __init s3c6400_clk_init(struct device_node *np)
{
s3c64xx_clk_init(np, 0, 0, true, NULL);
}
CLK_OF_DECLARE(s3c6400_clk, "samsung,s3c6400-clock", s3c6400_clk_init);
static void __init s3c6410_clk_init(struct device_node *np)
{
s3c64xx_clk_init(np, 0, 0, false, NULL);
}
CLK_OF_DECLARE(s3c6410_clk, "samsung,s3c6410-clock", s3c6410_clk_init);

View file

@ -0,0 +1,241 @@
/*
* Copyright (c) 2014 Tomasz Figa <t.figa@samsung.com>
*
* Based on Exynos Audio Subsystem Clock Controller driver:
*
* Copyright (c) 2013 Samsung Electronics Co., Ltd.
* Author: Padmavathi Venna <padma.v@samsung.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Driver for Audio Subsystem Clock Controller of S5PV210-compatible SoCs.
*/
#include <linux/clkdev.h>
#include <linux/io.h>
#include <linux/clk-provider.h>
#include <linux/of_address.h>
#include <linux/syscore_ops.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#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;
#define ASS_CLK_SRC 0x0
#define ASS_CLK_DIV 0x4
#define ASS_CLK_GATE 0x8
#ifdef CONFIG_PM_SLEEP
static unsigned long reg_save[][2] = {
{ASS_CLK_SRC, 0},
{ASS_CLK_DIV, 0},
{ASS_CLK_GATE, 0},
};
static int s5pv210_audss_clk_suspend(void)
{
int i;
for (i = 0; i < ARRAY_SIZE(reg_save); i++)
reg_save[i][1] = readl(reg_base + reg_save[i][0]);
return 0;
}
static void s5pv210_audss_clk_resume(void)
{
int i;
for (i = 0; i < ARRAY_SIZE(reg_save); i++)
writel(reg_save[i][1], reg_base + reg_save[i][0]);
}
static struct syscore_ops s5pv210_audss_clk_syscore_ops = {
.suspend = s5pv210_audss_clk_suspend,
.resume = s5pv210_audss_clk_resume,
};
#endif /* CONFIG_PM_SLEEP */
/* register s5pv210_audss clocks */
static int s5pv210_audss_clk_probe(struct platform_device *pdev)
{
int i, ret = 0;
struct resource *res;
const char *mout_audss_p[2];
const char *mout_i2s_p[3];
const char *hclk_p;
struct clk *hclk, *pll_ref, *pll_in, *cdclk, *sclk_audio;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
reg_base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(reg_base)) {
dev_err(&pdev->dev, "failed to map audss registers\n");
return PTR_ERR(reg_base);
}
clk_table = devm_kzalloc(&pdev->dev,
sizeof(struct clk *) * AUDSS_MAX_CLKS,
GFP_KERNEL);
if (!clk_table)
return -ENOMEM;
clk_data.clks = clk_table;
clk_data.clk_num = AUDSS_MAX_CLKS;
hclk = devm_clk_get(&pdev->dev, "hclk");
if (IS_ERR(hclk)) {
dev_err(&pdev->dev, "failed to get hclk clock\n");
return PTR_ERR(hclk);
}
pll_in = devm_clk_get(&pdev->dev, "fout_epll");
if (IS_ERR(pll_in)) {
dev_err(&pdev->dev, "failed to get fout_epll clock\n");
return PTR_ERR(pll_in);
}
sclk_audio = devm_clk_get(&pdev->dev, "sclk_audio0");
if (IS_ERR(sclk_audio)) {
dev_err(&pdev->dev, "failed to get sclk_audio0 clock\n");
return PTR_ERR(sclk_audio);
}
/* iiscdclk0 is an optional external I2S codec clock */
cdclk = devm_clk_get(&pdev->dev, "iiscdclk0");
pll_ref = devm_clk_get(&pdev->dev, "xxti");
if (!IS_ERR(pll_ref))
mout_audss_p[0] = __clk_get_name(pll_ref);
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",
mout_audss_p, ARRAY_SIZE(mout_audss_p),
CLK_SET_RATE_NO_REPARENT,
reg_base + ASS_CLK_SRC, 0, 1, 0, &lock);
mout_i2s_p[0] = "mout_audss";
if (!IS_ERR(cdclk))
mout_i2s_p[1] = __clk_get_name(cdclk);
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",
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,
"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_I2S] = clk_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",
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",
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",
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",
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",
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",
hclk_p, CLK_IGNORE_UNUSED,
reg_base + ASS_CLK_GATE, 0, 0, &lock);
for (i = 0; i < clk_data.clk_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]);
goto unregister;
}
}
ret = of_clk_add_provider(pdev->dev.of_node, of_clk_src_onecell_get,
&clk_data);
if (ret) {
dev_err(&pdev->dev, "failed to add clock provider\n");
goto unregister;
}
#ifdef CONFIG_PM_SLEEP
register_syscore_ops(&s5pv210_audss_clk_syscore_ops);
#endif
return 0;
unregister:
for (i = 0; i < clk_data.clk_num; i++) {
if (!IS_ERR(clk_table[i]))
clk_unregister(clk_table[i]);
}
return ret;
}
static int s5pv210_audss_clk_remove(struct platform_device *pdev)
{
int i;
of_clk_del_provider(pdev->dev.of_node);
for (i = 0; i < clk_data.clk_num; i++) {
if (!IS_ERR(clk_table[i]))
clk_unregister(clk_table[i]);
}
return 0;
}
static const struct of_device_id s5pv210_audss_clk_of_match[] = {
{ .compatible = "samsung,s5pv210-audss-clock", },
{},
};
static struct platform_driver s5pv210_audss_clk_driver = {
.driver = {
.name = "s5pv210-audss-clk",
.owner = THIS_MODULE,
.of_match_table = s5pv210_audss_clk_of_match,
},
.probe = s5pv210_audss_clk_probe,
.remove = s5pv210_audss_clk_remove,
};
static int __init s5pv210_audss_clk_init(void)
{
return platform_driver_register(&s5pv210_audss_clk_driver);
}
core_initcall(s5pv210_audss_clk_init);
static void __exit s5pv210_audss_clk_exit(void)
{
platform_driver_unregister(&s5pv210_audss_clk_driver);
}
module_exit(s5pv210_audss_clk_exit);
MODULE_AUTHOR("Tomasz Figa <t.figa@samsung.com>");
MODULE_DESCRIPTION("S5PV210 Audio Subsystem Clock Controller");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS("platform:s5pv210-audss-clk");

View file

@ -0,0 +1,856 @@
/*
* Copyright (c) 2013 Samsung Electronics Co., Ltd.
* Author: Mateusz Krawczuk <m.krawczuk@partner.samsung.com>
*
* Based on clock drivers for S3C64xx and Exynos4 SoCs.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Common Clock Framework support for all S5PC110/S5PV210 SoCs.
*/
#include <linux/clk.h>
#include <linux/clkdev.h>
#include <linux/clk-provider.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/syscore_ops.h>
#include "clk.h"
#include "clk-pll.h"
#include <dt-bindings/clock/s5pv210.h>
/* S5PC110/S5PV210 clock controller register offsets */
#define APLL_LOCK 0x0000
#define MPLL_LOCK 0x0008
#define EPLL_LOCK 0x0010
#define VPLL_LOCK 0x0020
#define APLL_CON0 0x0100
#define APLL_CON1 0x0104
#define MPLL_CON 0x0108
#define EPLL_CON0 0x0110
#define EPLL_CON1 0x0114
#define VPLL_CON 0x0120
#define CLK_SRC0 0x0200
#define CLK_SRC1 0x0204
#define CLK_SRC2 0x0208
#define CLK_SRC3 0x020c
#define CLK_SRC4 0x0210
#define CLK_SRC5 0x0214
#define CLK_SRC6 0x0218
#define CLK_SRC_MASK0 0x0280
#define CLK_SRC_MASK1 0x0284
#define CLK_DIV0 0x0300
#define CLK_DIV1 0x0304
#define CLK_DIV2 0x0308
#define CLK_DIV3 0x030c
#define CLK_DIV4 0x0310
#define CLK_DIV5 0x0314
#define CLK_DIV6 0x0318
#define CLK_DIV7 0x031c
#define CLK_GATE_MAIN0 0x0400
#define CLK_GATE_MAIN1 0x0404
#define CLK_GATE_MAIN2 0x0408
#define CLK_GATE_PERI0 0x0420
#define CLK_GATE_PERI1 0x0424
#define CLK_GATE_SCLK0 0x0440
#define CLK_GATE_SCLK1 0x0444
#define CLK_GATE_IP0 0x0460
#define CLK_GATE_IP1 0x0464
#define CLK_GATE_IP2 0x0468
#define CLK_GATE_IP3 0x046c
#define CLK_GATE_IP4 0x0470
#define CLK_GATE_BLOCK 0x0480
#define CLK_GATE_IP5 0x0484
#define CLK_OUT 0x0500
#define MISC 0xe000
#define OM_STAT 0xe100
/* IDs of PLLs available on S5PV210/S5P6442 SoCs */
enum {
apll,
mpll,
epll,
vpll,
};
/* IDs of external clocks (used for legacy boards) */
enum {
xxti,
xusbxti,
};
static void __iomem *reg_base;
#ifdef CONFIG_PM_SLEEP
static struct samsung_clk_reg_dump *s5pv210_clk_dump;
/* List of registers that need to be preserved across suspend/resume. */
static unsigned long s5pv210_clk_regs[] __initdata = {
CLK_SRC0,
CLK_SRC1,
CLK_SRC2,
CLK_SRC3,
CLK_SRC4,
CLK_SRC5,
CLK_SRC6,
CLK_SRC_MASK0,
CLK_SRC_MASK1,
CLK_DIV0,
CLK_DIV1,
CLK_DIV2,
CLK_DIV3,
CLK_DIV4,
CLK_DIV5,
CLK_DIV6,
CLK_DIV7,
CLK_GATE_MAIN0,
CLK_GATE_MAIN1,
CLK_GATE_MAIN2,
CLK_GATE_PERI0,
CLK_GATE_PERI1,
CLK_GATE_SCLK0,
CLK_GATE_SCLK1,
CLK_GATE_IP0,
CLK_GATE_IP1,
CLK_GATE_IP2,
CLK_GATE_IP3,
CLK_GATE_IP4,
CLK_GATE_IP5,
CLK_GATE_BLOCK,
APLL_LOCK,
MPLL_LOCK,
EPLL_LOCK,
VPLL_LOCK,
APLL_CON0,
APLL_CON1,
MPLL_CON,
EPLL_CON0,
EPLL_CON1,
VPLL_CON,
CLK_OUT,
};
static int s5pv210_clk_suspend(void)
{
samsung_clk_save(reg_base, s5pv210_clk_dump,
ARRAY_SIZE(s5pv210_clk_regs));
return 0;
}
static void s5pv210_clk_resume(void)
{
samsung_clk_restore(reg_base, s5pv210_clk_dump,
ARRAY_SIZE(s5pv210_clk_regs));
}
static struct syscore_ops s5pv210_clk_syscore_ops = {
.suspend = s5pv210_clk_suspend,
.resume = s5pv210_clk_resume,
};
static void s5pv210_clk_sleep_init(void)
{
s5pv210_clk_dump =
samsung_clk_alloc_reg_dump(s5pv210_clk_regs,
ARRAY_SIZE(s5pv210_clk_regs));
if (!s5pv210_clk_dump) {
pr_warn("%s: Failed to allocate sleep save data\n", __func__);
return;
}
register_syscore_ops(&s5pv210_clk_syscore_ops);
}
#else
static inline void s5pv210_clk_sleep_init(void) { }
#endif
/* Mux parent lists. */
static const char *fin_pll_p[] __initconst = {
"xxti",
"xusbxti"
};
static const char *mout_apll_p[] __initconst = {
"fin_pll",
"fout_apll"
};
static const char *mout_mpll_p[] __initconst = {
"fin_pll",
"fout_mpll"
};
static const char *mout_epll_p[] __initconst = {
"fin_pll",
"fout_epll"
};
static const char *mout_vpllsrc_p[] __initconst = {
"fin_pll",
"sclk_hdmi27m"
};
static const char *mout_vpll_p[] __initconst = {
"mout_vpllsrc",
"fout_vpll"
};
static const char *mout_group1_p[] __initconst = {
"dout_a2m",
"mout_mpll",
"mout_epll",
"mout_vpll"
};
static const char *mout_group2_p[] __initconst = {
"xxti",
"xusbxti",
"sclk_hdmi27m",
"sclk_usbphy0",
"sclk_usbphy1",
"sclk_hdmiphy",
"mout_mpll",
"mout_epll",
"mout_vpll",
};
static const char *mout_audio0_p[] __initconst = {
"xxti",
"pcmcdclk0",
"sclk_hdmi27m",
"sclk_usbphy0",
"sclk_usbphy1",
"sclk_hdmiphy",
"mout_mpll",
"mout_epll",
"mout_vpll",
};
static const char *mout_audio1_p[] __initconst = {
"i2scdclk1",
"pcmcdclk1",
"sclk_hdmi27m",
"sclk_usbphy0",
"sclk_usbphy1",
"sclk_hdmiphy",
"mout_mpll",
"mout_epll",
"mout_vpll",
};
static const char *mout_audio2_p[] __initconst = {
"i2scdclk2",
"pcmcdclk2",
"sclk_hdmi27m",
"sclk_usbphy0",
"sclk_usbphy1",
"sclk_hdmiphy",
"mout_mpll",
"mout_epll",
"mout_vpll",
};
static const char *mout_spdif_p[] __initconst = {
"dout_audio0",
"dout_audio1",
"dout_audio3",
};
static const char *mout_group3_p[] __initconst = {
"mout_apll",
"mout_mpll"
};
static const char *mout_group4_p[] __initconst = {
"mout_mpll",
"dout_a2m"
};
static const char *mout_flash_p[] __initconst = {
"dout_hclkd",
"dout_hclkp"
};
static const char *mout_dac_p[] __initconst = {
"mout_vpll",
"sclk_hdmiphy"
};
static const char *mout_hdmi_p[] __initconst = {
"sclk_hdmiphy",
"dout_tblk"
};
static const char *mout_mixer_p[] __initconst = {
"mout_dac",
"mout_hdmi"
};
static const char *mout_vpll_6442_p[] __initconst = {
"fin_pll",
"fout_vpll"
};
static const char *mout_mixer_6442_p[] __initconst = {
"mout_vpll",
"dout_mixer"
};
static const char *mout_d0sync_6442_p[] __initconst = {
"mout_dsys",
"div_apll"
};
static const char *mout_d1sync_6442_p[] __initconst = {
"mout_psys",
"div_apll"
};
static const char *mout_group2_6442_p[] __initconst = {
"fin_pll",
"none",
"none",
"sclk_usbphy0",
"none",
"none",
"mout_mpll",
"mout_epll",
"mout_vpll",
};
static const char *mout_audio0_6442_p[] __initconst = {
"fin_pll",
"pcmcdclk0",
"none",
"sclk_usbphy0",
"none",
"none",
"mout_mpll",
"mout_epll",
"mout_vpll",
};
static const char *mout_audio1_6442_p[] __initconst = {
"i2scdclk1",
"pcmcdclk1",
"none",
"sclk_usbphy0",
"none",
"none",
"mout_mpll",
"mout_epll",
"mout_vpll",
"fin_pll",
};
static const char *mout_clksel_p[] __initconst = {
"fout_apll_clkout",
"fout_mpll_clkout",
"fout_epll",
"fout_vpll",
"sclk_usbphy0",
"sclk_usbphy1",
"sclk_hdmiphy",
"rtc",
"rtc_tick",
"dout_hclkm",
"dout_pclkm",
"dout_hclkd",
"dout_pclkd",
"dout_hclkp",
"dout_pclkp",
"dout_apll_clkout",
"dout_hpm",
"xxti",
"xusbxti",
"div_dclk"
};
static const char *mout_clksel_6442_p[] __initconst = {
"fout_apll_clkout",
"fout_mpll_clkout",
"fout_epll",
"fout_vpll",
"sclk_usbphy0",
"none",
"none",
"rtc",
"rtc_tick",
"none",
"none",
"dout_hclkd",
"dout_pclkd",
"dout_hclkp",
"dout_pclkp",
"dout_apll_clkout",
"none",
"fin_pll",
"none",
"div_dclk"
};
static const char *mout_clkout_p[] __initconst = {
"dout_clkout",
"none",
"xxti",
"xusbxti"
};
/* Common fixed factor clocks. */
static struct samsung_fixed_factor_clock ffactor_clks[] __initdata = {
FFACTOR(FOUT_APLL_CLKOUT, "fout_apll_clkout", "fout_apll", 1, 4, 0),
FFACTOR(FOUT_MPLL_CLKOUT, "fout_mpll_clkout", "fout_mpll", 1, 2, 0),
FFACTOR(DOUT_APLL_CLKOUT, "dout_apll_clkout", "dout_apll", 1, 4, 0),
};
/* PLL input mux (fin_pll), which needs to be registered before PLLs. */
static struct samsung_mux_clock early_mux_clks[] __initdata = {
MUX_F(FIN_PLL, "fin_pll", fin_pll_p, OM_STAT, 0, 1,
CLK_MUX_READ_ONLY, 0),
};
/* Common clock muxes. */
static struct samsung_mux_clock mux_clks[] __initdata = {
MUX(MOUT_FLASH, "mout_flash", mout_flash_p, CLK_SRC0, 28, 1),
MUX(MOUT_PSYS, "mout_psys", mout_group4_p, CLK_SRC0, 24, 1),
MUX(MOUT_DSYS, "mout_dsys", mout_group4_p, CLK_SRC0, 20, 1),
MUX(MOUT_MSYS, "mout_msys", mout_group3_p, CLK_SRC0, 16, 1),
MUX(MOUT_EPLL, "mout_epll", mout_epll_p, CLK_SRC0, 8, 1),
MUX(MOUT_MPLL, "mout_mpll", mout_mpll_p, CLK_SRC0, 4, 1),
MUX(MOUT_APLL, "mout_apll", mout_apll_p, CLK_SRC0, 0, 1),
MUX(MOUT_CLKOUT, "mout_clkout", mout_clkout_p, MISC, 8, 2),
};
/* S5PV210-specific clock muxes. */
static struct samsung_mux_clock s5pv210_mux_clks[] __initdata = {
MUX(MOUT_VPLL, "mout_vpll", mout_vpll_p, CLK_SRC0, 12, 1),
MUX(MOUT_VPLLSRC, "mout_vpllsrc", mout_vpllsrc_p, CLK_SRC1, 28, 1),
MUX(MOUT_CSIS, "mout_csis", mout_group2_p, CLK_SRC1, 24, 4),
MUX(MOUT_FIMD, "mout_fimd", mout_group2_p, CLK_SRC1, 20, 4),
MUX(MOUT_CAM1, "mout_cam1", mout_group2_p, CLK_SRC1, 16, 4),
MUX(MOUT_CAM0, "mout_cam0", mout_group2_p, CLK_SRC1, 12, 4),
MUX(MOUT_DAC, "mout_dac", mout_dac_p, CLK_SRC1, 8, 1),
MUX(MOUT_MIXER, "mout_mixer", mout_mixer_p, CLK_SRC1, 4, 1),
MUX(MOUT_HDMI, "mout_hdmi", mout_hdmi_p, CLK_SRC1, 0, 1),
MUX(MOUT_G2D, "mout_g2d", mout_group1_p, CLK_SRC2, 8, 2),
MUX(MOUT_MFC, "mout_mfc", mout_group1_p, CLK_SRC2, 4, 2),
MUX(MOUT_G3D, "mout_g3d", mout_group1_p, CLK_SRC2, 0, 2),
MUX(MOUT_FIMC2, "mout_fimc2", mout_group2_p, CLK_SRC3, 20, 4),
MUX(MOUT_FIMC1, "mout_fimc1", mout_group2_p, CLK_SRC3, 16, 4),
MUX(MOUT_FIMC0, "mout_fimc0", mout_group2_p, CLK_SRC3, 12, 4),
MUX(MOUT_UART3, "mout_uart3", mout_group2_p, CLK_SRC4, 28, 4),
MUX(MOUT_UART2, "mout_uart2", mout_group2_p, CLK_SRC4, 24, 4),
MUX(MOUT_UART1, "mout_uart1", mout_group2_p, CLK_SRC4, 20, 4),
MUX(MOUT_UART0, "mout_uart0", mout_group2_p, CLK_SRC4, 16, 4),
MUX(MOUT_MMC3, "mout_mmc3", mout_group2_p, CLK_SRC4, 12, 4),
MUX(MOUT_MMC2, "mout_mmc2", mout_group2_p, CLK_SRC4, 8, 4),
MUX(MOUT_MMC1, "mout_mmc1", mout_group2_p, CLK_SRC4, 4, 4),
MUX(MOUT_MMC0, "mout_mmc0", mout_group2_p, CLK_SRC4, 0, 4),
MUX(MOUT_PWM, "mout_pwm", mout_group2_p, CLK_SRC5, 12, 4),
MUX(MOUT_SPI1, "mout_spi1", mout_group2_p, CLK_SRC5, 4, 4),
MUX(MOUT_SPI0, "mout_spi0", mout_group2_p, CLK_SRC5, 0, 4),
MUX(MOUT_DMC0, "mout_dmc0", mout_group1_p, CLK_SRC6, 24, 2),
MUX(MOUT_PWI, "mout_pwi", mout_group2_p, CLK_SRC6, 20, 4),
MUX(MOUT_HPM, "mout_hpm", mout_group3_p, CLK_SRC6, 16, 1),
MUX(MOUT_SPDIF, "mout_spdif", mout_spdif_p, CLK_SRC6, 12, 2),
MUX(MOUT_AUDIO2, "mout_audio2", mout_audio2_p, CLK_SRC6, 8, 4),
MUX(MOUT_AUDIO1, "mout_audio1", mout_audio1_p, CLK_SRC6, 4, 4),
MUX(MOUT_AUDIO0, "mout_audio0", mout_audio0_p, CLK_SRC6, 0, 4),
MUX(MOUT_CLKSEL, "mout_clksel", mout_clksel_p, CLK_OUT, 12, 5),
};
/* S5P6442-specific clock muxes. */
static struct samsung_mux_clock s5p6442_mux_clks[] __initdata = {
MUX(MOUT_VPLL, "mout_vpll", mout_vpll_6442_p, CLK_SRC0, 12, 1),
MUX(MOUT_FIMD, "mout_fimd", mout_group2_6442_p, CLK_SRC1, 20, 4),
MUX(MOUT_CAM1, "mout_cam1", mout_group2_6442_p, CLK_SRC1, 16, 4),
MUX(MOUT_CAM0, "mout_cam0", mout_group2_6442_p, CLK_SRC1, 12, 4),
MUX(MOUT_MIXER, "mout_mixer", mout_mixer_6442_p, CLK_SRC1, 4, 1),
MUX(MOUT_D0SYNC, "mout_d0sync", mout_d0sync_6442_p, CLK_SRC2, 28, 1),
MUX(MOUT_D1SYNC, "mout_d1sync", mout_d1sync_6442_p, CLK_SRC2, 24, 1),
MUX(MOUT_FIMC2, "mout_fimc2", mout_group2_6442_p, CLK_SRC3, 20, 4),
MUX(MOUT_FIMC1, "mout_fimc1", mout_group2_6442_p, CLK_SRC3, 16, 4),
MUX(MOUT_FIMC0, "mout_fimc0", mout_group2_6442_p, CLK_SRC3, 12, 4),
MUX(MOUT_UART2, "mout_uart2", mout_group2_6442_p, CLK_SRC4, 24, 4),
MUX(MOUT_UART1, "mout_uart1", mout_group2_6442_p, CLK_SRC4, 20, 4),
MUX(MOUT_UART0, "mout_uart0", mout_group2_6442_p, CLK_SRC4, 16, 4),
MUX(MOUT_MMC2, "mout_mmc2", mout_group2_6442_p, CLK_SRC4, 8, 4),
MUX(MOUT_MMC1, "mout_mmc1", mout_group2_6442_p, CLK_SRC4, 4, 4),
MUX(MOUT_MMC0, "mout_mmc0", mout_group2_6442_p, CLK_SRC4, 0, 4),
MUX(MOUT_PWM, "mout_pwm", mout_group2_6442_p, CLK_SRC5, 12, 4),
MUX(MOUT_SPI0, "mout_spi0", mout_group2_6442_p, CLK_SRC5, 0, 4),
MUX(MOUT_AUDIO1, "mout_audio1", mout_audio1_6442_p, CLK_SRC6, 4, 4),
MUX(MOUT_AUDIO0, "mout_audio0", mout_audio0_6442_p, CLK_SRC6, 0, 4),
MUX(MOUT_CLKSEL, "mout_clksel", mout_clksel_6442_p, CLK_OUT, 12, 5),
};
/* S5PV210-specific fixed rate clocks generated inside the SoC. */
static struct samsung_fixed_rate_clock s5pv210_frate_clks[] __initdata = {
FRATE(SCLK_HDMI27M, "sclk_hdmi27m", NULL, CLK_IS_ROOT, 27000000),
FRATE(SCLK_HDMIPHY, "sclk_hdmiphy", NULL, CLK_IS_ROOT, 27000000),
FRATE(SCLK_USBPHY0, "sclk_usbphy0", NULL, CLK_IS_ROOT, 48000000),
FRATE(SCLK_USBPHY1, "sclk_usbphy1", NULL, CLK_IS_ROOT, 48000000),
};
/* S5P6442-specific fixed rate clocks generated inside the SoC. */
static struct samsung_fixed_rate_clock s5p6442_frate_clks[] __initdata = {
FRATE(SCLK_USBPHY0, "sclk_usbphy0", NULL, CLK_IS_ROOT, 30000000),
};
/* Common clock dividers. */
static struct samsung_div_clock div_clks[] __initdata = {
DIV(DOUT_PCLKP, "dout_pclkp", "dout_hclkp", CLK_DIV0, 28, 3),
DIV(DOUT_PCLKD, "dout_pclkd", "dout_hclkd", CLK_DIV0, 20, 3),
DIV(DOUT_A2M, "dout_a2m", "mout_apll", CLK_DIV0, 4, 3),
DIV(DOUT_APLL, "dout_apll", "mout_msys", CLK_DIV0, 0, 3),
DIV(DOUT_FIMD, "dout_fimd", "mout_fimd", CLK_DIV1, 20, 4),
DIV(DOUT_CAM1, "dout_cam1", "mout_cam1", CLK_DIV1, 16, 4),
DIV(DOUT_CAM0, "dout_cam0", "mout_cam0", CLK_DIV1, 12, 4),
DIV(DOUT_FIMC2, "dout_fimc2", "mout_fimc2", CLK_DIV3, 20, 4),
DIV(DOUT_FIMC1, "dout_fimc1", "mout_fimc1", CLK_DIV3, 16, 4),
DIV(DOUT_FIMC0, "dout_fimc0", "mout_fimc0", CLK_DIV3, 12, 4),
DIV(DOUT_UART2, "dout_uart2", "mout_uart2", CLK_DIV4, 24, 4),
DIV(DOUT_UART1, "dout_uart1", "mout_uart1", CLK_DIV4, 20, 4),
DIV(DOUT_UART0, "dout_uart0", "mout_uart0", CLK_DIV4, 16, 4),
DIV(DOUT_MMC2, "dout_mmc2", "mout_mmc2", CLK_DIV4, 8, 4),
DIV(DOUT_MMC1, "dout_mmc1", "mout_mmc1", CLK_DIV4, 4, 4),
DIV(DOUT_MMC0, "dout_mmc0", "mout_mmc0", CLK_DIV4, 0, 4),
DIV(DOUT_PWM, "dout_pwm", "mout_pwm", CLK_DIV5, 12, 4),
DIV(DOUT_SPI0, "dout_spi0", "mout_spi0", CLK_DIV5, 0, 4),
DIV(DOUT_FLASH, "dout_flash", "mout_flash", CLK_DIV6, 12, 3),
DIV(DOUT_AUDIO1, "dout_audio1", "mout_audio1", CLK_DIV6, 4, 4),
DIV(DOUT_AUDIO0, "dout_audio0", "mout_audio0", CLK_DIV6, 0, 4),
DIV(DOUT_CLKOUT, "dout_clkout", "mout_clksel", CLK_OUT, 20, 4),
};
/* S5PV210-specific clock dividers. */
static struct samsung_div_clock s5pv210_div_clks[] __initdata = {
DIV(DOUT_HCLKP, "dout_hclkp", "mout_psys", CLK_DIV0, 24, 4),
DIV(DOUT_HCLKD, "dout_hclkd", "mout_dsys", CLK_DIV0, 16, 4),
DIV(DOUT_PCLKM, "dout_pclkm", "dout_hclkm", CLK_DIV0, 12, 3),
DIV(DOUT_HCLKM, "dout_hclkm", "dout_apll", CLK_DIV0, 8, 3),
DIV(DOUT_CSIS, "dout_csis", "mout_csis", CLK_DIV1, 28, 4),
DIV(DOUT_TBLK, "dout_tblk", "mout_vpll", CLK_DIV1, 0, 4),
DIV(DOUT_G2D, "dout_g2d", "mout_g2d", CLK_DIV2, 8, 4),
DIV(DOUT_MFC, "dout_mfc", "mout_mfc", CLK_DIV2, 4, 4),
DIV(DOUT_G3D, "dout_g3d", "mout_g3d", CLK_DIV2, 0, 4),
DIV(DOUT_UART3, "dout_uart3", "mout_uart3", CLK_DIV4, 28, 4),
DIV(DOUT_MMC3, "dout_mmc3", "mout_mmc3", CLK_DIV4, 12, 4),
DIV(DOUT_SPI1, "dout_spi1", "mout_spi1", CLK_DIV5, 4, 4),
DIV(DOUT_DMC0, "dout_dmc0", "mout_dmc0", CLK_DIV6, 28, 4),
DIV(DOUT_PWI, "dout_pwi", "mout_pwi", CLK_DIV6, 24, 4),
DIV(DOUT_HPM, "dout_hpm", "dout_copy", CLK_DIV6, 20, 3),
DIV(DOUT_COPY, "dout_copy", "mout_hpm", CLK_DIV6, 16, 3),
DIV(DOUT_AUDIO2, "dout_audio2", "mout_audio2", CLK_DIV6, 8, 4),
DIV(DOUT_DPM, "dout_dpm", "dout_pclkp", CLK_DIV7, 8, 7),
DIV(DOUT_DVSEM, "dout_dvsem", "dout_pclkp", CLK_DIV7, 0, 7),
};
/* S5P6442-specific clock dividers. */
static struct samsung_div_clock s5p6442_div_clks[] __initdata = {
DIV(DOUT_HCLKP, "dout_hclkp", "mout_d1sync", CLK_DIV0, 24, 4),
DIV(DOUT_HCLKD, "dout_hclkd", "mout_d0sync", CLK_DIV0, 16, 4),
DIV(DOUT_MIXER, "dout_mixer", "mout_vpll", CLK_DIV1, 0, 4),
};
/* Common clock gates. */
static struct samsung_gate_clock gate_clks[] __initdata = {
GATE(CLK_ROTATOR, "rotator", "dout_hclkd", CLK_GATE_IP0, 29, 0, 0),
GATE(CLK_FIMC2, "fimc2", "dout_hclkd", CLK_GATE_IP0, 26, 0, 0),
GATE(CLK_FIMC1, "fimc1", "dout_hclkd", CLK_GATE_IP0, 25, 0, 0),
GATE(CLK_FIMC0, "fimc0", "dout_hclkd", CLK_GATE_IP0, 24, 0, 0),
GATE(CLK_PDMA0, "pdma0", "dout_hclkp", CLK_GATE_IP0, 3, 0, 0),
GATE(CLK_MDMA, "mdma", "dout_hclkd", CLK_GATE_IP0, 2, 0, 0),
GATE(CLK_SROMC, "sromc", "dout_hclkp", CLK_GATE_IP1, 26, 0, 0),
GATE(CLK_NANDXL, "nandxl", "dout_hclkp", CLK_GATE_IP1, 24, 0, 0),
GATE(CLK_USB_OTG, "usb_otg", "dout_hclkp", CLK_GATE_IP1, 16, 0, 0),
GATE(CLK_TVENC, "tvenc", "dout_hclkd", CLK_GATE_IP1, 10, 0, 0),
GATE(CLK_MIXER, "mixer", "dout_hclkd", CLK_GATE_IP1, 9, 0, 0),
GATE(CLK_VP, "vp", "dout_hclkd", CLK_GATE_IP1, 8, 0, 0),
GATE(CLK_FIMD, "fimd", "dout_hclkd", CLK_GATE_IP1, 0, 0, 0),
GATE(CLK_HSMMC2, "hsmmc2", "dout_hclkp", CLK_GATE_IP2, 18, 0, 0),
GATE(CLK_HSMMC1, "hsmmc1", "dout_hclkp", CLK_GATE_IP2, 17, 0, 0),
GATE(CLK_HSMMC0, "hsmmc0", "dout_hclkp", CLK_GATE_IP2, 16, 0, 0),
GATE(CLK_MODEMIF, "modemif", "dout_hclkp", CLK_GATE_IP2, 9, 0, 0),
GATE(CLK_SECSS, "secss", "dout_hclkp", CLK_GATE_IP2, 0, 0, 0),
GATE(CLK_PCM1, "pcm1", "dout_pclkp", CLK_GATE_IP3, 29, 0, 0),
GATE(CLK_PCM0, "pcm0", "dout_pclkp", CLK_GATE_IP3, 28, 0, 0),
GATE(CLK_TSADC, "tsadc", "dout_pclkp", CLK_GATE_IP3, 24, 0, 0),
GATE(CLK_PWM, "pwm", "dout_pclkp", CLK_GATE_IP3, 23, 0, 0),
GATE(CLK_WDT, "watchdog", "dout_pclkp", CLK_GATE_IP3, 22, 0, 0),
GATE(CLK_KEYIF, "keyif", "dout_pclkp", CLK_GATE_IP3, 21, 0, 0),
GATE(CLK_UART2, "uart2", "dout_pclkp", CLK_GATE_IP3, 19, 0, 0),
GATE(CLK_UART1, "uart1", "dout_pclkp", CLK_GATE_IP3, 18, 0, 0),
GATE(CLK_UART0, "uart0", "dout_pclkp", CLK_GATE_IP3, 17, 0, 0),
GATE(CLK_SYSTIMER, "systimer", "dout_pclkp", CLK_GATE_IP3, 16, 0, 0),
GATE(CLK_RTC, "rtc", "dout_pclkp", CLK_GATE_IP3, 15, 0, 0),
GATE(CLK_SPI0, "spi0", "dout_pclkp", CLK_GATE_IP3, 12, 0, 0),
GATE(CLK_I2C2, "i2c2", "dout_pclkp", CLK_GATE_IP3, 9, 0, 0),
GATE(CLK_I2C0, "i2c0", "dout_pclkp", CLK_GATE_IP3, 7, 0, 0),
GATE(CLK_I2S1, "i2s1", "dout_pclkp", CLK_GATE_IP3, 5, 0, 0),
GATE(CLK_I2S0, "i2s0", "dout_pclkp", CLK_GATE_IP3, 4, 0, 0),
GATE(CLK_SECKEY, "seckey", "dout_pclkp", CLK_GATE_IP4, 3, 0, 0),
GATE(CLK_CHIPID, "chipid", "dout_pclkp", CLK_GATE_IP4, 0, 0, 0),
GATE(SCLK_AUDIO1, "sclk_audio1", "dout_audio1", CLK_SRC_MASK0, 25,
CLK_SET_RATE_PARENT, 0),
GATE(SCLK_AUDIO0, "sclk_audio0", "dout_audio0", CLK_SRC_MASK0, 24,
CLK_SET_RATE_PARENT, 0),
GATE(SCLK_PWM, "sclk_pwm", "dout_pwm", CLK_SRC_MASK0, 19,
CLK_SET_RATE_PARENT, 0),
GATE(SCLK_SPI0, "sclk_spi0", "dout_spi0", CLK_SRC_MASK0, 16,
CLK_SET_RATE_PARENT, 0),
GATE(SCLK_UART2, "sclk_uart2", "dout_uart2", CLK_SRC_MASK0, 14,
CLK_SET_RATE_PARENT, 0),
GATE(SCLK_UART1, "sclk_uart1", "dout_uart1", CLK_SRC_MASK0, 13,
CLK_SET_RATE_PARENT, 0),
GATE(SCLK_UART0, "sclk_uart0", "dout_uart0", CLK_SRC_MASK0, 12,
CLK_SET_RATE_PARENT, 0),
GATE(SCLK_MMC2, "sclk_mmc2", "dout_mmc2", CLK_SRC_MASK0, 10,
CLK_SET_RATE_PARENT, 0),
GATE(SCLK_MMC1, "sclk_mmc1", "dout_mmc1", CLK_SRC_MASK0, 9,
CLK_SET_RATE_PARENT, 0),
GATE(SCLK_MMC0, "sclk_mmc0", "dout_mmc0", CLK_SRC_MASK0, 8,
CLK_SET_RATE_PARENT, 0),
GATE(SCLK_FIMD, "sclk_fimd", "dout_fimd", CLK_SRC_MASK0, 5,
CLK_SET_RATE_PARENT, 0),
GATE(SCLK_CAM1, "sclk_cam1", "dout_cam1", CLK_SRC_MASK0, 4,
CLK_SET_RATE_PARENT, 0),
GATE(SCLK_CAM0, "sclk_cam0", "dout_cam0", CLK_SRC_MASK0, 3,
CLK_SET_RATE_PARENT, 0),
GATE(SCLK_MIXER, "sclk_mixer", "mout_mixer", CLK_SRC_MASK0, 1,
CLK_SET_RATE_PARENT, 0),
GATE(SCLK_FIMC2, "sclk_fimc2", "dout_fimc2", CLK_SRC_MASK1, 4,
CLK_SET_RATE_PARENT, 0),
GATE(SCLK_FIMC1, "sclk_fimc1", "dout_fimc1", CLK_SRC_MASK1, 3,
CLK_SET_RATE_PARENT, 0),
GATE(SCLK_FIMC0, "sclk_fimc0", "dout_fimc0", CLK_SRC_MASK1, 2,
CLK_SET_RATE_PARENT, 0),
};
/* S5PV210-specific clock gates. */
static struct samsung_gate_clock s5pv210_gate_clks[] __initdata = {
GATE(CLK_CSIS, "clk_csis", "dout_hclkd", CLK_GATE_IP0, 31, 0, 0),
GATE(CLK_MFC, "mfc", "dout_hclkm", CLK_GATE_IP0, 16, 0, 0),
GATE(CLK_G2D, "g2d", "dout_hclkd", CLK_GATE_IP0, 12, 0, 0),
GATE(CLK_G3D, "g3d", "dout_hclkm", CLK_GATE_IP0, 8, 0, 0),
GATE(CLK_IMEM, "imem", "dout_hclkm", CLK_GATE_IP0, 5, 0, 0),
GATE(CLK_PDMA1, "pdma1", "dout_hclkp", CLK_GATE_IP0, 4, 0, 0),
GATE(CLK_NFCON, "nfcon", "dout_hclkp", CLK_GATE_IP1, 28, 0, 0),
GATE(CLK_CFCON, "cfcon", "dout_hclkp", CLK_GATE_IP1, 25, 0, 0),
GATE(CLK_USB_HOST, "usb_host", "dout_hclkp", CLK_GATE_IP1, 17, 0, 0),
GATE(CLK_HDMI, "hdmi", "dout_hclkd", CLK_GATE_IP1, 11, 0, 0),
GATE(CLK_DSIM, "dsim", "dout_pclkd", CLK_GATE_IP1, 2, 0, 0),
GATE(CLK_TZIC3, "tzic3", "dout_hclkm", CLK_GATE_IP2, 31, 0, 0),
GATE(CLK_TZIC2, "tzic2", "dout_hclkm", CLK_GATE_IP2, 30, 0, 0),
GATE(CLK_TZIC1, "tzic1", "dout_hclkm", CLK_GATE_IP2, 29, 0, 0),
GATE(CLK_TZIC0, "tzic0", "dout_hclkm", CLK_GATE_IP2, 28, 0, 0),
GATE(CLK_TSI, "tsi", "dout_hclkd", CLK_GATE_IP2, 20, 0, 0),
GATE(CLK_HSMMC3, "hsmmc3", "dout_hclkp", CLK_GATE_IP2, 19, 0, 0),
GATE(CLK_JTAG, "jtag", "dout_hclkp", CLK_GATE_IP2, 11, 0, 0),
GATE(CLK_CORESIGHT, "coresight", "dout_pclkp", CLK_GATE_IP2, 8, 0, 0),
GATE(CLK_SDM, "sdm", "dout_pclkm", CLK_GATE_IP2, 1, 0, 0),
GATE(CLK_PCM2, "pcm2", "dout_pclkp", CLK_GATE_IP3, 30, 0, 0),
GATE(CLK_UART3, "uart3", "dout_pclkp", CLK_GATE_IP3, 20, 0, 0),
GATE(CLK_SPI1, "spi1", "dout_pclkp", CLK_GATE_IP3, 13, 0, 0),
GATE(CLK_I2C_HDMI_PHY, "i2c_hdmi_phy", "dout_pclkd",
CLK_GATE_IP3, 11, 0, 0),
GATE(CLK_I2C1, "i2c1", "dout_pclkd", CLK_GATE_IP3, 10, 0, 0),
GATE(CLK_I2S2, "i2s2", "dout_pclkp", CLK_GATE_IP3, 6, 0, 0),
GATE(CLK_AC97, "ac97", "dout_pclkp", CLK_GATE_IP3, 1, 0, 0),
GATE(CLK_SPDIF, "spdif", "dout_pclkp", CLK_GATE_IP3, 0, 0, 0),
GATE(CLK_TZPC3, "tzpc.3", "dout_pclkd", CLK_GATE_IP4, 8, 0, 0),
GATE(CLK_TZPC2, "tzpc.2", "dout_pclkd", CLK_GATE_IP4, 7, 0, 0),
GATE(CLK_TZPC1, "tzpc.1", "dout_pclkp", CLK_GATE_IP4, 6, 0, 0),
GATE(CLK_TZPC0, "tzpc.0", "dout_pclkm", CLK_GATE_IP4, 5, 0, 0),
GATE(CLK_IEM_APC, "iem_apc", "dout_pclkp", CLK_GATE_IP4, 2, 0, 0),
GATE(CLK_IEM_IEC, "iem_iec", "dout_pclkp", CLK_GATE_IP4, 1, 0, 0),
GATE(CLK_JPEG, "jpeg", "dout_hclkd", CLK_GATE_IP5, 29, 0, 0),
GATE(SCLK_SPDIF, "sclk_spdif", "mout_spdif", CLK_SRC_MASK0, 27,
CLK_SET_RATE_PARENT, 0),
GATE(SCLK_AUDIO2, "sclk_audio2", "dout_audio2", CLK_SRC_MASK0, 26,
CLK_SET_RATE_PARENT, 0),
GATE(SCLK_SPI1, "sclk_spi1", "dout_spi1", CLK_SRC_MASK0, 17,
CLK_SET_RATE_PARENT, 0),
GATE(SCLK_UART3, "sclk_uart3", "dout_uart3", CLK_SRC_MASK0, 15,
CLK_SET_RATE_PARENT, 0),
GATE(SCLK_MMC3, "sclk_mmc3", "dout_mmc3", CLK_SRC_MASK0, 11,
CLK_SET_RATE_PARENT, 0),
GATE(SCLK_CSIS, "sclk_csis", "dout_csis", CLK_SRC_MASK0, 6,
CLK_SET_RATE_PARENT, 0),
GATE(SCLK_DAC, "sclk_dac", "mout_dac", CLK_SRC_MASK0, 2,
CLK_SET_RATE_PARENT, 0),
GATE(SCLK_HDMI, "sclk_hdmi", "mout_hdmi", CLK_SRC_MASK0, 0,
CLK_SET_RATE_PARENT, 0),
};
/* S5P6442-specific clock gates. */
static struct samsung_gate_clock s5p6442_gate_clks[] __initdata = {
GATE(CLK_JPEG, "jpeg", "dout_hclkd", CLK_GATE_IP0, 28, 0, 0),
GATE(CLK_MFC, "mfc", "dout_hclkd", CLK_GATE_IP0, 16, 0, 0),
GATE(CLK_G2D, "g2d", "dout_hclkd", CLK_GATE_IP0, 12, 0, 0),
GATE(CLK_G3D, "g3d", "dout_hclkd", CLK_GATE_IP0, 8, 0, 0),
GATE(CLK_IMEM, "imem", "dout_hclkd", CLK_GATE_IP0, 5, 0, 0),
GATE(CLK_ETB, "etb", "dout_hclkd", CLK_GATE_IP1, 31, 0, 0),
GATE(CLK_ETM, "etm", "dout_hclkd", CLK_GATE_IP1, 30, 0, 0),
GATE(CLK_I2C1, "i2c1", "dout_pclkp", CLK_GATE_IP3, 8, 0, 0),
GATE(SCLK_DAC, "sclk_dac", "mout_vpll", CLK_SRC_MASK0, 2,
CLK_SET_RATE_PARENT, 0),
};
/*
* Clock aliases for legacy clkdev look-up.
* NOTE: Needed only to support legacy board files.
*/
static struct samsung_clock_alias s5pv210_aliases[] = {
ALIAS(DOUT_APLL, NULL, "armclk"),
ALIAS(DOUT_HCLKM, NULL, "hclk_msys"),
ALIAS(MOUT_DMC0, NULL, "sclk_dmc0"),
};
/* S5PV210-specific PLLs. */
static struct samsung_pll_clock s5pv210_pll_clks[] __initdata = {
[apll] = PLL(pll_4508, FOUT_APLL, "fout_apll", "fin_pll",
APLL_LOCK, APLL_CON0, NULL),
[mpll] = PLL(pll_4502, FOUT_MPLL, "fout_mpll", "fin_pll",
MPLL_LOCK, MPLL_CON, NULL),
[epll] = PLL(pll_4600, FOUT_EPLL, "fout_epll", "fin_pll",
EPLL_LOCK, EPLL_CON0, NULL),
[vpll] = PLL(pll_4502, FOUT_VPLL, "fout_vpll", "mout_vpllsrc",
VPLL_LOCK, VPLL_CON, NULL),
};
/* S5P6442-specific PLLs. */
static struct samsung_pll_clock s5p6442_pll_clks[] __initdata = {
[apll] = PLL(pll_4502, FOUT_APLL, "fout_apll", "fin_pll",
APLL_LOCK, APLL_CON0, NULL),
[mpll] = PLL(pll_4502, FOUT_MPLL, "fout_mpll", "fin_pll",
MPLL_LOCK, MPLL_CON, NULL),
[epll] = PLL(pll_4500, FOUT_EPLL, "fout_epll", "fin_pll",
EPLL_LOCK, EPLL_CON0, NULL),
[vpll] = PLL(pll_4500, FOUT_VPLL, "fout_vpll", "fin_pll",
VPLL_LOCK, VPLL_CON, NULL),
};
static void __init __s5pv210_clk_init(struct device_node *np,
unsigned long xxti_f,
unsigned long xusbxti_f,
bool is_s5p6442)
{
struct samsung_clk_provider *ctx;
ctx = samsung_clk_init(np, reg_base, NR_CLKS);
if (!ctx)
panic("%s: unable to allocate context.\n", __func__);
samsung_clk_register_mux(ctx, early_mux_clks,
ARRAY_SIZE(early_mux_clks));
if (is_s5p6442) {
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);
samsung_clk_register_mux(ctx, s5p6442_mux_clks,
ARRAY_SIZE(s5p6442_mux_clks));
samsung_clk_register_div(ctx, s5p6442_div_clks,
ARRAY_SIZE(s5p6442_div_clks));
samsung_clk_register_gate(ctx, s5p6442_gate_clks,
ARRAY_SIZE(s5p6442_gate_clks));
} else {
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);
samsung_clk_register_mux(ctx, s5pv210_mux_clks,
ARRAY_SIZE(s5pv210_mux_clks));
samsung_clk_register_div(ctx, s5pv210_div_clks,
ARRAY_SIZE(s5pv210_div_clks));
samsung_clk_register_gate(ctx, s5pv210_gate_clks,
ARRAY_SIZE(s5pv210_gate_clks));
}
samsung_clk_register_mux(ctx, mux_clks, ARRAY_SIZE(mux_clks));
samsung_clk_register_div(ctx, div_clks, ARRAY_SIZE(div_clks));
samsung_clk_register_gate(ctx, gate_clks, ARRAY_SIZE(gate_clks));
samsung_clk_register_fixed_factor(ctx, ffactor_clks,
ARRAY_SIZE(ffactor_clks));
samsung_clk_register_alias(ctx, s5pv210_aliases,
ARRAY_SIZE(s5pv210_aliases));
s5pv210_clk_sleep_init();
pr_info("%s clocks: mout_apll = %ld, mout_mpll = %ld\n"
"\tmout_epll = %ld, mout_vpll = %ld\n",
is_s5p6442 ? "S5P6442" : "S5PV210",
_get_rate("mout_apll"), _get_rate("mout_mpll"),
_get_rate("mout_epll"), _get_rate("mout_vpll"));
}
static void __init s5pv210_clk_dt_init(struct device_node *np)
{
reg_base = of_iomap(np, 0);
if (!reg_base)
panic("%s: failed to map registers\n", __func__);
__s5pv210_clk_init(np, 0, 0, false);
}
CLK_OF_DECLARE(s5pv210_clk, "samsung,s5pv210-clock", s5pv210_clk_dt_init);
static void __init s5p6442_clk_dt_init(struct device_node *np)
{
reg_base = of_iomap(np, 0);
if (!reg_base)
panic("%s: failed to map registers\n", __func__);
__s5pv210_clk_init(np, 0, 0, true);
}
CLK_OF_DECLARE(s5p6442_clk, "samsung,s5p6442-clock", s5p6442_clk_dt_init);

315
drivers/clk/samsung/clk.c Normal file
View file

@ -0,0 +1,315 @@
/*
* Copyright (c) 2013 Samsung Electronics Co., Ltd.
* Copyright (c) 2013 Linaro Ltd.
* Author: Thomas Abraham <thomas.ab@samsung.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This file includes utility functions to register clocks to common
* clock framework for Samsung platforms.
*/
#include <linux/syscore_ops.h>
#include "clk.h"
void samsung_clk_save(void __iomem *base,
struct samsung_clk_reg_dump *rd,
unsigned int num_regs)
{
for (; num_regs > 0; --num_regs, ++rd)
rd->value = readl(base + rd->offset);
}
void samsung_clk_restore(void __iomem *base,
const struct samsung_clk_reg_dump *rd,
unsigned int num_regs)
{
for (; num_regs > 0; --num_regs, ++rd)
writel(rd->value, base + rd->offset);
}
struct samsung_clk_reg_dump *samsung_clk_alloc_reg_dump(
const unsigned long *rdump,
unsigned long nr_rdump)
{
struct samsung_clk_reg_dump *rd;
unsigned int i;
rd = kcalloc(nr_rdump, sizeof(*rd), GFP_KERNEL);
if (!rd)
return NULL;
for (i = 0; i < nr_rdump; ++i)
rd[i].offset = rdump[i];
return rd;
}
/* setup the essentials required to support clock lookup using ccf */
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);
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->reg_base = base;
ctx->clk_data.clks = clk_table;
ctx->clk_data.clk_num = nr_clks;
spin_lock_init(&ctx->lock);
return ctx;
}
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,
&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)
{
if (ctx->clk_data.clks && id)
ctx->clk_data.clks[id] = clk;
}
/* register a list of aliases */
void __init samsung_clk_register_alias(struct samsung_clk_provider *ctx,
struct samsung_clock_alias *list,
unsigned int nr_clk)
{
struct clk *clk;
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__,
idx);
continue;
}
clk = ctx->clk_data.clks[list->id];
if (!clk) {
pr_err("%s: failed to find clock %d\n", __func__,
list->id);
continue;
}
ret = clk_register_clkdev(clk, list->alias, list->dev_name);
if (ret)
pr_err("%s: failed to register lookup %s\n",
__func__, list->alias);
}
}
/* register a list of fixed clocks */
void __init samsung_clk_register_fixed_rate(struct samsung_clk_provider *ctx,
struct samsung_fixed_rate_clock *list, unsigned int nr_clk)
{
struct clk *clk;
unsigned int idx, ret;
for (idx = 0; idx < nr_clk; idx++, list++) {
clk = clk_register_fixed_rate(NULL, list->name,
list->parent_name, list->flags, list->fixed_rate);
if (IS_ERR(clk)) {
pr_err("%s: failed to register clock %s\n", __func__,
list->name);
continue;
}
samsung_clk_add_lookup(ctx, clk, 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);
if (ret)
pr_err("%s: failed to register clock lookup for %s",
__func__, list->name);
}
}
/* register a list of fixed factor clocks */
void __init samsung_clk_register_fixed_factor(struct samsung_clk_provider *ctx,
struct samsung_fixed_factor_clock *list, unsigned int nr_clk)
{
struct clk *clk;
unsigned int idx;
for (idx = 0; idx < nr_clk; idx++, list++) {
clk = clk_register_fixed_factor(NULL, list->name,
list->parent_name, list->flags, list->mult, list->div);
if (IS_ERR(clk)) {
pr_err("%s: failed to register clock %s\n", __func__,
list->name);
continue;
}
samsung_clk_add_lookup(ctx, clk, list->id);
}
}
/* register a list of mux clocks */
void __init samsung_clk_register_mux(struct samsung_clk_provider *ctx,
struct samsung_mux_clock *list,
unsigned int nr_clk)
{
struct clk *clk;
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,
ctx->reg_base + list->offset,
list->shift, list->width, list->mux_flags, &ctx->lock);
if (IS_ERR(clk)) {
pr_err("%s: failed to register clock %s\n", __func__,
list->name);
continue;
}
samsung_clk_add_lookup(ctx, clk, list->id);
/* register a clock lookup only if a clock alias is specified */
if (list->alias) {
ret = clk_register_clkdev(clk, list->alias,
list->dev_name);
if (ret)
pr_err("%s: failed to register lookup %s\n",
__func__, list->alias);
}
}
}
/* register a list of div clocks */
void __init samsung_clk_register_div(struct samsung_clk_provider *ctx,
struct samsung_div_clock *list,
unsigned int nr_clk)
{
struct clk *clk;
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,
ctx->reg_base + list->offset,
list->shift, list->width, list->div_flags,
list->table, &ctx->lock);
else
clk = clk_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)) {
pr_err("%s: failed to register clock %s\n", __func__,
list->name);
continue;
}
samsung_clk_add_lookup(ctx, clk, list->id);
/* register a clock lookup only if a clock alias is specified */
if (list->alias) {
ret = clk_register_clkdev(clk, list->alias,
list->dev_name);
if (ret)
pr_err("%s: failed to register lookup %s\n",
__func__, list->alias);
}
}
}
/* register a list of gate clocks */
void __init samsung_clk_register_gate(struct samsung_clk_provider *ctx,
struct samsung_gate_clock *list,
unsigned int nr_clk)
{
struct clk *clk;
unsigned int idx, ret;
for (idx = 0; idx < nr_clk; idx++, list++) {
clk = clk_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)) {
pr_err("%s: failed to register clock %s\n", __func__,
list->name);
continue;
}
/* register a clock lookup only if a clock alias is specified */
if (list->alias) {
ret = clk_register_clkdev(clk, 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);
}
}
/*
* obtain the clock speed of all external fixed clock sources from device
* tree and register it
*/
#ifdef CONFIG_OF
void __init samsung_clk_of_register_fixed_ext(struct samsung_clk_provider *ctx,
struct samsung_fixed_rate_clock *fixed_rate_clk,
unsigned int nr_fixed_rate_clk,
const struct of_device_id *clk_matches)
{
const struct of_device_id *match;
struct device_node *clk_np;
u32 freq;
for_each_matching_node_and_match(clk_np, clk_matches, &match) {
if (of_property_read_u32(clk_np, "clock-frequency", &freq))
continue;
fixed_rate_clk[(unsigned long)match->data].fixed_rate = freq;
}
samsung_clk_register_fixed_rate(ctx, fixed_rate_clk, nr_fixed_rate_clk);
}
#endif
/* utility function to get the rate of a specified clock */
unsigned long _get_rate(const char *clk_name)
{
struct clk *clk;
clk = __clk_lookup(clk_name);
if (!clk) {
pr_err("%s: could not find clock %s\n", __func__, clk_name);
return 0;
}
return clk_get_rate(clk);
}

377
drivers/clk/samsung/clk.h Normal file
View file

@ -0,0 +1,377 @@
/*
* Copyright (c) 2013 Samsung Electronics Co., Ltd.
* Copyright (c) 2013 Linaro Ltd.
* Author: Thomas Abraham <thomas.ab@samsung.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Common Clock Framework support for all Samsung platforms
*/
#ifndef __SAMSUNG_CLK_H
#define __SAMSUNG_CLK_H
#include <linux/clk.h>
#include <linux/clkdev.h>
#include <linux/io.h>
#include <linux/clk-provider.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include "clk-pll.h"
/**
* 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 bwtween callbacks for a given clock-provider.
*/
struct samsung_clk_provider {
void __iomem *reg_base;
struct clk_onecell_data clk_data;
spinlock_t lock;
};
/**
* struct samsung_clock_alias: information about mux clock
* @id: platform specific id of the clock.
* @dev_name: name of the device to which this clock belongs.
* @alias: optional clock alias name to be assigned to this clock.
*/
struct samsung_clock_alias {
unsigned int id;
const char *dev_name;
const char *alias;
};
#define ALIAS(_id, dname, a) \
{ \
.id = _id, \
.dev_name = dname, \
.alias = a, \
}
#define MHZ (1000 * 1000)
/**
* struct samsung_fixed_rate_clock: information about fixed-rate clock
* @id: platform specific id of the clock.
* @name: name of this fixed-rate clock.
* @parent_name: optional parent clock name.
* @flags: optional fixed-rate clock flags.
* @fixed-rate: fixed clock rate of this clock.
*/
struct samsung_fixed_rate_clock {
unsigned int id;
char *name;
const char *parent_name;
unsigned long flags;
unsigned long fixed_rate;
};
#define FRATE(_id, cname, pname, f, frate) \
{ \
.id = _id, \
.name = cname, \
.parent_name = pname, \
.flags = f, \
.fixed_rate = frate, \
}
/*
* struct samsung_fixed_factor_clock: information about fixed-factor clock
* @id: platform specific id of the clock.
* @name: name of this fixed-factor clock.
* @parent_name: parent clock name.
* @mult: fixed multiplication factor.
* @div: fixed division factor.
* @flags: optional fixed-factor clock flags.
*/
struct samsung_fixed_factor_clock {
unsigned int id;
char *name;
const char *parent_name;
unsigned long mult;
unsigned long div;
unsigned long flags;
};
#define FFACTOR(_id, cname, pname, m, d, f) \
{ \
.id = _id, \
.name = cname, \
.parent_name = pname, \
.mult = m, \
.div = d, \
.flags = f, \
}
/**
* struct samsung_mux_clock: information about mux clock
* @id: platform specific id of the clock.
* @dev_name: name of the device to which this clock belongs.
* @name: name of this mux clock.
* @parent_names: array of pointer to parent clock names.
* @num_parents: number of parents listed in @parent_names.
* @flags: optional flags for basic clock.
* @offset: offset of the register for configuring the mux.
* @shift: starting bit location of the mux control bit-field in @reg.
* @width: width of the mux control bit-field in @reg.
* @mux_flags: flags for mux-type clock.
* @alias: optional clock alias name to be assigned to this clock.
*/
struct samsung_mux_clock {
unsigned int id;
const char *dev_name;
const char *name;
const char **parent_names;
u8 num_parents;
unsigned long flags;
unsigned long offset;
u8 shift;
u8 width;
u8 mux_flags;
const char *alias;
};
#define __MUX(_id, dname, cname, pnames, o, s, w, f, mf, a) \
{ \
.id = _id, \
.dev_name = dname, \
.name = cname, \
.parent_names = pnames, \
.num_parents = ARRAY_SIZE(pnames), \
.flags = (f) | CLK_SET_RATE_NO_REPARENT, \
.offset = o, \
.shift = s, \
.width = w, \
.mux_flags = mf, \
.alias = a, \
}
#define MUX(_id, cname, pnames, o, s, w) \
__MUX(_id, NULL, cname, pnames, o, s, w, 0, 0, NULL)
#define MUX_A(_id, cname, pnames, o, s, w, a) \
__MUX(_id, NULL, cname, pnames, o, s, w, 0, 0, a)
#define MUX_F(_id, cname, pnames, o, s, w, f, mf) \
__MUX(_id, NULL, cname, pnames, o, s, w, f, mf, NULL)
#define MUX_FA(_id, cname, pnames, o, s, w, f, mf, a) \
__MUX(_id, NULL, cname, pnames, o, s, w, f, mf, a)
/**
* @id: platform specific id of the clock.
* struct samsung_div_clock: information about div clock
* @dev_name: name of the device to which this clock belongs.
* @name: name of this div clock.
* @parent_name: name of the parent clock.
* @flags: optional flags for basic clock.
* @offset: offset of the register for configuring the div.
* @shift: starting bit location of the div control bit-field in @reg.
* @div_flags: flags for div-type clock.
* @alias: optional clock alias name to be assigned to this clock.
*/
struct samsung_div_clock {
unsigned int id;
const char *dev_name;
const char *name;
const char *parent_name;
unsigned long flags;
unsigned long offset;
u8 shift;
u8 width;
u8 div_flags;
const char *alias;
struct clk_div_table *table;
};
#define __DIV(_id, dname, cname, pname, o, s, w, f, df, a, t) \
{ \
.id = _id, \
.dev_name = dname, \
.name = cname, \
.parent_name = pname, \
.flags = f, \
.offset = o, \
.shift = s, \
.width = w, \
.div_flags = df, \
.alias = a, \
.table = t, \
}
#define DIV(_id, cname, pname, o, s, w) \
__DIV(_id, NULL, cname, pname, o, s, w, 0, 0, NULL, NULL)
#define DIV_A(_id, cname, pname, o, s, w, a) \
__DIV(_id, NULL, cname, pname, o, s, w, 0, 0, a, NULL)
#define DIV_F(_id, cname, pname, o, s, w, f, df) \
__DIV(_id, NULL, cname, pname, o, s, w, f, df, NULL, NULL)
#define DIV_T(_id, cname, pname, o, s, w, t) \
__DIV(_id, NULL, cname, pname, o, s, w, 0, 0, NULL, t)
/**
* struct samsung_gate_clock: information about gate clock
* @id: platform specific id of the clock.
* @dev_name: name of the device to which this clock belongs.
* @name: name of this gate clock.
* @parent_name: name of the parent clock.
* @flags: optional flags for basic clock.
* @offset: offset of the register for configuring the gate.
* @bit_idx: bit index of the gate control bit-field in @reg.
* @gate_flags: flags for gate-type clock.
* @alias: optional clock alias name to be assigned to this clock.
*/
struct samsung_gate_clock {
unsigned int id;
const char *dev_name;
const char *name;
const char *parent_name;
unsigned long flags;
unsigned long offset;
u8 bit_idx;
u8 gate_flags;
const char *alias;
};
#define __GATE(_id, dname, cname, pname, o, b, f, gf, a) \
{ \
.id = _id, \
.dev_name = dname, \
.name = cname, \
.parent_name = pname, \
.flags = f, \
.offset = o, \
.bit_idx = b, \
.gate_flags = gf, \
.alias = a, \
}
#define GATE(_id, cname, pname, o, b, f, gf) \
__GATE(_id, NULL, cname, pname, o, b, f, gf, NULL)
#define GATE_A(_id, cname, pname, o, b, f, gf, a) \
__GATE(_id, NULL, cname, pname, o, b, f, gf, a)
#define GATE_D(_id, dname, cname, pname, o, b, f, gf) \
__GATE(_id, dname, cname, pname, o, b, f, gf, NULL)
#define GATE_DA(_id, dname, cname, pname, o, b, f, gf, a) \
__GATE(_id, dname, cname, pname, o, b, f, gf, a)
#define PNAME(x) static const char *x[] __initdata
/**
* struct samsung_clk_reg_dump: register dump of clock controller registers.
* @offset: clock register offset from the controller base address.
* @value: the value to be register at offset.
*/
struct samsung_clk_reg_dump {
u32 offset;
u32 value;
};
/**
* struct samsung_pll_clock: information about pll clock
* @id: platform specific id of the clock.
* @dev_name: name of the device to which this clock belongs.
* @name: name of this pll clock.
* @parent_name: name of the parent clock.
* @flags: optional flags for basic clock.
* @con_offset: offset of the register for configuring the PLL.
* @lock_offset: offset of the register for locking the PLL.
* @type: Type of PLL to be registered.
* @alias: optional clock alias name to be assigned to this clock.
*/
struct samsung_pll_clock {
unsigned int id;
const char *dev_name;
const char *name;
const char *parent_name;
unsigned long flags;
int con_offset;
int lock_offset;
enum samsung_pll_type type;
const struct samsung_pll_rate_table *rate_table;
const char *alias;
};
#define __PLL(_typ, _id, _dname, _name, _pname, _flags, _lock, _con, \
_rtable, _alias) \
{ \
.id = _id, \
.type = _typ, \
.dev_name = _dname, \
.name = _name, \
.parent_name = _pname, \
.flags = CLK_GET_RATE_NOCACHE, \
.con_offset = _con, \
.lock_offset = _lock, \
.rate_table = _rtable, \
.alias = _alias, \
}
#define PLL(_typ, _id, _name, _pname, _lock, _con, _rtable) \
__PLL(_typ, _id, NULL, _name, _pname, CLK_GET_RATE_NOCACHE, \
_lock, _con, _rtable, _name)
#define PLL_A(_typ, _id, _name, _pname, _lock, _con, _alias, _rtable) \
__PLL(_typ, _id, NULL, _name, _pname, CLK_GET_RATE_NOCACHE, \
_lock, _con, _rtable, _alias)
extern struct samsung_clk_provider *__init samsung_clk_init(
struct device_node *np, void __iomem *base,
unsigned long nr_clks);
extern void __init samsung_clk_of_add_provider(struct device_node *np,
struct samsung_clk_provider *ctx);
extern void __init samsung_clk_of_register_fixed_ext(
struct samsung_clk_provider *ctx,
struct samsung_fixed_rate_clock *fixed_rate_clk,
unsigned int nr_fixed_rate_clk,
const struct of_device_id *clk_matches);
extern void samsung_clk_add_lookup(struct samsung_clk_provider *ctx,
struct clk *clk, unsigned int id);
extern void samsung_clk_register_alias(struct samsung_clk_provider *ctx,
struct samsung_clock_alias *list,
unsigned int nr_clk);
extern void __init samsung_clk_register_fixed_rate(
struct samsung_clk_provider *ctx,
struct samsung_fixed_rate_clock *clk_list,
unsigned int nr_clk);
extern void __init samsung_clk_register_fixed_factor(
struct samsung_clk_provider *ctx,
struct samsung_fixed_factor_clock *list,
unsigned int nr_clk);
extern void __init samsung_clk_register_mux(struct samsung_clk_provider *ctx,
struct samsung_mux_clock *clk_list,
unsigned int nr_clk);
extern void __init samsung_clk_register_div(struct samsung_clk_provider *ctx,
struct samsung_div_clock *clk_list,
unsigned int nr_clk);
extern void __init samsung_clk_register_gate(struct samsung_clk_provider *ctx,
struct samsung_gate_clock *clk_list,
unsigned int nr_clk);
extern void __init samsung_clk_register_pll(struct samsung_clk_provider *ctx,
struct samsung_pll_clock *pll_list,
unsigned int nr_clk, void __iomem *base);
extern unsigned long _get_rate(const char *clk_name);
extern void samsung_clk_save(void __iomem *base,
struct samsung_clk_reg_dump *rd,
unsigned int num_regs);
extern void samsung_clk_restore(void __iomem *base,
const struct samsung_clk_reg_dump *rd,
unsigned int num_regs);
extern struct samsung_clk_reg_dump *samsung_clk_alloc_reg_dump(
const unsigned long *rdump,
unsigned long nr_rdump);
#endif /* __SAMSUNG_CLK_H */

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,501 @@
/*
* Copyright (c) 2014 Samsung Electronics Co., Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This file contains the utility functions for composite clocks.
*/
#ifndef __SAMSUNG_CLK_COMPOSITE_H
#define __SAMSUNG_CLK_COMPOSITE_H
#include <linux/clk.h>
#include <linux/clkdev.h>
#include <linux/clk-provider.h>
#include <linux/io.h>
#include "../../soc/samsung/pwrcal/pwrcal.h"
/*
* 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 bwtween callbacks for a given clock-provider.
*/
struct samsung_clk_provider {
void __iomem *reg_base;
struct clk_onecell_data clk_data;
spinlock_t lock;
};
/*
* struct samsung_clk_reg_dump: register dump of clock controller registers.
* @offset: clock register offset from the controller base address.
* @value: the value to be register at offset.
*/
struct samsung_clk_reg_dump {
unsigned long offset;
u32 value;
};
/*
* struct samsung_fixed_rate_clock: information about fixed-rate clock
* @id: platform specific id of the clock.
* @name: name of this fixed-rate clock.
* @parent_name: optional parent clock name.
* @flags: optional fixed-rate clock flags.
* @fixed-rate: fixed clock rate of this clock.
*/
struct samsung_fixed_rate {
unsigned int id;
char *name;
const char *parent_name;
unsigned long flags;
unsigned long fixed_rate;
};
#define FRATE(_id, cname, pname, f, frate) \
{ \
.id = _id, \
.name = cname, \
.parent_name = pname, \
.flags = f, \
.fixed_rate = frate, \
}
extern void __init samsung_register_fixed_rate(
struct samsung_clk_provider *ctx,
struct samsung_fixed_rate *list,
unsigned int nr_clk);
/*
* struct samsung_fixed_factor_clock: information about fixed-factor clock
* @id: platform specific id of the clock.
* @name: name of this fixed-factor clock.
* @parent_name: parent clock name.
* @mult: fixed multiplication factor.
* @div: fixed division factor.
* @flags: optional fixed-factor clock flags.
*/
struct samsung_fixed_factor {
unsigned int id;
char *name;
const char *parent_name;
unsigned long mult;
unsigned long div;
unsigned long flags;
};
#define FFACTOR(_id, cname, pname, m, d, f) \
{ \
.id = _id, \
.name = cname, \
.parent_name = pname, \
.mult = m, \
.div = d, \
.flags = f, \
}
extern void __init samsung_register_fixed_factor(
struct samsung_clk_provider *ctx,
struct samsung_fixed_factor *list,
unsigned int nr_clk);
/*
* PLL145xx Clock Type: PLL1450x, PLL1451x, PLL1452x
* Maximum lock time can be 150 * Pdiv cycles
*/
#define PLL145XX_LOCK_FACTOR (150)
#define PLL145XX_MDIV_MASK (0x3FF)
#define PLL145XX_PDIV_MASK (0x03F)
#define PLL145XX_SDIV_MASK (0x007)
#define PLL145XX_LOCKED_MASK (0x1)
#define PLL145XX_MDIV_SHIFT (16)
#define PLL145XX_PDIV_SHIFT (8)
#define PLL145XX_SDIV_SHIFT (0)
#define PLL145XX_LOCKED_SHIFT (29)
/*
* PLL1460X Clock Type
* Maximum lock time can be 3000 * Pdiv cycles
*/
#define PLL1460X_LOCK_FACTOR (3000)
#define PLL1460X_MDIV_MASK (0x03FF)
#define PLL1460X_PDIV_MASK (0x003F)
#define PLL1460X_SDIV_MASK (0x0007)
#define PLL1460X_KDIV_MASK (0xFFFF)
#define PLL1460X_LOCKED_MASK (0x1)
#define PLL1460X_MDIV_SHIFT (16)
#define PLL1460X_PDIV_SHIFT (8)
#define PLL1460X_SDIV_SHIFT (0)
#define PLL1460X_KDIV_SHIFT (0)
#define PLL1460X_LOCKED_SHIFT (29)
/*
* PLL255xx Clock Type : PLL2551x, PLL2555x
* Maximum lock time can be 200 * Pdiv cycles
*/
#define PLL255XX_LOCK_FACTOR (200)
#define PLL255XX_MDIV_MASK (0x3FF)
#define PLL255XX_PDIV_MASK (0x3F)
#define PLL255XX_SDIV_MASK (0x7)
#define PLL255XX_LOCKED_MASK (0x1)
#define PLL255XX_MDIV_SHIFT (12)
#define PLL255XX_PDIV_SHIFT (4)
#define PLL255XX_SDIV_SHIFT (0)
#define PLL255XX_LOCKED_SHIFT (29)
/*
* PLL2650X Clock Type
* Maximum lock time can be 3000 * Pdiv cycles
*/
#define PLL2650X_LOCK_FACTOR (3000)
#define PLL2650X_MDIV_MASK (0x01FF)
#define PLL2650X_PDIV_MASK (0x003F)
#define PLL2650X_SDIV_MASK (0x0007)
#define PLL2650X_KDIV_MASK (0xFFFF)
#define PLL2650X_LOCKED_MASK (0x1)
#define PLL2650X_MDIV_SHIFT (12)
#define PLL2650X_PDIV_SHIFT (4)
#define PLL2650X_SDIV_SHIFT (0)
#define PLL2650X_KDIV_SHIFT (0)
#define PLL2650X_LOCKED_SHIFT (29)
enum pll_type {
pll_1450x = 0,
pll_1451x,
pll_1452x,
pll_1460x,
pll_2551x,
pll_2555x,
pll_2650x,
};
struct samsung_pll_rate_table {
long rate;
unsigned int pdiv;
unsigned int mdiv;
unsigned int sdiv;
unsigned int kdiv;
};
#define PLL_BYPASS BIT(0)
#define CHK_ON_CHANGING BIT(7)
/*
* struct samsung_composite_pll: information about composite-pll clocks
* @id: id of the clock for binding with device tree.
* @name: name of this pll clock.
* @type: type of this pll clock.
* @lock_reg: register for locking pll.
* @con_reg: configuration register for pll.
* @enable_reg: it can be different whether pll can be gated or only bypassed.
* @enable_bit: bit index for en/disable pll.
* @sel_reg: composite-pll has ctrl-mux. when disabled, it is set by 0.
* @sel_bit: bit index for ctrl-mux.
* @stat_reg: when sel_reg is set, status register must be checked.
* @stat_bit: bit index for status register.
* @rate_table: available pll output ratio table.
* @alias: support alias for this clock.
*/
struct samsung_composite_pll {
struct clk_hw hw;
unsigned int id;
const char *name;
enum pll_type type;
void __iomem *lock_reg;
void __iomem *con_reg;
void __iomem *enable_reg;
unsigned int enable_bit;
void __iomem *sel_reg;
unsigned int sel_bit;
void __iomem *stat_reg;
unsigned int stat_bit;
const struct samsung_pll_rate_table *rate_table;
unsigned int rate_count;
unsigned int pll_flag;
u8 flag;
const char *alias;
};
#define PLL(_id, cname, _type, lock, con, en, enbit, sel, selbit, stat, statbit, rtable, pf, f, a) \
{ \
.id = _id, \
.name = cname, \
.type = _type, \
.lock_reg = lock, \
.con_reg = con, \
.enable_reg = en, \
.enable_bit = enbit, \
.sel_reg = sel, \
.sel_bit = selbit, \
.stat_reg = stat, \
.stat_bit = statbit, \
.rate_table = rtable, \
.rate_count = 0, \
.pll_flag = pf, \
.flag = f, \
.alias = a, \
}
extern void samsung_register_comp_pll(
struct samsung_clk_provider *ctx,
struct samsung_composite_pll *pll_list,
unsigned int nr_pll);
#define PNAME(x) static const char *x[]
/*
* struct samsung_composite_mux: information about composite-mux clocks
* @id: id of the clock for binding with device tree.
* @name: name of this mux clock.
* @parents: array of parent clocks.
* @num_parents: number of parent clocks.
* @sel_reg: register for mux selection.
* @sel_bit: bit index for sel_reg.
* @sel_width: different by number of parent clocks.
* @stat_reg: status must be checked when changing parent.
* @stat_bit: bit index for status register.
* @stat_width: different by number of parent clocks.
* @flag: optional flag for clock.
* @alias: optional name. recommend no more than 15 characters.
*/
struct samsung_composite_mux {
struct clk_hw hw;
unsigned int id;
const char *name;
const char **parents;
unsigned int num_parents;
void __iomem *sel_reg;
unsigned int sel_bit;
unsigned int sel_width;
void __iomem *stat_reg;
unsigned int stat_bit;
unsigned int stat_width;
unsigned int flag;
const char *alias;
spinlock_t *lock;
};
#define MUX(_id, cname, pnames, sel, selbit, selwid, stat, statbit, statwid, f, a) \
{ \
.id = _id, \
.name = cname, \
.parents = pnames, \
.num_parents = ARRAY_SIZE(pnames), \
.sel_reg = sel, \
.sel_bit = selbit, \
.sel_width = selwid, \
.stat_reg = stat, \
.stat_bit = statbit, \
.stat_width = statwid, \
.flag = f, \
.alias = a, \
}
extern void samsung_register_comp_mux(
struct samsung_clk_provider *ctx,
struct samsung_composite_mux *mux_list,
unsigned int nr_mux);
/*
* struct samsung_composite_divider: information about composite-divider clocks
* @id: id of the clock for binding with device tree.
* @name: name of this divider clock.
* @parent_name: name of parent clock.
* @rate_reg: register for ratio selection.
* @rate_bit: bit index for rate_reg.
* @rate_width: can be different by bit index.
* @stat_reg: status must be checked when changing ratio.
* @stat_bit: bit index for status register.
* @stat_width: can be different by bit index.
* @flag: flag for clock.
* @alias: optional name. recommend no more than 15 characters.
*/
struct samsung_composite_divider {
struct clk_hw hw;
unsigned int id;
const char *name;
const char *parent_name;
void __iomem *rate_reg;
unsigned int rate_bit;
unsigned int rate_width;
void __iomem *stat_reg;
unsigned int stat_bit;
unsigned int stat_width;
unsigned int flag;
const char *alias;
spinlock_t *lock;
};
#define DIV(_id, cname, pname, rate, ratebit, ratewid, stat, statbit, statwid, f, a) \
{ \
.id = _id, \
.name = cname, \
.parent_name = pname, \
.rate_reg = rate, \
.rate_bit = ratebit, \
.rate_width = ratewid, \
.stat_reg = stat, \
.stat_bit = statbit, \
.stat_width = statwid, \
.flag = f, \
.alias = a, \
}
extern void samsung_register_comp_divider(struct samsung_clk_provider *ctx,
struct samsung_composite_divider *div_list, unsigned int nr_div);
#define CLK_GATE_ENABLE BIT(20)
#define CLK_ON_CHANGING BIT(7)
/*
* struct samsung_gate: information about gate clocks
* @id: id of the clock for binding with device tree.
* @name:
* @parent_name:
* @reg:
* @bit:
* @flag:
* @alias:
*/
struct samsung_gate {
unsigned int id;
const char *name;
const char *parent_name;
void __iomem *reg;
u8 bit;
unsigned int flag;
const char *alias;
};
#define GATE(_id, cname, pname, r, b, f, a) \
{ \
.id = _id, \
.name = cname, \
.parent_name = pname, \
.reg = r, \
.bit = b, \
.flag = f, \
.alias = a, \
}
extern void __init samsung_register_gate(
struct samsung_clk_provider *ctx,
struct samsung_gate *gate_list,
unsigned int nr_gate);
struct clk_samsung_usermux {
struct clk_hw hw;
void __iomem *sel_reg;
u8 sel_bit;
void __iomem *stat_reg;
u8 stat_bit;
u8 flag;
spinlock_t *lock;
};
/*
* struct samsung_composite_usermux: information about usermux clocks
* @id: id of the clock for binding with device tree.
* @name: name of this usermux clock.
* @parent_name: name of parent clock.
* @sel_reg: register for usermux selection.
* @sel_bit: bit index for sel_reg.
* @stat_reg: status must be checked when changing parent.
* @stat_bit: bit index for status register.
* @flag: optional flag for clock.
* @alias: optional name. recommend no more than 15 characters.
*/
struct samsung_usermux {
unsigned int id;
const char *name;
const char *parent_name;
void __iomem *sel_reg;
u8 sel_bit;
void __iomem *stat_reg;
u8 stat_bit;
u8 flag;
const char *alias;
};
#define USERMUX(_id, cname, pname, sel, selbit, stat, statbit, f, a) \
{ \
.id = _id, \
.name = cname, \
.parent_name = pname, \
.sel_reg = sel, \
.sel_bit = selbit, \
.stat_reg = stat, \
.stat_bit = statbit, \
.flag = f, \
.alias = a, \
}
extern void __init samsung_register_usermux(
struct samsung_clk_provider *ctx,
struct samsung_usermux *list,
unsigned int nr_usermux);
#define VCLK_DFS BIT(1)
#define VCLK_DFS_SWITCH BIT(2)
/*
* struct init_vclk: initial information for virtual clocks
* @id: id of the clock for binding with device tree.
* @calid: id of the clock for calling cal.
* @name: name of this virtual clock.
* @flags: optional flag for clock.
* @vclk_flags: optional flag for only virtual clock.
* @alias: optional name. recommend no more than 15 characters.
*/
struct init_vclk{
unsigned int id;
unsigned int calid;
const char *name;
u8 flags;
u8 vclk_flags;
const char *alias;
};
struct samsung_vclk {
struct clk_hw hw;
unsigned int id;
u8 flags;
spinlock_t *lock;
};
#define VCLK(_id, _calid, _name, f, vf, a) \
{ \
.id = _id, \
.calid = _calid, \
.name = _name, \
.flags = f, \
.vclk_flags = vf, \
.alias = a, \
}
extern void __init samsung_register_vclk(struct samsung_clk_provider *ctx,
struct init_vclk *list, unsigned int nr_vclk);
extern struct samsung_clk_provider *__init samsung_clk_init(
struct device_node *np, void __iomem *base,
unsigned long nr_clks);
extern void __init samsung_clk_of_add_provider(struct device_node *np,
struct samsung_clk_provider *ctx);
extern void __init samsung_register_of_fixed_ext(
struct samsung_clk_provider *ctx,
struct samsung_fixed_rate *fixed_rate_clk,
unsigned int nr_fixed_rate_clk,
struct of_device_id *clk_matches);
extern void samsung_clk_save(void __iomem *base,
struct samsung_clk_reg_dump *rd,
unsigned int num_regs);
extern void samsung_clk_restore(void __iomem *base,
const struct samsung_clk_reg_dump *rd,
unsigned int num_regs);
extern struct samsung_clk_reg_dump *samsung_clk_alloc_reg_dump(
const unsigned long *rdump,
unsigned long nr_rdump);
#endif /* __SAMSUNG_CLK_COMPOSITE_H */