From patchwork Tue Feb 28 13:29:58 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jerome Brunet X-Patchwork-Id: 9595577 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id DAD7B601D7 for ; Tue, 28 Feb 2017 13:30:54 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id C75DF28520 for ; Tue, 28 Feb 2017 13:30:54 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id B938528524; Tue, 28 Feb 2017 13:30:54 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-1.9 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID autolearn=ham version=3.3.1 Received: from bombadil.infradead.org (bombadil.infradead.org [65.50.211.133]) (using TLSv1.2 with cipher AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 0E08828520 for ; Tue, 28 Feb 2017 13:30:53 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:MIME-Version:Cc:List-Subscribe: List-Help:List-Post:List-Archive:List-Unsubscribe:List-Id:References: In-Reply-To:Message-Id:Date:Subject:To:From:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Owner; bh=BHcNx0yLmkpVGnkCR7NMAjM+nVZyBo/PIq4XeFFPgPM=; b=sQVp6plOxVxGOthE93MOrnyK0j LGKGMiOO5CXRZYZTCkj1IOD1Ujd92VVRCjW+uvOeOTMHmGrT+o8bzfBeyD7+LwdHe0EwjLSNRScuM e5J1QdGm3s5r+rBXgyLJCEab4uJeizob045ELKqpzVG4KgU7lg0bX1+7HQzvQIhsVw8dOKfoxyPmP lTpTY8Wql+j0pE3vBQROLf0HP7WvUVHgfq20g3GbwqxiosKTDNmyyy2DrztPNmIDNnItnBtLQXIfH R24Xnj5h6uRaJRTHLO8zvN7YdXzCaDfg9Vj56AO5QkwHKGOvh/nqkvFb+slmGvQ2i97XVcNlu3XRw EPzlN/1w==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.87 #1 (Red Hat Linux)) id 1cihrb-0004E5-Hg; Tue, 28 Feb 2017 13:30:47 +0000 Received: from mail-wm0-x22b.google.com ([2a00:1450:400c:c09::22b]) by bombadil.infradead.org with esmtps (Exim 4.87 #1 (Red Hat Linux)) id 1cihrV-00046C-Gq for linux-amlogic@lists.infradead.org; Tue, 28 Feb 2017 13:30:45 +0000 Received: by mail-wm0-x22b.google.com with SMTP id i17so2834342wmf.0 for ; Tue, 28 Feb 2017 05:30:21 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre-com.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=qDsz9jwThzDetPi4Rs/UmVT7DI13lE3sZqIpvWGhGtQ=; b=tNIymn6FZbVCT8iykZ/doO4MgL5u3IG0vCj77s1bo9NmVKACrDANwXxPCkp3z2kYk/ Rx+1U40dISqBJT/Jgqr6F2S/outDFdSI8FfUKUds9HtSAhUawFk3+28VwRsARcOABle2 BzhQZro1J0sH1H7Ap1EzFj/fQjYErBzynGbTlOpRGGjPfVTNNuEoCCLd2DOU0GFuro7X qhCT4eo5vzZx6tjeb3b/waw7hHAvJgOKKbFuAZ7l1kTo/KqaNmzyUHmmBxzbfi0fIJw8 0atTZEsPBnpqizC7ZA5NdDuvS/UlxCTQXOCUnRCPlANWNpKodkSzEanp6eACL9yuFewE Jjtw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=qDsz9jwThzDetPi4Rs/UmVT7DI13lE3sZqIpvWGhGtQ=; b=FCeQqh8H4/pZx2iZTHl3/i7UVm2y8+biHJdHWvb08wqjGe48HDoBItj8tISx78+gSw 2OVimlIxJ3BNHGhz9tRGynSu587BM5NYSfRHfLU/oojTo+BIa5P7XwKtaSPf8ejwX+gU kwlHgo2o/wd/tPLRyIRyr3+SCquwHL4gP4jl+sgVFA4QAnhL1SZV+xZrbYGvg1V24pj1 yK87V4nTgUZ9nfS0dC18V+NlKzNwYhK4l8TImMM2dVC+gSBViVzKVRcGhrDhG4l39FTF jgP1JcWn+3au2gcoV89bKUOrjVBHhXqch0IRKNNmutCl7BToT69yh/OqI6d/Hd+P6+3N GZ4A== X-Gm-Message-State: AMke39mYuydqDAeYYpMNt527Gj7eMmq3KdqEVU5EWQKaeCeUjmJO0OZdWnJ71gYfw6KuKsMO X-Received: by 10.28.140.135 with SMTP id o129mr2456031wmd.101.1488288619669; Tue, 28 Feb 2017 05:30:19 -0800 (PST) Received: from localhost.localdomain ([90.63.244.31]) by smtp.googlemail.com with ESMTPSA id k70sm18550982wmc.3.2017.02.28.05.30.18 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 28 Feb 2017 05:30:19 -0800 (PST) From: Jerome Brunet To: Michael Turquette , Stephen Boyd , Kevin Hilman , Carlo Caione Subject: [PATCH 3/7] clk: meson: mpll: add rw operation Date: Tue, 28 Feb 2017 14:29:58 +0100 Message-Id: <20170228133002.17894-4-jbrunet@baylibre.com> X-Mailer: git-send-email 2.9.3 In-Reply-To: <20170228133002.17894-1-jbrunet@baylibre.com> References: <20170228133002.17894-1-jbrunet@baylibre.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20170228_053041_804115_EA437054 X-CRM114-Status: GOOD ( 15.72 ) X-BeenThere: linux-amlogic@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: linux-amlogic@lists.infradead.org, linux-clk@vger.kernel.org, linux-kernel@vger.kernel.org, Jerome Brunet MIME-Version: 1.0 Sender: "linux-amlogic" Errors-To: linux-amlogic-bounces+patchwork-linux-amlogic=patchwork.kernel.org@lists.infradead.org X-Virus-Scanned: ClamAV using ClamSMTP This patch adds new callbacks to the meson-mpll driver to control and set the pll rate. For this, we also need to add the enable bit and sdm enable bit. The corresponding parameters are added to mpll data structure. Signed-off-by: Jerome Brunet --- drivers/clk/meson/clk-mpll.c | 152 +++++++++++++++++++++++++++++++++++++++++-- drivers/clk/meson/clkc.h | 4 +- drivers/clk/meson/gxbb.c | 30 +++++++++ 3 files changed, 180 insertions(+), 6 deletions(-) diff --git a/drivers/clk/meson/clk-mpll.c b/drivers/clk/meson/clk-mpll.c index 03af79005ddb..342b85d4e22a 100644 --- a/drivers/clk/meson/clk-mpll.c +++ b/drivers/clk/meson/clk-mpll.c @@ -64,16 +64,50 @@ #include #include "clkc.h" -#define SDM_MAX 16384 +#define SDM_DEN 16384 +#define SDM_MIN 1 +#define SDM_MAX 16383 +#define N2_MIN 4 +#define N2_MAX 127 #define to_meson_clk_mpll(_hw) container_of(_hw, struct meson_clk_mpll, hw) +static unsigned long rate_from_params(unsigned long parent_rate, + unsigned long sdm, + unsigned long n2) +{ + return (parent_rate * SDM_DEN) / ((SDM_DEN * n2) + sdm); +} + +static void params_from_rate(unsigned long requested_rate, + unsigned long parent_rate, + unsigned long *sdm, + unsigned long *n2) +{ + uint64_t div = parent_rate; + unsigned long rem = do_div(div, requested_rate); + + if (div < N2_MIN) { + *n2 = N2_MIN; + *sdm = SDM_MIN; + } else if (div > N2_MAX) { + *n2 = N2_MAX; + *sdm = SDM_MAX; + } else { + *n2 = div; + *sdm = DIV_ROUND_UP(rem * SDM_DEN, requested_rate); + if (*sdm < SDM_MIN) + *sdm = SDM_MIN; + else if (*sdm > SDM_MAX) + *sdm = SDM_MAX; + } +} + static unsigned long mpll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { struct meson_clk_mpll *mpll = to_meson_clk_mpll(hw); struct parm *p; - unsigned long rate = 0; unsigned long reg, sdm, n2; p = &mpll->sdm; @@ -84,11 +118,119 @@ static unsigned long mpll_recalc_rate(struct clk_hw *hw, reg = readl(mpll->base + p->reg_off); n2 = PARM_GET(p->width, p->shift, reg); - rate = (parent_rate * SDM_MAX) / ((SDM_MAX * n2) + sdm); + return rate_from_params(parent_rate, sdm, n2); +} + +static long mpll_round_rate(struct clk_hw *hw, + unsigned long rate, + unsigned long *parent_rate) +{ + unsigned long sdm, n2; + + params_from_rate(rate, *parent_rate, &sdm, &n2); + return rate_from_params(*parent_rate, sdm, n2); +} + +static int mpll_set_rate(struct clk_hw *hw, + unsigned long rate, + unsigned long parent_rate) +{ + struct meson_clk_mpll *mpll = to_meson_clk_mpll(hw); + struct parm *p; + unsigned long reg, sdm, n2; + unsigned long flags = 0; + + params_from_rate(rate, parent_rate, &sdm, &n2); + + if (mpll->lock) + spin_lock_irqsave(mpll->lock, flags); + else + __acquire(mpll->lock); + + p = &mpll->sdm; + reg = readl(mpll->base + p->reg_off); + reg = PARM_SET(p->width, p->shift, reg, sdm); + writel(reg, mpll->base + p->reg_off); + + p = &mpll->sdm_en; + reg = readl(mpll->base + p->reg_off); + reg = PARM_SET(p->width, p->shift, reg, 1); + writel(reg, mpll->base + p->reg_off); + + p = &mpll->n2; + reg = readl(mpll->base + p->reg_off); + reg = PARM_SET(p->width, p->shift, reg, n2); + writel(reg, mpll->base + p->reg_off); + + if (mpll->lock) + spin_unlock_irqrestore(mpll->lock, flags); + else + __release(mpll->lock); - return rate; + return 0; +} + +static void mpll_enable_core(struct clk_hw *hw, int enable) +{ + struct meson_clk_mpll *mpll = to_meson_clk_mpll(hw); + struct parm *p; + unsigned long reg; + unsigned long flags = 0; + + if (mpll->lock) + spin_lock_irqsave(mpll->lock, flags); + else + __acquire(mpll->lock); + + p = &mpll->en; + reg = readl(mpll->base + p->reg_off); + reg = PARM_SET(p->width, p->shift, reg, enable ? 1 : 0); + writel(reg, mpll->base + p->reg_off); + + if (mpll->lock) + spin_unlock_irqrestore(mpll->lock, flags); + else + __release(mpll->lock); +} + + +static int mpll_enable(struct clk_hw *hw) +{ + mpll_enable_core(hw, 1); + + return 0; +} + +static void mpll_disable(struct clk_hw *hw) +{ + mpll_enable_core(hw, 0); +} + +static int mpll_is_enabled(struct clk_hw *hw) +{ + struct meson_clk_mpll *mpll = to_meson_clk_mpll(hw); + struct parm *p; + unsigned long reg; + int en; + + p = &mpll->en; + reg = readl(mpll->base + p->reg_off); + en = PARM_GET(p->width, p->shift, reg); + + return en; } const struct clk_ops meson_clk_mpll_ro_ops = { - .recalc_rate = mpll_recalc_rate, + .recalc_rate = mpll_recalc_rate, + .round_rate = mpll_round_rate, + .is_enabled = mpll_is_enabled, +}; + +const struct clk_ops meson_clk_mpll_ops = { + .recalc_rate = mpll_recalc_rate, + .round_rate = mpll_round_rate, + .set_rate = mpll_set_rate, + .enable = mpll_enable, + .disable = mpll_disable, + .is_enabled = mpll_is_enabled, }; diff --git a/drivers/clk/meson/clkc.h b/drivers/clk/meson/clkc.h index 9bb70e7a7d6a..54d58a465039 100644 --- a/drivers/clk/meson/clkc.h +++ b/drivers/clk/meson/clkc.h @@ -92,8 +92,9 @@ struct meson_clk_mpll { struct clk_hw hw; void __iomem *base; struct parm sdm; + struct parm sdm_en; struct parm n2; - /* FIXME ssen gate control? */ + struct parm en; spinlock_t *lock; }; @@ -116,5 +117,6 @@ extern const struct clk_ops meson_clk_pll_ro_ops; extern const struct clk_ops meson_clk_pll_ops; extern const struct clk_ops meson_clk_cpu_ops; extern const struct clk_ops meson_clk_mpll_ro_ops; +extern const struct clk_ops meson_clk_mpll_ops; #endif /* __CLKC_H */ diff --git a/drivers/clk/meson/gxbb.c b/drivers/clk/meson/gxbb.c index 388b0c8838af..6b97f4da1708 100644 --- a/drivers/clk/meson/gxbb.c +++ b/drivers/clk/meson/gxbb.c @@ -441,11 +441,21 @@ static struct meson_clk_mpll gxbb_mpll0 = { .shift = 0, .width = 14, }, + .sdm_en = { + .reg_off = HHI_MPLL_CNTL7, + .shift = 15, + .width = 1, + }, .n2 = { .reg_off = HHI_MPLL_CNTL7, .shift = 16, .width = 9, }, + .en = { + .reg_off = HHI_MPLL_CNTL7, + .shift = 14, + .width = 1, + }, .lock = &clk_lock, .hw.init = &(struct clk_init_data){ .name = "mpll0", @@ -461,11 +471,21 @@ static struct meson_clk_mpll gxbb_mpll1 = { .shift = 0, .width = 14, }, + .sdm_en = { + .reg_off = HHI_MPLL_CNTL8, + .shift = 15, + .width = 1, + }, .n2 = { .reg_off = HHI_MPLL_CNTL8, .shift = 16, .width = 9, }, + .en = { + .reg_off = HHI_MPLL_CNTL8, + .shift = 14, + .width = 1, + }, .lock = &clk_lock, .hw.init = &(struct clk_init_data){ .name = "mpll1", @@ -481,11 +501,21 @@ static struct meson_clk_mpll gxbb_mpll2 = { .shift = 0, .width = 14, }, + .sdm_en = { + .reg_off = HHI_MPLL_CNTL9, + .shift = 15, + .width = 1, + }, .n2 = { .reg_off = HHI_MPLL_CNTL9, .shift = 16, .width = 9, }, + .en = { + .reg_off = HHI_MPLL_CNTL9, + .shift = 14, + .width = 1, + }, .lock = &clk_lock, .hw.init = &(struct clk_init_data){ .name = "mpll2",