mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: James Hogan <james.hogan@imgtec.com>
To: Mike Turquette <mturquette@linaro.org>,
	linux-metag@vger.kernel.org, linux-kernel@vger.kernel.org,
	devicetree@vger.kernel.org
Cc: Heiko Stuebner <heiko@sntech.de>, James Hogan <james.hogan@imgtec.com>
Subject: [PATCH v2 04/16] clk: tz1090: add deleter clock driver
Date: Mon,  1 Dec 2014 23:19:54 +0000	[thread overview]
Message-ID: <1417476006-10407-5-git-send-email-james.hogan@imgtec.com> (raw)
In-Reply-To: <1417476006-10407-1-git-send-email-james.hogan@imgtec.com>

Add a clock driver for clock deleters in the TZ1090 SoC, which delete up
to 1023 out of every 1024 clock pulses. There are 4 of these in TZ1090,
for the system clock, the Meta core clock, and one for each UCC.

The tz1090_clk_register_deleters() helper function can be used to
register a set of deleters from static initialisation data. A DEL()
macro is provided in tz1090/clk.h to aid the creation of this data, for
example:

static const struct tz1090_clk_deleter deleters[] __initconst = {
	DEL(CLK_TOP_SYS, "sys_undeleted", "sys", TOP_CLKDELETE),
	...
};
...
tz1090_clk_register_deleters(p, deleters, ARRAY_SIZE(deleters));

Signed-off-by: James Hogan <james.hogan@imgtec.com>
Cc: Mike Turquette <mturquette@linaro.org>
Cc: linux-metag@vger.kernel.org
---
Changes since v1 (patch 10):
- Renamed function prefixes from clk_tz1090_ to tz1090_clk_ for
  consistency with the rest.
- Drop DT binding as it will be instantiated directly from a provider.
- Add tz1090_clk_register_deleters() to conveniently register a set of
  deleters in a clock provider from static initilisation data.
- Extend tz1090/clk.h interface for easy static initialisation with
  macros.
---
 drivers/clk/tz1090/Makefile             |   1 +
 drivers/clk/tz1090/clk-tz1090-deleter.c | 132 ++++++++++++++++++++++++++++++++
 drivers/clk/tz1090/clk.h                |  31 ++++++++
 3 files changed, 164 insertions(+)
 create mode 100644 drivers/clk/tz1090/clk-tz1090-deleter.c

diff --git a/drivers/clk/tz1090/Makefile b/drivers/clk/tz1090/Makefile
index d44acac..39c29ac 100644
--- a/drivers/clk/tz1090/Makefile
+++ b/drivers/clk/tz1090/Makefile
@@ -1,5 +1,6 @@
 # Makefile for TZ1090-specific clocks
 obj-y		+= clk.o
 
+obj-y		+= clk-tz1090-deleter.o
 obj-y		+= clk-tz1090-gate-bank.o
 obj-y		+= clk-tz1090-mux-bank.o
