From patchwork Fri Feb 14 20:15:02 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ezequiel Garcia X-Patchwork-Id: 3653561 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 71D7F9F1EE for ; Fri, 14 Feb 2014 20:18:33 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 5B00E20172 for ; Fri, 14 Feb 2014 20:18:32 +0000 (UTC) Received: from casper.infradead.org (casper.infradead.org [85.118.1.10]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id DF21E20203 for ; Fri, 14 Feb 2014 20:18:30 +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 1WEPBZ-0008D2-2b; Fri, 14 Feb 2014 20:16:34 +0000 Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1WEPBA-0003lM-WA; Fri, 14 Feb 2014 20:16:09 +0000 Received: from top.free-electrons.com ([176.31.233.9] helo=mail.free-electrons.com) by merlin.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1WEPAk-0003hK-8W for linux-arm-kernel@lists.infradead.org; Fri, 14 Feb 2014 20:15:45 +0000 Received: by mail.free-electrons.com (Postfix, from userid 106) id 3DF2687B; Fri, 14 Feb 2014 21:15:32 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Spam-Level: X-Spam-Status: No, score=-4.8 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_MED, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 Received: from localhost.localdomain (unknown [190.2.98.212]) by mail.free-electrons.com (Postfix) with ESMTPA id 48BAA7AC; Fri, 14 Feb 2014 21:15:27 +0100 (CET) From: Ezequiel Garcia To: , Mike Turquette , Gregory Clement Subject: [PATCH 3/4] clk: mvebu: refactor corediv driver to support more SoC Date: Fri, 14 Feb 2014 17:15:02 -0300 Message-Id: <1392408903-31237-4-git-send-email-ezequiel.garcia@free-electrons.com> X-Mailer: git-send-email 1.8.1.5 In-Reply-To: <1392408903-31237-3-git-send-email-ezequiel.garcia@free-electrons.com> References: <1392408903-31237-1-git-send-email-ezequiel.garcia@free-electrons.com> <1392408903-31237-2-git-send-email-ezequiel.garcia@free-electrons.com> <1392408903-31237-3-git-send-email-ezequiel.garcia@free-electrons.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20140214_151542_573525_3489BFBA X-CRM114-Status: GOOD ( 14.63 ) X-Spam-Score: -1.9 (-) Cc: Thomas Petazzoni , Andrew Lunn , Jason Cooper , Nadav Haklai , Lior Amsalem , Ezequiel Garcia , Sebastian Hesselbarth 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-Virus-Scanned: ClamAV using ClamSMTP From: Thomas Petazzoni This commit refactors the corediv clock driver so that it is capable of handling various SOCs that have slightly different corediv clock registers and capabilities. It introduces a clk_corediv_soc_desc structure that encapsulates all the SoC specific details. Signed-off-by: Thomas Petazzoni Signed-off-by: Ezequiel Garcia --- drivers/clk/mvebu/clk-corediv.c | 81 +++++++++++++++++++++++++++++------------ 1 file changed, 57 insertions(+), 24 deletions(-) diff --git a/drivers/clk/mvebu/clk-corediv.c b/drivers/clk/mvebu/clk-corediv.c index 59db71d..f9e8a12 100644 --- a/drivers/clk/mvebu/clk-corediv.c +++ b/drivers/clk/mvebu/clk-corediv.c @@ -18,9 +18,6 @@ #include "common.h" #define CORE_CLK_DIV_RATIO_MASK 0xff -#define CORE_CLK_DIV_RATIO_RELOAD BIT(8) -#define CORE_CLK_DIV_ENABLE_OFFSET 24 -#define CORE_CLK_DIV_RATIO_OFFSET 0x8 /* * This structure describes the hardware details (bit offset and mask) @@ -36,6 +33,21 @@ struct clk_corediv_desc { }; /* + * This structure describes the hardware details to configure the core + * divider clocks on a given SoC. Amongst others, it points to the + * array of core divider clock descriptors for this SoC, as well as + * the corresponding operations to manipulate them. + */ +struct clk_corediv_soc_desc { + const struct clk_corediv_desc *descs; + unsigned int ndescs; + const struct clk_ops ops; + u32 ratio_reload; + u32 enable_bit_offset; + u32 ratio_offset; +}; + +/* * This structure represents one core divider clock for the clock * framework, and is dynamically allocated for each core divider clock * existing in the current SoC. @@ -44,6 +56,7 @@ struct clk_corediv { struct clk_hw hw; void __iomem *reg; const struct clk_corediv_desc *desc; + const struct clk_corediv_soc_desc *soc_desc; spinlock_t lock; }; @@ -63,8 +76,9 @@ static const struct clk_corediv_desc mvebu_corediv_desc[] = { static int clk_corediv_is_enabled(struct clk_hw *hwclk) { struct clk_corediv *corediv = to_corediv_clk(hwclk); + const struct clk_corediv_soc_desc *soc_desc = corediv->soc_desc; const struct clk_corediv_desc *desc = corediv->desc; - u32 enable_mask = BIT(desc->fieldbit) << CORE_CLK_DIV_ENABLE_OFFSET; + u32 enable_mask = BIT(desc->fieldbit) << soc_desc->enable_bit_offset; return !!(readl(corediv->reg) & enable_mask); } @@ -72,6 +86,7 @@ static int clk_corediv_is_enabled(struct clk_hw *hwclk) static int clk_corediv_enable(struct clk_hw *hwclk) { struct clk_corediv *corediv = to_corediv_clk(hwclk); + const struct clk_corediv_soc_desc *soc_desc = corediv->soc_desc; const struct clk_corediv_desc *desc = corediv->desc; unsigned long flags = 0; u32 reg; @@ -79,7 +94,7 @@ static int clk_corediv_enable(struct clk_hw *hwclk) spin_lock_irqsave(&corediv->lock, flags); reg = readl(corediv->reg); - reg |= (BIT(desc->fieldbit) << CORE_CLK_DIV_ENABLE_OFFSET); + reg |= (BIT(desc->fieldbit) << soc_desc->enable_bit_offset); writel(reg, corediv->reg); spin_unlock_irqrestore(&corediv->lock, flags); @@ -90,6 +105,7 @@ static int clk_corediv_enable(struct clk_hw *hwclk) static void clk_corediv_disable(struct clk_hw *hwclk) { struct clk_corediv *corediv = to_corediv_clk(hwclk); + const struct clk_corediv_soc_desc *soc_desc = corediv->soc_desc; const struct clk_corediv_desc *desc = corediv->desc; unsigned long flags = 0; u32 reg; @@ -97,7 +113,7 @@ static void clk_corediv_disable(struct clk_hw *hwclk) spin_lock_irqsave(&corediv->lock, flags); reg = readl(corediv->reg); - reg &= ~(BIT(desc->fieldbit) << CORE_CLK_DIV_ENABLE_OFFSET); + reg &= ~(BIT(desc->fieldbit) << soc_desc->enable_bit_offset); writel(reg, corediv->reg); spin_unlock_irqrestore(&corediv->lock, flags); @@ -107,10 +123,11 @@ static unsigned long clk_corediv_recalc_rate(struct clk_hw *hwclk, unsigned long parent_rate) { struct clk_corediv *corediv = to_corediv_clk(hwclk); + const struct clk_corediv_soc_desc *soc_desc = corediv->soc_desc; const struct clk_corediv_desc *desc = corediv->desc; u32 reg, div; - reg = readl(corediv->reg + CORE_CLK_DIV_RATIO_OFFSET); + reg = readl(corediv->reg + soc_desc->ratio_offset); div = (reg >> desc->offset) & desc->mask; return parent_rate / div; } @@ -134,6 +151,7 @@ static int clk_corediv_set_rate(struct clk_hw *hwclk, unsigned long rate, unsigned long parent_rate) { struct clk_corediv *corediv = to_corediv_clk(hwclk); + const struct clk_corediv_soc_desc *soc_desc = corediv->soc_desc; const struct clk_corediv_desc *desc = corediv->desc; unsigned long flags = 0; u32 reg, div; @@ -143,17 +161,17 @@ static int clk_corediv_set_rate(struct clk_hw *hwclk, unsigned long rate, spin_lock_irqsave(&corediv->lock, flags); /* Write new divider to the divider ratio register */ - reg = readl(corediv->reg + CORE_CLK_DIV_RATIO_OFFSET); + reg = readl(corediv->reg + soc_desc->ratio_offset); reg &= ~(desc->mask << desc->offset); reg |= (div & desc->mask) << desc->offset; - writel(reg, corediv->reg + CORE_CLK_DIV_RATIO_OFFSET); + writel(reg, corediv->reg + soc_desc->ratio_offset); /* Set reload-force for this clock */ reg = readl(corediv->reg) | BIT(desc->fieldbit); writel(reg, corediv->reg); /* Now trigger the clock update */ - reg = readl(corediv->reg) | CORE_CLK_DIV_RATIO_RELOAD; + reg = readl(corediv->reg) | soc_desc->ratio_reload; writel(reg, corediv->reg); /* @@ -161,7 +179,7 @@ static int clk_corediv_set_rate(struct clk_hw *hwclk, unsigned long rate, * ratios request and the reload request. */ udelay(1000); - reg &= ~(CORE_CLK_DIV_RATIO_MASK | CORE_CLK_DIV_RATIO_RELOAD); + reg &= ~(CORE_CLK_DIV_RATIO_MASK | soc_desc->ratio_reload); writel(reg, corediv->reg); udelay(1000); @@ -170,16 +188,25 @@ static int clk_corediv_set_rate(struct clk_hw *hwclk, unsigned long rate, return 0; } -static const struct clk_ops corediv_ops = { - .enable = clk_corediv_enable, - .disable = clk_corediv_disable, - .is_enabled = clk_corediv_is_enabled, - .recalc_rate = clk_corediv_recalc_rate, - .round_rate = clk_corediv_round_rate, - .set_rate = clk_corediv_set_rate, +static const struct clk_corediv_soc_desc armada370_corediv_soc = { + .descs = mvebu_corediv_desc, + .ndescs = ARRAY_SIZE(mvebu_corediv_desc), + .ops = { + .enable = clk_corediv_enable, + .disable = clk_corediv_disable, + .is_enabled = clk_corediv_is_enabled, + .recalc_rate = clk_corediv_recalc_rate, + .round_rate = clk_corediv_round_rate, + .set_rate = clk_corediv_set_rate, + }, + .ratio_reload = BIT(8), + .enable_bit_offset = 24, + .ratio_offset = 0x8, }; -static void __init mvebu_corediv_clk_init(struct device_node *node) +static void __init +mvebu_corediv_clk_init(struct device_node *node, + const struct clk_corediv_soc_desc *soc_desc) { struct clk_init_data init; struct clk_corediv *corediv; @@ -195,7 +222,7 @@ static void __init mvebu_corediv_clk_init(struct device_node *node) parent_name = of_clk_get_parent_name(node, 0); - clk_data.clk_num = ARRAY_SIZE(mvebu_corediv_desc); + clk_data.clk_num = soc_desc->ndescs; /* clks holds the clock array */ clks = kcalloc(clk_data.clk_num, sizeof(struct clk *), @@ -216,10 +243,11 @@ static void __init mvebu_corediv_clk_init(struct device_node *node) init.num_parents = 1; init.parent_names = &parent_name; init.name = clk_name; - init.ops = &corediv_ops; + init.ops = &soc_desc->ops; init.flags = 0; - corediv[i].desc = mvebu_corediv_desc + i; + corediv[i].soc_desc = soc_desc; + corediv[i].desc = soc_desc->descs + i; corediv[i].reg = base; corediv[i].hw.init = &init; @@ -236,5 +264,10 @@ err_free_clks: err_unmap: iounmap(base); } -CLK_OF_DECLARE(mvebu_corediv_clk, "marvell,armada-370-corediv-clock", - mvebu_corediv_clk_init); + +static void __init armada370_corediv_clk_init(struct device_node *node) +{ + return mvebu_corediv_clk_init(node, &armada370_corediv_soc); +} +CLK_OF_DECLARE(armada370_corediv_clk, "marvell,armada-370-corediv-clock", + armada370_corediv_clk_init);