[PATCH] clk: new driver for efm32 SoC

Uwe Kleine-König u.kleine-koenig at pengutronix.de
Wed Aug 14 16:04:53 EDT 2013


Signed-off-by: Uwe Kleine-König <u.kleine-koenig at pengutronix.de>
---
Hello,

I'm not sure if there is a naming convention for #defines in headers below
dt-bindings. I named my clocks clk_$namefromreferencemanual to have some
namespacing.

The clock stuff on the different variants of efm32 are similar, but
different enough to not be able to use the same driver, so this is only
for the Giant Gecko (efm32gg) variant, still I used "efm32" in some
places because the other variants would fit there, too. (For
include/dt-bindings/clock/efm32-cmu.h I would need some #ifdefs, is that
OK or should the name of the defines include efm32gg? (That would make
the names still longer and so more ugly.))

Best regards
Uwe

 .../devicetree/bindings/clock/efm32-clock.txt      | 11 +++
 drivers/clk/Makefile                               |  1 +
 drivers/clk/clk-efm32gg.c                          | 79 ++++++++++++++++++++++
 include/dt-bindings/clock/efm32-cmu.h              | 42 ++++++++++++
 include/linux/clk/efm32.h                          |  6 ++
 5 files changed, 139 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/clock/efm32-clock.txt
 create mode 100644 drivers/clk/clk-efm32gg.c
 create mode 100644 include/dt-bindings/clock/efm32-cmu.h
 create mode 100644 include/linux/clk/efm32.h

diff --git a/Documentation/devicetree/bindings/clock/efm32-clock.txt b/Documentation/devicetree/bindings/clock/efm32-clock.txt
new file mode 100644
index 0000000..263d293
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/efm32-clock.txt
@@ -0,0 +1,11 @@
+* Clock bindings for Energy Micro efm32 Giant Gecko's Clock Management Unit
+
+Required properties:
+- compatible: Should be "efm32gg,cmu"
+- reg: Base address and length of the register set
+- interrupts: Interrupt used by the CMU
+- #clock-cells: Should be <1>
+
+The clock consumer should specify the desired clock by having the clock ID in
+its "clocks" phandle cell. The header efm32-clk.h contains a list of available
+IDs.
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index 4038c2b..99d9ad0 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -11,6 +11,7 @@ obj-$(CONFIG_COMMON_CLK)	+= clk-composite.o
 
 # SoCs specific
 obj-$(CONFIG_ARCH_BCM2835)	+= clk-bcm2835.o
+obj-$(CONFIG_ARCH_EFM32)	+= clk-efm32gg.o
 obj-$(CONFIG_ARCH_NOMADIK)	+= clk-nomadik.o
 obj-$(CONFIG_ARCH_HIGHBANK)	+= clk-highbank.o
 obj-$(CONFIG_ARCH_NSPIRE)	+= clk-nspire.o