diff --git a/drivers/clk/tz1090/clk-tz1090-deleter.c b/drivers/clk/tz1090/clk-tz1090-deleter.c
new file mode 100644
index 0000000..9ec604d
--- /dev/null
+++ b/drivers/clk/tz1090/clk-tz1090-deleter.c
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 2012-2014 Imagination Technologies Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Clock deleter in TZ1090
+ */
+
+#include <linux/bitops.h>
+#include <linux/clk-provider.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/slab.h>
+
+#include "clk.h"
+
+/**
+ * struct tz1090_clk_deleter_priv - Clock deleter
+ *
+ * @hw:		handle between common and hardware-specific interfaces
+ * @reg:	delete register
+ * @period:	cycle period
+ * @mask:	bit mask of delete field
+ * @shift:	start bit of delete field
+ *
+ * Deleter in TZ1090, allowing up to period-1 out of each period cycles to be
+ * deleted.
+ */
+struct tz1090_clk_deleter_priv {
+	struct clk_hw	hw;
+	void __iomem	*reg;
+	u32		period;
+	u32		mask;
+	u8		shift;
+};
+
+#define to_tz1090_clk_deleter(_hw) \
+	container_of(_hw, struct tz1090_clk_deleter_priv, hw)
+
+static unsigned long tz1090_clk_deleter_recalc_rate(struct clk_hw *hw,
+						    unsigned long parent_rate)
+{
+	struct tz1090_clk_deleter_priv *deleter = to_tz1090_clk_deleter(hw);
+	u32 delete;
+	u64 rate;
+
+	delete = (readl(deleter->reg) & deleter->mask) >> deleter->shift;
+	rate = (u64)parent_rate * (deleter->period - delete);
+	do_div(rate, deleter->period);
+	return rate;
+}
+
+static const struct clk_ops tz1090_clk_deleter_ops = {
+	.recalc_rate = tz1090_clk_deleter_recalc_rate,
+};
+
+/**
+ * __register_deleter() - register a clock deleter
+ * @name:		name of this clock
+ * @parent_name:	name of clock's parent
+ * @flags:		framework-specific flags
+ * @reg:		register address to adjust deleter
+ * @period:		delete cycle period
+ * @mask:		mask of delete field
+ * @shift:		start bit of delete field
+ *
+ * Register a TZ1090 clock deleter with the clock framework.
+ */
+static struct clk *__init __register_deleter(const char *name,
+					     const char *parent_name,
+					     unsigned long flags,
+					     void __iomem *reg,
+					     u32 period,
+					     u32 mask,
+					     u8 shift)
+{
+	struct tz1090_clk_deleter_priv *deleter;
+	struct clk *clk;
+	struct clk_init_data init;
+
+	/* allocate the deleter */
+	deleter = kzalloc(sizeof(struct tz1090_clk_deleter_priv), GFP_KERNEL);
+	if (!deleter)
+		return ERR_PTR(-ENOMEM);
+
+	init.name = name;
+	init.ops = &tz1090_clk_deleter_ops;
+	init.flags = flags | CLK_IS_BASIC;
+	init.parent_names = (parent_name ? &parent_name : NULL);
+	init.num_parents = (parent_name ? 1 : 0);
+
+	/* struct tz1090_clk_deleter_priv assignments */
+	deleter->reg = reg;
+	deleter->period = period;
+	deleter->mask = mask;
+	deleter->shift = shift;
+	deleter->hw.init = &init;
+
+	/* register the clock */
+	clk = clk_register(NULL, &deleter->hw);
+
+	if (IS_ERR(clk))
+		kfree(deleter);
+
+	return clk;
+}
+
+/**
+ * tz1090_clk_register_deleters() - Register set of deleters with a provider.
+ * @p:		TZ1090 clock provider.
+ * @deleters:	Array of deleter descriptions.
+ * @count	Number of deleters described in the array.
+ */
+void __init tz1090_clk_register_deleters(struct tz1090_clk_provider *p,
+				const struct tz1090_clk_deleter *deleters,
+				unsigned int count)
+{
+	const struct tz1090_clk_deleter *del;
+	struct clk *clk;
+	unsigned int i;
+
+	for (del = deleters, i = 0; i < count; ++del, ++i) {
+		clk = __register_deleter(tz1090_clk_xlate(p, del->name),
+					 tz1090_clk_xlate(p, del->parent), 0,
+					 p->base + del->reg, 1024, 0x3ff, 0);
+		p->clk_data.clks[del->id] = clk;
+	}
+}
diff --git a/drivers/clk/tz1090/clk.h b/drivers/clk/tz1090/clk.h
index c9fe6ca..8f90908 100644
--- a/drivers/clk/tz1090/clk.h
+++ b/drivers/clk/tz1090/clk.h
@@ -135,4 +135,35 @@ struct tz1090_clk_mux_bank {
 void tz1090_clk_register_mux_bank(struct tz1090_clk_provider *p,
 				  const struct tz1090_clk_mux_bank *bank);
 
+
+/* Deleters */
+
+/**
+ * struct tz1090_clk_deleter - Describes a clock deleter.
+ * @id:		Id of output clock in provider.
+ * @reg:	Offset of deleter register in the MMIO region.
+ * @name:	Name of deleted clock to provide.
+ * @parent:	Name of parent/source clocks.
+ *
+ * The deleter is assumed to have a period of 1024.
+ */
+struct tz1090_clk_deleter {
+	unsigned int		id;
+	unsigned long		reg;
+	const char		*name;
+	const char		*parent;
+};
+
+#define DEL(_id, _parent, _name, _reg)		\
+	{					\
+		.id		= (_id),	\
+		.reg		= (_reg),	\
+		.name		= (_name),	\
+		.parent		= (_parent),	\
+	}
+
+void tz1090_clk_register_deleters(struct tz1090_clk_provider *p,
+				  const struct tz1090_clk_deleter *deleters,
+				  unsigned int count);
+
 #endif
-- 
2.0.4


  parent reply	other threads:[~2014-12-01 23:25 UTC|newest]

Thread overview: 18+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-12-01 23:19 [PATCH v2 00/16] tz1090: add clock components James Hogan
2014-12-01 23:19 ` [PATCH v2 01/16] clk: tz1090: add clock provider common code James Hogan
2014-12-01 23:19 ` [PATCH v2 02/16] clk: tz1090: add gate bank clock driver James Hogan
2014-12-01 23:19 ` [PATCH v2 03/16] clk: tz1090: add mux " James Hogan
2014-12-01 23:19 ` James Hogan [this message]
2014-12-01 23:19 ` [PATCH v2 05/16] clk: tz1090: add divider " James Hogan
2014-12-01 23:19 ` [PATCH v2 06/16] clk: tz1090: add PLL " James Hogan
2014-12-01 23:19 ` [PATCH v2 07/16] dt: binding: add binding for TZ1090 PDC clocks James Hogan
2014-12-01 23:19 ` [PATCH v2 08/16] clk: tz1090: add PDC clock provider driver James Hogan
2014-12-01 23:19 ` [PATCH v2 09/16] dt: binding: add binding for TZ1090 TOP clocks James Hogan
2014-12-01 23:20 ` [PATCH v2 10/16] clk: tz1090: add TOP clock provider driver James Hogan
2014-12-01 23:20 ` [PATCH v2 11/16] dt: binding: add binding for TZ1090 HEP clocks James Hogan
2014-12-01 23:20 ` [PATCH v2 12/16] clk: tz1090: add HEP clock provider driver James Hogan
2014-12-01 23:20 ` [PATCH v2 13/16] dt: binding: add binding for TZ1090 PERIP clocks James Hogan
2014-12-01 23:20 ` [PATCH v2 14/16] clk: tz1090: add PERIP clock provider driver James Hogan
2014-12-01 23:20 ` [PATCH v2 15/16] metag: tz1090: add TZ1090 clocks to device tree James Hogan
2014-12-01 23:20 ` [PATCH v2 16/16] metag: tz1090: connect Meta core clock James Hogan
2015-01-09 15:10 ` [PATCH v2 00/16] tz1090: add clock components James Hogan

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1417476006-10407-5-git-send-email-james.hogan@imgtec.com \
    --to=james.hogan@imgtec.com \
    --cc=devicetree@vger.kernel.org \
    --cc=heiko@sntech.de \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-metag@vger.kernel.org \
    --cc=mturquette@linaro.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®