diff options
Diffstat (limited to 'arch/avr32/mach-at32ap/at32ap7000.c')
-rw-r--r-- | arch/avr32/mach-at32ap/at32ap7000.c | 340 |
1 files changed, 250 insertions, 90 deletions
diff --git a/arch/avr32/mach-at32ap/at32ap7000.c b/arch/avr32/mach-at32ap/at32ap7000.c index 4dda42d3f6d5..64cc5583ddfb 100644 --- a/arch/avr32/mach-at32ap/at32ap7000.c +++ b/arch/avr32/mach-at32ap/at32ap7000.c | |||
@@ -17,14 +17,20 @@ | |||
17 | #include <asm/arch/at32ap7000.h> | 17 | #include <asm/arch/at32ap7000.h> |
18 | #include <asm/arch/board.h> | 18 | #include <asm/arch/board.h> |
19 | #include <asm/arch/portmux.h> | 19 | #include <asm/arch/portmux.h> |
20 | #include <asm/arch/sm.h> | ||
21 | 20 | ||
22 | #include <video/atmel_lcdc.h> | 21 | #include <video/atmel_lcdc.h> |
23 | 22 | ||
24 | #include "clock.h" | 23 | #include "clock.h" |
25 | #include "hmatrix.h" | 24 | #include "hmatrix.h" |
26 | #include "pio.h" | 25 | #include "pio.h" |
27 | #include "sm.h" | 26 | #include "pm.h" |
27 | |||
28 | /* | ||
29 | * We can reduce the code size a bit by using a constant here. Since | ||
30 | * this file is completely chip-specific, it's safe to not use | ||
31 | * ioremap. Generic drivers should of course never do this. | ||
32 | */ | ||
33 | #define AT32_PM_BASE 0xfff00000 | ||
28 | 34 | ||
29 | #define PBMEM(base) \ | 35 | #define PBMEM(base) \ |
30 | { \ | 36 | { \ |
@@ -88,6 +94,8 @@ static struct clk devname##_##_name = { \ | |||
88 | .index = _index, \ | 94 | .index = _index, \ |
89 | } | 95 | } |
90 | 96 | ||
97 | static DEFINE_SPINLOCK(pm_lock); | ||
98 | |||
91 | unsigned long at32ap7000_osc_rates[3] = { | 99 | unsigned long at32ap7000_osc_rates[3] = { |
92 | [0] = 32768, | 100 | [0] = 32768, |
93 | /* FIXME: these are ATSTK1002-specific */ | 101 | /* FIXME: these are ATSTK1002-specific */ |
@@ -104,11 +112,11 @@ static unsigned long pll_get_rate(struct clk *clk, unsigned long control) | |||
104 | { | 112 | { |
105 | unsigned long div, mul, rate; | 113 | unsigned long div, mul, rate; |
106 | 114 | ||
107 | if (!(control & SM_BIT(PLLEN))) | 115 | if (!(control & PM_BIT(PLLEN))) |
108 | return 0; | 116 | return 0; |
109 | 117 | ||
110 | div = SM_BFEXT(PLLDIV, control) + 1; | 118 | div = PM_BFEXT(PLLDIV, control) + 1; |
111 | mul = SM_BFEXT(PLLMUL, control) + 1; | 119 | mul = PM_BFEXT(PLLMUL, control) + 1; |
112 | 120 | ||
113 | rate = clk->parent->get_rate(clk->parent); | 121 | rate = clk->parent->get_rate(clk->parent); |
114 | rate = (rate + div / 2) / div; | 122 | rate = (rate + div / 2) / div; |
@@ -121,7 +129,7 @@ static unsigned long pll0_get_rate(struct clk *clk) | |||
121 | { | 129 | { |
122 | u32 control; | 130 | u32 control; |
123 | 131 | ||
124 | control = sm_readl(&system_manager, PM_PLL0); | 132 | control = pm_readl(PLL0); |
125 | 133 | ||
126 | return pll_get_rate(clk, control); | 134 | return pll_get_rate(clk, control); |
127 | } | 135 | } |
@@ -130,7 +138,7 @@ static unsigned long pll1_get_rate(struct clk *clk) | |||
130 | { | 138 | { |
131 | u32 control; | 139 | u32 control; |
132 | 140 | ||
133 | control = sm_readl(&system_manager, PM_PLL1); | 141 | control = pm_readl(PLL1); |
134 | 142 | ||
135 | return pll_get_rate(clk, control); | 143 | return pll_get_rate(clk, control); |
136 | } | 144 | } |
@@ -187,108 +195,139 @@ static unsigned long bus_clk_get_rate(struct clk *clk, unsigned int shift) | |||
187 | 195 | ||
188 | static void cpu_clk_mode(struct clk *clk, int enabled) | 196 | static void cpu_clk_mode(struct clk *clk, int enabled) |
189 | { | 197 | { |
190 | struct at32_sm *sm = &system_manager; | ||
191 | unsigned long flags; | 198 | unsigned long flags; |
192 | u32 mask; | 199 | u32 mask; |
193 | 200 | ||
194 | spin_lock_irqsave(&sm->lock, flags); | 201 | spin_lock_irqsave(&pm_lock, flags); |
195 | mask = sm_readl(sm, PM_CPU_MASK); | 202 | mask = pm_readl(CPU_MASK); |
196 | if (enabled) | 203 | if (enabled) |
197 | mask |= 1 << clk->index; | 204 | mask |= 1 << clk->index; |
198 | else | 205 | else |
199 | mask &= ~(1 << clk->index); | 206 | mask &= ~(1 << clk->index); |
200 | sm_writel(sm, PM_CPU_MASK, mask); | 207 | pm_writel(CPU_MASK, mask); |
201 | spin_unlock_irqrestore(&sm->lock, flags); | 208 | spin_unlock_irqrestore(&pm_lock, flags); |
202 | } | 209 | } |
203 | 210 | ||
204 | static unsigned long cpu_clk_get_rate(struct clk *clk) | 211 | static unsigned long cpu_clk_get_rate(struct clk *clk) |
205 | { | 212 | { |
206 | unsigned long cksel, shift = 0; | 213 | unsigned long cksel, shift = 0; |
207 | 214 | ||
208 | cksel = sm_readl(&system_manager, PM_CKSEL); | 215 | cksel = pm_readl(CKSEL); |
209 | if (cksel & SM_BIT(CPUDIV)) | 216 | if (cksel & PM_BIT(CPUDIV)) |
210 | shift = SM_BFEXT(CPUSEL, cksel) + 1; | 217 | shift = PM_BFEXT(CPUSEL, cksel) + 1; |
211 | 218 | ||
212 | return bus_clk_get_rate(clk, shift); | 219 | return bus_clk_get_rate(clk, shift); |
213 | } | 220 | } |
214 | 221 | ||
222 | static long cpu_clk_set_rate(struct clk *clk, unsigned long rate, int apply) | ||
223 | { | ||
224 | u32 control; | ||
225 | unsigned long parent_rate, child_div, actual_rate, div; | ||
226 | |||
227 | parent_rate = clk->parent->get_rate(clk->parent); | ||
228 | control = pm_readl(CKSEL); | ||
229 | |||
230 | if (control & PM_BIT(HSBDIV)) | ||
231 | child_div = 1 << (PM_BFEXT(HSBSEL, control) + 1); | ||
232 | else | ||
233 | child_div = 1; | ||
234 | |||
235 | if (rate > 3 * (parent_rate / 4) || child_div == 1) { | ||
236 | actual_rate = parent_rate; | ||
237 | control &= ~PM_BIT(CPUDIV); | ||
238 | } else { | ||
239 | unsigned int cpusel; | ||
240 | div = (parent_rate + rate / 2) / rate; | ||
241 | if (div > child_div) | ||
242 | div = child_div; | ||
243 | cpusel = (div > 1) ? (fls(div) - 2) : 0; | ||
244 | control = PM_BIT(CPUDIV) | PM_BFINS(CPUSEL, cpusel, control); | ||
245 | actual_rate = parent_rate / (1 << (cpusel + 1)); | ||
246 | } | ||
247 | |||
248 | pr_debug("clk %s: new rate %lu (actual rate %lu)\n", | ||
249 | clk->name, rate, actual_rate); | ||
250 | |||
251 | if (apply) | ||
252 | pm_writel(CKSEL, control); | ||
253 | |||
254 | return actual_rate; | ||
255 | } | ||
256 | |||
215 | static void hsb_clk_mode(struct clk *clk, int enabled) | 257 | static void hsb_clk_mode(struct clk *clk, int enabled) |
216 | { | 258 | { |
217 | struct at32_sm *sm = &system_manager; | ||
218 | unsigned long flags; | 259 | unsigned long flags; |
219 | u32 mask; | 260 | u32 mask; |
220 | 261 | ||
221 | spin_lock_irqsave(&sm->lock, flags); | 262 | spin_lock_irqsave(&pm_lock, flags); |
222 | mask = sm_readl(sm, PM_HSB_MASK); | 263 | mask = pm_readl(HSB_MASK); |
223 | if (enabled) | 264 | if (enabled) |
224 | mask |= 1 << clk->index; | 265 | mask |= 1 << clk->index; |
225 | else | 266 | else |
226 | mask &= ~(1 << clk->index); | 267 | mask &= ~(1 << clk->index); |
227 | sm_writel(sm, PM_HSB_MASK, mask); | 268 | pm_writel(HSB_MASK, mask); |
228 | spin_unlock_irqrestore(&sm->lock, flags); | 269 | spin_unlock_irqrestore(&pm_lock, flags); |
229 | } | 270 | } |
230 | 271 | ||
231 | static unsigned long hsb_clk_get_rate(struct clk *clk) | 272 | static unsigned long hsb_clk_get_rate(struct clk *clk) |
232 | { | 273 | { |
233 | unsigned long cksel, shift = 0; | 274 | unsigned long cksel, shift = 0; |
234 | 275 | ||
235 | cksel = sm_readl(&system_manager, PM_CKSEL); | 276 | cksel = pm_readl(CKSEL); |
236 | if (cksel & SM_BIT(HSBDIV)) | 277 | if (cksel & PM_BIT(HSBDIV)) |
237 | shift = SM_BFEXT(HSBSEL, cksel) + 1; | 278 | shift = PM_BFEXT(HSBSEL, cksel) + 1; |
238 | 279 | ||
239 | return bus_clk_get_rate(clk, shift); | 280 | return bus_clk_get_rate(clk, shift); |
240 | } | 281 | } |
241 | 282 | ||
242 | static void pba_clk_mode(struct clk *clk, int enabled) | 283 | static void pba_clk_mode(struct clk *clk, int enabled) |
243 | { | 284 | { |
244 | struct at32_sm *sm = &system_manager; | ||
245 | unsigned long flags; | 285 | unsigned long flags; |
246 | u32 mask; | 286 | u32 mask; |
247 | 287 | ||
248 | spin_lock_irqsave(&sm->lock, flags); | 288 | spin_lock_irqsave(&pm_lock, flags); |
249 | mask = sm_readl(sm, PM_PBA_MASK); | 289 | mask = pm_readl(PBA_MASK); |
250 | if (enabled) | 290 | if (enabled) |
251 | mask |= 1 << clk->index; | 291 | mask |= 1 << clk->index; |
252 | else | 292 | else |
253 | mask &= ~(1 << clk->index); | 293 | mask &= ~(1 << clk->index); |
254 | sm_writel(sm, PM_PBA_MASK, mask); | 294 | pm_writel(PBA_MASK, mask); |
255 | spin_unlock_irqrestore(&sm->lock, flags); | 295 | spin_unlock_irqrestore(&pm_lock, flags); |
256 | } | 296 | } |
257 | 297 | ||
258 | static unsigned long pba_clk_get_rate(struct clk *clk) | 298 | static unsigned long pba_clk_get_rate(struct clk *clk) |
259 | { | 299 | { |
260 | unsigned long cksel, shift = 0; | 300 | unsigned long cksel, shift = 0; |
261 | 301 | ||
262 | cksel = sm_readl(&system_manager, PM_CKSEL); | 302 | cksel = pm_readl(CKSEL); |
263 | if (cksel & SM_BIT(PBADIV)) | 303 | if (cksel & PM_BIT(PBADIV)) |
264 | shift = SM_BFEXT(PBASEL, cksel) + 1; | 304 | shift = PM_BFEXT(PBASEL, cksel) + 1; |
265 | 305 | ||
266 | return bus_clk_get_rate(clk, shift); | 306 | return bus_clk_get_rate(clk, shift); |
267 | } | 307 | } |
268 | 308 | ||
269 | static void pbb_clk_mode(struct clk *clk, int enabled) | 309 | static void pbb_clk_mode(struct clk *clk, int enabled) |
270 | { | 310 | { |
271 | struct at32_sm *sm = &system_manager; | ||
272 | unsigned long flags; | 311 | unsigned long flags; |
273 | u32 mask; | 312 | u32 mask; |
274 | 313 | ||
275 | spin_lock_irqsave(&sm->lock, flags); | 314 | spin_lock_irqsave(&pm_lock, flags); |
276 | mask = sm_readl(sm, PM_PBB_MASK); | 315 | mask = pm_readl(PBB_MASK); |
277 | if (enabled) | 316 | if (enabled) |
278 | mask |= 1 << clk->index; | 317 | mask |= 1 << clk->index; |
279 | else | 318 | else |
280 | mask &= ~(1 << clk->index); | 319 | mask &= ~(1 << clk->index); |
281 | sm_writel(sm, PM_PBB_MASK, mask); | 320 | pm_writel(PBB_MASK, mask); |
282 | spin_unlock_irqrestore(&sm->lock, flags); | 321 | spin_unlock_irqrestore(&pm_lock, flags); |
283 | } | 322 | } |
284 | 323 | ||
285 | static unsigned long pbb_clk_get_rate(struct clk *clk) | 324 | static unsigned long pbb_clk_get_rate(struct clk *clk) |
286 | { | 325 | { |
287 | unsigned long cksel, shift = 0; | 326 | unsigned long cksel, shift = 0; |
288 | 327 | ||
289 | cksel = sm_readl(&system_manager, PM_CKSEL); | 328 | cksel = pm_readl(CKSEL); |
290 | if (cksel & SM_BIT(PBBDIV)) | 329 | if (cksel & PM_BIT(PBBDIV)) |
291 | shift = SM_BFEXT(PBBSEL, cksel) + 1; | 330 | shift = PM_BFEXT(PBBSEL, cksel) + 1; |
292 | 331 | ||
293 | return bus_clk_get_rate(clk, shift); | 332 | return bus_clk_get_rate(clk, shift); |
294 | } | 333 | } |
@@ -296,6 +335,7 @@ static unsigned long pbb_clk_get_rate(struct clk *clk) | |||
296 | static struct clk cpu_clk = { | 335 | static struct clk cpu_clk = { |
297 | .name = "cpu", | 336 | .name = "cpu", |
298 | .get_rate = cpu_clk_get_rate, | 337 | .get_rate = cpu_clk_get_rate, |
338 | .set_rate = cpu_clk_set_rate, | ||
299 | .users = 1, | 339 | .users = 1, |
300 | }; | 340 | }; |
301 | static struct clk hsb_clk = { | 341 | static struct clk hsb_clk = { |
@@ -327,12 +367,12 @@ static void genclk_mode(struct clk *clk, int enabled) | |||
327 | { | 367 | { |
328 | u32 control; | 368 | u32 control; |
329 | 369 | ||
330 | control = sm_readl(&system_manager, PM_GCCTRL + 4 * clk->index); | 370 | control = pm_readl(GCCTRL(clk->index)); |
331 | if (enabled) | 371 | if (enabled) |
332 | control |= SM_BIT(CEN); | 372 | control |= PM_BIT(CEN); |
333 | else | 373 | else |
334 | control &= ~SM_BIT(CEN); | 374 | control &= ~PM_BIT(CEN); |
335 | sm_writel(&system_manager, PM_GCCTRL + 4 * clk->index, control); | 375 | pm_writel(GCCTRL(clk->index), control); |
336 | } | 376 | } |
337 | 377 | ||
338 | static unsigned long genclk_get_rate(struct clk *clk) | 378 | static unsigned long genclk_get_rate(struct clk *clk) |
@@ -340,9 +380,9 @@ static unsigned long genclk_get_rate(struct clk *clk) | |||
340 | u32 control; | 380 | u32 control; |
341 | unsigned long div = 1; | 381 | unsigned long div = 1; |
342 | 382 | ||
343 | control = sm_readl(&system_manager, PM_GCCTRL + 4 * clk->index); | 383 | control = pm_readl(GCCTRL(clk->index)); |
344 | if (control & SM_BIT(DIVEN)) | 384 | if (control & PM_BIT(DIVEN)) |
345 | div = 2 * (SM_BFEXT(DIV, control) + 1); | 385 | div = 2 * (PM_BFEXT(DIV, control) + 1); |
346 | 386 | ||
347 | return clk->parent->get_rate(clk->parent) / div; | 387 | return clk->parent->get_rate(clk->parent) / div; |
348 | } | 388 | } |
@@ -353,23 +393,22 @@ static long genclk_set_rate(struct clk *clk, unsigned long rate, int apply) | |||
353 | unsigned long parent_rate, actual_rate, div; | 393 | unsigned long parent_rate, actual_rate, div; |
354 | 394 | ||
355 | parent_rate = clk->parent->get_rate(clk->parent); | 395 | parent_rate = clk->parent->get_rate(clk->parent); |
356 | control = sm_readl(&system_manager, PM_GCCTRL + 4 * clk->index); | 396 | control = pm_readl(GCCTRL(clk->index)); |
357 | 397 | ||
358 | if (rate > 3 * parent_rate / 4) { | 398 | if (rate > 3 * parent_rate / 4) { |
359 | actual_rate = parent_rate; | 399 | actual_rate = parent_rate; |
360 | control &= ~SM_BIT(DIVEN); | 400 | control &= ~PM_BIT(DIVEN); |
361 | } else { | 401 | } else { |
362 | div = (parent_rate + rate) / (2 * rate) - 1; | 402 | div = (parent_rate + rate) / (2 * rate) - 1; |
363 | control = SM_BFINS(DIV, div, control) | SM_BIT(DIVEN); | 403 | control = PM_BFINS(DIV, div, control) | PM_BIT(DIVEN); |
364 | actual_rate = parent_rate / (2 * (div + 1)); | 404 | actual_rate = parent_rate / (2 * (div + 1)); |
365 | } | 405 | } |
366 | 406 | ||
367 | printk("clk %s: new rate %lu (actual rate %lu)\n", | 407 | dev_dbg(clk->dev, "clk %s: new rate %lu (actual rate %lu)\n", |
368 | clk->name, rate, actual_rate); | 408 | clk->name, rate, actual_rate); |
369 | 409 | ||
370 | if (apply) | 410 | if (apply) |
371 | sm_writel(&system_manager, PM_GCCTRL + 4 * clk->index, | 411 | pm_writel(GCCTRL(clk->index), control); |
372 | control); | ||
373 | 412 | ||
374 | return actual_rate; | 413 | return actual_rate; |
375 | } | 414 | } |
@@ -378,24 +417,24 @@ int genclk_set_parent(struct clk *clk, struct clk *parent) | |||
378 | { | 417 | { |
379 | u32 control; | 418 | u32 control; |
380 | 419 | ||
381 | printk("clk %s: new parent %s (was %s)\n", | 420 | dev_dbg(clk->dev, "clk %s: new parent %s (was %s)\n", |
382 | clk->name, parent->name, clk->parent->name); | 421 | clk->name, parent->name, clk->parent->name); |
383 | 422 | ||
384 | control = sm_readl(&system_manager, PM_GCCTRL + 4 * clk->index); | 423 | control = pm_readl(GCCTRL(clk->index)); |
385 | 424 | ||
386 | if (parent == &osc1 || parent == &pll1) | 425 | if (parent == &osc1 || parent == &pll1) |
387 | control |= SM_BIT(OSCSEL); | 426 | control |= PM_BIT(OSCSEL); |
388 | else if (parent == &osc0 || parent == &pll0) | 427 | else if (parent == &osc0 || parent == &pll0) |
389 | control &= ~SM_BIT(OSCSEL); | 428 | control &= ~PM_BIT(OSCSEL); |
390 | else | 429 | else |
391 | return -EINVAL; | 430 | return -EINVAL; |
392 | 431 | ||
393 | if (parent == &pll0 || parent == &pll1) | 432 | if (parent == &pll0 || parent == &pll1) |
394 | control |= SM_BIT(PLLSEL); | 433 | control |= PM_BIT(PLLSEL); |
395 | else | 434 | else |
396 | control &= ~SM_BIT(PLLSEL); | 435 | control &= ~PM_BIT(PLLSEL); |
397 | 436 | ||
398 | sm_writel(&system_manager, PM_GCCTRL + 4 * clk->index, control); | 437 | pm_writel(GCCTRL(clk->index), control); |
399 | clk->parent = parent; | 438 | clk->parent = parent; |
400 | 439 | ||
401 | return 0; | 440 | return 0; |
@@ -408,11 +447,11 @@ static void __init genclk_init_parent(struct clk *clk) | |||
408 | 447 | ||
409 | BUG_ON(clk->index > 7); | 448 | BUG_ON(clk->index > 7); |
410 | 449 | ||
411 | control = sm_readl(&system_manager, PM_GCCTRL + 4 * clk->index); | 450 | control = pm_readl(GCCTRL(clk->index)); |
412 | if (control & SM_BIT(OSCSEL)) | 451 | if (control & PM_BIT(OSCSEL)) |
413 | parent = (control & SM_BIT(PLLSEL)) ? &pll1 : &osc1; | 452 | parent = (control & PM_BIT(PLLSEL)) ? &pll1 : &osc1; |
414 | else | 453 | else |
415 | parent = (control & SM_BIT(PLLSEL)) ? &pll0 : &osc0; | 454 | parent = (control & PM_BIT(PLLSEL)) ? &pll0 : &osc0; |
416 | 455 | ||
417 | clk->parent = parent; | 456 | clk->parent = parent; |
418 | } | 457 | } |
@@ -420,21 +459,53 @@ static void __init genclk_init_parent(struct clk *clk) | |||
420 | /* -------------------------------------------------------------------- | 459 | /* -------------------------------------------------------------------- |
421 | * System peripherals | 460 | * System peripherals |
422 | * -------------------------------------------------------------------- */ | 461 | * -------------------------------------------------------------------- */ |
423 | static struct resource sm_resource[] = { | 462 | static struct resource at32_pm0_resource[] = { |
424 | PBMEM(0xfff00000), | 463 | { |
425 | NAMED_IRQ(19, "eim"), | 464 | .start = 0xfff00000, |
426 | NAMED_IRQ(20, "pm"), | 465 | .end = 0xfff0007f, |
427 | NAMED_IRQ(21, "rtc"), | 466 | .flags = IORESOURCE_MEM, |
467 | }, | ||
468 | IRQ(20), | ||
428 | }; | 469 | }; |
429 | struct platform_device at32_sm_device = { | 470 | |
430 | .name = "sm", | 471 | static struct resource at32ap700x_rtc0_resource[] = { |
431 | .id = 0, | 472 | { |
432 | .resource = sm_resource, | 473 | .start = 0xfff00080, |
433 | .num_resources = ARRAY_SIZE(sm_resource), | 474 | .end = 0xfff000af, |
475 | .flags = IORESOURCE_MEM, | ||
476 | }, | ||
477 | IRQ(21), | ||
478 | }; | ||
479 | |||
480 | static struct resource at32_wdt0_resource[] = { | ||
481 | { | ||
482 | .start = 0xfff000b0, | ||
483 | .end = 0xfff000bf, | ||
484 | .flags = IORESOURCE_MEM, | ||
485 | }, | ||
486 | }; | ||
487 | |||
488 | static struct resource at32_eic0_resource[] = { | ||
489 | { | ||
490 | .start = 0xfff00100, | ||
491 | .end = 0xfff0013f, | ||
492 | .flags = IORESOURCE_MEM, | ||
493 | }, | ||
494 | IRQ(19), | ||
434 | }; | 495 | }; |
435 | static struct clk at32_sm_pclk = { | 496 | |
497 | DEFINE_DEV(at32_pm, 0); | ||
498 | DEFINE_DEV(at32ap700x_rtc, 0); | ||
499 | DEFINE_DEV(at32_wdt, 0); | ||
500 | DEFINE_DEV(at32_eic, 0); | ||
501 | |||
502 | /* | ||
503 | * Peripheral clock for PM, RTC, WDT and EIC. PM will ensure that this | ||
504 | * is always running. | ||
505 | */ | ||
506 | static struct clk at32_pm_pclk = { | ||
436 | .name = "pclk", | 507 | .name = "pclk", |
437 | .dev = &at32_sm_device.dev, | 508 | .dev = &at32_pm0_device.dev, |
438 | .parent = &pbb_clk, | 509 | .parent = &pbb_clk, |
439 | .mode = pbb_clk_mode, | 510 | .mode = pbb_clk_mode, |
440 | .get_rate = pbb_clk_get_rate, | 511 | .get_rate = pbb_clk_get_rate, |
@@ -583,10 +654,11 @@ DEV_CLK(mck, pio4, pba, 14); | |||
583 | 654 | ||
584 | void __init at32_add_system_devices(void) | 655 | void __init at32_add_system_devices(void) |
585 | { | 656 | { |
586 | system_manager.eim_first_irq = EIM_IRQ_BASE; | 657 | platform_device_register(&at32_pm0_device); |
587 | |||
588 | platform_device_register(&at32_sm_device); | ||
589 | platform_device_register(&at32_intc0_device); | 658 | platform_device_register(&at32_intc0_device); |
659 | platform_device_register(&at32ap700x_rtc0_device); | ||
660 | platform_device_register(&at32_wdt0_device); | ||
661 | platform_device_register(&at32_eic0_device); | ||
590 | platform_device_register(&smc0_device); | 662 | platform_device_register(&smc0_device); |
591 | platform_device_register(&pdc_device); | 663 | platform_device_register(&pdc_device); |
592 | 664 | ||
@@ -1013,6 +1085,89 @@ err_dup_modedb: | |||
1013 | } | 1085 | } |
1014 | 1086 | ||
1015 | /* -------------------------------------------------------------------- | 1087 | /* -------------------------------------------------------------------- |
1088 | * SSC | ||
1089 | * -------------------------------------------------------------------- */ | ||
1090 | static struct resource ssc0_resource[] = { | ||
1091 | PBMEM(0xffe01c00), | ||
1092 | IRQ(10), | ||
1093 | }; | ||
1094 | DEFINE_DEV(ssc, 0); | ||
1095 | DEV_CLK(pclk, ssc0, pba, 7); | ||
1096 | |||
1097 | static struct resource ssc1_resource[] = { | ||
1098 | PBMEM(0xffe02000), | ||
1099 | IRQ(11), | ||
1100 | }; | ||
1101 | DEFINE_DEV(ssc, 1); | ||
1102 | DEV_CLK(pclk, ssc1, pba, 8); | ||
1103 | |||
1104 | static struct resource ssc2_resource[] = { | ||
1105 | PBMEM(0xffe02400), | ||
1106 | IRQ(12), | ||
1107 | }; | ||
1108 | DEFINE_DEV(ssc, 2); | ||
1109 | DEV_CLK(pclk, ssc2, pba, 9); | ||
1110 | |||
1111 | struct platform_device *__init | ||
1112 | at32_add_device_ssc(unsigned int id, unsigned int flags) | ||
1113 | { | ||
1114 | struct platform_device *pdev; | ||
1115 | |||
1116 | switch (id) { | ||
1117 | case 0: | ||
1118 | pdev = &ssc0_device; | ||
1119 | if (flags & ATMEL_SSC_RF) | ||
1120 | select_peripheral(PA(21), PERIPH_A, 0); /* RF */ | ||
1121 | if (flags & ATMEL_SSC_RK) | ||
1122 | select_peripheral(PA(22), PERIPH_A, 0); /* RK */ | ||
1123 | if (flags & ATMEL_SSC_TK) | ||
1124 | select_peripheral(PA(23), PERIPH_A, 0); /* TK */ | ||
1125 | if (flags & ATMEL_SSC_TF) | ||
1126 | select_peripheral(PA(24), PERIPH_A, 0); /* TF */ | ||
1127 | if (flags & ATMEL_SSC_TD) | ||
1128 | select_peripheral(PA(25), PERIPH_A, 0); /* TD */ | ||
1129 | if (flags & ATMEL_SSC_RD) | ||
1130 | select_peripheral(PA(26), PERIPH_A, 0); /* RD */ | ||
1131 | break; | ||
1132 | case 1: | ||
1133 | pdev = &ssc1_device; | ||
1134 | if (flags & ATMEL_SSC_RF) | ||
1135 | select_peripheral(PA(0), PERIPH_B, 0); /* RF */ | ||
1136 | if (flags & ATMEL_SSC_RK) | ||
1137 | select_peripheral(PA(1), PERIPH_B, 0); /* RK */ | ||
1138 | if (flags & ATMEL_SSC_TK) | ||
1139 | select_peripheral(PA(2), PERIPH_B, 0); /* TK */ | ||
1140 | if (flags & ATMEL_SSC_TF) | ||
1141 | select_peripheral(PA(3), PERIPH_B, 0); /* TF */ | ||
1142 | if (flags & ATMEL_SSC_TD) | ||
1143 | select_peripheral(PA(4), PERIPH_B, 0); /* TD */ | ||
1144 | if (flags & ATMEL_SSC_RD) | ||
1145 | select_peripheral(PA(5), PERIPH_B, 0); /* RD */ | ||
1146 | break; | ||
1147 | case 2: | ||
1148 | pdev = &ssc2_device; | ||
1149 | if (flags & ATMEL_SSC_TD) | ||
1150 | select_peripheral(PB(13), PERIPH_A, 0); /* TD */ | ||
1151 | if (flags & ATMEL_SSC_RD) | ||
1152 | select_peripheral(PB(14), PERIPH_A, 0); /* RD */ | ||
1153 | if (flags & ATMEL_SSC_TK) | ||
1154 | select_peripheral(PB(15), PERIPH_A, 0); /* TK */ | ||
1155 | if (flags & ATMEL_SSC_TF) | ||
1156 | select_peripheral(PB(16), PERIPH_A, 0); /* TF */ | ||
1157 | if (flags & ATMEL_SSC_RF) | ||
1158 | select_peripheral(PB(17), PERIPH_A, 0); /* RF */ | ||
1159 | if (flags & ATMEL_SSC_RK) | ||
1160 | select_peripheral(PB(18), PERIPH_A, 0); /* RK */ | ||
1161 | break; | ||
1162 | default: | ||
1163 | return NULL; | ||
1164 | } | ||
1165 | |||
1166 | platform_device_register(pdev); | ||
1167 | return pdev; | ||
1168 | } | ||
1169 | |||
1170 | /* -------------------------------------------------------------------- | ||
1016 | * GCLK | 1171 | * GCLK |
1017 | * -------------------------------------------------------------------- */ | 1172 | * -------------------------------------------------------------------- */ |
1018 | static struct clk gclk0 = { | 1173 | static struct clk gclk0 = { |
@@ -1066,7 +1221,7 @@ struct clk *at32_clock_list[] = { | |||
1066 | &hsb_clk, | 1221 | &hsb_clk, |
1067 | &pba_clk, | 1222 | &pba_clk, |
1068 | &pbb_clk, | 1223 | &pbb_clk, |
1069 | &at32_sm_pclk, | 1224 | &at32_pm_pclk, |
1070 | &at32_intc0_pclk, | 1225 | &at32_intc0_pclk, |
1071 | &hmatrix_clk, | 1226 | &hmatrix_clk, |
1072 | &ebi_clk, | 1227 | &ebi_clk, |
@@ -1094,6 +1249,9 @@ struct clk *at32_clock_list[] = { | |||
1094 | &atmel_spi1_spi_clk, | 1249 | &atmel_spi1_spi_clk, |
1095 | &atmel_lcdfb0_hck1, | 1250 | &atmel_lcdfb0_hck1, |
1096 | &atmel_lcdfb0_pixclk, | 1251 | &atmel_lcdfb0_pixclk, |
1252 | &ssc0_pclk, | ||
1253 | &ssc1_pclk, | ||
1254 | &ssc2_pclk, | ||
1097 | &gclk0, | 1255 | &gclk0, |
1098 | &gclk1, | 1256 | &gclk1, |
1099 | &gclk2, | 1257 | &gclk2, |
@@ -1113,18 +1271,20 @@ void __init at32_portmux_init(void) | |||
1113 | 1271 | ||
1114 | void __init at32_clock_init(void) | 1272 | void __init at32_clock_init(void) |
1115 | { | 1273 | { |
1116 | struct at32_sm *sm = &system_manager; | ||
1117 | u32 cpu_mask = 0, hsb_mask = 0, pba_mask = 0, pbb_mask = 0; | 1274 | u32 cpu_mask = 0, hsb_mask = 0, pba_mask = 0, pbb_mask = 0; |
1118 | int i; | 1275 | int i; |
1119 | 1276 | ||
1120 | if (sm_readl(sm, PM_MCCTRL) & SM_BIT(PLLSEL)) | 1277 | if (pm_readl(MCCTRL) & PM_BIT(PLLSEL)) { |
1121 | main_clock = &pll0; | 1278 | main_clock = &pll0; |
1122 | else | 1279 | cpu_clk.parent = &pll0; |
1280 | } else { | ||
1123 | main_clock = &osc0; | 1281 | main_clock = &osc0; |
1282 | cpu_clk.parent = &osc0; | ||
1283 | } | ||
1124 | 1284 | ||
1125 | if (sm_readl(sm, PM_PLL0) & SM_BIT(PLLOSC)) | 1285 | if (pm_readl(PLL0) & PM_BIT(PLLOSC)) |
1126 | pll0.parent = &osc1; | 1286 | pll0.parent = &osc1; |
1127 | if (sm_readl(sm, PM_PLL1) & SM_BIT(PLLOSC)) | 1287 | if (pm_readl(PLL1) & PM_BIT(PLLOSC)) |
1128 | pll1.parent = &osc1; | 1288 | pll1.parent = &osc1; |
1129 | 1289 | ||
1130 | genclk_init_parent(&gclk0); | 1290 | genclk_init_parent(&gclk0); |
@@ -1157,8 +1317,8 @@ void __init at32_clock_init(void) | |||
1157 | pbb_mask |= 1 << clk->index; | 1317 | pbb_mask |= 1 << clk->index; |
1158 | } | 1318 | } |
1159 | 1319 | ||
1160 | sm_writel(sm, PM_CPU_MASK, cpu_mask); | 1320 | pm_writel(CPU_MASK, cpu_mask); |
1161 | sm_writel(sm, PM_HSB_MASK, hsb_mask); | 1321 | pm_writel(HSB_MASK, hsb_mask); |
1162 | sm_writel(sm, PM_PBA_MASK, pba_mask); | 1322 | pm_writel(PBA_MASK, pba_mask); |
1163 | sm_writel(sm, PM_PBB_MASK, pbb_mask); | 1323 | pm_writel(PBB_MASK, pbb_mask); |
1164 | } | 1324 | } |