clk: Loongson1: Refactor Loongson1 clock
authorKelvin Cheung <keguang.zhang@gmail.com>
Mon, 19 Sep 2016 04:38:54 +0000 (12:38 +0800)
committerStephen Boyd <sboyd@codeaurora.org>
Fri, 23 Sep 2016 21:48:56 +0000 (14:48 -0700)
Factor out the common functions into loongson1/clk.c
to support both Loongson1B and Loongson1C. And, put
the rest into loongson1/clk-loongson1b.c.

Signed-off-by: Kelvin Cheung <keguang.zhang@gmail.com>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
drivers/clk/Makefile
drivers/clk/clk-ls1x.c [deleted file]
drivers/clk/loongson1/Makefile [new file with mode: 0644]
drivers/clk/loongson1/clk-loongson1b.c [new file with mode: 0644]
drivers/clk/loongson1/clk.c [new file with mode: 0644]
drivers/clk/loongson1/clk.h [new file with mode: 0644]

index 8264d81af5a9d2e73f6386dc3c088b243e5eaa57..925081ec14c04935e1eb17bf2709640c7ae3ae10 100644 (file)
@@ -26,7 +26,6 @@ obj-$(CONFIG_ARCH_CLPS711X)           += clk-clps711x.o
 obj-$(CONFIG_COMMON_CLK_CS2000_CP)     += clk-cs2000-cp.o
 obj-$(CONFIG_ARCH_EFM32)               += clk-efm32gg.o
 obj-$(CONFIG_ARCH_HIGHBANK)            += clk-highbank.o
-obj-$(CONFIG_MACH_LOONGSON32)          += clk-ls1x.o
 obj-$(CONFIG_COMMON_CLK_MAX77686)      += clk-max77686.o
 obj-$(CONFIG_ARCH_MB86S7X)             += clk-mb86s7x.o
 obj-$(CONFIG_ARCH_MOXART)              += clk-moxart.o
@@ -61,6 +60,7 @@ obj-$(CONFIG_ARCH_HISI)                       += hisilicon/
 obj-$(CONFIG_ARCH_MXC)                 += imx/
 obj-$(CONFIG_MACH_INGENIC)             += ingenic/
 obj-$(CONFIG_COMMON_CLK_KEYSTONE)      += keystone/
+obj-$(CONFIG_MACH_LOONGSON32)          += loongson1/
 obj-$(CONFIG_ARCH_MEDIATEK)            += mediatek/
 obj-$(CONFIG_COMMON_CLK_AMLOGIC)       += meson/
 obj-$(CONFIG_MACH_PIC32)               += microchip/
