diff options
Diffstat (limited to 'drivers/clk/shmobile')
-rw-r--r-- | drivers/clk/shmobile/Makefile | 13 | ||||
-rw-r--r-- | drivers/clk/shmobile/clk-div6.c | 319 | ||||
-rw-r--r-- | drivers/clk/shmobile/clk-div6.h | 7 | ||||
-rw-r--r-- | drivers/clk/shmobile/clk-emev2.c | 110 | ||||
-rw-r--r-- | drivers/clk/shmobile/clk-mstp.c | 329 | ||||
-rw-r--r-- | drivers/clk/shmobile/clk-r8a73a4.c | 241 | ||||
-rw-r--r-- | drivers/clk/shmobile/clk-r8a7740.c | 199 | ||||
-rw-r--r-- | drivers/clk/shmobile/clk-r8a7778.c | 145 | ||||
-rw-r--r-- | drivers/clk/shmobile/clk-r8a7779.c | 182 | ||||
-rw-r--r-- | drivers/clk/shmobile/clk-rcar-gen2.c | 429 | ||||
-rw-r--r-- | drivers/clk/shmobile/clk-rz.c | 106 | ||||
-rw-r--r-- | drivers/clk/shmobile/clk-sh73a0.c | 218 | ||||
-rw-r--r-- | drivers/clk/shmobile/r8a7795-cpg-mssr.c | 383 | ||||
-rw-r--r-- | drivers/clk/shmobile/renesas-cpg-mssr.c | 596 | ||||
-rw-r--r-- | drivers/clk/shmobile/renesas-cpg-mssr.h | 132 |
15 files changed, 0 insertions, 3409 deletions
diff --git a/drivers/clk/shmobile/Makefile b/drivers/clk/shmobile/Makefile deleted file mode 100644 index 7e2579b30..000000000 --- a/drivers/clk/shmobile/Makefile +++ /dev/null @@ -1,13 +0,0 @@ -obj-$(CONFIG_ARCH_EMEV2) += clk-emev2.o -obj-$(CONFIG_ARCH_R7S72100) += clk-rz.o clk-mstp.o -obj-$(CONFIG_ARCH_R8A73A4) += clk-r8a73a4.o clk-mstp.o clk-div6.o -obj-$(CONFIG_ARCH_R8A7740) += clk-r8a7740.o clk-mstp.o clk-div6.o -obj-$(CONFIG_ARCH_R8A7778) += clk-r8a7778.o clk-mstp.o -obj-$(CONFIG_ARCH_R8A7779) += clk-r8a7779.o clk-mstp.o -obj-$(CONFIG_ARCH_R8A7790) += clk-rcar-gen2.o clk-mstp.o clk-div6.o -obj-$(CONFIG_ARCH_R8A7791) += clk-rcar-gen2.o clk-mstp.o clk-div6.o -obj-$(CONFIG_ARCH_R8A7793) += clk-rcar-gen2.o clk-mstp.o clk-div6.o -obj-$(CONFIG_ARCH_R8A7794) += clk-rcar-gen2.o clk-mstp.o clk-div6.o -obj-$(CONFIG_ARCH_R8A7795) += renesas-cpg-mssr.o \ - r8a7795-cpg-mssr.o clk-div6.o -obj-$(CONFIG_ARCH_SH73A0) += clk-sh73a0.o clk-mstp.o clk-div6.o diff --git a/drivers/clk/shmobile/clk-div6.c b/drivers/clk/shmobile/clk-div6.c deleted file mode 100644 index 999994769..000000000 --- a/drivers/clk/shmobile/clk-div6.c +++ /dev/null @@ -1,319 +0,0 @@ -/* - * r8a7790 Common Clock Framework support - * - * Copyright (C) 2013 Renesas Solutions Corp. - * - * Contact: Laurent Pinchart <laurent.pinchart@ideasonboard.com> - * - * 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; version 2 of the License. - */ - -#include <linux/clk-provider.h> -#include <linux/init.h> -#include <linux/io.h> -#include <linux/kernel.h> -#include <linux/of.h> -#include <linux/of_address.h> -#include <linux/slab.h> - -#include "clk-div6.h" - -#define CPG_DIV6_CKSTP BIT(8) -#define CPG_DIV6_DIV(d) ((d) & 0x3f) -#define CPG_DIV6_DIV_MASK 0x3f - -/** - * struct div6_clock - CPG 6 bit divider clock - * @hw: handle between common and hardware-specific interfaces - * @reg: IO-remapped register - * @div: divisor value (1-64) - */ -struct div6_clock { - struct clk_hw hw; - void __iomem *reg; - unsigned int div; - u32 src_shift; - u32 src_width; - u8 *parents; -}; - -#define to_div6_clock(_hw) container_of(_hw, struct div6_clock, hw) - -static int cpg_div6_clock_enable(struct clk_hw *hw) -{ - struct div6_clock *clock = to_div6_clock(hw); - u32 val; - - val = (clk_readl(clock->reg) & ~(CPG_DIV6_DIV_MASK | CPG_DIV6_CKSTP)) - | CPG_DIV6_DIV(clock->div - 1); - clk_writel(val, clock->reg); - - return 0; -} - -static void cpg_div6_clock_disable(struct clk_hw *hw) -{ - struct div6_clock *clock = to_div6_clock(hw); - u32 val; - - val = clk_readl(clock->reg); - val |= CPG_DIV6_CKSTP; - /* - * DIV6 clocks require the divisor field to be non-zero when stopping - * the clock. However, some clocks (e.g. ZB on sh73a0) fail to be - * re-enabled later if the divisor field is changed when stopping the - * clock - */ - if (!(val & CPG_DIV6_DIV_MASK)) - val |= CPG_DIV6_DIV_MASK; - clk_writel(val, clock->reg); -} - -static int cpg_div6_clock_is_enabled(struct clk_hw *hw) -{ - struct div6_clock *clock = to_div6_clock(hw); - - return !(clk_readl(clock->reg) & CPG_DIV6_CKSTP); -} - -static unsigned long cpg_div6_clock_recalc_rate(struct clk_hw *hw, - unsigned long parent_rate) -{ - struct div6_clock *clock = to_div6_clock(hw); - unsigned int div = (clk_readl(clock->reg) & CPG_DIV6_DIV_MASK) + 1; - - return parent_rate / div; -} - -static unsigned int cpg_div6_clock_calc_div(unsigned long rate, - unsigned long parent_rate) -{ - unsigned int div; - - if (!rate) - rate = 1; - - div = DIV_ROUND_CLOSEST(parent_rate, rate); - return clamp_t(unsigned int, div, 1, 64); -} - -static long cpg_div6_clock_round_rate(struct clk_hw *hw, unsigned long rate, - unsigned long *parent_rate) -{ - unsigned int div = cpg_div6_clock_calc_div(rate, *parent_rate); - - return *parent_rate / div; -} - -static int cpg_div6_clock_set_rate(struct clk_hw *hw, unsigned long rate, - unsigned long parent_rate) -{ - struct div6_clock *clock = to_div6_clock(hw); - unsigned int div = cpg_div6_clock_calc_div(rate, parent_rate); - u32 val; - - clock->div = div; - - val = clk_readl(clock->reg) & ~CPG_DIV6_DIV_MASK; - /* Only program the new divisor if the clock isn't stopped. */ - if (!(val & CPG_DIV6_CKSTP)) - clk_writel(val | CPG_DIV6_DIV(clock->div - 1), clock->reg); - - return 0; -} - -static u8 cpg_div6_clock_get_parent(struct clk_hw *hw) -{ - struct div6_clock *clock = to_div6_clock(hw); - unsigned int i; - u8 hw_index; - - if (clock->src_width == 0) - return 0; - - hw_index = (clk_readl(clock->reg) >> clock->src_shift) & - (BIT(clock->src_width) - 1); - for (i = 0; i < clk_hw_get_num_parents(hw); i++) { - if (clock->parents[i] == hw_index) - return i; - } - - pr_err("%s: %s DIV6 clock set to invalid parent %u\n", - __func__, clk_hw_get_name(hw), hw_index); - return 0; -} - -static int cpg_div6_clock_set_parent(struct clk_hw *hw, u8 index) -{ - struct div6_clock *clock = to_div6_clock(hw); - u8 hw_index; - u32 mask; - - if (index >= clk_hw_get_num_parents(hw)) - return -EINVAL; - - mask = ~((BIT(clock->src_width) - 1) << clock->src_shift); - hw_index = clock->parents[index]; - - clk_writel((clk_readl(clock->reg) & mask) | - (hw_index << clock->src_shift), clock->reg); - - return 0; -} - -static const struct clk_ops cpg_div6_clock_ops = { - .enable = cpg_div6_clock_enable, - .disable = cpg_div6_clock_disable, - .is_enabled = cpg_div6_clock_is_enabled, - .get_parent = cpg_div6_clock_get_parent, - .set_parent = cpg_div6_clock_set_parent, - .recalc_rate = cpg_div6_clock_recalc_rate, - .round_rate = cpg_div6_clock_round_rate, - .set_rate = cpg_div6_clock_set_rate, -}; - - -/** - * cpg_div6_register - Register a DIV6 clock - * @name: Name of the DIV6 clock - * @num_parents: Number of parent clocks of the DIV6 clock (1, 4, or 8) - * @parent_names: Array containing the names of the parent clocks - * @reg: Mapped register used to control the DIV6 clock - */ -struct clk * __init cpg_div6_register(const char *name, - unsigned int num_parents, - const char **parent_names, - void __iomem *reg) -{ - unsigned int valid_parents; - struct clk_init_data init; - struct div6_clock *clock; - struct clk *clk; - unsigned int i; - - clock = kzalloc(sizeof(*clock), GFP_KERNEL); - if (!clock) - return ERR_PTR(-ENOMEM); - - clock->parents = kmalloc_array(num_parents, sizeof(*clock->parents), - GFP_KERNEL); - if (!clock->parents) { - clk = ERR_PTR(-ENOMEM); - goto free_clock; - } - - clock->reg = reg; - - /* - * Read the divisor. Disabling the clock overwrites the divisor, so we - * need to cache its value for the enable operation. - */ - clock->div = (clk_readl(clock->reg) & CPG_DIV6_DIV_MASK) + 1; - - switch (num_parents) { - case 1: - /* fixed parent clock */ - clock->src_shift = clock->src_width = 0; - break; - case 4: - /* clock with EXSRC bits 6-7 */ - clock->src_shift = 6; - clock->src_width = 2; - break; - case 8: - /* VCLK with EXSRC bits 12-14 */ - clock->src_shift = 12; - clock->src_width = 3; - break; - default: - pr_err("%s: invalid number of parents for DIV6 clock %s\n", - __func__, name); - clk = ERR_PTR(-EINVAL); - goto free_parents; - } - - /* Filter out invalid parents */ - for (i = 0, valid_parents = 0; i < num_parents; i++) { - if (parent_names[i]) { - parent_names[valid_parents] = parent_names[i]; - clock->parents[valid_parents] = i; - valid_parents++; - } - } - - /* Register the clock. */ - init.name = name; - init.ops = &cpg_div6_clock_ops; - init.flags = CLK_IS_BASIC; - init.parent_names = parent_names; - init.num_parents = valid_parents; - - clock->hw.init = &init; - - clk = clk_register(NULL, &clock->hw); - if (IS_ERR(clk)) - goto free_parents; - - return clk; - -free_parents: - kfree(clock->parents); -free_clock: - kfree(clock); - return clk; -} - -static void __init cpg_div6_clock_init(struct device_node *np) -{ - unsigned int num_parents; - const char **parent_names; - const char *clk_name = np->name; - void __iomem *reg; - struct clk *clk; - unsigned int i; - - num_parents = of_clk_get_parent_count(np); - if (num_parents < 1) { - pr_err("%s: no parent found for %s DIV6 clock\n", - __func__, np->name); - return; - } - - parent_names = kmalloc_array(num_parents, sizeof(*parent_names), - GFP_KERNEL); - if (!parent_names) - return; - - reg = of_iomap(np, 0); - if (reg == NULL) { - pr_err("%s: failed to map %s DIV6 clock register\n", - __func__, np->name); - goto error; - } - - /* Parse the DT properties. */ - of_property_read_string(np, "clock-output-names", &clk_name); - - for (i = 0; i < num_parents; i++) - parent_names[i] = of_clk_get_parent_name(np, i); - - clk = cpg_div6_register(clk_name, num_parents, parent_names, reg); - if (IS_ERR(clk)) { - pr_err("%s: failed to register %s DIV6 clock (%ld)\n", - __func__, np->name, PTR_ERR(clk)); - goto error; - } - - of_clk_add_provider(np, of_clk_src_simple_get, clk); - - kfree(parent_names); - return; - -error: - if (reg) - iounmap(reg); - kfree(parent_names); -} -CLK_OF_DECLARE(cpg_div6_clk, "renesas,cpg-div6-clock", cpg_div6_clock_init); diff --git a/drivers/clk/shmobile/clk-div6.h b/drivers/clk/shmobile/clk-div6.h deleted file mode 100644 index 9a85a9518..000000000 --- a/drivers/clk/shmobile/clk-div6.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef __SHMOBILE_CLK_DIV6_H__ -#define __SHMOBILE_CLK_DIV6_H__ - -struct clk *cpg_div6_register(const char *name, unsigned int num_parents, - const char **parent_names, void __iomem *reg); - -#endif diff --git a/drivers/clk/shmobile/clk-emev2.c b/drivers/clk/shmobile/clk-emev2.c deleted file mode 100644 index a91825471..000000000 --- a/drivers/clk/shmobile/clk-emev2.c +++ /dev/null @@ -1,110 +0,0 @@ -/* - * EMMA Mobile EV2 common clock framework support - * - * Copyright (C) 2013 Takashi Yoshii <takashi.yoshii.ze@renesas.com> - * Copyright (C) 2012 Magnus Damm - * - * 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; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ -#include <linux/clk-provider.h> -#include <linux/clkdev.h> -#include <linux/io.h> -#include <linux/of.h> -#include <linux/of_address.h> - -/* EMEV2 SMU registers */ -#define USIAU0_RSTCTRL 0x094 -#define USIBU1_RSTCTRL 0x0ac -#define USIBU2_RSTCTRL 0x0b0 -#define USIBU3_RSTCTRL 0x0b4 -#define IIC0_RSTCTRL 0x0dc -#define IIC1_RSTCTRL 0x0e0 -#define STI_RSTCTRL 0x124 -#define STI_CLKSEL 0x688 - -static DEFINE_SPINLOCK(lock); - -/* not pretty, but hey */ -static void __iomem *smu_base; - -static void __init emev2_smu_write(unsigned long value, int offs) -{ - BUG_ON(!smu_base || (offs >= PAGE_SIZE)); - writel_relaxed(value, smu_base + offs); -} - -static const struct of_device_id smu_id[] __initconst = { - { .compatible = "renesas,emev2-smu", }, - {}, -}; - -static void __init emev2_smu_init(void) -{ - struct device_node *np; - - np = of_find_matching_node(NULL, smu_id); - BUG_ON(!np); - smu_base = of_iomap(np, 0); - BUG_ON(!smu_base); - of_node_put(np); - - /* setup STI timer to run on 32.768 kHz and deassert reset */ - emev2_smu_write(0, STI_CLKSEL); - emev2_smu_write(1, STI_RSTCTRL); - - /* deassert reset for UART0->UART3 */ - emev2_smu_write(2, USIAU0_RSTCTRL); - emev2_smu_write(2, USIBU1_RSTCTRL); - emev2_smu_write(2, USIBU2_RSTCTRL); - emev2_smu_write(2, USIBU3_RSTCTRL); - - /* deassert reset for IIC0->IIC1 */ - emev2_smu_write(1, IIC0_RSTCTRL); - emev2_smu_write(1, IIC1_RSTCTRL); -} - -static void __init emev2_smu_clkdiv_init(struct device_node *np) -{ - u32 reg[2]; - struct clk *clk; - const char *parent_name = of_clk_get_parent_name(np, 0); - if (WARN_ON(of_property_read_u32_array(np, "reg", reg, 2))) - return; - if (!smu_base) - emev2_smu_init(); - clk = clk_register_divider(NULL, np->name, parent_name, 0, - smu_base + reg[0], reg[1], 8, 0, &lock); - of_clk_add_provider(np, of_clk_src_simple_get, clk); - clk_register_clkdev(clk, np->name, NULL); - pr_debug("## %s %s %p\n", __func__, np->name, clk); -} -CLK_OF_DECLARE(emev2_smu_clkdiv, "renesas,emev2-smu-clkdiv", - emev2_smu_clkdiv_init); - -static void __init emev2_smu_gclk_init(struct device_node *np) -{ - u32 reg[2]; - struct clk *clk; - const char *parent_name = of_clk_get_parent_name(np, 0); - if (WARN_ON(of_property_read_u32_array(np, "reg", reg, 2))) - return; - if (!smu_base) - emev2_smu_init(); - clk = clk_register_gate(NULL, np->name, parent_name, 0, - smu_base + reg[0], reg[1], 0, &lock); - of_clk_add_provider(np, of_clk_src_simple_get, clk); - clk_register_clkdev(clk, np->name, NULL); - pr_debug("## %s %s %p\n", __func__, np->name, clk); -} -CLK_OF_DECLARE(emev2_smu_gclk, "renesas,emev2-smu-gclk", emev2_smu_gclk_init); diff --git a/drivers/clk/shmobile/clk-mstp.c b/drivers/clk/shmobile/clk-mstp.c deleted file mode 100644 index 3b09716eb..000000000 --- a/drivers/clk/shmobile/clk-mstp.c +++ /dev/null @@ -1,329 +0,0 @@ -/* - * R-Car MSTP clocks - * - * Copyright (C) 2013 Ideas On Board SPRL - * Copyright (C) 2015 Glider bvba - * - * Contact: Laurent Pinchart <laurent.pinchart@ideasonboard.com> - * - * 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; version 2 of the License. - */ - -#include <linux/clk.h> -#include <linux/clk-provider.h> -#include <linux/clkdev.h> -#include <linux/clk/shmobile.h> -#include <linux/device.h> -#include <linux/io.h> -#include <linux/of.h> -#include <linux/of_address.h> -#include <linux/pm_clock.h> -#include <linux/pm_domain.h> -#include <linux/spinlock.h> - -/* - * MSTP clocks. We can't use standard gate clocks as we need to poll on the - * status register when enabling the clock. - */ - -#define MSTP_MAX_CLOCKS 32 - -/** - * struct mstp_clock_group - MSTP gating clocks group - * - * @data: clocks in this group - * @smstpcr: module stop control register - * @mstpsr: module stop status register (optional) - * @lock: protects writes to SMSTPCR - */ -struct mstp_clock_group { - struct clk_onecell_data data; - void __iomem *smstpcr; - void __iomem *mstpsr; - spinlock_t lock; -}; - -/** - * struct mstp_clock - MSTP gating clock - * @hw: handle between common and hardware-specific interfaces - * @bit_index: control bit index - * @group: MSTP clocks group - */ -struct mstp_clock { - struct clk_hw hw; - u32 bit_index; - struct mstp_clock_group *group; -}; - -#define to_mstp_clock(_hw) container_of(_hw, struct mstp_clock, hw) - -static int cpg_mstp_clock_endisable(struct clk_hw *hw, bool enable) -{ - struct mstp_clock *clock = to_mstp_clock(hw); - struct mstp_clock_group *group = clock->group; - u32 bitmask = BIT(clock->bit_index); - unsigned long flags; - unsigned int i; - u32 value; - - spin_lock_irqsave(&group->lock, flags); - - value = clk_readl(group->smstpcr); - if (enable) - value &= ~bitmask; - else - value |= bitmask; - clk_writel(value, group->smstpcr); - - spin_unlock_irqrestore(&group->lock, flags); - - if (!enable || !group->mstpsr) - return 0; - - for (i = 1000; i > 0; --i) { - if (!(clk_readl(group->mstpsr) & bitmask)) - break; - cpu_relax(); - } - - if (!i) { - pr_err("%s: failed to enable %p[%d]\n", __func__, - group->smstpcr, clock->bit_index); - return -ETIMEDOUT; - } - - return 0; -} - -static int cpg_mstp_clock_enable(struct clk_hw *hw) -{ - return cpg_mstp_clock_endisable(hw, true); -} - -static void cpg_mstp_clock_disable(struct clk_hw *hw) -{ - cpg_mstp_clock_endisable(hw, false); -} - -static int cpg_mstp_clock_is_enabled(struct clk_hw *hw) -{ - struct mstp_clock *clock = to_mstp_clock(hw); - struct mstp_clock_group *group = clock->group; - u32 value; - - if (group->mstpsr) - value = clk_readl(group->mstpsr); - else - value = clk_readl(group->smstpcr); - - return !(value & BIT(clock->bit_index)); -} - -static const struct clk_ops cpg_mstp_clock_ops = { - .enable = cpg_mstp_clock_enable, - .disable = cpg_mstp_clock_disable, - .is_enabled = cpg_mstp_clock_is_enabled, -}; - -static struct clk * __init -cpg_mstp_clock_register(const char *name, const char *parent_name, - unsigned int index, struct mstp_clock_group *group) -{ - struct clk_init_data init; - struct mstp_clock *clock; - struct clk *clk; - - clock = kzalloc(sizeof(*clock), GFP_KERNEL); - if (!clock) { - pr_err("%s: failed to allocate MSTP clock.\n", __func__); - return ERR_PTR(-ENOMEM); - } - - init.name = name; - init.ops = &cpg_mstp_clock_ops; - init.flags = CLK_IS_BASIC | CLK_SET_RATE_PARENT; - init.parent_names = &parent_name; - init.num_parents = 1; - - clock->bit_index = index; - clock->group = group; - clock->hw.init = &init; - - clk = clk_register(NULL, &clock->hw); - - if (IS_ERR(clk)) - kfree(clock); - - return clk; -} - -static void __init cpg_mstp_clocks_init(struct device_node *np) -{ - struct mstp_clock_group *group; - const char *idxname; - struct clk **clks; - unsigned int i; - - group = kzalloc(sizeof(*group), GFP_KERNEL); - clks = kmalloc(MSTP_MAX_CLOCKS * sizeof(*clks), GFP_KERNEL); - if (group == NULL || clks == NULL) { - kfree(group); - kfree(clks); - pr_err("%s: failed to allocate group\n", __func__); - return; - } - - spin_lock_init(&group->lock); - group->data.clks = clks; - - group->smstpcr = of_iomap(np, 0); - group->mstpsr = of_iomap(np, 1); - - if (group->smstpcr == NULL) { - pr_err("%s: failed to remap SMSTPCR\n", __func__); - kfree(group); - kfree(clks); - return; - } - - for (i = 0; i < MSTP_MAX_CLOCKS; ++i) - clks[i] = ERR_PTR(-ENOENT); - - if (of_find_property(np, "clock-indices", &i)) - idxname = "clock-indices"; - else - idxname = "renesas,clock-indices"; - - for (i = 0; i < MSTP_MAX_CLOCKS; ++i) { - const char *parent_name; - const char *name; - u32 clkidx; - int ret; - - /* Skip clocks with no name. */ - ret = of_property_read_string_index(np, "clock-output-names", - i, &name); - if (ret < 0 || strlen(name) == 0) - continue; - - parent_name = of_clk_get_parent_name(np, i); - ret = of_property_read_u32_index(np, idxname, i, &clkidx); - if (parent_name == NULL || ret < 0) - break; - - if (clkidx >= MSTP_MAX_CLOCKS) { - pr_err("%s: invalid clock %s %s index %u\n", - __func__, np->name, name, clkidx); - continue; - } - - clks[clkidx] = cpg_mstp_clock_register(name, parent_name, - clkidx, group); - if (!IS_ERR(clks[clkidx])) { - group->data.clk_num = max(group->data.clk_num, - clkidx + 1); - /* - * Register a clkdev to let board code retrieve the - * clock by name and register aliases for non-DT - * devices. - * - * FIXME: Remove this when all devices that require a - * clock will be instantiated from DT. - */ - clk_register_clkdev(clks[clkidx], name, NULL); - } else { - pr_err("%s: failed to register %s %s clock (%ld)\n", - __func__, np->name, name, PTR_ERR(clks[clkidx])); - } - } - - of_clk_add_provider(np, of_clk_src_onecell_get, &group->data); -} -CLK_OF_DECLARE(cpg_mstp_clks, "renesas,cpg-mstp-clocks", cpg_mstp_clocks_init); - - -#ifdef CONFIG_PM_GENERIC_DOMAINS_OF -int cpg_mstp_attach_dev(struct generic_pm_domain *domain, struct device *dev) -{ - struct device_node *np = dev->of_node; - struct of_phandle_args clkspec; - struct clk *clk; - int i = 0; - int error; - - while (!of_parse_phandle_with_args(np, "clocks", "#clock-cells", i, - &clkspec)) { - if (of_device_is_compatible(clkspec.np, - "renesas,cpg-mstp-clocks")) - goto found; - - /* BSC on r8a73a4/sh73a0 uses zb_clk instead of an mstp clock */ - if (!strcmp(clkspec.np->name, "zb_clk")) - goto found; - - of_node_put(clkspec.np); - i++; - } - - return 0; - -found: - clk = of_clk_get_from_provider(&clkspec); - of_node_put(clkspec.np); - - if (IS_ERR(clk)) - return PTR_ERR(clk); - - error = pm_clk_create(dev); - if (error) { - dev_err(dev, "pm_clk_create failed %d\n", error); - goto fail_put; - } - - error = pm_clk_add_clk(dev, clk); - if (error) { - dev_err(dev, "pm_clk_add_clk %pC failed %d\n", clk, error); - goto fail_destroy; - } - - return 0; - -fail_destroy: - pm_clk_destroy(dev); -fail_put: - clk_put(clk); - return error; -} - -void cpg_mstp_detach_dev(struct generic_pm_domain *domain, struct device *dev) -{ - if (!list_empty(&dev->power.subsys_data->clock_list)) - pm_clk_destroy(dev); -} - -void __init cpg_mstp_add_clk_domain(struct device_node *np) -{ - struct generic_pm_domain *pd; - u32 ncells; - - if (of_property_read_u32(np, "#power-domain-cells", &ncells)) { - pr_warn("%s lacks #power-domain-cells\n", np->full_name); - return; - } - - pd = kzalloc(sizeof(*pd), GFP_KERNEL); - if (!pd) - return; - - pd->name = np->name; - - pd->flags = GENPD_FLAG_PM_CLK; - pm_genpd_init(pd, &simple_qos_governor, false); - pd->attach_dev = cpg_mstp_attach_dev; - pd->detach_dev = cpg_mstp_detach_dev; - - of_genpd_add_provider_simple(np, pd); -} -#endif /* !CONFIG_PM_GENERIC_DOMAINS_OF */ diff --git a/drivers/clk/shmobile/clk-r8a73a4.c b/drivers/clk/shmobile/clk-r8a73a4.c deleted file mode 100644 index 9326204be..000000000 --- a/drivers/clk/shmobile/clk-r8a73a4.c +++ /dev/null @@ -1,241 +0,0 @@ -/* - * r8a73a4 Core CPG Clocks - * - * Copyright (C) 2014 Ulrich Hecht - * - * 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; version 2 of the License. - */ - -#include <linux/clk-provider.h> -#include <linux/clk/shmobile.h> -#include <linux/init.h> -#include <linux/kernel.h> -#include <linux/slab.h> -#include <linux/of.h> -#include <linux/of_address.h> -#include <linux/spinlock.h> - -struct r8a73a4_cpg { - struct clk_onecell_data data; - spinlock_t lock; - void __iomem *reg; -}; - -#define CPG_CKSCR 0xc0 -#define CPG_FRQCRA 0x00 -#define CPG_FRQCRB 0x04 -#define CPG_FRQCRC 0xe0 -#define CPG_PLL0CR 0xd8 -#define CPG_PLL1CR 0x28 -#define CPG_PLL2CR 0x2c -#define CPG_PLL2HCR 0xe4 -#define CPG_PLL2SCR 0xf4 - -#define CLK_ENABLE_ON_INIT BIT(0) - -struct div4_clk { - const char *name; - unsigned int reg; - unsigned int shift; -}; - -static struct div4_clk div4_clks[] = { - { "i", CPG_FRQCRA, 20 }, - { "m3", CPG_FRQCRA, 12 }, - { "b", CPG_FRQCRA, 8 }, - { "m1", CPG_FRQCRA, 4 }, - { "m2", CPG_FRQCRA, 0 }, - { "zx", CPG_FRQCRB, 12 }, - { "zs", CPG_FRQCRB, 8 }, - { "hp", CPG_FRQCRB, 4 }, - { NULL, 0, 0 }, -}; - -static const struct clk_div_table div4_div_table[] = { - { 0, 2 }, { 1, 3 }, { 2, 4 }, { 3, 6 }, { 4, 8 }, { 5, 12 }, - { 6, 16 }, { 7, 18 }, { 8, 24 }, { 10, 36 }, { 11, 48 }, - { 12, 10 }, { 0, 0 } -}; - -static struct clk * __init -r8a73a4_cpg_register_clock(struct device_node *np, struct r8a73a4_cpg *cpg, - const char *name) -{ - const struct clk_div_table *table = NULL; - const char *parent_name; - unsigned int shift, reg; - unsigned int mult = 1; - unsigned int div = 1; - - - if (!strcmp(name, "main")) { - u32 ckscr = clk_readl(cpg->reg + CPG_CKSCR); - - switch ((ckscr >> 28) & 3) { - case 0: /* extal1 */ - parent_name = of_clk_get_parent_name(np, 0); - break; - case 1: /* extal1 / 2 */ - parent_name = of_clk_get_parent_name(np, 0); - div = 2; - break; - case 2: /* extal2 */ - parent_name = of_clk_get_parent_name(np, 1); - break; - case 3: /* extal2 / 2 */ - parent_name = of_clk_get_parent_name(np, 1); - div = 2; - break; - } - } else if (!strcmp(name, "pll0")) { - /* PLL0/1 are configurable multiplier clocks. Register them as - * fixed factor clocks for now as there's no generic multiplier - * clock implementation and we currently have no need to change - * the multiplier value. - */ - u32 value = clk_readl(cpg->reg + CPG_PLL0CR); - - parent_name = "main"; - mult = ((value >> 24) & 0x7f) + 1; - if (value & BIT(20)) - div = 2; - } else if (!strcmp(name, "pll1")) { - u32 value = clk_readl(cpg->reg + CPG_PLL1CR); - - parent_name = "main"; - /* XXX: enable bit? */ - mult = ((value >> 24) & 0x7f) + 1; - if (value & BIT(7)) - div = 2; - } else if (!strncmp(name, "pll2", 4)) { - u32 value, cr; - - switch (name[4]) { - case 0: - cr = CPG_PLL2CR; - break; - case 's': - cr = CPG_PLL2SCR; - break; - case 'h': - cr = CPG_PLL2HCR; - break; - default: - return ERR_PTR(-EINVAL); - } - value = clk_readl(cpg->reg + cr); - switch ((value >> 5) & 7) { - case 0: - parent_name = "main"; - div = 2; - break; - case 1: - parent_name = "extal2"; - div = 2; - break; - case 3: - parent_name = "extal2"; - div = 4; - break; - case 4: - parent_name = "main"; - break; - case 5: - parent_name = "extal2"; - break; - default: - pr_warn("%s: unexpected parent of %s\n", __func__, - name); - return ERR_PTR(-EINVAL); - } - /* XXX: enable bit? */ - mult = ((value >> 24) & 0x7f) + 1; - } else if (!strcmp(name, "z") || !strcmp(name, "z2")) { - u32 shift = 8; - - parent_name = "pll0"; - if (name[1] == '2') { - div = 2; - shift = 0; - } - div *= 32; - mult = 0x20 - ((clk_readl(cpg->reg + CPG_FRQCRC) >> shift) - & 0x1f); - } else { - struct div4_clk *c; - - for (c = div4_clks; c->name; c++) { - if (!strcmp(name, c->name)) - break; - } - if (!c->name) - return ERR_PTR(-EINVAL); - - parent_name = "pll1"; - table = div4_div_table; - reg = c->reg; - shift = c->shift; - } - - if (!table) { - return clk_register_fixed_factor(NULL, name, parent_name, 0, - mult, div); - } else { - return clk_register_divider_table(NULL, name, parent_name, 0, - cpg->reg + reg, shift, 4, 0, - table, &cpg->lock); - } -} - -static void __init r8a73a4_cpg_clocks_init(struct device_node *np) -{ - struct r8a73a4_cpg *cpg; - struct clk **clks; - unsigned int i; - int num_clks; - - num_clks = of_property_count_strings(np, "clock-output-names"); - if (num_clks < 0) { - pr_err("%s: failed to count clocks\n", __func__); - return; - } - - cpg = kzalloc(sizeof(*cpg), GFP_KERNEL); - clks = kcalloc(num_clks, sizeof(*clks), GFP_KERNEL); - if (cpg == NULL || clks == NULL) { - /* We're leaking memory on purpose, there's no point in cleaning - * up as the system won't boot anyway. - */ - return; - } - - spin_lock_init(&cpg->lock); - - cpg->data.clks = clks; - cpg->data.clk_num = num_clks; - - cpg->reg = of_iomap(np, 0); - if (WARN_ON(cpg->reg == NULL)) - return; - - for (i = 0; i < num_clks; ++i) { - const char *name; - struct clk *clk; - - of_property_read_string_index(np, "clock-output-names", i, - &name); - - clk = r8a73a4_cpg_register_clock(np, cpg, name); - if (IS_ERR(clk)) - pr_err("%s: failed to register %s %s clock (%ld)\n", - __func__, np->name, name, PTR_ERR(clk)); - else - cpg->data.clks[i] = clk; - } - - of_clk_add_provider(np, of_clk_src_onecell_get, &cpg->data); -} -CLK_OF_DECLARE(r8a73a4_cpg_clks, "renesas,r8a73a4-cpg-clocks", - r8a73a4_cpg_clocks_init); diff --git a/drivers/clk/shmobile/clk-r8a7740.c b/drivers/clk/shmobile/clk-r8a7740.c deleted file mode 100644 index 1e6b1da58..000000000 --- a/drivers/clk/shmobile/clk-r8a7740.c +++ /dev/null @@ -1,199 +0,0 @@ -/* - * r8a7740 Core CPG Clocks - * - * Copyright (C) 2014 Ulrich Hecht - * - * 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; version 2 of the License. - */ - -#include <linux/clk-provider.h> -#include <linux/clk/shmobile.h> -#include <linux/init.h> -#include <linux/kernel.h> -#include <linux/slab.h> -#include <linux/of.h> -#include <linux/of_address.h> -#include <linux/spinlock.h> - -struct r8a7740_cpg { - struct clk_onecell_data data; - spinlock_t lock; - void __iomem *reg; -}; - -#define CPG_FRQCRA 0x00 -#define CPG_FRQCRB 0x04 -#define CPG_PLLC2CR 0x2c -#define CPG_USBCKCR 0x8c -#define CPG_FRQCRC 0xe0 - -#define CLK_ENABLE_ON_INIT BIT(0) - -struct div4_clk { - const char *name; - unsigned int reg; - unsigned int shift; - int flags; -}; - -static struct div4_clk div4_clks[] = { - { "i", CPG_FRQCRA, 20, CLK_ENABLE_ON_INIT }, - { "zg", CPG_FRQCRA, 16, CLK_ENABLE_ON_INIT }, - { "b", CPG_FRQCRA, 8, CLK_ENABLE_ON_INIT }, - { "m1", CPG_FRQCRA, 4, CLK_ENABLE_ON_INIT }, - { "hp", CPG_FRQCRB, 4, 0 }, - { "hpp", CPG_FRQCRC, 20, 0 }, - { "usbp", CPG_FRQCRC, 16, 0 }, - { "s", CPG_FRQCRC, 12, 0 }, - { "zb", CPG_FRQCRC, 8, 0 }, - { "m3", CPG_FRQCRC, 4, 0 }, - { "cp", CPG_FRQCRC, 0, 0 }, - { NULL, 0, 0, 0 }, -}; - -static const struct clk_div_table div4_div_table[] = { - { 0, 2 }, { 1, 3 }, { 2, 4 }, { 3, 6 }, { 4, 8 }, { 5, 12 }, - { 6, 16 }, { 7, 18 }, { 8, 24 }, { 9, 32 }, { 10, 36 }, { 11, 48 }, - { 13, 72 }, { 14, 96 }, { 0, 0 } -}; - -static u32 cpg_mode __initdata; - -static struct clk * __init -r8a7740_cpg_register_clock(struct device_node *np, struct r8a7740_cpg *cpg, - const char *name) -{ - const struct clk_div_table *table = NULL; - const char *parent_name; - unsigned int shift, reg; - unsigned int mult = 1; - unsigned int div = 1; - - if (!strcmp(name, "r")) { - switch (cpg_mode & (BIT(2) | BIT(1))) { - case BIT(1) | BIT(2): - /* extal1 */ - parent_name = of_clk_get_parent_name(np, 0); - div = 2048; - break; - case BIT(2): - /* extal1 */ - parent_name = of_clk_get_parent_name(np, 0); - div = 1024; - break; - default: - /* extalr */ - parent_name = of_clk_get_parent_name(np, 2); - break; - } - } else if (!strcmp(name, "system")) { - parent_name = of_clk_get_parent_name(np, 0); - if (cpg_mode & BIT(1)) - div = 2; - } else if (!strcmp(name, "pllc0")) { - /* PLLC0/1 are configurable multiplier clocks. Register them as - * fixed factor clocks for now as there's no generic multiplier - * clock implementation and we currently have no need to change - * the multiplier value. - */ - u32 value = clk_readl(cpg->reg + CPG_FRQCRC); - parent_name = "system"; - mult = ((value >> 24) & 0x7f) + 1; - } else if (!strcmp(name, "pllc1")) { - u32 value = clk_readl(cpg->reg + CPG_FRQCRA); - parent_name = "system"; - mult = ((value >> 24) & 0x7f) + 1; - div = 2; - } else if (!strcmp(name, "pllc2")) { - u32 value = clk_readl(cpg->reg + CPG_PLLC2CR); - parent_name = "system"; - mult = ((value >> 24) & 0x3f) + 1; - } else if (!strcmp(name, "usb24s")) { - u32 value = clk_readl(cpg->reg + CPG_USBCKCR); - if (value & BIT(7)) - /* extal2 */ - parent_name = of_clk_get_parent_name(np, 1); - else - parent_name = "system"; - if (!(value & BIT(6))) - div = 2; - } else { - struct div4_clk *c; - for (c = div4_clks; c->name; c++) { - if (!strcmp(name, c->name)) { - parent_name = "pllc1"; - table = div4_div_table; - reg = c->reg; - shift = c->shift; - break; - } - } - if (!c->name) - return ERR_PTR(-EINVAL); - } - - if (!table) { - return clk_register_fixed_factor(NULL, name, parent_name, 0, - mult, div); - } else { - return clk_register_divider_table(NULL, name, parent_name, 0, - cpg->reg + reg, shift, 4, 0, - table, &cpg->lock); - } -} - -static void __init r8a7740_cpg_clocks_init(struct device_node *np) -{ - struct r8a7740_cpg *cpg; - struct clk **clks; - unsigned int i; - int num_clks; - - if (of_property_read_u32(np, "renesas,mode", &cpg_mode)) - pr_warn("%s: missing renesas,mode property\n", __func__); - - num_clks = of_property_count_strings(np, "clock-output-names"); - if (num_clks < 0) { - pr_err("%s: failed to count clocks\n", __func__); - return; - } - - cpg = kzalloc(sizeof(*cpg), GFP_KERNEL); - clks = kzalloc(num_clks * sizeof(*clks), GFP_KERNEL); - if (cpg == NULL || clks == NULL) { - /* We're leaking memory on purpose, there's no point in cleaning - * up as the system won't boot anyway. - */ - return; - } - - spin_lock_init(&cpg->lock); - - cpg->data.clks = clks; - cpg->data.clk_num = num_clks; - - cpg->reg = of_iomap(np, 0); - if (WARN_ON(cpg->reg == NULL)) - return; - - for (i = 0; i < num_clks; ++i) { - const char *name; - struct clk *clk; - - of_property_read_string_index(np, "clock-output-names", i, - &name); - - clk = r8a7740_cpg_register_clock(np, cpg, name); - if (IS_ERR(clk)) - pr_err("%s: failed to register %s %s clock (%ld)\n", - __func__, np->name, name, PTR_ERR(clk)); - else - cpg->data.clks[i] = clk; - } - - of_clk_add_provider(np, of_clk_src_onecell_get, &cpg->data); -} -CLK_OF_DECLARE(r8a7740_cpg_clks, "renesas,r8a7740-cpg-clocks", - r8a7740_cpg_clocks_init); diff --git a/drivers/clk/shmobile/clk-r8a7778.c b/drivers/clk/shmobile/clk-r8a7778.c deleted file mode 100644 index b1741551f..000000000 --- a/drivers/clk/shmobile/clk-r8a7778.c +++ /dev/null @@ -1,145 +0,0 @@ -/* - * r8a7778 Core CPG Clocks - * - * Copyright (C) 2014 Ulrich Hecht - * - * 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; version 2 of the License. - */ - -#include <linux/clk-provider.h> -#include <linux/clk/shmobile.h> -#include <linux/of_address.h> -#include <linux/slab.h> - -struct r8a7778_cpg { - struct clk_onecell_data data; - spinlock_t lock; - void __iomem *reg; -}; - -/* PLL multipliers per bits 11, 12, and 18 of MODEMR */ -static const struct { - unsigned long plla_mult; - unsigned long pllb_mult; -} r8a7778_rates[] __initconst = { - [0] = { 21, 21 }, - [1] = { 24, 24 }, - [2] = { 28, 28 }, - [3] = { 32, 32 }, - [5] = { 24, 21 }, - [6] = { 28, 21 }, - [7] = { 32, 24 }, -}; - -/* Clock dividers per bits 1 and 2 of MODEMR */ -static const struct { - const char *name; - unsigned int div[4]; -} r8a7778_divs[6] __initconst = { - { "b", { 12, 12, 16, 18 } }, - { "out", { 12, 12, 16, 18 } }, - { "p", { 16, 12, 16, 12 } }, - { "s", { 4, 3, 4, 3 } }, - { "s1", { 8, 6, 8, 6 } }, -}; - -static u32 cpg_mode_rates __initdata; -static u32 cpg_mode_divs __initdata; - -static struct clk * __init -r8a7778_cpg_register_clock(struct device_node *np, struct r8a7778_cpg *cpg, - const char *name) -{ - if (!strcmp(name, "plla")) { - return clk_register_fixed_factor(NULL, "plla", - of_clk_get_parent_name(np, 0), 0, - r8a7778_rates[cpg_mode_rates].plla_mult, 1); - } else if (!strcmp(name, "pllb")) { - return clk_register_fixed_factor(NULL, "pllb", - of_clk_get_parent_name(np, 0), 0, - r8a7778_rates[cpg_mode_rates].pllb_mult, 1); - } else { - unsigned int i; - - for (i = 0; i < ARRAY_SIZE(r8a7778_divs); i++) { - if (!strcmp(name, r8a7778_divs[i].name)) { - return clk_register_fixed_factor(NULL, - r8a7778_divs[i].name, - "plla", 0, 1, - r8a7778_divs[i].div[cpg_mode_divs]); - } - } - } - - return ERR_PTR(-EINVAL); -} - - -static void __init r8a7778_cpg_clocks_init(struct device_node *np) -{ - struct r8a7778_cpg *cpg; - struct clk **clks; - unsigned int i; - int num_clks; - - num_clks = of_property_count_strings(np, "clock-output-names"); - if (num_clks < 0) { - pr_err("%s: failed to count clocks\n", __func__); - return; - } - - cpg = kzalloc(sizeof(*cpg), GFP_KERNEL); - clks = kcalloc(num_clks, sizeof(*clks), GFP_KERNEL); - if (cpg == NULL || clks == NULL) { - /* We're leaking memory on purpose, there's no point in cleaning - * up as the system won't boot anyway. - */ - return; - } - - spin_lock_init(&cpg->lock); - - cpg->data.clks = clks; - cpg->data.clk_num = num_clks; - - cpg->reg = of_iomap(np, 0); - if (WARN_ON(cpg->reg == NULL)) - return; - - for (i = 0; i < num_clks; ++i) { - const char *name; - struct clk *clk; - - of_property_read_string_index(np, "clock-output-names", i, - &name); - - clk = r8a7778_cpg_register_clock(np, cpg, name); - if (IS_ERR(clk)) - pr_err("%s: failed to register %s %s clock (%ld)\n", - __func__, np->name, name, PTR_ERR(clk)); - else - cpg->data.clks[i] = clk; - } - - of_clk_add_provider(np, of_clk_src_onecell_get, &cpg->data); - - cpg_mstp_add_clk_domain(np); -} - -CLK_OF_DECLARE(r8a7778_cpg_clks, "renesas,r8a7778-cpg-clocks", - r8a7778_cpg_clocks_init); - -void __init r8a7778_clocks_init(u32 mode) -{ - BUG_ON(!(mode & BIT(19))); - - cpg_mode_rates = (!!(mode & BIT(18)) << 2) | - (!!(mode & BIT(12)) << 1) | - (!!(mode & BIT(11))); - cpg_mode_divs = (!!(mode & BIT(2)) << 1) | - (!!(mode & BIT(1))); - - of_clk_init(NULL); -} diff --git a/drivers/clk/shmobile/clk-r8a7779.c b/drivers/clk/shmobile/clk-r8a7779.c deleted file mode 100644 index 92275c5f2..000000000 --- a/drivers/clk/shmobile/clk-r8a7779.c +++ /dev/null @@ -1,182 +0,0 @@ -/* - * r8a7779 Core CPG Clocks - * - * Copyright (C) 2013, 2014 Horms Solutions Ltd. - * - * Contact: Simon Horman <horms@verge.net.au> - * - * 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; version 2 of the License. - */ - -#include <linux/clk-provider.h> -#include <linux/clk/shmobile.h> -#include <linux/init.h> -#include <linux/kernel.h> -#include <linux/of.h> -#include <linux/of_address.h> -#include <linux/slab.h> -#include <linux/spinlock.h> - -#include <dt-bindings/clock/r8a7779-clock.h> - -#define CPG_NUM_CLOCKS (R8A7779_CLK_OUT + 1) - -struct r8a7779_cpg { - struct clk_onecell_data data; - spinlock_t lock; - void __iomem *reg; -}; - -/* ----------------------------------------------------------------------------- - * CPG Clock Data - */ - -/* - * MD1 = 1 MD1 = 0 - * (PLLA = 1500) (PLLA = 1600) - * (MHz) (MHz) - *------------------------------------------------+-------------------- - * clkz 1000 (2/3) 800 (1/2) - * clkzs 250 (1/6) 200 (1/8) - * clki 750 (1/2) 800 (1/2) - * clks 250 (1/6) 200 (1/8) - * clks1 125 (1/12) 100 (1/16) - * clks3 187.5 (1/8) 200 (1/8) - * clks4 93.7 (1/16) 100 (1/16) - * clkp 62.5 (1/24) 50 (1/32) - * clkg 62.5 (1/24) 66.6 (1/24) - * clkb, CLKOUT - * (MD2 = 0) 62.5 (1/24) 66.6 (1/24) - * (MD2 = 1) 41.6 (1/36) 50 (1/32) - */ - -#define CPG_CLK_CONFIG_INDEX(md) (((md) & (BIT(2)|BIT(1))) >> 1) - -struct cpg_clk_config { - unsigned int z_mult; - unsigned int z_div; - unsigned int zs_and_s_div; - unsigned int s1_div; - unsigned int p_div; - unsigned int b_and_out_div; -}; - -static const struct cpg_clk_config cpg_clk_configs[4] __initconst = { - { 1, 2, 8, 16, 32, 24 }, - { 2, 3, 6, 12, 24, 24 }, - { 1, 2, 8, 16, 32, 32 }, - { 2, 3, 6, 12, 24, 36 }, -}; - -/* - * MD PLLA Ratio - * 12 11 - *------------------------ - * 0 0 x42 - * 0 1 x48 - * 1 0 x56 - * 1 1 x64 - */ - -#define CPG_PLLA_MULT_INDEX(md) (((md) & (BIT(12)|BIT(11))) >> 11) - -static const unsigned int cpg_plla_mult[4] __initconst = { 42, 48, 56, 64 }; - -/* ----------------------------------------------------------------------------- - * Initialization - */ - -static u32 cpg_mode __initdata; - -static struct clk * __init -r8a7779_cpg_register_clock(struct device_node *np, struct r8a7779_cpg *cpg, - const struct cpg_clk_config *config, - unsigned int plla_mult, const char *name) -{ - const char *parent_name = "plla"; - unsigned int mult = 1; - unsigned int div = 1; - - if (!strcmp(name, "plla")) { - parent_name = of_clk_get_parent_name(np, 0); - mult = plla_mult; - } else if (!strcmp(name, "z")) { - div = config->z_div; - mult = config->z_mult; - } else if (!strcmp(name, "zs") || !strcmp(name, "s")) { - div = config->zs_and_s_div; - } else if (!strcmp(name, "s1")) { - div = config->s1_div; - } else if (!strcmp(name, "p")) { - div = config->p_div; - } else if (!strcmp(name, "b") || !strcmp(name, "out")) { - div = config->b_and_out_div; - } else { - return ERR_PTR(-EINVAL); - } - - return clk_register_fixed_factor(NULL, name, parent_name, 0, mult, div); -} - -static void __init r8a7779_cpg_clocks_init(struct device_node *np) -{ - const struct cpg_clk_config *config; - struct r8a7779_cpg *cpg; - struct clk **clks; - unsigned int i, plla_mult; - int num_clks; - - num_clks = of_property_count_strings(np, "clock-output-names"); - if (num_clks < 0) { - pr_err("%s: failed to count clocks\n", __func__); - return; - } - - cpg = kzalloc(sizeof(*cpg), GFP_KERNEL); - clks = kzalloc(CPG_NUM_CLOCKS * sizeof(*clks), GFP_KERNEL); - if (cpg == NULL || clks == NULL) { - /* We're leaking memory on purpose, there's no point in cleaning - * up as the system won't boot anyway. - */ - return; - } - - spin_lock_init(&cpg->lock); - - cpg->data.clks = clks; - cpg->data.clk_num = num_clks; - - config = &cpg_clk_configs[CPG_CLK_CONFIG_INDEX(cpg_mode)]; - plla_mult = cpg_plla_mult[CPG_PLLA_MULT_INDEX(cpg_mode)]; - - for (i = 0; i < num_clks; ++i) { - const char *name; - struct clk *clk; - - of_property_read_string_index(np, "clock-output-names", i, - &name); - - clk = r8a7779_cpg_register_clock(np, cpg, config, - plla_mult, name); - if (IS_ERR(clk)) - pr_err("%s: failed to register %s %s clock (%ld)\n", - __func__, np->name, name, PTR_ERR(clk)); - else - cpg->data.clks[i] = clk; - } - - of_clk_add_provider(np, of_clk_src_onecell_get, &cpg->data); - - cpg_mstp_add_clk_domain(np); -} -CLK_OF_DECLARE(r8a7779_cpg_clks, "renesas,r8a7779-cpg-clocks", - r8a7779_cpg_clocks_init); - -void __init r8a7779_clocks_init(u32 mode) -{ - cpg_mode = mode; - - of_clk_init(NULL); -} diff --git a/drivers/clk/shmobile/clk-rcar-gen2.c b/drivers/clk/shmobile/clk-rcar-gen2.c deleted file mode 100644 index 841977240..000000000 --- a/drivers/clk/shmobile/clk-rcar-gen2.c +++ /dev/null @@ -1,429 +0,0 @@ -/* - * rcar_gen2 Core CPG Clocks - * - * Copyright (C) 2013 Ideas On Board SPRL - * - * Contact: Laurent Pinchart <laurent.pinchart@ideasonboard.com> - * - * 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; version 2 of the License. - */ - -#include <linux/clk-provider.h> -#include <linux/clk/shmobile.h> -#include <linux/init.h> -#include <linux/kernel.h> -#include <linux/math64.h> -#include <linux/of.h> -#include <linux/of_address.h> -#include <linux/slab.h> -#include <linux/spinlock.h> - -struct rcar_gen2_cpg { - struct clk_onecell_data data; - spinlock_t lock; - void __iomem *reg; -}; - -#define CPG_FRQCRB 0x00000004 -#define CPG_FRQCRB_KICK BIT(31) -#define CPG_SDCKCR 0x00000074 -#define CPG_PLL0CR 0x000000d8 -#define CPG_FRQCRC 0x000000e0 -#define CPG_FRQCRC_ZFC_MASK (0x1f << 8) -#define CPG_FRQCRC_ZFC_SHIFT 8 -#define CPG_ADSPCKCR 0x0000025c -#define CPG_RCANCKCR 0x00000270 - -/* ----------------------------------------------------------------------------- - * Z Clock - * - * Traits of this clock: - * prepare - clk_prepare only ensures that parents are prepared - * enable - clk_enable only ensures that parents are enabled - * rate - rate is adjustable. clk->rate = parent->rate * mult / 32 - * parent - fixed parent. No clk_set_parent support - */ - -struct cpg_z_clk { - struct clk_hw hw; - void __iomem *reg; - void __iomem *kick_reg; -}; - -#define to_z_clk(_hw) container_of(_hw, struct cpg_z_clk, hw) - -static unsigned long cpg_z_clk_recalc_rate(struct clk_hw *hw, - unsigned long parent_rate) -{ - struct cpg_z_clk *zclk = to_z_clk(hw); - unsigned int mult; - unsigned int val; - - val = (clk_readl(zclk->reg) & CPG_FRQCRC_ZFC_MASK) - >> CPG_FRQCRC_ZFC_SHIFT; - mult = 32 - val; - - return div_u64((u64)parent_rate * mult, 32); -} - -static long cpg_z_clk_round_rate(struct clk_hw *hw, unsigned long rate, - unsigned long *parent_rate) -{ - unsigned long prate = *parent_rate; - unsigned int mult; - - if (!prate) - prate = 1; - - mult = div_u64((u64)rate * 32, prate); - mult = clamp(mult, 1U, 32U); - - return *parent_rate / 32 * mult; -} - -static int cpg_z_clk_set_rate(struct clk_hw *hw, unsigned long rate, - unsigned long parent_rate) -{ - struct cpg_z_clk *zclk = to_z_clk(hw); - unsigned int mult; - u32 val, kick; - unsigned int i; - - mult = div_u64((u64)rate * 32, parent_rate); - mult = clamp(mult, 1U, 32U); - - if (clk_readl(zclk->kick_reg) & CPG_FRQCRB_KICK) - return -EBUSY; - - val = clk_readl(zclk->reg); - val &= ~CPG_FRQCRC_ZFC_MASK; - val |= (32 - mult) << CPG_FRQCRC_ZFC_SHIFT; - clk_writel(val, zclk->reg); - - /* - * Set KICK bit in FRQCRB to update hardware setting and wait for - * clock change completion. - */ - kick = clk_readl(zclk->kick_reg); - kick |= CPG_FRQCRB_KICK; - clk_writel(kick, zclk->kick_reg); - - /* - * Note: There is no HW information about the worst case latency. - * - * Using experimental measurements, it seems that no more than - * ~10 iterations are needed, independently of the CPU rate. - * Since this value might be dependent on external xtal rate, pll1 - * rate or even the other emulation clocks rate, use 1000 as a - * "super" safe value. - */ - for (i = 1000; i; i--) { - if (!(clk_readl(zclk->kick_reg) & CPG_FRQCRB_KICK)) - return 0; - - cpu_relax(); - } - - return -ETIMEDOUT; -} - -static const struct clk_ops cpg_z_clk_ops = { - .recalc_rate = cpg_z_clk_recalc_rate, - .round_rate = cpg_z_clk_round_rate, - .set_rate = cpg_z_clk_set_rate, -}; - -static struct clk * __init cpg_z_clk_register(struct rcar_gen2_cpg *cpg) -{ - static const char *parent_name = "pll0"; - struct clk_init_data init; - struct cpg_z_clk *zclk; - struct clk *clk; - - zclk = kzalloc(sizeof(*zclk), GFP_KERNEL); - if (!zclk) - return ERR_PTR(-ENOMEM); - - init.name = "z"; - init.ops = &cpg_z_clk_ops; - init.flags = 0; - init.parent_names = &parent_name; - init.num_parents = 1; - - zclk->reg = cpg->reg + CPG_FRQCRC; - zclk->kick_reg = cpg->reg + CPG_FRQCRB; - zclk->hw.init = &init; - - clk = clk_register(NULL, &zclk->hw); - if (IS_ERR(clk)) - kfree(zclk); - - return clk; -} - -static struct clk * __init cpg_rcan_clk_register(struct rcar_gen2_cpg *cpg, - struct device_node *np) -{ - const char *parent_name = of_clk_get_parent_name(np, 1); - struct clk_fixed_factor *fixed; - struct clk_gate *gate; - struct clk *clk; - - fixed = kzalloc(sizeof(*fixed), GFP_KERNEL); - if (!fixed) - return ERR_PTR(-ENOMEM); - - fixed->mult = 1; - fixed->div = 6; - - gate = kzalloc(sizeof(*gate), GFP_KERNEL); - if (!gate) { - kfree(fixed); - return ERR_PTR(-ENOMEM); - } - - gate->reg = cpg->reg + CPG_RCANCKCR; - gate->bit_idx = 8; - gate->flags = CLK_GATE_SET_TO_DISABLE; - gate->lock = &cpg->lock; - - clk = clk_register_composite(NULL, "rcan", &parent_name, 1, NULL, NULL, - &fixed->hw, &clk_fixed_factor_ops, - &gate->hw, &clk_gate_ops, 0); - if (IS_ERR(clk)) { - kfree(gate); - kfree(fixed); - } - - return clk; -} - -/* ADSP divisors */ -static const struct clk_div_table cpg_adsp_div_table[] = { - { 1, 3 }, { 2, 4 }, { 3, 6 }, { 4, 8 }, - { 5, 12 }, { 6, 16 }, { 7, 18 }, { 8, 24 }, - { 10, 36 }, { 11, 48 }, { 0, 0 }, -}; - -static struct clk * __init cpg_adsp_clk_register(struct rcar_gen2_cpg *cpg) -{ - const char *parent_name = "pll1"; - struct clk_divider *div; - struct clk_gate *gate; - struct clk *clk; - - div = kzalloc(sizeof(*div), GFP_KERNEL); - if (!div) - return ERR_PTR(-ENOMEM); - - div->reg = cpg->reg + CPG_ADSPCKCR; - div->width = 4; - div->table = cpg_adsp_div_table; - div->lock = &cpg->lock; - - gate = kzalloc(sizeof(*gate), GFP_KERNEL); - if (!gate) { - kfree(div); - return ERR_PTR(-ENOMEM); - } - - gate->reg = cpg->reg + CPG_ADSPCKCR; - gate->bit_idx = 8; - gate->flags = CLK_GATE_SET_TO_DISABLE; - gate->lock = &cpg->lock; - - clk = clk_register_composite(NULL, "adsp", &parent_name, 1, NULL, NULL, - &div->hw, &clk_divider_ops, - &gate->hw, &clk_gate_ops, 0); - if (IS_ERR(clk)) { - kfree(gate); - kfree(div); - } - - return clk; -} - -/* ----------------------------------------------------------------------------- - * CPG Clock Data - */ - -/* - * MD EXTAL PLL0 PLL1 PLL3 - * 14 13 19 (MHz) *1 *1 - *--------------------------------------------------- - * 0 0 0 15 x 1 x172/2 x208/2 x106 - * 0 0 1 15 x 1 x172/2 x208/2 x88 - * 0 1 0 20 x 1 x130/2 x156/2 x80 - * 0 1 1 20 x 1 x130/2 x156/2 x66 - * 1 0 0 26 / 2 x200/2 x240/2 x122 - * 1 0 1 26 / 2 x200/2 x240/2 x102 - * 1 1 0 30 / 2 x172/2 x208/2 x106 - * 1 1 1 30 / 2 x172/2 x208/2 x88 - * - * *1 : Table 7.6 indicates VCO output (PLLx = VCO/2) - */ -#define CPG_PLL_CONFIG_INDEX(md) ((((md) & BIT(14)) >> 12) | \ - (((md) & BIT(13)) >> 12) | \ - (((md) & BIT(19)) >> 19)) -struct cpg_pll_config { - unsigned int extal_div; - unsigned int pll1_mult; - unsigned int pll3_mult; -}; - -static const struct cpg_pll_config cpg_pll_configs[8] __initconst = { - { 1, 208, 106 }, { 1, 208, 88 }, { 1, 156, 80 }, { 1, 156, 66 }, - { 2, 240, 122 }, { 2, 240, 102 }, { 2, 208, 106 }, { 2, 208, 88 }, -}; - -/* SDHI divisors */ -static const struct clk_div_table cpg_sdh_div_table[] = { - { 0, 2 }, { 1, 3 }, { 2, 4 }, { 3, 6 }, - { 4, 8 }, { 5, 12 }, { 6, 16 }, { 7, 18 }, - { 8, 24 }, { 10, 36 }, { 11, 48 }, { 0, 0 }, -}; - -static const struct clk_div_table cpg_sd01_div_table[] = { - { 4, 8 }, - { 5, 12 }, { 6, 16 }, { 7, 18 }, { 8, 24 }, - { 10, 36 }, { 11, 48 }, { 12, 10 }, { 0, 0 }, -}; - -/* ----------------------------------------------------------------------------- - * Initialization - */ - -static u32 cpg_mode __initdata; - -static struct clk * __init -rcar_gen2_cpg_register_clock(struct device_node *np, struct rcar_gen2_cpg *cpg, - const struct cpg_pll_config *config, - const char *name) -{ - const struct clk_div_table *table = NULL; - const char *parent_name; - unsigned int shift; - unsigned int mult = 1; - unsigned int div = 1; - - if (!strcmp(name, "main")) { - parent_name = of_clk_get_parent_name(np, 0); - div = config->extal_div; - } else if (!strcmp(name, "pll0")) { - /* PLL0 is a configurable multiplier clock. Register it as a - * fixed factor clock for now as there's no generic multiplier - * clock implementation and we currently have no need to change - * the multiplier value. - */ - u32 value = clk_readl(cpg->reg + CPG_PLL0CR); - parent_name = "main"; - mult = ((value >> 24) & ((1 << 7) - 1)) + 1; - } else if (!strcmp(name, "pll1")) { - parent_name = "main"; - mult = config->pll1_mult / 2; - } else if (!strcmp(name, "pll3")) { - parent_name = "main"; - mult = config->pll3_mult; - } else if (!strcmp(name, "lb")) { - parent_name = "pll1"; - div = cpg_mode & BIT(18) ? 36 : 24; - } else if (!strcmp(name, "qspi")) { - parent_name = "pll1_div2"; - div = (cpg_mode & (BIT(3) | BIT(2) | BIT(1))) == BIT(2) - ? 8 : 10; - } else if (!strcmp(name, "sdh")) { - parent_name = "pll1"; - table = cpg_sdh_div_table; - shift = 8; - } else if (!strcmp(name, "sd0")) { - parent_name = "pll1"; - table = cpg_sd01_div_table; - shift = 4; - } else if (!strcmp(name, "sd1")) { - parent_name = "pll1"; - table = cpg_sd01_div_table; - shift = 0; - } else if (!strcmp(name, "z")) { - return cpg_z_clk_register(cpg); - } else if (!strcmp(name, "rcan")) { - return cpg_rcan_clk_register(cpg, np); - } else if (!strcmp(name, "adsp")) { - return cpg_adsp_clk_register(cpg); - } else { - return ERR_PTR(-EINVAL); - } - - if (!table) - return clk_register_fixed_factor(NULL, name, parent_name, 0, - mult, div); - else - return clk_register_divider_table(NULL, name, parent_name, 0, - cpg->reg + CPG_SDCKCR, shift, - 4, 0, table, &cpg->lock); -} - -static void __init rcar_gen2_cpg_clocks_init(struct device_node *np) -{ - const struct cpg_pll_config *config; - struct rcar_gen2_cpg *cpg; - struct clk **clks; - unsigned int i; - int num_clks; - - num_clks = of_property_count_strings(np, "clock-output-names"); - if (num_clks < 0) { - pr_err("%s: failed to count clocks\n", __func__); - return; - } - - cpg = kzalloc(sizeof(*cpg), GFP_KERNEL); - clks = kzalloc(num_clks * sizeof(*clks), GFP_KERNEL); - if (cpg == NULL || clks == NULL) { - /* We're leaking memory on purpose, there's no point in cleaning - * up as the system won't boot anyway. - */ - pr_err("%s: failed to allocate cpg\n", __func__); - return; - } - - spin_lock_init(&cpg->lock); - - cpg->data.clks = clks; - cpg->data.clk_num = num_clks; - - cpg->reg = of_iomap(np, 0); - if (WARN_ON(cpg->reg == NULL)) - return; - - config = &cpg_pll_configs[CPG_PLL_CONFIG_INDEX(cpg_mode)]; - - for (i = 0; i < num_clks; ++i) { - const char *name; - struct clk *clk; - - of_property_read_string_index(np, "clock-output-names", i, - &name); - - clk = rcar_gen2_cpg_register_clock(np, cpg, config, name); - if (IS_ERR(clk)) - pr_err("%s: failed to register %s %s clock (%ld)\n", - __func__, np->name, name, PTR_ERR(clk)); - else - cpg->data.clks[i] = clk; - } - - of_clk_add_provider(np, of_clk_src_onecell_get, &cpg->data); - - cpg_mstp_add_clk_domain(np); -} -CLK_OF_DECLARE(rcar_gen2_cpg_clks, "renesas,rcar-gen2-cpg-clocks", - rcar_gen2_cpg_clocks_init); - -void __init rcar_gen2_clocks_init(u32 mode) -{ - cpg_mode = mode; - - of_clk_init(NULL); -} diff --git a/drivers/clk/shmobile/clk-rz.c b/drivers/clk/shmobile/clk-rz.c deleted file mode 100644 index 9766e3cb5..000000000 --- a/drivers/clk/shmobile/clk-rz.c +++ /dev/null @@ -1,106 +0,0 @@ -/* - * rz Core CPG Clocks - * - * Copyright (C) 2013 Ideas On Board SPRL - * Copyright (C) 2014 Wolfram Sang, Sang Engineering <wsa@sang-engineering.com> - * - * 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; version 2 of the License. - */ - -#include <linux/clk-provider.h> -#include <linux/clk/shmobile.h> -#include <linux/init.h> -#include <linux/kernel.h> -#include <linux/of.h> -#include <linux/of_address.h> -#include <linux/slab.h> - -struct rz_cpg { - struct clk_onecell_data data; - void __iomem *reg; -}; - -#define CPG_FRQCR 0x10 -#define CPG_FRQCR2 0x14 - -/* ----------------------------------------------------------------------------- - * Initialization - */ - -static struct clk * __init -rz_cpg_register_clock(struct device_node *np, struct rz_cpg *cpg, const char *name) -{ - u32 val; - unsigned mult; - static const unsigned frqcr_tab[4] = { 3, 2, 0, 1 }; - - if (strcmp(name, "pll") == 0) { - /* FIXME: cpg_mode should be read from GPIO. But no GPIO support yet */ - unsigned cpg_mode = 0; /* hardcoded to EXTAL for now */ - const char *parent_name = of_clk_get_parent_name(np, cpg_mode); - - mult = cpg_mode ? (32 / 4) : 30; - - return clk_register_fixed_factor(NULL, name, parent_name, 0, mult, 1); - } - - /* If mapping regs failed, skip non-pll clocks. System will boot anyhow */ - if (!cpg->reg) - return ERR_PTR(-ENXIO); - - /* FIXME:"i" and "g" are variable clocks with non-integer dividers (e.g. 2/3) - * and the constraint that always g <= i. To get the rz platform started, - * let them run at fixed current speed and implement the details later. - */ - if (strcmp(name, "i") == 0) - val = (clk_readl(cpg->reg + CPG_FRQCR) >> 8) & 3; - else if (strcmp(name, "g") == 0) - val = clk_readl(cpg->reg + CPG_FRQCR2) & 3; - else - return ERR_PTR(-EINVAL); - - mult = frqcr_tab[val]; - return clk_register_fixed_factor(NULL, name, "pll", 0, mult, 3); -} - -static void __init rz_cpg_clocks_init(struct device_node *np) -{ - struct rz_cpg *cpg; - struct clk **clks; - unsigned i; - int num_clks; - - num_clks = of_property_count_strings(np, "clock-output-names"); - if (WARN(num_clks <= 0, "can't count CPG clocks\n")) - return; - - cpg = kzalloc(sizeof(*cpg), GFP_KERNEL); - clks = kzalloc(num_clks * sizeof(*clks), GFP_KERNEL); - BUG_ON(!cpg || !clks); - - cpg->data.clks = clks; - cpg->data.clk_num = num_clks; - - cpg->reg = of_iomap(np, 0); - - for (i = 0; i < num_clks; ++i) { - const char *name; - struct clk *clk; - - of_property_read_string_index(np, "clock-output-names", i, &name); - - clk = rz_cpg_register_clock(np, cpg, name); - if (IS_ERR(clk)) - pr_err("%s: failed to register %s %s clock (%ld)\n", - __func__, np->name, name, PTR_ERR(clk)); - else - cpg->data.clks[i] = clk; - } - - of_clk_add_provider(np, of_clk_src_onecell_get, &cpg->data); - - cpg_mstp_add_clk_domain(np); -} -CLK_OF_DECLARE(rz_cpg_clks, "renesas,rz-cpg-clocks", rz_cpg_clocks_init); diff --git a/drivers/clk/shmobile/clk-sh73a0.c b/drivers/clk/shmobile/clk-sh73a0.c deleted file mode 100644 index 8966f8bbf..000000000 --- a/drivers/clk/shmobile/clk-sh73a0.c +++ /dev/null @@ -1,218 +0,0 @@ -/* - * sh73a0 Core CPG Clocks - * - * Copyright (C) 2014 Ulrich Hecht - * - * 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; version 2 of the License. - */ - -#include <linux/clk-provider.h> -#include <linux/clk/shmobile.h> -#include <linux/init.h> -#include <linux/kernel.h> -#include <linux/of.h> -#include <linux/of_address.h> -#include <linux/slab.h> -#include <linux/spinlock.h> - -struct sh73a0_cpg { - struct clk_onecell_data data; - spinlock_t lock; - void __iomem *reg; -}; - -#define CPG_FRQCRA 0x00 -#define CPG_FRQCRB 0x04 -#define CPG_SD0CKCR 0x74 -#define CPG_SD1CKCR 0x78 -#define CPG_SD2CKCR 0x7c -#define CPG_PLLECR 0xd0 -#define CPG_PLL0CR 0xd8 -#define CPG_PLL1CR 0x28 -#define CPG_PLL2CR 0x2c -#define CPG_PLL3CR 0xdc -#define CPG_CKSCR 0xc0 -#define CPG_DSI0PHYCR 0x6c -#define CPG_DSI1PHYCR 0x70 - -#define CLK_ENABLE_ON_INIT BIT(0) - -struct div4_clk { - const char *name; - const char *parent; - unsigned int reg; - unsigned int shift; -}; - -static struct div4_clk div4_clks[] = { - { "zg", "pll0", CPG_FRQCRA, 16 }, - { "m3", "pll1", CPG_FRQCRA, 12 }, - { "b", "pll1", CPG_FRQCRA, 8 }, - { "m1", "pll1", CPG_FRQCRA, 4 }, - { "m2", "pll1", CPG_FRQCRA, 0 }, - { "zx", "pll1", CPG_FRQCRB, 12 }, - { "hp", "pll1", CPG_FRQCRB, 4 }, - { NULL, NULL, 0, 0 }, -}; - -static const struct clk_div_table div4_div_table[] = { - { 0, 2 }, { 1, 3 }, { 2, 4 }, { 3, 6 }, { 4, 8 }, { 5, 12 }, - { 6, 16 }, { 7, 18 }, { 8, 24 }, { 10, 36 }, { 11, 48 }, - { 12, 7 }, { 0, 0 } -}; - -static const struct clk_div_table z_div_table[] = { - /* ZSEL == 0 */ - { 0, 1 }, { 1, 1 }, { 2, 1 }, { 3, 1 }, { 4, 1 }, { 5, 1 }, - { 6, 1 }, { 7, 1 }, { 8, 1 }, { 9, 1 }, { 10, 1 }, { 11, 1 }, - { 12, 1 }, { 13, 1 }, { 14, 1 }, { 15, 1 }, - /* ZSEL == 1 */ - { 16, 2 }, { 17, 3 }, { 18, 4 }, { 19, 6 }, { 20, 8 }, { 21, 12 }, - { 22, 16 }, { 24, 24 }, { 27, 48 }, { 0, 0 } -}; - -static struct clk * __init -sh73a0_cpg_register_clock(struct device_node *np, struct sh73a0_cpg *cpg, - const char *name) -{ - const struct clk_div_table *table = NULL; - unsigned int shift, reg, width; - const char *parent_name; - unsigned int mult = 1; - unsigned int div = 1; - - if (!strcmp(name, "main")) { - /* extal1, extal1_div2, extal2, extal2_div2 */ - u32 parent_idx = (clk_readl(cpg->reg + CPG_CKSCR) >> 28) & 3; - - parent_name = of_clk_get_parent_name(np, parent_idx >> 1); - div = (parent_idx & 1) + 1; - } else if (!strncmp(name, "pll", 3)) { - void __iomem *enable_reg = cpg->reg; - u32 enable_bit = name[3] - '0'; - - parent_name = "main"; - switch (enable_bit) { - case 0: - enable_reg += CPG_PLL0CR; - break; - case 1: - enable_reg += CPG_PLL1CR; - break; - case 2: - enable_reg += CPG_PLL2CR; - break; - case 3: - enable_reg += CPG_PLL3CR; - break; - default: - return ERR_PTR(-EINVAL); - } - if (clk_readl(cpg->reg + CPG_PLLECR) & BIT(enable_bit)) { - mult = ((clk_readl(enable_reg) >> 24) & 0x3f) + 1; - /* handle CFG bit for PLL1 and PLL2 */ - if (enable_bit == 1 || enable_bit == 2) - if (clk_readl(enable_reg) & BIT(20)) - mult *= 2; - } - } else if (!strcmp(name, "dsi0phy") || !strcmp(name, "dsi1phy")) { - u32 phy_no = name[3] - '0'; - void __iomem *dsi_reg = cpg->reg + - (phy_no ? CPG_DSI1PHYCR : CPG_DSI0PHYCR); - - parent_name = phy_no ? "dsi1pck" : "dsi0pck"; - mult = __raw_readl(dsi_reg); - if (!(mult & 0x8000)) - mult = 1; - else - mult = (mult & 0x3f) + 1; - } else if (!strcmp(name, "z")) { - parent_name = "pll0"; - table = z_div_table; - reg = CPG_FRQCRB; - shift = 24; - width = 5; - } else { - struct div4_clk *c; - - for (c = div4_clks; c->name; c++) { - if (!strcmp(name, c->name)) { - parent_name = c->parent; - table = div4_div_table; - reg = c->reg; - shift = c->shift; - width = 4; - break; - } - } - if (!c->name) - return ERR_PTR(-EINVAL); - } - - if (!table) { - return clk_register_fixed_factor(NULL, name, parent_name, 0, - mult, div); - } else { - return clk_register_divider_table(NULL, name, parent_name, 0, - cpg->reg + reg, shift, width, 0, - table, &cpg->lock); - } -} - -static void __init sh73a0_cpg_clocks_init(struct device_node *np) -{ - struct sh73a0_cpg *cpg; - struct clk **clks; - unsigned int i; - int num_clks; - - num_clks = of_property_count_strings(np, "clock-output-names"); - if (num_clks < 0) { - pr_err("%s: failed to count clocks\n", __func__); - return; - } - - cpg = kzalloc(sizeof(*cpg), GFP_KERNEL); - clks = kcalloc(num_clks, sizeof(*clks), GFP_KERNEL); - if (cpg == NULL || clks == NULL) { - /* We're leaking memory on purpose, there's no point in cleaning - * up as the system won't boot anyway. - */ - return; - } - - spin_lock_init(&cpg->lock); - - cpg->data.clks = clks; - cpg->data.clk_num = num_clks; - - cpg->reg = of_iomap(np, 0); - if (WARN_ON(cpg->reg == NULL)) - return; - - /* Set SDHI clocks to a known state */ - clk_writel(0x108, cpg->reg + CPG_SD0CKCR); - clk_writel(0x108, cpg->reg + CPG_SD1CKCR); - clk_writel(0x108, cpg->reg + CPG_SD2CKCR); - - for (i = 0; i < num_clks; ++i) { - const char *name; - struct clk *clk; - - of_property_read_string_index(np, "clock-output-names", i, - &name); - - clk = sh73a0_cpg_register_clock(np, cpg, name); - if (IS_ERR(clk)) - pr_err("%s: failed to register %s %s clock (%ld)\n", - __func__, np->name, name, PTR_ERR(clk)); - else - cpg->data.clks[i] = clk; - } - - of_clk_add_provider(np, of_clk_src_onecell_get, &cpg->data); -} -CLK_OF_DECLARE(sh73a0_cpg_clks, "renesas,sh73a0-cpg-clocks", - sh73a0_cpg_clocks_init); diff --git a/drivers/clk/shmobile/r8a7795-cpg-mssr.c b/drivers/clk/shmobile/r8a7795-cpg-mssr.c deleted file mode 100644 index 13e994772..000000000 --- a/drivers/clk/shmobile/r8a7795-cpg-mssr.c +++ /dev/null @@ -1,383 +0,0 @@ -/* - * r8a7795 Clock Pulse Generator / Module Standby and Software Reset - * - * Copyright (C) 2015 Glider bvba - * - * Based on clk-rcar-gen3.c - * - * Copyright (C) 2015 Renesas Electronics Corp. - * - * 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; version 2 of the License. - */ - -#include <linux/bug.h> -#include <linux/clk-provider.h> -#include <linux/device.h> -#include <linux/err.h> -#include <linux/init.h> -#include <linux/io.h> -#include <linux/kernel.h> -#include <linux/of.h> - -#include <dt-bindings/clock/r8a7795-cpg-mssr.h> - -#include "renesas-cpg-mssr.h" - - -enum clk_ids { - /* Core Clock Outputs exported to DT */ - LAST_DT_CORE_CLK = R8A7795_CLK_OSC, - - /* External Input Clocks */ - CLK_EXTAL, - CLK_EXTALR, - - /* Internal Core Clocks */ - CLK_MAIN, - CLK_PLL0, - CLK_PLL1, - CLK_PLL2, - CLK_PLL3, - CLK_PLL4, - CLK_PLL1_DIV2, - CLK_PLL1_DIV4, - CLK_S0, - CLK_S1, - CLK_S2, - CLK_S3, - CLK_SDSRC, - CLK_SSPSRC, - - /* Module Clocks */ - MOD_CLK_BASE -}; - -enum r8a7795_clk_types { - CLK_TYPE_GEN3_MAIN = CLK_TYPE_CUSTOM, - CLK_TYPE_GEN3_PLL0, - CLK_TYPE_GEN3_PLL1, - CLK_TYPE_GEN3_PLL2, - CLK_TYPE_GEN3_PLL3, - CLK_TYPE_GEN3_PLL4, -}; - -static const struct cpg_core_clk r8a7795_core_clks[] __initconst = { - /* External Clock Inputs */ - DEF_INPUT("extal", CLK_EXTAL), - DEF_INPUT("extalr", CLK_EXTALR), - - /* Internal Core Clocks */ - DEF_BASE(".main", CLK_MAIN, CLK_TYPE_GEN3_MAIN, CLK_EXTAL), - DEF_BASE(".pll0", CLK_PLL0, CLK_TYPE_GEN3_PLL0, CLK_MAIN), - DEF_BASE(".pll1", CLK_PLL1, CLK_TYPE_GEN3_PLL1, CLK_MAIN), - DEF_BASE(".pll2", CLK_PLL2, CLK_TYPE_GEN3_PLL2, CLK_MAIN), - DEF_BASE(".pll3", CLK_PLL3, CLK_TYPE_GEN3_PLL3, CLK_MAIN), - DEF_BASE(".pll4", CLK_PLL4, CLK_TYPE_GEN3_PLL4, CLK_MAIN), - - DEF_FIXED(".pll1_div2", CLK_PLL1_DIV2, CLK_PLL1, 2, 1), - DEF_FIXED(".pll1_div4", CLK_PLL1_DIV4, CLK_PLL1_DIV2, 2, 1), - DEF_FIXED(".s0", CLK_S0, CLK_PLL1_DIV2, 2, 1), - DEF_FIXED(".s1", CLK_S1, CLK_PLL1_DIV2, 3, 1), - DEF_FIXED(".s2", CLK_S2, CLK_PLL1_DIV2, 4, 1), - DEF_FIXED(".s3", CLK_S3, CLK_PLL1_DIV2, 6, 1), - - /* Core Clock Outputs */ - DEF_FIXED("ztr", R8A7795_CLK_ZTR, CLK_PLL1_DIV2, 6, 1), - DEF_FIXED("ztrd2", R8A7795_CLK_ZTRD2, CLK_PLL1_DIV2, 12, 1), - DEF_FIXED("zt", R8A7795_CLK_ZT, CLK_PLL1_DIV2, 4, 1), - DEF_FIXED("zx", R8A7795_CLK_ZX, CLK_PLL1_DIV2, 2, 1), - DEF_FIXED("s0d1", R8A7795_CLK_S0D1, CLK_S0, 1, 1), - DEF_FIXED("s0d4", R8A7795_CLK_S0D4, CLK_S0, 4, 1), - DEF_FIXED("s1d1", R8A7795_CLK_S1D1, CLK_S1, 1, 1), - DEF_FIXED("s1d2", R8A7795_CLK_S1D2, CLK_S1, 2, 1), - DEF_FIXED("s1d4", R8A7795_CLK_S1D4, CLK_S1, 4, 1), - DEF_FIXED("s2d1", R8A7795_CLK_S2D1, CLK_S2, 1, 1), - DEF_FIXED("s2d2", R8A7795_CLK_S2D2, CLK_S2, 2, 1), - DEF_FIXED("s2d4", R8A7795_CLK_S2D4, CLK_S2, 4, 1), - DEF_FIXED("s3d1", R8A7795_CLK_S3D1, CLK_S3, 1, 1), - DEF_FIXED("s3d2", R8A7795_CLK_S3D2, CLK_S3, 2, 1), - DEF_FIXED("s3d4", R8A7795_CLK_S3D4, CLK_S3, 4, 1), - DEF_FIXED("cl", R8A7795_CLK_CL, CLK_PLL1_DIV2, 48, 1), - DEF_FIXED("cp", R8A7795_CLK_CP, CLK_EXTAL, 2, 1), - - DEF_DIV6P1("mso", R8A7795_CLK_MSO, CLK_PLL1_DIV4, 0x014), - DEF_DIV6P1("hdmi", R8A7795_CLK_HDMI, CLK_PLL1_DIV2, 0x250), -}; - -static const struct mssr_mod_clk r8a7795_mod_clks[] __initconst = { - DEF_MOD("scif5", 202, R8A7795_CLK_S3D4), - DEF_MOD("scif4", 203, R8A7795_CLK_S3D4), - DEF_MOD("scif3", 204, R8A7795_CLK_S3D4), - DEF_MOD("scif1", 206, R8A7795_CLK_S3D4), - DEF_MOD("scif0", 207, R8A7795_CLK_S3D4), - DEF_MOD("msiof3", 208, R8A7795_CLK_MSO), - DEF_MOD("msiof2", 209, R8A7795_CLK_MSO), - DEF_MOD("msiof1", 210, R8A7795_CLK_MSO), - DEF_MOD("msiof0", 211, R8A7795_CLK_MSO), - DEF_MOD("sys-dmac2", 217, R8A7795_CLK_S3D1), - DEF_MOD("sys-dmac1", 218, R8A7795_CLK_S3D1), - DEF_MOD("sys-dmac0", 219, R8A7795_CLK_S3D1), - DEF_MOD("scif2", 310, R8A7795_CLK_S3D4), - DEF_MOD("pcie1", 318, R8A7795_CLK_S3D1), - DEF_MOD("pcie0", 319, R8A7795_CLK_S3D1), - DEF_MOD("intc-ap", 408, R8A7795_CLK_S3D1), - DEF_MOD("audmac0", 502, R8A7795_CLK_S3D4), - DEF_MOD("audmac1", 501, R8A7795_CLK_S3D4), - DEF_MOD("hscif4", 516, R8A7795_CLK_S3D1), - DEF_MOD("hscif3", 517, R8A7795_CLK_S3D1), - DEF_MOD("hscif2", 518, R8A7795_CLK_S3D1), - DEF_MOD("hscif1", 519, R8A7795_CLK_S3D1), - DEF_MOD("hscif0", 520, R8A7795_CLK_S3D1), - DEF_MOD("vspd3", 620, R8A7795_CLK_S2D1), - DEF_MOD("vspd2", 621, R8A7795_CLK_S2D1), - DEF_MOD("vspd1", 622, R8A7795_CLK_S2D1), - DEF_MOD("vspd0", 623, R8A7795_CLK_S2D1), - DEF_MOD("vspbc", 624, R8A7795_CLK_S2D1), - DEF_MOD("vspbd", 626, R8A7795_CLK_S2D1), - DEF_MOD("vspi2", 629, R8A7795_CLK_S2D1), - DEF_MOD("vspi1", 630, R8A7795_CLK_S2D1), - DEF_MOD("vspi0", 631, R8A7795_CLK_S2D1), - DEF_MOD("ehci2", 701, R8A7795_CLK_S3D4), - DEF_MOD("ehci1", 702, R8A7795_CLK_S3D4), - DEF_MOD("ehci0", 703, R8A7795_CLK_S3D4), - DEF_MOD("hsusb", 704, R8A7795_CLK_S3D4), - DEF_MOD("du3", 721, R8A7795_CLK_S2D1), - DEF_MOD("du2", 722, R8A7795_CLK_S2D1), - DEF_MOD("du1", 723, R8A7795_CLK_S2D1), - DEF_MOD("du0", 724, R8A7795_CLK_S2D1), - DEF_MOD("hdmi1", 728, R8A7795_CLK_HDMI), - DEF_MOD("hdmi0", 729, R8A7795_CLK_HDMI), - DEF_MOD("etheravb", 812, R8A7795_CLK_S3D2), - DEF_MOD("sata0", 815, R8A7795_CLK_S3D2), - DEF_MOD("gpio7", 905, R8A7795_CLK_CP), - DEF_MOD("gpio6", 906, R8A7795_CLK_CP), - DEF_MOD("gpio5", 907, R8A7795_CLK_CP), - DEF_MOD("gpio4", 908, R8A7795_CLK_CP), - DEF_MOD("gpio3", 909, R8A7795_CLK_CP), - DEF_MOD("gpio2", 910, R8A7795_CLK_CP), - DEF_MOD("gpio1", 911, R8A7795_CLK_CP), - DEF_MOD("gpio0", 912, R8A7795_CLK_CP), - DEF_MOD("i2c6", 918, R8A7795_CLK_S3D2), - DEF_MOD("i2c5", 919, R8A7795_CLK_S3D2), - DEF_MOD("i2c4", 927, R8A7795_CLK_S3D2), - DEF_MOD("i2c3", 928, R8A7795_CLK_S3D2), - DEF_MOD("i2c2", 929, R8A7795_CLK_S3D2), - DEF_MOD("i2c1", 930, R8A7795_CLK_S3D2), - DEF_MOD("i2c0", 931, R8A7795_CLK_S3D2), - DEF_MOD("ssi-all", 1005, R8A7795_CLK_S3D4), - DEF_MOD("ssi9", 1006, MOD_CLK_ID(1005)), - DEF_MOD("ssi8", 1007, MOD_CLK_ID(1005)), - DEF_MOD("ssi7", 1008, MOD_CLK_ID(1005)), - DEF_MOD("ssi6", 1009, MOD_CLK_ID(1005)), - DEF_MOD("ssi5", 1010, MOD_CLK_ID(1005)), - DEF_MOD("ssi4", 1011, MOD_CLK_ID(1005)), - DEF_MOD("ssi3", 1012, MOD_CLK_ID(1005)), - DEF_MOD("ssi2", 1013, MOD_CLK_ID(1005)), - DEF_MOD("ssi1", 1014, MOD_CLK_ID(1005)), - DEF_MOD("ssi0", 1015, MOD_CLK_ID(1005)), - DEF_MOD("scu-all", 1017, R8A7795_CLK_S3D4), - DEF_MOD("scu-dvc1", 1018, MOD_CLK_ID(1017)), - DEF_MOD("scu-dvc0", 1019, MOD_CLK_ID(1017)), - DEF_MOD("scu-ctu1-mix1", 1020, MOD_CLK_ID(1017)), - DEF_MOD("scu-ctu0-mix0", 1021, MOD_CLK_ID(1017)), - DEF_MOD("scu-src9", 1022, MOD_CLK_ID(1017)), - DEF_MOD("scu-src8", 1023, MOD_CLK_ID(1017)), - DEF_MOD("scu-src7", 1024, MOD_CLK_ID(1017)), - DEF_MOD("scu-src6", 1025, MOD_CLK_ID(1017)), - DEF_MOD("scu-src5", 1026, MOD_CLK_ID(1017)), - DEF_MOD("scu-src4", 1027, MOD_CLK_ID(1017)), - DEF_MOD("scu-src3", 1028, MOD_CLK_ID(1017)), - DEF_MOD("scu-src2", 1029, MOD_CLK_ID(1017)), - DEF_MOD("scu-src1", 1030, MOD_CLK_ID(1017)), - DEF_MOD("scu-src0", 1031, MOD_CLK_ID(1017)), -}; - -static const unsigned int r8a7795_crit_mod_clks[] __initconst = { - MOD_CLK_ID(408), /* INTC-AP (GIC) */ -}; - - -#define CPG_PLL0CR 0x00d8 -#define CPG_PLL2CR 0x002c -#define CPG_PLL4CR 0x01f4 - -/* - * CPG Clock Data - */ - -/* - * MD EXTAL PLL0 PLL1 PLL2 PLL3 PLL4 - * 14 13 19 17 (MHz) - *------------------------------------------------------------------- - * 0 0 0 0 16.66 x 1 x180 x192 x144 x192 x144 - * 0 0 0 1 16.66 x 1 x180 x192 x144 x128 x144 - * 0 0 1 0 Prohibited setting - * 0 0 1 1 16.66 x 1 x180 x192 x144 x192 x144 - * 0 1 0 0 20 x 1 x150 x160 x120 x160 x120 - * 0 1 0 1 20 x 1 x150 x160 x120 x106 x120 - * 0 1 1 0 Prohibited setting - * 0 1 1 1 20 x 1 x150 x160 x120 x160 x120 - * 1 0 0 0 25 x 1 x120 x128 x96 x128 x96 - * 1 0 0 1 25 x 1 x120 x128 x96 x84 x96 - * 1 0 1 0 Prohibited setting - * 1 0 1 1 25 x 1 x120 x128 x96 x128 x96 - * 1 1 0 0 33.33 / 2 x180 x192 x144 x192 x144 - * 1 1 0 1 33.33 / 2 x180 x192 x144 x128 x144 - * 1 1 1 0 Prohibited setting - * 1 1 1 1 33.33 / 2 x180 x192 x144 x192 x144 - */ -#define CPG_PLL_CONFIG_INDEX(md) ((((md) & BIT(14)) >> 11) | \ - (((md) & BIT(13)) >> 11) | \ - (((md) & BIT(19)) >> 18) | \ - (((md) & BIT(17)) >> 17)) - -struct cpg_pll_config { - unsigned int extal_div; - unsigned int pll1_mult; - unsigned int pll3_mult; -}; - -static const struct cpg_pll_config cpg_pll_configs[16] __initconst = { - /* EXTAL div PLL1 mult PLL3 mult */ - { 1, 192, 192, }, - { 1, 192, 128, }, - { 0, /* Prohibited setting */ }, - { 1, 192, 192, }, - { 1, 160, 160, }, - { 1, 160, 106, }, - { 0, /* Prohibited setting */ }, - { 1, 160, 160, }, - { 1, 128, 128, }, - { 1, 128, 84, }, - { 0, /* Prohibited setting */ }, - { 1, 128, 128, }, - { 2, 192, 192, }, - { 2, 192, 128, }, - { 0, /* Prohibited setting */ }, - { 2, 192, 192, }, -}; - -static const struct cpg_pll_config *cpg_pll_config __initdata; - -static -struct clk * __init r8a7795_cpg_clk_register(struct device *dev, - const struct cpg_core_clk *core, - const struct cpg_mssr_info *info, - struct clk **clks, - void __iomem *base) -{ - const struct clk *parent; - unsigned int mult = 1; - unsigned int div = 1; - u32 value; - - parent = clks[core->parent]; - if (IS_ERR(parent)) - return ERR_CAST(parent); - - switch (core->type) { - case CLK_TYPE_GEN3_MAIN: - div = cpg_pll_config->extal_div; - break; - - case CLK_TYPE_GEN3_PLL0: - /* - * PLL0 is a configurable multiplier clock. Register it as a - * fixed factor clock for now as there's no generic multiplier - * clock implementation and we currently have no need to change - * the multiplier value. - */ - value = readl(base + CPG_PLL0CR); - mult = (((value >> 24) & 0x7f) + 1) * 2; - break; - - case CLK_TYPE_GEN3_PLL1: - mult = cpg_pll_config->pll1_mult; - break; - - case CLK_TYPE_GEN3_PLL2: - /* - * PLL2 is a configurable multiplier clock. Register it as a - * fixed factor clock for now as there's no generic multiplier - * clock implementation and we currently have no need to change - * the multiplier value. - */ - value = readl(base + CPG_PLL2CR); - mult = (((value >> 24) & 0x7f) + 1) * 2; - break; - - case CLK_TYPE_GEN3_PLL3: - mult = cpg_pll_config->pll3_mult; - break; - - case CLK_TYPE_GEN3_PLL4: - /* - * PLL4 is a configurable multiplier clock. Register it as a - * fixed factor clock for now as there's no generic multiplier - * clock implementation and we currently have no need to change - * the multiplier value. - */ - value = readl(base + CPG_PLL4CR); - mult = (((value >> 24) & 0x7f) + 1) * 2; - break; - - default: - return ERR_PTR(-EINVAL); - } - - return clk_register_fixed_factor(NULL, core->name, - __clk_get_name(parent), 0, mult, div); -} - -/* - * Reset register definitions. - */ -#define MODEMR 0xe6160060 - -static u32 rcar_gen3_read_mode_pins(void) -{ - void __iomem *modemr = ioremap_nocache(MODEMR, 4); - u32 mode; - - BUG_ON(!modemr); - mode = ioread32(modemr); - iounmap(modemr); - - return mode; -} - -static int __init r8a7795_cpg_mssr_init(struct device *dev) -{ - u32 cpg_mode = rcar_gen3_read_mode_pins(); - - cpg_pll_config = &cpg_pll_configs[CPG_PLL_CONFIG_INDEX(cpg_mode)]; - if (!cpg_pll_config->extal_div) { - dev_err(dev, "Prohibited setting (cpg_mode=0x%x)\n", cpg_mode); - return -EINVAL; - } - - return 0; -} - -const struct cpg_mssr_info r8a7795_cpg_mssr_info __initconst = { - /* Core Clocks */ - .core_clks = r8a7795_core_clks, - .num_core_clks = ARRAY_SIZE(r8a7795_core_clks), - .last_dt_core_clk = LAST_DT_CORE_CLK, - .num_total_core_clks = MOD_CLK_BASE, - - /* Module Clocks */ - .mod_clks = r8a7795_mod_clks, - .num_mod_clks = ARRAY_SIZE(r8a7795_mod_clks), - .num_hw_mod_clks = 12 * 32, - - /* Critical Module Clocks */ - .crit_mod_clks = r8a7795_crit_mod_clks, - .num_crit_mod_clks = ARRAY_SIZE(r8a7795_crit_mod_clks), - - /* Callbacks */ - .init = r8a7795_cpg_mssr_init, - .cpg_clk_register = r8a7795_cpg_clk_register, -}; diff --git a/drivers/clk/shmobile/renesas-cpg-mssr.c b/drivers/clk/shmobile/renesas-cpg-mssr.c deleted file mode 100644 index 9a4d88816..000000000 --- a/drivers/clk/shmobile/renesas-cpg-mssr.c +++ /dev/null @@ -1,596 +0,0 @@ -/* - * Renesas Clock Pulse Generator / Module Standby and Software Reset - * - * Copyright (C) 2015 Glider bvba - * - * Based on clk-mstp.c, clk-rcar-gen2.c, and clk-rcar-gen3.c - * - * Copyright (C) 2013 Ideas On Board SPRL - * Copyright (C) 2015 Renesas Electronics Corp. - * - * 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; version 2 of the License. - */ - -#include <linux/clk.h> -#include <linux/clk-provider.h> -#include <linux/device.h> -#include <linux/init.h> -#include <linux/mod_devicetable.h> -#include <linux/module.h> -#include <linux/of_address.h> -#include <linux/of_device.h> -#include <linux/platform_device.h> -#include <linux/pm_clock.h> -#include <linux/pm_domain.h> -#include <linux/slab.h> - -#include <dt-bindings/clock/renesas-cpg-mssr.h> - -#include "renesas-cpg-mssr.h" -#include "clk-div6.h" - -#ifdef DEBUG -#define WARN_DEBUG(x) do { } while (0) -#else -#define WARN_DEBUG(x) WARN_ON(x) -#endif - - -/* - * Module Standby and Software Reset register offets. - * - * If the registers exist, these are valid for SH-Mobile, R-Mobile, - * R-Car Gen 2, and R-Car Gen 3. - * These are NOT valid for R-Car Gen1 and RZ/A1! - */ - -/* - * Module Stop Status Register offsets - */ - -static const u16 mstpsr[] = { - 0x030, 0x038, 0x040, 0x048, 0x04C, 0x03C, 0x1C0, 0x1C4, - 0x9A0, 0x9A4, 0x9A8, 0x9AC, -}; - -#define MSTPSR(i) mstpsr[i] - - -/* - * System Module Stop Control Register offsets - */ - -static const u16 smstpcr[] = { - 0x130, 0x134, 0x138, 0x13C, 0x140, 0x144, 0x148, 0x14C, - 0x990, 0x994, 0x998, 0x99C, -}; - -#define SMSTPCR(i) smstpcr[i] - - -/* - * Software Reset Register offsets - */ - -static const u16 srcr[] = { - 0x0A0, 0x0A8, 0x0B0, 0x0B8, 0x0BC, 0x0C4, 0x1C8, 0x1CC, - 0x920, 0x924, 0x928, 0x92C, -}; - -#define SRCR(i) srcr[i] - - -/* Realtime Module Stop Control Register offsets */ -#define RMSTPCR(i) (smstpcr[i] - 0x20) - -/* Modem Module Stop Control Register offsets (r8a73a4) */ -#define MMSTPCR(i) (smstpcr[i] + 0x20) - -/* Software Reset Clearing Register offsets */ -#define SRSTCLR(i) (0x940 + (i) * 4) - - -/** - * Clock Pulse Generator / Module Standby and Software Reset Private Data - * - * @dev: CPG/MSSR device - * @base: CPG/MSSR register block base address - * @mstp_lock: protects writes to SMSTPCR - * @clks: Array containing all Core and Module Clocks - * @num_core_clks: Number of Core Clocks in clks[] - * @num_mod_clks: Number of Module Clocks in clks[] - * @last_dt_core_clk: ID of the last Core Clock exported to DT - */ -struct cpg_mssr_priv { - struct device *dev; - void __iomem *base; - spinlock_t mstp_lock; - - struct clk **clks; - unsigned int num_core_clks; - unsigned int num_mod_clks; - unsigned int last_dt_core_clk; -}; - - -/** - * struct mstp_clock - MSTP gating clock - * @hw: handle between common and hardware-specific interfaces - * @index: MSTP clock number - * @priv: CPG/MSSR private data - */ -struct mstp_clock { - struct clk_hw hw; - u32 index; - struct cpg_mssr_priv *priv; -}; - -#define to_mstp_clock(_hw) container_of(_hw, struct mstp_clock, hw) - -static int cpg_mstp_clock_endisable(struct clk_hw *hw, bool enable) -{ - struct mstp_clock *clock = to_mstp_clock(hw); - struct cpg_mssr_priv *priv = clock->priv; - unsigned int reg = clock->index / 32; - unsigned int bit = clock->index % 32; - struct device *dev = priv->dev; - u32 bitmask = BIT(bit); - unsigned long flags; - unsigned int i; - u32 value; - - dev_dbg(dev, "MSTP %u%02u/%pC %s\n", reg, bit, hw->clk, - enable ? "ON" : "OFF"); - spin_lock_irqsave(&priv->mstp_lock, flags); - - value = clk_readl(priv->base + SMSTPCR(reg)); - if (enable) - value &= ~bitmask; - else - value |= bitmask; - clk_writel(value, priv->base + SMSTPCR(reg)); - - spin_unlock_irqrestore(&priv->mstp_lock, flags); - - if (!enable) - return 0; - - for (i = 1000; i > 0; --i) { - if (!(clk_readl(priv->base + MSTPSR(reg)) & - bitmask)) - break; - cpu_relax(); - } - - if (!i) { - dev_err(dev, "Failed to enable SMSTP %p[%d]\n", - priv->base + SMSTPCR(reg), bit); - return -ETIMEDOUT; - } - - return 0; -} - -static int cpg_mstp_clock_enable(struct clk_hw *hw) -{ - return cpg_mstp_clock_endisable(hw, true); -} - -static void cpg_mstp_clock_disable(struct clk_hw *hw) -{ - cpg_mstp_clock_endisable(hw, false); -} - -static int cpg_mstp_clock_is_enabled(struct clk_hw *hw) -{ - struct mstp_clock *clock = to_mstp_clock(hw); - struct cpg_mssr_priv *priv = clock->priv; - u32 value; - - value = clk_readl(priv->base + MSTPSR(clock->index / 32)); - - return !(value & BIT(clock->index % 32)); -} - -static const struct clk_ops cpg_mstp_clock_ops = { - .enable = cpg_mstp_clock_enable, - .disable = cpg_mstp_clock_disable, - .is_enabled = cpg_mstp_clock_is_enabled, -}; - -static -struct clk *cpg_mssr_clk_src_twocell_get(struct of_phandle_args *clkspec, - void *data) -{ - unsigned int clkidx = clkspec->args[1]; - struct cpg_mssr_priv *priv = data; - struct device *dev = priv->dev; - unsigned int idx; - const char *type; - struct clk *clk; - - switch (clkspec->args[0]) { - case CPG_CORE: - type = "core"; - if (clkidx > priv->last_dt_core_clk) { - dev_err(dev, "Invalid %s clock index %u\n", type, - clkidx); - return ERR_PTR(-EINVAL); - } - clk = priv->clks[clkidx]; - break; - - case CPG_MOD: - type = "module"; - idx = MOD_CLK_PACK(clkidx); - if (clkidx % 100 > 31 || idx >= priv->num_mod_clks) { - dev_err(dev, "Invalid %s clock index %u\n", type, - clkidx); - return ERR_PTR(-EINVAL); - } - clk = priv->clks[priv->num_core_clks + idx]; - break; - - default: - dev_err(dev, "Invalid CPG clock type %u\n", clkspec->args[0]); - return ERR_PTR(-EINVAL); - } - - if (IS_ERR(clk)) - dev_err(dev, "Cannot get %s clock %u: %ld", type, clkidx, - PTR_ERR(clk)); - else - dev_dbg(dev, "clock (%u, %u) is %pC at %pCr Hz\n", - clkspec->args[0], clkspec->args[1], clk, clk); - return clk; -} - -static void __init cpg_mssr_register_core_clk(const struct cpg_core_clk *core, - const struct cpg_mssr_info *info, - struct cpg_mssr_priv *priv) -{ - struct clk *clk = NULL, *parent; - struct device *dev = priv->dev; - unsigned int id = core->id; - const char *parent_name; - - WARN_DEBUG(id >= priv->num_core_clks); - WARN_DEBUG(PTR_ERR(priv->clks[id]) != -ENOENT); - - switch (core->type) { - case CLK_TYPE_IN: - clk = of_clk_get_by_name(priv->dev->of_node, core->name); - break; - - case CLK_TYPE_FF: - case CLK_TYPE_DIV6P1: - WARN_DEBUG(core->parent >= priv->num_core_clks); - parent = priv->clks[core->parent]; - if (IS_ERR(parent)) { - clk = parent; - goto fail; - } - - parent_name = __clk_get_name(parent); - if (core->type == CLK_TYPE_FF) { - clk = clk_register_fixed_factor(NULL, core->name, - parent_name, 0, - core->mult, core->div); - } else { - clk = cpg_div6_register(core->name, 1, &parent_name, - priv->base + core->offset); - } - break; - - default: - if (info->cpg_clk_register) - clk = info->cpg_clk_register(dev, core, info, - priv->clks, priv->base); - else - dev_err(dev, "%s has unsupported core clock type %u\n", - core->name, core->type); - break; - } - - if (IS_ERR_OR_NULL(clk)) - goto fail; - - dev_dbg(dev, "Core clock %pC at %pCr Hz\n", clk, clk); - priv->clks[id] = clk; - return; - -fail: - dev_err(dev, "Failed to register %s clock %s: %ld\n", "core,", - core->name, PTR_ERR(clk)); -} - -static void __init cpg_mssr_register_mod_clk(const struct mssr_mod_clk *mod, - const struct cpg_mssr_info *info, - struct cpg_mssr_priv *priv) -{ - struct mstp_clock *clock = NULL; - struct device *dev = priv->dev; - unsigned int id = mod->id; - struct clk_init_data init; - struct clk *parent, *clk; - const char *parent_name; - unsigned int i; - - WARN_DEBUG(id < priv->num_core_clks); - WARN_DEBUG(id >= priv->num_core_clks + priv->num_mod_clks); - WARN_DEBUG(mod->parent >= priv->num_core_clks + priv->num_mod_clks); - WARN_DEBUG(PTR_ERR(priv->clks[id]) != -ENOENT); - - parent = priv->clks[mod->parent]; - if (IS_ERR(parent)) { - clk = parent; - goto fail; - } - - clock = kzalloc(sizeof(*clock), GFP_KERNEL); - if (!clock) { - clk = ERR_PTR(-ENOMEM); - goto fail; - } - - init.name = mod->name; - init.ops = &cpg_mstp_clock_ops; - init.flags = CLK_IS_BASIC | CLK_SET_RATE_PARENT; - for (i = 0; i < info->num_crit_mod_clks; i++) - if (id == info->crit_mod_clks[i]) { -#ifdef CLK_ENABLE_HAND_OFF - dev_dbg(dev, "MSTP %s setting CLK_ENABLE_HAND_OFF\n", - mod->name); - init.flags |= CLK_ENABLE_HAND_OFF; - break; -#else - dev_dbg(dev, "Ignoring MSTP %s to prevent disabling\n", - mod->name); - return; -#endif - } - - parent_name = __clk_get_name(parent); - init.parent_names = &parent_name; - init.num_parents = 1; - - clock->index = id - priv->num_core_clks; - clock->priv = priv; - clock->hw.init = &init; - - clk = clk_register(NULL, &clock->hw); - if (IS_ERR(clk)) - goto fail; - - dev_dbg(dev, "Module clock %pC at %pCr Hz\n", clk, clk); - priv->clks[id] = clk; - return; - -fail: - dev_err(dev, "Failed to register %s clock %s: %ld\n", "module,", - mod->name, PTR_ERR(clk)); - kfree(clock); -} - - -#ifdef CONFIG_PM_GENERIC_DOMAINS_OF -struct cpg_mssr_clk_domain { - struct generic_pm_domain genpd; - struct device_node *np; - unsigned int num_core_pm_clks; - unsigned int core_pm_clks[0]; -}; - -static bool cpg_mssr_is_pm_clk(const struct of_phandle_args *clkspec, - struct cpg_mssr_clk_domain *pd) -{ - unsigned int i; - - if (clkspec->np != pd->np || clkspec->args_count != 2) - return false; - - switch (clkspec->args[0]) { - case CPG_CORE: - for (i = 0; i < pd->num_core_pm_clks; i++) - if (clkspec->args[1] == pd->core_pm_clks[i]) - return true; - return false; - - case CPG_MOD: - return true; - - default: - return false; - } -} - -static int cpg_mssr_attach_dev(struct generic_pm_domain *genpd, - struct device *dev) -{ - struct cpg_mssr_clk_domain *pd = - container_of(genpd, struct cpg_mssr_clk_domain, genpd); - struct device_node *np = dev->of_node; - struct of_phandle_args clkspec; - struct clk *clk; - int i = 0; - int error; - - while (!of_parse_phandle_with_args(np, "clocks", "#clock-cells", i, - &clkspec)) { - if (cpg_mssr_is_pm_clk(&clkspec, pd)) - goto found; - - of_node_put(clkspec.np); - i++; - } - - return 0; - -found: - clk = of_clk_get_from_provider(&clkspec); - of_node_put(clkspec.np); - - if (IS_ERR(clk)) - return PTR_ERR(clk); - - error = pm_clk_create(dev); - if (error) { - dev_err(dev, "pm_clk_create failed %d\n", error); - goto fail_put; - } - - error = pm_clk_add_clk(dev, clk); - if (error) { - dev_err(dev, "pm_clk_add_clk %pC failed %d\n", clk, error); - goto fail_destroy; - } - - return 0; - -fail_destroy: - pm_clk_destroy(dev); -fail_put: - clk_put(clk); - return error; -} - -static void cpg_mssr_detach_dev(struct generic_pm_domain *genpd, - struct device *dev) -{ - if (!list_empty(&dev->power.subsys_data->clock_list)) - pm_clk_destroy(dev); -} - -static int __init cpg_mssr_add_clk_domain(struct device *dev, - const unsigned int *core_pm_clks, - unsigned int num_core_pm_clks) -{ - struct device_node *np = dev->of_node; - struct generic_pm_domain *genpd; - struct cpg_mssr_clk_domain *pd; - size_t pm_size = num_core_pm_clks * sizeof(core_pm_clks[0]); - - pd = devm_kzalloc(dev, sizeof(*pd) + pm_size, GFP_KERNEL); - if (!pd) - return -ENOMEM; - - pd->np = np; - pd->num_core_pm_clks = num_core_pm_clks; - memcpy(pd->core_pm_clks, core_pm_clks, pm_size); - - genpd = &pd->genpd; - genpd->name = np->name; - genpd->flags = GENPD_FLAG_PM_CLK; - pm_genpd_init(genpd, &simple_qos_governor, false); - genpd->attach_dev = cpg_mssr_attach_dev; - genpd->detach_dev = cpg_mssr_detach_dev; - - of_genpd_add_provider_simple(np, genpd); - return 0; -} -#else -static inline int cpg_mssr_add_clk_domain(struct device *dev, - const unsigned int *core_pm_clks, - unsigned int num_core_pm_clks) -{ - return 0; -} -#endif /* !CONFIG_PM_GENERIC_DOMAINS_OF */ - - -static const struct of_device_id cpg_mssr_match[] = { -#ifdef CONFIG_ARCH_R8A7795 - { - .compatible = "renesas,r8a7795-cpg-mssr", - .data = &r8a7795_cpg_mssr_info, - }, -#endif - { /* sentinel */ } -}; - -static void cpg_mssr_del_clk_provider(void *data) -{ - of_clk_del_provider(data); -} - -static int __init cpg_mssr_probe(struct platform_device *pdev) -{ - struct device *dev = &pdev->dev; - struct device_node *np = dev->of_node; - const struct cpg_mssr_info *info; - struct cpg_mssr_priv *priv; - unsigned int nclks, i; - struct resource *res; - struct clk **clks; - int error; - - info = of_match_node(cpg_mssr_match, np)->data; - if (info->init) { - error = info->init(dev); - if (error) - return error; - } - - priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); - if (!priv) - return -ENOMEM; - - priv->dev = dev; - spin_lock_init(&priv->mstp_lock); - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - priv->base = devm_ioremap_resource(dev, res); - if (IS_ERR(priv->base)) - return PTR_ERR(priv->base); - - nclks = info->num_total_core_clks + info->num_hw_mod_clks; - clks = devm_kmalloc_array(dev, nclks, sizeof(*clks), GFP_KERNEL); - if (!clks) - return -ENOMEM; - - priv->clks = clks; - priv->num_core_clks = info->num_total_core_clks; - priv->num_mod_clks = info->num_hw_mod_clks; - priv->last_dt_core_clk = info->last_dt_core_clk; - - for (i = 0; i < nclks; i++) - clks[i] = ERR_PTR(-ENOENT); - - for (i = 0; i < info->num_core_clks; i++) - cpg_mssr_register_core_clk(&info->core_clks[i], info, priv); - - for (i = 0; i < info->num_mod_clks; i++) - cpg_mssr_register_mod_clk(&info->mod_clks[i], info, priv); - - error = of_clk_add_provider(np, cpg_mssr_clk_src_twocell_get, priv); - if (error) - return error; - - devm_add_action(dev, cpg_mssr_del_clk_provider, np); - - error = cpg_mssr_add_clk_domain(dev, info->core_pm_clks, - info->num_core_pm_clks); - if (error) - return error; - - return 0; -} - -static struct platform_driver cpg_mssr_driver = { - .driver = { - .name = "renesas-cpg-mssr", - .of_match_table = cpg_mssr_match, - }, -}; - -static int __init cpg_mssr_init(void) -{ - return platform_driver_probe(&cpg_mssr_driver, cpg_mssr_probe); -} - -subsys_initcall(cpg_mssr_init); - -MODULE_DESCRIPTION("Renesas CPG/MSSR Driver"); -MODULE_LICENSE("GPL v2"); diff --git a/drivers/clk/shmobile/renesas-cpg-mssr.h b/drivers/clk/shmobile/renesas-cpg-mssr.h deleted file mode 100644 index e09f03cbf..000000000 --- a/drivers/clk/shmobile/renesas-cpg-mssr.h +++ /dev/null @@ -1,132 +0,0 @@ -/* - * Renesas Clock Pulse Generator / Module Standby and Software Reset - * - * Copyright (C) 2015 Glider bvba - * - * 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; version 2 of the License. - */ - -#ifndef __CLK_RENESAS_CPG_MSSR_H__ -#define __CLK_RENESAS_CPG_MSSR_H__ - - /* - * Definitions of CPG Core Clocks - * - * These include: - * - Clock outputs exported to DT - * - External input clocks - * - Internal CPG clocks - */ - -struct cpg_core_clk { - /* Common */ - const char *name; - unsigned int id; - unsigned int type; - /* Depending on type */ - unsigned int parent; /* Core Clocks only */ - unsigned int div; - unsigned int mult; - unsigned int offset; -}; - -enum clk_types { - /* Generic */ - CLK_TYPE_IN, /* External Clock Input */ - CLK_TYPE_FF, /* Fixed Factor Clock */ - CLK_TYPE_DIV6P1, /* DIV6 Clock with 1 parent clock */ - - /* Custom definitions start here */ - CLK_TYPE_CUSTOM, -}; - -#define DEF_TYPE(_name, _id, _type...) \ - { .name = _name, .id = _id, .type = _type } -#define DEF_BASE(_name, _id, _type, _parent...) \ - DEF_TYPE(_name, _id, _type, .parent = _parent) - -#define DEF_INPUT(_name, _id) \ - DEF_TYPE(_name, _id, CLK_TYPE_IN) -#define DEF_FIXED(_name, _id, _parent, _div, _mult) \ - DEF_BASE(_name, _id, CLK_TYPE_FF, _parent, .div = _div, .mult = _mult) -#define DEF_DIV6P1(_name, _id, _parent, _offset) \ - DEF_BASE(_name, _id, CLK_TYPE_DIV6P1, _parent, .offset = _offset) - - - /* - * Definitions of Module Clocks - */ - -struct mssr_mod_clk { - const char *name; - unsigned int id; - unsigned int parent; /* Add MOD_CLK_BASE for Module Clocks */ -}; - -/* Convert from sparse base-100 to packed index space */ -#define MOD_CLK_PACK(x) ((x) - ((x) / 100) * (100 - 32)) - -#define MOD_CLK_ID(x) (MOD_CLK_BASE + MOD_CLK_PACK(x)) - -#define DEF_MOD(_name, _mod, _parent...) \ - { .name = _name, .id = MOD_CLK_ID(_mod), .parent = _parent } - - -struct device_node; - - /** - * SoC-specific CPG/MSSR Description - * - * @core_clks: Array of Core Clock definitions - * @num_core_clks: Number of entries in core_clks[] - * @last_dt_core_clk: ID of the last Core Clock exported to DT - * @num_total_core_clks: Total number of Core Clocks (exported + internal) - * - * @mod_clks: Array of Module Clock definitions - * @num_mod_clks: Number of entries in mod_clks[] - * @num_hw_mod_clks: Number of Module Clocks supported by the hardware - * - * @crit_mod_clks: Array with Module Clock IDs of critical clocks that - * should not be disabled without a knowledgeable driver - * @num_crit_mod_clks: Number of entries in crit_mod_clks[] - * - * @core_pm_clks: Array with IDs of Core Clocks that are suitable for Power - * Management, in addition to Module Clocks - * @num_core_pm_clks: Number of entries in core_pm_clks[] - * - * @init: Optional callback to perform SoC-specific initialization - * @cpg_clk_register: Optional callback to handle special Core Clock types - */ - -struct cpg_mssr_info { - /* Core Clocks */ - const struct cpg_core_clk *core_clks; - unsigned int num_core_clks; - unsigned int last_dt_core_clk; - unsigned int num_total_core_clks; - - /* Module Clocks */ - const struct mssr_mod_clk *mod_clks; - unsigned int num_mod_clks; - unsigned int num_hw_mod_clks; - - /* Critical Module Clocks that should not be disabled */ - const unsigned int *crit_mod_clks; - unsigned int num_crit_mod_clks; - - /* Core Clocks suitable for PM, in addition to the Module Clocks */ - const unsigned int *core_pm_clks; - unsigned int num_core_pm_clks; - - /* Callbacks */ - int (*init)(struct device *dev); - struct clk *(*cpg_clk_register)(struct device *dev, - const struct cpg_core_clk *core, - const struct cpg_mssr_info *info, - struct clk **clks, void __iomem *base); -}; - -extern const struct cpg_mssr_info r8a7795_cpg_mssr_info; -#endif |