]> Pileus Git - ~andy/linux/commitdiff
Merge branch 'clk-next-s3c64xx' into clk-next
authorMike Turquette <mturquette@linaro.org>
Mon, 5 Aug 2013 18:59:06 +0000 (11:59 -0700)
committerMike Turquette <mturquette@linaro.org>
Thu, 8 Aug 2013 22:57:26 +0000 (15:57 -0700)
14 files changed:
Documentation/devicetree/bindings/clock/clk-exynos-audss.txt
Documentation/devicetree/bindings/clock/exynos4-clock.txt
Documentation/devicetree/bindings/clock/exynos5250-clock.txt
Documentation/devicetree/bindings/gpu/samsung-g2d.txt
drivers/clk/Kconfig
drivers/clk/clk.c
drivers/clk/samsung/clk-exynos-audss.c
drivers/clk/samsung/clk-exynos4.c
drivers/clk/samsung/clk-exynos5250.c
drivers/clk/samsung/clk-exynos5420.c
drivers/clk/samsung/clk-exynos5440.c
drivers/clk/samsung/clk-pll.c
drivers/clk/samsung/clk-pll.h
drivers/clk/samsung/clk.h

index a1201802f90d0d8fdcfd552c7d359c3cc7b79d31..75e2e1999f87dabdb7eccc94ba01d472533a69fd 100644 (file)
@@ -2,7 +2,7 @@
 
 The Samsung Audio Subsystem clock controller generates and supplies clocks
 to Audio Subsystem block available in the S5PV210 and Exynos SoCs. The clock
-binding described here is applicable to all SoC's in Exynos family.
+binding described here is applicable to all SoCs in Exynos family.
 
 Required Properties:
 
index 14d5c2af26f4bec06f4fb507db6d647a3eb25255..c6bf8a6c8f52856b95af14e1e85134a246c1a44b 100644 (file)
@@ -236,6 +236,7 @@ Exynos4 SoC and this is specified where applicable.
   spi0_isp_sclk       380     Exynos4x12
   spi1_isp_sclk       381     Exynos4x12
   uart_isp_sclk       382     Exynos4x12
+  tmu_apbif           383
 
                [Mux Clocks]
 
index 781a6276adf75ca5eecac09eceb773fbe7fcef2f..24765c146e31d52ea4c732812c420ccdb5d3e670 100644 (file)
@@ -59,6 +59,9 @@ clock which they consume.
   sclk_spi0            154
   sclk_spi1            155
   sclk_spi2            156
+  div_i2s1             157
+  div_i2s2             158
+  sclk_hdmiphy         159
 
 
    [Peripheral Clock Gates]
@@ -154,7 +157,16 @@ clock which they consume.
   dsim0                        341
   dp                   342
   mixer                        343
-  hdmi                 345
+  hdmi                 344
+  g2d                  345
+
+
+   [Clock Muxes]
+
+  Clock                        ID
+  ----------------------------
+  mout_hdmi            1024
+
 
 Example 1: An example of a clock controller node is listed below.
 
index 3f454ffc654a4c969d40542de5056b69f94c2961..c4f358dafdaa58c8a2d2c197789cf740a802202d 100644 (file)
@@ -11,8 +11,11 @@ Required properties:
 
   - interrupts : G2D interrupt number to the CPU.
   - clocks : from common clock binding: handle to G2D clocks.
