All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 0/4] Clk drivers for NXP LPC18xx family
@ 2015-04-27 21:38 ` Joachim Eastwood
  0 siblings, 0 replies; 39+ messages in thread
From: Joachim Eastwood @ 2015-04-27 21:38 UTC (permalink / raw)
  To: mturquette-QSEj5FYQhm4dnm+yROfE0A, sboyd-sgV2jX0FEOL9JmXXK+q4OQ,
	arnd-r2nGTMty4D4, linux-clk-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
  Cc: devicetree-u79uwXL29TY76Z2rM5mHXA,
	ariel.dalessandro-Re5JQEeQqe8AvxtiuMwx3w,
	ezequiel-30ULvvUtt6G51wMPkGsGjgyUoB5FGQPZ, Joachim Eastwood

This patch set adds support for the two main clock peripherals in the
LPC18xx/43xx MCU family.

The Clock Generation Unit (CGU) is the base source of all clocks. It has
five external inputs and contains PLLs, dividers and muxes. The outputs
from the CGU are then routed to a Clock Control Unit (CCU) and a few
peripherals directly. There are two CCUs in the MCU. The CCU is a
collection of gates and a few dividers that sits between the CGU and
most of the peripherals.

Which clocks that are available depends on the specific device and it's
peripherals. It's possible in DT to setup the routing between the CGU
and the CCUs.

Changes since v1:
 - reorganize cgu clk structs
 - macros to create cgu clk structs
 - move drivers to nxp subdir
 - rebase on v4.1-rc1

Since there were no comments on v1. I hope that these drivers can
make it to Linux 4.1.

There are no dependencies in this patch set. The DTS changes will
be sent separately to arm-soc once this patch set goes upstream.

See the base support patch set for LPC18xx here:
http://marc.info/?l=linux-arm-kernel&m=143016894704253&w=2

Joachim Eastwood (4):
  clk: add lpc18xx cgu clk driver
  doc: dt: add documentation for lpc1850-cgu clk driver
  clk: add lpc18xx ccu clk driver
  doc: dt: add documentation for lpc1850-ccu clk driver

 .../devicetree/bindings/clock/lpc1850-ccu.txt      | 146 +++++
 .../devicetree/bindings/clock/lpc1850-cgu.txt      | 138 +++++
 drivers/clk/Makefile                               |   1 +
 drivers/clk/nxp/Makefile                           |   2 +
 drivers/clk/nxp/clk-lpc18xx-ccu.c                  | 318 +++++++++++
 drivers/clk/nxp/clk-lpc18xx-cgu.c                  | 628 +++++++++++++++++++++
 include/dt-bindings/clock/lpc18xx-ccu.h            |  74 +++
 include/dt-bindings/clock/lpc18xx-cgu.h            |  41 ++
 8 files changed, 1348 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/clock/lpc1850-ccu.txt
 create mode 100644 Documentation/devicetree/bindings/clock/lpc1850-cgu.txt
 create mode 100644 drivers/clk/nxp/Makefile
 create mode 100644 drivers/clk/nxp/clk-lpc18xx-ccu.c
 create mode 100644 drivers/clk/nxp/clk-lpc18xx-cgu.c
 create mode 100644 include/dt-bindings/clock/lpc18xx-ccu.h
 create mode 100644 include/dt-bindings/clock/lpc18xx-cgu.h

-- 
1.8.0

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 39+ messages in thread

* [PATCH v2 0/4] Clk drivers for NXP LPC18xx family
@ 2015-04-27 21:38 ` Joachim Eastwood
  0 siblings, 0 replies; 39+ messages in thread
From: Joachim Eastwood @ 2015-04-27 21:38 UTC (permalink / raw)
  To: mturquette, sboyd, arnd, linux-clk, linux-arm-kernel
  Cc: devicetree, ariel.dalessandro, ezequiel, Joachim Eastwood

This patch set adds support for the two main clock peripherals in the
LPC18xx/43xx MCU family.

The Clock Generation Unit (CGU) is the base source of all clocks. It has
five external inputs and contains PLLs, dividers and muxes. The outputs
from the CGU are then routed to a Clock Control Unit (CCU) and a few
peripherals directly. There are two CCUs in the MCU. The CCU is a
collection of gates and a few dividers that sits between the CGU and
most of the peripherals.

Which clocks that are available depends on the specific device and it's
peripherals. It's possible in DT to setup the routing between the CGU
and the CCUs.

Changes since v1:
 - reorganize cgu clk structs
 - macros to create cgu clk structs
 - move drivers to nxp subdir
 - rebase on v4.1-rc1

Since there were no comments on v1. I hope that these drivers can
make it to Linux 4.1.

There are no dependencies in this patch set. The DTS changes will
be sent separately to arm-soc once this patch set goes upstream.

See the base support patch set for LPC18xx here:
http://marc.info/?l=linux-arm-kernel&m=143016894704253&w=2

Joachim Eastwood (4):
  clk: add lpc18xx cgu clk driver
  doc: dt: add documentation for lpc1850-cgu clk driver
  clk: add lpc18xx ccu clk driver
  doc: dt: add documentation for lpc1850-ccu clk driver

 .../devicetree/bindings/clock/lpc1850-ccu.txt      | 146 +++++
 .../devicetree/bindings/clock/lpc1850-cgu.txt      | 138 +++++
 drivers/clk/Makefile                               |   1 +
 drivers/clk/nxp/Makefile                           |   2 +
 drivers/clk/nxp/clk-lpc18xx-ccu.c                  | 318 +++++++++++
 drivers/clk/nxp/clk-lpc18xx-cgu.c                  | 628 +++++++++++++++++++++
 include/dt-bindings/clock/lpc18xx-ccu.h            |  74 +++
 include/dt-bindings/clock/lpc18xx-cgu.h            |  41 ++
 8 files changed, 1348 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/clock/lpc1850-ccu.txt
 create mode 100644 Documentation/devicetree/bindings/clock/lpc1850-cgu.txt
 create mode 100644 drivers/clk/nxp/Makefile
 create mode 100644 drivers/clk/nxp/clk-lpc18xx-ccu.c
 create mode 100644 drivers/clk/nxp/clk-lpc18xx-cgu.c
 create mode 100644 include/dt-bindings/clock/lpc18xx-ccu.h
 create mode 100644 include/dt-bindings/clock/lpc18xx-cgu.h

-- 
1.8.0

^ permalink raw reply	[flat|nested] 39+ messages in thread

* [PATCH v2 0/4] Clk drivers for NXP LPC18xx family
@ 2015-04-27 21:38 ` Joachim Eastwood
  0 siblings, 0 replies; 39+ messages in thread
From: Joachim Eastwood @ 2015-04-27 21:38 UTC (permalink / raw)
  To: linux-arm-kernel

This patch set adds support for the two main clock peripherals in the
LPC18xx/43xx MCU family.

The Clock Generation Unit (CGU) is the base source of all clocks. It has
five external inputs and contains PLLs, dividers and muxes. The outputs
from the CGU are then routed to a Clock Control Unit (CCU) and a few
peripherals directly. There are two CCUs in the MCU. The CCU is a
collection of gates and a few dividers that sits between the CGU and
most of the peripherals.

Which clocks that are available depends on the specific device and it's
peripherals. It's possible in DT to setup the routing between the CGU
and the CCUs.

Changes since v1:
 - reorganize cgu clk structs
 - macros to create cgu clk structs
 - move drivers to nxp subdir
 - rebase on v4.1-rc1

Since there were no comments on v1. I hope that these drivers can
make it to Linux 4.1.

There are no dependencies in this patch set. The DTS changes will
be sent separately to arm-soc once this patch set goes upstream.

See the base support patch set for LPC18xx here:
http://marc.info/?l=linux-arm-kernel&m=143016894704253&w=2

Joachim Eastwood (4):
  clk: add lpc18xx cgu clk driver
  doc: dt: add documentation for lpc1850-cgu clk driver
  clk: add lpc18xx ccu clk driver
  doc: dt: add documentation for lpc1850-ccu clk driver

 .../devicetree/bindings/clock/lpc1850-ccu.txt      | 146 +++++
 .../devicetree/bindings/clock/lpc1850-cgu.txt      | 138 +++++
 drivers/clk/Makefile                               |   1 +
 drivers/clk/nxp/Makefile                           |   2 +
 drivers/clk/nxp/clk-lpc18xx-ccu.c                  | 318 +++++++++++
 drivers/clk/nxp/clk-lpc18xx-cgu.c                  | 628 +++++++++++++++++++++
 include/dt-bindings/clock/lpc18xx-ccu.h            |  74 +++
 include/dt-bindings/clock/lpc18xx-cgu.h            |  41 ++
 8 files changed, 1348 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/clock/lpc1850-ccu.txt
 create mode 100644 Documentation/devicetree/bindings/clock/lpc1850-cgu.txt
 create mode 100644 drivers/clk/nxp/Makefile
 create mode 100644 drivers/clk/nxp/clk-lpc18xx-ccu.c
 create mode 100644 drivers/clk/nxp/clk-lpc18xx-cgu.c
 create mode 100644 include/dt-bindings/clock/lpc18xx-ccu.h
 create mode 100644 include/dt-bindings/clock/lpc18xx-cgu.h

-- 
1.8.0

^ permalink raw reply	[flat|nested] 39+ messages in thread

* [PATCH v2 1/4] clk: add lpc18xx cgu clk driver
  2015-04-27 21:38 ` Joachim Eastwood
  (?)
@ 2015-04-27 21:38     ` Joachim Eastwood
  -1 siblings, 0 replies; 39+ messages in thread
From: Joachim Eastwood @ 2015-04-27 21:38 UTC (permalink / raw)
  To: mturquette-QSEj5FYQhm4dnm+yROfE0A, sboyd-sgV2jX0FEOL9JmXXK+q4OQ,
	arnd-r2nGTMty4D4, linux-clk-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
  Cc: devicetree-u79uwXL29TY76Z2rM5mHXA,
	ariel.dalessandro-Re5JQEeQqe8AvxtiuMwx3w,
	ezequiel-30ULvvUtt6G51wMPkGsGjgyUoB5FGQPZ, Joachim Eastwood

Add driver for NXP LPC18xx/43xx Clock Generation Unit (CGU). The CGU
contains several clock generators and output stages that route the
clocks either directly to peripherals or to a Clock Control Unit
(CCU).

Signed-off-by: Joachim Eastwood <manabian-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
---
 drivers/clk/Makefile                    |   1 +
 drivers/clk/nxp/Makefile                |   1 +
 drivers/clk/nxp/clk-lpc18xx-cgu.c       | 628 ++++++++++++++++++++++++++++++++
 include/dt-bindings/clock/lpc18xx-cgu.h |  41 +++
 4 files changed, 671 insertions(+)
 create mode 100644 drivers/clk/nxp/Makefile
 create mode 100644 drivers/clk/nxp/clk-lpc18xx-cgu.c
 create mode 100644 include/dt-bindings/clock/lpc18xx-cgu.h

diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index 3d00c25382c5..4a34419c1da1 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -56,6 +56,7 @@ obj-$(CONFIG_ARCH_MMP)			+= mmp/
 endif
 obj-$(CONFIG_PLAT_ORION)		+= mvebu/
 obj-$(CONFIG_ARCH_MXS)			+= mxs/
+obj-$(CONFIG_ARCH_LPC18XX)		+= nxp/
 obj-$(CONFIG_MACH_PISTACHIO)		+= pistachio/
 obj-$(CONFIG_COMMON_CLK_PXA)		+= pxa/
 obj-$(CONFIG_COMMON_CLK_QCOM)		+= qcom/
diff --git a/drivers/clk/nxp/Makefile b/drivers/clk/nxp/Makefile
new file mode 100644
index 000000000000..aca9d3e4f7fe
--- /dev/null
+++ b/drivers/clk/nxp/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_ARCH_LPC18XX)	+= clk-lpc18xx-cgu.o
diff --git a/drivers/clk/nxp/clk-lpc18xx-cgu.c b/drivers/clk/nxp/clk-lpc18xx-cgu.c
new file mode 100644
index 000000000000..15977f5d767f
--- /dev/null
+++ b/drivers/clk/nxp/clk-lpc18xx-cgu.c
@@ -0,0 +1,628 @@
+/*
+ * Clk driver for NXP LPC18xx/LPC43xx Clock Generation Unit (CGU)
+ *
+ * Copyright (C) 2015 Joachim Eastwood <manabian-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/delay.h>
+#include <linux/kernel.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+
+#include <dt-bindings/clock/lpc18xx-cgu.h>
+
+/* Clock Generation Unit (CGU) registers */
+#define LPC18XX_CGU_XTAL_OSC_CTRL	0x018
+#define LPC18XX_CGU_PLL0USB_STAT	0x01c
+#define LPC18XX_CGU_PLL0USB_CTRL	0x020
+#define LPC18XX_CGU_PLL0USB_MDIV	0x024
+#define LPC18XX_CGU_PLL0USB_NP_DIV	0x028
+#define LPC18XX_CGU_PLL0AUDIO_STAT	0x02c
+#define LPC18XX_CGU_PLL0AUDIO_CTRL	0x030
+#define LPC18XX_CGU_PLL0AUDIO_MDIV	0x034
+#define LPC18XX_CGU_PLL0AUDIO_NP_DIV	0x038
+#define LPC18XX_CGU_PLL0AUDIO_FRAC	0x03c
+#define LPC18XX_CGU_PLL1_STAT		0x040
+#define LPC18XX_CGU_PLL1_CTRL		0x044
+#define  LPC18XX_PLL1_CTRL_FBSEL	BIT(6)
+#define  LPC18XX_PLL1_CTRL_DIRECT	BIT(7)
+#define LPC18XX_CGU_IDIV_CTRL(n)	(0x048 + (n) * sizeof(u32))
+#define LPC18XX_CGU_BASE_CLK(id)	(0x05c + (id) * sizeof(u32))
+#define LPC18XX_CGU_PLL_CTRL_OFFSET	0x4
+
+/* PLL0 bits common to both audio and USB PLL */
+#define LPC18XX_PLL0_STAT_LOCK		BIT(0)
+#define LPC18XX_PLL0_CTRL_PD		BIT(0)
+#define LPC18XX_PLL0_CTRL_BYPASS	BIT(1)
+#define LPC18XX_PLL0_CTRL_DIRECTI	BIT(2)
+#define LPC18XX_PLL0_CTRL_DIRECTO	BIT(3)
+#define LPC18XX_PLL0_CTRL_CLKEN		BIT(4)
+#define LPC18XX_PLL0_MDIV_MDEC_MASK	0x1ffff
+#define LPC18XX_PLL0_MDIV_SELP_SHIFT	17
+#define LPC18XX_PLL0_MDIV_SELI_SHIFT	22
+#define LPC18XX_PLL0_MSEL_MAX		BIT(15)
+
+/* Register value that gives PLL0 post/pre dividers equal to 1 */
+#define LPC18XX_PLL0_NP_DIVS_1		0x00302062
+
+enum {
+	CLK_SRC_OSC32,
+	CLK_SRC_IRC,
+	CLK_SRC_ENET_RX_CLK,
+	CLK_SRC_ENET_TX_CLK,
+	CLK_SRC_GP_CLKIN,
+	CLK_SRC_RESERVED1,
+	CLK_SRC_OSC,
+	CLK_SRC_PLL0USB,
+	CLK_SRC_PLL0AUDIO,
+	CLK_SRC_PLL1,
+	CLK_SRC_RESERVED2,
+	CLK_SRC_RESERVED3,
+	CLK_SRC_IDIVA,
+	CLK_SRC_IDIVB,
+	CLK_SRC_IDIVC,
+	CLK_SRC_IDIVD,
+	CLK_SRC_IDIVE,
+	CLK_SRC_MAX
+};
+
+static const char *clk_src_names[CLK_SRC_MAX] = {
+	[CLK_SRC_OSC32]		= "osc32",
+	[CLK_SRC_IRC]		= "irc",
+	[CLK_SRC_ENET_RX_CLK]	= "enet_rx_clk",
+	[CLK_SRC_ENET_TX_CLK]	= "enet_tx_clk",
+	[CLK_SRC_GP_CLKIN]	= "gp_clkin",
+	[CLK_SRC_OSC]		= "osc",
+	[CLK_SRC_PLL0USB]	= "pll0usb",
+	[CLK_SRC_PLL0AUDIO]	= "pll0audio",
+	[CLK_SRC_PLL1]		= "pll1",
+	[CLK_SRC_IDIVA]		= "idiva",
+	[CLK_SRC_IDIVB]		= "idivb",
+	[CLK_SRC_IDIVC]		= "idivc",
+	[CLK_SRC_IDIVD]		= "idivd",
+	[CLK_SRC_IDIVE]		= "idive",
+};
+
+static const char *clk_base_names[BASE_CLK_MAX];
+
+static u32 lpc18xx_cgu_pll0_src_ids[] = {
+	CLK_SRC_OSC32, CLK_SRC_IRC, CLK_SRC_ENET_RX_CLK,
+	CLK_SRC_ENET_TX_CLK, CLK_SRC_GP_CLKIN, CLK_SRC_OSC,
+	CLK_SRC_PLL1, CLK_SRC_IDIVA, CLK_SRC_IDIVB, CLK_SRC_IDIVC,
+	CLK_SRC_IDIVD, CLK_SRC_IDIVE,
+};
+
+static u32 lpc18xx_cgu_pll1_src_ids[] = {
+	CLK_SRC_OSC32, CLK_SRC_IRC, CLK_SRC_ENET_RX_CLK,
+	CLK_SRC_ENET_TX_CLK, CLK_SRC_GP_CLKIN, CLK_SRC_OSC,
+	CLK_SRC_PLL0USB, CLK_SRC_PLL0AUDIO, CLK_SRC_IDIVA,
+	CLK_SRC_IDIVB, CLK_SRC_IDIVC, CLK_SRC_IDIVD, CLK_SRC_IDIVE,
+};
+
+static u32 lpc18xx_cgu_idiva_src_ids[] = {
+	CLK_SRC_OSC32, CLK_SRC_IRC, CLK_SRC_ENET_RX_CLK,
+	CLK_SRC_ENET_TX_CLK, CLK_SRC_GP_CLKIN, CLK_SRC_OSC,
+	CLK_SRC_PLL0USB, CLK_SRC_PLL0AUDIO, CLK_SRC_PLL1
+};
+
+static u32 lpc18xx_cgu_idivbcde_src_ids[] = {
+	CLK_SRC_OSC32, CLK_SRC_IRC, CLK_SRC_ENET_RX_CLK,
+	CLK_SRC_ENET_TX_CLK, CLK_SRC_GP_CLKIN, CLK_SRC_OSC,
+	CLK_SRC_PLL0AUDIO, CLK_SRC_PLL1, CLK_SRC_IDIVA,
+};
+
+static u32 lpc18xx_cgu_base_irc_src_ids[] = {CLK_SRC_IRC};
+
+static u32 lpc18xx_cgu_base_usb0_src_ids[] = {CLK_SRC_PLL0USB};
+
+static u32 lpc18xx_cgu_base_common_src_ids[] = {
+	CLK_SRC_OSC32, CLK_SRC_IRC, CLK_SRC_ENET_RX_CLK,
+	CLK_SRC_ENET_TX_CLK, CLK_SRC_GP_CLKIN, CLK_SRC_OSC,
+	CLK_SRC_PLL0AUDIO, CLK_SRC_PLL1, CLK_SRC_IDIVA,
+	CLK_SRC_IDIVB, CLK_SRC_IDIVC, CLK_SRC_IDIVD, CLK_SRC_IDIVE,
+};
+
+static u32 lpc18xx_cgu_base_all_src_ids[] = {
+	CLK_SRC_OSC32, CLK_SRC_IRC, CLK_SRC_ENET_RX_CLK,
+	CLK_SRC_ENET_TX_CLK, CLK_SRC_GP_CLKIN, CLK_SRC_OSC,
+	CLK_SRC_PLL0USB, CLK_SRC_PLL0AUDIO, CLK_SRC_PLL1,
+	CLK_SRC_IDIVA, CLK_SRC_IDIVB, CLK_SRC_IDIVC,
+	CLK_SRC_IDIVD, CLK_SRC_IDIVE,
+};
+
+struct lpc18xx_cgu_src_clk_div {
+	u8 clk_id;
+	u8 n_parents;
+	struct clk_divider	div;
+	struct clk_mux		mux;
+	struct clk_gate		gate;
+};
+
+#define LPC1XX_CGU_SRC_CLK_DIV(_id, _width, _table)	\
+{							\
+	.clk_id = CLK_SRC_ ##_id,			\
+	.n_parents = ARRAY_SIZE(lpc18xx_cgu_ ##_table),	\
+	.div = {					\
+		.shift = 2,				\
+		.width = _width,			\
+	},						\
+	.mux = {					\
+		.mask = 0x1f,				\
+		.shift = 24,				\
+		.table = lpc18xx_cgu_ ##_table,		\
+	},						\
+	.gate = {					\
+		.bit_idx = 0,				\
+		.flags = CLK_GATE_SET_TO_DISABLE,	\
+	},						\
+}
+
+static struct lpc18xx_cgu_src_clk_div lpc18xx_cgu_src_clk_divs[] = {
+	LPC1XX_CGU_SRC_CLK_DIV(IDIVA, 2, idiva_src_ids),
+	LPC1XX_CGU_SRC_CLK_DIV(IDIVB, 4, idivbcde_src_ids),
+	LPC1XX_CGU_SRC_CLK_DIV(IDIVC, 4, idivbcde_src_ids),
+	LPC1XX_CGU_SRC_CLK_DIV(IDIVD, 4, idivbcde_src_ids),
+	LPC1XX_CGU_SRC_CLK_DIV(IDIVE, 8, idivbcde_src_ids),
+};
+
+struct lpc18xx_cgu_base_clk {
+	u8 clk_id;
+	u8 n_parents;
+	struct clk_mux mux;
+	struct clk_gate gate;
+};
+
+#define LPC1XX_CGU_BASE_CLK(_id, _table, _flags)	\
+{							\
+	.clk_id = BASE_ ##_id ##_CLK,			\
+	.n_parents = ARRAY_SIZE(lpc18xx_cgu_ ##_table),	\
+	.mux = {					\
+		.mask = 0x1f,				\
+		.shift = 24,				\
+		.table = lpc18xx_cgu_ ##_table,		\
+		.flags = _flags,			\
+	},						\
+	.gate = {					\
+		.bit_idx = 0,				\
+		.flags = CLK_GATE_SET_TO_DISABLE,	\
+	},						\
+}
+
+static struct lpc18xx_cgu_base_clk lpc18xx_cgu_base_clks[] = {
+	LPC1XX_CGU_BASE_CLK(SAFE,	base_irc_src_ids, CLK_MUX_READ_ONLY),
+	LPC1XX_CGU_BASE_CLK(USB0,	base_usb0_src_ids,   0),
+	LPC1XX_CGU_BASE_CLK(PERIPH,	base_common_src_ids, 0),
+	LPC1XX_CGU_BASE_CLK(USB1,	base_all_src_ids,    0),
+	LPC1XX_CGU_BASE_CLK(CPU,	base_common_src_ids, 0),
+	LPC1XX_CGU_BASE_CLK(SPIFI,	base_common_src_ids, 0),
+	LPC1XX_CGU_BASE_CLK(SPI,	base_common_src_ids, 0),
+	LPC1XX_CGU_BASE_CLK(PHY_RX,	base_common_src_ids, 0),
+	LPC1XX_CGU_BASE_CLK(PHY_TX,	base_common_src_ids, 0),
+	LPC1XX_CGU_BASE_CLK(APB1,	base_common_src_ids, 0),
+	LPC1XX_CGU_BASE_CLK(APB3,	base_common_src_ids, 0),
+	LPC1XX_CGU_BASE_CLK(LCD,	base_common_src_ids, 0),
+	LPC1XX_CGU_BASE_CLK(ADCHS,	base_common_src_ids, 0),
+	LPC1XX_CGU_BASE_CLK(SDIO,	base_common_src_ids, 0),
+	LPC1XX_CGU_BASE_CLK(SSP0,	base_common_src_ids, 0),
+	LPC1XX_CGU_BASE_CLK(SSP1,	base_common_src_ids, 0),
+	LPC1XX_CGU_BASE_CLK(UART0,	base_common_src_ids, 0),
+	LPC1XX_CGU_BASE_CLK(UART1,	base_common_src_ids, 0),
+	LPC1XX_CGU_BASE_CLK(UART2,	base_common_src_ids, 0),
+	LPC1XX_CGU_BASE_CLK(UART3,	base_common_src_ids, 0),
+	LPC1XX_CGU_BASE_CLK(OUT,	base_all_src_ids,    0),
+	{ /* 21 reserved */ },
+	{ /* 22 reserved */ },
+	{ /* 23 reserved */ },
+	{ /* 24 reserved */ },
+	LPC1XX_CGU_BASE_CLK(AUDIO,	base_common_src_ids, 0),
+	LPC1XX_CGU_BASE_CLK(CGU_OUT0,	base_all_src_ids,    0),
+	LPC1XX_CGU_BASE_CLK(CGU_OUT1,	base_all_src_ids,    0),
+};
+
+struct lpc18xx_pll {
+	struct		clk_hw hw;
+	void __iomem	*reg;
+	spinlock_t	*lock;
+	u8		flags;
+};
+
+#define to_lpc_pll(hw) container_of(hw, struct lpc18xx_pll, hw)
+
+struct lpc18xx_cgu_pll_clk {
+	u8 clk_id;
+	u8 n_parents;
+	u8 reg_offset;
+	struct clk_mux mux;
+	struct clk_gate gate;
+	struct lpc18xx_pll pll;
+	const struct clk_ops *pll_ops;
+};
+
+#define LPC1XX_CGU_CLK_PLL(_id, _table, _pll_ops)	\
+{							\
+	.clk_id = CLK_SRC_ ##_id,			\
+	.n_parents = ARRAY_SIZE(lpc18xx_cgu_ ##_table),	\
+	.reg_offset = LPC18XX_CGU_ ##_id ##_STAT,	\
+	.mux = {					\
+		.mask = 0x1f,				\
+		.shift = 24,				\
+		.table = lpc18xx_cgu_ ##_table,		\
+	},						\
+	.gate = {					\
+		.bit_idx = 0,				\
+		.flags = CLK_GATE_SET_TO_DISABLE,	\
+	},						\
+	.pll_ops = &lpc18xx_ ##_pll_ops,		\
+}
+
+/*
+ * PLL0 uses a special register value encoding. The compute functions below
+ * are taken or derived from the LPC1850 user manual (section 12.6.3.3).
+ */
+
+/* Compute PLL0 multiplier from decoded version */
+static u32 lpc18xx_pll0_mdec2msel(u32 x)
+{
+	int i;
+
+	switch (x) {
+	case 0x18003: return 1;
+	case 0x10003: return 2;
+	default:
+		for (i = LPC18XX_PLL0_MSEL_MAX + 1; x != 0x4000 && i > 0; i--)
+			x = ((x ^ x >> 14) & 1) | (x << 1 & 0x7fff);
+		return i;
+	}
+}
+/* Compute PLL0 decoded multiplier from binary version */
+static u32 lpc18xx_pll0_msel2mdec(u32 msel)
+{
+	u32 i, x = 0x4000;
+
+	switch (msel) {
+	case 0: return 0;
+	case 1: return 0x18003;
+	case 2: return 0x10003;
+	default:
+		for (i = msel; i <= LPC18XX_PLL0_MSEL_MAX; i++)
+			x = ((x ^ x >> 1) & 1) << 14 | (x >> 1 & 0xffff);
+		return x;
+	}
+}
+
+/* Compute PLL0 bandwidth SELI reg from multiplier */
+static u32 lpc18xx_pll0_msel2seli(u32 msel)
+{
+	u32 tmp;
+
+	if (msel > 16384) return 1;
+	if (msel >  8192) return 2;
+	if (msel >  2048) return 4;
+	if (msel >=  501) return 8;
+	if (msel >=   60) {
+		tmp = 1024 / (msel + 9);
+		return ((1024 == (tmp * (msel + 9))) == 0) ? tmp * 4 : (tmp + 1) * 4;
+	}
+
+	return (msel & 0x3c) + 4;
+}
+
+/* Compute PLL0 bandwidth SELP reg from multiplier */
+static u32 lpc18xx_pll0_msel2selp(u32 msel)
+{
+	if (msel < 60)
+		return (msel >> 1) + 1;
+
+	return 31;
+}
+
+static unsigned long lpc18xx_pll0_recalc_rate(struct clk_hw *hw,
+					      unsigned long parent_rate)
+{
+	struct lpc18xx_pll *pll = to_lpc_pll(hw);
+	u32 ctrl, mdiv, msel, npdiv;
+
+	ctrl = clk_readl(pll->reg + LPC18XX_CGU_PLL0USB_CTRL);
+	mdiv = clk_readl(pll->reg + LPC18XX_CGU_PLL0USB_MDIV);
+	npdiv = clk_readl(pll->reg + LPC18XX_CGU_PLL0USB_NP_DIV);
+
+	if (ctrl & LPC18XX_PLL0_CTRL_BYPASS)
+		return parent_rate;
+
+	if (npdiv != LPC18XX_PLL0_NP_DIVS_1) {
+		pr_warn("%s: pre/post dividers not supported\n", __func__);
+		return 0;
+	}
+
+	msel = lpc18xx_pll0_mdec2msel(mdiv & LPC18XX_PLL0_MDIV_MDEC_MASK);
+	if (msel)
+		return 2 * msel * parent_rate;
+
+	pr_warn("%s: unable to calculate rate\n", __func__);
+
+	return 0;
+}
+
+static long lpc18xx_pll0_round_rate(struct clk_hw *hw, unsigned long rate,
+				    unsigned long *prate)
+{
+	unsigned long m;
+
+	if (*prate < rate) {
+		pr_warn("%s: pll dividers not supported\n", __func__);
+		return -EINVAL;
+	}
+
+	m = DIV_ROUND_UP_ULL(*prate, rate * 2);
+	if (m <= 0 && m > LPC18XX_PLL0_MSEL_MAX) {
+		pr_warn("%s: unable to support rate %lu\n", __func__, rate);
+		return -EINVAL;
+	}
+
+	return 2 * *prate * m;
+}
+
+static int lpc18xx_pll0_set_rate(struct clk_hw *hw, unsigned long rate,
+				 unsigned long parent_rate)
+{
+	struct lpc18xx_pll *pll = to_lpc_pll(hw);
+	u32 ctrl, stat, m;
+	int retry = 3;
+
+	if (parent_rate < rate) {
+		pr_warn("%s: pll dividers not supported\n", __func__);
+		return -EINVAL;
+	}
+
+	m = DIV_ROUND_UP_ULL(parent_rate, rate * 2);
+	if (m <= 0 && m > LPC18XX_PLL0_MSEL_MAX) {
+		pr_warn("%s: unable to support rate %lu\n", __func__, rate);
+		return -EINVAL;
+	}
+
+	m  = lpc18xx_pll0_msel2mdec(m);
+	m |= lpc18xx_pll0_msel2selp(m) << LPC18XX_PLL0_MDIV_SELP_SHIFT;
+	m |= lpc18xx_pll0_msel2seli(m) << LPC18XX_PLL0_MDIV_SELI_SHIFT;
+
+	/* Power down PLL, disable clk output and dividers */
+	ctrl = clk_readl(pll->reg + LPC18XX_CGU_PLL0USB_CTRL);
+	ctrl |= LPC18XX_PLL0_CTRL_PD;
+	ctrl &= ~(LPC18XX_PLL0_CTRL_BYPASS | LPC18XX_PLL0_CTRL_DIRECTI |
+		  LPC18XX_PLL0_CTRL_DIRECTO | LPC18XX_PLL0_CTRL_CLKEN);
+	clk_writel(ctrl, pll->reg + LPC18XX_CGU_PLL0USB_CTRL);
+
+	/* Configure new PLL settings */
+	clk_writel(m, pll->reg + LPC18XX_CGU_PLL0USB_MDIV);
+	clk_writel(LPC18XX_PLL0_NP_DIVS_1, pll->reg + LPC18XX_CGU_PLL0USB_NP_DIV);
+
+	/* Power up PLL and wait for lock */
+	ctrl &= ~LPC18XX_PLL0_CTRL_PD;
+	clk_writel(ctrl, pll->reg + LPC18XX_CGU_PLL0USB_CTRL);
+	do {
+		udelay(10);
+		stat = clk_readl(pll->reg + LPC18XX_CGU_PLL0USB_STAT);
+		if (stat & LPC18XX_PLL0_STAT_LOCK) {
+			ctrl |= LPC18XX_PLL0_CTRL_CLKEN;
+			clk_writel(ctrl, pll->reg + LPC18XX_CGU_PLL0USB_CTRL);
+
+			return 0;
+		}
+	} while (retry--);
+
+	pr_warn("%s: unable to lock pll\n", __func__);
+
+	return -EINVAL;
+}
+
+static const struct clk_ops lpc18xx_pll0_ops = {
+	.recalc_rate	= lpc18xx_pll0_recalc_rate,
+	.round_rate	= lpc18xx_pll0_round_rate,
+	.set_rate	= lpc18xx_pll0_set_rate,
+};
+
+static unsigned long lpc18xx_pll1_recalc_rate(struct clk_hw *hw,
+					      unsigned long parent_rate)
+{
+	struct lpc18xx_pll *pll = to_lpc_pll(hw);
+	u16 msel, nsel, psel;
+	bool direct, fbsel;
+	u32 stat, ctrl;
+
+	stat = clk_readl(pll->reg + LPC18XX_CGU_PLL1_STAT);
+	ctrl = clk_readl(pll->reg + LPC18XX_CGU_PLL1_CTRL);
+
+	direct = (ctrl & LPC18XX_PLL1_CTRL_DIRECT) ? true : false;
+	fbsel = (ctrl & LPC18XX_PLL1_CTRL_FBSEL) ? true : false;
+
+	msel = ((ctrl >> 16) & 0xff) + 1;
+	nsel = ((ctrl >> 12) & 0x3) + 1;
+
+	if (direct || fbsel)
+		return msel * (parent_rate / nsel);
+
+	psel = (ctrl >>  8) & 0x3;
+	psel = 1 << psel;
+
+	return (msel / (2 * psel)) * (parent_rate / nsel);
+}
+
+static const struct clk_ops lpc18xx_pll1_ops = {
+	.recalc_rate = lpc18xx_pll1_recalc_rate,
+};
+
+static struct lpc18xx_cgu_pll_clk lpc18xx_cgu_src_clk_plls[] = {
+	LPC1XX_CGU_CLK_PLL(PLL0USB,	pll0_src_ids, pll0_ops),
+	LPC1XX_CGU_CLK_PLL(PLL0AUDIO,	pll0_src_ids, pll0_ops),
+	LPC1XX_CGU_CLK_PLL(PLL1,	pll1_src_ids, pll1_ops),
+};
+
+static void lpc18xx_fill_parent_names(const char **parent, u32 *id, int size)
+{
+	int i;
+
+	for (i = 0; i < size; i++)
+		parent[i] = clk_src_names[id[i]];
+}
+
+static struct clk *lpc18xx_cgu_register_div(struct lpc18xx_cgu_src_clk_div *clk,
+					    void __iomem *base, int n)
+{
+	void __iomem *reg = base + LPC18XX_CGU_IDIV_CTRL(n);
+	const char *name = clk_src_names[clk->clk_id];
+	const char *parents[CLK_SRC_MAX];
+
+	clk->div.reg = reg;
+	clk->mux.reg = reg;
+	clk->gate.reg = reg;
+
+	lpc18xx_fill_parent_names(parents, clk->mux.table, clk->n_parents);
+
+	return clk_register_composite(NULL, name, parents, clk->n_parents,
+				      &clk->mux.hw, &clk_mux_ops,
+				      &clk->div.hw, &clk_divider_ops,
+				      &clk->gate.hw, &clk_gate_ops, 0);
+}
+
+
+static struct clk *lpc18xx_register_base_clk(struct lpc18xx_cgu_base_clk *clk,
+					     void __iomem *base, int n)
+{
+	void __iomem *reg = base + LPC18XX_CGU_BASE_CLK(n);
+	const char *name = clk_base_names[clk->clk_id];
+	const char *parents[CLK_SRC_MAX];
+
+	if (clk->n_parents == 0)
+		return ERR_PTR(-ENOENT);
+
+	clk->mux.reg = reg;
+	clk->gate.reg = reg;
+
+	lpc18xx_fill_parent_names(parents, clk->mux.table, clk->n_parents);
+
+	/* SAFE_CLK can not be turned off */
+	if (n == BASE_SAFE_CLK)
+		return clk_register_composite(NULL, name, parents, clk->n_parents,
+					      &clk->mux.hw, &clk_mux_ops,
+					      NULL, NULL, NULL, NULL, 0);
+
+	return clk_register_composite(NULL, name, parents, clk->n_parents,
+				      &clk->mux.hw, &clk_mux_ops,
+				      NULL,  NULL,
+				      &clk->gate.hw, &clk_gate_ops, 0);
+}
+
+
+static struct clk *lpc18xx_cgu_register_pll(struct lpc18xx_cgu_pll_clk *clk,
+					    void __iomem *base)
+{
+	const char *name = clk_src_names[clk->clk_id];
+	const char *parents[CLK_SRC_MAX];
+
+	clk->pll.reg  = base;
+	clk->mux.reg  = base + clk->reg_offset + LPC18XX_CGU_PLL_CTRL_OFFSET;
+	clk->gate.reg = base + clk->reg_offset + LPC18XX_CGU_PLL_CTRL_OFFSET;
+
+	lpc18xx_fill_parent_names(parents, clk->mux.table, clk->n_parents);
+
+	return clk_register_composite(NULL, name, parents, clk->n_parents,
+				      &clk->mux.hw, &clk_mux_ops,
+				      &clk->pll.hw, clk->pll_ops,
+				      &clk->gate.hw, &clk_gate_ops, 0);
+}
+
+static void __init lpc18xx_cgu_register_source_clks(void __iomem *base,
+						    struct device_node *np)
+{
+	const char *parents[CLK_SRC_MAX];
+	struct clk *clk;
+	int i;
+
+	/* Register the internal 12 MHz RC oscillator (IRC) */
+	clk = clk_register_fixed_rate(NULL, clk_src_names[CLK_SRC_IRC],
+				      NULL, CLK_IS_ROOT, 12000000);
+	if (IS_ERR(clk))
+		pr_warn("%s: failed to register irc clk\n", __func__);
+
+	/* Register crystal oscillator controlller */
+	parents[0] = of_clk_get_parent_name(np, 0);
+	clk = clk_register_gate(NULL, clk_src_names[CLK_SRC_OSC], parents[0],
+				0, base + LPC18XX_CGU_XTAL_OSC_CTRL,
+				0, CLK_GATE_SET_TO_DISABLE, NULL);
+	if (IS_ERR(clk))
+		pr_warn("%s: failed to register osc clk\n", __func__);
+
+	/* Register all PLLs */
+	for (i = 0; i < ARRAY_SIZE(lpc18xx_cgu_src_clk_plls); i++) {
+		clk = lpc18xx_cgu_register_pll(&lpc18xx_cgu_src_clk_plls[i],
+						   base);
+		if (IS_ERR(clk))
+			pr_warn("%s: failed to register pll (%d)\n", __func__, i);
+	}
+
+	/* Register all clock dividers A-E */
+	for (i = 0; i < ARRAY_SIZE(lpc18xx_cgu_src_clk_divs); i++) {
+		clk = lpc18xx_cgu_register_div(&lpc18xx_cgu_src_clk_divs[i],
+					       base, i);
+		if (IS_ERR(clk))
+			pr_warn("%s: failed to register div %d\n", __func__, i);
+	}
+}
+
+static struct clk *clk_base[BASE_CLK_MAX];
+static struct clk_onecell_data clk_base_data = {
+	.clks = clk_base,
+	.clk_num = BASE_CLK_MAX,
+};
+
+static void __init lpc18xx_cgu_register_base_clks(void __iomem *base)
+{
+	int i;
+
+	for (i = BASE_SAFE_CLK; i < BASE_CLK_MAX; i++) {
+		clk_base[i] = lpc18xx_register_base_clk(&lpc18xx_cgu_base_clks[i],
+							base, i);
+		if (IS_ERR(clk_base[i]) && PTR_ERR(clk_base[i]) != -ENOENT)
+			pr_warn("%s: register base clk %d failed\n", __func__, i);
+	}
+}
+
+static void __init lpc18xx_cgu_init(struct device_node *np)
+{
+	void __iomem *base;
+	const char *name;
+	int i, ret;
+	u32 idx;
+
+	base = of_iomap(np, 0);
+	if (!base) {
+		pr_warn("%s: failed to map address range\n", __func__);
+		return;
+	}
+
+	/* Get base clk names and ids from DT */
+	for (i = 0; i < BASE_CLK_MAX; i++) {
+		ret = of_property_read_u32_index(np, "clock-indices", i, &idx);
+		if (ret)
+			break;
+
+		ret = of_property_read_string_index(np, "clock-output-names",
+						    i, &name);
+		if (ret)
+			break;
+
+		if (idx < BASE_CLK_MAX)
+			clk_base_names[idx] = name;
+	}
+
+	lpc18xx_cgu_register_source_clks(base, np);
+	lpc18xx_cgu_register_base_clks(base);
+
+	of_clk_add_provider(np, of_clk_src_onecell_get, &clk_base_data);
+}
+CLK_OF_DECLARE(lpc18xx_cgu, "nxp,lpc1850-cgu", lpc18xx_cgu_init);
diff --git a/include/dt-bindings/clock/lpc18xx-cgu.h b/include/dt-bindings/clock/lpc18xx-cgu.h
new file mode 100644
index 000000000000..6e57c6d2ca66
--- /dev/null
+++ b/include/dt-bindings/clock/lpc18xx-cgu.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2015 Joachim Eastwood <manabian-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
+ *
+ * This code is released using a dual license strategy: BSD/GPL
+ * You can choose the licence that better fits your requirements.
+ *
+ * Released under the terms of 3-clause BSD License
+ * Released under the terms of GNU General Public License Version 2.0
+ *
+ */
+
+/* LPC18xx/43xx base clock ids */
+#define BASE_SAFE_CLK		0
+#define BASE_USB0_CLK		1
+#define BASE_PERIPH_CLK		2
+#define BASE_USB1_CLK		3
+#define BASE_CPU_CLK		4
+#define BASE_SPIFI_CLK		5
+#define BASE_SPI_CLK		6
+#define BASE_PHY_RX_CLK		7
+#define BASE_PHY_TX_CLK		8
+#define BASE_APB1_CLK		9
+#define BASE_APB3_CLK		10
+#define BASE_LCD_CLK		11
+#define BASE_ADCHS_CLK		12
+#define BASE_SDIO_CLK		13
+#define BASE_SSP0_CLK		14
+#define BASE_SSP1_CLK		15
+#define BASE_UART0_CLK		16
+#define BASE_UART1_CLK		17
+#define BASE_UART2_CLK		18
+#define BASE_UART3_CLK		19
+#define BASE_OUT_CLK		20
+#define BASE_RES1_CLK		21
+#define BASE_RES2_CLK		22
+#define BASE_RES3_CLK		23
+#define BASE_RES4_CLK		24
+#define BASE_AUDIO_CLK		25
+#define BASE_CGU_OUT0_CLK	26
+#define BASE_CGU_OUT1_CLK	27
+#define BASE_CLK_MAX		(BASE_CGU_OUT1_CLK + 1)
-- 
1.8.0

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH v2 1/4] clk: add lpc18xx cgu clk driver
@ 2015-04-27 21:38     ` Joachim Eastwood
  0 siblings, 0 replies; 39+ messages in thread
From: Joachim Eastwood @ 2015-04-27 21:38 UTC (permalink / raw)
  To: mturquette, sboyd, arnd, linux-clk, linux-arm-kernel
  Cc: devicetree, ariel.dalessandro, ezequiel, Joachim Eastwood

Add driver for NXP LPC18xx/43xx Clock Generation Unit (CGU). The CGU
contains several clock generators and output stages that route the
clocks either directly to peripherals or to a Clock Control Unit
(CCU).

Signed-off-by: Joachim Eastwood <manabian@gmail.com>
---
 drivers/clk/Makefile                    |   1 +
 drivers/clk/nxp/Makefile                |   1 +
 drivers/clk/nxp/clk-lpc18xx-cgu.c       | 628 ++++++++++++++++++++++++++++++++
 include/dt-bindings/clock/lpc18xx-cgu.h |  41 +++
 4 files changed, 671 insertions(+)
 create mode 100644 drivers/clk/nxp/Makefile
 create mode 100644 drivers/clk/nxp/clk-lpc18xx-cgu.c
 create mode 100644 include/dt-bindings/clock/lpc18xx-cgu.h

diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index 3d00c25382c5..4a34419c1da1 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -56,6 +56,7 @@ obj-$(CONFIG_ARCH_MMP)			+= mmp/
 endif
 obj-$(CONFIG_PLAT_ORION)		+= mvebu/
 obj-$(CONFIG_ARCH_MXS)			+= mxs/
+obj-$(CONFIG_ARCH_LPC18XX)		+= nxp/
 obj-$(CONFIG_MACH_PISTACHIO)		+= pistachio/
 obj-$(CONFIG_COMMON_CLK_PXA)		+= pxa/
 obj-$(CONFIG_COMMON_CLK_QCOM)		+= qcom/
diff --git a/drivers/clk/nxp/Makefile b/drivers/clk/nxp/Makefile
new file mode 100644
index 000000000000..aca9d3e4f7fe
--- /dev/null
+++ b/drivers/clk/nxp/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_ARCH_LPC18XX)	+= clk-lpc18xx-cgu.o
diff --git a/drivers/clk/nxp/clk-lpc18xx-cgu.c b/drivers/clk/nxp/clk-lpc18xx-cgu.c
new file mode 100644
index 000000000000..15977f5d767f
--- /dev/null
+++ b/drivers/clk/nxp/clk-lpc18xx-cgu.c
@@ -0,0 +1,628 @@
+/*
+ * Clk driver for NXP LPC18xx/LPC43xx Clock Generation Unit (CGU)
+ *
+ * Copyright (C) 2015 Joachim Eastwood <manabian@gmail.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/delay.h>
+#include <linux/kernel.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+
+#include <dt-bindings/clock/lpc18xx-cgu.h>
+
+/* Clock Generation Unit (CGU) registers */
+#define LPC18XX_CGU_XTAL_OSC_CTRL	0x018
+#define LPC18XX_CGU_PLL0USB_STAT	0x01c
+#define LPC18XX_CGU_PLL0USB_CTRL	0x020
+#define LPC18XX_CGU_PLL0USB_MDIV	0x024
+#define LPC18XX_CGU_PLL0USB_NP_DIV	0x028
+#define LPC18XX_CGU_PLL0AUDIO_STAT	0x02c
+#define LPC18XX_CGU_PLL0AUDIO_CTRL	0x030
+#define LPC18XX_CGU_PLL0AUDIO_MDIV	0x034
+#define LPC18XX_CGU_PLL0AUDIO_NP_DIV	0x038
+#define LPC18XX_CGU_PLL0AUDIO_FRAC	0x03c
+#define LPC18XX_CGU_PLL1_STAT		0x040
+#define LPC18XX_CGU_PLL1_CTRL		0x044
+#define  LPC18XX_PLL1_CTRL_FBSEL	BIT(6)
+#define  LPC18XX_PLL1_CTRL_DIRECT	BIT(7)
+#define LPC18XX_CGU_IDIV_CTRL(n)	(0x048 + (n) * sizeof(u32))
+#define LPC18XX_CGU_BASE_CLK(id)	(0x05c + (id) * sizeof(u32))
+#define LPC18XX_CGU_PLL_CTRL_OFFSET	0x4
+
+/* PLL0 bits common to both audio and USB PLL */
+#define LPC18XX_PLL0_STAT_LOCK		BIT(0)
+#define LPC18XX_PLL0_CTRL_PD		BIT(0)
+#define LPC18XX_PLL0_CTRL_BYPASS	BIT(1)
+#define LPC18XX_PLL0_CTRL_DIRECTI	BIT(2)
+#define LPC18XX_PLL0_CTRL_DIRECTO	BIT(3)
+#define LPC18XX_PLL0_CTRL_CLKEN		BIT(4)
+#define LPC18XX_PLL0_MDIV_MDEC_MASK	0x1ffff
+#define LPC18XX_PLL0_MDIV_SELP_SHIFT	17
+#define LPC18XX_PLL0_MDIV_SELI_SHIFT	22
+#define LPC18XX_PLL0_MSEL_MAX		BIT(15)
+
+/* Register value that gives PLL0 post/pre dividers equal to 1 */
+#define LPC18XX_PLL0_NP_DIVS_1		0x00302062
+
+enum {
+	CLK_SRC_OSC32,
+	CLK_SRC_IRC,
+	CLK_SRC_ENET_RX_CLK,
+	CLK_SRC_ENET_TX_CLK,
+	CLK_SRC_GP_CLKIN,
+	CLK_SRC_RESERVED1,
+	CLK_SRC_OSC,
+	CLK_SRC_PLL0USB,
+	CLK_SRC_PLL0AUDIO,
+	CLK_SRC_PLL1,
+	CLK_SRC_RESERVED2,
+	CLK_SRC_RESERVED3,
+	CLK_SRC_IDIVA,
+	CLK_SRC_IDIVB,
+	CLK_SRC_IDIVC,
+	CLK_SRC_IDIVD,
+	CLK_SRC_IDIVE,
+	CLK_SRC_MAX
+};
+
+static const char *clk_src_names[CLK_SRC_MAX] = {
+	[CLK_SRC_OSC32]		= "osc32",
+	[CLK_SRC_IRC]		= "irc",
+	[CLK_SRC_ENET_RX_CLK]	= "enet_rx_clk",
+	[CLK_SRC_ENET_TX_CLK]	= "enet_tx_clk",
+	[CLK_SRC_GP_CLKIN]	= "gp_clkin",
+	[CLK_SRC_OSC]		= "osc",
+	[CLK_SRC_PLL0USB]	= "pll0usb",
+	[CLK_SRC_PLL0AUDIO]	= "pll0audio",
+	[CLK_SRC_PLL1]		= "pll1",
+	[CLK_SRC_IDIVA]		= "idiva",
+	[CLK_SRC_IDIVB]		= "idivb",
+	[CLK_SRC_IDIVC]		= "idivc",
+	[CLK_SRC_IDIVD]		= "idivd",
+	[CLK_SRC_IDIVE]		= "idive",
+};
+
+static const char *clk_base_names[BASE_CLK_MAX];
+
+static u32 lpc18xx_cgu_pll0_src_ids[] = {
+	CLK_SRC_OSC32, CLK_SRC_IRC, CLK_SRC_ENET_RX_CLK,
+	CLK_SRC_ENET_TX_CLK, CLK_SRC_GP_CLKIN, CLK_SRC_OSC,
+	CLK_SRC_PLL1, CLK_SRC_IDIVA, CLK_SRC_IDIVB, CLK_SRC_IDIVC,
+	CLK_SRC_IDIVD, CLK_SRC_IDIVE,
+};
+
+static u32 lpc18xx_cgu_pll1_src_ids[] = {
+	CLK_SRC_OSC32, CLK_SRC_IRC, CLK_SRC_ENET_RX_CLK,
+	CLK_SRC_ENET_TX_CLK, CLK_SRC_GP_CLKIN, CLK_SRC_OSC,
+	CLK_SRC_PLL0USB, CLK_SRC_PLL0AUDIO, CLK_SRC_IDIVA,
+	CLK_SRC_IDIVB, CLK_SRC_IDIVC, CLK_SRC_IDIVD, CLK_SRC_IDIVE,
+};
+
+static u32 lpc18xx_cgu_idiva_src_ids[] = {
+	CLK_SRC_OSC32, CLK_SRC_IRC, CLK_SRC_ENET_RX_CLK,
+	CLK_SRC_ENET_TX_CLK, CLK_SRC_GP_CLKIN, CLK_SRC_OSC,
+	CLK_SRC_PLL0USB, CLK_SRC_PLL0AUDIO, CLK_SRC_PLL1
+};
+
+static u32 lpc18xx_cgu_idivbcde_src_ids[] = {
+	CLK_SRC_OSC32, CLK_SRC_IRC, CLK_SRC_ENET_RX_CLK,
+	CLK_SRC_ENET_TX_CLK, CLK_SRC_GP_CLKIN, CLK_SRC_OSC,
+	CLK_SRC_PLL0AUDIO, CLK_SRC_PLL1, CLK_SRC_IDIVA,
+};
+
+static u32 lpc18xx_cgu_base_irc_src_ids[] = {CLK_SRC_IRC};
+
+static u32 lpc18xx_cgu_base_usb0_src_ids[] = {CLK_SRC_PLL0USB};
+
+static u32 lpc18xx_cgu_base_common_src_ids[] = {
+	CLK_SRC_OSC32, CLK_SRC_IRC, CLK_SRC_ENET_RX_CLK,
+	CLK_SRC_ENET_TX_CLK, CLK_SRC_GP_CLKIN, CLK_SRC_OSC,
+	CLK_SRC_PLL0AUDIO, CLK_SRC_PLL1, CLK_SRC_IDIVA,
+	CLK_SRC_IDIVB, CLK_SRC_IDIVC, CLK_SRC_IDIVD, CLK_SRC_IDIVE,
+};
+
+static u32 lpc18xx_cgu_base_all_src_ids[] = {
+	CLK_SRC_OSC32, CLK_SRC_IRC, CLK_SRC_ENET_RX_CLK,
+	CLK_SRC_ENET_TX_CLK, CLK_SRC_GP_CLKIN, CLK_SRC_OSC,
+	CLK_SRC_PLL0USB, CLK_SRC_PLL0AUDIO, CLK_SRC_PLL1,
+	CLK_SRC_IDIVA, CLK_SRC_IDIVB, CLK_SRC_IDIVC,
+	CLK_SRC_IDIVD, CLK_SRC_IDIVE,
+};
+
+struct lpc18xx_cgu_src_clk_div {
+	u8 clk_id;
+	u8 n_parents;
+	struct clk_divider	div;
+	struct clk_mux		mux;
+	struct clk_gate		gate;
+};
+
+#define LPC1XX_CGU_SRC_CLK_DIV(_id, _width, _table)	\
+{							\
+	.clk_id = CLK_SRC_ ##_id,			\
+	.n_parents = ARRAY_SIZE(lpc18xx_cgu_ ##_table),	\
+	.div = {					\
+		.shift = 2,				\
+		.width = _width,			\
+	},						\
+	.mux = {					\
+		.mask = 0x1f,				\
+		.shift = 24,				\
+		.table = lpc18xx_cgu_ ##_table,		\
+	},						\
+	.gate = {					\
+		.bit_idx = 0,				\
+		.flags = CLK_GATE_SET_TO_DISABLE,	\
+	},						\
+}
+
+static struct lpc18xx_cgu_src_clk_div lpc18xx_cgu_src_clk_divs[] = {
+	LPC1XX_CGU_SRC_CLK_DIV(IDIVA, 2, idiva_src_ids),
+	LPC1XX_CGU_SRC_CLK_DIV(IDIVB, 4, idivbcde_src_ids),
+	LPC1XX_CGU_SRC_CLK_DIV(IDIVC, 4, idivbcde_src_ids),
+	LPC1XX_CGU_SRC_CLK_DIV(IDIVD, 4, idivbcde_src_ids),
+	LPC1XX_CGU_SRC_CLK_DIV(IDIVE, 8, idivbcde_src_ids),
+};
+
+struct lpc18xx_cgu_base_clk {
+	u8 clk_id;
+	u8 n_parents;
+	struct clk_mux mux;
+	struct clk_gate gate;
+};
+
+#define LPC1XX_CGU_BASE_CLK(_id, _table, _flags)	\
+{							\
+	.clk_id = BASE_ ##_id ##_CLK,			\
+	.n_parents = ARRAY_SIZE(lpc18xx_cgu_ ##_table),	\
+	.mux = {					\
+		.mask = 0x1f,				\
+		.shift = 24,				\
+		.table = lpc18xx_cgu_ ##_table,		\
+		.flags = _flags,			\
+	},						\
+	.gate = {					\
+		.bit_idx = 0,				\
+		.flags = CLK_GATE_SET_TO_DISABLE,	\
+	},						\
+}
+
+static struct lpc18xx_cgu_base_clk lpc18xx_cgu_base_clks[] = {
+	LPC1XX_CGU_BASE_CLK(SAFE,	base_irc_src_ids, CLK_MUX_READ_ONLY),
+	LPC1XX_CGU_BASE_CLK(USB0,	base_usb0_src_ids,   0),
+	LPC1XX_CGU_BASE_CLK(PERIPH,	base_common_src_ids, 0),
+	LPC1XX_CGU_BASE_CLK(USB1,	base_all_src_ids,    0),
+	LPC1XX_CGU_BASE_CLK(CPU,	base_common_src_ids, 0),
+	LPC1XX_CGU_BASE_CLK(SPIFI,	base_common_src_ids, 0),
+	LPC1XX_CGU_BASE_CLK(SPI,	base_common_src_ids, 0),
+	LPC1XX_CGU_BASE_CLK(PHY_RX,	base_common_src_ids, 0),
+	LPC1XX_CGU_BASE_CLK(PHY_TX,	base_common_src_ids, 0),
+	LPC1XX_CGU_BASE_CLK(APB1,	base_common_src_ids, 0),
+	LPC1XX_CGU_BASE_CLK(APB3,	base_common_src_ids, 0),
+	LPC1XX_CGU_BASE_CLK(LCD,	base_common_src_ids, 0),
+	LPC1XX_CGU_BASE_CLK(ADCHS,	base_common_src_ids, 0),
+	LPC1XX_CGU_BASE_CLK(SDIO,	base_common_src_ids, 0),
+	LPC1XX_CGU_BASE_CLK(SSP0,	base_common_src_ids, 0),
+	LPC1XX_CGU_BASE_CLK(SSP1,	base_common_src_ids, 0),
+	LPC1XX_CGU_BASE_CLK(UART0,	base_common_src_ids, 0),
+	LPC1XX_CGU_BASE_CLK(UART1,	base_common_src_ids, 0),
+	LPC1XX_CGU_BASE_CLK(UART2,	base_common_src_ids, 0),
+	LPC1XX_CGU_BASE_CLK(UART3,	base_common_src_ids, 0),
+	LPC1XX_CGU_BASE_CLK(OUT,	base_all_src_ids,    0),
+	{ /* 21 reserved */ },
+	{ /* 22 reserved */ },
+	{ /* 23 reserved */ },
+	{ /* 24 reserved */ },
+	LPC1XX_CGU_BASE_CLK(AUDIO,	base_common_src_ids, 0),
+	LPC1XX_CGU_BASE_CLK(CGU_OUT0,	base_all_src_ids,    0),
+	LPC1XX_CGU_BASE_CLK(CGU_OUT1,	base_all_src_ids,    0),
+};
+
+struct lpc18xx_pll {
+	struct		clk_hw hw;
+	void __iomem	*reg;
+	spinlock_t	*lock;
+	u8		flags;
+};
+
+#define to_lpc_pll(hw) container_of(hw, struct lpc18xx_pll, hw)
+
+struct lpc18xx_cgu_pll_clk {
+	u8 clk_id;
+	u8 n_parents;
+	u8 reg_offset;
+	struct clk_mux mux;
+	struct clk_gate gate;
+	struct lpc18xx_pll pll;
+	const struct clk_ops *pll_ops;
+};
+
+#define LPC1XX_CGU_CLK_PLL(_id, _table, _pll_ops)	\
+{							\
+	.clk_id = CLK_SRC_ ##_id,			\
+	.n_parents = ARRAY_SIZE(lpc18xx_cgu_ ##_table),	\
+	.reg_offset = LPC18XX_CGU_ ##_id ##_STAT,	\
+	.mux = {					\
+		.mask = 0x1f,				\
+		.shift = 24,				\
+		.table = lpc18xx_cgu_ ##_table,		\
+	},						\
+	.gate = {					\
+		.bit_idx = 0,				\
+		.flags = CLK_GATE_SET_TO_DISABLE,	\
+	},						\
+	.pll_ops = &lpc18xx_ ##_pll_ops,		\
+}
+
+/*
+ * PLL0 uses a special register value encoding. The compute functions below
+ * are taken or derived from the LPC1850 user manual (section 12.6.3.3).
+ */
+
+/* Compute PLL0 multiplier from decoded version */
+static u32 lpc18xx_pll0_mdec2msel(u32 x)
+{
+	int i;
+
+	switch (x) {
+	case 0x18003: return 1;
+	case 0x10003: return 2;
+	default:
+		for (i = LPC18XX_PLL0_MSEL_MAX + 1; x != 0x4000 && i > 0; i--)
+			x = ((x ^ x >> 14) & 1) | (x << 1 & 0x7fff);
+		return i;
+	}
+}
+/* Compute PLL0 decoded multiplier from binary version */
+static u32 lpc18xx_pll0_msel2mdec(u32 msel)
+{
+	u32 i, x = 0x4000;
+
+	switch (msel) {
+	case 0: return 0;
+	case 1: return 0x18003;
+	case 2: return 0x10003;
+	default:
+		for (i = msel; i <= LPC18XX_PLL0_MSEL_MAX; i++)
+			x = ((x ^ x >> 1) & 1) << 14 | (x >> 1 & 0xffff);
+		return x;
+	}
+}
+
+/* Compute PLL0 bandwidth SELI reg from multiplier */
+static u32 lpc18xx_pll0_msel2seli(u32 msel)
+{
+	u32 tmp;
+
+	if (msel > 16384) return 1;
+	if (msel >  8192) return 2;
+	if (msel >  2048) return 4;
+	if (msel >=  501) return 8;
+	if (msel >=   60) {
+		tmp = 1024 / (msel + 9);
+		return ((1024 == (tmp * (msel + 9))) == 0) ? tmp * 4 : (tmp + 1) * 4;
+	}
+
+	return (msel & 0x3c) + 4;
+}
+
+/* Compute PLL0 bandwidth SELP reg from multiplier */
+static u32 lpc18xx_pll0_msel2selp(u32 msel)
+{
+	if (msel < 60)
+		return (msel >> 1) + 1;
+
+	return 31;
+}
+
+static unsigned long lpc18xx_pll0_recalc_rate(struct clk_hw *hw,
+					      unsigned long parent_rate)
+{
+	struct lpc18xx_pll *pll = to_lpc_pll(hw);
+	u32 ctrl, mdiv, msel, npdiv;
+
+	ctrl = clk_readl(pll->reg + LPC18XX_CGU_PLL0USB_CTRL);
+	mdiv = clk_readl(pll->reg + LPC18XX_CGU_PLL0USB_MDIV);
+	npdiv = clk_readl(pll->reg + LPC18XX_CGU_PLL0USB_NP_DIV);
+
+	if (ctrl & LPC18XX_PLL0_CTRL_BYPASS)
+		return parent_rate;
+
+	if (npdiv != LPC18XX_PLL0_NP_DIVS_1) {
+		pr_warn("%s: pre/post dividers not supported\n", __func__);
+		return 0;
+	}
+
+	msel = lpc18xx_pll0_mdec2msel(mdiv & LPC18XX_PLL0_MDIV_MDEC_MASK);
+	if (msel)
+		return 2 * msel * parent_rate;
+
+	pr_warn("%s: unable to calculate rate\n", __func__);
+
+	return 0;
+}
+
+static long lpc18xx_pll0_round_rate(struct clk_hw *hw, unsigned long rate,
+				    unsigned long *prate)
+{
+	unsigned long m;
+
+	if (*prate < rate) {
+		pr_warn("%s: pll dividers not supported\n", __func__);
+		return -EINVAL;
+	}
+
+	m = DIV_ROUND_UP_ULL(*prate, rate * 2);
+	if (m <= 0 && m > LPC18XX_PLL0_MSEL_MAX) {
+		pr_warn("%s: unable to support rate %lu\n", __func__, rate);
+		return -EINVAL;
+	}
+
+	return 2 * *prate * m;
+}
+
+static int lpc18xx_pll0_set_rate(struct clk_hw *hw, unsigned long rate,
+				 unsigned long parent_rate)
+{
+	struct lpc18xx_pll *pll = to_lpc_pll(hw);
+	u32 ctrl, stat, m;
+	int retry = 3;
+
+	if (parent_rate < rate) {
+		pr_warn("%s: pll dividers not supported\n", __func__);
+		return -EINVAL;
+	}
+
+	m = DIV_ROUND_UP_ULL(parent_rate, rate * 2);
+	if (m <= 0 && m > LPC18XX_PLL0_MSEL_MAX) {
+		pr_warn("%s: unable to support rate %lu\n", __func__, rate);
+		return -EINVAL;
+	}
+
+	m  = lpc18xx_pll0_msel2mdec(m);
+	m |= lpc18xx_pll0_msel2selp(m) << LPC18XX_PLL0_MDIV_SELP_SHIFT;
+	m |= lpc18xx_pll0_msel2seli(m) << LPC18XX_PLL0_MDIV_SELI_SHIFT;
+
+	/* Power down PLL, disable clk output and dividers */
+	ctrl = clk_readl(pll->reg + LPC18XX_CGU_PLL0USB_CTRL);
+	ctrl |= LPC18XX_PLL0_CTRL_PD;
+	ctrl &= ~(LPC18XX_PLL0_CTRL_BYPASS | LPC18XX_PLL0_CTRL_DIRECTI |
+		  LPC18XX_PLL0_CTRL_DIRECTO | LPC18XX_PLL0_CTRL_CLKEN);
+	clk_writel(ctrl, pll->reg + LPC18XX_CGU_PLL0USB_CTRL);
+
+	/* Configure new PLL settings */
+	clk_writel(m, pll->reg + LPC18XX_CGU_PLL0USB_MDIV);
+	clk_writel(LPC18XX_PLL0_NP_DIVS_1, pll->reg + LPC18XX_CGU_PLL0USB_NP_DIV);
+
+	/* Power up PLL and wait for lock */
+	ctrl &= ~LPC18XX_PLL0_CTRL_PD;
+	clk_writel(ctrl, pll->reg + LPC18XX_CGU_PLL0USB_CTRL);
+	do {
+		udelay(10);
+		stat = clk_readl(pll->reg + LPC18XX_CGU_PLL0USB_STAT);
+		if (stat & LPC18XX_PLL0_STAT_LOCK) {
+			ctrl |= LPC18XX_PLL0_CTRL_CLKEN;
+			clk_writel(ctrl, pll->reg + LPC18XX_CGU_PLL0USB_CTRL);
+
+			return 0;
+		}
+	} while (retry--);
+
+	pr_warn("%s: unable to lock pll\n", __func__);
+
+	return -EINVAL;
+}
+
+static const struct clk_ops lpc18xx_pll0_ops = {
+	.recalc_rate	= lpc18xx_pll0_recalc_rate,
+	.round_rate	= lpc18xx_pll0_round_rate,
+	.set_rate	= lpc18xx_pll0_set_rate,
+};
+
+static unsigned long lpc18xx_pll1_recalc_rate(struct clk_hw *hw,
+					      unsigned long parent_rate)
+{
+	struct lpc18xx_pll *pll = to_lpc_pll(hw);
+	u16 msel, nsel, psel;
+	bool direct, fbsel;
+	u32 stat, ctrl;
+
+	stat = clk_readl(pll->reg + LPC18XX_CGU_PLL1_STAT);
+	ctrl = clk_readl(pll->reg + LPC18XX_CGU_PLL1_CTRL);
+
+	direct = (ctrl & LPC18XX_PLL1_CTRL_DIRECT) ? true : false;
+	fbsel = (ctrl & LPC18XX_PLL1_CTRL_FBSEL) ? true : false;
+
+	msel = ((ctrl >> 16) & 0xff) + 1;
+	nsel = ((ctrl >> 12) & 0x3) + 1;
+
+	if (direct || fbsel)
+		return msel * (parent_rate / nsel);
+
+	psel = (ctrl >>  8) & 0x3;
+	psel = 1 << psel;
+
+	return (msel / (2 * psel)) * (parent_rate / nsel);
+}
+
+static const struct clk_ops lpc18xx_pll1_ops = {
+	.recalc_rate = lpc18xx_pll1_recalc_rate,
+};
+
+static struct lpc18xx_cgu_pll_clk lpc18xx_cgu_src_clk_plls[] = {
+	LPC1XX_CGU_CLK_PLL(PLL0USB,	pll0_src_ids, pll0_ops),
+	LPC1XX_CGU_CLK_PLL(PLL0AUDIO,	pll0_src_ids, pll0_ops),
+	LPC1XX_CGU_CLK_PLL(PLL1,	pll1_src_ids, pll1_ops),
+};
+
+static void lpc18xx_fill_parent_names(const char **parent, u32 *id, int size)
+{
+	int i;
+
+	for (i = 0; i < size; i++)
+		parent[i] = clk_src_names[id[i]];
+}
+
+static struct clk *lpc18xx_cgu_register_div(struct lpc18xx_cgu_src_clk_div *clk,
+					    void __iomem *base, int n)
+{
+	void __iomem *reg = base + LPC18XX_CGU_IDIV_CTRL(n);
+	const char *name = clk_src_names[clk->clk_id];
+	const char *parents[CLK_SRC_MAX];
+
+	clk->div.reg = reg;
+	clk->mux.reg = reg;
+	clk->gate.reg = reg;
+
+	lpc18xx_fill_parent_names(parents, clk->mux.table, clk->n_parents);
+
+	return clk_register_composite(NULL, name, parents, clk->n_parents,
+				      &clk->mux.hw, &clk_mux_ops,
+				      &clk->div.hw, &clk_divider_ops,
+				      &clk->gate.hw, &clk_gate_ops, 0);
+}
+
+
+static struct clk *lpc18xx_register_base_clk(struct lpc18xx_cgu_base_clk *clk,
+					     void __iomem *base, int n)
+{
+	void __iomem *reg = base + LPC18XX_CGU_BASE_CLK(n);
+	const char *name = clk_base_names[clk->clk_id];
+	const char *parents[CLK_SRC_MAX];
+
+	if (clk->n_parents == 0)
+		return ERR_PTR(-ENOENT);
+
+	clk->mux.reg = reg;
+	clk->gate.reg = reg;
+
+	lpc18xx_fill_parent_names(parents, clk->mux.table, clk->n_parents);
+
+	/* SAFE_CLK can not be turned off */
+	if (n == BASE_SAFE_CLK)
+		return clk_register_composite(NULL, name, parents, clk->n_parents,
+					      &clk->mux.hw, &clk_mux_ops,
+					      NULL, NULL, NULL, NULL, 0);
+
+	return clk_register_composite(NULL, name, parents, clk->n_parents,
+				      &clk->mux.hw, &clk_mux_ops,
+				      NULL,  NULL,
+				      &clk->gate.hw, &clk_gate_ops, 0);
+}
+
+
+static struct clk *lpc18xx_cgu_register_pll(struct lpc18xx_cgu_pll_clk *clk,
+					    void __iomem *base)
+{
+	const char *name = clk_src_names[clk->clk_id];
+	const char *parents[CLK_SRC_MAX];
+
+	clk->pll.reg  = base;
+	clk->mux.reg  = base + clk->reg_offset + LPC18XX_CGU_PLL_CTRL_OFFSET;
+	clk->gate.reg = base + clk->reg_offset + LPC18XX_CGU_PLL_CTRL_OFFSET;
+
+	lpc18xx_fill_parent_names(parents, clk->mux.table, clk->n_parents);
+
+	return clk_register_composite(NULL, name, parents, clk->n_parents,
+				      &clk->mux.hw, &clk_mux_ops,
+				      &clk->pll.hw, clk->pll_ops,
+				      &clk->gate.hw, &clk_gate_ops, 0);
+}
+
+static void __init lpc18xx_cgu_register_source_clks(void __iomem *base,
+						    struct device_node *np)
+{
+	const char *parents[CLK_SRC_MAX];
+	struct clk *clk;
+	int i;
+
+	/* Register the internal 12 MHz RC oscillator (IRC) */
+	clk = clk_register_fixed_rate(NULL, clk_src_names[CLK_SRC_IRC],
+				      NULL, CLK_IS_ROOT, 12000000);
+	if (IS_ERR(clk))
+		pr_warn("%s: failed to register irc clk\n", __func__);
+
+	/* Register crystal oscillator controlller */
+	parents[0] = of_clk_get_parent_name(np, 0);
+	clk = clk_register_gate(NULL, clk_src_names[CLK_SRC_OSC], parents[0],
+				0, base + LPC18XX_CGU_XTAL_OSC_CTRL,
+				0, CLK_GATE_SET_TO_DISABLE, NULL);
+	if (IS_ERR(clk))
+		pr_warn("%s: failed to register osc clk\n", __func__);
+
+	/* Register all PLLs */
+	for (i = 0; i < ARRAY_SIZE(lpc18xx_cgu_src_clk_plls); i++) {
+		clk = lpc18xx_cgu_register_pll(&lpc18xx_cgu_src_clk_plls[i],
+						   base);
+		if (IS_ERR(clk))
+			pr_warn("%s: failed to register pll (%d)\n", __func__, i);
+	}
+
+	/* Register all clock dividers A-E */
+	for (i = 0; i < ARRAY_SIZE(lpc18xx_cgu_src_clk_divs); i++) {
+		clk = lpc18xx_cgu_register_div(&lpc18xx_cgu_src_clk_divs[i],
+					       base, i);
+		if (IS_ERR(clk))
+			pr_warn("%s: failed to register div %d\n", __func__, i);
+	}
+}
+
+static struct clk *clk_base[BASE_CLK_MAX];
+static struct clk_onecell_data clk_base_data = {
+	.clks = clk_base,
+	.clk_num = BASE_CLK_MAX,
+};
+
+static void __init lpc18xx_cgu_register_base_clks(void __iomem *base)
+{
+	int i;
+
+	for (i = BASE_SAFE_CLK; i < BASE_CLK_MAX; i++) {
+		clk_base[i] = lpc18xx_register_base_clk(&lpc18xx_cgu_base_clks[i],
+							base, i);
+		if (IS_ERR(clk_base[i]) && PTR_ERR(clk_base[i]) != -ENOENT)
+			pr_warn("%s: register base clk %d failed\n", __func__, i);
+	}
+}
+
+static void __init lpc18xx_cgu_init(struct device_node *np)
+{
+	void __iomem *base;
+	const char *name;
+	int i, ret;
+	u32 idx;
+
+	base = of_iomap(np, 0);
+	if (!base) {
+		pr_warn("%s: failed to map address range\n", __func__);
+		return;
+	}
+
+	/* Get base clk names and ids from DT */
+	for (i = 0; i < BASE_CLK_MAX; i++) {
+		ret = of_property_read_u32_index(np, "clock-indices", i, &idx);
+		if (ret)
+			break;
+
+		ret = of_property_read_string_index(np, "clock-output-names",
+						    i, &name);
+		if (ret)
+			break;
+
+		if (idx < BASE_CLK_MAX)
+			clk_base_names[idx] = name;
+	}
+
+	lpc18xx_cgu_register_source_clks(base, np);
+	lpc18xx_cgu_register_base_clks(base);
+
+	of_clk_add_provider(np, of_clk_src_onecell_get, &clk_base_data);
+}
+CLK_OF_DECLARE(lpc18xx_cgu, "nxp,lpc1850-cgu", lpc18xx_cgu_init);
diff --git a/include/dt-bindings/clock/lpc18xx-cgu.h b/include/dt-bindings/clock/lpc18xx-cgu.h
new file mode 100644
index 000000000000..6e57c6d2ca66
--- /dev/null
+++ b/include/dt-bindings/clock/lpc18xx-cgu.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2015 Joachim Eastwood <manabian@gmail.com>
+ *
+ * This code is released using a dual license strategy: BSD/GPL
+ * You can choose the licence that better fits your requirements.
+ *
+ * Released under the terms of 3-clause BSD License
+ * Released under the terms of GNU General Public License Version 2.0
+ *
+ */
+
+/* LPC18xx/43xx base clock ids */
+#define BASE_SAFE_CLK		0
+#define BASE_USB0_CLK		1
+#define BASE_PERIPH_CLK		2
+#define BASE_USB1_CLK		3
+#define BASE_CPU_CLK		4
+#define BASE_SPIFI_CLK		5
+#define BASE_SPI_CLK		6
+#define BASE_PHY_RX_CLK		7
+#define BASE_PHY_TX_CLK		8
+#define BASE_APB1_CLK		9
+#define BASE_APB3_CLK		10
+#define BASE_LCD_CLK		11
+#define BASE_ADCHS_CLK		12
+#define BASE_SDIO_CLK		13
+#define BASE_SSP0_CLK		14
+#define BASE_SSP1_CLK		15
+#define BASE_UART0_CLK		16
+#define BASE_UART1_CLK		17
+#define BASE_UART2_CLK		18
+#define BASE_UART3_CLK		19
+#define BASE_OUT_CLK		20
+#define BASE_RES1_CLK		21
+#define BASE_RES2_CLK		22
+#define BASE_RES3_CLK		23
+#define BASE_RES4_CLK		24
+#define BASE_AUDIO_CLK		25
+#define BASE_CGU_OUT0_CLK	26
+#define BASE_CGU_OUT1_CLK	27
+#define BASE_CLK_MAX		(BASE_CGU_OUT1_CLK + 1)
-- 
1.8.0

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH v2 1/4] clk: add lpc18xx cgu clk driver
@ 2015-04-27 21:38     ` Joachim Eastwood
  0 siblings, 0 replies; 39+ messages in thread
From: Joachim Eastwood @ 2015-04-27 21:38 UTC (permalink / raw)
  To: linux-arm-kernel

Add driver for NXP LPC18xx/43xx Clock Generation Unit (CGU). The CGU
contains several clock generators and output stages that route the
clocks either directly to peripherals or to a Clock Control Unit
(CCU).

Signed-off-by: Joachim Eastwood <manabian@gmail.com>
---
 drivers/clk/Makefile                    |   1 +
 drivers/clk/nxp/Makefile                |   1 +
 drivers/clk/nxp/clk-lpc18xx-cgu.c       | 628 ++++++++++++++++++++++++++++++++
 include/dt-bindings/clock/lpc18xx-cgu.h |  41 +++
 4 files changed, 671 insertions(+)
 create mode 100644 drivers/clk/nxp/Makefile
 create mode 100644 drivers/clk/nxp/clk-lpc18xx-cgu.c
 create mode 100644 include/dt-bindings/clock/lpc18xx-cgu.h

diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index 3d00c25382c5..4a34419c1da1 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -56,6 +56,7 @@ obj-$(CONFIG_ARCH_MMP)			+= mmp/
 endif
 obj-$(CONFIG_PLAT_ORION)		+= mvebu/
 obj-$(CONFIG_ARCH_MXS)			+= mxs/
+obj-$(CONFIG_ARCH_LPC18XX)		+= nxp/
 obj-$(CONFIG_MACH_PISTACHIO)		+= pistachio/
 obj-$(CONFIG_COMMON_CLK_PXA)		+= pxa/
 obj-$(CONFIG_COMMON_CLK_QCOM)		+= qcom/
diff --git a/drivers/clk/nxp/Makefile b/drivers/clk/nxp/Makefile
new file mode 100644
index 000000000000..aca9d3e4f7fe
--- /dev/null
+++ b/drivers/clk/nxp/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_ARCH_LPC18XX)	+= clk-lpc18xx-cgu.o
diff --git a/drivers/clk/nxp/clk-lpc18xx-cgu.c b/drivers/clk/nxp/clk-lpc18xx-cgu.c
new file mode 100644
index 000000000000..15977f5d767f
--- /dev/null
+++ b/drivers/clk/nxp/clk-lpc18xx-cgu.c
@@ -0,0 +1,628 @@
+/*
+ * Clk driver for NXP LPC18xx/LPC43xx Clock Generation Unit (CGU)
+ *
+ * Copyright (C) 2015 Joachim Eastwood <manabian@gmail.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/delay.h>
+#include <linux/kernel.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+
+#include <dt-bindings/clock/lpc18xx-cgu.h>
+
+/* Clock Generation Unit (CGU) registers */
+#define LPC18XX_CGU_XTAL_OSC_CTRL	0x018
+#define LPC18XX_CGU_PLL0USB_STAT	0x01c
+#define LPC18XX_CGU_PLL0USB_CTRL	0x020
+#define LPC18XX_CGU_PLL0USB_MDIV	0x024
+#define LPC18XX_CGU_PLL0USB_NP_DIV	0x028
+#define LPC18XX_CGU_PLL0AUDIO_STAT	0x02c
+#define LPC18XX_CGU_PLL0AUDIO_CTRL	0x030
+#define LPC18XX_CGU_PLL0AUDIO_MDIV	0x034
+#define LPC18XX_CGU_PLL0AUDIO_NP_DIV	0x038
+#define LPC18XX_CGU_PLL0AUDIO_FRAC	0x03c
+#define LPC18XX_CGU_PLL1_STAT		0x040
+#define LPC18XX_CGU_PLL1_CTRL		0x044
+#define  LPC18XX_PLL1_CTRL_FBSEL	BIT(6)
+#define  LPC18XX_PLL1_CTRL_DIRECT	BIT(7)
+#define LPC18XX_CGU_IDIV_CTRL(n)	(0x048 + (n) * sizeof(u32))
+#define LPC18XX_CGU_BASE_CLK(id)	(0x05c + (id) * sizeof(u32))
+#define LPC18XX_CGU_PLL_CTRL_OFFSET	0x4
+
+/* PLL0 bits common to both audio and USB PLL */
+#define LPC18XX_PLL0_STAT_LOCK		BIT(0)
+#define LPC18XX_PLL0_CTRL_PD		BIT(0)
+#define LPC18XX_PLL0_CTRL_BYPASS	BIT(1)
+#define LPC18XX_PLL0_CTRL_DIRECTI	BIT(2)
+#define LPC18XX_PLL0_CTRL_DIRECTO	BIT(3)
+#define LPC18XX_PLL0_CTRL_CLKEN		BIT(4)
+#define LPC18XX_PLL0_MDIV_MDEC_MASK	0x1ffff
+#define LPC18XX_PLL0_MDIV_SELP_SHIFT	17
+#define LPC18XX_PLL0_MDIV_SELI_SHIFT	22
+#define LPC18XX_PLL0_MSEL_MAX		BIT(15)
+
+/* Register value that gives PLL0 post/pre dividers equal to 1 */
+#define LPC18XX_PLL0_NP_DIVS_1		0x00302062
+
+enum {
+	CLK_SRC_OSC32,
+	CLK_SRC_IRC,
+	CLK_SRC_ENET_RX_CLK,
+	CLK_SRC_ENET_TX_CLK,
+	CLK_SRC_GP_CLKIN,
+	CLK_SRC_RESERVED1,
+	CLK_SRC_OSC,
+	CLK_SRC_PLL0USB,
+	CLK_SRC_PLL0AUDIO,
+	CLK_SRC_PLL1,
+	CLK_SRC_RESERVED2,
+	CLK_SRC_RESERVED3,
+	CLK_SRC_IDIVA,
+	CLK_SRC_IDIVB,
+	CLK_SRC_IDIVC,
+	CLK_SRC_IDIVD,
+	CLK_SRC_IDIVE,
+	CLK_SRC_MAX
+};
+
+static const char *clk_src_names[CLK_SRC_MAX] = {
+	[CLK_SRC_OSC32]		= "osc32",
+	[CLK_SRC_IRC]		= "irc",
+	[CLK_SRC_ENET_RX_CLK]	= "enet_rx_clk",
+	[CLK_SRC_ENET_TX_CLK]	= "enet_tx_clk",
+	[CLK_SRC_GP_CLKIN]	= "gp_clkin",
+	[CLK_SRC_OSC]		= "osc",
+	[CLK_SRC_PLL0USB]	= "pll0usb",
+	[CLK_SRC_PLL0AUDIO]	= "pll0audio",
+	[CLK_SRC_PLL1]		= "pll1",
+	[CLK_SRC_IDIVA]		= "idiva",
+	[CLK_SRC_IDIVB]		= "idivb",
+	[CLK_SRC_IDIVC]		= "idivc",
+	[CLK_SRC_IDIVD]		= "idivd",
+	[CLK_SRC_IDIVE]		= "idive",
+};
+
+static const char *clk_base_names[BASE_CLK_MAX];
+
+static u32 lpc18xx_cgu_pll0_src_ids[] = {
+	CLK_SRC_OSC32, CLK_SRC_IRC, CLK_SRC_ENET_RX_CLK,
+	CLK_SRC_ENET_TX_CLK, CLK_SRC_GP_CLKIN, CLK_SRC_OSC,
+	CLK_SRC_PLL1, CLK_SRC_IDIVA, CLK_SRC_IDIVB, CLK_SRC_IDIVC,
+	CLK_SRC_IDIVD, CLK_SRC_IDIVE,
+};
+
+static u32 lpc18xx_cgu_pll1_src_ids[] = {
+	CLK_SRC_OSC32, CLK_SRC_IRC, CLK_SRC_ENET_RX_CLK,
+	CLK_SRC_ENET_TX_CLK, CLK_SRC_GP_CLKIN, CLK_SRC_OSC,
+	CLK_SRC_PLL0USB, CLK_SRC_PLL0AUDIO, CLK_SRC_IDIVA,
+	CLK_SRC_IDIVB, CLK_SRC_IDIVC, CLK_SRC_IDIVD, CLK_SRC_IDIVE,
+};
+
+static u32 lpc18xx_cgu_idiva_src_ids[] = {
+	CLK_SRC_OSC32, CLK_SRC_IRC, CLK_SRC_ENET_RX_CLK,
+	CLK_SRC_ENET_TX_CLK, CLK_SRC_GP_CLKIN, CLK_SRC_OSC,
+	CLK_SRC_PLL0USB, CLK_SRC_PLL0AUDIO, CLK_SRC_PLL1
+};
+
+static u32 lpc18xx_cgu_idivbcde_src_ids[] = {
+	CLK_SRC_OSC32, CLK_SRC_IRC, CLK_SRC_ENET_RX_CLK,
+	CLK_SRC_ENET_TX_CLK, CLK_SRC_GP_CLKIN, CLK_SRC_OSC,
+	CLK_SRC_PLL0AUDIO, CLK_SRC_PLL1, CLK_SRC_IDIVA,
+};
+
+static u32 lpc18xx_cgu_base_irc_src_ids[] = {CLK_SRC_IRC};
+
+static u32 lpc18xx_cgu_base_usb0_src_ids[] = {CLK_SRC_PLL0USB};
+
+static u32 lpc18xx_cgu_base_common_src_ids[] = {
+	CLK_SRC_OSC32, CLK_SRC_IRC, CLK_SRC_ENET_RX_CLK,
+	CLK_SRC_ENET_TX_CLK, CLK_SRC_GP_CLKIN, CLK_SRC_OSC,
+	CLK_SRC_PLL0AUDIO, CLK_SRC_PLL1, CLK_SRC_IDIVA,
+	CLK_SRC_IDIVB, CLK_SRC_IDIVC, CLK_SRC_IDIVD, CLK_SRC_IDIVE,
+};
+
+static u32 lpc18xx_cgu_base_all_src_ids[] = {
+	CLK_SRC_OSC32, CLK_SRC_IRC, CLK_SRC_ENET_RX_CLK,
+	CLK_SRC_ENET_TX_CLK, CLK_SRC_GP_CLKIN, CLK_SRC_OSC,
+	CLK_SRC_PLL0USB, CLK_SRC_PLL0AUDIO, CLK_SRC_PLL1,
+	CLK_SRC_IDIVA, CLK_SRC_IDIVB, CLK_SRC_IDIVC,
+	CLK_SRC_IDIVD, CLK_SRC_IDIVE,
+};
+
+struct lpc18xx_cgu_src_clk_div {
+	u8 clk_id;
+	u8 n_parents;
+	struct clk_divider	div;
+	struct clk_mux		mux;
+	struct clk_gate		gate;
+};
+
+#define LPC1XX_CGU_SRC_CLK_DIV(_id, _width, _table)	\
+{							\
+	.clk_id = CLK_SRC_ ##_id,			\
+	.n_parents = ARRAY_SIZE(lpc18xx_cgu_ ##_table),	\
+	.div = {					\
+		.shift = 2,				\
+		.width = _width,			\
+	},						\
+	.mux = {					\
+		.mask = 0x1f,				\
+		.shift = 24,				\
+		.table = lpc18xx_cgu_ ##_table,		\
+	},						\
+	.gate = {					\
+		.bit_idx = 0,				\
+		.flags = CLK_GATE_SET_TO_DISABLE,	\
+	},						\
+}
+
+static struct lpc18xx_cgu_src_clk_div lpc18xx_cgu_src_clk_divs[] = {
+	LPC1XX_CGU_SRC_CLK_DIV(IDIVA, 2, idiva_src_ids),
+	LPC1XX_CGU_SRC_CLK_DIV(IDIVB, 4, idivbcde_src_ids),
+	LPC1XX_CGU_SRC_CLK_DIV(IDIVC, 4, idivbcde_src_ids),
+	LPC1XX_CGU_SRC_CLK_DIV(IDIVD, 4, idivbcde_src_ids),
+	LPC1XX_CGU_SRC_CLK_DIV(IDIVE, 8, idivbcde_src_ids),
+};
+
+struct lpc18xx_cgu_base_clk {
+	u8 clk_id;
+	u8 n_parents;
+	struct clk_mux mux;
+	struct clk_gate gate;
+};
+
+#define LPC1XX_CGU_BASE_CLK(_id, _table, _flags)	\
+{							\
+	.clk_id = BASE_ ##_id ##_CLK,			\
+	.n_parents = ARRAY_SIZE(lpc18xx_cgu_ ##_table),	\
+	.mux = {					\
+		.mask = 0x1f,				\
+		.shift = 24,				\
+		.table = lpc18xx_cgu_ ##_table,		\
+		.flags = _flags,			\
+	},						\
+	.gate = {					\
+		.bit_idx = 0,				\
+		.flags = CLK_GATE_SET_TO_DISABLE,	\
+	},						\
+}
+
+static struct lpc18xx_cgu_base_clk lpc18xx_cgu_base_clks[] = {
+	LPC1XX_CGU_BASE_CLK(SAFE,	base_irc_src_ids, CLK_MUX_READ_ONLY),
+	LPC1XX_CGU_BASE_CLK(USB0,	base_usb0_src_ids,   0),
+	LPC1XX_CGU_BASE_CLK(PERIPH,	base_common_src_ids, 0),
+	LPC1XX_CGU_BASE_CLK(USB1,	base_all_src_ids,    0),
+	LPC1XX_CGU_BASE_CLK(CPU,	base_common_src_ids, 0),
+	LPC1XX_CGU_BASE_CLK(SPIFI,	base_common_src_ids, 0),
+	LPC1XX_CGU_BASE_CLK(SPI,	base_common_src_ids, 0),
+	LPC1XX_CGU_BASE_CLK(PHY_RX,	base_common_src_ids, 0),
+	LPC1XX_CGU_BASE_CLK(PHY_TX,	base_common_src_ids, 0),
+	LPC1XX_CGU_BASE_CLK(APB1,	base_common_src_ids, 0),
+	LPC1XX_CGU_BASE_CLK(APB3,	base_common_src_ids, 0),
+	LPC1XX_CGU_BASE_CLK(LCD,	base_common_src_ids, 0),
+	LPC1XX_CGU_BASE_CLK(ADCHS,	base_common_src_ids, 0),
+	LPC1XX_CGU_BASE_CLK(SDIO,	base_common_src_ids, 0),
+	LPC1XX_CGU_BASE_CLK(SSP0,	base_common_src_ids, 0),
+	LPC1XX_CGU_BASE_CLK(SSP1,	base_common_src_ids, 0),
+	LPC1XX_CGU_BASE_CLK(UART0,	base_common_src_ids, 0),
+	LPC1XX_CGU_BASE_CLK(UART1,	base_common_src_ids, 0),
+	LPC1XX_CGU_BASE_CLK(UART2,	base_common_src_ids, 0),
+	LPC1XX_CGU_BASE_CLK(UART3,	base_common_src_ids, 0),
+	LPC1XX_CGU_BASE_CLK(OUT,	base_all_src_ids,    0),
+	{ /* 21 reserved */ },
+	{ /* 22 reserved */ },
+	{ /* 23 reserved */ },
+	{ /* 24 reserved */ },
+	LPC1XX_CGU_BASE_CLK(AUDIO,	base_common_src_ids, 0),
+	LPC1XX_CGU_BASE_CLK(CGU_OUT0,	base_all_src_ids,    0),
+	LPC1XX_CGU_BASE_CLK(CGU_OUT1,	base_all_src_ids,    0),
+};
+
+struct lpc18xx_pll {
+	struct		clk_hw hw;
+	void __iomem	*reg;
+	spinlock_t	*lock;
+	u8		flags;
+};
+
+#define to_lpc_pll(hw) container_of(hw, struct lpc18xx_pll, hw)
+
+struct lpc18xx_cgu_pll_clk {
+	u8 clk_id;
+	u8 n_parents;
+	u8 reg_offset;
+	struct clk_mux mux;
+	struct clk_gate gate;
+	struct lpc18xx_pll pll;
+	const struct clk_ops *pll_ops;
+};
+
+#define LPC1XX_CGU_CLK_PLL(_id, _table, _pll_ops)	\
+{							\
+	.clk_id = CLK_SRC_ ##_id,			\
+	.n_parents = ARRAY_SIZE(lpc18xx_cgu_ ##_table),	\
+	.reg_offset = LPC18XX_CGU_ ##_id ##_STAT,	\
+	.mux = {					\
+		.mask = 0x1f,				\
+		.shift = 24,				\
+		.table = lpc18xx_cgu_ ##_table,		\
+	},						\
+	.gate = {					\
+		.bit_idx = 0,				\
+		.flags = CLK_GATE_SET_TO_DISABLE,	\
+	},						\
+	.pll_ops = &lpc18xx_ ##_pll_ops,		\
+}
+
+/*
+ * PLL0 uses a special register value encoding. The compute functions below
+ * are taken or derived from the LPC1850 user manual (section 12.6.3.3).
+ */
+
+/* Compute PLL0 multiplier from decoded version */
+static u32 lpc18xx_pll0_mdec2msel(u32 x)
+{
+	int i;
+
+	switch (x) {
+	case 0x18003: return 1;
+	case 0x10003: return 2;
+	default:
+		for (i = LPC18XX_PLL0_MSEL_MAX + 1; x != 0x4000 && i > 0; i--)
+			x = ((x ^ x >> 14) & 1) | (x << 1 & 0x7fff);
+		return i;
+	}
+}
+/* Compute PLL0 decoded multiplier from binary version */
+static u32 lpc18xx_pll0_msel2mdec(u32 msel)
+{
+	u32 i, x = 0x4000;
+
+	switch (msel) {
+	case 0: return 0;
+	case 1: return 0x18003;
+	case 2: return 0x10003;
+	default:
+		for (i = msel; i <= LPC18XX_PLL0_MSEL_MAX; i++)
+			x = ((x ^ x >> 1) & 1) << 14 | (x >> 1 & 0xffff);
+		return x;
+	}
+}
+
+/* Compute PLL0 bandwidth SELI reg from multiplier */
+static u32 lpc18xx_pll0_msel2seli(u32 msel)
+{
+	u32 tmp;
+
+	if (msel > 16384) return 1;
+	if (msel >  8192) return 2;
+	if (msel >  2048) return 4;
+	if (msel >=  501) return 8;
+	if (msel >=   60) {
+		tmp = 1024 / (msel + 9);
+		return ((1024 == (tmp * (msel + 9))) == 0) ? tmp * 4 : (tmp + 1) * 4;
+	}
+
+	return (msel & 0x3c) + 4;
+}
+
+/* Compute PLL0 bandwidth SELP reg from multiplier */
+static u32 lpc18xx_pll0_msel2selp(u32 msel)
+{
+	if (msel < 60)
+		return (msel >> 1) + 1;
+
+	return 31;
+}
+
+static unsigned long lpc18xx_pll0_recalc_rate(struct clk_hw *hw,
+					      unsigned long parent_rate)
+{
+	struct lpc18xx_pll *pll = to_lpc_pll(hw);
+	u32 ctrl, mdiv, msel, npdiv;
+
+	ctrl = clk_readl(pll->reg + LPC18XX_CGU_PLL0USB_CTRL);
+	mdiv = clk_readl(pll->reg + LPC18XX_CGU_PLL0USB_MDIV);
+	npdiv = clk_readl(pll->reg + LPC18XX_CGU_PLL0USB_NP_DIV);
+
+	if (ctrl & LPC18XX_PLL0_CTRL_BYPASS)
+		return parent_rate;
+
+	if (npdiv != LPC18XX_PLL0_NP_DIVS_1) {
+		pr_warn("%s: pre/post dividers not supported\n", __func__);
+		return 0;
+	}
+
+	msel = lpc18xx_pll0_mdec2msel(mdiv & LPC18XX_PLL0_MDIV_MDEC_MASK);
+	if (msel)
+		return 2 * msel * parent_rate;
+
+	pr_warn("%s: unable to calculate rate\n", __func__);
+
+	return 0;
+}
+
+static long lpc18xx_pll0_round_rate(struct clk_hw *hw, unsigned long rate,
+				    unsigned long *prate)
+{
+	unsigned long m;
+
+	if (*prate < rate) {
+		pr_warn("%s: pll dividers not supported\n", __func__);
+		return -EINVAL;
+	}
+
+	m = DIV_ROUND_UP_ULL(*prate, rate * 2);
+	if (m <= 0 && m > LPC18XX_PLL0_MSEL_MAX) {
+		pr_warn("%s: unable to support rate %lu\n", __func__, rate);
+		return -EINVAL;
+	}
+
+	return 2 * *prate * m;
+}
+
+static int lpc18xx_pll0_set_rate(struct clk_hw *hw, unsigned long rate,
+				 unsigned long parent_rate)
+{
+	struct lpc18xx_pll *pll = to_lpc_pll(hw);
+	u32 ctrl, stat, m;
+	int retry = 3;
+
+	if (parent_rate < rate) {
+		pr_warn("%s: pll dividers not supported\n", __func__);
+		return -EINVAL;
+	}
+
+	m = DIV_ROUND_UP_ULL(parent_rate, rate * 2);
+	if (m <= 0 && m > LPC18XX_PLL0_MSEL_MAX) {
+		pr_warn("%s: unable to support rate %lu\n", __func__, rate);
+		return -EINVAL;
+	}
+
+	m  = lpc18xx_pll0_msel2mdec(m);
+	m |= lpc18xx_pll0_msel2selp(m) << LPC18XX_PLL0_MDIV_SELP_SHIFT;
+	m |= lpc18xx_pll0_msel2seli(m) << LPC18XX_PLL0_MDIV_SELI_SHIFT;
+
+	/* Power down PLL, disable clk output and dividers */
+	ctrl = clk_readl(pll->reg + LPC18XX_CGU_PLL0USB_CTRL);
+	ctrl |= LPC18XX_PLL0_CTRL_PD;
+	ctrl &= ~(LPC18XX_PLL0_CTRL_BYPASS | LPC18XX_PLL0_CTRL_DIRECTI |
+		  LPC18XX_PLL0_CTRL_DIRECTO | LPC18XX_PLL0_CTRL_CLKEN);
+	clk_writel(ctrl, pll->reg + LPC18XX_CGU_PLL0USB_CTRL);
+
+	/* Configure new PLL settings */
+	clk_writel(m, pll->reg + LPC18XX_CGU_PLL0USB_MDIV);
+	clk_writel(LPC18XX_PLL0_NP_DIVS_1, pll->reg + LPC18XX_CGU_PLL0USB_NP_DIV);
+
+	/* Power up PLL and wait for lock */
+	ctrl &= ~LPC18XX_PLL0_CTRL_PD;
+	clk_writel(ctrl, pll->reg + LPC18XX_CGU_PLL0USB_CTRL);
+	do {
+		udelay(10);
+		stat = clk_readl(pll->reg + LPC18XX_CGU_PLL0USB_STAT);
+		if (stat & LPC18XX_PLL0_STAT_LOCK) {
+			ctrl |= LPC18XX_PLL0_CTRL_CLKEN;
+			clk_writel(ctrl, pll->reg + LPC18XX_CGU_PLL0USB_CTRL);
+
+			return 0;
+		}
+	} while (retry--);
+
+	pr_warn("%s: unable to lock pll\n", __func__);
+
+	return -EINVAL;
+}
+
+static const struct clk_ops lpc18xx_pll0_ops = {
+	.recalc_rate	= lpc18xx_pll0_recalc_rate,
+	.round_rate	= lpc18xx_pll0_round_rate,
+	.set_rate	= lpc18xx_pll0_set_rate,
+};
+
+static unsigned long lpc18xx_pll1_recalc_rate(struct clk_hw *hw,
+					      unsigned long parent_rate)
+{
+	struct lpc18xx_pll *pll = to_lpc_pll(hw);
+	u16 msel, nsel, psel;
+	bool direct, fbsel;
+	u32 stat, ctrl;
+
+	stat = clk_readl(pll->reg + LPC18XX_CGU_PLL1_STAT);
+	ctrl = clk_readl(pll->reg + LPC18XX_CGU_PLL1_CTRL);
+
+	direct = (ctrl & LPC18XX_PLL1_CTRL_DIRECT) ? true : false;
+	fbsel = (ctrl & LPC18XX_PLL1_CTRL_FBSEL) ? true : false;
+
+	msel = ((ctrl >> 16) & 0xff) + 1;
+	nsel = ((ctrl >> 12) & 0x3) + 1;
+
+	if (direct || fbsel)
+		return msel * (parent_rate / nsel);
+
+	psel = (ctrl >>  8) & 0x3;
+	psel = 1 << psel;
+
+	return (msel / (2 * psel)) * (parent_rate / nsel);
+}
+
+static const struct clk_ops lpc18xx_pll1_ops = {
+	.recalc_rate = lpc18xx_pll1_recalc_rate,
+};
+
+static struct lpc18xx_cgu_pll_clk lpc18xx_cgu_src_clk_plls[] = {
+	LPC1XX_CGU_CLK_PLL(PLL0USB,	pll0_src_ids, pll0_ops),
+	LPC1XX_CGU_CLK_PLL(PLL0AUDIO,	pll0_src_ids, pll0_ops),
+	LPC1XX_CGU_CLK_PLL(PLL1,	pll1_src_ids, pll1_ops),
+};
+
+static void lpc18xx_fill_parent_names(const char **parent, u32 *id, int size)
+{
+	int i;
+
+	for (i = 0; i < size; i++)
+		parent[i] = clk_src_names[id[i]];
+}
+
+static struct clk *lpc18xx_cgu_register_div(struct lpc18xx_cgu_src_clk_div *clk,
+					    void __iomem *base, int n)
+{
+	void __iomem *reg = base + LPC18XX_CGU_IDIV_CTRL(n);
+	const char *name = clk_src_names[clk->clk_id];
+	const char *parents[CLK_SRC_MAX];
+
+	clk->div.reg = reg;
+	clk->mux.reg = reg;
+	clk->gate.reg = reg;
+
+	lpc18xx_fill_parent_names(parents, clk->mux.table, clk->n_parents);
+
+	return clk_register_composite(NULL, name, parents, clk->n_parents,
+				      &clk->mux.hw, &clk_mux_ops,
+				      &clk->div.hw, &clk_divider_ops,
+				      &clk->gate.hw, &clk_gate_ops, 0);
+}
+
+
+static struct clk *lpc18xx_register_base_clk(struct lpc18xx_cgu_base_clk *clk,
+					     void __iomem *base, int n)
+{
+	void __iomem *reg = base + LPC18XX_CGU_BASE_CLK(n);
+	const char *name = clk_base_names[clk->clk_id];
+	const char *parents[CLK_SRC_MAX];
+
+	if (clk->n_parents == 0)
+		return ERR_PTR(-ENOENT);
+
+	clk->mux.reg = reg;
+	clk->gate.reg = reg;
+
+	lpc18xx_fill_parent_names(parents, clk->mux.table, clk->n_parents);
+
+	/* SAFE_CLK can not be turned off */
+	if (n == BASE_SAFE_CLK)
+		return clk_register_composite(NULL, name, parents, clk->n_parents,
+					      &clk->mux.hw, &clk_mux_ops,
+					      NULL, NULL, NULL, NULL, 0);
+
+	return clk_register_composite(NULL, name, parents, clk->n_parents,
+				      &clk->mux.hw, &clk_mux_ops,
+				      NULL,  NULL,
+				      &clk->gate.hw, &clk_gate_ops, 0);
+}
+
+
+static struct clk *lpc18xx_cgu_register_pll(struct lpc18xx_cgu_pll_clk *clk,
+					    void __iomem *base)
+{
+	const char *name = clk_src_names[clk->clk_id];
+	const char *parents[CLK_SRC_MAX];
+
+	clk->pll.reg  = base;
+	clk->mux.reg  = base + clk->reg_offset + LPC18XX_CGU_PLL_CTRL_OFFSET;
+	clk->gate.reg = base + clk->reg_offset + LPC18XX_CGU_PLL_CTRL_OFFSET;
+
+	lpc18xx_fill_parent_names(parents, clk->mux.table, clk->n_parents);
+
+	return clk_register_composite(NULL, name, parents, clk->n_parents,
+				      &clk->mux.hw, &clk_mux_ops,
+				      &clk->pll.hw, clk->pll_ops,
+				      &clk->gate.hw, &clk_gate_ops, 0);
+}
+
+static void __init lpc18xx_cgu_register_source_clks(void __iomem *base,
+						    struct device_node *np)
+{
+	const char *parents[CLK_SRC_MAX];
+	struct clk *clk;
+	int i;
+
+	/* Register the internal 12 MHz RC oscillator (IRC) */
+	clk = clk_register_fixed_rate(NULL, clk_src_names[CLK_SRC_IRC],
+				      NULL, CLK_IS_ROOT, 12000000);
+	if (IS_ERR(clk))
+		pr_warn("%s: failed to register irc clk\n", __func__);
+
+	/* Register crystal oscillator controlller */
+	parents[0] = of_clk_get_parent_name(np, 0);
+	clk = clk_register_gate(NULL, clk_src_names[CLK_SRC_OSC], parents[0],
+				0, base + LPC18XX_CGU_XTAL_OSC_CTRL,
+				0, CLK_GATE_SET_TO_DISABLE, NULL);
+	if (IS_ERR(clk))
+		pr_warn("%s: failed to register osc clk\n", __func__);
+
+	/* Register all PLLs */
+	for (i = 0; i < ARRAY_SIZE(lpc18xx_cgu_src_clk_plls); i++) {
+		clk = lpc18xx_cgu_register_pll(&lpc18xx_cgu_src_clk_plls[i],
+						   base);
+		if (IS_ERR(clk))
+			pr_warn("%s: failed to register pll (%d)\n", __func__, i);
+	}
+
+	/* Register all clock dividers A-E */
+	for (i = 0; i < ARRAY_SIZE(lpc18xx_cgu_src_clk_divs); i++) {
+		clk = lpc18xx_cgu_register_div(&lpc18xx_cgu_src_clk_divs[i],
+					       base, i);
+		if (IS_ERR(clk))
+			pr_warn("%s: failed to register div %d\n", __func__, i);
+	}
+}
+
+static struct clk *clk_base[BASE_CLK_MAX];
+static struct clk_onecell_data clk_base_data = {
+	.clks = clk_base,
+	.clk_num = BASE_CLK_MAX,
+};
+
+static void __init lpc18xx_cgu_register_base_clks(void __iomem *base)
+{
+	int i;
+
+	for (i = BASE_SAFE_CLK; i < BASE_CLK_MAX; i++) {
+		clk_base[i] = lpc18xx_register_base_clk(&lpc18xx_cgu_base_clks[i],
+							base, i);
+		if (IS_ERR(clk_base[i]) && PTR_ERR(clk_base[i]) != -ENOENT)
+			pr_warn("%s: register base clk %d failed\n", __func__, i);
+	}
+}
+
+static void __init lpc18xx_cgu_init(struct device_node *np)
+{
+	void __iomem *base;
+	const char *name;
+	int i, ret;
+	u32 idx;
+
+	base = of_iomap(np, 0);
+	if (!base) {
+		pr_warn("%s: failed to map address range\n", __func__);
+		return;
+	}
+
+	/* Get base clk names and ids from DT */
+	for (i = 0; i < BASE_CLK_MAX; i++) {
+		ret = of_property_read_u32_index(np, "clock-indices", i, &idx);
+		if (ret)
+			break;
+
+		ret = of_property_read_string_index(np, "clock-output-names",
+						    i, &name);
+		if (ret)
+			break;
+
+		if (idx < BASE_CLK_MAX)
+			clk_base_names[idx] = name;
+	}
+
+	lpc18xx_cgu_register_source_clks(base, np);
+	lpc18xx_cgu_register_base_clks(base);
+
+	of_clk_add_provider(np, of_clk_src_onecell_get, &clk_base_data);
+}
+CLK_OF_DECLARE(lpc18xx_cgu, "nxp,lpc1850-cgu", lpc18xx_cgu_init);
diff --git a/include/dt-bindings/clock/lpc18xx-cgu.h b/include/dt-bindings/clock/lpc18xx-cgu.h
new file mode 100644
index 000000000000..6e57c6d2ca66
--- /dev/null
+++ b/include/dt-bindings/clock/lpc18xx-cgu.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2015 Joachim Eastwood <manabian@gmail.com>
+ *
+ * This code is released using a dual license strategy: BSD/GPL
+ * You can choose the licence that better fits your requirements.
+ *
+ * Released under the terms of 3-clause BSD License
+ * Released under the terms of GNU General Public License Version 2.0
+ *
+ */
+
+/* LPC18xx/43xx base clock ids */
+#define BASE_SAFE_CLK		0
+#define BASE_USB0_CLK		1
+#define BASE_PERIPH_CLK		2
+#define BASE_USB1_CLK		3
+#define BASE_CPU_CLK		4
+#define BASE_SPIFI_CLK		5
+#define BASE_SPI_CLK		6
+#define BASE_PHY_RX_CLK		7
+#define BASE_PHY_TX_CLK		8
+#define BASE_APB1_CLK		9
+#define BASE_APB3_CLK		10
+#define BASE_LCD_CLK		11
+#define BASE_ADCHS_CLK		12
+#define BASE_SDIO_CLK		13
+#define BASE_SSP0_CLK		14
+#define BASE_SSP1_CLK		15
+#define BASE_UART0_CLK		16
+#define BASE_UART1_CLK		17
+#define BASE_UART2_CLK		18
+#define BASE_UART3_CLK		19
+#define BASE_OUT_CLK		20
+#define BASE_RES1_CLK		21
+#define BASE_RES2_CLK		22
+#define BASE_RES3_CLK		23
+#define BASE_RES4_CLK		24
+#define BASE_AUDIO_CLK		25
+#define BASE_CGU_OUT0_CLK	26
+#define BASE_CGU_OUT1_CLK	27
+#define BASE_CLK_MAX		(BASE_CGU_OUT1_CLK + 1)
-- 
1.8.0

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH v2 2/4] doc: dt: add documentation for lpc1850-cgu clk driver
  2015-04-27 21:38 ` Joachim Eastwood
  (?)
@ 2015-04-27 21:38     ` Joachim Eastwood
  -1 siblings, 0 replies; 39+ messages in thread
From: Joachim Eastwood @ 2015-04-27 21:38 UTC (permalink / raw)
  To: mturquette-QSEj5FYQhm4dnm+yROfE0A, sboyd-sgV2jX0FEOL9JmXXK+q4OQ,
	arnd-r2nGTMty4D4, linux-clk-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
  Cc: devicetree-u79uwXL29TY76Z2rM5mHXA,
	ariel.dalessandro-Re5JQEeQqe8AvxtiuMwx3w,
	ezequiel-30ULvvUtt6G51wMPkGsGjgyUoB5FGQPZ, Joachim Eastwood

Add DT binding documentation for lpc1850-cgu driver.

Signed-off-by: Joachim Eastwood <manabian-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
---
 .../devicetree/bindings/clock/lpc1850-cgu.txt      | 138 +++++++++++++++++++++
 1 file changed, 138 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/clock/lpc1850-cgu.txt

diff --git a/Documentation/devicetree/bindings/clock/lpc1850-cgu.txt b/Documentation/devicetree/bindings/clock/lpc1850-cgu.txt
new file mode 100644
index 000000000000..0b278ca6aee7
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/lpc1850-cgu.txt
@@ -0,0 +1,138 @@
+* NXP LPC1850 Clock Generation Unit (CGU)
+
+The CGU generates multiple independent clocks for the core and the
+peripheral blocks of the LPC18xx. Each independent clock is called
+a base clock and itself is one of the inputs to the two Clock
+Control Units (CCUs) which control the branch clocks to the
+individual peripherals.
+
+The CGU selects the inputs to the clock generators from multiple
+clock sources, controls the clock generation, and routes the outputs
+of the clock generators through the clock source bus to the output
+stages. Each output stage provides an independent clock source and
+corresponds to one of the base clocks for the LPC18xx.
+
+ - Above text taken from NXP LPC1850 User Manual.
+
+
+This binding uses the common clock binding:
+    Documentation/devicetree/bindings/clock/clock-bindings.txt
+
+Required properties:
+- compatible:
+	Should be "nxp,lpc1850-cgu"
+- reg:
+	Shall define the base and range of the address space
+	containing clock control registers
+- #clock-cells:
+	Shall have value <1>.  The permitted clock-specifier values
+	are the base clock numbers defined below.
+- clocks:
+	Shall contain a list of phandles for the external input
+	sources to the CGU. The list shall be in the following
+	order: xtal, 32khz, enet_rx_clk, enet_tx_clk, gp_clkin.
+- clock-indices:
+	Shall be an ordered list of numbers defining the base clock
+	number provided by the CGU.
+- clock-output-names:
+	Shall be an ordered list of strings defining the names of
+	the clocks provided by the CGU.
+
+Which base clocks that are available on the CGU depends on the
+specific LPC part. Base cloks are numbered from 0 to 27.
+
+Number:		Name:			Description:
+ 0		BASE_SAFE_CLK		Base safe clock (always on) for WWDT
+ 1		BASE_USB0_CLK		Base clock for USB0
+ 2		BASE_PERIPH_CLK		Base clock for Cortex-M0SUB subsystem,
+					SPI, and SGPIO
+ 3		BASE_USB1_CLK		Base clock for USB1
+ 4		BASE_CPU_CLK		System base clock for ARM Cortex-M core
+					and APB peripheral blocks #0 and #2
+ 5		BASE_SPIFI_CLK		Base clock for SPIFI
+ 6		BASE_SPI_CLK		Base clock for SPI
+ 7		BASE_PHY_RX_CLK		Base clock for Ethernet PHY Receive clock
+ 8		BASE_PHY_TX_CLK		Base clock for Ethernet PHY Transmit clock
+ 9		BASE_APB1_CLK		Base clock for APB peripheral block # 1
+10		BASE_APB3_CLK		Base clock for APB peripheral block # 3
+11		BASE_LCD_CLK		Base clock for LCD
+12		BASE_ADCHS_CLK		Base clock for ADCHS
+13		BASE_SDIO_CLK		Base clock for SD/MMC
+14		BASE_SSP0_CLK		Base clock for SSP0
+15		BASE_SSP1_CLK		Base clock for SSP1
+16		BASE_UART0_CLK		Base clock for UART0
+17		BASE_UART1_CLK		Base clock for UART1
+18		BASE_UART2_CLK		Base clock for UART2
+19		BASE_UART3_CLK		Base clock for UART3
+20		BASE_OUT_CLK		Base clock for CLKOUT pin
+24-21		-			Reserved
+25		BASE_AUDIO_CLK		Base clock for audio system (I2S)
+26 		BASE_CGU_OUT0_CLK	Base clock for CGU_OUT0 clock output
+27 		BASE_CGU_OUT1_CLK	Base clock for CGU_OUT1 clock output
+
+BASE_PERIPH_CLK and BASE_SPI_CLK is only available on LPC43xx.
+BASE_ADCHS_CLK is only available on LPC4370.
+
+
+Example board file:
+
+/ {
+	clocks {
+		xtal: xtal {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <12000000>;
+		};
+
+		xtal32: xtal32 {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <32768>;
+		};
+
+		enet_rx_clk: enet_rx_clk {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <0>;
+			clock-output-names = "enet_rx_clk";
+		};
+
+		enet_tx_clk: enet_tx_clk {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <0>;
+			clock-output-names = "enet_tx_clk";
+		};
+
+		gp_clkin: gp_clkin {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <0>;
+			clock-output-names = "gp_clkin";
+		};
+	};
+
+	soc {
+		cgu: cgu@40050000 {
+			compatible = "nxp,lpc1850-cgu";
+			reg = <0x40050000 0x1000>;
+			#clock-cells = <1>;
+			clocks = <&xtal>, <&creg_clk 1>, <&enet_rx_clk>, <&enet_tx_clk>, <&gp_clkin>;
+			clock-indices =  <0>,  <1>,  <2>,  <3>,  <4>,  <5>,  <6>,  <7>,
+					 <8>,  <9>, <10>, <11>, <12>, <13>, <14>, <15>,
+					<16>, <17>, <18>, <19>, <20>, <25>, <26>, <27>;
+			clock-output-names = "base_safe_clk",    "base_usb0_clk",
+					     "base_periph_clk",  "base_usb1_clk",
+					     "base_cpu_clk",     "base_spifi_clk",
+					     "base_spi_clk",     "base_phy_rx_clk",
+					     "base_phy_tx_clk",  "base_apb1_clk",
+					     "base_apb3_clk",    "base_lcd_clk",
+					     "base_adchs_clk",   "base_sdio_clk",
+					     "base_ssp0_clk",    "base_ssp1_clk",
+					     "base_uart0_clk",   "base_uart1_clk",
+					     "base_uart2_clk",   "base_uart3_clk",
+					     "base_out_clk",     "base_audio_clk",
+					     "base_cgu_out0_clk","base_cgu_out1_clk";
+		};
+	};
+};
-- 
1.8.0

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH v2 2/4] doc: dt: add documentation for lpc1850-cgu clk driver
@ 2015-04-27 21:38     ` Joachim Eastwood
  0 siblings, 0 replies; 39+ messages in thread
From: Joachim Eastwood @ 2015-04-27 21:38 UTC (permalink / raw)
  To: mturquette, sboyd, arnd, linux-clk, linux-arm-kernel
  Cc: devicetree, ariel.dalessandro, ezequiel, Joachim Eastwood

Add DT binding documentation for lpc1850-cgu driver.

Signed-off-by: Joachim Eastwood <manabian@gmail.com>
---
 .../devicetree/bindings/clock/lpc1850-cgu.txt      | 138 +++++++++++++++++++++
 1 file changed, 138 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/clock/lpc1850-cgu.txt

diff --git a/Documentation/devicetree/bindings/clock/lpc1850-cgu.txt b/Documentation/devicetree/bindings/clock/lpc1850-cgu.txt
new file mode 100644
index 000000000000..0b278ca6aee7
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/lpc1850-cgu.txt
@@ -0,0 +1,138 @@
+* NXP LPC1850 Clock Generation Unit (CGU)
+
+The CGU generates multiple independent clocks for the core and the
+peripheral blocks of the LPC18xx. Each independent clock is called
+a base clock and itself is one of the inputs to the two Clock
+Control Units (CCUs) which control the branch clocks to the
+individual peripherals.
+
+The CGU selects the inputs to the clock generators from multiple
+clock sources, controls the clock generation, and routes the outputs
+of the clock generators through the clock source bus to the output
+stages. Each output stage provides an independent clock source and
+corresponds to one of the base clocks for the LPC18xx.
+
+ - Above text taken from NXP LPC1850 User Manual.
+
+
+This binding uses the common clock binding:
+    Documentation/devicetree/bindings/clock/clock-bindings.txt
+
+Required properties:
+- compatible:
+	Should be "nxp,lpc1850-cgu"
+- reg:
+	Shall define the base and range of the address space
+	containing clock control registers
+- #clock-cells:
+	Shall have value <1>.  The permitted clock-specifier values
+	are the base clock numbers defined below.
+- clocks:
+	Shall contain a list of phandles for the external input
+	sources to the CGU. The list shall be in the following
+	order: xtal, 32khz, enet_rx_clk, enet_tx_clk, gp_clkin.
+- clock-indices:
+	Shall be an ordered list of numbers defining the base clock
+	number provided by the CGU.
+- clock-output-names:
+	Shall be an ordered list of strings defining the names of
+	the clocks provided by the CGU.
+
+Which base clocks that are available on the CGU depends on the
+specific LPC part. Base cloks are numbered from 0 to 27.
+
+Number:		Name:			Description:
+ 0		BASE_SAFE_CLK		Base safe clock (always on) for WWDT
+ 1		BASE_USB0_CLK		Base clock for USB0
+ 2		BASE_PERIPH_CLK		Base clock for Cortex-M0SUB subsystem,
+					SPI, and SGPIO
+ 3		BASE_USB1_CLK		Base clock for USB1
+ 4		BASE_CPU_CLK		System base clock for ARM Cortex-M core
+					and APB peripheral blocks #0 and #2
+ 5		BASE_SPIFI_CLK		Base clock for SPIFI
+ 6		BASE_SPI_CLK		Base clock for SPI
+ 7		BASE_PHY_RX_CLK		Base clock for Ethernet PHY Receive clock
+ 8		BASE_PHY_TX_CLK		Base clock for Ethernet PHY Transmit clock
+ 9		BASE_APB1_CLK		Base clock for APB peripheral block # 1
+10		BASE_APB3_CLK		Base clock for APB peripheral block # 3
+11		BASE_LCD_CLK		Base clock for LCD
+12		BASE_ADCHS_CLK		Base clock for ADCHS
+13		BASE_SDIO_CLK		Base clock for SD/MMC
+14		BASE_SSP0_CLK		Base clock for SSP0
+15		BASE_SSP1_CLK		Base clock for SSP1
+16		BASE_UART0_CLK		Base clock for UART0
+17		BASE_UART1_CLK		Base clock for UART1
+18		BASE_UART2_CLK		Base clock for UART2
+19		BASE_UART3_CLK		Base clock for UART3
+20		BASE_OUT_CLK		Base clock for CLKOUT pin
+24-21		-			Reserved
+25		BASE_AUDIO_CLK		Base clock for audio system (I2S)
+26 		BASE_CGU_OUT0_CLK	Base clock for CGU_OUT0 clock output
+27 		BASE_CGU_OUT1_CLK	Base clock for CGU_OUT1 clock output
+
+BASE_PERIPH_CLK and BASE_SPI_CLK is only available on LPC43xx.
+BASE_ADCHS_CLK is only available on LPC4370.
+
+
+Example board file:
+
+/ {
+	clocks {
+		xtal: xtal {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <12000000>;
+		};
+
+		xtal32: xtal32 {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <32768>;
+		};
+
+		enet_rx_clk: enet_rx_clk {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <0>;
+			clock-output-names = "enet_rx_clk";
+		};
+
+		enet_tx_clk: enet_tx_clk {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <0>;
+			clock-output-names = "enet_tx_clk";
+		};
+
+		gp_clkin: gp_clkin {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <0>;
+			clock-output-names = "gp_clkin";
+		};
+	};
+
+	soc {
+		cgu: cgu@40050000 {
+			compatible = "nxp,lpc1850-cgu";
+			reg = <0x40050000 0x1000>;
+			#clock-cells = <1>;
+			clocks = <&xtal>, <&creg_clk 1>, <&enet_rx_clk>, <&enet_tx_clk>, <&gp_clkin>;
+			clock-indices =  <0>,  <1>,  <2>,  <3>,  <4>,  <5>,  <6>,  <7>,
+					 <8>,  <9>, <10>, <11>, <12>, <13>, <14>, <15>,
+					<16>, <17>, <18>, <19>, <20>, <25>, <26>, <27>;
+			clock-output-names = "base_safe_clk",    "base_usb0_clk",
+					     "base_periph_clk",  "base_usb1_clk",
+					     "base_cpu_clk",     "base_spifi_clk",
+					     "base_spi_clk",     "base_phy_rx_clk",
+					     "base_phy_tx_clk",  "base_apb1_clk",
+					     "base_apb3_clk",    "base_lcd_clk",
+					     "base_adchs_clk",   "base_sdio_clk",
+					     "base_ssp0_clk",    "base_ssp1_clk",
+					     "base_uart0_clk",   "base_uart1_clk",
+					     "base_uart2_clk",   "base_uart3_clk",
+					     "base_out_clk",     "base_audio_clk",
+					     "base_cgu_out0_clk","base_cgu_out1_clk";
+		};
+	};
+};
-- 
1.8.0

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH v2 2/4] doc: dt: add documentation for lpc1850-cgu clk driver
@ 2015-04-27 21:38     ` Joachim Eastwood
  0 siblings, 0 replies; 39+ messages in thread
From: Joachim Eastwood @ 2015-04-27 21:38 UTC (permalink / raw)
  To: linux-arm-kernel

Add DT binding documentation for lpc1850-cgu driver.

Signed-off-by: Joachim Eastwood <manabian@gmail.com>
---
 .../devicetree/bindings/clock/lpc1850-cgu.txt      | 138 +++++++++++++++++++++
 1 file changed, 138 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/clock/lpc1850-cgu.txt

diff --git a/Documentation/devicetree/bindings/clock/lpc1850-cgu.txt b/Documentation/devicetree/bindings/clock/lpc1850-cgu.txt
new file mode 100644
index 000000000000..0b278ca6aee7
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/lpc1850-cgu.txt
@@ -0,0 +1,138 @@
+* NXP LPC1850 Clock Generation Unit (CGU)
+
+The CGU generates multiple independent clocks for the core and the
+peripheral blocks of the LPC18xx. Each independent clock is called
+a base clock and itself is one of the inputs to the two Clock
+Control Units (CCUs) which control the branch clocks to the
+individual peripherals.
+
+The CGU selects the inputs to the clock generators from multiple
+clock sources, controls the clock generation, and routes the outputs
+of the clock generators through the clock source bus to the output
+stages. Each output stage provides an independent clock source and
+corresponds to one of the base clocks for the LPC18xx.
+
+ - Above text taken from NXP LPC1850 User Manual.
+
+
+This binding uses the common clock binding:
+    Documentation/devicetree/bindings/clock/clock-bindings.txt
+
+Required properties:
+- compatible:
+	Should be "nxp,lpc1850-cgu"
+- reg:
+	Shall define the base and range of the address space
+	containing clock control registers
+- #clock-cells:
+	Shall have value <1>.  The permitted clock-specifier values
+	are the base clock numbers defined below.
+- clocks:
+	Shall contain a list of phandles for the external input
+	sources to the CGU. The list shall be in the following
+	order: xtal, 32khz, enet_rx_clk, enet_tx_clk, gp_clkin.
+- clock-indices:
+	Shall be an ordered list of numbers defining the base clock
+	number provided by the CGU.
+- clock-output-names:
+	Shall be an ordered list of strings defining the names of
+	the clocks provided by the CGU.
+
+Which base clocks that are available on the CGU depends on the
+specific LPC part. Base cloks are numbered from 0 to 27.
+
+Number:		Name:			Description:
+ 0		BASE_SAFE_CLK		Base safe clock (always on) for WWDT
+ 1		BASE_USB0_CLK		Base clock for USB0
+ 2		BASE_PERIPH_CLK		Base clock for Cortex-M0SUB subsystem,
+					SPI, and SGPIO
+ 3		BASE_USB1_CLK		Base clock for USB1
+ 4		BASE_CPU_CLK		System base clock for ARM Cortex-M core
+					and APB peripheral blocks #0 and #2
+ 5		BASE_SPIFI_CLK		Base clock for SPIFI
+ 6		BASE_SPI_CLK		Base clock for SPI
+ 7		BASE_PHY_RX_CLK		Base clock for Ethernet PHY Receive clock
+ 8		BASE_PHY_TX_CLK		Base clock for Ethernet PHY Transmit clock
+ 9		BASE_APB1_CLK		Base clock for APB peripheral block # 1
+10		BASE_APB3_CLK		Base clock for APB peripheral block # 3
+11		BASE_LCD_CLK		Base clock for LCD
+12		BASE_ADCHS_CLK		Base clock for ADCHS
+13		BASE_SDIO_CLK		Base clock for SD/MMC
+14		BASE_SSP0_CLK		Base clock for SSP0
+15		BASE_SSP1_CLK		Base clock for SSP1
+16		BASE_UART0_CLK		Base clock for UART0
+17		BASE_UART1_CLK		Base clock for UART1
+18		BASE_UART2_CLK		Base clock for UART2
+19		BASE_UART3_CLK		Base clock for UART3
+20		BASE_OUT_CLK		Base clock for CLKOUT pin
+24-21		-			Reserved
+25		BASE_AUDIO_CLK		Base clock for audio system (I2S)
+26 		BASE_CGU_OUT0_CLK	Base clock for CGU_OUT0 clock output
+27 		BASE_CGU_OUT1_CLK	Base clock for CGU_OUT1 clock output
+
+BASE_PERIPH_CLK and BASE_SPI_CLK is only available on LPC43xx.
+BASE_ADCHS_CLK is only available on LPC4370.
+
+
+Example board file:
+
+/ {
+	clocks {
+		xtal: xtal {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <12000000>;
+		};
+
+		xtal32: xtal32 {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <32768>;
+		};
+
+		enet_rx_clk: enet_rx_clk {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <0>;
+			clock-output-names = "enet_rx_clk";
+		};
+
+		enet_tx_clk: enet_tx_clk {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <0>;
+			clock-output-names = "enet_tx_clk";
+		};
+
+		gp_clkin: gp_clkin {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <0>;
+			clock-output-names = "gp_clkin";
+		};
+	};
+
+	soc {
+		cgu: cgu at 40050000 {
+			compatible = "nxp,lpc1850-cgu";
+			reg = <0x40050000 0x1000>;
+			#clock-cells = <1>;
+			clocks = <&xtal>, <&creg_clk 1>, <&enet_rx_clk>, <&enet_tx_clk>, <&gp_clkin>;
+			clock-indices =  <0>,  <1>,  <2>,  <3>,  <4>,  <5>,  <6>,  <7>,
+					 <8>,  <9>, <10>, <11>, <12>, <13>, <14>, <15>,
+					<16>, <17>, <18>, <19>, <20>, <25>, <26>, <27>;
+			clock-output-names = "base_safe_clk",    "base_usb0_clk",
+					     "base_periph_clk",  "base_usb1_clk",
+					     "base_cpu_clk",     "base_spifi_clk",
+					     "base_spi_clk",     "base_phy_rx_clk",
+					     "base_phy_tx_clk",  "base_apb1_clk",
+					     "base_apb3_clk",    "base_lcd_clk",
+					     "base_adchs_clk",   "base_sdio_clk",
+					     "base_ssp0_clk",    "base_ssp1_clk",
+					     "base_uart0_clk",   "base_uart1_clk",
+					     "base_uart2_clk",   "base_uart3_clk",
+					     "base_out_clk",     "base_audio_clk",
+					     "base_cgu_out0_clk","base_cgu_out1_clk";
+		};
+	};
+};
-- 
1.8.0

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH v2 3/4] clk: add lpc18xx ccu clk driver
  2015-04-27 21:38 ` Joachim Eastwood
  (?)
@ 2015-04-27 21:38     ` Joachim Eastwood
  -1 siblings, 0 replies; 39+ messages in thread
From: Joachim Eastwood @ 2015-04-27 21:38 UTC (permalink / raw)
  To: mturquette-QSEj5FYQhm4dnm+yROfE0A, sboyd-sgV2jX0FEOL9JmXXK+q4OQ,
	arnd-r2nGTMty4D4, linux-clk-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
  Cc: devicetree-u79uwXL29TY76Z2rM5mHXA,
	ariel.dalessandro-Re5JQEeQqe8AvxtiuMwx3w,
	ezequiel-30ULvvUtt6G51wMPkGsGjgyUoB5FGQPZ, Joachim Eastwood

Add driver for NXP LPC18xx/43xx Clock Control Unit (CCU). The CCU
provides fine grained gating of most clocks present in the SoC.

Signed-off-by: Joachim Eastwood <manabian-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
---
 drivers/clk/nxp/Makefile                |   1 +
 drivers/clk/nxp/clk-lpc18xx-ccu.c       | 318 ++++++++++++++++++++++++++++++++
 include/dt-bindings/clock/lpc18xx-ccu.h |  74 ++++++++
 3 files changed, 393 insertions(+)
 create mode 100644 drivers/clk/nxp/clk-lpc18xx-ccu.c
 create mode 100644 include/dt-bindings/clock/lpc18xx-ccu.h

diff --git a/drivers/clk/nxp/Makefile b/drivers/clk/nxp/Makefile
index aca9d3e4f7fe..7f608b0ad7b4 100644
--- a/drivers/clk/nxp/Makefile
+++ b/drivers/clk/nxp/Makefile
@@ -1 +1,2 @@
 obj-$(CONFIG_ARCH_LPC18XX)	+= clk-lpc18xx-cgu.o
+obj-$(CONFIG_ARCH_LPC18XX)	+= clk-lpc18xx-ccu.o
diff --git a/drivers/clk/nxp/clk-lpc18xx-ccu.c b/drivers/clk/nxp/clk-lpc18xx-ccu.c
new file mode 100644
index 000000000000..01130f31611c
--- /dev/null
+++ b/drivers/clk/nxp/clk-lpc18xx-ccu.c
@@ -0,0 +1,318 @@
+/*
+ * Clk driver for NXP LPC18xx/LPC43xx Clock Control Unit (CCU)
+ *
+ * Copyright (C) 2015 Joachim Eastwood <manabian-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/kernel.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+
+#include <dt-bindings/clock/lpc18xx-cgu.h>
+#include <dt-bindings/clock/lpc18xx-ccu.h>
+
+/* Bit defines for CCU branch configuration register */
+#define LPC18XX_CCU_RUN		BIT(0)
+#define LPC18XX_CCU_AUTO	BIT(1)
+#define LPC18XX_CCU_DIV		BIT(5)
+#define LPC18XX_CCU_DIVSTAT	BIT(27)
+
+/* CCU branch feature bits */
+#define CCU_BRANCH_IS_BUS	BIT(0)
+#define CCU_BRANCH_HAVE_DIV2	BIT(1)
+
+#define to_clk_gate(_hw) container_of(_hw, struct clk_gate, hw)
+
+struct lpc18xx_branch_clk_data {
+	int *base_ids;
+	int num_base_ids;
+};
+
+struct lpc18xx_clk_branch {
+	int base_id;
+	const char *name;
+	u16 offset;
+	u16 flags;
+	struct clk *clk;
+	struct clk_gate gate;
+};
+
+static struct lpc18xx_clk_branch clk_branches[] = {
+	{BASE_APB3_CLK, "apb3_bus",		CLK_APB3_BUS,		CCU_BRANCH_IS_BUS},
+	{BASE_APB3_CLK, "apb3_i2c1",		CLK_APB3_I2C1,		0},
+	{BASE_APB3_CLK, "apb3_dac",		CLK_APB3_DAC,		0},
+	{BASE_APB3_CLK, "apb3_adc0",		CLK_APB3_ADC0,		0},
+	{BASE_APB3_CLK, "apb3_adc1",		CLK_APB3_ADC1,		0},
+	{BASE_APB3_CLK, "apb3_can0",		CLK_APB3_CAN0,		0},
+
+	{BASE_APB1_CLK, "apb1_bus",		CLK_APB1_BUS,		CCU_BRANCH_IS_BUS},
+	{BASE_APB1_CLK, "apb1_motorcon_pwm",	CLK_APB1_MOTOCON_PWM,	0},
+	{BASE_APB1_CLK, "apb1_i2c0",		CLK_APB1_I2C0,		0},
+	{BASE_APB1_CLK, "apb1_i2s",		CLK_APB1_I2S,		0},
+	{BASE_APB1_CLK, "apb1_can1",		CLK_APB1_CAN1,		0},
+
+	{BASE_SPIFI_CLK, "spifi",		CLK_SPIFI,		0},
+
+	{BASE_CPU_CLK, "cpu_bus",		CLK_CPU_BUS,		CCU_BRANCH_IS_BUS},
+	{BASE_CPU_CLK, "cpu_spifi",		CLK_CPU_SPIFI,		0},
+	{BASE_CPU_CLK, "cpu_gpio",		CLK_CPU_GPIO,		0},
+	{BASE_CPU_CLK, "cpu_lcd",		CLK_CPU_LCD,		0},
+	{BASE_CPU_CLK, "cpu_ethernet",		CLK_CPU_ETHERNET,	0},
+	{BASE_CPU_CLK, "cpu_usb0",		CLK_CPU_USB0,		0},
+	{BASE_CPU_CLK, "cpu_emc",		CLK_CPU_EMC,		0},
+	{BASE_CPU_CLK, "cpu_sdio",		CLK_CPU_SDIO,		0},
+	{BASE_CPU_CLK, "cpu_dma",		CLK_CPU_DMA,		0},
+	{BASE_CPU_CLK, "cpu_core",		CLK_CPU_CORE,		0},
+	{BASE_CPU_CLK, "cpu_sct",		CLK_CPU_SCT,		0},
+	{BASE_CPU_CLK, "cpu_usb1",		CLK_CPU_USB1,		0},
+	{BASE_CPU_CLK, "cpu_emcdiv",		CLK_CPU_EMCDIV,		CCU_BRANCH_HAVE_DIV2},
+	{BASE_CPU_CLK, "cpu_flasha",		CLK_CPU_FLASHA,		CCU_BRANCH_HAVE_DIV2},
+	{BASE_CPU_CLK, "cpu_flashb",		CLK_CPU_FLASHB,		CCU_BRANCH_HAVE_DIV2},
+	{BASE_CPU_CLK, "cpu_m0app",		CLK_CPU_M0APP,		CCU_BRANCH_HAVE_DIV2},
+	{BASE_CPU_CLK, "cpu_adchs",		CLK_CPU_ADCHS,		CCU_BRANCH_HAVE_DIV2},
+	{BASE_CPU_CLK, "cpu_eeprom",		CLK_CPU_EEPROM,		CCU_BRANCH_HAVE_DIV2},
+	{BASE_CPU_CLK, "cpu_wwdt",		CLK_CPU_WWDT,		0},
+	{BASE_CPU_CLK, "cpu_uart0",		CLK_CPU_UART0,		0},
+	{BASE_CPU_CLK, "cpu_uart1",		CLK_CPU_UART1,		0},
+	{BASE_CPU_CLK, "cpu_ssp0",		CLK_CPU_SSP0,		0},
+	{BASE_CPU_CLK, "cpu_timer0",		CLK_CPU_TIMER0,		0},
+	{BASE_CPU_CLK, "cpu_timer1",		CLK_CPU_TIMER1,		0},
+	{BASE_CPU_CLK, "cpu_scu",		CLK_CPU_SCU,		0},
+	{BASE_CPU_CLK, "cpu_creg",		CLK_CPU_CREG,		0},
+	{BASE_CPU_CLK, "cpu_ritimer",		CLK_CPU_RITIMER,	0},
+	{BASE_CPU_CLK, "cpu_uart2",		CLK_CPU_UART2,		0},
+	{BASE_CPU_CLK, "cpu_uart3",		CLK_CPU_UART3,		0},
+	{BASE_CPU_CLK, "cpu_timer2",		CLK_CPU_TIMER2,		0},
+	{BASE_CPU_CLK, "cpu_timer3",		CLK_CPU_TIMER3,		0},
+	{BASE_CPU_CLK, "cpu_ssp1",		CLK_CPU_SSP1,		0},
+	{BASE_CPU_CLK, "cpu_qei",		CLK_CPU_QEI,		0},
+
+	{BASE_PERIPH_CLK, "periph_bus",		CLK_PERIPH_BUS,		CCU_BRANCH_IS_BUS},
+	{BASE_PERIPH_CLK, "periph_core",	CLK_PERIPH_CORE,	0},
+	{BASE_PERIPH_CLK, "periph_sgpio",	CLK_PERIPH_SGPIO,	0},
+
+	{BASE_USB0_CLK,  "usb0",		CLK_USB0,		0},
+	{BASE_USB1_CLK,  "usb1",		CLK_USB1,		0},
+	{BASE_SPI_CLK,   "spi",			CLK_SPI,		0},
+	{BASE_ADCHS_CLK, "adchs",		CLK_ADCHS,		0},
+
+	{BASE_AUDIO_CLK, "audio",		CLK_AUDIO,		0},
+	{BASE_UART3_CLK, "apb2_uart3",		CLK_APB2_UART3,		0},
+	{BASE_UART2_CLK, "apb2_uart2",		CLK_APB2_UART2,		0},
+	{BASE_UART1_CLK, "apb0_uart1",		CLK_APB0_UART1,		0},
+	{BASE_UART0_CLK, "apb0_uart0",		CLK_APB0_UART0,		0},
+	{BASE_SSP1_CLK,  "apb2_ssp1",		CLK_APB2_SSP1,		0},
+	{BASE_SSP0_CLK,  "apb0_ssp0",		CLK_APB0_SSP0,		0},
+	{BASE_SDIO_CLK,  "sdio",		CLK_SDIO,		0},
+};
+
+static int of_clk_get_parent_arg(struct device_node *np, int index)
+{
+	struct of_phandle_args clkspec;
+	int rc;
+
+	if (index < 0)
+		return -EINVAL;
+
+	rc = of_parse_phandle_with_args(np, "clocks", "#clock-cells", index,
+					&clkspec);
+	if (rc)
+		return -EINVAL;
+
+	return clkspec.args_count ? clkspec.args[0] : -EINVAL;
+}
+
+static struct clk *lpc18xx_ccu_branch_clk_get(struct of_phandle_args *clkspec,
+					      void *data)
+{
+	struct lpc18xx_branch_clk_data *clk_data = data;
+	unsigned int offset = clkspec->args[0];
+	int i, j;
+
+	for (i = 0; i < ARRAY_SIZE(clk_branches); i++) {
+		if (clk_branches[i].offset != offset)
+			continue;
+
+		for (j = 0; j < clk_data->num_base_ids; j++) {
+			if (clk_data->base_ids[j] == clk_branches[i].base_id)
+				return clk_branches[i].clk;
+		}
+	}
+
+	pr_err("%s: invalid clock offset %d\n", __func__, offset);
+
+	return ERR_PTR(-EINVAL);
+}
+
+static int lpc18xx_ccu_gate_endisable(struct clk_hw *hw, bool enable)
+{
+	struct clk_gate *gate = to_clk_gate(hw);
+	u32 val;
+
+	/*
+	 * Divider field is write only, so divider stat field must
+	 * be read so divider field can be set accordingly.
+	 */
+	val = clk_readl(gate->reg);
+	if (val & LPC18XX_CCU_DIVSTAT)
+		val |= LPC18XX_CCU_DIV;
+
+	if (enable) {
+		val |= LPC18XX_CCU_RUN;
+	} else {
+		/*
+		 * To safely disable a branch clock a squence of two separate
+		 * writes must be used. First write should set the AUTO bit
+		 * and the next write should clear the RUN bit.
+		 */
+		val |= LPC18XX_CCU_AUTO;
+		clk_writel(val, gate->reg);
+
+		val &= ~LPC18XX_CCU_RUN;
+	}
+
+	clk_writel(val, gate->reg);
+
+	return 0;
+}
+
+static int lpc18xx_ccu_gate_enable(struct clk_hw *hw)
+{
+	return lpc18xx_ccu_gate_endisable(hw, true);
+}
+
+static void lpc18xx_ccu_gate_disable(struct clk_hw *hw)
+{
+	lpc18xx_ccu_gate_endisable(hw, false);
+}
+
+static int lpc18xx_ccu_gate_is_enabled(struct clk_hw *hw)
+{
+	struct clk_gate *gate = to_clk_gate(hw);
+
+	return clk_readl(gate->reg) & LPC18XX_CCU_RUN;
+}
+
+static const struct clk_ops lpc18xx_ccu_gate_ops = {
+	.enable		= lpc18xx_ccu_gate_enable,
+	.disable	= lpc18xx_ccu_gate_disable,
+	.is_enabled	= lpc18xx_ccu_gate_is_enabled,
+};
+
+static void lpc18xx_ccu_register_branch_gate_div(struct lpc18xx_clk_branch *branch,
+						 void __iomem *base,
+						 const char *parent)
+{
+	const struct clk_ops *div_ops = NULL;
+	struct clk_divider *div = NULL;
+	struct clk_hw *div_hw = NULL;
+
+	if (branch->flags & CCU_BRANCH_HAVE_DIV2) {
+		div = kzalloc(sizeof(*div), GFP_KERNEL);
+		if (!div)
+			return;
+
+		div->reg = branch->offset + base;
+		div->flags = CLK_DIVIDER_READ_ONLY;
+		div->shift = 27;
+		div->width = 1;
+
+		div_hw = &div->hw;
+		div_ops = &clk_divider_ops;
+	}
+
+	branch->gate.reg = branch->offset + base;
+	branch->gate.bit_idx = 0;
+
+	branch->clk = clk_register_composite(NULL, branch->name, &parent, 1,
+					     NULL, NULL,
+					     div_hw, div_ops,
+					     &branch->gate.hw, &lpc18xx_ccu_gate_ops, 0);
+	if (IS_ERR(branch->clk)) {
+		kfree(div);
+		pr_warn("%s: failed to register %s\n", __func__, branch->name);
+		return;
+	}
+
+	/* Grab essential branch clocks for CPU and SDRAM */
+	switch (branch->offset) {
+	case CLK_CPU_EMC:
+	case CLK_CPU_CORE:
+	case CLK_CPU_CREG:
+	case CLK_CPU_EMCDIV:
+		clk_prepare_enable(branch->clk);
+	}
+}
+
+static void lpc18xx_ccu_register_branch_clks(void __iomem *base, int base_clk_id,
+					     const char *parent)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(clk_branches); i++) {
+		if (clk_branches[i].base_id != base_clk_id)
+			continue;
+
+		lpc18xx_ccu_register_branch_gate_div(&clk_branches[i], base,
+						     parent);
+
+		if (clk_branches[i].flags & CCU_BRANCH_IS_BUS)
+			parent = clk_branches[i].name;
+	}
+}
+
+static void __init lpc18xx_ccu_init(struct device_node *np)
+{
+	struct lpc18xx_branch_clk_data *clk_data;
+	int num_base_ids, *base_ids;
+	void __iomem *base;
+	const char *parent;
+	int base_clk_id;
+	int i;
+
+	base = of_iomap(np, 0);
+	if (!base) {
+		pr_warn("%s: failed to map address range\n", __func__);
+		return;
+	}
+
+	clk_data = kzalloc(sizeof(*clk_data), GFP_KERNEL);
+	if (!clk_data)
+		return;
+
+	num_base_ids = of_clk_get_parent_count(np);
+
+	base_ids = kcalloc(num_base_ids, sizeof(int), GFP_KERNEL);
+	if (!base_ids) {
+		kfree(clk_data);
+		return;
+	}
+
+	clk_data->base_ids = base_ids;
+	clk_data->num_base_ids = num_base_ids;
+
+	for (i = 0; i < num_base_ids; i++) {
+		parent = of_clk_get_parent_name(np, i);
+
+		base_clk_id = of_clk_get_parent_arg(np, i);
+		if (base_clk_id < 0 && base_clk_id >= BASE_CLK_MAX) {
+			pr_warn("%s: invalid base clk at idx %d\n", __func__, i);
+			base_ids[i] = -EINVAL;
+			continue;
+		}
+
+		clk_data->base_ids[i] = base_clk_id;
+		lpc18xx_ccu_register_branch_clks(base, base_clk_id, parent);
+	}
+
+	of_clk_add_provider(np, lpc18xx_ccu_branch_clk_get, clk_data);
+}
+CLK_OF_DECLARE(lpc18xx_ccu, "nxp,lpc1850-ccu", lpc18xx_ccu_init);
diff --git a/include/dt-bindings/clock/lpc18xx-ccu.h b/include/dt-bindings/clock/lpc18xx-ccu.h
new file mode 100644
index 000000000000..bbfe00b6ab7d
--- /dev/null
+++ b/include/dt-bindings/clock/lpc18xx-ccu.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2015 Joachim Eastwood <manabian-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
+ *
+ * This code is released using a dual license strategy: BSD/GPL
+ * You can choose the licence that better fits your requirements.
+ *
+ * Released under the terms of 3-clause BSD License
+ * Released under the terms of GNU General Public License Version 2.0
+ *
+ */
+
+/* Clock Control Unit 1 (CCU1) clock offsets */
+#define CLK_APB3_BUS		0x100
+#define CLK_APB3_I2C1		0x108
+#define CLK_APB3_DAC		0x110
+#define CLK_APB3_ADC0		0x118
+#define CLK_APB3_ADC1		0x120
+#define CLK_APB3_CAN0		0x128
+#define CLK_APB1_BUS		0x200
+#define CLK_APB1_MOTOCON_PWM	0x208
+#define CLK_APB1_I2C0		0x210
+#define CLK_APB1_I2S		0x218
+#define CLK_APB1_CAN1		0x220
+#define CLK_SPIFI		0x300
+#define CLK_CPU_BUS		0x400
+#define CLK_CPU_SPIFI		0x408
+#define CLK_CPU_GPIO		0x410
+#define CLK_CPU_LCD		0x418
+#define CLK_CPU_ETHERNET	0x420
+#define CLK_CPU_USB0		0x428
+#define CLK_CPU_EMC		0x430
+#define CLK_CPU_SDIO		0x438
+#define CLK_CPU_DMA		0x440
+#define CLK_CPU_CORE		0x448
+#define CLK_CPU_SCT		0x468
+#define CLK_CPU_USB1		0x470
+#define CLK_CPU_EMCDIV		0x478
+#define CLK_CPU_FLASHA		0x480
+#define CLK_CPU_FLASHB		0x488
+#define CLK_CPU_M0APP		0x490
+#define CLK_CPU_ADCHS		0x498
+#define CLK_CPU_EEPROM		0x4a0
+#define CLK_CPU_WWDT		0x500
+#define CLK_CPU_UART0		0x508
+#define CLK_CPU_UART1		0x510
+#define CLK_CPU_SSP0		0x518
+#define CLK_CPU_TIMER0		0x520
+#define CLK_CPU_TIMER1		0x528
+#define CLK_CPU_SCU		0x530
+#define CLK_CPU_CREG		0x538
+#define CLK_CPU_RITIMER		0x600
+#define CLK_CPU_UART2		0x608
+#define CLK_CPU_UART3		0x610
+#define CLK_CPU_TIMER2		0x618
+#define CLK_CPU_TIMER3		0x620
+#define CLK_CPU_SSP1		0x628
+#define CLK_CPU_QEI		0x630
+#define CLK_PERIPH_BUS		0x700
+#define CLK_PERIPH_CORE		0x710
+#define CLK_PERIPH_SGPIO	0x718
+#define CLK_USB0		0x800
+#define CLK_USB1		0x900
+#define CLK_SPI			0xA00
+#define CLK_ADCHS		0xB00
+
+/* Clock Control Unit 2 (CCU2) clock offsets */
+#define CLK_AUDIO		0x100
+#define CLK_APB2_UART3		0x200
+#define CLK_APB2_UART2		0x300
+#define CLK_APB0_UART1		0x400
+#define CLK_APB0_UART0		0x500
+#define CLK_APB2_SSP1		0x600
+#define CLK_APB0_SSP0		0x700
+#define CLK_SDIO		0x800
-- 
1.8.0

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH v2 3/4] clk: add lpc18xx ccu clk driver
@ 2015-04-27 21:38     ` Joachim Eastwood
  0 siblings, 0 replies; 39+ messages in thread
From: Joachim Eastwood @ 2015-04-27 21:38 UTC (permalink / raw)
  To: mturquette, sboyd, arnd, linux-clk, linux-arm-kernel
  Cc: devicetree, ariel.dalessandro, ezequiel, Joachim Eastwood

Add driver for NXP LPC18xx/43xx Clock Control Unit (CCU). The CCU
provides fine grained gating of most clocks present in the SoC.

Signed-off-by: Joachim Eastwood <manabian@gmail.com>
---
 drivers/clk/nxp/Makefile                |   1 +
 drivers/clk/nxp/clk-lpc18xx-ccu.c       | 318 ++++++++++++++++++++++++++++++++
 include/dt-bindings/clock/lpc18xx-ccu.h |  74 ++++++++
 3 files changed, 393 insertions(+)
 create mode 100644 drivers/clk/nxp/clk-lpc18xx-ccu.c
 create mode 100644 include/dt-bindings/clock/lpc18xx-ccu.h

diff --git a/drivers/clk/nxp/Makefile b/drivers/clk/nxp/Makefile
index aca9d3e4f7fe..7f608b0ad7b4 100644
--- a/drivers/clk/nxp/Makefile
+++ b/drivers/clk/nxp/Makefile
@@ -1 +1,2 @@
 obj-$(CONFIG_ARCH_LPC18XX)	+= clk-lpc18xx-cgu.o
+obj-$(CONFIG_ARCH_LPC18XX)	+= clk-lpc18xx-ccu.o
diff --git a/drivers/clk/nxp/clk-lpc18xx-ccu.c b/drivers/clk/nxp/clk-lpc18xx-ccu.c
new file mode 100644
index 000000000000..01130f31611c
--- /dev/null
+++ b/drivers/clk/nxp/clk-lpc18xx-ccu.c
@@ -0,0 +1,318 @@
+/*
+ * Clk driver for NXP LPC18xx/LPC43xx Clock Control Unit (CCU)
+ *
+ * Copyright (C) 2015 Joachim Eastwood <manabian@gmail.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/kernel.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+
+#include <dt-bindings/clock/lpc18xx-cgu.h>
+#include <dt-bindings/clock/lpc18xx-ccu.h>
+
+/* Bit defines for CCU branch configuration register */
+#define LPC18XX_CCU_RUN		BIT(0)
+#define LPC18XX_CCU_AUTO	BIT(1)
+#define LPC18XX_CCU_DIV		BIT(5)
+#define LPC18XX_CCU_DIVSTAT	BIT(27)
+
+/* CCU branch feature bits */
+#define CCU_BRANCH_IS_BUS	BIT(0)
+#define CCU_BRANCH_HAVE_DIV2	BIT(1)
+
+#define to_clk_gate(_hw) container_of(_hw, struct clk_gate, hw)
+
+struct lpc18xx_branch_clk_data {
+	int *base_ids;
+	int num_base_ids;
+};
+
+struct lpc18xx_clk_branch {
+	int base_id;
+	const char *name;
+	u16 offset;
+	u16 flags;
+	struct clk *clk;
+	struct clk_gate gate;
+};
+
+static struct lpc18xx_clk_branch clk_branches[] = {
+	{BASE_APB3_CLK, "apb3_bus",		CLK_APB3_BUS,		CCU_BRANCH_IS_BUS},
+	{BASE_APB3_CLK, "apb3_i2c1",		CLK_APB3_I2C1,		0},
+	{BASE_APB3_CLK, "apb3_dac",		CLK_APB3_DAC,		0},
+	{BASE_APB3_CLK, "apb3_adc0",		CLK_APB3_ADC0,		0},
+	{BASE_APB3_CLK, "apb3_adc1",		CLK_APB3_ADC1,		0},
+	{BASE_APB3_CLK, "apb3_can0",		CLK_APB3_CAN0,		0},
+
+	{BASE_APB1_CLK, "apb1_bus",		CLK_APB1_BUS,		CCU_BRANCH_IS_BUS},
+	{BASE_APB1_CLK, "apb1_motorcon_pwm",	CLK_APB1_MOTOCON_PWM,	0},
+	{BASE_APB1_CLK, "apb1_i2c0",		CLK_APB1_I2C0,		0},
+	{BASE_APB1_CLK, "apb1_i2s",		CLK_APB1_I2S,		0},
+	{BASE_APB1_CLK, "apb1_can1",		CLK_APB1_CAN1,		0},
+
+	{BASE_SPIFI_CLK, "spifi",		CLK_SPIFI,		0},
+
+	{BASE_CPU_CLK, "cpu_bus",		CLK_CPU_BUS,		CCU_BRANCH_IS_BUS},
+	{BASE_CPU_CLK, "cpu_spifi",		CLK_CPU_SPIFI,		0},
+	{BASE_CPU_CLK, "cpu_gpio",		CLK_CPU_GPIO,		0},
+	{BASE_CPU_CLK, "cpu_lcd",		CLK_CPU_LCD,		0},
+	{BASE_CPU_CLK, "cpu_ethernet",		CLK_CPU_ETHERNET,	0},
+	{BASE_CPU_CLK, "cpu_usb0",		CLK_CPU_USB0,		0},
+	{BASE_CPU_CLK, "cpu_emc",		CLK_CPU_EMC,		0},
+	{BASE_CPU_CLK, "cpu_sdio",		CLK_CPU_SDIO,		0},
+	{BASE_CPU_CLK, "cpu_dma",		CLK_CPU_DMA,		0},
+	{BASE_CPU_CLK, "cpu_core",		CLK_CPU_CORE,		0},
+	{BASE_CPU_CLK, "cpu_sct",		CLK_CPU_SCT,		0},
+	{BASE_CPU_CLK, "cpu_usb1",		CLK_CPU_USB1,		0},
+	{BASE_CPU_CLK, "cpu_emcdiv",		CLK_CPU_EMCDIV,		CCU_BRANCH_HAVE_DIV2},
+	{BASE_CPU_CLK, "cpu_flasha",		CLK_CPU_FLASHA,		CCU_BRANCH_HAVE_DIV2},
+	{BASE_CPU_CLK, "cpu_flashb",		CLK_CPU_FLASHB,		CCU_BRANCH_HAVE_DIV2},
+	{BASE_CPU_CLK, "cpu_m0app",		CLK_CPU_M0APP,		CCU_BRANCH_HAVE_DIV2},
+	{BASE_CPU_CLK, "cpu_adchs",		CLK_CPU_ADCHS,		CCU_BRANCH_HAVE_DIV2},
+	{BASE_CPU_CLK, "cpu_eeprom",		CLK_CPU_EEPROM,		CCU_BRANCH_HAVE_DIV2},
+	{BASE_CPU_CLK, "cpu_wwdt",		CLK_CPU_WWDT,		0},
+	{BASE_CPU_CLK, "cpu_uart0",		CLK_CPU_UART0,		0},
+	{BASE_CPU_CLK, "cpu_uart1",		CLK_CPU_UART1,		0},
+	{BASE_CPU_CLK, "cpu_ssp0",		CLK_CPU_SSP0,		0},
+	{BASE_CPU_CLK, "cpu_timer0",		CLK_CPU_TIMER0,		0},
+	{BASE_CPU_CLK, "cpu_timer1",		CLK_CPU_TIMER1,		0},
+	{BASE_CPU_CLK, "cpu_scu",		CLK_CPU_SCU,		0},
+	{BASE_CPU_CLK, "cpu_creg",		CLK_CPU_CREG,		0},
+	{BASE_CPU_CLK, "cpu_ritimer",		CLK_CPU_RITIMER,	0},
+	{BASE_CPU_CLK, "cpu_uart2",		CLK_CPU_UART2,		0},
+	{BASE_CPU_CLK, "cpu_uart3",		CLK_CPU_UART3,		0},
+	{BASE_CPU_CLK, "cpu_timer2",		CLK_CPU_TIMER2,		0},
+	{BASE_CPU_CLK, "cpu_timer3",		CLK_CPU_TIMER3,		0},
+	{BASE_CPU_CLK, "cpu_ssp1",		CLK_CPU_SSP1,		0},
+	{BASE_CPU_CLK, "cpu_qei",		CLK_CPU_QEI,		0},
+
+	{BASE_PERIPH_CLK, "periph_bus",		CLK_PERIPH_BUS,		CCU_BRANCH_IS_BUS},
+	{BASE_PERIPH_CLK, "periph_core",	CLK_PERIPH_CORE,	0},
+	{BASE_PERIPH_CLK, "periph_sgpio",	CLK_PERIPH_SGPIO,	0},
+
+	{BASE_USB0_CLK,  "usb0",		CLK_USB0,		0},
+	{BASE_USB1_CLK,  "usb1",		CLK_USB1,		0},
+	{BASE_SPI_CLK,   "spi",			CLK_SPI,		0},
+	{BASE_ADCHS_CLK, "adchs",		CLK_ADCHS,		0},
+
+	{BASE_AUDIO_CLK, "audio",		CLK_AUDIO,		0},
+	{BASE_UART3_CLK, "apb2_uart3",		CLK_APB2_UART3,		0},
+	{BASE_UART2_CLK, "apb2_uart2",		CLK_APB2_UART2,		0},
+	{BASE_UART1_CLK, "apb0_uart1",		CLK_APB0_UART1,		0},
+	{BASE_UART0_CLK, "apb0_uart0",		CLK_APB0_UART0,		0},
+	{BASE_SSP1_CLK,  "apb2_ssp1",		CLK_APB2_SSP1,		0},
+	{BASE_SSP0_CLK,  "apb0_ssp0",		CLK_APB0_SSP0,		0},
+	{BASE_SDIO_CLK,  "sdio",		CLK_SDIO,		0},
+};
+
+static int of_clk_get_parent_arg(struct device_node *np, int index)
+{
+	struct of_phandle_args clkspec;
+	int rc;
+
+	if (index < 0)
+		return -EINVAL;
+
+	rc = of_parse_phandle_with_args(np, "clocks", "#clock-cells", index,
+					&clkspec);
+	if (rc)
+		return -EINVAL;
+
+	return clkspec.args_count ? clkspec.args[0] : -EINVAL;
+}
+
+static struct clk *lpc18xx_ccu_branch_clk_get(struct of_phandle_args *clkspec,
+					      void *data)
+{
+	struct lpc18xx_branch_clk_data *clk_data = data;
+	unsigned int offset = clkspec->args[0];
+	int i, j;
+
+	for (i = 0; i < ARRAY_SIZE(clk_branches); i++) {
+		if (clk_branches[i].offset != offset)
+			continue;
+
+		for (j = 0; j < clk_data->num_base_ids; j++) {
+			if (clk_data->base_ids[j] == clk_branches[i].base_id)
+				return clk_branches[i].clk;
+		}
+	}
+
+	pr_err("%s: invalid clock offset %d\n", __func__, offset);
+
+	return ERR_PTR(-EINVAL);
+}
+
+static int lpc18xx_ccu_gate_endisable(struct clk_hw *hw, bool enable)
+{
+	struct clk_gate *gate = to_clk_gate(hw);
+	u32 val;
+
+	/*
+	 * Divider field is write only, so divider stat field must
+	 * be read so divider field can be set accordingly.
+	 */
+	val = clk_readl(gate->reg);
+	if (val & LPC18XX_CCU_DIVSTAT)
+		val |= LPC18XX_CCU_DIV;
+
+	if (enable) {
+		val |= LPC18XX_CCU_RUN;
+	} else {
+		/*
+		 * To safely disable a branch clock a squence of two separate
+		 * writes must be used. First write should set the AUTO bit
+		 * and the next write should clear the RUN bit.
+		 */
+		val |= LPC18XX_CCU_AUTO;
+		clk_writel(val, gate->reg);
+
+		val &= ~LPC18XX_CCU_RUN;
+	}
+
+	clk_writel(val, gate->reg);
+
+	return 0;
+}
+
+static int lpc18xx_ccu_gate_enable(struct clk_hw *hw)
+{
+	return lpc18xx_ccu_gate_endisable(hw, true);
+}
+
+static void lpc18xx_ccu_gate_disable(struct clk_hw *hw)
+{
+	lpc18xx_ccu_gate_endisable(hw, false);
+}
+
+static int lpc18xx_ccu_gate_is_enabled(struct clk_hw *hw)
+{
+	struct clk_gate *gate = to_clk_gate(hw);
+
+	return clk_readl(gate->reg) & LPC18XX_CCU_RUN;
+}
+
+static const struct clk_ops lpc18xx_ccu_gate_ops = {
+	.enable		= lpc18xx_ccu_gate_enable,
+	.disable	= lpc18xx_ccu_gate_disable,
+	.is_enabled	= lpc18xx_ccu_gate_is_enabled,
+};
+
+static void lpc18xx_ccu_register_branch_gate_div(struct lpc18xx_clk_branch *branch,
+						 void __iomem *base,
+						 const char *parent)
+{
+	const struct clk_ops *div_ops = NULL;
+	struct clk_divider *div = NULL;
+	struct clk_hw *div_hw = NULL;
+
+	if (branch->flags & CCU_BRANCH_HAVE_DIV2) {
+		div = kzalloc(sizeof(*div), GFP_KERNEL);
+		if (!div)
+			return;
+
+		div->reg = branch->offset + base;
+		div->flags = CLK_DIVIDER_READ_ONLY;
+		div->shift = 27;
+		div->width = 1;
+
+		div_hw = &div->hw;
+		div_ops = &clk_divider_ops;
+	}
+
+	branch->gate.reg = branch->offset + base;
+	branch->gate.bit_idx = 0;
+
+	branch->clk = clk_register_composite(NULL, branch->name, &parent, 1,
+					     NULL, NULL,
+					     div_hw, div_ops,
+					     &branch->gate.hw, &lpc18xx_ccu_gate_ops, 0);
+	if (IS_ERR(branch->clk)) {
+		kfree(div);
+		pr_warn("%s: failed to register %s\n", __func__, branch->name);
+		return;
+	}
+
+	/* Grab essential branch clocks for CPU and SDRAM */
+	switch (branch->offset) {
+	case CLK_CPU_EMC:
+	case CLK_CPU_CORE:
+	case CLK_CPU_CREG:
+	case CLK_CPU_EMCDIV:
+		clk_prepare_enable(branch->clk);
+	}
+}
+
+static void lpc18xx_ccu_register_branch_clks(void __iomem *base, int base_clk_id,
+					     const char *parent)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(clk_branches); i++) {
+		if (clk_branches[i].base_id != base_clk_id)
+			continue;
+
+		lpc18xx_ccu_register_branch_gate_div(&clk_branches[i], base,
+						     parent);
+
+		if (clk_branches[i].flags & CCU_BRANCH_IS_BUS)
+			parent = clk_branches[i].name;
+	}
+}
+
+static void __init lpc18xx_ccu_init(struct device_node *np)
+{
+	struct lpc18xx_branch_clk_data *clk_data;
+	int num_base_ids, *base_ids;
+	void __iomem *base;
+	const char *parent;
+	int base_clk_id;
+	int i;
+
+	base = of_iomap(np, 0);
+	if (!base) {
+		pr_warn("%s: failed to map address range\n", __func__);
+		return;
+	}
+
+	clk_data = kzalloc(sizeof(*clk_data), GFP_KERNEL);
+	if (!clk_data)
+		return;
+
+	num_base_ids = of_clk_get_parent_count(np);
+
+	base_ids = kcalloc(num_base_ids, sizeof(int), GFP_KERNEL);
+	if (!base_ids) {
+		kfree(clk_data);
+		return;
+	}
+
+	clk_data->base_ids = base_ids;
+	clk_data->num_base_ids = num_base_ids;
+
+	for (i = 0; i < num_base_ids; i++) {
+		parent = of_clk_get_parent_name(np, i);
+
+		base_clk_id = of_clk_get_parent_arg(np, i);
+		if (base_clk_id < 0 && base_clk_id >= BASE_CLK_MAX) {
+			pr_warn("%s: invalid base clk at idx %d\n", __func__, i);
+			base_ids[i] = -EINVAL;
+			continue;
+		}
+
+		clk_data->base_ids[i] = base_clk_id;
+		lpc18xx_ccu_register_branch_clks(base, base_clk_id, parent);
+	}
+
+	of_clk_add_provider(np, lpc18xx_ccu_branch_clk_get, clk_data);
+}
+CLK_OF_DECLARE(lpc18xx_ccu, "nxp,lpc1850-ccu", lpc18xx_ccu_init);
diff --git a/include/dt-bindings/clock/lpc18xx-ccu.h b/include/dt-bindings/clock/lpc18xx-ccu.h
new file mode 100644
index 000000000000..bbfe00b6ab7d
--- /dev/null
+++ b/include/dt-bindings/clock/lpc18xx-ccu.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2015 Joachim Eastwood <manabian@gmail.com>
+ *
+ * This code is released using a dual license strategy: BSD/GPL
+ * You can choose the licence that better fits your requirements.
+ *
+ * Released under the terms of 3-clause BSD License
+ * Released under the terms of GNU General Public License Version 2.0
+ *
+ */
+
+/* Clock Control Unit 1 (CCU1) clock offsets */
+#define CLK_APB3_BUS		0x100
+#define CLK_APB3_I2C1		0x108
+#define CLK_APB3_DAC		0x110
+#define CLK_APB3_ADC0		0x118
+#define CLK_APB3_ADC1		0x120
+#define CLK_APB3_CAN0		0x128
+#define CLK_APB1_BUS		0x200
+#define CLK_APB1_MOTOCON_PWM	0x208
+#define CLK_APB1_I2C0		0x210
+#define CLK_APB1_I2S		0x218
+#define CLK_APB1_CAN1		0x220
+#define CLK_SPIFI		0x300
+#define CLK_CPU_BUS		0x400
+#define CLK_CPU_SPIFI		0x408
+#define CLK_CPU_GPIO		0x410
+#define CLK_CPU_LCD		0x418
+#define CLK_CPU_ETHERNET	0x420
+#define CLK_CPU_USB0		0x428
+#define CLK_CPU_EMC		0x430
+#define CLK_CPU_SDIO		0x438
+#define CLK_CPU_DMA		0x440
+#define CLK_CPU_CORE		0x448
+#define CLK_CPU_SCT		0x468
+#define CLK_CPU_USB1		0x470
+#define CLK_CPU_EMCDIV		0x478
+#define CLK_CPU_FLASHA		0x480
+#define CLK_CPU_FLASHB		0x488
+#define CLK_CPU_M0APP		0x490
+#define CLK_CPU_ADCHS		0x498
+#define CLK_CPU_EEPROM		0x4a0
+#define CLK_CPU_WWDT		0x500
+#define CLK_CPU_UART0		0x508
+#define CLK_CPU_UART1		0x510
+#define CLK_CPU_SSP0		0x518
+#define CLK_CPU_TIMER0		0x520
+#define CLK_CPU_TIMER1		0x528
+#define CLK_CPU_SCU		0x530
+#define CLK_CPU_CREG		0x538
+#define CLK_CPU_RITIMER		0x600
+#define CLK_CPU_UART2		0x608
+#define CLK_CPU_UART3		0x610
+#define CLK_CPU_TIMER2		0x618
+#define CLK_CPU_TIMER3		0x620
+#define CLK_CPU_SSP1		0x628
+#define CLK_CPU_QEI		0x630
+#define CLK_PERIPH_BUS		0x700
+#define CLK_PERIPH_CORE		0x710
+#define CLK_PERIPH_SGPIO	0x718
+#define CLK_USB0		0x800
+#define CLK_USB1		0x900
+#define CLK_SPI			0xA00
+#define CLK_ADCHS		0xB00
+
+/* Clock Control Unit 2 (CCU2) clock offsets */
+#define CLK_AUDIO		0x100
+#define CLK_APB2_UART3		0x200
+#define CLK_APB2_UART2		0x300
+#define CLK_APB0_UART1		0x400
+#define CLK_APB0_UART0		0x500
+#define CLK_APB2_SSP1		0x600
+#define CLK_APB0_SSP0		0x700
+#define CLK_SDIO		0x800
-- 
1.8.0

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH v2 3/4] clk: add lpc18xx ccu clk driver
@ 2015-04-27 21:38     ` Joachim Eastwood
  0 siblings, 0 replies; 39+ messages in thread
From: Joachim Eastwood @ 2015-04-27 21:38 UTC (permalink / raw)
  To: linux-arm-kernel

Add driver for NXP LPC18xx/43xx Clock Control Unit (CCU). The CCU
provides fine grained gating of most clocks present in the SoC.

Signed-off-by: Joachim Eastwood <manabian@gmail.com>
---
 drivers/clk/nxp/Makefile                |   1 +
 drivers/clk/nxp/clk-lpc18xx-ccu.c       | 318 ++++++++++++++++++++++++++++++++
 include/dt-bindings/clock/lpc18xx-ccu.h |  74 ++++++++
 3 files changed, 393 insertions(+)
 create mode 100644 drivers/clk/nxp/clk-lpc18xx-ccu.c
 create mode 100644 include/dt-bindings/clock/lpc18xx-ccu.h

diff --git a/drivers/clk/nxp/Makefile b/drivers/clk/nxp/Makefile
index aca9d3e4f7fe..7f608b0ad7b4 100644
--- a/drivers/clk/nxp/Makefile
+++ b/drivers/clk/nxp/Makefile
@@ -1 +1,2 @@
 obj-$(CONFIG_ARCH_LPC18XX)	+= clk-lpc18xx-cgu.o
+obj-$(CONFIG_ARCH_LPC18XX)	+= clk-lpc18xx-ccu.o
diff --git a/drivers/clk/nxp/clk-lpc18xx-ccu.c b/drivers/clk/nxp/clk-lpc18xx-ccu.c
new file mode 100644
index 000000000000..01130f31611c
--- /dev/null
+++ b/drivers/clk/nxp/clk-lpc18xx-ccu.c
@@ -0,0 +1,318 @@
+/*
+ * Clk driver for NXP LPC18xx/LPC43xx Clock Control Unit (CCU)
+ *
+ * Copyright (C) 2015 Joachim Eastwood <manabian@gmail.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/kernel.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+
+#include <dt-bindings/clock/lpc18xx-cgu.h>
+#include <dt-bindings/clock/lpc18xx-ccu.h>
+
+/* Bit defines for CCU branch configuration register */
+#define LPC18XX_CCU_RUN		BIT(0)
+#define LPC18XX_CCU_AUTO	BIT(1)
+#define LPC18XX_CCU_DIV		BIT(5)
+#define LPC18XX_CCU_DIVSTAT	BIT(27)
+
+/* CCU branch feature bits */
+#define CCU_BRANCH_IS_BUS	BIT(0)
+#define CCU_BRANCH_HAVE_DIV2	BIT(1)
+
+#define to_clk_gate(_hw) container_of(_hw, struct clk_gate, hw)
+
+struct lpc18xx_branch_clk_data {
+	int *base_ids;
+	int num_base_ids;
+};
+
+struct lpc18xx_clk_branch {
+	int base_id;
+	const char *name;
+	u16 offset;
+	u16 flags;
+	struct clk *clk;
+	struct clk_gate gate;
+};
+
+static struct lpc18xx_clk_branch clk_branches[] = {
+	{BASE_APB3_CLK, "apb3_bus",		CLK_APB3_BUS,		CCU_BRANCH_IS_BUS},
+	{BASE_APB3_CLK, "apb3_i2c1",		CLK_APB3_I2C1,		0},
+	{BASE_APB3_CLK, "apb3_dac",		CLK_APB3_DAC,		0},
+	{BASE_APB3_CLK, "apb3_adc0",		CLK_APB3_ADC0,		0},
+	{BASE_APB3_CLK, "apb3_adc1",		CLK_APB3_ADC1,		0},
+	{BASE_APB3_CLK, "apb3_can0",		CLK_APB3_CAN0,		0},
+
+	{BASE_APB1_CLK, "apb1_bus",		CLK_APB1_BUS,		CCU_BRANCH_IS_BUS},
+	{BASE_APB1_CLK, "apb1_motorcon_pwm",	CLK_APB1_MOTOCON_PWM,	0},
+	{BASE_APB1_CLK, "apb1_i2c0",		CLK_APB1_I2C0,		0},
+	{BASE_APB1_CLK, "apb1_i2s",		CLK_APB1_I2S,		0},
+	{BASE_APB1_CLK, "apb1_can1",		CLK_APB1_CAN1,		0},
+
+	{BASE_SPIFI_CLK, "spifi",		CLK_SPIFI,		0},
+
+	{BASE_CPU_CLK, "cpu_bus",		CLK_CPU_BUS,		CCU_BRANCH_IS_BUS},
+	{BASE_CPU_CLK, "cpu_spifi",		CLK_CPU_SPIFI,		0},
+	{BASE_CPU_CLK, "cpu_gpio",		CLK_CPU_GPIO,		0},
+	{BASE_CPU_CLK, "cpu_lcd",		CLK_CPU_LCD,		0},
+	{BASE_CPU_CLK, "cpu_ethernet",		CLK_CPU_ETHERNET,	0},
+	{BASE_CPU_CLK, "cpu_usb0",		CLK_CPU_USB0,		0},
+	{BASE_CPU_CLK, "cpu_emc",		CLK_CPU_EMC,		0},
+	{BASE_CPU_CLK, "cpu_sdio",		CLK_CPU_SDIO,		0},
+	{BASE_CPU_CLK, "cpu_dma",		CLK_CPU_DMA,		0},
+	{BASE_CPU_CLK, "cpu_core",		CLK_CPU_CORE,		0},
+	{BASE_CPU_CLK, "cpu_sct",		CLK_CPU_SCT,		0},
+	{BASE_CPU_CLK, "cpu_usb1",		CLK_CPU_USB1,		0},
+	{BASE_CPU_CLK, "cpu_emcdiv",		CLK_CPU_EMCDIV,		CCU_BRANCH_HAVE_DIV2},
+	{BASE_CPU_CLK, "cpu_flasha",		CLK_CPU_FLASHA,		CCU_BRANCH_HAVE_DIV2},
+	{BASE_CPU_CLK, "cpu_flashb",		CLK_CPU_FLASHB,		CCU_BRANCH_HAVE_DIV2},
+	{BASE_CPU_CLK, "cpu_m0app",		CLK_CPU_M0APP,		CCU_BRANCH_HAVE_DIV2},
+	{BASE_CPU_CLK, "cpu_adchs",		CLK_CPU_ADCHS,		CCU_BRANCH_HAVE_DIV2},
+	{BASE_CPU_CLK, "cpu_eeprom",		CLK_CPU_EEPROM,		CCU_BRANCH_HAVE_DIV2},
+	{BASE_CPU_CLK, "cpu_wwdt",		CLK_CPU_WWDT,		0},
+	{BASE_CPU_CLK, "cpu_uart0",		CLK_CPU_UART0,		0},
+	{BASE_CPU_CLK, "cpu_uart1",		CLK_CPU_UART1,		0},
+	{BASE_CPU_CLK, "cpu_ssp0",		CLK_CPU_SSP0,		0},
+	{BASE_CPU_CLK, "cpu_timer0",		CLK_CPU_TIMER0,		0},
+	{BASE_CPU_CLK, "cpu_timer1",		CLK_CPU_TIMER1,		0},
+	{BASE_CPU_CLK, "cpu_scu",		CLK_CPU_SCU,		0},
+	{BASE_CPU_CLK, "cpu_creg",		CLK_CPU_CREG,		0},
+	{BASE_CPU_CLK, "cpu_ritimer",		CLK_CPU_RITIMER,	0},
+	{BASE_CPU_CLK, "cpu_uart2",		CLK_CPU_UART2,		0},
+	{BASE_CPU_CLK, "cpu_uart3",		CLK_CPU_UART3,		0},
+	{BASE_CPU_CLK, "cpu_timer2",		CLK_CPU_TIMER2,		0},
+	{BASE_CPU_CLK, "cpu_timer3",		CLK_CPU_TIMER3,		0},
+	{BASE_CPU_CLK, "cpu_ssp1",		CLK_CPU_SSP1,		0},
+	{BASE_CPU_CLK, "cpu_qei",		CLK_CPU_QEI,		0},
+
+	{BASE_PERIPH_CLK, "periph_bus",		CLK_PERIPH_BUS,		CCU_BRANCH_IS_BUS},
+	{BASE_PERIPH_CLK, "periph_core",	CLK_PERIPH_CORE,	0},
+	{BASE_PERIPH_CLK, "periph_sgpio",	CLK_PERIPH_SGPIO,	0},
+
+	{BASE_USB0_CLK,  "usb0",		CLK_USB0,		0},
+	{BASE_USB1_CLK,  "usb1",		CLK_USB1,		0},
+	{BASE_SPI_CLK,   "spi",			CLK_SPI,		0},
+	{BASE_ADCHS_CLK, "adchs",		CLK_ADCHS,		0},
+
+	{BASE_AUDIO_CLK, "audio",		CLK_AUDIO,		0},
+	{BASE_UART3_CLK, "apb2_uart3",		CLK_APB2_UART3,		0},
+	{BASE_UART2_CLK, "apb2_uart2",		CLK_APB2_UART2,		0},
+	{BASE_UART1_CLK, "apb0_uart1",		CLK_APB0_UART1,		0},
+	{BASE_UART0_CLK, "apb0_uart0",		CLK_APB0_UART0,		0},
+	{BASE_SSP1_CLK,  "apb2_ssp1",		CLK_APB2_SSP1,		0},
+	{BASE_SSP0_CLK,  "apb0_ssp0",		CLK_APB0_SSP0,		0},
+	{BASE_SDIO_CLK,  "sdio",		CLK_SDIO,		0},
+};
+
+static int of_clk_get_parent_arg(struct device_node *np, int index)
+{
+	struct of_phandle_args clkspec;
+	int rc;
+
+	if (index < 0)
+		return -EINVAL;
+
+	rc = of_parse_phandle_with_args(np, "clocks", "#clock-cells", index,
+					&clkspec);
+	if (rc)
+		return -EINVAL;
+
+	return clkspec.args_count ? clkspec.args[0] : -EINVAL;
+}
+
+static struct clk *lpc18xx_ccu_branch_clk_get(struct of_phandle_args *clkspec,
+					      void *data)
+{
+	struct lpc18xx_branch_clk_data *clk_data = data;
+	unsigned int offset = clkspec->args[0];
+	int i, j;
+
+	for (i = 0; i < ARRAY_SIZE(clk_branches); i++) {
+		if (clk_branches[i].offset != offset)
+			continue;
+
+		for (j = 0; j < clk_data->num_base_ids; j++) {
+			if (clk_data->base_ids[j] == clk_branches[i].base_id)
+				return clk_branches[i].clk;
+		}
+	}
+
+	pr_err("%s: invalid clock offset %d\n", __func__, offset);
+
+	return ERR_PTR(-EINVAL);
+}
+
+static int lpc18xx_ccu_gate_endisable(struct clk_hw *hw, bool enable)
+{
+	struct clk_gate *gate = to_clk_gate(hw);
+	u32 val;
+
+	/*
+	 * Divider field is write only, so divider stat field must
+	 * be read so divider field can be set accordingly.
+	 */
+	val = clk_readl(gate->reg);
+	if (val & LPC18XX_CCU_DIVSTAT)
+		val |= LPC18XX_CCU_DIV;
+
+	if (enable) {
+		val |= LPC18XX_CCU_RUN;
+	} else {
+		/*
+		 * To safely disable a branch clock a squence of two separate
+		 * writes must be used. First write should set the AUTO bit
+		 * and the next write should clear the RUN bit.
+		 */
+		val |= LPC18XX_CCU_AUTO;
+		clk_writel(val, gate->reg);
+
+		val &= ~LPC18XX_CCU_RUN;
+	}
+
+	clk_writel(val, gate->reg);
+
+	return 0;
+}
+
+static int lpc18xx_ccu_gate_enable(struct clk_hw *hw)
+{
+	return lpc18xx_ccu_gate_endisable(hw, true);
+}
+
+static void lpc18xx_ccu_gate_disable(struct clk_hw *hw)
+{
+	lpc18xx_ccu_gate_endisable(hw, false);
+}
+
+static int lpc18xx_ccu_gate_is_enabled(struct clk_hw *hw)
+{
+	struct clk_gate *gate = to_clk_gate(hw);
+
+	return clk_readl(gate->reg) & LPC18XX_CCU_RUN;
+}
+
+static const struct clk_ops lpc18xx_ccu_gate_ops = {
+	.enable		= lpc18xx_ccu_gate_enable,
+	.disable	= lpc18xx_ccu_gate_disable,
+	.is_enabled	= lpc18xx_ccu_gate_is_enabled,
+};
+
+static void lpc18xx_ccu_register_branch_gate_div(struct lpc18xx_clk_branch *branch,
+						 void __iomem *base,
+						 const char *parent)
+{
+	const struct clk_ops *div_ops = NULL;
+	struct clk_divider *div = NULL;
+	struct clk_hw *div_hw = NULL;
+
+	if (branch->flags & CCU_BRANCH_HAVE_DIV2) {
+		div = kzalloc(sizeof(*div), GFP_KERNEL);
+		if (!div)
+			return;
+
+		div->reg = branch->offset + base;
+		div->flags = CLK_DIVIDER_READ_ONLY;
+		div->shift = 27;
+		div->width = 1;
+
+		div_hw = &div->hw;
+		div_ops = &clk_divider_ops;
+	}
+
+	branch->gate.reg = branch->offset + base;
+	branch->gate.bit_idx = 0;
+
+	branch->clk = clk_register_composite(NULL, branch->name, &parent, 1,
+					     NULL, NULL,
+					     div_hw, div_ops,
+					     &branch->gate.hw, &lpc18xx_ccu_gate_ops, 0);
+	if (IS_ERR(branch->clk)) {
+		kfree(div);
+		pr_warn("%s: failed to register %s\n", __func__, branch->name);
+		return;
+	}
+
+	/* Grab essential branch clocks for CPU and SDRAM */
+	switch (branch->offset) {
+	case CLK_CPU_EMC:
+	case CLK_CPU_CORE:
+	case CLK_CPU_CREG:
+	case CLK_CPU_EMCDIV:
+		clk_prepare_enable(branch->clk);
+	}
+}
+
+static void lpc18xx_ccu_register_branch_clks(void __iomem *base, int base_clk_id,
+					     const char *parent)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(clk_branches); i++) {
+		if (clk_branches[i].base_id != base_clk_id)
+			continue;
+
+		lpc18xx_ccu_register_branch_gate_div(&clk_branches[i], base,
+						     parent);
+
+		if (clk_branches[i].flags & CCU_BRANCH_IS_BUS)
+			parent = clk_branches[i].name;
+	}
+}
+
+static void __init lpc18xx_ccu_init(struct device_node *np)
+{
+	struct lpc18xx_branch_clk_data *clk_data;
+	int num_base_ids, *base_ids;
+	void __iomem *base;
+	const char *parent;
+	int base_clk_id;
+	int i;
+
+	base = of_iomap(np, 0);
+	if (!base) {
+		pr_warn("%s: failed to map address range\n", __func__);
+		return;
+	}
+
+	clk_data = kzalloc(sizeof(*clk_data), GFP_KERNEL);
+	if (!clk_data)
+		return;
+
+	num_base_ids = of_clk_get_parent_count(np);
+
+	base_ids = kcalloc(num_base_ids, sizeof(int), GFP_KERNEL);
+	if (!base_ids) {
+		kfree(clk_data);
+		return;
+	}
+
+	clk_data->base_ids = base_ids;
+	clk_data->num_base_ids = num_base_ids;
+
+	for (i = 0; i < num_base_ids; i++) {
+		parent = of_clk_get_parent_name(np, i);
+
+		base_clk_id = of_clk_get_parent_arg(np, i);
+		if (base_clk_id < 0 && base_clk_id >= BASE_CLK_MAX) {
+			pr_warn("%s: invalid base clk at idx %d\n", __func__, i);
+			base_ids[i] = -EINVAL;
+			continue;
+		}
+
+		clk_data->base_ids[i] = base_clk_id;
+		lpc18xx_ccu_register_branch_clks(base, base_clk_id, parent);
+	}
+
+	of_clk_add_provider(np, lpc18xx_ccu_branch_clk_get, clk_data);
+}
+CLK_OF_DECLARE(lpc18xx_ccu, "nxp,lpc1850-ccu", lpc18xx_ccu_init);
diff --git a/include/dt-bindings/clock/lpc18xx-ccu.h b/include/dt-bindings/clock/lpc18xx-ccu.h
new file mode 100644
index 000000000000..bbfe00b6ab7d
--- /dev/null
+++ b/include/dt-bindings/clock/lpc18xx-ccu.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2015 Joachim Eastwood <manabian@gmail.com>
+ *
+ * This code is released using a dual license strategy: BSD/GPL
+ * You can choose the licence that better fits your requirements.
+ *
+ * Released under the terms of 3-clause BSD License
+ * Released under the terms of GNU General Public License Version 2.0
+ *
+ */
+
+/* Clock Control Unit 1 (CCU1) clock offsets */
+#define CLK_APB3_BUS		0x100
+#define CLK_APB3_I2C1		0x108
+#define CLK_APB3_DAC		0x110
+#define CLK_APB3_ADC0		0x118
+#define CLK_APB3_ADC1		0x120
+#define CLK_APB3_CAN0		0x128
+#define CLK_APB1_BUS		0x200
+#define CLK_APB1_MOTOCON_PWM	0x208
+#define CLK_APB1_I2C0		0x210
+#define CLK_APB1_I2S		0x218
+#define CLK_APB1_CAN1		0x220
+#define CLK_SPIFI		0x300
+#define CLK_CPU_BUS		0x400
+#define CLK_CPU_SPIFI		0x408
+#define CLK_CPU_GPIO		0x410
+#define CLK_CPU_LCD		0x418
+#define CLK_CPU_ETHERNET	0x420
+#define CLK_CPU_USB0		0x428
+#define CLK_CPU_EMC		0x430
+#define CLK_CPU_SDIO		0x438
+#define CLK_CPU_DMA		0x440
+#define CLK_CPU_CORE		0x448
+#define CLK_CPU_SCT		0x468
+#define CLK_CPU_USB1		0x470
+#define CLK_CPU_EMCDIV		0x478
+#define CLK_CPU_FLASHA		0x480
+#define CLK_CPU_FLASHB		0x488
+#define CLK_CPU_M0APP		0x490
+#define CLK_CPU_ADCHS		0x498
+#define CLK_CPU_EEPROM		0x4a0
+#define CLK_CPU_WWDT		0x500
+#define CLK_CPU_UART0		0x508
+#define CLK_CPU_UART1		0x510
+#define CLK_CPU_SSP0		0x518
+#define CLK_CPU_TIMER0		0x520
+#define CLK_CPU_TIMER1		0x528
+#define CLK_CPU_SCU		0x530
+#define CLK_CPU_CREG		0x538
+#define CLK_CPU_RITIMER		0x600
+#define CLK_CPU_UART2		0x608
+#define CLK_CPU_UART3		0x610
+#define CLK_CPU_TIMER2		0x618
+#define CLK_CPU_TIMER3		0x620
+#define CLK_CPU_SSP1		0x628
+#define CLK_CPU_QEI		0x630
+#define CLK_PERIPH_BUS		0x700
+#define CLK_PERIPH_CORE		0x710
+#define CLK_PERIPH_SGPIO	0x718
+#define CLK_USB0		0x800
+#define CLK_USB1		0x900
+#define CLK_SPI			0xA00
+#define CLK_ADCHS		0xB00
+
+/* Clock Control Unit 2 (CCU2) clock offsets */
+#define CLK_AUDIO		0x100
+#define CLK_APB2_UART3		0x200
+#define CLK_APB2_UART2		0x300
+#define CLK_APB0_UART1		0x400
+#define CLK_APB0_UART0		0x500
+#define CLK_APB2_SSP1		0x600
+#define CLK_APB0_SSP0		0x700
+#define CLK_SDIO		0x800
-- 
1.8.0

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH v2 4/4] doc: dt: add documentation for lpc1850-ccu clk driver
  2015-04-27 21:38 ` Joachim Eastwood
  (?)
@ 2015-04-27 21:38     ` Joachim Eastwood
  -1 siblings, 0 replies; 39+ messages in thread
From: Joachim Eastwood @ 2015-04-27 21:38 UTC (permalink / raw)
  To: mturquette-QSEj5FYQhm4dnm+yROfE0A, sboyd-sgV2jX0FEOL9JmXXK+q4OQ,
	arnd-r2nGTMty4D4, linux-clk-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
  Cc: devicetree-u79uwXL29TY76Z2rM5mHXA,
	ariel.dalessandro-Re5JQEeQqe8AvxtiuMwx3w,
	ezequiel-30ULvvUtt6G51wMPkGsGjgyUoB5FGQPZ, Joachim Eastwood

Add DT binding documentation for lpc1850-ccu clk driver.

Signed-off-by: Joachim Eastwood <manabian-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
---
 .../devicetree/bindings/clock/lpc1850-ccu.txt      | 146 +++++++++++++++++++++
 1 file changed, 146 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/clock/lpc1850-ccu.txt

diff --git a/Documentation/devicetree/bindings/clock/lpc1850-ccu.txt b/Documentation/devicetree/bindings/clock/lpc1850-ccu.txt
new file mode 100644
index 000000000000..1b45bc9f004f
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/lpc1850-ccu.txt
@@ -0,0 +1,146 @@
+* NXP LPC1850 Clock Control Unit (CCU)
+
+Each CGU base clock has several clock branches which can be turned on
+or off independently by the Clock Control Units CCU1 or CCU2. The
+branch clocks are distributed between CCU1 and CCU2.
+
+ - Above text taken from NXP LPC1850 User Manual.
+
+This binding uses the common clock binding:
+    Documentation/devicetree/bindings/clock/clock-bindings.txt
+
+Required properties:
+- compatible:
+	Should be "nxp,lpc1850-ccu"
+- reg:
+	Shall define the base and range of the address space
+	containing clock control registers
+- #clock-cells:
+	Shall have value <1>.  The permitted clock-specifier values
+	are the branch clock names defined in table below.
+- clocks:
+	Shall contain a list of phandles for the base clocks routed
+	from the CGU to the specific CCU. See mapping of base clocks
+	and CCU in table below.
+
+Which brach clocks that are available on the CCU depends on the
+specific LPC part.
+
+CCU1 branch clocks:
+Base clock	Branch clock		Description
+BASE_APB3_CLK	CLK_APB3_BUS		APB3 bus clock.
+		CLK_APB3_I2C1		Clock to the I2C1 register interface
+					and I2C1 peripheral clock.
+		CLK_APB3_DAC		Clock to the DAC register interface.
+		CLK_APB3_ADC0		Clock to the ADC0 register interface
+					and ADC0 peripheral clock.
+		CLK_APB3_ADC1		Clock to the ADC1 register interface
+					and ADC1 peripheral clock.
+		CLK_APB3_CAN0		Clock to the C_CAN0 register interface
+					and C_CAN0 peripheral clock.
+BASE_APB1_CLK	CLK_APB1_BUS		APB1 bus clock.
+		CLK_APB1_MOTOCON_PWM	Clock to the PWM Motor control block and
+					PWM Motor control peripheral clock.
+		CLK_APB1_I2C0		Clock to the I2C0 register interface and
+					I2C0 peripheral clock.
+		CLK_APB1_I2S		Clock to the I2S0 and I2S1 register interfaces
+					and I2S0 and I2S1 peripheral clock.
+		CLK_APB1_CAN1		Clock to the C_CAN1 register interface and
+					C_CAN1 peripheral clock.
+BASE_SPIFI_CLK	CLK_SPIFI		Clock for the SPIFI SCKI clock input.
+BASE_CPU_CLK	CLK_CPU_BUS		M4 bus clock.
+		CLK_CPU_SPIFI		Clock to the SPIFI register interface.
+		CLK_CPU_GPIO		Clock to the GPIO register interface
+		CLK_CPU_LCD		Clock to the LCD register interface.
+		CLK_CPU_ETHERNET	Clock to the Ethernet register interface.
+		CLK_CPU_USB0		Clock to the USB0 register interface.
+		CLK_CPU_EMC		Clock to the External memory controller.
+		CLK_CPU_SDIO		Clock to the SD/MMC register interface.
+		CLK_CPU_DMA		Clock to the DMA register interface.
+		CLK_CPU_CORE		Clock to the Cortex-M core
+		CLK_CPU_SCT		Clock to the SCT register interface.
+		CLK_CPU_USB1		Clock to the USB1 register interface.
+		CLK_CPU_EMC_DIV		Clock to the EMC with clock divider.
+		CLK_CPU_FLASHA		Clock to the flash bank A.
+		CLK_CPU_FLASHB		Clock to the flash bank B.
+		CLK_CPU_M0APP		Clock to the M0APP coprocessor.
+		CLK_CPU_ADCHS		Clock to the ADCHS.
+		CLK_CPU_EEPROM		Clock to the EEPROM.
+		CLK_CPU_WWDT		Clock to the WWDT register interface.
+		CLK_CPU_UART0		Clock to the USART0 register interface.
+		CLK_CPU_UART1		Clock to the UART1 register interface.
+		CLK_CPU_SSP0		Clock to the SSP0 register interface.
+		CLK_CPU_TIMER0		Clock to the timer0 register interface and
+					timer0 peripheral clock.
+		CLK_CPU_TIMER1		Clock to the timer1 register interface and
+					timer1 peripheral clock.
+		CLK_CPU_SCU		Clock to the System control unit register interface.
+		CLK_CPU_CREG		Clock to the CREG register interface.
+		CLK_CPU_RITIMER		Clock to the RI timer register interface and
+					RI timer peripheral clock.
+		CLK_CPU_UART2		Clock to the UART2 register interface.
+		CLK_CPU_UART3		Clock to the UART3 register interface.
+		CLK_CPU_TIMER2		Clock to the timer2 register interface and
+					timer2 peripheral clock.
+		CLK_CPU_TIMER3		Clock to the timer3 register interface and
+					timer3 peripheral clock.
+		CLK_CPU_SSP1		Clock to the SSP1 register interface.
+		CLK_CPU_QEI		Clock to the QEI register interface and
+					QEI peripheral clock.
+BASE_PERIPH_CLK	CLK_PERIPH_BUS		Clock to the peripheral bus and the
+					Cortex-M0 subsystem AHB multilayer matrix.
+		CLK_PERIPH_CORE		Clock to the Cortex-M0 subsystem core.
+		CLK_PERIPH_SGPIO	Clock to the SGPIO interface.
+BASE_USB0_CLK	CLK_USB0		USB0 peripheral clock.
+BASE_USB1_CLK	CLK_USB1		USB1 peripheral clock.
+BASE_SPI_CLK	CLK_SPI			Clock to the SPI interface.
+BASE_ADCHS_CLK	CLK_ADCHS		ADCHS clock.
+
+CCU2 branch clocks:
+BASE_AUDIO_CLK	CLK_AUDIO		Audio system (I2S) clock.
+BASE_UART3_CLK	CLK_APB2_UART3		USART3 peripheral clock.
+BASE_UART2_CLK	CLK_APB2_UART2		USART2 peripheral clock.
+BASE_UART1_CLK	CLK_APB0_UART1		UART1 peripheral clock.
+BASE_UART0_CLK	CLK_APB0_UART0		USART0 peripheral clock.
+BASE_SSP1_CLK	CLK_APB2_SSP1		SSP1 peripheral clock.
+BASE_SSP0_CLK	CLK_APB0_SSP0		SSP0 peripheral clock.
+BASE_SDIO_CLK	CLK_SDIO		SD/MMC peripheral clock.
+
+Not all branch clocks are available on all LPC parts. Check the user
+manual for your specific part.
+
+Note that CLK_M3_x and CLK_M4_x have been renamed to CLK_CPU_x here
+be more generic since both LPC18xx (M3) and LPC43xx (M4) are
+supported.
+
+
+Example board file:
+
+soc {
+	ccu1: ccu@40051000 {
+		compatible = "nxp,lpc1850-ccu";
+		reg = <0x40051000 0x1000>;
+		#clock-cells = <1>;
+		clocks = <&cgu BASE_APB3_CLK>,   <&cgu BASE_APB1_CLK>,
+			 <&cgu BASE_SPIFI_CLK>,  <&cgu BASE_CPU_CLK>,
+			 <&cgu BASE_PERIPH_CLK>, <&cgu BASE_USB0_CLK>,
+			 <&cgu BASE_USB1_CLK>,   <&cgu BASE_SPI_CLK>;
+	};
+
+	ccu2: ccu@40052000 {
+		compatible = "nxp,lpc1850-ccu";
+		reg = <0x40052000 0x1000>;
+		#clock-cells = <1>;
+		clocks = <&cgu BASE_AUDIO_CLK>, <&cgu BASE_UART3_CLK>,
+			 <&cgu BASE_UART2_CLK>, <&cgu BASE_UART1_CLK>,
+			 <&cgu BASE_UART0_CLK>, <&cgu BASE_SSP1_CLK>,
+			 <&cgu BASE_SSP0_CLK>,  <&cgu BASE_SDIO_CLK>;
+	};
+
+	/* A user of CCU brach clocks */
+	uart1: serial@40082000 {
+		...
+		clocks = <&ccu2 CLK_APB0_UART1>, <&ccu1 CLK_CPU_UART1>;
+		...
+	};
+};
-- 
1.8.0

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH v2 4/4] doc: dt: add documentation for lpc1850-ccu clk driver
@ 2015-04-27 21:38     ` Joachim Eastwood
  0 siblings, 0 replies; 39+ messages in thread
From: Joachim Eastwood @ 2015-04-27 21:38 UTC (permalink / raw)
  To: mturquette, sboyd, arnd, linux-clk, linux-arm-kernel
  Cc: devicetree, ariel.dalessandro, ezequiel, Joachim Eastwood

Add DT binding documentation for lpc1850-ccu clk driver.

Signed-off-by: Joachim Eastwood <manabian@gmail.com>
---
 .../devicetree/bindings/clock/lpc1850-ccu.txt      | 146 +++++++++++++++++++++
 1 file changed, 146 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/clock/lpc1850-ccu.txt

diff --git a/Documentation/devicetree/bindings/clock/lpc1850-ccu.txt b/Documentation/devicetree/bindings/clock/lpc1850-ccu.txt
new file mode 100644
index 000000000000..1b45bc9f004f
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/lpc1850-ccu.txt
@@ -0,0 +1,146 @@
+* NXP LPC1850 Clock Control Unit (CCU)
+
+Each CGU base clock has several clock branches which can be turned on
+or off independently by the Clock Control Units CCU1 or CCU2. The
+branch clocks are distributed between CCU1 and CCU2.
+
+ - Above text taken from NXP LPC1850 User Manual.
+
+This binding uses the common clock binding:
+    Documentation/devicetree/bindings/clock/clock-bindings.txt
+
+Required properties:
+- compatible:
+	Should be "nxp,lpc1850-ccu"
+- reg:
+	Shall define the base and range of the address space
+	containing clock control registers
+- #clock-cells:
+	Shall have value <1>.  The permitted clock-specifier values
+	are the branch clock names defined in table below.
+- clocks:
+	Shall contain a list of phandles for the base clocks routed
+	from the CGU to the specific CCU. See mapping of base clocks
+	and CCU in table below.
+
+Which brach clocks that are available on the CCU depends on the
+specific LPC part.
+
+CCU1 branch clocks:
+Base clock	Branch clock		Description
+BASE_APB3_CLK	CLK_APB3_BUS		APB3 bus clock.
+		CLK_APB3_I2C1		Clock to the I2C1 register interface
+					and I2C1 peripheral clock.
+		CLK_APB3_DAC		Clock to the DAC register interface.
+		CLK_APB3_ADC0		Clock to the ADC0 register interface
+					and ADC0 peripheral clock.
+		CLK_APB3_ADC1		Clock to the ADC1 register interface
+					and ADC1 peripheral clock.
+		CLK_APB3_CAN0		Clock to the C_CAN0 register interface
+					and C_CAN0 peripheral clock.
+BASE_APB1_CLK	CLK_APB1_BUS		APB1 bus clock.
+		CLK_APB1_MOTOCON_PWM	Clock to the PWM Motor control block and
+					PWM Motor control peripheral clock.
+		CLK_APB1_I2C0		Clock to the I2C0 register interface and
+					I2C0 peripheral clock.
+		CLK_APB1_I2S		Clock to the I2S0 and I2S1 register interfaces
+					and I2S0 and I2S1 peripheral clock.
+		CLK_APB1_CAN1		Clock to the C_CAN1 register interface and
+					C_CAN1 peripheral clock.
+BASE_SPIFI_CLK	CLK_SPIFI		Clock for the SPIFI SCKI clock input.
+BASE_CPU_CLK	CLK_CPU_BUS		M4 bus clock.
+		CLK_CPU_SPIFI		Clock to the SPIFI register interface.
+		CLK_CPU_GPIO		Clock to the GPIO register interface
+		CLK_CPU_LCD		Clock to the LCD register interface.
+		CLK_CPU_ETHERNET	Clock to the Ethernet register interface.
+		CLK_CPU_USB0		Clock to the USB0 register interface.
+		CLK_CPU_EMC		Clock to the External memory controller.
+		CLK_CPU_SDIO		Clock to the SD/MMC register interface.
+		CLK_CPU_DMA		Clock to the DMA register interface.
+		CLK_CPU_CORE		Clock to the Cortex-M core
+		CLK_CPU_SCT		Clock to the SCT register interface.
+		CLK_CPU_USB1		Clock to the USB1 register interface.
+		CLK_CPU_EMC_DIV		Clock to the EMC with clock divider.
+		CLK_CPU_FLASHA		Clock to the flash bank A.
+		CLK_CPU_FLASHB		Clock to the flash bank B.
+		CLK_CPU_M0APP		Clock to the M0APP coprocessor.
+		CLK_CPU_ADCHS		Clock to the ADCHS.
+		CLK_CPU_EEPROM		Clock to the EEPROM.
+		CLK_CPU_WWDT		Clock to the WWDT register interface.
+		CLK_CPU_UART0		Clock to the USART0 register interface.
+		CLK_CPU_UART1		Clock to the UART1 register interface.
+		CLK_CPU_SSP0		Clock to the SSP0 register interface.
+		CLK_CPU_TIMER0		Clock to the timer0 register interface and
+					timer0 peripheral clock.
+		CLK_CPU_TIMER1		Clock to the timer1 register interface and
+					timer1 peripheral clock.
+		CLK_CPU_SCU		Clock to the System control unit register interface.
+		CLK_CPU_CREG		Clock to the CREG register interface.
+		CLK_CPU_RITIMER		Clock to the RI timer register interface and
+					RI timer peripheral clock.
+		CLK_CPU_UART2		Clock to the UART2 register interface.
+		CLK_CPU_UART3		Clock to the UART3 register interface.
+		CLK_CPU_TIMER2		Clock to the timer2 register interface and
+					timer2 peripheral clock.
+		CLK_CPU_TIMER3		Clock to the timer3 register interface and
+					timer3 peripheral clock.
+		CLK_CPU_SSP1		Clock to the SSP1 register interface.
+		CLK_CPU_QEI		Clock to the QEI register interface and
+					QEI peripheral clock.
+BASE_PERIPH_CLK	CLK_PERIPH_BUS		Clock to the peripheral bus and the
+					Cortex-M0 subsystem AHB multilayer matrix.
+		CLK_PERIPH_CORE		Clock to the Cortex-M0 subsystem core.
+		CLK_PERIPH_SGPIO	Clock to the SGPIO interface.
+BASE_USB0_CLK	CLK_USB0		USB0 peripheral clock.
+BASE_USB1_CLK	CLK_USB1		USB1 peripheral clock.
+BASE_SPI_CLK	CLK_SPI			Clock to the SPI interface.
+BASE_ADCHS_CLK	CLK_ADCHS		ADCHS clock.
+
+CCU2 branch clocks:
+BASE_AUDIO_CLK	CLK_AUDIO		Audio system (I2S) clock.
+BASE_UART3_CLK	CLK_APB2_UART3		USART3 peripheral clock.
+BASE_UART2_CLK	CLK_APB2_UART2		USART2 peripheral clock.
+BASE_UART1_CLK	CLK_APB0_UART1		UART1 peripheral clock.
+BASE_UART0_CLK	CLK_APB0_UART0		USART0 peripheral clock.
+BASE_SSP1_CLK	CLK_APB2_SSP1		SSP1 peripheral clock.
+BASE_SSP0_CLK	CLK_APB0_SSP0		SSP0 peripheral clock.
+BASE_SDIO_CLK	CLK_SDIO		SD/MMC peripheral clock.
+
+Not all branch clocks are available on all LPC parts. Check the user
+manual for your specific part.
+
+Note that CLK_M3_x and CLK_M4_x have been renamed to CLK_CPU_x here
+be more generic since both LPC18xx (M3) and LPC43xx (M4) are
+supported.
+
+
+Example board file:
+
+soc {
+	ccu1: ccu@40051000 {
+		compatible = "nxp,lpc1850-ccu";
+		reg = <0x40051000 0x1000>;
+		#clock-cells = <1>;
+		clocks = <&cgu BASE_APB3_CLK>,   <&cgu BASE_APB1_CLK>,
+			 <&cgu BASE_SPIFI_CLK>,  <&cgu BASE_CPU_CLK>,
+			 <&cgu BASE_PERIPH_CLK>, <&cgu BASE_USB0_CLK>,
+			 <&cgu BASE_USB1_CLK>,   <&cgu BASE_SPI_CLK>;
+	};
+
+	ccu2: ccu@40052000 {
+		compatible = "nxp,lpc1850-ccu";
+		reg = <0x40052000 0x1000>;
+		#clock-cells = <1>;
+		clocks = <&cgu BASE_AUDIO_CLK>, <&cgu BASE_UART3_CLK>,
+			 <&cgu BASE_UART2_CLK>, <&cgu BASE_UART1_CLK>,
+			 <&cgu BASE_UART0_CLK>, <&cgu BASE_SSP1_CLK>,
+			 <&cgu BASE_SSP0_CLK>,  <&cgu BASE_SDIO_CLK>;
+	};
+
+	/* A user of CCU brach clocks */
+	uart1: serial@40082000 {
+		...
+		clocks = <&ccu2 CLK_APB0_UART1>, <&ccu1 CLK_CPU_UART1>;
+		...
+	};
+};
-- 
1.8.0

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH v2 4/4] doc: dt: add documentation for lpc1850-ccu clk driver
@ 2015-04-27 21:38     ` Joachim Eastwood
  0 siblings, 0 replies; 39+ messages in thread
From: Joachim Eastwood @ 2015-04-27 21:38 UTC (permalink / raw)
  To: linux-arm-kernel

Add DT binding documentation for lpc1850-ccu clk driver.

Signed-off-by: Joachim Eastwood <manabian@gmail.com>
---
 .../devicetree/bindings/clock/lpc1850-ccu.txt      | 146 +++++++++++++++++++++
 1 file changed, 146 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/clock/lpc1850-ccu.txt

diff --git a/Documentation/devicetree/bindings/clock/lpc1850-ccu.txt b/Documentation/devicetree/bindings/clock/lpc1850-ccu.txt
new file mode 100644
index 000000000000..1b45bc9f004f
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/lpc1850-ccu.txt
@@ -0,0 +1,146 @@
+* NXP LPC1850 Clock Control Unit (CCU)
+
+Each CGU base clock has several clock branches which can be turned on
+or off independently by the Clock Control Units CCU1 or CCU2. The
+branch clocks are distributed between CCU1 and CCU2.
+
+ - Above text taken from NXP LPC1850 User Manual.
+
+This binding uses the common clock binding:
+    Documentation/devicetree/bindings/clock/clock-bindings.txt
+
+Required properties:
+- compatible:
+	Should be "nxp,lpc1850-ccu"
+- reg:
+	Shall define the base and range of the address space
+	containing clock control registers
+- #clock-cells:
+	Shall have value <1>.  The permitted clock-specifier values
+	are the branch clock names defined in table below.
+- clocks:
+	Shall contain a list of phandles for the base clocks routed
+	from the CGU to the specific CCU. See mapping of base clocks
+	and CCU in table below.
+
+Which brach clocks that are available on the CCU depends on the
+specific LPC part.
+
+CCU1 branch clocks:
+Base clock	Branch clock		Description
+BASE_APB3_CLK	CLK_APB3_BUS		APB3 bus clock.
+		CLK_APB3_I2C1		Clock to the I2C1 register interface
+					and I2C1 peripheral clock.
+		CLK_APB3_DAC		Clock to the DAC register interface.
+		CLK_APB3_ADC0		Clock to the ADC0 register interface
+					and ADC0 peripheral clock.
+		CLK_APB3_ADC1		Clock to the ADC1 register interface
+					and ADC1 peripheral clock.
+		CLK_APB3_CAN0		Clock to the C_CAN0 register interface
+					and C_CAN0 peripheral clock.
+BASE_APB1_CLK	CLK_APB1_BUS		APB1 bus clock.
+		CLK_APB1_MOTOCON_PWM	Clock to the PWM Motor control block and
+					PWM Motor control peripheral clock.
+		CLK_APB1_I2C0		Clock to the I2C0 register interface and
+					I2C0 peripheral clock.
+		CLK_APB1_I2S		Clock to the I2S0 and I2S1 register interfaces
+					and I2S0 and I2S1 peripheral clock.
+		CLK_APB1_CAN1		Clock to the C_CAN1 register interface and
+					C_CAN1 peripheral clock.
+BASE_SPIFI_CLK	CLK_SPIFI		Clock for the SPIFI SCKI clock input.
+BASE_CPU_CLK	CLK_CPU_BUS		M4 bus clock.
+		CLK_CPU_SPIFI		Clock to the SPIFI register interface.
+		CLK_CPU_GPIO		Clock to the GPIO register interface
+		CLK_CPU_LCD		Clock to the LCD register interface.
+		CLK_CPU_ETHERNET	Clock to the Ethernet register interface.
+		CLK_CPU_USB0		Clock to the USB0 register interface.
+		CLK_CPU_EMC		Clock to the External memory controller.
+		CLK_CPU_SDIO		Clock to the SD/MMC register interface.
+		CLK_CPU_DMA		Clock to the DMA register interface.
+		CLK_CPU_CORE		Clock to the Cortex-M core
+		CLK_CPU_SCT		Clock to the SCT register interface.
+		CLK_CPU_USB1		Clock to the USB1 register interface.
+		CLK_CPU_EMC_DIV		Clock to the EMC with clock divider.
+		CLK_CPU_FLASHA		Clock to the flash bank A.
+		CLK_CPU_FLASHB		Clock to the flash bank B.
+		CLK_CPU_M0APP		Clock to the M0APP coprocessor.
+		CLK_CPU_ADCHS		Clock to the ADCHS.
+		CLK_CPU_EEPROM		Clock to the EEPROM.
+		CLK_CPU_WWDT		Clock to the WWDT register interface.
+		CLK_CPU_UART0		Clock to the USART0 register interface.
+		CLK_CPU_UART1		Clock to the UART1 register interface.
+		CLK_CPU_SSP0		Clock to the SSP0 register interface.
+		CLK_CPU_TIMER0		Clock to the timer0 register interface and
+					timer0 peripheral clock.
+		CLK_CPU_TIMER1		Clock to the timer1 register interface and
+					timer1 peripheral clock.
+		CLK_CPU_SCU		Clock to the System control unit register interface.
+		CLK_CPU_CREG		Clock to the CREG register interface.
+		CLK_CPU_RITIMER		Clock to the RI timer register interface and
+					RI timer peripheral clock.
+		CLK_CPU_UART2		Clock to the UART2 register interface.
+		CLK_CPU_UART3		Clock to the UART3 register interface.
+		CLK_CPU_TIMER2		Clock to the timer2 register interface and
+					timer2 peripheral clock.
+		CLK_CPU_TIMER3		Clock to the timer3 register interface and
+					timer3 peripheral clock.
+		CLK_CPU_SSP1		Clock to the SSP1 register interface.
+		CLK_CPU_QEI		Clock to the QEI register interface and
+					QEI peripheral clock.
+BASE_PERIPH_CLK	CLK_PERIPH_BUS		Clock to the peripheral bus and the
+					Cortex-M0 subsystem AHB multilayer matrix.
+		CLK_PERIPH_CORE		Clock to the Cortex-M0 subsystem core.
+		CLK_PERIPH_SGPIO	Clock to the SGPIO interface.
+BASE_USB0_CLK	CLK_USB0		USB0 peripheral clock.
+BASE_USB1_CLK	CLK_USB1		USB1 peripheral clock.
+BASE_SPI_CLK	CLK_SPI			Clock to the SPI interface.
+BASE_ADCHS_CLK	CLK_ADCHS		ADCHS clock.
+
+CCU2 branch clocks:
+BASE_AUDIO_CLK	CLK_AUDIO		Audio system (I2S) clock.
+BASE_UART3_CLK	CLK_APB2_UART3		USART3 peripheral clock.
+BASE_UART2_CLK	CLK_APB2_UART2		USART2 peripheral clock.
+BASE_UART1_CLK	CLK_APB0_UART1		UART1 peripheral clock.
+BASE_UART0_CLK	CLK_APB0_UART0		USART0 peripheral clock.
+BASE_SSP1_CLK	CLK_APB2_SSP1		SSP1 peripheral clock.
+BASE_SSP0_CLK	CLK_APB0_SSP0		SSP0 peripheral clock.
+BASE_SDIO_CLK	CLK_SDIO		SD/MMC peripheral clock.
+
+Not all branch clocks are available on all LPC parts. Check the user
+manual for your specific part.
+
+Note that CLK_M3_x and CLK_M4_x have been renamed to CLK_CPU_x here
+be more generic since both LPC18xx (M3) and LPC43xx (M4) are
+supported.
+
+
+Example board file:
+
+soc {
+	ccu1: ccu at 40051000 {
+		compatible = "nxp,lpc1850-ccu";
+		reg = <0x40051000 0x1000>;
+		#clock-cells = <1>;
+		clocks = <&cgu BASE_APB3_CLK>,   <&cgu BASE_APB1_CLK>,
+			 <&cgu BASE_SPIFI_CLK>,  <&cgu BASE_CPU_CLK>,
+			 <&cgu BASE_PERIPH_CLK>, <&cgu BASE_USB0_CLK>,
+			 <&cgu BASE_USB1_CLK>,   <&cgu BASE_SPI_CLK>;
+	};
+
+	ccu2: ccu at 40052000 {
+		compatible = "nxp,lpc1850-ccu";
+		reg = <0x40052000 0x1000>;
+		#clock-cells = <1>;
+		clocks = <&cgu BASE_AUDIO_CLK>, <&cgu BASE_UART3_CLK>,
+			 <&cgu BASE_UART2_CLK>, <&cgu BASE_UART1_CLK>,
+			 <&cgu BASE_UART0_CLK>, <&cgu BASE_SSP1_CLK>,
+			 <&cgu BASE_SSP0_CLK>,  <&cgu BASE_SDIO_CLK>;
+	};
+
+	/* A user of CCU brach clocks */
+	uart1: serial at 40082000 {
+		...
+		clocks = <&ccu2 CLK_APB0_UART1>, <&ccu1 CLK_CPU_UART1>;
+		...
+	};
+};
-- 
1.8.0

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* Re: [PATCH v2 2/4] doc: dt: add documentation for lpc1850-cgu clk driver
  2015-04-27 21:38     ` Joachim Eastwood
  (?)
@ 2015-05-12 22:12         ` Michael Turquette
  -1 siblings, 0 replies; 39+ messages in thread
From: Michael Turquette @ 2015-05-12 22:12 UTC (permalink / raw)
  To: sboyd-sgV2jX0FEOL9JmXXK+q4OQ, arnd-r2nGTMty4D4,
	linux-clk-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
  Cc: devicetree-u79uwXL29TY76Z2rM5mHXA,
	ariel.dalessandro-Re5JQEeQqe8AvxtiuMwx3w,
	ezequiel-30ULvvUtt6G51wMPkGsGjgyUoB5FGQPZ, Joachim Eastwood

Quoting Joachim Eastwood (2015-04-27 14:38:11)
> Add DT binding documentation for lpc1850-cgu driver.
> 
> Signed-off-by: Joachim Eastwood <manabian-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
> ---
>  .../devicetree/bindings/clock/lpc1850-cgu.txt      | 138 +++++++++++++++++++++
>  1 file changed, 138 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/clock/lpc1850-cgu.txt
> 
> diff --git a/Documentation/devicetree/bindings/clock/lpc1850-cgu.txt b/Documentation/devicetree/bindings/clock/lpc1850-cgu.txt
> new file mode 100644
> index 000000000000..0b278ca6aee7
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/clock/lpc1850-cgu.txt
> @@ -0,0 +1,138 @@
> +* NXP LPC1850 Clock Generation Unit (CGU)
> +
> +The CGU generates multiple independent clocks for the core and the
> +peripheral blocks of the LPC18xx. Each independent clock is called
> +a base clock and itself is one of the inputs to the two Clock
> +Control Units (CCUs) which control the branch clocks to the
> +individual peripherals.
> +
> +The CGU selects the inputs to the clock generators from multiple
> +clock sources, controls the clock generation, and routes the outputs
> +of the clock generators through the clock source bus to the output
> +stages. Each output stage provides an independent clock source and
> +corresponds to one of the base clocks for the LPC18xx.
> +
> + - Above text taken from NXP LPC1850 User Manual.
> +
> +
> +This binding uses the common clock binding:
> +    Documentation/devicetree/bindings/clock/clock-bindings.txt
> +
> +Required properties:
> +- compatible:
> +       Should be "nxp,lpc1850-cgu"
> +- reg:
> +       Shall define the base and range of the address space
> +       containing clock control registers
> +- #clock-cells:
> +       Shall have value <1>.  The permitted clock-specifier values
> +       are the base clock numbers defined below.
> +- clocks:
> +       Shall contain a list of phandles for the external input
> +       sources to the CGU. The list shall be in the following
> +       order: xtal, 32khz, enet_rx_clk, enet_tx_clk, gp_clkin.
> +- clock-indices:
> +       Shall be an ordered list of numbers defining the base clock
> +       number provided by the CGU.
> +- clock-output-names:
> +       Shall be an ordered list of strings defining the names of
> +       the clocks provided by the CGU.
> +
> +Which base clocks that are available on the CGU depends on the
> +specific LPC part. Base cloks are numbered from 0 to 27.

s/cloks/clocks/

> +
> +Number:                Name:                   Description:
> + 0             BASE_SAFE_CLK           Base safe clock (always on) for WWDT
> + 1             BASE_USB0_CLK           Base clock for USB0
> + 2             BASE_PERIPH_CLK         Base clock for Cortex-M0SUB subsystem,
> +                                       SPI, and SGPIO
> + 3             BASE_USB1_CLK           Base clock for USB1
> + 4             BASE_CPU_CLK            System base clock for ARM Cortex-M core
> +                                       and APB peripheral blocks #0 and #2
> + 5             BASE_SPIFI_CLK          Base clock for SPIFI
> + 6             BASE_SPI_CLK            Base clock for SPI
> + 7             BASE_PHY_RX_CLK         Base clock for Ethernet PHY Receive clock
> + 8             BASE_PHY_TX_CLK         Base clock for Ethernet PHY Transmit clock
> + 9             BASE_APB1_CLK           Base clock for APB peripheral block # 1
> +10             BASE_APB3_CLK           Base clock for APB peripheral block # 3
> +11             BASE_LCD_CLK            Base clock for LCD
> +12             BASE_ADCHS_CLK          Base clock for ADCHS
> +13             BASE_SDIO_CLK           Base clock for SD/MMC
> +14             BASE_SSP0_CLK           Base clock for SSP0
> +15             BASE_SSP1_CLK           Base clock for SSP1
> +16             BASE_UART0_CLK          Base clock for UART0
> +17             BASE_UART1_CLK          Base clock for UART1
> +18             BASE_UART2_CLK          Base clock for UART2
> +19             BASE_UART3_CLK          Base clock for UART3
> +20             BASE_OUT_CLK            Base clock for CLKOUT pin
> +24-21          -                       Reserved
> +25             BASE_AUDIO_CLK          Base clock for audio system (I2S)
> +26             BASE_CGU_OUT0_CLK       Base clock for CGU_OUT0 clock output
> +27             BASE_CGU_OUT1_CLK       Base clock for CGU_OUT1 clock output
> +
> +BASE_PERIPH_CLK and BASE_SPI_CLK is only available on LPC43xx.
> +BASE_ADCHS_CLK is only available on LPC4370.
> +
> +
> +Example board file:
> +
> +/ {
> +       clocks {
> +               xtal: xtal {
> +                       compatible = "fixed-clock";
> +                       #clock-cells = <0>;
> +                       clock-frequency = <12000000>;
> +               };
> +
> +               xtal32: xtal32 {
> +                       compatible = "fixed-clock";
> +                       #clock-cells = <0>;
> +                       clock-frequency = <32768>;
> +               };
> +
> +               enet_rx_clk: enet_rx_clk {
> +                       compatible = "fixed-clock";
> +                       #clock-cells = <0>;
> +                       clock-frequency = <0>;
> +                       clock-output-names = "enet_rx_clk";
> +               };
> +
> +               enet_tx_clk: enet_tx_clk {
> +                       compatible = "fixed-clock";
> +                       #clock-cells = <0>;
> +                       clock-frequency = <0>;
> +                       clock-output-names = "enet_tx_clk";
> +               };
> +
> +               gp_clkin: gp_clkin {
> +                       compatible = "fixed-clock";
> +                       #clock-cells = <0>;
> +                       clock-frequency = <0>;
> +                       clock-output-names = "gp_clkin";
> +               };
> +       };
> +
> +       soc {
> +               cgu: cgu@40050000 {
> +                       compatible = "nxp,lpc1850-cgu";
> +                       reg = <0x40050000 0x1000>;
> +                       #clock-cells = <1>;
> +                       clocks = <&xtal>, <&creg_clk 1>, <&enet_rx_clk>, <&enet_tx_clk>, <&gp_clkin>;
> +                       clock-indices =  <0>,  <1>,  <2>,  <3>,  <4>,  <5>,  <6>,  <7>,
> +                                        <8>,  <9>, <10>, <11>, <12>, <13>, <14>, <15>,
> +                                       <16>, <17>, <18>, <19>, <20>, <25>, <26>, <27>;
> +                       clock-output-names = "base_safe_clk",    "base_usb0_clk",
> +                                            "base_periph_clk",  "base_usb1_clk",
> +                                            "base_cpu_clk",     "base_spifi_clk",
> +                                            "base_spi_clk",     "base_phy_rx_clk",
> +                                            "base_phy_tx_clk",  "base_apb1_clk",
> +                                            "base_apb3_clk",    "base_lcd_clk",
> +                                            "base_adchs_clk",   "base_sdio_clk",
> +                                            "base_ssp0_clk",    "base_ssp1_clk",
> +                                            "base_uart0_clk",   "base_uart1_clk",
> +                                            "base_uart2_clk",   "base_uart3_clk",
> +                                            "base_out_clk",     "base_audio_clk",
> +                                            "base_cgu_out0_clk","base_cgu_out1_clk";

Why do you need to use clock-indices?

Why do you need to use clock-output-names? If all of your clock
consumers have nodes in DT then you can skip this and name them on the
consuming side. See a further explanation here:
http://lkml.kernel.org/r/<20150416192014.19585.9663@quantum>

Also note that providing a clock consumer node in the examples section
of the binding is helpful when reviewing.

Regards,
Mike

> +               };
> +       };
> +};
> -- 
> 1.8.0
> 
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH v2 2/4] doc: dt: add documentation for lpc1850-cgu clk driver
@ 2015-05-12 22:12         ` Michael Turquette
  0 siblings, 0 replies; 39+ messages in thread
From: Michael Turquette @ 2015-05-12 22:12 UTC (permalink / raw)
  To: Joachim Eastwood, sboyd, arnd, linux-clk, linux-arm-kernel
  Cc: devicetree, ariel.dalessandro, ezequiel, Joachim Eastwood

Quoting Joachim Eastwood (2015-04-27 14:38:11)
> Add DT binding documentation for lpc1850-cgu driver.
> =

> Signed-off-by: Joachim Eastwood <manabian@gmail.com>
> ---
>  .../devicetree/bindings/clock/lpc1850-cgu.txt      | 138 +++++++++++++++=
++++++
>  1 file changed, 138 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/clock/lpc1850-cgu.t=
xt
> =

> diff --git a/Documentation/devicetree/bindings/clock/lpc1850-cgu.txt b/Do=
cumentation/devicetree/bindings/clock/lpc1850-cgu.txt
> new file mode 100644
> index 000000000000..0b278ca6aee7
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/clock/lpc1850-cgu.txt
> @@ -0,0 +1,138 @@
> +* NXP LPC1850 Clock Generation Unit (CGU)
> +
> +The CGU generates multiple independent clocks for the core and the
> +peripheral blocks of the LPC18xx. Each independent clock is called
> +a base clock and itself is one of the inputs to the two Clock
> +Control Units (CCUs) which control the branch clocks to the
> +individual peripherals.
> +
> +The CGU selects the inputs to the clock generators from multiple
> +clock sources, controls the clock generation, and routes the outputs
> +of the clock generators through the clock source bus to the output
> +stages. Each output stage provides an independent clock source and
> +corresponds to one of the base clocks for the LPC18xx.
> +
> + - Above text taken from NXP LPC1850 User Manual.
> +
> +
> +This binding uses the common clock binding:
> +    Documentation/devicetree/bindings/clock/clock-bindings.txt
> +
> +Required properties:
> +- compatible:
> +       Should be "nxp,lpc1850-cgu"
> +- reg:
> +       Shall define the base and range of the address space
> +       containing clock control registers
> +- #clock-cells:
> +       Shall have value <1>.  The permitted clock-specifier values
> +       are the base clock numbers defined below.
> +- clocks:
> +       Shall contain a list of phandles for the external input
> +       sources to the CGU. The list shall be in the following
> +       order: xtal, 32khz, enet_rx_clk, enet_tx_clk, gp_clkin.
> +- clock-indices:
> +       Shall be an ordered list of numbers defining the base clock
> +       number provided by the CGU.
> +- clock-output-names:
> +       Shall be an ordered list of strings defining the names of
> +       the clocks provided by the CGU.
> +
> +Which base clocks that are available on the CGU depends on the
> +specific LPC part. Base cloks are numbered from 0 to 27.

s/cloks/clocks/

> +
> +Number:                Name:                   Description:
> + 0             BASE_SAFE_CLK           Base safe clock (always on) for W=
WDT
> + 1             BASE_USB0_CLK           Base clock for USB0
> + 2             BASE_PERIPH_CLK         Base clock for Cortex-M0SUB subsy=
stem,
> +                                       SPI, and SGPIO
> + 3             BASE_USB1_CLK           Base clock for USB1
> + 4             BASE_CPU_CLK            System base clock for ARM Cortex-=
M core
> +                                       and APB peripheral blocks #0 and =
#2
> + 5             BASE_SPIFI_CLK          Base clock for SPIFI
> + 6             BASE_SPI_CLK            Base clock for SPI
> + 7             BASE_PHY_RX_CLK         Base clock for Ethernet PHY Recei=
ve clock
> + 8             BASE_PHY_TX_CLK         Base clock for Ethernet PHY Trans=
mit clock
> + 9             BASE_APB1_CLK           Base clock for APB peripheral blo=
ck # 1
> +10             BASE_APB3_CLK           Base clock for APB peripheral blo=
ck # 3
> +11             BASE_LCD_CLK            Base clock for LCD
> +12             BASE_ADCHS_CLK          Base clock for ADCHS
> +13             BASE_SDIO_CLK           Base clock for SD/MMC
> +14             BASE_SSP0_CLK           Base clock for SSP0
> +15             BASE_SSP1_CLK           Base clock for SSP1
> +16             BASE_UART0_CLK          Base clock for UART0
> +17             BASE_UART1_CLK          Base clock for UART1
> +18             BASE_UART2_CLK          Base clock for UART2
> +19             BASE_UART3_CLK          Base clock for UART3
> +20             BASE_OUT_CLK            Base clock for CLKOUT pin
> +24-21          -                       Reserved
> +25             BASE_AUDIO_CLK          Base clock for audio system (I2S)
> +26             BASE_CGU_OUT0_CLK       Base clock for CGU_OUT0 clock out=
put
> +27             BASE_CGU_OUT1_CLK       Base clock for CGU_OUT1 clock out=
put
> +
> +BASE_PERIPH_CLK and BASE_SPI_CLK is only available on LPC43xx.
> +BASE_ADCHS_CLK is only available on LPC4370.
> +
> +
> +Example board file:
> +
> +/ {
> +       clocks {
> +               xtal: xtal {
> +                       compatible =3D "fixed-clock";
> +                       #clock-cells =3D <0>;
> +                       clock-frequency =3D <12000000>;
> +               };
> +
> +               xtal32: xtal32 {
> +                       compatible =3D "fixed-clock";
> +                       #clock-cells =3D <0>;
> +                       clock-frequency =3D <32768>;
> +               };
> +
> +               enet_rx_clk: enet_rx_clk {
> +                       compatible =3D "fixed-clock";
> +                       #clock-cells =3D <0>;
> +                       clock-frequency =3D <0>;
> +                       clock-output-names =3D "enet_rx_clk";
> +               };
> +
> +               enet_tx_clk: enet_tx_clk {
> +                       compatible =3D "fixed-clock";
> +                       #clock-cells =3D <0>;
> +                       clock-frequency =3D <0>;
> +                       clock-output-names =3D "enet_tx_clk";
> +               };
> +
> +               gp_clkin: gp_clkin {
> +                       compatible =3D "fixed-clock";
> +                       #clock-cells =3D <0>;
> +                       clock-frequency =3D <0>;
> +                       clock-output-names =3D "gp_clkin";
> +               };
> +       };
> +
> +       soc {
> +               cgu: cgu@40050000 {
> +                       compatible =3D "nxp,lpc1850-cgu";
> +                       reg =3D <0x40050000 0x1000>;
> +                       #clock-cells =3D <1>;
> +                       clocks =3D <&xtal>, <&creg_clk 1>, <&enet_rx_clk>=
, <&enet_tx_clk>, <&gp_clkin>;
> +                       clock-indices =3D  <0>,  <1>,  <2>,  <3>,  <4>,  =
<5>,  <6>,  <7>,
> +                                        <8>,  <9>, <10>, <11>, <12>, <13=
>, <14>, <15>,
> +                                       <16>, <17>, <18>, <19>, <20>, <25=
>, <26>, <27>;
> +                       clock-output-names =3D "base_safe_clk",    "base_=
usb0_clk",
> +                                            "base_periph_clk",  "base_us=
b1_clk",
> +                                            "base_cpu_clk",     "base_sp=
ifi_clk",
> +                                            "base_spi_clk",     "base_ph=
y_rx_clk",
> +                                            "base_phy_tx_clk",  "base_ap=
b1_clk",
> +                                            "base_apb3_clk",    "base_lc=
d_clk",
> +                                            "base_adchs_clk",   "base_sd=
io_clk",
> +                                            "base_ssp0_clk",    "base_ss=
p1_clk",
> +                                            "base_uart0_clk",   "base_ua=
rt1_clk",
> +                                            "base_uart2_clk",   "base_ua=
rt3_clk",
> +                                            "base_out_clk",     "base_au=
dio_clk",
> +                                            "base_cgu_out0_clk","base_cg=
u_out1_clk";

Why do you need to use clock-indices?

Why do you need to use clock-output-names? If all of your clock
consumers have nodes in DT then you can skip this and name them on the
consuming side. See a further explanation here:
http://lkml.kernel.org/r/<20150416192014.19585.9663@quantum>

Also note that providing a clock consumer node in the examples section
of the binding is helpful when reviewing.

Regards,
Mike

> +               };
> +       };
> +};
> -- =

> 1.8.0
>=20

^ permalink raw reply	[flat|nested] 39+ messages in thread

* [PATCH v2 2/4] doc: dt: add documentation for lpc1850-cgu clk driver
@ 2015-05-12 22:12         ` Michael Turquette
  0 siblings, 0 replies; 39+ messages in thread
From: Michael Turquette @ 2015-05-12 22:12 UTC (permalink / raw)
  To: linux-arm-kernel

Quoting Joachim Eastwood (2015-04-27 14:38:11)
> Add DT binding documentation for lpc1850-cgu driver.
> 
> Signed-off-by: Joachim Eastwood <manabian@gmail.com>
> ---
>  .../devicetree/bindings/clock/lpc1850-cgu.txt      | 138 +++++++++++++++++++++
>  1 file changed, 138 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/clock/lpc1850-cgu.txt
> 
> diff --git a/Documentation/devicetree/bindings/clock/lpc1850-cgu.txt b/Documentation/devicetree/bindings/clock/lpc1850-cgu.txt
> new file mode 100644
> index 000000000000..0b278ca6aee7
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/clock/lpc1850-cgu.txt
> @@ -0,0 +1,138 @@
> +* NXP LPC1850 Clock Generation Unit (CGU)
> +
> +The CGU generates multiple independent clocks for the core and the
> +peripheral blocks of the LPC18xx. Each independent clock is called
> +a base clock and itself is one of the inputs to the two Clock
> +Control Units (CCUs) which control the branch clocks to the
> +individual peripherals.
> +
> +The CGU selects the inputs to the clock generators from multiple
> +clock sources, controls the clock generation, and routes the outputs
> +of the clock generators through the clock source bus to the output
> +stages. Each output stage provides an independent clock source and
> +corresponds to one of the base clocks for the LPC18xx.
> +
> + - Above text taken from NXP LPC1850 User Manual.
> +
> +
> +This binding uses the common clock binding:
> +    Documentation/devicetree/bindings/clock/clock-bindings.txt
> +
> +Required properties:
> +- compatible:
> +       Should be "nxp,lpc1850-cgu"
> +- reg:
> +       Shall define the base and range of the address space
> +       containing clock control registers
> +- #clock-cells:
> +       Shall have value <1>.  The permitted clock-specifier values
> +       are the base clock numbers defined below.
> +- clocks:
> +       Shall contain a list of phandles for the external input
> +       sources to the CGU. The list shall be in the following
> +       order: xtal, 32khz, enet_rx_clk, enet_tx_clk, gp_clkin.
> +- clock-indices:
> +       Shall be an ordered list of numbers defining the base clock
> +       number provided by the CGU.
> +- clock-output-names:
> +       Shall be an ordered list of strings defining the names of
> +       the clocks provided by the CGU.
> +
> +Which base clocks that are available on the CGU depends on the
> +specific LPC part. Base cloks are numbered from 0 to 27.

s/cloks/clocks/

> +
> +Number:                Name:                   Description:
> + 0             BASE_SAFE_CLK           Base safe clock (always on) for WWDT
> + 1             BASE_USB0_CLK           Base clock for USB0
> + 2             BASE_PERIPH_CLK         Base clock for Cortex-M0SUB subsystem,
> +                                       SPI, and SGPIO
> + 3             BASE_USB1_CLK           Base clock for USB1
> + 4             BASE_CPU_CLK            System base clock for ARM Cortex-M core
> +                                       and APB peripheral blocks #0 and #2
> + 5             BASE_SPIFI_CLK          Base clock for SPIFI
> + 6             BASE_SPI_CLK            Base clock for SPI
> + 7             BASE_PHY_RX_CLK         Base clock for Ethernet PHY Receive clock
> + 8             BASE_PHY_TX_CLK         Base clock for Ethernet PHY Transmit clock
> + 9             BASE_APB1_CLK           Base clock for APB peripheral block # 1
> +10             BASE_APB3_CLK           Base clock for APB peripheral block # 3
> +11             BASE_LCD_CLK            Base clock for LCD
> +12             BASE_ADCHS_CLK          Base clock for ADCHS
> +13             BASE_SDIO_CLK           Base clock for SD/MMC
> +14             BASE_SSP0_CLK           Base clock for SSP0
> +15             BASE_SSP1_CLK           Base clock for SSP1
> +16             BASE_UART0_CLK          Base clock for UART0
> +17             BASE_UART1_CLK          Base clock for UART1
> +18             BASE_UART2_CLK          Base clock for UART2
> +19             BASE_UART3_CLK          Base clock for UART3
> +20             BASE_OUT_CLK            Base clock for CLKOUT pin
> +24-21          -                       Reserved
> +25             BASE_AUDIO_CLK          Base clock for audio system (I2S)
> +26             BASE_CGU_OUT0_CLK       Base clock for CGU_OUT0 clock output
> +27             BASE_CGU_OUT1_CLK       Base clock for CGU_OUT1 clock output
> +
> +BASE_PERIPH_CLK and BASE_SPI_CLK is only available on LPC43xx.
> +BASE_ADCHS_CLK is only available on LPC4370.
> +
> +
> +Example board file:
> +
> +/ {
> +       clocks {
> +               xtal: xtal {
> +                       compatible = "fixed-clock";
> +                       #clock-cells = <0>;
> +                       clock-frequency = <12000000>;
> +               };
> +
> +               xtal32: xtal32 {
> +                       compatible = "fixed-clock";
> +                       #clock-cells = <0>;
> +                       clock-frequency = <32768>;
> +               };
> +
> +               enet_rx_clk: enet_rx_clk {
> +                       compatible = "fixed-clock";
> +                       #clock-cells = <0>;
> +                       clock-frequency = <0>;
> +                       clock-output-names = "enet_rx_clk";
> +               };
> +
> +               enet_tx_clk: enet_tx_clk {
> +                       compatible = "fixed-clock";
> +                       #clock-cells = <0>;
> +                       clock-frequency = <0>;
> +                       clock-output-names = "enet_tx_clk";
> +               };
> +
> +               gp_clkin: gp_clkin {
> +                       compatible = "fixed-clock";
> +                       #clock-cells = <0>;
> +                       clock-frequency = <0>;
> +                       clock-output-names = "gp_clkin";
> +               };
> +       };
> +
> +       soc {
> +               cgu: cgu at 40050000 {
> +                       compatible = "nxp,lpc1850-cgu";
> +                       reg = <0x40050000 0x1000>;
> +                       #clock-cells = <1>;
> +                       clocks = <&xtal>, <&creg_clk 1>, <&enet_rx_clk>, <&enet_tx_clk>, <&gp_clkin>;
> +                       clock-indices =  <0>,  <1>,  <2>,  <3>,  <4>,  <5>,  <6>,  <7>,
> +                                        <8>,  <9>, <10>, <11>, <12>, <13>, <14>, <15>,
> +                                       <16>, <17>, <18>, <19>, <20>, <25>, <26>, <27>;
> +                       clock-output-names = "base_safe_clk",    "base_usb0_clk",
> +                                            "base_periph_clk",  "base_usb1_clk",
> +                                            "base_cpu_clk",     "base_spifi_clk",
> +                                            "base_spi_clk",     "base_phy_rx_clk",
> +                                            "base_phy_tx_clk",  "base_apb1_clk",
> +                                            "base_apb3_clk",    "base_lcd_clk",
> +                                            "base_adchs_clk",   "base_sdio_clk",
> +                                            "base_ssp0_clk",    "base_ssp1_clk",
> +                                            "base_uart0_clk",   "base_uart1_clk",
> +                                            "base_uart2_clk",   "base_uart3_clk",
> +                                            "base_out_clk",     "base_audio_clk",
> +                                            "base_cgu_out0_clk","base_cgu_out1_clk";

Why do you need to use clock-indices?

Why do you need to use clock-output-names? If all of your clock
consumers have nodes in DT then you can skip this and name them on the
consuming side. See a further explanation here:
http://lkml.kernel.org/r/<20150416192014.19585.9663@quantum>

Also note that providing a clock consumer node in the examples section
of the binding is helpful when reviewing.

Regards,
Mike

> +               };
> +       };
> +};
> -- 
> 1.8.0
> 

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH v2 0/4] Clk drivers for NXP LPC18xx family
  2015-04-27 21:38 ` Joachim Eastwood
  (?)
@ 2015-05-12 22:31     ` Stephen Boyd
  -1 siblings, 0 replies; 39+ messages in thread
From: Stephen Boyd @ 2015-05-12 22:31 UTC (permalink / raw)
  To: Joachim Eastwood
  Cc: mturquette-QSEj5FYQhm4dnm+yROfE0A, arnd-r2nGTMty4D4,
	linux-clk-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	ariel.dalessandro-Re5JQEeQqe8AvxtiuMwx3w,
	ezequiel-30ULvvUtt6G51wMPkGsGjgyUoB5FGQPZ

On 04/27, Joachim Eastwood wrote:
> This patch set adds support for the two main clock peripherals in the
> LPC18xx/43xx MCU family.
> 
> The Clock Generation Unit (CGU) is the base source of all clocks. It has
> five external inputs and contains PLLs, dividers and muxes. The outputs
> from the CGU are then routed to a Clock Control Unit (CCU) and a few
> peripherals directly. There are two CCUs in the MCU. The CCU is a
> collection of gates and a few dividers that sits between the CGU and
> most of the peripherals.
> 
> Which clocks that are available depends on the specific device and it's
> peripherals. It's possible in DT to setup the routing between the CGU
> and the CCUs.

Is there any reason why this uses CLK_OF_DECLARE over the
platform device model? Typically we have CLK_OF_DECLARE for cases
where a provider needs to be up and running early during boot for
hardware that can't probe defer (i.e. timers, irq controllers).
Otherwise we should be able to use the standard linux device
model to probe clk providers. It looks like the clocksource is
using something from CCU, but perhaps CGU isn't "special" and
could be using device model.

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH v2 0/4] Clk drivers for NXP LPC18xx family
@ 2015-05-12 22:31     ` Stephen Boyd
  0 siblings, 0 replies; 39+ messages in thread
From: Stephen Boyd @ 2015-05-12 22:31 UTC (permalink / raw)
  To: Joachim Eastwood
  Cc: mturquette, arnd, linux-clk, linux-arm-kernel, devicetree,
	ariel.dalessandro, ezequiel

On 04/27, Joachim Eastwood wrote:
> This patch set adds support for the two main clock peripherals in the
> LPC18xx/43xx MCU family.
> 
> The Clock Generation Unit (CGU) is the base source of all clocks. It has
> five external inputs and contains PLLs, dividers and muxes. The outputs
> from the CGU are then routed to a Clock Control Unit (CCU) and a few
> peripherals directly. There are two CCUs in the MCU. The CCU is a
> collection of gates and a few dividers that sits between the CGU and
> most of the peripherals.
> 
> Which clocks that are available depends on the specific device and it's
> peripherals. It's possible in DT to setup the routing between the CGU
> and the CCUs.

Is there any reason why this uses CLK_OF_DECLARE over the
platform device model? Typically we have CLK_OF_DECLARE for cases
where a provider needs to be up and running early during boot for
hardware that can't probe defer (i.e. timers, irq controllers).
Otherwise we should be able to use the standard linux device
model to probe clk providers. It looks like the clocksource is
using something from CCU, but perhaps CGU isn't "special" and
could be using device model.

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project

^ permalink raw reply	[flat|nested] 39+ messages in thread

* [PATCH v2 0/4] Clk drivers for NXP LPC18xx family
@ 2015-05-12 22:31     ` Stephen Boyd
  0 siblings, 0 replies; 39+ messages in thread
From: Stephen Boyd @ 2015-05-12 22:31 UTC (permalink / raw)
  To: linux-arm-kernel

On 04/27, Joachim Eastwood wrote:
> This patch set adds support for the two main clock peripherals in the
> LPC18xx/43xx MCU family.
> 
> The Clock Generation Unit (CGU) is the base source of all clocks. It has
> five external inputs and contains PLLs, dividers and muxes. The outputs
> from the CGU are then routed to a Clock Control Unit (CCU) and a few
> peripherals directly. There are two CCUs in the MCU. The CCU is a
> collection of gates and a few dividers that sits between the CGU and
> most of the peripherals.
> 
> Which clocks that are available depends on the specific device and it's
> peripherals. It's possible in DT to setup the routing between the CGU
> and the CCUs.

Is there any reason why this uses CLK_OF_DECLARE over the
platform device model? Typically we have CLK_OF_DECLARE for cases
where a provider needs to be up and running early during boot for
hardware that can't probe defer (i.e. timers, irq controllers).
Otherwise we should be able to use the standard linux device
model to probe clk providers. It looks like the clocksource is
using something from CCU, but perhaps CGU isn't "special" and
could be using device model.

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH v2 3/4] clk: add lpc18xx ccu clk driver
  2015-04-27 21:38     ` Joachim Eastwood
  (?)
@ 2015-05-12 22:32         ` Michael Turquette
  -1 siblings, 0 replies; 39+ messages in thread
From: Michael Turquette @ 2015-05-12 22:32 UTC (permalink / raw)
  To: sboyd-sgV2jX0FEOL9JmXXK+q4OQ, arnd-r2nGTMty4D4,
	linux-clk-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
  Cc: devicetree-u79uwXL29TY76Z2rM5mHXA,
	ariel.dalessandro-Re5JQEeQqe8AvxtiuMwx3w,
	ezequiel-30ULvvUtt6G51wMPkGsGjgyUoB5FGQPZ, Joachim Eastwood

Quoting Joachim Eastwood (2015-04-27 14:38:12)
> +static int of_clk_get_parent_arg(struct device_node *np, int index)
> +{
> +       struct of_phandle_args clkspec;
> +       int rc;
> +
> +       if (index < 0)
> +               return -EINVAL;
> +
> +       rc = of_parse_phandle_with_args(np, "clocks", "#clock-cells", index,
> +                                       &clkspec);
> +       if (rc)
> +               return -EINVAL;
> +
> +       return clkspec.args_count ? clkspec.args[0] : -EINVAL;
> +}

Hi Joachim,

I'm not sure why you need this. I guess it is related to my question in
patch #2 about using clock-indices? Can you explain why this function is
required?

Anyways if returning the clock index is something that is really needed
then why not rename it to "of_clk_get_index" and put it in
drivers/clk/clk.c?

Thanks,
Mike
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH v2 3/4] clk: add lpc18xx ccu clk driver
@ 2015-05-12 22:32         ` Michael Turquette
  0 siblings, 0 replies; 39+ messages in thread
From: Michael Turquette @ 2015-05-12 22:32 UTC (permalink / raw)
  To: Joachim Eastwood, sboyd, arnd, linux-clk, linux-arm-kernel
  Cc: devicetree, ariel.dalessandro, ezequiel, Joachim Eastwood

Quoting Joachim Eastwood (2015-04-27 14:38:12)
> +static int of_clk_get_parent_arg(struct device_node *np, int index)
> +{
> +       struct of_phandle_args clkspec;
> +       int rc;
> +
> +       if (index < 0)
> +               return -EINVAL;
> +
> +       rc =3D of_parse_phandle_with_args(np, "clocks", "#clock-cells", i=
ndex,
> +                                       &clkspec);
> +       if (rc)
> +               return -EINVAL;
> +
> +       return clkspec.args_count ? clkspec.args[0] : -EINVAL;
> +}

Hi Joachim,

I'm not sure why you need this. I guess it is related to my question in
patch #2 about using clock-indices? Can you explain why this function is
required?

Anyways if returning the clock index is something that is really needed
then why not rename it to "of_clk_get_index" and put it in
drivers/clk/clk.c?

Thanks,
Mike

^ permalink raw reply	[flat|nested] 39+ messages in thread

* [PATCH v2 3/4] clk: add lpc18xx ccu clk driver
@ 2015-05-12 22:32         ` Michael Turquette
  0 siblings, 0 replies; 39+ messages in thread
From: Michael Turquette @ 2015-05-12 22:32 UTC (permalink / raw)
  To: linux-arm-kernel

Quoting Joachim Eastwood (2015-04-27 14:38:12)
> +static int of_clk_get_parent_arg(struct device_node *np, int index)
> +{
> +       struct of_phandle_args clkspec;
> +       int rc;
> +
> +       if (index < 0)
> +               return -EINVAL;
> +
> +       rc = of_parse_phandle_with_args(np, "clocks", "#clock-cells", index,
> +                                       &clkspec);
> +       if (rc)
> +               return -EINVAL;
> +
> +       return clkspec.args_count ? clkspec.args[0] : -EINVAL;
> +}

Hi Joachim,

I'm not sure why you need this. I guess it is related to my question in
patch #2 about using clock-indices? Can you explain why this function is
required?

Anyways if returning the clock index is something that is really needed
then why not rename it to "of_clk_get_index" and put it in
drivers/clk/clk.c?

Thanks,
Mike

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH v2 0/4] Clk drivers for NXP LPC18xx family
  2015-05-12 22:31     ` Stephen Boyd
  (?)
@ 2015-05-13  6:56         ` Joachim Eastwood
  -1 siblings, 0 replies; 39+ messages in thread
From: Joachim Eastwood @ 2015-05-13  6:56 UTC (permalink / raw)
  To: Stephen Boyd
  Cc: Mike Turquette, Arnd Bergmann, linux-clk-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	devicetree-u79uwXL29TY76Z2rM5mHXA, Ariel D'Alessandro,
	Ezequiel Garcia

On 13 May 2015 at 00:31, Stephen Boyd <sboyd-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org> wrote:
> On 04/27, Joachim Eastwood wrote:
>> This patch set adds support for the two main clock peripherals in the
>> LPC18xx/43xx MCU family.
>>
>> The Clock Generation Unit (CGU) is the base source of all clocks. It has
>> five external inputs and contains PLLs, dividers and muxes. The outputs
>> from the CGU are then routed to a Clock Control Unit (CCU) and a few
>> peripherals directly. There are two CCUs in the MCU. The CCU is a
>> collection of gates and a few dividers that sits between the CGU and
>> most of the peripherals.
>>
>> Which clocks that are available depends on the specific device and it's
>> peripherals. It's possible in DT to setup the routing between the CGU
>> and the CCUs.
>
> Is there any reason why this uses CLK_OF_DECLARE over the
> platform device model? Typically we have CLK_OF_DECLARE for cases
> where a provider needs to be up and running early during boot for
> hardware that can't probe defer (i.e. timers, irq controllers).

One of the CCUs provided clock for two of the timers that are used as
clock sources.
Specifically this timer:
http://marc.info/?l=linux-arm-kernel&m=143138193704763&w=2

Since the CGU provides the clock to the CCU which then again provides
the clock to the timer both must use CLK_OF_DECLARE for clk enable/get
rate to work in the timer driver.

> Otherwise we should be able to use the standard linux device
> model to probe clk providers. It looks like the clocksource is
> using something from CCU, but perhaps CGU isn't "special" and
> could be using device model.

It's is the CCU that uses the clocks from the CGU. So I think both
drivers needs to use CLK_OF_DECLARE.

regards,
Joachim Eastwood
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH v2 0/4] Clk drivers for NXP LPC18xx family
@ 2015-05-13  6:56         ` Joachim Eastwood
  0 siblings, 0 replies; 39+ messages in thread
From: Joachim Eastwood @ 2015-05-13  6:56 UTC (permalink / raw)
  To: Stephen Boyd
  Cc: Mike Turquette, Arnd Bergmann, linux-clk, linux-arm-kernel,
	devicetree, Ariel D'Alessandro, Ezequiel Garcia

On 13 May 2015 at 00:31, Stephen Boyd <sboyd@codeaurora.org> wrote:
> On 04/27, Joachim Eastwood wrote:
>> This patch set adds support for the two main clock peripherals in the
>> LPC18xx/43xx MCU family.
>>
>> The Clock Generation Unit (CGU) is the base source of all clocks. It has
>> five external inputs and contains PLLs, dividers and muxes. The outputs
>> from the CGU are then routed to a Clock Control Unit (CCU) and a few
>> peripherals directly. There are two CCUs in the MCU. The CCU is a
>> collection of gates and a few dividers that sits between the CGU and
>> most of the peripherals.
>>
>> Which clocks that are available depends on the specific device and it's
>> peripherals. It's possible in DT to setup the routing between the CGU
>> and the CCUs.
>
> Is there any reason why this uses CLK_OF_DECLARE over the
> platform device model? Typically we have CLK_OF_DECLARE for cases
> where a provider needs to be up and running early during boot for
> hardware that can't probe defer (i.e. timers, irq controllers).

One of the CCUs provided clock for two of the timers that are used as
clock sources.
Specifically this timer:
http://marc.info/?l=linux-arm-kernel&m=143138193704763&w=2

Since the CGU provides the clock to the CCU which then again provides
the clock to the timer both must use CLK_OF_DECLARE for clk enable/get
rate to work in the timer driver.

> Otherwise we should be able to use the standard linux device
> model to probe clk providers. It looks like the clocksource is
> using something from CCU, but perhaps CGU isn't "special" and
> could be using device model.

It's is the CCU that uses the clocks from the CGU. So I think both
drivers needs to use CLK_OF_DECLARE.

regards,
Joachim Eastwood

^ permalink raw reply	[flat|nested] 39+ messages in thread

* [PATCH v2 0/4] Clk drivers for NXP LPC18xx family
@ 2015-05-13  6:56         ` Joachim Eastwood
  0 siblings, 0 replies; 39+ messages in thread
From: Joachim Eastwood @ 2015-05-13  6:56 UTC (permalink / raw)
  To: linux-arm-kernel

On 13 May 2015 at 00:31, Stephen Boyd <sboyd@codeaurora.org> wrote:
> On 04/27, Joachim Eastwood wrote:
>> This patch set adds support for the two main clock peripherals in the
>> LPC18xx/43xx MCU family.
>>
>> The Clock Generation Unit (CGU) is the base source of all clocks. It has
>> five external inputs and contains PLLs, dividers and muxes. The outputs
>> from the CGU are then routed to a Clock Control Unit (CCU) and a few
>> peripherals directly. There are two CCUs in the MCU. The CCU is a
>> collection of gates and a few dividers that sits between the CGU and
>> most of the peripherals.
>>
>> Which clocks that are available depends on the specific device and it's
>> peripherals. It's possible in DT to setup the routing between the CGU
>> and the CCUs.
>
> Is there any reason why this uses CLK_OF_DECLARE over the
> platform device model? Typically we have CLK_OF_DECLARE for cases
> where a provider needs to be up and running early during boot for
> hardware that can't probe defer (i.e. timers, irq controllers).

One of the CCUs provided clock for two of the timers that are used as
clock sources.
Specifically this timer:
http://marc.info/?l=linux-arm-kernel&m=143138193704763&w=2

Since the CGU provides the clock to the CCU which then again provides
the clock to the timer both must use CLK_OF_DECLARE for clk enable/get
rate to work in the timer driver.

> Otherwise we should be able to use the standard linux device
> model to probe clk providers. It looks like the clocksource is
> using something from CCU, but perhaps CGU isn't "special" and
> could be using device model.

It's is the CCU that uses the clocks from the CGU. So I think both
drivers needs to use CLK_OF_DECLARE.

regards,
Joachim Eastwood

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH v2 2/4] doc: dt: add documentation for lpc1850-cgu clk driver
  2015-05-12 22:12         ` Michael Turquette
  (?)
@ 2015-05-13  7:57           ` Joachim Eastwood
  -1 siblings, 0 replies; 39+ messages in thread
From: Joachim Eastwood @ 2015-05-13  7:57 UTC (permalink / raw)
  To: Michael Turquette
  Cc: Stephen Boyd, Arnd Bergmann, linux-clk-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	devicetree-u79uwXL29TY76Z2rM5mHXA, Ariel D'Alessandro,
	Ezequiel Garcia

On 13 May 2015 at 00:12, Michael Turquette <mturquette-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org> wrote:
> Quoting Joachim Eastwood (2015-04-27 14:38:11)
>> Add DT binding documentation for lpc1850-cgu driver.
>>
>> Signed-off-by: Joachim Eastwood <manabian-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
>> ---
>>  .../devicetree/bindings/clock/lpc1850-cgu.txt      | 138 +++++++++++++++++++++
>>  1 file changed, 138 insertions(+)
>>  create mode 100644 Documentation/devicetree/bindings/clock/lpc1850-cgu.txt
>>
>> diff --git a/Documentation/devicetree/bindings/clock/lpc1850-cgu.txt b/Documentation/devicetree/bindings/clock/lpc1850-cgu.txt
>> new file mode 100644
>> index 000000000000..0b278ca6aee7
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/clock/lpc1850-cgu.txt
>> @@ -0,0 +1,138 @@
>> +* NXP LPC1850 Clock Generation Unit (CGU)
>> +
>> +The CGU generates multiple independent clocks for the core and the
>> +peripheral blocks of the LPC18xx. Each independent clock is called
>> +a base clock and itself is one of the inputs to the two Clock
>> +Control Units (CCUs) which control the branch clocks to the
>> +individual peripherals.
>> +
>> +The CGU selects the inputs to the clock generators from multiple
>> +clock sources, controls the clock generation, and routes the outputs
>> +of the clock generators through the clock source bus to the output
>> +stages. Each output stage provides an independent clock source and
>> +corresponds to one of the base clocks for the LPC18xx.
>> +
>> + - Above text taken from NXP LPC1850 User Manual.
>> +
>> +
>> +This binding uses the common clock binding:
>> +    Documentation/devicetree/bindings/clock/clock-bindings.txt
>> +
>> +Required properties:
>> +- compatible:
>> +       Should be "nxp,lpc1850-cgu"
>> +- reg:
>> +       Shall define the base and range of the address space
>> +       containing clock control registers
>> +- #clock-cells:
>> +       Shall have value <1>.  The permitted clock-specifier values
>> +       are the base clock numbers defined below.
>> +- clocks:
>> +       Shall contain a list of phandles for the external input
>> +       sources to the CGU. The list shall be in the following
>> +       order: xtal, 32khz, enet_rx_clk, enet_tx_clk, gp_clkin.
>> +- clock-indices:
>> +       Shall be an ordered list of numbers defining the base clock
>> +       number provided by the CGU.
>> +- clock-output-names:
>> +       Shall be an ordered list of strings defining the names of
>> +       the clocks provided by the CGU.
>> +
>> +Which base clocks that are available on the CGU depends on the
>> +specific LPC part. Base cloks are numbered from 0 to 27.
>
> s/cloks/clocks/
>
>> +
>> +Number:                Name:                   Description:
>> + 0             BASE_SAFE_CLK           Base safe clock (always on) for WWDT
>> + 1             BASE_USB0_CLK           Base clock for USB0
>> + 2             BASE_PERIPH_CLK         Base clock for Cortex-M0SUB subsystem,
>> +                                       SPI, and SGPIO
>> + 3             BASE_USB1_CLK           Base clock for USB1
>> + 4             BASE_CPU_CLK            System base clock for ARM Cortex-M core
>> +                                       and APB peripheral blocks #0 and #2
>> + 5             BASE_SPIFI_CLK          Base clock for SPIFI
>> + 6             BASE_SPI_CLK            Base clock for SPI
>> + 7             BASE_PHY_RX_CLK         Base clock for Ethernet PHY Receive clock
>> + 8             BASE_PHY_TX_CLK         Base clock for Ethernet PHY Transmit clock
>> + 9             BASE_APB1_CLK           Base clock for APB peripheral block # 1
>> +10             BASE_APB3_CLK           Base clock for APB peripheral block # 3
>> +11             BASE_LCD_CLK            Base clock for LCD
>> +12             BASE_ADCHS_CLK          Base clock for ADCHS
>> +13             BASE_SDIO_CLK           Base clock for SD/MMC
>> +14             BASE_SSP0_CLK           Base clock for SSP0
>> +15             BASE_SSP1_CLK           Base clock for SSP1
>> +16             BASE_UART0_CLK          Base clock for UART0
>> +17             BASE_UART1_CLK          Base clock for UART1
>> +18             BASE_UART2_CLK          Base clock for UART2
>> +19             BASE_UART3_CLK          Base clock for UART3
>> +20             BASE_OUT_CLK            Base clock for CLKOUT pin
>> +24-21          -                       Reserved
>> +25             BASE_AUDIO_CLK          Base clock for audio system (I2S)
>> +26             BASE_CGU_OUT0_CLK       Base clock for CGU_OUT0 clock output
>> +27             BASE_CGU_OUT1_CLK       Base clock for CGU_OUT1 clock output
>> +
>> +BASE_PERIPH_CLK and BASE_SPI_CLK is only available on LPC43xx.
>> +BASE_ADCHS_CLK is only available on LPC4370.
>> +
>> +
>> +Example board file:
>> +
>> +/ {
>> +       clocks {
>> +               xtal: xtal {
>> +                       compatible = "fixed-clock";
>> +                       #clock-cells = <0>;
>> +                       clock-frequency = <12000000>;
>> +               };
>> +
>> +               xtal32: xtal32 {
>> +                       compatible = "fixed-clock";
>> +                       #clock-cells = <0>;
>> +                       clock-frequency = <32768>;
>> +               };
>> +
>> +               enet_rx_clk: enet_rx_clk {
>> +                       compatible = "fixed-clock";
>> +                       #clock-cells = <0>;
>> +                       clock-frequency = <0>;
>> +                       clock-output-names = "enet_rx_clk";
>> +               };
>> +
>> +               enet_tx_clk: enet_tx_clk {
>> +                       compatible = "fixed-clock";
>> +                       #clock-cells = <0>;
>> +                       clock-frequency = <0>;
>> +                       clock-output-names = "enet_tx_clk";
>> +               };
>> +
>> +               gp_clkin: gp_clkin {
>> +                       compatible = "fixed-clock";
>> +                       #clock-cells = <0>;
>> +                       clock-frequency = <0>;
>> +                       clock-output-names = "gp_clkin";
>> +               };
>> +       };
>> +
>> +       soc {
>> +               cgu: cgu@40050000 {
>> +                       compatible = "nxp,lpc1850-cgu";
>> +                       reg = <0x40050000 0x1000>;
>> +                       #clock-cells = <1>;
>> +                       clocks = <&xtal>, <&creg_clk 1>, <&enet_rx_clk>, <&enet_tx_clk>, <&gp_clkin>;
>> +                       clock-indices =  <0>,  <1>,  <2>,  <3>,  <4>,  <5>,  <6>,  <7>,
>> +                                        <8>,  <9>, <10>, <11>, <12>, <13>, <14>, <15>,
>> +                                       <16>, <17>, <18>, <19>, <20>, <25>, <26>, <27>;
>> +                       clock-output-names = "base_safe_clk",    "base_usb0_clk",
>> +                                            "base_periph_clk",  "base_usb1_clk",
>> +                                            "base_cpu_clk",     "base_spifi_clk",
>> +                                            "base_spi_clk",     "base_phy_rx_clk",
>> +                                            "base_phy_tx_clk",  "base_apb1_clk",
>> +                                            "base_apb3_clk",    "base_lcd_clk",
>> +                                            "base_adchs_clk",   "base_sdio_clk",
>> +                                            "base_ssp0_clk",    "base_ssp1_clk",
>> +                                            "base_uart0_clk",   "base_uart1_clk",
>> +                                            "base_uart2_clk",   "base_uart3_clk",
>> +                                            "base_out_clk",     "base_audio_clk",
>> +                                            "base_cgu_out0_clk","base_cgu_out1_clk";
>
> Why do you need to use clock-indices?

Since the CGU can have up to 27 clock lines, but in this device not
all are used. So I use clock-indices so I don't need to have empty
entries in the clock-output-names array. I thought this was the
intended usage(?)

> Why do you need to use clock-output-names? If all of your clock
> consumers have nodes in DT then you can skip this and name them on the
> consuming side. See a further explanation here:
> http://lkml.kernel.org/r/<20150416192014.19585.9663@quantum>

Most of the clocks from the CGU goes to a CCU, but the CCU isn't the
real consumer. It's more like a clock router with a bunch of gates.

If you take a close look at the CCU driver you will notice that it
doesn't do clk_get on any of the clocks. My reason for doing this is
to not increase the usage counter on the CGU clock so that if there
are no consumer after a CCU the entire clock line up to the CGU can be
disabled. So this is the reason that the CCU driver uses a "special"
way to grab the clock output names from the CGU.

Hope this makes sense.

> Also note that providing a clock consumer node in the examples section
> of the binding is helpful when reviewing.

I'll add a consumer example in the next version.

regards,
Joachim Eastwood
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH v2 2/4] doc: dt: add documentation for lpc1850-cgu clk driver
@ 2015-05-13  7:57           ` Joachim Eastwood
  0 siblings, 0 replies; 39+ messages in thread
From: Joachim Eastwood @ 2015-05-13  7:57 UTC (permalink / raw)
  To: Michael Turquette
  Cc: Stephen Boyd, Arnd Bergmann, linux-clk, linux-arm-kernel,
	devicetree, Ariel D'Alessandro, Ezequiel Garcia

On 13 May 2015 at 00:12, Michael Turquette <mturquette@linaro.org> wrote:
> Quoting Joachim Eastwood (2015-04-27 14:38:11)
>> Add DT binding documentation for lpc1850-cgu driver.
>>
>> Signed-off-by: Joachim Eastwood <manabian@gmail.com>
>> ---
>>  .../devicetree/bindings/clock/lpc1850-cgu.txt      | 138 +++++++++++++++++++++
>>  1 file changed, 138 insertions(+)
>>  create mode 100644 Documentation/devicetree/bindings/clock/lpc1850-cgu.txt
>>
>> diff --git a/Documentation/devicetree/bindings/clock/lpc1850-cgu.txt b/Documentation/devicetree/bindings/clock/lpc1850-cgu.txt
>> new file mode 100644
>> index 000000000000..0b278ca6aee7
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/clock/lpc1850-cgu.txt
>> @@ -0,0 +1,138 @@
>> +* NXP LPC1850 Clock Generation Unit (CGU)
>> +
>> +The CGU generates multiple independent clocks for the core and the
>> +peripheral blocks of the LPC18xx. Each independent clock is called
>> +a base clock and itself is one of the inputs to the two Clock
>> +Control Units (CCUs) which control the branch clocks to the
>> +individual peripherals.
>> +
>> +The CGU selects the inputs to the clock generators from multiple
>> +clock sources, controls the clock generation, and routes the outputs
>> +of the clock generators through the clock source bus to the output
>> +stages. Each output stage provides an independent clock source and
>> +corresponds to one of the base clocks for the LPC18xx.
>> +
>> + - Above text taken from NXP LPC1850 User Manual.
>> +
>> +
>> +This binding uses the common clock binding:
>> +    Documentation/devicetree/bindings/clock/clock-bindings.txt
>> +
>> +Required properties:
>> +- compatible:
>> +       Should be "nxp,lpc1850-cgu"
>> +- reg:
>> +       Shall define the base and range of the address space
>> +       containing clock control registers
>> +- #clock-cells:
>> +       Shall have value <1>.  The permitted clock-specifier values
>> +       are the base clock numbers defined below.
>> +- clocks:
>> +       Shall contain a list of phandles for the external input
>> +       sources to the CGU. The list shall be in the following
>> +       order: xtal, 32khz, enet_rx_clk, enet_tx_clk, gp_clkin.
>> +- clock-indices:
>> +       Shall be an ordered list of numbers defining the base clock
>> +       number provided by the CGU.
>> +- clock-output-names:
>> +       Shall be an ordered list of strings defining the names of
>> +       the clocks provided by the CGU.
>> +
>> +Which base clocks that are available on the CGU depends on the
>> +specific LPC part. Base cloks are numbered from 0 to 27.
>
> s/cloks/clocks/
>
>> +
>> +Number:                Name:                   Description:
>> + 0             BASE_SAFE_CLK           Base safe clock (always on) for WWDT
>> + 1             BASE_USB0_CLK           Base clock for USB0
>> + 2             BASE_PERIPH_CLK         Base clock for Cortex-M0SUB subsystem,
>> +                                       SPI, and SGPIO
>> + 3             BASE_USB1_CLK           Base clock for USB1
>> + 4             BASE_CPU_CLK            System base clock for ARM Cortex-M core
>> +                                       and APB peripheral blocks #0 and #2
>> + 5             BASE_SPIFI_CLK          Base clock for SPIFI
>> + 6             BASE_SPI_CLK            Base clock for SPI
>> + 7             BASE_PHY_RX_CLK         Base clock for Ethernet PHY Receive clock
>> + 8             BASE_PHY_TX_CLK         Base clock for Ethernet PHY Transmit clock
>> + 9             BASE_APB1_CLK           Base clock for APB peripheral block # 1
>> +10             BASE_APB3_CLK           Base clock for APB peripheral block # 3
>> +11             BASE_LCD_CLK            Base clock for LCD
>> +12             BASE_ADCHS_CLK          Base clock for ADCHS
>> +13             BASE_SDIO_CLK           Base clock for SD/MMC
>> +14             BASE_SSP0_CLK           Base clock for SSP0
>> +15             BASE_SSP1_CLK           Base clock for SSP1
>> +16             BASE_UART0_CLK          Base clock for UART0
>> +17             BASE_UART1_CLK          Base clock for UART1
>> +18             BASE_UART2_CLK          Base clock for UART2
>> +19             BASE_UART3_CLK          Base clock for UART3
>> +20             BASE_OUT_CLK            Base clock for CLKOUT pin
>> +24-21          -                       Reserved
>> +25             BASE_AUDIO_CLK          Base clock for audio system (I2S)
>> +26             BASE_CGU_OUT0_CLK       Base clock for CGU_OUT0 clock output
>> +27             BASE_CGU_OUT1_CLK       Base clock for CGU_OUT1 clock output
>> +
>> +BASE_PERIPH_CLK and BASE_SPI_CLK is only available on LPC43xx.
>> +BASE_ADCHS_CLK is only available on LPC4370.
>> +
>> +
>> +Example board file:
>> +
>> +/ {
>> +       clocks {
>> +               xtal: xtal {
>> +                       compatible = "fixed-clock";
>> +                       #clock-cells = <0>;
>> +                       clock-frequency = <12000000>;
>> +               };
>> +
>> +               xtal32: xtal32 {
>> +                       compatible = "fixed-clock";
>> +                       #clock-cells = <0>;
>> +                       clock-frequency = <32768>;
>> +               };
>> +
>> +               enet_rx_clk: enet_rx_clk {
>> +                       compatible = "fixed-clock";
>> +                       #clock-cells = <0>;
>> +                       clock-frequency = <0>;
>> +                       clock-output-names = "enet_rx_clk";
>> +               };
>> +
>> +               enet_tx_clk: enet_tx_clk {
>> +                       compatible = "fixed-clock";
>> +                       #clock-cells = <0>;
>> +                       clock-frequency = <0>;
>> +                       clock-output-names = "enet_tx_clk";
>> +               };
>> +
>> +               gp_clkin: gp_clkin {
>> +                       compatible = "fixed-clock";
>> +                       #clock-cells = <0>;
>> +                       clock-frequency = <0>;
>> +                       clock-output-names = "gp_clkin";
>> +               };
>> +       };
>> +
>> +       soc {
>> +               cgu: cgu@40050000 {
>> +                       compatible = "nxp,lpc1850-cgu";
>> +                       reg = <0x40050000 0x1000>;
>> +                       #clock-cells = <1>;
>> +                       clocks = <&xtal>, <&creg_clk 1>, <&enet_rx_clk>, <&enet_tx_clk>, <&gp_clkin>;
>> +                       clock-indices =  <0>,  <1>,  <2>,  <3>,  <4>,  <5>,  <6>,  <7>,
>> +                                        <8>,  <9>, <10>, <11>, <12>, <13>, <14>, <15>,
>> +                                       <16>, <17>, <18>, <19>, <20>, <25>, <26>, <27>;
>> +                       clock-output-names = "base_safe_clk",    "base_usb0_clk",
>> +                                            "base_periph_clk",  "base_usb1_clk",
>> +                                            "base_cpu_clk",     "base_spifi_clk",
>> +                                            "base_spi_clk",     "base_phy_rx_clk",
>> +                                            "base_phy_tx_clk",  "base_apb1_clk",
>> +                                            "base_apb3_clk",    "base_lcd_clk",
>> +                                            "base_adchs_clk",   "base_sdio_clk",
>> +                                            "base_ssp0_clk",    "base_ssp1_clk",
>> +                                            "base_uart0_clk",   "base_uart1_clk",
>> +                                            "base_uart2_clk",   "base_uart3_clk",
>> +                                            "base_out_clk",     "base_audio_clk",
>> +                                            "base_cgu_out0_clk","base_cgu_out1_clk";
>
> Why do you need to use clock-indices?

Since the CGU can have up to 27 clock lines, but in this device not
all are used. So I use clock-indices so I don't need to have empty
entries in the clock-output-names array. I thought this was the
intended usage(?)

> Why do you need to use clock-output-names? If all of your clock
> consumers have nodes in DT then you can skip this and name them on the
> consuming side. See a further explanation here:
> http://lkml.kernel.org/r/<20150416192014.19585.9663@quantum>

Most of the clocks from the CGU goes to a CCU, but the CCU isn't the
real consumer. It's more like a clock router with a bunch of gates.

If you take a close look at the CCU driver you will notice that it
doesn't do clk_get on any of the clocks. My reason for doing this is
to not increase the usage counter on the CGU clock so that if there
are no consumer after a CCU the entire clock line up to the CGU can be
disabled. So this is the reason that the CCU driver uses a "special"
way to grab the clock output names from the CGU.

Hope this makes sense.

> Also note that providing a clock consumer node in the examples section
> of the binding is helpful when reviewing.

I'll add a consumer example in the next version.

regards,
Joachim Eastwood

^ permalink raw reply	[flat|nested] 39+ messages in thread

* [PATCH v2 2/4] doc: dt: add documentation for lpc1850-cgu clk driver
@ 2015-05-13  7:57           ` Joachim Eastwood
  0 siblings, 0 replies; 39+ messages in thread
From: Joachim Eastwood @ 2015-05-13  7:57 UTC (permalink / raw)
  To: linux-arm-kernel

On 13 May 2015 at 00:12, Michael Turquette <mturquette@linaro.org> wrote:
> Quoting Joachim Eastwood (2015-04-27 14:38:11)
>> Add DT binding documentation for lpc1850-cgu driver.
>>
>> Signed-off-by: Joachim Eastwood <manabian@gmail.com>
>> ---
>>  .../devicetree/bindings/clock/lpc1850-cgu.txt      | 138 +++++++++++++++++++++
>>  1 file changed, 138 insertions(+)
>>  create mode 100644 Documentation/devicetree/bindings/clock/lpc1850-cgu.txt
>>
>> diff --git a/Documentation/devicetree/bindings/clock/lpc1850-cgu.txt b/Documentation/devicetree/bindings/clock/lpc1850-cgu.txt
>> new file mode 100644
>> index 000000000000..0b278ca6aee7
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/clock/lpc1850-cgu.txt
>> @@ -0,0 +1,138 @@
>> +* NXP LPC1850 Clock Generation Unit (CGU)
>> +
>> +The CGU generates multiple independent clocks for the core and the
>> +peripheral blocks of the LPC18xx. Each independent clock is called
>> +a base clock and itself is one of the inputs to the two Clock
>> +Control Units (CCUs) which control the branch clocks to the
>> +individual peripherals.
>> +
>> +The CGU selects the inputs to the clock generators from multiple
>> +clock sources, controls the clock generation, and routes the outputs
>> +of the clock generators through the clock source bus to the output
>> +stages. Each output stage provides an independent clock source and
>> +corresponds to one of the base clocks for the LPC18xx.
>> +
>> + - Above text taken from NXP LPC1850 User Manual.
>> +
>> +
>> +This binding uses the common clock binding:
>> +    Documentation/devicetree/bindings/clock/clock-bindings.txt
>> +
>> +Required properties:
>> +- compatible:
>> +       Should be "nxp,lpc1850-cgu"
>> +- reg:
>> +       Shall define the base and range of the address space
>> +       containing clock control registers
>> +- #clock-cells:
>> +       Shall have value <1>.  The permitted clock-specifier values
>> +       are the base clock numbers defined below.
>> +- clocks:
>> +       Shall contain a list of phandles for the external input
>> +       sources to the CGU. The list shall be in the following
>> +       order: xtal, 32khz, enet_rx_clk, enet_tx_clk, gp_clkin.
>> +- clock-indices:
>> +       Shall be an ordered list of numbers defining the base clock
>> +       number provided by the CGU.
>> +- clock-output-names:
>> +       Shall be an ordered list of strings defining the names of
>> +       the clocks provided by the CGU.
>> +
>> +Which base clocks that are available on the CGU depends on the
>> +specific LPC part. Base cloks are numbered from 0 to 27.
>
> s/cloks/clocks/
>
>> +
>> +Number:                Name:                   Description:
>> + 0             BASE_SAFE_CLK           Base safe clock (always on) for WWDT
>> + 1             BASE_USB0_CLK           Base clock for USB0
>> + 2             BASE_PERIPH_CLK         Base clock for Cortex-M0SUB subsystem,
>> +                                       SPI, and SGPIO
>> + 3             BASE_USB1_CLK           Base clock for USB1
>> + 4             BASE_CPU_CLK            System base clock for ARM Cortex-M core
>> +                                       and APB peripheral blocks #0 and #2
>> + 5             BASE_SPIFI_CLK          Base clock for SPIFI
>> + 6             BASE_SPI_CLK            Base clock for SPI
>> + 7             BASE_PHY_RX_CLK         Base clock for Ethernet PHY Receive clock
>> + 8             BASE_PHY_TX_CLK         Base clock for Ethernet PHY Transmit clock
>> + 9             BASE_APB1_CLK           Base clock for APB peripheral block # 1
>> +10             BASE_APB3_CLK           Base clock for APB peripheral block # 3
>> +11             BASE_LCD_CLK            Base clock for LCD
>> +12             BASE_ADCHS_CLK          Base clock for ADCHS
>> +13             BASE_SDIO_CLK           Base clock for SD/MMC
>> +14             BASE_SSP0_CLK           Base clock for SSP0
>> +15             BASE_SSP1_CLK           Base clock for SSP1
>> +16             BASE_UART0_CLK          Base clock for UART0
>> +17             BASE_UART1_CLK          Base clock for UART1
>> +18             BASE_UART2_CLK          Base clock for UART2
>> +19             BASE_UART3_CLK          Base clock for UART3
>> +20             BASE_OUT_CLK            Base clock for CLKOUT pin
>> +24-21          -                       Reserved
>> +25             BASE_AUDIO_CLK          Base clock for audio system (I2S)
>> +26             BASE_CGU_OUT0_CLK       Base clock for CGU_OUT0 clock output
>> +27             BASE_CGU_OUT1_CLK       Base clock for CGU_OUT1 clock output
>> +
>> +BASE_PERIPH_CLK and BASE_SPI_CLK is only available on LPC43xx.
>> +BASE_ADCHS_CLK is only available on LPC4370.
>> +
>> +
>> +Example board file:
>> +
>> +/ {
>> +       clocks {
>> +               xtal: xtal {
>> +                       compatible = "fixed-clock";
>> +                       #clock-cells = <0>;
>> +                       clock-frequency = <12000000>;
>> +               };
>> +
>> +               xtal32: xtal32 {
>> +                       compatible = "fixed-clock";
>> +                       #clock-cells = <0>;
>> +                       clock-frequency = <32768>;
>> +               };
>> +
>> +               enet_rx_clk: enet_rx_clk {
>> +                       compatible = "fixed-clock";
>> +                       #clock-cells = <0>;
>> +                       clock-frequency = <0>;
>> +                       clock-output-names = "enet_rx_clk";
>> +               };
>> +
>> +               enet_tx_clk: enet_tx_clk {
>> +                       compatible = "fixed-clock";
>> +                       #clock-cells = <0>;
>> +                       clock-frequency = <0>;
>> +                       clock-output-names = "enet_tx_clk";
>> +               };
>> +
>> +               gp_clkin: gp_clkin {
>> +                       compatible = "fixed-clock";
>> +                       #clock-cells = <0>;
>> +                       clock-frequency = <0>;
>> +                       clock-output-names = "gp_clkin";
>> +               };
>> +       };
>> +
>> +       soc {
>> +               cgu: cgu at 40050000 {
>> +                       compatible = "nxp,lpc1850-cgu";
>> +                       reg = <0x40050000 0x1000>;
>> +                       #clock-cells = <1>;
>> +                       clocks = <&xtal>, <&creg_clk 1>, <&enet_rx_clk>, <&enet_tx_clk>, <&gp_clkin>;
>> +                       clock-indices =  <0>,  <1>,  <2>,  <3>,  <4>,  <5>,  <6>,  <7>,
>> +                                        <8>,  <9>, <10>, <11>, <12>, <13>, <14>, <15>,
>> +                                       <16>, <17>, <18>, <19>, <20>, <25>, <26>, <27>;
>> +                       clock-output-names = "base_safe_clk",    "base_usb0_clk",
>> +                                            "base_periph_clk",  "base_usb1_clk",
>> +                                            "base_cpu_clk",     "base_spifi_clk",
>> +                                            "base_spi_clk",     "base_phy_rx_clk",
>> +                                            "base_phy_tx_clk",  "base_apb1_clk",
>> +                                            "base_apb3_clk",    "base_lcd_clk",
>> +                                            "base_adchs_clk",   "base_sdio_clk",
>> +                                            "base_ssp0_clk",    "base_ssp1_clk",
>> +                                            "base_uart0_clk",   "base_uart1_clk",
>> +                                            "base_uart2_clk",   "base_uart3_clk",
>> +                                            "base_out_clk",     "base_audio_clk",
>> +                                            "base_cgu_out0_clk","base_cgu_out1_clk";
>
> Why do you need to use clock-indices?

Since the CGU can have up to 27 clock lines, but in this device not
all are used. So I use clock-indices so I don't need to have empty
entries in the clock-output-names array. I thought this was the
intended usage(?)

> Why do you need to use clock-output-names? If all of your clock
> consumers have nodes in DT then you can skip this and name them on the
> consuming side. See a further explanation here:
> http://lkml.kernel.org/r/<20150416192014.19585.9663@quantum>

Most of the clocks from the CGU goes to a CCU, but the CCU isn't the
real consumer. It's more like a clock router with a bunch of gates.

If you take a close look at the CCU driver you will notice that it
doesn't do clk_get on any of the clocks. My reason for doing this is
to not increase the usage counter on the CGU clock so that if there
are no consumer after a CCU the entire clock line up to the CGU can be
disabled. So this is the reason that the CCU driver uses a "special"
way to grab the clock output names from the CGU.

Hope this makes sense.

> Also note that providing a clock consumer node in the examples section
> of the binding is helpful when reviewing.

I'll add a consumer example in the next version.

regards,
Joachim Eastwood

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH v2 3/4] clk: add lpc18xx ccu clk driver
  2015-05-12 22:32         ` Michael Turquette
  (?)
@ 2015-05-13  8:09           ` Joachim Eastwood
  -1 siblings, 0 replies; 39+ messages in thread
From: Joachim Eastwood @ 2015-05-13  8:09 UTC (permalink / raw)
  To: Michael Turquette
  Cc: Stephen Boyd, Arnd Bergmann, linux-clk-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	devicetree-u79uwXL29TY76Z2rM5mHXA, Ariel D'Alessandro,
	Ezequiel Garcia

On 13 May 2015 at 00:32, Michael Turquette <mturquette-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org> wrote:
> Quoting Joachim Eastwood (2015-04-27 14:38:12)
>> +static int of_clk_get_parent_arg(struct device_node *np, int index)
>> +{
>> +       struct of_phandle_args clkspec;
>> +       int rc;
>> +
>> +       if (index < 0)
>> +               return -EINVAL;
>> +
>> +       rc = of_parse_phandle_with_args(np, "clocks", "#clock-cells", index,
>> +                                       &clkspec);
>> +       if (rc)
>> +               return -EINVAL;
>> +
>> +       return clkspec.args_count ? clkspec.args[0] : -EINVAL;
>> +}
>
> Hi Joachim,
>
> I'm not sure why you need this. I guess it is related to my question in
> patch #2 about using clock-indices?

Yes. I basically need the clock id without grabbing the clock using a
clk_get function. See below.

>Can you explain why this function is required?

Since the CCU doesn't act like a normal clock consumer using clk_get
type functions I use this function to retrieve the CGU clock id. This
drivers is used on two CCUs blocks and I need to match the id with one
in the clk_branches array so that the driver itself can be generic.

> Anyways if returning the clock index is something that is really needed
> then why not rename it to "of_clk_get_index" and put it in
> drivers/clk/clk.c?

Okey, I'll do that in the next version if we agree that the function
is still needed.

regards,
Joachim Eastwood
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH v2 3/4] clk: add lpc18xx ccu clk driver
@ 2015-05-13  8:09           ` Joachim Eastwood
  0 siblings, 0 replies; 39+ messages in thread
From: Joachim Eastwood @ 2015-05-13  8:09 UTC (permalink / raw)
  To: Michael Turquette
  Cc: Stephen Boyd, Arnd Bergmann, linux-clk, linux-arm-kernel,
	devicetree, Ariel D'Alessandro, Ezequiel Garcia

On 13 May 2015 at 00:32, Michael Turquette <mturquette@linaro.org> wrote:
> Quoting Joachim Eastwood (2015-04-27 14:38:12)
>> +static int of_clk_get_parent_arg(struct device_node *np, int index)
>> +{
>> +       struct of_phandle_args clkspec;
>> +       int rc;
>> +
>> +       if (index < 0)
>> +               return -EINVAL;
>> +
>> +       rc = of_parse_phandle_with_args(np, "clocks", "#clock-cells", index,
>> +                                       &clkspec);
>> +       if (rc)
>> +               return -EINVAL;
>> +
>> +       return clkspec.args_count ? clkspec.args[0] : -EINVAL;
>> +}
>
> Hi Joachim,
>
> I'm not sure why you need this. I guess it is related to my question in
> patch #2 about using clock-indices?

Yes. I basically need the clock id without grabbing the clock using a
clk_get function. See below.

>Can you explain why this function is required?

Since the CCU doesn't act like a normal clock consumer using clk_get
type functions I use this function to retrieve the CGU clock id. This
drivers is used on two CCUs blocks and I need to match the id with one
in the clk_branches array so that the driver itself can be generic.

> Anyways if returning the clock index is something that is really needed
> then why not rename it to "of_clk_get_index" and put it in
> drivers/clk/clk.c?

Okey, I'll do that in the next version if we agree that the function
is still needed.

regards,
Joachim Eastwood

^ permalink raw reply	[flat|nested] 39+ messages in thread

* [PATCH v2 3/4] clk: add lpc18xx ccu clk driver
@ 2015-05-13  8:09           ` Joachim Eastwood
  0 siblings, 0 replies; 39+ messages in thread
From: Joachim Eastwood @ 2015-05-13  8:09 UTC (permalink / raw)
  To: linux-arm-kernel

On 13 May 2015 at 00:32, Michael Turquette <mturquette@linaro.org> wrote:
> Quoting Joachim Eastwood (2015-04-27 14:38:12)
>> +static int of_clk_get_parent_arg(struct device_node *np, int index)
>> +{
>> +       struct of_phandle_args clkspec;
>> +       int rc;
>> +
>> +       if (index < 0)
>> +               return -EINVAL;
>> +
>> +       rc = of_parse_phandle_with_args(np, "clocks", "#clock-cells", index,
>> +                                       &clkspec);
>> +       if (rc)
>> +               return -EINVAL;
>> +
>> +       return clkspec.args_count ? clkspec.args[0] : -EINVAL;
>> +}
>
> Hi Joachim,
>
> I'm not sure why you need this. I guess it is related to my question in
> patch #2 about using clock-indices?

Yes. I basically need the clock id without grabbing the clock using a
clk_get function. See below.

>Can you explain why this function is required?

Since the CCU doesn't act like a normal clock consumer using clk_get
type functions I use this function to retrieve the CGU clock id. This
drivers is used on two CCUs blocks and I need to match the id with one
in the clk_branches array so that the driver itself can be generic.

> Anyways if returning the clock index is something that is really needed
> then why not rename it to "of_clk_get_index" and put it in
> drivers/clk/clk.c?

Okey, I'll do that in the next version if we agree that the function
is still needed.

regards,
Joachim Eastwood

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH v2 2/4] doc: dt: add documentation for lpc1850-cgu clk driver
  2015-05-13  7:57           ` Joachim Eastwood
  (?)
@ 2015-05-21 21:17             ` Michael Turquette
  -1 siblings, 0 replies; 39+ messages in thread
From: Michael Turquette @ 2015-05-21 21:17 UTC (permalink / raw)
  To: Joachim Eastwood
  Cc: devicetree, Arnd Bergmann, Stephen Boyd, Ariel D'Alessandro,
	Ezequiel Garcia, linux-clk, linux-arm-kernel

Quoting Joachim Eastwood (2015-05-13 00:57:18)
> On 13 May 2015 at 00:12, Michael Turquette <mturquette@linaro.org> wrote:
> > Quoting Joachim Eastwood (2015-04-27 14:38:11)
> >> Add DT binding documentation for lpc1850-cgu driver.
> >>
> >> Signed-off-by: Joachim Eastwood <manabian@gmail.com>
> >> ---
> >>  .../devicetree/bindings/clock/lpc1850-cgu.txt      | 138 +++++++++++++++++++++
> >>  1 file changed, 138 insertions(+)
> >>  create mode 100644 Documentation/devicetree/bindings/clock/lpc1850-cgu.txt
> >>
> >> diff --git a/Documentation/devicetree/bindings/clock/lpc1850-cgu.txt b/Documentation/devicetree/bindings/clock/lpc1850-cgu.txt
> >> new file mode 100644
> >> index 000000000000..0b278ca6aee7
> >> --- /dev/null
> >> +++ b/Documentation/devicetree/bindings/clock/lpc1850-cgu.txt
> >> @@ -0,0 +1,138 @@
> >> +* NXP LPC1850 Clock Generation Unit (CGU)
> >> +
> >> +The CGU generates multiple independent clocks for the core and the
> >> +peripheral blocks of the LPC18xx. Each independent clock is called
> >> +a base clock and itself is one of the inputs to the two Clock
> >> +Control Units (CCUs) which control the branch clocks to the
> >> +individual peripherals.
> >> +
> >> +The CGU selects the inputs to the clock generators from multiple
> >> +clock sources, controls the clock generation, and routes the outputs
> >> +of the clock generators through the clock source bus to the output
> >> +stages. Each output stage provides an independent clock source and
> >> +corresponds to one of the base clocks for the LPC18xx.
> >> +
> >> + - Above text taken from NXP LPC1850 User Manual.
> >> +
> >> +
> >> +This binding uses the common clock binding:
> >> +    Documentation/devicetree/bindings/clock/clock-bindings.txt
> >> +
> >> +Required properties:
> >> +- compatible:
> >> +       Should be "nxp,lpc1850-cgu"
> >> +- reg:
> >> +       Shall define the base and range of the address space
> >> +       containing clock control registers
> >> +- #clock-cells:
> >> +       Shall have value <1>.  The permitted clock-specifier values
> >> +       are the base clock numbers defined below.
> >> +- clocks:
> >> +       Shall contain a list of phandles for the external input
> >> +       sources to the CGU. The list shall be in the following
> >> +       order: xtal, 32khz, enet_rx_clk, enet_tx_clk, gp_clkin.
> >> +- clock-indices:
> >> +       Shall be an ordered list of numbers defining the base clock
> >> +       number provided by the CGU.
> >> +- clock-output-names:
> >> +       Shall be an ordered list of strings defining the names of
> >> +       the clocks provided by the CGU.
> >> +
> >> +Which base clocks that are available on the CGU depends on the
> >> +specific LPC part. Base cloks are numbered from 0 to 27.
> >
> > s/cloks/clocks/
> >
> >> +
> >> +Number:                Name:                   Description:
> >> + 0             BASE_SAFE_CLK           Base safe clock (always on) for WWDT
> >> + 1             BASE_USB0_CLK           Base clock for USB0
> >> + 2             BASE_PERIPH_CLK         Base clock for Cortex-M0SUB subsystem,
> >> +                                       SPI, and SGPIO
> >> + 3             BASE_USB1_CLK           Base clock for USB1
> >> + 4             BASE_CPU_CLK            System base clock for ARM Cortex-M core
> >> +                                       and APB peripheral blocks #0 and #2
> >> + 5             BASE_SPIFI_CLK          Base clock for SPIFI
> >> + 6             BASE_SPI_CLK            Base clock for SPI
> >> + 7             BASE_PHY_RX_CLK         Base clock for Ethernet PHY Receive clock
> >> + 8             BASE_PHY_TX_CLK         Base clock for Ethernet PHY Transmit clock
> >> + 9             BASE_APB1_CLK           Base clock for APB peripheral block # 1
> >> +10             BASE_APB3_CLK           Base clock for APB peripheral block # 3
> >> +11             BASE_LCD_CLK            Base clock for LCD
> >> +12             BASE_ADCHS_CLK          Base clock for ADCHS
> >> +13             BASE_SDIO_CLK           Base clock for SD/MMC
> >> +14             BASE_SSP0_CLK           Base clock for SSP0
> >> +15             BASE_SSP1_CLK           Base clock for SSP1
> >> +16             BASE_UART0_CLK          Base clock for UART0
> >> +17             BASE_UART1_CLK          Base clock for UART1
> >> +18             BASE_UART2_CLK          Base clock for UART2
> >> +19             BASE_UART3_CLK          Base clock for UART3
> >> +20             BASE_OUT_CLK            Base clock for CLKOUT pin
> >> +24-21          -                       Reserved
> >> +25             BASE_AUDIO_CLK          Base clock for audio system (I2S)
> >> +26             BASE_CGU_OUT0_CLK       Base clock for CGU_OUT0 clock output
> >> +27             BASE_CGU_OUT1_CLK       Base clock for CGU_OUT1 clock output
> >> +
> >> +BASE_PERIPH_CLK and BASE_SPI_CLK is only available on LPC43xx.
> >> +BASE_ADCHS_CLK is only available on LPC4370.
> >> +
> >> +
> >> +Example board file:
> >> +
> >> +/ {
> >> +       clocks {
> >> +               xtal: xtal {
> >> +                       compatible = "fixed-clock";
> >> +                       #clock-cells = <0>;
> >> +                       clock-frequency = <12000000>;
> >> +               };
> >> +
> >> +               xtal32: xtal32 {
> >> +                       compatible = "fixed-clock";
> >> +                       #clock-cells = <0>;
> >> +                       clock-frequency = <32768>;
> >> +               };
> >> +
> >> +               enet_rx_clk: enet_rx_clk {
> >> +                       compatible = "fixed-clock";
> >> +                       #clock-cells = <0>;
> >> +                       clock-frequency = <0>;
> >> +                       clock-output-names = "enet_rx_clk";
> >> +               };
> >> +
> >> +               enet_tx_clk: enet_tx_clk {
> >> +                       compatible = "fixed-clock";
> >> +                       #clock-cells = <0>;
> >> +                       clock-frequency = <0>;
> >> +                       clock-output-names = "enet_tx_clk";
> >> +               };
> >> +
> >> +               gp_clkin: gp_clkin {
> >> +                       compatible = "fixed-clock";
> >> +                       #clock-cells = <0>;
> >> +                       clock-frequency = <0>;
> >> +                       clock-output-names = "gp_clkin";
> >> +               };
> >> +       };
> >> +
> >> +       soc {
> >> +               cgu: cgu@40050000 {
> >> +                       compatible = "nxp,lpc1850-cgu";
> >> +                       reg = <0x40050000 0x1000>;
> >> +                       #clock-cells = <1>;
> >> +                       clocks = <&xtal>, <&creg_clk 1>, <&enet_rx_clk>, <&enet_tx_clk>, <&gp_clkin>;
> >> +                       clock-indices =  <0>,  <1>,  <2>,  <3>,  <4>,  <5>,  <6>,  <7>,
> >> +                                        <8>,  <9>, <10>, <11>, <12>, <13>, <14>, <15>,
> >> +                                       <16>, <17>, <18>, <19>, <20>, <25>, <26>, <27>;
> >> +                       clock-output-names = "base_safe_clk",    "base_usb0_clk",
> >> +                                            "base_periph_clk",  "base_usb1_clk",
> >> +                                            "base_cpu_clk",     "base_spifi_clk",
> >> +                                            "base_spi_clk",     "base_phy_rx_clk",
> >> +                                            "base_phy_tx_clk",  "base_apb1_clk",
> >> +                                            "base_apb3_clk",    "base_lcd_clk",
> >> +                                            "base_adchs_clk",   "base_sdio_clk",
> >> +                                            "base_ssp0_clk",    "base_ssp1_clk",
> >> +                                            "base_uart0_clk",   "base_uart1_clk",
> >> +                                            "base_uart2_clk",   "base_uart3_clk",
> >> +                                            "base_out_clk",     "base_audio_clk",
> >> +                                            "base_cgu_out0_clk","base_cgu_out1_clk";
> >
> > Why do you need to use clock-indices?
> 
> Since the CGU can have up to 27 clock lines, but in this device not
> all are used. So I use clock-indices so I don't need to have empty
> entries in the clock-output-names array. I thought this was the
> intended usage(?)
> 
> > Why do you need to use clock-output-names? If all of your clock
> > consumers have nodes in DT then you can skip this and name them on the
> > consuming side. See a further explanation here:
> > http://lkml.kernel.org/r/<20150416192014.19585.9663@quantum>
> 
> Most of the clocks from the CGU goes to a CCU, but the CCU isn't the
> real consumer. It's more like a clock router with a bunch of gates.
> 
> If you take a close look at the CCU driver you will notice that it
> doesn't do clk_get on any of the clocks. My reason for doing this is
> to not increase the usage counter on the CGU clock so that if there
> are no consumer after a CCU the entire clock line up to the CGU can be
> disabled. So this is the reason that the CCU driver uses a "special"
> way to grab the clock output names from the CGU.

A call to clk_get will not enable/ungate the clock signal. It seems that
there might be some confusion around that. It is always OK to get the
clk. This will not increase the enable_count or prepare_count values.

If the CCU is a separate IP block then it might make sense for it to
call clk_get on the CGU clocks. On the other hand it might make more
sense for the CCU clocks to simply use the CGU clocks as parent clock
signal inputs.

None of the points above have anything to do with my original comment.
The use of the clock-output-names property is unnecessary if all of the
consumer devices have DT nodes of their own. Please look at the thread I
linked to and let me know what you think about getting rid of the
clock-output-names property.

> 
> Hope this makes sense.
> 
> > Also note that providing a clock consumer node in the examples section
> > of the binding is helpful when reviewing.
> 
> I'll add a consumer example in the next version.

Great.

Thanks,
Mike

> 
> regards,
> Joachim Eastwood

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH v2 2/4] doc: dt: add documentation for lpc1850-cgu clk driver
@ 2015-05-21 21:17             ` Michael Turquette
  0 siblings, 0 replies; 39+ messages in thread
From: Michael Turquette @ 2015-05-21 21:17 UTC (permalink / raw)
  To: Joachim Eastwood
  Cc: Stephen Boyd, Arnd Bergmann, linux-clk, linux-arm-kernel,
	devicetree, Ariel D'Alessandro, Ezequiel Garcia

Quoting Joachim Eastwood (2015-05-13 00:57:18)
> On 13 May 2015 at 00:12, Michael Turquette <mturquette@linaro.org> wrote:
> > Quoting Joachim Eastwood (2015-04-27 14:38:11)
> >> Add DT binding documentation for lpc1850-cgu driver.
> >>
> >> Signed-off-by: Joachim Eastwood <manabian@gmail.com>
> >> ---
> >>  .../devicetree/bindings/clock/lpc1850-cgu.txt      | 138 ++++++++++++=
+++++++++
> >>  1 file changed, 138 insertions(+)
> >>  create mode 100644 Documentation/devicetree/bindings/clock/lpc1850-cg=
u.txt
> >>
> >> diff --git a/Documentation/devicetree/bindings/clock/lpc1850-cgu.txt b=
/Documentation/devicetree/bindings/clock/lpc1850-cgu.txt
> >> new file mode 100644
> >> index 000000000000..0b278ca6aee7
> >> --- /dev/null
> >> +++ b/Documentation/devicetree/bindings/clock/lpc1850-cgu.txt
> >> @@ -0,0 +1,138 @@
> >> +* NXP LPC1850 Clock Generation Unit (CGU)
> >> +
> >> +The CGU generates multiple independent clocks for the core and the
> >> +peripheral blocks of the LPC18xx. Each independent clock is called
> >> +a base clock and itself is one of the inputs to the two Clock
> >> +Control Units (CCUs) which control the branch clocks to the
> >> +individual peripherals.
> >> +
> >> +The CGU selects the inputs to the clock generators from multiple
> >> +clock sources, controls the clock generation, and routes the outputs
> >> +of the clock generators through the clock source bus to the output
> >> +stages. Each output stage provides an independent clock source and
> >> +corresponds to one of the base clocks for the LPC18xx.
> >> +
> >> + - Above text taken from NXP LPC1850 User Manual.
> >> +
> >> +
> >> +This binding uses the common clock binding:
> >> +    Documentation/devicetree/bindings/clock/clock-bindings.txt
> >> +
> >> +Required properties:
> >> +- compatible:
> >> +       Should be "nxp,lpc1850-cgu"
> >> +- reg:
> >> +       Shall define the base and range of the address space
> >> +       containing clock control registers
> >> +- #clock-cells:
> >> +       Shall have value <1>.  The permitted clock-specifier values
> >> +       are the base clock numbers defined below.
> >> +- clocks:
> >> +       Shall contain a list of phandles for the external input
> >> +       sources to the CGU. The list shall be in the following
> >> +       order: xtal, 32khz, enet_rx_clk, enet_tx_clk, gp_clkin.
> >> +- clock-indices:
> >> +       Shall be an ordered list of numbers defining the base clock
> >> +       number provided by the CGU.
> >> +- clock-output-names:
> >> +       Shall be an ordered list of strings defining the names of
> >> +       the clocks provided by the CGU.
> >> +
> >> +Which base clocks that are available on the CGU depends on the
> >> +specific LPC part. Base cloks are numbered from 0 to 27.
> >
> > s/cloks/clocks/
> >
> >> +
> >> +Number:                Name:                   Description:
> >> + 0             BASE_SAFE_CLK           Base safe clock (always on) fo=
r WWDT
> >> + 1             BASE_USB0_CLK           Base clock for USB0
> >> + 2             BASE_PERIPH_CLK         Base clock for Cortex-M0SUB su=
bsystem,
> >> +                                       SPI, and SGPIO
> >> + 3             BASE_USB1_CLK           Base clock for USB1
> >> + 4             BASE_CPU_CLK            System base clock for ARM Cort=
ex-M core
> >> +                                       and APB peripheral blocks #0 a=
nd #2
> >> + 5             BASE_SPIFI_CLK          Base clock for SPIFI
> >> + 6             BASE_SPI_CLK            Base clock for SPI
> >> + 7             BASE_PHY_RX_CLK         Base clock for Ethernet PHY Re=
ceive clock
> >> + 8             BASE_PHY_TX_CLK         Base clock for Ethernet PHY Tr=
ansmit clock
> >> + 9             BASE_APB1_CLK           Base clock for APB peripheral =
block # 1
> >> +10             BASE_APB3_CLK           Base clock for APB peripheral =
block # 3
> >> +11             BASE_LCD_CLK            Base clock for LCD
> >> +12             BASE_ADCHS_CLK          Base clock for ADCHS
> >> +13             BASE_SDIO_CLK           Base clock for SD/MMC
> >> +14             BASE_SSP0_CLK           Base clock for SSP0
> >> +15             BASE_SSP1_CLK           Base clock for SSP1
> >> +16             BASE_UART0_CLK          Base clock for UART0
> >> +17             BASE_UART1_CLK          Base clock for UART1
> >> +18             BASE_UART2_CLK          Base clock for UART2
> >> +19             BASE_UART3_CLK          Base clock for UART3
> >> +20             BASE_OUT_CLK            Base clock for CLKOUT pin
> >> +24-21          -                       Reserved
> >> +25             BASE_AUDIO_CLK          Base clock for audio system (I=
2S)
> >> +26             BASE_CGU_OUT0_CLK       Base clock for CGU_OUT0 clock =
output
> >> +27             BASE_CGU_OUT1_CLK       Base clock for CGU_OUT1 clock =
output
> >> +
> >> +BASE_PERIPH_CLK and BASE_SPI_CLK is only available on LPC43xx.
> >> +BASE_ADCHS_CLK is only available on LPC4370.
> >> +
> >> +
> >> +Example board file:
> >> +
> >> +/ {
> >> +       clocks {
> >> +               xtal: xtal {
> >> +                       compatible =3D "fixed-clock";
> >> +                       #clock-cells =3D <0>;
> >> +                       clock-frequency =3D <12000000>;
> >> +               };
> >> +
> >> +               xtal32: xtal32 {
> >> +                       compatible =3D "fixed-clock";
> >> +                       #clock-cells =3D <0>;
> >> +                       clock-frequency =3D <32768>;
> >> +               };
> >> +
> >> +               enet_rx_clk: enet_rx_clk {
> >> +                       compatible =3D "fixed-clock";
> >> +                       #clock-cells =3D <0>;
> >> +                       clock-frequency =3D <0>;
> >> +                       clock-output-names =3D "enet_rx_clk";
> >> +               };
> >> +
> >> +               enet_tx_clk: enet_tx_clk {
> >> +                       compatible =3D "fixed-clock";
> >> +                       #clock-cells =3D <0>;
> >> +                       clock-frequency =3D <0>;
> >> +                       clock-output-names =3D "enet_tx_clk";
> >> +               };
> >> +
> >> +               gp_clkin: gp_clkin {
> >> +                       compatible =3D "fixed-clock";
> >> +                       #clock-cells =3D <0>;
> >> +                       clock-frequency =3D <0>;
> >> +                       clock-output-names =3D "gp_clkin";
> >> +               };
> >> +       };
> >> +
> >> +       soc {
> >> +               cgu: cgu@40050000 {
> >> +                       compatible =3D "nxp,lpc1850-cgu";
> >> +                       reg =3D <0x40050000 0x1000>;
> >> +                       #clock-cells =3D <1>;
> >> +                       clocks =3D <&xtal>, <&creg_clk 1>, <&enet_rx_c=
lk>, <&enet_tx_clk>, <&gp_clkin>;
> >> +                       clock-indices =3D  <0>,  <1>,  <2>,  <3>,  <4>=
,  <5>,  <6>,  <7>,
> >> +                                        <8>,  <9>, <10>, <11>, <12>, =
<13>, <14>, <15>,
> >> +                                       <16>, <17>, <18>, <19>, <20>, =
<25>, <26>, <27>;
> >> +                       clock-output-names =3D "base_safe_clk",    "ba=
se_usb0_clk",
> >> +                                            "base_periph_clk",  "base=
_usb1_clk",
> >> +                                            "base_cpu_clk",     "base=
_spifi_clk",
> >> +                                            "base_spi_clk",     "base=
_phy_rx_clk",
> >> +                                            "base_phy_tx_clk",  "base=
_apb1_clk",
> >> +                                            "base_apb3_clk",    "base=
_lcd_clk",
> >> +                                            "base_adchs_clk",   "base=
_sdio_clk",
> >> +                                            "base_ssp0_clk",    "base=
_ssp1_clk",
> >> +                                            "base_uart0_clk",   "base=
_uart1_clk",
> >> +                                            "base_uart2_clk",   "base=
_uart3_clk",
> >> +                                            "base_out_clk",     "base=
_audio_clk",
> >> +                                            "base_cgu_out0_clk","base=
_cgu_out1_clk";
> >
> > Why do you need to use clock-indices?
> =

> Since the CGU can have up to 27 clock lines, but in this device not
> all are used. So I use clock-indices so I don't need to have empty
> entries in the clock-output-names array. I thought this was the
> intended usage(?)
> =

> > Why do you need to use clock-output-names? If all of your clock
> > consumers have nodes in DT then you can skip this and name them on the
> > consuming side. See a further explanation here:
> > http://lkml.kernel.org/r/<20150416192014.19585.9663@quantum>
> =

> Most of the clocks from the CGU goes to a CCU, but the CCU isn't the
> real consumer. It's more like a clock router with a bunch of gates.
> =

> If you take a close look at the CCU driver you will notice that it
> doesn't do clk_get on any of the clocks. My reason for doing this is
> to not increase the usage counter on the CGU clock so that if there
> are no consumer after a CCU the entire clock line up to the CGU can be
> disabled. So this is the reason that the CCU driver uses a "special"
> way to grab the clock output names from the CGU.

A call to clk_get will not enable/ungate the clock signal. It seems that
there might be some confusion around that. It is always OK to get the
clk. This will not increase the enable_count or prepare_count values.

If the CCU is a separate IP block then it might make sense for it to
call clk_get on the CGU clocks. On the other hand it might make more
sense for the CCU clocks to simply use the CGU clocks as parent clock
signal inputs.

None of the points above have anything to do with my original comment.
The use of the clock-output-names property is unnecessary if all of the
consumer devices have DT nodes of their own. Please look at the thread I
linked to and let me know what you think about getting rid of the
clock-output-names property.

> =

> Hope this makes sense.
> =

> > Also note that providing a clock consumer node in the examples section
> > of the binding is helpful when reviewing.
> =

> I'll add a consumer example in the next version.

Great.

Thanks,
Mike

> =

> regards,
> Joachim Eastwood

^ permalink raw reply	[flat|nested] 39+ messages in thread

* [PATCH v2 2/4] doc: dt: add documentation for lpc1850-cgu clk driver
@ 2015-05-21 21:17             ` Michael Turquette
  0 siblings, 0 replies; 39+ messages in thread
From: Michael Turquette @ 2015-05-21 21:17 UTC (permalink / raw)
  To: linux-arm-kernel

Quoting Joachim Eastwood (2015-05-13 00:57:18)
> On 13 May 2015 at 00:12, Michael Turquette <mturquette@linaro.org> wrote:
> > Quoting Joachim Eastwood (2015-04-27 14:38:11)
> >> Add DT binding documentation for lpc1850-cgu driver.
> >>
> >> Signed-off-by: Joachim Eastwood <manabian@gmail.com>
> >> ---
> >>  .../devicetree/bindings/clock/lpc1850-cgu.txt      | 138 +++++++++++++++++++++
> >>  1 file changed, 138 insertions(+)
> >>  create mode 100644 Documentation/devicetree/bindings/clock/lpc1850-cgu.txt
> >>
> >> diff --git a/Documentation/devicetree/bindings/clock/lpc1850-cgu.txt b/Documentation/devicetree/bindings/clock/lpc1850-cgu.txt
> >> new file mode 100644
> >> index 000000000000..0b278ca6aee7
> >> --- /dev/null
> >> +++ b/Documentation/devicetree/bindings/clock/lpc1850-cgu.txt
> >> @@ -0,0 +1,138 @@
> >> +* NXP LPC1850 Clock Generation Unit (CGU)
> >> +
> >> +The CGU generates multiple independent clocks for the core and the
> >> +peripheral blocks of the LPC18xx. Each independent clock is called
> >> +a base clock and itself is one of the inputs to the two Clock
> >> +Control Units (CCUs) which control the branch clocks to the
> >> +individual peripherals.
> >> +
> >> +The CGU selects the inputs to the clock generators from multiple
> >> +clock sources, controls the clock generation, and routes the outputs
> >> +of the clock generators through the clock source bus to the output
> >> +stages. Each output stage provides an independent clock source and
> >> +corresponds to one of the base clocks for the LPC18xx.
> >> +
> >> + - Above text taken from NXP LPC1850 User Manual.
> >> +
> >> +
> >> +This binding uses the common clock binding:
> >> +    Documentation/devicetree/bindings/clock/clock-bindings.txt
> >> +
> >> +Required properties:
> >> +- compatible:
> >> +       Should be "nxp,lpc1850-cgu"
> >> +- reg:
> >> +       Shall define the base and range of the address space
> >> +       containing clock control registers
> >> +- #clock-cells:
> >> +       Shall have value <1>.  The permitted clock-specifier values
> >> +       are the base clock numbers defined below.
> >> +- clocks:
> >> +       Shall contain a list of phandles for the external input
> >> +       sources to the CGU. The list shall be in the following
> >> +       order: xtal, 32khz, enet_rx_clk, enet_tx_clk, gp_clkin.
> >> +- clock-indices:
> >> +       Shall be an ordered list of numbers defining the base clock
> >> +       number provided by the CGU.
> >> +- clock-output-names:
> >> +       Shall be an ordered list of strings defining the names of
> >> +       the clocks provided by the CGU.
> >> +
> >> +Which base clocks that are available on the CGU depends on the
> >> +specific LPC part. Base cloks are numbered from 0 to 27.
> >
> > s/cloks/clocks/
> >
> >> +
> >> +Number:                Name:                   Description:
> >> + 0             BASE_SAFE_CLK           Base safe clock (always on) for WWDT
> >> + 1             BASE_USB0_CLK           Base clock for USB0
> >> + 2             BASE_PERIPH_CLK         Base clock for Cortex-M0SUB subsystem,
> >> +                                       SPI, and SGPIO
> >> + 3             BASE_USB1_CLK           Base clock for USB1
> >> + 4             BASE_CPU_CLK            System base clock for ARM Cortex-M core
> >> +                                       and APB peripheral blocks #0 and #2
> >> + 5             BASE_SPIFI_CLK          Base clock for SPIFI
> >> + 6             BASE_SPI_CLK            Base clock for SPI
> >> + 7             BASE_PHY_RX_CLK         Base clock for Ethernet PHY Receive clock
> >> + 8             BASE_PHY_TX_CLK         Base clock for Ethernet PHY Transmit clock
> >> + 9             BASE_APB1_CLK           Base clock for APB peripheral block # 1
> >> +10             BASE_APB3_CLK           Base clock for APB peripheral block # 3
> >> +11             BASE_LCD_CLK            Base clock for LCD
> >> +12             BASE_ADCHS_CLK          Base clock for ADCHS
> >> +13             BASE_SDIO_CLK           Base clock for SD/MMC
> >> +14             BASE_SSP0_CLK           Base clock for SSP0
> >> +15             BASE_SSP1_CLK           Base clock for SSP1
> >> +16             BASE_UART0_CLK          Base clock for UART0
> >> +17             BASE_UART1_CLK          Base clock for UART1
> >> +18             BASE_UART2_CLK          Base clock for UART2
> >> +19             BASE_UART3_CLK          Base clock for UART3
> >> +20             BASE_OUT_CLK            Base clock for CLKOUT pin
> >> +24-21          -                       Reserved
> >> +25             BASE_AUDIO_CLK          Base clock for audio system (I2S)
> >> +26             BASE_CGU_OUT0_CLK       Base clock for CGU_OUT0 clock output
> >> +27             BASE_CGU_OUT1_CLK       Base clock for CGU_OUT1 clock output
> >> +
> >> +BASE_PERIPH_CLK and BASE_SPI_CLK is only available on LPC43xx.
> >> +BASE_ADCHS_CLK is only available on LPC4370.
> >> +
> >> +
> >> +Example board file:
> >> +
> >> +/ {
> >> +       clocks {
> >> +               xtal: xtal {
> >> +                       compatible = "fixed-clock";
> >> +                       #clock-cells = <0>;
> >> +                       clock-frequency = <12000000>;
> >> +               };
> >> +
> >> +               xtal32: xtal32 {
> >> +                       compatible = "fixed-clock";
> >> +                       #clock-cells = <0>;
> >> +                       clock-frequency = <32768>;
> >> +               };
> >> +
> >> +               enet_rx_clk: enet_rx_clk {
> >> +                       compatible = "fixed-clock";
> >> +                       #clock-cells = <0>;
> >> +                       clock-frequency = <0>;
> >> +                       clock-output-names = "enet_rx_clk";
> >> +               };
> >> +
> >> +               enet_tx_clk: enet_tx_clk {
> >> +                       compatible = "fixed-clock";
> >> +                       #clock-cells = <0>;
> >> +                       clock-frequency = <0>;
> >> +                       clock-output-names = "enet_tx_clk";
> >> +               };
> >> +
> >> +               gp_clkin: gp_clkin {
> >> +                       compatible = "fixed-clock";
> >> +                       #clock-cells = <0>;
> >> +                       clock-frequency = <0>;
> >> +                       clock-output-names = "gp_clkin";
> >> +               };
> >> +       };
> >> +
> >> +       soc {
> >> +               cgu: cgu at 40050000 {
> >> +                       compatible = "nxp,lpc1850-cgu";
> >> +                       reg = <0x40050000 0x1000>;
> >> +                       #clock-cells = <1>;
> >> +                       clocks = <&xtal>, <&creg_clk 1>, <&enet_rx_clk>, <&enet_tx_clk>, <&gp_clkin>;
> >> +                       clock-indices =  <0>,  <1>,  <2>,  <3>,  <4>,  <5>,  <6>,  <7>,
> >> +                                        <8>,  <9>, <10>, <11>, <12>, <13>, <14>, <15>,
> >> +                                       <16>, <17>, <18>, <19>, <20>, <25>, <26>, <27>;
> >> +                       clock-output-names = "base_safe_clk",    "base_usb0_clk",
> >> +                                            "base_periph_clk",  "base_usb1_clk",
> >> +                                            "base_cpu_clk",     "base_spifi_clk",
> >> +                                            "base_spi_clk",     "base_phy_rx_clk",
> >> +                                            "base_phy_tx_clk",  "base_apb1_clk",
> >> +                                            "base_apb3_clk",    "base_lcd_clk",
> >> +                                            "base_adchs_clk",   "base_sdio_clk",
> >> +                                            "base_ssp0_clk",    "base_ssp1_clk",
> >> +                                            "base_uart0_clk",   "base_uart1_clk",
> >> +                                            "base_uart2_clk",   "base_uart3_clk",
> >> +                                            "base_out_clk",     "base_audio_clk",
> >> +                                            "base_cgu_out0_clk","base_cgu_out1_clk";
> >
> > Why do you need to use clock-indices?
> 
> Since the CGU can have up to 27 clock lines, but in this device not
> all are used. So I use clock-indices so I don't need to have empty
> entries in the clock-output-names array. I thought this was the
> intended usage(?)
> 
> > Why do you need to use clock-output-names? If all of your clock
> > consumers have nodes in DT then you can skip this and name them on the
> > consuming side. See a further explanation here:
> > http://lkml.kernel.org/r/<20150416192014.19585.9663@quantum>
> 
> Most of the clocks from the CGU goes to a CCU, but the CCU isn't the
> real consumer. It's more like a clock router with a bunch of gates.
> 
> If you take a close look at the CCU driver you will notice that it
> doesn't do clk_get on any of the clocks. My reason for doing this is
> to not increase the usage counter on the CGU clock so that if there
> are no consumer after a CCU the entire clock line up to the CGU can be
> disabled. So this is the reason that the CCU driver uses a "special"
> way to grab the clock output names from the CGU.

A call to clk_get will not enable/ungate the clock signal. It seems that
there might be some confusion around that. It is always OK to get the
clk. This will not increase the enable_count or prepare_count values.

If the CCU is a separate IP block then it might make sense for it to
call clk_get on the CGU clocks. On the other hand it might make more
sense for the CCU clocks to simply use the CGU clocks as parent clock
signal inputs.

None of the points above have anything to do with my original comment.
The use of the clock-output-names property is unnecessary if all of the
consumer devices have DT nodes of their own. Please look at the thread I
linked to and let me know what you think about getting rid of the
clock-output-names property.

> 
> Hope this makes sense.
> 
> > Also note that providing a clock consumer node in the examples section
> > of the binding is helpful when reviewing.
> 
> I'll add a consumer example in the next version.

Great.

Thanks,
Mike

> 
> regards,
> Joachim Eastwood

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH v2 2/4] doc: dt: add documentation for lpc1850-cgu clk driver
  2015-05-21 21:17             ` Michael Turquette
  (?)
@ 2015-05-21 22:21               ` Joachim Eastwood
  -1 siblings, 0 replies; 39+ messages in thread
From: Joachim Eastwood @ 2015-05-21 22:21 UTC (permalink / raw)
  To: Michael Turquette
  Cc: Stephen Boyd, Arnd Bergmann, linux-clk-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	devicetree-u79uwXL29TY76Z2rM5mHXA, Ariel D'Alessandro,
	Ezequiel Garcia

On 21 May 2015 at 23:17, Michael Turquette <mturquette-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org> wrote:
> Quoting Joachim Eastwood (2015-05-13 00:57:18)
>> On 13 May 2015 at 00:12, Michael Turquette <mturquette-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org> wrote:
>> >
>> > Why do you need to use clock-indices?
>>
>> Since the CGU can have up to 27 clock lines, but in this device not
>> all are used. So I use clock-indices so I don't need to have empty
>> entries in the clock-output-names array. I thought this was the
>> intended usage(?)
>>
>> > Why do you need to use clock-output-names? If all of your clock
>> > consumers have nodes in DT then you can skip this and name them on the
>> > consuming side. See a further explanation here:
>> > http://lkml.kernel.org/r/<20150416192014.19585.9663@quantum>
>>
>> Most of the clocks from the CGU goes to a CCU, but the CCU isn't the
>> real consumer. It's more like a clock router with a bunch of gates.
>>
>> If you take a close look at the CCU driver you will notice that it
>> doesn't do clk_get on any of the clocks. My reason for doing this is
>> to not increase the usage counter on the CGU clock so that if there
>> are no consumer after a CCU the entire clock line up to the CGU can be
>> disabled. So this is the reason that the CCU driver uses a "special"
>> way to grab the clock output names from the CGU.
>
> A call to clk_get will not enable/ungate the clock signal. It seems that
> there might be some confusion around that. It is always OK to get the
> clk. This will not increase the enable_count or prepare_count values.
>
> If the CCU is a separate IP block then it might make sense for it to
> call clk_get on the CGU clocks. On the other hand it might make more
> sense for the CCU clocks to simply use the CGU clocks as parent clock
> signal inputs.

v3, that was sent a couple of days ago, uses of_clk_get/clk_get_name
to set the CCU clock parents. See v3 cover letter for a short
explanation.

> None of the points above have anything to do with my original comment.
> The use of the clock-output-names property is unnecessary if all of the
> consumer devices have DT nodes of their own. Please look at the thread I
> linked to and let me know what you think about getting rid of the
> clock-output-names property.

v3 removes the property. Please take a look at it when you get the time.


regards,
Joachim Eastwood
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH v2 2/4] doc: dt: add documentation for lpc1850-cgu clk driver
@ 2015-05-21 22:21               ` Joachim Eastwood
  0 siblings, 0 replies; 39+ messages in thread
From: Joachim Eastwood @ 2015-05-21 22:21 UTC (permalink / raw)
  To: Michael Turquette
  Cc: Stephen Boyd, Arnd Bergmann, linux-clk, linux-arm-kernel,
	devicetree, Ariel D'Alessandro, Ezequiel Garcia

On 21 May 2015 at 23:17, Michael Turquette <mturquette@linaro.org> wrote:
> Quoting Joachim Eastwood (2015-05-13 00:57:18)
>> On 13 May 2015 at 00:12, Michael Turquette <mturquette@linaro.org> wrote:
>> >
>> > Why do you need to use clock-indices?
>>
>> Since the CGU can have up to 27 clock lines, but in this device not
>> all are used. So I use clock-indices so I don't need to have empty
>> entries in the clock-output-names array. I thought this was the
>> intended usage(?)
>>
>> > Why do you need to use clock-output-names? If all of your clock
>> > consumers have nodes in DT then you can skip this and name them on the
>> > consuming side. See a further explanation here:
>> > http://lkml.kernel.org/r/<20150416192014.19585.9663@quantum>
>>
>> Most of the clocks from the CGU goes to a CCU, but the CCU isn't the
>> real consumer. It's more like a clock router with a bunch of gates.
>>
>> If you take a close look at the CCU driver you will notice that it
>> doesn't do clk_get on any of the clocks. My reason for doing this is
>> to not increase the usage counter on the CGU clock so that if there
>> are no consumer after a CCU the entire clock line up to the CGU can be
>> disabled. So this is the reason that the CCU driver uses a "special"
>> way to grab the clock output names from the CGU.
>
> A call to clk_get will not enable/ungate the clock signal. It seems that
> there might be some confusion around that. It is always OK to get the
> clk. This will not increase the enable_count or prepare_count values.
>
> If the CCU is a separate IP block then it might make sense for it to
> call clk_get on the CGU clocks. On the other hand it might make more
> sense for the CCU clocks to simply use the CGU clocks as parent clock
> signal inputs.

v3, that was sent a couple of days ago, uses of_clk_get/clk_get_name
to set the CCU clock parents. See v3 cover letter for a short
explanation.

> None of the points above have anything to do with my original comment.
> The use of the clock-output-names property is unnecessary if all of the
> consumer devices have DT nodes of their own. Please look at the thread I
> linked to and let me know what you think about getting rid of the
> clock-output-names property.

v3 removes the property. Please take a look at it when you get the time.


regards,
Joachim Eastwood

^ permalink raw reply	[flat|nested] 39+ messages in thread

* [PATCH v2 2/4] doc: dt: add documentation for lpc1850-cgu clk driver
@ 2015-05-21 22:21               ` Joachim Eastwood
  0 siblings, 0 replies; 39+ messages in thread
From: Joachim Eastwood @ 2015-05-21 22:21 UTC (permalink / raw)
  To: linux-arm-kernel

On 21 May 2015 at 23:17, Michael Turquette <mturquette@linaro.org> wrote:
> Quoting Joachim Eastwood (2015-05-13 00:57:18)
>> On 13 May 2015 at 00:12, Michael Turquette <mturquette@linaro.org> wrote:
>> >
>> > Why do you need to use clock-indices?
>>
>> Since the CGU can have up to 27 clock lines, but in this device not
>> all are used. So I use clock-indices so I don't need to have empty
>> entries in the clock-output-names array. I thought this was the
>> intended usage(?)
>>
>> > Why do you need to use clock-output-names? If all of your clock
>> > consumers have nodes in DT then you can skip this and name them on the
>> > consuming side. See a further explanation here:
>> > http://lkml.kernel.org/r/<20150416192014.19585.9663@quantum>
>>
>> Most of the clocks from the CGU goes to a CCU, but the CCU isn't the
>> real consumer. It's more like a clock router with a bunch of gates.
>>
>> If you take a close look at the CCU driver you will notice that it
>> doesn't do clk_get on any of the clocks. My reason for doing this is
>> to not increase the usage counter on the CGU clock so that if there
>> are no consumer after a CCU the entire clock line up to the CGU can be
>> disabled. So this is the reason that the CCU driver uses a "special"
>> way to grab the clock output names from the CGU.
>
> A call to clk_get will not enable/ungate the clock signal. It seems that
> there might be some confusion around that. It is always OK to get the
> clk. This will not increase the enable_count or prepare_count values.
>
> If the CCU is a separate IP block then it might make sense for it to
> call clk_get on the CGU clocks. On the other hand it might make more
> sense for the CCU clocks to simply use the CGU clocks as parent clock
> signal inputs.

v3, that was sent a couple of days ago, uses of_clk_get/clk_get_name
to set the CCU clock parents. See v3 cover letter for a short
explanation.

> None of the points above have anything to do with my original comment.
> The use of the clock-output-names property is unnecessary if all of the
> consumer devices have DT nodes of their own. Please look at the thread I
> linked to and let me know what you think about getting rid of the
> clock-output-names property.

v3 removes the property. Please take a look at it when you get the time.


regards,
Joachim Eastwood

^ permalink raw reply	[flat|nested] 39+ messages in thread

end of thread, other threads:[~2015-05-21 22:21 UTC | newest]

Thread overview: 39+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-04-27 21:38 [PATCH v2 0/4] Clk drivers for NXP LPC18xx family Joachim Eastwood
2015-04-27 21:38 ` Joachim Eastwood
2015-04-27 21:38 ` Joachim Eastwood
     [not found] ` <1430170693-28303-1-git-send-email-manabian-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
2015-04-27 21:38   ` [PATCH v2 1/4] clk: add lpc18xx cgu clk driver Joachim Eastwood
2015-04-27 21:38     ` Joachim Eastwood
2015-04-27 21:38     ` Joachim Eastwood
2015-04-27 21:38   ` [PATCH v2 2/4] doc: dt: add documentation for lpc1850-cgu " Joachim Eastwood
2015-04-27 21:38     ` Joachim Eastwood
2015-04-27 21:38     ` Joachim Eastwood
     [not found]     ` <1430170693-28303-3-git-send-email-manabian-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
2015-05-12 22:12       ` Michael Turquette
2015-05-12 22:12         ` Michael Turquette
2015-05-12 22:12         ` Michael Turquette
2015-05-13  7:57         ` Joachim Eastwood
2015-05-13  7:57           ` Joachim Eastwood
2015-05-13  7:57           ` Joachim Eastwood
2015-05-21 21:17           ` Michael Turquette
2015-05-21 21:17             ` Michael Turquette
2015-05-21 21:17             ` Michael Turquette
2015-05-21 22:21             ` Joachim Eastwood
2015-05-21 22:21               ` Joachim Eastwood
2015-05-21 22:21               ` Joachim Eastwood
2015-04-27 21:38   ` [PATCH v2 3/4] clk: add lpc18xx ccu " Joachim Eastwood
2015-04-27 21:38     ` Joachim Eastwood
2015-04-27 21:38     ` Joachim Eastwood
     [not found]     ` <1430170693-28303-4-git-send-email-manabian-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
2015-05-12 22:32       ` Michael Turquette
2015-05-12 22:32         ` Michael Turquette
2015-05-12 22:32         ` Michael Turquette
2015-05-13  8:09         ` Joachim Eastwood
2015-05-13  8:09           ` Joachim Eastwood
2015-05-13  8:09           ` Joachim Eastwood
2015-04-27 21:38   ` [PATCH v2 4/4] doc: dt: add documentation for lpc1850-ccu " Joachim Eastwood
2015-04-27 21:38     ` Joachim Eastwood
2015-04-27 21:38     ` Joachim Eastwood
2015-05-12 22:31   ` [PATCH v2 0/4] Clk drivers for NXP LPC18xx family Stephen Boyd
2015-05-12 22:31     ` Stephen Boyd
2015-05-12 22:31     ` Stephen Boyd
     [not found]     ` <20150512223126.GA14873-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
2015-05-13  6:56       ` Joachim Eastwood
2015-05-13  6:56         ` Joachim Eastwood
2015-05-13  6:56         ` Joachim Eastwood

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.