In addition to a few clean up and code consolidation patches this
includes: - addition of sound subsystem related clocks for Exynos5410 SoC (EPLL, PDMA) and support for "samsung,exynos5410-audss-clock" compatible in the clk-exynos-audss driver, - addition of DRAM controller related clocks for exynos5420, - MAINTAINERS update adding Chanwoo Choi as the Samsung SoC clock drivers co-maintainer. -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAABCAAGBQJX0thBAAoJEE1bIKeAnHqLjhwP/1sNlCVU30OQYAsVOG8doaL2 tP4vQmxKWREMK+gg1iWyq6dhAWhOO/YdSL9KgvHAkCKolJfpoGfJjiPm0Pja+TOq pIHOdE5ql2Cb+PxeJoLQZxfcOsNczt0OorVWgeTJdDyB+/VXaGvVKYwoZFSUoQ5m nIPfAut5ynIVIk86EBjuSr61sUMoTEzVD7HFGAzYF78K4UPIsscfM43UWSHXqwiX rsxPZTzjETmtmjSPSP+m8mOY04nds0kFDWSPaP6lzmSQYC7jhGQxM7Pl4fmWBYho gqL1z4gcp4vHZYRHhtClOuKe1+dlXNRLRaFQSRgIFgpfX/AfQh0Hj35I7QhCmD3N LDNTWmiFxLVjPET0Z4NykPRzCfIcWYT4S2U2qJ857C2FG1v3DD/xiZ13UvbySTNi nh/Go6Jp1bbPRQMYxCcMY1a1RJ180qjsNCleC5/5w6KP0DWWJFVDcqFr3NLcmN7e nikD31moCKLEvPrd2Glezajv1IHD6K/c06cBcTHGBu2BobOrsBstTvjiIfDcjtC/ uZymcsWUztPaM1iPLJ0Dzsrw2TkGcukrYm3R4kN4iRzDJK5XPh4dFUgquJOYlyNH PgYGBMXocMrBXNOF9lQ9mAsiO9JCfZLjXH9k2NP3w2P0YNTTSfIjBuBvySSiGK6x aYF0CXwKNDfJhmep+PzE =lEKC -----END PGP SIGNATURE----- Merge tag 'clk-v4.9-samsung' of git://linuxtv.org/snawrocki/samsung into clk-next Pull samsung clk driver updates from Sylwester Nawrocki: In addition to a few clean up and code consolidation patches this includes: - addition of sound subsystem related clocks for Exynos5410 SoC (EPLL, PDMA) and support for "samsung,exynos5410-audss-clock" compatible in the clk-exynos-audss driver, - addition of DRAM controller related clocks for exynos5420, - MAINTAINERS update adding Chanwoo Choi as the Samsung SoC clock drivers co-maintainer. * tag 'clk-v4.9-samsung' of git://linuxtv.org/snawrocki/samsung: clk: samsung: Add support for EPLL on exynos5410 clk: samsung: clk-exynos-audss: Whitespace and debug trace cleanup clk: samsung: clk-exynos-audss: Add exynos5410 compatible clk: samsung: clk-exynos-audss: controller variant handling rework clk: samsung: Use common registration function for pll2550x clk: samsung: exynos5410: Expose the peripheral DMA gate clocks clk: samsung: exynos5420: Add clocks for CMU_CDREX domain clk: samsung: exynos5410: Use samsung_cmu_register_one() to simplify code clk: samsung: exynos5260: Move struct samsung_cmu_info to init section MAINTAINERS: Add myself as Samsung SoC clock drivers co-maintainer clk: samsung: exynos5410: Add clock IDs for PDMA and EPLL clocks clk: samsung: Add clock IDs for the CMU_CDREX (DRAM Express Controller)
This commit is contained in:
commit
3db385ea14
|
@ -10,6 +10,8 @@ Required Properties:
|
|||
- "samsung,exynos4210-audss-clock" - controller compatible with all Exynos4 SoCs.
|
||||
- "samsung,exynos5250-audss-clock" - controller compatible with Exynos5250
|
||||
SoCs.
|
||||
- "samsung,exynos5410-audss-clock" - controller compatible with Exynos5410
|
||||
SoCs.
|
||||
- "samsung,exynos5420-audss-clock" - controller compatible with Exynos5420
|
||||
SoCs.
|
||||
- reg: physical base address and length of the controller's register set.
|
||||
|
@ -91,5 +93,5 @@ i2s0: i2s@03830000 {
|
|||
<&clock_audss EXYNOS_MOUT_AUDSS>,
|
||||
<&clock_audss EXYNOS_MOUT_I2S>;
|
||||
clock-names = "iis", "i2s_opclk0", "i2s_opclk1",
|
||||
"mout_audss", "mout_i2s";
|
||||
"mout_audss", "mout_i2s";
|
||||
};
|
||||
|
|
|
@ -12,24 +12,29 @@ Required Properties:
|
|||
|
||||
- #clock-cells: should be 1.
|
||||
|
||||
- clocks: should contain an entry specifying the root clock from external
|
||||
oscillator supplied through XXTI or XusbXTI pin. This clock should be
|
||||
defined using standard clock bindings with "fin_pll" clock-output-name.
|
||||
That clock is being passed internally to the 9 PLLs.
|
||||
|
||||
All available clocks are defined as preprocessor macros in
|
||||
dt-bindings/clock/exynos5410.h header and can be used in device
|
||||
tree sources.
|
||||
|
||||
External clock:
|
||||
|
||||
There is clock that is generated outside the SoC. It
|
||||
is expected that it is defined using standard clock bindings
|
||||
with following clock-output-name:
|
||||
|
||||
- "fin_pll" - PLL input clock from XXTI
|
||||
|
||||
Example 1: An example of a clock controller node is listed below.
|
||||
|
||||
fin_pll: xxti {
|
||||
compatible = "fixed-clock";
|
||||
clock-frequency = <24000000>;
|
||||
clock-output-names = "fin_pll";
|
||||
#clock-cells = <0>;
|
||||
};
|
||||
|
||||
clock: clock-controller@0x10010000 {
|
||||
compatible = "samsung,exynos5410-clock";
|
||||
reg = <0x10010000 0x30000>;
|
||||
#clock-cells = <1>;
|
||||
clocks = <&fin_pll>;
|
||||
};
|
||||
|
||||
Example 2: UART controller node that consumes the clock generated by the clock
|
||||
|
|
|
@ -10240,9 +10240,12 @@ F: drivers/nfc/s3fwrn5
|
|||
SAMSUNG SOC CLOCK DRIVERS
|
||||
M: Sylwester Nawrocki <s.nawrocki@samsung.com>
|
||||
M: Tomasz Figa <tomasz.figa@gmail.com>
|
||||
M: Chanwoo Choi <cw00.choi@samsung.com>
|
||||
S: Supported
|
||||
L: linux-samsung-soc@vger.kernel.org (moderated for non-subscribers)
|
||||
F: drivers/clk/samsung/
|
||||
F: include/dt-bindings/clock/exynos*.h
|
||||
F: Documentation/devicetree/bindings/clock/exynos*.txt
|
||||
|
||||
SAMSUNG SXGBE DRIVERS
|
||||
M: Byungho An <bh74.an@samsung.com>
|
||||
|
|
|
@ -14,18 +14,13 @@
|
|||
#include <linux/clk.h>
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_device.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;
|
||||
|
@ -44,9 +39,9 @@ static struct clk *epll;
|
|||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static unsigned long reg_save[][2] = {
|
||||
{ASS_CLK_SRC, 0},
|
||||
{ASS_CLK_DIV, 0},
|
||||
{ASS_CLK_GATE, 0},
|
||||
{ ASS_CLK_SRC, 0 },
|
||||
{ ASS_CLK_DIV, 0 },
|
||||
{ ASS_CLK_GATE, 0 },
|
||||
};
|
||||
|
||||
static int exynos_audss_clk_suspend(void)
|
||||
|
@ -73,14 +68,43 @@ static struct syscore_ops exynos_audss_clk_syscore_ops = {
|
|||
};
|
||||
#endif /* CONFIG_PM_SLEEP */
|
||||
|
||||
struct exynos_audss_clk_drvdata {
|
||||
unsigned int has_adma_clk:1;
|
||||
unsigned int has_mst_clk:1;
|
||||
unsigned int enable_epll:1;
|
||||
unsigned int num_clks;
|
||||
};
|
||||
|
||||
static const struct exynos_audss_clk_drvdata exynos4210_drvdata = {
|
||||
.num_clks = EXYNOS_AUDSS_MAX_CLKS - 1,
|
||||
};
|
||||
|
||||
static const struct exynos_audss_clk_drvdata exynos5410_drvdata = {
|
||||
.num_clks = EXYNOS_AUDSS_MAX_CLKS - 1,
|
||||
.has_mst_clk = 1,
|
||||
};
|
||||
|
||||
static const struct exynos_audss_clk_drvdata exynos5420_drvdata = {
|
||||
.num_clks = EXYNOS_AUDSS_MAX_CLKS,
|
||||
.has_adma_clk = 1,
|
||||
.enable_epll = 1,
|
||||
};
|
||||
|
||||
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, },
|
||||
{},
|
||||
{
|
||||
.compatible = "samsung,exynos4210-audss-clock",
|
||||
.data = &exynos4210_drvdata,
|
||||
}, {
|
||||
.compatible = "samsung,exynos5250-audss-clock",
|
||||
.data = &exynos4210_drvdata,
|
||||
}, {
|
||||
.compatible = "samsung,exynos5410-audss-clock",
|
||||
.data = &exynos5410_drvdata,
|
||||
}, {
|
||||
.compatible = "samsung,exynos5420-audss-clock",
|
||||
.data = &exynos5420_drvdata,
|
||||
},
|
||||
{ },
|
||||
};
|
||||
|
||||
static void exynos_audss_clk_teardown(void)
|
||||
|
@ -106,19 +130,17 @@ static void exynos_audss_clk_teardown(void)
|
|||
/* 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;
|
||||
const struct exynos_audss_clk_drvdata *variant;
|
||||
struct resource *res;
|
||||
int i, ret = 0;
|
||||
|
||||
match = of_match_node(exynos_audss_clk_of_match, pdev->dev.of_node);
|
||||
if (!match)
|
||||
variant = of_device_get_match_data(&pdev->dev);
|
||||
if (!variant)
|
||||
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);
|
||||
|
@ -126,7 +148,7 @@ static int exynos_audss_clk_probe(struct platform_device *pdev)
|
|||
dev_err(&pdev->dev, "failed to map audss registers\n");
|
||||
return PTR_ERR(reg_base);
|
||||
}
|
||||
/* EPLL don't have to be enabled for boards other than Exynos5420 */
|
||||
|
||||
epll = ERR_PTR(-ENODEV);
|
||||
|
||||
clk_table = devm_kzalloc(&pdev->dev,
|
||||
|
@ -136,10 +158,7 @@ static int exynos_audss_clk_probe(struct platform_device *pdev)
|
|||
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;
|
||||
clk_data.clk_num = variant->num_clks;
|
||||
|
||||
pll_ref = devm_clk_get(&pdev->dev, "pll_ref");
|
||||
pll_in = devm_clk_get(&pdev->dev, "pll_in");
|
||||
|
@ -148,13 +167,13 @@ static int exynos_audss_clk_probe(struct platform_device *pdev)
|
|||
if (!IS_ERR(pll_in)) {
|
||||
mout_audss_p[1] = __clk_get_name(pll_in);
|
||||
|
||||
if (variant == TYPE_EXYNOS5420) {
|
||||
if (variant->enable_epll) {
|
||||
epll = pll_in;
|
||||
|
||||
ret = clk_prepare_enable(epll);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev,
|
||||
"failed to prepare the epll clock\n");
|
||||
"failed to prepare the epll clock\n");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
@ -210,7 +229,7 @@ static int exynos_audss_clk_probe(struct platform_device *pdev)
|
|||
sclk_pcm_p, CLK_SET_RATE_PARENT,
|
||||
reg_base + ASS_CLK_GATE, 5, 0, &lock);
|
||||
|
||||
if (variant == TYPE_EXYNOS5420) {
|
||||
if (variant->has_adma_clk) {
|
||||
clk_table[EXYNOS_ADMA] = clk_register_gate(NULL, "adma",
|
||||
"dout_srp", CLK_SET_RATE_PARENT,
|
||||
reg_base + ASS_CLK_GATE, 9, 0, &lock);
|
||||
|
@ -234,9 +253,6 @@ static int exynos_audss_clk_probe(struct platform_device *pdev)
|
|||
#ifdef CONFIG_PM_SLEEP
|
||||
register_syscore_ops(&exynos_audss_clk_syscore_ops);
|
||||
#endif
|
||||
|
||||
dev_info(&pdev->dev, "setup completed\n");
|
||||
|
||||
return 0;
|
||||
|
||||
unregister:
|
||||
|
|
|
@ -131,21 +131,21 @@ static const struct samsung_gate_clock aud_gate_clks[] __initconst = {
|
|||
EN_IP_AUD, 4, 0, 0),
|
||||
};
|
||||
|
||||
static const struct samsung_cmu_info aud_cmu __initconst = {
|
||||
.mux_clks = aud_mux_clks,
|
||||
.nr_mux_clks = ARRAY_SIZE(aud_mux_clks),
|
||||
.div_clks = aud_div_clks,
|
||||
.nr_div_clks = ARRAY_SIZE(aud_div_clks),
|
||||
.gate_clks = aud_gate_clks,
|
||||
.nr_gate_clks = ARRAY_SIZE(aud_gate_clks),
|
||||
.nr_clk_ids = AUD_NR_CLK,
|
||||
.clk_regs = aud_clk_regs,
|
||||
.nr_clk_regs = ARRAY_SIZE(aud_clk_regs),
|
||||
};
|
||||
|
||||
static void __init exynos5260_clk_aud_init(struct device_node *np)
|
||||
{
|
||||
struct samsung_cmu_info cmu = { NULL };
|
||||
|
||||
cmu.mux_clks = aud_mux_clks;
|
||||
cmu.nr_mux_clks = ARRAY_SIZE(aud_mux_clks);
|
||||
cmu.div_clks = aud_div_clks;
|
||||
cmu.nr_div_clks = ARRAY_SIZE(aud_div_clks);
|
||||
cmu.gate_clks = aud_gate_clks;
|
||||
cmu.nr_gate_clks = ARRAY_SIZE(aud_gate_clks);
|
||||
cmu.nr_clk_ids = AUD_NR_CLK;
|
||||
cmu.clk_regs = aud_clk_regs;
|
||||
cmu.nr_clk_regs = ARRAY_SIZE(aud_clk_regs);
|
||||
|
||||
samsung_cmu_register_one(np, &cmu);
|
||||
samsung_cmu_register_one(np, &aud_cmu);
|
||||
}
|
||||
|
||||
CLK_OF_DECLARE(exynos5260_clk_aud, "samsung,exynos5260-clock-aud",
|
||||
|
@ -321,21 +321,21 @@ static const struct samsung_gate_clock disp_gate_clks[] __initconst = {
|
|||
EN_IP_DISP, 25, 0, 0),
|
||||
};
|
||||
|
||||
static const struct samsung_cmu_info disp_cmu __initconst = {
|
||||
.mux_clks = disp_mux_clks,
|
||||
.nr_mux_clks = ARRAY_SIZE(disp_mux_clks),
|
||||
.div_clks = disp_div_clks,
|
||||
.nr_div_clks = ARRAY_SIZE(disp_div_clks),
|
||||
.gate_clks = disp_gate_clks,
|
||||
.nr_gate_clks = ARRAY_SIZE(disp_gate_clks),
|
||||
.nr_clk_ids = DISP_NR_CLK,
|
||||
.clk_regs = disp_clk_regs,
|
||||
.nr_clk_regs = ARRAY_SIZE(disp_clk_regs),
|
||||
};
|
||||
|
||||
static void __init exynos5260_clk_disp_init(struct device_node *np)
|
||||
{
|
||||
struct samsung_cmu_info cmu = { NULL };
|
||||
|
||||
cmu.mux_clks = disp_mux_clks;
|
||||
cmu.nr_mux_clks = ARRAY_SIZE(disp_mux_clks);
|
||||
cmu.div_clks = disp_div_clks;
|
||||
cmu.nr_div_clks = ARRAY_SIZE(disp_div_clks);
|
||||
cmu.gate_clks = disp_gate_clks;
|
||||
cmu.nr_gate_clks = ARRAY_SIZE(disp_gate_clks);
|
||||
cmu.nr_clk_ids = DISP_NR_CLK;
|
||||
cmu.clk_regs = disp_clk_regs;
|
||||
cmu.nr_clk_regs = ARRAY_SIZE(disp_clk_regs);
|
||||
|
||||
samsung_cmu_register_one(np, &cmu);
|
||||
samsung_cmu_register_one(np, &disp_cmu);
|
||||
}
|
||||
|
||||
CLK_OF_DECLARE(exynos5260_clk_disp, "samsung,exynos5260-clock-disp",
|
||||
|
@ -385,21 +385,21 @@ static const struct samsung_pll_clock egl_pll_clks[] __initconst = {
|
|||
pll2550_24mhz_tbl),
|
||||
};
|
||||
|
||||
static const struct samsung_cmu_info egl_cmu __initconst = {
|
||||
.pll_clks = egl_pll_clks,
|
||||
.nr_pll_clks = ARRAY_SIZE(egl_pll_clks),
|
||||
.mux_clks = egl_mux_clks,
|
||||
.nr_mux_clks = ARRAY_SIZE(egl_mux_clks),
|
||||
.div_clks = egl_div_clks,
|
||||
.nr_div_clks = ARRAY_SIZE(egl_div_clks),
|
||||
.nr_clk_ids = EGL_NR_CLK,
|
||||
.clk_regs = egl_clk_regs,
|
||||
.nr_clk_regs = ARRAY_SIZE(egl_clk_regs),
|
||||
};
|
||||
|
||||
static void __init exynos5260_clk_egl_init(struct device_node *np)
|
||||
{
|
||||
struct samsung_cmu_info cmu = { NULL };
|
||||
|
||||
cmu.pll_clks = egl_pll_clks;
|
||||
cmu.nr_pll_clks = ARRAY_SIZE(egl_pll_clks);
|
||||
cmu.mux_clks = egl_mux_clks;
|
||||
cmu.nr_mux_clks = ARRAY_SIZE(egl_mux_clks);
|
||||
cmu.div_clks = egl_div_clks;
|
||||
cmu.nr_div_clks = ARRAY_SIZE(egl_div_clks);
|
||||
cmu.nr_clk_ids = EGL_NR_CLK;
|
||||
cmu.clk_regs = egl_clk_regs;
|
||||
cmu.nr_clk_regs = ARRAY_SIZE(egl_clk_regs);
|
||||
|
||||
samsung_cmu_register_one(np, &cmu);
|
||||
samsung_cmu_register_one(np, &egl_cmu);
|
||||
}
|
||||
|
||||
CLK_OF_DECLARE(exynos5260_clk_egl, "samsung,exynos5260-clock-egl",
|
||||
|
@ -487,19 +487,19 @@ static const struct samsung_gate_clock fsys_gate_clks[] __initconst = {
|
|||
EN_IP_FSYS_SECURE_SMMU_RTIC, 12, 0, 0),
|
||||
};
|
||||
|
||||
static const struct samsung_cmu_info fsys_cmu __initconst = {
|
||||
.mux_clks = fsys_mux_clks,
|
||||
.nr_mux_clks = ARRAY_SIZE(fsys_mux_clks),
|
||||
.gate_clks = fsys_gate_clks,
|
||||
.nr_gate_clks = ARRAY_SIZE(fsys_gate_clks),
|
||||
.nr_clk_ids = FSYS_NR_CLK,
|
||||
.clk_regs = fsys_clk_regs,
|
||||
.nr_clk_regs = ARRAY_SIZE(fsys_clk_regs),
|
||||
};
|
||||
|
||||
static void __init exynos5260_clk_fsys_init(struct device_node *np)
|
||||
{
|
||||
struct samsung_cmu_info cmu = { NULL };
|
||||
|
||||
cmu.mux_clks = fsys_mux_clks;
|
||||
cmu.nr_mux_clks = ARRAY_SIZE(fsys_mux_clks);
|
||||
cmu.gate_clks = fsys_gate_clks;
|
||||
cmu.nr_gate_clks = ARRAY_SIZE(fsys_gate_clks);
|
||||
cmu.nr_clk_ids = FSYS_NR_CLK;
|
||||
cmu.clk_regs = fsys_clk_regs;
|
||||
cmu.nr_clk_regs = ARRAY_SIZE(fsys_clk_regs);
|
||||
|
||||
samsung_cmu_register_one(np, &cmu);
|
||||
samsung_cmu_register_one(np, &fsys_cmu);
|
||||
}
|
||||
|
||||
CLK_OF_DECLARE(exynos5260_clk_fsys, "samsung,exynos5260-clock-fsys",
|
||||
|
@ -576,21 +576,21 @@ static const struct samsung_gate_clock g2d_gate_clks[] __initconst = {
|
|||
EN_IP_G2D_SECURE_SMMU_G2D, 15, 0, 0),
|
||||
};
|
||||
|
||||
static const struct samsung_cmu_info g2d_cmu __initconst = {
|
||||
.mux_clks = g2d_mux_clks,
|
||||
.nr_mux_clks = ARRAY_SIZE(g2d_mux_clks),
|
||||
.div_clks = g2d_div_clks,
|
||||
.nr_div_clks = ARRAY_SIZE(g2d_div_clks),
|
||||
.gate_clks = g2d_gate_clks,
|
||||
.nr_gate_clks = ARRAY_SIZE(g2d_gate_clks),
|
||||
.nr_clk_ids = G2D_NR_CLK,
|
||||
.clk_regs = g2d_clk_regs,
|
||||
.nr_clk_regs = ARRAY_SIZE(g2d_clk_regs),
|
||||
};
|
||||
|
||||
static void __init exynos5260_clk_g2d_init(struct device_node *np)
|
||||
{
|
||||
struct samsung_cmu_info cmu = { NULL };
|
||||
|
||||
cmu.mux_clks = g2d_mux_clks;
|
||||
cmu.nr_mux_clks = ARRAY_SIZE(g2d_mux_clks);
|
||||
cmu.div_clks = g2d_div_clks;
|
||||
cmu.nr_div_clks = ARRAY_SIZE(g2d_div_clks);
|
||||
cmu.gate_clks = g2d_gate_clks;
|
||||
cmu.nr_gate_clks = ARRAY_SIZE(g2d_gate_clks);
|
||||
cmu.nr_clk_ids = G2D_NR_CLK;
|
||||
cmu.clk_regs = g2d_clk_regs;
|
||||
cmu.nr_clk_regs = ARRAY_SIZE(g2d_clk_regs);
|
||||
|
||||
samsung_cmu_register_one(np, &cmu);
|
||||
samsung_cmu_register_one(np, &g2d_cmu);
|
||||
}
|
||||
|
||||
CLK_OF_DECLARE(exynos5260_clk_g2d, "samsung,exynos5260-clock-g2d",
|
||||
|
@ -637,23 +637,23 @@ static const struct samsung_pll_clock g3d_pll_clks[] __initconst = {
|
|||
pll2550_24mhz_tbl),
|
||||
};
|
||||
|
||||
static const struct samsung_cmu_info g3d_cmu __initconst = {
|
||||
.pll_clks = g3d_pll_clks,
|
||||
.nr_pll_clks = ARRAY_SIZE(g3d_pll_clks),
|
||||
.mux_clks = g3d_mux_clks,
|
||||
.nr_mux_clks = ARRAY_SIZE(g3d_mux_clks),
|
||||
.div_clks = g3d_div_clks,
|
||||
.nr_div_clks = ARRAY_SIZE(g3d_div_clks),
|
||||
.gate_clks = g3d_gate_clks,
|
||||
.nr_gate_clks = ARRAY_SIZE(g3d_gate_clks),
|
||||
.nr_clk_ids = G3D_NR_CLK,
|
||||
.clk_regs = g3d_clk_regs,
|
||||
.nr_clk_regs = ARRAY_SIZE(g3d_clk_regs),
|
||||
};
|
||||
|
||||
static void __init exynos5260_clk_g3d_init(struct device_node *np)
|
||||
{
|
||||
struct samsung_cmu_info cmu = { NULL };
|
||||
|
||||
cmu.pll_clks = g3d_pll_clks;
|
||||
cmu.nr_pll_clks = ARRAY_SIZE(g3d_pll_clks);
|
||||
cmu.mux_clks = g3d_mux_clks;
|
||||
cmu.nr_mux_clks = ARRAY_SIZE(g3d_mux_clks);
|
||||
cmu.div_clks = g3d_div_clks;
|
||||
cmu.nr_div_clks = ARRAY_SIZE(g3d_div_clks);
|
||||
cmu.gate_clks = g3d_gate_clks;
|
||||
cmu.nr_gate_clks = ARRAY_SIZE(g3d_gate_clks);
|
||||
cmu.nr_clk_ids = G3D_NR_CLK;
|
||||
cmu.clk_regs = g3d_clk_regs;
|
||||
cmu.nr_clk_regs = ARRAY_SIZE(g3d_clk_regs);
|
||||
|
||||
samsung_cmu_register_one(np, &cmu);
|
||||
samsung_cmu_register_one(np, &g3d_cmu);
|
||||
}
|
||||
|
||||
CLK_OF_DECLARE(exynos5260_clk_g3d, "samsung,exynos5260-clock-g3d",
|
||||
|
@ -772,21 +772,21 @@ static const struct samsung_gate_clock gscl_gate_clks[] __initconst = {
|
|||
EN_IP_GSCL_SECURE_SMMU_MSCL1, 20, 0, 0),
|
||||
};
|
||||
|
||||
static const struct samsung_cmu_info gscl_cmu __initconst = {
|
||||
.mux_clks = gscl_mux_clks,
|
||||
.nr_mux_clks = ARRAY_SIZE(gscl_mux_clks),
|
||||
.div_clks = gscl_div_clks,
|
||||
.nr_div_clks = ARRAY_SIZE(gscl_div_clks),
|
||||
.gate_clks = gscl_gate_clks,
|
||||
.nr_gate_clks = ARRAY_SIZE(gscl_gate_clks),
|
||||
.nr_clk_ids = GSCL_NR_CLK,
|
||||
.clk_regs = gscl_clk_regs,
|
||||
.nr_clk_regs = ARRAY_SIZE(gscl_clk_regs),
|
||||
};
|
||||
|
||||
static void __init exynos5260_clk_gscl_init(struct device_node *np)
|
||||
{
|
||||
struct samsung_cmu_info cmu = { NULL };
|
||||
|
||||
cmu.mux_clks = gscl_mux_clks;
|
||||
cmu.nr_mux_clks = ARRAY_SIZE(gscl_mux_clks);
|
||||
cmu.div_clks = gscl_div_clks;
|
||||
cmu.nr_div_clks = ARRAY_SIZE(gscl_div_clks);
|
||||
cmu.gate_clks = gscl_gate_clks;
|
||||
cmu.nr_gate_clks = ARRAY_SIZE(gscl_gate_clks);
|
||||
cmu.nr_clk_ids = GSCL_NR_CLK;
|
||||
cmu.clk_regs = gscl_clk_regs;
|
||||
cmu.nr_clk_regs = ARRAY_SIZE(gscl_clk_regs);
|
||||
|
||||
samsung_cmu_register_one(np, &cmu);
|
||||
samsung_cmu_register_one(np, &gscl_cmu);
|
||||
}
|
||||
|
||||
CLK_OF_DECLARE(exynos5260_clk_gscl, "samsung,exynos5260-clock-gscl",
|
||||
|
@ -891,21 +891,21 @@ static const struct samsung_gate_clock isp_gate_clks[] __initconst = {
|
|||
EN_SCLK_ISP, 9, CLK_SET_RATE_PARENT, 0),
|
||||
};
|
||||
|
||||
static const struct samsung_cmu_info isp_cmu __initconst = {
|
||||
.mux_clks = isp_mux_clks,
|
||||
.nr_mux_clks = ARRAY_SIZE(isp_mux_clks),
|
||||
.div_clks = isp_div_clks,
|
||||
.nr_div_clks = ARRAY_SIZE(isp_div_clks),
|
||||
.gate_clks = isp_gate_clks,
|
||||
.nr_gate_clks = ARRAY_SIZE(isp_gate_clks),
|
||||
.nr_clk_ids = ISP_NR_CLK,
|
||||
.clk_regs = isp_clk_regs,
|
||||
.nr_clk_regs = ARRAY_SIZE(isp_clk_regs),
|
||||
};
|
||||
|
||||
static void __init exynos5260_clk_isp_init(struct device_node *np)
|
||||
{
|
||||
struct samsung_cmu_info cmu = { NULL };
|
||||
|
||||
cmu.mux_clks = isp_mux_clks;
|
||||
cmu.nr_mux_clks = ARRAY_SIZE(isp_mux_clks);
|
||||
cmu.div_clks = isp_div_clks;
|
||||
cmu.nr_div_clks = ARRAY_SIZE(isp_div_clks);
|
||||
cmu.gate_clks = isp_gate_clks;
|
||||
cmu.nr_gate_clks = ARRAY_SIZE(isp_gate_clks);
|
||||
cmu.nr_clk_ids = ISP_NR_CLK;
|
||||
cmu.clk_regs = isp_clk_regs;
|
||||
cmu.nr_clk_regs = ARRAY_SIZE(isp_clk_regs);
|
||||
|
||||
samsung_cmu_register_one(np, &cmu);
|
||||
samsung_cmu_register_one(np, &isp_cmu);
|
||||
}
|
||||
|
||||
CLK_OF_DECLARE(exynos5260_clk_isp, "samsung,exynos5260-clock-isp",
|
||||
|
@ -955,21 +955,21 @@ static const struct samsung_pll_clock kfc_pll_clks[] __initconst = {
|
|||
pll2550_24mhz_tbl),
|
||||
};
|
||||
|
||||
static const struct samsung_cmu_info kfc_cmu __initconst = {
|
||||
.pll_clks = kfc_pll_clks,
|
||||
.nr_pll_clks = ARRAY_SIZE(kfc_pll_clks),
|
||||
.mux_clks = kfc_mux_clks,
|
||||
.nr_mux_clks = ARRAY_SIZE(kfc_mux_clks),
|
||||
.div_clks = kfc_div_clks,
|
||||
.nr_div_clks = ARRAY_SIZE(kfc_div_clks),
|
||||
.nr_clk_ids = KFC_NR_CLK,
|
||||
.clk_regs = kfc_clk_regs,
|
||||
.nr_clk_regs = ARRAY_SIZE(kfc_clk_regs),
|
||||
};
|
||||
|
||||
static void __init exynos5260_clk_kfc_init(struct device_node *np)
|
||||
{
|
||||
struct samsung_cmu_info cmu = { NULL };
|
||||
|
||||
cmu.pll_clks = kfc_pll_clks;
|
||||
cmu.nr_pll_clks = ARRAY_SIZE(kfc_pll_clks);
|
||||
cmu.mux_clks = kfc_mux_clks;
|
||||
cmu.nr_mux_clks = ARRAY_SIZE(kfc_mux_clks);
|
||||
cmu.div_clks = kfc_div_clks;
|
||||
cmu.nr_div_clks = ARRAY_SIZE(kfc_div_clks);
|
||||
cmu.nr_clk_ids = KFC_NR_CLK;
|
||||
cmu.clk_regs = kfc_clk_regs;
|
||||
cmu.nr_clk_regs = ARRAY_SIZE(kfc_clk_regs);
|
||||
|
||||
samsung_cmu_register_one(np, &cmu);
|
||||
samsung_cmu_register_one(np, &kfc_cmu);
|
||||
}
|
||||
|
||||
CLK_OF_DECLARE(exynos5260_clk_kfc, "samsung,exynos5260-clock-kfc",
|
||||
|
@ -1011,21 +1011,21 @@ static const struct samsung_gate_clock mfc_gate_clks[] __initconst = {
|
|||
EN_IP_MFC_SECURE_SMMU2_MFC, 7, 0, 0),
|
||||
};
|
||||
|
||||
static const struct samsung_cmu_info mfc_cmu __initconst = {
|
||||
.mux_clks = mfc_mux_clks,
|
||||
.nr_mux_clks = ARRAY_SIZE(mfc_mux_clks),
|
||||
.div_clks = mfc_div_clks,
|
||||
.nr_div_clks = ARRAY_SIZE(mfc_div_clks),
|
||||
.gate_clks = mfc_gate_clks,
|
||||
.nr_gate_clks = ARRAY_SIZE(mfc_gate_clks),
|
||||
.nr_clk_ids = MFC_NR_CLK,
|
||||
.clk_regs = mfc_clk_regs,
|
||||
.nr_clk_regs = ARRAY_SIZE(mfc_clk_regs),
|
||||
};
|
||||
|
||||
static void __init exynos5260_clk_mfc_init(struct device_node *np)
|
||||
{
|
||||
struct samsung_cmu_info cmu = { NULL };
|
||||
|
||||
cmu.mux_clks = mfc_mux_clks;
|
||||
cmu.nr_mux_clks = ARRAY_SIZE(mfc_mux_clks);
|
||||
cmu.div_clks = mfc_div_clks;
|
||||
cmu.nr_div_clks = ARRAY_SIZE(mfc_div_clks);
|
||||
cmu.gate_clks = mfc_gate_clks;
|
||||
cmu.nr_gate_clks = ARRAY_SIZE(mfc_gate_clks);
|
||||
cmu.nr_clk_ids = MFC_NR_CLK;
|
||||
cmu.clk_regs = mfc_clk_regs;
|
||||
cmu.nr_clk_regs = ARRAY_SIZE(mfc_clk_regs);
|
||||
|
||||
samsung_cmu_register_one(np, &cmu);
|
||||
samsung_cmu_register_one(np, &mfc_cmu);
|
||||
}
|
||||
|
||||
CLK_OF_DECLARE(exynos5260_clk_mfc, "samsung,exynos5260-clock-mfc",
|
||||
|
@ -1158,23 +1158,23 @@ static const struct samsung_pll_clock mif_pll_clks[] __initconst = {
|
|||
pll2550_24mhz_tbl),
|
||||
};
|
||||
|
||||
static const struct samsung_cmu_info mif_cmu __initconst = {
|
||||
.pll_clks = mif_pll_clks,
|
||||
.nr_pll_clks = ARRAY_SIZE(mif_pll_clks),
|
||||
.mux_clks = mif_mux_clks,
|
||||
.nr_mux_clks = ARRAY_SIZE(mif_mux_clks),
|
||||
.div_clks = mif_div_clks,
|
||||
.nr_div_clks = ARRAY_SIZE(mif_div_clks),
|
||||
.gate_clks = mif_gate_clks,
|
||||
.nr_gate_clks = ARRAY_SIZE(mif_gate_clks),
|
||||
.nr_clk_ids = MIF_NR_CLK,
|
||||
.clk_regs = mif_clk_regs,
|
||||
.nr_clk_regs = ARRAY_SIZE(mif_clk_regs),
|
||||
};
|
||||
|
||||
static void __init exynos5260_clk_mif_init(struct device_node *np)
|
||||
{
|
||||
struct samsung_cmu_info cmu = { NULL };
|
||||
|
||||
cmu.pll_clks = mif_pll_clks;
|
||||
cmu.nr_pll_clks = ARRAY_SIZE(mif_pll_clks);
|
||||
cmu.mux_clks = mif_mux_clks;
|
||||
cmu.nr_mux_clks = ARRAY_SIZE(mif_mux_clks);
|
||||
cmu.div_clks = mif_div_clks;
|
||||
cmu.nr_div_clks = ARRAY_SIZE(mif_div_clks);
|
||||
cmu.gate_clks = mif_gate_clks;
|
||||
cmu.nr_gate_clks = ARRAY_SIZE(mif_gate_clks);
|
||||
cmu.nr_clk_ids = MIF_NR_CLK;
|
||||
cmu.clk_regs = mif_clk_regs;
|
||||
cmu.nr_clk_regs = ARRAY_SIZE(mif_clk_regs);
|
||||
|
||||
samsung_cmu_register_one(np, &cmu);
|
||||
samsung_cmu_register_one(np, &mif_cmu);
|
||||
}
|
||||
|
||||
CLK_OF_DECLARE(exynos5260_clk_mif, "samsung,exynos5260-clock-mif",
|
||||
|
@ -1366,21 +1366,21 @@ static const struct samsung_gate_clock peri_gate_clks[] __initconst = {
|
|||
EN_IP_PERI_SECURE_TZPC, 20, 0, 0),
|
||||
};
|
||||
|
||||
static const struct samsung_cmu_info peri_cmu __initconst = {
|
||||
.mux_clks = peri_mux_clks,
|
||||
.nr_mux_clks = ARRAY_SIZE(peri_mux_clks),
|
||||
.div_clks = peri_div_clks,
|
||||
.nr_div_clks = ARRAY_SIZE(peri_div_clks),
|
||||
.gate_clks = peri_gate_clks,
|
||||
.nr_gate_clks = ARRAY_SIZE(peri_gate_clks),
|
||||
.nr_clk_ids = PERI_NR_CLK,
|
||||
.clk_regs = peri_clk_regs,
|
||||
.nr_clk_regs = ARRAY_SIZE(peri_clk_regs),
|
||||
};
|
||||
|
||||
static void __init exynos5260_clk_peri_init(struct device_node *np)
|
||||
{
|
||||
struct samsung_cmu_info cmu = { NULL };
|
||||
|
||||
cmu.mux_clks = peri_mux_clks;
|
||||
cmu.nr_mux_clks = ARRAY_SIZE(peri_mux_clks);
|
||||
cmu.div_clks = peri_div_clks;
|
||||
cmu.nr_div_clks = ARRAY_SIZE(peri_div_clks);
|
||||
cmu.gate_clks = peri_gate_clks;
|
||||
cmu.nr_gate_clks = ARRAY_SIZE(peri_gate_clks);
|
||||
cmu.nr_clk_ids = PERI_NR_CLK;
|
||||
cmu.clk_regs = peri_clk_regs;
|
||||
cmu.nr_clk_regs = ARRAY_SIZE(peri_clk_regs);
|
||||
|
||||
samsung_cmu_register_one(np, &cmu);
|
||||
samsung_cmu_register_one(np, &peri_cmu);
|
||||
}
|
||||
|
||||
CLK_OF_DECLARE(exynos5260_clk_peri, "samsung,exynos5260-clock-peri",
|
||||
|
@ -1818,25 +1818,25 @@ static const struct samsung_pll_clock top_pll_clks[] __initconst = {
|
|||
pll2650_24mhz_tbl),
|
||||
};
|
||||
|
||||
static const struct samsung_cmu_info top_cmu __initconst = {
|
||||
.pll_clks = top_pll_clks,
|
||||
.nr_pll_clks = ARRAY_SIZE(top_pll_clks),
|
||||
.mux_clks = top_mux_clks,
|
||||
.nr_mux_clks = ARRAY_SIZE(top_mux_clks),
|
||||
.div_clks = top_div_clks,
|
||||
.nr_div_clks = ARRAY_SIZE(top_div_clks),
|
||||
.gate_clks = top_gate_clks,
|
||||
.nr_gate_clks = ARRAY_SIZE(top_gate_clks),
|
||||
.fixed_clks = fixed_rate_clks,
|
||||
.nr_fixed_clks = ARRAY_SIZE(fixed_rate_clks),
|
||||
.nr_clk_ids = TOP_NR_CLK,
|
||||
.clk_regs = top_clk_regs,
|
||||
.nr_clk_regs = ARRAY_SIZE(top_clk_regs),
|
||||
};
|
||||
|
||||
static void __init exynos5260_clk_top_init(struct device_node *np)
|
||||
{
|
||||
struct samsung_cmu_info cmu = { NULL };
|
||||
|
||||
cmu.pll_clks = top_pll_clks;
|
||||
cmu.nr_pll_clks = ARRAY_SIZE(top_pll_clks);
|
||||
cmu.mux_clks = top_mux_clks;
|
||||
cmu.nr_mux_clks = ARRAY_SIZE(top_mux_clks);
|
||||
cmu.div_clks = top_div_clks;
|
||||
cmu.nr_div_clks = ARRAY_SIZE(top_div_clks);
|
||||
cmu.gate_clks = top_gate_clks;
|
||||
cmu.nr_gate_clks = ARRAY_SIZE(top_gate_clks);
|
||||
cmu.fixed_clks = fixed_rate_clks;
|
||||
cmu.nr_fixed_clks = ARRAY_SIZE(fixed_rate_clks);
|
||||
cmu.nr_clk_ids = TOP_NR_CLK;
|
||||
cmu.clk_regs = top_clk_regs;
|
||||
cmu.nr_clk_regs = ARRAY_SIZE(top_clk_regs);
|
||||
|
||||
samsung_cmu_register_one(np, &cmu);
|
||||
samsung_cmu_register_one(np, &top_cmu);
|
||||
}
|
||||
|
||||
CLK_OF_DECLARE(exynos5260_clk_top, "samsung,exynos5260-clock-top",
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include <linux/clk-provider.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/clk.h>
|
||||
|
||||
#include "clk.h"
|
||||
|
||||
|
@ -21,6 +22,8 @@
|
|||
#define APLL_CON0 0x100
|
||||
#define CPLL_LOCK 0x10020
|
||||
#define CPLL_CON0 0x10120
|
||||
#define EPLL_LOCK 0x10040
|
||||
#define EPLL_CON0 0x10130
|
||||
#define MPLL_LOCK 0x4000
|
||||
#define MPLL_CON0 0x4100
|
||||
#define BPLL_LOCK 0x20010
|
||||
|
@ -58,7 +61,7 @@
|
|||
|
||||
/* list of PLLs */
|
||||
enum exynos5410_plls {
|
||||
apll, cpll, mpll,
|
||||
apll, cpll, epll, mpll,
|
||||
bpll, kpll,
|
||||
nr_plls /* number of PLLs */
|
||||
};
|
||||
|
@ -67,6 +70,7 @@ enum exynos5410_plls {
|
|||
PNAME(apll_p) = { "fin_pll", "fout_apll", };
|
||||
PNAME(bpll_p) = { "fin_pll", "fout_bpll", };
|
||||
PNAME(cpll_p) = { "fin_pll", "fout_cpll" };
|
||||
PNAME(epll_p) = { "fin_pll", "fout_epll" };
|
||||
PNAME(mpll_p) = { "fin_pll", "fout_mpll", };
|
||||
PNAME(kpll_p) = { "fin_pll", "fout_kpll", };
|
||||
|
||||
|
@ -95,6 +99,8 @@ static const struct samsung_mux_clock exynos5410_mux_clks[] __initconst = {
|
|||
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_epll", epll_p, SRC_TOP2, 12, 1),
|
||||
|
||||
MUX(0, "sclk_cpll", cpll_p, SRC_TOP2, 8, 1),
|
||||
|
||||
MUX(0, "sclk_mpll_bpll", mpll_bpll_p, SRC_TOP1, 20, 1),
|
||||
|
@ -176,6 +182,8 @@ static const struct samsung_gate_clock exynos5410_gate_clks[] __initconst = {
|
|||
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_PDMA1, "pdma1", "aclk200", GATE_BUS_FSYS0, 2, 0, 0),
|
||||
GATE(CLK_PDMA0, "pdma0", "aclk200", GATE_BUS_FSYS0, 1, 0, 0),
|
||||
|
||||
GATE(CLK_SCLK_USBPHY301, "sclk_usbphy301", "dout_usbphy301",
|
||||
GATE_TOP_SCLK_FSYS, 7, CLK_SET_RATE_PARENT, 0),
|
||||
|
@ -217,11 +225,26 @@ static const struct samsung_gate_clock exynos5410_gate_clks[] __initconst = {
|
|||
GATE(CLK_USBD301, "usbd301", "aclk200_fsys", GATE_IP_FSYS, 20, 0, 0),
|
||||
};
|
||||
|
||||
static const struct samsung_pll_clock exynos5410_plls[nr_plls] __initconst = {
|
||||
static const struct samsung_pll_rate_table exynos5410_pll2550x_24mhz_tbl[] __initconst = {
|
||||
PLL_36XX_RATE(400000000U, 200, 3, 2, 0),
|
||||
PLL_36XX_RATE(333000000U, 111, 2, 2, 0),
|
||||
PLL_36XX_RATE(300000000U, 100, 2, 2, 0),
|
||||
PLL_36XX_RATE(266000000U, 266, 3, 3, 0),
|
||||
PLL_36XX_RATE(200000000U, 200, 3, 3, 0),
|
||||
PLL_36XX_RATE(192000000U, 192, 3, 3, 0),
|
||||
PLL_36XX_RATE(166000000U, 166, 3, 3, 0),
|
||||
PLL_36XX_RATE(133000000U, 266, 3, 4, 0),
|
||||
PLL_36XX_RATE(100000000U, 200, 3, 4, 0),
|
||||
PLL_36XX_RATE(66000000U, 176, 2, 5, 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),
|
||||
[epll] = PLL(pll_2650x, CLK_FOUT_EPLL, "fout_epll", "fin_pll", EPLL_LOCK,
|
||||
EPLL_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,
|
||||
|
@ -230,29 +253,27 @@ static const struct samsung_pll_clock exynos5410_plls[nr_plls] __initconst = {
|
|||
KPLL_CON0, NULL),
|
||||
};
|
||||
|
||||
static const struct samsung_cmu_info cmu __initconst = {
|
||||
.pll_clks = exynos5410_plls,
|
||||
.nr_pll_clks = ARRAY_SIZE(exynos5410_plls),
|
||||
.mux_clks = exynos5410_mux_clks,
|
||||
.nr_mux_clks = ARRAY_SIZE(exynos5410_mux_clks),
|
||||
.div_clks = exynos5410_div_clks,
|
||||
.nr_div_clks = ARRAY_SIZE(exynos5410_div_clks),
|
||||
.gate_clks = exynos5410_gate_clks,
|
||||
.nr_gate_clks = ARRAY_SIZE(exynos5410_gate_clks),
|
||||
.nr_clk_ids = CLK_NR_CLKS,
|
||||
};
|
||||
|
||||
/* register exynos5410 clocks */
|
||||
static void __init exynos5410_clk_init(struct device_node *np)
|
||||
{
|
||||
struct samsung_clk_provider *ctx;
|
||||
void __iomem *reg_base;
|
||||
struct clk *xxti = of_clk_get(np, 0);
|
||||
|
||||
reg_base = of_iomap(np, 0);
|
||||
if (!reg_base)
|
||||
panic("%s: failed to map registers\n", __func__);
|
||||
if (!IS_ERR(xxti) && clk_get_rate(xxti) == 24 * MHZ)
|
||||
exynos5410_plls[epll].rate_table = exynos5410_pll2550x_24mhz_tbl;
|
||||
|
||||
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);
|
||||
samsung_cmu_register_one(np, &cmu);
|
||||
|
||||
pr_debug("Exynos5410: clock setup completed.\n");
|
||||
}
|
||||
|
|
|
@ -131,6 +131,9 @@
|
|||
#define TOP_SPARE2 0x10b08
|
||||
#define BPLL_LOCK 0x20010
|
||||
#define BPLL_CON0 0x20110
|
||||
#define SRC_CDREX 0x20200
|
||||
#define DIV_CDREX0 0x20500
|
||||
#define DIV_CDREX1 0x20504
|
||||
#define KPLL_LOCK 0x28000
|
||||
#define KPLL_CON0 0x28100
|
||||
#define SRC_KFC 0x28200
|
||||
|
@ -244,6 +247,9 @@ static const unsigned long exynos5x_clk_regs[] __initconst = {
|
|||
GATE_TOP_SCLK_FSYS,
|
||||
GATE_TOP_SCLK_PERIC,
|
||||
TOP_SPARE2,
|
||||
SRC_CDREX,
|
||||
DIV_CDREX0,
|
||||
DIV_CDREX1,
|
||||
SRC_KFC,
|
||||
DIV_KFC0,
|
||||
};
|
||||
|
@ -448,6 +454,8 @@ PNAME(mout_maudio0_p) = {"fin_pll", "maudio_clk", "mout_sclk_dpll",
|
|||
"mout_sclk_epll", "mout_sclk_rpll"};
|
||||
PNAME(mout_mau_epll_clk_p) = {"mout_sclk_epll", "mout_sclk_dpll",
|
||||
"mout_sclk_mpll", "mout_sclk_spll"};
|
||||
PNAME(mout_mclk_cdrex_p) = {"mout_bpll", "mout_mx_mspll_ccore"};
|
||||
|
||||
/* List of parents specific to exynos5800 */
|
||||
PNAME(mout_epll2_5800_p) = { "mout_sclk_epll", "ff_dout_epll2" };
|
||||
PNAME(mout_group1_5800_p) = { "mout_sclk_cpll", "mout_sclk_dpll",
|
||||
|
@ -465,6 +473,9 @@ PNAME(mout_group6_5800_p) = { "mout_sclk_ipll", "mout_sclk_dpll",
|
|||
PNAME(mout_group7_5800_p) = { "mout_sclk_cpll", "mout_sclk_dpll",
|
||||
"mout_sclk_mpll", "mout_sclk_spll",
|
||||
"mout_epll2", "mout_sclk_ipll" };
|
||||
PNAME(mout_mx_mspll_ccore_p) = {"sclk_bpll", "mout_sclk_dpll",
|
||||
"mout_sclk_mpll", "ff_dout_spll2",
|
||||
"mout_sclk_spll", "mout_sclk_epll"};
|
||||
PNAME(mout_mau_epll_clk_5800_p) = { "mout_sclk_epll", "mout_sclk_dpll",
|
||||
"mout_sclk_mpll",
|
||||
"ff_dout_spll2" };
|
||||
|
@ -523,6 +534,8 @@ static const struct samsung_mux_clock exynos5800_mux_clks[] __initconst = {
|
|||
MUX(0, "mout_aclk300_disp1", mout_group5_5800_p, SRC_TOP2, 24, 2),
|
||||
MUX(0, "mout_aclk300_gscl", mout_group5_5800_p, SRC_TOP2, 28, 2),
|
||||
|
||||
MUX(CLK_MOUT_MX_MSPLL_CCORE, "mout_mx_mspll_ccore",
|
||||
mout_mx_mspll_ccore_p, SRC_TOP7, 16, 2),
|
||||
MUX(0, "mout_mau_epll_clk", mout_mau_epll_clk_5800_p, SRC_TOP7,
|
||||
20, 2),
|
||||
MUX(0, "sclk_bpll", mout_bpll_p, SRC_TOP7, 24, 1),
|
||||
|
@ -601,6 +614,8 @@ static const struct samsung_mux_clock exynos5420_mux_clks[] __initconst = {
|
|||
MUX(0, "mout_aclk300_disp1", mout_group1_p, SRC_TOP2, 24, 2),
|
||||
MUX(0, "mout_aclk300_gscl", mout_group1_p, SRC_TOP2, 28, 2),
|
||||
|
||||
MUX(CLK_MOUT_MX_MSPLL_CCORE, "mout_mx_mspll_ccore",
|
||||
mout_group5_5800_p, SRC_TOP7, 16, 2),
|
||||
MUX(0, "mout_mau_epll_clk", mout_mau_epll_clk_p, SRC_TOP7, 20, 2),
|
||||
|
||||
MUX(0, "mout_fimd1", mout_group3_p, SRC_DISP10, 4, 1),
|
||||
|
@ -744,6 +759,12 @@ static const struct samsung_mux_clock exynos5x_mux_clks[] __initconst = {
|
|||
|
||||
MUX(0, "mout_fimd1_final", mout_fimd1_final_p, TOP_SPARE2, 8, 1),
|
||||
|
||||
/* CDREX block */
|
||||
MUX_F(CLK_MOUT_MCLK_CDREX, "mout_mclk_cdrex", mout_mclk_cdrex_p,
|
||||
SRC_CDREX, 4, 1, CLK_SET_RATE_PARENT, 0),
|
||||
MUX_F(CLK_MOUT_BPLL, "mout_bpll", mout_bpll_p, SRC_CDREX, 0, 1,
|
||||
CLK_SET_RATE_PARENT, 0),
|
||||
|
||||
/* MAU Block */
|
||||
MUX(CLK_MOUT_MAUDIO0, "mout_maudio0", mout_maudio0_p, SRC_MAU, 28, 3),
|
||||
|
||||
|
@ -836,6 +857,21 @@ static const struct samsung_div_clock exynos5x_div_clks[] __initconst = {
|
|||
DIV(CLK_DOUT_ACLK400_DISP1, "dout_aclk400_disp1",
|
||||
"mout_aclk400_disp1", DIV_TOP2, 4, 3),
|
||||
|
||||
/* CDREX Block */
|
||||
DIV(CLK_DOUT_PCLK_CDREX, "dout_pclk_cdrex", "dout_aclk_cdrex1",
|
||||
DIV_CDREX0, 28, 3),
|
||||
DIV_F(CLK_DOUT_SCLK_CDREX, "dout_sclk_cdrex", "mout_mclk_cdrex",
|
||||
DIV_CDREX0, 24, 3, CLK_SET_RATE_PARENT, 0),
|
||||
DIV(CLK_DOUT_ACLK_CDREX1, "dout_aclk_cdrex1", "dout_clk2x_phy0",
|
||||
DIV_CDREX0, 16, 3),
|
||||
DIV(CLK_DOUT_CCLK_DREX0, "dout_cclk_drex0", "dout_clk2x_phy0",
|
||||
DIV_CDREX0, 8, 3),
|
||||
DIV(CLK_DOUT_CLK2X_PHY0, "dout_clk2x_phy0", "dout_sclk_cdrex",
|
||||
DIV_CDREX0, 3, 5),
|
||||
|
||||
DIV(CLK_DOUT_PCLK_CORE_MEM, "dout_pclk_core_mem", "mout_mclk_cdrex",
|
||||
DIV_CDREX1, 8, 3),
|
||||
|
||||
/* Audio Block */
|
||||
DIV(0, "dout_maudio0", "mout_maudio0", DIV_MAU, 20, 4),
|
||||
DIV(0, "dout_maupcm0", "dout_maudio0", DIV_MAU, 24, 8),
|
||||
|
@ -1364,6 +1400,7 @@ static void __init exynos5x_clk_init(struct device_node *np,
|
|||
if (_get_rate("fin_pll") == 24 * MHZ) {
|
||||
exynos5x_plls[apll].rate_table = exynos5420_pll2550x_24mhz_tbl;
|
||||
exynos5x_plls[kpll].rate_table = exynos5420_pll2550x_24mhz_tbl;
|
||||
exynos5x_plls[bpll].rate_table = exynos5420_pll2550x_24mhz_tbl;
|
||||
}
|
||||
|
||||
samsung_clk_register_pll(ctx, exynos5x_plls, ARRAY_SIZE(exynos5x_plls),
|
||||
|
|
|
@ -112,6 +112,11 @@ static struct notifier_block exynos5440_clk_restart_handler = {
|
|||
.priority = 128,
|
||||
};
|
||||
|
||||
static const struct samsung_pll_clock exynos5440_plls[] __initconst = {
|
||||
PLL(pll_2550x, CLK_CPLLA, "cplla", "xtal", 0, 0x4c, NULL),
|
||||
PLL(pll_2550x, CLK_CPLLB, "cpllb", "xtal", 0, 0x50, NULL),
|
||||
};
|
||||
|
||||
/* register exynos5440 clocks */
|
||||
static void __init exynos5440_clk_init(struct device_node *np)
|
||||
{
|
||||
|
@ -129,8 +134,8 @@ static void __init exynos5440_clk_init(struct device_node *np)
|
|||
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_pll(ctx, exynos5440_plls,
|
||||
ARRAY_SIZE(exynos5440_plls), ctx->reg_base);
|
||||
|
||||
samsung_clk_register_fixed_rate(ctx, exynos5440_fixed_rate_clks,
|
||||
ARRAY_SIZE(exynos5440_fixed_rate_clks));
|
||||
|
|
|
@ -890,22 +890,14 @@ static const struct clk_ops samsung_s3c2440_mpll_clk_ops = {
|
|||
#define PLL2550X_M_SHIFT (4)
|
||||
#define PLL2550X_S_SHIFT (0)
|
||||
|
||||
struct samsung_clk_pll2550x {
|
||||
struct clk_hw hw;
|
||||
const void __iomem *reg_base;
|
||||
unsigned long offset;
|
||||
};
|
||||
|
||||
#define to_clk_pll2550x(_hw) container_of(_hw, struct samsung_clk_pll2550x, hw)
|
||||
|
||||
static unsigned long samsung_pll2550x_recalc_rate(struct clk_hw *hw,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
struct samsung_clk_pll2550x *pll = to_clk_pll2550x(hw);
|
||||
struct samsung_clk_pll *pll = to_clk_pll(hw);
|
||||
u32 r, p, m, s, pll_stat;
|
||||
u64 fvco = parent_rate;
|
||||
|
||||
pll_stat = readl_relaxed(pll->reg_base + pll->offset * 3);
|
||||
pll_stat = readl_relaxed(pll->con_reg);
|
||||
r = (pll_stat >> PLL2550X_R_SHIFT) & PLL2550X_R_MASK;
|
||||
if (!r)
|
||||
return 0;
|
||||
|
@ -923,43 +915,6 @@ static const struct clk_ops samsung_pll2550x_clk_ops = {
|
|||
.recalc_rate = samsung_pll2550x_recalc_rate,
|
||||
};
|
||||
|
||||
struct clk * __init samsung_clk_register_pll2550x(const char *name,
|
||||
const char *pname, const void __iomem *reg_base,
|
||||
const unsigned long offset)
|
||||
{
|
||||
struct samsung_clk_pll2550x *pll;
|
||||
struct clk *clk;
|
||||
struct clk_init_data init;
|
||||
|
||||
pll = kzalloc(sizeof(*pll), GFP_KERNEL);
|
||||
if (!pll) {
|
||||
pr_err("%s: could not allocate pll clk %s\n", __func__, name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
init.name = name;
|
||||
init.ops = &samsung_pll2550x_clk_ops;
|
||||
init.flags = CLK_GET_RATE_NOCACHE;
|
||||
init.parent_names = &pname;
|
||||
init.num_parents = 1;
|
||||
|
||||
pll->hw.init = &init;
|
||||
pll->reg_base = reg_base;
|
||||
pll->offset = offset;
|
||||
|
||||
clk = clk_register(NULL, &pll->hw);
|
||||
if (IS_ERR(clk)) {
|
||||
pr_err("%s: failed to register pll clock %s\n", __func__,
|
||||
name);
|
||||
kfree(pll);
|
||||
}
|
||||
|
||||
if (clk_register_clkdev(clk, name, NULL))
|
||||
pr_err("%s: failed to register lookup for %s", __func__, name);
|
||||
|
||||
return clk;
|
||||
}
|
||||
|
||||
/*
|
||||
* PLL2550xx Clock Type
|
||||
*/
|
||||
|
@ -1062,6 +1017,102 @@ static const struct clk_ops samsung_pll2550xx_clk_min_ops = {
|
|||
.recalc_rate = samsung_pll2550xx_recalc_rate,
|
||||
};
|
||||
|
||||
/*
|
||||
* PLL2650x Clock Type
|
||||
*/
|
||||
|
||||
/* Maximum lock time can be 3000 * PDIV cycles */
|
||||
#define PLL2650X_LOCK_FACTOR 3000
|
||||
|
||||
#define PLL2650X_M_MASK 0x1ff
|
||||
#define PLL2650X_P_MASK 0x3f
|
||||
#define PLL2650X_S_MASK 0x7
|
||||
#define PLL2650X_K_MASK 0xffff
|
||||
#define PLL2650X_LOCK_STAT_MASK 0x1
|
||||
#define PLL2650X_M_SHIFT 16
|
||||
#define PLL2650X_P_SHIFT 8
|
||||
#define PLL2650X_S_SHIFT 0
|
||||
#define PLL2650X_K_SHIFT 0
|
||||
#define PLL2650X_LOCK_STAT_SHIFT 29
|
||||
#define PLL2650X_PLL_ENABLE_SHIFT 31
|
||||
|
||||
static unsigned long samsung_pll2650x_recalc_rate(struct clk_hw *hw,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
struct samsung_clk_pll *pll = to_clk_pll(hw);
|
||||
u64 fout = parent_rate;
|
||||
u32 mdiv, pdiv, sdiv, pll_con0, pll_con1;
|
||||
s16 kdiv;
|
||||
|
||||
pll_con0 = readl_relaxed(pll->con_reg);
|
||||
mdiv = (pll_con0 >> PLL2650X_M_SHIFT) & PLL2650X_M_MASK;
|
||||
pdiv = (pll_con0 >> PLL2650X_P_SHIFT) & PLL2650X_P_MASK;
|
||||
sdiv = (pll_con0 >> PLL2650X_S_SHIFT) & PLL2650X_S_MASK;
|
||||
|
||||
pll_con1 = readl_relaxed(pll->con_reg + 4);
|
||||
kdiv = (s16)((pll_con1 >> PLL2650X_K_SHIFT) & PLL2650X_K_MASK);
|
||||
|
||||
fout *= (mdiv << 16) + kdiv;
|
||||
do_div(fout, (pdiv << sdiv));
|
||||
fout >>= 16;
|
||||
|
||||
return (unsigned long)fout;
|
||||
}
|
||||
|
||||
static int samsung_pll2650x_set_rate(struct clk_hw *hw, unsigned long drate,
|
||||
unsigned long prate)
|
||||
{
|
||||
struct samsung_clk_pll *pll = to_clk_pll(hw);
|
||||
const struct samsung_pll_rate_table *rate;
|
||||
u32 con0, con1;
|
||||
|
||||
/* Get required rate settings from table */
|
||||
rate = samsung_get_pll_settings(pll, drate);
|
||||
if (!rate) {
|
||||
pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__,
|
||||
drate, clk_hw_get_name(hw));
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
con0 = readl_relaxed(pll->con_reg);
|
||||
con1 = readl_relaxed(pll->con_reg + 4);
|
||||
|
||||
/* Set PLL lock time. */
|
||||
writel_relaxed(rate->pdiv * PLL2650X_LOCK_FACTOR, pll->lock_reg);
|
||||
|
||||
/* Change PLL PMS values */
|
||||
con0 &= ~((PLL2650X_M_MASK << PLL2650X_M_SHIFT) |
|
||||
(PLL2650X_P_MASK << PLL2650X_P_SHIFT) |
|
||||
(PLL2650X_S_MASK << PLL2650X_S_SHIFT));
|
||||
con0 |= (rate->mdiv << PLL2650X_M_SHIFT) |
|
||||
(rate->pdiv << PLL2650X_P_SHIFT) |
|
||||
(rate->sdiv << PLL2650X_S_SHIFT);
|
||||
con0 |= (1 << PLL2650X_PLL_ENABLE_SHIFT);
|
||||
writel_relaxed(con0, pll->con_reg);
|
||||
|
||||
con1 &= ~(PLL2650X_K_MASK << PLL2650X_K_SHIFT);
|
||||
con1 |= ((rate->kdiv & PLL2650X_K_MASK) << PLL2650X_K_SHIFT);
|
||||
writel_relaxed(con1, pll->con_reg + 4);
|
||||
|
||||
do {
|
||||
cpu_relax();
|
||||
con0 = readl_relaxed(pll->con_reg);
|
||||
} while (!(con0 & (PLL2650X_LOCK_STAT_MASK
|
||||
<< PLL2650X_LOCK_STAT_SHIFT)));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct clk_ops samsung_pll2650x_clk_ops = {
|
||||
.recalc_rate = samsung_pll2650x_recalc_rate,
|
||||
.round_rate = samsung_pll_round_rate,
|
||||
.set_rate = samsung_pll2650x_set_rate,
|
||||
};
|
||||
|
||||
static const struct clk_ops samsung_pll2650x_clk_min_ops = {
|
||||
.recalc_rate = samsung_pll2650x_recalc_rate,
|
||||
};
|
||||
|
||||
/*
|
||||
* PLL2650XX Clock Type
|
||||
*/
|
||||
|
@ -1263,12 +1314,21 @@ static void __init _samsung_clk_register_pll(struct samsung_clk_provider *ctx,
|
|||
else
|
||||
init.ops = &samsung_s3c2440_mpll_clk_ops;
|
||||
break;
|
||||
case pll_2550x:
|
||||
init.ops = &samsung_pll2550x_clk_ops;
|
||||
break;
|
||||
case pll_2550xx:
|
||||
if (!pll->rate_table)
|
||||
init.ops = &samsung_pll2550xx_clk_min_ops;
|
||||
else
|
||||
init.ops = &samsung_pll2550xx_clk_ops;
|
||||
break;
|
||||
case pll_2650x:
|
||||
if (!pll->rate_table)
|
||||
init.ops = &samsung_pll2650x_clk_min_ops;
|
||||
else
|
||||
init.ops = &samsung_pll2650x_clk_ops;
|
||||
break;
|
||||
case pll_2650xx:
|
||||
if (!pll->rate_table)
|
||||
init.ops = &samsung_pll2650xx_clk_min_ops;
|
||||
|
|
|
@ -31,7 +31,9 @@ enum samsung_pll_type {
|
|||
pll_s3c2410_mpll,
|
||||
pll_s3c2410_upll,
|
||||
pll_s3c2440_mpll,
|
||||
pll_2550x,
|
||||
pll_2550xx,
|
||||
pll_2650x,
|
||||
pll_2650xx,
|
||||
pll_1450x,
|
||||
pll_1451x,
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#define CLK_FOUT_MPLL 4
|
||||
#define CLK_FOUT_BPLL 5
|
||||
#define CLK_FOUT_KPLL 6
|
||||
#define CLK_FOUT_EPLL 7
|
||||
|
||||
/* gate for special clocks (sclk) */
|
||||
#define CLK_SCLK_UART0 128
|
||||
|
@ -55,6 +56,8 @@
|
|||
#define CLK_MMC0 351
|
||||
#define CLK_MMC1 352
|
||||
#define CLK_MMC2 353
|
||||
#define CLK_PDMA0 362
|
||||
#define CLK_PDMA1 363
|
||||
#define CLK_USBH20 365
|
||||
#define CLK_USBD300 366
|
||||
#define CLK_USBD301 367
|
||||
|
|
|
@ -214,6 +214,9 @@
|
|||
#define CLK_MOUT_SW_ACLK400 651
|
||||
#define CLK_MOUT_USER_ACLK300_GSCL 652
|
||||
#define CLK_MOUT_SW_ACLK300_GSCL 653
|
||||
#define CLK_MOUT_MCLK_CDREX 654
|
||||
#define CLK_MOUT_BPLL 655
|
||||
#define CLK_MOUT_MX_MSPLL_CCORE 656
|
||||
|
||||
/* divider clocks */
|
||||
#define CLK_DOUT_PIXEL 768
|
||||
|
@ -239,8 +242,14 @@
|
|||
#define CLK_DOUT_ACLK300_DISP1 788
|
||||
#define CLK_DOUT_ACLK300_GSCL 789
|
||||
#define CLK_DOUT_ACLK400_DISP1 790
|
||||
#define CLK_DOUT_PCLK_CDREX 791
|
||||
#define CLK_DOUT_SCLK_CDREX 792
|
||||
#define CLK_DOUT_ACLK_CDREX1 793
|
||||
#define CLK_DOUT_CCLK_DREX0 794
|
||||
#define CLK_DOUT_CLK2X_PHY0 795
|
||||
#define CLK_DOUT_PCLK_CORE_MEM 796
|
||||
|
||||
/* must be greater than maximal clock id */
|
||||
#define CLK_NR_CLKS 791
|
||||
#define CLK_NR_CLKS 797
|
||||
|
||||
#endif /* _DT_BINDINGS_CLOCK_EXYNOS_5420_H */
|
||||
|
|
|
@ -14,6 +14,8 @@
|
|||
|
||||
#define CLK_XTAL 1
|
||||
#define CLK_ARM_CLK 2
|
||||
#define CLK_CPLLA 3
|
||||
#define CLK_CPLLB 4
|
||||
#define CLK_SPI_BAUD 16
|
||||
#define CLK_PB0_250 17
|
||||
#define CLK_PR0_250 18
|
||||
|
|
Loading…
Reference in New Issue