Skip to contentSkip to conversation

generic clock framework

PATCH In review Francesco VIRLINZI 2 participants 3 messages Nov 10, 2009 – Nov 11, 2009

Subsystems (3)
lore
Share & tools
lore
#0 lore raw

PATCH 1/1 generic clock framework

Hi all

I'm Francesco and I work in STMicroelectronics

In the last ELC-E_2009 I spoke on a generic clock framework I'm working on
(see
http://tree.celinuxforum.org/CelfPubWiki/ELCEurope2009Presentations?action=AttachFile&do=view&target=ELC_E_2009_Generic_Clock_Framework.pdf).

I wrote the gcf to manage both clocks the platform_devices during a clock operation.

The main features are:
- it's integrated in the LDM
- it tracks the clock-to-clock relationship
- it tracks the clock-to-device relationship

- it has sysfs interface
- - the user can navigate the clock tree under /sys/clocks/...

- it uses the linux API (<linux/clk.h>) with some extra functions (to
register/unregister a clock
and other utility functions as clk_for_each())

- it involves the platform_device and the platform_driver in the clock
propagation.
- - basically each clock operation is managed as a transaction which
evolves step by step.
- - all the clock rates are evaluated (before the clk operation is
actually done)
- - each platform_device can check (before the clk operation is
actually done) the clk environment
it will have at the end of clock operation and if required it can
reject the operation.
- - each clock operation is actually executed only if all the
platform_devices accept the operation it-self

Moreover a common clock framework could be used to avoid a lot of duplicated and/or similar code
just a grep of 'EXPORT_SYMBOL\(clk_enable' under arch/arm finds 22
entries.

The patch is based on a 2.6.30 kernel also if it has a preliminary integration with the PM_RUNTIME
support.

It works on our st40 (an sh4 cpu based system) no test/porting was done on any ARM platform.

It would be mainly a starting point for a discussion and I'm available to extend/fix/share it.

Regards
Francesco

From 4e065fb9247ec511bfdc88001f0713977d3f4e89 Mon Sep 17 00:00:00 2001
From: Francesco Virlinzi <[email protected]>
Date: Fri, 23 Oct 2009 15:26:42 +0200
Subject: [PATCH] generic clock framework

version: 0.6.2

---
 drivers/base/Makefile           |    4 +
 drivers/base/base.h             |    5 +
 drivers/base/clk.c              | 1606 +++++++++++++++++++++++++++++++++++++++
 drivers/base/clk.h              |  319 ++++++++
 drivers/base/clk_pm.c           |  197 +++++
 drivers/base/clk_utils.c        |  456 +++++++++++
 drivers/base/init.c             |    1 +
 drivers/base/platform.c         |   27 +
 include/linux/clk.h             |  251 ++++++
 include/linux/platform_device.h |    9 +
 init/Kconfig                    |   23 +
 11 files changed, 2898 insertions(+), 0 deletions(-)
 create mode 100644 drivers/base/clk.c
 create mode 100644 drivers/base/clk.h
 create mode 100644 drivers/base/clk_pm.c
 create mode 100644 drivers/base/clk_utils.c
drivers/base/Makefile +4 -0
index b5b8ba5..b78a2bf 100644
@@ -16,6 +16,10 @@ ifeq ($(CONFIG_SYSFS),y)
 obj-$(CONFIG_MODULES)	+= module.o
 endif
 obj-$(CONFIG_SYS_HYPERVISOR) += hypervisor.o
+ifdef CONFIG_GENERIC_CLK_FM
+obj-y			+= clk.o clk_utils.o
+obj-$(CONFIG_PM)	+= clk_pm.o
+endif
 
 ifeq ($(CONFIG_DEBUG_DRIVER),y)
 EXTRA_CFLAGS += -DDEBUG
drivers/base/base.h +5 -0
index b528145..bc5b9e8 100644
@@ -94,6 +94,11 @@ extern int devices_init(void);
 extern int buses_init(void);
 extern int classes_init(void);
 extern int firmware_init(void);
+#ifdef CONFIG_GENERIC_CLK_FM
+extern int clock_init(void);
+#else
+static inline int clock_init(void){ return 0; }
+#endif
 #ifdef CONFIG_SYS_HYPERVISOR
 extern int hypervisor_init(void);
 #else
drivers/base/clk.c new file +1606 -0

1,606 lines not on this page · raw message

drivers/base/clk.h new file +319 -0

319 lines not on this page · raw message

drivers/base/clk_pm.c new file +197 -0

197 lines not on this page · raw message

drivers/base/clk_utils.c new file +456 -0

456 lines not on this page · raw message

drivers/base/init.c +1 -0
index 7bd9b6a..2441b26 100644
@@ -24,6 +24,7 @@ void __init driver_init(void)
 	buses_init();
 	classes_init();
 	firmware_init();
+	clock_init();
 	hypervisor_init();
 
 	/* These are also core pieces, but must come after the
drivers/base/platform.c +27 -0
index 8b4708e..550d993 100644
@@ -17,6 +17,8 @@
 #include <linux/bootmem.h>
 #include <linux/err.h>
 #include <linux/slab.h>
+#include <linux/clk.h>
+#include "clk.h"
 
 #include "base.h"
 
@@ -272,9 +274,20 @@ int platform_device_add(struct platform_device *pdev)
 	pr_debug("Registering platform device '%s'. Parent at %s\n",
 		 dev_name(&pdev->dev), dev_name(pdev->dev.parent));
 
+#ifdef CONFIG_GENERIC_CLK_FM
+	clk_add_device(pdev, PDEV_ADDING);
+
+	ret = device_add(&pdev->dev);
+
+	clk_add_device(pdev, (ret ? PDEV_ADD_FAILED : PDEV_ADDED));
+
+	if (ret == 0)
+		return ret;
+#else
 	ret = device_add(&pdev->dev);
 	if (ret == 0)
 		return ret;
+#endif
 
  failed:
 	while (--i >= 0) {
@@ -311,6 +324,9 @@ void platform_device_del(struct platform_device *pdev)
 			if (type == IORESOURCE_MEM || type == IORESOURCE_IO)
 				release_resource(r);
 		}
+#ifdef CONFIG_GENERIC_CLK_FM
+	clk_del_device(pdev);
+#endif
 	}
 }
 EXPORT_SYMBOL_GPL(platform_device_del);
@@ -445,7 +461,18 @@ static int platform_drv_probe(struct device *_dev)
 	struct platform_driver *drv = to_platform_driver(_dev->driver);
 	struct platform_device *dev = to_platform_device(_dev);
 
+#ifdef CONFIG_GENERIC_CLK_FM
+	int ret;
+	ret = clk_probe_device(dev, PDEV_PROBEING);
+	if (ret)
+		return ret;
+	ret = drv->probe(dev);
+
+	clk_probe_device(dev, (ret ? PDEV_PROBE_FAILED : PDEV_PROBED));
+	return ret;
+#else
 	return drv->probe(dev);
+#endif
 }
 
 static int platform_drv_probe_fail(struct device *_dev)
include/linux/clk.h +251 -0

261 lines not on this page · raw message

include/linux/platform_device.h +9 -0
index b67bb5d..db1989d 100644
@@ -12,6 +12,7 @@
 #define _PLATFORM_DEVICE_H_
 
 #include <linux/device.h>
+#include <linux/clk.h>
 #include <linux/mod_devicetable.h>
 
 struct platform_device {
@@ -22,6 +23,11 @@ struct platform_device {
 	struct resource	* resource;
 
 	struct platform_device_id	*id_entry;
+#ifdef CONFIG_GENERIC_CLK_FM
+	unsigned long	clk_state;      /* used by the core */
+	unsigned long	nr_clks;
+	struct pdev_clk_info    *clks;
+#endif
 };
 
 #define platform_get_device_id(pdev)	((pdev)->id_entry)
