- 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.
This commit is contained in:
Tom Rini 2020-08-24 09:06:02 -04:00
commit 1aa3966173
13 changed files with 152 additions and 29 deletions

View File

@ -23,31 +23,32 @@ static void show_clks(struct udevice *dev, int depth, int last_flag)
clkp = dev_get_clk_ptr(dev);
if (device_get_uclass_id(dev) == UCLASS_CLK && clkp) {
depth++;
rate = clk_get_rate(clkp);
printf(" %-12u %8d ", rate, clkp->enable_count);
printf(" %-12u %8d ", rate, clkp->enable_count);
for (i = depth; i >= 0; i--) {
is_last = (last_flag >> i) & 1;
if (i) {
if (is_last)
printf(" ");
else
printf("| ");
} else {
if (is_last)
printf("`-- ");
else
printf("|-- ");
for (i = depth; i >= 0; i--) {
is_last = (last_flag >> i) & 1;
if (i) {
if (is_last)
printf(" ");
else
printf("| ");
} else {
if (is_last)
printf("`-- ");
else
printf("|-- ");
}
}
}
printf("%s\n", dev->name);
printf("%s\n", dev->name);
}
list_for_each_entry(child, &dev->child_head, sibling_node) {
is_last = list_is_last(&child->sibling_node, &dev->child_head);
show_clks(child, depth + 1, (last_flag << 1) | is_last);
show_clks(child, depth, (last_flag << 1) | is_last);
}
}

View File

@ -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) {

View File

@ -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) {

View File

@ -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);

View File

@ -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) {

View File

@ -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)]);

View File

@ -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",

View File

@ -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));

View File

@ -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

View File

@ -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;
}

View File

@ -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,
};

View File

@ -50,6 +50,14 @@ static inline struct clk *sandbox_clk_divider(const char *name,
reg, shift, width, 0);
}
static inline struct clk *sandbox_clk_gate(const char *name, const char *parent,
void __iomem *reg, u8 bit_idx,
u8 clk_gate_flags)
{
return clk_register_gate(NULL, name, parent, CLK_SET_RATE_PARENT,
reg, bit_idx, clk_gate_flags, NULL);
}
struct clk *sandbox_clk_register_gate2(struct device *dev, const char *name,
const char *parent_name,
unsigned long flags,

View File

@ -30,11 +30,22 @@ static int dm_test_clk_ccf(struct unit_test_state *uts)
ret = clk_get_by_id(SANDBOX_CLK_ECSPI_ROOT, &clk);
ut_assertok(ret);
ut_asserteq_str("ecspi_root", clk->dev->name);
ut_asserteq(CLK_SET_RATE_PARENT, clk->flags);
/* Test for clk_get_parent_rate() */
ret = clk_get_by_id(SANDBOX_CLK_ECSPI1, &clk);
ut_assertok(ret);
ut_asserteq_str("ecspi1", clk->dev->name);
ut_asserteq(CLK_SET_RATE_PARENT, clk->flags);
rate = clk_get_parent_rate(clk);
ut_asserteq(rate, 20000000);
/* test the gate of CCF */
ret = clk_get_by_id(SANDBOX_CLK_ECSPI0, &clk);
ut_assertok(ret);
ut_asserteq_str("ecspi0", clk->dev->name);
ut_asserteq(CLK_SET_RATE_PARENT, clk->flags);
rate = clk_get_parent_rate(clk);
ut_asserteq(rate, 20000000);
@ -43,24 +54,52 @@ static int dm_test_clk_ccf(struct unit_test_state *uts)
ret = clk_get_by_id(SANDBOX_CLK_USDHC1_SEL, &clk);
ut_assertok(ret);
ut_asserteq_str("usdhc1_sel", clk->dev->name);
ut_asserteq(CLK_SET_RATE_NO_REPARENT, clk->flags);
rate = clk_get_parent_rate(clk);
ut_asserteq(rate, 60000000);
rate = clk_get_rate(clk);
ut_asserteq(rate, 60000000);
ret = clk_get_by_id(SANDBOX_CLK_PLL3_80M, &pclk);
ut_assertok(ret);
ret = clk_set_parent(clk, pclk);
ut_assertok(ret);
rate = clk_get_rate(clk);
ut_asserteq(rate, 80000000);
ret = clk_get_by_id(SANDBOX_CLK_USDHC2_SEL, &clk);
ut_assertok(ret);
ut_asserteq_str("usdhc2_sel", clk->dev->name);
ut_asserteq(CLK_SET_RATE_NO_REPARENT, clk->flags);
rate = clk_get_parent_rate(clk);
ut_asserteq(rate, 80000000);
pclk = clk_get_parent(clk);
ut_asserteq_str("pll3_80m", pclk->dev->name);
ut_asserteq(CLK_SET_RATE_PARENT, pclk->flags);
rate = clk_get_rate(clk);
ut_asserteq(rate, 80000000);
ret = clk_get_by_id(SANDBOX_CLK_PLL3_60M, &pclk);
ut_assertok(ret);
ret = clk_set_parent(clk, pclk);
ut_assertok(ret);
rate = clk_get_rate(clk);
ut_asserteq(rate, 60000000);
/* Test the composite of CCF */
ret = clk_get_by_id(SANDBOX_CLK_I2C, &clk);
ut_assertok(ret);
ut_asserteq_str("i2c", clk->dev->name);
ut_asserteq(CLK_SET_RATE_UNGATE, clk->flags);
rate = clk_get_rate(clk);
ut_asserteq(rate, 60000000);