aboutsummaryrefslogtreecommitdiff
path: root/drivers/clk/renesas/rcar-gen3-cpg.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/clk/renesas/rcar-gen3-cpg.c')
-rw-r--r--drivers/clk/renesas/rcar-gen3-cpg.c45
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);
}