Merge tag 'clk-for-linus' of git://git.linaro.org/people/mturquette/linux
authorLinus Torvalds <torvalds@linux-foundation.org>
Wed, 20 Feb 2013 19:02:10 +0000 (11:02 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Wed, 20 Feb 2013 19:02:10 +0000 (11:02 -0800)
Pull clock framework update from Michael Turquette:
 "The common clock framework changes for 3.9 are almost entirely fixes.

  None are dire enough to be Cc'd to stable which may be interpreted to
  mean that users of the framework are reaching stability.  Lots of new
  adoption of this framework is via DeviceTree data and that comes
  through the respective architecture and platform trees instead of
  through the clk framework tree.

  Two new features are improved debugfs output and an improvement to how
  DT clocks are initialized by reusing a common method."

* tag 'clk-for-linus' of git://git.linaro.org/people/mturquette/linux: (25 commits)
  clk: sunxi: remove stale Makefile entry
  clk: vexpress: Use common of_clk_init() function
  clk: zynq: Use common of_clk_init() function
  clk: vt8500: Use common of_clk_init() function
  clk: highbank: Use common of_clk_init() function
  clk: sunxi: Use common of_clk_init() function
  clk: add common of_clk_init() function
  clk: Deduplicate exit code in clk_set_rate
  clk: beautify Makefile
  clk-divider: fix macros
  clk: prima2: enable dt-binding clkdev mapping
  clk: mxs: Index is always positive
  clk: max77686: Avoid double free at remove time
  clk: remove exported function from __init section
  clk: vt8500: Add support for WM8750/WM8850 PLL clocks
  clk: vt8500: Fix division-by-0 when requested rate=0
  clk: vt8500: Fix device clock divisor calculations
  clk: vt8500: Fix error in PLL calculations on non-exact match.
  clk: max77686: Remove unnecessary NULL checking for container_of()
  clk: JSON debugfs clock tree summary
  ...

23 files changed:
Documentation/devicetree/bindings/clock/prima2-clock.txt [new file with mode: 0644]
arch/arm/boot/dts/prima2.dtsi
arch/arm/mach-highbank/core.h
arch/arm/mach-highbank/highbank.c
drivers/clk/Makefile
drivers/clk/clk-divider.c
drivers/clk/clk-fixed-factor.c
drivers/clk/clk-fixed-rate.c
drivers/clk/clk-highbank.c
drivers/clk/clk-max77686.c
drivers/clk/clk-prima2.c
drivers/clk/clk-sunxi.c [deleted file]
drivers/clk/clk-vt8500.c
drivers/clk/clk-zynq.c
drivers/clk/clk.c
drivers/clk/mxs/clk-imx23.c
drivers/clk/mxs/clk-imx28.c
drivers/clk/versatile/clk-vexpress-osc.c
drivers/clk/versatile/clk-vexpress.c
drivers/clocksource/sunxi_timer.c
include/asm-generic/vmlinux.lds.h
include/linux/clk-provider.h
include/linux/clk/sunxi.h [deleted file]

diff --git a/Documentation/devicetree/bindings/clock/prima2-clock.txt b/Documentation/devicetree/bindings/clock/prima2-clock.txt
new file mode 100644 (file)
index 0000000..5016979
--- /dev/null
@@ -0,0 +1,73 @@
+* Clock bindings for CSR SiRFprimaII
+
+Required properties:
+- compatible: Should be "sirf,prima2-clkc"
+- reg: Address and length of the register set
+- interrupts: Should contain clock controller interrupt
+- #clock-cells: Should be <1>
+
+The clock consumer should specify the desired clock by having the clock
+ID in its "clocks" phandle cell.  The following is a full list of prima2
+clocks and IDs.
+
+       Clock                   ID
+       ---------------------------
+       rtc                     0
+       osc                     1
+       pll1                    2
+       pll2                    3
+       pll3                    4
+       mem                     5
+       sys                     6
+       security                7
+       dsp                     8
+       gps                     9
+       mf                      10
+       io                      11
+       cpu                     12
+       uart0                   13
+       uart1                   14
+       uart2                   15
+       tsc                     16
+       i2c0                    17
+       i2c1                    18
+       spi0                    19
+       spi1                    20
+       pwmc                    21
+       efuse                   22
+       pulse                   23
+       dmac0                   24
+       dmac1                   25
+       nand                    26
+       audio                   27
+       usp0                    28
+       usp1                    29
+       usp2                    30
+       vip                     31
+       gfx                     32
+       mm                      33
+       lcd                     34
+       vpp                     35
+       mmc01                   36
+       mmc23                   37
+       mmc45                   38
+       usbpll                  39
+       usb0                    40
+       usb1                    41
+
+Examples:
+
+clks: clock-controller@88000000 {
+       compatible = "sirf,prima2-clkc";
+       reg = <0x88000000 0x1000>;
+       interrupts = <3>;
+       #clock-cells = <1>;
+};
+
+i2c0: i2c@b00e0000 {
+       cell-index = <0>;
+       compatible = "sirf,prima2-i2c";
+       reg = <0xb00e0000 0x10000>;
+       interrupts = <24>;
+       clocks = <&clks 17>;
+};
index 055fca542120bec47b150430144145d9b9c2a46f..3329719a9412b75c87a754cfdb10877c077bf206 100644 (file)
                        #size-cells = <1>;
                        ranges = <0x88000000 0x88000000 0x40000>;
 
-                       clock-controller@88000000 {
+                       clks: clock-controller@88000000 {
                                compatible = "sirf,prima2-clkc";
                                reg = <0x88000000 0x1000>;
                                interrupts = <3>;
+                               #clock-cells = <1>;
                        };
 
                        reset-controller@88010000 {
@@ -85,6 +86,7 @@
                                compatible = "sirf,prima2-memc";
                                reg = <0x90000000 0x10000>;
                                interrupts = <27>;
+                               clocks = <&clks 5>;
                        };
                };
 
                                compatible = "sirf,prima2-vpp";
                                reg = <0x90020000 0x10000>;
                                interrupts = <31>;
+                               clocks = <&clks 35>;
                        };
                };
 
                                compatible = "powervr,sgx531";
                                reg = <0x98000000 0x8000000>;
                                interrupts = <6>;
+                               clocks = <&clks 32>;
                        };
                };
 
                                compatible = "sirf,prima2-video-codec";
                                reg = <0xa0000000 0x8000000>;
                                interrupts = <5>;
+                               clocks = <&clks 33>;
                        };
                };
 
                                compatible = "sirf,prima2-gps";
                                reg = <0xa8010000 0x10000>;
                                interrupts = <7>;
+                               clocks = <&clks 9>;
                        };
 
                        dsp@a9000000 {
                                compatible = "sirf,prima2-dsp";
                                reg = <0xa9000000 0x1000000>;
                                interrupts = <8>;
+                               clocks = <&clks 8>;
                        };
                };
 
                                compatible = "sirf,prima2-nand";
                                reg = <0xb0030000 0x10000>;
                                interrupts = <41>;
