diff options
Diffstat (limited to 'drivers')
56 files changed, 5611 insertions, 519 deletions
diff --git a/drivers/clk/at91/clk-programmable.c b/drivers/clk/at91/clk-programmable.c index 62e2509f9df1..bbdb1b985c91 100644 --- a/drivers/clk/at91/clk-programmable.c +++ b/drivers/clk/at91/clk-programmable.c | |||
@@ -57,7 +57,7 @@ static unsigned long clk_programmable_recalc_rate(struct clk_hw *hw, | |||
57 | static long clk_programmable_determine_rate(struct clk_hw *hw, | 57 | static long clk_programmable_determine_rate(struct clk_hw *hw, |
58 | unsigned long rate, | 58 | unsigned long rate, |
59 | unsigned long *best_parent_rate, | 59 | unsigned long *best_parent_rate, |
60 | struct clk **best_parent_clk) | 60 | struct clk_hw **best_parent_hw) |
61 | { | 61 | { |
62 | struct clk *parent = NULL; | 62 | struct clk *parent = NULL; |
63 | long best_rate = -EINVAL; | 63 | long best_rate = -EINVAL; |
@@ -84,7 +84,7 @@ static long clk_programmable_determine_rate(struct clk_hw *hw, | |||
84 | if (best_rate < 0 || (rate - tmp_rate) < (rate - best_rate)) { | 84 | if (best_rate < 0 || (rate - tmp_rate) < (rate - best_rate)) { |
85 | best_rate = tmp_rate; | 85 | best_rate = tmp_rate; |
86 | *best_parent_rate = parent_rate; | 86 | *best_parent_rate = parent_rate; |
87 | *best_parent_clk = parent; | 87 | *best_parent_hw = __clk_get_hw(parent); |
88 | } | 88 | } |
89 | 89 | ||
90 | if (!best_rate) | 90 | if (!best_rate) |
diff --git a/drivers/clk/bcm/clk-kona.c b/drivers/clk/bcm/clk-kona.c index 95af2e665dd3..1c06f6f3a8c5 100644 --- a/drivers/clk/bcm/clk-kona.c +++ b/drivers/clk/bcm/clk-kona.c | |||
@@ -1032,7 +1032,7 @@ static long kona_peri_clk_round_rate(struct clk_hw *hw, unsigned long rate, | |||
1032 | } | 1032 | } |
1033 | 1033 | ||
1034 | static long kona_peri_clk_determine_rate(struct clk_hw *hw, unsigned long rate, | 1034 | static long kona_peri_clk_determine_rate(struct clk_hw *hw, unsigned long rate, |
1035 | unsigned long *best_parent_rate, struct clk **best_parent) | 1035 | unsigned long *best_parent_rate, struct clk_hw **best_parent) |
1036 | { | 1036 | { |
1037 | struct kona_clk *bcm_clk = to_kona_clk(hw); | 1037 | struct kona_clk *bcm_clk = to_kona_clk(hw); |
1038 | struct clk *clk = hw->clk; | 1038 | struct clk *clk = hw->clk; |
@@ -1075,7 +1075,7 @@ static long kona_peri_clk_determine_rate(struct clk_hw *hw, unsigned long rate, | |||
1075 | if (delta < best_delta) { | 1075 | if (delta < best_delta) { |
1076 | best_delta = delta; | 1076 | best_delta = delta; |
1077 | best_rate = other_rate; | 1077 | best_rate = other_rate; |
1078 | *best_parent = parent; | 1078 | *best_parent = __clk_get_hw(parent); |
1079 | *best_parent_rate = parent_rate; | 1079 | *best_parent_rate = parent_rate; |
1080 | } | 1080 | } |
1081 | } | 1081 | } |
diff --git a/drivers/clk/clk-composite.c b/drivers/clk/clk-composite.c index b9355daf8065..4386697236a7 100644 --- a/drivers/clk/clk-composite.c +++ b/drivers/clk/clk-composite.c | |||
@@ -57,7 +57,7 @@ static unsigned long clk_composite_recalc_rate(struct clk_hw *hw, | |||
57 | 57 | ||
58 | static long clk_composite_determine_rate(struct clk_hw *hw, unsigned long rate, | 58 | static long clk_composite_determine_rate(struct clk_hw *hw, unsigned long rate, |
59 | unsigned long *best_parent_rate, | 59 | unsigned long *best_parent_rate, |
60 | struct clk **best_parent_p) | 60 | struct clk_hw **best_parent_p) |
61 | { | 61 | { |
62 | struct clk_composite *composite = to_clk_composite(hw); | 62 | struct clk_composite *composite = to_clk_composite(hw); |
63 | const struct clk_ops *rate_ops = composite->rate_ops; | 63 | const struct clk_ops *rate_ops = composite->rate_ops; |
@@ -80,8 +80,9 @@ static long clk_composite_determine_rate(struct clk_hw *hw, unsigned long rate, | |||
80 | *best_parent_p = NULL; | 80 | *best_parent_p = NULL; |
81 | 81 | ||
82 | if (__clk_get_flags(hw->clk) & CLK_SET_RATE_NO_REPARENT) { | 82 | if (__clk_get_flags(hw->clk) & CLK_SET_RATE_NO_REPARENT) { |
83 | *best_parent_p = clk_get_parent(mux_hw->clk); | 83 | parent = clk_get_parent(mux_hw->clk); |
84 | *best_parent_rate = __clk_get_rate(*best_parent_p); | 84 | *best_parent_p = __clk_get_hw(parent); |
85 | *best_parent_rate = __clk_get_rate(parent); | ||
85 | 86 | ||
86 | return rate_ops->round_rate(rate_hw, rate, | 87 | return rate_ops->round_rate(rate_hw, rate, |
87 | best_parent_rate); | 88 | best_parent_rate); |
@@ -103,7 +104,7 @@ static long clk_composite_determine_rate(struct clk_hw *hw, unsigned long rate, | |||
103 | 104 | ||
104 | if (!rate_diff || !*best_parent_p | 105 | if (!rate_diff || !*best_parent_p |
105 | || best_rate_diff > rate_diff) { | 106 | || best_rate_diff > rate_diff) { |
106 | *best_parent_p = parent; | 107 | *best_parent_p = __clk_get_hw(parent); |
107 | *best_parent_rate = parent_rate; | 108 | *best_parent_rate = parent_rate; |
108 | best_rate_diff = rate_diff; | 109 | best_rate_diff = rate_diff; |
109 | best_rate = tmp_rate; | 110 | best_rate = tmp_rate; |
diff --git a/drivers/clk/clk-mux.c b/drivers/clk/clk-mux.c index 4f96ff3ba728..6e1ecf94bf58 100644 --- a/drivers/clk/clk-mux.c +++ b/drivers/clk/clk-mux.c | |||
@@ -77,7 +77,7 @@ static int clk_mux_set_parent(struct clk_hw *hw, u8 index) | |||
77 | 77 | ||
78 | else { | 78 | else { |
79 | if (mux->flags & CLK_MUX_INDEX_BIT) | 79 | if (mux->flags & CLK_MUX_INDEX_BIT) |
80 | index = (1 << ffs(index)); | 80 | index = 1 << index; |
81 | 81 | ||
82 | if (mux->flags & CLK_MUX_INDEX_ONE) | 82 | if (mux->flags & CLK_MUX_INDEX_ONE) |
83 | index++; | 83 | index++; |
diff --git a/drivers/clk/clk-s2mps11.c b/drivers/clk/clk-s2mps11.c index 87a41038237d..bfa1e64e267d 100644 --- a/drivers/clk/clk-s2mps11.c +++ b/drivers/clk/clk-s2mps11.c | |||
@@ -218,7 +218,7 @@ static int s2mps11_clk_probe(struct platform_device *pdev) | |||
218 | default: | 218 | default: |
219 | dev_err(&pdev->dev, "Invalid device type\n"); | 219 | dev_err(&pdev->dev, "Invalid device type\n"); |
220 | return -EINVAL; | 220 | return -EINVAL; |
221 | }; | 221 | } |
222 | 222 | ||
223 | /* Store clocks of_node in first element of s2mps11_clks array */ | 223 | /* Store clocks of_node in first element of s2mps11_clks array */ |
224 | s2mps11_clks->clk_np = s2mps11_clk_parse_dt(pdev, clks_init); | 224 | s2mps11_clks->clk_np = s2mps11_clk_parse_dt(pdev, clks_init); |
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index 4896ae9e23da..f4963b7d4e17 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c | |||
@@ -240,7 +240,6 @@ static const struct file_operations clk_dump_fops = { | |||
240 | .release = single_release, | 240 | .release = single_release, |
241 | }; | 241 | }; |
242 | 242 | ||
243 | /* caller must hold prepare_lock */ | ||
244 | static int clk_debug_create_one(struct clk *clk, struct dentry *pdentry) | 243 | static int clk_debug_create_one(struct clk *clk, struct dentry *pdentry) |
245 | { | 244 | { |
246 | struct dentry *d; | 245 | struct dentry *d; |
@@ -354,13 +353,13 @@ out: | |||
354 | mutex_unlock(&clk_debug_lock); | 353 | mutex_unlock(&clk_debug_lock); |
355 | } | 354 | } |
356 | 355 | ||
357 | struct dentry *clk_debugfs_add_file(struct clk *clk, char *name, umode_t mode, | 356 | struct dentry *clk_debugfs_add_file(struct clk_hw *hw, char *name, umode_t mode, |
358 | void *data, const struct file_operations *fops) | 357 | void *data, const struct file_operations *fops) |
359 | { | 358 | { |
360 | struct dentry *d = NULL; | 359 | struct dentry *d = NULL; |
361 | 360 | ||
362 | if (clk->dentry) | 361 | if (hw->clk->dentry) |
363 | d = debugfs_create_file(name, mode, clk->dentry, data, fops); | 362 | d = debugfs_create_file(name, mode, hw->clk->dentry, data, fops); |
364 | 363 | ||
365 | return d; | 364 | return d; |
366 | } | 365 | } |
@@ -574,11 +573,6 @@ unsigned int __clk_get_enable_count(struct clk *clk) | |||
574 | return !clk ? 0 : clk->enable_count; | 573 | return !clk ? 0 : clk->enable_count; |
575 | } | 574 | } |
576 | 575 | ||
577 | unsigned int __clk_get_prepare_count(struct clk *clk) | ||
578 | { | ||
579 | return !clk ? 0 : clk->prepare_count; | ||
580 | } | ||
581 | |||
582 | unsigned long __clk_get_rate(struct clk *clk) | 576 | unsigned long __clk_get_rate(struct clk *clk) |
583 | { | 577 | { |
584 | unsigned long ret; | 578 | unsigned long ret; |
@@ -601,7 +595,7 @@ out: | |||
601 | } | 595 | } |
602 | EXPORT_SYMBOL_GPL(__clk_get_rate); | 596 | EXPORT_SYMBOL_GPL(__clk_get_rate); |
603 | 597 | ||
604 | unsigned long __clk_get_accuracy(struct clk *clk) | 598 | static unsigned long __clk_get_accuracy(struct clk *clk) |
605 | { | 599 | { |
606 | if (!clk) | 600 | if (!clk) |
607 | return 0; | 601 | return 0; |
@@ -707,7 +701,7 @@ struct clk *__clk_lookup(const char *name) | |||
707 | */ | 701 | */ |
708 | long __clk_mux_determine_rate(struct clk_hw *hw, unsigned long rate, | 702 | long __clk_mux_determine_rate(struct clk_hw *hw, unsigned long rate, |
709 | unsigned long *best_parent_rate, | 703 | unsigned long *best_parent_rate, |
710 | struct clk **best_parent_p) | 704 | struct clk_hw **best_parent_p) |
711 | { | 705 | { |
712 | struct clk *clk = hw->clk, *parent, *best_parent = NULL; | 706 | struct clk *clk = hw->clk, *parent, *best_parent = NULL; |
713 | int i, num_parents; | 707 | int i, num_parents; |
@@ -743,7 +737,7 @@ long __clk_mux_determine_rate(struct clk_hw *hw, unsigned long rate, | |||
743 | 737 | ||
744 | out: | 738 | out: |
745 | if (best_parent) | 739 | if (best_parent) |
746 | *best_parent_p = best_parent; | 740 | *best_parent_p = best_parent->hw; |
747 | *best_parent_rate = best; | 741 | *best_parent_rate = best; |
748 | 742 | ||
749 | return best; | 743 | return best; |
@@ -951,6 +945,7 @@ unsigned long __clk_round_rate(struct clk *clk, unsigned long rate) | |||
951 | { | 945 | { |
952 | unsigned long parent_rate = 0; | 946 | unsigned long parent_rate = 0; |
953 | struct clk *parent; | 947 | struct clk *parent; |
948 | struct clk_hw *parent_hw; | ||
954 | 949 | ||
955 | if (!clk) | 950 | if (!clk) |
956 | return 0; | 951 | return 0; |
@@ -959,10 +954,11 @@ unsigned long __clk_round_rate(struct clk *clk, unsigned long rate) | |||
959 | if (parent) | 954 | if (parent) |
960 | parent_rate = parent->rate; | 955 | parent_rate = parent->rate; |
961 | 956 | ||
962 | if (clk->ops->determine_rate) | 957 | if (clk->ops->determine_rate) { |
958 | parent_hw = parent ? parent->hw : NULL; | ||
963 | return clk->ops->determine_rate(clk->hw, rate, &parent_rate, | 959 | return clk->ops->determine_rate(clk->hw, rate, &parent_rate, |
964 | &parent); | 960 | &parent_hw); |
965 | else if (clk->ops->round_rate) | 961 | } else if (clk->ops->round_rate) |
966 | return clk->ops->round_rate(clk->hw, rate, &parent_rate); | 962 | return clk->ops->round_rate(clk->hw, rate, &parent_rate); |
967 | else if (clk->flags & CLK_SET_RATE_PARENT) | 963 | else if (clk->flags & CLK_SET_RATE_PARENT) |
968 | return __clk_round_rate(clk->parent, rate); | 964 | return __clk_round_rate(clk->parent, rate); |
@@ -1350,6 +1346,7 @@ static struct clk *clk_calc_new_rates(struct clk *clk, unsigned long rate) | |||
1350 | { | 1346 | { |
1351 | struct clk *top = clk; | 1347 | struct clk *top = clk; |
1352 | struct clk *old_parent, *parent; | 1348 | struct clk *old_parent, *parent; |
1349 | struct clk_hw *parent_hw; | ||
1353 | unsigned long best_parent_rate = 0; | 1350 | unsigned long best_parent_rate = 0; |
1354 | unsigned long new_rate; | 1351 | unsigned long new_rate; |
1355 | int p_index = 0; | 1352 | int p_index = 0; |
@@ -1365,9 +1362,11 @@ static struct clk *clk_calc_new_rates(struct clk *clk, unsigned long rate) | |||
1365 | 1362 | ||
1366 | /* find the closest rate and parent clk/rate */ | 1363 | /* find the closest rate and parent clk/rate */ |
1367 | if (clk->ops->determine_rate) { | 1364 | if (clk->ops->determine_rate) { |
1365 | parent_hw = parent ? parent->hw : NULL; | ||
1368 | new_rate = clk->ops->determine_rate(clk->hw, rate, | 1366 | new_rate = clk->ops->determine_rate(clk->hw, rate, |
1369 | &best_parent_rate, | 1367 | &best_parent_rate, |
1370 | &parent); | 1368 | &parent_hw); |
1369 | parent = parent_hw->clk; | ||
1371 | } else if (clk->ops->round_rate) { | 1370 | } else if (clk->ops->round_rate) { |
1372 | new_rate = clk->ops->round_rate(clk->hw, rate, | 1371 | new_rate = clk->ops->round_rate(clk->hw, rate, |
1373 | &best_parent_rate); | 1372 | &best_parent_rate); |
@@ -1614,7 +1613,7 @@ static struct clk *__clk_init_parent(struct clk *clk) | |||
1614 | 1613 | ||
1615 | if (clk->num_parents == 1) { | 1614 | if (clk->num_parents == 1) { |
1616 | if (IS_ERR_OR_NULL(clk->parent)) | 1615 | if (IS_ERR_OR_NULL(clk->parent)) |
1617 | ret = clk->parent = __clk_lookup(clk->parent_names[0]); | 1616 | clk->parent = __clk_lookup(clk->parent_names[0]); |
1618 | ret = clk->parent; | 1617 | ret = clk->parent; |
1619 | goto out; | 1618 | goto out; |
1620 | } | 1619 | } |
@@ -1944,7 +1943,6 @@ int __clk_init(struct device *dev, struct clk *clk) | |||
1944 | else | 1943 | else |
1945 | clk->rate = 0; | 1944 | clk->rate = 0; |
1946 | 1945 | ||
1947 | clk_debug_register(clk); | ||
1948 | /* | 1946 | /* |
1949 | * walk the list of orphan clocks and reparent any that are children of | 1947 | * walk the list of orphan clocks and reparent any that are children of |
1950 | * this clock | 1948 | * this clock |
@@ -1979,6 +1977,9 @@ int __clk_init(struct device *dev, struct clk *clk) | |||
1979 | out: | 1977 | out: |
1980 | clk_prepare_unlock(); | 1978 | clk_prepare_unlock(); |
1981 | 1979 | ||
1980 | if (!ret) | ||
1981 | clk_debug_register(clk); | ||
1982 | |||
1982 | return ret; | 1983 | return ret; |
1983 | } | 1984 | } |
1984 | 1985 | ||
@@ -2273,14 +2274,17 @@ int __clk_get(struct clk *clk) | |||
2273 | 2274 | ||
2274 | void __clk_put(struct clk *clk) | 2275 | void __clk_put(struct clk *clk) |
2275 | { | 2276 | { |
2277 | struct module *owner; | ||
2278 | |||
2276 | if (!clk || WARN_ON_ONCE(IS_ERR(clk))) | 2279 | if (!clk || WARN_ON_ONCE(IS_ERR(clk))) |
2277 | return; | 2280 | return; |
2278 | 2281 | ||
2279 | clk_prepare_lock(); | 2282 | clk_prepare_lock(); |
2283 | owner = clk->owner; | ||
2280 | kref_put(&clk->ref, __clk_release); | 2284 | kref_put(&clk->ref, __clk_release); |
2281 | clk_prepare_unlock(); | 2285 | clk_prepare_unlock(); |
2282 | 2286 | ||
2283 | module_put(clk->owner); | 2287 | module_put(owner); |
2284 | } | 2288 | } |
2285 | 2289 | ||
2286 | /*** clk rate change notifiers ***/ | 2290 | /*** clk rate change notifiers ***/ |
diff --git a/drivers/clk/hisilicon/clk-hi3620.c b/drivers/clk/hisilicon/clk-hi3620.c index 339945d2503b..007144f81f50 100644 --- a/drivers/clk/hisilicon/clk-hi3620.c +++ b/drivers/clk/hisilicon/clk-hi3620.c | |||
@@ -38,44 +38,44 @@ | |||
38 | #include "clk.h" | 38 | #include "clk.h" |
39 | 39 | ||
40 | /* clock parent list */ | 40 | /* clock parent list */ |
41 | static const char *timer0_mux_p[] __initdata = { "osc32k", "timerclk01", }; | 41 | static const char *timer0_mux_p[] __initconst = { "osc32k", "timerclk01", }; |
42 | static const char *timer1_mux_p[] __initdata = { "osc32k", "timerclk01", }; | 42 | static const char *timer1_mux_p[] __initconst = { "osc32k", "timerclk01", }; |
43 | static const char *timer2_mux_p[] __initdata = { "osc32k", "timerclk23", }; | 43 | static const char *timer2_mux_p[] __initconst = { "osc32k", "timerclk23", }; |
44 | static const char *timer3_mux_p[] __initdata = { "osc32k", "timerclk23", }; | 44 | static const char *timer3_mux_p[] __initconst = { "osc32k", "timerclk23", }; |
45 | static const char *timer4_mux_p[] __initdata = { "osc32k", "timerclk45", }; | 45 | static const char *timer4_mux_p[] __initconst = { "osc32k", "timerclk45", }; |
46 | static const char *timer5_mux_p[] __initdata = { "osc32k", "timerclk45", }; | 46 | static const char *timer5_mux_p[] __initconst = { "osc32k", "timerclk45", }; |
47 | static const char *timer6_mux_p[] __initdata = { "osc32k", "timerclk67", }; | 47 | static const char *timer6_mux_p[] __initconst = { "osc32k", "timerclk67", }; |
48 | static const char *timer7_mux_p[] __initdata = { "osc32k", "timerclk67", }; | 48 | static const char *timer7_mux_p[] __initconst = { "osc32k", "timerclk67", }; |
49 | static const char *timer8_mux_p[] __initdata = { "osc32k", "timerclk89", }; | 49 | static const char *timer8_mux_p[] __initconst = { "osc32k", "timerclk89", }; |
50 | static const char *timer9_mux_p[] __initdata = { "osc32k", "timerclk89", }; | 50 | static const char *timer9_mux_p[] __initconst = { "osc32k", "timerclk89", }; |
51 | static const char *uart0_mux_p[] __initdata = { "osc26m", "pclk", }; | 51 | static const char *uart0_mux_p[] __initconst = { "osc26m", "pclk", }; |
52 | static const char *uart1_mux_p[] __initdata = { "osc26m", "pclk", }; | 52 | static const char *uart1_mux_p[] __initconst = { "osc26m", "pclk", }; |
53 | static const char *uart2_mux_p[] __initdata = { "osc26m", "pclk", }; | 53 | static const char *uart2_mux_p[] __initconst = { "osc26m", "pclk", }; |
54 | static const char *uart3_mux_p[] __initdata = { "osc26m", "pclk", }; | 54 | static const char *uart3_mux_p[] __initconst = { "osc26m", "pclk", }; |
55 | static const char *uart4_mux_p[] __initdata = { "osc26m", "pclk", }; | 55 | static const char *uart4_mux_p[] __initconst = { "osc26m", "pclk", }; |
56 | static const char *spi0_mux_p[] __initdata = { "osc26m", "rclk_cfgaxi", }; | 56 | static const char *spi0_mux_p[] __initconst = { "osc26m", "rclk_cfgaxi", }; |
57 | static const char *spi1_mux_p[] __initdata = { "osc26m", "rclk_cfgaxi", }; | 57 | static const char *spi1_mux_p[] __initconst = { "osc26m", "rclk_cfgaxi", }; |
58 | static const char *spi2_mux_p[] __initdata = { "osc26m", "rclk_cfgaxi", }; | 58 | static const char *spi2_mux_p[] __initconst = { "osc26m", "rclk_cfgaxi", }; |
59 | /* share axi parent */ | 59 | /* share axi parent */ |
60 | static const char *saxi_mux_p[] __initdata = { "armpll3", "armpll2", }; | 60 | static const char *saxi_mux_p[] __initconst = { "armpll3", "armpll2", }; |
61 | static const char *pwm0_mux_p[] __initdata = { "osc32k", "osc26m", }; | 61 | static const char *pwm0_mux_p[] __initconst = { "osc32k", "osc26m", }; |
62 | static const char *pwm1_mux_p[] __initdata = { "osc32k", "osc26m", }; | 62 | static const char *pwm1_mux_p[] __initconst = { "osc32k", "osc26m", }; |
63 | static const char *sd_mux_p[] __initdata = { "armpll2", "armpll3", }; | 63 | static const char *sd_mux_p[] __initconst = { "armpll2", "armpll3", }; |
64 | static const char *mmc1_mux_p[] __initdata = { "armpll2", "armpll3", }; | 64 | static const char *mmc1_mux_p[] __initconst = { "armpll2", "armpll3", }; |
65 | static const char *mmc1_mux2_p[] __initdata = { "osc26m", "mmc1_div", }; | 65 | static const char *mmc1_mux2_p[] __initconst = { "osc26m", "mmc1_div", }; |
66 | static const char *g2d_mux_p[] __initdata = { "armpll2", "armpll3", }; | 66 | static const char *g2d_mux_p[] __initconst = { "armpll2", "armpll3", }; |
67 | static const char *venc_mux_p[] __initdata = { "armpll2", "armpll3", }; | 67 | static const char *venc_mux_p[] __initconst = { "armpll2", "armpll3", }; |
68 | static const char *vdec_mux_p[] __initdata = { "armpll2", "armpll3", }; | 68 | static const char *vdec_mux_p[] __initconst = { "armpll2", "armpll3", }; |
69 | static const char *vpp_mux_p[] __initdata = { "armpll2", "armpll3", }; | 69 | static const char *vpp_mux_p[] __initconst = { "armpll2", "armpll3", }; |
70 | static const char *edc0_mux_p[] __initdata = { "armpll2", "armpll3", }; | 70 | static const char *edc0_mux_p[] __initconst = { "armpll2", "armpll3", }; |
71 | static const char *ldi0_mux_p[] __initdata = { "armpll2", "armpll4", | 71 | static const char *ldi0_mux_p[] __initconst = { "armpll2", "armpll4", |
72 | "armpll3", "armpll5", }; | 72 | "armpll3", "armpll5", }; |
73 | static const char *edc1_mux_p[] __initdata = { "armpll2", "armpll3", }; | 73 | static const char *edc1_mux_p[] __initconst = { "armpll2", "armpll3", }; |
74 | static const char *ldi1_mux_p[] __initdata = { "armpll2", "armpll4", | 74 | static const char *ldi1_mux_p[] __initconst = { "armpll2", "armpll4", |
75 | "armpll3", "armpll5", }; | 75 | "armpll3", "armpll5", }; |
76 | static const char *rclk_hsic_p[] __initdata = { "armpll3", "armpll2", }; | 76 | static const char *rclk_hsic_p[] __initconst = { "armpll3", "armpll2", }; |
77 | static const char *mmc2_mux_p[] __initdata = { "armpll2", "armpll3", }; | 77 | static const char *mmc2_mux_p[] __initconst = { "armpll2", "armpll3", }; |
78 | static const char *mmc3_mux_p[] __initdata = { "armpll2", "armpll3", }; | 78 | static const char *mmc3_mux_p[] __initconst = { "armpll2", "armpll3", }; |
79 | 79 | ||
80 | 80 | ||
81 | /* fixed rate clocks */ | 81 | /* fixed rate clocks */ |
@@ -296,7 +296,7 @@ static unsigned long mmc_clk_recalc_rate(struct clk_hw *hw, | |||
296 | 296 | ||
297 | static long mmc_clk_determine_rate(struct clk_hw *hw, unsigned long rate, | 297 | static long mmc_clk_determine_rate(struct clk_hw *hw, unsigned long rate, |
298 | unsigned long *best_parent_rate, | 298 | unsigned long *best_parent_rate, |
299 | struct clk **best_parent_p) | 299 | struct clk_hw **best_parent_p) |
300 | { | 300 | { |
301 | struct clk_mmc *mclk = to_mmc(hw); | 301 | struct clk_mmc *mclk = to_mmc(hw); |
302 | unsigned long best = 0; | 302 | unsigned long best = 0; |
diff --git a/drivers/clk/mmp/Makefile b/drivers/clk/mmp/Makefile index 392d78044ce3..3caaf7cc169c 100644 --- a/drivers/clk/mmp/Makefile +++ b/drivers/clk/mmp/Makefile | |||
@@ -2,7 +2,12 @@ | |||
2 | # Makefile for mmp specific clk | 2 | # Makefile for mmp specific clk |
3 | # | 3 | # |
4 | 4 | ||
5 | obj-y += clk-apbc.o clk-apmu.o clk-frac.o | 5 | obj-y += clk-apbc.o clk-apmu.o clk-frac.o clk-mix.o clk-gate.o clk.o |
6 | |||
7 | obj-$(CONFIG_RESET_CONTROLLER) += reset.o | ||
8 | |||
9 | obj-$(CONFIG_MACH_MMP_DT) += clk-of-pxa168.o clk-of-pxa910.o | ||
10 | obj-$(CONFIG_MACH_MMP2_DT) += clk-of-mmp2.o | ||
6 | 11 | ||
7 | obj-$(CONFIG_CPU_PXA168) += clk-pxa168.o | 12 | obj-$(CONFIG_CPU_PXA168) += clk-pxa168.o |
8 | obj-$(CONFIG_CPU_PXA910) += clk-pxa910.o | 13 | obj-$(CONFIG_CPU_PXA910) += clk-pxa910.o |
diff --git a/drivers/clk/mmp/clk-frac.c b/drivers/clk/mmp/clk-frac.c index 23a56f561812..584a9927993b 100644 --- a/drivers/clk/mmp/clk-frac.c +++ b/drivers/clk/mmp/clk-frac.c | |||
@@ -22,19 +22,12 @@ | |||
22 | * numerator/denominator = Fin / (Fout * factor) | 22 | * numerator/denominator = Fin / (Fout * factor) |
23 | */ | 23 | */ |
24 | 24 | ||
25 | #define to_clk_factor(hw) container_of(hw, struct clk_factor, hw) | 25 | #define to_clk_factor(hw) container_of(hw, struct mmp_clk_factor, hw) |
26 | struct clk_factor { | ||
27 | struct clk_hw hw; | ||
28 | void __iomem *base; | ||
29 | struct clk_factor_masks *masks; | ||
30 | struct clk_factor_tbl *ftbl; | ||
31 | unsigned int ftbl_cnt; | ||
32 | }; | ||
33 | 26 | ||
34 | static long clk_factor_round_rate(struct clk_hw *hw, unsigned long drate, | 27 | static long clk_factor_round_rate(struct clk_hw *hw, unsigned long drate, |
35 | unsigned long *prate) | 28 | unsigned long *prate) |
36 | { | 29 | { |
37 | struct clk_factor *factor = to_clk_factor(hw); | 30 | struct mmp_clk_factor *factor = to_clk_factor(hw); |
38 | unsigned long rate = 0, prev_rate; | 31 | unsigned long rate = 0, prev_rate; |
39 | int i; | 32 | int i; |
40 | 33 | ||
@@ -58,8 +51,8 @@ static long clk_factor_round_rate(struct clk_hw *hw, unsigned long drate, | |||
58 | static unsigned long clk_factor_recalc_rate(struct clk_hw *hw, | 51 | static unsigned long clk_factor_recalc_rate(struct clk_hw *hw, |
59 | unsigned long parent_rate) | 52 | unsigned long parent_rate) |
60 | { | 53 | { |
61 | struct clk_factor *factor = to_clk_factor(hw); | 54 | struct mmp_clk_factor *factor = to_clk_factor(hw); |
62 | struct clk_factor_masks *masks = factor->masks; | 55 | struct mmp_clk_factor_masks *masks = factor->masks; |
63 | unsigned int val, num, den; | 56 | unsigned int val, num, den; |
64 | 57 | ||
65 | val = readl_relaxed(factor->base); | 58 | val = readl_relaxed(factor->base); |
@@ -81,11 +74,12 @@ static unsigned long clk_factor_recalc_rate(struct clk_hw *hw, | |||
81 | static int clk_factor_set_rate(struct clk_hw *hw, unsigned long drate, | 74 | static int clk_factor_set_rate(struct clk_hw *hw, unsigned long drate, |
82 | unsigned long prate) | 75 | unsigned long prate) |
83 | { | 76 | { |
84 | struct clk_factor *factor = to_clk_factor(hw); | 77 | struct mmp_clk_factor *factor = to_clk_factor(hw); |
85 | struct clk_factor_masks *masks = factor->masks; | 78 | struct mmp_clk_factor_masks *masks = factor->masks; |
86 | int i; | 79 | int i; |
87 | unsigned long val; | 80 | unsigned long val; |
88 | unsigned long prev_rate, rate = 0; | 81 | unsigned long prev_rate, rate = 0; |
82 | unsigned long flags = 0; | ||
89 | 83 | ||
90 | for (i = 0; i < factor->ftbl_cnt; i++) { | 84 | for (i = 0; i < factor->ftbl_cnt; i++) { |
91 | prev_rate = rate; | 85 | prev_rate = rate; |
@@ -97,6 +91,9 @@ static int clk_factor_set_rate(struct clk_hw *hw, unsigned long drate, | |||
97 | if (i > 0) | 91 | if (i > 0) |
98 | i--; | 92 | i--; |
99 | 93 | ||
94 | if (factor->lock) | ||
95 | spin_lock_irqsave(factor->lock, flags); | ||
96 | |||
100 | val = readl_relaxed(factor->base); | 97 | val = readl_relaxed(factor->base); |
101 | 98 | ||
102 | val &= ~(masks->num_mask << masks->num_shift); | 99 | val &= ~(masks->num_mask << masks->num_shift); |
@@ -107,21 +104,65 @@ static int clk_factor_set_rate(struct clk_hw *hw, unsigned long drate, | |||
107 | 104 | ||
108 | writel_relaxed(val, factor->base); | 105 | writel_relaxed(val, factor->base); |
109 | 106 | ||
107 | if (factor->lock) | ||
108 | spin_unlock_irqrestore(factor->lock, flags); | ||
109 | |||
110 | return 0; | 110 | return 0; |
111 | } | 111 | } |
112 | 112 | ||
113 | static void clk_factor_init(struct clk_hw *hw) | ||
114 | { | ||
115 | struct mmp_clk_factor *factor = to_clk_factor(hw); | ||
116 | struct mmp_clk_factor_masks *masks = factor->masks; | ||
117 | u32 val, num, den; | ||
118 | int i; | ||
119 | unsigned long flags = 0; | ||
120 | |||
121 | if (factor->lock) | ||
122 | spin_lock_irqsave(factor->lock, flags); | ||
123 | |||
124 | val = readl(factor->base); | ||
125 | |||
126 | /* calculate numerator */ | ||
127 | num = (val >> masks->num_shift) & masks->num_mask; | ||
128 | |||
129 | /* calculate denominator */ | ||
130 | den = (val >> masks->den_shift) & masks->den_mask; | ||
131 | |||
132 | for (i = 0; i < factor->ftbl_cnt; i++) | ||
133 | if (den == factor->ftbl[i].den && num == factor->ftbl[i].num) | ||
134 | break; | ||
135 | |||
136 | if (i >= factor->ftbl_cnt) { | ||
137 | val &= ~(masks->num_mask << masks->num_shift); | ||
138 | val |= (factor->ftbl[0].num & masks->num_mask) << | ||
139 | masks->num_shift; | ||
140 | |||
141 | val &= ~(masks->den_mask << masks->den_shift); | ||
142 | val |= (factor->ftbl[0].den & masks->den_mask) << | ||
143 | masks->den_shift; | ||
144 | |||
145 | writel(val, factor->base); | ||
146 | } | ||
147 | |||
148 | if (factor->lock) | ||
149 | spin_unlock_irqrestore(factor->lock, flags); | ||
150 | } | ||
151 | |||
113 | static struct clk_ops clk_factor_ops = { | 152 | static struct clk_ops clk_factor_ops = { |
114 | .recalc_rate = clk_factor_recalc_rate, | 153 | .recalc_rate = clk_factor_recalc_rate, |
115 | .round_rate = clk_factor_round_rate, | 154 | .round_rate = clk_factor_round_rate, |
116 | .set_rate = clk_factor_set_rate, | 155 | .set_rate = clk_factor_set_rate, |
156 | .init = clk_factor_init, | ||
117 | }; | 157 | }; |
118 | 158 | ||
119 | struct clk *mmp_clk_register_factor(const char *name, const char *parent_name, | 159 | struct clk *mmp_clk_register_factor(const char *name, const char *parent_name, |
120 | unsigned long flags, void __iomem *base, | 160 | unsigned long flags, void __iomem *base, |
121 | struct clk_factor_masks *masks, struct clk_factor_tbl *ftbl, | 161 | struct mmp_clk_factor_masks *masks, |
122 | unsigned int ftbl_cnt) | 162 | struct mmp_clk_factor_tbl *ftbl, |
163 | unsigned int ftbl_cnt, spinlock_t *lock) | ||
123 | { | 164 | { |
124 | struct clk_factor *factor; | 165 | struct mmp_clk_factor *factor; |
125 | struct clk_init_data init; | 166 | struct clk_init_data init; |
126 | struct clk *clk; | 167 | struct clk *clk; |
127 | 168 | ||
@@ -142,6 +183,7 @@ struct clk *mmp_clk_register_factor(const char *name, const char *parent_name, | |||
142 | factor->ftbl = ftbl; | 183 | factor->ftbl = ftbl; |
143 | factor->ftbl_cnt = ftbl_cnt; | 184 | factor->ftbl_cnt = ftbl_cnt; |
144 | factor->hw.init = &init; | 185 | factor->hw.init = &init; |
186 | factor->lock = lock; | ||
145 | 187 | ||
146 | init.name = name; | 188 | init.name = name; |
147 | init.ops = &clk_factor_ops; | 189 | init.ops = &clk_factor_ops; |
diff --git a/drivers/clk/mmp/clk-gate.c b/drivers/clk/mmp/clk-gate.c new file mode 100644 index 000000000000..adbd9d64ded2 --- /dev/null +++ b/drivers/clk/mmp/clk-gate.c | |||
@@ -0,0 +1,133 @@ | |||
1 | /* | ||
2 | * mmp gate clock operation source file | ||
3 | * | ||
4 | * Copyright (C) 2014 Marvell | ||
5 | * Chao Xie <chao.xie@marvell.com> | ||
6 | * | ||
7 | * This file is licensed under the terms of the GNU General Public | ||
8 | * License version 2. This program is licensed "as is" without any | ||
9 | * warranty of any kind, whether express or implied. | ||
10 | */ | ||
11 | |||
12 | #include <linux/clk-provider.h> | ||
13 | #include <linux/slab.h> | ||
14 | #include <linux/io.h> | ||
15 | #include <linux/err.h> | ||
16 | #include <linux/delay.h> | ||
17 | |||
18 | #include "clk.h" | ||
19 | |||
20 | /* | ||
21 | * Some clocks will have mutiple bits to enable the clocks, and | ||
22 | * the bits to disable the clock is not same as enabling bits. | ||
23 | */ | ||
24 | |||
25 | #define to_clk_mmp_gate(hw) container_of(hw, struct mmp_clk_gate, hw) | ||
26 | |||
27 | static int mmp_clk_gate_enable(struct clk_hw *hw) | ||
28 | { | ||
29 | struct mmp_clk_gate *gate = to_clk_mmp_gate(hw); | ||
30 | struct clk *clk = hw->clk; | ||
31 | unsigned long flags = 0; | ||
32 | unsigned long rate; | ||
33 | u32 tmp; | ||
34 | |||
35 | if (gate->lock) | ||
36 | spin_lock_irqsave(gate->lock, flags); | ||
37 | |||
38 | tmp = readl(gate->reg); | ||
39 | tmp &= ~gate->mask; | ||
40 | tmp |= gate->val_enable; | ||
41 | writel(tmp, gate->reg); | ||
42 | |||
43 | if (gate->lock) | ||
44 | spin_unlock_irqrestore(gate->lock, flags); | ||
45 | |||
46 | if (gate->flags & MMP_CLK_GATE_NEED_DELAY) { | ||
47 | rate = __clk_get_rate(clk); | ||
48 | /* Need delay 2 cycles. */ | ||
49 | udelay(2000000/rate); | ||
50 | } | ||
51 | |||
52 | return 0; | ||
53 | } | ||
54 | |||
55 | static void mmp_clk_gate_disable(struct clk_hw *hw) | ||
56 | { | ||
57 | struct mmp_clk_gate *gate = to_clk_mmp_gate(hw); | ||
58 | unsigned long flags = 0; | ||
59 | u32 tmp; | ||
60 | |||
61 | if (gate->lock) | ||
62 | spin_lock_irqsave(gate->lock, flags); | ||
63 | |||
64 | tmp = readl(gate->reg); | ||
65 | tmp &= ~gate->mask; | ||
66 | tmp |= gate->val_disable; | ||
67 | writel(tmp, gate->reg); | ||
68 | |||
69 | if (gate->lock) | ||
70 | spin_unlock_irqrestore(gate->lock, flags); | ||
71 | } | ||
72 | |||
73 | static int mmp_clk_gate_is_enabled(struct clk_hw *hw) | ||
74 | { | ||
75 | struct mmp_clk_gate *gate = to_clk_mmp_gate(hw); | ||
76 | unsigned long flags = 0; | ||
77 | u32 tmp; | ||
78 | |||
79 | if (gate->lock) | ||
80 | spin_lock_irqsave(gate->lock, flags); | ||
81 | |||
82 | tmp = readl(gate->reg); | ||
83 | |||
84 | if (gate->lock) | ||
85 | spin_unlock_irqrestore(gate->lock, flags); | ||
86 | |||
87 | return (tmp & gate->mask) == gate->val_enable; | ||
88 | } | ||
89 | |||
90 | const struct clk_ops mmp_clk_gate_ops = { | ||
91 | .enable = mmp_clk_gate_enable, | ||
92 | .disable = mmp_clk_gate_disable, | ||
93 | .is_enabled = mmp_clk_gate_is_enabled, | ||
94 | }; | ||
95 | |||
96 | struct clk *mmp_clk_register_gate(struct device *dev, const char *name, | ||
97 | const char *parent_name, unsigned long flags, | ||
98 | void __iomem *reg, u32 mask, u32 val_enable, u32 val_disable, | ||
99 | unsigned int gate_flags, spinlock_t *lock) | ||
100 | { | ||
101 | struct mmp_clk_gate *gate; | ||
102 | struct clk *clk; | ||
103 | struct clk_init_data init; | ||
104 | |||
105 | /* allocate the gate */ | ||
106 | gate = kzalloc(sizeof(*gate), GFP_KERNEL); | ||
107 | if (!gate) { | ||
108 | pr_err("%s:%s could not allocate gate clk\n", __func__, name); | ||
109 | return ERR_PTR(-ENOMEM); | ||
110 | } | ||
111 | |||
112 | init.name = name; | ||
113 | init.ops = &mmp_clk_gate_ops; | ||
114 | init.flags = flags | CLK_IS_BASIC; | ||
115 | init.parent_names = (parent_name ? &parent_name : NULL); | ||
116 | init.num_parents = (parent_name ? 1 : 0); | ||
117 | |||
118 | /* struct clk_gate assignments */ | ||
119 | gate->reg = reg; | ||
120 | gate->mask = mask; | ||
121 | gate->val_enable = val_enable; | ||
122 | gate->val_disable = val_disable; | ||
123 | gate->flags = gate_flags; | ||
124 | gate->lock = lock; | ||
125 | gate->hw.init = &init; | ||
126 | |||
127 | clk = clk_register(dev, &gate->hw); | ||
128 | |||
129 | if (IS_ERR(clk)) | ||
130 | kfree(gate); | ||
131 | |||
132 | return clk; | ||
133 | } | ||
diff --git a/drivers/clk/mmp/clk-mix.c b/drivers/clk/mmp/clk-mix.c new file mode 100644 index 000000000000..48fa53c7ce5e --- /dev/null +++ b/drivers/clk/mmp/clk-mix.c | |||
@@ -0,0 +1,513 @@ | |||
1 | /* | ||
2 | * mmp mix(div and mux) clock operation source file | ||
3 | * | ||
4 | * Copyright (C) 2014 Marvell | ||
5 | * Chao Xie <chao.xie@marvell.com> | ||
6 | * | ||
7 | * This file is licensed under the terms of the GNU General Public | ||
8 | * License version 2. This program is licensed "as is" without any | ||
9 | * warranty of any kind, whether express or implied. | ||
10 | */ | ||
11 | |||
12 | #include <linux/clk-provider.h> | ||
13 | #include <linux/slab.h> | ||
14 | #include <linux/io.h> | ||
15 | #include <linux/err.h> | ||
16 | |||
17 | #include "clk.h" | ||
18 | |||
19 | /* | ||
20 | * The mix clock is a clock combined mux and div type clock. | ||
21 | * Because the div field and mux field need to be set at same | ||
22 | * time, we can not divide it into 2 types of clock | ||
23 | */ | ||
24 | |||
25 | #define to_clk_mix(hw) container_of(hw, struct mmp_clk_mix, hw) | ||
26 | |||
27 | static unsigned int _get_maxdiv(struct mmp_clk_mix *mix) | ||
28 | { | ||
29 | unsigned int div_mask = (1 << mix->reg_info.width_div) - 1; | ||
30 | unsigned int maxdiv = 0; | ||
31 | struct clk_div_table *clkt; | ||
32 | |||
33 | if (mix->div_flags & CLK_DIVIDER_ONE_BASED) | ||
34 | return div_mask; | ||
35 | if (mix->div_flags & CLK_DIVIDER_POWER_OF_TWO) | ||
36 | return 1 << div_mask; | ||
37 | if (mix->div_table) { | ||
38 | for (clkt = mix->div_table; clkt->div; clkt++) | ||
39 | if (clkt->div > maxdiv) | ||
40 | maxdiv = clkt->div; | ||
41 | return maxdiv; | ||
42 | } | ||
43 | return div_mask + 1; | ||
44 | } | ||
45 | |||
46 | static unsigned int _get_div(struct mmp_clk_mix *mix, unsigned int val) | ||
47 | { | ||
48 | struct clk_div_table *clkt; | ||
49 | |||
50 | if (mix->div_flags & CLK_DIVIDER_ONE_BASED) | ||
51 | return val; | ||
52 | if (mix->div_flags & CLK_DIVIDER_POWER_OF_TWO) | ||
53 | return 1 << val; | ||
54 | if (mix->div_table) { | ||
55 | for (clkt = mix->div_table; clkt->div; clkt++) | ||
56 | if (clkt->val == val) | ||
57 | return clkt->div; | ||
58 | if (clkt->div == 0) | ||
59 | return 0; | ||
60 | } | ||
61 | return val + 1; | ||
62 | } | ||
63 | |||
64 | static unsigned int _get_mux(struct mmp_clk_mix *mix, unsigned int val) | ||
65 | { | ||
66 | int num_parents = __clk_get_num_parents(mix->hw.clk); | ||
67 | int i; | ||
68 | |||
69 | if (mix->mux_flags & CLK_MUX_INDEX_BIT) | ||
70 | return ffs(val) - 1; | ||
71 | if (mix->mux_flags & CLK_MUX_INDEX_ONE) | ||
72 | return val - 1; | ||
73 | if (mix->mux_table) { | ||
74 | for (i = 0; i < num_parents; i++) | ||
75 | if (mix->mux_table[i] == val) | ||
76 | return i; | ||
77 | if (i == num_parents) | ||
78 | return 0; | ||
79 | } | ||
80 | |||
81 | return val; | ||
82 | } | ||
83 | static unsigned int _get_div_val(struct mmp_clk_mix *mix, unsigned int div) | ||
84 | { | ||
85 | struct clk_div_table *clkt; | ||
86 | |||
87 | if (mix->div_flags & CLK_DIVIDER_ONE_BASED) | ||
88 | return div; | ||
89 | if (mix->div_flags & CLK_DIVIDER_POWER_OF_TWO) | ||
90 | return __ffs(div); | ||
91 | if (mix->div_table) { | ||
92 | for (clkt = mix->div_table; clkt->div; clkt++) | ||
93 | if (clkt->div == div) | ||
94 | return clkt->val; | ||
95 | if (clkt->div == 0) | ||
96 | return 0; | ||
97 | } | ||
98 | |||
99 | return div - 1; | ||
100 | } | ||
101 | |||
102 | static unsigned int _get_mux_val(struct mmp_clk_mix *mix, unsigned int mux) | ||
103 | { | ||
104 | if (mix->mux_table) | ||
105 | return mix->mux_table[mux]; | ||
106 | |||
107 | return mux; | ||
108 | } | ||
109 | |||
110 | static void _filter_clk_table(struct mmp_clk_mix *mix, | ||
111 | struct mmp_clk_mix_clk_table *table, | ||
112 | unsigned int table_size) | ||
113 | { | ||
114 | int i; | ||
115 | struct mmp_clk_mix_clk_table *item; | ||
116 | struct clk *parent, *clk; | ||
117 | unsigned long parent_rate; | ||
118 | |||
119 | clk = mix->hw.clk; | ||
120 | |||
121 | for (i = 0; i < table_size; i++) { | ||
122 | item = &table[i]; | ||
123 | parent = clk_get_parent_by_index(clk, item->parent_index); | ||
124 | parent_rate = __clk_get_rate(parent); | ||
125 | if (parent_rate % item->rate) { | ||
126 | item->valid = 0; | ||
127 | } else { | ||
128 | item->divisor = parent_rate / item->rate; | ||
129 | item->valid = 1; | ||
130 | } | ||
131 | } | ||
132 | } | ||
133 | |||
134 | static int _set_rate(struct mmp_clk_mix *mix, u32 mux_val, u32 div_val, | ||
135 | unsigned int change_mux, unsigned int change_div) | ||
136 | { | ||
137 | struct mmp_clk_mix_reg_info *ri = &mix->reg_info; | ||
138 | u8 width, shift; | ||
139 | u32 mux_div, fc_req; | ||
140 | int ret, timeout = 50; | ||
141 | unsigned long flags = 0; | ||
142 | |||
143 | if (!change_mux && !change_div) | ||
144 | return -EINVAL; | ||
145 | |||
146 | if (mix->lock) | ||
147 | spin_lock_irqsave(mix->lock, flags); | ||
148 | |||
149 | if (mix->type == MMP_CLK_MIX_TYPE_V1 | ||
150 | || mix->type == MMP_CLK_MIX_TYPE_V2) | ||
151 | mux_div = readl(ri->reg_clk_ctrl); | ||
152 | else | ||
153 | mux_div = readl(ri->reg_clk_sel); | ||
154 | |||
155 | if (change_div) { | ||
156 | width = ri->width_div; | ||
157 | shift = ri->shift_div; | ||
158 | mux_div &= ~MMP_CLK_BITS_MASK(width, shift); | ||
159 | mux_div |= MMP_CLK_BITS_SET_VAL(div_val, width, shift); | ||
160 | } | ||
161 | |||
162 | if (change_mux) { | ||
163 | width = ri->width_mux; | ||
164 | shift = ri->shift_mux; | ||
165 | mux_div &= ~MMP_CLK_BITS_MASK(width, shift); | ||
166 | mux_div |= MMP_CLK_BITS_SET_VAL(mux_val, width, shift); | ||
167 | } | ||
168 | |||
169 | if (mix->type == MMP_CLK_MIX_TYPE_V1) { | ||
170 | writel(mux_div, ri->reg_clk_ctrl); | ||
171 | } else if (mix->type == MMP_CLK_MIX_TYPE_V2) { | ||
172 | mux_div |= (1 << ri->bit_fc); | ||
173 | writel(mux_div, ri->reg_clk_ctrl); | ||
174 | |||
175 | do { | ||
176 | fc_req = readl(ri->reg_clk_ctrl); | ||
177 | timeout--; | ||
178 | if (!(fc_req & (1 << ri->bit_fc))) | ||
179 | break; | ||
180 | } while (timeout); | ||
181 | |||
182 | if (timeout == 0) { | ||
183 | pr_err("%s:%s cannot do frequency change\n", | ||
184 | __func__, __clk_get_name(mix->hw.clk)); | ||
185 | ret = -EBUSY; | ||
186 | goto error; | ||
187 | } | ||
188 | } else { | ||
189 | fc_req = readl(ri->reg_clk_ctrl); | ||
190 | fc_req |= 1 << ri->bit_fc; | ||
191 | writel(fc_req, ri->reg_clk_ctrl); | ||
192 | writel(mux_div, ri->reg_clk_sel); | ||
193 | fc_req &= ~(1 << ri->bit_fc); | ||
194 | } | ||
195 | |||
196 | ret = 0; | ||
197 | error: | ||
198 | if (mix->lock) | ||
199 | spin_unlock_irqrestore(mix->lock, flags); | ||
200 | |||
201 | return ret; | ||
202 | } | ||
203 | |||
204 | static long mmp_clk_mix_determine_rate(struct clk_hw *hw, unsigned long rate, | ||
205 | unsigned long *best_parent_rate, | ||
206 | struct clk_hw **best_parent_clk) | ||
207 | { | ||
208 | struct mmp_clk_mix *mix = to_clk_mix(hw); | ||
209 | struct mmp_clk_mix_clk_table *item; | ||
210 | struct clk *parent, *parent_best, *mix_clk; | ||
211 | unsigned long parent_rate, mix_rate, mix_rate_best, parent_rate_best; | ||
212 | unsigned long gap, gap_best; | ||
213 | u32 div_val_max; | ||
214 | unsigned int div; | ||
215 | int i, j; | ||
216 | |||
217 | mix_clk = hw->clk; | ||
218 | |||
219 | parent = NULL; | ||
220 | mix_rate_best = 0; | ||
221 | parent_rate_best = 0; | ||
222 | gap_best = rate; | ||
223 | parent_best = NULL; | ||
224 | |||
225 | if (mix->table) { | ||
226 | for (i = 0; i < mix->table_size; i++) { | ||
227 | item = &mix->table[i]; | ||
228 | if (item->valid == 0) | ||
229 | continue; | ||
230 | parent = clk_get_parent_by_index(mix_clk, | ||
231 | item->parent_index); | ||
232 | parent_rate = __clk_get_rate(parent); | ||
233 | mix_rate = parent_rate / item->divisor; | ||
234 | gap = abs(mix_rate - rate); | ||
235 | if (parent_best == NULL || gap < gap_best) { | ||
236 | parent_best = parent; | ||
237 | parent_rate_best = parent_rate; | ||
238 | mix_rate_best = mix_rate; | ||
239 | gap_best = gap; | ||
240 | if (gap_best == 0) | ||
241 | goto found; | ||
242 | } | ||
243 | } | ||
244 | } else { | ||
245 | for (i = 0; i < __clk_get_num_parents(mix_clk); i++) { | ||
246 | parent = clk_get_parent_by_index(mix_clk, i); | ||
247 | parent_rate = __clk_get_rate(parent); | ||
248 | div_val_max = _get_maxdiv(mix); | ||
249 | for (j = 0; j < div_val_max; j++) { | ||
250 | div = _get_div(mix, j); | ||
251 | mix_rate = parent_rate / div; | ||
252 | gap = abs(mix_rate - rate); | ||
253 | if (parent_best == NULL || gap < gap_best) { | ||
254 | parent_best = parent; | ||
255 | parent_rate_best = parent_rate; | ||
256 | mix_rate_best = mix_rate; | ||
257 | gap_best = gap; | ||
258 | if (gap_best == 0) | ||
259 | goto found; | ||
260 | } | ||
261 | } | ||
262 | } | ||
263 | } | ||
264 | |||
265 | found: | ||
266 | *best_parent_rate = parent_rate_best; | ||
267 | *best_parent_clk = __clk_get_hw(parent_best); | ||
268 | |||
269 | return mix_rate_best; | ||
270 | } | ||
271 | |||
272 | static int mmp_clk_mix_set_rate_and_parent(struct clk_hw *hw, | ||
273 | unsigned long rate, | ||
274 | unsigned long parent_rate, | ||
275 | u8 index) | ||
276 | { | ||
277 | struct mmp_clk_mix *mix = to_clk_mix(hw); | ||
278 | unsigned int div; | ||
279 | u32 div_val, mux_val; | ||
280 | |||
281 | div = parent_rate / rate; | ||
282 | div_val = _get_div_val(mix, div); | ||
283 | mux_val = _get_mux_val(mix, index); | ||
284 | |||
285 | return _set_rate(mix, mux_val, div_val, 1, 1); | ||
286 | } | ||
287 | |||
288 | static u8 mmp_clk_mix_get_parent(struct clk_hw *hw) | ||
289 | { | ||
290 | struct mmp_clk_mix *mix = to_clk_mix(hw); | ||
291 | struct mmp_clk_mix_reg_info *ri = &mix->reg_info; | ||
292 | unsigned long flags = 0; | ||
293 | u32 mux_div = 0; | ||
294 | u8 width, shift; | ||
295 | u32 mux_val; | ||
296 | |||
297 | if (mix->lock) | ||
298 | spin_lock_irqsave(mix->lock, flags); | ||
299 | |||
300 | if (mix->type == MMP_CLK_MIX_TYPE_V1 | ||
301 | || mix->type == MMP_CLK_MIX_TYPE_V2) | ||
302 | mux_div = readl(ri->reg_clk_ctrl); | ||
303 | else | ||
304 | mux_div = readl(ri->reg_clk_sel); | ||
305 | |||
306 | if (mix->lock) | ||
307 | spin_unlock_irqrestore(mix->lock, flags); | ||
308 | |||
309 | width = mix->reg_info.width_mux; | ||
310 | shift = mix->reg_info.shift_mux; | ||
311 | |||
312 | mux_val = MMP_CLK_BITS_GET_VAL(mux_div, width, shift); | ||
313 | |||
314 | return _get_mux(mix, mux_val); | ||
315 | } | ||
316 | |||
317 | static unsigned long mmp_clk_mix_recalc_rate(struct clk_hw *hw, | ||
318 | unsigned long parent_rate) | ||
319 | { | ||
320 | struct mmp_clk_mix *mix = to_clk_mix(hw); | ||
321 | struct mmp_clk_mix_reg_info *ri = &mix->reg_info; | ||
322 | unsigned long flags = 0; | ||
323 | u32 mux_div = 0; | ||
324 | u8 width, shift; | ||
325 | unsigned int div; | ||
326 | |||
327 | if (mix->lock) | ||
328 | spin_lock_irqsave(mix->lock, flags); | ||
329 | |||
330 | if (mix->type == MMP_CLK_MIX_TYPE_V1 | ||
331 | || mix->type == MMP_CLK_MIX_TYPE_V2) | ||
332 | mux_div = readl(ri->reg_clk_ctrl); | ||
333 | else | ||
334 | mux_div = readl(ri->reg_clk_sel); | ||
335 | |||
336 | if (mix->lock) | ||
337 | spin_unlock_irqrestore(mix->lock, flags); | ||
338 | |||
339 | width = mix->reg_info.width_div; | ||
340 | shift = mix->reg_info.shift_div; | ||
341 | |||
342 | div = _get_div(mix, MMP_CLK_BITS_GET_VAL(mux_div, width, shift)); | ||
343 | |||
344 | return parent_rate / div; | ||
345 | } | ||
346 | |||
347 | static int mmp_clk_set_parent(struct clk_hw *hw, u8 index) | ||
348 | { | ||
349 | struct mmp_clk_mix *mix = to_clk_mix(hw); | ||
350 | struct mmp_clk_mix_clk_table *item; | ||
351 | int i; | ||
352 | u32 div_val, mux_val; | ||
353 | |||
354 | if (mix->table) { | ||
355 | for (i = 0; i < mix->table_size; i++) { | ||
356 | item = &mix->table[i]; | ||
357 | if (item->valid == 0) | ||
358 | continue; | ||
359 | if (item->parent_index == index) | ||
360 | break; | ||
361 | } | ||
362 | if (i < mix->table_size) { | ||
363 | div_val = _get_div_val(mix, item->divisor); | ||
364 | mux_val = _get_mux_val(mix, item->parent_index); | ||
365 | } else | ||
366 | return -EINVAL; | ||
367 | } else { | ||
368 | mux_val = _get_mux_val(mix, index); | ||
369 | div_val = 0; | ||
370 | } | ||
371 | |||
372 | return _set_rate(mix, mux_val, div_val, 1, div_val ? 1 : 0); | ||
373 | } | ||
374 | |||
375 | static int mmp_clk_set_rate(struct clk_hw *hw, unsigned long rate, | ||
376 | unsigned long best_parent_rate) | ||
377 | { | ||
378 | struct mmp_clk_mix *mix = to_clk_mix(hw); | ||
379 | struct mmp_clk_mix_clk_table *item; | ||
380 | unsigned long parent_rate; | ||
381 | unsigned int best_divisor; | ||
382 | struct clk *mix_clk, *parent; | ||
383 | int i; | ||
384 | |||
385 | best_divisor = best_parent_rate / rate; | ||
386 | |||
387 | mix_clk = hw->clk; | ||
388 | if (mix->table) { | ||
389 | for (i = 0; i < mix->table_size; i++) { | ||
390 | item = &mix->table[i]; | ||
391 | if (item->valid == 0) | ||
392 | continue; | ||
393 | parent = clk_get_parent_by_index(mix_clk, | ||
394 | item->parent_index); | ||
395 | parent_rate = __clk_get_rate(parent); | ||
396 | if (parent_rate == best_parent_rate | ||
397 | && item->divisor == best_divisor) | ||
398 | break; | ||
399 | } | ||
400 | if (i < mix->table_size) | ||
401 | return _set_rate(mix, | ||
402 | _get_mux_val(mix, item->parent_index), | ||
403 | _get_div_val(mix, item->divisor), | ||
404 | 1, 1); | ||
405 | else | ||
406 | return -EINVAL; | ||
407 | } else { | ||
408 | for (i = 0; i < __clk_get_num_parents(mix_clk); i++) { | ||
409 | parent = clk_get_parent_by_index(mix_clk, i); | ||
410 | parent_rate = __clk_get_rate(parent); | ||
411 | if (parent_rate == best_parent_rate) | ||
412 | break; | ||
413 | } | ||
414 | if (i < __clk_get_num_parents(mix_clk)) | ||
415 | return _set_rate(mix, _get_mux_val(mix, i), | ||
416 | _get_div_val(mix, best_divisor), 1, 1); | ||
417 | else | ||
418 | return -EINVAL; | ||
419 | } | ||
420 | } | ||
421 | |||
422 | static void mmp_clk_mix_init(struct clk_hw *hw) | ||
423 | { | ||
424 | struct mmp_clk_mix *mix = to_clk_mix(hw); | ||
425 | |||
426 | if (mix->table) | ||
427 | _filter_clk_table(mix, mix->table, mix->table_size); | ||
428 | } | ||
429 | |||
430 | const struct clk_ops mmp_clk_mix_ops = { | ||
431 | .determine_rate = mmp_clk_mix_determine_rate, | ||
432 | .set_rate_and_parent = mmp_clk_mix_set_rate_and_parent, | ||
433 | .set_rate = mmp_clk_set_rate, | ||
434 | .set_parent = mmp_clk_set_parent, | ||
435 | .get_parent = mmp_clk_mix_get_parent, | ||
436 | .recalc_rate = mmp_clk_mix_recalc_rate, | ||
437 | .init = mmp_clk_mix_init, | ||
438 | }; | ||
439 | |||
440 | struct clk *mmp_clk_register_mix(struct device *dev, | ||
441 | const char *name, | ||
442 | const char **parent_names, | ||
443 | u8 num_parents, | ||
444 | unsigned long flags, | ||
445 | struct mmp_clk_mix_config *config, | ||
446 | spinlock_t *lock) | ||
447 | { | ||
448 | struct mmp_clk_mix *mix; | ||
449 | struct clk *clk; | ||
450 | struct clk_init_data init; | ||
451 | size_t table_bytes; | ||
452 | |||
453 | mix = kzalloc(sizeof(*mix), GFP_KERNEL); | ||
454 | if (!mix) { | ||
455 | pr_err("%s:%s: could not allocate mmp mix clk\n", | ||
456 | __func__, name); | ||
457 | return ERR_PTR(-ENOMEM); | ||
458 | } | ||
459 | |||
460 | init.name = name; | ||
461 | init.flags = flags | CLK_GET_RATE_NOCACHE; | ||
462 | init.parent_names = parent_names; | ||
463 | init.num_parents = num_parents; | ||
464 | init.ops = &mmp_clk_mix_ops; | ||
465 | |||
466 | memcpy(&mix->reg_info, &config->reg_info, sizeof(config->reg_info)); | ||
467 | if (config->table) { | ||
468 | table_bytes = sizeof(*config->table) * config->table_size; | ||
469 | mix->table = kzalloc(table_bytes, GFP_KERNEL); | ||
470 | if (!mix->table) { | ||
471 | pr_err("%s:%s: could not allocate mmp mix table\n", | ||
472 | __func__, name); | ||
473 | kfree(mix); | ||
474 | return ERR_PTR(-ENOMEM); | ||
475 | } | ||
476 | memcpy(mix->table, config->table, table_bytes); | ||
477 | mix->table_size = config->table_size; | ||
478 | } | ||
479 | |||
480 | if (config->mux_table) { | ||
481 | table_bytes = sizeof(u32) * num_parents; | ||
482 | mix->mux_table = kzalloc(table_bytes, GFP_KERNEL); | ||
483 | if (!mix->mux_table) { | ||
484 | pr_err("%s:%s: could not allocate mmp mix mux-table\n", | ||
485 | __func__, name); | ||
486 | kfree(mix->table); | ||
487 | kfree(mix); | ||
488 | return ERR_PTR(-ENOMEM); | ||
489 | } | ||
490 | memcpy(mix->mux_table, config->mux_table, table_bytes); | ||
491 | } | ||
492 | |||
493 | mix->div_flags = config->div_flags; | ||
494 | mix->mux_flags = config->mux_flags; | ||
495 | mix->lock = lock; | ||
496 | mix->hw.init = &init; | ||
497 | |||
498 | if (config->reg_info.bit_fc >= 32) | ||
499 | mix->type = MMP_CLK_MIX_TYPE_V1; | ||
500 | else if (config->reg_info.reg_clk_sel) | ||
501 | mix->type = MMP_CLK_MIX_TYPE_V3; | ||
502 | else | ||
503 | mix->type = MMP_CLK_MIX_TYPE_V2; | ||
504 | clk = clk_register(dev, &mix->hw); | ||
505 | |||
506 | if (IS_ERR(clk)) { | ||
507 | kfree(mix->mux_table); | ||
508 | kfree(mix->table); | ||
509 | kfree(mix); | ||
510 | } | ||
511 | |||
512 | return clk; | ||
513 | } | ||
diff --git a/drivers/clk/mmp/clk-mmp2.c b/drivers/clk/mmp/clk-mmp2.c index b2721cae257a..5c90a4230fa3 100644 --- a/drivers/clk/mmp/clk-mmp2.c +++ b/drivers/clk/mmp/clk-mmp2.c | |||
@@ -54,7 +54,7 @@ | |||
54 | 54 | ||
55 | static DEFINE_SPINLOCK(clk_lock); | 55 | static DEFINE_SPINLOCK(clk_lock); |
56 | 56 | ||
57 | static struct clk_factor_masks uart_factor_masks = { | 57 | static struct mmp_clk_factor_masks uart_factor_masks = { |
58 | .factor = 2, | 58 | .factor = 2, |
59 | .num_mask = 0x1fff, | 59 | .num_mask = 0x1fff, |
60 | .den_mask = 0x1fff, | 60 | .den_mask = 0x1fff, |
@@ -62,7 +62,7 @@ static struct clk_factor_masks uart_factor_masks = { | |||
62 | .den_shift = 0, | 62 | .den_shift = 0, |
63 | }; | 63 | }; |
64 | 64 | ||
65 | static struct clk_factor_tbl uart_factor_tbl[] = { | 65 | static struct mmp_clk_factor_tbl uart_factor_tbl[] = { |
66 | {.num = 14634, .den = 2165}, /*14.745MHZ */ | 66 | {.num = 14634, .den = 2165}, /*14.745MHZ */ |
67 | {.num = 3521, .den = 689}, /*19.23MHZ */ | 67 | {.num = 3521, .den = 689}, /*19.23MHZ */ |
68 | {.num = 9679, .den = 5728}, /*58.9824MHZ */ | 68 | {.num = 9679, .den = 5728}, /*58.9824MHZ */ |
@@ -191,7 +191,7 @@ void __init mmp2_clk_init(void) | |||
191 | clk = mmp_clk_register_factor("uart_pll", "pll1_4", 0, | 191 | clk = mmp_clk_register_factor("uart_pll", "pll1_4", 0, |
192 | mpmu_base + MPMU_UART_PLL, | 192 | mpmu_base + MPMU_UART_PLL, |
193 | &uart_factor_masks, uart_factor_tbl, | 193 | &uart_factor_masks, uart_factor_tbl, |
194 | ARRAY_SIZE(uart_factor_tbl)); | 194 | ARRAY_SIZE(uart_factor_tbl), &clk_lock); |
195 | clk_set_rate(clk, 14745600); | 195 | clk_set_rate(clk, 14745600); |
196 | clk_register_clkdev(clk, "uart_pll", NULL); | 196 | clk_register_clkdev(clk, "uart_pll", NULL); |
197 | 197 | ||
diff --git a/drivers/clk/mmp/clk-of-mmp2.c b/drivers/clk/mmp/clk-of-mmp2.c new file mode 100644 index 000000000000..2cbc2b43ae52 --- /dev/null +++ b/drivers/clk/mmp/clk-of-mmp2.c | |||
@@ -0,0 +1,334 @@ | |||
1 | /* | ||
2 | * mmp2 clock framework source file | ||
3 | * | ||
4 | * Copyright (C) 2012 Marvell | ||
5 | * Chao Xie <xiechao.mail@gmail.com> | ||
6 | * | ||
7 | * This file is licensed under the terms of the GNU General Public | ||
8 | * License version 2. This program is licensed "as is" without any | ||
9 | * warranty of any kind, whether express or implied. | ||
10 | */ | ||
11 | |||
12 | #include <linux/module.h> | ||
13 | #include <linux/kernel.h> | ||
14 | #include <linux/spinlock.h> | ||
15 | #include <linux/io.h> | ||
16 | #include <linux/delay.h> | ||
17 | #include <linux/err.h> | ||
18 | #include <linux/of_address.h> | ||
19 | |||
20 | #include <dt-bindings/clock/marvell,mmp2.h> | ||
21 | |||
22 | #include "clk.h" | ||
23 | #include "reset.h" | ||
24 | |||
25 | #define APBC_RTC 0x0 | ||
26 | #define APBC_TWSI0 0x4 | ||
27 | #define APBC_TWSI1 0x8 | ||
28 | #define APBC_TWSI2 0xc | ||
29 | #define APBC_TWSI3 0x10 | ||
30 | #define APBC_TWSI4 0x7c | ||
31 | #define APBC_TWSI5 0x80 | ||
32 | #define APBC_KPC 0x18 | ||
33 | #define APBC_UART0 0x2c | ||
34 | #define APBC_UART1 0x30 | ||
35 | #define APBC_UART2 0x34 | ||
36 | #define APBC_UART3 0x88 | ||
37 | #define APBC_GPIO 0x38 | ||
38 | #define APBC_PWM0 0x3c | ||
39 | #define APBC_PWM1 0x40 | ||
40 | #define APBC_PWM2 0x44 | ||
41 | #define APBC_PWM3 0x48 | ||
42 | #define APBC_SSP0 0x50 | ||
43 | #define APBC_SSP1 0x54 | ||
44 | #define APBC_SSP2 0x58 | ||
45 | #define APBC_SSP3 0x5c | ||
46 | #define APMU_SDH0 0x54 | ||
47 | #define APMU_SDH1 0x58 | ||
48 | #define APMU_SDH2 0xe8 | ||
49 | #define APMU_SDH3 0xec | ||
50 | #define APMU_USB 0x5c | ||
51 | #define APMU_DISP0 0x4c | ||
52 | #define APMU_DISP1 0x110 | ||
53 | #define APMU_CCIC0 0x50 | ||
54 | #define APMU_CCIC1 0xf4 | ||
55 | #define MPMU_UART_PLL 0x14 | ||
56 | |||
57 | struct mmp2_clk_unit { | ||
58 | struct mmp_clk_unit unit; | ||
59 | void __iomem *mpmu_base; | ||
60 | void __iomem *apmu_base; | ||
61 | void __iomem *apbc_base; | ||
62 | }; | ||
63 | |||
64 | static struct mmp_param_fixed_rate_clk fixed_rate_clks[] = { | ||
65 | {MMP2_CLK_CLK32, "clk32", NULL, CLK_IS_ROOT, 32768}, | ||
66 | {MMP2_CLK_VCTCXO, "vctcxo", NULL, CLK_IS_ROOT, 26000000}, | ||
67 | {MMP2_CLK_PLL1, "pll1", NULL, CLK_IS_ROOT, 800000000}, | ||
68 | {MMP2_CLK_PLL2, "pll2", NULL, CLK_IS_ROOT, 960000000}, | ||
69 | {MMP2_CLK_USB_PLL, "usb_pll", NULL, CLK_IS_ROOT, 480000000}, | ||
70 | }; | ||
71 | |||
72 | static struct mmp_param_fixed_factor_clk fixed_factor_clks[] = { | ||
73 | {MMP2_CLK_PLL1_2, "pll1_2", "pll1", 1, 2, 0}, | ||
74 | {MMP2_CLK_PLL1_4, "pll1_4", "pll1_2", 1, 2, 0}, | ||
75 | {MMP2_CLK_PLL1_8, "pll1_8", "pll1_4", 1, 2, 0}, | ||
76 | {MMP2_CLK_PLL1_16, "pll1_16", "pll1_8", 1, 2, 0}, | ||
77 | {MMP2_CLK_PLL1_20, "pll1_20", "pll1_4", 1, 5, 0}, | ||
78 | {MMP2_CLK_PLL1_3, "pll1_3", "pll1", 1, 3, 0}, | ||
79 | {MMP2_CLK_PLL1_6, "pll1_6", "pll1_3", 1, 2, 0}, | ||
80 | {MMP2_CLK_PLL1_12, "pll1_12", "pll1_6", 1, 2, 0}, | ||
81 | {MMP2_CLK_PLL2_2, "pll2_2", "pll2", 1, 2, 0}, | ||
82 | {MMP2_CLK_PLL2_4, "pll2_4", "pll2_2", 1, 2, 0}, | ||
83 | {MMP2_CLK_PLL2_8, "pll2_8", "pll2_4", 1, 2, 0}, | ||
84 | {MMP2_CLK_PLL2_16, "pll2_16", "pll2_8", 1, 2, 0}, | ||
85 | {MMP2_CLK_PLL2_3, "pll2_3", "pll2", 1, 3, 0}, | ||
86 | {MMP2_CLK_PLL2_6, "pll2_6", "pll2_3", 1, 2, 0}, | ||
87 | {MMP2_CLK_PLL2_12, "pll2_12", "pll2_6", 1, 2, 0}, | ||
88 | {MMP2_CLK_VCTCXO_2, "vctcxo_2", "vctcxo", 1, 2, 0}, | ||
89 | {MMP2_CLK_VCTCXO_4, "vctcxo_4", "vctcxo_2", 1, 2, 0}, | ||
90 | }; | ||
91 | |||
92 | static struct mmp_clk_factor_masks uart_factor_masks = { | ||
93 | .factor = 2, | ||
94 | .num_mask = 0x1fff, | ||
95 | .den_mask = 0x1fff, | ||
96 | .num_shift = 16, | ||
97 | .den_shift = 0, | ||
98 | }; | ||
99 | |||
100 | static struct mmp_clk_factor_tbl uart_factor_tbl[] = { | ||
101 | {.num = 14634, .den = 2165}, /*14.745MHZ */ | ||
102 | {.num = 3521, .den = 689}, /*19.23MHZ */ | ||
103 | {.num = 9679, .den = 5728}, /*58.9824MHZ */ | ||
104 | {.num = 15850, .den = 9451}, /*59.429MHZ */ | ||
105 | }; | ||
106 | |||
107 | static void mmp2_pll_init(struct mmp2_clk_unit *pxa_unit) | ||
108 | { | ||
109 | struct clk *clk; | ||
110 | struct mmp_clk_unit *unit = &pxa_unit->unit; | ||
111 | |||
112 | mmp_register_fixed_rate_clks(unit, fixed_rate_clks, | ||
113 | ARRAY_SIZE(fixed_rate_clks)); | ||
114 | |||
115 | mmp_register_fixed_factor_clks(unit, fixed_factor_clks, | ||
116 | ARRAY_SIZE(fixed_factor_clks)); | ||
117 | |||
118 | clk = mmp_clk_register_factor("uart_pll", "pll1_4", | ||
119 | CLK_SET_RATE_PARENT, | ||
120 | pxa_unit->mpmu_base + MPMU_UART_PLL, | ||
121 | &uart_factor_masks, uart_factor_tbl, | ||
122 | ARRAY_SIZE(uart_factor_tbl), NULL); | ||
123 | mmp_clk_add(unit, MMP2_CLK_UART_PLL, clk); | ||
124 | } | ||
125 | |||
126 | static DEFINE_SPINLOCK(uart0_lock); | ||
127 | static DEFINE_SPINLOCK(uart1_lock); | ||
128 | static DEFINE_SPINLOCK(uart2_lock); | ||
129 | static const char *uart_parent_names[] = {"uart_pll", "vctcxo"}; | ||
130 | |||
131 | static DEFINE_SPINLOCK(ssp0_lock); | ||
132 | static DEFINE_SPINLOCK(ssp1_lock); | ||
133 | static DEFINE_SPINLOCK(ssp2_lock); | ||
134 | static DEFINE_SPINLOCK(ssp3_lock); | ||
135 | static const char *ssp_parent_names[] = {"vctcxo_4", "vctcxo_2", "vctcxo", "pll1_16"}; | ||
136 | |||
137 | static DEFINE_SPINLOCK(reset_lock); | ||
138 | |||
139 | static struct mmp_param_mux_clk apbc_mux_clks[] = { | ||
140 | {0, "uart0_mux", uart_parent_names, ARRAY_SIZE(uart_parent_names), CLK_SET_RATE_PARENT, APBC_UART0, 4, 3, 0, &uart0_lock}, | ||
141 | {0, "uart1_mux", uart_parent_names, ARRAY_SIZE(uart_parent_names), CLK_SET_RATE_PARENT, APBC_UART1, 4, 3, 0, &uart1_lock}, | ||
142 | {0, "uart2_mux", uart_parent_names, ARRAY_SIZE(uart_parent_names), CLK_SET_RATE_PARENT, APBC_UART2, 4, 3, 0, &uart2_lock}, | ||
143 | {0, "uart3_mux", uart_parent_names, ARRAY_SIZE(uart_parent_names), CLK_SET_RATE_PARENT, APBC_UART3, 4, 3, 0, &uart2_lock}, | ||
144 | {0, "ssp0_mux", ssp_parent_names, ARRAY_SIZE(ssp_parent_names), CLK_SET_RATE_PARENT, APBC_SSP0, 4, 3, 0, &ssp0_lock}, | ||
145 | {0, "ssp1_mux", ssp_parent_names, ARRAY_SIZE(ssp_parent_names), CLK_SET_RATE_PARENT, APBC_SSP1, 4, 3, 0, &ssp1_lock}, | ||
146 | {0, "ssp2_mux", ssp_parent_names, ARRAY_SIZE(ssp_parent_names), CLK_SET_RATE_PARENT, APBC_SSP2, 4, 3, 0, &ssp2_lock}, | ||
147 | {0, "ssp3_mux", ssp_parent_names, ARRAY_SIZE(ssp_parent_names), CLK_SET_RATE_PARENT, APBC_SSP3, 4, 3, 0, &ssp3_lock}, | ||
148 | }; | ||
149 | |||
150 | static struct mmp_param_gate_clk apbc_gate_clks[] = { | ||
151 | {MMP2_CLK_TWSI0, "twsi0_clk", "vctcxo", CLK_SET_RATE_PARENT, APBC_TWSI0, 0x7, 0x3, 0x0, 0, &reset_lock}, | ||
152 | {MMP2_CLK_TWSI1, "twsi1_clk", "vctcxo", CLK_SET_RATE_PARENT, APBC_TWSI1, 0x7, 0x3, 0x0, 0, &reset_lock}, | ||
153 | {MMP2_CLK_TWSI2, "twsi2_clk", "vctcxo", CLK_SET_RATE_PARENT, APBC_TWSI2, 0x7, 0x3, 0x0, 0, &reset_lock}, | ||
154 | {MMP2_CLK_TWSI3, "twsi3_clk", "vctcxo", CLK_SET_RATE_PARENT, APBC_TWSI3, 0x7, 0x3, 0x0, 0, &reset_lock}, | ||
155 | {MMP2_CLK_TWSI4, "twsi4_clk", "vctcxo", CLK_SET_RATE_PARENT, APBC_TWSI4, 0x7, 0x3, 0x0, 0, &reset_lock}, | ||
156 | {MMP2_CLK_TWSI5, "twsi5_clk", "vctcxo", CLK_SET_RATE_PARENT, APBC_TWSI5, 0x7, 0x3, 0x0, 0, &reset_lock}, | ||
157 | {MMP2_CLK_GPIO, "gpio_clk", "vctcxo", CLK_SET_RATE_PARENT, APBC_GPIO, 0x7, 0x3, 0x0, 0, &reset_lock}, | ||
158 | {MMP2_CLK_KPC, "kpc_clk", "clk32", CLK_SET_RATE_PARENT, APBC_KPC, 0x7, 0x3, 0x0, MMP_CLK_GATE_NEED_DELAY, &reset_lock}, | ||
159 | {MMP2_CLK_RTC, "rtc_clk", "clk32", CLK_SET_RATE_PARENT, APBC_RTC, 0x87, 0x83, 0x0, MMP_CLK_GATE_NEED_DELAY, &reset_lock}, | ||
160 | {MMP2_CLK_PWM0, "pwm0_clk", "pll1_48", CLK_SET_RATE_PARENT, APBC_PWM0, 0x7, 0x3, 0x0, 0, &reset_lock}, | ||
161 | {MMP2_CLK_PWM1, "pwm1_clk", "pll1_48", CLK_SET_RATE_PARENT, APBC_PWM1, 0x7, 0x3, 0x0, 0, &reset_lock}, | ||
162 | {MMP2_CLK_PWM2, "pwm2_clk", "pll1_48", CLK_SET_RATE_PARENT, APBC_PWM2, 0x7, 0x3, 0x0, 0, &reset_lock}, | ||
163 | {MMP2_CLK_PWM3, "pwm3_clk", "pll1_48", CLK_SET_RATE_PARENT, APBC_PWM3, 0x7, 0x3, 0x0, 0, &reset_lock}, | ||
164 | /* The gate clocks has mux parent. */ | ||
165 | {MMP2_CLK_UART0, "uart0_clk", "uart0_mux", CLK_SET_RATE_PARENT, APBC_UART0, 0x7, 0x3, 0x0, 0, &uart0_lock}, | ||
166 | {MMP2_CLK_UART1, "uart1_clk", "uart1_mux", CLK_SET_RATE_PARENT, APBC_UART1, 0x7, 0x3, 0x0, 0, &uart1_lock}, | ||
167 | {MMP2_CLK_UART2, "uart2_clk", "uart2_mux", CLK_SET_RATE_PARENT, APBC_UART2, 0x7, 0x3, 0x0, 0, &uart2_lock}, | ||
168 | {MMP2_CLK_UART3, "uart3_clk", "uart3_mux", CLK_SET_RATE_PARENT, APBC_UART3, 0x7, 0x3, 0x0, 0, &uart2_lock}, | ||
169 | {MMP2_CLK_SSP0, "ssp0_clk", "ssp0_mux", CLK_SET_RATE_PARENT, APBC_SSP0, 0x7, 0x3, 0x0, 0, &ssp0_lock}, | ||
170 | {MMP2_CLK_SSP1, "ssp1_clk", "ssp1_mux", CLK_SET_RATE_PARENT, APBC_SSP1, 0x7, 0x3, 0x0, 0, &ssp1_lock}, | ||
171 | {MMP2_CLK_SSP2, "ssp2_clk", "ssp2_mux", CLK_SET_RATE_PARENT, APBC_SSP2, 0x7, 0x3, 0x0, 0, &ssp2_lock}, | ||
172 | {MMP2_CLK_SSP3, "ssp3_clk", "ssp3_mux", CLK_SET_RATE_PARENT, APBC_SSP3, 0x7, 0x3, 0x0, 0, &ssp3_lock}, | ||
173 | }; | ||
174 | |||
175 | static void mmp2_apb_periph_clk_init(struct mmp2_clk_unit *pxa_unit) | ||
176 | { | ||
177 | struct mmp_clk_unit *unit = &pxa_unit->unit; | ||
178 | |||
179 | mmp_register_mux_clks(unit, apbc_mux_clks, pxa_unit->apbc_base, | ||
180 | ARRAY_SIZE(apbc_mux_clks)); | ||
181 | |||
182 | mmp_register_gate_clks(unit, apbc_gate_clks, pxa_unit->apbc_base, | ||
183 | ARRAY_SIZE(apbc_gate_clks)); | ||
184 | } | ||
185 | |||
186 | static DEFINE_SPINLOCK(sdh_lock); | ||
187 | static const char *sdh_parent_names[] = {"pll1_4", "pll2", "usb_pll", "pll1"}; | ||
188 | static struct mmp_clk_mix_config sdh_mix_config = { | ||
189 | .reg_info = DEFINE_MIX_REG_INFO(4, 10, 2, 8, 32), | ||
190 | }; | ||
191 | |||
192 | static DEFINE_SPINLOCK(usb_lock); | ||
193 | |||
194 | static DEFINE_SPINLOCK(disp0_lock); | ||
195 | static DEFINE_SPINLOCK(disp1_lock); | ||
196 | static const char *disp_parent_names[] = {"pll1", "pll1_16", "pll2", "vctcxo"}; | ||
197 | |||
198 | static DEFINE_SPINLOCK(ccic0_lock); | ||
199 | static DEFINE_SPINLOCK(ccic1_lock); | ||
200 | static const char *ccic_parent_names[] = {"pll1_2", "pll1_16", "vctcxo"}; | ||
201 | static struct mmp_clk_mix_config ccic0_mix_config = { | ||
202 | .reg_info = DEFINE_MIX_REG_INFO(4, 17, 2, 6, 32), | ||
203 | }; | ||
204 | static struct mmp_clk_mix_config ccic1_mix_config = { | ||
205 | .reg_info = DEFINE_MIX_REG_INFO(4, 16, 2, 6, 32), | ||
206 | }; | ||
207 | |||
208 | static struct mmp_param_mux_clk apmu_mux_clks[] = { | ||
209 | {MMP2_CLK_DISP0_MUX, "disp0_mux", disp_parent_names, ARRAY_SIZE(disp_parent_names), CLK_SET_RATE_PARENT, APMU_DISP0, 6, 2, 0, &disp0_lock}, | ||
210 | {MMP2_CLK_DISP1_MUX, "disp1_mux", disp_parent_names, ARRAY_SIZE(disp_parent_names), CLK_SET_RATE_PARENT, APMU_DISP1, 6, 2, 0, &disp1_lock}, | ||
211 | }; | ||
212 | |||
213 | static struct mmp_param_div_clk apmu_div_clks[] = { | ||
214 | {0, "disp0_div", "disp0_mux", CLK_SET_RATE_PARENT, APMU_DISP0, 8, 4, 0, &disp0_lock}, | ||
215 | {0, "disp0_sphy_div", "disp0_mux", CLK_SET_RATE_PARENT, APMU_DISP0, 15, 5, 0, &disp0_lock}, | ||
216 | {0, "disp1_div", "disp1_mux", CLK_SET_RATE_PARENT, APMU_DISP1, 8, 4, 0, &disp1_lock}, | ||
217 | {0, "ccic0_sphy_div", "ccic0_mix_clk", CLK_SET_RATE_PARENT, APMU_CCIC0, 10, 5, 0, &ccic0_lock}, | ||
218 | {0, "ccic1_sphy_div", "ccic1_mix_clk", CLK_SET_RATE_PARENT, APMU_CCIC1, 10, 5, 0, &ccic1_lock}, | ||
219 | }; | ||
220 | |||
221 | static struct mmp_param_gate_clk apmu_gate_clks[] = { | ||
222 | {MMP2_CLK_USB, "usb_clk", "usb_pll", 0, APMU_USB, 0x9, 0x9, 0x0, 0, &usb_lock}, | ||
223 | /* The gate clocks has mux parent. */ | ||
224 | {MMP2_CLK_SDH0, "sdh0_clk", "sdh_mix_clk", CLK_SET_RATE_PARENT, APMU_SDH0, 0x1b, 0x1b, 0x0, 0, &sdh_lock}, | ||
225 | {MMP2_CLK_SDH1, "sdh1_clk", "sdh_mix_clk", CLK_SET_RATE_PARENT, APMU_SDH1, 0x1b, 0x1b, 0x0, 0, &sdh_lock}, | ||
226 | {MMP2_CLK_SDH1, "sdh2_clk", "sdh_mix_clk", CLK_SET_RATE_PARENT, APMU_SDH2, 0x1b, 0x1b, 0x0, 0, &sdh_lock}, | ||
227 | {MMP2_CLK_SDH1, "sdh3_clk", "sdh_mix_clk", CLK_SET_RATE_PARENT, APMU_SDH3, 0x1b, 0x1b, 0x0, 0, &sdh_lock}, | ||
228 | {MMP2_CLK_DISP0, "disp0_clk", "disp0_div", CLK_SET_RATE_PARENT, APMU_DISP0, 0x1b, 0x1b, 0x0, 0, &disp0_lock}, | ||
229 | {MMP2_CLK_DISP0_SPHY, "disp0_sphy_clk", "disp0_sphy_div", CLK_SET_RATE_PARENT, APMU_DISP0, 0x1024, 0x1024, 0x0, 0, &disp0_lock}, | ||
230 | {MMP2_CLK_DISP1, "disp1_clk", "disp1_div", CLK_SET_RATE_PARENT, APMU_DISP1, 0x1b, 0x1b, 0x0, 0, &disp1_lock}, | ||
231 | {MMP2_CLK_CCIC_ARBITER, "ccic_arbiter", "vctcxo", CLK_SET_RATE_PARENT, APMU_CCIC0, 0x1800, 0x1800, 0x0, 0, &ccic0_lock}, | ||
232 | {MMP2_CLK_CCIC0, "ccic0_clk", "ccic0_mix_clk", CLK_SET_RATE_PARENT, APMU_CCIC0, 0x1b, 0x1b, 0x0, 0, &ccic0_lock}, | ||
233 | {MMP2_CLK_CCIC0_PHY, "ccic0_phy_clk", "ccic0_mix_clk", CLK_SET_RATE_PARENT, APMU_CCIC0, 0x24, 0x24, 0x0, 0, &ccic0_lock}, | ||
234 | {MMP2_CLK_CCIC0_SPHY, "ccic0_sphy_clk", "ccic0_sphy_div", CLK_SET_RATE_PARENT, APMU_CCIC0, 0x300, 0x300, 0x0, 0, &ccic0_lock}, | ||
235 | {MMP2_CLK_CCIC1, "ccic1_clk", "ccic1_mix_clk", CLK_SET_RATE_PARENT, APMU_CCIC1, 0x1b, 0x1b, 0x0, 0, &ccic1_lock}, | ||
236 | {MMP2_CLK_CCIC1_PHY, "ccic1_phy_clk", "ccic1_mix_clk", CLK_SET_RATE_PARENT, APMU_CCIC1, 0x24, 0x24, 0x0, 0, &ccic1_lock}, | ||
237 | {MMP2_CLK_CCIC1_SPHY, "ccic1_sphy_clk", "ccic1_sphy_div", CLK_SET_RATE_PARENT, APMU_CCIC1, 0x300, 0x300, 0x0, 0, &ccic1_lock}, | ||
238 | }; | ||
239 | |||
240 | static void mmp2_axi_periph_clk_init(struct mmp2_clk_unit *pxa_unit) | ||
241 | { | ||
242 | struct clk *clk; | ||
243 | struct mmp_clk_unit *unit = &pxa_unit->unit; | ||
244 | |||
245 | sdh_mix_config.reg_info.reg_clk_ctrl = pxa_unit->apmu_base + APMU_SDH0; | ||
246 | clk = mmp_clk_register_mix(NULL, "sdh_mix_clk", sdh_parent_names, | ||
247 | ARRAY_SIZE(sdh_parent_names), | ||
248 | CLK_SET_RATE_PARENT, | ||
249 | &sdh_mix_config, &sdh_lock); | ||
250 | |||
251 | ccic0_mix_config.reg_info.reg_clk_ctrl = pxa_unit->apmu_base + APMU_CCIC0; | ||
252 | clk = mmp_clk_register_mix(NULL, "ccic0_mix_clk", ccic_parent_names, | ||
253 | ARRAY_SIZE(ccic_parent_names), | ||
254 | CLK_SET_RATE_PARENT, | ||
255 | &ccic0_mix_config, &ccic0_lock); | ||
256 | mmp_clk_add(unit, MMP2_CLK_CCIC0_MIX, clk); | ||
257 | |||
258 | ccic1_mix_config.reg_info.reg_clk_ctrl = pxa_unit->apmu_base + APMU_CCIC1; | ||
259 | clk = mmp_clk_register_mix(NULL, "ccic1_mix_clk", ccic_parent_names, | ||
260 | ARRAY_SIZE(ccic_parent_names), | ||
261 | CLK_SET_RATE_PARENT, | ||
262 | &ccic1_mix_config, &ccic1_lock); | ||
263 | mmp_clk_add(unit, MMP2_CLK_CCIC1_MIX, clk); | ||
264 | |||
265 | mmp_register_mux_clks(unit, apmu_mux_clks, pxa_unit->apmu_base, | ||
266 | ARRAY_SIZE(apmu_mux_clks)); | ||
267 | |||
268 | mmp_register_div_clks(unit, apmu_div_clks, pxa_unit->apmu_base, | ||
269 | ARRAY_SIZE(apmu_div_clks)); | ||
270 | |||
271 | mmp_register_gate_clks(unit, apmu_gate_clks, pxa_unit->apmu_base, | ||
272 | ARRAY_SIZE(apmu_gate_clks)); | ||
273 | } | ||
274 | |||
275 | static void mmp2_clk_reset_init(struct device_node *np, | ||
276 | struct mmp2_clk_unit *pxa_unit) | ||
277 | { | ||
278 | struct mmp_clk_reset_cell *cells; | ||
279 | int i, nr_resets; | ||
280 | |||
281 | nr_resets = ARRAY_SIZE(apbc_gate_clks); | ||
282 | cells = kcalloc(nr_resets, sizeof(*cells), GFP_KERNEL); | ||
283 | if (!cells) | ||
284 | return; | ||
285 | |||
286 | for (i = 0; i < nr_resets; i++) { | ||
287 | cells[i].clk_id = apbc_gate_clks[i].id; | ||
288 | cells[i].reg = pxa_unit->apbc_base + apbc_gate_clks[i].offset; | ||
289 | cells[i].flags = 0; | ||
290 | cells[i].lock = apbc_gate_clks[i].lock; | ||
291 | cells[i].bits = 0x4; | ||
292 | } | ||
293 | |||
294 | mmp_clk_reset_register(np, cells, nr_resets); | ||
295 | } | ||
296 | |||
297 | static void __init mmp2_clk_init(struct device_node *np) | ||
298 | { | ||
299 | struct mmp2_clk_unit *pxa_unit; | ||
300 | |||
301 | pxa_unit = kzalloc(sizeof(*pxa_unit), GFP_KERNEL); | ||
302 | if (!pxa_unit) | ||
303 | return; | ||
304 | |||
305 | pxa_unit->mpmu_base = of_iomap(np, 0); | ||
306 | if (!pxa_unit->mpmu_base) { | ||
307 | pr_err("failed to map mpmu registers\n"); | ||
308 | return; | ||
309 | } | ||
310 | |||
311 | pxa_unit->apmu_base = of_iomap(np, 1); | ||
312 | if (!pxa_unit->mpmu_base) { | ||
313 | pr_err("failed to map apmu registers\n"); | ||
314 | return; | ||
315 | } | ||
316 | |||
317 | pxa_unit->apbc_base = of_iomap(np, 2); | ||
318 | if (!pxa_unit->apbc_base) { | ||
319 | pr_err("failed to map apbc registers\n"); | ||
320 | return; | ||
321 | } | ||
322 | |||
323 | mmp_clk_init(np, &pxa_unit->unit, MMP2_NR_CLKS); | ||
324 | |||
325 | mmp2_pll_init(pxa_unit); | ||
326 | |||
327 | mmp2_apb_periph_clk_init(pxa_unit); | ||
328 | |||
329 | mmp2_axi_periph_clk_init(pxa_unit); | ||
330 | |||
331 | mmp2_clk_reset_init(np, pxa_unit); | ||
332 | } | ||
333 | |||
334 | CLK_OF_DECLARE(mmp2_clk, "marvell,mmp2-clock", mmp2_clk_init); | ||
diff --git a/drivers/clk/mmp/clk-of-pxa168.c b/drivers/clk/mmp/clk-of-pxa168.c new file mode 100644 index 000000000000..5b1810dc4bd2 --- /dev/null +++ b/drivers/clk/mmp/clk-of-pxa168.c | |||
@@ -0,0 +1,279 @@ | |||
1 | /* | ||
2 | * pxa168 clock framework source file | ||
3 | * | ||
4 | * Copyright (C) 2012 Marvell | ||
5 | * Chao Xie <xiechao.mail@gmail.com> | ||
6 | * | ||
7 | * This file is licensed under the terms of the GNU General Public | ||
8 | * License version 2. This program is licensed "as is" without any | ||
9 | * warranty of any kind, whether express or implied. | ||
10 | */ | ||
11 | |||
12 | #include <linux/module.h> | ||
13 | #include <linux/kernel.h> | ||
14 | #include <linux/spinlock.h> | ||
15 | #include <linux/io.h> | ||
16 | #include <linux/delay.h> | ||
17 | #include <linux/err.h> | ||
18 | #include <linux/of_address.h> | ||
19 | |||
20 | #include <dt-bindings/clock/marvell,pxa168.h> | ||
21 | |||
22 | #include "clk.h" | ||
23 | #include "reset.h" | ||
24 | |||
25 | #define APBC_RTC 0x28 | ||
26 | #define APBC_TWSI0 0x2c | ||
27 | #define APBC_KPC 0x30 | ||
28 | #define APBC_UART0 0x0 | ||
29 | #define APBC_UART1 0x4 | ||
30 | #define APBC_GPIO 0x8 | ||
31 | #define APBC_PWM0 0xc | ||
32 | #define APBC_PWM1 0x10 | ||
33 | #define APBC_PWM2 0x14 | ||
34 | #define APBC_PWM3 0x18 | ||
35 | #define APBC_SSP0 0x81c | ||
36 | #define APBC_SSP1 0x820 | ||
37 | #define APBC_SSP2 0x84c | ||
38 | #define APBC_SSP3 0x858 | ||
39 | #define APBC_SSP4 0x85c | ||
40 | #define APBC_TWSI1 0x6c | ||
41 | #define APBC_UART2 0x70 | ||
42 | #define APMU_SDH0 0x54 | ||
43 | #define APMU_SDH1 0x58 | ||
44 | #define APMU_USB 0x5c | ||
45 | #define APMU_DISP0 0x4c | ||
46 | #define APMU_CCIC0 0x50 | ||
47 | #define APMU_DFC 0x60 | ||
48 | #define MPMU_UART_PLL 0x14 | ||
49 | |||
50 | struct pxa168_clk_unit { | ||
51 | struct mmp_clk_unit unit; | ||
52 | void __iomem *mpmu_base; | ||
53 | void __iomem *apmu_base; | ||
54 | void __iomem *apbc_base; | ||
55 | }; | ||
56 | |||
57 | static struct mmp_param_fixed_rate_clk fixed_rate_clks[] = { | ||
58 | {PXA168_CLK_CLK32, "clk32", NULL, CLK_IS_ROOT, 32768}, | ||
59 | {PXA168_CLK_VCTCXO, "vctcxo", NULL, CLK_IS_ROOT, 26000000}, | ||
60 | {PXA168_CLK_PLL1, "pll1", NULL, CLK_IS_ROOT, 624000000}, | ||
61 | }; | ||
62 | |||
63 | static struct mmp_param_fixed_factor_clk fixed_factor_clks[] = { | ||
64 | {PXA168_CLK_PLL1_2, "pll1_2", "pll1", 1, 2, 0}, | ||
65 | {PXA168_CLK_PLL1_4, "pll1_4", "pll1_2", 1, 2, 0}, | ||
66 | {PXA168_CLK_PLL1_8, "pll1_8", "pll1_4", 1, 2, 0}, | ||
67 | {PXA168_CLK_PLL1_16, "pll1_16", "pll1_8", 1, 2, 0}, | ||
68 | {PXA168_CLK_PLL1_6, "pll1_6", "pll1_2", 1, 3, 0}, | ||
69 | {PXA168_CLK_PLL1_12, "pll1_12", "pll1_6", 1, 2, 0}, | ||
70 | {PXA168_CLK_PLL1_24, "pll1_24", "pll1_12", 1, 2, 0}, | ||
71 | {PXA168_CLK_PLL1_48, "pll1_48", "pll1_24", 1, 2, 0}, | ||
72 | {PXA168_CLK_PLL1_96, "pll1_96", "pll1_48", 1, 2, 0}, | ||
73 | {PXA168_CLK_PLL1_13, "pll1_13", "pll1", 1, 13, 0}, | ||
74 | {PXA168_CLK_PLL1_13_1_5, "pll1_13_1_5", "pll1_13", 2, 3, 0}, | ||
75 | {PXA168_CLK_PLL1_2_1_5, "pll1_2_1_5", "pll1_2", 2, 3, 0}, | ||
76 | {PXA168_CLK_PLL1_3_16, "pll1_3_16", "pll1", 3, 16, 0}, | ||
77 | }; | ||
78 | |||
79 | static struct mmp_clk_factor_masks uart_factor_masks = { | ||
80 | .factor = 2, | ||
81 | .num_mask = 0x1fff, | ||
82 | .den_mask = 0x1fff, | ||
83 | .num_shift = 16, | ||
84 | .den_shift = 0, | ||
85 | }; | ||
86 | |||
87 | static struct mmp_clk_factor_tbl uart_factor_tbl[] = { | ||
88 | {.num = 8125, .den = 1536}, /*14.745MHZ */ | ||
89 | }; | ||
90 | |||
91 | static void pxa168_pll_init(struct pxa168_clk_unit *pxa_unit) | ||
92 | { | ||
93 | struct clk *clk; | ||
94 | struct mmp_clk_unit *unit = &pxa_unit->unit; | ||
95 | |||
96 | mmp_register_fixed_rate_clks(unit, fixed_rate_clks, | ||
97 | ARRAY_SIZE(fixed_rate_clks)); | ||
98 | |||
99 | mmp_register_fixed_factor_clks(unit, fixed_factor_clks, | ||
100 | ARRAY_SIZE(fixed_factor_clks)); | ||
101 | |||
102 | clk = mmp_clk_register_factor("uart_pll", "pll1_4", | ||
103 | CLK_SET_RATE_PARENT, | ||
104 | pxa_unit->mpmu_base + MPMU_UART_PLL, | ||
105 | &uart_factor_masks, uart_factor_tbl, | ||
106 | ARRAY_SIZE(uart_factor_tbl), NULL); | ||
107 | mmp_clk_add(unit, PXA168_CLK_UART_PLL, clk); | ||
108 | } | ||
109 | |||
110 | static DEFINE_SPINLOCK(uart0_lock); | ||
111 | static DEFINE_SPINLOCK(uart1_lock); | ||
112 | static DEFINE_SPINLOCK(uart2_lock); | ||
113 | static const char *uart_parent_names[] = {"pll1_3_16", "uart_pll"}; | ||
114 | |||
115 | static DEFINE_SPINLOCK(ssp0_lock); | ||
116 | static DEFINE_SPINLOCK(ssp1_lock); | ||
117 | static DEFINE_SPINLOCK(ssp2_lock); | ||
118 | static DEFINE_SPINLOCK(ssp3_lock); | ||
119 | static DEFINE_SPINLOCK(ssp4_lock); | ||
120 | static const char *ssp_parent_names[] = {"pll1_96", "pll1_48", "pll1_24", "pll1_12"}; | ||
121 | |||
122 | static DEFINE_SPINLOCK(reset_lock); | ||
123 | |||
124 | static struct mmp_param_mux_clk apbc_mux_clks[] = { | ||
125 | {0, "uart0_mux", uart_parent_names, ARRAY_SIZE(uart_parent_names), CLK_SET_RATE_PARENT, APBC_UART0, 4, 3, 0, &uart0_lock}, | ||
126 | {0, "uart1_mux", uart_parent_names, ARRAY_SIZE(uart_parent_names), CLK_SET_RATE_PARENT, APBC_UART1, 4, 3, 0, &uart1_lock}, | ||
127 | {0, "uart2_mux", uart_parent_names, ARRAY_SIZE(uart_parent_names), CLK_SET_RATE_PARENT, APBC_UART2, 4, 3, 0, &uart2_lock}, | ||
128 | {0, "ssp0_mux", ssp_parent_names, ARRAY_SIZE(ssp_parent_names), CLK_SET_RATE_PARENT, APBC_SSP0, 4, 3, 0, &ssp0_lock}, | ||
129 | {0, "ssp1_mux", ssp_parent_names, ARRAY_SIZE(ssp_parent_names), CLK_SET_RATE_PARENT, APBC_SSP1, 4, 3, 0, &ssp1_lock}, | ||
130 | {0, "ssp2_mux", ssp_parent_names, ARRAY_SIZE(ssp_parent_names), CLK_SET_RATE_PARENT, APBC_SSP2, 4, 3, 0, &ssp2_lock}, | ||
131 | {0, "ssp3_mux", ssp_parent_names, ARRAY_SIZE(ssp_parent_names), CLK_SET_RATE_PARENT, APBC_SSP3, 4, 3, 0, &ssp3_lock}, | ||
132 | {0, "ssp4_mux", ssp_parent_names, ARRAY_SIZE(ssp_parent_names), CLK_SET_RATE_PARENT, APBC_SSP4, 4, 3, 0, &ssp4_lock}, | ||
133 | }; | ||
134 | |||
135 | static struct mmp_param_gate_clk apbc_gate_clks[] = { | ||
136 | {PXA168_CLK_TWSI0, "twsi0_clk", "pll1_13_1_5", CLK_SET_RATE_PARENT, APBC_TWSI0, 0x3, 0x3, 0x0, 0, &reset_lock}, | ||
137 | {PXA168_CLK_TWSI1, "twsi1_clk", "pll1_13_1_5", CLK_SET_RATE_PARENT, APBC_TWSI1, 0x3, 0x3, 0x0, 0, &reset_lock}, | ||
138 | {PXA168_CLK_GPIO, "gpio_clk", "vctcxo", CLK_SET_RATE_PARENT, APBC_GPIO, 0x3, 0x3, 0x0, 0, &reset_lock}, | ||
139 | {PXA168_CLK_KPC, "kpc_clk", "clk32", CLK_SET_RATE_PARENT, APBC_KPC, 0x3, 0x3, 0x0, MMP_CLK_GATE_NEED_DELAY, NULL}, | ||
140 | {PXA168_CLK_RTC, "rtc_clk", "clk32", CLK_SET_RATE_PARENT, APBC_RTC, 0x83, 0x83, 0x0, MMP_CLK_GATE_NEED_DELAY, NULL}, | ||
141 | {PXA168_CLK_PWM0, "pwm0_clk", "pll1_48", CLK_SET_RATE_PARENT, APBC_PWM0, 0x3, 0x3, 0x0, 0, &reset_lock}, | ||
142 | {PXA168_CLK_PWM1, "pwm1_clk", "pll1_48", CLK_SET_RATE_PARENT, APBC_PWM1, 0x3, 0x3, 0x0, 0, &reset_lock}, | ||
143 | {PXA168_CLK_PWM2, "pwm2_clk", "pll1_48", CLK_SET_RATE_PARENT, APBC_PWM2, 0x3, 0x3, 0x0, 0, &reset_lock}, | ||
144 | {PXA168_CLK_PWM3, "pwm3_clk", "pll1_48", CLK_SET_RATE_PARENT, APBC_PWM3, 0x3, 0x3, 0x0, 0, &reset_lock}, | ||
145 | /* The gate clocks has mux parent. */ | ||
146 | {PXA168_CLK_UART0, "uart0_clk", "uart0_mux", CLK_SET_RATE_PARENT, APBC_UART0, 0x3, 0x3, 0x0, 0, &uart0_lock}, | ||
147 | {PXA168_CLK_UART1, "uart1_clk", "uart1_mux", CLK_SET_RATE_PARENT, APBC_UART1, 0x3, 0x3, 0x0, 0, &uart1_lock}, | ||
148 | {PXA168_CLK_UART2, "uart2_clk", "uart2_mux", CLK_SET_RATE_PARENT, APBC_UART2, 0x3, 0x3, 0x0, 0, &uart2_lock}, | ||
149 | {PXA168_CLK_SSP0, "ssp0_clk", "ssp0_mux", CLK_SET_RATE_PARENT, APBC_SSP0, 0x3, 0x3, 0x0, 0, &ssp0_lock}, | ||
150 | {PXA168_CLK_SSP1, "ssp1_clk", "ssp1_mux", CLK_SET_RATE_PARENT, APBC_SSP1, 0x3, 0x3, 0x0, 0, &ssp1_lock}, | ||
151 | {PXA168_CLK_SSP2, "ssp2_clk", "ssp2_mux", CLK_SET_RATE_PARENT, APBC_SSP2, 0x3, 0x3, 0x0, 0, &ssp2_lock}, | ||
152 | {PXA168_CLK_SSP3, "ssp3_clk", "ssp3_mux", CLK_SET_RATE_PARENT, APBC_SSP3, 0x3, 0x3, 0x0, 0, &ssp3_lock}, | ||
153 | {PXA168_CLK_SSP4, "ssp4_clk", "ssp4_mux", CLK_SET_RATE_PARENT, APBC_SSP4, 0x3, 0x3, 0x0, 0, &ssp4_lock}, | ||
154 | }; | ||
155 | |||
156 | static void pxa168_apb_periph_clk_init(struct pxa168_clk_unit *pxa_unit) | ||
157 | { | ||
158 | struct mmp_clk_unit *unit = &pxa_unit->unit; | ||
159 | |||
160 | mmp_register_mux_clks(unit, apbc_mux_clks, pxa_unit->apbc_base, | ||
161 | ARRAY_SIZE(apbc_mux_clks)); | ||
162 | |||
163 | mmp_register_gate_clks(unit, apbc_gate_clks, pxa_unit->apbc_base, | ||
164 | ARRAY_SIZE(apbc_gate_clks)); | ||
165 | |||
166 | } | ||
167 | |||
168 | static DEFINE_SPINLOCK(sdh0_lock); | ||
169 | static DEFINE_SPINLOCK(sdh1_lock); | ||
170 | static const char *sdh_parent_names[] = {"pll1_12", "pll1_13"}; | ||
171 | |||
172 | static DEFINE_SPINLOCK(usb_lock); | ||
173 | |||
174 | static DEFINE_SPINLOCK(disp0_lock); | ||
175 | static const char *disp_parent_names[] = {"pll1_2", "pll1_12"}; | ||
176 | |||
177 | static DEFINE_SPINLOCK(ccic0_lock); | ||
178 | static const char *ccic_parent_names[] = {"pll1_2", "pll1_12"}; | ||
179 | static const char *ccic_phy_parent_names[] = {"pll1_6", "pll1_12"}; | ||
180 | |||
181 | static struct mmp_param_mux_clk apmu_mux_clks[] = { | ||
182 | {0, "sdh0_mux", sdh_parent_names, ARRAY_SIZE(sdh_parent_names), CLK_SET_RATE_PARENT, APMU_SDH0, 6, 1, 0, &sdh0_lock}, | ||
183 | {0, "sdh1_mux", sdh_parent_names, ARRAY_SIZE(sdh_parent_names), CLK_SET_RATE_PARENT, APMU_SDH1, 6, 1, 0, &sdh1_lock}, | ||
184 | {0, "disp0_mux", disp_parent_names, ARRAY_SIZE(disp_parent_names), CLK_SET_RATE_PARENT, APMU_DISP0, 6, 1, 0, &disp0_lock}, | ||
185 | {0, "ccic0_mux", ccic_parent_names, ARRAY_SIZE(ccic_parent_names), CLK_SET_RATE_PARENT, APMU_CCIC0, 6, 1, 0, &ccic0_lock}, | ||
186 | {0, "ccic0_phy_mux", ccic_phy_parent_names, ARRAY_SIZE(ccic_phy_parent_names), CLK_SET_RATE_PARENT, APMU_CCIC0, 7, 1, 0, &ccic0_lock}, | ||
187 | }; | ||
188 | |||
189 | static struct mmp_param_div_clk apmu_div_clks[] = { | ||
190 | {0, "ccic0_sphy_div", "ccic0_mux", CLK_SET_RATE_PARENT, APMU_CCIC0, 10, 5, 0, &ccic0_lock}, | ||
191 | }; | ||
192 | |||
193 | static struct mmp_param_gate_clk apmu_gate_clks[] = { | ||
194 | {PXA168_CLK_DFC, "dfc_clk", "pll1_4", CLK_SET_RATE_PARENT, APMU_DFC, 0x19b, 0x19b, 0x0, 0, NULL}, | ||
195 | {PXA168_CLK_USB, "usb_clk", "usb_pll", 0, APMU_USB, 0x9, 0x9, 0x0, 0, &usb_lock}, | ||
196 | {PXA168_CLK_SPH, "sph_clk", "usb_pll", 0, APMU_USB, 0x12, 0x12, 0x0, 0, &usb_lock}, | ||
197 | /* The gate clocks has mux parent. */ | ||
198 | {PXA168_CLK_SDH0, "sdh0_clk", "sdh0_mux", CLK_SET_RATE_PARENT, APMU_SDH0, 0x1b, 0x1b, 0x0, 0, &sdh0_lock}, | ||
199 | {PXA168_CLK_SDH1, "sdh1_clk", "sdh1_mux", CLK_SET_RATE_PARENT, APMU_SDH1, 0x1b, 0x1b, 0x0, 0, &sdh1_lock}, | ||
200 | {PXA168_CLK_DISP0, "disp0_clk", "disp0_mux", CLK_SET_RATE_PARENT, APMU_DISP0, 0x1b, 0x1b, 0x0, 0, &disp0_lock}, | ||
201 | {PXA168_CLK_CCIC0, "ccic0_clk", "ccic0_mux", CLK_SET_RATE_PARENT, APMU_CCIC0, 0x1b, 0x1b, 0x0, 0, &ccic0_lock}, | ||
202 | {PXA168_CLK_CCIC0_PHY, "ccic0_phy_clk", "ccic0_phy_mux", CLK_SET_RATE_PARENT, APMU_CCIC0, 0x24, 0x24, 0x0, 0, &ccic0_lock}, | ||
203 | {PXA168_CLK_CCIC0_SPHY, "ccic0_sphy_clk", "ccic0_sphy_div", CLK_SET_RATE_PARENT, APMU_CCIC0, 0x300, 0x300, 0x0, 0, &ccic0_lock}, | ||
204 | }; | ||
205 | |||
206 | static void pxa168_axi_periph_clk_init(struct pxa168_clk_unit *pxa_unit) | ||
207 | { | ||
208 | struct mmp_clk_unit *unit = &pxa_unit->unit; | ||
209 | |||
210 | mmp_register_mux_clks(unit, apmu_mux_clks, pxa_unit->apmu_base, | ||
211 | ARRAY_SIZE(apmu_mux_clks)); | ||
212 | |||
213 | mmp_register_div_clks(unit, apmu_div_clks, pxa_unit->apmu_base, | ||
214 | ARRAY_SIZE(apmu_div_clks)); | ||
215 | |||
216 | mmp_register_gate_clks(unit, apmu_gate_clks, pxa_unit->apmu_base, | ||
217 | ARRAY_SIZE(apmu_gate_clks)); | ||
218 | } | ||
219 | |||
220 | static void pxa168_clk_reset_init(struct device_node *np, | ||
221 | struct pxa168_clk_unit *pxa_unit) | ||
222 | { | ||
223 | struct mmp_clk_reset_cell *cells; | ||
224 | int i, nr_resets; | ||
225 | |||
226 | nr_resets = ARRAY_SIZE(apbc_gate_clks); | ||
227 | cells = kcalloc(nr_resets, sizeof(*cells), GFP_KERNEL); | ||
228 | if (!cells) | ||
229 | return; | ||
230 | |||
231 | for (i = 0; i < nr_resets; i++) { | ||
232 | cells[i].clk_id = apbc_gate_clks[i].id; | ||
233 | cells[i].reg = pxa_unit->apbc_base + apbc_gate_clks[i].offset; | ||
234 | cells[i].flags = 0; | ||
235 | cells[i].lock = apbc_gate_clks[i].lock; | ||
236 | cells[i].bits = 0x4; | ||
237 | } | ||
238 | |||
239 | mmp_clk_reset_register(np, cells, nr_resets); | ||
240 | } | ||
241 | |||
242 | static void __init pxa168_clk_init(struct device_node *np) | ||
243 | { | ||
244 | struct pxa168_clk_unit *pxa_unit; | ||
245 | |||
246 | pxa_unit = kzalloc(sizeof(*pxa_unit), GFP_KERNEL); | ||
247 | if (!pxa_unit) | ||
248 | return; | ||
249 | |||
250 | pxa_unit->mpmu_base = of_iomap(np, 0); | ||
251 | if (!pxa_unit->mpmu_base) { | ||
252 | pr_err("failed to map mpmu registers\n"); | ||
253 | return; | ||
254 | } | ||
255 | |||
256 | pxa_unit->apmu_base = of_iomap(np, 1); | ||
257 | if (!pxa_unit->mpmu_base) { | ||
258 | pr_err("failed to map apmu registers\n"); | ||
259 | return; | ||
260 | } | ||
261 | |||
262 | pxa_unit->apbc_base = of_iomap(np, 2); | ||
263 | if (!pxa_unit->apbc_base) { | ||
264 | pr_err("failed to map apbc registers\n"); | ||
265 | return; | ||
266 | } | ||
267 | |||
268 | mmp_clk_init(np, &pxa_unit->unit, PXA168_NR_CLKS); | ||
269 | |||
270 | pxa168_pll_init(pxa_unit); | ||
271 | |||
272 | pxa168_apb_periph_clk_init(pxa_unit); | ||
273 | |||
274 | pxa168_axi_periph_clk_init(pxa_unit); | ||
275 | |||
276 | pxa168_clk_reset_init(np, pxa_unit); | ||
277 | } | ||
278 | |||
279 | CLK_OF_DECLARE(pxa168_clk, "marvell,pxa168-clock", pxa168_clk_init); | ||
diff --git a/drivers/clk/mmp/clk-of-pxa910.c b/drivers/clk/mmp/clk-of-pxa910.c new file mode 100644 index 000000000000..5e3c80dad336 --- /dev/null +++ b/drivers/clk/mmp/clk-of-pxa910.c | |||
@@ -0,0 +1,301 @@ | |||
1 | /* | ||
2 | * pxa910 clock framework source file | ||
3 | * | ||
4 | * Copyright (C) 2012 Marvell | ||
5 | * Chao Xie <xiechao.mail@gmail.com> | ||
6 | * | ||
7 | * This file is licensed under the terms of the GNU General Public | ||
8 | * License version 2. This program is licensed "as is" without any | ||
9 | * warranty of any kind, whether express or implied. | ||
10 | */ | ||
11 | |||
12 | #include <linux/module.h> | ||
13 | #include <linux/kernel.h> | ||
14 | #include <linux/spinlock.h> | ||
15 | #include <linux/io.h> | ||
16 | #include <linux/delay.h> | ||
17 | #include <linux/err.h> | ||
18 | #include <linux/of_address.h> | ||
19 | |||
20 | #include <dt-bindings/clock/marvell,pxa910.h> | ||
21 | |||
22 | #include "clk.h" | ||
23 | #include "reset.h" | ||
24 | |||
25 | #define APBC_RTC 0x28 | ||
26 | #define APBC_TWSI0 0x2c | ||
27 | #define APBC_KPC 0x18 | ||
28 | #define APBC_UART0 0x0 | ||
29 | #define APBC_UART1 0x4 | ||
30 | #define APBC_GPIO 0x8 | ||
31 | #define APBC_PWM0 0xc | ||
32 | #define APBC_PWM1 0x10 | ||
33 | #define APBC_PWM2 0x14 | ||
34 | #define APBC_PWM3 0x18 | ||
35 | #define APBC_SSP0 0x1c | ||
36 | #define APBC_SSP1 0x20 | ||
37 | #define APBC_SSP2 0x4c | ||
38 | #define APBCP_TWSI1 0x28 | ||
39 | #define APBCP_UART2 0x1c | ||
40 | #define APMU_SDH0 0x54 | ||
41 | #define APMU_SDH1 0x58 | ||
42 | #define APMU_USB 0x5c | ||
43 | #define APMU_DISP0 0x4c | ||
44 | #define APMU_CCIC0 0x50 | ||
45 | #define APMU_DFC 0x60 | ||
46 | #define MPMU_UART_PLL 0x14 | ||
47 | |||
48 | struct pxa910_clk_unit { | ||
49 | struct mmp_clk_unit unit; | ||
50 | void __iomem *mpmu_base; | ||
51 | void __iomem *apmu_base; | ||
52 | void __iomem *apbc_base; | ||
53 | void __iomem *apbcp_base; | ||
54 | }; | ||
55 | |||
56 | static struct mmp_param_fixed_rate_clk fixed_rate_clks[] = { | ||
57 | {PXA910_CLK_CLK32, "clk32", NULL, CLK_IS_ROOT, 32768}, | ||
58 | {PXA910_CLK_VCTCXO, "vctcxo", NULL, CLK_IS_ROOT, 26000000}, | ||
59 | {PXA910_CLK_PLL1, "pll1", NULL, CLK_IS_ROOT, 624000000}, | ||
60 | }; | ||
61 | |||
62 | static struct mmp_param_fixed_factor_clk fixed_factor_clks[] = { | ||
63 | {PXA910_CLK_PLL1_2, "pll1_2", "pll1", 1, 2, 0}, | ||
64 | {PXA910_CLK_PLL1_4, "pll1_4", "pll1_2", 1, 2, 0}, | ||
65 | {PXA910_CLK_PLL1_8, "pll1_8", "pll1_4", 1, 2, 0}, | ||
66 | {PXA910_CLK_PLL1_16, "pll1_16", "pll1_8", 1, 2, 0}, | ||
67 | {PXA910_CLK_PLL1_6, "pll1_6", "pll1_2", 1, 3, 0}, | ||
68 | {PXA910_CLK_PLL1_12, "pll1_12", "pll1_6", 1, 2, 0}, | ||
69 | {PXA910_CLK_PLL1_24, "pll1_24", "pll1_12", 1, 2, 0}, | ||
70 | {PXA910_CLK_PLL1_48, "pll1_48", "pll1_24", 1, 2, 0}, | ||
71 | {PXA910_CLK_PLL1_96, "pll1_96", "pll1_48", 1, 2, 0}, | ||
72 | {PXA910_CLK_PLL1_13, "pll1_13", "pll1", 1, 13, 0}, | ||
73 | {PXA910_CLK_PLL1_13_1_5, "pll1_13_1_5", "pll1_13", 2, 3, 0}, | ||
74 | {PXA910_CLK_PLL1_2_1_5, "pll1_2_1_5", "pll1_2", 2, 3, 0}, | ||
75 | {PXA910_CLK_PLL1_3_16, "pll1_3_16", "pll1", 3, 16, 0}, | ||
76 | }; | ||
77 | |||
78 | static struct mmp_clk_factor_masks uart_factor_masks = { | ||
79 | .factor = 2, | ||
80 | .num_mask = 0x1fff, | ||
81 | .den_mask = 0x1fff, | ||
82 | .num_shift = 16, | ||
83 | .den_shift = 0, | ||
84 | }; | ||
85 | |||
86 | static struct mmp_clk_factor_tbl uart_factor_tbl[] = { | ||
87 | {.num = 8125, .den = 1536}, /*14.745MHZ */ | ||
88 | }; | ||
89 | |||
90 | static void pxa910_pll_init(struct pxa910_clk_unit *pxa_unit) | ||
91 | { | ||
92 | struct clk *clk; | ||
93 | struct mmp_clk_unit *unit = &pxa_unit->unit; | ||
94 | |||
95 | mmp_register_fixed_rate_clks(unit, fixed_rate_clks, | ||
96 | ARRAY_SIZE(fixed_rate_clks)); | ||
97 | |||
98 | mmp_register_fixed_factor_clks(unit, fixed_factor_clks, | ||
99 | ARRAY_SIZE(fixed_factor_clks)); | ||
100 | |||
101 | clk = mmp_clk_register_factor("uart_pll", "pll1_4", | ||
102 | CLK_SET_RATE_PARENT, | ||
103 | pxa_unit->mpmu_base + MPMU_UART_PLL, | ||
104 | &uart_factor_masks, uart_factor_tbl, | ||
105 | ARRAY_SIZE(uart_factor_tbl), NULL); | ||
106 | mmp_clk_add(unit, PXA910_CLK_UART_PLL, clk); | ||
107 | } | ||
108 | |||
109 | static DEFINE_SPINLOCK(uart0_lock); | ||
110 | static DEFINE_SPINLOCK(uart1_lock); | ||
111 | static DEFINE_SPINLOCK(uart2_lock); | ||
112 | static const char *uart_parent_names[] = {"pll1_3_16", "uart_pll"}; | ||
113 | |||
114 | static DEFINE_SPINLOCK(ssp0_lock); | ||
115 | static DEFINE_SPINLOCK(ssp1_lock); | ||
116 | static const char *ssp_parent_names[] = {"pll1_96", "pll1_48", "pll1_24", "pll1_12"}; | ||
117 | |||
118 | static DEFINE_SPINLOCK(reset_lock); | ||
119 | |||
120 | static struct mmp_param_mux_clk apbc_mux_clks[] = { | ||
121 | {0, "uart0_mux", uart_parent_names, ARRAY_SIZE(uart_parent_names), CLK_SET_RATE_PARENT, APBC_UART0, 4, 3, 0, &uart0_lock}, | ||
122 | {0, "uart1_mux", uart_parent_names, ARRAY_SIZE(uart_parent_names), CLK_SET_RATE_PARENT, APBC_UART1, 4, 3, 0, &uart1_lock}, | ||
123 | {0, "ssp0_mux", ssp_parent_names, ARRAY_SIZE(ssp_parent_names), CLK_SET_RATE_PARENT, APBC_SSP0, 4, 3, 0, &ssp0_lock}, | ||
124 | {0, "ssp1_mux", ssp_parent_names, ARRAY_SIZE(ssp_parent_names), CLK_SET_RATE_PARENT, APBC_SSP1, 4, 3, 0, &ssp1_lock}, | ||
125 | }; | ||
126 | |||
127 | static struct mmp_param_mux_clk apbcp_mux_clks[] = { | ||
128 | {0, "uart2_mux", uart_parent_names, ARRAY_SIZE(uart_parent_names), CLK_SET_RATE_PARENT, APBCP_UART2, 4, 3, 0, &uart2_lock}, | ||
129 | }; | ||
130 | |||
131 | static struct mmp_param_gate_clk apbc_gate_clks[] = { | ||
132 | {PXA910_CLK_TWSI0, "twsi0_clk", "pll1_13_1_5", CLK_SET_RATE_PARENT, APBC_TWSI0, 0x3, 0x3, 0x0, 0, &reset_lock}, | ||
133 | {PXA910_CLK_GPIO, "gpio_clk", "vctcxo", CLK_SET_RATE_PARENT, APBC_GPIO, 0x3, 0x3, 0x0, 0, &reset_lock}, | ||
134 | {PXA910_CLK_KPC, "kpc_clk", "clk32", CLK_SET_RATE_PARENT, APBC_KPC, 0x3, 0x3, 0x0, MMP_CLK_GATE_NEED_DELAY, NULL}, | ||
135 | {PXA910_CLK_RTC, "rtc_clk", "clk32", CLK_SET_RATE_PARENT, APBC_RTC, 0x83, 0x83, 0x0, MMP_CLK_GATE_NEED_DELAY, NULL}, | ||
136 | {PXA910_CLK_PWM0, "pwm0_clk", "pll1_48", CLK_SET_RATE_PARENT, APBC_PWM0, 0x3, 0x3, 0x0, 0, &reset_lock}, | ||
137 | {PXA910_CLK_PWM1, "pwm1_clk", "pll1_48", CLK_SET_RATE_PARENT, APBC_PWM1, 0x3, 0x3, 0x0, 0, &reset_lock}, | ||
138 | {PXA910_CLK_PWM2, "pwm2_clk", "pll1_48", CLK_SET_RATE_PARENT, APBC_PWM2, 0x3, 0x3, 0x0, 0, &reset_lock}, | ||
139 | {PXA910_CLK_PWM3, "pwm3_clk", "pll1_48", CLK_SET_RATE_PARENT, APBC_PWM3, 0x3, 0x3, 0x0, 0, &reset_lock}, | ||
140 | /* The gate clocks has mux parent. */ | ||
141 | {PXA910_CLK_UART0, "uart0_clk", "uart0_mux", CLK_SET_RATE_PARENT, APBC_UART0, 0x3, 0x3, 0x0, 0, &uart0_lock}, | ||
142 | {PXA910_CLK_UART1, "uart1_clk", "uart1_mux", CLK_SET_RATE_PARENT, APBC_UART1, 0x3, 0x3, 0x0, 0, &uart1_lock}, | ||
143 | {PXA910_CLK_SSP0, "ssp0_clk", "ssp0_mux", CLK_SET_RATE_PARENT, APBC_SSP0, 0x3, 0x3, 0x0, 0, &ssp0_lock}, | ||
144 | {PXA910_CLK_SSP1, "ssp1_clk", "ssp1_mux", CLK_SET_RATE_PARENT, APBC_SSP1, 0x3, 0x3, 0x0, 0, &ssp1_lock}, | ||
145 | }; | ||
146 | |||
147 | static struct mmp_param_gate_clk apbcp_gate_clks[] = { | ||
148 | {PXA910_CLK_TWSI1, "twsi1_clk", "pll1_13_1_5", CLK_SET_RATE_PARENT, APBCP_TWSI1, 0x3, 0x3, 0x0, 0, &reset_lock}, | ||
149 | /* The gate clocks has mux parent. */ | ||
150 | {PXA910_CLK_UART2, "uart2_clk", "uart2_mux", CLK_SET_RATE_PARENT, APBCP_UART2, 0x3, 0x3, 0x0, 0, &uart2_lock}, | ||
151 | }; | ||
152 | |||
153 | static void pxa910_apb_periph_clk_init(struct pxa910_clk_unit *pxa_unit) | ||
154 | { | ||
155 | struct mmp_clk_unit *unit = &pxa_unit->unit; | ||
156 | |||
157 | mmp_register_mux_clks(unit, apbc_mux_clks, pxa_unit->apbc_base, | ||
158 | ARRAY_SIZE(apbc_mux_clks)); | ||
159 | |||
160 | mmp_register_mux_clks(unit, apbcp_mux_clks, pxa_unit->apbcp_base, | ||
161 | ARRAY_SIZE(apbcp_mux_clks)); | ||
162 | |||
163 | mmp_register_gate_clks(unit, apbc_gate_clks, pxa_unit->apbc_base, | ||
164 | ARRAY_SIZE(apbc_gate_clks)); | ||
165 | |||
166 | mmp_register_gate_clks(unit, apbcp_gate_clks, pxa_unit->apbcp_base, | ||
167 | ARRAY_SIZE(apbcp_gate_clks)); | ||
168 | } | ||
169 | |||
170 | static DEFINE_SPINLOCK(sdh0_lock); | ||
171 | static DEFINE_SPINLOCK(sdh1_lock); | ||
172 | static const char *sdh_parent_names[] = {"pll1_12", "pll1_13"}; | ||
173 | |||
174 | static DEFINE_SPINLOCK(usb_lock); | ||
175 | |||
176 | static DEFINE_SPINLOCK(disp0_lock); | ||
177 | static const char *disp_parent_names[] = {"pll1_2", "pll1_12"}; | ||
178 | |||
179 | static DEFINE_SPINLOCK(ccic0_lock); | ||
180 | static const char *ccic_parent_names[] = {"pll1_2", "pll1_12"}; | ||
181 | static const char *ccic_phy_parent_names[] = {"pll1_6", "pll1_12"}; | ||
182 | |||
183 | static struct mmp_param_mux_clk apmu_mux_clks[] = { | ||
184 | {0, "sdh0_mux", sdh_parent_names, ARRAY_SIZE(sdh_parent_names), CLK_SET_RATE_PARENT, APMU_SDH0, 6, 1, 0, &sdh0_lock}, | ||
185 | {0, "sdh1_mux", sdh_parent_names, ARRAY_SIZE(sdh_parent_names), CLK_SET_RATE_PARENT, APMU_SDH1, 6, 1, 0, &sdh1_lock}, | ||
186 | {0, "disp0_mux", disp_parent_names, ARRAY_SIZE(disp_parent_names), CLK_SET_RATE_PARENT, APMU_DISP0, 6, 1, 0, &disp0_lock}, | ||
187 | {0, "ccic0_mux", ccic_parent_names, ARRAY_SIZE(ccic_parent_names), CLK_SET_RATE_PARENT, APMU_CCIC0, 6, 1, 0, &ccic0_lock}, | ||
188 | {0, "ccic0_phy_mux", ccic_phy_parent_names, ARRAY_SIZE(ccic_phy_parent_names), CLK_SET_RATE_PARENT, APMU_CCIC0, 7, 1, 0, &ccic0_lock}, | ||
189 | }; | ||
190 | |||
191 | static struct mmp_param_div_clk apmu_div_clks[] = { | ||
192 | {0, "ccic0_sphy_div", "ccic0_mux", CLK_SET_RATE_PARENT, APMU_CCIC0, 10, 5, 0, &ccic0_lock}, | ||
193 | }; | ||
194 | |||
195 | static struct mmp_param_gate_clk apmu_gate_clks[] = { | ||
196 | {PXA910_CLK_DFC, "dfc_clk", "pll1_4", CLK_SET_RATE_PARENT, APMU_DFC, 0x19b, 0x19b, 0x0, 0, NULL}, | ||
197 | {PXA910_CLK_USB, "usb_clk", "usb_pll", 0, APMU_USB, 0x9, 0x9, 0x0, 0, &usb_lock}, | ||
198 | {PXA910_CLK_SPH, "sph_clk", "usb_pll", 0, APMU_USB, 0x12, 0x12, 0x0, 0, &usb_lock}, | ||
199 | /* The gate clocks has mux parent. */ | ||
200 | {PXA910_CLK_SDH0, "sdh0_clk", "sdh0_mux", CLK_SET_RATE_PARENT, APMU_SDH0, 0x1b, 0x1b, 0x0, 0, &sdh0_lock}, | ||
201 | {PXA910_CLK_SDH1, "sdh1_clk", "sdh1_mux", CLK_SET_RATE_PARENT, APMU_SDH1, 0x1b, 0x1b, 0x0, 0, &sdh1_lock}, | ||
202 | {PXA910_CLK_DISP0, "disp0_clk", "disp0_mux", CLK_SET_RATE_PARENT, APMU_DISP0, 0x1b, 0x1b, 0x0, 0, &disp0_lock}, | ||
203 | {PXA910_CLK_CCIC0, "ccic0_clk", "ccic0_mux", CLK_SET_RATE_PARENT, APMU_CCIC0, 0x1b, 0x1b, 0x0, 0, &ccic0_lock}, | ||
204 | {PXA910_CLK_CCIC0_PHY, "ccic0_phy_clk", "ccic0_phy_mux", CLK_SET_RATE_PARENT, APMU_CCIC0, 0x24, 0x24, 0x0, 0, &ccic0_lock}, | ||
205 | {PXA910_CLK_CCIC0_SPHY, "ccic0_sphy_clk", "ccic0_sphy_div", CLK_SET_RATE_PARENT, APMU_CCIC0, 0x300, 0x300, 0x0, 0, &ccic0_lock}, | ||
206 | }; | ||
207 | |||
208 | static void pxa910_axi_periph_clk_init(struct pxa910_clk_unit *pxa_unit) | ||
209 | { | ||
210 | struct mmp_clk_unit *unit = &pxa_unit->unit; | ||
211 | |||
212 | mmp_register_mux_clks(unit, apmu_mux_clks, pxa_unit->apmu_base, | ||
213 | ARRAY_SIZE(apmu_mux_clks)); | ||
214 | |||
215 | mmp_register_div_clks(unit, apmu_div_clks, pxa_unit->apmu_base, | ||
216 | ARRAY_SIZE(apmu_div_clks)); | ||
217 | |||
218 | mmp_register_gate_clks(unit, apmu_gate_clks, pxa_unit->apmu_base, | ||
219 | ARRAY_SIZE(apmu_gate_clks)); | ||
220 | } | ||
221 | |||
222 | static void pxa910_clk_reset_init(struct device_node *np, | ||
223 | struct pxa910_clk_unit *pxa_unit) | ||
224 | { | ||
225 | struct mmp_clk_reset_cell *cells; | ||
226 | int i, base, nr_resets_apbc, nr_resets_apbcp, nr_resets; | ||
227 | |||
228 | nr_resets_apbc = ARRAY_SIZE(apbc_gate_clks); | ||
229 | nr_resets_apbcp = ARRAY_SIZE(apbcp_gate_clks); | ||
230 | nr_resets = nr_resets_apbc + nr_resets_apbcp; | ||
231 | cells = kcalloc(nr_resets, sizeof(*cells), GFP_KERNEL); | ||
232 | if (!cells) | ||
233 | return; | ||
234 | |||
235 | base = 0; | ||
236 | for (i = 0; i < nr_resets_apbc; i++) { | ||
237 | cells[base + i].clk_id = apbc_gate_clks[i].id; | ||
238 | cells[base + i].reg = | ||
239 | pxa_unit->apbc_base + apbc_gate_clks[i].offset; | ||
240 | cells[base + i].flags = 0; | ||
241 | cells[base + i].lock = apbc_gate_clks[i].lock; | ||
242 | cells[base + i].bits = 0x4; | ||
243 | } | ||
244 | |||
245 | base = nr_resets_apbc; | ||
246 | for (i = 0; i < nr_resets_apbcp; i++) { | ||
247 | cells[base + i].clk_id = apbcp_gate_clks[i].id; | ||
248 | cells[base + i].reg = | ||
249 | pxa_unit->apbc_base + apbc_gate_clks[i].offset; | ||
250 | cells[base + i].flags = 0; | ||
251 | cells[base + i].lock = apbc_gate_clks[i].lock; | ||
252 | cells[base + i].bits = 0x4; | ||
253 | } | ||
254 | |||
255 | mmp_clk_reset_register(np, cells, nr_resets); | ||
256 | } | ||
257 | |||
258 | static void __init pxa910_clk_init(struct device_node *np) | ||
259 | { | ||
260 | struct pxa910_clk_unit *pxa_unit; | ||
261 | |||
262 | pxa_unit = kzalloc(sizeof(*pxa_unit), GFP_KERNEL); | ||
263 | if (!pxa_unit) | ||
264 | return; | ||
265 | |||
266 | pxa_unit->mpmu_base = of_iomap(np, 0); | ||
267 | if (!pxa_unit->mpmu_base) { | ||
268 | pr_err("failed to map mpmu registers\n"); | ||
269 | return; | ||
270 | } | ||
271 | |||
272 | pxa_unit->apmu_base = of_iomap(np, 1); | ||
273 | if (!pxa_unit->mpmu_base) { | ||
274 | pr_err("failed to map apmu registers\n"); | ||
275 | return; | ||
276 | } | ||
277 | |||
278 | pxa_unit->apbc_base = of_iomap(np, 2); | ||
279 | if (!pxa_unit->apbc_base) { | ||
280 | pr_err("failed to map apbc registers\n"); | ||
281 | return; | ||
282 | } | ||
283 | |||
284 | pxa_unit->apbcp_base = of_iomap(np, 3); | ||
285 | if (!pxa_unit->mpmu_base) { | ||
286 | pr_err("failed to map apbcp registers\n"); | ||
287 | return; | ||
288 | } | ||
289 | |||
290 | mmp_clk_init(np, &pxa_unit->unit, PXA910_NR_CLKS); | ||
291 | |||
292 | pxa910_pll_init(pxa_unit); | ||
293 | |||
294 | pxa910_apb_periph_clk_init(pxa_unit); | ||
295 | |||
296 | pxa910_axi_periph_clk_init(pxa_unit); | ||
297 | |||
298 | pxa910_clk_reset_init(np, pxa_unit); | ||
299 | } | ||
300 | |||
301 | CLK_OF_DECLARE(pxa910_clk, "marvell,pxa910-clock", pxa910_clk_init); | ||
diff --git a/drivers/clk/mmp/clk-pxa168.c b/drivers/clk/mmp/clk-pxa168.c index 014396b028a2..93e967c0f972 100644 --- a/drivers/clk/mmp/clk-pxa168.c +++ b/drivers/clk/mmp/clk-pxa168.c | |||
@@ -47,7 +47,7 @@ | |||
47 | 47 | ||
48 | static DEFINE_SPINLOCK(clk_lock); | 48 | static DEFINE_SPINLOCK(clk_lock); |
49 | 49 | ||
50 | static struct clk_factor_masks uart_factor_masks = { | 50 | static struct mmp_clk_factor_masks uart_factor_masks = { |
51 | .factor = 2, | 51 | .factor = 2, |
52 | .num_mask = 0x1fff, | 52 | .num_mask = 0x1fff, |
53 | .den_mask = 0x1fff, | 53 | .den_mask = 0x1fff, |
@@ -55,7 +55,7 @@ static struct clk_factor_masks uart_factor_masks = { | |||
55 | .den_shift = 0, | 55 | .den_shift = 0, |
56 | }; | 56 | }; |
57 | 57 | ||
58 | static struct clk_factor_tbl uart_factor_tbl[] = { | 58 | static struct mmp_clk_factor_tbl uart_factor_tbl[] = { |
59 | {.num = 8125, .den = 1536}, /*14.745MHZ */ | 59 | {.num = 8125, .den = 1536}, /*14.745MHZ */ |
60 | }; | 60 | }; |
61 | 61 | ||
@@ -158,7 +158,7 @@ void __init pxa168_clk_init(void) | |||
158 | uart_pll = mmp_clk_register_factor("uart_pll", "pll1_4", 0, | 158 | uart_pll = mmp_clk_register_factor("uart_pll", "pll1_4", 0, |
159 | mpmu_base + MPMU_UART_PLL, | 159 | mpmu_base + MPMU_UART_PLL, |
160 | &uart_factor_masks, uart_factor_tbl, | 160 | &uart_factor_masks, uart_factor_tbl, |
161 | ARRAY_SIZE(uart_factor_tbl)); | 161 | ARRAY_SIZE(uart_factor_tbl), &clk_lock); |
162 | clk_set_rate(uart_pll, 14745600); | 162 | clk_set_rate(uart_pll, 14745600); |
163 | clk_register_clkdev(uart_pll, "uart_pll", NULL); | 163 | clk_register_clkdev(uart_pll, "uart_pll", NULL); |
164 | 164 | ||
diff --git a/drivers/clk/mmp/clk-pxa910.c b/drivers/clk/mmp/clk-pxa910.c index 9efc6a47535d..993abcdb32cc 100644 --- a/drivers/clk/mmp/clk-pxa910.c +++ b/drivers/clk/mmp/clk-pxa910.c | |||
@@ -45,7 +45,7 @@ | |||
45 | 45 | ||
46 | static DEFINE_SPINLOCK(clk_lock); | 46 | static DEFINE_SPINLOCK(clk_lock); |
47 | 47 | ||
48 | static struct clk_factor_masks uart_factor_masks = { | 48 | static struct mmp_clk_factor_masks uart_factor_masks = { |
49 | .factor = 2, | 49 | .factor = 2, |
50 | .num_mask = 0x1fff, | 50 | .num_mask = 0x1fff, |
51 | .den_mask = 0x1fff, | 51 | .den_mask = 0x1fff, |
@@ -53,7 +53,7 @@ static struct clk_factor_masks uart_factor_masks = { | |||
53 | .den_shift = 0, | 53 | .den_shift = 0, |
54 | }; | 54 | }; |
55 | 55 | ||
56 | static struct clk_factor_tbl uart_factor_tbl[] = { | 56 | static struct mmp_clk_factor_tbl uart_factor_tbl[] = { |
57 | {.num = 8125, .den = 1536}, /*14.745MHZ */ | 57 | {.num = 8125, .den = 1536}, /*14.745MHZ */ |
58 | }; | 58 | }; |
59 | 59 | ||
@@ -163,7 +163,7 @@ void __init pxa910_clk_init(void) | |||
163 | uart_pll = mmp_clk_register_factor("uart_pll", "pll1_4", 0, | 163 | uart_pll = mmp_clk_register_factor("uart_pll", "pll1_4", 0, |
164 | mpmu_base + MPMU_UART_PLL, | 164 | mpmu_base + MPMU_UART_PLL, |
165 | &uart_factor_masks, uart_factor_tbl, | 165 | &uart_factor_masks, uart_factor_tbl, |
166 | ARRAY_SIZE(uart_factor_tbl)); | 166 | ARRAY_SIZE(uart_factor_tbl), &clk_lock); |
167 | clk_set_rate(uart_pll, 14745600); | 167 | clk_set_rate(uart_pll, 14745600); |
168 | clk_register_clkdev(uart_pll, "uart_pll", NULL); | 168 | clk_register_clkdev(uart_pll, "uart_pll", NULL); |
169 | 169 | ||
diff --git a/drivers/clk/mmp/clk.c b/drivers/clk/mmp/clk.c new file mode 100644 index 000000000000..cf038ef54c59 --- /dev/null +++ b/drivers/clk/mmp/clk.c | |||
@@ -0,0 +1,192 @@ | |||
1 | #include <linux/io.h> | ||
2 | #include <linux/clk.h> | ||
3 | #include <linux/clk-provider.h> | ||
4 | #include <linux/clkdev.h> | ||
5 | #include <linux/of.h> | ||
6 | #include <linux/of_address.h> | ||
7 | |||
8 | #include "clk.h" | ||
9 | |||
10 | void mmp_clk_init(struct device_node *np, struct mmp_clk_unit *unit, | ||
11 | int nr_clks) | ||
12 | { | ||
13 | static struct clk **clk_table; | ||
14 | |||
15 | clk_table = kcalloc(nr_clks, sizeof(struct clk *), GFP_KERNEL); | ||
16 | if (!clk_table) | ||
17 | return; | ||
18 | |||
19 | unit->clk_table = clk_table; | ||
20 | unit->nr_clks = nr_clks; | ||
21 | unit->clk_data.clks = clk_table; | ||
22 | unit->clk_data.clk_num = nr_clks; | ||
23 | of_clk_add_provider(np, of_clk_src_onecell_get, &unit->clk_data); | ||
24 | } | ||
25 | |||
26 | void mmp_register_fixed_rate_clks(struct mmp_clk_unit *unit, | ||
27 | struct mmp_param_fixed_rate_clk *clks, | ||
28 | int size) | ||
29 | { | ||
30 | int i; | ||
31 | struct clk *clk; | ||
32 | |||
33 | for (i = 0; i < size; i++) { | ||
34 | clk = clk_register_fixed_rate(NULL, clks[i].name, | ||
35 | clks[i].parent_name, | ||
36 | clks[i].flags, | ||
37 | clks[i].fixed_rate); | ||
38 | if (IS_ERR(clk)) { | ||
39 | pr_err("%s: failed to register clock %s\n", | ||
40 | __func__, clks[i].name); | ||
41 | continue; | ||
42 | } | ||
43 | if (clks[i].id) | ||
44 | unit->clk_table[clks[i].id] = clk; | ||
45 | } | ||
46 | } | ||
47 | |||
48 | void mmp_register_fixed_factor_clks(struct mmp_clk_unit *unit, | ||
49 | struct mmp_param_fixed_factor_clk *clks, | ||
50 | int size) | ||
51 | { | ||
52 | struct clk *clk; | ||
53 | int i; | ||
54 | |||
55 | for (i = 0; i < size; i++) { | ||
56 | clk = clk_register_fixed_factor(NULL, clks[i].name, | ||
57 | clks[i].parent_name, | ||
58 | clks[i].flags, clks[i].mult, | ||
59 | clks[i].div); | ||
60 | if (IS_ERR(clk)) { | ||
61 | pr_err("%s: failed to register clock %s\n", | ||
62 | __func__, clks[i].name); | ||
63 | continue; | ||
64 | } | ||
65 | if (clks[i].id) | ||
66 | unit->clk_table[clks[i].id] = clk; | ||
67 | } | ||
68 | } | ||
69 | |||
70 | void mmp_register_general_gate_clks(struct mmp_clk_unit *unit, | ||
71 | struct mmp_param_general_gate_clk *clks, | ||
72 | void __iomem *base, int size) | ||
73 | { | ||
74 | struct clk *clk; | ||
75 | int i; | ||
76 | |||
77 | for (i = 0; i < size; i++) { | ||
78 | clk = clk_register_gate(NULL, clks[i].name, | ||
79 | clks[i].parent_name, | ||
80 | clks[i].flags, | ||
81 | base + clks[i].offset, | ||
82 | clks[i].bit_idx, | ||
83 | clks[i].gate_flags, | ||
84 | clks[i].lock); | ||
85 | |||
86 | if (IS_ERR(clk)) { | ||
87 | pr_err("%s: failed to register clock %s\n", | ||
88 | __func__, clks[i].name); | ||
89 | continue; | ||
90 | } | ||
91 | if (clks[i].id) | ||
92 | unit->clk_table[clks[i].id] = clk; | ||
93 | } | ||
94 | } | ||
95 | |||
96 | void mmp_register_gate_clks(struct mmp_clk_unit *unit, | ||
97 | struct mmp_param_gate_clk *clks, | ||
98 | void __iomem *base, int size) | ||
99 | { | ||
100 | struct clk *clk; | ||
101 | int i; | ||
102 | |||
103 | for (i = 0; i < size; i++) { | ||
104 | clk = mmp_clk_register_gate(NULL, clks[i].name, | ||
105 | clks[i].parent_name, | ||
106 | clks[i].flags, | ||
107 | base + clks[i].offset, | ||
108 | clks[i].mask, | ||
109 | clks[i].val_enable, | ||
110 | clks[i].val_disable, | ||
111 | clks[i].gate_flags, | ||
112 | clks[i].lock); | ||
113 | |||
114 | if (IS_ERR(clk)) { | ||
115 | pr_err("%s: failed to register clock %s\n", | ||
116 | __func__, clks[i].name); | ||
117 | continue; | ||
118 | } | ||
119 | if (clks[i].id) | ||
120 | unit->clk_table[clks[i].id] = clk; | ||
121 | } | ||
122 | } | ||
123 | |||
124 | void mmp_register_mux_clks(struct mmp_clk_unit *unit, | ||
125 | struct mmp_param_mux_clk *clks, | ||
126 | void __iomem *base, int size) | ||
127 | { | ||
128 | struct clk *clk; | ||
129 | int i; | ||
130 | |||
131 | for (i = 0; i < size; i++) { | ||
132 | clk = clk_register_mux(NULL, clks[i].name, | ||
133 | clks[i].parent_name, | ||
134 | clks[i].num_parents, | ||
135 | clks[i].flags, | ||
136 | base + clks[i].offset, | ||
137 | clks[i].shift, | ||
138 | clks[i].width, | ||
139 | clks[i].mux_flags, | ||
140 | clks[i].lock); | ||
141 | |||
142 | if (IS_ERR(clk)) { | ||
143 | pr_err("%s: failed to register clock %s\n", | ||
144 | __func__, clks[i].name); | ||
145 | continue; | ||
146 | } | ||
147 | if (clks[i].id) | ||
148 | unit->clk_table[clks[i].id] = clk; | ||
149 | } | ||
150 | } | ||
151 | |||
152 | void mmp_register_div_clks(struct mmp_clk_unit *unit, | ||
153 | struct mmp_param_div_clk *clks, | ||
154 | void __iomem *base, int size) | ||
155 | { | ||
156 | struct clk *clk; | ||
157 | int i; | ||
158 | |||
159 | for (i = 0; i < size; i++) { | ||
160 | clk = clk_register_divider(NULL, clks[i].name, | ||
161 | clks[i].parent_name, | ||
162 | clks[i].flags, | ||
163 | base + clks[i].offset, | ||
164 | clks[i].shift, | ||
165 | clks[i].width, | ||
166 | clks[i].div_flags, | ||
167 | clks[i].lock); | ||
168 | |||
169 | if (IS_ERR(clk)) { | ||
170 | pr_err("%s: failed to register clock %s\n", | ||
171 | __func__, clks[i].name); | ||
172 | continue; | ||
173 | } | ||
174 | if (clks[i].id) | ||
175 | unit->clk_table[clks[i].id] = clk; | ||
176 | } | ||
177 | } | ||
178 | |||
179 | void mmp_clk_add(struct mmp_clk_unit *unit, unsigned int id, | ||
180 | struct clk *clk) | ||
181 | { | ||
182 | if (IS_ERR_OR_NULL(clk)) { | ||
183 | pr_err("CLK %d has invalid pointer %p\n", id, clk); | ||
184 | return; | ||
185 | } | ||
186 | if (id > unit->nr_clks) { | ||
187 | pr_err("CLK %d is invalid\n", id); | ||
188 | return; | ||
189 | } | ||
190 | |||
191 | unit->clk_table[id] = clk; | ||
192 | } | ||
diff --git a/drivers/clk/mmp/clk.h b/drivers/clk/mmp/clk.h index ab86dd4a416a..adf9b711b037 100644 --- a/drivers/clk/mmp/clk.h +++ b/drivers/clk/mmp/clk.h | |||
@@ -7,19 +7,123 @@ | |||
7 | #define APBC_NO_BUS_CTRL BIT(0) | 7 | #define APBC_NO_BUS_CTRL BIT(0) |
8 | #define APBC_POWER_CTRL BIT(1) | 8 | #define APBC_POWER_CTRL BIT(1) |
9 | 9 | ||
10 | struct clk_factor_masks { | 10 | |
11 | unsigned int factor; | 11 | /* Clock type "factor" */ |
12 | unsigned int num_mask; | 12 | struct mmp_clk_factor_masks { |
13 | unsigned int den_mask; | 13 | unsigned int factor; |
14 | unsigned int num_shift; | 14 | unsigned int num_mask; |
15 | unsigned int den_shift; | 15 | unsigned int den_mask; |
16 | unsigned int num_shift; | ||
17 | unsigned int den_shift; | ||
16 | }; | 18 | }; |
17 | 19 | ||
18 | struct clk_factor_tbl { | 20 | struct mmp_clk_factor_tbl { |
19 | unsigned int num; | 21 | unsigned int num; |
20 | unsigned int den; | 22 | unsigned int den; |
21 | }; | 23 | }; |
22 | 24 | ||
25 | struct mmp_clk_factor { | ||
26 | struct clk_hw hw; | ||
27 | void __iomem *base; | ||
28 | struct mmp_clk_factor_masks *masks; | ||
29 | struct mmp_clk_factor_tbl *ftbl; | ||
30 | unsigned int ftbl_cnt; | ||
31 | spinlock_t *lock; | ||
32 | }; | ||
33 | |||
34 | extern struct clk *mmp_clk_register_factor(const char *name, | ||
35 | const char *parent_name, unsigned long flags, | ||
36 | void __iomem *base, struct mmp_clk_factor_masks *masks, | ||
37 | struct mmp_clk_factor_tbl *ftbl, unsigned int ftbl_cnt, | ||
38 | spinlock_t *lock); | ||
39 | |||
40 | /* Clock type "mix" */ | ||
41 | #define MMP_CLK_BITS_MASK(width, shift) \ | ||
42 | (((1 << (width)) - 1) << (shift)) | ||
43 | #define MMP_CLK_BITS_GET_VAL(data, width, shift) \ | ||
44 | ((data & MMP_CLK_BITS_MASK(width, shift)) >> (shift)) | ||
45 | #define MMP_CLK_BITS_SET_VAL(val, width, shift) \ | ||
46 | (((val) << (shift)) & MMP_CLK_BITS_MASK(width, shift)) | ||
47 | |||
48 | enum { | ||
49 | MMP_CLK_MIX_TYPE_V1, | ||
50 | MMP_CLK_MIX_TYPE_V2, | ||
51 | MMP_CLK_MIX_TYPE_V3, | ||
52 | }; | ||
53 | |||
54 | /* The register layout */ | ||
55 | struct mmp_clk_mix_reg_info { | ||
56 | void __iomem *reg_clk_ctrl; | ||
57 | void __iomem *reg_clk_sel; | ||
58 | u8 width_div; | ||
59 | u8 shift_div; | ||
60 | u8 width_mux; | ||
61 | u8 shift_mux; | ||
62 | u8 bit_fc; | ||
63 | }; | ||
64 | |||
65 | /* The suggested clock table from user. */ | ||
66 | struct mmp_clk_mix_clk_table { | ||
67 | unsigned long rate; | ||
68 | u8 parent_index; | ||
69 | unsigned int divisor; | ||
70 | unsigned int valid; | ||
71 | }; | ||
72 | |||
73 | struct mmp_clk_mix_config { | ||
74 | struct mmp_clk_mix_reg_info reg_info; | ||
75 | struct mmp_clk_mix_clk_table *table; | ||
76 | unsigned int table_size; | ||
77 | u32 *mux_table; | ||
78 | struct clk_div_table *div_table; | ||
79 | u8 div_flags; | ||
80 | u8 mux_flags; | ||
81 | }; | ||
82 | |||
83 | struct mmp_clk_mix { | ||
84 | struct clk_hw hw; | ||
85 | struct mmp_clk_mix_reg_info reg_info; | ||
86 | struct mmp_clk_mix_clk_table *table; | ||
87 | u32 *mux_table; | ||
88 | struct clk_div_table *div_table; | ||
89 | unsigned int table_size; | ||
90 | u8 div_flags; | ||
91 | u8 mux_flags; | ||
92 | unsigned int type; | ||
93 | spinlock_t *lock; | ||
94 | }; | ||
95 | |||
96 | extern const struct clk_ops mmp_clk_mix_ops; | ||
97 | extern struct clk *mmp_clk_register_mix(struct device *dev, | ||
98 | const char *name, | ||
99 | const char **parent_names, | ||
100 | u8 num_parents, | ||
101 | unsigned long flags, | ||
102 | struct mmp_clk_mix_config *config, | ||
103 | spinlock_t *lock); | ||
104 | |||
105 | |||
106 | /* Clock type "gate". MMP private gate */ | ||
107 | #define MMP_CLK_GATE_NEED_DELAY BIT(0) | ||
108 | |||
109 | struct mmp_clk_gate { | ||
110 | struct clk_hw hw; | ||
111 | void __iomem *reg; | ||
112 | u32 mask; | ||
113 | u32 val_enable; | ||
114 | u32 val_disable; | ||
115 | unsigned int flags; | ||
116 | spinlock_t *lock; | ||
117 | }; | ||
118 | |||
119 | extern const struct clk_ops mmp_clk_gate_ops; | ||
120 | extern struct clk *mmp_clk_register_gate(struct device *dev, const char *name, | ||
121 | const char *parent_name, unsigned long flags, | ||
122 | void __iomem *reg, u32 mask, u32 val_enable, | ||
123 | u32 val_disable, unsigned int gate_flags, | ||
124 | spinlock_t *lock); | ||
125 | |||
126 | |||
23 | extern struct clk *mmp_clk_register_pll2(const char *name, | 127 | extern struct clk *mmp_clk_register_pll2(const char *name, |
24 | const char *parent_name, unsigned long flags); | 128 | const char *parent_name, unsigned long flags); |
25 | extern struct clk *mmp_clk_register_apbc(const char *name, | 129 | extern struct clk *mmp_clk_register_apbc(const char *name, |
@@ -28,8 +132,108 @@ extern struct clk *mmp_clk_register_apbc(const char *name, | |||
28 | extern struct clk *mmp_clk_register_apmu(const char *name, | 132 | extern struct clk *mmp_clk_register_apmu(const char *name, |
29 | const char *parent_name, void __iomem *base, u32 enable_mask, | 133 | const char *parent_name, void __iomem *base, u32 enable_mask, |
30 | spinlock_t *lock); | 134 | spinlock_t *lock); |
31 | extern struct clk *mmp_clk_register_factor(const char *name, | 135 | |
32 | const char *parent_name, unsigned long flags, | 136 | struct mmp_clk_unit { |
33 | void __iomem *base, struct clk_factor_masks *masks, | 137 | unsigned int nr_clks; |
34 | struct clk_factor_tbl *ftbl, unsigned int ftbl_cnt); | 138 | struct clk **clk_table; |
139 | struct clk_onecell_data clk_data; | ||
140 | }; | ||
141 | |||
142 | struct mmp_param_fixed_rate_clk { | ||
143 | unsigned int id; | ||
144 | char *name; | ||
145 | const char *parent_name; | ||
146 | unsigned long flags; | ||
147 | unsigned long fixed_rate; | ||
148 | }; | ||
149 | void mmp_register_fixed_rate_clks(struct mmp_clk_unit *unit, | ||
150 | struct mmp_param_fixed_rate_clk *clks, | ||
151 | int size); | ||
152 | |||
153 | struct mmp_param_fixed_factor_clk { | ||
154 | unsigned int id; | ||
155 | char *name; | ||
156 | const char *parent_name; | ||
157 | unsigned long mult; | ||
158 | unsigned long div; | ||
159 | unsigned long flags; | ||
160 | }; | ||
161 | void mmp_register_fixed_factor_clks(struct mmp_clk_unit *unit, | ||
162 | struct mmp_param_fixed_factor_clk *clks, | ||
163 | int size); | ||
164 | |||
165 | struct mmp_param_general_gate_clk { | ||
166 | unsigned int id; | ||
167 | const char *name; | ||
168 | const char *parent_name; | ||
169 | unsigned long flags; | ||
170 | unsigned long offset; | ||
171 | u8 bit_idx; | ||
172 | u8 gate_flags; | ||
173 | spinlock_t *lock; | ||
174 | }; | ||
175 | void mmp_register_general_gate_clks(struct mmp_clk_unit *unit, | ||
176 | struct mmp_param_general_gate_clk *clks, | ||
177 | void __iomem *base, int size); | ||
178 | |||
179 | struct mmp_param_gate_clk { | ||
180 | unsigned int id; | ||
181 | char *name; | ||
182 | const char *parent_name; | ||
183 | unsigned long flags; | ||
184 | unsigned long offset; | ||
185 | u32 mask; | ||
186 | u32 val_enable; | ||
187 | u32 val_disable; | ||
188 | unsigned int gate_flags; | ||
189 | spinlock_t *lock; | ||
190 | }; | ||
191 | void mmp_register_gate_clks(struct mmp_clk_unit *unit, | ||
192 | struct mmp_param_gate_clk *clks, | ||
193 | void __iomem *base, int size); | ||
194 | |||
195 | struct mmp_param_mux_clk { | ||
196 | unsigned int id; | ||
197 | char *name; | ||
198 | const char **parent_name; | ||
199 | u8 num_parents; | ||
200 | unsigned long flags; | ||
201 | unsigned long offset; | ||
202 | u8 shift; | ||
203 | u8 width; | ||
204 | u8 mux_flags; | ||
205 | spinlock_t *lock; | ||
206 | }; | ||
207 | void mmp_register_mux_clks(struct mmp_clk_unit *unit, | ||
208 | struct mmp_param_mux_clk *clks, | ||
209 | void __iomem *base, int size); | ||
210 | |||
211 | struct mmp_param_div_clk { | ||
212 | unsigned int id; | ||
213 | char *name; | ||
214 | const char *parent_name; | ||
215 | unsigned long flags; | ||
216 | unsigned long offset; | ||
217 | u8 shift; | ||
218 | u8 width; | ||
219 | u8 div_flags; | ||
220 | spinlock_t *lock; | ||
221 | }; | ||
222 | void mmp_register_div_clks(struct mmp_clk_unit *unit, | ||
223 | struct mmp_param_div_clk *clks, | ||
224 | void __iomem *base, int size); | ||
225 | |||
226 | #define DEFINE_MIX_REG_INFO(w_d, s_d, w_m, s_m, fc) \ | ||
227 | { \ | ||
228 | .width_div = (w_d), \ | ||
229 | .shift_div = (s_d), \ | ||
230 | .width_mux = (w_m), \ | ||
231 | .shift_mux = (s_m), \ | ||
232 | .bit_fc = (fc), \ | ||
233 | } | ||
234 | |||
235 | void mmp_clk_init(struct device_node *np, struct mmp_clk_unit *unit, | ||
236 | int nr_clks); | ||
237 | void mmp_clk_add(struct mmp_clk_unit *unit, unsigned int id, | ||
238 | struct clk *clk); | ||
35 | #endif | 239 | #endif |
diff --git a/drivers/clk/mmp/reset.c b/drivers/clk/mmp/reset.c new file mode 100644 index 000000000000..b54da1fe73f0 --- /dev/null +++ b/drivers/clk/mmp/reset.c | |||
@@ -0,0 +1,99 @@ | |||
1 | #include <linux/slab.h> | ||
2 | #include <linux/io.h> | ||
3 | #include <linux/of.h> | ||
4 | #include <linux/of_address.h> | ||
5 | #include <linux/reset-controller.h> | ||
6 | |||
7 | #include "reset.h" | ||
8 | |||
9 | #define rcdev_to_unit(rcdev) container_of(rcdev, struct mmp_clk_reset_unit, rcdev) | ||
10 | |||
11 | static int mmp_of_reset_xlate(struct reset_controller_dev *rcdev, | ||
12 | const struct of_phandle_args *reset_spec) | ||
13 | { | ||
14 | struct mmp_clk_reset_unit *unit = rcdev_to_unit(rcdev); | ||
15 | struct mmp_clk_reset_cell *cell; | ||
16 | int i; | ||
17 | |||
18 | if (WARN_ON(reset_spec->args_count != rcdev->of_reset_n_cells)) | ||
19 | return -EINVAL; | ||
20 | |||
21 | for (i = 0; i < rcdev->nr_resets; i++) { | ||
22 | cell = &unit->cells[i]; | ||
23 | if (cell->clk_id == reset_spec->args[0]) | ||
24 | break; | ||
25 | } | ||
26 | |||
27 | if (i == rcdev->nr_resets) | ||
28 | return -EINVAL; | ||
29 | |||
30 | return i; | ||
31 | } | ||
32 | |||
33 | static int mmp_clk_reset_assert(struct reset_controller_dev *rcdev, | ||
34 | unsigned long id) | ||
35 | { | ||
36 | struct mmp_clk_reset_unit *unit = rcdev_to_unit(rcdev); | ||
37 | struct mmp_clk_reset_cell *cell; | ||
38 | unsigned long flags = 0; | ||
39 | u32 val; | ||
40 | |||
41 | cell = &unit->cells[id]; | ||
42 | if (cell->lock) | ||
43 | spin_lock_irqsave(cell->lock, flags); | ||
44 | |||
45 | val = readl(cell->reg); | ||
46 | val |= cell->bits; | ||
47 | writel(val, cell->reg); | ||
48 | |||
49 | if (cell->lock) | ||
50 | spin_unlock_irqrestore(cell->lock, flags); | ||
51 | |||
52 | return 0; | ||
53 | } | ||
54 | |||
55 | static int mmp_clk_reset_deassert(struct reset_controller_dev *rcdev, | ||
56 | unsigned long id) | ||
57 | { | ||
58 | struct mmp_clk_reset_unit *unit = rcdev_to_unit(rcdev); | ||
59 | struct mmp_clk_reset_cell *cell; | ||
60 | unsigned long flags = 0; | ||
61 | u32 val; | ||
62 | |||
63 | cell = &unit->cells[id]; | ||
64 | if (cell->lock) | ||
65 | spin_lock_irqsave(cell->lock, flags); | ||
66 | |||
67 | val = readl(cell->reg); | ||
68 | val &= ~cell->bits; | ||
69 | writel(val, cell->reg); | ||
70 | |||
71 | if (cell->lock) | ||
72 | spin_unlock_irqrestore(cell->lock, flags); | ||
73 | |||
74 | return 0; | ||
75 | } | ||
76 | |||
77 | static struct reset_control_ops mmp_clk_reset_ops = { | ||
78 | .assert = mmp_clk_reset_assert, | ||
79 | .deassert = mmp_clk_reset_deassert, | ||
80 | }; | ||
81 | |||
82 | void mmp_clk_reset_register(struct device_node *np, | ||
83 | struct mmp_clk_reset_cell *cells, int nr_resets) | ||
84 | { | ||
85 | struct mmp_clk_reset_unit *unit; | ||
86 | |||
87 | unit = kzalloc(sizeof(*unit), GFP_KERNEL); | ||
88 | if (!unit) | ||
89 | return; | ||
90 | |||
91 | unit->cells = cells; | ||
92 | unit->rcdev.of_reset_n_cells = 1; | ||
93 | unit->rcdev.nr_resets = nr_resets; | ||
94 | unit->rcdev.ops = &mmp_clk_reset_ops; | ||
95 | unit->rcdev.of_node = np; | ||
96 | unit->rcdev.of_xlate = mmp_of_reset_xlate; | ||
97 | |||
98 | reset_controller_register(&unit->rcdev); | ||
99 | } | ||
diff --git a/drivers/clk/mmp/reset.h b/drivers/clk/mmp/reset.h new file mode 100644 index 000000000000..be8b1a7000f7 --- /dev/null +++ b/drivers/clk/mmp/reset.h | |||
@@ -0,0 +1,31 @@ | |||
1 | #ifndef __MACH_MMP_CLK_RESET_H | ||
2 | #define __MACH_MMP_CLK_RESET_H | ||
3 | |||
4 | #include <linux/reset-controller.h> | ||
5 | |||
6 | #define MMP_RESET_INVERT 1 | ||
7 | |||
8 | struct mmp_clk_reset_cell { | ||
9 | unsigned int clk_id; | ||
10 | void __iomem *reg; | ||
11 | u32 bits; | ||
12 | unsigned int flags; | ||
13 | spinlock_t *lock; | ||
14 | }; | ||
15 | |||
16 | struct mmp_clk_reset_unit { | ||
17 | struct reset_controller_dev rcdev; | ||
18 | struct mmp_clk_reset_cell *cells; | ||
19 | }; | ||
20 | |||
21 | #ifdef CONFIG_RESET_CONTROLLER | ||
22 | void mmp_clk_reset_register(struct device_node *np, | ||
23 | struct mmp_clk_reset_cell *cells, int nr_resets); | ||
24 | #else | ||
25 | static inline void mmp_clk_reset_register(struct device_node *np, | ||
26 | struct mmp_clk_reset_cell *cells, int nr_resets) | ||
27 | { | ||
28 | } | ||
29 | #endif | ||
30 | |||
31 | #endif | ||
diff --git a/drivers/clk/pxa/Makefile b/drivers/clk/pxa/Makefile index 4ff2abcd500b..38e915344605 100644 --- a/drivers/clk/pxa/Makefile +++ b/drivers/clk/pxa/Makefile | |||
@@ -1,2 +1,3 @@ | |||
1 | obj-y += clk-pxa.o | 1 | obj-y += clk-pxa.o |
2 | obj-$(CONFIG_PXA25x) += clk-pxa25x.o | ||
2 | obj-$(CONFIG_PXA27x) += clk-pxa27x.o | 3 | obj-$(CONFIG_PXA27x) += clk-pxa27x.o |
diff --git a/drivers/clk/pxa/clk-pxa.c b/drivers/clk/pxa/clk-pxa.c index ef3c05389c0a..4e834753ab09 100644 --- a/drivers/clk/pxa/clk-pxa.c +++ b/drivers/clk/pxa/clk-pxa.c | |||
@@ -26,12 +26,20 @@ static struct clk_onecell_data onecell_data = { | |||
26 | .clk_num = CLK_MAX, | 26 | .clk_num = CLK_MAX, |
27 | }; | 27 | }; |
28 | 28 | ||
29 | #define to_pxa_clk(_hw) container_of(_hw, struct pxa_clk_cken, hw) | 29 | struct pxa_clk { |
30 | struct clk_hw hw; | ||
31 | struct clk_fixed_factor lp; | ||
32 | struct clk_fixed_factor hp; | ||
33 | struct clk_gate gate; | ||
34 | bool (*is_in_low_power)(void); | ||
35 | }; | ||
36 | |||
37 | #define to_pxa_clk(_hw) container_of(_hw, struct pxa_clk, hw) | ||
30 | 38 | ||
31 | static unsigned long cken_recalc_rate(struct clk_hw *hw, | 39 | static unsigned long cken_recalc_rate(struct clk_hw *hw, |
32 | unsigned long parent_rate) | 40 | unsigned long parent_rate) |
33 | { | 41 | { |
34 | struct pxa_clk_cken *pclk = to_pxa_clk(hw); | 42 | struct pxa_clk *pclk = to_pxa_clk(hw); |
35 | struct clk_fixed_factor *fix; | 43 | struct clk_fixed_factor *fix; |
36 | 44 | ||
37 | if (!pclk->is_in_low_power || pclk->is_in_low_power()) | 45 | if (!pclk->is_in_low_power || pclk->is_in_low_power()) |
@@ -48,7 +56,7 @@ static struct clk_ops cken_rate_ops = { | |||
48 | 56 | ||
49 | static u8 cken_get_parent(struct clk_hw *hw) | 57 | static u8 cken_get_parent(struct clk_hw *hw) |
50 | { | 58 | { |
51 | struct pxa_clk_cken *pclk = to_pxa_clk(hw); | 59 | struct pxa_clk *pclk = to_pxa_clk(hw); |
52 | 60 | ||
53 | if (!pclk->is_in_low_power) | 61 | if (!pclk->is_in_low_power) |
54 | return 0; | 62 | return 0; |
@@ -69,29 +77,32 @@ void __init clkdev_pxa_register(int ckid, const char *con_id, | |||
69 | clk_register_clkdev(clk, con_id, dev_id); | 77 | clk_register_clkdev(clk, con_id, dev_id); |
70 | } | 78 | } |
71 | 79 | ||
72 | int __init clk_pxa_cken_init(struct pxa_clk_cken *clks, int nb_clks) | 80 | int __init clk_pxa_cken_init(const struct desc_clk_cken *clks, int nb_clks) |
73 | { | 81 | { |
74 | int i; | 82 | int i; |
75 | struct pxa_clk_cken *pclk; | 83 | struct pxa_clk *pxa_clk; |
76 | struct clk *clk; | 84 | struct clk *clk; |
77 | 85 | ||
78 | for (i = 0; i < nb_clks; i++) { | 86 | for (i = 0; i < nb_clks; i++) { |
79 | pclk = clks + i; | 87 | pxa_clk = kzalloc(sizeof(*pxa_clk), GFP_KERNEL); |
80 | pclk->gate.lock = &lock; | 88 | pxa_clk->is_in_low_power = clks[i].is_in_low_power; |
81 | clk = clk_register_composite(NULL, pclk->name, | 89 | pxa_clk->lp = clks[i].lp; |
82 | pclk->parent_names, 2, | 90 | pxa_clk->hp = clks[i].hp; |
83 | &pclk->hw, &cken_mux_ops, | 91 | pxa_clk->gate = clks[i].gate; |
84 | &pclk->hw, &cken_rate_ops, | 92 | pxa_clk->gate.lock = &lock; |
85 | &pclk->gate.hw, &clk_gate_ops, | 93 | clk = clk_register_composite(NULL, clks[i].name, |
86 | pclk->flags); | 94 | clks[i].parent_names, 2, |
87 | clkdev_pxa_register(pclk->ckid, pclk->con_id, pclk->dev_id, | 95 | &pxa_clk->hw, &cken_mux_ops, |
88 | clk); | 96 | &pxa_clk->hw, &cken_rate_ops, |
97 | &pxa_clk->gate.hw, &clk_gate_ops, | ||
98 | clks[i].flags); | ||
99 | clkdev_pxa_register(clks[i].ckid, clks[i].con_id, | ||
100 | clks[i].dev_id, clk); | ||
89 | } | 101 | } |
90 | return 0; | 102 | return 0; |
91 | } | 103 | } |
92 | 104 | ||
93 | static void __init pxa_dt_clocks_init(struct device_node *np) | 105 | void __init clk_pxa_dt_common_init(struct device_node *np) |
94 | { | 106 | { |
95 | of_clk_add_provider(np, of_clk_src_onecell_get, &onecell_data); | 107 | of_clk_add_provider(np, of_clk_src_onecell_get, &onecell_data); |
96 | } | 108 | } |
97 | CLK_OF_DECLARE(pxa_clks, "marvell,pxa-clocks", pxa_dt_clocks_init); | ||
diff --git a/drivers/clk/pxa/clk-pxa.h b/drivers/clk/pxa/clk-pxa.h index 5fe219d06b49..323965430111 100644 --- a/drivers/clk/pxa/clk-pxa.h +++ b/drivers/clk/pxa/clk-pxa.h | |||
@@ -25,7 +25,7 @@ | |||
25 | static struct clk_ops name ## _rate_ops = { \ | 25 | static struct clk_ops name ## _rate_ops = { \ |
26 | .recalc_rate = name ## _get_rate, \ | 26 | .recalc_rate = name ## _get_rate, \ |
27 | }; \ | 27 | }; \ |
28 | static struct clk *clk_register_ ## name(void) \ | 28 | static struct clk * __init clk_register_ ## name(void) \ |
29 | { \ | 29 | { \ |
30 | return clk_register_composite(NULL, clk_name, \ | 30 | return clk_register_composite(NULL, clk_name, \ |
31 | name ## _parents, \ | 31 | name ## _parents, \ |
@@ -40,7 +40,7 @@ | |||
40 | static struct clk_ops name ## _rate_ops = { \ | 40 | static struct clk_ops name ## _rate_ops = { \ |
41 | .recalc_rate = name ## _get_rate, \ | 41 | .recalc_rate = name ## _get_rate, \ |
42 | }; \ | 42 | }; \ |
43 | static struct clk *clk_register_ ## name(void) \ | 43 | static struct clk * __init clk_register_ ## name(void) \ |
44 | { \ | 44 | { \ |
45 | return clk_register_composite(NULL, clk_name, \ | 45 | return clk_register_composite(NULL, clk_name, \ |
46 | name ## _parents, \ | 46 | name ## _parents, \ |
@@ -66,7 +66,7 @@ | |||
66 | * | Clock | --- | / div_hp | | 66 | * | Clock | --- | / div_hp | |
67 | * +------------+ +-----------+ | 67 | * +------------+ +-----------+ |
68 | */ | 68 | */ |
69 | struct pxa_clk_cken { | 69 | struct desc_clk_cken { |
70 | struct clk_hw hw; | 70 | struct clk_hw hw; |
71 | int ckid; | 71 | int ckid; |
72 | const char *name; | 72 | const char *name; |
@@ -102,6 +102,7 @@ static int dummy_clk_set_parent(struct clk_hw *hw, u8 index) | |||
102 | 102 | ||
103 | extern void clkdev_pxa_register(int ckid, const char *con_id, | 103 | extern void clkdev_pxa_register(int ckid, const char *con_id, |
104 | const char *dev_id, struct clk *clk); | 104 | const char *dev_id, struct clk *clk); |
105 | extern int clk_pxa_cken_init(struct pxa_clk_cken *clks, int nb_clks); | 105 | extern int clk_pxa_cken_init(const struct desc_clk_cken *clks, int nb_clks); |
106 | void clk_pxa_dt_common_init(struct device_node *np); | ||
106 | 107 | ||
107 | #endif | 108 | #endif |
diff --git a/drivers/clk/pxa/clk-pxa25x.c b/drivers/clk/pxa/clk-pxa25x.c new file mode 100644 index 000000000000..6cd88d963a7f --- /dev/null +++ b/drivers/clk/pxa/clk-pxa25x.c | |||
@@ -0,0 +1,273 @@ | |||
1 | /* | ||
2 | * Marvell PXA25x family clocks | ||
3 | * | ||
4 | * Copyright (C) 2014 Robert Jarzmik | ||
5 | * | ||
6 | * Heavily inspired from former arch/arm/mach-pxa/pxa25x.c. | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; version 2 of the License. | ||
11 | * | ||
12 | * For non-devicetree platforms. Once pxa is fully converted to devicetree, this | ||
13 | * should go away. | ||
14 | */ | ||
15 | #include <linux/clk-provider.h> | ||
16 | #include <linux/clk.h> | ||
17 | #include <linux/clkdev.h> | ||
18 | #include <linux/io.h> | ||
19 | #include <linux/of.h> | ||
20 | #include <mach/pxa25x.h> | ||
21 | #include <mach/pxa2xx-regs.h> | ||
22 | |||
23 | #include <dt-bindings/clock/pxa-clock.h> | ||
24 | #include "clk-pxa.h" | ||
25 | |||
26 | #define KHz 1000 | ||
27 | #define MHz (1000 * 1000) | ||
28 | |||
29 | enum { | ||
30 | PXA_CORE_RUN = 0, | ||
31 | PXA_CORE_TURBO, | ||
32 | }; | ||
33 | |||
34 | /* | ||
35 | * Various clock factors driven by the CCCR register. | ||
36 | */ | ||
37 | |||
38 | /* Crystal Frequency to Memory Frequency Multiplier (L) */ | ||
39 | static unsigned char L_clk_mult[32] = { 0, 27, 32, 36, 40, 45, 0, }; | ||
40 | |||
41 | /* Memory Frequency to Run Mode Frequency Multiplier (M) */ | ||
42 | static unsigned char M_clk_mult[4] = { 0, 1, 2, 4 }; | ||
43 | |||
44 | /* Run Mode Frequency to Turbo Mode Frequency Multiplier (N) */ | ||
45 | /* Note: we store the value N * 2 here. */ | ||
46 | static unsigned char N2_clk_mult[8] = { 0, 0, 2, 3, 4, 0, 6, 0 }; | ||
47 | |||
48 | static const char * const get_freq_khz[] = { | ||
49 | "core", "run", "cpll", "memory" | ||
50 | }; | ||
51 | |||
52 | /* | ||
53 | * Get the clock frequency as reflected by CCCR and the turbo flag. | ||
54 | * We assume these values have been applied via a fcs. | ||
55 | * If info is not 0 we also display the current settings. | ||
56 | */ | ||
57 | unsigned int pxa25x_get_clk_frequency_khz(int info) | ||
58 | { | ||
59 | struct clk *clk; | ||
60 | unsigned long clks[5]; | ||
61 | int i; | ||
62 | |||
63 | for (i = 0; i < ARRAY_SIZE(get_freq_khz); i++) { | ||
64 | clk = clk_get(NULL, get_freq_khz[i]); | ||
65 | if (IS_ERR(clk)) { | ||
66 | clks[i] = 0; | ||
67 | } else { | ||
68 | clks[i] = clk_get_rate(clk); | ||
69 | clk_put(clk); | ||
70 | } | ||
71 | } | ||
72 | |||
73 | if (info) { | ||
74 | pr_info("Run Mode clock: %ld.%02ldMHz\n", | ||
75 | clks[1] / 1000000, (clks[1] % 1000000) / 10000); | ||
76 | pr_info("Turbo Mode clock: %ld.%02ldMHz\n", | ||
77 | clks[2] / 1000000, (clks[2] % 1000000) / 10000); | ||
78 | pr_info("Memory clock: %ld.%02ldMHz\n", | ||
79 | clks[3] / 1000000, (clks[3] % 1000000) / 10000); | ||
80 | } | ||
81 | |||
82 | return (unsigned int)clks[0]; | ||
83 | } | ||
84 | |||
85 | static unsigned long clk_pxa25x_memory_get_rate(struct clk_hw *hw, | ||
86 | unsigned long parent_rate) | ||
87 | { | ||
88 | unsigned long cccr = CCCR; | ||
89 | unsigned int m = M_clk_mult[(cccr >> 5) & 0x03]; | ||
90 | |||
91 | return parent_rate / m; | ||
92 | } | ||
93 | PARENTS(clk_pxa25x_memory) = { "run" }; | ||
94 | RATE_RO_OPS(clk_pxa25x_memory, "memory"); | ||
95 | |||
96 | PARENTS(pxa25x_pbus95) = { "ppll_95_85mhz", "ppll_95_85mhz" }; | ||
97 | PARENTS(pxa25x_pbus147) = { "ppll_147_46mhz", "ppll_147_46mhz" }; | ||
98 | PARENTS(pxa25x_osc3) = { "osc_3_6864mhz", "osc_3_6864mhz" }; | ||
99 | |||
100 | #define PXA25X_CKEN(dev_id, con_id, parents, mult, div, \ | ||
101 | bit, is_lp, flags) \ | ||
102 | PXA_CKEN(dev_id, con_id, bit, parents, mult, div, mult, div, \ | ||
103 | is_lp, &CKEN, CKEN_ ## bit, flags) | ||
104 | #define PXA25X_PBUS95_CKEN(dev_id, con_id, bit, mult_hp, div_hp, delay) \ | ||
105 | PXA25X_CKEN(dev_id, con_id, pxa25x_pbus95_parents, mult_hp, \ | ||
106 | div_hp, bit, NULL, 0) | ||
107 | #define PXA25X_PBUS147_CKEN(dev_id, con_id, bit, mult_hp, div_hp, delay)\ | ||
108 | PXA25X_CKEN(dev_id, con_id, pxa25x_pbus147_parents, mult_hp, \ | ||
109 | div_hp, bit, NULL, 0) | ||
110 | #define PXA25X_OSC3_CKEN(dev_id, con_id, bit, mult_hp, div_hp, delay) \ | ||
111 | PXA25X_CKEN(dev_id, con_id, pxa25x_osc3_parents, mult_hp, \ | ||
112 | div_hp, bit, NULL, 0) | ||
113 | |||
114 | #define PXA25X_CKEN_1RATE(dev_id, con_id, bit, parents, delay) \ | ||
115 | PXA_CKEN_1RATE(dev_id, con_id, bit, parents, \ | ||
116 | &CKEN, CKEN_ ## bit, 0) | ||
117 | #define PXA25X_CKEN_1RATE_AO(dev_id, con_id, bit, parents, delay) \ | ||
118 | PXA_CKEN_1RATE(dev_id, con_id, bit, parents, \ | ||
119 | &CKEN, CKEN_ ## bit, CLK_IGNORE_UNUSED) | ||
120 | |||
121 | static struct desc_clk_cken pxa25x_clocks[] __initdata = { | ||
122 | PXA25X_PBUS95_CKEN("pxa2xx-mci.0", NULL, MMC, 1, 5, 0), | ||
123 | PXA25X_PBUS95_CKEN("pxa2xx-i2c.0", NULL, I2C, 1, 3, 0), | ||
124 | PXA25X_PBUS95_CKEN("pxa2xx-ir", "FICPCLK", FICP, 1, 2, 0), | ||
125 | PXA25X_PBUS95_CKEN("pxa25x-udc", NULL, USB, 1, 2, 5), | ||
126 | PXA25X_PBUS147_CKEN("pxa2xx-uart.0", NULL, FFUART, 1, 10, 1), | ||
127 | PXA25X_PBUS147_CKEN("pxa2xx-uart.1", NULL, BTUART, 1, 10, 1), | ||
128 | PXA25X_PBUS147_CKEN("pxa2xx-uart.2", NULL, STUART, 1, 10, 1), | ||
129 | PXA25X_PBUS147_CKEN("pxa2xx-uart.3", NULL, HWUART, 1, 10, 1), | ||
130 | PXA25X_PBUS147_CKEN("pxa2xx-i2s", NULL, I2S, 1, 10, 0), | ||
131 | PXA25X_PBUS147_CKEN(NULL, "AC97CLK", AC97, 1, 12, 0), | ||
132 | PXA25X_OSC3_CKEN("pxa25x-ssp.0", NULL, SSP, 1, 1, 0), | ||
133 | PXA25X_OSC3_CKEN("pxa25x-nssp.1", NULL, NSSP, 1, 1, 0), | ||
134 | PXA25X_OSC3_CKEN("pxa25x-nssp.2", NULL, ASSP, 1, 1, 0), | ||
135 | PXA25X_OSC3_CKEN("pxa25x-pwm.0", NULL, PWM0, 1, 1, 0), | ||
136 | PXA25X_OSC3_CKEN("pxa25x-pwm.1", NULL, PWM1, 1, 1, 0), | ||
137 | |||
138 | PXA25X_CKEN_1RATE("pxa2xx-fb", NULL, LCD, clk_pxa25x_memory_parents, 0), | ||
139 | PXA25X_CKEN_1RATE_AO("pxa2xx-pcmcia", NULL, MEMC, | ||
140 | clk_pxa25x_memory_parents, 0), | ||
141 | }; | ||
142 | |||
143 | static u8 clk_pxa25x_core_get_parent(struct clk_hw *hw) | ||
144 | { | ||
145 | unsigned long clkcfg; | ||
146 | unsigned int t; | ||
147 | |||
148 | asm("mrc\tp14, 0, %0, c6, c0, 0" : "=r" (clkcfg)); | ||
149 | t = clkcfg & (1 << 0); | ||
150 | if (t) | ||
151 | return PXA_CORE_TURBO; | ||
152 | return PXA_CORE_RUN; | ||
153 | } | ||
154 | |||
155 | static unsigned long clk_pxa25x_core_get_rate(struct clk_hw *hw, | ||
156 | unsigned long parent_rate) | ||
157 | { | ||
158 | return parent_rate; | ||
159 | } | ||
160 | PARENTS(clk_pxa25x_core) = { "run", "cpll" }; | ||
161 | MUX_RO_RATE_RO_OPS(clk_pxa25x_core, "core"); | ||
162 | |||
163 | static unsigned long clk_pxa25x_run_get_rate(struct clk_hw *hw, | ||
164 | unsigned long parent_rate) | ||
165 | { | ||
166 | unsigned long cccr = CCCR; | ||
167 | unsigned int n2 = N2_clk_mult[(cccr >> 7) & 0x07]; | ||
168 | |||
169 | return (parent_rate / n2) * 2; | ||
170 | } | ||
171 | PARENTS(clk_pxa25x_run) = { "cpll" }; | ||
172 | RATE_RO_OPS(clk_pxa25x_run, "run"); | ||
173 | |||
174 | static unsigned long clk_pxa25x_cpll_get_rate(struct clk_hw *hw, | ||
175 | unsigned long parent_rate) | ||
176 | { | ||
177 | unsigned long clkcfg, cccr = CCCR; | ||
178 | unsigned int l, m, n2, t; | ||
179 | |||
180 | asm("mrc\tp14, 0, %0, c6, c0, 0" : "=r" (clkcfg)); | ||
181 | t = clkcfg & (1 << 0); | ||
182 | l = L_clk_mult[(cccr >> 0) & 0x1f]; | ||
183 | m = M_clk_mult[(cccr >> 5) & 0x03]; | ||
184 | n2 = N2_clk_mult[(cccr >> 7) & 0x07]; | ||
185 | |||
186 | if (t) | ||
187 | return m * l * n2 * parent_rate / 2; | ||
188 | return m * l * parent_rate; | ||
189 | } | ||
190 | PARENTS(clk_pxa25x_cpll) = { "osc_3_6864mhz" }; | ||
191 | RATE_RO_OPS(clk_pxa25x_cpll, "cpll"); | ||
192 | |||
193 | static void __init pxa25x_register_core(void) | ||
194 | { | ||
195 | clk_register_clk_pxa25x_cpll(); | ||
196 | clk_register_clk_pxa25x_run(); | ||
197 | clkdev_pxa_register(CLK_CORE, "core", NULL, | ||
198 | clk_register_clk_pxa25x_core()); | ||
199 | } | ||
200 | |||
201 | static void __init pxa25x_register_plls(void) | ||
202 | { | ||
203 | clk_register_fixed_rate(NULL, "osc_3_6864mhz", NULL, | ||
204 | CLK_GET_RATE_NOCACHE | CLK_IS_ROOT, | ||
205 | 3686400); | ||
206 | clk_register_fixed_rate(NULL, "osc_32_768khz", NULL, | ||
207 | CLK_GET_RATE_NOCACHE | CLK_IS_ROOT, | ||
208 | 32768); | ||
209 | clk_register_fixed_rate(NULL, "clk_dummy", NULL, CLK_IS_ROOT, 0); | ||
210 | clk_register_fixed_factor(NULL, "ppll_95_85mhz", "osc_3_6864mhz", | ||
211 | 0, 26, 1); | ||
212 | clk_register_fixed_factor(NULL, "ppll_147_46mhz", "osc_3_6864mhz", | ||
213 | 0, 40, 1); | ||
214 | } | ||
215 | |||
216 | static void __init pxa25x_base_clocks_init(void) | ||
217 | { | ||
218 | pxa25x_register_plls(); | ||
219 | pxa25x_register_core(); | ||
220 | clk_register_clk_pxa25x_memory(); | ||
221 | } | ||
222 | |||
223 | #define DUMMY_CLK(_con_id, _dev_id, _parent) \ | ||
224 | { .con_id = _con_id, .dev_id = _dev_id, .parent = _parent } | ||
225 | struct dummy_clk { | ||
226 | const char *con_id; | ||
227 | const char *dev_id; | ||
228 | const char *parent; | ||
229 | }; | ||
230 | static struct dummy_clk dummy_clks[] __initdata = { | ||
231 | DUMMY_CLK(NULL, "pxa25x-gpio", "osc_32_768khz"), | ||
232 | DUMMY_CLK(NULL, "pxa26x-gpio", "osc_32_768khz"), | ||
233 | DUMMY_CLK("GPIO11_CLK", NULL, "osc_3_6864mhz"), | ||
234 | DUMMY_CLK("GPIO12_CLK", NULL, "osc_32_768khz"), | ||
235 | DUMMY_CLK(NULL, "sa1100-rtc", "osc_32_768khz"), | ||
236 | DUMMY_CLK("OSTIMER0", NULL, "osc_32_768khz"), | ||
237 | DUMMY_CLK("UARTCLK", "pxa2xx-ir", "STUART"), | ||
238 | }; | ||
239 | |||
240 | static void __init pxa25x_dummy_clocks_init(void) | ||
241 | { | ||
242 | struct clk *clk; | ||
243 | struct dummy_clk *d; | ||
244 | const char *name; | ||
245 | int i; | ||
246 | |||
247 | /* | ||
248 | * All pinctrl logic has been wiped out of the clock driver, especially | ||
249 | * for gpio11 and gpio12 outputs. Machine code should ensure proper pin | ||
250 | * control (ie. pxa2xx_mfp_config() invocation). | ||
251 | */ | ||
252 | for (i = 0; i < ARRAY_SIZE(dummy_clks); i++) { | ||
253 | d = &dummy_clks[i]; | ||
254 | name = d->dev_id ? d->dev_id : d->con_id; | ||
255 | clk = clk_register_fixed_factor(NULL, name, d->parent, 0, 1, 1); | ||
256 | clk_register_clkdev(clk, d->con_id, d->dev_id); | ||
257 | } | ||
258 | } | ||
259 | |||
260 | int __init pxa25x_clocks_init(void) | ||
261 | { | ||
262 | pxa25x_base_clocks_init(); | ||
263 | pxa25x_dummy_clocks_init(); | ||
264 | return clk_pxa_cken_init(pxa25x_clocks, ARRAY_SIZE(pxa25x_clocks)); | ||
265 | } | ||
266 | |||
267 | static void __init pxa25x_dt_clocks_init(struct device_node *np) | ||
268 | { | ||
269 | pxa25x_clocks_init(); | ||
270 | clk_pxa_dt_common_init(np); | ||
271 | } | ||
272 | CLK_OF_DECLARE(pxa25x_clks, "marvell,pxa250-core-clocks", | ||
273 | pxa25x_dt_clocks_init); | ||
diff --git a/drivers/clk/pxa/clk-pxa27x.c b/drivers/clk/pxa/clk-pxa27x.c index 88b9fe13fa44..5f9b54b024b9 100644 --- a/drivers/clk/pxa/clk-pxa27x.c +++ b/drivers/clk/pxa/clk-pxa27x.c | |||
@@ -111,7 +111,7 @@ PARENTS(pxa27x_membus) = { "lcd_base", "lcd_base" }; | |||
111 | PXA_CKEN_1RATE(dev_id, con_id, bit, parents, \ | 111 | PXA_CKEN_1RATE(dev_id, con_id, bit, parents, \ |
112 | &CKEN, CKEN_ ## bit, CLK_IGNORE_UNUSED) | 112 | &CKEN, CKEN_ ## bit, CLK_IGNORE_UNUSED) |
113 | 113 | ||
114 | static struct pxa_clk_cken pxa27x_clocks[] = { | 114 | static struct desc_clk_cken pxa27x_clocks[] __initdata = { |
115 | PXA27X_PBUS_CKEN("pxa2xx-uart.0", NULL, FFUART, 2, 42, 1), | 115 | PXA27X_PBUS_CKEN("pxa2xx-uart.0", NULL, FFUART, 2, 42, 1), |
116 | PXA27X_PBUS_CKEN("pxa2xx-uart.1", NULL, BTUART, 2, 42, 1), | 116 | PXA27X_PBUS_CKEN("pxa2xx-uart.1", NULL, BTUART, 2, 42, 1), |
117 | PXA27X_PBUS_CKEN("pxa2xx-uart.2", NULL, STUART, 2, 42, 1), | 117 | PXA27X_PBUS_CKEN("pxa2xx-uart.2", NULL, STUART, 2, 42, 1), |
@@ -368,3 +368,10 @@ static int __init pxa27x_clocks_init(void) | |||
368 | return clk_pxa_cken_init(pxa27x_clocks, ARRAY_SIZE(pxa27x_clocks)); | 368 | return clk_pxa_cken_init(pxa27x_clocks, ARRAY_SIZE(pxa27x_clocks)); |
369 | } | 369 | } |
370 | postcore_initcall(pxa27x_clocks_init); | 370 | postcore_initcall(pxa27x_clocks_init); |
371 | |||
372 | static void __init pxa27x_dt_clocks_init(struct device_node *np) | ||
373 | { | ||
374 | pxa27x_clocks_init(); | ||
375 | clk_pxa_dt_common_init(np); | ||
376 | } | ||
377 | CLK_OF_DECLARE(pxa_clks, "marvell,pxa270-clocks", pxa27x_dt_clocks_init); | ||
diff --git a/drivers/clk/qcom/clk-pll.c b/drivers/clk/qcom/clk-pll.c index b823bc3b6250..60873a7f45d9 100644 --- a/drivers/clk/qcom/clk-pll.c +++ b/drivers/clk/qcom/clk-pll.c | |||
@@ -141,7 +141,7 @@ struct pll_freq_tbl *find_freq(const struct pll_freq_tbl *f, unsigned long rate) | |||
141 | 141 | ||
142 | static long | 142 | static long |
143 | clk_pll_determine_rate(struct clk_hw *hw, unsigned long rate, | 143 | clk_pll_determine_rate(struct clk_hw *hw, unsigned long rate, |
144 | unsigned long *p_rate, struct clk **p) | 144 | unsigned long *p_rate, struct clk_hw **p) |
145 | { | 145 | { |
146 | struct clk_pll *pll = to_clk_pll(hw); | 146 | struct clk_pll *pll = to_clk_pll(hw); |
147 | const struct pll_freq_tbl *f; | 147 | const struct pll_freq_tbl *f; |
diff --git a/drivers/clk/qcom/clk-rcg.c b/drivers/clk/qcom/clk-rcg.c index b6e6959e89aa..0b93972c8807 100644 --- a/drivers/clk/qcom/clk-rcg.c +++ b/drivers/clk/qcom/clk-rcg.c | |||
@@ -368,16 +368,17 @@ clk_dyn_rcg_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) | |||
368 | 368 | ||
369 | static long _freq_tbl_determine_rate(struct clk_hw *hw, | 369 | static long _freq_tbl_determine_rate(struct clk_hw *hw, |
370 | const struct freq_tbl *f, unsigned long rate, | 370 | const struct freq_tbl *f, unsigned long rate, |
371 | unsigned long *p_rate, struct clk **p) | 371 | unsigned long *p_rate, struct clk_hw **p_hw) |
372 | { | 372 | { |
373 | unsigned long clk_flags; | 373 | unsigned long clk_flags; |
374 | struct clk *p; | ||
374 | 375 | ||
375 | f = qcom_find_freq(f, rate); | 376 | f = qcom_find_freq(f, rate); |
376 | if (!f) | 377 | if (!f) |
377 | return -EINVAL; | 378 | return -EINVAL; |
378 | 379 | ||
379 | clk_flags = __clk_get_flags(hw->clk); | 380 | clk_flags = __clk_get_flags(hw->clk); |
380 | *p = clk_get_parent_by_index(hw->clk, f->src); | 381 | p = clk_get_parent_by_index(hw->clk, f->src); |
381 | if (clk_flags & CLK_SET_RATE_PARENT) { | 382 | if (clk_flags & CLK_SET_RATE_PARENT) { |
382 | rate = rate * f->pre_div; | 383 | rate = rate * f->pre_div; |
383 | if (f->n) { | 384 | if (f->n) { |
@@ -387,15 +388,16 @@ static long _freq_tbl_determine_rate(struct clk_hw *hw, | |||
387 | rate = tmp; | 388 | rate = tmp; |
388 | } | 389 | } |
389 | } else { | 390 | } else { |
390 | rate = __clk_get_rate(*p); | 391 | rate = __clk_get_rate(p); |
391 | } | 392 | } |
393 | *p_hw = __clk_get_hw(p); | ||
392 | *p_rate = rate; | 394 | *p_rate = rate; |
393 | 395 | ||
394 | return f->freq; | 396 | return f->freq; |
395 | } | 397 | } |
396 | 398 | ||
397 | static long clk_rcg_determine_rate(struct clk_hw *hw, unsigned long rate, | 399 | static long clk_rcg_determine_rate(struct clk_hw *hw, unsigned long rate, |
398 | unsigned long *p_rate, struct clk **p) | 400 | unsigned long *p_rate, struct clk_hw **p) |
399 | { | 401 | { |
400 | struct clk_rcg *rcg = to_clk_rcg(hw); | 402 | struct clk_rcg *rcg = to_clk_rcg(hw); |
401 | 403 | ||
@@ -403,7 +405,7 @@ static long clk_rcg_determine_rate(struct clk_hw *hw, unsigned long rate, | |||
403 | } | 405 | } |
404 | 406 | ||
405 | static long clk_dyn_rcg_determine_rate(struct clk_hw *hw, unsigned long rate, | 407 | static long clk_dyn_rcg_determine_rate(struct clk_hw *hw, unsigned long rate, |
406 | unsigned long *p_rate, struct clk **p) | 408 | unsigned long *p_rate, struct clk_hw **p) |
407 | { | 409 | { |
408 | struct clk_dyn_rcg *rcg = to_clk_dyn_rcg(hw); | 410 | struct clk_dyn_rcg *rcg = to_clk_dyn_rcg(hw); |
409 | 411 | ||
@@ -411,13 +413,15 @@ static long clk_dyn_rcg_determine_rate(struct clk_hw *hw, unsigned long rate, | |||
411 | } | 413 | } |
412 | 414 | ||
413 | static long clk_rcg_bypass_determine_rate(struct clk_hw *hw, unsigned long rate, | 415 | static long clk_rcg_bypass_determine_rate(struct clk_hw *hw, unsigned long rate, |
414 | unsigned long *p_rate, struct clk **p) | 416 | unsigned long *p_rate, struct clk_hw **p_hw) |
415 | { | 417 | { |
416 | struct clk_rcg *rcg = to_clk_rcg(hw); | 418 | struct clk_rcg *rcg = to_clk_rcg(hw); |
417 | const struct freq_tbl *f = rcg->freq_tbl; | 419 | const struct freq_tbl *f = rcg->freq_tbl; |
420 | struct clk *p; | ||
418 | 421 | ||
419 | *p = clk_get_parent_by_index(hw->clk, f->src); | 422 | p = clk_get_parent_by_index(hw->clk, f->src); |
420 | *p_rate = __clk_round_rate(*p, rate); | 423 | *p_hw = __clk_get_hw(p); |
424 | *p_rate = __clk_round_rate(p, rate); | ||
421 | 425 | ||
422 | return *p_rate; | 426 | return *p_rate; |
423 | } | 427 | } |
diff --git a/drivers/clk/qcom/clk-rcg2.c b/drivers/clk/qcom/clk-rcg2.c index cfa9eb4fe9ca..08b8b3729f53 100644 --- a/drivers/clk/qcom/clk-rcg2.c +++ b/drivers/clk/qcom/clk-rcg2.c | |||
@@ -175,16 +175,17 @@ clk_rcg2_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) | |||
175 | 175 | ||
176 | static long _freq_tbl_determine_rate(struct clk_hw *hw, | 176 | static long _freq_tbl_determine_rate(struct clk_hw *hw, |
177 | const struct freq_tbl *f, unsigned long rate, | 177 | const struct freq_tbl *f, unsigned long rate, |
178 | unsigned long *p_rate, struct clk **p) | 178 | unsigned long *p_rate, struct clk_hw **p_hw) |
179 | { | 179 | { |
180 | unsigned long clk_flags; | 180 | unsigned long clk_flags; |
181 | struct clk *p; | ||
181 | 182 | ||
182 | f = qcom_find_freq(f, rate); | 183 | f = qcom_find_freq(f, rate); |
183 | if (!f) | 184 | if (!f) |
184 | return -EINVAL; | 185 | return -EINVAL; |
185 | 186 | ||
186 | clk_flags = __clk_get_flags(hw->clk); | 187 | clk_flags = __clk_get_flags(hw->clk); |
187 | *p = clk_get_parent_by_index(hw->clk, f->src); | 188 | p = clk_get_parent_by_index(hw->clk, f->src); |
188 | if (clk_flags & CLK_SET_RATE_PARENT) { | 189 | if (clk_flags & CLK_SET_RATE_PARENT) { |
189 | if (f->pre_div) { | 190 | if (f->pre_div) { |
190 | rate /= 2; | 191 | rate /= 2; |
@@ -198,15 +199,16 @@ static long _freq_tbl_determine_rate(struct clk_hw *hw, | |||
198 | rate = tmp; | 199 | rate = tmp; |
199 | } | 200 | } |
200 | } else { | 201 | } else { |
201 | rate = __clk_get_rate(*p); | 202 | rate = __clk_get_rate(p); |
202 | } | 203 | } |
204 | *p_hw = __clk_get_hw(p); | ||
203 | *p_rate = rate; | 205 | *p_rate = rate; |
204 | 206 | ||
205 | return f->freq; | 207 | return f->freq; |
206 | } | 208 | } |
207 | 209 | ||
208 | static long clk_rcg2_determine_rate(struct clk_hw *hw, unsigned long rate, | 210 | static long clk_rcg2_determine_rate(struct clk_hw *hw, unsigned long rate, |
209 | unsigned long *p_rate, struct clk **p) | 211 | unsigned long *p_rate, struct clk_hw **p) |
210 | { | 212 | { |
211 | struct clk_rcg2 *rcg = to_clk_rcg2(hw); | 213 | struct clk_rcg2 *rcg = to_clk_rcg2(hw); |
212 | 214 | ||
@@ -359,7 +361,7 @@ static int clk_edp_pixel_set_rate_and_parent(struct clk_hw *hw, | |||
359 | } | 361 | } |
360 | 362 | ||
361 | static long clk_edp_pixel_determine_rate(struct clk_hw *hw, unsigned long rate, | 363 | static long clk_edp_pixel_determine_rate(struct clk_hw *hw, unsigned long rate, |
362 | unsigned long *p_rate, struct clk **p) | 364 | unsigned long *p_rate, struct clk_hw **p) |
363 | { | 365 | { |
364 | struct clk_rcg2 *rcg = to_clk_rcg2(hw); | 366 | struct clk_rcg2 *rcg = to_clk_rcg2(hw); |
365 | const struct freq_tbl *f = rcg->freq_tbl; | 367 | const struct freq_tbl *f = rcg->freq_tbl; |
@@ -371,7 +373,7 @@ static long clk_edp_pixel_determine_rate(struct clk_hw *hw, unsigned long rate, | |||
371 | u32 hid_div; | 373 | u32 hid_div; |
372 | 374 | ||
373 | /* Force the correct parent */ | 375 | /* Force the correct parent */ |
374 | *p = clk_get_parent_by_index(hw->clk, f->src); | 376 | *p = __clk_get_hw(clk_get_parent_by_index(hw->clk, f->src)); |
375 | 377 | ||
376 | if (src_rate == 810000000) | 378 | if (src_rate == 810000000) |
377 | frac = frac_table_810m; | 379 | frac = frac_table_810m; |
@@ -410,18 +412,20 @@ const struct clk_ops clk_edp_pixel_ops = { | |||
410 | EXPORT_SYMBOL_GPL(clk_edp_pixel_ops); | 412 | EXPORT_SYMBOL_GPL(clk_edp_pixel_ops); |
411 | 413 | ||
412 | static long clk_byte_determine_rate(struct clk_hw *hw, unsigned long rate, | 414 | static long clk_byte_determine_rate(struct clk_hw *hw, unsigned long rate, |
413 | unsigned long *p_rate, struct clk **p) | 415 | unsigned long *p_rate, struct clk_hw **p_hw) |
414 | { | 416 | { |
415 | struct clk_rcg2 *rcg = to_clk_rcg2(hw); | 417 | struct clk_rcg2 *rcg = to_clk_rcg2(hw); |
416 | const struct freq_tbl *f = rcg->freq_tbl; | 418 | const struct freq_tbl *f = rcg->freq_tbl; |
417 | unsigned long parent_rate, div; | 419 | unsigned long parent_rate, div; |
418 | u32 mask = BIT(rcg->hid_width) - 1; | 420 | u32 mask = BIT(rcg->hid_width) - 1; |
421 | struct clk *p; | ||
419 | 422 | ||
420 | if (rate == 0) | 423 | if (rate == 0) |
421 | return -EINVAL; | 424 | return -EINVAL; |
422 | 425 | ||
423 | *p = clk_get_parent_by_index(hw->clk, f->src); | 426 | p = clk_get_parent_by_index(hw->clk, f->src); |
424 | *p_rate = parent_rate = __clk_round_rate(*p, rate); | 427 | *p_hw = __clk_get_hw(p); |
428 | *p_rate = parent_rate = __clk_round_rate(p, rate); | ||
425 | 429 | ||
426 | div = DIV_ROUND_UP((2 * parent_rate), rate) - 1; | 430 | div = DIV_ROUND_UP((2 * parent_rate), rate) - 1; |
427 | div = min_t(u32, div, mask); | 431 | div = min_t(u32, div, mask); |
@@ -472,14 +476,16 @@ static const struct frac_entry frac_table_pixel[] = { | |||
472 | }; | 476 | }; |
473 | 477 | ||
474 | static long clk_pixel_determine_rate(struct clk_hw *hw, unsigned long rate, | 478 | static long clk_pixel_determine_rate(struct clk_hw *hw, unsigned long rate, |
475 | unsigned long *p_rate, struct clk **p) | 479 | unsigned long *p_rate, struct clk_hw **p) |
476 | { | 480 | { |
477 | struct clk_rcg2 *rcg = to_clk_rcg2(hw); | 481 | struct clk_rcg2 *rcg = to_clk_rcg2(hw); |
478 | unsigned long request, src_rate; | 482 | unsigned long request, src_rate; |
479 | int delta = 100000; | 483 | int delta = 100000; |
480 | const struct freq_tbl *f = rcg->freq_tbl; | 484 | const struct freq_tbl *f = rcg->freq_tbl; |
481 | const struct frac_entry *frac = frac_table_pixel; | 485 | const struct frac_entry *frac = frac_table_pixel; |
482 | struct clk *parent = *p = clk_get_parent_by_index(hw->clk, f->src); | 486 | struct clk *parent = clk_get_parent_by_index(hw->clk, f->src); |
487 | |||
488 | *p = __clk_get_hw(parent); | ||
483 | 489 | ||
484 | for (; frac->num; frac++) { | 490 | for (; frac->num; frac++) { |
485 | request = (rate * frac->den) / frac->num; | 491 | request = (rate * frac->den) / frac->num; |
diff --git a/drivers/clk/rockchip/Makefile b/drivers/clk/rockchip/Makefile index bd8514d63634..2714097f90db 100644 --- a/drivers/clk/rockchip/Makefile +++ b/drivers/clk/rockchip/Makefile | |||
@@ -6,6 +6,7 @@ obj-y += clk-rockchip.o | |||
6 | obj-y += clk.o | 6 | obj-y += clk.o |
7 | obj-y += clk-pll.o | 7 | obj-y += clk-pll.o |
8 | obj-y += clk-cpu.o | 8 | obj-y += clk-cpu.o |
9 | obj-y += clk-mmc-phase.o | ||
9 | obj-$(CONFIG_RESET_CONTROLLER) += softrst.o | 10 | obj-$(CONFIG_RESET_CONTROLLER) += softrst.o |
10 | 11 | ||
11 | obj-y += clk-rk3188.o | 12 | obj-y += clk-rk3188.o |
diff --git a/drivers/clk/rockchip/clk-mmc-phase.c b/drivers/clk/rockchip/clk-mmc-phase.c new file mode 100644 index 000000000000..c842e3b60f21 --- /dev/null +++ b/drivers/clk/rockchip/clk-mmc-phase.c | |||
@@ -0,0 +1,154 @@ | |||
1 | /* | ||
2 | * Copyright 2014 Google, Inc | ||
3 | * Author: Alexandru M Stan <amstan@chromium.org> | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU General Public License as published by | ||
7 | * the Free Software Foundation; either version 2 of the License, or | ||
8 | * (at your option) any later version. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | */ | ||
15 | |||
16 | #include <linux/slab.h> | ||
17 | #include <linux/clk-provider.h> | ||
18 | #include "clk.h" | ||
19 | |||
20 | struct rockchip_mmc_clock { | ||
21 | struct clk_hw hw; | ||
22 | void __iomem *reg; | ||
23 | int id; | ||
24 | int shift; | ||
25 | }; | ||
26 | |||
27 | #define to_mmc_clock(_hw) container_of(_hw, struct rockchip_mmc_clock, hw) | ||
28 | |||
29 | #define RK3288_MMC_CLKGEN_DIV 2 | ||
30 | |||
31 | static unsigned long rockchip_mmc_recalc(struct clk_hw *hw, | ||
32 | unsigned long parent_rate) | ||
33 | { | ||
34 | return parent_rate / RK3288_MMC_CLKGEN_DIV; | ||
35 | } | ||
36 | |||
37 | #define ROCKCHIP_MMC_DELAY_SEL BIT(10) | ||
38 | #define ROCKCHIP_MMC_DEGREE_MASK 0x3 | ||
39 | #define ROCKCHIP_MMC_DELAYNUM_OFFSET 2 | ||
40 | #define ROCKCHIP_MMC_DELAYNUM_MASK (0xff << ROCKCHIP_MMC_DELAYNUM_OFFSET) | ||
41 | |||
42 | #define PSECS_PER_SEC 1000000000000LL | ||
43 | |||
44 | /* | ||
45 | * Each fine delay is between 40ps-80ps. Assume each fine delay is 60ps to | ||
46 | * simplify calculations. So 45degs could be anywhere between 33deg and 66deg. | ||
47 | */ | ||
48 | #define ROCKCHIP_MMC_DELAY_ELEMENT_PSEC 60 | ||
49 | |||
50 | static int rockchip_mmc_get_phase(struct clk_hw *hw) | ||
51 | { | ||
52 | struct rockchip_mmc_clock *mmc_clock = to_mmc_clock(hw); | ||
53 | unsigned long rate = clk_get_rate(hw->clk); | ||
54 | u32 raw_value; | ||
55 | u16 degrees; | ||
56 | u32 delay_num = 0; | ||
57 | |||
58 | raw_value = readl(mmc_clock->reg) >> (mmc_clock->shift); | ||
59 | |||
60 | degrees = (raw_value & ROCKCHIP_MMC_DEGREE_MASK) * 90; | ||
61 | |||
62 | if (raw_value & ROCKCHIP_MMC_DELAY_SEL) { | ||
63 | /* degrees/delaynum * 10000 */ | ||
64 | unsigned long factor = (ROCKCHIP_MMC_DELAY_ELEMENT_PSEC / 10) * | ||
65 | 36 * (rate / 1000000); | ||
66 | |||
67 | delay_num = (raw_value & ROCKCHIP_MMC_DELAYNUM_MASK); | ||
68 | delay_num >>= ROCKCHIP_MMC_DELAYNUM_OFFSET; | ||
69 | degrees += delay_num * factor / 10000; | ||
70 | } | ||
71 | |||
72 | return degrees % 360; | ||
73 | } | ||
74 | |||
75 | static int rockchip_mmc_set_phase(struct clk_hw *hw, int degrees) | ||
76 | { | ||
77 | struct rockchip_mmc_clock *mmc_clock = to_mmc_clock(hw); | ||
78 | unsigned long rate = clk_get_rate(hw->clk); | ||
79 | u8 nineties, remainder; | ||
80 | u8 delay_num; | ||
81 | u32 raw_value; | ||
82 | u64 delay; | ||
83 | |||
84 | /* allow 22 to be 22.5 */ | ||
85 | degrees++; | ||
86 | /* floor to 22.5 increment */ | ||
87 | degrees -= ((degrees) * 10 % 225) / 10; | ||
88 | |||
89 | nineties = degrees / 90; | ||
90 | /* 22.5 multiples */ | ||
91 | remainder = (degrees % 90) / 22; | ||
92 | |||
93 | delay = PSECS_PER_SEC; | ||
94 | do_div(delay, rate); | ||
95 | /* / 360 / 22.5 */ | ||
96 | do_div(delay, 16); | ||
97 | do_div(delay, ROCKCHIP_MMC_DELAY_ELEMENT_PSEC); | ||
98 | |||
99 | delay *= remainder; | ||
100 | delay_num = (u8) min(delay, 255ULL); | ||
101 | |||
102 | raw_value = delay_num ? ROCKCHIP_MMC_DELAY_SEL : 0; | ||
103 | raw_value |= delay_num << ROCKCHIP_MMC_DELAYNUM_OFFSET; | ||
104 | raw_value |= nineties; | ||
105 | writel(HIWORD_UPDATE(raw_value, 0x07ff, mmc_clock->shift), mmc_clock->reg); | ||
106 | |||
107 | pr_debug("%s->set_phase(%d) delay_nums=%u reg[0x%p]=0x%03x actual_degrees=%d\n", | ||
108 | __clk_get_name(hw->clk), degrees, delay_num, | ||
109 | mmc_clock->reg, raw_value>>(mmc_clock->shift), | ||
110 | rockchip_mmc_get_phase(hw) | ||
111 | ); | ||
112 | |||
113 | return 0; | ||
114 | } | ||
115 | |||
116 | static const struct clk_ops rockchip_mmc_clk_ops = { | ||
117 | .recalc_rate = rockchip_mmc_recalc, | ||
118 | .get_phase = rockchip_mmc_get_phase, | ||
119 | .set_phase = rockchip_mmc_set_phase, | ||
120 | }; | ||
121 | |||
122 | struct clk *rockchip_clk_register_mmc(const char *name, | ||
123 | const char **parent_names, u8 num_parents, | ||
124 | void __iomem *reg, int shift) | ||
125 | { | ||
126 | struct clk_init_data init; | ||
127 | struct rockchip_mmc_clock *mmc_clock; | ||
128 | struct clk *clk; | ||
129 | |||
130 | mmc_clock = kmalloc(sizeof(*mmc_clock), GFP_KERNEL); | ||
131 | if (!mmc_clock) | ||
132 | return NULL; | ||
133 | |||
134 | init.num_parents = num_parents; | ||
135 | init.parent_names = parent_names; | ||
136 | init.ops = &rockchip_mmc_clk_ops; | ||
137 | |||
138 | mmc_clock->hw.init = &init; | ||
139 | mmc_clock->reg = reg; | ||
140 | mmc_clock->shift = shift; | ||
141 | |||
142 | if (name) | ||
143 | init.name = name; | ||
144 | |||
145 | clk = clk_register(NULL, &mmc_clock->hw); | ||
146 | if (IS_ERR(clk)) | ||
147 | goto err_free; | ||
148 | |||
149 | return clk; | ||
150 | |||
151 | err_free: | ||
152 | kfree(mmc_clock); | ||
153 | return NULL; | ||
154 | } | ||
diff --git a/drivers/clk/rockchip/clk-pll.c b/drivers/clk/rockchip/clk-pll.c index a3e886a38480..f8d3baf275b2 100644 --- a/drivers/clk/rockchip/clk-pll.c +++ b/drivers/clk/rockchip/clk-pll.c | |||
@@ -39,6 +39,7 @@ struct rockchip_clk_pll { | |||
39 | int lock_offset; | 39 | int lock_offset; |
40 | unsigned int lock_shift; | 40 | unsigned int lock_shift; |
41 | enum rockchip_pll_type type; | 41 | enum rockchip_pll_type type; |
42 | u8 flags; | ||
42 | const struct rockchip_pll_rate_table *rate_table; | 43 | const struct rockchip_pll_rate_table *rate_table; |
43 | unsigned int rate_count; | 44 | unsigned int rate_count; |
44 | spinlock_t *lock; | 45 | spinlock_t *lock; |
@@ -257,6 +258,55 @@ static int rockchip_rk3066_pll_is_enabled(struct clk_hw *hw) | |||
257 | return !(pllcon & RK3066_PLLCON3_PWRDOWN); | 258 | return !(pllcon & RK3066_PLLCON3_PWRDOWN); |
258 | } | 259 | } |
259 | 260 | ||
261 | static void rockchip_rk3066_pll_init(struct clk_hw *hw) | ||
262 | { | ||
263 | struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw); | ||
264 | const struct rockchip_pll_rate_table *rate; | ||
265 | unsigned int nf, nr, no, bwadj; | ||
266 | unsigned long drate; | ||
267 | u32 pllcon; | ||
268 | |||
269 | if (!(pll->flags & ROCKCHIP_PLL_SYNC_RATE)) | ||
270 | return; | ||
271 | |||
272 | drate = __clk_get_rate(hw->clk); | ||
273 | rate = rockchip_get_pll_settings(pll, drate); | ||
274 | |||
275 | /* when no rate setting for the current rate, rely on clk_set_rate */ | ||
276 | if (!rate) | ||
277 | return; | ||
278 | |||
279 | pllcon = readl_relaxed(pll->reg_base + RK3066_PLLCON(0)); | ||
280 | nr = ((pllcon >> RK3066_PLLCON0_NR_SHIFT) & RK3066_PLLCON0_NR_MASK) + 1; | ||
281 | no = ((pllcon >> RK3066_PLLCON0_OD_SHIFT) & RK3066_PLLCON0_OD_MASK) + 1; | ||
282 | |||
283 | pllcon = readl_relaxed(pll->reg_base + RK3066_PLLCON(1)); | ||
284 | nf = ((pllcon >> RK3066_PLLCON1_NF_SHIFT) & RK3066_PLLCON1_NF_MASK) + 1; | ||
285 | |||
286 | pllcon = readl_relaxed(pll->reg_base + RK3066_PLLCON(2)); | ||
287 | bwadj = (pllcon >> RK3066_PLLCON2_BWADJ_SHIFT) & RK3066_PLLCON2_BWADJ_MASK; | ||
288 | |||
289 | pr_debug("%s: pll %s@%lu: nr (%d:%d); no (%d:%d); nf(%d:%d), bwadj(%d:%d)\n", | ||
290 | __func__, __clk_get_name(hw->clk), drate, rate->nr, nr, | ||
291 | rate->no, no, rate->nf, nf, rate->bwadj, bwadj); | ||
292 | if (rate->nr != nr || rate->no != no || rate->nf != nf | ||
293 | || rate->bwadj != bwadj) { | ||
294 | struct clk *parent = __clk_get_parent(hw->clk); | ||
295 | unsigned long prate; | ||
296 | |||
297 | if (!parent) { | ||
298 | pr_warn("%s: parent of %s not available\n", | ||
299 | __func__, __clk_get_name(hw->clk)); | ||
300 | return; | ||
301 | } | ||
302 | |||
303 | pr_debug("%s: pll %s: rate params do not match rate table, adjusting\n", | ||
304 | __func__, __clk_get_name(hw->clk)); | ||
305 | prate = __clk_get_rate(parent); | ||
306 | rockchip_rk3066_pll_set_rate(hw, drate, prate); | ||
307 | } | ||
308 | } | ||
309 | |||
260 | static const struct clk_ops rockchip_rk3066_pll_clk_norate_ops = { | 310 | static const struct clk_ops rockchip_rk3066_pll_clk_norate_ops = { |
261 | .recalc_rate = rockchip_rk3066_pll_recalc_rate, | 311 | .recalc_rate = rockchip_rk3066_pll_recalc_rate, |
262 | .enable = rockchip_rk3066_pll_enable, | 312 | .enable = rockchip_rk3066_pll_enable, |
@@ -271,6 +321,7 @@ static const struct clk_ops rockchip_rk3066_pll_clk_ops = { | |||
271 | .enable = rockchip_rk3066_pll_enable, | 321 | .enable = rockchip_rk3066_pll_enable, |
272 | .disable = rockchip_rk3066_pll_disable, | 322 | .disable = rockchip_rk3066_pll_disable, |
273 | .is_enabled = rockchip_rk3066_pll_is_enabled, | 323 | .is_enabled = rockchip_rk3066_pll_is_enabled, |
324 | .init = rockchip_rk3066_pll_init, | ||
274 | }; | 325 | }; |
275 | 326 | ||
276 | /* | 327 | /* |
@@ -282,7 +333,7 @@ struct clk *rockchip_clk_register_pll(enum rockchip_pll_type pll_type, | |||
282 | void __iomem *base, int con_offset, int grf_lock_offset, | 333 | void __iomem *base, int con_offset, int grf_lock_offset, |
283 | int lock_shift, int mode_offset, int mode_shift, | 334 | int lock_shift, int mode_offset, int mode_shift, |
284 | struct rockchip_pll_rate_table *rate_table, | 335 | struct rockchip_pll_rate_table *rate_table, |
285 | spinlock_t *lock) | 336 | u8 clk_pll_flags, spinlock_t *lock) |
286 | { | 337 | { |
287 | const char *pll_parents[3]; | 338 | const char *pll_parents[3]; |
288 | struct clk_init_data init; | 339 | struct clk_init_data init; |
@@ -345,8 +396,22 @@ struct clk *rockchip_clk_register_pll(enum rockchip_pll_type pll_type, | |||
345 | pll->reg_base = base + con_offset; | 396 | pll->reg_base = base + con_offset; |
346 | pll->lock_offset = grf_lock_offset; | 397 | pll->lock_offset = grf_lock_offset; |
347 | pll->lock_shift = lock_shift; | 398 | pll->lock_shift = lock_shift; |
399 | pll->flags = clk_pll_flags; | ||
348 | pll->lock = lock; | 400 | pll->lock = lock; |
349 | 401 | ||
402 | /* create the mux on top of the real pll */ | ||
403 | pll->pll_mux_ops = &clk_mux_ops; | ||
404 | pll_mux = &pll->pll_mux; | ||
405 | pll_mux->reg = base + mode_offset; | ||
406 | pll_mux->shift = mode_shift; | ||
407 | pll_mux->mask = PLL_MODE_MASK; | ||
408 | pll_mux->flags = 0; | ||
409 | pll_mux->lock = lock; | ||
410 | pll_mux->hw.init = &init; | ||
411 | |||
412 | if (pll_type == pll_rk3066) | ||
413 | pll_mux->flags |= CLK_MUX_HIWORD_MASK; | ||
414 | |||
350 | pll_clk = clk_register(NULL, &pll->hw); | 415 | pll_clk = clk_register(NULL, &pll->hw); |
351 | if (IS_ERR(pll_clk)) { | 416 | if (IS_ERR(pll_clk)) { |
352 | pr_err("%s: failed to register pll clock %s : %ld\n", | 417 | pr_err("%s: failed to register pll clock %s : %ld\n", |
@@ -355,10 +420,6 @@ struct clk *rockchip_clk_register_pll(enum rockchip_pll_type pll_type, | |||
355 | goto err_pll; | 420 | goto err_pll; |
356 | } | 421 | } |
357 | 422 | ||
358 | /* create the mux on top of the real pll */ | ||
359 | pll->pll_mux_ops = &clk_mux_ops; | ||
360 | pll_mux = &pll->pll_mux; | ||
361 | |||
362 | /* the actual muxing is xin24m, pll-output, xin32k */ | 423 | /* the actual muxing is xin24m, pll-output, xin32k */ |
363 | pll_parents[0] = parent_names[0]; | 424 | pll_parents[0] = parent_names[0]; |
364 | pll_parents[1] = pll_name; | 425 | pll_parents[1] = pll_name; |
@@ -370,16 +431,6 @@ struct clk *rockchip_clk_register_pll(enum rockchip_pll_type pll_type, | |||
370 | init.parent_names = pll_parents; | 431 | init.parent_names = pll_parents; |
371 | init.num_parents = ARRAY_SIZE(pll_parents); | 432 | init.num_parents = ARRAY_SIZE(pll_parents); |
372 | 433 | ||
373 | pll_mux->reg = base + mode_offset; | ||
374 | pll_mux->shift = mode_shift; | ||
375 | pll_mux->mask = PLL_MODE_MASK; | ||
376 | pll_mux->flags = 0; | ||
377 | pll_mux->lock = lock; | ||
378 | pll_mux->hw.init = &init; | ||
379 | |||
380 | if (pll_type == pll_rk3066) | ||
381 | pll_mux->flags |= CLK_MUX_HIWORD_MASK; | ||
382 | |||
383 | mux_clk = clk_register(NULL, &pll_mux->hw); | 434 | mux_clk = clk_register(NULL, &pll_mux->hw); |
384 | if (IS_ERR(mux_clk)) | 435 | if (IS_ERR(mux_clk)) |
385 | goto err_mux; | 436 | goto err_mux; |
diff --git a/drivers/clk/rockchip/clk-rk3188.c b/drivers/clk/rockchip/clk-rk3188.c index beed49c79126..c54078960847 100644 --- a/drivers/clk/rockchip/clk-rk3188.c +++ b/drivers/clk/rockchip/clk-rk3188.c | |||
@@ -212,13 +212,13 @@ PNAME(mux_sclk_macref_p) = { "mac_src", "ext_rmii" }; | |||
212 | 212 | ||
213 | static struct rockchip_pll_clock rk3188_pll_clks[] __initdata = { | 213 | static struct rockchip_pll_clock rk3188_pll_clks[] __initdata = { |
214 | [apll] = PLL(pll_rk3066, PLL_APLL, "apll", mux_pll_p, 0, RK2928_PLL_CON(0), | 214 | [apll] = PLL(pll_rk3066, PLL_APLL, "apll", mux_pll_p, 0, RK2928_PLL_CON(0), |
215 | RK2928_MODE_CON, 0, 6, rk3188_pll_rates), | 215 | RK2928_MODE_CON, 0, 6, 0, rk3188_pll_rates), |
216 | [dpll] = PLL(pll_rk3066, PLL_DPLL, "dpll", mux_pll_p, 0, RK2928_PLL_CON(4), | 216 | [dpll] = PLL(pll_rk3066, PLL_DPLL, "dpll", mux_pll_p, 0, RK2928_PLL_CON(4), |
217 | RK2928_MODE_CON, 4, 5, NULL), | 217 | RK2928_MODE_CON, 4, 5, 0, NULL), |
218 | [cpll] = PLL(pll_rk3066, PLL_CPLL, "cpll", mux_pll_p, 0, RK2928_PLL_CON(8), | 218 | [cpll] = PLL(pll_rk3066, PLL_CPLL, "cpll", mux_pll_p, 0, RK2928_PLL_CON(8), |
219 | RK2928_MODE_CON, 8, 7, rk3188_pll_rates), | 219 | RK2928_MODE_CON, 8, 7, ROCKCHIP_PLL_SYNC_RATE, rk3188_pll_rates), |
220 | [gpll] = PLL(pll_rk3066, PLL_GPLL, "gpll", mux_pll_p, 0, RK2928_PLL_CON(12), | 220 | [gpll] = PLL(pll_rk3066, PLL_GPLL, "gpll", mux_pll_p, 0, RK2928_PLL_CON(12), |
221 | RK2928_MODE_CON, 12, 8, rk3188_pll_rates), | 221 | RK2928_MODE_CON, 12, 8, ROCKCHIP_PLL_SYNC_RATE, rk3188_pll_rates), |
222 | }; | 222 | }; |
223 | 223 | ||
224 | #define MFLAGS CLK_MUX_HIWORD_MASK | 224 | #define MFLAGS CLK_MUX_HIWORD_MASK |
@@ -257,9 +257,9 @@ static struct rockchip_clk_branch common_clk_branches[] __initdata = { | |||
257 | GATE(0, "hclk_vdpu", "aclk_vdpu", 0, | 257 | GATE(0, "hclk_vdpu", "aclk_vdpu", 0, |
258 | RK2928_CLKGATE_CON(3), 12, GFLAGS), | 258 | RK2928_CLKGATE_CON(3), 12, GFLAGS), |
259 | 259 | ||
260 | GATE(0, "gpll_ddr", "gpll", 0, | 260 | GATE(0, "gpll_ddr", "gpll", CLK_IGNORE_UNUSED, |
261 | RK2928_CLKGATE_CON(1), 7, GFLAGS), | 261 | RK2928_CLKGATE_CON(1), 7, GFLAGS), |
262 | COMPOSITE(0, "ddrphy", mux_ddrphy_p, 0, | 262 | COMPOSITE(0, "ddrphy", mux_ddrphy_p, CLK_IGNORE_UNUSED, |
263 | RK2928_CLKSEL_CON(26), 8, 1, MFLAGS, 0, 2, DFLAGS | CLK_DIVIDER_POWER_OF_TWO, | 263 | RK2928_CLKSEL_CON(26), 8, 1, MFLAGS, 0, 2, DFLAGS | CLK_DIVIDER_POWER_OF_TWO, |
264 | RK2928_CLKGATE_CON(0), 2, GFLAGS), | 264 | RK2928_CLKGATE_CON(0), 2, GFLAGS), |
265 | 265 | ||
@@ -270,10 +270,10 @@ static struct rockchip_clk_branch common_clk_branches[] __initdata = { | |||
270 | RK2928_CLKGATE_CON(0), 6, GFLAGS), | 270 | RK2928_CLKGATE_CON(0), 6, GFLAGS), |
271 | GATE(0, "pclk_cpu", "pclk_cpu_pre", 0, | 271 | GATE(0, "pclk_cpu", "pclk_cpu_pre", 0, |
272 | RK2928_CLKGATE_CON(0), 5, GFLAGS), | 272 | RK2928_CLKGATE_CON(0), 5, GFLAGS), |
273 | GATE(0, "hclk_cpu", "hclk_cpu_pre", 0, | 273 | GATE(0, "hclk_cpu", "hclk_cpu_pre", CLK_IGNORE_UNUSED, |
274 | RK2928_CLKGATE_CON(0), 4, GFLAGS), | 274 | RK2928_CLKGATE_CON(0), 4, GFLAGS), |
275 | 275 | ||
276 | COMPOSITE(0, "aclk_lcdc0_pre", mux_pll_src_cpll_gpll_p, 0, | 276 | COMPOSITE(0, "aclk_lcdc0_pre", mux_pll_src_cpll_gpll_p, CLK_IGNORE_UNUSED, |
277 | RK2928_CLKSEL_CON(31), 7, 1, MFLAGS, 0, 5, DFLAGS, | 277 | RK2928_CLKSEL_CON(31), 7, 1, MFLAGS, 0, 5, DFLAGS, |
278 | RK2928_CLKGATE_CON(3), 0, GFLAGS), | 278 | RK2928_CLKGATE_CON(3), 0, GFLAGS), |
279 | COMPOSITE(0, "aclk_lcdc1_pre", mux_pll_src_cpll_gpll_p, 0, | 279 | COMPOSITE(0, "aclk_lcdc1_pre", mux_pll_src_cpll_gpll_p, 0, |
@@ -304,9 +304,9 @@ static struct rockchip_clk_branch common_clk_branches[] __initdata = { | |||
304 | * the 480m are generated inside the usb block from these clocks, | 304 | * the 480m are generated inside the usb block from these clocks, |
305 | * but they are also a source for the hsicphy clock. | 305 | * but they are also a source for the hsicphy clock. |
306 | */ | 306 | */ |
307 | GATE(SCLK_OTGPHY0, "sclk_otgphy0", "usb480m", 0, | 307 | GATE(SCLK_OTGPHY0, "sclk_otgphy0", "usb480m", CLK_IGNORE_UNUSED, |
308 | RK2928_CLKGATE_CON(1), 5, GFLAGS), | 308 | RK2928_CLKGATE_CON(1), 5, GFLAGS), |
309 | GATE(SCLK_OTGPHY1, "sclk_otgphy1", "usb480m", 0, | 309 | GATE(SCLK_OTGPHY1, "sclk_otgphy1", "usb480m", CLK_IGNORE_UNUSED, |
310 | RK2928_CLKGATE_CON(1), 6, GFLAGS), | 310 | RK2928_CLKGATE_CON(1), 6, GFLAGS), |
311 | 311 | ||
312 | COMPOSITE(0, "mac_src", mux_mac_p, 0, | 312 | COMPOSITE(0, "mac_src", mux_mac_p, 0, |
@@ -320,9 +320,9 @@ static struct rockchip_clk_branch common_clk_branches[] __initdata = { | |||
320 | COMPOSITE(0, "hsadc_src", mux_pll_src_gpll_cpll_p, 0, | 320 | COMPOSITE(0, "hsadc_src", mux_pll_src_gpll_cpll_p, 0, |
321 | RK2928_CLKSEL_CON(22), 0, 1, MFLAGS, 8, 8, DFLAGS, | 321 | RK2928_CLKSEL_CON(22), 0, 1, MFLAGS, 8, 8, DFLAGS, |
322 | RK2928_CLKGATE_CON(2), 6, GFLAGS), | 322 | RK2928_CLKGATE_CON(2), 6, GFLAGS), |
323 | COMPOSITE_FRAC(0, "hsadc_frac", "hsadc_src", | 323 | COMPOSITE_FRAC(0, "hsadc_frac", "hsadc_src", 0, |
324 | RK2928_CLKSEL_CON(23), 0, | 324 | RK2928_CLKSEL_CON(23), 0, |
325 | RK2928_CLKGATE_CON(2), 7, 0, GFLAGS), | 325 | RK2928_CLKGATE_CON(2), 7, GFLAGS), |
326 | MUX(SCLK_HSADC, "sclk_hsadc", mux_sclk_hsadc_p, 0, | 326 | MUX(SCLK_HSADC, "sclk_hsadc", mux_sclk_hsadc_p, 0, |
327 | RK2928_CLKSEL_CON(22), 4, 2, MFLAGS), | 327 | RK2928_CLKSEL_CON(22), 4, 2, MFLAGS), |
328 | 328 | ||
@@ -330,6 +330,15 @@ static struct rockchip_clk_branch common_clk_branches[] __initdata = { | |||
330 | RK2928_CLKSEL_CON(24), 8, 8, DFLAGS, | 330 | RK2928_CLKSEL_CON(24), 8, 8, DFLAGS, |
331 | RK2928_CLKGATE_CON(2), 8, GFLAGS), | 331 | RK2928_CLKGATE_CON(2), 8, GFLAGS), |
332 | 332 | ||
333 | COMPOSITE_NOMUX(0, "spdif_pre", "i2s_src", 0, | ||
334 | RK2928_CLKSEL_CON(5), 0, 7, DFLAGS, | ||
335 | RK2928_CLKGATE_CON(0), 13, GFLAGS), | ||
336 | COMPOSITE_FRAC(0, "spdif_frac", "spdif_pll", 0, | ||
337 | RK2928_CLKSEL_CON(9), 0, | ||
338 | RK2928_CLKGATE_CON(0), 14, GFLAGS), | ||
339 | MUX(SCLK_SPDIF, "sclk_spdif", mux_sclk_spdif_p, 0, | ||
340 | RK2928_CLKSEL_CON(5), 8, 2, MFLAGS), | ||
341 | |||
333 | /* | 342 | /* |
334 | * Clock-Architecture Diagram 4 | 343 | * Clock-Architecture Diagram 4 |
335 | */ | 344 | */ |
@@ -399,8 +408,8 @@ static struct rockchip_clk_branch common_clk_branches[] __initdata = { | |||
399 | 408 | ||
400 | /* aclk_cpu gates */ | 409 | /* aclk_cpu gates */ |
401 | GATE(ACLK_DMA1, "aclk_dma1", "aclk_cpu", 0, RK2928_CLKGATE_CON(5), 0, GFLAGS), | 410 | GATE(ACLK_DMA1, "aclk_dma1", "aclk_cpu", 0, RK2928_CLKGATE_CON(5), 0, GFLAGS), |
402 | GATE(0, "aclk_intmem", "aclk_cpu", 0, RK2928_CLKGATE_CON(4), 12, GFLAGS), | 411 | GATE(0, "aclk_intmem", "aclk_cpu", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(4), 12, GFLAGS), |
403 | GATE(0, "aclk_strc_sys", "aclk_cpu", 0, RK2928_CLKGATE_CON(4), 10, GFLAGS), | 412 | GATE(0, "aclk_strc_sys", "aclk_cpu", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(4), 10, GFLAGS), |
404 | 413 | ||
405 | /* hclk_cpu gates */ | 414 | /* hclk_cpu gates */ |
406 | GATE(HCLK_ROM, "hclk_rom", "hclk_cpu", 0, RK2928_CLKGATE_CON(5), 6, GFLAGS), | 415 | GATE(HCLK_ROM, "hclk_rom", "hclk_cpu", 0, RK2928_CLKGATE_CON(5), 6, GFLAGS), |
@@ -410,14 +419,14 @@ static struct rockchip_clk_branch common_clk_branches[] __initdata = { | |||
410 | /* hclk_ahb2apb is part of a clk branch */ | 419 | /* hclk_ahb2apb is part of a clk branch */ |
411 | GATE(0, "hclk_vio_bus", "hclk_cpu", 0, RK2928_CLKGATE_CON(6), 12, GFLAGS), | 420 | GATE(0, "hclk_vio_bus", "hclk_cpu", 0, RK2928_CLKGATE_CON(6), 12, GFLAGS), |
412 | GATE(HCLK_LCDC0, "hclk_lcdc0", "hclk_cpu", 0, RK2928_CLKGATE_CON(6), 1, GFLAGS), | 421 | GATE(HCLK_LCDC0, "hclk_lcdc0", "hclk_cpu", 0, RK2928_CLKGATE_CON(6), 1, GFLAGS), |
413 | GATE(HCLK_LCDC1, "hclk_lcdc1", "aclk_cpu", 0, RK2928_CLKGATE_CON(6), 2, GFLAGS), | 422 | GATE(HCLK_LCDC1, "hclk_lcdc1", "hclk_cpu", 0, RK2928_CLKGATE_CON(6), 2, GFLAGS), |
414 | GATE(HCLK_CIF0, "hclk_cif0", "hclk_cpu", 0, RK2928_CLKGATE_CON(6), 4, GFLAGS), | 423 | GATE(HCLK_CIF0, "hclk_cif0", "hclk_cpu", 0, RK2928_CLKGATE_CON(6), 4, GFLAGS), |
415 | GATE(HCLK_IPP, "hclk_ipp", "hclk_cpu", 0, RK2928_CLKGATE_CON(6), 9, GFLAGS), | 424 | GATE(HCLK_IPP, "hclk_ipp", "hclk_cpu", 0, RK2928_CLKGATE_CON(6), 9, GFLAGS), |
416 | GATE(HCLK_RGA, "hclk_rga", "hclk_cpu", 0, RK2928_CLKGATE_CON(6), 10, GFLAGS), | 425 | GATE(HCLK_RGA, "hclk_rga", "hclk_cpu", 0, RK2928_CLKGATE_CON(6), 10, GFLAGS), |
417 | 426 | ||
418 | /* hclk_peri gates */ | 427 | /* hclk_peri gates */ |
419 | GATE(0, "hclk_peri_axi_matrix", "hclk_peri", 0, RK2928_CLKGATE_CON(4), 0, GFLAGS), | 428 | GATE(0, "hclk_peri_axi_matrix", "hclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(4), 0, GFLAGS), |
420 | GATE(0, "hclk_peri_ahb_arbi", "hclk_peri", 0, RK2928_CLKGATE_CON(4), 6, GFLAGS), | 429 | GATE(0, "hclk_peri_ahb_arbi", "hclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(4), 6, GFLAGS), |
421 | GATE(0, "hclk_emem_peri", "hclk_peri", 0, RK2928_CLKGATE_CON(4), 7, GFLAGS), | 430 | GATE(0, "hclk_emem_peri", "hclk_peri", 0, RK2928_CLKGATE_CON(4), 7, GFLAGS), |
422 | GATE(HCLK_EMAC, "hclk_emac", "hclk_peri", 0, RK2928_CLKGATE_CON(7), 0, GFLAGS), | 431 | GATE(HCLK_EMAC, "hclk_emac", "hclk_peri", 0, RK2928_CLKGATE_CON(7), 0, GFLAGS), |
423 | GATE(HCLK_NANDC0, "hclk_nandc0", "hclk_peri", 0, RK2928_CLKGATE_CON(5), 9, GFLAGS), | 432 | GATE(HCLK_NANDC0, "hclk_nandc0", "hclk_peri", 0, RK2928_CLKGATE_CON(5), 9, GFLAGS), |
@@ -457,18 +466,18 @@ static struct rockchip_clk_branch common_clk_branches[] __initdata = { | |||
457 | GATE(0, "pclk_ddrupctl", "pclk_cpu", 0, RK2928_CLKGATE_CON(5), 7, GFLAGS), | 466 | GATE(0, "pclk_ddrupctl", "pclk_cpu", 0, RK2928_CLKGATE_CON(5), 7, GFLAGS), |
458 | GATE(0, "pclk_ddrpubl", "pclk_cpu", 0, RK2928_CLKGATE_CON(9), 6, GFLAGS), | 467 | GATE(0, "pclk_ddrpubl", "pclk_cpu", 0, RK2928_CLKGATE_CON(9), 6, GFLAGS), |
459 | GATE(0, "pclk_dbg", "pclk_cpu", 0, RK2928_CLKGATE_CON(9), 1, GFLAGS), | 468 | GATE(0, "pclk_dbg", "pclk_cpu", 0, RK2928_CLKGATE_CON(9), 1, GFLAGS), |
460 | GATE(PCLK_GRF, "pclk_grf", "pclk_cpu", 0, RK2928_CLKGATE_CON(5), 4, GFLAGS), | 469 | GATE(PCLK_GRF, "pclk_grf", "pclk_cpu", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(5), 4, GFLAGS), |
461 | GATE(PCLK_PMU, "pclk_pmu", "pclk_cpu", 0, RK2928_CLKGATE_CON(5), 5, GFLAGS), | 470 | GATE(PCLK_PMU, "pclk_pmu", "pclk_cpu", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(5), 5, GFLAGS), |
462 | 471 | ||
463 | /* aclk_peri */ | 472 | /* aclk_peri */ |
464 | GATE(ACLK_DMA2, "aclk_dma2", "aclk_peri", 0, RK2928_CLKGATE_CON(5), 1, GFLAGS), | 473 | GATE(ACLK_DMA2, "aclk_dma2", "aclk_peri", 0, RK2928_CLKGATE_CON(5), 1, GFLAGS), |
465 | GATE(ACLK_SMC, "aclk_smc", "aclk_peri", 0, RK2928_CLKGATE_CON(5), 8, GFLAGS), | 474 | GATE(ACLK_SMC, "aclk_smc", "aclk_peri", 0, RK2928_CLKGATE_CON(5), 8, GFLAGS), |
466 | GATE(0, "aclk_peri_niu", "aclk_peri", 0, RK2928_CLKGATE_CON(4), 4, GFLAGS), | 475 | GATE(0, "aclk_peri_niu", "aclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(4), 4, GFLAGS), |
467 | GATE(0, "aclk_cpu_peri", "aclk_peri", 0, RK2928_CLKGATE_CON(4), 2, GFLAGS), | 476 | GATE(0, "aclk_cpu_peri", "aclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(4), 2, GFLAGS), |
468 | GATE(0, "aclk_peri_axi_matrix", "aclk_peri", 0, RK2928_CLKGATE_CON(4), 3, GFLAGS), | 477 | GATE(0, "aclk_peri_axi_matrix", "aclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(4), 3, GFLAGS), |
469 | 478 | ||
470 | /* pclk_peri gates */ | 479 | /* pclk_peri gates */ |
471 | GATE(0, "pclk_peri_axi_matrix", "pclk_peri", 0, RK2928_CLKGATE_CON(4), 1, GFLAGS), | 480 | GATE(0, "pclk_peri_axi_matrix", "pclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(4), 1, GFLAGS), |
472 | GATE(PCLK_PWM23, "pclk_pwm23", "pclk_peri", 0, RK2928_CLKGATE_CON(7), 11, GFLAGS), | 481 | GATE(PCLK_PWM23, "pclk_pwm23", "pclk_peri", 0, RK2928_CLKGATE_CON(7), 11, GFLAGS), |
473 | GATE(PCLK_WDT, "pclk_wdt", "pclk_peri", 0, RK2928_CLKGATE_CON(7), 15, GFLAGS), | 482 | GATE(PCLK_WDT, "pclk_wdt", "pclk_peri", 0, RK2928_CLKGATE_CON(7), 15, GFLAGS), |
474 | GATE(PCLK_SPI0, "pclk_spi0", "pclk_peri", 0, RK2928_CLKGATE_CON(7), 12, GFLAGS), | 483 | GATE(PCLK_SPI0, "pclk_spi0", "pclk_peri", 0, RK2928_CLKGATE_CON(7), 12, GFLAGS), |
@@ -511,7 +520,7 @@ static struct rockchip_clk_branch rk3066a_clk_branches[] __initdata = { | |||
511 | | CLK_DIVIDER_READ_ONLY, | 520 | | CLK_DIVIDER_READ_ONLY, |
512 | RK2928_CLKGATE_CON(4), 9, GFLAGS), | 521 | RK2928_CLKGATE_CON(4), 9, GFLAGS), |
513 | 522 | ||
514 | GATE(CORE_L2C, "core_l2c", "aclk_cpu", 0, | 523 | GATE(CORE_L2C, "core_l2c", "aclk_cpu", CLK_IGNORE_UNUSED, |
515 | RK2928_CLKGATE_CON(9), 4, GFLAGS), | 524 | RK2928_CLKGATE_CON(9), 4, GFLAGS), |
516 | 525 | ||
517 | COMPOSITE(0, "aclk_peri_pre", mux_pll_src_gpll_cpll_p, 0, | 526 | COMPOSITE(0, "aclk_peri_pre", mux_pll_src_gpll_cpll_p, 0, |
@@ -577,14 +586,6 @@ static struct rockchip_clk_branch rk3066a_clk_branches[] __initdata = { | |||
577 | RK2928_CLKGATE_CON(0), 12, GFLAGS), | 586 | RK2928_CLKGATE_CON(0), 12, GFLAGS), |
578 | MUX(SCLK_I2S2, "sclk_i2s2", mux_sclk_i2s2_p, 0, | 587 | MUX(SCLK_I2S2, "sclk_i2s2", mux_sclk_i2s2_p, 0, |
579 | RK2928_CLKSEL_CON(4), 8, 2, MFLAGS), | 588 | RK2928_CLKSEL_CON(4), 8, 2, MFLAGS), |
580 | COMPOSITE_NOMUX(0, "spdif_pre", "i2s_src", 0, | ||
581 | RK2928_CLKSEL_CON(5), 0, 7, DFLAGS, | ||
582 | RK2928_CLKGATE_CON(0), 13, GFLAGS), | ||
583 | COMPOSITE_FRAC(0, "spdif_frac", "spdif_pll", 0, | ||
584 | RK2928_CLKSEL_CON(9), 0, | ||
585 | RK2928_CLKGATE_CON(0), 14, GFLAGS), | ||
586 | MUX(SCLK_SPDIF, "sclk_spdif", mux_sclk_spdif_p, 0, | ||
587 | RK2928_CLKSEL_CON(5), 8, 2, MFLAGS), | ||
588 | 589 | ||
589 | GATE(HCLK_I2S1, "hclk_i2s1", "hclk_cpu", 0, RK2928_CLKGATE_CON(7), 3, GFLAGS), | 590 | GATE(HCLK_I2S1, "hclk_i2s1", "hclk_cpu", 0, RK2928_CLKGATE_CON(7), 3, GFLAGS), |
590 | GATE(HCLK_I2S2, "hclk_i2s2", "hclk_cpu", 0, RK2928_CLKGATE_CON(7), 4, GFLAGS), | 591 | GATE(HCLK_I2S2, "hclk_i2s2", "hclk_cpu", 0, RK2928_CLKGATE_CON(7), 4, GFLAGS), |
@@ -618,7 +619,7 @@ PNAME(mux_hsicphy_p) = { "sclk_otgphy0", "sclk_otgphy1", | |||
618 | "gpll", "cpll" }; | 619 | "gpll", "cpll" }; |
619 | 620 | ||
620 | static struct rockchip_clk_branch rk3188_clk_branches[] __initdata = { | 621 | static struct rockchip_clk_branch rk3188_clk_branches[] __initdata = { |
621 | COMPOSITE_NOMUX_DIVTBL(0, "aclk_core", "armclk", 0, | 622 | COMPOSITE_NOMUX_DIVTBL(0, "aclk_core", "armclk", CLK_IGNORE_UNUSED, |
622 | RK2928_CLKSEL_CON(1), 3, 3, DFLAGS | CLK_DIVIDER_READ_ONLY, | 623 | RK2928_CLKSEL_CON(1), 3, 3, DFLAGS | CLK_DIVIDER_READ_ONLY, |
623 | div_rk3188_aclk_core_t, RK2928_CLKGATE_CON(0), 7, GFLAGS), | 624 | div_rk3188_aclk_core_t, RK2928_CLKGATE_CON(0), 7, GFLAGS), |
624 | 625 | ||
@@ -633,7 +634,7 @@ static struct rockchip_clk_branch rk3188_clk_branches[] __initdata = { | |||
633 | RK2928_CLKSEL_CON(1), 14, 2, DFLAGS | CLK_DIVIDER_POWER_OF_TWO, | 634 | RK2928_CLKSEL_CON(1), 14, 2, DFLAGS | CLK_DIVIDER_POWER_OF_TWO, |
634 | RK2928_CLKGATE_CON(4), 9, GFLAGS), | 635 | RK2928_CLKGATE_CON(4), 9, GFLAGS), |
635 | 636 | ||
636 | GATE(CORE_L2C, "core_l2c", "armclk", 0, | 637 | GATE(CORE_L2C, "core_l2c", "armclk", CLK_IGNORE_UNUSED, |
637 | RK2928_CLKGATE_CON(9), 4, GFLAGS), | 638 | RK2928_CLKGATE_CON(9), 4, GFLAGS), |
638 | 639 | ||
639 | COMPOSITE(0, "aclk_peri_pre", mux_pll_src_cpll_gpll_p, 0, | 640 | COMPOSITE(0, "aclk_peri_pre", mux_pll_src_cpll_gpll_p, 0, |
@@ -663,7 +664,7 @@ static struct rockchip_clk_branch rk3188_clk_branches[] __initdata = { | |||
663 | RK2928_CLKSEL_CON(30), 0, 2, DFLAGS, | 664 | RK2928_CLKSEL_CON(30), 0, 2, DFLAGS, |
664 | RK2928_CLKGATE_CON(3), 6, GFLAGS), | 665 | RK2928_CLKGATE_CON(3), 6, GFLAGS), |
665 | DIV(0, "sclk_hsicphy_12m", "sclk_hsicphy_480m", 0, | 666 | DIV(0, "sclk_hsicphy_12m", "sclk_hsicphy_480m", 0, |
666 | RK2928_CLKGATE_CON(11), 8, 6, DFLAGS), | 667 | RK2928_CLKSEL_CON(11), 8, 6, DFLAGS), |
667 | 668 | ||
668 | MUX(0, "i2s_src", mux_pll_src_gpll_cpll_p, 0, | 669 | MUX(0, "i2s_src", mux_pll_src_gpll_cpll_p, 0, |
669 | RK2928_CLKSEL_CON(2), 15, 1, MFLAGS), | 670 | RK2928_CLKSEL_CON(2), 15, 1, MFLAGS), |
@@ -675,14 +676,6 @@ static struct rockchip_clk_branch rk3188_clk_branches[] __initdata = { | |||
675 | RK2928_CLKGATE_CON(0), 10, GFLAGS), | 676 | RK2928_CLKGATE_CON(0), 10, GFLAGS), |
676 | MUX(SCLK_I2S0, "sclk_i2s0", mux_sclk_i2s0_p, 0, | 677 | MUX(SCLK_I2S0, "sclk_i2s0", mux_sclk_i2s0_p, 0, |
677 | RK2928_CLKSEL_CON(3), 8, 2, MFLAGS), | 678 | RK2928_CLKSEL_CON(3), 8, 2, MFLAGS), |
678 | COMPOSITE_NOMUX(0, "spdif_pre", "i2s_src", 0, | ||
679 | RK2928_CLKSEL_CON(5), 0, 7, DFLAGS, | ||
680 | RK2928_CLKGATE_CON(13), 13, GFLAGS), | ||
681 | COMPOSITE_FRAC(0, "spdif_frac", "spdif_pll", 0, | ||
682 | RK2928_CLKSEL_CON(9), 0, | ||
683 | RK2928_CLKGATE_CON(0), 14, GFLAGS), | ||
684 | MUX(SCLK_SPDIF, "sclk_spdif", mux_sclk_spdif_p, 0, | ||
685 | RK2928_CLKSEL_CON(5), 8, 2, MFLAGS), | ||
686 | 679 | ||
687 | GATE(0, "hclk_imem0", "hclk_cpu", 0, RK2928_CLKGATE_CON(4), 14, GFLAGS), | 680 | GATE(0, "hclk_imem0", "hclk_cpu", 0, RK2928_CLKGATE_CON(4), 14, GFLAGS), |
688 | GATE(0, "hclk_imem1", "hclk_cpu", 0, RK2928_CLKGATE_CON(4), 15, GFLAGS), | 681 | GATE(0, "hclk_imem1", "hclk_cpu", 0, RK2928_CLKGATE_CON(4), 15, GFLAGS), |
diff --git a/drivers/clk/rockchip/clk-rk3288.c b/drivers/clk/rockchip/clk-rk3288.c index 23278291da44..ac6be7c0132d 100644 --- a/drivers/clk/rockchip/clk-rk3288.c +++ b/drivers/clk/rockchip/clk-rk3288.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/clk-provider.h> | 16 | #include <linux/clk-provider.h> |
17 | #include <linux/of.h> | 17 | #include <linux/of.h> |
18 | #include <linux/of_address.h> | 18 | #include <linux/of_address.h> |
19 | #include <linux/syscore_ops.h> | ||
19 | #include <dt-bindings/clock/rk3288-cru.h> | 20 | #include <dt-bindings/clock/rk3288-cru.h> |
20 | #include "clk.h" | 21 | #include "clk.h" |
21 | 22 | ||
@@ -83,11 +84,13 @@ struct rockchip_pll_rate_table rk3288_pll_rates[] = { | |||
83 | RK3066_PLL_RATE( 742500000, 8, 495, 2), | 84 | RK3066_PLL_RATE( 742500000, 8, 495, 2), |
84 | RK3066_PLL_RATE( 696000000, 1, 58, 2), | 85 | RK3066_PLL_RATE( 696000000, 1, 58, 2), |
85 | RK3066_PLL_RATE( 600000000, 1, 50, 2), | 86 | RK3066_PLL_RATE( 600000000, 1, 50, 2), |
86 | RK3066_PLL_RATE( 594000000, 2, 198, 4), | 87 | RK3066_PLL_RATE_BWADJ(594000000, 1, 198, 8, 1), |
87 | RK3066_PLL_RATE( 552000000, 1, 46, 2), | 88 | RK3066_PLL_RATE( 552000000, 1, 46, 2), |
88 | RK3066_PLL_RATE( 504000000, 1, 84, 4), | 89 | RK3066_PLL_RATE( 504000000, 1, 84, 4), |
90 | RK3066_PLL_RATE( 500000000, 3, 125, 2), | ||
89 | RK3066_PLL_RATE( 456000000, 1, 76, 4), | 91 | RK3066_PLL_RATE( 456000000, 1, 76, 4), |
90 | RK3066_PLL_RATE( 408000000, 1, 68, 4), | 92 | RK3066_PLL_RATE( 408000000, 1, 68, 4), |
93 | RK3066_PLL_RATE( 400000000, 3, 100, 2), | ||
91 | RK3066_PLL_RATE( 384000000, 2, 128, 4), | 94 | RK3066_PLL_RATE( 384000000, 2, 128, 4), |
92 | RK3066_PLL_RATE( 360000000, 1, 60, 4), | 95 | RK3066_PLL_RATE( 360000000, 1, 60, 4), |
93 | RK3066_PLL_RATE( 312000000, 1, 52, 4), | 96 | RK3066_PLL_RATE( 312000000, 1, 52, 4), |
@@ -173,14 +176,14 @@ PNAME(mux_aclk_cpu_src_p) = { "cpll_aclk_cpu", "gpll_aclk_cpu" }; | |||
173 | PNAME(mux_pll_src_cpll_gpll_p) = { "cpll", "gpll" }; | 176 | PNAME(mux_pll_src_cpll_gpll_p) = { "cpll", "gpll" }; |
174 | PNAME(mux_pll_src_npll_cpll_gpll_p) = { "npll", "cpll", "gpll" }; | 177 | PNAME(mux_pll_src_npll_cpll_gpll_p) = { "npll", "cpll", "gpll" }; |
175 | PNAME(mux_pll_src_cpll_gpll_npll_p) = { "cpll", "gpll", "npll" }; | 178 | PNAME(mux_pll_src_cpll_gpll_npll_p) = { "cpll", "gpll", "npll" }; |
176 | PNAME(mux_pll_src_cpll_gpll_usb480m_p) = { "cpll", "gpll", "usb480m" }; | 179 | PNAME(mux_pll_src_cpll_gpll_usb480m_p) = { "cpll", "gpll", "usbphy480m_src" }; |
180 | PNAME(mux_pll_src_cpll_gll_usb_npll_p) = { "cpll", "gpll", "usbphy480m_src", "npll" }; | ||
177 | 181 | ||
178 | PNAME(mux_mmc_src_p) = { "cpll", "gpll", "xin24m", "xin24m" }; | 182 | PNAME(mux_mmc_src_p) = { "cpll", "gpll", "xin24m", "xin24m" }; |
179 | PNAME(mux_i2s_pre_p) = { "i2s_src", "i2s_frac", "ext_i2s", "xin12m" }; | 183 | PNAME(mux_i2s_pre_p) = { "i2s_src", "i2s_frac", "ext_i2s", "xin12m" }; |
180 | PNAME(mux_i2s_clkout_p) = { "i2s_pre", "xin12m" }; | 184 | PNAME(mux_i2s_clkout_p) = { "i2s_pre", "xin12m" }; |
181 | PNAME(mux_spdif_p) = { "spdif_pre", "spdif_frac", "xin12m" }; | 185 | PNAME(mux_spdif_p) = { "spdif_pre", "spdif_frac", "xin12m" }; |
182 | PNAME(mux_spdif_8ch_p) = { "spdif_8ch_pre", "spdif_8ch_frac", "xin12m" }; | 186 | PNAME(mux_spdif_8ch_p) = { "spdif_8ch_pre", "spdif_8ch_frac", "xin12m" }; |
183 | PNAME(mux_uart0_pll_p) = { "cpll", "gpll", "usbphy_480m_src", "npll" }; | ||
184 | PNAME(mux_uart0_p) = { "uart0_src", "uart0_frac", "xin24m" }; | 187 | PNAME(mux_uart0_p) = { "uart0_src", "uart0_frac", "xin24m" }; |
185 | PNAME(mux_uart1_p) = { "uart1_src", "uart1_frac", "xin24m" }; | 188 | PNAME(mux_uart1_p) = { "uart1_src", "uart1_frac", "xin24m" }; |
186 | PNAME(mux_uart2_p) = { "uart2_src", "uart2_frac", "xin24m" }; | 189 | PNAME(mux_uart2_p) = { "uart2_src", "uart2_frac", "xin24m" }; |
@@ -192,22 +195,22 @@ PNAME(mux_hsadcout_p) = { "hsadc_src", "ext_hsadc" }; | |||
192 | PNAME(mux_edp_24m_p) = { "ext_edp_24m", "xin24m" }; | 195 | PNAME(mux_edp_24m_p) = { "ext_edp_24m", "xin24m" }; |
193 | PNAME(mux_tspout_p) = { "cpll", "gpll", "npll", "xin27m" }; | 196 | PNAME(mux_tspout_p) = { "cpll", "gpll", "npll", "xin27m" }; |
194 | 197 | ||
195 | PNAME(mux_usbphy480m_p) = { "sclk_otgphy0", "sclk_otgphy1", | 198 | PNAME(mux_usbphy480m_p) = { "sclk_otgphy1", "sclk_otgphy2", |
196 | "sclk_otgphy2" }; | 199 | "sclk_otgphy0" }; |
197 | PNAME(mux_hsicphy480m_p) = { "cpll", "gpll", "usbphy480m_src" }; | 200 | PNAME(mux_hsicphy480m_p) = { "cpll", "gpll", "usbphy480m_src" }; |
198 | PNAME(mux_hsicphy12m_p) = { "hsicphy12m_xin12m", "hsicphy12m_usbphy" }; | 201 | PNAME(mux_hsicphy12m_p) = { "hsicphy12m_xin12m", "hsicphy12m_usbphy" }; |
199 | 202 | ||
200 | static struct rockchip_pll_clock rk3288_pll_clks[] __initdata = { | 203 | static struct rockchip_pll_clock rk3288_pll_clks[] __initdata = { |
201 | [apll] = PLL(pll_rk3066, PLL_APLL, "apll", mux_pll_p, 0, RK3288_PLL_CON(0), | 204 | [apll] = PLL(pll_rk3066, PLL_APLL, "apll", mux_pll_p, 0, RK3288_PLL_CON(0), |
202 | RK3288_MODE_CON, 0, 6, rk3288_pll_rates), | 205 | RK3288_MODE_CON, 0, 6, 0, rk3288_pll_rates), |
203 | [dpll] = PLL(pll_rk3066, PLL_DPLL, "dpll", mux_pll_p, 0, RK3288_PLL_CON(4), | 206 | [dpll] = PLL(pll_rk3066, PLL_DPLL, "dpll", mux_pll_p, 0, RK3288_PLL_CON(4), |
204 | RK3288_MODE_CON, 4, 5, NULL), | 207 | RK3288_MODE_CON, 4, 5, 0, NULL), |
205 | [cpll] = PLL(pll_rk3066, PLL_CPLL, "cpll", mux_pll_p, 0, RK3288_PLL_CON(8), | 208 | [cpll] = PLL(pll_rk3066, PLL_CPLL, "cpll", mux_pll_p, 0, RK3288_PLL_CON(8), |
206 | RK3288_MODE_CON, 8, 7, rk3288_pll_rates), | 209 | RK3288_MODE_CON, 8, 7, ROCKCHIP_PLL_SYNC_RATE, rk3288_pll_rates), |
207 | [gpll] = PLL(pll_rk3066, PLL_GPLL, "gpll", mux_pll_p, 0, RK3288_PLL_CON(12), | 210 | [gpll] = PLL(pll_rk3066, PLL_GPLL, "gpll", mux_pll_p, 0, RK3288_PLL_CON(12), |
208 | RK3288_MODE_CON, 12, 8, rk3288_pll_rates), | 211 | RK3288_MODE_CON, 12, 8, ROCKCHIP_PLL_SYNC_RATE, rk3288_pll_rates), |
209 | [npll] = PLL(pll_rk3066, PLL_NPLL, "npll", mux_pll_p, 0, RK3288_PLL_CON(16), | 212 | [npll] = PLL(pll_rk3066, PLL_NPLL, "npll", mux_pll_p, 0, RK3288_PLL_CON(16), |
210 | RK3288_MODE_CON, 14, 9, rk3288_pll_rates), | 213 | RK3288_MODE_CON, 14, 9, ROCKCHIP_PLL_SYNC_RATE, rk3288_pll_rates), |
211 | }; | 214 | }; |
212 | 215 | ||
213 | static struct clk_div_table div_hclk_cpu_t[] = { | 216 | static struct clk_div_table div_hclk_cpu_t[] = { |
@@ -226,67 +229,67 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = { | |||
226 | * Clock-Architecture Diagram 1 | 229 | * Clock-Architecture Diagram 1 |
227 | */ | 230 | */ |
228 | 231 | ||
229 | GATE(0, "apll_core", "apll", 0, | 232 | GATE(0, "apll_core", "apll", CLK_IGNORE_UNUSED, |
230 | RK3288_CLKGATE_CON(0), 1, GFLAGS), | 233 | RK3288_CLKGATE_CON(0), 1, GFLAGS), |
231 | GATE(0, "gpll_core", "gpll", 0, | 234 | GATE(0, "gpll_core", "gpll", CLK_IGNORE_UNUSED, |
232 | RK3288_CLKGATE_CON(0), 2, GFLAGS), | 235 | RK3288_CLKGATE_CON(0), 2, GFLAGS), |
233 | 236 | ||
234 | COMPOSITE_NOMUX(0, "armcore0", "armclk", 0, | 237 | COMPOSITE_NOMUX(0, "armcore0", "armclk", CLK_IGNORE_UNUSED, |
235 | RK3288_CLKSEL_CON(36), 0, 3, DFLAGS | CLK_DIVIDER_READ_ONLY, | 238 | RK3288_CLKSEL_CON(36), 0, 3, DFLAGS | CLK_DIVIDER_READ_ONLY, |
236 | RK3288_CLKGATE_CON(12), 0, GFLAGS), | 239 | RK3288_CLKGATE_CON(12), 0, GFLAGS), |
237 | COMPOSITE_NOMUX(0, "armcore1", "armclk", 0, | 240 | COMPOSITE_NOMUX(0, "armcore1", "armclk", CLK_IGNORE_UNUSED, |
238 | RK3288_CLKSEL_CON(36), 4, 3, DFLAGS | CLK_DIVIDER_READ_ONLY, | 241 | RK3288_CLKSEL_CON(36), 4, 3, DFLAGS | CLK_DIVIDER_READ_ONLY, |
239 | RK3288_CLKGATE_CON(12), 1, GFLAGS), | 242 | RK3288_CLKGATE_CON(12), 1, GFLAGS), |
240 | COMPOSITE_NOMUX(0, "armcore2", "armclk", 0, | 243 | COMPOSITE_NOMUX(0, "armcore2", "armclk", CLK_IGNORE_UNUSED, |
241 | RK3288_CLKSEL_CON(36), 8, 3, DFLAGS | CLK_DIVIDER_READ_ONLY, | 244 | RK3288_CLKSEL_CON(36), 8, 3, DFLAGS | CLK_DIVIDER_READ_ONLY, |
242 | RK3288_CLKGATE_CON(12), 2, GFLAGS), | 245 | RK3288_CLKGATE_CON(12), 2, GFLAGS), |
243 | COMPOSITE_NOMUX(0, "armcore3", "armclk", 0, | 246 | COMPOSITE_NOMUX(0, "armcore3", "armclk", CLK_IGNORE_UNUSED, |
244 | RK3288_CLKSEL_CON(36), 12, 3, DFLAGS | CLK_DIVIDER_READ_ONLY, | 247 | RK3288_CLKSEL_CON(36), 12, 3, DFLAGS | CLK_DIVIDER_READ_ONLY, |
245 | RK3288_CLKGATE_CON(12), 3, GFLAGS), | 248 | RK3288_CLKGATE_CON(12), 3, GFLAGS), |
246 | COMPOSITE_NOMUX(0, "l2ram", "armclk", 0, | 249 | COMPOSITE_NOMUX(0, "l2ram", "armclk", CLK_IGNORE_UNUSED, |
247 | RK3288_CLKSEL_CON(37), 0, 3, DFLAGS | CLK_DIVIDER_READ_ONLY, | 250 | RK3288_CLKSEL_CON(37), 0, 3, DFLAGS | CLK_DIVIDER_READ_ONLY, |
248 | RK3288_CLKGATE_CON(12), 4, GFLAGS), | 251 | RK3288_CLKGATE_CON(12), 4, GFLAGS), |
249 | COMPOSITE_NOMUX(0, "aclk_core_m0", "armclk", 0, | 252 | COMPOSITE_NOMUX(0, "aclk_core_m0", "armclk", CLK_IGNORE_UNUSED, |
250 | RK3288_CLKSEL_CON(0), 0, 4, DFLAGS | CLK_DIVIDER_READ_ONLY, | 253 | RK3288_CLKSEL_CON(0), 0, 4, DFLAGS | CLK_DIVIDER_READ_ONLY, |
251 | RK3288_CLKGATE_CON(12), 5, GFLAGS), | 254 | RK3288_CLKGATE_CON(12), 5, GFLAGS), |
252 | COMPOSITE_NOMUX(0, "aclk_core_mp", "armclk", 0, | 255 | COMPOSITE_NOMUX(0, "aclk_core_mp", "armclk", CLK_IGNORE_UNUSED, |
253 | RK3288_CLKSEL_CON(0), 4, 4, DFLAGS | CLK_DIVIDER_READ_ONLY, | 256 | RK3288_CLKSEL_CON(0), 4, 4, DFLAGS | CLK_DIVIDER_READ_ONLY, |
254 | RK3288_CLKGATE_CON(12), 6, GFLAGS), | 257 | RK3288_CLKGATE_CON(12), 6, GFLAGS), |
255 | COMPOSITE_NOMUX(0, "atclk", "armclk", 0, | 258 | COMPOSITE_NOMUX(0, "atclk", "armclk", 0, |
256 | RK3288_CLKSEL_CON(37), 4, 5, DFLAGS | CLK_DIVIDER_READ_ONLY, | 259 | RK3288_CLKSEL_CON(37), 4, 5, DFLAGS | CLK_DIVIDER_READ_ONLY, |
257 | RK3288_CLKGATE_CON(12), 7, GFLAGS), | 260 | RK3288_CLKGATE_CON(12), 7, GFLAGS), |
258 | COMPOSITE_NOMUX(0, "pclk_dbg_pre", "armclk", 0, | 261 | COMPOSITE_NOMUX(0, "pclk_dbg_pre", "armclk", CLK_IGNORE_UNUSED, |
259 | RK3288_CLKSEL_CON(37), 9, 5, DFLAGS | CLK_DIVIDER_READ_ONLY, | 262 | RK3288_CLKSEL_CON(37), 9, 5, DFLAGS | CLK_DIVIDER_READ_ONLY, |
260 | RK3288_CLKGATE_CON(12), 8, GFLAGS), | 263 | RK3288_CLKGATE_CON(12), 8, GFLAGS), |
261 | GATE(0, "pclk_dbg", "pclk_dbg_pre", 0, | 264 | GATE(0, "pclk_dbg", "pclk_dbg_pre", 0, |
262 | RK3288_CLKGATE_CON(12), 9, GFLAGS), | 265 | RK3288_CLKGATE_CON(12), 9, GFLAGS), |
263 | GATE(0, "cs_dbg", "pclk_dbg_pre", 0, | 266 | GATE(0, "cs_dbg", "pclk_dbg_pre", CLK_IGNORE_UNUSED, |
264 | RK3288_CLKGATE_CON(12), 10, GFLAGS), | 267 | RK3288_CLKGATE_CON(12), 10, GFLAGS), |
265 | GATE(0, "pclk_core_niu", "pclk_dbg_pre", 0, | 268 | GATE(0, "pclk_core_niu", "pclk_dbg_pre", 0, |
266 | RK3288_CLKGATE_CON(12), 11, GFLAGS), | 269 | RK3288_CLKGATE_CON(12), 11, GFLAGS), |
267 | 270 | ||
268 | GATE(0, "dpll_ddr", "dpll", 0, | 271 | GATE(0, "dpll_ddr", "dpll", CLK_IGNORE_UNUSED, |
269 | RK3288_CLKGATE_CON(0), 8, GFLAGS), | 272 | RK3288_CLKGATE_CON(0), 8, GFLAGS), |
270 | GATE(0, "gpll_ddr", "gpll", 0, | 273 | GATE(0, "gpll_ddr", "gpll", 0, |
271 | RK3288_CLKGATE_CON(0), 9, GFLAGS), | 274 | RK3288_CLKGATE_CON(0), 9, GFLAGS), |
272 | COMPOSITE_NOGATE(0, "ddrphy", mux_ddrphy_p, 0, | 275 | COMPOSITE_NOGATE(0, "ddrphy", mux_ddrphy_p, CLK_IGNORE_UNUSED, |
273 | RK3288_CLKSEL_CON(26), 2, 1, MFLAGS, 0, 2, | 276 | RK3288_CLKSEL_CON(26), 2, 1, MFLAGS, 0, 2, |
274 | DFLAGS | CLK_DIVIDER_POWER_OF_TWO), | 277 | DFLAGS | CLK_DIVIDER_POWER_OF_TWO), |
275 | 278 | ||
276 | GATE(0, "gpll_aclk_cpu", "gpll", 0, | 279 | GATE(0, "gpll_aclk_cpu", "gpll", CLK_IGNORE_UNUSED, |
277 | RK3288_CLKGATE_CON(0), 10, GFLAGS), | 280 | RK3288_CLKGATE_CON(0), 10, GFLAGS), |
278 | GATE(0, "cpll_aclk_cpu", "cpll", 0, | 281 | GATE(0, "cpll_aclk_cpu", "cpll", CLK_IGNORE_UNUSED, |
279 | RK3288_CLKGATE_CON(0), 11, GFLAGS), | 282 | RK3288_CLKGATE_CON(0), 11, GFLAGS), |
280 | COMPOSITE_NOGATE(0, "aclk_cpu_src", mux_aclk_cpu_src_p, 0, | 283 | COMPOSITE_NOGATE(0, "aclk_cpu_src", mux_aclk_cpu_src_p, CLK_IGNORE_UNUSED, |
281 | RK3288_CLKSEL_CON(1), 15, 1, MFLAGS, 3, 5, DFLAGS), | 284 | RK3288_CLKSEL_CON(1), 15, 1, MFLAGS, 3, 5, DFLAGS), |
282 | DIV(0, "aclk_cpu_pre", "aclk_cpu_src", 0, | 285 | DIV(0, "aclk_cpu_pre", "aclk_cpu_src", CLK_SET_RATE_PARENT, |
283 | RK3288_CLKSEL_CON(1), 0, 3, DFLAGS), | 286 | RK3288_CLKSEL_CON(1), 0, 3, DFLAGS), |
284 | GATE(ACLK_CPU, "aclk_cpu", "aclk_cpu_pre", 0, | 287 | GATE(ACLK_CPU, "aclk_cpu", "aclk_cpu_pre", CLK_IGNORE_UNUSED, |
285 | RK3288_CLKGATE_CON(0), 3, GFLAGS), | 288 | RK3288_CLKGATE_CON(0), 3, GFLAGS), |
286 | COMPOSITE_NOMUX(PCLK_CPU, "pclk_cpu", "aclk_cpu_pre", 0, | 289 | COMPOSITE_NOMUX(PCLK_CPU, "pclk_cpu", "aclk_cpu_pre", CLK_IGNORE_UNUSED, |
287 | RK3288_CLKSEL_CON(1), 12, 3, DFLAGS, | 290 | RK3288_CLKSEL_CON(1), 12, 3, DFLAGS, |
288 | RK3288_CLKGATE_CON(0), 5, GFLAGS), | 291 | RK3288_CLKGATE_CON(0), 5, GFLAGS), |
289 | COMPOSITE_NOMUX_DIVTBL(HCLK_CPU, "hclk_cpu", "aclk_cpu_pre", 0, | 292 | COMPOSITE_NOMUX_DIVTBL(HCLK_CPU, "hclk_cpu", "aclk_cpu_pre", CLK_IGNORE_UNUSED, |
290 | RK3288_CLKSEL_CON(1), 8, 2, DFLAGS, div_hclk_cpu_t, | 293 | RK3288_CLKSEL_CON(1), 8, 2, DFLAGS, div_hclk_cpu_t, |
291 | RK3288_CLKGATE_CON(0), 4, GFLAGS), | 294 | RK3288_CLKGATE_CON(0), 4, GFLAGS), |
292 | GATE(0, "c2c_host", "aclk_cpu_src", 0, | 295 | GATE(0, "c2c_host", "aclk_cpu_src", 0, |
@@ -294,7 +297,7 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = { | |||
294 | COMPOSITE_NOMUX(0, "crypto", "aclk_cpu_pre", 0, | 297 | COMPOSITE_NOMUX(0, "crypto", "aclk_cpu_pre", 0, |
295 | RK3288_CLKSEL_CON(26), 6, 2, DFLAGS, | 298 | RK3288_CLKSEL_CON(26), 6, 2, DFLAGS, |
296 | RK3288_CLKGATE_CON(5), 4, GFLAGS), | 299 | RK3288_CLKGATE_CON(5), 4, GFLAGS), |
297 | GATE(0, "aclk_bus_2pmu", "aclk_cpu_pre", 0, | 300 | GATE(0, "aclk_bus_2pmu", "aclk_cpu_pre", CLK_IGNORE_UNUSED, |
298 | RK3288_CLKGATE_CON(0), 7, GFLAGS), | 301 | RK3288_CLKGATE_CON(0), 7, GFLAGS), |
299 | 302 | ||
300 | COMPOSITE(0, "i2s_src", mux_pll_src_cpll_gpll_p, 0, | 303 | COMPOSITE(0, "i2s_src", mux_pll_src_cpll_gpll_p, 0, |
@@ -305,7 +308,7 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = { | |||
305 | RK3288_CLKGATE_CON(4), 2, GFLAGS), | 308 | RK3288_CLKGATE_CON(4), 2, GFLAGS), |
306 | MUX(0, "i2s_pre", mux_i2s_pre_p, CLK_SET_RATE_PARENT, | 309 | MUX(0, "i2s_pre", mux_i2s_pre_p, CLK_SET_RATE_PARENT, |
307 | RK3288_CLKSEL_CON(4), 8, 2, MFLAGS), | 310 | RK3288_CLKSEL_CON(4), 8, 2, MFLAGS), |
308 | COMPOSITE_NODIV(0, "i2s0_clkout", mux_i2s_clkout_p, CLK_SET_RATE_PARENT, | 311 | COMPOSITE_NODIV(SCLK_I2S0_OUT, "i2s0_clkout", mux_i2s_clkout_p, 0, |
309 | RK3288_CLKSEL_CON(4), 12, 1, MFLAGS, | 312 | RK3288_CLKSEL_CON(4), 12, 1, MFLAGS, |
310 | RK3288_CLKGATE_CON(4), 0, GFLAGS), | 313 | RK3288_CLKGATE_CON(4), 0, GFLAGS), |
311 | GATE(SCLK_I2S0, "sclk_i2s0", "i2s_pre", CLK_SET_RATE_PARENT, | 314 | GATE(SCLK_I2S0, "sclk_i2s0", "i2s_pre", CLK_SET_RATE_PARENT, |
@@ -325,7 +328,7 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = { | |||
325 | COMPOSITE_NOMUX(0, "spdif_8ch_pre", "spdif_src", 0, | 328 | COMPOSITE_NOMUX(0, "spdif_8ch_pre", "spdif_src", 0, |
326 | RK3288_CLKSEL_CON(40), 0, 7, DFLAGS, | 329 | RK3288_CLKSEL_CON(40), 0, 7, DFLAGS, |
327 | RK3288_CLKGATE_CON(4), 7, GFLAGS), | 330 | RK3288_CLKGATE_CON(4), 7, GFLAGS), |
328 | COMPOSITE_FRAC(0, "spdif_8ch_frac", "spdif_8ch_src", 0, | 331 | COMPOSITE_FRAC(0, "spdif_8ch_frac", "spdif_8ch_pre", 0, |
329 | RK3288_CLKSEL_CON(41), 0, | 332 | RK3288_CLKSEL_CON(41), 0, |
330 | RK3288_CLKGATE_CON(4), 8, GFLAGS), | 333 | RK3288_CLKGATE_CON(4), 8, GFLAGS), |
331 | COMPOSITE_NODIV(SCLK_SPDIF8CH, "sclk_spdif_8ch", mux_spdif_8ch_p, 0, | 334 | COMPOSITE_NODIV(SCLK_SPDIF8CH, "sclk_spdif_8ch", mux_spdif_8ch_p, 0, |
@@ -373,12 +376,12 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = { | |||
373 | GATE(HCLK_VCODEC, "hclk_vcodec", "hclk_vcodec_pre", 0, | 376 | GATE(HCLK_VCODEC, "hclk_vcodec", "hclk_vcodec_pre", 0, |
374 | RK3288_CLKGATE_CON(9), 1, GFLAGS), | 377 | RK3288_CLKGATE_CON(9), 1, GFLAGS), |
375 | 378 | ||
376 | COMPOSITE(0, "aclk_vio0", mux_pll_src_cpll_gpll_usb480m_p, 0, | 379 | COMPOSITE(0, "aclk_vio0", mux_pll_src_cpll_gpll_usb480m_p, CLK_IGNORE_UNUSED, |
377 | RK3288_CLKSEL_CON(31), 6, 2, MFLAGS, 0, 5, DFLAGS, | 380 | RK3288_CLKSEL_CON(31), 6, 2, MFLAGS, 0, 5, DFLAGS, |
378 | RK3288_CLKGATE_CON(3), 0, GFLAGS), | 381 | RK3288_CLKGATE_CON(3), 0, GFLAGS), |
379 | DIV(0, "hclk_vio", "aclk_vio0", 0, | 382 | DIV(0, "hclk_vio", "aclk_vio0", 0, |
380 | RK3288_CLKSEL_CON(28), 8, 5, DFLAGS), | 383 | RK3288_CLKSEL_CON(28), 8, 5, DFLAGS), |
381 | COMPOSITE(0, "aclk_vio1", mux_pll_src_cpll_gpll_usb480m_p, 0, | 384 | COMPOSITE(0, "aclk_vio1", mux_pll_src_cpll_gpll_usb480m_p, CLK_IGNORE_UNUSED, |
382 | RK3288_CLKSEL_CON(31), 14, 2, MFLAGS, 8, 5, DFLAGS, | 385 | RK3288_CLKSEL_CON(31), 14, 2, MFLAGS, 8, 5, DFLAGS, |
383 | RK3288_CLKGATE_CON(3), 2, GFLAGS), | 386 | RK3288_CLKGATE_CON(3), 2, GFLAGS), |
384 | 387 | ||
@@ -436,24 +439,24 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = { | |||
436 | 439 | ||
437 | DIV(0, "pclk_pd_alive", "gpll", 0, | 440 | DIV(0, "pclk_pd_alive", "gpll", 0, |
438 | RK3288_CLKSEL_CON(33), 8, 5, DFLAGS), | 441 | RK3288_CLKSEL_CON(33), 8, 5, DFLAGS), |
439 | COMPOSITE_NOMUX(0, "pclk_pd_pmu", "gpll", 0, | 442 | COMPOSITE_NOMUX(0, "pclk_pd_pmu", "gpll", CLK_IGNORE_UNUSED, |
440 | RK3288_CLKSEL_CON(33), 0, 5, DFLAGS, | 443 | RK3288_CLKSEL_CON(33), 0, 5, DFLAGS, |
441 | RK3288_CLKGATE_CON(5), 8, GFLAGS), | 444 | RK3288_CLKGATE_CON(5), 8, GFLAGS), |
442 | 445 | ||
443 | COMPOSITE(SCLK_GPU, "sclk_gpu", mux_pll_src_cpll_gpll_usb480m_p, 0, | 446 | COMPOSITE(SCLK_GPU, "sclk_gpu", mux_pll_src_cpll_gll_usb_npll_p, 0, |
444 | RK3288_CLKSEL_CON(34), 6, 2, MFLAGS, 0, 5, DFLAGS, | 447 | RK3288_CLKSEL_CON(34), 6, 2, MFLAGS, 0, 5, DFLAGS, |
445 | RK3288_CLKGATE_CON(5), 7, GFLAGS), | 448 | RK3288_CLKGATE_CON(5), 7, GFLAGS), |
446 | 449 | ||
447 | COMPOSITE(0, "aclk_peri_src", mux_pll_src_cpll_gpll_p, 0, | 450 | COMPOSITE(0, "aclk_peri_src", mux_pll_src_cpll_gpll_p, CLK_IGNORE_UNUSED, |
448 | RK3288_CLKSEL_CON(10), 15, 1, MFLAGS, 0, 5, DFLAGS, | 451 | RK3288_CLKSEL_CON(10), 15, 1, MFLAGS, 0, 5, DFLAGS, |
449 | RK3288_CLKGATE_CON(2), 0, GFLAGS), | 452 | RK3288_CLKGATE_CON(2), 0, GFLAGS), |
450 | COMPOSITE_NOMUX(PCLK_PERI, "pclk_peri", "aclk_peri_src", 0, | 453 | COMPOSITE_NOMUX(PCLK_PERI, "pclk_peri", "aclk_peri_src", 0, |
451 | RK3288_CLKSEL_CON(10), 12, 2, DFLAGS | CLK_DIVIDER_POWER_OF_TWO, | 454 | RK3288_CLKSEL_CON(10), 12, 2, DFLAGS | CLK_DIVIDER_POWER_OF_TWO, |
452 | RK3288_CLKGATE_CON(2), 3, GFLAGS), | 455 | RK3288_CLKGATE_CON(2), 3, GFLAGS), |
453 | COMPOSITE_NOMUX(HCLK_PERI, "hclk_peri", "aclk_peri_src", 0, | 456 | COMPOSITE_NOMUX(HCLK_PERI, "hclk_peri", "aclk_peri_src", CLK_IGNORE_UNUSED, |
454 | RK3288_CLKSEL_CON(10), 8, 2, DFLAGS | CLK_DIVIDER_POWER_OF_TWO, | 457 | RK3288_CLKSEL_CON(10), 8, 2, DFLAGS | CLK_DIVIDER_POWER_OF_TWO, |
455 | RK3288_CLKGATE_CON(2), 2, GFLAGS), | 458 | RK3288_CLKGATE_CON(2), 2, GFLAGS), |
456 | GATE(ACLK_PERI, "aclk_peri", "aclk_peri_src", 0, | 459 | GATE(ACLK_PERI, "aclk_peri", "aclk_peri_src", CLK_IGNORE_UNUSED, |
457 | RK3288_CLKGATE_CON(2), 1, GFLAGS), | 460 | RK3288_CLKGATE_CON(2), 1, GFLAGS), |
458 | 461 | ||
459 | /* | 462 | /* |
@@ -483,6 +486,18 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = { | |||
483 | RK3288_CLKSEL_CON(12), 14, 2, MFLAGS, 8, 6, DFLAGS, | 486 | RK3288_CLKSEL_CON(12), 14, 2, MFLAGS, 8, 6, DFLAGS, |
484 | RK3288_CLKGATE_CON(13), 3, GFLAGS), | 487 | RK3288_CLKGATE_CON(13), 3, GFLAGS), |
485 | 488 | ||
489 | MMC(SCLK_SDMMC_DRV, "sdmmc_drv", "sclk_sdmmc", RK3288_SDMMC_CON0, 1), | ||
490 | MMC(SCLK_SDMMC_SAMPLE, "sdmmc_sample", "sclk_sdmmc", RK3288_SDMMC_CON1, 0), | ||
491 | |||
492 | MMC(SCLK_SDIO0_DRV, "sdio0_drv", "sclk_sdio0", RK3288_SDIO0_CON0, 1), | ||
493 | MMC(SCLK_SDIO0_SAMPLE, "sdio0_sample", "sclk_sdio0", RK3288_SDIO0_CON1, 0), | ||
494 | |||
495 | MMC(SCLK_SDIO1_DRV, "sdio1_drv", "sclk_sdio1", RK3288_SDIO1_CON0, 1), | ||
496 | MMC(SCLK_SDIO1_SAMPLE, "sdio1_sample", "sclk_sdio1", RK3288_SDIO1_CON1, 0), | ||
497 | |||
498 | MMC(SCLK_EMMC_DRV, "emmc_drv", "sclk_emmc", RK3288_EMMC_CON0, 1), | ||
499 | MMC(SCLK_EMMC_SAMPLE, "emmc_sample", "sclk_emmc", RK3288_EMMC_CON1, 0), | ||
500 | |||
486 | COMPOSITE(0, "sclk_tspout", mux_tspout_p, 0, | 501 | COMPOSITE(0, "sclk_tspout", mux_tspout_p, 0, |
487 | RK3288_CLKSEL_CON(35), 14, 2, MFLAGS, 8, 5, DFLAGS, | 502 | RK3288_CLKSEL_CON(35), 14, 2, MFLAGS, 8, 5, DFLAGS, |
488 | RK3288_CLKGATE_CON(4), 11, GFLAGS), | 503 | RK3288_CLKGATE_CON(4), 11, GFLAGS), |
@@ -490,13 +505,13 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = { | |||
490 | RK3288_CLKSEL_CON(35), 6, 2, MFLAGS, 0, 5, DFLAGS, | 505 | RK3288_CLKSEL_CON(35), 6, 2, MFLAGS, 0, 5, DFLAGS, |
491 | RK3288_CLKGATE_CON(4), 10, GFLAGS), | 506 | RK3288_CLKGATE_CON(4), 10, GFLAGS), |
492 | 507 | ||
493 | GATE(SCLK_OTGPHY0, "sclk_otgphy0", "usb480m", 0, | 508 | GATE(SCLK_OTGPHY0, "sclk_otgphy0", "usb480m", CLK_IGNORE_UNUSED, |
494 | RK3288_CLKGATE_CON(13), 4, GFLAGS), | 509 | RK3288_CLKGATE_CON(13), 4, GFLAGS), |
495 | GATE(SCLK_OTGPHY1, "sclk_otgphy1", "usb480m", 0, | 510 | GATE(SCLK_OTGPHY1, "sclk_otgphy1", "usb480m", CLK_IGNORE_UNUSED, |
496 | RK3288_CLKGATE_CON(13), 5, GFLAGS), | 511 | RK3288_CLKGATE_CON(13), 5, GFLAGS), |
497 | GATE(SCLK_OTGPHY2, "sclk_otgphy2", "usb480m", 0, | 512 | GATE(SCLK_OTGPHY2, "sclk_otgphy2", "usb480m", CLK_IGNORE_UNUSED, |
498 | RK3288_CLKGATE_CON(13), 6, GFLAGS), | 513 | RK3288_CLKGATE_CON(13), 6, GFLAGS), |
499 | GATE(SCLK_OTG_ADP, "sclk_otg_adp", "xin32k", 0, | 514 | GATE(SCLK_OTG_ADP, "sclk_otg_adp", "xin32k", CLK_IGNORE_UNUSED, |
500 | RK3288_CLKGATE_CON(13), 7, GFLAGS), | 515 | RK3288_CLKGATE_CON(13), 7, GFLAGS), |
501 | 516 | ||
502 | COMPOSITE_NOMUX(SCLK_TSADC, "sclk_tsadc", "xin32k", 0, | 517 | COMPOSITE_NOMUX(SCLK_TSADC, "sclk_tsadc", "xin32k", 0, |
@@ -517,7 +532,7 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = { | |||
517 | RK3288_CLKSEL_CON(38), 15, 1, MFLAGS, 8, 5, DFLAGS, | 532 | RK3288_CLKSEL_CON(38), 15, 1, MFLAGS, 8, 5, DFLAGS, |
518 | RK3288_CLKGATE_CON(5), 6, GFLAGS), | 533 | RK3288_CLKGATE_CON(5), 6, GFLAGS), |
519 | 534 | ||
520 | COMPOSITE(0, "uart0_src", mux_uart0_pll_p, 0, | 535 | COMPOSITE(0, "uart0_src", mux_pll_src_cpll_gll_usb_npll_p, 0, |
521 | RK3288_CLKSEL_CON(13), 13, 2, MFLAGS, 0, 7, DFLAGS, | 536 | RK3288_CLKSEL_CON(13), 13, 2, MFLAGS, 0, 7, DFLAGS, |
522 | RK3288_CLKGATE_CON(1), 8, GFLAGS), | 537 | RK3288_CLKGATE_CON(1), 8, GFLAGS), |
523 | COMPOSITE_FRAC(0, "uart0_frac", "uart0_src", 0, | 538 | COMPOSITE_FRAC(0, "uart0_frac", "uart0_src", 0, |
@@ -585,7 +600,7 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = { | |||
585 | 600 | ||
586 | COMPOSITE_NODIV(0, "usbphy480m_src", mux_usbphy480m_p, 0, | 601 | COMPOSITE_NODIV(0, "usbphy480m_src", mux_usbphy480m_p, 0, |
587 | RK3288_CLKSEL_CON(13), 11, 2, MFLAGS, | 602 | RK3288_CLKSEL_CON(13), 11, 2, MFLAGS, |
588 | RK3288_CLKGATE_CON(5), 15, GFLAGS), | 603 | RK3288_CLKGATE_CON(5), 14, GFLAGS), |
589 | COMPOSITE_NODIV(SCLK_HSICPHY480M, "sclk_hsicphy480m", mux_hsicphy480m_p, 0, | 604 | COMPOSITE_NODIV(SCLK_HSICPHY480M, "sclk_hsicphy480m", mux_hsicphy480m_p, 0, |
590 | RK3288_CLKSEL_CON(29), 0, 2, MFLAGS, | 605 | RK3288_CLKSEL_CON(29), 0, 2, MFLAGS, |
591 | RK3288_CLKGATE_CON(3), 6, GFLAGS), | 606 | RK3288_CLKGATE_CON(3), 6, GFLAGS), |
@@ -601,19 +616,19 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = { | |||
601 | */ | 616 | */ |
602 | 617 | ||
603 | /* aclk_cpu gates */ | 618 | /* aclk_cpu gates */ |
604 | GATE(0, "sclk_intmem0", "aclk_cpu", 0, RK3288_CLKGATE_CON(10), 5, GFLAGS), | 619 | GATE(0, "sclk_intmem0", "aclk_cpu", CLK_IGNORE_UNUSED, RK3288_CLKGATE_CON(10), 5, GFLAGS), |
605 | GATE(0, "sclk_intmem1", "aclk_cpu", 0, RK3288_CLKGATE_CON(10), 6, GFLAGS), | 620 | GATE(0, "sclk_intmem1", "aclk_cpu", CLK_IGNORE_UNUSED, RK3288_CLKGATE_CON(10), 6, GFLAGS), |
606 | GATE(0, "sclk_intmem2", "aclk_cpu", 0, RK3288_CLKGATE_CON(10), 7, GFLAGS), | 621 | GATE(0, "sclk_intmem2", "aclk_cpu", CLK_IGNORE_UNUSED, RK3288_CLKGATE_CON(10), 7, GFLAGS), |
607 | GATE(ACLK_DMAC1, "aclk_dmac1", "aclk_cpu", 0, RK3288_CLKGATE_CON(10), 12, GFLAGS), | 622 | GATE(ACLK_DMAC1, "aclk_dmac1", "aclk_cpu", 0, RK3288_CLKGATE_CON(10), 12, GFLAGS), |
608 | GATE(0, "aclk_strc_sys", "aclk_cpu", 0, RK3288_CLKGATE_CON(10), 13, GFLAGS), | 623 | GATE(0, "aclk_strc_sys", "aclk_cpu", CLK_IGNORE_UNUSED, RK3288_CLKGATE_CON(10), 13, GFLAGS), |
609 | GATE(0, "aclk_intmem", "aclk_cpu", 0, RK3288_CLKGATE_CON(10), 4, GFLAGS), | 624 | GATE(0, "aclk_intmem", "aclk_cpu", CLK_IGNORE_UNUSED, RK3288_CLKGATE_CON(10), 4, GFLAGS), |
610 | GATE(ACLK_CRYPTO, "aclk_crypto", "aclk_cpu", 0, RK3288_CLKGATE_CON(11), 6, GFLAGS), | 625 | GATE(ACLK_CRYPTO, "aclk_crypto", "aclk_cpu", 0, RK3288_CLKGATE_CON(11), 6, GFLAGS), |
611 | GATE(0, "aclk_ccp", "aclk_cpu", 0, RK3288_CLKGATE_CON(11), 8, GFLAGS), | 626 | GATE(0, "aclk_ccp", "aclk_cpu", 0, RK3288_CLKGATE_CON(11), 8, GFLAGS), |
612 | 627 | ||
613 | /* hclk_cpu gates */ | 628 | /* hclk_cpu gates */ |
614 | GATE(HCLK_CRYPTO, "hclk_crypto", "hclk_cpu", 0, RK3288_CLKGATE_CON(11), 7, GFLAGS), | 629 | GATE(HCLK_CRYPTO, "hclk_crypto", "hclk_cpu", 0, RK3288_CLKGATE_CON(11), 7, GFLAGS), |
615 | GATE(HCLK_I2S0, "hclk_i2s0", "hclk_cpu", 0, RK3288_CLKGATE_CON(10), 8, GFLAGS), | 630 | GATE(HCLK_I2S0, "hclk_i2s0", "hclk_cpu", 0, RK3288_CLKGATE_CON(10), 8, GFLAGS), |
616 | GATE(HCLK_ROM, "hclk_rom", "hclk_cpu", 0, RK3288_CLKGATE_CON(10), 9, GFLAGS), | 631 | GATE(HCLK_ROM, "hclk_rom", "hclk_cpu", CLK_IGNORE_UNUSED, RK3288_CLKGATE_CON(10), 9, GFLAGS), |
617 | GATE(HCLK_SPDIF, "hclk_spdif", "hclk_cpu", 0, RK3288_CLKGATE_CON(10), 10, GFLAGS), | 632 | GATE(HCLK_SPDIF, "hclk_spdif", "hclk_cpu", 0, RK3288_CLKGATE_CON(10), 10, GFLAGS), |
618 | GATE(HCLK_SPDIF8CH, "hclk_spdif_8ch", "hclk_cpu", 0, RK3288_CLKGATE_CON(10), 11, GFLAGS), | 633 | GATE(HCLK_SPDIF8CH, "hclk_spdif_8ch", "hclk_cpu", 0, RK3288_CLKGATE_CON(10), 11, GFLAGS), |
619 | 634 | ||
@@ -622,42 +637,42 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = { | |||
622 | GATE(PCLK_TIMER, "pclk_timer", "pclk_cpu", 0, RK3288_CLKGATE_CON(10), 1, GFLAGS), | 637 | GATE(PCLK_TIMER, "pclk_timer", "pclk_cpu", 0, RK3288_CLKGATE_CON(10), 1, GFLAGS), |
623 | GATE(PCLK_I2C0, "pclk_i2c0", "pclk_cpu", 0, RK3288_CLKGATE_CON(10), 2, GFLAGS), | 638 | GATE(PCLK_I2C0, "pclk_i2c0", "pclk_cpu", 0, RK3288_CLKGATE_CON(10), 2, GFLAGS), |
624 | GATE(PCLK_I2C2, "pclk_i2c2", "pclk_cpu", 0, RK3288_CLKGATE_CON(10), 3, GFLAGS), | 639 | GATE(PCLK_I2C2, "pclk_i2c2", "pclk_cpu", 0, RK3288_CLKGATE_CON(10), 3, GFLAGS), |
625 | GATE(0, "pclk_ddrupctl0", "pclk_cpu", 0, RK3288_CLKGATE_CON(10), 14, GFLAGS), | 640 | GATE(PCLK_DDRUPCTL0, "pclk_ddrupctl0", "pclk_cpu", 0, RK3288_CLKGATE_CON(10), 14, GFLAGS), |
626 | GATE(0, "pclk_publ0", "pclk_cpu", 0, RK3288_CLKGATE_CON(10), 15, GFLAGS), | 641 | GATE(PCLK_PUBL0, "pclk_publ0", "pclk_cpu", 0, RK3288_CLKGATE_CON(10), 15, GFLAGS), |
627 | GATE(0, "pclk_ddrupctl1", "pclk_cpu", 0, RK3288_CLKGATE_CON(11), 0, GFLAGS), | 642 | GATE(PCLK_DDRUPCTL1, "pclk_ddrupctl1", "pclk_cpu", 0, RK3288_CLKGATE_CON(11), 0, GFLAGS), |
628 | GATE(0, "pclk_publ1", "pclk_cpu", 0, RK3288_CLKGATE_CON(11), 1, GFLAGS), | 643 | GATE(PCLK_PUBL1, "pclk_publ1", "pclk_cpu", 0, RK3288_CLKGATE_CON(11), 1, GFLAGS), |
629 | GATE(0, "pclk_efuse_1024", "pclk_cpu", 0, RK3288_CLKGATE_CON(11), 2, GFLAGS), | 644 | GATE(0, "pclk_efuse_1024", "pclk_cpu", 0, RK3288_CLKGATE_CON(11), 2, GFLAGS), |
630 | GATE(PCLK_TZPC, "pclk_tzpc", "pclk_cpu", 0, RK3288_CLKGATE_CON(11), 3, GFLAGS), | 645 | GATE(PCLK_TZPC, "pclk_tzpc", "pclk_cpu", 0, RK3288_CLKGATE_CON(11), 3, GFLAGS), |
631 | GATE(PCLK_UART2, "pclk_uart2", "pclk_cpu", 0, RK3288_CLKGATE_CON(11), 9, GFLAGS), | 646 | GATE(PCLK_UART2, "pclk_uart2", "pclk_cpu", 0, RK3288_CLKGATE_CON(11), 9, GFLAGS), |
632 | GATE(0, "pclk_efuse_256", "pclk_cpu", 0, RK3288_CLKGATE_CON(11), 10, GFLAGS), | 647 | GATE(0, "pclk_efuse_256", "pclk_cpu", 0, RK3288_CLKGATE_CON(11), 10, GFLAGS), |
633 | GATE(PCLK_RKPWM, "pclk_rkpwm", "pclk_cpu", 0, RK3288_CLKGATE_CON(11), 11, GFLAGS), | 648 | GATE(PCLK_RKPWM, "pclk_rkpwm", "pclk_cpu", CLK_IGNORE_UNUSED, RK3288_CLKGATE_CON(11), 11, GFLAGS), |
634 | 649 | ||
635 | /* ddrctrl [DDR Controller PHY clock] gates */ | 650 | /* ddrctrl [DDR Controller PHY clock] gates */ |
636 | GATE(0, "nclk_ddrupctl0", "ddrphy", 0, RK3288_CLKGATE_CON(11), 4, GFLAGS), | 651 | GATE(0, "nclk_ddrupctl0", "ddrphy", CLK_IGNORE_UNUSED, RK3288_CLKGATE_CON(11), 4, GFLAGS), |
637 | GATE(0, "nclk_ddrupctl1", "ddrphy", 0, RK3288_CLKGATE_CON(11), 5, GFLAGS), | 652 | GATE(0, "nclk_ddrupctl1", "ddrphy", CLK_IGNORE_UNUSED, RK3288_CLKGATE_CON(11), 5, GFLAGS), |
638 | 653 | ||
639 | /* ddrphy gates */ | 654 | /* ddrphy gates */ |
640 | GATE(0, "sclk_ddrphy0", "ddrphy", 0, RK3288_CLKGATE_CON(4), 12, GFLAGS), | 655 | GATE(0, "sclk_ddrphy0", "ddrphy", CLK_IGNORE_UNUSED, RK3288_CLKGATE_CON(4), 12, GFLAGS), |
641 | GATE(0, "sclk_ddrphy1", "ddrphy", 0, RK3288_CLKGATE_CON(4), 13, GFLAGS), | 656 | GATE(0, "sclk_ddrphy1", "ddrphy", CLK_IGNORE_UNUSED, RK3288_CLKGATE_CON(4), 13, GFLAGS), |
642 | 657 | ||
643 | /* aclk_peri gates */ | 658 | /* aclk_peri gates */ |
644 | GATE(0, "aclk_peri_axi_matrix", "aclk_peri", 0, RK3288_CLKGATE_CON(6), 2, GFLAGS), | 659 | GATE(0, "aclk_peri_axi_matrix", "aclk_peri", CLK_IGNORE_UNUSED, RK3288_CLKGATE_CON(6), 2, GFLAGS), |
645 | GATE(ACLK_DMAC2, "aclk_dmac2", "aclk_peri", 0, RK3288_CLKGATE_CON(6), 3, GFLAGS), | 660 | GATE(ACLK_DMAC2, "aclk_dmac2", "aclk_peri", 0, RK3288_CLKGATE_CON(6), 3, GFLAGS), |
646 | GATE(0, "aclk_peri_niu", "aclk_peri", 0, RK3288_CLKGATE_CON(7), 11, GFLAGS), | 661 | GATE(0, "aclk_peri_niu", "aclk_peri", CLK_IGNORE_UNUSED, RK3288_CLKGATE_CON(7), 11, GFLAGS), |
647 | GATE(ACLK_MMU, "aclk_mmu", "aclk_peri", 0, RK3288_CLKGATE_CON(8), 12, GFLAGS), | 662 | GATE(ACLK_MMU, "aclk_mmu", "aclk_peri", CLK_IGNORE_UNUSED, RK3288_CLKGATE_CON(8), 12, GFLAGS), |
648 | GATE(ACLK_GMAC, "aclk_gmac", "aclk_peri", 0, RK3288_CLKGATE_CON(8), 0, GFLAGS), | 663 | GATE(ACLK_GMAC, "aclk_gmac", "aclk_peri", 0, RK3288_CLKGATE_CON(8), 0, GFLAGS), |
649 | GATE(HCLK_GPS, "hclk_gps", "aclk_peri", 0, RK3288_CLKGATE_CON(8), 2, GFLAGS), | 664 | GATE(HCLK_GPS, "hclk_gps", "aclk_peri", 0, RK3288_CLKGATE_CON(8), 2, GFLAGS), |
650 | 665 | ||
651 | /* hclk_peri gates */ | 666 | /* hclk_peri gates */ |
652 | GATE(0, "hclk_peri_matrix", "hclk_peri", 0, RK3288_CLKGATE_CON(6), 0, GFLAGS), | 667 | GATE(0, "hclk_peri_matrix", "hclk_peri", CLK_IGNORE_UNUSED, RK3288_CLKGATE_CON(6), 0, GFLAGS), |
653 | GATE(HCLK_OTG0, "hclk_otg0", "hclk_peri", 0, RK3288_CLKGATE_CON(7), 4, GFLAGS), | 668 | GATE(HCLK_OTG0, "hclk_otg0", "hclk_peri", CLK_IGNORE_UNUSED, RK3288_CLKGATE_CON(7), 4, GFLAGS), |
654 | GATE(HCLK_USBHOST0, "hclk_host0", "hclk_peri", 0, RK3288_CLKGATE_CON(7), 6, GFLAGS), | 669 | GATE(HCLK_USBHOST0, "hclk_host0", "hclk_peri", 0, RK3288_CLKGATE_CON(7), 6, GFLAGS), |
655 | GATE(HCLK_USBHOST1, "hclk_host1", "hclk_peri", 0, RK3288_CLKGATE_CON(7), 7, GFLAGS), | 670 | GATE(HCLK_USBHOST1, "hclk_host1", "hclk_peri", CLK_IGNORE_UNUSED, RK3288_CLKGATE_CON(7), 7, GFLAGS), |
656 | GATE(HCLK_HSIC, "hclk_hsic", "hclk_peri", 0, RK3288_CLKGATE_CON(7), 8, GFLAGS), | 671 | GATE(HCLK_HSIC, "hclk_hsic", "hclk_peri", 0, RK3288_CLKGATE_CON(7), 8, GFLAGS), |
657 | GATE(0, "hclk_usb_peri", "hclk_peri", 0, RK3288_CLKGATE_CON(7), 9, GFLAGS), | 672 | GATE(0, "hclk_usb_peri", "hclk_peri", CLK_IGNORE_UNUSED, RK3288_CLKGATE_CON(7), 9, GFLAGS), |
658 | GATE(0, "hclk_peri_ahb_arbi", "hclk_peri", 0, RK3288_CLKGATE_CON(7), 10, GFLAGS), | 673 | GATE(0, "hclk_peri_ahb_arbi", "hclk_peri", CLK_IGNORE_UNUSED, RK3288_CLKGATE_CON(7), 10, GFLAGS), |
659 | GATE(0, "hclk_emem", "hclk_peri", 0, RK3288_CLKGATE_CON(7), 12, GFLAGS), | 674 | GATE(0, "hclk_emem", "hclk_peri", CLK_IGNORE_UNUSED, RK3288_CLKGATE_CON(7), 12, GFLAGS), |
660 | GATE(0, "hclk_mem", "hclk_peri", 0, RK3288_CLKGATE_CON(7), 13, GFLAGS), | 675 | GATE(0, "hclk_mem", "hclk_peri", CLK_IGNORE_UNUSED, RK3288_CLKGATE_CON(7), 13, GFLAGS), |
661 | GATE(HCLK_NANDC0, "hclk_nandc0", "hclk_peri", 0, RK3288_CLKGATE_CON(7), 14, GFLAGS), | 676 | GATE(HCLK_NANDC0, "hclk_nandc0", "hclk_peri", 0, RK3288_CLKGATE_CON(7), 14, GFLAGS), |
662 | GATE(HCLK_NANDC1, "hclk_nandc1", "hclk_peri", 0, RK3288_CLKGATE_CON(7), 15, GFLAGS), | 677 | GATE(HCLK_NANDC1, "hclk_nandc1", "hclk_peri", 0, RK3288_CLKGATE_CON(7), 15, GFLAGS), |
663 | GATE(HCLK_TSP, "hclk_tsp", "hclk_peri", 0, RK3288_CLKGATE_CON(8), 8, GFLAGS), | 678 | GATE(HCLK_TSP, "hclk_tsp", "hclk_peri", 0, RK3288_CLKGATE_CON(8), 8, GFLAGS), |
@@ -669,7 +684,7 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = { | |||
669 | GATE(0, "pmu_hclk_otg0", "hclk_peri", 0, RK3288_CLKGATE_CON(7), 5, GFLAGS), | 684 | GATE(0, "pmu_hclk_otg0", "hclk_peri", 0, RK3288_CLKGATE_CON(7), 5, GFLAGS), |
670 | 685 | ||
671 | /* pclk_peri gates */ | 686 | /* pclk_peri gates */ |
672 | GATE(0, "pclk_peri_matrix", "pclk_peri", 0, RK3288_CLKGATE_CON(6), 1, GFLAGS), | 687 | GATE(0, "pclk_peri_matrix", "pclk_peri", CLK_IGNORE_UNUSED, RK3288_CLKGATE_CON(6), 1, GFLAGS), |
673 | GATE(PCLK_SPI0, "pclk_spi0", "pclk_peri", 0, RK3288_CLKGATE_CON(6), 4, GFLAGS), | 688 | GATE(PCLK_SPI0, "pclk_spi0", "pclk_peri", 0, RK3288_CLKGATE_CON(6), 4, GFLAGS), |
674 | GATE(PCLK_SPI1, "pclk_spi1", "pclk_peri", 0, RK3288_CLKGATE_CON(6), 5, GFLAGS), | 689 | GATE(PCLK_SPI1, "pclk_spi1", "pclk_peri", 0, RK3288_CLKGATE_CON(6), 5, GFLAGS), |
675 | GATE(PCLK_SPI2, "pclk_spi2", "pclk_peri", 0, RK3288_CLKGATE_CON(6), 6, GFLAGS), | 690 | GATE(PCLK_SPI2, "pclk_spi2", "pclk_peri", 0, RK3288_CLKGATE_CON(6), 6, GFLAGS), |
@@ -705,48 +720,48 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = { | |||
705 | GATE(PCLK_GPIO4, "pclk_gpio4", "pclk_pd_alive", 0, RK3288_CLKGATE_CON(14), 4, GFLAGS), | 720 | GATE(PCLK_GPIO4, "pclk_gpio4", "pclk_pd_alive", 0, RK3288_CLKGATE_CON(14), 4, GFLAGS), |
706 | GATE(PCLK_GPIO5, "pclk_gpio5", "pclk_pd_alive", 0, RK3288_CLKGATE_CON(14), 5, GFLAGS), | 721 | GATE(PCLK_GPIO5, "pclk_gpio5", "pclk_pd_alive", 0, RK3288_CLKGATE_CON(14), 5, GFLAGS), |
707 | GATE(PCLK_GPIO6, "pclk_gpio6", "pclk_pd_alive", 0, RK3288_CLKGATE_CON(14), 6, GFLAGS), | 722 | GATE(PCLK_GPIO6, "pclk_gpio6", "pclk_pd_alive", 0, RK3288_CLKGATE_CON(14), 6, GFLAGS), |
708 | GATE(PCLK_GRF, "pclk_grf", "pclk_pd_alive", 0, RK3288_CLKGATE_CON(14), 11, GFLAGS), | 723 | GATE(PCLK_GRF, "pclk_grf", "pclk_pd_alive", CLK_IGNORE_UNUSED, RK3288_CLKGATE_CON(14), 11, GFLAGS), |
709 | GATE(0, "pclk_alive_niu", "pclk_pd_alive", 0, RK3288_CLKGATE_CON(14), 12, GFLAGS), | 724 | GATE(0, "pclk_alive_niu", "pclk_pd_alive", CLK_IGNORE_UNUSED, RK3288_CLKGATE_CON(14), 12, GFLAGS), |
710 | 725 | ||
711 | /* pclk_pd_pmu gates */ | 726 | /* pclk_pd_pmu gates */ |
712 | GATE(PCLK_PMU, "pclk_pmu", "pclk_pd_pmu", 0, RK3288_CLKGATE_CON(17), 0, GFLAGS), | 727 | GATE(PCLK_PMU, "pclk_pmu", "pclk_pd_pmu", CLK_IGNORE_UNUSED, RK3288_CLKGATE_CON(17), 0, GFLAGS), |
713 | GATE(0, "pclk_intmem1", "pclk_pd_pmu", 0, RK3288_CLKGATE_CON(17), 1, GFLAGS), | 728 | GATE(0, "pclk_intmem1", "pclk_pd_pmu", CLK_IGNORE_UNUSED, RK3288_CLKGATE_CON(17), 1, GFLAGS), |
714 | GATE(0, "pclk_pmu_niu", "pclk_pd_pmu", 0, RK3288_CLKGATE_CON(17), 2, GFLAGS), | 729 | GATE(0, "pclk_pmu_niu", "pclk_pd_pmu", CLK_IGNORE_UNUSED, RK3288_CLKGATE_CON(17), 2, GFLAGS), |
715 | GATE(PCLK_SGRF, "pclk_sgrf", "pclk_pd_pmu", 0, RK3288_CLKGATE_CON(17), 3, GFLAGS), | 730 | GATE(PCLK_SGRF, "pclk_sgrf", "pclk_pd_pmu", CLK_IGNORE_UNUSED, RK3288_CLKGATE_CON(17), 3, GFLAGS), |
716 | GATE(PCLK_GPIO0, "pclk_gpio0", "pclk_pd_pmu", 0, RK3288_CLKGATE_CON(17), 4, GFLAGS), | 731 | GATE(PCLK_GPIO0, "pclk_gpio0", "pclk_pd_pmu", 0, RK3288_CLKGATE_CON(17), 4, GFLAGS), |
717 | 732 | ||
718 | /* hclk_vio gates */ | 733 | /* hclk_vio gates */ |
719 | GATE(HCLK_RGA, "hclk_rga", "hclk_vio", 0, RK3288_CLKGATE_CON(15), 1, GFLAGS), | 734 | GATE(HCLK_RGA, "hclk_rga", "hclk_vio", 0, RK3288_CLKGATE_CON(15), 1, GFLAGS), |
720 | GATE(HCLK_VOP0, "hclk_vop0", "hclk_vio", 0, RK3288_CLKGATE_CON(15), 6, GFLAGS), | 735 | GATE(HCLK_VOP0, "hclk_vop0", "hclk_vio", 0, RK3288_CLKGATE_CON(15), 6, GFLAGS), |
721 | GATE(HCLK_VOP1, "hclk_vop1", "hclk_vio", 0, RK3288_CLKGATE_CON(15), 8, GFLAGS), | 736 | GATE(HCLK_VOP1, "hclk_vop1", "hclk_vio", 0, RK3288_CLKGATE_CON(15), 8, GFLAGS), |
722 | GATE(HCLK_VIO_AHB_ARBI, "hclk_vio_ahb_arbi", "hclk_vio", 0, RK3288_CLKGATE_CON(15), 9, GFLAGS), | 737 | GATE(HCLK_VIO_AHB_ARBI, "hclk_vio_ahb_arbi", "hclk_vio", CLK_IGNORE_UNUSED, RK3288_CLKGATE_CON(15), 9, GFLAGS), |
723 | GATE(HCLK_VIO_NIU, "hclk_vio_niu", "hclk_vio", 0, RK3288_CLKGATE_CON(15), 10, GFLAGS), | 738 | GATE(HCLK_VIO_NIU, "hclk_vio_niu", "hclk_vio", CLK_IGNORE_UNUSED, RK3288_CLKGATE_CON(15), 10, GFLAGS), |
724 | GATE(HCLK_VIP, "hclk_vip", "hclk_vio", 0, RK3288_CLKGATE_CON(15), 15, GFLAGS), | 739 | GATE(HCLK_VIP, "hclk_vip", "hclk_vio", 0, RK3288_CLKGATE_CON(15), 15, GFLAGS), |
725 | GATE(HCLK_IEP, "hclk_iep", "hclk_vio", 0, RK3288_CLKGATE_CON(15), 3, GFLAGS), | 740 | GATE(HCLK_IEP, "hclk_iep", "hclk_vio", 0, RK3288_CLKGATE_CON(15), 3, GFLAGS), |
726 | GATE(HCLK_ISP, "hclk_isp", "hclk_vio", 0, RK3288_CLKGATE_CON(16), 1, GFLAGS), | 741 | GATE(HCLK_ISP, "hclk_isp", "hclk_vio", 0, RK3288_CLKGATE_CON(16), 1, GFLAGS), |
727 | GATE(HCLK_VIO2_H2P, "hclk_vio2_h2p", "hclk_vio", 0, RK3288_CLKGATE_CON(16), 10, GFLAGS), | 742 | GATE(HCLK_VIO2_H2P, "hclk_vio2_h2p", "hclk_vio", CLK_IGNORE_UNUSED, RK3288_CLKGATE_CON(16), 10, GFLAGS), |
728 | GATE(PCLK_MIPI_DSI0, "pclk_mipi_dsi0", "hclk_vio", 0, RK3288_CLKGATE_CON(16), 4, GFLAGS), | 743 | GATE(PCLK_MIPI_DSI0, "pclk_mipi_dsi0", "hclk_vio", 0, RK3288_CLKGATE_CON(16), 4, GFLAGS), |
729 | GATE(PCLK_MIPI_DSI1, "pclk_mipi_dsi1", "hclk_vio", 0, RK3288_CLKGATE_CON(16), 5, GFLAGS), | 744 | GATE(PCLK_MIPI_DSI1, "pclk_mipi_dsi1", "hclk_vio", 0, RK3288_CLKGATE_CON(16), 5, GFLAGS), |
730 | GATE(PCLK_MIPI_CSI, "pclk_mipi_csi", "hclk_vio", 0, RK3288_CLKGATE_CON(16), 6, GFLAGS), | 745 | GATE(PCLK_MIPI_CSI, "pclk_mipi_csi", "hclk_vio", 0, RK3288_CLKGATE_CON(16), 6, GFLAGS), |
731 | GATE(PCLK_LVDS_PHY, "pclk_lvds_phy", "hclk_vio", 0, RK3288_CLKGATE_CON(16), 7, GFLAGS), | 746 | GATE(PCLK_LVDS_PHY, "pclk_lvds_phy", "hclk_vio", 0, RK3288_CLKGATE_CON(16), 7, GFLAGS), |
732 | GATE(PCLK_EDP_CTRL, "pclk_edp_ctrl", "hclk_vio", 0, RK3288_CLKGATE_CON(16), 8, GFLAGS), | 747 | GATE(PCLK_EDP_CTRL, "pclk_edp_ctrl", "hclk_vio", CLK_IGNORE_UNUSED, RK3288_CLKGATE_CON(16), 8, GFLAGS), |
733 | GATE(PCLK_HDMI_CTRL, "pclk_hdmi_ctrl", "hclk_vio", 0, RK3288_CLKGATE_CON(16), 9, GFLAGS), | 748 | GATE(PCLK_HDMI_CTRL, "pclk_hdmi_ctrl", "hclk_vio", 0, RK3288_CLKGATE_CON(16), 9, GFLAGS), |
734 | GATE(PCLK_VIO2_H2P, "pclk_vio2_h2p", "hclk_vio", 0, RK3288_CLKGATE_CON(16), 11, GFLAGS), | 749 | GATE(PCLK_VIO2_H2P, "pclk_vio2_h2p", "hclk_vio", CLK_IGNORE_UNUSED, RK3288_CLKGATE_CON(16), 11, GFLAGS), |
735 | 750 | ||
736 | /* aclk_vio0 gates */ | 751 | /* aclk_vio0 gates */ |
737 | GATE(ACLK_VOP0, "aclk_vop0", "aclk_vio0", 0, RK3288_CLKGATE_CON(15), 5, GFLAGS), | 752 | GATE(ACLK_VOP0, "aclk_vop0", "aclk_vio0", 0, RK3288_CLKGATE_CON(15), 5, GFLAGS), |
738 | GATE(ACLK_IEP, "aclk_iep", "aclk_vio0", 0, RK3288_CLKGATE_CON(15), 2, GFLAGS), | 753 | GATE(ACLK_IEP, "aclk_iep", "aclk_vio0", 0, RK3288_CLKGATE_CON(15), 2, GFLAGS), |
739 | GATE(ACLK_VIO0_NIU, "aclk_vio0_niu", "aclk_vio0", 0, RK3288_CLKGATE_CON(15), 11, GFLAGS), | 754 | GATE(ACLK_VIO0_NIU, "aclk_vio0_niu", "aclk_vio0", CLK_IGNORE_UNUSED, RK3288_CLKGATE_CON(15), 11, GFLAGS), |
740 | GATE(ACLK_VIP, "aclk_vip", "aclk_vio0", 0, RK3288_CLKGATE_CON(15), 14, GFLAGS), | 755 | GATE(ACLK_VIP, "aclk_vip", "aclk_vio0", 0, RK3288_CLKGATE_CON(15), 14, GFLAGS), |
741 | 756 | ||
742 | /* aclk_vio1 gates */ | 757 | /* aclk_vio1 gates */ |
743 | GATE(ACLK_VOP1, "aclk_vop1", "aclk_vio1", 0, RK3288_CLKGATE_CON(15), 7, GFLAGS), | 758 | GATE(ACLK_VOP1, "aclk_vop1", "aclk_vio1", 0, RK3288_CLKGATE_CON(15), 7, GFLAGS), |
744 | GATE(ACLK_ISP, "aclk_isp", "aclk_vio1", 0, RK3288_CLKGATE_CON(16), 2, GFLAGS), | 759 | GATE(ACLK_ISP, "aclk_isp", "aclk_vio1", 0, RK3288_CLKGATE_CON(16), 2, GFLAGS), |
745 | GATE(ACLK_VIO1_NIU, "aclk_vio1_niu", "aclk_vio1", 0, RK3288_CLKGATE_CON(15), 12, GFLAGS), | 760 | GATE(ACLK_VIO1_NIU, "aclk_vio1_niu", "aclk_vio1", CLK_IGNORE_UNUSED, RK3288_CLKGATE_CON(15), 12, GFLAGS), |
746 | 761 | ||
747 | /* aclk_rga_pre gates */ | 762 | /* aclk_rga_pre gates */ |
748 | GATE(ACLK_RGA, "aclk_rga", "aclk_rga_pre", 0, RK3288_CLKGATE_CON(15), 0, GFLAGS), | 763 | GATE(ACLK_RGA, "aclk_rga", "aclk_rga_pre", 0, RK3288_CLKGATE_CON(15), 0, GFLAGS), |
749 | GATE(ACLK_RGA_NIU, "aclk_rga_niu", "aclk_rga_pre", 0, RK3288_CLKGATE_CON(15), 13, GFLAGS), | 764 | GATE(ACLK_RGA_NIU, "aclk_rga_niu", "aclk_rga_pre", CLK_IGNORE_UNUSED, RK3288_CLKGATE_CON(15), 13, GFLAGS), |
750 | 765 | ||
751 | /* | 766 | /* |
752 | * Other ungrouped clocks. | 767 | * Other ungrouped clocks. |
@@ -762,6 +777,64 @@ static const char *rk3288_critical_clocks[] __initconst = { | |||
762 | "hclk_peri", | 777 | "hclk_peri", |
763 | }; | 778 | }; |
764 | 779 | ||
780 | #ifdef CONFIG_PM_SLEEP | ||
781 | static void __iomem *rk3288_cru_base; | ||
782 | |||
783 | /* Some CRU registers will be reset in maskrom when the system | ||
784 | * wakes up from fastboot. | ||
785 | * So save them before suspend, restore them after resume. | ||
786 | */ | ||
787 | static const int rk3288_saved_cru_reg_ids[] = { | ||
788 | RK3288_MODE_CON, | ||
789 | RK3288_CLKSEL_CON(0), | ||
790 | RK3288_CLKSEL_CON(1), | ||
791 | RK3288_CLKSEL_CON(10), | ||
792 | RK3288_CLKSEL_CON(33), | ||
793 | RK3288_CLKSEL_CON(37), | ||
794 | }; | ||
795 | |||
796 | static u32 rk3288_saved_cru_regs[ARRAY_SIZE(rk3288_saved_cru_reg_ids)]; | ||
797 | |||
798 | static int rk3288_clk_suspend(void) | ||
799 | { | ||
800 | int i, reg_id; | ||
801 | |||
802 | for (i = 0; i < ARRAY_SIZE(rk3288_saved_cru_reg_ids); i++) { | ||
803 | reg_id = rk3288_saved_cru_reg_ids[i]; | ||
804 | |||
805 | rk3288_saved_cru_regs[i] = | ||
806 | readl_relaxed(rk3288_cru_base + reg_id); | ||
807 | } | ||
808 | return 0; | ||
809 | } | ||
810 | |||
811 | static void rk3288_clk_resume(void) | ||
812 | { | ||
813 | int i, reg_id; | ||
814 | |||
815 | for (i = ARRAY_SIZE(rk3288_saved_cru_reg_ids) - 1; i >= 0; i--) { | ||
816 | reg_id = rk3288_saved_cru_reg_ids[i]; | ||
817 | |||
818 | writel_relaxed(rk3288_saved_cru_regs[i] | 0xffff0000, | ||
819 | rk3288_cru_base + reg_id); | ||
820 | } | ||
821 | } | ||
822 | |||
823 | static struct syscore_ops rk3288_clk_syscore_ops = { | ||
824 | .suspend = rk3288_clk_suspend, | ||
825 | .resume = rk3288_clk_resume, | ||
826 | }; | ||
827 | |||
828 | static void rk3288_clk_sleep_init(void __iomem *reg_base) | ||
829 | { | ||
830 | rk3288_cru_base = reg_base; | ||
831 | register_syscore_ops(&rk3288_clk_syscore_ops); | ||
832 | } | ||
833 | |||
834 | #else /* CONFIG_PM_SLEEP */ | ||
835 | static void rk3288_clk_sleep_init(void __iomem *reg_base) {} | ||
836 | #endif | ||
837 | |||
765 | static void __init rk3288_clk_init(struct device_node *np) | 838 | static void __init rk3288_clk_init(struct device_node *np) |
766 | { | 839 | { |
767 | void __iomem *reg_base; | 840 | void __iomem *reg_base; |
@@ -810,5 +883,6 @@ static void __init rk3288_clk_init(struct device_node *np) | |||
810 | ROCKCHIP_SOFTRST_HIWORD_MASK); | 883 | ROCKCHIP_SOFTRST_HIWORD_MASK); |
811 | 884 | ||
812 | rockchip_register_restart_notifier(RK3288_GLB_SRST_FST); | 885 | rockchip_register_restart_notifier(RK3288_GLB_SRST_FST); |
886 | rk3288_clk_sleep_init(reg_base); | ||
813 | } | 887 | } |
814 | CLK_OF_DECLARE(rk3288_cru, "rockchip,rk3288-cru", rk3288_clk_init); | 888 | CLK_OF_DECLARE(rk3288_cru, "rockchip,rk3288-cru", rk3288_clk_init); |
diff --git a/drivers/clk/rockchip/clk.c b/drivers/clk/rockchip/clk.c index 880a266f0143..20e05bbb3a67 100644 --- a/drivers/clk/rockchip/clk.c +++ b/drivers/clk/rockchip/clk.c | |||
@@ -197,7 +197,8 @@ void __init rockchip_clk_register_plls(struct rockchip_pll_clock *list, | |||
197 | list->parent_names, list->num_parents, | 197 | list->parent_names, list->num_parents, |
198 | reg_base, list->con_offset, grf_lock_offset, | 198 | reg_base, list->con_offset, grf_lock_offset, |
199 | list->lock_shift, list->mode_offset, | 199 | list->lock_shift, list->mode_offset, |
200 | list->mode_shift, list->rate_table, &clk_lock); | 200 | list->mode_shift, list->rate_table, |
201 | list->pll_flags, &clk_lock); | ||
201 | if (IS_ERR(clk)) { | 202 | if (IS_ERR(clk)) { |
202 | pr_err("%s: failed to register clock %s\n", __func__, | 203 | pr_err("%s: failed to register clock %s\n", __func__, |
203 | list->name); | 204 | list->name); |
@@ -244,9 +245,6 @@ void __init rockchip_clk_register_branches( | |||
244 | list->div_flags, &clk_lock); | 245 | list->div_flags, &clk_lock); |
245 | break; | 246 | break; |
246 | case branch_fraction_divider: | 247 | case branch_fraction_divider: |
247 | /* keep all gates untouched for now */ | ||
248 | flags |= CLK_IGNORE_UNUSED; | ||
249 | |||
250 | clk = rockchip_clk_register_frac_branch(list->name, | 248 | clk = rockchip_clk_register_frac_branch(list->name, |
251 | list->parent_names, list->num_parents, | 249 | list->parent_names, list->num_parents, |
252 | reg_base, list->muxdiv_offset, list->div_flags, | 250 | reg_base, list->muxdiv_offset, list->div_flags, |
@@ -256,18 +254,12 @@ void __init rockchip_clk_register_branches( | |||
256 | case branch_gate: | 254 | case branch_gate: |
257 | flags |= CLK_SET_RATE_PARENT; | 255 | flags |= CLK_SET_RATE_PARENT; |
258 | 256 | ||
259 | /* keep all gates untouched for now */ | ||
260 | flags |= CLK_IGNORE_UNUSED; | ||
261 | |||
262 | clk = clk_register_gate(NULL, list->name, | 257 | clk = clk_register_gate(NULL, list->name, |
263 | list->parent_names[0], flags, | 258 | list->parent_names[0], flags, |
264 | reg_base + list->gate_offset, | 259 | reg_base + list->gate_offset, |
265 | list->gate_shift, list->gate_flags, &clk_lock); | 260 | list->gate_shift, list->gate_flags, &clk_lock); |
266 | break; | 261 | break; |
267 | case branch_composite: | 262 | case branch_composite: |
268 | /* keep all gates untouched for now */ | ||
269 | flags |= CLK_IGNORE_UNUSED; | ||
270 | |||
271 | clk = rockchip_clk_register_branch(list->name, | 263 | clk = rockchip_clk_register_branch(list->name, |
272 | list->parent_names, list->num_parents, | 264 | list->parent_names, list->num_parents, |
273 | reg_base, list->muxdiv_offset, list->mux_shift, | 265 | reg_base, list->muxdiv_offset, list->mux_shift, |
@@ -277,6 +269,14 @@ void __init rockchip_clk_register_branches( | |||
277 | list->gate_offset, list->gate_shift, | 269 | list->gate_offset, list->gate_shift, |
278 | list->gate_flags, flags, &clk_lock); | 270 | list->gate_flags, flags, &clk_lock); |
279 | break; | 271 | break; |
272 | case branch_mmc: | ||
273 | clk = rockchip_clk_register_mmc( | ||
274 | list->name, | ||
275 | list->parent_names, list->num_parents, | ||
276 | reg_base + list->muxdiv_offset, | ||
277 | list->div_shift | ||
278 | ); | ||
279 | break; | ||
280 | } | 280 | } |
281 | 281 | ||
282 | /* none of the cases above matched */ | 282 | /* none of the cases above matched */ |
diff --git a/drivers/clk/rockchip/clk.h b/drivers/clk/rockchip/clk.h index ca009ab0a33a..58d2e3bdf22f 100644 --- a/drivers/clk/rockchip/clk.h +++ b/drivers/clk/rockchip/clk.h | |||
@@ -48,6 +48,14 @@ | |||
48 | #define RK3288_GLB_SRST_SND 0x1b4 | 48 | #define RK3288_GLB_SRST_SND 0x1b4 |
49 | #define RK3288_SOFTRST_CON(x) (x * 0x4 + 0x1b8) | 49 | #define RK3288_SOFTRST_CON(x) (x * 0x4 + 0x1b8) |
50 | #define RK3288_MISC_CON 0x1e8 | 50 | #define RK3288_MISC_CON 0x1e8 |
51 | #define RK3288_SDMMC_CON0 0x200 | ||
52 | #define RK3288_SDMMC_CON1 0x204 | ||
53 | #define RK3288_SDIO0_CON0 0x208 | ||
54 | #define RK3288_SDIO0_CON1 0x20c | ||
55 | #define RK3288_SDIO1_CON0 0x210 | ||
56 | #define RK3288_SDIO1_CON1 0x214 | ||
57 | #define RK3288_EMMC_CON0 0x218 | ||
58 | #define RK3288_EMMC_CON1 0x21c | ||
51 | 59 | ||
52 | enum rockchip_pll_type { | 60 | enum rockchip_pll_type { |
53 | pll_rk3066, | 61 | pll_rk3066, |
@@ -62,6 +70,15 @@ enum rockchip_pll_type { | |||
62 | .bwadj = (_nf >> 1), \ | 70 | .bwadj = (_nf >> 1), \ |
63 | } | 71 | } |
64 | 72 | ||
73 | #define RK3066_PLL_RATE_BWADJ(_rate, _nr, _nf, _no, _bw) \ | ||
74 | { \ | ||
75 | .rate = _rate##U, \ | ||
76 | .nr = _nr, \ | ||
77 | .nf = _nf, \ | ||
78 | .no = _no, \ | ||
79 | .bwadj = _bw, \ | ||
80 | } | ||
81 | |||
65 | struct rockchip_pll_rate_table { | 82 | struct rockchip_pll_rate_table { |
66 | unsigned long rate; | 83 | unsigned long rate; |
67 | unsigned int nr; | 84 | unsigned int nr; |
@@ -81,7 +98,12 @@ struct rockchip_pll_rate_table { | |||
81 | * @mode_shift: offset inside the mode-register for the mode of this pll. | 98 | * @mode_shift: offset inside the mode-register for the mode of this pll. |
82 | * @lock_shift: offset inside the lock register for the lock status. | 99 | * @lock_shift: offset inside the lock register for the lock status. |
83 | * @type: Type of PLL to be registered. | 100 | * @type: Type of PLL to be registered. |
101 | * @pll_flags: hardware-specific flags | ||
84 | * @rate_table: Table of usable pll rates | 102 | * @rate_table: Table of usable pll rates |
103 | * | ||
104 | * Flags: | ||
105 | * ROCKCHIP_PLL_SYNC_RATE - check rate parameters to match against the | ||
106 | * rate_table parameters and ajust them if necessary. | ||
85 | */ | 107 | */ |
86 | struct rockchip_pll_clock { | 108 | struct rockchip_pll_clock { |
87 | unsigned int id; | 109 | unsigned int id; |
@@ -94,11 +116,14 @@ struct rockchip_pll_clock { | |||
94 | int mode_shift; | 116 | int mode_shift; |
95 | int lock_shift; | 117 | int lock_shift; |
96 | enum rockchip_pll_type type; | 118 | enum rockchip_pll_type type; |
119 | u8 pll_flags; | ||
97 | struct rockchip_pll_rate_table *rate_table; | 120 | struct rockchip_pll_rate_table *rate_table; |
98 | }; | 121 | }; |
99 | 122 | ||
123 | #define ROCKCHIP_PLL_SYNC_RATE BIT(0) | ||
124 | |||
100 | #define PLL(_type, _id, _name, _pnames, _flags, _con, _mode, _mshift, \ | 125 | #define PLL(_type, _id, _name, _pnames, _flags, _con, _mode, _mshift, \ |
101 | _lshift, _rtable) \ | 126 | _lshift, _pflags, _rtable) \ |
102 | { \ | 127 | { \ |
103 | .id = _id, \ | 128 | .id = _id, \ |
104 | .type = _type, \ | 129 | .type = _type, \ |
@@ -110,6 +135,7 @@ struct rockchip_pll_clock { | |||
110 | .mode_offset = _mode, \ | 135 | .mode_offset = _mode, \ |
111 | .mode_shift = _mshift, \ | 136 | .mode_shift = _mshift, \ |
112 | .lock_shift = _lshift, \ | 137 | .lock_shift = _lshift, \ |
138 | .pll_flags = _pflags, \ | ||
113 | .rate_table = _rtable, \ | 139 | .rate_table = _rtable, \ |
114 | } | 140 | } |
115 | 141 | ||
@@ -118,7 +144,7 @@ struct clk *rockchip_clk_register_pll(enum rockchip_pll_type pll_type, | |||
118 | void __iomem *base, int con_offset, int grf_lock_offset, | 144 | void __iomem *base, int con_offset, int grf_lock_offset, |
119 | int lock_shift, int reg_mode, int mode_shift, | 145 | int lock_shift, int reg_mode, int mode_shift, |
120 | struct rockchip_pll_rate_table *rate_table, | 146 | struct rockchip_pll_rate_table *rate_table, |
121 | spinlock_t *lock); | 147 | u8 clk_pll_flags, spinlock_t *lock); |
122 | 148 | ||
123 | struct rockchip_cpuclk_clksel { | 149 | struct rockchip_cpuclk_clksel { |
124 | int reg; | 150 | int reg; |
@@ -152,6 +178,10 @@ struct clk *rockchip_clk_register_cpuclk(const char *name, | |||
152 | const struct rockchip_cpuclk_rate_table *rates, | 178 | const struct rockchip_cpuclk_rate_table *rates, |
153 | int nrates, void __iomem *reg_base, spinlock_t *lock); | 179 | int nrates, void __iomem *reg_base, spinlock_t *lock); |
154 | 180 | ||
181 | struct clk *rockchip_clk_register_mmc(const char *name, | ||
182 | const char **parent_names, u8 num_parents, | ||
183 | void __iomem *reg, int shift); | ||
184 | |||
155 | #define PNAME(x) static const char *x[] __initconst | 185 | #define PNAME(x) static const char *x[] __initconst |
156 | 186 | ||
157 | enum rockchip_clk_branch_type { | 187 | enum rockchip_clk_branch_type { |
@@ -160,6 +190,7 @@ enum rockchip_clk_branch_type { | |||
160 | branch_divider, | 190 | branch_divider, |
161 | branch_fraction_divider, | 191 | branch_fraction_divider, |
162 | branch_gate, | 192 | branch_gate, |
193 | branch_mmc, | ||
163 | }; | 194 | }; |
164 | 195 | ||
165 | struct rockchip_clk_branch { | 196 | struct rockchip_clk_branch { |
@@ -352,6 +383,16 @@ struct rockchip_clk_branch { | |||
352 | .gate_flags = gf, \ | 383 | .gate_flags = gf, \ |
353 | } | 384 | } |
354 | 385 | ||
386 | #define MMC(_id, cname, pname, offset, shift) \ | ||
387 | { \ | ||
388 | .id = _id, \ | ||
389 | .branch_type = branch_mmc, \ | ||
390 | .name = cname, \ | ||
391 | .parent_names = (const char *[]){ pname }, \ | ||
392 | .num_parents = 1, \ | ||
393 | .muxdiv_offset = offset, \ | ||
394 | .div_shift = shift, \ | ||
395 | } | ||
355 | 396 | ||
356 | void rockchip_clk_init(struct device_node *np, void __iomem *base, | 397 | void rockchip_clk_init(struct device_node *np, void __iomem *base, |
357 | unsigned long nr_clks); | 398 | unsigned long nr_clks); |
diff --git a/drivers/clk/samsung/Makefile b/drivers/clk/samsung/Makefile index 6fb4bc602e8a..006c6f294310 100644 --- a/drivers/clk/samsung/Makefile +++ b/drivers/clk/samsung/Makefile | |||
@@ -5,6 +5,7 @@ | |||
5 | obj-$(CONFIG_COMMON_CLK) += clk.o clk-pll.o | 5 | obj-$(CONFIG_COMMON_CLK) += clk.o clk-pll.o |
6 | obj-$(CONFIG_SOC_EXYNOS3250) += clk-exynos3250.o | 6 | obj-$(CONFIG_SOC_EXYNOS3250) += clk-exynos3250.o |
7 | obj-$(CONFIG_ARCH_EXYNOS4) += clk-exynos4.o | 7 | obj-$(CONFIG_ARCH_EXYNOS4) += clk-exynos4.o |
8 | obj-$(CONFIG_SOC_EXYNOS4415) += clk-exynos4415.o | ||
8 | obj-$(CONFIG_SOC_EXYNOS5250) += clk-exynos5250.o | 9 | obj-$(CONFIG_SOC_EXYNOS5250) += clk-exynos5250.o |
9 | obj-$(CONFIG_SOC_EXYNOS5260) += clk-exynos5260.o | 10 | obj-$(CONFIG_SOC_EXYNOS5260) += clk-exynos5260.o |
10 | obj-$(CONFIG_SOC_EXYNOS5410) += clk-exynos5410.o | 11 | obj-$(CONFIG_SOC_EXYNOS5410) += clk-exynos5410.o |
@@ -12,6 +13,7 @@ obj-$(CONFIG_SOC_EXYNOS5420) += clk-exynos5420.o | |||
12 | obj-$(CONFIG_SOC_EXYNOS5440) += clk-exynos5440.o | 13 | obj-$(CONFIG_SOC_EXYNOS5440) += clk-exynos5440.o |
13 | obj-$(CONFIG_ARCH_EXYNOS) += clk-exynos-audss.o | 14 | obj-$(CONFIG_ARCH_EXYNOS) += clk-exynos-audss.o |
14 | obj-$(CONFIG_ARCH_EXYNOS) += clk-exynos-clkout.o | 15 | obj-$(CONFIG_ARCH_EXYNOS) += clk-exynos-clkout.o |
16 | obj-$(CONFIG_ARCH_EXYNOS7) += clk-exynos7.o | ||
15 | obj-$(CONFIG_S3C2410_COMMON_CLK)+= clk-s3c2410.o | 17 | obj-$(CONFIG_S3C2410_COMMON_CLK)+= clk-s3c2410.o |
16 | obj-$(CONFIG_S3C2410_COMMON_DCLK)+= clk-s3c2410-dclk.o | 18 | obj-$(CONFIG_S3C2410_COMMON_DCLK)+= clk-s3c2410-dclk.o |
17 | obj-$(CONFIG_S3C2412_COMMON_CLK)+= clk-s3c2412.o | 19 | obj-$(CONFIG_S3C2412_COMMON_CLK)+= clk-s3c2412.o |
diff --git a/drivers/clk/samsung/clk-exynos-audss.c b/drivers/clk/samsung/clk-exynos-audss.c index acce708ace18..f2c2ccce49bb 100644 --- a/drivers/clk/samsung/clk-exynos-audss.c +++ b/drivers/clk/samsung/clk-exynos-audss.c | |||
@@ -29,6 +29,13 @@ static DEFINE_SPINLOCK(lock); | |||
29 | static struct clk **clk_table; | 29 | static struct clk **clk_table; |
30 | static void __iomem *reg_base; | 30 | static void __iomem *reg_base; |
31 | static struct clk_onecell_data clk_data; | 31 | static struct clk_onecell_data clk_data; |
32 | /* | ||
33 | * On Exynos5420 this will be a clock which has to be enabled before any | ||
34 | * access to audss registers. Typically a child of EPLL. | ||
35 | * | ||
36 | * On other platforms this will be -ENODEV. | ||
37 | */ | ||
38 | static struct clk *epll; | ||
32 | 39 | ||
33 | #define ASS_CLK_SRC 0x0 | 40 | #define ASS_CLK_SRC 0x0 |
34 | #define ASS_CLK_DIV 0x4 | 41 | #define ASS_CLK_DIV 0x4 |
@@ -98,6 +105,8 @@ static int exynos_audss_clk_probe(struct platform_device *pdev) | |||
98 | dev_err(&pdev->dev, "failed to map audss registers\n"); | 105 | dev_err(&pdev->dev, "failed to map audss registers\n"); |
99 | return PTR_ERR(reg_base); | 106 | return PTR_ERR(reg_base); |
100 | } | 107 | } |
108 | /* EPLL don't have to be enabled for boards other than Exynos5420 */ | ||
109 | epll = ERR_PTR(-ENODEV); | ||
101 | 110 | ||
102 | clk_table = devm_kzalloc(&pdev->dev, | 111 | clk_table = devm_kzalloc(&pdev->dev, |
103 | sizeof(struct clk *) * EXYNOS_AUDSS_MAX_CLKS, | 112 | sizeof(struct clk *) * EXYNOS_AUDSS_MAX_CLKS, |
@@ -115,8 +124,20 @@ static int exynos_audss_clk_probe(struct platform_device *pdev) | |||
115 | pll_in = devm_clk_get(&pdev->dev, "pll_in"); | 124 | pll_in = devm_clk_get(&pdev->dev, "pll_in"); |
116 | if (!IS_ERR(pll_ref)) | 125 | if (!IS_ERR(pll_ref)) |
117 | mout_audss_p[0] = __clk_get_name(pll_ref); | 126 | mout_audss_p[0] = __clk_get_name(pll_ref); |
118 | if (!IS_ERR(pll_in)) | 127 | if (!IS_ERR(pll_in)) { |
119 | mout_audss_p[1] = __clk_get_name(pll_in); | 128 | mout_audss_p[1] = __clk_get_name(pll_in); |
129 | |||
130 | if (variant == TYPE_EXYNOS5420) { | ||
131 | epll = pll_in; | ||
132 | |||
133 | ret = clk_prepare_enable(epll); | ||
134 | if (ret) { | ||
135 | dev_err(&pdev->dev, | ||
136 | "failed to prepare the epll clock\n"); | ||
137 | return ret; | ||
138 | } | ||
139 | } | ||
140 | } | ||
120 | clk_table[EXYNOS_MOUT_AUDSS] = clk_register_mux(NULL, "mout_audss", | 141 | clk_table[EXYNOS_MOUT_AUDSS] = clk_register_mux(NULL, "mout_audss", |
121 | mout_audss_p, ARRAY_SIZE(mout_audss_p), | 142 | mout_audss_p, ARRAY_SIZE(mout_audss_p), |
122 | CLK_SET_RATE_NO_REPARENT, | 143 | CLK_SET_RATE_NO_REPARENT, |
@@ -203,6 +224,9 @@ unregister: | |||
203 | clk_unregister(clk_table[i]); | 224 | clk_unregister(clk_table[i]); |
204 | } | 225 | } |
205 | 226 | ||
227 | if (!IS_ERR(epll)) | ||
228 | clk_disable_unprepare(epll); | ||
229 | |||
206 | return ret; | 230 | return ret; |
207 | } | 231 | } |
208 | 232 | ||
@@ -210,6 +234,10 @@ static int exynos_audss_clk_remove(struct platform_device *pdev) | |||
210 | { | 234 | { |
211 | int i; | 235 | int i; |
212 | 236 | ||
237 | #ifdef CONFIG_PM_SLEEP | ||
238 | unregister_syscore_ops(&exynos_audss_clk_syscore_ops); | ||
239 | #endif | ||
240 | |||
213 | of_clk_del_provider(pdev->dev.of_node); | 241 | of_clk_del_provider(pdev->dev.of_node); |
214 | 242 | ||
215 | for (i = 0; i < clk_data.clk_num; i++) { | 243 | for (i = 0; i < clk_data.clk_num; i++) { |
@@ -217,6 +245,9 @@ static int exynos_audss_clk_remove(struct platform_device *pdev) | |||
217 | clk_unregister(clk_table[i]); | 245 | clk_unregister(clk_table[i]); |
218 | } | 246 | } |
219 | 247 | ||
248 | if (!IS_ERR(epll)) | ||
249 | clk_disable_unprepare(epll); | ||
250 | |||
220 | return 0; | 251 | return 0; |
221 | } | 252 | } |
222 | 253 | ||
diff --git a/drivers/clk/samsung/clk-exynos4.c b/drivers/clk/samsung/clk-exynos4.c index 940f02837b82..88e8c6bbd77f 100644 --- a/drivers/clk/samsung/clk-exynos4.c +++ b/drivers/clk/samsung/clk-exynos4.c | |||
@@ -505,7 +505,7 @@ static struct samsung_fixed_rate_clock exynos4_fixed_rate_ext_clks[] __initdata | |||
505 | /* fixed rate clocks generated inside the soc */ | 505 | /* fixed rate clocks generated inside the soc */ |
506 | static struct samsung_fixed_rate_clock exynos4_fixed_rate_clks[] __initdata = { | 506 | static struct samsung_fixed_rate_clock exynos4_fixed_rate_clks[] __initdata = { |
507 | FRATE(0, "sclk_hdmi24m", NULL, CLK_IS_ROOT, 24000000), | 507 | FRATE(0, "sclk_hdmi24m", NULL, CLK_IS_ROOT, 24000000), |
508 | FRATE(CLK_SCLK_HDMIPHY, "sclk_hdmiphy", NULL, CLK_IS_ROOT, 27000000), | 508 | FRATE(CLK_SCLK_HDMIPHY, "sclk_hdmiphy", "hdmi", 0, 27000000), |
509 | FRATE(0, "sclk_usbphy0", NULL, CLK_IS_ROOT, 48000000), | 509 | FRATE(0, "sclk_usbphy0", NULL, CLK_IS_ROOT, 48000000), |
510 | }; | 510 | }; |
511 | 511 | ||
diff --git a/drivers/clk/samsung/clk-exynos4415.c b/drivers/clk/samsung/clk-exynos4415.c new file mode 100644 index 000000000000..2123fc251e0f --- /dev/null +++ b/drivers/clk/samsung/clk-exynos4415.c | |||
@@ -0,0 +1,1144 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2014 Samsung Electronics Co., Ltd. | ||
3 | * Author: Chanwoo Choi <cw00.choi@samsung.com> | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU General Public License version 2 as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * Common Clock Framework support for Exynos4415 SoC. | ||
10 | */ | ||
11 | |||
12 | #include <linux/clk.h> | ||
13 | #include <linux/clkdev.h> | ||
14 | #include <linux/clk-provider.h> | ||
15 | #include <linux/of.h> | ||
16 | #include <linux/of_address.h> | ||
17 | #include <linux/platform_device.h> | ||
18 | #include <linux/syscore_ops.h> | ||
19 | |||
20 | #include <dt-bindings/clock/exynos4415.h> | ||
21 | |||
22 | #include "clk.h" | ||
23 | #include "clk-pll.h" | ||
24 | |||
25 | #define SRC_LEFTBUS 0x4200 | ||
26 | #define DIV_LEFTBUS 0x4500 | ||
27 | #define GATE_IP_LEFTBUS 0x4800 | ||
28 | #define GATE_IP_IMAGE 0x4930 | ||
29 | #define SRC_RIGHTBUS 0x8200 | ||
30 | #define DIV_RIGHTBUS 0x8500 | ||
31 | #define GATE_IP_RIGHTBUS 0x8800 | ||
32 | #define GATE_IP_PERIR 0x8960 | ||
33 | #define EPLL_LOCK 0xc010 | ||
34 | #define G3D_PLL_LOCK 0xc020 | ||
35 | #define DISP_PLL_LOCK 0xc030 | ||
36 | #define ISP_PLL_LOCK 0xc040 | ||
37 | #define EPLL_CON0 0xc110 | ||
38 | #define EPLL_CON1 0xc114 | ||
39 | #define EPLL_CON2 0xc118 | ||
40 | #define G3D_PLL_CON0 0xc120 | ||
41 | #define G3D_PLL_CON1 0xc124 | ||
42 | #define G3D_PLL_CON2 0xc128 | ||
43 | #define ISP_PLL_CON0 0xc130 | ||
44 | #define ISP_PLL_CON1 0xc134 | ||
45 | #define ISP_PLL_CON2 0xc138 | ||
46 | #define DISP_PLL_CON0 0xc140 | ||
47 | #define DISP_PLL_CON1 0xc144 | ||
48 | #define DISP_PLL_CON2 0xc148 | ||
49 | #define SRC_TOP0 0xc210 | ||
50 | #define SRC_TOP1 0xc214 | ||
51 | #define SRC_CAM 0xc220 | ||
52 | #define SRC_TV 0xc224 | ||
53 | #define SRC_MFC 0xc228 | ||
54 | #define SRC_G3D 0xc22c | ||
55 | #define SRC_LCD 0xc234 | ||
56 | #define SRC_ISP 0xc238 | ||
57 | #define SRC_MAUDIO 0xc23c | ||
58 | #define SRC_FSYS 0xc240 | ||
59 | #define SRC_PERIL0 0xc250 | ||
60 | #define SRC_PERIL1 0xc254 | ||
61 | #define SRC_CAM1 0xc258 | ||
62 | #define SRC_TOP_ISP0 0xc25c | ||
63 | #define SRC_TOP_ISP1 0xc260 | ||
64 | #define SRC_MASK_TOP 0xc310 | ||
65 | #define SRC_MASK_CAM 0xc320 | ||
66 | #define SRC_MASK_TV 0xc324 | ||
67 | #define SRC_MASK_LCD 0xc334 | ||
68 | #define SRC_MASK_ISP 0xc338 | ||
69 | #define SRC_MASK_MAUDIO 0xc33c | ||
70 | #define SRC_MASK_FSYS 0xc340 | ||
71 | #define SRC_MASK_PERIL0 0xc350 | ||
72 | #define SRC_MASK_PERIL1 0xc354 | ||
73 | #define DIV_TOP 0xc510 | ||
74 | #define DIV_CAM 0xc520 | ||
75 | #define DIV_TV 0xc524 | ||
76 | #define DIV_MFC 0xc528 | ||
77 | #define DIV_G3D 0xc52c | ||
78 | #define DIV_LCD 0xc534 | ||
79 | #define DIV_ISP 0xc538 | ||
80 | #define DIV_MAUDIO 0xc53c | ||
81 | #define DIV_FSYS0 0xc540 | ||
82 | #define DIV_FSYS1 0xc544 | ||
83 | #define DIV_FSYS2 0xc548 | ||
84 | #define DIV_PERIL0 0xc550 | ||
85 | #define DIV_PERIL1 0xc554 | ||
86 | #define DIV_PERIL2 0xc558 | ||
87 | #define DIV_PERIL3 0xc55c | ||
88 | #define DIV_PERIL4 0xc560 | ||
89 | #define DIV_PERIL5 0xc564 | ||
90 | #define DIV_CAM1 0xc568 | ||
91 | #define DIV_TOP_ISP1 0xc56c | ||
92 | #define DIV_TOP_ISP0 0xc570 | ||
93 | #define CLKDIV2_RATIO 0xc580 | ||
94 | #define GATE_SCLK_CAM 0xc820 | ||
95 | #define GATE_SCLK_TV 0xc824 | ||
96 | #define GATE_SCLK_MFC 0xc828 | ||
97 | #define GATE_SCLK_G3D 0xc82c | ||
98 | #define GATE_SCLK_LCD 0xc834 | ||
99 | #define GATE_SCLK_MAUDIO 0xc83c | ||
100 | #define GATE_SCLK_FSYS 0xc840 | ||
101 | #define GATE_SCLK_PERIL 0xc850 | ||
102 | #define GATE_IP_CAM 0xc920 | ||
103 | #define GATE_IP_TV 0xc924 | ||
104 | #define GATE_IP_MFC 0xc928 | ||
105 | #define GATE_IP_G3D 0xc92c | ||
106 | #define GATE_IP_LCD 0xc934 | ||
107 | #define GATE_IP_FSYS 0xc940 | ||
108 | #define GATE_IP_PERIL 0xc950 | ||
109 | #define GATE_BLOCK 0xc970 | ||
110 | #define APLL_LOCK 0x14000 | ||
111 | #define APLL_CON0 0x14100 | ||
112 | #define SRC_CPU 0x14200 | ||
113 | #define DIV_CPU0 0x14500 | ||
114 | #define DIV_CPU1 0x14504 | ||
115 | |||
116 | enum exynos4415_plls { | ||
117 | apll, epll, g3d_pll, isp_pll, disp_pll, | ||
118 | nr_plls, | ||
119 | }; | ||
120 | |||
121 | static struct samsung_clk_provider *exynos4415_ctx; | ||
122 | |||
123 | /* | ||
124 | * Support for CMU save/restore across system suspends | ||
125 | */ | ||
126 | #ifdef CONFIG_PM_SLEEP | ||
127 | static struct samsung_clk_reg_dump *exynos4415_clk_regs; | ||
128 | |||
129 | static unsigned long exynos4415_cmu_clk_regs[] __initdata = { | ||
130 | SRC_LEFTBUS, | ||
131 | DIV_LEFTBUS, | ||
132 | GATE_IP_LEFTBUS, | ||
133 | GATE_IP_IMAGE, | ||
134 | SRC_RIGHTBUS, | ||
135 | DIV_RIGHTBUS, | ||
136 | GATE_IP_RIGHTBUS, | ||
137 | GATE_IP_PERIR, | ||
138 | EPLL_LOCK, | ||
139 | G3D_PLL_LOCK, | ||
140 | DISP_PLL_LOCK, | ||
141 | ISP_PLL_LOCK, | ||
142 | EPLL_CON0, | ||
143 | EPLL_CON1, | ||
144 | EPLL_CON2, | ||
145 | G3D_PLL_CON0, | ||
146 | G3D_PLL_CON1, | ||
147 | G3D_PLL_CON2, | ||
148 | ISP_PLL_CON0, | ||
149 | ISP_PLL_CON1, | ||
150 | ISP_PLL_CON2, | ||
151 | DISP_PLL_CON0, | ||
152 | DISP_PLL_CON1, | ||
153 | DISP_PLL_CON2, | ||
154 | SRC_TOP0, | ||
155 | SRC_TOP1, | ||
156 | SRC_CAM, | ||
157 | SRC_TV, | ||
158 | SRC_MFC, | ||
159 | SRC_G3D, | ||
160 | SRC_LCD, | ||
161 | SRC_ISP, | ||
162 | SRC_MAUDIO, | ||
163 | SRC_FSYS, | ||
164 | SRC_PERIL0, | ||
165 | SRC_PERIL1, | ||
166 | SRC_CAM1, | ||
167 | SRC_TOP_ISP0, | ||
168 | SRC_TOP_ISP1, | ||
169 | SRC_MASK_TOP, | ||
170 | SRC_MASK_CAM, | ||
171 | SRC_MASK_TV, | ||
172 | SRC_MASK_LCD, | ||
173 | SRC_MASK_ISP, | ||
174 | SRC_MASK_MAUDIO, | ||
175 | SRC_MASK_FSYS, | ||
176 | SRC_MASK_PERIL0, | ||
177 | SRC_MASK_PERIL1, | ||
178 | DIV_TOP, | ||
179 | DIV_CAM, | ||
180 | DIV_TV, | ||
181 | DIV_MFC, | ||
182 | DIV_G3D, | ||
183 | DIV_LCD, | ||
184 | DIV_ISP, | ||
185 | DIV_MAUDIO, | ||
186 | DIV_FSYS0, | ||
187 | DIV_FSYS1, | ||
188 | DIV_FSYS2, | ||
189 | DIV_PERIL0, | ||
190 | DIV_PERIL1, | ||
191 | DIV_PERIL2, | ||
192 | DIV_PERIL3, | ||
193 | DIV_PERIL4, | ||
194 | DIV_PERIL5, | ||
195 | DIV_CAM1, | ||
196 | DIV_TOP_ISP1, | ||
197 | DIV_TOP_ISP0, | ||
198 | CLKDIV2_RATIO, | ||
199 | GATE_SCLK_CAM, | ||
200 | GATE_SCLK_TV, | ||
201 | GATE_SCLK_MFC, | ||
202 | GATE_SCLK_G3D, | ||
203 | GATE_SCLK_LCD, | ||
204 | GATE_SCLK_MAUDIO, | ||
205 | GATE_SCLK_FSYS, | ||
206 | GATE_SCLK_PERIL, | ||
207 | GATE_IP_CAM, | ||
208 | GATE_IP_TV, | ||
209 | GATE_IP_MFC, | ||
210 | GATE_IP_G3D, | ||
211 | GATE_IP_LCD, | ||
212 | GATE_IP_FSYS, | ||
213 | GATE_IP_PERIL, | ||
214 | GATE_BLOCK, | ||
215 | APLL_LOCK, | ||
216 | APLL_CON0, | ||
217 | SRC_CPU, | ||
218 | DIV_CPU0, | ||
219 | DIV_CPU1, | ||
220 | }; | ||
221 | |||
222 | static int exynos4415_clk_suspend(void) | ||
223 | { | ||
224 | samsung_clk_save(exynos4415_ctx->reg_base, exynos4415_clk_regs, | ||
225 | ARRAY_SIZE(exynos4415_cmu_clk_regs)); | ||
226 | |||
227 | return 0; | ||
228 | } | ||
229 | |||
230 | static void exynos4415_clk_resume(void) | ||
231 | { | ||
232 | samsung_clk_restore(exynos4415_ctx->reg_base, exynos4415_clk_regs, | ||
233 | ARRAY_SIZE(exynos4415_cmu_clk_regs)); | ||
234 | } | ||
235 | |||
236 | static struct syscore_ops exynos4415_clk_syscore_ops = { | ||
237 | .suspend = exynos4415_clk_suspend, | ||
238 | .resume = exynos4415_clk_resume, | ||
239 | }; | ||
240 | |||
241 | static void exynos4415_clk_sleep_init(void) | ||
242 | { | ||
243 | exynos4415_clk_regs = | ||
244 | samsung_clk_alloc_reg_dump(exynos4415_cmu_clk_regs, | ||
245 | ARRAY_SIZE(exynos4415_cmu_clk_regs)); | ||
246 | if (!exynos4415_clk_regs) { | ||
247 | pr_warn("%s: Failed to allocate sleep save data\n", __func__); | ||
248 | return; | ||
249 | } | ||
250 | |||
251 | register_syscore_ops(&exynos4415_clk_syscore_ops); | ||
252 | } | ||
253 | #else | ||
254 | static inline void exynos4415_clk_sleep_init(void) { } | ||
255 | #endif | ||
256 | |||
257 | /* list of all parent clock list */ | ||
258 | PNAME(mout_g3d_pllsrc_p) = { "fin_pll", }; | ||
259 | |||
260 | PNAME(mout_apll_p) = { "fin_pll", "fout_apll", }; | ||
261 | PNAME(mout_g3d_pll_p) = { "fin_pll", "fout_g3d_pll", }; | ||
262 | PNAME(mout_isp_pll_p) = { "fin_pll", "fout_isp_pll", }; | ||
263 | PNAME(mout_disp_pll_p) = { "fin_pll", "fout_disp_pll", }; | ||
264 | |||
265 | PNAME(mout_mpll_user_p) = { "fin_pll", "div_mpll_pre", }; | ||
266 | PNAME(mout_epll_p) = { "fin_pll", "fout_epll", }; | ||
267 | PNAME(mout_core_p) = { "mout_apll", "mout_mpll_user_c", }; | ||
268 | PNAME(mout_hpm_p) = { "mout_apll", "mout_mpll_user_c", }; | ||
269 | |||
270 | PNAME(mout_ebi_p) = { "div_aclk_200", "div_aclk_160", }; | ||
271 | PNAME(mout_ebi_1_p) = { "mout_ebi", "mout_g3d_pll", }; | ||
272 | |||
273 | PNAME(mout_gdl_p) = { "mout_mpll_user_l", }; | ||
274 | PNAME(mout_gdr_p) = { "mout_mpll_user_r", }; | ||
275 | |||
276 | PNAME(mout_aclk_266_p) = { "mout_mpll_user_t", "mout_g3d_pll", }; | ||
277 | |||
278 | PNAME(group_epll_g3dpll_p) = { "mout_epll", "mout_g3d_pll" }; | ||
279 | PNAME(group_sclk_p) = { "xxti", "xusbxti", | ||
280 | "none", "mout_isp_pll", | ||
281 | "none", "none", "div_mpll_pre", | ||
282 | "mout_epll", "mout_g3d_pll", }; | ||
283 | PNAME(group_spdif_p) = { "mout_audio0", "mout_audio1", | ||
284 | "mout_audio2", "spdif_extclk", }; | ||
285 | PNAME(group_sclk_audio2_p) = { "audiocdclk2", "none", | ||
286 | "none", "mout_isp_pll", | ||
287 | "mout_disp_pll", "xusbxti", | ||
288 | "div_mpll_pre", "mout_epll", | ||
289 | "mout_g3d_pll", }; | ||
290 | PNAME(group_sclk_audio1_p) = { "audiocdclk1", "none", | ||
291 | "none", "mout_isp_pll", | ||
292 | "mout_disp_pll", "xusbxti", | ||
293 | "div_mpll_pre", "mout_epll", | ||
294 | "mout_g3d_pll", }; | ||
295 | PNAME(group_sclk_audio0_p) = { "audiocdclk0", "none", | ||
296 | "none", "mout_isp_pll", | ||
297 | "mout_disp_pll", "xusbxti", | ||
298 | "div_mpll_pre", "mout_epll", | ||
299 | "mout_g3d_pll", }; | ||
300 | PNAME(group_fimc_lclk_p) = { "xxti", "xusbxti", | ||
301 | "none", "mout_isp_pll", | ||
302 | "none", "mout_disp_pll", | ||
303 | "mout_mpll_user_t", "mout_epll", | ||
304 | "mout_g3d_pll", }; | ||
305 | PNAME(group_sclk_fimd0_p) = { "xxti", "xusbxti", | ||
306 | "m_bitclkhsdiv4_4l", "mout_isp_pll", | ||
307 | "mout_disp_pll", "sclk_hdmiphy", | ||
308 | "div_mpll_pre", "mout_epll", | ||
309 | "mout_g3d_pll", }; | ||
310 | PNAME(mout_hdmi_p) = { "sclk_pixel", "sclk_hdmiphy" }; | ||
311 | PNAME(mout_mfc_p) = { "mout_mfc_0", "mout_mfc_1" }; | ||
312 | PNAME(mout_g3d_p) = { "mout_g3d_0", "mout_g3d_1" }; | ||
313 | PNAME(mout_jpeg_p) = { "mout_jpeg_0", "mout_jpeg_1" }; | ||
314 | PNAME(mout_jpeg1_p) = { "mout_epll", "mout_g3d_pll" }; | ||
315 | PNAME(group_aclk_isp0_300_p) = { "mout_isp_pll", "div_mpll_pre" }; | ||
316 | PNAME(group_aclk_isp0_400_user_p) = { "fin_pll", "div_aclk_400_mcuisp" }; | ||
317 | PNAME(group_aclk_isp0_300_user_p) = { "fin_pll", "mout_aclk_isp0_300" }; | ||
318 | PNAME(group_aclk_isp1_300_user_p) = { "fin_pll", "mout_aclk_isp1_300" }; | ||
319 | PNAME(group_mout_mpll_user_t_p) = { "mout_mpll_user_t" }; | ||
320 | |||
321 | static struct samsung_fixed_factor_clock exynos4415_fixed_factor_clks[] __initdata = { | ||
322 | /* HACK: fin_pll hardcoded to xusbxti until detection is implemented. */ | ||
323 | FFACTOR(CLK_FIN_PLL, "fin_pll", "xusbxti", 1, 1, 0), | ||
324 | }; | ||
325 | |||
326 | static struct samsung_fixed_rate_clock exynos4415_fixed_rate_clks[] __initdata = { | ||
327 | FRATE(CLK_SCLK_HDMIPHY, "sclk_hdmiphy", NULL, CLK_IS_ROOT, 27000000), | ||
328 | }; | ||
329 | |||
330 | static struct samsung_mux_clock exynos4415_mux_clks[] __initdata = { | ||
331 | /* | ||
332 | * NOTE: Following table is sorted by register address in ascending | ||
333 | * order and then bitfield shift in descending order, as it is done | ||
334 | * in the User's Manual. When adding new entries, please make sure | ||
335 | * that the order is preserved, to avoid merge conflicts and make | ||
336 | * further work with defined data easier. | ||
337 | */ | ||
338 | |||
339 | /* SRC_LEFTBUS */ | ||
340 | MUX(CLK_MOUT_MPLL_USER_L, "mout_mpll_user_l", mout_mpll_user_p, | ||
341 | SRC_LEFTBUS, 4, 1), | ||
342 | MUX(CLK_MOUT_GDL, "mout_gdl", mout_gdl_p, SRC_LEFTBUS, 0, 1), | ||
343 | |||
344 | /* SRC_RIGHTBUS */ | ||
345 | MUX(CLK_MOUT_MPLL_USER_R, "mout_mpll_user_r", mout_mpll_user_p, | ||
346 | SRC_RIGHTBUS, 4, 1), | ||
347 | MUX(CLK_MOUT_GDR, "mout_gdr", mout_gdr_p, SRC_RIGHTBUS, 0, 1), | ||
348 | |||
349 | /* SRC_TOP0 */ | ||
350 | MUX(CLK_MOUT_EBI, "mout_ebi", mout_ebi_p, SRC_TOP0, 28, 1), | ||
351 | MUX(CLK_MOUT_ACLK_200, "mout_aclk_200", group_mout_mpll_user_t_p, | ||
352 | SRC_TOP0, 24, 1), | ||
353 | MUX(CLK_MOUT_ACLK_160, "mout_aclk_160", group_mout_mpll_user_t_p, | ||
354 | SRC_TOP0, 20, 1), | ||
355 | MUX(CLK_MOUT_ACLK_100, "mout_aclk_100", group_mout_mpll_user_t_p, | ||
356 | SRC_TOP0, 16, 1), | ||
357 | MUX(CLK_MOUT_ACLK_266, "mout_aclk_266", mout_aclk_266_p, | ||
358 | SRC_TOP0, 12, 1), | ||
359 | MUX(CLK_MOUT_G3D_PLL, "mout_g3d_pll", mout_g3d_pll_p, | ||
360 | SRC_TOP0, 8, 1), | ||
361 | MUX(CLK_MOUT_EPLL, "mout_epll", mout_epll_p, SRC_TOP0, 4, 1), | ||
362 | MUX(CLK_MOUT_EBI_1, "mout_ebi_1", mout_ebi_1_p, SRC_TOP0, 0, 1), | ||
363 | |||
364 | /* SRC_TOP1 */ | ||
365 | MUX(CLK_MOUT_ISP_PLL, "mout_isp_pll", mout_isp_pll_p, | ||
366 | SRC_TOP1, 28, 1), | ||
367 | MUX(CLK_MOUT_DISP_PLL, "mout_disp_pll", mout_disp_pll_p, | ||
368 | SRC_TOP1, 16, 1), | ||
369 | MUX(CLK_MOUT_MPLL_USER_T, "mout_mpll_user_t", mout_mpll_user_p, | ||
370 | SRC_TOP1, 12, 1), | ||
371 | MUX(CLK_MOUT_ACLK_400_MCUISP, "mout_aclk_400_mcuisp", | ||
372 | group_mout_mpll_user_t_p, SRC_TOP1, 8, 1), | ||
373 | MUX(CLK_MOUT_G3D_PLLSRC, "mout_g3d_pllsrc", mout_g3d_pllsrc_p, | ||
374 | SRC_TOP1, 0, 1), | ||
375 | |||
376 | /* SRC_CAM */ | ||
377 | MUX(CLK_MOUT_CSIS1, "mout_csis1", group_fimc_lclk_p, SRC_CAM, 28, 4), | ||
378 | MUX(CLK_MOUT_CSIS0, "mout_csis0", group_fimc_lclk_p, SRC_CAM, 24, 4), | ||
379 | MUX(CLK_MOUT_CAM1, "mout_cam1", group_fimc_lclk_p, SRC_CAM, 20, 4), | ||
380 | MUX(CLK_MOUT_FIMC3_LCLK, "mout_fimc3_lclk", group_fimc_lclk_p, SRC_CAM, | ||
381 | 12, 4), | ||
382 | MUX(CLK_MOUT_FIMC2_LCLK, "mout_fimc2_lclk", group_fimc_lclk_p, SRC_CAM, | ||
383 | 8, 4), | ||
384 | MUX(CLK_MOUT_FIMC1_LCLK, "mout_fimc1_lclk", group_fimc_lclk_p, SRC_CAM, | ||
385 | 4, 4), | ||
386 | MUX(CLK_MOUT_FIMC0_LCLK, "mout_fimc0_lclk", group_fimc_lclk_p, SRC_CAM, | ||
387 | 0, 4), | ||
388 | |||
389 | /* SRC_TV */ | ||
390 | MUX(CLK_MOUT_HDMI, "mout_hdmi", mout_hdmi_p, SRC_TV, 0, 1), | ||
391 | |||
392 | /* SRC_MFC */ | ||
393 | MUX(CLK_MOUT_MFC, "mout_mfc", mout_mfc_p, SRC_MFC, 8, 1), | ||
394 | MUX(CLK_MOUT_MFC_1, "mout_mfc_1", group_epll_g3dpll_p, SRC_MFC, 4, 1), | ||
395 | MUX(CLK_MOUT_MFC_0, "mout_mfc_0", group_mout_mpll_user_t_p, SRC_MFC, 0, | ||
396 | 1), | ||
397 | |||
398 | /* SRC_G3D */ | ||
399 | MUX(CLK_MOUT_G3D, "mout_g3d", mout_g3d_p, SRC_G3D, 8, 1), | ||
400 | MUX(CLK_MOUT_G3D_1, "mout_g3d_1", group_epll_g3dpll_p, SRC_G3D, 4, 1), | ||
401 | MUX(CLK_MOUT_G3D_0, "mout_g3d_0", group_mout_mpll_user_t_p, SRC_G3D, 0, | ||
402 | 1), | ||
403 | |||
404 | /* SRC_LCD */ | ||
405 | MUX(CLK_MOUT_MIPI0, "mout_mipi0", group_fimc_lclk_p, SRC_LCD, 12, 4), | ||
406 | MUX(CLK_MOUT_FIMD0, "mout_fimd0", group_sclk_fimd0_p, SRC_LCD, 0, 4), | ||
407 | |||
408 | /* SRC_ISP */ | ||
409 | MUX(CLK_MOUT_TSADC_ISP, "mout_tsadc_isp", group_fimc_lclk_p, SRC_ISP, | ||
410 | 16, 4), | ||
411 | MUX(CLK_MOUT_UART_ISP, "mout_uart_isp", group_fimc_lclk_p, SRC_ISP, | ||
412 | 12, 4), | ||
413 | MUX(CLK_MOUT_SPI1_ISP, "mout_spi1_isp", group_fimc_lclk_p, SRC_ISP, | ||
414 | 8, 4), | ||
415 | MUX(CLK_MOUT_SPI0_ISP, "mout_spi0_isp", group_fimc_lclk_p, SRC_ISP, | ||
416 | 4, 4), | ||
417 | MUX(CLK_MOUT_PWM_ISP, "mout_pwm_isp", group_fimc_lclk_p, SRC_ISP, | ||
418 | 0, 4), | ||
419 | |||
420 | /* SRC_MAUDIO */ | ||
421 | MUX(CLK_MOUT_AUDIO0, "mout_audio0", group_sclk_audio0_p, SRC_MAUDIO, | ||
422 | 0, 4), | ||
423 | |||
424 | /* SRC_FSYS */ | ||
425 | MUX(CLK_MOUT_TSADC, "mout_tsadc", group_sclk_p, SRC_FSYS, 28, 4), | ||
426 | MUX(CLK_MOUT_MMC2, "mout_mmc2", group_sclk_p, SRC_FSYS, 8, 4), | ||
427 | MUX(CLK_MOUT_MMC1, "mout_mmc1", group_sclk_p, SRC_FSYS, 4, 4), | ||
428 | MUX(CLK_MOUT_MMC0, "mout_mmc0", group_sclk_p, SRC_FSYS, 0, 4), | ||
429 | |||
430 | /* SRC_PERIL0 */ | ||
431 | MUX(CLK_MOUT_UART3, "mout_uart3", group_sclk_p, SRC_PERIL0, 12, 4), | ||
432 | MUX(CLK_MOUT_UART2, "mout_uart2", group_sclk_p, SRC_PERIL0, 8, 4), | ||
433 | MUX(CLK_MOUT_UART1, "mout_uart1", group_sclk_p, SRC_PERIL0, 4, 4), | ||
434 | MUX(CLK_MOUT_UART0, "mout_uart0", group_sclk_p, SRC_PERIL0, 0, 4), | ||
435 | |||
436 | /* SRC_PERIL1 */ | ||
437 | MUX(CLK_MOUT_SPI2, "mout_spi2", group_sclk_p, SRC_PERIL1, 24, 4), | ||
438 | MUX(CLK_MOUT_SPI1, "mout_spi1", group_sclk_p, SRC_PERIL1, 20, 4), | ||
439 | MUX(CLK_MOUT_SPI0, "mout_spi0", group_sclk_p, SRC_PERIL1, 16, 4), | ||
440 | MUX(CLK_MOUT_SPDIF, "mout_spdif", group_spdif_p, SRC_PERIL1, 8, 4), | ||
441 | MUX(CLK_MOUT_AUDIO2, "mout_audio2", group_sclk_audio2_p, SRC_PERIL1, | ||
442 | 4, 4), | ||
443 | MUX(CLK_MOUT_AUDIO1, "mout_audio1", group_sclk_audio1_p, SRC_PERIL1, | ||
444 | 0, 4), | ||
445 | |||
446 | /* SRC_CPU */ | ||
447 | MUX(CLK_MOUT_MPLL_USER_C, "mout_mpll_user_c", mout_mpll_user_p, | ||
448 | SRC_CPU, 24, 1), | ||
449 | MUX(CLK_MOUT_HPM, "mout_hpm", mout_hpm_p, SRC_CPU, 20, 1), | ||
450 | MUX_F(CLK_MOUT_CORE, "mout_core", mout_core_p, SRC_CPU, 16, 1, 0, | ||
451 | CLK_MUX_READ_ONLY), | ||
452 | MUX_F(CLK_MOUT_APLL, "mout_apll", mout_apll_p, SRC_CPU, 0, 1, | ||
453 | CLK_SET_RATE_PARENT, 0), | ||
454 | |||
455 | /* SRC_CAM1 */ | ||
456 | MUX(CLK_MOUT_PXLASYNC_CSIS1_FIMC, "mout_pxlasync_csis1", | ||
457 | group_fimc_lclk_p, SRC_CAM1, 20, 1), | ||
458 | MUX(CLK_MOUT_PXLASYNC_CSIS0_FIMC, "mout_pxlasync_csis0", | ||
459 | group_fimc_lclk_p, SRC_CAM1, 16, 1), | ||
460 | MUX(CLK_MOUT_JPEG, "mout_jpeg", mout_jpeg_p, SRC_CAM1, 8, 1), | ||
461 | MUX(CLK_MOUT_JPEG1, "mout_jpeg_1", mout_jpeg1_p, SRC_CAM1, 4, 1), | ||
462 | MUX(CLK_MOUT_JPEG0, "mout_jpeg_0", group_mout_mpll_user_t_p, SRC_CAM1, | ||
463 | 0, 1), | ||
464 | |||
465 | /* SRC_TOP_ISP0 */ | ||
466 | MUX(CLK_MOUT_ACLK_ISP0_300, "mout_aclk_isp0_300", | ||
467 | group_aclk_isp0_300_p, SRC_TOP_ISP0, 8, 1), | ||
468 | MUX(CLK_MOUT_ACLK_ISP0_400, "mout_aclk_isp0_400_user", | ||
469 | group_aclk_isp0_400_user_p, SRC_TOP_ISP0, 4, 1), | ||
470 | MUX(CLK_MOUT_ACLK_ISP0_300_USER, "mout_aclk_isp0_300_user", | ||
471 | group_aclk_isp0_300_user_p, SRC_TOP_ISP0, 0, 1), | ||
472 | |||
473 | /* SRC_TOP_ISP1 */ | ||
474 | MUX(CLK_MOUT_ACLK_ISP1_300, "mout_aclk_isp1_300", | ||
475 | group_aclk_isp0_300_p, SRC_TOP_ISP1, 4, 1), | ||
476 | MUX(CLK_MOUT_ACLK_ISP1_300_USER, "mout_aclk_isp1_300_user", | ||
477 | group_aclk_isp1_300_user_p, SRC_TOP_ISP1, 0, 1), | ||
478 | }; | ||
479 | |||
480 | static struct samsung_div_clock exynos4415_div_clks[] __initdata = { | ||
481 | /* | ||
482 | * NOTE: Following table is sorted by register address in ascending | ||
483 | * order and then bitfield shift in descending order, as it is done | ||
484 | * in the User's Manual. When adding new entries, please make sure | ||
485 | * that the order is preserved, to avoid merge conflicts and make | ||
486 | * further work with defined data easier. | ||
487 | */ | ||
488 | |||
489 | /* DIV_LEFTBUS */ | ||
490 | DIV(CLK_DIV_GPL, "div_gpl", "div_gdl", DIV_LEFTBUS, 4, 3), | ||
491 | DIV(CLK_DIV_GDL, "div_gdl", "mout_gdl", DIV_LEFTBUS, 0, 4), | ||
492 | |||
493 | /* DIV_RIGHTBUS */ | ||
494 | DIV(CLK_DIV_GPR, "div_gpr", "div_gdr", DIV_RIGHTBUS, 4, 3), | ||
495 | DIV(CLK_DIV_GDR, "div_gdr", "mout_gdr", DIV_RIGHTBUS, 0, 4), | ||
496 | |||
497 | /* DIV_TOP */ | ||
498 | DIV(CLK_DIV_ACLK_400_MCUISP, "div_aclk_400_mcuisp", | ||
499 | "mout_aclk_400_mcuisp", DIV_TOP, 24, 3), | ||
500 | DIV(CLK_DIV_EBI, "div_ebi", "mout_ebi_1", DIV_TOP, 16, 3), | ||
501 | DIV(CLK_DIV_ACLK_200, "div_aclk_200", "mout_aclk_200", DIV_TOP, 12, 3), | ||
502 | DIV(CLK_DIV_ACLK_160, "div_aclk_160", "mout_aclk_160", DIV_TOP, 8, 3), | ||
503 | DIV(CLK_DIV_ACLK_100, "div_aclk_100", "mout_aclk_100", DIV_TOP, 4, 4), | ||
504 | DIV(CLK_DIV_ACLK_266, "div_aclk_266", "mout_aclk_266", DIV_TOP, 0, 3), | ||
505 | |||
506 | /* DIV_CAM */ | ||
507 | DIV(CLK_DIV_CSIS1, "div_csis1", "mout_csis1", DIV_CAM, 28, 4), | ||
508 | DIV(CLK_DIV_CSIS0, "div_csis0", "mout_csis0", DIV_CAM, 24, 4), | ||
509 | DIV(CLK_DIV_CAM1, "div_cam1", "mout_cam1", DIV_CAM, 20, 4), | ||
510 | DIV(CLK_DIV_FIMC3_LCLK, "div_fimc3_lclk", "mout_fimc3_lclk", DIV_CAM, | ||
511 | 12, 4), | ||
512 | DIV(CLK_DIV_FIMC2_LCLK, "div_fimc2_lclk", "mout_fimc2_lclk", DIV_CAM, | ||
513 | 8, 4), | ||
514 | DIV(CLK_DIV_FIMC1_LCLK, "div_fimc1_lclk", "mout_fimc1_lclk", DIV_CAM, | ||
515 | 4, 4), | ||
516 | DIV(CLK_DIV_FIMC0_LCLK, "div_fimc0_lclk", "mout_fimc0_lclk", DIV_CAM, | ||
517 | 0, 4), | ||
518 | |||
519 | /* DIV_TV */ | ||
520 | DIV(CLK_DIV_TV_BLK, "div_tv_blk", "mout_g3d_pll", DIV_TV, 0, 4), | ||
521 | |||
522 | /* DIV_MFC */ | ||
523 | DIV(CLK_DIV_MFC, "div_mfc", "mout_mfc", DIV_MFC, 0, 4), | ||
524 | |||
525 | /* DIV_G3D */ | ||
526 | DIV(CLK_DIV_G3D, "div_g3d", "mout_g3d", DIV_G3D, 0, 4), | ||
527 | |||
528 | /* DIV_LCD */ | ||
529 | DIV_F(CLK_DIV_MIPI0_PRE, "div_mipi0_pre", "div_mipi0", DIV_LCD, 20, 4, | ||
530 | CLK_SET_RATE_PARENT, 0), | ||
531 | DIV(CLK_DIV_MIPI0, "div_mipi0", "mout_mipi0", DIV_LCD, 16, 4), | ||
532 | DIV(CLK_DIV_FIMD0, "div_fimd0", "mout_fimd0", DIV_LCD, 0, 4), | ||
533 | |||
534 | /* DIV_ISP */ | ||
535 | DIV(CLK_DIV_UART_ISP, "div_uart_isp", "mout_uart_isp", DIV_ISP, 28, 4), | ||
536 | DIV_F(CLK_DIV_SPI1_ISP_PRE, "div_spi1_isp_pre", "div_spi1_isp", | ||
537 | DIV_ISP, 20, 8, CLK_SET_RATE_PARENT, 0), | ||
538 | DIV(CLK_DIV_SPI1_ISP, "div_spi1_isp", "mout_spi1_isp", DIV_ISP, 16, 4), | ||
539 | DIV_F(CLK_DIV_SPI0_ISP_PRE, "div_spi0_isp_pre", "div_spi0_isp", | ||
540 | DIV_ISP, 8, 8, CLK_SET_RATE_PARENT, 0), | ||
541 | DIV(CLK_DIV_SPI0_ISP, "div_spi0_isp", "mout_spi0_isp", DIV_ISP, 4, 4), | ||
542 | DIV(CLK_DIV_PWM_ISP, "div_pwm_isp", "mout_pwm_isp", DIV_ISP, 0, 4), | ||
543 | |||
544 | /* DIV_MAUDIO */ | ||
545 | DIV(CLK_DIV_PCM0, "div_pcm0", "div_audio0", DIV_MAUDIO, 4, 8), | ||
546 | DIV(CLK_DIV_AUDIO0, "div_audio0", "mout_audio0", DIV_MAUDIO, 0, 4), | ||
547 | |||
548 | /* DIV_FSYS0 */ | ||
549 | DIV_F(CLK_DIV_TSADC_PRE, "div_tsadc_pre", "div_tsadc", DIV_FSYS0, 8, 8, | ||
550 | CLK_SET_RATE_PARENT, 0), | ||
551 | DIV(CLK_DIV_TSADC, "div_tsadc", "mout_tsadc", DIV_FSYS0, 0, 4), | ||
552 | |||
553 | /* DIV_FSYS1 */ | ||
554 | DIV_F(CLK_DIV_MMC1_PRE, "div_mmc1_pre", "div_mmc1", DIV_FSYS1, 24, 8, | ||
555 | CLK_SET_RATE_PARENT, 0), | ||
556 | DIV(CLK_DIV_MMC1, "div_mmc1", "mout_mmc1", DIV_FSYS1, 16, 4), | ||
557 | DIV_F(CLK_DIV_MMC0_PRE, "div_mmc0_pre", "div_mmc0", DIV_FSYS1, 8, 8, | ||
558 | CLK_SET_RATE_PARENT, 0), | ||
559 | DIV(CLK_DIV_MMC0, "div_mmc0", "mout_mmc0", DIV_FSYS1, 0, 4), | ||
560 | |||
561 | /* DIV_FSYS2 */ | ||
562 | DIV_F(CLK_DIV_MMC2_PRE, "div_mmc2_pre", "div_mmc2", DIV_FSYS2, 8, 8, | ||
563 | CLK_SET_RATE_PARENT, 0), | ||
564 | DIV_F(CLK_DIV_MMC2_PRE, "div_mmc2", "mout_mmc2", DIV_FSYS2, 0, 4, | ||
565 | CLK_SET_RATE_PARENT, 0), | ||
566 | |||
567 | /* DIV_PERIL0 */ | ||
568 | DIV(CLK_DIV_UART3, "div_uart3", "mout_uart3", DIV_PERIL0, 12, 4), | ||
569 | DIV(CLK_DIV_UART2, "div_uart2", "mout_uart2", DIV_PERIL0, 8, 4), | ||
570 | DIV(CLK_DIV_UART1, "div_uart1", "mout_uart1", DIV_PERIL0, 4, 4), | ||
571 | DIV(CLK_DIV_UART0, "div_uart0", "mout_uart0", DIV_PERIL0, 0, 4), | ||
572 | |||
573 | /* DIV_PERIL1 */ | ||
574 | DIV_F(CLK_DIV_SPI1_PRE, "div_spi1_pre", "div_spi1", DIV_PERIL1, 24, 8, | ||
575 | CLK_SET_RATE_PARENT, 0), | ||
576 | DIV(CLK_DIV_SPI1, "div_spi1", "mout_spi1", DIV_PERIL1, 16, 4), | ||
577 | DIV_F(CLK_DIV_SPI0_PRE, "div_spi0_pre", "div_spi0", DIV_PERIL1, 8, 8, | ||
578 | CLK_SET_RATE_PARENT, 0), | ||
579 | DIV(CLK_DIV_SPI0, "div_spi0", "mout_spi0", DIV_PERIL1, 0, 4), | ||
580 | |||
581 | /* DIV_PERIL2 */ | ||
582 | DIV_F(CLK_DIV_SPI2_PRE, "div_spi2_pre", "div_spi2", DIV_PERIL2, 8, 8, | ||
583 | CLK_SET_RATE_PARENT, 0), | ||
584 | DIV(CLK_DIV_SPI2, "div_spi2", "mout_spi2", DIV_PERIL2, 0, 4), | ||
585 | |||
586 | /* DIV_PERIL4 */ | ||
587 | DIV(CLK_DIV_PCM2, "div_pcm2", "div_audio2", DIV_PERIL4, 20, 8), | ||
588 | DIV(CLK_DIV_AUDIO2, "div_audio2", "mout_audio2", DIV_PERIL4, 16, 4), | ||
589 | DIV(CLK_DIV_PCM1, "div_pcm1", "div_audio1", DIV_PERIL4, 20, 8), | ||
590 | DIV(CLK_DIV_AUDIO1, "div_audio1", "mout_audio1", DIV_PERIL4, 0, 4), | ||
591 | |||
592 | /* DIV_PERIL5 */ | ||
593 | DIV(CLK_DIV_I2S1, "div_i2s1", "div_audio1", DIV_PERIL5, 0, 6), | ||
594 | |||
595 | /* DIV_CAM1 */ | ||
596 | DIV(CLK_DIV_PXLASYNC_CSIS1_FIMC, "div_pxlasync_csis1_fimc", | ||
597 | "mout_pxlasync_csis1", DIV_CAM1, 24, 4), | ||
598 | DIV(CLK_DIV_PXLASYNC_CSIS0_FIMC, "div_pxlasync_csis0_fimc", | ||
599 | "mout_pxlasync_csis0", DIV_CAM1, 20, 4), | ||
600 | DIV(CLK_DIV_JPEG, "div_jpeg", "mout_jpeg", DIV_CAM1, 0, 4), | ||
601 | |||
602 | /* DIV_CPU0 */ | ||
603 | DIV(CLK_DIV_CORE2, "div_core2", "div_core", DIV_CPU0, 28, 3), | ||
604 | DIV_F(CLK_DIV_APLL, "div_apll", "mout_apll", DIV_CPU0, 24, 3, | ||
605 | CLK_GET_RATE_NOCACHE, CLK_DIVIDER_READ_ONLY), | ||
606 | DIV(CLK_DIV_PCLK_DBG, "div_pclk_dbg", "div_core2", DIV_CPU0, 20, 3), | ||
607 | DIV(CLK_DIV_ATB, "div_atb", "div_core2", DIV_CPU0, 16, 3), | ||
608 | DIV(CLK_DIV_PERIPH, "div_periph", "div_core2", DIV_CPU0, 12, 3), | ||
609 | DIV(CLK_DIV_COREM1, "div_corem1", "div_core2", DIV_CPU0, 8, 3), | ||
610 | DIV(CLK_DIV_COREM0, "div_corem0", "div_core2", DIV_CPU0, 4, 3), | ||
611 | DIV_F(CLK_DIV_CORE, "div_core", "mout_core", DIV_CPU0, 0, 3, | ||
612 | CLK_GET_RATE_NOCACHE, CLK_DIVIDER_READ_ONLY), | ||
613 | |||
614 | /* DIV_CPU1 */ | ||
615 | DIV(CLK_DIV_HPM, "div_hpm", "div_copy", DIV_CPU1, 4, 3), | ||
616 | DIV(CLK_DIV_COPY, "div_copy", "mout_hpm", DIV_CPU1, 0, 3), | ||
617 | }; | ||
618 | |||
619 | static struct samsung_gate_clock exynos4415_gate_clks[] __initdata = { | ||
620 | /* | ||
621 | * NOTE: Following table is sorted by register address in ascending | ||
622 | * order and then bitfield shift in descending order, as it is done | ||
623 | * in the User's Manual. When adding new entries, please make sure | ||
624 | * that the order is preserved, to avoid merge conflicts and make | ||
625 | * further work with defined data easier. | ||
626 | */ | ||
627 | |||
628 | /* GATE_IP_LEFTBUS */ | ||
629 | GATE(CLK_ASYNC_G3D, "async_g3d", "div_aclk_100", GATE_IP_LEFTBUS, 6, | ||
630 | CLK_IGNORE_UNUSED, 0), | ||
631 | GATE(CLK_ASYNC_MFCL, "async_mfcl", "div_aclk_100", GATE_IP_LEFTBUS, 4, | ||
632 | CLK_IGNORE_UNUSED, 0), | ||
633 | GATE(CLK_ASYNC_TVX, "async_tvx", "div_aclk_100", GATE_IP_LEFTBUS, 3, | ||
634 | CLK_IGNORE_UNUSED, 0), | ||
635 | GATE(CLK_PPMULEFT, "ppmuleft", "div_aclk_100", GATE_IP_LEFTBUS, 1, | ||
636 | CLK_IGNORE_UNUSED, 0), | ||
637 | GATE(CLK_GPIO_LEFT, "gpio_left", "div_aclk_100", GATE_IP_LEFTBUS, 0, | ||
638 | CLK_IGNORE_UNUSED, 0), | ||
639 | |||
640 | /* GATE_IP_IMAGE */ | ||
641 | GATE(CLK_PPMUIMAGE, "ppmuimage", "div_aclk_100", GATE_IP_IMAGE, | ||
642 | 9, 0, 0), | ||
643 | GATE(CLK_QEMDMA2, "qe_mdma2", "div_aclk_100", GATE_IP_IMAGE, | ||
644 | 8, 0, 0), | ||
645 | GATE(CLK_QEROTATOR, "qe_rotator", "div_aclk_100", GATE_IP_IMAGE, | ||
646 | 7, 0, 0), | ||
647 | GATE(CLK_SMMUMDMA2, "smmu_mdam2", "div_aclk_100", GATE_IP_IMAGE, | ||
648 | 5, 0, 0), | ||
649 | GATE(CLK_SMMUROTATOR, "smmu_rotator", "div_aclk_100", GATE_IP_IMAGE, | ||
650 | 4, 0, 0), | ||
651 | GATE(CLK_MDMA2, "mdma2", "div_aclk_100", GATE_IP_IMAGE, 2, 0, 0), | ||
652 | GATE(CLK_ROTATOR, "rotator", "div_aclk_100", GATE_IP_IMAGE, 1, 0, 0), | ||
653 | |||
654 | /* GATE_IP_RIGHTBUS */ | ||
655 | GATE(CLK_ASYNC_ISPMX, "async_ispmx", "div_aclk_100", | ||
656 | GATE_IP_RIGHTBUS, 9, CLK_IGNORE_UNUSED, 0), | ||
657 | GATE(CLK_ASYNC_MAUDIOX, "async_maudiox", "div_aclk_100", | ||
658 | GATE_IP_RIGHTBUS, 7, CLK_IGNORE_UNUSED, 0), | ||
659 | GATE(CLK_ASYNC_MFCR, "async_mfcr", "div_aclk_100", | ||
660 | GATE_IP_RIGHTBUS, 6, CLK_IGNORE_UNUSED, 0), | ||
661 | GATE(CLK_ASYNC_FSYSD, "async_fsysd", "div_aclk_100", | ||
662 | GATE_IP_RIGHTBUS, 5, CLK_IGNORE_UNUSED, 0), | ||
663 | GATE(CLK_ASYNC_LCD0X, "async_lcd0x", "div_aclk_100", | ||
664 | GATE_IP_RIGHTBUS, 3, CLK_IGNORE_UNUSED, 0), | ||
665 | GATE(CLK_ASYNC_CAMX, "async_camx", "div_aclk_100", | ||
666 | GATE_IP_RIGHTBUS, 2, CLK_IGNORE_UNUSED, 0), | ||
667 | GATE(CLK_PPMURIGHT, "ppmuright", "div_aclk_100", | ||
668 | GATE_IP_RIGHTBUS, 1, CLK_IGNORE_UNUSED, 0), | ||
669 | GATE(CLK_GPIO_RIGHT, "gpio_right", "div_aclk_100", | ||
670 | GATE_IP_RIGHTBUS, 0, CLK_IGNORE_UNUSED, 0), | ||
671 | |||
672 | /* GATE_IP_PERIR */ | ||
673 | GATE(CLK_ANTIRBK_APBIF, "antirbk_apbif", "div_aclk_100", | ||
674 | GATE_IP_PERIR, 24, CLK_IGNORE_UNUSED, 0), | ||
675 | GATE(CLK_EFUSE_WRITER_APBIF, "efuse_writer_apbif", "div_aclk_100", | ||
676 | GATE_IP_PERIR, 23, CLK_IGNORE_UNUSED, 0), | ||
677 | GATE(CLK_MONOCNT, "monocnt", "div_aclk_100", GATE_IP_PERIR, 22, | ||
678 | CLK_IGNORE_UNUSED, 0), | ||
679 | GATE(CLK_TZPC6, "tzpc6", "div_aclk_100", GATE_IP_PERIR, 21, | ||
680 | CLK_IGNORE_UNUSED, 0), | ||
681 | GATE(CLK_PROVISIONKEY1, "provisionkey1", "div_aclk_100", | ||
682 | GATE_IP_PERIR, 20, CLK_IGNORE_UNUSED, 0), | ||
683 | GATE(CLK_PROVISIONKEY0, "provisionkey0", "div_aclk_100", | ||
684 | GATE_IP_PERIR, 19, CLK_IGNORE_UNUSED, 0), | ||
685 | GATE(CLK_CMU_ISPPART, "cmu_isppart", "div_aclk_100", GATE_IP_PERIR, 18, | ||
686 | CLK_IGNORE_UNUSED, 0), | ||
687 | GATE(CLK_TMU_APBIF, "tmu_apbif", "div_aclk_100", | ||
688 | GATE_IP_PERIR, 17, 0, 0), | ||
689 | GATE(CLK_KEYIF, "keyif", "div_aclk_100", GATE_IP_PERIR, 16, 0, 0), | ||
690 | GATE(CLK_RTC, "rtc", "div_aclk_100", GATE_IP_PERIR, 15, 0, 0), | ||
691 | GATE(CLK_WDT, "wdt", "div_aclk_100", GATE_IP_PERIR, 14, 0, 0), | ||
692 | GATE(CLK_MCT, "mct", "div_aclk_100", GATE_IP_PERIR, 13, 0, 0), | ||
693 | GATE(CLK_SECKEY, "seckey", "div_aclk_100", GATE_IP_PERIR, 12, | ||
694 | CLK_IGNORE_UNUSED, 0), | ||
695 | GATE(CLK_HDMI_CEC, "hdmi_cec", "div_aclk_100", GATE_IP_PERIR, 11, | ||
696 | CLK_IGNORE_UNUSED, 0), | ||
697 | GATE(CLK_TZPC5, "tzpc5", "div_aclk_100", GATE_IP_PERIR, 10, | ||
698 | CLK_IGNORE_UNUSED, 0), | ||
699 | GATE(CLK_TZPC4, "tzpc4", "div_aclk_100", GATE_IP_PERIR, 9, | ||
700 | CLK_IGNORE_UNUSED, 0), | ||
701 | GATE(CLK_TZPC3, "tzpc3", "div_aclk_100", GATE_IP_PERIR, 8, | ||
702 | CLK_IGNORE_UNUSED, 0), | ||
703 | GATE(CLK_TZPC2, "tzpc2", "div_aclk_100", GATE_IP_PERIR, 7, | ||
704 | CLK_IGNORE_UNUSED, 0), | ||
705 | GATE(CLK_TZPC1, "tzpc1", "div_aclk_100", GATE_IP_PERIR, 6, | ||
706 | CLK_IGNORE_UNUSED, 0), | ||
707 | GATE(CLK_TZPC0, "tzpc0", "div_aclk_100", GATE_IP_PERIR, 5, | ||
708 | CLK_IGNORE_UNUSED, 0), | ||
709 | GATE(CLK_CMU_COREPART, "cmu_corepart", "div_aclk_100", GATE_IP_PERIR, 4, | ||
710 | CLK_IGNORE_UNUSED, 0), | ||
711 | GATE(CLK_CMU_TOPPART, "cmu_toppart", "div_aclk_100", GATE_IP_PERIR, 3, | ||
712 | CLK_IGNORE_UNUSED, 0), | ||
713 | GATE(CLK_PMU_APBIF, "pmu_apbif", "div_aclk_100", GATE_IP_PERIR, 2, | ||
714 | CLK_IGNORE_UNUSED, 0), | ||
715 | GATE(CLK_SYSREG, "sysreg", "div_aclk_100", GATE_IP_PERIR, 1, | ||
716 | CLK_IGNORE_UNUSED, 0), | ||
717 | GATE(CLK_CHIP_ID, "chip_id", "div_aclk_100", GATE_IP_PERIR, 0, | ||
718 | CLK_IGNORE_UNUSED, 0), | ||
719 | |||
720 | /* GATE_SCLK_CAM - non-completed */ | ||
721 | GATE(CLK_SCLK_PXLAYSNC_CSIS1_FIMC, "sclk_pxlasync_csis1_fimc", | ||
722 | "div_pxlasync_csis1_fimc", GATE_SCLK_CAM, 11, | ||
723 | CLK_SET_RATE_PARENT, 0), | ||
724 | GATE(CLK_SCLK_PXLAYSNC_CSIS0_FIMC, "sclk_pxlasync_csis0_fimc", | ||
725 | "div_pxlasync_csis0_fimc", GATE_SCLK_CAM, | ||
726 | 10, CLK_SET_RATE_PARENT, 0), | ||
727 | GATE(CLK_SCLK_JPEG, "sclk_jpeg", "div_jpeg", | ||
728 | GATE_SCLK_CAM, 8, CLK_SET_RATE_PARENT, 0), | ||
729 | GATE(CLK_SCLK_CSIS1, "sclk_csis1", "div_csis1", | ||
730 | GATE_SCLK_CAM, 7, CLK_SET_RATE_PARENT, 0), | ||
731 | GATE(CLK_SCLK_CSIS0, "sclk_csis0", "div_csis0", | ||
732 | GATE_SCLK_CAM, 6, CLK_SET_RATE_PARENT, 0), | ||
733 | GATE(CLK_SCLK_CAM1, "sclk_cam1", "div_cam1", | ||
734 | GATE_SCLK_CAM, 5, CLK_SET_RATE_PARENT, 0), | ||
735 | GATE(CLK_SCLK_FIMC3_LCLK, "sclk_fimc3_lclk", "div_fimc3_lclk", | ||
736 | GATE_SCLK_CAM, 3, CLK_SET_RATE_PARENT, 0), | ||
737 | GATE(CLK_SCLK_FIMC2_LCLK, "sclk_fimc2_lclk", "div_fimc2_lclk", | ||
738 | GATE_SCLK_CAM, 2, CLK_SET_RATE_PARENT, 0), | ||
739 | GATE(CLK_SCLK_FIMC1_LCLK, "sclk_fimc1_lclk", "div_fimc1_lclk", | ||
740 | GATE_SCLK_CAM, 1, CLK_SET_RATE_PARENT, 0), | ||
741 | GATE(CLK_SCLK_FIMC0_LCLK, "sclk_fimc0_lclk", "div_fimc0_lclk", | ||
742 | GATE_SCLK_CAM, 0, CLK_SET_RATE_PARENT, 0), | ||
743 | |||
744 | /* GATE_SCLK_TV */ | ||
745 | GATE(CLK_SCLK_PIXEL, "sclk_pixel", "div_tv_blk", | ||
746 | GATE_SCLK_TV, 3, CLK_SET_RATE_PARENT, 0), | ||
747 | GATE(CLK_SCLK_HDMI, "sclk_hdmi", "mout_hdmi", | ||
748 | GATE_SCLK_TV, 2, CLK_SET_RATE_PARENT, 0), | ||
749 | GATE(CLK_SCLK_MIXER, "sclk_mixer", "div_tv_blk", | ||
750 | GATE_SCLK_TV, 0, CLK_SET_RATE_PARENT, 0), | ||
751 | |||
752 | /* GATE_SCLK_MFC */ | ||
753 | GATE(CLK_SCLK_MFC, "sclk_mfc", "div_mfc", | ||
754 | GATE_SCLK_MFC, 0, CLK_SET_RATE_PARENT, 0), | ||
755 | |||
756 | /* GATE_SCLK_G3D */ | ||
757 | GATE(CLK_SCLK_G3D, "sclk_g3d", "div_g3d", | ||
758 | GATE_SCLK_G3D, 0, CLK_SET_RATE_PARENT, 0), | ||
759 | |||
760 | /* GATE_SCLK_LCD */ | ||
761 | GATE(CLK_SCLK_MIPIDPHY4L, "sclk_mipidphy4l", "div_mipi0", | ||
762 | GATE_SCLK_LCD, 4, CLK_SET_RATE_PARENT, 0), | ||
763 | GATE(CLK_SCLK_MIPI0, "sclk_mipi0", "div_mipi0_pre", | ||
764 | GATE_SCLK_LCD, 3, CLK_SET_RATE_PARENT, 0), | ||
765 | GATE(CLK_SCLK_MDNIE0, "sclk_mdnie0", "div_fimd0", | ||
766 | GATE_SCLK_LCD, 1, CLK_SET_RATE_PARENT, 0), | ||
767 | GATE(CLK_SCLK_FIMD0, "sclk_fimd0", "div_fimd0", | ||
768 | GATE_SCLK_LCD, 0, CLK_SET_RATE_PARENT, 0), | ||
769 | |||
770 | /* GATE_SCLK_MAUDIO */ | ||
771 | GATE(CLK_SCLK_PCM0, "sclk_pcm0", "div_pcm0", | ||
772 | GATE_SCLK_MAUDIO, 1, CLK_SET_RATE_PARENT, 0), | ||
773 | GATE(CLK_SCLK_AUDIO0, "sclk_audio0", "div_audio0", | ||
774 | GATE_SCLK_MAUDIO, 0, CLK_SET_RATE_PARENT, 0), | ||
775 | |||
776 | /* GATE_SCLK_FSYS */ | ||
777 | GATE(CLK_SCLK_TSADC, "sclk_tsadc", "div_tsadc_pre", | ||
778 | GATE_SCLK_FSYS, 9, CLK_SET_RATE_PARENT, 0), | ||
779 | GATE(CLK_SCLK_EBI, "sclk_ebi", "div_ebi", | ||
780 | GATE_SCLK_FSYS, 6, CLK_SET_RATE_PARENT, 0), | ||
781 | GATE(CLK_SCLK_MMC2, "sclk_mmc2", "div_mmc2_pre", | ||
782 | GATE_SCLK_FSYS, 2, CLK_SET_RATE_PARENT, 0), | ||
783 | GATE(CLK_SCLK_MMC1, "sclk_mmc1", "div_mmc1_pre", | ||
784 | GATE_SCLK_FSYS, 1, CLK_SET_RATE_PARENT, 0), | ||
785 | GATE(CLK_SCLK_MMC0, "sclk_mmc0", "div_mmc0_pre", | ||
786 | GATE_SCLK_FSYS, 0, CLK_SET_RATE_PARENT, 0), | ||
787 | |||
788 | /* GATE_SCLK_PERIL */ | ||
789 | GATE(CLK_SCLK_I2S, "sclk_i2s1", "div_i2s1", | ||
790 | GATE_SCLK_PERIL, 18, CLK_SET_RATE_PARENT, 0), | ||
791 | GATE(CLK_SCLK_PCM2, "sclk_pcm2", "div_pcm2", | ||
792 | GATE_SCLK_PERIL, 16, CLK_SET_RATE_PARENT, 0), | ||
793 | GATE(CLK_SCLK_PCM1, "sclk_pcm1", "div_pcm1", | ||
794 | GATE_SCLK_PERIL, 15, CLK_SET_RATE_PARENT, 0), | ||
795 | GATE(CLK_SCLK_AUDIO2, "sclk_audio2", "div_audio2", | ||
796 | GATE_SCLK_PERIL, 14, CLK_SET_RATE_PARENT, 0), | ||
797 | GATE(CLK_SCLK_AUDIO1, "sclk_audio1", "div_audio1", | ||
798 | GATE_SCLK_PERIL, 13, CLK_SET_RATE_PARENT, 0), | ||
799 | GATE(CLK_SCLK_SPDIF, "sclk_spdif", "mout_spdif", | ||
800 | GATE_SCLK_PERIL, 10, CLK_SET_RATE_PARENT, 0), | ||
801 | GATE(CLK_SCLK_SPI2, "sclk_spi2", "div_spi2_pre", | ||
802 | GATE_SCLK_PERIL, 8, CLK_SET_RATE_PARENT, 0), | ||
803 | GATE(CLK_SCLK_SPI1, "sclk_spi1", "div_spi1_pre", | ||
804 | GATE_SCLK_PERIL, 7, CLK_SET_RATE_PARENT, 0), | ||
805 | GATE(CLK_SCLK_SPI0, "sclk_spi0", "div_spi0_pre", | ||
806 | GATE_SCLK_PERIL, 6, CLK_SET_RATE_PARENT, 0), | ||
807 | GATE(CLK_SCLK_UART3, "sclk_uart3", "div_uart3", | ||
808 | GATE_SCLK_PERIL, 3, CLK_SET_RATE_PARENT, 0), | ||
809 | GATE(CLK_SCLK_UART2, "sclk_uart2", "div_uart2", | ||
810 | GATE_SCLK_PERIL, 2, CLK_SET_RATE_PARENT, 0), | ||
811 | GATE(CLK_SCLK_UART1, "sclk_uart1", "div_uart1", | ||
812 | GATE_SCLK_PERIL, 1, CLK_SET_RATE_PARENT, 0), | ||
813 | GATE(CLK_SCLK_UART0, "sclk_uart0", "div_uart0", | ||
814 | GATE_SCLK_PERIL, 0, CLK_SET_RATE_PARENT, 0), | ||
815 | |||
816 | /* GATE_IP_CAM */ | ||
817 | GATE(CLK_SMMUFIMC_LITE2, "smmufimc_lite2", "div_aclk_160", GATE_IP_CAM, | ||
818 | 22, CLK_IGNORE_UNUSED, 0), | ||
819 | GATE(CLK_FIMC_LITE2, "fimc_lite2", "div_aclk_160", GATE_IP_CAM, | ||
820 | 20, CLK_IGNORE_UNUSED, 0), | ||
821 | GATE(CLK_PIXELASYNCM1, "pixelasyncm1", "div_aclk_160", GATE_IP_CAM, | ||
822 | 18, CLK_IGNORE_UNUSED, 0), | ||
823 | GATE(CLK_PIXELASYNCM0, "pixelasyncm0", "div_aclk_160", GATE_IP_CAM, | ||
824 | 17, CLK_IGNORE_UNUSED, 0), | ||
825 | GATE(CLK_PPMUCAMIF, "ppmucamif", "div_aclk_160", GATE_IP_CAM, | ||
826 | 16, CLK_IGNORE_UNUSED, 0), | ||
827 | GATE(CLK_SMMUJPEG, "smmujpeg", "div_aclk_160", GATE_IP_CAM, 11, 0, 0), | ||
828 | GATE(CLK_SMMUFIMC3, "smmufimc3", "div_aclk_160", GATE_IP_CAM, 10, 0, 0), | ||
829 | GATE(CLK_SMMUFIMC2, "smmufimc2", "div_aclk_160", GATE_IP_CAM, 9, 0, 0), | ||
830 | GATE(CLK_SMMUFIMC1, "smmufimc1", "div_aclk_160", GATE_IP_CAM, 8, 0, 0), | ||
831 | GATE(CLK_SMMUFIMC0, "smmufimc0", "div_aclk_160", GATE_IP_CAM, 7, 0, 0), | ||
832 | GATE(CLK_JPEG, "jpeg", "div_aclk_160", GATE_IP_CAM, 6, 0, 0), | ||
833 | GATE(CLK_CSIS1, "csis1", "div_aclk_160", GATE_IP_CAM, 5, 0, 0), | ||
834 | GATE(CLK_CSIS0, "csis0", "div_aclk_160", GATE_IP_CAM, 4, 0, 0), | ||
835 | GATE(CLK_FIMC3, "fimc3", "div_aclk_160", GATE_IP_CAM, 3, 0, 0), | ||
836 | GATE(CLK_FIMC2, "fimc2", "div_aclk_160", GATE_IP_CAM, 2, 0, 0), | ||
837 | GATE(CLK_FIMC1, "fimc1", "div_aclk_160", GATE_IP_CAM, 1, 0, 0), | ||
838 | GATE(CLK_FIMC0, "fimc0", "div_aclk_160", GATE_IP_CAM, 0, 0, 0), | ||
839 | |||
840 | /* GATE_IP_TV */ | ||
841 | GATE(CLK_PPMUTV, "ppmutv", "div_aclk_100", GATE_IP_TV, 5, 0, 0), | ||
842 | GATE(CLK_SMMUTV, "smmutv", "div_aclk_100", GATE_IP_TV, 4, 0, 0), | ||
843 | GATE(CLK_HDMI, "hdmi", "div_aclk_100", GATE_IP_TV, 3, 0, 0), | ||
844 | GATE(CLK_MIXER, "mixer", "div_aclk_100", GATE_IP_TV, 1, 0, 0), | ||
845 | GATE(CLK_VP, "vp", "div_aclk_100", GATE_IP_TV, 0, 0, 0), | ||
846 | |||
847 | /* GATE_IP_MFC */ | ||
848 | GATE(CLK_PPMUMFC_R, "ppmumfc_r", "div_aclk_200", GATE_IP_MFC, 4, | ||
849 | CLK_IGNORE_UNUSED, 0), | ||
850 | GATE(CLK_PPMUMFC_L, "ppmumfc_l", "div_aclk_200", GATE_IP_MFC, 3, | ||
851 | CLK_IGNORE_UNUSED, 0), | ||
852 | GATE(CLK_SMMUMFC_R, "smmumfc_r", "div_aclk_200", GATE_IP_MFC, 2, 0, 0), | ||
853 | GATE(CLK_SMMUMFC_L, "smmumfc_l", "div_aclk_200", GATE_IP_MFC, 1, 0, 0), | ||
854 | GATE(CLK_MFC, "mfc", "div_aclk_200", GATE_IP_MFC, 0, 0, 0), | ||
855 | |||
856 | /* GATE_IP_G3D */ | ||
857 | GATE(CLK_PPMUG3D, "ppmug3d", "div_aclk_200", GATE_IP_G3D, 1, | ||
858 | CLK_IGNORE_UNUSED, 0), | ||
859 | GATE(CLK_G3D, "g3d", "div_aclk_200", GATE_IP_G3D, 0, 0, 0), | ||
860 | |||
861 | /* GATE_IP_LCD */ | ||
862 | GATE(CLK_PPMULCD0, "ppmulcd0", "div_aclk_160", GATE_IP_LCD, 5, | ||
863 | CLK_IGNORE_UNUSED, 0), | ||
864 | GATE(CLK_SMMUFIMD0, "smmufimd0", "div_aclk_160", GATE_IP_LCD, 4, 0, 0), | ||
865 | GATE(CLK_DSIM0, "dsim0", "div_aclk_160", GATE_IP_LCD, 3, 0, 0), | ||
866 | GATE(CLK_SMIES, "smies", "div_aclk_160", GATE_IP_LCD, 2, 0, 0), | ||
867 | GATE(CLK_MIE0, "mie0", "div_aclk_160", GATE_IP_LCD, 1, 0, 0), | ||
868 | GATE(CLK_FIMD0, "fimd0", "div_aclk_160", GATE_IP_LCD, 0, 0, 0), | ||
869 | |||
870 | /* GATE_IP_FSYS */ | ||
871 | GATE(CLK_TSADC, "tsadc", "div_aclk_200", GATE_IP_FSYS, 20, 0, 0), | ||
872 | GATE(CLK_PPMUFILE, "ppmufile", "div_aclk_200", GATE_IP_FSYS, 17, | ||
873 | CLK_IGNORE_UNUSED, 0), | ||
874 | GATE(CLK_NFCON, "nfcon", "div_aclk_200", GATE_IP_FSYS, 16, 0, 0), | ||
875 | GATE(CLK_USBDEVICE, "usbdevice", "div_aclk_200", GATE_IP_FSYS, 13, | ||
876 | 0, 0), | ||
877 | GATE(CLK_USBHOST, "usbhost", "div_aclk_200", GATE_IP_FSYS, 12, 0, 0), | ||
878 | GATE(CLK_SROMC, "sromc", "div_aclk_200", GATE_IP_FSYS, 11, 0, 0), | ||
879 | GATE(CLK_SDMMC2, "sdmmc2", "div_aclk_200", GATE_IP_FSYS, 7, 0, 0), | ||
880 | GATE(CLK_SDMMC1, "sdmmc1", "div_aclk_200", GATE_IP_FSYS, 6, 0, 0), | ||
881 | GATE(CLK_SDMMC0, "sdmmc0", "div_aclk_200", GATE_IP_FSYS, 5, 0, 0), | ||
882 | GATE(CLK_PDMA1, "pdma1", "div_aclk_200", GATE_IP_FSYS, 1, 0, 0), | ||
883 | GATE(CLK_PDMA0, "pdma0", "div_aclk_200", GATE_IP_FSYS, 0, 0, 0), | ||
884 | |||
885 | /* GATE_IP_PERIL */ | ||
886 | GATE(CLK_SPDIF, "spdif", "div_aclk_100", GATE_IP_PERIL, 26, 0, 0), | ||
887 | GATE(CLK_PWM, "pwm", "div_aclk_100", GATE_IP_PERIL, 24, 0, 0), | ||
888 | GATE(CLK_PCM2, "pcm2", "div_aclk_100", GATE_IP_PERIL, 23, 0, 0), | ||
889 | GATE(CLK_PCM1, "pcm1", "div_aclk_100", GATE_IP_PERIL, 22, 0, 0), | ||
890 | GATE(CLK_I2S1, "i2s1", "div_aclk_100", GATE_IP_PERIL, 20, 0, 0), | ||
891 | GATE(CLK_SPI2, "spi2", "div_aclk_100", GATE_IP_PERIL, 18, 0, 0), | ||
892 | GATE(CLK_SPI1, "spi1", "div_aclk_100", GATE_IP_PERIL, 17, 0, 0), | ||
893 | GATE(CLK_SPI0, "spi0", "div_aclk_100", GATE_IP_PERIL, 16, 0, 0), | ||
894 | GATE(CLK_I2CHDMI, "i2chdmi", "div_aclk_100", GATE_IP_PERIL, 14, 0, 0), | ||
895 | GATE(CLK_I2C7, "i2c7", "div_aclk_100", GATE_IP_PERIL, 13, 0, 0), | ||
896 | GATE(CLK_I2C6, "i2c6", "div_aclk_100", GATE_IP_PERIL, 12, 0, 0), | ||
897 | GATE(CLK_I2C5, "i2c5", "div_aclk_100", GATE_IP_PERIL, 11, 0, 0), | ||
898 | GATE(CLK_I2C4, "i2c4", "div_aclk_100", GATE_IP_PERIL, 10, 0, 0), | ||
899 | GATE(CLK_I2C3, "i2c3", "div_aclk_100", GATE_IP_PERIL, 9, 0, 0), | ||
900 | GATE(CLK_I2C2, "i2c2", "div_aclk_100", GATE_IP_PERIL, 8, 0, 0), | ||
901 | GATE(CLK_I2C1, "i2c1", "div_aclk_100", GATE_IP_PERIL, 7, 0, 0), | ||
902 | GATE(CLK_I2C0, "i2c0", "div_aclk_100", GATE_IP_PERIL, 6, 0, 0), | ||
903 | GATE(CLK_UART3, "uart3", "div_aclk_100", GATE_IP_PERIL, 3, 0, 0), | ||
904 | GATE(CLK_UART2, "uart2", "div_aclk_100", GATE_IP_PERIL, 2, 0, 0), | ||
905 | GATE(CLK_UART1, "uart1", "div_aclk_100", GATE_IP_PERIL, 1, 0, 0), | ||
906 | GATE(CLK_UART0, "uart0", "div_aclk_100", GATE_IP_PERIL, 0, 0, 0), | ||
907 | }; | ||
908 | |||
909 | /* | ||
910 | * APLL & MPLL & BPLL & ISP_PLL & DISP_PLL & G3D_PLL | ||
911 | */ | ||
912 | static struct samsung_pll_rate_table exynos4415_pll_rates[] = { | ||
913 | PLL_35XX_RATE(1600000000, 400, 3, 1), | ||
914 | PLL_35XX_RATE(1500000000, 250, 2, 1), | ||
915 | PLL_35XX_RATE(1400000000, 175, 3, 0), | ||
916 | PLL_35XX_RATE(1300000000, 325, 3, 1), | ||
917 | PLL_35XX_RATE(1200000000, 400, 4, 1), | ||
918 | PLL_35XX_RATE(1100000000, 275, 3, 1), | ||
919 | PLL_35XX_RATE(1066000000, 533, 6, 1), | ||
920 | PLL_35XX_RATE(1000000000, 250, 3, 1), | ||
921 | PLL_35XX_RATE(960000000, 320, 4, 1), | ||
922 | PLL_35XX_RATE(900000000, 300, 4, 1), | ||
923 | PLL_35XX_RATE(850000000, 425, 6, 1), | ||
924 | PLL_35XX_RATE(800000000, 200, 3, 1), | ||
925 | PLL_35XX_RATE(700000000, 175, 3, 1), | ||
926 | PLL_35XX_RATE(667000000, 667, 12, 1), | ||
927 | PLL_35XX_RATE(600000000, 400, 4, 2), | ||
928 | PLL_35XX_RATE(550000000, 275, 3, 2), | ||
929 | PLL_35XX_RATE(533000000, 533, 6, 2), | ||
930 | PLL_35XX_RATE(520000000, 260, 3, 2), | ||
931 | PLL_35XX_RATE(500000000, 250, 3, 2), | ||
932 | PLL_35XX_RATE(440000000, 220, 3, 2), | ||
933 | PLL_35XX_RATE(400000000, 200, 3, 2), | ||
934 | PLL_35XX_RATE(350000000, 175, 3, 2), | ||
935 | PLL_35XX_RATE(300000000, 300, 3, 3), | ||
936 | PLL_35XX_RATE(266000000, 266, 3, 3), | ||
937 | PLL_35XX_RATE(200000000, 200, 3, 3), | ||
938 | PLL_35XX_RATE(160000000, 160, 3, 3), | ||
939 | PLL_35XX_RATE(100000000, 200, 3, 4), | ||
940 | { /* sentinel */ } | ||
941 | }; | ||
942 | |||
943 | /* EPLL */ | ||
944 | static struct samsung_pll_rate_table exynos4415_epll_rates[] = { | ||
945 | PLL_36XX_RATE(800000000, 200, 3, 1, 0), | ||
946 | PLL_36XX_RATE(288000000, 96, 2, 2, 0), | ||
947 | PLL_36XX_RATE(192000000, 128, 2, 3, 0), | ||
948 | PLL_36XX_RATE(144000000, 96, 2, 3, 0), | ||
949 | PLL_36XX_RATE(96000000, 128, 2, 4, 0), | ||
950 | PLL_36XX_RATE(84000000, 112, 2, 4, 0), | ||
951 | PLL_36XX_RATE(80750011, 107, 2, 4, 43691), | ||
952 | PLL_36XX_RATE(73728004, 98, 2, 4, 19923), | ||
953 | PLL_36XX_RATE(67987602, 271, 3, 5, 62285), | ||
954 | PLL_36XX_RATE(65911004, 175, 2, 5, 49982), | ||
955 | PLL_36XX_RATE(50000000, 200, 3, 5, 0), | ||
956 | PLL_36XX_RATE(49152003, 131, 2, 5, 4719), | ||
957 | PLL_36XX_RATE(48000000, 128, 2, 5, 0), | ||
958 | PLL_36XX_RATE(45250000, 181, 3, 5, 0), | ||
959 | { /* sentinel */ } | ||
960 | }; | ||
961 | |||
962 | static struct samsung_pll_clock exynos4415_plls[nr_plls] __initdata = { | ||
963 | [apll] = PLL(pll_35xx, CLK_FOUT_APLL, "fout_apll", "fin_pll", | ||
964 | APLL_LOCK, APLL_CON0, NULL), | ||
965 | [epll] = PLL(pll_36xx, CLK_FOUT_EPLL, "fout_epll", "fin_pll", | ||
966 | EPLL_LOCK, EPLL_CON0, NULL), | ||
967 | [g3d_pll] = PLL(pll_35xx, CLK_FOUT_G3D_PLL, "fout_g3d_pll", | ||
968 | "mout_g3d_pllsrc", G3D_PLL_LOCK, G3D_PLL_CON0, NULL), | ||
969 | [isp_pll] = PLL(pll_35xx, CLK_FOUT_ISP_PLL, "fout_isp_pll", "fin_pll", | ||
970 | ISP_PLL_LOCK, ISP_PLL_CON0, NULL), | ||
971 | [disp_pll] = PLL(pll_35xx, CLK_FOUT_DISP_PLL, "fout_disp_pll", | ||
972 | "fin_pll", DISP_PLL_LOCK, DISP_PLL_CON0, NULL), | ||
973 | }; | ||
974 | |||
975 | static void __init exynos4415_cmu_init(struct device_node *np) | ||
976 | { | ||
977 | void __iomem *reg_base; | ||
978 | |||
979 | reg_base = of_iomap(np, 0); | ||
980 | if (!reg_base) | ||
981 | panic("%s: failed to map registers\n", __func__); | ||
982 | |||
983 | exynos4415_ctx = samsung_clk_init(np, reg_base, CLK_NR_CLKS); | ||
984 | if (!exynos4415_ctx) | ||
985 | panic("%s: unable to allocate context.\n", __func__); | ||
986 | |||
987 | exynos4415_plls[apll].rate_table = exynos4415_pll_rates; | ||
988 | exynos4415_plls[epll].rate_table = exynos4415_epll_rates; | ||
989 | exynos4415_plls[g3d_pll].rate_table = exynos4415_pll_rates; | ||
990 | exynos4415_plls[isp_pll].rate_table = exynos4415_pll_rates; | ||
991 | exynos4415_plls[disp_pll].rate_table = exynos4415_pll_rates; | ||
992 | |||
993 | samsung_clk_register_fixed_factor(exynos4415_ctx, | ||
994 | exynos4415_fixed_factor_clks, | ||
995 | ARRAY_SIZE(exynos4415_fixed_factor_clks)); | ||
996 | samsung_clk_register_fixed_rate(exynos4415_ctx, | ||
997 | exynos4415_fixed_rate_clks, | ||
998 | ARRAY_SIZE(exynos4415_fixed_rate_clks)); | ||
999 | |||
1000 | samsung_clk_register_pll(exynos4415_ctx, exynos4415_plls, | ||
1001 | ARRAY_SIZE(exynos4415_plls), reg_base); | ||
1002 | samsung_clk_register_mux(exynos4415_ctx, exynos4415_mux_clks, | ||
1003 | ARRAY_SIZE(exynos4415_mux_clks)); | ||
1004 | samsung_clk_register_div(exynos4415_ctx, exynos4415_div_clks, | ||
1005 | ARRAY_SIZE(exynos4415_div_clks)); | ||
1006 | samsung_clk_register_gate(exynos4415_ctx, exynos4415_gate_clks, | ||
1007 | ARRAY_SIZE(exynos4415_gate_clks)); | ||
1008 | |||
1009 | exynos4415_clk_sleep_init(); | ||
1010 | |||
1011 | samsung_clk_of_add_provider(np, exynos4415_ctx); | ||
1012 | } | ||
1013 | CLK_OF_DECLARE(exynos4415_cmu, "samsung,exynos4415-cmu", exynos4415_cmu_init); | ||
1014 | |||
1015 | /* | ||
1016 | * CMU DMC | ||
1017 | */ | ||
1018 | |||
1019 | #define MPLL_LOCK 0x008 | ||
1020 | #define MPLL_CON0 0x108 | ||
1021 | #define MPLL_CON1 0x10c | ||
1022 | #define MPLL_CON2 0x110 | ||
1023 | #define BPLL_LOCK 0x118 | ||
1024 | #define BPLL_CON0 0x218 | ||
1025 | #define BPLL_CON1 0x21c | ||
1026 | #define BPLL_CON2 0x220 | ||
1027 | #define SRC_DMC 0x300 | ||
1028 | #define DIV_DMC1 0x504 | ||
1029 | |||
1030 | enum exynos4415_dmc_plls { | ||
1031 | mpll, bpll, | ||
1032 | nr_dmc_plls, | ||
1033 | }; | ||
1034 | |||
1035 | static struct samsung_clk_provider *exynos4415_dmc_ctx; | ||
1036 | |||
1037 | #ifdef CONFIG_PM_SLEEP | ||
1038 | static struct samsung_clk_reg_dump *exynos4415_dmc_clk_regs; | ||
1039 | |||
1040 | static unsigned long exynos4415_cmu_dmc_clk_regs[] __initdata = { | ||
1041 | MPLL_LOCK, | ||
1042 | MPLL_CON0, | ||
1043 | MPLL_CON1, | ||
1044 | MPLL_CON2, | ||
1045 | BPLL_LOCK, | ||
1046 | BPLL_CON0, | ||
1047 | BPLL_CON1, | ||
1048 | BPLL_CON2, | ||
1049 | SRC_DMC, | ||
1050 | DIV_DMC1, | ||
1051 | }; | ||
1052 | |||
1053 | static int exynos4415_dmc_clk_suspend(void) | ||
1054 | { | ||
1055 | samsung_clk_save(exynos4415_dmc_ctx->reg_base, | ||
1056 | exynos4415_dmc_clk_regs, | ||
1057 | ARRAY_SIZE(exynos4415_cmu_dmc_clk_regs)); | ||
1058 | return 0; | ||
1059 | } | ||
1060 | |||
1061 | static void exynos4415_dmc_clk_resume(void) | ||
1062 | { | ||
1063 | samsung_clk_restore(exynos4415_dmc_ctx->reg_base, | ||
1064 | exynos4415_dmc_clk_regs, | ||
1065 | ARRAY_SIZE(exynos4415_cmu_dmc_clk_regs)); | ||
1066 | } | ||
1067 | |||
1068 | static struct syscore_ops exynos4415_dmc_clk_syscore_ops = { | ||
1069 | .suspend = exynos4415_dmc_clk_suspend, | ||
1070 | .resume = exynos4415_dmc_clk_resume, | ||
1071 | }; | ||
1072 | |||
1073 | static void exynos4415_dmc_clk_sleep_init(void) | ||
1074 | { | ||
1075 | exynos4415_dmc_clk_regs = | ||
1076 | samsung_clk_alloc_reg_dump(exynos4415_cmu_dmc_clk_regs, | ||
1077 | ARRAY_SIZE(exynos4415_cmu_dmc_clk_regs)); | ||
1078 | if (!exynos4415_dmc_clk_regs) { | ||
1079 | pr_warn("%s: Failed to allocate sleep save data\n", __func__); | ||
1080 | return; | ||
1081 | } | ||
1082 | |||
1083 | register_syscore_ops(&exynos4415_dmc_clk_syscore_ops); | ||
1084 | } | ||
1085 | #else | ||
1086 | static inline void exynos4415_dmc_clk_sleep_init(void) { } | ||
1087 | #endif /* CONFIG_PM_SLEEP */ | ||
1088 | |||
1089 | PNAME(mout_mpll_p) = { "fin_pll", "fout_mpll", }; | ||
1090 | PNAME(mout_bpll_p) = { "fin_pll", "fout_bpll", }; | ||
1091 | PNAME(mbpll_p) = { "mout_mpll", "mout_bpll", }; | ||
1092 | |||
1093 | static struct samsung_mux_clock exynos4415_dmc_mux_clks[] __initdata = { | ||
1094 | MUX(CLK_DMC_MOUT_MPLL, "mout_mpll", mout_mpll_p, SRC_DMC, 12, 1), | ||
1095 | MUX(CLK_DMC_MOUT_BPLL, "mout_bpll", mout_bpll_p, SRC_DMC, 10, 1), | ||
1096 | MUX(CLK_DMC_MOUT_DPHY, "mout_dphy", mbpll_p, SRC_DMC, 8, 1), | ||
1097 | MUX(CLK_DMC_MOUT_DMC_BUS, "mout_dmc_bus", mbpll_p, SRC_DMC, 4, 1), | ||
1098 | }; | ||
1099 | |||
1100 | static struct samsung_div_clock exynos4415_dmc_div_clks[] __initdata = { | ||
1101 | DIV(CLK_DMC_DIV_DMC, "div_dmc", "div_dmc_pre", DIV_DMC1, 27, 3), | ||
1102 | DIV(CLK_DMC_DIV_DPHY, "div_dphy", "mout_dphy", DIV_DMC1, 23, 3), | ||
1103 | DIV(CLK_DMC_DIV_DMC_PRE, "div_dmc_pre", "mout_dmc_bus", | ||
1104 | DIV_DMC1, 19, 2), | ||
1105 | DIV(CLK_DMC_DIV_DMCP, "div_dmcp", "div_dmcd", DIV_DMC1, 15, 3), | ||
1106 | DIV(CLK_DMC_DIV_DMCD, "div_dmcd", "div_dmc", DIV_DMC1, 11, 3), | ||
1107 | DIV(CLK_DMC_DIV_MPLL_PRE, "div_mpll_pre", "mout_mpll", DIV_DMC1, 8, 2), | ||
1108 | }; | ||
1109 | |||
1110 | static struct samsung_pll_clock exynos4415_dmc_plls[nr_dmc_plls] __initdata = { | ||
1111 | [mpll] = PLL(pll_35xx, CLK_DMC_FOUT_MPLL, "fout_mpll", "fin_pll", | ||
1112 | MPLL_LOCK, MPLL_CON0, NULL), | ||
1113 | [bpll] = PLL(pll_35xx, CLK_DMC_FOUT_BPLL, "fout_bpll", "fin_pll", | ||
1114 | BPLL_LOCK, BPLL_CON0, NULL), | ||
1115 | }; | ||
1116 | |||
1117 | static void __init exynos4415_cmu_dmc_init(struct device_node *np) | ||
1118 | { | ||
1119 | void __iomem *reg_base; | ||
1120 | |||
1121 | reg_base = of_iomap(np, 0); | ||
1122 | if (!reg_base) | ||
1123 | panic("%s: failed to map registers\n", __func__); | ||
1124 | |||
1125 | exynos4415_dmc_ctx = samsung_clk_init(np, reg_base, NR_CLKS_DMC); | ||
1126 | if (!exynos4415_dmc_ctx) | ||
1127 | panic("%s: unable to allocate context.\n", __func__); | ||
1128 | |||
1129 | exynos4415_dmc_plls[mpll].rate_table = exynos4415_pll_rates; | ||
1130 | exynos4415_dmc_plls[bpll].rate_table = exynos4415_pll_rates; | ||
1131 | |||
1132 | samsung_clk_register_pll(exynos4415_dmc_ctx, exynos4415_dmc_plls, | ||
1133 | ARRAY_SIZE(exynos4415_dmc_plls), reg_base); | ||
1134 | samsung_clk_register_mux(exynos4415_dmc_ctx, exynos4415_dmc_mux_clks, | ||
1135 | ARRAY_SIZE(exynos4415_dmc_mux_clks)); | ||
1136 | samsung_clk_register_div(exynos4415_dmc_ctx, exynos4415_dmc_div_clks, | ||
1137 | ARRAY_SIZE(exynos4415_dmc_div_clks)); | ||
1138 | |||
1139 | exynos4415_dmc_clk_sleep_init(); | ||
1140 | |||
1141 | samsung_clk_of_add_provider(np, exynos4415_dmc_ctx); | ||
1142 | } | ||
1143 | CLK_OF_DECLARE(exynos4415_cmu_dmc, "samsung,exynos4415-cmu-dmc", | ||
1144 | exynos4415_cmu_dmc_init); | ||
diff --git a/drivers/clk/samsung/clk-exynos5260.c b/drivers/clk/samsung/clk-exynos5260.c index 2527e39aadcf..e2e5193d1049 100644 --- a/drivers/clk/samsung/clk-exynos5260.c +++ b/drivers/clk/samsung/clk-exynos5260.c | |||
@@ -11,10 +11,8 @@ | |||
11 | 11 | ||
12 | #include <linux/clk.h> | 12 | #include <linux/clk.h> |
13 | #include <linux/clkdev.h> | 13 | #include <linux/clkdev.h> |
14 | #include <linux/clk-provider.h> | ||
15 | #include <linux/of.h> | 14 | #include <linux/of.h> |
16 | #include <linux/of_address.h> | 15 | #include <linux/of_address.h> |
17 | #include <linux/syscore_ops.h> | ||
18 | 16 | ||
19 | #include "clk-exynos5260.h" | 17 | #include "clk-exynos5260.h" |
20 | #include "clk.h" | 18 | #include "clk.h" |
@@ -22,39 +20,6 @@ | |||
22 | 20 | ||
23 | #include <dt-bindings/clock/exynos5260-clk.h> | 21 | #include <dt-bindings/clock/exynos5260-clk.h> |
24 | 22 | ||
25 | static LIST_HEAD(clock_reg_cache_list); | ||
26 | |||
27 | struct exynos5260_clock_reg_cache { | ||
28 | struct list_head node; | ||
29 | void __iomem *reg_base; | ||
30 | struct samsung_clk_reg_dump *rdump; | ||
31 | unsigned int rd_num; | ||
32 | }; | ||
33 | |||
34 | struct exynos5260_cmu_info { | ||
35 | /* list of pll clocks and respective count */ | ||
36 | struct samsung_pll_clock *pll_clks; | ||
37 | unsigned int nr_pll_clks; | ||
38 | /* list of mux clocks and respective count */ | ||
39 | struct samsung_mux_clock *mux_clks; | ||
40 | unsigned int nr_mux_clks; | ||
41 | /* list of div clocks and respective count */ | ||
42 | struct samsung_div_clock *div_clks; | ||
43 | unsigned int nr_div_clks; | ||
44 | /* list of gate clocks and respective count */ | ||
45 | struct samsung_gate_clock *gate_clks; | ||
46 | unsigned int nr_gate_clks; | ||
47 | /* list of fixed clocks and respective count */ | ||
48 | struct samsung_fixed_rate_clock *fixed_clks; | ||
49 | unsigned int nr_fixed_clks; | ||
50 | /* total number of clocks with IDs assigned*/ | ||
51 | unsigned int nr_clk_ids; | ||
52 | |||
53 | /* list and number of clocks registers */ | ||
54 | unsigned long *clk_regs; | ||
55 | unsigned int nr_clk_regs; | ||
56 | }; | ||
57 | |||
58 | /* | 23 | /* |
59 | * Applicable for all 2550 Type PLLS for Exynos5260, listed below | 24 | * Applicable for all 2550 Type PLLS for Exynos5260, listed below |
60 | * DISP_PLL, EGL_PLL, KFC_PLL, MEM_PLL, BUS_PLL, MEDIA_PLL, G3D_PLL. | 25 | * DISP_PLL, EGL_PLL, KFC_PLL, MEM_PLL, BUS_PLL, MEDIA_PLL, G3D_PLL. |
@@ -113,104 +78,6 @@ static struct samsung_pll_rate_table pll2650_24mhz_tbl[] __initdata = { | |||
113 | PLL_36XX_RATE(66000000, 176, 2, 5, 0), | 78 | PLL_36XX_RATE(66000000, 176, 2, 5, 0), |
114 | }; | 79 | }; |
115 | 80 | ||
116 | #ifdef CONFIG_PM_SLEEP | ||
117 | |||
118 | static int exynos5260_clk_suspend(void) | ||
119 | { | ||
120 | struct exynos5260_clock_reg_cache *cache; | ||
121 | |||
122 | list_for_each_entry(cache, &clock_reg_cache_list, node) | ||
123 | samsung_clk_save(cache->reg_base, cache->rdump, | ||
124 | cache->rd_num); | ||
125 | |||
126 | return 0; | ||
127 | } | ||
128 | |||
129 | static void exynos5260_clk_resume(void) | ||
130 | { | ||
131 | struct exynos5260_clock_reg_cache *cache; | ||
132 | |||
133 | list_for_each_entry(cache, &clock_reg_cache_list, node) | ||
134 | samsung_clk_restore(cache->reg_base, cache->rdump, | ||
135 | cache->rd_num); | ||
136 | } | ||
137 | |||
138 | static struct syscore_ops exynos5260_clk_syscore_ops = { | ||
139 | .suspend = exynos5260_clk_suspend, | ||
140 | .resume = exynos5260_clk_resume, | ||
141 | }; | ||
142 | |||
143 | static void exynos5260_clk_sleep_init(void __iomem *reg_base, | ||
144 | unsigned long *rdump, | ||
145 | unsigned long nr_rdump) | ||
146 | { | ||
147 | struct exynos5260_clock_reg_cache *reg_cache; | ||
148 | |||
149 | reg_cache = kzalloc(sizeof(struct exynos5260_clock_reg_cache), | ||
150 | GFP_KERNEL); | ||
151 | if (!reg_cache) | ||
152 | panic("could not allocate register cache.\n"); | ||
153 | |||
154 | reg_cache->rdump = samsung_clk_alloc_reg_dump(rdump, nr_rdump); | ||
155 | |||
156 | if (!reg_cache->rdump) | ||
157 | panic("could not allocate register dump storage.\n"); | ||
158 | |||
159 | if (list_empty(&clock_reg_cache_list)) | ||
160 | register_syscore_ops(&exynos5260_clk_syscore_ops); | ||
161 | |||
162 | reg_cache->rd_num = nr_rdump; | ||
163 | reg_cache->reg_base = reg_base; | ||
164 | list_add_tail(®_cache->node, &clock_reg_cache_list); | ||
165 | } | ||
166 | |||
167 | #else | ||
168 | static void exynos5260_clk_sleep_init(void __iomem *reg_base, | ||
169 | unsigned long *rdump, | ||
170 | unsigned long nr_rdump){} | ||
171 | #endif | ||
172 | |||
173 | /* | ||
174 | * Common function which registers plls, muxes, dividers and gates | ||
175 | * for each CMU. It also add CMU register list to register cache. | ||
176 | */ | ||
177 | |||
178 | void __init exynos5260_cmu_register_one(struct device_node *np, | ||
179 | struct exynos5260_cmu_info *cmu) | ||
180 | { | ||
181 | void __iomem *reg_base; | ||
182 | struct samsung_clk_provider *ctx; | ||
183 | |||
184 | reg_base = of_iomap(np, 0); | ||
185 | if (!reg_base) | ||
186 | panic("%s: failed to map registers\n", __func__); | ||
187 | |||
188 | ctx = samsung_clk_init(np, reg_base, cmu->nr_clk_ids); | ||
189 | if (!ctx) | ||
190 | panic("%s: unable to alllocate ctx\n", __func__); | ||
191 | |||
192 | if (cmu->pll_clks) | ||
193 | samsung_clk_register_pll(ctx, cmu->pll_clks, cmu->nr_pll_clks, | ||
194 | reg_base); | ||
195 | if (cmu->mux_clks) | ||
196 | samsung_clk_register_mux(ctx, cmu->mux_clks, | ||
197 | cmu->nr_mux_clks); | ||
198 | if (cmu->div_clks) | ||
199 | samsung_clk_register_div(ctx, cmu->div_clks, cmu->nr_div_clks); | ||
200 | if (cmu->gate_clks) | ||
201 | samsung_clk_register_gate(ctx, cmu->gate_clks, | ||
202 | cmu->nr_gate_clks); | ||
203 | if (cmu->fixed_clks) | ||
204 | samsung_clk_register_fixed_rate(ctx, cmu->fixed_clks, | ||
205 | cmu->nr_fixed_clks); | ||
206 | if (cmu->clk_regs) | ||
207 | exynos5260_clk_sleep_init(reg_base, cmu->clk_regs, | ||
208 | cmu->nr_clk_regs); | ||
209 | |||
210 | samsung_clk_of_add_provider(np, ctx); | ||
211 | } | ||
212 | |||
213 | |||
214 | /* CMU_AUD */ | 81 | /* CMU_AUD */ |
215 | 82 | ||
216 | static unsigned long aud_clk_regs[] __initdata = { | 83 | static unsigned long aud_clk_regs[] __initdata = { |
@@ -268,7 +135,7 @@ struct samsung_gate_clock aud_gate_clks[] __initdata = { | |||
268 | 135 | ||
269 | static void __init exynos5260_clk_aud_init(struct device_node *np) | 136 | static void __init exynos5260_clk_aud_init(struct device_node *np) |
270 | { | 137 | { |
271 | struct exynos5260_cmu_info cmu = {0}; | 138 | struct samsung_cmu_info cmu = {0}; |
272 | 139 | ||
273 | cmu.mux_clks = aud_mux_clks; | 140 | cmu.mux_clks = aud_mux_clks; |
274 | cmu.nr_mux_clks = ARRAY_SIZE(aud_mux_clks); | 141 | cmu.nr_mux_clks = ARRAY_SIZE(aud_mux_clks); |
@@ -280,7 +147,7 @@ static void __init exynos5260_clk_aud_init(struct device_node *np) | |||
280 | cmu.clk_regs = aud_clk_regs; | 147 | cmu.clk_regs = aud_clk_regs; |
281 | cmu.nr_clk_regs = ARRAY_SIZE(aud_clk_regs); | 148 | cmu.nr_clk_regs = ARRAY_SIZE(aud_clk_regs); |
282 | 149 | ||
283 | exynos5260_cmu_register_one(np, &cmu); | 150 | samsung_cmu_register_one(np, &cmu); |
284 | } | 151 | } |
285 | 152 | ||
286 | CLK_OF_DECLARE(exynos5260_clk_aud, "samsung,exynos5260-clock-aud", | 153 | CLK_OF_DECLARE(exynos5260_clk_aud, "samsung,exynos5260-clock-aud", |
@@ -458,7 +325,7 @@ struct samsung_gate_clock disp_gate_clks[] __initdata = { | |||
458 | 325 | ||
459 | static void __init exynos5260_clk_disp_init(struct device_node *np) | 326 | static void __init exynos5260_clk_disp_init(struct device_node *np) |
460 | { | 327 | { |
461 | struct exynos5260_cmu_info cmu = {0}; | 328 | struct samsung_cmu_info cmu = {0}; |
462 | 329 | ||
463 | cmu.mux_clks = disp_mux_clks; | 330 | cmu.mux_clks = disp_mux_clks; |
464 | cmu.nr_mux_clks = ARRAY_SIZE(disp_mux_clks); | 331 | cmu.nr_mux_clks = ARRAY_SIZE(disp_mux_clks); |
@@ -470,7 +337,7 @@ static void __init exynos5260_clk_disp_init(struct device_node *np) | |||
470 | cmu.clk_regs = disp_clk_regs; | 337 | cmu.clk_regs = disp_clk_regs; |
471 | cmu.nr_clk_regs = ARRAY_SIZE(disp_clk_regs); | 338 | cmu.nr_clk_regs = ARRAY_SIZE(disp_clk_regs); |
472 | 339 | ||
473 | exynos5260_cmu_register_one(np, &cmu); | 340 | samsung_cmu_register_one(np, &cmu); |
474 | } | 341 | } |
475 | 342 | ||
476 | CLK_OF_DECLARE(exynos5260_clk_disp, "samsung,exynos5260-clock-disp", | 343 | CLK_OF_DECLARE(exynos5260_clk_disp, "samsung,exynos5260-clock-disp", |
@@ -522,7 +389,7 @@ static struct samsung_pll_clock egl_pll_clks[] __initdata = { | |||
522 | 389 | ||
523 | static void __init exynos5260_clk_egl_init(struct device_node *np) | 390 | static void __init exynos5260_clk_egl_init(struct device_node *np) |
524 | { | 391 | { |
525 | struct exynos5260_cmu_info cmu = {0}; | 392 | struct samsung_cmu_info cmu = {0}; |
526 | 393 | ||
527 | cmu.pll_clks = egl_pll_clks; | 394 | cmu.pll_clks = egl_pll_clks; |
528 | cmu.nr_pll_clks = ARRAY_SIZE(egl_pll_clks); | 395 | cmu.nr_pll_clks = ARRAY_SIZE(egl_pll_clks); |
@@ -534,7 +401,7 @@ static void __init exynos5260_clk_egl_init(struct device_node *np) | |||
534 | cmu.clk_regs = egl_clk_regs; | 401 | cmu.clk_regs = egl_clk_regs; |
535 | cmu.nr_clk_regs = ARRAY_SIZE(egl_clk_regs); | 402 | cmu.nr_clk_regs = ARRAY_SIZE(egl_clk_regs); |
536 | 403 | ||
537 | exynos5260_cmu_register_one(np, &cmu); | 404 | samsung_cmu_register_one(np, &cmu); |
538 | } | 405 | } |
539 | 406 | ||
540 | CLK_OF_DECLARE(exynos5260_clk_egl, "samsung,exynos5260-clock-egl", | 407 | CLK_OF_DECLARE(exynos5260_clk_egl, "samsung,exynos5260-clock-egl", |
@@ -624,7 +491,7 @@ struct samsung_gate_clock fsys_gate_clks[] __initdata = { | |||
624 | 491 | ||
625 | static void __init exynos5260_clk_fsys_init(struct device_node *np) | 492 | static void __init exynos5260_clk_fsys_init(struct device_node *np) |
626 | { | 493 | { |
627 | struct exynos5260_cmu_info cmu = {0}; | 494 | struct samsung_cmu_info cmu = {0}; |
628 | 495 | ||
629 | cmu.mux_clks = fsys_mux_clks; | 496 | cmu.mux_clks = fsys_mux_clks; |
630 | cmu.nr_mux_clks = ARRAY_SIZE(fsys_mux_clks); | 497 | cmu.nr_mux_clks = ARRAY_SIZE(fsys_mux_clks); |
@@ -634,7 +501,7 @@ static void __init exynos5260_clk_fsys_init(struct device_node *np) | |||
634 | cmu.clk_regs = fsys_clk_regs; | 501 | cmu.clk_regs = fsys_clk_regs; |
635 | cmu.nr_clk_regs = ARRAY_SIZE(fsys_clk_regs); | 502 | cmu.nr_clk_regs = ARRAY_SIZE(fsys_clk_regs); |
636 | 503 | ||
637 | exynos5260_cmu_register_one(np, &cmu); | 504 | samsung_cmu_register_one(np, &cmu); |
638 | } | 505 | } |
639 | 506 | ||
640 | CLK_OF_DECLARE(exynos5260_clk_fsys, "samsung,exynos5260-clock-fsys", | 507 | CLK_OF_DECLARE(exynos5260_clk_fsys, "samsung,exynos5260-clock-fsys", |
@@ -713,7 +580,7 @@ struct samsung_gate_clock g2d_gate_clks[] __initdata = { | |||
713 | 580 | ||
714 | static void __init exynos5260_clk_g2d_init(struct device_node *np) | 581 | static void __init exynos5260_clk_g2d_init(struct device_node *np) |
715 | { | 582 | { |
716 | struct exynos5260_cmu_info cmu = {0}; | 583 | struct samsung_cmu_info cmu = {0}; |
717 | 584 | ||
718 | cmu.mux_clks = g2d_mux_clks; | 585 | cmu.mux_clks = g2d_mux_clks; |
719 | cmu.nr_mux_clks = ARRAY_SIZE(g2d_mux_clks); | 586 | cmu.nr_mux_clks = ARRAY_SIZE(g2d_mux_clks); |
@@ -725,7 +592,7 @@ static void __init exynos5260_clk_g2d_init(struct device_node *np) | |||
725 | cmu.clk_regs = g2d_clk_regs; | 592 | cmu.clk_regs = g2d_clk_regs; |
726 | cmu.nr_clk_regs = ARRAY_SIZE(g2d_clk_regs); | 593 | cmu.nr_clk_regs = ARRAY_SIZE(g2d_clk_regs); |
727 | 594 | ||
728 | exynos5260_cmu_register_one(np, &cmu); | 595 | samsung_cmu_register_one(np, &cmu); |
729 | } | 596 | } |
730 | 597 | ||
731 | CLK_OF_DECLARE(exynos5260_clk_g2d, "samsung,exynos5260-clock-g2d", | 598 | CLK_OF_DECLARE(exynos5260_clk_g2d, "samsung,exynos5260-clock-g2d", |
@@ -774,7 +641,7 @@ static struct samsung_pll_clock g3d_pll_clks[] __initdata = { | |||
774 | 641 | ||
775 | static void __init exynos5260_clk_g3d_init(struct device_node *np) | 642 | static void __init exynos5260_clk_g3d_init(struct device_node *np) |
776 | { | 643 | { |
777 | struct exynos5260_cmu_info cmu = {0}; | 644 | struct samsung_cmu_info cmu = {0}; |
778 | 645 | ||
779 | cmu.pll_clks = g3d_pll_clks; | 646 | cmu.pll_clks = g3d_pll_clks; |
780 | cmu.nr_pll_clks = ARRAY_SIZE(g3d_pll_clks); | 647 | cmu.nr_pll_clks = ARRAY_SIZE(g3d_pll_clks); |
@@ -788,7 +655,7 @@ static void __init exynos5260_clk_g3d_init(struct device_node *np) | |||
788 | cmu.clk_regs = g3d_clk_regs; | 655 | cmu.clk_regs = g3d_clk_regs; |
789 | cmu.nr_clk_regs = ARRAY_SIZE(g3d_clk_regs); | 656 | cmu.nr_clk_regs = ARRAY_SIZE(g3d_clk_regs); |
790 | 657 | ||
791 | exynos5260_cmu_register_one(np, &cmu); | 658 | samsung_cmu_register_one(np, &cmu); |
792 | } | 659 | } |
793 | 660 | ||
794 | CLK_OF_DECLARE(exynos5260_clk_g3d, "samsung,exynos5260-clock-g3d", | 661 | CLK_OF_DECLARE(exynos5260_clk_g3d, "samsung,exynos5260-clock-g3d", |
@@ -909,7 +776,7 @@ struct samsung_gate_clock gscl_gate_clks[] __initdata = { | |||
909 | 776 | ||
910 | static void __init exynos5260_clk_gscl_init(struct device_node *np) | 777 | static void __init exynos5260_clk_gscl_init(struct device_node *np) |
911 | { | 778 | { |
912 | struct exynos5260_cmu_info cmu = {0}; | 779 | struct samsung_cmu_info cmu = {0}; |
913 | 780 | ||
914 | cmu.mux_clks = gscl_mux_clks; | 781 | cmu.mux_clks = gscl_mux_clks; |
915 | cmu.nr_mux_clks = ARRAY_SIZE(gscl_mux_clks); | 782 | cmu.nr_mux_clks = ARRAY_SIZE(gscl_mux_clks); |
@@ -921,7 +788,7 @@ static void __init exynos5260_clk_gscl_init(struct device_node *np) | |||
921 | cmu.clk_regs = gscl_clk_regs; | 788 | cmu.clk_regs = gscl_clk_regs; |
922 | cmu.nr_clk_regs = ARRAY_SIZE(gscl_clk_regs); | 789 | cmu.nr_clk_regs = ARRAY_SIZE(gscl_clk_regs); |
923 | 790 | ||
924 | exynos5260_cmu_register_one(np, &cmu); | 791 | samsung_cmu_register_one(np, &cmu); |
925 | } | 792 | } |
926 | 793 | ||
927 | CLK_OF_DECLARE(exynos5260_clk_gscl, "samsung,exynos5260-clock-gscl", | 794 | CLK_OF_DECLARE(exynos5260_clk_gscl, "samsung,exynos5260-clock-gscl", |
@@ -1028,7 +895,7 @@ struct samsung_gate_clock isp_gate_clks[] __initdata = { | |||
1028 | 895 | ||
1029 | static void __init exynos5260_clk_isp_init(struct device_node *np) | 896 | static void __init exynos5260_clk_isp_init(struct device_node *np) |
1030 | { | 897 | { |
1031 | struct exynos5260_cmu_info cmu = {0}; | 898 | struct samsung_cmu_info cmu = {0}; |
1032 | 899 | ||
1033 | cmu.mux_clks = isp_mux_clks; | 900 | cmu.mux_clks = isp_mux_clks; |
1034 | cmu.nr_mux_clks = ARRAY_SIZE(isp_mux_clks); | 901 | cmu.nr_mux_clks = ARRAY_SIZE(isp_mux_clks); |
@@ -1040,7 +907,7 @@ static void __init exynos5260_clk_isp_init(struct device_node *np) | |||
1040 | cmu.clk_regs = isp_clk_regs; | 907 | cmu.clk_regs = isp_clk_regs; |
1041 | cmu.nr_clk_regs = ARRAY_SIZE(isp_clk_regs); | 908 | cmu.nr_clk_regs = ARRAY_SIZE(isp_clk_regs); |
1042 | 909 | ||
1043 | exynos5260_cmu_register_one(np, &cmu); | 910 | samsung_cmu_register_one(np, &cmu); |
1044 | } | 911 | } |
1045 | 912 | ||
1046 | CLK_OF_DECLARE(exynos5260_clk_isp, "samsung,exynos5260-clock-isp", | 913 | CLK_OF_DECLARE(exynos5260_clk_isp, "samsung,exynos5260-clock-isp", |
@@ -1092,7 +959,7 @@ static struct samsung_pll_clock kfc_pll_clks[] __initdata = { | |||
1092 | 959 | ||
1093 | static void __init exynos5260_clk_kfc_init(struct device_node *np) | 960 | static void __init exynos5260_clk_kfc_init(struct device_node *np) |
1094 | { | 961 | { |
1095 | struct exynos5260_cmu_info cmu = {0}; | 962 | struct samsung_cmu_info cmu = {0}; |
1096 | 963 | ||
1097 | cmu.pll_clks = kfc_pll_clks; | 964 | cmu.pll_clks = kfc_pll_clks; |
1098 | cmu.nr_pll_clks = ARRAY_SIZE(kfc_pll_clks); | 965 | cmu.nr_pll_clks = ARRAY_SIZE(kfc_pll_clks); |
@@ -1104,7 +971,7 @@ static void __init exynos5260_clk_kfc_init(struct device_node *np) | |||
1104 | cmu.clk_regs = kfc_clk_regs; | 971 | cmu.clk_regs = kfc_clk_regs; |
1105 | cmu.nr_clk_regs = ARRAY_SIZE(kfc_clk_regs); | 972 | cmu.nr_clk_regs = ARRAY_SIZE(kfc_clk_regs); |
1106 | 973 | ||
1107 | exynos5260_cmu_register_one(np, &cmu); | 974 | samsung_cmu_register_one(np, &cmu); |
1108 | } | 975 | } |
1109 | 976 | ||
1110 | CLK_OF_DECLARE(exynos5260_clk_kfc, "samsung,exynos5260-clock-kfc", | 977 | CLK_OF_DECLARE(exynos5260_clk_kfc, "samsung,exynos5260-clock-kfc", |
@@ -1148,7 +1015,7 @@ struct samsung_gate_clock mfc_gate_clks[] __initdata = { | |||
1148 | 1015 | ||
1149 | static void __init exynos5260_clk_mfc_init(struct device_node *np) | 1016 | static void __init exynos5260_clk_mfc_init(struct device_node *np) |
1150 | { | 1017 | { |
1151 | struct exynos5260_cmu_info cmu = {0}; | 1018 | struct samsung_cmu_info cmu = {0}; |
1152 | 1019 | ||
1153 | cmu.mux_clks = mfc_mux_clks; | 1020 | cmu.mux_clks = mfc_mux_clks; |
1154 | cmu.nr_mux_clks = ARRAY_SIZE(mfc_mux_clks); | 1021 | cmu.nr_mux_clks = ARRAY_SIZE(mfc_mux_clks); |
@@ -1160,7 +1027,7 @@ static void __init exynos5260_clk_mfc_init(struct device_node *np) | |||
1160 | cmu.clk_regs = mfc_clk_regs; | 1027 | cmu.clk_regs = mfc_clk_regs; |
1161 | cmu.nr_clk_regs = ARRAY_SIZE(mfc_clk_regs); | 1028 | cmu.nr_clk_regs = ARRAY_SIZE(mfc_clk_regs); |
1162 | 1029 | ||
1163 | exynos5260_cmu_register_one(np, &cmu); | 1030 | samsung_cmu_register_one(np, &cmu); |
1164 | } | 1031 | } |
1165 | 1032 | ||
1166 | CLK_OF_DECLARE(exynos5260_clk_mfc, "samsung,exynos5260-clock-mfc", | 1033 | CLK_OF_DECLARE(exynos5260_clk_mfc, "samsung,exynos5260-clock-mfc", |
@@ -1295,7 +1162,7 @@ static struct samsung_pll_clock mif_pll_clks[] __initdata = { | |||
1295 | 1162 | ||
1296 | static void __init exynos5260_clk_mif_init(struct device_node *np) | 1163 | static void __init exynos5260_clk_mif_init(struct device_node *np) |
1297 | { | 1164 | { |
1298 | struct exynos5260_cmu_info cmu = {0}; | 1165 | struct samsung_cmu_info cmu = {0}; |
1299 | 1166 | ||
1300 | cmu.pll_clks = mif_pll_clks; | 1167 | cmu.pll_clks = mif_pll_clks; |
1301 | cmu.nr_pll_clks = ARRAY_SIZE(mif_pll_clks); | 1168 | cmu.nr_pll_clks = ARRAY_SIZE(mif_pll_clks); |
@@ -1309,7 +1176,7 @@ static void __init exynos5260_clk_mif_init(struct device_node *np) | |||
1309 | cmu.clk_regs = mif_clk_regs; | 1176 | cmu.clk_regs = mif_clk_regs; |
1310 | cmu.nr_clk_regs = ARRAY_SIZE(mif_clk_regs); | 1177 | cmu.nr_clk_regs = ARRAY_SIZE(mif_clk_regs); |
1311 | 1178 | ||
1312 | exynos5260_cmu_register_one(np, &cmu); | 1179 | samsung_cmu_register_one(np, &cmu); |
1313 | } | 1180 | } |
1314 | 1181 | ||
1315 | CLK_OF_DECLARE(exynos5260_clk_mif, "samsung,exynos5260-clock-mif", | 1182 | CLK_OF_DECLARE(exynos5260_clk_mif, "samsung,exynos5260-clock-mif", |
@@ -1503,7 +1370,7 @@ struct samsung_gate_clock peri_gate_clks[] __initdata = { | |||
1503 | 1370 | ||
1504 | static void __init exynos5260_clk_peri_init(struct device_node *np) | 1371 | static void __init exynos5260_clk_peri_init(struct device_node *np) |
1505 | { | 1372 | { |
1506 | struct exynos5260_cmu_info cmu = {0}; | 1373 | struct samsung_cmu_info cmu = {0}; |
1507 | 1374 | ||
1508 | cmu.mux_clks = peri_mux_clks; | 1375 | cmu.mux_clks = peri_mux_clks; |
1509 | cmu.nr_mux_clks = ARRAY_SIZE(peri_mux_clks); | 1376 | cmu.nr_mux_clks = ARRAY_SIZE(peri_mux_clks); |
@@ -1515,7 +1382,7 @@ static void __init exynos5260_clk_peri_init(struct device_node *np) | |||
1515 | cmu.clk_regs = peri_clk_regs; | 1382 | cmu.clk_regs = peri_clk_regs; |
1516 | cmu.nr_clk_regs = ARRAY_SIZE(peri_clk_regs); | 1383 | cmu.nr_clk_regs = ARRAY_SIZE(peri_clk_regs); |
1517 | 1384 | ||
1518 | exynos5260_cmu_register_one(np, &cmu); | 1385 | samsung_cmu_register_one(np, &cmu); |
1519 | } | 1386 | } |
1520 | 1387 | ||
1521 | CLK_OF_DECLARE(exynos5260_clk_peri, "samsung,exynos5260-clock-peri", | 1388 | CLK_OF_DECLARE(exynos5260_clk_peri, "samsung,exynos5260-clock-peri", |
@@ -1959,7 +1826,7 @@ static struct samsung_pll_clock top_pll_clks[] __initdata = { | |||
1959 | 1826 | ||
1960 | static void __init exynos5260_clk_top_init(struct device_node *np) | 1827 | static void __init exynos5260_clk_top_init(struct device_node *np) |
1961 | { | 1828 | { |
1962 | struct exynos5260_cmu_info cmu = {0}; | 1829 | struct samsung_cmu_info cmu = {0}; |
1963 | 1830 | ||
1964 | cmu.pll_clks = top_pll_clks; | 1831 | cmu.pll_clks = top_pll_clks; |
1965 | cmu.nr_pll_clks = ARRAY_SIZE(top_pll_clks); | 1832 | cmu.nr_pll_clks = ARRAY_SIZE(top_pll_clks); |
@@ -1975,7 +1842,7 @@ static void __init exynos5260_clk_top_init(struct device_node *np) | |||
1975 | cmu.clk_regs = top_clk_regs; | 1842 | cmu.clk_regs = top_clk_regs; |
1976 | cmu.nr_clk_regs = ARRAY_SIZE(top_clk_regs); | 1843 | cmu.nr_clk_regs = ARRAY_SIZE(top_clk_regs); |
1977 | 1844 | ||
1978 | exynos5260_cmu_register_one(np, &cmu); | 1845 | samsung_cmu_register_one(np, &cmu); |
1979 | } | 1846 | } |
1980 | 1847 | ||
1981 | CLK_OF_DECLARE(exynos5260_clk_top, "samsung,exynos5260-clock-top", | 1848 | CLK_OF_DECLARE(exynos5260_clk_top, "samsung,exynos5260-clock-top", |
diff --git a/drivers/clk/samsung/clk-exynos7.c b/drivers/clk/samsung/clk-exynos7.c new file mode 100644 index 000000000000..ea4483b8d62e --- /dev/null +++ b/drivers/clk/samsung/clk-exynos7.c | |||
@@ -0,0 +1,743 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2014 Samsung Electronics Co., Ltd. | ||
3 | * Author: Naveen Krishna Ch <naveenkrishna.ch@gmail.com> | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU General Public License version 2 as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | */ | ||
10 | |||
11 | #include <linux/clk.h> | ||
12 | #include <linux/clkdev.h> | ||
13 | #include <linux/clk-provider.h> | ||
14 | #include <linux/of.h> | ||
15 | |||
16 | #include "clk.h" | ||
17 | #include <dt-bindings/clock/exynos7-clk.h> | ||
18 | |||
19 | /* Register Offset definitions for CMU_TOPC (0x10570000) */ | ||
20 | #define CC_PLL_LOCK 0x0000 | ||
21 | #define BUS0_PLL_LOCK 0x0004 | ||
22 | #define BUS1_DPLL_LOCK 0x0008 | ||
23 | #define MFC_PLL_LOCK 0x000C | ||
24 | #define AUD_PLL_LOCK 0x0010 | ||
25 | #define CC_PLL_CON0 0x0100 | ||
26 | #define BUS0_PLL_CON0 0x0110 | ||
27 | #define BUS1_DPLL_CON0 0x0120 | ||
28 | #define MFC_PLL_CON0 0x0130 | ||
29 | #define AUD_PLL_CON0 0x0140 | ||
30 | #define MUX_SEL_TOPC0 0x0200 | ||
31 | #define MUX_SEL_TOPC1 0x0204 | ||
32 | #define MUX_SEL_TOPC2 0x0208 | ||
33 | #define MUX_SEL_TOPC3 0x020C | ||
34 | #define DIV_TOPC0 0x0600 | ||
35 | #define DIV_TOPC1 0x0604 | ||
36 | #define DIV_TOPC3 0x060C | ||
37 | |||
38 | static struct samsung_fixed_factor_clock topc_fixed_factor_clks[] __initdata = { | ||
39 | FFACTOR(0, "ffac_topc_bus0_pll_div2", "mout_bus0_pll_ctrl", 1, 2, 0), | ||
40 | FFACTOR(0, "ffac_topc_bus0_pll_div4", | ||
41 | "ffac_topc_bus0_pll_div2", 1, 2, 0), | ||
42 | FFACTOR(0, "ffac_topc_bus1_pll_div2", "mout_bus1_pll_ctrl", 1, 2, 0), | ||
43 | FFACTOR(0, "ffac_topc_cc_pll_div2", "mout_cc_pll_ctrl", 1, 2, 0), | ||
44 | FFACTOR(0, "ffac_topc_mfc_pll_div2", "mout_mfc_pll_ctrl", 1, 2, 0), | ||
45 | }; | ||
46 | |||
47 | /* List of parent clocks for Muxes in CMU_TOPC */ | ||
48 | PNAME(mout_bus0_pll_ctrl_p) = { "fin_pll", "fout_bus0_pll" }; | ||
49 | PNAME(mout_bus1_pll_ctrl_p) = { "fin_pll", "fout_bus1_pll" }; | ||
50 | PNAME(mout_cc_pll_ctrl_p) = { "fin_pll", "fout_cc_pll" }; | ||
51 | PNAME(mout_mfc_pll_ctrl_p) = { "fin_pll", "fout_mfc_pll" }; | ||
52 | |||
53 | PNAME(mout_topc_group2) = { "mout_sclk_bus0_pll_cmuc", | ||
54 | "mout_sclk_bus1_pll_cmuc", "mout_sclk_cc_pll_cmuc", | ||
55 | "mout_sclk_mfc_pll_cmuc" }; | ||
56 | |||
57 | PNAME(mout_sclk_bus0_pll_cmuc_p) = { "mout_bus0_pll_ctrl", | ||
58 | "ffac_topc_bus0_pll_div2", "ffac_topc_bus0_pll_div4"}; | ||
59 | PNAME(mout_sclk_bus1_pll_cmuc_p) = { "mout_bus1_pll_ctrl", | ||
60 | "ffac_topc_bus1_pll_div2"}; | ||
61 | PNAME(mout_sclk_cc_pll_cmuc_p) = { "mout_cc_pll_ctrl", | ||
62 | "ffac_topc_cc_pll_div2"}; | ||
63 | PNAME(mout_sclk_mfc_pll_cmuc_p) = { "mout_mfc_pll_ctrl", | ||
64 | "ffac_topc_mfc_pll_div2"}; | ||
65 | |||
66 | |||
67 | PNAME(mout_sclk_bus0_pll_out_p) = {"mout_bus0_pll_ctrl", | ||
68 | "ffac_topc_bus0_pll_div2"}; | ||
69 | |||
70 | static unsigned long topc_clk_regs[] __initdata = { | ||
71 | CC_PLL_LOCK, | ||
72 | BUS0_PLL_LOCK, | ||
73 | BUS1_DPLL_LOCK, | ||
74 | MFC_PLL_LOCK, | ||
75 | AUD_PLL_LOCK, | ||
76 | CC_PLL_CON0, | ||
77 | BUS0_PLL_CON0, | ||
78 | BUS1_DPLL_CON0, | ||
79 | MFC_PLL_CON0, | ||
80 | AUD_PLL_CON0, | ||
81 | MUX_SEL_TOPC0, | ||
82 | MUX_SEL_TOPC1, | ||
83 | MUX_SEL_TOPC2, | ||
84 | MUX_SEL_TOPC3, | ||
85 | DIV_TOPC0, | ||
86 | DIV_TOPC1, | ||
87 | DIV_TOPC3, | ||
88 | }; | ||
89 | |||
90 | static struct samsung_mux_clock topc_mux_clks[] __initdata = { | ||
91 | MUX(0, "mout_bus0_pll_ctrl", mout_bus0_pll_ctrl_p, MUX_SEL_TOPC0, 0, 1), | ||
92 | MUX(0, "mout_bus1_pll_ctrl", mout_bus1_pll_ctrl_p, MUX_SEL_TOPC0, 4, 1), | ||
93 | MUX(0, "mout_cc_pll_ctrl", mout_cc_pll_ctrl_p, MUX_SEL_TOPC0, 8, 1), | ||
94 | MUX(0, "mout_mfc_pll_ctrl", mout_mfc_pll_ctrl_p, MUX_SEL_TOPC0, 12, 1), | ||
95 | |||
96 | MUX(0, "mout_sclk_bus0_pll_cmuc", mout_sclk_bus0_pll_cmuc_p, | ||
97 | MUX_SEL_TOPC0, 16, 2), | ||
98 | MUX(0, "mout_sclk_bus1_pll_cmuc", mout_sclk_bus1_pll_cmuc_p, | ||
99 | MUX_SEL_TOPC0, 20, 1), | ||
100 | MUX(0, "mout_sclk_cc_pll_cmuc", mout_sclk_cc_pll_cmuc_p, | ||
101 | MUX_SEL_TOPC0, 24, 1), | ||
102 | MUX(0, "mout_sclk_mfc_pll_cmuc", mout_sclk_mfc_pll_cmuc_p, | ||
103 | MUX_SEL_TOPC0, 28, 1), | ||
104 | |||
105 | MUX(0, "mout_sclk_bus0_pll_out", mout_sclk_bus0_pll_out_p, | ||
106 | MUX_SEL_TOPC1, 16, 1), | ||
107 | |||
108 | MUX(0, "mout_aclk_ccore_133", mout_topc_group2, MUX_SEL_TOPC2, 4, 2), | ||
109 | |||
110 | MUX(0, "mout_aclk_peris_66", mout_topc_group2, MUX_SEL_TOPC3, 24, 2), | ||
111 | }; | ||
112 | |||
113 | static struct samsung_div_clock topc_div_clks[] __initdata = { | ||
114 | DIV(DOUT_ACLK_CCORE_133, "dout_aclk_ccore_133", "mout_aclk_ccore_133", | ||
115 | DIV_TOPC0, 4, 4), | ||
116 | |||
117 | DIV(DOUT_ACLK_PERIS, "dout_aclk_peris_66", "mout_aclk_peris_66", | ||
118 | DIV_TOPC1, 24, 4), | ||
119 | |||
120 | DIV(DOUT_SCLK_BUS0_PLL, "dout_sclk_bus0_pll", "mout_sclk_bus0_pll_out", | ||
121 | DIV_TOPC3, 0, 3), | ||
122 | DIV(DOUT_SCLK_BUS1_PLL, "dout_sclk_bus1_pll", "mout_bus1_pll_ctrl", | ||
123 | DIV_TOPC3, 8, 3), | ||
124 | DIV(DOUT_SCLK_CC_PLL, "dout_sclk_cc_pll", "mout_cc_pll_ctrl", | ||
125 | DIV_TOPC3, 12, 3), | ||
126 | DIV(DOUT_SCLK_MFC_PLL, "dout_sclk_mfc_pll", "mout_mfc_pll_ctrl", | ||
127 | DIV_TOPC3, 16, 3), | ||
128 | }; | ||
129 | |||
130 | static struct samsung_pll_clock topc_pll_clks[] __initdata = { | ||
131 | PLL(pll_1451x, 0, "fout_bus0_pll", "fin_pll", BUS0_PLL_LOCK, | ||
132 | BUS0_PLL_CON0, NULL), | ||
133 | PLL(pll_1452x, 0, "fout_cc_pll", "fin_pll", CC_PLL_LOCK, | ||
134 | CC_PLL_CON0, NULL), | ||
135 | PLL(pll_1452x, 0, "fout_bus1_pll", "fin_pll", BUS1_DPLL_LOCK, | ||
136 | BUS1_DPLL_CON0, NULL), | ||
137 | PLL(pll_1452x, 0, "fout_mfc_pll", "fin_pll", MFC_PLL_LOCK, | ||
138 | MFC_PLL_CON0, NULL), | ||
139 | PLL(pll_1460x, 0, "fout_aud_pll", "fin_pll", AUD_PLL_LOCK, | ||
140 | AUD_PLL_CON0, NULL), | ||
141 | }; | ||
142 | |||
143 | static struct samsung_cmu_info topc_cmu_info __initdata = { | ||
144 | .pll_clks = topc_pll_clks, | ||
145 | .nr_pll_clks = ARRAY_SIZE(topc_pll_clks), | ||
146 | .mux_clks = topc_mux_clks, | ||
147 | .nr_mux_clks = ARRAY_SIZE(topc_mux_clks), | ||
148 | .div_clks = topc_div_clks, | ||
149 | .nr_div_clks = ARRAY_SIZE(topc_div_clks), | ||
150 | .fixed_factor_clks = topc_fixed_factor_clks, | ||
151 | .nr_fixed_factor_clks = ARRAY_SIZE(topc_fixed_factor_clks), | ||
152 | .nr_clk_ids = TOPC_NR_CLK, | ||
153 | .clk_regs = topc_clk_regs, | ||
154 | .nr_clk_regs = ARRAY_SIZE(topc_clk_regs), | ||
155 | }; | ||
156 | |||
157 | static void __init exynos7_clk_topc_init(struct device_node *np) | ||
158 | { | ||
159 | samsung_cmu_register_one(np, &topc_cmu_info); | ||
160 | } | ||
161 | |||
162 | CLK_OF_DECLARE(exynos7_clk_topc, "samsung,exynos7-clock-topc", | ||
163 | exynos7_clk_topc_init); | ||
164 | |||
165 | /* Register Offset definitions for CMU_TOP0 (0x105D0000) */ | ||
166 | #define MUX_SEL_TOP00 0x0200 | ||
167 | #define MUX_SEL_TOP01 0x0204 | ||
168 | #define MUX_SEL_TOP03 0x020C | ||
169 | #define MUX_SEL_TOP0_PERIC3 0x023C | ||
170 | #define DIV_TOP03 0x060C | ||
171 | #define DIV_TOP0_PERIC3 0x063C | ||
172 | #define ENABLE_SCLK_TOP0_PERIC3 0x0A3C | ||
173 | |||
174 | /* List of parent clocks for Muxes in CMU_TOP0 */ | ||
175 | PNAME(mout_bus0_pll_p) = { "fin_pll", "dout_sclk_bus0_pll" }; | ||
176 | PNAME(mout_bus1_pll_p) = { "fin_pll", "dout_sclk_bus1_pll" }; | ||
177 | PNAME(mout_cc_pll_p) = { "fin_pll", "dout_sclk_cc_pll" }; | ||
178 | PNAME(mout_mfc_pll_p) = { "fin_pll", "dout_sclk_mfc_pll" }; | ||
179 | |||
180 | PNAME(mout_top0_half_bus0_pll_p) = {"mout_top0_bus0_pll", | ||
181 | "ffac_top0_bus0_pll_div2"}; | ||
182 | PNAME(mout_top0_half_bus1_pll_p) = {"mout_top0_bus1_pll", | ||
183 | "ffac_top0_bus1_pll_div2"}; | ||
184 | PNAME(mout_top0_half_cc_pll_p) = {"mout_top0_cc_pll", | ||
185 | "ffac_top0_cc_pll_div2"}; | ||
186 | PNAME(mout_top0_half_mfc_pll_p) = {"mout_top0_mfc_pll", | ||
187 | "ffac_top0_mfc_pll_div2"}; | ||
188 | |||
189 | PNAME(mout_top0_group1) = {"mout_top0_half_bus0_pll", | ||
190 | "mout_top0_half_bus1_pll", "mout_top0_half_cc_pll", | ||
191 | "mout_top0_half_mfc_pll"}; | ||
192 | |||
193 | static unsigned long top0_clk_regs[] __initdata = { | ||
194 | MUX_SEL_TOP00, | ||
195 | MUX_SEL_TOP01, | ||
196 | MUX_SEL_TOP03, | ||
197 | MUX_SEL_TOP0_PERIC3, | ||
198 | DIV_TOP03, | ||
199 | DIV_TOP0_PERIC3, | ||
200 | ENABLE_SCLK_TOP0_PERIC3, | ||
201 | }; | ||
202 | |||
203 | static struct samsung_mux_clock top0_mux_clks[] __initdata = { | ||
204 | MUX(0, "mout_top0_mfc_pll", mout_mfc_pll_p, MUX_SEL_TOP00, 4, 1), | ||
205 | MUX(0, "mout_top0_cc_pll", mout_cc_pll_p, MUX_SEL_TOP00, 8, 1), | ||
206 | MUX(0, "mout_top0_bus1_pll", mout_bus1_pll_p, MUX_SEL_TOP00, 12, 1), | ||
207 | MUX(0, "mout_top0_bus0_pll", mout_bus0_pll_p, MUX_SEL_TOP00, 16, 1), | ||
208 | |||
209 | MUX(0, "mout_top0_half_mfc_pll", mout_top0_half_mfc_pll_p, | ||
210 | MUX_SEL_TOP01, 4, 1), | ||
211 | MUX(0, "mout_top0_half_cc_pll", mout_top0_half_cc_pll_p, | ||
212 | MUX_SEL_TOP01, 8, 1), | ||
213 | MUX(0, "mout_top0_half_bus1_pll", mout_top0_half_bus1_pll_p, | ||
214 | MUX_SEL_TOP01, 12, 1), | ||
215 | MUX(0, "mout_top0_half_bus0_pll", mout_top0_half_bus0_pll_p, | ||
216 | MUX_SEL_TOP01, 16, 1), | ||
217 | |||
218 | MUX(0, "mout_aclk_peric1_66", mout_top0_group1, MUX_SEL_TOP03, 12, 2), | ||
219 | MUX(0, "mout_aclk_peric0_66", mout_top0_group1, MUX_SEL_TOP03, 20, 2), | ||
220 | |||
221 | MUX(0, "mout_sclk_uart3", mout_top0_group1, MUX_SEL_TOP0_PERIC3, 4, 2), | ||
222 | MUX(0, "mout_sclk_uart2", mout_top0_group1, MUX_SEL_TOP0_PERIC3, 8, 2), | ||
223 | MUX(0, "mout_sclk_uart1", mout_top0_group1, MUX_SEL_TOP0_PERIC3, 12, 2), | ||
224 | MUX(0, "mout_sclk_uart0", mout_top0_group1, MUX_SEL_TOP0_PERIC3, 16, 2), | ||
225 | }; | ||
226 | |||
227 | static struct samsung_div_clock top0_div_clks[] __initdata = { | ||
228 | DIV(DOUT_ACLK_PERIC1, "dout_aclk_peric1_66", "mout_aclk_peric1_66", | ||
229 | DIV_TOP03, 12, 6), | ||
230 | DIV(DOUT_ACLK_PERIC0, "dout_aclk_peric0_66", "mout_aclk_peric0_66", | ||
231 | DIV_TOP03, 20, 6), | ||
232 | |||
233 | DIV(0, "dout_sclk_uart3", "mout_sclk_uart3", DIV_TOP0_PERIC3, 4, 4), | ||
234 | DIV(0, "dout_sclk_uart2", "mout_sclk_uart2", DIV_TOP0_PERIC3, 8, 4), | ||
235 | DIV(0, "dout_sclk_uart1", "mout_sclk_uart1", DIV_TOP0_PERIC3, 12, 4), | ||
236 | DIV(0, "dout_sclk_uart0", "mout_sclk_uart0", DIV_TOP0_PERIC3, 16, 4), | ||
237 | }; | ||
238 | |||
239 | static struct samsung_gate_clock top0_gate_clks[] __initdata = { | ||
240 | GATE(CLK_SCLK_UART3, "sclk_uart3", "dout_sclk_uart3", | ||
241 | ENABLE_SCLK_TOP0_PERIC3, 4, 0, 0), | ||
242 | GATE(CLK_SCLK_UART2, "sclk_uart2", "dout_sclk_uart2", | ||
243 | ENABLE_SCLK_TOP0_PERIC3, 8, 0, 0), | ||
244 | GATE(CLK_SCLK_UART1, "sclk_uart1", "dout_sclk_uart1", | ||
245 | ENABLE_SCLK_TOP0_PERIC3, 12, 0, 0), | ||
246 | GATE(CLK_SCLK_UART0, "sclk_uart0", "dout_sclk_uart0", | ||
247 | ENABLE_SCLK_TOP0_PERIC3, 16, 0, 0), | ||
248 | }; | ||
249 | |||
250 | static struct samsung_fixed_factor_clock top0_fixed_factor_clks[] __initdata = { | ||
251 | FFACTOR(0, "ffac_top0_bus0_pll_div2", "mout_top0_bus0_pll", 1, 2, 0), | ||
252 | FFACTOR(0, "ffac_top0_bus1_pll_div2", "mout_top0_bus1_pll", 1, 2, 0), | ||
253 | FFACTOR(0, "ffac_top0_cc_pll_div2", "mout_top0_cc_pll", 1, 2, 0), | ||
254 | FFACTOR(0, "ffac_top0_mfc_pll_div2", "mout_top0_mfc_pll", 1, 2, 0), | ||
255 | }; | ||
256 | |||
257 | static struct samsung_cmu_info top0_cmu_info __initdata = { | ||
258 | .mux_clks = top0_mux_clks, | ||
259 | .nr_mux_clks = ARRAY_SIZE(top0_mux_clks), | ||
260 | .div_clks = top0_div_clks, | ||
261 | .nr_div_clks = ARRAY_SIZE(top0_div_clks), | ||
262 | .gate_clks = top0_gate_clks, | ||
263 | .nr_gate_clks = ARRAY_SIZE(top0_gate_clks), | ||
264 | .fixed_factor_clks = top0_fixed_factor_clks, | ||
265 | .nr_fixed_factor_clks = ARRAY_SIZE(top0_fixed_factor_clks), | ||
266 | .nr_clk_ids = TOP0_NR_CLK, | ||
267 | .clk_regs = top0_clk_regs, | ||
268 | .nr_clk_regs = ARRAY_SIZE(top0_clk_regs), | ||
269 | }; | ||
270 | |||
271 | static void __init exynos7_clk_top0_init(struct device_node *np) | ||
272 | { | ||
273 | samsung_cmu_register_one(np, &top0_cmu_info); | ||
274 | } | ||
275 | |||
276 | CLK_OF_DECLARE(exynos7_clk_top0, "samsung,exynos7-clock-top0", | ||
277 | exynos7_clk_top0_init); | ||
278 | |||
279 | /* Register Offset definitions for CMU_TOP1 (0x105E0000) */ | ||
280 | #define MUX_SEL_TOP10 0x0200 | ||
281 | #define MUX_SEL_TOP11 0x0204 | ||
282 | #define MUX_SEL_TOP13 0x020C | ||
283 | #define MUX_SEL_TOP1_FSYS0 0x0224 | ||
284 | #define MUX_SEL_TOP1_FSYS1 0x0228 | ||
285 | #define DIV_TOP13 0x060C | ||
286 | #define DIV_TOP1_FSYS0 0x0624 | ||
287 | #define DIV_TOP1_FSYS1 0x0628 | ||
288 | #define ENABLE_ACLK_TOP13 0x080C | ||
289 | #define ENABLE_SCLK_TOP1_FSYS0 0x0A24 | ||
290 | #define ENABLE_SCLK_TOP1_FSYS1 0x0A28 | ||
291 | |||
292 | /* List of parent clocks for Muxes in CMU_TOP1 */ | ||
293 | PNAME(mout_top1_bus0_pll_p) = { "fin_pll", "dout_sclk_bus0_pll" }; | ||
294 | PNAME(mout_top1_bus1_pll_p) = { "fin_pll", "dout_sclk_bus1_pll_b" }; | ||
295 | PNAME(mout_top1_cc_pll_p) = { "fin_pll", "dout_sclk_cc_pll_b" }; | ||
296 | PNAME(mout_top1_mfc_pll_p) = { "fin_pll", "dout_sclk_mfc_pll_b" }; | ||
297 | |||
298 | PNAME(mout_top1_half_bus0_pll_p) = {"mout_top1_bus0_pll", | ||
299 | "ffac_top1_bus0_pll_div2"}; | ||
300 | PNAME(mout_top1_half_bus1_pll_p) = {"mout_top1_bus1_pll", | ||
301 | "ffac_top1_bus1_pll_div2"}; | ||
302 | PNAME(mout_top1_half_cc_pll_p) = {"mout_top1_cc_pll", | ||
303 | "ffac_top1_cc_pll_div2"}; | ||
304 | PNAME(mout_top1_half_mfc_pll_p) = {"mout_top1_mfc_pll", | ||
305 | "ffac_top1_mfc_pll_div2"}; | ||
306 | |||
307 | PNAME(mout_top1_group1) = {"mout_top1_half_bus0_pll", | ||
308 | "mout_top1_half_bus1_pll", "mout_top1_half_cc_pll", | ||
309 | "mout_top1_half_mfc_pll"}; | ||
310 | |||
311 | static unsigned long top1_clk_regs[] __initdata = { | ||
312 | MUX_SEL_TOP10, | ||
313 | MUX_SEL_TOP11, | ||
314 | MUX_SEL_TOP13, | ||
315 | MUX_SEL_TOP1_FSYS0, | ||
316 | MUX_SEL_TOP1_FSYS1, | ||
317 | DIV_TOP13, | ||
318 | DIV_TOP1_FSYS0, | ||
319 | DIV_TOP1_FSYS1, | ||
320 | ENABLE_ACLK_TOP13, | ||
321 | ENABLE_SCLK_TOP1_FSYS0, | ||
322 | ENABLE_SCLK_TOP1_FSYS1, | ||
323 | }; | ||
324 | |||
325 | static struct samsung_mux_clock top1_mux_clks[] __initdata = { | ||
326 | MUX(0, "mout_top1_mfc_pll", mout_top1_mfc_pll_p, MUX_SEL_TOP10, 4, 1), | ||
327 | MUX(0, "mout_top1_cc_pll", mout_top1_cc_pll_p, MUX_SEL_TOP10, 8, 1), | ||
328 | MUX(0, "mout_top1_bus1_pll", mout_top1_bus1_pll_p, | ||
329 | MUX_SEL_TOP10, 12, 1), | ||
330 | MUX(0, "mout_top1_bus0_pll", mout_top1_bus0_pll_p, | ||
331 | MUX_SEL_TOP10, 16, 1), | ||
332 | |||
333 | MUX(0, "mout_top1_half_mfc_pll", mout_top1_half_mfc_pll_p, | ||
334 | MUX_SEL_TOP11, 4, 1), | ||
335 | MUX(0, "mout_top1_half_cc_pll", mout_top1_half_cc_pll_p, | ||
336 | MUX_SEL_TOP11, 8, 1), | ||
337 | MUX(0, "mout_top1_half_bus1_pll", mout_top1_half_bus1_pll_p, | ||
338 | MUX_SEL_TOP11, 12, 1), | ||
339 | MUX(0, "mout_top1_half_bus0_pll", mout_top1_half_bus0_pll_p, | ||
340 | MUX_SEL_TOP11, 16, 1), | ||
341 | |||
342 | MUX(0, "mout_aclk_fsys1_200", mout_top1_group1, MUX_SEL_TOP13, 24, 2), | ||
343 | MUX(0, "mout_aclk_fsys0_200", mout_top1_group1, MUX_SEL_TOP13, 28, 2), | ||
344 | |||
345 | MUX(0, "mout_sclk_mmc2", mout_top1_group1, MUX_SEL_TOP1_FSYS0, 24, 2), | ||
346 | |||
347 | MUX(0, "mout_sclk_mmc1", mout_top1_group1, MUX_SEL_TOP1_FSYS1, 24, 2), | ||
348 | MUX(0, "mout_sclk_mmc0", mout_top1_group1, MUX_SEL_TOP1_FSYS1, 28, 2), | ||
349 | }; | ||
350 | |||
351 | static struct samsung_div_clock top1_div_clks[] __initdata = { | ||
352 | DIV(DOUT_ACLK_FSYS1_200, "dout_aclk_fsys1_200", "mout_aclk_fsys1_200", | ||
353 | DIV_TOP13, 24, 4), | ||
354 | DIV(DOUT_ACLK_FSYS0_200, "dout_aclk_fsys0_200", "mout_aclk_fsys0_200", | ||
355 | DIV_TOP13, 28, 4), | ||
356 | |||
357 | DIV(DOUT_SCLK_MMC2, "dout_sclk_mmc2", "mout_sclk_mmc2", | ||
358 | DIV_TOP1_FSYS0, 24, 4), | ||
359 | |||
360 | DIV(DOUT_SCLK_MMC1, "dout_sclk_mmc1", "mout_sclk_mmc1", | ||
361 | DIV_TOP1_FSYS1, 24, 4), | ||
362 | DIV(DOUT_SCLK_MMC0, "dout_sclk_mmc0", "mout_sclk_mmc0", | ||
363 | DIV_TOP1_FSYS1, 28, 4), | ||
364 | }; | ||
365 | |||
366 | static struct samsung_gate_clock top1_gate_clks[] __initdata = { | ||
367 | GATE(CLK_SCLK_MMC2, "sclk_mmc2", "dout_sclk_mmc2", | ||
368 | ENABLE_SCLK_TOP1_FSYS0, 24, CLK_SET_RATE_PARENT, 0), | ||
369 | |||
370 | GATE(CLK_SCLK_MMC1, "sclk_mmc1", "dout_sclk_mmc1", | ||
371 | ENABLE_SCLK_TOP1_FSYS1, 24, CLK_SET_RATE_PARENT, 0), | ||
372 | GATE(CLK_SCLK_MMC0, "sclk_mmc0", "dout_sclk_mmc0", | ||
373 | ENABLE_SCLK_TOP1_FSYS1, 28, CLK_SET_RATE_PARENT, 0), | ||
374 | }; | ||
375 | |||
376 | static struct samsung_fixed_factor_clock top1_fixed_factor_clks[] __initdata = { | ||
377 | FFACTOR(0, "ffac_top1_bus0_pll_div2", "mout_top1_bus0_pll", 1, 2, 0), | ||
378 | FFACTOR(0, "ffac_top1_bus1_pll_div2", "mout_top1_bus1_pll", 1, 2, 0), | ||
379 | FFACTOR(0, "ffac_top1_cc_pll_div2", "mout_top1_cc_pll", 1, 2, 0), | ||
380 | FFACTOR(0, "ffac_top1_mfc_pll_div2", "mout_top1_mfc_pll", 1, 2, 0), | ||
381 | }; | ||
382 | |||
383 | static struct samsung_cmu_info top1_cmu_info __initdata = { | ||
384 | .mux_clks = top1_mux_clks, | ||
385 | .nr_mux_clks = ARRAY_SIZE(top1_mux_clks), | ||
386 | .div_clks = top1_div_clks, | ||
387 | .nr_div_clks = ARRAY_SIZE(top1_div_clks), | ||
388 | .gate_clks = top1_gate_clks, | ||
389 | .nr_gate_clks = ARRAY_SIZE(top1_gate_clks), | ||
390 | .fixed_factor_clks = top1_fixed_factor_clks, | ||
391 | .nr_fixed_factor_clks = ARRAY_SIZE(top1_fixed_factor_clks), | ||
392 | .nr_clk_ids = TOP1_NR_CLK, | ||
393 | .clk_regs = top1_clk_regs, | ||
394 | .nr_clk_regs = ARRAY_SIZE(top1_clk_regs), | ||
395 | }; | ||
396 | |||
397 | static void __init exynos7_clk_top1_init(struct device_node *np) | ||
398 | { | ||
399 | samsung_cmu_register_one(np, &top1_cmu_info); | ||
400 | } | ||
401 | |||
402 | CLK_OF_DECLARE(exynos7_clk_top1, "samsung,exynos7-clock-top1", | ||
403 | exynos7_clk_top1_init); | ||
404 | |||
405 | /* Register Offset definitions for CMU_CCORE (0x105B0000) */ | ||
406 | #define MUX_SEL_CCORE 0x0200 | ||
407 | #define DIV_CCORE 0x0600 | ||
408 | #define ENABLE_ACLK_CCORE0 0x0800 | ||
409 | #define ENABLE_ACLK_CCORE1 0x0804 | ||
410 | #define ENABLE_PCLK_CCORE 0x0900 | ||
411 | |||
412 | /* | ||
413 | * List of parent clocks for Muxes in CMU_CCORE | ||
414 | */ | ||
415 | PNAME(mout_aclk_ccore_133_p) = { "fin_pll", "dout_aclk_ccore_133" }; | ||
416 | |||
417 | static unsigned long ccore_clk_regs[] __initdata = { | ||
418 | MUX_SEL_CCORE, | ||
419 | ENABLE_PCLK_CCORE, | ||
420 | }; | ||
421 | |||
422 | static struct samsung_mux_clock ccore_mux_clks[] __initdata = { | ||
423 | MUX(0, "mout_aclk_ccore_133_user", mout_aclk_ccore_133_p, | ||
424 | MUX_SEL_CCORE, 1, 1), | ||
425 | }; | ||
426 | |||
427 | static struct samsung_gate_clock ccore_gate_clks[] __initdata = { | ||
428 | GATE(PCLK_RTC, "pclk_rtc", "mout_aclk_ccore_133_user", | ||
429 | ENABLE_PCLK_CCORE, 8, 0, 0), | ||
430 | }; | ||
431 | |||
432 | static struct samsung_cmu_info ccore_cmu_info __initdata = { | ||
433 | .mux_clks = ccore_mux_clks, | ||
434 | .nr_mux_clks = ARRAY_SIZE(ccore_mux_clks), | ||
435 | .gate_clks = ccore_gate_clks, | ||
436 | .nr_gate_clks = ARRAY_SIZE(ccore_gate_clks), | ||
437 | .nr_clk_ids = CCORE_NR_CLK, | ||
438 | .clk_regs = ccore_clk_regs, | ||
439 | .nr_clk_regs = ARRAY_SIZE(ccore_clk_regs), | ||
440 | }; | ||
441 | |||
442 | static void __init exynos7_clk_ccore_init(struct device_node *np) | ||
443 | { | ||
444 | samsung_cmu_register_one(np, &ccore_cmu_info); | ||
445 | } | ||
446 | |||
447 | CLK_OF_DECLARE(exynos7_clk_ccore, "samsung,exynos7-clock-ccore", | ||
448 | exynos7_clk_ccore_init); | ||
449 | |||
450 | /* Register Offset definitions for CMU_PERIC0 (0x13610000) */ | ||
451 | #define MUX_SEL_PERIC0 0x0200 | ||
452 | #define ENABLE_PCLK_PERIC0 0x0900 | ||
453 | #define ENABLE_SCLK_PERIC0 0x0A00 | ||
454 | |||
455 | /* List of parent clocks for Muxes in CMU_PERIC0 */ | ||
456 | PNAME(mout_aclk_peric0_66_p) = { "fin_pll", "dout_aclk_peric0_66" }; | ||
457 | PNAME(mout_sclk_uart0_p) = { "fin_pll", "sclk_uart0" }; | ||
458 | |||
459 | static unsigned long peric0_clk_regs[] __initdata = { | ||
460 | MUX_SEL_PERIC0, | ||
461 | ENABLE_PCLK_PERIC0, | ||
462 | ENABLE_SCLK_PERIC0, | ||
463 | }; | ||
464 | |||
465 | static struct samsung_mux_clock peric0_mux_clks[] __initdata = { | ||
466 | MUX(0, "mout_aclk_peric0_66_user", mout_aclk_peric0_66_p, | ||
467 | MUX_SEL_PERIC0, 0, 1), | ||
468 | MUX(0, "mout_sclk_uart0_user", mout_sclk_uart0_p, | ||
469 | MUX_SEL_PERIC0, 16, 1), | ||
470 | }; | ||
471 | |||
472 | static struct samsung_gate_clock peric0_gate_clks[] __initdata = { | ||
473 | GATE(PCLK_HSI2C0, "pclk_hsi2c0", "mout_aclk_peric0_66_user", | ||
474 | ENABLE_PCLK_PERIC0, 8, 0, 0), | ||
475 | GATE(PCLK_HSI2C1, "pclk_hsi2c1", "mout_aclk_peric0_66_user", | ||
476 | ENABLE_PCLK_PERIC0, 9, 0, 0), | ||
477 | GATE(PCLK_HSI2C4, "pclk_hsi2c4", "mout_aclk_peric0_66_user", | ||
478 | ENABLE_PCLK_PERIC0, 10, 0, 0), | ||
479 | GATE(PCLK_HSI2C5, "pclk_hsi2c5", "mout_aclk_peric0_66_user", | ||
480 | ENABLE_PCLK_PERIC0, 11, 0, 0), | ||
481 | GATE(PCLK_HSI2C9, "pclk_hsi2c9", "mout_aclk_peric0_66_user", | ||
482 | ENABLE_PCLK_PERIC0, 12, 0, 0), | ||
483 | GATE(PCLK_HSI2C10, "pclk_hsi2c10", "mout_aclk_peric0_66_user", | ||
484 | ENABLE_PCLK_PERIC0, 13, 0, 0), | ||
485 | GATE(PCLK_HSI2C11, "pclk_hsi2c11", "mout_aclk_peric0_66_user", | ||
486 | ENABLE_PCLK_PERIC0, 14, 0, 0), | ||
487 | GATE(PCLK_UART0, "pclk_uart0", "mout_aclk_peric0_66_user", | ||
488 | ENABLE_PCLK_PERIC0, 16, 0, 0), | ||
489 | GATE(PCLK_ADCIF, "pclk_adcif", "mout_aclk_peric0_66_user", | ||
490 | ENABLE_PCLK_PERIC0, 20, 0, 0), | ||
491 | GATE(PCLK_PWM, "pclk_pwm", "mout_aclk_peric0_66_user", | ||
492 | ENABLE_PCLK_PERIC0, 21, 0, 0), | ||
493 | |||
494 | GATE(SCLK_UART0, "sclk_uart0_user", "mout_sclk_uart0_user", | ||
495 | ENABLE_SCLK_PERIC0, 16, 0, 0), | ||
496 | GATE(SCLK_PWM, "sclk_pwm", "fin_pll", ENABLE_SCLK_PERIC0, 21, 0, 0), | ||
497 | }; | ||
498 | |||
499 | static struct samsung_cmu_info peric0_cmu_info __initdata = { | ||
500 | .mux_clks = peric0_mux_clks, | ||
501 | .nr_mux_clks = ARRAY_SIZE(peric0_mux_clks), | ||
502 | .gate_clks = peric0_gate_clks, | ||
503 | .nr_gate_clks = ARRAY_SIZE(peric0_gate_clks), | ||
504 | .nr_clk_ids = PERIC0_NR_CLK, | ||
505 | .clk_regs = peric0_clk_regs, | ||
506 | .nr_clk_regs = ARRAY_SIZE(peric0_clk_regs), | ||
507 | }; | ||
508 | |||
509 | static void __init exynos7_clk_peric0_init(struct device_node *np) | ||
510 | { | ||
511 | samsung_cmu_register_one(np, &peric0_cmu_info); | ||
512 | } | ||
513 | |||
514 | /* Register Offset definitions for CMU_PERIC1 (0x14C80000) */ | ||
515 | #define MUX_SEL_PERIC10 0x0200 | ||
516 | #define MUX_SEL_PERIC11 0x0204 | ||
517 | #define ENABLE_PCLK_PERIC1 0x0900 | ||
518 | #define ENABLE_SCLK_PERIC10 0x0A00 | ||
519 | |||
520 | CLK_OF_DECLARE(exynos7_clk_peric0, "samsung,exynos7-clock-peric0", | ||
521 | exynos7_clk_peric0_init); | ||
522 | |||
523 | /* List of parent clocks for Muxes in CMU_PERIC1 */ | ||
524 | PNAME(mout_aclk_peric1_66_p) = { "fin_pll", "dout_aclk_peric1_66" }; | ||
525 | PNAME(mout_sclk_uart1_p) = { "fin_pll", "sclk_uart1" }; | ||
526 | PNAME(mout_sclk_uart2_p) = { "fin_pll", "sclk_uart2" }; | ||
527 | PNAME(mout_sclk_uart3_p) = { "fin_pll", "sclk_uart3" }; | ||
528 | |||
529 | static unsigned long peric1_clk_regs[] __initdata = { | ||
530 | MUX_SEL_PERIC10, | ||
531 | MUX_SEL_PERIC11, | ||
532 | ENABLE_PCLK_PERIC1, | ||
533 | ENABLE_SCLK_PERIC10, | ||
534 | }; | ||
535 | |||
536 | static struct samsung_mux_clock peric1_mux_clks[] __initdata = { | ||
537 | MUX(0, "mout_aclk_peric1_66_user", mout_aclk_peric1_66_p, | ||
538 | MUX_SEL_PERIC10, 0, 1), | ||
539 | |||
540 | MUX(0, "mout_sclk_uart1_user", mout_sclk_uart1_p, | ||
541 | MUX_SEL_PERIC11, 20, 1), | ||
542 | MUX(0, "mout_sclk_uart2_user", mout_sclk_uart2_p, | ||
543 | MUX_SEL_PERIC11, 24, 1), | ||
544 | MUX(0, "mout_sclk_uart3_user", mout_sclk_uart3_p, | ||
545 | MUX_SEL_PERIC11, 28, 1), | ||
546 | }; | ||
547 | |||
548 | static struct samsung_gate_clock peric1_gate_clks[] __initdata = { | ||
549 | GATE(PCLK_HSI2C2, "pclk_hsi2c2", "mout_aclk_peric1_66_user", | ||
550 | ENABLE_PCLK_PERIC1, 4, 0, 0), | ||
551 | GATE(PCLK_HSI2C3, "pclk_hsi2c3", "mout_aclk_peric1_66_user", | ||
552 | ENABLE_PCLK_PERIC1, 5, 0, 0), | ||
553 | GATE(PCLK_HSI2C6, "pclk_hsi2c6", "mout_aclk_peric1_66_user", | ||
554 | ENABLE_PCLK_PERIC1, 6, 0, 0), | ||
555 | GATE(PCLK_HSI2C7, "pclk_hsi2c7", "mout_aclk_peric1_66_user", | ||
556 | ENABLE_PCLK_PERIC1, 7, 0, 0), | ||
557 | GATE(PCLK_HSI2C8, "pclk_hsi2c8", "mout_aclk_peric1_66_user", | ||
558 | ENABLE_PCLK_PERIC1, 8, 0, 0), | ||
559 | GATE(PCLK_UART1, "pclk_uart1", "mout_aclk_peric1_66_user", | ||
560 | ENABLE_PCLK_PERIC1, 9, 0, 0), | ||
561 | GATE(PCLK_UART2, "pclk_uart2", "mout_aclk_peric1_66_user", | ||
562 | ENABLE_PCLK_PERIC1, 10, 0, 0), | ||
563 | GATE(PCLK_UART3, "pclk_uart3", "mout_aclk_peric1_66_user", | ||
564 | ENABLE_PCLK_PERIC1, 11, 0, 0), | ||
565 | |||
566 | GATE(SCLK_UART1, "sclk_uart1_user", "mout_sclk_uart1_user", | ||
567 | ENABLE_SCLK_PERIC10, 9, 0, 0), | ||
568 | GATE(SCLK_UART2, "sclk_uart2_user", "mout_sclk_uart2_user", | ||
569 | ENABLE_SCLK_PERIC10, 10, 0, 0), | ||
570 | GATE(SCLK_UART3, "sclk_uart3_user", "mout_sclk_uart3_user", | ||
571 | ENABLE_SCLK_PERIC10, 11, 0, 0), | ||
572 | }; | ||
573 | |||
574 | static struct samsung_cmu_info peric1_cmu_info __initdata = { | ||
575 | .mux_clks = peric1_mux_clks, | ||
576 | .nr_mux_clks = ARRAY_SIZE(peric1_mux_clks), | ||
577 | .gate_clks = peric1_gate_clks, | ||
578 | .nr_gate_clks = ARRAY_SIZE(peric1_gate_clks), | ||
579 | .nr_clk_ids = PERIC1_NR_CLK, | ||
580 | .clk_regs = peric1_clk_regs, | ||
581 | .nr_clk_regs = ARRAY_SIZE(peric1_clk_regs), | ||
582 | }; | ||
583 | |||
584 | static void __init exynos7_clk_peric1_init(struct device_node *np) | ||
585 | { | ||
586 | samsung_cmu_register_one(np, &peric1_cmu_info); | ||
587 | } | ||
588 | |||
589 | CLK_OF_DECLARE(exynos7_clk_peric1, "samsung,exynos7-clock-peric1", | ||
590 | exynos7_clk_peric1_init); | ||
591 | |||
592 | /* Register Offset definitions for CMU_PERIS (0x10040000) */ | ||
593 | #define MUX_SEL_PERIS 0x0200 | ||
594 | #define ENABLE_PCLK_PERIS 0x0900 | ||
595 | #define ENABLE_PCLK_PERIS_SECURE_CHIPID 0x0910 | ||
596 | #define ENABLE_SCLK_PERIS 0x0A00 | ||
597 | #define ENABLE_SCLK_PERIS_SECURE_CHIPID 0x0A10 | ||
598 | |||
599 | /* List of parent clocks for Muxes in CMU_PERIS */ | ||
600 | PNAME(mout_aclk_peris_66_p) = { "fin_pll", "dout_aclk_peris_66" }; | ||
601 | |||
602 | static unsigned long peris_clk_regs[] __initdata = { | ||
603 | MUX_SEL_PERIS, | ||
604 | ENABLE_PCLK_PERIS, | ||
605 | ENABLE_PCLK_PERIS_SECURE_CHIPID, | ||
606 | ENABLE_SCLK_PERIS, | ||
607 | ENABLE_SCLK_PERIS_SECURE_CHIPID, | ||
608 | }; | ||
609 | |||
610 | static struct samsung_mux_clock peris_mux_clks[] __initdata = { | ||
611 | MUX(0, "mout_aclk_peris_66_user", | ||
612 | mout_aclk_peris_66_p, MUX_SEL_PERIS, 0, 1), | ||
613 | }; | ||
614 | |||
615 | static struct samsung_gate_clock peris_gate_clks[] __initdata = { | ||
616 | GATE(PCLK_WDT, "pclk_wdt", "mout_aclk_peris_66_user", | ||
617 | ENABLE_PCLK_PERIS, 6, 0, 0), | ||
618 | GATE(PCLK_TMU, "pclk_tmu_apbif", "mout_aclk_peris_66_user", | ||
619 | ENABLE_PCLK_PERIS, 10, 0, 0), | ||
620 | |||
621 | GATE(PCLK_CHIPID, "pclk_chipid", "mout_aclk_peris_66_user", | ||
622 | ENABLE_PCLK_PERIS_SECURE_CHIPID, 0, 0, 0), | ||
623 | GATE(SCLK_CHIPID, "sclk_chipid", "fin_pll", | ||
624 | ENABLE_SCLK_PERIS_SECURE_CHIPID, 0, 0, 0), | ||
625 | |||
626 | GATE(SCLK_TMU, "sclk_tmu", "fin_pll", ENABLE_SCLK_PERIS, 10, 0, 0), | ||
627 | }; | ||
628 | |||
629 | static struct samsung_cmu_info peris_cmu_info __initdata = { | ||
630 | .mux_clks = peris_mux_clks, | ||
631 | .nr_mux_clks = ARRAY_SIZE(peris_mux_clks), | ||
632 | .gate_clks = peris_gate_clks, | ||
633 | .nr_gate_clks = ARRAY_SIZE(peris_gate_clks), | ||
634 | .nr_clk_ids = PERIS_NR_CLK, | ||
635 | .clk_regs = peris_clk_regs, | ||
636 | .nr_clk_regs = ARRAY_SIZE(peris_clk_regs), | ||
637 | }; | ||
638 | |||
639 | static void __init exynos7_clk_peris_init(struct device_node *np) | ||
640 | { | ||
641 | samsung_cmu_register_one(np, &peris_cmu_info); | ||
642 | } | ||
643 | |||
644 | CLK_OF_DECLARE(exynos7_clk_peris, "samsung,exynos7-clock-peris", | ||
645 | exynos7_clk_peris_init); | ||
646 | |||
647 | /* Register Offset definitions for CMU_FSYS0 (0x10E90000) */ | ||
648 | #define MUX_SEL_FSYS00 0x0200 | ||
649 | #define MUX_SEL_FSYS01 0x0204 | ||
650 | #define ENABLE_ACLK_FSYS01 0x0804 | ||
651 | |||
652 | /* | ||
653 | * List of parent clocks for Muxes in CMU_FSYS0 | ||
654 | */ | ||
655 | PNAME(mout_aclk_fsys0_200_p) = { "fin_pll", "dout_aclk_fsys0_200" }; | ||
656 | PNAME(mout_sclk_mmc2_p) = { "fin_pll", "sclk_mmc2" }; | ||
657 | |||
658 | static unsigned long fsys0_clk_regs[] __initdata = { | ||
659 | MUX_SEL_FSYS00, | ||
660 | MUX_SEL_FSYS01, | ||
661 | ENABLE_ACLK_FSYS01, | ||
662 | }; | ||
663 | |||
664 | static struct samsung_mux_clock fsys0_mux_clks[] __initdata = { | ||
665 | MUX(0, "mout_aclk_fsys0_200_user", mout_aclk_fsys0_200_p, | ||
666 | MUX_SEL_FSYS00, 24, 1), | ||
667 | |||
668 | MUX(0, "mout_sclk_mmc2_user", mout_sclk_mmc2_p, MUX_SEL_FSYS01, 24, 1), | ||
669 | }; | ||
670 | |||
671 | static struct samsung_gate_clock fsys0_gate_clks[] __initdata = { | ||
672 | GATE(ACLK_MMC2, "aclk_mmc2", "mout_aclk_fsys0_200_user", | ||
673 | ENABLE_ACLK_FSYS01, 31, 0, 0), | ||
674 | }; | ||
675 | |||
676 | static struct samsung_cmu_info fsys0_cmu_info __initdata = { | ||
677 | .mux_clks = fsys0_mux_clks, | ||
678 | .nr_mux_clks = ARRAY_SIZE(fsys0_mux_clks), | ||
679 | .gate_clks = fsys0_gate_clks, | ||
680 | .nr_gate_clks = ARRAY_SIZE(fsys0_gate_clks), | ||
681 | .nr_clk_ids = TOP1_NR_CLK, | ||
682 | .clk_regs = fsys0_clk_regs, | ||
683 | .nr_clk_regs = ARRAY_SIZE(fsys0_clk_regs), | ||
684 | }; | ||
685 | |||
686 | static void __init exynos7_clk_fsys0_init(struct device_node *np) | ||
687 | { | ||
688 | samsung_cmu_register_one(np, &fsys0_cmu_info); | ||
689 | } | ||
690 | |||
691 | CLK_OF_DECLARE(exynos7_clk_fsys0, "samsung,exynos7-clock-fsys0", | ||
692 | exynos7_clk_fsys0_init); | ||
693 | |||
694 | /* Register Offset definitions for CMU_FSYS1 (0x156E0000) */ | ||
695 | #define MUX_SEL_FSYS10 0x0200 | ||
696 | #define MUX_SEL_FSYS11 0x0204 | ||
697 | #define ENABLE_ACLK_FSYS1 0x0800 | ||
698 | |||
699 | /* | ||
700 | * List of parent clocks for Muxes in CMU_FSYS1 | ||
701 | */ | ||
702 | PNAME(mout_aclk_fsys1_200_p) = { "fin_pll", "dout_aclk_fsys1_200" }; | ||
703 | PNAME(mout_sclk_mmc0_p) = { "fin_pll", "sclk_mmc0" }; | ||
704 | PNAME(mout_sclk_mmc1_p) = { "fin_pll", "sclk_mmc1" }; | ||
705 | |||
706 | static unsigned long fsys1_clk_regs[] __initdata = { | ||
707 | MUX_SEL_FSYS10, | ||
708 | MUX_SEL_FSYS11, | ||
709 | ENABLE_ACLK_FSYS1, | ||
710 | }; | ||
711 | |||
712 | static struct samsung_mux_clock fsys1_mux_clks[] __initdata = { | ||
713 | MUX(0, "mout_aclk_fsys1_200_user", mout_aclk_fsys1_200_p, | ||
714 | MUX_SEL_FSYS10, 28, 1), | ||
715 | |||
716 | MUX(0, "mout_sclk_mmc1_user", mout_sclk_mmc1_p, MUX_SEL_FSYS11, 24, 1), | ||
717 | MUX(0, "mout_sclk_mmc0_user", mout_sclk_mmc0_p, MUX_SEL_FSYS11, 28, 1), | ||
718 | }; | ||
719 | |||
720 | static struct samsung_gate_clock fsys1_gate_clks[] __initdata = { | ||
721 | GATE(ACLK_MMC1, "aclk_mmc1", "mout_aclk_fsys1_200_user", | ||
722 | ENABLE_ACLK_FSYS1, 29, 0, 0), | ||
723 | GATE(ACLK_MMC0, "aclk_mmc0", "mout_aclk_fsys1_200_user", | ||
724 | ENABLE_ACLK_FSYS1, 30, 0, 0), | ||
725 | }; | ||
726 | |||
727 | static struct samsung_cmu_info fsys1_cmu_info __initdata = { | ||
728 | .mux_clks = fsys1_mux_clks, | ||
729 | .nr_mux_clks = ARRAY_SIZE(fsys1_mux_clks), | ||
730 | .gate_clks = fsys1_gate_clks, | ||
731 | .nr_gate_clks = ARRAY_SIZE(fsys1_gate_clks), | ||
732 | .nr_clk_ids = TOP1_NR_CLK, | ||
733 | .clk_regs = fsys1_clk_regs, | ||
734 | .nr_clk_regs = ARRAY_SIZE(fsys1_clk_regs), | ||
735 | }; | ||
736 | |||
737 | static void __init exynos7_clk_fsys1_init(struct device_node *np) | ||
738 | { | ||
739 | samsung_cmu_register_one(np, &fsys1_cmu_info); | ||
740 | } | ||
741 | |||
742 | CLK_OF_DECLARE(exynos7_clk_fsys1, "samsung,exynos7-clock-fsys1", | ||
743 | exynos7_clk_fsys1_init); | ||
diff --git a/drivers/clk/samsung/clk-pll.c b/drivers/clk/samsung/clk-pll.c index b07fad2a9167..9d70e5c03804 100644 --- a/drivers/clk/samsung/clk-pll.c +++ b/drivers/clk/samsung/clk-pll.c | |||
@@ -482,6 +482,8 @@ static const struct clk_ops samsung_pll45xx_clk_min_ops = { | |||
482 | 482 | ||
483 | #define PLL46XX_VSEL_MASK (1) | 483 | #define PLL46XX_VSEL_MASK (1) |
484 | #define PLL46XX_MDIV_MASK (0x1FF) | 484 | #define PLL46XX_MDIV_MASK (0x1FF) |
485 | #define PLL1460X_MDIV_MASK (0x3FF) | ||
486 | |||
485 | #define PLL46XX_PDIV_MASK (0x3F) | 487 | #define PLL46XX_PDIV_MASK (0x3F) |
486 | #define PLL46XX_SDIV_MASK (0x7) | 488 | #define PLL46XX_SDIV_MASK (0x7) |
487 | #define PLL46XX_VSEL_SHIFT (27) | 489 | #define PLL46XX_VSEL_SHIFT (27) |
@@ -511,13 +513,15 @@ static unsigned long samsung_pll46xx_recalc_rate(struct clk_hw *hw, | |||
511 | 513 | ||
512 | pll_con0 = __raw_readl(pll->con_reg); | 514 | pll_con0 = __raw_readl(pll->con_reg); |
513 | pll_con1 = __raw_readl(pll->con_reg + 4); | 515 | pll_con1 = __raw_readl(pll->con_reg + 4); |
514 | mdiv = (pll_con0 >> PLL46XX_MDIV_SHIFT) & PLL46XX_MDIV_MASK; | 516 | mdiv = (pll_con0 >> PLL46XX_MDIV_SHIFT) & ((pll->type == pll_1460x) ? |
517 | PLL1460X_MDIV_MASK : PLL46XX_MDIV_MASK); | ||
515 | pdiv = (pll_con0 >> PLL46XX_PDIV_SHIFT) & PLL46XX_PDIV_MASK; | 518 | pdiv = (pll_con0 >> PLL46XX_PDIV_SHIFT) & PLL46XX_PDIV_MASK; |
516 | sdiv = (pll_con0 >> PLL46XX_SDIV_SHIFT) & PLL46XX_SDIV_MASK; | 519 | sdiv = (pll_con0 >> PLL46XX_SDIV_SHIFT) & PLL46XX_SDIV_MASK; |
517 | kdiv = pll->type == pll_4650c ? pll_con1 & PLL4650C_KDIV_MASK : | 520 | kdiv = pll->type == pll_4650c ? pll_con1 & PLL4650C_KDIV_MASK : |
518 | pll_con1 & PLL46XX_KDIV_MASK; | 521 | pll_con1 & PLL46XX_KDIV_MASK; |
519 | 522 | ||
520 | shift = pll->type == pll_4600 ? 16 : 10; | 523 | shift = ((pll->type == pll_4600) || (pll->type == pll_1460x)) ? 16 : 10; |
524 | |||
521 | fvco *= (mdiv << shift) + kdiv; | 525 | fvco *= (mdiv << shift) + kdiv; |
522 | do_div(fvco, (pdiv << sdiv)); | 526 | do_div(fvco, (pdiv << sdiv)); |
523 | fvco >>= shift; | 527 | fvco >>= shift; |
@@ -573,14 +577,21 @@ static int samsung_pll46xx_set_rate(struct clk_hw *hw, unsigned long drate, | |||
573 | lock = 0xffff; | 577 | lock = 0xffff; |
574 | 578 | ||
575 | /* Set PLL PMS and VSEL values. */ | 579 | /* Set PLL PMS and VSEL values. */ |
576 | con0 &= ~((PLL46XX_MDIV_MASK << PLL46XX_MDIV_SHIFT) | | 580 | if (pll->type == pll_1460x) { |
581 | con0 &= ~((PLL1460X_MDIV_MASK << PLL46XX_MDIV_SHIFT) | | ||
582 | (PLL46XX_PDIV_MASK << PLL46XX_PDIV_SHIFT) | | ||
583 | (PLL46XX_SDIV_MASK << PLL46XX_SDIV_SHIFT)); | ||
584 | } else { | ||
585 | con0 &= ~((PLL46XX_MDIV_MASK << PLL46XX_MDIV_SHIFT) | | ||
577 | (PLL46XX_PDIV_MASK << PLL46XX_PDIV_SHIFT) | | 586 | (PLL46XX_PDIV_MASK << PLL46XX_PDIV_SHIFT) | |
578 | (PLL46XX_SDIV_MASK << PLL46XX_SDIV_SHIFT) | | 587 | (PLL46XX_SDIV_MASK << PLL46XX_SDIV_SHIFT) | |
579 | (PLL46XX_VSEL_MASK << PLL46XX_VSEL_SHIFT)); | 588 | (PLL46XX_VSEL_MASK << PLL46XX_VSEL_SHIFT)); |
589 | con0 |= rate->vsel << PLL46XX_VSEL_SHIFT; | ||
590 | } | ||
591 | |||
580 | con0 |= (rate->mdiv << PLL46XX_MDIV_SHIFT) | | 592 | con0 |= (rate->mdiv << PLL46XX_MDIV_SHIFT) | |
581 | (rate->pdiv << PLL46XX_PDIV_SHIFT) | | 593 | (rate->pdiv << PLL46XX_PDIV_SHIFT) | |
582 | (rate->sdiv << PLL46XX_SDIV_SHIFT) | | 594 | (rate->sdiv << PLL46XX_SDIV_SHIFT); |
583 | (rate->vsel << PLL46XX_VSEL_SHIFT); | ||
584 | 595 | ||
585 | /* Set PLL K, MFR and MRR values. */ | 596 | /* Set PLL K, MFR and MRR values. */ |
586 | con1 = __raw_readl(pll->con_reg + 0x4); | 597 | con1 = __raw_readl(pll->con_reg + 0x4); |
@@ -1190,6 +1201,9 @@ static void __init _samsung_clk_register_pll(struct samsung_clk_provider *ctx, | |||
1190 | /* clk_ops for 35xx and 2550 are similar */ | 1201 | /* clk_ops for 35xx and 2550 are similar */ |
1191 | case pll_35xx: | 1202 | case pll_35xx: |
1192 | case pll_2550: | 1203 | case pll_2550: |
1204 | case pll_1450x: | ||
1205 | case pll_1451x: | ||
1206 | case pll_1452x: | ||
1193 | if (!pll->rate_table) | 1207 | if (!pll->rate_table) |
1194 | init.ops = &samsung_pll35xx_clk_min_ops; | 1208 | init.ops = &samsung_pll35xx_clk_min_ops; |
1195 | else | 1209 | else |
@@ -1223,6 +1237,7 @@ static void __init _samsung_clk_register_pll(struct samsung_clk_provider *ctx, | |||
1223 | case pll_4600: | 1237 | case pll_4600: |
1224 | case pll_4650: | 1238 | case pll_4650: |
1225 | case pll_4650c: | 1239 | case pll_4650c: |
1240 | case pll_1460x: | ||
1226 | if (!pll->rate_table) | 1241 | if (!pll->rate_table) |
1227 | init.ops = &samsung_pll46xx_clk_min_ops; | 1242 | init.ops = &samsung_pll46xx_clk_min_ops; |
1228 | else | 1243 | else |
diff --git a/drivers/clk/samsung/clk-pll.h b/drivers/clk/samsung/clk-pll.h index c0ed4d41fd90..213de9af8b4f 100644 --- a/drivers/clk/samsung/clk-pll.h +++ b/drivers/clk/samsung/clk-pll.h | |||
@@ -33,6 +33,10 @@ enum samsung_pll_type { | |||
33 | pll_s3c2440_mpll, | 33 | pll_s3c2440_mpll, |
34 | pll_2550xx, | 34 | pll_2550xx, |
35 | pll_2650xx, | 35 | pll_2650xx, |
36 | pll_1450x, | ||
37 | pll_1451x, | ||
38 | pll_1452x, | ||
39 | pll_1460x, | ||
36 | }; | 40 | }; |
37 | 41 | ||
38 | #define PLL_35XX_RATE(_rate, _m, _p, _s) \ | 42 | #define PLL_35XX_RATE(_rate, _m, _p, _s) \ |
diff --git a/drivers/clk/samsung/clk.c b/drivers/clk/samsung/clk.c index deab84d9f37d..4bda54095a16 100644 --- a/drivers/clk/samsung/clk.c +++ b/drivers/clk/samsung/clk.c | |||
@@ -11,9 +11,13 @@ | |||
11 | * clock framework for Samsung platforms. | 11 | * clock framework for Samsung platforms. |
12 | */ | 12 | */ |
13 | 13 | ||
14 | #include <linux/of_address.h> | ||
14 | #include <linux/syscore_ops.h> | 15 | #include <linux/syscore_ops.h> |
16 | |||
15 | #include "clk.h" | 17 | #include "clk.h" |
16 | 18 | ||
19 | static LIST_HEAD(clock_reg_cache_list); | ||
20 | |||
17 | void samsung_clk_save(void __iomem *base, | 21 | void samsung_clk_save(void __iomem *base, |
18 | struct samsung_clk_reg_dump *rd, | 22 | struct samsung_clk_reg_dump *rd, |
19 | unsigned int num_regs) | 23 | unsigned int num_regs) |
@@ -281,7 +285,6 @@ void __init samsung_clk_register_gate(struct samsung_clk_provider *ctx, | |||
281 | * obtain the clock speed of all external fixed clock sources from device | 285 | * obtain the clock speed of all external fixed clock sources from device |
282 | * tree and register it | 286 | * tree and register it |
283 | */ | 287 | */ |
284 | #ifdef CONFIG_OF | ||
285 | void __init samsung_clk_of_register_fixed_ext(struct samsung_clk_provider *ctx, | 288 | void __init samsung_clk_of_register_fixed_ext(struct samsung_clk_provider *ctx, |
286 | struct samsung_fixed_rate_clock *fixed_rate_clk, | 289 | struct samsung_fixed_rate_clock *fixed_rate_clk, |
287 | unsigned int nr_fixed_rate_clk, | 290 | unsigned int nr_fixed_rate_clk, |
@@ -298,7 +301,6 @@ void __init samsung_clk_of_register_fixed_ext(struct samsung_clk_provider *ctx, | |||
298 | } | 301 | } |
299 | samsung_clk_register_fixed_rate(ctx, fixed_rate_clk, nr_fixed_rate_clk); | 302 | samsung_clk_register_fixed_rate(ctx, fixed_rate_clk, nr_fixed_rate_clk); |
300 | } | 303 | } |
301 | #endif | ||
302 | 304 | ||
303 | /* utility function to get the rate of a specified clock */ | 305 | /* utility function to get the rate of a specified clock */ |
304 | unsigned long _get_rate(const char *clk_name) | 306 | unsigned long _get_rate(const char *clk_name) |
@@ -313,3 +315,99 @@ unsigned long _get_rate(const char *clk_name) | |||
313 | 315 | ||
314 | return clk_get_rate(clk); | 316 | return clk_get_rate(clk); |
315 | } | 317 | } |
318 | |||
319 | #ifdef CONFIG_PM_SLEEP | ||
320 | static int samsung_clk_suspend(void) | ||
321 | { | ||
322 | struct samsung_clock_reg_cache *reg_cache; | ||
323 | |||
324 | list_for_each_entry(reg_cache, &clock_reg_cache_list, node) | ||
325 | samsung_clk_save(reg_cache->reg_base, reg_cache->rdump, | ||
326 | reg_cache->rd_num); | ||
327 | return 0; | ||
328 | } | ||
329 | |||
330 | static void samsung_clk_resume(void) | ||
331 | { | ||
332 | struct samsung_clock_reg_cache *reg_cache; | ||
333 | |||
334 | list_for_each_entry(reg_cache, &clock_reg_cache_list, node) | ||
335 | samsung_clk_restore(reg_cache->reg_base, reg_cache->rdump, | ||
336 | reg_cache->rd_num); | ||
337 | } | ||
338 | |||
339 | static struct syscore_ops samsung_clk_syscore_ops = { | ||
340 | .suspend = samsung_clk_suspend, | ||
341 | .resume = samsung_clk_resume, | ||
342 | }; | ||
343 | |||
344 | static void samsung_clk_sleep_init(void __iomem *reg_base, | ||
345 | const unsigned long *rdump, | ||
346 | unsigned long nr_rdump) | ||
347 | { | ||
348 | struct samsung_clock_reg_cache *reg_cache; | ||
349 | |||
350 | reg_cache = kzalloc(sizeof(struct samsung_clock_reg_cache), | ||
351 | GFP_KERNEL); | ||
352 | if (!reg_cache) | ||
353 | panic("could not allocate register reg_cache.\n"); | ||
354 | reg_cache->rdump = samsung_clk_alloc_reg_dump(rdump, nr_rdump); | ||
355 | |||
356 | if (!reg_cache->rdump) | ||
357 | panic("could not allocate register dump storage.\n"); | ||
358 | |||
359 | if (list_empty(&clock_reg_cache_list)) | ||
360 | register_syscore_ops(&samsung_clk_syscore_ops); | ||
361 | |||
362 | reg_cache->reg_base = reg_base; | ||
363 | reg_cache->rd_num = nr_rdump; | ||
364 | list_add_tail(®_cache->node, &clock_reg_cache_list); | ||
365 | } | ||
366 | |||
367 | #else | ||
368 | static void samsung_clk_sleep_init(void __iomem *reg_base, | ||
369 | const unsigned long *rdump, | ||
370 | unsigned long nr_rdump) {} | ||
371 | #endif | ||
372 | |||
373 | /* | ||
374 | * Common function which registers plls, muxes, dividers and gates | ||
375 | * for each CMU. It also add CMU register list to register cache. | ||
376 | */ | ||
377 | void __init samsung_cmu_register_one(struct device_node *np, | ||
378 | struct samsung_cmu_info *cmu) | ||
379 | { | ||
380 | void __iomem *reg_base; | ||
381 | struct samsung_clk_provider *ctx; | ||
382 | |||
383 | reg_base = of_iomap(np, 0); | ||
384 | if (!reg_base) | ||
385 | panic("%s: failed to map registers\n", __func__); | ||
386 | |||
387 | ctx = samsung_clk_init(np, reg_base, cmu->nr_clk_ids); | ||
388 | if (!ctx) | ||
389 | panic("%s: unable to alllocate ctx\n", __func__); | ||
390 | |||
391 | if (cmu->pll_clks) | ||
392 | samsung_clk_register_pll(ctx, cmu->pll_clks, cmu->nr_pll_clks, | ||
393 | reg_base); | ||
394 | if (cmu->mux_clks) | ||
395 | samsung_clk_register_mux(ctx, cmu->mux_clks, | ||
396 | cmu->nr_mux_clks); | ||
397 | if (cmu->div_clks) | ||
398 | samsung_clk_register_div(ctx, cmu->div_clks, cmu->nr_div_clks); | ||
399 | if (cmu->gate_clks) | ||
400 | samsung_clk_register_gate(ctx, cmu->gate_clks, | ||
401 | cmu->nr_gate_clks); | ||
402 | if (cmu->fixed_clks) | ||
403 | samsung_clk_register_fixed_rate(ctx, cmu->fixed_clks, | ||
404 | cmu->nr_fixed_clks); | ||
405 | if (cmu->fixed_factor_clks) | ||
406 | samsung_clk_register_fixed_factor(ctx, cmu->fixed_factor_clks, | ||
407 | cmu->nr_fixed_factor_clks); | ||
408 | if (cmu->clk_regs) | ||
409 | samsung_clk_sleep_init(reg_base, cmu->clk_regs, | ||
410 | cmu->nr_clk_regs); | ||
411 | |||
412 | samsung_clk_of_add_provider(np, ctx); | ||
413 | } | ||
diff --git a/drivers/clk/samsung/clk.h b/drivers/clk/samsung/clk.h index 66ab36b5cef1..8acabe1f32c4 100644 --- a/drivers/clk/samsung/clk.h +++ b/drivers/clk/samsung/clk.h | |||
@@ -13,19 +13,15 @@ | |||
13 | #ifndef __SAMSUNG_CLK_H | 13 | #ifndef __SAMSUNG_CLK_H |
14 | #define __SAMSUNG_CLK_H | 14 | #define __SAMSUNG_CLK_H |
15 | 15 | ||
16 | #include <linux/clk.h> | ||
17 | #include <linux/clkdev.h> | 16 | #include <linux/clkdev.h> |
18 | #include <linux/io.h> | ||
19 | #include <linux/clk-provider.h> | 17 | #include <linux/clk-provider.h> |
20 | #include <linux/of.h> | ||
21 | #include <linux/of_address.h> | ||
22 | #include "clk-pll.h" | 18 | #include "clk-pll.h" |
23 | 19 | ||
24 | /** | 20 | /** |
25 | * struct samsung_clk_provider: information about clock provider | 21 | * struct samsung_clk_provider: information about clock provider |
26 | * @reg_base: virtual address for the register base. | 22 | * @reg_base: virtual address for the register base. |
27 | * @clk_data: holds clock related data like clk* and number of clocks. | 23 | * @clk_data: holds clock related data like clk* and number of clocks. |
28 | * @lock: maintains exclusion bwtween callbacks for a given clock-provider. | 24 | * @lock: maintains exclusion between callbacks for a given clock-provider. |
29 | */ | 25 | */ |
30 | struct samsung_clk_provider { | 26 | struct samsung_clk_provider { |
31 | void __iomem *reg_base; | 27 | void __iomem *reg_base; |
@@ -324,6 +320,40 @@ struct samsung_pll_clock { | |||
324 | __PLL(_typ, _id, NULL, _name, _pname, CLK_GET_RATE_NOCACHE, \ | 320 | __PLL(_typ, _id, NULL, _name, _pname, CLK_GET_RATE_NOCACHE, \ |
325 | _lock, _con, _rtable, _alias) | 321 | _lock, _con, _rtable, _alias) |
326 | 322 | ||
323 | struct samsung_clock_reg_cache { | ||
324 | struct list_head node; | ||
325 | void __iomem *reg_base; | ||
326 | struct samsung_clk_reg_dump *rdump; | ||
327 | unsigned int rd_num; | ||
328 | }; | ||
329 | |||
330 | struct samsung_cmu_info { | ||
331 | /* list of pll clocks and respective count */ | ||
332 | struct samsung_pll_clock *pll_clks; | ||
333 | unsigned int nr_pll_clks; | ||
334 | /* list of mux clocks and respective count */ | ||
335 | struct samsung_mux_clock *mux_clks; | ||
336 | unsigned int nr_mux_clks; | ||
337 | /* list of div clocks and respective count */ | ||
338 | struct samsung_div_clock *div_clks; | ||
339 | unsigned int nr_div_clks; | ||
340 | /* list of gate clocks and respective count */ | ||
341 | struct samsung_gate_clock *gate_clks; | ||
342 | unsigned int nr_gate_clks; | ||
343 | /* list of fixed clocks and respective count */ | ||
344 | struct samsung_fixed_rate_clock *fixed_clks; | ||
345 | unsigned int nr_fixed_clks; | ||
346 | /* list of fixed factor clocks and respective count */ | ||
347 | struct samsung_fixed_factor_clock *fixed_factor_clks; | ||
348 | unsigned int nr_fixed_factor_clks; | ||
349 | /* total number of clocks with IDs assigned*/ | ||
350 | unsigned int nr_clk_ids; | ||
351 | |||
352 | /* list and number of clocks registers */ | ||
353 | unsigned long *clk_regs; | ||
354 | unsigned int nr_clk_regs; | ||
355 | }; | ||
356 | |||
327 | extern struct samsung_clk_provider *__init samsung_clk_init( | 357 | extern struct samsung_clk_provider *__init samsung_clk_init( |
328 | struct device_node *np, void __iomem *base, | 358 | struct device_node *np, void __iomem *base, |
329 | unsigned long nr_clks); | 359 | unsigned long nr_clks); |
@@ -362,6 +392,9 @@ extern void __init samsung_clk_register_pll(struct samsung_clk_provider *ctx, | |||
362 | struct samsung_pll_clock *pll_list, | 392 | struct samsung_pll_clock *pll_list, |
363 | unsigned int nr_clk, void __iomem *base); | 393 | unsigned int nr_clk, void __iomem *base); |
364 | 394 | ||
395 | extern void __init samsung_cmu_register_one(struct device_node *, | ||
396 | struct samsung_cmu_info *); | ||
397 | |||
365 | extern unsigned long _get_rate(const char *clk_name); | 398 | extern unsigned long _get_rate(const char *clk_name); |
366 | 399 | ||
367 | extern void samsung_clk_save(void __iomem *base, | 400 | extern void samsung_clk_save(void __iomem *base, |
diff --git a/drivers/clk/shmobile/clk-div6.c b/drivers/clk/shmobile/clk-div6.c index f065f694cb65..639241e31e03 100644 --- a/drivers/clk/shmobile/clk-div6.c +++ b/drivers/clk/shmobile/clk-div6.c | |||
@@ -32,6 +32,9 @@ struct div6_clock { | |||
32 | struct clk_hw hw; | 32 | struct clk_hw hw; |
33 | void __iomem *reg; | 33 | void __iomem *reg; |
34 | unsigned int div; | 34 | unsigned int div; |
35 | u32 src_shift; | ||
36 | u32 src_width; | ||
37 | u8 *parents; | ||
35 | }; | 38 | }; |
36 | 39 | ||
37 | #define to_div6_clock(_hw) container_of(_hw, struct div6_clock, hw) | 40 | #define to_div6_clock(_hw) container_of(_hw, struct div6_clock, hw) |
@@ -39,8 +42,11 @@ struct div6_clock { | |||
39 | static int cpg_div6_clock_enable(struct clk_hw *hw) | 42 | static int cpg_div6_clock_enable(struct clk_hw *hw) |
40 | { | 43 | { |
41 | struct div6_clock *clock = to_div6_clock(hw); | 44 | struct div6_clock *clock = to_div6_clock(hw); |
45 | u32 val; | ||
42 | 46 | ||
43 | clk_writel(CPG_DIV6_DIV(clock->div - 1), clock->reg); | 47 | val = (clk_readl(clock->reg) & ~(CPG_DIV6_DIV_MASK | CPG_DIV6_CKSTP)) |
48 | | CPG_DIV6_DIV(clock->div - 1); | ||
49 | clk_writel(val, clock->reg); | ||
44 | 50 | ||
45 | return 0; | 51 | return 0; |
46 | } | 52 | } |
@@ -52,7 +58,7 @@ static void cpg_div6_clock_disable(struct clk_hw *hw) | |||
52 | /* DIV6 clocks require the divisor field to be non-zero when stopping | 58 | /* DIV6 clocks require the divisor field to be non-zero when stopping |
53 | * the clock. | 59 | * the clock. |
54 | */ | 60 | */ |
55 | clk_writel(CPG_DIV6_CKSTP | CPG_DIV6_DIV(CPG_DIV6_DIV_MASK), | 61 | clk_writel(clk_readl(clock->reg) | CPG_DIV6_CKSTP | CPG_DIV6_DIV_MASK, |
56 | clock->reg); | 62 | clock->reg); |
57 | } | 63 | } |
58 | 64 | ||
@@ -94,12 +100,53 @@ static int cpg_div6_clock_set_rate(struct clk_hw *hw, unsigned long rate, | |||
94 | { | 100 | { |
95 | struct div6_clock *clock = to_div6_clock(hw); | 101 | struct div6_clock *clock = to_div6_clock(hw); |
96 | unsigned int div = cpg_div6_clock_calc_div(rate, parent_rate); | 102 | unsigned int div = cpg_div6_clock_calc_div(rate, parent_rate); |
103 | u32 val; | ||
97 | 104 | ||
98 | clock->div = div; | 105 | clock->div = div; |
99 | 106 | ||
107 | val = clk_readl(clock->reg) & ~CPG_DIV6_DIV_MASK; | ||
100 | /* Only program the new divisor if the clock isn't stopped. */ | 108 | /* Only program the new divisor if the clock isn't stopped. */ |
101 | if (!(clk_readl(clock->reg) & CPG_DIV6_CKSTP)) | 109 | if (!(val & CPG_DIV6_CKSTP)) |
102 | clk_writel(CPG_DIV6_DIV(clock->div - 1), clock->reg); | 110 | clk_writel(val | CPG_DIV6_DIV(clock->div - 1), clock->reg); |
111 | |||
112 | return 0; | ||
113 | } | ||
114 | |||
115 | static u8 cpg_div6_clock_get_parent(struct clk_hw *hw) | ||
116 | { | ||
117 | struct div6_clock *clock = to_div6_clock(hw); | ||
118 | unsigned int i; | ||
119 | u8 hw_index; | ||
120 | |||
121 | if (clock->src_width == 0) | ||
122 | return 0; | ||
123 | |||
124 | hw_index = (clk_readl(clock->reg) >> clock->src_shift) & | ||
125 | (BIT(clock->src_width) - 1); | ||
126 | for (i = 0; i < __clk_get_num_parents(hw->clk); i++) { | ||
127 | if (clock->parents[i] == hw_index) | ||
128 | return i; | ||
129 | } | ||
130 | |||
131 | pr_err("%s: %s DIV6 clock set to invalid parent %u\n", | ||
132 | __func__, __clk_get_name(hw->clk), hw_index); | ||
133 | return 0; | ||
134 | } | ||
135 | |||
136 | static int cpg_div6_clock_set_parent(struct clk_hw *hw, u8 index) | ||
137 | { | ||
138 | struct div6_clock *clock = to_div6_clock(hw); | ||
139 | u8 hw_index; | ||
140 | u32 mask; | ||
141 | |||
142 | if (index >= __clk_get_num_parents(hw->clk)) | ||
143 | return -EINVAL; | ||
144 | |||
145 | mask = ~((BIT(clock->src_width) - 1) << clock->src_shift); | ||
146 | hw_index = clock->parents[index]; | ||
147 | |||
148 | clk_writel((clk_readl(clock->reg) & mask) | | ||
149 | (hw_index << clock->src_shift), clock->reg); | ||
103 | 150 | ||
104 | return 0; | 151 | return 0; |
105 | } | 152 | } |
@@ -108,6 +155,8 @@ static const struct clk_ops cpg_div6_clock_ops = { | |||
108 | .enable = cpg_div6_clock_enable, | 155 | .enable = cpg_div6_clock_enable, |
109 | .disable = cpg_div6_clock_disable, | 156 | .disable = cpg_div6_clock_disable, |
110 | .is_enabled = cpg_div6_clock_is_enabled, | 157 | .is_enabled = cpg_div6_clock_is_enabled, |
158 | .get_parent = cpg_div6_clock_get_parent, | ||
159 | .set_parent = cpg_div6_clock_set_parent, | ||
111 | .recalc_rate = cpg_div6_clock_recalc_rate, | 160 | .recalc_rate = cpg_div6_clock_recalc_rate, |
112 | .round_rate = cpg_div6_clock_round_rate, | 161 | .round_rate = cpg_div6_clock_round_rate, |
113 | .set_rate = cpg_div6_clock_set_rate, | 162 | .set_rate = cpg_div6_clock_set_rate, |
@@ -115,20 +164,33 @@ static const struct clk_ops cpg_div6_clock_ops = { | |||
115 | 164 | ||
116 | static void __init cpg_div6_clock_init(struct device_node *np) | 165 | static void __init cpg_div6_clock_init(struct device_node *np) |
117 | { | 166 | { |
167 | unsigned int num_parents, valid_parents; | ||
168 | const char **parent_names; | ||
118 | struct clk_init_data init; | 169 | struct clk_init_data init; |
119 | struct div6_clock *clock; | 170 | struct div6_clock *clock; |
120 | const char *parent_name; | ||
121 | const char *name; | 171 | const char *name; |
122 | struct clk *clk; | 172 | struct clk *clk; |
173 | unsigned int i; | ||
123 | int ret; | 174 | int ret; |
124 | 175 | ||
125 | clock = kzalloc(sizeof(*clock), GFP_KERNEL); | 176 | clock = kzalloc(sizeof(*clock), GFP_KERNEL); |
126 | if (!clock) { | 177 | if (!clock) |
127 | pr_err("%s: failed to allocate %s DIV6 clock\n", | 178 | return; |
179 | |||
180 | num_parents = of_clk_get_parent_count(np); | ||
181 | if (num_parents < 1) { | ||
182 | pr_err("%s: no parent found for %s DIV6 clock\n", | ||
128 | __func__, np->name); | 183 | __func__, np->name); |
129 | return; | 184 | return; |
130 | } | 185 | } |
131 | 186 | ||
187 | clock->parents = kmalloc_array(num_parents, sizeof(*clock->parents), | ||
188 | GFP_KERNEL); | ||
189 | parent_names = kmalloc_array(num_parents, sizeof(*parent_names), | ||
190 | GFP_KERNEL); | ||
191 | if (!parent_names) | ||
192 | return; | ||
193 | |||
132 | /* Remap the clock register and read the divisor. Disabling the | 194 | /* Remap the clock register and read the divisor. Disabling the |
133 | * clock overwrites the divisor, so we need to cache its value for the | 195 | * clock overwrites the divisor, so we need to cache its value for the |
134 | * enable operation. | 196 | * enable operation. |
@@ -150,9 +212,34 @@ static void __init cpg_div6_clock_init(struct device_node *np) | |||
150 | goto error; | 212 | goto error; |
151 | } | 213 | } |
152 | 214 | ||
153 | parent_name = of_clk_get_parent_name(np, 0); | 215 | |
154 | if (parent_name == NULL) { | 216 | for (i = 0, valid_parents = 0; i < num_parents; i++) { |
155 | pr_err("%s: failed to get %s DIV6 clock parent name\n", | 217 | const char *name = of_clk_get_parent_name(np, i); |
218 | |||
219 | if (name) { | ||
220 | parent_names[valid_parents] = name; | ||
221 | clock->parents[valid_parents] = i; | ||
222 | valid_parents++; | ||
223 | } | ||
224 | } | ||
225 | |||
226 | switch (num_parents) { | ||
227 | case 1: | ||
228 | /* fixed parent clock */ | ||
229 | clock->src_shift = clock->src_width = 0; | ||
230 | break; | ||
231 | case 4: | ||
232 | /* clock with EXSRC bits 6-7 */ | ||
233 | clock->src_shift = 6; | ||
234 | clock->src_width = 2; | ||
235 | break; | ||
236 | case 8: | ||
237 | /* VCLK with EXSRC bits 12-14 */ | ||
238 | clock->src_shift = 12; | ||
239 | clock->src_width = 3; | ||
240 | break; | ||
241 | default: | ||
242 | pr_err("%s: invalid number of parents for DIV6 clock %s\n", | ||
156 | __func__, np->name); | 243 | __func__, np->name); |
157 | goto error; | 244 | goto error; |
158 | } | 245 | } |
@@ -161,8 +248,8 @@ static void __init cpg_div6_clock_init(struct device_node *np) | |||
161 | init.name = name; | 248 | init.name = name; |
162 | init.ops = &cpg_div6_clock_ops; | 249 | init.ops = &cpg_div6_clock_ops; |
163 | init.flags = CLK_IS_BASIC; | 250 | init.flags = CLK_IS_BASIC; |
164 | init.parent_names = &parent_name; | 251 | init.parent_names = parent_names; |
165 | init.num_parents = 1; | 252 | init.num_parents = valid_parents; |
166 | 253 | ||
167 | clock->hw.init = &init; | 254 | clock->hw.init = &init; |
168 | 255 | ||
@@ -175,11 +262,13 @@ static void __init cpg_div6_clock_init(struct device_node *np) | |||
175 | 262 | ||
176 | of_clk_add_provider(np, of_clk_src_simple_get, clk); | 263 | of_clk_add_provider(np, of_clk_src_simple_get, clk); |
177 | 264 | ||
265 | kfree(parent_names); | ||
178 | return; | 266 | return; |
179 | 267 | ||
180 | error: | 268 | error: |
181 | if (clock->reg) | 269 | if (clock->reg) |
182 | iounmap(clock->reg); | 270 | iounmap(clock->reg); |
271 | kfree(parent_names); | ||
183 | kfree(clock); | 272 | kfree(clock); |
184 | } | 273 | } |
185 | CLK_OF_DECLARE(cpg_div6_clk, "renesas,cpg-div6-clock", cpg_div6_clock_init); | 274 | CLK_OF_DECLARE(cpg_div6_clk, "renesas,cpg-div6-clock", cpg_div6_clock_init); |
diff --git a/drivers/clk/sunxi/Makefile b/drivers/clk/sunxi/Makefile index 7ddc2b553846..a66953c0f430 100644 --- a/drivers/clk/sunxi/Makefile +++ b/drivers/clk/sunxi/Makefile | |||
@@ -7,6 +7,7 @@ obj-y += clk-a10-hosc.o | |||
7 | obj-y += clk-a20-gmac.o | 7 | obj-y += clk-a20-gmac.o |
8 | obj-y += clk-mod0.o | 8 | obj-y += clk-mod0.o |
9 | obj-y += clk-sun8i-mbus.o | 9 | obj-y += clk-sun8i-mbus.o |
10 | obj-y += clk-sun9i-core.o | ||
10 | 11 | ||
11 | obj-$(CONFIG_MFD_SUN6I_PRCM) += \ | 12 | obj-$(CONFIG_MFD_SUN6I_PRCM) += \ |
12 | clk-sun6i-ar100.o clk-sun6i-apb0.o clk-sun6i-apb0-gates.o \ | 13 | clk-sun6i-ar100.o clk-sun6i-apb0.o clk-sun6i-apb0-gates.o \ |
diff --git a/drivers/clk/sunxi/clk-a20-gmac.c b/drivers/clk/sunxi/clk-a20-gmac.c index 5296fd6dd7b3..0dcf4f205fb8 100644 --- a/drivers/clk/sunxi/clk-a20-gmac.c +++ b/drivers/clk/sunxi/clk-a20-gmac.c | |||
@@ -53,6 +53,11 @@ static DEFINE_SPINLOCK(gmac_lock); | |||
53 | #define SUN7I_A20_GMAC_MASK 0x3 | 53 | #define SUN7I_A20_GMAC_MASK 0x3 |
54 | #define SUN7I_A20_GMAC_PARENTS 2 | 54 | #define SUN7I_A20_GMAC_PARENTS 2 |
55 | 55 | ||
56 | static u32 sun7i_a20_gmac_mux_table[SUN7I_A20_GMAC_PARENTS] = { | ||
57 | 0x00, /* Select mii_phy_tx_clk */ | ||
58 | 0x02, /* Select gmac_int_tx_clk */ | ||
59 | }; | ||
60 | |||
56 | static void __init sun7i_a20_gmac_clk_setup(struct device_node *node) | 61 | static void __init sun7i_a20_gmac_clk_setup(struct device_node *node) |
57 | { | 62 | { |
58 | struct clk *clk; | 63 | struct clk *clk; |
@@ -90,7 +95,7 @@ static void __init sun7i_a20_gmac_clk_setup(struct device_node *node) | |||
90 | gate->lock = &gmac_lock; | 95 | gate->lock = &gmac_lock; |
91 | mux->reg = reg; | 96 | mux->reg = reg; |
92 | mux->mask = SUN7I_A20_GMAC_MASK; | 97 | mux->mask = SUN7I_A20_GMAC_MASK; |
93 | mux->flags = CLK_MUX_INDEX_BIT; | 98 | mux->table = sun7i_a20_gmac_mux_table; |
94 | mux->lock = &gmac_lock; | 99 | mux->lock = &gmac_lock; |
95 | 100 | ||
96 | clk = clk_register_composite(NULL, clk_name, | 101 | clk = clk_register_composite(NULL, clk_name, |
diff --git a/drivers/clk/sunxi/clk-factors.c b/drivers/clk/sunxi/clk-factors.c index f83ba097126c..62e08fb58554 100644 --- a/drivers/clk/sunxi/clk-factors.c +++ b/drivers/clk/sunxi/clk-factors.c | |||
@@ -81,7 +81,7 @@ static long clk_factors_round_rate(struct clk_hw *hw, unsigned long rate, | |||
81 | 81 | ||
82 | static long clk_factors_determine_rate(struct clk_hw *hw, unsigned long rate, | 82 | static long clk_factors_determine_rate(struct clk_hw *hw, unsigned long rate, |
83 | unsigned long *best_parent_rate, | 83 | unsigned long *best_parent_rate, |
84 | struct clk **best_parent_p) | 84 | struct clk_hw **best_parent_p) |
85 | { | 85 | { |
86 | struct clk *clk = hw->clk, *parent, *best_parent = NULL; | 86 | struct clk *clk = hw->clk, *parent, *best_parent = NULL; |
87 | int i, num_parents; | 87 | int i, num_parents; |
@@ -108,7 +108,7 @@ static long clk_factors_determine_rate(struct clk_hw *hw, unsigned long rate, | |||
108 | } | 108 | } |
109 | 109 | ||
110 | if (best_parent) | 110 | if (best_parent) |
111 | *best_parent_p = best_parent; | 111 | *best_parent_p = __clk_get_hw(best_parent); |
112 | *best_parent_rate = best; | 112 | *best_parent_rate = best; |
113 | 113 | ||
114 | return best_child_rate; | 114 | return best_child_rate; |
@@ -224,7 +224,7 @@ struct clk * __init sunxi_factors_register(struct device_node *node, | |||
224 | /* set up gate properties */ | 224 | /* set up gate properties */ |
225 | mux->reg = reg; | 225 | mux->reg = reg; |
226 | mux->shift = data->mux; | 226 | mux->shift = data->mux; |
227 | mux->mask = SUNXI_FACTORS_MUX_MASK; | 227 | mux->mask = data->muxmask; |
228 | mux->lock = factors->lock; | 228 | mux->lock = factors->lock; |
229 | mux_hw = &mux->hw; | 229 | mux_hw = &mux->hw; |
230 | } | 230 | } |
diff --git a/drivers/clk/sunxi/clk-factors.h b/drivers/clk/sunxi/clk-factors.h index 9913840018d3..912238fde132 100644 --- a/drivers/clk/sunxi/clk-factors.h +++ b/drivers/clk/sunxi/clk-factors.h | |||
@@ -7,8 +7,6 @@ | |||
7 | 7 | ||
8 | #define SUNXI_FACTORS_NOT_APPLICABLE (0) | 8 | #define SUNXI_FACTORS_NOT_APPLICABLE (0) |
9 | 9 | ||
10 | #define SUNXI_FACTORS_MUX_MASK 0x3 | ||
11 | |||
12 | struct clk_factors_config { | 10 | struct clk_factors_config { |
13 | u8 nshift; | 11 | u8 nshift; |
14 | u8 nwidth; | 12 | u8 nwidth; |
@@ -24,6 +22,7 @@ struct clk_factors_config { | |||
24 | struct factors_data { | 22 | struct factors_data { |
25 | int enable; | 23 | int enable; |
26 | int mux; | 24 | int mux; |
25 | int muxmask; | ||
27 | struct clk_factors_config *table; | 26 | struct clk_factors_config *table; |
28 | void (*getter) (u32 *rate, u32 parent_rate, u8 *n, u8 *k, u8 *m, u8 *p); | 27 | void (*getter) (u32 *rate, u32 parent_rate, u8 *n, u8 *k, u8 *m, u8 *p); |
29 | const char *name; | 28 | const char *name; |
diff --git a/drivers/clk/sunxi/clk-mod0.c b/drivers/clk/sunxi/clk-mod0.c index 4a563850ee6e..da0524eaee94 100644 --- a/drivers/clk/sunxi/clk-mod0.c +++ b/drivers/clk/sunxi/clk-mod0.c | |||
@@ -70,6 +70,7 @@ static struct clk_factors_config sun4i_a10_mod0_config = { | |||
70 | static const struct factors_data sun4i_a10_mod0_data __initconst = { | 70 | static const struct factors_data sun4i_a10_mod0_data __initconst = { |
71 | .enable = 31, | 71 | .enable = 31, |
72 | .mux = 24, | 72 | .mux = 24, |
73 | .muxmask = BIT(1) | BIT(0), | ||
73 | .table = &sun4i_a10_mod0_config, | 74 | .table = &sun4i_a10_mod0_config, |
74 | .getter = sun4i_a10_get_mod0_factors, | 75 | .getter = sun4i_a10_get_mod0_factors, |
75 | }; | 76 | }; |
diff --git a/drivers/clk/sunxi/clk-sun6i-ar100.c b/drivers/clk/sunxi/clk-sun6i-ar100.c index acca53290be2..3d282fb8f85c 100644 --- a/drivers/clk/sunxi/clk-sun6i-ar100.c +++ b/drivers/clk/sunxi/clk-sun6i-ar100.c | |||
@@ -46,7 +46,7 @@ static unsigned long ar100_recalc_rate(struct clk_hw *hw, | |||
46 | 46 | ||
47 | static long ar100_determine_rate(struct clk_hw *hw, unsigned long rate, | 47 | static long ar100_determine_rate(struct clk_hw *hw, unsigned long rate, |
48 | unsigned long *best_parent_rate, | 48 | unsigned long *best_parent_rate, |
49 | struct clk **best_parent_clk) | 49 | struct clk_hw **best_parent_clk) |
50 | { | 50 | { |
51 | int nparents = __clk_get_num_parents(hw->clk); | 51 | int nparents = __clk_get_num_parents(hw->clk); |
52 | long best_rate = -EINVAL; | 52 | long best_rate = -EINVAL; |
@@ -100,7 +100,7 @@ static long ar100_determine_rate(struct clk_hw *hw, unsigned long rate, | |||
100 | 100 | ||
101 | tmp_rate = (parent_rate >> shift) / div; | 101 | tmp_rate = (parent_rate >> shift) / div; |
102 | if (!*best_parent_clk || tmp_rate > best_rate) { | 102 | if (!*best_parent_clk || tmp_rate > best_rate) { |
103 | *best_parent_clk = parent; | 103 | *best_parent_clk = __clk_get_hw(parent); |
104 | *best_parent_rate = parent_rate; | 104 | *best_parent_rate = parent_rate; |
105 | best_rate = tmp_rate; | 105 | best_rate = tmp_rate; |
106 | } | 106 | } |
diff --git a/drivers/clk/sunxi/clk-sun8i-mbus.c b/drivers/clk/sunxi/clk-sun8i-mbus.c index 8e49b44cee41..ef49786eefd3 100644 --- a/drivers/clk/sunxi/clk-sun8i-mbus.c +++ b/drivers/clk/sunxi/clk-sun8i-mbus.c | |||
@@ -60,6 +60,7 @@ static struct clk_factors_config sun8i_a23_mbus_config = { | |||
60 | static const struct factors_data sun8i_a23_mbus_data __initconst = { | 60 | static const struct factors_data sun8i_a23_mbus_data __initconst = { |
61 | .enable = 31, | 61 | .enable = 31, |
62 | .mux = 24, | 62 | .mux = 24, |
63 | .muxmask = BIT(1) | BIT(0), | ||
63 | .table = &sun8i_a23_mbus_config, | 64 | .table = &sun8i_a23_mbus_config, |
64 | .getter = sun8i_a23_get_mbus_factors, | 65 | .getter = sun8i_a23_get_mbus_factors, |
65 | }; | 66 | }; |
diff --git a/drivers/clk/sunxi/clk-sun9i-core.c b/drivers/clk/sunxi/clk-sun9i-core.c new file mode 100644 index 000000000000..3cb9036d91bb --- /dev/null +++ b/drivers/clk/sunxi/clk-sun9i-core.c | |||
@@ -0,0 +1,271 @@ | |||
1 | /* | ||
2 | * Copyright 2014 Chen-Yu Tsai | ||
3 | * | ||
4 | * Chen-Yu Tsai <wens@csie.org> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | */ | ||
16 | |||
17 | #include <linux/clk-provider.h> | ||
18 | #include <linux/clkdev.h> | ||
19 | #include <linux/of.h> | ||
20 | #include <linux/of_address.h> | ||
21 | #include <linux/log2.h> | ||
22 | |||
23 | #include "clk-factors.h" | ||
24 | |||
25 | |||
26 | /** | ||
27 | * sun9i_a80_get_pll4_factors() - calculates n, p, m factors for PLL1 | ||
28 | * PLL4 rate is calculated as follows | ||
29 | * rate = (parent_rate * n >> p) / (m + 1); | ||
30 | * parent_rate is always 24Mhz | ||
31 | * | ||
32 | * p and m are named div1 and div2 in Allwinner's SDK | ||
33 | */ | ||
34 | |||
35 | static void sun9i_a80_get_pll4_factors(u32 *freq, u32 parent_rate, | ||
36 | u8 *n, u8 *k, u8 *m, u8 *p) | ||
37 | { | ||
38 | int div; | ||
39 | |||
40 | /* Normalize value to a 6M multiple */ | ||
41 | div = DIV_ROUND_UP(*freq, 6000000); | ||
42 | |||
43 | /* divs above 256 cannot be odd */ | ||
44 | if (div > 256) | ||
45 | div = round_up(div, 2); | ||
46 | |||
47 | /* divs above 512 must be a multiple of 4 */ | ||
48 | if (div > 512) | ||
49 | div = round_up(div, 4); | ||
50 | |||
51 | *freq = 6000000 * div; | ||
52 | |||
53 | /* we were called to round the frequency, we can now return */ | ||
54 | if (n == NULL) | ||
55 | return; | ||
56 | |||
57 | /* p will be 1 for divs under 512 */ | ||
58 | if (div < 512) | ||
59 | *p = 1; | ||
60 | else | ||
61 | *p = 0; | ||
62 | |||
63 | /* m will be 1 if div is odd */ | ||
64 | if (div & 1) | ||
65 | *m = 1; | ||
66 | else | ||
67 | *m = 0; | ||
68 | |||
69 | /* calculate a suitable n based on m and p */ | ||
70 | *n = div / (*p + 1) / (*m + 1); | ||
71 | } | ||
72 | |||
73 | static struct clk_factors_config sun9i_a80_pll4_config = { | ||
74 | .mshift = 18, | ||
75 | .mwidth = 1, | ||
76 | .nshift = 8, | ||
77 | .nwidth = 8, | ||
78 | .pshift = 16, | ||
79 | .pwidth = 1, | ||
80 | }; | ||
81 | |||
82 | static const struct factors_data sun9i_a80_pll4_data __initconst = { | ||
83 | .enable = 31, | ||
84 | .table = &sun9i_a80_pll4_config, | ||
85 | .getter = sun9i_a80_get_pll4_factors, | ||
86 | }; | ||
87 | |||
88 | static DEFINE_SPINLOCK(sun9i_a80_pll4_lock); | ||
89 | |||
90 | static void __init sun9i_a80_pll4_setup(struct device_node *node) | ||
91 | { | ||
92 | sunxi_factors_register(node, &sun9i_a80_pll4_data, &sun9i_a80_pll4_lock); | ||
93 | } | ||
94 | CLK_OF_DECLARE(sun9i_a80_pll4, "allwinner,sun9i-a80-pll4-clk", sun9i_a80_pll4_setup); | ||
95 | |||
96 | |||
97 | /** | ||
98 | * sun9i_a80_get_gt_factors() - calculates m factor for GT | ||
99 | * GT rate is calculated as follows | ||
100 | * rate = parent_rate / (m + 1); | ||
101 | */ | ||
102 | |||
103 | static void sun9i_a80_get_gt_factors(u32 *freq, u32 parent_rate, | ||
104 | u8 *n, u8 *k, u8 *m, u8 *p) | ||
105 | { | ||
106 | u32 div; | ||
107 | |||
108 | if (parent_rate < *freq) | ||
109 | *freq = parent_rate; | ||
110 | |||
111 | div = DIV_ROUND_UP(parent_rate, *freq); | ||
112 | |||
113 | /* maximum divider is 4 */ | ||
114 | if (div > 4) | ||
115 | div = 4; | ||
116 | |||
117 | *freq = parent_rate / div; | ||
118 | |||
119 | /* we were called to round the frequency, we can now return */ | ||
120 | if (!m) | ||
121 | return; | ||
122 | |||
123 | *m = div; | ||
124 | } | ||
125 | |||
126 | static struct clk_factors_config sun9i_a80_gt_config = { | ||
127 | .mshift = 0, | ||
128 | .mwidth = 2, | ||
129 | }; | ||
130 | |||
131 | static const struct factors_data sun9i_a80_gt_data __initconst = { | ||
132 | .mux = 24, | ||
133 | .muxmask = BIT(1) | BIT(0), | ||
134 | .table = &sun9i_a80_gt_config, | ||
135 | .getter = sun9i_a80_get_gt_factors, | ||
136 | }; | ||
137 | |||
138 | static DEFINE_SPINLOCK(sun9i_a80_gt_lock); | ||
139 | |||
140 | static void __init sun9i_a80_gt_setup(struct device_node *node) | ||
141 | { | ||
142 | struct clk *gt = sunxi_factors_register(node, &sun9i_a80_gt_data, | ||
143 | &sun9i_a80_gt_lock); | ||
144 | |||
145 | /* The GT bus clock needs to be always enabled */ | ||
146 | __clk_get(gt); | ||
147 | clk_prepare_enable(gt); | ||
148 | } | ||
149 | CLK_OF_DECLARE(sun9i_a80_gt, "allwinner,sun9i-a80-gt-clk", sun9i_a80_gt_setup); | ||
150 | |||
151 | |||
152 | /** | ||
153 | * sun9i_a80_get_ahb_factors() - calculates p factor for AHB0/1/2 | ||
154 | * AHB rate is calculated as follows | ||
155 | * rate = parent_rate >> p; | ||
156 | */ | ||
157 | |||
158 | static void sun9i_a80_get_ahb_factors(u32 *freq, u32 parent_rate, | ||
159 | u8 *n, u8 *k, u8 *m, u8 *p) | ||
160 | { | ||
161 | u32 _p; | ||
162 | |||
163 | if (parent_rate < *freq) | ||
164 | *freq = parent_rate; | ||
165 | |||
166 | _p = order_base_2(DIV_ROUND_UP(parent_rate, *freq)); | ||
167 | |||
168 | /* maximum p is 3 */ | ||
169 | if (_p > 3) | ||
170 | _p = 3; | ||
171 | |||
172 | *freq = parent_rate >> _p; | ||
173 | |||
174 | /* we were called to round the frequency, we can now return */ | ||
175 | if (!p) | ||
176 | return; | ||
177 | |||
178 | *p = _p; | ||
179 | } | ||
180 | |||
181 | static struct clk_factors_config sun9i_a80_ahb_config = { | ||
182 | .pshift = 0, | ||
183 | .pwidth = 2, | ||
184 | }; | ||
185 | |||
186 | static const struct factors_data sun9i_a80_ahb_data __initconst = { | ||
187 | .mux = 24, | ||
188 | .muxmask = BIT(1) | BIT(0), | ||
189 | .table = &sun9i_a80_ahb_config, | ||
190 | .getter = sun9i_a80_get_ahb_factors, | ||
191 | }; | ||
192 | |||
193 | static DEFINE_SPINLOCK(sun9i_a80_ahb_lock); | ||
194 | |||
195 | static void __init sun9i_a80_ahb_setup(struct device_node *node) | ||
196 | { | ||
197 | sunxi_factors_register(node, &sun9i_a80_ahb_data, &sun9i_a80_ahb_lock); | ||
198 | } | ||
199 | CLK_OF_DECLARE(sun9i_a80_ahb, "allwinner,sun9i-a80-ahb-clk", sun9i_a80_ahb_setup); | ||
200 | |||
201 | |||
202 | static const struct factors_data sun9i_a80_apb0_data __initconst = { | ||
203 | .mux = 24, | ||
204 | .muxmask = BIT(0), | ||
205 | .table = &sun9i_a80_ahb_config, | ||
206 | .getter = sun9i_a80_get_ahb_factors, | ||
207 | }; | ||
208 | |||
209 | static DEFINE_SPINLOCK(sun9i_a80_apb0_lock); | ||
210 | |||
211 | static void __init sun9i_a80_apb0_setup(struct device_node *node) | ||
212 | { | ||
213 | sunxi_factors_register(node, &sun9i_a80_apb0_data, &sun9i_a80_apb0_lock); | ||
214 | } | ||
215 | CLK_OF_DECLARE(sun9i_a80_apb0, "allwinner,sun9i-a80-apb0-clk", sun9i_a80_apb0_setup); | ||
216 | |||
217 | |||
218 | /** | ||
219 | * sun9i_a80_get_apb1_factors() - calculates m, p factors for APB1 | ||
220 | * APB1 rate is calculated as follows | ||
221 | * rate = (parent_rate >> p) / (m + 1); | ||
222 | */ | ||
223 | |||
224 | static void sun9i_a80_get_apb1_factors(u32 *freq, u32 parent_rate, | ||
225 | u8 *n, u8 *k, u8 *m, u8 *p) | ||
226 | { | ||
227 | u32 div; | ||
228 | u8 calcm, calcp; | ||
229 | |||
230 | if (parent_rate < *freq) | ||
231 | *freq = parent_rate; | ||
232 | |||
233 | div = DIV_ROUND_UP(parent_rate, *freq); | ||
234 | |||
235 | /* Highest possible divider is 256 (p = 3, m = 31) */ | ||
236 | if (div > 256) | ||
237 | div = 256; | ||
238 | |||
239 | calcp = order_base_2(div); | ||
240 | calcm = (parent_rate >> calcp) - 1; | ||
241 | *freq = (parent_rate >> calcp) / (calcm + 1); | ||
242 | |||
243 | /* we were called to round the frequency, we can now return */ | ||
244 | if (n == NULL) | ||
245 | return; | ||
246 | |||
247 | *m = calcm; | ||
248 | *p = calcp; | ||
249 | } | ||
250 | |||
251 | static struct clk_factors_config sun9i_a80_apb1_config = { | ||
252 | .mshift = 0, | ||
253 | .mwidth = 5, | ||
254 | .pshift = 16, | ||
255 | .pwidth = 2, | ||
256 | }; | ||
257 | |||
258 | static const struct factors_data sun9i_a80_apb1_data __initconst = { | ||
259 | .mux = 24, | ||
260 | .muxmask = BIT(0), | ||
261 | .table = &sun9i_a80_apb1_config, | ||
262 | .getter = sun9i_a80_get_apb1_factors, | ||
263 | }; | ||
264 | |||
265 | static DEFINE_SPINLOCK(sun9i_a80_apb1_lock); | ||
266 | |||
267 | static void __init sun9i_a80_apb1_setup(struct device_node *node) | ||
268 | { | ||
269 | sunxi_factors_register(node, &sun9i_a80_apb1_data, &sun9i_a80_apb1_lock); | ||
270 | } | ||
271 | CLK_OF_DECLARE(sun9i_a80_apb1, "allwinner,sun9i-a80-apb1-clk", sun9i_a80_apb1_setup); | ||
diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c index d5dc951264ca..570202582dcf 100644 --- a/drivers/clk/sunxi/clk-sunxi.c +++ b/drivers/clk/sunxi/clk-sunxi.c | |||
@@ -245,9 +245,9 @@ static void sun4i_get_pll5_factors(u32 *freq, u32 parent_rate, | |||
245 | } | 245 | } |
246 | 246 | ||
247 | /** | 247 | /** |
248 | * sun6i_a31_get_pll6_factors() - calculates n, k factors for A31 PLL6 | 248 | * sun6i_a31_get_pll6_factors() - calculates n, k factors for A31 PLL6x2 |
249 | * PLL6 rate is calculated as follows | 249 | * PLL6x2 rate is calculated as follows |
250 | * rate = parent_rate * n * (k + 1) / 2 | 250 | * rate = parent_rate * (n + 1) * (k + 1) |
251 | * parent_rate is always 24Mhz | 251 | * parent_rate is always 24Mhz |
252 | */ | 252 | */ |
253 | 253 | ||
@@ -256,13 +256,7 @@ static void sun6i_a31_get_pll6_factors(u32 *freq, u32 parent_rate, | |||
256 | { | 256 | { |
257 | u8 div; | 257 | u8 div; |
258 | 258 | ||
259 | /* | 259 | /* Normalize value to a parent_rate multiple (24M) */ |
260 | * We always have 24MHz / 2, so we can just say that our | ||
261 | * parent clock is 12MHz. | ||
262 | */ | ||
263 | parent_rate = parent_rate / 2; | ||
264 | |||
265 | /* Normalize value to a parent_rate multiple (24M / 2) */ | ||
266 | div = *freq / parent_rate; | 260 | div = *freq / parent_rate; |
267 | *freq = parent_rate * div; | 261 | *freq = parent_rate * div; |
268 | 262 | ||
@@ -274,7 +268,7 @@ static void sun6i_a31_get_pll6_factors(u32 *freq, u32 parent_rate, | |||
274 | if (*k > 3) | 268 | if (*k > 3) |
275 | *k = 3; | 269 | *k = 3; |
276 | 270 | ||
277 | *n = DIV_ROUND_UP(div, (*k+1)); | 271 | *n = DIV_ROUND_UP(div, (*k+1)) - 1; |
278 | } | 272 | } |
279 | 273 | ||
280 | /** | 274 | /** |
@@ -445,6 +439,7 @@ static struct clk_factors_config sun6i_a31_pll6_config = { | |||
445 | .nwidth = 5, | 439 | .nwidth = 5, |
446 | .kshift = 4, | 440 | .kshift = 4, |
447 | .kwidth = 2, | 441 | .kwidth = 2, |
442 | .n_start = 1, | ||
448 | }; | 443 | }; |
449 | 444 | ||
450 | static struct clk_factors_config sun4i_apb1_config = { | 445 | static struct clk_factors_config sun4i_apb1_config = { |
@@ -504,9 +499,12 @@ static const struct factors_data sun6i_a31_pll6_data __initconst = { | |||
504 | .enable = 31, | 499 | .enable = 31, |
505 | .table = &sun6i_a31_pll6_config, | 500 | .table = &sun6i_a31_pll6_config, |
506 | .getter = sun6i_a31_get_pll6_factors, | 501 | .getter = sun6i_a31_get_pll6_factors, |
502 | .name = "pll6x2", | ||
507 | }; | 503 | }; |
508 | 504 | ||
509 | static const struct factors_data sun4i_apb1_data __initconst = { | 505 | static const struct factors_data sun4i_apb1_data __initconst = { |
506 | .mux = 24, | ||
507 | .muxmask = BIT(1) | BIT(0), | ||
510 | .table = &sun4i_apb1_config, | 508 | .table = &sun4i_apb1_config, |
511 | .getter = sun4i_get_apb1_factors, | 509 | .getter = sun4i_get_apb1_factors, |
512 | }; | 510 | }; |
@@ -514,6 +512,7 @@ static const struct factors_data sun4i_apb1_data __initconst = { | |||
514 | static const struct factors_data sun7i_a20_out_data __initconst = { | 512 | static const struct factors_data sun7i_a20_out_data __initconst = { |
515 | .enable = 31, | 513 | .enable = 31, |
516 | .mux = 24, | 514 | .mux = 24, |
515 | .muxmask = BIT(1) | BIT(0), | ||
517 | .table = &sun7i_a20_out_config, | 516 | .table = &sun7i_a20_out_config, |
518 | .getter = sun7i_a20_get_out_factors, | 517 | .getter = sun7i_a20_get_out_factors, |
519 | }; | 518 | }; |
@@ -544,10 +543,6 @@ static const struct mux_data sun6i_a31_ahb1_mux_data __initconst = { | |||
544 | .shift = 12, | 543 | .shift = 12, |
545 | }; | 544 | }; |
546 | 545 | ||
547 | static const struct mux_data sun4i_apb1_mux_data __initconst = { | ||
548 | .shift = 24, | ||
549 | }; | ||
550 | |||
551 | static void __init sunxi_mux_clk_setup(struct device_node *node, | 546 | static void __init sunxi_mux_clk_setup(struct device_node *node, |
552 | struct mux_data *data) | 547 | struct mux_data *data) |
553 | { | 548 | { |
@@ -633,12 +628,6 @@ static const struct div_data sun4i_apb0_data __initconst = { | |||
633 | .table = sun4i_apb0_table, | 628 | .table = sun4i_apb0_table, |
634 | }; | 629 | }; |
635 | 630 | ||
636 | static const struct div_data sun6i_a31_apb2_div_data __initconst = { | ||
637 | .shift = 0, | ||
638 | .pow = 0, | ||
639 | .width = 4, | ||
640 | }; | ||
641 | |||
642 | static void __init sunxi_divider_clk_setup(struct device_node *node, | 631 | static void __init sunxi_divider_clk_setup(struct device_node *node, |
643 | struct div_data *data) | 632 | struct div_data *data) |
644 | { | 633 | { |
@@ -757,6 +746,18 @@ static const struct gates_data sun8i_a23_ahb1_gates_data __initconst = { | |||
757 | .mask = {0x25386742, 0x2505111}, | 746 | .mask = {0x25386742, 0x2505111}, |
758 | }; | 747 | }; |
759 | 748 | ||
749 | static const struct gates_data sun9i_a80_ahb0_gates_data __initconst = { | ||
750 | .mask = {0xF5F12B}, | ||
751 | }; | ||
752 | |||
753 | static const struct gates_data sun9i_a80_ahb1_gates_data __initconst = { | ||
754 | .mask = {0x1E20003}, | ||
755 | }; | ||
756 | |||
757 | static const struct gates_data sun9i_a80_ahb2_gates_data __initconst = { | ||
758 | .mask = {0x9B7}, | ||
759 | }; | ||
760 | |||
760 | static const struct gates_data sun4i_apb0_gates_data __initconst = { | 761 | static const struct gates_data sun4i_apb0_gates_data __initconst = { |
761 | .mask = {0x4EF}, | 762 | .mask = {0x4EF}, |
762 | }; | 763 | }; |
@@ -773,6 +774,10 @@ static const struct gates_data sun7i_a20_apb0_gates_data __initconst = { | |||
773 | .mask = { 0x4ff }, | 774 | .mask = { 0x4ff }, |
774 | }; | 775 | }; |
775 | 776 | ||
777 | static const struct gates_data sun9i_a80_apb0_gates_data __initconst = { | ||
778 | .mask = {0xEB822}, | ||
779 | }; | ||
780 | |||
776 | static const struct gates_data sun4i_apb1_gates_data __initconst = { | 781 | static const struct gates_data sun4i_apb1_gates_data __initconst = { |
777 | .mask = {0xFF00F7}, | 782 | .mask = {0xFF00F7}, |
778 | }; | 783 | }; |
@@ -801,6 +806,10 @@ static const struct gates_data sun7i_a20_apb1_gates_data __initconst = { | |||
801 | .mask = { 0xff80ff }, | 806 | .mask = { 0xff80ff }, |
802 | }; | 807 | }; |
803 | 808 | ||
809 | static const struct gates_data sun9i_a80_apb1_gates_data __initconst = { | ||
810 | .mask = {0x3F001F}, | ||
811 | }; | ||
812 | |||
804 | static const struct gates_data sun8i_a23_apb2_gates_data __initconst = { | 813 | static const struct gates_data sun8i_a23_apb2_gates_data __initconst = { |
805 | .mask = {0x1F0007}, | 814 | .mask = {0x1F0007}, |
806 | }; | 815 | }; |
@@ -893,6 +902,7 @@ static void __init sunxi_gates_clk_setup(struct device_node *node, | |||
893 | 902 | ||
894 | struct divs_data { | 903 | struct divs_data { |
895 | const struct factors_data *factors; /* data for the factor clock */ | 904 | const struct factors_data *factors; /* data for the factor clock */ |
905 | int ndivs; /* number of children */ | ||
896 | struct { | 906 | struct { |
897 | u8 fixed; /* is it a fixed divisor? if not... */ | 907 | u8 fixed; /* is it a fixed divisor? if not... */ |
898 | struct clk_div_table *table; /* is it a table based divisor? */ | 908 | struct clk_div_table *table; /* is it a table based divisor? */ |
@@ -912,6 +922,7 @@ static struct clk_div_table pll6_sata_tbl[] = { | |||
912 | 922 | ||
913 | static const struct divs_data pll5_divs_data __initconst = { | 923 | static const struct divs_data pll5_divs_data __initconst = { |
914 | .factors = &sun4i_pll5_data, | 924 | .factors = &sun4i_pll5_data, |
925 | .ndivs = 2, | ||
915 | .div = { | 926 | .div = { |
916 | { .shift = 0, .pow = 0, }, /* M, DDR */ | 927 | { .shift = 0, .pow = 0, }, /* M, DDR */ |
917 | { .shift = 16, .pow = 1, }, /* P, other */ | 928 | { .shift = 16, .pow = 1, }, /* P, other */ |
@@ -920,12 +931,21 @@ static const struct divs_data pll5_divs_data __initconst = { | |||
920 | 931 | ||
921 | static const struct divs_data pll6_divs_data __initconst = { | 932 | static const struct divs_data pll6_divs_data __initconst = { |
922 | .factors = &sun4i_pll6_data, | 933 | .factors = &sun4i_pll6_data, |
934 | .ndivs = 2, | ||
923 | .div = { | 935 | .div = { |
924 | { .shift = 0, .table = pll6_sata_tbl, .gate = 14 }, /* M, SATA */ | 936 | { .shift = 0, .table = pll6_sata_tbl, .gate = 14 }, /* M, SATA */ |
925 | { .fixed = 2 }, /* P, other */ | 937 | { .fixed = 2 }, /* P, other */ |
926 | } | 938 | } |
927 | }; | 939 | }; |
928 | 940 | ||
941 | static const struct divs_data sun6i_a31_pll6_divs_data __initconst = { | ||
942 | .factors = &sun6i_a31_pll6_data, | ||
943 | .ndivs = 1, | ||
944 | .div = { | ||
945 | { .fixed = 2 }, /* normal output */ | ||
946 | } | ||
947 | }; | ||
948 | |||
929 | /** | 949 | /** |
930 | * sunxi_divs_clk_setup() - Setup function for leaf divisors on clocks | 950 | * sunxi_divs_clk_setup() - Setup function for leaf divisors on clocks |
931 | * | 951 | * |
@@ -950,7 +970,7 @@ static void __init sunxi_divs_clk_setup(struct device_node *node, | |||
950 | struct clk_fixed_factor *fix_factor; | 970 | struct clk_fixed_factor *fix_factor; |
951 | struct clk_divider *divider; | 971 | struct clk_divider *divider; |
952 | void __iomem *reg; | 972 | void __iomem *reg; |
953 | int i = 0; | 973 | int ndivs = SUNXI_DIVS_MAX_QTY, i = 0; |
954 | int flags, clkflags; | 974 | int flags, clkflags; |
955 | 975 | ||
956 | /* Set up factor clock that we will be dividing */ | 976 | /* Set up factor clock that we will be dividing */ |
@@ -973,7 +993,11 @@ static void __init sunxi_divs_clk_setup(struct device_node *node, | |||
973 | * our RAM clock! */ | 993 | * our RAM clock! */ |
974 | clkflags = !strcmp("pll5", parent) ? 0 : CLK_SET_RATE_PARENT; | 994 | clkflags = !strcmp("pll5", parent) ? 0 : CLK_SET_RATE_PARENT; |
975 | 995 | ||
976 | for (i = 0; i < SUNXI_DIVS_MAX_QTY; i++) { | 996 | /* if number of children known, use it */ |
997 | if (data->ndivs) | ||
998 | ndivs = data->ndivs; | ||
999 | |||
1000 | for (i = 0; i < ndivs; i++) { | ||
977 | if (of_property_read_string_index(node, "clock-output-names", | 1001 | if (of_property_read_string_index(node, "clock-output-names", |
978 | i, &clk_name) != 0) | 1002 | i, &clk_name) != 0) |
979 | break; | 1003 | break; |
@@ -1062,7 +1086,6 @@ static const struct of_device_id clk_factors_match[] __initconst = { | |||
1062 | {.compatible = "allwinner,sun6i-a31-pll1-clk", .data = &sun6i_a31_pll1_data,}, | 1086 | {.compatible = "allwinner,sun6i-a31-pll1-clk", .data = &sun6i_a31_pll1_data,}, |
1063 | {.compatible = "allwinner,sun8i-a23-pll1-clk", .data = &sun8i_a23_pll1_data,}, | 1087 | {.compatible = "allwinner,sun8i-a23-pll1-clk", .data = &sun8i_a23_pll1_data,}, |
1064 | {.compatible = "allwinner,sun7i-a20-pll4-clk", .data = &sun7i_a20_pll4_data,}, | 1088 | {.compatible = "allwinner,sun7i-a20-pll4-clk", .data = &sun7i_a20_pll4_data,}, |
1065 | {.compatible = "allwinner,sun6i-a31-pll6-clk", .data = &sun6i_a31_pll6_data,}, | ||
1066 | {.compatible = "allwinner,sun4i-a10-apb1-clk", .data = &sun4i_apb1_data,}, | 1089 | {.compatible = "allwinner,sun4i-a10-apb1-clk", .data = &sun4i_apb1_data,}, |
1067 | {.compatible = "allwinner,sun7i-a20-out-clk", .data = &sun7i_a20_out_data,}, | 1090 | {.compatible = "allwinner,sun7i-a20-out-clk", .data = &sun7i_a20_out_data,}, |
1068 | {} | 1091 | {} |
@@ -1074,7 +1097,6 @@ static const struct of_device_id clk_div_match[] __initconst = { | |||
1074 | {.compatible = "allwinner,sun8i-a23-axi-clk", .data = &sun8i_a23_axi_data,}, | 1097 | {.compatible = "allwinner,sun8i-a23-axi-clk", .data = &sun8i_a23_axi_data,}, |
1075 | {.compatible = "allwinner,sun4i-a10-ahb-clk", .data = &sun4i_ahb_data,}, | 1098 | {.compatible = "allwinner,sun4i-a10-ahb-clk", .data = &sun4i_ahb_data,}, |
1076 | {.compatible = "allwinner,sun4i-a10-apb0-clk", .data = &sun4i_apb0_data,}, | 1099 | {.compatible = "allwinner,sun4i-a10-apb0-clk", .data = &sun4i_apb0_data,}, |
1077 | {.compatible = "allwinner,sun6i-a31-apb2-div-clk", .data = &sun6i_a31_apb2_div_data,}, | ||
1078 | {} | 1100 | {} |
1079 | }; | 1101 | }; |
1080 | 1102 | ||
@@ -1082,13 +1104,13 @@ static const struct of_device_id clk_div_match[] __initconst = { | |||
1082 | static const struct of_device_id clk_divs_match[] __initconst = { | 1104 | static const struct of_device_id clk_divs_match[] __initconst = { |
1083 | {.compatible = "allwinner,sun4i-a10-pll5-clk", .data = &pll5_divs_data,}, | 1105 | {.compatible = "allwinner,sun4i-a10-pll5-clk", .data = &pll5_divs_data,}, |
1084 | {.compatible = "allwinner,sun4i-a10-pll6-clk", .data = &pll6_divs_data,}, | 1106 | {.compatible = "allwinner,sun4i-a10-pll6-clk", .data = &pll6_divs_data,}, |
1107 | {.compatible = "allwinner,sun6i-a31-pll6-clk", .data = &sun6i_a31_pll6_divs_data,}, | ||
1085 | {} | 1108 | {} |
1086 | }; | 1109 | }; |
1087 | 1110 | ||
1088 | /* Matches for mux clocks */ | 1111 | /* Matches for mux clocks */ |
1089 | static const struct of_device_id clk_mux_match[] __initconst = { | 1112 | static const struct of_device_id clk_mux_match[] __initconst = { |
1090 | {.compatible = "allwinner,sun4i-a10-cpu-clk", .data = &sun4i_cpu_mux_data,}, | 1113 | {.compatible = "allwinner,sun4i-a10-cpu-clk", .data = &sun4i_cpu_mux_data,}, |
1091 | {.compatible = "allwinner,sun4i-a10-apb1-mux-clk", .data = &sun4i_apb1_mux_data,}, | ||
1092 | {.compatible = "allwinner,sun6i-a31-ahb1-mux-clk", .data = &sun6i_a31_ahb1_mux_data,}, | 1114 | {.compatible = "allwinner,sun6i-a31-ahb1-mux-clk", .data = &sun6i_a31_ahb1_mux_data,}, |
1093 | {} | 1115 | {} |
1094 | }; | 1116 | }; |
@@ -1102,16 +1124,21 @@ static const struct of_device_id clk_gates_match[] __initconst = { | |||
1102 | {.compatible = "allwinner,sun6i-a31-ahb1-gates-clk", .data = &sun6i_a31_ahb1_gates_data,}, | 1124 | {.compatible = "allwinner,sun6i-a31-ahb1-gates-clk", .data = &sun6i_a31_ahb1_gates_data,}, |
1103 | {.compatible = "allwinner,sun7i-a20-ahb-gates-clk", .data = &sun7i_a20_ahb_gates_data,}, | 1125 | {.compatible = "allwinner,sun7i-a20-ahb-gates-clk", .data = &sun7i_a20_ahb_gates_data,}, |
1104 | {.compatible = "allwinner,sun8i-a23-ahb1-gates-clk", .data = &sun8i_a23_ahb1_gates_data,}, | 1126 | {.compatible = "allwinner,sun8i-a23-ahb1-gates-clk", .data = &sun8i_a23_ahb1_gates_data,}, |
1127 | {.compatible = "allwinner,sun9i-a80-ahb0-gates-clk", .data = &sun9i_a80_ahb0_gates_data,}, | ||
1128 | {.compatible = "allwinner,sun9i-a80-ahb1-gates-clk", .data = &sun9i_a80_ahb1_gates_data,}, | ||
1129 | {.compatible = "allwinner,sun9i-a80-ahb2-gates-clk", .data = &sun9i_a80_ahb2_gates_data,}, | ||
1105 | {.compatible = "allwinner,sun4i-a10-apb0-gates-clk", .data = &sun4i_apb0_gates_data,}, | 1130 | {.compatible = "allwinner,sun4i-a10-apb0-gates-clk", .data = &sun4i_apb0_gates_data,}, |
1106 | {.compatible = "allwinner,sun5i-a10s-apb0-gates-clk", .data = &sun5i_a10s_apb0_gates_data,}, | 1131 | {.compatible = "allwinner,sun5i-a10s-apb0-gates-clk", .data = &sun5i_a10s_apb0_gates_data,}, |
1107 | {.compatible = "allwinner,sun5i-a13-apb0-gates-clk", .data = &sun5i_a13_apb0_gates_data,}, | 1132 | {.compatible = "allwinner,sun5i-a13-apb0-gates-clk", .data = &sun5i_a13_apb0_gates_data,}, |
1108 | {.compatible = "allwinner,sun7i-a20-apb0-gates-clk", .data = &sun7i_a20_apb0_gates_data,}, | 1133 | {.compatible = "allwinner,sun7i-a20-apb0-gates-clk", .data = &sun7i_a20_apb0_gates_data,}, |
1134 | {.compatible = "allwinner,sun9i-a80-apb0-gates-clk", .data = &sun9i_a80_apb0_gates_data,}, | ||
1109 | {.compatible = "allwinner,sun4i-a10-apb1-gates-clk", .data = &sun4i_apb1_gates_data,}, | 1135 | {.compatible = "allwinner,sun4i-a10-apb1-gates-clk", .data = &sun4i_apb1_gates_data,}, |
1110 | {.compatible = "allwinner,sun5i-a10s-apb1-gates-clk", .data = &sun5i_a10s_apb1_gates_data,}, | 1136 | {.compatible = "allwinner,sun5i-a10s-apb1-gates-clk", .data = &sun5i_a10s_apb1_gates_data,}, |
1111 | {.compatible = "allwinner,sun5i-a13-apb1-gates-clk", .data = &sun5i_a13_apb1_gates_data,}, | 1137 | {.compatible = "allwinner,sun5i-a13-apb1-gates-clk", .data = &sun5i_a13_apb1_gates_data,}, |
1112 | {.compatible = "allwinner,sun6i-a31-apb1-gates-clk", .data = &sun6i_a31_apb1_gates_data,}, | 1138 | {.compatible = "allwinner,sun6i-a31-apb1-gates-clk", .data = &sun6i_a31_apb1_gates_data,}, |
1113 | {.compatible = "allwinner,sun7i-a20-apb1-gates-clk", .data = &sun7i_a20_apb1_gates_data,}, | 1139 | {.compatible = "allwinner,sun7i-a20-apb1-gates-clk", .data = &sun7i_a20_apb1_gates_data,}, |
1114 | {.compatible = "allwinner,sun8i-a23-apb1-gates-clk", .data = &sun8i_a23_apb1_gates_data,}, | 1140 | {.compatible = "allwinner,sun8i-a23-apb1-gates-clk", .data = &sun8i_a23_apb1_gates_data,}, |
1141 | {.compatible = "allwinner,sun9i-a80-apb1-gates-clk", .data = &sun9i_a80_apb1_gates_data,}, | ||
1115 | {.compatible = "allwinner,sun6i-a31-apb2-gates-clk", .data = &sun6i_a31_apb2_gates_data,}, | 1142 | {.compatible = "allwinner,sun6i-a31-apb2-gates-clk", .data = &sun6i_a31_apb2_gates_data,}, |
1116 | {.compatible = "allwinner,sun8i-a23-apb2-gates-clk", .data = &sun8i_a23_apb2_gates_data,}, | 1143 | {.compatible = "allwinner,sun8i-a23-apb2-gates-clk", .data = &sun8i_a23_apb2_gates_data,}, |
1117 | {.compatible = "allwinner,sun4i-a10-usb-clk", .data = &sun4i_a10_usb_gates_data,}, | 1144 | {.compatible = "allwinner,sun4i-a10-usb-clk", .data = &sun4i_a10_usb_gates_data,}, |
@@ -1200,3 +1227,9 @@ static void __init sun6i_init_clocks(struct device_node *node) | |||
1200 | } | 1227 | } |
1201 | CLK_OF_DECLARE(sun6i_a31_clk_init, "allwinner,sun6i-a31", sun6i_init_clocks); | 1228 | CLK_OF_DECLARE(sun6i_a31_clk_init, "allwinner,sun6i-a31", sun6i_init_clocks); |
1202 | CLK_OF_DECLARE(sun8i_a23_clk_init, "allwinner,sun8i-a23", sun6i_init_clocks); | 1229 | CLK_OF_DECLARE(sun8i_a23_clk_init, "allwinner,sun8i-a23", sun6i_init_clocks); |
1230 | |||
1231 | static void __init sun9i_init_clocks(struct device_node *node) | ||
1232 | { | ||
1233 | sunxi_init_clocks(NULL, 0); | ||
1234 | } | ||
1235 | CLK_OF_DECLARE(sun9i_a80_clk_init, "allwinner,sun9i-a80", sun9i_init_clocks); | ||