diff options
Diffstat (limited to 'drivers/clk')
-rw-r--r-- | drivers/clk/Kconfig | 8 | ||||
-rw-r--r-- | drivers/clk/Makefile | 1 | ||||
-rw-r--r-- | drivers/clk/clk_boston.c | 97 | ||||
-rw-r--r-- | drivers/clk/uniphier/clk-uniphier-core.c | 94 | ||||
-rw-r--r-- | drivers/clk/uniphier/clk-uniphier-mio.c | 51 | ||||
-rw-r--r-- | drivers/clk/uniphier/clk-uniphier.h | 18 |
6 files changed, 187 insertions, 82 deletions
diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig index 8f3b96a9736..c05ce2a9efa 100644 --- a/drivers/clk/Kconfig +++ b/drivers/clk/Kconfig @@ -20,6 +20,14 @@ config SPL_CLK setting up clocks within SPL, and allows the same drivers to be used as U-Boot proper. +config CLK_BOSTON + def_bool y if TARGET_BOSTON + depends on CLK + select REGMAP + select SYSCON + help + Enable this to support the clocks + source "drivers/clk/tegra/Kconfig" source "drivers/clk/uniphier/Kconfig" source "drivers/clk/exynos/Kconfig" diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index 778d7486f06..40a5e8cae86 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -15,3 +15,4 @@ obj-y += tegra/ obj-$(CONFIG_CLK_UNIPHIER) += uniphier/ obj-$(CONFIG_CLK_EXYNOS) += exynos/ obj-$(CONFIG_CLK_AT91) += at91/ +obj-$(CONFIG_CLK_BOSTON) += clk_boston.o diff --git a/drivers/clk/clk_boston.c b/drivers/clk/clk_boston.c new file mode 100644 index 00000000000..78f1b759d83 --- /dev/null +++ b/drivers/clk/clk_boston.c @@ -0,0 +1,97 @@ +/* + * Copyright (C) 2016 Imagination Technologies + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#include <common.h> +#include <clk-uclass.h> +#include <dm.h> +#include <dt-bindings/clock/boston-clock.h> +#include <regmap.h> +#include <syscon.h> + +struct clk_boston { + struct regmap *regmap; +}; + +#define BOSTON_PLAT_MMCMDIV 0x30 +# define BOSTON_PLAT_MMCMDIV_CLK0DIV (0xff << 0) +# define BOSTON_PLAT_MMCMDIV_INPUT (0xff << 8) +# define BOSTON_PLAT_MMCMDIV_MUL (0xff << 16) +# define BOSTON_PLAT_MMCMDIV_CLK1DIV (0xff << 24) + +static uint32_t ext_field(uint32_t val, uint32_t mask) +{ + return (val & mask) >> (ffs(mask) - 1); +} + +static ulong clk_boston_get_rate(struct clk *clk) +{ + struct clk_boston *state = dev_get_platdata(clk->dev); + uint32_t in_rate, mul, div; + uint mmcmdiv; + int err; + + err = regmap_read(state->regmap, BOSTON_PLAT_MMCMDIV, &mmcmdiv); + if (err) + return 0; + + in_rate = ext_field(mmcmdiv, BOSTON_PLAT_MMCMDIV_INPUT); + mul = ext_field(mmcmdiv, BOSTON_PLAT_MMCMDIV_MUL); + + switch (clk->id) { + case BOSTON_CLK_SYS: + div = ext_field(mmcmdiv, BOSTON_PLAT_MMCMDIV_CLK0DIV); + break; + case BOSTON_CLK_CPU: + div = ext_field(mmcmdiv, BOSTON_PLAT_MMCMDIV_CLK1DIV); + break; + default: + return 0; + } + + return (in_rate * mul * 1000000) / div; +} + +const struct clk_ops clk_boston_ops = { + .get_rate = clk_boston_get_rate, +}; + +static int clk_boston_ofdata_to_platdata(struct udevice *dev) +{ + struct clk_boston *state = dev_get_platdata(dev); + struct udevice *syscon; + int err; + + err = uclass_get_device_by_phandle(UCLASS_SYSCON, dev, + "regmap", &syscon); + if (err) { + error("unable to find syscon device\n"); + return err; + } + + state->regmap = syscon_get_regmap(syscon); + if (!state->regmap) { + error("unable to find regmap\n"); + return -ENODEV; + } + + return 0; +} + +static const struct udevice_id clk_boston_match[] = { + { + .compatible = "img,boston-clock", + }, + { /* sentinel */ } +}; + +U_BOOT_DRIVER(clk_boston) = { + .name = "boston_clock", + .id = UCLASS_CLK, + .of_match = clk_boston_match, + .ofdata_to_platdata = clk_boston_ofdata_to_platdata, + .platdata_auto_alloc_size = sizeof(struct clk_boston), + .ops = &clk_boston_ops, +}; diff --git a/drivers/clk/uniphier/clk-uniphier-core.c b/drivers/clk/uniphier/clk-uniphier-core.c index a91924e8a4e..394832607ed 100644 --- a/drivers/clk/uniphier/clk-uniphier-core.c +++ b/drivers/clk/uniphier/clk-uniphier-core.c @@ -14,10 +14,39 @@ #include "clk-uniphier.h" +/** + * struct uniphier_clk_priv - private data for UniPhier clock driver + * + * @base: base address of the clock provider + * @socdata: SoC specific data + */ +struct uniphier_clk_priv { + void __iomem *base; + const struct uniphier_clk_soc_data *socdata; +}; + +int uniphier_clk_probe(struct udevice *dev) +{ + struct uniphier_clk_priv *priv = dev_get_priv(dev); + fdt_addr_t addr; + + addr = dev_get_addr(dev->parent); + if (addr == FDT_ADDR_T_NONE) + return -EINVAL; + + priv->base = devm_ioremap(dev, addr, SZ_4K); + if (!priv->base) + return -ENOMEM; + + priv->socdata = (void *)dev_get_driver_data(dev); + + return 0; +} + static int uniphier_clk_enable(struct clk *clk) { struct uniphier_clk_priv *priv = dev_get_priv(clk->dev); - struct uniphier_clk_gate_data *gate = priv->socdata->gate; + const struct uniphier_clk_gate_data *gate = priv->socdata->gate; unsigned int nr_gate = priv->socdata->nr_gate; void __iomem *reg; u32 mask, data, tmp; @@ -44,7 +73,7 @@ static int uniphier_clk_enable(struct clk *clk) static ulong uniphier_clk_get_rate(struct clk *clk) { struct uniphier_clk_priv *priv = dev_get_priv(clk->dev); - struct uniphier_clk_rate_data *rdata = priv->socdata->rate; + const struct uniphier_clk_rate_data *rdata = priv->socdata->rate; unsigned int nr_rdata = priv->socdata->nr_rate; void __iomem *reg; u32 mask, data; @@ -78,7 +107,7 @@ static ulong uniphier_clk_get_rate(struct clk *clk) static ulong uniphier_clk_set_rate(struct clk *clk, ulong rate) { struct uniphier_clk_priv *priv = dev_get_priv(clk->dev); - struct uniphier_clk_rate_data *rdata = priv->socdata->rate; + const struct uniphier_clk_rate_data *rdata = priv->socdata->rate; unsigned int nr_rdata = priv->socdata->nr_rate; void __iomem *reg; u32 mask, data, tmp; @@ -128,20 +157,47 @@ const struct clk_ops uniphier_clk_ops = { .set_rate = uniphier_clk_set_rate, }; -int uniphier_clk_probe(struct udevice *dev) -{ - struct uniphier_clk_priv *priv = dev_get_priv(dev); - fdt_addr_t addr; - - addr = dev_get_addr(dev); - if (addr == FDT_ADDR_T_NONE) - return -EINVAL; - - priv->base = devm_ioremap(dev, addr, SZ_4K); - if (!priv->base) - return -ENOMEM; - - priv->socdata = (void *)dev_get_driver_data(dev); +static const struct udevice_id uniphier_clk_match[] = { + { + .compatible = "socionext,uniphier-sld3-mio-clock", + .data = (ulong)&uniphier_mio_clk_data, + }, + { + .compatible = "socionext,uniphier-ld4-mio-clock", + .data = (ulong)&uniphier_mio_clk_data, + }, + { + .compatible = "socionext,uniphier-pro4-mio-clock", + .data = (ulong)&uniphier_mio_clk_data, + }, + { + .compatible = "socionext,uniphier-sld8-mio-clock", + .data = (ulong)&uniphier_mio_clk_data, + }, + { + .compatible = "socionext,uniphier-pro5-mio-clock", + .data = (ulong)&uniphier_mio_clk_data, + }, + { + .compatible = "socionext,uniphier-pxs2-mio-clock", + .data = (ulong)&uniphier_mio_clk_data, + }, + { + .compatible = "socionext,uniphier-ld11-mio-clock", + .data = (ulong)&uniphier_mio_clk_data, + }, + { + .compatible = "socionext,uniphier-ld20-mio-clock", + .data = (ulong)&uniphier_mio_clk_data, + }, + { /* sentinel */ } +}; - return 0; -} +U_BOOT_DRIVER(uniphier_clk) = { + .name = "uniphier-clk", + .id = UCLASS_CLK, + .of_match = uniphier_clk_match, + .probe = uniphier_clk_probe, + .priv_auto_alloc_size = sizeof(struct uniphier_clk_priv), + .ops = &uniphier_clk_ops, +}; diff --git a/drivers/clk/uniphier/clk-uniphier-mio.c b/drivers/clk/uniphier/clk-uniphier-mio.c index 2eea5ebc2ae..c1e7197c1a8 100644 --- a/drivers/clk/uniphier/clk-uniphier-mio.c +++ b/drivers/clk/uniphier/clk-uniphier-mio.c @@ -115,7 +115,7 @@ .data = 0x00020000, \ } -static struct uniphier_clk_gate_data uniphier_mio_clk_gate[] = { +static const struct uniphier_clk_gate_data uniphier_mio_clk_gate[] = { UNIPHIER_MIO_CLK_GATE_SD(0, 0), UNIPHIER_MIO_CLK_GATE_SD(1, 1), UNIPHIER_MIO_CLK_GATE_SD(2, 2), /* for PH1-Pro4 only */ @@ -126,60 +126,15 @@ static struct uniphier_clk_gate_data uniphier_mio_clk_gate[] = { UNIPHIER_MIO_CLK_GATE_USB(3, 7), /* for PH1-sLD3 only */ }; -static struct uniphier_clk_rate_data uniphier_mio_clk_rate[] = { +static const struct uniphier_clk_rate_data uniphier_mio_clk_rate[] = { UNIPHIER_MIO_CLK_RATE_SD(0, 0), UNIPHIER_MIO_CLK_RATE_SD(1, 1), UNIPHIER_MIO_CLK_RATE_SD(2, 2), /* for PH1-Pro4 only */ }; -static struct uniphier_clk_soc_data uniphier_mio_clk_data = { +const struct uniphier_clk_soc_data uniphier_mio_clk_data = { .gate = uniphier_mio_clk_gate, .nr_gate = ARRAY_SIZE(uniphier_mio_clk_gate), .rate = uniphier_mio_clk_rate, .nr_rate = ARRAY_SIZE(uniphier_mio_clk_rate), }; - -static const struct udevice_id uniphier_mio_clk_match[] = { - { - .compatible = "socionext,ph1-sld3-mioctrl", - .data = (ulong)&uniphier_mio_clk_data, - }, - { - .compatible = "socionext,ph1-ld4-mioctrl", - .data = (ulong)&uniphier_mio_clk_data, - }, - { - .compatible = "socionext,ph1-pro4-mioctrl", - .data = (ulong)&uniphier_mio_clk_data, - }, - { - .compatible = "socionext,ph1-sld8-mioctrl", - .data = (ulong)&uniphier_mio_clk_data, - }, - { - .compatible = "socionext,ph1-pro5-mioctrl", - .data = (ulong)&uniphier_mio_clk_data, - }, - { - .compatible = "socionext,proxstream2-mioctrl", - .data = (ulong)&uniphier_mio_clk_data, - }, - { - .compatible = "socionext,ph1-ld11-mioctrl", - .data = (ulong)&uniphier_mio_clk_data, - }, - { - .compatible = "socionext,ph1-ld20-mioctrl", - .data = (ulong)&uniphier_mio_clk_data, - }, - { /* sentinel */ } -}; - -U_BOOT_DRIVER(uniphier_mio_clk) = { - .name = "uniphier-mio-clk", - .id = UCLASS_CLK, - .of_match = uniphier_mio_clk_match, - .probe = uniphier_clk_probe, - .priv_auto_alloc_size = sizeof(struct uniphier_clk_priv), - .ops = &uniphier_clk_ops, -}; diff --git a/drivers/clk/uniphier/clk-uniphier.h b/drivers/clk/uniphier/clk-uniphier.h index 18aa88849b3..0b60337205e 100644 --- a/drivers/clk/uniphier/clk-uniphier.h +++ b/drivers/clk/uniphier/clk-uniphier.h @@ -27,9 +27,9 @@ struct uniphier_clk_rate_data { }; struct uniphier_clk_soc_data { - struct uniphier_clk_gate_data *gate; + const struct uniphier_clk_gate_data *gate; unsigned int nr_gate; - struct uniphier_clk_rate_data *rate; + const struct uniphier_clk_rate_data *rate; unsigned int nr_rate; }; @@ -40,18 +40,6 @@ struct uniphier_clk_soc_data { .rate = f, \ } -/** - * struct uniphier_clk_priv - private data for UniPhier clock driver - * - * @base: base address of the clock provider - * @socdata: SoC specific data - */ -struct uniphier_clk_priv { - void __iomem *base; - struct uniphier_clk_soc_data *socdata; -}; - -extern const struct clk_ops uniphier_clk_ops; -int uniphier_clk_probe(struct udevice *dev); +extern const struct uniphier_clk_soc_data uniphier_mio_clk_data; #endif /* __CLK_UNIPHIER_H__ */ |