+                               clocks = <&clks 26>;
                        };
 
                        audio@b0040000 {
                                compatible = "sirf,prima2-audio";
                                reg = <0xb0040000 0x10000>;
                                interrupts = <35>;
+                               clocks = <&clks 27>;
                        };
 
                        uart0: uart@b0050000 {
                                compatible = "sirf,prima2-uart";
                                reg = <0xb0050000 0x10000>;
                                interrupts = <17>;
+                               clocks = <&clks 13>;
                        };
 
                        uart1: uart@b0060000 {
                                compatible = "sirf,prima2-uart";
                                reg = <0xb0060000 0x10000>;
                                interrupts = <18>;
+                               clocks = <&clks 14>;
                        };
 
                        uart2: uart@b0070000 {
                                compatible = "sirf,prima2-uart";
                                reg = <0xb0070000 0x10000>;
                                interrupts = <19>;
+                               clocks = <&clks 15>;
                        };
 
                        usp0: usp@b0080000 {
                                compatible = "sirf,prima2-usp";
                                reg = <0xb0080000 0x10000>;
                                interrupts = <20>;
+                               clocks = <&clks 28>;
                        };
 
                        usp1: usp@b0090000 {
                                compatible = "sirf,prima2-usp";
                                reg = <0xb0090000 0x10000>;
                                interrupts = <21>;
+                               clocks = <&clks 29>;
                        };
 
                        usp2: usp@b00a0000 {
                                compatible = "sirf,prima2-usp";
                                reg = <0xb00a0000 0x10000>;
                                interrupts = <22>;
+                               clocks = <&clks 30>;
                        };
 
                        dmac0: dma-controller@b00b0000 {
                                compatible = "sirf,prima2-dmac";
                                reg = <0xb00b0000 0x10000>;
                                interrupts = <12>;
+                               clocks = <&clks 24>;
                        };
 
                        dmac1: dma-controller@b0160000 {
                                compatible = "sirf,prima2-dmac";
                                reg = <0xb0160000 0x10000>;
                                interrupts = <13>;
+                               clocks = <&clks 25>;
                        };
 
                        vip@b00C0000 {
                                compatible = "sirf,prima2-vip";
                                reg = <0xb00C0000 0x10000>;
+                               clocks = <&clks 31>;
                        };
 
                        spi0: spi@b00d0000 {
                                compatible = "sirf,prima2-spi";
                                reg = <0xb00d0000 0x10000>;
                                interrupts = <15>;
+                               clocks = <&clks 19>;
                        };
 
                        spi1: spi@b0170000 {
                                compatible = "sirf,prima2-spi";
                                reg = <0xb0170000 0x10000>;
                                interrupts = <16>;
+                               clocks = <&clks 20>;
                        };
 
                        i2c0: i2c@b00e0000 {
                                compatible = "sirf,prima2-i2c";
                                reg = <0xb00e0000 0x10000>;
                                interrupts = <24>;
+                               clocks = <&clks 17>;
                        };
 
                        i2c1: i2c@b00f0000 {
                                compatible = "sirf,prima2-i2c";
                                reg = <0xb00f0000 0x10000>;
                                interrupts = <25>;
+                               clocks = <&clks 18>;
                        };
 
                        tsc@b0110000 {
                                compatible = "sirf,prima2-tsc";
                                reg = <0xb0110000 0x10000>;
                                interrupts = <33>;
+                               clocks = <&clks 16>;
                        };
 
                        gpio: pinctrl@b0120000 {
                        pwm@b0130000 {
                                compatible = "sirf,prima2-pwm";
                                reg = <0xb0130000 0x10000>;
+                               clocks = <&clks 21>;
                        };
 
                        efusesys@b0140000 {
                                compatible = "sirf,prima2-efuse";
                                reg = <0xb0140000 0x10000>;
+                               clocks = <&clks 22>;
                        };
 
                        pulsec@b0150000 {
                                compatible = "sirf,prima2-pulsec";
                                reg = <0xb0150000 0x10000>;
                                interrupts = <48>;
+                               clocks = <&clks 23>;
                        };
 
                        pci-iobg {
                                compatible = "chipidea,ci13611a-prima2";
                                reg = <0xb8000000 0x10000>;
                                interrupts = <10>;
+                               clocks = <&clks 40>;
                        };
 
                        usb1: usb@b00f0000 {
                                compatible = "chipidea,ci13611a-prima2";
                                reg = <0xb8010000 0x10000>;
                                interrupts = <11>;
+                               clocks = <&clks 41>;
                        };
 
                        sata@b00f0000 {
                                compatible = "sirf,prima2-security";
                                reg = <0xb8030000 0x10000>;
                                interrupts = <42>;
+                               clocks = <&clks 7>;
                        };
                };
        };
index 80235b46cb58e92572de427737b941f3542a69d8..3f65206a9b92aa360b4961fee853f851e5cfbd3b 100644 (file)
@@ -2,7 +2,6 @@
 #define __HIGHBANK_CORE_H
 
 extern void highbank_set_cpu_jump(int cpu, void *jump_addr);
-extern void highbank_clocks_init(void);
 extern void highbank_restart(char, const char *);
 extern void __iomem *scu_base_addr;
 
index e6c06128293962b24adbe84892e19d4a876ff373..65656ff0eb339c10d581196f0580420c8ba3c7bc 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/of_address.h>
 #include <linux/smp.h>
 #include <linux/amba/bus.h>
+#include <linux/clk-provider.h>
 
 #include <asm/arch_timer.h>
 #include <asm/cacheflush.h>
@@ -117,7 +118,7 @@ static void __init highbank_timer_init(void)
        WARN_ON(!timer_base);
        irq = irq_of_parse_and_map(np, 0);
 
-       highbank_clocks_init();
+       of_clk_init(NULL);
        lookup.clk = of_clk_get(np, 0);
        clkdev_add(&lookup);
 
index ee90e87e7675859e4ae80cf0587191732e8b6541..0ad642fbe7946a3e4c96ae8a6694d0d73b97b935 100644 (file)
@@ -1,8 +1,13 @@
 # common clock types
 obj-$(CONFIG_HAVE_CLK)         += clk-devres.o
 obj-$(CONFIG_CLKDEV_LOOKUP)    += clkdev.o
-obj-$(CONFIG_COMMON_CLK)       += clk.o clk-fixed-rate.o clk-gate.o \
-                                  clk-mux.o clk-divider.o clk-fixed-factor.o
+obj-$(CONFIG_COMMON_CLK)       += clk.o
+obj-$(CONFIG_COMMON_CLK)       += clk-divider.o
+obj-$(CONFIG_COMMON_CLK)       += clk-fixed-factor.o
+obj-$(CONFIG_COMMON_CLK)       += clk-fixed-rate.o
+obj-$(CONFIG_COMMON_CLK)       += clk-gate.o
+obj-$(CONFIG_COMMON_CLK)       += clk-mux.o
+
 # SoCs specific
 obj-$(CONFIG_ARCH_BCM2835)     += clk-bcm2835.o
 obj-$(CONFIG_ARCH_NOMADIK)     += clk-nomadik.o
@@ -20,7 +25,6 @@ endif
 obj-$(CONFIG_MACH_LOONGSON1)   += clk-ls1x.o
 obj-$(CONFIG_ARCH_U8500)       += ux500/
 obj-$(CONFIG_ARCH_VT8500)      += clk-vt8500.o
-obj-$(CONFIG_ARCH_SUNXI)       += clk-sunxi.o
 obj-$(CONFIG_ARCH_ZYNQ)                += clk-zynq.o
 
 # Chip specific
index a9204c69148d6057faee157367b860a451958d68..68b402101170f48c2e0ecda98c38f018247c1946 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/io.h>
 #include <linux/err.h>
 #include <linux/string.h>
