Signed-off-by: Tom Rini <trini@konsulko.com> Conflicts: configs/peach-pi_defconfig configs/peach-pit_defconfig
This commit is contained in:
@@ -21,5 +21,6 @@ config SPL_CLK
|
||||
used as U-Boot proper.
|
||||
|
||||
source "drivers/clk/uniphier/Kconfig"
|
||||
source "drivers/clk/exynos/Kconfig"
|
||||
|
||||
endmenu
|
||||
|
||||
@@ -11,3 +11,4 @@ obj-$(CONFIG_ROCKCHIP_RK3288) += clk_rk3288.o
|
||||
obj-$(CONFIG_SANDBOX) += clk_sandbox.o
|
||||
obj-$(CONFIG_MACH_PIC32) += clk_pic32.o
|
||||
obj-$(CONFIG_CLK_UNIPHIER) += uniphier/
|
||||
obj-$(CONFIG_CLK_EXYNOS) += exynos/
|
||||
|
||||
18
drivers/clk/exynos/Kconfig
Normal file
18
drivers/clk/exynos/Kconfig
Normal file
@@ -0,0 +1,18 @@
|
||||
config CLK_EXYNOS
|
||||
bool
|
||||
select CLK
|
||||
help
|
||||
This enables support for common clock driver API on Samsung
|
||||
Exynos SoCs.
|
||||
|
||||
menu "Clock drivers for Exynos SoCs"
|
||||
depends on CLK_EXYNOS
|
||||
|
||||
config CLK_EXYNOS7420
|
||||
bool "Clock driver for Samsung's Exynos7420 SoC"
|
||||
default y
|
||||
help
|
||||
This enables common clock driver support for platforms based
|
||||
on Samsung Exynos7420 SoC.
|
||||
|
||||
endmenu
|
||||
9
drivers/clk/exynos/Makefile
Normal file
9
drivers/clk/exynos/Makefile
Normal file
@@ -0,0 +1,9 @@
|
||||
#
|
||||
# Copyright (C) 2016 Samsung Electronics
|
||||
# Thomas Abraham <thomas.ab@samsung.com>
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-2.0+
|
||||
#
|
||||
|
||||
obj-y += clk-pll.o
|
||||
obj-$(CONFIG_CLK_EXYNOS7420) += clk-exynos7420.o
|
||||
236
drivers/clk/exynos/clk-exynos7420.c
Normal file
236
drivers/clk/exynos/clk-exynos7420.c
Normal file
@@ -0,0 +1,236 @@
|
||||
/*
|
||||
* Samsung Exynos7420 clock driver.
|
||||
* Copyright (C) 2016 Samsung Electronics
|
||||
* Thomas Abraham <thomas.ab@samsung.com>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <errno.h>
|
||||
#include <clk.h>
|
||||
#include <asm/io.h>
|
||||
#include <dt-bindings/clock/exynos7420-clk.h>
|
||||
#include "clk-pll.h"
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
#define DIVIDER(reg, shift, mask) \
|
||||
(((readl(reg) >> shift) & mask) + 1)
|
||||
|
||||
/* CMU TOPC block device structure */
|
||||
struct exynos7420_clk_cmu_topc {
|
||||
unsigned int rsvd1[68];
|
||||
unsigned int bus0_pll_con[2];
|
||||
unsigned int rsvd2[2];
|
||||
unsigned int bus1_pll_con[2];
|
||||
unsigned int rsvd3[54];
|
||||
unsigned int mux_sel[6];
|
||||
unsigned int rsvd4[250];
|
||||
unsigned int div[4];
|
||||
};
|
||||
|
||||
/* CMU TOP0 block device structure */
|
||||
struct exynos7420_clk_cmu_top0 {
|
||||
unsigned int rsvd0[128];
|
||||
unsigned int mux_sel[7];
|
||||
unsigned int rsvd1[261];
|
||||
unsigned int div_peric[5];
|
||||
};
|
||||
|
||||
/**
|
||||
* struct exynos7420_clk_topc_priv - private data for CMU topc clock driver.
|
||||
*
|
||||
* @topc: base address of the memory mapped CMU TOPC controller.
|
||||
* @fin_freq: frequency of the Oscillator clock.
|
||||
* @sclk_bus0_pll_a: frequency of sclk_bus0_pll_a clock.
|
||||
* @sclk_bus1_pll_a: frequency of sclk_bus1_pll_a clock.
|
||||
*/
|
||||
struct exynos7420_clk_topc_priv {
|
||||
struct exynos7420_clk_cmu_topc *topc;
|
||||
unsigned long fin_freq;
|
||||
unsigned long sclk_bus0_pll_a;
|
||||
unsigned long sclk_bus1_pll_a;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct exynos7420_clk_top0_priv - private data for CMU top0 clock driver.
|
||||
*
|
||||
* @top0: base address of the memory mapped CMU TOP0 controller.
|
||||
* @mout_top0_bus0_pll_half: frequency of mout_top0_bus0_pll_half clock
|
||||
* @sclk_uart2: frequency of sclk_uart2 clock.
|
||||
*/
|
||||
struct exynos7420_clk_top0_priv {
|
||||
struct exynos7420_clk_cmu_top0 *top0;
|
||||
unsigned long mout_top0_bus0_pll_half;
|
||||
unsigned long sclk_uart2;
|
||||
};
|
||||
|
||||
static ulong exynos7420_topc_get_periph_rate(struct udevice *dev, int periph)
|
||||
{
|
||||
struct exynos7420_clk_topc_priv *priv = dev_get_priv(dev);
|
||||
|
||||
switch (periph) {
|
||||
case DOUT_SCLK_BUS0_PLL:
|
||||
case SCLK_BUS0_PLL_A:
|
||||
case SCLK_BUS0_PLL_B:
|
||||
return priv->sclk_bus0_pll_a;
|
||||
case DOUT_SCLK_BUS1_PLL:
|
||||
case SCLK_BUS1_PLL_A:
|
||||
case SCLK_BUS1_PLL_B:
|
||||
return priv->sclk_bus1_pll_a;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static struct clk_ops exynos7420_clk_topc_ops = {
|
||||
.get_periph_rate = exynos7420_topc_get_periph_rate,
|
||||
};
|
||||
|
||||
static int exynos7420_clk_topc_probe(struct udevice *dev)
|
||||
{
|
||||
struct exynos7420_clk_topc_priv *priv = dev_get_priv(dev);
|
||||
struct exynos7420_clk_cmu_topc *topc;
|
||||
struct udevice *clk_dev;
|
||||
unsigned long rate;
|
||||
fdt_addr_t base;
|
||||
int ret;
|
||||
|
||||
base = dev_get_addr(dev);
|
||||
if (base == FDT_ADDR_T_NONE)
|
||||
return -EINVAL;
|
||||
|
||||
topc = (struct exynos7420_clk_cmu_topc *)base;
|
||||
priv->topc = topc;
|
||||
|
||||
ret = clk_get_by_index(dev, 0, &clk_dev);
|
||||
if (ret >= 0)
|
||||
priv->fin_freq = clk_get_rate(clk_dev);
|
||||
|
||||
rate = pll145x_get_rate(&topc->bus0_pll_con[0], priv->fin_freq);
|
||||
if (readl(&topc->mux_sel[1]) & (1 << 16))
|
||||
rate >>= 1;
|
||||
rate /= DIVIDER(&topc->div[3], 0, 0xf);
|
||||
priv->sclk_bus0_pll_a = rate;
|
||||
|
||||
rate = pll145x_get_rate(&topc->bus1_pll_con[0], priv->fin_freq) /
|
||||
DIVIDER(&topc->div[3], 8, 0xf);
|
||||
priv->sclk_bus1_pll_a = rate;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ulong exynos7420_top0_get_periph_rate(struct udevice *dev, int periph)
|
||||
{
|
||||
struct exynos7420_clk_top0_priv *priv = dev_get_priv(dev);
|
||||
struct exynos7420_clk_cmu_top0 *top0 = priv->top0;
|
||||
|
||||
switch (periph) {
|
||||
case CLK_SCLK_UART2:
|
||||
return priv->mout_top0_bus0_pll_half /
|
||||
DIVIDER(&top0->div_peric[3], 8, 0xf);
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static struct clk_ops exynos7420_clk_top0_ops = {
|
||||
.get_periph_rate = exynos7420_top0_get_periph_rate,
|
||||
};
|
||||
|
||||
static int exynos7420_clk_top0_probe(struct udevice *dev)
|
||||
{
|
||||
struct exynos7420_clk_top0_priv *priv;
|
||||
struct exynos7420_clk_cmu_top0 *top0;
|
||||
struct udevice *clk_dev;
|
||||
fdt_addr_t base;
|
||||
int ret;
|
||||
|
||||
priv = dev_get_priv(dev);
|
||||
if (!priv)
|
||||
return -EINVAL;
|
||||
|
||||
base = dev_get_addr(dev);
|
||||
if (base == FDT_ADDR_T_NONE)
|
||||
return -EINVAL;
|
||||
|
||||
top0 = (struct exynos7420_clk_cmu_top0 *)base;
|
||||
priv->top0 = top0;
|
||||
|
||||
ret = clk_get_by_index(dev, 1, &clk_dev);
|
||||
if (ret >= 0) {
|
||||
priv->mout_top0_bus0_pll_half =
|
||||
clk_get_periph_rate(clk_dev, ret);
|
||||
if (readl(&top0->mux_sel[1]) & (1 << 16))
|
||||
priv->mout_top0_bus0_pll_half >>= 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ulong exynos7420_peric1_get_periph_rate(struct udevice *dev, int periph)
|
||||
{
|
||||
struct udevice *clk_dev;
|
||||
unsigned int ret;
|
||||
unsigned long freq = 0;
|
||||
|
||||
switch (periph) {
|
||||
case SCLK_UART2:
|
||||
ret = clk_get_by_index(dev, 3, &clk_dev);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
freq = clk_get_periph_rate(clk_dev, ret);
|
||||
break;
|
||||
}
|
||||
|
||||
return freq;
|
||||
}
|
||||
|
||||
static struct clk_ops exynos7420_clk_peric1_ops = {
|
||||
.get_periph_rate = exynos7420_peric1_get_periph_rate,
|
||||
};
|
||||
|
||||
static const struct udevice_id exynos7420_clk_topc_compat[] = {
|
||||
{ .compatible = "samsung,exynos7-clock-topc" },
|
||||
{ }
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(exynos7420_clk_topc) = {
|
||||
.name = "exynos7420-clock-topc",
|
||||
.id = UCLASS_CLK,
|
||||
.of_match = exynos7420_clk_topc_compat,
|
||||
.probe = exynos7420_clk_topc_probe,
|
||||
.priv_auto_alloc_size = sizeof(struct exynos7420_clk_topc_priv),
|
||||
.ops = &exynos7420_clk_topc_ops,
|
||||
.flags = DM_FLAG_PRE_RELOC,
|
||||
};
|
||||
|
||||
static const struct udevice_id exynos7420_clk_top0_compat[] = {
|
||||
{ .compatible = "samsung,exynos7-clock-top0" },
|
||||
{ }
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(exynos7420_clk_top0) = {
|
||||
.name = "exynos7420-clock-top0",
|
||||
.id = UCLASS_CLK,
|
||||
.of_match = exynos7420_clk_top0_compat,
|
||||
.probe = exynos7420_clk_top0_probe,
|
||||
.priv_auto_alloc_size = sizeof(struct exynos7420_clk_top0_priv),
|
||||
.ops = &exynos7420_clk_top0_ops,
|
||||
.flags = DM_FLAG_PRE_RELOC,
|
||||
};
|
||||
|
||||
static const struct udevice_id exynos7420_clk_peric1_compat[] = {
|
||||
{ .compatible = "samsung,exynos7-clock-peric1" },
|
||||
{ }
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(exynos7420_clk_peric1) = {
|
||||
.name = "exynos7420-clock-peric1",
|
||||
.id = UCLASS_CLK,
|
||||
.of_match = exynos7420_clk_peric1_compat,
|
||||
.ops = &exynos7420_clk_peric1_ops,
|
||||
.flags = DM_FLAG_PRE_RELOC,
|
||||
};
|
||||
33
drivers/clk/exynos/clk-pll.c
Normal file
33
drivers/clk/exynos/clk-pll.c
Normal file
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Exynos PLL helper functions for clock drivers.
|
||||
* Copyright (C) 2016 Samsung Electronics
|
||||
* Thomas Abraham <thomas.ab@samsung.com>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <asm/io.h>
|
||||
#include <div64.h>
|
||||
|
||||
#define PLL145X_MDIV_SHIFT 16
|
||||
#define PLL145X_MDIV_MASK 0x3ff
|
||||
#define PLL145X_PDIV_SHIFT 8
|
||||
#define PLL145X_PDIV_MASK 0x3f
|
||||
#define PLL145X_SDIV_SHIFT 0
|
||||
#define PLL145X_SDIV_MASK 0x7
|
||||
|
||||
unsigned long pll145x_get_rate(unsigned int *con1, unsigned long fin_freq)
|
||||
{
|
||||
unsigned long pll_con1 = readl(con1);
|
||||
unsigned long mdiv, sdiv, pdiv;
|
||||
uint64_t fvco = fin_freq;
|
||||
|
||||
mdiv = (pll_con1 >> PLL145X_MDIV_SHIFT) & PLL145X_MDIV_MASK;
|
||||
pdiv = (pll_con1 >> PLL145X_PDIV_SHIFT) & PLL145X_PDIV_MASK;
|
||||
sdiv = (pll_con1 >> PLL145X_SDIV_SHIFT) & PLL145X_SDIV_MASK;
|
||||
|
||||
fvco *= mdiv;
|
||||
do_div(fvco, (pdiv << sdiv));
|
||||
return (unsigned long)fvco;
|
||||
}
|
||||
9
drivers/clk/exynos/clk-pll.h
Normal file
9
drivers/clk/exynos/clk-pll.h
Normal file
@@ -0,0 +1,9 @@
|
||||
/*
|
||||
* Exynos PLL helper functions for clock drivers.
|
||||
* Copyright (C) 2016 Samsung Electronics
|
||||
* Thomas Abraham <thomas.ab@samsung.com>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
unsigned long pll145x_get_rate(unsigned int *con1, unsigned long fin_freq);
|
||||
Reference in New Issue
Block a user