diff --git a/drivers/clk/clk-ls1x.c b/drivers/clk/clk-ls1x.c
deleted file mode 100644 (file)
index 8430e45..0000000
+++ /dev/null
@@ -1,162 +0,0 @@
-/*
- * Copyright (c) 2012 Zhang, Keguang <keguang.zhang@gmail.com>
- *
- * This program is free software; you can redistribute  it and/or modify it
- * under  the terms of  the GNU General  Public License as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
- * option) any later version.
- */
-
-#include <linux/clkdev.h>
-#include <linux/clk-provider.h>
-#include <linux/io.h>
-#include <linux/slab.h>
-#include <linux/err.h>
-
-#include <loongson1.h>
-
-#define OSC            (33 * 1000000)
-#define DIV_APB                2
-
-static DEFINE_SPINLOCK(_lock);
-
-static int ls1x_pll_clk_enable(struct clk_hw *hw)
-{
-       return 0;
-}
-
-static void ls1x_pll_clk_disable(struct clk_hw *hw)
-{
-}
-
-static unsigned long ls1x_pll_recalc_rate(struct clk_hw *hw,
-                                         unsigned long parent_rate)
-{
-       u32 pll, rate;
-
-       pll = __raw_readl(LS1X_CLK_PLL_FREQ);
-       rate = 12 + (pll & 0x3f) + (((pll >> 8) & 0x3ff) >> 10);
-       rate *= OSC;
-       rate >>= 1;
-
-       return rate;
-}
-
-static const struct clk_ops ls1x_pll_clk_ops = {
-       .enable = ls1x_pll_clk_enable,
-       .disable = ls1x_pll_clk_disable,
-       .recalc_rate = ls1x_pll_recalc_rate,
-};
-
-static struct clk_hw *__init clk_hw_register_pll(struct device *dev,
-                                                const char *name,
-                                                const char *parent_name,
-                                                unsigned long flags)
-{
-       int ret;
-       struct clk_hw *hw;
-       struct clk_init_data init;
-
-       /* allocate the divider */
-       hw = kzalloc(sizeof(struct clk_hw), GFP_KERNEL);
-       if (!hw) {
-               pr_err("%s: could not allocate clk_hw\n", __func__);
-               return ERR_PTR(-ENOMEM);
-       }
-
-       init.name = name;
-       init.ops = &ls1x_pll_clk_ops;
-       init.flags = flags | CLK_IS_BASIC;
-       init.parent_names = (parent_name ? &parent_name : NULL);
-       init.num_parents = (parent_name ? 1 : 0);
-       hw->init = &init;
-
-       /* register the clock */
-       ret = clk_hw_register(dev, hw);
-       if (ret) {
-               kfree(hw);
-               hw = ERR_PTR(ret);
-       }
-
-       return hw;
-}
-
-static const char * const cpu_parents[] = { "cpu_clk_div", "osc_33m_clk", };
-static const char * const ahb_parents[] = { "ahb_clk_div", "osc_33m_clk", };
-static const char * const dc_parents[] = { "dc_clk_div", "osc_33m_clk", };
-
-void __init ls1x_clk_init(void)
-{
-       struct clk_hw *hw;
-
-       hw = clk_hw_register_fixed_rate(NULL, "osc_33m_clk", NULL, 0, OSC);
-       clk_hw_register_clkdev(hw, "osc_33m_clk", NULL);
-
-       /* clock derived from 33 MHz OSC clk */
-       hw = clk_hw_register_pll(NULL, "pll_clk", "osc_33m_clk", 0);
-       clk_hw_register_clkdev(hw, "pll_clk", NULL);
-
-       /* clock derived from PLL clk */
-       /*                                 _____
-        *         _______________________|     |
-        * OSC ___/                       | MUX |___ CPU CLK
-        *        \___ PLL ___ CPU DIV ___|     |
-        *                                |_____|
-        */
-       hw = clk_hw_register_divider(NULL, "cpu_clk_div", "pll_clk",
-                                  CLK_GET_RATE_NOCACHE, LS1X_CLK_PLL_DIV,
-                                  DIV_CPU_SHIFT, DIV_CPU_WIDTH,
-                                  CLK_DIVIDER_ONE_BASED |
-                                  CLK_DIVIDER_ROUND_CLOSEST, &_lock);
-       clk_hw_register_clkdev(hw, "cpu_clk_div", NULL);
-       hw = clk_hw_register_mux(NULL, "cpu_clk", cpu_parents,
-                              ARRAY_SIZE(cpu_parents),
-                              CLK_SET_RATE_NO_REPARENT, LS1X_CLK_PLL_DIV,
-                              BYPASS_CPU_SHIFT, BYPASS_CPU_WIDTH, 0, &_lock);
-       clk_hw_register_clkdev(hw, "cpu_clk", NULL);
-
-       /*                                 _____
-        *         _______________________|     |
-        * OSC ___/                       | MUX |___ DC  CLK
-        *        \___ PLL ___ DC  DIV ___|     |
-        *                                |_____|
-        */
-       hw = clk_hw_register_divider(NULL, "dc_clk_div", "pll_clk",
-                                  0, LS1X_CLK_PLL_DIV, DIV_DC_SHIFT,
-                                  DIV_DC_WIDTH, CLK_DIVIDER_ONE_BASED, &_lock);
-       clk_hw_register_clkdev(hw, "dc_clk_div", NULL);
-       hw = clk_hw_register_mux(NULL, "dc_clk", dc_parents,
-                              ARRAY_SIZE(dc_parents),
-                              CLK_SET_RATE_NO_REPARENT, LS1X_CLK_PLL_DIV,
-                              BYPASS_DC_SHIFT, BYPASS_DC_WIDTH, 0, &_lock);
-       clk_hw_register_clkdev(hw, "dc_clk", NULL);
-
-       /*                                 _____
-        *         _______________________|     |
-        * OSC ___/                       | MUX |___ DDR CLK
-        *        \___ PLL ___ DDR DIV ___|     |
-        *                                |_____|
-        */
-       hw = clk_hw_register_divider(NULL, "ahb_clk_div", "pll_clk",
-                                  0, LS1X_CLK_PLL_DIV, DIV_DDR_SHIFT,
-                                  DIV_DDR_WIDTH, CLK_DIVIDER_ONE_BASED,
-                                  &_lock);
-       clk_hw_register_clkdev(hw, "ahb_clk_div", NULL);
-       hw = clk_hw_register_mux(NULL, "ahb_clk", ahb_parents,
-                              ARRAY_SIZE(ahb_parents),
-                              CLK_SET_RATE_NO_REPARENT, LS1X_CLK_PLL_DIV,
-                              BYPASS_DDR_SHIFT, BYPASS_DDR_WIDTH, 0, &_lock);
-       clk_hw_register_clkdev(hw, "ahb_clk", NULL);
-       clk_hw_register_clkdev(hw, "stmmaceth", NULL);
-
-       /* clock derived from AHB clk */
-       /* APB clk is always half of the AHB clk */
-       hw = clk_hw_register_fixed_factor(NULL, "apb_clk", "ahb_clk", 0, 1,
-                                       DIV_APB);
-       clk_hw_register_clkdev(hw, "apb_clk", NULL);
-       clk_hw_register_clkdev(hw, "ls1x_i2c", NULL);
-       clk_hw_register_clkdev(hw, "ls1x_pwmtimer", NULL);
-       clk_hw_register_clkdev(hw, "ls1x_spi", NULL);
-       clk_hw_register_clkdev(hw, "ls1x_wdt", NULL);
-       clk_hw_register_clkdev(hw, "serial8250", NULL);
-}
diff --git a/drivers/clk/loongson1/Makefile b/drivers/clk/loongson1/Makefile
new file mode 100644 (file)
index 0000000..5a162a1
--- /dev/null
@@ -0,0 +1,2 @@
+obj-y                          += clk.o
+obj-$(CONFIG_LOONGSON1_LS1B)   += clk-loongson1b.o
diff --git a/drivers/clk/loongson1/clk-loongson1b.c b/drivers/clk/loongson1/clk-loongson1b.c
new file mode 100644 (file)
index 0000000..5b6817e
--- /dev/null
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2012-2016 Zhang, Keguang <keguang.zhang@gmail.com>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/clkdev.h>
+#include <linux/clk-provider.h>
+#include <linux/io.h>
+#include <linux/err.h>
+
+#include <loongson1.h>
+#include "clk.h"
+
+#define OSC            (33 * 1000000)
+#define DIV_APB                2
+
+static DEFINE_SPINLOCK(_lock);
+
+static unsigned long ls1x_pll_recalc_rate(struct clk_hw *hw,
+                                         unsigned long parent_rate)
+{
+       u32 pll, rate;
+
+       pll = __raw_readl(LS1X_CLK_PLL_FREQ);
+       rate = 12 + (pll & 0x3f) + (((pll >> 8) & 0x3ff) >> 10);
+       rate *= OSC;
+       rate >>= 1;
+
+       return rate;
+}
+
+static const struct clk_ops ls1x_pll_clk_ops = {
+       .recalc_rate = ls1x_pll_recalc_rate,
+};
+
+static const char * const cpu_parents[] = { "cpu_clk_div", "osc_33m_clk", };
+static const char * const ahb_parents[] = { "ahb_clk_div", "osc_33m_clk", };
+static const char * const dc_parents[] = { "dc_clk_div", "osc_33m_clk", };
+
+void __init ls1x_clk_init(void)
+{
+       struct clk_hw *hw;
+
+       hw = clk_hw_register_fixed_rate(NULL, "osc_33m_clk", NULL, 0, OSC);
+       clk_hw_register_clkdev(hw, "osc_33m_clk", NULL);
+
+       /* clock derived from 33 MHz OSC clk */
+       hw = clk_hw_register_pll(NULL, "pll_clk", "osc_33m_clk",
+                                &ls1x_pll_clk_ops, 0);
+       clk_hw_register_clkdev(hw, "pll_clk", NULL);
+
+       /* clock derived from PLL clk */
+       /*                                 _____
+        *         _______________________|     |
+        * OSC ___/                       | MUX |___ CPU CLK
+        *        \___ PLL ___ CPU DIV ___|     |
+        *                                |_____|
+        */
+       hw = clk_hw_register_divider(NULL, "cpu_clk_div", "pll_clk",
+                                  CLK_GET_RATE_NOCACHE, LS1X_CLK_PLL_DIV,
+                                  DIV_CPU_SHIFT, DIV_CPU_WIDTH,
+                                  CLK_DIVIDER_ONE_BASED |
+                                  CLK_DIVIDER_ROUND_CLOSEST, &_lock);
+       clk_hw_register_clkdev(hw, "cpu_clk_div", NULL);
+       hw = clk_hw_register_mux(NULL, "cpu_clk", cpu_parents,
+                              ARRAY_SIZE(cpu_parents),
+                              CLK_SET_RATE_NO_REPARENT, LS1X_CLK_PLL_DIV,
+                              BYPASS_CPU_SHIFT, BYPASS_CPU_WIDTH, 0, &_lock);
+       clk_hw_register_clkdev(hw, "cpu_clk", NULL);
+
+       /*                                 _____
+        *         _______________________|     |
+        * OSC ___/                       | MUX |___ DC  CLK
+        *        \___ PLL ___ DC  DIV ___|     |
+        *                                |_____|
+        */
+       hw = clk_hw_register_divider(NULL, "dc_clk_div", "pll_clk",
+                                  0, LS1X_CLK_PLL_DIV, DIV_DC_SHIFT,
+                                  DIV_DC_WIDTH, CLK_DIVIDER_ONE_BASED, &_lock);
+       clk_hw_register_clkdev(hw, "dc_clk_div", NULL);
+       hw = clk_hw_register_mux(NULL, "dc_clk", dc_parents,
+                              ARRAY_SIZE(dc_parents),
+                              CLK_SET_RATE_NO_REPARENT, LS1X_CLK_PLL_DIV,
+                              BYPASS_DC_SHIFT, BYPASS_DC_WIDTH, 0, &_lock);
+       clk_hw_register_clkdev(hw, "dc_clk", NULL);
+
+       /*                                 _____
+        *         _______________________|     |
+        * OSC ___/                       | MUX |___ DDR CLK
+        *        \___ PLL ___ DDR DIV ___|     |
+        *                                |_____|
+        */
+       hw = clk_hw_register_divider(NULL, "ahb_clk_div", "pll_clk",
+                                  0, LS1X_CLK_PLL_DIV, DIV_DDR_SHIFT,
+                                  DIV_DDR_WIDTH, CLK_DIVIDER_ONE_BASED,
+                                  &_lock);
+       clk_hw_register_clkdev(hw, "ahb_clk_div", NULL);
+       hw = clk_hw_register_mux(NULL, "ahb_clk", ahb_parents,
+                              ARRAY_SIZE(ahb_parents),
+                              CLK_SET_RATE_NO_REPARENT, LS1X_CLK_PLL_DIV,
+                              BYPASS_DDR_SHIFT, BYPASS_DDR_WIDTH, 0, &_lock);
+       clk_hw_register_clkdev(hw, "ahb_clk", NULL);
+       clk_hw_register_clkdev(hw, "stmmaceth", NULL);
+
+       /* clock derived from AHB clk */
+       /* APB clk is always half of the AHB clk */
+       hw = clk_hw_register_fixed_factor(NULL, "apb_clk", "ahb_clk", 0, 1,
+                                       DIV_APB);
+       clk_hw_register_clkdev(hw, "apb_clk", NULL);
+       clk_hw_register_clkdev(hw, "ls1x_i2c", NULL);
+       clk_hw_register_clkdev(hw, "ls1x_pwmtimer", NULL);
+       clk_hw_register_clkdev(hw, "ls1x_spi", NULL);
+       clk_hw_register_clkdev(hw, "ls1x_wdt", NULL);
+       clk_hw_register_clkdev(hw, "serial8250", NULL);
+}
diff --git a/drivers/clk/loongson1/clk.c b/drivers/clk/loongson1/clk.c
new file mode 100644 (file)
index 0000000..cfcfd14
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2012-2016 Zhang, Keguang <keguang.zhang@gmail.com>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/slab.h>
+
+struct clk_hw *__init clk_hw_register_pll(struct device *dev,
+                                         const char *name,
+                                         const char *parent_name,
+                                         const struct clk_ops *ops,
+                                         unsigned long flags)
+{
+       int ret;
+       struct clk_hw *hw;
+       struct clk_init_data init;
+
+       /* allocate the divider */
+       hw = kzalloc(sizeof(*hw), GFP_KERNEL);
+       if (!hw)
+               return ERR_PTR(-ENOMEM);
+
+       init.name = name;
+       init.ops = ops;
+       init.flags = flags | CLK_IS_BASIC;
+       init.parent_names = (parent_name ? &parent_name : NULL);
+       init.num_parents = (parent_name ? 1 : 0);
+       hw->init = &init;
+
+       /* register the clock */
+       ret = clk_hw_register(dev, hw);
+       if (ret) {
+               kfree(hw);
+               hw = ERR_PTR(ret);
+       }
+
+       return hw;
+}
diff --git a/drivers/clk/loongson1/clk.h b/drivers/clk/loongson1/clk.h
new file mode 100644 (file)
index 0000000..085d74b
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2012-2016 Zhang, Keguang <keguang.zhang@gmail.com>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#ifndef __LOONGSON1_CLK_H
+#define __LOONGSON1_CLK_H
+
+struct clk_hw *clk_hw_register_pll(struct device *dev,
+                                  const char *name,
+                                  const char *parent_name,
+                                  const struct clk_ops *ops,
+                                  unsigned long flags);
+
+#endif /* __LOONGSON1_CLK_H */