From 935e09cdcb6d6dfa41f4cd8c8a69da52ef6850ed Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Sun, 9 Oct 2016 23:52:57 +0900 Subject: pinctrl: uniphier: fix unused-const-variable warnings for GCC 6.x Marek reports warnings in UniPhier pinctrl drivers when compiled by GCC 6.x, like: drivers/pinctrl/uniphier/pinctrl-uniphier-ld20.c:58:18: warning: 'usb3_muxvals' defined but not used [-Wunused-const-variable=] static const int usb3_muxvals[] = {0, 0}; ^~~~~~~~~~~~ My intention here is to compile minimum set of pin data for SPL to save memory footprint, but GCC these days is clever enough to notice unused data arrays. We can fix it by sprinkling around __maybe_unused on those arrays, but I did not do that because they are counterparts of the pinctrl drivers in Linux. All the pin data were just copy-pasted from Linux and are kept in sync for maintainability. I chose a bit tricky way to fix the issue; calculate ARRAY_SIZE of *_pins and *_muxvals and set their sum to an unused struct member. This trick will satisfy GCC because the data arrays are used anyway, but such data arrays will be dropped from the final binary because the pointers to them are not used. Signed-off-by: Masahiro Yamada Reported-by: Marek Vasut --- drivers/pinctrl/uniphier/pinctrl-uniphier.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier.h b/drivers/pinctrl/uniphier/pinctrl-uniphier.h index 5c3db2ab605..21e2d377b4c 100644 --- a/drivers/pinctrl/uniphier/pinctrl-uniphier.h +++ b/drivers/pinctrl/uniphier/pinctrl-uniphier.h @@ -91,7 +91,12 @@ struct uniphier_pinctrl_socdata { #define __UNIPHIER_PINMUX_FUNCTION(func) #func #ifdef CONFIG_SPL_BUILD -#define UNIPHIER_PINCTRL_GROUP(grp) { .name = NULL } + /* + * a tricky way to drop unneeded *_pins and *_muxvals arrays from SPL, + * suppressing "defined but not used" warnings. + */ +#define UNIPHIER_PINCTRL_GROUP(grp) \ + { .num_pins = ARRAY_SIZE(grp##_pins) + ARRAY_SIZE(grp##_muxvals) } #define UNIPHIER_PINMUX_FUNCTION(func) NULL #else #define UNIPHIER_PINCTRL_GROUP(grp) __UNIPHIER_PINCTRL_GROUP(grp) -- cgit v1.3.1 From 805dc44cc8afc357f7cdca8b183d0b641768bdb2 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Mon, 17 Oct 2016 22:18:01 +0900 Subject: clk: uniphier: rework UniPhier clk driver The initial design of the UniPhier clk driver for U-Boot was not very nice. Here is a re-work to sync it with Linux's clk and reset drivers, maximizing the code reuse from Linux's clk data. Signed-off-by: Masahiro Yamada --- drivers/clk/uniphier/Kconfig | 15 +-- drivers/clk/uniphier/Makefile | 5 +- drivers/clk/uniphier/clk-uniphier-core.c | 170 +++++++++++++--------------- drivers/clk/uniphier/clk-uniphier-mio.c | 183 +++++++++++-------------------- drivers/clk/uniphier/clk-uniphier.h | 46 +++++--- 5 files changed, 179 insertions(+), 240 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/uniphier/Kconfig b/drivers/clk/uniphier/Kconfig index 0e90c01a9a9..da3e3553895 100644 --- a/drivers/clk/uniphier/Kconfig +++ b/drivers/clk/uniphier/Kconfig @@ -1,13 +1,10 @@ config CLK_UNIPHIER - bool + bool "Clock driver for UniPhier SoCs" + depends on ARCH_UNIPHIER select CLK select SPL_CLK - -menu "Clock drivers for UniPhier SoCs" - depends on CLK_UNIPHIER - -config CLK_UNIPHIER_MIO - bool "Clock driver for UniPhier Media I/O block" default y - -endmenu + help + Support for clock controllers on UniPhier SoCs. + Say Y if you want to control clocks provided by System Control + block, Media I/O block, Peripheral Block. diff --git a/drivers/clk/uniphier/Makefile b/drivers/clk/uniphier/Makefile index a3168f9bc1b..ed623aa56f7 100644 --- a/drivers/clk/uniphier/Makefile +++ b/drivers/clk/uniphier/Makefile @@ -1,3 +1,2 @@ -obj-y += clk-uniphier-core.o - -obj-$(CONFIG_CLK_UNIPHIER_MIO) += clk-uniphier-mio.o +obj-y += clk-uniphier-core.o +obj-y += clk-uniphier-mio.o diff --git a/drivers/clk/uniphier/clk-uniphier-core.c b/drivers/clk/uniphier/clk-uniphier-core.c index 394832607ed..8ad0242d2a7 100644 --- a/drivers/clk/uniphier/clk-uniphier-core.c +++ b/drivers/clk/uniphier/clk-uniphier-core.c @@ -6,11 +6,11 @@ */ #include +#include +#include #include #include #include -#include -#include #include "clk-uniphier.h" @@ -18,136 +18,106 @@ * struct uniphier_clk_priv - private data for UniPhier clock driver * * @base: base address of the clock provider - * @socdata: SoC specific data + * @data: SoC specific data */ struct uniphier_clk_priv { void __iomem *base; - const struct uniphier_clk_soc_data *socdata; + const struct uniphier_clk_data *data; }; -int uniphier_clk_probe(struct udevice *dev) +static int uniphier_clk_enable(struct clk *clk) { - struct uniphier_clk_priv *priv = dev_get_priv(dev); - fdt_addr_t addr; + struct uniphier_clk_priv *priv = dev_get_priv(clk->dev); + unsigned long id = clk->id; + const struct uniphier_clk_gate_data *p; - addr = dev_get_addr(dev->parent); - if (addr == FDT_ADDR_T_NONE) - return -EINVAL; + for (p = priv->data->gate; p->id != UNIPHIER_CLK_ID_END; p++) { + u32 val; - priv->base = devm_ioremap(dev, addr, SZ_4K); - if (!priv->base) - return -ENOMEM; + if (p->id != id) + continue; - priv->socdata = (void *)dev_get_driver_data(dev); + val = readl(priv->base + p->reg); + val |= BIT(p->bit); + writel(val, priv->base + p->reg); - return 0; + return 0; + } + + dev_err(priv->dev, "clk_id=%lu was not handled\n", id); + return -EINVAL; } -static int uniphier_clk_enable(struct clk *clk) +static const struct uniphier_clk_mux_data * +uniphier_clk_get_mux_data(struct uniphier_clk_priv *priv, unsigned long id) { - struct uniphier_clk_priv *priv = dev_get_priv(clk->dev); - 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; - int i; - - for (i = 0; i < nr_gate; i++) { - if (gate[i].index != clk->id) - continue; - - reg = priv->base + gate[i].reg; - mask = gate[i].mask; - data = gate[i].data & mask; + const struct uniphier_clk_mux_data *p; - tmp = readl(reg); - tmp &= ~mask; - tmp |= data & mask; - debug("%s: %p: %08x\n", __func__, reg, tmp); - writel(tmp, reg); + for (p = priv->data->mux; p->id != UNIPHIER_CLK_ID_END; p++) { + if (p->id == id) + return p; } - return 0; + return NULL; } static ulong uniphier_clk_get_rate(struct clk *clk) { struct uniphier_clk_priv *priv = dev_get_priv(clk->dev); - const struct uniphier_clk_rate_data *rdata = priv->socdata->rate; - unsigned int nr_rdata = priv->socdata->nr_rate; - void __iomem *reg; - u32 mask, data; - ulong matched_rate = 0; + const struct uniphier_clk_mux_data *mux; + u32 val; int i; - for (i = 0; i < nr_rdata; i++) { - if (rdata[i].index != clk->id) - continue; + mux = uniphier_clk_get_mux_data(priv, clk->id); + if (!mux) + return 0; - if (rdata[i].reg == UNIPHIER_CLK_RATE_IS_FIXED) - return rdata[i].rate; - - reg = priv->base + rdata[i].reg; - mask = rdata[i].mask; - data = rdata[i].data & mask; - if ((readl(reg) & mask) == data) { - if (matched_rate && rdata[i].rate != matched_rate) { - printf("failed to get clk rate for insane register values\n"); - return -EINVAL; - } - matched_rate = rdata[i].rate; - } - } + if (!mux->nr_muxs) /* fixed-rate */ + return mux->rates[0]; + + val = readl(priv->base + mux->reg); - debug("%s: rate = %lu\n", __func__, matched_rate); + for (i = 0; i < mux->nr_muxs; i++) + if ((mux->masks[i] & val) == mux->vals[i]) + return mux->rates[i]; - return matched_rate; + return -EINVAL; } static ulong uniphier_clk_set_rate(struct clk *clk, ulong rate) { struct uniphier_clk_priv *priv = dev_get_priv(clk->dev); - 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; + const struct uniphier_clk_mux_data *mux; + u32 val; + int i, best_rate_id = -1; ulong best_rate = 0; - int i; - /* first, decide the best match rate */ - for (i = 0; i < nr_rdata; i++) { - if (rdata[i].index != clk->id) - continue; + mux = uniphier_clk_get_mux_data(priv, clk->id); + if (!mux) + return 0; - if (rdata[i].reg == UNIPHIER_CLK_RATE_IS_FIXED) - return 0; + if (!mux->nr_muxs) /* fixed-rate */ + return mux->rates[0]; - if (rdata[i].rate > best_rate && rdata[i].rate <= rate) - best_rate = rdata[i].rate; + /* 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; + } } - if (!best_rate) - return -ENODEV; + if (best_rate_id < 0) + 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); debug("%s: requested rate = %lu, set rate = %lu\n", __func__, rate, best_rate); - /* second, really set registers */ - for (i = 0; i < nr_rdata; i++) { - if (rdata[i].index != clk->id || rdata[i].rate != best_rate) - continue; - - reg = priv->base + rdata[i].reg; - mask = rdata[i].mask; - data = rdata[i].data & mask; - - tmp = readl(reg); - tmp &= ~mask; - tmp |= data; - debug("%s: %p: %08x\n", __func__, reg, tmp); - writel(tmp, reg); - } - return best_rate; } @@ -157,6 +127,24 @@ const struct clk_ops uniphier_clk_ops = { .set_rate = uniphier_clk_set_rate, }; +static 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->data = (void *)dev_get_driver_data(dev); + + return 0; +} + static const struct udevice_id uniphier_clk_match[] = { { .compatible = "socionext,uniphier-sld3-mio-clock", diff --git a/drivers/clk/uniphier/clk-uniphier-mio.c b/drivers/clk/uniphier/clk-uniphier-mio.c index c1e7197c1a8..18e68567092 100644 --- a/drivers/clk/uniphier/clk-uniphier-mio.c +++ b/drivers/clk/uniphier/clk-uniphier-mio.c @@ -5,136 +5,81 @@ * SPDX-License-Identifier: GPL-2.0+ */ -#include - #include "clk-uniphier.h" -#define UNIPHIER_MIO_CLK_GATE_SD(ch, idx) \ - { \ - .index = (idx), \ - .reg = 0x20 + 0x200 * (ch), \ - .mask = 0x00000100, \ - .data = 0x00000100, \ - }, \ - { \ - .index = (idx), \ - .reg = 0x110 + 0x200 * (ch), \ - .mask = 0x00000001, \ - .data = 0x00000001, \ - } +#define UNIPHIER_MIO_CLK_SD_GATE(id, ch) \ + UNIPHIER_CLK_GATE((id), 0x20 + 0x200 * (ch), 8) -#define UNIPHIER_MIO_CLK_RATE_SD(ch, idx) \ - { \ - .index = (idx), \ - .reg = 0x30 + 0x200 * (ch), \ - .mask = 0x00031300, \ - .data = 0x00000000, \ - .rate = 44444444, \ - }, \ - { \ - .index = (idx), \ - .reg = 0x30 + 0x200 * (ch), \ - .mask = 0x00031300, \ - .data = 0x00010000, \ - .rate = 33333333, \ - }, \ - { \ - .index = (idx), \ - .reg = 0x30 + 0x200 * (ch), \ - .mask = 0x00031300, \ - .data = 0x00020000, \ - .rate = 50000000, \ - }, \ - { \ - .index = (idx), \ - .reg = 0x30 + 0x200 * (ch), \ - .mask = 0x00031300, \ - .data = 0x00020000, \ - .rate = 66666666, \ - }, \ - { \ - .index = (idx), \ - .reg = 0x30 + 0x200 * (ch), \ - .mask = 0x00031300, \ - .data = 0x00001000, \ - .rate = 100000000, \ - }, \ - { \ - .index = (idx), \ - .reg = 0x30 + 0x200 * (ch), \ - .mask = 0x00031300, \ - .data = 0x00001100, \ - .rate = 40000000, \ - }, \ - { \ - .index = (idx), \ - .reg = 0x30 + 0x200 * (ch), \ - .mask = 0x00031300, \ - .data = 0x00001200, \ - .rate = 25000000, \ - }, \ - { \ - .index = (idx), \ - .reg = 0x30 + 0x200 * (ch), \ - .mask = 0x00031300, \ - .data = 0x00001300, \ - .rate = 22222222, \ - } +#define UNIPHIER_MIO_CLK_USB2(id, ch) \ + UNIPHIER_CLK_GATE((id), 0x20 + 0x200 * (ch), 28) -#define UNIPHIER_MIO_CLK_GATE_USB(ch, idx) \ - { \ - .index = (idx), \ - .reg = 0x20 + 0x200 * (ch), \ - .mask = 0x30000000, \ - .data = 0x30000000, \ - }, \ - { \ - .index = (idx), \ - .reg = 0x110 + 0x200 * (ch), \ - .mask = 0x01000000, \ - .data = 0x01000000, \ - }, \ - { \ - .index = (idx), \ - .reg = 0x114 + 0x200 * (ch), \ - .mask = 0x00000001, \ - .data = 0x00000001, \ - } +#define UNIPHIER_MIO_CLK_USB2_PHY(id, ch) \ + UNIPHIER_CLK_GATE((id), 0x20 + 0x200 * (ch), 29) + +#define UNIPHIER_MIO_CLK_DMAC(id) \ + UNIPHIER_CLK_GATE((id), 0x20, 25) -#define UNIPHIER_MIO_CLK_GATE_DMAC(idx) \ - { \ - .index = (idx), \ - .reg = 0x20, \ - .mask = 0x02000000, \ - .data = 0x02000000, \ - }, \ - { \ - .index = (idx), \ - .reg = 0x110, \ - .mask = 0x00020000, \ - .data = 0x00020000, \ +#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, \ + }, \ } 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 */ - UNIPHIER_MIO_CLK_GATE_USB(0, 3), - UNIPHIER_MIO_CLK_GATE_USB(1, 4), - UNIPHIER_MIO_CLK_GATE_USB(2, 5), - UNIPHIER_MIO_CLK_GATE_DMAC(6), - UNIPHIER_MIO_CLK_GATE_USB(3, 7), /* for PH1-sLD3 only */ + 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 */ + UNIPHIER_MIO_CLK_DMAC(7), + UNIPHIER_MIO_CLK_USB2(8, 0), + UNIPHIER_MIO_CLK_USB2(9, 1), + UNIPHIER_MIO_CLK_USB2(10, 2), + UNIPHIER_MIO_CLK_USB2(11, 3), /* for PH1-sLD3 only */ + UNIPHIER_MIO_CLK_USB2_PHY(12, 0), + UNIPHIER_MIO_CLK_USB2_PHY(13, 1), + UNIPHIER_MIO_CLK_USB2_PHY(14, 2), + UNIPHIER_MIO_CLK_USB2_PHY(15, 3), /* for PH1-sLD3 only */ + UNIPHIER_CLK_END }; -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 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_soc_data uniphier_mio_clk_data = { +const struct uniphier_clk_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), + .mux = uniphier_mio_clk_mux, }; diff --git a/drivers/clk/uniphier/clk-uniphier.h b/drivers/clk/uniphier/clk-uniphier.h index 0b60337205e..f9a560ee73d 100644 --- a/drivers/clk/uniphier/clk-uniphier.h +++ b/drivers/clk/uniphier/clk-uniphier.h @@ -10,36 +10,46 @@ #include +#define UNIPHIER_CLK_MAX_NR_MUXS 8 + struct uniphier_clk_gate_data { - int index; + unsigned int id; unsigned int reg; - u32 mask; - u32 data; + unsigned int bit; }; -struct uniphier_clk_rate_data { - int index; +struct uniphier_clk_mux_data { + unsigned int id; + unsigned int nr_muxs; unsigned int reg; -#define UNIPHIER_CLK_RATE_IS_FIXED UINT_MAX - u32 mask; - u32 data; - unsigned long rate; + unsigned int masks[UNIPHIER_CLK_MAX_NR_MUXS]; + unsigned int vals[UNIPHIER_CLK_MAX_NR_MUXS]; + unsigned long rates[UNIPHIER_CLK_MAX_NR_MUXS]; }; -struct uniphier_clk_soc_data { +struct uniphier_clk_data { const struct uniphier_clk_gate_data *gate; - unsigned int nr_gate; - const struct uniphier_clk_rate_data *rate; - unsigned int nr_rate; + const struct uniphier_clk_mux_data *mux; }; -#define UNIPHIER_CLK_FIXED_RATE(i, f) \ +#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_FIXED_RATE(_id, _rate) \ { \ - .index = i, \ - .reg = UNIPHIER_CLK_RATE_IS_FIXED, \ - .rate = f, \ + .id = (_id), \ + .rates = {(_reg),}, \ } -extern const struct uniphier_clk_soc_data uniphier_mio_clk_data; +extern const struct uniphier_clk_data uniphier_mio_clk_data; #endif /* __CLK_UNIPHIER_H__ */ -- cgit v1.3.1