From patchwork Thu Jul 11 09:27:49 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Thomas Abraham X-Patchwork-Id: 2826238 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 41B0D9F7D6 for ; Thu, 11 Jul 2013 09:29:43 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id CAA63200CF for ; Thu, 11 Jul 2013 09:29:41 +0000 (UTC) Received: from casper.infradead.org (casper.infradead.org [85.118.1.10]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id A3F2B200CA for ; Thu, 11 Jul 2013 09:29:40 +0000 (UTC) Received: from merlin.infradead.org ([2001:4978:20e::2]) by casper.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1UxDBH-0005rL-Or; Thu, 11 Jul 2013 09:28:56 +0000 Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1UxDAl-0002pZ-P0; Thu, 11 Jul 2013 09:28:23 +0000 Received: from mail-wi0-f169.google.com ([209.85.212.169]) by merlin.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1UxDAj-0002on-Gn for linux-arm-kernel@lists.infradead.org; Thu, 11 Jul 2013 09:28:22 +0000 Received: by mail-wi0-f169.google.com with SMTP id c10so13378584wiw.4 for ; Thu, 11 Jul 2013 02:27:55 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=from:to:cc:subject:date:message-id:x-mailer:x-gm-message-state; bh=2lg6vMbtVDbs+aIW1WuTDmB0frGuI4VUGULFAeXKfkk=; b=o2pT6mYhSi3FfNIOP62h0ZvcnsKHt2e8oLjLgdClbaeJVJ0Wmh5rmEJo77QVIgTfvL 0S0BUB81z//vBWD8bbwWI7P1PLUzrlKOEJdFZlIgee1LkCZ68+u67u3r7BTTURGoY7/C 0wiBfl1wXnxePMyDAJatKW1SJesQoEivHqz1jjhvTk5js+yN7jsh5KMhATEU4shfqcYy n+pf8LdubjiF5JkFarMB4ukLxeYrCFtEAOLnVNSdB3QFUuw5B4L7s+Bq+71Iwb5qTnsq BWLSIdgHFSNks+u4HRzvDiNwUmzNypIL4Vnl10+f5wqrbz8RUZkSwrtbjgjmPkk6S/W7 M99A== X-Received: by 10.180.78.98 with SMTP id a2mr36846460wix.27.1373534875852; Thu, 11 Jul 2013 02:27:55 -0700 (PDT) Received: from localhost.localdomain ([193.120.41.118]) by mx.google.com with ESMTPSA id r8sm59138509wiz.5.2013.07.11.02.27.53 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Thu, 11 Jul 2013 02:27:54 -0700 (PDT) From: Thomas Abraham To: linux-arm-kernel@lists.infradead.org Subject: [PATCH] clk: samsung: add set_rate and round_rate callbacks for pll45xx Date: Thu, 11 Jul 2013 14:57:49 +0530 Message-Id: <1373534869-12034-1-git-send-email-thomas.abraham@linaro.org> X-Mailer: git-send-email 1.7.5.4 X-Gm-Message-State: ALoCoQlHKDgiqPXuNkNPnyKEvLrARGD2GakhvyVVhWeoAc6PPJoEoM/Xi3hnbdCWMupjpHqZ0/r5 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20130711_052821_760617_7A7925EA X-CRM114-Status: GOOD ( 20.79 ) X-Spam-Score: -2.6 (--) Cc: kgene.kim@samsung.com, mturquette@linaro.org, heiko@sntech.de, yadi.brar01@gmail.com, tomasz.figa@gmail.com, vikas.sajjan@linaro.org X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Spam-Status: No, score=-4.5 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_MED, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Add support for set_rate and round_rate callbacks for pll45xx pll. This allows configuring pll45xx to generate a desired clock output. Signed-off-by: Thomas Abraham --- The set_rate and round_rate callbacks in this patch for pll45xx are handled slightly differently from the way it is done in the (not yet merged) patch series from Yadwinder (http://www.mail-archive.com/linux-samsung-soc@vger.kernel.org/msg19540.html) In this patch, the pll lookup table is kept as part of the pll configuration code itself, since the pll is just a hardware block which takes an input frequency and configuration values to genertate a output clock frequency. Given a set of inputs, a pll of a given type will generate the same output regardless of the SoC it is used in. So instead of supplying the pll lookup table from per-soc clock driver code (as done in the Yadwinder's patch series), the pll lookup table can be coupled with the pll code itself, saving duplication of pll lookup table for every SoC the pll is used with. drivers/clk/samsung/clk-pll.c | 88 +++++++++++++++++++++++++++++++++++++++++ drivers/clk/samsung/clk-pll.h | 15 +++++++ 2 files changed, 103 insertions(+), 0 deletions(-) diff --git a/drivers/clk/samsung/clk-pll.c b/drivers/clk/samsung/clk-pll.c index 362f12d..4940936 100644 --- a/drivers/clk/samsung/clk-pll.c +++ b/drivers/clk/samsung/clk-pll.c @@ -172,6 +172,8 @@ struct clk * __init samsung_clk_register_pll36xx(const char *name, * PLL45xx Clock Type */ +#define PLL45XX_EN_MASK (1 << 31) +#define PLL45XX_LOCK_MASK (1 << 29) #define PLL45XX_MDIV_MASK (0x3FF) #define PLL45XX_PDIV_MASK (0x3F) #define PLL45XX_SDIV_MASK (0x7) @@ -187,6 +189,90 @@ struct samsung_clk_pll45xx { #define to_clk_pll45xx(_hw) container_of(_hw, struct samsung_clk_pll45xx, hw) +/* a sorted table of freq supported by pll45xx with 24mhz parent clock */ +static struct pll45xx_freq_lookup pll45xx_freq_lookup_24mhz[] = { + PLL45XX_PMS(1000000000, 6, 250, 1), + PLL45XX_PMS(800000000, 6, 200, 1), + PLL45XX_PMS(500000000, 6, 250, 2), + PLL45XX_PMS(400000000, 6, 200, 2), + PLL45XX_PMS(200000000, 6, 200, 3), +}; + +static int samsung_pll45xx_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long prate) +{ + struct samsung_clk_pll45xx *pll = to_clk_pll45xx(hw); + struct pll45xx_freq_lookup *f; + unsigned long timeout, pll_con, cnt, idx; + + /* select a lookup table based on parent clock frequency */ + switch (prate) { + case 24000000: + f = pll45xx_freq_lookup_24mhz; + cnt = ARRAY_SIZE(pll45xx_freq_lookup_24mhz); + break; + default: + pr_err("%s: unsupported parent clock rate, failed to set rate", + __func__); + return -EINVAL; + } + + /* check if the requested freq is in the list of supported freq */ + for (idx = 0; idx < cnt; idx++, f++) + if (f->target_freq == rate) + break; + + if (idx == cnt) { + pr_err("%s: unspported clock speed %ld requested\n", + __func__, rate); + return -EINVAL; + } + + /* first, disable the output of the pll */ + writel(readl(pll->con_reg) & ~PLL45XX_EN_MASK, (void *)pll->con_reg); + + /* write the new pll configuration values */ + pll_con = (f->pdiv << PLL45XX_PDIV_SHIFT) | + (f->mdiv << PLL45XX_MDIV_SHIFT) | + (f->sdiv << PLL45XX_SDIV_SHIFT); + writel(pll_con, (void *)pll->con_reg); + + /* enable the pll and wait for it to stabilize */ + writel(pll_con | PLL45XX_EN_MASK, (void *)pll->con_reg); + timeout = jiffies + msecs_to_jiffies(20); + while (time_before(jiffies, timeout)) + if (readl(pll->con_reg) & PLL45XX_LOCK_MASK) + return 0; + return -EBUSY; +} + +static long samsung_pll45xx_round_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *prate) +{ + struct pll45xx_freq_lookup *f; + unsigned long cnt; + + /* select a lookup table based on parent clock frequency */ + switch (*prate) { + case 24000000: + f = pll45xx_freq_lookup_24mhz; + cnt = ARRAY_SIZE(pll45xx_freq_lookup_24mhz); + break; + default: + pr_err("%s: unsupported parent clock rate", __func__); + return *prate; + } + + /* find the nearest possible clock output that can be supported */ + while (cnt-- > 0) { + if (rate >= f->target_freq) + return f->target_freq; + f++; + } + + return (--f)->target_freq; +} + static unsigned long samsung_pll45xx_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { @@ -209,6 +295,8 @@ static unsigned long samsung_pll45xx_recalc_rate(struct clk_hw *hw, } static const struct clk_ops samsung_pll45xx_clk_ops = { + .set_rate = samsung_pll45xx_set_rate, + .round_rate = samsung_pll45xx_round_rate, .recalc_rate = samsung_pll45xx_recalc_rate, }; diff --git a/drivers/clk/samsung/clk-pll.h b/drivers/clk/samsung/clk-pll.h index f33786e..fb687ec 100644 --- a/drivers/clk/samsung/clk-pll.h +++ b/drivers/clk/samsung/clk-pll.h @@ -18,6 +18,21 @@ enum pll45xx_type { pll_4508 }; +struct pll45xx_freq_lookup { + unsigned long target_freq; + unsigned long pdiv; + unsigned long mdiv; + unsigned long sdiv; +}; + +#define PLL45XX_PMS(f, p, m, s) \ + { \ + .target_freq = f, \ + .pdiv = p, \ + .mdiv = m, \ + .sdiv = s, \ + } + enum pll46xx_type { pll_4600, pll_4650,