[v3] clk: qoriq: Add support for the FMan clock

2015-04-14 Thread Igal . Liberman
From: Igal Liberman igal.liber...@freescale.com

This patch depends on the following patches:
https://patchwork.ozlabs.org/patch/461151/
https://patchwork.ozlabs.org/patch/461155/

This patche is described by the following binding document update:
https://patchwork.ozlabs.org/patch/461166/

v3: Updated commit message

v2: - Added clock maintainers
- Cached FMan clock parent during initialization
- Register the clock after checking if the hardware exists
- updated error messages

Signed-off-by: Igal Liberman igal.liber...@freescale.com
---
 drivers/clk/clk-qoriq.c |  208 +++
 1 file changed, 208 insertions(+)

diff --git a/drivers/clk/clk-qoriq.c b/drivers/clk/clk-qoriq.c
index cda90a9..d588e90 100644
--- a/drivers/clk/clk-qoriq.c
+++ b/drivers/clk/clk-qoriq.c
@@ -19,6 +19,8 @@
 #include linux/of.h
 #include linux/slab.h
 
+#include asm/fsl_guts.h
+
 struct cmux_clk {
struct clk_hw hw;
void __iomem *reg;
@@ -155,6 +157,211 @@ err_name:
kfree(parent_names);
 }
 
+/* Table for matching compatible strings, for device tree
+ * guts node, for QorIQ SOCs.
+ * fsl,qoriq-device-config-2.0 corresponds to T4  B4
+ * SOCs. For the older SOCs fsl,qoriq-device-config-1.0
+ * string would be used.
+ */
+
+static const struct of_device_id guts_device_ids[] = {
+   { .compatible = fsl,qoriq-device-config-1.0, },
+   { .compatible = fsl,qoriq-device-config-2.0, },
+   {}
+};
+
+/* P2, P3, P4, P5 */
+#define FM1_CLK_SEL_SHIFT  30
+#define FM1_CLK_SELBIT(FM1_CLK_SEL_SHIFT)
+#define FM2_CLK_SEL_SHIFT  29
+#define FM2_CLK_SELBIT(FM2_CLK_SEL_SHIFT)
+#define HWA_ASYNC_DIV_SHIFT26
+#define HWA_ASYNC_DIV  BIT(HWA_ASYNC_DIV_SHIFT)
+
+/* B4, T2 */
+#define HWA_CGA_M1_CLK_SEL_SHIFT   29
+#define HWA_CGA_M1_CLK_SEL (BIT(HWA_CGA_M1_CLK_SEL_SHIFT + 2) |\
+BIT(HWA_CGA_M1_CLK_SEL_SHIFT + 1) |\
+BIT(HWA_CGA_M1_CLK_SEL_SHIFT))
+
+/* T4240 */
+#define HWA_CGB_M1_CLK_SEL_SHIFT   26
+#define HWA_CGB_M1_CLK_SEL (BIT(HWA_CGB_M1_CLK_SEL_SHIFT + 2) |\
+BIT(HWA_CGB_M1_CLK_SEL_SHIFT + 1) |\
+BIT(HWA_CGB_M1_CLK_SEL_SHIFT))
+#define HWA_CGB_M2_CLK_SEL_SHIFT   3
+#define HWA_CGB_M2_CLK_SEL (BIT(HWA_CGB_M2_CLK_SEL_SHIFT + 2) |\
+BIT(HWA_CGB_M2_CLK_SEL_SHIFT + 1) |\
+BIT(HWA_CGB_M2_CLK_SEL_SHIFT))
+
+static u8 get_fm_clk_parent(struct clk_hw *hw)
+{
+   return hw-init-flags;
+}
+
+static const struct clk_ops fm_clk_ops = {
+   .get_parent = get_fm_clk_parent,
+};
+
+static int get_fm_clk_idx(int fm_id, int *fm_clk_idx)
+{
+   struct ccsr_guts __iomem *guts_regs = NULL;
+   struct device_node *guts;
+   uint32_t reg = 0;
+   int clk_src = 0;
+
+   guts = of_find_matching_node(NULL, guts_device_ids);
+   if (!guts) {
+   pr_err(could not find GUTS node\n);
+   return -ENODEV;
+   }
+
+   guts_regs = of_iomap(guts, 0);
+   of_node_put(guts);
+   if (!guts_regs) {
+   pr_err(ioremap of GUTS node failed\n);
+   return -ENODEV;
+   }
+
+   if (of_device_is_compatible(guts, fsl,p1023-guts) ||
+   of_device_is_compatible(guts, fsl,t1040-device-config)) {
+   /* P1023 and T1040 have only one optional clock source */
+   *fm_clk_idx = 0;
+   } else if (of_device_is_compatible(guts, fsl,p2041-device-config) ||
+  of_device_is_compatible(guts, fsl,p3041-device-config) ||
+  of_device_is_compatible(guts, fsl,p4080-device-config)) {
+   /* Read RCW*/
+   reg = ioread32be(guts_regs-rcwsr[7]);
+
+   if (fm_id == 0)
+   *fm_clk_idx = (reg  FM1_CLK_SEL) 
+   FM1_CLK_SEL_SHIFT;
+   else
+   *fm_clk_idx = (reg  FM2_CLK_SEL) 
+   FM2_CLK_SEL_SHIFT;
+   } else if (of_device_is_compatible(guts, fsl,p5020-device-config) ||
+  of_device_is_compatible(guts, fsl,p5040-device-config)) {
+   /* Read RCW */
+   reg = ioread32be(guts_regs-rcwsr[7]);
+
+   if (fm_id == 0)
+   clk_src = (reg  FM1_CLK_SEL)  FM1_CLK_SEL_SHIFT;
+   else
+   clk_src = (reg  FM2_CLK_SEL)  FM2_CLK_SEL_SHIFT;
+
+   if (clk_src == 0) {
+   *fm_clk_idx = 0;
+   } else {
+   clk_src = (reg  HWA_ASYNC_DIV)  HWA_ASYNC_DIV_SHIFT;
+   *fm_clk_idx = clk_src + 1;
+

Re: [v3] clk: qoriq: Add support for the FMan clock

2015-04-14 Thread Scott Wood
On Tue, 2015-04-14 at 14:15 +0300, Igal.Liberman wrote:
 +static int get_fm_clk_idx(int fm_id, int *fm_clk_idx)
 +{
 + struct ccsr_guts __iomem *guts_regs = NULL;
 + struct device_node *guts;
 + uint32_t reg = 0;
 + int clk_src = 0;
 +
 + guts = of_find_matching_node(NULL, guts_device_ids);
 + if (!guts) {
 + pr_err(could not find GUTS node\n);
 + return -ENODEV;
 + }
 +
 + guts_regs = of_iomap(guts, 0);
 + of_node_put(guts);
 + if (!guts_regs) {
 + pr_err(ioremap of GUTS node failed\n);
 + return -ENODEV;
 + }

Error messages should include more context -- at least __func__.

-Scott


___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev