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.
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1.4.11 (GNU/Linux)
 
 iQIcBAABAgAGBQJRI81VAAoJEDqPOy9afJhJzXIQAMZX0DFBio0k5yxmlUS4r+I+
 LV6aRyyvdafVZwx16oTXE4SkGYkTUKrRfD+EAhZA+UsWdlWrAUE623dnBpvDXmkF
 gR+sRrhhzfF2754mWDVDHqFINNgqIR2d1pMNbCXLP85CZLWvkUISV1hnREB5pwfj
 W0T2hohtBe7XtXtsCTCqoLke+D2jrSqg9obcMDyEAM3R2K42nujsTcp0STi/NJvS
 i1YbbYgq6E1/2SNGDOf0YYZscxUGNOI2MN7OckVk1c5781hzKdyeiLiMzY5v6UvT
 aTPXiqetO6UlnCjUPZ1edluHRELVTvrO3qwEqmWfqky6MbcE5uxBqpNabF614ozZ
 eywTXd4xSBKY5Z1WfYn4pgukIvqGsqgGxLaxazUQGR76B66Uk0I3Rca+vSy/O652
 ry0Ejcc67dGOPwYuKkvuwuDwrSSOoRF3q6H99SRLjN/1YopksICVkMU8YeiuUNGJ
 Rb5mD37dfeLhJYLG0mhUdO5olAOsDQJN/nNLQJTAPCpPt+nQURpOaOI+LC9xV6Rr
 pNeA9m1t1hWpfBeYdnUL7y+IUv7XYgRFhjFpRRVjfTOK5nym6MR5OJgdtCv/Kzt4
 tYEJiT5/OgJkUBnCWz5yA+jxYEVxkAeJqT+UMht2a98NYq4rfIiJmJsUj+op69bD
 P2S+GUp0NlpgeNXkjO2s
 =1pl+
 -----END PGP SIGNATURE-----

Merge tag 'clk-for-linus' of git://git.linaro.org/people/mturquette/linux

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
  ...
This commit is contained in:
Linus Torvalds 2013-02-20 11:02:10 -08:00
commit 10b6339e93
23 changed files with 526 additions and 275 deletions

View File

@ -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>;
};

View File

@ -58,10 +58,11 @@
#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>;
};
};
@ -104,6 +106,7 @@
compatible = "sirf,prima2-vpp";
reg = <0x90020000 0x10000>;
interrupts = <31>;
clocks = <&clks 35>;
};
};
@ -117,6 +120,7 @@
compatible = "powervr,sgx531";
reg = <0x98000000 0x8000000>;
interrupts = <6>;
clocks = <&clks 32>;
};
};
@ -130,6 +134,7 @@
compatible = "sirf,prima2-video-codec";
reg = <0xa0000000 0x8000000>;
interrupts = <5>;
clocks = <&clks 33>;
};
};
@ -149,12 +154,14 @@
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>;
};
};
@ -174,12 +181,14 @@
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 {
@ -187,6 +196,7 @@
compatible = "sirf,prima2-uart";
reg = <0xb0050000 0x10000>;
interrupts = <17>;
clocks = <&clks 13>;
};
uart1: uart@b0060000 {
@ -194,6 +204,7 @@
compatible = "sirf,prima2-uart";
reg = <0xb0060000 0x10000>;
interrupts = <18>;
clocks = <&clks 14>;
};
uart2: uart@b0070000 {
@ -201,6 +212,7 @@
compatible = "sirf,prima2-uart";
reg = <0xb0070000 0x10000>;
interrupts = <19>;
clocks = <&clks 15>;
};
usp0: usp@b0080000 {
@ -208,6 +220,7 @@
compatible = "sirf,prima2-usp";
reg = <0xb0080000 0x10000>;
interrupts = <20>;
clocks = <&clks 28>;
};
usp1: usp@b0090000 {
@ -215,6 +228,7 @@
compatible = "sirf,prima2-usp";
reg = <0xb0090000 0x10000>;
interrupts = <21>;
clocks = <&clks 29>;
};
usp2: usp@b00a0000 {
@ -222,6 +236,7 @@
compatible = "sirf,prima2-usp";
reg = <0xb00a0000 0x10000>;
interrupts = <22>;
clocks = <&clks 30>;
};
dmac0: dma-controller@b00b0000 {
@ -229,6 +244,7 @@
compatible = "sirf,prima2-dmac";
reg = <0xb00b0000 0x10000>;
interrupts = <12>;
clocks = <&clks 24>;
};
dmac1: dma-controller@b0160000 {
@ -236,11 +252,13 @@
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 {
@ -248,6 +266,7 @@
compatible = "sirf,prima2-spi";
reg = <0xb00d0000 0x10000>;
interrupts = <15>;
clocks = <&clks 19>;
};
spi1: spi@b0170000 {
@ -255,6 +274,7 @@
compatible = "sirf,prima2-spi";
reg = <0xb0170000 0x10000>;
interrupts = <16>;
clocks = <&clks 20>;
};
i2c0: i2c@b00e0000 {
@ -262,6 +282,7 @@
compatible = "sirf,prima2-i2c";
reg = <0xb00e0000 0x10000>;
interrupts = <24>;
clocks = <&clks 17>;
};
i2c1: i2c@b00f0000 {
@ -269,12 +290,14 @@
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 {
@ -507,17 +530,20 @@
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 {
@ -616,12 +642,14 @@
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 {
@ -634,6 +662,7 @@
compatible = "sirf,prima2-security";
reg = <0xb8030000 0x10000>;
interrupts = <42>;
clocks = <&clks 7>;
};
};
};

View 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;

View 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);

View 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

View 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;

View 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,

View 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

View 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);

View 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;
struct max77686_clk *max77686 = to_max77686_clk(hw);
max77686 = get_max77686_clk(hw);
if (!max77686)
return -ENOMEM;
ret = regmap_update_bits(max77686->iodev->regmap,
MAX77686_REG_32KHZ, max77686->mask, max77686->mask);
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;
}

View 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);
}

View File

@ -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);
}

View 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);
}

View 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);
}

View 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;

View 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();

View 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();

View 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);

View 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));

View 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))

View File

@ -150,6 +150,15 @@
#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) = .; \
@ -493,6 +502,7 @@
DEV_DISCARD(init.rodata) \
CPU_DISCARD(init.rodata) \
MEM_DISCARD(init.rodata) \
CLK_OF_TABLES() \
KERNEL_DTB()
#define INIT_TEXT \

View 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 */

View File

@ -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