diff options
author | Masahiro Yamada <yamada.masahiro@socionext.com> | 2017-10-13 19:21:59 +0900 |
---|---|---|
committer | Masahiro Yamada <yamada.masahiro@socionext.com> | 2017-10-15 22:32:25 +0900 |
commit | d6c7ee7d281e1bace42d5981b35a98322b994bc1 (patch) | |
tree | 262ebb28e08d946bbea914bb39d5cfd15e7af265 /drivers/clk | |
parent | 2b7b2df91ea64c94c698d900d7b55f58f898b227 (diff) |
clk: uniphier: rework for better clock tree structure
U-Boot does not support fancy clock tree structures like the Linux
common clock framework. Implement a simple clock tree model at the
driver level. With this, the clock data will be simplified.
Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com>
Diffstat (limited to 'drivers/clk')
-rw-r--r-- | drivers/clk/uniphier/clk-uniphier-core.c | 267 | ||||
-rw-r--r-- | drivers/clk/uniphier/clk-uniphier-mio.c | 118 | ||||
-rw-r--r-- | drivers/clk/uniphier/clk-uniphier-sys.c | 42 | ||||
-rw-r--r-- | drivers/clk/uniphier/clk-uniphier.h | 79 |
4 files changed, 323 insertions, 183 deletions
diff --git a/drivers/clk/uniphier/clk-uniphier-core.c b/drivers/clk/uniphier/clk-uniphier-core.c index 722cd6b060..3d1d411e79 100644 --- a/drivers/clk/uniphier/clk-uniphier-core.c +++ b/drivers/clk/uniphier/clk-uniphier-core.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2016 Socionext Inc. + * Copyright (C) 2016-2017 Socionext Inc. * Author: Masahiro Yamada <yamada.masahiro@socionext.com> * * SPDX-License-Identifier: GPL-2.0+ @@ -21,104 +21,224 @@ * @data: SoC specific data */ struct uniphier_clk_priv { + struct udevice *dev; void __iomem *base; const struct uniphier_clk_data *data; }; -static int uniphier_clk_enable(struct clk *clk) +static void uniphier_clk_gate_enable(struct uniphier_clk_priv *priv, + const struct uniphier_clk_gate_data *gate) { - struct uniphier_clk_priv *priv = dev_get_priv(clk->dev); - unsigned long id = clk->id; - const struct uniphier_clk_gate_data *p; + u32 val; - for (p = priv->data->gate; p->id != UNIPHIER_CLK_ID_END; p++) { - u32 val; + val = readl(priv->base + gate->reg); + val |= BIT(gate->bit); + writel(val, priv->base + gate->reg); +} - if (p->id != id) - continue; +static void uniphier_clk_mux_set_parent(struct uniphier_clk_priv *priv, + const struct uniphier_clk_mux_data *mux, + u8 id) +{ + u32 val; + int i; - val = readl(priv->base + p->reg); - val |= BIT(p->bit); - writel(val, priv->base + p->reg); + for (i = 0; i < mux->num_parents; i++) { + if (mux->parent_ids[i] != id) + continue; - return 0; + val = readl(priv->base + mux->reg); + val &= ~mux->masks[i]; + val |= mux->vals[i]; + writel(val, priv->base + mux->reg); + return; } - dev_err(priv->dev, "clk_id=%lu was not handled\n", id); - return -EINVAL; + WARN_ON(1); } -static const struct uniphier_clk_mux_data * -uniphier_clk_get_mux_data(struct uniphier_clk_priv *priv, unsigned long id) +static u8 uniphier_clk_mux_get_parent(struct uniphier_clk_priv *priv, + const struct uniphier_clk_mux_data *mux) { - const struct uniphier_clk_mux_data *p; + u32 val; + int i; - for (p = priv->data->mux; p->id != UNIPHIER_CLK_ID_END; p++) { - if (p->id == id) - return p; - } + val = readl(priv->base + mux->reg); + + for (i = 0; i < mux->num_parents; i++) + if ((mux->masks[i] & val) == mux->vals[i]) + return mux->parent_ids[i]; + + dev_err(priv->dev, "invalid mux setting\n"); + + return UNIPHIER_CLK_ID_INVALID; +} + +static const struct uniphier_clk_data *uniphier_clk_get_data( + struct uniphier_clk_priv *priv, u8 id) +{ + const struct uniphier_clk_data *data; + + for (data = priv->data; data->type != UNIPHIER_CLK_TYPE_END; data++) + if (data->id == id) + return data; + + dev_err(priv->dev, "id=%u not found\n", id); return NULL; } -static ulong uniphier_clk_get_rate(struct clk *clk) +static const struct uniphier_clk_data *uniphier_clk_get_parent_data( + struct uniphier_clk_priv *priv, + const struct uniphier_clk_data *data) { - struct uniphier_clk_priv *priv = dev_get_priv(clk->dev); - const struct uniphier_clk_mux_data *mux; - u32 val; - int i; + const struct uniphier_clk_data *parent_data; + u8 parent_id = UNIPHIER_CLK_ID_INVALID; + + switch (data->type) { + case UNIPHIER_CLK_TYPE_GATE: + parent_id = data->data.gate.parent_id; + break; + case UNIPHIER_CLK_TYPE_MUX: + parent_id = uniphier_clk_mux_get_parent(priv, &data->data.mux); + break; + default: + break; + } - mux = uniphier_clk_get_mux_data(priv, clk->id); - if (!mux) - return 0; + if (parent_id == UNIPHIER_CLK_ID_INVALID) + return NULL; - if (!mux->nr_muxs) /* fixed-rate */ - return mux->rates[0]; + parent_data = uniphier_clk_get_data(priv, parent_id); - val = readl(priv->base + mux->reg); + WARN_ON(!parent_data); - for (i = 0; i < mux->nr_muxs; i++) - if ((mux->masks[i] & val) == mux->vals[i]) - return mux->rates[i]; + return parent_data; +} + +static void __uniphier_clk_enable(struct uniphier_clk_priv *priv, + const struct uniphier_clk_data *data) +{ + const struct uniphier_clk_data *parent_data; - return -EINVAL; + if (data->type == UNIPHIER_CLK_TYPE_GATE) + uniphier_clk_gate_enable(priv, &data->data.gate); + + parent_data = uniphier_clk_get_parent_data(priv, data); + if (!parent_data) + return; + + return __uniphier_clk_enable(priv, parent_data); } -static ulong uniphier_clk_set_rate(struct clk *clk, ulong rate) +static int uniphier_clk_enable(struct clk *clk) { struct uniphier_clk_priv *priv = dev_get_priv(clk->dev); - const struct uniphier_clk_mux_data *mux; - u32 val; - int i, best_rate_id = -1; - ulong best_rate = 0; + const struct uniphier_clk_data *data; + + data = uniphier_clk_get_data(priv, clk->id); + if (!data) + return -ENODEV; + + __uniphier_clk_enable(priv, data); + + return 0; +} + +static unsigned long __uniphier_clk_get_rate( + struct uniphier_clk_priv *priv, + const struct uniphier_clk_data *data) +{ + const struct uniphier_clk_data *parent_data; - mux = uniphier_clk_get_mux_data(priv, clk->id); - if (!mux) + if (data->type == UNIPHIER_CLK_TYPE_FIXED_RATE) + return data->data.rate.fixed_rate; + + parent_data = uniphier_clk_get_parent_data(priv, data); + if (!parent_data) return 0; - if (!mux->nr_muxs) /* fixed-rate */ - return mux->rates[0]; + return __uniphier_clk_get_rate(priv, parent_data); +} - /* first, decide the best match rate */ - for (i = 0; i < mux->nr_muxs; i++) { - if (mux->rates[i] > best_rate && mux->rates[i] <= rate) { - best_rate = mux->rates[i]; - best_rate_id = i; +static unsigned long uniphier_clk_get_rate(struct clk *clk) +{ + struct uniphier_clk_priv *priv = dev_get_priv(clk->dev); + const struct uniphier_clk_data *data; + + data = uniphier_clk_get_data(priv, clk->id); + if (!data) + return -ENODEV; + + return __uniphier_clk_get_rate(priv, data); +} + +static unsigned long __uniphier_clk_set_rate( + struct uniphier_clk_priv *priv, + const struct uniphier_clk_data *data, + unsigned long rate, bool set) +{ + const struct uniphier_clk_data *best_parent_data = NULL; + const struct uniphier_clk_data *parent_data; + unsigned long best_rate = 0; + unsigned long parent_rate; + u8 parent_id; + int i; + + if (data->type == UNIPHIER_CLK_TYPE_FIXED_RATE) + return data->data.rate.fixed_rate; + + if (data->type == UNIPHIER_CLK_TYPE_GATE) { + parent_data = uniphier_clk_get_parent_data(priv, data); + if (!parent_data) + return 0; + + return __uniphier_clk_set_rate(priv, parent_data, rate, set); + } + + if (WARN_ON(data->type != UNIPHIER_CLK_TYPE_MUX)) + return -EINVAL; + + for (i = 0; i < data->data.mux.num_parents; i++) { + parent_id = data->data.mux.parent_ids[i]; + parent_data = uniphier_clk_get_data(priv, parent_id); + if (WARN_ON(!parent_data)) + return -EINVAL; + + parent_rate = __uniphier_clk_set_rate(priv, parent_data, rate, + false); + + if (parent_rate <= rate && best_rate < parent_rate) { + best_rate = parent_rate; + best_parent_data = parent_data; } } - if (best_rate_id < 0) + dev_dbg(priv->dev, "id=%u, best_rate=%lu\n", data->id, best_rate); + + if (!best_parent_data) return -EINVAL; - val = readl(priv->base + mux->reg); - val &= ~mux->masks[best_rate_id]; - val |= mux->vals[best_rate_id]; - writel(val, priv->base + mux->reg); + if (!set) + return best_rate; + + uniphier_clk_mux_set_parent(priv, &data->data.mux, + best_parent_data->id); + + return best_rate = __uniphier_clk_set_rate(priv, best_parent_data, + rate, true); +} + +static unsigned long uniphier_clk_set_rate(struct clk *clk, ulong rate) +{ + struct uniphier_clk_priv *priv = dev_get_priv(clk->dev); + const struct uniphier_clk_data *data; - debug("%s: requested rate = %lu, set rate = %lu\n", __func__, - rate, best_rate); + data = uniphier_clk_get_data(priv, clk->id); + if (!data) + return -ENODEV; - return best_rate; + return __uniphier_clk_set_rate(priv, data, rate, true); } static const struct clk_ops uniphier_clk_ops = { @@ -140,6 +260,7 @@ static int uniphier_clk_probe(struct udevice *dev) if (!priv->base) return -ENOMEM; + priv->dev = dev; priv->data = (void *)dev_get_driver_data(dev); return 0; @@ -149,60 +270,60 @@ static const struct udevice_id uniphier_clk_match[] = { /* System clock */ { .compatible = "socionext,uniphier-ld4-clock", - .data = (ulong)&uniphier_pxs2_sys_clk_data, + .data = (ulong)uniphier_pxs2_sys_clk_data, }, { .compatible = "socionext,uniphier-pro4-clock", - .data = (ulong)&uniphier_pxs2_sys_clk_data, + .data = (ulong)uniphier_pxs2_sys_clk_data, }, { .compatible = "socionext,uniphier-sld8-clock", - .data = (ulong)&uniphier_pxs2_sys_clk_data, + .data = (ulong)uniphier_pxs2_sys_clk_data, }, { .compatible = "socionext,uniphier-pro5-clock", - .data = (ulong)&uniphier_pxs2_sys_clk_data, + .data = (ulong)uniphier_pxs2_sys_clk_data, }, { .compatible = "socionext,uniphier-pxs2-clock", - .data = (ulong)&uniphier_pxs2_sys_clk_data, + .data = (ulong)uniphier_pxs2_sys_clk_data, }, { .compatible = "socionext,uniphier-ld11-clock", - .data = (ulong)&uniphier_ld20_sys_clk_data, + .data = (ulong)uniphier_ld20_sys_clk_data, }, { .compatible = "socionext,uniphier-ld20-clock", - .data = (ulong)&uniphier_ld20_sys_clk_data, + .data = (ulong)uniphier_ld20_sys_clk_data, }, /* Media I/O clock */ { .compatible = "socionext,uniphier-ld4-mio-clock", - .data = (ulong)&uniphier_mio_clk_data, + .data = (ulong)uniphier_mio_clk_data, }, { .compatible = "socionext,uniphier-pro4-mio-clock", - .data = (ulong)&uniphier_mio_clk_data, + .data = (ulong)uniphier_mio_clk_data, }, { .compatible = "socionext,uniphier-sld8-mio-clock", - .data = (ulong)&uniphier_mio_clk_data, + .data = (ulong)uniphier_mio_clk_data, }, { .compatible = "socionext,uniphier-pro5-sd-clock", - .data = (ulong)&uniphier_mio_clk_data, + .data = (ulong)uniphier_mio_clk_data, }, { .compatible = "socionext,uniphier-pxs2-sd-clock", - .data = (ulong)&uniphier_mio_clk_data, + .data = (ulong)uniphier_mio_clk_data, }, { .compatible = "socionext,uniphier-ld11-mio-clock", - .data = (ulong)&uniphier_mio_clk_data, + .data = (ulong)uniphier_mio_clk_data, }, { .compatible = "socionext,uniphier-ld20-sd-clock", - .data = (ulong)&uniphier_mio_clk_data, + .data = (ulong)uniphier_mio_clk_data, }, { /* sentinel */ } }; diff --git a/drivers/clk/uniphier/clk-uniphier-mio.c b/drivers/clk/uniphier/clk-uniphier-mio.c index 9c13dcd555..5c73848402 100644 --- a/drivers/clk/uniphier/clk-uniphier-mio.c +++ b/drivers/clk/uniphier/clk-uniphier-mio.c @@ -7,59 +7,71 @@ #include "clk-uniphier.h" -#define UNIPHIER_MIO_CLK_SD_GATE(id, ch) \ - UNIPHIER_CLK_GATE((id), 0x20 + 0x200 * (ch), 8) +#define UNIPHIER_MIO_CLK_SD_FIXED \ + UNIPHIER_CLK_RATE(128, 44444444), \ + UNIPHIER_CLK_RATE(129, 33333333), \ + UNIPHIER_CLK_RATE(130, 50000000), \ + UNIPHIER_CLK_RATE(131, 66666667), \ + UNIPHIER_CLK_RATE(132, 100000000), \ + UNIPHIER_CLK_RATE(133, 40000000), \ + UNIPHIER_CLK_RATE(134, 25000000), \ + UNIPHIER_CLK_RATE(135, 22222222) + +#define UNIPHIER_MIO_CLK_SD(_id, ch) \ + { \ + .type = UNIPHIER_CLK_TYPE_MUX, \ + .id = (_id) + 32, \ + .data.mux = { \ + .parent_ids = { \ + 128, \ + 129, \ + 130, \ + 131, \ + 132, \ + 133, \ + 134, \ + 135, \ + }, \ + .num_parents = 8, \ + .reg = 0x30 + 0x200 * (ch), \ + .masks = { \ + 0x00031000, \ + 0x00031000, \ + 0x00031000, \ + 0x00031000, \ + 0x00001300, \ + 0x00001300, \ + 0x00001300, \ + 0x00001300, \ + }, \ + .vals = { \ + 0x00000000, \ + 0x00010000, \ + 0x00020000, \ + 0x00030000, \ + 0x00001000, \ + 0x00001100, \ + 0x00001200, \ + 0x00001300, \ + }, \ + }, \ + }, \ + UNIPHIER_CLK_GATE((_id), (_id) + 32, 0x20 + 0x200 * (ch), 8) #define UNIPHIER_MIO_CLK_USB2(id, ch) \ - UNIPHIER_CLK_GATE((id), 0x20 + 0x200 * (ch), 28) + UNIPHIER_CLK_GATE_SIMPLE((id), 0x20 + 0x200 * (ch), 28) #define UNIPHIER_MIO_CLK_USB2_PHY(id, ch) \ - UNIPHIER_CLK_GATE((id), 0x20 + 0x200 * (ch), 29) + UNIPHIER_CLK_GATE_SIMPLE((id), 0x20 + 0x200 * (ch), 29) #define UNIPHIER_MIO_CLK_DMAC(id) \ - UNIPHIER_CLK_GATE((id), 0x20, 25) - -#define UNIPHIER_MIO_CLK_SD_MUX(_id, ch) \ - { \ - .id = (_id), \ - .nr_muxs = 8, \ - .reg = 0x30 + 0x200 * (ch), \ - .masks = { \ - 0x00031000, \ - 0x00031000, \ - 0x00031000, \ - 0x00031000, \ - 0x00001300, \ - 0x00001300, \ - 0x00001300, \ - 0x00001300, \ - }, \ - .vals = { \ - 0x00000000, \ - 0x00010000, \ - 0x00020000, \ - 0x00030000, \ - 0x00001000, \ - 0x00001100, \ - 0x00001200, \ - 0x00001300, \ - }, \ - .rates = { \ - 44444444, \ - 33333333, \ - 50000000, \ - 66666666, \ - 100000000, \ - 40000000, \ - 25000000, \ - 22222222, \ - }, \ - } + UNIPHIER_CLK_GATE_SIMPLE((id), 0x20, 25) -static const struct uniphier_clk_gate_data uniphier_mio_clk_gate[] = { - UNIPHIER_MIO_CLK_SD_GATE(0, 0), - UNIPHIER_MIO_CLK_SD_GATE(1, 1), - UNIPHIER_MIO_CLK_SD_GATE(2, 2), /* for PH1-Pro4 only */ +const struct uniphier_clk_data uniphier_mio_clk_data[] = { + UNIPHIER_MIO_CLK_SD_FIXED, + UNIPHIER_MIO_CLK_SD(0, 0), + UNIPHIER_MIO_CLK_SD(1, 1), + UNIPHIER_MIO_CLK_SD(2, 2), UNIPHIER_MIO_CLK_DMAC(7), UNIPHIER_MIO_CLK_USB2(8, 0), UNIPHIER_MIO_CLK_USB2(9, 1), @@ -67,17 +79,5 @@ static const struct uniphier_clk_gate_data uniphier_mio_clk_gate[] = { UNIPHIER_MIO_CLK_USB2_PHY(12, 0), UNIPHIER_MIO_CLK_USB2_PHY(13, 1), UNIPHIER_MIO_CLK_USB2_PHY(14, 2), - UNIPHIER_CLK_END -}; - -static const struct uniphier_clk_mux_data uniphier_mio_clk_mux[] = { - UNIPHIER_MIO_CLK_SD_MUX(0, 0), - UNIPHIER_MIO_CLK_SD_MUX(1, 1), - UNIPHIER_MIO_CLK_SD_MUX(2, 2), /* for PH1-Pro4 only */ - UNIPHIER_CLK_END -}; - -const struct uniphier_clk_data uniphier_mio_clk_data = { - .gate = uniphier_mio_clk_gate, - .mux = uniphier_mio_clk_mux, + { /* sentinel */ } }; diff --git a/drivers/clk/uniphier/clk-uniphier-sys.c b/drivers/clk/uniphier/clk-uniphier-sys.c index 709fa5081a..e9df88508c 100644 --- a/drivers/clk/uniphier/clk-uniphier-sys.c +++ b/drivers/clk/uniphier/clk-uniphier-sys.c @@ -7,28 +7,26 @@ #include "clk-uniphier.h" -const struct uniphier_clk_gate_data uniphier_pxs2_sys_clk_gate[] = { - UNIPHIER_CLK_GATE(8, 0x2104, 10), /* stdmac */ - UNIPHIER_CLK_GATE(12, 0x2104, 6), /* gio (Pro4, Pro5) */ - UNIPHIER_CLK_GATE(14, 0x2104, 16), /* usb30 (Pro4, Pro5, PXs2) */ - UNIPHIER_CLK_GATE(15, 0x2104, 17), /* usb31 (Pro4, Pro5, PXs2) */ - UNIPHIER_CLK_GATE(16, 0x2104, 19), /* usb30-phy (PXs2) */ - UNIPHIER_CLK_GATE(20, 0x2104, 20), /* usb31-phy (PXs2) */ - UNIPHIER_CLK_END +const struct uniphier_clk_data uniphier_pxs2_sys_clk_data[] = { +#if defined(CONFIG_ARCH_UNIPHIER_LD4) || defined(CONFIG_ARCH_UNIPHIER_SLD8) ||\ + defined(CONFIG_ARCH_UNIPHIER_PRO4) || defined(CONFIG_ARCH_UNIPHIER_PRO5) ||\ + defined(CONFIG_ARCH_UNIPHIER_PXS2) || defined(CONFIG_ARCH_UNIPHIER_LD6B) + UNIPHIER_CLK_GATE_SIMPLE(8, 0x2104, 10), /* stdmac */ + UNIPHIER_CLK_GATE_SIMPLE(12, 0x2104, 6), /* gio (Pro4, Pro5) */ + UNIPHIER_CLK_GATE_SIMPLE(14, 0x2104, 16), /* usb30 (Pro4, Pro5, PXs2) */ + UNIPHIER_CLK_GATE_SIMPLE(15, 0x2104, 17), /* usb31 (Pro4, Pro5, PXs2) */ + UNIPHIER_CLK_GATE_SIMPLE(16, 0x2104, 19), /* usb30-phy (PXs2) */ + UNIPHIER_CLK_GATE_SIMPLE(20, 0x2104, 20), /* usb31-phy (PXs2) */ + { /* sentinel */ } +#endif }; -const struct uniphier_clk_data uniphier_pxs2_sys_clk_data = { - .gate = uniphier_pxs2_sys_clk_gate, -}; - -const struct uniphier_clk_gate_data uniphier_ld20_sys_clk_gate[] = { - UNIPHIER_CLK_GATE(8, 0x210c, 8), /* stdmac */ - UNIPHIER_CLK_GATE(14, 0x210c, 14), /* usb30 (LD20) */ - UNIPHIER_CLK_GATE(16, 0x210c, 12), /* usb30-phy0 (LD20) */ - UNIPHIER_CLK_GATE(17, 0x210c, 13), /* usb30-phy1 (LD20) */ - UNIPHIER_CLK_END -}; - -const struct uniphier_clk_data uniphier_ld20_sys_clk_data = { - .gate = uniphier_ld20_sys_clk_gate, +const struct uniphier_clk_data uniphier_ld20_sys_clk_data[] = { +#if defined(CONFIG_ARCH_UNIPHIER_LD11) || defined(CONFIG_ARCH_UNIPHIER_LD20) + UNIPHIER_CLK_GATE_SIMPLE(8, 0x210c, 8), /* stdmac */ + UNIPHIER_CLK_GATE_SIMPLE(14, 0x210c, 14), /* usb30 (LD20) */ + UNIPHIER_CLK_GATE_SIMPLE(16, 0x210c, 12), /* usb30-phy0 (LD20) */ + UNIPHIER_CLK_GATE_SIMPLE(17, 0x210c, 13), /* usb30-phy1 (LD20) */ + { /* sentinel */ } +#endif }; diff --git a/drivers/clk/uniphier/clk-uniphier.h b/drivers/clk/uniphier/clk-uniphier.h index 770a3225e1..9b6c94fc38 100644 --- a/drivers/clk/uniphier/clk-uniphier.h +++ b/drivers/clk/uniphier/clk-uniphier.h @@ -9,49 +9,70 @@ #define __CLK_UNIPHIER_H__ #include <linux/kernel.h> +#include <linux/types.h> -#define UNIPHIER_CLK_MAX_NR_MUXS 8 +#define UNIPHIER_CLK_MUX_MAX_PARENTS 8 + +#define UNIPHIER_CLK_TYPE_END 0 +#define UNIPHIER_CLK_TYPE_FIXED_RATE 2 +#define UNIPHIER_CLK_TYPE_GATE 3 +#define UNIPHIER_CLK_TYPE_MUX 4 + +#define UNIPHIER_CLK_ID_INVALID (U8_MAX) + +struct uniphier_clk_fixed_rate_data { + unsigned long fixed_rate; +}; struct uniphier_clk_gate_data { - unsigned int id; - unsigned int reg; - unsigned int bit; + u8 parent_id; + u16 reg; + u8 bit; }; struct uniphier_clk_mux_data { - unsigned int id; - unsigned int nr_muxs; - unsigned int reg; - unsigned int masks[UNIPHIER_CLK_MAX_NR_MUXS]; - unsigned int vals[UNIPHIER_CLK_MAX_NR_MUXS]; - unsigned long rates[UNIPHIER_CLK_MAX_NR_MUXS]; + u8 parent_ids[UNIPHIER_CLK_MUX_MAX_PARENTS]; + u8 num_parents; + u16 reg; + u32 masks[UNIPHIER_CLK_MUX_MAX_PARENTS]; + u32 vals[UNIPHIER_CLK_MUX_MAX_PARENTS]; }; struct uniphier_clk_data { - const struct uniphier_clk_gate_data *gate; - const struct uniphier_clk_mux_data *mux; + u8 type; + u8 id; + union { + struct uniphier_clk_fixed_rate_data rate; + struct uniphier_clk_gate_data gate; + struct uniphier_clk_mux_data mux; + } data; }; -#define UNIPHIER_CLK_ID_END (unsigned int)(-1) - -#define UNIPHIER_CLK_END \ - { .id = UNIPHIER_CLK_ID_END } - -#define UNIPHIER_CLK_GATE(_id, _reg, _bit) \ - { \ - .id = (_id), \ - .reg = (_reg), \ - .bit = (_bit), \ +#define UNIPHIER_CLK_RATE(_id, _rate) \ + { \ + .type = UNIPHIER_CLK_TYPE_FIXED_RATE, \ + .id = (_id), \ + .data.rate = { \ + .fixed_rate = (_rate), \ + }, \ } -#define UNIPHIER_CLK_FIXED_RATE(_id, _rate) \ - { \ - .id = (_id), \ - .rates = {(_reg),}, \ +#define UNIPHIER_CLK_GATE(_id, _parent, _reg, _bit) \ + { \ + .type = UNIPHIER_CLK_TYPE_GATE, \ + .id = (_id), \ + .data.gate = { \ + .parent_id = (_parent), \ + .reg = (_reg), \ + .bit = (_bit), \ + }, \ } -extern const struct uniphier_clk_data uniphier_pxs2_sys_clk_data; -extern const struct uniphier_clk_data uniphier_ld20_sys_clk_data; -extern const struct uniphier_clk_data uniphier_mio_clk_data; +#define UNIPHIER_CLK_GATE_SIMPLE(_id, _reg, _bit) \ + UNIPHIER_CLK_GATE(_id, UNIPHIER_CLK_ID_INVALID, _reg, _bit) + +extern const struct uniphier_clk_data uniphier_pxs2_sys_clk_data[]; +extern const struct uniphier_clk_data uniphier_ld20_sys_clk_data[]; +extern const struct uniphier_clk_data uniphier_mio_clk_data[]; #endif /* __CLK_UNIPHIER_H__ */ |