aboutsummaryrefslogtreecommitdiffstats
path: root/arch/avr32/mach-at32ap/at32ap7000.c
diff options
context:
space:
mode:
authorHaavard Skinnemoen <hskinnemoen@atmel.com>2007-06-04 06:58:30 -0400
committerHaavard Skinnemoen <hskinnemoen@atmel.com>2007-07-18 14:45:51 -0400
commit7a5b80590772c29bba1d54d3685622177d6fe39f (patch)
treed643198d28f6578febc2bcc0317a0681f951e62b /arch/avr32/mach-at32ap/at32ap7000.c
parentc6083cd61b5a64a1c73d1634744382f54cb99595 (diff)
[AVR32] Split SM device into PM, RTC, WDT and EIC
Split the SM platform device into separate platform devices for PM, RTC, WDT and EIC. This is more correct according to the documentation and allows us to simplify the code a little. Also turn the EIC driver into a real platform driver. Signed-off-by: Haavard Skinnemoen <hskinnemoen@atmel.com> Acked-by: Hans-Christian Egtvedt <hcegtvedt@atmel.com>
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}