diff mbox

[01/18] regmap: mmio: Add function to attach a clock

Message ID 02f409ad80afed68e02660f161fc26d588a86fa7.1499955058.git-series.maxime.ripard@free-electrons.com (mailing list archive)
State New, archived
Headers show

Commit Message

Maxime Ripard July 13, 2017, 2:12 p.m. UTC
regmap_init_mmio_clk allows to specify a clock that needs to be enabled
while accessing the registers.

However, that clock is retrieved through its clock ID, which means it will
lookup that clock based on the current device that registers the regmap,
and, in the DT case, will only look in that device OF node.

This might be problematic if the clock to enable is stored in another node.
Let's add a function that allows to attach a clock that has already been
retrieved to a regmap in order to fix this.

Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 drivers/base/regmap/regmap-mmio.c | 24 ++++++++++++++++++++++++
 include/linux/regmap.h            |  4 ++++
 2 files changed, 28 insertions(+)

Comments

Mark Brown July 13, 2017, 4:01 p.m. UTC | #1
On Thu, Jul 13, 2017 at 04:12:56PM +0200, Maxime Ripard wrote:

> This might be problematic if the clock to enable is stored in another node.
> Let's add a function that allows to attach a clock that has already been
> retrieved to a regmap in order to fix this.

What is the use case for this?
Maxime Ripard July 17, 2017, 9:01 a.m. UTC | #2
Hi Mark,

On Thu, Jul 13, 2017 at 05:01:42PM +0100, Mark Brown wrote:
> On Thu, Jul 13, 2017 at 04:12:56PM +0200, Maxime Ripard wrote:
> 
> > This might be problematic if the clock to enable is stored in another node.
> > Let's add a function that allows to attach a clock that has already been
> > retrieved to a regmap in order to fix this.
> 
> What is the use case for this?

This is useful when the clock you want to be handled by the regmap is
not described in the device node that probed the driver, but one of
its subnode, or an another node entirely.

We're in the latter case, where we have two controllers in the DT, but
are driven by the same driver. We'll create two regmaps, but one will
not have the proper of_node used to retrieve the clock.

Maxime
Mark Brown July 18, 2017, 1:21 p.m. UTC | #3
On Mon, Jul 17, 2017 at 11:01:07AM +0200, Maxime Ripard wrote:
> On Thu, Jul 13, 2017 at 05:01:42PM +0100, Mark Brown wrote:

> > > This might be problematic if the clock to enable is stored in another node.
> > > Let's add a function that allows to attach a clock that has already been
> > > retrieved to a regmap in order to fix this.

> > What is the use case for this?

> This is useful when the clock you want to be handled by the regmap is
> not described in the device node that probed the driver, but one of
> its subnode, or an another node entirely.

> We're in the latter case, where we have two controllers in the DT, but
> are driven by the same driver. We'll create two regmaps, but one will
> not have the proper of_node used to retrieve the clock.

I'm sorry but I'm still not seeing why you're doing this.  Can you be
more concrete please?
Maxime Ripard July 20, 2017, 2:44 p.m. UTC | #4
On Tue, Jul 18, 2017 at 02:21:47PM +0100, Mark Brown wrote:
> On Mon, Jul 17, 2017 at 11:01:07AM +0200, Maxime Ripard wrote:
> > On Thu, Jul 13, 2017 at 05:01:42PM +0100, Mark Brown wrote:
> 
> > > > This might be problematic if the clock to enable is stored in another node.
> > > > Let's add a function that allows to attach a clock that has already been
> > > > retrieved to a regmap in order to fix this.
> 
> > > What is the use case for this?
> 
> > This is useful when the clock you want to be handled by the regmap is
> > not described in the device node that probed the driver, but one of
> > its subnode, or an another node entirely.
> 
> > We're in the latter case, where we have two controllers in the DT, but
> > are driven by the same driver. We'll create two regmaps, but one will
> > not have the proper of_node used to retrieve the clock.
> 
> I'm sorry but I'm still not seeing why you're doing this.  Can you be
> more concrete please?

We have two devices needed to bring DSI: the DSI controller itself and
its associated PHY.

The PHY configuration cannot be done through a framework because it
requires more information than the various phy frameworks allow to
pass through to the driver.

Therefore, we have a single driver, attached to the DSI controller,
which handles both the PHY and the DSI controller.

Both the PHY and the DSI controller are separate device, with
different memory regions. Therefore, we need to create two regmaps,
with clocks attached to them.

However, the default clock retrieval mechanism doesn't work for the
phy regmap, since only the DSI controller device of_node is
considered, while its clock is stored in a separate node.

I hope it's clearer,
Maxime
diff mbox

Patch

diff --git a/drivers/base/regmap/regmap-mmio.c b/drivers/base/regmap/regmap-mmio.c
index 5189fd6182f6..5cadfd3394d8 100644
--- a/drivers/base/regmap/regmap-mmio.c
+++ b/drivers/base/regmap/regmap-mmio.c
@@ -28,6 +28,8 @@ 
 struct regmap_mmio_context {
 	void __iomem *regs;
 	unsigned val_bytes;
+
+	bool attached_clk;
 	struct clk *clk;
 
 	void (*reg_write)(struct regmap_mmio_context *ctx,
@@ -363,4 +365,26 @@  struct regmap *__devm_regmap_init_mmio_clk(struct device *dev,
 }
 EXPORT_SYMBOL_GPL(__devm_regmap_init_mmio_clk);
 
+int regmap_mmio_attach_clk(struct regmap *map, struct clk *clk)
+{
+	struct regmap_mmio_context *ctx = map->bus_context;
+
+	ctx->clk = clk;
+	ctx->attached_clk = true;
+
+	return clk_prepare(ctx->clk);
+}
+EXPORT_SYMBOL_GPL(regmap_mmio_attach_clk);
+
+void regmap_mmio_detach_clk(struct regmap *map)
+{
+	struct regmap_mmio_context *ctx = map->bus_context;
+
+	clk_unprepare(ctx->clk);
+
+	ctx->attached_clk = false;
+	ctx->clk = NULL;
+}
+EXPORT_SYMBOL_GPL(regmap_mmio_detach_clk);
+
 MODULE_LICENSE("GPL v2");
diff --git a/include/linux/regmap.h b/include/linux/regmap.h
index 978abfbac617..11a292a76586 100644
--- a/include/linux/regmap.h
+++ b/include/linux/regmap.h
@@ -21,6 +21,7 @@ 
 #include <linux/lockdep.h>
 
 struct module;
+struct clk;
 struct device;
 struct i2c_client;
 struct irq_domain;
@@ -789,6 +790,9 @@  bool regmap_ac97_default_volatile(struct device *dev, unsigned int reg);
 	__regmap_lockdep_wrapper(__devm_regmap_init_ac97, #config,	\
 				ac97, config)
 
+int regmap_mmio_attach_clk(struct regmap *map, struct clk *clk);
+void regmap_mmio_detach_clk(struct regmap *map);
+
 void regmap_exit(struct regmap *map);
 int regmap_reinit_cache(struct regmap *map,
 			const struct regmap_config *config);