[U-Boot] [PATCH v3 53/54] dm: Add a clock uclass

Simon Glass sjg at chromium.org
Tue Jun 23 23:39:15 CEST 2015


Clocks are an important feature of platforms and have become increasing
complex with time. Most modern SoCs have multiple PLLs and dozens of clock
dividers which distribute clocks to on-chip peripherals.

Some SoC implementations have a clock API which is private to that SoC family,
e.g. Tegra and Exynos. This is useful but it would be better to have a
common API that can be understood and used throughout U-Boot.

Add a simple clock API as a starting point. It supports querying and setting
the rate of a clock. Each clock is a device. To reduce memory and processing
overhead the concept of peripheral clocks is provided. These do not need to
be explicit devices - it is possible to write a driver that can adjust the
I2C clock (for example) without an explicit I2C clock device. This can
dramatically reduce the number of devices (and associated overhead) in a
complex SoC.

Clocks are referenced by a number, and it is expected that SoCs will define
that numbering themselves via an enum.

Signed-off-by: Simon Glass <sjg at chromium.org>
---

Changes in v3: None
Changes in v2: None

 drivers/Kconfig          |  2 ++
 drivers/Makefile         |  1 +
 drivers/clk/Kconfig      | 19 ++++++++++++
 drivers/clk/Makefile     |  8 +++++
 drivers/clk/clk-uclass.c | 58 +++++++++++++++++++++++++++++++++++
 include/clk.h            | 80 ++++++++++++++++++++++++++++++++++++++++++++++++
 include/dm/uclass-id.h   |  1 +
 scripts/Makefile.spl     |  1 +
 8 files changed, 170 insertions(+)
 create mode 100644 drivers/clk/Kconfig
 create mode 100644 drivers/clk/Makefile
 create mode 100644 drivers/clk/clk-uclass.c

diff --git a/drivers/Kconfig b/drivers/Kconfig
index 7c9eefc..619d93a 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -1,5 +1,7 @@
 menu "Device Drivers"
 
+source "drivers/clk/Kconfig"
+
 source "drivers/core/Kconfig"
 
 source "drivers/cpu/Kconfig"
diff --git a/drivers/Makefile b/drivers/Makefile
index 39b7919..9f5cec7 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -1,3 +1,4 @@
+obj-$(CONFIG_CLK) += clk/
 obj-$(CONFIG_DM) += core/
 obj-$(CONFIG_DM_DEMO) += demo/
 obj-$(CONFIG_BIOSEMU) += bios_emulator/
diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
new file mode 100644
index 0000000..07eb54c
--- /dev/null
+++ b/drivers/clk/Kconfig
@@ -0,0 +1,19 @@
+config CLK
+	bool "Enable clock driver support"
+	depends on DM
+	help
+	  This allows drivers to be provided for clock generators, including
+	  oscillators and PLLs. Devices can use a common clock API to request
+	  a particular clock rate and check on available clocks. Clocks can
+	  feed into other clocks in a tree structure, with multiplexers to
+	  choose the source for each clock.
+
+config SPL_CLK_SUPPORT
+	bool "Enable clock support in SPL"
+	depends on CLK
+	help
+	  The clock subsystem adds a small amount of overhead to the image.
+	  If this is acceptable and you have a need to use clock drivers in
+	  SPL, enable this option. It might provide a cleaner interface to
+	  setting up clocks within SPL, and allows the same drivers to be
+	  used as U-Boot proper.
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
new file mode 100644
index 0000000..b51cf23
--- /dev/null
+++ b/drivers/clk/Makefile
@@ -0,0 +1,8 @@
+#
+# Copyright (c) 2015 Google, Inc
+# Wolfgang Denk, DENX Software Engineering, wd at denx.de.
+#
+# SPDX-License-Identifier:      GPL-2.0+
+#
+
+obj-$(CONFIG_CLK) += clk-uclass.o
diff --git a/drivers/clk/clk-uclass.c b/drivers/clk/clk-uclass.c
new file mode 100644
index 0000000..73dfd7d
--- /dev/null
+++ b/drivers/clk/clk-uclass.c
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2015 Google, Inc
+ * Written by Simon Glass <sjg at chromium.org>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <clk.h>
+#include <dm.h>
+#include <errno.h>
+#include <dm/lists.h>
+#include <dm/root.h>
+
+ulong clk_get_rate(struct udevice *dev)
+{
+	struct clk_ops *ops = clk_get_ops(dev);
+
+	if (!ops->get_rate)
+		return -ENOSYS;
+
+	return ops->get_rate(dev);
+}
+
+ulong clk_set_rate(struct udevice *dev, ulong rate)
+{
+	struct clk_ops *ops = clk_get_ops(dev);
+
+	if (!ops->set_rate)
+		return -ENOSYS;
+
+	return ops->set_rate(dev, rate);
+}
+
+ulong clk_get_periph_rate(struct udevice *dev, int periph)
+{
+	struct clk_ops *ops = clk_get_ops(dev);
+
+	if (!ops->get_periph_rate)
+		return -ENOSYS;
+
+	return ops->get_periph_rate(dev, periph);
+}
+
+ulong clk_set_periph_rate(struct udevice *dev, int periph, ulong rate)
+{
+	struct clk_ops *ops = clk_get_ops(dev);
+
+	if (!ops->set_periph_rate)
+		return -ENOSYS;
+
+	return ops->set_periph_rate(dev, periph, rate);
+}
+
+UCLASS_DRIVER(clk) = {
+	.id		= UCLASS_CLK,
+	.name		= "clk",
+};
diff --git a/include/clk.h b/include/clk.h
index df4570c..254ad2b 100644
--- a/include/clk.h
+++ b/include/clk.h
@@ -1,6 +1,86 @@
+/*
+ * Copyright (c) 2015 Google, Inc
+ * Written by Simon Glass <sjg at chromium.org>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
 #ifndef _CLK_H_
 #define _CLK_H_
 
 int soc_clk_dump(void);
 
+struct clk_ops {
+	/**
+	 * get_rate() - Get current clock rate
+	 *
+	 * @dev:	Device to check (UCLASS_CLK)
+	 * @return clock rate in Hz, or -ve error code
+	 */
+	ulong (*get_rate)(struct udevice *dev);
+
+	/**
+	 * set_rate() - Set current clock rate
+	 *
+	 * @dev:	Device to adjust
+	 * @rate:	New clock rate in Hz
+	 * @return new rate, or -ve error code
+	 */
+	ulong (*set_rate)(struct udevice *dev, ulong rate);
+
+	/**
+	* clk_set_periph_rate() - Set clock rate for a peripheral
+	*
+	* @dev:	Device to adjust (UCLASS_CLK)
+	* @rate:	New clock rate in Hz
+	* @return new clock rate in Hz, or -ve error code
+	*/
+	ulong (*get_periph_rate)(struct udevice *dev, int periph);
+
+	/**
+	 * clk_set_periph_rate() - Set current clock rate for a peripheral
+	 *
+	 * @dev:	Device to update (UCLASS_CLK)
+	 * @periph:	Peripheral ID to cupdate
+	 * @return new clock rate in Hz, or -ve error code
+	 */
+	ulong (*set_periph_rate)(struct udevice *dev, int periph, ulong rate);
+};
+
+#define clk_get_ops(dev)	((struct clk_ops *)(dev)->driver->ops)
+
+/**
+ * clk_get_rate() - Get current clock rate
+ *
+ * @dev:	Device to check (UCLASS_CLK)
+ * @return clock rate in Hz, or -ve error code
+ */
+ulong clk_get_rate(struct udevice *dev);
+
+/**
+ * set_rate() - Set current clock rate
+ *
+ * @dev:	Device to adjust
+ * @rate:	New clock rate in Hz
+ * @return new rate, or -ve error code
+ */
+ulong clk_set_rate(struct udevice *dev, ulong rate);
+
+/**
+ * clk_get_periph_rate() - Get current clock rate for a peripheral
+ *
+ * @dev:	Device to check (UCLASS_CLK)
+ * @return clock rate in Hz, -ve error code
+ */
+ulong clk_get_periph_rate(struct udevice *dev, int periph);
+
+/**
+ * clk_set_periph_rate() - Set current clock rate for a peripheral
+ *
+ * @dev:	Device to update (UCLASS_CLK)
+ * @periph:	Peripheral ID to cupdate
+ * @return new clock rate in Hz, or -ve error code
+ */
+ulong clk_set_periph_rate(struct udevice *dev, int periph, ulong rate);
+
 #endif /* _CLK_H_ */
diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
index fc486f2..72512b5 100644
--- a/include/dm/uclass-id.h
+++ b/include/dm/uclass-id.h
@@ -25,6 +25,7 @@ enum uclass_id {
 	UCLASS_SIMPLE_BUS,	/* bus with child devices */
 
 	/* U-Boot uclasses start here - in alphabetical order */
+	UCLASS_CLK,		/* Clock source, e.g. used by peripherals */
 	UCLASS_CPU,		/* CPU, typically part of an SoC */
 	UCLASS_CROS_EC,		/* Chrome OS EC */
 	UCLASS_DISPLAY_PORT,	/* Display port video */
diff --git a/scripts/Makefile.spl b/scripts/Makefile.spl
index c4e83bb..9d7ac99 100644
--- a/scripts/Makefile.spl
+++ b/scripts/Makefile.spl
@@ -54,6 +54,7 @@ libs-$(HAVE_VENDOR_COMMON_LIB) += board/$(VENDOR)/common/
 libs-$(CONFIG_SPL_FRAMEWORK) += common/spl/
 libs-$(CONFIG_SPL_LIBCOMMON_SUPPORT) += common/
 libs-$(CONFIG_SPL_LIBDISK_SUPPORT) += disk/
+libs-$(CONFIG_SPL_CLK_SUPPORT) += drivers/clk/
 libs-$(CONFIG_SPL_DM) += drivers/core/
 libs-$(CONFIG_SPL_I2C_SUPPORT) += drivers/i2c/
 libs-$(CONFIG_SPL_GPIO_SUPPORT) += drivers/gpio/
-- 
2.4.3.573.g4eafbef



More information about the U-Boot mailing list