+#include <linux/log2.h>
 
 /*
  * DOC: basic adjustable divider clock that cannot gate
@@ -29,8 +30,7 @@
 
 #define to_clk_divider(_hw) container_of(_hw, struct clk_divider, hw)
 
-#define div_mask(d)    ((1 << (d->width)) - 1)
-#define is_power_of_two(i)     !(i & ~i)
+#define div_mask(d)    ((1 << ((d)->width)) - 1)
 
 static unsigned int _get_table_maxdiv(const struct clk_div_table *table)
 {
@@ -137,7 +137,7 @@ static bool _is_valid_table_div(const struct clk_div_table *table,
 static bool _is_valid_div(struct clk_divider *divider, unsigned int div)
 {
        if (divider->flags & CLK_DIVIDER_POWER_OF_TWO)
-               return is_power_of_two(div);
+               return is_power_of_2(div);
        if (divider->table)
                return _is_valid_table_div(divider->table, div);
        return true;
index a4899855c0f675bcc87a37adb40a56d6ae2b609b..1ef271e47594a318b04f5860ac03244e969df5aa 100644 (file)
@@ -28,8 +28,11 @@ static unsigned long clk_factor_recalc_rate(struct clk_hw *hw,
                unsigned long parent_rate)
 {
        struct clk_fixed_factor *fix = to_clk_fixed_factor(hw);
+       unsigned long long int rate;
 
-       return parent_rate * fix->mult / fix->div;
+       rate = (unsigned long long int)parent_rate * fix->mult;
+       do_div(rate, fix->div);
+       return (unsigned long)rate;
 }
 
 static long clk_factor_round_rate(struct clk_hw *hw, unsigned long rate,
index af78ed6b67ef36ea32438096df6121218c94d44e..dc58fbd8516f6e377472e962f3090cf06b299a8d 100644 (file)
@@ -85,7 +85,7 @@ struct clk *clk_register_fixed_rate(struct device *dev, const char *name,
 /**
  * of_fixed_clk_setup() - Setup function for simple fixed rate clock
  */
-void __init of_fixed_clk_setup(struct device_node *node)
+void of_fixed_clk_setup(struct device_node *node)
 {
        struct clk *clk;
        const char *clk_name = node->name;
@@ -101,4 +101,5 @@ void __init of_fixed_clk_setup(struct device_node *node)
                of_clk_add_provider(node, of_clk_src_simple_get, clk);
 }
 EXPORT_SYMBOL_GPL(of_fixed_clk_setup);
+CLK_OF_DECLARE(fixed_clk, "fixed-clock", of_fixed_clk_setup);
 #endif
index 52fecadf004a11c2fb597d90ad39d9ef4c9342ab..5d1de2e117535820211eac32df13673dea0b81b7 100644 (file)
@@ -314,33 +314,23 @@ static void __init hb_pll_init(struct device_node *node)
 {
        hb_clk_init(node, &clk_pll_ops);
 }
+CLK_OF_DECLARE(hb_pll, "calxeda,hb-pll-clock", hb_pll_init);
 
 static void __init hb_a9periph_init(struct device_node *node)
 {
        hb_clk_init(node, &a9periphclk_ops);
 }
+CLK_OF_DECLARE(hb_a9periph, "calxeda,hb-a9periph-clock", hb_a9periph_init);
 
 static void __init hb_a9bus_init(struct device_node *node)
 {
        struct clk *clk = hb_clk_init(node, &a9bclk_ops);
        clk_prepare_enable(clk);
 }
+CLK_OF_DECLARE(hb_a9bus, "calxeda,hb-a9bus-clock", hb_a9bus_init);
 
 static void __init hb_emmc_init(struct device_node *node)
 {
        hb_clk_init(node, &periclk_ops);
 }
-
-static const __initconst struct of_device_id clk_match[] = {
-       { .compatible = "fixed-clock", .data = of_fixed_clk_setup, },
-       { .compatible = "calxeda,hb-pll-clock", .data = hb_pll_init, },
-       { .compatible = "calxeda,hb-a9periph-clock", .data = hb_a9periph_init, },
-       { .compatible = "calxeda,hb-a9bus-clock", .data = hb_a9bus_init, },
-       { .compatible = "calxeda,hb-emmc-clock", .data = hb_emmc_init, },
-       {}
-};
-
-void __init highbank_clocks_init(void)
-{
-       of_clk_init(clk_match);
-}
+CLK_OF_DECLARE(hb_emmc, "calxeda,hb-emmc-clock", hb_emmc_init);
index d098f72e1d5ffea90c4b406dd67db2a775ecb4e5..9f57bc37cd60a3e7559c3972e2eb0ac55145b2b9 100644 (file)
@@ -44,33 +44,23 @@ struct max77686_clk {
        struct clk_lookup *lookup;
 };
 
