diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-01-30 20:07:18 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-01-30 20:07:18 -0500 |
commit | 4bcec913d0a98d991c750034a04675443d1f10b5 (patch) | |
tree | ce2e960ba26d50f09b6a7bd864b2b4d3c275e69b /drivers/net | |
parent | 03c7287dd22c18815964219c9a2e75054cd004df (diff) | |
parent | f878f84373aefda7f041a74b24a83b8b7dec1cf0 (diff) |
Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc
Pull more powerpc bits from Ben Herrenschmidt:
"Here are a few more powerpc bits for this merge window. The bulk is
made of two pull requests from Scott and Anatolij that I had missed
previously (they arrived while I was away). Since both their branches
are in -next independently, and the content has been around for a
little while, they can still go in.
The rest is mostly bug and regression fixes, a small series of
cleanups to our pseries cpuidle code (including moving it to the right
place), and one new cpuidle bakend for the powernv platform. I also
wired up the new sched_attr syscalls"
* 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc: (37 commits)
powerpc: Wire up sched_setattr and sched_getattr syscalls
powerpc/hugetlb: Replace __get_cpu_var with get_cpu_var
powerpc: Make sure "cache" directory is removed when offlining cpu
powerpc/mm: Fix mmap errno when MAP_FIXED is set and mapping exceeds the allowed address space
powerpc/powernv/cpuidle: Back-end cpuidle driver for powernv platform.
powerpc/pseries/cpuidle: smt-snooze-delay cleanup.
powerpc/pseries/cpuidle: Remove MAX_IDLE_STATE macro.
powerpc/pseries/cpuidle: Make cpuidle-pseries backend driver a non-module.
powerpc/pseries/cpuidle: Use cpuidle_register() for initialisation.
powerpc/pseries/cpuidle: Move processor_idle.c to drivers/cpuidle.
powerpc: Fix 32-bit frames for signals delivered when transactional
powerpc/iommu: Fix initialisation of DART iommu table
powerpc/numa: Fix decimal permissions
powerpc/mm: Fix compile error of pgtable-ppc64.h
powerpc: Fix hw breakpoints on !HAVE_HW_BREAKPOINT configurations
clk: corenet: Adds the clock binding
powerpc/booke64: Guard e6500 tlb handler with CONFIG_PPC_FSL_BOOK3E
powerpc/512x: dts: add MPC5125 clock specs
powerpc/512x: clk: support MPC5121/5123/5125 SoC variants
powerpc/512x: clk: enforce even SDHC divider values
...
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/can/mscan/mpc5xxx_can.c | 270 |
1 files changed, 154 insertions, 116 deletions
diff --git a/drivers/net/can/mscan/mpc5xxx_can.c b/drivers/net/can/mscan/mpc5xxx_can.c index 035e235e3118..44725296f72a 100644 --- a/drivers/net/can/mscan/mpc5xxx_can.c +++ b/drivers/net/can/mscan/mpc5xxx_can.c | |||
@@ -108,135 +108,170 @@ static u32 mpc52xx_can_get_clock(struct platform_device *ofdev, | |||
108 | #endif /* CONFIG_PPC_MPC52xx */ | 108 | #endif /* CONFIG_PPC_MPC52xx */ |
109 | 109 | ||
110 | #ifdef CONFIG_PPC_MPC512x | 110 | #ifdef CONFIG_PPC_MPC512x |
111 | struct mpc512x_clockctl { | ||
112 | u32 spmr; /* System PLL Mode Reg */ | ||
113 | u32 sccr[2]; /* System Clk Ctrl Reg 1 & 2 */ | ||
114 | u32 scfr1; /* System Clk Freq Reg 1 */ | ||
115 | u32 scfr2; /* System Clk Freq Reg 2 */ | ||
116 | u32 reserved; | ||
117 | u32 bcr; /* Bread Crumb Reg */ | ||
118 | u32 pccr[12]; /* PSC Clk Ctrl Reg 0-11 */ | ||
119 | u32 spccr; /* SPDIF Clk Ctrl Reg */ | ||
120 | u32 cccr; /* CFM Clk Ctrl Reg */ | ||
121 | u32 dccr; /* DIU Clk Cnfg Reg */ | ||
122 | u32 mccr[4]; /* MSCAN Clk Ctrl Reg 1-3 */ | ||
123 | }; | ||
124 | |||
125 | static struct of_device_id mpc512x_clock_ids[] = { | ||
126 | { .compatible = "fsl,mpc5121-clock", }, | ||
127 | {} | ||
128 | }; | ||
129 | |||
130 | static u32 mpc512x_can_get_clock(struct platform_device *ofdev, | 111 | static u32 mpc512x_can_get_clock(struct platform_device *ofdev, |
131 | const char *clock_name, int *mscan_clksrc) | 112 | const char *clock_source, int *mscan_clksrc) |
132 | { | 113 | { |
133 | struct mpc512x_clockctl __iomem *clockctl; | 114 | struct device_node *np; |
134 | struct device_node *np_clock; | 115 | u32 clockdiv; |
135 | struct clk *sys_clk, *ref_clk; | 116 | enum { |
136 | int plen, clockidx, clocksrc = -1; | 117 | CLK_FROM_AUTO, |
137 | u32 sys_freq, val, clockdiv = 1, freq = 0; | 118 | CLK_FROM_IPS, |
138 | const u32 *pval; | 119 | CLK_FROM_SYS, |
139 | 120 | CLK_FROM_REF, | |
140 | np_clock = of_find_matching_node(NULL, mpc512x_clock_ids); | 121 | } clk_from; |
141 | if (!np_clock) { | 122 | struct clk *clk_in, *clk_can; |
142 | dev_err(&ofdev->dev, "couldn't find clock node\n"); | 123 | unsigned long freq_calc; |
143 | return 0; | 124 | struct mscan_priv *priv; |
144 | } | 125 | struct clk *clk_ipg; |
145 | clockctl = of_iomap(np_clock, 0); | ||
146 | if (!clockctl) { | ||
147 | dev_err(&ofdev->dev, "couldn't map clock registers\n"); | ||
148 | goto exit_put; | ||
149 | } | ||
150 | 126 | ||
151 | /* Determine the MSCAN device index from the peripheral's | 127 | /* the caller passed in the clock source spec that was read from |
152 | * physical address. Register address offsets against the | 128 | * the device tree, get the optional clock divider as well |
153 | * IMMR base are: 0x1300, 0x1380, 0x2300, 0x2380 | ||
154 | */ | 129 | */ |
155 | pval = of_get_property(ofdev->dev.of_node, "reg", &plen); | 130 | np = ofdev->dev.of_node; |
156 | BUG_ON(!pval || plen < sizeof(*pval)); | 131 | clockdiv = 1; |
157 | clockidx = (*pval & 0x80) ? 1 : 0; | 132 | of_property_read_u32(np, "fsl,mscan-clock-divider", &clockdiv); |
158 | if (*pval & 0x2000) | 133 | dev_dbg(&ofdev->dev, "device tree specs: clk src[%s] div[%d]\n", |
159 | clockidx += 2; | 134 | clock_source ? clock_source : "<NULL>", clockdiv); |
135 | |||
136 | /* when clock-source is 'ip', the CANCTL1[CLKSRC] bit needs to | ||
137 | * get set, and the 'ips' clock is the input to the MSCAN | ||
138 | * component | ||
139 | * | ||
140 | * for clock-source values of 'ref' or 'sys' the CANCTL1[CLKSRC] | ||
141 | * bit needs to get cleared, an optional clock-divider may have | ||
142 | * been specified (the default value is 1), the appropriate | ||
143 | * MSCAN related MCLK is the input to the MSCAN component | ||
144 | * | ||
145 | * in the absence of a clock-source spec, first an optimal clock | ||
146 | * gets determined based on the 'sys' clock, if that fails the | ||
147 | * 'ref' clock is used | ||
148 | */ | ||
149 | clk_from = CLK_FROM_AUTO; | ||
150 | if (clock_source) { | ||
151 | /* interpret the device tree's spec for the clock source */ | ||
152 | if (!strcmp(clock_source, "ip")) | ||
153 | clk_from = CLK_FROM_IPS; | ||
154 | else if (!strcmp(clock_source, "sys")) | ||
155 | clk_from = CLK_FROM_SYS; | ||
156 | else if (!strcmp(clock_source, "ref")) | ||
157 | clk_from = CLK_FROM_REF; | ||
158 | else | ||
159 | goto err_invalid; | ||
160 | dev_dbg(&ofdev->dev, "got a clk source spec[%d]\n", clk_from); | ||
161 | } | ||
162 | if (clk_from == CLK_FROM_AUTO) { | ||
163 | /* no spec so far, try the 'sys' clock; round to the | ||
164 | * next MHz and see if we can get a multiple of 16MHz | ||
165 | */ | ||
166 | dev_dbg(&ofdev->dev, "no clk source spec, trying SYS\n"); | ||
167 | clk_in = devm_clk_get(&ofdev->dev, "sys"); | ||
168 | if (IS_ERR(clk_in)) | ||
169 | goto err_notavail; | ||
170 | freq_calc = clk_get_rate(clk_in); | ||
171 | freq_calc += 499999; | ||
172 | freq_calc /= 1000000; | ||
173 | freq_calc *= 1000000; | ||
174 | if ((freq_calc % 16000000) == 0) { | ||
175 | clk_from = CLK_FROM_SYS; | ||
176 | clockdiv = freq_calc / 16000000; | ||
177 | dev_dbg(&ofdev->dev, | ||
178 | "clk fit, sys[%lu] div[%d] freq[%lu]\n", | ||
179 | freq_calc, clockdiv, freq_calc / clockdiv); | ||
180 | } | ||
181 | } | ||
182 | if (clk_from == CLK_FROM_AUTO) { | ||
183 | /* no spec so far, use the 'ref' clock */ | ||
184 | dev_dbg(&ofdev->dev, "no clk source spec, trying REF\n"); | ||
185 | clk_in = devm_clk_get(&ofdev->dev, "ref"); | ||
186 | if (IS_ERR(clk_in)) | ||
187 | goto err_notavail; | ||
188 | clk_from = CLK_FROM_REF; | ||
189 | freq_calc = clk_get_rate(clk_in); | ||
190 | dev_dbg(&ofdev->dev, | ||
191 | "clk fit, ref[%lu] (no div) freq[%lu]\n", | ||
192 | freq_calc, freq_calc); | ||
193 | } | ||
160 | 194 | ||
161 | /* | 195 | /* select IPS or MCLK as the MSCAN input (returned to the caller), |
162 | * Clock source and divider selection: 3 different clock sources | 196 | * setup the MCLK mux source and rate if applicable, apply the |
163 | * can be selected: "ip", "ref" or "sys". For the latter two, a | 197 | * optionally specified or derived above divider, and determine |
164 | * clock divider can be defined as well. If the clock source is | 198 | * the actual resulting clock rate to return to the caller |
165 | * not specified by the device tree, we first try to find an | ||
166 | * optimal CAN source clock based on the system clock. If that | ||
167 | * is not posslible, the reference clock will be used. | ||
168 | */ | 199 | */ |
169 | if (clock_name && !strcmp(clock_name, "ip")) { | 200 | switch (clk_from) { |
201 | case CLK_FROM_IPS: | ||
202 | clk_can = devm_clk_get(&ofdev->dev, "ips"); | ||
203 | if (IS_ERR(clk_can)) | ||
204 | goto err_notavail; | ||
205 | priv = netdev_priv(dev_get_drvdata(&ofdev->dev)); | ||
206 | priv->clk_can = clk_can; | ||
207 | freq_calc = clk_get_rate(clk_can); | ||
170 | *mscan_clksrc = MSCAN_CLKSRC_IPS; | 208 | *mscan_clksrc = MSCAN_CLKSRC_IPS; |
171 | freq = mpc5xxx_get_bus_frequency(ofdev->dev.of_node); | 209 | dev_dbg(&ofdev->dev, "clk from IPS, clksrc[%d] freq[%lu]\n", |
172 | } else { | 210 | *mscan_clksrc, freq_calc); |
211 | break; | ||
212 | case CLK_FROM_SYS: | ||
213 | case CLK_FROM_REF: | ||
214 | clk_can = devm_clk_get(&ofdev->dev, "mclk"); | ||
215 | if (IS_ERR(clk_can)) | ||
216 | goto err_notavail; | ||
217 | priv = netdev_priv(dev_get_drvdata(&ofdev->dev)); | ||
218 | priv->clk_can = clk_can; | ||
219 | if (clk_from == CLK_FROM_SYS) | ||
220 | clk_in = devm_clk_get(&ofdev->dev, "sys"); | ||
221 | if (clk_from == CLK_FROM_REF) | ||
222 | clk_in = devm_clk_get(&ofdev->dev, "ref"); | ||
223 | if (IS_ERR(clk_in)) | ||
224 | goto err_notavail; | ||
225 | clk_set_parent(clk_can, clk_in); | ||
226 | freq_calc = clk_get_rate(clk_in); | ||
227 | freq_calc /= clockdiv; | ||
228 | clk_set_rate(clk_can, freq_calc); | ||
229 | freq_calc = clk_get_rate(clk_can); | ||
173 | *mscan_clksrc = MSCAN_CLKSRC_BUS; | 230 | *mscan_clksrc = MSCAN_CLKSRC_BUS; |
174 | 231 | dev_dbg(&ofdev->dev, "clk from MCLK, clksrc[%d] freq[%lu]\n", | |
175 | pval = of_get_property(ofdev->dev.of_node, | 232 | *mscan_clksrc, freq_calc); |
176 | "fsl,mscan-clock-divider", &plen); | 233 | break; |
177 | if (pval && plen == sizeof(*pval)) | 234 | default: |
178 | clockdiv = *pval; | 235 | goto err_invalid; |
179 | if (!clockdiv) | ||
180 | clockdiv = 1; | ||
181 | |||
182 | if (!clock_name || !strcmp(clock_name, "sys")) { | ||
183 | sys_clk = devm_clk_get(&ofdev->dev, "sys_clk"); | ||
184 | if (IS_ERR(sys_clk)) { | ||
185 | dev_err(&ofdev->dev, "couldn't get sys_clk\n"); | ||
186 | goto exit_unmap; | ||
187 | } | ||
188 | /* Get and round up/down sys clock rate */ | ||
189 | sys_freq = 1000000 * | ||
190 | ((clk_get_rate(sys_clk) + 499999) / 1000000); | ||
191 | |||
192 | if (!clock_name) { | ||
193 | /* A multiple of 16 MHz would be optimal */ | ||
194 | if ((sys_freq % 16000000) == 0) { | ||
195 | clocksrc = 0; | ||
196 | clockdiv = sys_freq / 16000000; | ||
197 | freq = sys_freq / clockdiv; | ||
198 | } | ||
199 | } else { | ||
200 | clocksrc = 0; | ||
201 | freq = sys_freq / clockdiv; | ||
202 | } | ||
203 | } | ||
204 | |||
205 | if (clocksrc < 0) { | ||
206 | ref_clk = devm_clk_get(&ofdev->dev, "ref_clk"); | ||
207 | if (IS_ERR(ref_clk)) { | ||
208 | dev_err(&ofdev->dev, "couldn't get ref_clk\n"); | ||
209 | goto exit_unmap; | ||
210 | } | ||
211 | clocksrc = 1; | ||
212 | freq = clk_get_rate(ref_clk) / clockdiv; | ||
213 | } | ||
214 | } | 236 | } |
215 | 237 | ||
216 | /* Disable clock */ | 238 | /* the above clk_can item is used for the bitrate, access to |
217 | out_be32(&clockctl->mccr[clockidx], 0x0); | 239 | * the peripheral's register set needs the clk_ipg item |
218 | if (clocksrc >= 0) { | 240 | */ |
219 | /* Set source and divider */ | 241 | clk_ipg = devm_clk_get(&ofdev->dev, "ipg"); |
220 | val = (clocksrc << 14) | ((clockdiv - 1) << 17); | 242 | if (IS_ERR(clk_ipg)) |
221 | out_be32(&clockctl->mccr[clockidx], val); | 243 | goto err_notavail_ipg; |
222 | /* Enable clock */ | 244 | if (clk_prepare_enable(clk_ipg)) |
223 | out_be32(&clockctl->mccr[clockidx], val | 0x10000); | 245 | goto err_notavail_ipg; |
224 | } | 246 | priv = netdev_priv(dev_get_drvdata(&ofdev->dev)); |
247 | priv->clk_ipg = clk_ipg; | ||
248 | |||
249 | /* return the determined clock source rate */ | ||
250 | return freq_calc; | ||
251 | |||
252 | err_invalid: | ||
253 | dev_err(&ofdev->dev, "invalid clock source specification\n"); | ||
254 | /* clock source rate could not get determined */ | ||
255 | return 0; | ||
225 | 256 | ||
226 | /* Enable MSCAN clock domain */ | 257 | err_notavail: |
227 | val = in_be32(&clockctl->sccr[1]); | 258 | dev_err(&ofdev->dev, "cannot acquire or setup bitrate clock source\n"); |
228 | if (!(val & (1 << 25))) | 259 | /* clock source rate could not get determined */ |
229 | out_be32(&clockctl->sccr[1], val | (1 << 25)); | 260 | return 0; |
230 | 261 | ||
231 | dev_dbg(&ofdev->dev, "using '%s' with frequency divider %d\n", | 262 | err_notavail_ipg: |
232 | *mscan_clksrc == MSCAN_CLKSRC_IPS ? "ips_clk" : | 263 | dev_err(&ofdev->dev, "cannot acquire or setup register clock\n"); |
233 | clocksrc == 1 ? "ref_clk" : "sys_clk", clockdiv); | 264 | /* clock source rate could not get determined */ |
265 | return 0; | ||
266 | } | ||
234 | 267 | ||
235 | exit_unmap: | 268 | static void mpc512x_can_put_clock(struct platform_device *ofdev) |
236 | iounmap(clockctl); | 269 | { |
237 | exit_put: | 270 | struct mscan_priv *priv; |
238 | of_node_put(np_clock); | 271 | |
239 | return freq; | 272 | priv = netdev_priv(dev_get_drvdata(&ofdev->dev)); |
273 | if (priv->clk_ipg) | ||
274 | clk_disable_unprepare(priv->clk_ipg); | ||
240 | } | 275 | } |
241 | #else /* !CONFIG_PPC_MPC512x */ | 276 | #else /* !CONFIG_PPC_MPC512x */ |
242 | static u32 mpc512x_can_get_clock(struct platform_device *ofdev, | 277 | static u32 mpc512x_can_get_clock(struct platform_device *ofdev, |
@@ -244,6 +279,7 @@ static u32 mpc512x_can_get_clock(struct platform_device *ofdev, | |||
244 | { | 279 | { |
245 | return 0; | 280 | return 0; |
246 | } | 281 | } |
282 | #define mpc512x_can_put_clock NULL | ||
247 | #endif /* CONFIG_PPC_MPC512x */ | 283 | #endif /* CONFIG_PPC_MPC512x */ |
248 | 284 | ||
249 | static const struct of_device_id mpc5xxx_can_table[]; | 285 | static const struct of_device_id mpc5xxx_can_table[]; |
@@ -385,11 +421,13 @@ static int mpc5xxx_can_resume(struct platform_device *ofdev) | |||
385 | static const struct mpc5xxx_can_data mpc5200_can_data = { | 421 | static const struct mpc5xxx_can_data mpc5200_can_data = { |
386 | .type = MSCAN_TYPE_MPC5200, | 422 | .type = MSCAN_TYPE_MPC5200, |
387 | .get_clock = mpc52xx_can_get_clock, | 423 | .get_clock = mpc52xx_can_get_clock, |
424 | /* .put_clock not applicable */ | ||
388 | }; | 425 | }; |
389 | 426 | ||
390 | static const struct mpc5xxx_can_data mpc5121_can_data = { | 427 | static const struct mpc5xxx_can_data mpc5121_can_data = { |
391 | .type = MSCAN_TYPE_MPC5121, | 428 | .type = MSCAN_TYPE_MPC5121, |
392 | .get_clock = mpc512x_can_get_clock, | 429 | .get_clock = mpc512x_can_get_clock, |
430 | .put_clock = mpc512x_can_put_clock, | ||
393 | }; | 431 | }; |
394 | 432 | ||
395 | static const struct of_device_id mpc5xxx_can_table[] = { | 433 | static const struct of_device_id mpc5xxx_can_table[] = { |