diff options
Diffstat (limited to 'drivers')
50 files changed, 3988 insertions, 395 deletions
diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c index 7336d4a7ab31..24712adf69df 100644 --- a/drivers/ata/sata_mv.c +++ b/drivers/ata/sata_mv.c | |||
@@ -553,6 +553,7 @@ struct mv_host_priv { | |||
553 | 553 | ||
554 | #if defined(CONFIG_HAVE_CLK) | 554 | #if defined(CONFIG_HAVE_CLK) |
555 | struct clk *clk; | 555 | struct clk *clk; |
556 | struct clk **port_clks; | ||
556 | #endif | 557 | #endif |
557 | /* | 558 | /* |
558 | * These consistent DMA memory pools give us guaranteed | 559 | * These consistent DMA memory pools give us guaranteed |
@@ -4027,6 +4028,9 @@ static int mv_platform_probe(struct platform_device *pdev) | |||
4027 | struct resource *res; | 4028 | struct resource *res; |
4028 | int n_ports = 0; | 4029 | int n_ports = 0; |
4029 | int rc; | 4030 | int rc; |
4031 | #if defined(CONFIG_HAVE_CLK) | ||
4032 | int port; | ||
4033 | #endif | ||
4030 | 4034 | ||
4031 | ata_print_version_once(&pdev->dev, DRV_VERSION); | 4035 | ata_print_version_once(&pdev->dev, DRV_VERSION); |
4032 | 4036 | ||
@@ -4054,6 +4058,13 @@ static int mv_platform_probe(struct platform_device *pdev) | |||
4054 | 4058 | ||
4055 | if (!host || !hpriv) | 4059 | if (!host || !hpriv) |
4056 | return -ENOMEM; | 4060 | return -ENOMEM; |
4061 | #if defined(CONFIG_HAVE_CLK) | ||
4062 | hpriv->port_clks = devm_kzalloc(&pdev->dev, | ||
4063 | sizeof(struct clk *) * n_ports, | ||
4064 | GFP_KERNEL); | ||
4065 | if (!hpriv->port_clks) | ||
4066 | return -ENOMEM; | ||
4067 | #endif | ||
4057 | host->private_data = hpriv; | 4068 | host->private_data = hpriv; |
4058 | hpriv->n_ports = n_ports; | 4069 | hpriv->n_ports = n_ports; |
4059 | hpriv->board_idx = chip_soc; | 4070 | hpriv->board_idx = chip_soc; |
@@ -4066,9 +4077,17 @@ static int mv_platform_probe(struct platform_device *pdev) | |||
4066 | #if defined(CONFIG_HAVE_CLK) | 4077 | #if defined(CONFIG_HAVE_CLK) |
4067 | hpriv->clk = clk_get(&pdev->dev, NULL); | 4078 | hpriv->clk = clk_get(&pdev->dev, NULL); |
4068 | if (IS_ERR(hpriv->clk)) | 4079 | if (IS_ERR(hpriv->clk)) |
4069 | dev_notice(&pdev->dev, "cannot get clkdev\n"); | 4080 | dev_notice(&pdev->dev, "cannot get optional clkdev\n"); |
4070 | else | 4081 | else |
4071 | clk_enable(hpriv->clk); | 4082 | clk_prepare_enable(hpriv->clk); |
4083 | |||
4084 | for (port = 0; port < n_ports; port++) { | ||
4085 | char port_number[16]; | ||
4086 | sprintf(port_number, "%d", port); | ||
4087 | hpriv->port_clks[port] = clk_get(&pdev->dev, port_number); | ||
4088 | if (!IS_ERR(hpriv->port_clks[port])) | ||
4089 | clk_prepare_enable(hpriv->port_clks[port]); | ||
4090 | } | ||
4072 | #endif | 4091 | #endif |
4073 | 4092 | ||
4074 | /* | 4093 | /* |
@@ -4098,9 +4117,15 @@ static int mv_platform_probe(struct platform_device *pdev) | |||
4098 | err: | 4117 | err: |
4099 | #if defined(CONFIG_HAVE_CLK) | 4118 | #if defined(CONFIG_HAVE_CLK) |
4100 | if (!IS_ERR(hpriv->clk)) { | 4119 | if (!IS_ERR(hpriv->clk)) { |
4101 | clk_disable(hpriv->clk); | 4120 | clk_disable_unprepare(hpriv->clk); |
4102 | clk_put(hpriv->clk); | 4121 | clk_put(hpriv->clk); |
4103 | } | 4122 | } |
4123 | for (port = 0; port < n_ports; port++) { | ||
4124 | if (!IS_ERR(hpriv->port_clks[port])) { | ||
4125 | clk_disable_unprepare(hpriv->port_clks[port]); | ||
4126 | clk_put(hpriv->port_clks[port]); | ||
4127 | } | ||
4128 | } | ||
4104 | #endif | 4129 | #endif |
4105 | 4130 | ||
4106 | return rc; | 4131 | return rc; |
@@ -4119,14 +4144,21 @@ static int __devexit mv_platform_remove(struct platform_device *pdev) | |||
4119 | struct ata_host *host = platform_get_drvdata(pdev); | 4144 | struct ata_host *host = platform_get_drvdata(pdev); |
4120 | #if defined(CONFIG_HAVE_CLK) | 4145 | #if defined(CONFIG_HAVE_CLK) |
4121 | struct mv_host_priv *hpriv = host->private_data; | 4146 | struct mv_host_priv *hpriv = host->private_data; |
4147 | int port; | ||
4122 | #endif | 4148 | #endif |
4123 | ata_host_detach(host); | 4149 | ata_host_detach(host); |
4124 | 4150 | ||
4125 | #if defined(CONFIG_HAVE_CLK) | 4151 | #if defined(CONFIG_HAVE_CLK) |
4126 | if (!IS_ERR(hpriv->clk)) { | 4152 | if (!IS_ERR(hpriv->clk)) { |
4127 | clk_disable(hpriv->clk); | 4153 | clk_disable_unprepare(hpriv->clk); |
4128 | clk_put(hpriv->clk); | 4154 | clk_put(hpriv->clk); |
4129 | } | 4155 | } |
4156 | for (port = 0; port < host->n_ports; port++) { | ||
4157 | if (!IS_ERR(hpriv->port_clks[port])) { | ||
4158 | clk_disable_unprepare(hpriv->port_clks[port]); | ||
4159 | clk_put(hpriv->port_clks[port]); | ||
4160 | } | ||
4161 | } | ||
4130 | #endif | 4162 | #endif |
4131 | return 0; | 4163 | return 0; |
4132 | } | 4164 | } |
diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig index 165e1febae53..4864407e3fc4 100644 --- a/drivers/clk/Kconfig +++ b/drivers/clk/Kconfig | |||
@@ -12,6 +12,7 @@ config HAVE_MACH_CLKDEV | |||
12 | config COMMON_CLK | 12 | config COMMON_CLK |
13 | bool | 13 | bool |
14 | select HAVE_CLK_PREPARE | 14 | select HAVE_CLK_PREPARE |
15 | select CLKDEV_LOOKUP | ||
15 | ---help--- | 16 | ---help--- |
16 | The common clock framework is a single definition of struct | 17 | The common clock framework is a single definition of struct |
17 | clk, useful across many platforms, as well as an | 18 | clk, useful across many platforms, as well as an |
@@ -22,17 +23,6 @@ config COMMON_CLK | |||
22 | menu "Common Clock Framework" | 23 | menu "Common Clock Framework" |
23 | depends on COMMON_CLK | 24 | depends on COMMON_CLK |
24 | 25 | ||
25 | config COMMON_CLK_DISABLE_UNUSED | ||
26 | bool "Disabled unused clocks at boot" | ||
27 | depends on COMMON_CLK | ||
28 | ---help--- | ||
29 | Traverses the entire clock tree and disables any clocks that are | ||
30 | enabled in hardware but have not been enabled by any device drivers. | ||
31 | This saves power and keeps the software model of the clock in line | ||
32 | with reality. | ||
33 | |||
34 | If in doubt, say "N". | ||
35 | |||
36 | config COMMON_CLK_DEBUG | 26 | config COMMON_CLK_DEBUG |
37 | bool "DebugFS representation of clock tree" | 27 | bool "DebugFS representation of clock tree" |
38 | depends on COMMON_CLK | 28 | depends on COMMON_CLK |
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index 1f736bc11c4b..b9a5158a30b1 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile | |||
@@ -1,4 +1,7 @@ | |||
1 | 1 | ||
2 | obj-$(CONFIG_CLKDEV_LOOKUP) += clkdev.o | 2 | obj-$(CONFIG_CLKDEV_LOOKUP) += clkdev.o |
3 | obj-$(CONFIG_COMMON_CLK) += clk.o clk-fixed-rate.o clk-gate.o \ | 3 | obj-$(CONFIG_COMMON_CLK) += clk.o clk-fixed-rate.o clk-gate.o \ |
4 | clk-mux.o clk-divider.o | 4 | clk-mux.o clk-divider.o clk-fixed-factor.o |
5 | # SoCs specific | ||
6 | obj-$(CONFIG_ARCH_MXS) += mxs/ | ||
7 | obj-$(CONFIG_PLAT_SPEAR) += spear/ | ||
diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c index d5ac6a75ea57..8ea11b444528 100644 --- a/drivers/clk/clk-divider.c +++ b/drivers/clk/clk-divider.c | |||
@@ -45,7 +45,6 @@ static unsigned long clk_divider_recalc_rate(struct clk_hw *hw, | |||
45 | 45 | ||
46 | return parent_rate / div; | 46 | return parent_rate / div; |
47 | } | 47 | } |
48 | EXPORT_SYMBOL_GPL(clk_divider_recalc_rate); | ||
49 | 48 | ||
50 | /* | 49 | /* |
51 | * The reverse of DIV_ROUND_UP: The maximum number which | 50 | * The reverse of DIV_ROUND_UP: The maximum number which |
@@ -68,8 +67,8 @@ static int clk_divider_bestdiv(struct clk_hw *hw, unsigned long rate, | |||
68 | if (divider->flags & CLK_DIVIDER_ONE_BASED) | 67 | if (divider->flags & CLK_DIVIDER_ONE_BASED) |
69 | maxdiv--; | 68 | maxdiv--; |
70 | 69 | ||
71 | if (!best_parent_rate) { | 70 | if (!(__clk_get_flags(hw->clk) & CLK_SET_RATE_PARENT)) { |
72 | parent_rate = __clk_get_rate(__clk_get_parent(hw->clk)); | 71 | parent_rate = *best_parent_rate; |
73 | bestdiv = DIV_ROUND_UP(parent_rate, rate); | 72 | bestdiv = DIV_ROUND_UP(parent_rate, rate); |
74 | bestdiv = bestdiv == 0 ? 1 : bestdiv; | 73 | bestdiv = bestdiv == 0 ? 1 : bestdiv; |
75 | bestdiv = bestdiv > maxdiv ? maxdiv : bestdiv; | 74 | bestdiv = bestdiv > maxdiv ? maxdiv : bestdiv; |
@@ -109,24 +108,18 @@ static long clk_divider_round_rate(struct clk_hw *hw, unsigned long rate, | |||
109 | int div; | 108 | int div; |
110 | div = clk_divider_bestdiv(hw, rate, prate); | 109 | div = clk_divider_bestdiv(hw, rate, prate); |
111 | 110 | ||
112 | if (prate) | 111 | return *prate / div; |
113 | return *prate / div; | ||
114 | else { | ||
115 | unsigned long r; | ||
116 | r = __clk_get_rate(__clk_get_parent(hw->clk)); | ||
117 | return r / div; | ||
118 | } | ||
119 | } | 112 | } |
120 | EXPORT_SYMBOL_GPL(clk_divider_round_rate); | ||
121 | 113 | ||
122 | static int clk_divider_set_rate(struct clk_hw *hw, unsigned long rate) | 114 | static int clk_divider_set_rate(struct clk_hw *hw, unsigned long rate, |
115 | unsigned long parent_rate) | ||
123 | { | 116 | { |
124 | struct clk_divider *divider = to_clk_divider(hw); | 117 | struct clk_divider *divider = to_clk_divider(hw); |
125 | unsigned int div; | 118 | unsigned int div; |
126 | unsigned long flags = 0; | 119 | unsigned long flags = 0; |
127 | u32 val; | 120 | u32 val; |
128 | 121 | ||
129 | div = __clk_get_rate(__clk_get_parent(hw->clk)) / rate; | 122 | div = parent_rate / rate; |
130 | 123 | ||
131 | if (!(divider->flags & CLK_DIVIDER_ONE_BASED)) | 124 | if (!(divider->flags & CLK_DIVIDER_ONE_BASED)) |
132 | div--; | 125 | div--; |
@@ -147,15 +140,26 @@ static int clk_divider_set_rate(struct clk_hw *hw, unsigned long rate) | |||
147 | 140 | ||
148 | return 0; | 141 | return 0; |
149 | } | 142 | } |
150 | EXPORT_SYMBOL_GPL(clk_divider_set_rate); | ||
151 | 143 | ||
152 | struct clk_ops clk_divider_ops = { | 144 | const struct clk_ops clk_divider_ops = { |
153 | .recalc_rate = clk_divider_recalc_rate, | 145 | .recalc_rate = clk_divider_recalc_rate, |
154 | .round_rate = clk_divider_round_rate, | 146 | .round_rate = clk_divider_round_rate, |
155 | .set_rate = clk_divider_set_rate, | 147 | .set_rate = clk_divider_set_rate, |
156 | }; | 148 | }; |
157 | EXPORT_SYMBOL_GPL(clk_divider_ops); | 149 | EXPORT_SYMBOL_GPL(clk_divider_ops); |
158 | 150 | ||
151 | /** | ||
152 | * clk_register_divider - register a divider clock with the clock framework | ||
153 | * @dev: device registering this clock | ||
154 | * @name: name of this clock | ||
155 | * @parent_name: name of clock's parent | ||
156 | * @flags: framework-specific flags | ||
157 | * @reg: register address to adjust divider | ||
158 | * @shift: number of bits to shift the bitfield | ||
159 | * @width: width of the bitfield | ||
160 | * @clk_divider_flags: divider-specific flags for this clock | ||
161 | * @lock: shared register lock for this clock | ||
162 | */ | ||
159 | struct clk *clk_register_divider(struct device *dev, const char *name, | 163 | struct clk *clk_register_divider(struct device *dev, const char *name, |
160 | const char *parent_name, unsigned long flags, | 164 | const char *parent_name, unsigned long flags, |
161 | void __iomem *reg, u8 shift, u8 width, | 165 | void __iomem *reg, u8 shift, u8 width, |
@@ -163,38 +167,34 @@ struct clk *clk_register_divider(struct device *dev, const char *name, | |||
163 | { | 167 | { |
164 | struct clk_divider *div; | 168 | struct clk_divider *div; |
165 | struct clk *clk; | 169 | struct clk *clk; |
170 | struct clk_init_data init; | ||
166 | 171 | ||
172 | /* allocate the divider */ | ||
167 | div = kzalloc(sizeof(struct clk_divider), GFP_KERNEL); | 173 | div = kzalloc(sizeof(struct clk_divider), GFP_KERNEL); |
168 | |||
169 | if (!div) { | 174 | if (!div) { |
170 | pr_err("%s: could not allocate divider clk\n", __func__); | 175 | pr_err("%s: could not allocate divider clk\n", __func__); |
171 | return NULL; | 176 | return ERR_PTR(-ENOMEM); |
172 | } | 177 | } |
173 | 178 | ||
179 | init.name = name; | ||
180 | init.ops = &clk_divider_ops; | ||
181 | init.flags = flags; | ||
182 | init.parent_names = (parent_name ? &parent_name: NULL); | ||
183 | init.num_parents = (parent_name ? 1 : 0); | ||
184 | |||
174 | /* struct clk_divider assignments */ | 185 | /* struct clk_divider assignments */ |
175 | div->reg = reg; | 186 | div->reg = reg; |
176 | div->shift = shift; | 187 | div->shift = shift; |
177 | div->width = width; | 188 | div->width = width; |
178 | div->flags = clk_divider_flags; | 189 | div->flags = clk_divider_flags; |
179 | div->lock = lock; | 190 | div->lock = lock; |
191 | div->hw.init = &init; | ||
180 | 192 | ||
181 | if (parent_name) { | 193 | /* register the clock */ |
182 | div->parent[0] = kstrdup(parent_name, GFP_KERNEL); | 194 | clk = clk_register(dev, &div->hw); |
183 | if (!div->parent[0]) | ||
184 | goto out; | ||
185 | } | ||
186 | |||
187 | clk = clk_register(dev, name, | ||
188 | &clk_divider_ops, &div->hw, | ||
189 | div->parent, | ||
190 | (parent_name ? 1 : 0), | ||
191 | flags); | ||
192 | if (clk) | ||
193 | return clk; | ||
194 | 195 | ||
195 | out: | 196 | if (IS_ERR(clk)) |
196 | kfree(div->parent[0]); | 197 | kfree(div); |
197 | kfree(div); | ||
198 | 198 | ||
199 | return NULL; | 199 | return clk; |
200 | } | 200 | } |
diff --git a/drivers/clk/clk-fixed-factor.c b/drivers/clk/clk-fixed-factor.c new file mode 100644 index 000000000000..c8c003e217ad --- /dev/null +++ b/drivers/clk/clk-fixed-factor.c | |||
@@ -0,0 +1,95 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2011 Sascha Hauer, Pengutronix <s.hauer@pengutronix.de> | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | * | ||
8 | * Standard functionality for the common clock API. | ||
9 | */ | ||
10 | #include <linux/module.h> | ||
11 | #include <linux/clk-provider.h> | ||
12 | #include <linux/slab.h> | ||
13 | #include <linux/err.h> | ||
14 | |||
15 | /* | ||
16 | * DOC: basic fixed multiplier and divider clock that cannot gate | ||
17 | * | ||
18 | * Traits of this clock: | ||
19 | * prepare - clk_prepare only ensures that parents are prepared | ||
20 | * enable - clk_enable only ensures that parents are enabled | ||
21 | * rate - rate is fixed. clk->rate = parent->rate / div * mult | ||
22 | * parent - fixed parent. No clk_set_parent support | ||
23 | */ | ||
24 | |||
25 | #define to_clk_fixed_factor(_hw) container_of(_hw, struct clk_fixed_factor, hw) | ||
26 | |||
27 | static unsigned long clk_factor_recalc_rate(struct clk_hw *hw, | ||
28 | unsigned long parent_rate) | ||
29 | { | ||
30 | struct clk_fixed_factor *fix = to_clk_fixed_factor(hw); | ||
31 | |||
32 | return parent_rate * fix->mult / fix->div; | ||
33 | } | ||
34 | |||
35 | static long clk_factor_round_rate(struct clk_hw *hw, unsigned long rate, | ||
36 | unsigned long *prate) | ||
37 | { | ||
38 | struct clk_fixed_factor *fix = to_clk_fixed_factor(hw); | ||
39 | |||
40 | if (__clk_get_flags(hw->clk) & CLK_SET_RATE_PARENT) { | ||
41 | unsigned long best_parent; | ||
42 | |||
43 | best_parent = (rate / fix->mult) * fix->div; | ||
44 | *prate = __clk_round_rate(__clk_get_parent(hw->clk), | ||
45 | best_parent); | ||
46 | } | ||
47 | |||
48 | return (*prate / fix->div) * fix->mult; | ||
49 | } | ||
50 | |||
51 | static int clk_factor_set_rate(struct clk_hw *hw, unsigned long rate, | ||
52 | unsigned long parent_rate) | ||
53 | { | ||
54 | return 0; | ||
55 | } | ||
56 | |||
57 | struct clk_ops clk_fixed_factor_ops = { | ||
58 | .round_rate = clk_factor_round_rate, | ||
59 | .set_rate = clk_factor_set_rate, | ||
60 | .recalc_rate = clk_factor_recalc_rate, | ||
61 | }; | ||
62 | EXPORT_SYMBOL_GPL(clk_fixed_factor_ops); | ||
63 | |||
64 | struct clk *clk_register_fixed_factor(struct device *dev, const char *name, | ||
65 | const char *parent_name, unsigned long flags, | ||
66 | unsigned int mult, unsigned int div) | ||
67 | { | ||
68 | struct clk_fixed_factor *fix; | ||
69 | struct clk_init_data init; | ||
70 | struct clk *clk; | ||
71 | |||
72 | fix = kmalloc(sizeof(*fix), GFP_KERNEL); | ||
73 | if (!fix) { | ||
74 | pr_err("%s: could not allocate fixed factor clk\n", __func__); | ||
75 | return ERR_PTR(-ENOMEM); | ||
76 | } | ||
77 | |||
78 | /* struct clk_fixed_factor assignments */ | ||
79 | fix->mult = mult; | ||
80 | fix->div = div; | ||
81 | fix->hw.init = &init; | ||
82 | |||
83 | init.name = name; | ||
84 | init.ops = &clk_fixed_factor_ops; | ||
85 | init.flags = flags; | ||
86 | init.parent_names = &parent_name; | ||
87 | init.num_parents = 1; | ||
88 | |||
89 | clk = clk_register(dev, &fix->hw); | ||
90 | |||
91 | if (IS_ERR(clk)) | ||
92 | kfree(fix); | ||
93 | |||
94 | return clk; | ||
95 | } | ||
diff --git a/drivers/clk/clk-fixed-rate.c b/drivers/clk/clk-fixed-rate.c index 90c79fb5d1bd..cbd246229786 100644 --- a/drivers/clk/clk-fixed-rate.c +++ b/drivers/clk/clk-fixed-rate.c | |||
@@ -32,51 +32,50 @@ static unsigned long clk_fixed_rate_recalc_rate(struct clk_hw *hw, | |||
32 | { | 32 | { |
33 | return to_clk_fixed_rate(hw)->fixed_rate; | 33 | return to_clk_fixed_rate(hw)->fixed_rate; |
34 | } | 34 | } |
35 | EXPORT_SYMBOL_GPL(clk_fixed_rate_recalc_rate); | ||
36 | 35 | ||
37 | struct clk_ops clk_fixed_rate_ops = { | 36 | const struct clk_ops clk_fixed_rate_ops = { |
38 | .recalc_rate = clk_fixed_rate_recalc_rate, | 37 | .recalc_rate = clk_fixed_rate_recalc_rate, |
39 | }; | 38 | }; |
40 | EXPORT_SYMBOL_GPL(clk_fixed_rate_ops); | 39 | EXPORT_SYMBOL_GPL(clk_fixed_rate_ops); |
41 | 40 | ||
41 | /** | ||
42 | * clk_register_fixed_rate - register fixed-rate clock with the clock framework | ||
43 | * @dev: device that is registering this clock | ||
44 | * @name: name of this clock | ||
45 | * @parent_name: name of clock's parent | ||
46 | * @flags: framework-specific flags | ||
47 | * @fixed_rate: non-adjustable clock rate | ||
48 | */ | ||
42 | struct clk *clk_register_fixed_rate(struct device *dev, const char *name, | 49 | struct clk *clk_register_fixed_rate(struct device *dev, const char *name, |
43 | const char *parent_name, unsigned long flags, | 50 | const char *parent_name, unsigned long flags, |
44 | unsigned long fixed_rate) | 51 | unsigned long fixed_rate) |
45 | { | 52 | { |
46 | struct clk_fixed_rate *fixed; | 53 | struct clk_fixed_rate *fixed; |
47 | char **parent_names = NULL; | 54 | struct clk *clk; |
48 | u8 len; | 55 | struct clk_init_data init; |
49 | 56 | ||
57 | /* allocate fixed-rate clock */ | ||
50 | fixed = kzalloc(sizeof(struct clk_fixed_rate), GFP_KERNEL); | 58 | fixed = kzalloc(sizeof(struct clk_fixed_rate), GFP_KERNEL); |
51 | |||
52 | if (!fixed) { | 59 | if (!fixed) { |
53 | pr_err("%s: could not allocate fixed clk\n", __func__); | 60 | pr_err("%s: could not allocate fixed clk\n", __func__); |
54 | return ERR_PTR(-ENOMEM); | 61 | return ERR_PTR(-ENOMEM); |
55 | } | 62 | } |
56 | 63 | ||
64 | init.name = name; | ||
65 | init.ops = &clk_fixed_rate_ops; | ||
66 | init.flags = flags; | ||
67 | init.parent_names = (parent_name ? &parent_name: NULL); | ||
68 | init.num_parents = (parent_name ? 1 : 0); | ||
69 | |||
57 | /* struct clk_fixed_rate assignments */ | 70 | /* struct clk_fixed_rate assignments */ |
58 | fixed->fixed_rate = fixed_rate; | 71 | fixed->fixed_rate = fixed_rate; |
72 | fixed->hw.init = &init; | ||
59 | 73 | ||
60 | if (parent_name) { | 74 | /* register the clock */ |
61 | parent_names = kmalloc(sizeof(char *), GFP_KERNEL); | 75 | clk = clk_register(dev, &fixed->hw); |
62 | |||
63 | if (! parent_names) | ||
64 | goto out; | ||
65 | 76 | ||
66 | len = sizeof(char) * strlen(parent_name); | 77 | if (IS_ERR(clk)) |
67 | 78 | kfree(fixed); | |
68 | parent_names[0] = kmalloc(len, GFP_KERNEL); | ||
69 | |||
70 | if (!parent_names[0]) | ||
71 | goto out; | ||
72 | |||
73 | strncpy(parent_names[0], parent_name, len); | ||
74 | } | ||
75 | 79 | ||
76 | out: | 80 | return clk; |
77 | return clk_register(dev, name, | ||
78 | &clk_fixed_rate_ops, &fixed->hw, | ||
79 | parent_names, | ||
80 | (parent_name ? 1 : 0), | ||
81 | flags); | ||
82 | } | 81 | } |
diff --git a/drivers/clk/clk-gate.c b/drivers/clk/clk-gate.c index b5902e2ef2fd..578465e04be6 100644 --- a/drivers/clk/clk-gate.c +++ b/drivers/clk/clk-gate.c | |||
@@ -28,32 +28,38 @@ | |||
28 | 28 | ||
29 | #define to_clk_gate(_hw) container_of(_hw, struct clk_gate, hw) | 29 | #define to_clk_gate(_hw) container_of(_hw, struct clk_gate, hw) |
30 | 30 | ||
31 | static void clk_gate_set_bit(struct clk_gate *gate) | 31 | /* |
32 | * It works on following logic: | ||
33 | * | ||
34 | * For enabling clock, enable = 1 | ||
35 | * set2dis = 1 -> clear bit -> set = 0 | ||
36 | * set2dis = 0 -> set bit -> set = 1 | ||
37 | * | ||
38 | * For disabling clock, enable = 0 | ||
39 | * set2dis = 1 -> set bit -> set = 1 | ||
40 | * set2dis = 0 -> clear bit -> set = 0 | ||
41 | * | ||
42 | * So, result is always: enable xor set2dis. | ||
43 | */ | ||
44 | static void clk_gate_endisable(struct clk_hw *hw, int enable) | ||
32 | { | 45 | { |
33 | u32 reg; | 46 | struct clk_gate *gate = to_clk_gate(hw); |
47 | int set = gate->flags & CLK_GATE_SET_TO_DISABLE ? 1 : 0; | ||
34 | unsigned long flags = 0; | 48 | unsigned long flags = 0; |
49 | u32 reg; | ||
50 | |||
51 | set ^= enable; | ||
35 | 52 | ||
36 | if (gate->lock) | 53 | if (gate->lock) |
37 | spin_lock_irqsave(gate->lock, flags); | 54 | spin_lock_irqsave(gate->lock, flags); |
38 | 55 | ||
39 | reg = readl(gate->reg); | 56 | reg = readl(gate->reg); |
40 | reg |= BIT(gate->bit_idx); | ||
41 | writel(reg, gate->reg); | ||
42 | |||
43 | if (gate->lock) | ||
44 | spin_unlock_irqrestore(gate->lock, flags); | ||
45 | } | ||
46 | |||
47 | static void clk_gate_clear_bit(struct clk_gate *gate) | ||
48 | { | ||
49 | u32 reg; | ||
50 | unsigned long flags = 0; | ||
51 | 57 | ||
52 | if (gate->lock) | 58 | if (set) |
53 | spin_lock_irqsave(gate->lock, flags); | 59 | reg |= BIT(gate->bit_idx); |
60 | else | ||
61 | reg &= ~BIT(gate->bit_idx); | ||
54 | 62 | ||
55 | reg = readl(gate->reg); | ||
56 | reg &= ~BIT(gate->bit_idx); | ||
57 | writel(reg, gate->reg); | 63 | writel(reg, gate->reg); |
58 | 64 | ||
59 | if (gate->lock) | 65 | if (gate->lock) |
@@ -62,27 +68,15 @@ static void clk_gate_clear_bit(struct clk_gate *gate) | |||
62 | 68 | ||
63 | static int clk_gate_enable(struct clk_hw *hw) | 69 | static int clk_gate_enable(struct clk_hw *hw) |
64 | { | 70 | { |
65 | struct clk_gate *gate = to_clk_gate(hw); | 71 | clk_gate_endisable(hw, 1); |
66 | |||
67 | if (gate->flags & CLK_GATE_SET_TO_DISABLE) | ||
68 | clk_gate_clear_bit(gate); | ||
69 | else | ||
70 | clk_gate_set_bit(gate); | ||
71 | 72 | ||
72 | return 0; | 73 | return 0; |
73 | } | 74 | } |
74 | EXPORT_SYMBOL_GPL(clk_gate_enable); | ||
75 | 75 | ||
76 | static void clk_gate_disable(struct clk_hw *hw) | 76 | static void clk_gate_disable(struct clk_hw *hw) |
77 | { | 77 | { |
78 | struct clk_gate *gate = to_clk_gate(hw); | 78 | clk_gate_endisable(hw, 0); |
79 | |||
80 | if (gate->flags & CLK_GATE_SET_TO_DISABLE) | ||
81 | clk_gate_set_bit(gate); | ||
82 | else | ||
83 | clk_gate_clear_bit(gate); | ||
84 | } | 79 | } |
85 | EXPORT_SYMBOL_GPL(clk_gate_disable); | ||
86 | 80 | ||
87 | static int clk_gate_is_enabled(struct clk_hw *hw) | 81 | static int clk_gate_is_enabled(struct clk_hw *hw) |
88 | { | 82 | { |
@@ -99,15 +93,25 @@ static int clk_gate_is_enabled(struct clk_hw *hw) | |||
99 | 93 | ||
100 | return reg ? 1 : 0; | 94 | return reg ? 1 : 0; |
101 | } | 95 | } |
102 | EXPORT_SYMBOL_GPL(clk_gate_is_enabled); | ||
103 | 96 | ||
104 | struct clk_ops clk_gate_ops = { | 97 | const struct clk_ops clk_gate_ops = { |
105 | .enable = clk_gate_enable, | 98 | .enable = clk_gate_enable, |
106 | .disable = clk_gate_disable, | 99 | .disable = clk_gate_disable, |
107 | .is_enabled = clk_gate_is_enabled, | 100 | .is_enabled = clk_gate_is_enabled, |
108 | }; | 101 | }; |
109 | EXPORT_SYMBOL_GPL(clk_gate_ops); | 102 | EXPORT_SYMBOL_GPL(clk_gate_ops); |
110 | 103 | ||
104 | /** | ||
105 | * clk_register_gate - register a gate clock with the clock framework | ||
106 | * @dev: device that is registering this clock | ||
107 | * @name: name of this clock | ||
108 | * @parent_name: name of this clock's parent | ||
109 | * @flags: framework-specific flags for this clock | ||
110 | * @reg: register address to control gating of this clock | ||
111 | * @bit_idx: which bit in the register controls gating of this clock | ||
112 | * @clk_gate_flags: gate-specific flags for this clock | ||
113 | * @lock: shared register lock for this clock | ||
114 | */ | ||
111 | struct clk *clk_register_gate(struct device *dev, const char *name, | 115 | struct clk *clk_register_gate(struct device *dev, const char *name, |
112 | const char *parent_name, unsigned long flags, | 116 | const char *parent_name, unsigned long flags, |
113 | void __iomem *reg, u8 bit_idx, | 117 | void __iomem *reg, u8 bit_idx, |
@@ -115,36 +119,32 @@ struct clk *clk_register_gate(struct device *dev, const char *name, | |||
115 | { | 119 | { |
116 | struct clk_gate *gate; | 120 | struct clk_gate *gate; |
117 | struct clk *clk; | 121 | struct clk *clk; |
122 | struct clk_init_data init; | ||
118 | 123 | ||
124 | /* allocate the gate */ | ||
119 | gate = kzalloc(sizeof(struct clk_gate), GFP_KERNEL); | 125 | gate = kzalloc(sizeof(struct clk_gate), GFP_KERNEL); |
120 | |||
121 | if (!gate) { | 126 | if (!gate) { |
122 | pr_err("%s: could not allocate gated clk\n", __func__); | 127 | pr_err("%s: could not allocate gated clk\n", __func__); |
123 | return NULL; | 128 | return ERR_PTR(-ENOMEM); |
124 | } | 129 | } |
125 | 130 | ||
131 | init.name = name; | ||
132 | init.ops = &clk_gate_ops; | ||
133 | init.flags = flags; | ||
134 | init.parent_names = (parent_name ? &parent_name: NULL); | ||
135 | init.num_parents = (parent_name ? 1 : 0); | ||
136 | |||
126 | /* struct clk_gate assignments */ | 137 | /* struct clk_gate assignments */ |
127 | gate->reg = reg; | 138 | gate->reg = reg; |
128 | gate->bit_idx = bit_idx; | 139 | gate->bit_idx = bit_idx; |
129 | gate->flags = clk_gate_flags; | 140 | gate->flags = clk_gate_flags; |
130 | gate->lock = lock; | 141 | gate->lock = lock; |
142 | gate->hw.init = &init; | ||
131 | 143 | ||
132 | if (parent_name) { | 144 | clk = clk_register(dev, &gate->hw); |
133 | gate->parent[0] = kstrdup(parent_name, GFP_KERNEL); | 145 | |
134 | if (!gate->parent[0]) | 146 | if (IS_ERR(clk)) |
135 | goto out; | 147 | kfree(gate); |
136 | } | ||
137 | 148 | ||
138 | clk = clk_register(dev, name, | 149 | return clk; |
139 | &clk_gate_ops, &gate->hw, | ||
140 | gate->parent, | ||
141 | (parent_name ? 1 : 0), | ||
142 | flags); | ||
143 | if (clk) | ||
144 | return clk; | ||
145 | out: | ||
146 | kfree(gate->parent[0]); | ||
147 | kfree(gate); | ||
148 | |||
149 | return NULL; | ||
150 | } | 150 | } |
diff --git a/drivers/clk/clk-mux.c b/drivers/clk/clk-mux.c index c71ad1f41a97..fd36a8ea73d9 100644 --- a/drivers/clk/clk-mux.c +++ b/drivers/clk/clk-mux.c | |||
@@ -55,7 +55,6 @@ static u8 clk_mux_get_parent(struct clk_hw *hw) | |||
55 | 55 | ||
56 | return val; | 56 | return val; |
57 | } | 57 | } |
58 | EXPORT_SYMBOL_GPL(clk_mux_get_parent); | ||
59 | 58 | ||
60 | static int clk_mux_set_parent(struct clk_hw *hw, u8 index) | 59 | static int clk_mux_set_parent(struct clk_hw *hw, u8 index) |
61 | { | 60 | { |
@@ -82,35 +81,47 @@ static int clk_mux_set_parent(struct clk_hw *hw, u8 index) | |||
82 | 81 | ||
83 | return 0; | 82 | return 0; |
84 | } | 83 | } |
85 | EXPORT_SYMBOL_GPL(clk_mux_set_parent); | ||
86 | 84 | ||
87 | struct clk_ops clk_mux_ops = { | 85 | const struct clk_ops clk_mux_ops = { |
88 | .get_parent = clk_mux_get_parent, | 86 | .get_parent = clk_mux_get_parent, |
89 | .set_parent = clk_mux_set_parent, | 87 | .set_parent = clk_mux_set_parent, |
90 | }; | 88 | }; |
91 | EXPORT_SYMBOL_GPL(clk_mux_ops); | 89 | EXPORT_SYMBOL_GPL(clk_mux_ops); |
92 | 90 | ||
93 | struct clk *clk_register_mux(struct device *dev, const char *name, | 91 | struct clk *clk_register_mux(struct device *dev, const char *name, |
94 | char **parent_names, u8 num_parents, unsigned long flags, | 92 | const char **parent_names, u8 num_parents, unsigned long flags, |
95 | void __iomem *reg, u8 shift, u8 width, | 93 | void __iomem *reg, u8 shift, u8 width, |
96 | u8 clk_mux_flags, spinlock_t *lock) | 94 | u8 clk_mux_flags, spinlock_t *lock) |
97 | { | 95 | { |
98 | struct clk_mux *mux; | 96 | struct clk_mux *mux; |
97 | struct clk *clk; | ||
98 | struct clk_init_data init; | ||
99 | 99 | ||
100 | mux = kmalloc(sizeof(struct clk_mux), GFP_KERNEL); | 100 | /* allocate the mux */ |
101 | 101 | mux = kzalloc(sizeof(struct clk_mux), GFP_KERNEL); | |
102 | if (!mux) { | 102 | if (!mux) { |
103 | pr_err("%s: could not allocate mux clk\n", __func__); | 103 | pr_err("%s: could not allocate mux clk\n", __func__); |
104 | return ERR_PTR(-ENOMEM); | 104 | return ERR_PTR(-ENOMEM); |
105 | } | 105 | } |
106 | 106 | ||
107 | init.name = name; | ||
108 | init.ops = &clk_mux_ops; | ||
109 | init.flags = flags; | ||
110 | init.parent_names = parent_names; | ||
111 | init.num_parents = num_parents; | ||
112 | |||
107 | /* struct clk_mux assignments */ | 113 | /* struct clk_mux assignments */ |
108 | mux->reg = reg; | 114 | mux->reg = reg; |
109 | mux->shift = shift; | 115 | mux->shift = shift; |
110 | mux->width = width; | 116 | mux->width = width; |
111 | mux->flags = clk_mux_flags; | 117 | mux->flags = clk_mux_flags; |
112 | mux->lock = lock; | 118 | mux->lock = lock; |
119 | mux->hw.init = &init; | ||
120 | |||
121 | clk = clk_register(dev, &mux->hw); | ||
122 | |||
123 | if (IS_ERR(clk)) | ||
124 | kfree(mux); | ||
113 | 125 | ||
114 | return clk_register(dev, name, &clk_mux_ops, &mux->hw, | 126 | return clk; |
115 | parent_names, num_parents, flags); | ||
116 | } | 127 | } |
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index 9cf6f59e3e19..687b00d67c8a 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c | |||
@@ -194,9 +194,8 @@ static int __init clk_debug_init(void) | |||
194 | late_initcall(clk_debug_init); | 194 | late_initcall(clk_debug_init); |
195 | #else | 195 | #else |
196 | static inline int clk_debug_register(struct clk *clk) { return 0; } | 196 | static inline int clk_debug_register(struct clk *clk) { return 0; } |
197 | #endif /* CONFIG_COMMON_CLK_DEBUG */ | 197 | #endif |
198 | 198 | ||
199 | #ifdef CONFIG_COMMON_CLK_DISABLE_UNUSED | ||
200 | /* caller must hold prepare_lock */ | 199 | /* caller must hold prepare_lock */ |
201 | static void clk_disable_unused_subtree(struct clk *clk) | 200 | static void clk_disable_unused_subtree(struct clk *clk) |
202 | { | 201 | { |
@@ -246,9 +245,6 @@ static int clk_disable_unused(void) | |||
246 | return 0; | 245 | return 0; |
247 | } | 246 | } |
248 | late_initcall(clk_disable_unused); | 247 | late_initcall(clk_disable_unused); |
249 | #else | ||
250 | static inline int clk_disable_unused(struct clk *clk) { return 0; } | ||
251 | #endif /* CONFIG_COMMON_CLK_DISABLE_UNUSED */ | ||
252 | 248 | ||
253 | /*** helper functions ***/ | 249 | /*** helper functions ***/ |
254 | 250 | ||
@@ -287,7 +283,7 @@ unsigned long __clk_get_rate(struct clk *clk) | |||
287 | unsigned long ret; | 283 | unsigned long ret; |
288 | 284 | ||
289 | if (!clk) { | 285 | if (!clk) { |
290 | ret = -EINVAL; | 286 | ret = 0; |
291 | goto out; | 287 | goto out; |
292 | } | 288 | } |
293 | 289 | ||
@@ -297,7 +293,7 @@ unsigned long __clk_get_rate(struct clk *clk) | |||
297 | goto out; | 293 | goto out; |
298 | 294 | ||
299 | if (!clk->parent) | 295 | if (!clk->parent) |
300 | ret = -ENODEV; | 296 | ret = 0; |
301 | 297 | ||
302 | out: | 298 | out: |
303 | return ret; | 299 | return ret; |
@@ -562,7 +558,7 @@ EXPORT_SYMBOL_GPL(clk_enable); | |||
562 | * @clk: the clk whose rate is being returned | 558 | * @clk: the clk whose rate is being returned |
563 | * | 559 | * |
564 | * Simply returns the cached rate of the clk. Does not query the hardware. If | 560 | * Simply returns the cached rate of the clk. Does not query the hardware. If |
565 | * clk is NULL then returns -EINVAL. | 561 | * clk is NULL then returns 0. |
566 | */ | 562 | */ |
567 | unsigned long clk_get_rate(struct clk *clk) | 563 | unsigned long clk_get_rate(struct clk *clk) |
568 | { | 564 | { |
@@ -584,18 +580,22 @@ EXPORT_SYMBOL_GPL(clk_get_rate); | |||
584 | */ | 580 | */ |
585 | unsigned long __clk_round_rate(struct clk *clk, unsigned long rate) | 581 | unsigned long __clk_round_rate(struct clk *clk, unsigned long rate) |
586 | { | 582 | { |
587 | unsigned long unused; | 583 | unsigned long parent_rate = 0; |
588 | 584 | ||
589 | if (!clk) | 585 | if (!clk) |
590 | return -EINVAL; | 586 | return -EINVAL; |
591 | 587 | ||
592 | if (!clk->ops->round_rate) | 588 | if (!clk->ops->round_rate) { |
593 | return clk->rate; | 589 | if (clk->flags & CLK_SET_RATE_PARENT) |
590 | return __clk_round_rate(clk->parent, rate); | ||
591 | else | ||
592 | return clk->rate; | ||
593 | } | ||
594 | 594 | ||
595 | if (clk->flags & CLK_SET_RATE_PARENT) | 595 | if (clk->parent) |
596 | return clk->ops->round_rate(clk->hw, rate, &unused); | 596 | parent_rate = clk->parent->rate; |
597 | else | 597 | |
598 | return clk->ops->round_rate(clk->hw, rate, NULL); | 598 | return clk->ops->round_rate(clk->hw, rate, &parent_rate); |
599 | } | 599 | } |
600 | 600 | ||
601 | /** | 601 | /** |
@@ -765,25 +765,41 @@ static void clk_calc_subtree(struct clk *clk, unsigned long new_rate) | |||
765 | static struct clk *clk_calc_new_rates(struct clk *clk, unsigned long rate) | 765 | static struct clk *clk_calc_new_rates(struct clk *clk, unsigned long rate) |
766 | { | 766 | { |
767 | struct clk *top = clk; | 767 | struct clk *top = clk; |
768 | unsigned long best_parent_rate = clk->parent->rate; | 768 | unsigned long best_parent_rate = 0; |
769 | unsigned long new_rate; | 769 | unsigned long new_rate; |
770 | 770 | ||
771 | if (!clk->ops->round_rate && !(clk->flags & CLK_SET_RATE_PARENT)) { | 771 | /* sanity */ |
772 | clk->new_rate = clk->rate; | 772 | if (IS_ERR_OR_NULL(clk)) |
773 | return NULL; | ||
774 | |||
775 | /* save parent rate, if it exists */ | ||
776 | if (clk->parent) | ||
777 | best_parent_rate = clk->parent->rate; | ||
778 | |||
779 | /* never propagate up to the parent */ | ||
780 | if (!(clk->flags & CLK_SET_RATE_PARENT)) { | ||
781 | if (!clk->ops->round_rate) { | ||
782 | clk->new_rate = clk->rate; | ||
783 | return NULL; | ||
784 | } | ||
785 | new_rate = clk->ops->round_rate(clk->hw, rate, &best_parent_rate); | ||
786 | goto out; | ||
787 | } | ||
788 | |||
789 | /* need clk->parent from here on out */ | ||
790 | if (!clk->parent) { | ||
791 | pr_debug("%s: %s has NULL parent\n", __func__, clk->name); | ||
773 | return NULL; | 792 | return NULL; |
774 | } | 793 | } |
775 | 794 | ||
776 | if (!clk->ops->round_rate && (clk->flags & CLK_SET_RATE_PARENT)) { | 795 | if (!clk->ops->round_rate) { |
777 | top = clk_calc_new_rates(clk->parent, rate); | 796 | top = clk_calc_new_rates(clk->parent, rate); |
778 | new_rate = clk->new_rate = clk->parent->new_rate; | 797 | new_rate = clk->parent->new_rate; |
779 | 798 | ||
780 | goto out; | 799 | goto out; |
781 | } | 800 | } |
782 | 801 | ||
783 | if (clk->flags & CLK_SET_RATE_PARENT) | 802 | new_rate = clk->ops->round_rate(clk->hw, rate, &best_parent_rate); |
784 | new_rate = clk->ops->round_rate(clk->hw, rate, &best_parent_rate); | ||
785 | else | ||
786 | new_rate = clk->ops->round_rate(clk->hw, rate, NULL); | ||
787 | 803 | ||
788 | if (best_parent_rate != clk->parent->rate) { | 804 | if (best_parent_rate != clk->parent->rate) { |
789 | top = clk_calc_new_rates(clk->parent, best_parent_rate); | 805 | top = clk_calc_new_rates(clk->parent, best_parent_rate); |
@@ -839,7 +855,7 @@ static void clk_change_rate(struct clk *clk) | |||
839 | old_rate = clk->rate; | 855 | old_rate = clk->rate; |
840 | 856 | ||
841 | if (clk->ops->set_rate) | 857 | if (clk->ops->set_rate) |
842 | clk->ops->set_rate(clk->hw, clk->new_rate); | 858 | clk->ops->set_rate(clk->hw, clk->new_rate, clk->parent->rate); |
843 | 859 | ||
844 | if (clk->ops->recalc_rate) | 860 | if (clk->ops->recalc_rate) |
845 | clk->rate = clk->ops->recalc_rate(clk->hw, | 861 | clk->rate = clk->ops->recalc_rate(clk->hw, |
@@ -859,38 +875,19 @@ static void clk_change_rate(struct clk *clk) | |||
859 | * @clk: the clk whose rate is being changed | 875 | * @clk: the clk whose rate is being changed |
860 | * @rate: the new rate for clk | 876 | * @rate: the new rate for clk |
861 | * | 877 | * |
862 | * In the simplest case clk_set_rate will only change the rate of clk. | 878 | * In the simplest case clk_set_rate will only adjust the rate of clk. |
863 | * | ||
864 | * If clk has the CLK_SET_RATE_GATE flag set and it is enabled this call | ||
865 | * will fail; only when the clk is disabled will it be able to change | ||
866 | * its rate. | ||
867 | * | 879 | * |
868 | * Setting the CLK_SET_RATE_PARENT flag allows clk_set_rate to | 880 | * Setting the CLK_SET_RATE_PARENT flag allows the rate change operation to |
869 | * recursively propagate up to clk's parent; whether or not this happens | 881 | * propagate up to clk's parent; whether or not this happens depends on the |
870 | * depends on the outcome of clk's .round_rate implementation. If | 882 | * outcome of clk's .round_rate implementation. If *parent_rate is unchanged |
871 | * *parent_rate is 0 after calling .round_rate then upstream parent | 883 | * after calling .round_rate then upstream parent propagation is ignored. If |
872 | * propagation is ignored. If *parent_rate comes back with a new rate | 884 | * *parent_rate comes back with a new rate for clk's parent then we propagate |
873 | * for clk's parent then we propagate up to clk's parent and set it's | 885 | * up to clk's parent and set it's rate. Upward propagation will continue |
874 | * rate. Upward propagation will continue until either a clk does not | 886 | * until either a clk does not support the CLK_SET_RATE_PARENT flag or |
875 | * support the CLK_SET_RATE_PARENT flag or .round_rate stops requesting | 887 | * .round_rate stops requesting changes to clk's parent_rate. |
876 | * changes to clk's parent_rate. If there is a failure during upstream | ||
877 | * propagation then clk_set_rate will unwind and restore each clk's rate | ||
878 | * that had been successfully changed. Afterwards a rate change abort | ||
879 | * notification will be propagated downstream, starting from the clk | ||
880 | * that failed. | ||
881 | * | 888 | * |
882 | * At the end of all of the rate setting, clk_set_rate internally calls | 889 | * Rate changes are accomplished via tree traversal that also recalculates the |
883 | * __clk_recalc_rates and propagates the rate changes downstream, | 890 | * rates for the clocks and fires off POST_RATE_CHANGE notifiers. |
884 | * starting from the highest clk whose rate was changed. This has the | ||
885 | * added benefit of propagating post-rate change notifiers. | ||
886 | * | ||
887 | * Note that while post-rate change and rate change abort notifications | ||
888 | * are guaranteed to be sent to a clk only once per call to | ||
889 | * clk_set_rate, pre-change notifications will be sent for every clk | ||
890 | * whose rate is changed. Stacking pre-change notifications is noisy | ||
891 | * for the drivers subscribed to them, but this allows drivers to react | ||
892 | * to intermediate clk rate changes up until the point where the final | ||
893 | * rate is achieved at the end of upstream propagation. | ||
894 | * | 891 | * |
895 | * Returns 0 on success, -EERROR otherwise. | 892 | * Returns 0 on success, -EERROR otherwise. |
896 | */ | 893 | */ |
@@ -906,6 +903,11 @@ int clk_set_rate(struct clk *clk, unsigned long rate) | |||
906 | if (rate == clk->rate) | 903 | if (rate == clk->rate) |
907 | goto out; | 904 | goto out; |
908 | 905 | ||
906 | if ((clk->flags & CLK_SET_RATE_GATE) && clk->prepare_count) { | ||
907 | ret = -EBUSY; | ||
908 | goto out; | ||
909 | } | ||
910 | |||
909 | /* calculate new rates and get the topmost changed clock */ | 911 | /* calculate new rates and get the topmost changed clock */ |
910 | top = clk_calc_new_rates(clk, rate); | 912 | top = clk_calc_new_rates(clk, rate); |
911 | if (!top) { | 913 | if (!top) { |
@@ -1175,40 +1177,41 @@ EXPORT_SYMBOL_GPL(clk_set_parent); | |||
1175 | * | 1177 | * |
1176 | * Initializes the lists in struct clk, queries the hardware for the | 1178 | * Initializes the lists in struct clk, queries the hardware for the |
1177 | * parent and rate and sets them both. | 1179 | * parent and rate and sets them both. |
1178 | * | ||
1179 | * Any struct clk passed into __clk_init must have the following members | ||
1180 | * populated: | ||
1181 | * .name | ||
1182 | * .ops | ||
1183 | * .hw | ||
1184 | * .parent_names | ||
1185 | * .num_parents | ||
1186 | * .flags | ||
1187 | * | ||
1188 | * Essentially, everything that would normally be passed into clk_register is | ||
1189 | * assumed to be initialized already in __clk_init. The other members may be | ||
1190 | * populated, but are optional. | ||
1191 | * | ||
1192 | * __clk_init is only exposed via clk-private.h and is intended for use with | ||
1193 | * very large numbers of clocks that need to be statically initialized. It is | ||
1194 | * a layering violation to include clk-private.h from any code which implements | ||
1195 | * a clock's .ops; as such any statically initialized clock data MUST be in a | ||
1196 | * separate C file from the logic that implements it's operations. | ||
1197 | */ | 1180 | */ |
1198 | void __clk_init(struct device *dev, struct clk *clk) | 1181 | int __clk_init(struct device *dev, struct clk *clk) |
1199 | { | 1182 | { |
1200 | int i; | 1183 | int i, ret = 0; |
1201 | struct clk *orphan; | 1184 | struct clk *orphan; |
1202 | struct hlist_node *tmp, *tmp2; | 1185 | struct hlist_node *tmp, *tmp2; |
1203 | 1186 | ||
1204 | if (!clk) | 1187 | if (!clk) |
1205 | return; | 1188 | return -EINVAL; |
1206 | 1189 | ||
1207 | mutex_lock(&prepare_lock); | 1190 | mutex_lock(&prepare_lock); |
1208 | 1191 | ||
1209 | /* check to see if a clock with this name is already registered */ | 1192 | /* check to see if a clock with this name is already registered */ |
1210 | if (__clk_lookup(clk->name)) | 1193 | if (__clk_lookup(clk->name)) { |
1194 | pr_debug("%s: clk %s already initialized\n", | ||
1195 | __func__, clk->name); | ||
1196 | ret = -EEXIST; | ||
1197 | goto out; | ||
1198 | } | ||
1199 | |||
1200 | /* check that clk_ops are sane. See Documentation/clk.txt */ | ||
1201 | if (clk->ops->set_rate && | ||
1202 | !(clk->ops->round_rate && clk->ops->recalc_rate)) { | ||
1203 | pr_warning("%s: %s must implement .round_rate & .recalc_rate\n", | ||
1204 | __func__, clk->name); | ||
1205 | ret = -EINVAL; | ||
1206 | goto out; | ||
1207 | } | ||
1208 | |||
1209 | if (clk->ops->set_parent && !clk->ops->get_parent) { | ||
1210 | pr_warning("%s: %s must implement .get_parent & .set_parent\n", | ||
1211 | __func__, clk->name); | ||
1212 | ret = -EINVAL; | ||
1211 | goto out; | 1213 | goto out; |
1214 | } | ||
1212 | 1215 | ||
1213 | /* throw a WARN if any entries in parent_names are NULL */ | 1216 | /* throw a WARN if any entries in parent_names are NULL */ |
1214 | for (i = 0; i < clk->num_parents; i++) | 1217 | for (i = 0; i < clk->num_parents; i++) |
@@ -1302,48 +1305,130 @@ void __clk_init(struct device *dev, struct clk *clk) | |||
1302 | out: | 1305 | out: |
1303 | mutex_unlock(&prepare_lock); | 1306 | mutex_unlock(&prepare_lock); |
1304 | 1307 | ||
1305 | return; | 1308 | return ret; |
1306 | } | 1309 | } |
1307 | 1310 | ||
1308 | /** | 1311 | /** |
1312 | * __clk_register - register a clock and return a cookie. | ||
1313 | * | ||
1314 | * Same as clk_register, except that the .clk field inside hw shall point to a | ||
1315 | * preallocated (generally statically allocated) struct clk. None of the fields | ||
1316 | * of the struct clk need to be initialized. | ||
1317 | * | ||
1318 | * The data pointed to by .init and .clk field shall NOT be marked as init | ||
1319 | * data. | ||
1320 | * | ||
1321 | * __clk_register is only exposed via clk-private.h and is intended for use with | ||
1322 | * very large numbers of clocks that need to be statically initialized. It is | ||
1323 | * a layering violation to include clk-private.h from any code which implements | ||
1324 | * a clock's .ops; as such any statically initialized clock data MUST be in a | ||
1325 | * separate C file from the logic that implements it's operations. Returns 0 | ||
1326 | * on success, otherwise an error code. | ||
1327 | */ | ||
1328 | struct clk *__clk_register(struct device *dev, struct clk_hw *hw) | ||
1329 | { | ||
1330 | int ret; | ||
1331 | struct clk *clk; | ||
1332 | |||
1333 | clk = hw->clk; | ||
1334 | clk->name = hw->init->name; | ||
1335 | clk->ops = hw->init->ops; | ||
1336 | clk->hw = hw; | ||
1337 | clk->flags = hw->init->flags; | ||
1338 | clk->parent_names = hw->init->parent_names; | ||
1339 | clk->num_parents = hw->init->num_parents; | ||
1340 | |||
1341 | ret = __clk_init(dev, clk); | ||
1342 | if (ret) | ||
1343 | return ERR_PTR(ret); | ||
1344 | |||
1345 | return clk; | ||
1346 | } | ||
1347 | EXPORT_SYMBOL_GPL(__clk_register); | ||
1348 | |||
1349 | /** | ||
1309 | * clk_register - allocate a new clock, register it and return an opaque cookie | 1350 | * clk_register - allocate a new clock, register it and return an opaque cookie |
1310 | * @dev: device that is registering this clock | 1351 | * @dev: device that is registering this clock |
1311 | * @name: clock name | ||
1312 | * @ops: operations this clock supports | ||
1313 | * @hw: link to hardware-specific clock data | 1352 | * @hw: link to hardware-specific clock data |
1314 | * @parent_names: array of string names for all possible parents | ||
1315 | * @num_parents: number of possible parents | ||
1316 | * @flags: framework-level hints and quirks | ||
1317 | * | 1353 | * |
1318 | * clk_register is the primary interface for populating the clock tree with new | 1354 | * clk_register is the primary interface for populating the clock tree with new |
1319 | * clock nodes. It returns a pointer to the newly allocated struct clk which | 1355 | * clock nodes. It returns a pointer to the newly allocated struct clk which |
1320 | * cannot be dereferenced by driver code but may be used in conjuction with the | 1356 | * cannot be dereferenced by driver code but may be used in conjuction with the |
1321 | * rest of the clock API. | 1357 | * rest of the clock API. In the event of an error clk_register will return an |
1358 | * error code; drivers must test for an error code after calling clk_register. | ||
1322 | */ | 1359 | */ |
1323 | struct clk *clk_register(struct device *dev, const char *name, | 1360 | struct clk *clk_register(struct device *dev, struct clk_hw *hw) |
1324 | const struct clk_ops *ops, struct clk_hw *hw, | ||
1325 | char **parent_names, u8 num_parents, unsigned long flags) | ||
1326 | { | 1361 | { |
1362 | int i, ret; | ||
1327 | struct clk *clk; | 1363 | struct clk *clk; |
1328 | 1364 | ||
1329 | clk = kzalloc(sizeof(*clk), GFP_KERNEL); | 1365 | clk = kzalloc(sizeof(*clk), GFP_KERNEL); |
1330 | if (!clk) | 1366 | if (!clk) { |
1331 | return NULL; | 1367 | pr_err("%s: could not allocate clk\n", __func__); |
1368 | ret = -ENOMEM; | ||
1369 | goto fail_out; | ||
1370 | } | ||
1332 | 1371 | ||
1333 | clk->name = name; | 1372 | clk->name = kstrdup(hw->init->name, GFP_KERNEL); |
1334 | clk->ops = ops; | 1373 | if (!clk->name) { |
1374 | pr_err("%s: could not allocate clk->name\n", __func__); | ||
1375 | ret = -ENOMEM; | ||
1376 | goto fail_name; | ||
1377 | } | ||
1378 | clk->ops = hw->init->ops; | ||
1335 | clk->hw = hw; | 1379 | clk->hw = hw; |
1336 | clk->flags = flags; | 1380 | clk->flags = hw->init->flags; |
1337 | clk->parent_names = parent_names; | 1381 | clk->num_parents = hw->init->num_parents; |
1338 | clk->num_parents = num_parents; | ||
1339 | hw->clk = clk; | 1382 | hw->clk = clk; |
1340 | 1383 | ||
1341 | __clk_init(dev, clk); | 1384 | /* allocate local copy in case parent_names is __initdata */ |
1385 | clk->parent_names = kzalloc((sizeof(char*) * clk->num_parents), | ||
1386 | GFP_KERNEL); | ||
1342 | 1387 | ||
1343 | return clk; | 1388 | if (!clk->parent_names) { |
1389 | pr_err("%s: could not allocate clk->parent_names\n", __func__); | ||
1390 | ret = -ENOMEM; | ||
1391 | goto fail_parent_names; | ||
1392 | } | ||
1393 | |||
1394 | |||
1395 | /* copy each string name in case parent_names is __initdata */ | ||
1396 | for (i = 0; i < clk->num_parents; i++) { | ||
1397 | clk->parent_names[i] = kstrdup(hw->init->parent_names[i], | ||
1398 | GFP_KERNEL); | ||
1399 | if (!clk->parent_names[i]) { | ||
1400 | pr_err("%s: could not copy parent_names\n", __func__); | ||
1401 | ret = -ENOMEM; | ||
1402 | goto fail_parent_names_copy; | ||
1403 | } | ||
1404 | } | ||
1405 | |||
1406 | ret = __clk_init(dev, clk); | ||
1407 | if (!ret) | ||
1408 | return clk; | ||
1409 | |||
1410 | fail_parent_names_copy: | ||
1411 | while (--i >= 0) | ||
1412 | kfree(clk->parent_names[i]); | ||
1413 | kfree(clk->parent_names); | ||
1414 | fail_parent_names: | ||
1415 | kfree(clk->name); | ||
1416 | fail_name: | ||
1417 | kfree(clk); | ||
1418 | fail_out: | ||
1419 | return ERR_PTR(ret); | ||
1344 | } | 1420 | } |
1345 | EXPORT_SYMBOL_GPL(clk_register); | 1421 | EXPORT_SYMBOL_GPL(clk_register); |
1346 | 1422 | ||
1423 | /** | ||
1424 | * clk_unregister - unregister a currently registered clock | ||
1425 | * @clk: clock to unregister | ||
1426 | * | ||
1427 | * Currently unimplemented. | ||
1428 | */ | ||
1429 | void clk_unregister(struct clk *clk) {} | ||
1430 | EXPORT_SYMBOL_GPL(clk_unregister); | ||
1431 | |||
1347 | /*** clk rate change notifiers ***/ | 1432 | /*** clk rate change notifiers ***/ |
1348 | 1433 | ||
1349 | /** | 1434 | /** |
diff --git a/drivers/clk/mxs/Makefile b/drivers/clk/mxs/Makefile new file mode 100644 index 000000000000..7bedeec08524 --- /dev/null +++ b/drivers/clk/mxs/Makefile | |||
@@ -0,0 +1,8 @@ | |||
1 | # | ||
2 | # Makefile for mxs specific clk | ||
3 | # | ||
4 | |||
5 | obj-y += clk.o clk-pll.o clk-ref.o clk-div.o clk-frac.o | ||
6 | |||
7 | obj-$(CONFIG_SOC_IMX23) += clk-imx23.o | ||
8 | obj-$(CONFIG_SOC_IMX28) += clk-imx28.o | ||
diff --git a/drivers/clk/mxs/clk-div.c b/drivers/clk/mxs/clk-div.c new file mode 100644 index 000000000000..90e1da93877e --- /dev/null +++ b/drivers/clk/mxs/clk-div.c | |||
@@ -0,0 +1,110 @@ | |||
1 | /* | ||
2 | * Copyright 2012 Freescale Semiconductor, Inc. | ||
3 | * | ||
4 | * The code contained herein is licensed under the GNU General Public | ||
5 | * License. You may obtain a copy of the GNU General Public License | ||
6 | * Version 2 or later at the following locations: | ||
7 | * | ||
8 | * http://www.opensource.org/licenses/gpl-license.html | ||
9 | * http://www.gnu.org/copyleft/gpl.html | ||
10 | */ | ||
11 | |||
12 | #include <linux/clk.h> | ||
13 | #include <linux/clk-provider.h> | ||
14 | #include <linux/err.h> | ||
15 | #include <linux/slab.h> | ||
16 | #include "clk.h" | ||
17 | |||
18 | /** | ||
19 | * struct clk_div - mxs integer divider clock | ||
20 | * @divider: the parent class | ||
21 | * @ops: pointer to clk_ops of parent class | ||
22 | * @reg: register address | ||
23 | * @busy: busy bit shift | ||
24 | * | ||
25 | * The mxs divider clock is a subclass of basic clk_divider with an | ||
26 | * addtional busy bit. | ||
27 | */ | ||
28 | struct clk_div { | ||
29 | struct clk_divider divider; | ||
30 | const struct clk_ops *ops; | ||
31 | void __iomem *reg; | ||
32 | u8 busy; | ||
33 | }; | ||
34 | |||
35 | static inline struct clk_div *to_clk_div(struct clk_hw *hw) | ||
36 | { | ||
37 | struct clk_divider *divider = container_of(hw, struct clk_divider, hw); | ||
38 | |||
39 | return container_of(divider, struct clk_div, divider); | ||
40 | } | ||
41 | |||
42 | static unsigned long clk_div_recalc_rate(struct clk_hw *hw, | ||
43 | unsigned long parent_rate) | ||
44 | { | ||
45 | struct clk_div *div = to_clk_div(hw); | ||
46 | |||
47 | return div->ops->recalc_rate(&div->divider.hw, parent_rate); | ||
48 | } | ||
49 | |||
50 | static long clk_div_round_rate(struct clk_hw *hw, unsigned long rate, | ||
51 | unsigned long *prate) | ||
52 | { | ||
53 | struct clk_div *div = to_clk_div(hw); | ||
54 | |||
55 | return div->ops->round_rate(&div->divider.hw, rate, prate); | ||
56 | } | ||
57 | |||
58 | static int clk_div_set_rate(struct clk_hw *hw, unsigned long rate, | ||
59 | unsigned long parent_rate) | ||
60 | { | ||
61 | struct clk_div *div = to_clk_div(hw); | ||
62 | int ret; | ||
63 | |||
64 | ret = div->ops->set_rate(&div->divider.hw, rate, parent_rate); | ||
65 | if (!ret) | ||
66 | ret = mxs_clk_wait(div->reg, div->busy); | ||
67 | |||
68 | return ret; | ||
69 | } | ||
70 | |||
71 | static struct clk_ops clk_div_ops = { | ||
72 | .recalc_rate = clk_div_recalc_rate, | ||
73 | .round_rate = clk_div_round_rate, | ||
74 | .set_rate = clk_div_set_rate, | ||
75 | }; | ||
76 | |||
77 | struct clk *mxs_clk_div(const char *name, const char *parent_name, | ||
78 | void __iomem *reg, u8 shift, u8 width, u8 busy) | ||
79 | { | ||
80 | struct clk_div *div; | ||
81 | struct clk *clk; | ||
82 | struct clk_init_data init; | ||
83 | |||
84 | div = kzalloc(sizeof(*div), GFP_KERNEL); | ||
85 | if (!div) | ||
86 | return ERR_PTR(-ENOMEM); | ||
87 | |||
88 | init.name = name; | ||
89 | init.ops = &clk_div_ops; | ||
90 | init.flags = CLK_SET_RATE_PARENT; | ||
91 | init.parent_names = (parent_name ? &parent_name: NULL); | ||
92 | init.num_parents = (parent_name ? 1 : 0); | ||
93 | |||
94 | div->reg = reg; | ||
95 | div->busy = busy; | ||
96 | |||
97 | div->divider.reg = reg; | ||
98 | div->divider.shift = shift; | ||
99 | div->divider.width = width; | ||
100 | div->divider.flags = CLK_DIVIDER_ONE_BASED; | ||
101 | div->divider.lock = &mxs_lock; | ||
102 | div->divider.hw.init = &init; | ||
103 | div->ops = &clk_divider_ops; | ||
104 | |||
105 | clk = clk_register(NULL, &div->divider.hw); | ||
106 | if (IS_ERR(clk)) | ||
107 | kfree(div); | ||
108 | |||
109 | return clk; | ||
110 | } | ||
diff --git a/drivers/clk/mxs/clk-frac.c b/drivers/clk/mxs/clk-frac.c new file mode 100644 index 000000000000..e6aa6b567d68 --- /dev/null +++ b/drivers/clk/mxs/clk-frac.c | |||
@@ -0,0 +1,139 @@ | |||
1 | /* | ||
2 | * Copyright 2012 Freescale Semiconductor, Inc. | ||
3 | * | ||
4 | * The code contained herein is licensed under the GNU General Public | ||
5 | * License. You may obtain a copy of the GNU General Public License | ||
6 | * Version 2 or later at the following locations: | ||
7 | * | ||
8 | * http://www.opensource.org/licenses/gpl-license.html | ||
9 | * http://www.gnu.org/copyleft/gpl.html | ||
10 | */ | ||
11 | |||
12 | #include <linux/clk.h> | ||
13 | #include <linux/clk-provider.h> | ||
14 | #include <linux/err.h> | ||
15 | #include <linux/io.h> | ||
16 | #include <linux/slab.h> | ||
17 | #include "clk.h" | ||
18 | |||
19 | /** | ||
20 | * struct clk_frac - mxs fractional divider clock | ||
21 | * @hw: clk_hw for the fractional divider clock | ||
22 | * @reg: register address | ||
23 | * @shift: the divider bit shift | ||
24 | * @width: the divider bit width | ||
25 | * @busy: busy bit shift | ||
26 | * | ||
27 | * The clock is an adjustable fractional divider with a busy bit to wait | ||
28 | * when the divider is adjusted. | ||
29 | */ | ||
30 | struct clk_frac { | ||
31 | struct clk_hw hw; | ||
32 | void __iomem *reg; | ||
33 | u8 shift; | ||
34 | u8 width; | ||
35 | u8 busy; | ||
36 | }; | ||
37 | |||
38 | #define to_clk_frac(_hw) container_of(_hw, struct clk_frac, hw) | ||
39 | |||
40 | static unsigned long clk_frac_recalc_rate(struct clk_hw *hw, | ||
41 | unsigned long parent_rate) | ||
42 | { | ||
43 | struct clk_frac *frac = to_clk_frac(hw); | ||
44 | u32 div; | ||
45 | |||
46 | div = readl_relaxed(frac->reg) >> frac->shift; | ||
47 | div &= (1 << frac->width) - 1; | ||
48 | |||
49 | return (parent_rate >> frac->width) * div; | ||
50 | } | ||
51 | |||
52 | static long clk_frac_round_rate(struct clk_hw *hw, unsigned long rate, | ||
53 | unsigned long *prate) | ||
54 | { | ||
55 | struct clk_frac *frac = to_clk_frac(hw); | ||
56 | unsigned long parent_rate = *prate; | ||
57 | u32 div; | ||
58 | u64 tmp; | ||
59 | |||
60 | if (rate > parent_rate) | ||
61 | return -EINVAL; | ||
62 | |||
63 | tmp = rate; | ||
64 | tmp <<= frac->width; | ||
65 | do_div(tmp, parent_rate); | ||
66 | div = tmp; | ||
67 | |||
68 | if (!div) | ||
69 | return -EINVAL; | ||
70 | |||
71 | return (parent_rate >> frac->width) * div; | ||
72 | } | ||
73 | |||
74 | static int clk_frac_set_rate(struct clk_hw *hw, unsigned long rate, | ||
75 | unsigned long parent_rate) | ||
76 | { | ||
77 | struct clk_frac *frac = to_clk_frac(hw); | ||
78 | unsigned long flags; | ||
79 | u32 div, val; | ||
80 | u64 tmp; | ||
81 | |||
82 | if (rate > parent_rate) | ||
83 | return -EINVAL; | ||
84 | |||
85 | tmp = rate; | ||
86 | tmp <<= frac->width; | ||
87 | do_div(tmp, parent_rate); | ||
88 | div = tmp; | ||
89 | |||
90 | if (!div) | ||
91 | return -EINVAL; | ||
92 | |||
93 | spin_lock_irqsave(&mxs_lock, flags); | ||
94 | |||
95 | val = readl_relaxed(frac->reg); | ||
96 | val &= ~(((1 << frac->width) - 1) << frac->shift); | ||
97 | val |= div << frac->shift; | ||
98 | writel_relaxed(val, frac->reg); | ||
99 | |||
100 | spin_unlock_irqrestore(&mxs_lock, flags); | ||
101 | |||
102 | return mxs_clk_wait(frac->reg, frac->busy); | ||
103 | } | ||
104 | |||
105 | static struct clk_ops clk_frac_ops = { | ||
106 | .recalc_rate = clk_frac_recalc_rate, | ||
107 | .round_rate = clk_frac_round_rate, | ||
108 | .set_rate = clk_frac_set_rate, | ||
109 | }; | ||
110 | |||
111 | struct clk *mxs_clk_frac(const char *name, const char *parent_name, | ||
112 | void __iomem *reg, u8 shift, u8 width, u8 busy) | ||
113 | { | ||
114 | struct clk_frac *frac; | ||
115 | struct clk *clk; | ||
116 | struct clk_init_data init; | ||
117 | |||
118 | frac = kzalloc(sizeof(*frac), GFP_KERNEL); | ||
119 | if (!frac) | ||
120 | return ERR_PTR(-ENOMEM); | ||
121 | |||
122 | init.name = name; | ||
123 | init.ops = &clk_frac_ops; | ||
124 | init.flags = CLK_SET_RATE_PARENT; | ||
125 | init.parent_names = (parent_name ? &parent_name: NULL); | ||
126 | init.num_parents = (parent_name ? 1 : 0); | ||
127 | |||
128 | frac->reg = reg; | ||
129 | frac->shift = shift; | ||
130 | frac->width = width; | ||
131 | frac->busy = busy; | ||
132 | frac->hw.init = &init; | ||
133 | |||
134 | clk = clk_register(NULL, &frac->hw); | ||
135 | if (IS_ERR(clk)) | ||
136 | kfree(frac); | ||
137 | |||
138 | return clk; | ||
139 | } | ||
diff --git a/drivers/clk/mxs/clk-imx23.c b/drivers/clk/mxs/clk-imx23.c new file mode 100644 index 000000000000..dcae11285716 --- /dev/null +++ b/drivers/clk/mxs/clk-imx23.c | |||
@@ -0,0 +1,204 @@ | |||
1 | /* | ||
2 | * Copyright 2012 Freescale Semiconductor, Inc. | ||
3 | * | ||
4 | * The code contained herein is licensed under the GNU General Public | ||
5 | * License. You may obtain a copy of the GNU General Public License | ||
6 | * Version 2 or later at the following locations: | ||
7 | * | ||
8 | * http://www.opensource.org/licenses/gpl-license.html | ||
9 | * http://www.gnu.org/copyleft/gpl.html | ||
10 | */ | ||
11 | |||
12 | #include <linux/clk.h> | ||
13 | #include <linux/clkdev.h> | ||
14 | #include <linux/err.h> | ||
15 | #include <linux/init.h> | ||
16 | #include <linux/io.h> | ||
17 | #include <mach/common.h> | ||
18 | #include <mach/mx23.h> | ||
19 | #include "clk.h" | ||
20 | |||
21 | #define DIGCTRL MX23_IO_ADDRESS(MX23_DIGCTL_BASE_ADDR) | ||
22 | #define CLKCTRL MX23_IO_ADDRESS(MX23_CLKCTRL_BASE_ADDR) | ||
23 | #define PLLCTRL0 (CLKCTRL + 0x0000) | ||
24 | #define CPU (CLKCTRL + 0x0020) | ||
25 | #define HBUS (CLKCTRL + 0x0030) | ||
26 | #define XBUS (CLKCTRL + 0x0040) | ||
27 | #define XTAL (CLKCTRL + 0x0050) | ||
28 | #define PIX (CLKCTRL + 0x0060) | ||
29 | #define SSP (CLKCTRL + 0x0070) | ||
30 | #define GPMI (CLKCTRL + 0x0080) | ||
31 | #define SPDIF (CLKCTRL + 0x0090) | ||
32 | #define EMI (CLKCTRL + 0x00a0) | ||
33 | #define SAIF (CLKCTRL + 0x00c0) | ||
34 | #define TV (CLKCTRL + 0x00d0) | ||
35 | #define ETM (CLKCTRL + 0x00e0) | ||
36 | #define FRAC (CLKCTRL + 0x00f0) | ||
37 | #define CLKSEQ (CLKCTRL + 0x0110) | ||
38 | |||
39 | #define BP_CPU_INTERRUPT_WAIT 12 | ||
40 | #define BP_CLKSEQ_BYPASS_SAIF 0 | ||
41 | #define BP_CLKSEQ_BYPASS_SSP 5 | ||
42 | #define BP_SAIF_DIV_FRAC_EN 16 | ||
43 | #define BP_FRAC_IOFRAC 24 | ||
44 | |||
45 | static void __init clk_misc_init(void) | ||
46 | { | ||
47 | u32 val; | ||
48 | |||
49 | /* Gate off cpu clock in WFI for power saving */ | ||
50 | __mxs_setl(1 << BP_CPU_INTERRUPT_WAIT, CPU); | ||
51 | |||
52 | /* Clear BYPASS for SAIF */ | ||
53 | __mxs_clrl(1 << BP_CLKSEQ_BYPASS_SAIF, CLKSEQ); | ||
54 | |||
55 | /* SAIF has to use frac div for functional operation */ | ||
56 | val = readl_relaxed(SAIF); | ||
57 | val |= 1 << BP_SAIF_DIV_FRAC_EN; | ||
58 | writel_relaxed(val, SAIF); | ||
59 | |||
60 | /* | ||
61 | * Source ssp clock from ref_io than ref_xtal, | ||
62 | * as ref_xtal only provides 24 MHz as maximum. | ||
63 | */ | ||
64 | __mxs_clrl(1 << BP_CLKSEQ_BYPASS_SSP, CLKSEQ); | ||
65 | |||
66 | /* | ||
67 | * 480 MHz seems too high to be ssp clock source directly, | ||
68 | * so set frac to get a 288 MHz ref_io. | ||
69 | */ | ||
70 | __mxs_clrl(0x3f << BP_FRAC_IOFRAC, FRAC); | ||
71 | __mxs_setl(30 << BP_FRAC_IOFRAC, FRAC); | ||
72 | } | ||
73 | |||
74 | static struct clk_lookup uart_lookups[] __initdata = { | ||
75 | { .dev_id = "duart", }, | ||
76 | { .dev_id = "mxs-auart.0", }, | ||
77 | { .dev_id = "mxs-auart.1", }, | ||
78 | { .dev_id = "8006c000.serial", }, | ||
79 | { .dev_id = "8006e000.serial", }, | ||
80 | { .dev_id = "80070000.serial", }, | ||
81 | }; | ||
82 | |||
83 | static struct clk_lookup hbus_lookups[] __initdata = { | ||
84 | { .dev_id = "mxs-dma-apbh", }, | ||
85 | { .dev_id = "80004000.dma-apbh", }, | ||
86 | }; | ||
87 | |||
88 | static struct clk_lookup xbus_lookups[] __initdata = { | ||
89 | { .dev_id = "duart", .con_id = "apb_pclk"}, | ||
90 | { .dev_id = "mxs-dma-apbx", }, | ||
91 | { .dev_id = "80024000.dma-apbx", }, | ||
92 | }; | ||
93 | |||
94 | static struct clk_lookup ssp_lookups[] __initdata = { | ||
95 | { .dev_id = "mxs-mmc.0", }, | ||
96 | { .dev_id = "mxs-mmc.1", }, | ||
97 | { .dev_id = "80010000.ssp", }, | ||
98 | { .dev_id = "80034000.ssp", }, | ||
99 | }; | ||
100 | |||
101 | static struct clk_lookup lcdif_lookups[] __initdata = { | ||
102 | { .dev_id = "imx23-fb", }, | ||
103 | { .dev_id = "80030000.lcdif", }, | ||
104 | }; | ||
105 | |||
106 | static struct clk_lookup gpmi_lookups[] __initdata = { | ||
107 | { .dev_id = "imx23-gpmi-nand", }, | ||
108 | { .dev_id = "8000c000.gpmi", }, | ||
109 | }; | ||
110 | |||
111 | static const char *sel_pll[] __initconst = { "pll", "ref_xtal", }; | ||
112 | static const char *sel_cpu[] __initconst = { "ref_cpu", "ref_xtal", }; | ||
113 | static const char *sel_pix[] __initconst = { "ref_pix", "ref_xtal", }; | ||
114 | static const char *sel_io[] __initconst = { "ref_io", "ref_xtal", }; | ||
115 | static const char *cpu_sels[] __initconst = { "cpu_pll", "cpu_xtal", }; | ||
116 | static const char *emi_sels[] __initconst = { "emi_pll", "emi_xtal", }; | ||
117 | |||
118 | enum imx23_clk { | ||
119 | ref_xtal, pll, ref_cpu, ref_emi, ref_pix, ref_io, saif_sel, | ||
120 | lcdif_sel, gpmi_sel, ssp_sel, emi_sel, cpu, etm_sel, cpu_pll, | ||
121 | cpu_xtal, hbus, xbus, lcdif_div, ssp_div, gpmi_div, emi_pll, | ||
122 | emi_xtal, etm_div, saif_div, clk32k_div, rtc, adc, spdif_div, | ||
123 | clk32k, dri, pwm, filt, uart, ssp, gpmi, spdif, emi, saif, | ||
124 | lcdif, etm, usb, usb_pwr, | ||
125 | clk_max | ||
126 | }; | ||
127 | |||
128 | static struct clk *clks[clk_max]; | ||
129 | |||
130 | static enum imx23_clk clks_init_on[] __initdata = { | ||
131 | cpu, hbus, xbus, emi, uart, | ||
132 | }; | ||
133 | |||
134 | int __init mx23_clocks_init(void) | ||
135 | { | ||
136 | int i; | ||
137 | |||
138 | clk_misc_init(); | ||
139 | |||
140 | clks[ref_xtal] = mxs_clk_fixed("ref_xtal", 24000000); | ||
141 | clks[pll] = mxs_clk_pll("pll", "ref_xtal", PLLCTRL0, 16, 480000000); | ||
142 | clks[ref_cpu] = mxs_clk_ref("ref_cpu", "pll", FRAC, 0); | ||
143 | clks[ref_emi] = mxs_clk_ref("ref_emi", "pll", FRAC, 1); | ||
144 | clks[ref_pix] = mxs_clk_ref("ref_pix", "pll", FRAC, 2); | ||
145 | clks[ref_io] = mxs_clk_ref("ref_io", "pll", FRAC, 3); | ||
146 | clks[saif_sel] = mxs_clk_mux("saif_sel", CLKSEQ, 0, 1, sel_pll, ARRAY_SIZE(sel_pll)); | ||
147 | clks[lcdif_sel] = mxs_clk_mux("lcdif_sel", CLKSEQ, 1, 1, sel_pix, ARRAY_SIZE(sel_pix)); | ||
148 | clks[gpmi_sel] = mxs_clk_mux("gpmi_sel", CLKSEQ, 4, 1, sel_io, ARRAY_SIZE(sel_io)); | ||
149 | clks[ssp_sel] = mxs_clk_mux("ssp_sel", CLKSEQ, 5, 1, sel_io, ARRAY_SIZE(sel_io)); | ||
150 | clks[emi_sel] = mxs_clk_mux("emi_sel", CLKSEQ, 6, 1, emi_sels, ARRAY_SIZE(emi_sels)); | ||
151 | clks[cpu] = mxs_clk_mux("cpu", CLKSEQ, 7, 1, cpu_sels, ARRAY_SIZE(cpu_sels)); | ||
152 | clks[etm_sel] = mxs_clk_mux("etm_sel", CLKSEQ, 8, 1, sel_cpu, ARRAY_SIZE(sel_cpu)); | ||
153 | clks[cpu_pll] = mxs_clk_div("cpu_pll", "ref_cpu", CPU, 0, 6, 28); | ||
154 | clks[cpu_xtal] = mxs_clk_div("cpu_xtal", "ref_xtal", CPU, 16, 10, 29); | ||
155 | clks[hbus] = mxs_clk_div("hbus", "cpu", HBUS, 0, 5, 29); | ||
156 | clks[xbus] = mxs_clk_div("xbus", "ref_xtal", XBUS, 0, 10, 31); | ||
157 | clks[lcdif_div] = mxs_clk_div("lcdif_div", "lcdif_sel", PIX, 0, 12, 29); | ||
158 | clks[ssp_div] = mxs_clk_div("ssp_div", "ssp_sel", SSP, 0, 9, 29); | ||
159 | clks[gpmi_div] = mxs_clk_div("gpmi_div", "gpmi_sel", GPMI, 0, 10, 29); | ||
160 | clks[emi_pll] = mxs_clk_div("emi_pll", "ref_emi", EMI, 0, 6, 28); | ||
161 | clks[emi_xtal] = mxs_clk_div("emi_xtal", "ref_xtal", EMI, 8, 4, 29); | ||
162 | clks[etm_div] = mxs_clk_div("etm_div", "etm_sel", ETM, 0, 6, 29); | ||
163 | clks[saif_div] = mxs_clk_frac("saif_div", "saif_sel", SAIF, 0, 16, 29); | ||
164 | clks[clk32k_div] = mxs_clk_fixed_factor("clk32k_div", "ref_xtal", 1, 750); | ||
165 | clks[rtc] = mxs_clk_fixed_factor("rtc", "ref_xtal", 1, 768); | ||
166 | clks[adc] = mxs_clk_fixed_factor("adc", "clk32k", 1, 16); | ||
167 | clks[spdif_div] = mxs_clk_fixed_factor("spdif_div", "pll", 1, 4); | ||
168 | clks[clk32k] = mxs_clk_gate("clk32k", "clk32k_div", XTAL, 26); | ||
169 | clks[dri] = mxs_clk_gate("dri", "ref_xtal", XTAL, 28); | ||
170 | clks[pwm] = mxs_clk_gate("pwm", "ref_xtal", XTAL, 29); | ||
171 | clks[filt] = mxs_clk_gate("filt", "ref_xtal", XTAL, 30); | ||
172 | clks[uart] = mxs_clk_gate("uart", "ref_xtal", XTAL, 31); | ||
173 | clks[ssp] = mxs_clk_gate("ssp", "ssp_div", SSP, 31); | ||
174 | clks[gpmi] = mxs_clk_gate("gpmi", "gpmi_div", GPMI, 31); | ||
175 | clks[spdif] = mxs_clk_gate("spdif", "spdif_div", SPDIF, 31); | ||
176 | clks[emi] = mxs_clk_gate("emi", "emi_sel", EMI, 31); | ||
177 | clks[saif] = mxs_clk_gate("saif", "saif_div", SAIF, 31); | ||
178 | clks[lcdif] = mxs_clk_gate("lcdif", "lcdif_div", PIX, 31); | ||
179 | clks[etm] = mxs_clk_gate("etm", "etm_div", ETM, 31); | ||
180 | clks[usb] = mxs_clk_gate("usb", "usb_pwr", DIGCTRL, 2); | ||
181 | clks[usb_pwr] = clk_register_gate(NULL, "usb_pwr", "pll", 0, PLLCTRL0, 18, 0, &mxs_lock); | ||
182 | |||
183 | for (i = 0; i < ARRAY_SIZE(clks); i++) | ||
184 | if (IS_ERR(clks[i])) { | ||
185 | pr_err("i.MX23 clk %d: register failed with %ld\n", | ||
186 | i, PTR_ERR(clks[i])); | ||
187 | return PTR_ERR(clks[i]); | ||
188 | } | ||
189 | |||
190 | clk_register_clkdev(clks[clk32k], NULL, "timrot"); | ||
191 | clk_register_clkdevs(clks[hbus], hbus_lookups, ARRAY_SIZE(hbus_lookups)); | ||
192 | clk_register_clkdevs(clks[xbus], xbus_lookups, ARRAY_SIZE(xbus_lookups)); | ||
193 | clk_register_clkdevs(clks[uart], uart_lookups, ARRAY_SIZE(uart_lookups)); | ||
194 | clk_register_clkdevs(clks[ssp], ssp_lookups, ARRAY_SIZE(ssp_lookups)); | ||
195 | clk_register_clkdevs(clks[gpmi], gpmi_lookups, ARRAY_SIZE(gpmi_lookups)); | ||
196 | clk_register_clkdevs(clks[lcdif], lcdif_lookups, ARRAY_SIZE(lcdif_lookups)); | ||
197 | |||
198 | for (i = 0; i < ARRAY_SIZE(clks_init_on); i++) | ||
199 | clk_prepare_enable(clks[clks_init_on[i]]); | ||
200 | |||
201 | mxs_timer_init(MX23_INT_TIMER0); | ||
202 | |||
203 | return 0; | ||
204 | } | ||
diff --git a/drivers/clk/mxs/clk-imx28.c b/drivers/clk/mxs/clk-imx28.c new file mode 100644 index 000000000000..b2a3257d4f66 --- /dev/null +++ b/drivers/clk/mxs/clk-imx28.c | |||
@@ -0,0 +1,337 @@ | |||
1 | /* | ||
2 | * Copyright 2012 Freescale Semiconductor, Inc. | ||
3 | * | ||
4 | * The code contained herein is licensed under the GNU General Public | ||
5 | * License. You may obtain a copy of the GNU General Public License | ||
6 | * Version 2 or later at the following locations: | ||
7 | * | ||
8 | * http://www.opensource.org/licenses/gpl-license.html | ||
9 | * http://www.gnu.org/copyleft/gpl.html | ||
10 | */ | ||
11 | |||
12 | #include <linux/clk.h> | ||
13 | #include <linux/clkdev.h> | ||
14 | #include <linux/err.h> | ||
15 | #include <linux/init.h> | ||
16 | #include <linux/io.h> | ||
17 | #include <mach/common.h> | ||
18 | #include <mach/mx28.h> | ||
19 | #include "clk.h" | ||
20 | |||
21 | #define CLKCTRL MX28_IO_ADDRESS(MX28_CLKCTRL_BASE_ADDR) | ||
22 | #define PLL0CTRL0 (CLKCTRL + 0x0000) | ||
23 | #define PLL1CTRL0 (CLKCTRL + 0x0020) | ||
24 | #define PLL2CTRL0 (CLKCTRL + 0x0040) | ||
25 | #define CPU (CLKCTRL + 0x0050) | ||
26 | #define HBUS (CLKCTRL + 0x0060) | ||
27 | #define XBUS (CLKCTRL + 0x0070) | ||
28 | #define XTAL (CLKCTRL + 0x0080) | ||
29 | #define SSP0 (CLKCTRL + 0x0090) | ||
30 | #define SSP1 (CLKCTRL + 0x00a0) | ||
31 | #define SSP2 (CLKCTRL + 0x00b0) | ||
32 | #define SSP3 (CLKCTRL + 0x00c0) | ||
33 | #define GPMI (CLKCTRL + 0x00d0) | ||
34 | #define SPDIF (CLKCTRL + 0x00e0) | ||
35 | #define EMI (CLKCTRL + 0x00f0) | ||
36 | #define SAIF0 (CLKCTRL + 0x0100) | ||
37 | #define SAIF1 (CLKCTRL + 0x0110) | ||
38 | #define LCDIF (CLKCTRL + 0x0120) | ||
39 | #define ETM (CLKCTRL + 0x0130) | ||
40 | #define ENET (CLKCTRL + 0x0140) | ||
41 | #define FLEXCAN (CLKCTRL + 0x0160) | ||
42 | #define FRAC0 (CLKCTRL + 0x01b0) | ||
43 | #define FRAC1 (CLKCTRL + 0x01c0) | ||
44 | #define CLKSEQ (CLKCTRL + 0x01d0) | ||
45 | |||
46 | #define BP_CPU_INTERRUPT_WAIT 12 | ||
47 | #define BP_SAIF_DIV_FRAC_EN 16 | ||
48 | #define BP_ENET_DIV_TIME 21 | ||
49 | #define BP_ENET_SLEEP 31 | ||
50 | #define BP_CLKSEQ_BYPASS_SAIF0 0 | ||
51 | #define BP_CLKSEQ_BYPASS_SSP0 3 | ||
52 | #define BP_FRAC0_IO1FRAC 16 | ||
53 | #define BP_FRAC0_IO0FRAC 24 | ||
54 | |||
55 | #define DIGCTRL MX28_IO_ADDRESS(MX28_DIGCTL_BASE_ADDR) | ||
56 | #define BP_SAIF_CLKMUX 10 | ||
57 | |||
58 | /* | ||
59 | * HW_SAIF_CLKMUX_SEL: | ||
60 | * DIRECT(0x0): SAIF0 clock pins selected for SAIF0 input clocks, and SAIF1 | ||
61 | * clock pins selected for SAIF1 input clocks. | ||
62 | * CROSSINPUT(0x1): SAIF1 clock inputs selected for SAIF0 input clocks, and | ||
63 | * SAIF0 clock inputs selected for SAIF1 input clocks. | ||
64 | * EXTMSTR0(0x2): SAIF0 clock pin selected for both SAIF0 and SAIF1 input | ||
65 | * clocks. | ||
66 | * EXTMSTR1(0x3): SAIF1 clock pin selected for both SAIF0 and SAIF1 input | ||
67 | * clocks. | ||
68 | */ | ||
69 | int mxs_saif_clkmux_select(unsigned int clkmux) | ||
70 | { | ||
71 | if (clkmux > 0x3) | ||
72 | return -EINVAL; | ||
73 | |||
74 | __mxs_clrl(0x3 << BP_SAIF_CLKMUX, DIGCTRL); | ||
75 | __mxs_setl(clkmux << BP_SAIF_CLKMUX, DIGCTRL); | ||
76 | |||
77 | return 0; | ||
78 | } | ||
79 | |||
80 | static void __init clk_misc_init(void) | ||
81 | { | ||
82 | u32 val; | ||
83 | |||
84 | /* Gate off cpu clock in WFI for power saving */ | ||
85 | __mxs_setl(1 << BP_CPU_INTERRUPT_WAIT, CPU); | ||
86 | |||
87 | /* 0 is a bad default value for a divider */ | ||
88 | __mxs_setl(1 << BP_ENET_DIV_TIME, ENET); | ||
89 | |||
90 | /* Clear BYPASS for SAIF */ | ||
91 | __mxs_clrl(0x3 << BP_CLKSEQ_BYPASS_SAIF0, CLKSEQ); | ||
92 | |||
93 | /* SAIF has to use frac div for functional operation */ | ||
94 | val = readl_relaxed(SAIF0); | ||
95 | val |= 1 << BP_SAIF_DIV_FRAC_EN; | ||
96 | writel_relaxed(val, SAIF0); | ||
97 | |||
98 | val = readl_relaxed(SAIF1); | ||
99 | val |= 1 << BP_SAIF_DIV_FRAC_EN; | ||
100 | writel_relaxed(val, SAIF1); | ||
101 | |||
102 | /* Extra fec clock setting */ | ||
103 | val = readl_relaxed(ENET); | ||
104 | val &= ~(1 << BP_ENET_SLEEP); | ||
105 | writel_relaxed(val, ENET); | ||
106 | |||
107 | /* | ||
108 | * Source ssp clock from ref_io than ref_xtal, | ||
109 | * as ref_xtal only provides 24 MHz as maximum. | ||
110 | */ | ||
111 | __mxs_clrl(0xf << BP_CLKSEQ_BYPASS_SSP0, CLKSEQ); | ||
112 | |||
113 | /* | ||
114 | * 480 MHz seems too high to be ssp clock source directly, | ||
115 | * so set frac0 to get a 288 MHz ref_io0. | ||
116 | */ | ||
117 | val = readl_relaxed(FRAC0); | ||
118 | val &= ~(0x3f << BP_FRAC0_IO0FRAC); | ||
119 | val |= 30 << BP_FRAC0_IO0FRAC; | ||
120 | writel_relaxed(val, FRAC0); | ||
121 | } | ||
122 | |||
123 | static struct clk_lookup uart_lookups[] __initdata = { | ||
124 | { .dev_id = "duart", }, | ||
125 | { .dev_id = "mxs-auart.0", }, | ||
126 | { .dev_id = "mxs-auart.1", }, | ||
127 | { .dev_id = "mxs-auart.2", }, | ||
128 | { .dev_id = "mxs-auart.3", }, | ||
129 | { .dev_id = "mxs-auart.4", }, | ||
130 | { .dev_id = "8006a000.serial", }, | ||
131 | { .dev_id = "8006c000.serial", }, | ||
132 | { .dev_id = "8006e000.serial", }, | ||
133 | { .dev_id = "80070000.serial", }, | ||
134 | { .dev_id = "80072000.serial", }, | ||
135 | { .dev_id = "80074000.serial", }, | ||
136 | }; | ||
137 | |||
138 | static struct clk_lookup hbus_lookups[] __initdata = { | ||
139 | { .dev_id = "mxs-dma-apbh", }, | ||
140 | { .dev_id = "80004000.dma-apbh", }, | ||
141 | }; | ||
142 | |||
143 | static struct clk_lookup xbus_lookups[] __initdata = { | ||
144 | { .dev_id = "duart", .con_id = "apb_pclk"}, | ||
145 | { .dev_id = "mxs-dma-apbx", }, | ||
146 | { .dev_id = "80024000.dma-apbx", }, | ||
147 | }; | ||
148 | |||
149 | static struct clk_lookup ssp0_lookups[] __initdata = { | ||
150 | { .dev_id = "mxs-mmc.0", }, | ||
151 | { .dev_id = "80010000.ssp", }, | ||
152 | }; | ||
153 | |||
154 | static struct clk_lookup ssp1_lookups[] __initdata = { | ||
155 | { .dev_id = "mxs-mmc.1", }, | ||
156 | { .dev_id = "80012000.ssp", }, | ||
157 | }; | ||
158 | |||
159 | static struct clk_lookup ssp2_lookups[] __initdata = { | ||
160 | { .dev_id = "mxs-mmc.2", }, | ||
161 | { .dev_id = "80014000.ssp", }, | ||
162 | }; | ||
163 | |||
164 | static struct clk_lookup ssp3_lookups[] __initdata = { | ||
165 | { .dev_id = "mxs-mmc.3", }, | ||
166 | { .dev_id = "80016000.ssp", }, | ||
167 | }; | ||
168 | |||
169 | static struct clk_lookup lcdif_lookups[] __initdata = { | ||
170 | { .dev_id = "imx28-fb", }, | ||
171 | { .dev_id = "80030000.lcdif", }, | ||
172 | }; | ||
173 | |||
174 | static struct clk_lookup gpmi_lookups[] __initdata = { | ||
175 | { .dev_id = "imx28-gpmi-nand", }, | ||
176 | { .dev_id = "8000c000.gpmi", }, | ||
177 | }; | ||
178 | |||
179 | static struct clk_lookup fec_lookups[] __initdata = { | ||
180 | { .dev_id = "imx28-fec.0", }, | ||
181 | { .dev_id = "imx28-fec.1", }, | ||
182 | { .dev_id = "800f0000.ethernet", }, | ||
183 | { .dev_id = "800f4000.ethernet", }, | ||
184 | }; | ||
185 | |||
186 | static struct clk_lookup can0_lookups[] __initdata = { | ||
187 | { .dev_id = "flexcan.0", }, | ||
188 | { .dev_id = "80032000.can", }, | ||
189 | }; | ||
190 | |||
191 | static struct clk_lookup can1_lookups[] __initdata = { | ||
192 | { .dev_id = "flexcan.1", }, | ||
193 | { .dev_id = "80034000.can", }, | ||
194 | }; | ||
195 | |||
196 | static struct clk_lookup saif0_lookups[] __initdata = { | ||
197 | { .dev_id = "mxs-saif.0", }, | ||
198 | { .dev_id = "80042000.saif", }, | ||
199 | }; | ||
200 | |||
201 | static struct clk_lookup saif1_lookups[] __initdata = { | ||
202 | { .dev_id = "mxs-saif.1", }, | ||
203 | { .dev_id = "80046000.saif", }, | ||
204 | }; | ||
205 | |||
206 | static const char *sel_cpu[] __initconst = { "ref_cpu", "ref_xtal", }; | ||
207 | static const char *sel_io0[] __initconst = { "ref_io0", "ref_xtal", }; | ||
208 | static const char *sel_io1[] __initconst = { "ref_io1", "ref_xtal", }; | ||
209 | static const char *sel_pix[] __initconst = { "ref_pix", "ref_xtal", }; | ||
210 | static const char *sel_gpmi[] __initconst = { "ref_gpmi", "ref_xtal", }; | ||
211 | static const char *sel_pll0[] __initconst = { "pll0", "ref_xtal", }; | ||
212 | static const char *cpu_sels[] __initconst = { "cpu_pll", "cpu_xtal", }; | ||
213 | static const char *emi_sels[] __initconst = { "emi_pll", "emi_xtal", }; | ||
214 | static const char *ptp_sels[] __initconst = { "ref_xtal", "pll0", }; | ||
215 | |||
216 | enum imx28_clk { | ||
217 | ref_xtal, pll0, pll1, pll2, ref_cpu, ref_emi, ref_io0, ref_io1, | ||
218 | ref_pix, ref_hsadc, ref_gpmi, saif0_sel, saif1_sel, gpmi_sel, | ||
219 | ssp0_sel, ssp1_sel, ssp2_sel, ssp3_sel, emi_sel, etm_sel, | ||
220 | lcdif_sel, cpu, ptp_sel, cpu_pll, cpu_xtal, hbus, xbus, | ||
221 | ssp0_div, ssp1_div, ssp2_div, ssp3_div, gpmi_div, emi_pll, | ||
222 | emi_xtal, lcdif_div, etm_div, ptp, saif0_div, saif1_div, | ||
223 | clk32k_div, rtc, lradc, spdif_div, clk32k, pwm, uart, ssp0, | ||
224 | ssp1, ssp2, ssp3, gpmi, spdif, emi, saif0, saif1, lcdif, etm, | ||
225 | fec, can0, can1, usb0, usb1, usb0_pwr, usb1_pwr, enet_out, | ||
226 | clk_max | ||
227 | }; | ||
228 | |||
229 | static struct clk *clks[clk_max]; | ||
230 | |||
231 | static enum imx28_clk clks_init_on[] __initdata = { | ||
232 | cpu, hbus, xbus, emi, uart, | ||
233 | }; | ||
234 | |||
235 | int __init mx28_clocks_init(void) | ||
236 | { | ||
237 | int i; | ||
238 | |||
239 | clk_misc_init(); | ||
240 | |||
241 | clks[ref_xtal] = mxs_clk_fixed("ref_xtal", 24000000); | ||
242 | clks[pll0] = mxs_clk_pll("pll0", "ref_xtal", PLL0CTRL0, 17, 480000000); | ||
243 | clks[pll1] = mxs_clk_pll("pll1", "ref_xtal", PLL1CTRL0, 17, 480000000); | ||
244 | clks[pll2] = mxs_clk_pll("pll2", "ref_xtal", PLL2CTRL0, 23, 50000000); | ||
245 | clks[ref_cpu] = mxs_clk_ref("ref_cpu", "pll0", FRAC0, 0); | ||
246 | clks[ref_emi] = mxs_clk_ref("ref_emi", "pll0", FRAC0, 1); | ||
247 | clks[ref_io0] = mxs_clk_ref("ref_io0", "pll0", FRAC0, 2); | ||
248 | clks[ref_io1] = mxs_clk_ref("ref_io1", "pll0", FRAC0, 3); | ||
249 | clks[ref_pix] = mxs_clk_ref("ref_pix", "pll0", FRAC1, 0); | ||
250 | clks[ref_hsadc] = mxs_clk_ref("ref_hsadc", "pll0", FRAC1, 1); | ||
251 | clks[ref_gpmi] = mxs_clk_ref("ref_gpmi", "pll0", FRAC1, 2); | ||
252 | clks[saif0_sel] = mxs_clk_mux("saif0_sel", CLKSEQ, 0, 1, sel_pll0, ARRAY_SIZE(sel_pll0)); | ||
253 | clks[saif1_sel] = mxs_clk_mux("saif1_sel", CLKSEQ, 1, 1, sel_pll0, ARRAY_SIZE(sel_pll0)); | ||
254 | clks[gpmi_sel] = mxs_clk_mux("gpmi_sel", CLKSEQ, 2, 1, sel_gpmi, ARRAY_SIZE(sel_gpmi)); | ||
255 | clks[ssp0_sel] = mxs_clk_mux("ssp0_sel", CLKSEQ, 3, 1, sel_io0, ARRAY_SIZE(sel_io0)); | ||
256 | clks[ssp1_sel] = mxs_clk_mux("ssp1_sel", CLKSEQ, 4, 1, sel_io0, ARRAY_SIZE(sel_io0)); | ||
257 | clks[ssp2_sel] = mxs_clk_mux("ssp2_sel", CLKSEQ, 5, 1, sel_io1, ARRAY_SIZE(sel_io1)); | ||
258 | clks[ssp3_sel] = mxs_clk_mux("ssp3_sel", CLKSEQ, 6, 1, sel_io1, ARRAY_SIZE(sel_io1)); | ||
259 | clks[emi_sel] = mxs_clk_mux("emi_sel", CLKSEQ, 7, 1, emi_sels, ARRAY_SIZE(emi_sels)); | ||
260 | clks[etm_sel] = mxs_clk_mux("etm_sel", CLKSEQ, 8, 1, sel_cpu, ARRAY_SIZE(sel_cpu)); | ||
261 | clks[lcdif_sel] = mxs_clk_mux("lcdif_sel", CLKSEQ, 14, 1, sel_pix, ARRAY_SIZE(sel_pix)); | ||
262 | clks[cpu] = mxs_clk_mux("cpu", CLKSEQ, 18, 1, cpu_sels, ARRAY_SIZE(cpu_sels)); | ||
263 | clks[ptp_sel] = mxs_clk_mux("ptp_sel", ENET, 19, 1, ptp_sels, ARRAY_SIZE(ptp_sels)); | ||
264 | clks[cpu_pll] = mxs_clk_div("cpu_pll", "ref_cpu", CPU, 0, 6, 28); | ||
265 | clks[cpu_xtal] = mxs_clk_div("cpu_xtal", "ref_xtal", CPU, 16, 10, 29); | ||
266 | clks[hbus] = mxs_clk_div("hbus", "cpu", HBUS, 0, 5, 31); | ||
267 | clks[xbus] = mxs_clk_div("xbus", "ref_xtal", XBUS, 0, 10, 31); | ||
268 | clks[ssp0_div] = mxs_clk_div("ssp0_div", "ssp0_sel", SSP0, 0, 9, 29); | ||
269 | clks[ssp1_div] = mxs_clk_div("ssp1_div", "ssp1_sel", SSP1, 0, 9, 29); | ||
270 | clks[ssp2_div] = mxs_clk_div("ssp2_div", "ssp2_sel", SSP2, 0, 9, 29); | ||
271 | clks[ssp3_div] = mxs_clk_div("ssp3_div", "ssp3_sel", SSP3, 0, 9, 29); | ||
272 | clks[gpmi_div] = mxs_clk_div("gpmi_div", "gpmi_sel", GPMI, 0, 10, 29); | ||
273 | clks[emi_pll] = mxs_clk_div("emi_pll", "ref_emi", EMI, 0, 6, 28); | ||
274 | clks[emi_xtal] = mxs_clk_div("emi_xtal", "ref_xtal", EMI, 8, 4, 29); | ||
275 | clks[lcdif_div] = mxs_clk_div("lcdif_div", "lcdif_sel", LCDIF, 0, 13, 29); | ||
276 | clks[etm_div] = mxs_clk_div("etm_div", "etm_sel", ETM, 0, 7, 29); | ||
277 | clks[ptp] = mxs_clk_div("ptp", "ptp_sel", ENET, 21, 6, 27); | ||
278 | clks[saif0_div] = mxs_clk_frac("saif0_div", "saif0_sel", SAIF0, 0, 16, 29); | ||
279 | clks[saif1_div] = mxs_clk_frac("saif1_div", "saif1_sel", SAIF1, 0, 16, 29); | ||
280 | clks[clk32k_div] = mxs_clk_fixed_factor("clk32k_div", "ref_xtal", 1, 750); | ||
281 | clks[rtc] = mxs_clk_fixed_factor("rtc", "ref_xtal", 1, 768); | ||
282 | clks[lradc] = mxs_clk_fixed_factor("lradc", "clk32k", 1, 16); | ||
283 | clks[spdif_div] = mxs_clk_fixed_factor("spdif_div", "pll0", 1, 4); | ||
284 | clks[clk32k] = mxs_clk_gate("clk32k", "clk32k_div", XTAL, 26); | ||
285 | clks[pwm] = mxs_clk_gate("pwm", "ref_xtal", XTAL, 29); | ||
286 | clks[uart] = mxs_clk_gate("uart", "ref_xtal", XTAL, 31); | ||
287 | clks[ssp0] = mxs_clk_gate("ssp0", "ssp0_div", SSP0, 31); | ||
288 | clks[ssp1] = mxs_clk_gate("ssp1", "ssp1_div", SSP1, 31); | ||
289 | clks[ssp2] = mxs_clk_gate("ssp2", "ssp2_div", SSP2, 31); | ||
290 | clks[ssp3] = mxs_clk_gate("ssp3", "ssp3_div", SSP3, 31); | ||
291 | clks[gpmi] = mxs_clk_gate("gpmi", "gpmi_div", GPMI, 31); | ||
292 | clks[spdif] = mxs_clk_gate("spdif", "spdif_div", SPDIF, 31); | ||
293 | clks[emi] = mxs_clk_gate("emi", "emi_sel", EMI, 31); | ||
294 | clks[saif0] = mxs_clk_gate("saif0", "saif0_div", SAIF0, 31); | ||
295 | clks[saif1] = mxs_clk_gate("saif1", "saif1_div", SAIF1, 31); | ||
296 | clks[lcdif] = mxs_clk_gate("lcdif", "lcdif_div", LCDIF, 31); | ||
297 | clks[etm] = mxs_clk_gate("etm", "etm_div", ETM, 31); | ||
298 | clks[fec] = mxs_clk_gate("fec", "hbus", ENET, 30); | ||
299 | clks[can0] = mxs_clk_gate("can0", "ref_xtal", FLEXCAN, 30); | ||
300 | clks[can1] = mxs_clk_gate("can1", "ref_xtal", FLEXCAN, 28); | ||
301 | clks[usb0] = mxs_clk_gate("usb0", "usb0_pwr", DIGCTRL, 2); | ||
302 | clks[usb1] = mxs_clk_gate("usb1", "usb1_pwr", DIGCTRL, 16); | ||
303 | clks[usb0_pwr] = clk_register_gate(NULL, "usb0_pwr", "pll0", 0, PLL0CTRL0, 18, 0, &mxs_lock); | ||
304 | clks[usb1_pwr] = clk_register_gate(NULL, "usb1_pwr", "pll1", 0, PLL1CTRL0, 18, 0, &mxs_lock); | ||
305 | clks[enet_out] = clk_register_gate(NULL, "enet_out", "pll2", 0, ENET, 18, 0, &mxs_lock); | ||
306 | |||
307 | for (i = 0; i < ARRAY_SIZE(clks); i++) | ||
308 | if (IS_ERR(clks[i])) { | ||
309 | pr_err("i.MX28 clk %d: register failed with %ld\n", | ||
310 | i, PTR_ERR(clks[i])); | ||
311 | return PTR_ERR(clks[i]); | ||
312 | } | ||
313 | |||
314 | clk_register_clkdev(clks[clk32k], NULL, "timrot"); | ||
315 | clk_register_clkdev(clks[enet_out], NULL, "enet_out"); | ||
316 | clk_register_clkdevs(clks[hbus], hbus_lookups, ARRAY_SIZE(hbus_lookups)); | ||
317 | clk_register_clkdevs(clks[xbus], xbus_lookups, ARRAY_SIZE(xbus_lookups)); | ||
318 | clk_register_clkdevs(clks[uart], uart_lookups, ARRAY_SIZE(uart_lookups)); | ||
319 | clk_register_clkdevs(clks[ssp0], ssp0_lookups, ARRAY_SIZE(ssp0_lookups)); | ||
320 | clk_register_clkdevs(clks[ssp1], ssp1_lookups, ARRAY_SIZE(ssp1_lookups)); | ||
321 | clk_register_clkdevs(clks[ssp2], ssp2_lookups, ARRAY_SIZE(ssp2_lookups)); | ||
322 | clk_register_clkdevs(clks[ssp3], ssp3_lookups, ARRAY_SIZE(ssp3_lookups)); | ||
323 | clk_register_clkdevs(clks[gpmi], gpmi_lookups, ARRAY_SIZE(gpmi_lookups)); | ||
324 | clk_register_clkdevs(clks[saif0], saif0_lookups, ARRAY_SIZE(saif0_lookups)); | ||
325 | clk_register_clkdevs(clks[saif1], saif1_lookups, ARRAY_SIZE(saif1_lookups)); | ||
326 | clk_register_clkdevs(clks[lcdif], lcdif_lookups, ARRAY_SIZE(lcdif_lookups)); | ||
327 | clk_register_clkdevs(clks[fec], fec_lookups, ARRAY_SIZE(fec_lookups)); | ||
328 | clk_register_clkdevs(clks[can0], can0_lookups, ARRAY_SIZE(can0_lookups)); | ||
329 | clk_register_clkdevs(clks[can1], can1_lookups, ARRAY_SIZE(can1_lookups)); | ||
330 | |||
331 | for (i = 0; i < ARRAY_SIZE(clks_init_on); i++) | ||
332 | clk_prepare_enable(clks[clks_init_on[i]]); | ||
333 | |||
334 | mxs_timer_init(MX28_INT_TIMER0); | ||
335 | |||
336 | return 0; | ||
337 | } | ||
diff --git a/drivers/clk/mxs/clk-pll.c b/drivers/clk/mxs/clk-pll.c new file mode 100644 index 000000000000..fadae41833ec --- /dev/null +++ b/drivers/clk/mxs/clk-pll.c | |||
@@ -0,0 +1,116 @@ | |||
1 | /* | ||
2 | * Copyright 2012 Freescale Semiconductor, Inc. | ||
3 | * | ||
4 | * The code contained herein is licensed under the GNU General Public | ||
5 | * License. You may obtain a copy of the GNU General Public License | ||
6 | * Version 2 or later at the following locations: | ||
7 | * | ||
8 | * http://www.opensource.org/licenses/gpl-license.html | ||
9 | * http://www.gnu.org/copyleft/gpl.html | ||
10 | */ | ||
11 | |||
12 | #include <linux/clk.h> | ||
13 | #include <linux/clk-provider.h> | ||
14 | #include <linux/delay.h> | ||
15 | #include <linux/err.h> | ||
16 | #include <linux/io.h> | ||
17 | #include <linux/slab.h> | ||
18 | #include "clk.h" | ||
19 | |||
20 | /** | ||
21 | * struct clk_pll - mxs pll clock | ||
22 | * @hw: clk_hw for the pll | ||
23 | * @base: base address of the pll | ||
24 | * @power: the shift of power bit | ||
25 | * @rate: the clock rate of the pll | ||
26 | * | ||
27 | * The mxs pll is a fixed rate clock with power and gate control, | ||
28 | * and the shift of gate bit is always 31. | ||
29 | */ | ||
30 | struct clk_pll { | ||
31 | struct clk_hw hw; | ||
32 | void __iomem *base; | ||
33 | u8 power; | ||
34 | unsigned long rate; | ||
35 | }; | ||
36 | |||
37 | #define to_clk_pll(_hw) container_of(_hw, struct clk_pll, hw) | ||
38 | |||
39 | static int clk_pll_prepare(struct clk_hw *hw) | ||
40 | { | ||
41 | struct clk_pll *pll = to_clk_pll(hw); | ||
42 | |||
43 | writel_relaxed(1 << pll->power, pll->base + SET); | ||
44 | |||
45 | udelay(10); | ||
46 | |||
47 | return 0; | ||
48 | } | ||
49 | |||
50 | static void clk_pll_unprepare(struct clk_hw *hw) | ||
51 | { | ||
52 | struct clk_pll *pll = to_clk_pll(hw); | ||
53 | |||
54 | writel_relaxed(1 << pll->power, pll->base + CLR); | ||
55 | } | ||
56 | |||
57 | static int clk_pll_enable(struct clk_hw *hw) | ||
58 | { | ||
59 | struct clk_pll *pll = to_clk_pll(hw); | ||
60 | |||
61 | writel_relaxed(1 << 31, pll->base + CLR); | ||
62 | |||
63 | return 0; | ||
64 | } | ||
65 | |||
66 | static void clk_pll_disable(struct clk_hw *hw) | ||
67 | { | ||
68 | struct clk_pll *pll = to_clk_pll(hw); | ||
69 | |||
70 | writel_relaxed(1 << 31, pll->base + SET); | ||
71 | } | ||
72 | |||
73 | static unsigned long clk_pll_recalc_rate(struct clk_hw *hw, | ||
74 | unsigned long parent_rate) | ||
75 | { | ||
76 | struct clk_pll *pll = to_clk_pll(hw); | ||
77 | |||
78 | return pll->rate; | ||
79 | } | ||
80 | |||
81 | static const struct clk_ops clk_pll_ops = { | ||
82 | .prepare = clk_pll_prepare, | ||
83 | .unprepare = clk_pll_unprepare, | ||
84 | .enable = clk_pll_enable, | ||
85 | .disable = clk_pll_disable, | ||
86 | .recalc_rate = clk_pll_recalc_rate, | ||
87 | }; | ||
88 | |||
89 | struct clk *mxs_clk_pll(const char *name, const char *parent_name, | ||
90 | void __iomem *base, u8 power, unsigned long rate) | ||
91 | { | ||
92 | struct clk_pll *pll; | ||
93 | struct clk *clk; | ||
94 | struct clk_init_data init; | ||
95 | |||
96 | pll = kzalloc(sizeof(*pll), GFP_KERNEL); | ||
97 | if (!pll) | ||
98 | return ERR_PTR(-ENOMEM); | ||
99 | |||
100 | init.name = name; | ||
101 | init.ops = &clk_pll_ops; | ||
102 | init.flags = 0; | ||
103 | init.parent_names = (parent_name ? &parent_name: NULL); | ||
104 | init.num_parents = (parent_name ? 1 : 0); | ||
105 | |||
106 | pll->base = base; | ||
107 | pll->rate = rate; | ||
108 | pll->power = power; | ||
109 | pll->hw.init = &init; | ||
110 | |||
111 | clk = clk_register(NULL, &pll->hw); | ||
112 | if (IS_ERR(clk)) | ||
113 | kfree(pll); | ||
114 | |||
115 | return clk; | ||
116 | } | ||
diff --git a/drivers/clk/mxs/clk-ref.c b/drivers/clk/mxs/clk-ref.c new file mode 100644 index 000000000000..4adeed6c2f94 --- /dev/null +++ b/drivers/clk/mxs/clk-ref.c | |||
@@ -0,0 +1,154 @@ | |||
1 | /* | ||
2 | * Copyright 2012 Freescale Semiconductor, Inc. | ||
3 | * | ||
4 | * The code contained herein is licensed under the GNU General Public | ||
5 | * License. You may obtain a copy of the GNU General Public License | ||
6 | * Version 2 or later at the following locations: | ||
7 | * | ||
8 | * http://www.opensource.org/licenses/gpl-license.html | ||
9 | * http://www.gnu.org/copyleft/gpl.html | ||
10 | */ | ||
11 | |||
12 | #include <linux/clk.h> | ||
13 | #include <linux/clk-provider.h> | ||
14 | #include <linux/err.h> | ||
15 | #include <linux/io.h> | ||
16 | #include <linux/slab.h> | ||
17 | #include "clk.h" | ||
18 | |||
19 | /** | ||
20 | * struct clk_ref - mxs reference clock | ||
21 | * @hw: clk_hw for the reference clock | ||
22 | * @reg: register address | ||
23 | * @idx: the index of the reference clock within the same register | ||
24 | * | ||
25 | * The mxs reference clock sources from pll. Every 4 reference clocks share | ||
26 | * one register space, and @idx is used to identify them. Each reference | ||
27 | * clock has a gate control and a fractional * divider. The rate is calculated | ||
28 | * as pll rate * (18 / FRAC), where FRAC = 18 ~ 35. | ||
29 | */ | ||
30 | struct clk_ref { | ||
31 | struct clk_hw hw; | ||
32 | void __iomem *reg; | ||
33 | u8 idx; | ||
34 | }; | ||
35 | |||
36 | #define to_clk_ref(_hw) container_of(_hw, struct clk_ref, hw) | ||
37 | |||
38 | static int clk_ref_enable(struct clk_hw *hw) | ||
39 | { | ||
40 | struct clk_ref *ref = to_clk_ref(hw); | ||
41 | |||
42 | writel_relaxed(1 << ((ref->idx + 1) * 8 - 1), ref->reg + CLR); | ||
43 | |||
44 | return 0; | ||
45 | } | ||
46 | |||
47 | static void clk_ref_disable(struct clk_hw *hw) | ||
48 | { | ||
49 | struct clk_ref *ref = to_clk_ref(hw); | ||
50 | |||
51 | writel_relaxed(1 << ((ref->idx + 1) * 8 - 1), ref->reg + SET); | ||
52 | } | ||
53 | |||
54 | static unsigned long clk_ref_recalc_rate(struct clk_hw *hw, | ||
55 | unsigned long parent_rate) | ||
56 | { | ||
57 | struct clk_ref *ref = to_clk_ref(hw); | ||
58 | u64 tmp = parent_rate; | ||
59 | u8 frac = (readl_relaxed(ref->reg) >> (ref->idx * 8)) & 0x3f; | ||
60 | |||
61 | tmp *= 18; | ||
62 | do_div(tmp, frac); | ||
63 | |||
64 | return tmp; | ||
65 | } | ||
66 | |||
67 | static long clk_ref_round_rate(struct clk_hw *hw, unsigned long rate, | ||
68 | unsigned long *prate) | ||
69 | { | ||
70 | unsigned long parent_rate = *prate; | ||
71 | u64 tmp = parent_rate; | ||
72 | u8 frac; | ||
73 | |||
74 | tmp = tmp * 18 + rate / 2; | ||
75 | do_div(tmp, rate); | ||
76 | frac = tmp; | ||
77 | |||
78 | if (frac < 18) | ||
79 | frac = 18; | ||
80 | else if (frac > 35) | ||
81 | frac = 35; | ||
82 | |||
83 | tmp = parent_rate; | ||
84 | tmp *= 18; | ||
85 | do_div(tmp, frac); | ||
86 | |||
87 | return tmp; | ||
88 | } | ||
89 | |||
90 | static int clk_ref_set_rate(struct clk_hw *hw, unsigned long rate, | ||
91 | unsigned long parent_rate) | ||
92 | { | ||
93 | struct clk_ref *ref = to_clk_ref(hw); | ||
94 | unsigned long flags; | ||
95 | u64 tmp = parent_rate; | ||
96 | u32 val; | ||
97 | u8 frac, shift = ref->idx * 8; | ||
98 | |||
99 | tmp = tmp * 18 + rate / 2; | ||
100 | do_div(tmp, rate); | ||
101 | frac = tmp; | ||
102 | |||
103 | if (frac < 18) | ||
104 | frac = 18; | ||
105 | else if (frac > 35) | ||
106 | frac = 35; | ||
107 | |||
108 | spin_lock_irqsave(&mxs_lock, flags); | ||
109 | |||
110 | val = readl_relaxed(ref->reg); | ||
111 | val &= ~(0x3f << shift); | ||
112 | val |= frac << shift; | ||
113 | writel_relaxed(val, ref->reg); | ||
114 | |||
115 | spin_unlock_irqrestore(&mxs_lock, flags); | ||
116 | |||
117 | return 0; | ||
118 | } | ||
119 | |||
120 | static const struct clk_ops clk_ref_ops = { | ||
121 | .enable = clk_ref_enable, | ||
122 | .disable = clk_ref_disable, | ||
123 | .recalc_rate = clk_ref_recalc_rate, | ||
124 | .round_rate = clk_ref_round_rate, | ||
125 | .set_rate = clk_ref_set_rate, | ||
126 | }; | ||
127 | |||
128 | struct clk *mxs_clk_ref(const char *name, const char *parent_name, | ||
129 | void __iomem *reg, u8 idx) | ||
130 | { | ||
131 | struct clk_ref *ref; | ||
132 | struct clk *clk; | ||
133 | struct clk_init_data init; | ||
134 | |||
135 | ref = kzalloc(sizeof(*ref), GFP_KERNEL); | ||
136 | if (!ref) | ||
137 | return ERR_PTR(-ENOMEM); | ||
138 | |||
139 | init.name = name; | ||
140 | init.ops = &clk_ref_ops; | ||
141 | init.flags = 0; | ||
142 | init.parent_names = (parent_name ? &parent_name: NULL); | ||
143 | init.num_parents = (parent_name ? 1 : 0); | ||
144 | |||
145 | ref->reg = reg; | ||
146 | ref->idx = idx; | ||
147 | ref->hw.init = &init; | ||
148 | |||
149 | clk = clk_register(NULL, &ref->hw); | ||
150 | if (IS_ERR(clk)) | ||
151 | kfree(ref); | ||
152 | |||
153 | return clk; | ||
154 | } | ||
diff --git a/drivers/clk/mxs/clk.c b/drivers/clk/mxs/clk.c new file mode 100644 index 000000000000..b24d56067c80 --- /dev/null +++ b/drivers/clk/mxs/clk.c | |||
@@ -0,0 +1,28 @@ | |||
1 | /* | ||
2 | * Copyright 2012 Freescale Semiconductor, Inc. | ||
3 | * | ||
4 | * The code contained herein is licensed under the GNU General Public | ||
5 | * License. You may obtain a copy of the GNU General Public License | ||
6 | * Version 2 or later at the following locations: | ||
7 | * | ||
8 | * http://www.opensource.org/licenses/gpl-license.html | ||
9 | * http://www.gnu.org/copyleft/gpl.html | ||
10 | */ | ||
11 | |||
12 | #include <linux/err.h> | ||
13 | #include <linux/io.h> | ||
14 | #include <linux/jiffies.h> | ||
15 | #include <linux/spinlock.h> | ||
16 | |||
17 | DEFINE_SPINLOCK(mxs_lock); | ||
18 | |||
19 | int mxs_clk_wait(void __iomem *reg, u8 shift) | ||
20 | { | ||
21 | unsigned long timeout = jiffies + msecs_to_jiffies(10); | ||
22 | |||
23 | while (readl_relaxed(reg) & (1 << shift)) | ||
24 | if (time_after(jiffies, timeout)) | ||
25 | return -ETIMEDOUT; | ||
26 | |||
27 | return 0; | ||
28 | } | ||
diff --git a/drivers/clk/mxs/clk.h b/drivers/clk/mxs/clk.h new file mode 100644 index 000000000000..81421e28e69c --- /dev/null +++ b/drivers/clk/mxs/clk.h | |||
@@ -0,0 +1,66 @@ | |||
1 | /* | ||
2 | * Copyright 2012 Freescale Semiconductor, Inc. | ||
3 | * | ||
4 | * The code contained herein is licensed under the GNU General Public | ||
5 | * License. You may obtain a copy of the GNU General Public License | ||
6 | * Version 2 or later at the following locations: | ||
7 | * | ||
8 | * http://www.opensource.org/licenses/gpl-license.html | ||
9 | * http://www.gnu.org/copyleft/gpl.html | ||
10 | */ | ||
11 | |||
12 | #ifndef __MXS_CLK_H | ||
13 | #define __MXS_CLK_H | ||
14 | |||
15 | #include <linux/clk.h> | ||
16 | #include <linux/clk-provider.h> | ||
17 | #include <linux/spinlock.h> | ||
18 | |||
19 | #define SET 0x4 | ||
20 | #define CLR 0x8 | ||
21 | |||
22 | extern spinlock_t mxs_lock; | ||
23 | |||
24 | int mxs_clk_wait(void __iomem *reg, u8 shift); | ||
25 | |||
26 | struct clk *mxs_clk_pll(const char *name, const char *parent_name, | ||
27 | void __iomem *base, u8 power, unsigned long rate); | ||
28 | |||
29 | struct clk *mxs_clk_ref(const char *name, const char *parent_name, | ||
30 | void __iomem *reg, u8 idx); | ||
31 | |||
32 | struct clk *mxs_clk_div(const char *name, const char *parent_name, | ||
33 | void __iomem *reg, u8 shift, u8 width, u8 busy); | ||
34 | |||
35 | struct clk *mxs_clk_frac(const char *name, const char *parent_name, | ||
36 | void __iomem *reg, u8 shift, u8 width, u8 busy); | ||
37 | |||
38 | static inline struct clk *mxs_clk_fixed(const char *name, int rate) | ||
39 | { | ||
40 | return clk_register_fixed_rate(NULL, name, NULL, CLK_IS_ROOT, rate); | ||
41 | } | ||
42 | |||
43 | static inline struct clk *mxs_clk_gate(const char *name, | ||
44 | const char *parent_name, void __iomem *reg, u8 shift) | ||
45 | { | ||
46 | return clk_register_gate(NULL, name, parent_name, CLK_SET_RATE_PARENT, | ||
47 | reg, shift, CLK_GATE_SET_TO_DISABLE, | ||
48 | &mxs_lock); | ||
49 | } | ||
50 | |||
51 | static inline struct clk *mxs_clk_mux(const char *name, void __iomem *reg, | ||
52 | u8 shift, u8 width, const char **parent_names, int num_parents) | ||
53 | { | ||
54 | return clk_register_mux(NULL, name, parent_names, num_parents, | ||
55 | CLK_SET_RATE_PARENT, reg, shift, width, | ||
56 | 0, &mxs_lock); | ||
57 | } | ||
58 | |||
59 | static inline struct clk *mxs_clk_fixed_factor(const char *name, | ||
60 | const char *parent_name, unsigned int mult, unsigned int div) | ||
61 | { | ||
62 | return clk_register_fixed_factor(NULL, name, parent_name, | ||
63 | CLK_SET_RATE_PARENT, mult, div); | ||
64 | } | ||
65 | |||
66 | #endif /* __MXS_CLK_H */ | ||
diff --git a/drivers/clk/spear/Makefile b/drivers/clk/spear/Makefile new file mode 100644 index 000000000000..335886049c83 --- /dev/null +++ b/drivers/clk/spear/Makefile | |||
@@ -0,0 +1,8 @@ | |||
1 | # | ||
2 | # SPEAr Clock specific Makefile | ||
3 | # | ||
4 | |||
5 | obj-y += clk.o clk-aux-synth.o clk-frac-synth.o clk-gpt-synth.o clk-vco-pll.o | ||
6 | |||
7 | obj-$(CONFIG_ARCH_SPEAR3XX) += spear3xx_clock.o | ||
8 | obj-$(CONFIG_ARCH_SPEAR6XX) += spear6xx_clock.o | ||
diff --git a/drivers/clk/spear/clk-aux-synth.c b/drivers/clk/spear/clk-aux-synth.c new file mode 100644 index 000000000000..af34074e702b --- /dev/null +++ b/drivers/clk/spear/clk-aux-synth.c | |||
@@ -0,0 +1,198 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2012 ST Microelectronics | ||
3 | * Viresh Kumar <viresh.kumar@st.com> | ||
4 | * | ||
5 | * This file is licensed under the terms of the GNU General Public | ||
6 | * License version 2. This program is licensed "as is" without any | ||
7 | * warranty of any kind, whether express or implied. | ||
8 | * | ||
9 | * Auxiliary Synthesizer clock implementation | ||
10 | */ | ||
11 | |||
12 | #define pr_fmt(fmt) "clk-aux-synth: " fmt | ||
13 | |||
14 | #include <linux/clk-provider.h> | ||
15 | #include <linux/slab.h> | ||
16 | #include <linux/io.h> | ||
17 | #include <linux/err.h> | ||
18 | #include "clk.h" | ||
19 | |||
20 | /* | ||
21 | * DOC: Auxiliary Synthesizer clock | ||
22 | * | ||
23 | * Aux synth gives rate for different values of eq, x and y | ||
24 | * | ||
25 | * Fout from synthesizer can be given from two equations: | ||
26 | * Fout1 = (Fin * X/Y)/2 EQ1 | ||
27 | * Fout2 = Fin * X/Y EQ2 | ||
28 | */ | ||
29 | |||
30 | #define to_clk_aux(_hw) container_of(_hw, struct clk_aux, hw) | ||
31 | |||
32 | static struct aux_clk_masks default_aux_masks = { | ||
33 | .eq_sel_mask = AUX_EQ_SEL_MASK, | ||
34 | .eq_sel_shift = AUX_EQ_SEL_SHIFT, | ||
35 | .eq1_mask = AUX_EQ1_SEL, | ||
36 | .eq2_mask = AUX_EQ2_SEL, | ||
37 | .xscale_sel_mask = AUX_XSCALE_MASK, | ||
38 | .xscale_sel_shift = AUX_XSCALE_SHIFT, | ||
39 | .yscale_sel_mask = AUX_YSCALE_MASK, | ||
40 | .yscale_sel_shift = AUX_YSCALE_SHIFT, | ||
41 | .enable_bit = AUX_SYNT_ENB, | ||
42 | }; | ||
43 | |||
44 | static unsigned long aux_calc_rate(struct clk_hw *hw, unsigned long prate, | ||
45 | int index) | ||
46 | { | ||
47 | struct clk_aux *aux = to_clk_aux(hw); | ||
48 | struct aux_rate_tbl *rtbl = aux->rtbl; | ||
49 | u8 eq = rtbl[index].eq ? 1 : 2; | ||
50 | |||
51 | return (((prate / 10000) * rtbl[index].xscale) / | ||
52 | (rtbl[index].yscale * eq)) * 10000; | ||
53 | } | ||
54 | |||
55 | static long clk_aux_round_rate(struct clk_hw *hw, unsigned long drate, | ||
56 | unsigned long *prate) | ||
57 | { | ||
58 | struct clk_aux *aux = to_clk_aux(hw); | ||
59 | int unused; | ||
60 | |||
61 | return clk_round_rate_index(hw, drate, *prate, aux_calc_rate, | ||
62 | aux->rtbl_cnt, &unused); | ||
63 | } | ||
64 | |||
65 | static unsigned long clk_aux_recalc_rate(struct clk_hw *hw, | ||
66 | unsigned long parent_rate) | ||
67 | { | ||
68 | struct clk_aux *aux = to_clk_aux(hw); | ||
69 | unsigned int num = 1, den = 1, val, eqn; | ||
70 | unsigned long flags = 0; | ||
71 | |||
72 | if (aux->lock) | ||
73 | spin_lock_irqsave(aux->lock, flags); | ||
74 | |||
75 | val = readl_relaxed(aux->reg); | ||
76 | |||
77 | if (aux->lock) | ||
78 | spin_unlock_irqrestore(aux->lock, flags); | ||
79 | |||
80 | eqn = (val >> aux->masks->eq_sel_shift) & aux->masks->eq_sel_mask; | ||
81 | if (eqn == aux->masks->eq1_mask) | ||
82 | den = 2; | ||
83 | |||
84 | /* calculate numerator */ | ||
85 | num = (val >> aux->masks->xscale_sel_shift) & | ||
86 | aux->masks->xscale_sel_mask; | ||
87 | |||
88 | /* calculate denominator */ | ||
89 | den *= (val >> aux->masks->yscale_sel_shift) & | ||
90 | aux->masks->yscale_sel_mask; | ||
91 | |||
92 | if (!den) | ||
93 | return 0; | ||
94 | |||
95 | return (((parent_rate / 10000) * num) / den) * 10000; | ||
96 | } | ||
97 | |||
98 | /* Configures new clock rate of aux */ | ||
99 | static int clk_aux_set_rate(struct clk_hw *hw, unsigned long drate, | ||
100 | unsigned long prate) | ||
101 | { | ||
102 | struct clk_aux *aux = to_clk_aux(hw); | ||
103 | struct aux_rate_tbl *rtbl = aux->rtbl; | ||
104 | unsigned long val, flags = 0; | ||
105 | int i; | ||
106 | |||
107 | clk_round_rate_index(hw, drate, prate, aux_calc_rate, aux->rtbl_cnt, | ||
108 | &i); | ||
109 | |||
110 | if (aux->lock) | ||
111 | spin_lock_irqsave(aux->lock, flags); | ||
112 | |||
113 | val = readl_relaxed(aux->reg) & | ||
114 | ~(aux->masks->eq_sel_mask << aux->masks->eq_sel_shift); | ||
115 | val |= (rtbl[i].eq & aux->masks->eq_sel_mask) << | ||
116 | aux->masks->eq_sel_shift; | ||
117 | val &= ~(aux->masks->xscale_sel_mask << aux->masks->xscale_sel_shift); | ||
118 | val |= (rtbl[i].xscale & aux->masks->xscale_sel_mask) << | ||
119 | aux->masks->xscale_sel_shift; | ||
120 | val &= ~(aux->masks->yscale_sel_mask << aux->masks->yscale_sel_shift); | ||
121 | val |= (rtbl[i].yscale & aux->masks->yscale_sel_mask) << | ||
122 | aux->masks->yscale_sel_shift; | ||
123 | writel_relaxed(val, aux->reg); | ||
124 | |||
125 | if (aux->lock) | ||
126 | spin_unlock_irqrestore(aux->lock, flags); | ||
127 | |||
128 | return 0; | ||
129 | } | ||
130 | |||
131 | static struct clk_ops clk_aux_ops = { | ||
132 | .recalc_rate = clk_aux_recalc_rate, | ||
133 | .round_rate = clk_aux_round_rate, | ||
134 | .set_rate = clk_aux_set_rate, | ||
135 | }; | ||
136 | |||
137 | struct clk *clk_register_aux(const char *aux_name, const char *gate_name, | ||
138 | const char *parent_name, unsigned long flags, void __iomem *reg, | ||
139 | struct aux_clk_masks *masks, struct aux_rate_tbl *rtbl, | ||
140 | u8 rtbl_cnt, spinlock_t *lock, struct clk **gate_clk) | ||
141 | { | ||
142 | struct clk_aux *aux; | ||
143 | struct clk_init_data init; | ||
144 | struct clk *clk; | ||
145 | |||
146 | if (!aux_name || !parent_name || !reg || !rtbl || !rtbl_cnt) { | ||
147 | pr_err("Invalid arguments passed"); | ||
148 | return ERR_PTR(-EINVAL); | ||
149 | } | ||
150 | |||
151 | aux = kzalloc(sizeof(*aux), GFP_KERNEL); | ||
152 | if (!aux) { | ||
153 | pr_err("could not allocate aux clk\n"); | ||
154 | return ERR_PTR(-ENOMEM); | ||
155 | } | ||
156 | |||
157 | /* struct clk_aux assignments */ | ||
158 | if (!masks) | ||
159 | aux->masks = &default_aux_masks; | ||
160 | else | ||
161 | aux->masks = masks; | ||
162 | |||
163 | aux->reg = reg; | ||
164 | aux->rtbl = rtbl; | ||
165 | aux->rtbl_cnt = rtbl_cnt; | ||
166 | aux->lock = lock; | ||
167 | aux->hw.init = &init; | ||
168 | |||
169 | init.name = aux_name; | ||
170 | init.ops = &clk_aux_ops; | ||
171 | init.flags = flags; | ||
172 | init.parent_names = &parent_name; | ||
173 | init.num_parents = 1; | ||
174 | |||
175 | clk = clk_register(NULL, &aux->hw); | ||
176 | if (IS_ERR_OR_NULL(clk)) | ||
177 | goto free_aux; | ||
178 | |||
179 | if (gate_name) { | ||
180 | struct clk *tgate_clk; | ||
181 | |||
182 | tgate_clk = clk_register_gate(NULL, gate_name, aux_name, 0, reg, | ||
183 | aux->masks->enable_bit, 0, lock); | ||
184 | if (IS_ERR_OR_NULL(tgate_clk)) | ||
185 | goto free_aux; | ||
186 | |||
187 | if (gate_clk) | ||
188 | *gate_clk = tgate_clk; | ||
189 | } | ||
190 | |||
191 | return clk; | ||
192 | |||
193 | free_aux: | ||
194 | kfree(aux); | ||
195 | pr_err("clk register failed\n"); | ||
196 | |||
197 | return NULL; | ||
198 | } | ||
diff --git a/drivers/clk/spear/clk-frac-synth.c b/drivers/clk/spear/clk-frac-synth.c new file mode 100644 index 000000000000..4dbdb3fe18e0 --- /dev/null +++ b/drivers/clk/spear/clk-frac-synth.c | |||
@@ -0,0 +1,165 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2012 ST Microelectronics | ||
3 | * Viresh Kumar <viresh.kumar@st.com> | ||
4 | * | ||
5 | * This file is licensed under the terms of the GNU General Public | ||
6 | * License version 2. This program is licensed "as is" without any | ||
7 | * warranty of any kind, whether express or implied. | ||
8 | * | ||
9 | * Fractional Synthesizer clock implementation | ||
10 | */ | ||
11 | |||
12 | #define pr_fmt(fmt) "clk-frac-synth: " fmt | ||
13 | |||
14 | #include <linux/clk-provider.h> | ||
15 | #include <linux/slab.h> | ||
16 | #include <linux/io.h> | ||
17 | #include <linux/err.h> | ||
18 | #include "clk.h" | ||
19 | |||
20 | #define DIV_FACTOR_MASK 0x1FFFF | ||
21 | |||
22 | /* | ||
23 | * DOC: Fractional Synthesizer clock | ||
24 | * | ||
25 | * Fout from synthesizer can be given from below equation: | ||
26 | * | ||
27 | * Fout= Fin/2*div (division factor) | ||
28 | * div is 17 bits:- | ||
29 | * 0-13 (fractional part) | ||
30 | * 14-16 (integer part) | ||
31 | * div is (16-14 bits).(13-0 bits) (in binary) | ||
32 | * | ||
33 | * Fout = Fin/(2 * div) | ||
34 | * Fout = ((Fin / 10000)/(2 * div)) * 10000 | ||
35 | * Fout = (2^14 * (Fin / 10000)/(2^14 * (2 * div))) * 10000 | ||
36 | * Fout = (((Fin / 10000) << 14)/(2 * (div << 14))) * 10000 | ||
37 | * | ||
38 | * div << 14 simply 17 bit value written at register. | ||
39 | * Max error due to scaling down by 10000 is 10 KHz | ||
40 | */ | ||
41 | |||
42 | #define to_clk_frac(_hw) container_of(_hw, struct clk_frac, hw) | ||
43 | |||
44 | static unsigned long frac_calc_rate(struct clk_hw *hw, unsigned long prate, | ||
45 | int index) | ||
46 | { | ||
47 | struct clk_frac *frac = to_clk_frac(hw); | ||
48 | struct frac_rate_tbl *rtbl = frac->rtbl; | ||
49 | |||
50 | prate /= 10000; | ||
51 | prate <<= 14; | ||
52 | prate /= (2 * rtbl[index].div); | ||
53 | prate *= 10000; | ||
54 | |||
55 | return prate; | ||
56 | } | ||
57 | |||
58 | static long clk_frac_round_rate(struct clk_hw *hw, unsigned long drate, | ||
59 | unsigned long *prate) | ||
60 | { | ||
61 | struct clk_frac *frac = to_clk_frac(hw); | ||
62 | int unused; | ||
63 | |||
64 | return clk_round_rate_index(hw, drate, *prate, frac_calc_rate, | ||
65 | frac->rtbl_cnt, &unused); | ||
66 | } | ||
67 | |||
68 | static unsigned long clk_frac_recalc_rate(struct clk_hw *hw, | ||
69 | unsigned long parent_rate) | ||
70 | { | ||
71 | struct clk_frac *frac = to_clk_frac(hw); | ||
72 | unsigned long flags = 0; | ||
73 | unsigned int div = 1, val; | ||
74 | |||
75 | if (frac->lock) | ||
76 | spin_lock_irqsave(frac->lock, flags); | ||
77 | |||
78 | val = readl_relaxed(frac->reg); | ||
79 | |||
80 | if (frac->lock) | ||
81 | spin_unlock_irqrestore(frac->lock, flags); | ||
82 | |||
83 | div = val & DIV_FACTOR_MASK; | ||
84 | |||
85 | if (!div) | ||
86 | return 0; | ||
87 | |||
88 | parent_rate = parent_rate / 10000; | ||
89 | |||
90 | parent_rate = (parent_rate << 14) / (2 * div); | ||
91 | return parent_rate * 10000; | ||
92 | } | ||
93 | |||
94 | /* Configures new clock rate of frac */ | ||
95 | static int clk_frac_set_rate(struct clk_hw *hw, unsigned long drate, | ||
96 | unsigned long prate) | ||
97 | { | ||
98 | struct clk_frac *frac = to_clk_frac(hw); | ||
99 | struct frac_rate_tbl *rtbl = frac->rtbl; | ||
100 | unsigned long flags = 0, val; | ||
101 | int i; | ||
102 | |||
103 | clk_round_rate_index(hw, drate, prate, frac_calc_rate, frac->rtbl_cnt, | ||
104 | &i); | ||
105 | |||
106 | if (frac->lock) | ||
107 | spin_lock_irqsave(frac->lock, flags); | ||
108 | |||
109 | val = readl_relaxed(frac->reg) & ~DIV_FACTOR_MASK; | ||
110 | val |= rtbl[i].div & DIV_FACTOR_MASK; | ||
111 | writel_relaxed(val, frac->reg); | ||
112 | |||
113 | if (frac->lock) | ||
114 | spin_unlock_irqrestore(frac->lock, flags); | ||
115 | |||
116 | return 0; | ||
117 | } | ||
118 | |||
119 | struct clk_ops clk_frac_ops = { | ||
120 | .recalc_rate = clk_frac_recalc_rate, | ||
121 | .round_rate = clk_frac_round_rate, | ||
122 | .set_rate = clk_frac_set_rate, | ||
123 | }; | ||
124 | |||
125 | struct clk *clk_register_frac(const char *name, const char *parent_name, | ||
126 | unsigned long flags, void __iomem *reg, | ||
127 | struct frac_rate_tbl *rtbl, u8 rtbl_cnt, spinlock_t *lock) | ||
128 | { | ||
129 | struct clk_init_data init; | ||
130 | struct clk_frac *frac; | ||
131 | struct clk *clk; | ||
132 | |||
133 | if (!name || !parent_name || !reg || !rtbl || !rtbl_cnt) { | ||
134 | pr_err("Invalid arguments passed"); | ||
135 | return ERR_PTR(-EINVAL); | ||
136 | } | ||
137 | |||
138 | frac = kzalloc(sizeof(*frac), GFP_KERNEL); | ||
139 | if (!frac) { | ||
140 | pr_err("could not allocate frac clk\n"); | ||
141 | return ERR_PTR(-ENOMEM); | ||
142 | } | ||
143 | |||
144 | /* struct clk_frac assignments */ | ||
145 | frac->reg = reg; | ||
146 | frac->rtbl = rtbl; | ||
147 | frac->rtbl_cnt = rtbl_cnt; | ||
148 | frac->lock = lock; | ||
149 | frac->hw.init = &init; | ||
150 | |||
151 | init.name = name; | ||
152 | init.ops = &clk_frac_ops; | ||
153 | init.flags = flags; | ||
154 | init.parent_names = &parent_name; | ||
155 | init.num_parents = 1; | ||
156 | |||
157 | clk = clk_register(NULL, &frac->hw); | ||
158 | if (!IS_ERR_OR_NULL(clk)) | ||
159 | return clk; | ||
160 | |||
161 | pr_err("clk register failed\n"); | ||
162 | kfree(frac); | ||
163 | |||
164 | return NULL; | ||
165 | } | ||
diff --git a/drivers/clk/spear/clk-gpt-synth.c b/drivers/clk/spear/clk-gpt-synth.c new file mode 100644 index 000000000000..b471c9762a97 --- /dev/null +++ b/drivers/clk/spear/clk-gpt-synth.c | |||
@@ -0,0 +1,154 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2012 ST Microelectronics | ||
3 | * Viresh Kumar <viresh.kumar@st.com> | ||
4 | * | ||
5 | * This file is licensed under the terms of the GNU General Public | ||
6 | * License version 2. This program is licensed "as is" without any | ||
7 | * warranty of any kind, whether express or implied. | ||
8 | * | ||
9 | * General Purpose Timer Synthesizer clock implementation | ||
10 | */ | ||
11 | |||
12 | #define pr_fmt(fmt) "clk-gpt-synth: " fmt | ||
13 | |||
14 | #include <linux/clk-provider.h> | ||
15 | #include <linux/slab.h> | ||
16 | #include <linux/io.h> | ||
17 | #include <linux/err.h> | ||
18 | #include "clk.h" | ||
19 | |||
20 | #define GPT_MSCALE_MASK 0xFFF | ||
21 | #define GPT_NSCALE_SHIFT 12 | ||
22 | #define GPT_NSCALE_MASK 0xF | ||
23 | |||
24 | /* | ||
25 | * DOC: General Purpose Timer Synthesizer clock | ||
26 | * | ||
27 | * Calculates gpt synth clk rate for different values of mscale and nscale | ||
28 | * | ||
29 | * Fout= Fin/((2 ^ (N+1)) * (M+1)) | ||
30 | */ | ||
31 | |||
32 | #define to_clk_gpt(_hw) container_of(_hw, struct clk_gpt, hw) | ||
33 | |||
34 | static unsigned long gpt_calc_rate(struct clk_hw *hw, unsigned long prate, | ||
35 | int index) | ||
36 | { | ||
37 | struct clk_gpt *gpt = to_clk_gpt(hw); | ||
38 | struct gpt_rate_tbl *rtbl = gpt->rtbl; | ||
39 | |||
40 | prate /= ((1 << (rtbl[index].nscale + 1)) * (rtbl[index].mscale + 1)); | ||
41 | |||
42 | return prate; | ||
43 | } | ||
44 | |||
45 | static long clk_gpt_round_rate(struct clk_hw *hw, unsigned long drate, | ||
46 | unsigned long *prate) | ||
47 | { | ||
48 | struct clk_gpt *gpt = to_clk_gpt(hw); | ||
49 | int unused; | ||
50 | |||
51 | return clk_round_rate_index(hw, drate, *prate, gpt_calc_rate, | ||
52 | gpt->rtbl_cnt, &unused); | ||
53 | } | ||
54 | |||
55 | static unsigned long clk_gpt_recalc_rate(struct clk_hw *hw, | ||
56 | unsigned long parent_rate) | ||
57 | { | ||
58 | struct clk_gpt *gpt = to_clk_gpt(hw); | ||
59 | unsigned long flags = 0; | ||
60 | unsigned int div = 1, val; | ||
61 | |||
62 | if (gpt->lock) | ||
63 | spin_lock_irqsave(gpt->lock, flags); | ||
64 | |||
65 | val = readl_relaxed(gpt->reg); | ||
66 | |||
67 | if (gpt->lock) | ||
68 | spin_unlock_irqrestore(gpt->lock, flags); | ||
69 | |||
70 | div += val & GPT_MSCALE_MASK; | ||
71 | div *= 1 << (((val >> GPT_NSCALE_SHIFT) & GPT_NSCALE_MASK) + 1); | ||
72 | |||
73 | if (!div) | ||
74 | return 0; | ||
75 | |||
76 | return parent_rate / div; | ||
77 | } | ||
78 | |||
79 | /* Configures new clock rate of gpt */ | ||
80 | static int clk_gpt_set_rate(struct clk_hw *hw, unsigned long drate, | ||
81 | unsigned long prate) | ||
82 | { | ||
83 | struct clk_gpt *gpt = to_clk_gpt(hw); | ||
84 | struct gpt_rate_tbl *rtbl = gpt->rtbl; | ||
85 | unsigned long flags = 0, val; | ||
86 | int i; | ||
87 | |||
88 | clk_round_rate_index(hw, drate, prate, gpt_calc_rate, gpt->rtbl_cnt, | ||
89 | &i); | ||
90 | |||
91 | if (gpt->lock) | ||
92 | spin_lock_irqsave(gpt->lock, flags); | ||
93 | |||
94 | val = readl(gpt->reg) & ~GPT_MSCALE_MASK; | ||
95 | val &= ~(GPT_NSCALE_MASK << GPT_NSCALE_SHIFT); | ||
96 | |||
97 | val |= rtbl[i].mscale & GPT_MSCALE_MASK; | ||
98 | val |= (rtbl[i].nscale & GPT_NSCALE_MASK) << GPT_NSCALE_SHIFT; | ||
99 | |||
100 | writel_relaxed(val, gpt->reg); | ||
101 | |||
102 | if (gpt->lock) | ||
103 | spin_unlock_irqrestore(gpt->lock, flags); | ||
104 | |||
105 | return 0; | ||
106 | } | ||
107 | |||
108 | static struct clk_ops clk_gpt_ops = { | ||
109 | .recalc_rate = clk_gpt_recalc_rate, | ||
110 | .round_rate = clk_gpt_round_rate, | ||
111 | .set_rate = clk_gpt_set_rate, | ||
112 | }; | ||
113 | |||
114 | struct clk *clk_register_gpt(const char *name, const char *parent_name, unsigned | ||
115 | long flags, void __iomem *reg, struct gpt_rate_tbl *rtbl, u8 | ||
116 | rtbl_cnt, spinlock_t *lock) | ||
117 | { | ||
118 | struct clk_init_data init; | ||
119 | struct clk_gpt *gpt; | ||
120 | struct clk *clk; | ||
121 | |||
122 | if (!name || !parent_name || !reg || !rtbl || !rtbl_cnt) { | ||
123 | pr_err("Invalid arguments passed"); | ||
124 | return ERR_PTR(-EINVAL); | ||
125 | } | ||
126 | |||
127 | gpt = kzalloc(sizeof(*gpt), GFP_KERNEL); | ||
128 | if (!gpt) { | ||
129 | pr_err("could not allocate gpt clk\n"); | ||
130 | return ERR_PTR(-ENOMEM); | ||
131 | } | ||
132 | |||
133 | /* struct clk_gpt assignments */ | ||
134 | gpt->reg = reg; | ||
135 | gpt->rtbl = rtbl; | ||
136 | gpt->rtbl_cnt = rtbl_cnt; | ||
137 | gpt->lock = lock; | ||
138 | gpt->hw.init = &init; | ||
139 | |||
140 | init.name = name; | ||
141 | init.ops = &clk_gpt_ops; | ||
142 | init.flags = flags; | ||
143 | init.parent_names = &parent_name; | ||
144 | init.num_parents = 1; | ||
145 | |||
146 | clk = clk_register(NULL, &gpt->hw); | ||
147 | if (!IS_ERR_OR_NULL(clk)) | ||
148 | return clk; | ||
149 | |||
150 | pr_err("clk register failed\n"); | ||
151 | kfree(gpt); | ||
152 | |||
153 | return NULL; | ||
154 | } | ||
diff --git a/drivers/clk/spear/clk-vco-pll.c b/drivers/clk/spear/clk-vco-pll.c new file mode 100644 index 000000000000..dcd4bdf4b0d9 --- /dev/null +++ b/drivers/clk/spear/clk-vco-pll.c | |||
@@ -0,0 +1,363 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2012 ST Microelectronics | ||
3 | * Viresh Kumar <viresh.kumar@st.com> | ||
4 | * | ||
5 | * This file is licensed under the terms of the GNU General Public | ||
6 | * License version 2. This program is licensed "as is" without any | ||
7 | * warranty of any kind, whether express or implied. | ||
8 | * | ||
9 | * VCO-PLL clock implementation | ||
10 | */ | ||
11 | |||
12 | #define pr_fmt(fmt) "clk-vco-pll: " fmt | ||
13 | |||
14 | #include <linux/clk-provider.h> | ||
15 | #include <linux/slab.h> | ||
16 | #include <linux/io.h> | ||
17 | #include <linux/err.h> | ||
18 | #include "clk.h" | ||
19 | |||
20 | /* | ||
21 | * DOC: VCO-PLL clock | ||
22 | * | ||
23 | * VCO and PLL rate are derived from following equations: | ||
24 | * | ||
25 | * In normal mode | ||
26 | * vco = (2 * M[15:8] * Fin)/N | ||
27 | * | ||
28 | * In Dithered mode | ||
29 | * vco = (2 * M[15:0] * Fin)/(256 * N) | ||
30 | * | ||
31 | * pll_rate = pll/2^p | ||
32 | * | ||
33 | * vco and pll are very closely bound to each other, "vco needs to program: | ||
34 | * mode, m & n" and "pll needs to program p", both share common enable/disable | ||
35 | * logic. | ||
36 | * | ||
37 | * clk_register_vco_pll() registers instances of both vco & pll. | ||
38 | * CLK_SET_RATE_PARENT flag is forced for pll, as it will always pass its | ||
39 | * set_rate to vco. A single rate table exists for both the clocks, which | ||
40 | * configures m, n and p. | ||
41 | */ | ||
42 | |||
43 | /* PLL_CTR register masks */ | ||
44 | #define PLL_MODE_NORMAL 0 | ||
45 | #define PLL_MODE_FRACTION 1 | ||
46 | #define PLL_MODE_DITH_DSM 2 | ||
47 | #define PLL_MODE_DITH_SSM 3 | ||
48 | #define PLL_MODE_MASK 3 | ||
49 | #define PLL_MODE_SHIFT 3 | ||
50 | #define PLL_ENABLE 2 | ||
51 | |||
52 | #define PLL_LOCK_SHIFT 0 | ||
53 | #define PLL_LOCK_MASK 1 | ||
54 | |||
55 | /* PLL FRQ register masks */ | ||
56 | #define PLL_NORM_FDBK_M_MASK 0xFF | ||
57 | #define PLL_NORM_FDBK_M_SHIFT 24 | ||
58 | #define PLL_DITH_FDBK_M_MASK 0xFFFF | ||
59 | #define PLL_DITH_FDBK_M_SHIFT 16 | ||
60 | #define PLL_DIV_P_MASK 0x7 | ||
61 | #define PLL_DIV_P_SHIFT 8 | ||
62 | #define PLL_DIV_N_MASK 0xFF | ||
63 | #define PLL_DIV_N_SHIFT 0 | ||
64 | |||
65 | #define to_clk_vco(_hw) container_of(_hw, struct clk_vco, hw) | ||
66 | #define to_clk_pll(_hw) container_of(_hw, struct clk_pll, hw) | ||
67 | |||
68 | /* Calculates pll clk rate for specific value of mode, m, n and p */ | ||
69 | static unsigned long pll_calc_rate(struct pll_rate_tbl *rtbl, | ||
70 | unsigned long prate, int index, unsigned long *pll_rate) | ||
71 | { | ||
72 | unsigned long rate = prate; | ||
73 | unsigned int mode; | ||
74 | |||
75 | mode = rtbl[index].mode ? 256 : 1; | ||
76 | rate = (((2 * rate / 10000) * rtbl[index].m) / (mode * rtbl[index].n)); | ||
77 | |||
78 | if (pll_rate) | ||
79 | *pll_rate = (rate / (1 << rtbl[index].p)) * 10000; | ||
80 | |||
81 | return rate * 10000; | ||
82 | } | ||
83 | |||
84 | static long clk_pll_round_rate_index(struct clk_hw *hw, unsigned long drate, | ||
85 | unsigned long *prate, int *index) | ||
86 | { | ||
87 | struct clk_pll *pll = to_clk_pll(hw); | ||
88 | unsigned long prev_rate, vco_prev_rate, rate = 0; | ||
89 | unsigned long vco_parent_rate = | ||
90 | __clk_get_rate(__clk_get_parent(__clk_get_parent(hw->clk))); | ||
91 | |||
92 | if (!prate) { | ||
93 | pr_err("%s: prate is must for pll clk\n", __func__); | ||
94 | return -EINVAL; | ||
95 | } | ||
96 | |||
97 | for (*index = 0; *index < pll->vco->rtbl_cnt; (*index)++) { | ||
98 | prev_rate = rate; | ||
99 | vco_prev_rate = *prate; | ||
100 | *prate = pll_calc_rate(pll->vco->rtbl, vco_parent_rate, *index, | ||
101 | &rate); | ||
102 | if (drate < rate) { | ||
103 | /* previous clock was best */ | ||
104 | if (*index) { | ||
105 | rate = prev_rate; | ||
106 | *prate = vco_prev_rate; | ||
107 | (*index)--; | ||
108 | } | ||
109 | break; | ||
110 | } | ||
111 | } | ||
112 | |||
113 | return rate; | ||
114 | } | ||
115 | |||
116 | static long clk_pll_round_rate(struct clk_hw *hw, unsigned long drate, | ||
117 | unsigned long *prate) | ||
118 | { | ||
119 | int unused; | ||
120 | |||
121 | return clk_pll_round_rate_index(hw, drate, prate, &unused); | ||
122 | } | ||
123 | |||
124 | static unsigned long clk_pll_recalc_rate(struct clk_hw *hw, unsigned long | ||
125 | parent_rate) | ||
126 | { | ||
127 | struct clk_pll *pll = to_clk_pll(hw); | ||
128 | unsigned long flags = 0; | ||
129 | unsigned int p; | ||
130 | |||
131 | if (pll->vco->lock) | ||
132 | spin_lock_irqsave(pll->vco->lock, flags); | ||
133 | |||
134 | p = readl_relaxed(pll->vco->cfg_reg); | ||
135 | |||
136 | if (pll->vco->lock) | ||
137 | spin_unlock_irqrestore(pll->vco->lock, flags); | ||
138 | |||
139 | p = (p >> PLL_DIV_P_SHIFT) & PLL_DIV_P_MASK; | ||
140 | |||
141 | return parent_rate / (1 << p); | ||
142 | } | ||
143 | |||
144 | static int clk_pll_set_rate(struct clk_hw *hw, unsigned long drate, | ||
145 | unsigned long prate) | ||
146 | { | ||
147 | struct clk_pll *pll = to_clk_pll(hw); | ||
148 | struct pll_rate_tbl *rtbl = pll->vco->rtbl; | ||
149 | unsigned long flags = 0, val; | ||
150 | int i; | ||
151 | |||
152 | clk_pll_round_rate_index(hw, drate, NULL, &i); | ||
153 | |||
154 | if (pll->vco->lock) | ||
155 | spin_lock_irqsave(pll->vco->lock, flags); | ||
156 | |||
157 | val = readl_relaxed(pll->vco->cfg_reg); | ||
158 | val &= ~(PLL_DIV_P_MASK << PLL_DIV_P_SHIFT); | ||
159 | val |= (rtbl[i].p & PLL_DIV_P_MASK) << PLL_DIV_P_SHIFT; | ||
160 | writel_relaxed(val, pll->vco->cfg_reg); | ||
161 | |||
162 | if (pll->vco->lock) | ||
163 | spin_unlock_irqrestore(pll->vco->lock, flags); | ||
164 | |||
165 | return 0; | ||
166 | } | ||
167 | |||
168 | static struct clk_ops clk_pll_ops = { | ||
169 | .recalc_rate = clk_pll_recalc_rate, | ||
170 | .round_rate = clk_pll_round_rate, | ||
171 | .set_rate = clk_pll_set_rate, | ||
172 | }; | ||
173 | |||
174 | static inline unsigned long vco_calc_rate(struct clk_hw *hw, | ||
175 | unsigned long prate, int index) | ||
176 | { | ||
177 | struct clk_vco *vco = to_clk_vco(hw); | ||
178 | |||
179 | return pll_calc_rate(vco->rtbl, prate, index, NULL); | ||
180 | } | ||
181 | |||
182 | static long clk_vco_round_rate(struct clk_hw *hw, unsigned long drate, | ||
183 | unsigned long *prate) | ||
184 | { | ||
185 | struct clk_vco *vco = to_clk_vco(hw); | ||
186 | int unused; | ||
187 | |||
188 | return clk_round_rate_index(hw, drate, *prate, vco_calc_rate, | ||
189 | vco->rtbl_cnt, &unused); | ||
190 | } | ||
191 | |||
192 | static unsigned long clk_vco_recalc_rate(struct clk_hw *hw, | ||
193 | unsigned long parent_rate) | ||
194 | { | ||
195 | struct clk_vco *vco = to_clk_vco(hw); | ||
196 | unsigned long flags = 0; | ||
197 | unsigned int num = 2, den = 0, val, mode = 0; | ||
198 | |||
199 | if (vco->lock) | ||
200 | spin_lock_irqsave(vco->lock, flags); | ||
201 | |||
202 | mode = (readl_relaxed(vco->mode_reg) >> PLL_MODE_SHIFT) & PLL_MODE_MASK; | ||
203 | |||
204 | val = readl_relaxed(vco->cfg_reg); | ||
205 | |||
206 | if (vco->lock) | ||
207 | spin_unlock_irqrestore(vco->lock, flags); | ||
208 | |||
209 | den = (val >> PLL_DIV_N_SHIFT) & PLL_DIV_N_MASK; | ||
210 | |||
211 | /* calculate numerator & denominator */ | ||
212 | if (!mode) { | ||
213 | /* Normal mode */ | ||
214 | num *= (val >> PLL_NORM_FDBK_M_SHIFT) & PLL_NORM_FDBK_M_MASK; | ||
215 | } else { | ||
216 | /* Dithered mode */ | ||
217 | num *= (val >> PLL_DITH_FDBK_M_SHIFT) & PLL_DITH_FDBK_M_MASK; | ||
218 | den *= 256; | ||
219 | } | ||
220 | |||
221 | if (!den) { | ||
222 | WARN(1, "%s: denominator can't be zero\n", __func__); | ||
223 | return 0; | ||
224 | } | ||
225 | |||
226 | return (((parent_rate / 10000) * num) / den) * 10000; | ||
227 | } | ||
228 | |||
229 | /* Configures new clock rate of vco */ | ||
230 | static int clk_vco_set_rate(struct clk_hw *hw, unsigned long drate, | ||
231 | unsigned long prate) | ||
232 | { | ||
233 | struct clk_vco *vco = to_clk_vco(hw); | ||
234 | struct pll_rate_tbl *rtbl = vco->rtbl; | ||
235 | unsigned long flags = 0, val; | ||
236 | int i; | ||
237 | |||
238 | clk_round_rate_index(hw, drate, prate, vco_calc_rate, vco->rtbl_cnt, | ||
239 | &i); | ||
240 | |||
241 | if (vco->lock) | ||
242 | spin_lock_irqsave(vco->lock, flags); | ||
243 | |||
244 | val = readl_relaxed(vco->mode_reg); | ||
245 | val &= ~(PLL_MODE_MASK << PLL_MODE_SHIFT); | ||
246 | val |= (rtbl[i].mode & PLL_MODE_MASK) << PLL_MODE_SHIFT; | ||
247 | writel_relaxed(val, vco->mode_reg); | ||
248 | |||
249 | val = readl_relaxed(vco->cfg_reg); | ||
250 | val &= ~(PLL_DIV_N_MASK << PLL_DIV_N_SHIFT); | ||
251 | val |= (rtbl[i].n & PLL_DIV_N_MASK) << PLL_DIV_N_SHIFT; | ||
252 | |||
253 | val &= ~(PLL_DITH_FDBK_M_MASK << PLL_DITH_FDBK_M_SHIFT); | ||
254 | if (rtbl[i].mode) | ||
255 | val |= (rtbl[i].m & PLL_DITH_FDBK_M_MASK) << | ||
256 | PLL_DITH_FDBK_M_SHIFT; | ||
257 | else | ||
258 | val |= (rtbl[i].m & PLL_NORM_FDBK_M_MASK) << | ||
259 | PLL_NORM_FDBK_M_SHIFT; | ||
260 | |||
261 | writel_relaxed(val, vco->cfg_reg); | ||
262 | |||
263 | if (vco->lock) | ||
264 | spin_unlock_irqrestore(vco->lock, flags); | ||
265 | |||
266 | return 0; | ||
267 | } | ||
268 | |||
269 | static struct clk_ops clk_vco_ops = { | ||
270 | .recalc_rate = clk_vco_recalc_rate, | ||
271 | .round_rate = clk_vco_round_rate, | ||
272 | .set_rate = clk_vco_set_rate, | ||
273 | }; | ||
274 | |||
275 | struct clk *clk_register_vco_pll(const char *vco_name, const char *pll_name, | ||
276 | const char *vco_gate_name, const char *parent_name, | ||
277 | unsigned long flags, void __iomem *mode_reg, void __iomem | ||
278 | *cfg_reg, struct pll_rate_tbl *rtbl, u8 rtbl_cnt, | ||
279 | spinlock_t *lock, struct clk **pll_clk, | ||
280 | struct clk **vco_gate_clk) | ||
281 | { | ||
282 | struct clk_vco *vco; | ||
283 | struct clk_pll *pll; | ||
284 | struct clk *vco_clk, *tpll_clk, *tvco_gate_clk; | ||
285 | struct clk_init_data vco_init, pll_init; | ||
286 | const char **vco_parent_name; | ||
287 | |||
288 | if (!vco_name || !pll_name || !parent_name || !mode_reg || !cfg_reg || | ||
289 | !rtbl || !rtbl_cnt) { | ||
290 | pr_err("Invalid arguments passed"); | ||
291 | return ERR_PTR(-EINVAL); | ||
292 | } | ||
293 | |||
294 | vco = kzalloc(sizeof(*vco), GFP_KERNEL); | ||
295 | if (!vco) { | ||
296 | pr_err("could not allocate vco clk\n"); | ||
297 | return ERR_PTR(-ENOMEM); | ||
298 | } | ||
299 | |||
300 | pll = kzalloc(sizeof(*pll), GFP_KERNEL); | ||
301 | if (!pll) { | ||
302 | pr_err("could not allocate pll clk\n"); | ||
303 | goto free_vco; | ||
304 | } | ||
305 | |||
306 | /* struct clk_vco assignments */ | ||
307 | vco->mode_reg = mode_reg; | ||
308 | vco->cfg_reg = cfg_reg; | ||
309 | vco->rtbl = rtbl; | ||
310 | vco->rtbl_cnt = rtbl_cnt; | ||
311 | vco->lock = lock; | ||
312 | vco->hw.init = &vco_init; | ||
313 | |||
314 | pll->vco = vco; | ||
315 | pll->hw.init = &pll_init; | ||
316 | |||
317 | if (vco_gate_name) { | ||
318 | tvco_gate_clk = clk_register_gate(NULL, vco_gate_name, | ||
319 | parent_name, 0, mode_reg, PLL_ENABLE, 0, lock); | ||
320 | if (IS_ERR_OR_NULL(tvco_gate_clk)) | ||
321 | goto free_pll; | ||
322 | |||
323 | if (vco_gate_clk) | ||
324 | *vco_gate_clk = tvco_gate_clk; | ||
325 | vco_parent_name = &vco_gate_name; | ||
326 | } else { | ||
327 | vco_parent_name = &parent_name; | ||
328 | } | ||
329 | |||
330 | vco_init.name = vco_name; | ||
331 | vco_init.ops = &clk_vco_ops; | ||
332 | vco_init.flags = flags; | ||
333 | vco_init.parent_names = vco_parent_name; | ||
334 | vco_init.num_parents = 1; | ||
335 | |||
336 | pll_init.name = pll_name; | ||
337 | pll_init.ops = &clk_pll_ops; | ||
338 | pll_init.flags = CLK_SET_RATE_PARENT; | ||
339 | pll_init.parent_names = &vco_name; | ||
340 | pll_init.num_parents = 1; | ||
341 | |||
342 | vco_clk = clk_register(NULL, &vco->hw); | ||
343 | if (IS_ERR_OR_NULL(vco_clk)) | ||
344 | goto free_pll; | ||
345 | |||
346 | tpll_clk = clk_register(NULL, &pll->hw); | ||
347 | if (IS_ERR_OR_NULL(tpll_clk)) | ||
348 | goto free_pll; | ||
349 | |||
350 | if (pll_clk) | ||
351 | *pll_clk = tpll_clk; | ||
352 | |||
353 | return vco_clk; | ||
354 | |||
355 | free_pll: | ||
356 | kfree(pll); | ||
357 | free_vco: | ||
358 | kfree(vco); | ||
359 | |||
360 | pr_err("Failed to register vco pll clock\n"); | ||
361 | |||
362 | return ERR_PTR(-ENOMEM); | ||
363 | } | ||
diff --git a/drivers/clk/spear/clk.c b/drivers/clk/spear/clk.c new file mode 100644 index 000000000000..376d4e5ff326 --- /dev/null +++ b/drivers/clk/spear/clk.c | |||
@@ -0,0 +1,36 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2012 ST Microelectronics | ||
3 | * Viresh Kumar <viresh.kumar@st.com> | ||
4 | * | ||
5 | * This file is licensed under the terms of the GNU General Public | ||
6 | * License version 2. This program is licensed "as is" without any | ||
7 | * warranty of any kind, whether express or implied. | ||
8 | * | ||
9 | * SPEAr clk - Common routines | ||
10 | */ | ||
11 | |||
12 | #include <linux/clk-provider.h> | ||
13 | #include <linux/types.h> | ||
14 | #include "clk.h" | ||
15 | |||
16 | long clk_round_rate_index(struct clk_hw *hw, unsigned long drate, | ||
17 | unsigned long parent_rate, clk_calc_rate calc_rate, u8 rtbl_cnt, | ||
18 | int *index) | ||
19 | { | ||
20 | unsigned long prev_rate, rate = 0; | ||
21 | |||
22 | for (*index = 0; *index < rtbl_cnt; (*index)++) { | ||
23 | prev_rate = rate; | ||
24 | rate = calc_rate(hw, parent_rate, *index); | ||
25 | if (drate < rate) { | ||
26 | /* previous clock was best */ | ||
27 | if (*index) { | ||
28 | rate = prev_rate; | ||
29 | (*index)--; | ||
30 | } | ||
31 | break; | ||
32 | } | ||
33 | } | ||
34 | |||
35 | return rate; | ||
36 | } | ||
diff --git a/drivers/clk/spear/clk.h b/drivers/clk/spear/clk.h new file mode 100644 index 000000000000..3321c46a071c --- /dev/null +++ b/drivers/clk/spear/clk.h | |||
@@ -0,0 +1,134 @@ | |||
1 | /* | ||
2 | * Clock framework definitions for SPEAr platform | ||
3 | * | ||
4 | * Copyright (C) 2012 ST Microelectronics | ||
5 | * Viresh Kumar <viresh.kumar@st.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 | #ifndef __SPEAR_CLK_H | ||
13 | #define __SPEAR_CLK_H | ||
14 | |||
15 | #include <linux/clk-provider.h> | ||
16 | #include <linux/spinlock_types.h> | ||
17 | #include <linux/types.h> | ||
18 | |||
19 | /* Auxiliary Synth clk */ | ||
20 | /* Default masks */ | ||
21 | #define AUX_EQ_SEL_SHIFT 30 | ||
22 | #define AUX_EQ_SEL_MASK 1 | ||
23 | #define AUX_EQ1_SEL 0 | ||
24 | #define AUX_EQ2_SEL 1 | ||
25 | #define AUX_XSCALE_SHIFT 16 | ||
26 | #define AUX_XSCALE_MASK 0xFFF | ||
27 | #define AUX_YSCALE_SHIFT 0 | ||
28 | #define AUX_YSCALE_MASK 0xFFF | ||
29 | #define AUX_SYNT_ENB 31 | ||
30 | |||
31 | struct aux_clk_masks { | ||
32 | u32 eq_sel_mask; | ||
33 | u32 eq_sel_shift; | ||
34 | u32 eq1_mask; | ||
35 | u32 eq2_mask; | ||
36 | u32 xscale_sel_mask; | ||
37 | u32 xscale_sel_shift; | ||
38 | u32 yscale_sel_mask; | ||
39 | u32 yscale_sel_shift; | ||
40 | u32 enable_bit; | ||
41 | }; | ||
42 | |||
43 | struct aux_rate_tbl { | ||
44 | u16 xscale; | ||
45 | u16 yscale; | ||
46 | u8 eq; | ||
47 | }; | ||
48 | |||
49 | struct clk_aux { | ||
50 | struct clk_hw hw; | ||
51 | void __iomem *reg; | ||
52 | struct aux_clk_masks *masks; | ||
53 | struct aux_rate_tbl *rtbl; | ||
54 | u8 rtbl_cnt; | ||
55 | spinlock_t *lock; | ||
56 | }; | ||
57 | |||
58 | /* Fractional Synth clk */ | ||
59 | struct frac_rate_tbl { | ||
60 | u32 div; | ||
61 | }; | ||
62 | |||
63 | struct clk_frac { | ||
64 | struct clk_hw hw; | ||
65 | void __iomem *reg; | ||
66 | struct frac_rate_tbl *rtbl; | ||
67 | u8 rtbl_cnt; | ||
68 | spinlock_t *lock; | ||
69 | }; | ||
70 | |||
71 | /* GPT clk */ | ||
72 | struct gpt_rate_tbl { | ||
73 | u16 mscale; | ||
74 | u16 nscale; | ||
75 | }; | ||
76 | |||
77 | struct clk_gpt { | ||
78 | struct clk_hw hw; | ||
79 | void __iomem *reg; | ||
80 | struct gpt_rate_tbl *rtbl; | ||
81 | u8 rtbl_cnt; | ||
82 | spinlock_t *lock; | ||
83 | }; | ||
84 | |||
85 | /* VCO-PLL clk */ | ||
86 | struct pll_rate_tbl { | ||
87 | u8 mode; | ||
88 | u16 m; | ||
89 | u8 n; | ||
90 | u8 p; | ||
91 | }; | ||
92 | |||
93 | struct clk_vco { | ||
94 | struct clk_hw hw; | ||
95 | void __iomem *mode_reg; | ||
96 | void __iomem *cfg_reg; | ||
97 | struct pll_rate_tbl *rtbl; | ||
98 | u8 rtbl_cnt; | ||
99 | spinlock_t *lock; | ||
100 | }; | ||
101 | |||
102 | struct clk_pll { | ||
103 | struct clk_hw hw; | ||
104 | struct clk_vco *vco; | ||
105 | const char *parent[1]; | ||
106 | spinlock_t *lock; | ||
107 | }; | ||
108 | |||
109 | typedef unsigned long (*clk_calc_rate)(struct clk_hw *hw, unsigned long prate, | ||
110 | int index); | ||
111 | |||
112 | /* clk register routines */ | ||
113 | struct clk *clk_register_aux(const char *aux_name, const char *gate_name, | ||
114 | const char *parent_name, unsigned long flags, void __iomem *reg, | ||
115 | struct aux_clk_masks *masks, struct aux_rate_tbl *rtbl, | ||
116 | u8 rtbl_cnt, spinlock_t *lock, struct clk **gate_clk); | ||
117 | struct clk *clk_register_frac(const char *name, const char *parent_name, | ||
118 | unsigned long flags, void __iomem *reg, | ||
119 | struct frac_rate_tbl *rtbl, u8 rtbl_cnt, spinlock_t *lock); | ||
120 | struct clk *clk_register_gpt(const char *name, const char *parent_name, unsigned | ||
121 | long flags, void __iomem *reg, struct gpt_rate_tbl *rtbl, u8 | ||
122 | rtbl_cnt, spinlock_t *lock); | ||
123 | struct clk *clk_register_vco_pll(const char *vco_name, const char *pll_name, | ||
124 | const char *vco_gate_name, const char *parent_name, | ||
125 | unsigned long flags, void __iomem *mode_reg, void __iomem | ||
126 | *cfg_reg, struct pll_rate_tbl *rtbl, u8 rtbl_cnt, | ||
127 | spinlock_t *lock, struct clk **pll_clk, | ||
128 | struct clk **vco_gate_clk); | ||
129 | |||
130 | long clk_round_rate_index(struct clk_hw *hw, unsigned long drate, | ||
131 | unsigned long parent_rate, clk_calc_rate calc_rate, u8 rtbl_cnt, | ||
132 | int *index); | ||
133 | |||
134 | #endif /* __SPEAR_CLK_H */ | ||
diff --git a/drivers/clk/spear/spear3xx_clock.c b/drivers/clk/spear/spear3xx_clock.c new file mode 100644 index 000000000000..440bb3e4c971 --- /dev/null +++ b/drivers/clk/spear/spear3xx_clock.c | |||
@@ -0,0 +1,612 @@ | |||
1 | /* | ||
2 | * SPEAr3xx machines clock framework source file | ||
3 | * | ||
4 | * Copyright (C) 2012 ST Microelectronics | ||
5 | * Viresh Kumar <viresh.kumar@st.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.h> | ||
13 | #include <linux/clkdev.h> | ||
14 | #include <linux/err.h> | ||
15 | #include <linux/io.h> | ||
16 | #include <linux/of_platform.h> | ||
17 | #include <linux/spinlock_types.h> | ||
18 | #include <mach/misc_regs.h> | ||
19 | #include "clk.h" | ||
20 | |||
21 | static DEFINE_SPINLOCK(_lock); | ||
22 | |||
23 | #define PLL1_CTR (MISC_BASE + 0x008) | ||
24 | #define PLL1_FRQ (MISC_BASE + 0x00C) | ||
25 | #define PLL2_CTR (MISC_BASE + 0x014) | ||
26 | #define PLL2_FRQ (MISC_BASE + 0x018) | ||
27 | #define PLL_CLK_CFG (MISC_BASE + 0x020) | ||
28 | /* PLL_CLK_CFG register masks */ | ||
29 | #define MCTR_CLK_SHIFT 28 | ||
30 | #define MCTR_CLK_MASK 3 | ||
31 | |||
32 | #define CORE_CLK_CFG (MISC_BASE + 0x024) | ||
33 | /* CORE CLK CFG register masks */ | ||
34 | #define GEN_SYNTH2_3_CLK_SHIFT 18 | ||
35 | #define GEN_SYNTH2_3_CLK_MASK 1 | ||
36 | |||
37 | #define HCLK_RATIO_SHIFT 10 | ||
38 | #define HCLK_RATIO_MASK 2 | ||
39 | #define PCLK_RATIO_SHIFT 8 | ||
40 | #define PCLK_RATIO_MASK 2 | ||
41 | |||
42 | #define PERIP_CLK_CFG (MISC_BASE + 0x028) | ||
43 | /* PERIP_CLK_CFG register masks */ | ||
44 | #define UART_CLK_SHIFT 4 | ||
45 | #define UART_CLK_MASK 1 | ||
46 | #define FIRDA_CLK_SHIFT 5 | ||
47 | #define FIRDA_CLK_MASK 2 | ||
48 | #define GPT0_CLK_SHIFT 8 | ||
49 | #define GPT1_CLK_SHIFT 11 | ||
50 | #define GPT2_CLK_SHIFT 12 | ||
51 | #define GPT_CLK_MASK 1 | ||
52 | |||
53 | #define PERIP1_CLK_ENB (MISC_BASE + 0x02C) | ||
54 | /* PERIP1_CLK_ENB register masks */ | ||
55 | #define UART_CLK_ENB 3 | ||
56 | #define SSP_CLK_ENB 5 | ||
57 | #define I2C_CLK_ENB 7 | ||
58 | #define JPEG_CLK_ENB 8 | ||
59 | #define FIRDA_CLK_ENB 10 | ||
60 | #define GPT1_CLK_ENB 11 | ||
61 | #define GPT2_CLK_ENB 12 | ||
62 | #define ADC_CLK_ENB 15 | ||
63 | #define RTC_CLK_ENB 17 | ||
64 | #define GPIO_CLK_ENB 18 | ||
65 | #define DMA_CLK_ENB 19 | ||
66 | #define SMI_CLK_ENB 21 | ||
67 | #define GMAC_CLK_ENB 23 | ||
68 | #define USBD_CLK_ENB 24 | ||
69 | #define USBH_CLK_ENB 25 | ||
70 | #define C3_CLK_ENB 31 | ||
71 | |||
72 | #define RAS_CLK_ENB (MISC_BASE + 0x034) | ||
73 | #define RAS_AHB_CLK_ENB 0 | ||
74 | #define RAS_PLL1_CLK_ENB 1 | ||
75 | #define RAS_APB_CLK_ENB 2 | ||
76 | #define RAS_32K_CLK_ENB 3 | ||
77 | #define RAS_24M_CLK_ENB 4 | ||
78 | #define RAS_48M_CLK_ENB 5 | ||
79 | #define RAS_PLL2_CLK_ENB 7 | ||
80 | #define RAS_SYNT0_CLK_ENB 8 | ||
81 | #define RAS_SYNT1_CLK_ENB 9 | ||
82 | #define RAS_SYNT2_CLK_ENB 10 | ||
83 | #define RAS_SYNT3_CLK_ENB 11 | ||
84 | |||
85 | #define PRSC0_CLK_CFG (MISC_BASE + 0x044) | ||
86 | #define PRSC1_CLK_CFG (MISC_BASE + 0x048) | ||
87 | #define PRSC2_CLK_CFG (MISC_BASE + 0x04C) | ||
88 | #define AMEM_CLK_CFG (MISC_BASE + 0x050) | ||
89 | #define AMEM_CLK_ENB 0 | ||
90 | |||
91 | #define CLCD_CLK_SYNT (MISC_BASE + 0x05C) | ||
92 | #define FIRDA_CLK_SYNT (MISC_BASE + 0x060) | ||
93 | #define UART_CLK_SYNT (MISC_BASE + 0x064) | ||
94 | #define GMAC_CLK_SYNT (MISC_BASE + 0x068) | ||
95 | #define GEN0_CLK_SYNT (MISC_BASE + 0x06C) | ||
96 | #define GEN1_CLK_SYNT (MISC_BASE + 0x070) | ||
97 | #define GEN2_CLK_SYNT (MISC_BASE + 0x074) | ||
98 | #define GEN3_CLK_SYNT (MISC_BASE + 0x078) | ||
99 | |||
100 | /* pll rate configuration table, in ascending order of rates */ | ||
101 | static struct pll_rate_tbl pll_rtbl[] = { | ||
102 | {.mode = 0, .m = 0x53, .n = 0x0C, .p = 0x1}, /* vco 332 & pll 166 MHz */ | ||
103 | {.mode = 0, .m = 0x85, .n = 0x0C, .p = 0x1}, /* vco 532 & pll 266 MHz */ | ||
104 | {.mode = 0, .m = 0xA6, .n = 0x0C, .p = 0x1}, /* vco 664 & pll 332 MHz */ | ||
105 | }; | ||
106 | |||
107 | /* aux rate configuration table, in ascending order of rates */ | ||
108 | static struct aux_rate_tbl aux_rtbl[] = { | ||
109 | /* For PLL1 = 332 MHz */ | ||
110 | {.xscale = 2, .yscale = 27, .eq = 0}, /* 12.296 MHz */ | ||
111 | {.xscale = 2, .yscale = 8, .eq = 0}, /* 41.5 MHz */ | ||
112 | {.xscale = 2, .yscale = 4, .eq = 0}, /* 83 MHz */ | ||
113 | {.xscale = 1, .yscale = 2, .eq = 1}, /* 166 MHz */ | ||
114 | }; | ||
115 | |||
116 | /* gpt rate configuration table, in ascending order of rates */ | ||
117 | static struct gpt_rate_tbl gpt_rtbl[] = { | ||
118 | /* For pll1 = 332 MHz */ | ||
119 | {.mscale = 4, .nscale = 0}, /* 41.5 MHz */ | ||
120 | {.mscale = 2, .nscale = 0}, /* 55.3 MHz */ | ||
121 | {.mscale = 1, .nscale = 0}, /* 83 MHz */ | ||
122 | }; | ||
123 | |||
124 | /* clock parents */ | ||
125 | static const char *uart0_parents[] = { "pll3_48m_clk", "uart_synth_gate_clk", }; | ||
126 | static const char *firda_parents[] = { "pll3_48m_clk", "firda_synth_gate_clk", | ||
127 | }; | ||
128 | static const char *gpt0_parents[] = { "pll3_48m_clk", "gpt0_synth_clk", }; | ||
129 | static const char *gpt1_parents[] = { "pll3_48m_clk", "gpt1_synth_clk", }; | ||
130 | static const char *gpt2_parents[] = { "pll3_48m_clk", "gpt2_synth_clk", }; | ||
131 | static const char *gen2_3_parents[] = { "pll1_clk", "pll2_clk", }; | ||
132 | static const char *ddr_parents[] = { "ahb_clk", "ahbmult2_clk", "none", | ||
133 | "pll2_clk", }; | ||
134 | |||
135 | #ifdef CONFIG_MACH_SPEAR300 | ||
136 | static void __init spear300_clk_init(void) | ||
137 | { | ||
138 | struct clk *clk; | ||
139 | |||
140 | clk = clk_register_fixed_factor(NULL, "clcd_clk", "ras_pll3_48m_clk", 0, | ||
141 | 1, 1); | ||
142 | clk_register_clkdev(clk, NULL, "60000000.clcd"); | ||
143 | |||
144 | clk = clk_register_fixed_factor(NULL, "fsmc_clk", "ras_ahb_clk", 0, 1, | ||
145 | 1); | ||
146 | clk_register_clkdev(clk, NULL, "94000000.flash"); | ||
147 | |||
148 | clk = clk_register_fixed_factor(NULL, "sdhci_clk", "ras_ahb_clk", 0, 1, | ||
149 | 1); | ||
150 | clk_register_clkdev(clk, NULL, "70000000.sdhci"); | ||
151 | |||
152 | clk = clk_register_fixed_factor(NULL, "gpio1_clk", "ras_apb_clk", 0, 1, | ||
153 | 1); | ||
154 | clk_register_clkdev(clk, NULL, "a9000000.gpio"); | ||
155 | |||
156 | clk = clk_register_fixed_factor(NULL, "kbd_clk", "ras_apb_clk", 0, 1, | ||
157 | 1); | ||
158 | clk_register_clkdev(clk, NULL, "a0000000.kbd"); | ||
159 | } | ||
160 | #endif | ||
161 | |||
162 | /* array of all spear 310 clock lookups */ | ||
163 | #ifdef CONFIG_MACH_SPEAR310 | ||
164 | static void __init spear310_clk_init(void) | ||
165 | { | ||
166 | struct clk *clk; | ||
167 | |||
168 | clk = clk_register_fixed_factor(NULL, "emi_clk", "ras_ahb_clk", 0, 1, | ||
169 | 1); | ||
170 | clk_register_clkdev(clk, "emi", NULL); | ||
171 | |||
172 | clk = clk_register_fixed_factor(NULL, "fsmc_clk", "ras_ahb_clk", 0, 1, | ||
173 | 1); | ||
174 | clk_register_clkdev(clk, NULL, "44000000.flash"); | ||
175 | |||
176 | clk = clk_register_fixed_factor(NULL, "tdm_clk", "ras_ahb_clk", 0, 1, | ||
177 | 1); | ||
178 | clk_register_clkdev(clk, NULL, "tdm"); | ||
179 | |||
180 | clk = clk_register_fixed_factor(NULL, "uart1_clk", "ras_apb_clk", 0, 1, | ||
181 | 1); | ||
182 | clk_register_clkdev(clk, NULL, "b2000000.serial"); | ||
183 | |||
184 | clk = clk_register_fixed_factor(NULL, "uart2_clk", "ras_apb_clk", 0, 1, | ||
185 | 1); | ||
186 | clk_register_clkdev(clk, NULL, "b2080000.serial"); | ||
187 | |||
188 | clk = clk_register_fixed_factor(NULL, "uart3_clk", "ras_apb_clk", 0, 1, | ||
189 | 1); | ||
190 | clk_register_clkdev(clk, NULL, "b2100000.serial"); | ||
191 | |||
192 | clk = clk_register_fixed_factor(NULL, "uart4_clk", "ras_apb_clk", 0, 1, | ||
193 | 1); | ||
194 | clk_register_clkdev(clk, NULL, "b2180000.serial"); | ||
195 | |||
196 | clk = clk_register_fixed_factor(NULL, "uart5_clk", "ras_apb_clk", 0, 1, | ||
197 | 1); | ||
198 | clk_register_clkdev(clk, NULL, "b2200000.serial"); | ||
199 | } | ||
200 | #endif | ||
201 | |||
202 | /* array of all spear 320 clock lookups */ | ||
203 | #ifdef CONFIG_MACH_SPEAR320 | ||
204 | #define SMII_PCLK_SHIFT 18 | ||
205 | #define SMII_PCLK_MASK 2 | ||
206 | #define SMII_PCLK_VAL_PAD 0x0 | ||
207 | #define SMII_PCLK_VAL_PLL2 0x1 | ||
208 | #define SMII_PCLK_VAL_SYNTH0 0x2 | ||
209 | #define SDHCI_PCLK_SHIFT 15 | ||
210 | #define SDHCI_PCLK_MASK 1 | ||
211 | #define SDHCI_PCLK_VAL_48M 0x0 | ||
212 | #define SDHCI_PCLK_VAL_SYNTH3 0x1 | ||
213 | #define I2S_REF_PCLK_SHIFT 8 | ||
214 | #define I2S_REF_PCLK_MASK 1 | ||
215 | #define I2S_REF_PCLK_SYNTH_VAL 0x1 | ||
216 | #define I2S_REF_PCLK_PLL2_VAL 0x0 | ||
217 | #define UART1_PCLK_SHIFT 6 | ||
218 | #define UART1_PCLK_MASK 1 | ||
219 | #define SPEAR320_UARTX_PCLK_VAL_SYNTH1 0x0 | ||
220 | #define SPEAR320_UARTX_PCLK_VAL_APB 0x1 | ||
221 | |||
222 | static const char *i2s_ref_parents[] = { "ras_pll2_clk", | ||
223 | "ras_gen2_synth_gate_clk", }; | ||
224 | static const char *sdhci_parents[] = { "ras_pll3_48m_clk", | ||
225 | "ras_gen3_synth_gate_clk", | ||
226 | }; | ||
227 | static const char *smii0_parents[] = { "smii_125m_pad", "ras_pll2_clk", | ||
228 | "ras_gen0_synth_gate_clk", }; | ||
229 | static const char *uartx_parents[] = { "ras_gen1_synth_gate_clk", "ras_apb_clk", | ||
230 | }; | ||
231 | |||
232 | static void __init spear320_clk_init(void) | ||
233 | { | ||
234 | struct clk *clk; | ||
235 | |||
236 | clk = clk_register_fixed_rate(NULL, "smii_125m_pad_clk", NULL, | ||
237 | CLK_IS_ROOT, 125000000); | ||
238 | clk_register_clkdev(clk, "smii_125m_pad", NULL); | ||
239 | |||
240 | clk = clk_register_fixed_factor(NULL, "clcd_clk", "ras_pll3_48m_clk", 0, | ||
241 | 1, 1); | ||
242 | clk_register_clkdev(clk, NULL, "90000000.clcd"); | ||
243 | |||
244 | clk = clk_register_fixed_factor(NULL, "emi_clk", "ras_ahb_clk", 0, 1, | ||
245 | 1); | ||
246 | clk_register_clkdev(clk, "emi", NULL); | ||
247 | |||
248 | clk = clk_register_fixed_factor(NULL, "fsmc_clk", "ras_ahb_clk", 0, 1, | ||
249 | 1); | ||
250 | clk_register_clkdev(clk, NULL, "4c000000.flash"); | ||
251 | |||
252 | clk = clk_register_fixed_factor(NULL, "i2c1_clk", "ras_ahb_clk", 0, 1, | ||
253 | 1); | ||
254 | clk_register_clkdev(clk, NULL, "a7000000.i2c"); | ||
255 | |||
256 | clk = clk_register_fixed_factor(NULL, "pwm_clk", "ras_ahb_clk", 0, 1, | ||
257 | 1); | ||
258 | clk_register_clkdev(clk, "pwm", NULL); | ||
259 | |||
260 | clk = clk_register_fixed_factor(NULL, "ssp1_clk", "ras_ahb_clk", 0, 1, | ||
261 | 1); | ||
262 | clk_register_clkdev(clk, NULL, "a5000000.spi"); | ||
263 | |||
264 | clk = clk_register_fixed_factor(NULL, "ssp2_clk", "ras_ahb_clk", 0, 1, | ||
265 | 1); | ||
266 | clk_register_clkdev(clk, NULL, "a6000000.spi"); | ||
267 | |||
268 | clk = clk_register_fixed_factor(NULL, "can0_clk", "ras_apb_clk", 0, 1, | ||
269 | 1); | ||
270 | clk_register_clkdev(clk, NULL, "c_can_platform.0"); | ||
271 | |||
272 | clk = clk_register_fixed_factor(NULL, "can1_clk", "ras_apb_clk", 0, 1, | ||
273 | 1); | ||
274 | clk_register_clkdev(clk, NULL, "c_can_platform.1"); | ||
275 | |||
276 | clk = clk_register_fixed_factor(NULL, "i2s_clk", "ras_apb_clk", 0, 1, | ||
277 | 1); | ||
278 | clk_register_clkdev(clk, NULL, "i2s"); | ||
279 | |||
280 | clk = clk_register_mux(NULL, "i2s_ref_clk", i2s_ref_parents, | ||
281 | ARRAY_SIZE(i2s_ref_parents), 0, SPEAR320_CONTROL_REG, | ||
282 | I2S_REF_PCLK_SHIFT, I2S_REF_PCLK_MASK, 0, &_lock); | ||
283 | clk_register_clkdev(clk, "i2s_ref_clk", NULL); | ||
284 | |||
285 | clk = clk_register_fixed_factor(NULL, "i2s_sclk", "i2s_ref_clk", 0, 1, | ||
286 | 4); | ||
287 | clk_register_clkdev(clk, "i2s_sclk", NULL); | ||
288 | |||
289 | clk = clk_register_mux(NULL, "rs485_clk", uartx_parents, | ||
290 | ARRAY_SIZE(uartx_parents), 0, SPEAR320_EXT_CTRL_REG, | ||
291 | SPEAR320_RS485_PCLK_SHIFT, SPEAR320_UARTX_PCLK_MASK, 0, | ||
292 | &_lock); | ||
293 | clk_register_clkdev(clk, NULL, "a9300000.serial"); | ||
294 | |||
295 | clk = clk_register_mux(NULL, "sdhci_clk", sdhci_parents, | ||
296 | ARRAY_SIZE(sdhci_parents), 0, SPEAR320_CONTROL_REG, | ||
297 | SDHCI_PCLK_SHIFT, SDHCI_PCLK_MASK, 0, &_lock); | ||
298 | clk_register_clkdev(clk, NULL, "70000000.sdhci"); | ||
299 | |||
300 | clk = clk_register_mux(NULL, "smii_pclk", smii0_parents, | ||
301 | ARRAY_SIZE(smii0_parents), 0, SPEAR320_CONTROL_REG, | ||
302 | SMII_PCLK_SHIFT, SMII_PCLK_MASK, 0, &_lock); | ||
303 | clk_register_clkdev(clk, NULL, "smii_pclk"); | ||
304 | |||
305 | clk = clk_register_fixed_factor(NULL, "smii_clk", "smii_pclk", 0, 1, 1); | ||
306 | clk_register_clkdev(clk, NULL, "smii"); | ||
307 | |||
308 | clk = clk_register_mux(NULL, "uart1_clk", uartx_parents, | ||
309 | ARRAY_SIZE(uartx_parents), 0, SPEAR320_CONTROL_REG, | ||
310 | UART1_PCLK_SHIFT, UART1_PCLK_MASK, 0, &_lock); | ||
311 | clk_register_clkdev(clk, NULL, "a3000000.serial"); | ||
312 | |||
313 | clk = clk_register_mux(NULL, "uart2_clk", uartx_parents, | ||
314 | ARRAY_SIZE(uartx_parents), 0, SPEAR320_EXT_CTRL_REG, | ||
315 | SPEAR320_UART2_PCLK_SHIFT, SPEAR320_UARTX_PCLK_MASK, 0, | ||
316 | &_lock); | ||
317 | clk_register_clkdev(clk, NULL, "a4000000.serial"); | ||
318 | |||
319 | clk = clk_register_mux(NULL, "uart3_clk", uartx_parents, | ||
320 | ARRAY_SIZE(uartx_parents), 0, SPEAR320_EXT_CTRL_REG, | ||
321 | SPEAR320_UART3_PCLK_SHIFT, SPEAR320_UARTX_PCLK_MASK, 0, | ||
322 | &_lock); | ||
323 | clk_register_clkdev(clk, NULL, "a9100000.serial"); | ||
324 | |||
325 | clk = clk_register_mux(NULL, "uart4_clk", uartx_parents, | ||
326 | ARRAY_SIZE(uartx_parents), 0, SPEAR320_EXT_CTRL_REG, | ||
327 | SPEAR320_UART4_PCLK_SHIFT, SPEAR320_UARTX_PCLK_MASK, 0, | ||
328 | &_lock); | ||
329 | clk_register_clkdev(clk, NULL, "a9200000.serial"); | ||
330 | |||
331 | clk = clk_register_mux(NULL, "uart5_clk", uartx_parents, | ||
332 | ARRAY_SIZE(uartx_parents), 0, SPEAR320_EXT_CTRL_REG, | ||
333 | SPEAR320_UART5_PCLK_SHIFT, SPEAR320_UARTX_PCLK_MASK, 0, | ||
334 | &_lock); | ||
335 | clk_register_clkdev(clk, NULL, "60000000.serial"); | ||
336 | |||
337 | clk = clk_register_mux(NULL, "uart6_clk", uartx_parents, | ||
338 | ARRAY_SIZE(uartx_parents), 0, SPEAR320_EXT_CTRL_REG, | ||
339 | SPEAR320_UART6_PCLK_SHIFT, SPEAR320_UARTX_PCLK_MASK, 0, | ||
340 | &_lock); | ||
341 | clk_register_clkdev(clk, NULL, "60100000.serial"); | ||
342 | } | ||
343 | #endif | ||
344 | |||
345 | void __init spear3xx_clk_init(void) | ||
346 | { | ||
347 | struct clk *clk, *clk1; | ||
348 | |||
349 | clk = clk_register_fixed_rate(NULL, "apb_pclk", NULL, CLK_IS_ROOT, 0); | ||
350 | clk_register_clkdev(clk, "apb_pclk", NULL); | ||
351 | |||
352 | clk = clk_register_fixed_rate(NULL, "osc_32k_clk", NULL, CLK_IS_ROOT, | ||
353 | 32000); | ||
354 | clk_register_clkdev(clk, "osc_32k_clk", NULL); | ||
355 | |||
356 | clk = clk_register_fixed_rate(NULL, "osc_24m_clk", NULL, CLK_IS_ROOT, | ||
357 | 24000000); | ||
358 | clk_register_clkdev(clk, "osc_24m_clk", NULL); | ||
359 | |||
360 | /* clock derived from 32 KHz osc clk */ | ||
361 | clk = clk_register_gate(NULL, "rtc-spear", "osc_32k_clk", 0, | ||
362 | PERIP1_CLK_ENB, RTC_CLK_ENB, 0, &_lock); | ||
363 | clk_register_clkdev(clk, NULL, "fc900000.rtc"); | ||
364 | |||
365 | /* clock derived from 24 MHz osc clk */ | ||
366 | clk = clk_register_fixed_rate(NULL, "pll3_48m_clk", "osc_24m_clk", 0, | ||
367 | 48000000); | ||
368 | clk_register_clkdev(clk, "pll3_48m_clk", NULL); | ||
369 | |||
370 | clk = clk_register_fixed_factor(NULL, "wdt_clk", "osc_24m_clk", 0, 1, | ||
371 | 1); | ||
372 | clk_register_clkdev(clk, NULL, "fc880000.wdt"); | ||
373 | |||
374 | clk = clk_register_vco_pll("vco1_clk", "pll1_clk", NULL, | ||
375 | "osc_24m_clk", 0, PLL1_CTR, PLL1_FRQ, pll_rtbl, | ||
376 | ARRAY_SIZE(pll_rtbl), &_lock, &clk1, NULL); | ||
377 | clk_register_clkdev(clk, "vco1_clk", NULL); | ||
378 | clk_register_clkdev(clk1, "pll1_clk", NULL); | ||
379 | |||
380 | clk = clk_register_vco_pll("vco2_clk", "pll2_clk", NULL, | ||
381 | "osc_24m_clk", 0, PLL2_CTR, PLL2_FRQ, pll_rtbl, | ||
382 | ARRAY_SIZE(pll_rtbl), &_lock, &clk1, NULL); | ||
383 | clk_register_clkdev(clk, "vco2_clk", NULL); | ||
384 | clk_register_clkdev(clk1, "pll2_clk", NULL); | ||
385 | |||
386 | /* clock derived from pll1 clk */ | ||
387 | clk = clk_register_fixed_factor(NULL, "cpu_clk", "pll1_clk", 0, 1, 1); | ||
388 | clk_register_clkdev(clk, "cpu_clk", NULL); | ||
389 | |||
390 | clk = clk_register_divider(NULL, "ahb_clk", "pll1_clk", | ||
391 | CLK_SET_RATE_PARENT, CORE_CLK_CFG, HCLK_RATIO_SHIFT, | ||
392 | HCLK_RATIO_MASK, 0, &_lock); | ||
393 | clk_register_clkdev(clk, "ahb_clk", NULL); | ||
394 | |||
395 | clk = clk_register_aux("uart_synth_clk", "uart_synth_gate_clk", | ||
396 | "pll1_clk", 0, UART_CLK_SYNT, NULL, aux_rtbl, | ||
397 | ARRAY_SIZE(aux_rtbl), &_lock, &clk1); | ||
398 | clk_register_clkdev(clk, "uart_synth_clk", NULL); | ||
399 | clk_register_clkdev(clk1, "uart_synth_gate_clk", NULL); | ||
400 | |||
401 | clk = clk_register_mux(NULL, "uart0_mux_clk", uart0_parents, | ||
402 | ARRAY_SIZE(uart0_parents), 0, PERIP_CLK_CFG, | ||
403 | UART_CLK_SHIFT, UART_CLK_MASK, 0, &_lock); | ||
404 | clk_register_clkdev(clk, "uart0_mux_clk", NULL); | ||
405 | |||
406 | clk = clk_register_gate(NULL, "uart0", "uart0_mux_clk", 0, | ||
407 | PERIP1_CLK_ENB, UART_CLK_ENB, 0, &_lock); | ||
408 | clk_register_clkdev(clk, NULL, "d0000000.serial"); | ||
409 | |||
410 | clk = clk_register_aux("firda_synth_clk", "firda_synth_gate_clk", | ||
411 | "pll1_clk", 0, FIRDA_CLK_SYNT, NULL, aux_rtbl, | ||
412 | ARRAY_SIZE(aux_rtbl), &_lock, &clk1); | ||
413 | clk_register_clkdev(clk, "firda_synth_clk", NULL); | ||
414 | clk_register_clkdev(clk1, "firda_synth_gate_clk", NULL); | ||
415 | |||
416 | clk = clk_register_mux(NULL, "firda_mux_clk", firda_parents, | ||
417 | ARRAY_SIZE(firda_parents), 0, PERIP_CLK_CFG, | ||
418 | FIRDA_CLK_SHIFT, FIRDA_CLK_MASK, 0, &_lock); | ||
419 | clk_register_clkdev(clk, "firda_mux_clk", NULL); | ||
420 | |||
421 | clk = clk_register_gate(NULL, "firda_clk", "firda_mux_clk", 0, | ||
422 | PERIP1_CLK_ENB, FIRDA_CLK_ENB, 0, &_lock); | ||
423 | clk_register_clkdev(clk, NULL, "firda"); | ||
424 | |||
425 | /* gpt clocks */ | ||
426 | clk_register_gpt("gpt0_synth_clk", "pll1_clk", 0, PRSC0_CLK_CFG, | ||
427 | gpt_rtbl, ARRAY_SIZE(gpt_rtbl), &_lock); | ||
428 | clk = clk_register_mux(NULL, "gpt0_clk", gpt0_parents, | ||
429 | ARRAY_SIZE(gpt0_parents), 0, PERIP_CLK_CFG, | ||
430 | GPT0_CLK_SHIFT, GPT_CLK_MASK, 0, &_lock); | ||
431 | clk_register_clkdev(clk, NULL, "gpt0"); | ||
432 | |||
433 | clk_register_gpt("gpt1_synth_clk", "pll1_clk", 0, PRSC1_CLK_CFG, | ||
434 | gpt_rtbl, ARRAY_SIZE(gpt_rtbl), &_lock); | ||
435 | clk = clk_register_mux(NULL, "gpt1_mux_clk", gpt1_parents, | ||
436 | ARRAY_SIZE(gpt1_parents), 0, PERIP_CLK_CFG, | ||
437 | GPT1_CLK_SHIFT, GPT_CLK_MASK, 0, &_lock); | ||
438 | clk_register_clkdev(clk, "gpt1_mux_clk", NULL); | ||
439 | clk = clk_register_gate(NULL, "gpt1_clk", "gpt1_mux_clk", 0, | ||
440 | PERIP1_CLK_ENB, GPT1_CLK_ENB, 0, &_lock); | ||
441 | clk_register_clkdev(clk, NULL, "gpt1"); | ||
442 | |||
443 | clk_register_gpt("gpt2_synth_clk", "pll1_clk", 0, PRSC2_CLK_CFG, | ||
444 | gpt_rtbl, ARRAY_SIZE(gpt_rtbl), &_lock); | ||
445 | clk = clk_register_mux(NULL, "gpt2_mux_clk", gpt2_parents, | ||
446 | ARRAY_SIZE(gpt2_parents), 0, PERIP_CLK_CFG, | ||
447 | GPT2_CLK_SHIFT, GPT_CLK_MASK, 0, &_lock); | ||
448 | clk_register_clkdev(clk, "gpt2_mux_clk", NULL); | ||
449 | clk = clk_register_gate(NULL, "gpt2_clk", "gpt2_mux_clk", 0, | ||
450 | PERIP1_CLK_ENB, GPT2_CLK_ENB, 0, &_lock); | ||
451 | clk_register_clkdev(clk, NULL, "gpt2"); | ||
452 | |||
453 | /* general synths clocks */ | ||
454 | clk = clk_register_aux("gen0_synth_clk", "gen0_synth_gate_clk", | ||
455 | "pll1_clk", 0, GEN0_CLK_SYNT, NULL, aux_rtbl, | ||
456 | ARRAY_SIZE(aux_rtbl), &_lock, &clk1); | ||
457 | clk_register_clkdev(clk, "gen0_synth_clk", NULL); | ||
458 | clk_register_clkdev(clk1, "gen0_synth_gate_clk", NULL); | ||
459 | |||
460 | clk = clk_register_aux("gen1_synth_clk", "gen1_synth_gate_clk", | ||
461 | "pll1_clk", 0, GEN1_CLK_SYNT, NULL, aux_rtbl, | ||
462 | ARRAY_SIZE(aux_rtbl), &_lock, &clk1); | ||
463 | clk_register_clkdev(clk, "gen1_synth_clk", NULL); | ||
464 | clk_register_clkdev(clk1, "gen1_synth_gate_clk", NULL); | ||
465 | |||
466 | clk = clk_register_mux(NULL, "gen2_3_parent_clk", gen2_3_parents, | ||
467 | ARRAY_SIZE(gen2_3_parents), 0, CORE_CLK_CFG, | ||
468 | GEN_SYNTH2_3_CLK_SHIFT, GEN_SYNTH2_3_CLK_MASK, 0, | ||
469 | &_lock); | ||
470 | clk_register_clkdev(clk, "gen2_3_parent_clk", NULL); | ||
471 | |||
472 | clk = clk_register_aux("gen2_synth_clk", "gen2_synth_gate_clk", | ||
473 | "gen2_3_parent_clk", 0, GEN2_CLK_SYNT, NULL, aux_rtbl, | ||
474 | ARRAY_SIZE(aux_rtbl), &_lock, &clk1); | ||
475 | clk_register_clkdev(clk, "gen2_synth_clk", NULL); | ||
476 | clk_register_clkdev(clk1, "gen2_synth_gate_clk", NULL); | ||
477 | |||
478 | clk = clk_register_aux("gen3_synth_clk", "gen3_synth_gate_clk", | ||
479 | "gen2_3_parent_clk", 0, GEN3_CLK_SYNT, NULL, aux_rtbl, | ||
480 | ARRAY_SIZE(aux_rtbl), &_lock, &clk1); | ||
481 | clk_register_clkdev(clk, "gen3_synth_clk", NULL); | ||
482 | clk_register_clkdev(clk1, "gen3_synth_gate_clk", NULL); | ||
483 | |||
484 | /* clock derived from pll3 clk */ | ||
485 | clk = clk_register_gate(NULL, "usbh_clk", "pll3_48m_clk", 0, | ||
486 | PERIP1_CLK_ENB, USBH_CLK_ENB, 0, &_lock); | ||
487 | clk_register_clkdev(clk, "usbh_clk", NULL); | ||
488 | |||
489 | clk = clk_register_fixed_factor(NULL, "usbh.0_clk", "usbh_clk", 0, 1, | ||
490 | 1); | ||
491 | clk_register_clkdev(clk, "usbh.0_clk", NULL); | ||
492 | |||
493 | clk = clk_register_fixed_factor(NULL, "usbh.1_clk", "usbh_clk", 0, 1, | ||
494 | 1); | ||
495 | clk_register_clkdev(clk, "usbh.1_clk", NULL); | ||
496 | |||
497 | clk = clk_register_gate(NULL, "usbd_clk", "pll3_48m_clk", 0, | ||
498 | PERIP1_CLK_ENB, USBD_CLK_ENB, 0, &_lock); | ||
499 | clk_register_clkdev(clk, NULL, "designware_udc"); | ||
500 | |||
501 | /* clock derived from ahb clk */ | ||
502 | clk = clk_register_fixed_factor(NULL, "ahbmult2_clk", "ahb_clk", 0, 2, | ||
503 | 1); | ||
504 | clk_register_clkdev(clk, "ahbmult2_clk", NULL); | ||
505 | |||
506 | clk = clk_register_mux(NULL, "ddr_clk", ddr_parents, | ||
507 | ARRAY_SIZE(ddr_parents), 0, PLL_CLK_CFG, MCTR_CLK_SHIFT, | ||
508 | MCTR_CLK_MASK, 0, &_lock); | ||
509 | clk_register_clkdev(clk, "ddr_clk", NULL); | ||
510 | |||
511 | clk = clk_register_divider(NULL, "apb_clk", "ahb_clk", | ||
512 | CLK_SET_RATE_PARENT, CORE_CLK_CFG, PCLK_RATIO_SHIFT, | ||
513 | PCLK_RATIO_MASK, 0, &_lock); | ||
514 | clk_register_clkdev(clk, "apb_clk", NULL); | ||
515 | |||
516 | clk = clk_register_gate(NULL, "amem_clk", "ahb_clk", 0, AMEM_CLK_CFG, | ||
517 | AMEM_CLK_ENB, 0, &_lock); | ||
518 | clk_register_clkdev(clk, "amem_clk", NULL); | ||
519 | |||
520 | clk = clk_register_gate(NULL, "c3_clk", "ahb_clk", 0, PERIP1_CLK_ENB, | ||
521 | C3_CLK_ENB, 0, &_lock); | ||
522 | clk_register_clkdev(clk, NULL, "c3_clk"); | ||
523 | |||
524 | clk = clk_register_gate(NULL, "dma_clk", "ahb_clk", 0, PERIP1_CLK_ENB, | ||
525 | DMA_CLK_ENB, 0, &_lock); | ||
526 | clk_register_clkdev(clk, NULL, "fc400000.dma"); | ||
527 | |||
528 | clk = clk_register_gate(NULL, "gmac_clk", "ahb_clk", 0, PERIP1_CLK_ENB, | ||
529 | GMAC_CLK_ENB, 0, &_lock); | ||
530 | clk_register_clkdev(clk, NULL, "e0800000.eth"); | ||
531 | |||
532 | clk = clk_register_gate(NULL, "i2c0_clk", "ahb_clk", 0, PERIP1_CLK_ENB, | ||
533 | I2C_CLK_ENB, 0, &_lock); | ||
534 | clk_register_clkdev(clk, NULL, "d0180000.i2c"); | ||
535 | |||
536 | clk = clk_register_gate(NULL, "jpeg_clk", "ahb_clk", 0, PERIP1_CLK_ENB, | ||
537 | JPEG_CLK_ENB, 0, &_lock); | ||
538 | clk_register_clkdev(clk, NULL, "jpeg"); | ||
539 | |||
540 | clk = clk_register_gate(NULL, "smi_clk", "ahb_clk", 0, PERIP1_CLK_ENB, | ||
541 | SMI_CLK_ENB, 0, &_lock); | ||
542 | clk_register_clkdev(clk, NULL, "fc000000.flash"); | ||
543 | |||
544 | /* clock derived from apb clk */ | ||
545 | clk = clk_register_gate(NULL, "adc_clk", "apb_clk", 0, PERIP1_CLK_ENB, | ||
546 | ADC_CLK_ENB, 0, &_lock); | ||
547 | clk_register_clkdev(clk, NULL, "adc"); | ||
548 | |||
549 | clk = clk_register_gate(NULL, "gpio0_clk", "apb_clk", 0, PERIP1_CLK_ENB, | ||
550 | GPIO_CLK_ENB, 0, &_lock); | ||
551 | clk_register_clkdev(clk, NULL, "fc980000.gpio"); | ||
552 | |||
553 | clk = clk_register_gate(NULL, "ssp0_clk", "apb_clk", 0, PERIP1_CLK_ENB, | ||
554 | SSP_CLK_ENB, 0, &_lock); | ||
555 | clk_register_clkdev(clk, NULL, "d0100000.spi"); | ||
556 | |||
557 | /* RAS clk enable */ | ||
558 | clk = clk_register_gate(NULL, "ras_ahb_clk", "ahb_clk", 0, RAS_CLK_ENB, | ||
559 | RAS_AHB_CLK_ENB, 0, &_lock); | ||
560 | clk_register_clkdev(clk, "ras_ahb_clk", NULL); | ||
561 | |||
562 | clk = clk_register_gate(NULL, "ras_apb_clk", "apb_clk", 0, RAS_CLK_ENB, | ||
563 | RAS_APB_CLK_ENB, 0, &_lock); | ||
564 | clk_register_clkdev(clk, "ras_apb_clk", NULL); | ||
565 | |||
566 | clk = clk_register_gate(NULL, "ras_32k_clk", "osc_32k_clk", 0, | ||
567 | RAS_CLK_ENB, RAS_32K_CLK_ENB, 0, &_lock); | ||
568 | clk_register_clkdev(clk, "ras_32k_clk", NULL); | ||
569 | |||
570 | clk = clk_register_gate(NULL, "ras_24m_clk", "osc_24m_clk", 0, | ||
571 | RAS_CLK_ENB, RAS_24M_CLK_ENB, 0, &_lock); | ||
572 | clk_register_clkdev(clk, "ras_24m_clk", NULL); | ||
573 | |||
574 | clk = clk_register_gate(NULL, "ras_pll1_clk", "pll1_clk", 0, | ||
575 | RAS_CLK_ENB, RAS_PLL1_CLK_ENB, 0, &_lock); | ||
576 | clk_register_clkdev(clk, "ras_pll1_clk", NULL); | ||
577 | |||
578 | clk = clk_register_gate(NULL, "ras_pll2_clk", "pll2_clk", 0, | ||
579 | RAS_CLK_ENB, RAS_PLL2_CLK_ENB, 0, &_lock); | ||
580 | clk_register_clkdev(clk, "ras_pll2_clk", NULL); | ||
581 | |||
582 | clk = clk_register_gate(NULL, "ras_pll3_48m_clk", "pll3_48m_clk", 0, | ||
583 | RAS_CLK_ENB, RAS_48M_CLK_ENB, 0, &_lock); | ||
584 | clk_register_clkdev(clk, "ras_pll3_48m_clk", NULL); | ||
585 | |||
586 | clk = clk_register_gate(NULL, "ras_gen0_synth_gate_clk", | ||
587 | "gen0_synth_gate_clk", 0, RAS_CLK_ENB, | ||
588 | RAS_SYNT0_CLK_ENB, 0, &_lock); | ||
589 | clk_register_clkdev(clk, "ras_gen0_synth_gate_clk", NULL); | ||
590 | |||
591 | clk = clk_register_gate(NULL, "ras_gen1_synth_gate_clk", | ||
592 | "gen1_synth_gate_clk", 0, RAS_CLK_ENB, | ||
593 | RAS_SYNT1_CLK_ENB, 0, &_lock); | ||
594 | clk_register_clkdev(clk, "ras_gen1_synth_gate_clk", NULL); | ||
595 | |||
596 | clk = clk_register_gate(NULL, "ras_gen2_synth_gate_clk", | ||
597 | "gen2_synth_gate_clk", 0, RAS_CLK_ENB, | ||
598 | RAS_SYNT2_CLK_ENB, 0, &_lock); | ||
599 | clk_register_clkdev(clk, "ras_gen2_synth_gate_clk", NULL); | ||
600 | |||
601 | clk = clk_register_gate(NULL, "ras_gen3_synth_gate_clk", | ||
602 | "gen3_synth_gate_clk", 0, RAS_CLK_ENB, | ||
603 | RAS_SYNT3_CLK_ENB, 0, &_lock); | ||
604 | clk_register_clkdev(clk, "ras_gen3_synth_gate_clk", NULL); | ||
605 | |||
606 | if (of_machine_is_compatible("st,spear300")) | ||
607 | spear300_clk_init(); | ||
608 | else if (of_machine_is_compatible("st,spear310")) | ||
609 | spear310_clk_init(); | ||
610 | else if (of_machine_is_compatible("st,spear320")) | ||
611 | spear320_clk_init(); | ||
612 | } | ||
diff --git a/drivers/clk/spear/spear6xx_clock.c b/drivers/clk/spear/spear6xx_clock.c new file mode 100644 index 000000000000..f9a20b382304 --- /dev/null +++ b/drivers/clk/spear/spear6xx_clock.c | |||
@@ -0,0 +1,342 @@ | |||
1 | /* | ||
2 | * SPEAr6xx machines clock framework source file | ||
3 | * | ||
4 | * Copyright (C) 2012 ST Microelectronics | ||
5 | * Viresh Kumar <viresh.kumar@st.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.h> | ||
13 | #include <linux/clkdev.h> | ||
14 | #include <linux/io.h> | ||
15 | #include <linux/spinlock_types.h> | ||
16 | #include <mach/misc_regs.h> | ||
17 | #include "clk.h" | ||
18 | |||
19 | static DEFINE_SPINLOCK(_lock); | ||
20 | |||
21 | #define PLL1_CTR (MISC_BASE + 0x008) | ||
22 | #define PLL1_FRQ (MISC_BASE + 0x00C) | ||
23 | #define PLL2_CTR (MISC_BASE + 0x014) | ||
24 | #define PLL2_FRQ (MISC_BASE + 0x018) | ||
25 | #define PLL_CLK_CFG (MISC_BASE + 0x020) | ||
26 | /* PLL_CLK_CFG register masks */ | ||
27 | #define MCTR_CLK_SHIFT 28 | ||
28 | #define MCTR_CLK_MASK 3 | ||
29 | |||
30 | #define CORE_CLK_CFG (MISC_BASE + 0x024) | ||
31 | /* CORE CLK CFG register masks */ | ||
32 | #define HCLK_RATIO_SHIFT 10 | ||
33 | #define HCLK_RATIO_MASK 2 | ||
34 | #define PCLK_RATIO_SHIFT 8 | ||
35 | #define PCLK_RATIO_MASK 2 | ||
36 | |||
37 | #define PERIP_CLK_CFG (MISC_BASE + 0x028) | ||
38 | /* PERIP_CLK_CFG register masks */ | ||
39 | #define CLCD_CLK_SHIFT 2 | ||
40 | #define CLCD_CLK_MASK 2 | ||
41 | #define UART_CLK_SHIFT 4 | ||
42 | #define UART_CLK_MASK 1 | ||
43 | #define FIRDA_CLK_SHIFT 5 | ||
44 | #define FIRDA_CLK_MASK 2 | ||
45 | #define GPT0_CLK_SHIFT 8 | ||
46 | #define GPT1_CLK_SHIFT 10 | ||
47 | #define GPT2_CLK_SHIFT 11 | ||
48 | #define GPT3_CLK_SHIFT 12 | ||
49 | #define GPT_CLK_MASK 1 | ||
50 | |||
51 | #define PERIP1_CLK_ENB (MISC_BASE + 0x02C) | ||
52 | /* PERIP1_CLK_ENB register masks */ | ||
53 | #define UART0_CLK_ENB 3 | ||
54 | #define UART1_CLK_ENB 4 | ||
55 | #define SSP0_CLK_ENB 5 | ||
56 | #define SSP1_CLK_ENB 6 | ||
57 | #define I2C_CLK_ENB 7 | ||
58 | #define JPEG_CLK_ENB 8 | ||
59 | #define FSMC_CLK_ENB 9 | ||
60 | #define FIRDA_CLK_ENB 10 | ||
61 | #define GPT2_CLK_ENB 11 | ||
62 | #define GPT3_CLK_ENB 12 | ||
63 | #define GPIO2_CLK_ENB 13 | ||
64 | #define SSP2_CLK_ENB 14 | ||
65 | #define ADC_CLK_ENB 15 | ||
66 | #define GPT1_CLK_ENB 11 | ||
67 | #define RTC_CLK_ENB 17 | ||
68 | #define GPIO1_CLK_ENB 18 | ||
69 | #define DMA_CLK_ENB 19 | ||
70 | #define SMI_CLK_ENB 21 | ||
71 | #define CLCD_CLK_ENB 22 | ||
72 | #define GMAC_CLK_ENB 23 | ||
73 | #define USBD_CLK_ENB 24 | ||
74 | #define USBH0_CLK_ENB 25 | ||
75 | #define USBH1_CLK_ENB 26 | ||
76 | |||
77 | #define PRSC0_CLK_CFG (MISC_BASE + 0x044) | ||
78 | #define PRSC1_CLK_CFG (MISC_BASE + 0x048) | ||
79 | #define PRSC2_CLK_CFG (MISC_BASE + 0x04C) | ||
80 | |||
81 | #define CLCD_CLK_SYNT (MISC_BASE + 0x05C) | ||
82 | #define FIRDA_CLK_SYNT (MISC_BASE + 0x060) | ||
83 | #define UART_CLK_SYNT (MISC_BASE + 0x064) | ||
84 | |||
85 | /* vco rate configuration table, in ascending order of rates */ | ||
86 | static struct pll_rate_tbl pll_rtbl[] = { | ||
87 | {.mode = 0, .m = 0x53, .n = 0x0F, .p = 0x1}, /* vco 332 & pll 166 MHz */ | ||
88 | {.mode = 0, .m = 0x85, .n = 0x0F, .p = 0x1}, /* vco 532 & pll 266 MHz */ | ||
89 | {.mode = 0, .m = 0xA6, .n = 0x0F, .p = 0x1}, /* vco 664 & pll 332 MHz */ | ||
90 | }; | ||
91 | |||
92 | /* aux rate configuration table, in ascending order of rates */ | ||
93 | static struct aux_rate_tbl aux_rtbl[] = { | ||
94 | /* For PLL1 = 332 MHz */ | ||
95 | {.xscale = 2, .yscale = 8, .eq = 0}, /* 41.5 MHz */ | ||
96 | {.xscale = 2, .yscale = 4, .eq = 0}, /* 83 MHz */ | ||
97 | {.xscale = 1, .yscale = 2, .eq = 1}, /* 166 MHz */ | ||
98 | }; | ||
99 | |||
100 | static const char *clcd_parents[] = { "pll3_48m_clk", "clcd_synth_gate_clk", }; | ||
101 | static const char *firda_parents[] = { "pll3_48m_clk", "firda_synth_gate_clk", | ||
102 | }; | ||
103 | static const char *uart_parents[] = { "pll3_48m_clk", "uart_synth_gate_clk", }; | ||
104 | static const char *gpt0_1_parents[] = { "pll3_48m_clk", "gpt0_1_synth_clk", }; | ||
105 | static const char *gpt2_parents[] = { "pll3_48m_clk", "gpt2_synth_clk", }; | ||
106 | static const char *gpt3_parents[] = { "pll3_48m_clk", "gpt3_synth_clk", }; | ||
107 | static const char *ddr_parents[] = { "ahb_clk", "ahbmult2_clk", "none", | ||
108 | "pll2_clk", }; | ||
109 | |||
110 | /* gpt rate configuration table, in ascending order of rates */ | ||
111 | static struct gpt_rate_tbl gpt_rtbl[] = { | ||
112 | /* For pll1 = 332 MHz */ | ||
113 | {.mscale = 4, .nscale = 0}, /* 41.5 MHz */ | ||
114 | {.mscale = 2, .nscale = 0}, /* 55.3 MHz */ | ||
115 | {.mscale = 1, .nscale = 0}, /* 83 MHz */ | ||
116 | }; | ||
117 | |||
118 | void __init spear6xx_clk_init(void) | ||
119 | { | ||
120 | struct clk *clk, *clk1; | ||
121 | |||
122 | clk = clk_register_fixed_rate(NULL, "apb_pclk", NULL, CLK_IS_ROOT, 0); | ||
123 | clk_register_clkdev(clk, "apb_pclk", NULL); | ||
124 | |||
125 | clk = clk_register_fixed_rate(NULL, "osc_32k_clk", NULL, CLK_IS_ROOT, | ||
126 | 32000); | ||
127 | clk_register_clkdev(clk, "osc_32k_clk", NULL); | ||
128 | |||
129 | clk = clk_register_fixed_rate(NULL, "osc_30m_clk", NULL, CLK_IS_ROOT, | ||
130 | 30000000); | ||
131 | clk_register_clkdev(clk, "osc_30m_clk", NULL); | ||
132 | |||
133 | /* clock derived from 32 KHz osc clk */ | ||
134 | clk = clk_register_gate(NULL, "rtc_spear", "osc_32k_clk", 0, | ||
135 | PERIP1_CLK_ENB, RTC_CLK_ENB, 0, &_lock); | ||
136 | clk_register_clkdev(clk, NULL, "rtc-spear"); | ||
137 | |||
138 | /* clock derived from 30 MHz osc clk */ | ||
139 | clk = clk_register_fixed_rate(NULL, "pll3_48m_clk", "osc_24m_clk", 0, | ||
140 | 48000000); | ||
141 | clk_register_clkdev(clk, "pll3_48m_clk", NULL); | ||
142 | |||
143 | clk = clk_register_vco_pll("vco1_clk", "pll1_clk", NULL, "osc_30m_clk", | ||
144 | 0, PLL1_CTR, PLL1_FRQ, pll_rtbl, ARRAY_SIZE(pll_rtbl), | ||
145 | &_lock, &clk1, NULL); | ||
146 | clk_register_clkdev(clk, "vco1_clk", NULL); | ||
147 | clk_register_clkdev(clk1, "pll1_clk", NULL); | ||
148 | |||
149 | clk = clk_register_vco_pll("vco2_clk", "pll2_clk", NULL, | ||
150 | "osc_30m_clk", 0, PLL2_CTR, PLL2_FRQ, pll_rtbl, | ||
151 | ARRAY_SIZE(pll_rtbl), &_lock, &clk1, NULL); | ||
152 | clk_register_clkdev(clk, "vco2_clk", NULL); | ||
153 | clk_register_clkdev(clk1, "pll2_clk", NULL); | ||
154 | |||
155 | clk = clk_register_fixed_factor(NULL, "wdt_clk", "osc_30m_clk", 0, 1, | ||
156 | 1); | ||
157 | clk_register_clkdev(clk, NULL, "wdt"); | ||
158 | |||
159 | /* clock derived from pll1 clk */ | ||
160 | clk = clk_register_fixed_factor(NULL, "cpu_clk", "pll1_clk", 0, 1, 1); | ||
161 | clk_register_clkdev(clk, "cpu_clk", NULL); | ||
162 | |||
163 | clk = clk_register_divider(NULL, "ahb_clk", "pll1_clk", | ||
164 | CLK_SET_RATE_PARENT, CORE_CLK_CFG, HCLK_RATIO_SHIFT, | ||
165 | HCLK_RATIO_MASK, 0, &_lock); | ||
166 | clk_register_clkdev(clk, "ahb_clk", NULL); | ||
167 | |||
168 | clk = clk_register_aux("uart_synth_clk", "uart_synth_gate_clk", | ||
169 | "pll1_clk", 0, UART_CLK_SYNT, NULL, aux_rtbl, | ||
170 | ARRAY_SIZE(aux_rtbl), &_lock, &clk1); | ||
171 | clk_register_clkdev(clk, "uart_synth_clk", NULL); | ||
172 | clk_register_clkdev(clk1, "uart_synth_gate_clk", NULL); | ||
173 | |||
174 | clk = clk_register_mux(NULL, "uart_mux_clk", uart_parents, | ||
175 | ARRAY_SIZE(uart_parents), 0, PERIP_CLK_CFG, | ||
176 | UART_CLK_SHIFT, UART_CLK_MASK, 0, &_lock); | ||
177 | clk_register_clkdev(clk, "uart_mux_clk", NULL); | ||
178 | |||
179 | clk = clk_register_gate(NULL, "uart0", "uart_mux_clk", 0, | ||
180 | PERIP1_CLK_ENB, UART0_CLK_ENB, 0, &_lock); | ||
181 | clk_register_clkdev(clk, NULL, "d0000000.serial"); | ||
182 | |||
183 | clk = clk_register_gate(NULL, "uart1", "uart_mux_clk", 0, | ||
184 | PERIP1_CLK_ENB, UART1_CLK_ENB, 0, &_lock); | ||
185 | clk_register_clkdev(clk, NULL, "d0080000.serial"); | ||
186 | |||
187 | clk = clk_register_aux("firda_synth_clk", "firda_synth_gate_clk", | ||
188 | "pll1_clk", 0, FIRDA_CLK_SYNT, NULL, aux_rtbl, | ||
189 | ARRAY_SIZE(aux_rtbl), &_lock, &clk1); | ||
190 | clk_register_clkdev(clk, "firda_synth_clk", NULL); | ||
191 | clk_register_clkdev(clk1, "firda_synth_gate_clk", NULL); | ||
192 | |||
193 | clk = clk_register_mux(NULL, "firda_mux_clk", firda_parents, | ||
194 | ARRAY_SIZE(firda_parents), 0, PERIP_CLK_CFG, | ||
195 | FIRDA_CLK_SHIFT, FIRDA_CLK_MASK, 0, &_lock); | ||
196 | clk_register_clkdev(clk, "firda_mux_clk", NULL); | ||
197 | |||
198 | clk = clk_register_gate(NULL, "firda_clk", "firda_mux_clk", 0, | ||
199 | PERIP1_CLK_ENB, FIRDA_CLK_ENB, 0, &_lock); | ||
200 | clk_register_clkdev(clk, NULL, "firda"); | ||
201 | |||
202 | clk = clk_register_aux("clcd_synth_clk", "clcd_synth_gate_clk", | ||
203 | "pll1_clk", 0, CLCD_CLK_SYNT, NULL, aux_rtbl, | ||
204 | ARRAY_SIZE(aux_rtbl), &_lock, &clk1); | ||
205 | clk_register_clkdev(clk, "clcd_synth_clk", NULL); | ||
206 | clk_register_clkdev(clk1, "clcd_synth_gate_clk", NULL); | ||
207 | |||
208 | clk = clk_register_mux(NULL, "clcd_mux_clk", clcd_parents, | ||
209 | ARRAY_SIZE(clcd_parents), 0, PERIP_CLK_CFG, | ||
210 | CLCD_CLK_SHIFT, CLCD_CLK_MASK, 0, &_lock); | ||
211 | clk_register_clkdev(clk, "clcd_mux_clk", NULL); | ||
212 | |||
213 | clk = clk_register_gate(NULL, "clcd_clk", "clcd_mux_clk", 0, | ||
214 | PERIP1_CLK_ENB, CLCD_CLK_ENB, 0, &_lock); | ||
215 | clk_register_clkdev(clk, NULL, "clcd"); | ||
216 | |||
217 | /* gpt clocks */ | ||
218 | clk = clk_register_gpt("gpt0_1_synth_clk", "pll1_clk", 0, PRSC0_CLK_CFG, | ||
219 | gpt_rtbl, ARRAY_SIZE(gpt_rtbl), &_lock); | ||
220 | clk_register_clkdev(clk, "gpt0_1_synth_clk", NULL); | ||
221 | |||
222 | clk = clk_register_mux(NULL, "gpt0_mux_clk", gpt0_1_parents, | ||
223 | ARRAY_SIZE(gpt0_1_parents), 0, PERIP_CLK_CFG, | ||
224 | GPT0_CLK_SHIFT, GPT_CLK_MASK, 0, &_lock); | ||
225 | clk_register_clkdev(clk, NULL, "gpt0"); | ||
226 | |||
227 | clk = clk_register_mux(NULL, "gpt1_mux_clk", gpt0_1_parents, | ||
228 | ARRAY_SIZE(gpt0_1_parents), 0, PERIP_CLK_CFG, | ||
229 | GPT1_CLK_SHIFT, GPT_CLK_MASK, 0, &_lock); | ||
230 | clk_register_clkdev(clk, "gpt1_mux_clk", NULL); | ||
231 | |||
232 | clk = clk_register_gate(NULL, "gpt1_clk", "gpt1_mux_clk", 0, | ||
233 | PERIP1_CLK_ENB, GPT1_CLK_ENB, 0, &_lock); | ||
234 | clk_register_clkdev(clk, NULL, "gpt1"); | ||
235 | |||
236 | clk = clk_register_gpt("gpt2_synth_clk", "pll1_clk", 0, PRSC1_CLK_CFG, | ||
237 | gpt_rtbl, ARRAY_SIZE(gpt_rtbl), &_lock); | ||
238 | clk_register_clkdev(clk, "gpt2_synth_clk", NULL); | ||
239 | |||
240 | clk = clk_register_mux(NULL, "gpt2_mux_clk", gpt2_parents, | ||
241 | ARRAY_SIZE(gpt2_parents), 0, PERIP_CLK_CFG, | ||
242 | GPT2_CLK_SHIFT, GPT_CLK_MASK, 0, &_lock); | ||
243 | clk_register_clkdev(clk, "gpt2_mux_clk", NULL); | ||
244 | |||
245 | clk = clk_register_gate(NULL, "gpt2_clk", "gpt2_mux_clk", 0, | ||
246 | PERIP1_CLK_ENB, GPT2_CLK_ENB, 0, &_lock); | ||
247 | clk_register_clkdev(clk, NULL, "gpt2"); | ||
248 | |||
249 | clk = clk_register_gpt("gpt3_synth_clk", "pll1_clk", 0, PRSC2_CLK_CFG, | ||
250 | gpt_rtbl, ARRAY_SIZE(gpt_rtbl), &_lock); | ||
251 | clk_register_clkdev(clk, "gpt3_synth_clk", NULL); | ||
252 | |||
253 | clk = clk_register_mux(NULL, "gpt3_mux_clk", gpt3_parents, | ||
254 | ARRAY_SIZE(gpt3_parents), 0, PERIP_CLK_CFG, | ||
255 | GPT3_CLK_SHIFT, GPT_CLK_MASK, 0, &_lock); | ||
256 | clk_register_clkdev(clk, "gpt3_mux_clk", NULL); | ||
257 | |||
258 | clk = clk_register_gate(NULL, "gpt3_clk", "gpt3_mux_clk", 0, | ||
259 | PERIP1_CLK_ENB, GPT3_CLK_ENB, 0, &_lock); | ||
260 | clk_register_clkdev(clk, NULL, "gpt3"); | ||
261 | |||
262 | /* clock derived from pll3 clk */ | ||
263 | clk = clk_register_gate(NULL, "usbh0_clk", "pll3_48m_clk", 0, | ||
264 | PERIP1_CLK_ENB, USBH0_CLK_ENB, 0, &_lock); | ||
265 | clk_register_clkdev(clk, NULL, "usbh.0_clk"); | ||
266 | |||
267 | clk = clk_register_gate(NULL, "usbh1_clk", "pll3_48m_clk", 0, | ||
268 | PERIP1_CLK_ENB, USBH1_CLK_ENB, 0, &_lock); | ||
269 | clk_register_clkdev(clk, NULL, "usbh.1_clk"); | ||
270 | |||
271 | clk = clk_register_gate(NULL, "usbd_clk", "pll3_48m_clk", 0, | ||
272 | PERIP1_CLK_ENB, USBD_CLK_ENB, 0, &_lock); | ||
273 | clk_register_clkdev(clk, NULL, "designware_udc"); | ||
274 | |||
275 | /* clock derived from ahb clk */ | ||
276 | clk = clk_register_fixed_factor(NULL, "ahbmult2_clk", "ahb_clk", 0, 2, | ||
277 | 1); | ||
278 | clk_register_clkdev(clk, "ahbmult2_clk", NULL); | ||
279 | |||
280 | clk = clk_register_mux(NULL, "ddr_clk", ddr_parents, | ||
281 | ARRAY_SIZE(ddr_parents), | ||
282 | 0, PLL_CLK_CFG, MCTR_CLK_SHIFT, MCTR_CLK_MASK, 0, | ||
283 | &_lock); | ||
284 | clk_register_clkdev(clk, "ddr_clk", NULL); | ||
285 | |||
286 | clk = clk_register_divider(NULL, "apb_clk", "ahb_clk", | ||
287 | CLK_SET_RATE_PARENT, CORE_CLK_CFG, PCLK_RATIO_SHIFT, | ||
288 | PCLK_RATIO_MASK, 0, &_lock); | ||
289 | clk_register_clkdev(clk, "apb_clk", NULL); | ||
290 | |||
291 | clk = clk_register_gate(NULL, "dma_clk", "ahb_clk", 0, PERIP1_CLK_ENB, | ||
292 | DMA_CLK_ENB, 0, &_lock); | ||
293 | clk_register_clkdev(clk, NULL, "fc400000.dma"); | ||
294 | |||
295 | clk = clk_register_gate(NULL, "fsmc_clk", "ahb_clk", 0, PERIP1_CLK_ENB, | ||
296 | FSMC_CLK_ENB, 0, &_lock); | ||
297 | clk_register_clkdev(clk, NULL, "d1800000.flash"); | ||
298 | |||
299 | clk = clk_register_gate(NULL, "gmac_clk", "ahb_clk", 0, PERIP1_CLK_ENB, | ||
300 | GMAC_CLK_ENB, 0, &_lock); | ||
301 | clk_register_clkdev(clk, NULL, "gmac"); | ||
302 | |||
303 | clk = clk_register_gate(NULL, "i2c_clk", "ahb_clk", 0, PERIP1_CLK_ENB, | ||
304 | I2C_CLK_ENB, 0, &_lock); | ||
305 | clk_register_clkdev(clk, NULL, "d0200000.i2c"); | ||
306 | |||
307 | clk = clk_register_gate(NULL, "jpeg_clk", "ahb_clk", 0, PERIP1_CLK_ENB, | ||
308 | JPEG_CLK_ENB, 0, &_lock); | ||
309 | clk_register_clkdev(clk, NULL, "jpeg"); | ||
310 | |||
311 | clk = clk_register_gate(NULL, "smi_clk", "ahb_clk", 0, PERIP1_CLK_ENB, | ||
312 | SMI_CLK_ENB, 0, &_lock); | ||
313 | clk_register_clkdev(clk, NULL, "fc000000.flash"); | ||
314 | |||
315 | /* clock derived from apb clk */ | ||
316 | clk = clk_register_gate(NULL, "adc_clk", "apb_clk", 0, PERIP1_CLK_ENB, | ||
317 | ADC_CLK_ENB, 0, &_lock); | ||
318 | clk_register_clkdev(clk, NULL, "adc"); | ||
319 | |||
320 | clk = clk_register_fixed_factor(NULL, "gpio0_clk", "apb_clk", 0, 1, 1); | ||
321 | clk_register_clkdev(clk, NULL, "f0100000.gpio"); | ||
322 | |||
323 | clk = clk_register_gate(NULL, "gpio1_clk", "apb_clk", 0, PERIP1_CLK_ENB, | ||
324 | GPIO1_CLK_ENB, 0, &_lock); | ||
325 | clk_register_clkdev(clk, NULL, "fc980000.gpio"); | ||
326 | |||
327 | clk = clk_register_gate(NULL, "gpio2_clk", "apb_clk", 0, PERIP1_CLK_ENB, | ||
328 | GPIO2_CLK_ENB, 0, &_lock); | ||
329 | clk_register_clkdev(clk, NULL, "d8100000.gpio"); | ||
330 | |||
331 | clk = clk_register_gate(NULL, "ssp0_clk", "apb_clk", 0, PERIP1_CLK_ENB, | ||
332 | SSP0_CLK_ENB, 0, &_lock); | ||
333 | clk_register_clkdev(clk, NULL, "ssp-pl022.0"); | ||
334 | |||
335 | clk = clk_register_gate(NULL, "ssp1_clk", "apb_clk", 0, PERIP1_CLK_ENB, | ||
336 | SSP1_CLK_ENB, 0, &_lock); | ||
337 | clk_register_clkdev(clk, NULL, "ssp-pl022.1"); | ||
338 | |||
339 | clk = clk_register_gate(NULL, "ssp2_clk", "apb_clk", 0, PERIP1_CLK_ENB, | ||
340 | SSP2_CLK_ENB, 0, &_lock); | ||
341 | clk_register_clkdev(clk, NULL, "ssp-pl022.2"); | ||
342 | } | ||
diff --git a/drivers/crypto/mv_cesa.c b/drivers/crypto/mv_cesa.c index e6ecc5f23943..1cc6b3f3e262 100644 --- a/drivers/crypto/mv_cesa.c +++ b/drivers/crypto/mv_cesa.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/scatterlist.h> | 16 | #include <linux/scatterlist.h> |
17 | #include <linux/slab.h> | 17 | #include <linux/slab.h> |
18 | #include <linux/module.h> | 18 | #include <linux/module.h> |
19 | #include <linux/clk.h> | ||
19 | #include <crypto/internal/hash.h> | 20 | #include <crypto/internal/hash.h> |
20 | #include <crypto/sha.h> | 21 | #include <crypto/sha.h> |
21 | 22 | ||
@@ -79,6 +80,7 @@ struct crypto_priv { | |||
79 | void __iomem *reg; | 80 | void __iomem *reg; |
80 | void __iomem *sram; | 81 | void __iomem *sram; |
81 | int irq; | 82 | int irq; |
83 | struct clk *clk; | ||
82 | struct task_struct *queue_th; | 84 | struct task_struct *queue_th; |
83 | 85 | ||
84 | /* the lock protects queue and eng_st */ | 86 | /* the lock protects queue and eng_st */ |
@@ -1053,6 +1055,12 @@ static int mv_probe(struct platform_device *pdev) | |||
1053 | if (ret) | 1055 | if (ret) |
1054 | goto err_thread; | 1056 | goto err_thread; |
1055 | 1057 | ||
1058 | /* Not all platforms can gate the clock, so it is not | ||
1059 | an error if the clock does not exists. */ | ||
1060 | cp->clk = clk_get(&pdev->dev, NULL); | ||
1061 | if (!IS_ERR(cp->clk)) | ||
1062 | clk_prepare_enable(cp->clk); | ||
1063 | |||
1056 | writel(SEC_INT_ACCEL0_DONE, cpg->reg + SEC_ACCEL_INT_MASK); | 1064 | writel(SEC_INT_ACCEL0_DONE, cpg->reg + SEC_ACCEL_INT_MASK); |
1057 | writel(SEC_CFG_STOP_DIG_ERR, cpg->reg + SEC_ACCEL_CFG); | 1065 | writel(SEC_CFG_STOP_DIG_ERR, cpg->reg + SEC_ACCEL_CFG); |
1058 | writel(SRAM_CONFIG, cpg->reg + SEC_ACCEL_DESC_P0); | 1066 | writel(SRAM_CONFIG, cpg->reg + SEC_ACCEL_DESC_P0); |
@@ -1118,6 +1126,12 @@ static int mv_remove(struct platform_device *pdev) | |||
1118 | memset(cp->sram, 0, cp->sram_size); | 1126 | memset(cp->sram, 0, cp->sram_size); |
1119 | iounmap(cp->sram); | 1127 | iounmap(cp->sram); |
1120 | iounmap(cp->reg); | 1128 | iounmap(cp->reg); |
1129 | |||
1130 | if (!IS_ERR(cp->clk)) { | ||
1131 | clk_disable_unprepare(cp->clk); | ||
1132 | clk_put(cp->clk); | ||
1133 | } | ||
1134 | |||
1121 | kfree(cp); | 1135 | kfree(cp); |
1122 | cpg = NULL; | 1136 | cpg = NULL; |
1123 | return 0; | 1137 | return 0; |
diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c index a472a29d8497..fb4f4990f5eb 100644 --- a/drivers/dma/imx-sdma.c +++ b/drivers/dma/imx-sdma.c | |||
@@ -323,7 +323,8 @@ struct sdma_engine { | |||
323 | struct sdma_context_data *context; | 323 | struct sdma_context_data *context; |
324 | dma_addr_t context_phys; | 324 | dma_addr_t context_phys; |
325 | struct dma_device dma_device; | 325 | struct dma_device dma_device; |
326 | struct clk *clk; | 326 | struct clk *clk_ipg; |
327 | struct clk *clk_ahb; | ||
327 | spinlock_t channel_0_lock; | 328 | spinlock_t channel_0_lock; |
328 | struct sdma_script_start_addrs *script_addrs; | 329 | struct sdma_script_start_addrs *script_addrs; |
329 | }; | 330 | }; |
@@ -867,7 +868,8 @@ static int sdma_alloc_chan_resources(struct dma_chan *chan) | |||
867 | sdmac->peripheral_type = data->peripheral_type; | 868 | sdmac->peripheral_type = data->peripheral_type; |
868 | sdmac->event_id0 = data->dma_request; | 869 | sdmac->event_id0 = data->dma_request; |
869 | 870 | ||
870 | clk_enable(sdmac->sdma->clk); | 871 | clk_enable(sdmac->sdma->clk_ipg); |
872 | clk_enable(sdmac->sdma->clk_ahb); | ||
871 | 873 | ||
872 | ret = sdma_request_channel(sdmac); | 874 | ret = sdma_request_channel(sdmac); |
873 | if (ret) | 875 | if (ret) |
@@ -904,7 +906,8 @@ static void sdma_free_chan_resources(struct dma_chan *chan) | |||
904 | 906 | ||
905 | dma_free_coherent(NULL, PAGE_SIZE, sdmac->bd, sdmac->bd_phys); | 907 | dma_free_coherent(NULL, PAGE_SIZE, sdmac->bd, sdmac->bd_phys); |
906 | 908 | ||
907 | clk_disable(sdma->clk); | 909 | clk_disable(sdma->clk_ipg); |
910 | clk_disable(sdma->clk_ahb); | ||
908 | } | 911 | } |
909 | 912 | ||
910 | static struct dma_async_tx_descriptor *sdma_prep_slave_sg( | 913 | static struct dma_async_tx_descriptor *sdma_prep_slave_sg( |
@@ -1177,12 +1180,14 @@ static void sdma_load_firmware(const struct firmware *fw, void *context) | |||
1177 | addr = (void *)header + header->script_addrs_start; | 1180 | addr = (void *)header + header->script_addrs_start; |
1178 | ram_code = (void *)header + header->ram_code_start; | 1181 | ram_code = (void *)header + header->ram_code_start; |
1179 | 1182 | ||
1180 | clk_enable(sdma->clk); | 1183 | clk_enable(sdma->clk_ipg); |
1184 | clk_enable(sdma->clk_ahb); | ||
1181 | /* download the RAM image for SDMA */ | 1185 | /* download the RAM image for SDMA */ |
1182 | sdma_load_script(sdma, ram_code, | 1186 | sdma_load_script(sdma, ram_code, |
1183 | header->ram_code_size, | 1187 | header->ram_code_size, |
1184 | addr->ram_code_start_addr); | 1188 | addr->ram_code_start_addr); |
1185 | clk_disable(sdma->clk); | 1189 | clk_disable(sdma->clk_ipg); |
1190 | clk_disable(sdma->clk_ahb); | ||
1186 | 1191 | ||
1187 | sdma_add_scripts(sdma, addr); | 1192 | sdma_add_scripts(sdma, addr); |
1188 | 1193 | ||
@@ -1224,7 +1229,8 @@ static int __init sdma_init(struct sdma_engine *sdma) | |||
1224 | return -ENODEV; | 1229 | return -ENODEV; |
1225 | } | 1230 | } |
1226 | 1231 | ||
1227 | clk_enable(sdma->clk); | 1232 | clk_enable(sdma->clk_ipg); |
1233 | clk_enable(sdma->clk_ahb); | ||
1228 | 1234 | ||
1229 | /* Be sure SDMA has not started yet */ | 1235 | /* Be sure SDMA has not started yet */ |
1230 | writel_relaxed(0, sdma->regs + SDMA_H_C0PTR); | 1236 | writel_relaxed(0, sdma->regs + SDMA_H_C0PTR); |
@@ -1277,12 +1283,14 @@ static int __init sdma_init(struct sdma_engine *sdma) | |||
1277 | /* Initializes channel's priorities */ | 1283 | /* Initializes channel's priorities */ |
1278 | sdma_set_channel_priority(&sdma->channel[0], 7); | 1284 | sdma_set_channel_priority(&sdma->channel[0], 7); |
1279 | 1285 | ||
1280 | clk_disable(sdma->clk); | 1286 | clk_disable(sdma->clk_ipg); |
1287 | clk_disable(sdma->clk_ahb); | ||
1281 | 1288 | ||
1282 | return 0; | 1289 | return 0; |
1283 | 1290 | ||
1284 | err_dma_alloc: | 1291 | err_dma_alloc: |
1285 | clk_disable(sdma->clk); | 1292 | clk_disable(sdma->clk_ipg); |
1293 | clk_disable(sdma->clk_ahb); | ||
1286 | dev_err(sdma->dev, "initialisation failed with %d\n", ret); | 1294 | dev_err(sdma->dev, "initialisation failed with %d\n", ret); |
1287 | return ret; | 1295 | return ret; |
1288 | } | 1296 | } |
@@ -1321,12 +1329,21 @@ static int __init sdma_probe(struct platform_device *pdev) | |||
1321 | goto err_request_region; | 1329 | goto err_request_region; |
1322 | } | 1330 | } |
1323 | 1331 | ||
1324 | sdma->clk = clk_get(&pdev->dev, NULL); | 1332 | sdma->clk_ipg = devm_clk_get(&pdev->dev, "ipg"); |
1325 | if (IS_ERR(sdma->clk)) { | 1333 | if (IS_ERR(sdma->clk_ipg)) { |
1326 | ret = PTR_ERR(sdma->clk); | 1334 | ret = PTR_ERR(sdma->clk_ipg); |
1327 | goto err_clk; | 1335 | goto err_clk; |
1328 | } | 1336 | } |
1329 | 1337 | ||
1338 | sdma->clk_ahb = devm_clk_get(&pdev->dev, "ahb"); | ||
1339 | if (IS_ERR(sdma->clk_ahb)) { | ||
1340 | ret = PTR_ERR(sdma->clk_ahb); | ||
1341 | goto err_clk; | ||
1342 | } | ||
1343 | |||
1344 | clk_prepare(sdma->clk_ipg); | ||
1345 | clk_prepare(sdma->clk_ahb); | ||
1346 | |||
1330 | sdma->regs = ioremap(iores->start, resource_size(iores)); | 1347 | sdma->regs = ioremap(iores->start, resource_size(iores)); |
1331 | if (!sdma->regs) { | 1348 | if (!sdma->regs) { |
1332 | ret = -ENOMEM; | 1349 | ret = -ENOMEM; |
@@ -1436,7 +1453,6 @@ err_alloc: | |||
1436 | err_request_irq: | 1453 | err_request_irq: |
1437 | iounmap(sdma->regs); | 1454 | iounmap(sdma->regs); |
1438 | err_ioremap: | 1455 | err_ioremap: |
1439 | clk_put(sdma->clk); | ||
1440 | err_clk: | 1456 | err_clk: |
1441 | release_mem_region(iores->start, resource_size(iores)); | 1457 | release_mem_region(iores->start, resource_size(iores)); |
1442 | err_request_region: | 1458 | err_request_region: |
diff --git a/drivers/dma/ipu/ipu_idmac.c b/drivers/dma/ipu/ipu_idmac.c index 62e3f8ec2461..5ec72044ea4c 100644 --- a/drivers/dma/ipu/ipu_idmac.c +++ b/drivers/dma/ipu/ipu_idmac.c | |||
@@ -1715,7 +1715,7 @@ static int __init ipu_probe(struct platform_device *pdev) | |||
1715 | } | 1715 | } |
1716 | 1716 | ||
1717 | /* Make sure IPU HSP clock is running */ | 1717 | /* Make sure IPU HSP clock is running */ |
1718 | clk_enable(ipu_data.ipu_clk); | 1718 | clk_prepare_enable(ipu_data.ipu_clk); |
1719 | 1719 | ||
1720 | /* Disable all interrupts */ | 1720 | /* Disable all interrupts */ |
1721 | idmac_write_ipureg(&ipu_data, 0, IPU_INT_CTRL_1); | 1721 | idmac_write_ipureg(&ipu_data, 0, IPU_INT_CTRL_1); |
@@ -1747,7 +1747,7 @@ static int __init ipu_probe(struct platform_device *pdev) | |||
1747 | err_idmac_init: | 1747 | err_idmac_init: |
1748 | err_attach_irq: | 1748 | err_attach_irq: |
1749 | ipu_irq_detach_irq(&ipu_data, pdev); | 1749 | ipu_irq_detach_irq(&ipu_data, pdev); |
1750 | clk_disable(ipu_data.ipu_clk); | 1750 | clk_disable_unprepare(ipu_data.ipu_clk); |
1751 | clk_put(ipu_data.ipu_clk); | 1751 | clk_put(ipu_data.ipu_clk); |
1752 | err_clk_get: | 1752 | err_clk_get: |
1753 | iounmap(ipu_data.reg_ic); | 1753 | iounmap(ipu_data.reg_ic); |
@@ -1765,7 +1765,7 @@ static int __exit ipu_remove(struct platform_device *pdev) | |||
1765 | 1765 | ||
1766 | ipu_idmac_exit(ipu); | 1766 | ipu_idmac_exit(ipu); |
1767 | ipu_irq_detach_irq(ipu, pdev); | 1767 | ipu_irq_detach_irq(ipu, pdev); |
1768 | clk_disable(ipu->ipu_clk); | 1768 | clk_disable_unprepare(ipu->ipu_clk); |
1769 | clk_put(ipu->ipu_clk); | 1769 | clk_put(ipu->ipu_clk); |
1770 | iounmap(ipu->reg_ic); | 1770 | iounmap(ipu->reg_ic); |
1771 | iounmap(ipu->reg_ipu); | 1771 | iounmap(ipu->reg_ipu); |
diff --git a/drivers/dma/mv_xor.c b/drivers/dma/mv_xor.c index fa5d55fea46c..0b12e68bf79c 100644 --- a/drivers/dma/mv_xor.c +++ b/drivers/dma/mv_xor.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include <linux/interrupt.h> | 25 | #include <linux/interrupt.h> |
26 | #include <linux/platform_device.h> | 26 | #include <linux/platform_device.h> |
27 | #include <linux/memory.h> | 27 | #include <linux/memory.h> |
28 | #include <linux/clk.h> | ||
28 | #include <plat/mv_xor.h> | 29 | #include <plat/mv_xor.h> |
29 | 30 | ||
30 | #include "dmaengine.h" | 31 | #include "dmaengine.h" |
@@ -1307,11 +1308,25 @@ static int mv_xor_shared_probe(struct platform_device *pdev) | |||
1307 | if (dram) | 1308 | if (dram) |
1308 | mv_xor_conf_mbus_windows(msp, dram); | 1309 | mv_xor_conf_mbus_windows(msp, dram); |
1309 | 1310 | ||
1311 | /* Not all platforms can gate the clock, so it is not | ||
1312 | * an error if the clock does not exists. | ||
1313 | */ | ||
1314 | msp->clk = clk_get(&pdev->dev, NULL); | ||
1315 | if (!IS_ERR(msp->clk)) | ||
1316 | clk_prepare_enable(msp->clk); | ||
1317 | |||
1310 | return 0; | 1318 | return 0; |
1311 | } | 1319 | } |
1312 | 1320 | ||
1313 | static int mv_xor_shared_remove(struct platform_device *pdev) | 1321 | static int mv_xor_shared_remove(struct platform_device *pdev) |
1314 | { | 1322 | { |
1323 | struct mv_xor_shared_private *msp = platform_get_drvdata(pdev); | ||
1324 | |||
1325 | if (!IS_ERR(msp->clk)) { | ||
1326 | clk_disable_unprepare(msp->clk); | ||
1327 | clk_put(msp->clk); | ||
1328 | } | ||
1329 | |||
1315 | return 0; | 1330 | return 0; |
1316 | } | 1331 | } |
1317 | 1332 | ||
diff --git a/drivers/dma/mv_xor.h b/drivers/dma/mv_xor.h index 654876b7ba1d..a5b422f5a8ab 100644 --- a/drivers/dma/mv_xor.h +++ b/drivers/dma/mv_xor.h | |||
@@ -55,6 +55,7 @@ | |||
55 | struct mv_xor_shared_private { | 55 | struct mv_xor_shared_private { |
56 | void __iomem *xor_base; | 56 | void __iomem *xor_base; |
57 | void __iomem *xor_high_base; | 57 | void __iomem *xor_high_base; |
58 | struct clk *clk; | ||
58 | }; | 59 | }; |
59 | 60 | ||
60 | 61 | ||
diff --git a/drivers/media/video/mx3_camera.c b/drivers/media/video/mx3_camera.c index 02d54a057b60..f13643d31353 100644 --- a/drivers/media/video/mx3_camera.c +++ b/drivers/media/video/mx3_camera.c | |||
@@ -511,7 +511,7 @@ static void mx3_camera_activate(struct mx3_camera_dev *mx3_cam, | |||
511 | /* ipu_csi_init_interface() */ | 511 | /* ipu_csi_init_interface() */ |
512 | csi_reg_write(mx3_cam, conf, CSI_SENS_CONF); | 512 | csi_reg_write(mx3_cam, conf, CSI_SENS_CONF); |
513 | 513 | ||
514 | clk_enable(mx3_cam->clk); | 514 | clk_prepare_enable(mx3_cam->clk); |
515 | rate = clk_round_rate(mx3_cam->clk, mx3_cam->mclk); | 515 | rate = clk_round_rate(mx3_cam->clk, mx3_cam->mclk); |
516 | dev_dbg(icd->parent, "Set SENS_CONF to %x, rate %ld\n", conf, rate); | 516 | dev_dbg(icd->parent, "Set SENS_CONF to %x, rate %ld\n", conf, rate); |
517 | if (rate) | 517 | if (rate) |
@@ -552,7 +552,7 @@ static void mx3_camera_remove_device(struct soc_camera_device *icd) | |||
552 | *ichan = NULL; | 552 | *ichan = NULL; |
553 | } | 553 | } |
554 | 554 | ||
555 | clk_disable(mx3_cam->clk); | 555 | clk_disable_unprepare(mx3_cam->clk); |
556 | 556 | ||
557 | mx3_cam->icd = NULL; | 557 | mx3_cam->icd = NULL; |
558 | 558 | ||
diff --git a/drivers/mmc/host/mvsdio.c b/drivers/mmc/host/mvsdio.c index eeb8cd125b0c..3b9136c1a475 100644 --- a/drivers/mmc/host/mvsdio.c +++ b/drivers/mmc/host/mvsdio.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <linux/dma-mapping.h> | 19 | #include <linux/dma-mapping.h> |
20 | #include <linux/scatterlist.h> | 20 | #include <linux/scatterlist.h> |
21 | #include <linux/irq.h> | 21 | #include <linux/irq.h> |
22 | #include <linux/clk.h> | ||
22 | #include <linux/gpio.h> | 23 | #include <linux/gpio.h> |
23 | #include <linux/mmc/host.h> | 24 | #include <linux/mmc/host.h> |
24 | 25 | ||
@@ -51,6 +52,7 @@ struct mvsd_host { | |||
51 | struct device *dev; | 52 | struct device *dev; |
52 | struct resource *res; | 53 | struct resource *res; |
53 | int irq; | 54 | int irq; |
55 | struct clk *clk; | ||
54 | int gpio_card_detect; | 56 | int gpio_card_detect; |
55 | int gpio_write_protect; | 57 | int gpio_write_protect; |
56 | }; | 58 | }; |
@@ -770,6 +772,13 @@ static int __init mvsd_probe(struct platform_device *pdev) | |||
770 | } else | 772 | } else |
771 | host->irq = irq; | 773 | host->irq = irq; |
772 | 774 | ||
775 | /* Not all platforms can gate the clock, so it is not | ||
776 | an error if the clock does not exists. */ | ||
777 | host->clk = clk_get(&pdev->dev, NULL); | ||
778 | if (!IS_ERR(host->clk)) { | ||
779 | clk_prepare_enable(host->clk); | ||
780 | } | ||
781 | |||
773 | if (mvsd_data->gpio_card_detect) { | 782 | if (mvsd_data->gpio_card_detect) { |
774 | ret = gpio_request(mvsd_data->gpio_card_detect, | 783 | ret = gpio_request(mvsd_data->gpio_card_detect, |
775 | DRIVER_NAME " cd"); | 784 | DRIVER_NAME " cd"); |
@@ -854,6 +863,11 @@ static int __exit mvsd_remove(struct platform_device *pdev) | |||
854 | mvsd_power_down(host); | 863 | mvsd_power_down(host); |
855 | iounmap(host->base); | 864 | iounmap(host->base); |
856 | release_resource(host->res); | 865 | release_resource(host->res); |
866 | |||
867 | if (!IS_ERR(host->clk)) { | ||
868 | clk_disable_unprepare(host->clk); | ||
869 | clk_put(host->clk); | ||
870 | } | ||
857 | mmc_free_host(mmc); | 871 | mmc_free_host(mmc); |
858 | } | 872 | } |
859 | platform_set_drvdata(pdev, NULL); | 873 | platform_set_drvdata(pdev, NULL); |
diff --git a/drivers/mmc/host/mxcmmc.c b/drivers/mmc/host/mxcmmc.c index b2058b432320..28ed52d58f7f 100644 --- a/drivers/mmc/host/mxcmmc.c +++ b/drivers/mmc/host/mxcmmc.c | |||
@@ -136,7 +136,8 @@ struct mxcmci_host { | |||
136 | u16 rev_no; | 136 | u16 rev_no; |
137 | unsigned int cmdat; | 137 | unsigned int cmdat; |
138 | 138 | ||
139 | struct clk *clk; | 139 | struct clk *clk_ipg; |
140 | struct clk *clk_per; | ||
140 | 141 | ||
141 | int clock; | 142 | int clock; |
142 | 143 | ||
@@ -672,7 +673,7 @@ static void mxcmci_set_clk_rate(struct mxcmci_host *host, unsigned int clk_ios) | |||
672 | { | 673 | { |
673 | unsigned int divider; | 674 | unsigned int divider; |
674 | int prescaler = 0; | 675 | int prescaler = 0; |
675 | unsigned int clk_in = clk_get_rate(host->clk); | 676 | unsigned int clk_in = clk_get_rate(host->clk_per); |
676 | 677 | ||
677 | while (prescaler <= 0x800) { | 678 | while (prescaler <= 0x800) { |
678 | for (divider = 1; divider <= 0xF; divider++) { | 679 | for (divider = 1; divider <= 0xF; divider++) { |
@@ -900,12 +901,20 @@ static int mxcmci_probe(struct platform_device *pdev) | |||
900 | host->res = r; | 901 | host->res = r; |
901 | host->irq = irq; | 902 | host->irq = irq; |
902 | 903 | ||
903 | host->clk = clk_get(&pdev->dev, NULL); | 904 | host->clk_ipg = devm_clk_get(&pdev->dev, "ipg"); |
904 | if (IS_ERR(host->clk)) { | 905 | if (IS_ERR(host->clk_ipg)) { |
905 | ret = PTR_ERR(host->clk); | 906 | ret = PTR_ERR(host->clk_ipg); |
906 | goto out_iounmap; | 907 | goto out_iounmap; |
907 | } | 908 | } |
908 | clk_enable(host->clk); | 909 | |
910 | host->clk_per = devm_clk_get(&pdev->dev, "per"); | ||
911 | if (IS_ERR(host->clk_per)) { | ||
912 | ret = PTR_ERR(host->clk_per); | ||
913 | goto out_iounmap; | ||
914 | } | ||
915 | |||
916 | clk_prepare_enable(host->clk_per); | ||
917 | clk_prepare_enable(host->clk_ipg); | ||
909 | 918 | ||
910 | mxcmci_softreset(host); | 919 | mxcmci_softreset(host); |
911 | 920 | ||
@@ -917,8 +926,8 @@ static int mxcmci_probe(struct platform_device *pdev) | |||
917 | goto out_clk_put; | 926 | goto out_clk_put; |
918 | } | 927 | } |
919 | 928 | ||
920 | mmc->f_min = clk_get_rate(host->clk) >> 16; | 929 | mmc->f_min = clk_get_rate(host->clk_per) >> 16; |
921 | mmc->f_max = clk_get_rate(host->clk) >> 1; | 930 | mmc->f_max = clk_get_rate(host->clk_per) >> 1; |
922 | 931 | ||
923 | /* recommended in data sheet */ | 932 | /* recommended in data sheet */ |
924 | writew(0x2db4, host->base + MMC_REG_READ_TO); | 933 | writew(0x2db4, host->base + MMC_REG_READ_TO); |
@@ -967,8 +976,8 @@ out_free_dma: | |||
967 | if (host->dma) | 976 | if (host->dma) |
968 | dma_release_channel(host->dma); | 977 | dma_release_channel(host->dma); |
969 | out_clk_put: | 978 | out_clk_put: |
970 | clk_disable(host->clk); | 979 | clk_disable_unprepare(host->clk_per); |
971 | clk_put(host->clk); | 980 | clk_disable_unprepare(host->clk_ipg); |
972 | out_iounmap: | 981 | out_iounmap: |
973 | iounmap(host->base); | 982 | iounmap(host->base); |
974 | out_free: | 983 | out_free: |
@@ -999,8 +1008,8 @@ static int mxcmci_remove(struct platform_device *pdev) | |||
999 | if (host->dma) | 1008 | if (host->dma) |
1000 | dma_release_channel(host->dma); | 1009 | dma_release_channel(host->dma); |
1001 | 1010 | ||
1002 | clk_disable(host->clk); | 1011 | clk_disable_unprepare(host->clk_per); |
1003 | clk_put(host->clk); | 1012 | clk_disable_unprepare(host->clk_ipg); |
1004 | 1013 | ||
1005 | release_mem_region(host->res->start, resource_size(host->res)); | 1014 | release_mem_region(host->res->start, resource_size(host->res)); |
1006 | 1015 | ||
@@ -1018,7 +1027,8 @@ static int mxcmci_suspend(struct device *dev) | |||
1018 | 1027 | ||
1019 | if (mmc) | 1028 | if (mmc) |
1020 | ret = mmc_suspend_host(mmc); | 1029 | ret = mmc_suspend_host(mmc); |
1021 | clk_disable(host->clk); | 1030 | clk_disable_unprepare(host->clk_per); |
1031 | clk_disable_unprepare(host->clk_ipg); | ||
1022 | 1032 | ||
1023 | return ret; | 1033 | return ret; |
1024 | } | 1034 | } |
@@ -1029,7 +1039,8 @@ static int mxcmci_resume(struct device *dev) | |||
1029 | struct mxcmci_host *host = mmc_priv(mmc); | 1039 | struct mxcmci_host *host = mmc_priv(mmc); |
1030 | int ret = 0; | 1040 | int ret = 0; |
1031 | 1041 | ||
1032 | clk_enable(host->clk); | 1042 | clk_prepare_enable(host->clk_per); |
1043 | clk_prepare_enable(host->clk_ipg); | ||
1033 | if (mmc) | 1044 | if (mmc) |
1034 | ret = mmc_resume_host(mmc); | 1045 | ret = mmc_resume_host(mmc); |
1035 | 1046 | ||
diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c index 365b16c230f8..ebbe984e5d00 100644 --- a/drivers/mmc/host/sdhci-esdhc-imx.c +++ b/drivers/mmc/host/sdhci-esdhc-imx.c | |||
@@ -71,6 +71,9 @@ struct pltfm_imx_data { | |||
71 | enum imx_esdhc_type devtype; | 71 | enum imx_esdhc_type devtype; |
72 | struct pinctrl *pinctrl; | 72 | struct pinctrl *pinctrl; |
73 | struct esdhc_platform_data boarddata; | 73 | struct esdhc_platform_data boarddata; |
74 | struct clk *clk_ipg; | ||
75 | struct clk *clk_ahb; | ||
76 | struct clk *clk_per; | ||
74 | }; | 77 | }; |
75 | 78 | ||
76 | static struct platform_device_id imx_esdhc_devtype[] = { | 79 | static struct platform_device_id imx_esdhc_devtype[] = { |
@@ -439,7 +442,6 @@ static int __devinit sdhci_esdhc_imx_probe(struct platform_device *pdev) | |||
439 | struct sdhci_pltfm_host *pltfm_host; | 442 | struct sdhci_pltfm_host *pltfm_host; |
440 | struct sdhci_host *host; | 443 | struct sdhci_host *host; |
441 | struct esdhc_platform_data *boarddata; | 444 | struct esdhc_platform_data *boarddata; |
442 | struct clk *clk; | ||
443 | int err; | 445 | int err; |
444 | struct pltfm_imx_data *imx_data; | 446 | struct pltfm_imx_data *imx_data; |
445 | 447 | ||
@@ -460,14 +462,29 @@ static int __devinit sdhci_esdhc_imx_probe(struct platform_device *pdev) | |||
460 | imx_data->devtype = pdev->id_entry->driver_data; | 462 | imx_data->devtype = pdev->id_entry->driver_data; |
461 | pltfm_host->priv = imx_data; | 463 | pltfm_host->priv = imx_data; |
462 | 464 | ||
463 | clk = clk_get(mmc_dev(host->mmc), NULL); | 465 | imx_data->clk_ipg = devm_clk_get(&pdev->dev, "ipg"); |
464 | if (IS_ERR(clk)) { | 466 | if (IS_ERR(imx_data->clk_ipg)) { |
465 | dev_err(mmc_dev(host->mmc), "clk err\n"); | 467 | err = PTR_ERR(imx_data->clk_ipg); |
466 | err = PTR_ERR(clk); | ||
467 | goto err_clk_get; | 468 | goto err_clk_get; |
468 | } | 469 | } |
469 | clk_prepare_enable(clk); | 470 | |
470 | pltfm_host->clk = clk; | 471 | imx_data->clk_ahb = devm_clk_get(&pdev->dev, "ahb"); |
472 | if (IS_ERR(imx_data->clk_ahb)) { | ||
473 | err = PTR_ERR(imx_data->clk_ahb); | ||
474 | goto err_clk_get; | ||
475 | } | ||
476 | |||
477 | imx_data->clk_per = devm_clk_get(&pdev->dev, "per"); | ||
478 | if (IS_ERR(imx_data->clk_per)) { | ||
479 | err = PTR_ERR(imx_data->clk_per); | ||
480 | goto err_clk_get; | ||
481 | } | ||
482 | |||
483 | pltfm_host->clk = imx_data->clk_per; | ||
484 | |||
485 | clk_prepare_enable(imx_data->clk_per); | ||
486 | clk_prepare_enable(imx_data->clk_ipg); | ||
487 | clk_prepare_enable(imx_data->clk_ahb); | ||
471 | 488 | ||
472 | imx_data->pinctrl = devm_pinctrl_get_select_default(&pdev->dev); | 489 | imx_data->pinctrl = devm_pinctrl_get_select_default(&pdev->dev); |
473 | if (IS_ERR(imx_data->pinctrl)) { | 490 | if (IS_ERR(imx_data->pinctrl)) { |
@@ -567,8 +584,9 @@ no_card_detect_irq: | |||
567 | no_card_detect_pin: | 584 | no_card_detect_pin: |
568 | no_board_data: | 585 | no_board_data: |
569 | pin_err: | 586 | pin_err: |
570 | clk_disable_unprepare(pltfm_host->clk); | 587 | clk_disable_unprepare(imx_data->clk_per); |
571 | clk_put(pltfm_host->clk); | 588 | clk_disable_unprepare(imx_data->clk_ipg); |
589 | clk_disable_unprepare(imx_data->clk_ahb); | ||
572 | err_clk_get: | 590 | err_clk_get: |
573 | kfree(imx_data); | 591 | kfree(imx_data); |
574 | err_imx_data: | 592 | err_imx_data: |
@@ -594,8 +612,10 @@ static int __devexit sdhci_esdhc_imx_remove(struct platform_device *pdev) | |||
594 | gpio_free(boarddata->cd_gpio); | 612 | gpio_free(boarddata->cd_gpio); |
595 | } | 613 | } |
596 | 614 | ||
597 | clk_disable_unprepare(pltfm_host->clk); | 615 | clk_disable_unprepare(imx_data->clk_per); |
598 | clk_put(pltfm_host->clk); | 616 | clk_disable_unprepare(imx_data->clk_ipg); |
617 | clk_disable_unprepare(imx_data->clk_ahb); | ||
618 | |||
599 | kfree(imx_data); | 619 | kfree(imx_data); |
600 | 620 | ||
601 | sdhci_pltfm_free(pdev); | 621 | sdhci_pltfm_free(pdev); |
diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c index cc0678a967c1..9e374e9bd296 100644 --- a/drivers/mtd/nand/mxc_nand.c +++ b/drivers/mtd/nand/mxc_nand.c | |||
@@ -690,7 +690,7 @@ static void mxc_nand_select_chip(struct mtd_info *mtd, int chip) | |||
690 | if (chip == -1) { | 690 | if (chip == -1) { |
691 | /* Disable the NFC clock */ | 691 | /* Disable the NFC clock */ |
692 | if (host->clk_act) { | 692 | if (host->clk_act) { |
693 | clk_disable(host->clk); | 693 | clk_disable_unprepare(host->clk); |
694 | host->clk_act = 0; | 694 | host->clk_act = 0; |
695 | } | 695 | } |
696 | return; | 696 | return; |
@@ -698,7 +698,7 @@ static void mxc_nand_select_chip(struct mtd_info *mtd, int chip) | |||
698 | 698 | ||
699 | if (!host->clk_act) { | 699 | if (!host->clk_act) { |
700 | /* Enable the NFC clock */ | 700 | /* Enable the NFC clock */ |
701 | clk_enable(host->clk); | 701 | clk_prepare_enable(host->clk); |
702 | host->clk_act = 1; | 702 | host->clk_act = 1; |
703 | } | 703 | } |
704 | 704 | ||
@@ -1078,7 +1078,7 @@ static int __init mxcnd_probe(struct platform_device *pdev) | |||
1078 | goto eclk; | 1078 | goto eclk; |
1079 | } | 1079 | } |
1080 | 1080 | ||
1081 | clk_enable(host->clk); | 1081 | clk_prepare_enable(host->clk); |
1082 | host->clk_act = 1; | 1082 | host->clk_act = 1; |
1083 | 1083 | ||
1084 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 1084 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
diff --git a/drivers/mtd/nand/orion_nand.c b/drivers/mtd/nand/orion_nand.c index 0f50ef38b87b..513dc88a05ca 100644 --- a/drivers/mtd/nand/orion_nand.c +++ b/drivers/mtd/nand/orion_nand.c | |||
@@ -17,6 +17,8 @@ | |||
17 | #include <linux/mtd/mtd.h> | 17 | #include <linux/mtd/mtd.h> |
18 | #include <linux/mtd/nand.h> | 18 | #include <linux/mtd/nand.h> |
19 | #include <linux/mtd/partitions.h> | 19 | #include <linux/mtd/partitions.h> |
20 | #include <linux/clk.h> | ||
21 | #include <linux/err.h> | ||
20 | #include <asm/io.h> | 22 | #include <asm/io.h> |
21 | #include <asm/sizes.h> | 23 | #include <asm/sizes.h> |
22 | #include <mach/hardware.h> | 24 | #include <mach/hardware.h> |
@@ -79,6 +81,7 @@ static int __init orion_nand_probe(struct platform_device *pdev) | |||
79 | struct nand_chip *nc; | 81 | struct nand_chip *nc; |
80 | struct orion_nand_data *board; | 82 | struct orion_nand_data *board; |
81 | struct resource *res; | 83 | struct resource *res; |
84 | struct clk *clk; | ||
82 | void __iomem *io_base; | 85 | void __iomem *io_base; |
83 | int ret = 0; | 86 | int ret = 0; |
84 | u32 val = 0; | 87 | u32 val = 0; |
@@ -155,6 +158,14 @@ static int __init orion_nand_probe(struct platform_device *pdev) | |||
155 | 158 | ||
156 | platform_set_drvdata(pdev, mtd); | 159 | platform_set_drvdata(pdev, mtd); |
157 | 160 | ||
161 | /* Not all platforms can gate the clock, so it is not | ||
162 | an error if the clock does not exists. */ | ||
163 | clk = clk_get(&pdev->dev, NULL); | ||
164 | if (!IS_ERR(clk)) { | ||
165 | clk_prepare_enable(clk); | ||
166 | clk_put(clk); | ||
167 | } | ||
168 | |||
158 | if (nand_scan(mtd, 1)) { | 169 | if (nand_scan(mtd, 1)) { |
159 | ret = -ENXIO; | 170 | ret = -ENXIO; |
160 | goto no_dev; | 171 | goto no_dev; |
@@ -184,6 +195,7 @@ static int __devexit orion_nand_remove(struct platform_device *pdev) | |||
184 | { | 195 | { |
185 | struct mtd_info *mtd = platform_get_drvdata(pdev); | 196 | struct mtd_info *mtd = platform_get_drvdata(pdev); |
186 | struct nand_chip *nc = mtd->priv; | 197 | struct nand_chip *nc = mtd->priv; |
198 | struct clk *clk; | ||
187 | 199 | ||
188 | nand_release(mtd); | 200 | nand_release(mtd); |
189 | 201 | ||
@@ -191,6 +203,12 @@ static int __devexit orion_nand_remove(struct platform_device *pdev) | |||
191 | 203 | ||
192 | kfree(nc); | 204 | kfree(nc); |
193 | 205 | ||
206 | clk = clk_get(&pdev->dev, NULL); | ||
207 | if (!IS_ERR(clk)) { | ||
208 | clk_disable_unprepare(clk); | ||
209 | clk_put(clk); | ||
210 | } | ||
211 | |||
194 | return 0; | 212 | return 0; |
195 | } | 213 | } |
196 | 214 | ||
diff --git a/drivers/net/ethernet/freescale/fec.c b/drivers/net/ethernet/freescale/fec.c index 8f2cf8c09e2d..ff7f4c5115a1 100644 --- a/drivers/net/ethernet/freescale/fec.c +++ b/drivers/net/ethernet/freescale/fec.c | |||
@@ -207,7 +207,8 @@ struct fec_enet_private { | |||
207 | 207 | ||
208 | struct net_device *netdev; | 208 | struct net_device *netdev; |
209 | 209 | ||
210 | struct clk *clk; | 210 | struct clk *clk_ipg; |
211 | struct clk *clk_ahb; | ||
211 | 212 | ||
212 | /* The saved address of a sent-in-place packet/buffer, for skfree(). */ | 213 | /* The saved address of a sent-in-place packet/buffer, for skfree(). */ |
213 | unsigned char *tx_bounce[TX_RING_SIZE]; | 214 | unsigned char *tx_bounce[TX_RING_SIZE]; |
@@ -1065,7 +1066,7 @@ static int fec_enet_mii_init(struct platform_device *pdev) | |||
1065 | * Reference Manual has an error on this, and gets fixed on i.MX6Q | 1066 | * Reference Manual has an error on this, and gets fixed on i.MX6Q |
1066 | * document. | 1067 | * document. |
1067 | */ | 1068 | */ |
1068 | fep->phy_speed = DIV_ROUND_UP(clk_get_rate(fep->clk), 5000000); | 1069 | fep->phy_speed = DIV_ROUND_UP(clk_get_rate(fep->clk_ahb), 5000000); |
1069 | if (id_entry->driver_data & FEC_QUIRK_ENET_MAC) | 1070 | if (id_entry->driver_data & FEC_QUIRK_ENET_MAC) |
1070 | fep->phy_speed--; | 1071 | fep->phy_speed--; |
1071 | fep->phy_speed <<= 1; | 1072 | fep->phy_speed <<= 1; |
@@ -1618,12 +1619,20 @@ fec_probe(struct platform_device *pdev) | |||
1618 | goto failed_pin; | 1619 | goto failed_pin; |
1619 | } | 1620 | } |
1620 | 1621 | ||
1621 | fep->clk = clk_get(&pdev->dev, NULL); | 1622 | fep->clk_ipg = devm_clk_get(&pdev->dev, "ipg"); |
1622 | if (IS_ERR(fep->clk)) { | 1623 | if (IS_ERR(fep->clk_ipg)) { |
1623 | ret = PTR_ERR(fep->clk); | 1624 | ret = PTR_ERR(fep->clk_ipg); |
1624 | goto failed_clk; | 1625 | goto failed_clk; |
1625 | } | 1626 | } |
1626 | clk_prepare_enable(fep->clk); | 1627 | |
1628 | fep->clk_ahb = devm_clk_get(&pdev->dev, "ahb"); | ||
1629 | if (IS_ERR(fep->clk_ahb)) { | ||
1630 | ret = PTR_ERR(fep->clk_ahb); | ||
1631 | goto failed_clk; | ||
1632 | } | ||
1633 | |||
1634 | clk_prepare_enable(fep->clk_ahb); | ||
1635 | clk_prepare_enable(fep->clk_ipg); | ||
1627 | 1636 | ||
1628 | ret = fec_enet_init(ndev); | 1637 | ret = fec_enet_init(ndev); |
1629 | if (ret) | 1638 | if (ret) |
@@ -1646,8 +1655,8 @@ failed_register: | |||
1646 | fec_enet_mii_remove(fep); | 1655 | fec_enet_mii_remove(fep); |
1647 | failed_mii_init: | 1656 | failed_mii_init: |
1648 | failed_init: | 1657 | failed_init: |
1649 | clk_disable_unprepare(fep->clk); | 1658 | clk_disable_unprepare(fep->clk_ahb); |
1650 | clk_put(fep->clk); | 1659 | clk_disable_unprepare(fep->clk_ipg); |
1651 | failed_pin: | 1660 | failed_pin: |
1652 | failed_clk: | 1661 | failed_clk: |
1653 | for (i = 0; i < FEC_IRQ_NUM; i++) { | 1662 | for (i = 0; i < FEC_IRQ_NUM; i++) { |
@@ -1680,8 +1689,8 @@ fec_drv_remove(struct platform_device *pdev) | |||
1680 | if (irq > 0) | 1689 | if (irq > 0) |
1681 | free_irq(irq, ndev); | 1690 | free_irq(irq, ndev); |
1682 | } | 1691 | } |
1683 | clk_disable_unprepare(fep->clk); | 1692 | clk_disable_unprepare(fep->clk_ahb); |
1684 | clk_put(fep->clk); | 1693 | clk_disable_unprepare(fep->clk_ipg); |
1685 | iounmap(fep->hwp); | 1694 | iounmap(fep->hwp); |
1686 | free_netdev(ndev); | 1695 | free_netdev(ndev); |
1687 | 1696 | ||
@@ -1705,7 +1714,8 @@ fec_suspend(struct device *dev) | |||
1705 | fec_stop(ndev); | 1714 | fec_stop(ndev); |
1706 | netif_device_detach(ndev); | 1715 | netif_device_detach(ndev); |
1707 | } | 1716 | } |
1708 | clk_disable_unprepare(fep->clk); | 1717 | clk_disable_unprepare(fep->clk_ahb); |
1718 | clk_disable_unprepare(fep->clk_ipg); | ||
1709 | 1719 | ||
1710 | return 0; | 1720 | return 0; |
1711 | } | 1721 | } |
@@ -1716,7 +1726,8 @@ fec_resume(struct device *dev) | |||
1716 | struct net_device *ndev = dev_get_drvdata(dev); | 1726 | struct net_device *ndev = dev_get_drvdata(dev); |
1717 | struct fec_enet_private *fep = netdev_priv(ndev); | 1727 | struct fec_enet_private *fep = netdev_priv(ndev); |
1718 | 1728 | ||
1719 | clk_prepare_enable(fep->clk); | 1729 | clk_prepare_enable(fep->clk_ahb); |
1730 | clk_prepare_enable(fep->clk_ipg); | ||
1720 | if (netif_running(ndev)) { | 1731 | if (netif_running(ndev)) { |
1721 | fec_restart(ndev, fep->full_duplex); | 1732 | fec_restart(ndev, fep->full_duplex); |
1722 | netif_device_attach(ndev); | 1733 | netif_device_attach(ndev); |
diff --git a/drivers/net/ethernet/marvell/mv643xx_eth.c b/drivers/net/ethernet/marvell/mv643xx_eth.c index c8950da60e6b..04d901d0ff63 100644 --- a/drivers/net/ethernet/marvell/mv643xx_eth.c +++ b/drivers/net/ethernet/marvell/mv643xx_eth.c | |||
@@ -57,6 +57,7 @@ | |||
57 | #include <linux/types.h> | 57 | #include <linux/types.h> |
58 | #include <linux/inet_lro.h> | 58 | #include <linux/inet_lro.h> |
59 | #include <linux/slab.h> | 59 | #include <linux/slab.h> |
60 | #include <linux/clk.h> | ||
60 | 61 | ||
61 | static char mv643xx_eth_driver_name[] = "mv643xx_eth"; | 62 | static char mv643xx_eth_driver_name[] = "mv643xx_eth"; |
62 | static char mv643xx_eth_driver_version[] = "1.4"; | 63 | static char mv643xx_eth_driver_version[] = "1.4"; |
@@ -289,10 +290,10 @@ struct mv643xx_eth_shared_private { | |||
289 | /* | 290 | /* |
290 | * Hardware-specific parameters. | 291 | * Hardware-specific parameters. |
291 | */ | 292 | */ |
292 | unsigned int t_clk; | ||
293 | int extended_rx_coal_limit; | 293 | int extended_rx_coal_limit; |
294 | int tx_bw_control; | 294 | int tx_bw_control; |
295 | int tx_csum_limit; | 295 | int tx_csum_limit; |
296 | |||
296 | }; | 297 | }; |
297 | 298 | ||
298 | #define TX_BW_CONTROL_ABSENT 0 | 299 | #define TX_BW_CONTROL_ABSENT 0 |
@@ -431,6 +432,12 @@ struct mv643xx_eth_private { | |||
431 | int tx_desc_sram_size; | 432 | int tx_desc_sram_size; |
432 | int txq_count; | 433 | int txq_count; |
433 | struct tx_queue txq[8]; | 434 | struct tx_queue txq[8]; |
435 | |||
436 | /* | ||
437 | * Hardware-specific parameters. | ||
438 | */ | ||
439 | struct clk *clk; | ||
440 | unsigned int t_clk; | ||
434 | }; | 441 | }; |
435 | 442 | ||
436 | 443 | ||
@@ -1010,7 +1017,7 @@ static void tx_set_rate(struct mv643xx_eth_private *mp, int rate, int burst) | |||
1010 | int mtu; | 1017 | int mtu; |
1011 | int bucket_size; | 1018 | int bucket_size; |
1012 | 1019 | ||
1013 | token_rate = ((rate / 1000) * 64) / (mp->shared->t_clk / 1000); | 1020 | token_rate = ((rate / 1000) * 64) / (mp->t_clk / 1000); |
1014 | if (token_rate > 1023) | 1021 | if (token_rate > 1023) |
1015 | token_rate = 1023; | 1022 | token_rate = 1023; |
1016 | 1023 | ||
@@ -1042,7 +1049,7 @@ static void txq_set_rate(struct tx_queue *txq, int rate, int burst) | |||
1042 | int token_rate; | 1049 | int token_rate; |
1043 | int bucket_size; | 1050 | int bucket_size; |
1044 | 1051 | ||
1045 | token_rate = ((rate / 1000) * 64) / (mp->shared->t_clk / 1000); | 1052 | token_rate = ((rate / 1000) * 64) / (mp->t_clk / 1000); |
1046 | if (token_rate > 1023) | 1053 | if (token_rate > 1023) |
1047 | token_rate = 1023; | 1054 | token_rate = 1023; |
1048 | 1055 | ||
@@ -1309,7 +1316,7 @@ static unsigned int get_rx_coal(struct mv643xx_eth_private *mp) | |||
1309 | temp = (val & 0x003fff00) >> 8; | 1316 | temp = (val & 0x003fff00) >> 8; |
1310 | 1317 | ||
1311 | temp *= 64000000; | 1318 | temp *= 64000000; |
1312 | do_div(temp, mp->shared->t_clk); | 1319 | do_div(temp, mp->t_clk); |
1313 | 1320 | ||
1314 | return (unsigned int)temp; | 1321 | return (unsigned int)temp; |
1315 | } | 1322 | } |
@@ -1319,7 +1326,7 @@ static void set_rx_coal(struct mv643xx_eth_private *mp, unsigned int usec) | |||
1319 | u64 temp; | 1326 | u64 temp; |
1320 | u32 val; | 1327 | u32 val; |
1321 | 1328 | ||
1322 | temp = (u64)usec * mp->shared->t_clk; | 1329 | temp = (u64)usec * mp->t_clk; |
1323 | temp += 31999999; | 1330 | temp += 31999999; |
1324 | do_div(temp, 64000000); | 1331 | do_div(temp, 64000000); |
1325 | 1332 | ||
@@ -1345,7 +1352,7 @@ static unsigned int get_tx_coal(struct mv643xx_eth_private *mp) | |||
1345 | 1352 | ||
1346 | temp = (rdlp(mp, TX_FIFO_URGENT_THRESHOLD) & 0x3fff0) >> 4; | 1353 | temp = (rdlp(mp, TX_FIFO_URGENT_THRESHOLD) & 0x3fff0) >> 4; |
1347 | temp *= 64000000; | 1354 | temp *= 64000000; |
1348 | do_div(temp, mp->shared->t_clk); | 1355 | do_div(temp, mp->t_clk); |
1349 | 1356 | ||
1350 | return (unsigned int)temp; | 1357 | return (unsigned int)temp; |
1351 | } | 1358 | } |
@@ -1354,7 +1361,7 @@ static void set_tx_coal(struct mv643xx_eth_private *mp, unsigned int usec) | |||
1354 | { | 1361 | { |
1355 | u64 temp; | 1362 | u64 temp; |
1356 | 1363 | ||
1357 | temp = (u64)usec * mp->shared->t_clk; | 1364 | temp = (u64)usec * mp->t_clk; |
1358 | temp += 31999999; | 1365 | temp += 31999999; |
1359 | do_div(temp, 64000000); | 1366 | do_div(temp, 64000000); |
1360 | 1367 | ||
@@ -2663,10 +2670,6 @@ static int mv643xx_eth_shared_probe(struct platform_device *pdev) | |||
2663 | if (dram) | 2670 | if (dram) |
2664 | mv643xx_eth_conf_mbus_windows(msp, dram); | 2671 | mv643xx_eth_conf_mbus_windows(msp, dram); |
2665 | 2672 | ||
2666 | /* | ||
2667 | * Detect hardware parameters. | ||
2668 | */ | ||
2669 | msp->t_clk = (pd != NULL && pd->t_clk != 0) ? pd->t_clk : 133000000; | ||
2670 | msp->tx_csum_limit = (pd != NULL && pd->tx_csum_limit) ? | 2673 | msp->tx_csum_limit = (pd != NULL && pd->tx_csum_limit) ? |
2671 | pd->tx_csum_limit : 9 * 1024; | 2674 | pd->tx_csum_limit : 9 * 1024; |
2672 | infer_hw_params(msp); | 2675 | infer_hw_params(msp); |
@@ -2891,6 +2894,18 @@ static int mv643xx_eth_probe(struct platform_device *pdev) | |||
2891 | 2894 | ||
2892 | mp->dev = dev; | 2895 | mp->dev = dev; |
2893 | 2896 | ||
2897 | /* | ||
2898 | * Get the clk rate, if there is one, otherwise use the default. | ||
2899 | */ | ||
2900 | mp->clk = clk_get(&pdev->dev, (pdev->id ? "1" : "0")); | ||
2901 | if (!IS_ERR(mp->clk)) { | ||
2902 | clk_prepare_enable(mp->clk); | ||
2903 | mp->t_clk = clk_get_rate(mp->clk); | ||
2904 | } else { | ||
2905 | mp->t_clk = 133000000; | ||
2906 | printk(KERN_WARNING "Unable to get clock"); | ||
2907 | } | ||
2908 | |||
2894 | set_params(mp, pd); | 2909 | set_params(mp, pd); |
2895 | netif_set_real_num_tx_queues(dev, mp->txq_count); | 2910 | netif_set_real_num_tx_queues(dev, mp->txq_count); |
2896 | netif_set_real_num_rx_queues(dev, mp->rxq_count); | 2911 | netif_set_real_num_rx_queues(dev, mp->rxq_count); |
@@ -2979,6 +2994,11 @@ static int mv643xx_eth_remove(struct platform_device *pdev) | |||
2979 | if (mp->phy != NULL) | 2994 | if (mp->phy != NULL) |
2980 | phy_detach(mp->phy); | 2995 | phy_detach(mp->phy); |
2981 | cancel_work_sync(&mp->tx_timeout_task); | 2996 | cancel_work_sync(&mp->tx_timeout_task); |
2997 | |||
2998 | if (!IS_ERR(mp->clk)) { | ||
2999 | clk_disable_unprepare(mp->clk); | ||
3000 | clk_put(mp->clk); | ||
3001 | } | ||
2982 | free_netdev(mp->dev); | 3002 | free_netdev(mp->dev); |
2983 | 3003 | ||
2984 | platform_set_drvdata(pdev, NULL); | 3004 | platform_set_drvdata(pdev, NULL); |
diff --git a/drivers/rtc/rtc-imxdi.c b/drivers/rtc/rtc-imxdi.c index d93a9608b1f0..891cd6c61d0a 100644 --- a/drivers/rtc/rtc-imxdi.c +++ b/drivers/rtc/rtc-imxdi.c | |||
@@ -405,7 +405,7 @@ static int dryice_rtc_probe(struct platform_device *pdev) | |||
405 | imxdi->clk = clk_get(&pdev->dev, NULL); | 405 | imxdi->clk = clk_get(&pdev->dev, NULL); |
406 | if (IS_ERR(imxdi->clk)) | 406 | if (IS_ERR(imxdi->clk)) |
407 | return PTR_ERR(imxdi->clk); | 407 | return PTR_ERR(imxdi->clk); |
408 | clk_enable(imxdi->clk); | 408 | clk_prepare_enable(imxdi->clk); |
409 | 409 | ||
410 | /* | 410 | /* |
411 | * Initialize dryice hardware | 411 | * Initialize dryice hardware |
@@ -470,7 +470,7 @@ static int dryice_rtc_probe(struct platform_device *pdev) | |||
470 | return 0; | 470 | return 0; |
471 | 471 | ||
472 | err: | 472 | err: |
473 | clk_disable(imxdi->clk); | 473 | clk_disable_unprepare(imxdi->clk); |
474 | clk_put(imxdi->clk); | 474 | clk_put(imxdi->clk); |
475 | 475 | ||
476 | return rc; | 476 | return rc; |
@@ -487,7 +487,7 @@ static int __devexit dryice_rtc_remove(struct platform_device *pdev) | |||
487 | 487 | ||
488 | rtc_device_unregister(imxdi->rtc); | 488 | rtc_device_unregister(imxdi->rtc); |
489 | 489 | ||
490 | clk_disable(imxdi->clk); | 490 | clk_disable_unprepare(imxdi->clk); |
491 | clk_put(imxdi->clk); | 491 | clk_put(imxdi->clk); |
492 | 492 | ||
493 | return 0; | 493 | return 0; |
diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c index 69c9a6601f45..47877d687614 100644 --- a/drivers/spi/spi-imx.c +++ b/drivers/spi/spi-imx.c | |||
@@ -86,7 +86,8 @@ struct spi_imx_data { | |||
86 | struct completion xfer_done; | 86 | struct completion xfer_done; |
87 | void __iomem *base; | 87 | void __iomem *base; |
88 | int irq; | 88 | int irq; |
89 | struct clk *clk; | 89 | struct clk *clk_per; |
90 | struct clk *clk_ipg; | ||
90 | unsigned long spi_clk; | 91 | unsigned long spi_clk; |
91 | 92 | ||
92 | unsigned int count; | 93 | unsigned int count; |
@@ -853,15 +854,22 @@ static int __devinit spi_imx_probe(struct platform_device *pdev) | |||
853 | goto out_free_irq; | 854 | goto out_free_irq; |
854 | } | 855 | } |
855 | 856 | ||
856 | spi_imx->clk = clk_get(&pdev->dev, NULL); | 857 | spi_imx->clk_ipg = devm_clk_get(&pdev->dev, "ipg"); |
857 | if (IS_ERR(spi_imx->clk)) { | 858 | if (IS_ERR(spi_imx->clk_ipg)) { |
858 | dev_err(&pdev->dev, "unable to get clock\n"); | 859 | ret = PTR_ERR(spi_imx->clk_ipg); |
859 | ret = PTR_ERR(spi_imx->clk); | ||
860 | goto out_free_irq; | 860 | goto out_free_irq; |
861 | } | 861 | } |
862 | 862 | ||
863 | clk_enable(spi_imx->clk); | 863 | spi_imx->clk_per = devm_clk_get(&pdev->dev, "per"); |
864 | spi_imx->spi_clk = clk_get_rate(spi_imx->clk); | 864 | if (IS_ERR(spi_imx->clk_per)) { |
865 | ret = PTR_ERR(spi_imx->clk_per); | ||
866 | goto out_free_irq; | ||
867 | } | ||
868 | |||
869 | clk_prepare_enable(spi_imx->clk_per); | ||
870 | clk_prepare_enable(spi_imx->clk_ipg); | ||
871 | |||
872 | spi_imx->spi_clk = clk_get_rate(spi_imx->clk_per); | ||
865 | 873 | ||
866 | spi_imx->devtype_data->reset(spi_imx); | 874 | spi_imx->devtype_data->reset(spi_imx); |
867 | 875 | ||
@@ -879,8 +887,8 @@ static int __devinit spi_imx_probe(struct platform_device *pdev) | |||
879 | return ret; | 887 | return ret; |
880 | 888 | ||
881 | out_clk_put: | 889 | out_clk_put: |
882 | clk_disable(spi_imx->clk); | 890 | clk_disable_unprepare(spi_imx->clk_per); |
883 | clk_put(spi_imx->clk); | 891 | clk_disable_unprepare(spi_imx->clk_ipg); |
884 | out_free_irq: | 892 | out_free_irq: |
885 | free_irq(spi_imx->irq, spi_imx); | 893 | free_irq(spi_imx->irq, spi_imx); |
886 | out_iounmap: | 894 | out_iounmap: |
@@ -908,8 +916,8 @@ static int __devexit spi_imx_remove(struct platform_device *pdev) | |||
908 | spi_bitbang_stop(&spi_imx->bitbang); | 916 | spi_bitbang_stop(&spi_imx->bitbang); |
909 | 917 | ||
910 | writel(0, spi_imx->base + MXC_CSPICTRL); | 918 | writel(0, spi_imx->base + MXC_CSPICTRL); |
911 | clk_disable(spi_imx->clk); | 919 | clk_disable_unprepare(spi_imx->clk_per); |
912 | clk_put(spi_imx->clk); | 920 | clk_disable_unprepare(spi_imx->clk_ipg); |
913 | free_irq(spi_imx->irq, spi_imx); | 921 | free_irq(spi_imx->irq, spi_imx); |
914 | iounmap(spi_imx->base); | 922 | iounmap(spi_imx->base); |
915 | 923 | ||
diff --git a/drivers/spi/spi-orion.c b/drivers/spi/spi-orion.c index e496f799b7a9..dfd04e91fa6d 100644 --- a/drivers/spi/spi-orion.c +++ b/drivers/spi/spi-orion.c | |||
@@ -16,8 +16,8 @@ | |||
16 | #include <linux/err.h> | 16 | #include <linux/err.h> |
17 | #include <linux/io.h> | 17 | #include <linux/io.h> |
18 | #include <linux/spi/spi.h> | 18 | #include <linux/spi/spi.h> |
19 | #include <linux/spi/orion_spi.h> | ||
20 | #include <linux/module.h> | 19 | #include <linux/module.h> |
20 | #include <linux/clk.h> | ||
21 | #include <asm/unaligned.h> | 21 | #include <asm/unaligned.h> |
22 | 22 | ||
23 | #define DRIVER_NAME "orion_spi" | 23 | #define DRIVER_NAME "orion_spi" |
@@ -46,6 +46,7 @@ struct orion_spi { | |||
46 | unsigned int max_speed; | 46 | unsigned int max_speed; |
47 | unsigned int min_speed; | 47 | unsigned int min_speed; |
48 | struct orion_spi_info *spi_info; | 48 | struct orion_spi_info *spi_info; |
49 | struct clk *clk; | ||
49 | }; | 50 | }; |
50 | 51 | ||
51 | static struct workqueue_struct *orion_spi_wq; | 52 | static struct workqueue_struct *orion_spi_wq; |
@@ -104,7 +105,7 @@ static int orion_spi_baudrate_set(struct spi_device *spi, unsigned int speed) | |||
104 | 105 | ||
105 | orion_spi = spi_master_get_devdata(spi->master); | 106 | orion_spi = spi_master_get_devdata(spi->master); |
106 | 107 | ||
107 | tclk_hz = orion_spi->spi_info->tclk; | 108 | tclk_hz = clk_get_rate(orion_spi->clk); |
108 | 109 | ||
109 | /* | 110 | /* |
110 | * the supported rates are: 4,6,8...30 | 111 | * the supported rates are: 4,6,8...30 |
@@ -450,6 +451,7 @@ static int __init orion_spi_probe(struct platform_device *pdev) | |||
450 | struct orion_spi *spi; | 451 | struct orion_spi *spi; |
451 | struct resource *r; | 452 | struct resource *r; |
452 | struct orion_spi_info *spi_info; | 453 | struct orion_spi_info *spi_info; |
454 | unsigned long tclk_hz; | ||
453 | int status = 0; | 455 | int status = 0; |
454 | 456 | ||
455 | spi_info = pdev->dev.platform_data; | 457 | spi_info = pdev->dev.platform_data; |
@@ -476,19 +478,28 @@ static int __init orion_spi_probe(struct platform_device *pdev) | |||
476 | spi->master = master; | 478 | spi->master = master; |
477 | spi->spi_info = spi_info; | 479 | spi->spi_info = spi_info; |
478 | 480 | ||
479 | spi->max_speed = DIV_ROUND_UP(spi_info->tclk, 4); | 481 | spi->clk = clk_get(&pdev->dev, NULL); |
480 | spi->min_speed = DIV_ROUND_UP(spi_info->tclk, 30); | 482 | if (IS_ERR(spi->clk)) { |
483 | status = PTR_ERR(spi->clk); | ||
484 | goto out; | ||
485 | } | ||
486 | |||
487 | clk_prepare(spi->clk); | ||
488 | clk_enable(spi->clk); | ||
489 | tclk_hz = clk_get_rate(spi->clk); | ||
490 | spi->max_speed = DIV_ROUND_UP(tclk_hz, 4); | ||
491 | spi->min_speed = DIV_ROUND_UP(tclk_hz, 30); | ||
481 | 492 | ||
482 | r = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 493 | r = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
483 | if (r == NULL) { | 494 | if (r == NULL) { |
484 | status = -ENODEV; | 495 | status = -ENODEV; |
485 | goto out; | 496 | goto out_rel_clk; |
486 | } | 497 | } |
487 | 498 | ||
488 | if (!request_mem_region(r->start, resource_size(r), | 499 | if (!request_mem_region(r->start, resource_size(r), |
489 | dev_name(&pdev->dev))) { | 500 | dev_name(&pdev->dev))) { |
490 | status = -EBUSY; | 501 | status = -EBUSY; |
491 | goto out; | 502 | goto out_rel_clk; |
492 | } | 503 | } |
493 | spi->base = ioremap(r->start, SZ_1K); | 504 | spi->base = ioremap(r->start, SZ_1K); |
494 | 505 | ||
@@ -508,7 +519,9 @@ static int __init orion_spi_probe(struct platform_device *pdev) | |||
508 | 519 | ||
509 | out_rel_mem: | 520 | out_rel_mem: |
510 | release_mem_region(r->start, resource_size(r)); | 521 | release_mem_region(r->start, resource_size(r)); |
511 | 522 | out_rel_clk: | |
523 | clk_disable_unprepare(spi->clk); | ||
524 | clk_put(spi->clk); | ||
512 | out: | 525 | out: |
513 | spi_master_put(master); | 526 | spi_master_put(master); |
514 | return status; | 527 | return status; |
@@ -526,6 +539,9 @@ static int __exit orion_spi_remove(struct platform_device *pdev) | |||
526 | 539 | ||
527 | cancel_work_sync(&spi->work); | 540 | cancel_work_sync(&spi->work); |
528 | 541 | ||
542 | clk_disable_unprepare(spi->clk); | ||
543 | clk_put(spi->clk); | ||
544 | |||
529 | r = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 545 | r = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
530 | release_mem_region(r->start, resource_size(r)); | 546 | release_mem_region(r->start, resource_size(r)); |
531 | 547 | ||
diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c index ec206732f68c..4ef747307ecb 100644 --- a/drivers/tty/serial/imx.c +++ b/drivers/tty/serial/imx.c | |||
@@ -205,7 +205,8 @@ struct imx_port { | |||
205 | unsigned int irda_inv_rx:1; | 205 | unsigned int irda_inv_rx:1; |
206 | unsigned int irda_inv_tx:1; | 206 | unsigned int irda_inv_tx:1; |
207 | unsigned short trcv_delay; /* transceiver delay */ | 207 | unsigned short trcv_delay; /* transceiver delay */ |
208 | struct clk *clk; | 208 | struct clk *clk_ipg; |
209 | struct clk *clk_per; | ||
209 | struct imx_uart_data *devdata; | 210 | struct imx_uart_data *devdata; |
210 | }; | 211 | }; |
211 | 212 | ||
@@ -673,7 +674,7 @@ static int imx_setup_ufcr(struct imx_port *sport, unsigned int mode) | |||
673 | * RFDIV is set such way to satisfy requested uartclk value | 674 | * RFDIV is set such way to satisfy requested uartclk value |
674 | */ | 675 | */ |
675 | val = TXTL << 10 | RXTL; | 676 | val = TXTL << 10 | RXTL; |
676 | ufcr_rfdiv = (clk_get_rate(sport->clk) + sport->port.uartclk / 2) | 677 | ufcr_rfdiv = (clk_get_rate(sport->clk_per) + sport->port.uartclk / 2) |
677 | / sport->port.uartclk; | 678 | / sport->port.uartclk; |
678 | 679 | ||
679 | if(!ufcr_rfdiv) | 680 | if(!ufcr_rfdiv) |
@@ -1286,7 +1287,7 @@ imx_console_get_options(struct imx_port *sport, int *baud, | |||
1286 | else | 1287 | else |
1287 | ucfr_rfdiv = 6 - ucfr_rfdiv; | 1288 | ucfr_rfdiv = 6 - ucfr_rfdiv; |
1288 | 1289 | ||
1289 | uartclk = clk_get_rate(sport->clk); | 1290 | uartclk = clk_get_rate(sport->clk_per); |
1290 | uartclk /= ucfr_rfdiv; | 1291 | uartclk /= ucfr_rfdiv; |
1291 | 1292 | ||
1292 | { /* | 1293 | { /* |
@@ -1511,14 +1512,22 @@ static int serial_imx_probe(struct platform_device *pdev) | |||
1511 | goto unmap; | 1512 | goto unmap; |
1512 | } | 1513 | } |
1513 | 1514 | ||
1514 | sport->clk = clk_get(&pdev->dev, "uart"); | 1515 | sport->clk_ipg = devm_clk_get(&pdev->dev, "ipg"); |
1515 | if (IS_ERR(sport->clk)) { | 1516 | if (IS_ERR(sport->clk_ipg)) { |
1516 | ret = PTR_ERR(sport->clk); | 1517 | ret = PTR_ERR(sport->clk_ipg); |
1517 | goto unmap; | 1518 | goto unmap; |
1518 | } | 1519 | } |
1519 | clk_prepare_enable(sport->clk); | ||
1520 | 1520 | ||
1521 | sport->port.uartclk = clk_get_rate(sport->clk); | 1521 | sport->clk_per = devm_clk_get(&pdev->dev, "per"); |
1522 | if (IS_ERR(sport->clk_per)) { | ||
1523 | ret = PTR_ERR(sport->clk_per); | ||
1524 | goto unmap; | ||
1525 | } | ||
1526 | |||
1527 | clk_prepare_enable(sport->clk_per); | ||
1528 | clk_prepare_enable(sport->clk_ipg); | ||
1529 | |||
1530 | sport->port.uartclk = clk_get_rate(sport->clk_per); | ||
1522 | 1531 | ||
1523 | imx_ports[sport->port.line] = sport; | 1532 | imx_ports[sport->port.line] = sport; |
1524 | 1533 | ||
@@ -1539,8 +1548,8 @@ deinit: | |||
1539 | if (pdata && pdata->exit) | 1548 | if (pdata && pdata->exit) |
1540 | pdata->exit(pdev); | 1549 | pdata->exit(pdev); |
1541 | clkput: | 1550 | clkput: |
1542 | clk_disable_unprepare(sport->clk); | 1551 | clk_disable_unprepare(sport->clk_per); |
1543 | clk_put(sport->clk); | 1552 | clk_disable_unprepare(sport->clk_ipg); |
1544 | unmap: | 1553 | unmap: |
1545 | iounmap(sport->port.membase); | 1554 | iounmap(sport->port.membase); |
1546 | free: | 1555 | free: |
@@ -1558,11 +1567,10 @@ static int serial_imx_remove(struct platform_device *pdev) | |||
1558 | 1567 | ||
1559 | platform_set_drvdata(pdev, NULL); | 1568 | platform_set_drvdata(pdev, NULL); |
1560 | 1569 | ||
1561 | if (sport) { | 1570 | uart_remove_one_port(&imx_reg, &sport->port); |
1562 | uart_remove_one_port(&imx_reg, &sport->port); | 1571 | |
1563 | clk_disable_unprepare(sport->clk); | 1572 | clk_disable_unprepare(sport->clk_per); |
1564 | clk_put(sport->clk); | 1573 | clk_disable_unprepare(sport->clk_ipg); |
1565 | } | ||
1566 | 1574 | ||
1567 | if (pdata && pdata->exit) | 1575 | if (pdata && pdata->exit) |
1568 | pdata->exit(pdev); | 1576 | pdata->exit(pdev); |
diff --git a/drivers/usb/host/ehci-mxc.c b/drivers/usb/host/ehci-mxc.c index a797d51ecbe8..c778ffe4e4e5 100644 --- a/drivers/usb/host/ehci-mxc.c +++ b/drivers/usb/host/ehci-mxc.c | |||
@@ -32,7 +32,7 @@ | |||
32 | #define ULPI_VIEWPORT_OFFSET 0x170 | 32 | #define ULPI_VIEWPORT_OFFSET 0x170 |
33 | 33 | ||
34 | struct ehci_mxc_priv { | 34 | struct ehci_mxc_priv { |
35 | struct clk *usbclk, *ahbclk, *phy1clk; | 35 | struct clk *usbclk, *ahbclk, *phyclk; |
36 | struct usb_hcd *hcd; | 36 | struct usb_hcd *hcd; |
37 | }; | 37 | }; |
38 | 38 | ||
@@ -166,31 +166,26 @@ static int ehci_mxc_drv_probe(struct platform_device *pdev) | |||
166 | } | 166 | } |
167 | 167 | ||
168 | /* enable clocks */ | 168 | /* enable clocks */ |
169 | priv->usbclk = clk_get(dev, "usb"); | 169 | priv->usbclk = clk_get(dev, "ipg"); |
170 | if (IS_ERR(priv->usbclk)) { | 170 | if (IS_ERR(priv->usbclk)) { |
171 | ret = PTR_ERR(priv->usbclk); | 171 | ret = PTR_ERR(priv->usbclk); |
172 | goto err_clk; | 172 | goto err_clk; |
173 | } | 173 | } |
174 | clk_enable(priv->usbclk); | 174 | clk_prepare_enable(priv->usbclk); |
175 | 175 | ||
176 | if (!cpu_is_mx35() && !cpu_is_mx25()) { | 176 | priv->ahbclk = clk_get(dev, "ahb"); |
177 | priv->ahbclk = clk_get(dev, "usb_ahb"); | 177 | if (IS_ERR(priv->ahbclk)) { |
178 | if (IS_ERR(priv->ahbclk)) { | 178 | ret = PTR_ERR(priv->ahbclk); |
179 | ret = PTR_ERR(priv->ahbclk); | 179 | goto err_clk_ahb; |
180 | goto err_clk_ahb; | ||
181 | } | ||
182 | clk_enable(priv->ahbclk); | ||
183 | } | 180 | } |
181 | clk_prepare_enable(priv->ahbclk); | ||
184 | 182 | ||
185 | /* "dr" device has its own clock on i.MX51 */ | 183 | /* "dr" device has its own clock on i.MX51 */ |
186 | if (cpu_is_mx51() && (pdev->id == 0)) { | 184 | priv->phyclk = clk_get(dev, "phy"); |
187 | priv->phy1clk = clk_get(dev, "usb_phy1"); | 185 | if (IS_ERR(priv->phyclk)) |
188 | if (IS_ERR(priv->phy1clk)) { | 186 | priv->phyclk = NULL; |
189 | ret = PTR_ERR(priv->phy1clk); | 187 | if (priv->phyclk) |
190 | goto err_clk_phy; | 188 | clk_prepare_enable(priv->phyclk); |
191 | } | ||
192 | clk_enable(priv->phy1clk); | ||
193 | } | ||
194 | 189 | ||
195 | 190 | ||
196 | /* call platform specific init function */ | 191 | /* call platform specific init function */ |
@@ -265,17 +260,15 @@ err_add: | |||
265 | if (pdata && pdata->exit) | 260 | if (pdata && pdata->exit) |
266 | pdata->exit(pdev); | 261 | pdata->exit(pdev); |
267 | err_init: | 262 | err_init: |
268 | if (priv->phy1clk) { | 263 | if (priv->phyclk) { |
269 | clk_disable(priv->phy1clk); | 264 | clk_disable_unprepare(priv->phyclk); |
270 | clk_put(priv->phy1clk); | 265 | clk_put(priv->phyclk); |
271 | } | ||
272 | err_clk_phy: | ||
273 | if (priv->ahbclk) { | ||
274 | clk_disable(priv->ahbclk); | ||
275 | clk_put(priv->ahbclk); | ||
276 | } | 266 | } |
267 | |||
268 | clk_disable_unprepare(priv->ahbclk); | ||
269 | clk_put(priv->ahbclk); | ||
277 | err_clk_ahb: | 270 | err_clk_ahb: |
278 | clk_disable(priv->usbclk); | 271 | clk_disable_unprepare(priv->usbclk); |
279 | clk_put(priv->usbclk); | 272 | clk_put(priv->usbclk); |
280 | err_clk: | 273 | err_clk: |
281 | iounmap(hcd->regs); | 274 | iounmap(hcd->regs); |
@@ -307,15 +300,14 @@ static int __exit ehci_mxc_drv_remove(struct platform_device *pdev) | |||
307 | usb_put_hcd(hcd); | 300 | usb_put_hcd(hcd); |
308 | platform_set_drvdata(pdev, NULL); | 301 | platform_set_drvdata(pdev, NULL); |
309 | 302 | ||
310 | clk_disable(priv->usbclk); | 303 | clk_disable_unprepare(priv->usbclk); |
311 | clk_put(priv->usbclk); | 304 | clk_put(priv->usbclk); |
312 | if (priv->ahbclk) { | 305 | clk_disable_unprepare(priv->ahbclk); |
313 | clk_disable(priv->ahbclk); | 306 | clk_put(priv->ahbclk); |
314 | clk_put(priv->ahbclk); | 307 | |
315 | } | 308 | if (priv->phyclk) { |
316 | if (priv->phy1clk) { | 309 | clk_disable_unprepare(priv->phyclk); |
317 | clk_disable(priv->phy1clk); | 310 | clk_put(priv->phyclk); |
318 | clk_put(priv->phy1clk); | ||
319 | } | 311 | } |
320 | 312 | ||
321 | kfree(priv); | 313 | kfree(priv); |
diff --git a/drivers/usb/host/ehci-orion.c b/drivers/usb/host/ehci-orion.c index 6c6a5a3b4ea7..82de1073aa52 100644 --- a/drivers/usb/host/ehci-orion.c +++ b/drivers/usb/host/ehci-orion.c | |||
@@ -12,6 +12,7 @@ | |||
12 | #include <linux/module.h> | 12 | #include <linux/module.h> |
13 | #include <linux/platform_device.h> | 13 | #include <linux/platform_device.h> |
14 | #include <linux/mbus.h> | 14 | #include <linux/mbus.h> |
15 | #include <linux/clk.h> | ||
15 | #include <plat/ehci-orion.h> | 16 | #include <plat/ehci-orion.h> |
16 | 17 | ||
17 | #define rdl(off) __raw_readl(hcd->regs + (off)) | 18 | #define rdl(off) __raw_readl(hcd->regs + (off)) |
@@ -198,6 +199,7 @@ static int __devinit ehci_orion_drv_probe(struct platform_device *pdev) | |||
198 | struct resource *res; | 199 | struct resource *res; |
199 | struct usb_hcd *hcd; | 200 | struct usb_hcd *hcd; |
200 | struct ehci_hcd *ehci; | 201 | struct ehci_hcd *ehci; |
202 | struct clk *clk; | ||
201 | void __iomem *regs; | 203 | void __iomem *regs; |
202 | int irq, err; | 204 | int irq, err; |
203 | 205 | ||
@@ -238,6 +240,14 @@ static int __devinit ehci_orion_drv_probe(struct platform_device *pdev) | |||
238 | goto err2; | 240 | goto err2; |
239 | } | 241 | } |
240 | 242 | ||
243 | /* Not all platforms can gate the clock, so it is not | ||
244 | an error if the clock does not exists. */ | ||
245 | clk = clk_get(&pdev->dev, NULL); | ||
246 | if (!IS_ERR(clk)) { | ||
247 | clk_prepare_enable(clk); | ||
248 | clk_put(clk); | ||
249 | } | ||
250 | |||
241 | hcd = usb_create_hcd(&ehci_orion_hc_driver, | 251 | hcd = usb_create_hcd(&ehci_orion_hc_driver, |
242 | &pdev->dev, dev_name(&pdev->dev)); | 252 | &pdev->dev, dev_name(&pdev->dev)); |
243 | if (!hcd) { | 253 | if (!hcd) { |
@@ -301,12 +311,18 @@ err1: | |||
301 | static int __exit ehci_orion_drv_remove(struct platform_device *pdev) | 311 | static int __exit ehci_orion_drv_remove(struct platform_device *pdev) |
302 | { | 312 | { |
303 | struct usb_hcd *hcd = platform_get_drvdata(pdev); | 313 | struct usb_hcd *hcd = platform_get_drvdata(pdev); |
314 | struct clk *clk; | ||
304 | 315 | ||
305 | usb_remove_hcd(hcd); | 316 | usb_remove_hcd(hcd); |
306 | iounmap(hcd->regs); | 317 | iounmap(hcd->regs); |
307 | release_mem_region(hcd->rsrc_start, hcd->rsrc_len); | 318 | release_mem_region(hcd->rsrc_start, hcd->rsrc_len); |
308 | usb_put_hcd(hcd); | 319 | usb_put_hcd(hcd); |
309 | 320 | ||
321 | clk = clk_get(&pdev->dev, NULL); | ||
322 | if (!IS_ERR(clk)) { | ||
323 | clk_disable_unprepare(clk); | ||
324 | clk_put(clk); | ||
325 | } | ||
310 | return 0; | 326 | return 0; |
311 | } | 327 | } |
312 | 328 | ||
diff --git a/drivers/video/imxfb.c b/drivers/video/imxfb.c index f135dbead07d..caad3689b4e6 100644 --- a/drivers/video/imxfb.c +++ b/drivers/video/imxfb.c | |||
@@ -131,7 +131,9 @@ struct imxfb_rgb { | |||
131 | struct imxfb_info { | 131 | struct imxfb_info { |
132 | struct platform_device *pdev; | 132 | struct platform_device *pdev; |
133 | void __iomem *regs; | 133 | void __iomem *regs; |
134 | struct clk *clk; | 134 | struct clk *clk_ipg; |
135 | struct clk *clk_ahb; | ||
136 | struct clk *clk_per; | ||
135 | 137 | ||
136 | /* | 138 | /* |
137 | * These are the addresses we mapped | 139 | * These are the addresses we mapped |
@@ -340,7 +342,7 @@ static int imxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) | |||
340 | 342 | ||
341 | pr_debug("var->bits_per_pixel=%d\n", var->bits_per_pixel); | 343 | pr_debug("var->bits_per_pixel=%d\n", var->bits_per_pixel); |
342 | 344 | ||
343 | lcd_clk = clk_get_rate(fbi->clk); | 345 | lcd_clk = clk_get_rate(fbi->clk_per); |
344 | 346 | ||
345 | tmp = var->pixclock * (unsigned long long)lcd_clk; | 347 | tmp = var->pixclock * (unsigned long long)lcd_clk; |
346 | 348 | ||
@@ -455,11 +457,17 @@ static int imxfb_bl_update_status(struct backlight_device *bl) | |||
455 | 457 | ||
456 | fbi->pwmr = (fbi->pwmr & ~0xFF) | brightness; | 458 | fbi->pwmr = (fbi->pwmr & ~0xFF) | brightness; |
457 | 459 | ||
458 | if (bl->props.fb_blank != FB_BLANK_UNBLANK) | 460 | if (bl->props.fb_blank != FB_BLANK_UNBLANK) { |
459 | clk_enable(fbi->clk); | 461 | clk_prepare_enable(fbi->clk_ipg); |
462 | clk_prepare_enable(fbi->clk_ahb); | ||
463 | clk_prepare_enable(fbi->clk_per); | ||
464 | } | ||
460 | writel(fbi->pwmr, fbi->regs + LCDC_PWMR); | 465 | writel(fbi->pwmr, fbi->regs + LCDC_PWMR); |
461 | if (bl->props.fb_blank != FB_BLANK_UNBLANK) | 466 | if (bl->props.fb_blank != FB_BLANK_UNBLANK) { |
462 | clk_disable(fbi->clk); | 467 | clk_disable_unprepare(fbi->clk_per); |
468 | clk_disable_unprepare(fbi->clk_ahb); | ||
469 | clk_disable_unprepare(fbi->clk_ipg); | ||
470 | } | ||
463 | 471 | ||
464 | return 0; | 472 | return 0; |
465 | } | 473 | } |
@@ -522,7 +530,9 @@ static void imxfb_enable_controller(struct imxfb_info *fbi) | |||
522 | */ | 530 | */ |
523 | writel(RMCR_LCDC_EN_MX1, fbi->regs + LCDC_RMCR); | 531 | writel(RMCR_LCDC_EN_MX1, fbi->regs + LCDC_RMCR); |
524 | 532 | ||
525 | clk_enable(fbi->clk); | 533 | clk_prepare_enable(fbi->clk_ipg); |
534 | clk_prepare_enable(fbi->clk_ahb); | ||
535 | clk_prepare_enable(fbi->clk_per); | ||
526 | 536 | ||
527 | if (fbi->backlight_power) | 537 | if (fbi->backlight_power) |
528 | fbi->backlight_power(1); | 538 | fbi->backlight_power(1); |
@@ -539,7 +549,9 @@ static void imxfb_disable_controller(struct imxfb_info *fbi) | |||
539 | if (fbi->lcd_power) | 549 | if (fbi->lcd_power) |
540 | fbi->lcd_power(0); | 550 | fbi->lcd_power(0); |
541 | 551 | ||
542 | clk_disable(fbi->clk); | 552 | clk_disable_unprepare(fbi->clk_per); |
553 | clk_disable_unprepare(fbi->clk_ipg); | ||
554 | clk_disable_unprepare(fbi->clk_ahb); | ||
543 | 555 | ||
544 | writel(0, fbi->regs + LCDC_RMCR); | 556 | writel(0, fbi->regs + LCDC_RMCR); |
545 | } | 557 | } |
@@ -770,10 +782,21 @@ static int __init imxfb_probe(struct platform_device *pdev) | |||
770 | goto failed_req; | 782 | goto failed_req; |
771 | } | 783 | } |
772 | 784 | ||
773 | fbi->clk = clk_get(&pdev->dev, NULL); | 785 | fbi->clk_ipg = devm_clk_get(&pdev->dev, "ipg"); |
774 | if (IS_ERR(fbi->clk)) { | 786 | if (IS_ERR(fbi->clk_ipg)) { |
775 | ret = PTR_ERR(fbi->clk); | 787 | ret = PTR_ERR(fbi->clk_ipg); |
776 | dev_err(&pdev->dev, "unable to get clock: %d\n", ret); | 788 | goto failed_getclock; |
789 | } | ||
790 | |||
791 | fbi->clk_ahb = devm_clk_get(&pdev->dev, "ahb"); | ||
792 | if (IS_ERR(fbi->clk_ahb)) { | ||
793 | ret = PTR_ERR(fbi->clk_ahb); | ||
794 | goto failed_getclock; | ||
795 | } | ||
796 | |||
797 | fbi->clk_per = devm_clk_get(&pdev->dev, "per"); | ||
798 | if (IS_ERR(fbi->clk_per)) { | ||
799 | ret = PTR_ERR(fbi->clk_per); | ||
777 | goto failed_getclock; | 800 | goto failed_getclock; |
778 | } | 801 | } |
779 | 802 | ||
@@ -858,7 +881,6 @@ failed_platform_init: | |||
858 | failed_map: | 881 | failed_map: |
859 | iounmap(fbi->regs); | 882 | iounmap(fbi->regs); |
860 | failed_ioremap: | 883 | failed_ioremap: |
861 | clk_put(fbi->clk); | ||
862 | failed_getclock: | 884 | failed_getclock: |
863 | release_mem_region(res->start, resource_size(res)); | 885 | release_mem_region(res->start, resource_size(res)); |
864 | failed_req: | 886 | failed_req: |
@@ -895,8 +917,6 @@ static int __devexit imxfb_remove(struct platform_device *pdev) | |||
895 | 917 | ||
896 | iounmap(fbi->regs); | 918 | iounmap(fbi->regs); |
897 | release_mem_region(res->start, resource_size(res)); | 919 | release_mem_region(res->start, resource_size(res)); |
898 | clk_disable(fbi->clk); | ||
899 | clk_put(fbi->clk); | ||
900 | 920 | ||
901 | platform_set_drvdata(pdev, NULL); | 921 | platform_set_drvdata(pdev, NULL); |
902 | 922 | ||
diff --git a/drivers/w1/masters/mxc_w1.c b/drivers/w1/masters/mxc_w1.c index a3b6a74c67a7..1cc61a700fa8 100644 --- a/drivers/w1/masters/mxc_w1.c +++ b/drivers/w1/masters/mxc_w1.c | |||
@@ -138,7 +138,7 @@ static int __devinit mxc_w1_probe(struct platform_device *pdev) | |||
138 | goto failed_ioremap; | 138 | goto failed_ioremap; |
139 | } | 139 | } |
140 | 140 | ||
141 | clk_enable(mdev->clk); | 141 | clk_prepare_enable(mdev->clk); |
142 | __raw_writeb(mdev->clkdiv, mdev->regs + MXC_W1_TIME_DIVIDER); | 142 | __raw_writeb(mdev->clkdiv, mdev->regs + MXC_W1_TIME_DIVIDER); |
143 | 143 | ||
144 | mdev->bus_master.data = mdev; | 144 | mdev->bus_master.data = mdev; |
@@ -178,7 +178,7 @@ static int __devexit mxc_w1_remove(struct platform_device *pdev) | |||
178 | 178 | ||
179 | iounmap(mdev->regs); | 179 | iounmap(mdev->regs); |
180 | release_mem_region(res->start, resource_size(res)); | 180 | release_mem_region(res->start, resource_size(res)); |
181 | clk_disable(mdev->clk); | 181 | clk_disable_unprepare(mdev->clk); |
182 | clk_put(mdev->clk); | 182 | clk_put(mdev->clk); |
183 | 183 | ||
184 | platform_set_drvdata(pdev, NULL); | 184 | platform_set_drvdata(pdev, NULL); |
diff --git a/drivers/watchdog/imx2_wdt.c b/drivers/watchdog/imx2_wdt.c index 7a2b734fcdc7..bcfab2b00ad2 100644 --- a/drivers/watchdog/imx2_wdt.c +++ b/drivers/watchdog/imx2_wdt.c | |||
@@ -121,7 +121,7 @@ static void imx2_wdt_start(void) | |||
121 | { | 121 | { |
122 | if (!test_and_set_bit(IMX2_WDT_STATUS_STARTED, &imx2_wdt.status)) { | 122 | if (!test_and_set_bit(IMX2_WDT_STATUS_STARTED, &imx2_wdt.status)) { |
123 | /* at our first start we enable clock and do initialisations */ | 123 | /* at our first start we enable clock and do initialisations */ |
124 | clk_enable(imx2_wdt.clk); | 124 | clk_prepare_enable(imx2_wdt.clk); |
125 | 125 | ||
126 | imx2_wdt_setup(); | 126 | imx2_wdt_setup(); |
127 | } else /* delete the timer that pings the watchdog after close */ | 127 | } else /* delete the timer that pings the watchdog after close */ |
diff --git a/drivers/watchdog/orion_wdt.c b/drivers/watchdog/orion_wdt.c index 788aa158e78c..0f5736949c61 100644 --- a/drivers/watchdog/orion_wdt.c +++ b/drivers/watchdog/orion_wdt.c | |||
@@ -24,8 +24,8 @@ | |||
24 | #include <linux/uaccess.h> | 24 | #include <linux/uaccess.h> |
25 | #include <linux/io.h> | 25 | #include <linux/io.h> |
26 | #include <linux/spinlock.h> | 26 | #include <linux/spinlock.h> |
27 | #include <linux/clk.h> | ||
27 | #include <mach/bridge-regs.h> | 28 | #include <mach/bridge-regs.h> |
28 | #include <plat/orion_wdt.h> | ||
29 | 29 | ||
30 | /* | 30 | /* |
31 | * Watchdog timer block registers. | 31 | * Watchdog timer block registers. |
@@ -41,6 +41,7 @@ | |||
41 | static bool nowayout = WATCHDOG_NOWAYOUT; | 41 | static bool nowayout = WATCHDOG_NOWAYOUT; |
42 | static int heartbeat = -1; /* module parameter (seconds) */ | 42 | static int heartbeat = -1; /* module parameter (seconds) */ |
43 | static unsigned int wdt_max_duration; /* (seconds) */ | 43 | static unsigned int wdt_max_duration; /* (seconds) */ |
44 | static struct clk *clk; | ||
44 | static unsigned int wdt_tclk; | 45 | static unsigned int wdt_tclk; |
45 | static void __iomem *wdt_reg; | 46 | static void __iomem *wdt_reg; |
46 | static unsigned long wdt_status; | 47 | static unsigned long wdt_status; |
@@ -237,16 +238,16 @@ static struct miscdevice orion_wdt_miscdev = { | |||
237 | 238 | ||
238 | static int __devinit orion_wdt_probe(struct platform_device *pdev) | 239 | static int __devinit orion_wdt_probe(struct platform_device *pdev) |
239 | { | 240 | { |
240 | struct orion_wdt_platform_data *pdata = pdev->dev.platform_data; | ||
241 | struct resource *res; | 241 | struct resource *res; |
242 | int ret; | 242 | int ret; |
243 | 243 | ||
244 | if (pdata) { | 244 | clk = clk_get(&pdev->dev, NULL); |
245 | wdt_tclk = pdata->tclk; | 245 | if (IS_ERR(clk)) { |
246 | } else { | 246 | printk(KERN_ERR "Orion Watchdog missing clock\n"); |
247 | pr_err("misses platform data\n"); | ||
248 | return -ENODEV; | 247 | return -ENODEV; |
249 | } | 248 | } |
249 | clk_prepare_enable(clk); | ||
250 | wdt_tclk = clk_get_rate(clk); | ||
250 | 251 | ||
251 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 252 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
252 | 253 | ||
@@ -282,6 +283,9 @@ static int __devexit orion_wdt_remove(struct platform_device *pdev) | |||
282 | if (!ret) | 283 | if (!ret) |
283 | orion_wdt_miscdev.parent = NULL; | 284 | orion_wdt_miscdev.parent = NULL; |
284 | 285 | ||
286 | clk_disable_unprepare(clk); | ||
287 | clk_put(clk); | ||
288 | |||
285 | return ret; | 289 | return ret; |
286 | } | 290 | } |
287 | 291 | ||