From patchwork Thu Sep 8 11:57:19 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexandre Belloni X-Patchwork-Id: 9321131 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 30674607D3 for ; Thu, 8 Sep 2016 12:01:27 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 1E6D3297FD for ; Thu, 8 Sep 2016 12:01:27 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 1278529803; Thu, 8 Sep 2016 12:01:27 +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=-4.2 required=2.0 tests=BAYES_00, RCVD_IN_DNSWL_MED autolearn=unavailable version=3.3.1 Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.9]) (using TLSv1.2 with cipher AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id EE669297FD for ; Thu, 8 Sep 2016 12:01:25 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.85_2 #1 (Red Hat Linux)) id 1bhxzN-00060L-4J; Thu, 08 Sep 2016 11:59:29 +0000 Received: from down.free-electrons.com ([37.187.137.238] helo=mail.free-electrons.com) by bombadil.infradead.org with esmtp (Exim 4.85_2 #1 (Red Hat Linux)) id 1bhxxm-0004ny-D7 for linux-arm-kernel@lists.infradead.org; Thu, 08 Sep 2016 11:57:59 +0000 Received: by mail.free-electrons.com (Postfix, from userid 110) id D7CC4329; Thu, 8 Sep 2016 13:57:28 +0200 (CEST) Received: from localhost (unknown [88.191.26.124]) by mail.free-electrons.com (Postfix) with ESMTPSA id 9EEB310E; Thu, 8 Sep 2016 13:57:28 +0200 (CEST) From: Alexandre Belloni To: Nicolas Ferre , Boris Brezillon , Stephen Boyd Subject: [PATCH 1/5] clk: at91: move slow clock controller clocks to sckc.c Date: Thu, 8 Sep 2016 13:57:19 +0200 Message-Id: <20160908115723.11878-2-alexandre.belloni@free-electrons.com> X-Mailer: git-send-email 2.9.3 In-Reply-To: <20160908115723.11878-1-alexandre.belloni@free-electrons.com> References: <20160908115723.11878-1-alexandre.belloni@free-electrons.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20160908_045751_121116_513AF941 X-CRM114-Status: GOOD ( 15.71 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Michael Turquette , Alexandre Belloni , linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-clk@vger.kernel.org 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 Move all clocks related to the slow clock controller to sckc.c. This avoids extern definitions and allows to remove sckc.h Signed-off-by: Alexandre Belloni --- drivers/clk/at91/clk-slow.c | 353 -------------------------------------------- drivers/clk/at91/sckc.c | 352 ++++++++++++++++++++++++++++++++++++++++++- drivers/clk/at91/sckc.h | 22 --- 3 files changed, 351 insertions(+), 376 deletions(-) delete mode 100644 drivers/clk/at91/sckc.h diff --git a/drivers/clk/at91/clk-slow.c b/drivers/clk/at91/clk-slow.c index 61090b1146cf..31908331e883 100644 --- a/drivers/clk/at91/clk-slow.c +++ b/drivers/clk/at91/clk-slow.c @@ -13,42 +13,11 @@ #include #include #include -#include #include #include #include #include "pmc.h" -#include "sckc.h" - -#define SLOW_CLOCK_FREQ 32768 -#define SLOWCK_SW_CYCLES 5 -#define SLOWCK_SW_TIME_USEC ((SLOWCK_SW_CYCLES * USEC_PER_SEC) / \ - SLOW_CLOCK_FREQ) - -#define AT91_SCKC_CR 0x00 -#define AT91_SCKC_RCEN (1 << 0) -#define AT91_SCKC_OSC32EN (1 << 1) -#define AT91_SCKC_OSC32BYP (1 << 2) -#define AT91_SCKC_OSCSEL (1 << 3) - -struct clk_slow_osc { - struct clk_hw hw; - void __iomem *sckcr; - unsigned long startup_usec; -}; - -#define to_clk_slow_osc(hw) container_of(hw, struct clk_slow_osc, hw) - -struct clk_slow_rc_osc { - struct clk_hw hw; - void __iomem *sckcr; - unsigned long frequency; - unsigned long accuracy; - unsigned long startup_usec; -}; - -#define to_clk_slow_rc_osc(hw) container_of(hw, struct clk_slow_rc_osc, hw) struct clk_sam9260_slow { struct clk_hw hw; @@ -57,328 +26,6 @@ struct clk_sam9260_slow { #define to_clk_sam9260_slow(hw) container_of(hw, struct clk_sam9260_slow, hw) -struct clk_sam9x5_slow { - struct clk_hw hw; - void __iomem *sckcr; - u8 parent; -}; - -#define to_clk_sam9x5_slow(hw) container_of(hw, struct clk_sam9x5_slow, hw) - -static int clk_slow_osc_prepare(struct clk_hw *hw) -{ - struct clk_slow_osc *osc = to_clk_slow_osc(hw); - void __iomem *sckcr = osc->sckcr; - u32 tmp = readl(sckcr); - - if (tmp & AT91_SCKC_OSC32BYP) - return 0; - - writel(tmp | AT91_SCKC_OSC32EN, sckcr); - - usleep_range(osc->startup_usec, osc->startup_usec + 1); - - return 0; -} - -static void clk_slow_osc_unprepare(struct clk_hw *hw) -{ - struct clk_slow_osc *osc = to_clk_slow_osc(hw); - void __iomem *sckcr = osc->sckcr; - u32 tmp = readl(sckcr); - - if (tmp & AT91_SCKC_OSC32BYP) - return; - - writel(tmp & ~AT91_SCKC_OSC32EN, sckcr); -} - -static int clk_slow_osc_is_prepared(struct clk_hw *hw) -{ - struct clk_slow_osc *osc = to_clk_slow_osc(hw); - void __iomem *sckcr = osc->sckcr; - u32 tmp = readl(sckcr); - - if (tmp & AT91_SCKC_OSC32BYP) - return 1; - - return !!(tmp & AT91_SCKC_OSC32EN); -} - -static const struct clk_ops slow_osc_ops = { - .prepare = clk_slow_osc_prepare, - .unprepare = clk_slow_osc_unprepare, - .is_prepared = clk_slow_osc_is_prepared, -}; - -static struct clk * __init -at91_clk_register_slow_osc(void __iomem *sckcr, - const char *name, - const char *parent_name, - unsigned long startup, - bool bypass) -{ - struct clk_slow_osc *osc; - struct clk *clk = NULL; - struct clk_init_data init; - - if (!sckcr || !name || !parent_name) - return ERR_PTR(-EINVAL); - - osc = kzalloc(sizeof(*osc), GFP_KERNEL); - if (!osc) - return ERR_PTR(-ENOMEM); - - init.name = name; - init.ops = &slow_osc_ops; - init.parent_names = &parent_name; - init.num_parents = 1; - init.flags = CLK_IGNORE_UNUSED; - - osc->hw.init = &init; - osc->sckcr = sckcr; - osc->startup_usec = startup; - - if (bypass) - writel((readl(sckcr) & ~AT91_SCKC_OSC32EN) | AT91_SCKC_OSC32BYP, - sckcr); - - clk = clk_register(NULL, &osc->hw); - if (IS_ERR(clk)) - kfree(osc); - - return clk; -} - -void __init of_at91sam9x5_clk_slow_osc_setup(struct device_node *np, - void __iomem *sckcr) -{ - struct clk *clk; - const char *parent_name; - const char *name = np->name; - u32 startup; - bool bypass; - - parent_name = of_clk_get_parent_name(np, 0); - of_property_read_string(np, "clock-output-names", &name); - of_property_read_u32(np, "atmel,startup-time-usec", &startup); - bypass = of_property_read_bool(np, "atmel,osc-bypass"); - - clk = at91_clk_register_slow_osc(sckcr, name, parent_name, startup, - bypass); - if (IS_ERR(clk)) - return; - - of_clk_add_provider(np, of_clk_src_simple_get, clk); -} - -static unsigned long clk_slow_rc_osc_recalc_rate(struct clk_hw *hw, - unsigned long parent_rate) -{ - struct clk_slow_rc_osc *osc = to_clk_slow_rc_osc(hw); - - return osc->frequency; -} - -static unsigned long clk_slow_rc_osc_recalc_accuracy(struct clk_hw *hw, - unsigned long parent_acc) -{ - struct clk_slow_rc_osc *osc = to_clk_slow_rc_osc(hw); - - return osc->accuracy; -} - -static int clk_slow_rc_osc_prepare(struct clk_hw *hw) -{ - struct clk_slow_rc_osc *osc = to_clk_slow_rc_osc(hw); - void __iomem *sckcr = osc->sckcr; - - writel(readl(sckcr) | AT91_SCKC_RCEN, sckcr); - - usleep_range(osc->startup_usec, osc->startup_usec + 1); - - return 0; -} - -static void clk_slow_rc_osc_unprepare(struct clk_hw *hw) -{ - struct clk_slow_rc_osc *osc = to_clk_slow_rc_osc(hw); - void __iomem *sckcr = osc->sckcr; - - writel(readl(sckcr) & ~AT91_SCKC_RCEN, sckcr); -} - -static int clk_slow_rc_osc_is_prepared(struct clk_hw *hw) -{ - struct clk_slow_rc_osc *osc = to_clk_slow_rc_osc(hw); - - return !!(readl(osc->sckcr) & AT91_SCKC_RCEN); -} - -static const struct clk_ops slow_rc_osc_ops = { - .prepare = clk_slow_rc_osc_prepare, - .unprepare = clk_slow_rc_osc_unprepare, - .is_prepared = clk_slow_rc_osc_is_prepared, - .recalc_rate = clk_slow_rc_osc_recalc_rate, - .recalc_accuracy = clk_slow_rc_osc_recalc_accuracy, -}; - -static struct clk * __init -at91_clk_register_slow_rc_osc(void __iomem *sckcr, - const char *name, - unsigned long frequency, - unsigned long accuracy, - unsigned long startup) -{ - struct clk_slow_rc_osc *osc; - struct clk *clk = NULL; - struct clk_init_data init; - - if (!sckcr || !name) - return ERR_PTR(-EINVAL); - - osc = kzalloc(sizeof(*osc), GFP_KERNEL); - if (!osc) - return ERR_PTR(-ENOMEM); - - init.name = name; - init.ops = &slow_rc_osc_ops; - init.parent_names = NULL; - init.num_parents = 0; - init.flags = CLK_IGNORE_UNUSED; - - osc->hw.init = &init; - osc->sckcr = sckcr; - osc->frequency = frequency; - osc->accuracy = accuracy; - osc->startup_usec = startup; - - clk = clk_register(NULL, &osc->hw); - if (IS_ERR(clk)) - kfree(osc); - - return clk; -} - -void __init of_at91sam9x5_clk_slow_rc_osc_setup(struct device_node *np, - void __iomem *sckcr) -{ - struct clk *clk; - u32 frequency = 0; - u32 accuracy = 0; - u32 startup = 0; - const char *name = np->name; - - of_property_read_string(np, "clock-output-names", &name); - of_property_read_u32(np, "clock-frequency", &frequency); - of_property_read_u32(np, "clock-accuracy", &accuracy); - of_property_read_u32(np, "atmel,startup-time-usec", &startup); - - clk = at91_clk_register_slow_rc_osc(sckcr, name, frequency, accuracy, - startup); - if (IS_ERR(clk)) - return; - - of_clk_add_provider(np, of_clk_src_simple_get, clk); -} - -static int clk_sam9x5_slow_set_parent(struct clk_hw *hw, u8 index) -{ - struct clk_sam9x5_slow *slowck = to_clk_sam9x5_slow(hw); - void __iomem *sckcr = slowck->sckcr; - u32 tmp; - - if (index > 1) - return -EINVAL; - - tmp = readl(sckcr); - - if ((!index && !(tmp & AT91_SCKC_OSCSEL)) || - (index && (tmp & AT91_SCKC_OSCSEL))) - return 0; - - if (index) - tmp |= AT91_SCKC_OSCSEL; - else - tmp &= ~AT91_SCKC_OSCSEL; - - writel(tmp, sckcr); - - usleep_range(SLOWCK_SW_TIME_USEC, SLOWCK_SW_TIME_USEC + 1); - - return 0; -} - -static u8 clk_sam9x5_slow_get_parent(struct clk_hw *hw) -{ - struct clk_sam9x5_slow *slowck = to_clk_sam9x5_slow(hw); - - return !!(readl(slowck->sckcr) & AT91_SCKC_OSCSEL); -} - -static const struct clk_ops sam9x5_slow_ops = { - .set_parent = clk_sam9x5_slow_set_parent, - .get_parent = clk_sam9x5_slow_get_parent, -}; - -static struct clk * __init -at91_clk_register_sam9x5_slow(void __iomem *sckcr, - const char *name, - const char **parent_names, - int num_parents) -{ - struct clk_sam9x5_slow *slowck; - struct clk *clk = NULL; - struct clk_init_data init; - - if (!sckcr || !name || !parent_names || !num_parents) - return ERR_PTR(-EINVAL); - - slowck = kzalloc(sizeof(*slowck), GFP_KERNEL); - if (!slowck) - return ERR_PTR(-ENOMEM); - - init.name = name; - init.ops = &sam9x5_slow_ops; - init.parent_names = parent_names; - init.num_parents = num_parents; - init.flags = 0; - - slowck->hw.init = &init; - slowck->sckcr = sckcr; - slowck->parent = !!(readl(sckcr) & AT91_SCKC_OSCSEL); - - clk = clk_register(NULL, &slowck->hw); - if (IS_ERR(clk)) - kfree(slowck); - - return clk; -} - -void __init of_at91sam9x5_clk_slow_setup(struct device_node *np, - void __iomem *sckcr) -{ - struct clk *clk; - const char *parent_names[2]; - unsigned int num_parents; - const char *name = np->name; - - num_parents = of_clk_get_parent_count(np); - if (num_parents == 0 || num_parents > 2) - return; - - of_clk_parent_fill(np, parent_names, num_parents); - - of_property_read_string(np, "clock-output-names", &name); - - clk = at91_clk_register_sam9x5_slow(sckcr, name, parent_names, - num_parents); - if (IS_ERR(clk)) - return; - - of_clk_add_provider(np, of_clk_src_simple_get, clk); -} - static u8 clk_sam9260_slow_get_parent(struct clk_hw *hw) { struct clk_sam9260_slow *slowck = to_clk_sam9260_slow(hw); diff --git a/drivers/clk/at91/sckc.c b/drivers/clk/at91/sckc.c index 1184d76a7ab7..f1b00b1d7132 100644 --- a/drivers/clk/at91/sckc.c +++ b/drivers/clk/at91/sckc.c @@ -12,11 +12,361 @@ #include #include +#include #include #include #include -#include "sckc.h" +#define SLOW_CLOCK_FREQ 32768 +#define SLOWCK_SW_CYCLES 5 +#define SLOWCK_SW_TIME_USEC ((SLOWCK_SW_CYCLES * USEC_PER_SEC) / \ + SLOW_CLOCK_FREQ) + +#define AT91_SCKC_CR 0x00 +#define AT91_SCKC_RCEN (1 << 0) +#define AT91_SCKC_OSC32EN (1 << 1) +#define AT91_SCKC_OSC32BYP (1 << 2) +#define AT91_SCKC_OSCSEL (1 << 3) + +struct clk_slow_osc { + struct clk_hw hw; + void __iomem *sckcr; + unsigned long startup_usec; +}; + +#define to_clk_slow_osc(hw) container_of(hw, struct clk_slow_osc, hw) + +struct clk_slow_rc_osc { + struct clk_hw hw; + void __iomem *sckcr; + unsigned long frequency; + unsigned long accuracy; + unsigned long startup_usec; +}; + +#define to_clk_slow_rc_osc(hw) container_of(hw, struct clk_slow_rc_osc, hw) + +struct clk_sam9x5_slow { + struct clk_hw hw; + void __iomem *sckcr; + u8 parent; +}; + +#define to_clk_sam9x5_slow(hw) container_of(hw, struct clk_sam9x5_slow, hw) + +static int clk_slow_osc_prepare(struct clk_hw *hw) +{ + struct clk_slow_osc *osc = to_clk_slow_osc(hw); + void __iomem *sckcr = osc->sckcr; + u32 tmp = readl(sckcr); + + if (tmp & AT91_SCKC_OSC32BYP) + return 0; + + writel(tmp | AT91_SCKC_OSC32EN, sckcr); + + usleep_range(osc->startup_usec, osc->startup_usec + 1); + + return 0; +} + +static void clk_slow_osc_unprepare(struct clk_hw *hw) +{ + struct clk_slow_osc *osc = to_clk_slow_osc(hw); + void __iomem *sckcr = osc->sckcr; + u32 tmp = readl(sckcr); + + if (tmp & AT91_SCKC_OSC32BYP) + return; + + writel(tmp & ~AT91_SCKC_OSC32EN, sckcr); +} + +static int clk_slow_osc_is_prepared(struct clk_hw *hw) +{ + struct clk_slow_osc *osc = to_clk_slow_osc(hw); + void __iomem *sckcr = osc->sckcr; + u32 tmp = readl(sckcr); + + if (tmp & AT91_SCKC_OSC32BYP) + return 1; + + return !!(tmp & AT91_SCKC_OSC32EN); +} + +static const struct clk_ops slow_osc_ops = { + .prepare = clk_slow_osc_prepare, + .unprepare = clk_slow_osc_unprepare, + .is_prepared = clk_slow_osc_is_prepared, +}; + +static struct clk * __init +at91_clk_register_slow_osc(void __iomem *sckcr, + const char *name, + const char *parent_name, + unsigned long startup, + bool bypass) +{ + struct clk_slow_osc *osc; + struct clk *clk = NULL; + struct clk_init_data init; + + if (!sckcr || !name || !parent_name) + return ERR_PTR(-EINVAL); + + osc = kzalloc(sizeof(*osc), GFP_KERNEL); + if (!osc) + return ERR_PTR(-ENOMEM); + + init.name = name; + init.ops = &slow_osc_ops; + init.parent_names = &parent_name; + init.num_parents = 1; + init.flags = CLK_IGNORE_UNUSED; + + osc->hw.init = &init; + osc->sckcr = sckcr; + osc->startup_usec = startup; + + if (bypass) + writel((readl(sckcr) & ~AT91_SCKC_OSC32EN) | AT91_SCKC_OSC32BYP, + sckcr); + + clk = clk_register(NULL, &osc->hw); + if (IS_ERR(clk)) + kfree(osc); + + return clk; +} + +void __init of_at91sam9x5_clk_slow_osc_setup(struct device_node *np, + void __iomem *sckcr) +{ + struct clk *clk; + const char *parent_name; + const char *name = np->name; + u32 startup; + bool bypass; + + parent_name = of_clk_get_parent_name(np, 0); + of_property_read_string(np, "clock-output-names", &name); + of_property_read_u32(np, "atmel,startup-time-usec", &startup); + bypass = of_property_read_bool(np, "atmel,osc-bypass"); + + clk = at91_clk_register_slow_osc(sckcr, name, parent_name, startup, + bypass); + if (IS_ERR(clk)) + return; + + of_clk_add_provider(np, of_clk_src_simple_get, clk); +} + +static unsigned long clk_slow_rc_osc_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct clk_slow_rc_osc *osc = to_clk_slow_rc_osc(hw); + + return osc->frequency; +} + +static unsigned long clk_slow_rc_osc_recalc_accuracy(struct clk_hw *hw, + unsigned long parent_acc) +{ + struct clk_slow_rc_osc *osc = to_clk_slow_rc_osc(hw); + + return osc->accuracy; +} + +static int clk_slow_rc_osc_prepare(struct clk_hw *hw) +{ + struct clk_slow_rc_osc *osc = to_clk_slow_rc_osc(hw); + void __iomem *sckcr = osc->sckcr; + + writel(readl(sckcr) | AT91_SCKC_RCEN, sckcr); + + usleep_range(osc->startup_usec, osc->startup_usec + 1); + + return 0; +} + +static void clk_slow_rc_osc_unprepare(struct clk_hw *hw) +{ + struct clk_slow_rc_osc *osc = to_clk_slow_rc_osc(hw); + void __iomem *sckcr = osc->sckcr; + + writel(readl(sckcr) & ~AT91_SCKC_RCEN, sckcr); +} + +static int clk_slow_rc_osc_is_prepared(struct clk_hw *hw) +{ + struct clk_slow_rc_osc *osc = to_clk_slow_rc_osc(hw); + + return !!(readl(osc->sckcr) & AT91_SCKC_RCEN); +} + +static const struct clk_ops slow_rc_osc_ops = { + .prepare = clk_slow_rc_osc_prepare, + .unprepare = clk_slow_rc_osc_unprepare, + .is_prepared = clk_slow_rc_osc_is_prepared, + .recalc_rate = clk_slow_rc_osc_recalc_rate, + .recalc_accuracy = clk_slow_rc_osc_recalc_accuracy, +}; + +static struct clk * __init +at91_clk_register_slow_rc_osc(void __iomem *sckcr, + const char *name, + unsigned long frequency, + unsigned long accuracy, + unsigned long startup) +{ + struct clk_slow_rc_osc *osc; + struct clk *clk = NULL; + struct clk_init_data init; + + if (!sckcr || !name) + return ERR_PTR(-EINVAL); + + osc = kzalloc(sizeof(*osc), GFP_KERNEL); + if (!osc) + return ERR_PTR(-ENOMEM); + + init.name = name; + init.ops = &slow_rc_osc_ops; + init.parent_names = NULL; + init.num_parents = 0; + init.flags = CLK_IGNORE_UNUSED; + + osc->hw.init = &init; + osc->sckcr = sckcr; + osc->frequency = frequency; + osc->accuracy = accuracy; + osc->startup_usec = startup; + + clk = clk_register(NULL, &osc->hw); + if (IS_ERR(clk)) + kfree(osc); + + return clk; +} + +void __init of_at91sam9x5_clk_slow_rc_osc_setup(struct device_node *np, + void __iomem *sckcr) +{ + struct clk *clk; + u32 frequency = 0; + u32 accuracy = 0; + u32 startup = 0; + const char *name = np->name; + + of_property_read_string(np, "clock-output-names", &name); + of_property_read_u32(np, "clock-frequency", &frequency); + of_property_read_u32(np, "clock-accuracy", &accuracy); + of_property_read_u32(np, "atmel,startup-time-usec", &startup); + + clk = at91_clk_register_slow_rc_osc(sckcr, name, frequency, accuracy, + startup); + if (IS_ERR(clk)) + return; + + of_clk_add_provider(np, of_clk_src_simple_get, clk); +} + +static int clk_sam9x5_slow_set_parent(struct clk_hw *hw, u8 index) +{ + struct clk_sam9x5_slow *slowck = to_clk_sam9x5_slow(hw); + void __iomem *sckcr = slowck->sckcr; + u32 tmp; + + if (index > 1) + return -EINVAL; + + tmp = readl(sckcr); + + if ((!index && !(tmp & AT91_SCKC_OSCSEL)) || + (index && (tmp & AT91_SCKC_OSCSEL))) + return 0; + + if (index) + tmp |= AT91_SCKC_OSCSEL; + else + tmp &= ~AT91_SCKC_OSCSEL; + + writel(tmp, sckcr); + + usleep_range(SLOWCK_SW_TIME_USEC, SLOWCK_SW_TIME_USEC + 1); + + return 0; +} + +static u8 clk_sam9x5_slow_get_parent(struct clk_hw *hw) +{ + struct clk_sam9x5_slow *slowck = to_clk_sam9x5_slow(hw); + + return !!(readl(slowck->sckcr) & AT91_SCKC_OSCSEL); +} + +static const struct clk_ops sam9x5_slow_ops = { + .set_parent = clk_sam9x5_slow_set_parent, + .get_parent = clk_sam9x5_slow_get_parent, +}; + +static struct clk * __init +at91_clk_register_sam9x5_slow(void __iomem *sckcr, + const char *name, + const char **parent_names, + int num_parents) +{ + struct clk_sam9x5_slow *slowck; + struct clk *clk = NULL; + struct clk_init_data init; + + if (!sckcr || !name || !parent_names || !num_parents) + return ERR_PTR(-EINVAL); + + slowck = kzalloc(sizeof(*slowck), GFP_KERNEL); + if (!slowck) + return ERR_PTR(-ENOMEM); + + init.name = name; + init.ops = &sam9x5_slow_ops; + init.parent_names = parent_names; + init.num_parents = num_parents; + init.flags = 0; + + slowck->hw.init = &init; + slowck->sckcr = sckcr; + slowck->parent = !!(readl(sckcr) & AT91_SCKC_OSCSEL); + + clk = clk_register(NULL, &slowck->hw); + if (IS_ERR(clk)) + kfree(slowck); + + return clk; +} + +void __init of_at91sam9x5_clk_slow_setup(struct device_node *np, + void __iomem *sckcr) +{ + struct clk *clk; + const char *parent_names[2]; + unsigned int num_parents; + const char *name = np->name; + + num_parents = of_clk_get_parent_count(np); + if (num_parents == 0 || num_parents > 2) + return; + + of_clk_parent_fill(np, parent_names, num_parents); + + of_property_read_string(np, "clock-output-names", &name); + + clk = at91_clk_register_sam9x5_slow(sckcr, name, parent_names, + num_parents); + if (IS_ERR(clk)) + return; + + of_clk_add_provider(np, of_clk_src_simple_get, clk); +} static const struct of_device_id sckc_clk_ids[] __initconst = { /* Slow clock */ diff --git a/drivers/clk/at91/sckc.h b/drivers/clk/at91/sckc.h deleted file mode 100644 index 836fcf59820f..000000000000 --- a/drivers/clk/at91/sckc.h +++ /dev/null @@ -1,22 +0,0 @@ -/* - * drivers/clk/at91/sckc.h - * - * Copyright (C) 2013 Boris BREZILLON - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -#ifndef __AT91_SCKC_H_ -#define __AT91_SCKC_H_ - -extern void __init of_at91sam9x5_clk_slow_osc_setup(struct device_node *np, - void __iomem *sckcr); -extern void __init of_at91sam9x5_clk_slow_rc_osc_setup(struct device_node *np, - void __iomem *sckcr); -extern void __init of_at91sam9x5_clk_slow_setup(struct device_node *np, - void __iomem *sckcr); - -#endif /* __AT91_SCKC_H_ */