diff options
Diffstat (limited to 'drivers/clk/renesas/rcar-gen3-cpg.c')
-rw-r--r-- | drivers/clk/renesas/rcar-gen3-cpg.c | 45 |
1 files changed, 32 insertions, 13 deletions
diff --git a/drivers/clk/renesas/rcar-gen3-cpg.c b/drivers/clk/renesas/rcar-gen3-cpg.c index 628b63b85d3f..4ba38f98cc7b 100644 --- a/drivers/clk/renesas/rcar-gen3-cpg.c +++ b/drivers/clk/renesas/rcar-gen3-cpg.c @@ -1,15 +1,12 @@ +// SPDX-License-Identifier: GPL-2.0 /* * R-Car Gen3 Clock Pulse Generator * - * Copyright (C) 2015-2016 Glider bvba + * Copyright (C) 2015-2018 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> @@ -31,6 +28,8 @@ #define CPG_PLL2CR 0x002c #define CPG_PLL4CR 0x01f4 +#define CPG_RCKCR_CKSEL BIT(15) /* RCLK Clock Source Select */ + struct cpg_simple_notifier { struct notifier_block nb; void __iomem *reg; @@ -444,7 +443,7 @@ struct clk * __init rcar_gen3_cpg_clk_register(struct device *dev, unsigned int div = 1; u32 value; - parent = clks[core->parent & 0xffff]; /* CLK_TYPE_PE uses high bits */ + parent = clks[core->parent & 0xffff]; /* some types use high bits */ if (IS_ERR(parent)) return ERR_CAST(parent); @@ -524,7 +523,7 @@ struct clk * __init rcar_gen3_cpg_clk_register(struct device *dev, if (clk_get_rate(clks[cpg_clk_extalr])) { parent = clks[cpg_clk_extalr]; - value |= BIT(15); + value |= CPG_RCKCR_CKSEL; } writel(value, csn->reg); @@ -537,16 +536,14 @@ struct clk * __init rcar_gen3_cpg_clk_register(struct device *dev, parent = clks[cpg_clk_extalr]; break; - case CLK_TYPE_GEN3_PE: + case CLK_TYPE_GEN3_MDSEL: /* - * Peripheral clock with a fixed divider, selectable between - * clean and spread spectrum parents using MD12 + * Clock selectable between two parents and two fixed dividers + * using a mode pin */ - if (cpg_mode & BIT(12)) { - /* Clean */ + if (cpg_mode & BIT(core->offset)) { div = core->div & 0xffff; } else { - /* SCCG */ parent = clks[core->parent >> 16]; if (IS_ERR(parent)) return ERR_CAST(parent); @@ -563,6 +560,28 @@ struct clk * __init rcar_gen3_cpg_clk_register(struct device *dev, return cpg_z_clk_register(core->name, __clk_get_name(parent), base, CPG_FRQCRC_Z2FC_MASK); + case CLK_TYPE_GEN3_OSC: + /* + * Clock combining OSC EXTAL predivider and a fixed divider + */ + div = cpg_pll_config->osc_prediv * core->div; + break; + + case CLK_TYPE_GEN3_RCKSEL: + /* + * Clock selectable between two parents and two fixed dividers + * using RCKCR.CKSEL + */ + if (readl(base + CPG_RCKCR) & CPG_RCKCR_CKSEL) { + div = core->div & 0xffff; + } else { + parent = clks[core->parent >> 16]; + if (IS_ERR(parent)) + return ERR_CAST(parent); + div = core->div >> 16; + } + break; + default: return ERR_PTR(-EINVAL); } |