@@ -61,6 +67,9 @@ struct platform_driver {
 	int (*resume_early)(struct platform_device *);
 	int (*resume)(struct platform_device *);
 	struct device_driver driver;
+#ifdef CONFIG_GENERIC_CLK_FM
+	int (*notify)(unsigned long code, struct platform_device *, void *);
+#endif
 	struct platform_device_id *id_table;
 };
 
init/Kconfig +23 -0
index 0682ecc..4254c5f 100644
@@ -1042,6 +1042,29 @@ config SLOW_WORK
 
 	  See Documentation/slow-work.txt.
 
+config GENERIC_CLK_FM
+        default n
+	depends on EXPERIMENTAL
+        bool "Generic Clock Framework"
+        help
+          Add the clock framework in the Linux driver model
+          to track the clocks used by each devices and drivers
+
+config CLK_FORCE_GENERIC_EVALUATE
+        depends on GENERIC_CLK_FM
+        default n
+        bool "Force the clk_generic_evaluate_rate"
+        help
+          Say the if you want use the clk_generic_evaluate_rate on every clock
+          without evaluate_rate
+
+config CLK_DEBUG
+        depends on GENERIC_CLK_FM
+        default n
+        bool "Debug the Generic Clk Framework"
+        help
+          Prints some message to debug the clock framework
+
 endmenu		# General setup
 
 config HAVE_GENERIC_DMA_COHERENT
Signature · 1 line
1.6.2.5
#1 lore raw
Quoted 11 lines · Francesco VIRLINZI

Hi all

I'm Francesco and I work in STMicroelectronics

In the last ELC-E_2009 I spoke on a generic clock framework I'm working on
(see
http://tree.celinuxforum.org/CelfPubWiki/ELCEurope2009Presentations?action=AttachFile&do=view&target=ELC_E_2009_Generic_Clock_Framework.pdf).

I wrote the gcf to manage both clocks the platform_devices during a clock operation.

This looks good to me, in principle, but I'm not a clock or PM expert. I would recommend sending this to the linux-kernel and linux-pm lists as well. I think you'll get a wider audience for feedback.
-- Tim

=============================
Tim Bird
Architecture Group Chair, CE Linux Forum Senior Staff Engineer, Sony Corporation of America
=============================

#2 lore raw

PATCH 1/1 generic clock framework

Hi Tim
Thanks for your feedback.
ARM mail list was already involved.

Regards
Francesco

Quoted 28 lines · Tim Bird
Quoted 4 lines · Francesco VIRLINZI

Hi all

I'm Francesco and I work in STMicroelectronics

Quoted 8 lines

In the last ELC-E_2009 I spoke on a generic clock framework I'm working on
(see
http://tree.celinuxforum.org/CelfPubWiki/ELCEurope2009Presentations?action=AttachFile&do=view&target=ELC_E_2009_Generic_Clock_Framework.pdf).

I wrote the gcf to manage both clocks the platform_devices during a clock operation.

This looks good to me, in principle, but I'm not a clock or PM expert. I would recommend sending this to the linux-kernel and linux-pm lists as well. I think you'll get a wider audience for feedback.
-- Tim

=============================
Tim Bird
Architecture Group Chair, CE Linux Forum Senior Staff Engineer, Sony Corporation of America
=============================