summaryrefslogtreecommitdiffstats
path: root/drivers/clk/at91/clk-generated.c
diff options
context:
space:
mode:
authorWenyou Yang <wenyou.yang@atmel.com>2016-09-27 11:00:29 +0800
committerAndreas Bießmann <andreas@biessmann.org>2016-10-28 18:37:14 +0200
commit6cadaa046b196bebebd7acb13edd840bcfef98e2 (patch)
tree91724b2c42297e4d8f7bc5735f9881ada4a99903 /drivers/clk/at91/clk-generated.c
parent3f56b1321593c0081e77a3bc900177e6cf2f21d6 (diff)
downloadu-boot-6cadaa046b196bebebd7acb13edd840bcfef98e2.tar.gz
u-boot-6cadaa046b196bebebd7acb13edd840bcfef98e2.tar.xz
u-boot-6cadaa046b196bebebd7acb13edd840bcfef98e2.zip
clk: at91: Improve the clock implementation
For the peripheral clock, provide the clock ops for the clock provider, such as spi0_clk. The .of_xlate is to get the clk->id, the .enable is to enable the spi0 peripheral clock, the .get_rate is to get the clock frequency. The driver for periph32ck node is responsible for recursively binding its children as clk devices, not provide the clock ops. So do the generated clock and system clock. Signed-off-by: Wenyou Yang <wenyou.yang@atmel.com> Acked-by: Stephen Warren <swarren@nvidia.com>
Diffstat (limited to 'drivers/clk/at91/clk-generated.c')
-rw-r--r--drivers/clk/at91/clk-generated.c87
1 files changed, 51 insertions, 36 deletions
diff --git a/drivers/clk/at91/clk-generated.c b/drivers/clk/at91/clk-generated.c
index f6164cc8ca..d36f64ffdf 100644
--- a/drivers/clk/at91/clk-generated.c
+++ b/drivers/clk/at91/clk-generated.c
@@ -17,15 +17,41 @@ DECLARE_GLOBAL_DATA_PTR;
#define GENERATED_SOURCE_MAX 6
#define GENERATED_MAX_DIV 255
-struct generated_clk_priv {
+/**
+ * generated_clk_bind() - for the generated clock driver
+ * Recursively bind its children as clk devices.
+ *
+ * @return: 0 on success, or negative error code on failure
+ */
+static int generated_clk_bind(struct udevice *dev)
+{
+ return at91_clk_sub_device_bind(dev, "generic-clk");
+}
+
+static const struct udevice_id generated_clk_match[] = {
+ { .compatible = "atmel,sama5d2-clk-generated" },
+ {}
+};
+
+U_BOOT_DRIVER(generated_clk) = {
+ .name = "generated-clk",
+ .id = UCLASS_MISC,
+ .of_match = generated_clk_match,
+ .bind = generated_clk_bind,
+};
+
+/*-------------------------------------------------------------*/
+
+struct generic_clk_priv {
u32 num_parents;
};
-static ulong generated_clk_get_rate(struct clk *clk)
+static ulong generic_clk_get_rate(struct clk *clk)
{
struct pmc_platdata *plat = dev_get_platdata(clk->dev);
struct at91_pmc *pmc = plat->reg_base;
struct clk parent;
+ ulong clk_rate;
u32 tmp, gckdiv;
u8 parent_id;
int ret;
@@ -36,18 +62,22 @@ static ulong generated_clk_get_rate(struct clk *clk)
AT91_PMC_PCR_GCKCSS_MASK;
gckdiv = (tmp >> AT91_PMC_PCR_GCKDIV_OFFSET) & AT91_PMC_PCR_GCKDIV_MASK;
- ret = clk_get_by_index(clk->dev, parent_id, &parent);
+ ret = clk_get_by_index(dev_get_parent(clk->dev), parent_id, &parent);
if (ret)
return 0;
- return clk_get_rate(&parent) / (gckdiv + 1);
+ clk_rate = clk_get_rate(&parent) / (gckdiv + 1);
+
+ clk_free(&parent);
+
+ return clk_rate;
}
-static ulong generated_clk_set_rate(struct clk *clk, ulong rate)
+static ulong generic_clk_set_rate(struct clk *clk, ulong rate)
{
struct pmc_platdata *plat = dev_get_platdata(clk->dev);
struct at91_pmc *pmc = plat->reg_base;
- struct generated_clk_priv *priv = dev_get_priv(clk->dev);
+ struct generic_clk_priv *priv = dev_get_priv(clk->dev);
struct clk parent, best_parent;
ulong tmp_rate, best_rate = rate, parent_rate;
int tmp_diff, best_diff = -1;
@@ -58,7 +88,7 @@ static ulong generated_clk_set_rate(struct clk *clk, ulong rate)
int ret;
for (i = 0; i < priv->num_parents; i++) {
- ret = clk_get_by_index(clk->dev, i, &parent);
+ ret = clk_get_by_index(dev_get_parent(clk->dev), i, &parent);
if (ret)
return ret;
@@ -111,18 +141,20 @@ static ulong generated_clk_set_rate(struct clk *clk, ulong rate)
return 0;
}
-static struct clk_ops generated_clk_ops = {
- .get_rate = generated_clk_get_rate,
- .set_rate = generated_clk_set_rate,
+static struct clk_ops generic_clk_ops = {
+ .of_xlate = at91_clk_of_xlate,
+ .get_rate = generic_clk_get_rate,
+ .set_rate = generic_clk_set_rate,
};
-static int generated_clk_ofdata_to_platdata(struct udevice *dev)
+static int generic_clk_ofdata_to_platdata(struct udevice *dev)
{
- struct generated_clk_priv *priv = dev_get_priv(dev);
+ struct generic_clk_priv *priv = dev_get_priv(dev);
u32 cells[GENERATED_SOURCE_MAX];
u32 num_parents;
- num_parents = fdtdec_get_int_array_count(gd->fdt_blob, dev->of_offset,
+ num_parents = fdtdec_get_int_array_count(gd->fdt_blob,
+ dev_get_parent(dev)->of_offset,
"clocks", cells,
GENERATED_SOURCE_MAX);
@@ -134,29 +166,12 @@ static int generated_clk_ofdata_to_platdata(struct udevice *dev)
return 0;
}
-static int generated_clk_bind(struct udevice *dev)
-{
- return at91_pmc_clk_node_bind(dev);
-}
-
-static int generated_clk_probe(struct udevice *dev)
-{
- return at91_pmc_core_probe(dev);
-}
-
-static const struct udevice_id generated_clk_match[] = {
- { .compatible = "atmel,sama5d2-clk-generated" },
- {}
-};
-
-U_BOOT_DRIVER(generated_clk) = {
- .name = "generated-clk",
+U_BOOT_DRIVER(generic_clk) = {
+ .name = "generic-clk",
.id = UCLASS_CLK,
- .of_match = generated_clk_match,
- .bind = generated_clk_bind,
- .probe = generated_clk_probe,
- .ofdata_to_platdata = generated_clk_ofdata_to_platdata,
- .priv_auto_alloc_size = sizeof(struct generated_clk_priv),
+ .probe = at91_clk_probe,
+ .ofdata_to_platdata = generic_clk_ofdata_to_platdata,
+ .priv_auto_alloc_size = sizeof(struct generic_clk_priv),
.platdata_auto_alloc_size = sizeof(struct pmc_platdata),
- .ops = &generated_clk_ops,
+ .ops = &generic_clk_ops,
};