-  - clock-names : from common clock binding: must contain "sclk_fimg2d" and
-                 "fimg2d", corresponding to entries in the clocks property.
+  - clock-names : names of clocks listed in clocks property, in the same
+                 order, depending on SoC type:
+                 - for S5PV210 and Exynos4 based SoCs: "fimg2d" and
+                   "sclk_fimg2d"
+                 - for Exynos5250 SoC: "fimg2d".
 
 Example:
        g2d@12800000 {
index 51380d655d1aff80ab4368dddfe2d4284becc59c..cd49096c38fa48091ffeefef1c187d99f103169b 100644 (file)
@@ -27,7 +27,7 @@ config COMMON_CLK_DEBUG
        bool "DebugFS representation of clock tree"
        select DEBUG_FS
        ---help---
-         Creates a directory hierchy in debugfs for visualizing the clk
+         Creates a directory hierarchy in debugfs for visualizing the clk
          tree structure.  Each directory contains read-only members
          that export information specific to that clk node: clk_rate,
          clk_flags, clk_prepare_count, clk_enable_count &
index 54a191c5bbf0e3f4c1b23807c12a59cdb0d74031..56a00db61332eee32aed15354801bf335e14368d 100644 (file)
@@ -702,7 +702,7 @@ void __clk_unprepare(struct clk *clk)
 
 /**
  * clk_unprepare - undo preparation of a clock source
- * @clk: the clk being unprepare
+ * @clk: the clk being unprepared
  *
  * clk_unprepare may sleep, which differentiates it from clk_disable.  In a
  * simple case, clk_unprepare can be used instead of clk_disable to gate a clk
@@ -869,6 +869,7 @@ EXPORT_SYMBOL_GPL(clk_enable);
 /**
  * __clk_round_rate - round the given rate for a clk
  * @clk: round the rate of this clock
+ * @rate: the rate which is to be rounded
  *
  * Caller must hold prepare_lock.  Useful for clk_ops such as .set_rate
  */
@@ -956,7 +957,7 @@ static int __clk_notify(struct clk *clk, unsigned long msg,
  *
  * Walks the subtree of clks starting with clk and recalculates rates as it
  * goes.  Note that if a clk does not implement the .recalc_rate callback then
- * it is assumed that the clock will take on the rate of it's parent.
+ * it is assumed that the clock will take on the rate of its parent.
  *
  * clk_recalc_rates also propagates the POST_RATE_CHANGE notification,
  * if necessary.
@@ -1026,7 +1027,7 @@ EXPORT_SYMBOL_GPL(clk_get_rate);
  * pre-rate change notifications and returns early if no clks in the
  * subtree have subscribed to the notifications.  Note that if a clk does not
  * implement the .recalc_rate callback then it is assumed that the clock will
- * take on the rate of it's parent.
+ * take on the rate of its parent.
  *
  * Caller must hold prepare_lock.
  */
@@ -1198,7 +1199,7 @@ static void clk_change_rate(struct clk *clk)
  * outcome of clk's .round_rate implementation.  If *parent_rate is unchanged
  * after calling .round_rate then upstream parent propagation is ignored.  If
  * *parent_rate comes back with a new rate for clk's parent then we propagate
- * up to clk's parent and set it's rate.  Upward propagation will continue
+ * up to clk's parent and set its rate.  Upward propagation will continue
  * until either a clk does not support the CLK_SET_RATE_PARENT flag or
  * .round_rate stops requesting changes to clk's parent_rate.
  *
@@ -1648,7 +1649,7 @@ int __clk_init(struct device *dev, struct clk *clk)
         * The .init callback is not used by any of the basic clock types, but
         * exists for weird hardware that must perform initialization magic.
         * Please consider other ways of solving initialization problems before
-        * using this callback, as it's use is discouraged.
+        * using this callback, as its use is discouraged.
         */
        if (clk->ops->init)
                clk->ops->init(clk->hw);
@@ -1675,7 +1676,7 @@ out:
  * very large numbers of clocks that need to be statically initialized.  It is
  * a layering violation to include clk-private.h from any code which implements
  * a clock's .ops; as such any statically initialized clock data MUST be in a
- * separate C file from the logic that implements it's operations.  Returns 0
+ * separate C file from the logic that implements its operations.  Returns 0
  * on success, otherwise an error code.
  */
 struct clk *__clk_register(struct device *dev, struct clk_hw *hw)
index 9b1bbd52fd1f227b01a460a24b7dcb4db562c58f..51b48daf5c8a95b31153d8bf6144c95e143a6e69 100644 (file)
@@ -62,7 +62,7 @@ static struct syscore_ops exynos_audss_clk_syscore_ops = {
 #endif /* CONFIG_PM_SLEEP */
 
 /* register exynos_audss clocks */
-void __init exynos_audss_clk_init(struct device_node *np)
+static void __init exynos_audss_clk_init(struct device_node *np)
 {
        reg_base = of_iomap(np, 0);
        if (!reg_base) {
index 1bdb882c845bd48a96597bb8f65c2cbe2a3c03c2..68f9a4a672663d161b8e39e2a22c07a5b186ab71 100644 (file)
@@ -17,7 +17,6 @@
 #include <linux/of_address.h>
 
 #include "clk.h"
-#include "clk-pll.h"
 
 /* Exynos4 clock controller register offsets */
 #define SRC_LEFTBUS            0x4200
 #define GATE_IP_PERIL          0xc950
 #define E4210_GATE_IP_PERIR    0xc960
 #define GATE_BLOCK             0xc970
+#define E4X12_MPLL_LOCK                0x10008
 #define E4X12_MPLL_CON0                0x10108
 #define SRC_DMC                        0x10200
 #define SRC_MASK_DMC           0x10300
 #define DIV_DMC0               0x10500
 #define DIV_DMC1               0x10504
 #define GATE_IP_DMC            0x10900
+#define APLL_LOCK              0x14000
 #define APLL_CON0              0x14100
 #define E4210_MPLL_CON0                0x14108
 #define SRC_CPU                        0x14200
@@ -121,6 +122,12 @@ enum exynos4_soc {
        EXYNOS4X12,
 };
 
+/* list of PLLs to be registered */
+enum exynos4_plls {
+       apll, mpll, epll, vpll,
+       nr_plls                 /* number of PLLs */
+};
+
 /*
  * Let each supported clock get a unique id. This id is used to lookup the clock
  * for device tree based platforms. The clocks are categorized into three
@@ -169,7 +176,7 @@ enum exynos4_clks {
        gicisp, smmu_isp, smmu_drc, smmu_fd, smmu_lite0, smmu_lite1, mcuctl_isp,
        mpwm_isp, i2c0_isp, i2c1_isp, mtcadc_isp, pwm_isp, wdt_isp, uart_isp,
        asyncaxim, smmu_ispcx, spi0_isp, spi1_isp, pwm_isp_sclk, spi0_isp_sclk,
-       spi1_isp_sclk, uart_isp_sclk,
+       spi1_isp_sclk, uart_isp_sclk, tmu_apbif,
 
        /* mux clocks */
        mout_fimc0 = 384, mout_fimc1, mout_fimc2, mout_fimc3, mout_cam0,
@@ -338,24 +345,24 @@ PNAME(mout_user_aclk200_p4x12) = {"fin_pll", "div_aclk200", };
 PNAME(mout_user_aclk266_gps_p4x12) = {"fin_pll", "div_aclk266_gps", };
 
 /* fixed rate clocks generated outside the soc */
-struct samsung_fixed_rate_clock exynos4_fixed_rate_ext_clks[] __initdata = {
+static struct samsung_fixed_rate_clock exynos4_fixed_rate_ext_clks[] __initdata = {
        FRATE(xxti, "xxti", NULL, CLK_IS_ROOT, 0),
        FRATE(xusbxti, "xusbxti", NULL, CLK_IS_ROOT, 0),
 };
 
 /* fixed rate clocks generated inside the soc */
-struct samsung_fixed_rate_clock exynos4_fixed_rate_clks[] __initdata = {
+static struct samsung_fixed_rate_clock exynos4_fixed_rate_clks[] __initdata = {
        FRATE(none, "sclk_hdmi24m", NULL, CLK_IS_ROOT, 24000000),
        FRATE(none, "sclk_hdmiphy", NULL, CLK_IS_ROOT, 27000000),
        FRATE(none, "sclk_usbphy0", NULL, CLK_IS_ROOT, 48000000),
 };
 
-struct samsung_fixed_rate_clock exynos4210_fixed_rate_clks[] __initdata = {
+static struct samsung_fixed_rate_clock exynos4210_fixed_rate_clks[] __initdata = {
        FRATE(none, "sclk_usbphy1", NULL, CLK_IS_ROOT, 48000000),
 };
 
 /* list of mux clocks supported in all exynos4 soc's */
-struct samsung_mux_clock exynos4_mux_clks[] __initdata = {
+static struct samsung_mux_clock exynos4_mux_clks[] __initdata = {
        MUX_FA(mout_apll, "mout_apll", mout_apll_p, SRC_CPU, 0, 1,
                        CLK_SET_RATE_PARENT, 0, "mout_apll"),
        MUX(none, "mout_hdmi", mout_hdmi_p, SRC_TV, 0, 1),
@@ -372,7 +379,7 @@ struct samsung_mux_clock exynos4_mux_clks[] __initdata = {
 };
 
 /* list of mux clocks supported in exynos4210 soc */
-struct samsung_mux_clock exynos4210_mux_clks[] __initdata = {
+static struct samsung_mux_clock exynos4210_mux_clks[] __initdata = {
        MUX(none, "mout_aclk200", sclk_ampll_p4210, SRC_TOP0, 12, 1),
        MUX(none, "mout_aclk100", sclk_ampll_p4210, SRC_TOP0, 16, 1),
        MUX(none, "mout_aclk160", sclk_ampll_p4210, SRC_TOP0, 20, 1),
@@ -423,7 +430,7 @@ struct samsung_mux_clock exynos4210_mux_clks[] __initdata = {
 };
 
 /* list of mux clocks supported in exynos4x12 soc */
-struct samsung_mux_clock exynos4x12_mux_clks[] __initdata = {
+static struct samsung_mux_clock exynos4x12_mux_clks[] __initdata = {
        MUX_A(mout_mpll_user_c, "mout_mpll_user_c", mout_mpll_user_p4x12,
                        SRC_CPU, 24, 1, "mout_mpll"),
        MUX(none, "mout_aclk266_gps", aclk_p4412, SRC_TOP1, 4, 1),
@@ -491,7 +498,7 @@ struct samsung_mux_clock exynos4x12_mux_clks[] __initdata = {
 };
 
 /* list of divider clocks supported in all exynos4 soc's */
-struct samsung_div_clock exynos4_div_clks[] __initdata = {
+static struct samsung_div_clock exynos4_div_clks[] __initdata = {
        DIV(none, "div_core", "mout_core", DIV_CPU0, 0, 3),
        DIV(none, "div_core2", "div_core", DIV_CPU0, 28, 3),
        DIV(none, "div_fimc0", "mout_fimc0", DIV_CAM, 0, 4),
@@ -554,7 +561,7 @@ struct samsung_div_clock exynos4_div_clks[] __initdata = {
 };
 
 /* list of divider clocks supported in exynos4210 soc */
-struct samsung_div_clock exynos4210_div_clks[] __initdata = {
+static struct samsung_div_clock exynos4210_div_clks[] __initdata = {
        DIV(aclk200, "aclk200", "mout_aclk200", DIV_TOP, 0, 3),
        DIV(sclk_fimg2d, "sclk_fimg2d", "mout_g2d", DIV_IMAGE, 0, 4),
        DIV(none, "div_fimd1", "mout_fimd1", E4210_DIV_LCD1, 0, 4),
@@ -565,7 +572,7 @@ struct samsung_div_clock exynos4210_div_clks[] __initdata = {
 };
 
 /* list of divider clocks supported in exynos4x12 soc */
-struct samsung_div_clock exynos4x12_div_clks[] __initdata = {
+static struct samsung_div_clock exynos4x12_div_clks[] __initdata = {
        DIV(none, "div_mdnie0", "mout_mdnie0", DIV_LCD0, 4, 4),
        DIV(none, "div_mdnie_pwm0", "mout_mdnie_pwm0", DIV_LCD0, 8, 4),
        DIV(none, "div_mdnie_pwm_pre0", "div_mdnie_pwm0", DIV_LCD0, 12, 4),
@@ -590,7 +597,7 @@ struct samsung_div_clock exynos4x12_div_clks[] __initdata = {
 };
 
 /* list of gate clocks supported in all exynos4 soc's */
-struct samsung_gate_clock exynos4_gate_clks[] __initdata = {
+static struct samsung_gate_clock exynos4_gate_clks[] __initdata = {
        /*
         * After all Exynos4 based platforms are migrated to use device tree,
         * the device name and clock alias names specified below for some
@@ -782,7 +789,7 @@ struct samsung_gate_clock exynos4_gate_clks[] __initdata = {
 };
 
 /* list of gate clocks supported in exynos4210 soc */
-struct samsung_gate_clock exynos4210_gate_clks[] __initdata = {
+static struct samsung_gate_clock exynos4210_gate_clks[] __initdata = {
        GATE(tvenc, "tvenc", "aclk160", GATE_IP_TV, 2, 0, 0),
        GATE(g2d, "g2d", "aclk200", E4210_GATE_IP_IMAGE, 0, 0, 0),
        GATE(rotator, "rotator", "aclk200", E4210_GATE_IP_IMAGE, 1, 0, 0),
@@ -814,10 +821,11 @@ struct samsung_gate_clock exynos4210_gate_clks[] __initdata = {
        GATE_A(keyif, "keyif", "aclk100", E4210_GATE_IP_PERIR, 16, 0, 0, "keypad"),
        GATE_DA(sclk_fimd1, "exynos4-fb.1", "sclk_fimd1", "div_fimd1",
                        E4210_SRC_MASK_LCD1, 0, CLK_SET_RATE_PARENT, 0, "sclk_fimd"),
+       GATE(tmu_apbif, "tmu_apbif", "aclk100", E4210_GATE_IP_PERIR, 17, 0, 0),
 };
 
 /* list of gate clocks supported in exynos4x12 soc */
-struct samsung_gate_clock exynos4x12_gate_clks[] __initdata = {
+static struct samsung_gate_clock exynos4x12_gate_clks[] __initdata = {
        GATE(audss, "audss", "sclk_epll", E4X12_GATE_IP_MAUDIO, 0, 0, 0),
        GATE(mdnie0, "mdnie0", "aclk160", GATE_IP_LCD0, 2, 0, 0),
        GATE(rotator, "rotator", "aclk200", E4X12_GATE_IP_IMAGE, 1, 0, 0),
@@ -915,6 +923,7 @@ struct samsung_gate_clock exynos4x12_gate_clks[] __initdata = {
        GATE(spi1_isp, "spi1_isp", "aclk200", E4X12_GATE_ISP1, 13,
                        CLK_IGNORE_UNUSED, 0),
        GATE(g2d, "g2d", "aclk200", GATE_IP_DMC, 23, 0, 0),
+       GATE(tmu_apbif, "tmu_apbif", "aclk100", E4X12_GATE_IP_PERIR, 17, 0, 0),
 };
 
 /*
@@ -969,28 +978,27 @@ static void __init exynos4_clk_register_finpll(unsigned long xom)
 
 }
 
-/*
- * This function allows non-dt platforms to specify the clock speed of the
- * xxti and xusbxti clocks. These clocks are then registered with the specified
- * clock speed.
- */
-void __init exynos4_clk_register_fixed_ext(unsigned long xxti_f,
-                                               unsigned long xusbxti_f)
-{
-       exynos4_fixed_rate_ext_clks[0].fixed_rate = xxti_f;
-       exynos4_fixed_rate_ext_clks[1].fixed_rate = xusbxti_f;
-       samsung_clk_register_fixed_rate(exynos4_fixed_rate_ext_clks,
-                       ARRAY_SIZE(exynos4_fixed_rate_ext_clks));
-}
-
 static __initdata struct of_device_id ext_clk_match[] = {
        { .compatible = "samsung,clock-xxti", .data = (void *)0, },
        { .compatible = "samsung,clock-xusbxti", .data = (void *)1, },
        {},
 };
 
+struct __initdata samsung_pll_clock exynos4_plls[nr_plls] = {
+       [apll] = PLL_A(pll_35xx, fout_apll, "fout_apll", "fin_pll", APLL_LOCK,
+               APLL_CON0, "fout_apll", NULL),
+       [mpll] = PLL_A(pll_35xx, fout_mpll, "fout_mpll", "fin_pll",
+               E4X12_MPLL_LOCK, E4X12_MPLL_CON0, "fout_mpll", NULL),
+       [epll] = PLL_A(pll_36xx, fout_epll, "fout_epll", "fin_pll", EPLL_LOCK,
+               EPLL_CON0, "fout_epll", NULL),
+       [vpll] = PLL_A(pll_36xx, fout_vpll, "fout_vpll", "fin_pll", VPLL_LOCK,
+               VPLL_CON0, "fout_vpll", NULL),
+};
+
 /* register exynos4 clocks */
-void __init exynos4_clk_init(struct device_node *np, enum exynos4_soc exynos4_soc, void __iomem *reg_base, unsigned long xom)
+static void __init exynos4_clk_init(struct device_node *np,
+                                   enum exynos4_soc exynos4_soc,
+                                   void __iomem *reg_base, unsigned long xom)
 {
        struct clk *apll, *mpll, *epll, *vpll;
 
@@ -1025,22 +1033,16 @@ void __init exynos4_clk_init(struct device_node *np, enum exynos4_soc exynos4_so
                                        reg_base + EPLL_CON0, pll_4600);
                vpll = samsung_clk_register_pll46xx("fout_vpll", "mout_vpllsrc",
                                        reg_base + VPLL_CON0, pll_4650c);
+
+               samsung_clk_add_lookup(apll, fout_apll);
+               samsung_clk_add_lookup(mpll, fout_mpll);
+               samsung_clk_add_lookup(epll, fout_epll);
+               samsung_clk_add_lookup(vpll, fout_vpll);
        } else {
-               apll = samsung_clk_register_pll35xx("fout_apll", "fin_pll",
-                                       reg_base + APLL_CON0);
-               mpll = samsung_clk_register_pll35xx("fout_mpll", "fin_pll",
-                                       reg_base + E4X12_MPLL_CON0);
-               epll = samsung_clk_register_pll36xx("fout_epll", "fin_pll",
-                                       reg_base + EPLL_CON0);
-               vpll = samsung_clk_register_pll36xx("fout_vpll", "fin_pll",
-                                       reg_base + VPLL_CON0);
+               samsung_clk_register_pll(exynos4_plls,
+                                       ARRAY_SIZE(exynos4_plls), reg_base);
        }
 
-       samsung_clk_add_lookup(apll, fout_apll);
-       samsung_clk_add_lookup(mpll, fout_mpll);
-       samsung_clk_add_lookup(epll, fout_epll);
-       samsung_clk_add_lookup(vpll, fout_vpll);
-
        samsung_clk_register_fixed_rate(exynos4_fixed_rate_clks,
                        ARRAY_SIZE(exynos4_fixed_rate_clks));
        samsung_clk_register_mux(exynos4_mux_clks,
index 6f767c515ec77df4d100edcdabfb78da7cb60e9e..df3628cf259766cf5d815dd26f0b1933ba73513c 100644 (file)
 #include <linux/of_address.h>
 
 #include "clk.h"
-#include "clk-pll.h"
 
+#define APLL_LOCK              0x0
+#define APLL_CON0              0x100
 #define SRC_CPU                        0x200
 #define DIV_CPU0               0x500
+#define MPLL_LOCK              0x4000
+#define MPLL_CON0              0x4100
 #define SRC_CORE1              0x4204
+#define CPLL_LOCK              0x10020
+#define EPLL_LOCK              0x10030
+#define VPLL_LOCK              0x10040
+#define GPLL_LOCK              0x10050
+#define CPLL_CON0              0x10120
+#define EPLL_CON0              0x10130
+#define VPLL_CON0              0x10140
+#define GPLL_CON0              0x10150
 #define SRC_TOP0               0x10210
 #define SRC_TOP2               0x10218
 #define SRC_GSCL               0x10220
 #define GATE_IP_FSYS           0x10944
 #define GATE_IP_PERIC          0x10950
 #define GATE_IP_PERIS          0x10960
+#define BPLL_LOCK              0x20010
+#define BPLL_CON0              0x20110
 #define SRC_CDREX              0x20200
 #define PLL_DIV2_SEL           0x20a24
 #define GATE_IP_DISP1          0x10928
+#define GATE_IP_ACP            0x10000
+
+/* list of PLLs to be registered */
+enum exynos5250_plls {
+       apll, mpll, cpll, epll, vpll, gpll, bpll,
+       nr_plls                 /* number of PLLs */
+};
 
 /*
  * Let each supported clock get a unique id. This id is used to lookup the clock
@@ -79,7 +99,8 @@ enum exynos5250_clks {
        none,
 
        /* core clocks */
-       fin_pll,
+       fin_pll, fout_apll, fout_mpll, fout_bpll, fout_gpll, fout_cpll,
+       fout_epll, fout_vpll,
 
        /* gate for special clocks (sclk) */
        sclk_cam_bayer = 128, sclk_cam0, sclk_cam1, sclk_gscl_wa, sclk_gscl_wb,
@@ -87,7 +108,7 @@ enum exynos5250_clks {
        sclk_mmc0, sclk_mmc1, sclk_mmc2, sclk_mmc3, sclk_sata, sclk_usb3,
        sclk_jpeg, sclk_uart0, sclk_uart1, sclk_uart2, sclk_uart3, sclk_pwm,
        sclk_audio1, sclk_audio2, sclk_spdif, sclk_spi0, sclk_spi1, sclk_spi2,
-       div_i2s1, div_i2s2,
+       div_i2s1, div_i2s2, sclk_hdmiphy,
 
        /* gate clocks */
        gscl0 = 256, gscl1, gscl2, gscl3, gscl_wa, gscl_wb, smmu_gscl0,
@@ -99,7 +120,10 @@ enum exynos5250_clks {
        spi2, i2s1, i2s2, pcm1, pcm2, pwm, spdif, ac97, hsi2c0, hsi2c1, hsi2c2,
        hsi2c3, chipid, sysreg, pmu, cmu_top, cmu_core, cmu_mem, tzpc0, tzpc1,
        tzpc2, tzpc3, tzpc4, tzpc5, tzpc6, tzpc7, tzpc8, tzpc9, hdmi_cec, mct,
-       wdt, rtc, tmu, fimd1, mie1, dsim0, dp, mixer, hdmi,
+       wdt, rtc, tmu, fimd1, mie1, dsim0, dp, mixer, hdmi, g2d,
+
+       /* mux clocks */
+       mout_hdmi = 1024,
 
        nr_clks,
 };
@@ -152,6 +176,7 @@ static __initdata unsigned long exynos5250_clk_regs[] = {
        SRC_CDREX,
        PLL_DIV2_SEL,
        GATE_IP_DISP1,
+       GATE_IP_ACP,
 };
 
 /* list of all parent clock list */
@@ -191,31 +216,34 @@ PNAME(mout_spdif_p)       = { "sclk_audio0", "sclk_audio1", "sclk_audio2",
                                "spdif_extclk" };
 
 /* fixed rate clocks generated outside the soc */
-struct samsung_fixed_rate_clock exynos5250_fixed_rate_ext_clks[] __initdata = {
+static struct samsung_fixed_rate_clock exynos5250_fixed_rate_ext_clks[] __initdata = {
        FRATE(fin_pll, "fin_pll", NULL, CLK_IS_ROOT, 0),
 };
 
 /* fixed rate clocks generated inside the soc */
-struct samsung_fixed_rate_clock exynos5250_fixed_rate_clks[] __initdata = {
-       FRATE(none, "sclk_hdmiphy", NULL, CLK_IS_ROOT, 24000000),
+static struct samsung_fixed_rate_clock exynos5250_fixed_rate_clks[] __initdata = {
+       FRATE(sclk_hdmiphy, "sclk_hdmiphy", NULL, CLK_IS_ROOT, 24000000),
        FRATE(none, "sclk_hdmi27m", NULL, CLK_IS_ROOT, 27000000),
        FRATE(none, "sclk_dptxphy", NULL, CLK_IS_ROOT, 24000000),
        FRATE(none, "sclk_uhostphy", NULL, CLK_IS_ROOT, 48000000),
 };
 
-struct samsung_fixed_factor_clock exynos5250_fixed_factor_clks[] __initdata = {
+static struct samsung_fixed_factor_clock exynos5250_fixed_factor_clks[] __initdata = {
        FFACTOR(none, "fout_mplldiv2", "fout_mpll", 1, 2, 0),
        FFACTOR(none, "fout_bplldiv2", "fout_bpll", 1, 2, 0),
 };
 
-struct samsung_mux_clock exynos5250_mux_clks[] __initdata = {
+static struct samsung_mux_clock exynos5250_pll_pmux_clks[] __initdata = {
+       MUX(none, "mout_vpllsrc", mout_vpllsrc_p, SRC_TOP2, 0, 1),
+};
+
+static struct samsung_mux_clock exynos5250_mux_clks[] __initdata = {
        MUX_A(none, "mout_apll", mout_apll_p, SRC_CPU, 0, 1, "mout_apll"),
        MUX_A(none, "mout_cpu", mout_cpu_p, SRC_CPU, 16, 1, "mout_cpu"),
        MUX(none, "mout_mpll_fout", mout_mpll_fout_p, PLL_DIV2_SEL, 4, 1),
        MUX_A(none, "sclk_mpll", mout_mpll_p, SRC_CORE1, 8, 1, "mout_mpll"),
        MUX(none, "mout_bpll_fout", mout_bpll_fout_p, PLL_DIV2_SEL, 0, 1),
        MUX(none, "sclk_bpll", mout_bpll_p, SRC_CDREX, 0, 1),
-       MUX(none, "mout_vpllsrc", mout_vpllsrc_p, SRC_TOP2, 0, 1),
        MUX(none, "sclk_vpll", mout_vpll_p, SRC_TOP2, 16, 1),
        MUX(none, "sclk_epll", mout_epll_p, SRC_TOP2, 12, 1),
        MUX(none, "sclk_cpll", mout_cpll_p, SRC_TOP2, 8, 1),
@@ -232,7 +260,7 @@ struct samsung_mux_clock exynos5250_mux_clks[] __initdata = {
        MUX(none, "mout_fimd1", mout_group1_p, SRC_DISP1_0, 0, 4),
        MUX(none, "mout_mipi1", mout_group1_p, SRC_DISP1_0, 12, 4),
        MUX(none, "mout_dp", mout_group1_p, SRC_DISP1_0, 16, 4),
-       MUX(none, "mout_hdmi", mout_hdmi_p, SRC_DISP1_0, 20, 1),
+       MUX(mout_hdmi, "mout_hdmi", mout_hdmi_p, SRC_DISP1_0, 20, 1),
        MUX(none, "mout_audio0", mout_audio0_p, SRC_MAU, 0, 4),
        MUX(none, "mout_mmc0", mout_group1_p, SRC_FSYS, 0, 4),
        MUX(none, "mout_mmc1", mout_group1_p, SRC_FSYS, 4, 4),
@@ -254,7 +282,7 @@ struct samsung_mux_clock exynos5250_mux_clks[] __initdata = {
        MUX(none, "mout_spi2", mout_group1_p, SRC_PERIC1, 24, 4),
 };
 
-struct samsung_div_clock exynos5250_div_clks[] __initdata = {
+static struct samsung_div_clock exynos5250_div_clks[] __initdata = {
        DIV(none, "div_arm", "mout_cpu", DIV_CPU0, 0, 3),
        DIV(none, "sclk_apll", "mout_apll", DIV_CPU0, 24, 3),
        DIV(none, "aclk66_pre", "sclk_mpll_user", DIV_TOP1, 24, 3),
@@ -314,7 +342,7 @@ struct samsung_div_clock exynos5250_div_clks[] __initdata = {
                        DIV_PERIC2, 8, 8, CLK_SET_RATE_PARENT, 0),
 };
 
-struct samsung_gate_clock exynos5250_gate_clks[] __initdata = {
+static struct samsung_gate_clock exynos5250_gate_clks[] __initdata = {
        GATE(gscl0, "gscl0", "none", GATE_IP_GSCL, 0, 0, 0),
        GATE(gscl1, "gscl1", "none", GATE_IP_GSCL, 1, 0, 0),
        GATE(gscl2, "gscl2", "aclk266", GATE_IP_GSCL, 2, 0, 0),
@@ -463,6 +491,47 @@ struct samsung_gate_clock exynos5250_gate_clks[] __initdata = {
        GATE(dp, "dp", "aclk200", GATE_IP_DISP1, 4, 0, 0),
        GATE(mixer, "mixer", "aclk200", GATE_IP_DISP1, 5, 0, 0),
        GATE(hdmi, "hdmi", "aclk200", GATE_IP_DISP1, 6, 0, 0),
+       GATE(g2d, "g2d", "aclk200", GATE_IP_ACP, 3, 0, 0),
+};
+
+static __initdata struct samsung_pll_rate_table vpll_24mhz_tbl[] = {
+       /* sorted in descending order */
+       /* PLL_36XX_RATE(rate, m, p, s, k) */
+       PLL_36XX_RATE(266000000, 266, 3, 3, 0),
+       /* Not in UM, but need for eDP on snow */
+       PLL_36XX_RATE(70500000, 94, 2, 4, 0),
+       { },
+};
+
+static __initdata struct samsung_pll_rate_table epll_24mhz_tbl[] = {
+       /* sorted in descending order */
+       /* PLL_36XX_RATE(rate, m, p, s, k) */
+       PLL_36XX_RATE(192000000, 64, 2, 2, 0),
+       PLL_36XX_RATE(180633600, 90, 3, 2, 20762),
+       PLL_36XX_RATE(180000000, 90, 3, 2, 0),
+       PLL_36XX_RATE(73728000, 98, 2, 4, 19923),
+       PLL_36XX_RATE(67737600, 90, 2, 4, 20762),
+       PLL_36XX_RATE(49152000, 98, 3, 4, 19923),
+       PLL_36XX_RATE(45158400, 90, 3, 4, 20762),
+       PLL_36XX_RATE(32768000, 131, 3, 5, 4719),
+       { },
+};
+
+struct __initdata samsung_pll_clock exynos5250_plls[nr_plls] = {
+       [apll] = PLL_A(pll_35xx, fout_apll, "fout_apll", "fin_pll", APLL_LOCK,
+               APLL_CON0, "fout_apll", NULL),
+       [mpll] = PLL_A(pll_35xx, fout_mpll, "fout_mpll", "fin_pll", MPLL_LOCK,
+               MPLL_CON0, "fout_mpll", NULL),
+       [bpll] = PLL(pll_35xx, fout_bpll, "fout_bpll", "fin_pll", BPLL_LOCK,
+               BPLL_CON0, NULL),
+       [gpll] = PLL(pll_35xx, fout_gpll, "fout_gpll", "fin_pll", GPLL_LOCK,
+               GPLL_CON0, NULL),
+       [cpll] = PLL(pll_35xx, fout_cpll, "fout_cpll", "fin_pll", CPLL_LOCK,
+               CPLL_CON0, NULL),
+       [epll] = PLL(pll_36xx, fout_epll, "fout_epll", "fin_pll", EPLL_LOCK,
+               EPLL_CON0, NULL),
+       [vpll] = PLL(pll_36xx, fout_vpll, "fout_vpll", "mout_vpllsrc",
+               VPLL_LOCK, VPLL_CON0, NULL),
 };
 
 static __initdata struct of_device_id ext_clk_match[] = {
@@ -471,10 +540,11 @@ static __initdata struct of_device_id ext_clk_match[] = {
 };
 
 /* register exynox5250 clocks */
-void __init exynos5250_clk_init(struct device_node *np)
+static void __init exynos5250_clk_init(struct device_node *np)
 {
        void __iomem *reg_base;
-       struct clk *apll, *mpll, *epll, *vpll, *bpll, *gpll, *cpll;
+       struct clk *vpllsrc;
+       unsigned long fin_pll_rate, mout_vpllsrc_rate = 0;
 
        if (np) {
                reg_base = of_iomap(np, 0);
@@ -490,22 +560,23 @@ void __init exynos5250_clk_init(struct device_node *np)
        samsung_clk_of_register_fixed_ext(exynos5250_fixed_rate_ext_clks,
                        ARRAY_SIZE(exynos5250_fixed_rate_ext_clks),
                        ext_clk_match);
+       samsung_clk_register_mux(exynos5250_pll_pmux_clks,
+                               ARRAY_SIZE(exynos5250_pll_pmux_clks));
+
+       fin_pll_rate = _get_rate("fin_pll");
+
+       if (fin_pll_rate == 24 * MHZ)
+               exynos5250_plls[epll].rate_table = epll_24mhz_tbl;
+
+       vpllsrc = __clk_lookup("mout_vpllsrc");
+       if (vpllsrc)
+               mout_vpllsrc_rate = clk_get_rate(vpllsrc);
 
-       apll = samsung_clk_register_pll35xx("fout_apll", "fin_pll",
-                       reg_base + 0x100);
-       mpll = samsung_clk_register_pll35xx("fout_mpll", "fin_pll",
-                       reg_base + 0x4100);
-       bpll = samsung_clk_register_pll35xx("fout_bpll", "fin_pll",
-                       reg_base + 0x20110);
-       gpll = samsung_clk_register_pll35xx("fout_gpll", "fin_pll",
-                       reg_base + 0x10150);
-       cpll = samsung_clk_register_pll35xx("fout_cpll", "fin_pll",
-                       reg_base + 0x10120);
-       epll = samsung_clk_register_pll36xx("fout_epll", "fin_pll",
-                       reg_base + 0x10130);
-       vpll = samsung_clk_register_pll36xx("fout_vpll", "mout_vpllsrc",
-                       reg_base + 0x10140);
+       if (mout_vpllsrc_rate == 24 * MHZ)
+               exynos5250_plls[vpll].rate_table =  vpll_24mhz_tbl;
 
+       samsung_clk_register_pll(exynos5250_plls, ARRAY_SIZE(exynos5250_plls),
+                                       reg_base);
        samsung_clk_register_fixed_rate(exynos5250_fixed_rate_clks,
                        ARRAY_SIZE(exynos5250_fixed_rate_clks));
        samsung_clk_register_fixed_factor(exynos5250_fixed_factor_clks,
index 68a96cbd4936724da2919498cb3821b52724ed3d..ca352695a954e9d9da2d3260cbb8c263f6f37a57 100644 (file)
 #include <linux/of_address.h>
 
 #include "clk.h"
-#include "clk-pll.h"
 
+#define APLL_LOCK              0x0
+#define APLL_CON0              0x100
 #define SRC_CPU                        0x200
 #define DIV_CPU0               0x500
 #define DIV_CPU1               0x504
 #define GATE_BUS_CPU           0x700
 #define GATE_SCLK_CPU          0x800
+#define CPLL_LOCK              0x10020
+#define DPLL_LOCK              0x10030
+#define EPLL_LOCK              0x10040
+#define RPLL_LOCK              0x10050
+#define IPLL_LOCK              0x10060
+#define SPLL_LOCK              0x10070
+#define VPLL_LOCK              0x10070
+#define MPLL_LOCK              0x10090
+#define CPLL_CON0              0x10120
+#define DPLL_CON0              0x10128
+#define EPLL_CON0              0x10130
+#define RPLL_CON0              0x10140
+#define IPLL_CON0              0x10150
+#define SPLL_CON0              0x10160
+#define VPLL_CON0              0x10170
+#define MPLL_CON0              0x10180
 #define SRC_TOP0               0x10200
 #define SRC_TOP1               0x10204
 #define SRC_TOP2               0x10208
 #define GATE_TOP_SCLK_MAU      0x1083c
 #define GATE_TOP_SCLK_FSYS     0x10840
 #define GATE_TOP_SCLK_PERIC    0x10850
+#define BPLL_LOCK              0x20010
+#define BPLL_CON0              0x20110
 #define SRC_CDREX              0x20200
+#define KPLL_LOCK              0x28000
+#define KPLL_CON0              0x28100
 #define SRC_KFC                        0x28200
 #define DIV_KFC0               0x28500
 
+/* list of PLLs */
+enum exynos5420_plls {
+       apll, cpll, dpll, epll, rpll, ipll, spll, vpll, mpll,
+       bpll, kpll,
+       nr_plls                 /* number of PLLs */
+};
+
 enum exynos5420_clks {
        none,
 
        /* core clocks */
-       fin_pll,
+       fin_pll,  fout_apll, fout_cpll, fout_dpll, fout_epll, fout_rpll,
+       fout_ipll, fout_spll, fout_vpll, fout_mpll, fout_bpll, fout_kpll,
 
        /* gate for special clocks (sclk) */
        sclk_uart0 = 128, sclk_uart1, sclk_uart2, sclk_uart3, sclk_mmc0,
@@ -262,12 +291,12 @@ PNAME(maudio0_p)  = { "fin_pll", "maudio_clk", "sclk_dpll", "sclk_mpll",
                          "sclk_spll", "sclk_ipll", "sclk_epll", "sclk_rpll" };
 
 /* fixed rate clocks generated outside the soc */
-struct samsung_fixed_rate_clock exynos5420_fixed_rate_ext_clks[] __initdata = {
+static struct samsung_fixed_rate_clock exynos5420_fixed_rate_ext_clks[] __initdata = {
        FRATE(fin_pll, "fin_pll", NULL, CLK_IS_ROOT, 0),
 };
 
 /* fixed rate clocks generated inside the soc */
-struct samsung_fixed_rate_clock exynos5420_fixed_rate_clks[] __initdata = {
+static struct samsung_fixed_rate_clock exynos5420_fixed_rate_clks[] __initdata = {
        FRATE(none, "sclk_hdmiphy", NULL, CLK_IS_ROOT, 24000000),
        FRATE(none, "sclk_pwi", NULL, CLK_IS_ROOT, 24000000),
        FRATE(none, "sclk_usbh20", NULL, CLK_IS_ROOT, 48000000),
@@ -275,11 +304,11 @@ struct samsung_fixed_rate_clock exynos5420_fixed_rate_clks[] __initdata = {
        FRATE(none, "sclk_usbh20_scan_clk", NULL, CLK_IS_ROOT, 480000000),
 };
 
-struct samsung_fixed_factor_clock exynos5420_fixed_factor_clks[] __initdata = {
+static struct samsung_fixed_factor_clock exynos5420_fixed_factor_clks[] __initdata = {
        FFACTOR(none, "sclk_hsic_12m", "fin_pll", 1, 2, 0),
 };
 
-struct samsung_mux_clock exynos5420_mux_clks[] __initdata = {
+static struct samsung_mux_clock exynos5420_mux_clks[] __initdata = {
        MUX(none, "mout_mspll_kfc", mspll_cpu_p, SRC_TOP7, 8, 2),
        MUX(none, "mout_mspll_cpu", mspll_cpu_p, SRC_TOP7, 12, 2),
        MUX(none, "mout_apll", apll_p, SRC_CPU, 0, 1),
@@ -399,7 +428,7 @@ struct samsung_mux_clock exynos5420_mux_clks[] __initdata = {
        MUX(none, "mout_spi2", group2_p, SRC_PERIC1, 28, 3),
 };
 
-struct samsung_div_clock exynos5420_div_clks[] __initdata = {
+static struct samsung_div_clock exynos5420_div_clks[] __initdata = {
        DIV(none, "div_arm", "mout_cpu", DIV_CPU0, 0, 3),
        DIV(none, "sclk_apll", "mout_apll", DIV_CPU0, 24, 3),
        DIV(none, "armclk2", "div_arm", DIV_CPU0, 28, 3),
@@ -479,7 +508,7 @@ struct samsung_div_clock exynos5420_div_clks[] __initdata = {
        DIV(none, "dout_pre_spi2", "dout_spi2", DIV_PERIC4, 24, 8),
 };
 
-struct samsung_gate_clock exynos5420_gate_clks[] __initdata = {
+static struct samsung_gate_clock exynos5420_gate_clks[] __initdata = {
        /* TODO: Re-verify the CG bits for all the gate clocks */
        GATE_A(mct, "pclk_st", "aclk66_psgen", GATE_BUS_PERIS1, 2, 0, 0, "mct"),
 
@@ -698,17 +727,40 @@ struct samsung_gate_clock exynos5420_gate_clks[] __initdata = {
        GATE(smmu_mscl2, "smmu_mscl2", "aclk400_mscl", GATE_IP_MSCL, 10, 0, 0),
 };
 
+struct __initdata samsung_pll_clock exynos5420_plls[nr_plls] = {
+       [apll] = PLL(pll_2550, fout_apll, "fout_apll", "fin_pll", APLL_LOCK,
+               APLL_CON0, NULL),
+       [cpll] = PLL(pll_2550, fout_mpll, "fout_mpll", "fin_pll", MPLL_LOCK,
+               MPLL_CON0, NULL),
+       [dpll] = PLL(pll_2550, fout_dpll, "fout_dpll", "fin_pll", DPLL_LOCK,
+               DPLL_CON0, NULL),
+       [epll] = PLL(pll_2650, fout_epll, "fout_epll", "fin_pll", EPLL_LOCK,
+               EPLL_CON0, NULL),
+       [rpll] = PLL(pll_2650, fout_rpll, "fout_rpll", "fin_pll", RPLL_LOCK,
+               RPLL_CON0, NULL),
+       [ipll] = PLL(pll_2550, fout_ipll, "fout_ipll", "fin_pll", IPLL_LOCK,
+               IPLL_CON0, NULL),
+       [spll] = PLL(pll_2550, fout_spll, "fout_spll", "fin_pll", SPLL_LOCK,
+               SPLL_CON0, NULL),
+       [vpll] = PLL(pll_2550, fout_vpll, "fout_vpll", "fin_pll", VPLL_LOCK,
+               VPLL_CON0, NULL),
+       [mpll] = PLL(pll_2550, fout_mpll, "fout_mpll", "fin_pll", MPLL_LOCK,
+               MPLL_CON0, NULL),
+       [bpll] = PLL(pll_2550, fout_bpll, "fout_bpll", "fin_pll", BPLL_LOCK,
+               BPLL_CON0, NULL),
+       [kpll] = PLL(pll_2550, fout_kpll, "fout_kpll", "fin_pll", KPLL_LOCK,
+               KPLL_CON0, NULL),
+};
+
 static __initdata struct of_device_id ext_clk_match[] = {
        { .compatible = "samsung,exynos5420-oscclk", .data = (void *)0, },
        { },
 };
 
 /* register exynos5420 clocks */
-void __init exynos5420_clk_init(struct device_node *np)
+static void __init exynos5420_clk_init(struct device_node *np)
 {
        void __iomem *reg_base;
-       struct clk *apll, *bpll, *cpll, *dpll, *epll, *ipll, *kpll, *mpll;
-       struct clk *rpll, *spll, *vpll;
 
        if (np) {
                reg_base = of_iomap(np, 0);
@@ -724,30 +776,8 @@ void __init exynos5420_clk_init(struct device_node *np)
        samsung_clk_of_register_fixed_ext(exynos5420_fixed_rate_ext_clks,
                        ARRAY_SIZE(exynos5420_fixed_rate_ext_clks),
                        ext_clk_match);
-
-       apll = samsung_clk_register_pll35xx("fout_apll", "fin_pll",
-                       reg_base + 0x100);
-       bpll = samsung_clk_register_pll35xx("fout_bpll", "fin_pll",
-                       reg_base + 0x20110);
-       cpll = samsung_clk_register_pll35xx("fout_cpll", "fin_pll",
-                       reg_base + 0x10120);
-       dpll = samsung_clk_register_pll35xx("fout_dpll", "fin_pll",
-                       reg_base + 0x10128);
-       epll = samsung_clk_register_pll36xx("fout_epll", "fin_pll",
-                       reg_base + 0x10130);
-       ipll = samsung_clk_register_pll35xx("fout_ipll", "fin_pll",
-                       reg_base + 0x10150);
-       kpll = samsung_clk_register_pll35xx("fout_kpll", "fin_pll",
-                       reg_base + 0x28100);
-       mpll = samsung_clk_register_pll35xx("fout_mpll", "fin_pll",
-                       reg_base + 0x10180);
-       rpll = samsung_clk_register_pll36xx("fout_rpll", "fin_pll",
-                       reg_base + 0x10140);
-       spll = samsung_clk_register_pll35xx("fout_spll", "fin_pll",
-                       reg_base + 0x10160);
-       vpll = samsung_clk_register_pll35xx("fout_vpll", "fin_pll",
-                       reg_base + 0x10170);
-
+       samsung_clk_register_pll(exynos5420_plls, ARRAY_SIZE(exynos5420_plls),
+                                       reg_base);
        samsung_clk_register_fixed_rate(exynos5420_fixed_rate_clks,
                        ARRAY_SIZE(exynos5420_fixed_rate_clks));
        samsung_clk_register_fixed_factor(exynos5420_fixed_factor_clks,
index 7d5434167a96839dc7bb3f0e4fd92c065cdce21e..6d043a285d86447606f1309b9af834ad5df1bd49 100644 (file)
@@ -41,12 +41,12 @@ PNAME(mout_armclk_p)        = { "cplla", "cpllb" };
 PNAME(mout_spi_p)      = { "div125", "div200" };
 
 /* fixed rate clocks generated outside the soc */
-struct samsung_fixed_rate_clock exynos5440_fixed_rate_ext_clks[] __initdata = {
+static struct samsung_fixed_rate_clock exynos5440_fixed_rate_ext_clks[] __initdata = {
        FRATE(none, "xtal", NULL, CLK_IS_ROOT, 0),
 };
 
 /* fixed rate clocks */
-struct samsung_fixed_rate_clock exynos5440_fixed_rate_clks[] __initdata = {
+static struct samsung_fixed_rate_clock exynos5440_fixed_rate_clks[] __initdata = {
        FRATE(none, "ppll", NULL, CLK_IS_ROOT, 1000000000),
        FRATE(none, "usb_phy0", NULL, CLK_IS_ROOT, 60000000),
        FRATE(none, "usb_phy1", NULL, CLK_IS_ROOT, 60000000),
@@ -55,26 +55,26 @@ struct samsung_fixed_rate_clock exynos5440_fixed_rate_clks[] __initdata = {
 };
 
 /* fixed factor clocks */
-struct samsung_fixed_factor_clock exynos5440_fixed_factor_clks[] __initdata = {
+static struct samsung_fixed_factor_clock exynos5440_fixed_factor_clks[] __initdata = {
        FFACTOR(none, "div250", "ppll", 1, 4, 0),
        FFACTOR(none, "div200", "ppll", 1, 5, 0),
        FFACTOR(none, "div125", "div250", 1, 2, 0),
 };
 
 /* mux clocks */
-struct samsung_mux_clock exynos5440_mux_clks[] __initdata = {
+static struct samsung_mux_clock exynos5440_mux_clks[] __initdata = {
        MUX(none, "mout_spi", mout_spi_p, MISC_DOUT1, 5, 1),
        MUX_A(arm_clk, "arm_clk", mout_armclk_p,
                        CPU_CLK_STATUS, 0, 1, "armclk"),
 };
 
 /* divider clocks */
-struct samsung_div_clock exynos5440_div_clks[] __initdata = {
+static struct samsung_div_clock exynos5440_div_clks[] __initdata = {
        DIV(spi_baud, "div_spi", "mout_spi", MISC_DOUT1, 3, 2),
 };
 
 /* gate clocks */
-struct samsung_gate_clock exynos5440_gate_clks[] __initdata = {
+static struct samsung_gate_clock exynos5440_gate_clks[] __initdata = {
        GATE(pb0_250, "pb0_250", "div250", CLKEN_OV_VAL, 3, 0, 0),
        GATE(pr0_250, "pr0_250", "div250", CLKEN_OV_VAL, 4, 0, 0),
        GATE(pr1_250, "pr1_250", "div250", CLKEN_OV_VAL, 5, 0, 0),
@@ -103,7 +103,7 @@ static __initdata struct of_device_id ext_clk_match[] = {
 };
 
 /* register exynos5440 clocks */
-void __init exynos5440_clk_init(struct device_node *np)
+static void __init exynos5440_clk_init(struct device_node *np)
 {
        void __iomem *reg_base;
 
index 698e5621b6e72c2d18f7f0ec6d53ee805c50bc04..077555416ce16f036764825f1580bf4ed78ffd7c 100644 (file)
 #include "clk.h"
 #include "clk-pll.h"
 
+struct samsung_clk_pll {
+       struct clk_hw           hw;
+       void __iomem            *lock_reg;
+       void __iomem            *con_reg;
+       enum samsung_pll_type   type;
+       unsigned int            rate_count;
+       const struct samsung_pll_rate_table *rate_table;
+};
+
+#define to_clk_pll(_hw) container_of(_hw, struct samsung_clk_pll, hw)
+
+static const struct samsung_pll_rate_table *samsung_get_pll_settings(
+                               struct samsung_clk_pll *pll, unsigned long rate)
+{
+       const struct samsung_pll_rate_table  *rate_table = pll->rate_table;
+       int i;
+
+       for (i = 0; i < pll->rate_count; i++) {
+               if (rate == rate_table[i].rate)
+                       return &rate_table[i];
+       }
+
+       return NULL;
+}
+
+static long samsung_pll_round_rate(struct clk_hw *hw,
+                       unsigned long drate, unsigned long *prate)
+{
+       struct samsung_clk_pll *pll = to_clk_pll(hw);
+       const struct samsung_pll_rate_table *rate_table = pll->rate_table;
+       int i;
+
+       /* Assumming rate_table is in descending order */
+       for (i = 0; i < pll->rate_count; i++) {
+               if (drate >= rate_table[i].rate)
+                       return rate_table[i].rate;
+       }
+
+       /* return minimum supported value */
+       return rate_table[i - 1].rate;
+}
+
 /*
  * PLL35xx Clock Type
  */
+/* Maximum lock time can be 270 * PDIV cycles */
+#define PLL35XX_LOCK_FACTOR    (270)
 
 #define PLL35XX_MDIV_MASK       (0x3FF)
 #define PLL35XX_PDIV_MASK       (0x3F)
 #define PLL35XX_SDIV_MASK       (0x7)
+#define PLL35XX_LOCK_STAT_MASK (0x1)
 #define PLL35XX_MDIV_SHIFT      (16)
 #define PLL35XX_PDIV_SHIFT      (8)
 #define PLL35XX_SDIV_SHIFT      (0)
-
-struct samsung_clk_pll35xx {
-       struct clk_hw           hw;
-       const void __iomem      *con_reg;
-};
-
-#define to_clk_pll35xx(_hw) container_of(_hw, struct samsung_clk_pll35xx, hw)
+#define PLL35XX_LOCK_STAT_SHIFT        (29)
 
 static unsigned long samsung_pll35xx_recalc_rate(struct clk_hw *hw,
                                unsigned long parent_rate)
 {
-       struct samsung_clk_pll35xx *pll = to_clk_pll35xx(hw);
+       struct samsung_clk_pll *pll = to_clk_pll(hw);
        u32 mdiv, pdiv, sdiv, pll_con;
        u64 fvco = parent_rate;
 
@@ -49,48 +88,80 @@ static unsigned long samsung_pll35xx_recalc_rate(struct clk_hw *hw,
        return (unsigned long)fvco;
 }
 
-static const struct clk_ops samsung_pll35xx_clk_ops = {
-       .recalc_rate = samsung_pll35xx_recalc_rate,
-};
-
-struct clk * __init samsung_clk_register_pll35xx(const char *name,
-                       const char *pname, const void __iomem *con_reg)
+static inline bool samsung_pll35xx_mp_change(
+               const struct samsung_pll_rate_table *rate, u32 pll_con)
 {
-       struct samsung_clk_pll35xx *pll;
-       struct clk *clk;
-       struct clk_init_data init;
+       u32 old_mdiv, old_pdiv;
 
-       pll = kzalloc(sizeof(*pll), GFP_KERNEL);
-       if (!pll) {
-               pr_err("%s: could not allocate pll clk %s\n", __func__, name);
-               return NULL;
+       old_mdiv = (pll_con >> PLL35XX_MDIV_SHIFT) & PLL35XX_MDIV_MASK;
+       old_pdiv = (pll_con >> PLL35XX_PDIV_SHIFT) & PLL35XX_PDIV_MASK;
+
+       return (rate->mdiv != old_mdiv || rate->pdiv != old_pdiv);
+}
+
+static int samsung_pll35xx_set_rate(struct clk_hw *hw, unsigned long drate,
+                                       unsigned long prate)
+{
+       struct samsung_clk_pll *pll = to_clk_pll(hw);
+       const struct samsung_pll_rate_table *rate;
+       u32 tmp;
+
+       /* Get required rate settings from table */
+       rate = samsung_get_pll_settings(pll, drate);
+       if (!rate) {
+               pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__,
+                       drate, __clk_get_name(hw->clk));
+               return -EINVAL;
        }
 
-       init.name = name;
-       init.ops = &samsung_pll35xx_clk_ops;
-       init.flags = CLK_GET_RATE_NOCACHE;
-       init.parent_names = &pname;
-       init.num_parents = 1;
+       tmp = __raw_readl(pll->con_reg);
 
-       pll->hw.init = &init;
-       pll->con_reg = con_reg;
+       if (!(samsung_pll35xx_mp_change(rate, tmp))) {
+               /* If only s change, change just s value only*/
+               tmp &= ~(PLL35XX_SDIV_MASK << PLL35XX_SDIV_SHIFT);
+               tmp |= rate->sdiv << PLL35XX_SDIV_SHIFT;
+               __raw_writel(tmp, pll->con_reg);
 
-       clk = clk_register(NULL, &pll->hw);
-       if (IS_ERR(clk)) {
-               pr_err("%s: failed to register pll clock %s\n", __func__,
-                               name);
-               kfree(pll);
+               return 0;
        }
 
-       if (clk_register_clkdev(clk, name, NULL))
-               pr_err("%s: failed to register lookup for %s", __func__, name);
-
-       return clk;
+       /* Set PLL lock time. */
+       __raw_writel(rate->pdiv * PLL35XX_LOCK_FACTOR,
+                       pll->lock_reg);
+
+       /* Change PLL PMS values */
+       tmp &= ~((PLL35XX_MDIV_MASK << PLL35XX_MDIV_SHIFT) |
+                       (PLL35XX_PDIV_MASK << PLL35XX_PDIV_SHIFT) |
+                       (PLL35XX_SDIV_MASK << PLL35XX_SDIV_SHIFT));
+       tmp |= (rate->mdiv << PLL35XX_MDIV_SHIFT) |
+                       (rate->pdiv << PLL35XX_PDIV_SHIFT) |
+                       (rate->sdiv << PLL35XX_SDIV_SHIFT);
+       __raw_writel(tmp, pll->con_reg);
+
+       /* wait_lock_time */
+       do {
+               cpu_relax();
+               tmp = __raw_readl(pll->con_reg);
+       } while (!(tmp & (PLL35XX_LOCK_STAT_MASK
+                               << PLL35XX_LOCK_STAT_SHIFT)));
+       return 0;
 }
 
+static const struct clk_ops samsung_pll35xx_clk_ops = {
+       .recalc_rate = samsung_pll35xx_recalc_rate,
+       .round_rate = samsung_pll_round_rate,
+       .set_rate = samsung_pll35xx_set_rate,
+};
+
+static const struct clk_ops samsung_pll35xx_clk_min_ops = {
+       .recalc_rate = samsung_pll35xx_recalc_rate,
+};
+
 /*
  * PLL36xx Clock Type
  */
+/* Maximum lock time can be 3000 * PDIV cycles */
+#define PLL36XX_LOCK_FACTOR    (3000)
 
 #define PLL36XX_KDIV_MASK      (0xFFFF)
 #define PLL36XX_MDIV_MASK      (0x1FF)
@@ -99,18 +170,13 @@ struct clk * __init samsung_clk_register_pll35xx(const char *name,
 #define PLL36XX_MDIV_SHIFT     (16)
 #define PLL36XX_PDIV_SHIFT     (8)
 #define PLL36XX_SDIV_SHIFT     (0)
-
-struct samsung_clk_pll36xx {
-       struct clk_hw           hw;
-       const void __iomem      *con_reg;
-};
-
-#define to_clk_pll36xx(_hw) container_of(_hw, struct samsung_clk_pll36xx, hw)
+#define PLL36XX_KDIV_SHIFT     (0)
+#define PLL36XX_LOCK_STAT_SHIFT        (29)
 
 static unsigned long samsung_pll36xx_recalc_rate(struct clk_hw *hw,
                                unsigned long parent_rate)
 {
-       struct samsung_clk_pll36xx *pll = to_clk_pll36xx(hw);
+       struct samsung_clk_pll *pll = to_clk_pll(hw);
        u32 mdiv, pdiv, sdiv, pll_con0, pll_con1;
        s16 kdiv;
        u64 fvco = parent_rate;
@@ -129,45 +195,80 @@ static unsigned long samsung_pll36xx_recalc_rate(struct clk_hw *hw,
        return (unsigned long)fvco;
 }
 
-static const struct clk_ops samsung_pll36xx_clk_ops = {
-       .recalc_rate = samsung_pll36xx_recalc_rate,
-};
-
-struct clk * __init samsung_clk_register_pll36xx(const char *name,
-                       const char *pname, const void __iomem *con_reg)
+static inline bool samsung_pll36xx_mpk_change(
+       const struct samsung_pll_rate_table *rate, u32 pll_con0, u32 pll_con1)
 {
-       struct samsung_clk_pll36xx *pll;
-       struct clk *clk;
-       struct clk_init_data init;
+       u32 old_mdiv, old_pdiv, old_kdiv;
 
-       pll = kzalloc(sizeof(*pll), GFP_KERNEL);
-       if (!pll) {
-               pr_err("%s: could not allocate pll clk %s\n", __func__, name);
-               return NULL;
+       old_mdiv = (pll_con0 >> PLL36XX_MDIV_SHIFT) & PLL36XX_MDIV_MASK;
+       old_pdiv = (pll_con0 >> PLL36XX_PDIV_SHIFT) & PLL36XX_PDIV_MASK;
+       old_kdiv = (pll_con1 >> PLL36XX_KDIV_SHIFT) & PLL36XX_KDIV_MASK;
+
+       return (rate->mdiv != old_mdiv || rate->pdiv != old_pdiv ||
+               rate->kdiv != old_kdiv);
+}
+
+static int samsung_pll36xx_set_rate(struct clk_hw *hw, unsigned long drate,
+                                       unsigned long parent_rate)
+{
+       struct samsung_clk_pll *pll = to_clk_pll(hw);
+       u32 tmp, pll_con0, pll_con1;
+       const struct samsung_pll_rate_table *rate;
+
+       rate = samsung_get_pll_settings(pll, drate);
+       if (!rate) {
+               pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__,
+                       drate, __clk_get_name(hw->clk));
+               return -EINVAL;
        }
 
-       init.name = name;
-       init.ops = &samsung_pll36xx_clk_ops;
-       init.flags = CLK_GET_RATE_NOCACHE;
-       init.parent_names = &pname;
-       init.num_parents = 1;
+       pll_con0 = __raw_readl(pll->con_reg);
+       pll_con1 = __raw_readl(pll->con_reg + 4);
 
-       pll->hw.init = &init;
-       pll->con_reg = con_reg;
+       if (!(samsung_pll36xx_mpk_change(rate, pll_con0, pll_con1))) {
+               /* If only s change, change just s value only*/
+               pll_con0 &= ~(PLL36XX_SDIV_MASK << PLL36XX_SDIV_SHIFT);
+               pll_con0 |= (rate->sdiv << PLL36XX_SDIV_SHIFT);
+               __raw_writel(pll_con0, pll->con_reg);
 
-       clk = clk_register(NULL, &pll->hw);
-       if (IS_ERR(clk)) {
-               pr_err("%s: failed to register pll clock %s\n", __func__,
-                               name);
-               kfree(pll);
+               return 0;
        }
 
-       if (clk_register_clkdev(clk, name, NULL))
-               pr_err("%s: failed to register lookup for %s", __func__, name);
-
-       return clk;
+       /* Set PLL lock time. */
+       __raw_writel(rate->pdiv * PLL36XX_LOCK_FACTOR, pll->lock_reg);
+
+        /* Change PLL PMS values */
+       pll_con0 &= ~((PLL36XX_MDIV_MASK << PLL36XX_MDIV_SHIFT) |
+                       (PLL36XX_PDIV_MASK << PLL36XX_PDIV_SHIFT) |
+                       (PLL36XX_SDIV_MASK << PLL36XX_SDIV_SHIFT));
+       pll_con0 |= (rate->mdiv << PLL36XX_MDIV_SHIFT) |
+                       (rate->pdiv << PLL36XX_PDIV_SHIFT) |
+                       (rate->sdiv << PLL36XX_SDIV_SHIFT);
+       __raw_writel(pll_con0, pll->con_reg);
+
+       pll_con1 &= ~(PLL36XX_KDIV_MASK << PLL36XX_KDIV_SHIFT);
+       pll_con1 |= rate->kdiv << PLL36XX_KDIV_SHIFT;
+       __raw_writel(pll_con1, pll->con_reg + 4);
+
+       /* wait_lock_time */
+       do {
+               cpu_relax();
+               tmp = __raw_readl(pll->con_reg);
+       } while (!(tmp & (1 << PLL36XX_LOCK_STAT_SHIFT)));
+
+       return 0;
 }
 
+static const struct clk_ops samsung_pll36xx_clk_ops = {
+       .recalc_rate = samsung_pll36xx_recalc_rate,
+       .set_rate = samsung_pll36xx_set_rate,
+       .round_rate = samsung_pll_round_rate,
+};
+
+static const struct clk_ops samsung_pll36xx_clk_min_ops = {
+       .recalc_rate = samsung_pll36xx_recalc_rate,
+};
+
 /*
  * PLL45xx Clock Type
  */
@@ -578,3 +679,93 @@ struct clk * __init samsung_clk_register_pll2550x(const char *name,
 
        return clk;
 }
+
+static void __init _samsung_clk_register_pll(struct samsung_pll_clock *pll_clk,
+                                               void __iomem *base)
+{
+       struct samsung_clk_pll *pll;
+       struct clk *clk;
+       struct clk_init_data init;
+       int ret, len;
+
+       pll = kzalloc(sizeof(*pll), GFP_KERNEL);
+       if (!pll) {
+               pr_err("%s: could not allocate pll clk %s\n",
+                       __func__, pll_clk->name);
+               return;
+       }
+
+       init.name = pll_clk->name;
+       init.flags = pll_clk->flags;
+       init.parent_names = &pll_clk->parent_name;
+       init.num_parents = 1;
+
+       if (pll_clk->rate_table) {
+               /* find count of rates in rate_table */
+               for (len = 0; pll_clk->rate_table[len].rate != 0; )
+                       len++;
+
+               pll->rate_count = len;
+               pll->rate_table = kmemdup(pll_clk->rate_table,
+                                       pll->rate_count *
+                                       sizeof(struct samsung_pll_rate_table),
+                                       GFP_KERNEL);
+               WARN(!pll->rate_table,
+                       "%s: could not allocate rate table for %s\n",
+                       __func__, pll_clk->name);
+       }
+
+       switch (pll_clk->type) {
+       /* clk_ops for 35xx and 2550 are similar */
+       case pll_35xx:
+       case pll_2550:
+               if (!pll->rate_table)
+                       init.ops = &samsung_pll35xx_clk_min_ops;
+               else
+                       init.ops = &samsung_pll35xx_clk_ops;
+               break;
+       /* clk_ops for 36xx and 2650 are similar */
+       case pll_36xx:
+       case pll_2650:
+               if (!pll->rate_table)
+                       init.ops = &samsung_pll36xx_clk_min_ops;
+               else
+                       init.ops = &samsung_pll36xx_clk_ops;
+               break;
+       default:
+               pr_warn("%s: Unknown pll type for pll clk %s\n",
+                       __func__, pll_clk->name);
+       }
+
+       pll->hw.init = &init;
+       pll->type = pll_clk->type;
+       pll->lock_reg = base + pll_clk->lock_offset;
+       pll->con_reg = base + pll_clk->con_offset;
+
+       clk = clk_register(NULL, &pll->hw);
+       if (IS_ERR(clk)) {
+               pr_err("%s: failed to register pll clock %s : %ld\n",
+                       __func__, pll_clk->name, PTR_ERR(clk));
+               kfree(pll);
+               return;
+       }
+
+       samsung_clk_add_lookup(clk, pll_clk->id);
+
+       if (!pll_clk->alias)
+               return;
+
+       ret = clk_register_clkdev(clk, pll_clk->alias, pll_clk->dev_name);
+       if (ret)
+               pr_err("%s: failed to register lookup for %s : %d",
+                       __func__, pll_clk->name, ret);
+}
+
+void __init samsung_clk_register_pll(struct samsung_pll_clock *pll_list,
+                               unsigned int nr_pll, void __iomem *base)
+{
+       int cnt;
+
+       for (cnt = 0; cnt < nr_pll; cnt++)
+               _samsung_clk_register_pll(&pll_list[cnt], base);
+}
index 1d68a68d6c62666acf8aec5ed2e41c9b16d0e416..2f70e88d61047eb2983af8ecd8856da37eb7c350 100644 (file)
 #ifndef __SAMSUNG_CLK_PLL_H
 #define __SAMSUNG_CLK_PLL_H
 
+enum samsung_pll_type {
+       pll_35xx,
+       pll_36xx,
+       pll_2550,
+       pll_2650,
+};
+
+#define PLL_35XX_RATE(_rate, _m, _p, _s)                       \
+       {                                                       \
+               .rate   =       (_rate),                                \
+               .mdiv   =       (_m),                           \
+               .pdiv   =       (_p),                           \
+               .sdiv   =       (_s),                           \
+       }
+
+#define PLL_36XX_RATE(_rate, _m, _p, _s, _k)                   \
+       {                                                       \
+               .rate   =       (_rate),                                \
+               .mdiv   =       (_m),                           \
+               .pdiv   =       (_p),                           \
+               .sdiv   =       (_s),                           \
+               .kdiv   =       (_k),                           \
+       }
+
+/* NOTE: Rate table should be kept sorted in descending order. */
+
+struct samsung_pll_rate_table {
+       unsigned int rate;
+       unsigned int pdiv;
+       unsigned int mdiv;
+       unsigned int sdiv;
+       unsigned int kdiv;
+};
+
 enum pll45xx_type {
        pll_4500,
        pll_4502,
@@ -24,10 +58,6 @@ enum pll46xx_type {
        pll_4650c,
 };
 
-extern struct clk * __init samsung_clk_register_pll35xx(const char *name,
-                       const char *pname, const void __iomem *con_reg);
-extern struct clk * __init samsung_clk_register_pll36xx(const char *name,
-                       const char *pname, const void __iomem *con_reg);
 extern struct clk * __init samsung_clk_register_pll45xx(const char *name,
                        const char *pname, const void __iomem *con_reg,
                        enum pll45xx_type type);
index 2f7dba20ced8b9145f261b817be65387f3048662..e7dfccb5d98167f78e5d79163c7f83503cf5924f 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/clk-provider.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
+#include "clk-pll.h"
 
 /**
  * struct samsung_clock_alias: information about mux clock
@@ -39,6 +40,8 @@ struct samsung_clock_alias {
                .alias          = a,                            \
        }
 
+#define MHZ (1000 * 1000)
+
 /**
  * struct samsung_fixed_rate_clock: information about fixed-rate clock
  * @id: platform specific id of the clock.
@@ -261,6 +264,54 @@ struct samsung_clk_reg_dump {
        u32     value;
 };
 
+/**
+ * struct samsung_pll_clock: information about pll clock
+ * @id: platform specific id of the clock.
+ * @dev_name: name of the device to which this clock belongs.
+ * @name: name of this pll clock.
+ * @parent_name: name of the parent clock.
+ * @flags: optional flags for basic clock.
+ * @con_offset: offset of the register for configuring the PLL.
+ * @lock_offset: offset of the register for locking the PLL.
+ * @type: Type of PLL to be registered.
+ * @alias: optional clock alias name to be assigned to this clock.
+ */
+struct samsung_pll_clock {
+       unsigned int            id;
+       const char              *dev_name;
+       const char              *name;
+       const char              *parent_name;
+       unsigned long           flags;
+       int                     con_offset;
+       int                     lock_offset;
+       enum samsung_pll_type   type;
+       const struct samsung_pll_rate_table *rate_table;
+       const char              *alias;
+};
+
+#define __PLL(_typ, _id, _dname, _name, _pname, _flags, _lock, _con,   \
+               _rtable, _alias)                                        \
+       {                                                               \
+               .id             = _id,                                  \
+               .type           = _typ,                                 \
+               .dev_name       = _dname,                               \
+               .name           = _name,                                \
+               .parent_name    = _pname,                               \
+               .flags          = CLK_GET_RATE_NOCACHE,                 \
+               .con_offset     = _con,                                 \
+               .lock_offset    = _lock,                                \
+               .rate_table     = _rtable,                              \
+               .alias          = _alias,                               \
+       }
+
+#define PLL(_typ, _id, _name, _pname, _lock, _con, _rtable)    \
+       __PLL(_typ, _id, NULL, _name, _pname, CLK_GET_RATE_NOCACHE,     \
+               _lock, _con, _rtable, _name)
+
+#define PLL_A(_typ, _id, _name, _pname, _lock, _con, _alias, _rtable) \
+       __PLL(_typ, _id, NULL, _name, _pname, CLK_GET_RATE_NOCACHE,     \
+               _lock, _con, _rtable, _alias)
+
 extern void __init samsung_clk_init(struct device_node *np, void __iomem *base,
                unsigned long nr_clks, unsigned long *rdump,
                unsigned long nr_rdump, unsigned long *soc_rdump,
@@ -284,6 +335,8 @@ extern void __init samsung_clk_register_div(struct samsung_div_clock *clk_list,
                unsigned int nr_clk);
 extern void __init samsung_clk_register_gate(
                struct samsung_gate_clock *clk_list, unsigned int nr_clk);
+extern void __init samsung_clk_register_pll(struct samsung_pll_clock *pll_list,
+               unsigned int nr_clk, void __iomem *base);
 
 extern unsigned long _get_rate(const char *clk_name);