aboutsummaryrefslogtreecommitdiffstats
path: root/arch/avr32/mach-at32ap/at32ap7000.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/avr32/mach-at32ap/at32ap7000.c')
-rw-r--r--arch/avr32/mach-at32ap/at32ap7000.c213
1 files changed, 124 insertions, 89 deletions
diff --git a/arch/avr32/mach-at32ap/at32ap7000.c b/arch/avr32/mach-at32ap/at32ap7000.c
index 4dda42d3f6d5..5faa97e5ab16 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
97static DEFINE_SPINLOCK(pm_lock);
98
91unsigned long at32ap7000_osc_rates[3] = { 99unsigned 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,104 @@ static unsigned long bus_clk_get_rate(struct clk *clk, unsigned int shift)
187 195
188static void cpu_clk_mode(struct clk *clk, int enabled) 196static 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
204static unsigned long cpu_clk_get_rate(struct clk *clk) 211static 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
215static void hsb_clk_mode(struct clk *clk, int enabled) 222static void hsb_clk_mode(struct clk *clk, int enabled)
216{ 223{
217 struct at32_sm *sm = &system_manager;
218 unsigned long flags; 224 unsigned long flags;
219 u32 mask; 225 u32 mask;
220 226
221 spin_lock_irqsave(&sm->lock, flags); 227 spin_lock_irqsave(&pm_lock, flags);
222 mask = sm_readl(sm, PM_HSB_MASK); 228 mask = pm_readl(HSB_MASK);
223 if (enabled) 229 if (enabled)
224 mask |= 1 << clk->index; 230 mask |= 1 << clk->index;
225 else 231 else
226 mask &= ~(1 << clk->index); 232 mask &= ~(1 << clk->index);
227 sm_writel(sm, PM_HSB_MASK, mask); 233 pm_writel(HSB_MASK, mask);
228 spin_unlock_irqrestore(&sm->lock, flags); 234 spin_unlock_irqrestore(&pm_lock, flags);
229} 235}
230 236
231static unsigned long hsb_clk_get_rate(struct clk *clk) 237static unsigned long hsb_clk_get_rate(struct clk *clk)
232{ 238{
233 unsigned long cksel, shift = 0; 239 unsigned long cksel, shift = 0;
234 240
235 cksel = sm_readl(&system_manager, PM_CKSEL); 241 cksel = pm_readl(CKSEL);
236 if (cksel & SM_BIT(HSBDIV)) 242 if (cksel & PM_BIT(HSBDIV))
237 shift = SM_BFEXT(HSBSEL, cksel) + 1; 243 shift = PM_BFEXT(HSBSEL, cksel) + 1;
238 244
239 return bus_clk_get_rate(clk, shift); 245 return bus_clk_get_rate(clk, shift);
240} 246}
241 247
242static void pba_clk_mode(struct clk *clk, int enabled) 248static void pba_clk_mode(struct clk *clk, int enabled)
243{ 249{
244 struct at32_sm *sm = &system_manager;
245 unsigned long flags; 250 unsigned long flags;
246 u32 mask; 251 u32 mask;
247 252
248 spin_lock_irqsave(&sm->lock, flags); 253 spin_lock_irqsave(&pm_lock, flags);
249 mask = sm_readl(sm, PM_PBA_MASK); 254 mask = pm_readl(PBA_MASK);
250 if (enabled) 255 if (enabled)
251 mask |= 1 << clk->index; 256 mask |= 1 << clk->index;
252 else 257 else
253 mask &= ~(1 << clk->index); 258 mask &= ~(1 << clk->index);
254 sm_writel(sm, PM_PBA_MASK, mask); 259 pm_writel(PBA_MASK, mask);
255 spin_unlock_irqrestore(&sm->lock, flags); 260 spin_unlock_irqrestore(&pm_lock, flags);
256} 261}
257 262
258static unsigned long pba_clk_get_rate(struct clk *clk) 263static unsigned long pba_clk_get_rate(struct clk *clk)
259{ 264{
260 unsigned long cksel, shift = 0; 265 unsigned long cksel, shift = 0;
261 266
262 cksel = sm_readl(&system_manager, PM_CKSEL); 267 cksel = pm_readl(CKSEL);
263 if (cksel & SM_BIT(PBADIV)) 268 if (cksel & PM_BIT(PBADIV))
264 shift = SM_BFEXT(PBASEL, cksel) + 1; 269 shift = PM_BFEXT(PBASEL, cksel) + 1;
265 270
266 return bus_clk_get_rate(clk, shift); 271 return bus_clk_get_rate(clk, shift);
267} 272}
268 273
269static void pbb_clk_mode(struct clk *clk, int enabled) 274static void pbb_clk_mode(struct clk *clk, int enabled)
270{ 275{
271 struct at32_sm *sm = &system_manager;
272 unsigned long flags; 276 unsigned long flags;
273 u32 mask; 277 u32 mask;
274 278
275 spin_lock_irqsave(&sm->lock, flags); 279 spin_lock_irqsave(&pm_lock, flags);
276 mask = sm_readl(sm, PM_PBB_MASK); 280 mask = pm_readl(PBB_MASK);
277 if (enabled) 281 if (enabled)
278 mask |= 1 << clk->index; 282 mask |= 1 << clk->index;
279 else 283 else
280 mask &= ~(1 << clk->index); 284 mask &= ~(1 << clk->index);
281 sm_writel(sm, PM_PBB_MASK, mask); 285 pm_writel(PBB_MASK, mask);
282 spin_unlock_irqrestore(&sm->lock, flags); 286 spin_unlock_irqrestore(&pm_lock, flags);
283} 287}
284 288
285static unsigned long pbb_clk_get_rate(struct clk *clk) 289static unsigned long pbb_clk_get_rate(struct clk *clk)
286{ 290{
287 unsigned long cksel, shift = 0; 291 unsigned long cksel, shift = 0;
288 292
289 cksel = sm_readl(&system_manager, PM_CKSEL); 293 cksel = pm_readl(CKSEL);
290 if (cksel & SM_BIT(PBBDIV)) 294 if (cksel & PM_BIT(PBBDIV))
291 shift = SM_BFEXT(PBBSEL, cksel) + 1; 295 shift = PM_BFEXT(PBBSEL, cksel) + 1;
292 296
293 return bus_clk_get_rate(clk, shift); 297 return bus_clk_get_rate(clk, shift);
294} 298}
@@ -327,12 +331,12 @@ static void genclk_mode(struct clk *clk, int enabled)
327{ 331{
328 u32 control; 332 u32 control;
329 333
330 control = sm_readl(&system_manager, PM_GCCTRL + 4 * clk->index); 334 control = pm_readl(GCCTRL(clk->index));
331 if (enabled) 335 if (enabled)
332 control |= SM_BIT(CEN); 336 control |= PM_BIT(CEN);
333 else 337 else
334 control &= ~SM_BIT(CEN); 338 control &= ~PM_BIT(CEN);
335 sm_writel(&system_manager, PM_GCCTRL + 4 * clk->index, control); 339 pm_writel(GCCTRL(clk->index), control);
336} 340}
337 341
338static unsigned long genclk_get_rate(struct clk *clk) 342static unsigned long genclk_get_rate(struct clk *clk)
@@ -340,9 +344,9 @@ static unsigned long genclk_get_rate(struct clk *clk)
340 u32 control; 344 u32 control;
341 unsigned long div = 1; 345 unsigned long div = 1;
342 346
343 control = sm_readl(&system_manager, PM_GCCTRL + 4 * clk->index); 347 control = pm_readl(GCCTRL(clk->index));
344 if (control & SM_BIT(DIVEN)) 348 if (control & PM_BIT(DIVEN))
345 div = 2 * (SM_BFEXT(DIV, control) + 1); 349 div = 2 * (PM_BFEXT(DIV, control) + 1);
346 350
347 return clk->parent->get_rate(clk->parent) / div; 351 return clk->parent->get_rate(clk->parent) / div;
348} 352}
@@ -353,23 +357,22 @@ static long genclk_set_rate(struct clk *clk, unsigned long rate, int apply)
353 unsigned long parent_rate, actual_rate, div; 357 unsigned long parent_rate, actual_rate, div;
354 358
355 parent_rate = clk->parent->get_rate(clk->parent); 359 parent_rate = clk->parent->get_rate(clk->parent);
356 control = sm_readl(&system_manager, PM_GCCTRL + 4 * clk->index); 360 control = pm_readl(GCCTRL(clk->index));
357 361
358 if (rate > 3 * parent_rate / 4) { 362 if (rate > 3 * parent_rate / 4) {
359 actual_rate = parent_rate; 363 actual_rate = parent_rate;
360 control &= ~SM_BIT(DIVEN); 364 control &= ~PM_BIT(DIVEN);
361 } else { 365 } else {
362 div = (parent_rate + rate) / (2 * rate) - 1; 366 div = (parent_rate + rate) / (2 * rate) - 1;
363 control = SM_BFINS(DIV, div, control) | SM_BIT(DIVEN); 367 control = PM_BFINS(DIV, div, control) | PM_BIT(DIVEN);
364 actual_rate = parent_rate / (2 * (div + 1)); 368 actual_rate = parent_rate / (2 * (div + 1));
365 } 369 }
366 370
367 printk("clk %s: new rate %lu (actual rate %lu)\n", 371 dev_dbg(clk->dev, "clk %s: new rate %lu (actual rate %lu)\n",
368 clk->name, rate, actual_rate); 372 clk->name, rate, actual_rate);
369 373
370 if (apply) 374 if (apply)
371 sm_writel(&system_manager, PM_GCCTRL + 4 * clk->index, 375 pm_writel(GCCTRL(clk->index), control);
372 control);
373 376
374 return actual_rate; 377 return actual_rate;
375} 378}
@@ -378,24 +381,24 @@ int genclk_set_parent(struct clk *clk, struct clk *parent)
378{ 381{
379 u32 control; 382 u32 control;
380 383
381 printk("clk %s: new parent %s (was %s)\n", 384 dev_dbg(clk->dev, "clk %s: new parent %s (was %s)\n",
382 clk->name, parent->name, clk->parent->name); 385 clk->name, parent->name, clk->parent->name);
383 386
384 control = sm_readl(&system_manager, PM_GCCTRL + 4 * clk->index); 387 control = pm_readl(GCCTRL(clk->index));
385 388
386 if (parent == &osc1 || parent == &pll1) 389 if (parent == &osc1 || parent == &pll1)
387 control |= SM_BIT(OSCSEL); 390 control |= PM_BIT(OSCSEL);
388 else if (parent == &osc0 || parent == &pll0) 391 else if (parent == &osc0 || parent == &pll0)
389 control &= ~SM_BIT(OSCSEL); 392 control &= ~PM_BIT(OSCSEL);
390 else 393 else
391 return -EINVAL; 394 return -EINVAL;
392 395
393 if (parent == &pll0 || parent == &pll1) 396 if (parent == &pll0 || parent == &pll1)
394 control |= SM_BIT(PLLSEL); 397 control |= PM_BIT(PLLSEL);
395 else 398 else
396 control &= ~SM_BIT(PLLSEL); 399 control &= ~PM_BIT(PLLSEL);
397 400
398 sm_writel(&system_manager, PM_GCCTRL + 4 * clk->index, control); 401 pm_writel(GCCTRL(clk->index), control);
399 clk->parent = parent; 402 clk->parent = parent;
400 403
401 return 0; 404 return 0;
@@ -408,11 +411,11 @@ static void __init genclk_init_parent(struct clk *clk)
408 411
409 BUG_ON(clk->index > 7); 412 BUG_ON(clk->index > 7);
410 413
411 control = sm_readl(&system_manager, PM_GCCTRL + 4 * clk->index); 414 control = pm_readl(GCCTRL(clk->index));
412 if (control & SM_BIT(OSCSEL)) 415 if (control & PM_BIT(OSCSEL))
413 parent = (control & SM_BIT(PLLSEL)) ? &pll1 : &osc1; 416 parent = (control & PM_BIT(PLLSEL)) ? &pll1 : &osc1;
414 else 417 else
415 parent = (control & SM_BIT(PLLSEL)) ? &pll0 : &osc0; 418 parent = (control & PM_BIT(PLLSEL)) ? &pll0 : &osc0;
416 419
417 clk->parent = parent; 420 clk->parent = parent;
418} 421}
@@ -420,21 +423,53 @@ static void __init genclk_init_parent(struct clk *clk)
420/* -------------------------------------------------------------------- 423/* --------------------------------------------------------------------
421 * System peripherals 424 * System peripherals
422 * -------------------------------------------------------------------- */ 425 * -------------------------------------------------------------------- */
423static struct resource sm_resource[] = { 426static struct resource at32_pm0_resource[] = {
424 PBMEM(0xfff00000), 427 {
425 NAMED_IRQ(19, "eim"), 428 .start = 0xfff00000,
426 NAMED_IRQ(20, "pm"), 429 .end = 0xfff0007f,
427 NAMED_IRQ(21, "rtc"), 430 .flags = IORESOURCE_MEM,
431 },
432 IRQ(20),
428}; 433};
429struct platform_device at32_sm_device = { 434
430 .name = "sm", 435static struct resource at32ap700x_rtc0_resource[] = {
431 .id = 0, 436 {
432 .resource = sm_resource, 437 .start = 0xfff00080,
433 .num_resources = ARRAY_SIZE(sm_resource), 438 .end = 0xfff000af,
439 .flags = IORESOURCE_MEM,
440 },
441 IRQ(21),
434}; 442};
435static struct clk at32_sm_pclk = { 443
444static struct resource at32_wdt0_resource[] = {
445 {
446 .start = 0xfff000b0,
447 .end = 0xfff000bf,
448 .flags = IORESOURCE_MEM,
449 },
450};
451
452static struct resource at32_eic0_resource[] = {
453 {
454 .start = 0xfff00100,
455 .end = 0xfff0013f,
456 .flags = IORESOURCE_MEM,
457 },
458 IRQ(19),
459};
460
461DEFINE_DEV(at32_pm, 0);
462DEFINE_DEV(at32ap700x_rtc, 0);
463DEFINE_DEV(at32_wdt, 0);
464DEFINE_DEV(at32_eic, 0);
465
466/*
467 * Peripheral clock for PM, RTC, WDT and EIC. PM will ensure that this
468 * is always running.
469 */
470static struct clk at32_pm_pclk = {
436 .name = "pclk", 471 .name = "pclk",
437 .dev = &at32_sm_device.dev, 472 .dev = &at32_pm0_device.dev,
438 .parent = &pbb_clk, 473 .parent = &pbb_clk,
439 .mode = pbb_clk_mode, 474 .mode = pbb_clk_mode,
440 .get_rate = pbb_clk_get_rate, 475 .get_rate = pbb_clk_get_rate,
@@ -583,10 +618,11 @@ DEV_CLK(mck, pio4, pba, 14);
583 618
584void __init at32_add_system_devices(void) 619void __init at32_add_system_devices(void)
585{ 620{
586 system_manager.eim_first_irq = EIM_IRQ_BASE; 621 platform_device_register(&at32_pm0_device);
587
588 platform_device_register(&at32_sm_device);
589 platform_device_register(&at32_intc0_device); 622 platform_device_register(&at32_intc0_device);
623 platform_device_register(&at32ap700x_rtc0_device);
624 platform_device_register(&at32_wdt0_device);
625 platform_device_register(&at32_eic0_device);
590 platform_device_register(&smc0_device); 626 platform_device_register(&smc0_device);
591 platform_device_register(&pdc_device); 627 platform_device_register(&pdc_device);
592 628
@@ -1066,7 +1102,7 @@ struct clk *at32_clock_list[] = {
1066 &hsb_clk, 1102 &hsb_clk,
1067 &pba_clk, 1103 &pba_clk,
1068 &pbb_clk, 1104 &pbb_clk,
1069 &at32_sm_pclk, 1105 &at32_pm_pclk,
1070 &at32_intc0_pclk, 1106 &at32_intc0_pclk,
1071 &hmatrix_clk, 1107 &hmatrix_clk,
1072 &ebi_clk, 1108 &ebi_clk,
@@ -1113,18 +1149,17 @@ void __init at32_portmux_init(void)
1113 1149
1114void __init at32_clock_init(void) 1150void __init at32_clock_init(void)
1115{ 1151{
1116 struct at32_sm *sm = &system_manager;
1117 u32 cpu_mask = 0, hsb_mask = 0, pba_mask = 0, pbb_mask = 0; 1152 u32 cpu_mask = 0, hsb_mask = 0, pba_mask = 0, pbb_mask = 0;
1118 int i; 1153 int i;
1119 1154
1120 if (sm_readl(sm, PM_MCCTRL) & SM_BIT(PLLSEL)) 1155 if (pm_readl(MCCTRL) & PM_BIT(PLLSEL))
1121 main_clock = &pll0; 1156 main_clock = &pll0;
1122 else 1157 else
1123 main_clock = &osc0; 1158 main_clock = &osc0;
1124 1159
1125 if (sm_readl(sm, PM_PLL0) & SM_BIT(PLLOSC)) 1160 if (pm_readl(PLL0) & PM_BIT(PLLOSC))
1126 pll0.parent = &osc1; 1161 pll0.parent = &osc1;
1127 if (sm_readl(sm, PM_PLL1) & SM_BIT(PLLOSC)) 1162 if (pm_readl(PLL1) & PM_BIT(PLLOSC))
1128 pll1.parent = &osc1; 1163 pll1.parent = &osc1;
1129 1164
1130 genclk_init_parent(&gclk0); 1165 genclk_init_parent(&gclk0);
@@ -1157,8 +1192,8 @@ void __init at32_clock_init(void)
1157 pbb_mask |= 1 << clk->index; 1192 pbb_mask |= 1 << clk->index;
1158 } 1193 }
1159 1194
1160 sm_writel(sm, PM_CPU_MASK, cpu_mask); 1195 pm_writel(CPU_MASK, cpu_mask);
1161 sm_writel(sm, PM_HSB_MASK, hsb_mask); 1196 pm_writel(HSB_MASK, hsb_mask);
1162 sm_writel(sm, PM_PBA_MASK, pba_mask); 1197 pm_writel(PBA_MASK, pba_mask);
1163 sm_writel(sm, PM_PBB_MASK, pbb_mask); 1198 pm_writel(PBB_MASK, pbb_mask);
1164} 1199}