aboutsummaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorTom Rini <trini@konsulko.com>2020-08-24 09:06:02 -0400
committerTom Rini <trini@konsulko.com>2020-08-24 09:06:02 -0400
commit1aa3966173fe92fa3c46638ee8eb8b8491f521d6 (patch)
tree3c56e11089c590734d01bf967d0a185e3c0e9505 /drivers
parentd584648dad691caec3ecc7777dbfa3f1936878e5 (diff)
parentebd3f1f0d032cc35dfb8d03da7f7ade6e9a51aef (diff)
downloadu-boot-1aa3966173fe92fa3c46638ee8eb8b8491f521d6.zip
u-boot-1aa3966173fe92fa3c46638ee8eb8b8491f521d6.tar.gz
u-boot-1aa3966173fe92fa3c46638ee8eb8b8491f521d6.tar.bz2
Merge tag 'u-boot-clk-24Aug2020' of https://gitlab.denx.de/u-boot/custodians/u-boot-clk
- Add CCF clocks definitions for iMX6Q enet (ETH) - Several fixes for CCF framework - the most notable is the one, which adds get_rate helper to clk-mux.c - Improvements for clk command - better visibility and alignment.
Diffstat (limited to 'drivers')
-rw-r--r--drivers/clk/clk-composite.c1
-rw-r--r--drivers/clk/clk-divider.c1
-rw-r--r--drivers/clk/clk-fixed-factor.c1
-rw-r--r--drivers/clk/clk-gate.c1
-rw-r--r--drivers/clk/clk-mux.c46
-rw-r--r--drivers/clk/clk.c10
-rw-r--r--drivers/clk/clk_sandbox_ccf.c7
-rw-r--r--drivers/clk/ics8n3qv01.c1
-rw-r--r--drivers/clk/imx/clk-imx6q.c8
-rw-r--r--drivers/clk/imx/clk-pllv3.c25
10 files changed, 88 insertions, 13 deletions
diff --git a/drivers/clk/clk-composite.c b/drivers/clk/clk-composite.c
index 819bfca..7e99c5b 100644
--- a/drivers/clk/clk-composite.c
+++ b/drivers/clk/clk-composite.c
@@ -145,6 +145,7 @@ struct clk *clk_register_composite(struct device *dev, const char *name,
}
clk = &composite->clk;
+ clk->flags = flags;
ret = clk_register(clk, UBOOT_DM_CLK_COMPOSITE, name,
parent_names[clk_composite_get_parent(clk)]);
if (ret) {
diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c
index 3465853..8f59d7f 100644
--- a/drivers/clk/clk-divider.c
+++ b/drivers/clk/clk-divider.c
@@ -212,6 +212,7 @@ static struct clk *_register_divider(struct device *dev, const char *name,
/* register the clock */
clk = &div->clk;
+ clk->flags = flags;
ret = clk_register(clk, UBOOT_DM_CLK_CCF_DIVIDER, name, parent_name);
if (ret) {
diff --git a/drivers/clk/clk-fixed-factor.c b/drivers/clk/clk-fixed-factor.c
index 0eb24b8..8d9823b 100644
--- a/drivers/clk/clk-fixed-factor.c
+++ b/drivers/clk/clk-fixed-factor.c
@@ -49,6 +49,7 @@ struct clk *clk_hw_register_fixed_factor(struct device *dev,
fix->mult = mult;
fix->div = div;
clk = &fix->clk;
+ clk->flags = flags;
ret = clk_register(clk, UBOOT_DM_CLK_IMX_FIXED_FACTOR, name,
parent_name);
diff --git a/drivers/clk/clk-gate.c b/drivers/clk/clk-gate.c
index 98e4b80..006d3b6 100644
--- a/drivers/clk/clk-gate.c
+++ b/drivers/clk/clk-gate.c
@@ -142,6 +142,7 @@ struct clk *clk_register_gate(struct device *dev, const char *name,
#endif
clk = &gate->clk;
+ clk->flags = flags;
ret = clk_register(clk, UBOOT_DM_CLK_GATE, name, parent_name);
if (ret) {
diff --git a/drivers/clk/clk-mux.c b/drivers/clk/clk-mux.c
index 26991a5..7a5ee7a 100644
--- a/drivers/clk/clk-mux.c
+++ b/drivers/clk/clk-mux.c
@@ -22,16 +22,17 @@
*/
#include <common.h>
-#include <asm/io.h>
-#include <malloc.h>
+#include <clk.h>
#include <clk-uclass.h>
#include <dm/device.h>
#include <dm/devres.h>
+#include <dm/uclass.h>
#include <linux/bitops.h>
+#include <malloc.h>
+#include <asm/io.h>
#include <linux/clk-provider.h>
-#include <clk.h>
-#include "clk.h"
#include <linux/err.h>
+#include "clk.h"
#define UBOOT_DM_CLK_CCF_MUX "ccf_clk_mux"
@@ -131,18 +132,50 @@ static int clk_mux_set_parent(struct clk *clk, struct clk *parent)
if (mux->flags & CLK_MUX_HIWORD_MASK) {
reg = mux->mask << (mux->shift + 16);
} else {
+#if CONFIG_IS_ENABLED(SANDBOX_CLK_CCF)
+ reg = mux->io_mux_val;
+#else
reg = readl(mux->reg);
+#endif
reg &= ~(mux->mask << mux->shift);
}
val = val << mux->shift;
reg |= val;
+#if CONFIG_IS_ENABLED(SANDBOX_CLK_CCF)
+ mux->io_mux_val = reg;
+#else
writel(reg, mux->reg);
+#endif
return 0;
}
+static ulong clk_mux_get_rate(struct clk *clk)
+{
+ struct clk_mux *mux = to_clk_mux(clk_dev_binded(clk) ?
+ dev_get_clk_ptr(clk->dev) : clk);
+ struct udevice *parent;
+ struct clk *pclk;
+ int err, index;
+
+ index = clk_mux_get_parent(clk);
+ if (index >= mux->num_parents)
+ return -EFAULT;
+
+ err = uclass_get_device_by_name(UCLASS_CLK, mux->parent_names[index],
+ &parent);
+ if (err)
+ return err;
+
+ pclk = dev_get_clk_ptr(parent);
+ if (!pclk)
+ return -ENODEV;
+
+ return clk_get_rate(pclk);
+}
+
const struct clk_ops clk_mux_ops = {
- .get_rate = clk_generic_get_rate,
+ .get_rate = clk_mux_get_rate,
.set_parent = clk_mux_set_parent,
};
@@ -185,12 +218,13 @@ struct clk *clk_hw_register_mux_table(struct device *dev, const char *name,
#endif
clk = &mux->clk;
+ clk->flags = flags;
/*
* Read the current mux setup - so we assign correct parent.
*
* Changing parent would require changing internals of udevice struct
- * for the corresponding clock (to do that define .set_parent() method.
+ * for the corresponding clock (to do that define .set_parent() method).
*/
ret = clk_register(clk, UBOOT_DM_CLK_CCF_MUX, name,
parent_names[clk_mux_get_parent(clk)]);
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index 0f55ba7..786f4e8 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -22,13 +22,13 @@ int clk_register(struct clk *clk, const char *drv_name,
ret = uclass_get_device_by_name(UCLASS_CLK, parent_name, &parent);
if (ret) {
- printf("%s: name: %s parent: %s [0x%p]\n",
- __func__, name, parent->name, parent);
+ printf("%s: failed to get %s device (parent of %s)\n",
+ __func__, parent_name, name);
+ } else {
+ debug("%s: name: %s parent: %s [0x%p]\n", __func__, name,
+ parent->name, parent);
}
- debug("%s: name: %s parent: %s [0x%p]\n", __func__, name, parent->name,
- parent);
-
drv = lists_driver_lookup_name(drv_name);
if (!drv) {
printf("%s: %s is not a valid driver name\n",
diff --git a/drivers/clk/clk_sandbox_ccf.c b/drivers/clk/clk_sandbox_ccf.c
index 0619d04..fedcdd4 100644
--- a/drivers/clk/clk_sandbox_ccf.c
+++ b/drivers/clk/clk_sandbox_ccf.c
@@ -130,6 +130,7 @@ struct clk *sandbox_clk_register_gate2(struct device *dev, const char *name,
gate->state = 0;
clk = &gate->clk;
+ clk->flags = flags;
ret = clk_register(clk, "sandbox_clk_gate2", name, parent_name);
if (ret) {
@@ -250,6 +251,10 @@ static int sandbox_clk_ccf_probe(struct udevice *dev)
clk_dm(SANDBOX_CLK_ECSPI_ROOT,
sandbox_clk_divider("ecspi_root", "pll3_60m", &reg, 19, 6));
+ reg = 0;
+ clk_dm(SANDBOX_CLK_ECSPI0,
+ sandbox_clk_gate("ecspi0", "ecspi_root", &reg, 0, 0));
+
clk_dm(SANDBOX_CLK_ECSPI1,
sandbox_clk_gate2("ecspi1", "ecspi_root", base + 0x6c, 0));
@@ -268,7 +273,7 @@ static int sandbox_clk_ccf_probe(struct udevice *dev)
reg = BIT(28) | BIT(24) | BIT(16);
clk_dm(SANDBOX_CLK_I2C,
sandbox_clk_composite("i2c", i2c_sels, ARRAY_SIZE(i2c_sels),
- &reg, 0));
+ &reg, CLK_SET_RATE_UNGATE));
clk_dm(SANDBOX_CLK_I2C_ROOT,
sandbox_clk_gate2("i2c_root", "i2c", base + 0x7c, 0));
diff --git a/drivers/clk/ics8n3qv01.c b/drivers/clk/ics8n3qv01.c
index 4f80bf6..76b27ad 100644
--- a/drivers/clk/ics8n3qv01.c
+++ b/drivers/clk/ics8n3qv01.c
@@ -82,7 +82,6 @@ static int ics8n3qv01_calc_parameters(uint fout, uint *_mint, uint *_mfrac,
uint n, foutiic, fvcoiic, mint;
u64 mfrac;
- n = (2215000000U + fout / 2) / fout;
if (fout < 417000000U)
n = 2 * ((2215000000U / 2 + fout / 2) / fout);
else
diff --git a/drivers/clk/imx/clk-imx6q.c b/drivers/clk/imx/clk-imx6q.c
index 11d1943..5343036 100644
--- a/drivers/clk/imx/clk-imx6q.c
+++ b/drivers/clk/imx/clk-imx6q.c
@@ -113,6 +113,10 @@ static int imx6q_clk_probe(struct udevice *dev)
imx_clk_pfd("pll2_pfd0_352m", "pll2_bus", base + 0x100, 0));
clk_dm(IMX6QDL_CLK_PLL2_PFD2_396M,
imx_clk_pfd("pll2_pfd2_396m", "pll2_bus", base + 0x100, 2));
+ clk_dm(IMX6QDL_CLK_PLL6,
+ imx_clk_pllv3(IMX_PLLV3_ENET, "pll6", "osc", base + 0xe0, 0x3));
+ clk_dm(IMX6QDL_CLK_PLL6_ENET,
+ imx_clk_gate("pll6_enet", "pll6", base + 0xe0, 13));
/* CCM clocks */
base = dev_read_addr_ptr(dev);
@@ -183,6 +187,10 @@ static int imx6q_clk_probe(struct udevice *dev)
clk_dm(IMX6QDL_CLK_I2C2,
imx_clk_gate2("i2c2", "ipg_per", base + 0x70, 8));
+ clk_dm(IMX6QDL_CLK_ENET, imx_clk_gate2("enet", "ipg", base + 0x6c, 10));
+ clk_dm(IMX6QDL_CLK_ENET_REF,
+ imx_clk_fixed_factor("enet_ref", "pll6_enet", 1, 1));
+
return 0;
}
diff --git a/drivers/clk/imx/clk-pllv3.c b/drivers/clk/imx/clk-pllv3.c
index b4a9d58..feacaee 100644
--- a/drivers/clk/imx/clk-pllv3.c
+++ b/drivers/clk/imx/clk-pllv3.c
@@ -20,6 +20,7 @@
#define UBOOT_DM_CLK_IMX_PLLV3_SYS "imx_clk_pllv3_sys"
#define UBOOT_DM_CLK_IMX_PLLV3_USB "imx_clk_pllv3_usb"
#define UBOOT_DM_CLK_IMX_PLLV3_AV "imx_clk_pllv3_av"
+#define UBOOT_DM_CLK_IMX_PLLV3_ENET "imx_clk_pllv3_enet"
#define PLL_NUM_OFFSET 0x10
#define PLL_DENOM_OFFSET 0x20
@@ -36,6 +37,7 @@ struct clk_pllv3 {
u32 enable_bit;
u32 div_mask;
u32 div_shift;
+ unsigned long ref_clock;
};
#define to_clk_pllv3(_clk) container_of(_clk, struct clk_pllv3, clk)
@@ -232,6 +234,19 @@ static const struct clk_ops clk_pllv3_av_ops = {
.set_rate = clk_pllv3_av_set_rate,
};
+static ulong clk_pllv3_enet_get_rate(struct clk *clk)
+{
+ struct clk_pllv3 *pll = to_clk_pllv3(clk);
+
+ return pll->ref_clock;
+}
+
+static const struct clk_ops clk_pllv3_enet_ops = {
+ .enable = clk_pllv3_generic_enable,
+ .disable = clk_pllv3_generic_disable,
+ .get_rate = clk_pllv3_enet_get_rate,
+};
+
struct clk *imx_clk_pllv3(enum imx_pllv3_type type, const char *name,
const char *parent_name, void __iomem *base,
u32 div_mask)
@@ -269,6 +284,10 @@ struct clk *imx_clk_pllv3(enum imx_pllv3_type type, const char *name,
pll->div_shift = 0;
pll->powerup_set = false;
break;
+ case IMX_PLLV3_ENET:
+ drv_name = UBOOT_DM_CLK_IMX_PLLV3_ENET;
+ pll->ref_clock = 500000000;
+ break;
default:
kfree(pll);
return ERR_PTR(-ENOTSUPP);
@@ -314,3 +333,9 @@ U_BOOT_DRIVER(clk_pllv3_av) = {
.ops = &clk_pllv3_av_ops,
.flags = DM_FLAG_PRE_RELOC,
};
+
+U_BOOT_DRIVER(clk_pllv3_enet) = {
+ .name = UBOOT_DM_CLK_IMX_PLLV3_ENET,
+ .id = UCLASS_CLK,
+ .ops = &clk_pllv3_enet_ops,
+};