From patchwork Mon Oct 17 13:18:01 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Masahiro Yamada X-Patchwork-Id: 77742 Delivered-To: patch@linaro.org Received: by 10.140.97.247 with SMTP id m110csp390414qge; Mon, 17 Oct 2016 06:15:56 -0700 (PDT) X-Received: by 10.28.141.148 with SMTP id p142mr7838525wmd.107.1476710156169; Mon, 17 Oct 2016 06:15:56 -0700 (PDT) Return-Path: Received: from theia.denx.de (theia.denx.de. [85.214.87.163]) by mx.google.com with ESMTP id gs10si41450056wjb.257.2016.10.17.06.15.55; Mon, 17 Oct 2016 06:15:56 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of u-boot-bounces@lists.denx.de designates 85.214.87.163 as permitted sender) client-ip=85.214.87.163; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@nifty.com; spf=pass (google.com: best guess record for domain of u-boot-bounces@lists.denx.de designates 85.214.87.163 as permitted sender) smtp.mailfrom=u-boot-bounces@lists.denx.de Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id E22DCB383A; Mon, 17 Oct 2016 15:15:51 +0200 (CEST) Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id ukWXn7DkS7ho; Mon, 17 Oct 2016 15:15:51 +0200 (CEST) Received: from theia.denx.de (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id A8215A75FF; Mon, 17 Oct 2016 15:15:49 +0200 (CEST) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id D9B62A75C3 for ; Mon, 17 Oct 2016 15:15:41 +0200 (CEST) Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id RuR45htDsjAW for ; Mon, 17 Oct 2016 15:15:41 +0200 (CEST) X-policyd-weight: NOT_IN_SBL_XBL_SPAMHAUS=-1.5 NOT_IN_SPAMCOP=-1.5 NOT_IN_BL_NJABL=-1.5 (only DNSBL check requested) Received: from conuserg-12.nifty.com (conuserg-12.nifty.com [210.131.2.79]) by theia.denx.de (Postfix) with ESMTPS id 20D48A759C for ; Mon, 17 Oct 2016 15:15:40 +0200 (CEST) Received: from beagle.diag.org (p14092-ipngnfx01kyoto.kyoto.ocn.ne.jp [153.142.97.92]) (authenticated) by conuserg-12.nifty.com with ESMTP id u9HDFWtZ028415; Mon, 17 Oct 2016 22:15:33 +0900 DKIM-Filter: OpenDKIM Filter v2.10.3 conuserg-12.nifty.com u9HDFWtZ028415 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=nifty.com; s=dec2015msa; t=1476710133; bh=MzUAvWZR2obyHDp98z19K1yrLwfHh2Um+A5jbdO1G/0=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=ufyDAwZF+RgIhUwl4hih0sbyqUb8C7R4EXqv/3xEDRM2aceFBO3TPtcX2zmnfD4MI V+p+y0CNvZ9uWFNCKzFWiiThAhu88Y/rDKXV2/sZ98i/sOviMlxS3F3M19+0Oxf171 YM9xSIzbTtUzQZR5NMa3X2sGFZ475YJuO73VeZ1JOw7gRtQzByx386EZp6YIUhUUSL /69pwPLUtWM/In/zbyh+91iP4jj3oy9rQy5GhMq6qgPfqLKI6JshWMGDLVrs1d3yTc /gV7FK9qs5XV5LLuH4/4aNQIgTGjHWIctdCx8MIY/j+lw9DEIu8a0MB7qxIa/numW5 lA/nk8OGpXGiQ== X-Nifty-SrcIP: [153.142.97.92] From: Masahiro Yamada To: u-boot@lists.denx.de Date: Mon, 17 Oct 2016 22:18:01 +0900 Message-Id: <1476710283-19586-2-git-send-email-yamada.masahiro@socionext.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1476710283-19586-1-git-send-email-yamada.masahiro@socionext.com> References: <1476710283-19586-1-git-send-email-yamada.masahiro@socionext.com> Subject: [U-Boot] [PATCH 1/3] clk: uniphier: rework UniPhier clk driver X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.15 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" 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(-) -- 1.9.1 _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot diff --git a/drivers/clk/uniphier/Kconfig b/drivers/clk/uniphier/Kconfig index 0e90c01..da3e355 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 a3168f9..ed623aa 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 3948326..8ad0242 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 c1e7197..18e6856 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 0b60337..f9a560e 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__ */