summaryrefslogtreecommitdiffstats
path: root/drivers/clk/clk_rk3288.c
diff options
context:
space:
mode:
authorStephen Warren <swarren@nvidia.com>2016-06-17 09:44:00 -0600
committerSimon Glass <sjg@chromium.org>2016-06-19 17:05:55 -0600
commit135aa95002646c46e89de93fa36adad1b010548f (patch)
treeb601e08f7d91c7e2cda127d59f8f81128d0cb1ac /drivers/clk/clk_rk3288.c
parent4581b717b1bf0fb04e7d9fcaf3d4c23d357154ac (diff)
downloadtalos-obmc-uboot-135aa95002646c46e89de93fa36adad1b010548f.tar.gz
talos-obmc-uboot-135aa95002646c46e89de93fa36adad1b010548f.zip
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: Stephen Warren <swarren@nvidia.com> Acked-by: Simon Glass <sjg@chromium.org>
Diffstat (limited to 'drivers/clk/clk_rk3288.c')
-rw-r--r--drivers/clk/clk_rk3288.c143
1 files changed, 26 insertions, 117 deletions
diff --git a/drivers/clk/clk_rk3288.c b/drivers/clk/clk_rk3288.c
index d88893c8ea..2285453e8d 100644
--- a/drivers/clk/clk_rk3288.c
+++ b/drivers/clk/clk_rk3288.c
@@ -5,7 +5,7 @@
*/
#include <common.h>
-#include <clk.h>
+#include <clk-uclass.h>
#include <dm.h>
#include <errno.h>
#include <syscon.h>
@@ -21,10 +21,6 @@
DECLARE_GLOBAL_DATA_PTR;
-struct rk3288_clk_plat {
- enum rk_clk_id clk_id;
-};
-
struct rk3288_clk_priv {
struct rk3288_grf *grf;
struct rk3288_cru *cru;
@@ -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 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)
{
struct rk3288_clk_priv *priv;
struct udevice *dev;
int ret;
- ret = rkclk_get_clk(CLK_GENERAL, &dev);
+ ret = uclass_get_device(UCLASS_CLK, 0, &dev);
if (ret)
return ERR_PTR(ret);
+
priv = dev_get_priv(dev);
+
return priv->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,
int periph)
{
@@ -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);
}
-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 udevice *gclk;
+ struct rk3288_clk_priv *priv = dev_get_priv(clk->dev);
ulong new_rate, gclk_rate;
- int ret;
- ret = rkclk_get_clk(CLK_GENERAL, &gclk);
- if (ret)
- return ret;
- gclk_rate = clk_get_rate(gclk);
- switch (periph) {
+ gclk_rate = rkclk_pll_get_rate(priv->cru, CLK_GENERAL);
+ switch (clk->id) {
+ case 0 ... 63:
+ new_rate = rkclk_pll_get_rate(priv->cru, clk->id);
+ break;
case HCLK_EMMC:
case HCLK_SDMMC:
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;
case SCLK_SPI0:
case SCLK_SPI1:
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;
case PCLK_I2C0:
case PCLK_I2C1:
@@ -746,36 +698,34 @@ static ulong rk3288_get_periph_rate(struct udevice *dev, int periph)
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 udevice *gclk;
ulong new_rate, gclk_rate;
- int ret;
- ret = rkclk_get_clk(CLK_GENERAL, &gclk);
- if (ret)
- return ret;
- gclk_rate = clk_get_rate(gclk);
- switch (periph) {
+ gclk_rate = rkclk_pll_get_rate(priv->cru, CLK_GENERAL);
+ switch (clk->id) {
+ case CLK_DDR:
+ new_rate = rkclk_configure_ddr(priv->cru, priv->grf, rate);
+ break;
case HCLK_EMMC:
case HCLK_SDMMC:
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;
case SCLK_SPI0:
case SCLK_SPI1:
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;
#ifndef CONFIG_SPL_BUILD
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;
case DCLK_VOP0:
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;
case SCLK_EDP_24M:
/* clk_edp_24M source: 24M */
@@ -795,7 +745,7 @@ static ulong rk3288_set_periph_rate(struct udevice *dev, int periph, ulong rate)
div = CPLL_HZ / rate;
assert((div - 1 < 64) && (div * rate == CPLL_HZ));
- switch (periph) {
+ switch (clk->id) {
case ACLK_VOP0:
rk_clrsetreg(&cru->cru_clksel_con[31],
3 << 6 | 0x1f << 0,
@@ -831,22 +781,12 @@ static ulong rk3288_set_periph_rate(struct udevice *dev, int periph, ulong rate)
static struct clk_ops rk3288_clk_ops = {
.get_rate = rk3288_clk_get_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)
{
- struct rk3288_clk_plat *plat = dev_get_platdata(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->grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF);
#ifdef CONFIG_SPL_BUILD
@@ -856,39 +796,9 @@ static int rk3288_clk_probe(struct udevice *dev)
return 0;
}
-static const char *const clk_name[CLK_COUNT] = {
- "osc",
- "apll",
- "dpll",
- "cpll",
- "gpll",
- "npll",
-};
-
static int rk3288_clk_bind(struct udevice *dev)
{
- struct rk3288_clk_plat *plat = dev_get_platdata(dev);
- 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;
- }
+ int ret;
/* The reset driver does not have a device node, so bind it here */
ret = device_bind_driver(gd->dm_root, "rk3288_sysreset", "reset", &dev);
@@ -908,7 +818,6 @@ U_BOOT_DRIVER(clk_rk3288) = {
.id = UCLASS_CLK,
.of_match = rk3288_clk_ids,
.priv_auto_alloc_size = sizeof(struct rk3288_clk_priv),
- .platdata_auto_alloc_size = sizeof(struct rk3288_clk_plat),
.ops = &rk3288_clk_ops,
.bind = rk3288_clk_bind,
.probe = rk3288_clk_probe,
OpenPOWER on IntegriCloud