aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/clk
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2014-06-15 22:02:20 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2014-06-15 22:02:20 -0400
commitdd1845af24a47b70cf84c29126698884f740ff9c (patch)
treefa12809d854d18ba36a568c21d57ceff43617af1 /drivers/clk
parentb55b39020289f225bf2455349ce1a67372a0baa9 (diff)
parentb640a6037c9ecd1f0ad23a8e9b4ca5f5b4112508 (diff)
Merge tag 'clk-for-linus-3.16-part2' of git://git.linaro.org/people/mike.turquette/linux
Pull more clock framework updates from Mike Turquette: "This contains the second half the of the clk changes for 3.16. They are simply fixes and code refactoring for the OMAP clock drivers. The sunxi clock driver changes include splitting out the one mega-driver into several smaller pieces and adding support for the A31 SoC clocks" * tag 'clk-for-linus-3.16-part2' of git://git.linaro.org/people/mike.turquette/linux: (25 commits) clk: sunxi: document PRCM clock compatible strings clk: sunxi: add PRCM (Power/Reset/Clock Management) clks support clk: sun6i: Protect SDRAM gating bit clk: sun6i: Protect CPU clock clk: sunxi: Rework clock protection code clk: sunxi: Move the GMAC clock to a file of its own clk: sunxi: Move the 24M oscillator to a file of its own clk: sunxi: Remove calls to clk_put clk: sunxi: document new A31 USB clock compatible clk: sunxi: Implement A31 USB clock ARM: dts: OMAP5/DRA7: use omap5-mpu-dpll-clock capable of dealing with higher frequencies CLK: TI: dpll: support OMAP5 MPU DPLL that need special handling for higher frequencies ARM: OMAP5+: dpll: support Duty Cycle Correction(DCC) CLK: TI: clk-54xx: Set the rate for dpll_abe_m2x2_ck CLK: TI: Driver for DRA7 ATL (Audio Tracking Logic) dt:/bindings: DRA7 ATL (Audio Tracking Logic) clock bindings ARM: dts: dra7xx-clocks: Correct name for atl clkin3 clock CLK: TI: gate: add composite interface clock to OMAP2 only build ARM: OMAP2: clock: add DT boot support for cpufreq_ck CLK: TI: OMAP2: add clock init support ...
Diffstat (limited to 'drivers/clk')
-rw-r--r--drivers/clk/sunxi/Makefile4
-rw-r--r--drivers/clk/sunxi/clk-a10-hosc.c73
-rw-r--r--drivers/clk/sunxi/clk-a20-gmac.c119
-rw-r--r--drivers/clk/sunxi/clk-sun6i-apb0-gates.c99
-rw-r--r--drivers/clk/sunxi/clk-sun6i-apb0.c77
-rw-r--r--drivers/clk/sunxi/clk-sun6i-ar100.c233
-rw-r--r--drivers/clk/sunxi/clk-sunxi.c239
-rw-r--r--drivers/clk/ti/Makefile4
-rw-r--r--drivers/clk/ti/apll.c181
-rw-r--r--drivers/clk/ti/clk-2xxx.c256
-rw-r--r--drivers/clk/ti/clk-54xx.c6
-rw-r--r--drivers/clk/ti/clk-7xx.c2
-rw-r--r--drivers/clk/ti/clk-dra7-atl.c312
-rw-r--r--drivers/clk/ti/dpll.c138
-rw-r--r--drivers/clk/ti/gate.c2
-rw-r--r--drivers/clk/ti/interface.c11
16 files changed, 1531 insertions, 225 deletions
diff --git a/drivers/clk/sunxi/Makefile b/drivers/clk/sunxi/Makefile
index b5bac917612c..762fd64dbd1f 100644
--- a/drivers/clk/sunxi/Makefile
+++ b/drivers/clk/sunxi/Makefile
@@ -3,3 +3,7 @@
3# 3#
4 4
5obj-y += clk-sunxi.o clk-factors.o 5obj-y += clk-sunxi.o clk-factors.o
6obj-y += clk-a10-hosc.o
7obj-y += clk-a20-gmac.o
8
9obj-$(CONFIG_MFD_SUN6I_PRCM) += clk-sun6i-ar100.o clk-sun6i-apb0.o clk-sun6i-apb0-gates.o
diff --git a/drivers/clk/sunxi/clk-a10-hosc.c b/drivers/clk/sunxi/clk-a10-hosc.c
new file mode 100644
index 000000000000..0481d5d673d6
--- /dev/null
+++ b/drivers/clk/sunxi/clk-a10-hosc.c
@@ -0,0 +1,73 @@
1/*
2 * Copyright 2013 Emilio López
3 *
4 * Emilio López <emilio@elopez.com.ar>
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
22#define SUNXI_OSC24M_GATE 0
23
24static DEFINE_SPINLOCK(hosc_lock);
25
26static void __init sun4i_osc_clk_setup(struct device_node *node)
27{
28 struct clk *clk;
29 struct clk_fixed_rate *fixed;
30 struct clk_gate *gate;
31 const char *clk_name = node->name;
32 u32 rate;
33
34 if (of_property_read_u32(node, "clock-frequency", &rate))
35 return;
36
37 /* allocate fixed-rate and gate clock structs */
38 fixed = kzalloc(sizeof(struct clk_fixed_rate), GFP_KERNEL);
39 if (!fixed)
40 return;
41 gate = kzalloc(sizeof(struct clk_gate), GFP_KERNEL);
42 if (!gate)
43 goto err_free_fixed;
44
45 of_property_read_string(node, "clock-output-names", &clk_name);
46
47 /* set up gate and fixed rate properties */
48 gate->reg = of_iomap(node, 0);
49 gate->bit_idx = SUNXI_OSC24M_GATE;
50 gate->lock = &hosc_lock;
51 fixed->fixed_rate = rate;
52
53 clk = clk_register_composite(NULL, clk_name,
54 NULL, 0,
55 NULL, NULL,
56 &fixed->hw, &clk_fixed_rate_ops,
57 &gate->hw, &clk_gate_ops,
58 CLK_IS_ROOT);
59
60 if (IS_ERR(clk))
61 goto err_free_gate;
62
63 of_clk_add_provider(node, of_clk_src_simple_get, clk);
64 clk_register_clkdev(clk, clk_name, NULL);
65
66 return;
67
68err_free_gate:
69 kfree(gate);
70err_free_fixed:
71 kfree(fixed);
72}
73CLK_OF_DECLARE(sun4i_osc, "allwinner,sun4i-a10-osc-clk", sun4i_osc_clk_setup);
diff --git a/drivers/clk/sunxi/clk-a20-gmac.c b/drivers/clk/sunxi/clk-a20-gmac.c
new file mode 100644
index 000000000000..633ddc4389ef
--- /dev/null
+++ b/drivers/clk/sunxi/clk-a20-gmac.c
@@ -0,0 +1,119 @@
1/*
2 * Copyright 2013 Emilio López
3 * Emilio López <emilio@elopez.com.ar>
4 *
5 * Copyright 2013 Chen-Yu Tsai
6 * Chen-Yu Tsai <wens@csie.org>
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; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 */
18
19#include <linux/clk-provider.h>
20#include <linux/clkdev.h>
21#include <linux/of.h>
22#include <linux/of_address.h>
23#include <linux/slab.h>
24
25static DEFINE_SPINLOCK(gmac_lock);
26
27/**
28 * sun7i_a20_gmac_clk_setup - Setup function for A20/A31 GMAC clock module
29 *
30 * This clock looks something like this
31 * ________________________
32 * MII TX clock from PHY >-----|___________ _________|----> to GMAC core
33 * GMAC Int. RGMII TX clk >----|___________\__/__gate---|----> to PHY
34 * Ext. 125MHz RGMII TX clk >--|__divider__/ |
35 * |________________________|
36 *
37 * The external 125 MHz reference is optional, i.e. GMAC can use its
38 * internal TX clock just fine. The A31 GMAC clock module does not have
39 * the divider controls for the external reference.
40 *
41 * To keep it simple, let the GMAC use either the MII TX clock for MII mode,
42 * and its internal TX clock for GMII and RGMII modes. The GMAC driver should
43 * select the appropriate source and gate/ungate the output to the PHY.
44 *
45 * Only the GMAC should use this clock. Altering the clock so that it doesn't
46 * match the GMAC's operation parameters will result in the GMAC not being
47 * able to send traffic out. The GMAC driver should set the clock rate and
48 * enable/disable this clock to configure the required state. The clock
49 * driver then responds by auto-reparenting the clock.
50 */
51
52#define SUN7I_A20_GMAC_GPIT 2
53#define SUN7I_A20_GMAC_MASK 0x3
54#define SUN7I_A20_GMAC_PARENTS 2
55
56static void __init sun7i_a20_gmac_clk_setup(struct device_node *node)
57{
58 struct clk *clk;
59 struct clk_mux *mux;
60 struct clk_gate *gate;
61 const char *clk_name = node->name;
62 const char *parents[SUN7I_A20_GMAC_PARENTS];
63 void *reg;
64
65 if (of_property_read_string(node, "clock-output-names", &clk_name))
66 return;
67
68 /* allocate mux and gate clock structs */
69 mux = kzalloc(sizeof(struct clk_mux), GFP_KERNEL);
70 if (!mux)
71 return;
72
73 gate = kzalloc(sizeof(struct clk_gate), GFP_KERNEL);
74 if (!gate)
75 goto free_mux;
76
77 /* gmac clock requires exactly 2 parents */
78 parents[0] = of_clk_get_parent_name(node, 0);
79 parents[1] = of_clk_get_parent_name(node, 1);
80 if (!parents[0] || !parents[1])
81 goto free_gate;
82
83 reg = of_iomap(node, 0);
84 if (!reg)
85 goto free_gate;
86
87 /* set up gate and fixed rate properties */
88 gate->reg = reg;
89 gate->bit_idx = SUN7I_A20_GMAC_GPIT;
90 gate->lock = &gmac_lock;
91 mux->reg = reg;
92 mux->mask = SUN7I_A20_GMAC_MASK;
93 mux->flags = CLK_MUX_INDEX_BIT;
94 mux->lock = &gmac_lock;
95
96 clk = clk_register_composite(NULL, clk_name,
97 parents, SUN7I_A20_GMAC_PARENTS,
98 &mux->hw, &clk_mux_ops,
99 NULL, NULL,
100 &gate->hw, &clk_gate_ops,
101 0);
102
103 if (IS_ERR(clk))
104 goto iounmap_reg;
105
106 of_clk_add_provider(node, of_clk_src_simple_get, clk);
107 clk_register_clkdev(clk, clk_name, NULL);
108
109 return;
110
111iounmap_reg:
112 iounmap(reg);
113free_gate:
114 kfree(gate);
115free_mux:
116 kfree(mux);
117}
118CLK_OF_DECLARE(sun7i_a20_gmac, "allwinner,sun7i-a20-gmac-clk",
119 sun7i_a20_gmac_clk_setup);
diff --git a/drivers/clk/sunxi/clk-sun6i-apb0-gates.c b/drivers/clk/sunxi/clk-sun6i-apb0-gates.c
new file mode 100644
index 000000000000..44cd27c5c401
--- /dev/null
+++ b/drivers/clk/sunxi/clk-sun6i-apb0-gates.c
@@ -0,0 +1,99 @@
1/*
2 * Copyright (C) 2014 Free Electrons
3 *
4 * License Terms: GNU General Public License v2
5 * Author: Boris BREZILLON <boris.brezillon@free-electrons.com>
6 *
7 * Allwinner A31 APB0 clock gates driver
8 *
9 */
10
11#include <linux/clk-provider.h>
12#include <linux/module.h>
13#include <linux/of.h>
14#include <linux/platform_device.h>
15
16#define SUN6I_APB0_GATES_MAX_SIZE 32
17
18static int sun6i_a31_apb0_gates_clk_probe(struct platform_device *pdev)
19{
20 struct device_node *np = pdev->dev.of_node;
21 struct clk_onecell_data *clk_data;
22 const char *clk_parent;
23 const char *clk_name;
24 struct resource *r;
25 void __iomem *reg;
26 int gate_id;
27 int ngates;
28 int i;
29
30 r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
31 reg = devm_ioremap_resource(&pdev->dev, r);
32 if (!reg)
33 return PTR_ERR(reg);
34
35 clk_parent = of_clk_get_parent_name(np, 0);
36 if (!clk_parent)
37 return -EINVAL;
38
39 ngates = of_property_count_strings(np, "clock-output-names");
40 if (ngates < 0)
41 return ngates;
42
43 if (!ngates || ngates > SUN6I_APB0_GATES_MAX_SIZE)
44 return -EINVAL;
45
46 clk_data = devm_kzalloc(&pdev->dev, sizeof(struct clk_onecell_data),
47 GFP_KERNEL);
48 if (!clk_data)
49 return -ENOMEM;
50
51 clk_data->clks = devm_kzalloc(&pdev->dev,
52 SUN6I_APB0_GATES_MAX_SIZE *
53 sizeof(struct clk *),
54 GFP_KERNEL);
55 if (!clk_data->clks)
56 return -ENOMEM;
57
58 for (i = 0; i < ngates; i++) {
59 of_property_read_string_index(np, "clock-output-names",
60 i, &clk_name);
61
62 gate_id = i;
63 of_property_read_u32_index(np, "clock-indices", i, &gate_id);
64
65 WARN_ON(gate_id >= SUN6I_APB0_GATES_MAX_SIZE);
66 if (gate_id >= SUN6I_APB0_GATES_MAX_SIZE)
67 continue;
68
69 clk_data->clks[gate_id] = clk_register_gate(&pdev->dev,
70 clk_name,
71 clk_parent, 0,
72 reg, gate_id,
73 0, NULL);
74 WARN_ON(IS_ERR(clk_data->clks[gate_id]));
75 }
76
77 clk_data->clk_num = ngates;
78
79 return of_clk_add_provider(np, of_clk_src_onecell_get, clk_data);
80}
81
82const struct of_device_id sun6i_a31_apb0_gates_clk_dt_ids[] = {
83 { .compatible = "allwinner,sun6i-a31-apb0-gates-clk" },
84 { /* sentinel */ }
85};
86
87static struct platform_driver sun6i_a31_apb0_gates_clk_driver = {
88 .driver = {
89 .name = "sun6i-a31-apb0-gates-clk",
90 .owner = THIS_MODULE,
91 .of_match_table = sun6i_a31_apb0_gates_clk_dt_ids,
92 },
93 .probe = sun6i_a31_apb0_gates_clk_probe,
94};
95module_platform_driver(sun6i_a31_apb0_gates_clk_driver);
96
97MODULE_AUTHOR("Boris BREZILLON <boris.brezillon@free-electrons.com>");
98MODULE_DESCRIPTION("Allwinner A31 APB0 gate clocks driver");
99MODULE_LICENSE("GPL v2");
diff --git a/drivers/clk/sunxi/clk-sun6i-apb0.c b/drivers/clk/sunxi/clk-sun6i-apb0.c
new file mode 100644
index 000000000000..11f17c34c2ae
--- /dev/null
+++ b/drivers/clk/sunxi/clk-sun6i-apb0.c
@@ -0,0 +1,77 @@
1/*
2 * Copyright (C) 2014 Free Electrons
3 *
4 * License Terms: GNU General Public License v2
5 * Author: Boris BREZILLON <boris.brezillon@free-electrons.com>
6 *
7 * Allwinner A31 APB0 clock driver
8 *
9 */
10
11#include <linux/clk-provider.h>
12#include <linux/module.h>
13#include <linux/of.h>
14#include <linux/platform_device.h>
15
16/*
17 * The APB0 clk has a configurable divisor.
18 *
19 * We must use a clk_div_table and not a regular power of 2
20 * divisor here, because the first 2 values divide the clock
21 * by 2.
22 */
23static const struct clk_div_table sun6i_a31_apb0_divs[] = {
24 { .val = 0, .div = 2, },
25 { .val = 1, .div = 2, },
26 { .val = 2, .div = 4, },
27 { .val = 3, .div = 8, },
28 { /* sentinel */ },
29};
30
31static int sun6i_a31_apb0_clk_probe(struct platform_device *pdev)
32{
33 struct device_node *np = pdev->dev.of_node;
34 const char *clk_name = np->name;
35 const char *clk_parent;
36 struct resource *r;
37 void __iomem *reg;
38 struct clk *clk;
39
40 r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
41 reg = devm_ioremap_resource(&pdev->dev, r);
42 if (IS_ERR(reg))
43 return PTR_ERR(reg);
44
45 clk_parent = of_clk_get_parent_name(np, 0);
46 if (!clk_parent)
47 return -EINVAL;
48
49 of_property_read_string(np, "clock-output-names", &clk_name);
50
51 clk = clk_register_divider_table(&pdev->dev, clk_name, clk_parent,
52 0, reg, 0, 2, 0, sun6i_a31_apb0_divs,
53 NULL);
54 if (IS_ERR(clk))
55 return PTR_ERR(clk);
56
57 return of_clk_add_provider(np, of_clk_src_simple_get, clk);
58}
59
60const struct of_device_id sun6i_a31_apb0_clk_dt_ids[] = {
61 { .compatible = "allwinner,sun6i-a31-apb0-clk" },
62 { /* sentinel */ }
63};
64
65static struct platform_driver sun6i_a31_apb0_clk_driver = {
66 .driver = {
67 .name = "sun6i-a31-apb0-clk",
68 .owner = THIS_MODULE,
69 .of_match_table = sun6i_a31_apb0_clk_dt_ids,
70 },
71 .probe = sun6i_a31_apb0_clk_probe,
72};
73module_platform_driver(sun6i_a31_apb0_clk_driver);
74
75MODULE_AUTHOR("Boris BREZILLON <boris.brezillon@free-electrons.com>");
76MODULE_DESCRIPTION("Allwinner A31 APB0 clock Driver");
77MODULE_LICENSE("GPL v2");
diff --git a/drivers/clk/sunxi/clk-sun6i-ar100.c b/drivers/clk/sunxi/clk-sun6i-ar100.c
new file mode 100644
index 000000000000..f73cc051f0dd
--- /dev/null
+++ b/drivers/clk/sunxi/clk-sun6i-ar100.c
@@ -0,0 +1,233 @@
1/*
2 * Copyright (C) 2014 Free Electrons
3 *
4 * License Terms: GNU General Public License v2
5 * Author: Boris BREZILLON <boris.brezillon@free-electrons.com>
6 *
7 * Allwinner A31 AR100 clock driver
8 *
9 */
10
11#include <linux/clk-provider.h>
12#include <linux/module.h>
13#include <linux/of.h>
14#include <linux/platform_device.h>
15
16#define SUN6I_AR100_MAX_PARENTS 4
17#define SUN6I_AR100_SHIFT_MASK 0x3
18#define SUN6I_AR100_SHIFT_MAX SUN6I_AR100_SHIFT_MASK
19#define SUN6I_AR100_SHIFT_SHIFT 4
20#define SUN6I_AR100_DIV_MASK 0x1f
21#define SUN6I_AR100_DIV_MAX (SUN6I_AR100_DIV_MASK + 1)
22#define SUN6I_AR100_DIV_SHIFT 8
23#define SUN6I_AR100_MUX_MASK 0x3
24#define SUN6I_AR100_MUX_SHIFT 16
25
26struct ar100_clk {
27 struct clk_hw hw;
28 void __iomem *reg;
29};
30
31static inline struct ar100_clk *to_ar100_clk(struct clk_hw *hw)
32{
33 return container_of(hw, struct ar100_clk, hw);
34}
35
36static unsigned long ar100_recalc_rate(struct clk_hw *hw,
37 unsigned long parent_rate)
38{
39 struct ar100_clk *clk = to_ar100_clk(hw);
40 u32 val = readl(clk->reg);
41 int shift = (val >> SUN6I_AR100_SHIFT_SHIFT) & SUN6I_AR100_SHIFT_MASK;
42 int div = (val >> SUN6I_AR100_DIV_SHIFT) & SUN6I_AR100_DIV_MASK;
43
44 return (parent_rate >> shift) / (div + 1);
45}
46
47static long ar100_determine_rate(struct clk_hw *hw, unsigned long rate,
48 unsigned long *best_parent_rate,
49 struct clk **best_parent_clk)
50{
51 int nparents = __clk_get_num_parents(hw->clk);
52 long best_rate = -EINVAL;
53 int i;
54
55 *best_parent_clk = NULL;
56
57 for (i = 0; i < nparents; i++) {
58 unsigned long parent_rate;
59 unsigned long tmp_rate;
60 struct clk *parent;
61 unsigned long div;
62 int shift;
63
64 parent = clk_get_parent_by_index(hw->clk, i);
65 parent_rate = __clk_get_rate(parent);
66 div = DIV_ROUND_UP(parent_rate, rate);
67
68 /*
69 * The AR100 clk contains 2 divisors:
70 * - one power of 2 divisor
71 * - one regular divisor
72 *
73 * First check if we can safely shift (or divide by a power
74 * of 2) without losing precision on the requested rate.
75 */
76 shift = ffs(div) - 1;
77 if (shift > SUN6I_AR100_SHIFT_MAX)
78 shift = SUN6I_AR100_SHIFT_MAX;
79
80 div >>= shift;
81
82 /*
83 * Then if the divisor is still bigger than what the HW
84 * actually supports, use a bigger shift (or power of 2
85 * divider) value and accept to lose some precision.
86 */
87 while (div > SUN6I_AR100_DIV_MAX) {
88 shift++;
89 div >>= 1;
90 if (shift > SUN6I_AR100_SHIFT_MAX)
91 break;
92 }
93
94 /*
95 * If the shift value (or power of 2 divider) is bigger
96 * than what the HW actually support, skip this parent.
97 */
98 if (shift > SUN6I_AR100_SHIFT_MAX)
99 continue;
100
101 tmp_rate = (parent_rate >> shift) / div;
102 if (!*best_parent_clk || tmp_rate > best_rate) {
103 *best_parent_clk = parent;
104 *best_parent_rate = parent_rate;
105 best_rate = tmp_rate;
106 }
107 }
108
109 return best_rate;
110}
111
112static int ar100_set_parent(struct clk_hw *hw, u8 index)
113{
114 struct ar100_clk *clk = to_ar100_clk(hw);
115 u32 val = readl(clk->reg);
116
117 if (index >= SUN6I_AR100_MAX_PARENTS)
118 return -EINVAL;
119
120 val &= ~(SUN6I_AR100_MUX_MASK << SUN6I_AR100_MUX_SHIFT);
121 val |= (index << SUN6I_AR100_MUX_SHIFT);
122 writel(val, clk->reg);
123
124 return 0;
125}
126
127static u8 ar100_get_parent(struct clk_hw *hw)
128{
129 struct ar100_clk *clk = to_ar100_clk(hw);
130 return (readl(clk->reg) >> SUN6I_AR100_MUX_SHIFT) &
131 SUN6I_AR100_MUX_MASK;
132}
133
134static int ar100_set_rate(struct clk_hw *hw, unsigned long rate,
135 unsigned long parent_rate)
136{
137 unsigned long div = parent_rate / rate;
138 struct ar100_clk *clk = to_ar100_clk(hw);
139 u32 val = readl(clk->reg);
140 int shift;
141
142 if (parent_rate % rate)
143 return -EINVAL;
144
145 shift = ffs(div) - 1;
146 if (shift > SUN6I_AR100_SHIFT_MAX)
147 shift = SUN6I_AR100_SHIFT_MAX;
148
149 div >>= shift;
150
151 if (div > SUN6I_AR100_DIV_MAX)
152 return -EINVAL;
153
154 val &= ~((SUN6I_AR100_SHIFT_MASK << SUN6I_AR100_SHIFT_SHIFT) |
155 (SUN6I_AR100_DIV_MASK << SUN6I_AR100_DIV_SHIFT));
156 val |= (shift << SUN6I_AR100_SHIFT_SHIFT) |
157 (div << SUN6I_AR100_DIV_SHIFT);
158 writel(val, clk->reg);
159
160 return 0;
161}
162
163struct clk_ops ar100_ops = {
164 .recalc_rate = ar100_recalc_rate,
165 .determine_rate = ar100_determine_rate,
166 .set_parent = ar100_set_parent,
167 .get_parent = ar100_get_parent,
168 .set_rate = ar100_set_rate,
169};
170
171static int sun6i_a31_ar100_clk_probe(struct platform_device *pdev)
172{
173 const char *parents[SUN6I_AR100_MAX_PARENTS];
174 struct device_node *np = pdev->dev.of_node;
175 const char *clk_name = np->name;
176 struct clk_init_data init;
177 struct ar100_clk *ar100;
178 struct resource *r;
179 struct clk *clk;
180 int nparents;
181 int i;
182
183 ar100 = devm_kzalloc(&pdev->dev, sizeof(*ar100), GFP_KERNEL);
184 if (!ar100)
185 return -ENOMEM;
186
187 r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
188 ar100->reg = devm_ioremap_resource(&pdev->dev, r);
189 if (IS_ERR(ar100->reg))
190 return PTR_ERR(ar100->reg);
191
192 nparents = of_clk_get_parent_count(np);
193 if (nparents > SUN6I_AR100_MAX_PARENTS)
194 nparents = SUN6I_AR100_MAX_PARENTS;
195
196 for (i = 0; i < nparents; i++)
197 parents[i] = of_clk_get_parent_name(np, i);
198
199 of_property_read_string(np, "clock-output-names", &clk_name);
200
201 init.name = clk_name;
202 init.ops = &ar100_ops;
203 init.parent_names = parents;
204 init.num_parents = nparents;
205 init.flags = 0;
206
207 ar100->hw.init = &init;
208
209 clk = clk_register(&pdev->dev, &ar100->hw);
210 if (IS_ERR(clk))
211 return PTR_ERR(clk);
212
213 return of_clk_add_provider(np, of_clk_src_simple_get, clk);
214}
215
216const struct of_device_id sun6i_a31_ar100_clk_dt_ids[] = {
217 { .compatible = "allwinner,sun6i-a31-ar100-clk" },
218 { /* sentinel */ }
219};
220
221static struct platform_driver sun6i_a31_ar100_clk_driver = {
222 .driver = {
223 .name = "sun6i-a31-ar100-clk",
224 .owner = THIS_MODULE,
225 .of_match_table = sun6i_a31_ar100_clk_dt_ids,
226 },
227 .probe = sun6i_a31_ar100_clk_probe,
228};
229module_platform_driver(sun6i_a31_ar100_clk_driver);
230
231MODULE_AUTHOR("Boris BREZILLON <boris.brezillon@free-electrons.com>");
232MODULE_DESCRIPTION("Allwinner A31 AR100 clock Driver");
233MODULE_LICENSE("GPL v2");
diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c
index 426483422d3d..fb2ce8440f0e 100644
--- a/drivers/clk/sunxi/clk-sunxi.c
+++ b/drivers/clk/sunxi/clk-sunxi.c
@@ -28,63 +28,6 @@ static DEFINE_SPINLOCK(clk_lock);
28#define SUNXI_MAX_PARENTS 5 28#define SUNXI_MAX_PARENTS 5
29 29
30/** 30/**
31 * sun4i_osc_clk_setup() - Setup function for gatable oscillator
32 */
33
34#define SUNXI_OSC24M_GATE 0
35
36static void __init sun4i_osc_clk_setup(struct device_node *node)
37{
38 struct clk *clk;
39 struct clk_fixed_rate *fixed;
40 struct clk_gate *gate;
41 const char *clk_name = node->name;
42 u32 rate;
43
44 if (of_property_read_u32(node, "clock-frequency", &rate))
45 return;
46
47 /* allocate fixed-rate and gate clock structs */
48 fixed = kzalloc(sizeof(struct clk_fixed_rate), GFP_KERNEL);
49 if (!fixed)
50 return;
51 gate = kzalloc(sizeof(struct clk_gate), GFP_KERNEL);
52 if (!gate)
53 goto err_free_fixed;
54
55 of_property_read_string(node, "clock-output-names", &clk_name);
56
57 /* set up gate and fixed rate properties */
58 gate->reg = of_iomap(node, 0);
59 gate->bit_idx = SUNXI_OSC24M_GATE;
60 gate->lock = &clk_lock;
61 fixed->fixed_rate = rate;
62
63 clk = clk_register_composite(NULL, clk_name,
64 NULL, 0,
65 NULL, NULL,
66 &fixed->hw, &clk_fixed_rate_ops,
67 &gate->hw, &clk_gate_ops,
68 CLK_IS_ROOT);
69
70 if (IS_ERR(clk))
71 goto err_free_gate;
72
73 of_clk_add_provider(node, of_clk_src_simple_get, clk);
74 clk_register_clkdev(clk, clk_name, NULL);
75
76 return;
77
78err_free_gate:
79 kfree(gate);
80err_free_fixed:
81 kfree(fixed);
82}
83CLK_OF_DECLARE(sun4i_osc, "allwinner,sun4i-a10-osc-clk", sun4i_osc_clk_setup);
84
85
86
87/**
88 * sun4i_get_pll1_factors() - calculates n, k, m, p factors for PLL1 31 * sun4i_get_pll1_factors() - calculates n, k, m, p factors for PLL1
89 * PLL1 rate is calculated as follows 32 * PLL1 rate is calculated as follows
90 * rate = (parent_rate * n * (k + 1) >> p) / (m + 1); 33 * rate = (parent_rate * n * (k + 1) >> p) / (m + 1);
@@ -408,104 +351,6 @@ static void sun7i_a20_get_out_factors(u32 *freq, u32 parent_rate,
408 *p = calcp; 351 *p = calcp;
409} 352}
410 353
411
412
413/**
414 * sun7i_a20_gmac_clk_setup - Setup function for A20/A31 GMAC clock module
415 *
416 * This clock looks something like this
417 * ________________________
418 * MII TX clock from PHY >-----|___________ _________|----> to GMAC core
419 * GMAC Int. RGMII TX clk >----|___________\__/__gate---|----> to PHY
420 * Ext. 125MHz RGMII TX clk >--|__divider__/ |
421 * |________________________|
422 *
423 * The external 125 MHz reference is optional, i.e. GMAC can use its
424 * internal TX clock just fine. The A31 GMAC clock module does not have
425 * the divider controls for the external reference.
426 *
427 * To keep it simple, let the GMAC use either the MII TX clock for MII mode,
428 * and its internal TX clock for GMII and RGMII modes. The GMAC driver should
429 * select the appropriate source and gate/ungate the output to the PHY.
430 *
431 * Only the GMAC should use this clock. Altering the clock so that it doesn't
432 * match the GMAC's operation parameters will result in the GMAC not being
433 * able to send traffic out. The GMAC driver should set the clock rate and
434 * enable/disable this clock to configure the required state. The clock
435 * driver then responds by auto-reparenting the clock.
436 */
437
438#define SUN7I_A20_GMAC_GPIT 2
439#define SUN7I_A20_GMAC_MASK 0x3
440#define SUN7I_A20_GMAC_PARENTS 2
441
442static void __init sun7i_a20_gmac_clk_setup(struct device_node *node)
443{
444 struct clk *clk;
445 struct clk_mux *mux;
446 struct clk_gate *gate;
447 const char *clk_name = node->name;
448 const char *parents[SUN7I_A20_GMAC_PARENTS];
449 void *reg;
450
451 if (of_property_read_string(node, "clock-output-names", &clk_name))
452 return;
453
454 /* allocate mux and gate clock structs */
455 mux = kzalloc(sizeof(struct clk_mux), GFP_KERNEL);
456 if (!mux)
457 return;
458
459 gate = kzalloc(sizeof(struct clk_gate), GFP_KERNEL);
460 if (!gate)
461 goto free_mux;
462
463 /* gmac clock requires exactly 2 parents */
464 parents[0] = of_clk_get_parent_name(node, 0);
465 parents[1] = of_clk_get_parent_name(node, 1);
466 if (!parents[0] || !parents[1])
467 goto free_gate;
468
469 reg = of_iomap(node, 0);
470 if (!reg)
471 goto free_gate;
472
473 /* set up gate and fixed rate properties */
474 gate->reg = reg;
475 gate->bit_idx = SUN7I_A20_GMAC_GPIT;
476 gate->lock = &clk_lock;
477 mux->reg = reg;
478 mux->mask = SUN7I_A20_GMAC_MASK;
479 mux->flags = CLK_MUX_INDEX_BIT;
480 mux->lock = &clk_lock;
481
482 clk = clk_register_composite(NULL, clk_name,
483 parents, SUN7I_A20_GMAC_PARENTS,
484 &mux->hw, &clk_mux_ops,
485 NULL, NULL,
486 &gate->hw, &clk_gate_ops,
487 0);
488
489 if (IS_ERR(clk))
490 goto iounmap_reg;
491
492 of_clk_add_provider(node, of_clk_src_simple_get, clk);
493 clk_register_clkdev(clk, clk_name, NULL);
494
495 return;
496
497iounmap_reg:
498 iounmap(reg);
499free_gate:
500 kfree(gate);
501free_mux:
502 kfree(mux);
503}
504CLK_OF_DECLARE(sun7i_a20_gmac, "allwinner,sun7i-a20-gmac-clk",
505 sun7i_a20_gmac_clk_setup);
506
507
508
509/** 354/**
510 * clk_sunxi_mmc_phase_control() - configures MMC clock phase control 355 * clk_sunxi_mmc_phase_control() - configures MMC clock phase control
511 */ 356 */
@@ -1009,6 +854,11 @@ static const struct gates_data sun5i_a13_usb_gates_data __initconst = {
1009 .reset_mask = 0x03, 854 .reset_mask = 0x03,
1010}; 855};
1011 856
857static const struct gates_data sun6i_a31_usb_gates_data __initconst = {
858 .mask = { BIT(18) | BIT(17) | BIT(16) | BIT(10) | BIT(9) | BIT(8) },
859 .reset_mask = BIT(2) | BIT(1) | BIT(0),
860};
861
1012static void __init sunxi_gates_clk_setup(struct device_node *node, 862static void __init sunxi_gates_clk_setup(struct device_node *node,
1013 struct gates_data *data) 863 struct gates_data *data)
1014{ 864{
@@ -1304,6 +1154,7 @@ static const struct of_device_id clk_gates_match[] __initconst = {
1304 {.compatible = "allwinner,sun6i-a31-apb2-gates-clk", .data = &sun6i_a31_apb2_gates_data,}, 1154 {.compatible = "allwinner,sun6i-a31-apb2-gates-clk", .data = &sun6i_a31_apb2_gates_data,},
1305 {.compatible = "allwinner,sun4i-a10-usb-clk", .data = &sun4i_a10_usb_gates_data,}, 1155 {.compatible = "allwinner,sun4i-a10-usb-clk", .data = &sun4i_a10_usb_gates_data,},
1306 {.compatible = "allwinner,sun5i-a13-usb-clk", .data = &sun5i_a13_usb_gates_data,}, 1156 {.compatible = "allwinner,sun5i-a13-usb-clk", .data = &sun5i_a13_usb_gates_data,},
1157 {.compatible = "allwinner,sun6i-a31-usb-clk", .data = &sun6i_a31_usb_gates_data,},
1307 {} 1158 {}
1308}; 1159};
1309 1160
@@ -1321,33 +1172,10 @@ static void __init of_sunxi_table_clock_setup(const struct of_device_id *clk_mat
1321 } 1172 }
1322} 1173}
1323 1174
1324/** 1175static void __init sunxi_init_clocks(const char *clocks[], int nclocks)
1325 * System clock protection
1326 *
1327 * By enabling these critical clocks, we prevent their accidental gating
1328 * by the framework
1329 */
1330static void __init sunxi_clock_protect(void)
1331{ 1176{
1332 struct clk *clk; 1177 unsigned int i;
1333
1334 /* memory bus clock - sun5i+ */
1335 clk = clk_get(NULL, "mbus");
1336 if (!IS_ERR(clk)) {
1337 clk_prepare_enable(clk);
1338 clk_put(clk);
1339 }
1340
1341 /* DDR clock - sun4i+ */
1342 clk = clk_get(NULL, "pll5_ddr");
1343 if (!IS_ERR(clk)) {
1344 clk_prepare_enable(clk);
1345 clk_put(clk);
1346 }
1347}
1348 1178
1349static void __init sunxi_init_clocks(struct device_node *np)
1350{
1351 /* Register factor clocks */ 1179 /* Register factor clocks */
1352 of_sunxi_table_clock_setup(clk_factors_match, sunxi_factors_clk_setup); 1180 of_sunxi_table_clock_setup(clk_factors_match, sunxi_factors_clk_setup);
1353 1181
@@ -1363,11 +1191,48 @@ static void __init sunxi_init_clocks(struct device_node *np)
1363 /* Register gate clocks */ 1191 /* Register gate clocks */
1364 of_sunxi_table_clock_setup(clk_gates_match, sunxi_gates_clk_setup); 1192 of_sunxi_table_clock_setup(clk_gates_match, sunxi_gates_clk_setup);
1365 1193
1366 /* Enable core system clocks */ 1194 /* Protect the clocks that needs to stay on */
1367 sunxi_clock_protect(); 1195 for (i = 0; i < nclocks; i++) {
1196 struct clk *clk = clk_get(NULL, clocks[i]);
1197
1198 if (!IS_ERR(clk))
1199 clk_prepare_enable(clk);
1200 }
1201}
1202
1203static const char *sun4i_a10_critical_clocks[] __initdata = {
1204 "pll5_ddr",
1205};
1206
1207static void __init sun4i_a10_init_clocks(struct device_node *node)
1208{
1209 sunxi_init_clocks(sun4i_a10_critical_clocks,
1210 ARRAY_SIZE(sun4i_a10_critical_clocks));
1211}
1212CLK_OF_DECLARE(sun4i_a10_clk_init, "allwinner,sun4i-a10", sun4i_a10_init_clocks);
1213
1214static const char *sun5i_critical_clocks[] __initdata = {
1215 "mbus",
1216 "pll5_ddr",
1217};
1218
1219static void __init sun5i_init_clocks(struct device_node *node)
1220{
1221 sunxi_init_clocks(sun5i_critical_clocks,
1222 ARRAY_SIZE(sun5i_critical_clocks));
1223}
1224CLK_OF_DECLARE(sun5i_a10s_clk_init, "allwinner,sun5i-a10s", sun5i_init_clocks);
1225CLK_OF_DECLARE(sun5i_a13_clk_init, "allwinner,sun5i-a13", sun5i_init_clocks);
1226CLK_OF_DECLARE(sun7i_a20_clk_init, "allwinner,sun7i-a20", sun5i_init_clocks);
1227
1228static const char *sun6i_critical_clocks[] __initdata = {
1229 "cpu",
1230 "ahb1_sdram",
1231};
1232
1233static void __init sun6i_init_clocks(struct device_node *node)
1234{
1235 sunxi_init_clocks(sun6i_critical_clocks,
1236 ARRAY_SIZE(sun6i_critical_clocks));
1368} 1237}
1369CLK_OF_DECLARE(sun4i_a10_clk_init, "allwinner,sun4i-a10", sunxi_init_clocks); 1238CLK_OF_DECLARE(sun6i_a31_clk_init, "allwinner,sun6i-a31", sun6i_init_clocks);
1370CLK_OF_DECLARE(sun5i_a10s_clk_init, "allwinner,sun5i-a10s", sunxi_init_clocks);
1371CLK_OF_DECLARE(sun5i_a13_clk_init, "allwinner,sun5i-a13", sunxi_init_clocks);
1372CLK_OF_DECLARE(sun6i_a31_clk_init, "allwinner,sun6i-a31", sunxi_init_clocks);
1373CLK_OF_DECLARE(sun7i_a20_clk_init, "allwinner,sun7i-a20", sunxi_init_clocks);
diff --git a/drivers/clk/ti/Makefile b/drivers/clk/ti/Makefile
index 4319d4031aa3..ed4d0aaf8916 100644
--- a/drivers/clk/ti/Makefile
+++ b/drivers/clk/ti/Makefile
@@ -3,9 +3,11 @@ obj-y += clk.o autoidle.o clockdomain.o
3clk-common = dpll.o composite.o divider.o gate.o \ 3clk-common = dpll.o composite.o divider.o gate.o \
4 fixed-factor.o mux.o apll.o 4 fixed-factor.o mux.o apll.o
5obj-$(CONFIG_SOC_AM33XX) += $(clk-common) clk-33xx.o 5obj-$(CONFIG_SOC_AM33XX) += $(clk-common) clk-33xx.o
6obj-$(CONFIG_ARCH_OMAP2) += $(clk-common) interface.o clk-2xxx.o
6obj-$(CONFIG_ARCH_OMAP3) += $(clk-common) interface.o clk-3xxx.o 7obj-$(CONFIG_ARCH_OMAP3) += $(clk-common) interface.o clk-3xxx.o
7obj-$(CONFIG_ARCH_OMAP4) += $(clk-common) clk-44xx.o 8obj-$(CONFIG_ARCH_OMAP4) += $(clk-common) clk-44xx.o
8obj-$(CONFIG_SOC_OMAP5) += $(clk-common) clk-54xx.o 9obj-$(CONFIG_SOC_OMAP5) += $(clk-common) clk-54xx.o
9obj-$(CONFIG_SOC_DRA7XX) += $(clk-common) clk-7xx.o 10obj-$(CONFIG_SOC_DRA7XX) += $(clk-common) clk-7xx.o \
11 clk-dra7-atl.o
10obj-$(CONFIG_SOC_AM43XX) += $(clk-common) clk-43xx.o 12obj-$(CONFIG_SOC_AM43XX) += $(clk-common) clk-43xx.o
11endif 13endif
diff --git a/drivers/clk/ti/apll.c b/drivers/clk/ti/apll.c
index b986f61f5a77..5428c9c547cd 100644
--- a/drivers/clk/ti/apll.c
+++ b/drivers/clk/ti/apll.c
@@ -221,3 +221,184 @@ cleanup:
221 kfree(init); 221 kfree(init);
222} 222}
223CLK_OF_DECLARE(dra7_apll_clock, "ti,dra7-apll-clock", of_dra7_apll_setup); 223CLK_OF_DECLARE(dra7_apll_clock, "ti,dra7-apll-clock", of_dra7_apll_setup);
224
225#define OMAP2_EN_APLL_LOCKED 0x3
226#define OMAP2_EN_APLL_STOPPED 0x0
227
228static int omap2_apll_is_enabled(struct clk_hw *hw)
229{
230 struct clk_hw_omap *clk = to_clk_hw_omap(hw);
231 struct dpll_data *ad = clk->dpll_data;
232 u32 v;
233
234 v = ti_clk_ll_ops->clk_readl(ad->control_reg);
235 v &= ad->enable_mask;
236
237 v >>= __ffs(ad->enable_mask);
238
239 return v == OMAP2_EN_APLL_LOCKED ? 1 : 0;
240}
241
242static unsigned long omap2_apll_recalc(struct clk_hw *hw,
243 unsigned long parent_rate)
244{
245 struct clk_hw_omap *clk = to_clk_hw_omap(hw);
246
247 if (omap2_apll_is_enabled(hw))
248 return clk->fixed_rate;
249
250 return 0;
251}
252
253static int omap2_apll_enable(struct clk_hw *hw)
254{
255 struct clk_hw_omap *clk = to_clk_hw_omap(hw);
256 struct dpll_data *ad = clk->dpll_data;
257 u32 v;
258 int i = 0;
259
260 v = ti_clk_ll_ops->clk_readl(ad->control_reg);
261 v &= ~ad->enable_mask;
262 v |= OMAP2_EN_APLL_LOCKED << __ffs(ad->enable_mask);
263 ti_clk_ll_ops->clk_writel(v, ad->control_reg);
264
265 while (1) {
266 v = ti_clk_ll_ops->clk_readl(ad->idlest_reg);
267 if (v & ad->idlest_mask)
268 break;
269 if (i > MAX_APLL_WAIT_TRIES)
270 break;
271 i++;
272 udelay(1);
273 }
274
275 if (i == MAX_APLL_WAIT_TRIES) {
276 pr_warn("%s failed to transition to locked\n",
277 __clk_get_name(clk->hw.clk));
278 return -EBUSY;
279 }
280
281 return 0;
282}
283
284static void omap2_apll_disable(struct clk_hw *hw)
285{
286 struct clk_hw_omap *clk = to_clk_hw_omap(hw);
287 struct dpll_data *ad = clk->dpll_data;
288 u32 v;
289
290 v = ti_clk_ll_ops->clk_readl(ad->control_reg);
291 v &= ~ad->enable_mask;
292 v |= OMAP2_EN_APLL_STOPPED << __ffs(ad->enable_mask);
293 ti_clk_ll_ops->clk_writel(v, ad->control_reg);
294}
295
296static struct clk_ops omap2_apll_ops = {
297 .enable = &omap2_apll_enable,
298 .disable = &omap2_apll_disable,
299 .is_enabled = &omap2_apll_is_enabled,
300 .recalc_rate = &omap2_apll_recalc,
301};
302
303static void omap2_apll_set_autoidle(struct clk_hw_omap *clk, u32 val)
304{
305 struct dpll_data *ad = clk->dpll_data;
306 u32 v;
307
308 v = ti_clk_ll_ops->clk_readl(ad->autoidle_reg);
309 v &= ~ad->autoidle_mask;
310 v |= val << __ffs(ad->autoidle_mask);
311 ti_clk_ll_ops->clk_writel(v, ad->control_reg);
312}
313
314#define OMAP2_APLL_AUTOIDLE_LOW_POWER_STOP 0x3
315#define OMAP2_APLL_AUTOIDLE_DISABLE 0x0
316
317static void omap2_apll_allow_idle(struct clk_hw_omap *clk)
318{
319 omap2_apll_set_autoidle(clk, OMAP2_APLL_AUTOIDLE_LOW_POWER_STOP);
320}
321
322static void omap2_apll_deny_idle(struct clk_hw_omap *clk)
323{
324 omap2_apll_set_autoidle(clk, OMAP2_APLL_AUTOIDLE_DISABLE);
325}
326
327static struct clk_hw_omap_ops omap2_apll_hwops = {
328 .allow_idle = &omap2_apll_allow_idle,
329 .deny_idle = &omap2_apll_deny_idle,
330};
331
332static void __init of_omap2_apll_setup(struct device_node *node)
333{
334 struct dpll_data *ad = NULL;
335 struct clk_hw_omap *clk_hw = NULL;
336 struct clk_init_data *init = NULL;
337 struct clk *clk;
338 const char *parent_name;
339 u32 val;
340
341 ad = kzalloc(sizeof(*clk_hw), GFP_KERNEL);
342 clk_hw = kzalloc(sizeof(*clk_hw), GFP_KERNEL);
343 init = kzalloc(sizeof(*init), GFP_KERNEL);
344
345 if (!ad || !clk_hw || !init)
346 goto cleanup;
347
348 clk_hw->dpll_data = ad;
349 clk_hw->hw.init = init;
350 init->ops = &omap2_apll_ops;
351 init->name = node->name;
352 clk_hw->ops = &omap2_apll_hwops;
353
354 init->num_parents = of_clk_get_parent_count(node);
355 if (init->num_parents != 1) {
356 pr_err("%s must have one parent\n", node->name);
357 goto cleanup;
358 }
359
360 parent_name = of_clk_get_parent_name(node, 0);
361 init->parent_names = &parent_name;
362
363 if (of_property_read_u32(node, "ti,clock-frequency", &val)) {
364 pr_err("%s missing clock-frequency\n", node->name);
365 goto cleanup;
366 }
367 clk_hw->fixed_rate = val;
368
369 if (of_property_read_u32(node, "ti,bit-shift", &val)) {
370 pr_err("%s missing bit-shift\n", node->name);
371 goto cleanup;
372 }
373
374 clk_hw->enable_bit = val;
375 ad->enable_mask = 0x3 << val;
376 ad->autoidle_mask = 0x3 << val;
377
378 if (of_property_read_u32(node, "ti,idlest-shift", &val)) {
379 pr_err("%s missing idlest-shift\n", node->name);
380 goto cleanup;
381 }
382
383 ad->idlest_mask = 1 << val;
384
385 ad->control_reg = ti_clk_get_reg_addr(node, 0);
386 ad->autoidle_reg = ti_clk_get_reg_addr(node, 1);
387 ad->idlest_reg = ti_clk_get_reg_addr(node, 2);
388
389 if (!ad->control_reg || !ad->autoidle_reg || !ad->idlest_reg)
390 goto cleanup;
391
392 clk = clk_register(NULL, &clk_hw->hw);
393 if (!IS_ERR(clk)) {
394 of_clk_add_provider(node, of_clk_src_simple_get, clk);
395 kfree(init);
396 return;
397 }
398cleanup:
399 kfree(ad);
400 kfree(clk_hw);
401 kfree(init);
402}
403CLK_OF_DECLARE(omap2_apll_clock, "ti,omap2-apll-clock",
404 of_omap2_apll_setup);
diff --git a/drivers/clk/ti/clk-2xxx.c b/drivers/clk/ti/clk-2xxx.c
new file mode 100644
index 000000000000..c808ab3d2bb2
--- /dev/null
+++ b/drivers/clk/ti/clk-2xxx.c
@@ -0,0 +1,256 @@
1/*
2 * OMAP2 Clock init
3 *
4 * Copyright (C) 2013 Texas Instruments, Inc
5 * Tero Kristo (t-kristo@ti.com)
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License as
9 * published by the Free Software Foundation version 2.
10 *
11 * This program is distributed "as is" WITHOUT ANY WARRANTY of any
12 * kind, whether express or implied; without even the implied warranty
13 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 */
16
17#include <linux/kernel.h>
18#include <linux/list.h>
19#include <linux/clk-provider.h>
20#include <linux/clk/ti.h>
21
22static struct ti_dt_clk omap2xxx_clks[] = {
23 DT_CLK(NULL, "func_32k_ck", "func_32k_ck"),
24 DT_CLK(NULL, "secure_32k_ck", "secure_32k_ck"),
25 DT_CLK(NULL, "virt_12m_ck", "virt_12m_ck"),
26 DT_CLK(NULL, "virt_13m_ck", "virt_13m_ck"),
27 DT_CLK(NULL, "virt_19200000_ck", "virt_19200000_ck"),
28 DT_CLK(NULL, "virt_26m_ck", "virt_26m_ck"),
29 DT_CLK(NULL, "aplls_clkin_ck", "aplls_clkin_ck"),
30 DT_CLK(NULL, "aplls_clkin_x2_ck", "aplls_clkin_x2_ck"),
31 DT_CLK(NULL, "osc_ck", "osc_ck"),
32 DT_CLK(NULL, "sys_ck", "sys_ck"),
33 DT_CLK(NULL, "alt_ck", "alt_ck"),
34 DT_CLK(NULL, "mcbsp_clks", "mcbsp_clks"),
35 DT_CLK(NULL, "dpll_ck", "dpll_ck"),
36 DT_CLK(NULL, "apll96_ck", "apll96_ck"),
37 DT_CLK(NULL, "apll54_ck", "apll54_ck"),
38 DT_CLK(NULL, "func_54m_ck", "func_54m_ck"),
39 DT_CLK(NULL, "core_ck", "core_ck"),
40 DT_CLK(NULL, "func_96m_ck", "func_96m_ck"),
41 DT_CLK(NULL, "func_48m_ck", "func_48m_ck"),
42 DT_CLK(NULL, "func_12m_ck", "func_12m_ck"),
43 DT_CLK(NULL, "sys_clkout_src", "sys_clkout_src"),
44 DT_CLK(NULL, "sys_clkout", "sys_clkout"),
45 DT_CLK(NULL, "emul_ck", "emul_ck"),
46 DT_CLK(NULL, "mpu_ck", "mpu_ck"),
47 DT_CLK(NULL, "dsp_fck", "dsp_fck"),
48 DT_CLK(NULL, "gfx_3d_fck", "gfx_3d_fck"),
49 DT_CLK(NULL, "gfx_2d_fck", "gfx_2d_fck"),
50 DT_CLK(NULL, "gfx_ick", "gfx_ick"),
51 DT_CLK("omapdss_dss", "ick", "dss_ick"),
52 DT_CLK(NULL, "dss_ick", "dss_ick"),
53 DT_CLK(NULL, "dss1_fck", "dss1_fck"),
54 DT_CLK(NULL, "dss2_fck", "dss2_fck"),
55 DT_CLK(NULL, "dss_54m_fck", "dss_54m_fck"),
56 DT_CLK(NULL, "core_l3_ck", "core_l3_ck"),
57 DT_CLK(NULL, "ssi_fck", "ssi_ssr_sst_fck"),
58 DT_CLK(NULL, "usb_l4_ick", "usb_l4_ick"),
59 DT_CLK(NULL, "l4_ck", "l4_ck"),
60 DT_CLK(NULL, "ssi_l4_ick", "ssi_l4_ick"),
61 DT_CLK(NULL, "gpt1_ick", "gpt1_ick"),
62 DT_CLK(NULL, "gpt1_fck", "gpt1_fck"),
63 DT_CLK(NULL, "gpt2_ick", "gpt2_ick"),
64 DT_CLK(NULL, "gpt2_fck", "gpt2_fck"),
65 DT_CLK(NULL, "gpt3_ick", "gpt3_ick"),
66 DT_CLK(NULL, "gpt3_fck", "gpt3_fck"),
67 DT_CLK(NULL, "gpt4_ick", "gpt4_ick"),
68 DT_CLK(NULL, "gpt4_fck", "gpt4_fck"),
69 DT_CLK(NULL, "gpt5_ick", "gpt5_ick"),
70 DT_CLK(NULL, "gpt5_fck", "gpt5_fck"),
71 DT_CLK(NULL, "gpt6_ick", "gpt6_ick"),
72 DT_CLK(NULL, "gpt6_fck", "gpt6_fck"),
73 DT_CLK(NULL, "gpt7_ick", "gpt7_ick"),
74 DT_CLK(NULL, "gpt7_fck", "gpt7_fck"),
75 DT_CLK(NULL, "gpt8_ick", "gpt8_ick"),
76 DT_CLK(NULL, "gpt8_fck", "gpt8_fck"),
77 DT_CLK(NULL, "gpt9_ick", "gpt9_ick"),
78 DT_CLK(NULL, "gpt9_fck", "gpt9_fck"),
79 DT_CLK(NULL, "gpt10_ick", "gpt10_ick"),
80 DT_CLK(NULL, "gpt10_fck", "gpt10_fck"),
81 DT_CLK(NULL, "gpt11_ick", "gpt11_ick"),
82 DT_CLK(NULL, "gpt11_fck", "gpt11_fck"),
83 DT_CLK(NULL, "gpt12_ick", "gpt12_ick"),
84 DT_CLK(NULL, "gpt12_fck", "gpt12_fck"),
85 DT_CLK("omap-mcbsp.1", "ick", "mcbsp1_ick"),
86 DT_CLK(NULL, "mcbsp1_ick", "mcbsp1_ick"),
87 DT_CLK(NULL, "mcbsp1_fck", "mcbsp1_fck"),
88 DT_CLK("omap-mcbsp.2", "ick", "mcbsp2_ick"),
89 DT_CLK(NULL, "mcbsp2_ick", "mcbsp2_ick"),
90 DT_CLK(NULL, "mcbsp2_fck", "mcbsp2_fck"),
91 DT_CLK("omap2_mcspi.1", "ick", "mcspi1_ick"),
92 DT_CLK(NULL, "mcspi1_ick", "mcspi1_ick"),
93 DT_CLK(NULL, "mcspi1_fck", "mcspi1_fck"),
94 DT_CLK("omap2_mcspi.2", "ick", "mcspi2_ick"),
95 DT_CLK(NULL, "mcspi2_ick", "mcspi2_ick"),
96 DT_CLK(NULL, "mcspi2_fck", "mcspi2_fck"),
97 DT_CLK(NULL, "uart1_ick", "uart1_ick"),
98 DT_CLK(NULL, "uart1_fck", "uart1_fck"),
99 DT_CLK(NULL, "uart2_ick", "uart2_ick"),
100 DT_CLK(NULL, "uart2_fck", "uart2_fck"),
101 DT_CLK(NULL, "uart3_ick", "uart3_ick"),
102 DT_CLK(NULL, "uart3_fck", "uart3_fck"),
103 DT_CLK(NULL, "gpios_ick", "gpios_ick"),
104 DT_CLK(NULL, "gpios_fck", "gpios_fck"),
105 DT_CLK("omap_wdt", "ick", "mpu_wdt_ick"),
106 DT_CLK(NULL, "mpu_wdt_ick", "mpu_wdt_ick"),
107 DT_CLK(NULL, "mpu_wdt_fck", "mpu_wdt_fck"),
108 DT_CLK(NULL, "sync_32k_ick", "sync_32k_ick"),
109 DT_CLK(NULL, "wdt1_ick", "wdt1_ick"),
110 DT_CLK(NULL, "omapctrl_ick", "omapctrl_ick"),
111 DT_CLK("omap24xxcam", "fck", "cam_fck"),
112 DT_CLK(NULL, "cam_fck", "cam_fck"),
113 DT_CLK("omap24xxcam", "ick", "cam_ick"),
114 DT_CLK(NULL, "cam_ick", "cam_ick"),
115 DT_CLK(NULL, "mailboxes_ick", "mailboxes_ick"),
116 DT_CLK(NULL, "wdt4_ick", "wdt4_ick"),
117 DT_CLK(NULL, "wdt4_fck", "wdt4_fck"),
118 DT_CLK(NULL, "mspro_ick", "mspro_ick"),
119 DT_CLK(NULL, "mspro_fck", "mspro_fck"),
120 DT_CLK(NULL, "fac_ick", "fac_ick"),
121 DT_CLK(NULL, "fac_fck", "fac_fck"),
122 DT_CLK("omap_hdq.0", "ick", "hdq_ick"),
123 DT_CLK(NULL, "hdq_ick", "hdq_ick"),
124 DT_CLK("omap_hdq.0", "fck", "hdq_fck"),
125 DT_CLK(NULL, "hdq_fck", "hdq_fck"),
126 DT_CLK("omap_i2c.1", "ick", "i2c1_ick"),
127 DT_CLK(NULL, "i2c1_ick", "i2c1_ick"),
128 DT_CLK("omap_i2c.2", "ick", "i2c2_ick"),
129 DT_CLK(NULL, "i2c2_ick", "i2c2_ick"),
130 DT_CLK(NULL, "gpmc_fck", "gpmc_fck"),
131 DT_CLK(NULL, "sdma_fck", "sdma_fck"),
132 DT_CLK(NULL, "sdma_ick", "sdma_ick"),
133 DT_CLK(NULL, "sdrc_ick", "sdrc_ick"),
134 DT_CLK(NULL, "des_ick", "des_ick"),
135 DT_CLK("omap-sham", "ick", "sha_ick"),
136 DT_CLK(NULL, "sha_ick", "sha_ick"),
137 DT_CLK("omap_rng", "ick", "rng_ick"),
138 DT_CLK(NULL, "rng_ick", "rng_ick"),
139 DT_CLK("omap-aes", "ick", "aes_ick"),
140 DT_CLK(NULL, "aes_ick", "aes_ick"),
141 DT_CLK(NULL, "pka_ick", "pka_ick"),
142 DT_CLK(NULL, "usb_fck", "usb_fck"),
143 DT_CLK(NULL, "timer_32k_ck", "func_32k_ck"),
144 DT_CLK(NULL, "timer_sys_ck", "sys_ck"),
145 DT_CLK(NULL, "timer_ext_ck", "alt_ck"),
146 { .node_name = NULL },
147};
148
149static struct ti_dt_clk omap2420_clks[] = {
150 DT_CLK(NULL, "sys_clkout2_src", "sys_clkout2_src"),
151 DT_CLK(NULL, "sys_clkout2", "sys_clkout2"),
152 DT_CLK(NULL, "dsp_ick", "dsp_ick"),
153 DT_CLK(NULL, "iva1_ifck", "iva1_ifck"),
154 DT_CLK(NULL, "iva1_mpu_int_ifck", "iva1_mpu_int_ifck"),
155 DT_CLK(NULL, "wdt3_ick", "wdt3_ick"),
156 DT_CLK(NULL, "wdt3_fck", "wdt3_fck"),
157 DT_CLK("mmci-omap.0", "ick", "mmc_ick"),
158 DT_CLK(NULL, "mmc_ick", "mmc_ick"),
159 DT_CLK("mmci-omap.0", "fck", "mmc_fck"),
160 DT_CLK(NULL, "mmc_fck", "mmc_fck"),
161 DT_CLK(NULL, "eac_ick", "eac_ick"),
162 DT_CLK(NULL, "eac_fck", "eac_fck"),
163 DT_CLK(NULL, "i2c1_fck", "i2c1_fck"),
164 DT_CLK(NULL, "i2c2_fck", "i2c2_fck"),
165 DT_CLK(NULL, "vlynq_ick", "vlynq_ick"),
166 DT_CLK(NULL, "vlynq_fck", "vlynq_fck"),
167 DT_CLK("musb-hdrc", "fck", "osc_ck"),
168 { .node_name = NULL },
169};
170
171static struct ti_dt_clk omap2430_clks[] = {
172 DT_CLK("twl", "fck", "osc_ck"),
173 DT_CLK(NULL, "iva2_1_ick", "iva2_1_ick"),
174 DT_CLK(NULL, "mdm_ick", "mdm_ick"),
175 DT_CLK(NULL, "mdm_osc_ck", "mdm_osc_ck"),
176 DT_CLK("omap-mcbsp.3", "ick", "mcbsp3_ick"),
177 DT_CLK(NULL, "mcbsp3_ick", "mcbsp3_ick"),
178 DT_CLK(NULL, "mcbsp3_fck", "mcbsp3_fck"),
179 DT_CLK("omap-mcbsp.4", "ick", "mcbsp4_ick"),
180 DT_CLK(NULL, "mcbsp4_ick", "mcbsp4_ick"),
181 DT_CLK(NULL, "mcbsp4_fck", "mcbsp4_fck"),
182 DT_CLK("omap-mcbsp.5", "ick", "mcbsp5_ick"),
183 DT_CLK(NULL, "mcbsp5_ick", "mcbsp5_ick"),
184 DT_CLK(NULL, "mcbsp5_fck", "mcbsp5_fck"),
185 DT_CLK("omap2_mcspi.3", "ick", "mcspi3_ick"),
186 DT_CLK(NULL, "mcspi3_ick", "mcspi3_ick"),
187 DT_CLK(NULL, "mcspi3_fck", "mcspi3_fck"),
188 DT_CLK(NULL, "icr_ick", "icr_ick"),
189 DT_CLK(NULL, "i2chs1_fck", "i2chs1_fck"),
190 DT_CLK(NULL, "i2chs2_fck", "i2chs2_fck"),
191 DT_CLK("musb-omap2430", "ick", "usbhs_ick"),
192 DT_CLK(NULL, "usbhs_ick", "usbhs_ick"),
193 DT_CLK("omap_hsmmc.0", "ick", "mmchs1_ick"),
194 DT_CLK(NULL, "mmchs1_ick", "mmchs1_ick"),
195 DT_CLK(NULL, "mmchs1_fck", "mmchs1_fck"),
196 DT_CLK("omap_hsmmc.1", "ick", "mmchs2_ick"),
197 DT_CLK(NULL, "mmchs2_ick", "mmchs2_ick"),
198 DT_CLK(NULL, "mmchs2_fck", "mmchs2_fck"),
199 DT_CLK(NULL, "gpio5_ick", "gpio5_ick"),
200 DT_CLK(NULL, "gpio5_fck", "gpio5_fck"),
201 DT_CLK(NULL, "mdm_intc_ick", "mdm_intc_ick"),
202 DT_CLK("omap_hsmmc.0", "mmchsdb_fck", "mmchsdb1_fck"),
203 DT_CLK(NULL, "mmchsdb1_fck", "mmchsdb1_fck"),
204 DT_CLK("omap_hsmmc.1", "mmchsdb_fck", "mmchsdb2_fck"),
205 DT_CLK(NULL, "mmchsdb2_fck", "mmchsdb2_fck"),
206 { .node_name = NULL },
207};
208
209static const char *enable_init_clks[] = {
210 "apll96_ck",
211 "apll54_ck",
212 "sync_32k_ick",
213 "omapctrl_ick",
214 "gpmc_fck",
215 "sdrc_ick",
216};
217
218enum {
219 OMAP2_SOC_OMAP2420,
220 OMAP2_SOC_OMAP2430,
221};
222
223static int __init omap2xxx_dt_clk_init(int soc_type)
224{
225 ti_dt_clocks_register(omap2xxx_clks);
226
227 if (soc_type == OMAP2_SOC_OMAP2420)
228 ti_dt_clocks_register(omap2420_clks);
229 else
230 ti_dt_clocks_register(omap2430_clks);
231
232 omap2xxx_clkt_vps_init();
233
234 omap2_clk_disable_autoidle_all();
235
236 omap2_clk_enable_init_clocks(enable_init_clks,
237 ARRAY_SIZE(enable_init_clks));
238
239 pr_info("Clocking rate (Crystal/DPLL/MPU): %ld.%01ld/%ld/%ld MHz\n",
240 (clk_get_rate(clk_get_sys(NULL, "sys_ck")) / 1000000),
241 (clk_get_rate(clk_get_sys(NULL, "sys_ck")) / 100000) % 10,
242 (clk_get_rate(clk_get_sys(NULL, "dpll_ck")) / 1000000),
243 (clk_get_rate(clk_get_sys(NULL, "mpu_ck")) / 1000000));
244
245 return 0;
246}
247
248int __init omap2420_dt_clk_init(void)
249{
250 return omap2xxx_dt_clk_init(OMAP2_SOC_OMAP2420);
251}
252
253int __init omap2430_dt_clk_init(void)
254{
255 return omap2xxx_dt_clk_init(OMAP2_SOC_OMAP2430);
256}
diff --git a/drivers/clk/ti/clk-54xx.c b/drivers/clk/ti/clk-54xx.c
index 08f3d1b915b3..5e183993e3ec 100644
--- a/drivers/clk/ti/clk-54xx.c
+++ b/drivers/clk/ti/clk-54xx.c
@@ -240,6 +240,12 @@ int __init omap5xxx_dt_clk_init(void)
240 if (rc) 240 if (rc)
241 pr_err("%s: failed to configure ABE DPLL!\n", __func__); 241 pr_err("%s: failed to configure ABE DPLL!\n", __func__);
242 242
243 abe_dpll = clk_get_sys(NULL, "dpll_abe_m2x2_ck");
244 if (!rc)
245 rc = clk_set_rate(abe_dpll, OMAP5_DPLL_ABE_DEFFREQ * 2);
246 if (rc)
247 pr_err("%s: failed to configure ABE m2x2 DPLL!\n", __func__);
248
243 usb_dpll = clk_get_sys(NULL, "dpll_usb_ck"); 249 usb_dpll = clk_get_sys(NULL, "dpll_usb_ck");
244 rc = clk_set_rate(usb_dpll, OMAP5_DPLL_USB_DEFFREQ); 250 rc = clk_set_rate(usb_dpll, OMAP5_DPLL_USB_DEFFREQ);
245 if (rc) 251 if (rc)
diff --git a/drivers/clk/ti/clk-7xx.c b/drivers/clk/ti/clk-7xx.c
index f7e40734c819..e1581335937d 100644
--- a/drivers/clk/ti/clk-7xx.c
+++ b/drivers/clk/ti/clk-7xx.c
@@ -24,7 +24,7 @@ static struct ti_dt_clk dra7xx_clks[] = {
24 DT_CLK(NULL, "atl_clkin0_ck", "atl_clkin0_ck"), 24 DT_CLK(NULL, "atl_clkin0_ck", "atl_clkin0_ck"),
25 DT_CLK(NULL, "atl_clkin1_ck", "atl_clkin1_ck"), 25 DT_CLK(NULL, "atl_clkin1_ck", "atl_clkin1_ck"),
26 DT_CLK(NULL, "atl_clkin2_ck", "atl_clkin2_ck"), 26 DT_CLK(NULL, "atl_clkin2_ck", "atl_clkin2_ck"),
27 DT_CLK(NULL, "atlclkin3_ck", "atlclkin3_ck"), 27 DT_CLK(NULL, "atl_clkin3_ck", "atl_clkin3_ck"),
28 DT_CLK(NULL, "hdmi_clkin_ck", "hdmi_clkin_ck"), 28 DT_CLK(NULL, "hdmi_clkin_ck", "hdmi_clkin_ck"),
29 DT_CLK(NULL, "mlb_clkin_ck", "mlb_clkin_ck"), 29 DT_CLK(NULL, "mlb_clkin_ck", "mlb_clkin_ck"),
30 DT_CLK(NULL, "mlbp_clkin_ck", "mlbp_clkin_ck"), 30 DT_CLK(NULL, "mlbp_clkin_ck", "mlbp_clkin_ck"),
diff --git a/drivers/clk/ti/clk-dra7-atl.c b/drivers/clk/ti/clk-dra7-atl.c
new file mode 100644
index 000000000000..4a65b410e4d5
--- /dev/null
+++ b/drivers/clk/ti/clk-dra7-atl.c
@@ -0,0 +1,312 @@
1/*
2 * DRA7 ATL (Audio Tracking Logic) clock driver
3 *
4 * Copyright (C) 2013 Texas Instruments, Inc.
5 *
6 * Peter Ujfalusi <peter.ujfalusi@ti.com>
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 version 2 as
10 * published by the Free Software Foundation.
11 *
12 * This program is distributed "as is" WITHOUT ANY WARRANTY of any
13 * kind, whether express or implied; without even the implied warranty
14 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 */
17
18#include <linux/module.h>
19#include <linux/clk-provider.h>
20#include <linux/slab.h>
21#include <linux/io.h>
22#include <linux/of.h>
23#include <linux/of_address.h>
24#include <linux/platform_device.h>
25#include <linux/pm_runtime.h>
26
27#define DRA7_ATL_INSTANCES 4
28
29#define DRA7_ATL_PPMR_REG(id) (0x200 + (id * 0x80))
30#define DRA7_ATL_BBSR_REG(id) (0x204 + (id * 0x80))
31#define DRA7_ATL_ATLCR_REG(id) (0x208 + (id * 0x80))
32#define DRA7_ATL_SWEN_REG(id) (0x210 + (id * 0x80))
33#define DRA7_ATL_BWSMUX_REG(id) (0x214 + (id * 0x80))
34#define DRA7_ATL_AWSMUX_REG(id) (0x218 + (id * 0x80))
35#define DRA7_ATL_PCLKMUX_REG(id) (0x21c + (id * 0x80))
36
37#define DRA7_ATL_SWEN BIT(0)
38#define DRA7_ATL_DIVIDER_MASK (0x1f)
39#define DRA7_ATL_PCLKMUX BIT(0)
40struct dra7_atl_clock_info;
41
42struct dra7_atl_desc {
43 struct clk *clk;
44 struct clk_hw hw;
45 struct dra7_atl_clock_info *cinfo;
46 int id;
47
48 bool probed; /* the driver for the IP has been loaded */
49 bool valid; /* configured */
50 bool enabled;
51 u32 bws; /* Baseband Word Select Mux */
52 u32 aws; /* Audio Word Select Mux */
53 u32 divider; /* Cached divider value */
54};
55
56struct dra7_atl_clock_info {
57 struct device *dev;
58 void __iomem *iobase;
59
60 struct dra7_atl_desc *cdesc;
61};
62
63#define to_atl_desc(_hw) container_of(_hw, struct dra7_atl_desc, hw)
64
65static inline void atl_write(struct dra7_atl_clock_info *cinfo, u32 reg,
66 u32 val)
67{
68 __raw_writel(val, cinfo->iobase + reg);
69}
70
71static inline int atl_read(struct dra7_atl_clock_info *cinfo, u32 reg)
72{
73 return __raw_readl(cinfo->iobase + reg);
74}
75
76static int atl_clk_enable(struct clk_hw *hw)
77{
78 struct dra7_atl_desc *cdesc = to_atl_desc(hw);
79
80 if (!cdesc->probed)
81 goto out;
82
83 if (unlikely(!cdesc->valid))
84 dev_warn(cdesc->cinfo->dev, "atl%d has not been configured\n",
85 cdesc->id);
86 pm_runtime_get_sync(cdesc->cinfo->dev);
87
88 atl_write(cdesc->cinfo, DRA7_ATL_ATLCR_REG(cdesc->id),
89 cdesc->divider - 1);
90 atl_write(cdesc->cinfo, DRA7_ATL_SWEN_REG(cdesc->id), DRA7_ATL_SWEN);
91
92out:
93 cdesc->enabled = true;
94
95 return 0;
96}
97
98static void atl_clk_disable(struct clk_hw *hw)
99{
100 struct dra7_atl_desc *cdesc = to_atl_desc(hw);
101
102 if (!cdesc->probed)
103 goto out;
104
105 atl_write(cdesc->cinfo, DRA7_ATL_SWEN_REG(cdesc->id), 0);
106 pm_runtime_put_sync(cdesc->cinfo->dev);
107
108out:
109 cdesc->enabled = false;
110}
111
112static int atl_clk_is_enabled(struct clk_hw *hw)
113{
114 struct dra7_atl_desc *cdesc = to_atl_desc(hw);
115
116 return cdesc->enabled;
117}
118
119static unsigned long atl_clk_recalc_rate(struct clk_hw *hw,
120 unsigned long parent_rate)
121{
122 struct dra7_atl_desc *cdesc = to_atl_desc(hw);
123
124 return parent_rate / cdesc->divider;
125}
126
127static long atl_clk_round_rate(struct clk_hw *hw, unsigned long rate,
128 unsigned long *parent_rate)
129{
130 unsigned divider;
131
132 divider = (*parent_rate + rate / 2) / rate;
133 if (divider > DRA7_ATL_DIVIDER_MASK + 1)
134 divider = DRA7_ATL_DIVIDER_MASK + 1;
135
136 return *parent_rate / divider;
137}
138
139static int atl_clk_set_rate(struct clk_hw *hw, unsigned long rate,
140 unsigned long parent_rate)
141{
142 struct dra7_atl_desc *cdesc = to_atl_desc(hw);
143 u32 divider;
144
145 divider = ((parent_rate + rate / 2) / rate) - 1;
146 if (divider > DRA7_ATL_DIVIDER_MASK)
147 divider = DRA7_ATL_DIVIDER_MASK;
148
149 cdesc->divider = divider + 1;
150
151 return 0;
152}
153
154const struct clk_ops atl_clk_ops = {
155 .enable = atl_clk_enable,
156 .disable = atl_clk_disable,
157 .is_enabled = atl_clk_is_enabled,
158 .recalc_rate = atl_clk_recalc_rate,
159 .round_rate = atl_clk_round_rate,
160 .set_rate = atl_clk_set_rate,
161};
162
163static void __init of_dra7_atl_clock_setup(struct device_node *node)
164{
165 struct dra7_atl_desc *clk_hw = NULL;
166 struct clk_init_data init = { 0 };
167 const char **parent_names = NULL;
168 struct clk *clk;
169
170 clk_hw = kzalloc(sizeof(*clk_hw), GFP_KERNEL);
171 if (!clk_hw) {
172 pr_err("%s: could not allocate dra7_atl_desc\n", __func__);
173 return;
174 }
175
176 clk_hw->hw.init = &init;
177 clk_hw->divider = 1;
178 init.name = node->name;
179 init.ops = &atl_clk_ops;
180 init.flags = CLK_IGNORE_UNUSED;
181 init.num_parents = of_clk_get_parent_count(node);
182
183 if (init.num_parents != 1) {
184 pr_err("%s: atl clock %s must have 1 parent\n", __func__,
185 node->name);
186 goto cleanup;
187 }
188
189 parent_names = kzalloc(sizeof(char *), GFP_KERNEL);
190
191 if (!parent_names)
192 goto cleanup;
193
194 parent_names[0] = of_clk_get_parent_name(node, 0);
195
196 init.parent_names = parent_names;
197
198 clk = clk_register(NULL, &clk_hw->hw);
199
200 if (!IS_ERR(clk)) {
201 of_clk_add_provider(node, of_clk_src_simple_get, clk);
202 return;
203 }
204cleanup:
205 kfree(parent_names);
206 kfree(clk_hw);
207}
208CLK_OF_DECLARE(dra7_atl_clock, "ti,dra7-atl-clock", of_dra7_atl_clock_setup);
209
210static int of_dra7_atl_clk_probe(struct platform_device *pdev)
211{
212 struct device_node *node = pdev->dev.of_node;
213 struct dra7_atl_clock_info *cinfo;
214 int i;
215 int ret = 0;
216
217 if (!node)
218 return -ENODEV;
219
220 cinfo = devm_kzalloc(&pdev->dev, sizeof(*cinfo), GFP_KERNEL);
221 if (!cinfo)
222 return -ENOMEM;
223
224 cinfo->iobase = of_iomap(node, 0);
225 cinfo->dev = &pdev->dev;
226 pm_runtime_enable(cinfo->dev);
227
228 pm_runtime_get_sync(cinfo->dev);
229 atl_write(cinfo, DRA7_ATL_PCLKMUX_REG(0), DRA7_ATL_PCLKMUX);
230
231 for (i = 0; i < DRA7_ATL_INSTANCES; i++) {
232 struct device_node *cfg_node;
233 char prop[5];
234 struct dra7_atl_desc *cdesc;
235 struct of_phandle_args clkspec;
236 struct clk *clk;
237 int rc;
238
239 rc = of_parse_phandle_with_args(node, "ti,provided-clocks",
240 NULL, i, &clkspec);
241
242 if (rc) {
243 pr_err("%s: failed to lookup atl clock %d\n", __func__,
244 i);
245 return -EINVAL;
246 }
247
248 clk = of_clk_get_from_provider(&clkspec);
249
250 cdesc = to_atl_desc(__clk_get_hw(clk));
251 cdesc->cinfo = cinfo;
252 cdesc->id = i;
253
254 /* Get configuration for the ATL instances */
255 snprintf(prop, sizeof(prop), "atl%u", i);
256 cfg_node = of_find_node_by_name(node, prop);
257 if (cfg_node) {
258 ret = of_property_read_u32(cfg_node, "bws",
259 &cdesc->bws);
260 ret |= of_property_read_u32(cfg_node, "aws",
261 &cdesc->aws);
262 if (!ret) {
263 cdesc->valid = true;
264 atl_write(cinfo, DRA7_ATL_BWSMUX_REG(i),
265 cdesc->bws);
266 atl_write(cinfo, DRA7_ATL_AWSMUX_REG(i),
267 cdesc->aws);
268 }
269 }
270
271 cdesc->probed = true;
272 /*
273 * Enable the clock if it has been asked prior to loading the
274 * hw driver
275 */
276 if (cdesc->enabled)
277 atl_clk_enable(__clk_get_hw(clk));
278 }
279 pm_runtime_put_sync(cinfo->dev);
280
281 return ret;
282}
283
284static int of_dra7_atl_clk_remove(struct platform_device *pdev)
285{
286 pm_runtime_disable(&pdev->dev);
287
288 return 0;
289}
290
291static struct of_device_id of_dra7_atl_clk_match_tbl[] = {
292 { .compatible = "ti,dra7-atl", },
293 {},
294};
295MODULE_DEVICE_TABLE(of, of_dra7_atl_clk_match_tbl);
296
297static struct platform_driver dra7_atl_clk_driver = {
298 .driver = {
299 .name = "dra7-atl",
300 .owner = THIS_MODULE,
301 .of_match_table = of_dra7_atl_clk_match_tbl,
302 },
303 .probe = of_dra7_atl_clk_probe,
304 .remove = of_dra7_atl_clk_remove,
305};
306
307module_platform_driver(dra7_atl_clk_driver);
308
309MODULE_DESCRIPTION("Clock driver for DRA7 Audio Tracking Logic");
310MODULE_ALIAS("platform:dra7-atl-clock");
311MODULE_AUTHOR("Peter Ujfalusi <peter.ujfalusi@ti.com>");
312MODULE_LICENSE("GPL v2");
diff --git a/drivers/clk/ti/dpll.c b/drivers/clk/ti/dpll.c
index 7e498a44f97d..abd956d5f838 100644
--- a/drivers/clk/ti/dpll.c
+++ b/drivers/clk/ti/dpll.c
@@ -25,8 +25,6 @@
25#undef pr_fmt 25#undef pr_fmt
26#define pr_fmt(fmt) "%s: " fmt, __func__ 26#define pr_fmt(fmt) "%s: " fmt, __func__
27 27
28#define DPLL_HAS_AUTOIDLE 0x1
29
30#if defined(CONFIG_ARCH_OMAP4) || defined(CONFIG_SOC_OMAP5) || \ 28#if defined(CONFIG_ARCH_OMAP4) || defined(CONFIG_SOC_OMAP5) || \
31 defined(CONFIG_SOC_DRA7XX) 29 defined(CONFIG_SOC_DRA7XX)
32static const struct clk_ops dpll_m4xen_ck_ops = { 30static const struct clk_ops dpll_m4xen_ck_ops = {
@@ -37,21 +35,18 @@ static const struct clk_ops dpll_m4xen_ck_ops = {
37 .set_rate = &omap3_noncore_dpll_set_rate, 35 .set_rate = &omap3_noncore_dpll_set_rate,
38 .get_parent = &omap2_init_dpll_parent, 36 .get_parent = &omap2_init_dpll_parent,
39}; 37};
38#else
39static const struct clk_ops dpll_m4xen_ck_ops = {};
40#endif 40#endif
41 41
42#if defined(CONFIG_ARCH_OMAP3) || defined(CONFIG_ARCH_OMAP4) || \
43 defined(CONFIG_SOC_OMAP5) || defined(CONFIG_SOC_DRA7XX) || \
44 defined(CONFIG_SOC_AM33XX) || defined(CONFIG_SOC_AM43XX)
42static const struct clk_ops dpll_core_ck_ops = { 45static const struct clk_ops dpll_core_ck_ops = {
43 .recalc_rate = &omap3_dpll_recalc, 46 .recalc_rate = &omap3_dpll_recalc,
44 .get_parent = &omap2_init_dpll_parent, 47 .get_parent = &omap2_init_dpll_parent,
45}; 48};
46 49
47#ifdef CONFIG_ARCH_OMAP3
48static const struct clk_ops omap3_dpll_core_ck_ops = {
49 .get_parent = &omap2_init_dpll_parent,
50 .recalc_rate = &omap3_dpll_recalc,
51 .round_rate = &omap2_dpll_round_rate,
52};
53#endif
54
55static const struct clk_ops dpll_ck_ops = { 50static const struct clk_ops dpll_ck_ops = {
56 .enable = &omap3_noncore_dpll_enable, 51 .enable = &omap3_noncore_dpll_enable,
57 .disable = &omap3_noncore_dpll_disable, 52 .disable = &omap3_noncore_dpll_disable,
@@ -67,6 +62,33 @@ static const struct clk_ops dpll_no_gate_ck_ops = {
67 .round_rate = &omap2_dpll_round_rate, 62 .round_rate = &omap2_dpll_round_rate,
68 .set_rate = &omap3_noncore_dpll_set_rate, 63 .set_rate = &omap3_noncore_dpll_set_rate,
69}; 64};
65#else
66static const struct clk_ops dpll_core_ck_ops = {};
67static const struct clk_ops dpll_ck_ops = {};
68static const struct clk_ops dpll_no_gate_ck_ops = {};
69const struct clk_hw_omap_ops clkhwops_omap3_dpll = {};
70#endif
71
72#ifdef CONFIG_ARCH_OMAP2
73static const struct clk_ops omap2_dpll_core_ck_ops = {
74 .get_parent = &omap2_init_dpll_parent,
75 .recalc_rate = &omap2_dpllcore_recalc,
76 .round_rate = &omap2_dpll_round_rate,
77 .set_rate = &omap2_reprogram_dpllcore,
78};
79#else
80static const struct clk_ops omap2_dpll_core_ck_ops = {};
81#endif
82
83#ifdef CONFIG_ARCH_OMAP3
84static const struct clk_ops omap3_dpll_core_ck_ops = {
85 .get_parent = &omap2_init_dpll_parent,
86 .recalc_rate = &omap3_dpll_recalc,
87 .round_rate = &omap2_dpll_round_rate,
88};
89#else
90static const struct clk_ops omap3_dpll_core_ck_ops = {};
91#endif
70 92
71#ifdef CONFIG_ARCH_OMAP3 93#ifdef CONFIG_ARCH_OMAP3
72static const struct clk_ops omap3_dpll_ck_ops = { 94static const struct clk_ops omap3_dpll_ck_ops = {
@@ -193,14 +215,12 @@ static void ti_clk_register_dpll_x2(struct device_node *node,
193 * @node: device node containing the DPLL info 215 * @node: device node containing the DPLL info
194 * @ops: ops for the DPLL 216 * @ops: ops for the DPLL
195 * @ddt: DPLL data template to use 217 * @ddt: DPLL data template to use
196 * @init_flags: flags for controlling init types
197 * 218 *
198 * Initializes a DPLL clock from device tree data. 219 * Initializes a DPLL clock from device tree data.
199 */ 220 */
200static void __init of_ti_dpll_setup(struct device_node *node, 221static void __init of_ti_dpll_setup(struct device_node *node,
201 const struct clk_ops *ops, 222 const struct clk_ops *ops,
202 const struct dpll_data *ddt, 223 const struct dpll_data *ddt)
203 u8 init_flags)
204{ 224{
205 struct clk_hw_omap *clk_hw = NULL; 225 struct clk_hw_omap *clk_hw = NULL;
206 struct clk_init_data *init = NULL; 226 struct clk_init_data *init = NULL;
@@ -241,13 +261,30 @@ static void __init of_ti_dpll_setup(struct device_node *node,
241 init->parent_names = parent_names; 261 init->parent_names = parent_names;
242 262
243 dd->control_reg = ti_clk_get_reg_addr(node, 0); 263 dd->control_reg = ti_clk_get_reg_addr(node, 0);
244 dd->idlest_reg = ti_clk_get_reg_addr(node, 1);
245 dd->mult_div1_reg = ti_clk_get_reg_addr(node, 2);
246 264
247 if (!dd->control_reg || !dd->idlest_reg || !dd->mult_div1_reg) 265 /*
266 * Special case for OMAP2 DPLL, register order is different due to
267 * missing idlest_reg, also clkhwops is different. Detected from
268 * missing idlest_mask.
269 */
270 if (!dd->idlest_mask) {
271 dd->mult_div1_reg = ti_clk_get_reg_addr(node, 1);
272#ifdef CONFIG_ARCH_OMAP2
273 clk_hw->ops = &clkhwops_omap2xxx_dpll;
274 omap2xxx_clkt_dpllcore_init(&clk_hw->hw);
275#endif
276 } else {
277 dd->idlest_reg = ti_clk_get_reg_addr(node, 1);
278 if (!dd->idlest_reg)
279 goto cleanup;
280
281 dd->mult_div1_reg = ti_clk_get_reg_addr(node, 2);
282 }
283
284 if (!dd->control_reg || !dd->mult_div1_reg)
248 goto cleanup; 285 goto cleanup;
249 286
250 if (init_flags & DPLL_HAS_AUTOIDLE) { 287 if (dd->autoidle_mask) {
251 dd->autoidle_reg = ti_clk_get_reg_addr(node, 3); 288 dd->autoidle_reg = ti_clk_get_reg_addr(node, 3);
252 if (!dd->autoidle_reg) 289 if (!dd->autoidle_reg)
253 goto cleanup; 290 goto cleanup;
@@ -310,7 +347,7 @@ static void __init of_ti_omap3_dpll_setup(struct device_node *node)
310 .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED), 347 .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
311 }; 348 };
312 349
313 of_ti_dpll_setup(node, &omap3_dpll_ck_ops, &dd, DPLL_HAS_AUTOIDLE); 350 of_ti_dpll_setup(node, &omap3_dpll_ck_ops, &dd);
314} 351}
315CLK_OF_DECLARE(ti_omap3_dpll_clock, "ti,omap3-dpll-clock", 352CLK_OF_DECLARE(ti_omap3_dpll_clock, "ti,omap3-dpll-clock",
316 of_ti_omap3_dpll_setup); 353 of_ti_omap3_dpll_setup);
@@ -329,7 +366,7 @@ static void __init of_ti_omap3_core_dpll_setup(struct device_node *node)
329 .freqsel_mask = 0xf0, 366 .freqsel_mask = 0xf0,
330 }; 367 };
331 368
332 of_ti_dpll_setup(node, &omap3_dpll_core_ck_ops, &dd, DPLL_HAS_AUTOIDLE); 369 of_ti_dpll_setup(node, &omap3_dpll_core_ck_ops, &dd);
333} 370}
334CLK_OF_DECLARE(ti_omap3_core_dpll_clock, "ti,omap3-dpll-core-clock", 371CLK_OF_DECLARE(ti_omap3_core_dpll_clock, "ti,omap3-dpll-core-clock",
335 of_ti_omap3_core_dpll_setup); 372 of_ti_omap3_core_dpll_setup);
@@ -349,7 +386,7 @@ static void __init of_ti_omap3_per_dpll_setup(struct device_node *node)
349 .modes = (1 << DPLL_LOW_POWER_STOP) | (1 << DPLL_LOCKED), 386 .modes = (1 << DPLL_LOW_POWER_STOP) | (1 << DPLL_LOCKED),
350 }; 387 };
351 388
352 of_ti_dpll_setup(node, &omap3_dpll_per_ck_ops, &dd, DPLL_HAS_AUTOIDLE); 389 of_ti_dpll_setup(node, &omap3_dpll_per_ck_ops, &dd);
353} 390}
354CLK_OF_DECLARE(ti_omap3_per_dpll_clock, "ti,omap3-dpll-per-clock", 391CLK_OF_DECLARE(ti_omap3_per_dpll_clock, "ti,omap3-dpll-per-clock",
355 of_ti_omap3_per_dpll_setup); 392 of_ti_omap3_per_dpll_setup);
@@ -371,7 +408,7 @@ static void __init of_ti_omap3_per_jtype_dpll_setup(struct device_node *node)
371 .modes = (1 << DPLL_LOW_POWER_STOP) | (1 << DPLL_LOCKED), 408 .modes = (1 << DPLL_LOW_POWER_STOP) | (1 << DPLL_LOCKED),
372 }; 409 };
373 410
374 of_ti_dpll_setup(node, &omap3_dpll_per_ck_ops, &dd, DPLL_HAS_AUTOIDLE); 411 of_ti_dpll_setup(node, &omap3_dpll_per_ck_ops, &dd);
375} 412}
376CLK_OF_DECLARE(ti_omap3_per_jtype_dpll_clock, "ti,omap3-dpll-per-j-type-clock", 413CLK_OF_DECLARE(ti_omap3_per_jtype_dpll_clock, "ti,omap3-dpll-per-j-type-clock",
377 of_ti_omap3_per_jtype_dpll_setup); 414 of_ti_omap3_per_jtype_dpll_setup);
@@ -391,11 +428,32 @@ static void __init of_ti_omap4_dpll_setup(struct device_node *node)
391 .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED), 428 .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
392 }; 429 };
393 430
394 of_ti_dpll_setup(node, &dpll_ck_ops, &dd, DPLL_HAS_AUTOIDLE); 431 of_ti_dpll_setup(node, &dpll_ck_ops, &dd);
395} 432}
396CLK_OF_DECLARE(ti_omap4_dpll_clock, "ti,omap4-dpll-clock", 433CLK_OF_DECLARE(ti_omap4_dpll_clock, "ti,omap4-dpll-clock",
397 of_ti_omap4_dpll_setup); 434 of_ti_omap4_dpll_setup);
398 435
436static void __init of_ti_omap5_mpu_dpll_setup(struct device_node *node)
437{
438 const struct dpll_data dd = {
439 .idlest_mask = 0x1,
440 .enable_mask = 0x7,
441 .autoidle_mask = 0x7,
442 .mult_mask = 0x7ff << 8,
443 .div1_mask = 0x7f,
444 .max_multiplier = 2047,
445 .max_divider = 128,
446 .dcc_mask = BIT(22),
447 .dcc_rate = 1400000000, /* DCC beyond 1.4GHz */
448 .min_divider = 1,
449 .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
450 };
451
452 of_ti_dpll_setup(node, &dpll_ck_ops, &dd);
453}
454CLK_OF_DECLARE(of_ti_omap5_mpu_dpll_clock, "ti,omap5-mpu-dpll-clock",
455 of_ti_omap5_mpu_dpll_setup);
456
399static void __init of_ti_omap4_core_dpll_setup(struct device_node *node) 457static void __init of_ti_omap4_core_dpll_setup(struct device_node *node)
400{ 458{
401 const struct dpll_data dd = { 459 const struct dpll_data dd = {
@@ -410,7 +468,7 @@ static void __init of_ti_omap4_core_dpll_setup(struct device_node *node)
410 .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED), 468 .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
411 }; 469 };
412 470
413 of_ti_dpll_setup(node, &dpll_core_ck_ops, &dd, DPLL_HAS_AUTOIDLE); 471 of_ti_dpll_setup(node, &dpll_core_ck_ops, &dd);
414} 472}
415CLK_OF_DECLARE(ti_omap4_core_dpll_clock, "ti,omap4-dpll-core-clock", 473CLK_OF_DECLARE(ti_omap4_core_dpll_clock, "ti,omap4-dpll-core-clock",
416 of_ti_omap4_core_dpll_setup); 474 of_ti_omap4_core_dpll_setup);
@@ -433,7 +491,7 @@ static void __init of_ti_omap4_m4xen_dpll_setup(struct device_node *node)
433 .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED), 491 .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
434 }; 492 };
435 493
436 of_ti_dpll_setup(node, &dpll_m4xen_ck_ops, &dd, DPLL_HAS_AUTOIDLE); 494 of_ti_dpll_setup(node, &dpll_m4xen_ck_ops, &dd);
437} 495}
438CLK_OF_DECLARE(ti_omap4_m4xen_dpll_clock, "ti,omap4-dpll-m4xen-clock", 496CLK_OF_DECLARE(ti_omap4_m4xen_dpll_clock, "ti,omap4-dpll-m4xen-clock",
439 of_ti_omap4_m4xen_dpll_setup); 497 of_ti_omap4_m4xen_dpll_setup);
@@ -454,7 +512,7 @@ static void __init of_ti_omap4_jtype_dpll_setup(struct device_node *node)
454 .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED), 512 .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
455 }; 513 };
456 514
457 of_ti_dpll_setup(node, &dpll_m4xen_ck_ops, &dd, DPLL_HAS_AUTOIDLE); 515 of_ti_dpll_setup(node, &dpll_m4xen_ck_ops, &dd);
458} 516}
459CLK_OF_DECLARE(ti_omap4_jtype_dpll_clock, "ti,omap4-dpll-j-type-clock", 517CLK_OF_DECLARE(ti_omap4_jtype_dpll_clock, "ti,omap4-dpll-j-type-clock",
460 of_ti_omap4_jtype_dpll_setup); 518 of_ti_omap4_jtype_dpll_setup);
@@ -465,7 +523,6 @@ static void __init of_ti_am3_no_gate_dpll_setup(struct device_node *node)
465 const struct dpll_data dd = { 523 const struct dpll_data dd = {
466 .idlest_mask = 0x1, 524 .idlest_mask = 0x1,
467 .enable_mask = 0x7, 525 .enable_mask = 0x7,
468 .autoidle_mask = 0x7,
469 .mult_mask = 0x7ff << 8, 526 .mult_mask = 0x7ff << 8,
470 .div1_mask = 0x7f, 527 .div1_mask = 0x7f,
471 .max_multiplier = 2047, 528 .max_multiplier = 2047,
@@ -474,7 +531,7 @@ static void __init of_ti_am3_no_gate_dpll_setup(struct device_node *node)
474 .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED), 531 .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
475 }; 532 };
476 533
477 of_ti_dpll_setup(node, &dpll_no_gate_ck_ops, &dd, 0); 534 of_ti_dpll_setup(node, &dpll_no_gate_ck_ops, &dd);
478} 535}
479CLK_OF_DECLARE(ti_am3_no_gate_dpll_clock, "ti,am3-dpll-no-gate-clock", 536CLK_OF_DECLARE(ti_am3_no_gate_dpll_clock, "ti,am3-dpll-no-gate-clock",
480 of_ti_am3_no_gate_dpll_setup); 537 of_ti_am3_no_gate_dpll_setup);
@@ -484,7 +541,6 @@ static void __init of_ti_am3_jtype_dpll_setup(struct device_node *node)
484 const struct dpll_data dd = { 541 const struct dpll_data dd = {
485 .idlest_mask = 0x1, 542 .idlest_mask = 0x1,
486 .enable_mask = 0x7, 543 .enable_mask = 0x7,
487 .autoidle_mask = 0x7,
488 .mult_mask = 0x7ff << 8, 544 .mult_mask = 0x7ff << 8,
489 .div1_mask = 0x7f, 545 .div1_mask = 0x7f,
490 .max_multiplier = 4095, 546 .max_multiplier = 4095,
@@ -494,7 +550,7 @@ static void __init of_ti_am3_jtype_dpll_setup(struct device_node *node)
494 .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED), 550 .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
495 }; 551 };
496 552
497 of_ti_dpll_setup(node, &dpll_ck_ops, &dd, 0); 553 of_ti_dpll_setup(node, &dpll_ck_ops, &dd);
498} 554}
499CLK_OF_DECLARE(ti_am3_jtype_dpll_clock, "ti,am3-dpll-j-type-clock", 555CLK_OF_DECLARE(ti_am3_jtype_dpll_clock, "ti,am3-dpll-j-type-clock",
500 of_ti_am3_jtype_dpll_setup); 556 of_ti_am3_jtype_dpll_setup);
@@ -504,7 +560,6 @@ static void __init of_ti_am3_no_gate_jtype_dpll_setup(struct device_node *node)
504 const struct dpll_data dd = { 560 const struct dpll_data dd = {
505 .idlest_mask = 0x1, 561 .idlest_mask = 0x1,
506 .enable_mask = 0x7, 562 .enable_mask = 0x7,
507 .autoidle_mask = 0x7,
508 .mult_mask = 0x7ff << 8, 563 .mult_mask = 0x7ff << 8,
509 .div1_mask = 0x7f, 564 .div1_mask = 0x7f,
510 .max_multiplier = 2047, 565 .max_multiplier = 2047,
@@ -514,7 +569,7 @@ static void __init of_ti_am3_no_gate_jtype_dpll_setup(struct device_node *node)
514 .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED), 569 .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
515 }; 570 };
516 571
517 of_ti_dpll_setup(node, &dpll_no_gate_ck_ops, &dd, 0); 572 of_ti_dpll_setup(node, &dpll_no_gate_ck_ops, &dd);
518} 573}
519CLK_OF_DECLARE(ti_am3_no_gate_jtype_dpll_clock, 574CLK_OF_DECLARE(ti_am3_no_gate_jtype_dpll_clock,
520 "ti,am3-dpll-no-gate-j-type-clock", 575 "ti,am3-dpll-no-gate-j-type-clock",
@@ -525,7 +580,6 @@ static void __init of_ti_am3_dpll_setup(struct device_node *node)
525 const struct dpll_data dd = { 580 const struct dpll_data dd = {
526 .idlest_mask = 0x1, 581 .idlest_mask = 0x1,
527 .enable_mask = 0x7, 582 .enable_mask = 0x7,
528 .autoidle_mask = 0x7,
529 .mult_mask = 0x7ff << 8, 583 .mult_mask = 0x7ff << 8,
530 .div1_mask = 0x7f, 584 .div1_mask = 0x7f,
531 .max_multiplier = 2047, 585 .max_multiplier = 2047,
@@ -534,7 +588,7 @@ static void __init of_ti_am3_dpll_setup(struct device_node *node)
534 .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED), 588 .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
535 }; 589 };
536 590
537 of_ti_dpll_setup(node, &dpll_ck_ops, &dd, 0); 591 of_ti_dpll_setup(node, &dpll_ck_ops, &dd);
538} 592}
539CLK_OF_DECLARE(ti_am3_dpll_clock, "ti,am3-dpll-clock", of_ti_am3_dpll_setup); 593CLK_OF_DECLARE(ti_am3_dpll_clock, "ti,am3-dpll-clock", of_ti_am3_dpll_setup);
540 594
@@ -543,7 +597,6 @@ static void __init of_ti_am3_core_dpll_setup(struct device_node *node)
543 const struct dpll_data dd = { 597 const struct dpll_data dd = {
544 .idlest_mask = 0x1, 598 .idlest_mask = 0x1,
545 .enable_mask = 0x7, 599 .enable_mask = 0x7,
546 .autoidle_mask = 0x7,
547 .mult_mask = 0x7ff << 8, 600 .mult_mask = 0x7ff << 8,
548 .div1_mask = 0x7f, 601 .div1_mask = 0x7f,
549 .max_multiplier = 2047, 602 .max_multiplier = 2047,
@@ -552,7 +605,22 @@ static void __init of_ti_am3_core_dpll_setup(struct device_node *node)
552 .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED), 605 .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
553 }; 606 };
554 607
555 of_ti_dpll_setup(node, &dpll_core_ck_ops, &dd, 0); 608 of_ti_dpll_setup(node, &dpll_core_ck_ops, &dd);
556} 609}
557CLK_OF_DECLARE(ti_am3_core_dpll_clock, "ti,am3-dpll-core-clock", 610CLK_OF_DECLARE(ti_am3_core_dpll_clock, "ti,am3-dpll-core-clock",
558 of_ti_am3_core_dpll_setup); 611 of_ti_am3_core_dpll_setup);
612
613static void __init of_ti_omap2_core_dpll_setup(struct device_node *node)
614{
615 const struct dpll_data dd = {
616 .enable_mask = 0x3,
617 .mult_mask = 0x3ff << 12,
618 .div1_mask = 0xf << 8,
619 .max_divider = 16,
620 .min_divider = 1,
621 };
622
623 of_ti_dpll_setup(node, &omap2_dpll_core_ck_ops, &dd);
624}
625CLK_OF_DECLARE(ti_omap2_core_dpll_clock, "ti,omap2-dpll-core-clock",
626 of_ti_omap2_core_dpll_setup);
diff --git a/drivers/clk/ti/gate.c b/drivers/clk/ti/gate.c
index 58734817d502..b326d2797feb 100644
--- a/drivers/clk/ti/gate.c
+++ b/drivers/clk/ti/gate.c
@@ -185,7 +185,7 @@ of_ti_composite_no_wait_gate_clk_setup(struct device_node *node)
185CLK_OF_DECLARE(ti_composite_no_wait_gate_clk, "ti,composite-no-wait-gate-clock", 185CLK_OF_DECLARE(ti_composite_no_wait_gate_clk, "ti,composite-no-wait-gate-clock",
186 of_ti_composite_no_wait_gate_clk_setup); 186 of_ti_composite_no_wait_gate_clk_setup);
187 187
188#ifdef CONFIG_ARCH_OMAP3 188#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
189static void __init of_ti_composite_interface_clk_setup(struct device_node *node) 189static void __init of_ti_composite_interface_clk_setup(struct device_node *node)
190{ 190{
191 _of_ti_composite_gate_clk_setup(node, &clkhwops_iclk_wait); 191 _of_ti_composite_gate_clk_setup(node, &clkhwops_iclk_wait);
diff --git a/drivers/clk/ti/interface.c b/drivers/clk/ti/interface.c
index 320a2b168bb2..9c3e8c4aaa40 100644
--- a/drivers/clk/ti/interface.c
+++ b/drivers/clk/ti/interface.c
@@ -94,6 +94,7 @@ static void __init of_ti_no_wait_interface_clk_setup(struct device_node *node)
94CLK_OF_DECLARE(ti_no_wait_interface_clk, "ti,omap3-no-wait-interface-clock", 94CLK_OF_DECLARE(ti_no_wait_interface_clk, "ti,omap3-no-wait-interface-clock",
95 of_ti_no_wait_interface_clk_setup); 95 of_ti_no_wait_interface_clk_setup);
96 96
97#ifdef CONFIG_ARCH_OMAP3
97static void __init of_ti_hsotgusb_interface_clk_setup(struct device_node *node) 98static void __init of_ti_hsotgusb_interface_clk_setup(struct device_node *node)
98{ 99{
99 _of_ti_interface_clk_setup(node, 100 _of_ti_interface_clk_setup(node,
@@ -123,3 +124,13 @@ static void __init of_ti_am35xx_interface_clk_setup(struct device_node *node)
123} 124}
124CLK_OF_DECLARE(ti_am35xx_interface_clk, "ti,am35xx-interface-clock", 125CLK_OF_DECLARE(ti_am35xx_interface_clk, "ti,am35xx-interface-clock",
125 of_ti_am35xx_interface_clk_setup); 126 of_ti_am35xx_interface_clk_setup);
127#endif
128
129#ifdef CONFIG_SOC_OMAP2430
130static void __init of_ti_omap2430_interface_clk_setup(struct device_node *node)
131{
132 _of_ti_interface_clk_setup(node, &clkhwops_omap2430_i2chs_wait);
133}
134CLK_OF_DECLARE(ti_omap2430_interface_clk, "ti,omap2430-interface-clock",
135 of_ti_omap2430_interface_clk_setup);
136#endif