Skip to content
Snippets Groups Projects
Commit 135aa950 authored by Stephen Warren's avatar Stephen Warren Committed by Simon Glass
Browse files

clk: convert API to match reset/mailbox style


The following changes are made to the clock API:
* The concept of "clocks" and "peripheral clocks" are unified; each clock
  provider now implements a single set of clocks. This provides a simpler
  conceptual interface to clients, and better aligns with device tree
  clock bindings.
* Clocks are now identified with a single "struct clk", rather than
  requiring clients to store the clock provider device and clock identity
  values separately. For simple clock consumers, this isolates clients
  from internal details of the clock API.
* clk.h is split so it only contains the client/consumer API, whereas
  clk-uclass.h contains the provider API. This aligns with the recently
  added reset and mailbox APIs.
* clk_ops .of_xlate(), .request(), and .free() are added so providers
  can customize these operations if needed. This also aligns with the
  recently added reset and mailbox APIs.
* clk_disable() is added.
* All users of the current clock APIs are updated.
* Sandbox clock tests are updated to exercise clock lookup via DT, and
  clock enable/disable.
* rkclk_get_clk() is removed and replaced with standard APIs.

Buildman shows no clock-related errors for any board for which buildman
can download a toolchain.

test/py passes for sandbox (which invokes the dm clk test amongst
others).