diff --git a/drivers/clk/clk-efm32gg.c b/drivers/clk/clk-efm32gg.c
new file mode 100644
index 0000000..2e63584
--- /dev/null
+++ b/drivers/clk/clk-efm32gg.c
@@ -0,0 +1,79 @@
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/clk-provider.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+
+#include <dt-bindings/clock/efm32-cmu.h>
+
+#define CMU_HFPERCLKEN0		0x44
+
+static struct clk *clk[37];
+static struct clk_onecell_data clk_data = {
+	.clks = clk,
+	.clk_num = ARRAY_SIZE(clk),
+};
+
+int __init efm32gg_clk_init(void)
+{
+	int i;
+	struct device_node *np;
+	void __iomem *base;
+
+	for (i = 0; i < ARRAY_SIZE(clk); ++i)
+		clk[i] = ERR_PTR(-ENOENT);
+
+	np = of_find_compatible_node(NULL, NULL, "efm32gg,cmu");
+	if (!np) {
+		pr_warn("No efm32gg,cmu node found in device tree\n");
+		return -ENOENT;
+	}
+
+	base = of_iomap(np, 0);
+	if (!base) {
+		pr_warn("Failed to map address range for efm32gg,cmu node\n");
+		return -EADDRNOTAVAIL;
+	}
+
+	clk[clk_HFXO] = clk_register_fixed_rate(NULL, "HFXO", NULL,
+			CLK_IS_ROOT, 48000000);
+
+	clk[clk_HFPERCLKUSART0] = clk_register_gate(NULL, "HFPERCLK.USART0",
+			"HFXO", 0, base + CMU_HFPERCLKEN0, 0, 0, NULL);
+	clk[clk_HFPERCLKUSART1] = clk_register_gate(NULL, "HFPERCLK.USART1",
+			"HFXO", 0, base + CMU_HFPERCLKEN0, 1, 0, NULL);
+	clk[clk_HFPERCLKUSART2] = clk_register_gate(NULL, "HFPERCLK.USART2",
+			"HFXO", 0, base + CMU_HFPERCLKEN0, 2, 0, NULL);
+	clk[clk_HFPERCLKUART0] = clk_register_gate(NULL, "HFPERCLK.UART0",
+			"HFXO", 0, base + CMU_HFPERCLKEN0, 3, 0, NULL);
+	clk[clk_HFPERCLKUART1] = clk_register_gate(NULL, "HFPERCLK.UART1",
+			"HFXO", 0, base + CMU_HFPERCLKEN0, 4, 0, NULL);
+	clk[clk_HFPERCLKTIMER0] = clk_register_gate(NULL, "HFPERCLK.TIMER0",
+			"HFXO", 0, base + CMU_HFPERCLKEN0, 5, 0, NULL);
+	clk[clk_HFPERCLKTIMER1] = clk_register_gate(NULL, "HFPERCLK.TIMER1",
+			"HFXO", 0, base + CMU_HFPERCLKEN0, 6, 0, NULL);
+	clk[clk_HFPERCLKTIMER2] = clk_register_gate(NULL, "HFPERCLK.TIMER2",
+			"HFXO", 0, base + CMU_HFPERCLKEN0, 7, 0, NULL);
+	clk[clk_HFPERCLKTIMER3] = clk_register_gate(NULL, "HFPERCLK.TIMER3",
+			"HFXO", 0, base + CMU_HFPERCLKEN0, 8, 0, NULL);
+	clk[clk_HFPERCLKACMP0] = clk_register_gate(NULL, "HFPERCLK.ACMP0",
+			"HFXO", 0, base + CMU_HFPERCLKEN0, 9, 0, NULL);
+	clk[clk_HFPERCLKACMP1] = clk_register_gate(NULL, "HFPERCLK.ACMP1",
+			"HFXO", 0, base + CMU_HFPERCLKEN0, 10, 0, NULL);
+	clk[clk_HFPERCLKI2C0] = clk_register_gate(NULL, "HFPERCLK.I2C0",
+			"HFXO", 0, base + CMU_HFPERCLKEN0, 11, 0, NULL);
+	clk[clk_HFPERCLKI2C1] = clk_register_gate(NULL, "HFPERCLK.I2C1",
+			"HFXO", 0, base + CMU_HFPERCLKEN0, 12, 0, NULL);
+	clk[clk_HFPERCLKGPIO] = clk_register_gate(NULL, "HFPERCLK.GPIO",
+			"HFXO", 0, base + CMU_HFPERCLKEN0, 13, 0, NULL);
+	clk[clk_HFPERCLKVCMP] = clk_register_gate(NULL, "HFPERCLK.VCMP",
+			"HFXO", 0, base + CMU_HFPERCLKEN0, 14, 0, NULL);
+	clk[clk_HFPERCLKPRS] = clk_register_gate(NULL, "HFPERCLK.PRS",
+			"HFXO", 0, base + CMU_HFPERCLKEN0, 15, 0, NULL);
+	clk[clk_HFPERCLKADC0] = clk_register_gate(NULL, "HFPERCLK.ADC0",
+			"HFXO", 0, base + CMU_HFPERCLKEN0, 16, 0, NULL);
+	clk[clk_HFPERCLKDAC0] = clk_register_gate(NULL, "HFPERCLK.DAC0",
+			"HFXO", 0, base + CMU_HFPERCLKEN0, 17, 0, NULL);
+
+	return of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
+}
diff --git a/include/dt-bindings/clock/efm32-cmu.h b/include/dt-bindings/clock/efm32-cmu.h
new file mode 100644
index 0000000..b21b91e
--- /dev/null
+++ b/include/dt-bindings/clock/efm32-cmu.h
@@ -0,0 +1,42 @@
+#ifndef __DT_BINDINGS_CLOCK_EFM32_CMU_H
+#define __DT_BINDINGS_CLOCK_EFM32_CMU_H
+
+#define clk_HFXO		0
+#define clk_HFRCO		1
+#define clk_LFXO		2
+#define clk_LFRCO		3
+#define clk_ULFRCO		4
+#define clk_AUXHFRCO		5
+#define clk_HFCLKNODIV		6
+#define clk_HFCLK		7
+#define clk_HFPERCLK		8
+#define clk_HFCORECLK		9
+#define clk_LFACLK		10
+#define clk_LFBCLK		11
+#define clk_WDOGCLK		12
+#define clk_HFCORECLKDMA	13
+#define clk_HFCORECLKAES	14
+#define clk_HFCORECLKUSBC	15
+#define clk_HFCORECLKUSB	16
+#define clk_HFCORECLKLE		17
+#define clk_HFCORECLKEBI	18
+#define clk_HFPERCLKUSART0	19
+#define clk_HFPERCLKUSART1	20
+#define clk_HFPERCLKUSART2	21
+#define clk_HFPERCLKUART0	22
+#define clk_HFPERCLKUART1	23
+#define clk_HFPERCLKTIMER0	24
+#define clk_HFPERCLKTIMER1	25
+#define clk_HFPERCLKTIMER2	26
+#define clk_HFPERCLKTIMER3	27
+#define clk_HFPERCLKACMP0	28
+#define clk_HFPERCLKACMP1	29
+#define clk_HFPERCLKI2C0	30
+#define clk_HFPERCLKI2C1	31
+#define clk_HFPERCLKGPIO	32
+#define clk_HFPERCLKVCMP	33
+#define clk_HFPERCLKPRS		34
+#define clk_HFPERCLKADC0	35
+#define clk_HFPERCLKDAC0	36
+
+#endif /* __DT_BINDINGS_CLOCK_EFM32_CMU_H */
diff --git a/include/linux/clk/efm32.h b/include/linux/clk/efm32.h
new file mode 100644
index 0000000..4032dc0
--- /dev/null
+++ b/include/linux/clk/efm32.h
@@ -0,0 +1,6 @@
+#ifndef __LINUX_CLK_EFM32_H__
+#define __LINUX_CLK_EFM32_H__
+
+int efm32gg_clk_init(void);
+
+#endif /* __LINUX_CLK_EFM32_H__ */
-- 
1.8.4.rc0




More information about the linux-arm-kernel mailing list