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 934A8C433EF for ; Wed, 15 Dec 2021 03:01:58 +0000 (UTC) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 3342883022; Wed, 15 Dec 2021 04:01:39 +0100 (CET) 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="TySREo4R"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 831CC8069D; Wed, 15 Dec 2021 03:58:47 +0100 (CET) Received: from mail-pj1-x1032.google.com (mail-pj1-x1032.google.com [IPv6:2607:f8b0:4864:20::1032]) (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 019AC82F66 for ; Wed, 15 Dec 2021 03:58:41 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=stanley.chuys@gmail.com Received: by mail-pj1-x1032.google.com with SMTP id np3so16057192pjb.4 for ; Tue, 14 Dec 2021 18:58:40 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=bEjJbs4j9gwiiTBBfqmFFMtQ0lhPiQQ/Xv+vHytEXdQ=; b=TySREo4Ro4g8tCEWLYL5kd4eoHATXj/XDyNIfvSSRbzzCaQWRn54xq/WKFnd4TreaI +q8xAQR5AEy2JTPyiEz95vy5ojZfdgWe/Kqlzn1zQ6mbq8MJMyHiBvCPdEi8Zv6zn9qr eRT+gQ2j1I9JHGeO9Zv6Cvjf4dT8e3300arCGOU8+FEOIQyu2+VLlLt21Ir1g1Am6P87 80SZck0TaLNYkNxikmrFUtXCk8N9Q9o3a5oggy1QgbLbv1kjjiXfZvczRsoJt3bq5opk K1F6oB3E0NaRO+BvlVMWQlgFhoM7wY7iWIrOztRJP0opnG8dh2IgDST7rluMMDo5WG2h pL/Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=bEjJbs4j9gwiiTBBfqmFFMtQ0lhPiQQ/Xv+vHytEXdQ=; b=dxKjr0QASd7DkpEDSD8jHaaBvqCEcsT2XOujTDA6mUn4OO72vUkU/tSIw3IYuGLB+K rjg14GMcCMJO6oDRu/vQQxH3BRMMGLt0cI0V5T0Kn7S/OMIK2MtGw7J+LSqI8BbrFlow 2g4Ksk2Ek26gitI9jFvwQYkEi0JzLBC73PUOLeATej3KJwcyLbDhOG3/RML83/CxsL2o fG/+4Z8r9A/WUTK0pW99sH782sbGFPOVHMJ3wExFOfREag6UHRcH3ZdxZyxV0iWs6dmx j1r8zmwEuKOOTad1/ACAIa2VLfvcxzTQeCVGUNkrR2tkJ3g4tmb46G1yFOhsZbWXa8yE CsJg== X-Gm-Message-State: AOAM531zreCi2uavpxYAvoFCn0+QnbJmkcgW5jBtRLr2NzKdCCUUTKSp DmVWJivlz2wkEYhZ5Cyi+uM= X-Google-Smtp-Source: ABdhPJzv0yZxFLc7xK5vWxxyTA76Ev1ReebzSZgarg2Nc6dikj4wZFHJbmQxNyl2QGzntI/a2nCT8w== X-Received: by 2002:a17:90b:17cd:: with SMTP id me13mr9509268pjb.79.1639537119257; Tue, 14 Dec 2021 18:58:39 -0800 (PST) Received: from cs20-buildserver.lan ([180.217.149.17]) by smtp.gmail.com with ESMTPSA id q18sm437413pfn.83.2021.12.14.18.58.32 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 14 Dec 2021 18:58:38 -0800 (PST) From: Stanley Chu X-Google-Original-From: Stanley Chu To: lukma@denx.de, jagan@amarulasolutions.com, andre.przywara@arm.com, festevam@denx.de, narmstrong@baylibre.com, pbrobinson@gmail.com, tharvey@gateworks.com, christianshewitt@gmail.com, lokeshvutla@ti.com, sjg@chromium.org, sr@denx.de, michal.simek@xilinx.com, hs@denx.de, weijie.gao@mediatek.com, hannes.schmelzer@br-automation.com, harm.berntsen@nedap.com, sebastian.reichel@collabora.com, stephan@gerhold.net, fangyuanseu@gmail.com, kettenis@openbsd.org, seanga2@gmail.com, dsankouski@gmail.com, vabhav.sharma@nxp.com, bmeng.cn@gmail.com, patrick@blueri.se, samuel@sholland.org, giulio.benetti@benettiengineering.com, mr.bossman075@gmail.com, yschu@nuvoton.com, kwliu@nuvoton.com, ctcchien@nuvoton.com, avifishman70@gmail.com, tmaimon77@gmail.com Cc: u-boot@lists.denx.de, openbmc@lists.ozlabs.org Subject: [PATCH v1 2/9] clk: nuvoton: Add support for NPCM845 Date: Wed, 15 Dec 2021 10:57:53 +0800 Message-Id: <20211215025800.26918-3-yschu@nuvoton.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20211215025800.26918-1-yschu@nuvoton.com> References: <20211215025800.26918-1-yschu@nuvoton.com> X-Mailman-Approved-At: Wed, 15 Dec 2021 04:01:29 +0100 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.38 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.2 at phobos.denx.de X-Virus-Status: Clean Add clock controller driver for NPCM845 Signed-off-by: Stanley Chu --- drivers/clk/Makefile | 1 + drivers/clk/nuvoton/Makefile | 1 + drivers/clk/nuvoton/clk_npcm8xx.c | 213 ++++++++++++++++++++++ include/dt-bindings/clock/npcm845-clock.h | 17 ++ 4 files changed, 232 insertions(+) create mode 100644 drivers/clk/nuvoton/Makefile create mode 100644 drivers/clk/nuvoton/clk_npcm8xx.c create mode 100644 include/dt-bindings/clock/npcm845-clock.h diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index 711ae5bc29..a3b64b73c2 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -53,3 +53,4 @@ obj-$(CONFIG_STM32H7) += clk_stm32h7.o obj-$(CONFIG_CLK_VERSAL) += clk_versal.o obj-$(CONFIG_CLK_CDCE9XX) += clk-cdce9xx.o obj-$(CONFIG_CLK_VERSACLOCK) += clk_versaclock.o +obj-$(CONFIG_ARCH_NPCM) += nuvoton/ diff --git a/drivers/clk/nuvoton/Makefile b/drivers/clk/nuvoton/Makefile new file mode 100644 index 0000000000..998e5329bb --- /dev/null +++ b/drivers/clk/nuvoton/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_ARCH_NPCM8XX) += clk_npcm8xx.o diff --git a/drivers/clk/nuvoton/clk_npcm8xx.c b/drivers/clk/nuvoton/clk_npcm8xx.c new file mode 100644 index 0000000000..c547c47e82 --- /dev/null +++ b/drivers/clk/nuvoton/clk_npcm8xx.c @@ -0,0 +1,213 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2021 Nuvoton Technology. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +struct npcm_clk_priv { + struct clk_ctl *regs; +}; + +enum regss { + PLL_0, + PLL_1, + PLL_2, + PLL_CLKREF, +}; + +static u32 clk_get_pll_freq(struct clk_ctl *regs, enum regss pll) +{ + u32 pllval; + u32 fin = EXT_CLOCK_FREQUENCY_KHZ; /* 25KHz */ + u32 fout, nr, nf, no; + + switch (pll) { + case PLL_0: + pllval = readl(®s->pllcon0); + break; + case PLL_1: + pllval = readl(®s->pllcon1); + break; + case PLL_2: + pllval = readl(®s->pllcon2); + break; + case PLL_CLKREF: + default: + return 0; + } + + /* PLL Input Clock Divider */ + nr = (pllval >> PLLCON_INDV) & 0x1f; + /* PLL VCO Output Clock Feedback Divider */ + nf = (pllval >> PLLCON_FBDV) & 0xfff; + /* PLL Output Clock Divider 1 */ + no = ((pllval >> PLLCON_OTDV1) & 0x7) * + ((pllval >> PLLCON_OTDV2) & 0x7); + + fout = ((10 * fin * nf) / (no * nr)); + + return fout * 100; +} + +static u32 npcm_mmc_set_rate(struct clk_ctl *regs, ulong rate) +{ + u32 pll0_freq, div, sdhci_clk; + + /* To acquire PLL0 frequency. */ + pll0_freq = clk_get_pll_freq(regs, PLL_0); + + /* Calculate rounded up div to produce closest to + * target output clock + */ + div = (pll0_freq % rate == 0) ? (pll0_freq / rate) : + (pll0_freq / rate) + 1; + + writel((readl(®s->clkdiv1) & ~(0x1f << CLKDIV1_MMCCKDIV)) + | (div - 1) << CLKDIV1_MMCCKDIV, ®s->clkdiv1); + + /* Wait to the div to stabilize */ + udelay(100); + + /* Select PLL0 as source */ + writel((readl(®s->clksel) & ~(0x3 << CLKSEL_SDCKSEL)) + | (CLKSEL_SDCKSEL_PLL0 << CLKSEL_SDCKSEL), + ®s->clksel); + + sdhci_clk = pll0_freq / div; + + return sdhci_clk; +} + +static u32 npcm_uart_set_rate(struct clk_ctl *regs, ulong rate) +{ + u32 src_freq, div; + + src_freq = clk_get_pll_freq(regs, PLL_2) / 2; + div = (src_freq % rate == 0) ? (src_freq / rate) : + (src_freq / rate) + 1; + writel((readl(®s->clkdiv1) & ~(0x1f << CLKDIV1_UARTDIV)) + | (div - 1) << CLKDIV1_UARTDIV, ®s->clkdiv1); + writel((readl(®s->clksel) & ~(3 << CLKSEL_UARTCKSEL)) + | (CLKSEL_UARTCKSEL_PLL2 << CLKSEL_UARTCKSEL), + ®s->clksel); + + return (src_freq / div); +} + +static ulong npcm_get_cpu_freq(struct clk_ctl *regs) +{ + ulong fout = 0; + u32 clksel = readl(®s->clksel) & (0x3 << CLKSEL_CPUCKSEL); + + if (clksel == CLKSEL_CPUCKSEL_PLL0) + fout = (ulong)clk_get_pll_freq(regs, PLL_0); + else if (clksel == CLKSEL_CPUCKSEL_PLL1) + fout = (ulong)clk_get_pll_freq(regs, PLL_1); + else if (clksel == CLKSEL_CPUCKSEL_CLKREF) + fout = EXT_CLOCK_FREQUENCY_MHZ; /* FOUT is specified in MHz */ + else + fout = EXT_CLOCK_FREQUENCY_MHZ; /* FOUT is specified in MHz */ + + return fout; +} + +static u32 npcm_get_apb_divisor(struct clk_ctl *regs, u32 apb) +{ + u32 apb_divisor = 2; + + /* AHBn div */ + apb_divisor = apb_divisor * (1 << ((readl(®s->clkdiv1) + >> CLKDIV1_CLK4DIV) & 0x3)); + + switch (apb) { + case APB2: /* APB divisor */ + apb_divisor = apb_divisor * + (1 << ((readl(®s->clkdiv2) + >> CLKDIV2_APB2CKDIV) & 0x3)); + break; + case APB5: /* APB divisor */ + apb_divisor = apb_divisor * + (1 << ((readl(®s->clkdiv2) + >> CLKDIV2_APB5CKDIV) & 0x3)); + break; + default: + apb_divisor = 0xFFFFFFFF; + break; + } + + return apb_divisor; +} + +static ulong npcm_clk_get_rate(struct clk *clk) +{ + struct npcm_clk_priv *priv = dev_get_priv(clk->dev); + + switch (clk->id) { + case CLK_APB2: + return npcm_get_cpu_freq(priv->regs) / + npcm_get_apb_divisor(priv->regs, APB2); + case CLK_APB5: + return npcm_get_cpu_freq(priv->regs) / + npcm_get_apb_divisor(priv->regs, APB5); + } + + return 0; +} + +static ulong npcm_clk_set_rate(struct clk *clk, ulong rate) +{ + struct npcm_clk_priv *priv = dev_get_priv(clk->dev); + + switch (clk->id) { + case CLK_EMMC: + return npcm_mmc_set_rate(priv->regs, rate); + + case CLK_UART: + return npcm_uart_set_rate(priv->regs, rate); + default: + return -ENOENT; + } + + return 0; +} + +static int npcm_clk_probe(struct udevice *dev) +{ + struct npcm_clk_priv *priv = dev_get_priv(dev); + void *base; + + base = dev_read_addr_ptr(dev); + if (!base) + return -ENOENT; + + priv->regs = (struct clk_ctl *)base; + + return 0; +} + +static struct clk_ops npcm_clk_ops = { + .get_rate = npcm_clk_get_rate, + .set_rate = npcm_clk_set_rate, +}; + +static const struct udevice_id npcm_clk_ids[] = { + { .compatible = "nuvoton,npcm845-clock" }, + { } +}; + +U_BOOT_DRIVER(clk_npcm) = { + .name = "clk_npcm", + .id = UCLASS_CLK, + .of_match = npcm_clk_ids, + .ops = &npcm_clk_ops, + .priv_auto = sizeof(struct npcm_clk_priv), + .probe = npcm_clk_probe, +}; diff --git a/include/dt-bindings/clock/npcm845-clock.h b/include/dt-bindings/clock/npcm845-clock.h new file mode 100644 index 0000000000..fca10d39c8 --- /dev/null +++ b/include/dt-bindings/clock/npcm845-clock.h @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ + +#ifndef _DT_BINDINGS_NPCM845_CLOCK_H_ +#define _DT_BINDINGS_NPCM845_CLOCK_H_ + +#define CLK_TIMER 0 +#define CLK_UART 1 +#define CLK_SD 2 +#define CLK_EMMC 3 +#define CLK_APB1 4 +#define CLK_APB2 5 +#define CLK_APB3 6 +#define CLK_APB4 7 +#define CLK_APB5 8 +#define CLK_AHB 9 + +#endif -- 2.17.1