diff options
Diffstat (limited to 'arch/avr32/mach-at32ap')
-rw-r--r-- | arch/avr32/mach-at32ap/Kconfig | 31 | ||||
-rw-r--r-- | arch/avr32/mach-at32ap/Makefile | 1 | ||||
-rw-r--r-- | arch/avr32/mach-at32ap/at32ap7000.c | 70 | ||||
-rw-r--r-- | arch/avr32/mach-at32ap/hmatrix.h | 182 | ||||
-rw-r--r-- | arch/avr32/mach-at32ap/hsmc.c | 23 | ||||
-rw-r--r-- | arch/avr32/mach-at32ap/time-tc.c | 218 |
6 files changed, 524 insertions, 1 deletions
diff --git a/arch/avr32/mach-at32ap/Kconfig b/arch/avr32/mach-at32ap/Kconfig new file mode 100644 index 000000000000..eb307838457b --- /dev/null +++ b/arch/avr32/mach-at32ap/Kconfig | |||
@@ -0,0 +1,31 @@ | |||
1 | if PLATFORM_AT32AP | ||
2 | |||
3 | menu "Atmel AVR32 AP options" | ||
4 | |||
5 | choice | ||
6 | prompt "AT32AP7000 static memory bus width" | ||
7 | depends on CPU_AT32AP7000 | ||
8 | default AP7000_16_BIT_SMC | ||
9 | help | ||
10 | Define the width of the AP7000 external static memory interface. | ||
11 | This is used to determine how to mangle the address and/or data | ||
12 | when doing little-endian port access. | ||
13 | |||
14 | The current code can only support a single external memory bus | ||
15 | width for all chip selects, excluding the flash (which is using | ||
16 | raw access and is thus not affected by any of this.) | ||
17 | |||
18 | config AP7000_32_BIT_SMC | ||
19 | bool "32 bit" | ||
20 | |||
21 | config AP7000_16_BIT_SMC | ||
22 | bool "16 bit" | ||
23 | |||
24 | config AP7000_8_BIT_SMC | ||
25 | bool "8 bit" | ||
26 | |||
27 | endchoice | ||
28 | |||
29 | endmenu | ||
30 | |||
31 | endif # PLATFORM_AT32AP | ||
diff --git a/arch/avr32/mach-at32ap/Makefile b/arch/avr32/mach-at32ap/Makefile index b21bea9af8b1..f1d395724ac6 100644 --- a/arch/avr32/mach-at32ap/Makefile +++ b/arch/avr32/mach-at32ap/Makefile | |||
@@ -1,2 +1,3 @@ | |||
1 | obj-y += at32ap.o clock.o intc.o extint.o pio.o hsmc.o | 1 | obj-y += at32ap.o clock.o intc.o extint.o pio.o hsmc.o |
2 | obj-$(CONFIG_CPU_AT32AP7000) += at32ap7000.o | 2 | obj-$(CONFIG_CPU_AT32AP7000) += at32ap7000.o |
3 | obj-$(CONFIG_CPU_AT32AP7000) += time-tc.o | ||
diff --git a/arch/avr32/mach-at32ap/at32ap7000.c b/arch/avr32/mach-at32ap/at32ap7000.c index 472703f90c22..56db45b99a0f 100644 --- a/arch/avr32/mach-at32ap/at32ap7000.c +++ b/arch/avr32/mach-at32ap/at32ap7000.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <asm/arch/sm.h> | 18 | #include <asm/arch/sm.h> |
19 | 19 | ||
20 | #include "clock.h" | 20 | #include "clock.h" |
21 | #include "hmatrix.h" | ||
21 | #include "pio.h" | 22 | #include "pio.h" |
22 | #include "sm.h" | 23 | #include "sm.h" |
23 | 24 | ||
@@ -416,7 +417,15 @@ struct platform_device at32_sm_device = { | |||
416 | .resource = sm_resource, | 417 | .resource = sm_resource, |
417 | .num_resources = ARRAY_SIZE(sm_resource), | 418 | .num_resources = ARRAY_SIZE(sm_resource), |
418 | }; | 419 | }; |
419 | DEV_CLK(pclk, at32_sm, pbb, 0); | 420 | static struct clk at32_sm_pclk = { |
421 | .name = "pclk", | ||
422 | .dev = &at32_sm_device.dev, | ||
423 | .parent = &pbb_clk, | ||
424 | .mode = pbb_clk_mode, | ||
425 | .get_rate = pbb_clk_get_rate, | ||
426 | .users = 1, | ||
427 | .index = 0, | ||
428 | }; | ||
420 | 429 | ||
421 | static struct resource intc0_resource[] = { | 430 | static struct resource intc0_resource[] = { |
422 | PBMEM(0xfff00400), | 431 | PBMEM(0xfff00400), |
@@ -442,6 +451,7 @@ static struct clk hramc_clk = { | |||
442 | .mode = hsb_clk_mode, | 451 | .mode = hsb_clk_mode, |
443 | .get_rate = hsb_clk_get_rate, | 452 | .get_rate = hsb_clk_get_rate, |
444 | .users = 1, | 453 | .users = 1, |
454 | .index = 3, | ||
445 | }; | 455 | }; |
446 | 456 | ||
447 | static struct resource smc0_resource[] = { | 457 | static struct resource smc0_resource[] = { |
@@ -467,6 +477,57 @@ static struct clk pico_clk = { | |||
467 | }; | 477 | }; |
468 | 478 | ||
469 | /* -------------------------------------------------------------------- | 479 | /* -------------------------------------------------------------------- |
480 | * HMATRIX | ||
481 | * -------------------------------------------------------------------- */ | ||
482 | |||
483 | static struct clk hmatrix_clk = { | ||
484 | .name = "hmatrix_clk", | ||
485 | .parent = &pbb_clk, | ||
486 | .mode = pbb_clk_mode, | ||
487 | .get_rate = pbb_clk_get_rate, | ||
488 | .index = 2, | ||
489 | .users = 1, | ||
490 | }; | ||
491 | #define HMATRIX_BASE ((void __iomem *)0xfff00800) | ||
492 | |||
493 | #define hmatrix_readl(reg) \ | ||
494 | __raw_readl((HMATRIX_BASE) + HMATRIX_##reg) | ||
495 | #define hmatrix_writel(reg,value) \ | ||
496 | __raw_writel((value), (HMATRIX_BASE) + HMATRIX_##reg) | ||
497 | |||
498 | /* | ||
499 | * Set bits in the HMATRIX Special Function Register (SFR) used by the | ||
500 | * External Bus Interface (EBI). This can be used to enable special | ||
501 | * features like CompactFlash support, NAND Flash support, etc. on | ||
502 | * certain chipselects. | ||
503 | */ | ||
504 | static inline void set_ebi_sfr_bits(u32 mask) | ||
505 | { | ||
506 | u32 sfr; | ||
507 | |||
508 | clk_enable(&hmatrix_clk); | ||
509 | sfr = hmatrix_readl(SFR4); | ||
510 | sfr |= mask; | ||
511 | hmatrix_writel(SFR4, sfr); | ||
512 | clk_disable(&hmatrix_clk); | ||
513 | } | ||
514 | |||
515 | /* -------------------------------------------------------------------- | ||
516 | * System Timer/Counter (TC) | ||
517 | * -------------------------------------------------------------------- */ | ||
518 | static struct resource at32_systc0_resource[] = { | ||
519 | PBMEM(0xfff00c00), | ||
520 | IRQ(22), | ||
521 | }; | ||
522 | struct platform_device at32_systc0_device = { | ||
523 | .name = "systc", | ||
524 | .id = 0, | ||
525 | .resource = at32_systc0_resource, | ||
526 | .num_resources = ARRAY_SIZE(at32_systc0_resource), | ||
527 | }; | ||
528 | DEV_CLK(pclk, at32_systc0, pbb, 3); | ||
529 | |||
530 | /* -------------------------------------------------------------------- | ||
470 | * PIO | 531 | * PIO |
471 | * -------------------------------------------------------------------- */ | 532 | * -------------------------------------------------------------------- */ |
472 | 533 | ||
@@ -514,6 +575,8 @@ void __init at32_add_system_devices(void) | |||
514 | platform_device_register(&smc0_device); | 575 | platform_device_register(&smc0_device); |
515 | platform_device_register(&pdc_device); | 576 | platform_device_register(&pdc_device); |
516 | 577 | ||
578 | platform_device_register(&at32_systc0_device); | ||
579 | |||
517 | platform_device_register(&pio0_device); | 580 | platform_device_register(&pio0_device); |
518 | platform_device_register(&pio1_device); | 581 | platform_device_register(&pio1_device); |
519 | platform_device_register(&pio2_device); | 582 | platform_device_register(&pio2_device); |
@@ -950,6 +1013,7 @@ struct clk *at32_clock_list[] = { | |||
950 | &pbb_clk, | 1013 | &pbb_clk, |
951 | &at32_sm_pclk, | 1014 | &at32_sm_pclk, |
952 | &at32_intc0_pclk, | 1015 | &at32_intc0_pclk, |
1016 | &hmatrix_clk, | ||
953 | &ebi_clk, | 1017 | &ebi_clk, |
954 | &hramc_clk, | 1018 | &hramc_clk, |
955 | &smc0_pclk, | 1019 | &smc0_pclk, |
@@ -962,6 +1026,7 @@ struct clk *at32_clock_list[] = { | |||
962 | &pio2_mck, | 1026 | &pio2_mck, |
963 | &pio3_mck, | 1027 | &pio3_mck, |
964 | &pio4_mck, | 1028 | &pio4_mck, |
1029 | &at32_systc0_pclk, | ||
965 | &atmel_usart0_usart, | 1030 | &atmel_usart0_usart, |
966 | &atmel_usart1_usart, | 1031 | &atmel_usart1_usart, |
967 | &atmel_usart2_usart, | 1032 | &atmel_usart2_usart, |
@@ -1024,6 +1089,9 @@ void __init at32_clock_init(void) | |||
1024 | for (i = 0; i < ARRAY_SIZE(at32_clock_list); i++) { | 1089 | for (i = 0; i < ARRAY_SIZE(at32_clock_list); i++) { |
1025 | struct clk *clk = at32_clock_list[i]; | 1090 | struct clk *clk = at32_clock_list[i]; |
1026 | 1091 | ||
1092 | if (clk->users == 0) | ||
1093 | continue; | ||
1094 | |||
1027 | if (clk->mode == &cpu_clk_mode) | 1095 | if (clk->mode == &cpu_clk_mode) |
1028 | cpu_mask |= 1 << clk->index; | 1096 | cpu_mask |= 1 << clk->index; |
1029 | else if (clk->mode == &hsb_clk_mode) | 1097 | else if (clk->mode == &hsb_clk_mode) |
diff --git a/arch/avr32/mach-at32ap/hmatrix.h b/arch/avr32/mach-at32ap/hmatrix.h new file mode 100644 index 000000000000..d10bfb60d68d --- /dev/null +++ b/arch/avr32/mach-at32ap/hmatrix.h | |||
@@ -0,0 +1,182 @@ | |||
1 | /* | ||
2 | * Register definitions for High-Speed Bus Matrix | ||
3 | */ | ||
4 | #ifndef __HMATRIX_H | ||
5 | #define __HMATRIX_H | ||
6 | |||
7 | /* HMATRIX register offsets */ | ||
8 | #define HMATRIX_MCFG0 0x0000 | ||
9 | #define HMATRIX_MCFG1 0x0004 | ||
10 | #define HMATRIX_MCFG2 0x0008 | ||
11 | #define HMATRIX_MCFG3 0x000c | ||
12 | #define HMATRIX_MCFG4 0x0010 | ||
13 | #define HMATRIX_MCFG5 0x0014 | ||
14 | #define HMATRIX_MCFG6 0x0018 | ||
15 | #define HMATRIX_MCFG7 0x001c | ||
16 | #define HMATRIX_MCFG8 0x0020 | ||
17 | #define HMATRIX_MCFG9 0x0024 | ||
18 | #define HMATRIX_MCFG10 0x0028 | ||
19 | #define HMATRIX_MCFG11 0x002c | ||
20 | #define HMATRIX_MCFG12 0x0030 | ||
21 | #define HMATRIX_MCFG13 0x0034 | ||
22 | #define HMATRIX_MCFG14 0x0038 | ||
23 | #define HMATRIX_MCFG15 0x003c | ||
24 | #define HMATRIX_SCFG0 0x0040 | ||
25 | #define HMATRIX_SCFG1 0x0044 | ||
26 | #define HMATRIX_SCFG2 0x0048 | ||
27 | #define HMATRIX_SCFG3 0x004c | ||
28 | #define HMATRIX_SCFG4 0x0050 | ||
29 | #define HMATRIX_SCFG5 0x0054 | ||
30 | #define HMATRIX_SCFG6 0x0058 | ||
31 | #define HMATRIX_SCFG7 0x005c | ||
32 | #define HMATRIX_SCFG8 0x0060 | ||
33 | #define HMATRIX_SCFG9 0x0064 | ||
34 | #define HMATRIX_SCFG10 0x0068 | ||
35 | #define HMATRIX_SCFG11 0x006c | ||
36 | #define HMATRIX_SCFG12 0x0070 | ||
37 | #define HMATRIX_SCFG13 0x0074 | ||
38 | #define HMATRIX_SCFG14 0x0078 | ||
39 | #define HMATRIX_SCFG15 0x007c | ||
40 | #define HMATRIX_PRAS0 0x0080 | ||
41 | #define HMATRIX_PRBS0 0x0084 | ||
42 | #define HMATRIX_PRAS1 0x0088 | ||
43 | #define HMATRIX_PRBS1 0x008c | ||
44 | #define HMATRIX_PRAS2 0x0090 | ||
45 | #define HMATRIX_PRBS2 0x0094 | ||
46 | #define HMATRIX_PRAS3 0x0098 | ||
47 | #define HMATRIX_PRBS3 0x009c | ||
48 | #define HMATRIX_PRAS4 0x00a0 | ||
49 | #define HMATRIX_PRBS4 0x00a4 | ||
50 | #define HMATRIX_PRAS5 0x00a8 | ||
51 | #define HMATRIX_PRBS5 0x00ac | ||
52 | #define HMATRIX_PRAS6 0x00b0 | ||
53 | #define HMATRIX_PRBS6 0x00b4 | ||
54 | #define HMATRIX_PRAS7 0x00b8 | ||
55 | #define HMATRIX_PRBS7 0x00bc | ||
56 | #define HMATRIX_PRAS8 0x00c0 | ||
57 | #define HMATRIX_PRBS8 0x00c4 | ||
58 | #define HMATRIX_PRAS9 0x00c8 | ||
59 | #define HMATRIX_PRBS9 0x00cc | ||
60 | #define HMATRIX_PRAS10 0x00d0 | ||
61 | #define HMATRIX_PRBS10 0x00d4 | ||
62 | #define HMATRIX_PRAS11 0x00d8 | ||
63 | #define HMATRIX_PRBS11 0x00dc | ||
64 | #define HMATRIX_PRAS12 0x00e0 | ||
65 | #define HMATRIX_PRBS12 0x00e4 | ||
66 | #define HMATRIX_PRAS13 0x00e8 | ||
67 | #define HMATRIX_PRBS13 0x00ec | ||
68 | #define HMATRIX_PRAS14 0x00f0 | ||
69 | #define HMATRIX_PRBS14 0x00f4 | ||
70 | #define HMATRIX_PRAS15 0x00f8 | ||
71 | #define HMATRIX_PRBS15 0x00fc | ||
72 | #define HMATRIX_MRCR 0x0100 | ||
73 | #define HMATRIX_SFR0 0x0110 | ||
74 | #define HMATRIX_SFR1 0x0114 | ||
75 | #define HMATRIX_SFR2 0x0118 | ||
76 | #define HMATRIX_SFR3 0x011c | ||
77 | #define HMATRIX_SFR4 0x0120 | ||
78 | #define HMATRIX_SFR5 0x0124 | ||
79 | #define HMATRIX_SFR6 0x0128 | ||
80 | #define HMATRIX_SFR7 0x012c | ||
81 | #define HMATRIX_SFR8 0x0130 | ||
82 | #define HMATRIX_SFR9 0x0134 | ||
83 | #define HMATRIX_SFR10 0x0138 | ||
84 | #define HMATRIX_SFR11 0x013c | ||
85 | #define HMATRIX_SFR12 0x0140 | ||
86 | #define HMATRIX_SFR13 0x0144 | ||
87 | #define HMATRIX_SFR14 0x0148 | ||
88 | #define HMATRIX_SFR15 0x014c | ||
89 | |||
90 | /* Bitfields in MCFGx */ | ||
91 | #define HMATRIX_ULBT_OFFSET 0 | ||
92 | #define HMATRIX_ULBT_SIZE 3 | ||
93 | |||
94 | /* Bitfields in SCFGx */ | ||
95 | #define HMATRIX_SLOT_CYCLE_OFFSET 0 | ||
96 | #define HMATRIX_SLOT_CYCLE_SIZE 8 | ||
97 | #define HMATRIX_DEFMSTR_TYPE_OFFSET 16 | ||
98 | #define HMATRIX_DEFMSTR_TYPE_SIZE 2 | ||
99 | #define HMATRIX_FIXED_DEFMSTR_OFFSET 18 | ||
100 | #define HMATRIX_FIXED_DEFMSTR_SIZE 4 | ||
101 | #define HMATRIX_ARBT_OFFSET 24 | ||
102 | #define HMATRIX_ARBT_SIZE 2 | ||
103 | |||
104 | /* Bitfields in PRASx */ | ||
105 | #define HMATRIX_M0PR_OFFSET 0 | ||
106 | #define HMATRIX_M0PR_SIZE 4 | ||
107 | #define HMATRIX_M1PR_OFFSET 4 | ||
108 | #define HMATRIX_M1PR_SIZE 4 | ||
109 | #define HMATRIX_M2PR_OFFSET 8 | ||
110 | #define HMATRIX_M2PR_SIZE 4 | ||
111 | #define HMATRIX_M3PR_OFFSET 12 | ||
112 | #define HMATRIX_M3PR_SIZE 4 | ||
113 | #define HMATRIX_M4PR_OFFSET 16 | ||
114 | #define HMATRIX_M4PR_SIZE 4 | ||
115 | #define HMATRIX_M5PR_OFFSET 20 | ||
116 | #define HMATRIX_M5PR_SIZE 4 | ||
117 | #define HMATRIX_M6PR_OFFSET 24 | ||
118 | #define HMATRIX_M6PR_SIZE 4 | ||
119 | #define HMATRIX_M7PR_OFFSET 28 | ||
120 | #define HMATRIX_M7PR_SIZE 4 | ||
121 | |||
122 | /* Bitfields in PRBSx */ | ||
123 | #define HMATRIX_M8PR_OFFSET 0 | ||
124 | #define HMATRIX_M8PR_SIZE 4 | ||
125 | #define HMATRIX_M9PR_OFFSET 4 | ||
126 | #define HMATRIX_M9PR_SIZE 4 | ||
127 | #define HMATRIX_M10PR_OFFSET 8 | ||
128 | #define HMATRIX_M10PR_SIZE 4 | ||
129 | #define HMATRIX_M11PR_OFFSET 12 | ||
130 | #define HMATRIX_M11PR_SIZE 4 | ||
131 | #define HMATRIX_M12PR_OFFSET 16 | ||
132 | #define HMATRIX_M12PR_SIZE 4 | ||
133 | #define HMATRIX_M13PR_OFFSET 20 | ||
134 | #define HMATRIX_M13PR_SIZE 4 | ||
135 | #define HMATRIX_M14PR_OFFSET 24 | ||
136 | #define HMATRIX_M14PR_SIZE 4 | ||
137 | #define HMATRIX_M15PR_OFFSET 28 | ||
138 | #define HMATRIX_M15PR_SIZE 4 | ||
139 | |||
140 | /* Bitfields in SFR4 */ | ||
141 | #define HMATRIX_CS1A_OFFSET 1 | ||
142 | #define HMATRIX_CS1A_SIZE 1 | ||
143 | #define HMATRIX_CS3A_OFFSET 3 | ||
144 | #define HMATRIX_CS3A_SIZE 1 | ||
145 | #define HMATRIX_CS4A_OFFSET 4 | ||
146 | #define HMATRIX_CS4A_SIZE 1 | ||
147 | #define HMATRIX_CS5A_OFFSET 5 | ||
148 | #define HMATRIX_CS5A_SIZE 1 | ||
149 | #define HMATRIX_DBPUC_OFFSET 8 | ||
150 | #define HMATRIX_DBPUC_SIZE 1 | ||
151 | |||
152 | /* Constants for ULBT */ | ||
153 | #define HMATRIX_ULBT_INFINITE 0 | ||
154 | #define HMATRIX_ULBT_SINGLE 1 | ||
155 | #define HMATRIX_ULBT_FOUR_BEAT 2 | ||
156 | #define HMATRIX_ULBT_EIGHT_BEAT 3 | ||
157 | #define HMATRIX_ULBT_SIXTEEN_BEAT 4 | ||
158 | |||
159 | /* Constants for DEFMSTR_TYPE */ | ||
160 | #define HMATRIX_DEFMSTR_TYPE_NO_DEFAULT 0 | ||
161 | #define HMATRIX_DEFMSTR_TYPE_LAST_DEFAULT 1 | ||
162 | #define HMATRIX_DEFMSTR_TYPE_FIXED_DEFAULT 2 | ||
163 | |||
164 | /* Constants for ARBT */ | ||
165 | #define HMATRIX_ARBT_ROUND_ROBIN 0 | ||
166 | #define HMATRIX_ARBT_FIXED_PRIORITY 1 | ||
167 | |||
168 | /* Bit manipulation macros */ | ||
169 | #define HMATRIX_BIT(name) \ | ||
170 | (1 << HMATRIX_##name##_OFFSET) | ||
171 | #define HMATRIX_BF(name,value) \ | ||
172 | (((value) & ((1 << HMATRIX_##name##_SIZE) - 1)) \ | ||
173 | << HMATRIX_##name##_OFFSET) | ||
174 | #define HMATRIX_BFEXT(name,value) \ | ||
175 | (((value) >> HMATRIX_##name##_OFFSET) \ | ||
176 | & ((1 << HMATRIX_##name##_SIZE) - 1)) | ||
177 | #define HMATRIX_BFINS(name,value,old) \ | ||
178 | (((old) & ~(((1 << HMATRIX_##name##_SIZE) - 1) \ | ||
179 | << HMATRIX_##name##_OFFSET)) \ | ||
180 | | HMATRIX_BF(name,value)) | ||
181 | |||
182 | #endif /* __HMATRIX_H */ | ||
diff --git a/arch/avr32/mach-at32ap/hsmc.c b/arch/avr32/mach-at32ap/hsmc.c index 7691721928a7..5e22a750632b 100644 --- a/arch/avr32/mach-at32ap/hsmc.c +++ b/arch/avr32/mach-at32ap/hsmc.c | |||
@@ -75,12 +75,35 @@ int smc_set_configuration(int cs, const struct smc_config *config) | |||
75 | return -EINVAL; | 75 | return -EINVAL; |
76 | } | 76 | } |
77 | 77 | ||
78 | switch (config->nwait_mode) { | ||
79 | case 0: | ||
80 | mode |= HSMC_BF(EXNW_MODE, HSMC_EXNW_MODE_DISABLED); | ||
81 | break; | ||
82 | case 1: | ||
83 | mode |= HSMC_BF(EXNW_MODE, HSMC_EXNW_MODE_RESERVED); | ||
84 | break; | ||
85 | case 2: | ||
86 | mode |= HSMC_BF(EXNW_MODE, HSMC_EXNW_MODE_FROZEN); | ||
87 | break; | ||
88 | case 3: | ||
89 | mode |= HSMC_BF(EXNW_MODE, HSMC_EXNW_MODE_READY); | ||
90 | break; | ||
91 | default: | ||
92 | return -EINVAL; | ||
93 | } | ||
94 | |||
95 | if (config->tdf_cycles) { | ||
96 | mode |= HSMC_BF(TDF_CYCLES, config->tdf_cycles); | ||
97 | } | ||
98 | |||
78 | if (config->nrd_controlled) | 99 | if (config->nrd_controlled) |
79 | mode |= HSMC_BIT(READ_MODE); | 100 | mode |= HSMC_BIT(READ_MODE); |
80 | if (config->nwe_controlled) | 101 | if (config->nwe_controlled) |
81 | mode |= HSMC_BIT(WRITE_MODE); | 102 | mode |= HSMC_BIT(WRITE_MODE); |
82 | if (config->byte_write) | 103 | if (config->byte_write) |
83 | mode |= HSMC_BIT(BAT); | 104 | mode |= HSMC_BIT(BAT); |
105 | if (config->tdf_mode) | ||
106 | mode |= HSMC_BIT(TDF_MODE); | ||
84 | 107 | ||
85 | pr_debug("smc cs%d: setup/%08x pulse/%08x cycle/%08x mode/%08x\n", | 108 | pr_debug("smc cs%d: setup/%08x pulse/%08x cycle/%08x mode/%08x\n", |
86 | cs, setup, pulse, cycle, mode); | 109 | cs, setup, pulse, cycle, mode); |
diff --git a/arch/avr32/mach-at32ap/time-tc.c b/arch/avr32/mach-at32ap/time-tc.c new file mode 100644 index 000000000000..e3070bdd4bb9 --- /dev/null +++ b/arch/avr32/mach-at32ap/time-tc.c | |||
@@ -0,0 +1,218 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2004-2007 Atmel Corporation | ||
3 | * | ||
4 | * Based on MIPS implementation arch/mips/kernel/time.c | ||
5 | * Copyright 2001 MontaVista Software Inc. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | */ | ||
11 | |||
12 | #include <linux/clk.h> | ||
13 | #include <linux/clocksource.h> | ||
14 | #include <linux/time.h> | ||
15 | #include <linux/module.h> | ||
16 | #include <linux/interrupt.h> | ||
17 | #include <linux/irq.h> | ||
18 | #include <linux/kernel_stat.h> | ||
19 | #include <linux/errno.h> | ||
20 | #include <linux/init.h> | ||
21 | #include <linux/profile.h> | ||
22 | #include <linux/sysdev.h> | ||
23 | #include <linux/err.h> | ||
24 | |||
25 | #include <asm/div64.h> | ||
26 | #include <asm/sysreg.h> | ||
27 | #include <asm/io.h> | ||
28 | #include <asm/sections.h> | ||
29 | |||
30 | #include <asm/arch/time.h> | ||
31 | |||
32 | /* how many counter cycles in a jiffy? */ | ||
33 | static u32 cycles_per_jiffy; | ||
34 | |||
35 | /* the count value for the next timer interrupt */ | ||
36 | static u32 expirelo; | ||
37 | |||
38 | /* the I/O registers of the TC module */ | ||
39 | static void __iomem *ioregs; | ||
40 | |||
41 | cycle_t read_cycle_count(void) | ||
42 | { | ||
43 | return (cycle_t)timer_read(ioregs, 0, CV); | ||
44 | } | ||
45 | |||
46 | struct clocksource clocksource_avr32 = { | ||
47 | .name = "avr32", | ||
48 | .rating = 342, | ||
49 | .read = read_cycle_count, | ||
50 | .mask = CLOCKSOURCE_MASK(16), | ||
51 | .shift = 16, | ||
52 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, | ||
53 | }; | ||
54 | |||
55 | static void avr32_timer_ack(void) | ||
56 | { | ||
57 | u16 count = expirelo; | ||
58 | |||
59 | /* Ack this timer interrupt and set the next one, use a u16 | ||
60 | * variable so it will wrap around correctly */ | ||
61 | count += cycles_per_jiffy; | ||
62 | expirelo = count; | ||
63 | timer_write(ioregs, 0, RC, expirelo); | ||
64 | |||
65 | /* Check to see if we have missed any timer interrupts */ | ||
66 | count = timer_read(ioregs, 0, CV); | ||
67 | if ((count - expirelo) < 0x7fff) { | ||
68 | expirelo = count + cycles_per_jiffy; | ||
69 | timer_write(ioregs, 0, RC, expirelo); | ||
70 | } | ||
71 | } | ||
72 | |||
73 | u32 avr32_hpt_read(void) | ||
74 | { | ||
75 | return timer_read(ioregs, 0, CV); | ||
76 | } | ||
77 | |||
78 | static int avr32_timer_calc_div_and_set_jiffies(struct clk *pclk) | ||
79 | { | ||
80 | unsigned int cycles_max = (clocksource_avr32.mask + 1) / 2; | ||
81 | unsigned int divs[] = { 4, 8, 16, 32 }; | ||
82 | int divs_size = sizeof(divs) / sizeof(*divs); | ||
83 | int i = 0; | ||
84 | unsigned long count_hz; | ||
85 | unsigned long shift; | ||
86 | unsigned long mult; | ||
87 | int clock_div = -1; | ||
88 | u64 tmp; | ||
89 | |||
90 | shift = clocksource_avr32.shift; | ||
91 | |||
92 | do { | ||
93 | count_hz = clk_get_rate(pclk) / divs[i]; | ||
94 | mult = clocksource_hz2mult(count_hz, shift); | ||
95 | clocksource_avr32.mult = mult; | ||
96 | |||
97 | tmp = TICK_NSEC; | ||
98 | tmp <<= shift; | ||
99 | tmp += mult / 2; | ||
100 | do_div(tmp, mult); | ||
101 | |||
102 | cycles_per_jiffy = tmp; | ||
103 | } while (cycles_per_jiffy > cycles_max && ++i < divs_size); | ||
104 | |||
105 | clock_div = i + 1; | ||
106 | |||
107 | if (clock_div > divs_size) { | ||
108 | pr_debug("timer: could not calculate clock divider\n"); | ||
109 | return -EFAULT; | ||
110 | } | ||
111 | |||
112 | /* Set the clock divider */ | ||
113 | timer_write(ioregs, 0, CMR, TIMER_BF(CMR_TCCLKS, clock_div)); | ||
114 | |||
115 | return 0; | ||
116 | } | ||
117 | |||
118 | int avr32_hpt_init(unsigned int count) | ||
119 | { | ||
120 | struct resource *regs; | ||
121 | struct clk *pclk; | ||
122 | int irq = -1; | ||
123 | int ret = 0; | ||
124 | |||
125 | ret = -ENXIO; | ||
126 | |||
127 | irq = platform_get_irq(&at32_systc0_device, 0); | ||
128 | if (irq < 0) { | ||
129 | pr_debug("timer: could not get irq\n"); | ||
130 | goto out_error; | ||
131 | } | ||
132 | |||
133 | pclk = clk_get(&at32_systc0_device.dev, "pclk"); | ||
134 | if (IS_ERR(pclk)) { | ||
135 | pr_debug("timer: could not get clk: %ld\n", PTR_ERR(pclk)); | ||
136 | goto out_error; | ||
137 | } | ||
138 | clk_enable(pclk); | ||
139 | |||
140 | regs = platform_get_resource(&at32_systc0_device, IORESOURCE_MEM, 0); | ||
141 | if (!regs) { | ||
142 | pr_debug("timer: could not get resource\n"); | ||
143 | goto out_error_clk; | ||
144 | } | ||
145 | |||
146 | ioregs = ioremap(regs->start, regs->end - regs->start + 1); | ||
147 | if (!ioregs) { | ||
148 | pr_debug("timer: could not get ioregs\n"); | ||
149 | goto out_error_clk; | ||
150 | } | ||
151 | |||
152 | ret = avr32_timer_calc_div_and_set_jiffies(pclk); | ||
153 | if (ret) | ||
154 | goto out_error_io; | ||
155 | |||
156 | ret = setup_irq(irq, &timer_irqaction); | ||
157 | if (ret) { | ||
158 | pr_debug("timer: could not request irq %d: %d\n", | ||
159 | irq, ret); | ||
160 | goto out_error_io; | ||
161 | } | ||
162 | |||
163 | expirelo = (timer_read(ioregs, 0, CV) / cycles_per_jiffy + 1) | ||
164 | * cycles_per_jiffy; | ||
165 | |||
166 | /* Enable clock and interrupts on RC compare */ | ||
167 | timer_write(ioregs, 0, CCR, TIMER_BIT(CCR_CLKEN)); | ||
168 | timer_write(ioregs, 0, IER, TIMER_BIT(IER_CPCS)); | ||
169 | /* Set cycles to first interrupt */ | ||
170 | timer_write(ioregs, 0, RC, expirelo); | ||
171 | |||
172 | printk(KERN_INFO "timer: AT32AP system timer/counter at 0x%p irq %d\n", | ||
173 | ioregs, irq); | ||
174 | |||
175 | return 0; | ||
176 | |||
177 | out_error_io: | ||
178 | iounmap(ioregs); | ||
179 | out_error_clk: | ||
180 | clk_put(pclk); | ||
181 | out_error: | ||
182 | return ret; | ||
183 | } | ||
184 | |||
185 | int avr32_hpt_start(void) | ||
186 | { | ||
187 | timer_write(ioregs, 0, CCR, TIMER_BIT(CCR_SWTRG)); | ||
188 | return 0; | ||
189 | } | ||
190 | |||
191 | irqreturn_t timer_interrupt(int irq, void *dev_id) | ||
192 | { | ||
193 | unsigned int sr = timer_read(ioregs, 0, SR); | ||
194 | |||
195 | if (sr & TIMER_BIT(SR_CPCS)) { | ||
196 | /* ack timer interrupt and try to set next interrupt */ | ||
197 | avr32_timer_ack(); | ||
198 | |||
199 | /* | ||
200 | * Call the generic timer interrupt handler | ||
201 | */ | ||
202 | write_seqlock(&xtime_lock); | ||
203 | do_timer(1); | ||
204 | write_sequnlock(&xtime_lock); | ||
205 | |||
206 | /* | ||
207 | * In UP mode, we call local_timer_interrupt() to do profiling | ||
208 | * and process accounting. | ||
209 | * | ||
210 | * SMP is not supported yet. | ||
211 | */ | ||
212 | local_timer_interrupt(irq, dev_id); | ||
213 | |||
214 | return IRQ_HANDLED; | ||
215 | } | ||
216 | |||
217 | return IRQ_NONE; | ||
218 | } | ||