-static struct max77686_clk *get_max77686_clk(struct clk_hw *hw)
+static struct max77686_clk *to_max77686_clk(struct clk_hw *hw)
 {
        return container_of(hw, struct max77686_clk, hw);
 }
 
 static int max77686_clk_prepare(struct clk_hw *hw)
 {
-       struct max77686_clk *max77686;
-       int ret;
-
-       max77686 = get_max77686_clk(hw);
-       if (!max77686)
-               return -ENOMEM;
-
-       ret = regmap_update_bits(max77686->iodev->regmap,
-               MAX77686_REG_32KHZ, max77686->mask, max77686->mask);
+       struct max77686_clk *max77686 = to_max77686_clk(hw);
 
-       return ret;
+       return regmap_update_bits(max77686->iodev->regmap,
+                                 MAX77686_REG_32KHZ, max77686->mask,
+                                 max77686->mask);
 }
 
 static void max77686_clk_unprepare(struct clk_hw *hw)
 {
-       struct max77686_clk *max77686;
-
-       max77686 = get_max77686_clk(hw);
-       if (!max77686)
-               return;
+       struct max77686_clk *max77686 = to_max77686_clk(hw);
 
        regmap_update_bits(max77686->iodev->regmap,
                MAX77686_REG_32KHZ, max77686->mask, ~max77686->mask);
@@ -78,14 +68,10 @@ static void max77686_clk_unprepare(struct clk_hw *hw)
 
 static int max77686_clk_is_enabled(struct clk_hw *hw)
 {
-       struct max77686_clk *max77686;
+       struct max77686_clk *max77686 = to_max77686_clk(hw);
        int ret;
        u32 val;
 
-       max77686 = get_max77686_clk(hw);
-       if (!max77686)
-               return -ENOMEM;
-
        ret = regmap_read(max77686->iodev->regmap,
                                MAX77686_REG_32KHZ, &val);
 
@@ -130,9 +116,8 @@ static int max77686_clk_register(struct device *dev,
        if (IS_ERR(clk))
                return -ENOMEM;
 
-       max77686->lookup = devm_kzalloc(dev, sizeof(struct clk_lookup),
-                                       GFP_KERNEL);
-       if (IS_ERR(max77686->lookup))
+       max77686->lookup = kzalloc(sizeof(struct clk_lookup), GFP_KERNEL);
+       if (!max77686->lookup)
                return -ENOMEM;
 
        max77686->lookup->con_id = hw->init->name;
@@ -151,13 +136,13 @@ static int max77686_clk_probe(struct platform_device *pdev)
 
        max77686_clks = devm_kzalloc(&pdev->dev, sizeof(struct max77686_clk *)
                                        * MAX77686_CLKS_NUM, GFP_KERNEL);
-       if (IS_ERR(max77686_clks))
+       if (!max77686_clks)
                return -ENOMEM;
 
        for (i = 0; i < MAX77686_CLKS_NUM; i++) {
                max77686_clks[i] = devm_kzalloc(&pdev->dev,
                                        sizeof(struct max77686_clk), GFP_KERNEL);
-               if (IS_ERR(max77686_clks[i]))
+               if (!max77686_clks[i])
                        return -ENOMEM;
        }
 
index a203ecccdc4f8c6a1fd71d357fdfdeb9341a7bad..f8e9d0c27be27252f53aeb0ecec904c9caabc99a 100644 (file)
@@ -1025,20 +1025,67 @@ static struct of_device_id rsc_ids[] = {
        {},
 };
 
+enum prima2_clk_index {
+       /* 0    1     2      3      4      5      6       7         8      9 */
+       rtc,    osc,   pll1,  pll2,  pll3,  mem,   sys,   security, dsp,   gps,
+       mf,     io,    cpu,   uart0, uart1, uart2, tsc,   i2c0,     i2c1,  spi0,
+       spi1,   pwmc,  efuse, pulse, dmac0, dmac1, nand,  audio,    usp0,  usp1,
+       usp2,   vip,   gfx,   mm,    lcd,   vpp,   mmc01, mmc23,    mmc45, usbpll,
+       usb0,  usb1,  maxclk,
+};
+
+static __initdata struct clk_hw* prima2_clk_hw_array[maxclk] = {
+       NULL, /* dummy */
+       NULL,
+       &clk_pll1.hw,
+       &clk_pll2.hw,
+       &clk_pll3.hw,
+       &clk_mem.hw,
+       &clk_sys.hw,
+       &clk_security.hw,
+       &clk_dsp.hw,
+       &clk_gps.hw,
+       &clk_mf.hw,
+       &clk_io.hw,
+       &clk_cpu.hw,
+       &clk_uart0.hw,
+       &clk_uart1.hw,
+       &clk_uart2.hw,
+       &clk_tsc.hw,
+       &clk_i2c0.hw,
+       &clk_i2c1.hw,
+       &clk_spi0.hw,
+       &clk_spi1.hw,
+       &clk_pwmc.hw,
+       &clk_efuse.hw,
+       &clk_pulse.hw,
+       &clk_dmac0.hw,
+       &clk_dmac1.hw,
+       &clk_nand.hw,
+       &clk_audio.hw,
+       &clk_usp0.hw,
+       &clk_usp1.hw,
+       &clk_usp2.hw,
+       &clk_vip.hw,
+       &clk_gfx.hw,
+       &clk_mm.hw,
+       &clk_lcd.hw,
+       &clk_vpp.hw,
+       &clk_mmc01.hw,
+       &clk_mmc23.hw,
+       &clk_mmc45.hw,
+       &usb_pll_clk_hw,
+       &clk_usb0.hw,
+       &clk_usb1.hw,
+};
+
+static struct clk *prima2_clks[maxclk];
+static struct clk_onecell_data clk_data;
+
 void __init sirfsoc_of_clk_init(void)
 {
-       struct clk *clk;
        struct device_node *np;
-
-       np = of_find_matching_node(NULL, clkc_ids);
-       if (!np)
-               panic("unable to find compatible clkc node in dtb\n");
-
-       sirfsoc_clk_vbase = of_iomap(np, 0);
-       if (!sirfsoc_clk_vbase)
-               panic("unable to map clkc registers\n");
-
-       of_node_put(np);
+       int i;
 
        np = of_find_matching_node(NULL, rsc_ids);
        if (!np)
@@ -1050,122 +1097,30 @@ void __init sirfsoc_of_clk_init(void)
 
        of_node_put(np);
 
+       np = of_find_matching_node(NULL, clkc_ids);
+       if (!np)
+               return;
+
+       sirfsoc_clk_vbase = of_iomap(np, 0);
+       if (!sirfsoc_clk_vbase)
+               panic("unable to map clkc registers\n");
 
        /* These are always available (RTC and 26MHz OSC)*/
-       clk = clk_register_fixed_rate(NULL, "rtc", NULL,
+       prima2_clks[rtc] = clk_register_fixed_rate(NULL, "rtc", NULL,
                CLK_IS_ROOT, 32768);
-       BUG_ON(IS_ERR(clk));
-       clk = clk_register_fixed_rate(NULL, "osc", NULL,
+       prima2_clks[osc]= clk_register_fixed_rate(NULL, "osc", NULL,
                CLK_IS_ROOT, 26000000);
-       BUG_ON(IS_ERR(clk));
-
-       clk = clk_register(NULL, &clk_pll1.hw);
-       BUG_ON(IS_ERR(clk));
-       clk = clk_register(NULL, &clk_pll2.hw);
-       BUG_ON(IS_ERR(clk));
-       clk = clk_register(NULL, &clk_pll3.hw);
-       BUG_ON(IS_ERR(clk));
-       clk = clk_register(NULL, &clk_mem.hw);
-       BUG_ON(IS_ERR(clk));
-       clk = clk_register(NULL, &clk_sys.hw);
-       BUG_ON(IS_ERR(clk));
-       clk = clk_register(NULL, &clk_security.hw);
-       BUG_ON(IS_ERR(clk));
-       clk_register_clkdev(clk, NULL, "b8030000.security");
-       clk = clk_register(NULL, &clk_dsp.hw);
-       BUG_ON(IS_ERR(clk));
-       clk = clk_register(NULL, &clk_gps.hw);
-       BUG_ON(IS_ERR(clk));
-       clk_register_clkdev(clk, NULL, "a8010000.gps");
-       clk = clk_register(NULL, &clk_mf.hw);
-       BUG_ON(IS_ERR(clk));
-       clk = clk_register(NULL, &clk_io.hw);
-       BUG_ON(IS_ERR(clk));
-       clk_register_clkdev(clk, NULL, "io");
-       clk = clk_register(NULL, &clk_cpu.hw);
-       BUG_ON(IS_ERR(clk));
-       clk_register_clkdev(clk, NULL, "cpu");
-       clk = clk_register(NULL, &clk_uart0.hw);
-       BUG_ON(IS_ERR(clk));
-       clk_register_clkdev(clk, NULL, "b0050000.uart");
-       clk = clk_register(NULL, &clk_uart1.hw);
-       BUG_ON(IS_ERR(clk));
-       clk_register_clkdev(clk, NULL, "b0060000.uart");
-       clk = clk_register(NULL, &clk_uart2.hw);
-       BUG_ON(IS_ERR(clk));
-       clk_register_clkdev(clk, NULL, "b0070000.uart");
-       clk = clk_register(NULL, &clk_tsc.hw);
-       BUG_ON(IS_ERR(clk));
-       clk_register_clkdev(clk, NULL, "b0110000.tsc");
-       clk = clk_register(NULL, &clk_i2c0.hw);
-       BUG_ON(IS_ERR(clk));
-       clk_register_clkdev(clk, NULL, "b00e0000.i2c");
-       clk = clk_register(NULL, &clk_i2c1.hw);
-       BUG_ON(IS_ERR(clk));
-       clk_register_clkdev(clk, NULL, "b00f0000.i2c");
-       clk = clk_register(NULL, &clk_spi0.hw);
-       BUG_ON(IS_ERR(clk));
-       clk_register_clkdev(clk, NULL, "b00d0000.spi");
-       clk = clk_register(NULL, &clk_spi1.hw);
-       BUG_ON(IS_ERR(clk));
-       clk_register_clkdev(clk, NULL, "b0170000.spi");
-       clk = clk_register(NULL, &clk_pwmc.hw);
-       BUG_ON(IS_ERR(clk));
-       clk_register_clkdev(clk, NULL, "b0130000.pwm");
-       clk = clk_register(NULL, &clk_efuse.hw);
-       BUG_ON(IS_ERR(clk));
-       clk_register_clkdev(clk, NULL, "b0140000.efusesys");
-       clk = clk_register(NULL, &clk_pulse.hw);
-       BUG_ON(IS_ERR(clk));
-       clk_register_clkdev(clk, NULL, "b0150000.pulsec");
-       clk = clk_register(NULL, &clk_dmac0.hw);
-       BUG_ON(IS_ERR(clk));
-       clk_register_clkdev(clk, NULL, "b00b0000.dma-controller");
-       clk = clk_register(NULL, &clk_dmac1.hw);
-       BUG_ON(IS_ERR(clk));
-       clk_register_clkdev(clk, NULL, "b0160000.dma-controller");
-       clk = clk_register(NULL, &clk_nand.hw);
-       BUG_ON(IS_ERR(clk));
-       clk_register_clkdev(clk, NULL, "b0030000.nand");
-       clk = clk_register(NULL, &clk_audio.hw);
-       BUG_ON(IS_ERR(clk));
-       clk_register_clkdev(clk, NULL, "b0040000.audio");
-       clk = clk_register(NULL, &clk_usp0.hw);
-       BUG_ON(IS_ERR(clk));
-       clk_register_clkdev(clk, NULL, "b0080000.usp");
-       clk = clk_register(NULL, &clk_usp1.hw);
-       BUG_ON(IS_ERR(clk));
-       clk_register_clkdev(clk, NULL, "b0090000.usp");
-       clk = clk_register(NULL, &clk_usp2.hw);
-       BUG_ON(IS_ERR(clk));
-       clk_register_clkdev(clk, NULL, "b00a0000.usp");
-       clk = clk_register(NULL, &clk_vip.hw);
-       BUG_ON(IS_ERR(clk));
-       clk_register_clkdev(clk, NULL, "b00c0000.vip");
-       clk = clk_register(NULL, &clk_gfx.hw);
-       BUG_ON(IS_ERR(clk));
-       clk_register_clkdev(clk, NULL, "98000000.graphics");
-       clk = clk_register(NULL, &clk_mm.hw);
-       BUG_ON(IS_ERR(clk));
-       clk_register_clkdev(clk, NULL, "a0000000.multimedia");
-       clk = clk_register(NULL, &clk_lcd.hw);
-       BUG_ON(IS_ERR(clk));
-       clk_register_clkdev(clk, NULL, "90010000.display");
-       clk = clk_register(NULL, &clk_vpp.hw);
-       BUG_ON(IS_ERR(clk));
-       clk_register_clkdev(clk, NULL, "90020000.vpp");
-       clk = clk_register(NULL, &clk_mmc01.hw);
-       BUG_ON(IS_ERR(clk));
-       clk = clk_register(NULL, &clk_mmc23.hw);
-       BUG_ON(IS_ERR(clk));
-       clk = clk_register(NULL, &clk_mmc45.hw);
-       BUG_ON(IS_ERR(clk));
-       clk = clk_register(NULL, &usb_pll_clk_hw);
-       BUG_ON(IS_ERR(clk));
-       clk = clk_register(NULL, &clk_usb0.hw);
-       BUG_ON(IS_ERR(clk));
-       clk_register_clkdev(clk, NULL, "b00e0000.usb");
-       clk = clk_register(NULL, &clk_usb1.hw);
-       BUG_ON(IS_ERR(clk));
-       clk_register_clkdev(clk, NULL, "b00f0000.usb");
+
+       for (i = pll1; i < maxclk; i++) {
+               prima2_clks[i] = clk_register(NULL, prima2_clk_hw_array[i]);
+               BUG_ON(!prima2_clks[i]);
+       }
+       clk_register_clkdev(prima2_clks[cpu], NULL, "cpu");
+       clk_register_clkdev(prima2_clks[io],  NULL, "io");
+       clk_register_clkdev(prima2_clks[mem],  NULL, "mem");
+
+       clk_data.clks = prima2_clks;
+       clk_data.clk_num = maxclk;
+
+       of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
 }
diff --git a/drivers/clk/clk-sunxi.c b/drivers/clk/clk-sunxi.c
deleted file mode 100644 (file)
index 0e831b5..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright 2012 Maxime Ripard
- *
- * Maxime Ripard <maxime.ripard@free-electrons.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.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#include <linux/clk-provider.h>
-#include <linux/clkdev.h>
-#include <linux/clk/sunxi.h>
-#include <linux/of.h>
-
-static const __initconst struct of_device_id clk_match[] = {
-       { .compatible = "fixed-clock", .data = of_fixed_clk_setup, },
-       {}
-};
-
-void __init sunxi_init_clocks(void)
-{
-       of_clk_init(clk_match);
-}
index fe25570874d6b63dd937111a3664dbec9d244e32..b5538bba7a10b84581c70d51357a8e360fc81545 100644 (file)
@@ -41,6 +41,7 @@ struct clk_device {
 
 #define PLL_TYPE_VT8500                0
 #define PLL_TYPE_WM8650                1
+#define PLL_TYPE_WM8750                2
 
 struct clk_pll {
        struct clk_hw   hw;
@@ -121,7 +122,16 @@ static long vt8500_dclk_round_rate(struct clk_hw *hw, unsigned long rate,
                                unsigned long *prate)
 {
        struct clk_device *cdev = to_clk_device(hw);
-       u32 divisor = *prate / rate;
+       u32 divisor;
+
+       if (rate == 0)
+               return 0;
+
+       divisor = *prate / rate;
+
+       /* If prate / rate would be decimal, incr the divisor */
+       if (rate * divisor < *prate)
+               divisor++;
 
        /*
         * If this is a request for SDMMC we have to adjust the divisor
@@ -138,9 +148,18 @@ static int vt8500_dclk_set_rate(struct clk_hw *hw, unsigned long rate,
                                unsigned long parent_rate)
 {
        struct clk_device *cdev = to_clk_device(hw);
-       u32 divisor = parent_rate / rate;
+       u32 divisor;
        unsigned long flags = 0;
 
+       if (rate == 0)
+               return 0;
+
+       divisor =  parent_rate / rate;
+
+       /* If prate / rate would be decimal, incr the divisor */
+       if (rate * divisor < *prate)
+               divisor++;
+
        if (divisor == cdev->div_mask + 1)
                divisor = 0;
 
@@ -272,7 +291,7 @@ static __init void vtwm_device_clk_init(struct device_node *node)
        rc = of_clk_add_provider(node, of_clk_src_simple_get, clk);
        clk_register_clkdev(clk, clk_name, NULL);
 }
-
+CLK_OF_DECLARE(vt8500_device, "via,vt8500-device-clock", vtwm_device_clk_init);
 
 /* PLL clock related functions */
 
@@ -298,6 +317,16 @@ static __init void vtwm_device_clk_init(struct device_node *node)
 #define WM8650_BITS_TO_VAL(m, d1, d2)                                  \
                                ((d2 << 13) | (d1 << 10) | (m & 0x3FF))
 
+/* Helper macros for PLL_WM8750 */
+#define WM8750_PLL_MUL(x)      (((x >> 16) & 0xFF) + 1)
+#define WM8750_PLL_DIV(x)      ((((x >> 8) & 1) + 1) * (1 << (x & 7)))
+
+#define WM8750_BITS_TO_FREQ(r, m, d1, d2)                              \
+                               (r * (m+1) / ((d1+1) * (1 << d2)))
+
+#define WM8750_BITS_TO_VAL(f, m, d1, d2)                               \
+               ((f << 24) | ((m - 1) << 16) | ((d1 - 1) << 8) | d2)
+
 
 static void vt8500_find_pll_bits(unsigned long rate, unsigned long parent_rate,
                                u32 *multiplier, u32 *prediv)
@@ -361,16 +390,87 @@ static void wm8650_find_pll_bits(unsigned long rate, unsigned long parent_rate,
        /* if we got here, it wasn't an exact match */
        pr_warn("%s: requested rate %lu, found rate %lu\n", __func__, rate,
                                                        rate - best_err);
-       *multiplier = mul;
-       *divisor1 = div1;
-       *divisor2 = div2;
+       *multiplier = best_mul;
+       *divisor1 = best_div1;
+       *divisor2 = best_div2;
+}
+
+static u32 wm8750_get_filter(u32 parent_rate, u32 divisor1)
+{
+       /* calculate frequency (MHz) after pre-divisor */
+       u32 freq = (parent_rate / 1000000) / (divisor1 + 1);
+
+       if ((freq < 10) || (freq > 200))
+               pr_warn("%s: PLL recommended input frequency 10..200Mhz (requested %d Mhz)\n",
+                               __func__, freq);
+
+       if (freq >= 166)
+               return 7;
+       else if (freq >= 104)
+               return 6;
+       else if (freq >= 65)
+               return 5;
+       else if (freq >= 42)
+               return 4;
+       else if (freq >= 26)
+               return 3;
+       else if (freq >= 16)
+               return 2;
+       else if (freq >= 10)
+               return 1;
+
+       return 0;
+}
+
+static void wm8750_find_pll_bits(unsigned long rate, unsigned long parent_rate,
+                               u32 *filter, u32 *multiplier, u32 *divisor1, u32 *divisor2)
+{
+       u32 mul, div1, div2;
+       u32 best_mul, best_div1, best_div2;
+       unsigned long tclk, rate_err, best_err;
+
+       best_err = (unsigned long)-1;
+
+       /* Find the closest match (lower or equal to requested) */
+       for (div1 = 1; div1 >= 0; div1--)
+               for (div2 = 7; div2 >= 0; div2--)
+                       for (mul = 0; mul <= 255; mul++) {
+                               tclk = parent_rate * (mul + 1) / ((div1 + 1) * (1 << div2));
+                               if (tclk > rate)
+                                       continue;
+                               /* error will always be +ve */
+                               rate_err = rate - tclk;
+                               if (rate_err == 0) {
+                                       *filter = wm8750_get_filter(parent_rate, div1);
+                                       *multiplier = mul;
+                                       *divisor1 = div1;
+                                       *divisor2 = div2;
+                                       return;
+                               }
+
+                               if (rate_err < best_err) {
+                                       best_err = rate_err;
+                                       best_mul = mul;
+                                       best_div1 = div1;
+                                       best_div2 = div2;
+                               }
+                       }
+
+       /* if we got here, it wasn't an exact match */
+       pr_warn("%s: requested rate %lu, found rate %lu\n", __func__, rate,
+                                                       rate - best_err);
+
+       *filter = wm8750_get_filter(parent_rate, best_div1);
+       *multiplier = best_mul;
+       *divisor1 = best_div1;
+       *divisor2 = best_div2;
 }
 
 static int vtwm_pll_set_rate(struct clk_hw *hw, unsigned long rate,
                                unsigned long parent_rate)
 {
        struct clk_pll *pll = to_clk_pll(hw);
-       u32 mul, div1, div2;
+       u32 filter, mul, div1, div2;
        u32 pll_val;
        unsigned long flags = 0;
 
@@ -385,6 +485,9 @@ static int vtwm_pll_set_rate(struct clk_hw *hw, unsigned long rate,
                wm8650_find_pll_bits(rate, parent_rate, &mul, &div1, &div2);
                pll_val = WM8650_BITS_TO_VAL(mul, div1, div2);
                break;
+       case PLL_TYPE_WM8750:
+               wm8750_find_pll_bits(rate, parent_rate, &filter, &mul, &div1, &div2);
+               pll_val = WM8750_BITS_TO_VAL(filter, mul, div1, div2);
        default:
                pr_err("%s: invalid pll type\n", __func__);
                return 0;
@@ -405,7 +508,7 @@ static long vtwm_pll_round_rate(struct clk_hw *hw, unsigned long rate,
                                unsigned long *prate)
 {
        struct clk_pll *pll = to_clk_pll(hw);
-       u32 mul, div1, div2;
+       u32 filter, mul, div1, div2;
        long round_rate;
 
        switch (pll->type) {
@@ -417,6 +520,9 @@ static long vtwm_pll_round_rate(struct clk_hw *hw, unsigned long rate,
                wm8650_find_pll_bits(rate, *prate, &mul, &div1, &div2);
                round_rate = WM8650_BITS_TO_FREQ(*prate, mul, div1, div2);
                break;
+       case PLL_TYPE_WM8750:
+               wm8750_find_pll_bits(rate, *prate, &filter, &mul, &div1, &div2);
+               round_rate = WM8750_BITS_TO_FREQ(*prate, mul, div1, div2);
        default:
                round_rate = 0;
        }
@@ -440,6 +546,10 @@ static unsigned long vtwm_pll_recalc_rate(struct clk_hw *hw,
                pll_freq = parent_rate * WM8650_PLL_MUL(pll_val);
                pll_freq /= WM8650_PLL_DIV(pll_val);
                break;
+       case PLL_TYPE_WM8750:
+               pll_freq = parent_rate * WM8750_PLL_MUL(pll_val);
+               pll_freq /= WM8750_PLL_DIV(pll_val);
+               break;
        default:
                pll_freq = 0;
        }
@@ -502,20 +612,19 @@ static void __init vt8500_pll_init(struct device_node *node)
 {
        vtwm_pll_clk_init(node, PLL_TYPE_VT8500);
 }
+CLK_OF_DECLARE(vt8500_pll, "via,vt8500-pll-clock", vt8500_pll_init);
 
 static void __init wm8650_pll_init(struct device_node *node)
 {
        vtwm_pll_clk_init(node, PLL_TYPE_WM8650);
 }
+CLK_OF_DECLARE(wm8650_pll, "wm,wm8650-pll-clock", wm8650_pll_init);
 
-static const __initconst struct of_device_id clk_match[] = {
-       { .compatible = "fixed-clock", .data = of_fixed_clk_setup, },
-       { .compatible = "via,vt8500-pll-clock", .data = vt8500_pll_init, },
-       { .compatible = "wm,wm8650-pll-clock", .data = wm8650_pll_init, },
-       { .compatible = "via,vt8500-device-clock",
-                                       .data = vtwm_device_clk_init, },
-       { /* sentinel */ }
-};
+static void __init wm8750_pll_init(struct device_node *node)
+{
+       vtwm_pll_clk_init(node, PLL_TYPE_WM8750);
+}
+CLK_OF_DECLARE(wm8750_pll, "wm,wm8750-pll-clock", wm8750_pll_init);
 
 void __init vtwm_clk_init(void __iomem *base)
 {
@@ -524,5 +633,5 @@ void __init vtwm_clk_init(void __iomem *base)
 
        pmc_base = base;
 
-       of_clk_init(clk_match);
+       of_clk_init(NULL);
 }
index 37a30514fd66261d2ab64fad0a5900e6d391c121..b14a25f3925514ac09ee75953fa07e4104291b5b 100644 (file)
@@ -81,6 +81,7 @@ static void __init zynq_pll_clk_setup(struct device_node *np)
        if (WARN_ON(ret))
                return;
 }
+CLK_OF_DECLARE(zynq_pll, "xlnx,zynq-pll", zynq_pll_clk_setup);
 
 struct zynq_periph_clk {
        struct clk_hw           hw;
@@ -187,6 +188,7 @@ static void __init zynq_periph_clk_setup(struct device_node *np)
        if (WARN_ON(err))
                return;
 }
+CLK_OF_DECLARE(zynq_periph, "xlnx,zynq-periph-clock", zynq_periph_clk_setup);
 
 /* CPU Clock domain is modelled as a mux with 4 children subclks, whose
  * derivative rates depend on CLK_621_TRUE
@@ -366,18 +368,10 @@ static void __init zynq_cpu_clk_setup(struct device_node *np)
        if (WARN_ON(err))
                return;
 }
-
-static const __initconst struct of_device_id zynq_clk_match[] = {
-       { .compatible = "fixed-clock", .data = of_fixed_clk_setup, },
-       { .compatible = "xlnx,zynq-pll", .data = zynq_pll_clk_setup, },
-       { .compatible = "xlnx,zynq-periph-clock",
-               .data = zynq_periph_clk_setup, },
-       { .compatible = "xlnx,zynq-cpu-clock", .data = zynq_cpu_clk_setup, },
-       {}
-};
+CLK_OF_DECLARE(zynq_cpu, "xlnx,zynq-cpu-clock", zynq_cpu_clk_setup);
 
 void __init xilinx_zynq_clocks_init(void __iomem *slcr)
 {
        slcr_base = slcr;
-       of_clk_init(zynq_clk_match);
+       of_clk_init(NULL);
 }
index 251e45d6024d26b188d1e81195318fcb82cdc502..fabbfe1a9253bc017840ec69c89244e461b31737 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/slab.h>
 #include <linux/of.h>
 #include <linux/device.h>
+#include <linux/init.h>
 
 static DEFINE_SPINLOCK(enable_lock);
 static DEFINE_MUTEX(prepare_lock);
@@ -35,6 +36,137 @@ static struct dentry *rootdir;
 static struct dentry *orphandir;
 static int inited = 0;
 
+static void clk_summary_show_one(struct seq_file *s, struct clk *c, int level)
+{
+       if (!c)
+               return;
+
+       seq_printf(s, "%*s%-*s %-11d %-12d %-10lu",
+                  level * 3 + 1, "",
+                  30 - level * 3, c->name,
+                  c->enable_count, c->prepare_count, c->rate);
+       seq_printf(s, "\n");
+}
+
+static void clk_summary_show_subtree(struct seq_file *s, struct clk *c,
+                                    int level)
+{
+       struct clk *child;
+       struct hlist_node *tmp;
+
+       if (!c)
+               return;
+
+       clk_summary_show_one(s, c, level);
+
+       hlist_for_each_entry(child, tmp, &c->children, child_node)
+               clk_summary_show_subtree(s, child, level + 1);
+}
+
+static int clk_summary_show(struct seq_file *s, void *data)
+{
+       struct clk *c;
+       struct hlist_node *tmp;
+
+       seq_printf(s, "   clock                        enable_cnt  prepare_cnt  rate\n");
+       seq_printf(s, "---------------------------------------------------------------------\n");
+
+       mutex_lock(&prepare_lock);
+
+       hlist_for_each_entry(c, tmp, &clk_root_list, child_node)
+               clk_summary_show_subtree(s, c, 0);
+
+       hlist_for_each_entry(c, tmp, &clk_orphan_list, child_node)
+               clk_summary_show_subtree(s, c, 0);
+
+       mutex_unlock(&prepare_lock);
+
+       return 0;
+}
+
+
+static int clk_summary_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, clk_summary_show, inode->i_private);
+}
+
+static const struct file_operations clk_summary_fops = {
+       .open           = clk_summary_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+};
+
+static void clk_dump_one(struct seq_file *s, struct clk *c, int level)
+{
+       if (!c)
+               return;
+
+       seq_printf(s, "\"%s\": { ", c->name);
+       seq_printf(s, "\"enable_count\": %d,", c->enable_count);
+       seq_printf(s, "\"prepare_count\": %d,", c->prepare_count);
+       seq_printf(s, "\"rate\": %lu", c->rate);
+}
+
+static void clk_dump_subtree(struct seq_file *s, struct clk *c, int level)
+{
+       struct clk *child;
+       struct hlist_node *tmp;
+
+       if (!c)
+               return;
+
+       clk_dump_one(s, c, level);
+
+       hlist_for_each_entry(child, tmp, &c->children, child_node) {
+               seq_printf(s, ",");
+               clk_dump_subtree(s, child, level + 1);
+       }
+
+       seq_printf(s, "}");
+}
+
+static int clk_dump(struct seq_file *s, void *data)
+{
+       struct clk *c;
+       struct hlist_node *tmp;
+       bool first_node = true;
+
+       seq_printf(s, "{");
+
+       mutex_lock(&prepare_lock);
+
+       hlist_for_each_entry(c, tmp, &clk_root_list, child_node) {
+               if (!first_node)
+                       seq_printf(s, ",");
+               first_node = false;
+               clk_dump_subtree(s, c, 0);
+       }
+
+       hlist_for_each_entry(c, tmp, &clk_orphan_list, child_node) {
+               seq_printf(s, ",");
+               clk_dump_subtree(s, c, 0);
+       }
+
+       mutex_unlock(&prepare_lock);
+
+       seq_printf(s, "}");
+       return 0;
+}
+
+
+static int clk_dump_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, clk_dump, inode->i_private);
+}
+
+static const struct file_operations clk_dump_fops = {
+       .open           = clk_dump_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+};
+
 /* caller must hold prepare_lock */
 static int clk_debug_create_one(struct clk *clk, struct dentry *pdentry)
 {
@@ -168,12 +300,23 @@ static int __init clk_debug_init(void)
 {
        struct clk *clk;
        struct hlist_node *tmp;
+       struct dentry *d;
 
        rootdir = debugfs_create_dir("clk", NULL);
 
        if (!rootdir)
                return -ENOMEM;
 
+       d = debugfs_create_file("clk_summary", S_IRUGO, rootdir, NULL,
+                               &clk_summary_fops);
+       if (!d)
+               return -ENOMEM;
+
+       d = debugfs_create_file("clk_dump", S_IRUGO, rootdir, NULL,
+                               &clk_dump_fops);
+       if (!d)
+               return -ENOMEM;
+
        orphandir = debugfs_create_dir("orphans", rootdir);
 
        if (!orphandir)
@@ -259,32 +402,33 @@ late_initcall(clk_disable_unused);
 
 /***    helper functions   ***/
 
-inline const char *__clk_get_name(struct clk *clk)
+const char *__clk_get_name(struct clk *clk)
 {
        return !clk ? NULL : clk->name;
 }
+EXPORT_SYMBOL_GPL(__clk_get_name);
 
-inline struct clk_hw *__clk_get_hw(struct clk *clk)
+struct clk_hw *__clk_get_hw(struct clk *clk)
 {
        return !clk ? NULL : clk->hw;
 }
 
-inline u8 __clk_get_num_parents(struct clk *clk)
+u8 __clk_get_num_parents(struct clk *clk)
 {
        return !clk ? 0 : clk->num_parents;
 }
 
-inline struct clk *__clk_get_parent(struct clk *clk)
+struct clk *__clk_get_parent(struct clk *clk)
 {
        return !clk ? NULL : clk->parent;
 }
 
-inline unsigned int __clk_get_enable_count(struct clk *clk)
+unsigned int __clk_get_enable_count(struct clk *clk)
 {
        return !clk ? 0 : clk->enable_count;
 }
 
-inline unsigned int __clk_get_prepare_count(struct clk *clk)
+unsigned int __clk_get_prepare_count(struct clk *clk)
 {
        return !clk ? 0 : clk->prepare_count;
 }
@@ -310,7 +454,7 @@ out:
        return ret;
 }
 
-inline unsigned long __clk_get_flags(struct clk *clk)
+unsigned long __clk_get_flags(struct clk *clk)
 {
        return !clk ? 0 : clk->flags;
 }
@@ -950,9 +1094,6 @@ int clk_set_rate(struct clk *clk, unsigned long rate)
        /* change the rates */
        clk_change_rate(top);
 
-       mutex_unlock(&prepare_lock);
-
-       return 0;
 out:
        mutex_unlock(&prepare_lock);
 
@@ -1663,6 +1804,11 @@ struct of_clk_provider {
        void *data;
 };
 
+extern struct of_device_id __clk_of_table[];
+
+static const struct of_device_id __clk_of_table_sentinel
+       __used __section(__clk_of_table_end);
+
 static LIST_HEAD(of_clk_providers);
 static DEFINE_MUTEX(of_clk_lock);
 
@@ -1791,6 +1937,9 @@ void __init of_clk_init(const struct of_device_id *matches)
 {
        struct device_node *np;
 
+       if (!matches)
+               matches = __clk_of_table;
+
        for_each_matching_node(np, matches) {
                const struct of_device_id *match = of_match_node(matches, np);
                of_clk_init_cb_t clk_init_cb = match->data;
index 8dd476e2a9c5f19912d96948717fc67175eb5cc5..b5c06f9766f610439954d7f55489e4e7750cf726 100644 (file)
@@ -99,7 +99,7 @@ static enum imx23_clk clks_init_on[] __initdata = {
 int __init mx23_clocks_init(void)
 {
        struct device_node *np;
-       int i;
+       u32 i;
 
        clk_misc_init();
 
index db3af0874121cdf348d4d314be7b44a80d499422..126370a62ce2479378151b838fa7568094cb113f 100644 (file)
@@ -154,7 +154,7 @@ static enum imx28_clk clks_init_on[] __initdata = {
 int __init mx28_clocks_init(void)
 {
        struct device_node *np;
-       int i;
+       u32 i;
 
        clk_misc_init();
 
index dcb6ae0a04256db9da9906106707f17d311b5ef2..256c8be74df8483073ac84fe2f9984724a837ac9 100644 (file)
@@ -144,3 +144,4 @@ error:
                vexpress_config_func_put(osc->func);
        kfree(osc);
 }
+CLK_OF_DECLARE(vexpress_soc, "arm,vexpress-osc", vexpress_osc_of_setup);
index c742ac7c60bb3613184106520330eea8427e983e..f889f2f07b370338ee5f2e9a97053ba83005fc13 100644 (file)
@@ -99,19 +99,13 @@ struct clk *vexpress_sp810_of_get(struct of_phandle_args *clkspec, void *data)
        return vexpress_sp810_timerclken[clkspec->args[0]];
 }
 
-static const __initconst struct of_device_id vexpress_fixed_clk_match[] = {
-       { .compatible = "fixed-clock", .data = of_fixed_clk_setup, },
-       { .compatible = "arm,vexpress-osc", .data = vexpress_osc_of_setup, },
-       {}
-};
-
 void __init vexpress_clk_of_init(void)
 {
        struct device_node *node;
        struct clk *clk;
        struct clk *refclk, *timclk;
 
-       of_clk_init(vexpress_fixed_clk_match);
+       of_clk_init(NULL);
 
        node = of_find_compatible_node(NULL, NULL, "arm,sp810");
        vexpress_sp810_init(of_iomap(node, 0));
index 3cd1bd3d7aee7fd0f6c77143bfb11b8d1100e59e..93d09d0e009fc9e344ad32807479cb8bb514bd34 100644 (file)
@@ -23,7 +23,7 @@
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
 #include <linux/sunxi_timer.h>
-#include <linux/clk/sunxi.h>
+#include <linux/clk-provider.h>
 
 #define TIMER_CTL_REG          0x00
 #define TIMER_CTL_ENABLE               (1 << 0)
@@ -124,7 +124,7 @@ static void __init sunxi_timer_init(void)
        if (irq <= 0)
                panic("Can't parse IRQ");
 
-       sunxi_init_clocks();
+       of_clk_init(NULL);
 
        clk = of_clk_get(node, 0);
        if (IS_ERR(clk))
index d1ea7ce0b4cb95c9e61935aefbcb09c12f49bdbc..c1fe60ad1540a0f922458cda1a6609c51de2c42e 100644 (file)
 #endif
 
 
+#ifdef CONFIG_COMMON_CLK
+#define CLK_OF_TABLES() . = ALIGN(8);                          \
+                       VMLINUX_SYMBOL(__clk_of_table) = .;     \
+                       *(__clk_of_table)                       \
+                       *(__clk_of_table_end)
+#else
+#define CLK_OF_TABLES()
+#endif
+
 #define KERNEL_DTB()                                                   \
        STRUCT_ALIGN();                                                 \
        VMLINUX_SYMBOL(__dtb_start) = .;                                \
        DEV_DISCARD(init.rodata)                                        \
        CPU_DISCARD(init.rodata)                                        \
        MEM_DISCARD(init.rodata)                                        \
+       CLK_OF_TABLES()                                                 \
        KERNEL_DTB()
 
 #define INIT_TEXT                                                      \
index 4989b8a7bed1703659c8f9a3fd7d955b5c6f6ffb..7f197d7addb0be18141a66ad225135b9b0730b24 100644 (file)
@@ -379,7 +379,13 @@ struct clk_onecell_data {
 };
 struct clk *of_clk_src_onecell_get(struct of_phandle_args *clkspec, void *data);
 const char *of_clk_get_parent_name(struct device_node *np, int index);
+
 void of_clk_init(const struct of_device_id *matches);
 
+#define CLK_OF_DECLARE(name, compat, fn)                       \
+       static const struct of_device_id __clk_of_table_##name  \
+               __used __section(__clk_of_table)                \
+               = { .compatible = compat, .data = fn };
+
 #endif /* CONFIG_COMMON_CLK */
 #endif /* CLK_PROVIDER_H */
diff --git a/include/linux/clk/sunxi.h b/include/linux/clk/sunxi.h
deleted file mode 100644 (file)
index e074fdd..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright 2012 Maxime Ripard
- *
- * Maxime Ripard <maxime.ripard@free-electrons.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.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#ifndef __LINUX_CLK_SUNXI_H_
-#define __LINUX_CLK_SUNXI_H_
-
-void __init sunxi_init_clocks(void);
-
-#endif