aboutsummaryrefslogtreecommitdiff
path: root/drivers/clk
diff options
context:
space:
mode:
authorTom Rini <trini@konsulko.com>2021-04-05 11:29:57 -0400
committerTom Rini <trini@konsulko.com>2021-04-05 11:29:57 -0400
commit90eba245a66aa20589404ba537215faf2012c1a3 (patch)
treec581cd1f00dd162aeac4262bb4e74c2a9fea98c9 /drivers/clk
parentb46dd116ce03e235f2a7d4843c6278e1da44b5e1 (diff)
parentdb8b46120aed6554d1ff405260ea6d2cc2439fcc (diff)
downloadu-boot-90eba245a66aa20589404ba537215faf2012c1a3.zip
u-boot-90eba245a66aa20589404ba537215faf2012c1a3.tar.gz
u-boot-90eba245a66aa20589404ba537215faf2012c1a3.tar.bz2
Merge branch 'next'
Diffstat (limited to 'drivers/clk')
-rw-r--r--drivers/clk/clk-uclass.c2
-rw-r--r--drivers/clk/clk_fixed_rate.c14
-rw-r--r--drivers/clk/clk_sandbox.c40
-rw-r--r--drivers/clk/clk_sandbox_test.c6
-rw-r--r--drivers/clk/clk_zynqmp.c251
5 files changed, 214 insertions, 99 deletions
diff --git a/drivers/clk/clk-uclass.c b/drivers/clk/clk-uclass.c
index b87288d..4ab3c40 100644
--- a/drivers/clk/clk-uclass.c
+++ b/drivers/clk/clk-uclass.c
@@ -39,7 +39,7 @@ int clk_get_by_driver_info(struct udevice *dev, struct phandle_1_arg *cells,
{
int ret;
- ret = device_get_by_driver_info_idx(cells->idx, &clk->dev);
+ ret = device_get_by_ofplat_idx(cells->idx, &clk->dev);
if (ret)
return ret;
clk->id = cells->arg[0];
diff --git a/drivers/clk/clk_fixed_rate.c b/drivers/clk/clk_fixed_rate.c
index 3c5a83c..09f9ef2 100644
--- a/drivers/clk/clk_fixed_rate.c
+++ b/drivers/clk/clk_fixed_rate.c
@@ -25,18 +25,24 @@ const struct clk_ops clk_fixed_rate_ops = {
.enable = dummy_enable,
};
-static int clk_fixed_rate_of_to_plat(struct udevice *dev)
+void clk_fixed_rate_ofdata_to_plat_(struct udevice *dev,
+ struct clk_fixed_rate *plat)
{
- struct clk *clk = &to_clk_fixed_rate(dev)->clk;
+ struct clk *clk = &plat->clk;
#if !CONFIG_IS_ENABLED(OF_PLATDATA)
- to_clk_fixed_rate(dev)->fixed_rate =
- dev_read_u32_default(dev, "clock-frequency", 0);
+ plat->fixed_rate = dev_read_u32_default(dev, "clock-frequency", 0);
#endif
/* Make fixed rate clock accessible from higher level struct clk */
/* FIXME: This is not allowed */
dev_set_uclass_priv(dev, clk);
+
clk->dev = dev;
clk->enable_count = 0;
+}
+
+static int clk_fixed_rate_of_to_plat(struct udevice *dev)
+{
+ clk_fixed_rate_ofdata_to_plat_(dev, to_clk_fixed_rate(dev));
return 0;
}
diff --git a/drivers/clk/clk_sandbox.c b/drivers/clk/clk_sandbox.c
index b28b67b..57acf7d 100644
--- a/drivers/clk/clk_sandbox.c
+++ b/drivers/clk/clk_sandbox.c
@@ -9,13 +9,7 @@
#include <errno.h>
#include <malloc.h>
#include <asm/clk.h>
-
-struct sandbox_clk_priv {
- bool probed;
- ulong rate[SANDBOX_CLK_ID_COUNT];
- bool enabled[SANDBOX_CLK_ID_COUNT];
- bool requested[SANDBOX_CLK_ID_COUNT];
-};
+#include <linux/clk-provider.h>
static ulong sandbox_clk_get_rate(struct clk *clk)
{
@@ -178,3 +172,35 @@ int sandbox_clk_query_requested(struct udevice *dev, int id)
return -EINVAL;
return priv->requested[id];
}
+
+int clk_fixed_rate_of_to_plat(struct udevice *dev)
+{
+ struct clk_fixed_rate *cplat;
+
+#if CONFIG_IS_ENABLED(OF_PLATDATA)
+ struct sandbox_clk_fixed_rate_plat *plat = dev_get_plat(dev);
+
+ cplat = &plat->fixed;
+ cplat->fixed_rate = plat->dtplat.clock_frequency;
+#else
+ cplat = to_clk_fixed_rate(dev);
+#endif
+ clk_fixed_rate_ofdata_to_plat_(dev, cplat);
+
+ return 0;
+}
+
+static const struct udevice_id sandbox_clk_fixed_rate_match[] = {
+ { .compatible = "sandbox,fixed-clock" },
+ { /* sentinel */ }
+};
+
+U_BOOT_DRIVER(sandbox_fixed_clock) = {
+ .name = "sandbox_fixed_clock",
+ .id = UCLASS_CLK,
+ .of_match = sandbox_clk_fixed_rate_match,
+ .of_to_plat = clk_fixed_rate_of_to_plat,
+ .plat_auto = sizeof(struct sandbox_clk_fixed_rate_plat),
+ .ops = &clk_fixed_rate_ops,
+ .flags = DM_FLAG_PRE_RELOC,
+};
diff --git a/drivers/clk/clk_sandbox_test.c b/drivers/clk/clk_sandbox_test.c
index c4e4481..f665fd3 100644
--- a/drivers/clk/clk_sandbox_test.c
+++ b/drivers/clk/clk_sandbox_test.c
@@ -11,12 +11,6 @@
#include <dm/device_compat.h>
#include <linux/err.h>
-struct sandbox_clk_test {
- struct clk clks[SANDBOX_CLK_TEST_NON_DEVM_COUNT];
- struct clk *clkps[SANDBOX_CLK_TEST_ID_COUNT];
- struct clk_bulk bulk;
-};
-
static const char * const sandbox_clk_test_names[] = {
[SANDBOX_CLK_TEST_ID_FIXED] = "fixed",
[SANDBOX_CLK_TEST_ID_SPI] = "spi",
diff --git a/drivers/clk/clk_zynqmp.c b/drivers/clk/clk_zynqmp.c
index 609d8e3..13a623f 100644
--- a/drivers/clk/clk_zynqmp.c
+++ b/drivers/clk/clk_zynqmp.c
@@ -97,8 +97,7 @@ static const resource_size_t zynqmp_crl_apb_clkc_base = 0xff5e0020;
#define CLK_CTRL_DIV1_MASK (ZYNQ_CLK_MAXDIV << CLK_CTRL_DIV1_SHIFT)
#define CLK_CTRL_DIV0_SHIFT 8
#define CLK_CTRL_DIV0_MASK (ZYNQ_CLK_MAXDIV << CLK_CTRL_DIV0_SHIFT)
-#define CLK_CTRL_SRCSEL_SHIFT 0
-#define CLK_CTRL_SRCSEL_MASK (0x3 << CLK_CTRL_SRCSEL_SHIFT)
+#define CLK_CTRL_SRCSEL_MASK 0x7
#define PLLCTRL_FBDIV_MASK 0x7f00
#define PLLCTRL_FBDIV_SHIFT 8
#define PLLCTRL_RESET_MASK 1
@@ -132,7 +131,7 @@ enum zynqmp_clk {
iou_switch,
gem_tsu_ref, gem_tsu,
gem0_ref, gem1_ref, gem2_ref, gem3_ref,
- gem0_rx, gem1_rx, gem2_rx, gem3_rx,
+ gem0_tx, gem1_tx, gem2_tx, gem3_tx,
qspi_ref,
sdio0_ref, sdio1_ref,
uart0_ref, uart1_ref,
@@ -152,7 +151,7 @@ static const char * const clk_names[clk_max] = {
"iopll", "rpll", "apll", "dpll",
"vpll", "iopll_to_fpd", "rpll_to_fpd",
"apll_to_lpd", "dpll_to_lpd", "vpll_to_lpd",
- "acpu", "acpu_half", "dbf_fpd", "dbf_lpd",
+ "acpu", "acpu_half", "dbg_fpd", "dbg_lpd",
"dbg_trace", "dbg_tstmp", "dp_video_ref",
"dp_audio_ref", "dp_stc_ref", "gdma_ref",
"dpdma_ref", "ddr_ref", "sata_ref", "pcie_ref",
@@ -172,6 +171,38 @@ static const char * const clk_names[clk_max] = {
"ams_ref", "pl0", "pl1", "pl2", "pl3", "wdt"
};
+static const u32 pll_src[][4] = {
+ {apll, 0xff, dpll, vpll}, /* acpu */
+ {dpll, vpll, 0xff, 0xff}, /* ddr_ref */
+ {rpll, iopll, 0xff, 0xff}, /* dll_ref */
+ {iopll, 0xff, rpll, dpll_to_lpd}, /* gem_tsu_ref */
+ {iopll, 0xff, rpll, dpll}, /* peripheral */
+ {apll, 0xff, iopll_to_fpd, dpll}, /* wdt */
+ {iopll_to_fpd, 0xff, dpll, apll}, /* dbg_fpd */
+ {iopll, 0xff, rpll, dpll_to_lpd}, /* timestamp_ref */
+ {iopll_to_fpd, 0xff, apll, dpll}, /* sata_ref */
+ {iopll_to_fpd, 0xff, rpll_to_fpd, dpll},/* pcie_ref */
+ {iopll_to_fpd, 0xff, vpll, dpll}, /* gpu_ref */
+ {apll, 0xff, vpll, dpll}, /* topsw_main_ref */
+ {rpll, 0xff, iopll, dpll_to_lpd}, /* cpu_r5_ref */
+};
+
+enum zynqmp_clk_pll_src {
+ ACPU_CLK_SRC = 0,
+ DDR_CLK_SRC,
+ DLL_CLK_SRC,
+ GEM_TSU_CLK_SRC,
+ PERI_CLK_SRC,
+ WDT_CLK_SRC,
+ DBG_FPD_CLK_SRC,
+ TIMESTAMP_CLK_SRC,
+ SATA_CLK_SRC,
+ PCIE_CLK_SRC,
+ GPU_CLK_SRC,
+ TOPSW_MAIN_CLK_SRC,
+ CPU_R5_CLK_SRC
+};
+
struct zynqmp_clk_priv {
unsigned long ps_clk_freq;
unsigned long video_clk;
@@ -195,12 +226,38 @@ static u32 zynqmp_clk_get_register(enum zynqmp_clk id)
return CRF_APB_VPLL_CTRL;
case acpu:
return CRF_APB_ACPU_CTRL;
+ case dbg_fpd:
+ return CRF_APB_DBG_FPD_CTRL;
+ case dbg_trace:
+ return CRF_APB_DBG_TRACE_CTRL;
+ case dbg_tstmp:
+ return CRF_APB_DBG_TSTMP_CTRL;
+ case gpu_ref ... gpu_pp1_ref:
+ return CRF_APB_GPU_REF_CTRL;
case ddr_ref:
return CRF_APB_DDR_CTRL;
+ case sata_ref:
+ return CRF_APB_SATA_REF_CTRL;
+ case pcie_ref:
+ return CRF_APB_PCIE_REF_CTRL;
+ case gdma_ref:
+ return CRF_APB_GDMA_REF_CTRL;
+ case dpdma_ref:
+ return CRF_APB_DPDMA_REF_CTRL;
+ case topsw_main:
+ return CRF_APB_TOPSW_MAIN_CTRL;
+ case topsw_lsbus:
+ return CRF_APB_TOPSW_LSBUS_CTRL;
+ case lpd_switch:
+ return CRL_APB_LPD_SWITCH_CTRL;
+ case lpd_lsbus:
+ return CRL_APB_LPD_LSBUS_CTRL;
case qspi_ref:
return CRL_APB_QSPI_REF_CTRL;
case usb3_dual_ref:
return CRL_APB_USB3_DUAL_REF_CTRL;
+ case gem_tsu_ref:
+ return CRL_APB_GEM_TSU_REF_CTRL;
case gem0_ref:
return CRL_APB_GEM0_REF_CTRL;
case gem1_ref:
@@ -213,6 +270,8 @@ static u32 zynqmp_clk_get_register(enum zynqmp_clk id)
return CRL_APB_USB0_BUS_REF_CTRL;
case usb1_bus_ref:
return CRL_APB_USB1_BUS_REF_CTRL;
+ case cpu_r5:
+ return CRL_APB_CPU_R5_CTRL;
case uart0_ref:
return CRL_APB_UART0_REF_CTRL;
case uart1_ref:
@@ -235,6 +294,14 @@ static u32 zynqmp_clk_get_register(enum zynqmp_clk id)
return CRL_APB_CAN0_REF_CTRL;
case can1_ref:
return CRL_APB_CAN1_REF_CTRL;
+ case dll_ref:
+ return CRL_APB_DLL_REF_CTRL;
+ case adma_ref:
+ return CRL_APB_ADMA_REF_CTRL;
+ case timestamp_ref:
+ return CRL_APB_TIMESTAMP_REF_CTRL;
+ case ams_ref:
+ return CRL_APB_AMS_REF_CTRL;
case pl0:
return CRL_APB_PL0_REF_CTRL;
case pl1:
@@ -253,68 +320,6 @@ static u32 zynqmp_clk_get_register(enum zynqmp_clk id)
return 0;
}
-static enum zynqmp_clk zynqmp_clk_get_cpu_pll(u32 clk_ctrl)
-{
- u32 srcsel = (clk_ctrl & CLK_CTRL_SRCSEL_MASK) >>
- CLK_CTRL_SRCSEL_SHIFT;
-
- switch (srcsel) {
- case 2:
- return dpll;
- case 3:
- return vpll;
- case 0 ... 1:
- default:
- return apll;
- }
-}
-
-static enum zynqmp_clk zynqmp_clk_get_ddr_pll(u32 clk_ctrl)
-{
- u32 srcsel = (clk_ctrl & CLK_CTRL_SRCSEL_MASK) >>
- CLK_CTRL_SRCSEL_SHIFT;
-
- switch (srcsel) {
- case 1:
- return vpll;
- case 0:
- default:
- return dpll;
- }
-}
-
-static enum zynqmp_clk zynqmp_clk_get_peripheral_pll(u32 clk_ctrl)
-{
- u32 srcsel = (clk_ctrl & CLK_CTRL_SRCSEL_MASK) >>
- CLK_CTRL_SRCSEL_SHIFT;
-
- switch (srcsel) {
- case 2:
- return rpll;
- case 3:
- return dpll;
- case 0 ... 1:
- default:
- return iopll;
- }
-}
-
-static enum zynqmp_clk zynqmp_clk_get_wdt_pll(u32 clk_ctrl)
-{
- u32 srcsel = (clk_ctrl & CLK_CTRL_SRCSEL_MASK) >>
- CLK_CTRL_SRCSEL_SHIFT;
-
- switch (srcsel) {
- case 2:
- return iopll_to_fpd;
- case 3:
- return dpll;
- case 0 ... 1:
- default:
- return apll;
- }
-}
-
static ulong zynqmp_clk_get_pll_src(ulong clk_ctrl,
struct zynqmp_clk_priv *priv,
bool is_pre_src)
@@ -378,7 +383,7 @@ static ulong zynqmp_clk_get_pll_rate(struct zynqmp_clk_priv *priv,
static ulong zynqmp_clk_get_cpu_rate(struct zynqmp_clk_priv *priv,
enum zynqmp_clk id)
{
- u32 clk_ctrl, div;
+ u32 clk_ctrl, div, srcsel;
enum zynqmp_clk pll;
int ret;
unsigned long pllrate;
@@ -391,7 +396,8 @@ static ulong zynqmp_clk_get_cpu_rate(struct zynqmp_clk_priv *priv,
div = (clk_ctrl & CLK_CTRL_DIV0_MASK) >> CLK_CTRL_DIV0_SHIFT;
- pll = zynqmp_clk_get_cpu_pll(clk_ctrl);
+ srcsel = clk_ctrl & CLK_CTRL_SRCSEL_MASK;
+ pll = pll_src[ACPU_CLK_SRC][srcsel];
pllrate = zynqmp_clk_get_pll_rate(priv, pll);
if (IS_ERR_VALUE(pllrate))
return pllrate;
@@ -401,7 +407,7 @@ static ulong zynqmp_clk_get_cpu_rate(struct zynqmp_clk_priv *priv,
static ulong zynqmp_clk_get_ddr_rate(struct zynqmp_clk_priv *priv)
{
- u32 clk_ctrl, div;
+ u32 clk_ctrl, div, srcsel;
enum zynqmp_clk pll;
int ret;
ulong pllrate;
@@ -414,7 +420,8 @@ static ulong zynqmp_clk_get_ddr_rate(struct zynqmp_clk_priv *priv)
div = (clk_ctrl & CLK_CTRL_DIV0_MASK) >> CLK_CTRL_DIV0_SHIFT;
- pll = zynqmp_clk_get_ddr_pll(clk_ctrl);
+ srcsel = clk_ctrl & CLK_CTRL_SRCSEL_MASK;
+ pll = pll_src[DDR_CLK_SRC][srcsel];
pllrate = zynqmp_clk_get_pll_rate(priv, pll);
if (IS_ERR_VALUE(pllrate))
return pllrate;
@@ -422,11 +429,33 @@ static ulong zynqmp_clk_get_ddr_rate(struct zynqmp_clk_priv *priv)
return DIV_ROUND_CLOSEST(pllrate, div);
}
+static ulong zynqmp_clk_get_dll_rate(struct zynqmp_clk_priv *priv)
+{
+ u32 clk_ctrl, srcsel;
+ enum zynqmp_clk pll;
+ ulong pllrate;
+ int ret;
+
+ ret = zynqmp_mmio_read(CRL_APB_DLL_REF_CTRL, &clk_ctrl);
+ if (ret) {
+ printf("%s mio read fail\n", __func__);
+ return -EIO;
+ }
+
+ srcsel = clk_ctrl & CLK_CTRL_SRCSEL_MASK;
+ pll = pll_src[DLL_CLK_SRC][srcsel];
+ pllrate = zynqmp_clk_get_pll_rate(priv, pll);
+ if (IS_ERR_VALUE(pllrate))
+ return pllrate;
+
+ return pllrate;
+}
+
static ulong zynqmp_clk_get_peripheral_rate(struct zynqmp_clk_priv *priv,
- enum zynqmp_clk id, bool two_divs)
+ enum zynqmp_clk id, bool two_divs)
{
enum zynqmp_clk pll;
- u32 clk_ctrl, div0;
+ u32 clk_ctrl, div0, srcsel;
u32 div1 = 1;
int ret;
ulong pllrate;
@@ -446,8 +475,13 @@ static ulong zynqmp_clk_get_peripheral_rate(struct zynqmp_clk_priv *priv,
if (!div1)
div1 = 1;
}
+ srcsel = clk_ctrl & CLK_CTRL_SRCSEL_MASK;
+
+ if (id == gem_tsu_ref)
+ pll = pll_src[GEM_TSU_CLK_SRC][srcsel];
+ else
+ pll = pll_src[PERI_CLK_SRC][srcsel];
- pll = zynqmp_clk_get_peripheral_pll(clk_ctrl);
pllrate = zynqmp_clk_get_pll_rate(priv, pll);
if (IS_ERR_VALUE(pllrate))
return pllrate;
@@ -457,11 +491,11 @@ static ulong zynqmp_clk_get_peripheral_rate(struct zynqmp_clk_priv *priv,
DIV_ROUND_CLOSEST(pllrate, div0), div1);
}
-static ulong zynqmp_clk_get_wdt_rate(struct zynqmp_clk_priv *priv,
- enum zynqmp_clk id, bool two_divs)
+static ulong zynqmp_clk_get_crf_crl_rate(struct zynqmp_clk_priv *priv,
+ enum zynqmp_clk id, bool two_divs)
{
enum zynqmp_clk pll;
- u32 clk_ctrl, div0;
+ u32 clk_ctrl, div0, srcsel;
u32 div1 = 1;
int ret;
ulong pllrate;
@@ -475,8 +509,45 @@ static ulong zynqmp_clk_get_wdt_rate(struct zynqmp_clk_priv *priv,
div0 = (clk_ctrl & CLK_CTRL_DIV0_MASK) >> CLK_CTRL_DIV0_SHIFT;
if (!div0)
div0 = 1;
+ srcsel = clk_ctrl & CLK_CTRL_SRCSEL_MASK;
- pll = zynqmp_clk_get_wdt_pll(clk_ctrl);
+ switch (id) {
+ case wdt:
+ case dbg_trace:
+ case topsw_lsbus:
+ pll = pll_src[WDT_CLK_SRC][srcsel];
+ break;
+ case dbg_fpd:
+ case dbg_tstmp:
+ pll = pll_src[DBG_FPD_CLK_SRC][srcsel];
+ break;
+ case timestamp_ref:
+ pll = pll_src[TIMESTAMP_CLK_SRC][srcsel];
+ break;
+ case sata_ref:
+ pll = pll_src[SATA_CLK_SRC][srcsel];
+ break;
+ case pcie_ref:
+ pll = pll_src[PCIE_CLK_SRC][srcsel];
+ break;
+ case gpu_ref ... gpu_pp1_ref:
+ pll = pll_src[GPU_CLK_SRC][srcsel];
+ break;
+ case gdma_ref:
+ case dpdma_ref:
+ case topsw_main:
+ pll = pll_src[TOPSW_MAIN_CLK_SRC][srcsel];
+ break;
+ case cpu_r5:
+ case ams_ref:
+ case adma_ref:
+ case lpd_lsbus:
+ case lpd_switch:
+ pll = pll_src[CPU_R5_CLK_SRC][srcsel];
+ break;
+ default:
+ return -ENXIO;
+ }
if (two_divs) {
ret = zynqmp_mmio_read(zynqmp_clk_get_register(pll), &clk_ctrl);
if (ret) {
@@ -533,7 +604,7 @@ static ulong zynqmp_clk_set_peripheral_rate(struct zynqmp_clk_priv *priv,
enum zynqmp_clk pll;
u32 clk_ctrl, div0 = 0, div1 = 0;
ulong pll_rate, new_rate;
- u32 reg;
+ u32 reg, srcsel;
int ret;
u32 mask;
@@ -544,7 +615,8 @@ static ulong zynqmp_clk_set_peripheral_rate(struct zynqmp_clk_priv *priv,
return -EIO;
}
- pll = zynqmp_clk_get_peripheral_pll(clk_ctrl);
+ srcsel = clk_ctrl & CLK_CTRL_SRCSEL_MASK;
+ pll = pll_src[PERI_CLK_SRC][srcsel];
pll_rate = zynqmp_clk_get_pll_rate(priv, pll);
if (IS_ERR_VALUE(pll_rate))
return pll_rate;
@@ -588,14 +660,31 @@ static ulong zynqmp_clk_get_rate(struct clk *clk)
return zynqmp_clk_get_cpu_rate(priv, id);
case ddr_ref:
return zynqmp_clk_get_ddr_rate(priv);
+ case dll_ref:
+ return zynqmp_clk_get_dll_rate(priv);
+ case gem_tsu_ref:
+ case pl0 ... pl3:
case gem0_ref ... gem3_ref:
case qspi_ref ... can1_ref:
- case pl0 ... pl3:
+ case usb0_bus_ref ... usb3_dual_ref:
two_divs = true;
return zynqmp_clk_get_peripheral_rate(priv, id, two_divs);
case wdt:
+ case topsw_lsbus:
+ case sata_ref ... gpu_pp1_ref:
two_divs = true;
- return zynqmp_clk_get_wdt_rate(priv, id, two_divs);
+ case cpu_r5:
+ case dbg_fpd:
+ case ams_ref:
+ case adma_ref:
+ case lpd_lsbus:
+ case dbg_trace:
+ case dbg_tstmp:
+ case lpd_switch:
+ case topsw_main:
+ case timestamp_ref:
+ case gdma_ref ... dpdma_ref:
+ return zynqmp_clk_get_crf_crl_rate(priv, id, two_divs);
default:
return -ENXIO;
}