lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-Id: <201407310023.43605.sergei.shtylyov@cogentembedded.com>
Date:	Thu, 31 Jul 2014 00:23:43 +0400
From:	Sergei Shtylyov <sergei.shtylyov@...entembedded.com>
To:	mturquette@...aro.org, linux-kernel@...r.kernel.org
Cc:	linux-sh@...r.kernel.org, vksavl@...il.com
Subject: [PATCH] clk-rcar-gen2: RCAN clock support

Add RCAN clock support to the R-Car generation 2 CPG driver. This clock gets
derived from the USB_EXTAL clock by dividing it by 6. The layout of RCANCKCR
register is close to those of the clocks supported by the 'clk-div6'  driver
but has no divider field, and so can't be supported by that driver...

Signed-off-by: Sergei Shtylyov <sergei.shtylyov@...entembedded.com>

---
The patch is against the 'clk-next' branch of Mike Turquette's 'linux.git' repo.

 drivers/clk/shmobile/clk-rcar-gen2.c |   99 +++++++++++++++++++++++++++++++++++
 1 file changed, 99 insertions(+)

Index: linux/drivers/clk/shmobile/clk-rcar-gen2.c
===================================================================
--- linux.orig/drivers/clk/shmobile/clk-rcar-gen2.c
+++ linux/drivers/clk/shmobile/clk-rcar-gen2.c
@@ -33,6 +33,8 @@ struct rcar_gen2_cpg {
 #define CPG_FRQCRC			0x000000e0
 #define CPG_FRQCRC_ZFC_MASK		(0x1f << 8)
 #define CPG_FRQCRC_ZFC_SHIFT		8
+#define CPG_RCANCKCR			0x00000270
+#define CPG_RCANCKCR_CKSTP		BIT(8)
 
 /* -----------------------------------------------------------------------------
  * Z Clock
@@ -162,6 +164,101 @@ static struct clk * __init cpg_z_clk_reg
 }
 
 /* -----------------------------------------------------------------------------
+ * RCAN Clock
+ *
+ * Traits of this clock:
+ * prepare - clk_prepare only ensures that parents are prepared
+ * enable - clk_enable clears RCANCKCR.CKSTP bit
+ * rate - rate is adjustable.  clk->rate = parent->rate / 6
+ * parent - fixed parent.  No clk_set_parent support
+ */
+struct cpg_rcan_clk {
+	struct clk_hw hw;
+	void __iomem *reg;
+};
+
+#define to_rcan_clk(_hw)	container_of(_hw, struct cpg_rcan_clk, hw)
+
+static unsigned long cpg_rcan_clk_recalc_rate(struct clk_hw *hw,
+					      unsigned long parent_rate)
+{
+	return parent_rate / 6;
+}
+
+static long cpg_rcan_clk_round_rate(struct clk_hw *hw, unsigned long rate,
+				    unsigned long *parent_rate)
+{
+	return *parent_rate / 6;
+}
+
+static int cpg_rcan_clk_set_rate(struct clk_hw *hw, unsigned long rate,
+				 unsigned long parent_rate)
+{
+	return 0;
+}
+
+static int cpg_rcan_clk_enable(struct clk_hw *hw)
+{
+	struct cpg_rcan_clk *clock = to_rcan_clk(hw);
+
+	clk_writel(clk_readl(clock->reg) & ~CPG_RCANCKCR_CKSTP, clock->reg);
+
+	return 0;
+}
+
+static void cpg_rcan_clk_disable(struct clk_hw *hw)
+{
+	struct cpg_rcan_clk *clock = to_rcan_clk(hw);
+
+	clk_writel(clk_readl(clock->reg) | CPG_RCANCKCR_CKSTP, clock->reg);
+}
+
+static int cpg_rcan_clk_is_enabled(struct clk_hw *hw)
+{
+	struct cpg_rcan_clk *clock = to_rcan_clk(hw);
+
+	return !(clk_readl(clock->reg) & CPG_RCANCKCR_CKSTP);
+}
+
+static const struct clk_ops cpg_rcan_clk_ops = {
+	.enable = cpg_rcan_clk_enable,
+	.disable = cpg_rcan_clk_disable,
+	.is_enabled = cpg_rcan_clk_is_enabled,
+	.recalc_rate = cpg_rcan_clk_recalc_rate,
+	.round_rate = cpg_rcan_clk_round_rate,
+	.set_rate = cpg_rcan_clk_set_rate,
+};
+
+static struct clk * __init cpg_rcan_clk_register(struct rcar_gen2_cpg *cpg,
+						 struct device_node *np)
+{
+	static const char *parent_name;
+	struct clk_init_data init;
+	struct cpg_rcan_clk *rcanclk;
+	struct clk *clk;
+
+	rcanclk = kzalloc(sizeof(*rcanclk), GFP_KERNEL);
+	if (!rcanclk)
+		return ERR_PTR(-ENOMEM);
+
+	parent_name = of_clk_get_parent_name(np, 1);
+
+	init.name = "rcan";
+	init.ops = &cpg_rcan_clk_ops;
+	init.parent_names = &parent_name;
+	init.num_parents = 1;
+
+	rcanclk->reg = cpg->reg + CPG_RCANCKCR;
+	rcanclk->hw.init = &init;
+
+	clk = clk_register(NULL, &rcanclk->hw);
+	if (IS_ERR(clk))
+		kfree(rcanclk);
+
+	return clk;
+}
+
+/* -----------------------------------------------------------------------------
  * CPG Clock Data
  */
 
@@ -262,6 +359,8 @@ rcar_gen2_cpg_register_clock(struct devi
 		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 {
 		return ERR_PTR(-EINVAL);
 	}
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