diff options
Diffstat (limited to 'drivers/clk')
-rw-r--r-- | drivers/clk/Makefile | 1 | ||||
-rw-r--r-- | drivers/clk/clk-uclass.c | 202 | ||||
-rw-r--r-- | drivers/clk/clk_fixed_rate.c | 13 | ||||
-rw-r--r-- | drivers/clk/clk_pic32.c | 32 | ||||
-rw-r--r-- | drivers/clk/clk_rk3036.c | 83 | ||||
-rw-r--r-- | drivers/clk/clk_rk3288.c | 143 | ||||
-rw-r--r-- | drivers/clk/clk_sandbox.c | 85 | ||||
-rw-r--r-- | drivers/clk/clk_sandbox_test.c | 101 | ||||
-rw-r--r-- | drivers/clk/exynos/clk-exynos7420.c | 42 | ||||
-rw-r--r-- | drivers/clk/uniphier/clk-uniphier-core.c | 26 | ||||
-rw-r--r-- | drivers/clk/uniphier/clk-uniphier-mio.c | 1 |
11 files changed, 396 insertions, 333 deletions
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index 81fe600188c..f7a88912e06 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -9,6 +9,7 @@ obj-$(CONFIG_CLK) += clk-uclass.o clk_fixed_rate.o obj-$(CONFIG_ROCKCHIP_RK3036) += clk_rk3036.o obj-$(CONFIG_ROCKCHIP_RK3288) += clk_rk3288.o obj-$(CONFIG_SANDBOX) += clk_sandbox.o +obj-$(CONFIG_SANDBOX) += clk_sandbox_test.o obj-$(CONFIG_MACH_PIC32) += clk_pic32.o obj-$(CONFIG_CLK_UNIPHIER) += uniphier/ obj-$(CONFIG_CLK_EXYNOS) += exynos/ diff --git a/drivers/clk/clk-uclass.c b/drivers/clk/clk-uclass.c index b483c1ef33b..6e4d67220a1 100644 --- a/drivers/clk/clk-uclass.c +++ b/drivers/clk/clk-uclass.c @@ -1,91 +1,78 @@ /* * Copyright (C) 2015 Google, Inc * Written by Simon Glass <sjg@chromium.org> + * Copyright (c) 2016, NVIDIA CORPORATION. * * SPDX-License-Identifier: GPL-2.0+ */ #include <common.h> #include <clk.h> +#include <clk-uclass.h> #include <dm.h> #include <errno.h> -#include <dm/lists.h> -#include <dm/root.h> 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); - - if (!ops->get_rate) - return -ENOSYS; - - return ops->get_rate(dev); + return (struct clk_ops *)dev->driver->ops; } -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 ops->set_rate(dev, rate); + assert(clk); + 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 ops->enable(dev, periph); + return -ENOSYS; } - -ulong clk_get_periph_rate(struct udevice *dev, int periph) +#else +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) - return -ENOSYS; - - return ops->get_periph_rate(dev, periph); -} - -ulong clk_set_periph_rate(struct udevice *dev, int periph, ulong rate) -{ - struct clk_ops *ops = clk_get_ops(dev); + if (args->args_count > 1) { + debug("Invaild args_count: %d\n", args->args_count); + return -EINVAL; + } - if (!ops->set_periph_rate) - return -ENOSYS; + if (args->args_count) + clk->id = args->args[0]; + else + clk->id = 0; - 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 udevice **clk_devp) +int clk_get_by_index(struct udevice *dev, int index, struct clk *clk) { 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 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, "clocks", "#clock-cells", 0, index, &args); @@ -95,16 +82,117 @@ int clk_get_by_index(struct udevice *dev, int index, struct udevice **clk_devp) 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) { debug("%s: uclass_get_device_by_of_offset failed: err=%d\n", __func__, ret); return ret; } - return args.args_count > 0 ? args.args[0] : 0; -#endif + ops = clk_dev_ops(dev_clk); + + 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 + +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) = { .id = UCLASS_CLK, diff --git a/drivers/clk/clk_fixed_rate.c b/drivers/clk/clk_fixed_rate.c index 8beda9cb557..797e5379075 100644 --- a/drivers/clk/clk_fixed_rate.c +++ b/drivers/clk/clk_fixed_rate.c @@ -5,7 +5,7 @@ */ #include <common.h> -#include <clk.h> +#include <clk-uclass.h> #include <dm/device.h> DECLARE_GLOBAL_DATA_PTR; @@ -16,19 +16,16 @@ struct clk_fixed_rate { #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 clk_fixed_rate_get_rate(dev); + return to_clk_fixed_rate(clk->dev)->fixed_rate; } const struct clk_ops clk_fixed_rate_ops = { .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) diff --git a/drivers/clk/clk_pic32.c b/drivers/clk/clk_pic32.c index 5d883544d51..70ec3543cf9 100644 --- a/drivers/clk/clk_pic32.c +++ b/drivers/clk/clk_pic32.c @@ -6,7 +6,7 @@ */ #include <common.h> -#include <clk.h> +#include <clk-uclass.h> #include <dm.h> #include <div64.h> #include <wait_bit.h> @@ -339,24 +339,17 @@ static void pic32_clk_init(struct udevice *dev) 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); - - 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); + struct pic32_clk_priv *priv = dev_get_priv(clk->dev); ulong rate; - switch (periph) { + switch (clk->id) { case PB1CLK ... PB7CLK: - rate = pic32_get_pbclk(priv, periph); + rate = pic32_get_pbclk(priv, clk->id); break; case REF1CLK ... REF5CLK: - rate = pic32_get_refclk(priv, periph); + rate = pic32_get_refclk(priv, clk->id); break; case PLLCLK: rate = pic32_get_pll_rate(priv); @@ -372,15 +365,15 @@ static ulong pic32_get_periph_rate(struct udevice *dev, int periph) 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; - switch (periph) { + switch (clk->id) { case REF1CLK ... REF5CLK: 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; default: break; @@ -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 = { - .get_rate = pic32_clk_get_rate, - .set_periph_rate = pic32_set_periph_rate, - .get_periph_rate = pic32_get_periph_rate, + .set_rate = pic32_set_rate, + .get_rate = pic32_get_rate, }; static int pic32_clk_probe(struct udevice *dev) diff --git a/drivers/clk/clk_rk3036.c b/drivers/clk/clk_rk3036.c index 7ec65bdff02..6202c9da5da 100644 --- a/drivers/clk/clk_rk3036.c +++ b/drivers/clk/clk_rk3036.c @@ -5,7 +5,7 @@ */ #include <common.h> -#include <clk.h> +#include <clk-uclass.h> #include <dm.h> #include <errno.h> #include <syscon.h> @@ -18,10 +18,6 @@ DECLARE_GLOBAL_DATA_PTR; -struct rk3036_clk_plat { - enum rk_clk_id clk_id; -}; - struct rk3036_clk_priv { struct rk3036_cru *cru; ulong 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); } -static ulong rk3036_clk_get_rate(struct udevice *dev) -{ - struct rk3036_clk_plat *plat = dev_get_platdata(dev); - struct rk3036_clk_priv *priv = dev_get_priv(dev); - - debug("%s\n", dev->name); - return rkclk_pll_get_rate(priv->cru, plat->clk_id); -} - -static ulong rk3036_clk_set_rate(struct udevice *dev, ulong rate) +static ulong rk3036_clk_get_rate(struct clk *clk) { - debug("%s\n", dev->name); + struct rk3036_clk_priv *priv = dev_get_priv(clk->dev); - return 0; + switch (clk->id) { + case 0 ... 63: + return rkclk_pll_get_rate(priv->cru, clk->id); + default: + return -ENOENT; + } } -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); - ulong new_rate; + struct rk3036_clk_priv *priv = dev_get_priv(clk->dev); + 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: - new_rate = rockchip_mmc_set_clk(priv->cru, clk_get_rate(dev), - periph, rate); + new_rate = rockchip_mmc_set_clk(priv->cru, gclk_rate, + clk->id, rate); break; default: return -ENOENT; @@ -351,60 +346,21 @@ static ulong rk3036_set_periph_rate(struct udevice *dev, int periph, ulong rate) static struct clk_ops rk3036_clk_ops = { .get_rate = rk3036_clk_get_rate, .set_rate = rk3036_clk_set_rate, - .set_periph_rate = rk3036_set_periph_rate, }; 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); - 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); rkclk_init(priv->cru); return 0; } -static const char *const clk_name[] = { - "osc", - "apll", - "dpll", - "cpll", - "gpll", - "mpll", -}; - static int rk3036_clk_bind(struct udevice *dev) { - struct rk3036_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 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; - } + int ret; /* The reset driver does not have a device node, so bind it here */ ret = device_bind_driver(gd->dm_root, "rk3036_sysreset", "reset", &dev); @@ -424,7 +380,6 @@ U_BOOT_DRIVER(clk_rk3036) = { .id = UCLASS_CLK, .of_match = rk3036_clk_ids, .priv_auto_alloc_size = sizeof(struct rk3036_clk_priv), - .platdata_auto_alloc_size = sizeof(struct rk3036_clk_plat), .ops = &rk3036_clk_ops, .bind = rk3036_clk_bind, .probe = rk3036_clk_probe, diff --git a/drivers/clk/clk_rk3288.c b/drivers/clk/clk_rk3288.c index d88893c8ea6..2285453e8de 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, diff --git a/drivers/clk/clk_sandbox.c b/drivers/clk/clk_sandbox.c index 367130f8b76..c6bd7c64e29 100644 --- a/drivers/clk/clk_sandbox.c +++ b/drivers/clk/clk_sandbox.c @@ -5,61 +5,63 @@ */ #include <common.h> -#include <clk.h> +#include <clk-uclass.h> #include <dm.h> #include <errno.h> -#include <asm/test.h> +#include <asm/clk.h> struct sandbox_clk_priv { - ulong rate; - ulong periph_rate[PERIPH_ID_COUNT]; + ulong rate[SANDBOX_CLK_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) return -EINVAL; - priv->rate = rate; - return 0; -} -static ulong sandbox_get_periph_rate(struct udevice *dev, int periph) -{ - struct sandbox_clk_priv *priv = dev_get_priv(dev); + old_rate = priv->rate[clk->id]; + priv->rate[clk->id] = rate; - if (periph < PERIPH_ID_FIRST || periph >= PERIPH_ID_COUNT) - return -EINVAL; - return priv->periph_rate[periph]; + return old_rate; } -static ulong sandbox_set_periph_rate(struct udevice *dev, int periph, - ulong rate) +static int sandbox_clk_enable(struct clk *clk) { - struct sandbox_clk_priv *priv = dev_get_priv(dev); - ulong old_rate; + struct sandbox_clk_priv *priv = dev_get_priv(clk->dev); - if (periph < PERIPH_ID_FIRST || periph >= PERIPH_ID_COUNT) + if (clk->id < 0 || clk->id >= SANDBOX_CLK_ID_COUNT) 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; } @@ -67,8 +69,8 @@ static int sandbox_clk_probe(struct udevice *dev) static struct clk_ops sandbox_clk_ops = { .get_rate = sandbox_clk_get_rate, .set_rate = sandbox_clk_set_rate, - .get_periph_rate = sandbox_get_periph_rate, - .set_periph_rate = sandbox_set_periph_rate, + .enable = sandbox_clk_enable, + .disable = sandbox_clk_disable, }; static const struct udevice_id sandbox_clk_ids[] = { @@ -82,5 +84,24 @@ U_BOOT_DRIVER(clk_sandbox) = { .of_match = sandbox_clk_ids, .ops = &sandbox_clk_ops, .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]; +} diff --git a/drivers/clk/clk_sandbox_test.c b/drivers/clk/clk_sandbox_test.c new file mode 100644 index 00000000000..999100de9d2 --- /dev/null +++ b/drivers/clk/clk_sandbox_test.c @@ -0,0 +1,101 @@ +/* + * 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), +}; diff --git a/drivers/clk/exynos/clk-exynos7420.c b/drivers/clk/exynos/clk-exynos7420.c index bf5d0e6e603..1f017a307f3 100644 --- a/drivers/clk/exynos/clk-exynos7420.c +++ b/drivers/clk/exynos/clk-exynos7420.c @@ -9,7 +9,7 @@ #include <common.h> #include <dm.h> #include <errno.h> -#include <clk.h> +#include <clk-uclass.h> #include <asm/io.h> #include <dt-bindings/clock/exynos7420-clk.h> #include "clk-pll.h" @@ -67,11 +67,11 @@ struct exynos7420_clk_top0_priv { 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 SCLK_BUS0_PLL_A: case SCLK_BUS0_PLL_B: @@ -86,14 +86,14 @@ static ulong exynos7420_topc_get_periph_rate(struct udevice *dev, int periph) } 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) { struct exynos7420_clk_topc_priv *priv = dev_get_priv(dev); struct exynos7420_clk_cmu_topc *topc; - struct udevice *clk_dev; + struct clk in_clk; unsigned long rate; fdt_addr_t base; int ret; @@ -105,9 +105,9 @@ static int exynos7420_clk_topc_probe(struct udevice *dev) topc = (struct exynos7420_clk_cmu_topc *)base; priv->topc = topc; - ret = clk_get_by_index(dev, 0, &clk_dev); + ret = clk_get_by_index(dev, 0, &in_clk); 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); if (readl(&topc->mux_sel[1]) & (1 << 16)) @@ -122,12 +122,12 @@ static int exynos7420_clk_topc_probe(struct udevice *dev) 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; - switch (periph) { + switch (clk->id) { case CLK_SCLK_UART2: return priv->mout_top0_bus0_pll_half / DIVIDER(&top0->div_peric[3], 8, 0xf); @@ -137,14 +137,14 @@ static ulong exynos7420_top0_get_periph_rate(struct udevice *dev, int periph) } 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) { struct exynos7420_clk_top0_priv *priv; struct exynos7420_clk_cmu_top0 *top0; - struct udevice *clk_dev; + struct clk in_clk; fdt_addr_t base; int ret; @@ -159,10 +159,10 @@ static int exynos7420_clk_top0_probe(struct udevice *dev) top0 = (struct exynos7420_clk_cmu_top0 *)base; priv->top0 = top0; - ret = clk_get_by_index(dev, 1, &clk_dev); + ret = clk_get_by_index(dev, 1, &in_clk); if (ret >= 0) { 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)) priv->mout_top0_bus0_pll_half >>= 1; } @@ -170,18 +170,18 @@ static int exynos7420_clk_top0_probe(struct udevice *dev) 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 long freq = 0; - switch (periph) { + switch (clk->id) { 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) return ret; - freq = clk_get_periph_rate(clk_dev, ret); + freq = clk_get_rate(&in_clk); break; } @@ -189,7 +189,7 @@ static ulong exynos7420_peric1_get_periph_rate(struct udevice *dev, int periph) } 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[] = { diff --git a/drivers/clk/uniphier/clk-uniphier-core.c b/drivers/clk/uniphier/clk-uniphier-core.c index 25c163b395d..2f5d4d83910 100644 --- a/drivers/clk/uniphier/clk-uniphier-core.c +++ b/drivers/clk/uniphier/clk-uniphier-core.c @@ -9,14 +9,14 @@ #include <linux/bitops.h> #include <linux/io.h> #include <linux/sizes.h> -#include <clk.h> +#include <clk-uclass.h> #include <dm/device.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; unsigned int nr_gate = priv->socdata->nr_gate; void __iomem *reg; @@ -24,7 +24,7 @@ static int uniphier_clk_enable(struct udevice *dev, int index) int i; for (i = 0; i < nr_gate; i++) { - if (gate[i].index != index) + if (gate[i].index != clk->id) continue; reg = priv->base + gate[i].reg; @@ -41,9 +41,9 @@ static int uniphier_clk_enable(struct udevice *dev, int index) 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; unsigned int nr_rdata = priv->socdata->nr_rate; void __iomem *reg; @@ -52,7 +52,7 @@ static ulong uniphier_clk_get_rate(struct udevice *dev, int index) int i; for (i = 0; i < nr_rdata; i++) { - if (rdata[i].index != index) + if (rdata[i].index != clk->id) continue; if (rdata[i].reg == UNIPHIER_CLK_RATE_IS_FIXED) @@ -75,9 +75,9 @@ static ulong uniphier_clk_get_rate(struct udevice *dev, int index) 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; unsigned int nr_rdata = priv->socdata->nr_rate; void __iomem *reg; @@ -87,7 +87,7 @@ static ulong uniphier_clk_set_rate(struct udevice *dev, int index, ulong rate) /* first, decide the best match rate */ for (i = 0; i < nr_rdata; i++) { - if (rdata[i].index != index) + if (rdata[i].index != clk->id) continue; 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) /* second, really set registers */ 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; reg = priv->base + rdata[i].reg; @@ -124,8 +124,8 @@ static ulong uniphier_clk_set_rate(struct udevice *dev, int index, ulong rate) const struct clk_ops uniphier_clk_ops = { .enable = uniphier_clk_enable, - .get_periph_rate = uniphier_clk_get_rate, - .set_periph_rate = uniphier_clk_set_rate, + .get_rate = uniphier_clk_get_rate, + .set_rate = uniphier_clk_set_rate, }; int uniphier_clk_probe(struct udevice *dev) diff --git a/drivers/clk/uniphier/clk-uniphier-mio.c b/drivers/clk/uniphier/clk-uniphier-mio.c index c6ecd119bd6..2dd3fc074a7 100644 --- a/drivers/clk/uniphier/clk-uniphier-mio.c +++ b/drivers/clk/uniphier/clk-uniphier-mio.c @@ -4,7 +4,6 @@ * SPDX-License-Identifier: GPL-2.0+ */ -#include <clk.h> #include <dm/device.h> #include "clk-uniphier.h" |