From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from phobos.denx.de (phobos.denx.de [85.214.62.61]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 67287C433EF for ; Fri, 22 Apr 2022 00:36:18 +0000 (UTC) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 5844183DB6; Fri, 22 Apr 2022 02:36:16 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="jhiL/xay"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 0565983DA9; Fri, 22 Apr 2022 02:36:14 +0200 (CEST) Received: from mail-qk1-x735.google.com (mail-qk1-x735.google.com [IPv6:2607:f8b0:4864:20::735]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 6802683DB6 for ; Fri, 22 Apr 2022 02:36:08 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=seanga2@gmail.com Received: by mail-qk1-x735.google.com with SMTP id d19so4832704qko.3 for ; Thu, 21 Apr 2022 17:36:08 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=subject:to:cc:references:from:message-id:date:user-agent :mime-version:in-reply-to:content-language:content-transfer-encoding; bh=I9GtawJPfWoRYdUNNku7k15Eg+lSUk0L1wnjLDo7tkY=; b=jhiL/xayCenoU1anYLLOQUv9S+QIpuoz5NI8op/Wz7EYbtvPnQVa+57jxYTcBP8k35 5EJ7FCIR6ph80Z2y9eHDoPt5OaYUfNNN+yYD95okGmm5r2k0boc3eF3L8i6pcZ6/Hipa ej5+9sJePDvEHRiw+G+Un/Ha+DbdaA+0VavTFh058P/QneqLzJHBSWVMbrP1DI8XcvJ8 cRG3bI1+aCTXhPWQP9jAd0DCHex8mZToObmfF//BCt90v4RJk4lh0ExN5SlMqdUO17W7 O88dS5sQtTwL0WSNlTDjru8EZodBPwqlhn5abMqwXKD0h3KT6erwGgE+9cTXELs9E1tT nCwg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:subject:to:cc:references:from:message-id:date :user-agent:mime-version:in-reply-to:content-language :content-transfer-encoding; bh=I9GtawJPfWoRYdUNNku7k15Eg+lSUk0L1wnjLDo7tkY=; b=25is0qnQN/Er2GVTB5afkZARPYN50l+pY1HcT/AjKpz5s+unz7r5NIyH/h2glw/7Be 7GHr3Axd8oU+MJiIGVoLMm5qfOMQ1OzJbjSuoXbHBwZaNrfTXUr0iT/KRSXGl833oBOh y06J+PD9LLL614VSJ08LzrI8ZfZ4LHVpHVjgRgSl4tCzqwzJhJIpgzVgg5AR99zEsDzl MXjsk8bDJ3RTjGXwNjoP6mswYoRsRPUlujVGVInnk8u17mb9+xrQbrC/eRC/xqHPIPek /LwlsJoNbJCB4XalbXM817j54C/1GD1BqqLub+IO2PoURQ5Xz8nV1S3CnuchIFOCYO0S mKIQ== X-Gm-Message-State: AOAM5306LwzR+sFcmTKfBuUPXzEkYrPMWo/d13o0hi0IHDoe3hN82tPB SQR2ifpDX5pPhbyzwywWUkN1oacw2BY= X-Google-Smtp-Source: ABdhPJxJJFmfBxsXJ4+cUhnvDem9XdCdAsw9AjU4sqlRNrmU0ZxCipEhUDle6R4BeeUVtDix1EOhvQ== X-Received: by 2002:a37:9b06:0:b0:69c:915f:ef6d with SMTP id d6-20020a379b06000000b0069c915fef6dmr1289483qke.682.1650587766840; Thu, 21 Apr 2022 17:36:06 -0700 (PDT) Received: from [192.168.1.201] (pool-108-18-137-133.washdc.fios.verizon.net. [108.18.137.133]) by smtp.googlemail.com with ESMTPSA id 128-20020a370486000000b0069e9d72b45fsm253124qke.13.2022.04.21.17.36.05 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Thu, 21 Apr 2022 17:36:06 -0700 (PDT) Subject: Re: [PATCH v3 2/4] clk: nuvoton: Add support for NPCM750 To: Jim Liu , JJLIU0@nuvoton.com, KWLIU@nuvoton.com, YSCHU@nuvoton.com, lukma@denx.de, sjg@chromium.org, sr@denx.de, trini@konsulko.com Cc: u-boot@lists.denx.de References: <20220419053222.29518-1-JJLIU0@nuvoton.com> <20220419053222.29518-3-JJLIU0@nuvoton.com> From: Sean Anderson Message-ID: <0b310264-1140-9786-10c3-f29cce131938@gmail.com> Date: Thu, 21 Apr 2022 20:36:05 -0400 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Thunderbird/68.12.0 MIME-Version: 1.0 In-Reply-To: <20220419053222.29518-3-JJLIU0@nuvoton.com> Content-Type: text/plain; charset=utf-8; format=flowed Content-Language: en-US Content-Transfer-Encoding: 7bit X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.5 at phobos.denx.de X-Virus-Status: Clean On 4/19/22 1:32 AM, Jim Liu wrote: > Add clock controller driver for NPCM750 > > Signed-off-by: Jim Liu > Signed-off-by: Stanley Chu > --- > Changes for v3: > - no changes since v2 > Changes for v2: > - combine NPCM750 and NPCM845 clk driver. > --- > drivers/clk/Makefile | 1 + > drivers/clk/nuvoton/Makefile | 2 + > drivers/clk/nuvoton/clk_npcm.c | 299 ++++++++++++++++++ > drivers/clk/nuvoton/clk_npcm.h | 105 ++++++ > drivers/clk/nuvoton/clk_npcm7xx.c | 95 ++++++ > .../dt-bindings/clock/nuvoton,npcm7xx-clock.h | 46 +++ > 6 files changed, 548 insertions(+) > create mode 100644 drivers/clk/nuvoton/Makefile > create mode 100644 drivers/clk/nuvoton/clk_npcm.c > create mode 100644 drivers/clk/nuvoton/clk_npcm.h > create mode 100644 drivers/clk/nuvoton/clk_npcm7xx.c > create mode 100644 include/dt-bindings/clock/nuvoton,npcm7xx-clock.h > > diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile > index bb4eee5d99..f5b553172c 100644 > --- a/drivers/clk/Makefile > +++ b/drivers/clk/Makefile > @@ -20,6 +20,7 @@ obj-$(CONFIG_ARCH_ASPEED) += aspeed/ > obj-$(CONFIG_ARCH_MEDIATEK) += mediatek/ > obj-$(CONFIG_ARCH_MESON) += meson/ > obj-$(CONFIG_ARCH_MTMIPS) += mtmips/ > +obj-$(CONFIG_ARCH_NPCM) += nuvoton/ > obj-$(CONFIG_ARCH_ROCKCHIP) += rockchip/ > obj-$(CONFIG_ARCH_SOCFPGA) += altera/ > obj-$(CONFIG_ARCH_SUNXI) += sunxi/ > diff --git a/drivers/clk/nuvoton/Makefile b/drivers/clk/nuvoton/Makefile > new file mode 100644 > index 0000000000..c63d9c16f1 > --- /dev/null > +++ b/drivers/clk/nuvoton/Makefile > @@ -0,0 +1,2 @@ > +obj-$(CONFIG_ARCH_NPCM) += clk_npcm.o > +obj-$(CONFIG_ARCH_NPCM7xx) += clk_npcm7xx.o > diff --git a/drivers/clk/nuvoton/clk_npcm.c b/drivers/clk/nuvoton/clk_npcm.c > new file mode 100644 > index 0000000000..8d71f2a24b > --- /dev/null > +++ b/drivers/clk/nuvoton/clk_npcm.c > @@ -0,0 +1,299 @@ > +// SPDX-License-Identifier: GPL-2.0+ > +/* > + * Copyright (c) 2022 Nuvoton Technology Corp. > + * > + * Formula for calculating clock rate: > + * Fout = ((Fin / PRE_DIV) / div) / POST_DIV > + */ > + > +#include > +#include > +#include > +#include > +#include > +#include "clk_npcm.h" > + > +static int clkid_to_clksel(struct npcm_clk_select *selector, int id) > +{ > + int i; > + > + for (i = 0; i < selector->num_parents; i++) { > + if (selector->parents[i].id == id) > + return selector->parents[i].clksel; > + } > + > + return -EINVAL; > +} > + > +static int clksel_to_clkid(struct npcm_clk_select *selector, int clksel) > +{ > + int i; > + > + for (i = 0; i < selector->num_parents; i++) { > + if (selector->parents[i].clksel == clksel) > + return selector->parents[i].id; > + } > + > + return -EINVAL; > +} > + > +static struct npcm_clk_pll *npcm_clk_pll_get(struct npcm_clk_data *clk_data, int id) > +{ > + struct npcm_clk_pll *pll = clk_data->clk_plls; > + int i; > + > + for (i = 0; i < clk_data->num_plls; i++) { > + if (pll->id == id) > + return pll; > + pll++; > + } > + > + return NULL; > +} > + > +static struct npcm_clk_select *npcm_clk_selector_get(struct npcm_clk_data *clk_data, > + int id) > +{ > + struct npcm_clk_select *selector = clk_data->clk_selectors; > + int i; > + > + for (i = 0; i < clk_data->num_selectors; i++) { > + if (selector->id == id) > + return selector; > + selector++; > + } > + > + return NULL; > +} > + > +static struct npcm_clk_div *npcm_clk_divider_get(struct npcm_clk_data *clk_data, > + int id) > +{ > + struct npcm_clk_div *divider = clk_data->clk_dividers; > + int i; > + > + for (i = 0; i < clk_data->num_dividers; i++) { > + if (divider->id == id) > + return divider; > + divider++; > + } > + > + return NULL; > +} > + > +static ulong npcm_clk_get_fin(struct clk *clk) > +{ > + struct npcm_clk_priv *priv = dev_get_priv(clk->dev); > + struct npcm_clk_select *selector; > + struct clk parent; > + ulong parent_rate; > + u32 val, clksel; > + int ret; > + > + selector = npcm_clk_selector_get(priv->clk_data, clk->id); > + if (!selector) > + return 0; > + > + if (selector->flags & FIXED_PARENT) { > + clksel = 0; > + } else { > + val = readl(priv->base + selector->reg); > + clksel = (val & selector->mask) >> (ffs(selector->mask) - 1); > + } > + parent.id = clksel_to_clkid(selector, clksel); > + > + ret = clk_request(clk->dev, &parent); > + if (ret) > + return 0; > + > + parent_rate = clk_get_rate(&parent); > + > + debug("fin of clk%lu = %lu\n", clk->id, parent_rate); > + return parent_rate; > +} > + > +static u32 npcm_clk_get_div(struct clk *clk) > +{ > + struct npcm_clk_priv *priv = dev_get_priv(clk->dev); > + struct npcm_clk_div *divider; > + u32 val, div; > + > + divider = npcm_clk_divider_get(priv->clk_data, clk->id); > + if (!divider) > + return 0; > + > + val = readl(priv->base + divider->reg); > + div = (val & divider->mask) >> (ffs(divider->mask) - 1); > + if (divider->flags & DIV_TYPE1) > + div = div + 1; > + else > + div = 1 << div; > + > + if (divider->flags & PRE_DIV2) > + div = div << 1; > + > + return div; > +} > + > +static u32 npcm_clk_set_div(struct clk *clk, u32 div) > +{ > + struct npcm_clk_priv *priv = dev_get_priv(clk->dev); > + struct npcm_clk_div *divider; > + u32 val, clkdiv; > + > + divider = npcm_clk_divider_get(priv->clk_data, clk->id); > + if (!divider) > + return -EINVAL; > + > + if (divider->flags & PRE_DIV2) > + div = div >> 1; > + > + if (divider->flags & DIV_TYPE1) > + clkdiv = div - 1; > + else > + clkdiv = ilog2(div); > + > + val = readl(priv->base + divider->reg); > + val &= ~divider->mask; > + val |= (clkdiv << (ffs(divider->mask) - 1)) & divider->mask; > + writel(val, priv->base + divider->reg); > + > + return 0; > +} > + > +static ulong npcm_clk_get_fout(struct clk *clk) > +{ > + ulong parent_rate; > + u32 div; > + > + parent_rate = npcm_clk_get_fin(clk); > + if (!parent_rate) > + return -EINVAL; > + > + div = npcm_clk_get_div(clk); > + if (!div) > + return -EINVAL; > + > + debug("fout of clk%lu = (%lu / %u)\n", clk->id, parent_rate, div); > + return (parent_rate / div); > +} > + > +static ulong npcm_clk_get_pll_fout(struct clk *clk) > +{ > + struct npcm_clk_priv *priv = dev_get_priv(clk->dev); > + struct npcm_clk_pll *pll; > + struct clk parent; > + ulong parent_rate; > + ulong fbdv, indv, otdv1, otdv2; > + u32 val; > + u64 ret; > + > + pll = npcm_clk_pll_get(priv->clk_data, clk->id); > + if (!pll) > + return -ENODEV; > + > + parent.id = pll->parent_id; > + ret = clk_request(clk->dev, &parent); > + if (ret) > + return ret; > + > + parent_rate = clk_get_rate(&parent); > + > + val = readl(priv->base + pll->reg); > + indv = FIELD_GET(PLLCON_INDV, val); > + fbdv = FIELD_GET(PLLCON_FBDV, val); > + otdv1 = FIELD_GET(PLLCON_OTDV1, val); > + otdv2 = FIELD_GET(PLLCON_OTDV2, val); > + > + ret = (u64)parent_rate * fbdv; > + do_div(ret, indv * otdv1 * otdv2); > + if (pll->flags & POST_DIV2) > + do_div(ret, 2); > + > + debug("fout of pll(id %lu) = %llu\n", clk->id, ret); > + return ret; > +} > + > +static ulong npcm_clk_get_rate(struct clk *clk) > +{ > + struct npcm_clk_priv *priv = dev_get_priv(clk->dev); > + struct npcm_clk_data *clk_data = priv->clk_data; > + struct clk refclk; > + int ret; > + > + debug("%s: id %lu\n", __func__, clk->id); > + if (clk->id == clk_data->refclk_id) { > + ret = clk_get_by_name(clk->dev, "refclk", &refclk); > + if (!ret) > + return clk_get_rate(&refclk); > + else > + return ret; > + } > + > + if (clk->id >= clk_data->pll0_id && > + clk->id < clk_data->pll0_id + clk_data->num_plls) > + return npcm_clk_get_pll_fout(clk); > + else > + return npcm_clk_get_fout(clk); > +} > + > +static ulong npcm_clk_set_rate(struct clk *clk, ulong rate) > +{ > + ulong parent_rate; > + u32 div; > + int ret; > + > + debug("%s: id %lu, rate %lu\n", __func__, clk->id, rate); > + parent_rate = npcm_clk_get_fin(clk); > + if (!parent_rate) > + return -EINVAL; > + > + div = DIV_ROUND_UP(parent_rate, rate); > + ret = npcm_clk_set_div(clk, div); > + if (ret) > + return ret; > + > + debug("%s: rate %lu, new rate (%lu / %u)\n", __func__, rate, parent_rate, div); > + return (parent_rate / div); > +} > + > +static int npcm_clk_set_parent(struct clk *clk, struct clk *parent) > +{ > + struct npcm_clk_priv *priv = dev_get_priv(clk->dev); > + struct npcm_clk_select *selector; > + int clksel; > + u32 val; > + > + debug("%s: id %lu, parent %lu\n", __func__, clk->id, parent->id); > + selector = npcm_clk_selector_get(priv->clk_data, clk->id); > + if (!selector) > + return -EINVAL; > + > + clksel = clkid_to_clksel(selector, parent->id); > + if (clksel < 0) > + return -EINVAL; > + > + val = readl(priv->base + selector->reg); > + val &= ~selector->mask; > + val |= clksel << (ffs(selector->mask) - 1); > + writel(val, priv->base + selector->reg); > + > + return 0; > +} > + > +static int npcm_clk_request(struct clk *clk) > +{ > + struct npcm_clk_priv *priv = dev_get_priv(clk->dev); > + > + if (clk->id >= priv->num_clks) > + return -EINVAL; > + > + return 0; > +} > + > +const struct clk_ops npcm_clk_ops = { > + .get_rate = npcm_clk_get_rate, > + .set_rate = npcm_clk_set_rate, > + .set_parent = npcm_clk_set_parent, > + .request = npcm_clk_request, > +}; > diff --git a/drivers/clk/nuvoton/clk_npcm.h b/drivers/clk/nuvoton/clk_npcm.h > new file mode 100644 > index 0000000000..06b60dc8b8 > --- /dev/null > +++ b/drivers/clk/nuvoton/clk_npcm.h > @@ -0,0 +1,105 @@ > +/* SPDX-License-Identifier: GPL-2.0+ */ > + > +#ifndef _CLK_NPCM_H_ > +#define _CLK_NPCM_H_ > + > +#include > + > +/* Register offsets */ > +#define CLKSEL 0x04 /* clock source selection */ > +#define CLKDIV1 0x08 /* clock divider 1 */ > +#define CLKDIV2 0x2C /* clock divider 2 */ > +#define CLKDIV3 0x58 /* clock divider 3 */ > +#define PLLCON0 0x0C /* pll0 control */ > +#define PLLCON1 0x10 /* pll1 control */ > +#define PLLCON2 0x54 /* pll2 control */ > + > +/* CLKSEL bit filed */ > +#define NPCM7XX_CPUCKSEL GENMASK(1, 0) > +#define NPCM8XX_CPUCKSEL GENMASK(2, 0) > +#define SDCKSEL GENMASK(7, 6) > +#define UARTCKSEL GENMASK(9, 8) > +#define TIMCKSEL GENMASK(15, 14) > + > +/* CLKDIV1 bit filed */ > +#define SPI3CKDIV GENMASK(10, 6) > +#define MMCCKDIV GENMASK(15, 11) > +#define UARTDIV1 GENMASK(20, 16) > +#define TIMCKDIV GENMASK(25, 21) > +#define CLK4DIV GENMASK(27, 26) > + > +/* CLKDIV2 bit filed */ > +#define APB5CKDIV GENMASK(23, 22) > +#define APB2CKDIV GENMASK(27, 26) > + > +/* CLKDIV3 bit filed */ > +#define SPIXCKDIV GENMASK(5, 1) > +#define SPI0CKDIV GENMASK(10, 6) > +#define UARTDIV2 GENMASK(15, 11) > +#define SPI1CKDIV GENMASK(23, 16) > + > +/* PLLCON bit filed */ > +#define PLLCON_INDV GENMASK(5, 0) > +#define PLLCON_OTDV1 GENMASK(10, 8) > +#define PLLCON_OTDV2 GENMASK(15, 13) > +#define PLLCON_FBDV GENMASK(27, 16) > + > +/* Flags */ > +#define DIV_TYPE1 BIT(0) /* div = clkdiv + 1 */ > +#define DIV_TYPE2 BIT(1) /* div = 1 << clkdiv */ > +#define PRE_DIV2 BIT(2) /* Pre divisor = 2 */ > +#define POST_DIV2 BIT(3) /* Post divisor = 2 */ > +#define FIXED_PARENT BIT(4) /* clock source is fixed */ > + > +/* Parameters of PLL configuration */ > +struct npcm_clk_pll { > + const int id; > + const int parent_id; > + u32 reg; > + u32 flags; > +}; > + > +/* Parent clock id to clksel mapping */ > +struct parent_data { > + int id; > + int clksel; > +}; > + > +/* Parameters of parent selection */ > +struct npcm_clk_select { > + const int id; > + const struct parent_data *parents; > + u32 reg; > + u32 mask; > + u8 num_parents; > + u32 flags; > +}; > + > +/* Parameters of clock divider */ > +struct npcm_clk_div { > + const int id; > + u32 reg; > + u32 mask; > + u32 flags; > +}; > + > +struct npcm_clk_data { > + struct npcm_clk_pll *clk_plls; > + int num_plls; > + struct npcm_clk_select *clk_selectors; > + int num_selectors; > + struct npcm_clk_div *clk_dividers; > + int num_dividers; > + int refclk_id; > + int pll0_id; > +}; > + > +struct npcm_clk_priv { > + void __iomem *base; > + struct npcm_clk_data *clk_data; > + int num_clks; > +}; > + > +extern const struct clk_ops npcm_clk_ops; > + > +#endif > diff --git a/drivers/clk/nuvoton/clk_npcm7xx.c b/drivers/clk/nuvoton/clk_npcm7xx.c > new file mode 100644 > index 0000000000..a12aaa2f4c > --- /dev/null > +++ b/drivers/clk/nuvoton/clk_npcm7xx.c > @@ -0,0 +1,95 @@ > +// SPDX-License-Identifier: GPL-2.0+ > +/* > + * Copyright (c) 2021 Nuvoton Technology Corp. > + */ > + > +#include > +#include > +#include "clk_npcm.h" > + > +/* Parent clock map */ > +static const struct parent_data pll_parents[] = { > + {NPCM7XX_CLK_PLL0, 0}, > + {NPCM7XX_CLK_PLL1, 1}, > + {NPCM7XX_CLK_REFCLK, 2}, > + {NPCM7XX_CLK_PLL2DIV2, 3} > +}; > + > +static const struct parent_data cpuck_parents[] = { > + {NPCM7XX_CLK_PLL0, 0}, > + {NPCM7XX_CLK_PLL1, 1}, > + {NPCM7XX_CLK_REFCLK, 2}, > +}; > + > +static const struct parent_data apb_parent[] = {{NPCM7XX_CLK_AHB, 0}}; > + > +static struct npcm_clk_pll npcm7xx_clk_plls[] = { > + {NPCM7XX_CLK_PLL0, NPCM7XX_CLK_REFCLK, PLLCON0, 0}, > + {NPCM7XX_CLK_PLL1, NPCM7XX_CLK_REFCLK, PLLCON1, 0}, > + {NPCM7XX_CLK_PLL2, NPCM7XX_CLK_REFCLK, PLLCON2, 0}, > + {NPCM7XX_CLK_PLL2DIV2, NPCM7XX_CLK_REFCLK, PLLCON2, POST_DIV2} > +}; > + > +static struct npcm_clk_select npcm7xx_clk_selectors[] = { > + {NPCM7XX_CLK_AHB, cpuck_parents, CLKSEL, NPCM7XX_CPUCKSEL, 3, 0}, > + {NPCM7XX_CLK_APB2, apb_parent, 0, 0, 1, FIXED_PARENT}, > + {NPCM7XX_CLK_APB5, apb_parent, 0, 0, 1, FIXED_PARENT}, > + {NPCM7XX_CLK_SPI0, apb_parent, 0, 0, 1, FIXED_PARENT}, > + {NPCM7XX_CLK_SPI3, apb_parent, 0, 0, 1, FIXED_PARENT}, > + {NPCM7XX_CLK_SPIX, apb_parent, 0, 0, 1, FIXED_PARENT}, > + {NPCM7XX_CLK_UART, pll_parents, CLKSEL, UARTCKSEL, 4, 0}, > + {NPCM7XX_CLK_TIMER, pll_parents, CLKSEL, TIMCKSEL, 4, 0}, > + {NPCM7XX_CLK_SDHC, pll_parents, CLKSEL, SDCKSEL, 4, 0} > +}; > + > +static struct npcm_clk_div npcm7xx_clk_dividers[] = { > + {NPCM7XX_CLK_AHB, CLKDIV1, CLK4DIV, DIV_TYPE1 | PRE_DIV2}, > + {NPCM7XX_CLK_APB2, CLKDIV2, APB2CKDIV, DIV_TYPE2}, > + {NPCM7XX_CLK_APB5, CLKDIV2, APB5CKDIV, DIV_TYPE2}, > + {NPCM7XX_CLK_SPI0, CLKDIV3, SPI0CKDIV, DIV_TYPE1}, > + {NPCM7XX_CLK_SPI3, CLKDIV1, SPI3CKDIV, DIV_TYPE1}, > + {NPCM7XX_CLK_SPIX, CLKDIV3, SPIXCKDIV, DIV_TYPE1}, > + {NPCM7XX_CLK_UART, CLKDIV1, UARTDIV1, DIV_TYPE1}, > + {NPCM7XX_CLK_TIMER, CLKDIV1, TIMCKDIV, DIV_TYPE2}, > + {NPCM7XX_CLK_SDHC, CLKDIV1, MMCCKDIV, DIV_TYPE1} > +}; > + > +static struct npcm_clk_data npcm7xx_clk_data = { > + .clk_plls = npcm7xx_clk_plls, > + .num_plls = ARRAY_SIZE(npcm7xx_clk_plls), > + .clk_selectors = npcm7xx_clk_selectors, > + .num_selectors = ARRAY_SIZE(npcm7xx_clk_selectors), > + .clk_dividers = npcm7xx_clk_dividers, > + .num_dividers = ARRAY_SIZE(npcm7xx_clk_dividers), > + .refclk_id = NPCM7XX_CLK_REFCLK, > + .pll0_id = NPCM7XX_CLK_PLL0, > +}; > + > +static int npcm7xx_clk_probe(struct udevice *dev) > +{ > + struct npcm_clk_priv *priv = dev_get_priv(dev); > + > + priv->base = dev_read_addr_ptr(dev); > + if (!priv->base) > + return -EINVAL; > + > + priv->clk_data = &npcm7xx_clk_data; > + priv->num_clks = NPCM7XX_NUM_CLOCKS; > + > + return 0; > +} > + > +static const struct udevice_id npcm7xx_clk_ids[] = { > + { .compatible = "nuvoton,npcm750-clk" }, > + { } > +}; > + > +U_BOOT_DRIVER(clk_npcm) = { > + .name = "clk_npcm", > + .id = UCLASS_CLK, > + .of_match = npcm7xx_clk_ids, > + .ops = &npcm_clk_ops, > + .priv_auto = sizeof(struct npcm_clk_priv), > + .probe = npcm7xx_clk_probe, > + .flags = DM_FLAG_PRE_RELOC, > +}; > diff --git a/include/dt-bindings/clock/nuvoton,npcm7xx-clock.h b/include/dt-bindings/clock/nuvoton,npcm7xx-clock.h > new file mode 100644 > index 0000000000..65e6bc4eee > --- /dev/null > +++ b/include/dt-bindings/clock/nuvoton,npcm7xx-clock.h > @@ -0,0 +1,46 @@ > +/* SPDX-License-Identifier: GPL-2.0 */ > +/* > + * Nuvoton NPCM7xx Clock Generator binding > + * clock binding number for all clocks supportted by nuvoton,npcm7xx-clk > + * > + * Copyright (C) 2018 Nuvoton Technologies tali.perry@nuvoton.com > + * > + */ > + > +#ifndef __DT_BINDINGS_CLOCK_NPCM7XX_H > +#define __DT_BINDINGS_CLOCK_NPCM7XX_H > + > +#define NPCM7XX_CLK_CPU 0 > +#define NPCM7XX_CLK_GFX_PIXEL 1 > +#define NPCM7XX_CLK_MC 2 > +#define NPCM7XX_CLK_ADC 3 > +#define NPCM7XX_CLK_AHB 4 > +#define NPCM7XX_CLK_TIMER 5 > +#define NPCM7XX_CLK_UART 6 > +#define NPCM7XX_CLK_MMC 7 > +#define NPCM7XX_CLK_SPI3 8 > +#define NPCM7XX_CLK_PCI 9 > +#define NPCM7XX_CLK_AXI 10 > +#define NPCM7XX_CLK_APB4 11 > +#define NPCM7XX_CLK_APB3 12 > +#define NPCM7XX_CLK_APB2 13 > +#define NPCM7XX_CLK_APB1 14 > +#define NPCM7XX_CLK_APB5 15 > +#define NPCM7XX_CLK_CLKOUT 16 > +#define NPCM7XX_CLK_GFX 17 > +#define NPCM7XX_CLK_SU 18 > +#define NPCM7XX_CLK_SU48 19 > +#define NPCM7XX_CLK_SDHC 20 > +#define NPCM7XX_CLK_SPI0 21 > +#define NPCM7XX_CLK_SPIX 22 > +#define NPCM7XX_CLK_REFCLK 23 > +#define NPCM7XX_CLK_SYSBYPCK 24 > +#define NPCM7XX_CLK_MCBYPCK 25 > +#define NPCM7XX_CLK_PLL0 26 > +#define NPCM7XX_CLK_PLL1 27 > +#define NPCM7XX_CLK_PLL2 28 > +#define NPCM7XX_CLK_PLL2DIV2 29 > +#define NPCM7XX_NUM_CLOCKS (NPCM7XX_CLK_PLL2DIV2 + 1) > + > +#endif > + > Reviewed-by: Sean Anderson