Signed-off-by: default avatarStephen Warren <swarren@nvidia.com>
Acked-by: default avatarSimon Glass <sjg@chromium.org>
parent 4581b717
Branches
Tags
No related merge requests found
Showing
with 616 additions and 392 deletions
...@@ -62,18 +62,6 @@ static inline u32 clk_get_divisor(ulong input_rate, uint output_rate) ...@@ -62,18 +62,6 @@ static inline u32 clk_get_divisor(ulong input_rate, uint output_rate)
*/ */
void *rockchip_get_cru(void); void *rockchip_get_cru(void);
/**
* rkclk_get_clk() - get a pointer to a given clock
*
* This is an internal function - use outside the clock subsystem indicates
* that work is needed!
*
* @clk_id: Clock requested
* @devp: Returns a pointer to that clock
* @return 0 if OK, -ve on error
*/
int rkclk_get_clk(enum rk_clk_id clk_id, struct udevice **devp);
struct rk3288_cru; struct rk3288_cru;
struct rk3288_grf; struct rk3288_grf;
......
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#include <dm.h> #include <dm.h>
#include <ram.h> #include <ram.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/arch/clock.h>
DECLARE_GLOBAL_DATA_PTR; DECLARE_GLOBAL_DATA_PTR;
...@@ -54,15 +55,43 @@ void lowlevel_init(void) ...@@ -54,15 +55,43 @@ void lowlevel_init(void)
static int do_clock(cmd_tbl_t *cmdtp, int flag, int argc, static int do_clock(cmd_tbl_t *cmdtp, int flag, int argc,
char * const argv[]) char * const argv[])
{ {
static const struct {
char *name;
int id;
} clks[] = {
{ "osc", CLK_OSC },
{ "apll", CLK_ARM },
{ "dpll", CLK_DDR },
{ "cpll", CLK_CODEC },
{ "gpll", CLK_GENERAL },
#ifdef CONFIG_ROCKCHIP_RK3036
{ "mpll", CLK_NEW },
#else
{ "npll", CLK_NEW },
#endif
};
int ret, i;
struct udevice *dev; struct udevice *dev;
for (uclass_first_device(UCLASS_CLK, &dev); ret = uclass_get_device(UCLASS_CLK, 0, &dev);
dev; if (ret) {
uclass_next_device(&dev)) { printf("clk-uclass not found\n");
return 0;
}
for (i = 0; i < ARRAY_SIZE(clks); i++) {
struct clk clk;
ulong rate; ulong rate;
rate = clk_get_rate(dev); clk.id = clks[i].id;
printf("%s: %lu\n", dev->name, rate); ret = clk_request(dev, &clk);
if (ret < 0)
continue;
rate = clk_get_rate(&clk);
printf("%s: %lu\n", clks[i].name, rate);
clk_free(&clk);
} }
return 0; return 0;
......
...@@ -36,7 +36,7 @@ struct chan_info { ...@@ -36,7 +36,7 @@ struct chan_info {
struct dram_info { struct dram_info {
struct chan_info chan[2]; struct chan_info chan[2];
struct ram_info info; struct ram_info info;
struct udevice *ddr_clk; struct clk ddr_clk;
struct rk3288_cru *cru; struct rk3288_cru *cru;
struct rk3288_grf *grf; struct rk3288_grf *grf;
struct rk3288_sgrf *sgrf; struct rk3288_sgrf *sgrf;
...@@ -576,7 +576,7 @@ static void dram_all_config(const struct dram_info *dram, ...@@ -576,7 +576,7 @@ static void dram_all_config(const struct dram_info *dram,
rk_clrsetreg(&dram->sgrf->soc_con2, 0x1f, sdram_params->base.stride); rk_clrsetreg(&dram->sgrf->soc_con2, 0x1f, sdram_params->base.stride);
} }
static int sdram_init(const struct dram_info *dram, static int sdram_init(struct dram_info *dram,
const struct rk3288_sdram_params *sdram_params) const struct rk3288_sdram_params *sdram_params)
{ {
int channel; int channel;
...@@ -592,8 +592,8 @@ static int sdram_init(const struct dram_info *dram, ...@@ -592,8 +592,8 @@ static int sdram_init(const struct dram_info *dram,
return -E2BIG; return -E2BIG;
} }
debug("ddr clk %s\n", dram->ddr_clk->name); debug("ddr clk dpll\n");
ret = clk_set_rate(dram->ddr_clk, sdram_params->base.ddr_freq); ret = clk_set_rate(&dram->ddr_clk, sdram_params->base.ddr_freq);
debug("ret=%d\n", ret); debug("ret=%d\n", ret);
if (ret) { if (ret) {
debug("Could not set DDR clock\n"); debug("Could not set DDR clock\n");
...@@ -836,6 +836,7 @@ static int rk3288_dmc_probe(struct udevice *dev) ...@@ -836,6 +836,7 @@ static int rk3288_dmc_probe(struct udevice *dev)
struct dram_info *priv = dev_get_priv(dev); struct dram_info *priv = dev_get_priv(dev);
struct regmap *map; struct regmap *map;
int ret; int ret;
struct udevice *dev_clk;
map = syscon_get_regmap_by_driver_data(ROCKCHIP_SYSCON_NOC); map = syscon_get_regmap_by_driver_data(ROCKCHIP_SYSCON_NOC);
if (IS_ERR(map)) if (IS_ERR(map))
...@@ -856,7 +857,11 @@ static int rk3288_dmc_probe(struct udevice *dev) ...@@ -856,7 +857,11 @@ static int rk3288_dmc_probe(struct udevice *dev)
priv->chan[1].pctl = regmap_get_range(map, 2); priv->chan[1].pctl = regmap_get_range(map, 2);
priv->chan[1].publ = regmap_get_range(map, 3); priv->chan[1].publ = regmap_get_range(map, 3);
ret = uclass_get_device(UCLASS_CLK, CLK_DDR, &priv->ddr_clk); ret = uclass_get_device(UCLASS_CLK, 0, &dev_clk);
if (ret)
return ret;
priv->ddr_clk.id = CLK_DDR;
ret = clk_request(dev_clk, &priv->ddr_clk);
if (ret) if (ret)
return ret; return ret;
......
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
*/ */
#include <common.h> #include <common.h>
#include <clk.h> #include <clk-uclass.h>
#include <dm.h> #include <dm.h>
#include <errno.h> #include <errno.h>
#include <asm/io.h> #include <asm/io.h>
...@@ -212,11 +212,11 @@ static int clk_init_uart(struct msm_clk_priv *priv) ...@@ -212,11 +212,11 @@ static int clk_init_uart(struct msm_clk_priv *priv)
return 0; return 0;
} }
ulong msm_set_periph_rate(struct udevice *dev, int periph, ulong rate) ulong msm_set_rate(struct clk *clk, ulong rate)
{ {
struct msm_clk_priv *priv = dev_get_priv(dev); struct msm_clk_priv *priv = dev_get_priv(clk->dev);
switch (periph) { switch (clk->id) {
case 0: /* SDC1 */ case 0: /* SDC1 */
return clk_init_sdc(priv, 0, rate); return clk_init_sdc(priv, 0, rate);
break; break;
...@@ -243,7 +243,7 @@ static int msm_clk_probe(struct udevice *dev) ...@@ -243,7 +243,7 @@ static int msm_clk_probe(struct udevice *dev)
} }
static struct clk_ops msm_clk_ops = { static struct clk_ops msm_clk_ops = {
.set_periph_rate = msm_set_periph_rate, .set_rate = msm_set_rate,
}; };
static const struct udevice_id msm_clk_ids[] = { static const struct udevice_id msm_clk_ids[] = {
......
...@@ -6,7 +6,6 @@ ...@@ -6,7 +6,6 @@
*/ */
#include <common.h> #include <common.h>
#include <errno.h> #include <errno.h>
#include <clk.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/arch/hardware.h> #include <asm/arch/hardware.h>
#include <asm/arch/clk.h> #include <asm/arch/clk.h>
......
...@@ -23,18 +23,34 @@ ...@@ -23,18 +23,34 @@
DECLARE_GLOBAL_DATA_PTR; DECLARE_GLOBAL_DATA_PTR;
static ulong clk_get_cpu_rate(void) static ulong rate(int id)
{ {
int ret; int ret;
struct udevice *dev; struct udevice *dev;
struct clk clk;
ulong rate;
ret = uclass_get_device(UCLASS_CLK, 0, &dev); ret = uclass_get_device(UCLASS_CLK, 0, &dev);
if (ret) { if (ret) {
panic("uclass-clk: device not found\n"); printf("clk-uclass not found\n");
return 0; return 0;
} }
return clk_get_rate(dev); clk.id = id;
ret = clk_request(dev, &clk);
if (ret < 0)
return ret;
rate = clk_get_rate(&clk);
clk_free(&clk);
return rate;
}
static ulong clk_get_cpu_rate(void)
{
return rate(PB7CLK);
} }
/* initialize prefetch module related to cpu_clk */ /* initialize prefetch module related to cpu_clk */
...@@ -127,30 +143,25 @@ const char *get_core_name(void) ...@@ -127,30 +143,25 @@ const char *get_core_name(void)
} }
#endif #endif
#ifdef CONFIG_CMD_CLK #ifdef CONFIG_CMD_CLK
int soc_clk_dump(void) int soc_clk_dump(void)
{ {
int i, ret; int i;
struct udevice *dev;
ret = uclass_get_device(UCLASS_CLK, 0, &dev);
if (ret) {
printf("clk-uclass not found\n");
return ret;
}
printf("PLL Speed: %lu MHz\n", printf("PLL Speed: %lu MHz\n",
CLK_MHZ(clk_get_periph_rate(dev, PLLCLK))); CLK_MHZ(rate(PLLCLK)));
printf("CPU Speed: %lu MHz\n", CLK_MHZ(clk_get_rate(dev)));
printf("MPLL Speed: %lu MHz\n", printf("CPU Speed: %lu MHz\n", CLK_MHZ(rate(PB7CLK)));
CLK_MHZ(clk_get_periph_rate(dev, MPLL)));
printf("MPLL Speed: %lu MHz\n", CLK_MHZ(rate(MPLL)));
for (i = PB1CLK; i <= PB7CLK; i++) for (i = PB1CLK; i <= PB7CLK; i++)
printf("PB%d Clock Speed: %lu MHz\n", i - PB1CLK + 1, printf("PB%d Clock Speed: %lu MHz\n", i - PB1CLK + 1,
CLK_MHZ(clk_get_periph_rate(dev, i))); CLK_MHZ(rate(i)));
for (i = REF1CLK; i <= REF5CLK; i++) for (i = REF1CLK; i <= REF5CLK; i++)
printf("REFO%d Clock Speed: %lu MHz\n", i - REF1CLK + 1, printf("REFO%d Clock Speed: %lu MHz\n", i - REF1CLK + 1,
CLK_MHZ(clk_get_periph_rate(dev, i))); CLK_MHZ(rate(i)));
return 0; return 0;
} }
#endif #endif
...@@ -108,8 +108,23 @@ ...@@ -108,8 +108,23 @@
compatible = "denx,u-boot-fdt-test"; compatible = "denx,u-boot-fdt-test";
}; };
clk@0 { clk_fixed: clk-fixed {
compatible = "fixed-clock";
#clock-cells = <0>;
clock-frequency = <1234>;
};
clk_sandbox: clk-sbox {
compatible = "sandbox,clk"; compatible = "sandbox,clk";
#clock-cells = <1>;
};
clk-test {
compatible = "sandbox,clk-test";
clocks = <&clk_fixed>,
<&clk_sandbox 1>,
<&clk_sandbox 0>;
clock-names = "fixed", "i2c", "spi";
}; };
eth@10002000 { eth@10002000 {
......
/*
* Copyright (c) 2016, NVIDIA CORPORATION.
*
* SPDX-License-Identifier: GPL-2.0
*/
#ifndef __SANDBOX_CLK_H
#define __SANDBOX_CLK_H
#include <common.h>
struct udevice;
/**
* enum sandbox_clk_id - Identity of clocks implemented by the sandbox clock
* provider.
*
* These IDs are within/relative-to the clock provider.
*/
enum sandbox_clk_id {
SANDBOX_CLK_ID_SPI,
SANDBOX_CLK_ID_I2C,
SANDBOX_CLK_ID_COUNT,
};
/**
* enum sandbox_clk_test_id - Identity of the clocks consumed by the sandbox
* clock test device.
*
* These are the IDs the clock consumer knows the clocks as.
*/
enum sandbox_clk_test_id {
SANDBOX_CLK_TEST_ID_FIXED,
SANDBOX_CLK_TEST_ID_SPI,
SANDBOX_CLK_TEST_ID_I2C,
SANDBOX_CLK_TEST_ID_COUNT,
};
/**
* sandbox_clk_query_rate - Query the current rate of a sandbox clock.
*
* @dev: The sandbox clock provider device.
* @id: The clock to query.
* @return: The rate of the clock.
*/
ulong sandbox_clk_query_rate(struct udevice *dev, int id);
/**
* sandbox_clk_query_enable - Query the enable state of a sandbox clock.
*
* @dev: The sandbox clock provider device.
* @id: The clock to query.
* @return: The rate of the clock.
*/
int sandbox_clk_query_enable(struct udevice *dev, int id);
/**
* sandbox_clk_test_get - Ask the sandbox clock test device to request its
* clocks.
*
* @dev: The sandbox clock test (client) devivce.
* @return: 0 if OK, or a negative error code.
*/
int sandbox_clk_test_get(struct udevice *dev);
/**
* sandbox_clk_test_get_rate - Ask the sandbox clock test device to query a
* clock's rate.
*
* @dev: The sandbox clock test (client) devivce.
* @id: The test device's clock ID to query.
* @return: The rate of the clock.
*/
ulong sandbox_clk_test_get_rate(struct udevice *dev, int id);
/**
* sandbox_clk_test_set_rate - Ask the sandbox clock test device to set a
* clock's rate.
*
* @dev: The sandbox clock test (client) devivce.
* @id: The test device's clock ID to configure.
* @return: The new rate of the clock.
*/
ulong sandbox_clk_test_set_rate(struct udevice *dev, int id, ulong rate);
/**
* sandbox_clk_test_enable - Ask the sandbox clock test device to enable a
* clock.
*
* @dev: The sandbox clock test (client) devivce.
* @id: The test device's clock ID to configure.
* @return: 0 if OK, or a negative error code.
*/
int sandbox_clk_test_enable(struct udevice *dev, int id);
/**
* sandbox_clk_test_disable - Ask the sandbox clock test device to disable a
* clock.
*
* @dev: The sandbox clock test (client) devivce.
* @id: The test device's clock ID to configure.
* @return: 0 if OK, or a negative error code.
*/
int sandbox_clk_test_disable(struct udevice *dev, int id);
/**
* sandbox_clk_test_free - Ask the sandbox clock test device to free its
* clocks.
*
* @dev: The sandbox clock test (client) devivce.
* @return: 0 if OK, or a negative error code.
*/
int sandbox_clk_test_free(struct udevice *dev);
#endif
...@@ -19,15 +19,6 @@ ...@@ -19,15 +19,6 @@
#define SANDBOX_CLK_RATE 32768 #define SANDBOX_CLK_RATE 32768
enum {
PERIPH_ID_FIRST = 0,
PERIPH_ID_SPI = PERIPH_ID_FIRST,
PERIPH_ID_I2C,
PERIPH_ID_PCI,
PERIPH_ID_COUNT,
};
/* System controller driver data */ /* System controller driver data */
enum { enum {
SYSCON0 = 32, SYSCON0 = 32,
......
...@@ -11,20 +11,31 @@ ...@@ -11,20 +11,31 @@
#include <common.h> #include <common.h>
#include <dm.h> #include <dm.h>
#include <clk.h> #include <clk.h>
#include <dt-bindings/clock/microchip,clock.h>
#include <mach/pic32.h> #include <mach/pic32.h>
#ifdef CONFIG_DISPLAY_BOARDINFO #ifdef CONFIG_DISPLAY_BOARDINFO
int checkboard(void) int checkboard(void)
{ {
ulong rate = 0; ulong rate;
struct udevice *dev; struct udevice *dev;
struct clk clk;
int ret;
printf("Core: %s\n", get_core_name()); printf("Core: %s\n", get_core_name());
if (!uclass_get_device(UCLASS_CLK, 0, &dev)) { if (uclass_get_device(UCLASS_CLK, 0, &dev))
rate = clk_get_rate(dev); return 0;
clk.id = PB7CLK;
ret = clk_request(dev, &clk);
if (ret < 0)
return 0;
rate = clk_get_rate(&clk);
printf("CPU Speed: %lu MHz\n", rate / 1000000); printf("CPU Speed: %lu MHz\n", rate / 1000000);
}
clk_free(&clk);
return 0; return 0;
} }
......
...@@ -9,6 +9,7 @@ obj-$(CONFIG_CLK) += clk-uclass.o clk_fixed_rate.o ...@@ -9,6 +9,7 @@ obj-$(CONFIG_CLK) += clk-uclass.o clk_fixed_rate.o
obj-$(CONFIG_ROCKCHIP_RK3036) += clk_rk3036.o obj-$(CONFIG_ROCKCHIP_RK3036) += clk_rk3036.o
obj-$(CONFIG_ROCKCHIP_RK3288) += clk_rk3288.o obj-$(CONFIG_ROCKCHIP_RK3288) += clk_rk3288.o
obj-$(CONFIG_SANDBOX) += clk_sandbox.o obj-$(CONFIG_SANDBOX) += clk_sandbox.o
obj-$(CONFIG_SANDBOX) += clk_sandbox_test.o
obj-$(CONFIG_MACH_PIC32) += clk_pic32.o obj-$(CONFIG_MACH_PIC32) += clk_pic32.o
obj-$(CONFIG_CLK_UNIPHIER) += uniphier/ obj-$(CONFIG_CLK_UNIPHIER) += uniphier/
obj-$(CONFIG_CLK_EXYNOS) += exynos/ obj-$(CONFIG_CLK_EXYNOS) += exynos/
/* /*
* Copyright (C) 2015 Google, Inc * Copyright (C) 2015 Google, Inc
* Written by Simon Glass <sjg@chromium.org> * Written by Simon Glass <sjg@chromium.org>
* Copyright (c) 2016, NVIDIA CORPORATION.
* *
* SPDX-License-Identifier: GPL-2.0+ * SPDX-License-Identifier: GPL-2.0+
*/ */
#include <common.h> #include <common.h>
#include <clk.h> #include <clk.h>
#include <clk-uclass.h>
#include <dm.h> #include <dm.h>
#include <errno.h> #include <errno.h>
#include <dm/lists.h>
#include <dm/root.h>
DECLARE_GLOBAL_DATA_PTR; DECLARE_GLOBAL_DATA_PTR;
ulong clk_get_rate(struct udevice *dev) static inline struct clk_ops *clk_dev_ops(struct udevice *dev)
{ {
struct clk_ops *ops = clk_get_ops(dev); return (struct clk_ops *)dev->driver->ops;
if (!ops->get_rate)
return -ENOSYS;
return ops->get_rate(dev);
} }
ulong clk_set_rate(struct udevice *dev, ulong rate) #if CONFIG_IS_ENABLED(OF_CONTROL)
#ifdef CONFIG_SPL_BUILD
int clk_get_by_index(struct udevice *dev, int index, struct clk *clk)
{ {
struct clk_ops *ops = clk_get_ops(dev); int ret;
u32 cell[2];
if (!ops->set_rate) if (index != 0)
return -ENOSYS; return -ENOSYS;
assert(clk);
return ops->set_rate(dev, rate); ret = uclass_get_device(UCLASS_CLK, 0, &clk->dev);
if (ret)
return ret;
ret = fdtdec_get_int_array(gd->fdt_blob, dev->of_offset, "clocks",
cell, 2);
if (ret)
return ret;
clk->id = cell[1];
return 0;
} }
int clk_enable(struct udevice *dev, int periph) int clk_get_by_name(struct udevice *dev, const char *name, struct clk *clk)
{ {
struct clk_ops *ops = clk_get_ops(dev);
if (!ops->enable)
return -ENOSYS; return -ENOSYS;
return ops->enable(dev, periph);
} }
#else
ulong clk_get_periph_rate(struct udevice *dev, int periph) static int clk_of_xlate_default(struct clk *clk,
struct fdtdec_phandle_args *args)
{ {
struct clk_ops *ops = clk_get_ops(dev); debug("%s(clk=%p)\n", __func__, clk);
if (!ops->get_periph_rate) if (args->args_count > 1) {
return -ENOSYS; debug("Invaild args_count: %d\n", args->args_count);
return -EINVAL;
return ops->get_periph_rate(dev, periph);
} }
ulong clk_set_periph_rate(struct udevice *dev, int periph, ulong rate) if (args->args_count)
{ clk->id = args->args[0];
struct clk_ops *ops = clk_get_ops(dev); else
clk->id = 0;
if (!ops->set_periph_rate)
return -ENOSYS;
return ops->set_periph_rate(dev, periph, rate); return 0;
} }
#if CONFIG_IS_ENABLED(OF_CONTROL) int clk_get_by_index(struct udevice *dev, int index, struct clk *clk)
int clk_get_by_index(struct udevice *dev, int index, struct udevice **clk_devp)
{ {
int ret; int ret;
#ifdef CONFIG_SPL_BUILD
u32 cell[2];
if (index != 0)
return -ENOSYS;
assert(*clk_devp);
ret = uclass_get_device(UCLASS_CLK, 0, clk_devp);
if (ret)
return ret;
ret = fdtdec_get_int_array(gd->fdt_blob, dev->of_offset, "clocks",
cell, 2);
if (ret)
return ret;
return cell[1];
#else
struct fdtdec_phandle_args args; struct fdtdec_phandle_args args;
struct udevice *dev_clk;
struct clk_ops *ops;
debug("%s(dev=%p, index=%d, clk=%p)\n", __func__, dev, index, clk);
assert(*clk_devp); assert(clk);
ret = fdtdec_parse_phandle_with_args(gd->fdt_blob, dev->of_offset, ret = fdtdec_parse_phandle_with_args(gd->fdt_blob, dev->of_offset,
"clocks", "#clock-cells", 0, index, "clocks", "#clock-cells", 0, index,
&args); &args);
...@@ -95,16 +82,117 @@ int clk_get_by_index(struct udevice *dev, int index, struct udevice **clk_devp) ...@@ -95,16 +82,117 @@ int clk_get_by_index(struct udevice *dev, int index, struct udevice **clk_devp)
return ret; return ret;
} }
ret = uclass_get_device_by_of_offset(UCLASS_CLK, args.node, clk_devp); ret = uclass_get_device_by_of_offset(UCLASS_CLK, args.node, &dev_clk);
if (ret) { if (ret) {
debug("%s: uclass_get_device_by_of_offset failed: err=%d\n", debug("%s: uclass_get_device_by_of_offset failed: err=%d\n",
__func__, ret); __func__, ret);
return ret; return ret;
} }
return args.args_count > 0 ? args.args[0] : 0; ops = clk_dev_ops(dev_clk);
#endif
if (ops->of_xlate)
ret = ops->of_xlate(clk, &args);
else
ret = clk_of_xlate_default(clk, &args);
if (ret) {
debug("of_xlate() failed: %d\n", ret);
return ret;
}
return clk_request(dev_clk, clk);
}
int clk_get_by_name(struct udevice *dev, const char *name, struct clk *clk)
{
int index;
debug("%s(dev=%p, name=%s, clk=%p)\n", __func__, dev, name, clk);
index = fdt_find_string(gd->fdt_blob, dev->of_offset, "clock-names",
name);
if (index < 0) {
debug("fdt_find_string() failed: %d\n", index);
return index;
}
return clk_get_by_index(dev, index, clk);
} }
#endif #endif
#endif
int clk_request(struct udevice *dev, struct clk *clk)
{
struct clk_ops *ops = clk_dev_ops(dev);
debug("%s(dev=%p, clk=%p)\n", __func__, dev, clk);
clk->dev = dev;
if (!ops->request)
return 0;
return ops->request(clk);
}
int clk_free(struct clk *clk)
{
struct clk_ops *ops = clk_dev_ops(clk->dev);
debug("%s(clk=%p)\n", __func__, clk);
if (!ops->free)
return 0;
return ops->free(clk);
}
ulong clk_get_rate(struct clk *clk)
{
struct clk_ops *ops = clk_dev_ops(clk->dev);
debug("%s(clk=%p)\n", __func__, clk);
if (!ops->get_rate)
return -ENOSYS;
return ops->get_rate(clk);
}
ulong clk_set_rate(struct clk *clk, ulong rate)
{
struct clk_ops *ops = clk_dev_ops(clk->dev);
debug("%s(clk=%p, rate=%lu)\n", __func__, clk, rate);
if (!ops->set_rate)
return -ENOSYS;
return ops->set_rate(clk, rate);
}
int clk_enable(struct clk *clk)
{
struct clk_ops *ops = clk_dev_ops(clk->dev);
debug("%s(clk=%p)\n", __func__, clk);
if (!ops->enable)
return -ENOSYS;
return ops->enable(clk);
}
int clk_disable(struct clk *clk)
{
struct clk_ops *ops = clk_dev_ops(clk->dev);
debug("%s(clk=%p)\n", __func__, clk);
if (!ops->disable)
return -ENOSYS;
return ops->disable(clk);
}
UCLASS_DRIVER(clk) = { UCLASS_DRIVER(clk) = {
.id = UCLASS_CLK, .id = UCLASS_CLK,
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
*/ */
#include <common.h> #include <common.h>
#include <clk.h> #include <clk-uclass.h>
#include <dm/device.h> #include <dm/device.h>
DECLARE_GLOBAL_DATA_PTR; DECLARE_GLOBAL_DATA_PTR;
...@@ -16,19 +16,16 @@ struct clk_fixed_rate { ...@@ -16,19 +16,16 @@ struct clk_fixed_rate {
#define to_clk_fixed_rate(dev) ((struct clk_fixed_rate *)dev_get_platdata(dev)) #define to_clk_fixed_rate(dev) ((struct clk_fixed_rate *)dev_get_platdata(dev))
static ulong clk_fixed_rate_get_rate(struct udevice *dev) static ulong clk_fixed_rate_get_rate(struct clk *clk)
{ {
return to_clk_fixed_rate(dev)->fixed_rate; if (clk->id != 0)
} return -EINVAL;
static ulong clk_fixed_rate_get_periph_rate(struct udevice *dev, int periph) return to_clk_fixed_rate(clk->dev)->fixed_rate;
{
return clk_fixed_rate_get_rate(dev);
} }
const struct clk_ops clk_fixed_rate_ops = { const struct clk_ops clk_fixed_rate_ops = {
.get_rate = clk_fixed_rate_get_rate, .get_rate = clk_fixed_rate_get_rate,
.get_periph_rate = clk_fixed_rate_get_periph_rate,
}; };
static int clk_fixed_rate_ofdata_to_platdata(struct udevice *dev) static int clk_fixed_rate_ofdata_to_platdata(struct udevice *dev)
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
*/ */
#include <common.h> #include <common.h>
#include <clk.h> #include <clk-uclass.h>
#include <dm.h> #include <dm.h>
#include <div64.h> #include <div64.h>
#include <wait_bit.h> #include <wait_bit.h>
...@@ -339,24 +339,17 @@ static void pic32_clk_init(struct udevice *dev) ...@@ -339,24 +339,17 @@ static void pic32_clk_init(struct udevice *dev)
pic32_mpll_init(priv); pic32_mpll_init(priv);
} }
static ulong pic32_clk_get_rate(struct udevice *dev) static ulong pic32_get_rate(struct clk *clk)
{ {
struct pic32_clk_priv *priv = dev_get_priv(dev); struct pic32_clk_priv *priv = dev_get_priv(clk->dev);
return pic32_get_cpuclk(priv);
}
static ulong pic32_get_periph_rate(struct udevice *dev, int periph)
{
struct pic32_clk_priv *priv = dev_get_priv(dev);
ulong rate; ulong rate;
switch (periph) { switch (clk->id) {
case PB1CLK ... PB7CLK: case PB1CLK ... PB7CLK:
rate = pic32_get_pbclk(priv, periph); rate = pic32_get_pbclk(priv, clk->id);
break; break;
case REF1CLK ... REF5CLK: case REF1CLK ... REF5CLK:
rate = pic32_get_refclk(priv, periph); rate = pic32_get_refclk(priv, clk->id);
break; break;
case PLLCLK: case PLLCLK:
rate = pic32_get_pll_rate(priv); rate = pic32_get_pll_rate(priv);
...@@ -372,15 +365,15 @@ static ulong pic32_get_periph_rate(struct udevice *dev, int periph) ...@@ -372,15 +365,15 @@ static ulong pic32_get_periph_rate(struct udevice *dev, int periph)
return rate; return rate;
} }
static ulong pic32_set_periph_rate(struct udevice *dev, int periph, ulong rate) static ulong pic32_set_rate(struct clk *clk, ulong rate)
{ {
struct pic32_clk_priv *priv = dev_get_priv(dev); struct pic32_clk_priv *priv = dev_get_priv(clk->dev);
ulong pll_hz; ulong pll_hz;
switch (periph) { switch (clk->id) {
case REF1CLK ... REF5CLK: case REF1CLK ... REF5CLK:
pll_hz = pic32_get_pll_rate(priv); pll_hz = pic32_get_pll_rate(priv);
pic32_set_refclk(priv, periph, pll_hz, rate, ROCLK_SRC_SPLL); pic32_set_refclk(priv, clk->id, pll_hz, rate, ROCLK_SRC_SPLL);
break; break;
default: default:
break; break;
...@@ -390,9 +383,8 @@ static ulong pic32_set_periph_rate(struct udevice *dev, int periph, ulong rate) ...@@ -390,9 +383,8 @@ static ulong pic32_set_periph_rate(struct udevice *dev, int periph, ulong rate)
} }
static struct clk_ops pic32_pic32_clk_ops = { static struct clk_ops pic32_pic32_clk_ops = {
.get_rate = pic32_clk_get_rate, .set_rate = pic32_set_rate,
.set_periph_rate = pic32_set_periph_rate, .get_rate = pic32_get_rate,
.get_periph_rate = pic32_get_periph_rate,
}; };
static int pic32_clk_probe(struct udevice *dev) static int pic32_clk_probe(struct udevice *dev)
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
*/ */
#include <common.h> #include <common.h>
#include <clk.h> #include <clk-uclass.h>
#include <dm.h> #include <dm.h>
#include <errno.h> #include <errno.h>
#include <syscon.h> #include <syscon.h>
...@@ -18,10 +18,6 @@ ...@@ -18,10 +18,6 @@
DECLARE_GLOBAL_DATA_PTR; DECLARE_GLOBAL_DATA_PTR;
struct rk3036_clk_plat {
enum rk_clk_id clk_id;
};
struct rk3036_clk_priv { struct rk3036_clk_priv {
struct rk3036_cru *cru; struct rk3036_cru *cru;
ulong rate; ulong rate;
...@@ -315,31 +311,30 @@ static ulong rockchip_mmc_set_clk(struct rk3036_cru *cru, uint clk_general_rate, ...@@ -315,31 +311,30 @@ static ulong rockchip_mmc_set_clk(struct rk3036_cru *cru, uint clk_general_rate,
return rockchip_mmc_get_clk(cru, clk_general_rate, periph); return rockchip_mmc_get_clk(cru, clk_general_rate, periph);
} }
static ulong rk3036_clk_get_rate(struct udevice *dev) static ulong rk3036_clk_get_rate(struct clk *clk)
{ {
struct rk3036_clk_plat *plat = dev_get_platdata(dev); struct rk3036_clk_priv *priv = dev_get_priv(clk->dev);
struct rk3036_clk_priv *priv = dev_get_priv(dev);
debug("%s\n", dev->name); switch (clk->id) {
return rkclk_pll_get_rate(priv->cru, plat->clk_id); case 0 ... 63:
return rkclk_pll_get_rate(priv->cru, clk->id);
default:
return -ENOENT;
} }
static ulong rk3036_clk_set_rate(struct udevice *dev, ulong rate)
{
debug("%s\n", dev->name);
return 0;
} }
static ulong rk3036_set_periph_rate(struct udevice *dev, int periph, ulong rate) static ulong rk3036_clk_set_rate(struct clk *clk, ulong rate)
{ {
struct rk3036_clk_priv *priv = dev_get_priv(dev); struct rk3036_clk_priv *priv = dev_get_priv(clk->dev);
ulong new_rate; ulong new_rate, gclk_rate;
switch (periph) { gclk_rate = rkclk_pll_get_rate(priv->cru, CLK_GENERAL);
switch (clk->id) {
case 0 ... 63:
return 0;
case HCLK_EMMC: case HCLK_EMMC:
new_rate = rockchip_mmc_set_clk(priv->cru, clk_get_rate(dev), new_rate = rockchip_mmc_set_clk(priv->cru, gclk_rate,
periph, rate); clk->id, rate);
break; break;
default: default:
return -ENOENT; return -ENOENT;
...@@ -351,60 +346,21 @@ static ulong rk3036_set_periph_rate(struct udevice *dev, int periph, ulong rate) ...@@ -351,60 +346,21 @@ static ulong rk3036_set_periph_rate(struct udevice *dev, int periph, ulong rate)
static struct clk_ops rk3036_clk_ops = { static struct clk_ops rk3036_clk_ops = {
.get_rate = rk3036_clk_get_rate, .get_rate = rk3036_clk_get_rate,
.set_rate = rk3036_clk_set_rate, .set_rate = rk3036_clk_set_rate,
.set_periph_rate = rk3036_set_periph_rate,
}; };
static int rk3036_clk_probe(struct udevice *dev) static int rk3036_clk_probe(struct udevice *dev)
{ {
struct rk3036_clk_plat *plat = dev_get_platdata(dev);
struct rk3036_clk_priv *priv = dev_get_priv(dev); struct rk3036_clk_priv *priv = dev_get_priv(dev);
if (plat->clk_id != CLK_OSC) {
struct rk3036_clk_priv *parent_priv = dev_get_priv(dev->parent);
priv->cru = parent_priv->cru;
return 0;
}
priv->cru = (struct rk3036_cru *)dev_get_addr(dev); priv->cru = (struct rk3036_cru *)dev_get_addr(dev);
rkclk_init(priv->cru); rkclk_init(priv->cru);
return 0; return 0;
} }
static const char *const clk_name[] = {
"osc",
"apll",
"dpll",
"cpll",
"gpll",
"mpll",
};
static int rk3036_clk_bind(struct udevice *dev) static int rk3036_clk_bind(struct udevice *dev)
{ {
struct rk3036_clk_plat *plat = dev_get_platdata(dev); int ret;
int pll, ret;
/* We only need to set up the root clock */
if (dev->of_offset == -1) {
plat->clk_id = CLK_OSC;
return 0;
}
/* Create devices for P main clocks */
for (pll = 1; pll < CLK_COUNT; pll++) {
struct udevice *child;
struct rk3036_clk_plat *cplat;
debug("%s %s\n", __func__, clk_name[pll]);
ret = device_bind_driver(dev, "clk_rk3036", clk_name[pll],
&child);
if (ret)
return ret;
cplat = dev_get_platdata(child);
cplat->clk_id = pll;
}
/* The reset driver does not have a device node, so bind it here */ /* The reset driver does not have a device node, so bind it here */
ret = device_bind_driver(gd->dm_root, "rk3036_sysreset", "reset", &dev); ret = device_bind_driver(gd->dm_root, "rk3036_sysreset", "reset", &dev);
...@@ -424,7 +380,6 @@ U_BOOT_DRIVER(clk_rk3036) = { ...@@ -424,7 +380,6 @@ U_BOOT_DRIVER(clk_rk3036) = {
.id = UCLASS_CLK, .id = UCLASS_CLK,
.of_match = rk3036_clk_ids, .of_match = rk3036_clk_ids,
.priv_auto_alloc_size = sizeof(struct rk3036_clk_priv), .priv_auto_alloc_size = sizeof(struct rk3036_clk_priv),
.platdata_auto_alloc_size = sizeof(struct rk3036_clk_plat),
.ops = &rk3036_clk_ops, .ops = &rk3036_clk_ops,
.bind = rk3036_clk_bind, .bind = rk3036_clk_bind,
.probe = rk3036_clk_probe, .probe = rk3036_clk_probe,
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
*/ */
#include <common.h> #include <common.h>
#include <clk.h> #include <clk-uclass.h>
#include <dm.h> #include <dm.h>
#include <errno.h> #include <errno.h>
#include <syscon.h> #include <syscon.h>
...@@ -21,10 +21,6 @@ ...@@ -21,10 +21,6 @@
DECLARE_GLOBAL_DATA_PTR; DECLARE_GLOBAL_DATA_PTR;
struct rk3288_clk_plat {
enum rk_clk_id clk_id;
};
struct rk3288_clk_priv { struct rk3288_clk_priv {
struct rk3288_grf *grf; struct rk3288_grf *grf;
struct rk3288_cru *cru; struct rk3288_cru *cru;
...@@ -135,34 +131,18 @@ static const struct pll_div apll_init_cfg = PLL_DIVISORS(APLL_HZ, 1, 1); ...@@ -135,34 +131,18 @@ static const struct pll_div apll_init_cfg = PLL_DIVISORS(APLL_HZ, 1, 1);
static const struct pll_div gpll_init_cfg = PLL_DIVISORS(GPLL_HZ, 2, 2); static const struct pll_div gpll_init_cfg = PLL_DIVISORS(GPLL_HZ, 2, 2);
static const struct pll_div cpll_init_cfg = PLL_DIVISORS(CPLL_HZ, 1, 2); static const struct pll_div cpll_init_cfg = PLL_DIVISORS(CPLL_HZ, 1, 2);
int rkclk_get_clk(enum rk_clk_id clk_id, struct udevice **devp)
{
struct udevice *dev;
for (uclass_find_first_device(UCLASS_CLK, &dev);
dev;
uclass_find_next_device(&dev)) {
struct rk3288_clk_plat *plat = dev_get_platdata(dev);
if (plat->clk_id == clk_id) {
*devp = dev;
return device_probe(dev);
}
}
return -ENODEV;
}
void *rockchip_get_cru(void) void *rockchip_get_cru(void)
{ {
struct rk3288_clk_priv *priv; struct rk3288_clk_priv *priv;
struct udevice *dev; struct udevice *dev;
int ret; int ret;
ret = rkclk_get_clk(CLK_GENERAL, &dev); ret = uclass_get_device(UCLASS_CLK, 0, &dev);
if (ret) if (ret)
return ERR_PTR(ret); return ERR_PTR(ret);
priv = dev_get_priv(dev); priv = dev_get_priv(dev);
return priv->cru; return priv->cru;
} }
...@@ -539,32 +519,6 @@ static uint32_t rkclk_pll_get_rate(struct rk3288_cru *cru, ...@@ -539,32 +519,6 @@ static uint32_t rkclk_pll_get_rate(struct rk3288_cru *cru,
} }
} }
static ulong rk3288_clk_get_rate(struct udevice *dev)
{
struct rk3288_clk_plat *plat = dev_get_platdata(dev);
struct rk3288_clk_priv *priv = dev_get_priv(dev);
debug("%s\n", dev->name);
return rkclk_pll_get_rate(priv->cru, plat->clk_id);
}
static ulong rk3288_clk_set_rate(struct udevice *dev, ulong rate)
{
struct rk3288_clk_plat *plat = dev_get_platdata(dev);
struct rk3288_clk_priv *priv = dev_get_priv(dev);
debug("%s\n", dev->name);
switch (plat->clk_id) {
case CLK_DDR:
rkclk_configure_ddr(priv->cru, priv->grf, rate);
break;
default:
return -ENOENT;
}
return 0;
}
static ulong rockchip_mmc_get_clk(struct rk3288_cru *cru, uint gclk_rate, static ulong rockchip_mmc_get_clk(struct rk3288_cru *cru, uint gclk_rate,
int periph) int periph)
{ {
...@@ -710,27 +664,25 @@ static ulong rockchip_spi_set_clk(struct rk3288_cru *cru, uint gclk_rate, ...@@ -710,27 +664,25 @@ static ulong rockchip_spi_set_clk(struct rk3288_cru *cru, uint gclk_rate,
return rockchip_spi_get_clk(cru, gclk_rate, periph); return rockchip_spi_get_clk(cru, gclk_rate, periph);
} }
static ulong rk3288_get_periph_rate(struct udevice *dev, int periph) static ulong rk3288_clk_get_rate(struct clk *clk)
{ {
struct rk3288_clk_priv *priv = dev_get_priv(dev); struct rk3288_clk_priv *priv = dev_get_priv(clk->dev);
struct udevice *gclk;
ulong new_rate, gclk_rate; ulong new_rate, gclk_rate;
int ret;
ret = rkclk_get_clk(CLK_GENERAL, &gclk); gclk_rate = rkclk_pll_get_rate(priv->cru, CLK_GENERAL);
if (ret) switch (clk->id) {
return ret; case 0 ... 63:
gclk_rate = clk_get_rate(gclk); new_rate = rkclk_pll_get_rate(priv->cru, clk->id);
switch (periph) { break;
case HCLK_EMMC: case HCLK_EMMC:
case HCLK_SDMMC: case HCLK_SDMMC:
case HCLK_SDIO0: case HCLK_SDIO0:
new_rate = rockchip_mmc_get_clk(priv->cru, gclk_rate, periph); new_rate = rockchip_mmc_get_clk(priv->cru, gclk_rate, clk->id);
break; break;
case SCLK_SPI0: case SCLK_SPI0:
case SCLK_SPI1: case SCLK_SPI1:
case SCLK_SPI2: case SCLK_SPI2:
new_rate = rockchip_spi_get_clk(priv->cru, gclk_rate, periph); new_rate = rockchip_spi_get_clk(priv->cru, gclk_rate, clk->id);
break; break;
case PCLK_I2C0: case PCLK_I2C0:
case PCLK_I2C1: case PCLK_I2C1:
...@@ -746,36 +698,34 @@ static ulong rk3288_get_periph_rate(struct udevice *dev, int periph) ...@@ -746,36 +698,34 @@ static ulong rk3288_get_periph_rate(struct udevice *dev, int periph)
return new_rate; return new_rate;
} }
static ulong rk3288_set_periph_rate(struct udevice *dev, int periph, ulong rate) static ulong rk3288_clk_set_rate(struct clk *clk, ulong rate)
{ {
struct rk3288_clk_priv *priv = dev_get_priv(dev); struct rk3288_clk_priv *priv = dev_get_priv(clk->dev);
struct rk3288_cru *cru = priv->cru; struct rk3288_cru *cru = priv->cru;
struct udevice *gclk;
ulong new_rate, gclk_rate; ulong new_rate, gclk_rate;
int ret;
ret = rkclk_get_clk(CLK_GENERAL, &gclk); gclk_rate = rkclk_pll_get_rate(priv->cru, CLK_GENERAL);
if (ret) switch (clk->id) {
return ret; case CLK_DDR:
gclk_rate = clk_get_rate(gclk); new_rate = rkclk_configure_ddr(priv->cru, priv->grf, rate);
switch (periph) { break;
case HCLK_EMMC: case HCLK_EMMC:
case HCLK_SDMMC: case HCLK_SDMMC:
case HCLK_SDIO0: case HCLK_SDIO0:
new_rate = rockchip_mmc_set_clk(cru, gclk_rate, periph, rate); new_rate = rockchip_mmc_set_clk(cru, gclk_rate, clk->id, rate);
break; break;
case SCLK_SPI0: case SCLK_SPI0:
case SCLK_SPI1: case SCLK_SPI1:
case SCLK_SPI2: case SCLK_SPI2:
new_rate = rockchip_spi_set_clk(cru, gclk_rate, periph, rate); new_rate = rockchip_spi_set_clk(cru, gclk_rate, clk->id, rate);
break; break;
#ifndef CONFIG_SPL_BUILD #ifndef CONFIG_SPL_BUILD
case SCLK_MAC: case SCLK_MAC:
new_rate = rockchip_mac_set_clk(priv->cru, periph, rate); new_rate = rockchip_mac_set_clk(priv->cru, clk->id, rate);
break; break;
case DCLK_VOP0: case DCLK_VOP0:
case DCLK_VOP1: case DCLK_VOP1:
new_rate = rockchip_vop_set_clk(cru, priv->grf, periph, rate); new_rate = rockchip_vop_set_clk(cru, priv->grf, clk->id, rate);
break; break;
case SCLK_EDP_24M: case SCLK_EDP_24M:
/* clk_edp_24M source: 24M */ /* clk_edp_24M source: 24M */
...@@ -795,7 +745,7 @@ static ulong rk3288_set_periph_rate(struct udevice *dev, int periph, ulong rate) ...@@ -795,7 +745,7 @@ static ulong rk3288_set_periph_rate(struct udevice *dev, int periph, ulong rate)
div = CPLL_HZ / rate; div = CPLL_HZ / rate;
assert((div - 1 < 64) && (div * rate == CPLL_HZ)); assert((div - 1 < 64) && (div * rate == CPLL_HZ));
switch (periph) { switch (clk->id) {
case ACLK_VOP0: case ACLK_VOP0:
rk_clrsetreg(&cru->cru_clksel_con[31], rk_clrsetreg(&cru->cru_clksel_con[31],
3 << 6 | 0x1f << 0, 3 << 6 | 0x1f << 0,
...@@ -831,22 +781,12 @@ static ulong rk3288_set_periph_rate(struct udevice *dev, int periph, ulong rate) ...@@ -831,22 +781,12 @@ static ulong rk3288_set_periph_rate(struct udevice *dev, int periph, ulong rate)
static struct clk_ops rk3288_clk_ops = { static struct clk_ops rk3288_clk_ops = {
.get_rate = rk3288_clk_get_rate, .get_rate = rk3288_clk_get_rate,
.set_rate = rk3288_clk_set_rate, .set_rate = rk3288_clk_set_rate,
.set_periph_rate = rk3288_set_periph_rate,
.get_periph_rate = rk3288_get_periph_rate,
}; };
static int rk3288_clk_probe(struct udevice *dev) static int rk3288_clk_probe(struct udevice *dev)
{ {
struct rk3288_clk_plat *plat = dev_get_platdata(dev);
struct rk3288_clk_priv *priv = dev_get_priv(dev); struct rk3288_clk_priv *priv = dev_get_priv(dev);
if (plat->clk_id != CLK_OSC) {
struct rk3288_clk_priv *parent_priv = dev_get_priv(dev->parent);
priv->cru = parent_priv->cru;
priv->grf = parent_priv->grf;
return 0;
}
priv->cru = (struct rk3288_cru *)dev_get_addr(dev); priv->cru = (struct rk3288_cru *)dev_get_addr(dev);
priv->grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF); priv->grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF);
#ifdef CONFIG_SPL_BUILD #ifdef CONFIG_SPL_BUILD
...@@ -856,39 +796,9 @@ static int rk3288_clk_probe(struct udevice *dev) ...@@ -856,39 +796,9 @@ static int rk3288_clk_probe(struct udevice *dev)
return 0; return 0;
} }
static const char *const clk_name[CLK_COUNT] = {
"osc",
"apll",
"dpll",
"cpll",
"gpll",
"npll",
};
static int rk3288_clk_bind(struct udevice *dev) static int rk3288_clk_bind(struct udevice *dev)
{ {
struct rk3288_clk_plat *plat = dev_get_platdata(dev); int ret;
int pll, ret;
/* We only need to set up the root clock */
if (dev->of_offset == -1) {
plat->clk_id = CLK_OSC;
return 0;
}
/* Create devices for P main clocks */
for (pll = 1; pll < CLK_COUNT; pll++) {
struct udevice *child;
struct rk3288_clk_plat *cplat;
debug("%s %s\n", __func__, clk_name[pll]);
ret = device_bind_driver(dev, "clk_rk3288", clk_name[pll],
&child);
if (ret)
return ret;
cplat = dev_get_platdata(child);
cplat->clk_id = pll;
}
/* The reset driver does not have a device node, so bind it here */ /* The reset driver does not have a device node, so bind it here */
ret = device_bind_driver(gd->dm_root, "rk3288_sysreset", "reset", &dev); ret = device_bind_driver(gd->dm_root, "rk3288_sysreset", "reset", &dev);
...@@ -908,7 +818,6 @@ U_BOOT_DRIVER(clk_rk3288) = { ...@@ -908,7 +818,6 @@ U_BOOT_DRIVER(clk_rk3288) = {
.id = UCLASS_CLK, .id = UCLASS_CLK,
.of_match = rk3288_clk_ids, .of_match = rk3288_clk_ids,
.priv_auto_alloc_size = sizeof(struct rk3288_clk_priv), .priv_auto_alloc_size = sizeof(struct rk3288_clk_priv),
.platdata_auto_alloc_size = sizeof(struct rk3288_clk_plat),
.ops = &rk3288_clk_ops, .ops = &rk3288_clk_ops,
.bind = rk3288_clk_bind, .bind = rk3288_clk_bind,
.probe = rk3288_clk_probe, .probe = rk3288_clk_probe,
......
...@@ -5,61 +5,63 @@ ...@@ -5,61 +5,63 @@
*/ */
#include <common.h> #include <common.h>
#include <clk.h> #include <clk-uclass.h>
#include <dm.h> #include <dm.h>
#include <errno.h> #include <errno.h>
#include <asm/test.h> #include <asm/clk.h>
struct sandbox_clk_priv { struct sandbox_clk_priv {
ulong rate; ulong rate[SANDBOX_CLK_ID_COUNT];
ulong periph_rate[PERIPH_ID_COUNT]; bool enabled[SANDBOX_CLK_ID_COUNT];
}; };
static ulong sandbox_clk_get_rate(struct udevice *dev) static ulong sandbox_clk_get_rate(struct clk *clk)
{ {
struct sandbox_clk_priv *priv = dev_get_priv(dev); struct sandbox_clk_priv *priv = dev_get_priv(clk->dev);
if (clk->id < 0 || clk->id >= SANDBOX_CLK_ID_COUNT)
return -EINVAL;
return priv->rate; return priv->rate[clk->id];
} }
static ulong sandbox_clk_set_rate(struct udevice *dev, ulong rate) static ulong sandbox_clk_set_rate(struct clk *clk, ulong rate)
{ {
struct sandbox_clk_priv *priv = dev_get_priv(dev); struct sandbox_clk_priv *priv = dev_get_priv(clk->dev);
ulong old_rate;
if (clk->id < 0 || clk->id >= SANDBOX_CLK_ID_COUNT)
return -EINVAL;
if (!rate) if (!rate)
return -EINVAL; return -EINVAL;
priv->rate = rate;
return 0;
}
static ulong sandbox_get_periph_rate(struct udevice *dev, int periph) old_rate = priv->rate[clk->id];
{ priv->rate[clk->id] = rate;
struct sandbox_clk_priv *priv = dev_get_priv(dev);
if (periph < PERIPH_ID_FIRST || periph >= PERIPH_ID_COUNT) return old_rate;
return -EINVAL;
return priv->periph_rate[periph];
} }
static ulong sandbox_set_periph_rate(struct udevice *dev, int periph, static int sandbox_clk_enable(struct clk *clk)
ulong rate)
{ {
struct sandbox_clk_priv *priv = dev_get_priv(dev); struct sandbox_clk_priv *priv = dev_get_priv(clk->dev);
ulong old_rate;
if (periph < PERIPH_ID_FIRST || periph >= PERIPH_ID_COUNT) if (clk->id < 0 || clk->id >= SANDBOX_CLK_ID_COUNT)
return -EINVAL; return -EINVAL;
old_rate = priv->periph_rate[periph];
priv->periph_rate[periph] = rate;
return old_rate; priv->enabled[clk->id] = true;
return 0;
} }
static int sandbox_clk_probe(struct udevice *dev) static int sandbox_clk_disable(struct clk *clk)
{ {
struct sandbox_clk_priv *priv = dev_get_priv(dev); struct sandbox_clk_priv *priv = dev_get_priv(clk->dev);
if (clk->id < 0 || clk->id >= SANDBOX_CLK_ID_COUNT)
return -EINVAL;
priv->rate = SANDBOX_CLK_RATE; priv->enabled[clk->id] = false;
return 0; return 0;
} }
...@@ -67,8 +69,8 @@ static int sandbox_clk_probe(struct udevice *dev) ...@@ -67,8 +69,8 @@ static int sandbox_clk_probe(struct udevice *dev)
static struct clk_ops sandbox_clk_ops = { static struct clk_ops sandbox_clk_ops = {
.get_rate = sandbox_clk_get_rate, .get_rate = sandbox_clk_get_rate,
.set_rate = sandbox_clk_set_rate, .set_rate = sandbox_clk_set_rate,
.get_periph_rate = sandbox_get_periph_rate, .enable = sandbox_clk_enable,
.set_periph_rate = sandbox_set_periph_rate, .disable = sandbox_clk_disable,
}; };
static const struct udevice_id sandbox_clk_ids[] = { static const struct udevice_id sandbox_clk_ids[] = {
...@@ -82,5 +84,24 @@ U_BOOT_DRIVER(clk_sandbox) = { ...@@ -82,5 +84,24 @@ U_BOOT_DRIVER(clk_sandbox) = {
.of_match = sandbox_clk_ids, .of_match = sandbox_clk_ids,
.ops = &sandbox_clk_ops, .ops = &sandbox_clk_ops,
.priv_auto_alloc_size = sizeof(struct sandbox_clk_priv), .priv_auto_alloc_size = sizeof(struct sandbox_clk_priv),
.probe = sandbox_clk_probe,
}; };
ulong sandbox_clk_query_rate(struct udevice *dev, int id)
{
struct sandbox_clk_priv *priv = dev_get_priv(dev);
if (id < 0 || id >= SANDBOX_CLK_ID_COUNT)
return -EINVAL;
return priv->rate[id];
}
int sandbox_clk_query_enable(struct udevice *dev, int id)
{
struct sandbox_clk_priv *priv = dev_get_priv(dev);
if (id < 0 || id >= SANDBOX_CLK_ID_COUNT)
return -EINVAL;
return priv->enabled[id];
}
/*
* Copyright (c) 2016, NVIDIA CORPORATION.
*
* SPDX-License-Identifier: GPL-2.0
*/
#include <common.h>
#include <dm.h>
#include <clk.h>
#include <asm/clk.h>
struct sandbox_clk_test {
struct clk clks[SANDBOX_CLK_TEST_ID_COUNT];
};
static const char * const sandbox_clk_test_names[] = {
[SANDBOX_CLK_TEST_ID_FIXED] = "fixed",
[SANDBOX_CLK_TEST_ID_SPI] = "spi",
[SANDBOX_CLK_TEST_ID_I2C] = "i2c",
};
int sandbox_clk_test_get(struct udevice *dev)
{
struct sandbox_clk_test *sbct = dev_get_priv(dev);
int i, ret;
for (i = 0; i < SANDBOX_CLK_TEST_ID_COUNT; i++) {
ret = clk_get_by_name(dev, sandbox_clk_test_names[i],
&sbct->clks[i]);
if (ret)
return ret;
}
return 0;
}
ulong sandbox_clk_test_get_rate(struct udevice *dev, int id)
{
struct sandbox_clk_test *sbct = dev_get_priv(dev);
if (id < 0 || id >= SANDBOX_CLK_TEST_ID_COUNT)
return -EINVAL;
return clk_get_rate(&sbct->clks[id]);
}
ulong sandbox_clk_test_set_rate(struct udevice *dev, int id, ulong rate)
{
struct sandbox_clk_test *sbct = dev_get_priv(dev);
if (id < 0 || id >= SANDBOX_CLK_TEST_ID_COUNT)
return -EINVAL;
return clk_set_rate(&sbct->clks[id], rate);
}
int sandbox_clk_test_enable(struct udevice *dev, int id)
{
struct sandbox_clk_test *sbct = dev_get_priv(dev);
if (id < 0 || id >= SANDBOX_CLK_TEST_ID_COUNT)
return -EINVAL;
return clk_enable(&sbct->clks[id]);
}
int sandbox_clk_test_disable(struct udevice *dev, int id)
{
struct sandbox_clk_test *sbct = dev_get_priv(dev);
if (id < 0 || id >= SANDBOX_CLK_TEST_ID_COUNT)
return -EINVAL;
return clk_disable(&sbct->clks[id]);
}
int sandbox_clk_test_free(struct udevice *dev)
{
struct sandbox_clk_test *sbct = dev_get_priv(dev);
int i, ret;
for (i = 0; i < SANDBOX_CLK_TEST_ID_COUNT; i++) {
ret = clk_free(&sbct->clks[i]);
if (ret)
return ret;
}
return 0;
}
static const struct udevice_id sandbox_clk_test_ids[] = {
{ .compatible = "sandbox,clk-test" },
{ }
};
U_BOOT_DRIVER(sandbox_clk_test) = {
.name = "sandbox_clk_test",
.id = UCLASS_MISC,
.of_match = sandbox_clk_test_ids,
.priv_auto_alloc_size = sizeof(struct sandbox_clk_test),
};
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
#include <common.h> #include <common.h>
#include <dm.h> #include <dm.h>
#include <errno.h> #include <errno.h>
#include <clk.h> #include <clk-uclass.h>
#include <asm/io.h> #include <asm/io.h>
#include <dt-bindings/clock/exynos7420-clk.h> #include <dt-bindings/clock/exynos7420-clk.h>
#include "clk-pll.h" #include "clk-pll.h"
...@@ -67,11 +67,11 @@ struct exynos7420_clk_top0_priv { ...@@ -67,11 +67,11 @@ struct exynos7420_clk_top0_priv {
unsigned long sclk_uart2; unsigned long sclk_uart2;
}; };
static ulong exynos7420_topc_get_periph_rate(struct udevice *dev, int periph) static ulong exynos7420_topc_get_rate(struct clk *clk)
{ {
struct exynos7420_clk_topc_priv *priv = dev_get_priv(dev); struct exynos7420_clk_topc_priv *priv = dev_get_priv(clk->dev);
switch (periph) { switch (clk->id) {
case DOUT_SCLK_BUS0_PLL: case DOUT_SCLK_BUS0_PLL:
case SCLK_BUS0_PLL_A: case SCLK_BUS0_PLL_A:
case SCLK_BUS0_PLL_B: case SCLK_BUS0_PLL_B:
...@@ -86,14 +86,14 @@ static ulong exynos7420_topc_get_periph_rate(struct udevice *dev, int periph) ...@@ -86,14 +86,14 @@ static ulong exynos7420_topc_get_periph_rate(struct udevice *dev, int periph)
} }
static struct clk_ops exynos7420_clk_topc_ops = { static struct clk_ops exynos7420_clk_topc_ops = {
.get_periph_rate = exynos7420_topc_get_periph_rate, .get_rate = exynos7420_topc_get_rate,
}; };
static int exynos7420_clk_topc_probe(struct udevice *dev) static int exynos7420_clk_topc_probe(struct udevice *dev)
{ {
struct exynos7420_clk_topc_priv *priv = dev_get_priv(dev); struct exynos7420_clk_topc_priv *priv = dev_get_priv(dev);
struct exynos7420_clk_cmu_topc *topc; struct exynos7420_clk_cmu_topc *topc;
struct udevice *clk_dev; struct clk in_clk;
unsigned long rate; unsigned long rate;
fdt_addr_t base; fdt_addr_t base;
int ret; int ret;
...@@ -105,9 +105,9 @@ static int exynos7420_clk_topc_probe(struct udevice *dev) ...@@ -105,9 +105,9 @@ static int exynos7420_clk_topc_probe(struct udevice *dev)
topc = (struct exynos7420_clk_cmu_topc *)base; topc = (struct exynos7420_clk_cmu_topc *)base;
priv->topc = topc; priv->topc = topc;
ret = clk_get_by_index(dev, 0, &clk_dev); ret = clk_get_by_index(dev, 0, &in_clk);
if (ret >= 0) if (ret >= 0)
priv->fin_freq = clk_get_rate(clk_dev); priv->fin_freq = clk_get_rate(&in_clk);
rate = pll145x_get_rate(&topc->bus0_pll_con[0], priv->fin_freq); rate = pll145x_get_rate(&topc->bus0_pll_con[0], priv->fin_freq);
if (readl(&topc->mux_sel[1]) & (1 << 16)) if (readl(&topc->mux_sel[1]) & (1 << 16))
...@@ -122,12 +122,12 @@ static int exynos7420_clk_topc_probe(struct udevice *dev) ...@@ -122,12 +122,12 @@ static int exynos7420_clk_topc_probe(struct udevice *dev)
return 0; return 0;
} }
static ulong exynos7420_top0_get_periph_rate(struct udevice *dev, int periph) static ulong exynos7420_top0_get_rate(struct clk *clk)
{ {
struct exynos7420_clk_top0_priv *priv = dev_get_priv(dev); struct exynos7420_clk_top0_priv *priv = dev_get_priv(clk->dev);
struct exynos7420_clk_cmu_top0 *top0 = priv->top0; struct exynos7420_clk_cmu_top0 *top0 = priv->top0;
switch (periph) { switch (clk->id) {
case CLK_SCLK_UART2: case CLK_SCLK_UART2:
return priv->mout_top0_bus0_pll_half / return priv->mout_top0_bus0_pll_half /
DIVIDER(&top0->div_peric[3], 8, 0xf); DIVIDER(&top0->div_peric[3], 8, 0xf);
...@@ -137,14 +137,14 @@ static ulong exynos7420_top0_get_periph_rate(struct udevice *dev, int periph) ...@@ -137,14 +137,14 @@ static ulong exynos7420_top0_get_periph_rate(struct udevice *dev, int periph)
} }
static struct clk_ops exynos7420_clk_top0_ops = { static struct clk_ops exynos7420_clk_top0_ops = {
.get_periph_rate = exynos7420_top0_get_periph_rate, .get_rate = exynos7420_top0_get_rate,
}; };
static int exynos7420_clk_top0_probe(struct udevice *dev) static int exynos7420_clk_top0_probe(struct udevice *dev)
{ {
struct exynos7420_clk_top0_priv *priv; struct exynos7420_clk_top0_priv *priv;
struct exynos7420_clk_cmu_top0 *top0; struct exynos7420_clk_cmu_top0 *top0;
struct udevice *clk_dev; struct clk in_clk;
fdt_addr_t base; fdt_addr_t base;
int ret; int ret;
...@@ -159,10 +159,10 @@ static int exynos7420_clk_top0_probe(struct udevice *dev) ...@@ -159,10 +159,10 @@ static int exynos7420_clk_top0_probe(struct udevice *dev)
top0 = (struct exynos7420_clk_cmu_top0 *)base; top0 = (struct exynos7420_clk_cmu_top0 *)base;
priv->top0 = top0; priv->top0 = top0;
ret = clk_get_by_index(dev, 1, &clk_dev); ret = clk_get_by_index(dev, 1, &in_clk);
if (ret >= 0) { if (ret >= 0) {
priv->mout_top0_bus0_pll_half = priv->mout_top0_bus0_pll_half =
clk_get_periph_rate(clk_dev, ret); clk_get_rate(&in_clk);
if (readl(&top0->mux_sel[1]) & (1 << 16)) if (readl(&top0->mux_sel[1]) & (1 << 16))
priv->mout_top0_bus0_pll_half >>= 1; priv->mout_top0_bus0_pll_half >>= 1;
} }
...@@ -170,18 +170,18 @@ static int exynos7420_clk_top0_probe(struct udevice *dev) ...@@ -170,18 +170,18 @@ static int exynos7420_clk_top0_probe(struct udevice *dev)
return 0; return 0;
} }
static ulong exynos7420_peric1_get_periph_rate(struct udevice *dev, int periph) static ulong exynos7420_peric1_get_rate(struct clk *clk)
{ {
struct udevice *clk_dev; struct clk in_clk;
unsigned int ret; unsigned int ret;
unsigned long freq = 0; unsigned long freq = 0;
switch (periph) { switch (clk->id) {
case SCLK_UART2: case SCLK_UART2:
ret = clk_get_by_index(dev, 3, &clk_dev); ret = clk_get_by_index(clk->dev, 3, &in_clk);
if (ret < 0) if (ret < 0)
return ret; return ret;
freq = clk_get_periph_rate(clk_dev, ret); freq = clk_get_rate(&in_clk);
break; break;
} }
...@@ -189,7 +189,7 @@ static ulong exynos7420_peric1_get_periph_rate(struct udevice *dev, int periph) ...@@ -189,7 +189,7 @@ static ulong exynos7420_peric1_get_periph_rate(struct udevice *dev, int periph)
} }
static struct clk_ops exynos7420_clk_peric1_ops = { static struct clk_ops exynos7420_clk_peric1_ops = {
.get_periph_rate = exynos7420_peric1_get_periph_rate, .get_rate = exynos7420_peric1_get_rate,
}; };
static const struct udevice_id exynos7420_clk_topc_compat[] = { static const struct udevice_id exynos7420_clk_topc_compat[] = {
......
...@@ -9,14 +9,14 @@ ...@@ -9,14 +9,14 @@
#include <linux/bitops.h> #include <linux/bitops.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/sizes.h> #include <linux/sizes.h>
#include <clk.h> #include <clk-uclass.h>
#include <dm/device.h> #include <dm/device.h>
#include "clk-uniphier.h" #include "clk-uniphier.h"
static int uniphier_clk_enable(struct udevice *dev, int index) static int uniphier_clk_enable(struct clk *clk)
{ {
struct uniphier_clk_priv *priv = dev_get_priv(dev); struct uniphier_clk_priv *priv = dev_get_priv(clk->dev);
struct uniphier_clk_gate_data *gate = priv->socdata->gate; struct uniphier_clk_gate_data *gate = priv->socdata->gate;
unsigned int nr_gate = priv->socdata->nr_gate; unsigned int nr_gate = priv->socdata->nr_gate;
void __iomem *reg; void __iomem *reg;
...@@ -24,7 +24,7 @@ static int uniphier_clk_enable(struct udevice *dev, int index) ...@@ -24,7 +24,7 @@ static int uniphier_clk_enable(struct udevice *dev, int index)
int i; int i;
for (i = 0; i < nr_gate; i++) { for (i = 0; i < nr_gate; i++) {
if (gate[i].index != index) if (gate[i].index != clk->id)
continue; continue;
reg = priv->base + gate[i].reg; reg = priv->base + gate[i].reg;
...@@ -41,9 +41,9 @@ static int uniphier_clk_enable(struct udevice *dev, int index) ...@@ -41,9 +41,9 @@ static int uniphier_clk_enable(struct udevice *dev, int index)
return 0; return 0;
} }
static ulong uniphier_clk_get_rate(struct udevice *dev, int index) static ulong uniphier_clk_get_rate(struct clk *clk)
{ {
struct uniphier_clk_priv *priv = dev_get_priv(dev); struct uniphier_clk_priv *priv = dev_get_priv(clk->dev);
struct uniphier_clk_rate_data *rdata = priv->socdata->rate; struct uniphier_clk_rate_data *rdata = priv->socdata->rate;
unsigned int nr_rdata = priv->socdata->nr_rate; unsigned int nr_rdata = priv->socdata->nr_rate;
void __iomem *reg; void __iomem *reg;
...@@ -52,7 +52,7 @@ static ulong uniphier_clk_get_rate(struct udevice *dev, int index) ...@@ -52,7 +52,7 @@ static ulong uniphier_clk_get_rate(struct udevice *dev, int index)
int i; int i;
for (i = 0; i < nr_rdata; i++) { for (i = 0; i < nr_rdata; i++) {
if (rdata[i].index != index) if (rdata[i].index != clk->id)
continue; continue;
if (rdata[i].reg == UNIPHIER_CLK_RATE_IS_FIXED) if (rdata[i].reg == UNIPHIER_CLK_RATE_IS_FIXED)
...@@ -75,9 +75,9 @@ static ulong uniphier_clk_get_rate(struct udevice *dev, int index) ...@@ -75,9 +75,9 @@ static ulong uniphier_clk_get_rate(struct udevice *dev, int index)
return matched_rate; return matched_rate;
} }
static ulong uniphier_clk_set_rate(struct udevice *dev, int index, ulong rate) static ulong uniphier_clk_set_rate(struct clk *clk, ulong rate)
{ {
struct uniphier_clk_priv *priv = dev_get_priv(dev); struct uniphier_clk_priv *priv = dev_get_priv(clk->dev);
struct uniphier_clk_rate_data *rdata = priv->socdata->rate; struct uniphier_clk_rate_data *rdata = priv->socdata->rate;
unsigned int nr_rdata = priv->socdata->nr_rate; unsigned int nr_rdata = priv->socdata->nr_rate;
void __iomem *reg; void __iomem *reg;
...@@ -87,7 +87,7 @@ static ulong uniphier_clk_set_rate(struct udevice *dev, int index, ulong rate) ...@@ -87,7 +87,7 @@ static ulong uniphier_clk_set_rate(struct udevice *dev, int index, ulong rate)
/* first, decide the best match rate */ /* first, decide the best match rate */
for (i = 0; i < nr_rdata; i++) { for (i = 0; i < nr_rdata; i++) {
if (rdata[i].index != index) if (rdata[i].index != clk->id)
continue; continue;
if (rdata[i].reg == UNIPHIER_CLK_RATE_IS_FIXED) if (rdata[i].reg == UNIPHIER_CLK_RATE_IS_FIXED)
...@@ -105,7 +105,7 @@ static ulong uniphier_clk_set_rate(struct udevice *dev, int index, ulong rate) ...@@ -105,7 +105,7 @@ static ulong uniphier_clk_set_rate(struct udevice *dev, int index, ulong rate)
/* second, really set registers */ /* second, really set registers */
for (i = 0; i < nr_rdata; i++) { for (i = 0; i < nr_rdata; i++) {
if (rdata[i].index != index || rdata[i].rate != best_rate) if (rdata[i].index != clk->id || rdata[i].rate != best_rate)
continue; continue;
reg = priv->base + rdata[i].reg; reg = priv->base + rdata[i].reg;
...@@ -124,8 +124,8 @@ static ulong uniphier_clk_set_rate(struct udevice *dev, int index, ulong rate) ...@@ -124,8 +124,8 @@ static ulong uniphier_clk_set_rate(struct udevice *dev, int index, ulong rate)
const struct clk_ops uniphier_clk_ops = { const struct clk_ops uniphier_clk_ops = {
.enable = uniphier_clk_enable, .enable = uniphier_clk_enable,
.get_periph_rate = uniphier_clk_get_rate, .get_rate = uniphier_clk_get_rate,
.set_periph_rate = uniphier_clk_set_rate, .set_rate = uniphier_clk_set_rate,
}; };
int uniphier_clk_probe(struct udevice *dev) int uniphier_clk_probe(struct udevice *dev)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment